Skip to content

Commit 96a45e5

Browse files
committed
[*] DatePicker: date range selection
- Fix date range selection - Support disabled ranges
1 parent 3bba304 commit 96a45e5

File tree

5 files changed

+121
-51
lines changed

5 files changed

+121
-51
lines changed

preview/src/components/date_picker/component.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@ pub fn DatePicker(props: DatePickerProps) -> Element {
2020
selected_date: props.selected_date,
2121
disabled: props.disabled,
2222
read_only: props.read_only,
23+
min_date: props.min_date,
24+
max_date: props.max_date,
25+
disabled_ranges: props.disabled_ranges,
26+
roving_loop: props.roving_loop,
2327
attributes: props.attributes,
2428
date_picker::DatePickerPopover {
2529
popover_root: PopoverRoot,
@@ -41,6 +45,10 @@ pub fn DateRangePicker(props: DateRangePickerProps) -> Element {
4145
selected_range: props.selected_range,
4246
disabled: props.disabled,
4347
read_only: props.read_only,
48+
min_date: props.min_date,
49+
max_date: props.max_date,
50+
disabled_ranges: props.disabled_ranges,
51+
roving_loop: props.roving_loop,
4452
attributes: props.attributes,
4553
date_picker::DatePickerPopover {
4654
popover_root: PopoverRoot,
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
use super::super::component::*;
2+
use dioxus::prelude::*;
3+
4+
use dioxus_primitives::calendar::DateRange;
5+
use time::{ext::NumericalDuration, UtcDateTime};
6+
7+
#[component]
8+
pub fn Demo() -> Element {
9+
let mut selected_range = use_signal(|| None::<DateRange>);
10+
11+
let now = UtcDateTime::now().date();
12+
let disabled_ranges = use_signal(|| {
13+
vec![
14+
DateRange::new(now, now.saturating_add(3.days())),
15+
DateRange::new(now.saturating_add(15.days()), now.saturating_add(18.days())),
16+
DateRange::new(now.saturating_add(22.days()), now.saturating_add(23.days())),
17+
]
18+
});
19+
20+
rsx! {
21+
div {
22+
DateRangePicker {
23+
selected_range: selected_range(),
24+
on_range_change: move |range| {
25+
tracing::info!("Selected range: {:?}", range);
26+
selected_range.set(range);
27+
},
28+
disabled_ranges: disabled_ranges,
29+
DateRangePickerInput {}
30+
}
31+
}
32+
}
33+
}

preview/src/components/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ examples!(
6666
checkbox,
6767
collapsible,
6868
context_menu,
69-
date_picker[internationalized, range],
69+
date_picker[internationalized, range, unavailable_dates],
7070
dialog,
7171
dropdown_menu,
7272
hover_card,

primitives/src/calendar.rs

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -201,14 +201,16 @@ impl Display for DateRange {
201201
}
202202
}
203203

204+
/// Calendar available dates
204205
#[derive(Debug, Clone, PartialEq)]
205-
struct AvailableRanges {
206+
pub struct AvailableRanges {
206207
/// A sorted list of dates. Values after an odd number of elements are disabled.
207208
changes: Vec<Date>,
208209
}
209210

210211
impl AvailableRanges {
211-
fn new(disabled_ranges: &[DateRange]) -> Self {
212+
/// Create a new available dates
213+
pub fn new(disabled_ranges: &[DateRange]) -> Self {
212214
let mut sorted_range: Vec<_> = disabled_ranges
213215
.iter()
214216
.enumerate()
@@ -236,7 +238,8 @@ impl AvailableRanges {
236238
}
237239
}
238240

239-
fn valid_interval(&self, date: Date) -> bool {
241+
/// Check the availability of given date
242+
pub fn valid_interval(&self, date: Date) -> bool {
240243
match self.changes.binary_search(&date) {
241244
Ok(_) => false,
242245
Err(index) => index % 2 == 0,
@@ -266,6 +269,14 @@ impl AvailableRanges {
266269

267270
Some(DateRange::new(start, end))
268271
}
272+
273+
/// Get disabled ranges
274+
pub fn to_disabled_ranges(&self) -> Vec<DateRange> {
275+
self.changes
276+
.chunks(2)
277+
.map(|d| DateRange::new(d[0], d[1]))
278+
.collect()
279+
}
269280
}
270281

271282
/// The base context provided by the [`Calendar`] and the [`RangeCalendar`] component to its children.
@@ -557,7 +568,6 @@ pub fn Calendar(props: CalendarProps) -> Element {
557568
pub struct RangeCalendarContext {
558569
// The date that the user clicked on to begin range selection
559570
anchor_date: Signal<Option<Date>>,
560-
set_anchor_date: Callback<Option<Date>>,
561571
// Currently highlighted date range
562572
highlighted_range: Signal<Option<DateRange>>,
563573
set_selected_range: Callback<Option<DateRange>>,
@@ -570,7 +580,6 @@ impl RangeCalendarContext {
570580
Some(anchor) => {
571581
if let Some(date) = date {
572582
self.anchor_date.set(None);
573-
self.set_anchor_date.call(None);
574583

575584
let range = DateRange::new(date, anchor);
576585
self.set_selected_range.call(Some(range));
@@ -579,7 +588,6 @@ impl RangeCalendarContext {
579588
}
580589
None => {
581590
self.anchor_date.set(date);
582-
self.set_anchor_date.call(date);
583591

584592
let range = date.map(|d| DateRange::new(d, d));
585593
self.highlighted_range.set(range);
@@ -598,7 +606,6 @@ impl RangeCalendarContext {
598606
/// Set previous selected range
599607
pub fn reset_selection(&mut self, range: Option<DateRange>) {
600608
self.anchor_date.set(None);
601-
self.set_anchor_date.call(None);
602609
self.highlighted_range.set(range);
603610
}
604611
}
@@ -614,10 +621,6 @@ pub struct RangeCalendarProps {
614621
#[props(default)]
615622
pub on_range_change: Callback<Option<DateRange>>,
616623

617-
/// Callback when anchor date changes
618-
#[props(default)]
619-
pub(crate) on_anchor_change: Callback<Option<Date>>,
620-
621624
/// Callback when display weekday
622625
#[props(default = Callback::new(|weekday: Weekday| weekday_abbreviation(weekday).to_string()))]
623626
pub on_format_weekday: Callback<Weekday, String>,
@@ -739,7 +742,6 @@ pub fn RangeCalendar(props: RangeCalendarProps) -> Element {
739742
// Create RangeCalendar context provider for child components
740743
let mut ctx = use_context_provider(|| RangeCalendarContext {
741744
anchor_date,
742-
set_anchor_date: props.on_anchor_change,
743745
highlighted_range,
744746
set_selected_range: props.on_range_change,
745747
});

0 commit comments

Comments
 (0)