diff --git a/crates/story/src/date_picker_story.rs b/crates/story/src/date_picker_story.rs index 926b378a..63a02770 100644 --- a/crates/story/src/date_picker_story.rs +++ b/crates/story/src/date_picker_story.rs @@ -1,4 +1,4 @@ -use chrono::{Days, Duration, Utc}; +use chrono::{Datelike, Days, Duration, Utc}; use gpui::{ px, App, AppContext, Context, Entity, Focusable, IntoElement, ParentElement as _, Render, Styled as _, Subscription, Window, @@ -15,6 +15,7 @@ pub struct DatePickerStory { date_picker: Entity, date_picker_small: Entity, date_picker_large: Entity, + data_picker_custom: Entity, date_picker_value: Option, date_range_picker: Entity, default_range_mode_picker: Entity, @@ -73,6 +74,16 @@ impl DatePickerStory { picker.set_date(now, window, cx); picker }); + let data_picker_custom = cx.new(|cx| { + let mut picker = DatePickerState::new(window, cx); + picker.set_disabled( + calendar::Matcher::custom(|date| date.day0() < 5), + window, + cx, + ); + picker.set_date(now, window, cx); + picker + }); let date_range_picker = cx.new(|cx| { let mut picker = DatePickerState::new(window, cx); picker.set_date( @@ -107,6 +118,7 @@ impl DatePickerStory { date_picker, date_picker_large, date_picker_small, + data_picker_custom, date_range_picker, default_range_mode_picker, date_picker_value: None, @@ -183,6 +195,11 @@ impl Render for DatePickerStory { .width(px(300.)), ), ) + .child( + section("Custom (First 5 days of each month disabled)") + .max_w_md() + .child(DatePicker::new(&self.data_picker_custom)), + ) .child( section("Date Range").max_w_md().child( DatePicker::new(&self.date_range_picker) diff --git a/crates/ui/src/time/calendar.rs b/crates/ui/src/time/calendar.rs index 7959951d..1be2bef4 100644 --- a/crates/ui/src/time/calendar.rs +++ b/crates/ui/src/time/calendar.rs @@ -179,6 +179,13 @@ pub enum Matcher { /// }) /// Will match the days that are between 2020-01-01 and 2020-01-03. Range(RangeMatcher), + /// Match dates using a custom function. + /// + /// let matcher = Matcher::Custom(Box::new(|date: &NaiveDate| { + /// date.day0() < 5 + /// })); + /// Will match first 5 days of each month + Custom(Box bool + Send + Sync>), } impl From> for Matcher { @@ -187,6 +194,15 @@ impl From> for Matcher { } } +impl From for Matcher +where + F: Fn(&NaiveDate) -> bool + Send + Sync +'static, +{ + fn from(f: F) -> Self { + Matcher::Custom(Box::new(f)) + } +} + impl Matcher { pub fn interval(before: Option, after: Option) -> Self { Matcher::Interval(IntervalMatcher { before, after }) @@ -209,6 +225,7 @@ impl Matcher { let to_check = range.to.map_or(false, |to| date > &to); !from_check && !to_check } + Matcher::Custom(f) => f(date), } } @@ -219,6 +236,13 @@ impl Matcher { _ => false, } } + + pub fn custom(f: F) -> Self + where + F: Fn(&NaiveDate) -> bool + Send + Sync + 'static, + { + Matcher::Custom(Box::new(f)) + } } /// Use to store the state of the calendar.