Add major comparisons #45

Merged
BobdaFett merged 4 commits from feature/categorize-chips into main 2026-01-14 03:23:57 +00:00
3 changed files with 34 additions and 21 deletions
Showing only changes of commit c1f0c0cb81 - Show all commits

No files matched your search

+4 -4
View File
@@ -41,11 +41,11 @@ pub fn Checkbox(
#[prop(into)] value: Signal<String>, #[prop(into)] value: Signal<String>,
/// The name of the checkbox. This is used to group checkboxes together, so every checkbox /// The name of the checkbox. This is used to group checkboxes together, so every checkbox
/// in a group should have the same name. /// in a group should have the same name.
#[prop(into)] name: String, #[prop(into)] name: Signal<String>,
/// A [`Signal`] indicating whether the checkbox is disabled. /// A [`Signal`] indicating whether the checkbox is disabled.
#[prop(into)] disabled: Signal<bool>, #[prop(into)] disabled: Signal<bool>,
) -> impl IntoView { ) -> impl IntoView {
let id = create_unique_id(&name, &value.get_untracked()); let id = create_unique_id(&name.get(), &value.get_untracked());
view! { view! {
<label for=id class="flex items-center"> <label for=id class="flex items-center">
@@ -104,7 +104,7 @@ pub fn Checkbox(
#[component] #[component]
pub fn CheckboxList( pub fn CheckboxList(
/// The data member that this list should edit/display from the `data_map`. /// The data member that this list should edit/display from the `data_map`.
#[prop(into)] data_member: String, #[prop(into)] data_member: Signal<String>,
/// A [`Signal`] allowing access to a data store. /// A [`Signal`] allowing access to a data store.
#[prop()] data_map: RwSignal<HashMap<String, ValueType>>, #[prop()] data_map: RwSignal<HashMap<String, ValueType>>,
/// The available choices for this list. /// The available choices for this list.
@@ -159,7 +159,7 @@ pub fn CheckboxList(
on_change=on_change on_change=on_change
// The actual selected values are tracked by this element, not by the checkboxes themselves. // The actual selected values are tracked by this element, not by the checkboxes themselves.
value=item value=item
name=data_member.clone() name=data_member
disabled=disabled disabled=disabled
/> />
} }
+4 -4
View File
@@ -27,14 +27,14 @@ use super::utils::use_selectable_list;
pub fn Chip( pub fn Chip(
#[prop(into)] display_text: Signal<String>, #[prop(into)] display_text: Signal<String>,
#[prop(into)] value: Signal<String>, #[prop(into)] value: Signal<String>,
#[prop(into)] name: String, #[prop(into)] name: Signal<String>,
#[prop(into)] on_change: Callback<(), ()>, #[prop(into)] on_change: Callback<(), ()>,
#[prop()] checked: Signal<bool>, #[prop()] checked: Signal<bool>,
#[prop(optional, into)] disabled: Signal<bool>, #[prop(optional, into)] disabled: Signal<bool>,
) -> impl IntoView { ) -> impl IntoView {
// Generate a unique id - ensure that the value doesn't contain spaces. // Generate a unique id - ensure that the value doesn't contain spaces.
// Without this id, checkbox/radio inputs can interfere with each other. // Without this id, checkbox/radio inputs can interfere with each other.
let id = create_unique_id(&name, &value.get_untracked()); let id = create_unique_id(&name.get(), &value.get_untracked());
view! { view! {
<label for=id> <label for=id>
@@ -71,7 +71,7 @@ pub fn Chip(
#[component] #[component]
pub fn ChipsList( pub fn ChipsList(
/// The member in the data map that this input affects. /// The member in the data map that this input affects.
#[prop(into)] data_member: String, #[prop(into)] data_member: Signal<String>,
/// The data map that contains the list of values. This will be edited as the input changes. /// The data map that contains the list of values. This will be edited as the input changes.
#[prop()] data_map: RwSignal<HashMap<String, ValueType>>, #[prop()] data_map: RwSignal<HashMap<String, ValueType>>,
/// The list of strings that should be displayed in the list. /// The list of strings that should be displayed in the list.
@@ -132,7 +132,7 @@ pub fn ChipsList(
on_change=on_change on_change=on_change
value=value value=value
display_text=text display_text=text
name=data_member.clone() name=data_member
disabled=disabled disabled=disabled
/> />
} }
+26 -13
View File
@@ -23,24 +23,37 @@ fn value_type_to_vec(value_type: &ValueType) -> Vec<String> {
} }
pub fn use_selectable_list( pub fn use_selectable_list(
data_member: String, data_member: Signal<String>,
data_map: RwSignal<HashMap<String, ValueType>>, data_map: RwSignal<HashMap<String, ValueType>>,
required: Signal<bool> required: Signal<bool>
) -> ListController { ) -> ListController {
//#region Central List Logic //#region Central List Logic
// Get default values from the data map. This will only run once, when the input is created
// and mounted to the DOM.
let temp_map = data_map.get_untracked();
let origin_value_type = temp_map.get(&data_member)
.unwrap_or(&ValueType::List(None));
let origin_list = value_type_to_vec(origin_value_type);
// "Raw" selected values - just strings, no ValueTyping // "Raw" selected values - just strings, no ValueTyping
let selected_list = RwSignal::new(origin_list); let selected_list = RwSignal::new(Vec::new());
let hydrated = RwSignal::new(false);
let dirty = RwSignal::new(false);
// Hydration effect - runs only once, to hydrate data.
Effect::new(move || {
if hydrated.get() {
return;
}
// React to data_map changes
let map = data_map.get();
let key = data_member.get();
let list = map
.get(&key)
.unwrap_or(&ValueType::List(None));
selected_list.set(value_type_to_vec(list));
hydrated.set(true);
});
Effect::new({ Effect::new({
let data_member = data_member.clone();
move || { move || {
// Convert selected strings into ValueTypes // Convert selected strings into ValueTypes
let typed_list = selected_list.with(|list| let typed_list = selected_list.with(|list|
@@ -51,7 +64,7 @@ pub fn use_selectable_list(
// Update the map // Update the map
data_map.update(|map| { data_map.update(|map| {
map.insert(data_member.clone(), ValueType::List(Some(typed_list))); map.insert(data_member.get(), ValueType::List(Some(typed_list)));
}); });
} }
}); });
@@ -69,11 +82,11 @@ pub fn use_selectable_list(
ValidationState::Valid ValidationState::Valid
} }
}); });
let dirty = RwSignal::new(false);
let show_errors = Signal::derive(move || dirty.get() && matches!(error.get(), ValidationState::Invalid(_))); let show_errors = Signal::derive(move || dirty.get() && matches!(error.get(), ValidationState::Invalid(_)));
let validator = RwSignal::new(InputState::new( let validator = RwSignal::new(InputState::new(
data_member.clone(), data_member.get(),
error.clone(), error.clone(),
dirty.clone() dirty.clone()
)); ));