fix: TimePicker scroll problem (#180)

This commit is contained in:
luoxiaozero 2024-04-23 15:56:18 +08:00 committed by GitHub
parent 92f2812acf
commit bc8c326c91
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 48 additions and 31 deletions

View file

@ -5,6 +5,7 @@ use thaw::*;
pub fn SwitchVersion() -> impl IntoView {
let options = vec![
SelectOption::new("main", "https://thawui.vercel.app".into()),
SelectOption::new("0.3.0", "https://thaw-gxcwse9r5-thaw.vercel.app".into()),
SelectOption::new("0.2.6", "https://thaw-mzh1656cm-thaw.vercel.app".into()),
SelectOption::new("0.2.5", "https://thaw-8og1kv8zs-thaw.vercel.app".into()),
];

View file

@ -53,6 +53,8 @@ pub fn Scrollbar(
if let Some(comp_ref) = comp_ref {
comp_ref.load(ScrollbarRef {
container_scroll_top,
container_ref,
content_ref,
});
}
@ -335,10 +337,18 @@ enum ThumbStatus {
#[derive(Clone)]
pub struct ScrollbarRef {
container_scroll_top: RwSignal<i32>,
container_ref: NodeRef<html::Div>,
pub content_ref: NodeRef<html::Div>,
}
impl ScrollbarRef {
pub fn container_scroll_top(&self) -> i32 {
self.container_scroll_top.get_untracked()
}
pub fn scroll_to_with_scroll_to_options(&self, options: &web_sys::ScrollToOptions) {
if let Some(el) = self.container_ref.get_untracked() {
el.scroll_to_with_scroll_to_options(options);
}
}
}

View file

@ -3,8 +3,8 @@ mod theme;
pub use theme::TimePickerTheme;
use crate::{
use_theme, Button, ButtonSize, ButtonVariant, Icon, Input, InputSuffix, Scrollbar, SignalWatch,
Theme,
use_theme, Button, ButtonSize, ButtonVariant, Icon, Input, InputSuffix, Scrollbar,
ScrollbarRef, SignalWatch, Theme,
};
use chrono::{Local, NaiveTime, Timelike};
use leptos::*;
@ -165,9 +165,9 @@ fn Panel(
_ = panel_ref;
}
let hour_ref = create_node_ref::<html::Div>();
let minute_ref = create_node_ref::<html::Div>();
let second_ref = create_node_ref::<html::Div>();
let hour_ref = ComponentRef::<ScrollbarRef>::new();
let minute_ref = ComponentRef::<ScrollbarRef>::new();
let second_ref = ComponentRef::<ScrollbarRef>::new();
comp_ref.load(PanelRef {
hour_ref,
minute_ref,
@ -188,8 +188,8 @@ fn Panel(
ref=panel_ref
>
<div class="thaw-time-picker-panel__time">
<div class="thaw-time-picker-panel__time-hour" ref=hour_ref>
<Scrollbar size=6>
<div class="thaw-time-picker-panel__time-hour">
<Scrollbar size=6 comp_ref=hour_ref>
{(0..24)
.map(|hour| {
let comp_ref = ComponentRef::<PanelTimeItemRef>::default();
@ -217,11 +217,11 @@ fn Panel(
}
})
.collect_view()}
<div class="thaw-time-picker-panel__time-padding"></div>
</Scrollbar>
<div class="thaw-time-picker-panel__time-padding"></div>
</div>
<div class="thaw-time-picker-panel__time-minute" ref=minute_ref>
<Scrollbar size=6>
<div class="thaw-time-picker-panel__time-minute">
<Scrollbar size=6 comp_ref=minute_ref>
{(0..60)
.map(|minute| {
let comp_ref = ComponentRef::<PanelTimeItemRef>::default();
@ -249,11 +249,11 @@ fn Panel(
}
})
.collect_view()}
<div class="thaw-time-picker-panel__time-padding"></div>
</Scrollbar>
<div class="thaw-time-picker-panel__time-padding"></div>
</div>
<div class="thaw-time-picker-panel__time-second" ref=second_ref>
<Scrollbar size=6>
<div class="thaw-time-picker-panel__time-second">
<Scrollbar size=6 comp_ref=second_ref>
{(0..60)
.map(|second| {
let comp_ref = ComponentRef::<PanelTimeItemRef>::default();
@ -281,8 +281,8 @@ fn Panel(
}
})
.collect_view()}
<div class="thaw-time-picker-panel__time-padding"></div>
</Scrollbar>
<div class="thaw-time-picker-panel__time-padding"></div>
</div>
</div>
<div class="thaw-time-picker-panel__footer">
@ -300,32 +300,38 @@ fn Panel(
#[derive(Clone)]
struct PanelRef {
hour_ref: NodeRef<html::Div>,
minute_ref: NodeRef<html::Div>,
second_ref: NodeRef<html::Div>,
hour_ref: ComponentRef<ScrollbarRef>,
minute_ref: ComponentRef<ScrollbarRef>,
second_ref: ComponentRef<ScrollbarRef>,
}
impl PanelRef {
fn scroll_top(el: HtmlElement<html::Div>) {
if let Ok(Some(slected_el)) =
el.query_selector(".thaw-time-picker-panel__time-item--slected")
{
use wasm_bindgen::JsCast;
if let Ok(slected_el) = slected_el.dyn_into::<web_sys::HtmlElement>() {
el.set_scroll_top(slected_el.offset_top());
}
fn scroll_top(scrollbar_ref: ScrollbarRef) {
let Some(contetn_ref) = scrollbar_ref.content_ref.get_untracked() else {
return;
};
let Ok(Some(slected_el)) =
contetn_ref.query_selector(".thaw-time-picker-panel__time-item--slected")
else {
return;
};
use wasm_bindgen::JsCast;
if let Ok(slected_el) = slected_el.dyn_into::<web_sys::HtmlElement>() {
scrollbar_ref.scroll_to_with_scroll_to_options(
web_sys::ScrollToOptions::new().top(f64::from(slected_el.offset_top())),
);
}
}
fn scroll_into_view(&self) {
if let Some(hour_el) = self.hour_ref.get_untracked() {
Self::scroll_top(hour_el);
if let Some(hour) = self.hour_ref.get_untracked() {
Self::scroll_top(hour);
}
if let Some(minute_el) = self.minute_ref.get_untracked() {
Self::scroll_top(minute_el);
if let Some(minute) = self.minute_ref.get_untracked() {
Self::scroll_top(minute);
}
if let Some(second_el) = self.second_ref.get_untracked() {
Self::scroll_top(second_el);
if let Some(second) = self.second_ref.get_untracked() {
Self::scroll_top(second);
}
}
}