mirror of
https://github.com/adoyle0/thaw.git
synced 2025-01-23 06:19:22 -05:00
Feat/model (#92)
* feat: add Model * feat: RwSignal is migrated to Model
This commit is contained in:
parent
1cba68520a
commit
b2f68906df
22 changed files with 248 additions and 46 deletions
|
@ -3,7 +3,7 @@ mod theme;
|
||||||
use crate::{
|
use crate::{
|
||||||
components::{Binder, Follower, FollowerPlacement, FollowerWidth},
|
components::{Binder, Follower, FollowerPlacement, FollowerWidth},
|
||||||
use_theme,
|
use_theme,
|
||||||
utils::{class_list::class_list, mount_style, StoredMaybeSignal},
|
utils::{class_list::class_list, mount_style, Model, StoredMaybeSignal},
|
||||||
ComponentRef, Input, InputPrefix, InputRef, InputSuffix, Theme,
|
ComponentRef, Input, InputPrefix, InputRef, InputSuffix, Theme,
|
||||||
};
|
};
|
||||||
use leptos::*;
|
use leptos::*;
|
||||||
|
@ -27,7 +27,7 @@ pub struct AutoCompleteSuffix {
|
||||||
|
|
||||||
#[component]
|
#[component]
|
||||||
pub fn AutoComplete(
|
pub fn AutoComplete(
|
||||||
#[prop(optional, into)] value: RwSignal<String>,
|
#[prop(optional, into)] value: Model<String>,
|
||||||
#[prop(optional, into)] placeholder: MaybeSignal<String>,
|
#[prop(optional, into)] placeholder: MaybeSignal<String>,
|
||||||
#[prop(optional, into)] options: MaybeSignal<Vec<AutoCompleteOption>>,
|
#[prop(optional, into)] options: MaybeSignal<Vec<AutoCompleteOption>>,
|
||||||
#[prop(optional, into)] clear_after_select: MaybeSignal<bool>,
|
#[prop(optional, into)] clear_after_select: MaybeSignal<bool>,
|
||||||
|
|
|
@ -3,7 +3,7 @@ mod theme;
|
||||||
use crate::{
|
use crate::{
|
||||||
chrono::{Datelike, Days, Local, NaiveDate},
|
chrono::{Datelike, Days, Local, NaiveDate},
|
||||||
use_theme,
|
use_theme,
|
||||||
utils::{class_list::class_list, mount_style},
|
utils::{class_list::class_list, mount_style, Model},
|
||||||
Button, ButtonGroup, ButtonVariant, Theme,
|
Button, ButtonGroup, ButtonVariant, Theme,
|
||||||
};
|
};
|
||||||
use chrono::{Month, Months};
|
use chrono::{Month, Months};
|
||||||
|
@ -14,7 +14,7 @@ pub use theme::CalendarTheme;
|
||||||
#[component]
|
#[component]
|
||||||
pub fn Calendar(
|
pub fn Calendar(
|
||||||
#[prop(optional, into)] class: MaybeSignal<String>,
|
#[prop(optional, into)] class: MaybeSignal<String>,
|
||||||
#[prop(optional, into)] value: RwSignal<Option<NaiveDate>>,
|
#[prop(optional, into)] value: Model<Option<NaiveDate>>,
|
||||||
) -> impl IntoView {
|
) -> impl IntoView {
|
||||||
mount_style("calendar", include_str!("./calendar.css"));
|
mount_style("calendar", include_str!("./calendar.css"));
|
||||||
let theme = use_theme(Theme::light);
|
let theme = use_theme(Theme::light);
|
||||||
|
@ -170,7 +170,7 @@ pub fn Calendar(
|
||||||
|
|
||||||
#[component]
|
#[component]
|
||||||
fn CalendarItem(
|
fn CalendarItem(
|
||||||
value: RwSignal<Option<NaiveDate>>,
|
value: Model<Option<NaiveDate>>,
|
||||||
index: usize,
|
index: usize,
|
||||||
date: CalendarItemDate,
|
date: CalendarItemDate,
|
||||||
) -> impl IntoView {
|
) -> impl IntoView {
|
||||||
|
|
|
@ -1,16 +1,17 @@
|
||||||
|
use crate::utils::Model;
|
||||||
use leptos::*;
|
use leptos::*;
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
|
|
||||||
#[component]
|
#[component]
|
||||||
pub fn CheckboxGroup(
|
pub fn CheckboxGroup(
|
||||||
#[prop(optional, into)] value: RwSignal<HashSet<String>>,
|
#[prop(optional, into)] value: Model<HashSet<String>>,
|
||||||
children: Children,
|
children: Children,
|
||||||
) -> impl IntoView {
|
) -> impl IntoView {
|
||||||
view! { <Provider value=CheckboxGroupInjection(value) children/> }
|
view! { <Provider value=CheckboxGroupInjection(value) children/> }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub(crate) struct CheckboxGroupInjection(pub RwSignal<HashSet<String>>);
|
pub(crate) struct CheckboxGroupInjection(pub Model<HashSet<String>>);
|
||||||
|
|
||||||
pub(crate) fn use_checkbox_group() -> CheckboxGroupInjection {
|
pub(crate) fn use_checkbox_group() -> CheckboxGroupInjection {
|
||||||
expect_context()
|
expect_context()
|
||||||
|
|
|
@ -5,7 +5,7 @@ use crate::{
|
||||||
components::*,
|
components::*,
|
||||||
icon::*,
|
icon::*,
|
||||||
theme::use_theme,
|
theme::use_theme,
|
||||||
utils::{class_list::class_list, mount_style},
|
utils::{class_list::class_list, mount_style, Model},
|
||||||
Theme,
|
Theme,
|
||||||
};
|
};
|
||||||
pub use checkbox_group::CheckboxGroup;
|
pub use checkbox_group::CheckboxGroup;
|
||||||
|
@ -14,7 +14,7 @@ use leptos::*;
|
||||||
|
|
||||||
#[component]
|
#[component]
|
||||||
pub fn Checkbox(
|
pub fn Checkbox(
|
||||||
#[prop(optional, into)] value: RwSignal<bool>,
|
#[prop(optional, into)] value: Model<bool>,
|
||||||
#[prop(optional, into)] class: MaybeSignal<String>,
|
#[prop(optional, into)] class: MaybeSignal<String>,
|
||||||
children: Children,
|
children: Children,
|
||||||
) -> impl IntoView {
|
) -> impl IntoView {
|
||||||
|
@ -44,7 +44,7 @@ pub fn Checkbox(
|
||||||
>
|
>
|
||||||
<input class="thaw-checkbox__input" type="checkbox"/>
|
<input class="thaw-checkbox__input" type="checkbox"/>
|
||||||
<div class="thaw-checkbox__dot">
|
<div class="thaw-checkbox__dot">
|
||||||
<If cond=value>
|
<If cond=value.signal()>
|
||||||
<Then slot>
|
<Then slot>
|
||||||
<Icon icon=icondata::AiCheckOutlined style="color: white"/>
|
<Icon icon=icondata::AiCheckOutlined style="color: white"/>
|
||||||
</Then>
|
</Then>
|
||||||
|
|
|
@ -6,7 +6,7 @@ pub use theme::CollapseTheme;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
use_theme,
|
use_theme,
|
||||||
utils::{class_list::class_list, mount_style},
|
utils::{class_list::class_list, mount_style, Model},
|
||||||
Theme,
|
Theme,
|
||||||
};
|
};
|
||||||
use leptos::*;
|
use leptos::*;
|
||||||
|
@ -15,7 +15,7 @@ use std::collections::HashSet;
|
||||||
#[component]
|
#[component]
|
||||||
pub fn Collapse(
|
pub fn Collapse(
|
||||||
#[prop(optional, into)] class: MaybeSignal<String>,
|
#[prop(optional, into)] class: MaybeSignal<String>,
|
||||||
#[prop(optional, into)] value: RwSignal<HashSet<String>>,
|
#[prop(optional, into)] value: Model<HashSet<String>>,
|
||||||
#[prop(optional)] accordion: bool,
|
#[prop(optional)] accordion: bool,
|
||||||
children: Children,
|
children: Children,
|
||||||
) -> impl IntoView {
|
) -> impl IntoView {
|
||||||
|
@ -42,7 +42,7 @@ pub fn Collapse(
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub(crate) struct CollapseInjection {
|
pub(crate) struct CollapseInjection {
|
||||||
pub value: RwSignal<HashSet<String>>,
|
pub value: Model<HashSet<String>>,
|
||||||
pub accordion: bool,
|
pub accordion: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@ mod theme;
|
||||||
use crate::{
|
use crate::{
|
||||||
components::{Binder, Follower, FollowerPlacement},
|
components::{Binder, Follower, FollowerPlacement},
|
||||||
use_theme,
|
use_theme,
|
||||||
utils::{class_list::class_list, mount_style},
|
utils::{class_list::class_list, mount_style, Model},
|
||||||
Theme,
|
Theme,
|
||||||
};
|
};
|
||||||
pub use color::*;
|
pub use color::*;
|
||||||
|
@ -14,7 +14,7 @@ pub use theme::ColorPickerTheme;
|
||||||
|
|
||||||
#[component]
|
#[component]
|
||||||
pub fn ColorPicker(
|
pub fn ColorPicker(
|
||||||
#[prop(optional, into)] value: RwSignal<RGBA>,
|
#[prop(optional, into)] value: Model<RGBA>,
|
||||||
#[prop(optional, into)] class: MaybeSignal<String>,
|
#[prop(optional, into)] class: MaybeSignal<String>,
|
||||||
) -> impl IntoView {
|
) -> impl IntoView {
|
||||||
mount_style("color-picker", include_str!("./color-picker.css"));
|
mount_style("color-picker", include_str!("./color-picker.css"));
|
||||||
|
|
|
@ -4,7 +4,7 @@ mod theme;
|
||||||
use crate::{
|
use crate::{
|
||||||
chrono::NaiveDate,
|
chrono::NaiveDate,
|
||||||
components::{Binder, Follower, FollowerPlacement},
|
components::{Binder, Follower, FollowerPlacement},
|
||||||
utils::{mount_style, now_date, ComponentRef},
|
utils::{mount_style, now_date, ComponentRef, Model},
|
||||||
Icon, Input, InputSuffix, SignalWatch,
|
Icon, Input, InputSuffix, SignalWatch,
|
||||||
};
|
};
|
||||||
use leptos::*;
|
use leptos::*;
|
||||||
|
@ -13,7 +13,7 @@ pub use theme::DatePickerTheme;
|
||||||
|
|
||||||
#[component]
|
#[component]
|
||||||
pub fn DatePicker(
|
pub fn DatePicker(
|
||||||
#[prop(optional, into)] value: RwSignal<Option<NaiveDate>>,
|
#[prop(optional, into)] value: Model<Option<NaiveDate>>,
|
||||||
#[prop(optional, into)] class: MaybeSignal<String>,
|
#[prop(optional, into)] class: MaybeSignal<String>,
|
||||||
#[prop(attrs)] attrs: Vec<(&'static str, Attribute)>,
|
#[prop(attrs)] attrs: Vec<(&'static str, Attribute)>,
|
||||||
) -> impl IntoView {
|
) -> impl IntoView {
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
components::Teleport,
|
components::Teleport,
|
||||||
utils::{class_list::class_list, mount_style},
|
utils::{class_list::class_list, mount_style, Model},
|
||||||
Card,
|
Card,
|
||||||
};
|
};
|
||||||
use leptos::*;
|
use leptos::*;
|
||||||
|
|
||||||
#[component]
|
#[component]
|
||||||
pub fn Drawer(
|
pub fn Drawer(
|
||||||
#[prop(into)] show: RwSignal<bool>,
|
#[prop(into)] show: Model<bool>,
|
||||||
#[prop(optional, into)] title: MaybeSignal<String>,
|
#[prop(optional, into)] title: MaybeSignal<String>,
|
||||||
#[prop(optional, into)] placement: MaybeSignal<DrawerPlacement>,
|
#[prop(optional, into)] placement: MaybeSignal<DrawerPlacement>,
|
||||||
#[prop(default = MaybeSignal::Static("520px".to_string()), into)] width: MaybeSignal<String>,
|
#[prop(default = MaybeSignal::Static("520px".to_string()), into)] width: MaybeSignal<String>,
|
||||||
|
|
|
@ -6,7 +6,7 @@ pub use theme::InputTheme;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
theme::{use_theme, Theme},
|
theme::{use_theme, Theme},
|
||||||
utils::{class_list::class_list, mount_style, ComponentRef},
|
utils::{class_list::class_list, mount_style, ComponentRef, Model},
|
||||||
};
|
};
|
||||||
use leptos::*;
|
use leptos::*;
|
||||||
|
|
||||||
|
@ -42,7 +42,7 @@ pub struct InputSuffix {
|
||||||
|
|
||||||
#[component]
|
#[component]
|
||||||
pub fn Input(
|
pub fn Input(
|
||||||
#[prop(optional, into)] value: RwSignal<String>,
|
#[prop(optional, into)] value: Model<String>,
|
||||||
#[prop(optional, into)] allow_value: Option<Callback<String, bool>>,
|
#[prop(optional, into)] allow_value: Option<Callback<String, bool>>,
|
||||||
#[prop(optional, into)] variant: MaybeSignal<InputVariant>,
|
#[prop(optional, into)] variant: MaybeSignal<InputVariant>,
|
||||||
#[prop(optional, into)] placeholder: MaybeSignal<String>,
|
#[prop(optional, into)] placeholder: MaybeSignal<String>,
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
theme::{use_theme, Theme},
|
theme::{use_theme, Theme},
|
||||||
utils::{class_list::class_list, mount_style, ComponentRef},
|
utils::{class_list::class_list, mount_style, ComponentRef, Model},
|
||||||
};
|
};
|
||||||
use leptos::*;
|
use leptos::*;
|
||||||
|
|
||||||
#[component]
|
#[component]
|
||||||
pub fn TextArea(
|
pub fn TextArea(
|
||||||
#[prop(optional, into)] value: RwSignal<String>,
|
#[prop(optional, into)] value: Model<String>,
|
||||||
#[prop(optional, into)] allow_value: Option<Callback<String, bool>>,
|
#[prop(optional, into)] allow_value: Option<Callback<String, bool>>,
|
||||||
#[prop(optional, into)] placeholder: MaybeSignal<String>,
|
#[prop(optional, into)] placeholder: MaybeSignal<String>,
|
||||||
#[prop(optional, into)] on_focus: Option<Callback<ev::FocusEvent>>,
|
#[prop(optional, into)] on_focus: Option<Callback<ev::FocusEvent>>,
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::utils::StoredMaybeSignal;
|
use crate::utils::{Model, StoredMaybeSignal};
|
||||||
use crate::{Button, ButtonVariant, ComponentRef, Icon, Input, InputRef, InputSuffix};
|
use crate::{Button, ButtonVariant, ComponentRef, Icon, Input, InputRef, InputSuffix};
|
||||||
use leptos::*;
|
use leptos::*;
|
||||||
use std::ops::{Add, Sub};
|
use std::ops::{Add, Sub};
|
||||||
|
@ -6,7 +6,7 @@ use std::str::FromStr;
|
||||||
|
|
||||||
#[component]
|
#[component]
|
||||||
pub fn InputNumber<T>(
|
pub fn InputNumber<T>(
|
||||||
#[prop(optional, into)] value: RwSignal<T>,
|
#[prop(optional, into)] value: Model<T>,
|
||||||
#[prop(optional, into)] placeholder: MaybeSignal<String>,
|
#[prop(optional, into)] placeholder: MaybeSignal<String>,
|
||||||
#[prop(into)] step: MaybeSignal<T>,
|
#[prop(into)] step: MaybeSignal<T>,
|
||||||
#[prop(optional, into)] disabled: MaybeSignal<bool>,
|
#[prop(optional, into)] disabled: MaybeSignal<bool>,
|
||||||
|
|
|
@ -2,7 +2,7 @@ mod menu_group;
|
||||||
mod menu_item;
|
mod menu_item;
|
||||||
mod theme;
|
mod theme;
|
||||||
|
|
||||||
use crate::utils::class_list::class_list;
|
use crate::utils::{class_list::class_list, Model};
|
||||||
use leptos::*;
|
use leptos::*;
|
||||||
pub use menu_group::MenuGroup;
|
pub use menu_group::MenuGroup;
|
||||||
pub use menu_item::*;
|
pub use menu_item::*;
|
||||||
|
@ -10,7 +10,7 @@ pub use theme::MenuTheme;
|
||||||
|
|
||||||
#[component]
|
#[component]
|
||||||
pub fn Menu(
|
pub fn Menu(
|
||||||
#[prop(optional, into)] value: RwSignal<String>,
|
#[prop(optional, into)] value: Model<String>,
|
||||||
#[prop(optional, into)] class: MaybeSignal<String>,
|
#[prop(optional, into)] class: MaybeSignal<String>,
|
||||||
children: Children,
|
children: Children,
|
||||||
) -> impl IntoView {
|
) -> impl IntoView {
|
||||||
|
@ -22,7 +22,7 @@ pub fn Menu(
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub(crate) struct MenuInjection(pub RwSignal<String>);
|
pub(crate) struct MenuInjection(pub Model<String>);
|
||||||
|
|
||||||
pub(crate) fn use_menu() -> MenuInjection {
|
pub(crate) fn use_menu() -> MenuInjection {
|
||||||
expect_context()
|
expect_context()
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
mod tabbar_item;
|
mod tabbar_item;
|
||||||
mod theme;
|
mod theme;
|
||||||
|
|
||||||
use crate::{use_theme, utils::mount_style, Theme};
|
use crate::{use_theme, utils::{mount_style, Model}, Theme};
|
||||||
use leptos::*;
|
use leptos::*;
|
||||||
pub use tabbar_item::*;
|
pub use tabbar_item::*;
|
||||||
pub use theme::TabbarTheme;
|
pub use theme::TabbarTheme;
|
||||||
|
|
||||||
#[component]
|
#[component]
|
||||||
pub fn Tabbar(
|
pub fn Tabbar(
|
||||||
#[prop(optional, into)] value: RwSignal<String>,
|
#[prop(optional, into)] value: Model<String>,
|
||||||
children: Children,
|
children: Children,
|
||||||
) -> impl IntoView {
|
) -> impl IntoView {
|
||||||
mount_style("tabbar", include_str!("./tabbar.css"));
|
mount_style("tabbar", include_str!("./tabbar.css"));
|
||||||
|
@ -32,7 +32,7 @@ pub fn Tabbar(
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub(crate) struct TabbarInjection(pub RwSignal<String>);
|
pub(crate) struct TabbarInjection(pub Model<String>);
|
||||||
|
|
||||||
pub(crate) fn use_tabbar() -> TabbarInjection {
|
pub(crate) fn use_tabbar() -> TabbarInjection {
|
||||||
expect_context()
|
expect_context()
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
use crate::icon::*;
|
use crate::icon::*;
|
||||||
|
use crate::utils::Model;
|
||||||
use crate::{
|
use crate::{
|
||||||
components::{OptionComp, Teleport},
|
components::{OptionComp, Teleport},
|
||||||
utils::{mount_style, StoredMaybeSignal},
|
utils::{mount_style, StoredMaybeSignal},
|
||||||
|
@ -13,7 +14,7 @@ pub struct ModalFooter {
|
||||||
|
|
||||||
#[component]
|
#[component]
|
||||||
pub fn Modal(
|
pub fn Modal(
|
||||||
#[prop(into)] show: RwSignal<bool>,
|
#[prop(into)] show: Model<bool>,
|
||||||
#[prop(optional, into)] title: MaybeSignal<String>,
|
#[prop(optional, into)] title: MaybeSignal<String>,
|
||||||
children: Children,
|
children: Children,
|
||||||
#[prop(optional)] modal_footer: Option<ModalFooter>,
|
#[prop(optional)] modal_footer: Option<ModalFooter>,
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
theme::use_theme,
|
theme::use_theme,
|
||||||
utils::{class_list::class_list, mount_style},
|
utils::{class_list::class_list, mount_style, Model},
|
||||||
Theme,
|
Theme,
|
||||||
};
|
};
|
||||||
use leptos::*;
|
use leptos::*;
|
||||||
|
|
||||||
#[component]
|
#[component]
|
||||||
pub fn Radio(
|
pub fn Radio(
|
||||||
#[prop(optional, into)] value: RwSignal<bool>,
|
#[prop(optional, into)] value: Model<bool>,
|
||||||
#[prop(optional, into)] class: MaybeSignal<String>,
|
#[prop(optional, into)] class: MaybeSignal<String>,
|
||||||
children: Children,
|
children: Children,
|
||||||
) -> impl IntoView {
|
) -> impl IntoView {
|
||||||
|
|
|
@ -3,7 +3,7 @@ mod theme;
|
||||||
use crate::{
|
use crate::{
|
||||||
components::{Binder, Follower, FollowerPlacement, FollowerWidth},
|
components::{Binder, Follower, FollowerPlacement, FollowerWidth},
|
||||||
theme::use_theme,
|
theme::use_theme,
|
||||||
utils::{class_list::class_list, mount_style},
|
utils::{class_list::class_list, mount_style, Model},
|
||||||
Theme,
|
Theme,
|
||||||
};
|
};
|
||||||
use leptos::*;
|
use leptos::*;
|
||||||
|
@ -18,7 +18,7 @@ pub struct SelectOption<T> {
|
||||||
|
|
||||||
#[component]
|
#[component]
|
||||||
pub fn Select<T>(
|
pub fn Select<T>(
|
||||||
#[prop(optional, into)] value: RwSignal<Option<T>>,
|
#[prop(optional, into)] value: Model<Option<T>>,
|
||||||
#[prop(optional, into)] options: MaybeSignal<Vec<SelectOption<T>>>,
|
#[prop(optional, into)] options: MaybeSignal<Vec<SelectOption<T>>>,
|
||||||
#[prop(optional, into)] class: MaybeSignal<String>,
|
#[prop(optional, into)] class: MaybeSignal<String>,
|
||||||
) -> impl IntoView
|
) -> impl IntoView
|
||||||
|
|
|
@ -4,7 +4,7 @@ mod theme;
|
||||||
use crate::{
|
use crate::{
|
||||||
components::OptionComp,
|
components::OptionComp,
|
||||||
theme::use_theme,
|
theme::use_theme,
|
||||||
utils::{class_list::class_list, mount_style},
|
utils::{class_list::class_list, mount_style, Model},
|
||||||
Theme,
|
Theme,
|
||||||
};
|
};
|
||||||
use leptos::*;
|
use leptos::*;
|
||||||
|
@ -15,7 +15,7 @@ pub use theme::SliderTheme;
|
||||||
|
|
||||||
#[component]
|
#[component]
|
||||||
pub fn Slider(
|
pub fn Slider(
|
||||||
#[prop(optional, into)] value: RwSignal<f64>,
|
#[prop(optional, into)] value: Model<f64>,
|
||||||
#[prop(default = MaybeSignal::Static(100f64), into)] max: MaybeSignal<f64>,
|
#[prop(default = MaybeSignal::Static(100f64), into)] max: MaybeSignal<f64>,
|
||||||
#[prop(optional, into)] step: MaybeSignal<f64>,
|
#[prop(optional, into)] step: MaybeSignal<f64>,
|
||||||
#[prop(optional, into)] class: MaybeSignal<String>,
|
#[prop(optional, into)] class: MaybeSignal<String>,
|
||||||
|
|
|
@ -2,7 +2,7 @@ mod theme;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
theme::use_theme,
|
theme::use_theme,
|
||||||
utils::{class_list::class_list, mount_style},
|
utils::{class_list::class_list, mount_style, Model},
|
||||||
Theme,
|
Theme,
|
||||||
};
|
};
|
||||||
use leptos::*;
|
use leptos::*;
|
||||||
|
@ -10,7 +10,7 @@ pub use theme::SwitchTheme;
|
||||||
|
|
||||||
#[component]
|
#[component]
|
||||||
pub fn Switch(
|
pub fn Switch(
|
||||||
#[prop(optional, into)] value: RwSignal<bool>,
|
#[prop(optional, into)] value: Model<bool>,
|
||||||
#[prop(optional, into)] class: MaybeSignal<String>,
|
#[prop(optional, into)] class: MaybeSignal<String>,
|
||||||
) -> impl IntoView {
|
) -> impl IntoView {
|
||||||
mount_style("switch", include_str!("./switch.css"));
|
mount_style("switch", include_str!("./switch.css"));
|
||||||
|
|
|
@ -2,7 +2,7 @@ mod tab;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
theme::use_theme,
|
theme::use_theme,
|
||||||
utils::{class_list::class_list, mount_style},
|
utils::{class_list::class_list, mount_style, Model},
|
||||||
Theme,
|
Theme,
|
||||||
};
|
};
|
||||||
use leptos::*;
|
use leptos::*;
|
||||||
|
@ -11,7 +11,7 @@ pub use tab::*;
|
||||||
|
|
||||||
#[component]
|
#[component]
|
||||||
pub fn Tabs(
|
pub fn Tabs(
|
||||||
#[prop(optional, into)] value: RwSignal<String>,
|
#[prop(optional, into)] value: Model<String>,
|
||||||
#[prop(optional, into)] class: MaybeSignal<String>,
|
#[prop(optional, into)] class: MaybeSignal<String>,
|
||||||
children: Children,
|
children: Children,
|
||||||
) -> impl IntoView {
|
) -> impl IntoView {
|
||||||
|
@ -30,7 +30,7 @@ pub fn Tabs(
|
||||||
|
|
||||||
#[component]
|
#[component]
|
||||||
fn TabsInner(
|
fn TabsInner(
|
||||||
value: RwSignal<String>,
|
value: Model<String>,
|
||||||
tab_options_vec: RwSignal<Vec<TabOption>>,
|
tab_options_vec: RwSignal<Vec<TabOption>>,
|
||||||
#[prop(optional, into)] class: MaybeSignal<String>,
|
#[prop(optional, into)] class: MaybeSignal<String>,
|
||||||
children: Children,
|
children: Children,
|
||||||
|
@ -161,7 +161,7 @@ pub(crate) struct TabsLabelLine {
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub(crate) struct TabsInjection {
|
pub(crate) struct TabsInjection {
|
||||||
active_key: RwSignal<String>,
|
active_key: Model<String>,
|
||||||
tab_options_vec: RwSignal<Vec<TabOption>>,
|
tab_options_vec: RwSignal<Vec<TabOption>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@ use crate::{
|
||||||
chrono::{Local, NaiveTime, Timelike},
|
chrono::{Local, NaiveTime, Timelike},
|
||||||
components::{Binder, Follower, FollowerPlacement},
|
components::{Binder, Follower, FollowerPlacement},
|
||||||
use_theme,
|
use_theme,
|
||||||
utils::{mount_style, ComponentRef},
|
utils::{mount_style, ComponentRef, Model},
|
||||||
Button, ButtonSize, ButtonVariant, Icon, Input, InputSuffix, SignalWatch, Theme,
|
Button, ButtonSize, ButtonVariant, Icon, Input, InputSuffix, SignalWatch, Theme,
|
||||||
};
|
};
|
||||||
use leptos::*;
|
use leptos::*;
|
||||||
|
@ -12,7 +12,7 @@ pub use theme::TimePickerTheme;
|
||||||
|
|
||||||
#[component]
|
#[component]
|
||||||
pub fn TimePicker(
|
pub fn TimePicker(
|
||||||
#[prop(optional, into)] value: RwSignal<Option<NaiveTime>>,
|
#[prop(optional, into)] value: Model<Option<NaiveTime>>,
|
||||||
#[prop(optional, into)] class: MaybeSignal<String>,
|
#[prop(optional, into)] class: MaybeSignal<String>,
|
||||||
#[prop(attrs)] attrs: Vec<(&'static str, Attribute)>,
|
#[prop(attrs)] attrs: Vec<(&'static str, Attribute)>,
|
||||||
) -> impl IntoView {
|
) -> impl IntoView {
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
pub(crate) mod class_list;
|
pub(crate) mod class_list;
|
||||||
mod component_ref;
|
mod component_ref;
|
||||||
mod event_listener;
|
mod event_listener;
|
||||||
|
mod model;
|
||||||
mod mount_style;
|
mod mount_style;
|
||||||
mod signal;
|
mod signal;
|
||||||
mod stored_maybe_signal;
|
mod stored_maybe_signal;
|
||||||
|
@ -10,6 +11,7 @@ mod time;
|
||||||
// pub use callback::AsyncCallback;
|
// pub use callback::AsyncCallback;
|
||||||
pub use component_ref::{create_component_ref, ComponentRef};
|
pub use component_ref::{create_component_ref, ComponentRef};
|
||||||
pub(crate) use event_listener::*;
|
pub(crate) use event_listener::*;
|
||||||
|
pub(crate) use model::Model;
|
||||||
pub(crate) use mount_style::mount_style;
|
pub(crate) use mount_style::mount_style;
|
||||||
pub use signal::SignalWatch;
|
pub use signal::SignalWatch;
|
||||||
pub(crate) use stored_maybe_signal::*;
|
pub(crate) use stored_maybe_signal::*;
|
||||||
|
|
198
thaw/src/utils/model.rs
Normal file
198
thaw/src/utils/model.rs
Normal file
|
@ -0,0 +1,198 @@
|
||||||
|
use leptos::{
|
||||||
|
Memo, ReadSignal, RwSignal, Signal, SignalGet, SignalGetUntracked, SignalSet, SignalUpdate,
|
||||||
|
SignalWith, SignalWithUntracked, WriteSignal,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct Model<T>
|
||||||
|
where
|
||||||
|
T: 'static,
|
||||||
|
{
|
||||||
|
read: Signal<T>,
|
||||||
|
write: WriteSignal<T>,
|
||||||
|
on_write: Option<WriteSignal<T>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Default> Default for Model<T> {
|
||||||
|
fn default() -> Self {
|
||||||
|
RwSignal::new(Default::default()).into()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Clone for Model<T> {
|
||||||
|
fn clone(&self) -> Self {
|
||||||
|
Self {
|
||||||
|
read: self.read.clone(),
|
||||||
|
write: self.write.clone(),
|
||||||
|
on_write: self.on_write.clone(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Copy for Model<T> {}
|
||||||
|
|
||||||
|
impl<T> Model<T> {
|
||||||
|
fn new(value: T) -> Self {
|
||||||
|
let rw_signal = RwSignal::new(value);
|
||||||
|
rw_signal.into()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn signal(&self) -> Signal<T> {
|
||||||
|
self.read.clone()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Clone> SignalGet for Model<T> {
|
||||||
|
type Value = T;
|
||||||
|
|
||||||
|
fn get(&self) -> Self::Value {
|
||||||
|
self.read.get()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn try_get(&self) -> Option<Self::Value> {
|
||||||
|
self.read.try_get()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Clone> SignalGetUntracked for Model<T> {
|
||||||
|
type Value = T;
|
||||||
|
|
||||||
|
fn get_untracked(&self) -> Self::Value {
|
||||||
|
self.read.get_untracked()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn try_get_untracked(&self) -> Option<Self::Value> {
|
||||||
|
self.read.try_get_untracked()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Clone> SignalSet for Model<T> {
|
||||||
|
type Value = T;
|
||||||
|
|
||||||
|
fn set(&self, new_value: Self::Value) {
|
||||||
|
if let Some(on_write) = self.on_write.as_ref() {
|
||||||
|
on_write.set(new_value.clone());
|
||||||
|
}
|
||||||
|
self.write.set(new_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn try_set(&self, new_value: Self::Value) -> Option<Self::Value> {
|
||||||
|
if let Some(on_write) = self.on_write.as_ref() {
|
||||||
|
on_write.try_set(new_value.clone());
|
||||||
|
}
|
||||||
|
self.write.try_set(new_value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> SignalWith for Model<T> {
|
||||||
|
type Value = T;
|
||||||
|
|
||||||
|
fn with<O>(&self, f: impl FnOnce(&Self::Value) -> O) -> O {
|
||||||
|
self.read.with(f)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn try_with<O>(&self, f: impl FnOnce(&Self::Value) -> O) -> Option<O> {
|
||||||
|
self.read.try_with(f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> SignalWithUntracked for Model<T> {
|
||||||
|
type Value = T;
|
||||||
|
|
||||||
|
fn with_untracked<O>(&self, f: impl FnOnce(&Self::Value) -> O) -> O {
|
||||||
|
self.read.with_untracked(f)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn try_with_untracked<O>(&self, f: impl FnOnce(&Self::Value) -> O) -> Option<O> {
|
||||||
|
self.read.try_with_untracked(f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> SignalUpdate for Model<T> {
|
||||||
|
type Value = T;
|
||||||
|
|
||||||
|
fn update(&self, f: impl FnOnce(&mut Self::Value)) {
|
||||||
|
self.write.update(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn try_update<O>(&self, f: impl FnOnce(&mut Self::Value) -> O) -> Option<O> {
|
||||||
|
self.write.try_update(f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> From<T> for Model<T> {
|
||||||
|
fn from(value: T) -> Self {
|
||||||
|
Self::new(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> From<RwSignal<T>> for Model<T> {
|
||||||
|
fn from(rw_signal: RwSignal<T>) -> Self {
|
||||||
|
let (read, write) = rw_signal.split();
|
||||||
|
Self {
|
||||||
|
read: read.into(),
|
||||||
|
write,
|
||||||
|
on_write: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> From<(ReadSignal<T>, WriteSignal<T>)> for Model<T> {
|
||||||
|
fn from((read, write): (ReadSignal<T>, WriteSignal<T>)) -> Self {
|
||||||
|
Self {
|
||||||
|
read: read.into(),
|
||||||
|
write,
|
||||||
|
on_write: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> From<(Memo<T>, WriteSignal<T>)> for Model<T> {
|
||||||
|
fn from((read, write): (Memo<T>, WriteSignal<T>)) -> Self {
|
||||||
|
Self {
|
||||||
|
read: read.into(),
|
||||||
|
write,
|
||||||
|
on_write: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Default> From<(Option<T>, WriteSignal<T>)> for Model<T> {
|
||||||
|
fn from((read, write): (Option<T>, WriteSignal<T>)) -> Self {
|
||||||
|
let mut modal = Self::new(read.unwrap_or_default());
|
||||||
|
modal.on_write = Some(write.into());
|
||||||
|
modal
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use super::Model;
|
||||||
|
use leptos::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn from() {
|
||||||
|
let runtime = create_runtime();
|
||||||
|
|
||||||
|
// T
|
||||||
|
let modal: Model<i32> = 0.into();
|
||||||
|
assert_eq!(modal.get_untracked(), 0);
|
||||||
|
modal.set(1);
|
||||||
|
assert_eq!(modal.get_untracked(), 1);
|
||||||
|
|
||||||
|
// RwSignal
|
||||||
|
let rw_signal = RwSignal::new(0);
|
||||||
|
let modal: Model<i32> = rw_signal.into();
|
||||||
|
assert_eq!(modal.get_untracked(), 0);
|
||||||
|
modal.set(1);
|
||||||
|
assert_eq!(modal.get_untracked(), 1);
|
||||||
|
|
||||||
|
// Read Write
|
||||||
|
let (read, write) = create_signal(0);
|
||||||
|
let modal: Model<i32> = (read, write).into();
|
||||||
|
assert_eq!(modal.get_untracked(), 0);
|
||||||
|
modal.set(1);
|
||||||
|
assert_eq!(modal.get_untracked(), 1);
|
||||||
|
|
||||||
|
runtime.dispose();
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue