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 crate::combobox::listbox::ListboxInjection;
use leptos::prelude::*;
#[component]
pub fn AutoCompleteOption(value: String, children: Children) -> impl IntoView {
let auto_complete = AutoCompleteInjection::expect_context();
let listbox = ListboxInjection::expect_context();
let is_selected = Memo::new({
let value = value.clone();
move |_| auto_complete.is_selected(&value)
});
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();
listbox.trigger();
on_cleanup(move || {
auto_complete.remove_option(&id);
listbox.trigger();
});
}

View file

@ -1,3 +1,4 @@
use super::listbox::ListboxInjection;
use crate::ComboboxInjection;
use leptos::prelude::*;
use thaw_components::{Fallback, If, OptionComp, Then};
@ -10,6 +11,7 @@ pub fn ComboboxOption(
#[prop(optional)] children: Option<Children>,
) -> impl IntoView {
let combobox = ComboboxInjection::expect_context();
let listbox = ListboxInjection::expect_context();
let value = StoredValue::new(value.unwrap_or_else(|| text.clone()));
let text = StoredValue::new(text);
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()));
let id = id.clone();
listbox.trigger();
on_cleanup(move || {
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 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_utils::mount_style;
use web_sys::{HtmlElement, Node};
@ -18,9 +17,14 @@ pub fn Listbox(
mount_style("listbox", include_str!("./listbox.css"));
let config_provider = ConfigInjection::expect_context();
let effect = RenderEffect::new(move |_| {
if let Some(listbox_el) = listbox_ref.get() {
set_listbox(listbox_el.into());
let trigger = ArcTrigger::new();
let effect = RenderEffect::new({
let trigger = trigger.clone();
move |_| {
trigger.track();
if let Some(listbox_el) = listbox_ref.get() {
set_listbox(listbox_el.into());
}
}
});
on_cleanup(move || {
@ -28,23 +32,40 @@ pub fn Listbox(
});
view! {
<CSSTransition
node_ref=listbox_ref
name="fade-in-scale-up-transition"
appear=open.get_untracked()
show=open
let:display
>
<div
class=format!("thaw-config-provider thaw-listbox {class}")
style=move || display.get().unwrap_or_default()
data-thaw-id=config_provider.id().clone()
<Provider value=ListboxInjection(trigger)>
<CSSTransition
node_ref=listbox_ref
role="listbox"
name="fade-in-scale-up-transition"
appear=open.get_untracked()
show=open
let:display
>
{children()}
</div>
</CSSTransition>
<div
class=format!("thaw-config-provider thaw-listbox {class}")
style=move || display.get().unwrap_or_default()
data-thaw-id=config_provider.id().clone()
node_ref=listbox_ref
role="listbox"
>
{children()}
</div>
</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();
}
}