@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":"data-table.js","sources":["../../../src/data-table/data-table.tsx"],"sourcesContent":["import { ArrowDownIcon, ArrowUpIcon } from \"@lifesg/react-icons\";\nimport clsx from \"clsx\";\nimport { useEffect, useRef, useState } from \"react\";\nimport { useResizeDetector } from \"react-resize-detector\";\n\nimport { LoadingDotsSpinner } from \"../animations\";\nimport { Checkbox } from \"../checkbox\";\nimport { ErrorDisplay } from \"../error-display\";\nimport { concatIds, VisuallyHidden } from \"../shared/accessibility\";\nimport { BasicButton } from \"../shared/input-wrapper\";\nimport { useApplyStyle } from \"../theme\";\nimport { Typography } from \"../typography\";\nimport { useEvent, useEventListener, useId, useThrottle } from \"../util\";\nimport * as styles from \"./data-table.styles\";\nimport type { DataTableProps, HeaderProps, RowProps } from \"./types\";\n\n// @catalog\n/**\n * Renders a sortable, selectable data table with scroll-aware action bar and loading state support.\n *\n * Use `DataTable` when presenting structured multi-column data that users may need to sort by\n * column or select rows for bulk actions. Row selection, sort indicators, and the action bar\n * content are all externally controlled; the component manages scroll detection, sticky-header\n * positioning, and floating action bar behaviour internally.\n */\nexport const DataTable = ({\n id,\n headers,\n rows,\n className,\n sortIndicators,\n alternatingRows,\n loadState = \"success\",\n enableMultiSelect,\n selectedIds,\n disabledIds,\n enableActionBar,\n enableActionBarWithoutSelection,\n enableSelectAll,\n enableStickyHeader,\n emptyView,\n actionBarContent,\n renderCustomEmptyView,\n onHeaderClick,\n onSelect,\n onSelectAll,\n onClearSelectionClick,\n ...otherProps\n}: DataTableProps) => {\n // =============================================================================\n // CONST, STATE, REF\n // =============================================================================\n const tableRef = useRef<HTMLTableElement>(null);\n const headerRef = useRef<HTMLTableSectionElement>(null);\n const actionBarWrapperRef = useRef<HTMLDivElement>(null);\n const wrapperRef = useRef<HTMLDivElement>(null);\n const internalId = useId();\n const keyColumns = headers.filter(\n (header): header is Exclude<HeaderProps, string> => {\n return typeof header !== \"string\" && !!header.keyColumn;\n }\n );\n\n const [actionBarStrategy, setActionBarStrategy] = useState<\n \"sticky\" | \"fixed\" | \"inline\"\n >(\"inline\");\n const [scrollable, setScrollable] = useState(false);\n const [isFloatingActionBar, setIsFloatingActionBar] = useState(false);\n\n useApplyStyle(actionBarWrapperRef, {\n [styles.tokens.actionBarWrapperLeft]:\n isFloatingActionBar && tableRef.current\n ? `${tableRef.current.getBoundingClientRect().left}px`\n : undefined,\n [styles.tokens.actionBarWrapperWidth]: tableRef.current\n ? `${tableRef.current.clientWidth}px`\n : undefined,\n });\n\n // =============================================================================\n // EFFECTS, EVENT LISTENERS\n // ============================================================================\n const useUpdateActionBarBehaviour = useEvent(() => {\n updateActionBarBehaviour();\n });\n\n useEffect(() => {\n useUpdateActionBarBehaviour();\n }, [useUpdateActionBarBehaviour]);\n\n const updateActionBarBehaviourThrottled = useThrottle(\n () => updateActionBarBehaviour(),\n 100\n );\n\n useResizeDetector({\n targetRef: wrapperRef,\n onResize: () => updateActionBarBehaviourThrottled(),\n });\n\n useEventListener(\"scroll\", updateActionBarBehaviourThrottled);\n useEventListener(\n \"scroll\",\n updateActionBarBehaviourThrottled,\n wrapperRef.current\n );\n\n // ===========================================================================\n // HELPER FUNCTIONS\n // ===========================================================================\n const isAllCheckboxSelected = (): boolean => {\n if (!rows || !rows.length || !selectedIds) {\n return false;\n }\n return selectedIds.length === rows.length;\n };\n\n const isIndeterminateCheckbox = (): boolean => {\n return (\n !!selectedIds &&\n selectedIds.length !== 0 &&\n !isAllCheckboxSelected()\n );\n };\n\n const isHeaderCheckboxDisabled = (): boolean => {\n return !rows || !rows.length || !selectedIds;\n };\n\n const isRowSelected = (rowId: string): boolean => {\n return !!selectedIds?.includes(rowId);\n };\n\n const isAlternatingRow = (index: number): boolean => {\n return !!alternatingRows && index % 2 === 1;\n };\n\n const isDisabledRow = (rowId: string): boolean => {\n return !!disabledIds?.includes(rowId);\n };\n\n const getDataTestId = (subStr: string) => {\n if (!otherProps[\"data-testid\"]) return undefined;\n return `${otherProps[\"data-testid\"]}-${subStr}`;\n };\n\n const getTotalColumns = (): number => {\n return headers.length + (enableMultiSelect ? 1 : 0);\n };\n\n const getSortDirection = (fieldKey: string) => {\n return sortIndicators?.[fieldKey];\n };\n\n const getHeaderAriaSort = (fieldKey: string) => {\n const sortDirection = getSortDirection(fieldKey);\n\n if (!sortDirection) {\n return undefined;\n }\n\n return sortDirection === \"asc\" ? \"ascending\" : \"descending\";\n };\n\n const getSortButtonAriaLabel = (fieldKey: string) => {\n const nextSortDirection =\n getSortDirection(fieldKey) === \"asc\" ? \"descending\" : \"ascending\";\n\n return ` by ${nextSortDirection} order`;\n };\n\n const getHeaderCellId = (fieldKey: string) => {\n return `${internalId}-header-${fieldKey}`;\n };\n const getCellId = (rowId: string, fieldKey: string) => {\n return `${internalId}-row-${rowId}-${fieldKey}-key-column`;\n };\n\n const getRowCheckboxAriaLabelledBy = (rowId: string) => {\n const keyColumnIds = keyColumns.map((header) =>\n getCellId(rowId, header.fieldKey)\n );\n\n return concatIds(...keyColumnIds);\n };\n\n const updateActionBarBehaviour = () => {\n if (\n !wrapperRef.current ||\n !headerRef.current ||\n !actionBarWrapperRef.current\n ) {\n return;\n }\n\n const wrapperBounds = wrapperRef.current.getBoundingClientRect();\n const headerBounds = headerRef.current.getBoundingClientRect();\n\n let strategy: typeof actionBarStrategy = \"inline\";\n\n const scrollable =\n wrapperRef.current.scrollHeight > wrapperRef.current.clientHeight;\n\n if (\n wrapperBounds.top > window.innerHeight ||\n wrapperBounds.bottom < 0\n ) {\n // if fully out of the viewport, disable floating\n strategy = \"inline\";\n } else if (scrollable) {\n if (\n wrapperBounds.top > 0 &&\n wrapperBounds.top < window.innerHeight &&\n wrapperBounds.bottom > 0 &&\n wrapperBounds.bottom < window.innerHeight\n ) {\n // if fully in the viewport, use the native sticky behaviour\n strategy = \"sticky\";\n } else if (\n wrapperBounds.top < 0 &&\n wrapperBounds.bottom > 0 &&\n wrapperBounds.bottom < window.innerHeight\n ) {\n // if partially offscreen at the top, use the native sticky behaviour\n strategy = \"sticky\";\n } else if (\n wrapperBounds.bottom > window.innerHeight &&\n Math.max(wrapperBounds.top, headerBounds.bottom) +\n headerBounds.height <\n window.innerHeight\n ) {\n // if offscreen at the bottom, pin to the viewport, up until the table/header\n strategy = \"fixed\";\n }\n } else if (\n wrapperBounds.bottom > window.innerHeight &&\n headerBounds.bottom + headerBounds.height < window.innerHeight\n ) {\n // if offscreen at the bottom, pin to the viewport, up until the header\n strategy = \"fixed\";\n }\n\n setScrollable(scrollable);\n setActionBarStrategy(strategy);\n\n if (strategy === \"fixed\") {\n setIsFloatingActionBar(true);\n } else if (strategy === \"sticky\") {\n const beforeScrollEnd =\n wrapperRef.current.scrollTop + wrapperRef.current.clientHeight <\n wrapperRef.current.scrollHeight;\n setIsFloatingActionBar(beforeScrollEnd);\n } else {\n setIsFloatingActionBar(false);\n }\n };\n\n // =============================================================================\n // EVENT HANDLERS\n // =============================================================================\n const handleHeaderClick = (fieldKey: string) => {\n onHeaderClick?.(fieldKey);\n };\n\n const handleHeaderButtonClick = (\n event: React.MouseEvent<HTMLButtonElement>,\n fieldKey: string\n ) => {\n event.stopPropagation();\n onHeaderClick?.(fieldKey);\n };\n\n // =============================================================================\n // RENDER FUNCTIONS\n // =============================================================================\n const renderHeaders = () => (\n <thead\n ref={headerRef}\n className={enableStickyHeader ? styles.stickyHeader : undefined}\n >\n <tr className={styles.headerRow}>\n {enableMultiSelect && renderHeaderCheckBox()}\n {headers.map(renderHeaderCell)}\n </tr>\n </thead>\n );\n\n const renderHeaderCell = (header: HeaderProps) => {\n const {\n fieldKey,\n label,\n clickable = false,\n style,\n } = typeof header === \"string\"\n ? {\n fieldKey: header,\n label: header,\n style: undefined,\n }\n : header;\n\n const isSortable = !!getSortDirection(fieldKey);\n const headerCellId = getHeaderCellId(fieldKey);\n return (\n <th\n data-testid={getDataTestId(`header-${fieldKey}`)}\n key={fieldKey}\n className={clsx(\n styles.headerCell,\n clickable && styles.headerCellClickable\n )}\n scope=\"col\"\n aria-sort={getHeaderAriaSort(fieldKey)}\n style={style}\n onClick={() => handleHeaderClick(fieldKey)}\n >\n <div className={styles.headerCellContent} id={headerCellId}>\n {typeof label === \"string\" ? (\n <Typography.BodyBL weight=\"bold\">\n {label}\n </Typography.BodyBL>\n ) : (\n label\n )}\n {renderSortedArrow(fieldKey)}\n </div>\n {(clickable || isSortable) && (\n <VisuallyHidden>\n <button\n onClick={(event) =>\n handleHeaderButtonClick(event, fieldKey)\n }\n >\n {isSortable && \"Sort \"}\n <span aria-labelledby={headerCellId} />\n {isSortable && getSortButtonAriaLabel(fieldKey)}\n </button>\n </VisuallyHidden>\n )}\n </th>\n );\n };\n\n const renderSortedArrow = (fieldKey: string) => {\n const isSorted = sortIndicators?.[fieldKey];\n\n if (!isSorted) {\n return <></>;\n }\n if (isSorted === \"asc\") {\n return (\n <ArrowUpIcon\n aria-hidden\n data-testid={getDataTestId(`header-${fieldKey}-arrowup`)}\n />\n );\n }\n return (\n <ArrowDownIcon\n aria-hidden\n data-testid={getDataTestId(`header-${fieldKey}-arrowdown`)}\n />\n );\n };\n\n const renderHeaderCheckBox = () => {\n return (\n <th\n data-testid={getDataTestId(\"header-selection\")}\n className={clsx(styles.headerCell, styles.headerCellCheckbox)}\n scope=\"col\"\n >\n <div className={styles.selectionCheckboxWrapper}>\n <VisuallyHidden>Row selection</VisuallyHidden>\n {enableSelectAll && (\n <Checkbox\n checked={isAllCheckboxSelected()}\n indeterminate={isIndeterminateCheckbox()}\n disabled={isHeaderCheckboxDisabled()}\n aria-label=\"Select all rows\"\n onClick={() => {\n if (onSelectAll) {\n onSelectAll(isAllCheckboxSelected());\n }\n }}\n />\n )}\n </div>\n </th>\n );\n };\n\n const renderRows = () => {\n return !rows || rows.length < 1 ? (\n <tr className={styles.bodyRow}>\n <td\n className={styles.emptyStateCell}\n colSpan={getTotalColumns()}\n >\n {renderCustomEmptyView\n ? renderCustomEmptyView()\n : renderBasicEmptyView()}\n </td>\n </tr>\n ) : (\n <>\n {rows?.map((row: RowProps, index: number) => (\n <tr\n data-testid={getDataTestId(`row-${row.id.toString()}`)}\n key={row.id.toString()}\n className={clsx(\n styles.bodyRow,\n isFloatingActionBar &&\n styles.bodyRowWithBottomBorder,\n isAlternatingRow(index) &&\n styles.bodyRowAlternating,\n enableMultiSelect && styles.bodyRowSelectable,\n isRowSelected(row.id.toString()) &&\n styles.bodyRowSelected\n )}\n >\n {enableMultiSelect && renderRowCheckBox(row)}\n\n {headers.map((header) => renderRowCell(header, row))}\n </tr>\n ))}\n </>\n );\n };\n\n const renderRowCell = (header: HeaderProps, row: RowProps) => {\n const style = typeof header === \"string\" ? undefined : header.style;\n const fieldKey = typeof header === \"string\" ? header : header.fieldKey;\n const rowId = row.id.toString();\n const cellData = row[fieldKey];\n const cellId = `${rowId}-${fieldKey}`;\n\n let cellContent: React.ReactNode;\n if (typeof cellData === \"string\" || typeof cellData === \"number\") {\n cellContent = (\n <Typography.BodyBL className={styles.bodyCellText}>\n {cellData}\n </Typography.BodyBL>\n );\n } else if (typeof cellData === \"function\") {\n cellContent = cellData(row, { isSelected: isRowSelected(rowId) });\n } else {\n cellContent = cellData;\n }\n\n return (\n <td\n data-testid={getDataTestId(`row-${cellId}`)}\n key={cellId}\n id={getCellId(rowId, fieldKey)}\n className={styles.bodyCell}\n style={style}\n >\n {cellContent}\n </td>\n );\n };\n\n const renderRowCheckBox = (row: RowProps) => {\n const rowId = row.id.toString();\n\n return (\n <td\n data-testid={getDataTestId(`row-${rowId}-selection`)}\n className={clsx(styles.bodyCell, styles.bodyCellCheckbox)}\n >\n <div className={styles.selectionCheckboxWrapper}>\n <Checkbox\n checked={isRowSelected(rowId)}\n aria-labelledby={getRowCheckboxAriaLabelledBy(rowId)}\n onClick={() => {\n if (onSelect) {\n onSelect(rowId, !isRowSelected(rowId));\n }\n }}\n disabled={isDisabledRow(rowId)}\n focusableWhenDisabled={isDisabledRow(rowId)}\n />\n </div>\n </td>\n );\n };\n\n const renderBasicEmptyView = () => {\n let emptyTitle: JSX.Element;\n if (!emptyView?.title) {\n emptyTitle = (\n <Typography.HeadingSM\n className={styles.emptyStateTitle}\n weight=\"bold\"\n >\n {\"No <items> found\"}\n </Typography.HeadingSM>\n );\n } else if (typeof emptyView.title === \"string\") {\n emptyTitle = (\n <Typography.HeadingSM\n className={styles.emptyStateTitle}\n weight=\"bold\"\n >\n {emptyView.title}\n </Typography.HeadingSM>\n );\n } else {\n emptyTitle = emptyView.title;\n }\n\n return (\n <ErrorDisplay\n type={\"no-item-found\"}\n {...emptyView}\n title={emptyTitle}\n description={\n emptyView?.description\n ? emptyView.description\n : \"No matching rows\"\n }\n />\n );\n };\n\n const renderLoader = () => {\n return (\n <tr className={styles.bodyRow}>\n <td colSpan={getTotalColumns()}>\n <div\n className={styles.loadingStateWrapper}\n role=\"status\"\n aria-live=\"polite\"\n aria-label=\"Loading table\"\n >\n {loadState === \"loading\" && <LoadingDotsSpinner />}\n </div>\n </td>\n </tr>\n );\n };\n\n const renderSelectionBar = () => {\n const count = selectedIds?.length ?? 0;\n const counter = `item${count === 1 ? \"\" : \"s\"}`;\n\n return (\n <>\n <div\n ref={actionBarWrapperRef}\n className={styles.actionBarWrapper}\n data-strategy={actionBarStrategy}\n >\n <div\n data-testid=\"data-table-action-bar\"\n className={clsx(\n styles.actionBar,\n isFloatingActionBar && styles.actionBarFloating\n )}\n >\n <Typography.BodyMD weight=\"semibold\">{`${count} ${counter} selected`}</Typography.BodyMD>\n {count > 0 ? (\n <BasicButton\n className={styles.actionBarButton}\n type=\"button\"\n aria-label={`Clear selection of ${count} ${counter}`}\n onClick={onClearSelectionClick}\n >\n Clear selection\n </BasicButton>\n ) : (\n <div className={styles.actionBarGap} />\n )}\n {actionBarContent}\n </div>\n </div>\n {/* leave a fixed space when action bar floats to avoid layout shift */}\n {actionBarStrategy !== \"sticky\" && (\n <div className={styles.actionBarSpacer} />\n )}\n </>\n );\n };\n\n return (\n <div\n id={id || \"table-wrapper\"}\n data-testid={otherProps[\"data-testid\"] || \"table\"}\n className={clsx(\n styles.tableWrapper,\n scrollable && styles.tableWrapperScrollable,\n className\n )}\n ref={wrapperRef}\n tabIndex={0} // scrollable container must be focusable to support keyboard users\n >\n <div className={styles.tableContainer}>\n <table ref={tableRef} className={styles.table}>\n {renderHeaders()}\n <tbody>\n {loadState === \"success\"\n ? renderRows()\n : renderLoader()}\n </tbody>\n </table>\n </div>\n {enableActionBar &&\n ((selectedIds && selectedIds.length > 0) ||\n enableActionBarWithoutSelection) &&\n renderSelectionBar()}\n </div>\n );\n};\n"],"names":["_a","id","headers","rows","className","sortIndicators","alternatingRows","loadState","enableMultiSelect","selectedIds","disabledIds","enableActionBar","enableActionBarWithoutSelection","enableSelectAll","enableStickyHeader","emptyView","actionBarContent","renderCustomEmptyView","onHeaderClick","onSelect","onSelectAll","onClearSelectionClick","otherProps","__rest","tableRef","useRef","headerRef","actionBarWrapperRef","wrapperRef","internalId","useId","keyColumns","filter","header","keyColumn","actionBarStrategy","setActionBarStrategy","useState","scrollable","setScrollable","isFloatingActionBar","setIsFloatingActionBar","useApplyStyle","styles.tokens","actionBarWrapperLeft","current","getBoundingClientRect","left","undefined","actionBarWrapperWidth","clientWidth","useUpdateActionBarBehaviour","useEvent","updateActionBarBehaviour","useEffect","updateActionBarBehaviourThrottled","useThrottle","useResizeDetector","targetRef","onResize","useEventListener","isAllCheckboxSelected","length","isRowSelected","rowId","includes","isAlternatingRow","index","isDisabledRow","getDataTestId","subStr","getTotalColumns","getSortDirection","fieldKey","getHeaderAriaSort","sortDirection","getSortButtonAriaLabel","getCellId","getRowCheckboxAriaLabelledBy","keyColumnIds","map","concatIds","wrapperBounds","headerBounds","strategy","scrollHeight","clientHeight","top","window","innerHeight","bottom","Math","max","height","beforeScrollEnd","scrollTop","renderHeaderCell","label","clickable","style","isSortable","headerCellId","getHeaderCellId","_jsxs","clsx","styles.headerCell","styles.headerCellClickable","scope","onClick","handleHeaderClick","children","styles.headerCellContent","_jsx","Typography","BodyBL","weight","renderSortedArrow","VisuallyHidden","event","stopPropagation","handleHeaderButtonClick","isSorted","ArrowUpIcon","ArrowDownIcon","renderHeaderCheckBox","styles.headerCellCheckbox","styles.selectionCheckboxWrapper","Checkbox","checked","indeterminate","disabled","renderRowCell","row","toString","cellData","cellId","cellContent","styles.bodyCellText","isSelected","styles.bodyCell","renderRowCheckBox","styles.bodyCellCheckbox","focusableWhenDisabled","renderBasicEmptyView","emptyTitle","title","HeadingSM","styles.emptyStateTitle","ErrorDisplay","Object","assign","type","description","styles.tableWrapper","styles.tableWrapperScrollable","ref","tabIndex","styles.tableContainer","styles.table","styles.stickyHeader","styles.headerRow","styles.bodyRow","styles.emptyStateCell","colSpan","_Fragment","styles.bodyRowWithBottomBorder","styles.bodyRowAlternating","styles.bodyRowSelectable","styles.bodyRowSelected","styles.loadingStateWrapper","role","LoadingDotsSpinner","count","counter","styles.actionBarWrapper","styles.actionBar","styles.actionBarFloating","BodyMD","BasicButton","styles.actionBarButton","styles.actionBarGap","styles.actionBarSpacer","renderSelectionBar"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"data-table.js","sources":["../../../src/data-table/data-table.tsx"],"sourcesContent":["import { ArrowDownIcon, ArrowUpIcon } from \"@lifesg/react-icons\";\nimport clsx from \"clsx\";\nimport { useEffect, useRef, useState } from \"react\";\nimport { useResizeDetector } from \"react-resize-detector\";\n\nimport { LoadingDotsSpinner } from \"../animations\";\nimport { Checkbox } from \"../checkbox\";\nimport { ErrorDisplay } from \"../error-display\";\nimport { concatIds, VisuallyHidden } from \"../shared/accessibility\";\nimport { BasicButton } from \"../shared/input-wrapper\";\nimport { useApplyStyle } from \"../theme\";\nimport { Typography } from \"../typography\";\nimport { useEvent, useEventListener, useId, useThrottle } from \"../util\";\nimport * as styles from \"./data-table.styles\";\nimport type { DataTableProps, HeaderProps, RowProps } from \"./types\";\n\n// @catalog\n/**\n * Renders a sortable, selectable data table with scroll-aware action bar and loading state support.\n *\n * Use `DataTable` when presenting structured multi-column data that users may need to sort by\n * column or select rows for bulk actions. Row selection, sort indicators, and the action bar\n * content are all externally controlled; the component manages scroll detection, sticky-header\n * positioning, and floating action bar behaviour internally.\n */\nexport const DataTable = ({\n id,\n headers,\n rows,\n className,\n sortIndicators,\n alternatingRows,\n loadState = \"success\",\n enableMultiSelect,\n selectedIds,\n disabledIds,\n enableActionBar,\n enableActionBarWithoutSelection,\n enableSelectAll,\n enableStickyHeader,\n emptyView,\n actionBarContent,\n renderCustomEmptyView,\n onHeaderClick,\n onSelect,\n onSelectAll,\n onClearSelectionClick,\n ...otherProps\n}: DataTableProps) => {\n // =============================================================================\n // CONST, STATE, REF\n // =============================================================================\n const tableRef = useRef<HTMLTableElement>(null);\n const headerRef = useRef<HTMLTableSectionElement>(null);\n const actionBarWrapperRef = useRef<HTMLDivElement>(null);\n const wrapperRef = useRef<HTMLDivElement>(null);\n const internalId = useId();\n const keyColumns = headers.filter(\n (header): header is Exclude<HeaderProps, string> => {\n return typeof header !== \"string\" && !!header.keyColumn;\n }\n );\n\n const [actionBarStrategy, setActionBarStrategy] = useState<\n \"sticky\" | \"fixed\" | \"inline\"\n >(\"inline\");\n const [scrollable, setScrollable] = useState(false);\n const [isFloatingActionBar, setIsFloatingActionBar] = useState(false);\n\n useApplyStyle(actionBarWrapperRef, {\n [styles.tokens.actionBarWrapperLeft]:\n isFloatingActionBar && tableRef.current\n ? `${tableRef.current.getBoundingClientRect().left}px`\n : undefined,\n [styles.tokens.actionBarWrapperWidth]: tableRef.current\n ? `${tableRef.current.clientWidth}px`\n : undefined,\n });\n\n // =============================================================================\n // EFFECTS, EVENT LISTENERS\n // ============================================================================\n const useUpdateActionBarBehaviour = useEvent(() => {\n updateActionBarBehaviour();\n });\n\n useEffect(() => {\n useUpdateActionBarBehaviour();\n }, [useUpdateActionBarBehaviour]);\n\n const updateActionBarBehaviourThrottled = useThrottle(\n () => updateActionBarBehaviour(),\n 100\n );\n\n useResizeDetector({\n targetRef: wrapperRef,\n onResize: () => updateActionBarBehaviourThrottled(),\n });\n\n useEventListener(\"scroll\", updateActionBarBehaviourThrottled);\n useEventListener(\n \"scroll\",\n updateActionBarBehaviourThrottled,\n wrapperRef.current\n );\n\n // ===========================================================================\n // HELPER FUNCTIONS\n // ===========================================================================\n const isAllCheckboxSelected = (): boolean => {\n if (!rows || !rows.length || !selectedIds) {\n return false;\n }\n return selectedIds.length === rows.length;\n };\n\n const isIndeterminateCheckbox = (): boolean => {\n return (\n !!selectedIds &&\n selectedIds.length !== 0 &&\n !isAllCheckboxSelected()\n );\n };\n\n const isHeaderCheckboxDisabled = (): boolean => {\n return !rows || !rows.length;\n };\n\n const isRowSelected = (rowId: string): boolean => {\n return !!selectedIds?.includes(rowId);\n };\n\n const isAlternatingRow = (index: number): boolean => {\n return !!alternatingRows && index % 2 === 1;\n };\n\n const isDisabledRow = (rowId: string): boolean => {\n return !!disabledIds?.includes(rowId);\n };\n\n const getDataTestId = (subStr: string) => {\n if (!otherProps[\"data-testid\"]) return undefined;\n return `${otherProps[\"data-testid\"]}-${subStr}`;\n };\n\n const getTotalColumns = (): number => {\n return headers.length + (enableMultiSelect ? 1 : 0);\n };\n\n const getSortDirection = (fieldKey: string) => {\n return sortIndicators?.[fieldKey];\n };\n\n const getHeaderAriaSort = (fieldKey: string) => {\n const sortDirection = getSortDirection(fieldKey);\n\n if (!sortDirection) {\n return undefined;\n }\n\n return sortDirection === \"asc\" ? \"ascending\" : \"descending\";\n };\n\n const getSortButtonAriaLabel = (fieldKey: string) => {\n const nextSortDirection =\n getSortDirection(fieldKey) === \"asc\" ? \"descending\" : \"ascending\";\n\n return ` by ${nextSortDirection} order`;\n };\n\n const getHeaderCellId = (fieldKey: string) => {\n return `${internalId}-header-${fieldKey}`;\n };\n const getCellId = (rowId: string, fieldKey: string) => {\n return `${internalId}-row-${rowId}-${fieldKey}-key-column`;\n };\n\n const getRowCheckboxAriaLabelledBy = (rowId: string) => {\n const keyColumnIds = keyColumns.map((header) =>\n getCellId(rowId, header.fieldKey)\n );\n\n return concatIds(...keyColumnIds);\n };\n\n const updateActionBarBehaviour = () => {\n if (\n !wrapperRef.current ||\n !headerRef.current ||\n !actionBarWrapperRef.current\n ) {\n return;\n }\n\n const wrapperBounds = wrapperRef.current.getBoundingClientRect();\n const headerBounds = headerRef.current.getBoundingClientRect();\n\n let strategy: typeof actionBarStrategy = \"inline\";\n\n const scrollable =\n wrapperRef.current.scrollHeight > wrapperRef.current.clientHeight;\n\n if (\n wrapperBounds.top > window.innerHeight ||\n wrapperBounds.bottom < 0\n ) {\n // if fully out of the viewport, disable floating\n strategy = \"inline\";\n } else if (scrollable) {\n if (\n wrapperBounds.top > 0 &&\n wrapperBounds.top < window.innerHeight &&\n wrapperBounds.bottom > 0 &&\n wrapperBounds.bottom < window.innerHeight\n ) {\n // if fully in the viewport, use the native sticky behaviour\n strategy = \"sticky\";\n } else if (\n wrapperBounds.top < 0 &&\n wrapperBounds.bottom > 0 &&\n wrapperBounds.bottom < window.innerHeight\n ) {\n // if partially offscreen at the top, use the native sticky behaviour\n strategy = \"sticky\";\n } else if (\n wrapperBounds.bottom > window.innerHeight &&\n Math.max(wrapperBounds.top, headerBounds.bottom) +\n headerBounds.height <\n window.innerHeight\n ) {\n // if offscreen at the bottom, pin to the viewport, up until the table/header\n strategy = \"fixed\";\n }\n } else if (\n wrapperBounds.bottom > window.innerHeight &&\n headerBounds.bottom + headerBounds.height < window.innerHeight\n ) {\n // if offscreen at the bottom, pin to the viewport, up until the header\n strategy = \"fixed\";\n }\n\n setScrollable(scrollable);\n setActionBarStrategy(strategy);\n\n if (strategy === \"fixed\") {\n setIsFloatingActionBar(true);\n } else if (strategy === \"sticky\") {\n const beforeScrollEnd =\n wrapperRef.current.scrollTop + wrapperRef.current.clientHeight <\n wrapperRef.current.scrollHeight;\n setIsFloatingActionBar(beforeScrollEnd);\n } else {\n setIsFloatingActionBar(false);\n }\n };\n\n // =============================================================================\n // EVENT HANDLERS\n // =============================================================================\n const handleHeaderClick = (fieldKey: string) => {\n onHeaderClick?.(fieldKey);\n };\n\n const handleHeaderButtonClick = (\n event: React.MouseEvent<HTMLButtonElement>,\n fieldKey: string\n ) => {\n event.stopPropagation();\n onHeaderClick?.(fieldKey);\n };\n\n // =============================================================================\n // RENDER FUNCTIONS\n // =============================================================================\n const renderHeaders = () => (\n <thead\n ref={headerRef}\n className={enableStickyHeader ? styles.stickyHeader : undefined}\n >\n <tr className={styles.headerRow}>\n {enableMultiSelect && renderHeaderCheckBox()}\n {headers.map(renderHeaderCell)}\n </tr>\n </thead>\n );\n\n const renderHeaderCell = (header: HeaderProps) => {\n const {\n fieldKey,\n label,\n clickable = false,\n style,\n } = typeof header === \"string\"\n ? {\n fieldKey: header,\n label: header,\n style: undefined,\n }\n : header;\n\n const isSortable = !!getSortDirection(fieldKey);\n const headerCellId = getHeaderCellId(fieldKey);\n return (\n <th\n data-testid={getDataTestId(`header-${fieldKey}`)}\n key={fieldKey}\n className={clsx(\n styles.headerCell,\n clickable && styles.headerCellClickable\n )}\n scope=\"col\"\n aria-sort={getHeaderAriaSort(fieldKey)}\n style={style}\n onClick={() => handleHeaderClick(fieldKey)}\n >\n <div className={styles.headerCellContent} id={headerCellId}>\n {typeof label === \"string\" ? (\n <Typography.BodyBL weight=\"bold\">\n {label}\n </Typography.BodyBL>\n ) : (\n label\n )}\n {renderSortedArrow(fieldKey)}\n </div>\n {(clickable || isSortable) && (\n <VisuallyHidden>\n <button\n onClick={(event) =>\n handleHeaderButtonClick(event, fieldKey)\n }\n >\n {isSortable && \"Sort \"}\n <span aria-labelledby={headerCellId} />\n {isSortable && getSortButtonAriaLabel(fieldKey)}\n </button>\n </VisuallyHidden>\n )}\n </th>\n );\n };\n\n const renderSortedArrow = (fieldKey: string) => {\n const isSorted = sortIndicators?.[fieldKey];\n\n if (!isSorted) {\n return <></>;\n }\n if (isSorted === \"asc\") {\n return (\n <ArrowUpIcon\n aria-hidden\n data-testid={getDataTestId(`header-${fieldKey}-arrowup`)}\n />\n );\n }\n return (\n <ArrowDownIcon\n aria-hidden\n data-testid={getDataTestId(`header-${fieldKey}-arrowdown`)}\n />\n );\n };\n\n const renderHeaderCheckBox = () => {\n return (\n <th\n data-testid={getDataTestId(\"header-selection\")}\n className={clsx(styles.headerCell, styles.headerCellCheckbox)}\n scope=\"col\"\n >\n <div className={styles.selectionCheckboxWrapper}>\n <VisuallyHidden>Row selection</VisuallyHidden>\n {enableSelectAll && (\n <Checkbox\n checked={isAllCheckboxSelected()}\n indeterminate={isIndeterminateCheckbox()}\n disabled={isHeaderCheckboxDisabled()}\n aria-label=\"Select all rows\"\n onClick={() => {\n if (onSelectAll) {\n onSelectAll(isAllCheckboxSelected());\n }\n }}\n />\n )}\n </div>\n </th>\n );\n };\n\n const renderRows = () => {\n return !rows || rows.length < 1 ? (\n <tr className={styles.bodyRow}>\n <td\n className={styles.emptyStateCell}\n colSpan={getTotalColumns()}\n >\n {renderCustomEmptyView\n ? renderCustomEmptyView()\n : renderBasicEmptyView()}\n </td>\n </tr>\n ) : (\n <>\n {rows?.map((row: RowProps, index: number) => (\n <tr\n data-testid={getDataTestId(`row-${row.id.toString()}`)}\n key={row.id.toString()}\n className={clsx(\n styles.bodyRow,\n isFloatingActionBar &&\n styles.bodyRowWithBottomBorder,\n isAlternatingRow(index) &&\n styles.bodyRowAlternating,\n enableMultiSelect && styles.bodyRowSelectable,\n isRowSelected(row.id.toString()) &&\n styles.bodyRowSelected\n )}\n >\n {enableMultiSelect && renderRowCheckBox(row)}\n\n {headers.map((header) => renderRowCell(header, row))}\n </tr>\n ))}\n </>\n );\n };\n\n const renderRowCell = (header: HeaderProps, row: RowProps) => {\n const style = typeof header === \"string\" ? undefined : header.style;\n const fieldKey = typeof header === \"string\" ? header : header.fieldKey;\n const rowId = row.id.toString();\n const cellData = row[fieldKey];\n const cellId = `${rowId}-${fieldKey}`;\n\n let cellContent: React.ReactNode;\n if (typeof cellData === \"string\" || typeof cellData === \"number\") {\n cellContent = (\n <Typography.BodyBL className={styles.bodyCellText}>\n {cellData}\n </Typography.BodyBL>\n );\n } else if (typeof cellData === \"function\") {\n cellContent = cellData(row, { isSelected: isRowSelected(rowId) });\n } else {\n cellContent = cellData;\n }\n\n return (\n <td\n data-testid={getDataTestId(`row-${cellId}`)}\n key={cellId}\n id={getCellId(rowId, fieldKey)}\n className={styles.bodyCell}\n style={style}\n >\n {cellContent}\n </td>\n );\n };\n\n const renderRowCheckBox = (row: RowProps) => {\n const rowId = row.id.toString();\n\n return (\n <td\n data-testid={getDataTestId(`row-${rowId}-selection`)}\n className={clsx(styles.bodyCell, styles.bodyCellCheckbox)}\n >\n <div className={styles.selectionCheckboxWrapper}>\n <Checkbox\n checked={isRowSelected(rowId)}\n aria-labelledby={getRowCheckboxAriaLabelledBy(rowId)}\n onClick={() => {\n if (onSelect) {\n onSelect(rowId, !isRowSelected(rowId));\n }\n }}\n disabled={isDisabledRow(rowId)}\n focusableWhenDisabled={isDisabledRow(rowId)}\n />\n </div>\n </td>\n );\n };\n\n const renderBasicEmptyView = () => {\n let emptyTitle: JSX.Element;\n if (!emptyView?.title) {\n emptyTitle = (\n <Typography.HeadingSM\n className={styles.emptyStateTitle}\n weight=\"bold\"\n >\n {\"No <items> found\"}\n </Typography.HeadingSM>\n );\n } else if (typeof emptyView.title === \"string\") {\n emptyTitle = (\n <Typography.HeadingSM\n className={styles.emptyStateTitle}\n weight=\"bold\"\n >\n {emptyView.title}\n </Typography.HeadingSM>\n );\n } else {\n emptyTitle = emptyView.title;\n }\n\n return (\n <ErrorDisplay\n type={\"no-item-found\"}\n {...emptyView}\n title={emptyTitle}\n description={\n emptyView?.description\n ? emptyView.description\n : \"No matching rows\"\n }\n />\n );\n };\n\n const renderLoader = () => {\n return (\n <tr className={styles.bodyRow}>\n <td colSpan={getTotalColumns()}>\n <div\n className={styles.loadingStateWrapper}\n role=\"status\"\n aria-live=\"polite\"\n aria-label=\"Loading table\"\n >\n {loadState === \"loading\" && <LoadingDotsSpinner />}\n </div>\n </td>\n </tr>\n );\n };\n\n const renderSelectionBar = () => {\n const count = selectedIds?.length ?? 0;\n const counter = `item${count === 1 ? \"\" : \"s\"}`;\n\n return (\n <>\n <div\n ref={actionBarWrapperRef}\n className={styles.actionBarWrapper}\n data-strategy={actionBarStrategy}\n >\n <div\n data-testid=\"data-table-action-bar\"\n className={clsx(\n styles.actionBar,\n isFloatingActionBar && styles.actionBarFloating\n )}\n >\n <Typography.BodyMD weight=\"semibold\">{`${count} ${counter} selected`}</Typography.BodyMD>\n {count > 0 ? (\n <BasicButton\n className={styles.actionBarButton}\n type=\"button\"\n aria-label={`Clear selection of ${count} ${counter}`}\n onClick={onClearSelectionClick}\n >\n Clear selection\n </BasicButton>\n ) : (\n <div className={styles.actionBarGap} />\n )}\n {actionBarContent}\n </div>\n </div>\n {/* leave a fixed space when action bar floats to avoid layout shift */}\n {actionBarStrategy !== \"sticky\" && (\n <div className={styles.actionBarSpacer} />\n )}\n </>\n );\n };\n\n return (\n <div\n id={id || \"table-wrapper\"}\n data-testid={otherProps[\"data-testid\"] || \"table\"}\n className={clsx(\n styles.tableWrapper,\n scrollable && styles.tableWrapperScrollable,\n className\n )}\n ref={wrapperRef}\n tabIndex={0} // scrollable container must be focusable to support keyboard users\n >\n <div className={styles.tableContainer}>\n <table ref={tableRef} className={styles.table}>\n {renderHeaders()}\n <tbody>\n {loadState === \"success\"\n ? renderRows()\n : renderLoader()}\n </tbody>\n </table>\n </div>\n {enableActionBar &&\n ((selectedIds && selectedIds.length > 0) ||\n enableActionBarWithoutSelection) &&\n renderSelectionBar()}\n </div>\n );\n};\n"],"names":["_a","id","headers","rows","className","sortIndicators","alternatingRows","loadState","enableMultiSelect","selectedIds","disabledIds","enableActionBar","enableActionBarWithoutSelection","enableSelectAll","enableStickyHeader","emptyView","actionBarContent","renderCustomEmptyView","onHeaderClick","onSelect","onSelectAll","onClearSelectionClick","otherProps","__rest","tableRef","useRef","headerRef","actionBarWrapperRef","wrapperRef","internalId","useId","keyColumns","filter","header","keyColumn","actionBarStrategy","setActionBarStrategy","useState","scrollable","setScrollable","isFloatingActionBar","setIsFloatingActionBar","useApplyStyle","styles.tokens","actionBarWrapperLeft","current","getBoundingClientRect","left","undefined","actionBarWrapperWidth","clientWidth","useUpdateActionBarBehaviour","useEvent","updateActionBarBehaviour","useEffect","updateActionBarBehaviourThrottled","useThrottle","useResizeDetector","targetRef","onResize","useEventListener","isAllCheckboxSelected","length","isRowSelected","rowId","includes","isAlternatingRow","index","isDisabledRow","getDataTestId","subStr","getTotalColumns","getSortDirection","fieldKey","getHeaderAriaSort","sortDirection","getSortButtonAriaLabel","getCellId","getRowCheckboxAriaLabelledBy","keyColumnIds","map","concatIds","wrapperBounds","headerBounds","strategy","scrollHeight","clientHeight","top","window","innerHeight","bottom","Math","max","height","beforeScrollEnd","scrollTop","renderHeaderCell","label","clickable","style","isSortable","headerCellId","getHeaderCellId","_jsxs","clsx","styles.headerCell","styles.headerCellClickable","scope","onClick","handleHeaderClick","children","styles.headerCellContent","_jsx","Typography","BodyBL","weight","renderSortedArrow","VisuallyHidden","event","stopPropagation","handleHeaderButtonClick","isSorted","ArrowUpIcon","ArrowDownIcon","renderHeaderCheckBox","styles.headerCellCheckbox","styles.selectionCheckboxWrapper","Checkbox","checked","indeterminate","disabled","renderRowCell","row","toString","cellData","cellId","cellContent","styles.bodyCellText","isSelected","styles.bodyCell","renderRowCheckBox","styles.bodyCellCheckbox","focusableWhenDisabled","renderBasicEmptyView","emptyTitle","title","HeadingSM","styles.emptyStateTitle","ErrorDisplay","Object","assign","type","description","styles.tableWrapper","styles.tableWrapperScrollable","ref","tabIndex","styles.tableContainer","styles.table","styles.stickyHeader","styles.headerRow","styles.bodyRow","styles.emptyStateCell","colSpan","_Fragment","styles.bodyRowWithBottomBorder","styles.bodyRowAlternating","styles.bodyRowSelectable","styles.bodyRowSelected","styles.loadingStateWrapper","role","LoadingDotsSpinner","count","counter","styles.actionBarWrapper","styles.actionBar","styles.actionBarFloating","BodyMD","BasicButton","styles.actionBarButton","styles.actionBarGap","styles.actionBarSpacer","renderSelectionBar"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"date-range-input.js","sources":["../../../src/date-range-input/date-range-input.tsx"],"sourcesContent":["import clsx from \"clsx\";\nimport dayjs from \"dayjs\";\nimport { useEffect, useRef, useState } from \"react\";\n\nimport type { DropdownRenderProps } from \"../shared/dropdown-wrapper\";\nimport { ElementWithDropdown } from \"../shared/dropdown-wrapper\";\nimport { InputWrapper } from \"../shared/input-wrapper\";\nimport type {\n CalendarAction,\n FocusType,\n InternalCalendarRef,\n} from \"../shared/internal-calendar\";\nimport { CalendarDropdown } from \"../shared/internal-calendar\";\nimport { RangeInputInnerContainer } from \"../shared/range-input-inner-container\";\nimport type { StandaloneDateInputRef } from \"../shared/standalone-date-input/standalone-date-input\";\nimport { StandaloneDateInput } from \"../shared/standalone-date-input/standalone-date-input\";\nimport { DateHelper, DateInputHelper, useContainerQuery } from \"../util\";\nimport { useStateActions } from \"../util/use-state-actions\";\nimport * as styles from \"./date-range-input.styles\";\nimport type { DateRangeInputProps } from \"./types\";\n\ninterface DateRangeInputState {\n initialStart: string;\n initialEnd: string;\n selectedStart: string;\n selectedEnd: string;\n currentFocus: FocusType;\n calendarOpen: boolean;\n isStartDirty: boolean;\n isEndDirty: boolean;\n focused: boolean;\n}\n\nconst INITIAL_STATE: DateRangeInputState = {\n initialStart: \"\",\n initialEnd: \"\",\n selectedStart: \"\",\n selectedEnd: \"\",\n currentFocus: \"none\",\n calendarOpen: false,\n isStartDirty: false,\n isEndDirty: false,\n focused: false,\n};\n\n// @catalog\n/**\n * A paired date input with an attached calendar dropdown that lets users\n * select a contiguous date range.\n */\nexport const DateRangeInput = ({\n minDate,\n maxDate,\n disabled,\n disabledDates,\n error,\n hideInputKeyboard,\n value,\n valueEnd,\n onChange,\n onFocus,\n onBlur,\n onYearMonthDisplayChange,\n withButton = true,\n variant = \"range\",\n numberOfDays = 7,\n readOnly,\n id,\n allowDisabledSelection,\n zIndex,\n dropdownRootNode: rootNode,\n ...otherProps\n}: DateRangeInputProps) => {\n // =============================================================================\n // CONST, STATE, REF\n // =============================================================================\n const [initialCalendarDate, setInitialCalendarDate] = useState<string>();\n const [hoverValue, setHoverValue] = useState<string | undefined>(undefined);\n const isWeekSelection = variant === \"week\";\n const isFixedRangeSelection = variant === \"fixed-range\";\n\n const [isStartDisabled, setIsStartDisabled] = useState<boolean>(false);\n const [isEndDisabled, setIsEndDisabled] = useState<boolean>(false);\n\n const [\n {\n selectedStart,\n selectedEnd,\n currentFocus,\n calendarOpen,\n isStartDirty,\n isEndDirty,\n focused,\n },\n actions,\n ] = useStateActions({\n name: \"date-range-input\",\n initialState: INITIAL_STATE,\n reducers: {\n blur: (state) => ({\n ...state,\n selectedStart: state.initialStart,\n selectedEnd: state.initialEnd,\n currentFocus: \"none\",\n calendarOpen: false,\n isStartDirty: false,\n isEndDirty: false,\n focused: false,\n }),\n dismiss: (state) => ({\n ...state,\n selectedStart: state.initialStart,\n selectedEnd: state.initialEnd,\n currentFocus: \"none\",\n calendarOpen: false,\n isStartDirty: false,\n isEndDirty: false,\n }),\n changeStart: (state, val: string) => ({\n ...state,\n selectedStart: val,\n isStartDirty: true,\n }),\n changeEnd: (state, val: string) => ({\n ...state,\n selectedEnd: val,\n isEndDirty: true,\n }),\n reselectStart: (state) => ({\n ...state,\n selectedStart: \"\",\n currentFocus: \"start\",\n }),\n reselectEnd: (state) => ({\n ...state,\n selectedEnd: \"\",\n currentFocus: \"end\",\n }),\n focus: (state, currentFocus: FocusType) => ({\n ...state,\n currentFocus: isWeekSelection\n ? \"none\"\n : isFixedRangeSelection\n ? \"start\"\n : currentFocus,\n calendarOpen: !readOnly,\n focused: true,\n }),\n cancel: (state) => ({\n ...state,\n selectedStart: state.initialStart,\n selectedEnd: state.initialEnd,\n currentFocus: \"none\",\n calendarOpen: false,\n }),\n done: (state, payload: { start: string; end: string }) => ({\n ...state,\n selectedStart: payload.start,\n selectedEnd: payload.end,\n initialStart: payload.start,\n initialEnd: payload.end,\n currentFocus: \"none\",\n calendarOpen: false,\n isStartDirty: false,\n isEndDirty: false,\n }),\n resetStart: (state) => ({\n ...state,\n selectedStart: state.initialStart,\n }),\n resetEnd: (state) => ({\n ...state,\n selectedEnd: state.initialEnd,\n }),\n resetRange: (state, payload: { start: string; end: string }) => ({\n ...state,\n initialStart: payload.start,\n selectedStart: payload.start,\n initialEnd: payload.end,\n selectedEnd: payload.end,\n }),\n },\n });\n\n // tracks if current value in focused input is allowed for selection\n const isUnselectable = useRef<boolean>(false);\n const nodeRef = useRef<HTMLDivElement>(null);\n const calendarRef = useRef<InternalCalendarRef>(null);\n const startInputRef = useRef<StandaloneDateInputRef>(null);\n const endInputRef = useRef<StandaloneDateInputRef>(null);\n const shouldWrap = useContainerQuery({\n maxWidth: styles.MOBILE_WRAP_WIDTH,\n targetRef: nodeRef,\n });\n\n // =============================================================================\n // EFFECTS\n // =============================================================================\n useEffect(() => {\n actions.resetRange({\n start: DateInputHelper.sanitizeInput(value),\n end: DateInputHelper.sanitizeInput(valueEnd),\n });\n }, [value, valueEnd]);\n\n useEffect(() => {\n if (currentFocus === \"start\") {\n setInitialCalendarDate(selectedStart);\n } else if (currentFocus === \"end\" && selectedEnd) {\n setInitialCalendarDate(selectedEnd);\n }\n }, [currentFocus]);\n\n // =============================================================================\n // EVENT HANDLERS\n // =============================================================================\n const handleNodeKeyDown = (event: React.KeyboardEvent) => {\n if (event.code === \"Enter\" && !withButton) {\n if (selectedStart && selectedEnd) {\n actions.done({\n start: selectedStart,\n end: selectedEnd,\n });\n onChange?.(selectedStart, selectedEnd);\n } else {\n actions.dismiss();\n nodeRef.current?.focus();\n startInputRef.current?.resetPlaceholder();\n endInputRef.current?.resetPlaceholder();\n }\n }\n };\n\n const handleClose = () => {\n actions.blur();\n\n setIsStartDisabled(false);\n setIsEndDisabled(false);\n startInputRef.current?.resetPlaceholder();\n endInputRef.current?.resetPlaceholder();\n\n performOnBlurHandler();\n };\n\n const handleDismiss = () => {\n actions.dismiss();\n\n nodeRef.current?.focus();\n startInputRef.current?.resetPlaceholder();\n endInputRef.current?.resetPlaceholder();\n };\n\n const handleStartDateChange = (val: string) => {\n if (isDateUnselectable(val)) {\n // date is invalid, remain on this input\n isUnselectable.current = true;\n return;\n }\n\n actions.changeStart(val);\n if (val) calendarRef.current?.setCalendarDate(val);\n isUnselectable.current = false;\n\n if (!val) {\n // if both start and end were cleared, confirm the selection\n // and remain on this input\n if (!withButton && !selectedEnd && isEndDirty) {\n actions.resetRange({ start: \"\", end: \"\" });\n onChange?.(\"\", \"\");\n }\n return;\n }\n\n /*\n - if next input is empty, focus it\n - else if date range is invalid, clear and focus the next input\n - else if date range is valid\n - if next input is still pristine, focus it\n - else if !withButton, confirm the selection and \"blur\" the field\n */\n\n if (!selectedEnd) {\n actions.focus(\"end\");\n return;\n }\n\n const isInvalidRange = dayjs(val).isAfter(selectedEnd, \"day\");\n\n if (isInvalidRange) {\n actions.reselectEnd();\n return;\n }\n\n if (!isEndDirty) {\n actions.focus(\"end\");\n return;\n }\n\n if (!withButton) {\n actions.done({ start: val, end: selectedEnd });\n onChange?.(val, selectedEnd);\n return;\n }\n };\n\n const handleEndDateChange = (val: string) => {\n if (isDateUnselectable(val)) {\n // date is invalid, remain on this input\n isUnselectable.current = true;\n return;\n }\n\n const isBeforeStartDate = dayjs(val).isBefore(selectedStart, \"day\");\n\n // if date range is invalid, set selected value as start and reselect end\n if (isBeforeStartDate) {\n actions.changeStart(val);\n calendarRef.current?.setCalendarDate(val);\n actions.reselectEnd();\n return;\n }\n\n actions.changeEnd(val);\n if (val) calendarRef.current?.setCalendarDate(val);\n\n if (!val) {\n // if both start and end were cleared, confirm the selection\n // and remain on this input\n if (!withButton && !selectedStart && isStartDirty) {\n actions.resetRange({ start: \"\", end: \"\" });\n onChange?.(\"\", \"\");\n }\n return;\n }\n\n /*\n - if next input is empty, focus it\n - else if !withButton, confirm the selection and \"blur\" the field\n */\n\n if (!selectedStart) {\n actions.focus(\"start\");\n return;\n }\n\n if (!withButton) {\n endInputRef.current?.focusYearRef();\n\n actions.done({ start: selectedStart, end: val });\n onChange?.(selectedStart, val);\n return;\n }\n };\n\n const handleWeekSelectionChange = (val: string) => {\n const start = dayjs(val).startOf(\"week\").format(\"YYYY-MM-DD\");\n const end = dayjs(val).endOf(\"week\").format(\"YYYY-MM-DD\");\n\n actions.changeStart(start);\n actions.changeEnd(end);\n isUnselectable.current = false;\n\n if (!withButton) {\n endInputRef.current?.focusYearRef();\n\n actions.done({ start, end });\n onChange?.(start, end);\n return;\n }\n };\n\n const handleFixedRangeSelectionChange = (val: string) => {\n if (isDateUnselectable(val)) {\n isUnselectable.current = true;\n return;\n }\n\n actions.changeStart(val);\n calendarRef.current?.setCalendarDate(val);\n isUnselectable.current = false;\n\n if (!val) {\n if (withButton) {\n actions.changeEnd(\"\");\n } else {\n actions.resetRange({ start: \"\", end: \"\" });\n onChange?.(\"\", \"\");\n }\n return;\n }\n\n const start = dayjs(val).format(\"YYYY-MM-DD\");\n const end = dayjs(start)\n .add(numberOfDays - 1, \"day\")\n .format(\"YYYY-MM-DD\");\n actions.changeStart(start);\n actions.changeEnd(end);\n isUnselectable.current = false;\n\n if (!withButton) {\n actions.done({ start, end });\n startInputRef.current?.focusYearRef();\n\n onChange?.(start, end);\n return;\n }\n };\n\n const handleFocus = () => {\n if (isWeekSelection || isFixedRangeSelection) {\n setIsEndDisabled(true);\n }\n\n if (isWeekSelection) {\n setIsStartDisabled(true);\n }\n\n if (readOnly || disabled || focused) return;\n\n actions.focus(\"start\");\n onFocus?.();\n };\n\n const handleBlur = (e: React.FocusEvent) => {\n const target = e.relatedTarget as HTMLElement;\n\n const isInsideCalendar =\n calendarRef.current && calendarRef.current.contains(target);\n const isInsideNode =\n nodeRef.current && nodeRef.current.contains(target);\n const isFloatingElement =\n target?.matches?.(\"[data-floating-ui-focusable]\") ||\n target?.matches?.(\"[data-floating-ui-focus-guard]\");\n\n // Condition when the calendar is closed and focus moved outside the component\n const shouldBlurWhenClosed =\n focused && !calendarOpen && !isInsideNode && !isFloatingElement;\n\n // Condition when the calendar is open, and focus went outside both input and calendar\n const shouldBlurWhenOpenOutside =\n calendarOpen &&\n !isInsideNode &&\n !isInsideCalendar &&\n !isFloatingElement;\n\n if (shouldBlurWhenClosed || shouldBlurWhenOpenOutside) {\n actions.blur();\n\n setIsEndDisabled(false);\n setIsStartDisabled(false);\n\n startInputRef.current?.resetPlaceholder();\n endInputRef.current?.resetPlaceholder();\n\n performOnBlurHandler();\n }\n };\n\n const handleInputFocus =\n (focusType: FocusType) => (event: React.FocusEvent) => {\n event.stopPropagation();\n\n if (readOnly) return;\n\n actions.focus(focusType);\n\n handleWeekSelectionInputFocus();\n handleFixedRangeSelectionInputFocus();\n\n if (!focused) {\n onFocus?.();\n }\n };\n\n const handleWeekSelectionInputFocus = () => {\n if (isWeekSelection) {\n const firstDayOfWeek = DateHelper.toDayjs(selectedStart)\n .startOf(\"week\")\n .format(\"YYYY-MM-DD\");\n\n setIsStartDisabled(true);\n setIsEndDisabled(true);\n setInitialCalendarDate(firstDayOfWeek);\n }\n };\n\n const handleFixedRangeSelectionInputFocus = () => {\n if (isFixedRangeSelection) {\n setIsEndDisabled(true);\n setInitialCalendarDate(selectedStart);\n }\n };\n\n const handleStartInputBlur = (validFormat: boolean) => {\n if (!validFormat || isUnselectable.current) {\n actions.resetStart();\n startInputRef.current?.resetInput();\n }\n };\n\n const handleEndInputBlur = (validFormat: boolean) => {\n if (!validFormat || isUnselectable.current) {\n actions.resetEnd();\n endInputRef.current?.resetInput();\n }\n };\n\n const handleCalendarSelect = (val: string) => {\n switch (variant) {\n case \"week\":\n handleWeekSelectionChange(val);\n break;\n case \"fixed-range\":\n handleFixedRangeSelectionChange(val);\n break;\n default:\n if (currentFocus === \"start\") {\n handleStartDateChange(val);\n } else if (currentFocus === \"end\") {\n handleEndDateChange(val);\n }\n break;\n }\n };\n\n const handleCalendarDismiss = (action: CalendarAction) => {\n nodeRef.current?.focus();\n\n switch (action) {\n case \"reset\":\n actions.cancel();\n break;\n case \"confirmed\":\n actions.done({ start: selectedStart, end: selectedEnd });\n onChange?.(selectedStart, selectedEnd);\n\n if (isWeekSelection) break;\n\n if (isValidRange(selectedStart, selectedEnd)) {\n if (variant === \"range\") {\n endInputRef.current?.focusYearRef();\n } else {\n startInputRef.current?.focusYearRef();\n }\n }\n break;\n }\n };\n\n const handleCalendarHover = (val: string) => {\n setHoverValue(val);\n };\n\n // =============================================================================\n // HELPER FUNCTIONS\n // =============================================================================\n const performOnBlurHandler = () => {\n if (onBlur) {\n onBlur();\n }\n };\n\n const isDateUnselectable = (val: string) => {\n return (\n !allowDisabledSelection &&\n val &&\n DateInputHelper.isDateDisabled(val, {\n disabledDates,\n minDate,\n maxDate,\n })\n );\n };\n\n const isValidRange = (startDate: string, endDate: string) => {\n if (!startDate || !endDate) return false;\n return dayjs(startDate).isBefore(endDate, \"day\");\n };\n\n const getHoverValue = (getValue: Exclude<FocusType, \"none\">) => {\n let values: { start: string | undefined; end: string | undefined } = {\n start: undefined,\n end: undefined,\n };\n\n switch (variant) {\n case \"range\":\n values = {\n start: currentFocus === \"start\" ? hoverValue : undefined,\n end: currentFocus === \"end\" ? hoverValue : undefined,\n };\n break;\n case \"week\":\n if (!hoverValue) return;\n\n values = {\n start: dayjs(hoverValue)\n .startOf(\"week\")\n .format(\"YYYY-MM-DD\"),\n end: dayjs(hoverValue).endOf(\"week\").format(\"YYYY-MM-DD\"),\n };\n break;\n case \"fixed-range\":\n if (!hoverValue) return;\n\n values = {\n start: dayjs(hoverValue).format(\"YYYY-MM-DD\"),\n end: dayjs(hoverValue)\n .add(numberOfDays - 1, \"day\")\n .format(\"YYYY-MM-DD\"),\n };\n break;\n }\n return values[getValue];\n };\n\n // =============================================================================\n // RENDER FUNCTIONS\n // =============================================================================\n const renderInput = () => {\n return (\n <InputWrapper\n role=\"group\"\n ref={nodeRef}\n tabIndex={0}\n onFocus={handleFocus}\n onBlur={handleBlur}\n focused={focused}\n disabled={disabled}\n readOnly={readOnly}\n error={error}\n id={id}\n data-testid={otherProps[\"data-testid\"]}\n aria-disabled={disabled}\n onKeyDown={handleNodeKeyDown}\n {...otherProps}\n className={clsx(\n shouldWrap && !readOnly && styles.containerWrap,\n shouldWrap && readOnly && styles.containerWrapReadOnly,\n otherProps.className\n )}\n >\n <RangeInputInnerContainer\n currentActive={currentFocus}\n wrap={shouldWrap}\n error={error}\n >\n <div\n className={clsx(\n styles.inputContainer,\n shouldWrap && styles.inputContainerWrap\n )}\n >\n <StandaloneDateInput\n ref={startInputRef}\n placeholder=\"From\"\n names={[\"start-day\", \"start-month\", \"start-year\"]}\n inputLabels={[\n \"Start Date\",\n \"Start Month\",\n \"Start Year\",\n ]}\n value={selectedStart}\n disabled={disabled}\n readOnly={isStartDisabled || readOnly}\n focused={currentFocus === \"start\"}\n hoverValue={getHoverValue(\"start\")}\n onChange={\n isFixedRangeSelection\n ? handleFixedRangeSelectionChange\n : handleStartDateChange\n }\n onFocus={handleInputFocus(\"start\")}\n onBlur={handleStartInputBlur}\n hideInputKeyboard={hideInputKeyboard}\n />\n </div>\n <div\n className={clsx(\n styles.inputContainer,\n shouldWrap && styles.inputContainerWrap\n )}\n >\n <StandaloneDateInput\n ref={endInputRef}\n placeholder=\"To\"\n names={[\"end-day\", \"end-month\", \"end-year\"]}\n inputLabels={[\"End Date\", \"End Month\", \"End Year\"]}\n value={selectedEnd}\n disabled={disabled}\n readOnly={isEndDisabled || readOnly}\n focused={currentFocus === \"end\"}\n hoverValue={getHoverValue(\"end\")}\n onChange={handleEndDateChange}\n onFocus={handleInputFocus(\"end\")}\n onBlur={handleEndInputBlur}\n hideInputKeyboard={hideInputKeyboard}\n />\n </div>\n </RangeInputInnerContainer>\n </InputWrapper>\n );\n };\n\n const renderCalendar = ({ elementWidth }: DropdownRenderProps) => {\n return (\n <CalendarDropdown\n ref={calendarRef}\n variant={variant}\n initialCalendarDate={initialCalendarDate}\n withButton={withButton}\n value={selectedStart}\n endValue={selectedEnd}\n selectWithinRange={isStartDirty || isEndDirty}\n currentFocus={currentFocus}\n disabledDates={disabledDates}\n minDate={minDate}\n maxDate={maxDate}\n allowDisabledSelection={allowDisabledSelection}\n onSelect={handleCalendarSelect}\n onDismiss={handleCalendarDismiss}\n onHover={handleCalendarHover}\n onYearMonthDisplayChange={onYearMonthDisplayChange}\n numberOfDays={numberOfDays}\n width={elementWidth}\n isFocusable={!readOnly && !disabled}\n />\n );\n };\n\n return (\n <ElementWithDropdown\n enabled={!readOnly && !disabled}\n isOpen={calendarOpen}\n onClose={handleClose}\n onDismiss={handleDismiss}\n renderElement={renderInput}\n renderDropdown={renderCalendar}\n customZIndex={zIndex}\n offset={16}\n rootNode={rootNode}\n />\n );\n};\n"],"names":["INITIAL_STATE","initialStart","initialEnd","selectedStart","selectedEnd","currentFocus","calendarOpen","isStartDirty","isEndDirty","focused","_a","minDate","maxDate","disabled","disabledDates","error","hideInputKeyboard","value","valueEnd","onChange","onFocus","onBlur","onYearMonthDisplayChange","withButton","variant","numberOfDays","readOnly","id","allowDisabledSelection","zIndex","dropdownRootNode","rootNode","otherProps","__rest","initialCalendarDate","setInitialCalendarDate","useState","hoverValue","setHoverValue","undefined","isWeekSelection","isFixedRangeSelection","isStartDisabled","setIsStartDisabled","isEndDisabled","setIsEndDisabled","actions","useStateActions","name","initialState","reducers","blur","state","dismiss","Object","assign","changeStart","val","changeEnd","reselectStart","reselectEnd","focus","cancel","done","payload","start","end","resetStart","resetEnd","resetRange","isUnselectable","useRef","nodeRef","calendarRef","startInputRef","endInputRef","shouldWrap","useContainerQuery","maxWidth","styles.MOBILE_WRAP_WIDTH","targetRef","useEffect","DateInputHelper","sanitizeInput","handleNodeKeyDown","event","code","current","_b","resetPlaceholder","_c","handleStartDateChange","isDateUnselectable","setCalendarDate","dayjs","isAfter","handleEndDateChange","isBefore","focusYearRef","handleFixedRangeSelectionChange","format","add","handleFocus","handleBlur","e","target","relatedTarget","isInsideCalendar","contains","isInsideNode","isFloatingElement","matches","call","_d","performOnBlurHandler","handleInputFocus","focusType","stopPropagation","handleWeekSelectionInputFocus","handleFixedRangeSelectionInputFocus","firstDayOfWeek","DateHelper","toDayjs","startOf","handleStartInputBlur","validFormat","resetInput","handleEndInputBlur","handleCalendarSelect","endOf","handleWeekSelectionChange","handleCalendarDismiss","action","isValidRange","handleCalendarHover","isDateDisabled","startDate","endDate","getHoverValue","getValue","values","_jsx","ElementWithDropdown","enabled","isOpen","onClose","onDismiss","renderElement","InputWrapper","role","ref","tabIndex","onKeyDown","className","clsx","styles.containerWrap","styles.containerWrapReadOnly","_jsxs","RangeInputInnerContainer","currentActive","wrap","children","styles.inputContainer","styles.inputContainerWrap","StandaloneDateInput","placeholder","names","inputLabels","renderDropdown","elementWidth","CalendarDropdown","endValue","selectWithinRange","onSelect","onHover","width","isFocusable","customZIndex","offset"],"mappings":"w/BAiCA,MAAMA,EAAqC,CACvCC,aAAc,GACdC,WAAY,GACZC,cAAe,GACfC,YAAa,GACbC,aAAc,OACdC,cAAc,EACdC,cAAc,EACdC,YAAY,EACZC,SAAS,0BAQkBC,QAAAC,QAC3BA,EAAOC,QACPA,EAAOC,SACPA,EAAQC,cACRA,EAAaC,MACbA,EAAKC,kBACLA,EAAiBC,MACjBA,EAAKC,SACLA,EAAQC,SACRA,EAAQC,QACRA,EAAOC,OACPA,EAAMC,yBACNA,EAAwBC,WACxBA,GAAa,EAAIC,QACjBA,EAAU,QAAOC,aACjBA,EAAe,EAACC,SAChBA,EAAQC,GACRA,EAAEC,uBACFA,EAAsBC,OACtBA,EACAC,iBAAkBC,KACfC,EAAUC,EAAAA,OAAAvB,EArBc,CAAA,UAAA,UAAA,WAAA,gBAAA,QAAA,oBAAA,QAAA,WAAA,WAAA,UAAA,SAAA,2BAAA,aAAA,UAAA,eAAA,WAAA,KAAA,yBAAA,SAAA,qBA0B3B,MAAOwB,EAAqBC,GAA0BC,cAC/CC,EAAYC,GAAiBF,EAAAA,cAA6BG,GAC3DC,EAA8B,SAAZhB,EAClBiB,EAAoC,gBAAZjB,GAEvBkB,EAAiBC,GAAsBP,EAAAA,UAAkB,IACzDQ,EAAeC,GAAoBT,EAAAA,UAAkB,KAGxDjC,cACIA,EAAaC,YACbA,EAAWC,aACXA,EAAYC,aACZA,EAAYC,aACZA,EAAYC,WACZA,EAAUC,QACVA,IAEJqC,IACAC,EAAAA,gBAAgB,CAChBC,KAAM,mBACNC,aAAcjD,EACdkD,SAAU,CACNC,KAAOC,kCACAA,GAAK,CACRjD,cAAeiD,EAAMnD,aACrBG,YAAagD,EAAMlD,WACnBG,aAAc,OACdC,cAAc,EACdC,cAAc,EACdC,YAAY,EACZC,SAAS,IAEb4C,QAAUD,GAAUE,OAAAC,OAAAD,OAAAC,OAAA,CAAA,EACbH,GAAK,CACRjD,cAAeiD,EAAMnD,aACrBG,YAAagD,EAAMlD,WACnBG,aAAc,OACdC,cAAc,EACdC,cAAc,EACdC,YAAY,IAEhBgD,YAAa,CAACJ,EAAOK,IAAgBH,OAAAC,OAAAD,OAAAC,OAAA,CAAA,EAC9BH,GAAK,CACRjD,cAAesD,EACflD,cAAc,IAElBmD,UAAW,CAACN,EAAOK,IAAgBH,OAAAC,OAAAD,OAAAC,OAAA,CAAA,EAC5BH,GAAK,CACRhD,YAAaqD,EACbjD,YAAY,IAEhBmD,cAAgBP,GAAUE,OAAAC,OAAAD,OAAAC,OAAA,CAAA,EACnBH,GAAK,CACRjD,cAAe,GACfE,aAAc,UAElBuD,YAAcR,GAAUE,OAAAC,OAAAD,OAAAC,OAAA,CAAA,EACjBH,GAAK,CACRhD,YAAa,GACbC,aAAc,QAElBwD,MAAO,CAACT,EAAO/C,IAA4BiD,OAAAC,OAAAD,OAAAC,OAAA,CAAA,EACpCH,GAAK,CACR/C,aAAcmC,EACR,OACAC,EACA,QACApC,EACNC,cAAeoB,EACfjB,SAAS,IAEbqD,OAASV,GAAUE,OAAAC,OAAAD,OAAAC,OAAA,CAAA,EACZH,GAAK,CACRjD,cAAeiD,EAAMnD,aACrBG,YAAagD,EAAMlD,WACnBG,aAAc,OACdC,cAAc,IAElByD,KAAM,CAACX,EAAOY,IAA4CV,OAAAC,OAAAD,OAAAC,OAAA,CAAA,EACnDH,GAAK,CACRjD,cAAe6D,EAAQC,MACvB7D,YAAa4D,EAAQE,IACrBjE,aAAc+D,EAAQC,MACtB/D,WAAY8D,EAAQE,IACpB7D,aAAc,OACdC,cAAc,EACdC,cAAc,EACdC,YAAY,IAEhB2D,WAAaf,GAAUE,OAAAC,OAAAD,OAAAC,OAAA,GAChBH,GAAK,CACRjD,cAAeiD,EAAMnD,eAEzBmE,SAAWhB,GAAUE,OAAAC,OAAAD,OAAAC,OAAA,GACdH,GAAK,CACRhD,YAAagD,EAAMlD,aAEvBmE,WAAY,CAACjB,EAAOY,IAA4CV,OAAAC,OAAAD,OAAAC,OAAA,CAAA,EACzDH,GAAK,CACRnD,aAAc+D,EAAQC,MACtB9D,cAAe6D,EAAQC,MACvB/D,WAAY8D,EAAQE,IACpB9D,YAAa4D,EAAQE,SAM3BI,GAAiBC,EAAAA,QAAgB,GACjCC,GAAUD,EAAAA,OAAuB,MACjCE,GAAcF,EAAAA,OAA4B,MAC1CG,GAAgBH,EAAAA,OAA+B,MAC/CI,GAAcJ,EAAAA,OAA+B,MAC7CK,GAAaC,EAAAA,kBAAkB,CACjCC,SAAUC,EAAAA,kBACVC,UAAWR,KAMfS,EAAAA,WAAU,KACNnC,GAAQuB,WAAW,CACfJ,MAAOiB,EAAAA,gBAAgBC,cAAclE,GACrCiD,IAAKgB,EAAAA,gBAAgBC,cAAcjE,IACrC,GACH,CAACD,EAAOC,IAEX+D,EAAAA,WAAU,KACe,UAAjB5E,EACA8B,EAAuBhC,GACC,QAAjBE,GAA0BD,GACjC+B,EAAuB/B,EAC3B,GACD,CAACC,IAKJ,MAAM+E,GAAqBC,cACJ,UAAfA,EAAMC,MAAqB/D,IACvBpB,GAAiBC,GACjB0C,GAAQiB,KAAK,CACTE,MAAO9D,EACP+D,IAAK9D,IAETe,SAAAA,EAAWhB,EAAeC,KAE1B0C,GAAQO,UACO,QAAf3C,EAAA8D,GAAQe,eAAO,IAAA7E,GAAAA,EAAEmD,QACI,QAArB2B,EAAAd,GAAca,eAAO,IAAAC,GAAAA,EAAEC,mBACJ,QAAnBC,EAAAf,GAAYY,eAAO,IAAAG,GAAAA,EAAED,oBAE7B,EAsBEE,GAAyBlC,UAC3B,GAAImC,GAAmBnC,GAGnB,YADAa,GAAeiB,SAAU,GAQ7B,GAJAzC,GAAQU,YAAYC,GAChBA,IAAwB,QAAnB/C,EAAA+D,GAAYc,eAAO,IAAA7E,GAAAA,EAAEmF,gBAAgBpC,IAC9Ca,GAAeiB,SAAU,GAEpB9B,EAOD,YAJKlC,GAAenB,IAAeI,IAC/BsC,GAAQuB,WAAW,CAAEJ,MAAO,GAAIC,IAAK,KACrC/C,SAAAA,EAAW,GAAI,MAavB,IAAKf,EAED,YADA0C,GAAQe,MAAM,OAMlB,GAFuBiC,EAAAA,QAAMrC,GAAKsC,QAAQ3F,EAAa,OAGnD0C,GAAQc,kBADZ,CAKA,GAAKpD,EAKL,OAAKe,OAAL,GACIuB,GAAQiB,KAAK,CAAEE,MAAOR,EAAKS,IAAK9D,SAChCe,SAAAA,EAAWsC,EAAKrD,KANhB0C,GAAQe,MAAM,MAHlB,CAWA,EAGEmC,GAAuBvC,cACzB,GAAImC,GAAmBnC,GAGnB,YADAa,GAAeiB,SAAU,GAO7B,GAH0BO,EAAAA,QAAMrC,GAAKwC,SAAS9F,EAAe,OAOzD,OAHA2C,GAAQU,YAAYC,GACD,QAAnB/C,EAAA+D,GAAYc,eAAO,IAAA7E,GAAAA,EAAEmF,gBAAgBpC,QACrCX,GAAQc,cAOZ,GAHAd,GAAQY,UAAUD,GACdA,IAAwB,QAAnB+B,EAAAf,GAAYc,eAAO,IAAAC,GAAAA,EAAEK,gBAAgBpC,IAEzCA,EAAL,CAeA,GAAKtD,EAKL,OAAKoB,OAAL,GACuB,QAAnBmE,EAAAf,GAAYY,eAAO,IAAAG,GAAAA,EAAEQ,eAErBpD,GAAQiB,KAAK,CAAEE,MAAO9D,EAAe+D,IAAKT,SAC1CtC,SAAAA,EAAWhB,EAAesD,KAR1BX,GAAQe,MAAM,QARlB,MALStC,GAAepB,IAAiBI,IACjCuC,GAAQuB,WAAW,CAAEJ,MAAO,GAAIC,IAAK,KACrC/C,SAAAA,EAAW,GAAI,IAqBvB,EAoBEgF,GAAmC1C,YACrC,GAAImC,GAAmBnC,GAEnB,YADAa,GAAeiB,SAAU,GAQ7B,GAJAzC,GAAQU,YAAYC,GACD,QAAnB/C,EAAA+D,GAAYc,eAAO,IAAA7E,GAAAA,EAAEmF,gBAAgBpC,GACrCa,GAAeiB,SAAU,GAEpB9B,EAOD,YANIlC,EACAuB,GAAQY,UAAU,KAElBZ,GAAQuB,WAAW,CAAEJ,MAAO,GAAIC,IAAK,KACrC/C,SAAAA,EAAW,GAAI,MAKvB,MAAM8C,EAAQ6B,EAAAA,QAAMrC,GAAK2C,OAAO,cAC1BlC,EAAM4B,EAAAA,QAAM7B,GACboC,IAAI5E,EAAe,EAAG,OACtB2E,OAAO,cAKZ,OAJAtD,GAAQU,YAAYS,GACpBnB,GAAQY,UAAUQ,GAClBI,GAAeiB,SAAU,EAEpBhE,OAAL,GACIuB,GAAQiB,KAAK,CAAEE,QAAOC,QACD,QAArBsB,EAAAd,GAAca,eAAO,IAAAC,GAAAA,EAAEU,oBAEvB/E,SAAAA,EAAW8C,EAAOC,IAEtB,EAGEoC,GAAc,MACZ9D,GAAmBC,IACnBI,GAAiB,GAGjBL,GACAG,GAAmB,GAGnBjB,GAAYb,GAAYJ,KAE5BqC,GAAQe,MAAM,SACdzC,SAAAA,IAAW,EAGTmF,GAAcC,gBAChB,MAAMC,EAASD,EAAEE,cAEXC,EACFlC,GAAYc,SAAWd,GAAYc,QAAQqB,SAASH,GAClDI,EACFrC,GAAQe,SAAWf,GAAQe,QAAQqB,SAASH,GAC1CK,GACa,QAAfpG,EAAA+F,aAAM,EAANA,EAAQM,eAAO,IAAArG,OAAA,EAAAA,EAAAsG,KAAAP,EAAG,mCACH,QAAfjB,EAAAiB,aAAM,EAANA,EAAQM,eAAO,IAAAvB,OAAA,EAAAA,EAAAwB,KAAAP,EAAG,oCAIlBhG,KAAYH,IAAiBuG,IAAiBC,GAI9CxG,IACCuG,IACAF,IACAG,KAGDhE,GAAQK,OAERN,GAAiB,GACjBF,GAAmB,GAEE,QAArB+C,EAAAhB,GAAca,eAAO,IAAAG,GAAAA,EAAED,mBACJ,QAAnBwB,EAAAtC,GAAYY,eAAO,IAAA0B,GAAAA,EAAExB,mBAErByB,KACJ,EAGEC,GACDC,GAA0B/B,IACvBA,EAAMgC,kBAEF3F,IAEJoB,GAAQe,MAAMuD,GAEdE,KACAC,KAEK9G,IACDW,SAAAA,IACJ,EAGFkG,GAAgC,KAClC,GAAI9E,EAAiB,CACjB,MAAMgF,EAAiBC,aAAWC,QAAQvH,GACrCwH,QAAQ,QACRvB,OAAO,cAEZzD,GAAmB,GACnBE,GAAiB,GACjBV,EAAuBqF,EAC3B,GAGED,GAAsC,KACpC9E,IACAI,GAAiB,GACjBV,EAAuBhC,GAC3B,EAGEyH,GAAwBC,UACrBA,IAAevD,GAAeiB,UAC/BzC,GAAQqB,aACa,QAArBzD,EAAAgE,GAAca,eAAO,IAAA7E,GAAAA,EAAEoH,aAC3B,EAGEC,GAAsBF,UACnBA,IAAevD,GAAeiB,UAC/BzC,GAAQsB,WACW,QAAnB1D,EAAAiE,GAAYY,eAAO,IAAA7E,GAAAA,EAAEoH,aACzB,EAGEE,GAAwBvE,IAC1B,OAAQjC,GACJ,IAAK,OA3JqB,CAACiC,UAC/B,MAAMQ,EAAQ6B,EAAAA,QAAMrC,GAAKkE,QAAQ,QAAQvB,OAAO,cAC1ClC,EAAM4B,EAAAA,QAAMrC,GAAKwE,MAAM,QAAQ7B,OAAO,cAM5C,GAJAtD,GAAQU,YAAYS,GACpBnB,GAAQY,UAAUQ,GAClBI,GAAeiB,SAAU,GAEpBhE,EACkB,QAAnBb,EAAAiE,GAAYY,eAAO,IAAA7E,GAAAA,EAAEwF,eAErBpD,GAAQiB,KAAK,CAAEE,QAAOC,QACtB/C,SAAAA,EAAW8C,EAAOC,EAEtB,EA8IQgE,CAA0BzE,GAC1B,MACJ,IAAK,cACD0C,GAAgC1C,GAChC,MACJ,QACyB,UAAjBpD,EACAsF,GAAsBlC,GACE,QAAjBpD,GACP2F,GAAoBvC,KAM9B0E,GAAyBC,cAG3B,OAFe,QAAf1H,EAAA8D,GAAQe,eAAO,IAAA7E,GAAAA,EAAEmD,QAETuE,GACJ,IAAK,QACDtF,GAAQgB,SACR,MACJ,IAAK,YAID,GAHAhB,GAAQiB,KAAK,CAAEE,MAAO9D,EAAe+D,IAAK9D,IAC1Ce,SAAAA,EAAWhB,EAAeC,GAEtBoC,EAAiB,MAEjB6F,GAAalI,EAAeC,KACZ,UAAZoB,EACmB,QAAnBgE,EAAAb,GAAYY,eAAO,IAAAC,GAAAA,EAAEU,eAEA,QAArBR,EAAAhB,GAAca,eAAO,IAAAG,GAAAA,EAAEQ,kBAOrCoC,GAAuB7E,IACzBnB,EAAcmB,EAAI,EAMhByD,GAAuB,KACrB7F,GACAA,GACJ,EAGEuE,GAAsBnC,IAEnB7B,GACD6B,GACAyB,EAAAA,gBAAgBqD,eAAe9E,EAAK,CAChC3C,gBACAH,UACAC,YAKNyH,GAAe,CAACG,EAAmBC,OAChCD,IAAcC,IACZ3C,EAAAA,QAAM0C,GAAWvC,SAASwC,EAAS,OAGxCC,GAAiBC,IACnB,IAAIC,EAAiE,CACjE3E,WAAO1B,EACP2B,SAAK3B,GAGT,OAAQf,GACJ,IAAK,QACDoH,EAAS,CACL3E,MAAwB,UAAjB5D,EAA2BgC,OAAaE,EAC/C2B,IAAsB,QAAjB7D,EAAyBgC,OAAaE,GAE/C,MACJ,IAAK,OACD,IAAKF,EAAY,OAEjBuG,EAAS,CACL3E,MAAO6B,EAAAA,QAAMzD,GACRsF,QAAQ,QACRvB,OAAO,cACZlC,IAAK4B,EAAAA,QAAMzD,GAAY4F,MAAM,QAAQ7B,OAAO,eAEhD,MACJ,IAAK,cACD,IAAK/D,EAAY,OAEjBuG,EAAS,CACL3E,MAAO6B,EAAAA,QAAMzD,GAAY+D,OAAO,cAChClC,IAAK4B,EAAAA,QAAMzD,GACNgE,IAAI5E,EAAe,EAAG,OACtB2E,OAAO,eAIxB,OAAOwC,EAAOD,EAAS,EAqH3B,OACIE,MAACC,EAAAA,oBAAmB,CAChBC,SAAUrH,IAAab,EACvBmI,OAAQ1I,EACR2I,QArfY,aAChBnG,GAAQK,OAERR,GAAmB,GACnBE,GAAiB,GACI,QAArBnC,EAAAgE,GAAca,eAAO,IAAA7E,GAAAA,EAAE+E,mBACJ,QAAnBD,EAAAb,GAAYY,eAAO,IAAAC,GAAAA,EAAEC,mBAErByB,IAAsB,EA8elBgC,UA3ec,eAClBpG,GAAQO,UAEO,QAAf3C,EAAA8D,GAAQe,eAAO,IAAA7E,GAAAA,EAAEmD,QACI,QAArB2B,EAAAd,GAAca,eAAO,IAAAC,GAAAA,EAAEC,mBACJ,QAAnBC,EAAAf,GAAYY,eAAO,IAAAG,GAAAA,EAAED,kBAAkB,EAuenC0D,cArHY,IAEZN,EAAAA,IAACO,EAAAA,aAAY9F,OAAAC,OAAA,CACT8F,KAAK,QACLC,IAAK9E,GACL+E,SAAU,EACVnI,QAASkF,GACTjF,OAAQkF,GACR9F,QAASA,GACTI,SAAUA,EACVa,SAAUA,EACVX,MAAOA,EACPY,GAAIA,EAAE,cACOK,EAAW,eAAc,gBACvBnB,EACf2I,UAAWpE,IACPpD,GACJyH,UAAWC,EAAAA,QACP9E,KAAelD,GAAYiI,EAAAA,cAC3B/E,IAAclD,GAAYkI,wBAC1B5H,EAAWyH,oBAGfI,EAAAA,KAACC,EAAAA,yBAAwB,CACrBC,cAAe1J,EACf2J,KAAMpF,GACN7D,MAAOA,EAAKkJ,SAAA,CAEZpB,EAAAA,IAAA,MAAA,CACIY,UAAWC,EAAAA,QACPQ,EAAAA,eACAtF,IAAcuF,EAAAA,oBACjBF,SAEDpB,EAAAA,IAACuB,EAAAA,oBAAmB,CAChBd,IAAK5E,GACL2F,YAAY,OACZC,MAAO,CAAC,YAAa,cAAe,cACpCC,YAAa,CACT,aACA,cACA,cAEJtJ,MAAOd,EACPU,SAAUA,EACVa,SAAUgB,GAAmBhB,EAC7BjB,QAA0B,UAAjBJ,EACTgC,WAAYqG,GAAc,SAC1BvH,SACIsB,EACM0D,GACAR,GAEVvE,QAAS+F,GAAiB,SAC1B9F,OAAQuG,GACR5G,kBAAmBA,MAG3B6H,EAAAA,IAAA,MAAA,CACIY,UAAWC,EAAAA,QACPQ,EAAAA,eACAtF,IAAcuF,EAAAA,oBACjBF,SAEDpB,EAAAA,IAACuB,EAAAA,oBAAmB,CAChBd,IAAK3E,GACL0F,YAAY,KACZC,MAAO,CAAC,UAAW,YAAa,YAChCC,YAAa,CAAC,WAAY,YAAa,YACvCtJ,MAAOb,EACPS,SAAUA,EACVa,SAAUkB,GAAiBlB,EAC3BjB,QAA0B,QAAjBJ,EACTgC,WAAYqG,GAAc,OAC1BvH,SAAU6E,GACV5E,QAAS+F,GAAiB,OAC1B9F,OAAQ0G,GACR/G,kBAAmBA,YAyCnCwJ,eAjCe,EAAGC,kBAElB5B,EAAAA,IAAC6B,oBACGpB,IAAK7E,GACLjD,QAASA,EACTU,oBAAqBA,EACrBX,WAAYA,EACZN,MAAOd,EACPwK,SAAUvK,EACVwK,kBAAmBrK,GAAgBC,EACnCH,aAAcA,EACdS,cAAeA,EACfH,QAASA,EACTC,QAASA,EACTgB,uBAAwBA,EACxBiJ,SAAU7C,GACVkB,UAAWf,GACX2C,QAASxC,GACThH,yBAA0BA,EAC1BG,aAAcA,EACdsJ,MAAON,EACPO,aAActJ,IAAab,IAa/BoK,aAAcpJ,EACdqJ,OAAQ,GACRnJ,SAAUA,GACZ"}
|
|
1
|
+
{"version":3,"file":"date-range-input.js","sources":["../../../src/date-range-input/date-range-input.tsx"],"sourcesContent":["import clsx from \"clsx\";\nimport dayjs from \"dayjs\";\nimport { useEffect, useRef, useState } from \"react\";\n\nimport type { DropdownRenderProps } from \"../shared/dropdown-wrapper\";\nimport { ElementWithDropdown } from \"../shared/dropdown-wrapper\";\nimport { InputWrapper } from \"../shared/input-wrapper\";\nimport type {\n CalendarAction,\n FocusType,\n InternalCalendarRef,\n} from \"../shared/internal-calendar\";\nimport { CalendarDropdown } from \"../shared/internal-calendar\";\nimport { RangeInputInnerContainer } from \"../shared/range-input-inner-container\";\nimport type { StandaloneDateInputRef } from \"../shared/standalone-date-input/standalone-date-input\";\nimport { StandaloneDateInput } from \"../shared/standalone-date-input/standalone-date-input\";\nimport { DateHelper, DateInputHelper, useContainerQuery } from \"../util\";\nimport { useStateActions } from \"../util/use-state-actions\";\nimport * as styles from \"./date-range-input.styles\";\nimport type { DateRangeInputProps } from \"./types\";\n\ninterface DateRangeInputState {\n initialStart: string;\n initialEnd: string;\n selectedStart: string;\n selectedEnd: string;\n currentFocus: FocusType;\n calendarOpen: boolean;\n isStartDirty: boolean;\n isEndDirty: boolean;\n focused: boolean;\n}\n\nconst INITIAL_STATE: DateRangeInputState = {\n initialStart: \"\",\n initialEnd: \"\",\n selectedStart: \"\",\n selectedEnd: \"\",\n currentFocus: \"none\",\n calendarOpen: false,\n isStartDirty: false,\n isEndDirty: false,\n focused: false,\n};\n\n// @catalog\n/**\n * A paired date input with an attached calendar dropdown that lets users\n * select a contiguous date range.\n */\nexport const DateRangeInput = ({\n minDate,\n maxDate,\n disabled,\n disabledDates,\n error,\n hideInputKeyboard,\n value,\n valueEnd,\n onChange,\n onFocus,\n onBlur,\n onYearMonthDisplayChange,\n withButton = true,\n variant = \"range\",\n numberOfDays = 7,\n readOnly,\n id,\n allowDisabledSelection,\n zIndex,\n dropdownRootNode: rootNode,\n ...otherProps\n}: DateRangeInputProps) => {\n // =============================================================================\n // CONST, STATE, REF\n // =============================================================================\n const [initialCalendarDate, setInitialCalendarDate] = useState<string>();\n const [hoverValue, setHoverValue] = useState<string | undefined>(undefined);\n const isWeekSelection = variant === \"week\";\n const isFixedRangeSelection = variant === \"fixed-range\";\n\n const [isStartDisabled, setIsStartDisabled] = useState<boolean>(false);\n const [isEndDisabled, setIsEndDisabled] = useState<boolean>(false);\n\n const [\n {\n selectedStart,\n selectedEnd,\n currentFocus,\n calendarOpen,\n isStartDirty,\n isEndDirty,\n focused,\n },\n actions,\n ] = useStateActions({\n name: \"date-range-input\",\n initialState: INITIAL_STATE,\n reducers: {\n blur: (state) => ({\n ...state,\n selectedStart: state.initialStart,\n selectedEnd: state.initialEnd,\n currentFocus: \"none\",\n calendarOpen: false,\n isStartDirty: false,\n isEndDirty: false,\n focused: false,\n }),\n dismiss: (state) => ({\n ...state,\n selectedStart: state.initialStart,\n selectedEnd: state.initialEnd,\n currentFocus: \"none\",\n calendarOpen: false,\n isStartDirty: false,\n isEndDirty: false,\n }),\n changeStart: (state, val: string) => ({\n ...state,\n selectedStart: val,\n isStartDirty: true,\n }),\n changeEnd: (state, val: string) => ({\n ...state,\n selectedEnd: val,\n isEndDirty: true,\n }),\n reselectStart: (state) => ({\n ...state,\n selectedStart: \"\",\n currentFocus: \"start\",\n }),\n reselectEnd: (state) => ({\n ...state,\n selectedEnd: \"\",\n currentFocus: \"end\",\n }),\n focus: (state, currentFocus: FocusType) => ({\n ...state,\n currentFocus: isWeekSelection\n ? \"none\"\n : isFixedRangeSelection\n ? \"start\"\n : currentFocus,\n calendarOpen: !readOnly,\n focused: true,\n }),\n cancel: (state) => ({\n ...state,\n selectedStart: state.initialStart,\n selectedEnd: state.initialEnd,\n currentFocus: \"none\",\n calendarOpen: false,\n }),\n done: (state, payload: { start: string; end: string }) => ({\n ...state,\n selectedStart: payload.start,\n selectedEnd: payload.end,\n initialStart: payload.start,\n initialEnd: payload.end,\n currentFocus: \"none\",\n calendarOpen: false,\n isStartDirty: false,\n isEndDirty: false,\n }),\n resetStart: (state) => ({\n ...state,\n selectedStart: state.initialStart,\n }),\n resetEnd: (state) => ({\n ...state,\n selectedEnd: state.initialEnd,\n }),\n resetRange: (state, payload: { start: string; end: string }) => ({\n ...state,\n initialStart: payload.start,\n selectedStart: payload.start,\n initialEnd: payload.end,\n selectedEnd: payload.end,\n }),\n },\n });\n\n // tracks if current value in focused input is allowed for selection\n const isUnselectable = useRef<boolean>(false);\n const nodeRef = useRef<HTMLDivElement>(null);\n const calendarRef = useRef<InternalCalendarRef>(null);\n const startInputRef = useRef<StandaloneDateInputRef>(null);\n const endInputRef = useRef<StandaloneDateInputRef>(null);\n const shouldWrap = useContainerQuery({\n maxWidth: styles.MOBILE_WRAP_WIDTH,\n targetRef: nodeRef,\n });\n\n // =============================================================================\n // EFFECTS\n // =============================================================================\n useEffect(() => {\n actions.resetRange({\n start: DateInputHelper.sanitizeInput(value),\n end: DateInputHelper.sanitizeInput(valueEnd),\n });\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [value, valueEnd]);\n\n useEffect(() => {\n if (currentFocus === \"start\") {\n setInitialCalendarDate(selectedStart);\n } else if (currentFocus === \"end\" && selectedEnd) {\n setInitialCalendarDate(selectedEnd);\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [currentFocus]);\n\n // =============================================================================\n // EVENT HANDLERS\n // =============================================================================\n const handleNodeKeyDown = (event: React.KeyboardEvent) => {\n if (event.code === \"Enter\" && !withButton) {\n if (selectedStart && selectedEnd) {\n actions.done({\n start: selectedStart,\n end: selectedEnd,\n });\n onChange?.(selectedStart, selectedEnd);\n } else {\n actions.dismiss();\n nodeRef.current?.focus();\n startInputRef.current?.resetPlaceholder();\n endInputRef.current?.resetPlaceholder();\n }\n }\n };\n\n const handleClose = () => {\n actions.blur();\n\n setIsStartDisabled(false);\n setIsEndDisabled(false);\n startInputRef.current?.resetPlaceholder();\n endInputRef.current?.resetPlaceholder();\n\n performOnBlurHandler();\n };\n\n const handleDismiss = () => {\n actions.dismiss();\n\n nodeRef.current?.focus();\n startInputRef.current?.resetPlaceholder();\n endInputRef.current?.resetPlaceholder();\n };\n\n const handleStartDateChange = (val: string) => {\n if (isDateUnselectable(val)) {\n // date is invalid, remain on this input\n isUnselectable.current = true;\n return;\n }\n\n actions.changeStart(val);\n if (val) calendarRef.current?.setCalendarDate(val);\n isUnselectable.current = false;\n\n if (!val) {\n // if both start and end were cleared, confirm the selection\n // and remain on this input\n if (!withButton && !selectedEnd && isEndDirty) {\n actions.resetRange({ start: \"\", end: \"\" });\n onChange?.(\"\", \"\");\n }\n return;\n }\n\n /*\n - if next input is empty, focus it\n - else if date range is invalid, clear and focus the next input\n - else if date range is valid\n - if next input is still pristine, focus it\n - else if !withButton, confirm the selection and \"blur\" the field\n */\n\n if (!selectedEnd) {\n actions.focus(\"end\");\n return;\n }\n\n const isInvalidRange = dayjs(val).isAfter(selectedEnd, \"day\");\n\n if (isInvalidRange) {\n actions.reselectEnd();\n return;\n }\n\n if (!isEndDirty) {\n actions.focus(\"end\");\n return;\n }\n\n if (!withButton) {\n actions.done({ start: val, end: selectedEnd });\n onChange?.(val, selectedEnd);\n return;\n }\n };\n\n const handleEndDateChange = (val: string) => {\n if (isDateUnselectable(val)) {\n // date is invalid, remain on this input\n isUnselectable.current = true;\n return;\n }\n\n const isBeforeStartDate = dayjs(val).isBefore(selectedStart, \"day\");\n\n // if date range is invalid, set selected value as start and reselect end\n if (isBeforeStartDate) {\n actions.changeStart(val);\n calendarRef.current?.setCalendarDate(val);\n actions.reselectEnd();\n return;\n }\n\n actions.changeEnd(val);\n if (val) calendarRef.current?.setCalendarDate(val);\n\n if (!val) {\n // if both start and end were cleared, confirm the selection\n // and remain on this input\n if (!withButton && !selectedStart && isStartDirty) {\n actions.resetRange({ start: \"\", end: \"\" });\n onChange?.(\"\", \"\");\n }\n return;\n }\n\n /*\n - if next input is empty, focus it\n - else if !withButton, confirm the selection and \"blur\" the field\n */\n\n if (!selectedStart) {\n actions.focus(\"start\");\n return;\n }\n\n if (!withButton) {\n endInputRef.current?.focusYearRef();\n\n actions.done({ start: selectedStart, end: val });\n onChange?.(selectedStart, val);\n return;\n }\n };\n\n const handleWeekSelectionChange = (val: string) => {\n const start = dayjs(val).startOf(\"week\").format(\"YYYY-MM-DD\");\n const end = dayjs(val).endOf(\"week\").format(\"YYYY-MM-DD\");\n\n actions.changeStart(start);\n actions.changeEnd(end);\n isUnselectable.current = false;\n\n if (!withButton) {\n endInputRef.current?.focusYearRef();\n\n actions.done({ start, end });\n onChange?.(start, end);\n return;\n }\n };\n\n const handleFixedRangeSelectionChange = (val: string) => {\n if (isDateUnselectable(val)) {\n isUnselectable.current = true;\n return;\n }\n\n actions.changeStart(val);\n calendarRef.current?.setCalendarDate(val);\n isUnselectable.current = false;\n\n if (!val) {\n if (withButton) {\n actions.changeEnd(\"\");\n } else {\n actions.resetRange({ start: \"\", end: \"\" });\n onChange?.(\"\", \"\");\n }\n return;\n }\n\n const start = dayjs(val).format(\"YYYY-MM-DD\");\n const end = dayjs(start)\n .add(numberOfDays - 1, \"day\")\n .format(\"YYYY-MM-DD\");\n actions.changeStart(start);\n actions.changeEnd(end);\n isUnselectable.current = false;\n\n if (!withButton) {\n actions.done({ start, end });\n startInputRef.current?.focusYearRef();\n\n onChange?.(start, end);\n return;\n }\n };\n\n const handleFocus = () => {\n if (isWeekSelection || isFixedRangeSelection) {\n setIsEndDisabled(true);\n }\n\n if (isWeekSelection) {\n setIsStartDisabled(true);\n }\n\n if (readOnly || disabled || focused) return;\n\n actions.focus(\"start\");\n onFocus?.();\n };\n\n const handleBlur = (e: React.FocusEvent) => {\n const target = e.relatedTarget as HTMLElement;\n\n const isInsideCalendar =\n calendarRef.current && calendarRef.current.contains(target);\n const isInsideNode =\n nodeRef.current && nodeRef.current.contains(target);\n const isFloatingElement =\n target?.matches?.(\"[data-floating-ui-focusable]\") ||\n target?.matches?.(\"[data-floating-ui-focus-guard]\");\n\n // Condition when the calendar is closed and focus moved outside the component\n const shouldBlurWhenClosed =\n focused && !calendarOpen && !isInsideNode && !isFloatingElement;\n\n // Condition when the calendar is open, and focus went outside both input and calendar\n const shouldBlurWhenOpenOutside =\n calendarOpen &&\n !isInsideNode &&\n !isInsideCalendar &&\n !isFloatingElement;\n\n if (shouldBlurWhenClosed || shouldBlurWhenOpenOutside) {\n actions.blur();\n\n setIsEndDisabled(false);\n setIsStartDisabled(false);\n\n startInputRef.current?.resetPlaceholder();\n endInputRef.current?.resetPlaceholder();\n\n performOnBlurHandler();\n }\n };\n\n const handleInputFocus =\n (focusType: FocusType) => (event: React.FocusEvent) => {\n event.stopPropagation();\n\n if (readOnly) return;\n\n actions.focus(focusType);\n\n handleWeekSelectionInputFocus();\n handleFixedRangeSelectionInputFocus();\n\n if (!focused) {\n onFocus?.();\n }\n };\n\n const handleWeekSelectionInputFocus = () => {\n if (isWeekSelection) {\n const firstDayOfWeek = DateHelper.toDayjs(selectedStart)\n .startOf(\"week\")\n .format(\"YYYY-MM-DD\");\n\n setIsStartDisabled(true);\n setIsEndDisabled(true);\n setInitialCalendarDate(firstDayOfWeek);\n }\n };\n\n const handleFixedRangeSelectionInputFocus = () => {\n if (isFixedRangeSelection) {\n setIsEndDisabled(true);\n setInitialCalendarDate(selectedStart);\n }\n };\n\n const handleStartInputBlur = (validFormat: boolean) => {\n if (!validFormat || isUnselectable.current) {\n actions.resetStart();\n startInputRef.current?.resetInput();\n }\n };\n\n const handleEndInputBlur = (validFormat: boolean) => {\n if (!validFormat || isUnselectable.current) {\n actions.resetEnd();\n endInputRef.current?.resetInput();\n }\n };\n\n const handleCalendarSelect = (val: string) => {\n switch (variant) {\n case \"week\":\n handleWeekSelectionChange(val);\n break;\n case \"fixed-range\":\n handleFixedRangeSelectionChange(val);\n break;\n default:\n if (currentFocus === \"start\") {\n handleStartDateChange(val);\n } else if (currentFocus === \"end\") {\n handleEndDateChange(val);\n }\n break;\n }\n };\n\n const handleCalendarDismiss = (action: CalendarAction) => {\n nodeRef.current?.focus();\n\n switch (action) {\n case \"reset\":\n actions.cancel();\n break;\n case \"confirmed\":\n actions.done({ start: selectedStart, end: selectedEnd });\n onChange?.(selectedStart, selectedEnd);\n\n if (isWeekSelection) break;\n\n if (isValidRange(selectedStart, selectedEnd)) {\n if (variant === \"range\") {\n endInputRef.current?.focusYearRef();\n } else {\n startInputRef.current?.focusYearRef();\n }\n }\n break;\n }\n };\n\n const handleCalendarHover = (val: string) => {\n setHoverValue(val);\n };\n\n // =============================================================================\n // HELPER FUNCTIONS\n // =============================================================================\n const performOnBlurHandler = () => {\n if (onBlur) {\n onBlur();\n }\n };\n\n const isDateUnselectable = (val: string) => {\n return (\n !allowDisabledSelection &&\n val &&\n DateInputHelper.isDateDisabled(val, {\n disabledDates,\n minDate,\n maxDate,\n })\n );\n };\n\n const isValidRange = (startDate: string, endDate: string) => {\n if (!startDate || !endDate) return false;\n return dayjs(startDate).isBefore(endDate, \"day\");\n };\n\n const getHoverValue = (getValue: Exclude<FocusType, \"none\">) => {\n let values: { start: string | undefined; end: string | undefined } = {\n start: undefined,\n end: undefined,\n };\n\n switch (variant) {\n case \"range\":\n values = {\n start: currentFocus === \"start\" ? hoverValue : undefined,\n end: currentFocus === \"end\" ? hoverValue : undefined,\n };\n break;\n case \"week\":\n if (!hoverValue) return;\n\n values = {\n start: dayjs(hoverValue)\n .startOf(\"week\")\n .format(\"YYYY-MM-DD\"),\n end: dayjs(hoverValue).endOf(\"week\").format(\"YYYY-MM-DD\"),\n };\n break;\n case \"fixed-range\":\n if (!hoverValue) return;\n\n values = {\n start: dayjs(hoverValue).format(\"YYYY-MM-DD\"),\n end: dayjs(hoverValue)\n .add(numberOfDays - 1, \"day\")\n .format(\"YYYY-MM-DD\"),\n };\n break;\n }\n return values[getValue];\n };\n\n // =============================================================================\n // RENDER FUNCTIONS\n // =============================================================================\n const renderInput = () => {\n return (\n <InputWrapper\n role=\"group\"\n ref={nodeRef}\n tabIndex={0}\n onFocus={handleFocus}\n onBlur={handleBlur}\n focused={focused}\n disabled={disabled}\n readOnly={readOnly}\n error={error}\n id={id}\n data-testid={otherProps[\"data-testid\"]}\n aria-disabled={disabled}\n onKeyDown={handleNodeKeyDown}\n {...otherProps}\n className={clsx(\n shouldWrap && !readOnly && styles.containerWrap,\n shouldWrap && readOnly && styles.containerWrapReadOnly,\n otherProps.className\n )}\n >\n <RangeInputInnerContainer\n currentActive={currentFocus}\n wrap={shouldWrap}\n error={error}\n >\n <div\n className={clsx(\n styles.inputContainer,\n shouldWrap && styles.inputContainerWrap\n )}\n >\n <StandaloneDateInput\n ref={startInputRef}\n placeholder=\"From\"\n names={[\"start-day\", \"start-month\", \"start-year\"]}\n inputLabels={[\n \"Start Date\",\n \"Start Month\",\n \"Start Year\",\n ]}\n value={selectedStart}\n disabled={disabled}\n readOnly={isStartDisabled || readOnly}\n focused={currentFocus === \"start\"}\n hoverValue={getHoverValue(\"start\")}\n onChange={\n isFixedRangeSelection\n ? handleFixedRangeSelectionChange\n : handleStartDateChange\n }\n onFocus={handleInputFocus(\"start\")}\n onBlur={handleStartInputBlur}\n hideInputKeyboard={hideInputKeyboard}\n />\n </div>\n <div\n className={clsx(\n styles.inputContainer,\n shouldWrap && styles.inputContainerWrap\n )}\n >\n <StandaloneDateInput\n ref={endInputRef}\n placeholder=\"To\"\n names={[\"end-day\", \"end-month\", \"end-year\"]}\n inputLabels={[\"End Date\", \"End Month\", \"End Year\"]}\n value={selectedEnd}\n disabled={disabled}\n readOnly={isEndDisabled || readOnly}\n focused={currentFocus === \"end\"}\n hoverValue={getHoverValue(\"end\")}\n onChange={handleEndDateChange}\n onFocus={handleInputFocus(\"end\")}\n onBlur={handleEndInputBlur}\n hideInputKeyboard={hideInputKeyboard}\n />\n </div>\n </RangeInputInnerContainer>\n </InputWrapper>\n );\n };\n\n const renderCalendar = ({ elementWidth }: DropdownRenderProps) => {\n return (\n <CalendarDropdown\n ref={calendarRef}\n variant={variant}\n initialCalendarDate={initialCalendarDate}\n withButton={withButton}\n value={selectedStart}\n endValue={selectedEnd}\n selectWithinRange={isStartDirty || isEndDirty}\n currentFocus={currentFocus}\n disabledDates={disabledDates}\n minDate={minDate}\n maxDate={maxDate}\n allowDisabledSelection={allowDisabledSelection}\n onSelect={handleCalendarSelect}\n onDismiss={handleCalendarDismiss}\n onHover={handleCalendarHover}\n onYearMonthDisplayChange={onYearMonthDisplayChange}\n numberOfDays={numberOfDays}\n width={elementWidth}\n isFocusable={!readOnly && !disabled}\n />\n );\n };\n\n return (\n <ElementWithDropdown\n enabled={!readOnly && !disabled}\n isOpen={calendarOpen}\n onClose={handleClose}\n onDismiss={handleDismiss}\n renderElement={renderInput}\n renderDropdown={renderCalendar}\n customZIndex={zIndex}\n offset={16}\n rootNode={rootNode}\n />\n );\n};\n"],"names":["INITIAL_STATE","initialStart","initialEnd","selectedStart","selectedEnd","currentFocus","calendarOpen","isStartDirty","isEndDirty","focused","_a","minDate","maxDate","disabled","disabledDates","error","hideInputKeyboard","value","valueEnd","onChange","onFocus","onBlur","onYearMonthDisplayChange","withButton","variant","numberOfDays","readOnly","id","allowDisabledSelection","zIndex","dropdownRootNode","rootNode","otherProps","__rest","initialCalendarDate","setInitialCalendarDate","useState","hoverValue","setHoverValue","undefined","isWeekSelection","isFixedRangeSelection","isStartDisabled","setIsStartDisabled","isEndDisabled","setIsEndDisabled","actions","useStateActions","name","initialState","reducers","blur","state","dismiss","Object","assign","changeStart","val","changeEnd","reselectStart","reselectEnd","focus","cancel","done","payload","start","end","resetStart","resetEnd","resetRange","isUnselectable","useRef","nodeRef","calendarRef","startInputRef","endInputRef","shouldWrap","useContainerQuery","maxWidth","styles.MOBILE_WRAP_WIDTH","targetRef","useEffect","DateInputHelper","sanitizeInput","handleNodeKeyDown","event","code","current","_b","resetPlaceholder","_c","handleStartDateChange","isDateUnselectable","setCalendarDate","dayjs","isAfter","handleEndDateChange","isBefore","focusYearRef","handleFixedRangeSelectionChange","format","add","handleFocus","handleBlur","e","target","relatedTarget","isInsideCalendar","contains","isInsideNode","isFloatingElement","matches","call","_d","performOnBlurHandler","handleInputFocus","focusType","stopPropagation","handleWeekSelectionInputFocus","handleFixedRangeSelectionInputFocus","firstDayOfWeek","DateHelper","toDayjs","startOf","handleStartInputBlur","validFormat","resetInput","handleEndInputBlur","handleCalendarSelect","endOf","handleWeekSelectionChange","handleCalendarDismiss","action","isValidRange","handleCalendarHover","isDateDisabled","startDate","endDate","getHoverValue","getValue","values","_jsx","ElementWithDropdown","enabled","isOpen","onClose","onDismiss","renderElement","InputWrapper","role","ref","tabIndex","onKeyDown","className","clsx","styles.containerWrap","styles.containerWrapReadOnly","_jsxs","RangeInputInnerContainer","currentActive","wrap","children","styles.inputContainer","styles.inputContainerWrap","StandaloneDateInput","placeholder","names","inputLabels","renderDropdown","elementWidth","CalendarDropdown","endValue","selectWithinRange","onSelect","onHover","width","isFocusable","customZIndex","offset"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"e-signature-canvas.js","sources":["../../../src/e-signature/e-signature-canvas.tsx"],"sourcesContent":["import { Canvas as FabricCanvas, FabricImage, PencilBrush } from \"fabric\";\nimport type { Ref } from \"react\";\nimport {\n forwardRef,\n useCallback,\n useEffect,\n useImperativeHandle,\n useRef,\n} from \"react\";\n\nimport { Colour } from \"../theme\";\nimport { useDesignTokenOverride } from \"../theme/utils\";\nimport * as styles from \"./e-signature.styles\";\n\ninterface ESignatureCanvasProps {\n baseImageDataURL?: string | null | undefined;\n forwardedRef?: Ref<ESignatureCanvasRef> | undefined;\n}\n\nexport interface ESignatureCanvasRef {\n clear: VoidFunction;\n export: () => string | null;\n}\n\nconst Component = (\n props: ESignatureCanvasProps,\n ref: Ref<ESignatureCanvasRef>\n) => {\n // =============================================================================\n // CONST, STATE, REF\n // =============================================================================\n const { baseImageDataURL } = props;\n const containerRef = useRef<HTMLDivElement>(null);\n const canvasRef = useRef<HTMLCanvasElement>(null);\n const fabricCanvas = useRef<FabricCanvas>();\n const pencilBrush = useRef<PencilBrush>();\n const resolvedColor = useDesignTokenOverride({ token: Colour[\"text\"] });\n\n // =============================================================================\n // HOOKS\n // =============================================================================\n useImperativeHandle(ref, () => ({\n clear: () => fabricCanvas.current?.clear(),\n export: () => exportAsImage(),\n }));\n\n // =============================================================================\n // HELPER FUNCTIONS\n // =============================================================================\n const exportAsImage = () => {\n if (!fabricCanvas.current) return null;\n if (!fabricCanvas.current.getObjects().length) return null;\n const dataURL = fabricCanvas.current.toDataURL({\n multiplier: 1,\n format: \"png\",\n quality: 1,\n enableRetinaScaling: true,\n });\n return dataURL;\n };\n\n const handleResize = useCallback(async () => {\n // slight delay for fabricjs to update on orientation change\n await new Promise((resolve) => setTimeout(resolve));\n if (containerRef.current && canvasRef.current && fabricCanvas.current) {\n const canvasWidth = containerRef.current.clientWidth;\n const canvasHeight = containerRef.current.clientHeight;\n canvasRef.current.width = canvasWidth;\n canvasRef.current.height = canvasHeight;\n fabricCanvas.current.setDimensions({\n width: canvasWidth,\n height: canvasHeight,\n });\n\n fabricCanvas.current.forEachObject((obj) => {\n if (fabricCanvas.current) {\n fabricCanvas.current.centerObject(obj);\n }\n });\n }\n }, []);\n\n // =============================================================================\n // EFFECTS\n // =============================================================================\n // initialise fabric and brushes\n useEffect(() => {\n if (containerRef.current && canvasRef.current) {\n fabricCanvas.current = new FabricCanvas(\"eSignatureCanvas\");\n fabricCanvas.current.selection = false;\n fabricCanvas.current.isDrawingMode = true;\n\n pencilBrush.current = new PencilBrush(fabricCanvas.current);\n pencilBrush.current.color = resolvedColor || \"#000000\";\n pencilBrush.current.width = 3;\n\n fabricCanvas.current.freeDrawingBrush = pencilBrush.current;\n\n return () => {\n fabricCanvas.current?.dispose();\n };\n }\n }, []);\n\n useEffect(() => {\n if (pencilBrush.current && resolvedColor) {\n pencilBrush.current.color = resolvedColor;\n }\n }, [resolvedColor]);\n\n // resize\n useEffect(() => {\n if (window) {\n window.addEventListener(\"resize\", handleResize);\n screen.orientation?.addEventListener(\"change\", handleResize);\n handleResize();\n return () => {\n window.removeEventListener(\"resize\", handleResize);\n screen.orientation?.removeEventListener(\"change\", handleResize);\n };\n }\n }, [handleResize]);\n\n // update base image\n useEffect(() => {\n const updateImage = async () => {\n if (baseImageDataURL) {\n const img = await FabricImage.fromURL(baseImageDataURL);\n if (fabricCanvas.current) {\n fabricCanvas.current.clear();\n img.selectable = false;\n img.hoverCursor = \"default\";\n\n if (fabricCanvas.current.width && img.width) {\n img.scale(fabricCanvas.current.width / img.width);\n }\n fabricCanvas.current.add(img);\n fabricCanvas.current.centerObject(img);\n }\n }\n };\n\n updateImage();\n }, [baseImageDataURL]);\n\n // =============================================================================\n // RENDER FUNCTIONS\n // =============================================================================\n return (\n <div className={styles.signatureCanvasContainer} ref={containerRef}>\n <canvas\n className={styles.signatureCanvas}\n id=\"eSignatureCanvas\"\n ref={canvasRef}\n />\n </div>\n );\n};\n\nexport const ESignatureCanvas = forwardRef<\n ESignatureCanvasRef,\n ESignatureCanvasProps\n>(Component);\n"],"names":["ESignatureCanvas","forwardRef","props","ref","baseImageDataURL","containerRef","useRef","canvasRef","fabricCanvas","pencilBrush","resolvedColor","useDesignTokenOverride","token","Colour","useImperativeHandle","clear","_a","current","export","exportAsImage","getObjects","length","toDataURL","multiplier","format","quality","enableRetinaScaling","handleResize","useCallback","__awaiter","Promise","resolve","setTimeout","canvasWidth","clientWidth","canvasHeight","clientHeight","width","height","setDimensions","forEachObject","obj","centerObject","useEffect","FabricCanvas","selection","isDrawingMode","PencilBrush","color","freeDrawingBrush","dispose","window","addEventListener","screen","orientation","removeEventListener","img","FabricImage","fromURL","selectable","hoverCursor","scale","add","_jsx","className","styles.signatureCanvasContainer","children","styles.signatureCanvas","id"],"mappings":"osBAwBA,
|
|
1
|
+
{"version":3,"file":"e-signature-canvas.js","sources":["../../../src/e-signature/e-signature-canvas.tsx"],"sourcesContent":["import { Canvas as FabricCanvas, FabricImage, PencilBrush } from \"fabric\";\nimport type { Ref } from \"react\";\nimport {\n forwardRef,\n useCallback,\n useEffect,\n useImperativeHandle,\n useRef,\n} from \"react\";\n\nimport { Colour } from \"../theme\";\nimport { useDesignTokenOverride } from \"../theme/utils\";\nimport * as styles from \"./e-signature.styles\";\n\ninterface ESignatureCanvasProps {\n baseImageDataURL?: string | null | undefined;\n forwardedRef?: Ref<ESignatureCanvasRef> | undefined;\n}\n\nexport interface ESignatureCanvasRef {\n clear: VoidFunction;\n export: () => string | null;\n}\n\nconst Component = (\n props: ESignatureCanvasProps,\n ref: Ref<ESignatureCanvasRef>\n) => {\n // =============================================================================\n // CONST, STATE, REF\n // =============================================================================\n const { baseImageDataURL } = props;\n const containerRef = useRef<HTMLDivElement>(null);\n const canvasRef = useRef<HTMLCanvasElement>(null);\n const fabricCanvas = useRef<FabricCanvas>();\n const pencilBrush = useRef<PencilBrush>();\n const resolvedColor = useDesignTokenOverride({ token: Colour[\"text\"] });\n\n // =============================================================================\n // HOOKS\n // =============================================================================\n useImperativeHandle(ref, () => ({\n clear: () => fabricCanvas.current?.clear(),\n export: () => exportAsImage(),\n }));\n\n // =============================================================================\n // HELPER FUNCTIONS\n // =============================================================================\n const exportAsImage = () => {\n if (!fabricCanvas.current) return null;\n if (!fabricCanvas.current.getObjects().length) return null;\n const dataURL = fabricCanvas.current.toDataURL({\n multiplier: 1,\n format: \"png\",\n quality: 1,\n enableRetinaScaling: true,\n });\n return dataURL;\n };\n\n const handleResize = useCallback(async () => {\n // slight delay for fabricjs to update on orientation change\n await new Promise((resolve) => setTimeout(resolve));\n if (containerRef.current && canvasRef.current && fabricCanvas.current) {\n const canvasWidth = containerRef.current.clientWidth;\n const canvasHeight = containerRef.current.clientHeight;\n canvasRef.current.width = canvasWidth;\n canvasRef.current.height = canvasHeight;\n fabricCanvas.current.setDimensions({\n width: canvasWidth,\n height: canvasHeight,\n });\n\n fabricCanvas.current.forEachObject((obj) => {\n if (fabricCanvas.current) {\n fabricCanvas.current.centerObject(obj);\n }\n });\n }\n }, []);\n\n // =============================================================================\n // EFFECTS\n // =============================================================================\n // initialise fabric and brushes\n useEffect(() => {\n if (containerRef.current && canvasRef.current) {\n fabricCanvas.current = new FabricCanvas(\"eSignatureCanvas\");\n fabricCanvas.current.selection = false;\n fabricCanvas.current.isDrawingMode = true;\n\n pencilBrush.current = new PencilBrush(fabricCanvas.current);\n pencilBrush.current.color = resolvedColor || \"#000000\";\n pencilBrush.current.width = 3;\n\n fabricCanvas.current.freeDrawingBrush = pencilBrush.current;\n\n return () => {\n fabricCanvas.current?.dispose();\n };\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n useEffect(() => {\n if (pencilBrush.current && resolvedColor) {\n pencilBrush.current.color = resolvedColor;\n }\n }, [resolvedColor]);\n\n // resize\n useEffect(() => {\n if (window) {\n window.addEventListener(\"resize\", handleResize);\n screen.orientation?.addEventListener(\"change\", handleResize);\n handleResize();\n return () => {\n window.removeEventListener(\"resize\", handleResize);\n screen.orientation?.removeEventListener(\"change\", handleResize);\n };\n }\n }, [handleResize]);\n\n // update base image\n useEffect(() => {\n const updateImage = async () => {\n if (baseImageDataURL) {\n const img = await FabricImage.fromURL(baseImageDataURL);\n if (fabricCanvas.current) {\n fabricCanvas.current.clear();\n img.selectable = false;\n img.hoverCursor = \"default\";\n\n if (fabricCanvas.current.width && img.width) {\n img.scale(fabricCanvas.current.width / img.width);\n }\n fabricCanvas.current.add(img);\n fabricCanvas.current.centerObject(img);\n }\n }\n };\n\n updateImage();\n }, [baseImageDataURL]);\n\n // =============================================================================\n // RENDER FUNCTIONS\n // =============================================================================\n return (\n <div className={styles.signatureCanvasContainer} ref={containerRef}>\n <canvas\n className={styles.signatureCanvas}\n id=\"eSignatureCanvas\"\n ref={canvasRef}\n />\n </div>\n );\n};\n\nexport const ESignatureCanvas = forwardRef<\n ESignatureCanvasRef,\n ESignatureCanvasProps\n>(Component);\n"],"names":["ESignatureCanvas","forwardRef","props","ref","baseImageDataURL","containerRef","useRef","canvasRef","fabricCanvas","pencilBrush","resolvedColor","useDesignTokenOverride","token","Colour","useImperativeHandle","clear","_a","current","export","exportAsImage","getObjects","length","toDataURL","multiplier","format","quality","enableRetinaScaling","handleResize","useCallback","__awaiter","Promise","resolve","setTimeout","canvasWidth","clientWidth","canvasHeight","clientHeight","width","height","setDimensions","forEachObject","obj","centerObject","useEffect","FabricCanvas","selection","isDrawingMode","PencilBrush","color","freeDrawingBrush","dispose","window","addEventListener","screen","orientation","removeEventListener","img","FabricImage","fromURL","selectable","hoverCursor","scale","add","_jsx","className","styles.signatureCanvasContainer","children","styles.signatureCanvas","id"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"inactivity-timer.js","sources":["../../../src/error-display/inactivity-timer.tsx"],"sourcesContent":["import { useEffect, useRef, useState } from \"react\";\n\nimport { VisuallyHidden } from \"../shared/accessibility\";\n\ninterface InactivityTimerProps {\n secondsLeft?: number;\n reminderInterval?: number;\n imageOnly?: boolean;\n hasCustomDescription?: boolean;\n}\n\nexport const InactivityTimer = ({\n secondsLeft,\n reminderInterval = 120,\n imageOnly,\n hasCustomDescription,\n}: InactivityTimerProps) => {\n const [liveReminderText, setLiveReminderText] = useState<string>(\"\");\n const prevSecondsLeftRef = useRef<number | undefined>(undefined);\n\n const shouldEnable =\n !imageOnly &&\n !hasCustomDescription &&\n typeof secondsLeft === \"number\" &&\n secondsLeft >= 0;\n\n const buildReminderSentence = (s: number): string => {\n const min = Math.floor(s / 60);\n const sec = s % 60;\n return `You’ve been inactive for a while. To protect your privacy, you’ll be logged out in ${min} minutes ${sec} seconds.`;\n };\n\n useEffect(() => {\n if (\n !shouldEnable ||\n typeof secondsLeft !== \"number\" ||\n secondsLeft < 0\n ) {\n prevSecondsLeftRef.current = undefined;\n setLiveReminderText(\"\");\n return;\n }\n\n const prev = prevSecondsLeftRef.current;\n prevSecondsLeftRef.current = secondsLeft;\n\n if (prev == null) {\n setLiveReminderText(buildReminderSentence(secondsLeft));\n return;\n }\n\n if (secondsLeft >= prev) return;\n\n const interval = Math.max(1, reminderInterval);\n const prevBucket = Math.floor(prev / interval);\n const currBucket = Math.floor(secondsLeft / interval);\n\n if (prevBucket !== currBucket) {\n setLiveReminderText(buildReminderSentence(secondsLeft));\n }\n }, [secondsLeft, reminderInterval]);\n\n if (!liveReminderText || !shouldEnable) return null;\n\n return (\n <VisuallyHidden aria-live=\"polite\" aria-atomic=\"true\">\n {liveReminderText}\n </VisuallyHidden>\n );\n};\n"],"names":["secondsLeft","reminderInterval","imageOnly","hasCustomDescription","liveReminderText","setLiveReminderText","useState","prevSecondsLeftRef","useRef","undefined","shouldEnable","buildReminderSentence","s","Math","floor","useEffect","current","prev","interval","max","_jsx","VisuallyHidden","children"],"mappings":"yIAW+B,EAC3BA,cACAC,mBAAmB,IACnBC,YACAC,2BAEA,MAAOC,EAAkBC,GAAuBC,EAAAA,SAAiB,IAC3DC,EAAqBC,EAAAA,YAA2BC,GAEhDC,GACDR,IACAC,GACsB,iBAAhBH,GACPA,GAAe,EAEbW,EAAyBC,GAGpB,sFAFKC,KAAKC,MAAMF,EAAI,eACfA,EAAI,
|
|
1
|
+
{"version":3,"file":"inactivity-timer.js","sources":["../../../src/error-display/inactivity-timer.tsx"],"sourcesContent":["import { useEffect, useRef, useState } from \"react\";\n\nimport { VisuallyHidden } from \"../shared/accessibility\";\n\ninterface InactivityTimerProps {\n secondsLeft?: number;\n reminderInterval?: number;\n imageOnly?: boolean;\n hasCustomDescription?: boolean;\n}\n\nexport const InactivityTimer = ({\n secondsLeft,\n reminderInterval = 120,\n imageOnly,\n hasCustomDescription,\n}: InactivityTimerProps) => {\n const [liveReminderText, setLiveReminderText] = useState<string>(\"\");\n const prevSecondsLeftRef = useRef<number | undefined>(undefined);\n\n const shouldEnable =\n !imageOnly &&\n !hasCustomDescription &&\n typeof secondsLeft === \"number\" &&\n secondsLeft >= 0;\n\n const buildReminderSentence = (s: number): string => {\n const min = Math.floor(s / 60);\n const sec = s % 60;\n return `You’ve been inactive for a while. To protect your privacy, you’ll be logged out in ${min} minutes ${sec} seconds.`;\n };\n\n useEffect(() => {\n if (\n !shouldEnable ||\n typeof secondsLeft !== \"number\" ||\n secondsLeft < 0\n ) {\n prevSecondsLeftRef.current = undefined;\n setLiveReminderText(\"\");\n return;\n }\n\n const prev = prevSecondsLeftRef.current;\n prevSecondsLeftRef.current = secondsLeft;\n\n if (prev == null) {\n setLiveReminderText(buildReminderSentence(secondsLeft));\n return;\n }\n\n if (secondsLeft >= prev) return;\n\n const interval = Math.max(1, reminderInterval);\n const prevBucket = Math.floor(prev / interval);\n const currBucket = Math.floor(secondsLeft / interval);\n\n if (prevBucket !== currBucket) {\n setLiveReminderText(buildReminderSentence(secondsLeft));\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [secondsLeft, reminderInterval]);\n\n if (!liveReminderText || !shouldEnable) return null;\n\n return (\n <VisuallyHidden aria-live=\"polite\" aria-atomic=\"true\">\n {liveReminderText}\n </VisuallyHidden>\n );\n};\n"],"names":["secondsLeft","reminderInterval","imageOnly","hasCustomDescription","liveReminderText","setLiveReminderText","useState","prevSecondsLeftRef","useRef","undefined","shouldEnable","buildReminderSentence","s","Math","floor","useEffect","current","prev","interval","max","_jsx","VisuallyHidden","children"],"mappings":"yIAW+B,EAC3BA,cACAC,mBAAmB,IACnBC,YACAC,2BAEA,MAAOC,EAAkBC,GAAuBC,EAAAA,SAAiB,IAC3DC,EAAqBC,EAAAA,YAA2BC,GAEhDC,GACDR,IACAC,GACsB,iBAAhBH,GACPA,GAAe,EAEbW,EAAyBC,GAGpB,sFAFKC,KAAKC,MAAMF,EAAI,eACfA,EAAI,cAmCpB,OA/BAG,EAAAA,WAAU,KACN,IACKL,GACsB,iBAAhBV,GACPA,EAAc,EAId,OAFAO,EAAmBS,aAAUP,OAC7BJ,EAAoB,IAIxB,MAAMY,EAAOV,EAAmBS,QAGhC,GAFAT,EAAmBS,QAAUhB,EAEjB,MAARiB,EAEA,YADAZ,EAAoBM,EAAsBX,IAI9C,GAAIA,GAAeiB,EAAM,OAEzB,MAAMC,EAAWL,KAAKM,IAAI,EAAGlB,GACVY,KAAKC,MAAMG,EAAOC,KAClBL,KAAKC,MAAMd,EAAckB,IAGxCb,EAAoBM,EAAsBX,GAC9C,GAED,CAACA,EAAaC,IAEZG,GAAqBM,EAGtBU,EAAAA,IAACC,iBAAc,CAAA,YAAW,SAAQ,cAAa,OAAMC,SAChDlB,IAJsC,IAK1B"}
|