@lifesg/react-design-system 4.0.0-alpha.8 → 4.0.0-alpha.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/accordion/accordion-item.js.map +1 -1
- package/accordion/accordion.js.map +1 -1
- package/alert/alert.js.map +1 -1
- package/cjs/accordion/accordion-item.js.map +1 -1
- package/cjs/accordion/accordion.js.map +1 -1
- package/cjs/alert/alert.js.map +1 -1
- package/cjs/countdown-timer/countdown-timer.js.map +1 -1
- package/cjs/data-table/data-table.js +1 -1
- package/cjs/data-table/data-table.js.map +1 -1
- package/cjs/date-range-input/date-range-input.js.map +1 -1
- package/cjs/e-signature/e-signature-canvas.js.map +1 -1
- package/cjs/error-display/inactivity-timer.js.map +1 -1
- package/cjs/external/dompurify/dist/purify.es.js +2 -2
- package/cjs/external/dompurify/dist/purify.es.js.map +1 -1
- package/cjs/file-download/file-list-card/file-list-card.js.map +1 -1
- package/cjs/file-upload/custom-sensors.js.map +1 -1
- package/cjs/file-upload/file-list/file-list.js.map +1 -1
- package/cjs/filter/addons/filter-item-checkbox-helpers.js.map +1 -1
- package/cjs/filter/addons/filter-item-checkbox.js.map +1 -1
- package/cjs/filter/filter-item.js.map +1 -1
- package/cjs/filter/filter.js.map +1 -1
- package/cjs/form/form-textarea/form-textarea.js +1 -1
- package/cjs/form/form-textarea/form-textarea.js.map +1 -1
- package/cjs/fullscreen-image-carousel/stateful-image.js.map +1 -1
- package/cjs/histogram-slider/histogram-slider.js.map +1 -1
- package/cjs/input-range-slider/input-range-slider.js.map +1 -1
- package/cjs/input-slider/input-slider.js.map +1 -1
- package/cjs/input-textarea/textarea-counter.js.map +1 -1
- package/cjs/input-textarea/textarea.js +1 -1
- package/cjs/input-textarea/textarea.js.map +1 -1
- package/cjs/input-textarea/textarea.styles.js +1 -1
- package/cjs/input-textarea/textarea.styles.js.map +1 -1
- package/{input-textarea/textarea.styles_q77m5x.css → cjs/input-textarea/textarea.styles_6we7bs.css} +3 -1
- package/cjs/modal/index.js.map +1 -1
- package/cjs/modal-v2/modal-v2.js +1 -1
- package/cjs/modal-v2/modal-v2.js.map +1 -1
- package/cjs/modal-v2/slots/card.js +1 -1
- package/cjs/modal-v2/slots/card.js.map +1 -1
- package/cjs/modal-v2/slots/header.js +2 -0
- package/cjs/modal-v2/slots/header.js.map +1 -0
- package/cjs/modal-v2/slots/slot-styles.js +1 -1
- package/cjs/modal-v2/slots/slot-styles.js.map +1 -1
- package/cjs/modal-v2/slots/{slot-styles_13sd376.css → slot-styles_10ut1v7.css} +5 -1
- package/cjs/navbar/navbar-items.js +1 -1
- package/cjs/navbar/navbar-items.js.map +1 -1
- package/cjs/navbar/navbar-items.styles.js +1 -1
- package/cjs/navbar/navbar-items.styles.js.map +1 -1
- package/cjs/navbar/{navbar-items.styles_1i3ltot.css → navbar-items.styles_1b1zx.css} +9 -8
- package/cjs/navbar/navbar-logo-data.js +1 -1
- package/cjs/navbar/navbar-logo-data.js.map +1 -1
- package/cjs/navbar/navbar.js.map +1 -1
- package/cjs/otp-input/otp-input.js.map +1 -1
- package/cjs/overlay/overlay.js.map +1 -1
- package/cjs/pagination/pagination.js.map +1 -1
- package/cjs/phone-number-input/phone-number-input.js.map +1 -1
- package/cjs/predictive-text-input/predictive-text-input.js.map +1 -1
- package/cjs/shared/dropdown-list/dropdown-list.js.map +1 -1
- package/cjs/shared/internal-calendar/calendar-manager.js.map +1 -1
- package/cjs/shared/standalone-date-input/standalone-date-input.js.map +1 -1
- package/cjs/theme/types.js +1 -1
- package/cjs/theme/types.js.map +1 -1
- package/cjs/time-slot-bar/time-slot-bar.js.map +1 -1
- package/cjs/time-slot-bar-week/time-slot-bar-week-days.js.map +1 -1
- package/cjs/timetable/timetable.js.map +1 -1
- package/cjs/toggle/toggle-icon.js +1 -1
- package/cjs/toggle/toggle-icon.js.map +1 -1
- package/cjs/toggle/toggle-icon.styles.js +1 -1
- package/cjs/toggle/toggle-icon.styles.js.map +1 -1
- package/cjs/toggle/{toggle-icon.styles_ba71y.css → toggle-icon.styles_o6dxr3.css} +3 -2
- package/cjs/toggle/toggle.js +1 -1
- package/cjs/toggle/toggle.js.map +1 -1
- package/cjs/toggle/toggle.styles.js +1 -1
- package/cjs/toggle/toggle.styles.js.map +1 -1
- package/cjs/toggle/toggle.styles_11tmfsr.css +41 -0
- package/cjs/unit-number/unit-number-input.js.map +1 -1
- package/cjs/util/is-styled-components.js.map +1 -1
- package/cjs/util/string-helper.js +1 -1
- package/cjs/util/string-helper.js.map +1 -1
- package/cjs/util/use-event-listener.js.map +1 -1
- package/cjs/util/use-state-actions.js.map +1 -1
- package/countdown-timer/countdown-timer.js.map +1 -1
- package/data-table/data-table.js +1 -1
- package/data-table/data-table.js.map +1 -1
- package/data-table/types.d.ts +2 -2
- package/date-range-input/date-range-input.js.map +1 -1
- package/docs/component-catalog.json +1 -1
- package/e-signature/e-signature-canvas.js.map +1 -1
- package/error-display/inactivity-timer.js.map +1 -1
- package/external/dompurify/dist/purify.es.js +2 -2
- package/external/dompurify/dist/purify.es.js.map +1 -1
- package/file-download/file-list-card/file-list-card.js.map +1 -1
- package/file-upload/custom-sensors.d.ts +2 -2
- package/file-upload/custom-sensors.js.map +1 -1
- package/file-upload/file-list/file-list.js.map +1 -1
- package/filter/addons/filter-item-checkbox-helpers.js.map +1 -1
- package/filter/addons/filter-item-checkbox.js.map +1 -1
- package/filter/filter-item.js.map +1 -1
- package/filter/filter.js.map +1 -1
- package/form/form-textarea/form-textarea.js +1 -1
- package/form/form-textarea/form-textarea.js.map +1 -1
- package/fullscreen-image-carousel/stateful-image.js.map +1 -1
- package/fullscreen-image-carousel/types.d.ts +2 -2
- package/histogram-slider/histogram-slider.js.map +1 -1
- package/input-range-slider/input-range-slider.js.map +1 -1
- package/input-slider/input-slider.js.map +1 -1
- package/input-textarea/textarea-counter.js.map +1 -1
- package/input-textarea/textarea.js +1 -1
- package/input-textarea/textarea.js.map +1 -1
- package/input-textarea/textarea.styles.d.ts +2 -0
- package/input-textarea/textarea.styles.js +1 -1
- package/input-textarea/textarea.styles.js.map +1 -1
- package/{cjs/input-textarea/textarea.styles_q77m5x.css → input-textarea/textarea.styles_6we7bs.css} +3 -1
- package/input-textarea/types.d.ts +7 -0
- package/modal/index.d.ts +4 -0
- package/modal/index.js.map +1 -1
- package/modal/types.d.ts +2 -0
- package/modal-v2/modal-v2.d.ts +6 -0
- package/modal-v2/modal-v2.js +1 -1
- package/modal-v2/modal-v2.js.map +1 -1
- package/modal-v2/slots/card.js +1 -1
- package/modal-v2/slots/card.js.map +1 -1
- package/modal-v2/slots/header.d.ts +5 -0
- package/modal-v2/slots/header.js +2 -0
- package/modal-v2/slots/header.js.map +1 -0
- package/modal-v2/slots/index.d.ts +1 -0
- package/modal-v2/slots/slot-styles.d.ts +4 -0
- package/modal-v2/slots/slot-styles.js +1 -1
- package/modal-v2/slots/slot-styles.js.map +1 -1
- package/modal-v2/slots/{slot-styles_13sd376.css → slot-styles_10ut1v7.css} +5 -1
- package/modal-v2/types.d.ts +21 -0
- package/navbar/navbar-items.js +1 -1
- package/navbar/navbar-items.js.map +1 -1
- package/navbar/navbar-items.styles.d.ts +2 -1
- package/navbar/navbar-items.styles.js +1 -1
- package/navbar/navbar-items.styles.js.map +1 -1
- package/navbar/{navbar-items.styles_1i3ltot.css → navbar-items.styles_1b1zx.css} +9 -8
- package/navbar/navbar-logo-data.js +1 -1
- package/navbar/navbar-logo-data.js.map +1 -1
- package/navbar/navbar.js.map +1 -1
- package/otp-input/otp-input.js.map +1 -1
- package/overlay/overlay.js.map +1 -1
- package/package.json +1 -1
- package/pagination/pagination.js.map +1 -1
- package/phone-number-input/phone-number-input.js.map +1 -1
- package/predictive-text-input/predictive-text-input.js.map +1 -1
- package/shared/dropdown-list/dropdown-list.js.map +1 -1
- package/shared/internal-calendar/calendar-manager.js.map +1 -1
- package/shared/standalone-date-input/standalone-date-input.js.map +1 -1
- package/theme/styles/a11y-playground.css +358 -87
- package/theme/styles/bookingsg.css +391 -85
- package/theme/styles/careercompass.css +396 -90
- package/theme/styles/ccube.css +402 -45
- package/theme/styles/imda.css +348 -85
- package/theme/styles/lifesg.css +377 -87
- package/theme/styles/mylegacy.css +382 -85
- package/theme/styles/oneservice.css +349 -86
- package/theme/styles/pa.css +172 -63
- package/theme/styles/rbs.css +403 -46
- package/theme/styles/sgw-digital-lobby.css +352 -87
- package/theme/styles/smgs.css +401 -95
- package/theme/styles/spf.css +208 -99
- package/theme/styles/supportgowhere.css +387 -90
- package/theme/styles/tote-board.css +816 -0
- package/theme/types.d.ts +1 -1
- package/theme/types.js +1 -1
- package/theme/types.js.map +1 -1
- package/time-slot-bar/time-slot-bar.js.map +1 -1
- package/time-slot-bar-week/time-slot-bar-week-days.js.map +1 -1
- package/timetable/timetable.js.map +1 -1
- package/toggle/toggle-icon.d.ts +2 -1
- package/toggle/toggle-icon.js +1 -1
- package/toggle/toggle-icon.js.map +1 -1
- package/toggle/toggle-icon.styles.d.ts +1 -0
- package/toggle/toggle-icon.styles.js +1 -1
- package/toggle/toggle-icon.styles.js.map +1 -1
- package/toggle/{toggle-icon.styles_ba71y.css → toggle-icon.styles_o6dxr3.css} +3 -2
- package/toggle/toggle.js +1 -1
- package/toggle/toggle.js.map +1 -1
- package/toggle/toggle.styles.d.ts +18 -15
- package/toggle/toggle.styles.js +1 -1
- package/toggle/toggle.styles.js.map +1 -1
- package/toggle/toggle.styles_11tmfsr.css +41 -0
- package/unit-number/unit-number-input.js.map +1 -1
- package/util/is-styled-components.js.map +1 -1
- package/util/string-helper.d.ts +2 -2
- package/util/string-helper.js +1 -1
- package/util/string-helper.js.map +1 -1
- package/util/use-event-listener.js.map +1 -1
- package/util/use-state-actions.js.map +1 -1
- package/cjs/form/form-textarea/form-textarea.styles.js +0 -2
- package/cjs/form/form-textarea/form-textarea.styles.js.map +0 -1
- package/cjs/form/form-textarea/form-textarea.styles_1kneyif.css +0 -3
- package/cjs/toggle/toggle.styles_1t5qrye.css +0 -38
- package/form/form-textarea/form-textarea.styles.d.ts +0 -3
- package/form/form-textarea/form-textarea.styles.js +0 -2
- package/form/form-textarea/form-textarea.styles.js.map +0 -1
- package/form/form-textarea/form-textarea.styles_1kneyif.css +0 -3
- package/theme/styles/default.css +0 -158
- package/toggle/toggle.styles_1t5qrye.css +0 -38
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"calendar-manager.js","sources":["../../../../src/shared/internal-calendar/calendar-manager.tsx"],"sourcesContent":["import { ChevronDownIcon } from \"@lifesg/react-icons/chevron-down\";\nimport { ChevronLeftIcon } from \"@lifesg/react-icons/chevron-left\";\nimport { ChevronRightIcon } from \"@lifesg/react-icons/chevron-right\";\nimport clsx from \"clsx\";\nimport type { Dayjs } from \"dayjs\";\nimport dayjs from \"dayjs\";\nimport React, { useEffect, useImperativeHandle, useRef, useState } from \"react\";\n\nimport { Button } from \"../../button\";\nimport { DateHelper } from \"../../util\";\nimport { CalendarHelper } from \"../../util/calendar-helper\";\nimport { inertValue } from \"../accessibility\";\nimport { ClickableIcon } from \"../clickable-icon\";\nimport * as styles from \"./calendar-manager.styles\";\nimport { InternalCalendarMonth } from \"./internal-calendar-month\";\nimport { InternalCalendarYear } from \"./internal-calendar-year\";\nimport type {\n CalendarAction,\n CalendarManagerProps,\n CalendarManagerRef,\n View,\n} from \"./types\";\n\nconst Component = (\n {\n children,\n initialCalendarDate,\n minDate,\n maxDate,\n currentFocus,\n selectedStartDate,\n selectedEndDate,\n selectWithinRange,\n dynamicHeight = false,\n allowDisabledSelection,\n onCalendarDateChange,\n /* action button props */\n withButton,\n doneButtonDisabled,\n onDismiss,\n /* header props */\n showNavigationHeader = true,\n getLeftArrowDate,\n getRightArrowDate,\n isLeftArrowDisabled: _isLeftArrowDisabled,\n isRightArrowDisabled: _isRightArrowDisabled,\n getMonthHeaderLabel,\n getYearHeaderLabel,\n isFocusable = false,\n ...otherProps\n }: CalendarManagerProps,\n ref: React.ForwardedRef<CalendarManagerRef>\n) => {\n // =============================================================================\n // CONST, STATE, REF\n // =============================================================================\n // the current visible date in month/year views and header\n const [calendarDate, setCalendarDate] = useState<Dayjs>(\n DateHelper.toDayjs(initialCalendarDate)\n );\n // the selected date in month/year views and the current visible date in day view\n const [viewCalendarDate, setViewCalendarDate] = useState<Dayjs>(\n DateHelper.toDayjs(initialCalendarDate)\n );\n const [currentView, setCurrentView] = useState<View>(\"default\");\n\n const doneButtonRef = useRef<HTMLButtonElement>(null);\n const cancelButtonRef = useRef<HTMLButtonElement>(null);\n const containerRef = useRef<HTMLDivElement>(null);\n const yearDropdownRef = useRef<HTMLButtonElement>(null);\n\n // =============================================================================\n // EFFECTS\n // =============================================================================\n useImperativeHandle(ref, () => {\n return {\n defaultView() {\n setCurrentView(\"default\");\n },\n resetView() {\n const date = DateHelper.toDayjs(initialCalendarDate);\n setCalendarDate(date);\n setViewCalendarDate(date);\n\n setCurrentView(\"default\");\n },\n setCalendarDate(value?: string) {\n const date = DateHelper.toDayjs(value);\n setCalendarDate(date);\n setViewCalendarDate(date);\n },\n };\n });\n\n useEffect(() => {\n const date = DateHelper.toDayjs(initialCalendarDate);\n setCalendarDate(date);\n setViewCalendarDate(date);\n }, [initialCalendarDate]);\n\n useEffect(() => {\n performOnCalendarDateChange(viewCalendarDate);\n // more accurate than calendarDate since it accounts for selection state\n // in month/year views\n }, [viewCalendarDate]);\n\n // =============================================================================\n // EVENT HANDLERS\n // =============================================================================\n const handleMonthDropdownClick = () => {\n if (currentView !== \"month-options\") {\n setCurrentView(\"month-options\");\n\n // Maintain focus when selecting month dropdown\n containerRef.current?.focus();\n } else {\n setCurrentView(\"default\");\n setCalendarDate(viewCalendarDate);\n }\n };\n\n const handleMonthDropdownKeydown = (\n event: React.KeyboardEvent<HTMLButtonElement>\n ) => {\n if (event.key === \"Enter\" || event.key === \" \") {\n event.preventDefault();\n handleMonthDropdownClick();\n yearDropdownRef.current?.focus(); // Focus on year dropdown after month selection\n }\n\n // Up and Down arrow keys will change the month\n if (event.key === \"ArrowUp\" || event.key === \"ArrowDown\") {\n event.preventDefault();\n const nextDate =\n event.key === \"ArrowUp\"\n ? calendarDate.subtract(1, \"month\")\n : calendarDate.add(1, \"month\");\n\n if (\n !CalendarHelper.isWithinRange(\n nextDate,\n minDate ? dayjs(minDate) : undefined,\n maxDate ? dayjs(maxDate) : undefined,\n \"month\"\n )\n )\n return;\n setCalendarDate(nextDate);\n\n if (currentView === \"default\") {\n setViewCalendarDate(nextDate);\n }\n }\n };\n\n const handleYearDropdownClick = () => {\n /**\n * If the view is in the month options view,\n * then clicking will send the view back to\n * default\n */\n if (currentView !== \"default\") {\n setCurrentView(\"default\");\n setCalendarDate(viewCalendarDate);\n } else {\n setCurrentView(\"year-options\");\n }\n };\n\n const handleYearDropdownKeydown = (\n event: React.KeyboardEvent<HTMLButtonElement>\n ) => {\n if (event.key === \"Enter\" || event.key === \" \") {\n event.preventDefault();\n handleYearDropdownClick();\n }\n\n // Up and Down arrow keys will change the year\n if (event.key === \"ArrowUp\" || event.key === \"ArrowDown\") {\n event.preventDefault();\n const isYearView = currentView === \"year-options\";\n let nextDate: Dayjs;\n\n if (isYearView) {\n // In year options view, change decade\n nextDate =\n event.key === \"ArrowUp\"\n ? calendarDate.subtract(10, \"year\")\n : calendarDate.add(10, \"year\");\n } else {\n // In default view, change year\n nextDate =\n event.key === \"ArrowUp\"\n ? calendarDate.subtract(1, \"year\")\n : calendarDate.add(1, \"year\");\n }\n\n if (\n !CalendarHelper.isWithinRange(\n nextDate,\n minDate ? dayjs(minDate) : undefined,\n maxDate ? dayjs(maxDate) : undefined,\n \"year\"\n )\n )\n return;\n\n setCalendarDate(nextDate);\n\n if (currentView === \"default\") {\n setViewCalendarDate(nextDate);\n }\n }\n };\n\n const handleLeftArrowClick = () => {\n // Maintain focus as button could become disabled\n containerRef.current?.focus();\n\n const nextDate = getLeftArrowDate\n ? getLeftArrowDate(calendarDate)\n : calendarDate.subtract(1, \"month\");\n\n switch (currentView) {\n case \"default\":\n setViewCalendarDate(nextDate);\n setCalendarDate(nextDate);\n break;\n case \"month-options\":\n setCalendarDate((date) => date.subtract(1, \"year\"));\n break;\n case \"year-options\":\n setCalendarDate((date) => date.subtract(10, \"year\"));\n break;\n }\n };\n\n const handleRightArrowClick = () => {\n // Maintain focus as button could become disabled\n containerRef.current?.focus();\n\n const nextDate = getRightArrowDate\n ? getRightArrowDate(calendarDate)\n : calendarDate.add(1, \"month\");\n\n switch (currentView) {\n case \"default\":\n setViewCalendarDate(nextDate);\n setCalendarDate(nextDate);\n break;\n case \"month-options\":\n setCalendarDate((date) => date.add(1, \"year\"));\n break;\n case \"year-options\":\n setCalendarDate((date) => date.add(10, \"year\"));\n break;\n }\n };\n\n const handleMonthYearSelect = (value: Dayjs) => {\n setCalendarDate(value);\n setViewCalendarDate(value);\n\n if (!withButton) {\n setCurrentView(\"default\");\n }\n };\n\n const handleCancelButton = () => {\n const initialValue = DateHelper.toDayjs(initialCalendarDate);\n setCalendarDate(initialValue);\n setViewCalendarDate(initialValue);\n\n if (currentView === \"default\") {\n performOnDismissHandler(\"reset\");\n } else {\n setCurrentView(\"default\");\n }\n };\n\n const handleDoneButton = (isDisabled: boolean | undefined) => {\n if (isDisabled) return;\n\n setCalendarDate(viewCalendarDate);\n\n if (currentView === \"default\") {\n performOnDismissHandler(\"confirmed\");\n } else {\n setCurrentView(\"default\");\n }\n };\n\n // =============================================================================\n // HELPER FUNCTIONS\n // =============================================================================\n const performOnCalendarDateChange = (date: Dayjs) => {\n if (onCalendarDateChange) {\n onCalendarDateChange(date);\n }\n };\n\n const performOnDismissHandler = (action: CalendarAction) => {\n if (onDismiss) {\n onDismiss(action);\n }\n };\n\n const isLeftArrowDisabled = () => {\n if (!minDate || allowDisabledSelection) {\n return false;\n }\n\n const min = dayjs(minDate);\n if (currentView === \"month-options\") {\n return !CalendarHelper.isPreviousYearWithinRange(calendarDate, min);\n } else if (currentView === \"year-options\") {\n return !CalendarHelper.isPreviousDecadeWithinRange(\n calendarDate,\n min\n );\n } else {\n if (_isLeftArrowDisabled) {\n return _isLeftArrowDisabled(calendarDate);\n }\n return !CalendarHelper.isPreviousMonthWithinRange(\n calendarDate,\n min\n );\n }\n };\n\n const isRightArrowDisabled = () => {\n if (!maxDate || allowDisabledSelection) {\n return false;\n }\n\n const max = dayjs(maxDate);\n if (currentView === \"month-options\") {\n return !CalendarHelper.isNextYearWithinRange(calendarDate, max);\n } else if (currentView === \"year-options\") {\n return !CalendarHelper.isNextDecadeWithinRange(calendarDate, max);\n } else {\n if (_isRightArrowDisabled) {\n return _isRightArrowDisabled(calendarDate);\n }\n return !CalendarHelper.isNextMonthWithinRange(calendarDate, max);\n }\n };\n\n // =============================================================================\n // RENDER FUNCTIONS\n // =============================================================================\n\n const getYearHeaderText = (): string => {\n if (currentView === \"year-options\") {\n const { beginDecade, endDecade } =\n CalendarHelper.getStartEndDecade(calendarDate);\n\n return `${beginDecade} to ${endDecade}`;\n } else {\n return getYearHeaderLabel\n ? getYearHeaderLabel(calendarDate)\n : calendarDate.format(\"YYYY\");\n }\n };\n\n const renderDropdownButtons = () => {\n const monthLabel = getMonthHeaderLabel\n ? getMonthHeaderLabel(calendarDate)\n : calendarDate.format(\"MMM\");\n\n const fullMonthLabel = dayjs(monthLabel, \"MMM\").format(\"MMMM\");\n\n const yearLabel = getYearHeaderText();\n const viewToYearLabel: Record<View, string> = {\n \"month-options\": `${yearLabel}, Close month selection`,\n \"year-options\": `${yearLabel}, Close year selection`,\n default: `${yearLabel}, Select year`,\n };\n\n return (\n <>\n <button\n className={clsx(\n styles.dropdownButton,\n currentView !== \"default\" && styles.hidden\n )}\n aria-label={`${fullMonthLabel}, Select month`}\n type=\"button\"\n id=\"month-dropdown\"\n onClick={handleMonthDropdownClick}\n onKeyDown={handleMonthDropdownKeydown}\n tabIndex={isFocusable ? 0 : -1}\n >\n <span className={styles.dropdownText}>{monthLabel}</span>\n <ChevronDownIcon\n className={clsx(\n styles.icon,\n styles.iconChevronDown,\n currentView === \"month-options\" &&\n styles.iconChevronDownExpanded\n )}\n />\n </button>\n <button\n ref={yearDropdownRef}\n className={styles.dropdownButton}\n aria-label={viewToYearLabel[currentView]}\n type=\"button\"\n id=\"year-dropdown\"\n onClick={handleYearDropdownClick}\n onKeyDown={handleYearDropdownKeydown}\n tabIndex={isFocusable ? 0 : -1}\n >\n <span className={styles.dropdownText}>{yearLabel}</span>\n <ChevronDownIcon\n className={clsx(\n styles.icon,\n styles.iconChevronDown,\n currentView !== \"default\" &&\n styles.iconChevronDownExpanded\n )}\n />\n </button>\n </>\n );\n };\n\n const renderOptionsOverlay = () => {\n switch (currentView) {\n case \"month-options\":\n return (\n <InternalCalendarMonth\n calendarDate={calendarDate}\n currentFocus={currentFocus}\n minDate={minDate}\n maxDate={maxDate}\n selectedStartDate={selectedStartDate}\n selectedEndDate={selectedEndDate}\n viewCalendarDate={viewCalendarDate}\n isNewSelection={!!selectWithinRange}\n onMonthSelect={handleMonthYearSelect}\n allowDisabledSelection={allowDisabledSelection}\n />\n );\n case \"year-options\":\n return (\n <InternalCalendarYear\n setCalendarDate={setCalendarDate}\n calendarDate={calendarDate}\n currentFocus={currentFocus}\n minDate={minDate}\n maxDate={maxDate}\n selectedStartDate={selectedStartDate}\n selectedEndDate={selectedEndDate}\n viewCalendarDate={viewCalendarDate}\n isNewSelection={!!selectWithinRange}\n onYearSelect={handleMonthYearSelect}\n allowDisabledSelection={allowDisabledSelection}\n />\n );\n default:\n return null;\n }\n };\n\n const renderHeader = () => {\n const viewToSelection: Record<View, string> = {\n \"month-options\": \"year\",\n \"year-options\": \"decade\",\n default: \"month\",\n };\n\n const selection = viewToSelection[currentView];\n\n return (\n <div\n className={styles.header}\n data-id=\"calendar-header\"\n data-testid=\"calendar-header\"\n >\n <div className={styles.headerInputDropdown}>\n {renderDropdownButtons()}\n </div>\n <div className={styles.headerArrows}>\n <ClickableIcon\n className={styles.headerArrowButton}\n aria-label={`Previous ${selection}`}\n data-testid=\"left-arrow-btn\"\n disabled={isLeftArrowDisabled()}\n focusHighlight={false}\n focusOutline=\"browser\"\n onClick={handleLeftArrowClick}\n tabIndex={isFocusable ? 0 : -1}\n >\n <ChevronLeftIcon className={styles.icon} />\n </ClickableIcon>\n <ClickableIcon\n className={styles.headerArrowButton}\n aria-label={`Next ${selection}`}\n data-testid=\"right-arrow-btn\"\n disabled={isRightArrowDisabled()}\n focusHighlight={false}\n focusOutline=\"browser\"\n onClick={handleRightArrowClick}\n tabIndex={isFocusable ? 0 : -1}\n >\n <ChevronRightIcon className={styles.icon} />\n </ClickableIcon>\n </div>\n </div>\n );\n };\n\n const renderActionButtons = () => {\n if (!withButton) return;\n\n const isDayView = currentView === \"default\";\n\n const disabled = !isDayView ? false : doneButtonDisabled;\n\n return (\n <div className={styles.actionButtonSection}>\n <Button\n className={styles.actionButton}\n ref={cancelButtonRef}\n data-testid=\"cancel-button\"\n styleType=\"light\"\n type=\"button\"\n onClick={handleCancelButton}\n sizeType=\"small\"\n >\n Cancel\n </Button>\n <Button\n className={styles.actionButton}\n data-testid=\"done-button\"\n ref={doneButtonRef}\n type=\"button\"\n onClick={() => handleDoneButton(disabled)}\n disabled={disabled}\n sizeType=\"small\"\n >\n Done\n </Button>\n </div>\n );\n };\n\n const renderViews = () => {\n const defaultView =\n typeof children === \"function\"\n ? children({ calendarDate: viewCalendarDate, currentView })\n : children;\n\n if (dynamicHeight) {\n return (\n <>\n {currentView === \"default\" && defaultView}\n {renderOptionsOverlay()}\n </>\n );\n } else {\n const isDefaultView = currentView === \"default\";\n return (\n // Prevent interaction with the default view when options are open\n <>\n <div\n className={styles.defaultView}\n inert={inertValue(!isDefaultView)}\n >\n {defaultView}\n </div>\n <div\n className={clsx(\n styles.optionsOverlay,\n isDefaultView && styles.hidden\n )}\n >\n {renderOptionsOverlay()}\n </div>\n </>\n );\n }\n };\n\n return (\n <div\n className={styles.container}\n ref={containerRef}\n data-id=\"calendar-container\"\n data-testid=\"calendar-container\"\n aria-label={viewCalendarDate.format(\"MMMM, YYYY\")}\n role=\"group\"\n {...otherProps}\n >\n {showNavigationHeader && renderHeader()}\n <div className={styles.toggleZone} data-testid=\"toggle-zone\">\n {renderViews()}\n </div>\n {renderActionButtons()}\n </div>\n );\n};\n\nexport const CalendarManager = React.forwardRef(Component);\n"],"names":["CalendarManager","React","forwardRef","_a","ref","children","initialCalendarDate","minDate","maxDate","currentFocus","selectedStartDate","selectedEndDate","selectWithinRange","dynamicHeight","allowDisabledSelection","onCalendarDateChange","withButton","doneButtonDisabled","onDismiss","showNavigationHeader","getLeftArrowDate","getRightArrowDate","isLeftArrowDisabled","_isLeftArrowDisabled","isRightArrowDisabled","_isRightArrowDisabled","getMonthHeaderLabel","getYearHeaderLabel","isFocusable","otherProps","__rest","calendarDate","setCalendarDate","useState","DateHelper","toDayjs","viewCalendarDate","setViewCalendarDate","currentView","setCurrentView","doneButtonRef","useRef","cancelButtonRef","containerRef","yearDropdownRef","useImperativeHandle","defaultView","resetView","date","value","useEffect","performOnCalendarDateChange","handleMonthDropdownClick","current","focus","handleMonthDropdownKeydown","event","key","preventDefault","nextDate","subtract","add","CalendarHelper","isWithinRange","dayjs","undefined","handleYearDropdownClick","handleYearDropdownKeydown","handleLeftArrowClick","handleRightArrowClick","handleMonthYearSelect","handleCancelButton","initialValue","performOnDismissHandler","action","min","isPreviousYearWithinRange","isPreviousDecadeWithinRange","isPreviousMonthWithinRange","max","isNextYearWithinRange","isNextDecadeWithinRange","isNextMonthWithinRange","renderDropdownButtons","monthLabel","format","fullMonthLabel","yearLabel","beginDecade","endDecade","getStartEndDecade","getYearHeaderText","viewToYearLabel","default","_jsxs","_Fragment","className","clsx","styles.dropdownButton","styles.hidden","type","id","onClick","onKeyDown","tabIndex","_jsx","styles.dropdownText","ChevronDownIcon","styles.icon","styles.iconChevronDown","styles.iconChevronDownExpanded","renderOptionsOverlay","InternalCalendarMonth","isNewSelection","onMonthSelect","InternalCalendarYear","onYearSelect","styles.container","role","selection","styles.header","styles.headerInputDropdown","styles.headerArrows","ClickableIcon","styles.headerArrowButton","disabled","focusHighlight","focusOutline","ChevronLeftIcon","ChevronRightIcon","renderHeader","styles.toggleZone","isDefaultView","styles.defaultView","inert","inertValue","styles.optionsOverlay","renderViews","styles.actionButtonSection","Button","styles.actionButton","styleType","sizeType","renderActionButtons"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"calendar-manager.js","sources":["../../../../src/shared/internal-calendar/calendar-manager.tsx"],"sourcesContent":["import { ChevronDownIcon } from \"@lifesg/react-icons/chevron-down\";\nimport { ChevronLeftIcon } from \"@lifesg/react-icons/chevron-left\";\nimport { ChevronRightIcon } from \"@lifesg/react-icons/chevron-right\";\nimport clsx from \"clsx\";\nimport type { Dayjs } from \"dayjs\";\nimport dayjs from \"dayjs\";\nimport React, { useEffect, useImperativeHandle, useRef, useState } from \"react\";\n\nimport { Button } from \"../../button\";\nimport { DateHelper } from \"../../util\";\nimport { CalendarHelper } from \"../../util/calendar-helper\";\nimport { inertValue } from \"../accessibility\";\nimport { ClickableIcon } from \"../clickable-icon\";\nimport * as styles from \"./calendar-manager.styles\";\nimport { InternalCalendarMonth } from \"./internal-calendar-month\";\nimport { InternalCalendarYear } from \"./internal-calendar-year\";\nimport type {\n CalendarAction,\n CalendarManagerProps,\n CalendarManagerRef,\n View,\n} from \"./types\";\n\nconst Component = (\n {\n children,\n initialCalendarDate,\n minDate,\n maxDate,\n currentFocus,\n selectedStartDate,\n selectedEndDate,\n selectWithinRange,\n dynamicHeight = false,\n allowDisabledSelection,\n onCalendarDateChange,\n /* action button props */\n withButton,\n doneButtonDisabled,\n onDismiss,\n /* header props */\n showNavigationHeader = true,\n getLeftArrowDate,\n getRightArrowDate,\n isLeftArrowDisabled: _isLeftArrowDisabled,\n isRightArrowDisabled: _isRightArrowDisabled,\n getMonthHeaderLabel,\n getYearHeaderLabel,\n isFocusable = false,\n ...otherProps\n }: CalendarManagerProps,\n ref: React.ForwardedRef<CalendarManagerRef>\n) => {\n // =============================================================================\n // CONST, STATE, REF\n // =============================================================================\n // the current visible date in month/year views and header\n const [calendarDate, setCalendarDate] = useState<Dayjs>(\n DateHelper.toDayjs(initialCalendarDate)\n );\n // the selected date in month/year views and the current visible date in day view\n const [viewCalendarDate, setViewCalendarDate] = useState<Dayjs>(\n DateHelper.toDayjs(initialCalendarDate)\n );\n const [currentView, setCurrentView] = useState<View>(\"default\");\n\n const doneButtonRef = useRef<HTMLButtonElement>(null);\n const cancelButtonRef = useRef<HTMLButtonElement>(null);\n const containerRef = useRef<HTMLDivElement>(null);\n const yearDropdownRef = useRef<HTMLButtonElement>(null);\n\n // =============================================================================\n // EFFECTS\n // =============================================================================\n useImperativeHandle(ref, () => {\n return {\n defaultView() {\n setCurrentView(\"default\");\n },\n resetView() {\n const date = DateHelper.toDayjs(initialCalendarDate);\n setCalendarDate(date);\n setViewCalendarDate(date);\n\n setCurrentView(\"default\");\n },\n setCalendarDate(value?: string) {\n const date = DateHelper.toDayjs(value);\n setCalendarDate(date);\n setViewCalendarDate(date);\n },\n };\n });\n\n useEffect(() => {\n const date = DateHelper.toDayjs(initialCalendarDate);\n setCalendarDate(date);\n setViewCalendarDate(date);\n }, [initialCalendarDate]);\n\n useEffect(() => {\n performOnCalendarDateChange(viewCalendarDate);\n // more accurate than calendarDate since it accounts for selection state\n // in month/year views\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [viewCalendarDate]);\n\n // =============================================================================\n // EVENT HANDLERS\n // =============================================================================\n const handleMonthDropdownClick = () => {\n if (currentView !== \"month-options\") {\n setCurrentView(\"month-options\");\n\n // Maintain focus when selecting month dropdown\n containerRef.current?.focus();\n } else {\n setCurrentView(\"default\");\n setCalendarDate(viewCalendarDate);\n }\n };\n\n const handleMonthDropdownKeydown = (\n event: React.KeyboardEvent<HTMLButtonElement>\n ) => {\n if (event.key === \"Enter\" || event.key === \" \") {\n event.preventDefault();\n handleMonthDropdownClick();\n yearDropdownRef.current?.focus(); // Focus on year dropdown after month selection\n }\n\n // Up and Down arrow keys will change the month\n if (event.key === \"ArrowUp\" || event.key === \"ArrowDown\") {\n event.preventDefault();\n const nextDate =\n event.key === \"ArrowUp\"\n ? calendarDate.subtract(1, \"month\")\n : calendarDate.add(1, \"month\");\n\n if (\n !CalendarHelper.isWithinRange(\n nextDate,\n minDate ? dayjs(minDate) : undefined,\n maxDate ? dayjs(maxDate) : undefined,\n \"month\"\n )\n )\n return;\n setCalendarDate(nextDate);\n\n if (currentView === \"default\") {\n setViewCalendarDate(nextDate);\n }\n }\n };\n\n const handleYearDropdownClick = () => {\n /**\n * If the view is in the month options view,\n * then clicking will send the view back to\n * default\n */\n if (currentView !== \"default\") {\n setCurrentView(\"default\");\n setCalendarDate(viewCalendarDate);\n } else {\n setCurrentView(\"year-options\");\n }\n };\n\n const handleYearDropdownKeydown = (\n event: React.KeyboardEvent<HTMLButtonElement>\n ) => {\n if (event.key === \"Enter\" || event.key === \" \") {\n event.preventDefault();\n handleYearDropdownClick();\n }\n\n // Up and Down arrow keys will change the year\n if (event.key === \"ArrowUp\" || event.key === \"ArrowDown\") {\n event.preventDefault();\n const isYearView = currentView === \"year-options\";\n let nextDate: Dayjs;\n\n if (isYearView) {\n // In year options view, change decade\n nextDate =\n event.key === \"ArrowUp\"\n ? calendarDate.subtract(10, \"year\")\n : calendarDate.add(10, \"year\");\n } else {\n // In default view, change year\n nextDate =\n event.key === \"ArrowUp\"\n ? calendarDate.subtract(1, \"year\")\n : calendarDate.add(1, \"year\");\n }\n\n if (\n !CalendarHelper.isWithinRange(\n nextDate,\n minDate ? dayjs(minDate) : undefined,\n maxDate ? dayjs(maxDate) : undefined,\n \"year\"\n )\n )\n return;\n\n setCalendarDate(nextDate);\n\n if (currentView === \"default\") {\n setViewCalendarDate(nextDate);\n }\n }\n };\n\n const handleLeftArrowClick = () => {\n // Maintain focus as button could become disabled\n containerRef.current?.focus();\n\n const nextDate = getLeftArrowDate\n ? getLeftArrowDate(calendarDate)\n : calendarDate.subtract(1, \"month\");\n\n switch (currentView) {\n case \"default\":\n setViewCalendarDate(nextDate);\n setCalendarDate(nextDate);\n break;\n case \"month-options\":\n setCalendarDate((date) => date.subtract(1, \"year\"));\n break;\n case \"year-options\":\n setCalendarDate((date) => date.subtract(10, \"year\"));\n break;\n }\n };\n\n const handleRightArrowClick = () => {\n // Maintain focus as button could become disabled\n containerRef.current?.focus();\n\n const nextDate = getRightArrowDate\n ? getRightArrowDate(calendarDate)\n : calendarDate.add(1, \"month\");\n\n switch (currentView) {\n case \"default\":\n setViewCalendarDate(nextDate);\n setCalendarDate(nextDate);\n break;\n case \"month-options\":\n setCalendarDate((date) => date.add(1, \"year\"));\n break;\n case \"year-options\":\n setCalendarDate((date) => date.add(10, \"year\"));\n break;\n }\n };\n\n const handleMonthYearSelect = (value: Dayjs) => {\n setCalendarDate(value);\n setViewCalendarDate(value);\n\n if (!withButton) {\n setCurrentView(\"default\");\n }\n };\n\n const handleCancelButton = () => {\n const initialValue = DateHelper.toDayjs(initialCalendarDate);\n setCalendarDate(initialValue);\n setViewCalendarDate(initialValue);\n\n if (currentView === \"default\") {\n performOnDismissHandler(\"reset\");\n } else {\n setCurrentView(\"default\");\n }\n };\n\n const handleDoneButton = (isDisabled: boolean | undefined) => {\n if (isDisabled) return;\n\n setCalendarDate(viewCalendarDate);\n\n if (currentView === \"default\") {\n performOnDismissHandler(\"confirmed\");\n } else {\n setCurrentView(\"default\");\n }\n };\n\n // =============================================================================\n // HELPER FUNCTIONS\n // =============================================================================\n const performOnCalendarDateChange = (date: Dayjs) => {\n if (onCalendarDateChange) {\n onCalendarDateChange(date);\n }\n };\n\n const performOnDismissHandler = (action: CalendarAction) => {\n if (onDismiss) {\n onDismiss(action);\n }\n };\n\n const isLeftArrowDisabled = () => {\n if (!minDate || allowDisabledSelection) {\n return false;\n }\n\n const min = dayjs(minDate);\n if (currentView === \"month-options\") {\n return !CalendarHelper.isPreviousYearWithinRange(calendarDate, min);\n } else if (currentView === \"year-options\") {\n return !CalendarHelper.isPreviousDecadeWithinRange(\n calendarDate,\n min\n );\n } else {\n if (_isLeftArrowDisabled) {\n return _isLeftArrowDisabled(calendarDate);\n }\n return !CalendarHelper.isPreviousMonthWithinRange(\n calendarDate,\n min\n );\n }\n };\n\n const isRightArrowDisabled = () => {\n if (!maxDate || allowDisabledSelection) {\n return false;\n }\n\n const max = dayjs(maxDate);\n if (currentView === \"month-options\") {\n return !CalendarHelper.isNextYearWithinRange(calendarDate, max);\n } else if (currentView === \"year-options\") {\n return !CalendarHelper.isNextDecadeWithinRange(calendarDate, max);\n } else {\n if (_isRightArrowDisabled) {\n return _isRightArrowDisabled(calendarDate);\n }\n return !CalendarHelper.isNextMonthWithinRange(calendarDate, max);\n }\n };\n\n // =============================================================================\n // RENDER FUNCTIONS\n // =============================================================================\n\n const getYearHeaderText = (): string => {\n if (currentView === \"year-options\") {\n const { beginDecade, endDecade } =\n CalendarHelper.getStartEndDecade(calendarDate);\n\n return `${beginDecade} to ${endDecade}`;\n } else {\n return getYearHeaderLabel\n ? getYearHeaderLabel(calendarDate)\n : calendarDate.format(\"YYYY\");\n }\n };\n\n const renderDropdownButtons = () => {\n const monthLabel = getMonthHeaderLabel\n ? getMonthHeaderLabel(calendarDate)\n : calendarDate.format(\"MMM\");\n\n const fullMonthLabel = dayjs(monthLabel, \"MMM\").format(\"MMMM\");\n\n const yearLabel = getYearHeaderText();\n const viewToYearLabel: Record<View, string> = {\n \"month-options\": `${yearLabel}, Close month selection`,\n \"year-options\": `${yearLabel}, Close year selection`,\n default: `${yearLabel}, Select year`,\n };\n\n return (\n <>\n <button\n className={clsx(\n styles.dropdownButton,\n currentView !== \"default\" && styles.hidden\n )}\n aria-label={`${fullMonthLabel}, Select month`}\n type=\"button\"\n id=\"month-dropdown\"\n onClick={handleMonthDropdownClick}\n onKeyDown={handleMonthDropdownKeydown}\n tabIndex={isFocusable ? 0 : -1}\n >\n <span className={styles.dropdownText}>{monthLabel}</span>\n <ChevronDownIcon\n className={clsx(\n styles.icon,\n styles.iconChevronDown,\n currentView === \"month-options\" &&\n styles.iconChevronDownExpanded\n )}\n />\n </button>\n <button\n ref={yearDropdownRef}\n className={styles.dropdownButton}\n aria-label={viewToYearLabel[currentView]}\n type=\"button\"\n id=\"year-dropdown\"\n onClick={handleYearDropdownClick}\n onKeyDown={handleYearDropdownKeydown}\n tabIndex={isFocusable ? 0 : -1}\n >\n <span className={styles.dropdownText}>{yearLabel}</span>\n <ChevronDownIcon\n className={clsx(\n styles.icon,\n styles.iconChevronDown,\n currentView !== \"default\" &&\n styles.iconChevronDownExpanded\n )}\n />\n </button>\n </>\n );\n };\n\n const renderOptionsOverlay = () => {\n switch (currentView) {\n case \"month-options\":\n return (\n <InternalCalendarMonth\n calendarDate={calendarDate}\n currentFocus={currentFocus}\n minDate={minDate}\n maxDate={maxDate}\n selectedStartDate={selectedStartDate}\n selectedEndDate={selectedEndDate}\n viewCalendarDate={viewCalendarDate}\n isNewSelection={!!selectWithinRange}\n onMonthSelect={handleMonthYearSelect}\n allowDisabledSelection={allowDisabledSelection}\n />\n );\n case \"year-options\":\n return (\n <InternalCalendarYear\n setCalendarDate={setCalendarDate}\n calendarDate={calendarDate}\n currentFocus={currentFocus}\n minDate={minDate}\n maxDate={maxDate}\n selectedStartDate={selectedStartDate}\n selectedEndDate={selectedEndDate}\n viewCalendarDate={viewCalendarDate}\n isNewSelection={!!selectWithinRange}\n onYearSelect={handleMonthYearSelect}\n allowDisabledSelection={allowDisabledSelection}\n />\n );\n default:\n return null;\n }\n };\n\n const renderHeader = () => {\n const viewToSelection: Record<View, string> = {\n \"month-options\": \"year\",\n \"year-options\": \"decade\",\n default: \"month\",\n };\n\n const selection = viewToSelection[currentView];\n\n return (\n <div\n className={styles.header}\n data-id=\"calendar-header\"\n data-testid=\"calendar-header\"\n >\n <div className={styles.headerInputDropdown}>\n {renderDropdownButtons()}\n </div>\n <div className={styles.headerArrows}>\n <ClickableIcon\n className={styles.headerArrowButton}\n aria-label={`Previous ${selection}`}\n data-testid=\"left-arrow-btn\"\n disabled={isLeftArrowDisabled()}\n focusHighlight={false}\n focusOutline=\"browser\"\n onClick={handleLeftArrowClick}\n tabIndex={isFocusable ? 0 : -1}\n >\n <ChevronLeftIcon className={styles.icon} />\n </ClickableIcon>\n <ClickableIcon\n className={styles.headerArrowButton}\n aria-label={`Next ${selection}`}\n data-testid=\"right-arrow-btn\"\n disabled={isRightArrowDisabled()}\n focusHighlight={false}\n focusOutline=\"browser\"\n onClick={handleRightArrowClick}\n tabIndex={isFocusable ? 0 : -1}\n >\n <ChevronRightIcon className={styles.icon} />\n </ClickableIcon>\n </div>\n </div>\n );\n };\n\n const renderActionButtons = () => {\n if (!withButton) return;\n\n const isDayView = currentView === \"default\";\n\n const disabled = !isDayView ? false : doneButtonDisabled;\n\n return (\n <div className={styles.actionButtonSection}>\n <Button\n className={styles.actionButton}\n ref={cancelButtonRef}\n data-testid=\"cancel-button\"\n styleType=\"light\"\n type=\"button\"\n onClick={handleCancelButton}\n sizeType=\"small\"\n >\n Cancel\n </Button>\n <Button\n className={styles.actionButton}\n data-testid=\"done-button\"\n ref={doneButtonRef}\n type=\"button\"\n onClick={() => handleDoneButton(disabled)}\n disabled={disabled}\n sizeType=\"small\"\n >\n Done\n </Button>\n </div>\n );\n };\n\n const renderViews = () => {\n const defaultView =\n typeof children === \"function\"\n ? children({ calendarDate: viewCalendarDate, currentView })\n : children;\n\n if (dynamicHeight) {\n return (\n <>\n {currentView === \"default\" && defaultView}\n {renderOptionsOverlay()}\n </>\n );\n } else {\n const isDefaultView = currentView === \"default\";\n return (\n // Prevent interaction with the default view when options are open\n <>\n <div\n className={styles.defaultView}\n inert={inertValue(!isDefaultView)}\n >\n {defaultView}\n </div>\n <div\n className={clsx(\n styles.optionsOverlay,\n isDefaultView && styles.hidden\n )}\n >\n {renderOptionsOverlay()}\n </div>\n </>\n );\n }\n };\n\n return (\n <div\n className={styles.container}\n ref={containerRef}\n data-id=\"calendar-container\"\n data-testid=\"calendar-container\"\n aria-label={viewCalendarDate.format(\"MMMM, YYYY\")}\n role=\"group\"\n {...otherProps}\n >\n {showNavigationHeader && renderHeader()}\n <div className={styles.toggleZone} data-testid=\"toggle-zone\">\n {renderViews()}\n </div>\n {renderActionButtons()}\n </div>\n );\n};\n\nexport const CalendarManager = React.forwardRef(Component);\n"],"names":["CalendarManager","React","forwardRef","_a","ref","children","initialCalendarDate","minDate","maxDate","currentFocus","selectedStartDate","selectedEndDate","selectWithinRange","dynamicHeight","allowDisabledSelection","onCalendarDateChange","withButton","doneButtonDisabled","onDismiss","showNavigationHeader","getLeftArrowDate","getRightArrowDate","isLeftArrowDisabled","_isLeftArrowDisabled","isRightArrowDisabled","_isRightArrowDisabled","getMonthHeaderLabel","getYearHeaderLabel","isFocusable","otherProps","__rest","calendarDate","setCalendarDate","useState","DateHelper","toDayjs","viewCalendarDate","setViewCalendarDate","currentView","setCurrentView","doneButtonRef","useRef","cancelButtonRef","containerRef","yearDropdownRef","useImperativeHandle","defaultView","resetView","date","value","useEffect","performOnCalendarDateChange","handleMonthDropdownClick","current","focus","handleMonthDropdownKeydown","event","key","preventDefault","nextDate","subtract","add","CalendarHelper","isWithinRange","dayjs","undefined","handleYearDropdownClick","handleYearDropdownKeydown","handleLeftArrowClick","handleRightArrowClick","handleMonthYearSelect","handleCancelButton","initialValue","performOnDismissHandler","action","min","isPreviousYearWithinRange","isPreviousDecadeWithinRange","isPreviousMonthWithinRange","max","isNextYearWithinRange","isNextDecadeWithinRange","isNextMonthWithinRange","renderDropdownButtons","monthLabel","format","fullMonthLabel","yearLabel","beginDecade","endDecade","getStartEndDecade","getYearHeaderText","viewToYearLabel","default","_jsxs","_Fragment","className","clsx","styles.dropdownButton","styles.hidden","type","id","onClick","onKeyDown","tabIndex","_jsx","styles.dropdownText","ChevronDownIcon","styles.icon","styles.iconChevronDown","styles.iconChevronDownExpanded","renderOptionsOverlay","InternalCalendarMonth","isNewSelection","onMonthSelect","InternalCalendarYear","onYearSelect","styles.container","role","selection","styles.header","styles.headerInputDropdown","styles.headerArrows","ClickableIcon","styles.headerArrowButton","disabled","focusHighlight","focusOutline","ChevronLeftIcon","ChevronRightIcon","renderHeader","styles.toggleZone","isDefaultView","styles.defaultView","inert","inertValue","styles.optionsOverlay","renderViews","styles.actionButtonSection","Button","styles.actionButton","styleType","sizeType","renderActionButtons"],"mappings":"i1BAuBA,MAukBaA,OAAkBC,QAAMC,YAvkBnB,CACdC,EA2BAC,SA3BAC,SACIA,EAAQC,oBACRA,EAAmBC,QACnBA,EAAOC,QACPA,EAAOC,aACPA,EAAYC,kBACZA,EAAiBC,gBACjBA,EAAeC,kBACfA,EAAiBC,cACjBA,GAAgB,EAAKC,uBACrBA,EAAsBC,qBACtBA,EAAoBC,WAEpBA,EAAUC,mBACVA,EAAkBC,UAClBA,EAASC,qBAETA,GAAuB,EAAIC,iBAC3BA,EAAgBC,kBAChBA,EACAC,oBAAqBC,EACrBC,qBAAsBC,EAAqBC,oBAC3CA,EAAmBC,mBACnBA,EAAkBC,YAClBA,GAAc,GAAKzB,EAChB0B,EAAUC,EAAAA,OAAA3B,EAzBjB,CAAA,WAAA,sBAAA,UAAA,UAAA,eAAA,oBAAA,kBAAA,oBAAA,gBAAA,yBAAA,uBAAA,aAAA,qBAAA,YAAA,uBAAA,mBAAA,oBAAA,sBAAA,uBAAA,sBAAA,qBAAA,gBAiCA,MAAO4B,EAAcC,GAAmBC,EAAAA,SACpCC,aAAWC,QAAQ7B,KAGhB8B,EAAkBC,GAAuBJ,EAAAA,SAC5CC,aAAWC,QAAQ7B,KAEhBgC,EAAaC,GAAkBN,EAAAA,SAAe,WAE/CO,EAAgBC,EAAAA,OAA0B,MAC1CC,EAAkBD,EAAAA,OAA0B,MAC5CE,EAAeF,EAAAA,OAAuB,MACtCG,EAAkBH,EAAAA,OAA0B,MAKlDI,EAAAA,oBAAoBzC,GAAK,KACd,CACH,WAAA0C,GACIP,EAAe,UACnB,EACA,SAAAQ,GACI,MAAMC,EAAOd,EAAAA,WAAWC,QAAQ7B,GAChC0B,EAAgBgB,GAChBX,EAAoBW,GAEpBT,EAAe,UACnB,EACA,eAAAP,CAAgBiB,GACZ,MAAMD,EAAOd,EAAAA,WAAWC,QAAQc,GAChCjB,EAAgBgB,GAChBX,EAAoBW,EACxB,MAIRE,EAAAA,WAAU,KACN,MAAMF,EAAOd,EAAAA,WAAWC,QAAQ7B,GAChC0B,EAAgBgB,GAChBX,EAAoBW,EAAK,GAC1B,CAAC1C,IAEJ4C,EAAAA,WAAU,KACNC,GAA4Bf,EAAiB,GAI9C,CAACA,IAKJ,MAAMgB,EAA2B,WACT,kBAAhBd,GACAC,EAAe,iBAGK,QAApBpC,EAAAwC,EAAaU,eAAO,IAAAlD,GAAAA,EAAEmD,UAEtBf,EAAe,WACfP,EAAgBI,GACpB,EAGEmB,EACFC,UASA,GAPkB,UAAdA,EAAMC,KAAiC,MAAdD,EAAMC,MAC/BD,EAAME,iBACNN,IACuB,QAAvBjD,EAAAyC,EAAgBS,eAAO,IAAAlD,GAAAA,EAAEmD,SAIX,YAAdE,EAAMC,KAAmC,cAAdD,EAAMC,IAAqB,CACtDD,EAAME,iBACN,MAAMC,EACY,YAAdH,EAAMC,IACA1B,EAAa6B,SAAS,EAAG,SACzB7B,EAAa8B,IAAI,EAAG,SAE9B,IACKC,EAAAA,eAAeC,cACZJ,EACApD,EAAUyD,EAAAA,QAAMzD,QAAW0D,EAC3BzD,EAAUwD,EAAAA,QAAMxD,QAAWyD,EAC3B,SAGJ,OACJjC,EAAgB2B,GAEI,YAAhBrB,GACAD,EAAoBsB,EAE5B,GAGEO,EAA0B,KAMR,YAAhB5B,GACAC,EAAe,WACfP,EAAgBI,IAEhBG,EAAe,eACnB,EAGE4B,GACFX,IAQA,GANkB,UAAdA,EAAMC,KAAiC,MAAdD,EAAMC,MAC/BD,EAAME,iBACNQ,KAIc,YAAdV,EAAMC,KAAmC,cAAdD,EAAMC,IAAqB,CACtDD,EAAME,iBAEN,IAAIC,EAgBJ,GAZIA,EAL+B,iBAAhBrB,EAMG,YAAdkB,EAAMC,IACA1B,EAAa6B,SAAS,GAAI,QAC1B7B,EAAa8B,IAAI,GAAI,QAIb,YAAdL,EAAMC,IACA1B,EAAa6B,SAAS,EAAG,QACzB7B,EAAa8B,IAAI,EAAG,SAI7BC,EAAAA,eAAeC,cACZJ,EACApD,EAAUyD,EAAAA,QAAMzD,QAAW0D,EAC3BzD,EAAUwD,EAAAA,QAAMxD,QAAWyD,EAC3B,QAGJ,OAEJjC,EAAgB2B,GAEI,YAAhBrB,GACAD,EAAoBsB,EAE5B,GAGES,GAAuB,WAEL,QAApBjE,EAAAwC,EAAaU,eAAO,IAAAlD,GAAAA,EAAEmD,QAEtB,MAAMK,EAAWvC,EACXA,EAAiBW,GACjBA,EAAa6B,SAAS,EAAG,SAE/B,OAAQtB,GACJ,IAAK,UACDD,EAAoBsB,GACpB3B,EAAgB2B,GAChB,MACJ,IAAK,gBACD3B,GAAiBgB,GAASA,EAAKY,SAAS,EAAG,UAC3C,MACJ,IAAK,eACD5B,GAAiBgB,GAASA,EAAKY,SAAS,GAAI,YAKlDS,GAAwB,WAEN,QAApBlE,EAAAwC,EAAaU,eAAO,IAAAlD,GAAAA,EAAEmD,QAEtB,MAAMK,EAAWtC,EACXA,EAAkBU,GAClBA,EAAa8B,IAAI,EAAG,SAE1B,OAAQvB,GACJ,IAAK,UACDD,EAAoBsB,GACpB3B,EAAgB2B,GAChB,MACJ,IAAK,gBACD3B,GAAiBgB,GAASA,EAAKa,IAAI,EAAG,UACtC,MACJ,IAAK,eACD7B,GAAiBgB,GAASA,EAAKa,IAAI,GAAI,YAK7CS,GAAyBrB,IAC3BjB,EAAgBiB,GAChBZ,EAAoBY,GAEfjC,GACDuB,EAAe,UACnB,EAGEgC,GAAqB,KACvB,MAAMC,EAAetC,EAAAA,WAAWC,QAAQ7B,GACxC0B,EAAgBwC,GAChBnC,EAAoBmC,GAEA,YAAhBlC,EACAmC,GAAwB,SAExBlC,EAAe,UACnB,EAkBEY,GAA+BH,IAC7BjC,GACAA,EAAqBiC,EACzB,EAGEyB,GAA2BC,IACzBxD,GACAA,EAAUwD,EACd,EAGEpD,GAAsB,KACxB,IAAKf,GAAWO,EACZ,OAAO,EAGX,MAAM6D,EAAMX,EAAAA,QAAMzD,GAClB,MAAoB,kBAAhB+B,GACQwB,EAAAA,eAAec,0BAA0B7C,EAAc4C,GACxC,iBAAhBrC,GACCwB,EAAAA,eAAee,4BACnB9C,EACA4C,GAGApD,EACOA,EAAqBQ,IAExB+B,EAAAA,eAAegB,2BACnB/C,EACA4C,EAER,EAGEnD,GAAuB,KACzB,IAAKhB,GAAWM,EACZ,OAAO,EAGX,MAAMiE,EAAMf,EAAAA,QAAMxD,GAClB,MAAoB,kBAAhB8B,GACQwB,EAAAA,eAAekB,sBAAsBjD,EAAcgD,GACpC,iBAAhBzC,GACCwB,EAAAA,eAAemB,wBAAwBlD,EAAcgD,GAEzDtD,EACOA,EAAsBM,IAEzB+B,EAAAA,eAAeoB,uBAAuBnD,EAAcgD,EAChE,EAoBEI,GAAwB,KAC1B,MAAMC,EAAa1D,EACbA,EAAoBK,GACpBA,EAAasD,OAAO,OAEpBC,EAAiBtB,EAAAA,QAAMoB,EAAY,OAAOC,OAAO,QAEjDE,EApBgB,MACtB,GAAoB,iBAAhBjD,EAAgC,CAChC,MAAMkD,YAAEA,EAAWC,UAAEA,GACjB3B,EAAAA,eAAe4B,kBAAkB3D,GAErC,MAAO,GAAGyD,QAAkBC,GAChC,CACI,OAAO9D,EACDA,EAAmBI,GACnBA,EAAasD,OAAO,OAC9B,EAUkBM,GACZC,EAAwC,CAC1C,gBAAiB,GAAGL,2BACpB,eAAgB,GAAGA,0BACnBM,QAAS,GAAGN,kBAGhB,OACIO,OAAAC,EAAAA,SAAA,CAAA1F,SAAA,CACIyF,EAAAA,KAAA,SAAA,CACIE,UAAWC,UACPC,EAAAA,eACgB,YAAhB5D,GAA6B6D,EAAAA,QAChC,aACW,GAAGb,kBACfc,KAAK,SACLC,GAAG,iBACHC,QAASlD,EACTmD,UAAWhD,EACXiD,SAAU5E,EAAc,eAExB6E,EAAAA,IAAA,OAAA,CAAMT,UAAWU,eAAmBrG,SAAG+E,IACvCqB,EAAAA,IAACE,EAAAA,gBAAe,CACZX,UAAWC,UACPW,EAAAA,KACAC,EAAAA,gBACgB,kBAAhBvE,GACIwE,gCAIhBhB,EAAAA,KAAA,SAAA,CACI1F,IAAKwC,EACLoD,UAAWE,EAAAA,eAAqB,aACpBN,EAAgBtD,GAC5B8D,KAAK,SACLC,GAAG,gBACHC,QAASpC,EACTqC,UAAWpC,GACXqC,SAAU5E,EAAc,KAAMvB,SAAA,CAE9BoG,cAAMT,UAAWU,EAAAA,aAAmBrG,SAAGkF,IACvCkB,EAAAA,IAACE,kBAAe,CACZX,UAAWC,EAAAA,QACPW,EAAAA,KACAC,kBACgB,YAAhBvE,GACIwE,EAAAA,gCAIjB,EAILC,GAAuB,KACzB,OAAQzE,GACJ,IAAK,gBACD,OACImE,MAACO,EAAAA,sBAAqB,CAClBjF,aAAcA,EACdtB,aAAcA,EACdF,QAASA,EACTC,QAASA,EACTE,kBAAmBA,EACnBC,gBAAiBA,EACjByB,iBAAkBA,EAClB6E,iBAAkBrG,EAClBsG,cAAe5C,GACfxD,uBAAwBA,IAGpC,IAAK,eACD,OACI2F,EAAAA,IAACU,EAAAA,qBAAoB,CACjBnF,gBAAiBA,EACjBD,aAAcA,EACdtB,aAAcA,EACdF,QAASA,EACTC,QAASA,EACTE,kBAAmBA,EACnBC,gBAAiBA,EACjByB,iBAAkBA,EAClB6E,iBAAkBrG,EAClBwG,aAAc9C,GACdxD,uBAAwBA,IAGpC,QACI,OAAO,OA4HnB,OACIgF,EAAAA,0BACIE,UAAWqB,EAAAA,UACXjH,IAAKuC,YACG,qBAAoB,cAChB,qBAAoB,aACpBP,EAAiBiD,OAAO,cACpCiC,KAAK,SACDzF,EAAU,CAAAxB,SAAA,CAEbc,GAlIY,MACjB,MAMMoG,EANwC,CAC1C,gBAAiB,OACjB,eAAgB,SAChB1B,QAAS,SAGqBvD,GAElC,OACIwD,EAAAA,KAAA,MAAA,CACIE,UAAWwB,EAAAA,OAAa,UAChB,kBAAiB,cACb,kBAAiBnH,SAAA,CAE7BoG,EAAAA,IAAA,MAAA,CAAKT,UAAWyB,sBAA0BpH,SACrC8E,OAELW,OAAA,MAAA,CAAKE,UAAW0B,EAAAA,aAAmBrH,SAAA,CAC/BoG,EAAAA,IAACkB,iBACG3B,UAAW4B,oBAAwB,aACvB,YAAYL,IAAW,cACvB,iBACZM,SAAUvG,KACVwG,gBAAgB,EAChBC,aAAa,UACbzB,QAASlC,GACToC,SAAU5E,EAAc,GAAI,EAAEvB,SAE9BoG,EAAAA,IAACuB,EAAAA,gBAAe,CAAChC,UAAWY,EAAAA,SAEhCH,EAAAA,IAACkB,EAAAA,cAAa,CACV3B,UAAW4B,oBAAwB,aACvB,QAAQL,IAAW,cACnB,kBACZM,SAAUrG,KACVsG,gBAAgB,EAChBC,aAAa,UACbzB,QAASjC,GACTmC,SAAU5E,EAAc,GAAI,EAAEvB,SAE9BoG,EAAAA,IAACwB,EAAAA,kBAAiBjC,UAAWY,gBAGnC,EAsFmBsB,GACzBzB,EAAAA,IAAA,MAAA,CAAKT,UAAWmC,EAAAA,WAAiB,cAAc,cAAa9H,SAhDhD,MAChB,MAAMyC,EACkB,mBAAbzC,EACDA,EAAS,CAAE0B,aAAcK,EAAkBE,gBAC3CjC,EAEV,GAAIQ,EACA,OACIiF,EAAAA,KAAAC,WAAA,CAAA1F,SAAA,CACqB,YAAhBiC,GAA6BQ,EAC7BiE,QAGN,CACH,MAAMqB,EAAgC,YAAhB9F,EACtB,OAEIwD,EAAAA,KAAAC,EAAAA,SAAA,CAAA1F,SAAA,CACIoG,EAAAA,WACIT,UAAWqC,EAAAA,YACXC,MAAOC,EAAAA,YAAYH,GAAc/H,SAEhCyC,IAEL2D,EAAAA,IAAA,MAAA,CACIT,UAAWC,EAAAA,QACPuC,EAAAA,eACAJ,GAAiBjC,EAAAA,QACpB9F,SAEA0G,SAIjB,GAeS0B,KApFe,MACxB,IAAKzH,EAAY,OAEjB,MAEM6G,KAF4B,YAAhBvF,IAEoBrB,EAEtC,OACI6E,OAAA,MAAA,CAAKE,UAAW0C,EAAAA,oBAA0BrI,SAAA,CACtCoG,MAACkC,EAAAA,QACG3C,UAAW4C,EAAAA,aACXxI,IAAKsC,gBACO,gBACZmG,UAAU,QACVzC,KAAK,SACLE,QAAS/B,GACTuE,SAAS,QAAOzI,SAAA,WAIpBoG,EAAAA,IAACkC,SAAM,CACH3C,UAAW4C,EAAAA,aAAmB,cAClB,cACZxI,IAAKoC,EACL4D,KAAK,SACLE,QAAS,KAAuBuB,IAhQ5C7F,EAAgBI,GAEI,YAAhBE,EACAmC,GAAwB,aAExBlC,EAAe,WA2PkC,EACzCsF,SAAUA,EACViB,SAAS,QAAOzI,SAAA,WAIlB,EAuDL0I,MACC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"standalone-date-input.js","sources":["../../../../src/shared/standalone-date-input/standalone-date-input.tsx"],"sourcesContent":["import clsx from \"clsx\";\nimport dayjs from \"dayjs\";\nimport customParseFormat from \"dayjs/plugin/customParseFormat\";\nimport React, { useEffect, useImperativeHandle, useRef, useState } from \"react\";\n\nimport { DateInputHelper, StringHelper, useStateRef } from \"../../util\";\nimport * as styles from \"./standalone-date-input.styles\";\n\ndayjs.extend(customParseFormat);\n\ntype StartInputNames = [\"start-day\", \"start-month\", \"start-year\"];\ntype EndInputNames = [\"end-day\", \"end-month\", \"end-year\"];\n\nexport type FieldType =\n | StartInputNames[number]\n | EndInputNames[number]\n | \"none\";\n\ninterface Props {\n disabled?: boolean | undefined;\n readOnly?: boolean | undefined;\n hideInputKeyboard?: boolean | undefined;\n names: StartInputNames | EndInputNames;\n value: string | undefined;\n hoverValue?: string | undefined;\n focused: boolean;\n placeholder?: string | undefined;\n label?: string | undefined;\n inputLabels?: string[] | undefined;\n onChange: (value: string) => void;\n onFocus?: ((event: React.FocusEvent) => void) | undefined;\n onBlur?: ((valid: boolean) => void) | undefined;\n}\n\nexport interface StandaloneDateInputRef {\n ref: React.RefObject<HTMLDivElement>;\n resetPlaceholder: () => void;\n resetInput: () => void;\n focusYearRef: () => void;\n}\n\nexport const Component = (\n {\n disabled,\n readOnly,\n names,\n value,\n focused,\n hoverValue,\n placeholder,\n label,\n onChange,\n onFocus,\n onBlur,\n hideInputKeyboard,\n inputLabels = [\"Date\", \"Month\", \"Year\"],\n }: Props,\n ref: React.ForwardedRef<StandaloneDateInputRef>\n) => {\n // =============================================================================\n // CONST, STATE, REF\n // =============================================================================\n const inputMode = hideInputKeyboard ? \"none\" : \"numeric\";\n\n const [dayValue, setDayValue, dayValueRef] = useStateRef<string>(\"\");\n const [monthValue, setMonthValue, monthValueRef] = useStateRef<string>(\"\");\n const [yearValue, setYearValue, yearValueRef] = useStateRef<string>(\"\");\n const [currentFocus, setCurrentFocus] = useState<FieldType>(\"none\");\n const [hidePlaceholder, setHidePlaceholder] = useState<boolean>(false);\n\n const nodeRef = useRef<HTMLDivElement>(null);\n const dayInputRef = useRef<HTMLInputElement>(null);\n const monthInputRef = useRef<HTMLInputElement>(null);\n const yearInputRef = useRef<HTMLInputElement>(null);\n\n const [hoverDayValue, hoverMonthValue, hoverYearValue] =\n parseToInputValues(hoverValue);\n\n // =============================================================================\n // EFFECTS\n // =============================================================================\n useEffect(() => {\n const [day = \"\", month = \"\", year = \"\"] = parseToInputValues(value);\n setDayValue(day);\n setMonthValue(month);\n setYearValue(year);\n\n // re-focus on day input if all 3 inputs get cleared while typing\n if (\n !day &&\n !month &&\n !year &&\n nodeRef.current &&\n nodeRef.current.contains(document.activeElement)\n )\n dayInputRef.current?.focus();\n }, [value]);\n\n useEffect(() => {\n // clear internal focus state\n if (!focused) {\n setCurrentFocus(\"none\");\n }\n\n // ensure at least one input is focused\n if (focused) {\n setHidePlaceholder(true);\n\n if (\n nodeRef.current &&\n !nodeRef.current.contains(document.activeElement)\n ) {\n dayInputRef.current?.focus();\n }\n }\n }, [focused]);\n\n useImperativeHandle(\n ref,\n () => ({\n ref: nodeRef,\n resetPlaceholder() {\n setHidePlaceholder(false);\n },\n resetInput() {\n const [day = \"\", month = \"\", year = \"\"] =\n parseToInputValues(value);\n setDayValue(day);\n setMonthValue(month);\n setYearValue(year);\n },\n focusYearRef() {\n yearInputRef.current?.focus();\n },\n }),\n [setDayValue, setMonthValue, setYearValue, value]\n );\n\n // =============================================================================\n // EVENT HANDLERS\n // =============================================================================\n const handleSectionClick = () => {\n if (disabled || readOnly) {\n return;\n }\n\n setHidePlaceholder(true);\n\n if (\n nodeRef.current &&\n !nodeRef.current.contains(document.activeElement)\n ) {\n dayInputRef.current?.focus();\n }\n };\n\n const handleSectionFocus = (event: React.FocusEvent) => {\n if (disabled) {\n return;\n }\n\n setHidePlaceholder(true);\n\n if (!focused) {\n onFocus?.(event);\n }\n };\n\n const handlePlaceholderClick = (event: React.MouseEvent) => {\n event.preventDefault();\n dayInputRef.current?.focus();\n };\n\n const handleInputFocus = (event: React.FocusEvent<HTMLInputElement>) => {\n event.target.select();\n const targetName = event.target.name as FieldType;\n setCurrentFocus(targetName);\n };\n\n const handleInputBlur = (event: React.FocusEvent<HTMLInputElement>) => {\n const [dayName, monthName, yearName] = names;\n const date = {\n [dayName]: dayValueRef.current,\n [monthName]: monthValueRef.current,\n [yearName]: yearValueRef.current,\n };\n\n const targetName = event.target.name as FieldType;\n const targetValue = date[targetName];\n\n // pad single digits for day and month inputs\n\n const paddedValue =\n targetName !== yearName\n ? StringHelper.padValue(targetValue, true)\n : targetValue;\n\n switch (targetName) {\n case dayName:\n date[dayName] = paddedValue;\n setDayValue(paddedValue);\n break;\n case monthName:\n date[monthName] = paddedValue;\n setMonthValue(paddedValue);\n break;\n case yearName:\n default:\n break;\n }\n\n const value = `${date[yearName]}-${date[monthName]}-${date[dayName]}`;\n const isValid = dayjs(value, \"YYYY-MM-DD\", true).isValid();\n const isEmpty = !date[dayName] && !date[monthName] && !date[yearName];\n const isPadded = targetValue !== paddedValue;\n\n if (isValid && isPadded) {\n onChange(value);\n }\n\n if (nodeRef.current && !nodeRef.current.contains(event.relatedTarget)) {\n // entire field was blurred\n setCurrentFocus(\"none\");\n onBlur?.(isEmpty || isValid);\n }\n };\n\n const handleInputChange = (event: React.ChangeEvent<HTMLInputElement>) => {\n if (hoverValue) {\n // do not modify inputs when selecting date from another source\n return;\n }\n\n const targetName = event.target.name as FieldType;\n const targetValue = event.target.value.replace(/[^0-9]/g, \"\");\n\n const date = {\n day: dayValue,\n month: monthValue,\n year: yearValue,\n };\n\n switch (targetName) {\n case names[0]:\n date.day = targetValue;\n setDayValue(targetValue);\n // auto focus the next input once filled in\n if (targetValue.length === 2) {\n monthInputRef.current?.focus();\n }\n break;\n case names[1]:\n date.month = targetValue;\n setMonthValue(targetValue);\n // auto focus the next input once filled in\n if (targetValue.length === 2) {\n yearInputRef.current?.focus();\n }\n break;\n case names[2]:\n date.year = targetValue;\n setYearValue(targetValue);\n break;\n default:\n break;\n }\n\n if (!date.day && !date.month && !date.year) {\n onChange(\"\");\n return;\n }\n\n const value = `${date.year}-${date.month}-${date.day}`;\n const isValid = dayjs(value, \"YYYY-MM-DD\", true).isValid();\n\n if (isValid) {\n onChange(value);\n }\n };\n\n const handleKeyDown = (event: React.KeyboardEvent<HTMLInputElement>) => {\n /**\n * Allow going to the field before if user presses Backspace\n * on an empty field\n */\n if (event.code === \"Backspace\" || event.key === \"Backspace\") {\n if (currentFocus === names[1] && monthValue.length === 0) {\n dayInputRef.current?.focus();\n }\n\n if (currentFocus === names[2] && yearValue.length === 0) {\n monthInputRef.current?.focus();\n }\n }\n };\n\n // =============================================================================\n // HELPERS\n // =============================================================================\n function parseToInputValues(stringVal: string | undefined) {\n if (!stringVal) {\n return [undefined, undefined, undefined];\n } else {\n const sanitized = DateInputHelper.sanitizeInput(stringVal);\n\n if (!sanitized) {\n return [undefined, undefined, undefined];\n }\n\n const day = dayjs(sanitized, \"YYYY-MM-DD\", true);\n\n return [\n StringHelper.padValue(day.date().toString()),\n StringHelper.padValue((day.month() + 1).toString()),\n day.year().toString(),\n ];\n }\n }\n\n // =============================================================================\n // RENDER FUNCTIONS\n // =============================================================================\n const renderPlaceholder = () => {\n if (value || readOnly || !placeholder) {\n return;\n }\n\n return (\n <div\n className={clsx(\n styles.placeholder,\n disabled && styles.placeholderDisabled,\n hidePlaceholder && styles.placeholderHide\n )}\n onMouseDown={handlePlaceholderClick}\n >\n {placeholder}\n </div>\n );\n };\n\n return (\n <div\n role=\"group\"\n aria-label={label}\n className={styles.inputSection}\n onClick={handleSectionClick}\n onFocus={handleSectionFocus}\n >\n <div ref={nodeRef} className={styles.inputContainer}>\n <span\n className={clsx(\n styles.inputSizerBase,\n styles.dayInputSizer\n )}\n >\n <input\n ref={dayInputRef}\n name={names[0]}\n maxLength={2}\n value={hoverDayValue ?? dayValue}\n onFocus={handleInputFocus}\n onBlur={handleInputBlur}\n onChange={handleInputChange}\n type=\"text\"\n inputMode={inputMode}\n pattern=\"[0-9]{2}\"\n data-testid={`${names[0]}-input`}\n aria-label={inputLabels[0]}\n disabled={disabled}\n readOnly={readOnly}\n tabIndex={readOnly ? -1 : 0}\n autoComplete=\"off\"\n placeholder={\n currentFocus === names[0] && !readOnly ? \"\" : \"DD\"\n }\n className={clsx(\n styles.baseInput,\n !!hoverValue && styles.baseInputHover\n )}\n />\n </span>\n <span\n className={clsx(\n styles.divider,\n !!hoverValue && styles.dividerHover,\n disabled && styles.dividerDisabled,\n !disabled &&\n dayValue.length === 0 &&\n styles.dividerInactive\n )}\n >\n /\n </span>\n <span\n className={clsx(\n styles.inputSizerBase,\n styles.monthInputSizer\n )}\n >\n <input\n ref={monthInputRef}\n name={names[1]}\n maxLength={2}\n value={hoverMonthValue ?? monthValue}\n onFocus={handleInputFocus}\n onBlur={handleInputBlur}\n onChange={handleInputChange}\n onKeyDown={handleKeyDown}\n type=\"text\"\n inputMode={inputMode}\n pattern=\"[0-9]{2}\"\n data-testid={`${names[1]}-input`}\n aria-label={inputLabels[1]}\n disabled={disabled}\n readOnly={readOnly}\n tabIndex={readOnly ? -1 : 0}\n autoComplete=\"off\"\n placeholder={\n currentFocus === names[1] && !readOnly ? \"\" : \"MM\"\n }\n className={clsx(\n styles.baseInput,\n !!hoverValue && styles.baseInputHover\n )}\n />\n </span>\n <span\n className={clsx(\n styles.divider,\n !!hoverValue && styles.dividerHover,\n disabled && styles.dividerDisabled,\n !disabled &&\n monthValue.length === 0 &&\n styles.dividerInactive\n )}\n >\n /\n </span>\n <span\n className={clsx(\n styles.inputSizerBase,\n styles.yearInputSizer\n )}\n >\n <input\n ref={yearInputRef}\n name={names[2]}\n maxLength={4}\n value={hoverYearValue ?? yearValue}\n onFocus={handleInputFocus}\n onBlur={handleInputBlur}\n onChange={handleInputChange}\n onKeyDown={handleKeyDown}\n type=\"text\"\n inputMode={inputMode}\n pattern=\"[0-9]{4}\"\n data-testid={`${names[2]}-input`}\n aria-label={inputLabels[2]}\n disabled={disabled}\n readOnly={readOnly}\n tabIndex={readOnly ? -1 : 0}\n autoComplete=\"off\"\n placeholder={\n currentFocus === names[2] && !readOnly ? \"\" : \"YYYY\"\n }\n className={clsx(\n styles.baseInput,\n !!hoverValue && styles.baseInputHover\n )}\n />\n </span>\n </div>\n {renderPlaceholder()}\n </div>\n );\n};\n\nexport const StandaloneDateInput = React.forwardRef(Component);\n"],"names":["dayjs","extend","customParseFormat","Component","disabled","readOnly","names","value","focused","hoverValue","placeholder","label","onChange","onFocus","onBlur","hideInputKeyboard","inputLabels","ref","inputMode","dayValue","setDayValue","dayValueRef","useStateRef","monthValue","setMonthValue","monthValueRef","yearValue","setYearValue","yearValueRef","currentFocus","setCurrentFocus","useState","hidePlaceholder","setHidePlaceholder","nodeRef","useRef","dayInputRef","monthInputRef","yearInputRef","hoverDayValue","hoverMonthValue","hoverYearValue","parseToInputValues","useEffect","day","month","year","current","contains","document","activeElement","_a","focus","useImperativeHandle","resetPlaceholder","resetInput","focusYearRef","handlePlaceholderClick","event","preventDefault","handleInputFocus","target","select","targetName","name","handleInputBlur","dayName","monthName","yearName","date","targetValue","paddedValue","StringHelper","padValue","isValid","isEmpty","relatedTarget","handleInputChange","replace","length","_b","handleKeyDown","code","key","stringVal","sanitized","DateInputHelper","sanitizeInput","undefined","toString","_jsxs","role","className","styles.inputSection","onClick","children","styles.inputContainer","_jsx","clsx","styles.inputSizerBase","styles.dayInputSizer","maxLength","type","pattern","tabIndex","autoComplete","styles.baseInput","styles.baseInputHover","styles.divider","styles.dividerHover","styles.dividerDisabled","styles.dividerInactive","styles.monthInputSizer","onKeyDown","styles.yearInputSizer","styles.placeholder","styles.placeholderDisabled","styles.placeholderHide","onMouseDown","renderPlaceholder","StandaloneDateInput","React","forwardRef"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"standalone-date-input.js","sources":["../../../../src/shared/standalone-date-input/standalone-date-input.tsx"],"sourcesContent":["import clsx from \"clsx\";\nimport dayjs from \"dayjs\";\nimport customParseFormat from \"dayjs/plugin/customParseFormat\";\nimport React, { useEffect, useImperativeHandle, useRef, useState } from \"react\";\n\nimport { DateInputHelper, StringHelper, useStateRef } from \"../../util\";\nimport * as styles from \"./standalone-date-input.styles\";\n\ndayjs.extend(customParseFormat);\n\ntype StartInputNames = [\"start-day\", \"start-month\", \"start-year\"];\ntype EndInputNames = [\"end-day\", \"end-month\", \"end-year\"];\n\nexport type FieldType =\n | StartInputNames[number]\n | EndInputNames[number]\n | \"none\";\n\ninterface Props {\n disabled?: boolean | undefined;\n readOnly?: boolean | undefined;\n hideInputKeyboard?: boolean | undefined;\n names: StartInputNames | EndInputNames;\n value: string | undefined;\n hoverValue?: string | undefined;\n focused: boolean;\n placeholder?: string | undefined;\n label?: string | undefined;\n inputLabels?: string[] | undefined;\n onChange: (value: string) => void;\n onFocus?: ((event: React.FocusEvent) => void) | undefined;\n onBlur?: ((valid: boolean) => void) | undefined;\n}\n\nexport interface StandaloneDateInputRef {\n ref: React.RefObject<HTMLDivElement>;\n resetPlaceholder: () => void;\n resetInput: () => void;\n focusYearRef: () => void;\n}\n\nexport const Component = (\n {\n disabled,\n readOnly,\n names,\n value,\n focused,\n hoverValue,\n placeholder,\n label,\n onChange,\n onFocus,\n onBlur,\n hideInputKeyboard,\n inputLabels = [\"Date\", \"Month\", \"Year\"],\n }: Props,\n ref: React.ForwardedRef<StandaloneDateInputRef>\n) => {\n // =============================================================================\n // CONST, STATE, REF\n // =============================================================================\n const inputMode = hideInputKeyboard ? \"none\" : \"numeric\";\n\n const [dayValue, setDayValue, dayValueRef] = useStateRef<string>(\"\");\n const [monthValue, setMonthValue, monthValueRef] = useStateRef<string>(\"\");\n const [yearValue, setYearValue, yearValueRef] = useStateRef<string>(\"\");\n const [currentFocus, setCurrentFocus] = useState<FieldType>(\"none\");\n const [hidePlaceholder, setHidePlaceholder] = useState<boolean>(false);\n\n const nodeRef = useRef<HTMLDivElement>(null);\n const dayInputRef = useRef<HTMLInputElement>(null);\n const monthInputRef = useRef<HTMLInputElement>(null);\n const yearInputRef = useRef<HTMLInputElement>(null);\n\n const [hoverDayValue, hoverMonthValue, hoverYearValue] =\n parseToInputValues(hoverValue);\n\n // =============================================================================\n // EFFECTS\n // =============================================================================\n useEffect(() => {\n const [day = \"\", month = \"\", year = \"\"] = parseToInputValues(value);\n setDayValue(day);\n setMonthValue(month);\n setYearValue(year);\n\n // re-focus on day input if all 3 inputs get cleared while typing\n if (\n !day &&\n !month &&\n !year &&\n nodeRef.current &&\n nodeRef.current.contains(document.activeElement)\n )\n dayInputRef.current?.focus();\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [value]);\n\n useEffect(() => {\n // clear internal focus state\n if (!focused) {\n setCurrentFocus(\"none\");\n }\n\n // ensure at least one input is focused\n if (focused) {\n setHidePlaceholder(true);\n\n if (\n nodeRef.current &&\n !nodeRef.current.contains(document.activeElement)\n ) {\n dayInputRef.current?.focus();\n }\n }\n }, [focused]);\n\n useImperativeHandle(\n ref,\n () => ({\n ref: nodeRef,\n resetPlaceholder() {\n setHidePlaceholder(false);\n },\n resetInput() {\n const [day = \"\", month = \"\", year = \"\"] =\n parseToInputValues(value);\n setDayValue(day);\n setMonthValue(month);\n setYearValue(year);\n },\n focusYearRef() {\n yearInputRef.current?.focus();\n },\n }),\n [setDayValue, setMonthValue, setYearValue, value]\n );\n\n // =============================================================================\n // EVENT HANDLERS\n // =============================================================================\n const handleSectionClick = () => {\n if (disabled || readOnly) {\n return;\n }\n\n setHidePlaceholder(true);\n\n if (\n nodeRef.current &&\n !nodeRef.current.contains(document.activeElement)\n ) {\n dayInputRef.current?.focus();\n }\n };\n\n const handleSectionFocus = (event: React.FocusEvent) => {\n if (disabled) {\n return;\n }\n\n setHidePlaceholder(true);\n\n if (!focused) {\n onFocus?.(event);\n }\n };\n\n const handlePlaceholderClick = (event: React.MouseEvent) => {\n event.preventDefault();\n dayInputRef.current?.focus();\n };\n\n const handleInputFocus = (event: React.FocusEvent<HTMLInputElement>) => {\n event.target.select();\n const targetName = event.target.name as FieldType;\n setCurrentFocus(targetName);\n };\n\n const handleInputBlur = (event: React.FocusEvent<HTMLInputElement>) => {\n const [dayName, monthName, yearName] = names;\n const date = {\n [dayName]: dayValueRef.current,\n [monthName]: monthValueRef.current,\n [yearName]: yearValueRef.current,\n };\n\n const targetName = event.target.name as FieldType;\n const targetValue = date[targetName];\n\n // pad single digits for day and month inputs\n\n const paddedValue =\n targetName !== yearName\n ? StringHelper.padValue(targetValue, true)\n : targetValue;\n\n switch (targetName) {\n case dayName:\n date[dayName] = paddedValue;\n setDayValue(paddedValue);\n break;\n case monthName:\n date[monthName] = paddedValue;\n setMonthValue(paddedValue);\n break;\n case yearName:\n default:\n break;\n }\n\n const value = `${date[yearName]}-${date[monthName]}-${date[dayName]}`;\n const isValid = dayjs(value, \"YYYY-MM-DD\", true).isValid();\n const isEmpty = !date[dayName] && !date[monthName] && !date[yearName];\n const isPadded = targetValue !== paddedValue;\n\n if (isValid && isPadded) {\n onChange(value);\n }\n\n if (nodeRef.current && !nodeRef.current.contains(event.relatedTarget)) {\n // entire field was blurred\n setCurrentFocus(\"none\");\n onBlur?.(isEmpty || isValid);\n }\n };\n\n const handleInputChange = (event: React.ChangeEvent<HTMLInputElement>) => {\n if (hoverValue) {\n // do not modify inputs when selecting date from another source\n return;\n }\n\n const targetName = event.target.name as FieldType;\n const targetValue = event.target.value.replace(/[^0-9]/g, \"\");\n\n const date = {\n day: dayValue,\n month: monthValue,\n year: yearValue,\n };\n\n switch (targetName) {\n case names[0]:\n date.day = targetValue;\n setDayValue(targetValue);\n // auto focus the next input once filled in\n if (targetValue.length === 2) {\n monthInputRef.current?.focus();\n }\n break;\n case names[1]:\n date.month = targetValue;\n setMonthValue(targetValue);\n // auto focus the next input once filled in\n if (targetValue.length === 2) {\n yearInputRef.current?.focus();\n }\n break;\n case names[2]:\n date.year = targetValue;\n setYearValue(targetValue);\n break;\n default:\n break;\n }\n\n if (!date.day && !date.month && !date.year) {\n onChange(\"\");\n return;\n }\n\n const value = `${date.year}-${date.month}-${date.day}`;\n const isValid = dayjs(value, \"YYYY-MM-DD\", true).isValid();\n\n if (isValid) {\n onChange(value);\n }\n };\n\n const handleKeyDown = (event: React.KeyboardEvent<HTMLInputElement>) => {\n /**\n * Allow going to the field before if user presses Backspace\n * on an empty field\n */\n if (event.code === \"Backspace\" || event.key === \"Backspace\") {\n if (currentFocus === names[1] && monthValue.length === 0) {\n dayInputRef.current?.focus();\n }\n\n if (currentFocus === names[2] && yearValue.length === 0) {\n monthInputRef.current?.focus();\n }\n }\n };\n\n // =============================================================================\n // HELPERS\n // =============================================================================\n function parseToInputValues(stringVal: string | undefined) {\n if (!stringVal) {\n return [undefined, undefined, undefined];\n } else {\n const sanitized = DateInputHelper.sanitizeInput(stringVal);\n\n if (!sanitized) {\n return [undefined, undefined, undefined];\n }\n\n const day = dayjs(sanitized, \"YYYY-MM-DD\", true);\n\n return [\n StringHelper.padValue(day.date().toString()),\n StringHelper.padValue((day.month() + 1).toString()),\n day.year().toString(),\n ];\n }\n }\n\n // =============================================================================\n // RENDER FUNCTIONS\n // =============================================================================\n const renderPlaceholder = () => {\n if (value || readOnly || !placeholder) {\n return;\n }\n\n return (\n <div\n className={clsx(\n styles.placeholder,\n disabled && styles.placeholderDisabled,\n hidePlaceholder && styles.placeholderHide\n )}\n onMouseDown={handlePlaceholderClick}\n >\n {placeholder}\n </div>\n );\n };\n\n return (\n <div\n role=\"group\"\n aria-label={label}\n className={styles.inputSection}\n onClick={handleSectionClick}\n onFocus={handleSectionFocus}\n >\n <div ref={nodeRef} className={styles.inputContainer}>\n <span\n className={clsx(\n styles.inputSizerBase,\n styles.dayInputSizer\n )}\n >\n <input\n ref={dayInputRef}\n name={names[0]}\n maxLength={2}\n value={hoverDayValue ?? dayValue}\n onFocus={handleInputFocus}\n onBlur={handleInputBlur}\n onChange={handleInputChange}\n type=\"text\"\n inputMode={inputMode}\n pattern=\"[0-9]{2}\"\n data-testid={`${names[0]}-input`}\n aria-label={inputLabels[0]}\n disabled={disabled}\n readOnly={readOnly}\n tabIndex={readOnly ? -1 : 0}\n autoComplete=\"off\"\n placeholder={\n currentFocus === names[0] && !readOnly ? \"\" : \"DD\"\n }\n className={clsx(\n styles.baseInput,\n !!hoverValue && styles.baseInputHover\n )}\n />\n </span>\n <span\n className={clsx(\n styles.divider,\n !!hoverValue && styles.dividerHover,\n disabled && styles.dividerDisabled,\n !disabled &&\n dayValue.length === 0 &&\n styles.dividerInactive\n )}\n >\n /\n </span>\n <span\n className={clsx(\n styles.inputSizerBase,\n styles.monthInputSizer\n )}\n >\n <input\n ref={monthInputRef}\n name={names[1]}\n maxLength={2}\n value={hoverMonthValue ?? monthValue}\n onFocus={handleInputFocus}\n onBlur={handleInputBlur}\n onChange={handleInputChange}\n onKeyDown={handleKeyDown}\n type=\"text\"\n inputMode={inputMode}\n pattern=\"[0-9]{2}\"\n data-testid={`${names[1]}-input`}\n aria-label={inputLabels[1]}\n disabled={disabled}\n readOnly={readOnly}\n tabIndex={readOnly ? -1 : 0}\n autoComplete=\"off\"\n placeholder={\n currentFocus === names[1] && !readOnly ? \"\" : \"MM\"\n }\n className={clsx(\n styles.baseInput,\n !!hoverValue && styles.baseInputHover\n )}\n />\n </span>\n <span\n className={clsx(\n styles.divider,\n !!hoverValue && styles.dividerHover,\n disabled && styles.dividerDisabled,\n !disabled &&\n monthValue.length === 0 &&\n styles.dividerInactive\n )}\n >\n /\n </span>\n <span\n className={clsx(\n styles.inputSizerBase,\n styles.yearInputSizer\n )}\n >\n <input\n ref={yearInputRef}\n name={names[2]}\n maxLength={4}\n value={hoverYearValue ?? yearValue}\n onFocus={handleInputFocus}\n onBlur={handleInputBlur}\n onChange={handleInputChange}\n onKeyDown={handleKeyDown}\n type=\"text\"\n inputMode={inputMode}\n pattern=\"[0-9]{4}\"\n data-testid={`${names[2]}-input`}\n aria-label={inputLabels[2]}\n disabled={disabled}\n readOnly={readOnly}\n tabIndex={readOnly ? -1 : 0}\n autoComplete=\"off\"\n placeholder={\n currentFocus === names[2] && !readOnly ? \"\" : \"YYYY\"\n }\n className={clsx(\n styles.baseInput,\n !!hoverValue && styles.baseInputHover\n )}\n />\n </span>\n </div>\n {renderPlaceholder()}\n </div>\n );\n};\n\nexport const StandaloneDateInput = React.forwardRef(Component);\n"],"names":["dayjs","extend","customParseFormat","Component","disabled","readOnly","names","value","focused","hoverValue","placeholder","label","onChange","onFocus","onBlur","hideInputKeyboard","inputLabels","ref","inputMode","dayValue","setDayValue","dayValueRef","useStateRef","monthValue","setMonthValue","monthValueRef","yearValue","setYearValue","yearValueRef","currentFocus","setCurrentFocus","useState","hidePlaceholder","setHidePlaceholder","nodeRef","useRef","dayInputRef","monthInputRef","yearInputRef","hoverDayValue","hoverMonthValue","hoverYearValue","parseToInputValues","useEffect","day","month","year","current","contains","document","activeElement","_a","focus","useImperativeHandle","resetPlaceholder","resetInput","focusYearRef","handlePlaceholderClick","event","preventDefault","handleInputFocus","target","select","targetName","name","handleInputBlur","dayName","monthName","yearName","date","targetValue","paddedValue","StringHelper","padValue","isValid","isEmpty","relatedTarget","handleInputChange","replace","length","_b","handleKeyDown","code","key","stringVal","sanitized","DateInputHelper","sanitizeInput","undefined","toString","_jsxs","role","className","styles.inputSection","onClick","children","styles.inputContainer","_jsx","clsx","styles.inputSizerBase","styles.dayInputSizer","maxLength","type","pattern","tabIndex","autoComplete","styles.baseInput","styles.baseInputHover","styles.divider","styles.dividerHover","styles.dividerDisabled","styles.dividerInactive","styles.monthInputSizer","onKeyDown","styles.yearInputSizer","styles.placeholder","styles.placeholderDisabled","styles.placeholderHide","onMouseDown","renderPlaceholder","StandaloneDateInput","React","forwardRef"],"mappings":"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"}
|
package/cjs/theme/types.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";exports.THEME_TYPES=["a11y-playground","bookingsg","careercompass","ccube","imda","lifesg","mylegacy","oneservice","pa","rbs","sgw-digital-lobby","smgs","spf","supportgowhere"];
|
|
1
|
+
"use strict";exports.THEME_TYPES=["a11y-playground","bookingsg","careercompass","ccube","imda","lifesg","mylegacy","oneservice","pa","rbs","sgw-digital-lobby","smgs","spf","supportgowhere","tote-board"];
|
|
2
2
|
//# sourceMappingURL=types.js.map
|
package/cjs/theme/types.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sources":["../../../src/theme/types.ts"],"sourcesContent":["import type { ValueOf } from \"../util/utility-types\";\nimport type {\n Border,\n Breakpoint,\n ComponentToken,\n FontSpec,\n Motion,\n PrimitiveColours,\n Radius,\n SemanticColours,\n Shadow,\n Spacing,\n} from \"./tokens\";\n\n/** All available theme names. */\nexport const THEME_TYPES = [\n \"a11y-playground\",\n \"bookingsg\",\n \"careercompass\",\n \"ccube\",\n \"imda\",\n \"lifesg\",\n \"mylegacy\",\n \"oneservice\",\n \"pa\",\n \"rbs\",\n \"sgw-digital-lobby\",\n \"smgs\",\n \"spf\",\n \"supportgowhere\",\n] as const;\n\n/** Union of all supported theme names. */\nexport type ThemeType = (typeof THEME_TYPES)[number];\n/**\n * Colour mode accepted by `ThemeProvider`.\n * — `\"auto\"` follows OS preference.\n * - `\"light\"` light mode.\n * - `\"dark\"` dark mode.\n */\nexport type ThemeMode = \"light\" | \"dark\" | \"auto\";\n\n/** Resolved colour mode. */\nexport type ResolvedThemeMode = \"light\" | \"dark\";\n\n/** Available typography size presets. */\nexport type FontSize =\n | \"heading-xxl\"\n | \"heading-xl\"\n | \"heading-lg\"\n | \"heading-md\"\n | \"heading-sm\"\n | \"heading-xs\"\n | \"body-baseline\"\n | \"body-md\"\n | \"body-sm\"\n | \"body-xs\"\n | \"form-label\"\n | \"form-description\";\n\n/** Available typography weight presets. */\nexport type FontWeight = \"light\" | \"regular\" | \"semibold\" | \"bold\";\n\n/** Accepted breakpoint CSS variable strings. */\nexport type BreakpointCSSVariableString = ValueOf<typeof Breakpoint>;\n/** Accepted border CSS variable strings. */\nexport type BorderCSSVariableString = ValueOf<typeof Border>;\n/** Accepted component-scoped CSS variable strings. */\nexport type ComponentTokenCSSVariableString =\n | ValueOf<typeof ComponentToken.Animation>\n | ValueOf<typeof ComponentToken.Button>\n | ValueOf<typeof ComponentToken.Footer>\n | ValueOf<typeof ComponentToken.Navbar>;\n/** Accepted font CSS variable strings. */\nexport type FontSpecCSSVariableString = ValueOf<typeof FontSpec>;\n/** Accepted motion CSS variable strings. */\nexport type MotionCSSVariableString = ValueOf<typeof Motion>;\n/** Accepted primitive colour CSS variable strings. */\nexport type PrimitiveColourCSSVariableString = ValueOf<typeof PrimitiveColours>;\n/** Accepted radius CSS variable strings. */\nexport type RadiusCSSVariableString = ValueOf<typeof Radius>;\n/** Accepted semantic colour CSS variable strings. */\nexport type SemanticColourCSSVariableString = ValueOf<typeof SemanticColours>;\n/** Accepted colour CSS variable strings. */\nexport type ColourCSSVariableString =\n | PrimitiveColourCSSVariableString\n | SemanticColourCSSVariableString;\n/** Accepted shadow CSS variable strings. */\nexport type ShadowCSSVariableString = ValueOf<typeof Shadow>;\n/** Accepted spacing and layout CSS variable strings. */\nexport type SpacingCSSVariableString = ValueOf<typeof Spacing>;\n\n/** Union of all design-token CSS variable string literals. */\nexport type CSSVariableString =\n | BreakpointCSSVariableString\n | BorderCSSVariableString\n | ColourCSSVariableString\n | ComponentTokenCSSVariableString\n | FontSpecCSSVariableString\n | MotionCSSVariableString\n | RadiusCSSVariableString\n | ShadowCSSVariableString\n | SpacingCSSVariableString;\n"],"names":[],"mappings":"iCAe2B,CACvB,kBACA,YACA,gBACA,QACA,OACA,SACA,WACA,aACA,KACA,MACA,oBACA,OACA,MACA"}
|
|
1
|
+
{"version":3,"file":"types.js","sources":["../../../src/theme/types.ts"],"sourcesContent":["import type { ValueOf } from \"../util/utility-types\";\nimport type {\n Border,\n Breakpoint,\n ComponentToken,\n FontSpec,\n Motion,\n PrimitiveColours,\n Radius,\n SemanticColours,\n Shadow,\n Spacing,\n} from \"./tokens\";\n\n/** All available theme names. */\nexport const THEME_TYPES = [\n \"a11y-playground\",\n \"bookingsg\",\n \"careercompass\",\n \"ccube\",\n \"imda\",\n \"lifesg\",\n \"mylegacy\",\n \"oneservice\",\n \"pa\",\n \"rbs\",\n \"sgw-digital-lobby\",\n \"smgs\",\n \"spf\",\n \"supportgowhere\",\n \"tote-board\",\n] as const;\n\n/** Union of all supported theme names. */\nexport type ThemeType = (typeof THEME_TYPES)[number];\n/**\n * Colour mode accepted by `ThemeProvider`.\n * — `\"auto\"` follows OS preference.\n * - `\"light\"` light mode.\n * - `\"dark\"` dark mode.\n */\nexport type ThemeMode = \"light\" | \"dark\" | \"auto\";\n\n/** Resolved colour mode. */\nexport type ResolvedThemeMode = \"light\" | \"dark\";\n\n/** Available typography size presets. */\nexport type FontSize =\n | \"heading-xxl\"\n | \"heading-xl\"\n | \"heading-lg\"\n | \"heading-md\"\n | \"heading-sm\"\n | \"heading-xs\"\n | \"body-baseline\"\n | \"body-md\"\n | \"body-sm\"\n | \"body-xs\"\n | \"form-label\"\n | \"form-description\";\n\n/** Available typography weight presets. */\nexport type FontWeight = \"light\" | \"regular\" | \"semibold\" | \"bold\";\n\n/** Accepted breakpoint CSS variable strings. */\nexport type BreakpointCSSVariableString = ValueOf<typeof Breakpoint>;\n/** Accepted border CSS variable strings. */\nexport type BorderCSSVariableString = ValueOf<typeof Border>;\n/** Accepted component-scoped CSS variable strings. */\nexport type ComponentTokenCSSVariableString =\n | ValueOf<typeof ComponentToken.Animation>\n | ValueOf<typeof ComponentToken.Button>\n | ValueOf<typeof ComponentToken.Footer>\n | ValueOf<typeof ComponentToken.Navbar>;\n/** Accepted font CSS variable strings. */\nexport type FontSpecCSSVariableString = ValueOf<typeof FontSpec>;\n/** Accepted motion CSS variable strings. */\nexport type MotionCSSVariableString = ValueOf<typeof Motion>;\n/** Accepted primitive colour CSS variable strings. */\nexport type PrimitiveColourCSSVariableString = ValueOf<typeof PrimitiveColours>;\n/** Accepted radius CSS variable strings. */\nexport type RadiusCSSVariableString = ValueOf<typeof Radius>;\n/** Accepted semantic colour CSS variable strings. */\nexport type SemanticColourCSSVariableString = ValueOf<typeof SemanticColours>;\n/** Accepted colour CSS variable strings. */\nexport type ColourCSSVariableString =\n | PrimitiveColourCSSVariableString\n | SemanticColourCSSVariableString;\n/** Accepted shadow CSS variable strings. */\nexport type ShadowCSSVariableString = ValueOf<typeof Shadow>;\n/** Accepted spacing and layout CSS variable strings. */\nexport type SpacingCSSVariableString = ValueOf<typeof Spacing>;\n\n/** Union of all design-token CSS variable string literals. */\nexport type CSSVariableString =\n | BreakpointCSSVariableString\n | BorderCSSVariableString\n | ColourCSSVariableString\n | ComponentTokenCSSVariableString\n | FontSpecCSSVariableString\n | MotionCSSVariableString\n | RadiusCSSVariableString\n | ShadowCSSVariableString\n | SpacingCSSVariableString;\n"],"names":[],"mappings":"iCAe2B,CACvB,kBACA,YACA,gBACA,QACA,OACA,SACA,WACA,aACA,KACA,MACA,oBACA,OACA,MACA,iBACA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"time-slot-bar.js","sources":["../../../src/time-slot-bar/time-slot-bar.tsx"],"sourcesContent":["import { ChevronLeftIcon } from \"@lifesg/react-icons/chevron-left\";\nimport { ChevronRightIcon } from \"@lifesg/react-icons/chevron-right\";\nimport clsx from \"clsx\";\nimport dayjs, { type Dayjs } from \"dayjs\";\nimport {\n forwardRef,\n useEffect,\n useImperativeHandle,\n useMemo,\n useRef,\n useState,\n} from \"react\";\nimport { useResizeDetector } from \"react-resize-detector\";\n\nimport { VisuallyHidden } from \"../shared/accessibility\";\nimport { ClickableIcon } from \"../shared/clickable-icon\";\nimport { TimeSlot } from \"../shared/time-slot\";\nimport { Typography } from \"../typography\";\nimport { TimeHelper } from \"../util/time-helper\";\nimport { getCellWidth, TimeSlotBarHelper } from \"./helper\";\nimport type { Direction } from \"./internal-types\";\nimport * as styles from \"./time-slot-bar.styles\";\nimport TimeSlotDivider from \"./time-slot-divider\";\nimport TimeSlotItem from \"./time-slot-item\";\nimport type {\n TimeSlot as TTimeSlot,\n TimeSlotBarProps,\n TimeSlotBarRef,\n TimeSlotBarVariant,\n} from \"./types\";\n\nconst CELL_DURATION = 30; // In minutes\n\nconst Component = (props: TimeSlotBarProps, ref: React.Ref<TimeSlotBarRef>) => {\n // =============================================================================\n // CONST, STATE, REF\n // =============================================================================\n const {\n \"data-testid\": testId,\n className,\n variant = \"default\",\n startTime,\n endTime,\n slots,\n onSlotClick,\n onClick,\n styleAttributes,\n initialScrollTime,\n roundInitialScrollTime = true,\n } = props;\n const barRef = useRef<HTMLDivElement>(null);\n const [scrollPosition, setScrollPosition] = useState<number>(0);\n const [clientWidth, setClientWidth] = useState<number>(0);\n const cellWidth = getCellWidth(variant);\n\n const adjustedStartTime = TimeSlotBarHelper.adjustTimeForMarker(\n startTime,\n \"start\"\n );\n const adjustedEndTime = TimeSlotBarHelper.adjustTimeForMarker(\n endTime,\n \"end\"\n );\n\n const SCROLL_INCREMENT = cellWidth * 2.5; // In px. Each scroll increment corresponds to 75mins\n\n // Expose imperative handle\n useImperativeHandle(ref, () => ({\n resetScroll,\n }));\n\n const { summary: slotsSummary, computedSlots: allSlots } = useMemo(() => {\n return TimeSlotBarHelper.processSlots(\n { start: adjustedStartTime, end: adjustedEndTime },\n slots,\n variant\n );\n }, [adjustedStartTime, adjustedEndTime, slots, variant]);\n\n // =============================================================================\n // EFFECTS\n // =============================================================================\n\n useEffect(() => {\n const container = barRef.current;\n if (container) {\n container.addEventListener(\"scroll\", handleScroll);\n // Initialize clientWidth on mount\n setClientWidth(container.clientWidth);\n }\n\n return () => {\n if (container) {\n container.removeEventListener(\"scroll\", handleScroll);\n }\n };\n }, []);\n\n // Initial scroll on mount and when dependencies change\n useEffect(() => {\n resetScroll();\n }, [initialScrollTime, cellWidth, startTime, endTime]);\n\n // =============================================================================\n // EVENT HANDLERS\n // =============================================================================\n\n const handleScroll = () => {\n if (barRef.current) {\n setScrollPosition(barRef.current.scrollLeft);\n }\n };\n\n const handleArrowButtonClick = (direction: Direction) => {\n if (barRef.current) {\n barRef.current.scrollBy({\n left:\n direction === \"left\" ? -SCROLL_INCREMENT : SCROLL_INCREMENT,\n behavior: \"smooth\",\n });\n }\n };\n\n const handleResize = () => {\n if (barRef.current) {\n setClientWidth(barRef.current.clientWidth);\n }\n };\n\n useResizeDetector({\n onResize: handleResize,\n targetRef: barRef,\n refreshMode: \"debounce\",\n refreshRate: 50,\n });\n\n // ===========================================================================\n // HELPER FUNCTIONS\n // ===========================================================================\n /**\n * NOTE: Special condition\n * Show ellipsis only if the slotWidth is smaller or equal to\n * 15min interval\n */\n const showFullEllipsis = (slotWidth: number) => {\n return slotWidth <= cellWidth / 2;\n };\n\n const getDataTestId = (subStr: string) => {\n if (!testId) return undefined;\n return `${testId}-${subStr}`;\n };\n\n /**\n * Function to determine if a long time marker should be displayed\n * For minified variant the long time marker is displayed every alternate hour\n */\n const shouldDisplayLongTimeMarker = (\n currentTime: Dayjs,\n isStartHourEven: boolean, // To determine if the first hour is even or odd for minified\n variant: TimeSlotBarVariant\n ) => {\n const isHour = currentTime.minute() === 0;\n\n if (variant === \"default\") {\n return isHour;\n }\n\n const isAlternateHour =\n isHour &&\n (isStartHourEven\n ? currentTime.hour() % 2 === 0\n : currentTime.hour() % 2 === 1);\n\n return isAlternateHour;\n };\n\n // Function to reset scroll to initialScrollTime\n const resetScroll = () => {\n if (initialScrollTime && barRef.current && cellWidth > 0) {\n const scrollPosition = TimeHelper.calculateScrollPosition({\n scrollTime: initialScrollTime,\n minTime: adjustedStartTime,\n maxTime: adjustedEndTime,\n interval: CELL_DURATION,\n intervalWidth: cellWidth,\n options: {\n roundToInterval: roundInitialScrollTime,\n },\n });\n\n if (scrollPosition !== null) {\n barRef.current.scrollLeft = scrollPosition;\n }\n }\n };\n\n const isVariant = (v: TimeSlotBarVariant) => {\n if (variant === v) return true;\n return false;\n };\n\n // =============================================================================\n // RENDER FUNCTIONS\n // =============================================================================\n\n // Render time markers\n const renderTimeMarkers = () => {\n const timeMarkers = [];\n const startTimeFormatted = dayjs(adjustedStartTime, \"HH:mm\");\n const endTimeFormatted = dayjs(adjustedEndTime, \"HH:mm\");\n\n const isStartHourEven = startTimeFormatted.hour() % 2 === 0;\n\n for (\n let currentTime = startTimeFormatted;\n currentTime.isBefore(endTimeFormatted);\n currentTime = currentTime.add(CELL_DURATION, \"minute\")\n ) {\n const displayLongTimeMarker = shouldDisplayLongTimeMarker(\n currentTime,\n isStartHourEven,\n variant\n );\n\n timeMarkers.push(\n <div\n data-testid={`${currentTime.format(\"HH:mm\")}-marker`}\n key={currentTime.format(\"HH:mm\")}\n className={clsx(\n styles.timeMarker,\n variant === \"default\"\n ? styles.timeMarkerDefault\n : styles.timeMarkerMinified,\n displayLongTimeMarker && styles.timeMarkerLong\n )}\n >\n {displayLongTimeMarker && (\n <Typography.BodyXS\n className={styles.timeLabel}\n weight=\"semibold\"\n >\n {TimeSlotBarHelper.formatHourlyDisplay(\n currentTime.format(\"HH:mm\")\n )}\n </Typography.BodyXS>\n )}\n </div>\n );\n }\n return timeMarkers;\n };\n\n // Render default time slot (aka background)\n const renderDefaultTimeSlots = () => {\n if (!styleAttributes) return;\n\n const {\n backgroundColor,\n backgroundColor2,\n hoverBackgroundColor,\n hoverBackgroundColor2,\n styleType = \"default\",\n } = styleAttributes;\n\n const slotWidth = TimeSlotBarHelper.calculateWidth(\n adjustedStartTime,\n adjustedEndTime,\n cellWidth\n );\n\n const isClickable = !!onClick && isVariant(\"default\");\n\n return (\n <>\n <TimeSlotDivider variant={variant} />\n <TimeSlotItem\n key={\"default-timeslot\"}\n variant={variant}\n dataTestId={getDataTestId(\"default-timeslot\")}\n slotWidth={slotWidth}\n slotOffset={0}\n onClick={isClickable ? onClick : undefined}\n >\n <TimeSlot\n className={styles.timeSlotItemContent}\n styleType={styleType}\n bgColor={backgroundColor}\n bgColor2={backgroundColor2}\n hoverBgColor={hoverBackgroundColor}\n hoverBgColor2={hoverBackgroundColor2}\n clickable={isClickable}\n />\n </TimeSlotItem>\n </>\n );\n };\n\n // Render time slots\n const renderTimeSlots = () => {\n return allSlots.map((slot) => {\n const {\n id,\n startTime: slotStartTime,\n endTime: slotEndTime,\n label,\n clickable = true,\n styleAttributes,\n ariaLabel,\n } = slot;\n\n const {\n color,\n styleType = \"default\",\n backgroundColor,\n backgroundColor2,\n hoverBackgroundColor,\n hoverBackgroundColor2,\n } = styleAttributes;\n\n const slotWidth = TimeSlotBarHelper.calculateWidth(\n slotStartTime,\n slotEndTime,\n cellWidth\n );\n const slotOffset = TimeSlotBarHelper.calculateWidth(\n adjustedStartTime,\n slotStartTime,\n cellWidth\n );\n\n const isClickable = clickable && variant === \"default\";\n const showLabel = isVariant(\"default\") && label;\n\n const handleSlotClick =\n (clickedSlot: TTimeSlot & { ariaLabel?: string }) =>\n (evt: React.MouseEvent<HTMLElement>) => {\n evt.stopPropagation();\n\n const { ariaLabel: _, ...slot } = clickedSlot;\n if (isClickable) onSlotClick(slot);\n };\n\n return (\n <div key={id} role=\"gridcell\">\n <TimeSlotDivider\n variant={variant}\n left={slotOffset}\n dataTestId=\"start-border\"\n />\n <TimeSlotItem\n variant={variant}\n dataTestId={getDataTestId(`${id}-timeslot`)}\n slotWidth={slotWidth}\n slotOffset={slotOffset}\n color={color}\n onClick={handleSlotClick(slot)}\n >\n <TimeSlot\n className={styles.timeSlotItemContent}\n styleType={styleType}\n bgColor={backgroundColor}\n bgColor2={backgroundColor2}\n hoverBgColor={hoverBackgroundColor}\n hoverBgColor2={hoverBackgroundColor2}\n clickable={isClickable}\n >\n {!!ariaLabel && (\n <VisuallyHidden>\n <button\n type=\"button\" // overrides default type=\"submit\" when used with <form>\n aria-disabled={!isClickable}\n aria-label={ariaLabel}\n onClick={handleSlotClick(slot)} // use `button` element native keyboard activation handling\n />\n </VisuallyHidden>\n )}\n\n {showLabel && (\n <Typography.BodyXS\n className={styles.cellText}\n weight={\"semibold\"}\n aria-hidden={!ariaLabel}\n >\n {showFullEllipsis(slotWidth)\n ? \"...\"\n : label}\n </Typography.BodyXS>\n )}\n </TimeSlot>\n </TimeSlotItem>\n {endTime !== slotEndTime && (\n <TimeSlotDivider\n variant={variant}\n dataTestId=\"end-border\"\n left={slotOffset + slotWidth}\n />\n )}\n </div>\n );\n });\n };\n\n const renderArrowButton = (direction: Direction) => {\n const isLeft = direction === \"left\";\n const totalScrollableWidth = TimeSlotBarHelper.calculateWidth(\n adjustedStartTime,\n adjustedEndTime,\n cellWidth\n );\n const hasContentOnLeft = scrollPosition > 0;\n const hasContentOnRight =\n scrollPosition + clientWidth < totalScrollableWidth;\n const shouldShowArrow = isLeft ? hasContentOnLeft : hasContentOnRight;\n\n if (!shouldShowArrow) return null;\n\n const directionClass = isLeft\n ? styles.arrowButtonLeft\n : styles.arrowButtonRight;\n const variantClass =\n variant === \"default\"\n ? styles.arrowButtonDefault\n : styles.arrowButtonMinified;\n const arrowIcon = isLeft ? (\n <ChevronLeftIcon className={styles.arrowIcon} />\n ) : (\n <ChevronRightIcon className={styles.arrowIcon} />\n );\n\n return (\n <ClickableIcon\n data-testid={getDataTestId(`arrow-${direction}`)}\n aria-hidden\n tabIndex={-1}\n className={clsx(\n styles.arrowButton,\n directionClass,\n variantClass\n )}\n focusHighlight={false}\n focusOutline=\"none\"\n onClick={() => {\n handleArrowButtonClick(direction);\n }}\n >\n {arrowIcon}\n </ClickableIcon>\n );\n };\n\n return (\n <div className={clsx(styles.container, className)}>\n <div\n data-testid={testId}\n ref={barRef}\n className={clsx(\n styles.timeSlotBarContainer,\n variant === \"default\"\n ? styles.containerDefault\n : styles.containerMinified\n )}\n >\n <div\n className={styles.timeMarkerWrapper}\n data-testid={getDataTestId(\"time-marker-wrapper\")}\n data-id=\"marker-wrapper\"\n >\n {renderTimeMarkers()}\n </div>\n <div role=\"grid\" aria-label={slotsSummary} tabIndex={0}>\n <div\n className={styles.timeSlotWrapper}\n data-testid={getDataTestId(\"time-slot-wrapper\")}\n data-id=\"slot-wrapper\"\n role=\"row\"\n >\n {renderDefaultTimeSlots()}\n {renderTimeSlots()}\n </div>\n </div>\n </div>\n {renderArrowButton(\"left\")}\n {renderArrowButton(\"right\")}\n </div>\n );\n};\n\n// @catalog\n/**\n * A horizontally scrollable timeline bar that visualises time slots across a\n * defined time range.\n *\n * Use `TimeSlotBar` to display availability, bookings, or schedule occupancy\n * as coloured cells on a shared time axis.\n */\nexport const TimeSlotBar = forwardRef<TimeSlotBarRef, TimeSlotBarProps>(\n Component\n);\n"],"names":["TimeSlotBar","forwardRef","props","ref","testId","className","variant","startTime","endTime","slots","onSlotClick","onClick","styleAttributes","initialScrollTime","roundInitialScrollTime","barRef","useRef","scrollPosition","setScrollPosition","useState","clientWidth","setClientWidth","cellWidth","getCellWidth","adjustedStartTime","TimeSlotBarHelper","adjustTimeForMarker","adjustedEndTime","SCROLL_INCREMENT","useImperativeHandle","resetScroll","summary","slotsSummary","computedSlots","allSlots","useMemo","processSlots","start","end","useEffect","container","current","addEventListener","handleScroll","removeEventListener","scrollLeft","useResizeDetector","onResize","targetRef","refreshMode","refreshRate","showFullEllipsis","slotWidth","getDataTestId","subStr","shouldDisplayLongTimeMarker","currentTime","isStartHourEven","isHour","minute","hour","TimeHelper","calculateScrollPosition","scrollTime","minTime","maxTime","interval","intervalWidth","options","roundToInterval","isVariant","v","renderArrowButton","direction","isLeft","totalScrollableWidth","calculateWidth","directionClass","styles.arrowButtonLeft","styles.arrowButtonRight","variantClass","styles.arrowButtonDefault","styles.arrowButtonMinified","arrowIcon","_jsx","ChevronLeftIcon","styles.arrowIcon","ChevronRightIcon","ClickableIcon","tabIndex","clsx","styles.arrowButton","focusHighlight","focusOutline","scrollBy","left","behavior","handleArrowButtonClick","children","_jsxs","styles.container","styles.timeSlotBarContainer","styles.containerDefault","styles.containerMinified","styles.timeMarkerWrapper","timeMarkers","startTimeFormatted","dayjs","endTimeFormatted","isBefore","add","displayLongTimeMarker","push","format","styles.timeMarker","styles.timeMarkerDefault","styles.timeMarkerMinified","styles.timeMarkerLong","Typography","BodyXS","styles.timeLabel","weight","formatHourlyDisplay","renderTimeMarkers","role","styles.timeSlotWrapper","backgroundColor","backgroundColor2","hoverBackgroundColor","hoverBackgroundColor2","styleType","isClickable","_Fragment","TimeSlotDivider","TimeSlotItem","dataTestId","slotOffset","undefined","TimeSlot","styles.timeSlotItemContent","bgColor","bgColor2","hoverBgColor","hoverBgColor2","clickable","renderDefaultTimeSlots","map","slot","id","slotStartTime","slotEndTime","label","ariaLabel","color","showLabel","handleSlotClick","clickedSlot","evt","stopPropagation","_","__rest","VisuallyHidden","type","styles.cellText"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"time-slot-bar.js","sources":["../../../src/time-slot-bar/time-slot-bar.tsx"],"sourcesContent":["import { ChevronLeftIcon } from \"@lifesg/react-icons/chevron-left\";\nimport { ChevronRightIcon } from \"@lifesg/react-icons/chevron-right\";\nimport clsx from \"clsx\";\nimport dayjs, { type Dayjs } from \"dayjs\";\nimport {\n forwardRef,\n useEffect,\n useImperativeHandle,\n useMemo,\n useRef,\n useState,\n} from \"react\";\nimport { useResizeDetector } from \"react-resize-detector\";\n\nimport { VisuallyHidden } from \"../shared/accessibility\";\nimport { ClickableIcon } from \"../shared/clickable-icon\";\nimport { TimeSlot } from \"../shared/time-slot\";\nimport { Typography } from \"../typography\";\nimport { TimeHelper } from \"../util/time-helper\";\nimport { getCellWidth, TimeSlotBarHelper } from \"./helper\";\nimport type { Direction } from \"./internal-types\";\nimport * as styles from \"./time-slot-bar.styles\";\nimport TimeSlotDivider from \"./time-slot-divider\";\nimport TimeSlotItem from \"./time-slot-item\";\nimport type {\n TimeSlot as TTimeSlot,\n TimeSlotBarProps,\n TimeSlotBarRef,\n TimeSlotBarVariant,\n} from \"./types\";\n\nconst CELL_DURATION = 30; // In minutes\n\nconst Component = (props: TimeSlotBarProps, ref: React.Ref<TimeSlotBarRef>) => {\n // =============================================================================\n // CONST, STATE, REF\n // =============================================================================\n const {\n \"data-testid\": testId,\n className,\n variant = \"default\",\n startTime,\n endTime,\n slots,\n onSlotClick,\n onClick,\n styleAttributes,\n initialScrollTime,\n roundInitialScrollTime = true,\n } = props;\n const barRef = useRef<HTMLDivElement>(null);\n const [scrollPosition, setScrollPosition] = useState<number>(0);\n const [clientWidth, setClientWidth] = useState<number>(0);\n const cellWidth = getCellWidth(variant);\n\n const adjustedStartTime = TimeSlotBarHelper.adjustTimeForMarker(\n startTime,\n \"start\"\n );\n const adjustedEndTime = TimeSlotBarHelper.adjustTimeForMarker(\n endTime,\n \"end\"\n );\n\n const SCROLL_INCREMENT = cellWidth * 2.5; // In px. Each scroll increment corresponds to 75mins\n\n // Expose imperative handle\n useImperativeHandle(ref, () => ({\n resetScroll,\n }));\n\n const { summary: slotsSummary, computedSlots: allSlots } = useMemo(() => {\n return TimeSlotBarHelper.processSlots(\n { start: adjustedStartTime, end: adjustedEndTime },\n slots,\n variant\n );\n }, [adjustedStartTime, adjustedEndTime, slots, variant]);\n\n // =============================================================================\n // EFFECTS\n // =============================================================================\n\n useEffect(() => {\n const container = barRef.current;\n if (container) {\n container.addEventListener(\"scroll\", handleScroll);\n // Initialize clientWidth on mount\n setClientWidth(container.clientWidth);\n }\n\n return () => {\n if (container) {\n container.removeEventListener(\"scroll\", handleScroll);\n }\n };\n }, []);\n\n // Initial scroll on mount and when dependencies change\n useEffect(() => {\n resetScroll();\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [initialScrollTime, cellWidth, startTime, endTime]);\n\n // =============================================================================\n // EVENT HANDLERS\n // =============================================================================\n\n const handleScroll = () => {\n if (barRef.current) {\n setScrollPosition(barRef.current.scrollLeft);\n }\n };\n\n const handleArrowButtonClick = (direction: Direction) => {\n if (barRef.current) {\n barRef.current.scrollBy({\n left:\n direction === \"left\" ? -SCROLL_INCREMENT : SCROLL_INCREMENT,\n behavior: \"smooth\",\n });\n }\n };\n\n const handleResize = () => {\n if (barRef.current) {\n setClientWidth(barRef.current.clientWidth);\n }\n };\n\n useResizeDetector({\n onResize: handleResize,\n targetRef: barRef,\n refreshMode: \"debounce\",\n refreshRate: 50,\n });\n\n // ===========================================================================\n // HELPER FUNCTIONS\n // ===========================================================================\n /**\n * NOTE: Special condition\n * Show ellipsis only if the slotWidth is smaller or equal to\n * 15min interval\n */\n const showFullEllipsis = (slotWidth: number) => {\n return slotWidth <= cellWidth / 2;\n };\n\n const getDataTestId = (subStr: string) => {\n if (!testId) return undefined;\n return `${testId}-${subStr}`;\n };\n\n /**\n * Function to determine if a long time marker should be displayed\n * For minified variant the long time marker is displayed every alternate hour\n */\n const shouldDisplayLongTimeMarker = (\n currentTime: Dayjs,\n isStartHourEven: boolean, // To determine if the first hour is even or odd for minified\n variant: TimeSlotBarVariant\n ) => {\n const isHour = currentTime.minute() === 0;\n\n if (variant === \"default\") {\n return isHour;\n }\n\n const isAlternateHour =\n isHour &&\n (isStartHourEven\n ? currentTime.hour() % 2 === 0\n : currentTime.hour() % 2 === 1);\n\n return isAlternateHour;\n };\n\n // Function to reset scroll to initialScrollTime\n const resetScroll = () => {\n if (initialScrollTime && barRef.current && cellWidth > 0) {\n const scrollPosition = TimeHelper.calculateScrollPosition({\n scrollTime: initialScrollTime,\n minTime: adjustedStartTime,\n maxTime: adjustedEndTime,\n interval: CELL_DURATION,\n intervalWidth: cellWidth,\n options: {\n roundToInterval: roundInitialScrollTime,\n },\n });\n\n if (scrollPosition !== null) {\n barRef.current.scrollLeft = scrollPosition;\n }\n }\n };\n\n const isVariant = (v: TimeSlotBarVariant) => {\n if (variant === v) return true;\n return false;\n };\n\n // =============================================================================\n // RENDER FUNCTIONS\n // =============================================================================\n\n // Render time markers\n const renderTimeMarkers = () => {\n const timeMarkers = [];\n const startTimeFormatted = dayjs(adjustedStartTime, \"HH:mm\");\n const endTimeFormatted = dayjs(adjustedEndTime, \"HH:mm\");\n\n const isStartHourEven = startTimeFormatted.hour() % 2 === 0;\n\n for (\n let currentTime = startTimeFormatted;\n currentTime.isBefore(endTimeFormatted);\n currentTime = currentTime.add(CELL_DURATION, \"minute\")\n ) {\n const displayLongTimeMarker = shouldDisplayLongTimeMarker(\n currentTime,\n isStartHourEven,\n variant\n );\n\n timeMarkers.push(\n <div\n data-testid={`${currentTime.format(\"HH:mm\")}-marker`}\n key={currentTime.format(\"HH:mm\")}\n className={clsx(\n styles.timeMarker,\n variant === \"default\"\n ? styles.timeMarkerDefault\n : styles.timeMarkerMinified,\n displayLongTimeMarker && styles.timeMarkerLong\n )}\n >\n {displayLongTimeMarker && (\n <Typography.BodyXS\n className={styles.timeLabel}\n weight=\"semibold\"\n >\n {TimeSlotBarHelper.formatHourlyDisplay(\n currentTime.format(\"HH:mm\")\n )}\n </Typography.BodyXS>\n )}\n </div>\n );\n }\n return timeMarkers;\n };\n\n // Render default time slot (aka background)\n const renderDefaultTimeSlots = () => {\n if (!styleAttributes) return;\n\n const {\n backgroundColor,\n backgroundColor2,\n hoverBackgroundColor,\n hoverBackgroundColor2,\n styleType = \"default\",\n } = styleAttributes;\n\n const slotWidth = TimeSlotBarHelper.calculateWidth(\n adjustedStartTime,\n adjustedEndTime,\n cellWidth\n );\n\n const isClickable = !!onClick && isVariant(\"default\");\n\n return (\n <>\n <TimeSlotDivider variant={variant} />\n <TimeSlotItem\n key={\"default-timeslot\"}\n variant={variant}\n dataTestId={getDataTestId(\"default-timeslot\")}\n slotWidth={slotWidth}\n slotOffset={0}\n onClick={isClickable ? onClick : undefined}\n >\n <TimeSlot\n className={styles.timeSlotItemContent}\n styleType={styleType}\n bgColor={backgroundColor}\n bgColor2={backgroundColor2}\n hoverBgColor={hoverBackgroundColor}\n hoverBgColor2={hoverBackgroundColor2}\n clickable={isClickable}\n />\n </TimeSlotItem>\n </>\n );\n };\n\n // Render time slots\n const renderTimeSlots = () => {\n return allSlots.map((slot) => {\n const {\n id,\n startTime: slotStartTime,\n endTime: slotEndTime,\n label,\n clickable = true,\n styleAttributes,\n ariaLabel,\n } = slot;\n\n const {\n color,\n styleType = \"default\",\n backgroundColor,\n backgroundColor2,\n hoverBackgroundColor,\n hoverBackgroundColor2,\n } = styleAttributes;\n\n const slotWidth = TimeSlotBarHelper.calculateWidth(\n slotStartTime,\n slotEndTime,\n cellWidth\n );\n const slotOffset = TimeSlotBarHelper.calculateWidth(\n adjustedStartTime,\n slotStartTime,\n cellWidth\n );\n\n const isClickable = clickable && variant === \"default\";\n const showLabel = isVariant(\"default\") && label;\n\n const handleSlotClick =\n (clickedSlot: TTimeSlot & { ariaLabel?: string }) =>\n (evt: React.MouseEvent<HTMLElement>) => {\n evt.stopPropagation();\n\n const { ariaLabel: _, ...slot } = clickedSlot;\n if (isClickable) onSlotClick(slot);\n };\n\n return (\n <div key={id} role=\"gridcell\">\n <TimeSlotDivider\n variant={variant}\n left={slotOffset}\n dataTestId=\"start-border\"\n />\n <TimeSlotItem\n variant={variant}\n dataTestId={getDataTestId(`${id}-timeslot`)}\n slotWidth={slotWidth}\n slotOffset={slotOffset}\n color={color}\n onClick={handleSlotClick(slot)}\n >\n <TimeSlot\n className={styles.timeSlotItemContent}\n styleType={styleType}\n bgColor={backgroundColor}\n bgColor2={backgroundColor2}\n hoverBgColor={hoverBackgroundColor}\n hoverBgColor2={hoverBackgroundColor2}\n clickable={isClickable}\n >\n {!!ariaLabel && (\n <VisuallyHidden>\n <button\n type=\"button\" // overrides default type=\"submit\" when used with <form>\n aria-disabled={!isClickable}\n aria-label={ariaLabel}\n onClick={handleSlotClick(slot)} // use `button` element native keyboard activation handling\n />\n </VisuallyHidden>\n )}\n\n {showLabel && (\n <Typography.BodyXS\n className={styles.cellText}\n weight={\"semibold\"}\n aria-hidden={!ariaLabel}\n >\n {showFullEllipsis(slotWidth)\n ? \"...\"\n : label}\n </Typography.BodyXS>\n )}\n </TimeSlot>\n </TimeSlotItem>\n {endTime !== slotEndTime && (\n <TimeSlotDivider\n variant={variant}\n dataTestId=\"end-border\"\n left={slotOffset + slotWidth}\n />\n )}\n </div>\n );\n });\n };\n\n const renderArrowButton = (direction: Direction) => {\n const isLeft = direction === \"left\";\n const totalScrollableWidth = TimeSlotBarHelper.calculateWidth(\n adjustedStartTime,\n adjustedEndTime,\n cellWidth\n );\n const hasContentOnLeft = scrollPosition > 0;\n const hasContentOnRight =\n scrollPosition + clientWidth < totalScrollableWidth;\n const shouldShowArrow = isLeft ? hasContentOnLeft : hasContentOnRight;\n\n if (!shouldShowArrow) return null;\n\n const directionClass = isLeft\n ? styles.arrowButtonLeft\n : styles.arrowButtonRight;\n const variantClass =\n variant === \"default\"\n ? styles.arrowButtonDefault\n : styles.arrowButtonMinified;\n const arrowIcon = isLeft ? (\n <ChevronLeftIcon className={styles.arrowIcon} />\n ) : (\n <ChevronRightIcon className={styles.arrowIcon} />\n );\n\n return (\n <ClickableIcon\n data-testid={getDataTestId(`arrow-${direction}`)}\n aria-hidden\n tabIndex={-1}\n className={clsx(\n styles.arrowButton,\n directionClass,\n variantClass\n )}\n focusHighlight={false}\n focusOutline=\"none\"\n onClick={() => {\n handleArrowButtonClick(direction);\n }}\n >\n {arrowIcon}\n </ClickableIcon>\n );\n };\n\n return (\n <div className={clsx(styles.container, className)}>\n <div\n data-testid={testId}\n ref={barRef}\n className={clsx(\n styles.timeSlotBarContainer,\n variant === \"default\"\n ? styles.containerDefault\n : styles.containerMinified\n )}\n >\n <div\n className={styles.timeMarkerWrapper}\n data-testid={getDataTestId(\"time-marker-wrapper\")}\n data-id=\"marker-wrapper\"\n >\n {renderTimeMarkers()}\n </div>\n <div role=\"grid\" aria-label={slotsSummary} tabIndex={0}>\n <div\n className={styles.timeSlotWrapper}\n data-testid={getDataTestId(\"time-slot-wrapper\")}\n data-id=\"slot-wrapper\"\n role=\"row\"\n >\n {renderDefaultTimeSlots()}\n {renderTimeSlots()}\n </div>\n </div>\n </div>\n {renderArrowButton(\"left\")}\n {renderArrowButton(\"right\")}\n </div>\n );\n};\n\n// @catalog\n/**\n * A horizontally scrollable timeline bar that visualises time slots across a\n * defined time range.\n *\n * Use `TimeSlotBar` to display availability, bookings, or schedule occupancy\n * as coloured cells on a shared time axis.\n */\nexport const TimeSlotBar = forwardRef<TimeSlotBarRef, TimeSlotBarProps>(\n Component\n);\n"],"names":["TimeSlotBar","forwardRef","props","ref","testId","className","variant","startTime","endTime","slots","onSlotClick","onClick","styleAttributes","initialScrollTime","roundInitialScrollTime","barRef","useRef","scrollPosition","setScrollPosition","useState","clientWidth","setClientWidth","cellWidth","getCellWidth","adjustedStartTime","TimeSlotBarHelper","adjustTimeForMarker","adjustedEndTime","SCROLL_INCREMENT","useImperativeHandle","resetScroll","summary","slotsSummary","computedSlots","allSlots","useMemo","processSlots","start","end","useEffect","container","current","addEventListener","handleScroll","removeEventListener","scrollLeft","useResizeDetector","onResize","targetRef","refreshMode","refreshRate","showFullEllipsis","slotWidth","getDataTestId","subStr","shouldDisplayLongTimeMarker","currentTime","isStartHourEven","isHour","minute","hour","TimeHelper","calculateScrollPosition","scrollTime","minTime","maxTime","interval","intervalWidth","options","roundToInterval","isVariant","v","renderArrowButton","direction","isLeft","totalScrollableWidth","calculateWidth","directionClass","styles.arrowButtonLeft","styles.arrowButtonRight","variantClass","styles.arrowButtonDefault","styles.arrowButtonMinified","arrowIcon","_jsx","ChevronLeftIcon","styles.arrowIcon","ChevronRightIcon","ClickableIcon","tabIndex","clsx","styles.arrowButton","focusHighlight","focusOutline","scrollBy","left","behavior","handleArrowButtonClick","children","_jsxs","styles.container","styles.timeSlotBarContainer","styles.containerDefault","styles.containerMinified","styles.timeMarkerWrapper","timeMarkers","startTimeFormatted","dayjs","endTimeFormatted","isBefore","add","displayLongTimeMarker","push","format","styles.timeMarker","styles.timeMarkerDefault","styles.timeMarkerMinified","styles.timeMarkerLong","Typography","BodyXS","styles.timeLabel","weight","formatHourlyDisplay","renderTimeMarkers","role","styles.timeSlotWrapper","backgroundColor","backgroundColor2","hoverBackgroundColor","hoverBackgroundColor2","styleType","isClickable","_Fragment","TimeSlotDivider","TimeSlotItem","dataTestId","slotOffset","undefined","TimeSlot","styles.timeSlotItemContent","bgColor","bgColor2","hoverBgColor","hoverBgColor2","clickable","renderDefaultTimeSlots","map","slot","id","slotStartTime","slotEndTime","label","ariaLabel","color","showLabel","handleSlotClick","clickedSlot","evt","stopPropagation","_","__rest","VisuallyHidden","type","styles.cellText"],"mappings":"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"}
|