Skip to content

Commit

Permalink
feat: allow #[prop(attrs)] on slots
Browse files Browse the repository at this point in the history
  • Loading branch information
Upbolt committed Mar 2, 2024
1 parent 7996f83 commit d0e0f5d
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 2 deletions.
54 changes: 52 additions & 2 deletions leptos_macro/src/slot.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,15 +65,50 @@ impl ToTokens for Model {
body,
} = self;

let (_, generics, where_clause) = body.generics.split_for_impl();
let (impl_generics, generics, where_clause) =
body.generics.split_for_impl();

let builder_name = quote::format_ident!("{name}Builder");
let prop_builder_fields = prop_builder_fields(vis, props);
let prop_docs = generate_prop_docs(props);
let builder_name_doc = LitStr::new(
&format!("Props for the [`{name}`] slot."),
name.span(),
);

let count = props
.iter()
.filter(
|Prop {
prop_opts: PropOpt { attrs, .. },
..
}| *attrs,
)
.count();

let dyn_attrs_props = props
.iter()
.filter(
|Prop {
prop_opts: PropOpt { attrs, .. },
..
}| *attrs,
)
.enumerate()
.map(|(idx, Prop { name, .. })| {
let ident = &name;
if idx < count - 1 {
quote! {
self.#ident = v.clone().into();
}
} else {
quote! {
self.#ident = v.into();
}
}
})
.collect::<TokenStream>();

let output = quote! {
#[doc = #builder_name_doc]
#[doc = ""]
Expand All @@ -90,6 +125,20 @@ impl ToTokens for Model {
vec![value]
}
}

impl #impl_generics ::leptos::Props for #name #generics #where_clause {
type Builder = #builder_name #generics;
fn builder() -> Self::Builder {
#name::builder()
}
}

impl #impl_generics ::leptos::DynAttrs for #name #generics #where_clause {
fn dyn_attrs(mut self, v: Vec<(&'static str, ::leptos::Attribute)>) -> Self {
#dyn_attrs_props
self
}
}
};

tokens.append_all(output)
Expand Down Expand Up @@ -142,6 +191,7 @@ struct PropOpt {
#[attribute(example = "5 * 10")]
pub default: Option<syn::Expr>,
pub into: bool,
pub attrs: bool,
}

struct TypedBuilderOpts {
Expand All @@ -154,7 +204,7 @@ struct TypedBuilderOpts {
impl TypedBuilderOpts {
pub fn from_opts(opts: &PropOpt, is_ty_option: bool) -> Self {
Self {
default: opts.optional || opts.optional_no_strip,
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,
into: opts.into,
Expand Down
20 changes: 20 additions & 0 deletions leptos_macro/src/view/slot_helper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ pub(crate) fn slot_to_tokens(
.filter(|attr| {
!attr.key.to_string().starts_with("let:")
&& !attr.key.to_string().starts_with("clone:")
&& !attr.key.to_string().starts_with("attr:")
})
.map(|attr| {
let name = &attr.key;
Expand Down Expand Up @@ -86,6 +87,24 @@ pub(crate) fn slot_to_tokens(
})
.collect::<Vec<_>>();

let dyn_attrs = attrs
.filter(|attr| attr.key.to_string().starts_with("attr:"))
.filter_map(|attr| {
let name = &attr.key.to_string();
let name = name.strip_prefix("attr:");
let value = attr.value().map(|v| {
quote! { #v }
})?;
Some(quote! { (#name, ::leptos::IntoAttribute::into_attribute(#value)) })
})
.collect::<Vec<_>>();

let dyn_attrs = if dyn_attrs.is_empty() {
quote! {}
} else {
quote! { .dyn_attrs(vec![#(#dyn_attrs),*]) }
};

let mut slots = HashMap::new();
let children = if node.children.is_empty() {
quote! {}
Expand Down Expand Up @@ -159,6 +178,7 @@ pub(crate) fn slot_to_tokens(
#(#slots)*
#children
.build()
#dyn_attrs
.into(),
};

Expand Down

0 comments on commit d0e0f5d

Please sign in to comment.