feat: adds ListboxInjection

This commit is contained in:
luoxiao 2024-07-23 18:00:55 +08:00
parent 87a4ef115c
commit 7da18dc9e5
3 changed files with 51 additions and 22 deletions

View file

@ -1,19 +1,23 @@
use super::AutoCompleteInjection; use super::AutoCompleteInjection;
use crate::combobox::listbox::ListboxInjection;
use leptos::prelude::*; use leptos::prelude::*;
#[component] #[component]
pub fn AutoCompleteOption(value: String, children: Children) -> impl IntoView { pub fn AutoCompleteOption(value: String, children: Children) -> impl IntoView {
let auto_complete = AutoCompleteInjection::expect_context(); let auto_complete = AutoCompleteInjection::expect_context();
let listbox = ListboxInjection::expect_context();
let is_selected = Memo::new({ let is_selected = Memo::new({
let value = value.clone(); let value = value.clone();
move |_| auto_complete.is_selected(&value) move |_| auto_complete.is_selected(&value)
}); });
let id = uuid::Uuid::new_v4().to_string(); let id = uuid::Uuid::new_v4().to_string();
auto_complete.insert_option(id.clone(), value.clone());
{ {
auto_complete.insert_option(id.clone(), value.clone());
let id = id.clone(); let id = id.clone();
listbox.trigger();
on_cleanup(move || { on_cleanup(move || {
auto_complete.remove_option(&id); auto_complete.remove_option(&id);
listbox.trigger();
}); });
} }

View file

@ -1,3 +1,4 @@
use super::listbox::ListboxInjection;
use crate::ComboboxInjection; use crate::ComboboxInjection;
use leptos::prelude::*; use leptos::prelude::*;
use thaw_components::{Fallback, If, OptionComp, Then}; use thaw_components::{Fallback, If, OptionComp, Then};
@ -10,6 +11,7 @@ pub fn ComboboxOption(
#[prop(optional)] children: Option<Children>, #[prop(optional)] children: Option<Children>,
) -> impl IntoView { ) -> impl IntoView {
let combobox = ComboboxInjection::expect_context(); let combobox = ComboboxInjection::expect_context();
let listbox = ListboxInjection::expect_context();
let value = StoredValue::new(value.unwrap_or_else(|| text.clone())); let value = StoredValue::new(value.unwrap_or_else(|| text.clone()));
let text = StoredValue::new(text); let text = StoredValue::new(text);
let is_selected = Memo::new(move |_| value.with_value(|value| combobox.is_selected(&value))); let is_selected = Memo::new(move |_| value.with_value(|value| combobox.is_selected(&value)));
@ -26,8 +28,10 @@ pub fn ComboboxOption(
{ {
combobox.insert_option(id.clone(), (value.get_value(), text.get_value())); combobox.insert_option(id.clone(), (value.get_value(), text.get_value()));
let id = id.clone(); let id = id.clone();
listbox.trigger();
on_cleanup(move || { on_cleanup(move || {
combobox.remove_option(&id); combobox.remove_option(&id);
listbox.trigger();
}); });
} }

View file

@ -1,8 +1,7 @@
use std::sync::Arc;
use super::utils::{get_dropdown_action_from_key, DropdownAction}; use super::utils::{get_dropdown_action_from_key, DropdownAction};
use crate::{ConfigInjection, _aria::ActiveDescendantController}; use crate::{ConfigInjection, _aria::ActiveDescendantController};
use leptos::{ev, html, prelude::*}; use leptos::{context::Provider, ev, html, prelude::*};
use std::sync::Arc;
use thaw_components::CSSTransition; use thaw_components::CSSTransition;
use thaw_utils::mount_style; use thaw_utils::mount_style;
use web_sys::{HtmlElement, Node}; use web_sys::{HtmlElement, Node};
@ -18,16 +17,22 @@ pub fn Listbox(
mount_style("listbox", include_str!("./listbox.css")); mount_style("listbox", include_str!("./listbox.css"));
let config_provider = ConfigInjection::expect_context(); let config_provider = ConfigInjection::expect_context();
let effect = RenderEffect::new(move |_| { let trigger = ArcTrigger::new();
let effect = RenderEffect::new({
let trigger = trigger.clone();
move |_| {
trigger.track();
if let Some(listbox_el) = listbox_ref.get() { if let Some(listbox_el) = listbox_ref.get() {
set_listbox(listbox_el.into()); set_listbox(listbox_el.into());
} }
}
}); });
on_cleanup(move || { on_cleanup(move || {
drop(effect); drop(effect);
}); });
view! { view! {
<Provider value=ListboxInjection(trigger)>
<CSSTransition <CSSTransition
node_ref=listbox_ref node_ref=listbox_ref
name="fade-in-scale-up-transition" name="fade-in-scale-up-transition"
@ -45,6 +50,22 @@ pub fn Listbox(
{children()} {children()}
</div> </div>
</CSSTransition> </CSSTransition>
</Provider>
}
}
#[derive(Clone)]
pub(crate) struct ListboxInjection(ArcTrigger);
impl ListboxInjection {
#[inline]
pub fn expect_context() -> Self {
expect_context()
}
#[inline]
pub fn trigger(&self) {
self.0.trigger();
} }
} }