@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":"histogram-slider.js","sources":["../../../src/histogram-slider/histogram-slider.tsx"],"sourcesContent":["import { announce, clearAnnouncer } from \"@react-aria/live-announcer\";\nimport clsx from \"clsx\";\nimport { useEffect, useMemo, useRef, useState } from \"react\";\n\nimport { InputRangeSlider } from \"../input-range-slider\";\nimport { concatIds } from \"../shared/accessibility\";\nimport { useApplyStyle } from \"../theme\";\nimport { Typography } from \"../typography\";\nimport { useId } from \"../util\";\nimport * as styles from \"./histogram-slider.styles\";\nimport type { HistogramBinProps, HistogramSliderProps } from \"./types\";\n\nconst ANNOUNCEMENT_DEBOUNCE_MS = 500;\n\n// @catalog\n/**\n * A histogram with an overlaid two-thumb range slider for numeric filtering.\n *\n * Use `HistogramSlider` to let users narrow a dataset by selecting a numeric\n * range while seeing how values are distributed across bins.\n */\nexport const HistogramSlider = ({\n bins = [],\n interval,\n disabled,\n readOnly,\n value,\n showRangeLabels,\n rangeLabelPrefix,\n rangeLabelSuffix,\n ariaLabels,\n \"aria-labelledby\": ariaLabelledBy,\n \"aria-describedby\": ariaDescribedBy,\n onChange,\n onChangeEnd,\n renderEmptyView,\n renderRangeLabel,\n className,\n ...otherProps\n}: HistogramSliderProps) => {\n // =========================================================================\n // CONST, STATE, REF\n // =========================================================================\n const counts = bins.map((item) => item.count);\n const maxCount = Math.max(...counts);\n\n const values = bins.map((item) => item.minValue);\n const maxValue = Math.max(...values);\n const minValue = Math.min(...values);\n\n const [selection, setSelection] = useState<[number, number]>(\n initSelection()\n );\n const internalId = useId();\n const announcementTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(\n null\n );\n const rangeLabelId = `${internalId}-range-label`;\n const sliderDescribedBy = concatIds(\n ariaDescribedBy,\n showRangeLabels ? rangeLabelId : undefined\n );\n\n const items = useMemo(() => {\n const sorted = [...bins].sort((a, b) => a.minValue - b.minValue);\n const numCols = (maxValue - minValue) / interval + 1;\n\n const items: typeof sorted = [];\n for (let i = 0; i < numCols; i++) {\n const bin = sorted.find(\n (b) => b.minValue === minValue + interval * i\n );\n if (bin) {\n items.push(bin);\n } else {\n items.push({ count: 0, minValue: minValue + interval * i });\n }\n }\n return items;\n }, [bins, interval]);\n\n // =========================================================================\n // EFFECTS\n // =========================================================================\n useEffect(() => {\n if (value !== selection) {\n setSelection(initSelection());\n }\n }, [value]);\n\n useEffect(() => {\n return () => {\n clearPendingAnnouncement();\n };\n }, []);\n\n // =========================================================================\n // EVENT HANDLERS\n // =========================================================================\n const handleChange = (values: number[]) => {\n const [val1, val2] = values;\n const newSelection: [number, number] = [val1, val2];\n setSelection(newSelection);\n scheduleRangePercentageAnnouncement(newSelection);\n onChange?.(newSelection);\n };\n\n const handleChangeEnd = (values: number[]) => {\n const [val1, val2] = values;\n const newSelection: [number, number] = [val1, val2];\n setSelection(newSelection);\n scheduleRangePercentageAnnouncement(newSelection);\n onChangeEnd?.(newSelection);\n };\n\n // =========================================================================\n // HELPER FUNCTIONS\n // =========================================================================\n function initSelection(): [number, number] {\n return value ?? [minValue, minValue + interval];\n }\n\n function clearPendingAnnouncement() {\n if (announcementTimeoutRef.current) {\n clearTimeout(announcementTimeoutRef.current);\n announcementTimeoutRef.current = null;\n }\n }\n\n function getRangePercentageDescription(currentSelection: [number, number]) {\n const totalCount = items.reduce((sum, item) => sum + item.count, 0);\n\n if (totalCount === 0) {\n return \"0% of results available in the range you specified.\";\n }\n\n const selectedCount = items.reduce((sum, item) => {\n const isSelected =\n item.minValue >= currentSelection[0] &&\n item.minValue < currentSelection[1];\n\n return isSelected ? sum + item.count : sum;\n }, 0);\n\n const percentage = Math.round((selectedCount / totalCount) * 100);\n\n return `${percentage}% of results available in the range you specified.`;\n }\n\n function scheduleRangePercentageAnnouncement(\n currentSelection: [number, number]\n ) {\n if (disabled || readOnly) {\n return;\n }\n\n const announcement = getRangePercentageDescription(currentSelection);\n\n clearPendingAnnouncement();\n\n announcementTimeoutRef.current = setTimeout(() => {\n clearAnnouncer(\"polite\");\n announce(announcement, \"polite\");\n }, ANNOUNCEMENT_DEBOUNCE_MS);\n }\n\n // =========================================================================\n // RENDER FUNCTIONS\n // =========================================================================\n const renderRangeItem = (value: number) => {\n if (renderRangeLabel) {\n return renderRangeLabel(value);\n }\n return (\n <Typography.BodyBL>\n {rangeLabelPrefix}\n {value}\n {rangeLabelSuffix}\n </Typography.BodyBL>\n );\n };\n\n const renderHistogramSlider = () => {\n const selectionDescription = getRangePercentageDescription(selection);\n\n return (\n <>\n <div className={styles.histogram}>\n {items.map((item, i) => (\n <HistogramBar\n key={i}\n item={item}\n maxCount={maxCount}\n isSelected={\n item.minValue >= selection[0] &&\n item.minValue < selection[1]\n }\n isDisabled={disabled || readOnly}\n />\n ))}\n </div>\n <InputRangeSlider\n min={minValue}\n max={maxValue + interval}\n step={interval}\n minRange={interval}\n numOfThumbs={2}\n value={selection}\n disabled={disabled}\n readOnly={readOnly}\n ariaLabels={ariaLabels}\n ariaDescriptions={[\n selectionDescription,\n selectionDescription,\n ]}\n aria-describedby={sliderDescribedBy}\n aria-labelledby={ariaLabelledBy}\n onChange={handleChange}\n onChangeEnd={handleChangeEnd}\n className={styles.slider}\n />\n </>\n );\n };\n\n return (\n <div role=\"group\" {...otherProps} className={className}>\n {showRangeLabels && (\n <div id={rangeLabelId} className={styles.label}>\n {renderRangeItem(selection[0])}\n <div className={styles.separator}>-</div>\n {renderRangeItem(selection[1])}\n </div>\n )}\n {items.every((item) => item.count === 0) && renderEmptyView\n ? renderEmptyView()\n : renderHistogramSlider()}\n </div>\n );\n};\n\n// =============================================================================\n// SUB COMPONENT\n// =============================================================================\ninterface HistogramBarProps {\n item: HistogramBinProps;\n maxCount: number;\n isSelected: boolean;\n isDisabled: boolean | undefined;\n}\n\nconst HistogramBar = ({\n item,\n maxCount,\n isSelected,\n isDisabled,\n}: HistogramBarProps) => {\n const ratio = item.count / maxCount;\n const barRef = useRef<HTMLDivElement>(null);\n\n useApplyStyle(barRef, {\n height: ratio ? `calc(calc(100% - 0.25rem) * ${ratio} + 0.25rem)` : \"0\",\n });\n\n return (\n <div\n data-testid=\"histogram-bar\"\n className={clsx(\n styles.bar,\n isDisabled && isSelected && styles.barSelectedDisabled,\n isDisabled && styles.barDisabled,\n isSelected && styles.barSelected\n )}\n ref={barRef}\n />\n );\n};\n"],"names":["HistogramBar","item","maxCount","isSelected","isDisabled","ratio","count","barRef","useRef","useApplyStyle","height","_jsx","className","clsx","styles.bar","styles.barSelectedDisabled","styles.barDisabled","styles.barSelected","ref","_a","bins","interval","disabled","readOnly","value","showRangeLabels","rangeLabelPrefix","rangeLabelSuffix","ariaLabels","ariaLabelledBy","ariaDescribedBy","onChange","onChangeEnd","renderEmptyView","renderRangeLabel","otherProps","__rest","counts","map","Math","max","values","minValue","maxValue","min","selection","setSelection","useState","initSelection","internalId","useId","announcementTimeoutRef","rangeLabelId","sliderDescribedBy","concatIds","undefined","items","useMemo","sorted","sort","a","b","numCols","i","bin","find","push","useEffect","clearPendingAnnouncement","handleChange","val1","val2","newSelection","scheduleRangePercentageAnnouncement","handleChangeEnd","current","clearTimeout","getRangePercentageDescription","currentSelection","totalCount","reduce","sum","selectedCount","round","announcement","setTimeout","clearAnnouncer","announce","renderRangeItem","_jsxs","Typography","BodyBL","children","Object","assign","role","id","styles.label","styles.separator","every","selectionDescription","_Fragment","styles.histogram","InputRangeSlider","step","minRange","numOfThumbs","ariaDescriptions","styles.slider","renderHistogramSlider"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"histogram-slider.js","sources":["../../../src/histogram-slider/histogram-slider.tsx"],"sourcesContent":["import { announce, clearAnnouncer } from \"@react-aria/live-announcer\";\nimport clsx from \"clsx\";\nimport { useEffect, useMemo, useRef, useState } from \"react\";\n\nimport { InputRangeSlider } from \"../input-range-slider\";\nimport { concatIds } from \"../shared/accessibility\";\nimport { useApplyStyle } from \"../theme\";\nimport { Typography } from \"../typography\";\nimport { useId } from \"../util\";\nimport * as styles from \"./histogram-slider.styles\";\nimport type { HistogramBinProps, HistogramSliderProps } from \"./types\";\n\nconst ANNOUNCEMENT_DEBOUNCE_MS = 500;\n\n// @catalog\n/**\n * A histogram with an overlaid two-thumb range slider for numeric filtering.\n *\n * Use `HistogramSlider` to let users narrow a dataset by selecting a numeric\n * range while seeing how values are distributed across bins.\n */\nexport const HistogramSlider = ({\n bins = [],\n interval,\n disabled,\n readOnly,\n value,\n showRangeLabels,\n rangeLabelPrefix,\n rangeLabelSuffix,\n ariaLabels,\n \"aria-labelledby\": ariaLabelledBy,\n \"aria-describedby\": ariaDescribedBy,\n onChange,\n onChangeEnd,\n renderEmptyView,\n renderRangeLabel,\n className,\n ...otherProps\n}: HistogramSliderProps) => {\n // =========================================================================\n // CONST, STATE, REF\n // =========================================================================\n const counts = bins.map((item) => item.count);\n const maxCount = Math.max(...counts);\n\n const values = bins.map((item) => item.minValue);\n const maxValue = Math.max(...values);\n const minValue = Math.min(...values);\n\n const [selection, setSelection] = useState<[number, number]>(\n initSelection()\n );\n const internalId = useId();\n const announcementTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(\n null\n );\n const rangeLabelId = `${internalId}-range-label`;\n const sliderDescribedBy = concatIds(\n ariaDescribedBy,\n showRangeLabels ? rangeLabelId : undefined\n );\n\n const items = useMemo(() => {\n const sorted = [...bins].sort((a, b) => a.minValue - b.minValue);\n const numCols = (maxValue - minValue) / interval + 1;\n\n const items: typeof sorted = [];\n for (let i = 0; i < numCols; i++) {\n const bin = sorted.find(\n (b) => b.minValue === minValue + interval * i\n );\n if (bin) {\n items.push(bin);\n } else {\n items.push({ count: 0, minValue: minValue + interval * i });\n }\n }\n return items;\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [bins, interval]);\n\n // =========================================================================\n // EFFECTS\n // =========================================================================\n useEffect(() => {\n if (value !== selection) {\n setSelection(initSelection());\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [value]);\n\n useEffect(() => {\n return () => {\n clearPendingAnnouncement();\n };\n }, []);\n\n // =========================================================================\n // EVENT HANDLERS\n // =========================================================================\n const handleChange = (values: number[]) => {\n const [val1, val2] = values;\n const newSelection: [number, number] = [val1, val2];\n setSelection(newSelection);\n scheduleRangePercentageAnnouncement(newSelection);\n onChange?.(newSelection);\n };\n\n const handleChangeEnd = (values: number[]) => {\n const [val1, val2] = values;\n const newSelection: [number, number] = [val1, val2];\n setSelection(newSelection);\n scheduleRangePercentageAnnouncement(newSelection);\n onChangeEnd?.(newSelection);\n };\n\n // =========================================================================\n // HELPER FUNCTIONS\n // =========================================================================\n function initSelection(): [number, number] {\n return value ?? [minValue, minValue + interval];\n }\n\n function clearPendingAnnouncement() {\n if (announcementTimeoutRef.current) {\n clearTimeout(announcementTimeoutRef.current);\n announcementTimeoutRef.current = null;\n }\n }\n\n function getRangePercentageDescription(currentSelection: [number, number]) {\n const totalCount = items.reduce((sum, item) => sum + item.count, 0);\n\n if (totalCount === 0) {\n return \"0% of results available in the range you specified.\";\n }\n\n const selectedCount = items.reduce((sum, item) => {\n const isSelected =\n item.minValue >= currentSelection[0] &&\n item.minValue < currentSelection[1];\n\n return isSelected ? sum + item.count : sum;\n }, 0);\n\n const percentage = Math.round((selectedCount / totalCount) * 100);\n\n return `${percentage}% of results available in the range you specified.`;\n }\n\n function scheduleRangePercentageAnnouncement(\n currentSelection: [number, number]\n ) {\n if (disabled || readOnly) {\n return;\n }\n\n const announcement = getRangePercentageDescription(currentSelection);\n\n clearPendingAnnouncement();\n\n announcementTimeoutRef.current = setTimeout(() => {\n clearAnnouncer(\"polite\");\n announce(announcement, \"polite\");\n }, ANNOUNCEMENT_DEBOUNCE_MS);\n }\n\n // =========================================================================\n // RENDER FUNCTIONS\n // =========================================================================\n const renderRangeItem = (value: number) => {\n if (renderRangeLabel) {\n return renderRangeLabel(value);\n }\n return (\n <Typography.BodyBL>\n {rangeLabelPrefix}\n {value}\n {rangeLabelSuffix}\n </Typography.BodyBL>\n );\n };\n\n const renderHistogramSlider = () => {\n const selectionDescription = getRangePercentageDescription(selection);\n\n return (\n <>\n <div className={styles.histogram}>\n {items.map((item, i) => (\n <HistogramBar\n key={i}\n item={item}\n maxCount={maxCount}\n isSelected={\n item.minValue >= selection[0] &&\n item.minValue < selection[1]\n }\n isDisabled={disabled || readOnly}\n />\n ))}\n </div>\n <InputRangeSlider\n min={minValue}\n max={maxValue + interval}\n step={interval}\n minRange={interval}\n numOfThumbs={2}\n value={selection}\n disabled={disabled}\n readOnly={readOnly}\n ariaLabels={ariaLabels}\n ariaDescriptions={[\n selectionDescription,\n selectionDescription,\n ]}\n aria-describedby={sliderDescribedBy}\n aria-labelledby={ariaLabelledBy}\n onChange={handleChange}\n onChangeEnd={handleChangeEnd}\n className={styles.slider}\n />\n </>\n );\n };\n\n return (\n <div role=\"group\" {...otherProps} className={className}>\n {showRangeLabels && (\n <div id={rangeLabelId} className={styles.label}>\n {renderRangeItem(selection[0])}\n <div className={styles.separator}>-</div>\n {renderRangeItem(selection[1])}\n </div>\n )}\n {items.every((item) => item.count === 0) && renderEmptyView\n ? renderEmptyView()\n : renderHistogramSlider()}\n </div>\n );\n};\n\n// =============================================================================\n// SUB COMPONENT\n// =============================================================================\ninterface HistogramBarProps {\n item: HistogramBinProps;\n maxCount: number;\n isSelected: boolean;\n isDisabled: boolean | undefined;\n}\n\nconst HistogramBar = ({\n item,\n maxCount,\n isSelected,\n isDisabled,\n}: HistogramBarProps) => {\n const ratio = item.count / maxCount;\n const barRef = useRef<HTMLDivElement>(null);\n\n useApplyStyle(barRef, {\n height: ratio ? `calc(calc(100% - 0.25rem) * ${ratio} + 0.25rem)` : \"0\",\n });\n\n return (\n <div\n data-testid=\"histogram-bar\"\n className={clsx(\n styles.bar,\n isDisabled && isSelected && styles.barSelectedDisabled,\n isDisabled && styles.barDisabled,\n isSelected && styles.barSelected\n )}\n ref={barRef}\n />\n );\n};\n"],"names":["HistogramBar","item","maxCount","isSelected","isDisabled","ratio","count","barRef","useRef","useApplyStyle","height","_jsx","className","clsx","styles.bar","styles.barSelectedDisabled","styles.barDisabled","styles.barSelected","ref","_a","bins","interval","disabled","readOnly","value","showRangeLabels","rangeLabelPrefix","rangeLabelSuffix","ariaLabels","ariaLabelledBy","ariaDescribedBy","onChange","onChangeEnd","renderEmptyView","renderRangeLabel","otherProps","__rest","counts","map","Math","max","values","minValue","maxValue","min","selection","setSelection","useState","initSelection","internalId","useId","announcementTimeoutRef","rangeLabelId","sliderDescribedBy","concatIds","undefined","items","useMemo","sorted","sort","a","b","numCols","i","bin","find","push","useEffect","clearPendingAnnouncement","handleChange","val1","val2","newSelection","scheduleRangePercentageAnnouncement","handleChangeEnd","current","clearTimeout","getRangePercentageDescription","currentSelection","totalCount","reduce","sum","selectedCount","round","announcement","setTimeout","clearAnnouncer","announce","renderRangeItem","_jsxs","Typography","BodyBL","children","Object","assign","role","id","styles.label","styles.separator","every","selectionDescription","_Fragment","styles.histogram","InputRangeSlider","step","minRange","numOfThumbs","ariaDescriptions","styles.slider","renderHistogramSlider"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"input-range-slider.js","sources":["../../../src/input-range-slider/input-range-slider.tsx"],"sourcesContent":["import { announce, clearAnnouncer } from \"@react-aria/live-announcer\";\nimport clsx from \"clsx\";\nimport type React from \"react\";\nimport { useEffect, useState } from \"react\";\nimport ReactSlider from \"react-slider\";\n\nimport { concatIds, VisuallyHidden } from \"../shared/accessibility\";\nimport { Colour } from \"../theme\";\nimport { Typography } from \"../typography\";\nimport { useId } from \"../util\";\nimport * as styles from \"./input-range-slider.styles\";\nimport { Thumb, Track } from \"./slider-components\";\nimport type { InputRangeSliderProps } from \"./types\";\n\n// @catalog\n/**\n * A draggable track slider for selecting one or more numeric values within a\n * bounded range.\n *\n * Use `InputRangeSlider` when the selection does not need to be precise;\n * the user picks a value or a range by dragging thumb controls along a track.\n */\nexport const InputRangeSlider = ({\n id,\n value,\n min = 0,\n max = 100,\n step = 1,\n minRange = 0,\n numOfThumbs = 2,\n colors,\n disabled,\n readOnly,\n showSliderLabels,\n sliderLabelPrefix,\n sliderLabelSuffix,\n showIndicatorLabel,\n indicatorLabelPrefix,\n indicatorLabelSuffix,\n ariaLabels,\n ariaDescriptions,\n \"aria-invalid\": ariaInvalid,\n \"aria-labelledby\": ariaLabelledBy,\n \"aria-describedby\": ariaDescribedBy,\n renderSliderLabel,\n onChange,\n onChangeEnd,\n className,\n ...otherProps\n}: InputRangeSliderProps) => {\n // =========================================================================\n // CONST, STATE, REF\n // =========================================================================\n const [selection, setSelection] = useState<number[]>(initialiseSelection());\n const [focusedThumbIndex, setFocusedThumbIndex] = useState<number | null>(\n null\n );\n const internalId = useId();\n const trackColors = getTrackColors();\n const indicatorTextId = `${internalId}-indicator`;\n const instructionTextId = `${internalId}-instruction`;\n const resolvedAriaLabels = getResolvedAriaLabels();\n\n // =========================================================================\n // EFFECTS\n // =========================================================================\n useEffect(() => {\n if (value !== selection) {\n setSelection(initialiseSelection());\n }\n }, [value]);\n\n // =========================================================================\n // EVENT HANDLERS\n // =========================================================================\n const handleChange = (value: number | readonly number[], index: number) => {\n if (readOnly || disabled) {\n return;\n }\n\n if (typeof value === \"number\") {\n const nextValue = [value];\n setSelection(nextValue);\n onChange?.(nextValue);\n return;\n }\n\n if (index > -1 && selection[index] === value[index]) {\n // skip unnecessary update when dragging the start thumb across the end thumb\n return;\n }\n\n const nextValue = [...value];\n setSelection(nextValue);\n onChange?.(nextValue);\n };\n\n const handleChangeEnd = (value: number | readonly number[]) => {\n if (readOnly || disabled) {\n return;\n }\n\n if (typeof value === \"number\") {\n const val = [value];\n setSelection(val);\n onChangeEnd?.(val);\n return;\n }\n\n const newSelection = [...value];\n setSelection(newSelection);\n onChangeEnd?.(newSelection);\n };\n\n const handleThumbKeyDown = (\n event: React.KeyboardEvent<HTMLDivElement>,\n index: number\n ) => {\n if (disabled || readOnly) {\n return;\n }\n\n const message = getBlockedMovementMessage(event.key, index);\n\n if (!message) {\n return;\n }\n\n clearAnnouncer(\"assertive\");\n announce(message, \"assertive\");\n };\n\n const handleNativeRangeChange = (\n event: React.ChangeEvent<HTMLInputElement>,\n index: number\n ) => {\n if (disabled || readOnly) {\n return;\n }\n\n const nextRawValue = Number(event.currentTarget.value);\n\n const nextSelection = [...selection];\n nextSelection[index] = clampValueForThumb(\n nextRawValue,\n index,\n selection\n );\n\n setSelection(nextSelection);\n onChange?.(nextSelection);\n onChangeEnd?.(nextSelection);\n };\n\n // =========================================================================\n // HELPER FUNCTIONS\n // =========================================================================\n function initialiseSelection() {\n if (value && value.length === numOfThumbs) {\n return value;\n }\n\n const values: number[] = [];\n for (let i = 0; i < numOfThumbs; i++) {\n values.push(min + step * i);\n }\n return values;\n }\n\n function getResolvedAriaLabels() {\n return Array.from({ length: numOfThumbs }, (_, index) => {\n return ariaLabels?.[index] || getDefaultAriaLabel(index);\n });\n }\n\n function getDefaultAriaLabel(index: number) {\n if (numOfThumbs === 1) {\n return \"\";\n }\n\n if (index === 0) {\n return \"Minimum value slider\";\n }\n\n if (index === numOfThumbs - 1) {\n return \"Maximum value slider\";\n }\n\n return \"Indeterminate value slider\";\n }\n\n function getThumbDescriptionText(index: number) {\n return ariaDescriptions?.[index];\n }\n\n function getTrackColors() {\n const defaultColors = getDefaultColors();\n return new Array(numOfThumbs + 1).fill(0).map((_, i) => {\n return colors?.[i] || defaultColors[i];\n });\n }\n\n function getDefaultColors() {\n const inactiveColor =\n disabled || readOnly\n ? Colour[\"border-disabled\"]\n : Colour[\"border-strong\"];\n const activeColor =\n disabled || readOnly\n ? Colour[\"border-selected-disabled\"]\n : Colour[\"border-selected\"];\n\n if (numOfThumbs === 1) {\n return [activeColor, inactiveColor];\n }\n\n const defaultColors: typeof colors = [inactiveColor];\n\n for (let index = 0; index < numOfThumbs - 1; index++) {\n defaultColors.push(activeColor);\n }\n\n defaultColors.push(inactiveColor);\n return defaultColors;\n }\n\n function getValueText(currentValue: number) {\n return `${sliderLabelPrefix || \"\"}${currentValue}${\n sliderLabelSuffix || \"\"\n }`;\n }\n\n function getThumbDescriptionIds(thumbDescriptionId?: string) {\n return concatIds(\n ariaDescribedBy,\n showIndicatorLabel ? indicatorTextId : undefined,\n disabled || readOnly ? undefined : instructionTextId,\n thumbDescriptionId\n );\n }\n\n function isIncreaseKey(key: string) {\n return [\"ArrowRight\", \"ArrowUp\", \"PageUp\", \"End\"].includes(key);\n }\n\n function isDecreaseKey(key: string) {\n return [\"ArrowLeft\", \"ArrowDown\", \"PageDown\", \"Home\"].includes(key);\n }\n\n function getSliderTypeText(label?: string) {\n if (!label) {\n return \"slider\";\n }\n\n return label.toLowerCase();\n }\n\n function getSliderTargetText(label?: string) {\n if (!label) {\n return \"slider\";\n }\n\n return label.replace(/ slider$/i, \"\").toLowerCase();\n }\n\n function getBlockedMovementMessage(key: string, index: number) {\n if (numOfThumbs < 2) {\n return \"\";\n }\n\n const currentValue = selection[index];\n const previousValue = index > 0 ? selection[index - 1] : undefined;\n const nextValue =\n index < selection.length - 1 ? selection[index + 1] : undefined;\n\n const currentLabel = resolvedAriaLabels[index];\n const previousLabel =\n index > 0 ? resolvedAriaLabels[index - 1] : undefined;\n const nextLabel =\n index < resolvedAriaLabels.length - 1\n ? resolvedAriaLabels[index + 1]\n : undefined;\n\n if (isIncreaseKey(key)) {\n if (\n nextValue !== undefined &&\n currentValue >= nextValue - minRange\n ) {\n return `The ${getSliderTypeText(\n currentLabel\n )} has reached its limit. Increase the ${getSliderTargetText(\n nextLabel\n )} to set a higher ${getSliderTargetText(currentLabel)}.`;\n }\n }\n\n if (isDecreaseKey(key)) {\n if (\n previousValue !== undefined &&\n currentValue <= previousValue + minRange\n ) {\n return `The ${getSliderTypeText(\n currentLabel\n )} has reached its limit. Decrease the ${getSliderTargetText(\n previousLabel\n )} to set a lower ${getSliderTargetText(currentLabel)}.`;\n }\n }\n\n return \"\";\n }\n\n function getThumbMin(index: number, values = selection) {\n if (index === 0) {\n return min;\n }\n\n return values[index - 1] + minRange;\n }\n\n function getThumbMax(index: number, values = selection) {\n if (index === values.length - 1) {\n return max;\n }\n\n return values[index + 1] - minRange;\n }\n\n function clampValueForThumb(\n nextValue: number,\n index: number,\n values: number[]\n ) {\n const minAllowed = getThumbMin(index, values);\n const maxAllowed = getThumbMax(index, values);\n\n return Math.min(maxAllowed, Math.max(minAllowed, nextValue));\n }\n\n // =========================================================================\n // RENDER FUNCTIONS\n // =========================================================================\n const formatLabel = (value: number) => {\n if (renderSliderLabel) {\n return renderSliderLabel(value);\n }\n\n return (\n <Typography.BodyBL className={styles.labelText}>\n {sliderLabelPrefix}\n {value}\n {sliderLabelSuffix}\n </Typography.BodyBL>\n );\n };\n\n const formatIndicationLabel = () => {\n let formattedSelection = \"\";\n\n if (selection.length === 1) {\n formattedSelection = `${selection[0]}`;\n } else if (selection.length === 2) {\n formattedSelection = `${selection[0]} - ${selection[1]}`;\n } else if (selection.length > 2) {\n const minValue = Math.min(...selection);\n const maxValue = Math.max(...selection);\n formattedSelection = `${minValue} - ${maxValue}`;\n }\n\n return (\n <Typography.BodyBL className={styles.labelText}>\n {indicatorLabelPrefix}\n {formattedSelection}\n {indicatorLabelSuffix}\n </Typography.BodyBL>\n );\n };\n\n return (\n <div\n {...otherProps}\n id={id}\n role=\"group\"\n aria-labelledby={ariaLabelledBy}\n aria-disabled={disabled}\n className={clsx(styles.wrapper, className)}\n >\n {!disabled && !readOnly && (\n <VisuallyHidden id={instructionTextId}>\n Use left and right arrow keys to adjust the slider.\n </VisuallyHidden>\n )}\n\n {showIndicatorLabel && (\n <div\n id={indicatorTextId}\n className={styles.indicatorLabelContainer}\n >\n {formatIndicationLabel()}\n </div>\n )}\n\n {selection.map((thumbValue, index) => {\n const thumbLabelTextId = `${internalId}-thumb-label-${index}`;\n const thumbDescriptionText = getThumbDescriptionText(index);\n const thumbDescriptionTextId = thumbDescriptionText\n ? `${internalId}-thumb-description-${index}`\n : undefined;\n\n return (\n <VisuallyHidden key={`native-slider-${index}`}>\n {thumbDescriptionTextId && (\n <span id={thumbDescriptionTextId}>\n {thumbDescriptionText}\n </span>\n )}\n <span id={thumbLabelTextId}>\n {resolvedAriaLabels[index]}\n </span>\n\n <input\n data-testid={`slider-input-${index}`}\n type=\"range\"\n min={getThumbMin(index)}\n max={getThumbMax(index)}\n step={step}\n value={thumbValue}\n aria-disabled={disabled || undefined}\n readOnly={readOnly}\n aria-labelledby={concatIds(\n ariaLabelledBy,\n thumbLabelTextId\n )}\n aria-describedby={getThumbDescriptionIds(\n thumbDescriptionTextId\n )}\n aria-valuetext={getValueText(thumbValue)}\n aria-invalid={ariaInvalid}\n onFocus={() => setFocusedThumbIndex(index)}\n onBlur={() => setFocusedThumbIndex(null)}\n onChange={(event) =>\n handleNativeRangeChange(event, index)\n }\n onKeyDown={(event) => {\n handleThumbKeyDown(event, index);\n }}\n />\n </VisuallyHidden>\n );\n })}\n\n {/* Native range inputs provide the accessible interaction model.\n The visible react-slider is presentation-only. */}\n <ReactSlider\n step={step}\n min={min}\n max={max}\n value={selection}\n disabled={disabled || readOnly}\n onChange={handleChange}\n onAfterChange={handleChangeEnd}\n minDistance={minRange}\n aria-hidden\n className={styles.slider}\n renderThumb={(thumbProps, state) => {\n return (\n <Thumb\n data-testid={`slider-thumb-${state.index}`}\n {...thumbProps}\n key={thumbProps.key}\n tabIndex={-1}\n aria-hidden\n focused={focusedThumbIndex === state.index}\n disabled={disabled}\n readOnly={readOnly}\n />\n );\n }}\n renderTrack={(trackProps, state) => {\n return (\n <Track\n data-testid={`slider-track-${state.index}`}\n {...trackProps}\n key={trackProps.key}\n color={trackColors[state.index]}\n />\n );\n }}\n />\n\n {showSliderLabels && (\n <div className={styles.labelContainer}>\n <div>{formatLabel(min)}</div>\n <div>{formatLabel(max)}</div>\n </div>\n )}\n </div>\n );\n};\n"],"names":["_a","id","value","min","max","step","minRange","numOfThumbs","colors","disabled","readOnly","showSliderLabels","sliderLabelPrefix","sliderLabelSuffix","showIndicatorLabel","indicatorLabelPrefix","indicatorLabelSuffix","ariaLabels","ariaDescriptions","ariaInvalid","ariaLabelledBy","ariaDescribedBy","renderSliderLabel","onChange","onChangeEnd","className","otherProps","__rest","selection","setSelection","useState","initialiseSelection","focusedThumbIndex","setFocusedThumbIndex","internalId","useId","trackColors","defaultColors","inactiveColor","Colour","activeColor","index","push","getDefaultColors","Array","fill","map","_","i","getTrackColors","indicatorTextId","instructionTextId","resolvedAriaLabels","from","length","getDefaultAriaLabel","useEffect","handleThumbKeyDown","event","message","key","currentValue","previousValue","undefined","nextValue","currentLabel","previousLabel","nextLabel","includes","isIncreaseKey","getSliderTypeText","getSliderTargetText","isDecreaseKey","getBlockedMovementMessage","clearAnnouncer","announce","handleNativeRangeChange","nextRawValue","Number","currentTarget","nextSelection","values","minAllowed","getThumbMin","maxAllowed","getThumbMax","Math","clampValueForThumb","label","toLowerCase","replace","formatLabel","_jsxs","Typography","BodyBL","styles.labelText","children","Object","assign","role","clsx","styles.wrapper","_jsx","VisuallyHidden","styles.indicatorLabelContainer","formattedSelection","formatIndicationLabel","thumbValue","thumbLabelTextId","thumbDescriptionText","getThumbDescriptionText","thumbDescriptionTextId","type","concatIds","thumbDescriptionId","onFocus","onBlur","onKeyDown","ReactSlider","onAfterChange","val","newSelection","minDistance","styles.slider","renderThumb","thumbProps","state","_createElement","Thumb","tabIndex","focused","renderTrack","trackProps","Track","color","styles.labelContainer"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"input-range-slider.js","sources":["../../../src/input-range-slider/input-range-slider.tsx"],"sourcesContent":["import { announce, clearAnnouncer } from \"@react-aria/live-announcer\";\nimport clsx from \"clsx\";\nimport type React from \"react\";\nimport { useEffect, useState } from \"react\";\nimport ReactSlider from \"react-slider\";\n\nimport { concatIds, VisuallyHidden } from \"../shared/accessibility\";\nimport { Colour } from \"../theme\";\nimport { Typography } from \"../typography\";\nimport { useId } from \"../util\";\nimport * as styles from \"./input-range-slider.styles\";\nimport { Thumb, Track } from \"./slider-components\";\nimport type { InputRangeSliderProps } from \"./types\";\n\n// @catalog\n/**\n * A draggable track slider for selecting one or more numeric values within a\n * bounded range.\n *\n * Use `InputRangeSlider` when the selection does not need to be precise;\n * the user picks a value or a range by dragging thumb controls along a track.\n */\nexport const InputRangeSlider = ({\n id,\n value,\n min = 0,\n max = 100,\n step = 1,\n minRange = 0,\n numOfThumbs = 2,\n colors,\n disabled,\n readOnly,\n showSliderLabels,\n sliderLabelPrefix,\n sliderLabelSuffix,\n showIndicatorLabel,\n indicatorLabelPrefix,\n indicatorLabelSuffix,\n ariaLabels,\n ariaDescriptions,\n \"aria-invalid\": ariaInvalid,\n \"aria-labelledby\": ariaLabelledBy,\n \"aria-describedby\": ariaDescribedBy,\n renderSliderLabel,\n onChange,\n onChangeEnd,\n className,\n ...otherProps\n}: InputRangeSliderProps) => {\n // =========================================================================\n // CONST, STATE, REF\n // =========================================================================\n const [selection, setSelection] = useState<number[]>(initialiseSelection());\n const [focusedThumbIndex, setFocusedThumbIndex] = useState<number | null>(\n null\n );\n const internalId = useId();\n const trackColors = getTrackColors();\n const indicatorTextId = `${internalId}-indicator`;\n const instructionTextId = `${internalId}-instruction`;\n const resolvedAriaLabels = getResolvedAriaLabels();\n\n // =========================================================================\n // EFFECTS\n // =========================================================================\n useEffect(() => {\n if (value !== selection) {\n setSelection(initialiseSelection());\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [value]);\n\n // =========================================================================\n // EVENT HANDLERS\n // =========================================================================\n const handleChange = (value: number | readonly number[], index: number) => {\n if (readOnly || disabled) {\n return;\n }\n\n if (typeof value === \"number\") {\n const nextValue = [value];\n setSelection(nextValue);\n onChange?.(nextValue);\n return;\n }\n\n if (index > -1 && selection[index] === value[index]) {\n // skip unnecessary update when dragging the start thumb across the end thumb\n return;\n }\n\n const nextValue = [...value];\n setSelection(nextValue);\n onChange?.(nextValue);\n };\n\n const handleChangeEnd = (value: number | readonly number[]) => {\n if (readOnly || disabled) {\n return;\n }\n\n if (typeof value === \"number\") {\n const val = [value];\n setSelection(val);\n onChangeEnd?.(val);\n return;\n }\n\n const newSelection = [...value];\n setSelection(newSelection);\n onChangeEnd?.(newSelection);\n };\n\n const handleThumbKeyDown = (\n event: React.KeyboardEvent<HTMLDivElement>,\n index: number\n ) => {\n if (disabled || readOnly) {\n return;\n }\n\n const message = getBlockedMovementMessage(event.key, index);\n\n if (!message) {\n return;\n }\n\n clearAnnouncer(\"assertive\");\n announce(message, \"assertive\");\n };\n\n const handleNativeRangeChange = (\n event: React.ChangeEvent<HTMLInputElement>,\n index: number\n ) => {\n if (disabled || readOnly) {\n return;\n }\n\n const nextRawValue = Number(event.currentTarget.value);\n\n const nextSelection = [...selection];\n nextSelection[index] = clampValueForThumb(\n nextRawValue,\n index,\n selection\n );\n\n setSelection(nextSelection);\n onChange?.(nextSelection);\n onChangeEnd?.(nextSelection);\n };\n\n // =========================================================================\n // HELPER FUNCTIONS\n // =========================================================================\n function initialiseSelection() {\n if (value && value.length === numOfThumbs) {\n return value;\n }\n\n const values: number[] = [];\n for (let i = 0; i < numOfThumbs; i++) {\n values.push(min + step * i);\n }\n return values;\n }\n\n function getResolvedAriaLabels() {\n return Array.from({ length: numOfThumbs }, (_, index) => {\n return ariaLabels?.[index] || getDefaultAriaLabel(index);\n });\n }\n\n function getDefaultAriaLabel(index: number) {\n if (numOfThumbs === 1) {\n return \"\";\n }\n\n if (index === 0) {\n return \"Minimum value slider\";\n }\n\n if (index === numOfThumbs - 1) {\n return \"Maximum value slider\";\n }\n\n return \"Indeterminate value slider\";\n }\n\n function getThumbDescriptionText(index: number) {\n return ariaDescriptions?.[index];\n }\n\n function getTrackColors() {\n const defaultColors = getDefaultColors();\n return new Array(numOfThumbs + 1).fill(0).map((_, i) => {\n return colors?.[i] || defaultColors[i];\n });\n }\n\n function getDefaultColors() {\n const inactiveColor =\n disabled || readOnly\n ? Colour[\"border-disabled\"]\n : Colour[\"border-strong\"];\n const activeColor =\n disabled || readOnly\n ? Colour[\"border-selected-disabled\"]\n : Colour[\"border-selected\"];\n\n if (numOfThumbs === 1) {\n return [activeColor, inactiveColor];\n }\n\n const defaultColors: typeof colors = [inactiveColor];\n\n for (let index = 0; index < numOfThumbs - 1; index++) {\n defaultColors.push(activeColor);\n }\n\n defaultColors.push(inactiveColor);\n return defaultColors;\n }\n\n function getValueText(currentValue: number) {\n return `${sliderLabelPrefix || \"\"}${currentValue}${\n sliderLabelSuffix || \"\"\n }`;\n }\n\n function getThumbDescriptionIds(thumbDescriptionId?: string) {\n return concatIds(\n ariaDescribedBy,\n showIndicatorLabel ? indicatorTextId : undefined,\n disabled || readOnly ? undefined : instructionTextId,\n thumbDescriptionId\n );\n }\n\n function isIncreaseKey(key: string) {\n return [\"ArrowRight\", \"ArrowUp\", \"PageUp\", \"End\"].includes(key);\n }\n\n function isDecreaseKey(key: string) {\n return [\"ArrowLeft\", \"ArrowDown\", \"PageDown\", \"Home\"].includes(key);\n }\n\n function getSliderTypeText(label?: string) {\n if (!label) {\n return \"slider\";\n }\n\n return label.toLowerCase();\n }\n\n function getSliderTargetText(label?: string) {\n if (!label) {\n return \"slider\";\n }\n\n return label.replace(/ slider$/i, \"\").toLowerCase();\n }\n\n function getBlockedMovementMessage(key: string, index: number) {\n if (numOfThumbs < 2) {\n return \"\";\n }\n\n const currentValue = selection[index];\n const previousValue = index > 0 ? selection[index - 1] : undefined;\n const nextValue =\n index < selection.length - 1 ? selection[index + 1] : undefined;\n\n const currentLabel = resolvedAriaLabels[index];\n const previousLabel =\n index > 0 ? resolvedAriaLabels[index - 1] : undefined;\n const nextLabel =\n index < resolvedAriaLabels.length - 1\n ? resolvedAriaLabels[index + 1]\n : undefined;\n\n if (isIncreaseKey(key)) {\n if (\n nextValue !== undefined &&\n currentValue >= nextValue - minRange\n ) {\n return `The ${getSliderTypeText(\n currentLabel\n )} has reached its limit. Increase the ${getSliderTargetText(\n nextLabel\n )} to set a higher ${getSliderTargetText(currentLabel)}.`;\n }\n }\n\n if (isDecreaseKey(key)) {\n if (\n previousValue !== undefined &&\n currentValue <= previousValue + minRange\n ) {\n return `The ${getSliderTypeText(\n currentLabel\n )} has reached its limit. Decrease the ${getSliderTargetText(\n previousLabel\n )} to set a lower ${getSliderTargetText(currentLabel)}.`;\n }\n }\n\n return \"\";\n }\n\n function getThumbMin(index: number, values = selection) {\n if (index === 0) {\n return min;\n }\n\n return values[index - 1] + minRange;\n }\n\n function getThumbMax(index: number, values = selection) {\n if (index === values.length - 1) {\n return max;\n }\n\n return values[index + 1] - minRange;\n }\n\n function clampValueForThumb(\n nextValue: number,\n index: number,\n values: number[]\n ) {\n const minAllowed = getThumbMin(index, values);\n const maxAllowed = getThumbMax(index, values);\n\n return Math.min(maxAllowed, Math.max(minAllowed, nextValue));\n }\n\n // =========================================================================\n // RENDER FUNCTIONS\n // =========================================================================\n const formatLabel = (value: number) => {\n if (renderSliderLabel) {\n return renderSliderLabel(value);\n }\n\n return (\n <Typography.BodyBL className={styles.labelText}>\n {sliderLabelPrefix}\n {value}\n {sliderLabelSuffix}\n </Typography.BodyBL>\n );\n };\n\n const formatIndicationLabel = () => {\n let formattedSelection = \"\";\n\n if (selection.length === 1) {\n formattedSelection = `${selection[0]}`;\n } else if (selection.length === 2) {\n formattedSelection = `${selection[0]} - ${selection[1]}`;\n } else if (selection.length > 2) {\n const minValue = Math.min(...selection);\n const maxValue = Math.max(...selection);\n formattedSelection = `${minValue} - ${maxValue}`;\n }\n\n return (\n <Typography.BodyBL className={styles.labelText}>\n {indicatorLabelPrefix}\n {formattedSelection}\n {indicatorLabelSuffix}\n </Typography.BodyBL>\n );\n };\n\n return (\n <div\n {...otherProps}\n id={id}\n role=\"group\"\n aria-labelledby={ariaLabelledBy}\n aria-disabled={disabled}\n className={clsx(styles.wrapper, className)}\n >\n {!disabled && !readOnly && (\n <VisuallyHidden id={instructionTextId}>\n Use left and right arrow keys to adjust the slider.\n </VisuallyHidden>\n )}\n\n {showIndicatorLabel && (\n <div\n id={indicatorTextId}\n className={styles.indicatorLabelContainer}\n >\n {formatIndicationLabel()}\n </div>\n )}\n\n {selection.map((thumbValue, index) => {\n const thumbLabelTextId = `${internalId}-thumb-label-${index}`;\n const thumbDescriptionText = getThumbDescriptionText(index);\n const thumbDescriptionTextId = thumbDescriptionText\n ? `${internalId}-thumb-description-${index}`\n : undefined;\n\n return (\n <VisuallyHidden key={`native-slider-${index}`}>\n {thumbDescriptionTextId && (\n <span id={thumbDescriptionTextId}>\n {thumbDescriptionText}\n </span>\n )}\n <span id={thumbLabelTextId}>\n {resolvedAriaLabels[index]}\n </span>\n\n <input\n data-testid={`slider-input-${index}`}\n type=\"range\"\n min={getThumbMin(index)}\n max={getThumbMax(index)}\n step={step}\n value={thumbValue}\n aria-disabled={disabled || undefined}\n readOnly={readOnly}\n aria-labelledby={concatIds(\n ariaLabelledBy,\n thumbLabelTextId\n )}\n aria-describedby={getThumbDescriptionIds(\n thumbDescriptionTextId\n )}\n aria-valuetext={getValueText(thumbValue)}\n aria-invalid={ariaInvalid}\n onFocus={() => setFocusedThumbIndex(index)}\n onBlur={() => setFocusedThumbIndex(null)}\n onChange={(event) =>\n handleNativeRangeChange(event, index)\n }\n onKeyDown={(event) => {\n handleThumbKeyDown(event, index);\n }}\n />\n </VisuallyHidden>\n );\n })}\n\n {/* Native range inputs provide the accessible interaction model.\n The visible react-slider is presentation-only. */}\n <ReactSlider\n step={step}\n min={min}\n max={max}\n value={selection}\n disabled={disabled || readOnly}\n onChange={handleChange}\n onAfterChange={handleChangeEnd}\n minDistance={minRange}\n aria-hidden\n className={styles.slider}\n renderThumb={(thumbProps, state) => {\n return (\n <Thumb\n data-testid={`slider-thumb-${state.index}`}\n {...thumbProps}\n key={thumbProps.key}\n tabIndex={-1}\n aria-hidden\n focused={focusedThumbIndex === state.index}\n disabled={disabled}\n readOnly={readOnly}\n />\n );\n }}\n renderTrack={(trackProps, state) => {\n return (\n <Track\n data-testid={`slider-track-${state.index}`}\n {...trackProps}\n key={trackProps.key}\n color={trackColors[state.index]}\n />\n );\n }}\n />\n\n {showSliderLabels && (\n <div className={styles.labelContainer}>\n <div>{formatLabel(min)}</div>\n <div>{formatLabel(max)}</div>\n </div>\n )}\n </div>\n );\n};\n"],"names":["_a","id","value","min","max","step","minRange","numOfThumbs","colors","disabled","readOnly","showSliderLabels","sliderLabelPrefix","sliderLabelSuffix","showIndicatorLabel","indicatorLabelPrefix","indicatorLabelSuffix","ariaLabels","ariaDescriptions","ariaInvalid","ariaLabelledBy","ariaDescribedBy","renderSliderLabel","onChange","onChangeEnd","className","otherProps","__rest","selection","setSelection","useState","initialiseSelection","focusedThumbIndex","setFocusedThumbIndex","internalId","useId","trackColors","defaultColors","inactiveColor","Colour","activeColor","index","push","getDefaultColors","Array","fill","map","_","i","getTrackColors","indicatorTextId","instructionTextId","resolvedAriaLabels","from","length","getDefaultAriaLabel","useEffect","handleThumbKeyDown","event","message","key","currentValue","previousValue","undefined","nextValue","currentLabel","previousLabel","nextLabel","includes","isIncreaseKey","getSliderTypeText","getSliderTargetText","isDecreaseKey","getBlockedMovementMessage","clearAnnouncer","announce","handleNativeRangeChange","nextRawValue","Number","currentTarget","nextSelection","values","minAllowed","getThumbMin","maxAllowed","getThumbMax","Math","clampValueForThumb","label","toLowerCase","replace","formatLabel","_jsxs","Typography","BodyBL","styles.labelText","children","Object","assign","role","clsx","styles.wrapper","_jsx","VisuallyHidden","styles.indicatorLabelContainer","formattedSelection","formatIndicationLabel","thumbValue","thumbLabelTextId","thumbDescriptionText","getThumbDescriptionText","thumbDescriptionTextId","type","concatIds","thumbDescriptionId","onFocus","onBlur","onKeyDown","ReactSlider","onAfterChange","val","newSelection","minDistance","styles.slider","renderThumb","thumbProps","state","_createElement","Thumb","tabIndex","focused","renderTrack","trackProps","Track","color","styles.labelContainer"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"input-slider.js","sources":["../../../src/input-slider/input-slider.tsx"],"sourcesContent":["import { useEffect, useState } from \"react\";\n\nimport { InputRangeSlider } from \"../input-range-slider\";\nimport type { InputSliderProps } from \"./types\";\n\n// @catalog\n/**\n * A single-thumb slider for selecting one numeric value within a range.\n *\n * Use `InputSlider` when a user needs to pick a single point on a continuous\n * scale without a precise value. For selecting a range between two values, use `InputRangeSlider` instead.\n */\nexport const InputSlider = ({\n value,\n ariaLabel,\n onChange,\n onChangeEnd,\n ...otherProps\n}: InputSliderProps) => {\n // =========================================================================\n // CONST, STATE, REF\n // =========================================================================\n const [selection, setSelection] = useState<number[]>(initialiseSelection());\n\n // =========================================================================\n // EFFECTS\n // =========================================================================\n useEffect(() => {\n if (value !== selection[0]) {\n setSelection(initialiseSelection());\n }\n }, [value]);\n\n // =========================================================================\n // EVENT HANDLERS\n // =========================================================================\n const handleChange = (value: number[]) => {\n const [newVal] = value;\n setSelection([newVal]);\n onChange?.(newVal);\n };\n\n const handleChangeEnd = (value: number[]) => {\n const [newVal] = value;\n setSelection([newVal]);\n onChangeEnd?.(newVal);\n };\n\n // =========================================================================\n // HELPER FUNCTIONS\n // =========================================================================\n function initialiseSelection() {\n return value != undefined ? [value] : [0];\n }\n\n return (\n <InputRangeSlider\n {...otherProps}\n value={selection}\n numOfThumbs={1}\n onChange={handleChange}\n onChangeEnd={handleChangeEnd}\n ariaLabels={ariaLabel ? [ariaLabel] : undefined}\n />\n );\n};\n"],"names":["_a","value","ariaLabel","onChange","onChangeEnd","otherProps","__rest","selection","setSelection","useState","initialiseSelection","useEffect","undefined","_jsx","InputRangeSlider","Object","assign","numOfThumbs","newVal","ariaLabels"],"mappings":"mLAY4BA,IAAA,IAAAC,MACxBA,EAAKC,UACLA,EAASC,SACTA,EAAQC,YACRA,GAAWJ,EACRK,EAAUC,EAAAA,OAAAN,EALW,CAAA,QAAA,YAAA,WAAA,gBAUxB,MAAOO,EAAWC,GAAgBC,EAAAA,SAAmBC,KAKrDC,EAAAA,WAAU,KACFV,IAAUM,EAAU,IACpBC,EAAaE,IACjB,
|
|
1
|
+
{"version":3,"file":"input-slider.js","sources":["../../../src/input-slider/input-slider.tsx"],"sourcesContent":["import { useEffect, useState } from \"react\";\n\nimport { InputRangeSlider } from \"../input-range-slider\";\nimport type { InputSliderProps } from \"./types\";\n\n// @catalog\n/**\n * A single-thumb slider for selecting one numeric value within a range.\n *\n * Use `InputSlider` when a user needs to pick a single point on a continuous\n * scale without a precise value. For selecting a range between two values, use `InputRangeSlider` instead.\n */\nexport const InputSlider = ({\n value,\n ariaLabel,\n onChange,\n onChangeEnd,\n ...otherProps\n}: InputSliderProps) => {\n // =========================================================================\n // CONST, STATE, REF\n // =========================================================================\n const [selection, setSelection] = useState<number[]>(initialiseSelection());\n\n // =========================================================================\n // EFFECTS\n // =========================================================================\n useEffect(() => {\n if (value !== selection[0]) {\n setSelection(initialiseSelection());\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [value]);\n\n // =========================================================================\n // EVENT HANDLERS\n // =========================================================================\n const handleChange = (value: number[]) => {\n const [newVal] = value;\n setSelection([newVal]);\n onChange?.(newVal);\n };\n\n const handleChangeEnd = (value: number[]) => {\n const [newVal] = value;\n setSelection([newVal]);\n onChangeEnd?.(newVal);\n };\n\n // =========================================================================\n // HELPER FUNCTIONS\n // =========================================================================\n function initialiseSelection() {\n return value != undefined ? [value] : [0];\n }\n\n return (\n <InputRangeSlider\n {...otherProps}\n value={selection}\n numOfThumbs={1}\n onChange={handleChange}\n onChangeEnd={handleChangeEnd}\n ariaLabels={ariaLabel ? [ariaLabel] : undefined}\n />\n );\n};\n"],"names":["_a","value","ariaLabel","onChange","onChangeEnd","otherProps","__rest","selection","setSelection","useState","initialiseSelection","useEffect","undefined","_jsx","InputRangeSlider","Object","assign","numOfThumbs","newVal","ariaLabels"],"mappings":"mLAY4BA,IAAA,IAAAC,MACxBA,EAAKC,UACLA,EAASC,SACTA,EAAQC,YACRA,GAAWJ,EACRK,EAAUC,EAAAA,OAAAN,EALW,CAAA,QAAA,YAAA,WAAA,gBAUxB,MAAOO,EAAWC,GAAgBC,EAAAA,SAAmBC,KAKrDC,EAAAA,WAAU,KACFV,IAAUM,EAAU,IACpBC,EAAaE,IACjB,GAED,CAACT,IAoBJ,SAASS,IACL,OAAgBE,MAATX,EAAqB,CAACA,GAAS,CAAC,EAC3C,CAEA,OACIY,EAAAA,IAACC,mBAAgBC,OAAAC,OAAA,CAAA,EACTX,GACJJ,MAAOM,EACPU,YAAa,EACbd,SAxBcF,IAClB,MAAOiB,GAAUjB,EACjBO,EAAa,CAACU,IACdf,SAAAA,EAAWe,EAAO,EAsBdd,YAnBiBH,IACrB,MAAOiB,GAAUjB,EACjBO,EAAa,CAACU,IACdd,SAAAA,EAAcc,EAAO,EAiBjBC,WAAYjB,EAAY,CAACA,QAAaU,IACxC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"textarea-counter.js","sources":["../../../src/input-textarea/textarea-counter.tsx"],"sourcesContent":["import React, { useEffect, useState } from \"react\";\n\nimport * as styles from \"./textarea-counter.styles\";\n\ninterface Props {\n value: string | number | readonly string[] | undefined;\n maxLength: number;\n renderCustomCounter?: (\n maxLength: number,\n currentValueLength: number\n ) => JSX.Element;\n}\n\nexport const TextareaCounter = ({\n value,\n maxLength,\n renderCustomCounter,\n}: Props): JSX.Element => {\n // =============================================================================\n // CONST, STATE, REF\n // =============================================================================\n const [counterLabel, setCounterLabel] = useState<\n string | number | readonly string[] | JSX.Element\n >(\"\");\n\n // =============================================================================\n // EFFECTS\n // =============================================================================\n useEffect(() => {\n setCounterLabel(getCounterLabel(`${value || \"\"}`));\n }, [value, maxLength]);\n\n // =============================================================================\n // HELPER FUNCTIONS\n // =============================================================================\n const getCounterLabel = (value: string | number | readonly string[]) => {\n if (renderCustomCounter) {\n return renderCustomCounter(maxLength, value.toString().length);\n } else {\n const remainingLength = maxLength - value.toString().length;\n if (remainingLength === 1) {\n return `${remainingLength} character left`;\n } else {\n return `${remainingLength.toLocaleString()} characters left`;\n }\n }\n };\n\n // =============================================================================\n // RENDER FUNCTIONS\n // =============================================================================\n return (\n <>\n {React.isValidElement(counterLabel) ? (\n counterLabel\n ) : (\n <p className={styles.counterLabel} data-testid=\"counter-label\">\n {counterLabel}\n </p>\n )}\n </>\n );\n};\n"],"names":["value","maxLength","renderCustomCounter","counterLabel","setCounterLabel","useState","useEffect","getCounterLabel","toString","length","remainingLength","toLocaleString","_jsx","_Fragment","children","React","isValidElement","className","styles.counterLabel"],"mappings":"wNAa+B,EAC3BA,QACAC,YACAC,0BAKA,MAAOC,EAAcC,GAAmBC,EAAAA,SAEtC,IAKFC,EAAAA,WAAU,KACNF,EAAgBG,EAAgB,GAAGP,GAAS,MAAM,
|
|
1
|
+
{"version":3,"file":"textarea-counter.js","sources":["../../../src/input-textarea/textarea-counter.tsx"],"sourcesContent":["import React, { useEffect, useState } from \"react\";\n\nimport * as styles from \"./textarea-counter.styles\";\n\ninterface Props {\n value: string | number | readonly string[] | undefined;\n maxLength: number;\n renderCustomCounter?: (\n maxLength: number,\n currentValueLength: number\n ) => JSX.Element;\n}\n\nexport const TextareaCounter = ({\n value,\n maxLength,\n renderCustomCounter,\n}: Props): JSX.Element => {\n // =============================================================================\n // CONST, STATE, REF\n // =============================================================================\n const [counterLabel, setCounterLabel] = useState<\n string | number | readonly string[] | JSX.Element\n >(\"\");\n\n // =============================================================================\n // EFFECTS\n // =============================================================================\n useEffect(() => {\n setCounterLabel(getCounterLabel(`${value || \"\"}`));\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [value, maxLength]);\n\n // =============================================================================\n // HELPER FUNCTIONS\n // =============================================================================\n const getCounterLabel = (value: string | number | readonly string[]) => {\n if (renderCustomCounter) {\n return renderCustomCounter(maxLength, value.toString().length);\n } else {\n const remainingLength = maxLength - value.toString().length;\n if (remainingLength === 1) {\n return `${remainingLength} character left`;\n } else {\n return `${remainingLength.toLocaleString()} characters left`;\n }\n }\n };\n\n // =============================================================================\n // RENDER FUNCTIONS\n // =============================================================================\n return (\n <>\n {React.isValidElement(counterLabel) ? (\n counterLabel\n ) : (\n <p className={styles.counterLabel} data-testid=\"counter-label\">\n {counterLabel}\n </p>\n )}\n </>\n );\n};\n"],"names":["value","maxLength","renderCustomCounter","counterLabel","setCounterLabel","useState","useEffect","getCounterLabel","toString","length","remainingLength","toLocaleString","_jsx","_Fragment","children","React","isValidElement","className","styles.counterLabel"],"mappings":"wNAa+B,EAC3BA,QACAC,YACAC,0BAKA,MAAOC,EAAcC,GAAmBC,EAAAA,SAEtC,IAKFC,EAAAA,WAAU,KACNF,EAAgBG,EAAgB,GAAGP,GAAS,MAAM,GAEnD,CAACA,EAAOC,IAKX,MAAMM,EAAmBP,IACrB,GAAIE,EACA,OAAOA,EAAoBD,EAAWD,EAAMQ,WAAWC,QACpD,CACH,MAAMC,EAAkBT,EAAYD,EAAMQ,WAAWC,OACrD,OAAwB,IAApBC,EACO,GAAGA,mBAEH,GAAGA,EAAgBC,kCAElC,GAMJ,OACIC,EAAAA,IAAAC,EAAAA,SAAA,CAAAC,SACKC,EAAAA,QAAMC,eAAeb,GAAa,EAG/BS,EAAAA,IAAA,IAAA,CAAGK,UAAWC,EAAAA,aAAmB,cAAc,gBAAeJ,SACzDX,KAGV"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";var e=require("../_virtual/_tslib.js"),
|
|
1
|
+
"use strict";var e=require("../_virtual/_tslib.js"),r=require("react/jsx-runtime"),t=require("clsx"),a=require("react"),s=require("../form/form-label/form-label.js"),n=require("./textarea.styles.js"),l=require("./textarea-counter.js");function o(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}var u=o(t),i=o(a);const g=i.default.forwardRef(((t,s)=>{var{className:l,disabled:o,error:i,maxLength:g,onChange:c,prefix:d,readOnly:f,rows:m=5,transformValue:x,value:h}=t,v=e.__rest(t,["className","disabled","error","maxLength","onChange","prefix","readOnly","rows","transformValue","value"]);const[b,j]=a.useState(h);a.useEffect((()=>{j(h)}),[h]);return r.jsx("textarea",Object.assign({ref:s,disabled:o,value:d?d+(null!=b?b:""):b,onChange:e=>{let r=e.target.value;if(d){r.startsWith(d)||(r=d+r.trimStart()),r.length<d.length&&(r=d);if((e.target.selectionStart||0)<d.length)return void e.preventDefault();const t=r.slice(d.length),a=x?x(t):t;if(j(a),e.target.value=d+a,c){const r=Object.assign(Object.assign({},e),{target:Object.assign(Object.assign({},e.target),{value:a})});c(r)}}else{const t=x?x(null!=r?r:""):r;j(t),e.target.value=t,c&&c(e)}},onKeyDown:e=>{if(!d)return;const{selectionStart:r}=e.currentTarget;"Backspace"===e.key&&r<=d.length&&e.preventDefault(),"ArrowLeft"===e.key&&r<=d.length&&e.preventDefault(),"Home"===e.key&&(e.preventDefault(),requestAnimationFrame((()=>{e.currentTarget.setSelectionRange(d.length,d.length)})))},readOnly:f,className:u.default(n.element,f&&n.elementReadOnly||o&&n.elementDisabled||i&&n.elementError,l),rows:m,maxLength:d&&g?d.length+g:g},v))})),c=i.default.forwardRef(((t,o)=>{var{value:u,disabled:i,rows:c=5,onChange:d,transformValue:f,prefix:m,maxLength:x,renderCustomCounter:h,errorMessage:v,"data-error-testid":b,error:j}=t,p=e.__rest(t,["value","disabled","rows","onChange","transformValue","prefix","maxLength","renderCustomCounter","errorMessage","data-error-testid","error"]);const[C,w]=a.useState(u);a.useEffect((()=>{w(u)}),[u]);return r.jsxs("div",{className:n.wrapper,children:[r.jsx(g,Object.assign({ref:o,disabled:i,value:C,rows:c||5,onChange:e=>{const r=e.target.value;w(r),d&&d(e)},prefix:m,transformValue:f,maxLength:x,error:!!v||j},p)),v||x?r.jsxs("div",{className:n.labelContainer,children:[v&&r.jsx(s.FormErrorMessage,{className:n.errorMessage,"data-testid":b,children:v}),x&&r.jsx(l.TextareaCounter,{value:C,maxLength:x,renderCustomCounter:h})]}):null]})}));exports.Textarea=c,exports.TextareaBase=g;
|
|
2
2
|
//# sourceMappingURL=textarea.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"textarea.js","sources":["../../../src/input-textarea/textarea.tsx"],"sourcesContent":["import clsx from \"clsx\";\nimport React, { useEffect, useState } from \"react\";\n\nimport * as styles from \"./textarea.styles\";\nimport { TextareaCounter } from \"./textarea-counter\";\nimport type { TextareaProps, TextareaRef } from \"./types\";\n\n// =============================================================================\n// BASE COMPONENT\n// =============================================================================\nconst TextareaBaseComponent = (\n {\n className,\n disabled,\n error,\n maxLength,\n onChange,\n prefix,\n readOnly,\n rows = 5,\n transformValue,\n value,\n ...otherProps\n }: TextareaProps,\n ref: TextareaRef\n) => {\n const [stateValue, setStateValue] = useState(value);\n\n useEffect(() => {\n setStateValue(value);\n }, [value]);\n\n const handleChange = (event: React.ChangeEvent<HTMLTextAreaElement>) => {\n let newValue = event.target.value;\n if (prefix) {\n // Ensure prefix is always present\n if (!newValue.startsWith(prefix)) {\n newValue = prefix + newValue.trimStart();\n }\n\n // Prevent deleting the prefix\n if (newValue.length < prefix.length) {\n newValue = prefix;\n }\n\n const cursorPosition = event.target.selectionStart || 0;\n\n // Ensure backspace does not delete the prefix\n if (cursorPosition < prefix.length) {\n event.preventDefault();\n return;\n }\n\n // Extract user input\n const userInput = newValue.slice(prefix.length);\n\n // Transform the input if needed\n const transformedValue = transformValue\n ? transformValue(userInput)\n : userInput;\n\n // Update state and input field\n setStateValue(transformedValue);\n event.target.value = prefix + transformedValue;\n\n // Pass only the user input (without prefix) to `onChange`\n if (onChange) {\n const syntheticEvent = {\n ...event,\n target: { ...event.target, value: transformedValue },\n };\n onChange(\n syntheticEvent as React.ChangeEvent<HTMLTextAreaElement>\n );\n }\n } else {\n const transformedValue = transformValue\n ? transformValue(newValue ?? \"\")\n : newValue;\n\n setStateValue(transformedValue);\n event.target.value = transformedValue;\n if (onChange) onChange(event);\n }\n };\n\n const getDisplayValue = () => {\n return prefix ? prefix + (stateValue ?? \"\") : stateValue;\n };\n\n const handleKeyDown = (event: React.KeyboardEvent<HTMLTextAreaElement>) => {\n if (!prefix) return;\n\n const { selectionStart } = event.currentTarget;\n\n // Prevent backspace in prefix\n if (event.key === \"Backspace\" && selectionStart <= prefix.length) {\n event.preventDefault();\n }\n\n // Prevent left arrow from moving into prefix\n if (event.key === \"ArrowLeft\" && selectionStart <= prefix.length) {\n event.preventDefault();\n }\n\n // Prevent \"Home\" key from moving cursor to beginning\n if (event.key === \"Home\") {\n event.preventDefault();\n requestAnimationFrame(() => {\n event.currentTarget.setSelectionRange(\n prefix.length,\n prefix.length\n );\n });\n }\n };\n\n return (\n <textarea\n ref={ref}\n disabled={disabled}\n value={getDisplayValue()}\n onChange={handleChange}\n onKeyDown={handleKeyDown}\n readOnly={readOnly}\n className={clsx(\n styles.element,\n (readOnly && styles.elementReadOnly) ||\n (disabled && styles.elementDisabled) ||\n (error && styles.elementError),\n className\n )}\n rows={rows}\n maxLength={\n prefix && maxLength ? prefix.length + maxLength : maxLength\n }\n {...otherProps}\n />\n );\n};\n\nexport const TextareaBase = React.forwardRef(TextareaBaseComponent);\n\n// =============================================================================\n// MODULE COMPONENT (comes with the counter)\n// =============================================================================\n\nconst TextareaComponent = (\n {\n value,\n disabled,\n rows = 5,\n onChange,\n transformValue,\n prefix,\n maxLength,\n renderCustomCounter,\n ...otherProps\n }: TextareaProps,\n ref: TextareaRef\n) => {\n // -------------------------------------------------------------------------\n // CONST, STATE, REF\n // -------------------------------------------------------------------------\n const [stateValue, setStateValue] = useState<\n string | number | readonly string[] | undefined\n >(value);\n\n // -------------------------------------------------------------------------\n // EFFECTS\n // -------------------------------------------------------------------------\n useEffect(() => {\n setStateValue(value);\n }, [value]);\n\n // -------------------------------------------------------------------------\n // EVENT HANDLER\n // -------------------------------------------------------------------------\n const handleChange = (event: React.ChangeEvent<HTMLTextAreaElement>) => {\n const newValue = event.target.value;\n setStateValue(newValue);\n if (onChange) onChange(event);\n };\n\n // -------------------------------------------------------------------------\n // RENDER FUNCTIONS\n // -------------------------------------------------------------------------\n return (\n <div className={styles.wrapper}>\n <TextareaBase\n ref={ref}\n disabled={disabled}\n value={stateValue}\n rows={rows || 5}\n onChange={handleChange}\n prefix={prefix}\n transformValue={transformValue}\n maxLength={maxLength}\n {...otherProps}\n />\n {maxLength && (\n <TextareaCounter\n value={stateValue}\n maxLength={maxLength}\n renderCustomCounter={renderCustomCounter}\n />\n )}\n </div>\n );\n};\n\n// @catalog\n/**\n * A multi-line text input with an optional character counter and prefix.\n */\nexport const Textarea = React.forwardRef(TextareaComponent);\n"],"names":["TextareaBase","React","forwardRef","_a","ref","className","disabled","error","maxLength","onChange","prefix","readOnly","rows","transformValue","value","otherProps","__rest","stateValue","setStateValue","useState","useEffect","_jsx","Object","assign","event","newValue","target","startsWith","trimStart","length","selectionStart","preventDefault","userInput","slice","transformedValue","syntheticEvent","onKeyDown","currentTarget","key","requestAnimationFrame","setSelectionRange","clsx","styles.element","styles.elementReadOnly","styles.elementDisabled","styles.elementError","Textarea","renderCustomCounter","_jsxs","styles.wrapper","children","TextareaCounter"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"textarea.js","sources":["../../../src/input-textarea/textarea.tsx"],"sourcesContent":["import clsx from \"clsx\";\nimport React, { useEffect, useState } from \"react\";\n\nimport { FormErrorMessage } from \"../form/form-label\";\nimport * as styles from \"./textarea.styles\";\nimport { TextareaCounter } from \"./textarea-counter\";\nimport type { TextareaProps, TextareaRef } from \"./types\";\n\n// =============================================================================\n// BASE COMPONENT\n// =============================================================================\nconst TextareaBaseComponent = (\n {\n className,\n disabled,\n error,\n maxLength,\n onChange,\n prefix,\n readOnly,\n rows = 5,\n transformValue,\n value,\n ...otherProps\n }: TextareaProps,\n ref: TextareaRef\n) => {\n const [stateValue, setStateValue] = useState(value);\n\n useEffect(() => {\n setStateValue(value);\n }, [value]);\n\n const handleChange = (event: React.ChangeEvent<HTMLTextAreaElement>) => {\n let newValue = event.target.value;\n if (prefix) {\n // Ensure prefix is always present\n if (!newValue.startsWith(prefix)) {\n newValue = prefix + newValue.trimStart();\n }\n\n // Prevent deleting the prefix\n if (newValue.length < prefix.length) {\n newValue = prefix;\n }\n\n const cursorPosition = event.target.selectionStart || 0;\n\n // Ensure backspace does not delete the prefix\n if (cursorPosition < prefix.length) {\n event.preventDefault();\n return;\n }\n\n // Extract user input\n const userInput = newValue.slice(prefix.length);\n\n // Transform the input if needed\n const transformedValue = transformValue\n ? transformValue(userInput)\n : userInput;\n\n // Update state and input field\n setStateValue(transformedValue);\n event.target.value = prefix + transformedValue;\n\n // Pass only the user input (without prefix) to `onChange`\n if (onChange) {\n const syntheticEvent = {\n ...event,\n target: { ...event.target, value: transformedValue },\n };\n onChange(\n syntheticEvent as React.ChangeEvent<HTMLTextAreaElement>\n );\n }\n } else {\n const transformedValue = transformValue\n ? transformValue(newValue ?? \"\")\n : newValue;\n\n setStateValue(transformedValue);\n event.target.value = transformedValue;\n if (onChange) onChange(event);\n }\n };\n\n const getDisplayValue = () => {\n return prefix ? prefix + (stateValue ?? \"\") : stateValue;\n };\n\n const handleKeyDown = (event: React.KeyboardEvent<HTMLTextAreaElement>) => {\n if (!prefix) return;\n\n const { selectionStart } = event.currentTarget;\n\n // Prevent backspace in prefix\n if (event.key === \"Backspace\" && selectionStart <= prefix.length) {\n event.preventDefault();\n }\n\n // Prevent left arrow from moving into prefix\n if (event.key === \"ArrowLeft\" && selectionStart <= prefix.length) {\n event.preventDefault();\n }\n\n // Prevent \"Home\" key from moving cursor to beginning\n if (event.key === \"Home\") {\n event.preventDefault();\n requestAnimationFrame(() => {\n event.currentTarget.setSelectionRange(\n prefix.length,\n prefix.length\n );\n });\n }\n };\n\n return (\n <textarea\n ref={ref}\n disabled={disabled}\n value={getDisplayValue()}\n onChange={handleChange}\n onKeyDown={handleKeyDown}\n readOnly={readOnly}\n className={clsx(\n styles.element,\n (readOnly && styles.elementReadOnly) ||\n (disabled && styles.elementDisabled) ||\n (error && styles.elementError),\n className\n )}\n rows={rows}\n maxLength={\n prefix && maxLength ? prefix.length + maxLength : maxLength\n }\n {...otherProps}\n />\n );\n};\n\nexport const TextareaBase = React.forwardRef(TextareaBaseComponent);\n\n// =============================================================================\n// MODULE COMPONENT (comes with the counter)\n// =============================================================================\n\nconst TextareaComponent = (\n {\n value,\n disabled,\n rows = 5,\n onChange,\n transformValue,\n prefix,\n maxLength,\n renderCustomCounter,\n errorMessage,\n \"data-error-testid\": errorTestId,\n error,\n ...otherProps\n }: TextareaProps,\n ref: TextareaRef\n) => {\n // -------------------------------------------------------------------------\n // CONST, STATE, REF\n // -------------------------------------------------------------------------\n const [stateValue, setStateValue] = useState<\n string | number | readonly string[] | undefined\n >(value);\n\n // -------------------------------------------------------------------------\n // EFFECTS\n // -------------------------------------------------------------------------\n useEffect(() => {\n setStateValue(value);\n }, [value]);\n\n // -------------------------------------------------------------------------\n // EVENT HANDLER\n // -------------------------------------------------------------------------\n const handleChange = (event: React.ChangeEvent<HTMLTextAreaElement>) => {\n const newValue = event.target.value;\n setStateValue(newValue);\n if (onChange) onChange(event);\n };\n\n // -------------------------------------------------------------------------\n // RENDER FUNCTIONS\n // -------------------------------------------------------------------------\n const renderBottomLabels = () => {\n if (!errorMessage && !maxLength) return null;\n return (\n <div className={styles.labelContainer}>\n {errorMessage && (\n <FormErrorMessage\n className={styles.errorMessage}\n data-testid={errorTestId}\n >\n {errorMessage}\n </FormErrorMessage>\n )}\n {maxLength && (\n <TextareaCounter\n value={stateValue}\n maxLength={maxLength}\n renderCustomCounter={renderCustomCounter}\n />\n )}\n </div>\n );\n };\n\n return (\n <div className={styles.wrapper}>\n <TextareaBase\n ref={ref}\n disabled={disabled}\n value={stateValue}\n rows={rows || 5}\n onChange={handleChange}\n prefix={prefix}\n transformValue={transformValue}\n maxLength={maxLength}\n error={!!errorMessage || error}\n {...otherProps}\n />\n {renderBottomLabels()}\n </div>\n );\n};\n\n// @catalog\n/**\n * A multi-line text input with an optional character counter and prefix.\n */\nexport const Textarea = React.forwardRef(TextareaComponent);\n"],"names":["TextareaBase","React","forwardRef","_a","ref","className","disabled","error","maxLength","onChange","prefix","readOnly","rows","transformValue","value","otherProps","__rest","stateValue","setStateValue","useState","useEffect","_jsx","Object","assign","event","newValue","target","startsWith","trimStart","length","selectionStart","preventDefault","userInput","slice","transformedValue","syntheticEvent","onKeyDown","currentTarget","key","requestAnimationFrame","setSelectionRange","clsx","styles.element","styles.elementReadOnly","styles.elementDisabled","styles.elementError","Textarea","renderCustomCounter","errorMessage","errorTestId","_jsxs","styles.wrapper","children","styles.labelContainer","FormErrorMessage","styles.errorMessage","TextareaCounter"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";require("./textarea.
|
|
1
|
+
"use strict";require("./textarea.styles_6we7bs.css");exports.element="e10c6rk9",exports.elementDisabled="e9uwuyt",exports.elementError="etmlvbn",exports.elementReadOnly="e1kovz0t",exports.errorMessage="e1mvywhi",exports.labelContainer="l1npkv4w",exports.wrapper="w1xqauhq";
|
|
2
2
|
//# sourceMappingURL=textarea.styles.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"textarea.styles.js","sources":["../../../src/input-textarea/textarea.styles.ts"],"sourcesContent":["import { css } from \"@linaria/core\";\n\nimport { Border, Colour, Font, Radius, Spacing } from \"../theme\";\n\nexport const wrapper = css`\n display: flex;\n flex-direction: column;\n gap: ${Spacing[\"spacing-8\"]};\n`;\n\nexport const element = css`\n border: ${Border[\"width-010\"]} ${Border[\"solid\"]} ${Colour[\"border\"]};\n border-radius: ${Radius[\"sm\"]};\n background: ${Colour.bg};\n outline: none;\n overflow: auto;\n\n display: block;\n padding: ${Spacing[\"spacing-12\"]} ${Spacing[\"spacing-16\"]};\n width: 100%;\n\n ${Font[\"body-baseline-regular\"]}\n color: ${Colour[\"text\"]};\n\n &:focus,\n &:active {\n outline-offset: -1px;\n outline: ${Border[\"width-020\"]} ${Border[\"solid\"]}\n ${Colour[\"border-focus\"]};\n }\n\n &::placeholder,\n &::-webkit-input-placeholder {\n color: ${Colour[\"text-subtler\"]};\n }\n\n &::-webkit-scrollbar {\n width: 14px;\n }\n\n &::-webkit-scrollbar-track {\n background: transparent;\n }\n\n &::-webkit-scrollbar-thumb {\n background: ${Colour[\"bg-inverse-subtlest\"]};\n border: 5px solid transparent;\n border-radius: ${Radius[\"full\"]};\n background-clip: padding-box;\n }\n`;\n\nexport const elementReadOnly = css`\n border-color: transparent;\n background: transparent !important;\n padding: ${Spacing[\"spacing-12\"]} 0;\n\n &:focus,\n &:active {\n outline-color: ${Colour[\"border-focus\"]};\n }\n`;\n\nexport const elementDisabled = css`\n background: ${Colour[\"bg-disabled\"]};\n cursor: not-allowed;\n\n &:focus,\n &:active {\n outline-color: ${Colour[\"border-disabled\"]};\n }\n`;\n\nexport const elementError = css`\n border-color: ${Colour[\"border-error\"]};\n\n &:focus,\n &:active {\n outline-color: ${Colour[\"border-error-focus\"]};\n }\n`;\n"],"names":[],"mappings":"mGAUoB,mCAqDQ,+BAUH,kCArBG,
|
|
1
|
+
{"version":3,"file":"textarea.styles.js","sources":["../../../src/input-textarea/textarea.styles.ts"],"sourcesContent":["import { css } from \"@linaria/core\";\n\nimport { Border, Colour, Font, Radius, Spacing } from \"../theme\";\n\nexport const wrapper = css`\n display: flex;\n flex-direction: column;\n gap: ${Spacing[\"spacing-8\"]};\n`;\n\nexport const element = css`\n border: ${Border[\"width-010\"]} ${Border[\"solid\"]} ${Colour[\"border\"]};\n border-radius: ${Radius[\"sm\"]};\n background: ${Colour.bg};\n outline: none;\n overflow: auto;\n\n display: block;\n padding: ${Spacing[\"spacing-12\"]} ${Spacing[\"spacing-16\"]};\n width: 100%;\n\n ${Font[\"body-baseline-regular\"]}\n color: ${Colour[\"text\"]};\n\n &:focus,\n &:active {\n outline-offset: -1px;\n outline: ${Border[\"width-020\"]} ${Border[\"solid\"]}\n ${Colour[\"border-focus\"]};\n }\n\n &::placeholder,\n &::-webkit-input-placeholder {\n color: ${Colour[\"text-subtler\"]};\n }\n\n &::-webkit-scrollbar {\n width: 14px;\n }\n\n &::-webkit-scrollbar-track {\n background: transparent;\n }\n\n &::-webkit-scrollbar-thumb {\n background: ${Colour[\"bg-inverse-subtlest\"]};\n border: 5px solid transparent;\n border-radius: ${Radius[\"full\"]};\n background-clip: padding-box;\n }\n`;\n\nexport const elementReadOnly = css`\n border-color: transparent;\n background: transparent !important;\n padding: ${Spacing[\"spacing-12\"]} 0;\n\n &:focus,\n &:active {\n outline-color: ${Colour[\"border-focus\"]};\n }\n`;\n\nexport const elementDisabled = css`\n background: ${Colour[\"bg-disabled\"]};\n cursor: not-allowed;\n\n &:focus,\n &:active {\n outline-color: ${Colour[\"border-disabled\"]};\n }\n`;\n\nexport const elementError = css`\n border-color: ${Colour[\"border-error\"]};\n\n &:focus,\n &:active {\n outline-color: ${Colour[\"border-error-focus\"]};\n }\n`;\n\nexport const labelContainer = css`\n display: flex;\n justify-content: flex-end;\n gap: ${Spacing[\"spacing-12\"]};\n`;\n\nexport const errorMessage = css`\n flex: 1;\n margin-top: 0;\n align-items: flex-start;\n`;\n"],"names":[],"mappings":"mGAUoB,mCAqDQ,+BAUH,kCArBG,gCAoCH,kCANE,2BA9EP"}
|
package/{input-textarea/textarea.styles_q77m5x.css → cjs/input-textarea/textarea.styles_6we7bs.css}
RENAMED
|
@@ -2,4 +2,6 @@
|
|
|
2
2
|
.e10c6rk9{border:var(--fds-border-width-010) var(--fds-border-style-solid) var(--fds-colour-border);border-radius:var(--fds-radius-sm);background:var(--fds-colour-bg);outline:none;overflow:auto;display:block;padding:var(--fds-spacing-12) var(--fds-spacing-16);width:100%;font-family:var(--fds-font-family-body);font-variant:var(--fds-font-variant);font-size:var(--fds-font-body-size-baseline);font-weight:var(--fds-font-weight-regular);line-height:var(--fds-font-body-lh-baseline);letter-spacing:var(--fds-font-body-ls-baseline);color:var(--fds-colour-text);}.e10c6rk9:focus,.e10c6rk9:active{outline-offset:-1px;outline:var(--fds-border-width-020) var(--fds-border-style-solid) var(--fds-colour-border-focus);}.e10c6rk9::-webkit-input-placeholder{color:var(--fds-colour-text-subtler);}.e10c6rk9::-webkit-scrollbar{width:14px;}.e10c6rk9::-webkit-scrollbar-track{background:transparent;}.e10c6rk9::-webkit-scrollbar-thumb{background:var(--fds-colour-bg-inverse-subtlest);border:5px solid transparent;border-radius:var(--fds-radius-full);-webkit-background-clip:padding-box;background-clip:padding-box;}.e10c6rk9::-webkit-input-placeholder{color:var(--fds-colour-text-subtler);}.e10c6rk9::-moz-placeholder{color:var(--fds-colour-text-subtler);}.e10c6rk9:-ms-input-placeholder{color:var(--fds-colour-text-subtler);}.e10c6rk9::placeholder{color:var(--fds-colour-text-subtler);}
|
|
3
3
|
.e1kovz0t{border-color:transparent;background:transparent!important;padding:var(--fds-spacing-12) 0;}.e1kovz0t:focus,.e1kovz0t:active{outline-color:var(--fds-colour-border-focus);}
|
|
4
4
|
.e9uwuyt{background:var(--fds-colour-bg-disabled);cursor:not-allowed;}.e9uwuyt:focus,.e9uwuyt:active{outline-color:var(--fds-colour-border-disabled);}
|
|
5
|
-
.etmlvbn{border-color:var(--fds-colour-border-error);}.etmlvbn:focus,.etmlvbn:active{outline-color:var(--fds-colour-border-error-focus);}
|
|
5
|
+
.etmlvbn{border-color:var(--fds-colour-border-error);}.etmlvbn:focus,.etmlvbn:active{outline-color:var(--fds-colour-border-error-focus);}
|
|
6
|
+
.l1npkv4w{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-pack:end;-ms-flex-pack:end;-webkit-justify-content:flex-end;justify-content:flex-end;gap:var(--fds-spacing-12);}
|
|
7
|
+
.e1mvywhi{-webkit-flex:1;-ms-flex:1;flex:1;margin-top:0;-webkit-align-items:flex-start;-webkit-box-align:flex-start;-ms-flex-align:flex-start;align-items:flex-start;}}
|
package/cjs/modal/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../../../src/modal/index.ts"],"sourcesContent":["import { Modal as Base } from \"./modal\";\nimport { ModalBox as Box } from \"./modal-box\";\n\n// @catalog\n/**\n * A full-screen overlay modal with a slide animation.\n *\n * Use `Modal` to present content that requires the user's immediate attention\n * or a focused interaction. Use `ModalV2` for built-in scroll handling and improved accessibility.\n *\n * Sub-components:\n * - `Modal.Box` — a styled content box with an optional close button.\n */\nexport const Modal = Object.assign(Base, {\n /**\n * A styled content container for use inside `Modal`. Renders an optional\n * close button and stops click events from propagating to the overlay.\n */\n Box,\n});\n\nexport * from \"./types\";\n"],"names":["Modal","Object","assign","Base","Box"],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../../src/modal/index.ts"],"sourcesContent":["import { Modal as Base } from \"./modal\";\nimport { ModalBox as Box } from \"./modal-box\";\n\n// @catalog\n/**\n * A full-screen overlay modal with a slide animation.\n *\n * Use `Modal` to present content that requires the user's immediate attention\n * or a focused interaction. Use `ModalV2` for built-in scroll handling and improved accessibility.\n *\n * Sub-components:\n * - `Modal.Box` — a styled content box with an optional close button.\n *\n * @deprecated Use `ModalV2` instead, which provides a more composable API, improved scroll behaviour, and proper accessibility.\n */\nexport const Modal = Object.assign(Base, {\n /**\n * A styled content container for use inside `Modal`. Renders an optional\n * close button and stops click events from propagating to the overlay.\n *\n * @deprecated Use `ModalV2.Card` instead.\n */\n Box,\n});\n\nexport * from \"./types\";\n"],"names":["Modal","Object","assign","Base","Box"],"mappings":"2EAeaA,EAAQC,OAAOC,OAAOC,QAAM,KAOrCC,EAAAA"}
|
package/cjs/modal-v2/modal-v2.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";var e=require("../_virtual/_tslib.js"),r=require("react/jsx-runtime"),t=require("@floating-ui/react"),a=require("clsx"),i=require("react"),s=require("../overlay/overlay.js"),l=require("../shared/hooks/useViewport.js");require("../theme/theme-provider/index.js"),require("../theme/theme-provider/context.js"),require("../theme/tokens/border.js"),require("../theme/tokens/colour.js"),require("../theme/tokens/font.js"),require("../theme/tokens/media-query.js");var o=require("../theme/utils/use-apply-styles.js");require("../theme/utils/use-media-query.js"),require("../util/calendar-helper.js"),require("../external/dayjs/dayjs.min.js"),require("../util/simple-id-generator.js"),require("../util/string-helper.js"),require("@react-aria/live-announcer");var n=require("../util/use-event.js"),u=require("./modal-context.js"),d=require("./modal-v2.styles.js"),c=require("./slots/card.js"),m=require("./slots/close-button.js"),j=require("./slots/content.js"),v=require("./slots/footer.js");function
|
|
1
|
+
"use strict";var e=require("../_virtual/_tslib.js"),r=require("react/jsx-runtime"),t=require("@floating-ui/react"),a=require("clsx"),i=require("react"),s=require("../overlay/overlay.js"),l=require("../shared/hooks/useViewport.js");require("../theme/theme-provider/index.js"),require("../theme/theme-provider/context.js"),require("../theme/tokens/border.js"),require("../theme/tokens/colour.js"),require("../theme/tokens/font.js"),require("../theme/tokens/media-query.js");var o=require("../theme/utils/use-apply-styles.js");require("../theme/utils/use-media-query.js"),require("../util/calendar-helper.js"),require("../external/dayjs/dayjs.min.js"),require("../util/simple-id-generator.js"),require("../util/string-helper.js"),require("@react-aria/live-announcer");var n=require("../util/use-event.js"),u=require("./modal-context.js"),d=require("./modal-v2.styles.js"),c=require("./slots/card.js"),m=require("./slots/close-button.js"),j=require("./slots/content.js"),v=require("./slots/footer.js"),b=require("./slots/header.js");function h(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}var q=h(a),y=h(i);const C=Object.assign((a=>{var{id:c,show:m,onClose:j,animationFrom:v="bottom",children:b,enableOverlayClick:h=!0,rootComponentId:C,zIndex:x,onOverlayClick:f,dismissKeyboardOnShow:p=!0,"data-testid":g="modal","aria-label":O,"aria-labelledby":k,"aria-describedby":F,disableInitialFocus:I=!1,className:w}=a,N=e.__rest(a,["id","show","onClose","animationFrom","children","enableOverlayClick","rootComponentId","zIndex","onOverlayClick","dismissKeyboardOnShow","data-testid","aria-label","aria-labelledby","aria-describedby","disableInitialFocus","className"]);const S=n.useEvent((()=>{var e,r;p&&(null===(r=null===(e=document.activeElement)||void 0===e?void 0:e.blur)||void 0===r||r.call(e))})),{verticalHeight:H}=l.useViewport({enabled:m,onBeforeStart:S}),M=i.useRef(null),_=i.useRef(null),z=b&&y.default.cloneElement(b,{ref:M});o.useApplyStyle(_,{[d.tokens.container.verticalHeight]:null==H?null:`${H}px`});const{refs:B,context:E}=t.useFloating({open:m,onOpenChange:e=>{e||null==j||j()}}),{isMounted:P,status:R}=t.useTransitionStatus(E,{duration:300}),V=t.useDismiss(E,{outsidePress:!1,enabled:!!j}),{getFloatingProps:K}=t.useInteractions([V]);return r.jsx(s.Overlay,{"data-testid":`${g}-overlay`,show:m,enableOverlayClick:h,onOverlayClick:f,id:c,rootId:C,containerRef:M,zIndex:x,children:r.jsx("div",Object.assign({ref:_,"data-testid":g,"data-status":R,"data-animation-from":v},N,{className:q.default(d.container,w),children:r.jsx(u.ModalContext.Provider,{value:{onClose:j},children:P&&r.jsx(t.FloatingFocusManager,{context:E,initialFocus:I?-1:B.floating,children:r.jsx("div",{className:d.scrollContainer,children:r.jsx("div",Object.assign({ref:B.setFloating},K(),{role:"dialog","aria-label":O,"aria-labelledby":k,"aria-describedby":F,className:d.modalContainer,children:z}))})})})}))})}),{Card:c.Card,CloseButton:m.CloseButton,Content:j.Content,Footer:v.Footer,Header:b.Header});exports.ModalV2=C;
|
|
2
2
|
//# sourceMappingURL=modal-v2.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"modal-v2.js","sources":["../../../src/modal-v2/modal-v2.tsx"],"sourcesContent":["import {\n FloatingFocusManager,\n useDismiss,\n useFloating,\n useInteractions,\n useTransitionStatus,\n} from \"@floating-ui/react\";\nimport clsx from \"clsx\";\nimport React, { useRef } from \"react\";\n\nimport { Overlay } from \"../overlay/overlay\";\nimport { useViewport } from \"../shared/hooks\";\nimport { useApplyStyle } from \"../theme\";\nimport { useEvent } from \"../util\";\nimport { ModalContext } from \"./modal-context\";\nimport * as styles from \"./modal-v2.styles\";\nimport { Card, CloseButton, Content, Footer } from \"./slots\";\nimport type { ModalV2Props } from \"./types\";\n\nconst Base = ({\n id,\n show,\n onClose,\n animationFrom = \"bottom\",\n children,\n enableOverlayClick = true,\n rootComponentId,\n zIndex,\n onOverlayClick,\n dismissKeyboardOnShow = true,\n \"data-testid\": testId = \"modal\",\n \"aria-label\": ariaLabel,\n \"aria-labelledby\": ariaLabelledBy,\n \"aria-describedby\": ariaDescribedBy,\n disableInitialFocus = false,\n className,\n ...otherProps\n}: ModalV2Props): JSX.Element => {\n // =========================================================================\n // CONST, STATE, REF\n // =========================================================================\n const dismissKeyboard = useEvent(() => {\n if (dismissKeyboardOnShow) {\n (document.activeElement as HTMLElement)?.blur?.();\n }\n });\n const { verticalHeight } = useViewport({\n enabled: show,\n onBeforeStart: dismissKeyboard,\n });\n const childRef = useRef<HTMLDivElement>(null);\n const containerRef = useRef<HTMLDivElement>(null);\n const childWithRef =\n children && React.cloneElement(children, { ref: childRef });\n\n useApplyStyle(containerRef, {\n [styles.tokens.container.verticalHeight]:\n verticalHeight == null ? null : `${verticalHeight}px`,\n });\n\n // =========================================================================\n // FLOATING UI CONFIG\n // =========================================================================\n const { refs, context } = useFloating({\n open: show,\n onOpenChange: (isOpen) => {\n if (!isOpen) {\n onClose?.();\n }\n },\n });\n const { isMounted, status } = useTransitionStatus(context, {\n duration: 300,\n });\n const dismiss = useDismiss(context, {\n /* handled by overlayclick */\n outsidePress: false,\n enabled: !!onClose,\n });\n const { getFloatingProps } = useInteractions([dismiss]);\n\n // =========================================================================\n // RENDER FUNCTIONS\n // =========================================================================\n return (\n <Overlay\n data-testid={`${testId}-overlay`}\n show={show}\n enableOverlayClick={enableOverlayClick}\n onOverlayClick={onOverlayClick}\n id={id}\n rootId={rootComponentId}\n containerRef={childRef}\n zIndex={zIndex}\n >\n <div\n ref={containerRef}\n data-testid={testId}\n data-status={status}\n data-animation-from={animationFrom}\n {...otherProps}\n className={clsx(styles.container, className)}\n >\n <ModalContext.Provider value={{ onClose }}>\n {isMounted && (\n <FloatingFocusManager\n context={context}\n initialFocus={\n disableInitialFocus ? -1 : refs.floating\n }\n >\n <div className={styles.scrollContainer}>\n <div\n ref={refs.setFloating}\n {...getFloatingProps()}\n role=\"dialog\"\n aria-label={ariaLabel}\n aria-labelledby={ariaLabelledBy}\n aria-describedby={ariaDescribedBy}\n className={styles.modalContainer}\n >\n {childWithRef}\n </div>\n </div>\n </FloatingFocusManager>\n )}\n </ModalContext.Provider>\n </div>\n </Overlay>\n );\n};\n\n// @catalog\n/**\n * A composable modal dialog with slot-based content layout.\n *\n * Use `ModalV2` when you need a controlled overlay dialog with structured\n * content slots.\n *\n * Sub-components:\n * - `ModalV2.Card` — wraps modal content and arranges `Content`, `Footer`, and `CloseButton` slots in the correct layout.\n * - `ModalV2.CloseButton` — renders an accessible close button that invokes the modal's `onClose` callback.\n * - `ModalV2.Content` — container for the body content of the modal card.\n * - `ModalV2.Footer` — footer area for primary and secondary action buttons.\n */\nexport const ModalV2 = Object.assign(Base, {\n /** Wraps modal content and arranges `Content`, `Footer`, and `CloseButton` slots in the correct layout. */\n Card,\n /** Renders an accessible close button that invokes the modal's `onClose` callback. */\n CloseButton,\n /** Container for the body content of the modal card. */\n Content,\n /** Footer area for primary and secondary action buttons. */\n Footer,\n});\n"],"names":["ModalV2","Object","assign","_a","id","show","onClose","animationFrom","children","enableOverlayClick","rootComponentId","zIndex","onOverlayClick","dismissKeyboardOnShow","testId","ariaLabel","ariaLabelledBy","ariaDescribedBy","disableInitialFocus","className","otherProps","__rest","dismissKeyboard","useEvent","_b","document","activeElement","blur","verticalHeight","useViewport","enabled","onBeforeStart","childRef","useRef","containerRef","childWithRef","React","cloneElement","ref","useApplyStyle","styles.tokens","container","refs","context","useFloating","open","onOpenChange","isOpen","isMounted","status","useTransitionStatus","duration","dismiss","useDismiss","outsidePress","getFloatingProps","useInteractions","_jsx","Overlay","rootId","clsx","styles.container","ModalContext","Provider","value","FloatingFocusManager","initialFocus","floating","styles.scrollContainer","setFloating","role","styles.modalContainer","Card","CloseButton","Content","Footer"],"mappings":"
|
|
1
|
+
{"version":3,"file":"modal-v2.js","sources":["../../../src/modal-v2/modal-v2.tsx"],"sourcesContent":["import {\n FloatingFocusManager,\n useDismiss,\n useFloating,\n useInteractions,\n useTransitionStatus,\n} from \"@floating-ui/react\";\nimport clsx from \"clsx\";\nimport React, { useRef } from \"react\";\n\nimport { Overlay } from \"../overlay/overlay\";\nimport { useViewport } from \"../shared/hooks\";\nimport { useApplyStyle } from \"../theme\";\nimport { useEvent } from \"../util\";\nimport { ModalContext } from \"./modal-context\";\nimport * as styles from \"./modal-v2.styles\";\nimport { Card, CloseButton, Content, Footer, Header } from \"./slots\";\nimport type { ModalV2Props } from \"./types\";\n\nconst Base = ({\n id,\n show,\n onClose,\n animationFrom = \"bottom\",\n children,\n enableOverlayClick = true,\n rootComponentId,\n zIndex,\n onOverlayClick,\n dismissKeyboardOnShow = true,\n \"data-testid\": testId = \"modal\",\n \"aria-label\": ariaLabel,\n \"aria-labelledby\": ariaLabelledBy,\n \"aria-describedby\": ariaDescribedBy,\n disableInitialFocus = false,\n className,\n ...otherProps\n}: ModalV2Props): JSX.Element => {\n // =========================================================================\n // CONST, STATE, REF\n // =========================================================================\n const dismissKeyboard = useEvent(() => {\n if (dismissKeyboardOnShow) {\n (document.activeElement as HTMLElement)?.blur?.();\n }\n });\n const { verticalHeight } = useViewport({\n enabled: show,\n onBeforeStart: dismissKeyboard,\n });\n const childRef = useRef<HTMLDivElement>(null);\n const containerRef = useRef<HTMLDivElement>(null);\n const childWithRef =\n children && React.cloneElement(children, { ref: childRef });\n\n useApplyStyle(containerRef, {\n [styles.tokens.container.verticalHeight]:\n verticalHeight == null ? null : `${verticalHeight}px`,\n });\n\n // =========================================================================\n // FLOATING UI CONFIG\n // =========================================================================\n const { refs, context } = useFloating({\n open: show,\n onOpenChange: (isOpen) => {\n if (!isOpen) {\n onClose?.();\n }\n },\n });\n const { isMounted, status } = useTransitionStatus(context, {\n duration: 300,\n });\n const dismiss = useDismiss(context, {\n /* handled by overlayclick */\n outsidePress: false,\n enabled: !!onClose,\n });\n const { getFloatingProps } = useInteractions([dismiss]);\n\n // =========================================================================\n // RENDER FUNCTIONS\n // =========================================================================\n return (\n <Overlay\n data-testid={`${testId}-overlay`}\n show={show}\n enableOverlayClick={enableOverlayClick}\n onOverlayClick={onOverlayClick}\n id={id}\n rootId={rootComponentId}\n containerRef={childRef}\n zIndex={zIndex}\n >\n <div\n ref={containerRef}\n data-testid={testId}\n data-status={status}\n data-animation-from={animationFrom}\n {...otherProps}\n className={clsx(styles.container, className)}\n >\n <ModalContext.Provider value={{ onClose }}>\n {isMounted && (\n <FloatingFocusManager\n context={context}\n initialFocus={\n disableInitialFocus ? -1 : refs.floating\n }\n >\n <div className={styles.scrollContainer}>\n <div\n ref={refs.setFloating}\n {...getFloatingProps()}\n role=\"dialog\"\n aria-label={ariaLabel}\n aria-labelledby={ariaLabelledBy}\n aria-describedby={ariaDescribedBy}\n className={styles.modalContainer}\n >\n {childWithRef}\n </div>\n </div>\n </FloatingFocusManager>\n )}\n </ModalContext.Provider>\n </div>\n </Overlay>\n );\n};\n\n// @catalog\n/**\n * A composable modal dialog with slot-based content layout.\n *\n * Use `ModalV2` when you need a controlled overlay dialog with structured\n * content slots.\n *\n * Sub-components:\n * - `ModalV2.Card` — wraps modal content and arranges `Content`, `Footer`, and `CloseButton` slots in the correct layout.\n * - `ModalV2.CloseButton` — renders an accessible close button that invokes the modal's `onClose` callback.\n * - `ModalV2.Content` — container for the body content of the modal card.\n * - `ModalV2.Footer` — footer area for primary and secondary action buttons.\n * - `ModalV2.Header` — header bar with a close button and optional title. Use instead of `CloseButton` when a heading is needed.\n */\nexport const ModalV2 = Object.assign(Base, {\n /** Wraps modal content and arranges `Content`, `Footer`, and `CloseButton` slots in the correct layout. */\n Card,\n /** Renders an accessible close button that invokes the modal's `onClose` callback. */\n CloseButton,\n /** Container for the body content of the modal card. */\n Content,\n /** Footer area for primary and secondary action buttons. */\n Footer,\n /** Header bar with a close button and optional title. Use instead of `CloseButton` when a heading is needed. */\n Header,\n});\n"],"names":["ModalV2","Object","assign","_a","id","show","onClose","animationFrom","children","enableOverlayClick","rootComponentId","zIndex","onOverlayClick","dismissKeyboardOnShow","testId","ariaLabel","ariaLabelledBy","ariaDescribedBy","disableInitialFocus","className","otherProps","__rest","dismissKeyboard","useEvent","_b","document","activeElement","blur","verticalHeight","useViewport","enabled","onBeforeStart","childRef","useRef","containerRef","childWithRef","React","cloneElement","ref","useApplyStyle","styles.tokens","container","refs","context","useFloating","open","onOpenChange","isOpen","isMounted","status","useTransitionStatus","duration","dismiss","useDismiss","outsidePress","getFloatingProps","useInteractions","_jsx","Overlay","rootId","clsx","styles.container","ModalContext","Provider","value","FloatingFocusManager","initialFocus","floating","styles.scrollContainer","setFloating","role","styles.modalContainer","Card","CloseButton","Content","Footer","Header"],"mappings":"+lCAmBA,MA+HaA,EAAUC,OAAOC,QA/HhBC,QAAAC,GACVA,EAAEC,KACFA,EAAIC,QACJA,EAAOC,cACPA,EAAgB,SAAQC,SACxBA,EAAQC,mBACRA,GAAqB,EAAIC,gBACzBA,EAAeC,OACfA,EAAMC,eACNA,EAAcC,sBACdA,GAAwB,EACxB,cAAeC,EAAS,QACxB,aAAcC,EACd,kBAAmBC,EACnB,mBAAoBC,EAAeC,oBACnCA,GAAsB,EAAKC,UAC3BA,GAAShB,EACNiB,EAAUC,EAAAA,OAAAlB,EAjBH,CAAA,KAAA,OAAA,UAAA,gBAAA,WAAA,qBAAA,kBAAA,SAAA,iBAAA,wBAAA,cAAA,aAAA,kBAAA,mBAAA,sBAAA,cAsBV,MAAMmB,EAAkBC,EAAAA,UAAS,aACzBV,YACAW,EAAuC,UAAtCC,SAASC,qBAA6B,IAAAvB,OAAA,EAAAA,EAAEwB,6BAC7C,KAEEC,eAAEA,GAAmBC,cAAY,CACnCC,QAASzB,EACT0B,cAAeT,IAEbU,EAAWC,EAAAA,OAAuB,MAClCC,EAAeD,EAAAA,OAAuB,MACtCE,EACF3B,GAAY4B,UAAMC,aAAa7B,EAAU,CAAE8B,IAAKN,IAEpDO,EAAAA,cAAcL,EAAc,CACxB,CAACM,EAAAA,OAAcC,UAAUb,gBACH,MAAlBA,EAAyB,KAAO,GAAGA,QAM3C,MAAMc,KAAEA,EAAIC,QAAEA,GAAYC,cAAY,CAClCC,KAAMxC,EACNyC,aAAeC,IACNA,GACDzC,SAAAA,GACJ,KAGF0C,UAAEA,EAASC,OAAEA,GAAWC,EAAAA,oBAAoBP,EAAS,CACvDQ,SAAU,MAERC,EAAUC,EAAAA,WAAWV,EAAS,CAEhCW,cAAc,EACdxB,UAAWxB,KAETiD,iBAAEA,GAAqBC,kBAAgB,CAACJ,IAK9C,OACIK,MAACC,EAAAA,QAAO,CAAA,cACS,GAAG5C,YAChBT,KAAMA,EACNI,mBAAoBA,EACpBG,eAAgBA,EAChBR,GAAIA,EACJuD,OAAQjD,EACRwB,aAAcF,EACdrB,OAAQA,EAAMH,SAEdiD,EAAAA,IAAA,MAAAxD,OAAAC,OAAA,CACIoC,IAAKJ,EAAY,cACJpB,EAAM,cACNmC,EAAM,sBACE1C,GACjBa,GACJD,UAAWyC,UAAKC,EAAAA,UAAkB1C,GAAUX,SAE5CiD,MAACK,EAAAA,aAAaC,SAAQ,CAACC,MAAO,CAAE1D,WAASE,SACpCwC,GACGS,EAAAA,IAACQ,uBAAoB,CACjBtB,QAASA,EACTuB,aACIhD,GAAsB,EAAKwB,EAAKyB,SAAQ3D,SAG5CiD,EAAAA,IAAA,MAAA,CAAKtC,UAAWiD,EAAAA,gBAAsB5D,SAClCiD,MAAA,MAAAxD,OAAAC,OAAA,CACIoC,IAAKI,EAAK2B,aACNd,IAAkB,CACtBe,KAAK,SAAQ,aACDvD,EAAS,kBACJC,EAAc,mBACbC,EAClBE,UAAWoD,EAAAA,wBAEVpC,eAOnB,GAkByB,MAEvCqC,EAAAA,iBAEAC,EAAAA,oBAEAC,EAAAA,eAEAC,EAAAA,cAEAC,EAAAA"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";var e=require("../../_virtual/_tslib.js"),r=require("react/jsx-runtime"),t=require("clsx"),a=require("react");require("../../util/calendar-helper.js"),require("../../external/dayjs/dayjs.min.js");var s=require("../../util/merge-refs.js");require("../../util/simple-id-generator.js"),require("../../util/string-helper.js"),require("@react-aria/live-announcer");var i=require("../../util/is-styled-components.js"),l=require("./close-button.js"),d=require("./content.js"),u=require("./footer.js"),n=require("./slot-styles.js");function
|
|
1
|
+
"use strict";var e=require("../../_virtual/_tslib.js"),r=require("react/jsx-runtime"),t=require("clsx"),a=require("react");require("../../util/calendar-helper.js"),require("../../external/dayjs/dayjs.min.js");var s=require("../../util/merge-refs.js");require("../../util/simple-id-generator.js"),require("../../util/string-helper.js"),require("@react-aria/live-announcer");var i=require("../../util/is-styled-components.js"),l=require("./close-button.js"),d=require("./content.js"),u=require("./footer.js"),n=require("./header.js"),o=require("./slot-styles.js");function c(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}var f=c(t),j=c(a);const q=j.default.forwardRef((function(t,a){var{id:c,"data-testid":q="modal-card",children:m,className:p,elementRef:y}=t,h=e.__rest(t,["id","data-testid","children","className","elementRef"]);const v=e=>j.default.Children.toArray(m).find((r=>((e,r)=>i.default(e.type)?e.type.target===r:e.type===r)(r,e))),g=v(l.CloseButton),C=v(d.Content),x=v(u.Footer),b=v(n.Header),N=!!g||!!b;return r.jsxs("div",Object.assign({ref:s.mergeRefs(a,y),id:c,"data-testid":q},h,{onClick:e=>{e.stopPropagation()},className:f.default(o.modalCard,p),children:[r.jsxs("div",{"data-has-close-button":!!N,className:f.default(o.slotSpacer),children:[C,x]}),N&&(b||g)]}))}));q.displayName="ModalV2.Card",exports.Card=q;
|
|
2
2
|
//# sourceMappingURL=card.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"card.js","sources":["../../../../src/modal-v2/slots/card.tsx"],"sourcesContent":["import clsx from \"clsx\";\nimport type { NamedExoticComponent } from \"react\";\nimport React from \"react\";\n\nimport { mergeRefs } from \"../../util\";\nimport isStyledComponent from \"../../util/is-styled-components\";\nimport type { ModalCardProps } from \"../types\";\nimport { CloseButton } from \"./close-button\";\nimport { Content } from \"./content\";\nimport { Footer } from \"./footer\";\nimport * as styles from \"./slot-styles\";\n\nfunction CardInner(\n {\n id,\n \"data-testid\": testId = \"modal-card\",\n children,\n className,\n elementRef,\n ...otherProps\n }: ModalCardProps,\n ref: React.ForwardedRef<HTMLDivElement>\n) {\n // =============================================================================\n // EVENT HANDLERS\n // =============================================================================\n const handleOnClick = (event: React.MouseEvent) => {\n event.stopPropagation();\n };\n\n // =========================================================================\n // HELPERS\n // =========================================================================\n const isComponentType = (child: React.ReactPortal, type: any) =>\n isStyledComponent(child.type)\n ? (child.type as unknown as { target: any }).target === type\n : child.type === type;\n\n const findComponentOfType = (type: any) => {\n return React.Children.toArray(children).find((child) =>\n isComponentType(child as React.ReactPortal, type)\n );\n };\n\n // =============================================================================\n // RENDER FUNCTIONS\n // =============================================================================\n const CloseButtonSlot = findComponentOfType(CloseButton);\n const ContentSlot = findComponentOfType(Content);\n const FooterSlot = findComponentOfType(Footer);\n\n const
|
|
1
|
+
{"version":3,"file":"card.js","sources":["../../../../src/modal-v2/slots/card.tsx"],"sourcesContent":["import clsx from \"clsx\";\nimport type { NamedExoticComponent } from \"react\";\nimport React from \"react\";\n\nimport { mergeRefs } from \"../../util\";\nimport isStyledComponent from \"../../util/is-styled-components\";\nimport type { ModalCardProps } from \"../types\";\nimport { CloseButton } from \"./close-button\";\nimport { Content } from \"./content\";\nimport { Footer } from \"./footer\";\nimport { Header } from \"./header\";\nimport * as styles from \"./slot-styles\";\n\nfunction CardInner(\n {\n id,\n \"data-testid\": testId = \"modal-card\",\n children,\n className,\n elementRef,\n ...otherProps\n }: ModalCardProps,\n ref: React.ForwardedRef<HTMLDivElement>\n) {\n // =============================================================================\n // EVENT HANDLERS\n // =============================================================================\n const handleOnClick = (event: React.MouseEvent) => {\n event.stopPropagation();\n };\n\n // =========================================================================\n // HELPERS\n // =========================================================================\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const isComponentType = (child: React.ReactPortal, type: any) =>\n isStyledComponent(child.type)\n ? // eslint-disable-next-line @typescript-eslint/no-explicit-any\n (child.type as unknown as { target: any }).target === type\n : child.type === type;\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const findComponentOfType = (type: any) => {\n return React.Children.toArray(children).find((child) =>\n isComponentType(child as React.ReactPortal, type)\n );\n };\n\n // =============================================================================\n // RENDER FUNCTIONS\n // =============================================================================\n const CloseButtonSlot = findComponentOfType(CloseButton);\n const ContentSlot = findComponentOfType(Content);\n const FooterSlot = findComponentOfType(Footer);\n const HeaderSlot = findComponentOfType(Header);\n\n const hasHeader = !!CloseButtonSlot || !!HeaderSlot;\n\n return (\n <div\n ref={mergeRefs(ref, elementRef)}\n id={id}\n data-testid={testId}\n {...otherProps}\n onClick={handleOnClick}\n className={clsx(styles.modalCard, className)}\n >\n <div\n data-has-close-button={!!hasHeader}\n className={clsx(styles.slotSpacer)}\n >\n {ContentSlot}\n {FooterSlot}\n </div>\n {hasHeader && (HeaderSlot || CloseButtonSlot)}\n </div>\n );\n}\n\nexport const Card = React.forwardRef<HTMLDivElement, ModalCardProps>(CardInner);\n\n(Card as NamedExoticComponent).displayName = \"ModalV2.Card\";\n"],"names":["Card","React","forwardRef","_a","ref","id","testId","children","className","elementRef","otherProps","__rest","findComponentOfType","type","Children","toArray","find","child","isStyledComponent","target","isComponentType","CloseButtonSlot","CloseButton","ContentSlot","Content","FooterSlot","Footer","HeaderSlot","Header","hasHeader","_jsxs","Object","assign","mergeRefs","onClick","event","stopPropagation","clsx","styles.modalCard","styles.slotSpacer","displayName"],"mappings":"4oBA+EO,MAAMA,EAAOC,EAAAA,QAAMC,YAlE1B,SACIC,EAQAC,GARA,IAAAC,GACIA,EACA,cAAeC,EAAS,aAAYC,SACpCA,EAAQC,UACRA,EAASC,WACTA,GAAUN,EACPO,EAAUC,EAAAA,OAAAR,EANjB,0DAaA,MAeMS,EAAuBC,GAClBZ,UAAMa,SAASC,QAAQR,GAAUS,MAAMC,GAR1B,EAACA,EAA0BJ,IAC/CK,EAAAA,QAAkBD,EAAMJ,MAEjBI,EAAMJ,KAAoCM,SAAWN,EACtDI,EAAMJ,OAASA,EAKjBO,CAAgBH,EAA4BJ,KAO9CQ,EAAkBT,EAAoBU,eACtCC,EAAcX,EAAoBY,WAClCC,EAAab,EAAoBc,UACjCC,EAAaf,EAAoBgB,UAEjCC,IAAcR,KAAqBM,EAEzC,OACIG,EAAAA,KAAA,MAAAC,OAAAC,OAAA,CACI5B,IAAK6B,EAAAA,UAAU7B,EAAKK,GACpBJ,GAAIA,EAAE,cACOC,GACTI,EAAU,CACdwB,QArCeC,IACnBA,EAAMC,iBAAiB,EAqCnB5B,UAAW6B,EAAAA,QAAKC,YAAkB9B,GAAUD,SAAA,CAE5CuB,OAAA,MAAA,CAAA,0BAC6BD,EACzBrB,UAAW6B,EAAAA,QAAKE,EAAAA,YAAkBhC,SAAA,CAEjCgB,EACAE,KAEJI,IAAcF,GAAcN,MAGzC,IAICrB,EAA8BwC,YAAc"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";var e=require("../../_virtual/_tslib.js"),t=require("react/jsx-runtime"),s=require("@lifesg/react-icons/cross"),a=require("clsx"),i=require("react"),r=require("../../shared/clickable-icon/clickable-icon.js"),o=require("../modal-context.js"),l=require("./slot-styles.js");function c(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}var n=c(a);const d=a=>{var{"data-testid":c="modal-header",title:d,closeButtonPosition:u="right",className:h}=a,j=e.__rest(a,["data-testid","title","closeButtonPosition","className"]);const{onClose:b}=i.useContext(o.ModalContext);return t.jsxs("div",Object.assign({"data-testid":c,"data-close-button-position":u,className:n.default(l.headerContainer,h)},j,{children:[t.jsx(r.ClickableIcon,{onClick:b,"data-testid":"close-button",focusHighlight:!1,focusOutline:"browser","aria-label":"Close button",className:l.headerCloseButton,children:t.jsx(s.CrossIcon,{"aria-hidden":!0})}),d&&t.jsx("span",{className:l.headerTitle,children:d}),d&&t.jsx("div",{className:l.headerSpacer,"aria-hidden":!0})]}))};d.displayName="ModalV2.Header",exports.Header=d;
|
|
2
|
+
//# sourceMappingURL=header.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"header.js","sources":["../../../../src/modal-v2/slots/header.tsx"],"sourcesContent":["import { CrossIcon } from \"@lifesg/react-icons/cross\";\nimport clsx from \"clsx\";\nimport { useContext } from \"react\";\n\nimport { ClickableIcon } from \"../../shared/clickable-icon\";\nimport { ModalContext } from \"../modal-context\";\nimport type { ModalHeaderProps } from \"../types\";\nimport * as styles from \"./slot-styles\";\n\nexport const Header = ({\n \"data-testid\": testId = \"modal-header\",\n title,\n closeButtonPosition = \"right\",\n className,\n ...otherProps\n}: ModalHeaderProps) => {\n const { onClose } = useContext(ModalContext);\n\n return (\n <div\n data-testid={testId}\n data-close-button-position={closeButtonPosition}\n className={clsx(styles.headerContainer, className)}\n {...otherProps}\n >\n <ClickableIcon\n onClick={onClose}\n data-testid=\"close-button\"\n focusHighlight={false}\n focusOutline=\"browser\"\n aria-label=\"Close button\"\n className={styles.headerCloseButton}\n >\n <CrossIcon aria-hidden />\n </ClickableIcon>\n {title && <span className={styles.headerTitle}>{title}</span>}\n {title && <div className={styles.headerSpacer} aria-hidden />}\n </div>\n );\n};\n\nHeader.displayName = \"ModalV2.Header\";\n"],"names":["Header","_a","testId","title","closeButtonPosition","className","otherProps","__rest","onClose","useContext","ModalContext","_jsxs","Object","assign","clsx","styles.headerContainer","children","_jsx","ClickableIcon","onClick","focusHighlight","focusOutline","styles.headerCloseButton","CrossIcon","styles.headerTitle","styles.headerSpacer","displayName"],"mappings":"+WASO,MAAMA,EAAUC,IAAA,IACnB,cAAeC,EAAS,eAAcC,MACtCA,EAAKC,oBACLA,EAAsB,QAAOC,UAC7BA,GAASJ,EACNK,EAAUC,EAAAA,OAAAN,EALM,2DAOnB,MAAMO,QAAEA,GAAYC,EAAAA,WAAWC,gBAE/B,OACIC,EAAAA,KAAA,MAAAC,OAAAC,OAAA,CAAA,cACiBX,EAAM,6BACSE,EAC5BC,UAAWS,EAAAA,QAAKC,EAAAA,gBAAwBV,IACpCC,EAAU,CAAAU,SAAA,CAEdC,EAAAA,IAACC,EAAAA,cAAa,CACVC,QAASX,EAAO,cACJ,eACZY,gBAAgB,EAChBC,aAAa,UAAS,aACX,eACXhB,UAAWiB,EAAAA,kBAAwBN,SAEnCC,EAAAA,IAACM,EAAAA,UAAS,CAAA,eAAA,MAEbpB,GAASc,EAAAA,IAAA,OAAA,CAAMZ,UAAWmB,EAAAA,YAAkBR,SAAGb,IAC/CA,GAASc,EAAAA,IAAA,MAAA,CAAKZ,UAAWoB,EAAAA,aAAmB,eAAA,OAC3C,EAIdzB,EAAO0B,YAAc"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";require("./slot-
|
|
1
|
+
"use strict";require("./slot-styles_10ut1v7.css");exports.closeButtonContainer="c1247joo",exports.contentContainer="c1ls09wh",exports.footerContainer="f1s12qxk",exports.headerCloseButton="ha88pah",exports.headerContainer="h1adf5mq",exports.headerSpacer="h3mtfiz",exports.headerTitle="hii7rdr",exports.modalCard="metykyj",exports.slotSpacer="s1vsayl1",exports.styledClickableIcon="st53q25";
|
|
2
2
|
//# sourceMappingURL=slot-styles.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"slot-styles.js","sources":["../../../../src/modal-v2/slots/slot-styles.ts"],"sourcesContent":["import { css } from \"@linaria/core\";\n\nimport {\n Breakpoint,\n Colour,\n MediaQuery,\n Radius,\n Shadow,\n Spacing,\n} from \"../../theme\";\n\n// =============================================================================\n// Tokens and attributes\n// =============================================================================\nexport const slotSpacerHasCloseButtonAttribute = \"data-has-close-button\";\nconst internalSlotSpacerTokens = {\n firstChildMarginTop:\n \"--fds-internal-modalV2-slotSpacer-firstChildMarginTop\",\n} as const;\n\nexport const slotSpacerTokens = {\n firstChildMarginTopWithCloseButton:\n \"--fds-internal-modalV2-slotSpacer-firstChildMarginTopWithCloseButton\",\n firstChildMarginTopNoCloseButton:\n \"--fds-internal-modalV2-slotSpacer-firstChildMarginTopNoCloseButton\",\n\n contentLastChildMarginBottom:\n \"--fds-internal-modalV2-slotSpacer-contentLastChildMarginBottom\",\n\n footerNotFirstChildMarginTop:\n \"--fds-internal-modalV2-slotSpacer-footerNotFirstChildMarginTop\",\n footerLastChildMarginBottom:\n \"--fds-internal-modalV2-slotSpacer-footerLastChildMarginBottom\",\n} as const;\n\n// =============================================================================\n// STYLING\n// =============================================================================\nexport const modalCard = css`\n width: 40rem;\n margin: ${Spacing[\"spacing-64\"]} auto;\n background: ${Colour.bg};\n box-shadow: ${Shadow[\"xs-strong\"]};\n border-radius: ${Radius[\"lg\"]};\n\n display: flex;\n flex-direction: column-reverse;\n\n max-width: calc(100% - ${Breakpoint[\"xxl-margin\"]} * 2);\n\n ${MediaQuery.MaxWidth.xl} {\n max-width: calc(100% - ${Breakpoint[\"xl-margin\"]} * 2);\n }\n\n ${MediaQuery.MaxWidth.lg} {\n max-width: calc(100% - ${Breakpoint[\"lg-margin\"]} * 2);\n }\n\n ${MediaQuery.MaxWidth.md} {\n max-width: calc(100% - ${Breakpoint[\"md-margin\"]} * 2);\n }\n\n ${MediaQuery.MaxWidth.sm} {\n max-width: calc(100% - ${Breakpoint[\"sm-margin\"]} * 2);\n }\n\n ${MediaQuery.MaxWidth.xs} {\n max-width: calc(100% - ${Breakpoint[\"xs-margin\"]} * 2);\n }\n\n ${MediaQuery.MaxWidth.xxs} {\n max-width: calc(100% - ${Breakpoint[\"xxs-margin\"]} * 2);\n }\n`;\n\nexport const closeButtonContainer = css`\n margin-right: ${Spacing[\"spacing-16\"]};\n margin-left: auto;\n margin-top: ${Spacing[\"spacing-16\"]};\n margin-bottom: ${Spacing[\"spacing-16\"]};\n`;\n\nexport const styledClickableIcon = css`\n padding: 0;\n color: ${Colour.icon};\n\n & svg {\n height: 2rem;\n width: 2rem;\n }\n`;\n\nexport const contentContainer = css`\n margin-right: ${Spacing[\"spacing-64\"]};\n margin-left: ${Spacing[\"spacing-64\"]};\n\n ${MediaQuery.MaxWidth.sm} {\n margin-right: ${Spacing[\"spacing-20\"]};\n margin-left: ${Spacing[\"spacing-20\"]};\n }\n`;\n\nexport const footerContainer = css`\n margin-right: ${Spacing[\"spacing-64\"]};\n margin-left: ${Spacing[\"spacing-64\"]};\n\n ${MediaQuery.MaxWidth.sm} {\n margin-right: ${Spacing[\"spacing-20\"]};\n margin-left: ${Spacing[\"spacing-20\"]};\n }\n\n display: flex;\n flex-direction: row-reverse; /* primary button on right */\n column-gap: ${Spacing[\"spacing-32\"]};\n row-gap: ${Spacing[\"spacing-16\"]};\n\n & > button {\n flex: 1;\n }\n\n ${MediaQuery.MaxWidth.md} {\n flex-direction: column;\n }\n`;\n\nexport const slotSpacer = css`\n ${slotSpacerTokens.contentLastChildMarginBottom}: initial;\n ${slotSpacerTokens.footerNotFirstChildMarginTop}: initial;\n ${slotSpacerTokens.footerLastChildMarginBottom}: initial;\n ${slotSpacerTokens.firstChildMarginTopWithCloseButton}: initial;\n ${slotSpacerTokens.firstChildMarginTopNoCloseButton}: initial;\n\n ${internalSlotSpacerTokens.firstChildMarginTop}: var(\n ${slotSpacerTokens.firstChildMarginTopNoCloseButton},\n ${Spacing[\"spacing-64\"]}\n );\n\n & > :where(.${contentContainer}:last-child) {\n margin-bottom: var(\n ${slotSpacerTokens.contentLastChildMarginBottom},\n ${Spacing[\"spacing-64\"]}\n );\n }\n\n & > :where(.${footerContainer}:not(:first-child)) {\n margin-top: var(\n ${slotSpacerTokens.footerNotFirstChildMarginTop},\n ${Spacing[\"spacing-32\"]}\n );\n }\n\n & > :where(.${footerContainer}:last-child) {\n margin-bottom: var(\n ${slotSpacerTokens.footerLastChildMarginBottom},\n ${Spacing[\"spacing-64\"]}\n );\n }\n\n &\n > :where(\n .${contentContainer}:first-child, .${footerContainer}:first-child\n ) {\n margin-top: var(${internalSlotSpacerTokens.firstChildMarginTop});\n }\n\n &[${slotSpacerHasCloseButtonAttribute}=\"true\"] {\n ${internalSlotSpacerTokens.firstChildMarginTop}: var(\n ${slotSpacerTokens.firstChildMarginTopWithCloseButton},\n 0\n );\n }\n\n &[${slotSpacerHasCloseButtonAttribute}=\"false\"] {\n ${internalSlotSpacerTokens.firstChildMarginTop}: var(\n ${slotSpacerTokens.firstChildMarginTopNoCloseButton},\n ${Spacing[\"spacing-64\"]}\n );\n }\n`;\n"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"slot-styles.js","sources":["../../../../src/modal-v2/slots/slot-styles.ts"],"sourcesContent":["import { css } from \"@linaria/core\";\n\nimport {\n Breakpoint,\n Colour,\n Font,\n MediaQuery,\n Radius,\n Shadow,\n Spacing,\n} from \"../../theme\";\n\n// =============================================================================\n// Tokens and attributes\n// =============================================================================\nexport const slotSpacerHasCloseButtonAttribute = \"data-has-close-button\";\nconst internalSlotSpacerTokens = {\n firstChildMarginTop:\n \"--fds-internal-modalV2-slotSpacer-firstChildMarginTop\",\n} as const;\n\nexport const slotSpacerTokens = {\n firstChildMarginTopWithCloseButton:\n \"--fds-internal-modalV2-slotSpacer-firstChildMarginTopWithCloseButton\",\n firstChildMarginTopNoCloseButton:\n \"--fds-internal-modalV2-slotSpacer-firstChildMarginTopNoCloseButton\",\n\n contentLastChildMarginBottom:\n \"--fds-internal-modalV2-slotSpacer-contentLastChildMarginBottom\",\n\n footerNotFirstChildMarginTop:\n \"--fds-internal-modalV2-slotSpacer-footerNotFirstChildMarginTop\",\n footerLastChildMarginBottom:\n \"--fds-internal-modalV2-slotSpacer-footerLastChildMarginBottom\",\n} as const;\n\n// =============================================================================\n// STYLING\n// =============================================================================\nexport const modalCard = css`\n width: 40rem;\n margin: ${Spacing[\"spacing-64\"]} auto;\n background: ${Colour.bg};\n box-shadow: ${Shadow[\"xs-strong\"]};\n border-radius: ${Radius[\"lg\"]};\n\n display: flex;\n flex-direction: column-reverse;\n\n max-width: calc(100% - ${Breakpoint[\"xxl-margin\"]} * 2);\n\n ${MediaQuery.MaxWidth.xl} {\n max-width: calc(100% - ${Breakpoint[\"xl-margin\"]} * 2);\n }\n\n ${MediaQuery.MaxWidth.lg} {\n max-width: calc(100% - ${Breakpoint[\"lg-margin\"]} * 2);\n }\n\n ${MediaQuery.MaxWidth.md} {\n max-width: calc(100% - ${Breakpoint[\"md-margin\"]} * 2);\n }\n\n ${MediaQuery.MaxWidth.sm} {\n max-width: calc(100% - ${Breakpoint[\"sm-margin\"]} * 2);\n }\n\n ${MediaQuery.MaxWidth.xs} {\n max-width: calc(100% - ${Breakpoint[\"xs-margin\"]} * 2);\n }\n\n ${MediaQuery.MaxWidth.xxs} {\n max-width: calc(100% - ${Breakpoint[\"xxs-margin\"]} * 2);\n }\n`;\n\nexport const closeButtonContainer = css`\n margin-right: ${Spacing[\"spacing-16\"]};\n margin-left: auto;\n margin-top: ${Spacing[\"spacing-16\"]};\n margin-bottom: ${Spacing[\"spacing-16\"]};\n`;\n\nexport const styledClickableIcon = css`\n padding: 0;\n color: ${Colour.icon};\n\n & svg {\n height: 2rem;\n width: 2rem;\n }\n`;\n\nexport const contentContainer = css`\n margin-right: ${Spacing[\"spacing-64\"]};\n margin-left: ${Spacing[\"spacing-64\"]};\n\n ${MediaQuery.MaxWidth.sm} {\n margin-right: ${Spacing[\"spacing-20\"]};\n margin-left: ${Spacing[\"spacing-20\"]};\n }\n`;\n\nexport const footerContainer = css`\n margin-right: ${Spacing[\"spacing-64\"]};\n margin-left: ${Spacing[\"spacing-64\"]};\n\n ${MediaQuery.MaxWidth.sm} {\n margin-right: ${Spacing[\"spacing-20\"]};\n margin-left: ${Spacing[\"spacing-20\"]};\n }\n\n display: flex;\n flex-direction: row-reverse; /* primary button on right */\n column-gap: ${Spacing[\"spacing-32\"]};\n row-gap: ${Spacing[\"spacing-16\"]};\n\n & > button {\n flex: 1;\n }\n\n ${MediaQuery.MaxWidth.md} {\n flex-direction: column;\n }\n`;\n\nexport const slotSpacer = css`\n ${slotSpacerTokens.contentLastChildMarginBottom}: initial;\n ${slotSpacerTokens.footerNotFirstChildMarginTop}: initial;\n ${slotSpacerTokens.footerLastChildMarginBottom}: initial;\n ${slotSpacerTokens.firstChildMarginTopWithCloseButton}: initial;\n ${slotSpacerTokens.firstChildMarginTopNoCloseButton}: initial;\n\n ${internalSlotSpacerTokens.firstChildMarginTop}: var(\n ${slotSpacerTokens.firstChildMarginTopNoCloseButton},\n ${Spacing[\"spacing-64\"]}\n );\n\n & > :where(.${contentContainer}:last-child) {\n margin-bottom: var(\n ${slotSpacerTokens.contentLastChildMarginBottom},\n ${Spacing[\"spacing-64\"]}\n );\n }\n\n & > :where(.${footerContainer}:not(:first-child)) {\n margin-top: var(\n ${slotSpacerTokens.footerNotFirstChildMarginTop},\n ${Spacing[\"spacing-32\"]}\n );\n }\n\n & > :where(.${footerContainer}:last-child) {\n margin-bottom: var(\n ${slotSpacerTokens.footerLastChildMarginBottom},\n ${Spacing[\"spacing-64\"]}\n );\n }\n\n &\n > :where(\n .${contentContainer}:first-child, .${footerContainer}:first-child\n ) {\n margin-top: var(${internalSlotSpacerTokens.firstChildMarginTop});\n }\n\n &[${slotSpacerHasCloseButtonAttribute}=\"true\"] {\n ${internalSlotSpacerTokens.firstChildMarginTop}: var(\n ${slotSpacerTokens.firstChildMarginTopWithCloseButton},\n 0\n );\n }\n\n &[${slotSpacerHasCloseButtonAttribute}=\"false\"] {\n ${internalSlotSpacerTokens.firstChildMarginTop}: var(\n ${slotSpacerTokens.firstChildMarginTopNoCloseButton},\n ${Spacing[\"spacing-64\"]}\n );\n }\n`;\n\nexport const headerContainer = css`\n display: flex;\n align-items: center;\n padding: ${Spacing[\"spacing-16\"]};\n\n &[data-close-button-position=\"right\"] {\n flex-direction: row-reverse;\n }\n`;\n\nexport const headerTitle = css`\n ${Font[\"heading-xs-semibold\"]}\n color: ${Colour.text};\n flex: 1;\n text-align: center;\n`;\n\nexport const headerCloseButton = css`\n padding: 0;\n color: ${Colour.icon};\n flex-shrink: 0;\n\n & svg {\n height: 2rem;\n width: 2rem;\n }\n`;\n\nexport const headerSpacer = css`\n width: 2rem;\n flex-shrink: 0;\n`;\n"],"names":[],"mappings":"6GA4EiC,oCAiBJ,mCAUD,qCA+FE,kCAjBF,gCA4BH,8BAlBD,4BAxJF,6BAuFC,uCA3CS"}
|
|
@@ -23,4 +23,8 @@
|
|
|
23
23
|
);}.s1vsayl1[data-has-close-button="false"]{--fds-internal-modalV2-slotSpacer-firstChildMarginTop:var(
|
|
24
24
|
--fds-internal-modalV2-slotSpacer-firstChildMarginTopNoCloseButton,
|
|
25
25
|
var(--fds-spacing-64)
|
|
26
|
-
);}
|
|
26
|
+
);}
|
|
27
|
+
.h1adf5mq{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;padding:var(--fds-spacing-16);}.h1adf5mq[data-close-button-position="right"]{-webkit-flex-direction:row-reverse;-ms-flex-direction:row-reverse;flex-direction:row-reverse;}
|
|
28
|
+
.hii7rdr{font-family:var(--fds-font-family-heading);font-variant:var(--fds-font-variant);font-size:var(--fds-font-heading-size-xs);font-weight:var(--fds-font-weight-semibold);line-height:var(--fds-font-heading-lh-xs);letter-spacing:var(--fds-font-heading-ls-xs);color:var(--fds-colour-text);-webkit-flex:1;-ms-flex:1;flex:1;text-align:center;}
|
|
29
|
+
.ha88pah{padding:0;color:var(--fds-colour-icon);-webkit-flex-shrink:0;-ms-flex-negative:0;flex-shrink:0;}.ha88pah svg{height:2rem;width:2rem;}
|
|
30
|
+
.h3mtfiz{width:2rem;-webkit-flex-shrink:0;-ms-flex-negative:0;flex-shrink:0;}}
|