UNPKG

@wordpress/components

Version:
209 lines (208 loc) 7.14 kB
// packages/components/src/date-time/date/index.tsx import { format, isSameDay, subMonths, addMonths, startOfDay, isEqual, addDays, subWeeks, addWeeks, isSameMonth, startOfWeek, endOfWeek } from "date-fns"; import { __, _n, sprintf, isRTL } from "@wordpress/i18n"; import { arrowLeft, arrowRight } from "@wordpress/icons"; import { getSettings, gmdateI18n } from "@wordpress/date"; import { useState, useRef, useEffect } from "@wordpress/element"; import { useLilius } from "./use-lilius"; import { Wrapper, Navigator, ViewPreviousMonthButton, ViewNextMonthButton, NavigatorHeading, Calendar, DayOfWeek, DayButton } from "./styles"; import { inputToDate } from "../utils"; import { TIMEZONELESS_FORMAT } from "../constants"; import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; function DatePicker({ currentDate, onChange, events = [], isInvalidDate, onMonthPreviewed, startOfWeek: weekStartsOn = 0 }) { const date = currentDate ? inputToDate(currentDate) : /* @__PURE__ */ new Date(); const { calendar, viewing, setSelected, setViewing, isSelected, viewPreviousMonth, viewNextMonth } = useLilius({ selected: [startOfDay(date)], viewing: startOfDay(date), weekStartsOn }); const [focusable, setFocusable] = useState(startOfDay(date)); const [isFocusWithinCalendar, setIsFocusWithinCalendar] = useState(false); const [prevCurrentDate, setPrevCurrentDate] = useState(currentDate); if (currentDate !== prevCurrentDate) { setPrevCurrentDate(currentDate); setSelected([startOfDay(date)]); setViewing(startOfDay(date)); setFocusable(startOfDay(date)); } return /* @__PURE__ */ _jsxs(Wrapper, { className: "components-datetime__date", role: "application", "aria-label": __("Calendar"), children: [/* @__PURE__ */ _jsxs(Navigator, { children: [/* @__PURE__ */ _jsx(ViewPreviousMonthButton, { icon: isRTL() ? arrowRight : arrowLeft, variant: "tertiary", "aria-label": __("View previous month"), onClick: () => { viewPreviousMonth(); setFocusable(subMonths(focusable, 1)); onMonthPreviewed?.(format(subMonths(viewing, 1), TIMEZONELESS_FORMAT)); }, size: "compact" }), /* @__PURE__ */ _jsxs(NavigatorHeading, { level: 3, children: [/* @__PURE__ */ _jsx("strong", { children: gmdateI18n("F", viewing) }), " ", gmdateI18n("Y", viewing)] }), /* @__PURE__ */ _jsx(ViewNextMonthButton, { icon: isRTL() ? arrowLeft : arrowRight, variant: "tertiary", "aria-label": __("View next month"), onClick: () => { viewNextMonth(); setFocusable(addMonths(focusable, 1)); onMonthPreviewed?.(format(addMonths(viewing, 1), TIMEZONELESS_FORMAT)); }, size: "compact" })] }), /* @__PURE__ */ _jsxs(Calendar, { onFocus: () => setIsFocusWithinCalendar(true), onBlur: () => setIsFocusWithinCalendar(false), children: [calendar[0][0].map((day) => /* @__PURE__ */ _jsx(DayOfWeek, { children: gmdateI18n("D", day) }, day.toString())), calendar[0].map((week) => week.map((day, index) => { if (!isSameMonth(day, viewing)) { return null; } return /* @__PURE__ */ _jsx(Day, { day, column: index + 1, isSelected: isSelected(day), isFocusable: isEqual(day, focusable), isFocusAllowed: isFocusWithinCalendar, isToday: isSameDay(day, /* @__PURE__ */ new Date()), isInvalid: isInvalidDate ? isInvalidDate(day) : false, numEvents: events.filter((event) => isSameDay(event.date, day)).length, onClick: () => { setSelected([day]); setFocusable(day); onChange?.(format( // Don't change the selected date's time fields. new Date(day.getFullYear(), day.getMonth(), day.getDate(), date.getHours(), date.getMinutes(), date.getSeconds(), date.getMilliseconds()), TIMEZONELESS_FORMAT )); }, onKeyDown: (event) => { let nextFocusable; if (event.key === "ArrowLeft") { nextFocusable = addDays(day, isRTL() ? 1 : -1); } if (event.key === "ArrowRight") { nextFocusable = addDays(day, isRTL() ? -1 : 1); } if (event.key === "ArrowUp") { nextFocusable = subWeeks(day, 1); } if (event.key === "ArrowDown") { nextFocusable = addWeeks(day, 1); } if (event.key === "PageUp") { nextFocusable = subMonths(day, 1); } if (event.key === "PageDown") { nextFocusable = addMonths(day, 1); } if (event.key === "Home") { nextFocusable = startOfWeek(day); } if (event.key === "End") { nextFocusable = startOfDay(endOfWeek(day)); } if (nextFocusable) { event.preventDefault(); setFocusable(nextFocusable); if (!isSameMonth(nextFocusable, viewing)) { setViewing(nextFocusable); onMonthPreviewed?.(format(nextFocusable, TIMEZONELESS_FORMAT)); } } } }, day.toString()); }))] })] }); } function Day({ day, column, isSelected, isFocusable, isFocusAllowed, isToday, isInvalid, numEvents, onClick, onKeyDown }) { const ref = useRef(); useEffect(() => { if (ref.current && isFocusable && isFocusAllowed) { ref.current.focus(); } }, [isFocusable]); return /* @__PURE__ */ _jsx(DayButton, { __next40pxDefaultSize: true, ref, className: "components-datetime__date__day", disabled: isInvalid, tabIndex: isFocusable ? 0 : -1, "aria-label": getDayLabel(day, isSelected, numEvents), column, isSelected, isToday, hasEvents: numEvents > 0, onClick, onKeyDown, children: gmdateI18n("j", day) }); } function getDayLabel(date, isSelected, numEvents) { const { formats } = getSettings(); const localizedDate = gmdateI18n(formats.date, date); if (isSelected && numEvents > 0) { return sprintf( // translators: 1: The calendar date. 2: Number of events on the calendar date. _n("%1$s. Selected. There is %2$d event", "%1$s. Selected. There are %2$d events", numEvents), localizedDate, numEvents ); } else if (isSelected) { return sprintf( // translators: 1: The calendar date. __("%1$s. Selected"), localizedDate ); } else if (numEvents > 0) { return sprintf( // translators: 1: The calendar date. 2: Number of events on the calendar date. _n("%1$s. There is %2$d event", "%1$s. There are %2$d events", numEvents), localizedDate, numEvents ); } return localizedDate; } var date_default = DatePicker; export { DatePicker, date_default as default }; //# sourceMappingURL=index.js.map