use js_sys::{Array, Function};
use wasm_bindgen::prelude::*;
use crate::{constructors::HTML_ELEMENT_CONSTRUCTOR, Bridge, CustomElement, GeneratedConstructor};
type MakeStruct = Closure<dyn FnMut(JsValue, Array) -> JsValue>;
#[wasm_bindgen(module = "/src/createCustomElement.js")]
extern "C" {
#[wasm_bindgen(js_name = createCustomElement)]
pub(self) fn _create_custom_element(
make_rust_struct: &MakeStruct,
attributes: Vec<String>,
constructor: &Function,
) -> Function;
}
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
pub struct CustomElementConfiguration<'a> {
pub element_constructor: &'a Function,
}
impl<'a> Default for CustomElementConfiguration<'a> {
fn default() -> Self {
Self {
element_constructor: &HTML_ELEMENT_CONSTRUCTOR,
}
}
}
pub struct CustomElementResult {
pub constructor: GeneratedConstructor,
pub closure: MakeStruct,
}
pub fn create_custom_element<
C: CustomElement + 'static,
F: FnMut(JsValue, Array) -> C + 'static,
>(
create_cutom_element: F,
attributes: Vec<String>,
) -> (MakeStruct, GeneratedConstructor) {
let config = CustomElementConfiguration::default();
create_custom_element_with_config(create_cutom_element, attributes, config)
}
pub fn create_custom_element_with_config<
C: CustomElement + 'static,
F: FnMut(JsValue, Array) -> C + 'static,
>(
mut create_cutom_element: F,
attributes: Vec<String>,
config: CustomElementConfiguration,
) -> (MakeStruct, GeneratedConstructor) {
let closure = Closure::new(move |element, args| {
let bridge: Bridge = create_cutom_element(element, args).into();
bridge.into()
});
let class = _create_custom_element(&closure, attributes, config.element_constructor);
(closure, GeneratedConstructor(class))
}