@lifesg/react-design-system 4.0.0-alpha.7 → 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.
Files changed (268) hide show
  1. package/accordion/accordion-item.js.map +1 -1
  2. package/accordion/accordion.js.map +1 -1
  3. package/alert/alert.js.map +1 -1
  4. package/button/button.js +1 -1
  5. package/button/button.js.map +1 -1
  6. package/button/button.styles.d.ts +1 -0
  7. package/button/button.styles.js +1 -1
  8. package/button/button.styles.js.map +1 -1
  9. package/button/button.styles_19i4dfq.css +21 -0
  10. package/cjs/accordion/accordion-item.js.map +1 -1
  11. package/cjs/accordion/accordion.js.map +1 -1
  12. package/cjs/alert/alert.js.map +1 -1
  13. package/cjs/button/button.js +1 -1
  14. package/cjs/button/button.js.map +1 -1
  15. package/cjs/button/button.styles.js +1 -1
  16. package/cjs/button/button.styles.js.map +1 -1
  17. package/cjs/button/button.styles_19i4dfq.css +21 -0
  18. package/cjs/countdown-timer/countdown-timer.js.map +1 -1
  19. package/cjs/data-table/data-table.js +1 -1
  20. package/cjs/data-table/data-table.js.map +1 -1
  21. package/cjs/data-table/data-table.styles.js +1 -1
  22. package/cjs/data-table/data-table.styles.js.map +1 -1
  23. package/{data-table/data-table.styles_rxganh.css → cjs/data-table/data-table.styles_1tnlmhe.css} +7 -6
  24. package/cjs/date-range-input/date-range-input.js.map +1 -1
  25. package/cjs/e-signature/e-signature-canvas.js.map +1 -1
  26. package/cjs/error-display/error-display-data.js +1 -1
  27. package/cjs/error-display/error-display-data.js.map +1 -1
  28. package/cjs/error-display/inactivity-timer.js.map +1 -1
  29. package/cjs/external/dompurify/dist/purify.es.js +2 -2
  30. package/cjs/external/dompurify/dist/purify.es.js.map +1 -1
  31. package/cjs/file-download/file-list-card/file-list-card.js.map +1 -1
  32. package/cjs/file-upload/custom-sensors.js.map +1 -1
  33. package/cjs/file-upload/file-list/file-list.js.map +1 -1
  34. package/cjs/filter/addons/filter-item-checkbox-helpers.js.map +1 -1
  35. package/cjs/filter/addons/filter-item-checkbox.js.map +1 -1
  36. package/cjs/filter/addons/filter-item-checkbox.styles.js +1 -1
  37. package/cjs/filter/addons/filter-item-checkbox.styles.js.map +1 -1
  38. package/{filter/addons/filter-item-checkbox.styles_7degw7.css → cjs/filter/addons/filter-item-checkbox.styles_6nbpdl.css} +1 -1
  39. package/cjs/filter/filter-item.js.map +1 -1
  40. package/cjs/filter/filter-item.styles.js +1 -1
  41. package/cjs/filter/filter-item.styles.js.map +1 -1
  42. package/cjs/filter/{filter-item.styles_cphjnj.css → filter-item.styles_1yixp8h.css} +1 -1
  43. package/cjs/filter/filter-modal.styles.js +1 -1
  44. package/cjs/filter/filter-modal.styles.js.map +1 -1
  45. package/{filter/filter-modal.styles_qw3xlg.css → cjs/filter/filter-modal.styles_kuth21.css} +1 -1
  46. package/cjs/filter/filter-sidebar.styles.js +1 -1
  47. package/cjs/filter/filter-sidebar.styles.js.map +1 -1
  48. package/cjs/filter/{filter-sidebar.styles_1otwpjl.css → filter-sidebar.styles_rbfq4f.css} +1 -1
  49. package/cjs/filter/filter.js.map +1 -1
  50. package/cjs/form/form-textarea/form-textarea.js +1 -1
  51. package/cjs/form/form-textarea/form-textarea.js.map +1 -1
  52. package/cjs/fullscreen-image-carousel/stateful-image.js.map +1 -1
  53. package/cjs/histogram-slider/histogram-slider.js.map +1 -1
  54. package/cjs/input-range-slider/input-range-slider.js.map +1 -1
  55. package/cjs/input-slider/input-slider.js.map +1 -1
  56. package/cjs/input-textarea/textarea-counter.js.map +1 -1
  57. package/cjs/input-textarea/textarea.js +1 -1
  58. package/cjs/input-textarea/textarea.js.map +1 -1
  59. package/cjs/input-textarea/textarea.styles.js +1 -1
  60. package/cjs/input-textarea/textarea.styles.js.map +1 -1
  61. package/cjs/input-textarea/{textarea.styles_q77m5x.css → textarea.styles_6we7bs.css} +3 -1
  62. package/cjs/modal/index.js.map +1 -1
  63. package/cjs/modal-v2/modal-v2.js +1 -1
  64. package/cjs/modal-v2/modal-v2.js.map +1 -1
  65. package/cjs/modal-v2/slots/card.js +1 -1
  66. package/cjs/modal-v2/slots/card.js.map +1 -1
  67. package/cjs/modal-v2/slots/header.js +2 -0
  68. package/cjs/modal-v2/slots/header.js.map +1 -0
  69. package/cjs/modal-v2/slots/slot-styles.js +1 -1
  70. package/cjs/modal-v2/slots/slot-styles.js.map +1 -1
  71. package/cjs/modal-v2/slots/{slot-styles_13sd376.css → slot-styles_10ut1v7.css} +5 -1
  72. package/cjs/navbar/navbar-items.js +1 -1
  73. package/cjs/navbar/navbar-items.js.map +1 -1
  74. package/cjs/navbar/navbar-items.styles.js +1 -1
  75. package/cjs/navbar/navbar-items.styles.js.map +1 -1
  76. package/cjs/navbar/{navbar-items.styles_1i3ltot.css → navbar-items.styles_1b1zx.css} +9 -8
  77. package/cjs/navbar/navbar-logo-data.js +1 -1
  78. package/cjs/navbar/navbar-logo-data.js.map +1 -1
  79. package/cjs/navbar/navbar.js.map +1 -1
  80. package/cjs/otp-input/otp-input.js.map +1 -1
  81. package/cjs/overlay/overlay.js.map +1 -1
  82. package/cjs/pagination/pagination.js.map +1 -1
  83. package/cjs/phone-number-input/phone-number-input.js.map +1 -1
  84. package/cjs/predictive-text-input/predictive-text-input.js.map +1 -1
  85. package/cjs/shared/dropdown-list/dropdown-list.js.map +1 -1
  86. package/cjs/shared/internal-calendar/calendar-manager.js.map +1 -1
  87. package/cjs/shared/standalone-date-input/standalone-date-input.js.map +1 -1
  88. package/cjs/singpass-button/singpass-button.styles.js +1 -1
  89. package/cjs/singpass-button/singpass-button.styles.js.map +1 -1
  90. package/cjs/singpass-button/{singpass-button.styles_1miyex3.css → singpass-button.styles_1fj2lru.css} +1 -1
  91. package/cjs/smart-app-banner/smart-app-banner.styles.js +1 -1
  92. package/cjs/smart-app-banner/smart-app-banner.styles.js.map +1 -1
  93. package/cjs/smart-app-banner/{smart-app-banner.styles_15u6yv4.css → smart-app-banner.styles_r6yjq9.css} +1 -1
  94. package/cjs/theme/types.js +1 -1
  95. package/cjs/theme/types.js.map +1 -1
  96. package/cjs/time-slot-bar/time-slot-bar.js.map +1 -1
  97. package/cjs/time-slot-bar-week/time-slot-bar-week-days.js.map +1 -1
  98. package/cjs/timetable/timetable.js.map +1 -1
  99. package/cjs/toast/toast.styles.js +1 -1
  100. package/cjs/toast/toast.styles.js.map +1 -1
  101. package/{toast/toast.styles_1e0l60w.css → cjs/toast/toast.styles_57j3lf.css} +1 -1
  102. package/cjs/toggle/toggle-icon.js +1 -1
  103. package/cjs/toggle/toggle-icon.js.map +1 -1
  104. package/cjs/toggle/toggle-icon.styles.js +1 -1
  105. package/cjs/toggle/toggle-icon.styles.js.map +1 -1
  106. package/cjs/toggle/{toggle-icon.styles_ba71y.css → toggle-icon.styles_o6dxr3.css} +3 -2
  107. package/cjs/toggle/toggle.js +1 -1
  108. package/cjs/toggle/toggle.js.map +1 -1
  109. package/cjs/toggle/toggle.styles.js +1 -1
  110. package/cjs/toggle/toggle.styles.js.map +1 -1
  111. package/cjs/toggle/toggle.styles_11tmfsr.css +41 -0
  112. package/cjs/unit-number/unit-number-input.js.map +1 -1
  113. package/cjs/util/is-styled-components.js.map +1 -1
  114. package/cjs/util/string-helper.js +1 -1
  115. package/cjs/util/string-helper.js.map +1 -1
  116. package/cjs/util/use-event-listener.js.map +1 -1
  117. package/cjs/util/use-state-actions.js.map +1 -1
  118. package/countdown-timer/countdown-timer.js.map +1 -1
  119. package/data-table/data-table.d.ts +1 -1
  120. package/data-table/data-table.js +1 -1
  121. package/data-table/data-table.js.map +1 -1
  122. package/data-table/data-table.styles.d.ts +1 -0
  123. package/data-table/data-table.styles.js +1 -1
  124. package/data-table/data-table.styles.js.map +1 -1
  125. package/{cjs/data-table/data-table.styles_rxganh.css → data-table/data-table.styles_1tnlmhe.css} +7 -6
  126. package/data-table/types.d.ts +4 -2
  127. package/date-range-input/date-range-input.js.map +1 -1
  128. package/docs/component-catalog.json +1 -1
  129. package/e-signature/e-signature-canvas.js.map +1 -1
  130. package/error-display/error-display-data.js +1 -1
  131. package/error-display/error-display-data.js.map +1 -1
  132. package/error-display/inactivity-timer.js.map +1 -1
  133. package/external/dompurify/dist/purify.es.js +2 -2
  134. package/external/dompurify/dist/purify.es.js.map +1 -1
  135. package/file-download/file-list-card/file-list-card.js.map +1 -1
  136. package/file-upload/custom-sensors.d.ts +2 -2
  137. package/file-upload/custom-sensors.js.map +1 -1
  138. package/file-upload/file-list/file-list.js.map +1 -1
  139. package/filter/addons/filter-item-checkbox-helpers.js.map +1 -1
  140. package/filter/addons/filter-item-checkbox.js.map +1 -1
  141. package/filter/addons/filter-item-checkbox.styles.js +1 -1
  142. package/filter/addons/filter-item-checkbox.styles.js.map +1 -1
  143. package/{cjs/filter/addons/filter-item-checkbox.styles_7degw7.css → filter/addons/filter-item-checkbox.styles_6nbpdl.css} +1 -1
  144. package/filter/filter-item.js.map +1 -1
  145. package/filter/filter-item.styles.js +1 -1
  146. package/filter/filter-item.styles.js.map +1 -1
  147. package/filter/{filter-item.styles_cphjnj.css → filter-item.styles_1yixp8h.css} +1 -1
  148. package/filter/filter-modal.styles.js +1 -1
  149. package/filter/filter-modal.styles.js.map +1 -1
  150. package/{cjs/filter/filter-modal.styles_qw3xlg.css → filter/filter-modal.styles_kuth21.css} +1 -1
  151. package/filter/filter-sidebar.styles.js +1 -1
  152. package/filter/filter-sidebar.styles.js.map +1 -1
  153. package/filter/{filter-sidebar.styles_1otwpjl.css → filter-sidebar.styles_rbfq4f.css} +1 -1
  154. package/filter/filter.js.map +1 -1
  155. package/form/form-textarea/form-textarea.js +1 -1
  156. package/form/form-textarea/form-textarea.js.map +1 -1
  157. package/fullscreen-image-carousel/stateful-image.js.map +1 -1
  158. package/fullscreen-image-carousel/types.d.ts +2 -2
  159. package/histogram-slider/histogram-slider.js.map +1 -1
  160. package/input-range-slider/input-range-slider.js.map +1 -1
  161. package/input-slider/input-slider.js.map +1 -1
  162. package/input-textarea/textarea-counter.js.map +1 -1
  163. package/input-textarea/textarea.js +1 -1
  164. package/input-textarea/textarea.js.map +1 -1
  165. package/input-textarea/textarea.styles.d.ts +2 -0
  166. package/input-textarea/textarea.styles.js +1 -1
  167. package/input-textarea/textarea.styles.js.map +1 -1
  168. package/input-textarea/{textarea.styles_q77m5x.css → textarea.styles_6we7bs.css} +3 -1
  169. package/input-textarea/types.d.ts +7 -0
  170. package/modal/index.d.ts +4 -0
  171. package/modal/index.js.map +1 -1
  172. package/modal/types.d.ts +2 -0
  173. package/modal-v2/modal-v2.d.ts +6 -0
  174. package/modal-v2/modal-v2.js +1 -1
  175. package/modal-v2/modal-v2.js.map +1 -1
  176. package/modal-v2/slots/card.js +1 -1
  177. package/modal-v2/slots/card.js.map +1 -1
  178. package/modal-v2/slots/header.d.ts +5 -0
  179. package/modal-v2/slots/header.js +2 -0
  180. package/modal-v2/slots/header.js.map +1 -0
  181. package/modal-v2/slots/index.d.ts +1 -0
  182. package/modal-v2/slots/slot-styles.d.ts +4 -0
  183. package/modal-v2/slots/slot-styles.js +1 -1
  184. package/modal-v2/slots/slot-styles.js.map +1 -1
  185. package/modal-v2/slots/{slot-styles_13sd376.css → slot-styles_10ut1v7.css} +5 -1
  186. package/modal-v2/types.d.ts +21 -0
  187. package/navbar/navbar-items.js +1 -1
  188. package/navbar/navbar-items.js.map +1 -1
  189. package/navbar/navbar-items.styles.d.ts +2 -1
  190. package/navbar/navbar-items.styles.js +1 -1
  191. package/navbar/navbar-items.styles.js.map +1 -1
  192. package/navbar/{navbar-items.styles_1i3ltot.css → navbar-items.styles_1b1zx.css} +9 -8
  193. package/navbar/navbar-logo-data.js +1 -1
  194. package/navbar/navbar-logo-data.js.map +1 -1
  195. package/navbar/navbar.js.map +1 -1
  196. package/otp-input/otp-input.js.map +1 -1
  197. package/overlay/overlay.js.map +1 -1
  198. package/package.json +1 -1
  199. package/pagination/pagination.js.map +1 -1
  200. package/phone-number-input/phone-number-input.js.map +1 -1
  201. package/predictive-text-input/predictive-text-input.js.map +1 -1
  202. package/shared/dropdown-list/dropdown-list.js.map +1 -1
  203. package/shared/internal-calendar/calendar-manager.js.map +1 -1
  204. package/shared/standalone-date-input/standalone-date-input.js.map +1 -1
  205. package/singpass-button/singpass-button.styles.js +1 -1
  206. package/singpass-button/singpass-button.styles.js.map +1 -1
  207. package/singpass-button/{singpass-button.styles_1miyex3.css → singpass-button.styles_1fj2lru.css} +1 -1
  208. package/smart-app-banner/smart-app-banner.styles.js +1 -1
  209. package/smart-app-banner/smart-app-banner.styles.js.map +1 -1
  210. package/smart-app-banner/{smart-app-banner.styles_15u6yv4.css → smart-app-banner.styles_r6yjq9.css} +1 -1
  211. package/theme/styles/a11y-playground.css +358 -87
  212. package/theme/styles/bookingsg.css +391 -85
  213. package/theme/styles/careercompass.css +396 -90
  214. package/theme/styles/ccube.css +402 -45
  215. package/theme/styles/imda.css +348 -85
  216. package/theme/styles/lifesg.css +377 -87
  217. package/theme/styles/mylegacy.css +382 -85
  218. package/theme/styles/oneservice.css +349 -86
  219. package/theme/styles/pa.css +172 -104
  220. package/theme/styles/rbs.css +403 -46
  221. package/theme/styles/sgw-digital-lobby.css +352 -87
  222. package/theme/styles/smgs.css +401 -95
  223. package/theme/styles/spf.css +208 -99
  224. package/theme/styles/supportgowhere.css +387 -90
  225. package/theme/styles/tote-board.css +816 -0
  226. package/theme/types.d.ts +1 -1
  227. package/theme/types.js +1 -1
  228. package/theme/types.js.map +1 -1
  229. package/time-slot-bar/time-slot-bar.js.map +1 -1
  230. package/time-slot-bar-week/time-slot-bar-week-days.js.map +1 -1
  231. package/timetable/timetable.js.map +1 -1
  232. package/toast/toast.styles.js +1 -1
  233. package/toast/toast.styles.js.map +1 -1
  234. package/{cjs/toast/toast.styles_1e0l60w.css → toast/toast.styles_57j3lf.css} +1 -1
  235. package/toggle/toggle-icon.d.ts +2 -1
  236. package/toggle/toggle-icon.js +1 -1
  237. package/toggle/toggle-icon.js.map +1 -1
  238. package/toggle/toggle-icon.styles.d.ts +1 -0
  239. package/toggle/toggle-icon.styles.js +1 -1
  240. package/toggle/toggle-icon.styles.js.map +1 -1
  241. package/toggle/{toggle-icon.styles_ba71y.css → toggle-icon.styles_o6dxr3.css} +3 -2
  242. package/toggle/toggle.js +1 -1
  243. package/toggle/toggle.js.map +1 -1
  244. package/toggle/toggle.styles.d.ts +18 -15
  245. package/toggle/toggle.styles.js +1 -1
  246. package/toggle/toggle.styles.js.map +1 -1
  247. package/toggle/toggle.styles_11tmfsr.css +41 -0
  248. package/tools/storybook-argtypes/services/arg-types-row-builder.d.ts +6 -0
  249. package/tools/storybook-argtypes/types.d.ts +13 -1
  250. package/unit-number/unit-number-input.js.map +1 -1
  251. package/util/is-styled-components.js.map +1 -1
  252. package/util/string-helper.d.ts +2 -2
  253. package/util/string-helper.js +1 -1
  254. package/util/string-helper.js.map +1 -1
  255. package/util/use-event-listener.js.map +1 -1
  256. package/util/use-state-actions.js.map +1 -1
  257. package/button/button.styles_1pxy0co.css +0 -20
  258. package/cjs/button/button.styles_1pxy0co.css +0 -20
  259. package/cjs/form/form-textarea/form-textarea.styles.js +0 -2
  260. package/cjs/form/form-textarea/form-textarea.styles.js.map +0 -1
  261. package/cjs/form/form-textarea/form-textarea.styles_1kneyif.css +0 -3
  262. package/cjs/toggle/toggle.styles_1t5qrye.css +0 -38
  263. package/form/form-textarea/form-textarea.styles.d.ts +0 -3
  264. package/form/form-textarea/form-textarea.styles.js +0 -2
  265. package/form/form-textarea/form-textarea.styles.js.map +0 -1
  266. package/form/form-textarea/form-textarea.styles_1kneyif.css +0 -3
  267. package/theme/styles/default.css +0 -158
  268. package/toggle/toggle.styles_1t5qrye.css +0 -38
@@ -1 +1 @@
1
- {"version":3,"file":"file-list-card.js","sources":["../../../../src/file-download/file-list-card/file-list-card.tsx"],"sourcesContent":["import { DownloadIcon } from \"@lifesg/react-icons\";\nimport { ExclamationCircleFillIcon } from \"@lifesg/react-icons/exclamation-circle-fill\";\nimport clsx from \"clsx\";\nimport { memo, useEffect, useRef, useState } from \"react\";\n\nimport { Button } from \"../../button\";\nimport { FileUploadHelper } from \"../../file-upload/helper\";\nimport { ImageWithFallback } from \"../../shared/image-with-fallback/image-with-fallback\";\nimport { useMaxWidthMediaQuery } from \"../../theme\";\nimport { StringHelper } from \"../../util\";\nimport * as styles from \"./file-list-card.styles\";\nimport type { FileListItemProps } from \"./types\";\n\nconst Component = ({ fileItem, onDownload }: FileListItemProps) => {\n // =========================================================================\n // CONST, STATE, REFS\n // =========================================================================\n const {\n id,\n name,\n size,\n errorMessage,\n thumbnailImageDataUrl,\n truncateText = true,\n ready = true,\n } = fileItem;\n\n // Local variables\n const [isLoading, setIsLoading] = useState<boolean>(false);\n const [isError, setIsError] = useState<boolean>(false);\n const fileSize = FileUploadHelper.formatFileSizeDisplay(size);\n const isMobile = useMaxWidthMediaQuery(\"sm\");\n const [displayText, setDisplayText] = useState<string>();\n const containerRef = useRef<HTMLDivElement>(null);\n\n // =========================================================================\n // EFFECTS\n // =========================================================================\n useEffect(() => {\n if (!containerRef.current) return;\n if (isMobile) {\n setDisplayText(getTruncatedText(name));\n } else {\n setDisplayText(name);\n }\n }, [name, isMobile]);\n\n // =========================================================================\n // EVENT HANDLERS\n // =========================================================================\n const handleDownload = async () => {\n if (!ready || isLoading) {\n return;\n }\n\n setIsLoading(true);\n try {\n setIsError(false);\n await onDownload(fileItem);\n } catch {\n setIsError(true);\n } finally {\n setIsLoading(false);\n }\n };\n\n // =========================================================================\n // HELPER FUNCTIONS\n // =========================================================================\n const getTruncatedText = (value: string) => {\n if (!truncateText) return value;\n\n const widthOfElement =\n containerRef && containerRef.current\n ? containerRef.current.getBoundingClientRect().width\n : 0;\n\n return StringHelper.truncateTwoLines(value, widthOfElement, 16, 1.5);\n };\n\n // =========================================================================\n // RENDER FUNCTIONS\n // =========================================================================\n const renderNameDescription = () => (\n <>\n <div className={styles.itemNameText} ref={containerRef}>\n {displayText}\n </div>\n {isError && (\n <div className={styles.desktopErrorMessage}>\n <ExclamationCircleFillIcon className={styles.errorIcon} />\n {errorMessage ? errorMessage : \"Something went wrong\"}\n </div>\n )}\n </>\n );\n\n const renderWithThumbnail = (thumbnailSrc: string) => (\n <>\n <div\n className={styles.thumbnailContainer}\n data-testid={`${id}-thumbnail`}\n >\n <ImageWithFallback\n className={styles.thumbnail}\n data-testid={`${id}-thumbnail-image`}\n src={thumbnailSrc}\n />\n </div>\n <div className={styles.extendedNameSection}>\n <div className={styles.nameSection}>\n {renderNameDescription()}\n </div>\n <div className={styles.fileSizeSection}>\n {fileSize ? fileSize : \"-\"}\n </div>\n {isError && (\n <div className={styles.mobileErrorMessage}>\n <ExclamationCircleFillIcon\n className={styles.errorIcon}\n />\n {errorMessage ? errorMessage : \"Something went wrong\"}\n </div>\n )}\n </div>\n </>\n );\n\n const renderDefault = () => (\n <>\n <div className={styles.nameSection}>{renderNameDescription()}</div>\n <div className={styles.fileSizeSection}>\n {fileSize ? fileSize : \"-\"}\n </div>\n {isError && (\n <div className={styles.mobileErrorMessage}>\n <ExclamationCircleFillIcon className={styles.errorIcon} />\n {errorMessage ? errorMessage : \"Something went wrong\"}\n </div>\n )}\n </>\n );\n\n const renderContents = () => {\n let content: JSX.Element;\n\n if (thumbnailImageDataUrl) {\n content = renderWithThumbnail(thumbnailImageDataUrl);\n } else {\n content = renderDefault();\n }\n\n return (\n <div\n className={clsx(\n styles.contentSection,\n !!thumbnailImageDataUrl && styles.contentSectionHasThumbnail\n )}\n >\n {content}\n </div>\n );\n };\n\n const renderActions = () => {\n return (\n <div className={styles.actionContainer}>\n <Button\n className={styles.iconButton}\n data-testid={`${id}-download-button`}\n type=\"button\"\n styleType=\"light\"\n sizeType=\"small\"\n aria-label={`download ${name}`}\n loading={isLoading || !ready}\n icon={<DownloadIcon />}\n />\n </div>\n );\n };\n\n return (\n <li className={styles.item} data-testid={id}>\n <div\n className={clsx(styles.box, isError && styles.boxError)}\n onClick={handleDownload}\n >\n {renderContents()}\n {renderActions()}\n </div>\n </li>\n );\n};\n\nexport const FileListCard = memo(Component);\n"],"names":["FileListCard","memo","fileItem","onDownload","id","name","size","errorMessage","thumbnailImageDataUrl","truncateText","ready","isLoading","setIsLoading","useState","isError","setIsError","fileSize","FileUploadHelper","formatFileSizeDisplay","isMobile","useMaxWidthMediaQuery","displayText","setDisplayText","containerRef","useRef","useEffect","current","getTruncatedText","value","widthOfElement","getBoundingClientRect","width","StringHelper","truncateTwoLines","renderNameDescription","_jsxs","_Fragment","children","_jsx","className","styles.itemNameText","ref","styles.desktopErrorMessage","ExclamationCircleFillIcon","styles.errorIcon","styles.item","clsx","styles.box","styles.boxError","onClick","__awaiter","_a","content","thumbnailSrc","styles.thumbnailContainer","ImageWithFallback","styles.thumbnail","src","styles.extendedNameSection","styles.nameSection","styles.fileSizeSection","styles.mobileErrorMessage","styles.contentSection","styles.contentSectionHasThumbnail","renderContents","styles.actionContainer","Button","styles.iconButton","type","styleType","sizeType","loading","icon","DownloadIcon"],"mappings":"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"}
1
+ {"version":3,"file":"file-list-card.js","sources":["../../../../src/file-download/file-list-card/file-list-card.tsx"],"sourcesContent":["import { DownloadIcon } from \"@lifesg/react-icons\";\nimport { ExclamationCircleFillIcon } from \"@lifesg/react-icons/exclamation-circle-fill\";\nimport clsx from \"clsx\";\nimport { memo, useEffect, useRef, useState } from \"react\";\n\nimport { Button } from \"../../button\";\nimport { FileUploadHelper } from \"../../file-upload/helper\";\nimport { ImageWithFallback } from \"../../shared/image-with-fallback/image-with-fallback\";\nimport { useMaxWidthMediaQuery } from \"../../theme\";\nimport { StringHelper } from \"../../util\";\nimport * as styles from \"./file-list-card.styles\";\nimport type { FileListItemProps } from \"./types\";\n\nconst Component = ({ fileItem, onDownload }: FileListItemProps) => {\n // =========================================================================\n // CONST, STATE, REFS\n // =========================================================================\n const {\n id,\n name,\n size,\n errorMessage,\n thumbnailImageDataUrl,\n truncateText = true,\n ready = true,\n } = fileItem;\n\n // Local variables\n const [isLoading, setIsLoading] = useState<boolean>(false);\n const [isError, setIsError] = useState<boolean>(false);\n const fileSize = FileUploadHelper.formatFileSizeDisplay(size);\n const isMobile = useMaxWidthMediaQuery(\"sm\");\n const [displayText, setDisplayText] = useState<string>();\n const containerRef = useRef<HTMLDivElement>(null);\n\n // =========================================================================\n // EFFECTS\n // =========================================================================\n useEffect(() => {\n if (!containerRef.current) return;\n if (isMobile) {\n setDisplayText(getTruncatedText(name));\n } else {\n setDisplayText(name);\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [name, isMobile]);\n\n // =========================================================================\n // EVENT HANDLERS\n // =========================================================================\n const handleDownload = async () => {\n if (!ready || isLoading) {\n return;\n }\n\n setIsLoading(true);\n try {\n setIsError(false);\n await onDownload(fileItem);\n } catch {\n setIsError(true);\n } finally {\n setIsLoading(false);\n }\n };\n\n // =========================================================================\n // HELPER FUNCTIONS\n // =========================================================================\n const getTruncatedText = (value: string) => {\n if (!truncateText) return value;\n\n const widthOfElement =\n containerRef && containerRef.current\n ? containerRef.current.getBoundingClientRect().width\n : 0;\n\n return StringHelper.truncateTwoLines(value, widthOfElement, 16, 1.5);\n };\n\n // =========================================================================\n // RENDER FUNCTIONS\n // =========================================================================\n const renderNameDescription = () => (\n <>\n <div className={styles.itemNameText} ref={containerRef}>\n {displayText}\n </div>\n {isError && (\n <div className={styles.desktopErrorMessage}>\n <ExclamationCircleFillIcon className={styles.errorIcon} />\n {errorMessage ? errorMessage : \"Something went wrong\"}\n </div>\n )}\n </>\n );\n\n const renderWithThumbnail = (thumbnailSrc: string) => (\n <>\n <div\n className={styles.thumbnailContainer}\n data-testid={`${id}-thumbnail`}\n >\n <ImageWithFallback\n className={styles.thumbnail}\n data-testid={`${id}-thumbnail-image`}\n src={thumbnailSrc}\n />\n </div>\n <div className={styles.extendedNameSection}>\n <div className={styles.nameSection}>\n {renderNameDescription()}\n </div>\n <div className={styles.fileSizeSection}>\n {fileSize ? fileSize : \"-\"}\n </div>\n {isError && (\n <div className={styles.mobileErrorMessage}>\n <ExclamationCircleFillIcon\n className={styles.errorIcon}\n />\n {errorMessage ? errorMessage : \"Something went wrong\"}\n </div>\n )}\n </div>\n </>\n );\n\n const renderDefault = () => (\n <>\n <div className={styles.nameSection}>{renderNameDescription()}</div>\n <div className={styles.fileSizeSection}>\n {fileSize ? fileSize : \"-\"}\n </div>\n {isError && (\n <div className={styles.mobileErrorMessage}>\n <ExclamationCircleFillIcon className={styles.errorIcon} />\n {errorMessage ? errorMessage : \"Something went wrong\"}\n </div>\n )}\n </>\n );\n\n const renderContents = () => {\n let content: JSX.Element;\n\n if (thumbnailImageDataUrl) {\n content = renderWithThumbnail(thumbnailImageDataUrl);\n } else {\n content = renderDefault();\n }\n\n return (\n <div\n className={clsx(\n styles.contentSection,\n !!thumbnailImageDataUrl && styles.contentSectionHasThumbnail\n )}\n >\n {content}\n </div>\n );\n };\n\n const renderActions = () => {\n return (\n <div className={styles.actionContainer}>\n <Button\n className={styles.iconButton}\n data-testid={`${id}-download-button`}\n type=\"button\"\n styleType=\"light\"\n sizeType=\"small\"\n aria-label={`download ${name}`}\n loading={isLoading || !ready}\n icon={<DownloadIcon />}\n />\n </div>\n );\n };\n\n return (\n <li className={styles.item} data-testid={id}>\n <div\n className={clsx(styles.box, isError && styles.boxError)}\n onClick={handleDownload}\n >\n {renderContents()}\n {renderActions()}\n </div>\n </li>\n );\n};\n\nexport const FileListCard = memo(Component);\n"],"names":["FileListCard","memo","fileItem","onDownload","id","name","size","errorMessage","thumbnailImageDataUrl","truncateText","ready","isLoading","setIsLoading","useState","isError","setIsError","fileSize","FileUploadHelper","formatFileSizeDisplay","isMobile","useMaxWidthMediaQuery","displayText","setDisplayText","containerRef","useRef","useEffect","current","getTruncatedText","value","widthOfElement","getBoundingClientRect","width","StringHelper","truncateTwoLines","renderNameDescription","_jsxs","_Fragment","children","_jsx","className","styles.itemNameText","ref","styles.desktopErrorMessage","ExclamationCircleFillIcon","styles.errorIcon","styles.item","clsx","styles.box","styles.boxError","onClick","__awaiter","_a","content","thumbnailSrc","styles.thumbnailContainer","ImageWithFallback","styles.thumbnail","src","styles.extendedNameSection","styles.nameSection","styles.fileSizeSection","styles.mobileErrorMessage","styles.contentSection","styles.contentSectionHasThumbnail","renderContents","styles.actionContainer","Button","styles.iconButton","type","styleType","sizeType","loading","icon","DownloadIcon"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"custom-sensors.js","sources":["../../../src/file-upload/custom-sensors.tsx"],"sourcesContent":["import {\n KeyboardSensor as LibKeyboardSensor,\n MouseSensor as LibMouseSensor,\n} from \"@dnd-kit/core\";\n\nexport class MouseSensor extends LibMouseSensor {\n static activators = [\n {\n eventName: \"onMouseDown\" as const,\n handler: ({ nativeEvent: event }: React.MouseEvent) => {\n return shouldHandleEvent(event.target as HTMLElement);\n },\n },\n ];\n}\n\nexport class KeyboardSensor extends LibKeyboardSensor {\n static activators = [\n {\n eventName: \"onKeyDown\" as const,\n handler: ({ nativeEvent: event }: React.KeyboardEvent<Element>) => {\n return shouldHandleEvent(event.target as HTMLElement);\n },\n },\n ];\n}\n\nfunction shouldHandleEvent(element: HTMLElement | null) {\n let current = element;\n while (current) {\n if (current.dataset && current.dataset.noDnd) {\n return false;\n }\n current = current.parentElement;\n }\n\n return true;\n}\n"],"names":["MouseSensor","LibMouseSensor","activators","eventName","handler","nativeEvent","event","shouldHandleEvent","target","KeyboardSensor","LibKeyboardSensor","element","current","dataset","noDnd","parentElement"],"mappings":"yEAKM,MAAOA,UAAoBC,EAAAA,aACtBD,EAAAE,WAAa,CAChB,CACIC,UAAW,cACXC,QAAS,EAAGC,YAAaC,KACdC,EAAkBD,EAAME,UAMzC,MAAOC,UAAuBC,EAAAA,gBAWpC,SAASH,EAAkBI,GACvB,IAAIC,EAAUD,EACd,KAAOC,GAAS,CACZ,GAAIA,EAAQC,SAAWD,EAAQC,QAAQC,MACnC,OAAO,EAEXF,EAAUA,EAAQG,aACtB,CAEA,OAAO,CACX,CApBWN,EAAAP,WAAa,CAChB,CACIC,UAAW,YACXC,QAAS,EAAGC,YAAaC,KACdC,EAAkBD,EAAME"}
1
+ {"version":3,"file":"custom-sensors.js","sources":["../../../src/file-upload/custom-sensors.tsx"],"sourcesContent":["import {\n KeyboardSensor as LibKeyboardSensor,\n MouseSensor as LibMouseSensor,\n} from \"@dnd-kit/core\";\n\nexport class MouseSensor extends LibMouseSensor {\n public static readonly activators = [\n {\n eventName: \"onMouseDown\" as const,\n handler: ({ nativeEvent: event }: React.MouseEvent) => {\n return shouldHandleEvent(event.target as HTMLElement);\n },\n },\n ];\n}\n\nexport class KeyboardSensor extends LibKeyboardSensor {\n public static readonly activators = [\n {\n eventName: \"onKeyDown\" as const,\n handler: ({ nativeEvent: event }: React.KeyboardEvent<Element>) => {\n return shouldHandleEvent(event.target as HTMLElement);\n },\n },\n ];\n}\n\nfunction shouldHandleEvent(element: HTMLElement | null) {\n let current = element;\n while (current) {\n if (current.dataset && current.dataset.noDnd) {\n return false;\n }\n current = current.parentElement;\n }\n\n return true;\n}\n"],"names":["MouseSensor","LibMouseSensor","activators","eventName","handler","nativeEvent","event","shouldHandleEvent","target","KeyboardSensor","LibKeyboardSensor","element","current","dataset","noDnd","parentElement"],"mappings":"yEAKM,MAAOA,UAAoBC,EAAAA,aACND,EAAAE,WAAa,CAChC,CACIC,UAAW,cACXC,QAAS,EAAGC,YAAaC,KACdC,EAAkBD,EAAME,UAMzC,MAAOC,UAAuBC,EAAAA,gBAWpC,SAASH,EAAkBI,GACvB,IAAIC,EAAUD,EACd,KAAOC,GAAS,CACZ,GAAIA,EAAQC,SAAWD,EAAQC,QAAQC,MACnC,OAAO,EAEXF,EAAUA,EAAQG,aACtB,CAEA,OAAO,CACX,CApB2BN,EAAAP,WAAa,CAChC,CACIC,UAAW,YACXC,QAAS,EAAGC,YAAaC,KACdC,EAAkBD,EAAME"}
@@ -1 +1 @@
1
- {"version":3,"file":"file-list.js","sources":["../../../../src/file-upload/file-list/file-list.tsx"],"sourcesContent":["import type { DragEndEvent, DragStartEvent } from \"@dnd-kit/core\";\nimport {\n DndContext,\n KeyboardSensor,\n TouchSensor,\n useSensor,\n useSensors,\n} from \"@dnd-kit/core\";\nimport {\n arrayMove,\n SortableContext,\n sortableKeyboardCoordinates,\n verticalListSortingStrategy,\n} from \"@dnd-kit/sortable\";\nimport clsx from \"clsx\";\nimport type React from \"react\";\nimport {\n forwardRef,\n useContext,\n useEffect,\n useImperativeHandle,\n useRef,\n useState,\n} from \"react\";\nimport { useResizeDetector } from \"react-resize-detector\";\n\nimport type { FormLabelProps } from \"../../form/form-label/types\";\nimport { VisuallyHidden } from \"../../shared/accessibility\";\nimport { FileUploadContext } from \"../context\";\nimport { MouseSensor } from \"../custom-sensors\";\nimport { FileItemEdit } from \"../file-item-edit\";\nimport { FileListItem } from \"../file-list-item\";\nimport { FileUploadHelper } from \"../helper\";\nimport type { FileItemProps } from \"../types\";\nimport * as styles from \"./file-list.styles\";\n\n// =============================================================================\n// INTERFACES\n// =============================================================================\ntype RenderMode = \"edit\" | \"display\" | \"error\";\n\ntype FileItemRenderModes = Record<string, RenderMode>;\ntype FileEditedDescriptions = Record<string, string>;\n\ntype RenderItem = FileItemProps | FileItemProps[];\n\ninterface Props {\n fileItems: FileItemProps[] | undefined;\n editableFileItems: boolean;\n fileDescriptionMaxLength?: number | undefined;\n descriptionRequired?: boolean | undefined;\n descriptionLabel?: FormLabelProps | undefined;\n sortable?: boolean | undefined;\n disabled?: boolean | undefined;\n readOnly?: boolean | undefined;\n onItemUpdate: (item: FileItemProps) => void;\n onItemDelete: (item: FileItemProps) => void;\n onSort?: ((reorderedFileItems: FileItemProps[]) => void) | undefined;\n}\n\ntype AnnouncementProgress = Record<\n string,\n {\n progress: number;\n timestamp: number;\n status: \"in-progress\" | \"complete\" | \"error\";\n }\n>;\n\nexport interface FileListRef {\n focus: () => void;\n}\n\n// =============================================================================\n// COMPONENT\n// =============================================================================\n\nfunction Component(\n {\n fileItems = [],\n editableFileItems,\n fileDescriptionMaxLength,\n descriptionRequired,\n descriptionLabel,\n sortable,\n disabled,\n readOnly,\n onItemUpdate,\n onItemDelete,\n onSort,\n }: Props,\n ref: React.Ref<FileListRef>\n) {\n // =========================================================================\n // CONST, STATE, REFS\n // =========================================================================\n const [renderModes, setRenderModes] = useState<FileItemRenderModes>({});\n const { setActiveId } = useContext(FileUploadContext);\n\n // Progress announcement state (for aria-live) - announces start and completion only\n const [progressAnnouncement, setProgressAnnouncement] = useState(\"\");\n const lastAnnouncedRef = useRef<AnnouncementProgress>({});\n\n useImperativeHandle(ref, () => ({\n focus: () => {\n wrapperRef.current?.focus();\n },\n }));\n const { width: wrapperWidth = 0, ref: wrapperRef } = useResizeDetector();\n\n // Keep track of edited description without re-rendering\n const descriptionsValueRef = useRef<FileEditedDescriptions>({});\n\n /**\n * As the default drag sensors interfere with click events\n * on the file items, we'll need to configure the sensor to\n * only activate the drag if the mouse moves a certain distance\n */\n const sensors = useSensors(\n useSensor(MouseSensor, {\n activationConstraint: {\n distance: 8, // mouse drag of 8px then activate the drag event\n },\n }),\n useSensor(TouchSensor, {\n activationConstraint: {\n delay: 150,\n tolerance: 5,\n },\n }),\n useSensor(KeyboardSensor, {\n coordinateGetter: sortableKeyboardCoordinates,\n })\n );\n\n // =========================================================================\n // REF METHODS\n // =========================================================================\n const removeDescription = (itemId: string) => {\n delete descriptionsValueRef.current[itemId];\n };\n\n const shallowCompareRenderModes = (\n prev: FileItemRenderModes,\n next: FileItemRenderModes\n ) => {\n const prevKeys = Object.keys(prev);\n const nextKeys = Object.keys(next);\n if (prevKeys.length !== nextKeys.length) {\n return false;\n }\n for (const k of nextKeys) {\n if (prev[k] !== next[k]) {\n return false;\n }\n }\n return true;\n };\n\n // =========================================================================\n // EFFECTS\n // =========================================================================\n useEffect(() => {\n const nextModes = getItemsRenderMode(fileItems);\n const prevModes = renderModes;\n // We perform shallowCompare to avoid infinite re-render loop\n if (shallowCompareRenderModes(prevModes, nextModes)) {\n return;\n }\n setRenderModes(nextModes);\n }, [fileItems, editableFileItems, readOnly]);\n\n // Progress announcements only at start and completion\n useEffect(() => {\n if (!fileItems || fileItems.length === 0) {\n setProgressAnnouncement(\"\");\n return;\n }\n const now = Date.now();\n const messages: string[] = [];\n\n for (const item of fileItems) {\n const fileStatus = lastAnnouncedRef.current[item.id];\n\n if (item.errorMessage) {\n if (fileStatus?.status !== \"error\") {\n messages.push(\n typeof item.errorMessage === \"string\"\n ? `Error uploading ${item.name}: ${item.errorMessage}`\n : `Error uploading ${item.name}`\n );\n lastAnnouncedRef.current[item.id] = {\n progress: item.progress ?? 1,\n timestamp: now,\n status: \"error\",\n };\n }\n continue;\n }\n\n if (item.progress === undefined) {\n continue;\n }\n\n if (item.progress >= 1) {\n if (fileStatus?.status !== \"complete\") {\n messages.push(`${item.name} upload is complete`);\n lastAnnouncedRef.current[item.id] = {\n progress: 1,\n timestamp: now,\n status: \"complete\",\n };\n }\n continue;\n }\n\n // In progress - only announce start, not progress updates\n if (typeof item.progress === \"number\" && item.progress < 1) {\n // Only announce when starting upload (no previous status or status was not in-progress)\n const shouldAnnounce =\n !fileStatus || fileStatus.status !== \"in-progress\";\n\n if (shouldAnnounce) {\n messages.push(`Starting upload of ${item.name}`);\n lastAnnouncedRef.current[item.id] = {\n progress: item.progress,\n timestamp: now,\n status: \"in-progress\",\n };\n }\n }\n }\n\n if (messages.length > 0) {\n // Update aria-live region once with aggregated message\n setProgressAnnouncement(messages.join(\", \"));\n }\n }, [fileItems]);\n\n // =========================================================================\n // EVENT HANDLERS\n // =========================================================================\n const handleSaveEdit = (item: FileItemProps) => (description: string) => {\n updateRenderModes(item.id, \"display\");\n removeDescription(item.id);\n\n const updatedItem = { ...item, description };\n onItemUpdate(updatedItem);\n };\n\n const handleBlurEdit = (item: FileItemProps) => (value: string) => {\n descriptionsValueRef.current[item.id] = value;\n };\n\n const handleCancel = (item: FileItemProps) => () => {\n if (!item.description || item.description.length === 0) {\n // New addition\n onItemDelete(item);\n } else {\n updateRenderModes(item.id, \"display\");\n }\n removeDescription(item.id);\n };\n\n const handleInitiateEdit = (item: FileItemProps) => () => {\n updateRenderModes(item.id, \"edit\");\n };\n\n const handleDelete = (item: FileItemProps) => () => {\n onItemDelete(item);\n if (wrapperRef.current) {\n wrapperRef.current.focus();\n }\n };\n\n const handleDragEnd = (event: DragEndEvent) => {\n if (onSort && fileItems) {\n const { active, over } = event;\n\n if (over && active.id !== over.id) {\n const oldIndex = fileItems.findIndex(\n (item) => item.id === active.id\n );\n const newIndex = fileItems.findIndex(\n (item) => item.id === over.id\n );\n\n const updatedFileItems = arrayMove(\n fileItems,\n oldIndex,\n newIndex\n );\n\n onSort(updatedFileItems);\n }\n }\n\n setActiveId(undefined);\n };\n\n const handleDragStart = (event: DragStartEvent) => {\n const { active } = event;\n setActiveId(active.id as string);\n };\n\n // =========================================================================\n // HELPER FUNCTIONS\n // =========================================================================\n const checkEditable = (item: FileItemProps) => {\n return (\n editableFileItems &&\n FileUploadHelper.isSupportedImageType(item.type)\n );\n };\n\n const shouldRenderEditMode = (item: FileItemProps) => {\n return (\n !item.errorMessage &&\n !readOnly &&\n !(typeof item.progress === \"number\" && item.progress < 1) &&\n checkEditable(item) &&\n !item.description\n );\n };\n\n const getItemsRenderMode = (\n fileItems: FileItemProps[] | undefined\n ): FileItemRenderModes => {\n if (!fileItems || fileItems.length === 0) return {};\n\n const newRenderModes: FileItemRenderModes = {};\n\n for (const item of fileItems) {\n if (item.errorMessage) {\n newRenderModes[item.id] = \"error\";\n } else if (!renderModes[item.id]) {\n newRenderModes[item.id] = shouldRenderEditMode(item)\n ? \"edit\"\n : \"display\";\n } else {\n newRenderModes[item.id] = renderModes[item.id];\n }\n }\n\n return newRenderModes;\n };\n\n const updateRenderModes = (itemId: string, mode: RenderMode) => {\n setRenderModes((prevRenderModes) => {\n return {\n ...prevRenderModes,\n [itemId]: mode,\n };\n });\n };\n\n /**\n * Due to a UI requirement, we will render the items\n * with edit modes as a group\n */\n const getArrangedItems = (\n fileItems: FileItemProps[] | undefined,\n renderModes: FileItemRenderModes\n ) => {\n if (!fileItems || fileItems.length === 0) return [];\n\n const arrangedItems: RenderItem[] = [];\n\n for (const fileItem of fileItems) {\n if (renderModes[fileItem.id] === \"edit\") {\n const previousElement = arrangedItems[arrangedItems.length - 1];\n if (Array.isArray(previousElement)) {\n previousElement.push(fileItem);\n } else {\n arrangedItems.push([fileItem]);\n }\n } else {\n arrangedItems.push(fileItem);\n }\n }\n\n return arrangedItems;\n };\n\n const areAllItemsInDisplayViews = () => {\n return Object.values(renderModes).every((mode) => mode === \"display\");\n };\n\n const shouldEnableSort = () => {\n return (\n fileItems &&\n fileItems.length > 1 &&\n sortable &&\n areAllItemsInDisplayViews()\n );\n };\n\n /**\n * If there are no files, return \"No files uploaded\".\n * If readOnly is true, return \"Read-only file list\".\n * If there are files, return a summary of the file statuses.\n * For example, \"File list. 2 completed files, 1 file in progress, 1 file with error\".\n *\n * @returns aria label\n */\n const getWrapperAriaLabel = () => {\n if (fileItems.length === 0) {\n return \"No files uploaded\";\n }\n const completedCount = fileItems.filter(\n (item) =>\n !item?.errorMessage &&\n (item.progress === 1 || item.progress === undefined)\n ).length;\n const inProgressCount = fileItems.filter(\n (item) => typeof item.progress === \"number\" && item.progress < 1\n ).length;\n const errorCount = fileItems.filter((item) => item.errorMessage).length;\n if (completedCount === 0 && inProgressCount === 0 && errorCount === 0) {\n return `File list`;\n }\n const completedText =\n completedCount > 0 ? `${completedCount} completed files` : \"\";\n const inProgressText =\n inProgressCount > 0 ? `${inProgressCount} file in progress` : \"\";\n const errorText =\n errorCount > 0\n ? `${errorCount} ${\n errorCount > 1 ? \"files\" : \"file\"\n } with error`\n : \"\";\n const parts = [completedText, inProgressText, errorText].filter(\n Boolean\n );\n const prefix = readOnly ? \"Read-only file list\" : \"File list\";\n return `${prefix}. ${parts.join(\", \")}`;\n };\n\n // =========================================================================\n // RENDER FUNCTIONS\n // =========================================================================\n const renderItemsInEditMode = (\n fileItems: FileItemProps[],\n keyToUse: number\n ) => {\n const itemsToRender = fileItems.map((item) => {\n const updatedFileItem = { ...item };\n if (descriptionsValueRef.current[item.id] !== undefined) {\n updatedFileItem.description =\n descriptionsValueRef.current[item.id];\n }\n\n return (\n <FileItemEdit\n key={item.id}\n fileItem={updatedFileItem}\n wrapperWidth={wrapperWidth}\n fileDescriptionMaxLength={fileDescriptionMaxLength}\n descriptionRequired={descriptionRequired}\n descriptionLabel={descriptionLabel}\n onSave={handleSaveEdit(item)}\n onCancel={handleCancel(item)}\n onBlur={handleBlurEdit(item)}\n />\n );\n });\n\n return (\n <li\n key={`editable-${keyToUse}`}\n className={styles.editableItemsContainer}\n >\n <ul>{itemsToRender}</ul>\n </li>\n );\n };\n\n const renderItems = () => {\n const arrangedItems = getArrangedItems(fileItems, renderModes);\n\n if (arrangedItems.length === 0) return null;\n\n return arrangedItems.map((item, index) => {\n if (Array.isArray(item)) {\n return renderItemsInEditMode(item, index);\n } else {\n return (\n <FileListItem\n key={item.id}\n fileItem={item}\n editable={checkEditable(item)}\n wrapperWidth={wrapperWidth}\n sortable={shouldEnableSort()}\n disabled={disabled}\n readOnly={readOnly}\n descriptionLabel={descriptionLabel}\n onDelete={handleDelete(item)}\n onEditClick={handleInitiateEdit(item)}\n />\n );\n }\n });\n };\n\n /**\n * Renders the progress status of each file upload.\n * In progress: 25% complete for uploading filename.pdf\n * Complete: filename.pdf upload is complete\n * Error: Error uploading filename.pdf: error message\n *\n * @returns A visually hidden element announcing the progress status.\n */\n const renderProgressStatus = () => (\n <VisuallyHidden aria-live=\"polite\" aria-atomic=\"true\">\n {progressAnnouncement}\n </VisuallyHidden>\n );\n\n const renderItemsWithWrapper = () => {\n return (\n <>\n {renderProgressStatus()}\n <ul\n tabIndex={-1}\n className={clsx(\n styles.listWrapper,\n readOnly && styles.listWrapperReadOnly\n )}\n ref={wrapperRef}\n aria-label={getWrapperAriaLabel()}\n >\n {renderItems()}\n </ul>\n </>\n );\n };\n\n if (disabled || readOnly || !shouldEnableSort()) {\n return renderItemsWithWrapper();\n } else {\n return (\n <DndContext\n sensors={sensors}\n onDragEnd={handleDragEnd}\n onDragStart={handleDragStart}\n >\n <SortableContext\n items={fileItems}\n strategy={verticalListSortingStrategy}\n >\n {renderItemsWithWrapper()}\n </SortableContext>\n </DndContext>\n );\n }\n}\n\nexport const FileList = forwardRef<FileListRef, Props>(Component);\n"],"names":["FileList","forwardRef","fileItems","editableFileItems","fileDescriptionMaxLength","descriptionRequired","descriptionLabel","sortable","disabled","readOnly","onItemUpdate","onItemDelete","onSort","ref","renderModes","setRenderModes","useState","setActiveId","useContext","FileUploadContext","progressAnnouncement","setProgressAnnouncement","lastAnnouncedRef","useRef","useImperativeHandle","focus","_a","wrapperRef","current","width","wrapperWidth","useResizeDetector","descriptionsValueRef","sensors","useSensors","useSensor","MouseSensor","activationConstraint","distance","TouchSensor","delay","tolerance","KeyboardSensor","coordinateGetter","sortableKeyboardCoordinates","removeDescription","itemId","useEffect","nextModes","getItemsRenderMode","prev","next","prevKeys","Object","keys","nextKeys","length","k","shallowCompareRenderModes","now","Date","messages","item","fileStatus","id","errorMessage","status","push","name","progress","timestamp","undefined","join","handleSaveEdit","description","updateRenderModes","updatedItem","assign","handleBlurEdit","value","handleCancel","handleInitiateEdit","handleDelete","handleDragEnd","event","active","over","oldIndex","findIndex","newIndex","updatedFileItems","arrayMove","handleDragStart","checkEditable","FileUploadHelper","isSupportedImageType","type","shouldRenderEditMode","newRenderModes","mode","prevRenderModes","shouldEnableSort","values","every","getWrapperAriaLabel","completedCount","filter","inProgressCount","errorCount","parts","Boolean","renderItems","arrangedItems","fileItem","previousElement","Array","isArray","getArrangedItems","map","index","keyToUse","itemsToRender","updatedFileItem","_jsx","FileItemEdit","onSave","onCancel","onBlur","className","styles.editableItemsContainer","children","renderItemsInEditMode","FileListItem","editable","onDelete","onEditClick","renderItemsWithWrapper","_jsxs","_Fragment","VisuallyHidden","tabIndex","clsx","styles.listWrapper","styles.listWrapperReadOnly","DndContext","onDragEnd","onDragStart","SortableContext","items","strategy","verticalListSortingStrategy"],"mappings":"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"}
1
+ {"version":3,"file":"file-list.js","sources":["../../../../src/file-upload/file-list/file-list.tsx"],"sourcesContent":["import type { DragEndEvent, DragStartEvent } from \"@dnd-kit/core\";\nimport {\n DndContext,\n KeyboardSensor,\n TouchSensor,\n useSensor,\n useSensors,\n} from \"@dnd-kit/core\";\nimport {\n arrayMove,\n SortableContext,\n sortableKeyboardCoordinates,\n verticalListSortingStrategy,\n} from \"@dnd-kit/sortable\";\nimport clsx from \"clsx\";\nimport type React from \"react\";\nimport {\n forwardRef,\n useContext,\n useEffect,\n useImperativeHandle,\n useRef,\n useState,\n} from \"react\";\nimport { useResizeDetector } from \"react-resize-detector\";\n\nimport type { FormLabelProps } from \"../../form/form-label/types\";\nimport { VisuallyHidden } from \"../../shared/accessibility\";\nimport { FileUploadContext } from \"../context\";\nimport { MouseSensor } from \"../custom-sensors\";\nimport { FileItemEdit } from \"../file-item-edit\";\nimport { FileListItem } from \"../file-list-item\";\nimport { FileUploadHelper } from \"../helper\";\nimport type { FileItemProps } from \"../types\";\nimport * as styles from \"./file-list.styles\";\n\n// =============================================================================\n// INTERFACES\n// =============================================================================\ntype RenderMode = \"edit\" | \"display\" | \"error\";\n\ntype FileItemRenderModes = Record<string, RenderMode>;\ntype FileEditedDescriptions = Record<string, string>;\n\ntype RenderItem = FileItemProps | FileItemProps[];\n\ninterface Props {\n fileItems: FileItemProps[] | undefined;\n editableFileItems: boolean;\n fileDescriptionMaxLength?: number | undefined;\n descriptionRequired?: boolean | undefined;\n descriptionLabel?: FormLabelProps | undefined;\n sortable?: boolean | undefined;\n disabled?: boolean | undefined;\n readOnly?: boolean | undefined;\n onItemUpdate: (item: FileItemProps) => void;\n onItemDelete: (item: FileItemProps) => void;\n onSort?: ((reorderedFileItems: FileItemProps[]) => void) | undefined;\n}\n\ntype AnnouncementProgress = Record<\n string,\n {\n progress: number;\n timestamp: number;\n status: \"in-progress\" | \"complete\" | \"error\";\n }\n>;\n\nexport interface FileListRef {\n focus: () => void;\n}\n\n// =============================================================================\n// COMPONENT\n// =============================================================================\n\nfunction Component(\n {\n fileItems = [],\n editableFileItems,\n fileDescriptionMaxLength,\n descriptionRequired,\n descriptionLabel,\n sortable,\n disabled,\n readOnly,\n onItemUpdate,\n onItemDelete,\n onSort,\n }: Props,\n ref: React.Ref<FileListRef>\n) {\n // =========================================================================\n // CONST, STATE, REFS\n // =========================================================================\n const [renderModes, setRenderModes] = useState<FileItemRenderModes>({});\n const { setActiveId } = useContext(FileUploadContext);\n\n // Progress announcement state (for aria-live) - announces start and completion only\n const [progressAnnouncement, setProgressAnnouncement] = useState(\"\");\n const lastAnnouncedRef = useRef<AnnouncementProgress>({});\n\n useImperativeHandle(ref, () => ({\n focus: () => {\n wrapperRef.current?.focus();\n },\n }));\n const { width: wrapperWidth = 0, ref: wrapperRef } = useResizeDetector();\n\n // Keep track of edited description without re-rendering\n const descriptionsValueRef = useRef<FileEditedDescriptions>({});\n\n /**\n * As the default drag sensors interfere with click events\n * on the file items, we'll need to configure the sensor to\n * only activate the drag if the mouse moves a certain distance\n */\n const sensors = useSensors(\n useSensor(MouseSensor, {\n activationConstraint: {\n distance: 8, // mouse drag of 8px then activate the drag event\n },\n }),\n useSensor(TouchSensor, {\n activationConstraint: {\n delay: 150,\n tolerance: 5,\n },\n }),\n useSensor(KeyboardSensor, {\n coordinateGetter: sortableKeyboardCoordinates,\n })\n );\n\n // =========================================================================\n // REF METHODS\n // =========================================================================\n const removeDescription = (itemId: string) => {\n delete descriptionsValueRef.current[itemId];\n };\n\n const shallowCompareRenderModes = (\n prev: FileItemRenderModes,\n next: FileItemRenderModes\n ) => {\n const prevKeys = Object.keys(prev);\n const nextKeys = Object.keys(next);\n if (prevKeys.length !== nextKeys.length) {\n return false;\n }\n for (const k of nextKeys) {\n if (prev[k] !== next[k]) {\n return false;\n }\n }\n return true;\n };\n\n // =========================================================================\n // EFFECTS\n // =========================================================================\n useEffect(() => {\n const nextModes = getItemsRenderMode(fileItems);\n const prevModes = renderModes;\n // We perform shallowCompare to avoid infinite re-render loop\n if (shallowCompareRenderModes(prevModes, nextModes)) {\n return;\n }\n setRenderModes(nextModes);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [fileItems, editableFileItems, readOnly]);\n\n // Progress announcements only at start and completion\n useEffect(() => {\n if (!fileItems || fileItems.length === 0) {\n setProgressAnnouncement(\"\");\n return;\n }\n const now = Date.now();\n const messages: string[] = [];\n\n for (const item of fileItems) {\n const fileStatus = lastAnnouncedRef.current[item.id];\n\n if (item.errorMessage) {\n if (fileStatus?.status !== \"error\") {\n messages.push(\n typeof item.errorMessage === \"string\"\n ? `Error uploading ${item.name}: ${item.errorMessage}`\n : `Error uploading ${item.name}`\n );\n lastAnnouncedRef.current[item.id] = {\n progress: item.progress ?? 1,\n timestamp: now,\n status: \"error\",\n };\n }\n continue;\n }\n\n if (item.progress === undefined) {\n continue;\n }\n\n if (item.progress >= 1) {\n if (fileStatus?.status !== \"complete\") {\n messages.push(`${item.name} upload is complete`);\n lastAnnouncedRef.current[item.id] = {\n progress: 1,\n timestamp: now,\n status: \"complete\",\n };\n }\n continue;\n }\n\n // In progress - only announce start, not progress updates\n if (typeof item.progress === \"number\" && item.progress < 1) {\n // Only announce when starting upload (no previous status or status was not in-progress)\n const shouldAnnounce =\n !fileStatus || fileStatus.status !== \"in-progress\";\n\n if (shouldAnnounce) {\n messages.push(`Starting upload of ${item.name}`);\n lastAnnouncedRef.current[item.id] = {\n progress: item.progress,\n timestamp: now,\n status: \"in-progress\",\n };\n }\n }\n }\n\n if (messages.length > 0) {\n // Update aria-live region once with aggregated message\n setProgressAnnouncement(messages.join(\", \"));\n }\n }, [fileItems]);\n\n // =========================================================================\n // EVENT HANDLERS\n // =========================================================================\n const handleSaveEdit = (item: FileItemProps) => (description: string) => {\n updateRenderModes(item.id, \"display\");\n removeDescription(item.id);\n\n const updatedItem = { ...item, description };\n onItemUpdate(updatedItem);\n };\n\n const handleBlurEdit = (item: FileItemProps) => (value: string) => {\n descriptionsValueRef.current[item.id] = value;\n };\n\n const handleCancel = (item: FileItemProps) => () => {\n if (!item.description || item.description.length === 0) {\n // New addition\n onItemDelete(item);\n } else {\n updateRenderModes(item.id, \"display\");\n }\n removeDescription(item.id);\n };\n\n const handleInitiateEdit = (item: FileItemProps) => () => {\n updateRenderModes(item.id, \"edit\");\n };\n\n const handleDelete = (item: FileItemProps) => () => {\n onItemDelete(item);\n if (wrapperRef.current) {\n wrapperRef.current.focus();\n }\n };\n\n const handleDragEnd = (event: DragEndEvent) => {\n if (onSort && fileItems) {\n const { active, over } = event;\n\n if (over && active.id !== over.id) {\n const oldIndex = fileItems.findIndex(\n (item) => item.id === active.id\n );\n const newIndex = fileItems.findIndex(\n (item) => item.id === over.id\n );\n\n const updatedFileItems = arrayMove(\n fileItems,\n oldIndex,\n newIndex\n );\n\n onSort(updatedFileItems);\n }\n }\n\n setActiveId(undefined);\n };\n\n const handleDragStart = (event: DragStartEvent) => {\n const { active } = event;\n setActiveId(active.id as string);\n };\n\n // =========================================================================\n // HELPER FUNCTIONS\n // =========================================================================\n const checkEditable = (item: FileItemProps) => {\n return (\n editableFileItems &&\n FileUploadHelper.isSupportedImageType(item.type)\n );\n };\n\n const shouldRenderEditMode = (item: FileItemProps) => {\n return (\n !item.errorMessage &&\n !readOnly &&\n !(typeof item.progress === \"number\" && item.progress < 1) &&\n checkEditable(item) &&\n !item.description\n );\n };\n\n const getItemsRenderMode = (\n fileItems: FileItemProps[] | undefined\n ): FileItemRenderModes => {\n if (!fileItems || fileItems.length === 0) return {};\n\n const newRenderModes: FileItemRenderModes = {};\n\n for (const item of fileItems) {\n if (item.errorMessage) {\n newRenderModes[item.id] = \"error\";\n } else if (!renderModes[item.id]) {\n newRenderModes[item.id] = shouldRenderEditMode(item)\n ? \"edit\"\n : \"display\";\n } else {\n newRenderModes[item.id] = renderModes[item.id];\n }\n }\n\n return newRenderModes;\n };\n\n const updateRenderModes = (itemId: string, mode: RenderMode) => {\n setRenderModes((prevRenderModes) => {\n return {\n ...prevRenderModes,\n [itemId]: mode,\n };\n });\n };\n\n /**\n * Due to a UI requirement, we will render the items\n * with edit modes as a group\n */\n const getArrangedItems = (\n fileItems: FileItemProps[] | undefined,\n renderModes: FileItemRenderModes\n ) => {\n if (!fileItems || fileItems.length === 0) return [];\n\n const arrangedItems: RenderItem[] = [];\n\n for (const fileItem of fileItems) {\n if (renderModes[fileItem.id] === \"edit\") {\n const previousElement = arrangedItems[arrangedItems.length - 1];\n if (Array.isArray(previousElement)) {\n previousElement.push(fileItem);\n } else {\n arrangedItems.push([fileItem]);\n }\n } else {\n arrangedItems.push(fileItem);\n }\n }\n\n return arrangedItems;\n };\n\n const areAllItemsInDisplayViews = () => {\n return Object.values(renderModes).every((mode) => mode === \"display\");\n };\n\n const shouldEnableSort = () => {\n return (\n fileItems &&\n fileItems.length > 1 &&\n sortable &&\n areAllItemsInDisplayViews()\n );\n };\n\n /**\n * If there are no files, return \"No files uploaded\".\n * If readOnly is true, return \"Read-only file list\".\n * If there are files, return a summary of the file statuses.\n * For example, \"File list. 2 completed files, 1 file in progress, 1 file with error\".\n *\n * @returns aria label\n */\n const getWrapperAriaLabel = () => {\n if (fileItems.length === 0) {\n return \"No files uploaded\";\n }\n const completedCount = fileItems.filter(\n (item) =>\n !item?.errorMessage &&\n (item.progress === 1 || item.progress === undefined)\n ).length;\n const inProgressCount = fileItems.filter(\n (item) => typeof item.progress === \"number\" && item.progress < 1\n ).length;\n const errorCount = fileItems.filter((item) => item.errorMessage).length;\n if (completedCount === 0 && inProgressCount === 0 && errorCount === 0) {\n return `File list`;\n }\n const completedText =\n completedCount > 0 ? `${completedCount} completed files` : \"\";\n const inProgressText =\n inProgressCount > 0 ? `${inProgressCount} file in progress` : \"\";\n const errorText =\n errorCount > 0\n ? `${errorCount} ${\n errorCount > 1 ? \"files\" : \"file\"\n } with error`\n : \"\";\n const parts = [completedText, inProgressText, errorText].filter(\n Boolean\n );\n const prefix = readOnly ? \"Read-only file list\" : \"File list\";\n return `${prefix}. ${parts.join(\", \")}`;\n };\n\n // =========================================================================\n // RENDER FUNCTIONS\n // =========================================================================\n const renderItemsInEditMode = (\n fileItems: FileItemProps[],\n keyToUse: number\n ) => {\n const itemsToRender = fileItems.map((item) => {\n const updatedFileItem = { ...item };\n if (descriptionsValueRef.current[item.id] !== undefined) {\n updatedFileItem.description =\n descriptionsValueRef.current[item.id];\n }\n\n return (\n <FileItemEdit\n key={item.id}\n fileItem={updatedFileItem}\n wrapperWidth={wrapperWidth}\n fileDescriptionMaxLength={fileDescriptionMaxLength}\n descriptionRequired={descriptionRequired}\n descriptionLabel={descriptionLabel}\n onSave={handleSaveEdit(item)}\n onCancel={handleCancel(item)}\n onBlur={handleBlurEdit(item)}\n />\n );\n });\n\n return (\n <li\n key={`editable-${keyToUse}`}\n className={styles.editableItemsContainer}\n >\n <ul>{itemsToRender}</ul>\n </li>\n );\n };\n\n const renderItems = () => {\n const arrangedItems = getArrangedItems(fileItems, renderModes);\n\n if (arrangedItems.length === 0) return null;\n\n return arrangedItems.map((item, index) => {\n if (Array.isArray(item)) {\n return renderItemsInEditMode(item, index);\n } else {\n return (\n <FileListItem\n key={item.id}\n fileItem={item}\n editable={checkEditable(item)}\n wrapperWidth={wrapperWidth}\n sortable={shouldEnableSort()}\n disabled={disabled}\n readOnly={readOnly}\n descriptionLabel={descriptionLabel}\n onDelete={handleDelete(item)}\n onEditClick={handleInitiateEdit(item)}\n />\n );\n }\n });\n };\n\n /**\n * Renders the progress status of each file upload.\n * In progress: 25% complete for uploading filename.pdf\n * Complete: filename.pdf upload is complete\n * Error: Error uploading filename.pdf: error message\n *\n * @returns A visually hidden element announcing the progress status.\n */\n const renderProgressStatus = () => (\n <VisuallyHidden aria-live=\"polite\" aria-atomic=\"true\">\n {progressAnnouncement}\n </VisuallyHidden>\n );\n\n const renderItemsWithWrapper = () => {\n return (\n <>\n {renderProgressStatus()}\n <ul\n tabIndex={-1}\n className={clsx(\n styles.listWrapper,\n readOnly && styles.listWrapperReadOnly\n )}\n ref={wrapperRef}\n aria-label={getWrapperAriaLabel()}\n >\n {renderItems()}\n </ul>\n </>\n );\n };\n\n if (disabled || readOnly || !shouldEnableSort()) {\n return renderItemsWithWrapper();\n } else {\n return (\n <DndContext\n sensors={sensors}\n onDragEnd={handleDragEnd}\n onDragStart={handleDragStart}\n >\n <SortableContext\n items={fileItems}\n strategy={verticalListSortingStrategy}\n >\n {renderItemsWithWrapper()}\n </SortableContext>\n </DndContext>\n );\n }\n}\n\nexport const FileList = forwardRef<FileListRef, Props>(Component);\n"],"names":["FileList","forwardRef","fileItems","editableFileItems","fileDescriptionMaxLength","descriptionRequired","descriptionLabel","sortable","disabled","readOnly","onItemUpdate","onItemDelete","onSort","ref","renderModes","setRenderModes","useState","setActiveId","useContext","FileUploadContext","progressAnnouncement","setProgressAnnouncement","lastAnnouncedRef","useRef","useImperativeHandle","focus","_a","wrapperRef","current","width","wrapperWidth","useResizeDetector","descriptionsValueRef","sensors","useSensors","useSensor","MouseSensor","activationConstraint","distance","TouchSensor","delay","tolerance","KeyboardSensor","coordinateGetter","sortableKeyboardCoordinates","removeDescription","itemId","useEffect","nextModes","getItemsRenderMode","prev","next","prevKeys","Object","keys","nextKeys","length","k","shallowCompareRenderModes","now","Date","messages","item","fileStatus","id","errorMessage","status","push","name","progress","timestamp","undefined","join","handleSaveEdit","description","updateRenderModes","updatedItem","assign","handleBlurEdit","value","handleCancel","handleInitiateEdit","handleDelete","handleDragEnd","event","active","over","oldIndex","findIndex","newIndex","updatedFileItems","arrayMove","handleDragStart","checkEditable","FileUploadHelper","isSupportedImageType","type","shouldRenderEditMode","newRenderModes","mode","prevRenderModes","shouldEnableSort","values","every","getWrapperAriaLabel","completedCount","filter","inProgressCount","errorCount","parts","Boolean","renderItems","arrangedItems","fileItem","previousElement","Array","isArray","getArrangedItems","map","index","keyToUse","itemsToRender","updatedFileItem","_jsx","FileItemEdit","onSave","onCancel","onBlur","className","styles.editableItemsContainer","children","renderItemsInEditMode","FileListItem","editable","onDelete","onEditClick","renderItemsWithWrapper","_jsxs","_Fragment","VisuallyHidden","tabIndex","clsx","styles.listWrapper","styles.listWrapperReadOnly","DndContext","onDragEnd","onDragStart","SortableContext","items","strategy","verticalListSortingStrategy"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"filter-item-checkbox-helpers.js","sources":["../../../../src/filter/addons/filter-item-checkbox-helpers.ts"],"sourcesContent":["import type { FlattenedFilterOption } from \"./internal-types\";\nimport type { FilterItemCheckboxOptionProps } from \"./types\";\n\n// =============================================================================\n// HELPER FUNCTIONS FOR NESTED OPTIONS\n// =============================================================================\n\n/**\n * Builds a key path string from an array of keys\n */\nexport const buildKeyPath = (keyPath: string[]): string => {\n return keyPath.join(\".\");\n};\n\n/**\n * Flattens nested options into a flat array for rendering\n */\nexport const flattenNestedOptions = <T = FilterItemCheckboxOptionProps>(\n nestedOptions: T[],\n parentKeyPath: string[] = [],\n valueExtractor?: (item: T) => string,\n labelExtractor?: (item: T) => string\n): FlattenedFilterOption<T>[] => {\n const flattened: FlattenedFilterOption<T>[] = [];\n\n nestedOptions.forEach((option, index) => {\n const value: string = valueExtractor\n ? valueExtractor(option)\n : (option as any).value;\n const label: string = labelExtractor\n ? labelExtractor(option)\n : (option as any).label;\n const options: any[] = (option as any).options;\n const keyPath = [...parentKeyPath, value];\n const hasChildren = !!(options && options.length > 0);\n\n flattened.push({\n originalItem: option,\n value,\n label,\n keyPath,\n level: parentKeyPath.length,\n hasChildren,\n parentKeyPath: parentKeyPath.length > 0 ? parentKeyPath : undefined,\n indexInParent: index,\n parentSetSize: nestedOptions.length,\n });\n\n // Recursively flatten children\n if (hasChildren) {\n flattened.push(\n ...flattenNestedOptions(\n options,\n keyPath,\n valueExtractor,\n labelExtractor\n )\n );\n }\n });\n\n return flattened;\n};\n\n/**\n * Checks if a child key path is a descendant of a parent key path\n */\nconst isChild = (parentKeyPath: string[], childKeyPath: string[]): boolean => {\n if (childKeyPath.length <= parentKeyPath.length) return false;\n\n const parentKeyPathString = buildKeyPath(parentKeyPath);\n const childKeyPathString = buildKeyPath(childKeyPath);\n\n return childKeyPathString.startsWith(parentKeyPathString + \".\");\n};\n\n/**\n * Gets all descendant key paths (children, grandchildren, etc.) for a given parent\n */\nexport const getAllDescendantKeyPaths = <T = FilterItemCheckboxOptionProps>(\n flattenedOptions: FlattenedFilterOption<T>[],\n parentKeyPath: string[]\n): string[][] => {\n return flattenedOptions\n .filter((option) => isChild(parentKeyPath, option.keyPath))\n .map((option) => option.keyPath);\n};\n\n/**\n * Gets all descendant leaf children (non-parent items)\n */\nexport const getAllDescendantChildren = <T = FilterItemCheckboxOptionProps>(\n flattenedOptions: FlattenedFilterOption<T>[],\n parentKeyPath: string[]\n): T[] => {\n const parentKeyPathString = buildKeyPath(parentKeyPath);\n const children: T[] = [];\n\n const parentIndex = flattenedOptions.findIndex(\n (option) => buildKeyPath(option.keyPath) === parentKeyPathString\n );\n\n if (parentIndex === -1) return children;\n\n // Single pass: iterate from parent+1 until we find an item that's not a descendant\n for (let i = parentIndex + 1; i < flattenedOptions.length; i++) {\n const option = flattenedOptions[i];\n\n // Check if this item is a descendant\n if (isChild(parentKeyPath, option.keyPath)) {\n // Only include leaf nodes (non-parent items)\n if (!option.hasChildren) {\n children.push(option.originalItem as T);\n }\n } else {\n // No more descendants - we can break early\n break;\n }\n }\n\n return children;\n};\n\n/**\n * Checks if an option has nested options\n */\nexport const hasNestedOptions = <T = FilterItemCheckboxOptionProps>(\n options: T[],\n optionsExtractor?: (item: T) => T[]\n): boolean => {\n return options.some((option: T) => {\n const nestedOptions: any[] = optionsExtractor\n ? optionsExtractor(option)\n : (option as any).options;\n return nestedOptions && nestedOptions.length > 0;\n });\n};\n"],"names":["buildKeyPath","keyPath","join","flattenNestedOptions","nestedOptions","parentKeyPath","valueExtractor","labelExtractor","flattened","forEach","option","index","value","label","options","hasChildren","length","push","originalItem","level","undefined","indexInParent","parentSetSize","isChild","childKeyPath","parentKeyPathString","startsWith","flattenedOptions","children","parentIndex","findIndex","i","filter","map","optionsExtractor","some"],"mappings":"aAUO,MAAMA,EAAgBC,GAClBA,EAAQC,KAAK,KAMXC,EAAuB,CAChCC,EACAC,EAA0B,GAC1BC,EACAC,KAEA,MAAMC,EAAwC,GAsC9C,OApCAJ,EAAcK,SAAQ,CAACC,EAAQC,KAC3B,MAAMC,EAAgBN,EAChBA,EAAeI,GACdA,EAAeE,MAChBC,EAAgBN,EAChBA,EAAeG,GACdA,EAAeG,MAChBC,EAAkBJ,EAAeI,QACjCb,EAAU,IAAII,EAAeO,GAC7BG,KAAiBD,GAAWA,EAAQE,OAAS,GAEnDR,EAAUS,KAAK,CACXC,aAAcR,EACdE,QACAC,QACAZ,UACAkB,MAAOd,EAAcW,OACrBD,cACAV,cAAeA,EAAcW,OAAS,EAAIX,OAAgBe,EAC1DC,cAAeV,EACfW,cAAelB,EAAcY,SAI7BD,GACAP,EAAUS,QACHd,EACCW,EACAb,EACAK,EACAC,GAGZ,IAGGC,CAAS,EAMde,EAAU,CAAClB,EAAyBmB,KACtC,GAAIA,EAAaR,QAAUX,EAAcW,OAAQ,OAAO,EAExD,MAAMS,EAAsBzB,EAAaK,GAGzC,OAF2BL,EAAawB,GAEdE,WAAWD,EAAsB,IAAI,yFAkB3B,CACpCE,EACAtB,KAEA,MAAMoB,EAAsBzB,EAAaK,GACnCuB,EAAgB,GAEhBC,EAAcF,EAAiBG,WAChCpB,GAAWV,EAAaU,EAAOT,WAAawB,IAGjD,IAAoB,IAAhBI,EAAoB,OAAOD,EAG/B,IAAK,IAAIG,EAAIF,EAAc,EAAGE,EAAIJ,EAAiBX,OAAQe,IAAK,CAC5D,MAAMrB,EAASiB,EAAiBI,GAGhC,IAAIR,EAAQlB,EAAeK,EAAOT,SAO9B,MALKS,EAAOK,aACRa,EAASX,KAAKP,EAAOQ,aAMjC,CAEA,OAAOU,CAAQ,mCAzCqB,CACpCD,EACAtB,IAEOsB,EACFK,QAAQtB,GAAWa,EAAQlB,EAAeK,EAAOT,WACjDgC,KAAKvB,GAAWA,EAAOT,mCAyCA,CAC5Ba,EACAoB,IAEOpB,EAAQqB,MAAMzB,IACjB,MAAMN,EAAuB8B,EACvBA,EAAiBxB,GAChBA,EAAeI,QACtB,OAAOV,GAAiBA,EAAcY,OAAS,CAAC"}
1
+ {"version":3,"file":"filter-item-checkbox-helpers.js","sources":["../../../../src/filter/addons/filter-item-checkbox-helpers.ts"],"sourcesContent":["import type { FlattenedFilterOption } from \"./internal-types\";\nimport type { FilterItemCheckboxOptionProps } from \"./types\";\n\n// =============================================================================\n// HELPER FUNCTIONS FOR NESTED OPTIONS\n// =============================================================================\n\n/**\n * Builds a key path string from an array of keys\n */\nexport const buildKeyPath = (keyPath: string[]): string => {\n return keyPath.join(\".\");\n};\n\n/**\n * Flattens nested options into a flat array for rendering\n */\nexport const flattenNestedOptions = <T = FilterItemCheckboxOptionProps>(\n nestedOptions: T[],\n parentKeyPath: string[] = [],\n valueExtractor?: (item: T) => string,\n labelExtractor?: (item: T) => string\n): FlattenedFilterOption<T>[] => {\n const flattened: FlattenedFilterOption<T>[] = [];\n\n nestedOptions.forEach((option, index) => {\n const value: string = valueExtractor\n ? valueExtractor(option)\n : // eslint-disable-next-line @typescript-eslint/no-explicit-any\n (option as any).value;\n const label: string = labelExtractor\n ? labelExtractor(option)\n : // eslint-disable-next-line @typescript-eslint/no-explicit-any\n (option as any).label;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const options: any[] = (option as any).options;\n const keyPath = [...parentKeyPath, value];\n const hasChildren = !!(options && options.length > 0);\n\n flattened.push({\n originalItem: option,\n value,\n label,\n keyPath,\n level: parentKeyPath.length,\n hasChildren,\n parentKeyPath: parentKeyPath.length > 0 ? parentKeyPath : undefined,\n indexInParent: index,\n parentSetSize: nestedOptions.length,\n });\n\n // Recursively flatten children\n if (hasChildren) {\n flattened.push(\n ...flattenNestedOptions(\n options,\n keyPath,\n valueExtractor,\n labelExtractor\n )\n );\n }\n });\n\n return flattened;\n};\n\n/**\n * Checks if a child key path is a descendant of a parent key path\n */\nconst isChild = (parentKeyPath: string[], childKeyPath: string[]): boolean => {\n if (childKeyPath.length <= parentKeyPath.length) return false;\n\n const parentKeyPathString = buildKeyPath(parentKeyPath);\n const childKeyPathString = buildKeyPath(childKeyPath);\n\n return childKeyPathString.startsWith(parentKeyPathString + \".\");\n};\n\n/**\n * Gets all descendant key paths (children, grandchildren, etc.) for a given parent\n */\nexport const getAllDescendantKeyPaths = <T = FilterItemCheckboxOptionProps>(\n flattenedOptions: FlattenedFilterOption<T>[],\n parentKeyPath: string[]\n): string[][] => {\n return flattenedOptions\n .filter((option) => isChild(parentKeyPath, option.keyPath))\n .map((option) => option.keyPath);\n};\n\n/**\n * Gets all descendant leaf children (non-parent items)\n */\nexport const getAllDescendantChildren = <T = FilterItemCheckboxOptionProps>(\n flattenedOptions: FlattenedFilterOption<T>[],\n parentKeyPath: string[]\n): T[] => {\n const parentKeyPathString = buildKeyPath(parentKeyPath);\n const children: T[] = [];\n\n const parentIndex = flattenedOptions.findIndex(\n (option) => buildKeyPath(option.keyPath) === parentKeyPathString\n );\n\n if (parentIndex === -1) return children;\n\n // Single pass: iterate from parent+1 until we find an item that's not a descendant\n for (let i = parentIndex + 1; i < flattenedOptions.length; i++) {\n const option = flattenedOptions[i];\n\n // Check if this item is a descendant\n if (isChild(parentKeyPath, option.keyPath)) {\n // Only include leaf nodes (non-parent items)\n if (!option.hasChildren) {\n children.push(option.originalItem as T);\n }\n } else {\n // No more descendants - we can break early\n break;\n }\n }\n\n return children;\n};\n\n/**\n * Checks if an option has nested options\n */\nexport const hasNestedOptions = <T = FilterItemCheckboxOptionProps>(\n options: T[],\n optionsExtractor?: (item: T) => T[]\n): boolean => {\n return options.some((option: T) => {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const nestedOptions: any[] = optionsExtractor\n ? optionsExtractor(option)\n : // eslint-disable-next-line @typescript-eslint/no-explicit-any\n (option as any).options;\n return nestedOptions && nestedOptions.length > 0;\n });\n};\n"],"names":["buildKeyPath","keyPath","join","flattenNestedOptions","nestedOptions","parentKeyPath","valueExtractor","labelExtractor","flattened","forEach","option","index","value","label","options","hasChildren","length","push","originalItem","level","undefined","indexInParent","parentSetSize","isChild","childKeyPath","parentKeyPathString","startsWith","flattenedOptions","children","parentIndex","findIndex","i","filter","map","optionsExtractor","some"],"mappings":"aAUO,MAAMA,EAAgBC,GAClBA,EAAQC,KAAK,KAMXC,EAAuB,CAChCC,EACAC,EAA0B,GAC1BC,EACAC,KAEA,MAAMC,EAAwC,GAyC9C,OAvCAJ,EAAcK,SAAQ,CAACC,EAAQC,KAC3B,MAAMC,EAAgBN,EAChBA,EAAeI,GAEdA,EAAeE,MAChBC,EAAgBN,EAChBA,EAAeG,GAEdA,EAAeG,MAEhBC,EAAkBJ,EAAeI,QACjCb,EAAU,IAAII,EAAeO,GAC7BG,KAAiBD,GAAWA,EAAQE,OAAS,GAEnDR,EAAUS,KAAK,CACXC,aAAcR,EACdE,QACAC,QACAZ,UACAkB,MAAOd,EAAcW,OACrBD,cACAV,cAAeA,EAAcW,OAAS,EAAIX,OAAgBe,EAC1DC,cAAeV,EACfW,cAAelB,EAAcY,SAI7BD,GACAP,EAAUS,QACHd,EACCW,EACAb,EACAK,EACAC,GAGZ,IAGGC,CAAS,EAMde,EAAU,CAAClB,EAAyBmB,KACtC,GAAIA,EAAaR,QAAUX,EAAcW,OAAQ,OAAO,EAExD,MAAMS,EAAsBzB,EAAaK,GAGzC,OAF2BL,EAAawB,GAEdE,WAAWD,EAAsB,IAAI,yFAkB3B,CACpCE,EACAtB,KAEA,MAAMoB,EAAsBzB,EAAaK,GACnCuB,EAAgB,GAEhBC,EAAcF,EAAiBG,WAChCpB,GAAWV,EAAaU,EAAOT,WAAawB,IAGjD,IAAoB,IAAhBI,EAAoB,OAAOD,EAG/B,IAAK,IAAIG,EAAIF,EAAc,EAAGE,EAAIJ,EAAiBX,OAAQe,IAAK,CAC5D,MAAMrB,EAASiB,EAAiBI,GAGhC,IAAIR,EAAQlB,EAAeK,EAAOT,SAO9B,MALKS,EAAOK,aACRa,EAASX,KAAKP,EAAOQ,aAMjC,CAEA,OAAOU,CAAQ,mCAzCqB,CACpCD,EACAtB,IAEOsB,EACFK,QAAQtB,GAAWa,EAAQlB,EAAeK,EAAOT,WACjDgC,KAAKvB,GAAWA,EAAOT,mCAyCA,CAC5Ba,EACAoB,IAEOpB,EAAQqB,MAAMzB,IAEjB,MAAMN,EAAuB8B,EACvBA,EAAiBxB,GAEhBA,EAAeI,QACtB,OAAOV,GAAiBA,EAAcY,OAAS,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"filter-item-checkbox.js","sources":["../../../../src/filter/addons/filter-item-checkbox.tsx"],"sourcesContent":["import clsx from \"clsx\";\nimport type { AriaAttributes } from \"react\";\nimport {\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from \"react\";\nimport { useResizeDetector } from \"react-resize-detector\";\n\nimport { Button } from \"../../button\";\nimport { Checkbox } from \"../../checkbox\";\nimport { Toggle } from \"../../toggle\";\nimport { FilterContext } from \"../filter-context\";\nimport { FilterItem } from \"../filter-item\";\nimport * as styles from \"./filter-item-checkbox.styles\";\nimport {\n buildKeyPath,\n flattenNestedOptions,\n getAllDescendantChildren,\n getAllDescendantKeyPaths,\n hasNestedOptions,\n} from \"./filter-item-checkbox-helpers\";\nimport type { FlattenedFilterOption } from \"./internal-types\";\nimport type {\n FilterItemCheckboxOptionProps,\n FilterItemCheckboxProps,\n} from \"./types\";\n\nexport const FilterItemCheckbox = <T = FilterItemCheckboxOptionProps,>({\n selectedOptions,\n options,\n showAsCheckboxInMobile = false,\n minimisableOptions = true,\n onSelect,\n labelExtractor,\n valueExtractor,\n useToggleContentWidth,\n ...filterItemProps\n}: FilterItemCheckboxProps<T>) => {\n // =============================================================================\n // CONST, STATE, REF\n // =============================================================================\n const { mode } = useContext(FilterContext);\n const [selected, setSelected] = useState<T[]>(selectedOptions || []);\n const [minimisedHeight, setMinimisedHeight] = useState<number>();\n const [lastVisibleElementIndex, setLastVisibleElementIndex] =\n useState<number>(options.length);\n const parentRef = useRef<HTMLDivElement>(null);\n const lastVisibleElement = useRef<HTMLElement | null>(null);\n\n // Check if options have nested structure\n const isNested = useMemo(\n () => hasNestedOptions(options, (item) => (item as any).options),\n [options]\n );\n\n const isMobileToggleMode =\n mode === \"mobile\" && !showAsCheckboxInMobile && !isNested;\n\n // Flatten nested options\n const flattenedOptions = useMemo(\n () =>\n flattenNestedOptions(\n options,\n [],\n valueExtractor || ((item) => (item as any).value),\n labelExtractor || ((item) => (item as any).label)\n ),\n [options, valueExtractor, labelExtractor]\n );\n\n const optionCount = flattenedOptions.length;\n\n // =============================================================================\n // EVENT HANDLERS\n // =============================================================================\n const handleItemClick = (item: T) => () => {\n // Find the flattened option\n const flatOption = flattenedOptions.find(\n (opt) => opt.originalItem === item\n );\n if (!flatOption) return;\n\n if (flatOption.hasChildren) {\n // Handle parent click - select/deselect all children\n const allChildren = getAllDescendantChildren<T>(\n flattenedOptions,\n flatOption.keyPath\n );\n\n const currentlySelectedChildren = allChildren.filter((child) =>\n selected.some((s) => getValue(s) === getValue(child))\n );\n\n let newSelection = [...selected];\n\n if (currentlySelectedChildren.length === allChildren.length) {\n // All children selected, deselect all\n newSelection = newSelection.filter(\n (s) =>\n !allChildren.some(\n (child) => getValue(child) === getValue(s)\n )\n );\n } else {\n // Some or no children selected, select all\n allChildren.forEach((child) => {\n if (\n !newSelection.some(\n (s) => getValue(s) === getValue(child)\n )\n ) {\n newSelection.push(child);\n }\n });\n }\n\n setSelected(newSelection);\n onSelect?.(newSelection);\n } else {\n // Handle leaf item click - toggle selection\n const newSelection = [...selected];\n const selectedIndex = selected.findIndex(\n (s) => getValue(s) === getValue(item)\n );\n\n if (selectedIndex >= 0) {\n newSelection.splice(selectedIndex, 1);\n } else {\n newSelection.push(item);\n }\n setSelected(newSelection);\n onSelect?.(newSelection);\n }\n };\n\n const handleSelectClearAll = () => {\n if (isNested) {\n if (selected.length > 0) {\n // Clear all\n setSelected([]);\n onSelect?.([]);\n } else {\n // Select all leaf nodes\n const leafOptions = flattenedOptions.filter(\n (option) => !option.hasChildren\n );\n const allValues = leafOptions.map(\n (option) => option.originalItem\n ) as T[];\n setSelected(allValues);\n onSelect?.(allValues);\n }\n } else {\n const newSelection = selected.length ? [] : options;\n setSelected(newSelection);\n onSelect?.(newSelection);\n }\n };\n\n const handleListItemKeyDown =\n (originalItem: T) => (event: React.KeyboardEvent) => {\n if (isNested && (event.key === \" \" || event.key === \"Enter\")) {\n event.preventDefault();\n handleItemClick(originalItem)();\n }\n };\n\n const handleCheckboxChange = (originalItem: T) => () => {\n if (!isNested) {\n handleItemClick(originalItem)();\n }\n };\n\n // =============================================================================\n // HELPER FUNCTIONS\n // =============================================================================\n const getCheckboxState = (flatOption: (typeof flattenedOptions)[0]) => {\n if (!flatOption.hasChildren) {\n // Leaf item - simple check\n return {\n checked: selected.some(\n (s) =>\n getValue(s) === getValue(flatOption.originalItem as T)\n ),\n indeterminate: false,\n };\n }\n\n // Parent item - check children states (following IndeterminateState pattern)\n const allChildren = getAllDescendantKeyPaths(\n flattenedOptions,\n flatOption.keyPath\n )\n .map((keyPath: string[]) =>\n flattenedOptions.find(\n (opt) => buildKeyPath(opt.keyPath) === buildKeyPath(keyPath)\n )\n )\n .filter((opt) => opt && !opt.hasChildren)\n .map((opt) => opt!.originalItem as T);\n\n const selectedChildren = allChildren.filter((child) =>\n selected.some((s) => getValue(s) === getValue(child))\n );\n\n return {\n checked:\n selectedChildren.length === allChildren.length &&\n allChildren.length > 0,\n indeterminate:\n selectedChildren.length > 0 &&\n selectedChildren.length < allChildren.length,\n };\n };\n\n const getLabel = (item: T): React.ReactNode => {\n return labelExtractor\n ? labelExtractor(item)\n : (item as any).label ?? item?.toString();\n };\n\n const getValue = (item: T): string => {\n return valueExtractor\n ? valueExtractor(item)\n : (item as any).value ?? item?.toString();\n };\n\n const setVisibleItemsWhenMinimised = () => {\n const elementBottom = lastVisibleElement.current\n ? lastVisibleElement.current.offsetTop +\n lastVisibleElement.current.clientHeight\n : undefined;\n setMinimisedHeight(elementBottom);\n };\n\n const setVisibleMobileItemsWhenMinimised = useCallback(() => {\n if (!parentRef.current) {\n setMinimisedHeight(undefined);\n return;\n }\n\n const children = Array.from(parentRef.current.children);\n\n let lastElementInRow = 0;\n let rowCount = 0;\n let rowTop = -1;\n\n for (let i = 0; i < children.length; i++) {\n const childTop = (children[i] as HTMLDivElement).offsetTop;\n if (childTop > rowTop) {\n rowCount++;\n rowTop = childTop;\n // show only the first 2 rows\n if (rowCount > 2) {\n break;\n }\n }\n lastElementInRow = i;\n }\n\n setLastVisibleElementIndex(lastElementInRow);\n\n if (rowCount > 2) {\n setMinimisedHeight(rowTop - 8); // gap from next row\n } else {\n setMinimisedHeight(undefined);\n }\n }, []);\n\n // =============================================================================\n // EFFECTS\n // =============================================================================\n useEffect(() => {\n if (selectedOptions !== selected) {\n setSelected(selectedOptions || []);\n }\n }, [selectedOptions]);\n\n useEffect(() => {\n if (isMobileToggleMode) {\n setVisibleMobileItemsWhenMinimised();\n } else {\n setVisibleItemsWhenMinimised();\n }\n }, [options]);\n\n useResizeDetector({\n handleWidth: true,\n handleHeight: false,\n skipOnMount: true,\n refreshMode: \"throttle\",\n targetRef: parentRef,\n onResize: isMobileToggleMode\n ? setVisibleMobileItemsWhenMinimised\n : setVisibleItemsWhenMinimised,\n });\n\n // =============================================================================\n // RENDER FUNCTIONS\n // =============================================================================\n const renderCheckboxIcon = (\n originalItem: T,\n flatOption: FlattenedFilterOption<T>\n ) => {\n const { checked, indeterminate } = getCheckboxState(flatOption);\n\n return (\n <Checkbox\n className={styles.checkbox}\n displaySize=\"small\"\n checked={checked}\n indeterminate={indeterminate}\n onChange={handleCheckboxChange(originalItem)}\n tabIndex={isNested ? -1 : undefined}\n aria-hidden={isNested ? \"true\" : undefined}\n />\n );\n };\n\n const renderCheckbox = (\n option: FlattenedFilterOption<T>,\n index: number,\n minimised: boolean\n ) => {\n const originalItem = option.originalItem;\n const optionLabel = getLabel(originalItem);\n const { checked, indeterminate } = getCheckboxState(option);\n const isSelected = checked || indeterminate;\n const isVisible = !minimised || index < 5;\n\n // ARIA attributes for tree items\n const treeItemAriaAttributes: AriaAttributes = isNested\n ? {\n \"aria-checked\": indeterminate ? \"mixed\" : checked,\n \"aria-selected\": !!checked,\n \"aria-level\": option.level + 1,\n \"aria-posinset\": option.indexInParent + 1,\n \"aria-setsize\": option.parentSetSize,\n }\n : {};\n\n const itemRef = (el: HTMLElement | null) => {\n if (el && option.level) {\n el.style.setProperty(\n styles.tokens.item.level,\n String(option.level)\n );\n }\n if (index === 4) {\n lastVisibleElement.current = el;\n }\n };\n\n const itemClassName = clsx(\n styles.item,\n !isVisible && styles.itemHidden,\n isSelected && styles.itemSelected\n );\n\n const itemContent = (\n <>\n {renderCheckboxIcon(originalItem, option)}\n {optionLabel}\n </>\n );\n\n if (isNested) {\n return (\n <div\n key={buildKeyPath(option.keyPath)}\n role=\"treeitem\"\n {...treeItemAriaAttributes}\n onClick={handleItemClick(originalItem)}\n onKeyDown={handleListItemKeyDown(originalItem)}\n tabIndex={0}\n className={itemClassName}\n ref={itemRef}\n >\n {itemContent}\n </div>\n );\n }\n\n return (\n <label\n key={buildKeyPath(option.keyPath)}\n onKeyDown={handleListItemKeyDown(originalItem)}\n className={itemClassName}\n ref={itemRef}\n >\n {itemContent}\n </label>\n );\n };\n\n const renderToggle = (\n option: FlattenedFilterOption<T>,\n index: number,\n minimised: boolean\n ) => {\n const originalItem = option.originalItem;\n const optionLabel = getLabel(originalItem);\n const optionValue = getValue(originalItem);\n const checked = !!selected.find((s) => getValue(s) === optionValue);\n const isToggleVisible =\n !minimised ||\n (!!minimisedHeight && index <= lastVisibleElementIndex);\n return (\n <Toggle\n key={optionValue}\n type=\"checkbox\"\n checked={checked}\n className={clsx(\n !useToggleContentWidth && styles.toggle,\n !isToggleVisible && styles.toggleHidden\n )}\n onChange={handleItemClick(originalItem)}\n useContentWidth={useToggleContentWidth}\n >\n {optionLabel}\n </Toggle>\n );\n };\n\n const renderSelectClearAllButton = () => {\n if (optionCount < 3) {\n return null;\n }\n return (\n <Button\n className={styles.selectAllButton}\n styleType=\"link\"\n type=\"button\"\n sizeType=\"small\"\n onClick={handleSelectClearAll}\n aria-label={\n selected.length\n ? \"Clear all selections\"\n : `Select all in ${\n parentRef.current?.ariaLabel || \"this group\"\n }`\n }\n >\n {selected.length ? \"Clear all\" : \"Select all\"}\n </Button>\n );\n };\n\n return (\n <FilterItem\n minimisable={\n minimisableOptions\n ? isMobileToggleMode // set minimisable base on mobile toggle mode\n ? !!minimisedHeight\n : optionCount > 5\n : false // if minimisableOptions is false, never allow minimising\n }\n minimisedHeight={minimisedHeight}\n {...filterItemProps}\n className={clsx(styles.filterItem, filterItemProps.className)}\n >\n {(_, { minimised }) => (\n <>\n {renderSelectClearAllButton()}\n <div\n role={isNested ? \"tree\" : \"group\"}\n aria-label={filterItemProps.title}\n aria-multiselectable={true}\n ref={parentRef}\n className={clsx(\n styles.group,\n isMobileToggleMode && styles.groupMobileToggleMode\n )}\n >\n {flattenedOptions.map((option, i) =>\n isMobileToggleMode\n ? renderToggle(option, i, minimised)\n : renderCheckbox(option, i, minimised)\n )}\n </div>\n </>\n )}\n </FilterItem>\n );\n};\n\nFilterItemCheckbox.displayName = \"Filter.Checkbox\";\n"],"names":["FilterItemCheckbox","_a","selectedOptions","options","showAsCheckboxInMobile","minimisableOptions","onSelect","labelExtractor","valueExtractor","useToggleContentWidth","filterItemProps","__rest","mode","useContext","FilterContext","selected","setSelected","useState","minimisedHeight","setMinimisedHeight","lastVisibleElementIndex","setLastVisibleElementIndex","length","parentRef","useRef","lastVisibleElement","isNested","useMemo","hasNestedOptions","item","isMobileToggleMode","flattenedOptions","flattenNestedOptions","value","label","optionCount","handleItemClick","flatOption","find","opt","originalItem","hasChildren","allChildren","getAllDescendantChildren","keyPath","currentlySelectedChildren","filter","child","some","s","getValue","newSelection","forEach","push","selectedIndex","findIndex","splice","handleSelectClearAll","allValues","option","map","handleListItemKeyDown","event","key","preventDefault","handleCheckboxChange","getCheckboxState","checked","indeterminate","getAllDescendantKeyPaths","buildKeyPath","selectedChildren","getLabel","toString","setVisibleItemsWhenMinimised","elementBottom","current","offsetTop","clientHeight","undefined","setVisibleMobileItemsWhenMinimised","useCallback","children","Array","from","lastElementInRow","rowCount","rowTop","i","childTop","useEffect","useResizeDetector","handleWidth","handleHeight","skipOnMount","refreshMode","targetRef","onResize","renderCheckboxIcon","_jsx","Checkbox","className","styles.checkbox","displaySize","onChange","tabIndex","renderSelectClearAllButton","Button","styles.selectAllButton","styleType","type","sizeType","onClick","ariaLabel","FilterItem","Object","assign","minimisable","clsx","styles.filterItem","_","minimised","_jsxs","_Fragment","role","title","ref","styles.group","styles.groupMobileToggleMode","index","optionLabel","optionValue","isToggleVisible","Toggle","styles.toggle","styles.toggleHidden","useContentWidth","renderToggle","isSelected","isVisible","treeItemAriaAttributes","level","indexInParent","parentSetSize","itemRef","el","style","setProperty","styles.tokens","String","itemClassName","styles.item","styles.itemHidden","styles.itemSelected","itemContent","onKeyDown","renderCheckbox","displayName"],"mappings":"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"}
1
+ {"version":3,"file":"filter-item-checkbox.js","sources":["../../../../src/filter/addons/filter-item-checkbox.tsx"],"sourcesContent":["import clsx from \"clsx\";\nimport type { AriaAttributes } from \"react\";\nimport {\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from \"react\";\nimport { useResizeDetector } from \"react-resize-detector\";\n\nimport { Button } from \"../../button\";\nimport { Checkbox } from \"../../checkbox\";\nimport { Toggle } from \"../../toggle\";\nimport { FilterContext } from \"../filter-context\";\nimport { FilterItem } from \"../filter-item\";\nimport * as styles from \"./filter-item-checkbox.styles\";\nimport {\n buildKeyPath,\n flattenNestedOptions,\n getAllDescendantChildren,\n getAllDescendantKeyPaths,\n hasNestedOptions,\n} from \"./filter-item-checkbox-helpers\";\nimport type { FlattenedFilterOption } from \"./internal-types\";\nimport type {\n FilterItemCheckboxOptionProps,\n FilterItemCheckboxProps,\n} from \"./types\";\n\nexport const FilterItemCheckbox = <T = FilterItemCheckboxOptionProps,>({\n selectedOptions,\n options,\n showAsCheckboxInMobile = false,\n minimisableOptions = true,\n onSelect,\n labelExtractor,\n valueExtractor,\n useToggleContentWidth,\n ...filterItemProps\n}: FilterItemCheckboxProps<T>) => {\n // =============================================================================\n // CONST, STATE, REF\n // =============================================================================\n const { mode } = useContext(FilterContext);\n const [selected, setSelected] = useState<T[]>(selectedOptions || []);\n const [minimisedHeight, setMinimisedHeight] = useState<number>();\n const [lastVisibleElementIndex, setLastVisibleElementIndex] =\n useState<number>(options.length);\n const parentRef = useRef<HTMLDivElement>(null);\n const lastVisibleElement = useRef<HTMLElement | null>(null);\n\n // Check if options have nested structure\n const isNested = useMemo(\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n () => hasNestedOptions(options, (item) => (item as any).options),\n [options]\n );\n\n const isMobileToggleMode =\n mode === \"mobile\" && !showAsCheckboxInMobile && !isNested;\n\n // Flatten nested options\n const flattenedOptions = useMemo(\n () =>\n flattenNestedOptions(\n options,\n [],\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n valueExtractor || ((item) => (item as any).value),\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n labelExtractor || ((item) => (item as any).label)\n ),\n [options, valueExtractor, labelExtractor]\n );\n\n const optionCount = flattenedOptions.length;\n\n // =============================================================================\n // EVENT HANDLERS\n // =============================================================================\n const handleItemClick = (item: T) => () => {\n // Find the flattened option\n const flatOption = flattenedOptions.find(\n (opt) => opt.originalItem === item\n );\n if (!flatOption) return;\n\n if (flatOption.hasChildren) {\n // Handle parent click - select/deselect all children\n const allChildren = getAllDescendantChildren<T>(\n flattenedOptions,\n flatOption.keyPath\n );\n\n const currentlySelectedChildren = allChildren.filter((child) =>\n selected.some((s) => getValue(s) === getValue(child))\n );\n\n let newSelection = [...selected];\n\n if (currentlySelectedChildren.length === allChildren.length) {\n // All children selected, deselect all\n newSelection = newSelection.filter(\n (s) =>\n !allChildren.some(\n (child) => getValue(child) === getValue(s)\n )\n );\n } else {\n // Some or no children selected, select all\n allChildren.forEach((child) => {\n if (\n !newSelection.some(\n (s) => getValue(s) === getValue(child)\n )\n ) {\n newSelection.push(child);\n }\n });\n }\n\n setSelected(newSelection);\n onSelect?.(newSelection);\n } else {\n // Handle leaf item click - toggle selection\n const newSelection = [...selected];\n const selectedIndex = selected.findIndex(\n (s) => getValue(s) === getValue(item)\n );\n\n if (selectedIndex >= 0) {\n newSelection.splice(selectedIndex, 1);\n } else {\n newSelection.push(item);\n }\n setSelected(newSelection);\n onSelect?.(newSelection);\n }\n };\n\n const handleSelectClearAll = () => {\n if (isNested) {\n if (selected.length > 0) {\n // Clear all\n setSelected([]);\n onSelect?.([]);\n } else {\n // Select all leaf nodes\n const leafOptions = flattenedOptions.filter(\n (option) => !option.hasChildren\n );\n const allValues = leafOptions.map(\n (option) => option.originalItem\n ) as T[];\n setSelected(allValues);\n onSelect?.(allValues);\n }\n } else {\n const newSelection = selected.length ? [] : options;\n setSelected(newSelection);\n onSelect?.(newSelection);\n }\n };\n\n const handleListItemKeyDown =\n (originalItem: T) => (event: React.KeyboardEvent) => {\n if (isNested && (event.key === \" \" || event.key === \"Enter\")) {\n event.preventDefault();\n handleItemClick(originalItem)();\n }\n };\n\n const handleCheckboxChange = (originalItem: T) => () => {\n if (!isNested) {\n handleItemClick(originalItem)();\n }\n };\n\n // =============================================================================\n // HELPER FUNCTIONS\n // =============================================================================\n const getCheckboxState = (flatOption: (typeof flattenedOptions)[0]) => {\n if (!flatOption.hasChildren) {\n // Leaf item - simple check\n return {\n checked: selected.some(\n (s) =>\n getValue(s) === getValue(flatOption.originalItem as T)\n ),\n indeterminate: false,\n };\n }\n\n // Parent item - check children states (following IndeterminateState pattern)\n const allChildren = getAllDescendantKeyPaths(\n flattenedOptions,\n flatOption.keyPath\n )\n .map((keyPath: string[]) =>\n flattenedOptions.find(\n (opt) => buildKeyPath(opt.keyPath) === buildKeyPath(keyPath)\n )\n )\n .filter((opt) => opt && !opt.hasChildren)\n .map((opt) => opt!.originalItem as T);\n\n const selectedChildren = allChildren.filter((child) =>\n selected.some((s) => getValue(s) === getValue(child))\n );\n\n return {\n checked:\n selectedChildren.length === allChildren.length &&\n allChildren.length > 0,\n indeterminate:\n selectedChildren.length > 0 &&\n selectedChildren.length < allChildren.length,\n };\n };\n\n const getLabel = (item: T): React.ReactNode => {\n return labelExtractor\n ? labelExtractor(item)\n : // eslint-disable-next-line @typescript-eslint/no-explicit-any\n (item as any).label ?? item?.toString();\n };\n\n const getValue = (item: T): string => {\n return valueExtractor\n ? valueExtractor(item)\n : // eslint-disable-next-line @typescript-eslint/no-explicit-any\n (item as any).value ?? item?.toString();\n };\n\n const setVisibleItemsWhenMinimised = () => {\n const elementBottom = lastVisibleElement.current\n ? lastVisibleElement.current.offsetTop +\n lastVisibleElement.current.clientHeight\n : undefined;\n setMinimisedHeight(elementBottom);\n };\n\n const setVisibleMobileItemsWhenMinimised = useCallback(() => {\n if (!parentRef.current) {\n setMinimisedHeight(undefined);\n return;\n }\n\n const children = Array.from(parentRef.current.children);\n\n let lastElementInRow = 0;\n let rowCount = 0;\n let rowTop = -1;\n\n for (let i = 0; i < children.length; i++) {\n const childTop = (children[i] as HTMLDivElement).offsetTop;\n if (childTop > rowTop) {\n rowCount++;\n rowTop = childTop;\n // show only the first 2 rows\n if (rowCount > 2) {\n break;\n }\n }\n lastElementInRow = i;\n }\n\n setLastVisibleElementIndex(lastElementInRow);\n\n if (rowCount > 2) {\n setMinimisedHeight(rowTop - 8); // gap from next row\n } else {\n setMinimisedHeight(undefined);\n }\n }, []);\n\n // =============================================================================\n // EFFECTS\n // =============================================================================\n useEffect(() => {\n if (selectedOptions !== selected) {\n setSelected(selectedOptions || []);\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [selectedOptions]);\n\n useEffect(() => {\n if (isMobileToggleMode) {\n setVisibleMobileItemsWhenMinimised();\n } else {\n setVisibleItemsWhenMinimised();\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [options]);\n\n useResizeDetector({\n handleWidth: true,\n handleHeight: false,\n skipOnMount: true,\n refreshMode: \"throttle\",\n targetRef: parentRef,\n onResize: isMobileToggleMode\n ? setVisibleMobileItemsWhenMinimised\n : setVisibleItemsWhenMinimised,\n });\n\n // =============================================================================\n // RENDER FUNCTIONS\n // =============================================================================\n const renderCheckboxIcon = (\n originalItem: T,\n flatOption: FlattenedFilterOption<T>\n ) => {\n const { checked, indeterminate } = getCheckboxState(flatOption);\n\n return (\n <Checkbox\n className={styles.checkbox}\n displaySize=\"small\"\n checked={checked}\n indeterminate={indeterminate}\n onChange={handleCheckboxChange(originalItem)}\n tabIndex={isNested ? -1 : undefined}\n aria-hidden={isNested ? \"true\" : undefined}\n />\n );\n };\n\n const renderCheckbox = (\n option: FlattenedFilterOption<T>,\n index: number,\n minimised: boolean\n ) => {\n const originalItem = option.originalItem;\n const optionLabel = getLabel(originalItem);\n const { checked, indeterminate } = getCheckboxState(option);\n const isSelected = checked || indeterminate;\n const isVisible = !minimised || index < 5;\n\n // ARIA attributes for tree items\n const treeItemAriaAttributes: AriaAttributes = isNested\n ? {\n \"aria-checked\": indeterminate ? \"mixed\" : checked,\n \"aria-selected\": !!checked,\n \"aria-level\": option.level + 1,\n \"aria-posinset\": option.indexInParent + 1,\n \"aria-setsize\": option.parentSetSize,\n }\n : {};\n\n const itemRef = (el: HTMLElement | null) => {\n if (el && option.level) {\n el.style.setProperty(\n styles.tokens.item.level,\n String(option.level)\n );\n }\n if (index === 4) {\n lastVisibleElement.current = el;\n }\n };\n\n const itemClassName = clsx(\n styles.item,\n !isVisible && styles.itemHidden,\n isSelected && styles.itemSelected\n );\n\n const itemContent = (\n <>\n {renderCheckboxIcon(originalItem, option)}\n {optionLabel}\n </>\n );\n\n if (isNested) {\n return (\n <div\n key={buildKeyPath(option.keyPath)}\n role=\"treeitem\"\n {...treeItemAriaAttributes}\n onClick={handleItemClick(originalItem)}\n onKeyDown={handleListItemKeyDown(originalItem)}\n tabIndex={0}\n className={itemClassName}\n ref={itemRef}\n >\n {itemContent}\n </div>\n );\n }\n\n return (\n <label\n key={buildKeyPath(option.keyPath)}\n onKeyDown={handleListItemKeyDown(originalItem)}\n className={itemClassName}\n ref={itemRef}\n >\n {itemContent}\n </label>\n );\n };\n\n const renderToggle = (\n option: FlattenedFilterOption<T>,\n index: number,\n minimised: boolean\n ) => {\n const originalItem = option.originalItem;\n const optionLabel = getLabel(originalItem);\n const optionValue = getValue(originalItem);\n const checked = !!selected.find((s) => getValue(s) === optionValue);\n const isToggleVisible =\n !minimised ||\n (!!minimisedHeight && index <= lastVisibleElementIndex);\n return (\n <Toggle\n key={optionValue}\n type=\"checkbox\"\n checked={checked}\n className={clsx(\n !useToggleContentWidth && styles.toggle,\n !isToggleVisible && styles.toggleHidden\n )}\n onChange={handleItemClick(originalItem)}\n useContentWidth={useToggleContentWidth}\n >\n {optionLabel}\n </Toggle>\n );\n };\n\n const renderSelectClearAllButton = () => {\n if (optionCount < 3) {\n return null;\n }\n return (\n <Button\n className={styles.selectAllButton}\n styleType=\"link\"\n type=\"button\"\n sizeType=\"small\"\n onClick={handleSelectClearAll}\n aria-label={\n selected.length\n ? \"Clear all selections\"\n : `Select all in ${\n parentRef.current?.ariaLabel || \"this group\"\n }`\n }\n >\n {selected.length ? \"Clear all\" : \"Select all\"}\n </Button>\n );\n };\n\n return (\n <FilterItem\n minimisable={\n minimisableOptions\n ? isMobileToggleMode // set minimisable base on mobile toggle mode\n ? !!minimisedHeight\n : optionCount > 5\n : false // if minimisableOptions is false, never allow minimising\n }\n minimisedHeight={minimisedHeight}\n {...filterItemProps}\n className={clsx(styles.filterItem, filterItemProps.className)}\n >\n {(_, { minimised }) => (\n <>\n {renderSelectClearAllButton()}\n <div\n role={isNested ? \"tree\" : \"group\"}\n aria-label={filterItemProps.title}\n aria-multiselectable={true}\n ref={parentRef}\n className={clsx(\n styles.group,\n isMobileToggleMode && styles.groupMobileToggleMode\n )}\n >\n {flattenedOptions.map((option, i) =>\n isMobileToggleMode\n ? renderToggle(option, i, minimised)\n : renderCheckbox(option, i, minimised)\n )}\n </div>\n </>\n )}\n </FilterItem>\n );\n};\n\nFilterItemCheckbox.displayName = \"Filter.Checkbox\";\n"],"names":["FilterItemCheckbox","_a","selectedOptions","options","showAsCheckboxInMobile","minimisableOptions","onSelect","labelExtractor","valueExtractor","useToggleContentWidth","filterItemProps","__rest","mode","useContext","FilterContext","selected","setSelected","useState","minimisedHeight","setMinimisedHeight","lastVisibleElementIndex","setLastVisibleElementIndex","length","parentRef","useRef","lastVisibleElement","isNested","useMemo","hasNestedOptions","item","isMobileToggleMode","flattenedOptions","flattenNestedOptions","value","label","optionCount","handleItemClick","flatOption","find","opt","originalItem","hasChildren","allChildren","getAllDescendantChildren","keyPath","currentlySelectedChildren","filter","child","some","s","getValue","newSelection","forEach","push","selectedIndex","findIndex","splice","handleSelectClearAll","allValues","option","map","handleListItemKeyDown","event","key","preventDefault","handleCheckboxChange","getCheckboxState","checked","indeterminate","getAllDescendantKeyPaths","buildKeyPath","selectedChildren","getLabel","toString","setVisibleItemsWhenMinimised","elementBottom","current","offsetTop","clientHeight","undefined","setVisibleMobileItemsWhenMinimised","useCallback","children","Array","from","lastElementInRow","rowCount","rowTop","i","childTop","useEffect","useResizeDetector","handleWidth","handleHeight","skipOnMount","refreshMode","targetRef","onResize","renderCheckboxIcon","_jsx","Checkbox","className","styles.checkbox","displaySize","onChange","tabIndex","renderSelectClearAllButton","Button","styles.selectAllButton","styleType","type","sizeType","onClick","ariaLabel","FilterItem","Object","assign","minimisable","clsx","styles.filterItem","_","minimised","_jsxs","_Fragment","role","title","ref","styles.group","styles.groupMobileToggleMode","index","optionLabel","optionValue","isToggleVisible","Toggle","styles.toggle","styles.toggleHidden","useContentWidth","renderToggle","isSelected","isVisible","treeItemAriaAttributes","level","indexInParent","parentSetSize","itemRef","el","style","setProperty","styles.tokens","String","itemClassName","styles.item","styles.itemHidden","styles.itemSelected","itemContent","onKeyDown","renderCheckbox","displayName"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- "use strict";require("./filter-item-checkbox.styles_7degw7.css");exports.checkbox="c13wglju",exports.filterItem="f1m3a5f4",exports.group="g11488am",exports.groupMobileToggleMode="g1nnu0tt",exports.item="i4hhc1a",exports.itemHidden="i7vabkq",exports.itemSelected="i4eh8j6",exports.selectAllButton="sbvftpe",exports.toggle="twhh8xx",exports.toggleHidden="tb2fwos",exports.tokens={item:{level:"--fds-internal-filterItemCheckbox-item-level"}};
1
+ "use strict";require("./filter-item-checkbox.styles_6nbpdl.css");exports.checkbox="c13wglju",exports.filterItem="f1m3a5f4",exports.group="g11488am",exports.groupMobileToggleMode="g1nnu0tt",exports.item="i4hhc1a",exports.itemHidden="i7vabkq",exports.itemSelected="i4eh8j6",exports.selectAllButton="sbvftpe",exports.toggle="twhh8xx",exports.toggleHidden="tb2fwos",exports.tokens={item:{level:"--fds-internal-filterItemCheckbox-item-level"}};
2
2
  //# sourceMappingURL=filter-item-checkbox.styles.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"filter-item-checkbox.styles.js","sources":["../../../../src/filter/addons/filter-item-checkbox.styles.ts"],"sourcesContent":["import { css } from \"@linaria/core\";\n\nimport { Colour, Font, MediaQuery, Spacing } from \"../../theme\";\n\nexport const tokens = {\n item: {\n level: \"--fds-internal-filterItemCheckbox-item-level\",\n },\n} as const;\n\nexport const filterItem = css`\n padding: 0 0 ${Spacing[\"spacing-16\"]};\n\n [data-id=\"content-container\"] {\n position: relative; // to get the item position relative to this parent\n padding: ${Spacing[\"spacing-8\"]} ${Spacing[\"spacing-8\"]} 0;\n\n ${MediaQuery.MaxWidth.lg} {\n padding: ${Spacing[\"spacing-16\"]} ${Spacing[\"spacing-20\"]}\n ${Spacing[\"spacing-8\"]};\n }\n }\n\n [data-id=\"minimise-button\"] {\n margin: ${Spacing[\"spacing-8\"]} ${Spacing[\"spacing-20\"]} 0;\n }\n`;\n\nexport const group = css`\n display: flex;\n flex-direction: column;\n\n ${MediaQuery.MaxWidth.lg} {\n flex-direction: row;\n flex-wrap: wrap;\n gap: 0;\n }\n`;\n\nexport const groupMobileToggleMode = css`\n ${MediaQuery.MaxWidth.lg} {\n gap: ${Spacing[\"spacing-16\"]};\n }\n`;\n\nexport const item = css`\n ${tokens.item.level}: 0;\n\n display: flex;\n align-items: flex-start;\n\n position: relative;\n width: 100%;\n min-height: 1.5rem;\n padding: ${Spacing[\"spacing-8\"]} ${Spacing[\"spacing-12\"]};\n padding-left: calc(\n ${Spacing[\"spacing-12\"]} + var(${tokens.item.level}) *\n ${Spacing[\"spacing-32\"]}\n );\n\n cursor: pointer;\n ${Font[\"body-md-regular\"]}\n color: ${Colour[\"text\"]};\n\n ${MediaQuery.MaxWidth.lg} {\n padding: ${Spacing[\"spacing-8\"]};\n padding-left: calc(\n ${Spacing[\"spacing-8\"]} + var(${tokens.item.level}) *\n ${Spacing[\"spacing-32\"]}\n );\n }\n`;\n\nexport const itemHidden = css`\n display: none;\n`;\n\nexport const itemSelected = css`\n color: ${Colour[\"text-selected\"]};\n`;\n\nexport const checkbox = css`\n flex-shrink: 0;\n margin-right: ${Spacing[\"spacing-8\"]};\n`;\n\nexport const toggle = css`\n min-width: 5rem;\n`;\n\nexport const toggleHidden = css`\n visibility: hidden;\n`;\n\nexport const selectAllButton = css`\n height: fit-content;\n padding: 0;\n margin: ${Spacing[\"spacing-16\"]} 0 ${Spacing[\"spacing-8\"]}\n ${Spacing[\"spacing-12\"]};\n\n ${MediaQuery.MaxWidth.lg} {\n margin: 0 0 ${Spacing[\"spacing-16\"]} 0;\n }\n`;\n"],"names":["item","level"],"mappings":"+GAiFqB,8BAvEE,yBAkBL,yCAWgB,wBAMjB,6BA4BM,+BAIE,kCAiBG,yBART,+BAIM,yBAtFH,CAClBA,KAAM,CACFC,MAAO"}
1
+ {"version":3,"file":"filter-item-checkbox.styles.js","sources":["../../../../src/filter/addons/filter-item-checkbox.styles.ts"],"sourcesContent":["import { css } from \"@linaria/core\";\n\nimport { Colour, Font, MediaQuery, Spacing } from \"../../theme\";\n\nexport const tokens = {\n item: {\n level: \"--fds-internal-filterItemCheckbox-item-level\",\n },\n} as const;\n\nexport const filterItem = css`\n padding: 0 0 ${Spacing[\"spacing-16\"]};\n\n [data-id=\"content-container\"] {\n position: relative; // to get the item position relative to this parent\n padding: ${Spacing[\"spacing-8\"]} ${Spacing[\"spacing-8\"]} 0;\n\n ${MediaQuery.MaxWidth.lg} {\n padding: ${Spacing[\"spacing-16\"]} ${Spacing[\"spacing-20\"]}\n ${Spacing[\"spacing-8\"]};\n }\n }\n\n [data-id=\"minimise-button\"] {\n margin: ${Spacing[\"spacing-8\"]} ${Spacing[\"spacing-20\"]} 0;\n }\n`;\n\nexport const group = css`\n display: flex;\n flex-direction: column;\n\n ${MediaQuery.MaxWidth.lg} {\n flex-direction: row;\n flex-wrap: wrap;\n gap: 0;\n }\n`;\n\nexport const groupMobileToggleMode = css`\n ${MediaQuery.MaxWidth.lg} {\n gap: ${Spacing[\"spacing-16\"]};\n }\n`;\n\nexport const item = css`\n ${tokens.item.level}: 0;\n\n display: flex;\n align-items: flex-start;\n\n position: relative;\n width: 100%;\n min-height: 1.5rem;\n padding: ${Spacing[\"spacing-8\"]} ${Spacing[\"spacing-12\"]};\n padding-left: calc(\n ${Spacing[\"spacing-12\"]} + var(${tokens.item.level}) *\n ${Spacing[\"spacing-32\"]}\n );\n\n cursor: pointer;\n ${Font[\"body-md-regular\"]}\n color: ${Colour[\"text\"]};\n\n ${MediaQuery.MaxWidth.lg} {\n padding: ${Spacing[\"spacing-8\"]};\n padding-left: calc(\n ${Spacing[\"spacing-8\"]} + var(${tokens.item.level}) *\n ${Spacing[\"spacing-32\"]}\n );\n }\n`;\n\nexport const itemHidden = css`\n display: none;\n`;\n\nexport const itemSelected = css`\n color: ${Colour[\"text-selected\"]};\n`;\n\nexport const checkbox = css`\n flex-shrink: 0;\n margin-right: ${Spacing[\"spacing-8\"]};\n`;\n\nexport const toggle = css`\n min-width: 5rem;\n`;\n\nexport const toggleHidden = css`\n visibility: hidden;\n`;\n\nexport const selectAllButton = css`\n height: fit-content;\n min-height: unset;\n padding: 0;\n margin: ${Spacing[\"spacing-16\"]} 0 ${Spacing[\"spacing-8\"]}\n ${Spacing[\"spacing-12\"]};\n\n ${MediaQuery.MaxWidth.lg} {\n margin: 0 0 ${Spacing[\"spacing-16\"]} 0;\n }\n`;\n"],"names":["item","level"],"mappings":"+GAiFqB,8BAvEE,yBAkBL,yCAWgB,wBAMjB,6BA4BM,+BAIE,kCAiBG,yBART,+BAIM,yBAtFH,CAClBA,KAAM,CACFC,MAAO"}
@@ -13,4 +13,4 @@
13
13
  .c13wglju{-webkit-flex-shrink:0;-ms-flex-negative:0;flex-shrink:0;margin-right:var(--fds-spacing-8);}
14
14
  .twhh8xx{min-width:5rem;}
15
15
  .tb2fwos{visibility:hidden;}
16
- .sbvftpe{height:-webkit-fit-content;height:-moz-fit-content;height:fit-content;padding:0;margin:var(--fds-spacing-16) 0 var(--fds-spacing-8) var(--fds-spacing-12);}:where(body.fds-breakpoint-lg-max) .sbvftpe{margin:0 0 var(--fds-spacing-16) 0;}}
16
+ .sbvftpe{height:-webkit-fit-content;height:-moz-fit-content;height:fit-content;min-height:unset;padding:0;margin:var(--fds-spacing-16) 0 var(--fds-spacing-8) var(--fds-spacing-12);}:where(body.fds-breakpoint-lg-max) .sbvftpe{margin:0 0 var(--fds-spacing-16) 0;}}
@@ -1 +1 @@
1
- {"version":3,"file":"filter-item.js","sources":["../../../src/filter/filter-item.tsx"],"sourcesContent":["import { ChevronDownIcon } from \"@lifesg/react-icons/chevron-down\";\nimport { animated, useSpring } from \"@react-spring/web\";\nimport clsx from \"clsx\";\nimport isNil from \"lodash/isNil\";\nimport { useContext, useEffect, useRef, useState } from \"react\";\nimport { useResizeDetector } from \"react-resize-detector\";\n\nimport { Button } from \"../button\";\nimport { PopoverAddon } from \"../form/form-label/form-label-addon\";\nimport { inertValue, VisuallyHidden } from \"../shared/accessibility\";\nimport { ClickableIcon } from \"../shared/clickable-icon\";\nimport { useApplyStyle } from \"../theme\";\nimport { useId } from \"../util\";\nimport { FilterContext } from \"./filter-context\";\nimport * as styles from \"./filter-item.styles\";\nimport type { FilterItemProps } from \"./types\";\n\nconst DEFAULT_MINIMISED_HEIGHT_CAP = 216;\n\nexport const FilterItem = ({\n collapsible: desktopCollapsible = true,\n initialExpanded = false,\n expanded: controlledExpanded,\n onExpandChange,\n minimisable = false,\n minimisedHeight,\n showDivider = true,\n showMobileDivider = true,\n title,\n addon,\n children,\n className,\n ...otherProps\n}: FilterItemProps) => {\n // =============================================================================\n // CONST, STATE, REF\n // =============================================================================\n const { mode, rootNode } = useContext(FilterContext);\n const isMobile = mode === \"mobile\";\n const [expanded, setExpanded] = useState(getInitialExpandState());\n const [contentMinimised, setContentMinimised] = useState(minimisable);\n const collapsible = !isMobile && desktopCollapsible;\n\n const itemResizeDetector = useResizeDetector();\n const contentResizeDetector = useResizeDetector();\n const itemAnimationStyles = useSpring({\n height: expanded ? itemResizeDetector.height : 0,\n });\n const contentHeight = contentMinimised\n ? minimisedHeight ??\n Math.min(\n (contentResizeDetector.height ?? 0) * 0.5,\n DEFAULT_MINIMISED_HEIGHT_CAP\n )\n : contentResizeDetector.height;\n const internalId = useId();\n const contentId = `${internalId}-content`;\n const titleId = `${internalId}-title`;\n const minimisableContentRef = useRef<HTMLDivElement | null>(null);\n\n useApplyStyle(minimisableContentRef, {\n [styles.tokens.minimisableContent.height]: contentHeight\n ? `${contentHeight}px`\n : null,\n });\n\n // =============================================================================\n // EFFECTS\n // =============================================================================\n useEffect(() => {\n setExpanded(getInitialExpandState());\n }, [desktopCollapsible, controlledExpanded]);\n\n useEffect(() => {\n setContentMinimised(minimisable);\n }, [minimisable]);\n // =============================================================================\n // EVENT HANDLERS\n // =============================================================================\n const handleExpandCollapse = () => {\n const nextState = !expanded;\n\n if (isNil(controlledExpanded)) {\n setExpanded(nextState);\n }\n\n if (onExpandChange) {\n onExpandChange(nextState);\n }\n };\n\n const handleMinimise = () => {\n setContentMinimised(!contentMinimised);\n };\n\n // =============================================================================\n // HELPERS\n // =============================================================================\n function getInitialExpandState() {\n if (isMobile) {\n return true;\n }\n if (isNil(controlledExpanded)) {\n return !desktopCollapsible || initialExpanded;\n }\n return controlledExpanded;\n }\n\n // =============================================================================\n // RENDER\n // =============================================================================\n\n const renderAddon = () => {\n switch (addon?.type) {\n case \"popover\":\n return (\n <PopoverAddon\n addon={addon}\n rootNode={isMobile ? rootNode : undefined}\n />\n );\n default:\n return null;\n }\n };\n\n return (\n <div\n aria-labelledby={titleId}\n className={clsx(\n styles.filterItemWrapper,\n (collapsible || isMobile) && styles.filterItemWrapperDarker\n )}\n >\n <div\n className={clsx(\n styles.divider,\n (isMobile ? showMobileDivider : showDivider) &&\n styles.dividerVisible,\n isMobile && styles.dividerMobile\n )}\n />\n {(title || collapsible) && (\n <div\n className={clsx(\n styles.filterItemHeader,\n isMobile && styles.filterItemHeaderMobile\n )}\n >\n {title && (\n <h3\n id={titleId}\n data-testid=\"filter-item-title\"\n className={clsx(\n styles.filterItemTitle,\n isMobile && styles.filterItemTitleMobile\n )}\n >\n {title} {addon && renderAddon()}\n </h3>\n )}\n {collapsible && (\n <ClickableIcon\n className={styles.filterItemExpandButton}\n data-testid={\"expand-collapse-button\"}\n focusHighlight={false}\n focusOutline=\"browser\"\n onClick={handleExpandCollapse}\n aria-expanded={expanded}\n aria-disabled={!collapsible}\n aria-controls={contentId}\n >\n {title && <VisuallyHidden>{title}</VisuallyHidden>}\n <ChevronDownIcon\n aria-hidden\n className={clsx(\n styles.chevronIcon,\n expanded && styles.chevronIconExpanded\n )}\n />\n </ClickableIcon>\n )}\n </div>\n )}\n <animated.div\n className={styles.expandableItem}\n id={contentId}\n data-testid={\"expandable-container\"}\n data-expanded={expanded}\n style={itemAnimationStyles}\n inert={inertValue(!expanded)}\n >\n <div ref={itemResizeDetector.ref}>\n <div\n className={clsx(styles.filterItemBody, className)}\n {...otherProps}\n >\n <div\n ref={minimisableContentRef}\n data-testid=\"minimisable-container\"\n className={clsx(\n styles.minimisableContent,\n minimisable &&\n styles.minimisableContentMinimisable\n )}\n >\n <div ref={contentResizeDetector.ref}>\n <div data-id=\"content-container\">\n {typeof children === \"function\"\n ? children(mode, {\n minimised: contentMinimised,\n })\n : children}\n </div>\n </div>\n </div>\n {minimisable && (\n <Button\n className={styles.filterItemMinimiseButton}\n data-id=\"minimise-button\"\n sizeType=\"small\"\n styleType=\"link\"\n type=\"button\"\n onClick={handleMinimise}\n >\n <VisuallyHidden>{`view ${\n contentMinimised ? \"more\" : \"less\"\n } in ${title}`}</VisuallyHidden>\n <span aria-hidden>\n View {contentMinimised ? \"more\" : \"less\"}\n </span>\n </Button>\n )}\n </div>\n </div>\n </animated.div>\n </div>\n );\n};\n\nFilterItem.displayName = \"Filter.Item\";\n"],"names":["FilterItem","_a","collapsible","desktopCollapsible","initialExpanded","expanded","controlledExpanded","onExpandChange","minimisable","minimisedHeight","showDivider","showMobileDivider","title","addon","children","className","otherProps","__rest","mode","rootNode","useContext","FilterContext","isMobile","setExpanded","useState","getInitialExpandState","contentMinimised","setContentMinimised","itemResizeDetector","useResizeDetector","contentResizeDetector","itemAnimationStyles","useSpring","height","contentHeight","Math","min","_b","internalId","useId","contentId","titleId","minimisableContentRef","useRef","useApplyStyle","styles.tokens","minimisableContent","useEffect","isNil","_jsxs","clsx","styles.filterItemWrapper","styles.filterItemWrapperDarker","_jsx","styles.divider","styles.dividerVisible","styles.dividerMobile","styles.filterItemHeader","styles.filterItemHeaderMobile","id","styles.filterItemTitle","styles.filterItemTitleMobile","type","PopoverAddon","undefined","ClickableIcon","styles.filterItemExpandButton","focusHighlight","focusOutline","onClick","nextState","VisuallyHidden","ChevronDownIcon","styles.chevronIcon","styles.chevronIconExpanded","animated","div","styles.expandableItem","style","inert","inertValue","ref","Object","assign","styles.filterItemBody","styles.minimisableContent","styles.minimisableContentMinimisable","minimised","Button","styles.filterItemMinimiseButton","sizeType","styleType","displayName"],"mappings":"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"}
1
+ {"version":3,"file":"filter-item.js","sources":["../../../src/filter/filter-item.tsx"],"sourcesContent":["import { ChevronDownIcon } from \"@lifesg/react-icons/chevron-down\";\nimport { animated, useSpring } from \"@react-spring/web\";\nimport clsx from \"clsx\";\nimport isNil from \"lodash/isNil\";\nimport { useContext, useEffect, useRef, useState } from \"react\";\nimport { useResizeDetector } from \"react-resize-detector\";\n\nimport { Button } from \"../button\";\nimport { PopoverAddon } from \"../form/form-label/form-label-addon\";\nimport { inertValue, VisuallyHidden } from \"../shared/accessibility\";\nimport { ClickableIcon } from \"../shared/clickable-icon\";\nimport { useApplyStyle } from \"../theme\";\nimport { useId } from \"../util\";\nimport { FilterContext } from \"./filter-context\";\nimport * as styles from \"./filter-item.styles\";\nimport type { FilterItemProps } from \"./types\";\n\nconst DEFAULT_MINIMISED_HEIGHT_CAP = 216;\n\nexport const FilterItem = ({\n collapsible: desktopCollapsible = true,\n initialExpanded = false,\n expanded: controlledExpanded,\n onExpandChange,\n minimisable = false,\n minimisedHeight,\n showDivider = true,\n showMobileDivider = true,\n title,\n addon,\n children,\n className,\n ...otherProps\n}: FilterItemProps) => {\n // =============================================================================\n // CONST, STATE, REF\n // =============================================================================\n const { mode, rootNode } = useContext(FilterContext);\n const isMobile = mode === \"mobile\";\n const [expanded, setExpanded] = useState(getInitialExpandState());\n const [contentMinimised, setContentMinimised] = useState(minimisable);\n const collapsible = !isMobile && desktopCollapsible;\n\n const itemResizeDetector = useResizeDetector();\n const contentResizeDetector = useResizeDetector();\n const itemAnimationStyles = useSpring({\n height: expanded ? itemResizeDetector.height : 0,\n });\n const contentHeight = contentMinimised\n ? minimisedHeight ??\n Math.min(\n (contentResizeDetector.height ?? 0) * 0.5,\n DEFAULT_MINIMISED_HEIGHT_CAP\n )\n : contentResizeDetector.height;\n const internalId = useId();\n const contentId = `${internalId}-content`;\n const titleId = `${internalId}-title`;\n const minimisableContentRef = useRef<HTMLDivElement | null>(null);\n\n useApplyStyle(minimisableContentRef, {\n [styles.tokens.minimisableContent.height]: contentHeight\n ? `${contentHeight}px`\n : null,\n });\n\n // =============================================================================\n // EFFECTS\n // =============================================================================\n useEffect(() => {\n setExpanded(getInitialExpandState());\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [desktopCollapsible, controlledExpanded]);\n\n useEffect(() => {\n setContentMinimised(minimisable);\n }, [minimisable]);\n // =============================================================================\n // EVENT HANDLERS\n // =============================================================================\n const handleExpandCollapse = () => {\n const nextState = !expanded;\n\n if (isNil(controlledExpanded)) {\n setExpanded(nextState);\n }\n\n if (onExpandChange) {\n onExpandChange(nextState);\n }\n };\n\n const handleMinimise = () => {\n setContentMinimised(!contentMinimised);\n };\n\n // =============================================================================\n // HELPERS\n // =============================================================================\n function getInitialExpandState() {\n if (isMobile) {\n return true;\n }\n if (isNil(controlledExpanded)) {\n return !desktopCollapsible || initialExpanded;\n }\n return controlledExpanded;\n }\n\n // =============================================================================\n // RENDER\n // =============================================================================\n\n const renderAddon = () => {\n switch (addon?.type) {\n case \"popover\":\n return (\n <PopoverAddon\n addon={addon}\n rootNode={isMobile ? rootNode : undefined}\n />\n );\n default:\n return null;\n }\n };\n\n return (\n <div\n aria-labelledby={titleId}\n className={clsx(\n styles.filterItemWrapper,\n (collapsible || isMobile) && styles.filterItemWrapperDarker\n )}\n >\n <div\n className={clsx(\n styles.divider,\n (isMobile ? showMobileDivider : showDivider) &&\n styles.dividerVisible,\n isMobile && styles.dividerMobile\n )}\n />\n {(title || collapsible) && (\n <div\n className={clsx(\n styles.filterItemHeader,\n isMobile && styles.filterItemHeaderMobile\n )}\n >\n {title && (\n <h3\n id={titleId}\n data-testid=\"filter-item-title\"\n className={clsx(\n styles.filterItemTitle,\n isMobile && styles.filterItemTitleMobile\n )}\n >\n {title} {addon && renderAddon()}\n </h3>\n )}\n {collapsible && (\n <ClickableIcon\n className={styles.filterItemExpandButton}\n data-testid={\"expand-collapse-button\"}\n focusHighlight={false}\n focusOutline=\"browser\"\n onClick={handleExpandCollapse}\n aria-expanded={expanded}\n aria-disabled={!collapsible}\n aria-controls={contentId}\n >\n {title && <VisuallyHidden>{title}</VisuallyHidden>}\n <ChevronDownIcon\n aria-hidden\n className={clsx(\n styles.chevronIcon,\n expanded && styles.chevronIconExpanded\n )}\n />\n </ClickableIcon>\n )}\n </div>\n )}\n <animated.div\n className={styles.expandableItem}\n id={contentId}\n data-testid={\"expandable-container\"}\n data-expanded={expanded}\n style={itemAnimationStyles}\n inert={inertValue(!expanded)}\n >\n <div ref={itemResizeDetector.ref}>\n <div\n className={clsx(styles.filterItemBody, className)}\n {...otherProps}\n >\n <div\n ref={minimisableContentRef}\n data-testid=\"minimisable-container\"\n className={clsx(\n styles.minimisableContent,\n minimisable &&\n styles.minimisableContentMinimisable\n )}\n >\n <div ref={contentResizeDetector.ref}>\n <div data-id=\"content-container\">\n {typeof children === \"function\"\n ? children(mode, {\n minimised: contentMinimised,\n })\n : children}\n </div>\n </div>\n </div>\n {minimisable && (\n <Button\n className={styles.filterItemMinimiseButton}\n data-id=\"minimise-button\"\n sizeType=\"small\"\n styleType=\"link\"\n type=\"button\"\n onClick={handleMinimise}\n >\n <VisuallyHidden>{`view ${\n contentMinimised ? \"more\" : \"less\"\n } in ${title}`}</VisuallyHidden>\n <span aria-hidden>\n View {contentMinimised ? \"more\" : \"less\"}\n </span>\n </Button>\n )}\n </div>\n </div>\n </animated.div>\n </div>\n );\n};\n\nFilterItem.displayName = \"Filter.Item\";\n"],"names":["FilterItem","_a","collapsible","desktopCollapsible","initialExpanded","expanded","controlledExpanded","onExpandChange","minimisable","minimisedHeight","showDivider","showMobileDivider","title","addon","children","className","otherProps","__rest","mode","rootNode","useContext","FilterContext","isMobile","setExpanded","useState","getInitialExpandState","contentMinimised","setContentMinimised","itemResizeDetector","useResizeDetector","contentResizeDetector","itemAnimationStyles","useSpring","height","contentHeight","Math","min","_b","internalId","useId","contentId","titleId","minimisableContentRef","useRef","useApplyStyle","styles.tokens","minimisableContent","useEffect","isNil","_jsxs","clsx","styles.filterItemWrapper","styles.filterItemWrapperDarker","_jsx","styles.divider","styles.dividerVisible","styles.dividerMobile","styles.filterItemHeader","styles.filterItemHeaderMobile","id","styles.filterItemTitle","styles.filterItemTitleMobile","type","PopoverAddon","undefined","ClickableIcon","styles.filterItemExpandButton","focusHighlight","focusOutline","onClick","nextState","VisuallyHidden","ChevronDownIcon","styles.chevronIcon","styles.chevronIconExpanded","animated","div","styles.expandableItem","style","inert","inertValue","ref","Object","assign","styles.filterItemBody","styles.minimisableContent","styles.minimisableContentMinimisable","minimised","Button","styles.filterItemMinimiseButton","sizeType","styleType","displayName"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- "use strict";require("./filter-item.styles_cphjnj.css");exports.chevronIcon="cjime8m",exports.chevronIconExpanded="cl88d88",exports.divider="d136l108",exports.dividerMobile="d4x3x5q",exports.dividerVisible="d89ue12",exports.expandableItem="eqgs6og",exports.filterItemBody="fu0jz3r",exports.filterItemExpandButton="fe52bn7",exports.filterItemHeader="f1eimp3e",exports.filterItemHeaderMobile="f1b5woey",exports.filterItemMinimiseButton="fw516jj",exports.filterItemTitle="fxnpooo",exports.filterItemTitleMobile="f9puapc",exports.filterItemWrapper="f1afprn0",exports.filterItemWrapperDarker="fo96iku",exports.minimisableContent="m1n17l6q",exports.minimisableContentMinimisable="my7z4fl",exports.tokens={minimisableContent:{height:"--fds-internal-filter-minimisableContent-height"}};
1
+ "use strict";require("./filter-item.styles_1yixp8h.css");exports.chevronIcon="cjime8m",exports.chevronIconExpanded="cl88d88",exports.divider="d136l108",exports.dividerMobile="d4x3x5q",exports.dividerVisible="d89ue12",exports.expandableItem="eqgs6og",exports.filterItemBody="fu0jz3r",exports.filterItemExpandButton="fe52bn7",exports.filterItemHeader="f1eimp3e",exports.filterItemHeaderMobile="f1b5woey",exports.filterItemMinimiseButton="fw516jj",exports.filterItemTitle="fxnpooo",exports.filterItemTitleMobile="f9puapc",exports.filterItemWrapper="f1afprn0",exports.filterItemWrapperDarker="fo96iku",exports.minimisableContent="m1n17l6q",exports.minimisableContentMinimisable="my7z4fl",exports.tokens={minimisableContent:{height:"--fds-internal-filter-minimisableContent-height"}};
2
2
  //# sourceMappingURL=filter-item.styles.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"filter-item.styles.js","sources":["../../../src/filter/filter-item.styles.ts"],"sourcesContent":["import { css } from \"@linaria/core\";\n\nimport { Colour, Font, Motion, Spacing } from \"../theme\";\n\nexport const tokens = {\n minimisableContent: {\n height: \"--fds-internal-filter-minimisableContent-height\",\n },\n} as const;\n\n// =============================================================================\n// FILTER ITEM STYLES\n// =============================================================================\n\nexport const filterItemWrapper = css`\n background-color: ${Colour[\"bg\"]};\n`;\n\nexport const filterItemWrapperDarker = css`\n background-color: ${Colour[\"bg-strong\"]};\n`;\n\nexport const divider = css`\n display: none;\n height: 1px;\n background-color: ${Colour[\"border\"]};\n`;\n\nexport const dividerVisible = css`\n display: block;\n`;\n\nexport const dividerMobile = css`\n margin: 0 ${Spacing[\"spacing-16\"]};\n`;\n\n// =============================================================================\n// HEADER STYLES\n// =============================================================================\n\nexport const filterItemHeader = css`\n display: flex;\n align-items: center;\n\n background-color: ${Colour[\"bg\"]};\n`;\n\nexport const filterItemHeaderMobile = css`\n background-color: transparent;\n`;\n\nexport const filterItemExpandButton = css`\n margin: 0 0 0 auto;\n\n color: ${Colour[\"icon\"]};\n &:hover {\n color: ${Colour[\"icon-hover\"]};\n }\n`;\n\nexport const chevronIcon = css`\n height: ${Font.Spec[\"body-size-baseline\"]};\n width: ${Font.Spec[\"body-size-baseline\"]};\n\n transform: rotate(0deg);\n transition: transform ${Motion[\"duration-350\"]} ${Motion[\"ease-standard\"]};\n`;\n\nexport const chevronIconExpanded = css`\n transform: rotate(180deg);\n`;\n\nexport const filterItemTitle = css`\n ${Font[\"heading-xs-semibold\"]}\n color: ${Colour[\"text\"]};\n\n margin: ${Spacing[\"spacing-24\"]} 0;\n margin-left: ${Spacing[\"spacing-20\"]};\n`;\n\nexport const filterItemTitleMobile = css`\n ${Font[\"body-md-semibold\"]}\n color: ${Colour[\"text-subtle\"]};\n\n margin: ${Spacing[\"spacing-24\"]} ${Spacing[\"spacing-20\"]} 0\n ${Spacing[\"spacing-20\"]};\n`;\n\n// =============================================================================\n// CONTENT STYLES\n// =============================================================================\n\nexport const expandableItem = css`\n overflow: hidden;\n`;\n\nexport const filterItemBody = css`\n padding: ${Spacing[\"spacing-24\"]} ${Spacing[\"spacing-20\"]};\n`;\n\nexport const minimisableContent = css`\n ${tokens.minimisableContent.height}: initial;\n height: var(${tokens.minimisableContent.height});\n`;\n\nexport const minimisableContentMinimisable = css`\n overflow: hidden;\n`;\n\nexport const filterItemMinimiseButton = css`\n height: fit-content;\n padding: 0;\n margin: ${Spacing[\"spacing-16\"]} 0 0 0;\n`;\n"],"names":["minimisableContent","height"],"mappings":"kGA4DwB,sCAQQ,0BA9CZ,iCAUM,iCAJC,iCAgEA,iCAIA,yCA7CQ,mCAXN,0CAOM,4CA8DE,kCArCT,wCAQM,oCAlEJ,2CAIM,qCAkFL,iDAKW,yBArGpB,CAClBA,mBAAoB,CAChBC,OAAQ"}
1
+ {"version":3,"file":"filter-item.styles.js","sources":["../../../src/filter/filter-item.styles.ts"],"sourcesContent":["import { css } from \"@linaria/core\";\n\nimport { Colour, Font, Motion, Spacing } from \"../theme\";\n\nexport const tokens = {\n minimisableContent: {\n height: \"--fds-internal-filter-minimisableContent-height\",\n },\n} as const;\n\n// =============================================================================\n// FILTER ITEM STYLES\n// =============================================================================\n\nexport const filterItemWrapper = css`\n background-color: ${Colour[\"bg\"]};\n`;\n\nexport const filterItemWrapperDarker = css`\n background-color: ${Colour[\"bg-strong\"]};\n`;\n\nexport const divider = css`\n display: none;\n height: 1px;\n background-color: ${Colour[\"border\"]};\n`;\n\nexport const dividerVisible = css`\n display: block;\n`;\n\nexport const dividerMobile = css`\n margin: 0 ${Spacing[\"spacing-16\"]};\n`;\n\n// =============================================================================\n// HEADER STYLES\n// =============================================================================\n\nexport const filterItemHeader = css`\n display: flex;\n align-items: center;\n\n background-color: ${Colour[\"bg\"]};\n`;\n\nexport const filterItemHeaderMobile = css`\n background-color: transparent;\n`;\n\nexport const filterItemExpandButton = css`\n margin: 0 0 0 auto;\n\n color: ${Colour[\"icon\"]};\n &:hover {\n color: ${Colour[\"icon-hover\"]};\n }\n`;\n\nexport const chevronIcon = css`\n height: ${Font.Spec[\"body-size-baseline\"]};\n width: ${Font.Spec[\"body-size-baseline\"]};\n\n transform: rotate(0deg);\n transition: transform ${Motion[\"duration-350\"]} ${Motion[\"ease-standard\"]};\n`;\n\nexport const chevronIconExpanded = css`\n transform: rotate(180deg);\n`;\n\nexport const filterItemTitle = css`\n ${Font[\"heading-xs-semibold\"]}\n color: ${Colour[\"text\"]};\n\n margin: ${Spacing[\"spacing-24\"]} 0;\n margin-left: ${Spacing[\"spacing-20\"]};\n`;\n\nexport const filterItemTitleMobile = css`\n ${Font[\"body-md-semibold\"]}\n color: ${Colour[\"text-subtle\"]};\n\n margin: ${Spacing[\"spacing-24\"]} ${Spacing[\"spacing-20\"]} 0\n ${Spacing[\"spacing-20\"]};\n`;\n\n// =============================================================================\n// CONTENT STYLES\n// =============================================================================\n\nexport const expandableItem = css`\n overflow: hidden;\n`;\n\nexport const filterItemBody = css`\n padding: ${Spacing[\"spacing-24\"]} ${Spacing[\"spacing-20\"]};\n`;\n\nexport const minimisableContent = css`\n ${tokens.minimisableContent.height}: initial;\n height: var(${tokens.minimisableContent.height});\n`;\n\nexport const minimisableContentMinimisable = css`\n overflow: hidden;\n`;\n\nexport const filterItemMinimiseButton = css`\n min-height: unset;\n padding: 0;\n margin: ${Spacing[\"spacing-16\"]} 0 0 0;\n`;\n"],"names":["minimisableContent","height"],"mappings":"mGA4DwB,sCAQQ,0BA9CZ,iCAUM,iCAJC,iCAgEA,iCAIA,yCA7CQ,mCAXN,0CAOM,4CA8DE,kCArCT,wCAQM,oCAlEJ,2CAIM,qCAkFL,iDAKW,yBArGpB,CAClBA,mBAAoB,CAChBC,OAAQ"}
@@ -14,4 +14,4 @@
14
14
  .fu0jz3r{padding:var(--fds-spacing-24) var(--fds-spacing-20);}
15
15
  .m1n17l6q{--fds-internal-filter-minimisableContent-height:initial;height:var(--fds-internal-filter-minimisableContent-height);}
16
16
  .my7z4fl{overflow:hidden;}
17
- .fw516jj{height:-webkit-fit-content;height:-moz-fit-content;height:fit-content;padding:0;margin:var(--fds-spacing-16) 0 0 0;}}
17
+ .fw516jj{min-height:unset;padding:0;margin:var(--fds-spacing-16) 0 0 0;}}
@@ -1,2 +1,2 @@
1
- "use strict";require("./filter-modal.styles_qw3xlg.css");exports.filterButton="flrfycx",exports.filterClearButton="f14zog8f",exports.filterHeader="f1ijv0o9",exports.filterHeaderWithInsetTop="f50yopa",exports.filterTitle="f14huz7l",exports.filterTitleGroup="f15rygha",exports.filterToggleContent="fxpov9b",exports.floatingWrapper="fidypou",exports.mobileContainer="m19agezm",exports.mobileOverlayContainer="m11wuwo8",exports.tokens={filterHeader:{insetTop:"--fds-internal-filter-filterModalHeader-insetTop"}};
1
+ "use strict";require("./filter-modal.styles_kuth21.css");exports.filterButton="flrfycx",exports.filterClearButton="f14zog8f",exports.filterHeader="f1ijv0o9",exports.filterHeaderWithInsetTop="f50yopa",exports.filterTitle="f14huz7l",exports.filterTitleGroup="f15rygha",exports.filterToggleContent="fxpov9b",exports.floatingWrapper="fidypou",exports.mobileContainer="m19agezm",exports.mobileOverlayContainer="m11wuwo8",exports.tokens={filterHeader:{insetTop:"--fds-internal-filter-filterModalHeader-insetTop"}};
2
2
  //# sourceMappingURL=filter-modal.styles.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"filter-modal.styles.js","sources":["../../../src/filter/filter-modal.styles.ts"],"sourcesContent":["import { css } from \"@linaria/core\";\n\nimport { Colour, Font, Spacing } from \"../theme\";\n\nexport const tokens = {\n filterHeader: {\n insetTop: \"--fds-internal-filter-filterModalHeader-insetTop\",\n },\n} as const;\n\n// =============================================================================\n// CONTAINER STYLES\n// =============================================================================\n\nexport const mobileContainer = css`\n background-color: ${Colour[\"bg-strong\"]};\n height: 100%;\n width: 100%;\n display: flex;\n flex-direction: column;\n`;\n\nexport const mobileOverlayContainer = css`\n background-color: ${Colour[\"bg\"]};\n height: 100%;\n width: 100%;\n`;\n\nexport const floatingWrapper = css`\n height: 100%;\n`;\n\n// =============================================================================\n// HEADER STYLES\n// =============================================================================\n\nexport const filterHeader = css`\n display: flex;\n align-items: center;\n background-color: ${Colour[\"bg\"]};\n`;\n\nexport const filterHeaderWithInsetTop = css`\n ${tokens.filterHeader.insetTop}: initial;\n padding-top: var(${tokens.filterHeader.insetTop});\n`;\n\nexport const filterTitleGroup = css`\n flex: 1;\n display: flex;\n align-items: center;\n justify-content: center;\n gap: ${Spacing[\"spacing-8\"]};\n margin: ${Spacing[\"spacing-24\"]} 0;\n`;\n\nexport const filterTitle = css`\n ${Font[\"heading-xs-semibold\"]}\n color: ${Colour[\"text\"]};\n`;\n\nexport const filterToggleContent = css`\n display: inline-flex;\n align-items: center;\n gap: ${Spacing[\"spacing-8\"]};\n`;\n\nexport const filterClearButton = css`\n background-color: transparent;\n height: 100%;\n padding: ${Spacing[\"spacing-24\"]} ${Spacing[\"spacing-20\"]};\n`;\n\n// =============================================================================\n// COMPONENT STYLES\n// =============================================================================\n\nexport const filterButton = css`\n width: 100%;\n`;\n"],"names":["filterHeader","insetTop"],"mappings":"oGA6EyB,oCAVK,gCA/BL,4CAMY,8BAcb,oCATK,uCAcG,kCAjCJ,kCAdA,0CAQO,0BAlBb,CAClBA,aAAc,CACVC,SAAU"}
1
+ {"version":3,"file":"filter-modal.styles.js","sources":["../../../src/filter/filter-modal.styles.ts"],"sourcesContent":["import { css } from \"@linaria/core\";\n\nimport { Colour, Font, Spacing } from \"../theme\";\n\nexport const tokens = {\n filterHeader: {\n insetTop: \"--fds-internal-filter-filterModalHeader-insetTop\",\n },\n} as const;\n\n// =============================================================================\n// CONTAINER STYLES\n// =============================================================================\n\nexport const mobileContainer = css`\n background-color: ${Colour[\"bg-strong\"]};\n height: 100%;\n width: 100%;\n display: flex;\n flex-direction: column;\n`;\n\nexport const mobileOverlayContainer = css`\n background-color: ${Colour[\"bg\"]};\n height: 100%;\n width: 100%;\n`;\n\nexport const floatingWrapper = css`\n height: 100%;\n`;\n\n// =============================================================================\n// HEADER STYLES\n// =============================================================================\n\nexport const filterHeader = css`\n display: flex;\n align-items: center;\n background-color: ${Colour[\"bg\"]};\n`;\n\nexport const filterHeaderWithInsetTop = css`\n ${tokens.filterHeader.insetTop}: initial;\n padding-top: var(${tokens.filterHeader.insetTop});\n`;\n\nexport const filterTitleGroup = css`\n flex: 1;\n display: flex;\n align-items: center;\n justify-content: center;\n gap: ${Spacing[\"spacing-8\"]};\n margin: ${Spacing[\"spacing-24\"]} 0;\n`;\n\nexport const filterTitle = css`\n ${Font[\"heading-xs-semibold\"]}\n color: ${Colour[\"text\"]};\n`;\n\nexport const filterToggleContent = css`\n display: inline-flex;\n align-items: center;\n gap: ${Spacing[\"spacing-8\"]};\n`;\n\nexport const filterClearButton = css`\n background-color: transparent;\n min-height: unset;\n padding: ${Spacing[\"spacing-24\"]} ${Spacing[\"spacing-20\"]};\n`;\n\n// =============================================================================\n// COMPONENT STYLES\n// =============================================================================\n\nexport const filterButton = css`\n width: 100%;\n`;\n"],"names":["filterHeader","insetTop"],"mappings":"oGA6EyB,oCAVK,gCA/BL,4CAMY,8BAcb,oCATK,uCAcG,kCAjCJ,kCAdA,0CAQO,0BAlBb,CAClBA,aAAc,CACVC,SAAU"}
@@ -6,5 +6,5 @@
6
6
  .f15rygha{-webkit-flex:1;-ms-flex:1;flex:1;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;-webkit-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;justify-content:center;gap:var(--fds-spacing-8);margin:var(--fds-spacing-24) 0;}
7
7
  .f14huz7l{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);}
8
8
  .fxpov9b{display:-webkit-inline-box;display:-webkit-inline-flex;display:-ms-inline-flexbox;display:inline-flex;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;gap:var(--fds-spacing-8);}
9
- .f14zog8f{background-color:transparent;height:100%;padding:var(--fds-spacing-24) var(--fds-spacing-20);}
9
+ .f14zog8f{background-color:transparent;min-height:unset;padding:var(--fds-spacing-24) var(--fds-spacing-20);}
10
10
  .flrfycx{width:100%;}}
@@ -1,2 +1,2 @@
1
- "use strict";require("./filter-sidebar.styles_1otwpjl.css");exports.desktopContainer="d1a2pl71",exports.filterClearButton="f122t6n9",exports.filterHeader="fq9unar",exports.filterTitle="f1i4s84l",exports.filterTitleGroup="fjfy2r5";
1
+ "use strict";require("./filter-sidebar.styles_rbfq4f.css");exports.desktopContainer="d1a2pl71",exports.filterClearButton="f122t6n9",exports.filterHeader="fq9unar",exports.filterTitle="f1i4s84l",exports.filterTitleGroup="fjfy2r5";
2
2
  //# sourceMappingURL=filter-sidebar.styles.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"filter-sidebar.styles.js","sources":["../../../src/filter/filter-sidebar.styles.ts"],"sourcesContent":["import { css } from \"@linaria/core\";\n\nimport { Border, Colour, Font, Radius, Spacing } from \"../theme\";\n\n// =============================================================================\n// CONTAINER STYLES\n// =============================================================================\n\nexport const desktopContainer = css`\n background-color: ${Colour[\"bg\"]};\n border: ${Border[\"width-010\"]} ${Border[\"solid\"]} ${Colour[\"border\"]};\n border-radius: ${Radius[\"md\"]};\n overflow: hidden;\n width: 100%;\n`;\n\n// =============================================================================\n// HEADER STYLES\n// =============================================================================\n\nexport const filterHeader = css`\n display: flex;\n align-items: center;\n\n background-color: ${Colour[\"bg\"]};\n color: ${Colour[\"text\"]};\n`;\n\nexport const filterTitleGroup = css`\n flex: 1;\n display: flex;\n align-items: center;\n justify-content: flex-start;\n gap: ${Spacing[\"spacing-8\"]};\n margin: ${Spacing[\"spacing-24\"]} 0 ${Spacing[\"spacing-24\"]}\n ${Spacing[\"spacing-20\"]};\n`;\n\nexport const filterTitle = css`\n ${Font[\"heading-xs-semibold\"]}\n`;\n\nexport const filterClearButton = css`\n background-color: transparent;\n padding-right: ${Spacing[\"spacing-20\"]};\n padding-left: ${Spacing[\"spacing-20\"]};\n height: 100%;\n`;\n"],"names":[],"mappings":"2GAQ6B,qCAkCC,gCAtBL,8BAkBD,oCAVK"}
1
+ {"version":3,"file":"filter-sidebar.styles.js","sources":["../../../src/filter/filter-sidebar.styles.ts"],"sourcesContent":["import { css } from \"@linaria/core\";\n\nimport { Border, Colour, Font, Radius, Spacing } from \"../theme\";\n\n// =============================================================================\n// CONTAINER STYLES\n// =============================================================================\n\nexport const desktopContainer = css`\n background-color: ${Colour[\"bg\"]};\n border: ${Border[\"width-010\"]} ${Border[\"solid\"]} ${Colour[\"border\"]};\n border-radius: ${Radius[\"md\"]};\n overflow: hidden;\n width: 100%;\n`;\n\n// =============================================================================\n// HEADER STYLES\n// =============================================================================\n\nexport const filterHeader = css`\n display: flex;\n align-items: center;\n\n background-color: ${Colour[\"bg\"]};\n color: ${Colour[\"text\"]};\n`;\n\nexport const filterTitleGroup = css`\n flex: 1;\n display: flex;\n align-items: center;\n justify-content: flex-start;\n gap: ${Spacing[\"spacing-8\"]};\n margin: ${Spacing[\"spacing-24\"]} 0 ${Spacing[\"spacing-24\"]}\n ${Spacing[\"spacing-20\"]};\n`;\n\nexport const filterTitle = css`\n ${Font[\"heading-xs-semibold\"]}\n`;\n\nexport const filterClearButton = css`\n background-color: transparent;\n padding-right: ${Spacing[\"spacing-20\"]};\n padding-left: ${Spacing[\"spacing-20\"]};\n min-height: unset;\n`;\n"],"names":[],"mappings":"0GAQ6B,qCAkCC,gCAtBL,8BAkBD,oCAVK"}