UNPKG

@material-ui/lab

Version:
434 lines (384 loc) 14.6 kB
import _extends from "@babel/runtime/helpers/esm/extends"; import * as React from 'react'; import PropTypes from 'prop-types'; import { unstable_useId as useId } from '@material-ui/utils'; import { styled, useThemeProps } from '@material-ui/core/styles'; import { unstable_composeClasses as composeClasses, generateUtilityClass, generateUtilityClasses } from '@material-ui/unstyled'; import Clock from './Clock'; import { pipe } from '../internal/pickers/utils'; import { useUtils, useNow } from '../internal/pickers/hooks/useUtils'; import { getHourNumbers, getMinutesNumbers } from './ClockNumbers'; import PickersArrowSwitcher from '../internal/pickers/PickersArrowSwitcher'; import { convertValueToMeridiem, createIsAfterIgnoreDatePart } from '../internal/pickers/time-utils'; import { useMeridiemMode } from '../internal/pickers/hooks/date-helpers-hooks'; import { jsx as _jsx } from "react/jsx-runtime"; import { jsxs as _jsxs } from "react/jsx-runtime"; export function getClockPickerUtilityClass(slot) { return generateUtilityClass('MuiClockPicker', slot); } export var clockPickerClasses = generateUtilityClasses('MuiClockPicker', ['arrowSwitcher']); var useUtilityClasses = function useUtilityClasses(styleProps) { var classes = styleProps.classes; var slots = { arrowSwitcher: ['arrowSwitcher'] }; return composeClasses(slots, getClockPickerUtilityClass, classes); }; var ClockPickerArrowSwitcher = styled(PickersArrowSwitcher, { name: 'MuiClockPicker', slot: 'ArrowSwticher', overridesResolver: function overridesResolver(props, styles) { return styles.arrowSwitcher; } })({ position: 'absolute', right: 12, top: 15 }); var defaultGetClockLabelText = function defaultGetClockLabelText(view, time, adapter) { return "Select ".concat(view, ". ").concat(time === null ? 'No time selected' : "Selected time is ".concat(adapter.format(time, 'fullTime'))); }; var defaultGetMinutesClockNumberText = function defaultGetMinutesClockNumberText(minutes) { return "".concat(minutes, " minutes"); }; var defaultGetHoursClockNumberText = function defaultGetHoursClockNumberText(hours) { return "".concat(hours, " hours"); }; var defaultGetSecondsClockNumberText = function defaultGetSecondsClockNumberText(seconds) { return "".concat(seconds, " seconds"); }; /** * * API: * * - [ClockPicker API](https://material-ui.com/api/clock-picker/) */ function ClockPicker(inProps) { var props = useThemeProps({ props: inProps, name: 'MuiClockPicker' }); var _props$ampm = props.ampm, ampm = _props$ampm === void 0 ? false : _props$ampm, _props$ampmInClock = props.ampmInClock, ampmInClock = _props$ampmInClock === void 0 ? false : _props$ampmInClock, autoFocus = props.autoFocus, components = props.components, componentsProps = props.componentsProps, date = props.date, _props$disableIgnorin = props.disableIgnoringDatePartForTimeValidation, disableIgnoringDatePartForTimeValidation = _props$disableIgnorin === void 0 ? false : _props$disableIgnorin, _props$getClockLabelT = props.getClockLabelText, getClockLabelText = _props$getClockLabelT === void 0 ? defaultGetClockLabelText : _props$getClockLabelT, _props$getHoursClockN = props.getHoursClockNumberText, getHoursClockNumberText = _props$getHoursClockN === void 0 ? defaultGetHoursClockNumberText : _props$getHoursClockN, _props$getMinutesCloc = props.getMinutesClockNumberText, getMinutesClockNumberText = _props$getMinutesCloc === void 0 ? defaultGetMinutesClockNumberText : _props$getMinutesCloc, _props$getSecondsCloc = props.getSecondsClockNumberText, getSecondsClockNumberText = _props$getSecondsCloc === void 0 ? defaultGetSecondsClockNumberText : _props$getSecondsCloc, _props$leftArrowButto = props.leftArrowButtonText, leftArrowButtonText = _props$leftArrowButto === void 0 ? 'open previous view' : _props$leftArrowButto, maxTime = props.maxTime, minTime = props.minTime, _props$minutesStep = props.minutesStep, minutesStep = _props$minutesStep === void 0 ? 1 : _props$minutesStep, nextViewAvailable = props.nextViewAvailable, onChange = props.onChange, openNextView = props.openNextView, openPreviousView = props.openPreviousView, previousViewAvailable = props.previousViewAvailable, _props$rightArrowButt = props.rightArrowButtonText, rightArrowButtonText = _props$rightArrowButt === void 0 ? 'open next view' : _props$rightArrowButt, shouldDisableTime = props.shouldDisableTime, showViewSwitcher = props.showViewSwitcher, view = props.view; var now = useNow(); var utils = useUtils(); var midnight = utils.setSeconds(utils.setMinutes(utils.setHours(now, 0), 0), 0); var dateOrMidnight = date || midnight; var _useMeridiemMode = useMeridiemMode(dateOrMidnight, ampm, onChange), meridiemMode = _useMeridiemMode.meridiemMode, handleMeridiemChange = _useMeridiemMode.handleMeridiemChange; var isTimeDisabled = React.useCallback(function (rawValue, viewType) { if (date === null) { return false; } var validateTimeValue = function validateTimeValue(getRequestedTimePoint) { var isAfterComparingFn = createIsAfterIgnoreDatePart(disableIgnoringDatePartForTimeValidation, utils); return Boolean(minTime && isAfterComparingFn(minTime, getRequestedTimePoint('end')) || maxTime && isAfterComparingFn(getRequestedTimePoint('start'), maxTime) || shouldDisableTime && shouldDisableTime(rawValue, viewType)); }; switch (viewType) { case 'hours': { var hoursWithMeridiem = convertValueToMeridiem(rawValue, meridiemMode, ampm); return validateTimeValue(function (when) { return pipe(function (currentDate) { return utils.setHours(currentDate, hoursWithMeridiem); }, function (dateWithHours) { return utils.setMinutes(dateWithHours, when === 'start' ? 0 : 59); }, function (dateWithMinutes) { return utils.setSeconds(dateWithMinutes, when === 'start' ? 0 : 59); })(date); }); } case 'minutes': return validateTimeValue(function (when) { return pipe(function (currentDate) { return utils.setMinutes(currentDate, rawValue); }, function (dateWithMinutes) { return utils.setSeconds(dateWithMinutes, when === 'start' ? 0 : 59); })(date); }); case 'seconds': return validateTimeValue(function () { return utils.setSeconds(date, rawValue); }); default: throw new Error('not supported'); } }, [ampm, date, disableIgnoringDatePartForTimeValidation, maxTime, meridiemMode, minTime, shouldDisableTime, utils]); var selectedId = useId(); var viewProps = React.useMemo(function () { switch (view) { case 'hours': { var handleHoursChange = function handleHoursChange(value, isFinish) { var valueWithMeridiem = convertValueToMeridiem(value, meridiemMode, ampm); onChange(utils.setHours(dateOrMidnight, valueWithMeridiem), isFinish); }; return { onChange: handleHoursChange, value: utils.getHours(dateOrMidnight), children: getHourNumbers({ date: date, utils: utils, ampm: ampm, onChange: handleHoursChange, getClockNumberText: getHoursClockNumberText, isDisabled: function isDisabled(value) { return isTimeDisabled(value, 'hours'); }, selectedId: selectedId }) }; } case 'minutes': { var minutesValue = utils.getMinutes(dateOrMidnight); var handleMinutesChange = function handleMinutesChange(value, isFinish) { onChange(utils.setMinutes(dateOrMidnight, value), isFinish); }; return { value: minutesValue, onChange: handleMinutesChange, children: getMinutesNumbers({ utils: utils, value: minutesValue, onChange: handleMinutesChange, getClockNumberText: getMinutesClockNumberText, isDisabled: function isDisabled(value) { return isTimeDisabled(value, 'minutes'); }, selectedId: selectedId }) }; } case 'seconds': { var secondsValue = utils.getSeconds(dateOrMidnight); var handleSecondsChange = function handleSecondsChange(value, isFinish) { onChange(utils.setSeconds(dateOrMidnight, value), isFinish); }; return { value: secondsValue, onChange: handleSecondsChange, children: getMinutesNumbers({ utils: utils, value: secondsValue, onChange: handleSecondsChange, getClockNumberText: getSecondsClockNumberText, isDisabled: function isDisabled(value) { return isTimeDisabled(value, 'seconds'); }, selectedId: selectedId }) }; } default: throw new Error('You must provide the type for ClockView'); } }, [view, utils, date, ampm, getHoursClockNumberText, getMinutesClockNumberText, getSecondsClockNumberText, meridiemMode, onChange, dateOrMidnight, isTimeDisabled, selectedId]); var styleProps = props; var classes = useUtilityClasses(styleProps); return /*#__PURE__*/_jsxs(React.Fragment, { children: [showViewSwitcher && /*#__PURE__*/_jsx(ClockPickerArrowSwitcher, { className: classes.arrowSwitcher, leftArrowButtonText: leftArrowButtonText, rightArrowButtonText: rightArrowButtonText, components: components, componentsProps: componentsProps, onLeftClick: openPreviousView, onRightClick: openNextView, isLeftDisabled: previousViewAvailable, isRightDisabled: nextViewAvailable, styleProps: styleProps }), /*#__PURE__*/_jsx(Clock, _extends({ autoFocus: autoFocus, date: date, ampmInClock: ampmInClock, type: view, ampm: ampm, getClockLabelText: getClockLabelText, minutesStep: minutesStep, isTimeDisabled: isTimeDisabled, meridiemMode: meridiemMode, handleMeridiemChange: handleMeridiemChange, selectedId: selectedId }, viewProps))] }); } process.env.NODE_ENV !== "production" ? ClockPicker.propTypes /* remove-proptypes */ = { // ----------------------------- Warning -------------------------------- // | These PropTypes are generated from the TypeScript type definitions | // | To update them edit TypeScript types and run "yarn proptypes" | // ---------------------------------------------------------------------- /** * 12h/24h view for hour selection clock. * @default false */ ampm: PropTypes.bool, /** * Display ampm controls under the clock (instead of in the toolbar). * @default false */ ampmInClock: PropTypes.bool, /** * Set to `true` if focus should be moved to clock picker. */ autoFocus: PropTypes.bool, /** * Override or extend the styles applied to the component. */ classes: PropTypes.object, /** * The components used for each slot. * Either a string to use a HTML element or a component. */ components: PropTypes.shape({ LeftArrowButton: PropTypes.elementType, LeftArrowIcon: PropTypes.elementType, RightArrowButton: PropTypes.elementType, RightArrowIcon: PropTypes.elementType }), /** * The props used for each slot inside. */ componentsProps: PropTypes.object, /** * Selected date @DateIOType. */ date: PropTypes.any, /** * Do not ignore date part when validating min/max time. * @default false */ disableIgnoringDatePartForTimeValidation: PropTypes.bool, /** * Accessible text that helps user to understand which time and view is selected. * @default <TDate extends any>( * view: ClockView, * time: TDate | null, * adapter: MuiPickersAdapter<TDate>, * ) => * `Select ${view}. ${ * time === null ? 'No time selected' : `Selected time is ${adapter.format(time, 'fullTime')}` * }` */ getClockLabelText: PropTypes.func, /** * Get clock number aria-text for hours. * @default (hours: string) => `${hours} hours` */ getHoursClockNumberText: PropTypes.func, /** * Get clock number aria-text for minutes. * @default (minutes: string) => `${minutes} minutes` */ getMinutesClockNumberText: PropTypes.func, /** * Get clock number aria-text for seconds. * @default (seconds: string) => `${seconds} seconds` */ getSecondsClockNumberText: PropTypes.func, /** * Left arrow icon aria-label text. * @default 'open previous view' */ leftArrowButtonText: PropTypes.string, /** * Max time acceptable time. * For input validation date part of passed object will be ignored if `disableIgnoringDatePartForTimeValidation` not specified. */ maxTime: PropTypes.any, /** * Min time acceptable time. * For input validation date part of passed object will be ignored if `disableIgnoringDatePartForTimeValidation` not specified. */ minTime: PropTypes.any, /** * Step over minutes. * @default 1 */ minutesStep: PropTypes.number, /** * @ignore */ nextViewAvailable: PropTypes.bool.isRequired, /** * On change callback @DateIOType. */ onChange: PropTypes.func.isRequired, /** * @ignore */ openNextView: PropTypes.func.isRequired, /** * @ignore */ openPreviousView: PropTypes.func.isRequired, /** * @ignore */ previousViewAvailable: PropTypes.bool.isRequired, /** * Right arrow icon aria-label text. * @default 'open next view' */ rightArrowButtonText: PropTypes.string, /** * Dynamically check if time is disabled or not. * If returns `false` appropriate time point will ot be acceptable. */ shouldDisableTime: PropTypes.func, /** * @ignore */ showViewSwitcher: PropTypes.bool, /** * @ignore */ view: PropTypes.oneOf(['hours', 'minutes', 'seconds']).isRequired } : void 0; /** * * Demos: * * - [Time Picker](https://material-ui.com/components/time-picker/) * * API: * * - [ClockPicker API](https://material-ui.com/api/clock-picker/) */ export default ClockPicker;