@lifesg/react-design-system 4.0.0-alpha.6 → 4.0.0-alpha.7

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 (684) hide show
  1. package/accordion/accordion.js.map +1 -1
  2. package/alert/alert.js.map +1 -1
  3. package/alert/types.d.ts +2 -0
  4. package/animations/loading-dots/loading-dots.d.ts +5 -2
  5. package/animations/loading-dots/loading-dots.js.map +1 -1
  6. package/animations/loading-dots-spinner/loading-dots-spinner.d.ts +3 -0
  7. package/animations/loading-dots-spinner/loading-dots-spinner.js.map +1 -1
  8. package/animations/loading-dots-spinner/lottie-animation.d.ts +2 -2
  9. package/animations/loading-dots-spinner/lottie-animation.js.map +1 -1
  10. package/animations/loading-spinner/loading-spinner.d.ts +5 -2
  11. package/animations/loading-spinner/loading-spinner.js.map +1 -1
  12. package/animations/themed-loading-spinner/themed-loading-spinner.d.ts +5 -2
  13. package/animations/themed-loading-spinner/themed-loading-spinner.js.map +1 -1
  14. package/animations/types.d.ts +13 -6
  15. package/avatar/avatar.js.map +1 -1
  16. package/badge/badge.js.map +1 -1
  17. package/badge/types.d.ts +13 -2
  18. package/box-container/box-container.js.map +1 -1
  19. package/box-container/types.d.ts +2 -0
  20. package/breadcrumb/breadcrumb.js.map +1 -1
  21. package/breadcrumb/types.d.ts +7 -2
  22. package/button/button.js.map +1 -1
  23. package/button/types.d.ts +5 -0
  24. package/calendar/calendar.js.map +1 -1
  25. package/calendar/types.d.ts +3 -3
  26. package/card/card.js.map +1 -1
  27. package/checkbox/checkbox.js.map +1 -1
  28. package/checkbox/types.d.ts +4 -0
  29. package/cjs/accordion/accordion.js.map +1 -1
  30. package/cjs/alert/alert.js.map +1 -1
  31. package/cjs/animations/loading-dots/loading-dots.js.map +1 -1
  32. package/cjs/animations/loading-dots-spinner/loading-dots-spinner.js.map +1 -1
  33. package/cjs/animations/loading-dots-spinner/lottie-animation.js.map +1 -1
  34. package/cjs/animations/loading-spinner/loading-spinner.js.map +1 -1
  35. package/cjs/animations/themed-loading-spinner/themed-loading-spinner.js.map +1 -1
  36. package/cjs/avatar/avatar.js.map +1 -1
  37. package/cjs/badge/badge.js.map +1 -1
  38. package/cjs/box-container/box-container.js.map +1 -1
  39. package/cjs/breadcrumb/breadcrumb.js.map +1 -1
  40. package/cjs/button/button.js.map +1 -1
  41. package/cjs/calendar/calendar.js.map +1 -1
  42. package/cjs/card/card.js.map +1 -1
  43. package/cjs/checkbox/checkbox.js.map +1 -1
  44. package/cjs/countdown-timer/countdown-timer.js.map +1 -1
  45. package/cjs/dashed-border/dashed-border.js.map +1 -1
  46. package/cjs/data-table/data-table.js.map +1 -1
  47. package/cjs/date-input/date-input.js.map +1 -1
  48. package/cjs/date-navigator/date-navigator.js.map +1 -1
  49. package/cjs/date-range-input/date-range-input.js.map +1 -1
  50. package/cjs/divider/divider.js.map +1 -1
  51. package/cjs/drawer/drawer.js.map +1 -1
  52. package/cjs/e-signature/e-signature.js.map +1 -1
  53. package/cjs/error-display/error-display.js.map +1 -1
  54. package/cjs/feedback-rating/feedback-rating.js.map +1 -1
  55. package/cjs/file-download/file-download.js.map +1 -1
  56. package/cjs/file-upload/file-item-edit.js.map +1 -1
  57. package/cjs/file-upload/file-list/file-list.js.map +1 -1
  58. package/cjs/file-upload/file-list-item/file-list-item.js.map +1 -1
  59. package/cjs/file-upload/file-list-item/file-list-item.styles.js +1 -1
  60. package/cjs/file-upload/file-list-item/file-list-item.styles.js.map +1 -1
  61. package/cjs/file-upload/file-list-item/{file-list-item.styles_o8000f.css → file-list-item.styles_kgtfke.css} +1 -1
  62. package/cjs/file-upload/file-upload.js.map +1 -1
  63. package/cjs/filter/addons/filter-item-checkbox-helpers.js.map +1 -1
  64. package/cjs/filter/addons/filter-item-checkbox.js.map +1 -1
  65. package/cjs/filter/filter-item.js +1 -1
  66. package/cjs/filter/filter-item.js.map +1 -1
  67. package/cjs/filter/filter.js.map +1 -1
  68. package/cjs/footer/footer.js.map +1 -1
  69. package/cjs/form/form-custom-field/form-custom-field.js +2 -0
  70. package/cjs/form/form-custom-field/form-custom-field.js.map +1 -0
  71. package/cjs/form/form-date-input/form-date-input.js +2 -0
  72. package/cjs/form/form-date-input/form-date-input.js.map +1 -0
  73. package/cjs/form/form-date-range-input/form-date-range-input.js +2 -0
  74. package/cjs/form/form-date-range-input/form-date-range-input.js.map +1 -0
  75. package/cjs/form/form-e-signature/form-e-signature.js +2 -0
  76. package/cjs/form/form-e-signature/form-e-signature.js.map +1 -0
  77. package/cjs/form/form-histogram-slider/form-histogram-slider.js +2 -0
  78. package/cjs/form/form-histogram-slider/form-histogram-slider.js.map +1 -0
  79. package/cjs/form/form-input/form-input.js +2 -0
  80. package/cjs/form/form-input/form-input.js.map +1 -0
  81. package/cjs/form/form-input-group/form-input-group.js +2 -0
  82. package/cjs/form/form-input-group/form-input-group.js.map +1 -0
  83. package/cjs/form/form-label/form-label-addon.js +2 -0
  84. package/cjs/form/form-label/form-label-addon.js.map +1 -0
  85. package/cjs/form/form-label/form-label-addon.styles.js +2 -0
  86. package/cjs/form/form-label/form-label-addon.styles.js.map +1 -0
  87. package/cjs/form/form-label/form-label-addon.styles_aztasj.css +1 -0
  88. package/cjs/form/form-label/form-label.js +2 -0
  89. package/cjs/form/form-label/form-label.js.map +1 -0
  90. package/cjs/form/form-label/form-label.styles.js +2 -0
  91. package/cjs/form/form-label/form-label.styles.js.map +1 -0
  92. package/cjs/form/form-label/form-label.styles_180zf7j.css +6 -0
  93. package/cjs/form/form-masked-input/form-masked-input.js +2 -0
  94. package/cjs/form/form-masked-input/form-masked-input.js.map +1 -0
  95. package/cjs/form/form-multi-select/form-multi-select.js +2 -0
  96. package/cjs/form/form-multi-select/form-multi-select.js.map +1 -0
  97. package/cjs/form/form-nested-multi-select/form-nested-multi-select.js +2 -0
  98. package/cjs/form/form-nested-multi-select/form-nested-multi-select.js.map +1 -0
  99. package/cjs/form/form-nested-select/form-nested-select.js +2 -0
  100. package/cjs/form/form-nested-select/form-nested-select.js.map +1 -0
  101. package/cjs/form/form-otp-verification/form-otp-verification.js +2 -0
  102. package/cjs/form/form-otp-verification/form-otp-verification.js.map +1 -0
  103. package/cjs/form/form-phone-number-input/form-phone-number-input.js +2 -0
  104. package/cjs/form/form-phone-number-input/form-phone-number-input.js.map +1 -0
  105. package/cjs/form/form-predictive-text-input/form-predictive-text-input.js +2 -0
  106. package/cjs/form/form-predictive-text-input/form-predictive-text-input.js.map +1 -0
  107. package/cjs/form/form-range-select/form-range-select.js +2 -0
  108. package/cjs/form/form-range-select/form-range-select.js.map +1 -0
  109. package/cjs/form/form-range-slider/form-range-slider.js +2 -0
  110. package/cjs/form/form-range-slider/form-range-slider.js.map +1 -0
  111. package/cjs/form/form-select/form-select.js +2 -0
  112. package/cjs/form/form-select/form-select.js.map +1 -0
  113. package/cjs/form/form-select-histogram/form-select-histogram.js +2 -0
  114. package/cjs/form/form-select-histogram/form-select-histogram.js.map +1 -0
  115. package/cjs/form/form-slider/form-slider.js +2 -0
  116. package/cjs/form/form-slider/form-slider.js.map +1 -0
  117. package/cjs/form/form-textarea/form-textarea.js +2 -0
  118. package/cjs/form/form-textarea/form-textarea.js.map +1 -0
  119. package/cjs/form/form-textarea/form-textarea.styles.js +2 -0
  120. package/cjs/form/form-textarea/form-textarea.styles.js.map +1 -0
  121. package/cjs/form/form-textarea/form-textarea.styles_1kneyif.css +3 -0
  122. package/cjs/form/form-time-range-picker/form-time-range-picker.js +2 -0
  123. package/cjs/form/form-time-range-picker/form-time-range-picker.js.map +1 -0
  124. package/cjs/form/form-timepicker/form-timepicker.js +2 -0
  125. package/cjs/form/form-timepicker/form-timepicker.js.map +1 -0
  126. package/cjs/form/form-unit-number-input/form-unit-number-input.js +2 -0
  127. package/cjs/form/form-unit-number-input/form-unit-number-input.js.map +1 -0
  128. package/cjs/form/form-wrapper.js +1 -1
  129. package/cjs/form/form-wrapper.js.map +1 -1
  130. package/cjs/form/index.js +1 -1
  131. package/cjs/form/index.js.map +1 -1
  132. package/cjs/fullscreen-image-carousel/fullscreen-image-carousel.js.map +1 -1
  133. package/cjs/histogram-slider/histogram-slider.js.map +1 -1
  134. package/cjs/image-button/image-button.js.map +1 -1
  135. package/cjs/input/input.js.map +1 -1
  136. package/cjs/input-group/input-group.js.map +1 -1
  137. package/cjs/input-multi-select/input-multi-select.js.map +1 -1
  138. package/cjs/input-nested-multi-select/input-nested-multi-select.js.map +1 -1
  139. package/cjs/input-nested-select/input-nested-select.js.map +1 -1
  140. package/cjs/input-range-select/input-range-select.js.map +1 -1
  141. package/cjs/input-range-slider/input-range-slider.js.map +1 -1
  142. package/cjs/input-select/input-select.js.map +1 -1
  143. package/cjs/input-slider/input-slider.js.map +1 -1
  144. package/cjs/input-textarea/textarea.js.map +1 -1
  145. package/cjs/input-textarea/textarea.styles.js +1 -1
  146. package/cjs/input-textarea/textarea.styles.js.map +1 -1
  147. package/cjs/input-textarea/{textarea.styles_22z4n3.css → textarea.styles_q77m5x.css} +1 -1
  148. package/cjs/language-switcher/language-switcher.js.map +1 -1
  149. package/cjs/layout/index.js.map +1 -1
  150. package/cjs/link-list/components/common.js.map +1 -1
  151. package/cjs/link-list/components/link-list-eager.js.map +1 -1
  152. package/cjs/link-list/components/link-list-lazy.js.map +1 -1
  153. package/cjs/link-list/link-list.js.map +1 -1
  154. package/cjs/local-nav/local-nav-dropdown/local-nav-dropdown.js.map +1 -1
  155. package/cjs/local-nav/local-nav-menu/local-nav-menu.js.map +1 -1
  156. package/cjs/markup/markup.js.map +1 -1
  157. package/cjs/masked-input/masked-input.js.map +1 -1
  158. package/cjs/masthead/masthead.js.map +1 -1
  159. package/cjs/menu/menu.js.map +1 -1
  160. package/cjs/modal/index.js.map +1 -1
  161. package/cjs/modal-v2/modal-v2.js.map +1 -1
  162. package/cjs/navbar/navbar.js.map +1 -1
  163. package/cjs/notification-banner/notification-banner.js.map +1 -1
  164. package/cjs/otp-input/otp-input.js +1 -1
  165. package/cjs/otp-input/otp-input.js.map +1 -1
  166. package/cjs/otp-verification/contact-input-section.js +1 -1
  167. package/cjs/otp-verification/contact-input-section.js.map +1 -1
  168. package/cjs/otp-verification/otp-verification.js.map +1 -1
  169. package/cjs/otp-verification/verification-section.js +1 -1
  170. package/cjs/otp-verification/verification-section.js.map +1 -1
  171. package/cjs/overlay/overlay.js.map +1 -1
  172. package/cjs/pagination/pagination.js.map +1 -1
  173. package/cjs/phone-number-input/phone-number-input.js.map +1 -1
  174. package/cjs/pill/pill.js.map +1 -1
  175. package/cjs/popover/popover-inline/popover-inline.js.map +1 -1
  176. package/cjs/popover/popover.js.map +1 -1
  177. package/cjs/predictive-text-input/predictive-text-input.js +1 -1
  178. package/cjs/predictive-text-input/predictive-text-input.js.map +1 -1
  179. package/cjs/progress-indicator/progress-indicator.js.map +1 -1
  180. package/cjs/radio-button/radio-button.js.map +1 -1
  181. package/cjs/schedule/schedule.js.map +1 -1
  182. package/cjs/select-histogram/select-histogram.js.map +1 -1
  183. package/cjs/shared/dropdown-list/dropdown-list.js +1 -1
  184. package/cjs/shared/dropdown-list/dropdown-list.js.map +1 -1
  185. package/cjs/shared/dropdown-wrapper/element-with-dropdown.js +1 -1
  186. package/cjs/shared/dropdown-wrapper/element-with-dropdown.js.map +1 -1
  187. package/cjs/sidenav/sidenav.js.map +1 -1
  188. package/cjs/singpass-button/singpass-button.js.map +1 -1
  189. package/cjs/smart-app-banner/smart-app-banner.js.map +1 -1
  190. package/cjs/tab/tab.js.map +1 -1
  191. package/cjs/table/table.js.map +1 -1
  192. package/cjs/tag/tag.js.map +1 -1
  193. package/cjs/text-list/index.js.map +1 -1
  194. package/cjs/theme/theme-provider/hooks.js.map +1 -1
  195. package/cjs/theme/theme-provider/index.js.map +1 -1
  196. package/cjs/theme/tokens/border.js.map +1 -1
  197. package/cjs/theme/tokens/breakpoint.js.map +1 -1
  198. package/cjs/theme/tokens/colour.js.map +1 -1
  199. package/cjs/theme/tokens/component.js.map +1 -1
  200. package/cjs/theme/tokens/font.js.map +1 -1
  201. package/cjs/theme/tokens/media-query.js.map +1 -1
  202. package/cjs/theme/tokens/motion.js.map +1 -1
  203. package/cjs/theme/tokens/radius.js.map +1 -1
  204. package/cjs/theme/tokens/shadow.js.map +1 -1
  205. package/cjs/theme/tokens/spacing.js.map +1 -1
  206. package/cjs/theme/utils/use-apply-styles.js.map +1 -1
  207. package/cjs/theme/utils/use-design-token.js.map +1 -1
  208. package/cjs/theme/utils/use-media-query.js.map +1 -1
  209. package/cjs/time-range-picker/combobox-picker/combobox-picker.js +1 -1
  210. package/cjs/time-range-picker/combobox-picker/combobox-picker.js.map +1 -1
  211. package/cjs/time-range-picker/time-range-picker.js.map +1 -1
  212. package/cjs/time-slot-bar/time-slot-bar.js.map +1 -1
  213. package/cjs/time-slot-bar-week/time-slot-bar-week.js.map +1 -1
  214. package/cjs/time-slot-week-view/time-slot-week-view.js.map +1 -1
  215. package/cjs/timeline/timeline.js.map +1 -1
  216. package/cjs/timepicker/timepicker.js.map +1 -1
  217. package/cjs/timetable/timetable.js.map +1 -1
  218. package/cjs/toast/toast.js.map +1 -1
  219. package/cjs/toggle/toggle.js.map +1 -1
  220. package/cjs/typography/index.js.map +1 -1
  221. package/cjs/uneditable-section/index.js.map +1 -1
  222. package/cjs/uneditable-section/section-item.js +1 -1
  223. package/cjs/uneditable-section/section-item.js.map +1 -1
  224. package/cjs/unit-number/unit-number-input.js.map +1 -1
  225. package/countdown-timer/countdown-timer.js.map +1 -1
  226. package/countdown-timer/types.d.ts +3 -3
  227. package/dashed-border/dashed-border.js.map +1 -1
  228. package/data-table/data-table.js.map +1 -1
  229. package/date-input/date-input.js.map +1 -1
  230. package/date-input/types.d.ts +1 -1
  231. package/date-navigator/date-navigator.js.map +1 -1
  232. package/date-navigator/types.d.ts +1 -1
  233. package/date-range-input/date-range-input.js.map +1 -1
  234. package/date-range-input/types.d.ts +1 -1
  235. package/divider/divider.js.map +1 -1
  236. package/divider/types.d.ts +1 -1
  237. package/docs/component-catalog.json +644 -0
  238. package/drawer/drawer.js.map +1 -1
  239. package/e-signature/e-signature.js.map +1 -1
  240. package/error-display/error-display.js.map +1 -1
  241. package/feedback-rating/feedback-rating.js.map +1 -1
  242. package/file-download/file-download.js.map +1 -1
  243. package/file-download/types.d.ts +6 -1
  244. package/file-upload/file-item-edit.d.ts +1 -1
  245. package/file-upload/file-item-edit.js.map +1 -1
  246. package/file-upload/file-list/file-list.d.ts +1 -1
  247. package/file-upload/file-list/file-list.js.map +1 -1
  248. package/file-upload/file-list-item/file-list-item.d.ts +1 -1
  249. package/file-upload/file-list-item/file-list-item.js.map +1 -1
  250. package/file-upload/file-list-item/file-list-item.styles.js +1 -1
  251. package/file-upload/file-list-item/file-list-item.styles.js.map +1 -1
  252. package/file-upload/file-list-item/{file-list-item.styles_o8000f.css → file-list-item.styles_kgtfke.css} +1 -1
  253. package/file-upload/file-upload.js.map +1 -1
  254. package/file-upload/types.d.ts +6 -2
  255. package/filter/addons/filter-item-checkbox-helpers.d.ts +2 -2
  256. package/filter/addons/filter-item-checkbox-helpers.js.map +1 -1
  257. package/filter/addons/filter-item-checkbox.d.ts +1 -1
  258. package/filter/addons/filter-item-checkbox.js.map +1 -1
  259. package/filter/addons/internal-types.d.ts +12 -0
  260. package/filter/addons/types.d.ts +60 -9
  261. package/filter/filter-item.js +1 -1
  262. package/filter/filter-item.js.map +1 -1
  263. package/filter/filter.d.ts +1 -1
  264. package/filter/filter.js.map +1 -1
  265. package/filter/index.d.ts +1 -0
  266. package/filter/types.d.ts +31 -63
  267. package/footer/footer.js.map +1 -1
  268. package/form/form-custom-field/form-custom-field.js +2 -0
  269. package/form/form-custom-field/form-custom-field.js.map +1 -0
  270. package/form/form-custom-field/index.d.ts +2 -0
  271. package/form/form-custom-field/types.d.ts +7 -0
  272. package/form/form-date-input/form-date-input.js +2 -0
  273. package/form/form-date-input/form-date-input.js.map +1 -0
  274. package/form/form-date-input/index.d.ts +2 -0
  275. package/form/form-date-input/types.d.ts +8 -0
  276. package/form/form-date-range-input/form-date-range-input.js +2 -0
  277. package/form/form-date-range-input/form-date-range-input.js.map +1 -0
  278. package/form/form-date-range-input/index.d.ts +2 -0
  279. package/form/form-date-range-input/types.d.ts +8 -0
  280. package/form/form-e-signature/form-e-signature.js +2 -0
  281. package/form/form-e-signature/form-e-signature.js.map +1 -0
  282. package/form/form-e-signature/index.d.ts +2 -0
  283. package/form/form-e-signature/types.d.ts +8 -0
  284. package/form/form-histogram-slider/form-histogram-slider.js +2 -0
  285. package/form/form-histogram-slider/form-histogram-slider.js.map +1 -0
  286. package/form/form-histogram-slider/index.d.ts +2 -0
  287. package/form/form-histogram-slider/types.d.ts +8 -0
  288. package/form/form-input/form-input.js +2 -0
  289. package/form/form-input/form-input.js.map +1 -0
  290. package/form/form-input/index.d.ts +2 -0
  291. package/form/form-input/types.d.ts +8 -0
  292. package/form/form-input-group/form-input-group.js +2 -0
  293. package/form/form-input-group/form-input-group.js.map +1 -0
  294. package/form/form-input-group/index.d.ts +2 -0
  295. package/form/form-input-group/types.d.ts +10 -0
  296. package/form/form-label/form-label-addon.js +2 -0
  297. package/form/form-label/form-label-addon.js.map +1 -0
  298. package/form/form-label/form-label-addon.styles.js +2 -0
  299. package/form/form-label/form-label-addon.styles.js.map +1 -0
  300. package/form/form-label/form-label-addon.styles_aztasj.css +1 -0
  301. package/form/form-label/form-label.js +2 -0
  302. package/form/form-label/form-label.js.map +1 -0
  303. package/form/form-label/form-label.styles.js +2 -0
  304. package/form/form-label/form-label.styles.js.map +1 -0
  305. package/form/form-label/form-label.styles_180zf7j.css +6 -0
  306. package/form/form-label/index.d.ts +2 -0
  307. package/form/form-label/types.d.ts +39 -0
  308. package/form/form-masked-input/form-masked-input.js +2 -0
  309. package/form/form-masked-input/form-masked-input.js.map +1 -0
  310. package/form/form-masked-input/index.d.ts +2 -0
  311. package/form/form-masked-input/types.d.ts +8 -0
  312. package/form/form-multi-select/form-multi-select.js +2 -0
  313. package/form/form-multi-select/form-multi-select.js.map +1 -0
  314. package/form/form-multi-select/index.d.ts +2 -0
  315. package/form/form-multi-select/types.d.ts +10 -0
  316. package/form/form-nested-multi-select/form-nested-multi-select.js +2 -0
  317. package/form/form-nested-multi-select/form-nested-multi-select.js.map +1 -0
  318. package/form/form-nested-multi-select/index.d.ts +2 -0
  319. package/form/form-nested-multi-select/types.d.ts +11 -0
  320. package/form/form-nested-select/form-nested-select.js +2 -0
  321. package/form/form-nested-select/form-nested-select.js.map +1 -0
  322. package/form/form-nested-select/index.d.ts +2 -0
  323. package/form/form-nested-select/types.d.ts +11 -0
  324. package/form/{form-otp-verification.d.ts → form-otp-verification/form-otp-verification.d.ts} +1 -1
  325. package/form/form-otp-verification/form-otp-verification.js +2 -0
  326. package/form/form-otp-verification/form-otp-verification.js.map +1 -0
  327. package/form/form-otp-verification/index.d.ts +2 -0
  328. package/form/form-otp-verification/types.d.ts +1 -0
  329. package/form/form-phone-number-input/form-phone-number-input.js +2 -0
  330. package/form/form-phone-number-input/form-phone-number-input.js.map +1 -0
  331. package/form/form-phone-number-input/index.d.ts +2 -0
  332. package/form/form-phone-number-input/types.d.ts +8 -0
  333. package/form/form-predictive-text-input/form-predictive-text-input.js +2 -0
  334. package/form/form-predictive-text-input/form-predictive-text-input.js.map +1 -0
  335. package/form/form-predictive-text-input/index.d.ts +2 -0
  336. package/form/form-predictive-text-input/types.d.ts +10 -0
  337. package/form/form-range-select/form-range-select.js +2 -0
  338. package/form/form-range-select/form-range-select.js.map +1 -0
  339. package/form/form-range-select/index.d.ts +2 -0
  340. package/form/form-range-select/types.d.ts +10 -0
  341. package/form/form-range-slider/form-range-slider.js +2 -0
  342. package/form/form-range-slider/form-range-slider.js.map +1 -0
  343. package/form/form-range-slider/index.d.ts +2 -0
  344. package/form/form-range-slider/types.d.ts +8 -0
  345. package/form/form-select/form-select.js +2 -0
  346. package/form/form-select/form-select.js.map +1 -0
  347. package/form/form-select/index.d.ts +2 -0
  348. package/form/form-select/types.d.ts +10 -0
  349. package/form/form-select-histogram/form-select-histogram.js +2 -0
  350. package/form/form-select-histogram/form-select-histogram.js.map +1 -0
  351. package/form/form-select-histogram/index.d.ts +2 -0
  352. package/form/form-select-histogram/types.d.ts +8 -0
  353. package/form/form-slider/form-slider.js +2 -0
  354. package/form/form-slider/form-slider.js.map +1 -0
  355. package/form/form-slider/index.d.ts +2 -0
  356. package/form/form-slider/types.d.ts +8 -0
  357. package/form/form-textarea/form-textarea.js +2 -0
  358. package/form/form-textarea/form-textarea.js.map +1 -0
  359. package/form/form-textarea/form-textarea.styles.js +2 -0
  360. package/form/form-textarea/form-textarea.styles.js.map +1 -0
  361. package/form/form-textarea/form-textarea.styles_1kneyif.css +3 -0
  362. package/form/form-textarea/index.d.ts +2 -0
  363. package/form/form-textarea/types.d.ts +8 -0
  364. package/form/form-time-range-picker/form-time-range-picker.js +2 -0
  365. package/form/form-time-range-picker/form-time-range-picker.js.map +1 -0
  366. package/form/form-time-range-picker/index.d.ts +2 -0
  367. package/form/form-time-range-picker/types.d.ts +8 -0
  368. package/form/form-timepicker/form-timepicker.js +2 -0
  369. package/form/form-timepicker/form-timepicker.js.map +1 -0
  370. package/form/form-timepicker/index.d.ts +2 -0
  371. package/form/form-timepicker/types.d.ts +8 -0
  372. package/form/form-unit-number-input/form-unit-number-input.js +2 -0
  373. package/form/form-unit-number-input/form-unit-number-input.js.map +1 -0
  374. package/form/form-unit-number-input/index.d.ts +2 -0
  375. package/form/form-unit-number-input/types.d.ts +8 -0
  376. package/form/form-wrapper.js +1 -1
  377. package/form/form-wrapper.js.map +1 -1
  378. package/form/index.d.ts +47 -24
  379. package/form/index.js +1 -1
  380. package/form/index.js.map +1 -1
  381. package/form/types.d.ts +1 -208
  382. package/fullscreen-image-carousel/fullscreen-image-carousel.js.map +1 -1
  383. package/histogram-slider/histogram-slider.js.map +1 -1
  384. package/image-button/image-button.js.map +1 -1
  385. package/input/input.js.map +1 -1
  386. package/input-group/input-group.js.map +1 -1
  387. package/input-group/types.d.ts +1 -1
  388. package/input-multi-select/input-multi-select.js.map +1 -1
  389. package/input-multi-select/types.d.ts +1 -1
  390. package/input-nested-multi-select/input-nested-multi-select.js.map +1 -1
  391. package/input-nested-select/input-nested-select.js.map +1 -1
  392. package/input-nested-select/types.d.ts +1 -1
  393. package/input-range-select/input-range-select.js.map +1 -1
  394. package/input-range-select/types.d.ts +1 -1
  395. package/input-range-slider/input-range-slider.js.map +1 -1
  396. package/input-select/input-select.js.map +1 -1
  397. package/input-select/types.d.ts +1 -1
  398. package/input-slider/input-slider.js.map +1 -1
  399. package/input-slider/types.d.ts +1 -1
  400. package/input-textarea/textarea.js.map +1 -1
  401. package/input-textarea/textarea.styles.js +1 -1
  402. package/input-textarea/textarea.styles.js.map +1 -1
  403. package/input-textarea/{textarea.styles_22z4n3.css → textarea.styles_q77m5x.css} +1 -1
  404. package/language-switcher/language-switcher.js.map +1 -1
  405. package/layout/index.js.map +1 -1
  406. package/link-list/components/common.d.ts +1 -1
  407. package/link-list/components/common.js.map +1 -1
  408. package/link-list/components/link-list-eager.d.ts +2 -2
  409. package/link-list/components/link-list-eager.js.map +1 -1
  410. package/link-list/components/link-list-lazy.d.ts +2 -2
  411. package/link-list/components/link-list-lazy.js.map +1 -1
  412. package/link-list/link-list.js.map +1 -1
  413. package/link-list/types.d.ts +89 -3
  414. package/local-nav/local-nav-dropdown/local-nav-dropdown.js.map +1 -1
  415. package/local-nav/local-nav-menu/local-nav-menu.js.map +1 -1
  416. package/markup/markup.js.map +1 -1
  417. package/masked-input/masked-input.js.map +1 -1
  418. package/masthead/masthead.js.map +1 -1
  419. package/menu/menu.js.map +1 -1
  420. package/menu/types.d.ts +17 -1
  421. package/modal/index.js.map +1 -1
  422. package/modal/types.d.ts +3 -1
  423. package/modal-v2/modal-v2.js.map +1 -1
  424. package/modal-v2/types.d.ts +17 -0
  425. package/navbar/navbar.js.map +1 -1
  426. package/navbar/types.d.ts +1 -0
  427. package/notification-banner/notification-banner.js.map +1 -1
  428. package/otp-input/otp-input.js +1 -1
  429. package/otp-input/otp-input.js.map +1 -1
  430. package/otp-input/types.d.ts +14 -9
  431. package/otp-verification/contact-input-section.js +1 -1
  432. package/otp-verification/contact-input-section.js.map +1 -1
  433. package/otp-verification/otp-verification.js.map +1 -1
  434. package/otp-verification/verification-section.js +1 -1
  435. package/otp-verification/verification-section.js.map +1 -1
  436. package/overlay/overlay.js.map +1 -1
  437. package/package.json +1 -1
  438. package/pagination/pagination.js.map +1 -1
  439. package/phone-number-input/phone-number-input.js.map +1 -1
  440. package/pill/pill.js.map +1 -1
  441. package/popover/popover-inline/index.d.ts +1 -0
  442. package/popover/popover-inline/popover-inline.d.ts +1 -1
  443. package/popover/popover-inline/popover-inline.js.map +1 -1
  444. package/popover/popover-inline/types.d.ts +36 -0
  445. package/popover/popover.js.map +1 -1
  446. package/popover/types.d.ts +2 -35
  447. package/predictive-text-input/predictive-text-input.js +1 -1
  448. package/predictive-text-input/predictive-text-input.js.map +1 -1
  449. package/predictive-text-input/types.d.ts +1 -1
  450. package/progress-indicator/progress-indicator.js.map +1 -1
  451. package/radio-button/radio-button.js.map +1 -1
  452. package/radio-button/types.d.ts +3 -0
  453. package/schedule/schedule.js.map +1 -1
  454. package/select-histogram/select-histogram.js.map +1 -1
  455. package/select-histogram/types.d.ts +1 -1
  456. package/shared/dropdown-list/dropdown-list.js +1 -1
  457. package/shared/dropdown-list/dropdown-list.js.map +1 -1
  458. package/shared/dropdown-wrapper/element-with-dropdown.d.ts +5 -4
  459. package/shared/dropdown-wrapper/element-with-dropdown.js +1 -1
  460. package/shared/dropdown-wrapper/element-with-dropdown.js.map +1 -1
  461. package/sidenav/sidenav.js.map +1 -1
  462. package/sidenav/types.d.ts +1 -0
  463. package/singpass-button/singpass-button.js.map +1 -1
  464. package/smart-app-banner/smart-app-banner.js.map +1 -1
  465. package/smart-app-banner/types.d.ts +2 -0
  466. package/tab/tab.js.map +1 -1
  467. package/table/table.d.ts +9 -8
  468. package/table/table.js.map +1 -1
  469. package/table/types.d.ts +35 -0
  470. package/tag/tag.js.map +1 -1
  471. package/text-list/index.js.map +1 -1
  472. package/theme/theme-provider/hooks.js.map +1 -1
  473. package/theme/theme-provider/index.js.map +1 -1
  474. package/theme/tokens/border.d.ts +9 -3
  475. package/theme/tokens/border.js.map +1 -1
  476. package/theme/tokens/breakpoint.js.map +1 -1
  477. package/theme/tokens/colour.d.ts +9 -3
  478. package/theme/tokens/colour.js.map +1 -1
  479. package/theme/tokens/component.d.ts +3 -1
  480. package/theme/tokens/component.js.map +1 -1
  481. package/theme/tokens/font.d.ts +6 -2
  482. package/theme/tokens/font.js.map +1 -1
  483. package/theme/tokens/media-query.d.ts +3 -1
  484. package/theme/tokens/media-query.js.map +1 -1
  485. package/theme/tokens/motion.d.ts +3 -1
  486. package/theme/tokens/motion.js.map +1 -1
  487. package/theme/tokens/radius.d.ts +3 -1
  488. package/theme/tokens/radius.js.map +1 -1
  489. package/theme/tokens/shadow.d.ts +3 -1
  490. package/theme/tokens/shadow.js.map +1 -1
  491. package/theme/tokens/spacing.d.ts +3 -1
  492. package/theme/tokens/spacing.js.map +1 -1
  493. package/theme/utils/use-apply-styles.js.map +1 -1
  494. package/theme/utils/use-design-token.js.map +1 -1
  495. package/theme/utils/use-media-query.js.map +1 -1
  496. package/time-range-picker/combobox-picker/combobox-picker.js +1 -1
  497. package/time-range-picker/combobox-picker/combobox-picker.js.map +1 -1
  498. package/time-range-picker/time-range-picker.js.map +1 -1
  499. package/time-range-picker/types.d.ts +1 -1
  500. package/time-slot-bar/time-slot-bar.js.map +1 -1
  501. package/time-slot-bar/types.d.ts +5 -1
  502. package/time-slot-bar-week/time-slot-bar-week.js.map +1 -1
  503. package/time-slot-bar-week/types.d.ts +6 -0
  504. package/time-slot-week-view/time-slot-week-view.js.map +1 -1
  505. package/time-slot-week-view/types.d.ts +2 -0
  506. package/timeline/timeline.js.map +1 -1
  507. package/timeline/types.d.ts +1 -1
  508. package/timepicker/timepicker.js.map +1 -1
  509. package/timepicker/types.d.ts +2 -2
  510. package/timetable/timetable.js.map +1 -1
  511. package/toast/toast.js.map +1 -1
  512. package/toast/types.d.ts +2 -0
  513. package/toggle/toggle.js.map +1 -1
  514. package/tools/shared/generated-file-formatter.d.ts +6 -0
  515. package/tools/shared/jsdoc-parser.d.ts +36 -0
  516. package/tools/shared/ts-morph-project-factory.d.ts +9 -0
  517. package/tools/shared/typescript-source-provider.d.ts +9 -0
  518. package/tools/storybook-argtypes/adapters/file-system-adapter.d.ts +69 -0
  519. package/tools/storybook-argtypes/arg-types-generator.d.ts +85 -0
  520. package/tools/storybook-argtypes/config/arg-types-config.d.ts +31 -0
  521. package/tools/storybook-argtypes/index.d.ts +11 -0
  522. package/tools/storybook-argtypes/services/arg-types-row-builder.d.ts +43 -0
  523. package/tools/storybook-argtypes/services/file-path-resolver.d.ts +118 -0
  524. package/tools/storybook-argtypes/services/index.d.ts +6 -0
  525. package/tools/storybook-argtypes/services/jsdoc-metadata-extractor.d.ts +33 -0
  526. package/tools/storybook-argtypes/services/story-registry-generator.d.ts +27 -0
  527. package/tools/storybook-argtypes/services/type-dependency-resolver.d.ts +46 -0
  528. package/tools/storybook-argtypes/services/type-formatting-service.d.ts +27 -0
  529. package/tools/storybook-argtypes/types.d.ts +102 -0
  530. package/typography/index.js.map +1 -1
  531. package/uneditable-section/index.js.map +1 -1
  532. package/uneditable-section/section-item.js +1 -1
  533. package/uneditable-section/section-item.js.map +1 -1
  534. package/uneditable-section/types.d.ts +2 -2
  535. package/unit-number/unit-number-input.js.map +1 -1
  536. package/cjs/form/form-custom-field.js +0 -2
  537. package/cjs/form/form-custom-field.js.map +0 -1
  538. package/cjs/form/form-date-input.js +0 -2
  539. package/cjs/form/form-date-input.js.map +0 -1
  540. package/cjs/form/form-date-range-input.js +0 -2
  541. package/cjs/form/form-date-range-input.js.map +0 -1
  542. package/cjs/form/form-e-signature.js +0 -2
  543. package/cjs/form/form-e-signature.js.map +0 -1
  544. package/cjs/form/form-histogram.js +0 -2
  545. package/cjs/form/form-histogram.js.map +0 -1
  546. package/cjs/form/form-input-group.js +0 -2
  547. package/cjs/form/form-input-group.js.map +0 -1
  548. package/cjs/form/form-input.js +0 -2
  549. package/cjs/form/form-input.js.map +0 -1
  550. package/cjs/form/form-label-addon.js +0 -2
  551. package/cjs/form/form-label-addon.js.map +0 -1
  552. package/cjs/form/form-label-addon.styles.js +0 -2
  553. package/cjs/form/form-label-addon.styles.js.map +0 -1
  554. package/cjs/form/form-label-addon.styles_b00z8p.css +0 -1
  555. package/cjs/form/form-label.js +0 -2
  556. package/cjs/form/form-label.js.map +0 -1
  557. package/cjs/form/form-label.styles.js +0 -2
  558. package/cjs/form/form-label.styles.js.map +0 -1
  559. package/cjs/form/form-label.styles_1nbe0bm.css +0 -6
  560. package/cjs/form/form-masked-input.js +0 -2
  561. package/cjs/form/form-masked-input.js.map +0 -1
  562. package/cjs/form/form-multi-select.js +0 -2
  563. package/cjs/form/form-multi-select.js.map +0 -1
  564. package/cjs/form/form-nested-multi-select.js +0 -2
  565. package/cjs/form/form-nested-multi-select.js.map +0 -1
  566. package/cjs/form/form-nested-select.js +0 -2
  567. package/cjs/form/form-nested-select.js.map +0 -1
  568. package/cjs/form/form-otp-verification.js +0 -2
  569. package/cjs/form/form-otp-verification.js.map +0 -1
  570. package/cjs/form/form-phone-number-input.js +0 -2
  571. package/cjs/form/form-phone-number-input.js.map +0 -1
  572. package/cjs/form/form-predictive-text-input.js +0 -2
  573. package/cjs/form/form-predictive-text-input.js.map +0 -1
  574. package/cjs/form/form-range-select.js +0 -2
  575. package/cjs/form/form-range-select.js.map +0 -1
  576. package/cjs/form/form-range-slider.js +0 -2
  577. package/cjs/form/form-range-slider.js.map +0 -1
  578. package/cjs/form/form-select-histogram.js +0 -2
  579. package/cjs/form/form-select-histogram.js.map +0 -1
  580. package/cjs/form/form-select.js +0 -2
  581. package/cjs/form/form-select.js.map +0 -1
  582. package/cjs/form/form-slider.js +0 -2
  583. package/cjs/form/form-slider.js.map +0 -1
  584. package/cjs/form/form-textarea.js +0 -2
  585. package/cjs/form/form-textarea.js.map +0 -1
  586. package/cjs/form/form-textarea.styles.js +0 -2
  587. package/cjs/form/form-textarea.styles.js.map +0 -1
  588. package/cjs/form/form-textarea.styles_3p9qoy.css +0 -3
  589. package/cjs/form/form-time-range-picker.js +0 -2
  590. package/cjs/form/form-time-range-picker.js.map +0 -1
  591. package/cjs/form/form-timepicker.js +0 -2
  592. package/cjs/form/form-timepicker.js.map +0 -1
  593. package/cjs/form/form-unit-number-input.js +0 -2
  594. package/cjs/form/form-unit-number-input.js.map +0 -1
  595. package/form/form-custom-field.js +0 -2
  596. package/form/form-custom-field.js.map +0 -1
  597. package/form/form-date-input.js +0 -2
  598. package/form/form-date-input.js.map +0 -1
  599. package/form/form-date-range-input.js +0 -2
  600. package/form/form-date-range-input.js.map +0 -1
  601. package/form/form-e-signature.js +0 -2
  602. package/form/form-e-signature.js.map +0 -1
  603. package/form/form-histogram.js +0 -2
  604. package/form/form-histogram.js.map +0 -1
  605. package/form/form-input-group.js +0 -2
  606. package/form/form-input-group.js.map +0 -1
  607. package/form/form-input.js +0 -2
  608. package/form/form-input.js.map +0 -1
  609. package/form/form-label-addon.js +0 -2
  610. package/form/form-label-addon.js.map +0 -1
  611. package/form/form-label-addon.styles.js +0 -2
  612. package/form/form-label-addon.styles.js.map +0 -1
  613. package/form/form-label-addon.styles_b00z8p.css +0 -1
  614. package/form/form-label.js +0 -2
  615. package/form/form-label.js.map +0 -1
  616. package/form/form-label.styles.js +0 -2
  617. package/form/form-label.styles.js.map +0 -1
  618. package/form/form-label.styles_1nbe0bm.css +0 -6
  619. package/form/form-masked-input.js +0 -2
  620. package/form/form-masked-input.js.map +0 -1
  621. package/form/form-multi-select.js +0 -2
  622. package/form/form-multi-select.js.map +0 -1
  623. package/form/form-nested-multi-select.js +0 -2
  624. package/form/form-nested-multi-select.js.map +0 -1
  625. package/form/form-nested-select.js +0 -2
  626. package/form/form-nested-select.js.map +0 -1
  627. package/form/form-otp-verification.js +0 -2
  628. package/form/form-otp-verification.js.map +0 -1
  629. package/form/form-phone-number-input.js +0 -2
  630. package/form/form-phone-number-input.js.map +0 -1
  631. package/form/form-predictive-text-input.js +0 -2
  632. package/form/form-predictive-text-input.js.map +0 -1
  633. package/form/form-range-select.js +0 -2
  634. package/form/form-range-select.js.map +0 -1
  635. package/form/form-range-slider.js +0 -2
  636. package/form/form-range-slider.js.map +0 -1
  637. package/form/form-select-histogram.js +0 -2
  638. package/form/form-select-histogram.js.map +0 -1
  639. package/form/form-select.js +0 -2
  640. package/form/form-select.js.map +0 -1
  641. package/form/form-slider.js +0 -2
  642. package/form/form-slider.js.map +0 -1
  643. package/form/form-textarea.js +0 -2
  644. package/form/form-textarea.js.map +0 -1
  645. package/form/form-textarea.styles.js +0 -2
  646. package/form/form-textarea.styles.js.map +0 -1
  647. package/form/form-textarea.styles_3p9qoy.css +0 -3
  648. package/form/form-time-range-picker.js +0 -2
  649. package/form/form-time-range-picker.js.map +0 -1
  650. package/form/form-timepicker.js +0 -2
  651. package/form/form-timepicker.js.map +0 -1
  652. package/form/form-unit-number-input.js +0 -2
  653. package/form/form-unit-number-input.js.map +0 -1
  654. package/link-list/internal-types.d.ts +0 -85
  655. /package/{codemod-utils.d.ts → codemods/codemod-utils.d.ts} +0 -0
  656. /package/{migrate-popover → codemods/migrate-popover}/index.d.ts +0 -0
  657. /package/{run-codemod.d.ts → codemods/run-codemod.d.ts} +0 -0
  658. /package/form/{form-custom-field.d.ts → form-custom-field/form-custom-field.d.ts} +0 -0
  659. /package/form/{form-date-input.d.ts → form-date-input/form-date-input.d.ts} +0 -0
  660. /package/form/{form-date-range-input.d.ts → form-date-range-input/form-date-range-input.d.ts} +0 -0
  661. /package/form/{form-e-signature.d.ts → form-e-signature/form-e-signature.d.ts} +0 -0
  662. /package/form/{form-histogram.d.ts → form-histogram-slider/form-histogram-slider.d.ts} +0 -0
  663. /package/form/{form-input.d.ts → form-input/form-input.d.ts} +0 -0
  664. /package/form/{form-input-group.d.ts → form-input-group/form-input-group.d.ts} +0 -0
  665. /package/form/{form-label-addon.d.ts → form-label/form-label-addon.d.ts} +0 -0
  666. /package/form/{form-label-addon.styles.d.ts → form-label/form-label-addon.styles.d.ts} +0 -0
  667. /package/form/{form-label.d.ts → form-label/form-label.d.ts} +0 -0
  668. /package/form/{form-label.styles.d.ts → form-label/form-label.styles.d.ts} +0 -0
  669. /package/form/{form-masked-input.d.ts → form-masked-input/form-masked-input.d.ts} +0 -0
  670. /package/form/{form-multi-select.d.ts → form-multi-select/form-multi-select.d.ts} +0 -0
  671. /package/form/{form-nested-multi-select.d.ts → form-nested-multi-select/form-nested-multi-select.d.ts} +0 -0
  672. /package/form/{form-nested-select.d.ts → form-nested-select/form-nested-select.d.ts} +0 -0
  673. /package/form/{form-phone-number-input.d.ts → form-phone-number-input/form-phone-number-input.d.ts} +0 -0
  674. /package/form/{form-predictive-text-input.d.ts → form-predictive-text-input/form-predictive-text-input.d.ts} +0 -0
  675. /package/form/{form-range-select.d.ts → form-range-select/form-range-select.d.ts} +0 -0
  676. /package/form/{form-range-slider.d.ts → form-range-slider/form-range-slider.d.ts} +0 -0
  677. /package/form/{form-select.d.ts → form-select/form-select.d.ts} +0 -0
  678. /package/form/{form-select-histogram.d.ts → form-select-histogram/form-select-histogram.d.ts} +0 -0
  679. /package/form/{form-slider.d.ts → form-slider/form-slider.d.ts} +0 -0
  680. /package/form/{form-textarea.d.ts → form-textarea/form-textarea.d.ts} +0 -0
  681. /package/form/{form-textarea.styles.d.ts → form-textarea/form-textarea.styles.d.ts} +0 -0
  682. /package/form/{form-time-range-picker.d.ts → form-time-range-picker/form-time-range-picker.d.ts} +0 -0
  683. /package/form/{form-timepicker.d.ts → form-timepicker/form-timepicker.d.ts} +0 -0
  684. /package/form/{form-unit-number-input.d.ts → form-unit-number-input/form-unit-number-input.d.ts} +0 -0
@@ -1 +1 @@
1
- {"version":3,"file":"drawer.js","sources":["../../src/drawer/drawer.tsx"],"sourcesContent":["import {\n FloatingFocusManager,\n useDismiss,\n useFloating,\n useInteractions,\n useTransitionStatus,\n} from \"@floating-ui/react\";\nimport { CrossIcon } from \"@lifesg/react-icons/cross\";\nimport clsx from \"clsx\";\nimport { useEffect, useRef, useState } from \"react\";\n\nimport { Overlay } from \"../overlay\";\nimport { ClickableIcon } from \"../shared/clickable-icon\";\nimport { Typography } from \"../typography\";\nimport { useId } from \"../util\";\nimport * as styles from \"./drawer.styles\";\nimport type { DrawerProps } from \"./types\";\n\n/**\n * A slide-in panel that overlays the page content.\n *\n * Use `Drawer` to surface supplementary content or navigation options without\n * navigating away from the current page. Focus is trapped inside the dialog\n * while it is open and returns to the triggering element on close.\n */\nexport const Drawer = ({\n children,\n heading,\n show,\n onClose,\n onOverlayClick,\n className,\n ...otherProps\n}: DrawerProps) => {\n // =========================================================================\n // CONST, STATE, REFS\n // =========================================================================\n const [showOverlay, setShowOverlay] = useState(show);\n const id = useId();\n const initialFocusRef = useRef<HTMLHeadingElement>(null);\n\n // =========================================================================\n // FLOATING UI CONFIG\n // =========================================================================\n const { context, refs } = useFloating({\n open: show,\n onOpenChange: (open) => {\n if (!open && onClose) {\n onClose();\n }\n },\n });\n\n const dismiss = useDismiss(context, {\n escapeKey: true,\n outsidePress: false, // defer to Overlay click\n });\n\n const { getFloatingProps } = useInteractions([dismiss]);\n\n const { isMounted, status } = useTransitionStatus(context, {\n duration: 800,\n });\n\n // =========================================================================\n // EFFECTS\n // =========================================================================\n useEffect(() => {\n if (!show) {\n const timer = setTimeout(() => setShowOverlay(false), 800);\n return () => clearTimeout(timer);\n } else {\n setShowOverlay(true);\n }\n }, [show]);\n\n // =========================================================================\n // EVENT HANDLERS\n // =========================================================================\n const handleDialogVisibility = (e: React.TransitionEvent) => {\n if (e.propertyName === \"visibility\" && show) {\n // focus the first element so that the screenreader enters the dialog\n initialFocusRef.current?.focus();\n }\n };\n\n // =========================================================================\n // RENDER FUNCTIONS\n // =========================================================================\n return (\n <Overlay\n show={showOverlay}\n enableOverlayClick\n onOverlayClick={onOverlayClick}\n >\n {isMounted ? (\n <FloatingFocusManager\n context={context}\n initialFocus={-1}\n returnFocus={true}\n >\n <div\n ref={refs.setFloating}\n data-status={status}\n data-testid=\"drawer\"\n aria-modal\n role=\"dialog\"\n aria-labelledby={id}\n onTransitionEnd={handleDialogVisibility}\n className={clsx(styles.container, className)}\n {...getFloatingProps()}\n {...otherProps}\n >\n <div className={styles.header}>\n <Typography.HeadingMD\n as=\"h2\"\n className={styles.heading}\n id={id}\n ref={initialFocusRef}\n tabIndex={-1}\n weight=\"bold\"\n >\n {heading}\n </Typography.HeadingMD>\n </div>\n <div className={styles.content}>{children}</div>\n <ClickableIcon\n aria-label=\"Close drawer\"\n onClick={onClose}\n focusHighlight={false}\n className={styles.closeButton}\n >\n <CrossIcon aria-hidden />\n </ClickableIcon>\n </div>\n </FloatingFocusManager>\n ) : undefined}\n </Overlay>\n );\n};\n"],"names":["Drawer","_a","children","heading","show","onClose","onOverlayClick","className","otherProps","__rest","showOverlay","setShowOverlay","useState","id","useId","initialFocusRef","useRef","context","refs","useFloating","open","onOpenChange","dismiss","useDismiss","escapeKey","outsidePress","getFloatingProps","useInteractions","isMounted","status","useTransitionStatus","duration","useEffect","timer","setTimeout","clearTimeout","_jsx","Overlay","enableOverlayClick","FloatingFocusManager","initialFocus","returnFocus","_jsxs","ref","setFloating","role","onTransitionEnd","e","propertyName","current","focus","clsx","styles.container","styles.header","Typography","HeadingMD","as","styles.heading","tabIndex","weight","styles.content","ClickableIcon","onClick","focusHighlight","styles.closeButton","CrossIcon","undefined"],"mappings":"00BAyBO,MAAMA,EAAUC,IAAA,IAAAC,SACnBA,EAAQC,QACRA,EAAOC,KACPA,EAAIC,QACJA,EAAOC,eACPA,EAAcC,UACdA,GAASN,EACNO,EAAUC,EAAAR,EAPM,sEAYnB,MAAOS,EAAaC,GAAkBC,EAASR,GACzCS,EAAKC,IACLC,EAAkBC,EAA2B,OAK7CC,QAAEA,EAAOC,KAAEA,GAASC,EAAY,CAClCC,KAAMhB,EACNiB,aAAeD,KACNA,GAAQf,GACTA,GACJ,IAIFiB,EAAUC,EAAWN,EAAS,CAChCO,WAAW,EACXC,cAAc,KAGZC,iBAAEA,GAAqBC,EAAgB,CAACL,KAExCM,UAAEA,EAASC,OAAEA,GAAWC,EAAoBb,EAAS,CACvDc,SAAU,MAMdC,GAAU,KACN,IAAK5B,EAAM,CACP,MAAM6B,EAAQC,YAAW,IAAMvB,GAAe,IAAQ,KACtD,MAAO,IAAMwB,aAAaF,EAC9B,CACItB,GAAe,EACnB,GACD,CAACP,IAeJ,OACIgC,EAACC,EAAO,CACJjC,KAAMM,EACN4B,oBAAkB,EAClBhC,eAAgBA,EAAcJ,SAE7B0B,EACGQ,EAACG,EAAoB,CACjBtB,QAASA,EACTuB,cAAc,EACdC,aAAa,EAAIvC,SAEjBwC,uBACIC,IAAKzB,EAAK0B,YAAW,cACRf,EAAM,cACP,yBAEZgB,KAAK,SAAQ,kBACIhC,EACjBiC,gBA7BYC,UACL,eAAnBA,EAAEC,cAAiC5C,IAEZ,QAAvBH,EAAAc,EAAgBkC,eAAO,IAAAhD,GAAAA,EAAEiD,QAC7B,EA0BgB3C,UAAW4C,EAAKC,EAAkB7C,IAC9BmB,IACAlB,EAAU,CAAAN,SAAA,CAEdkC,EAAA,MAAA,CAAK7B,UAAW8C,EAAanD,SACzBkC,EAACkB,EAAWC,UAAS,CACjBC,GAAG,KACHjD,UAAWkD,EACX5C,GAAIA,EACJ8B,IAAK5B,EACL2C,UAAU,EACVC,OAAO,gBAENxD,MAGTiC,SAAK7B,UAAWqD,EAAc1D,SAAGA,IACjCkC,EAACyB,EAAa,CAAA,aACC,eACXC,QAASzD,EACT0D,gBAAgB,EAChBxD,UAAWyD,EAAkB9D,SAE7BkC,EAAC6B,EAAS,CAAA,eAAA,iBAItBC,GACE"}
1
+ {"version":3,"file":"drawer.js","sources":["../../src/drawer/drawer.tsx"],"sourcesContent":["import {\n FloatingFocusManager,\n useDismiss,\n useFloating,\n useInteractions,\n useTransitionStatus,\n} from \"@floating-ui/react\";\nimport { CrossIcon } from \"@lifesg/react-icons/cross\";\nimport clsx from \"clsx\";\nimport { useEffect, useRef, useState } from \"react\";\n\nimport { Overlay } from \"../overlay\";\nimport { ClickableIcon } from \"../shared/clickable-icon\";\nimport { Typography } from \"../typography\";\nimport { useId } from \"../util\";\nimport * as styles from \"./drawer.styles\";\nimport type { DrawerProps } from \"./types\";\n\n// @catalog\n/**\n * A slide-in panel that overlays the page content.\n *\n * Use `Drawer` to surface supplementary content or navigation options without\n * navigating away from the current page. Focus is trapped inside the dialog\n * while it is open and returns to the triggering element on close.\n */\nexport const Drawer = ({\n children,\n heading,\n show,\n onClose,\n onOverlayClick,\n className,\n ...otherProps\n}: DrawerProps) => {\n // =========================================================================\n // CONST, STATE, REFS\n // =========================================================================\n const [showOverlay, setShowOverlay] = useState(show);\n const id = useId();\n const initialFocusRef = useRef<HTMLHeadingElement>(null);\n\n // =========================================================================\n // FLOATING UI CONFIG\n // =========================================================================\n const { context, refs } = useFloating({\n open: show,\n onOpenChange: (open) => {\n if (!open && onClose) {\n onClose();\n }\n },\n });\n\n const dismiss = useDismiss(context, {\n escapeKey: true,\n outsidePress: false, // defer to Overlay click\n });\n\n const { getFloatingProps } = useInteractions([dismiss]);\n\n const { isMounted, status } = useTransitionStatus(context, {\n duration: 800,\n });\n\n // =========================================================================\n // EFFECTS\n // =========================================================================\n useEffect(() => {\n if (!show) {\n const timer = setTimeout(() => setShowOverlay(false), 800);\n return () => clearTimeout(timer);\n } else {\n setShowOverlay(true);\n }\n }, [show]);\n\n // =========================================================================\n // EVENT HANDLERS\n // =========================================================================\n const handleDialogVisibility = (e: React.TransitionEvent) => {\n if (e.propertyName === \"visibility\" && show) {\n // focus the first element so that the screenreader enters the dialog\n initialFocusRef.current?.focus();\n }\n };\n\n // =========================================================================\n // RENDER FUNCTIONS\n // =========================================================================\n return (\n <Overlay\n show={showOverlay}\n enableOverlayClick\n onOverlayClick={onOverlayClick}\n >\n {isMounted ? (\n <FloatingFocusManager\n context={context}\n initialFocus={-1}\n returnFocus={true}\n >\n <div\n ref={refs.setFloating}\n data-status={status}\n data-testid=\"drawer\"\n aria-modal\n role=\"dialog\"\n aria-labelledby={id}\n onTransitionEnd={handleDialogVisibility}\n className={clsx(styles.container, className)}\n {...getFloatingProps()}\n {...otherProps}\n >\n <div className={styles.header}>\n <Typography.HeadingMD\n as=\"h2\"\n className={styles.heading}\n id={id}\n ref={initialFocusRef}\n tabIndex={-1}\n weight=\"bold\"\n >\n {heading}\n </Typography.HeadingMD>\n </div>\n <div className={styles.content}>{children}</div>\n <ClickableIcon\n aria-label=\"Close drawer\"\n onClick={onClose}\n focusHighlight={false}\n className={styles.closeButton}\n >\n <CrossIcon aria-hidden />\n </ClickableIcon>\n </div>\n </FloatingFocusManager>\n ) : undefined}\n </Overlay>\n );\n};\n"],"names":["Drawer","_a","children","heading","show","onClose","onOverlayClick","className","otherProps","__rest","showOverlay","setShowOverlay","useState","id","useId","initialFocusRef","useRef","context","refs","useFloating","open","onOpenChange","dismiss","useDismiss","escapeKey","outsidePress","getFloatingProps","useInteractions","isMounted","status","useTransitionStatus","duration","useEffect","timer","setTimeout","clearTimeout","_jsx","Overlay","enableOverlayClick","FloatingFocusManager","initialFocus","returnFocus","_jsxs","ref","setFloating","role","onTransitionEnd","e","propertyName","current","focus","clsx","styles.container","styles.header","Typography","HeadingMD","as","styles.heading","tabIndex","weight","styles.content","ClickableIcon","onClick","focusHighlight","styles.closeButton","CrossIcon","undefined"],"mappings":"00BA0BO,MAAMA,EAAUC,IAAA,IAAAC,SACnBA,EAAQC,QACRA,EAAOC,KACPA,EAAIC,QACJA,EAAOC,eACPA,EAAcC,UACdA,GAASN,EACNO,EAAUC,EAAAR,EAPM,sEAYnB,MAAOS,EAAaC,GAAkBC,EAASR,GACzCS,EAAKC,IACLC,EAAkBC,EAA2B,OAK7CC,QAAEA,EAAOC,KAAEA,GAASC,EAAY,CAClCC,KAAMhB,EACNiB,aAAeD,KACNA,GAAQf,GACTA,GACJ,IAIFiB,EAAUC,EAAWN,EAAS,CAChCO,WAAW,EACXC,cAAc,KAGZC,iBAAEA,GAAqBC,EAAgB,CAACL,KAExCM,UAAEA,EAASC,OAAEA,GAAWC,EAAoBb,EAAS,CACvDc,SAAU,MAMdC,GAAU,KACN,IAAK5B,EAAM,CACP,MAAM6B,EAAQC,YAAW,IAAMvB,GAAe,IAAQ,KACtD,MAAO,IAAMwB,aAAaF,EAC9B,CACItB,GAAe,EACnB,GACD,CAACP,IAeJ,OACIgC,EAACC,EAAO,CACJjC,KAAMM,EACN4B,oBAAkB,EAClBhC,eAAgBA,EAAcJ,SAE7B0B,EACGQ,EAACG,EAAoB,CACjBtB,QAASA,EACTuB,cAAc,EACdC,aAAa,EAAIvC,SAEjBwC,uBACIC,IAAKzB,EAAK0B,YAAW,cACRf,EAAM,cACP,yBAEZgB,KAAK,SAAQ,kBACIhC,EACjBiC,gBA7BYC,UACL,eAAnBA,EAAEC,cAAiC5C,IAEZ,QAAvBH,EAAAc,EAAgBkC,eAAO,IAAAhD,GAAAA,EAAEiD,QAC7B,EA0BgB3C,UAAW4C,EAAKC,EAAkB7C,IAC9BmB,IACAlB,EAAU,CAAAN,SAAA,CAEdkC,EAAA,MAAA,CAAK7B,UAAW8C,EAAanD,SACzBkC,EAACkB,EAAWC,UAAS,CACjBC,GAAG,KACHjD,UAAWkD,EACX5C,GAAIA,EACJ8B,IAAK5B,EACL2C,UAAU,EACVC,OAAO,gBAENxD,MAGTiC,SAAK7B,UAAWqD,EAAc1D,SAAGA,IACjCkC,EAACyB,EAAa,CAAA,aACC,eACXC,QAASzD,EACT0D,gBAAgB,EAChBxD,UAAWyD,EAAkB9D,SAE7BkC,EAAC6B,EAAS,CAAA,eAAA,iBAItBC,GACE"}
@@ -1 +1 @@
1
- {"version":3,"file":"e-signature.js","sources":["../../src/e-signature/e-signature.tsx"],"sourcesContent":["import { EraserIcon, PencilIcon } from \"@lifesg/react-icons\";\nimport { lazy, Suspense, useEffect, useRef, useState } from \"react\";\n\nimport { Button } from \"../button\";\nimport { DashedBorder } from \"../dashed-border\";\nimport { Modal } from \"../modal\";\nimport { ProgressBar } from \"../shared/progress-bar\";\nimport {\n Border,\n Breakpoint,\n Colour,\n Radius,\n useMaxWidthMediaQuery,\n useMediaQuery,\n useResolvedBreakpointToken,\n} from \"../theme\";\nimport { Typography } from \"../typography\";\nimport * as styles from \"./e-signature.styles\";\nimport type { ESignatureCanvasRef } from \"./e-signature-canvas\";\nimport type { EsignatureProps } from \"./types\";\n\n// lazy load to fix next.js SSR errors\nconst ESignatureCanvas = lazy(async () => ({\n default: (await import(\"./e-signature-canvas\")).ESignatureCanvas,\n}));\n\n/**\n * A field that lets users draw and save a signature.\n *\n * Use in forms that require a handwritten signature.\n */\nexport const ESignature = (props: EsignatureProps) => {\n // =============================================================================\n // CONST, STATE, REF\n // =============================================================================\n const {\n description,\n id,\n loadingProgress,\n loadingLabel = \"Uploading...\",\n onChange,\n value,\n disabled,\n ...otherProps\n } = props;\n const [showModal, setShowModal] = useState(false);\n const eSignatureCanvasRef = useRef<ESignatureCanvasRef>(null);\n const [dataURL, setDataURL] = useState<string | null | undefined>(value);\n const isMobile = useMaxWidthMediaQuery(\"sm\");\n const mobileBreakpoint = useResolvedBreakpointToken(Breakpoint[\"sm-max\"]);\n const isMobileLandscape = useMediaQuery({\n clauses: [\n {\n feature: \"orientation\",\n value: \"landscape\",\n },\n {\n feature: \"max-height\",\n value: mobileBreakpoint,\n },\n ],\n });\n\n // =============================================================================\n // EVENT HANDLERS\n // =============================================================================\n const handleClearDrawing = () => {\n eSignatureCanvasRef.current?.clear();\n };\n\n const handleClickSave = () => {\n if (eSignatureCanvasRef.current) {\n const dataURL = eSignatureCanvasRef.current.export();\n setDataURL(dataURL);\n setShowModal(false);\n onChange?.(dataURL);\n }\n };\n\n // =============================================================================\n // EFFECTS\n // =============================================================================\n useEffect(() => {\n setDataURL(value);\n }, [value]);\n\n // =============================================================================\n // RENDER FUNCTIONS\n // =============================================================================\n const renderSignatureArea = () => {\n if (!dataURL) {\n return (\n <Button\n className={styles.addSignatureButton}\n type=\"button\"\n styleType=\"secondary\"\n aria-label=\"Add signature\"\n id={id}\n onClick={() => setShowModal(true)}\n disabled={disabled}\n >\n Add signature\n </Button>\n );\n }\n\n return (\n <>\n <img\n className={styles.signaturePreviewImage}\n src={dataURL}\n alt=\"Signature preview\"\n />\n <Button\n className={styles.editSignatureButton}\n styleType=\"light\"\n onClick={() => setShowModal(true)}\n id={id}\n icon={<PencilIcon />}\n aria-label=\"Edit signature\"\n disabled={disabled}\n />\n </>\n );\n };\n\n const renderLoadingIndicator = () => {\n return (\n <div className={styles.progressBox}>\n {loadingLabel && (\n <Typography.BodyMD>{loadingLabel}</Typography.BodyMD>\n )}\n <ProgressBar\n progress={loadingProgress ?? 0}\n data-testid={`${id || \"e-signature\"}-progress-bar`}\n />\n </div>\n );\n };\n\n const renderModal = () => {\n return (\n <Modal\n className={styles.scrollableModal}\n data-testid=\"signature-modal\"\n show={showModal}\n >\n <div\n className={styles.growContainer}\n data-mobile-landscape={isMobileLandscape}\n >\n <Modal.Box\n className={styles.modalBox}\n data-mobile-landscape={isMobileLandscape}\n onClose={() => setShowModal(false)}\n >\n <h2\n className={styles.modalTitle}\n data-mobile-landscape={isMobileLandscape}\n >\n Signature\n </h2>\n <div\n className={styles.eSignatureContainer}\n data-mobile-landscape={isMobileLandscape}\n >\n <div\n className={styles.eSignatureDrawable}\n data-mobile-landscape={isMobileLandscape}\n >\n <div\n className={styles.signatureLine}\n data-mobile-landscape={isMobileLandscape}\n />\n <Suspense fallback={null}>\n {showModal && (\n <ESignatureCanvas\n ref={eSignatureCanvasRef}\n baseImageDataURL={dataURL}\n />\n )}\n </Suspense>\n </div>\n </div>\n <div\n className={styles.modalButtons}\n data-mobile-landscape={isMobileLandscape}\n >\n <Button\n className={styles.modalActionButton}\n data-mobile-landscape={isMobileLandscape}\n sizeType={\n isMobileLandscape ? \"small\" : \"default\"\n }\n type=\"button\"\n styleType={\n isMobile && !isMobileLandscape\n ? \"light\"\n : \"link\"\n }\n icon={<EraserIcon />}\n onClick={handleClearDrawing}\n >\n Clear\n </Button>\n <Button\n className={styles.modalActionButton}\n data-mobile-landscape={isMobileLandscape}\n sizeType={\n isMobileLandscape ? \"small\" : \"default\"\n }\n type=\"button\"\n onClick={handleClickSave}\n >\n Save\n </Button>\n </div>\n </Modal.Box>\n </div>\n </Modal>\n );\n };\n\n const renderDescription = () => {\n if (!description) return null;\n return (\n <Typography.BodySM className={styles.instructions}>\n {description}\n </Typography.BodySM>\n );\n };\n\n return (\n <div {...otherProps}>\n <DashedBorder\n className={styles.signatureArea}\n thickness={Border[\"width-040\"]}\n radius={Radius[\"sm\"]}\n colour={disabled ? Colour[\"border-disabled\"] : Colour[\"border\"]}\n backgroundColor={\n disabled ? Colour[\"bg-disabled\"] : Colour[\"bg\"]\n }\n >\n {typeof loadingProgress === \"number\"\n ? renderLoadingIndicator()\n : renderSignatureArea()}\n </DashedBorder>\n {renderModal()}\n {renderDescription()}\n </div>\n );\n};\n"],"names":["ESignatureCanvas","lazy","__awaiter","default","import","ESignature","props","description","id","loadingProgress","loadingLabel","onChange","value","disabled","otherProps","__rest","showModal","setShowModal","useState","eSignatureCanvasRef","useRef","dataURL","setDataURL","isMobile","useMaxWidthMediaQuery","mobileBreakpoint","useResolvedBreakpointToken","Breakpoint","isMobileLandscape","useMediaQuery","clauses","feature","handleClearDrawing","_a","current","clear","handleClickSave","export","useEffect","_jsxs","Object","assign","children","_jsx","DashedBorder","className","styles.signatureArea","thickness","Border","radius","Radius","colour","Colour","backgroundColor","styles.progressBox","Typography","BodyMD","ProgressBar","progress","_Fragment","styles.signaturePreviewImage","src","alt","Button","styles.editSignatureButton","styleType","onClick","icon","PencilIcon","styles.addSignatureButton","type","Modal","styles.scrollableModal","show","styles.growContainer","Box","styles.modalBox","onClose","styles.modalTitle","styles.eSignatureContainer","styles.eSignatureDrawable","styles.signatureLine","Suspense","fallback","ref","baseImageDataURL","styles.modalButtons","styles.modalActionButton","sizeType","EraserIcon","BodySM","styles.instructions"],"mappings":"+hDAsBA,MAAMA,EAAmBC,GAAK,IAAWC,OAAA,OAAA,OAAA,GAAA,YAAC,MAAA,CACtCC,eAAgBC,OAAO,4BAAyBJ,iBAClD,MAOWK,EAAcC,IAIvB,MAAMC,YACFA,EAAWC,GACXA,EAAEC,gBACFA,EAAeC,aACfA,EAAe,eAAcC,SAC7BA,EAAQC,MACRA,EAAKC,SACLA,GAEAP,EADGQ,EAAUC,EACbT,EATE,CAAA,cAAA,KAAA,kBAAA,eAAA,WAAA,QAAA,cAUCU,EAAWC,GAAgBC,GAAS,GACrCC,EAAsBC,EAA4B,OACjDC,EAASC,GAAcJ,EAAoCN,GAC5DW,EAAWC,EAAsB,MACjCC,EAAmBC,EAA2BC,EAAW,WACzDC,GAAoBC,EAAc,CACpCC,QAAS,CACL,CACIC,QAAS,cACTnB,MAAO,aAEX,CACImB,QAAS,aACTnB,MAAOa,MAQbO,GAAqB,WACI,QAA3BC,EAAAd,EAAoBe,eAAO,IAAAD,GAAAA,EAAEE,OAAO,EAGlCC,GAAkB,KACpB,GAAIjB,EAAoBe,QAAS,CAC7B,MAAMb,EAAUF,EAAoBe,QAAQG,SAC5Cf,EAAWD,GACXJ,GAAa,GACbN,SAAAA,EAAWU,EACf,GAMJiB,GAAU,KACNhB,EAAWV,EAAM,GAClB,CAACA,IAoJJ,OACI2B,EAAA,MAAAC,OAAAC,OAAA,GAAS3B,EAAU,CAAA4B,SAAA,CACfC,EAACC,EAAY,CACTC,UAAWC,EACXC,UAAWC,EAAO,aAClBC,OAAQC,EAAW,GACnBC,OAAQtC,EAAWuC,EAAO,mBAAqBA,EAAe,OAC9DC,gBACIxC,EAAWuC,EAAO,eAAiBA,EAAW,GAACV,SAGvB,iBAApBjC,EAnHZ8B,EAAA,MAAA,CAAKM,UAAWS,EAAkBZ,SAAA,CAC7BhC,GACGiC,EAACY,EAAWC,OAAM,CAAAd,SAAEhC,IAExBiC,EAACc,GACGC,SAAUjD,QAAAA,EAAmB,EAAC,cACjB,GAAGD,GAAM,kCA5C7Ba,EAiBDkB,EAAAoB,EAAA,CAAAjB,SAAA,CACIC,EAAA,MAAA,CACIE,UAAWe,EACXC,IAAKxC,EACLyC,IAAI,sBAERnB,EAACoB,EAAM,CACHlB,UAAWmB,EACXC,UAAU,QACVC,QAAS,IAAMjD,GAAa,GAC5BT,GAAIA,EACJ2D,KAAMxB,EAACyB,EAAU,CAAA,GAAG,aACT,iBACXvD,SAAUA,OA5Bd8B,EAACoB,EAAM,CACHlB,UAAWwB,EACXC,KAAK,SACLL,UAAU,YAAW,aACV,gBACXzD,GAAIA,EACJ0D,QAAS,IAAMjD,GAAa,GAC5BJ,SAAUA,EAAQ6B,SAAA,oBA2C1BC,EAAC4B,EAAK,CACF1B,UAAW2B,gBACC,kBACZC,KAAMzD,EAAS0B,SAEfC,EAAA,MAAA,CACIE,UAAW6B,EAAoB,wBACR9C,YAEvBW,EAACgC,EAAMI,KACH9B,UAAW+B,EAAe,wBACHhD,GACvBiD,QAAS,IAAM5D,GAAa,GAAMyB,SAAA,CAElCC,QACIE,UAAWiC,EAAiB,wBACLlD,GAAiBc,SAAA,cAI5CC,SACIE,UAAWkC,EAA0B,wBACdnD,GAAiBc,SAExCH,EAAA,MAAA,CACIM,UAAWmC,0BACYpD,GAAiBc,SAAA,CAExCC,EAAA,MAAA,CACIE,UAAWoC,0BACYrD,KAE3Be,EAACuC,EAAQ,CAACC,SAAU,cACfnE,GACG2B,EAAC3C,EAAgB,CACboF,IAAKjE,EACLkE,iBAAkBhE,WAMtCkB,SACIM,UAAWyC,EAAmB,wBACP1D,GAAiBc,SAAA,CAExCC,EAACoB,EAAM,CACHlB,UAAW0C,EAAwB,wBACZ3D,GACvB4D,SACI5D,GAAoB,QAAU,UAElC0C,KAAK,SACLL,UACI1C,IAAaK,GACP,QACA,OAEVuC,KAAMxB,EAAC8C,EAAU,CAAA,GACjBvB,QAASlC,GAAkBU,SAAA,UAI/BC,EAACoB,EAAM,CACHlB,UAAW0C,EAAwB,wBACZ3D,GACvB4D,SACI5D,GAAoB,QAAU,UAElC0C,KAAK,SACLJ,QAAS9B,GAAeM,SAAA,mBAY3CnC,EAEDoC,EAACY,EAAWmC,OAAM,CAAC7C,UAAW8C,EAAmBjD,SAC5CnC,IAHgB,QAyBnB"}
1
+ {"version":3,"file":"e-signature.js","sources":["../../src/e-signature/e-signature.tsx"],"sourcesContent":["import { EraserIcon, PencilIcon } from \"@lifesg/react-icons\";\nimport { lazy, Suspense, useEffect, useRef, useState } from \"react\";\n\nimport { Button } from \"../button\";\nimport { DashedBorder } from \"../dashed-border\";\nimport { Modal } from \"../modal\";\nimport { ProgressBar } from \"../shared/progress-bar\";\nimport {\n Border,\n Breakpoint,\n Colour,\n Radius,\n useMaxWidthMediaQuery,\n useMediaQuery,\n useResolvedBreakpointToken,\n} from \"../theme\";\nimport { Typography } from \"../typography\";\nimport * as styles from \"./e-signature.styles\";\nimport type { ESignatureCanvasRef } from \"./e-signature-canvas\";\nimport type { EsignatureProps } from \"./types\";\n\n// lazy load to fix next.js SSR errors\nconst ESignatureCanvas = lazy(async () => ({\n default: (await import(\"./e-signature-canvas\")).ESignatureCanvas,\n}));\n\n// @catalog\n/**\n * A field that lets users draw and save a signature.\n *\n * Use in forms that require a handwritten signature.\n */\nexport const ESignature = (props: EsignatureProps) => {\n // =============================================================================\n // CONST, STATE, REF\n // =============================================================================\n const {\n description,\n id,\n loadingProgress,\n loadingLabel = \"Uploading...\",\n onChange,\n value,\n disabled,\n ...otherProps\n } = props;\n const [showModal, setShowModal] = useState(false);\n const eSignatureCanvasRef = useRef<ESignatureCanvasRef>(null);\n const [dataURL, setDataURL] = useState<string | null | undefined>(value);\n const isMobile = useMaxWidthMediaQuery(\"sm\");\n const mobileBreakpoint = useResolvedBreakpointToken(Breakpoint[\"sm-max\"]);\n const isMobileLandscape = useMediaQuery({\n clauses: [\n {\n feature: \"orientation\",\n value: \"landscape\",\n },\n {\n feature: \"max-height\",\n value: mobileBreakpoint,\n },\n ],\n });\n\n // =============================================================================\n // EVENT HANDLERS\n // =============================================================================\n const handleClearDrawing = () => {\n eSignatureCanvasRef.current?.clear();\n };\n\n const handleClickSave = () => {\n if (eSignatureCanvasRef.current) {\n const dataURL = eSignatureCanvasRef.current.export();\n setDataURL(dataURL);\n setShowModal(false);\n onChange?.(dataURL);\n }\n };\n\n // =============================================================================\n // EFFECTS\n // =============================================================================\n useEffect(() => {\n setDataURL(value);\n }, [value]);\n\n // =============================================================================\n // RENDER FUNCTIONS\n // =============================================================================\n const renderSignatureArea = () => {\n if (!dataURL) {\n return (\n <Button\n className={styles.addSignatureButton}\n type=\"button\"\n styleType=\"secondary\"\n aria-label=\"Add signature\"\n id={id}\n onClick={() => setShowModal(true)}\n disabled={disabled}\n >\n Add signature\n </Button>\n );\n }\n\n return (\n <>\n <img\n className={styles.signaturePreviewImage}\n src={dataURL}\n alt=\"Signature preview\"\n />\n <Button\n className={styles.editSignatureButton}\n styleType=\"light\"\n onClick={() => setShowModal(true)}\n id={id}\n icon={<PencilIcon />}\n aria-label=\"Edit signature\"\n disabled={disabled}\n />\n </>\n );\n };\n\n const renderLoadingIndicator = () => {\n return (\n <div className={styles.progressBox}>\n {loadingLabel && (\n <Typography.BodyMD>{loadingLabel}</Typography.BodyMD>\n )}\n <ProgressBar\n progress={loadingProgress ?? 0}\n data-testid={`${id || \"e-signature\"}-progress-bar`}\n />\n </div>\n );\n };\n\n const renderModal = () => {\n return (\n <Modal\n className={styles.scrollableModal}\n data-testid=\"signature-modal\"\n show={showModal}\n >\n <div\n className={styles.growContainer}\n data-mobile-landscape={isMobileLandscape}\n >\n <Modal.Box\n className={styles.modalBox}\n data-mobile-landscape={isMobileLandscape}\n onClose={() => setShowModal(false)}\n >\n <h2\n className={styles.modalTitle}\n data-mobile-landscape={isMobileLandscape}\n >\n Signature\n </h2>\n <div\n className={styles.eSignatureContainer}\n data-mobile-landscape={isMobileLandscape}\n >\n <div\n className={styles.eSignatureDrawable}\n data-mobile-landscape={isMobileLandscape}\n >\n <div\n className={styles.signatureLine}\n data-mobile-landscape={isMobileLandscape}\n />\n <Suspense fallback={null}>\n {showModal && (\n <ESignatureCanvas\n ref={eSignatureCanvasRef}\n baseImageDataURL={dataURL}\n />\n )}\n </Suspense>\n </div>\n </div>\n <div\n className={styles.modalButtons}\n data-mobile-landscape={isMobileLandscape}\n >\n <Button\n className={styles.modalActionButton}\n data-mobile-landscape={isMobileLandscape}\n sizeType={\n isMobileLandscape ? \"small\" : \"default\"\n }\n type=\"button\"\n styleType={\n isMobile && !isMobileLandscape\n ? \"light\"\n : \"link\"\n }\n icon={<EraserIcon />}\n onClick={handleClearDrawing}\n >\n Clear\n </Button>\n <Button\n className={styles.modalActionButton}\n data-mobile-landscape={isMobileLandscape}\n sizeType={\n isMobileLandscape ? \"small\" : \"default\"\n }\n type=\"button\"\n onClick={handleClickSave}\n >\n Save\n </Button>\n </div>\n </Modal.Box>\n </div>\n </Modal>\n );\n };\n\n const renderDescription = () => {\n if (!description) return null;\n return (\n <Typography.BodySM className={styles.instructions}>\n {description}\n </Typography.BodySM>\n );\n };\n\n return (\n <div {...otherProps}>\n <DashedBorder\n className={styles.signatureArea}\n thickness={Border[\"width-040\"]}\n radius={Radius[\"sm\"]}\n colour={disabled ? Colour[\"border-disabled\"] : Colour[\"border\"]}\n backgroundColor={\n disabled ? Colour[\"bg-disabled\"] : Colour[\"bg\"]\n }\n >\n {typeof loadingProgress === \"number\"\n ? renderLoadingIndicator()\n : renderSignatureArea()}\n </DashedBorder>\n {renderModal()}\n {renderDescription()}\n </div>\n );\n};\n"],"names":["ESignatureCanvas","lazy","__awaiter","default","import","ESignature","props","description","id","loadingProgress","loadingLabel","onChange","value","disabled","otherProps","__rest","showModal","setShowModal","useState","eSignatureCanvasRef","useRef","dataURL","setDataURL","isMobile","useMaxWidthMediaQuery","mobileBreakpoint","useResolvedBreakpointToken","Breakpoint","isMobileLandscape","useMediaQuery","clauses","feature","handleClearDrawing","_a","current","clear","handleClickSave","export","useEffect","_jsxs","Object","assign","children","_jsx","DashedBorder","className","styles.signatureArea","thickness","Border","radius","Radius","colour","Colour","backgroundColor","styles.progressBox","Typography","BodyMD","ProgressBar","progress","_Fragment","styles.signaturePreviewImage","src","alt","Button","styles.editSignatureButton","styleType","onClick","icon","PencilIcon","styles.addSignatureButton","type","Modal","styles.scrollableModal","show","styles.growContainer","Box","styles.modalBox","onClose","styles.modalTitle","styles.eSignatureContainer","styles.eSignatureDrawable","styles.signatureLine","Suspense","fallback","ref","baseImageDataURL","styles.modalButtons","styles.modalActionButton","sizeType","EraserIcon","BodySM","styles.instructions"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"error-display.js","sources":["../../src/error-display/error-display.tsx"],"sourcesContent":["import clsx from \"clsx\";\nimport type React from \"react\";\nimport { useContext } from \"react\";\n\nimport { Button } from \"../button\";\nimport { Markup } from \"../markup\";\nimport { ThemeContext } from \"../theme/theme-provider/context\";\nimport { Typography } from \"../typography\";\nimport * as styles from \"./error-display.styles\";\nimport { getErrorDisplayData } from \"./error-display-data\";\nimport { InactivityTimer } from \"./inactivity-timer\";\nimport type {\n ErrorDisplayProps,\n InactivityAdditionalAttributes,\n MaintenanceAdditionalAttributes,\n} from \"./types\";\n\n/**\n * Displays a predefined error or status state with an illustration, title,\n * description, and optional action button.\n *\n * Use `ErrorDisplay` to communicate HTTP error codes, session lifecycle states,\n * maintenance windows, and other system-level statuses to users.\n */\nexport const ErrorDisplay = ({\n type,\n img,\n title,\n description,\n actionButton,\n additionalProps,\n imageOnly,\n illustrationScheme,\n className,\n ...otherProps\n}: ErrorDisplayProps) => {\n // =============================================================================\n // CONST, STATE, REF\n // =============================================================================\n const theme = useContext(ThemeContext);\n const defaultAssets = getErrorDisplayData(\n type,\n illustrationScheme || theme?.theme || \"lifesg\"\n );\n const inactivityAttrs =\n type === \"inactivity\"\n ? (additionalProps as InactivityAdditionalAttributes | undefined)\n : undefined;\n\n const secondsLeft = inactivityAttrs?.secondsLeft;\n const reminderInterval = inactivityAttrs?.reminderInterval;\n const testId = otherProps[\"data-testid\"] || \"error-display\";\n\n // =============================================================================\n // HELPER FUNCTIONS\n // =============================================================================\n const getCustomDescription = (): string | JSX.Element | undefined => {\n switch (type) {\n case \"maintenance\": {\n const typecastProps =\n additionalProps as MaintenanceAdditionalAttributes;\n return additionalProps && typecastProps.dateString\n ? defaultAssets?.renderDescription?.(typecastProps)\n : description || undefined;\n }\n case \"inactivity\": {\n const typecastProps =\n additionalProps as InactivityAdditionalAttributes;\n return additionalProps && typecastProps.secondsLeft\n ? defaultAssets?.renderDescription?.(typecastProps)\n : description || undefined;\n }\n default:\n return description || undefined;\n }\n };\n\n // =============================================================================\n // RENDER\n // =============================================================================\n if (!defaultAssets) {\n return null;\n }\n\n const renderActionButton = () => {\n const buttonProps: React.ButtonHTMLAttributes<HTMLButtonElement> = {\n children: \"Proceed\",\n ...actionButton,\n };\n\n return <Button className={styles.actionButton} {...buttonProps} />;\n };\n\n const updatedAssets = {\n ...defaultAssets,\n ...(img && { img }),\n ...(title && { title }),\n ...(getCustomDescription() && { description: getCustomDescription() }),\n };\n\n const renderContentDisplay = () => {\n if (updatedAssets.title || updatedAssets.description) {\n return (\n <div className={styles.textContainer}>\n {updatedAssets.title &&\n (typeof updatedAssets.title === \"string\" ? (\n <Typography.HeadingMD\n className={styles.title}\n data-testid={`${testId}--title`}\n data-id=\"error-display-title\"\n as=\"h2\"\n weight=\"semibold\"\n >\n {updatedAssets.title}\n </Typography.HeadingMD>\n ) : (\n updatedAssets.title\n ))}\n {updatedAssets.description && (\n <Markup\n className={styles.descriptionContainer}\n data-testid={`${testId}--description`}\n data-id=\"error-display-description\"\n baseTextSize=\"body-baseline\"\n >\n {typeof updatedAssets.description === \"string\" ? (\n <p>{updatedAssets.description}</p>\n ) : (\n updatedAssets.description\n )}\n </Markup>\n )}\n </div>\n );\n }\n\n return null;\n };\n\n return (\n <div\n {...otherProps}\n data-testid={testId}\n className={clsx(styles.container, className)}\n >\n {type === \"inactivity\" && (\n <InactivityTimer\n secondsLeft={secondsLeft}\n reminderInterval={reminderInterval}\n imageOnly={imageOnly}\n hasCustomDescription={!!description}\n />\n )}\n <img\n {...updatedAssets.img}\n alt=\"\"\n data-id=\"error-display-image\"\n className={clsx(styles.img, updatedAssets.img?.className)}\n />\n {!imageOnly && renderContentDisplay()}\n {actionButton && renderActionButton()}\n </div>\n );\n};\n"],"names":["ErrorDisplay","_a","type","img","title","description","actionButton","additionalProps","imageOnly","illustrationScheme","className","otherProps","__rest","theme","useContext","ThemeContext","defaultAssets","getErrorDisplayData","inactivityAttrs","undefined","secondsLeft","reminderInterval","testId","getCustomDescription","typecastProps","dateString","renderDescription","call","_b","updatedAssets","Object","assign","_jsxs","clsx","styles.container","children","_jsx","InactivityTimer","hasCustomDescription","alt","styles.img","styles.textContainer","Typography","HeadingMD","styles.title","as","weight","Markup","styles.descriptionContainer","baseTextSize","buttonProps","Button","styles.actionButton","renderActionButton"],"mappings":"umBAwBO,MAAMA,EAAgBC,WAAAC,KACzBA,EAAIC,IACJA,EAAGC,MACHA,EAAKC,YACLA,EAAWC,aACXA,EAAYC,gBACZA,EAAeC,UACfA,EAASC,mBACTA,EAAkBC,UAClBA,KACGC,EAAUC,EAAAX,EAVY,CAAA,OAAA,MAAA,QAAA,cAAA,eAAA,kBAAA,YAAA,qBAAA,cAezB,MAAMY,EAAQC,EAAWC,GACnBC,EAAgBC,EAClBf,EACAO,IAAsBI,aAAK,EAALA,EAAOA,QAAS,UAEpCK,EACO,eAAThB,EACOK,OACDY,EAEJC,EAAcF,aAAe,EAAfA,EAAiBE,YAC/BC,EAAmBH,aAAe,EAAfA,EAAiBG,iBACpCC,EAASX,EAAW,gBAAkB,gBAKtCY,EAAuB,aACzB,OAAQrB,GACJ,IAAK,cAAe,CAChB,MAAMsB,EACFjB,EACJ,OAAOA,GAAmBiB,EAAcC,WACF,QAAhCxB,EAAAe,aAAa,EAAbA,EAAeU,yBAAiB,IAAAzB,OAAA,EAAAA,EAAA0B,KAAAX,EAAGQ,GACnCnB,QAAec,CACzB,CACA,IAAK,aAAc,CACf,MAAMK,EACFjB,EACJ,OAAOA,GAAmBiB,EAAcJ,YACF,QAAhCQ,EAAAZ,aAAa,EAAbA,EAAeU,yBAAiB,IAAAE,OAAA,EAAAA,EAAAD,KAAAX,EAAGQ,GACnCnB,QAAec,CACzB,CACA,QACI,OAAOd,QAAec,IAOlC,IAAKH,EACD,OAAO,KAGX,MASMa,EAAaC,OAAAC,OAAAD,OAAAC,OAAAD,OAAAC,OAAAD,OAAAC,OAAA,CAAA,EACZf,GACCb,GAAO,KAAEA,IACTC,GAAS,CAAAA,MAAEA,IACXmB,KAA0B,CAAElB,YAAakB,MA0CjD,OACIS,EAAA,MAAAF,OAAAC,OAAA,CAAA,EACQpB,iBACSW,EACbZ,UAAWuB,EAAKC,EAAkBxB,GAAUyB,SAAA,CAElC,eAATjC,GACGkC,EAACC,EAAe,CACZjB,YAAaA,EACbC,iBAAkBA,EAClBb,UAAWA,EACX8B,uBAAwBjC,IAGhC+B,EAAA,MAAAN,OAAAC,OAAA,CAAA,EACQF,EAAc1B,IAAG,CACrBoC,IAAI,GAAE,UACE,sBACR7B,UAAWuB,EAAKO,EAA6B,QAAjBZ,EAAAC,EAAc1B,WAAG,IAAAyB,OAAA,EAAAA,EAAElB,eAEjDF,IA1DFqB,EAAczB,OAASyB,EAAcxB,YAEjC2B,EAAA,MAAA,CAAKtB,UAAW+B,EAAoBN,SAAA,CAC/BN,EAAczB,QACqB,iBAAxByB,EAAczB,MAClBgC,EAACM,EAAWC,WACRjC,UAAWkC,EAAY,cACV,GAAGtB,qBACR,sBACRuB,GAAG,KACHC,OAAO,WAAUX,SAEhBN,EAAczB,QAGnByB,EAAmB,OAE1BA,EAAcxB,aACX+B,EAACW,GACGrC,UAAWsC,EAA2B,cACzB,GAAG1B,2BACR,4BACR2B,aAAa,gBAAed,SAEU,iBAA9BN,EAAcxB,YAClB+B,EAAA,IAAA,CAAAD,SAAIN,EAAcxB,cAElBwB,EAAyB,iBAQ1C,MAwBFvB,GA5EkB,MACvB,MAAM4C,iBACFf,SAAU,WACP7B,GAGP,OAAO8B,EAACe,EAAMrB,OAAAC,OAAA,CAACrB,UAAW0C,GAAyBF,GAAe,EAsE7CG,MACf"}
1
+ {"version":3,"file":"error-display.js","sources":["../../src/error-display/error-display.tsx"],"sourcesContent":["import clsx from \"clsx\";\nimport type React from \"react\";\nimport { useContext } from \"react\";\n\nimport { Button } from \"../button\";\nimport { Markup } from \"../markup\";\nimport { ThemeContext } from \"../theme/theme-provider/context\";\nimport { Typography } from \"../typography\";\nimport * as styles from \"./error-display.styles\";\nimport { getErrorDisplayData } from \"./error-display-data\";\nimport { InactivityTimer } from \"./inactivity-timer\";\nimport type {\n ErrorDisplayProps,\n InactivityAdditionalAttributes,\n MaintenanceAdditionalAttributes,\n} from \"./types\";\n\n// @catalog\n/**\n * Displays a predefined error or status state with an illustration, title,\n * description, and optional action button.\n *\n * Use `ErrorDisplay` to communicate HTTP error codes, session lifecycle states,\n * maintenance windows, and other system-level statuses to users.\n */\nexport const ErrorDisplay = ({\n type,\n img,\n title,\n description,\n actionButton,\n additionalProps,\n imageOnly,\n illustrationScheme,\n className,\n ...otherProps\n}: ErrorDisplayProps) => {\n // =============================================================================\n // CONST, STATE, REF\n // =============================================================================\n const theme = useContext(ThemeContext);\n const defaultAssets = getErrorDisplayData(\n type,\n illustrationScheme || theme?.theme || \"lifesg\"\n );\n const inactivityAttrs =\n type === \"inactivity\"\n ? (additionalProps as InactivityAdditionalAttributes | undefined)\n : undefined;\n\n const secondsLeft = inactivityAttrs?.secondsLeft;\n const reminderInterval = inactivityAttrs?.reminderInterval;\n const testId = otherProps[\"data-testid\"] || \"error-display\";\n\n // =============================================================================\n // HELPER FUNCTIONS\n // =============================================================================\n const getCustomDescription = (): string | JSX.Element | undefined => {\n switch (type) {\n case \"maintenance\": {\n const typecastProps =\n additionalProps as MaintenanceAdditionalAttributes;\n return additionalProps && typecastProps.dateString\n ? defaultAssets?.renderDescription?.(typecastProps)\n : description || undefined;\n }\n case \"inactivity\": {\n const typecastProps =\n additionalProps as InactivityAdditionalAttributes;\n return additionalProps && typecastProps.secondsLeft\n ? defaultAssets?.renderDescription?.(typecastProps)\n : description || undefined;\n }\n default:\n return description || undefined;\n }\n };\n\n // =============================================================================\n // RENDER\n // =============================================================================\n if (!defaultAssets) {\n return null;\n }\n\n const renderActionButton = () => {\n const buttonProps: React.ButtonHTMLAttributes<HTMLButtonElement> = {\n children: \"Proceed\",\n ...actionButton,\n };\n\n return <Button className={styles.actionButton} {...buttonProps} />;\n };\n\n const updatedAssets = {\n ...defaultAssets,\n ...(img && { img }),\n ...(title && { title }),\n ...(getCustomDescription() && { description: getCustomDescription() }),\n };\n\n const renderContentDisplay = () => {\n if (updatedAssets.title || updatedAssets.description) {\n return (\n <div className={styles.textContainer}>\n {updatedAssets.title &&\n (typeof updatedAssets.title === \"string\" ? (\n <Typography.HeadingMD\n className={styles.title}\n data-testid={`${testId}--title`}\n data-id=\"error-display-title\"\n as=\"h2\"\n weight=\"semibold\"\n >\n {updatedAssets.title}\n </Typography.HeadingMD>\n ) : (\n updatedAssets.title\n ))}\n {updatedAssets.description && (\n <Markup\n className={styles.descriptionContainer}\n data-testid={`${testId}--description`}\n data-id=\"error-display-description\"\n baseTextSize=\"body-baseline\"\n >\n {typeof updatedAssets.description === \"string\" ? (\n <p>{updatedAssets.description}</p>\n ) : (\n updatedAssets.description\n )}\n </Markup>\n )}\n </div>\n );\n }\n\n return null;\n };\n\n return (\n <div\n {...otherProps}\n data-testid={testId}\n className={clsx(styles.container, className)}\n >\n {type === \"inactivity\" && (\n <InactivityTimer\n secondsLeft={secondsLeft}\n reminderInterval={reminderInterval}\n imageOnly={imageOnly}\n hasCustomDescription={!!description}\n />\n )}\n <img\n {...updatedAssets.img}\n alt=\"\"\n data-id=\"error-display-image\"\n className={clsx(styles.img, updatedAssets.img?.className)}\n />\n {!imageOnly && renderContentDisplay()}\n {actionButton && renderActionButton()}\n </div>\n );\n};\n"],"names":["ErrorDisplay","_a","type","img","title","description","actionButton","additionalProps","imageOnly","illustrationScheme","className","otherProps","__rest","theme","useContext","ThemeContext","defaultAssets","getErrorDisplayData","inactivityAttrs","undefined","secondsLeft","reminderInterval","testId","getCustomDescription","typecastProps","dateString","renderDescription","call","_b","updatedAssets","Object","assign","_jsxs","clsx","styles.container","children","_jsx","InactivityTimer","hasCustomDescription","alt","styles.img","styles.textContainer","Typography","HeadingMD","styles.title","as","weight","Markup","styles.descriptionContainer","baseTextSize","buttonProps","Button","styles.actionButton","renderActionButton"],"mappings":"umBAyBO,MAAMA,EAAgBC,WAAAC,KACzBA,EAAIC,IACJA,EAAGC,MACHA,EAAKC,YACLA,EAAWC,aACXA,EAAYC,gBACZA,EAAeC,UACfA,EAASC,mBACTA,EAAkBC,UAClBA,KACGC,EAAUC,EAAAX,EAVY,CAAA,OAAA,MAAA,QAAA,cAAA,eAAA,kBAAA,YAAA,qBAAA,cAezB,MAAMY,EAAQC,EAAWC,GACnBC,EAAgBC,EAClBf,EACAO,IAAsBI,aAAK,EAALA,EAAOA,QAAS,UAEpCK,EACO,eAAThB,EACOK,OACDY,EAEJC,EAAcF,aAAe,EAAfA,EAAiBE,YAC/BC,EAAmBH,aAAe,EAAfA,EAAiBG,iBACpCC,EAASX,EAAW,gBAAkB,gBAKtCY,EAAuB,aACzB,OAAQrB,GACJ,IAAK,cAAe,CAChB,MAAMsB,EACFjB,EACJ,OAAOA,GAAmBiB,EAAcC,WACF,QAAhCxB,EAAAe,aAAa,EAAbA,EAAeU,yBAAiB,IAAAzB,OAAA,EAAAA,EAAA0B,KAAAX,EAAGQ,GACnCnB,QAAec,CACzB,CACA,IAAK,aAAc,CACf,MAAMK,EACFjB,EACJ,OAAOA,GAAmBiB,EAAcJ,YACF,QAAhCQ,EAAAZ,aAAa,EAAbA,EAAeU,yBAAiB,IAAAE,OAAA,EAAAA,EAAAD,KAAAX,EAAGQ,GACnCnB,QAAec,CACzB,CACA,QACI,OAAOd,QAAec,IAOlC,IAAKH,EACD,OAAO,KAGX,MASMa,EAAaC,OAAAC,OAAAD,OAAAC,OAAAD,OAAAC,OAAAD,OAAAC,OAAA,CAAA,EACZf,GACCb,GAAO,KAAEA,IACTC,GAAS,CAAAA,MAAEA,IACXmB,KAA0B,CAAElB,YAAakB,MA0CjD,OACIS,EAAA,MAAAF,OAAAC,OAAA,CAAA,EACQpB,iBACSW,EACbZ,UAAWuB,EAAKC,EAAkBxB,GAAUyB,SAAA,CAElC,eAATjC,GACGkC,EAACC,EAAe,CACZjB,YAAaA,EACbC,iBAAkBA,EAClBb,UAAWA,EACX8B,uBAAwBjC,IAGhC+B,EAAA,MAAAN,OAAAC,OAAA,CAAA,EACQF,EAAc1B,IAAG,CACrBoC,IAAI,GAAE,UACE,sBACR7B,UAAWuB,EAAKO,EAA6B,QAAjBZ,EAAAC,EAAc1B,WAAG,IAAAyB,OAAA,EAAAA,EAAElB,eAEjDF,IA1DFqB,EAAczB,OAASyB,EAAcxB,YAEjC2B,EAAA,MAAA,CAAKtB,UAAW+B,EAAoBN,SAAA,CAC/BN,EAAczB,QACqB,iBAAxByB,EAAczB,MAClBgC,EAACM,EAAWC,WACRjC,UAAWkC,EAAY,cACV,GAAGtB,qBACR,sBACRuB,GAAG,KACHC,OAAO,WAAUX,SAEhBN,EAAczB,QAGnByB,EAAmB,OAE1BA,EAAcxB,aACX+B,EAACW,GACGrC,UAAWsC,EAA2B,cACzB,GAAG1B,2BACR,4BACR2B,aAAa,gBAAed,SAEU,iBAA9BN,EAAcxB,YAClB+B,EAAA,IAAA,CAAAD,SAAIN,EAAcxB,cAElBwB,EAAyB,iBAQ1C,MAwBFvB,GA5EkB,MACvB,MAAM4C,iBACFf,SAAU,WACP7B,GAGP,OAAO8B,EAACe,EAAMrB,OAAAC,OAAA,CAACrB,UAAW0C,GAAyBF,GAAe,EAsE7CG,MACf"}
@@ -1 +1 @@
1
- {"version":3,"file":"feedback-rating.js","sources":["../../src/feedback-rating/feedback-rating.tsx"],"sourcesContent":["import clsx from \"clsx\";\nimport { useEffect, useRef, useState } from \"react\";\n\nimport { Button } from \"../button\";\nimport { VisuallyHidden } from \"../shared/accessibility\";\nimport { Typography } from \"../typography\";\nimport { useId } from \"../util\";\nimport * as styles from \"./feedback-rating.styles\";\nimport { FeedbackRatingData } from \"./feedback-rating-data\";\nimport { FeedbackRatingStarsContainer } from \"./feedback-rating-stars-container\";\nimport type { FeedbackRatingProps } from \"./types\";\n\n/**\n * A star-rating widget for collecting user feedback.\n *\n * Use `FeedbackRating` to prompt users for a 1–5 star rating.\n * The submit button remains disabled until a star is selected.\n */\nexport const FeedbackRating = (props: FeedbackRatingProps): JSX.Element => {\n // =========================================================================\n // CONST, STATE, REF\n // =========================================================================\n const {\n imgSrc,\n buttonLabel,\n description,\n rating,\n onRatingChange,\n onSubmit,\n className,\n id,\n \"data-testid\": testId,\n ...otherProps\n } = props;\n const [hasImageError, setHasImageError] = useState(false);\n const imgRef = useRef<HTMLImageElement>(null);\n const internalId = useId();\n const descriptionId = `${internalId}-description`;\n const bannerSrc = imgSrc ?? FeedbackRatingData.IMG;\n const componentDescription =\n description ?? FeedbackRatingData.DEFAULT_DESCRIPTION;\n const resolvedButtonLabel =\n buttonLabel ?? FeedbackRatingData.DEFAULT_BUTTON_LABEL;\n const isSubmitDisabled = !rating;\n\n useEffect(() => {\n setHasImageError(false);\n\n if (imgRef.current?.complete && imgRef.current.naturalWidth === 0) {\n setHasImageError(true);\n }\n }, [bannerSrc]);\n\n const handleImgError = () => {\n setHasImageError(true);\n };\n\n return (\n <div\n role=\"group\"\n aria-labelledby={internalId}\n className={clsx(styles.mainContainer, className)}\n id={id}\n data-testid={testId}\n {...otherProps}\n >\n {bannerSrc && !hasImageError && (\n <img\n ref={imgRef}\n className={styles.image}\n data-testid=\"feedback-banner-image\"\n src={bannerSrc}\n alt=\"\"\n onError={handleImgError}\n />\n )}\n <div className={styles.childContainer}>\n <Typography.HeadingSM as=\"h2\" id={internalId} weight=\"semibold\">\n {componentDescription}\n </Typography.HeadingSM>\n <FeedbackRatingStarsContainer\n ariaLabelledBy={internalId}\n ariaDescribedBy={descriptionId}\n rating={rating}\n onRatingChange={onRatingChange}\n />\n <VisuallyHidden id={descriptionId}>\n Minimum, 1 star. Maximum, 5 stars.\n </VisuallyHidden>\n <Button\n className={styles.submitButton}\n disabled={isSubmitDisabled}\n focusableWhenDisabled\n onClick={onSubmit}\n type=\"button\"\n >\n {resolvedButtonLabel}\n </Button>\n </div>\n </div>\n );\n};\n"],"names":["FeedbackRating","props","imgSrc","buttonLabel","description","rating","onRatingChange","onSubmit","className","id","testId","otherProps","__rest","hasImageError","setHasImageError","useState","imgRef","useRef","internalId","useId","descriptionId","bannerSrc","FeedbackRatingData","IMG","componentDescription","DEFAULT_DESCRIPTION","resolvedButtonLabel","DEFAULT_BUTTON_LABEL","isSubmitDisabled","useEffect","_a","current","complete","naturalWidth","_jsxs","Object","assign","role","clsx","styles.mainContainer","children","_jsx","ref","styles.image","src","alt","onError","styles.childContainer","Typography","HeadingSM","as","weight","FeedbackRatingStarsContainer","ariaLabelledBy","ariaDescribedBy","VisuallyHidden","Button","styles.submitButton","disabled","focusableWhenDisabled","onClick","type"],"mappings":"yxBAkBO,MAAMA,EAAkBC,IAI3B,MAAMC,OACFA,EAAMC,YACNA,EAAWC,YACXA,EAAWC,OACXA,EAAMC,eACNA,EAAcC,SACdA,EAAQC,UACRA,EAASC,GACTA,EACA,cAAeC,GAEfT,EADGU,EAAUC,EACbX,EAXE,CAAA,SAAA,cAAA,cAAA,SAAA,iBAAA,WAAA,YAAA,KAAA,iBAYCY,EAAeC,GAAoBC,GAAS,GAC7CC,EAASC,EAAyB,MAClCC,EAAaC,IACbC,EAAgB,GAAGF,gBACnBG,EAAYnB,QAAAA,EAAUoB,EAAmBC,IACzCC,EACFpB,QAAAA,EAAekB,EAAmBG,oBAChCC,EACFvB,QAAAA,EAAemB,EAAmBK,qBAChCC,GAAoBvB,EAE1BwB,GAAU,WACNf,GAAiB,YAEbgB,EAAAd,EAAOe,8BAASC,WAA4C,IAAhChB,EAAOe,QAAQE,cAC3CnB,GAAiB,EACrB,GACD,CAACO,IAMJ,OACIa,EAAA,MAAAC,OAAAC,OAAA,CACIC,KAAK,QAAO,kBACKnB,EACjBV,UAAW8B,EAAKC,EAAsB/B,GACtCC,GAAIA,gBACSC,GACTC,EAAU,CAAA6B,SAAA,CAEbnB,IAAcR,GACX4B,EAAA,MAAA,CACIC,IAAK1B,EACLR,UAAWmC,EAAY,cACX,wBACZC,IAAKvB,EACLwB,IAAI,GACJC,QApBO,KACnBhC,GAAiB,EAAK,IAsBlBoB,EAAA,MAAA,CAAK1B,UAAWuC,EAAqBP,SAAA,CACjCC,EAACO,EAAWC,UAAS,CAACC,GAAG,KAAKzC,GAAIS,EAAYiC,OAAO,WAAUX,SAC1DhB,IAELiB,EAACW,EAA4B,CACzBC,eAAgBnC,EAChBoC,gBAAiBlC,EACjBf,OAAQA,EACRC,eAAgBA,IAEpBmC,EAACc,EAAc,CAAC9C,GAAIW,EAAaoB,SAAA,uCAGjCC,EAACe,EAAM,CACHhD,UAAWiD,EACXC,SAAU9B,EACV+B,uBAAqB,EACrBC,QAASrD,EACTsD,KAAK,kBAEJnC,UAGP"}
1
+ {"version":3,"file":"feedback-rating.js","sources":["../../src/feedback-rating/feedback-rating.tsx"],"sourcesContent":["import clsx from \"clsx\";\nimport { useEffect, useRef, useState } from \"react\";\n\nimport { Button } from \"../button\";\nimport { VisuallyHidden } from \"../shared/accessibility\";\nimport { Typography } from \"../typography\";\nimport { useId } from \"../util\";\nimport * as styles from \"./feedback-rating.styles\";\nimport { FeedbackRatingData } from \"./feedback-rating-data\";\nimport { FeedbackRatingStarsContainer } from \"./feedback-rating-stars-container\";\nimport type { FeedbackRatingProps } from \"./types\";\n\n// @catalog\n/**\n * A star-rating widget for collecting user feedback.\n *\n * Use `FeedbackRating` to prompt users for a 1–5 star rating.\n * The submit button remains disabled until a star is selected.\n */\nexport const FeedbackRating = (props: FeedbackRatingProps): JSX.Element => {\n // =========================================================================\n // CONST, STATE, REF\n // =========================================================================\n const {\n imgSrc,\n buttonLabel,\n description,\n rating,\n onRatingChange,\n onSubmit,\n className,\n id,\n \"data-testid\": testId,\n ...otherProps\n } = props;\n const [hasImageError, setHasImageError] = useState(false);\n const imgRef = useRef<HTMLImageElement>(null);\n const internalId = useId();\n const descriptionId = `${internalId}-description`;\n const bannerSrc = imgSrc ?? FeedbackRatingData.IMG;\n const componentDescription =\n description ?? FeedbackRatingData.DEFAULT_DESCRIPTION;\n const resolvedButtonLabel =\n buttonLabel ?? FeedbackRatingData.DEFAULT_BUTTON_LABEL;\n const isSubmitDisabled = !rating;\n\n useEffect(() => {\n setHasImageError(false);\n\n if (imgRef.current?.complete && imgRef.current.naturalWidth === 0) {\n setHasImageError(true);\n }\n }, [bannerSrc]);\n\n const handleImgError = () => {\n setHasImageError(true);\n };\n\n return (\n <div\n role=\"group\"\n aria-labelledby={internalId}\n className={clsx(styles.mainContainer, className)}\n id={id}\n data-testid={testId}\n {...otherProps}\n >\n {bannerSrc && !hasImageError && (\n <img\n ref={imgRef}\n className={styles.image}\n data-testid=\"feedback-banner-image\"\n src={bannerSrc}\n alt=\"\"\n onError={handleImgError}\n />\n )}\n <div className={styles.childContainer}>\n <Typography.HeadingSM as=\"h2\" id={internalId} weight=\"semibold\">\n {componentDescription}\n </Typography.HeadingSM>\n <FeedbackRatingStarsContainer\n ariaLabelledBy={internalId}\n ariaDescribedBy={descriptionId}\n rating={rating}\n onRatingChange={onRatingChange}\n />\n <VisuallyHidden id={descriptionId}>\n Minimum, 1 star. Maximum, 5 stars.\n </VisuallyHidden>\n <Button\n className={styles.submitButton}\n disabled={isSubmitDisabled}\n focusableWhenDisabled\n onClick={onSubmit}\n type=\"button\"\n >\n {resolvedButtonLabel}\n </Button>\n </div>\n </div>\n );\n};\n"],"names":["FeedbackRating","props","imgSrc","buttonLabel","description","rating","onRatingChange","onSubmit","className","id","testId","otherProps","__rest","hasImageError","setHasImageError","useState","imgRef","useRef","internalId","useId","descriptionId","bannerSrc","FeedbackRatingData","IMG","componentDescription","DEFAULT_DESCRIPTION","resolvedButtonLabel","DEFAULT_BUTTON_LABEL","isSubmitDisabled","useEffect","_a","current","complete","naturalWidth","_jsxs","Object","assign","role","clsx","styles.mainContainer","children","_jsx","ref","styles.image","src","alt","onError","styles.childContainer","Typography","HeadingSM","as","weight","FeedbackRatingStarsContainer","ariaLabelledBy","ariaDescribedBy","VisuallyHidden","Button","styles.submitButton","disabled","focusableWhenDisabled","onClick","type"],"mappings":"yxBAmBO,MAAMA,EAAkBC,IAI3B,MAAMC,OACFA,EAAMC,YACNA,EAAWC,YACXA,EAAWC,OACXA,EAAMC,eACNA,EAAcC,SACdA,EAAQC,UACRA,EAASC,GACTA,EACA,cAAeC,GAEfT,EADGU,EAAUC,EACbX,EAXE,CAAA,SAAA,cAAA,cAAA,SAAA,iBAAA,WAAA,YAAA,KAAA,iBAYCY,EAAeC,GAAoBC,GAAS,GAC7CC,EAASC,EAAyB,MAClCC,EAAaC,IACbC,EAAgB,GAAGF,gBACnBG,EAAYnB,QAAAA,EAAUoB,EAAmBC,IACzCC,EACFpB,QAAAA,EAAekB,EAAmBG,oBAChCC,EACFvB,QAAAA,EAAemB,EAAmBK,qBAChCC,GAAoBvB,EAE1BwB,GAAU,WACNf,GAAiB,YAEbgB,EAAAd,EAAOe,8BAASC,WAA4C,IAAhChB,EAAOe,QAAQE,cAC3CnB,GAAiB,EACrB,GACD,CAACO,IAMJ,OACIa,EAAA,MAAAC,OAAAC,OAAA,CACIC,KAAK,QAAO,kBACKnB,EACjBV,UAAW8B,EAAKC,EAAsB/B,GACtCC,GAAIA,gBACSC,GACTC,EAAU,CAAA6B,SAAA,CAEbnB,IAAcR,GACX4B,EAAA,MAAA,CACIC,IAAK1B,EACLR,UAAWmC,EAAY,cACX,wBACZC,IAAKvB,EACLwB,IAAI,GACJC,QApBO,KACnBhC,GAAiB,EAAK,IAsBlBoB,EAAA,MAAA,CAAK1B,UAAWuC,EAAqBP,SAAA,CACjCC,EAACO,EAAWC,UAAS,CAACC,GAAG,KAAKzC,GAAIS,EAAYiC,OAAO,WAAUX,SAC1DhB,IAELiB,EAACW,EAA4B,CACzBC,eAAgBnC,EAChBoC,gBAAiBlC,EACjBf,OAAQA,EACRC,eAAgBA,IAEpBmC,EAACc,EAAc,CAAC9C,GAAIW,EAAaoB,SAAA,uCAGjCC,EAACe,EAAM,CACHhD,UAAWiD,EACXC,SAAU9B,EACV+B,uBAAqB,EACrBC,QAASrD,EACTsD,KAAK,kBAEJnC,UAGP"}
@@ -1 +1 @@
1
- {"version":3,"file":"file-download.js","sources":["../../src/file-download/file-download.tsx"],"sourcesContent":["import clsx from \"clsx\";\n\nimport { DashedBorder } from \"../dashed-border\";\nimport { Markup } from \"../markup\";\nimport { Border, Colour, Radius } from \"../theme\";\nimport * as styles from \"./file-download.styles\";\nimport { FileListCard } from \"./file-list-card\";\nimport type { FileDownloadProps, FileItemDownloadProps } from \"./types\";\n\n/**\n * Displays a list of downloadable files, optionally grouped under a title and description.\n *\n * Use `FileDownload` to present one or more files that users can download individually.\n * Each file item renders as a card with file metadata and a download trigger.\n */\nexport const FileDownload = ({\n id,\n fileItems,\n title,\n description,\n onDownload,\n \"data-testid\": testId,\n className,\n styleType = \"bordered\",\n}: FileDownloadProps) => {\n // =========================================================================\n // EVENT HANDLERS\n // =========================================================================\n const handleDownloadItem = async (item: FileItemDownloadProps) => {\n if (onDownload) {\n await onDownload(item);\n }\n };\n\n // =========================================================================\n // RENDER FUNCTIONS\n // =========================================================================\n const renderTitle = () => {\n if (!title) {\n return null;\n }\n\n if (typeof title === \"string\") {\n return <p className={styles.title}>{title}</p>;\n }\n\n return (\n <Markup className={styles.titleContainer} baseTextSize=\"heading-xs\">\n {title}\n </Markup>\n );\n };\n\n const renderDescription = () => {\n if (!description) {\n return null;\n }\n\n if (typeof description === \"string\") {\n return <p className={styles.description}>{description}</p>;\n }\n\n return (\n <Markup\n className={styles.descriptionContainer}\n baseTextSize=\"body-md\"\n >\n {description}\n </Markup>\n );\n };\n\n const isBordered = styleType === \"bordered\";\n\n return (\n <DashedBorder\n id={id ? `${id}-file-download` : \"file-download\"}\n className={clsx(\n styles.container,\n isBordered && styles.containerBordered,\n className\n )}\n data-testid={testId}\n enabled={isBordered}\n thickness={Border[\"width-040\"]}\n radius={Radius[\"sm\"]}\n colour={Colour[\"border\"]}\n >\n {(title || description) && (\n <div className={styles.textContainer}>\n {renderTitle()}\n {renderDescription()}\n </div>\n )}\n <ul className={styles.listWrapper}>\n {fileItems &&\n fileItems.length > 0 &&\n fileItems.map((item) => (\n <FileListCard\n key={item.id}\n fileItem={item}\n onDownload={handleDownloadItem}\n />\n ))}\n </ul>\n </DashedBorder>\n );\n};\n"],"names":["FileDownload","id","fileItems","title","description","onDownload","testId","className","styleType","handleDownloadItem","item","__awaiter","isBordered","_jsxs","DashedBorder","clsx","styles.container","styles.containerBordered","enabled","thickness","Border","radius","Radius","colour","Colour","children","styles.textContainer","_jsx","styles.title","Markup","styles.titleContainer","baseTextSize","styles.description","styles.descriptionContainer","styles.listWrapper","length","map","FileListCard","fileItem"],"mappings":"ogCAeO,MAAMA,EAAe,EACxBC,KACAC,YAASC,MACTA,EAAKC,YACLA,EACAC,aACA,cAAeC,EACfC,YACAC,YAAY,eAKZ,MAAMC,EAA4BC,GAA+BC,OAAA,OAAA,OAAA,GAAA,YACzDN,UACMA,EAAWK,GAEzB,IAwCME,EAA2B,aAAdJ,EAEnB,OACIK,EAACC,GACGb,GAAIA,EAAK,GAAGA,kBAAqB,gBACjCM,UAAWQ,EACPC,EACAJ,GAAcK,EACdV,GACH,cACYD,EACbY,QAASN,EACTO,UAAWC,EAAO,aAClBC,OAAQC,EAAW,GACnBC,OAAQC,EAAe,OAACC,SAAA,EAEtBtB,GAASC,IACPS,SAAKN,UAAWmB,YAnDnBvB,EAIgB,iBAAVA,EACAwB,EAAA,IAAA,CAAGpB,UAAWqB,EAAYH,SAAGtB,IAIpCwB,EAACE,EAAM,CAACtB,UAAWuB,EAAuBC,aAAa,sBAClD5B,IATE,KAeNC,EAIsB,iBAAhBA,EACAuB,EAAA,IAAA,CAAGpB,UAAWyB,EAAkBP,SAAGrB,IAI1CuB,EAACE,EAAM,CACHtB,UAAW0B,EACXF,aAAa,mBAEZ3B,IAZE,QAuCPuB,QAAIpB,UAAW2B,WACVhC,GACGA,EAAUiC,OAAS,GACnBjC,EAAUkC,KAAK1B,GACXiB,EAACU,EAAY,CAETC,SAAU5B,EACVL,WAAYI,GAFPC,EAAKT,UAMf"}
1
+ {"version":3,"file":"file-download.js","sources":["../../src/file-download/file-download.tsx"],"sourcesContent":["import clsx from \"clsx\";\n\nimport { DashedBorder } from \"../dashed-border\";\nimport { Markup } from \"../markup\";\nimport { Border, Colour, Radius } from \"../theme\";\nimport * as styles from \"./file-download.styles\";\nimport { FileListCard } from \"./file-list-card\";\nimport type { FileDownloadProps, FileItemDownloadProps } from \"./types\";\n\n// @catalog\n/**\n * Displays a list of downloadable files, optionally grouped under a title and description.\n *\n * Use `FileDownload` to present one or more files that users can download individually.\n * Each file item renders as a card with file metadata and a download trigger.\n */\nexport const FileDownload = ({\n id,\n fileItems,\n title,\n description,\n onDownload,\n \"data-testid\": testId,\n className,\n styleType = \"bordered\",\n}: FileDownloadProps) => {\n // =========================================================================\n // EVENT HANDLERS\n // =========================================================================\n const handleDownloadItem = async (item: FileItemDownloadProps) => {\n if (onDownload) {\n await onDownload(item);\n }\n };\n\n // =========================================================================\n // RENDER FUNCTIONS\n // =========================================================================\n const renderTitle = () => {\n if (!title) {\n return null;\n }\n\n if (typeof title === \"string\") {\n return <p className={styles.title}>{title}</p>;\n }\n\n return (\n <Markup className={styles.titleContainer} baseTextSize=\"heading-xs\">\n {title}\n </Markup>\n );\n };\n\n const renderDescription = () => {\n if (!description) {\n return null;\n }\n\n if (typeof description === \"string\") {\n return <p className={styles.description}>{description}</p>;\n }\n\n return (\n <Markup\n className={styles.descriptionContainer}\n baseTextSize=\"body-md\"\n >\n {description}\n </Markup>\n );\n };\n\n const isBordered = styleType === \"bordered\";\n\n return (\n <DashedBorder\n id={id ? `${id}-file-download` : \"file-download\"}\n className={clsx(\n styles.container,\n isBordered && styles.containerBordered,\n className\n )}\n data-testid={testId}\n enabled={isBordered}\n thickness={Border[\"width-040\"]}\n radius={Radius[\"sm\"]}\n colour={Colour[\"border\"]}\n >\n {(title || description) && (\n <div className={styles.textContainer}>\n {renderTitle()}\n {renderDescription()}\n </div>\n )}\n <ul className={styles.listWrapper}>\n {fileItems &&\n fileItems.length > 0 &&\n fileItems.map((item) => (\n <FileListCard\n key={item.id}\n fileItem={item}\n onDownload={handleDownloadItem}\n />\n ))}\n </ul>\n </DashedBorder>\n );\n};\n"],"names":["FileDownload","id","fileItems","title","description","onDownload","testId","className","styleType","handleDownloadItem","item","__awaiter","isBordered","_jsxs","DashedBorder","clsx","styles.container","styles.containerBordered","enabled","thickness","Border","radius","Radius","colour","Colour","children","styles.textContainer","_jsx","styles.title","Markup","styles.titleContainer","baseTextSize","styles.description","styles.descriptionContainer","styles.listWrapper","length","map","FileListCard","fileItem"],"mappings":"ogCAgBO,MAAMA,EAAe,EACxBC,KACAC,YAASC,MACTA,EAAKC,YACLA,EACAC,aACA,cAAeC,EACfC,YACAC,YAAY,eAKZ,MAAMC,EAA4BC,GAA+BC,OAAA,OAAA,OAAA,GAAA,YACzDN,UACMA,EAAWK,GAEzB,IAwCME,EAA2B,aAAdJ,EAEnB,OACIK,EAACC,GACGb,GAAIA,EAAK,GAAGA,kBAAqB,gBACjCM,UAAWQ,EACPC,EACAJ,GAAcK,EACdV,GACH,cACYD,EACbY,QAASN,EACTO,UAAWC,EAAO,aAClBC,OAAQC,EAAW,GACnBC,OAAQC,EAAe,OAACC,SAAA,EAEtBtB,GAASC,IACPS,SAAKN,UAAWmB,YAnDnBvB,EAIgB,iBAAVA,EACAwB,EAAA,IAAA,CAAGpB,UAAWqB,EAAYH,SAAGtB,IAIpCwB,EAACE,EAAM,CAACtB,UAAWuB,EAAuBC,aAAa,sBAClD5B,IATE,KAeNC,EAIsB,iBAAhBA,EACAuB,EAAA,IAAA,CAAGpB,UAAWyB,EAAkBP,SAAGrB,IAI1CuB,EAACE,EAAM,CACHtB,UAAW0B,EACXF,aAAa,mBAEZ3B,IAZE,QAuCPuB,QAAIpB,UAAW2B,WACVhC,GACGA,EAAUiC,OAAS,GACnBjC,EAAUkC,KAAK1B,GACXiB,EAACU,EAAY,CAETC,SAAU5B,EACVL,WAAYI,GAFPC,EAAKT,UAMf"}
@@ -18,7 +18,11 @@ export interface FileItemDownloadProps {
18
18
  errorMessage?: string | React.ReactNode | undefined;
19
19
  /** URL or data URL for a thumbnail image shown alongside the file entry. */
20
20
  thumbnailImageDataUrl?: string | undefined;
21
- /** Truncates long file names with an ellipsis when `true`. */
21
+ /**
22
+ * Truncates long file names with an ellipsis when `true`.
23
+ *
24
+ * @default true
25
+ */
22
26
  truncateText?: boolean | undefined;
23
27
  /**
24
28
  * Indicates the file is available and ready to be downloaded.
@@ -61,6 +65,7 @@ export interface FileDownloadProps {
61
65
  * and the error UI is shown for that file card.
62
66
  *
63
67
  * @param file The file item that was activated for download.
68
+ * @returns A `Promise` that resolves when the download is complete, or `void` for synchronous handling.
64
69
  */
65
70
  onDownload: (file: FileItemDownloadProps) => void | Promise<void>;
66
71
  }
@@ -1,4 +1,4 @@
1
- import type { FormLabelProps } from "../form/types";
1
+ import type { FormLabelProps } from "../form/form-label/types";
2
2
  import type { FileItemProps } from "./types";
3
3
  interface Props {
4
4
  fileItem: FileItemProps;
@@ -1 +1 @@
1
- {"version":3,"file":"file-item-edit.js","sources":["../../src/file-upload/file-item-edit.tsx"],"sourcesContent":["import clsx from \"clsx\";\nimport { useCallback, useEffect, useRef, useState } from \"react\";\n\nimport { Button } from \"../button\";\nimport { Form } from \"../form\";\nimport type { FormLabelProps } from \"../form/types\";\nimport { Typography } from \"../typography\";\nimport { StringHelper } from \"../util\";\nimport * as styles from \"./file-item-edit.styles\";\nimport { FileListItemThumbnail } from \"./file-list-item/file-list-item-thumbnail\";\nimport { FileUploadHelper } from \"./helper\";\nimport type { FileItemProps } from \"./types\";\n\ninterface Props {\n fileItem: FileItemProps;\n wrapperWidth: number;\n fileDescriptionMaxLength?: number | undefined;\n descriptionRequired?: boolean | undefined;\n descriptionLabel?: FormLabelProps | undefined;\n onSave: (description: string) => void;\n onCancel: () => void;\n onBlur: (value: string) => void;\n}\n\nexport const FileItemEdit = ({\n fileItem,\n fileDescriptionMaxLength,\n descriptionRequired = true,\n descriptionLabel,\n wrapperWidth,\n onSave,\n onCancel,\n onBlur,\n}: Props) => {\n // =========================================================================\n // CONST, STATE, REFS\n // =========================================================================\n const {\n id,\n name,\n size,\n type,\n truncateText = true,\n thumbnailImageDataUrl,\n } = fileItem;\n\n const [formattedName, setFormattedName] = useState<string>();\n const [currentDescription, setCurrentDescription] = useState<string>(\"\");\n\n const textareaRef = useRef<HTMLTextAreaElement>(null);\n const nameSectionRef = useRef<HTMLDivElement>(null);\n\n // =========================================================================\n // HELPER FUNCTIONS\n // =========================================================================\n const getTruncatedText = useCallback(\n (value: string) => {\n if (!truncateText) return value;\n\n const widthOfElement =\n nameSectionRef && nameSectionRef.current\n ? nameSectionRef.current.getBoundingClientRect().width\n : 0;\n\n return StringHelper.truncateOneLine(\n value,\n widthOfElement,\n widthOfElement / 2,\n widthOfElement / 2 / 8, // Arbitrary\n 16 // Font size\n );\n },\n [truncateText]\n );\n\n // =========================================================================\n // EFFECTS\n // =========================================================================\n useEffect(() => {\n setFormattedName(getTruncatedText(name));\n }, [wrapperWidth, getTruncatedText, name]);\n\n useEffect(() => {\n setCurrentDescription(fileItem.description || \"\");\n }, [fileItem]);\n\n // =========================================================================\n // EVENT HANDLERS\n // =========================================================================\n const handleSave = () => {\n if (textareaRef.current) {\n onSave(textareaRef.current.value.trim());\n }\n };\n\n const handleChange = (event: React.ChangeEvent<HTMLTextAreaElement>) => {\n setCurrentDescription(event.target.value);\n };\n\n const handleBlur = (event: React.FocusEvent<HTMLTextAreaElement>) => {\n onBlur(event.target.value);\n };\n\n const shouldDisableSave = () => {\n if (!descriptionRequired) return false;\n const trimmedDescription = currentDescription.trim();\n return trimmedDescription.length === 0;\n };\n\n const shouldShowThumbnail =\n !!thumbnailImageDataUrl || type === FileUploadHelper.PDF_MIME_TYPE;\n\n // =========================================================================\n // RENDER FUNCTIONS\n // =========================================================================\n const renderFileNameAndSize = () => (\n <div ref={nameSectionRef} className={styles.nameSection}>\n <Typography.BodyMD\n className={styles.fileNameText}\n weight=\"semibold\"\n >\n {formattedName}\n </Typography.BodyMD>\n <Typography.BodyMD className={styles.fileSizeText}>\n {FileUploadHelper.formatFileSizeDisplay(size)}\n </Typography.BodyMD>\n </div>\n );\n\n return (\n <li data-testid={`${id}-edit-display`} className={styles.item}>\n <div className={styles.contentSection}>\n {shouldShowThumbnail && (\n <FileListItemThumbnail\n thumbnailImageDataUrl={thumbnailImageDataUrl}\n fileType={type}\n />\n )}\n <div className={styles.detailsSection}>\n {renderFileNameAndSize()}\n <Form.Textarea\n ref={textareaRef}\n id={`${id}-description-textarea`}\n data-testid={`${id}-textarea`}\n value={currentDescription}\n maxLength={fileDescriptionMaxLength}\n onChange={handleChange}\n onBlur={handleBlur}\n rows={3}\n label={\n descriptionLabel ?? {\n children: \"Photo description\",\n subtitle:\n \"Describe this photo to users who may not be able to see the image.\",\n }\n }\n />\n </div>\n </div>\n <div\n className={clsx(\n styles.actionButtonsSection,\n shouldShowThumbnail &&\n styles.actionButtonsSectionWithThumbnail\n )}\n >\n <Button\n data-testid={`${id}-save-button`}\n type=\"button\"\n sizeType=\"small\"\n disabled={shouldDisableSave()}\n onClick={handleSave}\n className={styles.actionButton}\n >\n Save\n </Button>\n <Button\n type=\"button\"\n sizeType=\"small\"\n styleType=\"secondary\"\n data-testid={`${id}-cancel-button`}\n onClick={onCancel}\n className={styles.actionButton}\n >\n Cancel\n </Button>\n </div>\n </li>\n );\n};\n"],"names":["FileItemEdit","fileItem","fileDescriptionMaxLength","descriptionRequired","descriptionLabel","wrapperWidth","onSave","onCancel","onBlur","id","name","size","type","truncateText","thumbnailImageDataUrl","formattedName","setFormattedName","useState","currentDescription","setCurrentDescription","textareaRef","useRef","nameSectionRef","getTruncatedText","useCallback","value","widthOfElement","current","getBoundingClientRect","width","StringHelper","truncateOneLine","useEffect","description","shouldShowThumbnail","FileUploadHelper","PDF_MIME_TYPE","_jsxs","className","styles.item","children","styles.contentSection","_jsx","FileListItemThumbnail","fileType","styles.detailsSection","ref","styles.nameSection","Typography","BodyMD","styles.fileNameText","weight","styles.fileSizeText","formatFileSizeDisplay","Form","Textarea","maxLength","onChange","event","target","rows","label","subtitle","clsx","styles.actionButtonsSection","styles.actionButtonsSectionWithThumbnail","Button","sizeType","disabled","trim","length","shouldDisableSave","onClick","styles.actionButton","styleType"],"mappings":"80BAwBO,MAAMA,EAAe,EACxBC,WACAC,2BACAC,uBAAsB,EACtBC,mBACAC,eACAC,SACAC,WACAC,aAKA,MAAMC,GACFA,EAAEC,KACFA,EAAIC,KACJA,EAAIC,KACJA,EAAIC,aACJA,GAAe,EAAIC,sBACnBA,GACAb,GAEGc,EAAeC,GAAoBC,KACnCC,EAAoBC,GAAyBF,EAAiB,IAE/DG,EAAcC,EAA4B,MAC1CC,EAAiBD,EAAuB,MAKxCE,EAAmBC,GACpBC,IACG,IAAKZ,EAAc,OAAOY,EAE1B,MAAMC,EACFJ,GAAkBA,EAAeK,QAC3BL,EAAeK,QAAQC,wBAAwBC,MAC/C,EAEV,OAAOC,EAAaC,gBAChBN,EACAC,EACAA,EAAiB,EACjBA,EAAiB,EAAI,EACrB,GACH,GAEL,CAACb,IAMLmB,GAAU,KACNhB,EAAiBO,EAAiBb,GAAM,GACzC,CAACL,EAAckB,EAAkBb,IAEpCsB,GAAU,KACNb,EAAsBlB,EAASgC,aAAe,GAAG,GAClD,CAAChC,IAKJ,MAoBMiC,IACApB,GAAyBF,IAASuB,EAAiBC,cAmBzD,OACIC,EAAA,KAAA,CAAA,cAAiB,GAAG5B,iBAAmB6B,UAAWC,EAAWC,SAAA,CACzDH,SAAKC,UAAWG,YACXP,GACGQ,EAACC,GACG7B,sBAAuBA,EACvB8B,SAAUhC,IAGlByB,EAAA,MAAA,CAAKC,UAAWO,EAAqBL,SAAA,CAtB7CH,EAAA,MAAA,CAAKS,IAAKxB,EAAgBgB,UAAWS,EAAkBP,SAAA,CACnDE,EAACM,EAAWC,OAAM,CACdX,UAAWY,EACXC,OAAO,WAAUX,SAEhBzB,IAEL2B,EAACM,EAAWC,OAAM,CAACX,UAAWc,EAAmBZ,SAC5CL,EAAiBkB,sBAAsB1C,QAgBpC+B,EAACY,EAAKC,SAAQ,CACVT,IAAK1B,EACLX,GAAI,GAAGA,yBAAyB,cACnB,GAAGA,aAChBgB,MAAOP,EACPsC,UAAWtD,EACXuD,SAnDEC,IAClBvC,EAAsBuC,EAAMC,OAAOlC,MAAM,EAmDzBjB,OAhDAkD,IAChBlD,EAAOkD,EAAMC,OAAOlC,MAAM,EAgDVmC,KAAM,EACNC,MACIzD,QAAAA,EAAoB,CAChBoC,SAAU,oBACVsB,SACI,8EAMxBzB,EAAA,MAAA,CACIC,UAAWyB,EACPC,EACA9B,GACI+B,GACPzB,SAAA,CAEDE,EAACwB,EAAM,CAAA,cACU,GAAGzD,gBAChBG,KAAK,SACLuD,SAAS,QACTC,SAnEU,MACtB,IAAKjE,EAAqB,OAAO,EAEjC,OAAqC,IADVe,EAAmBmD,OACpBC,MAAY,EAgEhBC,GACVC,QAlFG,KACXpD,EAAYO,SACZrB,EAAOc,EAAYO,QAAQF,MAAM4C,OACrC,EAgFY/B,UAAWmC,EAAmBjC,SAAA,SAIlCE,EAACwB,EAAM,CACHtD,KAAK,SACLuD,SAAS,QACTO,UAAU,YAAW,cACR,GAAGjE,kBAChB+D,QAASjE,EACT+B,UAAWmC,EAAmBjC,SAAA,gBAKrC"}
1
+ {"version":3,"file":"file-item-edit.js","sources":["../../src/file-upload/file-item-edit.tsx"],"sourcesContent":["import clsx from \"clsx\";\nimport { useCallback, useEffect, useRef, useState } from \"react\";\n\nimport { Button } from \"../button\";\nimport { Form } from \"../form\";\nimport type { FormLabelProps } from \"../form/form-label/types\";\nimport { Typography } from \"../typography\";\nimport { StringHelper } from \"../util\";\nimport * as styles from \"./file-item-edit.styles\";\nimport { FileListItemThumbnail } from \"./file-list-item/file-list-item-thumbnail\";\nimport { FileUploadHelper } from \"./helper\";\nimport type { FileItemProps } from \"./types\";\n\ninterface Props {\n fileItem: FileItemProps;\n wrapperWidth: number;\n fileDescriptionMaxLength?: number | undefined;\n descriptionRequired?: boolean | undefined;\n descriptionLabel?: FormLabelProps | undefined;\n onSave: (description: string) => void;\n onCancel: () => void;\n onBlur: (value: string) => void;\n}\n\nexport const FileItemEdit = ({\n fileItem,\n fileDescriptionMaxLength,\n descriptionRequired = true,\n descriptionLabel,\n wrapperWidth,\n onSave,\n onCancel,\n onBlur,\n}: Props) => {\n // =========================================================================\n // CONST, STATE, REFS\n // =========================================================================\n const {\n id,\n name,\n size,\n type,\n truncateText = true,\n thumbnailImageDataUrl,\n } = fileItem;\n\n const [formattedName, setFormattedName] = useState<string>();\n const [currentDescription, setCurrentDescription] = useState<string>(\"\");\n\n const textareaRef = useRef<HTMLTextAreaElement>(null);\n const nameSectionRef = useRef<HTMLDivElement>(null);\n\n // =========================================================================\n // HELPER FUNCTIONS\n // =========================================================================\n const getTruncatedText = useCallback(\n (value: string) => {\n if (!truncateText) return value;\n\n const widthOfElement =\n nameSectionRef && nameSectionRef.current\n ? nameSectionRef.current.getBoundingClientRect().width\n : 0;\n\n return StringHelper.truncateOneLine(\n value,\n widthOfElement,\n widthOfElement / 2,\n widthOfElement / 2 / 8, // Arbitrary\n 16 // Font size\n );\n },\n [truncateText]\n );\n\n // =========================================================================\n // EFFECTS\n // =========================================================================\n useEffect(() => {\n setFormattedName(getTruncatedText(name));\n }, [wrapperWidth, getTruncatedText, name]);\n\n useEffect(() => {\n setCurrentDescription(fileItem.description || \"\");\n }, [fileItem]);\n\n // =========================================================================\n // EVENT HANDLERS\n // =========================================================================\n const handleSave = () => {\n if (textareaRef.current) {\n onSave(textareaRef.current.value.trim());\n }\n };\n\n const handleChange = (event: React.ChangeEvent<HTMLTextAreaElement>) => {\n setCurrentDescription(event.target.value);\n };\n\n const handleBlur = (event: React.FocusEvent<HTMLTextAreaElement>) => {\n onBlur(event.target.value);\n };\n\n const shouldDisableSave = () => {\n if (!descriptionRequired) return false;\n const trimmedDescription = currentDescription.trim();\n return trimmedDescription.length === 0;\n };\n\n const shouldShowThumbnail =\n !!thumbnailImageDataUrl || type === FileUploadHelper.PDF_MIME_TYPE;\n\n // =========================================================================\n // RENDER FUNCTIONS\n // =========================================================================\n const renderFileNameAndSize = () => (\n <div ref={nameSectionRef} className={styles.nameSection}>\n <Typography.BodyMD\n className={styles.fileNameText}\n weight=\"semibold\"\n >\n {formattedName}\n </Typography.BodyMD>\n <Typography.BodyMD className={styles.fileSizeText}>\n {FileUploadHelper.formatFileSizeDisplay(size)}\n </Typography.BodyMD>\n </div>\n );\n\n return (\n <li data-testid={`${id}-edit-display`} className={styles.item}>\n <div className={styles.contentSection}>\n {shouldShowThumbnail && (\n <FileListItemThumbnail\n thumbnailImageDataUrl={thumbnailImageDataUrl}\n fileType={type}\n />\n )}\n <div className={styles.detailsSection}>\n {renderFileNameAndSize()}\n <Form.Textarea\n ref={textareaRef}\n id={`${id}-description-textarea`}\n data-testid={`${id}-textarea`}\n value={currentDescription}\n maxLength={fileDescriptionMaxLength}\n onChange={handleChange}\n onBlur={handleBlur}\n rows={3}\n label={\n descriptionLabel ?? {\n children: \"Photo description\",\n subtitle:\n \"Describe this photo to users who may not be able to see the image.\",\n }\n }\n />\n </div>\n </div>\n <div\n className={clsx(\n styles.actionButtonsSection,\n shouldShowThumbnail &&\n styles.actionButtonsSectionWithThumbnail\n )}\n >\n <Button\n data-testid={`${id}-save-button`}\n type=\"button\"\n sizeType=\"small\"\n disabled={shouldDisableSave()}\n onClick={handleSave}\n className={styles.actionButton}\n >\n Save\n </Button>\n <Button\n type=\"button\"\n sizeType=\"small\"\n styleType=\"secondary\"\n data-testid={`${id}-cancel-button`}\n onClick={onCancel}\n className={styles.actionButton}\n >\n Cancel\n </Button>\n </div>\n </li>\n );\n};\n"],"names":["FileItemEdit","fileItem","fileDescriptionMaxLength","descriptionRequired","descriptionLabel","wrapperWidth","onSave","onCancel","onBlur","id","name","size","type","truncateText","thumbnailImageDataUrl","formattedName","setFormattedName","useState","currentDescription","setCurrentDescription","textareaRef","useRef","nameSectionRef","getTruncatedText","useCallback","value","widthOfElement","current","getBoundingClientRect","width","StringHelper","truncateOneLine","useEffect","description","shouldShowThumbnail","FileUploadHelper","PDF_MIME_TYPE","_jsxs","className","styles.item","children","styles.contentSection","_jsx","FileListItemThumbnail","fileType","styles.detailsSection","ref","styles.nameSection","Typography","BodyMD","styles.fileNameText","weight","styles.fileSizeText","formatFileSizeDisplay","Form","Textarea","maxLength","onChange","event","target","rows","label","subtitle","clsx","styles.actionButtonsSection","styles.actionButtonsSectionWithThumbnail","Button","sizeType","disabled","trim","length","shouldDisableSave","onClick","styles.actionButton","styleType"],"mappings":"80BAwBO,MAAMA,EAAe,EACxBC,WACAC,2BACAC,uBAAsB,EACtBC,mBACAC,eACAC,SACAC,WACAC,aAKA,MAAMC,GACFA,EAAEC,KACFA,EAAIC,KACJA,EAAIC,KACJA,EAAIC,aACJA,GAAe,EAAIC,sBACnBA,GACAb,GAEGc,EAAeC,GAAoBC,KACnCC,EAAoBC,GAAyBF,EAAiB,IAE/DG,EAAcC,EAA4B,MAC1CC,EAAiBD,EAAuB,MAKxCE,EAAmBC,GACpBC,IACG,IAAKZ,EAAc,OAAOY,EAE1B,MAAMC,EACFJ,GAAkBA,EAAeK,QAC3BL,EAAeK,QAAQC,wBAAwBC,MAC/C,EAEV,OAAOC,EAAaC,gBAChBN,EACAC,EACAA,EAAiB,EACjBA,EAAiB,EAAI,EACrB,GACH,GAEL,CAACb,IAMLmB,GAAU,KACNhB,EAAiBO,EAAiBb,GAAM,GACzC,CAACL,EAAckB,EAAkBb,IAEpCsB,GAAU,KACNb,EAAsBlB,EAASgC,aAAe,GAAG,GAClD,CAAChC,IAKJ,MAoBMiC,IACApB,GAAyBF,IAASuB,EAAiBC,cAmBzD,OACIC,EAAA,KAAA,CAAA,cAAiB,GAAG5B,iBAAmB6B,UAAWC,EAAWC,SAAA,CACzDH,SAAKC,UAAWG,YACXP,GACGQ,EAACC,GACG7B,sBAAuBA,EACvB8B,SAAUhC,IAGlByB,EAAA,MAAA,CAAKC,UAAWO,EAAqBL,SAAA,CAtB7CH,EAAA,MAAA,CAAKS,IAAKxB,EAAgBgB,UAAWS,EAAkBP,SAAA,CACnDE,EAACM,EAAWC,OAAM,CACdX,UAAWY,EACXC,OAAO,WAAUX,SAEhBzB,IAEL2B,EAACM,EAAWC,OAAM,CAACX,UAAWc,EAAmBZ,SAC5CL,EAAiBkB,sBAAsB1C,QAgBpC+B,EAACY,EAAKC,SAAQ,CACVT,IAAK1B,EACLX,GAAI,GAAGA,yBAAyB,cACnB,GAAGA,aAChBgB,MAAOP,EACPsC,UAAWtD,EACXuD,SAnDEC,IAClBvC,EAAsBuC,EAAMC,OAAOlC,MAAM,EAmDzBjB,OAhDAkD,IAChBlD,EAAOkD,EAAMC,OAAOlC,MAAM,EAgDVmC,KAAM,EACNC,MACIzD,QAAAA,EAAoB,CAChBoC,SAAU,oBACVsB,SACI,8EAMxBzB,EAAA,MAAA,CACIC,UAAWyB,EACPC,EACA9B,GACI+B,GACPzB,SAAA,CAEDE,EAACwB,EAAM,CAAA,cACU,GAAGzD,gBAChBG,KAAK,SACLuD,SAAS,QACTC,SAnEU,MACtB,IAAKjE,EAAqB,OAAO,EAEjC,OAAqC,IADVe,EAAmBmD,OACpBC,MAAY,EAgEhBC,GACVC,QAlFG,KACXpD,EAAYO,SACZrB,EAAOc,EAAYO,QAAQF,MAAM4C,OACrC,EAgFY/B,UAAWmC,EAAmBjC,SAAA,SAIlCE,EAACwB,EAAM,CACHtD,KAAK,SACLuD,SAAS,QACTO,UAAU,YAAW,cACR,GAAGjE,kBAChB+D,QAASjE,EACT+B,UAAWmC,EAAmBjC,SAAA,gBAKrC"}
@@ -1,5 +1,5 @@
1
1
  import type React from "react";
2
- import type { FormLabelProps } from "../../form/types";
2
+ import type { FormLabelProps } from "../../form/form-label/types";
3
3
  import type { FileItemProps } from "../types";
4
4
  interface Props {
5
5
  fileItems: FileItemProps[] | undefined;
@@ -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/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 }, [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,4 +1,4 @@
1
- import type { FormLabelProps } from "../../form/types";
1
+ import type { FormLabelProps } from "../../form/form-label/types";
2
2
  import type { FileListItemProps } from "./types";
3
3
  interface Props extends FileListItemProps {
4
4
  readOnly?: boolean | undefined;
@@ -1 +1 @@
1
- {"version":3,"file":"file-list-item.js","sources":["../../../src/file-upload/file-list-item/file-list-item.tsx"],"sourcesContent":["import { useSortable } from \"@dnd-kit/sortable\";\nimport { CSS } from \"@dnd-kit/utilities\";\nimport { BinIcon } from \"@lifesg/react-icons/bin\";\nimport { DragHandleIcon as DSDragHandleIcon } from \"@lifesg/react-icons/drag-handle\";\nimport { ExclamationCircleFillIcon } from \"@lifesg/react-icons/exclamation-circle-fill\";\nimport { PencilIcon } from \"@lifesg/react-icons/pencil\";\nimport {\n memo,\n useCallback,\n useContext,\n useEffect,\n useRef,\n useState,\n} from \"react\";\n\nimport { Button } from \"../../button\";\nimport type { FormLabelProps } from \"../../form/types\";\nimport { ProgressBar } from \"../../shared/progress-bar\";\nimport { Typography } from \"../../typography\";\nimport { StringHelper } from \"../../util\";\nimport { FileUploadContext } from \"../context\";\nimport { FileUploadHelper } from \"../helper\";\nimport type { ItemFocusType } from \"./file-list-item.styles\";\nimport * as styles from \"./file-list-item.styles\";\nimport { FileListItemThumbnail } from \"./file-list-item-thumbnail\";\nimport type { FileListItemProps } from \"./types\";\n\ninterface Props extends FileListItemProps {\n readOnly?: boolean | undefined;\n descriptionLabel?: FormLabelProps | undefined;\n}\n\nconst Component = ({\n fileItem,\n editable,\n sortable,\n wrapperWidth,\n disabled,\n readOnly,\n descriptionLabel,\n onDelete,\n onEditClick,\n}: Props) => {\n // =========================================================================\n // CONST, STATE, REFS\n // =========================================================================\n const {\n id,\n name,\n size,\n description,\n progress = 1,\n errorMessage,\n thumbnailImageDataUrl,\n truncateText = true,\n } = fileItem;\n const [formattedName, setFormattedName] = useState<string>();\n const { activeId } = useContext(FileUploadContext);\n\n // Sortable mechanism\n const { attributes, listeners, setNodeRef, transform, transition } =\n useSortable({ id });\n const detailSectionRef = useRef<HTMLDivElement>(null);\n const style = {\n transform: CSS.Translate.toString(transform),\n transition,\n };\n\n const sortableProps = {\n style,\n ...attributes,\n ...listeners,\n };\n\n // Local variables\n const isLoading = progress < 1;\n const fileSize = FileUploadHelper.formatFileSizeDisplay(size);\n const hasInlineActions = !!description && !!editable;\n const focusType: ItemFocusType = activeId\n ? activeId === id\n ? \"self\"\n : \"others\"\n : \"none\";\n\n // =========================================================================\n // HELPER FUNCTIONS\n // =========================================================================\n const getTruncatedText = useCallback(\n (value: string) => {\n if (!truncateText) return value;\n\n const widthOfElement =\n detailSectionRef && detailSectionRef.current\n ? detailSectionRef.current.getBoundingClientRect().width\n : 0;\n\n return StringHelper.truncateOneLine(\n value,\n widthOfElement,\n widthOfElement / 2,\n widthOfElement / 2 / 8, // Arbitrary\n 16 // Font size\n );\n },\n [truncateText]\n );\n\n // =========================================================================\n // EFFECTS\n // =========================================================================\n useEffect(() => {\n setFormattedName(getTruncatedText(name));\n }, [wrapperWidth, getTruncatedText, name]);\n\n // =========================================================================\n // EVENT HANDLERS\n // =========================================================================\n const handleDelete = () => {\n onDelete();\n };\n\n const handleEdit = () => {\n if (onEditClick) {\n onEditClick();\n }\n };\n\n const handleKeyDown = (event: React.KeyboardEvent<HTMLButtonElement>) => {\n /**\n * Circumvent issue of keydown action activating the sort mechanism\n * rather than the actual action\n */\n if (sortable) {\n event.stopPropagation();\n }\n };\n\n const shouldDisable = () => disabled || !!activeId;\n\n const shouldEnableSort = () => !!sortable && !readOnly;\n\n const getItemState = () => {\n if (shouldDisable() && focusType === \"none\") {\n return \"disabled\";\n }\n\n if (shouldEnableSort() && focusType === \"self\") {\n return \"sortable-active\";\n }\n\n if (shouldEnableSort()) {\n return \"sortable\";\n }\n\n return undefined;\n };\n\n const getDragHandleState = () => {\n if (focusType === \"self\") {\n return \"active\";\n }\n\n if (shouldDisable()) {\n return \"disabled\";\n }\n\n return undefined;\n };\n\n const getBoxState = () => {\n if (focusType === \"self\") {\n return \"focused\";\n }\n\n if (shouldDisable()) {\n return \"disabled\";\n }\n\n if (errorMessage) {\n return \"error\";\n }\n\n return undefined;\n };\n\n const getActionContainerLayout = () => {\n if (!errorMessage && isLoading) {\n return \"loading\";\n }\n\n if (!errorMessage && editable) {\n return \"editable\";\n }\n\n return undefined;\n };\n\n // =========================================================================\n // RENDER FUNCTIONS\n // =========================================================================\n const renderNameDescription = () => (\n <>\n <Typography.BodyMD weight={description ? \"semibold\" : \"regular\"}>\n {formattedName}\n </Typography.BodyMD>\n {description && (\n <>\n <Typography.BodyMD className={styles.itemDescriptionLabel}>\n {descriptionLabel?.children ?? \"Photo description\"}\n </Typography.BodyMD>\n <Typography.BodyMD className={styles.itemDescriptionText}>\n {description}\n </Typography.BodyMD>\n </>\n )}\n </>\n );\n\n const renderErrorState = () => (\n <>\n <div ref={detailSectionRef} className={styles.nameSection}>\n {renderNameDescription()}\n {errorMessage && (\n <Typography.BodySM\n className={styles.desktopErrorMessage}\n weight=\"semibold\"\n >\n <ExclamationCircleFillIcon\n className={styles.errorIcon}\n aria-hidden\n />\n {errorMessage}\n </Typography.BodySM>\n )}\n </div>\n <div\n className={styles.fileSizeSection}\n data-mobile-visibility={isLoading ? \"hidden\" : \"expand\"}\n >\n <Typography.BodyMD className={styles.fileSizeText}>\n {fileSize}\n </Typography.BodyMD>\n </div>\n {errorMessage && (\n <Typography.BodySM\n className={styles.mobileErrorMessage}\n weight=\"semibold\"\n >\n <ExclamationCircleFillIcon\n className={styles.errorIcon}\n aria-hidden\n />\n {errorMessage}\n </Typography.BodySM>\n )}\n </>\n );\n\n const renderInlineActions = () => (\n <div className={styles.inlineActionContainer}>\n <Button\n key=\"edit\"\n data-testid={`${id}-edit-button`}\n data-no-dnd=\"true\"\n type=\"button\"\n styleType=\"light\"\n sizeType=\"small\"\n aria-label={`edit ${name}`}\n disabled={shouldDisable()}\n onClick={handleEdit}\n onKeyDown={handleKeyDown}\n icon={<PencilIcon aria-hidden />}\n className={styles.iconButton}\n />\n <Button\n key=\"delete\"\n data-testid={`${id}-delete-button`}\n data-no-dnd=\"true\"\n type=\"button\"\n styleType=\"light\"\n sizeType=\"small\"\n aria-label={`delete ${name}`}\n disabled={shouldDisable()}\n onClick={handleDelete}\n onKeyDown={handleKeyDown}\n icon={<BinIcon aria-hidden />}\n className={styles.iconButton}\n />\n </div>\n );\n\n const renderDescriptionContent = () => (\n <div ref={detailSectionRef} className={styles.extendedNameSection}>\n <Typography.BodyMD weight=\"semibold\">\n {formattedName}\n </Typography.BodyMD>\n <Typography.BodyMD className={styles.itemDescriptionLabel}>\n {descriptionLabel?.children ?? \"Photo description\"}\n </Typography.BodyMD>\n <Typography.BodyMD className={styles.itemDescriptionText}>\n {description}\n </Typography.BodyMD>\n <Typography.BodyMD className={styles.descriptionFileSizeText}>\n {fileSize}\n </Typography.BodyMD>\n {!readOnly && hasInlineActions && renderInlineActions()}\n </div>\n );\n\n const renderFileContent = (thumbnailImageDataUrl?: string) => {\n const shouldShowThumbnail =\n !!thumbnailImageDataUrl ||\n fileItem.type === FileUploadHelper.PDF_MIME_TYPE;\n\n const thumbnail = shouldShowThumbnail ? (\n <FileListItemThumbnail\n thumbnailImageDataUrl={thumbnailImageDataUrl || \"\"}\n fileType={fileItem.type}\n data-testid={`${id}-thumbnail`}\n />\n ) : null;\n\n if (hasInlineActions) {\n return (\n <>\n {thumbnail}\n {renderDescriptionContent()}\n </>\n );\n }\n\n return (\n <>\n {thumbnail}\n <div ref={detailSectionRef} className={styles.nameSection}>\n {renderNameDescription()}\n {!isLoading && (\n <Typography.BodyMD\n className={styles.descriptionFileSizeText}\n >\n {fileSize}\n </Typography.BodyMD>\n )}\n </div>\n </>\n );\n };\n\n const renderContents = () => {\n const shouldShowThumbnail =\n !!thumbnailImageDataUrl ||\n fileItem.type === FileUploadHelper.PDF_MIME_TYPE;\n\n const content = errorMessage\n ? renderErrorState()\n : renderFileContent(thumbnailImageDataUrl);\n\n return (\n <div\n className={styles.contentSection}\n data-has-thumbnail={shouldShowThumbnail}\n >\n {content}\n </div>\n );\n };\n\n const renderActions = () => {\n let content: JSX.Element;\n\n if (errorMessage) {\n content = (\n <Button\n data-testid={`${id}-error-delete-button`}\n data-no-dnd=\"true\"\n type=\"button\"\n styleType=\"light\"\n sizeType=\"small\"\n aria-label={`delete ${name}, error: ${errorMessage}`}\n onClick={handleDelete}\n className={styles.iconButton}\n icon={<BinIcon aria-hidden />}\n />\n );\n } else if (isLoading) {\n content = (\n <ProgressBar\n progress={progress}\n data-testid={`${id}-progress-bar`}\n />\n );\n } else {\n content = (\n <>\n {editable && (\n <Button\n key=\"edit\"\n data-testid={`${id}-edit-button`}\n data-no-dnd=\"true\"\n type=\"button\"\n styleType=\"light\"\n sizeType=\"small\"\n aria-label={`edit ${name}`}\n disabled={shouldDisable()}\n onClick={handleEdit}\n onKeyDown={handleKeyDown}\n icon={<PencilIcon aria-hidden />}\n className={styles.iconButton}\n />\n )}\n <Button\n key=\"delete\"\n data-testid={`${id}-delete-button`}\n data-no-dnd=\"true\"\n type=\"button\"\n styleType=\"light\"\n sizeType=\"small\"\n aria-label={`delete ${name}`}\n disabled={shouldDisable()}\n onClick={handleDelete}\n onKeyDown={handleKeyDown}\n icon={<BinIcon aria-hidden />}\n className={styles.iconButton}\n />\n </>\n );\n }\n\n return (\n <div\n className={styles.actionContainer}\n data-mobile-layout={getActionContainerLayout()}\n >\n {content}\n </div>\n );\n };\n\n return (\n <li\n id={id}\n ref={setNodeRef}\n className={styles.item}\n data-item-state={getItemState()}\n data-testid={`${id}-item`}\n {...(shouldEnableSort() ? sortableProps : {})}\n >\n {shouldEnableSort() && (\n <DSDragHandleIcon\n data-testid={`${id}-drag-handle`}\n className={styles.dragHandleIcon}\n data-drag-handle-state={getDragHandleState()}\n />\n )}\n <div\n className={styles.box}\n data-box-state={getBoxState()}\n data-stack-mobile={!errorMessage && (isLoading || editable)}\n >\n {renderContents()}\n {!readOnly && !hasInlineActions && renderActions()}\n </div>\n </li>\n );\n};\n\nexport const FileListItem = memo(Component);\n"],"names":["FileListItem","memo","fileItem","editable","sortable","wrapperWidth","disabled","readOnly","descriptionLabel","onDelete","onEditClick","id","name","size","description","progress","errorMessage","thumbnailImageDataUrl","truncateText","formattedName","setFormattedName","useState","activeId","useContext","FileUploadContext","attributes","listeners","setNodeRef","transform","transition","useSortable","detailSectionRef","useRef","style","CSS","Translate","toString","sortableProps","isLoading","fileSize","FileUploadHelper","formatFileSizeDisplay","hasInlineActions","focusType","getTruncatedText","useCallback","value","widthOfElement","current","getBoundingClientRect","width","StringHelper","truncateOneLine","useEffect","handleDelete","handleEdit","handleKeyDown","event","stopPropagation","shouldDisable","shouldEnableSort","renderNameDescription","_jsxs","_Fragment","children","_jsx","Typography","BodyMD","weight","className","styles.itemDescriptionLabel","_a","styles.itemDescriptionText","Object","assign","ref","styles.item","DSDragHandleIcon","styles.dragHandleIcon","styles.box","shouldShowThumbnail","type","PDF_MIME_TYPE","content","styles.nameSection","BodySM","styles.desktopErrorMessage","ExclamationCircleFillIcon","styles.errorIcon","styles.fileSizeSection","styles.fileSizeText","styles.mobileErrorMessage","thumbnail","FileListItemThumbnail","fileType","styles.extendedNameSection","styles.descriptionFileSizeText","styles.inlineActionContainer","Button","styleType","sizeType","onClick","onKeyDown","icon","PencilIcon","styles.iconButton","BinIcon","renderFileContent","styles.contentSection","renderContents","ProgressBar","styles.actionContainer","renderActions"],"mappings":"+/CAgCA,MAkbaA,EAAeC,GAlbV,EACdC,WACAC,WACAC,WACAC,eACAC,WACAC,WACAC,mBACAC,WACAC,kBAKA,MAAMC,GACFA,EAAEC,KACFA,EAAIC,KACJA,EAAIC,YACJA,EAAWC,SACXA,EAAW,EAACC,aACZA,EAAYC,sBACZA,EAAqBC,aACrBA,IAAe,GACfhB,GACGiB,GAAeC,IAAoBC,KACpCC,SAAEA,IAAaC,EAAWC,IAG1BC,WAAEA,GAAUC,UAAEA,GAASC,WAAEA,GAAUC,UAAEA,GAASC,WAAEA,IAClDC,EAAY,CAAEnB,OACZoB,GAAmBC,EAAuB,MAC1CC,GAAQ,CACVL,UAAWM,EAAIC,UAAUC,SAASR,IAClCC,eAGEQ,gCACFJ,UACGR,IACAC,IAIDY,GAAYvB,EAAW,EACvBwB,GAAWC,EAAiBC,sBAAsB5B,GAClD6B,KAAqB5B,KAAiBX,EACtCwC,GAA2BrB,GAC3BA,KAAaX,EACT,OACA,SACJ,OAKAiC,GAAmBC,GACpBC,IACG,IAAK5B,GAAc,OAAO4B,EAE1B,MAAMC,EACFhB,IAAoBA,GAAiBiB,QAC/BjB,GAAiBiB,QAAQC,wBAAwBC,MACjD,EAEV,OAAOC,EAAaC,gBAChBN,EACAC,EACAA,EAAiB,EACjBA,EAAiB,EAAI,EACrB,GACH,GAEL,CAAC7B,KAMLmC,GAAU,KACNjC,GAAiBwB,GAAiBhC,GAAM,GACzC,CAACP,EAAcuC,GAAkBhC,IAKpC,MAAM0C,GAAe,KACjB7C,GAAU,EAGR8C,GAAa,KACX7C,GACAA,GACJ,EAGE8C,GAAiBC,IAKfrD,GACAqD,EAAMC,iBACV,EAGEC,GAAgB,IAAMrD,KAAcgB,GAEpCsC,GAAmB,MAAQxD,IAAaG,EA6DxCsD,GAAwB,WAAM,OAChCC,EAAAC,EAAA,CAAAC,SAAA,CACIC,EAACC,EAAWC,OAAM,CAACC,OAAQtD,EAAc,WAAa,UAASkD,SAC1D7C,KAEJL,GACGgD,EAAAC,EAAA,CAAAC,SAAA,CACIC,EAACC,EAAWC,QAAOE,UAAWC,EAA2BN,SAC1B,QAA1BO,EAAA/D,aAAgB,EAAhBA,EAAkBwD,gBAAQ,IAAAO,EAAAA,EAAI,sBAEnCN,EAACC,EAAWC,OAAM,CAACE,UAAWG,EAA0BR,SACnDlD,SAId,EA+NP,OACIgD,EAAA,KAAAW,OAAAC,OAAA,CACI/D,GAAIA,EACJgE,IAAKhD,GACL0C,UAAWO,oBA5SXjB,MAAiC,SAAdhB,GACZ,WAGPiB,MAAoC,SAAdjB,GACf,kBAGPiB,KACO,gBADX,gBAsSiB,GAAGjD,UACXiD,KAAqBvB,GAAgB,CAAA,EAAG,CAAA2B,SAAA,CAE5CJ,MACGK,EAACY,iBACgB,GAAGlE,gBAChB0D,UAAWS,EAAqB,yBApS1B,SAAdnC,GACO,SAGPgB,KACO,gBADX,IAoSIG,EAAA,MAAA,CACIO,UAAWU,EAAU,iBA7RX,SAAdpC,GACO,UAGPgB,KACO,WAGP3C,EACO,aADX,EAsRqC,qBACTA,IAAiBsB,IAAanC,GAAS6D,SAAA,CA7GhD,MACnB,MAAMgB,IACA/D,GACFf,EAAS+E,OAASzC,EAAiB0C,cAEjCC,EAAUnE,EAtIhB8C,EAAAC,EAAA,CAAAC,SAAA,CACIF,EAAA,MAAA,CAAKa,IAAK5C,GAAkBsC,UAAWe,EAAkBpB,SAAA,CACpDH,KACA7C,GACG8C,EAACI,EAAWmB,QACRhB,UAAWiB,EACXlB,OAAO,WAAUJ,SAAA,CAEjBC,EAACsB,EAAyB,CACtBlB,UAAWmB,EAAgB,eAAA,IAG9BxE,QAIbiD,EAAA,MAAA,CACII,UAAWoB,EAAsB,yBACTnD,GAAY,SAAW,SAAQ0B,SAEvDC,EAACC,EAAWC,OAAM,CAACE,UAAWqB,EAAmB1B,SAC5CzB,OAGRvB,GACG8C,EAACI,EAAWmB,OAAM,CACdhB,UAAWsB,EACXvB,OAAO,WAAUJ,SAAA,CAEjBC,EAACsB,EAAyB,CACtBlB,UAAWmB,EAAgB,eAAA,IAG9BxE,QAyDS,CAACC,IACvB,MAIM2E,EAHA3E,GACFf,EAAS+E,OAASzC,EAAiB0C,cAGnCjB,EAAC4B,EAAqB,CAClB5E,sBAAuBA,GAAyB,GAChD6E,SAAU5F,EAAS+E,mBACN,GAAGtE,gBAEpB,KAEJ,OAEQmD,IAFJpB,cAGSkD,EAjCb9B,EAAA,MAAA,CAAKa,IAAK5C,GAAkBsC,UAAW0B,YACnC9B,EAACC,EAAWC,OAAM,CAACC,OAAO,WAAUJ,SAC/B7C,KAEL8C,EAACC,EAAWC,QAAOE,UAAWC,EAA2BN,SAC1B,QAA1BO,EAAA/D,eAAAA,EAAkBwD,gBAAQ,IAAAO,EAAAA,EAAI,sBAEnCN,EAACC,EAAWC,OAAM,CAACE,UAAWG,EAA0BR,SACnDlD,IAELmD,EAACC,EAAWC,OAAM,CAACE,UAAW2B,EAA8BhC,SACvDzB,MAEHhC,GAAYmC,IA9ClBoB,EAAA,MAAA,CAAKO,UAAW4B,EAA4BjC,SAAA,CACxCC,EAACiC,EAAM,CAAA,cAEU,GAAGvF,gBAAgB,cACpB,OACZsE,KAAK,SACLkB,UAAU,QACVC,SAAS,QAAO,aACJ,QAAQxF,IACpBN,SAAUqD,KACV0C,QAAS9C,GACT+C,UAAW9C,GACX+C,KAAMtC,EAACuC,EAAU,CAAA,eAAA,IACjBnC,UAAWoC,GAXP,QAaRxC,EAACiC,EAAM,CAAA,cAEU,GAAGvF,kBAAkB,cACtB,OACZsE,KAAK,SACLkB,UAAU,QACVC,SAAS,QAAO,aACJ,UAAUxF,IACtBN,SAAUqD,KACV0C,QAAS/C,GACTgD,UAAW9C,GACX+C,KAAMtC,EAACyC,EAAO,CAAA,eAAA,IACdrC,UAAWoC,GAXP,kBAyDR,CAAAzC,SAAA,CACK4B,EACD9B,EAAA,MAAA,CAAKa,IAAK5C,GAAkBsC,UAAWe,EAAkBpB,SAAA,CACpDH,MACCvB,IACE2B,EAACC,EAAWC,OAAM,CACdE,UAAW2B,WAEVzD,WAjDQ,KAqDtB,EAWDoE,CAAkB1F,GAExB,OACIgD,EAAA,MAAA,CACII,UAAWuC,EAAqB,qBACZ5B,EAAmBhB,SAEtCmB,GACC,EAgGD0B,IACCtG,IAAamC,IA7FL,MAClB,IAAIyC,EA4DJ,OAzDIA,EADAnE,EAEIiD,EAACiC,iBACgB,GAAGvF,wBAAwB,cAC5B,OACZsE,KAAK,SACLkB,UAAU,QACVC,SAAS,QAAO,aACJ,UAAUxF,aAAgBI,IACtCqF,QAAS/C,GACTe,UAAWoC,EACXF,KAAMtC,EAACyC,EAAO,CAAA,eAAA,MAGfpE,GAEH2B,EAAC6C,GACG/F,SAAUA,EAAQ,cACL,GAAGJ,mBAKpBmD,EAAAC,EAAA,CAAAC,SAAA,CACK7D,GACG8D,EAACiC,EAAM,CAAA,cAEU,GAAGvF,8BACJ,OACZsE,KAAK,SACLkB,UAAU,QACVC,SAAS,QAAO,aACJ,QAAQxF,IACpBN,SAAUqD,KACV0C,QAAS9C,GACT+C,UAAW9C,GACX+C,KAAMtC,EAACuC,EAAU,CAAA,eAAA,IACjBnC,UAAWoC,GAXP,QAcZxC,EAACiC,EAAM,CAAA,cAEU,GAAGvF,kBAAkB,cACtB,OACZsE,KAAK,SACLkB,UAAU,QACVC,SAAS,QAAO,aACJ,UAAUxF,IACtBN,SAAUqD,KACV0C,QAAS/C,GACTgD,UAAW9C,GACX+C,KAAMtC,EAACyC,EAAO,CAAA,eAAA,IACdrC,UAAWoC,GAXP,aAkBhBxC,EAAA,MAAA,CACII,UAAW0C,EAAsB,sBApPpC/F,GAAgBsB,GACV,WAGNtB,GAAgBb,EACV,gBADX,EAiPsD6D,SAE7CmB,GACC,EA0BiC6B,SAEtC"}
1
+ {"version":3,"file":"file-list-item.js","sources":["../../../src/file-upload/file-list-item/file-list-item.tsx"],"sourcesContent":["import { useSortable } from \"@dnd-kit/sortable\";\nimport { CSS } from \"@dnd-kit/utilities\";\nimport { BinIcon } from \"@lifesg/react-icons/bin\";\nimport { DragHandleIcon as DSDragHandleIcon } from \"@lifesg/react-icons/drag-handle\";\nimport { ExclamationCircleFillIcon } from \"@lifesg/react-icons/exclamation-circle-fill\";\nimport { PencilIcon } from \"@lifesg/react-icons/pencil\";\nimport {\n memo,\n useCallback,\n useContext,\n useEffect,\n useRef,\n useState,\n} from \"react\";\n\nimport { Button } from \"../../button\";\nimport type { FormLabelProps } from \"../../form/form-label/types\";\nimport { ProgressBar } from \"../../shared/progress-bar\";\nimport { Typography } from \"../../typography\";\nimport { StringHelper } from \"../../util\";\nimport { FileUploadContext } from \"../context\";\nimport { FileUploadHelper } from \"../helper\";\nimport type { ItemFocusType } from \"./file-list-item.styles\";\nimport * as styles from \"./file-list-item.styles\";\nimport { FileListItemThumbnail } from \"./file-list-item-thumbnail\";\nimport type { FileListItemProps } from \"./types\";\n\ninterface Props extends FileListItemProps {\n readOnly?: boolean | undefined;\n descriptionLabel?: FormLabelProps | undefined;\n}\n\nconst Component = ({\n fileItem,\n editable,\n sortable,\n wrapperWidth,\n disabled,\n readOnly,\n descriptionLabel,\n onDelete,\n onEditClick,\n}: Props) => {\n // =========================================================================\n // CONST, STATE, REFS\n // =========================================================================\n const {\n id,\n name,\n size,\n description,\n progress = 1,\n errorMessage,\n thumbnailImageDataUrl,\n truncateText = true,\n } = fileItem;\n const [formattedName, setFormattedName] = useState<string>();\n const { activeId } = useContext(FileUploadContext);\n\n // Sortable mechanism\n const { attributes, listeners, setNodeRef, transform, transition } =\n useSortable({ id });\n const detailSectionRef = useRef<HTMLDivElement>(null);\n const style = {\n transform: CSS.Translate.toString(transform),\n transition,\n };\n\n const sortableProps = {\n style,\n ...attributes,\n ...listeners,\n };\n\n // Local variables\n const isLoading = progress < 1;\n const fileSize = FileUploadHelper.formatFileSizeDisplay(size);\n const hasInlineActions = !!description && !!editable;\n const focusType: ItemFocusType = activeId\n ? activeId === id\n ? \"self\"\n : \"others\"\n : \"none\";\n\n // =========================================================================\n // HELPER FUNCTIONS\n // =========================================================================\n const getTruncatedText = useCallback(\n (value: string) => {\n if (!truncateText) return value;\n\n const widthOfElement =\n detailSectionRef && detailSectionRef.current\n ? detailSectionRef.current.getBoundingClientRect().width\n : 0;\n\n return StringHelper.truncateOneLine(\n value,\n widthOfElement,\n widthOfElement / 2,\n widthOfElement / 2 / 8, // Arbitrary\n 16 // Font size\n );\n },\n [truncateText]\n );\n\n // =========================================================================\n // EFFECTS\n // =========================================================================\n useEffect(() => {\n setFormattedName(getTruncatedText(name));\n }, [wrapperWidth, getTruncatedText, name]);\n\n // =========================================================================\n // EVENT HANDLERS\n // =========================================================================\n const handleDelete = () => {\n onDelete();\n };\n\n const handleEdit = () => {\n if (onEditClick) {\n onEditClick();\n }\n };\n\n const handleKeyDown = (event: React.KeyboardEvent<HTMLButtonElement>) => {\n /**\n * Circumvent issue of keydown action activating the sort mechanism\n * rather than the actual action\n */\n if (sortable) {\n event.stopPropagation();\n }\n };\n\n const shouldDisable = () => disabled || !!activeId;\n\n const shouldEnableSort = () => !!sortable && !readOnly;\n\n const getItemState = () => {\n if (shouldDisable() && focusType === \"none\") {\n return \"disabled\";\n }\n\n if (shouldEnableSort() && focusType === \"self\") {\n return \"sortable-active\";\n }\n\n if (shouldEnableSort()) {\n return \"sortable\";\n }\n\n return undefined;\n };\n\n const getDragHandleState = () => {\n if (focusType === \"self\") {\n return \"active\";\n }\n\n if (shouldDisable()) {\n return \"disabled\";\n }\n\n return undefined;\n };\n\n const getBoxState = () => {\n if (focusType === \"self\") {\n return \"focused\";\n }\n\n if (shouldDisable()) {\n return \"disabled\";\n }\n\n if (errorMessage) {\n return \"error\";\n }\n\n return undefined;\n };\n\n const getActionContainerLayout = () => {\n if (!errorMessage && isLoading) {\n return \"loading\";\n }\n\n if (!errorMessage && editable) {\n return \"editable\";\n }\n\n return undefined;\n };\n\n // =========================================================================\n // RENDER FUNCTIONS\n // =========================================================================\n const renderNameDescription = () => (\n <>\n <Typography.BodyMD weight={description ? \"semibold\" : \"regular\"}>\n {formattedName}\n </Typography.BodyMD>\n {description && (\n <>\n <Typography.BodyMD className={styles.itemDescriptionLabel}>\n {descriptionLabel?.children ?? \"Photo description\"}\n </Typography.BodyMD>\n <Typography.BodyMD className={styles.itemDescriptionText}>\n {description}\n </Typography.BodyMD>\n </>\n )}\n </>\n );\n\n const renderErrorState = () => (\n <>\n <div ref={detailSectionRef} className={styles.nameSection}>\n {renderNameDescription()}\n {errorMessage && (\n <Typography.BodySM\n className={styles.desktopErrorMessage}\n weight=\"semibold\"\n >\n <ExclamationCircleFillIcon\n className={styles.errorIcon}\n aria-hidden\n />\n {errorMessage}\n </Typography.BodySM>\n )}\n </div>\n <div\n className={styles.fileSizeSection}\n data-mobile-visibility={isLoading ? \"hidden\" : \"expand\"}\n >\n <Typography.BodyMD className={styles.fileSizeText}>\n {fileSize}\n </Typography.BodyMD>\n </div>\n {errorMessage && (\n <Typography.BodySM\n className={styles.mobileErrorMessage}\n weight=\"semibold\"\n >\n <ExclamationCircleFillIcon\n className={styles.errorIcon}\n aria-hidden\n />\n {errorMessage}\n </Typography.BodySM>\n )}\n </>\n );\n\n const renderInlineActions = () => (\n <div className={styles.inlineActionContainer}>\n <Button\n key=\"edit\"\n data-testid={`${id}-edit-button`}\n data-no-dnd=\"true\"\n type=\"button\"\n styleType=\"light\"\n sizeType=\"small\"\n aria-label={`edit ${name}`}\n disabled={shouldDisable()}\n onClick={handleEdit}\n onKeyDown={handleKeyDown}\n icon={<PencilIcon aria-hidden />}\n className={styles.iconButton}\n />\n <Button\n key=\"delete\"\n data-testid={`${id}-delete-button`}\n data-no-dnd=\"true\"\n type=\"button\"\n styleType=\"light\"\n sizeType=\"small\"\n aria-label={`delete ${name}`}\n disabled={shouldDisable()}\n onClick={handleDelete}\n onKeyDown={handleKeyDown}\n icon={<BinIcon aria-hidden />}\n className={styles.iconButton}\n />\n </div>\n );\n\n const renderDescriptionContent = () => (\n <div ref={detailSectionRef} className={styles.extendedNameSection}>\n <Typography.BodyMD weight=\"semibold\">\n {formattedName}\n </Typography.BodyMD>\n <Typography.BodyMD className={styles.itemDescriptionLabel}>\n {descriptionLabel?.children ?? \"Photo description\"}\n </Typography.BodyMD>\n <Typography.BodyMD className={styles.itemDescriptionText}>\n {description}\n </Typography.BodyMD>\n <Typography.BodyMD className={styles.descriptionFileSizeText}>\n {fileSize}\n </Typography.BodyMD>\n {!readOnly && hasInlineActions && renderInlineActions()}\n </div>\n );\n\n const renderFileContent = (thumbnailImageDataUrl?: string) => {\n const shouldShowThumbnail =\n !!thumbnailImageDataUrl ||\n fileItem.type === FileUploadHelper.PDF_MIME_TYPE;\n\n const thumbnail = shouldShowThumbnail ? (\n <FileListItemThumbnail\n thumbnailImageDataUrl={thumbnailImageDataUrl || \"\"}\n fileType={fileItem.type}\n data-testid={`${id}-thumbnail`}\n />\n ) : null;\n\n if (hasInlineActions) {\n return (\n <>\n {thumbnail}\n {renderDescriptionContent()}\n </>\n );\n }\n\n return (\n <>\n {thumbnail}\n <div ref={detailSectionRef} className={styles.nameSection}>\n {renderNameDescription()}\n {!isLoading && (\n <Typography.BodyMD\n className={styles.descriptionFileSizeText}\n >\n {fileSize}\n </Typography.BodyMD>\n )}\n </div>\n </>\n );\n };\n\n const renderContents = () => {\n const shouldShowThumbnail =\n !!thumbnailImageDataUrl ||\n fileItem.type === FileUploadHelper.PDF_MIME_TYPE;\n\n const content = errorMessage\n ? renderErrorState()\n : renderFileContent(thumbnailImageDataUrl);\n\n return (\n <div\n className={styles.contentSection}\n data-has-thumbnail={shouldShowThumbnail}\n >\n {content}\n </div>\n );\n };\n\n const renderActions = () => {\n let content: JSX.Element;\n\n if (errorMessage) {\n content = (\n <Button\n data-testid={`${id}-error-delete-button`}\n data-no-dnd=\"true\"\n type=\"button\"\n styleType=\"light\"\n sizeType=\"small\"\n aria-label={`delete ${name}, error: ${errorMessage}`}\n onClick={handleDelete}\n className={styles.iconButton}\n icon={<BinIcon aria-hidden />}\n />\n );\n } else if (isLoading) {\n content = (\n <ProgressBar\n progress={progress}\n data-testid={`${id}-progress-bar`}\n />\n );\n } else {\n content = (\n <>\n {editable && (\n <Button\n key=\"edit\"\n data-testid={`${id}-edit-button`}\n data-no-dnd=\"true\"\n type=\"button\"\n styleType=\"light\"\n sizeType=\"small\"\n aria-label={`edit ${name}`}\n disabled={shouldDisable()}\n onClick={handleEdit}\n onKeyDown={handleKeyDown}\n icon={<PencilIcon aria-hidden />}\n className={styles.iconButton}\n />\n )}\n <Button\n key=\"delete\"\n data-testid={`${id}-delete-button`}\n data-no-dnd=\"true\"\n type=\"button\"\n styleType=\"light\"\n sizeType=\"small\"\n aria-label={`delete ${name}`}\n disabled={shouldDisable()}\n onClick={handleDelete}\n onKeyDown={handleKeyDown}\n icon={<BinIcon aria-hidden />}\n className={styles.iconButton}\n />\n </>\n );\n }\n\n return (\n <div\n className={styles.actionContainer}\n data-mobile-layout={getActionContainerLayout()}\n >\n {content}\n </div>\n );\n };\n\n return (\n <li\n id={id}\n ref={setNodeRef}\n className={styles.item}\n data-item-state={getItemState()}\n data-testid={`${id}-item`}\n {...(shouldEnableSort() ? sortableProps : {})}\n >\n {shouldEnableSort() && (\n <DSDragHandleIcon\n data-testid={`${id}-drag-handle`}\n className={styles.dragHandleIcon}\n data-drag-handle-state={getDragHandleState()}\n />\n )}\n <div\n className={styles.box}\n data-box-state={getBoxState()}\n data-stack-mobile={!errorMessage && (isLoading || editable)}\n >\n {renderContents()}\n {!readOnly && !hasInlineActions && renderActions()}\n </div>\n </li>\n );\n};\n\nexport const FileListItem = memo(Component);\n"],"names":["FileListItem","memo","fileItem","editable","sortable","wrapperWidth","disabled","readOnly","descriptionLabel","onDelete","onEditClick","id","name","size","description","progress","errorMessage","thumbnailImageDataUrl","truncateText","formattedName","setFormattedName","useState","activeId","useContext","FileUploadContext","attributes","listeners","setNodeRef","transform","transition","useSortable","detailSectionRef","useRef","style","CSS","Translate","toString","sortableProps","isLoading","fileSize","FileUploadHelper","formatFileSizeDisplay","hasInlineActions","focusType","getTruncatedText","useCallback","value","widthOfElement","current","getBoundingClientRect","width","StringHelper","truncateOneLine","useEffect","handleDelete","handleEdit","handleKeyDown","event","stopPropagation","shouldDisable","shouldEnableSort","renderNameDescription","_jsxs","_Fragment","children","_jsx","Typography","BodyMD","weight","className","styles.itemDescriptionLabel","_a","styles.itemDescriptionText","Object","assign","ref","styles.item","DSDragHandleIcon","styles.dragHandleIcon","styles.box","shouldShowThumbnail","type","PDF_MIME_TYPE","content","styles.nameSection","BodySM","styles.desktopErrorMessage","ExclamationCircleFillIcon","styles.errorIcon","styles.fileSizeSection","styles.fileSizeText","styles.mobileErrorMessage","thumbnail","FileListItemThumbnail","fileType","styles.extendedNameSection","styles.descriptionFileSizeText","styles.inlineActionContainer","Button","styleType","sizeType","onClick","onKeyDown","icon","PencilIcon","styles.iconButton","BinIcon","renderFileContent","styles.contentSection","renderContents","ProgressBar","styles.actionContainer","renderActions"],"mappings":"+/CAgCA,MAkbaA,EAAeC,GAlbV,EACdC,WACAC,WACAC,WACAC,eACAC,WACAC,WACAC,mBACAC,WACAC,kBAKA,MAAMC,GACFA,EAAEC,KACFA,EAAIC,KACJA,EAAIC,YACJA,EAAWC,SACXA,EAAW,EAACC,aACZA,EAAYC,sBACZA,EAAqBC,aACrBA,IAAe,GACfhB,GACGiB,GAAeC,IAAoBC,KACpCC,SAAEA,IAAaC,EAAWC,IAG1BC,WAAEA,GAAUC,UAAEA,GAASC,WAAEA,GAAUC,UAAEA,GAASC,WAAEA,IAClDC,EAAY,CAAEnB,OACZoB,GAAmBC,EAAuB,MAC1CC,GAAQ,CACVL,UAAWM,EAAIC,UAAUC,SAASR,IAClCC,eAGEQ,gCACFJ,UACGR,IACAC,IAIDY,GAAYvB,EAAW,EACvBwB,GAAWC,EAAiBC,sBAAsB5B,GAClD6B,KAAqB5B,KAAiBX,EACtCwC,GAA2BrB,GAC3BA,KAAaX,EACT,OACA,SACJ,OAKAiC,GAAmBC,GACpBC,IACG,IAAK5B,GAAc,OAAO4B,EAE1B,MAAMC,EACFhB,IAAoBA,GAAiBiB,QAC/BjB,GAAiBiB,QAAQC,wBAAwBC,MACjD,EAEV,OAAOC,EAAaC,gBAChBN,EACAC,EACAA,EAAiB,EACjBA,EAAiB,EAAI,EACrB,GACH,GAEL,CAAC7B,KAMLmC,GAAU,KACNjC,GAAiBwB,GAAiBhC,GAAM,GACzC,CAACP,EAAcuC,GAAkBhC,IAKpC,MAAM0C,GAAe,KACjB7C,GAAU,EAGR8C,GAAa,KACX7C,GACAA,GACJ,EAGE8C,GAAiBC,IAKfrD,GACAqD,EAAMC,iBACV,EAGEC,GAAgB,IAAMrD,KAAcgB,GAEpCsC,GAAmB,MAAQxD,IAAaG,EA6DxCsD,GAAwB,WAAM,OAChCC,EAAAC,EAAA,CAAAC,SAAA,CACIC,EAACC,EAAWC,OAAM,CAACC,OAAQtD,EAAc,WAAa,UAASkD,SAC1D7C,KAEJL,GACGgD,EAAAC,EAAA,CAAAC,SAAA,CACIC,EAACC,EAAWC,QAAOE,UAAWC,EAA2BN,SAC1B,QAA1BO,EAAA/D,aAAgB,EAAhBA,EAAkBwD,gBAAQ,IAAAO,EAAAA,EAAI,sBAEnCN,EAACC,EAAWC,OAAM,CAACE,UAAWG,EAA0BR,SACnDlD,SAId,EA+NP,OACIgD,EAAA,KAAAW,OAAAC,OAAA,CACI/D,GAAIA,EACJgE,IAAKhD,GACL0C,UAAWO,oBA5SXjB,MAAiC,SAAdhB,GACZ,WAGPiB,MAAoC,SAAdjB,GACf,kBAGPiB,KACO,gBADX,gBAsSiB,GAAGjD,UACXiD,KAAqBvB,GAAgB,CAAA,EAAG,CAAA2B,SAAA,CAE5CJ,MACGK,EAACY,iBACgB,GAAGlE,gBAChB0D,UAAWS,EAAqB,yBApS1B,SAAdnC,GACO,SAGPgB,KACO,gBADX,IAoSIG,EAAA,MAAA,CACIO,UAAWU,EAAU,iBA7RX,SAAdpC,GACO,UAGPgB,KACO,WAGP3C,EACO,aADX,EAsRqC,qBACTA,IAAiBsB,IAAanC,GAAS6D,SAAA,CA7GhD,MACnB,MAAMgB,IACA/D,GACFf,EAAS+E,OAASzC,EAAiB0C,cAEjCC,EAAUnE,EAtIhB8C,EAAAC,EAAA,CAAAC,SAAA,CACIF,EAAA,MAAA,CAAKa,IAAK5C,GAAkBsC,UAAWe,EAAkBpB,SAAA,CACpDH,KACA7C,GACG8C,EAACI,EAAWmB,QACRhB,UAAWiB,EACXlB,OAAO,WAAUJ,SAAA,CAEjBC,EAACsB,EAAyB,CACtBlB,UAAWmB,EAAgB,eAAA,IAG9BxE,QAIbiD,EAAA,MAAA,CACII,UAAWoB,EAAsB,yBACTnD,GAAY,SAAW,SAAQ0B,SAEvDC,EAACC,EAAWC,OAAM,CAACE,UAAWqB,EAAmB1B,SAC5CzB,OAGRvB,GACG8C,EAACI,EAAWmB,OAAM,CACdhB,UAAWsB,EACXvB,OAAO,WAAUJ,SAAA,CAEjBC,EAACsB,EAAyB,CACtBlB,UAAWmB,EAAgB,eAAA,IAG9BxE,QAyDS,CAACC,IACvB,MAIM2E,EAHA3E,GACFf,EAAS+E,OAASzC,EAAiB0C,cAGnCjB,EAAC4B,EAAqB,CAClB5E,sBAAuBA,GAAyB,GAChD6E,SAAU5F,EAAS+E,mBACN,GAAGtE,gBAEpB,KAEJ,OAEQmD,IAFJpB,cAGSkD,EAjCb9B,EAAA,MAAA,CAAKa,IAAK5C,GAAkBsC,UAAW0B,YACnC9B,EAACC,EAAWC,OAAM,CAACC,OAAO,WAAUJ,SAC/B7C,KAEL8C,EAACC,EAAWC,QAAOE,UAAWC,EAA2BN,SAC1B,QAA1BO,EAAA/D,eAAAA,EAAkBwD,gBAAQ,IAAAO,EAAAA,EAAI,sBAEnCN,EAACC,EAAWC,OAAM,CAACE,UAAWG,EAA0BR,SACnDlD,IAELmD,EAACC,EAAWC,OAAM,CAACE,UAAW2B,EAA8BhC,SACvDzB,MAEHhC,GAAYmC,IA9ClBoB,EAAA,MAAA,CAAKO,UAAW4B,EAA4BjC,SAAA,CACxCC,EAACiC,EAAM,CAAA,cAEU,GAAGvF,gBAAgB,cACpB,OACZsE,KAAK,SACLkB,UAAU,QACVC,SAAS,QAAO,aACJ,QAAQxF,IACpBN,SAAUqD,KACV0C,QAAS9C,GACT+C,UAAW9C,GACX+C,KAAMtC,EAACuC,EAAU,CAAA,eAAA,IACjBnC,UAAWoC,GAXP,QAaRxC,EAACiC,EAAM,CAAA,cAEU,GAAGvF,kBAAkB,cACtB,OACZsE,KAAK,SACLkB,UAAU,QACVC,SAAS,QAAO,aACJ,UAAUxF,IACtBN,SAAUqD,KACV0C,QAAS/C,GACTgD,UAAW9C,GACX+C,KAAMtC,EAACyC,EAAO,CAAA,eAAA,IACdrC,UAAWoC,GAXP,kBAyDR,CAAAzC,SAAA,CACK4B,EACD9B,EAAA,MAAA,CAAKa,IAAK5C,GAAkBsC,UAAWe,EAAkBpB,SAAA,CACpDH,MACCvB,IACE2B,EAACC,EAAWC,OAAM,CACdE,UAAW2B,WAEVzD,WAjDQ,KAqDtB,EAWDoE,CAAkB1F,GAExB,OACIgD,EAAA,MAAA,CACII,UAAWuC,EAAqB,qBACZ5B,EAAmBhB,SAEtCmB,GACC,EAgGD0B,IACCtG,IAAamC,IA7FL,MAClB,IAAIyC,EA4DJ,OAzDIA,EADAnE,EAEIiD,EAACiC,iBACgB,GAAGvF,wBAAwB,cAC5B,OACZsE,KAAK,SACLkB,UAAU,QACVC,SAAS,QAAO,aACJ,UAAUxF,aAAgBI,IACtCqF,QAAS/C,GACTe,UAAWoC,EACXF,KAAMtC,EAACyC,EAAO,CAAA,eAAA,MAGfpE,GAEH2B,EAAC6C,GACG/F,SAAUA,EAAQ,cACL,GAAGJ,mBAKpBmD,EAAAC,EAAA,CAAAC,SAAA,CACK7D,GACG8D,EAACiC,EAAM,CAAA,cAEU,GAAGvF,8BACJ,OACZsE,KAAK,SACLkB,UAAU,QACVC,SAAS,QAAO,aACJ,QAAQxF,IACpBN,SAAUqD,KACV0C,QAAS9C,GACT+C,UAAW9C,GACX+C,KAAMtC,EAACuC,EAAU,CAAA,eAAA,IACjBnC,UAAWoC,GAXP,QAcZxC,EAACiC,EAAM,CAAA,cAEU,GAAGvF,kBAAkB,cACtB,OACZsE,KAAK,SACLkB,UAAU,QACVC,SAAS,QAAO,aACJ,UAAUxF,IACtBN,SAAUqD,KACV0C,QAAS/C,GACTgD,UAAW9C,GACX+C,KAAMtC,EAACyC,EAAO,CAAA,eAAA,IACdrC,UAAWoC,GAXP,aAkBhBxC,EAAA,MAAA,CACII,UAAW0C,EAAsB,sBApPpC/F,GAAgBsB,GACV,WAGNtB,GAAgBb,EACV,gBADX,EAiPsD6D,SAE7CmB,GACC,EA0BiC6B,SAEtC"}