-
-
Notifications
You must be signed in to change notification settings - Fork 1.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[pickers] Support onMonthChange
/ onYearChange
in day
view
#6954
Changes from all commits
9118dfa
bccef18
7a69bf2
a2b32d6
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -296,26 +296,10 @@ export const DateCalendar = React.forwardRef(function DateCalendar<TDate>( | |
default: defaultValue ?? null, | ||
}); | ||
|
||
const handleValueChange = useEventCallback( | ||
(newValue: TDate | null, selectionState?: PickerSelectionState) => { | ||
setValue(newValue); | ||
onChange?.(newValue, selectionState); | ||
}, | ||
); | ||
|
||
const { openView, setOpenView, openNext } = useViews({ | ||
view, | ||
views, | ||
openTo, | ||
onChange: handleValueChange, | ||
onViewChange, | ||
}); | ||
|
||
const { | ||
calendarState, | ||
changeFocusedDay, | ||
changeMonth, | ||
handleChangeMonth, | ||
slideToMonth, | ||
isDateDisabled, | ||
onMonthSwitchingAnimationEnd, | ||
} = useCalendarState({ | ||
|
@@ -330,6 +314,29 @@ export const DateCalendar = React.forwardRef(function DateCalendar<TDate>( | |
disableFuture, | ||
}); | ||
|
||
const handleValueChange = useEventCallback( | ||
(newValue: TDate | null, selectionState?: PickerSelectionState) => { | ||
setValue(newValue); | ||
onChange?.(newValue, selectionState); | ||
|
||
if (newValue != null) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We now do the checks here to make sure that any value change causes a call to |
||
slideToMonth(newValue); | ||
|
||
if (onYearChange && !utils.isSameYear(newValue, calendarState.currentMonth)) { | ||
onYearChange(newValue); | ||
} | ||
} | ||
}, | ||
); | ||
|
||
const { openView, setOpenView, openNext } = useViews({ | ||
view, | ||
views, | ||
openTo, | ||
onChange: handleValueChange, | ||
onViewChange, | ||
}); | ||
|
||
const handleDateMonthChange = useEventCallback((newDate: TDate) => { | ||
const startOfMonth = utils.startOfMonth(newDate); | ||
const endOfMonth = utils.endOfMonth(newDate); | ||
|
@@ -351,7 +358,7 @@ export const DateCalendar = React.forwardRef(function DateCalendar<TDate>( | |
onMonthChange?.(startOfMonth); | ||
} else { | ||
openNext(); | ||
changeMonth(startOfMonth); | ||
slideToMonth(startOfMonth); | ||
} | ||
|
||
changeFocusedDay(closestEnabledDate, true); | ||
|
@@ -375,10 +382,9 @@ export const DateCalendar = React.forwardRef(function DateCalendar<TDate>( | |
|
||
if (closestEnabledDate) { | ||
handleValueChange(closestEnabledDate, 'finish'); | ||
onYearChange?.(closestEnabledDate); | ||
} else { | ||
openNext(); | ||
changeMonth(startOfYear); | ||
slideToMonth(startOfYear); | ||
} | ||
|
||
changeFocusedDay(closestEnabledDate, true); | ||
|
@@ -397,7 +403,7 @@ export const DateCalendar = React.forwardRef(function DateCalendar<TDate>( | |
|
||
React.useEffect(() => { | ||
if (value != null && utils.isValid(value)) { | ||
changeMonth(value); | ||
slideToMonth(value); | ||
} | ||
}, [value]); // eslint-disable-line | ||
|
||
|
@@ -474,7 +480,7 @@ export const DateCalendar = React.forwardRef(function DateCalendar<TDate>( | |
openView={openView} | ||
currentMonth={calendarState.currentMonth} | ||
onViewChange={setOpenView} | ||
onMonthChange={(newMonth, direction) => handleChangeMonth({ newMonth, direction })} | ||
onMonthChange={slideToMonth} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I now compute the direction inside |
||
minDate={minDateWithDisabled} | ||
maxDate={maxDateWithDisabled} | ||
disabled={disabled} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,5 @@ | ||
import * as React from 'react'; | ||
import useEventCallback from '@mui/utils/useEventCallback'; | ||
import { SlideDirection } from './PickersSlideTransition'; | ||
import { useIsDateDisabled } from '../internals/hooks/validation/useDateValidation'; | ||
import { useUtils, useNow } from '../internals/hooks/useUtils'; | ||
|
@@ -71,18 +72,27 @@ export const createCalendarStateReducer = | |
!disableSwitchToMonthOnDayFocus && | ||
!utils.isSameMonth(state.currentMonth, action.focusedDay); | ||
|
||
let slideDirection: SlideDirection; | ||
if (!needMonthSwitch) { | ||
slideDirection = state.slideDirection; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Before, the slide to the new month was caused by the Without this check, the focus was resetting the slide direction, causing it to go on the wrong direction in some scenario. |
||
} else if ( | ||
action.focusedDay != null && | ||
utils.isAfterDay(action.focusedDay, state.currentMonth) | ||
) { | ||
slideDirection = 'left'; | ||
} else { | ||
slideDirection = 'right'; | ||
} | ||
|
||
return { | ||
...state, | ||
slideDirection, | ||
focusedDay: action.focusedDay, | ||
isMonthSwitchingAnimating: | ||
needMonthSwitch && !reduceAnimations && !action.withoutMonthSwitchingAnimation, | ||
currentMonth: needMonthSwitch | ||
? utils.startOfMonth(action.focusedDay!) | ||
: state.currentMonth, | ||
slideDirection: | ||
action.focusedDay != null && utils.isAfterDay(action.focusedDay, state.currentMonth) | ||
? 'left' | ||
: 'right', | ||
}; | ||
} | ||
|
||
|
@@ -139,36 +149,25 @@ export const useCalendarState = <TDate extends unknown>({ | |
slideDirection: 'left', | ||
}); | ||
|
||
const handleChangeMonth = React.useCallback( | ||
(payload: ChangeMonthPayload<TDate>) => { | ||
dispatch({ | ||
type: 'changeMonth', | ||
...payload, | ||
}); | ||
const slideToMonth = useEventCallback((newDate: TDate) => { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Renamed to make clear that we are not updating any value, just "meta data" used to handle the visually displayed month There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If we are going this route, then maybe |
||
const newDateRequested = newDate; | ||
if (utils.isSameMonth(newDateRequested, calendarState.currentMonth)) { | ||
return; | ||
} | ||
|
||
if (onMonthChange) { | ||
onMonthChange(payload.newMonth); | ||
} | ||
}, | ||
[onMonthChange], | ||
); | ||
const newMonth = utils.startOfMonth(newDateRequested); | ||
const direction = utils.isAfterDay(newDateRequested, calendarState.currentMonth) | ||
? 'left' | ||
: 'right'; | ||
|
||
const changeMonth = React.useCallback( | ||
(newDate: TDate) => { | ||
const newDateRequested = newDate; | ||
if (utils.isSameMonth(newDateRequested, calendarState.currentMonth)) { | ||
return; | ||
} | ||
dispatch({ | ||
type: 'changeMonth', | ||
newMonth, | ||
direction, | ||
}); | ||
|
||
handleChangeMonth({ | ||
newMonth: utils.startOfMonth(newDateRequested), | ||
direction: utils.isAfterDay(newDateRequested, calendarState.currentMonth) | ||
? 'left' | ||
: 'right', | ||
}); | ||
}, | ||
[calendarState.currentMonth, handleChangeMonth, utils], | ||
); | ||
onMonthChange?.(newMonth); | ||
}); | ||
|
||
const isDateDisabled = useIsDateDisabled({ | ||
shouldDisableDate, | ||
|
@@ -197,10 +196,9 @@ export const useCalendarState = <TDate extends unknown>({ | |
|
||
return { | ||
calendarState, | ||
changeMonth, | ||
slideToMonth, | ||
changeFocusedDay, | ||
isDateDisabled, | ||
onMonthSwitchingAnimationEnd, | ||
handleChangeMonth, | ||
}; | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nitpick: Should we maybe replace these with
useEventCallback
? 🤔