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::{
|
||||
components::{Binder, Follower, FollowerPlacement, FollowerWidth},
|
||||
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,
|
||||
};
|
||||
use leptos::*;
|
||||
|
@ -27,7 +27,7 @@ pub struct AutoCompleteSuffix {
|
|||
|
||||
#[component]
|
||||
pub fn AutoComplete(
|
||||
#[prop(optional, into)] value: RwSignal<String>,
|
||||
#[prop(optional, into)] value: Model<String>,
|
||||
#[prop(optional, into)] placeholder: MaybeSignal<String>,
|
||||
#[prop(optional, into)] options: MaybeSignal<Vec<AutoCompleteOption>>,
|
||||
#[prop(optional, into)] clear_after_select: MaybeSignal<bool>,
|
||||
|
|
|
@ -3,7 +3,7 @@ mod theme;
|
|||
use crate::{
|
||||
chrono::{Datelike, Days, Local, NaiveDate},
|
||||
use_theme,
|
||||
utils::{class_list::class_list, mount_style},
|
||||
utils::{class_list::class_list, mount_style, Model},
|
||||
Button, ButtonGroup, ButtonVariant, Theme,
|
||||
};
|
||||
use chrono::{Month, Months};
|
||||
|
@ -14,7 +14,7 @@ pub use theme::CalendarTheme;
|
|||
#[component]
|
||||
pub fn Calendar(
|
||||
#[prop(optional, into)] class: MaybeSignal<String>,
|
||||
#[prop(optional, into)] value: RwSignal<Option<NaiveDate>>,
|
||||
#[prop(optional, into)] value: Model<Option<NaiveDate>>,
|
||||
) -> impl IntoView {
|
||||
mount_style("calendar", include_str!("./calendar.css"));
|
||||
let theme = use_theme(Theme::light);
|
||||
|
@ -170,7 +170,7 @@ pub fn Calendar(
|
|||
|
||||
#[component]
|
||||
fn CalendarItem(
|
||||
value: RwSignal<Option<NaiveDate>>,
|
||||
value: Model<Option<NaiveDate>>,
|
||||
index: usize,
|
||||
date: CalendarItemDate,
|
||||
) -> impl IntoView {
|
||||
|
|
|
@ -1,16 +1,17 @@
|
|||
use crate::utils::Model;
|
||||
use leptos::*;
|
||||
use std::collections::HashSet;
|
||||
|
||||
#[component]
|
||||
pub fn CheckboxGroup(
|
||||
#[prop(optional, into)] value: RwSignal<HashSet<String>>,
|
||||
#[prop(optional, into)] value: Model<HashSet<String>>,
|
||||
children: Children,
|
||||
) -> impl IntoView {
|
||||
view! { <Provider value=CheckboxGroupInjection(value) children/> }
|
||||
}
|
||||
|
||||
#[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 {
|
||||
expect_context()
|
||||
|
|
|
@ -5,7 +5,7 @@ use crate::{
|
|||
components::*,
|
||||
icon::*,
|
||||
theme::use_theme,
|
||||
utils::{class_list::class_list, mount_style},
|
||||
utils::{class_list::class_list, mount_style, Model},
|
||||
Theme,
|
||||
};
|
||||
pub use checkbox_group::CheckboxGroup;
|
||||
|
@ -14,7 +14,7 @@ use leptos::*;
|
|||
|
||||
#[component]
|
||||
pub fn Checkbox(
|
||||
#[prop(optional, into)] value: RwSignal<bool>,
|
||||
#[prop(optional, into)] value: Model<bool>,
|
||||
#[prop(optional, into)] class: MaybeSignal<String>,
|
||||
children: Children,
|
||||
) -> impl IntoView {
|
||||
|
@ -44,7 +44,7 @@ pub fn Checkbox(
|
|||
>
|
||||
<input class="thaw-checkbox__input" type="checkbox"/>
|
||||
<div class="thaw-checkbox__dot">
|
||||
<If cond=value>
|
||||
<If cond=value.signal()>
|
||||
<Then slot>
|
||||
<Icon icon=icondata::AiCheckOutlined style="color: white"/>
|
||||
</Then>
|
||||
|
|
|
@ -6,7 +6,7 @@ pub use theme::CollapseTheme;
|
|||
|
||||
use crate::{
|
||||
use_theme,
|
||||
utils::{class_list::class_list, mount_style},
|
||||
utils::{class_list::class_list, mount_style, Model},
|
||||
Theme,
|
||||
};
|
||||
use leptos::*;
|
||||
|
@ -15,7 +15,7 @@ use std::collections::HashSet;
|
|||
#[component]
|
||||
pub fn Collapse(
|
||||
#[prop(optional, into)] class: MaybeSignal<String>,
|
||||
#[prop(optional, into)] value: RwSignal<HashSet<String>>,
|
||||
#[prop(optional, into)] value: Model<HashSet<String>>,
|
||||
#[prop(optional)] accordion: bool,
|
||||
children: Children,
|
||||
) -> impl IntoView {
|
||||
|
@ -42,7 +42,7 @@ pub fn Collapse(
|
|||
|
||||
#[derive(Clone)]
|
||||
pub(crate) struct CollapseInjection {
|
||||
pub value: RwSignal<HashSet<String>>,
|
||||
pub value: Model<HashSet<String>>,
|
||||
pub accordion: bool,
|
||||
}
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ mod theme;
|
|||
use crate::{
|
||||
components::{Binder, Follower, FollowerPlacement},
|
||||
use_theme,
|
||||
utils::{class_list::class_list, mount_style},
|
||||
utils::{class_list::class_list, mount_style, Model},
|
||||
Theme,
|
||||
};
|
||||
pub use color::*;
|
||||
|
@ -14,7 +14,7 @@ pub use theme::ColorPickerTheme;
|
|||
|
||||
#[component]
|
||||
pub fn ColorPicker(
|
||||
#[prop(optional, into)] value: RwSignal<RGBA>,
|
||||
#[prop(optional, into)] value: Model<RGBA>,
|
||||
#[prop(optional, into)] class: MaybeSignal<String>,
|
||||
) -> impl IntoView {
|
||||
mount_style("color-picker", include_str!("./color-picker.css"));
|
||||
|
|
|
@ -4,7 +4,7 @@ mod theme;
|
|||
use crate::{
|
||||
chrono::NaiveDate,
|
||||
components::{Binder, Follower, FollowerPlacement},
|
||||
utils::{mount_style, now_date, ComponentRef},
|
||||
utils::{mount_style, now_date, ComponentRef, Model},
|
||||
Icon, Input, InputSuffix, SignalWatch,
|
||||
};
|
||||
use leptos::*;
|
||||
|
@ -13,7 +13,7 @@ pub use theme::DatePickerTheme;
|
|||
|
||||
#[component]
|
||||
pub fn DatePicker(
|
||||
#[prop(optional, into)] value: RwSignal<Option<NaiveDate>>,
|
||||
#[prop(optional, into)] value: Model<Option<NaiveDate>>,
|
||||
#[prop(optional, into)] class: MaybeSignal<String>,
|
||||
#[prop(attrs)] attrs: Vec<(&'static str, Attribute)>,
|
||||
) -> impl IntoView {
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
use crate::{
|
||||
components::Teleport,
|
||||
utils::{class_list::class_list, mount_style},
|
||||
utils::{class_list::class_list, mount_style, Model},
|
||||
Card,
|
||||
};
|
||||
use leptos::*;
|
||||
|
||||
#[component]
|
||||
pub fn Drawer(
|
||||
#[prop(into)] show: RwSignal<bool>,
|
||||
#[prop(into)] show: Model<bool>,
|
||||
#[prop(optional, into)] title: MaybeSignal<String>,
|
||||
#[prop(optional, into)] placement: MaybeSignal<DrawerPlacement>,
|
||||
#[prop(default = MaybeSignal::Static("520px".to_string()), into)] width: MaybeSignal<String>,
|
||||
|
|
|
@ -6,7 +6,7 @@ pub use theme::InputTheme;
|
|||
|
||||
use crate::{
|
||||
theme::{use_theme, Theme},
|
||||
utils::{class_list::class_list, mount_style, ComponentRef},
|
||||
utils::{class_list::class_list, mount_style, ComponentRef, Model},
|
||||
};
|
||||
use leptos::*;
|
||||
|
||||
|
@ -42,7 +42,7 @@ pub struct InputSuffix {
|
|||
|
||||
#[component]
|
||||
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)] variant: MaybeSignal<InputVariant>,
|
||||
#[prop(optional, into)] placeholder: MaybeSignal<String>,
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
use crate::{
|
||||
theme::{use_theme, Theme},
|
||||
utils::{class_list::class_list, mount_style, ComponentRef},
|
||||
utils::{class_list::class_list, mount_style, ComponentRef, Model},
|
||||
};
|
||||
use leptos::*;
|
||||
|
||||
#[component]
|
||||
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)] placeholder: MaybeSignal<String>,
|
||||
#[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 leptos::*;
|
||||
use std::ops::{Add, Sub};
|
||||
|
@ -6,7 +6,7 @@ use std::str::FromStr;
|
|||
|
||||
#[component]
|
||||
pub fn InputNumber<T>(
|
||||
#[prop(optional, into)] value: RwSignal<T>,
|
||||
#[prop(optional, into)] value: Model<T>,
|
||||
#[prop(optional, into)] placeholder: MaybeSignal<String>,
|
||||
#[prop(into)] step: MaybeSignal<T>,
|
||||
#[prop(optional, into)] disabled: MaybeSignal<bool>,
|
||||
|
|
|
@ -2,7 +2,7 @@ mod menu_group;
|
|||
mod menu_item;
|
||||
mod theme;
|
||||
|
||||
use crate::utils::class_list::class_list;
|
||||
use crate::utils::{class_list::class_list, Model};
|
||||
use leptos::*;
|
||||
pub use menu_group::MenuGroup;
|
||||
pub use menu_item::*;
|
||||
|
@ -10,7 +10,7 @@ pub use theme::MenuTheme;
|
|||
|
||||
#[component]
|
||||
pub fn Menu(
|
||||
#[prop(optional, into)] value: RwSignal<String>,
|
||||
#[prop(optional, into)] value: Model<String>,
|
||||
#[prop(optional, into)] class: MaybeSignal<String>,
|
||||
children: Children,
|
||||
) -> impl IntoView {
|
||||
|
@ -22,7 +22,7 @@ pub fn Menu(
|
|||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub(crate) struct MenuInjection(pub RwSignal<String>);
|
||||
pub(crate) struct MenuInjection(pub Model<String>);
|
||||
|
||||
pub(crate) fn use_menu() -> MenuInjection {
|
||||
expect_context()
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
mod tabbar_item;
|
||||
mod theme;
|
||||
|
||||
use crate::{use_theme, utils::mount_style, Theme};
|
||||
use crate::{use_theme, utils::{mount_style, Model}, Theme};
|
||||
use leptos::*;
|
||||
pub use tabbar_item::*;
|
||||
pub use theme::TabbarTheme;
|
||||
|
||||
#[component]
|
||||
pub fn Tabbar(
|
||||
#[prop(optional, into)] value: RwSignal<String>,
|
||||
#[prop(optional, into)] value: Model<String>,
|
||||
children: Children,
|
||||
) -> impl IntoView {
|
||||
mount_style("tabbar", include_str!("./tabbar.css"));
|
||||
|
@ -32,7 +32,7 @@ pub fn Tabbar(
|
|||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub(crate) struct TabbarInjection(pub RwSignal<String>);
|
||||
pub(crate) struct TabbarInjection(pub Model<String>);
|
||||
|
||||
pub(crate) fn use_tabbar() -> TabbarInjection {
|
||||
expect_context()
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
use crate::icon::*;
|
||||
use crate::utils::Model;
|
||||
use crate::{
|
||||
components::{OptionComp, Teleport},
|
||||
utils::{mount_style, StoredMaybeSignal},
|
||||
|
@ -13,7 +14,7 @@ pub struct ModalFooter {
|
|||
|
||||
#[component]
|
||||
pub fn Modal(
|
||||
#[prop(into)] show: RwSignal<bool>,
|
||||
#[prop(into)] show: Model<bool>,
|
||||
#[prop(optional, into)] title: MaybeSignal<String>,
|
||||
children: Children,
|
||||
#[prop(optional)] modal_footer: Option<ModalFooter>,
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
use crate::{
|
||||
theme::use_theme,
|
||||
utils::{class_list::class_list, mount_style},
|
||||
utils::{class_list::class_list, mount_style, Model},
|
||||
Theme,
|
||||
};
|
||||
use leptos::*;
|
||||
|
||||
#[component]
|
||||
pub fn Radio(
|
||||
#[prop(optional, into)] value: RwSignal<bool>,
|
||||
#[prop(optional, into)] value: Model<bool>,
|
||||
#[prop(optional, into)] class: MaybeSignal<String>,
|
||||
children: Children,
|
||||
) -> impl IntoView {
|
||||
|
|
|
@ -3,7 +3,7 @@ mod theme;
|
|||
use crate::{
|
||||
components::{Binder, Follower, FollowerPlacement, FollowerWidth},
|
||||
theme::use_theme,
|
||||
utils::{class_list::class_list, mount_style},
|
||||
utils::{class_list::class_list, mount_style, Model},
|
||||
Theme,
|
||||
};
|
||||
use leptos::*;
|
||||
|
@ -18,7 +18,7 @@ pub struct SelectOption<T> {
|
|||
|
||||
#[component]
|
||||
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)] class: MaybeSignal<String>,
|
||||
) -> impl IntoView
|
||||
|
|
|
@ -4,7 +4,7 @@ mod theme;
|
|||
use crate::{
|
||||
components::OptionComp,
|
||||
theme::use_theme,
|
||||
utils::{class_list::class_list, mount_style},
|
||||
utils::{class_list::class_list, mount_style, Model},
|
||||
Theme,
|
||||
};
|
||||
use leptos::*;
|
||||
|
@ -15,7 +15,7 @@ pub use theme::SliderTheme;
|
|||
|
||||
#[component]
|
||||
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(optional, into)] step: MaybeSignal<f64>,
|
||||
#[prop(optional, into)] class: MaybeSignal<String>,
|
||||
|
|
|
@ -2,7 +2,7 @@ mod theme;
|
|||
|
||||
use crate::{
|
||||
theme::use_theme,
|
||||
utils::{class_list::class_list, mount_style},
|
||||
utils::{class_list::class_list, mount_style, Model},
|
||||
Theme,
|
||||
};
|
||||
use leptos::*;
|
||||
|
@ -10,7 +10,7 @@ pub use theme::SwitchTheme;
|
|||
|
||||
#[component]
|
||||
pub fn Switch(
|
||||
#[prop(optional, into)] value: RwSignal<bool>,
|
||||
#[prop(optional, into)] value: Model<bool>,
|
||||
#[prop(optional, into)] class: MaybeSignal<String>,
|
||||
) -> impl IntoView {
|
||||
mount_style("switch", include_str!("./switch.css"));
|
||||
|
|
|
@ -2,7 +2,7 @@ mod tab;
|
|||
|
||||
use crate::{
|
||||
theme::use_theme,
|
||||
utils::{class_list::class_list, mount_style},
|
||||
utils::{class_list::class_list, mount_style, Model},
|
||||
Theme,
|
||||
};
|
||||
use leptos::*;
|
||||
|
@ -11,7 +11,7 @@ pub use tab::*;
|
|||
|
||||
#[component]
|
||||
pub fn Tabs(
|
||||
#[prop(optional, into)] value: RwSignal<String>,
|
||||
#[prop(optional, into)] value: Model<String>,
|
||||
#[prop(optional, into)] class: MaybeSignal<String>,
|
||||
children: Children,
|
||||
) -> impl IntoView {
|
||||
|
@ -30,7 +30,7 @@ pub fn Tabs(
|
|||
|
||||
#[component]
|
||||
fn TabsInner(
|
||||
value: RwSignal<String>,
|
||||
value: Model<String>,
|
||||
tab_options_vec: RwSignal<Vec<TabOption>>,
|
||||
#[prop(optional, into)] class: MaybeSignal<String>,
|
||||
children: Children,
|
||||
|
@ -161,7 +161,7 @@ pub(crate) struct TabsLabelLine {
|
|||
|
||||
#[derive(Clone)]
|
||||
pub(crate) struct TabsInjection {
|
||||
active_key: RwSignal<String>,
|
||||
active_key: Model<String>,
|
||||
tab_options_vec: RwSignal<Vec<TabOption>>,
|
||||
}
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ use crate::{
|
|||
chrono::{Local, NaiveTime, Timelike},
|
||||
components::{Binder, Follower, FollowerPlacement},
|
||||
use_theme,
|
||||
utils::{mount_style, ComponentRef},
|
||||
utils::{mount_style, ComponentRef, Model},
|
||||
Button, ButtonSize, ButtonVariant, Icon, Input, InputSuffix, SignalWatch, Theme,
|
||||
};
|
||||
use leptos::*;
|
||||
|
@ -12,7 +12,7 @@ pub use theme::TimePickerTheme;
|
|||
|
||||
#[component]
|
||||
pub fn TimePicker(
|
||||
#[prop(optional, into)] value: RwSignal<Option<NaiveTime>>,
|
||||
#[prop(optional, into)] value: Model<Option<NaiveTime>>,
|
||||
#[prop(optional, into)] class: MaybeSignal<String>,
|
||||
#[prop(attrs)] attrs: Vec<(&'static str, Attribute)>,
|
||||
) -> impl IntoView {
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
pub(crate) mod class_list;
|
||||
mod component_ref;
|
||||
mod event_listener;
|
||||
mod model;
|
||||
mod mount_style;
|
||||
mod signal;
|
||||
mod stored_maybe_signal;
|
||||
|
@ -10,6 +11,7 @@ mod time;
|
|||
// pub use callback::AsyncCallback;
|
||||
pub use component_ref::{create_component_ref, ComponentRef};
|
||||
pub(crate) use event_listener::*;
|
||||
pub(crate) use model::Model;
|
||||
pub(crate) use mount_style::mount_style;
|
||||
pub use signal::SignalWatch;
|
||||
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