WARNING: THIS SITE IS A MIRROR OF GITHUB.COM / IT CANNOT LOGIN OR REGISTER ACCOUNTS / THE CONTENTS ARE PROVIDED AS-IS / THIS SITE ASSUMES NO RESPONSIBILITY FOR ANY DISPLAYED CONTENT OR LINKS / IF YOU FOUND SOMETHING MAY NOT GOOD FOR EVERYONE, CONTACT ADMIN AT ilovescratch@foxmail.com
Skip to content

Commit a104d37

Browse files
committed
[*] DatePicker: updates
- Fix docs - Add alignment between the days of the week and the Calendar grid - Add simple title variant in Calendar demo - Add css for Calendar title - Update time crate version (support PartialOrd for Month) - Fix view day on next/previous button click - Fix DateRangePickerContext (sync data) - Fix arrow navigation
1 parent afa968a commit a104d37

File tree

7 files changed

+71
-78
lines changed

7 files changed

+71
-78
lines changed

Cargo.lock

Lines changed: 8 additions & 8 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

preview/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ dioxus-i18n = { git = "https://github.com/ealmloff/dioxus-i18n", branch = "bump-
1111
unic-langid = { version = "0.9", features = ["macros"] }
1212
strum = { version = "0.27.2", features = ["derive"] }
1313
tracing.workspace = true
14-
time = { version = "0.3.41", features = ["std", "macros"] }
14+
time = { version = "0.3.44", features = ["std", "macros"] }
1515

1616
[build-dependencies]
1717
syntect = "5.2"

preview/src/components/calendar/style.css

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,14 @@
5959
cursor: not-allowed;
6060
}
6161

62+
.calendar-month-title {
63+
display: flex;
64+
width: 100%;
65+
height: 1.75rem;
66+
align-items: center;
67+
justify-content: center;
68+
}
69+
6270
/* Calendar Grid */
6371
.calendar-div {
6472
display: flex;
@@ -77,7 +85,7 @@
7785
}
7886

7987
.calendar-grid-day-header {
80-
width: 2rem;
88+
flex: 1;
8189
color: var(--secondary-color-5);
8290
font-size: 12px;
8391
font-weight: 300;
@@ -271,4 +279,4 @@ td:has(.calendar-grid-cell[data-selection-end="true"]) {
271279
stroke-linecap: round;
272280
stroke-linejoin: round;
273281
stroke-width: 2;
274-
}
282+
}

preview/src/components/calendar/variants/multi_month/mod.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,7 @@ pub fn Demo() -> Element {
2727
CalendarHeader {
2828
CalendarNavigation {
2929
CalendarPreviousMonthButton {}
30-
CalendarSelectMonth {}
31-
CalendarSelectYear {}
30+
CalendarMonthTitle {}
3231
CalendarNextMonthButton {}
3332
}
3433
}

primitives/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ repository = "https://github.com/DioxusLabs/components"
1414
[dependencies]
1515
dioxus.workspace = true
1616
dioxus-time = { git = "https://github.com/ealmloff/dioxus-std", branch = "0.7" }
17-
time = { version = "0.3.41", features = ["std", "macros", "parsing"] }
17+
time = { version = "0.3.44", features = ["std", "macros", "parsing"] }
1818
num-integer = "0.1.46"
1919
tracing.workspace = true
2020

primitives/src/calendar.rs

Lines changed: 45 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -154,32 +154,13 @@ fn replace_month(date: Date, month: Month) -> Date {
154154
.expect("invalid or out-of-range date")
155155
}
156156

157-
fn gt(lhs_month: Month, rhs_month: Month) -> bool {
158-
let lhs = lhs_month as u8;
159-
let rhs = rhs_month as u8;
160-
lhs > rhs
161-
}
162-
163-
fn nth_month_prev(date: Date, n: u8) -> Option<Date> {
164-
match n {
165-
0 => Some(date),
166-
n => {
167-
let month = date.month();
168-
let nth_month: Month = month.nth_prev(n);
169-
let year = date.year() - if gt(month, nth_month) { 0 } else { 1 };
170-
let max_day = nth_month.length(year);
171-
Date::from_calendar_date(year, nth_month, date.day().min(max_day)).ok()
172-
}
173-
}
174-
}
175-
176157
fn nth_month_next(date: Date, n: u8) -> Option<Date> {
177158
match n {
178159
0 => Some(date),
179160
n => {
180161
let month = date.month();
181162
let nth_month = month.nth_next(n);
182-
let year = date.year() + if gt(month, nth_month) { 1 } else { 0 };
163+
let year = date.year() + if month > nth_month { 1 } else { 0 };
183164
let max_day = nth_month.length(year);
184165
Date::from_calendar_date(year, nth_month, date.day().min(max_day)).ok()
185166
}
@@ -328,6 +309,7 @@ pub struct BaseCalendarContext {
328309
today: Date,
329310
first_day_of_week: Weekday,
330311
enabled_date_range: DateRange,
312+
month_count: u8,
331313
}
332314

333315
impl BaseCalendarContext {
@@ -524,6 +506,7 @@ pub fn Calendar(props: CalendarProps) -> Element {
524506
today: props.today,
525507
first_day_of_week: props.first_day_of_week,
526508
enabled_date_range: DateRange::new(props.min_date, props.max_date),
509+
month_count: props.month_count,
527510
});
528511
// Create Calendar context provider for child components
529512
use_context_provider(|| CalendarContext {
@@ -542,11 +525,18 @@ pub fn Calendar(props: CalendarProps) -> Element {
542525
return;
543526
};
544527
let mut set_focused_date = |new_date: Option<Date>| {
545-
let mut view_date = (base_ctx.view_date)();
546528
if let Some(date) = new_date {
547-
if date.month() != view_date.month() {
548-
view_date = date.replace_day(1).unwrap();
529+
let min_date = (base_ctx.view_date)().replace_day(1).unwrap();
530+
if date < min_date {
531+
let view_date = previous_month(min_date).unwrap_or(min_date);
549532
(base_ctx.set_view_date)(view_date);
533+
} else {
534+
let max_date = nth_month_next(min_date, props.month_count)
535+
.unwrap_or(min_date);
536+
if date >= max_date {
537+
let view_date = next_month(min_date).unwrap_or(min_date);
538+
(base_ctx.set_view_date)(view_date);
539+
}
550540
}
551541
}
552542
match new_date {
@@ -591,12 +581,8 @@ pub fn Calendar(props: CalendarProps) -> Element {
591581
}
592582
},
593583
for offset in 0..props.month_count {
594-
CalendarView {
595-
offset,
596-
div {
597-
..props.attributes.clone(),
598-
{props.children.clone()}
599-
}
584+
CalendarView { offset,
585+
div { ..props.attributes.clone(),{props.children.clone()} }
600586
}
601587
}
602588
}
@@ -781,6 +767,7 @@ pub fn RangeCalendar(props: RangeCalendarProps) -> Element {
781767
today: props.today,
782768
first_day_of_week: props.first_day_of_week,
783769
enabled_date_range: DateRange::new(props.min_date, props.max_date),
770+
month_count: props.month_count,
784771
});
785772

786773
// Create RangeCalendar context provider for child components
@@ -811,11 +798,18 @@ pub fn RangeCalendar(props: RangeCalendarProps) -> Element {
811798
}
812799
}
813800
let mut set_focused_date = |new_date: Option<Date>| {
814-
let mut view_date = (base_ctx.view_date)();
815801
if let Some(date) = new_date {
816-
if date.month() != view_date.month() {
817-
view_date = date.replace_day(1).unwrap();
802+
let min_date = (base_ctx.view_date)().replace_day(1).unwrap();
803+
if date < min_date {
804+
let view_date = previous_month(min_date).unwrap_or(min_date);
818805
(base_ctx.set_view_date)(view_date);
806+
} else {
807+
let max_date = nth_month_next(min_date, props.month_count)
808+
.unwrap_or(min_date);
809+
if date >= max_date {
810+
let view_date = next_month(min_date).unwrap_or(min_date);
811+
(base_ctx.set_view_date)(view_date);
812+
}
819813
}
820814
}
821815
match new_date {
@@ -868,12 +862,8 @@ pub fn RangeCalendar(props: RangeCalendarProps) -> Element {
868862
}
869863
},
870864
for offset in 0..props.month_count {
871-
CalendarView {
872-
offset,
873-
div {
874-
..props.attributes.clone(),
875-
{props.children.clone()}
876-
}
865+
CalendarView { offset,
866+
div { ..props.attributes.clone(),{props.children.clone()} }
877867
}
878868
}
879869
}
@@ -890,7 +880,7 @@ struct CalendarViewProps {
890880
pub children: Element,
891881
}
892882

893-
#[derive(Clone, PartialEq)]
883+
#[derive(Copy, Clone, PartialEq)]
894884
struct CalendarViewContext {
895885
offset: u8,
896886
view_date: Signal<Date>,
@@ -902,25 +892,17 @@ impl CalendarViewContext {
902892
self.view_date.set(new_date);
903893
}
904894

905-
fn sub_months(&self, date: Date) -> Option<Date> {
906-
nth_month_prev(date, self.offset.max(1))
907-
}
908-
909-
fn add_months(&self, date: Date) -> Option<Date> {
910-
nth_month_next(date, self.offset.max(1))
911-
}
912-
913895
fn replace_year(&self, date: Date, year: i32) -> Date {
914896
let month = date.month();
915897
let view_month = (self.view_date)().month();
916-
let year = year - if gt(month, view_month) { 1 } else { 0 };
898+
let year = year - if month > view_month { 1 } else { 0 };
917899
date.replace_year(year).unwrap_or(date)
918900
}
919901

920902
fn replace_month(&self, date: Date, month: Month) -> Date {
921903
let view_date = (self.view_date)();
922904
let new_month = month.nth_prev(self.offset);
923-
let year = view_date.year() - if gt(month, view_date.month()) { 1 } else { 0 };
905+
let year = view_date.year() - if month > view_date.month() { 1 } else { 0 };
924906
Date::from_calendar_date(year, new_month, 1).unwrap_or(date)
925907
}
926908

@@ -1147,6 +1129,10 @@ pub fn CalendarPreviousMonthButton(props: CalendarPreviousMonthButtonProps) -> E
11471129
let ctx: BaseCalendarContext = use_context();
11481130
let view_ctx: CalendarViewContext = use_context();
11491131

1132+
if view_ctx.offset != 0 {
1133+
return rsx! {};
1134+
}
1135+
11501136
// disable previous button when we reach the limit
11511137
let button_disabled = use_memo(move || {
11521138
// Get the current view date from context
@@ -1168,7 +1154,7 @@ pub fn CalendarPreviousMonthButton(props: CalendarPreviousMonthButtonProps) -> E
11681154
let handle_prev_month = move |e: Event<MouseData>| {
11691155
e.prevent_default();
11701156
let current_view = (ctx.view_date)();
1171-
if let Some(date) = view_ctx.sub_months(current_view) {
1157+
if let Some(date) = previous_month(current_view) {
11721158
ctx.set_view_date.call(date)
11731159
}
11741160
};
@@ -1248,6 +1234,10 @@ pub fn CalendarNextMonthButton(props: CalendarNextMonthButtonProps) -> Element {
12481234
let ctx: BaseCalendarContext = use_context();
12491235
let view_ctx: CalendarViewContext = use_context();
12501236

1237+
if view_ctx.offset + 1 != ctx.month_count {
1238+
return rsx! {};
1239+
}
1240+
12511241
// disable next button when we reach the limit
12521242
let button_disabled = use_memo(move || {
12531243
// Get the current view date from context
@@ -1273,7 +1263,7 @@ pub fn CalendarNextMonthButton(props: CalendarNextMonthButtonProps) -> Element {
12731263
let handle_next_month = move |e: Event<MouseData>| {
12741264
e.prevent_default();
12751265
let current_view = (ctx.view_date)();
1276-
if let Some(date) = view_ctx.add_months(current_view) {
1266+
if let Some(date) = next_month(current_view) {
12771267
ctx.set_view_date.call(date)
12781268
}
12791269
};
@@ -1511,7 +1501,7 @@ pub fn CalendarGrid(props: CalendarGridProps) -> Element {
15111501
// Day name headers
15121502
for (weekday, label) in weekday_headers() {
15131503
th {
1514-
key: "{weekday:?}", // Add key for efficient diffing
1504+
key: "{weekday:?}", // Add key for efficient diffing
15151505
class: "calendar-grid-day-header",
15161506
{label}
15171507
}
@@ -1890,9 +1880,7 @@ fn relative_calendar_month(
18901880
} else if date > base_ctx.enabled_date_range.end {
18911881
RelativeMonth::Next
18921882
} else {
1893-
let lhs = date.month() as u8;
1894-
let rhs = current_month as u8;
1895-
match lhs.cmp(&rhs) {
1883+
match date.month().cmp(&current_month) {
18961884
std::cmp::Ordering::Less => RelativeMonth::Last,
18971885
std::cmp::Ordering::Equal => RelativeMonth::Current,
18981886
std::cmp::Ordering::Greater => RelativeMonth::Next,
@@ -1937,7 +1925,7 @@ fn SingleCalendarDay(props: CalendarDayProps) -> Element {
19371925
let view_date = (view_ctx.view_date)();
19381926
let month = relative_calendar_month(date, &base_ctx, view_date.month());
19391927
let in_current_month = month.current_month();
1940-
let is_focused = move || base_ctx.is_focused(date);
1928+
let is_focused = move || in_current_month && base_ctx.is_focused(date);
19411929
let is_today = date == base_ctx.today;
19421930
let is_unavailable = base_ctx.is_unavailable(date);
19431931

@@ -2011,7 +1999,7 @@ fn RangeCalendarDay(props: CalendarDayProps) -> Element {
20111999
let view_date = (view_ctx.view_date)();
20122000
let month = relative_calendar_month(date, &base_ctx, view_date.month());
20132001
let in_current_month = month.current_month();
2014-
let is_focused = move || base_ctx.is_focused(date);
2002+
let is_focused = move || in_current_month && base_ctx.is_focused(date);
20152003
let is_today = date == base_ctx.today;
20162004
let is_unavailable = base_ctx.is_unavailable(date);
20172005

primitives/src/date_picker.rs

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -169,19 +169,18 @@ pub fn DatePicker(props: DatePickerProps) -> Element {
169169
}
170170
}
171171

172-
/// The context provided by the [`RangeCalendar`] component to its children.
172+
/// The context provided by the [`DateRangePicker`] component to its children.
173173
#[derive(Copy, Clone)]
174174
pub struct DateRangePickerContext {
175175
// Currently selected date range
176-
date_range: Signal<Option<DateRange>>,
176+
date_range: ReadSignal<Option<DateRange>>,
177177
set_selected_range: Callback<Option<DateRange>>,
178178
}
179179

180180
impl DateRangePickerContext {
181181
/// Set the selected date
182182
pub fn set_range(&mut self, range: Option<DateRange>) {
183183
if (self.date_range)() != range {
184-
self.date_range.set(range);
185184
self.set_selected_range.call(range);
186185
}
187186
}
@@ -294,16 +293,15 @@ pub fn DateRangePicker(props: DateRangePickerProps) -> Element {
294293
month_count: props.month_count,
295294
});
296295

297-
let date_range = use_signal(|| (props.selected_range)());
298296
use_context_provider(|| DateRangePickerContext {
299-
date_range,
297+
date_range: props.selected_range,
300298
set_selected_range: props.on_range_change,
301299
});
302300

303301
rsx! {
304302
div {
305303
role: "group",
306-
aria_label: "DateRange",
304+
aria_label: "Date Range",
307305
"data-disabled": (props.disabled)(),
308306
..props.attributes,
309307
{props.children}
@@ -397,7 +395,7 @@ pub fn DatePickerPopover(props: DatePickerPopoverProps) -> Element {
397395
}
398396
}
399397

400-
/// The props for the [`Calendar`] and [`RangeCalendar`] component.
398+
/// The props for the Calendar component.
401399
#[allow(unpredictable_function_pointer_comparisons)]
402400
#[derive(Props, Clone, PartialEq)]
403401
pub struct DatePickerCalendarProps<T: Properties + PartialEq> {

0 commit comments

Comments
 (0)