feat: update leptos

This commit is contained in:
luoxiao 2024-08-05 00:05:39 +08:00
parent 2d46cc41d0
commit 008da2e5b1
14 changed files with 125 additions and 152 deletions

View file

@ -16,5 +16,6 @@ thaw_components = { version = "0.2.0-alpha", path = "./thaw_components" }
thaw_macro = { version = "0.1.0-alpha", path = "./thaw_macro" } thaw_macro = { version = "0.1.0-alpha", path = "./thaw_macro" }
thaw_utils = { version = "0.1.0-alpha", path = "./thaw_utils" } thaw_utils = { version = "0.1.0-alpha", path = "./thaw_utils" }
leptos = "0.7.0-beta" leptos = { git = "https://github.com/leptos-rs/leptos", rev = "3dbedfc8710add4bc9a94fe27fa000fb180f393b" }
leptos_meta = "0.7.0-beta" leptos_meta = { git = "https://github.com/leptos-rs/leptos", rev = "3dbedfc8710add4bc9a94fe27fa000fb180f393b" }
leptos_router = { git = "https://github.com/leptos-rs/leptos", rev = "3dbedfc8710add4bc9a94fe27fa000fb180f393b" }

View file

@ -9,7 +9,7 @@ edition = "2021"
[dependencies] [dependencies]
leptos = { workspace = true } leptos = { workspace = true }
leptos_meta = { workspace = true } leptos_meta = { workspace = true }
leptos_router = "0.7.0-beta" leptos_router = { workspace = true }
thaw = { path = "../thaw" } thaw = { path = "../thaw" }
demo_markdown = { path = "../demo_markdown" } demo_markdown = { path = "../demo_markdown" }
icondata = "0.3.0" icondata = "0.3.0"

View file

@ -10,7 +10,7 @@ use crate::{
use leptos::{context::Provider, either::Either, html, prelude::*}; use leptos::{context::Provider, either::Either, html, prelude::*};
use std::collections::HashMap; use std::collections::HashMap;
use thaw_components::{Binder, Follower, FollowerPlacement, FollowerWidth}; use thaw_components::{Binder, Follower, FollowerPlacement, FollowerWidth};
use thaw_utils::{class_list, mount_style, ArcOneCallback, BoxOneCallback, Model, OptionalProp}; use thaw_utils::{class_list, mount_style, ArcOneCallback, BoxOneCallback, Model};
#[slot] #[slot]
pub struct AutoCompletePrefix { pub struct AutoCompletePrefix {
@ -25,7 +25,7 @@ pub struct AutoCompleteSuffix {
#[component] #[component]
pub fn AutoComplete( pub fn AutoComplete(
#[prop(optional, into)] value: Model<String>, #[prop(optional, into)] value: Model<String>,
#[prop(optional, into)] placeholder: OptionalProp<MaybeSignal<String>>, #[prop(optional, into)] placeholder: MaybeProp<String>,
#[prop(optional, into)] clear_after_select: MaybeSignal<bool>, #[prop(optional, into)] clear_after_select: MaybeSignal<bool>,
#[prop(optional, into)] blur_after_select: MaybeSignal<bool>, #[prop(optional, into)] blur_after_select: MaybeSignal<bool>,
#[prop(optional, into)] on_select: Option<BoxOneCallback<String>>, #[prop(optional, into)] on_select: Option<BoxOneCallback<String>>,

View file

@ -24,7 +24,7 @@ pub fn Input(
#[prop(optional, into)] input_type: MaybeSignal<InputType>, #[prop(optional, into)] input_type: MaybeSignal<InputType>,
/// Placeholder text for the input. /// Placeholder text for the input.
#[prop(optional, into)] #[prop(optional, into)]
placeholder: OptionalProp<MaybeSignal<String>>, placeholder: MaybeProp<String>,
#[prop(optional, into)] on_focus: Option<BoxOneCallback<ev::FocusEvent>>, #[prop(optional, into)] on_focus: Option<BoxOneCallback<ev::FocusEvent>>,
#[prop(optional, into)] on_blur: Option<BoxOneCallback<ev::FocusEvent>>, #[prop(optional, into)] on_blur: Option<BoxOneCallback<ev::FocusEvent>>,
/// Whether the input is disabled /// Whether the input is disabled
@ -165,7 +165,7 @@ pub fn Input(
on:blur=on_internal_blur on:blur=on_internal_blur
class="thaw-input__input" class="thaw-input__input"
disabled=move || disabled.get() disabled=move || disabled.get()
placeholder=placeholder.map(|p| move || p.get()) placeholder=move || placeholder.get()
node_ref=input_ref node_ref=input_ref
/> />

View file

@ -4,11 +4,11 @@ use crate::{
}; };
use leptos::prelude::*; use leptos::prelude::*;
use thaw_components::{Fallback, If, OptionComp, Then}; use thaw_components::{Fallback, If, OptionComp, Then};
use thaw_utils::{class_list, mount_style, OptionalMaybeSignal}; use thaw_utils::{class_list, mount_style};
#[component] #[component]
pub fn MenuItem( pub fn MenuItem(
#[prop(optional, into)] icon: OptionalMaybeSignal<icondata_core::Icon>, #[prop(optional, into)] icon: MaybeProp<icondata_core::Icon>,
#[prop(into)] value: MaybeSignal<String>, #[prop(into)] value: MaybeSignal<String>,
#[prop(optional, into)] disabled: MaybeSignal<bool>, #[prop(optional, into)] disabled: MaybeSignal<bool>,
#[prop(optional, into)] class: MaybeProp<String>, #[prop(optional, into)] class: MaybeProp<String>,

View file

@ -7,14 +7,13 @@ use leptos::{ev, html::Div, leptos_dom::helpers::TimeoutHandle, prelude::*};
use std::time::Duration; use std::time::Duration;
use thaw_components::{Binder, CSSTransition, Follower, FollowerPlacement}; use thaw_components::{Binder, CSSTransition, Follower, FollowerPlacement};
use thaw_utils::{ use thaw_utils::{
add_event_listener, call_on_click_outside, class_list, mount_style, ArcOneCallback, add_event_listener, call_on_click_outside, class_list, mount_style, ArcOneCallback, BoxCallback,
BoxCallback, OptionalProp,
}; };
#[slot] #[slot]
pub struct MenuTrigger { pub struct MenuTrigger {
#[prop(optional, into)] #[prop(optional, into)]
class: OptionalProp<MaybeSignal<String>>, class: MaybeProp<String>,
children: Children, children: Children,
} }
@ -103,7 +102,7 @@ pub fn Menu(
view! { view! {
<Binder target_ref> <Binder target_ref>
<div <div
class=class_list!["thaw-menu-trigger", trigger_class.map(| c | move || c.get())] class=class_list!["thaw-menu-trigger", trigger_class]
node_ref=target_ref node_ref=target_ref
on:mouseenter=on_mouse_enter on:mouseenter=on_mouse_enter
on:mouseleave=on_mouse_leave on:mouseleave=on_mouse_leave

View file

@ -1,5 +1,5 @@
use leptos::prelude::*; use leptos::prelude::*;
use thaw_utils::{class_list, mount_style, OptionalMaybeSignal}; use thaw_utils::{class_list, mount_style};
#[derive(Default)] #[derive(Default)]
pub enum SpaceGap { pub enum SpaceGap {
@ -16,8 +16,8 @@ pub enum SpaceGap {
pub fn Space( pub fn Space(
#[prop(optional)] gap: SpaceGap, #[prop(optional)] gap: SpaceGap,
#[prop(optional)] vertical: bool, #[prop(optional)] vertical: bool,
#[prop(optional, into)] align: OptionalMaybeSignal<SpaceAlign>, #[prop(optional, into)] align: MaybeProp<SpaceAlign>,
#[prop(optional, into)] justify: OptionalMaybeSignal<SpaceJustify>, #[prop(optional, into)] justify: MaybeProp<SpaceJustify>,
#[prop(optional, into)] class: MaybeProp<String>, #[prop(optional, into)] class: MaybeProp<String>,
children: ChildrenFragment, children: ChildrenFragment,
) -> impl IntoView { ) -> impl IntoView {

View file

@ -1,4 +1,7 @@
use leptos::prelude::{MaybeSignal, Memo, ReadSignal, RwSignal, Signal}; use leptos::{
prelude::{MaybeSignal, Memo, ReadSignal, RwSignal, Signal},
reactive_graph::owner::Storage,
};
use std::ops::{Deref, DerefMut}; use std::ops::{Deref, DerefMut};
use crate::BoxOneCallback; use crate::BoxOneCallback;
@ -58,6 +61,7 @@ impl From<&str> for OptionalProp<String> {
} }
} }
/// TODO remove signal
impl From<&str> for OptionalProp<MaybeSignal<String>> { impl From<&str> for OptionalProp<MaybeSignal<String>> {
fn from(value: &str) -> Self { fn from(value: &str) -> Self {
Self(Some(MaybeSignal::from(value.to_string()))) Self(Some(MaybeSignal::from(value.to_string())))
@ -88,8 +92,11 @@ impl<T: Send + Sync> From<Memo<T>> for OptionalProp<MaybeSignal<T>> {
} }
} }
impl<T> From<Signal<T>> for OptionalProp<MaybeSignal<T>> { impl<T, S> From<Signal<T, S>> for OptionalProp<MaybeSignal<T, S>>
fn from(value: Signal<T>) -> Self { where
S: Storage<T>,
{
fn from(value: Signal<T, S>) -> Self {
Self(Some(MaybeSignal::from(value))) Self(Some(MaybeSignal::from(value)))
} }
} }

View file

@ -1,11 +1,9 @@
mod component_ref; mod component_ref;
mod model; mod model;
mod optional_maybe_signal;
mod signal_watch; mod signal_watch;
mod stored_maybe_signal; mod stored_maybe_signal;
pub use component_ref::ComponentRef; pub use component_ref::ComponentRef;
pub use model::{Model, OptionModel, VecModel}; pub use model::{Model, OptionModel, VecModel};
pub use optional_maybe_signal::OptionalMaybeSignal;
pub use signal_watch::SignalWatch; pub use signal_watch::SignalWatch;
pub use stored_maybe_signal::StoredMaybeSignal; pub use stored_maybe_signal::StoredMaybeSignal;

View file

@ -6,18 +6,20 @@ pub use vec_model::VecModel;
use leptos::reactive_graph::{ use leptos::reactive_graph::{
computed::Memo, computed::Memo,
owner::{Storage, SyncStorage},
signal::{ReadSignal, RwSignal, WriteSignal}, signal::{ReadSignal, RwSignal, WriteSignal},
traits::{DefinedAt, IsDisposed, Set, Update, With, WithUntracked}, traits::{DefinedAt, IsDisposed, Set, Update, With, WithUntracked},
wrappers::read::Signal, wrappers::read::Signal,
}; };
pub struct Model<T> pub struct Model<T, S = SyncStorage>
where where
T: 'static, T: 'static,
S: Storage<T>,
{ {
read: Signal<T>, read: Signal<T, S>,
write: WriteSignal<T>, write: WriteSignal<T, S>,
on_write: Option<WriteSignal<T>>, on_write: Option<WriteSignal<T, S>>,
} }
impl<T: Default + Send + Sync> Default for Model<T> { impl<T: Default + Send + Sync> Default for Model<T> {
@ -26,13 +28,16 @@ impl<T: Default + Send + Sync> Default for Model<T> {
} }
} }
impl<T> Clone for Model<T> { impl<T, S> Clone for Model<T, S>
where
S: Storage<T>,
{
fn clone(&self) -> Self { fn clone(&self) -> Self {
*self *self
} }
} }
impl<T> Copy for Model<T> {} impl<T, S> Copy for Model<T, S> where S: Storage<T> {}
impl<T: Send + Sync> Model<T> { impl<T: Send + Sync> Model<T> {
fn new(value: T) -> Self { fn new(value: T) -> Self {
@ -45,9 +50,12 @@ impl<T: Send + Sync> Model<T> {
} }
} }
impl<T> DefinedAt for Model<T> { impl<T, S> DefinedAt for Model<T, S>
where
S: Storage<T>,
{
fn defined_at(&self) -> Option<&'static std::panic::Location<'static>> { fn defined_at(&self) -> Option<&'static std::panic::Location<'static>> {
todo!() self.read.defined_at()
} }
} }
@ -82,7 +90,10 @@ impl<T: Send + Sync + Clone> Update for Model<T> {
} }
} }
impl<T> IsDisposed for Model<T> { impl<T, S> IsDisposed for Model<T, S>
where
S: Storage<T>,
{
fn is_disposed(&self) -> bool { fn is_disposed(&self) -> bool {
self.write.is_disposed() self.write.is_disposed()
} }
@ -105,8 +116,11 @@ impl<T: Send + Sync> From<RwSignal<T>> for Model<T> {
} }
} }
impl<T> From<(Signal<T>, WriteSignal<T>)> for Model<T> { impl<T, S> From<(Signal<T, S>, WriteSignal<T, S>)> for Model<T, S>
fn from((read, write): (Signal<T>, WriteSignal<T>)) -> Self { where
S: Storage<T>,
{
fn from((read, write): (Signal<T, S>, WriteSignal<T, S>)) -> Self {
Self { Self {
read, read,
write, write,

View file

@ -1,19 +1,21 @@
use leptos::reactive_graph::{ use leptos::reactive_graph::{
computed::Memo, computed::Memo,
owner::{Storage, SyncStorage},
signal::{ReadSignal, RwSignal, WriteSignal}, signal::{ReadSignal, RwSignal, WriteSignal},
traits::{Get, GetUntracked, Set, With, WithUntracked}, traits::{Get, GetUntracked, Set, With, WithUntracked},
wrappers::read::Signal, wrappers::read::Signal,
}; };
pub enum OptionModel<T> pub enum OptionModel<T, S = SyncStorage>
where where
T: 'static, T: 'static,
S: Storage<T> + Storage<Option<T>>,
{ {
T(Signal<T>, WriteSignal<T>, Option<WriteSignal<T>>), T(Signal<T, S>, WriteSignal<T, S>, Option<WriteSignal<T, S>>),
Option( Option(
Signal<Option<T>>, Signal<Option<T>, S>,
WriteSignal<Option<T>>, WriteSignal<Option<T>, S>,
Option<WriteSignal<Option<T>>>, Option<WriteSignal<Option<T>, S>>,
), ),
} }
@ -23,13 +25,16 @@ impl<T: Default + Send + Sync> Default for OptionModel<T> {
} }
} }
impl<T> Clone for OptionModel<T> { impl<T, S> Clone for OptionModel<T, S>
where
S: Storage<T> + Storage<Option<T>>,
{
fn clone(&self) -> Self { fn clone(&self) -> Self {
*self *self
} }
} }
impl<T> Copy for OptionModel<T> {} impl<T, S> Copy for OptionModel<T, S> where S: Storage<T> + Storage<Option<T>> {}
impl<T: Send + Sync> OptionModel<T> { impl<T: Send + Sync> OptionModel<T> {
fn new(value: T) -> Self { fn new(value: T) -> Self {
@ -112,14 +117,20 @@ impl<T: Send + Sync> From<RwSignal<Option<T>>> for OptionModel<T> {
} }
} }
impl<T> From<(Signal<T>, WriteSignal<T>)> for OptionModel<T> { impl<T, S> From<(Signal<T, S>, WriteSignal<T, S>)> for OptionModel<T, S>
fn from((read, write): (Signal<T>, WriteSignal<T>)) -> Self { where
S: Storage<T> + Storage<Option<T>>,
{
fn from((read, write): (Signal<T, S>, WriteSignal<T, S>)) -> Self {
Self::T(read, write, None) Self::T(read, write, None)
} }
} }
impl<T> From<(Signal<Option<T>>, WriteSignal<Option<T>>)> for OptionModel<T> { impl<T, S> From<(Signal<Option<T>, S>, WriteSignal<Option<T>, S>)> for OptionModel<T, S>
fn from((read, write): (Signal<Option<T>>, WriteSignal<Option<T>>)) -> Self { where
S: Storage<T> + Storage<Option<T>>,
{
fn from((read, write): (Signal<Option<T>, S>, WriteSignal<Option<T>, S>)) -> Self {
Self::Option(read, write, None) Self::Option(read, write, None)
} }
} }

View file

@ -2,26 +2,28 @@ use leptos::{
prelude::Update, prelude::Update,
reactive_graph::{ reactive_graph::{
computed::Memo, computed::Memo,
owner::{Storage, SyncStorage},
signal::{ReadSignal, RwSignal, WriteSignal}, signal::{ReadSignal, RwSignal, WriteSignal},
traits::{GetUntracked, Set, With, WithUntracked}, traits::{GetUntracked, Set, With, WithUntracked},
wrappers::read::Signal, wrappers::read::Signal,
}, },
}; };
pub enum VecModel<T> pub enum VecModel<T, S = SyncStorage>
where where
T: 'static, T: 'static,
S: Storage<T> + Storage<Option<T>> + Storage<Vec<T>>,
{ {
T(Signal<T>, WriteSignal<T>, Option<WriteSignal<T>>), T(Signal<T, S>, WriteSignal<T, S>, Option<WriteSignal<T, S>>),
Option( Option(
Signal<Option<T>>, Signal<Option<T>, S>,
WriteSignal<Option<T>>, WriteSignal<Option<T>, S>,
Option<WriteSignal<Option<T>>>, Option<WriteSignal<Option<T>, S>>,
), ),
Vec( Vec(
Signal<Vec<T>>, Signal<Vec<T>, S>,
WriteSignal<Vec<T>>, WriteSignal<Vec<T>, S>,
Option<WriteSignal<Vec<T>>>, Option<WriteSignal<Vec<T>, S>>,
), ),
} }
@ -31,13 +33,16 @@ impl<T: Default + Send + Sync> Default for VecModel<T> {
} }
} }
impl<T> Clone for VecModel<T> { impl<T, S> Clone for VecModel<T, S>
where
S: Storage<T> + Storage<Option<T>> + Storage<Vec<T>>,
{
fn clone(&self) -> Self { fn clone(&self) -> Self {
*self *self
} }
} }
impl<T> Copy for VecModel<T> {} impl<T, S> Copy for VecModel<T, S> where S: Storage<T> + Storage<Option<T>> + Storage<Vec<T>> {}
impl<T: Send + Sync> VecModel<T> { impl<T: Send + Sync> VecModel<T> {
fn new(value: T) -> Self { fn new(value: T) -> Self {
@ -192,20 +197,29 @@ impl<T: Send + Sync> From<RwSignal<Vec<T>>> for VecModel<T> {
} }
} }
impl<T> From<(Signal<T>, WriteSignal<T>)> for VecModel<T> { impl<T, S> From<(Signal<T, S>, WriteSignal<T, S>)> for VecModel<T, S>
fn from((read, write): (Signal<T>, WriteSignal<T>)) -> Self { where
S: Storage<T> + Storage<Option<T>> + Storage<Vec<T>>,
{
fn from((read, write): (Signal<T, S>, WriteSignal<T, S>)) -> Self {
Self::T(read, write, None) Self::T(read, write, None)
} }
} }
impl<T> From<(Signal<Option<T>>, WriteSignal<Option<T>>)> for VecModel<T> { impl<T, S> From<(Signal<Option<T>, S>, WriteSignal<Option<T>, S>)> for VecModel<T, S>
fn from((read, write): (Signal<Option<T>>, WriteSignal<Option<T>>)) -> Self { where
S: Storage<T> + Storage<Option<T>> + Storage<Vec<T>>,
{
fn from((read, write): (Signal<Option<T>, S>, WriteSignal<Option<T>, S>)) -> Self {
Self::Option(read, write, None) Self::Option(read, write, None)
} }
} }
impl<T> From<(Signal<Vec<T>>, WriteSignal<Vec<T>>)> for VecModel<T> { impl<T, S> From<(Signal<Vec<T>, S>, WriteSignal<Vec<T>, S>)> for VecModel<T, S>
fn from((read, write): (Signal<Vec<T>>, WriteSignal<Vec<T>>)) -> Self { where
S: Storage<T> + Storage<Option<T>> + Storage<Vec<T>>,
{
fn from((read, write): (Signal<Vec<T>, S>, WriteSignal<Vec<T>, S>)) -> Self {
Self::Vec(read, write, None) Self::Vec(read, write, None)
} }
} }

View file

@ -1,86 +0,0 @@
use leptos::prelude::*;
use std::ops::Deref;
pub struct OptionalMaybeSignal<T: 'static>(MaybeSignal<Option<T>>);
impl<T> Default for OptionalMaybeSignal<T> {
fn default() -> Self {
Self(MaybeSignal::Static(None))
}
}
impl<T: Copy> Copy for OptionalMaybeSignal<T> {}
impl<T: Clone> Clone for OptionalMaybeSignal<T> {
fn clone(&self) -> Self {
Self(self.0.clone())
}
}
impl<T> Deref for OptionalMaybeSignal<T> {
type Target = MaybeSignal<Option<T>>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<T> From<T> for OptionalMaybeSignal<T> {
fn from(value: T) -> Self {
Self(MaybeSignal::Static(Some(value)))
}
}
impl<T> From<Option<T>> for OptionalMaybeSignal<T> {
fn from(value: Option<T>) -> Self {
Self(MaybeSignal::Static(value))
}
}
impl<T: Send + Sync> From<ReadSignal<Option<T>>> for OptionalMaybeSignal<T> {
fn from(value: ReadSignal<Option<T>>) -> Self {
Self(MaybeSignal::Dynamic(value.into()))
}
}
impl<T: Send + Sync> From<RwSignal<Option<T>>> for OptionalMaybeSignal<T> {
fn from(value: RwSignal<Option<T>>) -> Self {
Self(MaybeSignal::Dynamic(value.into()))
}
}
impl<T: Send + Sync> From<Memo<Option<T>>> for OptionalMaybeSignal<T> {
fn from(value: Memo<Option<T>>) -> Self {
Self(MaybeSignal::Dynamic(value.into()))
}
}
impl<T> From<Signal<Option<T>>> for OptionalMaybeSignal<T> {
fn from(value: Signal<Option<T>>) -> Self {
Self(MaybeSignal::Dynamic(value))
}
}
impl<T> From<MaybeSignal<Option<T>>> for OptionalMaybeSignal<T> {
fn from(value: MaybeSignal<Option<T>>) -> Self {
Self(value)
}
}
// TODO
// #[cfg(test)]
// mod test {
// use super::OptionalMaybeSignal;
// use leptos::{create_runtime, MaybeSignal};
// #[test]
// fn into() {
// let runtime = create_runtime();
// let _: MaybeSignal<i32> = 12.into();
// let _: OptionalMaybeSignal<i32> = Some(12).into();
// let _: OptionalMaybeSignal<i32> = MaybeSignal::Static(Some(12)).into();
// runtime.dispose();
// }
// }

View file

@ -1,21 +1,36 @@
use leptos::reactive_graph::{ use leptos::reactive_graph::{
owner::StoredValue, owner::{Storage, StoredValue, SyncStorage},
traits::{DefinedAt, With, WithUntracked}, traits::{DefinedAt, With, WithUntracked},
wrappers::read::{MaybeSignal, Signal}, wrappers::read::{MaybeSignal, Signal},
}; };
#[derive(Clone)] pub enum StoredMaybeSignal<T, S = SyncStorage>
pub enum StoredMaybeSignal<T>
where where
T: 'static, T: 'static,
S: Storage<T>,
{ {
StoredValue(StoredValue<T>), StoredValue(StoredValue<T, S>),
Signal(Signal<T>), Signal(Signal<T, S>),
} }
impl<T: Clone> Copy for StoredMaybeSignal<T> {} impl<T, S> Clone for StoredMaybeSignal<T, S>
where
S: Storage<T>,
{
fn clone(&self) -> Self {
match self {
Self::StoredValue(v) => Self::StoredValue(v.clone()),
Self::Signal(s) => Self::Signal(s.clone()),
}
}
}
impl<T> DefinedAt for StoredMaybeSignal<T> { impl<T: Clone, S> Copy for StoredMaybeSignal<T, S> where S: Storage<T> {}
impl<T, S> DefinedAt for StoredMaybeSignal<T, S>
where
S: Storage<T>,
{
fn defined_at(&self) -> Option<&'static std::panic::Location<'static>> { fn defined_at(&self) -> Option<&'static std::panic::Location<'static>> {
match self { match self {
StoredMaybeSignal::StoredValue(value) => value.defined_at(), StoredMaybeSignal::StoredValue(value) => value.defined_at(),