fix: resolve all type inference and closure ownership errors in DataTable
All checks were successful
Build MIPS Binary / build (push) Successful in 5m33s
All checks were successful
Build MIPS Binary / build (push) Successful in 5m33s
This commit is contained in:
@@ -1,2 +1,3 @@
|
|||||||
pub mod use_random;
|
pub mod use_random;
|
||||||
pub mod use_theme_mode;
|
pub mod use_theme_mode;
|
||||||
|
pub mod use_can_scroll_vertical;
|
||||||
25
frontend/src/components/hooks/use_can_scroll_vertical.rs
Normal file
25
frontend/src/components/hooks/use_can_scroll_vertical.rs
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
use leptos::prelude::*;
|
||||||
|
use wasm_bindgen::JsCast;
|
||||||
|
|
||||||
|
/// Hook to determine if an element can scroll vertically.
|
||||||
|
///
|
||||||
|
/// Returns (on_scroll_callback, can_scroll_up_signal, can_scroll_down_signal)
|
||||||
|
pub fn use_can_scroll_vertical() -> (Callback<web_sys::Event>, ReadSignal<bool>, ReadSignal<bool>) {
|
||||||
|
let can_scroll_up = RwSignal::new(false);
|
||||||
|
let can_scroll_down = RwSignal::new(false);
|
||||||
|
|
||||||
|
let on_scroll = Callback::new(move |ev: web_sys::Event| {
|
||||||
|
if let Some(target) = ev.target() {
|
||||||
|
if let Some(el) = target.dyn_ref::<web_sys::HtmlElement>() {
|
||||||
|
let scroll_top = el.scroll_top();
|
||||||
|
let scroll_height = el.scroll_height();
|
||||||
|
let client_height = el.client_height();
|
||||||
|
|
||||||
|
can_scroll_up.set(scroll_top > 0);
|
||||||
|
can_scroll_down.set(scroll_top + client_height < scroll_height - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
(on_scroll, can_scroll_up.read_only(), can_scroll_down.read_only())
|
||||||
|
}
|
||||||
@@ -11,7 +11,6 @@ pub mod input;
|
|||||||
pub mod multi_select;
|
pub mod multi_select;
|
||||||
pub mod select;
|
pub mod select;
|
||||||
pub mod separator;
|
pub mod separator;
|
||||||
pub mod sonner;
|
|
||||||
pub mod svg_icon;
|
pub mod svg_icon;
|
||||||
pub mod table;
|
pub mod table;
|
||||||
pub mod theme_toggle;
|
pub mod theme_toggle;
|
||||||
|
|||||||
@@ -20,13 +20,6 @@ pub enum MultiSelectAlign {
|
|||||||
End,
|
End,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, PartialEq, Eq, Default)]
|
|
||||||
pub enum MultiSelectPosition {
|
|
||||||
#[default]
|
|
||||||
Below,
|
|
||||||
Above,
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ========================================================== */
|
/* ========================================================== */
|
||||||
/* ✨ FUNCTIONS ✨ */
|
/* ✨ FUNCTIONS ✨ */
|
||||||
/* ========================================================== */
|
/* ========================================================== */
|
||||||
@@ -181,12 +174,13 @@ pub fn MultiSelectContent(children: Children, #[prop(optional, into)] class: Str
|
|||||||
);
|
);
|
||||||
|
|
||||||
let target_id_for_script = multi_select_ctx.target_id.clone();
|
let target_id_for_script = multi_select_ctx.target_id.clone();
|
||||||
|
let target_id_for_script_2 = multi_select_ctx.target_id.clone();
|
||||||
|
|
||||||
// Scroll indicator signals
|
// Scroll indicator signals
|
||||||
let (on_scroll, can_scroll_up_signal, can_scroll_down_signal) = use_can_scroll_vertical();
|
let (on_scroll, can_scroll_up_signal, can_scroll_down_signal) = use_can_scroll_vertical();
|
||||||
|
|
||||||
view! {
|
view! {
|
||||||
<script src="/hooks/lock_scroll.js"></script>
|
<script src="/lock_scroll.js"></script>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
data-name="MultiSelectContent"
|
data-name="MultiSelectContent"
|
||||||
@@ -196,12 +190,13 @@ pub fn MultiSelectContent(children: Children, #[prop(optional, into)] class: Str
|
|||||||
data-state="closed"
|
data-state="closed"
|
||||||
data-align=align_str
|
data-align=align_str
|
||||||
style="pointer-events: none;"
|
style="pointer-events: none;"
|
||||||
on:scroll=on_scroll
|
on:scroll=move |ev| on_scroll.run(ev)
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
data-scroll-up="true"
|
data-scroll-up="true"
|
||||||
class=move || {
|
class=move || {
|
||||||
if can_scroll_up_signal.get() {
|
let is_up: bool = can_scroll_up_signal.get();
|
||||||
|
if is_up {
|
||||||
"sticky -top-1 z-10 flex items-center justify-center py-1 bg-card"
|
"sticky -top-1 z-10 flex items-center justify-center py-1 bg-card"
|
||||||
} else {
|
} else {
|
||||||
"hidden"
|
"hidden"
|
||||||
@@ -214,7 +209,8 @@ pub fn MultiSelectContent(children: Children, #[prop(optional, into)] class: Str
|
|||||||
<div
|
<div
|
||||||
data-scroll-down="true"
|
data-scroll-down="true"
|
||||||
class=move || {
|
class=move || {
|
||||||
if can_scroll_down_signal.get() {
|
let is_down: bool = can_scroll_down_signal.get();
|
||||||
|
if is_down {
|
||||||
"sticky -bottom-1 z-10 flex items-center justify-center py-1 bg-card"
|
"sticky -bottom-1 z-10 flex items-center justify-center py-1 bg-card"
|
||||||
} else {
|
} else {
|
||||||
"hidden"
|
"hidden"
|
||||||
@@ -247,21 +243,12 @@ pub fn MultiSelectContent(children: Children, #[prop(optional, into)] class: Str
|
|||||||
|
|
||||||
const openMultiSelect = () => {{
|
const openMultiSelect = () => {{
|
||||||
isOpen = true;
|
isOpen = true;
|
||||||
|
if (window.ScrollLock) window.ScrollLock.lock();
|
||||||
// Lock all scrollable elements
|
|
||||||
window.ScrollLock.lock();
|
|
||||||
|
|
||||||
multiSelect.setAttribute('data-state', 'open');
|
multiSelect.setAttribute('data-state', 'open');
|
||||||
multiSelect.style.pointerEvents = 'auto';
|
multiSelect.style.pointerEvents = 'auto';
|
||||||
|
|
||||||
// Set min-width to match trigger
|
|
||||||
const triggerRect = trigger.getBoundingClientRect();
|
const triggerRect = trigger.getBoundingClientRect();
|
||||||
multiSelect.style.minWidth = `${{triggerRect.width}}px`;
|
multiSelect.style.minWidth = `${{triggerRect.width}}px`;
|
||||||
|
|
||||||
// Trigger scroll event to update indicators
|
|
||||||
multiSelect.dispatchEvent(new Event('scroll'));
|
multiSelect.dispatchEvent(new Event('scroll'));
|
||||||
|
|
||||||
// Close on click outside
|
|
||||||
setTimeout(() => {{
|
setTimeout(() => {{
|
||||||
document.addEventListener('click', handleClickOutside);
|
document.addEventListener('click', handleClickOutside);
|
||||||
}}, 0);
|
}}, 0);
|
||||||
@@ -272,9 +259,7 @@ pub fn MultiSelectContent(children: Children, #[prop(optional, into)] class: Str
|
|||||||
multiSelect.setAttribute('data-state', 'closed');
|
multiSelect.setAttribute('data-state', 'closed');
|
||||||
multiSelect.style.pointerEvents = 'none';
|
multiSelect.style.pointerEvents = 'none';
|
||||||
document.removeEventListener('click', handleClickOutside);
|
document.removeEventListener('click', handleClickOutside);
|
||||||
|
if (window.ScrollLock) window.ScrollLock.unlock(200);
|
||||||
// Unlock scroll after animation (200ms delay)
|
|
||||||
window.ScrollLock.unlock(200);
|
|
||||||
}};
|
}};
|
||||||
|
|
||||||
const handleClickOutside = (e) => {{
|
const handleClickOutside = (e) => {{
|
||||||
@@ -283,17 +268,11 @@ pub fn MultiSelectContent(children: Children, #[prop(optional, into)] class: Str
|
|||||||
}}
|
}}
|
||||||
}};
|
}};
|
||||||
|
|
||||||
// Toggle multi-select when trigger is clicked
|
|
||||||
trigger.addEventListener('click', (e) => {{
|
trigger.addEventListener('click', (e) => {{
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
if (isOpen) {{
|
if (isOpen) closeMultiSelect(); else openMultiSelect();
|
||||||
closeMultiSelect();
|
|
||||||
}} else {{
|
|
||||||
openMultiSelect();
|
|
||||||
}}
|
|
||||||
}});
|
}});
|
||||||
|
|
||||||
// Handle ESC key to close
|
|
||||||
document.addEventListener('keydown', (e) => {{
|
document.addEventListener('keydown', (e) => {{
|
||||||
if (e.key === 'Escape' && isOpen) {{
|
if (e.key === 'Escape' && isOpen) {{
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
@@ -310,8 +289,8 @@ pub fn MultiSelectContent(children: Children, #[prop(optional, into)] class: Str
|
|||||||
}})();
|
}})();
|
||||||
"#,
|
"#,
|
||||||
target_id_for_script,
|
target_id_for_script,
|
||||||
target_id_for_script,
|
target_id_for_script_2,
|
||||||
)}
|
)}
|
||||||
</script>
|
</script>
|
||||||
}
|
}.into_any()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -166,6 +166,7 @@ pub fn SelectContent(
|
|||||||
);
|
);
|
||||||
|
|
||||||
let target_id_for_script = ctx.target_id.clone();
|
let target_id_for_script = ctx.target_id.clone();
|
||||||
|
let target_id_for_script_2 = ctx.target_id.clone();
|
||||||
|
|
||||||
// Scroll indicator signals
|
// Scroll indicator signals
|
||||||
let (on_scroll, can_scroll_up_signal, can_scroll_down_signal) = use_can_scroll_vertical();
|
let (on_scroll, can_scroll_up_signal, can_scroll_down_signal) = use_can_scroll_vertical();
|
||||||
@@ -176,7 +177,6 @@ pub fn SelectContent(
|
|||||||
<div
|
<div
|
||||||
data-name="SelectContent"
|
data-name="SelectContent"
|
||||||
class=merged_class
|
class=merged_class
|
||||||
// Listen for custom 'selectclose' event dispatched by JS
|
|
||||||
on:selectclose=move |_: web_sys::CustomEvent| {
|
on:selectclose=move |_: web_sys::CustomEvent| {
|
||||||
if let Some(cb) = on_close {
|
if let Some(cb) = on_close {
|
||||||
cb.run(());
|
cb.run(());
|
||||||
@@ -187,12 +187,13 @@ pub fn SelectContent(
|
|||||||
data-state="closed"
|
data-state="closed"
|
||||||
data-position=position.to_string()
|
data-position=position.to_string()
|
||||||
style="pointer-events: none;"
|
style="pointer-events: none;"
|
||||||
on:scroll=on_scroll
|
on:scroll=move |ev| on_scroll.run(ev)
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
data-scroll-up="true"
|
data-scroll-up="true"
|
||||||
class=move || {
|
class=move || {
|
||||||
if can_scroll_up_signal.get() {
|
let is_up: bool = can_scroll_up_signal.get();
|
||||||
|
if is_up {
|
||||||
"sticky -top-1 z-10 flex items-center justify-center py-1 bg-card"
|
"sticky -top-1 z-10 flex items-center justify-center py-1 bg-card"
|
||||||
} else {
|
} else {
|
||||||
"hidden"
|
"hidden"
|
||||||
@@ -205,7 +206,8 @@ pub fn SelectContent(
|
|||||||
<div
|
<div
|
||||||
data-scroll-down="true"
|
data-scroll-down="true"
|
||||||
class=move || {
|
class=move || {
|
||||||
if can_scroll_down_signal.get() {
|
let is_down: bool = can_scroll_down_signal.get();
|
||||||
|
if is_down {
|
||||||
"sticky -bottom-1 z-10 flex items-center justify-center py-1 bg-card"
|
"sticky -bottom-1 z-10 flex items-center justify-center py-1 bg-card"
|
||||||
} else {
|
} else {
|
||||||
"hidden"
|
"hidden"
|
||||||
@@ -304,8 +306,8 @@ pub fn SelectContent(
|
|||||||
}})();
|
}})();
|
||||||
"#,
|
"#,
|
||||||
target_id_for_script,
|
target_id_for_script,
|
||||||
target_id_for_script,
|
target_id_for_script_2,
|
||||||
)}
|
)}
|
||||||
</script>
|
</script>
|
||||||
}.into_any()
|
}.into_any()
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user