1use crate::theme::{Theme, ThemeProvider, ThemeTokens};
2use dioxus::prelude::*;
3
4#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
6pub enum ComponentSize {
7 Small,
8 #[default]
9 Middle,
10 Large,
11}
12
13#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
15pub enum Locale {
16 #[default]
18 ZhCN,
19 EnUS,
21}
22
23#[derive(Clone, Debug, PartialEq)]
28pub struct ConfigContextValue {
29 pub size: ComponentSize,
30 pub disabled: bool,
31 pub prefix_cls: String,
32 pub locale: Locale,
33}
34
35impl Default for ConfigContextValue {
36 fn default() -> Self {
37 Self {
38 size: ComponentSize::Middle,
39 disabled: false,
40 prefix_cls: "adui".to_string(),
41 locale: Locale::ZhCN,
42 }
43 }
44}
45
46#[derive(Props, Clone, PartialEq)]
48pub struct ConfigProviderProps {
49 #[props(optional)]
51 pub size: Option<ComponentSize>,
52 #[props(optional)]
55 pub disabled: Option<bool>,
56 #[props(optional)]
58 pub prefix_cls: Option<String>,
59 #[props(optional)]
62 pub locale: Option<Locale>,
63 #[props(optional)]
66 pub theme: Option<Theme>,
67 pub children: Element,
68}
69
70#[component]
73pub fn ConfigProvider(props: ConfigProviderProps) -> Element {
74 let parent = try_use_context::<ConfigContextValue>().unwrap_or_default();
75
76 let value = ConfigContextValue {
77 size: props.size.unwrap_or(parent.size),
78 disabled: props.disabled.unwrap_or(parent.disabled),
79 prefix_cls: props.prefix_cls.clone().unwrap_or(parent.prefix_cls),
80 locale: props.locale.unwrap_or(parent.locale),
81 };
82
83 use_context_provider(|| value.clone());
87
88 rsx! {
89 ThemeProvider { theme: props.theme.clone(), {props.children} }
90 }
91}
92
93pub fn use_config() -> ConfigContextValue {
95 try_use_context::<ConfigContextValue>().unwrap_or_default()
96}
97
98pub fn control_heights(config: &ConfigContextValue, tokens: &ThemeTokens) -> (f32, f32, f32) {
102 let base = tokens.control_height;
103 let small = tokens.control_height_small;
104 let large = tokens.control_height_large;
105 match config.size {
106 ComponentSize::Small => (small, small, base),
107 ComponentSize::Large => (large, large, base),
108 ComponentSize::Middle => (base, small, large),
109 }
110}
111
112#[cfg(test)]
113mod tests {
114 use super::*;
115 use crate::theme::ThemeTokens;
116
117 #[test]
118 fn component_size_default() {
119 assert_eq!(ComponentSize::default(), ComponentSize::Middle);
120 }
121
122 #[test]
123 fn component_size_all_variants() {
124 assert_eq!(ComponentSize::Small, ComponentSize::Small);
125 assert_eq!(ComponentSize::Middle, ComponentSize::Middle);
126 assert_eq!(ComponentSize::Large, ComponentSize::Large);
127 assert_ne!(ComponentSize::Small, ComponentSize::Middle);
128 assert_ne!(ComponentSize::Small, ComponentSize::Large);
129 assert_ne!(ComponentSize::Middle, ComponentSize::Large);
130 }
131
132 #[test]
133 fn component_size_clone() {
134 let original = ComponentSize::Small;
135 let cloned = original;
136 assert_eq!(original, cloned);
137 }
138
139 #[test]
140 fn locale_default() {
141 assert_eq!(Locale::default(), Locale::ZhCN);
142 }
143
144 #[test]
145 fn locale_all_variants() {
146 assert_eq!(Locale::ZhCN, Locale::ZhCN);
147 assert_eq!(Locale::EnUS, Locale::EnUS);
148 assert_ne!(Locale::ZhCN, Locale::EnUS);
149 }
150
151 #[test]
152 fn locale_clone() {
153 let original = Locale::ZhCN;
154 let cloned = original;
155 assert_eq!(original, cloned);
156 }
157
158 #[test]
159 fn config_context_value_default() {
160 let config = ConfigContextValue::default();
161 assert_eq!(config.size, ComponentSize::Middle);
162 assert_eq!(config.disabled, false);
163 assert_eq!(config.prefix_cls, "adui");
164 assert_eq!(config.locale, Locale::ZhCN);
165 }
166
167 #[test]
168 fn config_context_value_clone() {
169 let original = ConfigContextValue {
170 size: ComponentSize::Large,
171 disabled: true,
172 prefix_cls: "custom".to_string(),
173 locale: Locale::EnUS,
174 };
175 let cloned = original.clone();
176 assert_eq!(original, cloned);
177 }
178
179 #[test]
180 fn control_heights_small() {
181 let tokens = ThemeTokens::light();
182 let config = ConfigContextValue {
183 size: ComponentSize::Small,
184 disabled: false,
185 prefix_cls: "adui".to_string(),
186 locale: Locale::ZhCN,
187 };
188 let (small, middle, large) = control_heights(&config, &tokens);
189 assert_eq!(small, tokens.control_height_small);
190 assert_eq!(middle, tokens.control_height_small);
191 assert_eq!(large, tokens.control_height);
192 }
193
194 #[test]
195 fn control_heights_middle() {
196 let tokens = ThemeTokens::light();
197 let config = ConfigContextValue {
198 size: ComponentSize::Middle,
199 disabled: false,
200 prefix_cls: "adui".to_string(),
201 locale: Locale::ZhCN,
202 };
203 let (small, middle, large) = control_heights(&config, &tokens);
204 assert_eq!(small, tokens.control_height);
205 assert_eq!(middle, tokens.control_height_small);
206 assert_eq!(large, tokens.control_height_large);
207 }
208
209 #[test]
210 fn control_heights_large() {
211 let tokens = ThemeTokens::light();
212 let config = ConfigContextValue {
213 size: ComponentSize::Large,
214 disabled: false,
215 prefix_cls: "adui".to_string(),
216 locale: Locale::ZhCN,
217 };
218 let (small, middle, large) = control_heights(&config, &tokens);
219 assert_eq!(small, tokens.control_height_large);
220 assert_eq!(middle, tokens.control_height_large);
221 assert_eq!(large, tokens.control_height);
222 }
223}