UNPKG

@gechiui/components

Version:
284 lines (250 loc) 9.69 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.TimePicker = TimePicker; exports.default = void 0; var _element = require("@gechiui/element"); var _classnames = _interopRequireDefault(require("classnames")); var _lodash = require("lodash"); var _moment = _interopRequireDefault(require("moment")); var _i18n = require("@gechiui/i18n"); var _button = _interopRequireDefault(require("../button")); var _buttonGroup = _interopRequireDefault(require("../button-group")); var _timezone = _interopRequireDefault(require("./timezone")); /** * External dependencies */ /** * GeChiUI dependencies */ /** * Internal dependencies */ /** * Module Constants */ const TIMEZONELESS_FORMAT = 'YYYY-MM-DDTHH:mm:ss'; function from12hTo24h(hours, isPm) { return isPm ? (hours % 12 + 12) % 24 : hours % 12; } /** * <UpdateOnBlurAsIntegerField> * A shared component to parse, validate, and handle remounting of the underlying form field element like <input> and <select>. * * @param {Object} props Component props. * @param {string} props.as Render the component as specific element tag, defaults to "input". * @param {number|string} props.value The default value of the component which will be parsed to integer. * @param {Function} props.onUpdate Call back when blurred and validated. */ function UpdateOnBlurAsIntegerField(_ref) { let { as, value, onUpdate, ...props } = _ref; function handleBlur(event) { const { target } = event; if (value === target.value) { return; } const parsedValue = parseInt(target.value, 10); // Run basic number validation on the input. if (!(0, _lodash.isInteger)(parsedValue) || typeof props.max !== 'undefined' && parsedValue > props.max || typeof props.min !== 'undefined' && parsedValue < props.min) { // If validation failed, reset the value to the previous valid value. target.value = value; } else { // Otherwise, it's valid, call onUpdate. onUpdate(target.name, parsedValue); } } return (0, _element.createElement)(as || 'input', { // Re-mount the input value to accept the latest value as the defaultValue. key: value, defaultValue: value, onBlur: handleBlur, ...props }); } /** * <TimePicker> * * @typedef {Date|string|number} GCValidDateTimeFormat * * @param {Object} props Component props. * @param {boolean} props.is12Hour Should the time picker showed in 12 hour format or 24 hour format. * @param {GCValidDateTimeFormat} props.currentTime The initial current time the time picker should render. * @param {Function} props.onChange Callback function when the date changed. */ function TimePicker(_ref2) { let { is12Hour, currentTime, onChange } = _ref2; const [date, setDate] = (0, _element.useState)(() => // Truncate the date at the minutes, see: #15495. (0, _moment.default)(currentTime).startOf('minutes')); // Reset the state when currentTime changed. (0, _element.useEffect)(() => { setDate(currentTime ? (0, _moment.default)(currentTime).startOf('minutes') : (0, _moment.default)()); }, [currentTime]); const { day, month, year, minutes, hours, am } = (0, _element.useMemo)(() => ({ day: date.format('DD'), month: date.format('MM'), year: date.format('YYYY'), minutes: date.format('mm'), hours: date.format(is12Hour ? 'hh' : 'HH'), am: date.format('H') <= 11 ? 'AM' : 'PM' }), [date, is12Hour]); /** * Function that sets the date state and calls the onChange with a new date. * The date is truncated at the minutes. * * @param {Object} newDate The date object. */ function changeDate(newDate) { setDate(newDate); onChange(newDate.format(TIMEZONELESS_FORMAT)); } function update(name, value) { // If the 12-hour format is being used and the 'PM' period is selected, then // the incoming value (which ranges 1-12) should be increased by 12 to match // the expected 24-hour format. let adjustedValue = value; if (name === 'hours' && is12Hour) { adjustedValue = from12hTo24h(value, am === 'PM'); } // Clone the date and call the specific setter function according to `name`. const newDate = date.clone()[name](adjustedValue); changeDate(newDate); } function updateAmPm(value) { return () => { if (am === value) { return; } const parsedHours = parseInt(hours, 10); const newDate = date.clone().hours(from12hTo24h(parsedHours, value === 'PM')); changeDate(newDate); }; } const dayFormat = (0, _element.createElement)("div", { className: "components-datetime__time-field components-datetime__time-field-day" }, (0, _element.createElement)(UpdateOnBlurAsIntegerField, { "aria-label": (0, _i18n.__)('日'), className: "components-datetime__time-field-day-input", type: "number" // The correct function to call in moment.js is "date" not "day". , name: "date", value: day, step: 1, min: 1, max: 31, onUpdate: update })); const monthFormat = (0, _element.createElement)("div", { className: "components-datetime__time-field components-datetime__time-field-month" }, (0, _element.createElement)(UpdateOnBlurAsIntegerField, { as: "select", "aria-label": (0, _i18n.__)('月'), className: "components-datetime__time-field-month-select", name: "month", value: month // The value starts from 0, so we have to -1 when setting month. , onUpdate: (key, value) => update(key, value - 1) }, (0, _element.createElement)("option", { value: "01" }, (0, _i18n.__)('1月')), (0, _element.createElement)("option", { value: "02" }, (0, _i18n.__)('2月')), (0, _element.createElement)("option", { value: "03" }, (0, _i18n.__)('3月')), (0, _element.createElement)("option", { value: "04" }, (0, _i18n.__)('4月')), (0, _element.createElement)("option", { value: "05" }, (0, _i18n.__)('5月')), (0, _element.createElement)("option", { value: "06" }, (0, _i18n.__)('6月')), (0, _element.createElement)("option", { value: "07" }, (0, _i18n.__)('7月')), (0, _element.createElement)("option", { value: "08" }, (0, _i18n.__)('8月')), (0, _element.createElement)("option", { value: "09" }, (0, _i18n.__)('9月')), (0, _element.createElement)("option", { value: "10" }, (0, _i18n.__)('10月')), (0, _element.createElement)("option", { value: "11" }, (0, _i18n.__)('11月')), (0, _element.createElement)("option", { value: "12" }, (0, _i18n.__)('12月')))); const dayMonthFormat = is12Hour ? (0, _element.createElement)(_element.Fragment, null, dayFormat, monthFormat) : (0, _element.createElement)(_element.Fragment, null, monthFormat, dayFormat); return (0, _element.createElement)("div", { className: (0, _classnames.default)('components-datetime__time') }, (0, _element.createElement)("fieldset", null, (0, _element.createElement)("legend", { className: "components-datetime__time-legend invisible" }, (0, _i18n.__)('日期')), (0, _element.createElement)("div", { className: "components-datetime__time-wrapper" }, dayMonthFormat, (0, _element.createElement)("div", { className: "components-datetime__time-field components-datetime__time-field-year" }, (0, _element.createElement)(UpdateOnBlurAsIntegerField, { "aria-label": (0, _i18n.__)('年'), className: "components-datetime__time-field-year-input", type: "number", name: "year", step: 1, min: 0, max: 9999, value: year, onUpdate: update })))), (0, _element.createElement)("fieldset", null, (0, _element.createElement)("legend", { className: "components-datetime__time-legend invisible" }, (0, _i18n.__)('时间')), (0, _element.createElement)("div", { className: "components-datetime__time-wrapper" }, (0, _element.createElement)("div", { className: "components-datetime__time-field components-datetime__time-field-time" }, (0, _element.createElement)(UpdateOnBlurAsIntegerField, { "aria-label": (0, _i18n.__)('小时'), className: "components-datetime__time-field-hours-input", type: "number", name: "hours", step: 1, min: is12Hour ? 1 : 0, max: is12Hour ? 12 : 23, value: hours, onUpdate: update }), (0, _element.createElement)("span", { className: "components-datetime__time-separator", "aria-hidden": "true" }, ":"), (0, _element.createElement)(UpdateOnBlurAsIntegerField, { "aria-label": (0, _i18n.__)('分钟'), className: "components-datetime__time-field-minutes-input", type: "number", name: "minutes", step: 1, min: 0, max: 59, value: minutes, onUpdate: update })), is12Hour && (0, _element.createElement)(_buttonGroup.default, { className: "components-datetime__time-field components-datetime__time-field-am-pm" }, (0, _element.createElement)(_button.default, { variant: am === 'AM' ? 'primary' : 'secondary', onClick: updateAmPm('AM'), className: "components-datetime__time-am-button" }, (0, _i18n.__)('上午')), (0, _element.createElement)(_button.default, { variant: am === 'PM' ? 'primary' : 'secondary', onClick: updateAmPm('PM'), className: "components-datetime__time-pm-button" }, (0, _i18n.__)('下午'))), (0, _element.createElement)(_timezone.default, null)))); } var _default = TimePicker; exports.default = _default; //# sourceMappingURL=time.js.map