UNPKG

@wordpress/components

Version:
288 lines (280 loc) 9.01 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.TimePicker = TimePicker; exports.default = void 0; var _dateFns = require("date-fns"); var _element = require("@wordpress/element"); var _i18n = require("@wordpress/i18n"); var _baseControl = _interopRequireDefault(require("../../base-control")); var _visuallyHidden = require("../../visually-hidden"); var _selectControl = _interopRequireDefault(require("../../select-control")); var _timezone = _interopRequireDefault(require("./timezone")); var _styles = require("./styles"); var _hStack = require("../../h-stack"); var _spacer = require("../../spacer"); var _utils = require("../utils"); var _constants = require("../constants"); var _timeInput = require("./time-input"); var _jsxRuntime = require("react/jsx-runtime"); /** * External dependencies */ /** * WordPress dependencies */ /** * Internal dependencies */ const VALID_DATE_ORDERS = ['dmy', 'mdy', 'ymd']; /** * TimePicker is a React component that renders a clock for time selection. * * ```jsx * import { TimePicker } from '@wordpress/components'; * import { useState } from '@wordpress/element'; * * const MyTimePicker = () => { * const [ time, setTime ] = useState( new Date() ); * * return ( * <TimePicker * currentTime={ date } * onChange={ ( newTime ) => setTime( newTime ) } * is12Hour * /> * ); * }; * ``` */ function TimePicker({ is12Hour, currentTime, onChange, dateOrder: dateOrderProp, hideLabelFromVision = false }) { const [date, setDate] = (0, _element.useState)(() => // Truncate the date at the minutes, see: #15495. currentTime ? (0, _dateFns.startOfMinute)((0, _utils.inputToDate)(currentTime)) : new Date()); // Reset the state when currentTime changed. // TODO: useEffect() shouldn't be used like this, causes an unnecessary render (0, _element.useEffect)(() => { setDate(currentTime ? (0, _dateFns.startOfMinute)((0, _utils.inputToDate)(currentTime)) : new Date()); }, [currentTime]); const monthOptions = [{ value: '01', label: (0, _i18n.__)('January') }, { value: '02', label: (0, _i18n.__)('February') }, { value: '03', label: (0, _i18n.__)('March') }, { value: '04', label: (0, _i18n.__)('April') }, { value: '05', label: (0, _i18n.__)('May') }, { value: '06', label: (0, _i18n.__)('June') }, { value: '07', label: (0, _i18n.__)('July') }, { value: '08', label: (0, _i18n.__)('August') }, { value: '09', label: (0, _i18n.__)('September') }, { value: '10', label: (0, _i18n.__)('October') }, { value: '11', label: (0, _i18n.__)('November') }, { value: '12', label: (0, _i18n.__)('December') }]; const { day, month, year, minutes, hours } = (0, _element.useMemo)(() => ({ day: (0, _dateFns.format)(date, 'dd'), month: (0, _dateFns.format)(date, 'MM'), year: (0, _dateFns.format)(date, 'yyyy'), minutes: (0, _dateFns.format)(date, 'mm'), hours: (0, _dateFns.format)(date, 'HH'), am: (0, _dateFns.format)(date, 'a') }), [date]); const buildNumberControlChangeCallback = method => { const callback = (value, { event }) => { if (!(0, _utils.validateInputElementTarget)(event)) { return; } // We can safely assume value is a number if target is valid. const numberValue = Number(value); const newDate = (0, _dateFns.set)(date, { [method]: numberValue }); setDate(newDate); onChange?.((0, _dateFns.format)(newDate, _constants.TIMEZONELESS_FORMAT)); }; return callback; }; const onTimeInputChangeCallback = ({ hours: newHours, minutes: newMinutes }) => { const newDate = (0, _dateFns.set)(date, { hours: newHours, minutes: newMinutes }); setDate(newDate); onChange?.((0, _dateFns.format)(newDate, _constants.TIMEZONELESS_FORMAT)); }; const dayField = /*#__PURE__*/(0, _jsxRuntime.jsx)(_styles.DayInput, { className: "components-datetime__time-field components-datetime__time-field-day" // Unused, for backwards compatibility. , label: (0, _i18n.__)('Day'), hideLabelFromVision: true, __next40pxDefaultSize: true, value: day, step: 1, min: 1, max: 31, required: true, spinControls: "none", isPressEnterToChange: true, isDragEnabled: false, isShiftStepEnabled: false, onChange: buildNumberControlChangeCallback('date') }, "day"); const monthField = /*#__PURE__*/(0, _jsxRuntime.jsx)(_styles.MonthSelectWrapper, { children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_selectControl.default, { className: "components-datetime__time-field components-datetime__time-field-month" // Unused, for backwards compatibility. , label: (0, _i18n.__)('Month'), hideLabelFromVision: true, __next40pxDefaultSize: true, __nextHasNoMarginBottom: true, value: month, options: monthOptions, onChange: value => { const newDate = (0, _dateFns.setMonth)(date, Number(value) - 1); setDate(newDate); onChange?.((0, _dateFns.format)(newDate, _constants.TIMEZONELESS_FORMAT)); } }) }, "month"); const yearField = /*#__PURE__*/(0, _jsxRuntime.jsx)(_styles.YearInput, { className: "components-datetime__time-field components-datetime__time-field-year" // Unused, for backwards compatibility. , label: (0, _i18n.__)('Year'), hideLabelFromVision: true, __next40pxDefaultSize: true, value: year, step: 1, min: 1, max: 9999, required: true, spinControls: "none", isPressEnterToChange: true, isDragEnabled: false, isShiftStepEnabled: false, onChange: buildNumberControlChangeCallback('year'), __unstableStateReducer: (0, _utils.buildPadInputStateReducer)(4) }, "year"); const defaultDateOrder = is12Hour ? 'mdy' : 'dmy'; const dateOrder = dateOrderProp && VALID_DATE_ORDERS.includes(dateOrderProp) ? dateOrderProp : defaultDateOrder; const fields = dateOrder.split('').map(field => { switch (field) { case 'd': return dayField; case 'm': return monthField; case 'y': return yearField; default: return null; } }); return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_styles.Wrapper, { className: "components-datetime__time" // Unused, for backwards compatibility. , children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_styles.Fieldset, { children: [hideLabelFromVision ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_visuallyHidden.VisuallyHidden, { as: "legend", children: (0, _i18n.__)('Time') }) : /*#__PURE__*/(0, _jsxRuntime.jsx)(_baseControl.default.VisualLabel, { as: "legend", className: "components-datetime__time-legend" // Unused, for backwards compatibility. , children: (0, _i18n.__)('Time') }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_hStack.HStack, { className: "components-datetime__time-wrapper" // Unused, for backwards compatibility. , children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_timeInput.TimeInput, { value: { hours: Number(hours), minutes: Number(minutes) }, is12Hour: is12Hour, onChange: onTimeInputChangeCallback }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_spacer.Spacer, {}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_timezone.default, {})] })] }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_styles.Fieldset, { children: [hideLabelFromVision ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_visuallyHidden.VisuallyHidden, { as: "legend", children: (0, _i18n.__)('Date') }) : /*#__PURE__*/(0, _jsxRuntime.jsx)(_baseControl.default.VisualLabel, { as: "legend", className: "components-datetime__time-legend" // Unused, for backwards compatibility. , children: (0, _i18n.__)('Date') }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_hStack.HStack, { className: "components-datetime__time-wrapper" // Unused, for backwards compatibility. , children: fields })] })] }); } /** * A component to input a time. * * Values are passed as an object in 24-hour format (`{ hours: number, minutes: number }`). * * ```jsx * import { TimePicker } from '@wordpress/components'; * import { useState } from '@wordpress/element'; * * const MyTimeInput = () => { * const [ time, setTime ] = useState( { hours: 13, minutes: 30 } ); * * return ( * <TimePicker.TimeInput * value={ time } * onChange={ setTime } * label="Time" * /> * ); * }; * ``` */ TimePicker.TimeInput = _timeInput.TimeInput; Object.assign(TimePicker.TimeInput, { displayName: 'TimePicker.TimeInput' }); var _default = exports.default = TimePicker; //# sourceMappingURL=index.js.map