fix: the position is messed up when switching DatePicker panels (#240)

This commit is contained in:
luoxiaozero 2024-08-24 16:20:00 +08:00 committed by GitHub
parent b476835c11
commit 7b29f7da37
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 63 additions and 17 deletions

View file

@ -1,8 +1,9 @@
use super::PanelVariant;
use crate::{Button, ButtonAppearance, ButtonSize, CalendarItemDate};
use chrono::{Datelike, Days, Month, Months, NaiveDate};
use leptos::prelude::*;
use leptos::{html, prelude::*};
use std::ops::Deref;
use thaw_components::FollowerInjection;
use thaw_utils::{now_date, ArcOneCallback};
#[component]
@ -12,6 +13,14 @@ pub fn DatePanel(
close_panel: ArcOneCallback<Option<NaiveDate>>,
panel_variant: RwSignal<PanelVariant>,
) -> impl IntoView {
let follower = FollowerInjection::expect_context();
let panel_ref = NodeRef::<html::Div>::new();
Effect::new(move || {
let Some(_) = panel_ref.get() else {
return;
};
follower.refresh_position();
});
let dates = Memo::new(move |_| {
let show_date = show_date.get();
let show_date_month = show_date.month();
@ -87,7 +96,7 @@ pub fn DatePanel(
}
};
view! {
<div>
<div class="thaw-date-picker-date-panel" node_ref=panel_ref>
<div class="thaw-date-picker-date-panel__calendar">
<div class="thaw-date-picker-date-panel__header">
<Button

View file

@ -1,13 +1,23 @@
use super::PanelVariant;
use crate::{Button, ButtonAppearance, ButtonSize};
use chrono::{Datelike, Month, Months, NaiveDate};
use leptos::prelude::*;
use leptos::{html, prelude::*};
use thaw_components::FollowerInjection;
#[component]
pub fn MonthPanel(
date_panel_show_date: RwSignal<NaiveDate>,
panel_variant: RwSignal<PanelVariant>,
) -> impl IntoView {
let follower = FollowerInjection::expect_context();
let panel_ref = NodeRef::<html::Div>::new();
Effect::new(move || {
let Some(_) = panel_ref.get() else {
return;
};
follower.refresh_position();
});
let show_date = RwSignal::new(date_panel_show_date.get_untracked());
let previous_year = move |_| {
show_date.update(|date| {
@ -20,7 +30,7 @@ pub fn MonthPanel(
});
};
view! {
<div class="thaw-date-picker-month-panel">
<div class="thaw-date-picker-month-panel" node_ref=panel_ref>
<div class="thaw-date-picker-month-panel__header">
<Button
appearance=ButtonAppearance::Transparent

View file

@ -1,7 +1,8 @@
use super::PanelVariant;
use crate::{Button, ButtonAppearance, ButtonSize};
use chrono::{Datelike, NaiveDate};
use leptos::prelude::*;
use leptos::{html, prelude::*};
use thaw_components::FollowerInjection;
const MAX_YEAR: i32 = (i32::MAX >> 13) / 10 - 1;
const MIN_YEAR: i32 = (i32::MIN >> 13) / 10 + 1;
@ -11,6 +12,14 @@ pub fn YearPanel(
date_panel_show_date: RwSignal<NaiveDate>,
panel_variant: RwSignal<PanelVariant>,
) -> impl IntoView {
let follower = FollowerInjection::expect_context();
let panel_ref = NodeRef::<html::Div>::new();
Effect::new(move || {
let Some(_) = panel_ref.get() else {
return;
};
follower.refresh_position();
});
let show_min_year = RwSignal::new(date_panel_show_date.get_untracked().year() / 10);
let previous_year_range = move |_| {
show_min_year.update(|year| {
@ -27,7 +36,7 @@ pub fn YearPanel(
});
};
view! {
<div>
<div class="thaw-date-picker-year-panel" node_ref=panel_ref>
<div class="thaw-date-picker-year-panel__header">
<Button
appearance=ButtonAppearance::Transparent

View file

@ -8,6 +8,7 @@ use web_sys::wasm_bindgen::JsCast;
use crate::Teleport;
use get_placement_style::{get_follower_placement_offset, FollowerPlacementOffset};
use leptos::{
context::Provider,
ev,
html::{self, ElementType},
leptos_dom::helpers::WindowListenerHandle,
@ -187,23 +188,40 @@ where
}
});
on_cleanup(move || {
Owner::on_cleanup(move || {
remove_listener();
});
let follower_injection = FollowerInjection(Callback::new(move |_| sync_position()));
view! {
{children()}
<Teleport immediate=follower_show>
<div class="thaw-binder-follower-container">
<div
class="thaw-binder-follower-content"
data-thaw-placement=move || placement_str.get()
node_ref=content_ref
style=move || content_style.get()
>
{follower_children()}
<Provider value=follower_injection>
<div class="thaw-binder-follower-container">
<div
class="thaw-binder-follower-content"
data-thaw-placement=move || placement_str.get()
node_ref=content_ref
style=move || content_style.get()
>
{follower_children()}
</div>
</div>
</div>
</Provider>
</Teleport>
}
}
#[derive(Debug, Clone)]
pub struct FollowerInjection(Callback<()>);
impl FollowerInjection {
pub fn expect_context() -> Self {
expect_context()
}
pub fn refresh_position(&self) {
self.0.run(());
}
}

View file

@ -5,7 +5,7 @@ mod if_comp;
mod option_comp;
mod teleport;
pub use binder::{Binder, Follower, FollowerPlacement, FollowerWidth};
pub use binder::{Binder, Follower, FollowerInjection, FollowerPlacement, FollowerWidth};
pub use css_transition::CSSTransition;
pub use focus_trap::FocusTrap;
pub use if_comp::{ElseIf, If, Then};