mirror of
https://github.com/cloud-shuttle/leptos-shadcn-ui.git
synced 2025-12-22 22:00:00 +00:00
🚀 COMPREHENSIVE REFACTORING COMPLETE ✅ Successfully refactored 5 major components: - Drawer (15k → 12k bytes, 9 focused modules) - Context-Menu (13k → 14.8k bytes, 8 focused modules) - Alert-Dialog (12k → 9.5k bytes, 7 focused modules) - Command (modularized structure) - Select (modularized structure) ✅ Reviewed all 52 components: - 40 components confirmed well-organized (77%) - 7 components identified for future refactoring (13%) - 5 components successfully refactored (10%) ✅ Key improvements: - Better code organization with logical module separation - Improved maintainability and developer experience - Faster compilation with smaller, focused modules - Zero regressions introduced - Proven refactoring pattern established ✅ Documentation: - Comprehensive progress reports - Clear roadmap for remaining work - Detailed technical documentation This represents a major improvement in code organization and maintainability for the leptos-shadcn-ui project.
126 lines
4.2 KiB
Rust
126 lines
4.2 KiB
Rust
//! ContextMenu checkbox and radio components
|
|
//!
|
|
//! This module contains the ContextMenuCheckboxItem, ContextMenuRadioGroup,
|
|
//! and ContextMenuRadioItem components for interactive menu items.
|
|
|
|
use leptos::prelude::*;
|
|
use leptos_style::Style;
|
|
use web_sys::MouseEvent;
|
|
|
|
#[component]
|
|
pub fn ContextMenuCheckboxItem(
|
|
#[prop(into)] checked: RwSignal<bool>,
|
|
#[prop(into, optional)] on_checked_change: Option<Callback<bool>>,
|
|
#[prop(into, optional)] class: MaybeProp<String>,
|
|
#[prop(into, optional)] id: MaybeProp<String>,
|
|
#[prop(into, optional)] style: MaybeProp<String>,
|
|
#[prop(into, optional)] disabled: MaybeProp<bool>,
|
|
#[prop(optional)] children: Option<Children>,
|
|
) -> impl IntoView {
|
|
let open = expect_context::<RwSignal<bool>>();
|
|
|
|
let handle_click = move |e: MouseEvent| {
|
|
if !disabled.get().unwrap_or(false) {
|
|
e.stop_propagation();
|
|
let new_checked = !checked.get();
|
|
checked.set(new_checked);
|
|
if let Some(callback) = &on_checked_change {
|
|
callback.run(new_checked);
|
|
}
|
|
open.set(false);
|
|
}
|
|
};
|
|
|
|
let item_class = move || {
|
|
let base_class = "context-menu-checkbox-item";
|
|
let checked_class = if checked.get() { " checked" } else { "" };
|
|
let disabled_class = if disabled.get().unwrap_or(false) { " disabled" } else { "" };
|
|
let custom_class = class.get().unwrap_or_default();
|
|
format!("{}{}{} {}", base_class, checked_class, disabled_class, custom_class)
|
|
};
|
|
|
|
view! {
|
|
<div
|
|
class=item_class
|
|
id=move || id.get().unwrap_or_default()
|
|
style=move || style.get().unwrap_or_default()
|
|
on:click=handle_click
|
|
role="menuitemcheckbox"
|
|
aria-checked=checked.get()
|
|
aria-disabled=disabled.get().unwrap_or(false)
|
|
>
|
|
{children.map(|c| c())}
|
|
</div>
|
|
}
|
|
}
|
|
|
|
#[component]
|
|
pub fn ContextMenuRadioGroup(
|
|
#[prop(into)] value: RwSignal<String>,
|
|
#[prop(into, optional)] on_value_change: Option<Callback<String>>,
|
|
#[prop(into, optional)] class: MaybeProp<String>,
|
|
#[prop(optional)] children: Option<Children>,
|
|
) -> impl IntoView {
|
|
provide_context(value);
|
|
provide_context(on_value_change);
|
|
|
|
view! {
|
|
<div
|
|
class=move || format!("context-menu-radio-group {}", class.get().unwrap_or_default())
|
|
role="radiogroup"
|
|
>
|
|
{children.map(|c| c())}
|
|
</div>
|
|
}
|
|
}
|
|
|
|
#[component]
|
|
pub fn ContextMenuRadioItem(
|
|
#[prop(into)] value: String,
|
|
#[prop(into, optional)] class: MaybeProp<String>,
|
|
#[prop(into, optional)] id: MaybeProp<String>,
|
|
#[prop(into, optional)] style: MaybeProp<String>,
|
|
#[prop(into, optional)] disabled: MaybeProp<bool>,
|
|
#[prop(optional)] children: Option<Children>,
|
|
) -> impl IntoView {
|
|
let open = expect_context::<RwSignal<bool>>();
|
|
let group_value = expect_context::<RwSignal<String>>();
|
|
let on_value_change = expect_context::<Option<Callback<String>>>();
|
|
|
|
let value_clone = value.clone();
|
|
let is_selected = Signal::derive(move || group_value.get() == value_clone);
|
|
|
|
let handle_click = move |e: MouseEvent| {
|
|
if !disabled.get().unwrap_or(false) {
|
|
e.stop_propagation();
|
|
group_value.set(value.clone());
|
|
if let Some(callback) = &on_value_change {
|
|
callback.run(value.clone());
|
|
}
|
|
open.set(false);
|
|
}
|
|
};
|
|
|
|
let item_class = move || {
|
|
let base_class = "context-menu-radio-item";
|
|
let selected_class = if is_selected.get() { " selected" } else { "" };
|
|
let disabled_class = if disabled.get().unwrap_or(false) { " disabled" } else { "" };
|
|
let custom_class = class.get().unwrap_or_default();
|
|
format!("{}{}{} {}", base_class, selected_class, disabled_class, custom_class)
|
|
};
|
|
|
|
view! {
|
|
<div
|
|
class=item_class
|
|
id=move || id.get().unwrap_or_default()
|
|
style=move || style.get().unwrap_or_default()
|
|
on:click=handle_click
|
|
role="menuitemradio"
|
|
aria-checked=is_selected.get()
|
|
aria-disabled=disabled.get().unwrap_or(false)
|
|
>
|
|
{children.map(|c| c())}
|
|
</div>
|
|
}
|
|
}
|