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 { pub fn SwitchVersion() -> impl IntoView {
let options = vec![ let options = vec![
SelectOption::new("main", "https://thawui.vercel.app".into()), 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.6", "https://thaw-mzh1656cm-thaw.vercel.app".into()),
SelectOption::new("0.2.5", "https://thaw-8og1kv8zs-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 { if let Some(comp_ref) = comp_ref {
comp_ref.load(ScrollbarRef { comp_ref.load(ScrollbarRef {
container_scroll_top, container_scroll_top,
container_ref,
content_ref,
}); });
} }
@ -335,10 +337,18 @@ enum ThumbStatus {
#[derive(Clone)] #[derive(Clone)]
pub struct ScrollbarRef { pub struct ScrollbarRef {
container_scroll_top: RwSignal<i32>, container_scroll_top: RwSignal<i32>,
container_ref: NodeRef<html::Div>,
pub content_ref: NodeRef<html::Div>,
} }
impl ScrollbarRef { impl ScrollbarRef {
pub fn container_scroll_top(&self) -> i32 { pub fn container_scroll_top(&self) -> i32 {
self.container_scroll_top.get_untracked() 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; pub use theme::TimePickerTheme;
use crate::{ use crate::{
use_theme, Button, ButtonSize, ButtonVariant, Icon, Input, InputSuffix, Scrollbar, SignalWatch, use_theme, Button, ButtonSize, ButtonVariant, Icon, Input, InputSuffix, Scrollbar,
Theme, ScrollbarRef, SignalWatch, Theme,
}; };
use chrono::{Local, NaiveTime, Timelike}; use chrono::{Local, NaiveTime, Timelike};
use leptos::*; use leptos::*;
@ -165,9 +165,9 @@ fn Panel(
_ = panel_ref; _ = panel_ref;
} }
let hour_ref = create_node_ref::<html::Div>(); let hour_ref = ComponentRef::<ScrollbarRef>::new();
let minute_ref = create_node_ref::<html::Div>(); let minute_ref = ComponentRef::<ScrollbarRef>::new();
let second_ref = create_node_ref::<html::Div>(); let second_ref = ComponentRef::<ScrollbarRef>::new();
comp_ref.load(PanelRef { comp_ref.load(PanelRef {
hour_ref, hour_ref,
minute_ref, minute_ref,
@ -188,8 +188,8 @@ fn Panel(
ref=panel_ref ref=panel_ref
> >
<div class="thaw-time-picker-panel__time"> <div class="thaw-time-picker-panel__time">
<div class="thaw-time-picker-panel__time-hour" ref=hour_ref> <div class="thaw-time-picker-panel__time-hour">
<Scrollbar size=6> <Scrollbar size=6 comp_ref=hour_ref>
{(0..24) {(0..24)
.map(|hour| { .map(|hour| {
let comp_ref = ComponentRef::<PanelTimeItemRef>::default(); let comp_ref = ComponentRef::<PanelTimeItemRef>::default();
@ -217,11 +217,11 @@ fn Panel(
} }
}) })
.collect_view()} .collect_view()}
<div class="thaw-time-picker-panel__time-padding"></div>
</Scrollbar> </Scrollbar>
<div class="thaw-time-picker-panel__time-padding"></div>
</div> </div>
<div class="thaw-time-picker-panel__time-minute" ref=minute_ref> <div class="thaw-time-picker-panel__time-minute">
<Scrollbar size=6> <Scrollbar size=6 comp_ref=minute_ref>
{(0..60) {(0..60)
.map(|minute| { .map(|minute| {
let comp_ref = ComponentRef::<PanelTimeItemRef>::default(); let comp_ref = ComponentRef::<PanelTimeItemRef>::default();
@ -249,11 +249,11 @@ fn Panel(
} }
}) })
.collect_view()} .collect_view()}
<div class="thaw-time-picker-panel__time-padding"></div>
</Scrollbar> </Scrollbar>
<div class="thaw-time-picker-panel__time-padding"></div>
</div> </div>
<div class="thaw-time-picker-panel__time-second" ref=second_ref> <div class="thaw-time-picker-panel__time-second">
<Scrollbar size=6> <Scrollbar size=6 comp_ref=second_ref>
{(0..60) {(0..60)
.map(|second| { .map(|second| {
let comp_ref = ComponentRef::<PanelTimeItemRef>::default(); let comp_ref = ComponentRef::<PanelTimeItemRef>::default();
@ -281,8 +281,8 @@ fn Panel(
} }
}) })
.collect_view()} .collect_view()}
<div class="thaw-time-picker-panel__time-padding"></div>
</Scrollbar> </Scrollbar>
<div class="thaw-time-picker-panel__time-padding"></div>
</div> </div>
</div> </div>
<div class="thaw-time-picker-panel__footer"> <div class="thaw-time-picker-panel__footer">
@ -300,32 +300,38 @@ fn Panel(
#[derive(Clone)] #[derive(Clone)]
struct PanelRef { struct PanelRef {
hour_ref: NodeRef<html::Div>, hour_ref: ComponentRef<ScrollbarRef>,
minute_ref: NodeRef<html::Div>, minute_ref: ComponentRef<ScrollbarRef>,
second_ref: NodeRef<html::Div>, second_ref: ComponentRef<ScrollbarRef>,
} }
impl PanelRef { impl PanelRef {
fn scroll_top(el: HtmlElement<html::Div>) { fn scroll_top(scrollbar_ref: ScrollbarRef) {
if let Ok(Some(slected_el)) = let Some(contetn_ref) = scrollbar_ref.content_ref.get_untracked() else {
el.query_selector(".thaw-time-picker-panel__time-item--slected") return;
{ };
use wasm_bindgen::JsCast; let Ok(Some(slected_el)) =
if let Ok(slected_el) = slected_el.dyn_into::<web_sys::HtmlElement>() { contetn_ref.query_selector(".thaw-time-picker-panel__time-item--slected")
el.set_scroll_top(slected_el.offset_top()); 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) { fn scroll_into_view(&self) {
if let Some(hour_el) = self.hour_ref.get_untracked() { if let Some(hour) = self.hour_ref.get_untracked() {
Self::scroll_top(hour_el); Self::scroll_top(hour);
} }
if let Some(minute_el) = self.minute_ref.get_untracked() { if let Some(minute) = self.minute_ref.get_untracked() {
Self::scroll_top(minute_el); Self::scroll_top(minute);
} }
if let Some(second_el) = self.second_ref.get_untracked() { if let Some(second) = self.second_ref.get_untracked() {
Self::scroll_top(second_el); Self::scroll_top(second);
} }
} }
} }