UNPKG

@mui/x-date-pickers

Version:

The community edition of the Date and Time Picker components (MUI X).

128 lines (127 loc) 4.96 kB
import _extends from "@babel/runtime/helpers/esm/extends"; import * as React from 'react'; import useEventCallback from '@mui/utils/useEventCallback'; import useControlled from '@mui/utils/useControlled'; import { DEFAULT_STEP_NAVIGATION } from "../utils/createStepNavigation.js"; let warnedOnceNotValidView = false; export function useViews({ onChange, onViewChange, openTo, view: inView, views, autoFocus, focusedView: inFocusedView, onFocusedViewChange, getStepNavigation }) { if (process.env.NODE_ENV !== 'production') { if (!warnedOnceNotValidView) { if (inView != null && !views.includes(inView)) { console.warn(`MUI X: \`view="${inView}"\` is not a valid prop.`, `It must be an element of \`views=["${views.join('", "')}"]\`.`); warnedOnceNotValidView = true; } if (inView == null && openTo != null && !views.includes(openTo)) { console.warn(`MUI X: \`openTo="${openTo}"\` is not a valid prop.`, `It must be an element of \`views=["${views.join('", "')}"]\`.`); warnedOnceNotValidView = true; } } } const previousOpenTo = React.useRef(openTo); const previousViews = React.useRef(views); const defaultView = React.useRef(views.includes(openTo) ? openTo : views[0]); const [view, setView] = useControlled({ name: 'useViews', state: 'view', controlled: inView, default: defaultView.current }); const defaultFocusedView = React.useRef(autoFocus ? view : null); const [focusedView, setFocusedView] = useControlled({ name: 'useViews', state: 'focusedView', controlled: inFocusedView, default: defaultFocusedView.current }); const stepNavigation = getStepNavigation ? getStepNavigation({ setView, view, defaultView: defaultView.current, views }) : DEFAULT_STEP_NAVIGATION; React.useEffect(() => { // Update the current view when `openTo` or `views` props change if (previousOpenTo.current && previousOpenTo.current !== openTo || previousViews.current && previousViews.current.some(previousView => !views.includes(previousView))) { setView(views.includes(openTo) ? openTo : views[0]); previousViews.current = views; previousOpenTo.current = openTo; } }, [openTo, setView, view, views]); const viewIndex = views.indexOf(view); const previousView = views[viewIndex - 1] ?? null; const nextView = views[viewIndex + 1] ?? null; const handleFocusedViewChange = useEventCallback((viewToFocus, hasFocus) => { if (hasFocus) { // Focus event setFocusedView(viewToFocus); } else { // Blur event setFocusedView(prevFocusedView => viewToFocus === prevFocusedView ? null : prevFocusedView // If false the blur is due to view switching ); } onFocusedViewChange?.(viewToFocus, hasFocus); }); const handleChangeView = useEventCallback(newView => { // always keep the focused view in sync handleFocusedViewChange(newView, true); if (newView === view) { return; } setView(newView); if (onViewChange) { onViewChange(newView); } }); const goToNextView = useEventCallback(() => { if (nextView) { handleChangeView(nextView); } }); const setValueAndGoToNextView = useEventCallback((value, currentViewSelectionState, selectedView) => { const isSelectionFinishedOnCurrentView = currentViewSelectionState === 'finish'; const hasMoreViews = selectedView ? // handles case like `DateTimePicker`, where a view might return a `finish` selection state // but when it's not the final view given all `views` -> overall selection state should be `partial`. views.indexOf(selectedView) < views.length - 1 : Boolean(nextView); const globalSelectionState = isSelectionFinishedOnCurrentView && hasMoreViews ? 'partial' : currentViewSelectionState; onChange(value, globalSelectionState, selectedView); // The selected view can be different from the active view, // This can happen if multiple views are displayed, like in `DesktopDateTimePicker` or `MultiSectionDigitalClock`. let currentView = null; if (selectedView != null && selectedView !== view) { currentView = selectedView; } else if (isSelectionFinishedOnCurrentView) { currentView = view; } if (currentView == null) { return; } const viewToNavigateTo = views[views.indexOf(currentView) + 1]; if (viewToNavigateTo == null || !stepNavigation.areViewsInSameStep(currentView, viewToNavigateTo)) { return; } handleChangeView(viewToNavigateTo); }); return _extends({}, stepNavigation, { view, setView: handleChangeView, focusedView, setFocusedView: handleFocusedViewChange, nextView, previousView, // Always return up-to-date default view instead of the initial one (i.e. defaultView.current) defaultView: views.includes(openTo) ? openTo : views[0], goToNextView, setValueAndGoToNextView }); }