radix_leptos_primitives/components/
sheet.rs1use crate::utils::{merge_classes, generate_id};
2use leptos::callback::Callback;
3use leptos::children::Children;
4use leptos::prelude::*;
5
6#[derive(Debug, Clone, Copy, PartialEq)]
63pub enum SheetVariant {
64 Default,
65 Destructive,
66 Success,
67 Warning,
68 Info,
69}
70
71#[derive(Debug, Clone, Copy, PartialEq)]
72pub enum SheetPosition {
73 Left,
74 Right,
75 Top,
76 Bottom,
77}
78
79#[derive(Debug, Clone, Copy, PartialEq)]
80pub enum SheetSize {
81 Small,
82 Medium,
83 Large,
84 ExtraLarge,
85 Full,
86}
87
88impl SheetVariant {
89 pub fn as_str(&self) -> &'static str {
90 match self {
91 SheetVariant::Default => "default",
92 SheetVariant::Destructive => "destructive",
93 SheetVariant::Success => "success",
94 SheetVariant::Warning => "warning",
95 SheetVariant::Info => "info",
96 }
97 }
98}
99
100impl SheetPosition {
101 pub fn as_str(&self) -> &'static str {
102 match self {
103 SheetPosition::Left => "left",
104 SheetPosition::Right => "right",
105 SheetPosition::Top => "top",
106 SheetPosition::Bottom => "bottom",
107 }
108 }
109}
110
111impl SheetSize {
112 pub fn as_str(&self) -> &'static str {
113 match self {
114 SheetSize::Small => "sm",
115 SheetSize::Medium => "md",
116 SheetSize::Large => "lg",
117 SheetSize::ExtraLarge => "xl",
118 SheetSize::Full => "full",
119 }
120 }
121}
122
123#[component]
125pub fn Sheet(
126 #[prop(optional)] class: Option<String>,
127 #[prop(optional)] style: Option<String>,
128 #[prop(optional)] children: Option<Children>,
129 #[prop(optional)] open: Option<bool>,
130 #[prop(optional)] position: Option<SheetPosition>,
131 #[prop(optional)] size: Option<SheetSize>,
132 #[prop(optional)] onopen_change: Option<Callback<bool>>,
133) -> impl IntoView {
134 let open = open.unwrap_or(false);
135 let position = position.unwrap_or(SheetPosition::Right);
136 let size = size.unwrap_or(SheetSize::Medium);
137 let onopen_change = onopen_change.unwrap_or_else(|| Callback::new(|_| {}));
138
139 let class = merge_classes(vec!["sheet", position.as_str(), size.as_str()]);
140}
141
142#[component]
144pub fn SheetContent(
145 #[prop(optional)] class: Option<String>,
146 #[prop(optional)] style: Option<String>,
147 #[prop(optional)] children: Option<Children>,
148) -> impl IntoView {
149 let class = merge_classes(vec!["sheet-content", class.as_deref().unwrap_or("")]);
150
151 view! {
152 <div
153 class=class
154 style=style
155 >
156 {children.map(|c| c())}
157 </div>
158 }
159}
160
161#[component]
163pub fn SheetHeader(
164 #[prop(optional)] class: Option<String>,
165 #[prop(optional)] style: Option<String>,
166 #[prop(optional)] children: Option<Children>,
167) -> impl IntoView {
168 let class = merge_classes(vec!["sheet-header", class.as_deref().unwrap_or("")]);
169
170 view! {
171 <div
172 class=class
173 style=style
174 >
175 {children.map(|c| c())}
176 </div>
177 }
178}
179
180#[component]
182pub fn SheetTitle(
183 #[prop(optional)] class: Option<String>,
184 #[prop(optional)] style: Option<String>,
185 #[prop(optional)] children: Option<Children>,
186) -> impl IntoView {
187 let class = merge_classes(vec!["sheet-title", class.as_deref().unwrap_or("")]);
188
189 view! {
190 <h2
191 class=class
192 style=style
193 >
194 {children.map(|c| c())}
195 </h2>
196 }
197}
198
199#[component]
201pub fn SheetDescription(
202 #[prop(optional)] class: Option<String>,
203 #[prop(optional)] style: Option<String>,
204 #[prop(optional)] children: Option<Children>,
205) -> impl IntoView {
206 let class = merge_classes(vec!["sheet-description", class.as_deref().unwrap_or("")]);
207
208 view! {
209 <p
210 class=class
211 style=style
212 >
213 {children.map(|c| c())}
214 </p>
215 }
216}
217
218#[component]
220pub fn SheetBody(
221 #[prop(optional)] class: Option<String>,
222 #[prop(optional)] style: Option<String>,
223 #[prop(optional)] children: Option<Children>,
224) -> impl IntoView {
225 let class = merge_classes(vec!["sheet-body", class.as_deref().unwrap_or("")]);
226
227 view! {
228 <div
229 class=class
230 style=style
231 >
232 {children.map(|c| c())}
233 </div>
234 }
235}
236
237#[component]
239pub fn SheetFooter(
240 #[prop(optional)] class: Option<String>,
241 #[prop(optional)] style: Option<String>,
242 #[prop(optional)] children: Option<Children>,
243) -> impl IntoView {
244 let class = merge_classes(vec!["sheet-footer", class.as_deref().unwrap_or("")]);
245
246 view! {
247 <div
248 class=class
249 style=style
250 >
251 {children.map(|c| c())}
252 </div>
253 }
254}
255
256#[component]
258pub fn SheetClose(
259 #[prop(optional)] class: Option<String>,
260 #[prop(optional)] style: Option<String>,
261 #[prop(optional)] children: Option<Children>,
262 #[prop(optional)] on_click: Option<Callback<()>>,
263) -> impl IntoView {
264 let on_click = on_click.unwrap_or_else(|| Callback::new(|_| {}));
265
266 let class = merge_classes(vec!["sheet-close", class.as_deref().unwrap_or("")]);
267
268 view! {
269 <button
270 class=class
271 style=style
272 on:click=move |_| on_click.run(())
273 aria-label="Close sheet"
274 >
275 {children.map(|c| c())}
276 </button>
277 }
278}
279
280#[cfg(test)]
281mod tests {
282 use proptest::prelude::*;
283
284 #[test]
285 fn test_sheet_component_creation() {}
286
287 #[test]
288 fn test_sheet_with_position_component_creation() {}
289
290 proptest! {
291 #[test]
292 fn test_sheet_props(___class in ".*", ___style in ".*") {
293
294 }
295
296 #[test]
297 fn test_sheetopen_state(__open: bool, ___position_index in 0..4usize, ___size_index in 0..5usize) {
298
299 }
300
301 #[test]
302 fn test_sheet_positions(___position_index in 0..4usize) {
303
304 }
305
306 #[test]
307 fn test_sheet_sizes(___size_index in 0..5usize) {
308
309 }
310
311 #[test]
312 fn test_sheet_content_props(___class in ".*", ___style in ".*") {
313
314 }
315
316 #[test]
317 fn test_sheet_header_props(___class in ".*", ___style in ".*") {
318
319 }
320
321 #[test]
322 fn test_sheet_title_props(___class in ".*", ___style in ".*") {
323
324 }
325
326 #[test]
327 fn test_sheet_description_props(___class in ".*", ___style in ".*") {
328
329 }
330
331 #[test]
332 fn test_sheet_body_props(___class in ".*", ___style in ".*") {
333
334 }
335
336 #[test]
337 fn test_sheet_footer_props(___class in ".*", ___style in ".*") {
338
339 }
340
341 #[test]
342 fn test_sheet_close_props(___class in ".*", ___style in ".*") {
343
344 }
345 }
346}