chrore: Refactor the disabled API for NumberInput, DatePicker, OtpInput, Calandar. (#1102)
- Added `disabled` method to OtpInput.
- Added `disabled` method to DatePicker.
- Added `disabled_matcher` method to CalendarState.
## Break Changes
- The `InputState` has been removed `disabled` and `set_disabled`
method, the disabled state should assign from TextInput element.
```diff
- let state = InputState::new("input1").disabled(true)
+ let state = InputState::new("input1");
+ TextInput::new(&state).disabled(true)
```
- Renamed `set_disabled` method to `set_disabled_matcher` from
`CalendarState`.
- Removed `set_disabled` method from `DatePickerState`, use
`disabled_matcher` method in `DatePicker` element.
---------
Co-authored-by: Jason Lee <huacnlee@gmail.com>
This commit is contained in:
parent
c07bc4aaad
commit
7487662343
9 changed files with 167 additions and 82 deletions
|
|
@ -13,6 +13,7 @@ pub struct CalendarStory {
|
|||
focus_handle: FocusHandle,
|
||||
calendar: Entity<CalendarState>,
|
||||
calendar_wide: Entity<CalendarState>,
|
||||
calendar_with_disabled_matcher: Entity<CalendarState>,
|
||||
}
|
||||
|
||||
impl super::Story for CalendarStory {
|
||||
|
|
@ -37,10 +38,13 @@ impl CalendarStory {
|
|||
fn new(window: &mut Window, cx: &mut Context<Self>) -> Self {
|
||||
let calendar = cx.new(|cx| CalendarState::new(window, cx));
|
||||
let calendar_wide = cx.new(|cx| CalendarState::new(window, cx));
|
||||
let calendar_with_disabled_matcher =
|
||||
cx.new(|cx| CalendarState::new(window, cx).disabled_matcher(vec![0, 3, 6]));
|
||||
|
||||
Self {
|
||||
calendar,
|
||||
calendar_wide,
|
||||
calendar_with_disabled_matcher,
|
||||
focus_handle: cx.focus_handle(),
|
||||
}
|
||||
}
|
||||
|
|
@ -66,5 +70,10 @@ impl Render for CalendarStory {
|
|||
.max_w_md()
|
||||
.child(Calendar::new(&self.calendar_wide).number_of_months(3)),
|
||||
)
|
||||
.child(
|
||||
section("With Disabled matcher (Sundays, Wednesdays, Saturdays)")
|
||||
.max_w_md()
|
||||
.child(Calendar::new(&self.calendar_with_disabled_matcher)),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -45,18 +45,17 @@ impl DatePickerStory {
|
|||
fn new(window: &mut Window, cx: &mut Context<Self>) -> Self {
|
||||
let now = chrono::Local::now().naive_local().date();
|
||||
let date_picker = cx.new(|cx| {
|
||||
let mut picker = DatePickerState::new(window, cx);
|
||||
let mut picker = DatePickerState::new(window, cx).disabled_matcher(vec![0, 6]);
|
||||
picker.set_date(now, window, cx);
|
||||
picker.set_disabled(vec![0, 6], window, cx);
|
||||
picker
|
||||
});
|
||||
let date_picker_large = cx.new(|cx| {
|
||||
let mut picker = DatePickerState::new(window, cx).date_format("%Y-%m-%d");
|
||||
picker.set_disabled(
|
||||
calendar::Matcher::range(Some(now), now.checked_add_days(Days::new(7))),
|
||||
window,
|
||||
cx,
|
||||
);
|
||||
let mut picker = DatePickerState::new(window, cx)
|
||||
.date_format("%Y-%m-%d")
|
||||
.disabled_matcher(calendar::Matcher::range(
|
||||
Some(now),
|
||||
now.checked_add_days(Days::new(7)),
|
||||
));
|
||||
picker.set_date(
|
||||
now.checked_sub_days(Days::new(1)).unwrap_or_default(),
|
||||
window,
|
||||
|
|
@ -65,22 +64,15 @@ impl DatePickerStory {
|
|||
picker
|
||||
});
|
||||
let date_picker_small = cx.new(|cx| {
|
||||
let mut picker = DatePickerState::new(window, cx);
|
||||
picker.set_disabled(
|
||||
let mut picker = DatePickerState::new(window, cx).disabled_matcher(
|
||||
calendar::Matcher::interval(Some(now), now.checked_add_days(Days::new(5))),
|
||||
window,
|
||||
cx,
|
||||
);
|
||||
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,
|
||||
);
|
||||
let mut picker = DatePickerState::new(window, cx)
|
||||
.disabled_matcher(calendar::Matcher::custom(|date| date.day0() < 5));
|
||||
picker.set_date(now, window, cx);
|
||||
picker
|
||||
});
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ use crate::{section, Tab, TabPrev};
|
|||
use gpui_component::{
|
||||
button::{Button, ButtonVariants},
|
||||
input::{InputEvent, InputState, MaskPattern, NumberInput, NumberInputEvent, StepAction},
|
||||
v_flex, ActiveTheme, FocusableCycle, IconName, Sizable,
|
||||
v_flex, ActiveTheme, Disableable, FocusableCycle, IconName, Sizable,
|
||||
};
|
||||
|
||||
const CONTEXT: &str = "NumberInputStory";
|
||||
|
|
@ -29,6 +29,7 @@ pub struct NumberInputStory {
|
|||
number_input3_value: f64,
|
||||
number_input4: Entity<InputState>,
|
||||
number_input4_value: f64,
|
||||
disabled_input: Entity<InputState>,
|
||||
|
||||
_subscriptions: Vec<Subscription>,
|
||||
}
|
||||
|
|
@ -88,6 +89,12 @@ impl NumberInputStory {
|
|||
})
|
||||
});
|
||||
|
||||
let disabled_input = cx.new(|cx| {
|
||||
InputState::new(window, cx)
|
||||
.default_value("100")
|
||||
.placeholder("Disabled input")
|
||||
});
|
||||
|
||||
let _subscriptions = vec![
|
||||
cx.subscribe_in(&number_input1, window, Self::on_input_event),
|
||||
cx.subscribe_in(&number_input1, window, Self::on_number_input_event),
|
||||
|
|
@ -97,6 +104,8 @@ impl NumberInputStory {
|
|||
cx.subscribe_in(&number_input3, window, Self::on_number_input_event),
|
||||
cx.subscribe_in(&number_input4, window, Self::on_input_event),
|
||||
cx.subscribe_in(&number_input4, window, Self::on_number_input_event),
|
||||
cx.subscribe_in(&disabled_input, window, Self::on_input_event),
|
||||
cx.subscribe_in(&disabled_input, window, Self::on_number_input_event),
|
||||
];
|
||||
|
||||
Self {
|
||||
|
|
@ -108,6 +117,7 @@ impl NumberInputStory {
|
|||
number_input3_value: 0.0,
|
||||
number_input4,
|
||||
number_input4_value: 0.0,
|
||||
disabled_input,
|
||||
_subscriptions,
|
||||
}
|
||||
}
|
||||
|
|
@ -238,6 +248,11 @@ impl Render for NumberInputStory {
|
|||
.max_w_md()
|
||||
.child(NumberInput::new(&self.number_input1)),
|
||||
)
|
||||
.child(
|
||||
section("Disabled")
|
||||
.max_w_md()
|
||||
.child(NumberInput::new(&self.disabled_input).disabled(true)),
|
||||
)
|
||||
.child(
|
||||
section("Small Size with suffix").max_w_md().child(
|
||||
NumberInput::new(&self.number_input2)
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ use gpui_component::{
|
|||
checkbox::Checkbox,
|
||||
h_flex,
|
||||
input::{InputEvent, OtpInput, OtpState},
|
||||
v_flex, FocusableCycle, Sizable, StyledExt,
|
||||
v_flex, Disableable as _, FocusableCycle, Sizable, StyledExt,
|
||||
};
|
||||
|
||||
use crate::{section, Tab, TabPrev};
|
||||
|
|
@ -28,6 +28,7 @@ pub struct OtpInputStory {
|
|||
otp_state_small: Entity<OtpState>,
|
||||
otp_state_large: Entity<OtpState>,
|
||||
otp_state_sized: Entity<OtpState>,
|
||||
otp_state_disabled: Entity<OtpState>,
|
||||
|
||||
_subscriptions: Vec<Subscription>,
|
||||
}
|
||||
|
|
@ -88,6 +89,11 @@ impl OtpInputStory {
|
|||
.masked(true)
|
||||
.default_value("654321")
|
||||
}),
|
||||
otp_state_disabled: cx.new(|cx| {
|
||||
OtpState::new(6, window, cx)
|
||||
.masked(true)
|
||||
.default_value("123456")
|
||||
}),
|
||||
_subscriptions,
|
||||
}
|
||||
}
|
||||
|
|
@ -102,17 +108,20 @@ impl OtpInputStory {
|
|||
|
||||
fn toggle_opt_masked(&mut self, _: &bool, window: &mut Window, cx: &mut Context<Self>) {
|
||||
self.otp_masked = !self.otp_masked;
|
||||
self.otp_state.update(cx, |input, cx| {
|
||||
input.set_masked(self.otp_masked, window, cx)
|
||||
self.otp_state.update(cx, |state, cx| {
|
||||
state.set_masked(self.otp_masked, window, cx)
|
||||
});
|
||||
self.otp_state_small.update(cx, |input, cx| {
|
||||
input.set_masked(self.otp_masked, window, cx)
|
||||
self.otp_state_small.update(cx, |state, cx| {
|
||||
state.set_masked(self.otp_masked, window, cx)
|
||||
});
|
||||
self.otp_state_large.update(cx, |input, cx| {
|
||||
input.set_masked(self.otp_masked, window, cx)
|
||||
self.otp_state_large.update(cx, |state, cx| {
|
||||
state.set_masked(self.otp_masked, window, cx)
|
||||
});
|
||||
self.otp_state_sized.update(cx, |input, cx| {
|
||||
input.set_masked(self.otp_masked, window, cx)
|
||||
self.otp_state_sized.update(cx, |state, cx| {
|
||||
state.set_masked(self.otp_masked, window, cx)
|
||||
});
|
||||
self.otp_state_disabled.update(cx, |state, cx| {
|
||||
state.set_masked(self.otp_masked, window, cx)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -162,5 +171,8 @@ impl Render for OtpInputStory {
|
|||
.with_size(px(55.)),
|
||||
),
|
||||
)
|
||||
.child(
|
||||
section("Disabled").child(OtpInput::new(&self.otp_state_disabled).disabled(true)),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ use gpui::{
|
|||
|
||||
use crate::{
|
||||
button::{Button, ButtonVariants as _},
|
||||
h_flex, ActiveTheme, IconName, Sizable, Size, StyleSized, StyledExt as _,
|
||||
h_flex, ActiveTheme, Disableable, IconName, Sizable, Size, StyleSized, StyledExt as _,
|
||||
};
|
||||
|
||||
use super::{InputState, TextInput};
|
||||
|
|
@ -30,6 +30,7 @@ pub struct NumberInput {
|
|||
prefix: Option<AnyElement>,
|
||||
suffix: Option<AnyElement>,
|
||||
appearance: bool,
|
||||
disabled: bool,
|
||||
}
|
||||
|
||||
impl NumberInput {
|
||||
|
|
@ -42,6 +43,7 @@ impl NumberInput {
|
|||
prefix: None,
|
||||
suffix: None,
|
||||
appearance: true,
|
||||
disabled: false,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -84,6 +86,13 @@ impl NumberInput {
|
|||
}
|
||||
}
|
||||
|
||||
impl Disableable for NumberInput {
|
||||
fn disabled(mut self, disabled: bool) -> Self {
|
||||
self.disabled = disabled;
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl InputState {
|
||||
fn on_action_increment(&mut self, _: &Increment, window: &mut Window, cx: &mut Context<Self>) {
|
||||
self.on_number_input_step(StepAction::Increment, window, cx);
|
||||
|
|
@ -142,6 +151,7 @@ impl RenderOnce for NumberInput {
|
|||
.border_1()
|
||||
.rounded(cx.theme().radius)
|
||||
})
|
||||
.when(self.disabled, |this| this.bg(cx.theme().muted))
|
||||
.when(focused, |this| this.focused_border(cx))
|
||||
.child(
|
||||
Button::new("minus")
|
||||
|
|
@ -149,6 +159,7 @@ impl RenderOnce for NumberInput {
|
|||
.with_size(self.size.smaller())
|
||||
.icon(IconName::Minus)
|
||||
.compact()
|
||||
.disabled(self.disabled)
|
||||
.on_click({
|
||||
let state = self.state.clone();
|
||||
move |_, window, cx| {
|
||||
|
|
@ -159,6 +170,7 @@ impl RenderOnce for NumberInput {
|
|||
.child(
|
||||
TextInput::new(&self.state)
|
||||
.appearance(false)
|
||||
.disabled(self.disabled)
|
||||
.px(px(2.))
|
||||
.gap_0()
|
||||
.when_some(self.prefix, |this, prefix| this.prefix(prefix))
|
||||
|
|
@ -170,6 +182,7 @@ impl RenderOnce for NumberInput {
|
|||
.with_size(self.size.smaller())
|
||||
.icon(IconName::Plus)
|
||||
.compact()
|
||||
.disabled(self.disabled)
|
||||
.on_click({
|
||||
let state = self.state.clone();
|
||||
move |_, window, cx| {
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ use gpui::{
|
|||
};
|
||||
|
||||
use super::{blink_cursor::BlinkCursor, InputEvent};
|
||||
use crate::{h_flex, v_flex, ActiveTheme, Icon, IconName, Sizable, Size};
|
||||
use crate::{h_flex, v_flex, ActiveTheme, Disableable, Icon, IconName, Sizable, Size};
|
||||
|
||||
pub struct OtpState {
|
||||
focus_handle: FocusHandle,
|
||||
|
|
@ -183,6 +183,7 @@ pub struct OtpInput {
|
|||
state: Entity<OtpState>,
|
||||
number_of_groups: usize,
|
||||
size: Size,
|
||||
disabled: bool,
|
||||
}
|
||||
|
||||
impl OtpInput {
|
||||
|
|
@ -192,6 +193,7 @@ impl OtpInput {
|
|||
state: state.clone(),
|
||||
number_of_groups: 2,
|
||||
size: Size::Medium,
|
||||
disabled: false,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -201,7 +203,12 @@ impl OtpInput {
|
|||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl Disableable for OtpInput {
|
||||
fn disabled(mut self, disabled: bool) -> Self {
|
||||
self.disabled = disabled;
|
||||
self
|
||||
}
|
||||
}
|
||||
impl Sizable for OtpInput {
|
||||
fn with_size(mut self, size: impl Into<crate::Size>) -> Self {
|
||||
self.size = size.into();
|
||||
|
|
@ -248,6 +255,10 @@ impl RenderOnce for OtpInput {
|
|||
.border_1()
|
||||
.border_color(cx.theme().input)
|
||||
.bg(cx.theme().background)
|
||||
.when(self.disabled, |this| {
|
||||
this.bg(cx.theme().muted)
|
||||
.text_color(cx.theme().muted_foreground)
|
||||
})
|
||||
.when(is_input_focused, |this| this.border_color(cx.theme().ring))
|
||||
.when(cx.theme().shadow, |this| this.shadow_xs())
|
||||
.items_center()
|
||||
|
|
@ -271,6 +282,9 @@ impl RenderOnce for OtpInput {
|
|||
this.child(
|
||||
Icon::new(IconName::Asterisk)
|
||||
.text_color(cx.theme().secondary_foreground)
|
||||
.when(self.disabled, |this| {
|
||||
this.text_color(cx.theme().muted_foreground)
|
||||
})
|
||||
.with_size(text_size),
|
||||
)
|
||||
} else {
|
||||
|
|
@ -294,7 +308,9 @@ impl RenderOnce for OtpInput {
|
|||
v_flex()
|
||||
.id(("otp-input", self.state.entity_id()))
|
||||
.track_focus(&self.state.read(cx).focus_handle)
|
||||
.on_key_down(window.listener_for(&self.state, OtpState::on_key_down))
|
||||
.when(!self.disabled, |this| {
|
||||
this.on_key_down(window.listener_for(&self.state, OtpState::on_key_down))
|
||||
})
|
||||
.items_center()
|
||||
.child(
|
||||
h_flex().items_center().gap_5().children(
|
||||
|
|
|
|||
|
|
@ -723,24 +723,11 @@ impl InputState {
|
|||
/// Set with disabled mode.
|
||||
///
|
||||
/// See also: [`Self::set_disabled`], [`Self::is_disabled`].
|
||||
pub fn disabled(mut self, disabled: bool) -> Self {
|
||||
pub(crate) fn disabled(mut self, disabled: bool) -> Self {
|
||||
self.disabled = disabled;
|
||||
self
|
||||
}
|
||||
|
||||
/// Set the disabled state of the input field.
|
||||
///
|
||||
/// See also: [`Self::disabled`], [`Self::is_disabled`].
|
||||
pub fn set_disabled(&mut self, disabled: bool, _: &mut Window, cx: &mut Context<Self>) {
|
||||
self.disabled = disabled;
|
||||
cx.notify();
|
||||
}
|
||||
|
||||
/// Return is the input field is disabled.
|
||||
pub fn is_disabled(&self) -> bool {
|
||||
self.disabled
|
||||
}
|
||||
|
||||
/// Set with password masked state.
|
||||
pub fn masked(mut self, masked: bool) -> Self {
|
||||
self.masked = masked;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use std::borrow::Cow;
|
||||
use std::{borrow::Cow, rc::Rc};
|
||||
|
||||
use chrono::{Datelike, Local, NaiveDate};
|
||||
use gpui::{
|
||||
|
|
@ -248,6 +248,7 @@ impl Matcher {
|
|||
|
||||
#[derive(IntoElement)]
|
||||
pub struct Calendar {
|
||||
id: ElementId,
|
||||
size: Size,
|
||||
state: Entity<CalendarState>,
|
||||
style: StyleRefinement,
|
||||
|
|
@ -267,7 +268,7 @@ pub struct CalendarState {
|
|||
today: NaiveDate,
|
||||
/// Number of the months view to show.
|
||||
number_of_months: usize,
|
||||
disabled: Option<Matcher>,
|
||||
pub(crate) disabled_matcher: Option<Rc<Matcher>>,
|
||||
}
|
||||
|
||||
impl CalendarState {
|
||||
|
|
@ -283,11 +284,29 @@ impl CalendarState {
|
|||
year_page: 0,
|
||||
today,
|
||||
number_of_months: 1,
|
||||
disabled: None,
|
||||
disabled_matcher: None,
|
||||
}
|
||||
.year_range((today.year() - 50, today.year() + 50))
|
||||
}
|
||||
|
||||
/// Set the disabled matcher of the calendar state.
|
||||
pub fn disabled_matcher(mut self, matcher: impl Into<Matcher>) -> Self {
|
||||
self.disabled_matcher = Some(Rc::new(matcher.into()));
|
||||
self
|
||||
}
|
||||
|
||||
/// Set the disabled matcher of the calendar.
|
||||
///
|
||||
/// The disabled matcher will be used to disable the days that match the matcher.
|
||||
pub fn set_disabled_matcher(
|
||||
&mut self,
|
||||
disabled: impl Into<Matcher>,
|
||||
_: &mut Window,
|
||||
_: &mut Context<Self>,
|
||||
) {
|
||||
self.disabled_matcher = Some(Rc::new(disabled.into()));
|
||||
}
|
||||
|
||||
/// Set the date of the calendar.
|
||||
///
|
||||
/// When you set a range date, the mode will be automatically set to `Mode::Range`.
|
||||
|
|
@ -295,9 +314,9 @@ impl CalendarState {
|
|||
let date = date.into();
|
||||
|
||||
let invalid = self
|
||||
.disabled
|
||||
.disabled_matcher
|
||||
.as_ref()
|
||||
.map_or(false, |disabled| disabled.date_matched(&date));
|
||||
.map_or(false, |matcher| matcher.date_matched(&date));
|
||||
|
||||
if invalid {
|
||||
return;
|
||||
|
|
@ -356,13 +375,6 @@ impl CalendarState {
|
|||
self
|
||||
}
|
||||
|
||||
/// Set the disabled matcher of the calendar.
|
||||
///
|
||||
/// The disabled matcher will be used to disable the days that match the matcher.
|
||||
pub fn set_disabled(&mut self, disabled: Matcher, _: &mut Window, _: &mut Context<Self>) {
|
||||
self.disabled = Some(disabled);
|
||||
}
|
||||
|
||||
/// Get year and month by offset month.
|
||||
fn offset_year_month(&self, offset_month: usize) -> (i32, u32) {
|
||||
let mut month = self.current_month as i32 + offset_month as i32;
|
||||
|
|
@ -497,6 +509,7 @@ impl Render for CalendarState {
|
|||
impl Calendar {
|
||||
pub fn new(state: &Entity<CalendarState>) -> Self {
|
||||
Self {
|
||||
id: ("calendar", state.entity_id()).into(),
|
||||
size: Size::default(),
|
||||
state: state.clone(),
|
||||
style: StyleRefinement::default(),
|
||||
|
|
@ -527,7 +540,7 @@ impl Calendar {
|
|||
let date = *d;
|
||||
let is_today = *d == state.today;
|
||||
let disabled = state
|
||||
.disabled
|
||||
.disabled_matcher
|
||||
.as_ref()
|
||||
.map_or(false, |disabled| disabled.matched(&date));
|
||||
|
||||
|
|
@ -914,10 +927,12 @@ impl RenderOnce for Calendar {
|
|||
fn render(self, window: &mut Window, cx: &mut App) -> impl IntoElement {
|
||||
let view_mode = self.state.read(cx).view_mode;
|
||||
let number_of_months = self.number_of_months;
|
||||
self.state
|
||||
.update(cx, |state, _| state.number_of_months = number_of_months);
|
||||
self.state.update(cx, |state, _| {
|
||||
state.number_of_months = number_of_months;
|
||||
});
|
||||
|
||||
v_flex()
|
||||
.id(self.id.clone())
|
||||
.track_focus(&self.state.read(cx).focus_handle)
|
||||
.border_1()
|
||||
.border_color(cx.theme().border)
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
use std::rc::Rc;
|
||||
|
||||
use chrono::NaiveDate;
|
||||
use gpui::{
|
||||
anchored, deferred, div, prelude::FluentBuilder as _, px, App, AppContext, Context, ElementId,
|
||||
|
|
@ -12,7 +14,8 @@ use crate::{
|
|||
button::{Button, ButtonVariants as _},
|
||||
h_flex,
|
||||
input::clear_button,
|
||||
v_flex, ActiveTheme, Icon, IconName, Sizable, Size, StyleSized as _, StyledExt as _,
|
||||
v_flex, ActiveTheme, Disableable, Icon, IconName, Sizable, Size, StyleSized as _,
|
||||
StyledExt as _,
|
||||
};
|
||||
|
||||
use super::calendar::{Calendar, CalendarEvent, CalendarState, Date, Matcher};
|
||||
|
|
@ -64,6 +67,7 @@ pub struct DatePickerState {
|
|||
calendar: Entity<CalendarState>,
|
||||
date_format: SharedString,
|
||||
number_of_months: usize,
|
||||
disabled_matcher: Option<Rc<Matcher>>,
|
||||
_subscriptions: Vec<Subscription>,
|
||||
}
|
||||
|
||||
|
|
@ -116,6 +120,7 @@ impl DatePickerState {
|
|||
open: false,
|
||||
date_format: "%Y/%m/%d".into(),
|
||||
number_of_months: 1,
|
||||
disabled_matcher: None,
|
||||
_subscriptions,
|
||||
}
|
||||
}
|
||||
|
|
@ -154,15 +159,17 @@ impl DatePickerState {
|
|||
cx.notify();
|
||||
}
|
||||
|
||||
/// Set the disabled match for the calendar.
|
||||
pub fn disabled_matcher(mut self, disabled: impl Into<Matcher>) -> Self {
|
||||
self.disabled_matcher = Some(Rc::new(disabled.into()));
|
||||
self
|
||||
}
|
||||
|
||||
/// Set the disabled matcher of the date picker.
|
||||
pub fn set_disabled(
|
||||
&mut self,
|
||||
disabled: impl Into<Matcher>,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) {
|
||||
self.calendar.update(cx, |view, cx| {
|
||||
view.set_disabled(disabled.into(), window, cx);
|
||||
fn set_canlendar_disabled_matcher(&mut self, _: &mut Window, cx: &mut Context<Self>) {
|
||||
let matcher = self.disabled_matcher.clone();
|
||||
self.calendar.update(cx, |state, _| {
|
||||
state.disabled_matcher = matcher;
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -239,6 +246,7 @@ pub struct DatePicker {
|
|||
number_of_months: usize,
|
||||
presets: Option<Vec<DateRangePreset>>,
|
||||
appearance: bool,
|
||||
disabled: bool,
|
||||
}
|
||||
|
||||
impl Sizable for DatePicker {
|
||||
|
|
@ -259,6 +267,13 @@ impl Styled for DatePicker {
|
|||
}
|
||||
}
|
||||
|
||||
impl Disableable for DatePicker {
|
||||
fn disabled(mut self, disabled: bool) -> Self {
|
||||
self.disabled = disabled;
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl Render for DatePickerState {
|
||||
fn render(&mut self, _: &mut Window, _: &mut Context<Self>) -> impl gpui::IntoElement {
|
||||
Empty
|
||||
|
|
@ -277,6 +292,7 @@ impl DatePicker {
|
|||
number_of_months: 2,
|
||||
presets: None,
|
||||
appearance: true,
|
||||
disabled: false,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -313,6 +329,10 @@ impl DatePicker {
|
|||
|
||||
impl RenderOnce for DatePicker {
|
||||
fn render(self, window: &mut Window, cx: &mut App) -> impl IntoElement {
|
||||
self.state.update(cx, |state, cx| {
|
||||
state.set_canlendar_disabled_matcher(window, cx);
|
||||
});
|
||||
|
||||
// This for keep focus border style, when click on the popup.
|
||||
let is_focused = self.focus_handle(cx).contains_focused(window, cx);
|
||||
let state = self.state.read(cx);
|
||||
|
|
@ -352,11 +372,15 @@ impl RenderOnce for DatePicker {
|
|||
.rounded(cx.theme().radius)
|
||||
.when(cx.theme().shadow, |this| this.shadow_xs())
|
||||
.when(is_focused, |this| this.focused_border(cx))
|
||||
.when(self.disabled, |this| {
|
||||
this.bg(cx.theme().muted)
|
||||
.text_color(cx.theme().muted_foreground)
|
||||
})
|
||||
})
|
||||
.overflow_hidden()
|
||||
.input_text_size(self.size)
|
||||
.input_size(self.size)
|
||||
.when(!state.open, |this| {
|
||||
.when(!state.open && !self.disabled, |this| {
|
||||
this.on_click(
|
||||
window.listener_for(&self.state, DatePickerState::toggle_calendar),
|
||||
)
|
||||
|
|
@ -368,17 +392,19 @@ impl RenderOnce for DatePicker {
|
|||
.justify_between()
|
||||
.gap_1()
|
||||
.child(div().w_full().overflow_hidden().child(display_title))
|
||||
.when(show_clean, |this| {
|
||||
this.child(clear_button(cx).on_click(
|
||||
window.listener_for(&self.state, DatePickerState::clean),
|
||||
))
|
||||
})
|
||||
.when(!show_clean, |this| {
|
||||
this.child(
|
||||
Icon::new(IconName::Calendar)
|
||||
.xsmall()
|
||||
.text_color(cx.theme().muted_foreground),
|
||||
)
|
||||
.when(!self.disabled, |this| {
|
||||
this.when(show_clean, |this| {
|
||||
this.child(clear_button(cx).on_click(
|
||||
window.listener_for(&self.state, DatePickerState::clean),
|
||||
))
|
||||
})
|
||||
.when(!show_clean, |this| {
|
||||
this.child(
|
||||
Icon::new(IconName::Calendar)
|
||||
.xsmall()
|
||||
.text_color(cx.theme().muted_foreground),
|
||||
)
|
||||
})
|
||||
}),
|
||||
),
|
||||
)
|
||||
|
|
|
|||
Loading…
Reference in a new issue