mirror of
https://github.com/zaphar/wasm-web-components.git
synced 2025-07-21 19:40:30 -04:00
Allow you to configure which element you inherit from.
This commit is contained in:
parent
2b00383712
commit
5ba459bcb6
@ -33,14 +33,23 @@ fn expand_crate_ref(name: &str, path: Path) -> syn::Path {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct AttributeConfig {
|
||||||
|
class_name: Literal,
|
||||||
|
element_name: Literal,
|
||||||
|
observed_attributes: Literal,
|
||||||
|
observed_events: Literal,
|
||||||
|
base_class: Literal,
|
||||||
|
}
|
||||||
|
|
||||||
fn get_class_and_element_names(
|
fn get_class_and_element_names(
|
||||||
args: Vec<NestedMeta>,
|
args: Vec<NestedMeta>,
|
||||||
struct_name: &Ident,
|
struct_name: &Ident,
|
||||||
) -> (Literal, Literal, Literal, Literal) {
|
) -> AttributeConfig {
|
||||||
let mut class_name = None;
|
let mut class_name = None;
|
||||||
let mut element_name = None;
|
let mut element_name = None;
|
||||||
let mut observed_attributes = None;
|
let mut observed_attributes = None;
|
||||||
let mut observed_events = None;
|
let mut observed_events = None;
|
||||||
|
let mut base_class = None;
|
||||||
for arg in args {
|
for arg in args {
|
||||||
if let NestedMeta::Meta(Meta::NameValue(nv)) = arg {
|
if let NestedMeta::Meta(Meta::NameValue(nv)) = arg {
|
||||||
if nv.path.is_ident("class_name") {
|
if nv.path.is_ident("class_name") {
|
||||||
@ -59,6 +68,10 @@ fn get_class_and_element_names(
|
|||||||
if let Lit::Str(nm) = nv.lit {
|
if let Lit::Str(nm) = nv.lit {
|
||||||
observed_events = Some(nm);
|
observed_events = Some(nm);
|
||||||
}
|
}
|
||||||
|
} else if nv.path.is_ident("base_clas") {
|
||||||
|
if let Lit::Str(nm) = nv.lit {
|
||||||
|
base_class = Some(nm);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -74,6 +87,7 @@ fn get_class_and_element_names(
|
|||||||
LitStr::new(&class_kebab, Span::call_site()).token()
|
LitStr::new(&class_kebab, Span::call_site()).token()
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
let base_class = base_class.unwrap_or_else(|| LitStr::new("HTMLElement", Span::call_site())).token();
|
||||||
|
|
||||||
let observed_attributes = observed_attributes
|
let observed_attributes = observed_attributes
|
||||||
.map(|n| n.token())
|
.map(|n| n.token())
|
||||||
@ -81,7 +95,13 @@ fn get_class_and_element_names(
|
|||||||
let observed_events = observed_events
|
let observed_events = observed_events
|
||||||
.map(|n| n.token())
|
.map(|n| n.token())
|
||||||
.unwrap_or_else(|| LitStr::new("[]", Span::call_site()).token());
|
.unwrap_or_else(|| LitStr::new("[]", Span::call_site()).token());
|
||||||
(class_name, element_name, observed_attributes, observed_events)
|
AttributeConfig {
|
||||||
|
class_name,
|
||||||
|
element_name,
|
||||||
|
observed_attributes,
|
||||||
|
observed_events,
|
||||||
|
base_class,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expand_component_def(
|
fn expand_component_def(
|
||||||
@ -107,9 +127,15 @@ fn expand_component_def(
|
|||||||
fn expand_wc_struct_trait_shim(
|
fn expand_wc_struct_trait_shim(
|
||||||
struct_name: &Ident,
|
struct_name: &Ident,
|
||||||
once_name: &Ident,
|
once_name: &Ident,
|
||||||
observed_attrs: Literal,
|
config: AttributeConfig,
|
||||||
observed_events: Literal,
|
|
||||||
) -> syn::ItemImpl {
|
) -> syn::ItemImpl {
|
||||||
|
let AttributeConfig {
|
||||||
|
class_name: _,
|
||||||
|
element_name: _,
|
||||||
|
observed_attributes,
|
||||||
|
observed_events,
|
||||||
|
base_class,
|
||||||
|
} = config;
|
||||||
let trait_path = expand_crate_ref("wasm-web-component", parse_quote!(WebComponentDef));
|
let trait_path = expand_crate_ref("wasm-web-component", parse_quote!(WebComponentDef));
|
||||||
let handle_path = expand_crate_ref("wasm-web-component", parse_quote!(WebComponentHandle));
|
let handle_path = expand_crate_ref("wasm-web-component", parse_quote!(WebComponentHandle));
|
||||||
parse_quote! {
|
parse_quote! {
|
||||||
@ -139,7 +165,7 @@ fn expand_wc_struct_trait_shim(
|
|||||||
return Err("Custom Element has already been defined".into());
|
return Err("Custom Element has already been defined".into());
|
||||||
}
|
}
|
||||||
let body = format!(
|
let body = format!(
|
||||||
"class {name} extends HTMLElement {{
|
"class {name} extends {base_class} {{
|
||||||
constructor() {{
|
constructor() {{
|
||||||
super();
|
super();
|
||||||
this._impl = impl();
|
this._impl = impl();
|
||||||
@ -189,8 +215,9 @@ var element = customElements.get(\"{element_name}\");
|
|||||||
return element;",
|
return element;",
|
||||||
name = Self::class_name(),
|
name = Self::class_name(),
|
||||||
element_name = Self::element_name(),
|
element_name = Self::element_name(),
|
||||||
observed_attributes = #observed_attrs,
|
observed_attributes = #observed_attributes,
|
||||||
observed_events = #observed_events,
|
observed_events = #observed_events,
|
||||||
|
base_class = #base_class,
|
||||||
);
|
);
|
||||||
let fun = js_sys::Function::new_with_args("impl", &body);
|
let fun = js_sys::Function::new_with_args("impl", &body);
|
||||||
let f: Box<dyn FnMut() -> Self> = Box::new(|| {
|
let f: Box<dyn FnMut() -> Self> = Box::new(|| {
|
||||||
@ -295,19 +322,16 @@ fn expand_binding(struct_name: &Ident) -> syn::ItemImpl {
|
|||||||
|
|
||||||
fn expand_web_component_struct(
|
fn expand_web_component_struct(
|
||||||
item_struct: ItemStruct,
|
item_struct: ItemStruct,
|
||||||
class_name: Literal,
|
config: AttributeConfig,
|
||||||
element_name: Literal,
|
|
||||||
observed_attributes: Literal,
|
|
||||||
observed_events: Literal,
|
|
||||||
) -> TokenStream {
|
) -> TokenStream {
|
||||||
let struct_name = item_struct.ident.clone();
|
let struct_name = item_struct.ident.clone();
|
||||||
let struct_once_name = Ident::new(
|
let struct_once_name = Ident::new(
|
||||||
&(struct_name.to_string().to_snake_case().to_uppercase() + "_ONCE"),
|
&(struct_name.to_string().to_snake_case().to_uppercase() + "_ONCE"),
|
||||||
Span::call_site(),
|
Span::call_site(),
|
||||||
);
|
);
|
||||||
let component_def = expand_component_def(&struct_name, &class_name, &element_name);
|
let component_def = expand_component_def(&struct_name, &config.class_name, &config.element_name);
|
||||||
let non_wasm_impl =
|
let non_wasm_impl =
|
||||||
expand_wc_struct_trait_shim(&struct_name, &struct_once_name, observed_attributes, observed_events);
|
expand_wc_struct_trait_shim(&struct_name, &struct_once_name, config);
|
||||||
let wasm_shim = expand_wasm_shim(&struct_name);
|
let wasm_shim = expand_wasm_shim(&struct_name);
|
||||||
let binding_trait = expand_binding(&struct_name);
|
let binding_trait = expand_binding(&struct_name);
|
||||||
let expanded = quote! {
|
let expanded = quote! {
|
||||||
@ -369,10 +393,10 @@ pub fn web_component(attr: TokenStream, item: TokenStream) -> TokenStream {
|
|||||||
let args = parse_macro_input!(attr as AttributeArgs);
|
let args = parse_macro_input!(attr as AttributeArgs);
|
||||||
let item_struct = parse_macro_input!(item as ItemStruct);
|
let item_struct = parse_macro_input!(item as ItemStruct);
|
||||||
|
|
||||||
let (class_name, element_name, observed_attributes, observed_events) =
|
let config =
|
||||||
get_class_and_element_names(args, &item_struct.ident);
|
get_class_and_element_names(args, &item_struct.ident);
|
||||||
|
|
||||||
expand_web_component_struct(item_struct, class_name, element_name, observed_attributes, observed_events)
|
expand_web_component_struct(item_struct, config)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates the neccessary Rust and Javascript shims for rendering an HtmlTemplateElement
|
/// Creates the neccessary Rust and Javascript shims for rendering an HtmlTemplateElement
|
||||||
|
@ -25,12 +25,17 @@ use web_sys::{window, Element, Event, HtmlElement, Window};
|
|||||||
///
|
///
|
||||||
/// ## Example
|
/// ## Example
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```ignore
|
||||||
|
/// use web_sys::*;
|
||||||
|
/// use wasm_bindgen::*;
|
||||||
|
/// use wasm_web_component::{web_component, WebComponent, WebComponentHandle, WebComponentDef, WebComponentBinding};
|
||||||
|
///
|
||||||
/// #[web_component(
|
/// #[web_component(
|
||||||
/// class_name = "MyElement",
|
/// class_name = "MyElement",
|
||||||
/// element_name = "my-element",
|
/// element_name = "my-element",
|
||||||
/// observed_attrs = "['class']"
|
/// observed_attrs = "['class']",
|
||||||
/// observed_events = "['click']"
|
/// observed_events = "['click']",
|
||||||
|
/// base_class = "HTMLElement"
|
||||||
/// )]
|
/// )]
|
||||||
/// pub struct MyElementImpl {}
|
/// pub struct MyElementImpl {}
|
||||||
///
|
///
|
||||||
@ -69,7 +74,7 @@ use web_sys::{window, Element, Event, HtmlElement, Window};
|
|||||||
/// element.append_child(&node).unwrap();
|
/// element.append_child(&node).unwrap();
|
||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
/// fn handle_event(&self, element: &HtmlElement, event: &Event)) {
|
/// fn handle_event(&self, element: &HtmlElement, event: &Event) {
|
||||||
/// // handle this event
|
/// // handle this event
|
||||||
/// }
|
/// }
|
||||||
/// }
|
/// }
|
||||||
@ -98,7 +103,10 @@ pub use wasm_web_component_macros::web_component;
|
|||||||
/// if the template has not been defined yet `None` will get returned.
|
/// if the template has not been defined yet `None` will get returned.
|
||||||
///
|
///
|
||||||
/// ## Example usage
|
/// ## Example usage
|
||||||
/// ```rust
|
/// ```ignore
|
||||||
|
/// use wasm_web_component::*;
|
||||||
|
/// use wasm_bindgen::*;
|
||||||
|
/// # #[cfg(feature = "HtmlTemplateElement")]
|
||||||
/// #[template_element]
|
/// #[template_element]
|
||||||
/// pub struct MyTemplate ();
|
/// pub struct MyTemplate ();
|
||||||
/// impl TemplateElementRender for MyTemplate {
|
/// impl TemplateElementRender for MyTemplate {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user