diff --git a/packages/dom/src/middleware.rs b/packages/dom/src/middleware.rs index ab99f6f..5b867ab 100644 --- a/packages/dom/src/middleware.rs +++ b/packages/dom/src/middleware.rs @@ -7,9 +7,10 @@ use web_sys::{Element, Window}; pub use floating_ui_core::middleware::{ ApplyState, ArrowData, ArrowOptions, AutoPlacementData, AutoPlacementDataOverflow, AutoPlacementOptions, DefaultLimiter, FallbackStrategy, FlipData, FlipDataOverflow, - FlipOptions, LimitShift, LimitShiftOffset, LimitShiftOffsetValues, LimitShiftOptions, - OffsetData, OffsetOptions, OffsetOptionsValues, ShiftData, ShiftOptions, SizeOptions, - ARROW_NAME, AUTO_PLACEMENT_NAME, FLIP_NAME, HIDE_NAME, OFFSET_NAME, SHIFT_NAME, SIZE_NAME, + FlipOptions, HideData, HideOptions, HideStrategy, LimitShift, LimitShiftOffset, + LimitShiftOffsetValues, LimitShiftOptions, OffsetData, OffsetOptions, OffsetOptionsValues, + ShiftData, ShiftOptions, SizeOptions, ARROW_NAME, AUTO_PLACEMENT_NAME, FLIP_NAME, HIDE_NAME, + OFFSET_NAME, SHIFT_NAME, SIZE_NAME, }; /// Provides data to position an inner element of the floating element so that it appears centered to the reference element. diff --git a/packages/leptos/src/lib.rs b/packages/leptos/src/lib.rs index d73d074..6e974de 100644 --- a/packages/leptos/src/lib.rs +++ b/packages/leptos/src/lib.rs @@ -14,10 +14,10 @@ pub use floating_ui_dom::{ AutoUpdateOptions, Axis, ClientRectObject, ComputePositionConfig, ComputePositionReturn, Coords, DefaultLimiter, Derivable, DerivableFn, DetectOverflowOptions, Dimensions, ElementOrVirtual, ElementRects, FallbackStrategy, Flip, FlipData, FlipDataOverflow, - FlipOptions, Length, LimitShift, LimitShiftOffset, LimitShiftOffsetValues, LimitShiftOptions, - Middleware, MiddlewareData, MiddlewareReturn, MiddlewareState, MiddlewareVec, - MiddlewareWithOptions, Offset, OffsetData, OffsetOptions, OffsetOptionsValues, Padding, - Placement, Rect, Shift, ShiftData, ShiftOptions, Side, Size, SizeOptions, Strategy, - VirtualElement, ARROW_NAME, AUTO_PLACEMENT_NAME, FLIP_NAME, HIDE_NAME, OFFSET_NAME, SHIFT_NAME, - SIZE_NAME, + FlipOptions, Hide, HideData, HideOptions, HideStrategy, Length, LimitShift, LimitShiftOffset, + LimitShiftOffsetValues, LimitShiftOptions, Middleware, MiddlewareData, MiddlewareReturn, + MiddlewareState, MiddlewareVec, MiddlewareWithOptions, Offset, OffsetData, OffsetOptions, + OffsetOptionsValues, Padding, Placement, Rect, Shift, ShiftData, ShiftOptions, Side, Size, + SizeOptions, Strategy, VirtualElement, ARROW_NAME, AUTO_PLACEMENT_NAME, FLIP_NAME, HIDE_NAME, + OFFSET_NAME, SHIFT_NAME, SIZE_NAME, }; diff --git a/packages/leptos/tests/playwright.rs b/packages/leptos/tests/playwright.rs index 6c1f341..f448ad6 100644 --- a/packages/leptos/tests/playwright.rs +++ b/packages/leptos/tests/playwright.rs @@ -1,6 +1,6 @@ use std::{env, fs, path::Path, process::Command}; -const IMPLEMENTED_TESTS: [&str; 16] = [ +const IMPLEMENTED_TESTS: [&str; 17] = [ "arrow", "autoPlacement", "autoUpdate", @@ -8,6 +8,7 @@ const IMPLEMENTED_TESTS: [&str; 16] = [ "containing-block", "decimal-size", "flip", + "hide", "offset", "placement", "relative", diff --git a/packages/leptos/tests/visual/src/app.rs b/packages/leptos/tests/visual/src/app.rs index db25a0f..180b418 100644 --- a/packages/leptos/tests/visual/src/app.rs +++ b/packages/leptos/tests/visual/src/app.rs @@ -8,6 +8,7 @@ use crate::spec::border::Border; use crate::spec::containing_block::ContainingBlock; use crate::spec::decimal_size::DecimalSize; use crate::spec::flip::Flip; +use crate::spec::hide::Hide; use crate::spec::offset::Offset; use crate::spec::placement::Placement; use crate::spec::relative::Relative; @@ -114,7 +115,7 @@ pub fn App() -> impl IntoView { - // + // diff --git a/packages/leptos/tests/visual/src/spec.rs b/packages/leptos/tests/visual/src/spec.rs index a08ee0c..d815e78 100644 --- a/packages/leptos/tests/visual/src/spec.rs +++ b/packages/leptos/tests/visual/src/spec.rs @@ -5,6 +5,7 @@ pub mod border; pub mod containing_block; pub mod decimal_size; pub mod flip; +pub mod hide; pub mod offset; pub mod placement; pub mod relative; diff --git a/packages/leptos/tests/visual/src/spec/hide.rs b/packages/leptos/tests/visual/src/spec/hide.rs new file mode 100644 index 0000000..f19be6b --- /dev/null +++ b/packages/leptos/tests/visual/src/spec/hide.rs @@ -0,0 +1,340 @@ +use convert_case::{Case, Casing}; +use floating_ui_leptos::{ + use_floating, ApplyState, Hide, HideData, HideOptions, HideStrategy, MiddlewareState, + MiddlewareVec, Placement, Shift, ShiftOptions, Size, SizeOptions, Strategy, UseFloatingOptions, + UseFloatingReturn, HIDE_NAME, +}; +use leptos::{html::Div, *}; +use wasm_bindgen::JsCast; + +use crate::utils::{ + all_placements::ALL_PLACEMENTS, + use_scroll::{use_scroll, UseScrollOptions, UseScrollReturn}, +}; + +#[component] +pub fn Hide() -> impl IntoView { + let reference_ref = create_node_ref::
(); + let floating_ref = create_node_ref::
(); + + let (placement, set_placement) = create_signal(Placement::Bottom); + let (hierarchy, set_hierarchy) = create_signal('a'); + let is_fixed_strategy = move || ['j', 'k', 'l', 'm', 'o', 'p', 'q'].contains(&hierarchy()); + + let UseFloatingReturn { + x, + y, + strategy, + middleware_data, + update, + .. + } = use_floating( + reference_ref, + floating_ref, + UseFloatingOptions::default() + .placement(placement.into()) + .strategy(MaybeProp::derive(move || { + Some(match is_fixed_strategy() { + true => Strategy::Fixed, + false => Strategy::Absolute, + }) + })) + .while_elements_mounted_auto_update() + .middleware(MaybeProp::derive(move || { + let mut middleware: MiddlewareVec = vec![ + Box::new(Hide::new( + HideOptions::default().strategy(HideStrategy::ReferenceHidden), + )), + Box::new(Hide::new( + HideOptions::default().strategy(HideStrategy::Escaped), + )), + ]; + + if hierarchy() == 'o' { + middleware.push(Box::new(Shift::new(ShiftOptions::default()))); + } + + middleware.push(Box::new(Size::new(SizeOptions::new( + match is_fixed_strategy() { + true => &|ApplyState { + state, + available_height, + .. + }| { + let MiddlewareState { elements, .. } = state; + + let floating = (*elements.floating) + .clone() + .unchecked_into::(); + + floating + .style() + .set_property("max-height", &format!("{}px", available_height)) + .expect("Style should be updated."); + }, + false => &|ApplyState { state, .. }| { + let MiddlewareState { elements, .. } = state; + + let floating = (*elements.floating) + .clone() + .unchecked_into::(); + + floating + .style() + .remove_property("max-height") + .expect("Style should be updated."); + }, + }, + )))); + + Some(middleware) + })), + ); + + let hide_data = move || middleware_data().get_as::(HIDE_NAME); + let reference_hidden = move || { + hide_data().map_or(false, |data| match data { + HideData::ReferenceHidden(data) => data.reference_hidden, + HideData::Escaped(_) => false, + }) + }; + let escaped = move || { + hide_data().map_or(false, |data| match data { + HideData::ReferenceHidden(_) => false, + HideData::Escaped(data) => data.escaped, + }) + }; + + let hierarchy_update = update.clone(); + + let UseScrollReturn { + scroll_ref, + indicator, + .. + } = use_scroll(UseScrollOptions { + reference_ref, + floating_ref, + update, + rtl: None::.into(), + }); + + let reference_view = move || { + let base = view! { +
+ Reference +
+ }; + + match hierarchy() { + 'b' => view! { +
+
+ {base} +
+
+ }, + 'c' => view! { +
+
+
+ {base} +
+
+
+ }, + 'd' => view! { +
+
+ Reference +
+
+ }, + 'e' => view! { +
+
+
+ {base} +
+
+
+ }, + 'f' => view! { +
+
+
+ {base} +
+
+
+ }, + 'g' => view! { +
+
+
+
+ {base} +
+
+
+
+ }, + 'h' => view! { +
+
+
+
+ {base} +
+
+
+
+ }, + 'i' => view! { +
+
+
+
+ {base} +
+
+
+
+ }, + 'n' => view! { +
+ {base} +
+ }, + 'p' => view! { +
+
+
+ {base} +
+
+
+ }, + 'q' => view! { +
+
+ {base} +
+
+ }, + _ => base, + } + }; + + let floating_view = move || { + let base = view! { +
"black", + false => match escaped() { + true => "yellow", + false => "" + } + } + > + Floating +
+ }; + + match hierarchy() { + 'j' => view! { +
+ {base} +
+ }, + 'k' => view! { +
+ {base} +
+ }, + 'l' => view! { +
+
+ {base} +
+
+ }, + 'm' => view! { +
+
+ Floating +
+
+ }, + _ => base, + } + }; + + view! { +

Hide

+

+
+
+ {indicator} + {reference_view} + {floating_view} +
+
+ +
+ "black", + false => "" + } + on:click=move |_| set_placement(local_placement) + > + {format!("{:?}", local_placement).to_case(Case::Kebab)} + + } + /> +
+ +

Hierarchy

+
+ "black", + false => "" + } + on:click=move |_| { + set_hierarchy(local_hierarchy); + hierarchy_update(); + } + > + {local_hierarchy} + + } + } + /> +
+ } +}