1use std::marker::PhantomData;
4use std::rc::Rc;
5
6use implicit_clone::unsync::IArray;
7use implicit_clone::ImplicitClone;
8use yew::html::ChildrenRenderer;
9
10pub fn into_node_iter<IT, T, R>(it: IT) -> impl Iterator<Item = R>
12where
13 IT: IntoIterator<Item = T>,
14 T: Into<R>,
15{
16 it.into_iter().map(|n| n.into())
17}
18
19fn array_single<T: ImplicitClone + 'static>(singl: T) -> IArray<T> {
20 IArray::Rc(Rc::new([singl]))
21}
22
23#[derive(Debug)]
25pub struct NodeSeq<IN, OUT: ImplicitClone + 'static>(IArray<OUT>, PhantomData<IN>);
26
27impl<IN: Into<OUT>, OUT: ImplicitClone + 'static> From<IN> for NodeSeq<IN, OUT> {
28 fn from(val: IN) -> Self {
29 Self(array_single(val.into()), PhantomData)
30 }
31}
32
33impl<IN: Into<OUT>, OUT: ImplicitClone + 'static> From<Option<IN>> for NodeSeq<IN, OUT> {
34 fn from(val: Option<IN>) -> Self {
35 Self(
36 val.map(|s| array_single(s.into())).unwrap_or_default(),
37 PhantomData,
38 )
39 }
40}
41
42impl<IN: Into<OUT>, OUT: ImplicitClone + 'static> From<Vec<IN>> for NodeSeq<IN, OUT> {
43 fn from(mut val: Vec<IN>) -> Self {
44 if val.len() == 1 {
45 let item = val.pop().unwrap();
46 Self(array_single(item.into()), PhantomData)
47 } else {
48 Self(val.into_iter().map(|x| x.into()).collect(), PhantomData)
49 }
50 }
51}
52
53impl<IN: Into<OUT> + ImplicitClone, OUT: ImplicitClone + 'static> From<IArray<IN>>
54 for NodeSeq<IN, OUT>
55{
56 fn from(val: IArray<IN>) -> Self {
57 Self(val.into_iter().map(|x| x.into()).collect(), PhantomData)
58 }
59}
60
61impl<IN: Into<OUT> + ImplicitClone, OUT: ImplicitClone + 'static> From<&IArray<IN>>
62 for NodeSeq<IN, OUT>
63{
64 fn from(val: &IArray<IN>) -> Self {
65 Self(
66 val.clone().into_iter().map(|x| x.into()).collect(),
67 PhantomData,
68 )
69 }
70}
71
72impl<IN: Into<OUT> + Clone, OUT: ImplicitClone + 'static> From<&ChildrenRenderer<IN>>
73 for NodeSeq<IN, OUT>
74{
75 fn from(val: &ChildrenRenderer<IN>) -> Self {
76 Self(val.iter().map(|x| x.into()).collect(), PhantomData)
77 }
78}
79
80impl<IN, OUT: ImplicitClone + 'static> IntoIterator for NodeSeq<IN, OUT> {
81 type IntoIter = implicit_clone::unsync::IArrayIntoIter<Self::Item>;
82 type Item = OUT;
83
84 fn into_iter(self) -> Self::IntoIter {
85 self.0.into_iter()
86 }
87}
88
89#[doc(hidden)]
92pub fn __ensure_type<T>(_: T) {}
93
94pub fn print_node(n: &web_sys::Node) -> String {
96 use wasm_bindgen::JsCast;
97
98 match n.dyn_ref::<web_sys::Element>() {
99 Some(el) => el.outer_html(),
100 None => n.text_content().unwrap_or_default(),
101 }
102}
103
104pub(crate) trait RcExt<T: Clone> {
106 fn unwrap_or_clone(this: Self) -> T;
107}
108
109impl<T: Clone> RcExt<T> for std::rc::Rc<T> {
110 fn unwrap_or_clone(this: Self) -> T {
111 std::rc::Rc::try_unwrap(this).unwrap_or_else(|rc| (*rc).clone())
112 }
113}