@wordpress/components
Version:
UI components for WordPress.
219 lines (218 loc) • 6.69 kB
JavaScript
// packages/components/src/date-time/time/index.tsx
import { startOfMinute } from "date-fns";
import { useState, useMemo, useEffect } from "@wordpress/element";
import { __ } from "@wordpress/i18n";
import { date as formatDate } from "@wordpress/date";
import BaseControl from "../../base-control/index.mjs";
import { VisuallyHidden } from "../../visually-hidden/index.mjs";
import SelectControl from "../../select-control/index.mjs";
import TimeZone from "./timezone.mjs";
import { Wrapper, Fieldset, MonthSelectWrapper, DayInput, YearInput } from "./styles.mjs";
import { HStack } from "../../h-stack/index.mjs";
import { Spacer } from "../../spacer/index.mjs";
import { inputToDate, buildPadInputStateReducer, validateInputElementTarget, setInConfiguredTimezone, getDaysInMonth } from "../utils.mjs";
import { TIMEZONELESS_FORMAT } from "../constants.mjs";
import { TimeInput } from "./time-input/index.mjs";
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
var VALID_DATE_ORDERS = ["dmy", "mdy", "ymd"];
function TimePicker({
is12Hour,
currentTime,
onChange,
dateOrder: dateOrderProp,
hideLabelFromVision = false
}) {
const [date, setDate] = useState(() => (
// Truncate the date at the minutes, see: #15495.
startOfMinute(inputToDate(currentTime ?? /* @__PURE__ */ new Date()))
));
useEffect(() => {
setDate(startOfMinute(inputToDate(currentTime ?? /* @__PURE__ */ new Date())));
}, [currentTime]);
const monthOptions = [{
value: "01",
label: __("January")
}, {
value: "02",
label: __("February")
}, {
value: "03",
label: __("March")
}, {
value: "04",
label: __("April")
}, {
value: "05",
label: __("May")
}, {
value: "06",
label: __("June")
}, {
value: "07",
label: __("July")
}, {
value: "08",
label: __("August")
}, {
value: "09",
label: __("September")
}, {
value: "10",
label: __("October")
}, {
value: "11",
label: __("November")
}, {
value: "12",
label: __("December")
}];
const {
day,
month,
year,
minutes,
hours
} = useMemo(() => ({
day: formatDate("d", date),
month: formatDate("m", date),
year: formatDate("Y", date),
minutes: formatDate("i", date),
hours: formatDate("H", date)
}), [date]);
const buildNumberControlChangeCallback = (method) => {
const callback = (value, {
event
}) => {
if (!validateInputElementTarget(event)) {
return;
}
const numberValue = Number(value);
const newDate = setInConfiguredTimezone(date, {
[method]: numberValue
});
setDate(newDate);
onChange?.(formatDate(TIMEZONELESS_FORMAT, newDate));
};
return callback;
};
const onTimeInputChangeCallback = ({
hours: newHours,
minutes: newMinutes
}) => {
const newDate = setInConfiguredTimezone(date, {
hours: newHours,
minutes: newMinutes
});
setDate(newDate);
onChange?.(formatDate(TIMEZONELESS_FORMAT, newDate));
};
const dayField = /* @__PURE__ */ _jsx(DayInput, {
className: "components-datetime__time-field components-datetime__time-field-day",
label: __("Day"),
hideLabelFromVision: true,
__next40pxDefaultSize: true,
value: day,
step: 1,
min: 1,
max: getDaysInMonth(Number(year), Number(month) - 1),
required: true,
spinControls: "none",
isPressEnterToChange: true,
isDragEnabled: false,
isShiftStepEnabled: false,
onChange: buildNumberControlChangeCallback("date")
}, "day");
const monthField = /* @__PURE__ */ _jsx(MonthSelectWrapper, {
children: /* @__PURE__ */ _jsx(SelectControl, {
className: "components-datetime__time-field components-datetime__time-field-month",
label: __("Month"),
hideLabelFromVision: true,
__next40pxDefaultSize: true,
value: month,
options: monthOptions,
onChange: (value) => {
const newDate = setInConfiguredTimezone(date, {
month: Number(value) - 1
});
setDate(newDate);
onChange?.(formatDate(TIMEZONELESS_FORMAT, newDate));
}
})
}, "month");
const yearField = /* @__PURE__ */ _jsx(YearInput, {
className: "components-datetime__time-field components-datetime__time-field-year",
label: __("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: 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__ */ _jsxs(Wrapper, {
className: "components-datetime__time",
children: [/* @__PURE__ */ _jsxs(Fieldset, {
children: [hideLabelFromVision ? /* @__PURE__ */ _jsx(VisuallyHidden, {
as: "legend",
children: __("Time")
}) : /* @__PURE__ */ _jsx(BaseControl.VisualLabel, {
as: "legend",
className: "components-datetime__time-legend",
children: __("Time")
}), /* @__PURE__ */ _jsxs(HStack, {
className: "components-datetime__time-wrapper",
children: [/* @__PURE__ */ _jsx(TimeInput, {
value: {
hours: Number(hours),
minutes: Number(minutes)
},
is12Hour,
onChange: onTimeInputChangeCallback
}), /* @__PURE__ */ _jsx(Spacer, {}), /* @__PURE__ */ _jsx(TimeZone, {})]
})]
}), /* @__PURE__ */ _jsxs(Fieldset, {
children: [hideLabelFromVision ? /* @__PURE__ */ _jsx(VisuallyHidden, {
as: "legend",
children: __("Date")
}) : /* @__PURE__ */ _jsx(BaseControl.VisualLabel, {
as: "legend",
className: "components-datetime__time-legend",
children: __("Date")
}), /* @__PURE__ */ _jsx(HStack, {
className: "components-datetime__time-wrapper",
children: fields
})]
})]
});
}
TimePicker.TimeInput = TimeInput;
Object.assign(TimePicker.TimeInput, {
displayName: "TimePicker.TimeInput"
});
var time_default = TimePicker;
export {
TimePicker,
time_default as default
};
//# sourceMappingURL=index.mjs.map