Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 10 additions & 8 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,8 @@ itertools = { default-features = false, version = "0.14.0" }
convert_case = { default-features = false, version = "0.8.0" }
serde_json = { default-features = false, version = "1.0.143" }
trybuild = { default-features = false, version = "1.0.110" }
typed-builder = { default-features = false, version = "0.21.2" }
typed-builder = { default-features = false, version = "0.22.0" }
typed-builder-macro = { default-features = false, version = "0.22.0" }
thiserror = { default-features = false, version = "2.0.16" }
wasm-bindgen = { default-features = false, version = "0.2.100" }
indexmap = { default-features = false, version = "2.11.0" }
Expand Down Expand Up @@ -123,7 +124,6 @@ serial_test = { default-features = false, version = "3.2.0" }
erased = { default-features = false, version = "0.1.2" }
glib = { default-features = false, version = "0.20.12" }
async-trait = { default-features = false, version = "0.1.89" }
typed-builder-macro = { default-features = false, version = "0.21.0" }
linear-map = { default-features = false, version = "1.2.0" }
anyhow = { default-features = false, version = "1.0.100" }
walkdir = { default-features = false, version = "2.5.0" }
Expand Down
2 changes: 1 addition & 1 deletion leptos/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ pub mod prelude {
pub mod form;

/// A standard way to wrap functions and closures to pass them to components.
pub mod callback;
pub use reactive_graph::callback;

/// Types that can be passed as the `children` prop of a component.
pub mod children;
Expand Down
39 changes: 27 additions & 12 deletions leptos_macro/src/component.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1016,25 +1016,27 @@ struct PropOpt {
name: Option<String>,
}

struct TypedBuilderOpts {
struct TypedBuilderOpts<'a> {
default: bool,
default_with_value: Option<syn::Expr>,
strip_option: bool,
into: bool,
ty: &'a Type,
}

impl TypedBuilderOpts {
fn from_opts(opts: &PropOpt, is_ty_option: bool) -> Self {
impl<'a> TypedBuilderOpts<'a> {
fn from_opts(opts: &PropOpt, ty: &'a Type) -> Self {
Self {
default: opts.optional || opts.optional_no_strip || opts.attrs,
default_with_value: opts.default.clone(),
strip_option: opts.strip_option || opts.optional && is_ty_option,
strip_option: opts.strip_option || opts.optional && is_option(ty),
into: opts.into,
ty,
}
}
}

impl TypedBuilderOpts {
impl TypedBuilderOpts<'_> {
fn to_serde_tokens(&self) -> TokenStream {
let default = if let Some(v) = &self.default_with_value {
let v = v.to_token_stream().to_string();
Expand All @@ -1053,7 +1055,7 @@ impl TypedBuilderOpts {
}
}

impl ToTokens for TypedBuilderOpts {
impl ToTokens for TypedBuilderOpts<'_> {
fn to_tokens(&self, tokens: &mut TokenStream) {
let default = if let Some(v) = &self.default_with_value {
let v = v.to_token_stream().to_string();
Expand All @@ -1064,14 +1066,29 @@ impl ToTokens for TypedBuilderOpts {
quote! {}
};

let strip_option = if self.strip_option {
// If self.strip_option && self.into, then the strip_option will be represented as part of the transform closure.
let strip_option = if self.strip_option && !self.into {
quote! { strip_option, }
} else {
quote! {}
};

let into = if self.into {
quote! { into, }
if !self.strip_option {
let ty = &self.ty;
quote! {
fn transform<__IntoReactiveValueMarker>(value: impl ::leptos::prelude::IntoReactiveValue<#ty, __IntoReactiveValueMarker>) -> #ty {
value.into_reactive_value()
},
}
} else {
let ty = unwrap_option(self.ty);
quote! {
fn transform<__IntoReactiveValueMarker>(value: impl ::leptos::prelude::IntoReactiveValue<#ty, __IntoReactiveValueMarker>) -> Option<#ty> {
Some(value.into_reactive_value())
},
}
}
} else {
quote! {}
};
Expand Down Expand Up @@ -1107,8 +1124,7 @@ fn prop_builder_fields(
ty,
} = prop;

let builder_attrs =
TypedBuilderOpts::from_opts(prop_opts, is_option(ty));
let builder_attrs = TypedBuilderOpts::from_opts(prop_opts, ty);

let builder_docs = prop_to_doc(prop, PropDocStyle::Inline);

Expand Down Expand Up @@ -1153,8 +1169,7 @@ fn prop_serializer_fields(vis: &Visibility, props: &[Prop]) -> TokenStream {
ty,
} = prop;

let builder_attrs =
TypedBuilderOpts::from_opts(prop_opts, is_option(ty));
let builder_attrs = TypedBuilderOpts::from_opts(prop_opts, ty);
let serde_attrs = builder_attrs.to_serde_tokens();

let PatIdent { ident, by_ref, .. } = &name;
Expand Down
34 changes: 25 additions & 9 deletions leptos_macro/src/slot.rs
Original file line number Diff line number Diff line change
Expand Up @@ -159,25 +159,27 @@ struct PropOpt {
pub attrs: bool,
}

struct TypedBuilderOpts {
struct TypedBuilderOpts<'a> {
default: bool,
default_with_value: Option<syn::Expr>,
strip_option: bool,
into: bool,
ty: &'a Type,
}

impl TypedBuilderOpts {
pub fn from_opts(opts: &PropOpt, is_ty_option: bool) -> Self {
impl<'a> TypedBuilderOpts<'a> {
pub fn from_opts(opts: &PropOpt, ty: &'a Type) -> Self {
Self {
default: opts.optional || opts.optional_no_strip || opts.attrs,
default_with_value: opts.default.clone(),
strip_option: opts.strip_option || opts.optional && is_ty_option,
strip_option: opts.strip_option || opts.optional && is_option(ty),
into: opts.into,
ty,
}
}
}

impl ToTokens for TypedBuilderOpts {
impl ToTokens for TypedBuilderOpts<'_> {
fn to_tokens(&self, tokens: &mut TokenStream) {
let default = if let Some(v) = &self.default_with_value {
let v = v.to_token_stream().to_string();
Expand All @@ -188,14 +190,29 @@ impl ToTokens for TypedBuilderOpts {
quote! {}
};

let strip_option = if self.strip_option {
// If self.strip_option && self.into, then the strip_option will be represented as part of the transform closure.
let strip_option = if self.strip_option && !self.into {
quote! { strip_option, }
} else {
quote! {}
};

let into = if self.into {
quote! { into, }
if !self.strip_option {
let ty = &self.ty;
quote! {
fn transform<__IntoReactiveValueMarker>(value: impl ::leptos::prelude::IntoReactiveValue<#ty, __IntoReactiveValueMarker>) -> #ty {
value.into_reactive_value()
},
}
} else {
let ty = unwrap_option(self.ty);
quote! {
fn transform<__IntoReactiveValueMarker>(value: impl ::leptos::prelude::IntoReactiveValue<#ty, __IntoReactiveValueMarker>) -> Option<#ty> {
Some(value.into_reactive_value())
},
}
}
} else {
quote! {}
};
Expand Down Expand Up @@ -227,8 +244,7 @@ fn prop_builder_fields(vis: &Visibility, props: &[Prop]) -> TokenStream {
ty,
} = prop;

let builder_attrs =
TypedBuilderOpts::from_opts(prop_opts, is_option(ty));
let builder_attrs = TypedBuilderOpts::from_opts(prop_opts, ty);

let builder_docs = prop_to_doc(prop, PropDocStyle::Inline);

Expand Down
2 changes: 1 addition & 1 deletion leptos_macro/src/view/component_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ pub(crate) fn component_to_tokens(

if optional {
optional_props.push(quote! {
props.#name = { #value }.map(Into::into);
props.#name = { #value }.map(::leptos::prelude::IntoReactiveValue::into_reactive_value);
})
} else {
required_props.push(quote! {
Expand Down
Loading
Loading