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
use std::rc::Rc;
use yew::prelude::*;

use crate::prelude::OptionalHtml;

#[derive(Debug, Clone, PartialEq, Properties)]
pub struct ToggleGroupProperties {
    /// Content rendered inside the toggle group
    #[prop_or_default]
    pub children: ChildrenWithProps<ToggleGroupItem>,
    /// Additional classes added to the toggle group
    #[prop_or_default]
    pub class: Classes,
    /// Modifies the toggle group to include compact styling
    #[prop_or_default]
    pub compact: bool,
    /// Disable all toggle group items under this component
    #[prop_or_default]
    pub all_disabled: bool,
}

#[function_component(ToggleGroup)]
pub fn toggle_group(props: &ToggleGroupProperties) -> Html {
    let mut class = classes!(props.class.clone(), "pf-v5-c-toggle-group");
    if props.compact {
        class.push("pf-m-compact");
    };
    html! {
        <div {class} role="group">
            {for props.children.iter().map(|mut item| {
                let item_props = Rc::make_mut(&mut item.props);
                item_props.disabled |= props.all_disabled;
                item
            })}
        </div>
    }
}

#[derive(Debug, Clone, PartialEq, Properties)]
pub struct ToggleGroupItemProperties {
    /// Text rendered inside the toggle group item
    #[prop_or_default]
    pub text: OptionalHtml,
    /// Icon rendered inside the toggle group item
    #[prop_or_default]
    pub icon: OptionalHtml,
    /// Additional classes added to the toggle group item
    #[prop_or_default]
    pub class: Classes,
    /// Flag indicating if the toggle group item is disabled
    #[prop_or_default]
    pub disabled: bool,
    /// Flag indicating if the toggle group item is selected
    #[prop_or_default]
    pub selected: bool,
    /// A callback for when the toggle group item selection changes
    #[prop_or_default]
    pub onchange: Callback<()>,
    /// A reference to the button which emits the event for onchange.
    #[prop_or_default]
    pub button_ref: NodeRef,
}

#[function_component(ToggleGroupItem)]
pub fn toggle_group_item(props: &ToggleGroupItemProperties) -> Html {
    let mut class = classes!(props.class.clone(), "pf-v5-c-toggle-group__item");
    let mut button_class = classes!("pf-v5-c-toggle-group__button");
    if props.selected {
        class.push("pf-m-selected");
        button_class.push("pf-m-selected");
    }
    let onclick = use_callback(props.onchange.clone(), |_, onchange| onchange.emit(()));
    html! {
        <div {class}>
            <button
                type="button"
                class={button_class}
                {onclick}
                disabled={props.disabled}
                ref={props.button_ref.clone()}
            >
                if let Some(icon) = (*props.icon).as_ref() {
                    <ToggleGroupItemElement
                        variant={ToggleGroupItemElementVariant::Icon(icon.clone())}
                    />
                }
                if let Some(text) = (*props.text).as_ref() {
                    <ToggleGroupItemElement
                        variant={ToggleGroupItemElementVariant::Text(text.clone())}
                    />
                }
            </button>
        </div>
    }
}

#[derive(Debug, Clone, PartialEq)]
pub enum ToggleGroupItemElementVariant {
    Icon(Html),
    Text(Html),
}

#[derive(Debug, Clone, PartialEq, Properties)]
pub struct ToggleGroupItemElementProperties {
    #[prop_or_default]
    variant: Option<ToggleGroupItemElementVariant>,
}

#[function_component(ToggleGroupItemElement)]
pub fn toggle_group_item_element(props: &ToggleGroupItemElementProperties) -> Html {
    let (class, children) = props
        .variant
        .as_ref()
        .map(|v| match v {
            ToggleGroupItemElementVariant::Icon(children) => {
                ("pf-v5-c-toggle-group__icon", children)
            }
            ToggleGroupItemElementVariant::Text(children) => {
                ("pf-v5-c-toggle-group__text", children)
            }
        })
        .unzip();
    html! {
        <span {class} id="foo">
            if let Some(children) = children {
                {(*children).clone()}
            }
        </span>
    }
}