1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
use leptos_dom::Fragment;
use std::rc::Rc;

/// The most common type for the `children` property on components,
/// which can only be called once.
pub type Children = Box<dyn FnOnce() -> Fragment>;

/// A type for the `children` property on components that can be called
/// more than once.
pub type ChildrenFn = Rc<dyn Fn() -> Fragment>;

/// A type for the `children` property on components that can be called
/// more than once, but may mutate the children.
pub type ChildrenFnMut = Box<dyn FnMut() -> Fragment>;

// This is to still support components that accept `Box<dyn Fn() -> Fragment>` as a children.
type BoxedChildrenFn = Box<dyn Fn() -> Fragment>;

/// This trait can be used when constructing a component that takes children without needing
/// to know exactly what children type the component expects. This is used internally by the
/// `view!` macro implementation, and can also be used explicitly when using the builder syntax.
///
/// # Examples
///
/// ## Without ToChildren
///
/// Without [ToChildren], consumers need to explicitly provide children using the type expected
/// by the component. For example, [Provider][crate::Provider]'s children need to wrapped in
/// a [Box], while [Show][crate::Show]'s children need to be wrapped in an [Rc].
///
/// ```
/// # use leptos::{ProviderProps, ShowProps};
/// # use leptos_dom::html::p;
/// # use leptos_dom::IntoView;
/// # use leptos_macro::component;
/// # use std::rc::Rc;
/// #
/// #[component]
/// fn App() -> impl IntoView {
///     (
///         ProviderProps::builder()
///             .children(Box::new(|| p().child("Foo").into_view().into()))
///             // ...
/// #           .value("Foo")
/// #           .build(),
///         ShowProps::builder()
///             .children(Rc::new(|| p().child("Foo").into_view().into()))
///             // ...
/// #           .when(|| true)
/// #           .fallback(|| p().child("foo"))
/// #           .build(),
///     )
/// }
/// ```
///
/// ## With ToChildren
///
/// With [ToChildren], consumers don't need to know exactly which type a component uses for
/// its children.
///
/// ```
/// # use leptos::{ProviderProps, ShowProps};
/// # use leptos_dom::html::p;
/// # use leptos_dom::IntoView;
/// # use leptos_macro::component;
/// # use std::rc::Rc;
/// # use leptos::ToChildren;
/// #
/// #[component]
/// fn App() -> impl IntoView {
///     (
///         ProviderProps::builder()
///             .children(ToChildren::to_children(|| {
///                 p().child("Foo").into_view().into()
///             }))
///             // ...
/// #           .value("Foo")
/// #           .build(),
///         ShowProps::builder()
///             .children(ToChildren::to_children(|| {
///                 p().child("Foo").into_view().into()
///             }))
///             // ...
/// #           .when(|| true)
/// #           .fallback(|| p().child("foo"))
/// #           .build(),
///     )
/// }
pub trait ToChildren<F> {
    /// Convert the provided type to (generally a closure) to Self (generally a "children" type,
    /// e.g., [Children]). See the implementations to see exactly which input types are supported
    /// and which "children" type they are converted to.
    fn to_children(f: F) -> Self;
}

impl<F> ToChildren<F> for Children
where
    F: FnOnce() -> Fragment + 'static,
{
    #[inline]
    fn to_children(f: F) -> Self {
        Box::new(f)
    }
}

impl<F> ToChildren<F> for ChildrenFn
where
    F: Fn() -> Fragment + 'static,
{
    #[inline]
    fn to_children(f: F) -> Self {
        Rc::new(f)
    }
}

impl<F> ToChildren<F> for ChildrenFnMut
where
    F: FnMut() -> Fragment + 'static,
{
    #[inline]
    fn to_children(f: F) -> Self {
        Box::new(f)
    }
}

impl<F> ToChildren<F> for BoxedChildrenFn
where
    F: Fn() -> Fragment + 'static,
{
    #[inline]
    fn to_children(f: F) -> Self {
        Box::new(f)
    }
}