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

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 (445) hide show
  1. package/accordion/types.d.ts +1 -1
  2. package/breadcrumb/breadcrumb.d.ts +7 -0
  3. package/breadcrumb/breadcrumb.js.map +1 -1
  4. package/breadcrumb/types.d.ts +31 -0
  5. package/button/button.d.ts +1 -0
  6. package/button/button.js.map +1 -1
  7. package/button/types.d.ts +42 -9
  8. package/calendar/calendar.d.ts +3 -0
  9. package/calendar/calendar.js.map +1 -1
  10. package/calendar/types.d.ts +43 -7
  11. package/card/card.d.ts +1 -0
  12. package/card/card.js.map +1 -1
  13. package/card/types.d.ts +1 -0
  14. package/checkbox/checkbox.d.ts +3 -0
  15. package/checkbox/checkbox.js.map +1 -1
  16. package/checkbox/types.d.ts +19 -3
  17. package/cjs/breadcrumb/breadcrumb.js.map +1 -1
  18. package/cjs/button/button.js.map +1 -1
  19. package/cjs/calendar/calendar.js.map +1 -1
  20. package/cjs/card/card.js.map +1 -1
  21. package/cjs/checkbox/checkbox.js.map +1 -1
  22. package/cjs/data-table/data-table.js +1 -1
  23. package/cjs/data-table/data-table.js.map +1 -1
  24. package/cjs/data-table/data-table.styles.js +1 -1
  25. package/cjs/data-table/data-table.styles.js.map +1 -1
  26. package/cjs/data-table/data-table.styles_rxganh.css +27 -0
  27. package/cjs/external/dompurify/dist/purify.es.js +2 -2
  28. package/cjs/external/dompurify/dist/purify.es.js.map +1 -1
  29. package/cjs/external/lodash/_setCacheHas.js.map +1 -1
  30. package/cjs/external/lodash/lodash.js +1 -1
  31. package/cjs/external/lodash/lodash.js.map +1 -1
  32. package/cjs/form/form-label-addon.js +1 -1
  33. package/cjs/form/form-label-addon.js.map +1 -1
  34. package/cjs/form/index.js +1 -1
  35. package/cjs/form/index.js.map +1 -1
  36. package/cjs/fullscreen-image-carousel/fullscreen-image-carousel.js +1 -1
  37. package/cjs/fullscreen-image-carousel/fullscreen-image-carousel.js.map +1 -1
  38. package/cjs/histogram-slider/histogram-slider.js.map +1 -1
  39. package/cjs/image-button/image-button.js.map +1 -1
  40. package/cjs/index.js +1 -1
  41. package/cjs/input/input.js.map +1 -1
  42. package/cjs/input-group/input-group.js.map +1 -1
  43. package/cjs/input-multi-select/input-multi-select.js.map +1 -1
  44. package/cjs/input-nested-multi-select/input-nested-multi-select.js.map +1 -1
  45. package/cjs/input-nested-select/input-nested-select.js.map +1 -1
  46. package/cjs/input-range-select/input-range-select.js.map +1 -1
  47. package/cjs/input-range-slider/input-range-slider.js.map +1 -1
  48. package/cjs/input-select/input-select.js.map +1 -1
  49. package/cjs/input-slider/input-slider.js.map +1 -1
  50. package/cjs/input-textarea/textarea.js.map +1 -1
  51. package/cjs/language-switcher/language-switcher.js.map +1 -1
  52. package/cjs/layout/index.js +1 -1
  53. package/cjs/layout/index.js.map +1 -1
  54. package/cjs/link-list/link-list.js.map +1 -1
  55. package/cjs/local-nav/local-nav-dropdown/local-nav-dropdown.js.map +1 -1
  56. package/cjs/local-nav/local-nav-menu/local-nav-menu.js.map +1 -1
  57. package/cjs/markup/markup.js.map +1 -1
  58. package/cjs/masked-input/masked-input.js.map +1 -1
  59. package/cjs/masthead/masthead.js.map +1 -1
  60. package/cjs/menu/menu.js +1 -1
  61. package/cjs/menu/menu.js.map +1 -1
  62. package/cjs/modal/index.js.map +1 -1
  63. package/cjs/modal/modal-box.js +1 -1
  64. package/cjs/modal/modal-box.js.map +1 -1
  65. package/cjs/modal-v2/index.js +1 -1
  66. package/cjs/modal-v2/index.js.map +1 -1
  67. package/cjs/modal-v2/modal-v2.js +1 -1
  68. package/cjs/modal-v2/modal-v2.js.map +1 -1
  69. package/cjs/modal-v2/slots/card.js +1 -1
  70. package/cjs/modal-v2/slots/card.js.map +1 -1
  71. package/cjs/navbar/navbar.js.map +1 -1
  72. package/cjs/notification-banner/notification-banner-hoc.js.map +1 -1
  73. package/cjs/notification-banner/notification-banner.js.map +1 -1
  74. package/cjs/otp-input/otp-input.js.map +1 -1
  75. package/cjs/otp-verification/otp-verification.js.map +1 -1
  76. package/cjs/overlay/overlay.js.map +1 -1
  77. package/cjs/pagination/pagination.js.map +1 -1
  78. package/cjs/phone-number-input/phone-number-input.js.map +1 -1
  79. package/cjs/pill/pill.js.map +1 -1
  80. package/cjs/popover/popover-inline/popover-inline.js.map +1 -1
  81. package/cjs/popover/popover-trigger.js.map +1 -1
  82. package/cjs/popover/popover.js +1 -1
  83. package/cjs/popover/popover.js.map +1 -1
  84. package/cjs/predictive-text-input/predictive-text-input.js.map +1 -1
  85. package/cjs/progress-indicator/progress-indicator.js.map +1 -1
  86. package/cjs/radio-button/radio-button.js.map +1 -1
  87. package/cjs/schedule/schedule.js.map +1 -1
  88. package/cjs/schedule/shared/with-optional-popover.js +1 -1
  89. package/cjs/schedule/shared/with-optional-popover.js.map +1 -1
  90. package/cjs/select-histogram/select-histogram.js.map +1 -1
  91. package/cjs/sidenav/sidenav.js.map +1 -1
  92. package/cjs/singpass-button/singpass-button.js.map +1 -1
  93. package/cjs/smart-app-banner/smart-app-banner.js.map +1 -1
  94. package/cjs/tab/tab.js.map +1 -1
  95. package/cjs/table/table.js.map +1 -1
  96. package/cjs/table/table.styles.js +1 -1
  97. package/cjs/table/table.styles.js.map +1 -1
  98. package/{table/table.styles_1af5ipv.css → cjs/table/table.styles_1vjx31g.css} +1 -1
  99. package/cjs/tag/tag.js.map +1 -1
  100. package/cjs/text-list/index.js.map +1 -1
  101. package/cjs/theme/theme-provider/breakpoint.js +1 -1
  102. package/cjs/theme/theme-provider/breakpoint.js.map +1 -1
  103. package/cjs/theme/theme-provider/hooks.js.map +1 -1
  104. package/cjs/theme/theme-provider/index.js.map +1 -1
  105. package/cjs/theme/tokens/border.js.map +1 -1
  106. package/cjs/theme/tokens/breakpoint.js.map +1 -1
  107. package/cjs/theme/tokens/colour.js.map +1 -1
  108. package/cjs/theme/tokens/component.js.map +1 -1
  109. package/cjs/theme/tokens/font.js.map +1 -1
  110. package/cjs/theme/tokens/media-query.js.map +1 -1
  111. package/cjs/theme/tokens/motion.js.map +1 -1
  112. package/cjs/theme/tokens/radius.js.map +1 -1
  113. package/cjs/theme/tokens/shadow.js.map +1 -1
  114. package/cjs/theme/tokens/spacing.js.map +1 -1
  115. package/cjs/theme/types.js.map +1 -1
  116. package/cjs/theme/utils/css-variable.js.map +1 -1
  117. package/cjs/theme/utils/font.js.map +1 -1
  118. package/cjs/theme/utils/use-apply-styles.js +1 -1
  119. package/cjs/theme/utils/use-apply-styles.js.map +1 -1
  120. package/cjs/theme/utils/use-design-token-override.js.map +1 -1
  121. package/cjs/theme/utils/use-design-token.js.map +1 -1
  122. package/cjs/theme/utils/use-media-query.js.map +1 -1
  123. package/cjs/time-range-picker/combobox-picker/combobox-picker.js +1 -1
  124. package/cjs/time-range-picker/combobox-picker/combobox-picker.js.map +1 -1
  125. package/cjs/time-range-picker/common.styles.js +1 -1
  126. package/cjs/time-range-picker/common.styles.js.map +1 -1
  127. package/{time-range-picker/common.styles_1qwp4xa.css → cjs/time-range-picker/common.styles_cnkkax.css} +2 -1
  128. package/cjs/time-range-picker/dial-picker/dial-picker.js +1 -1
  129. package/cjs/time-range-picker/dial-picker/dial-picker.js.map +1 -1
  130. package/cjs/time-range-picker/time-range-picker.js.map +1 -1
  131. package/cjs/time-slot-bar/time-slot-bar.js.map +1 -1
  132. package/cjs/time-slot-bar-week/time-slot-bar-week.js.map +1 -1
  133. package/cjs/time-slot-week-view/time-slot-week-view.js.map +1 -1
  134. package/cjs/timeline/timeline.js.map +1 -1
  135. package/cjs/timepicker/timepicker.js +1 -1
  136. package/cjs/timepicker/timepicker.js.map +1 -1
  137. package/cjs/timepicker/timepicker.styles.js +1 -1
  138. package/cjs/timepicker/timepicker.styles.js.map +1 -1
  139. package/cjs/timepicker/timepicker.styles_lyizvq.css +2 -0
  140. package/cjs/timetable/timetable-row/with-optional-popover.js +1 -1
  141. package/cjs/timetable/timetable-row/with-optional-popover.js.map +1 -1
  142. package/cjs/timetable/timetable.js +1 -1
  143. package/cjs/timetable/timetable.js.map +1 -1
  144. package/cjs/toast/toast.js.map +1 -1
  145. package/cjs/toggle/toggle.js.map +1 -1
  146. package/cjs/typography/index.js.map +1 -1
  147. package/cjs/uneditable-section/index.js.map +1 -1
  148. package/cjs/unit-number/unit-number-input.js.map +1 -1
  149. package/cjs/util/merge-refs.js.map +1 -1
  150. package/cjs/util/use-throttle.js +2 -0
  151. package/cjs/util/use-throttle.js.map +1 -0
  152. package/countdown-timer/types.d.ts +3 -3
  153. package/data-table/data-table.js +1 -1
  154. package/data-table/data-table.js.map +1 -1
  155. package/data-table/data-table.styles.d.ts +2 -1
  156. package/data-table/data-table.styles.js +1 -1
  157. package/data-table/data-table.styles.js.map +1 -1
  158. package/data-table/data-table.styles_rxganh.css +27 -0
  159. package/date-range-input/types.d.ts +1 -1
  160. package/drawer/types.d.ts +1 -1
  161. package/e-signature/types.d.ts +1 -1
  162. package/external/dompurify/dist/purify.es.js +2 -2
  163. package/external/dompurify/dist/purify.es.js.map +1 -1
  164. package/external/lodash/_setCacheHas.js.map +1 -1
  165. package/external/lodash/lodash.js +1 -1
  166. package/external/lodash/lodash.js.map +1 -1
  167. package/file-upload/types.d.ts +0 -1
  168. package/filter/types.d.ts +6 -10
  169. package/form/form-label-addon.js +1 -1
  170. package/form/form-label-addon.js.map +1 -1
  171. package/form/index.d.ts +65 -8
  172. package/form/index.js +1 -1
  173. package/form/index.js.map +1 -1
  174. package/form/types.d.ts +155 -6
  175. package/fullscreen-image-carousel/fullscreen-image-carousel.d.ts +7 -0
  176. package/fullscreen-image-carousel/fullscreen-image-carousel.js +1 -1
  177. package/fullscreen-image-carousel/fullscreen-image-carousel.js.map +1 -1
  178. package/fullscreen-image-carousel/types.d.ts +91 -3
  179. package/histogram-slider/histogram-slider.d.ts +6 -0
  180. package/histogram-slider/histogram-slider.js.map +1 -1
  181. package/histogram-slider/types.d.ts +63 -3
  182. package/image-button/image-button.d.ts +6 -0
  183. package/image-button/image-button.js.map +1 -1
  184. package/image-button/types.d.ts +11 -1
  185. package/index.js +1 -1
  186. package/input/input.d.ts +6 -0
  187. package/input/input.js.map +1 -1
  188. package/input/types.d.ts +38 -2
  189. package/input-group/input-group.d.ts +7 -0
  190. package/input-group/input-group.js.map +1 -1
  191. package/input-group/types.d.ts +84 -8
  192. package/input-multi-select/input-multi-select.d.ts +6 -0
  193. package/input-multi-select/input-multi-select.js.map +1 -1
  194. package/input-multi-select/types.d.ts +46 -5
  195. package/input-nested-multi-select/input-nested-multi-select.d.ts +8 -0
  196. package/input-nested-multi-select/input-nested-multi-select.js.map +1 -1
  197. package/input-nested-multi-select/types.d.ts +35 -5
  198. package/input-nested-select/input-nested-select.d.ts +9 -2
  199. package/input-nested-select/input-nested-select.js.map +1 -1
  200. package/input-nested-select/types.d.ts +77 -8
  201. package/input-range-select/input-range-select.d.ts +6 -0
  202. package/input-range-select/input-range-select.js.map +1 -1
  203. package/input-range-select/types.d.ts +68 -1
  204. package/input-range-slider/input-range-slider.d.ts +7 -0
  205. package/input-range-slider/input-range-slider.js.map +1 -1
  206. package/input-range-slider/types.d.ts +91 -6
  207. package/input-select/input-select.d.ts +5 -0
  208. package/input-select/input-select.js.map +1 -1
  209. package/input-select/types.d.ts +70 -14
  210. package/input-slider/input-slider.d.ts +6 -0
  211. package/input-slider/input-slider.js.map +1 -1
  212. package/input-slider/types.d.ts +21 -2
  213. package/input-textarea/textarea.d.ts +3 -0
  214. package/input-textarea/textarea.js.map +1 -1
  215. package/input-textarea/types.d.ts +24 -1
  216. package/language-switcher/language-switcher.d.ts +6 -0
  217. package/language-switcher/language-switcher.js.map +1 -1
  218. package/language-switcher/types.d.ts +23 -0
  219. package/layout/index.d.ts +16 -2
  220. package/layout/index.js +1 -1
  221. package/layout/index.js.map +1 -1
  222. package/layout/types.d.ts +61 -3
  223. package/link-list/internal-types.d.ts +57 -3
  224. package/link-list/link-list.d.ts +6 -0
  225. package/link-list/link-list.js.map +1 -1
  226. package/link-list/types.d.ts +3 -0
  227. package/local-nav/local-nav-dropdown/local-nav-dropdown.d.ts +11 -0
  228. package/local-nav/local-nav-dropdown/local-nav-dropdown.js.map +1 -1
  229. package/local-nav/local-nav-menu/local-nav-menu.d.ts +6 -0
  230. package/local-nav/local-nav-menu/local-nav-menu.js.map +1 -1
  231. package/local-nav/types.d.ts +51 -0
  232. package/markup/markup.d.ts +6 -0
  233. package/markup/markup.js.map +1 -1
  234. package/markup/types.d.ts +6 -2
  235. package/masked-input/masked-input.d.ts +6 -0
  236. package/masked-input/masked-input.js.map +1 -1
  237. package/masked-input/types.d.ts +83 -8
  238. package/masthead/masthead.d.ts +6 -0
  239. package/masthead/masthead.js.map +1 -1
  240. package/masthead/types.d.ts +9 -0
  241. package/menu/menu.d.ts +27 -4
  242. package/menu/menu.js +1 -1
  243. package/menu/menu.js.map +1 -1
  244. package/menu/types.d.ts +32 -0
  245. package/modal/index.d.ts +13 -0
  246. package/modal/index.js.map +1 -1
  247. package/modal/modal-box.js +1 -1
  248. package/modal/modal-box.js.map +1 -1
  249. package/modal/types.d.ts +54 -7
  250. package/modal-v2/index.d.ts +1 -15
  251. package/modal-v2/index.js +1 -1
  252. package/modal-v2/index.js.map +1 -1
  253. package/modal-v2/modal-v2.d.ts +32 -1
  254. package/modal-v2/modal-v2.js +1 -1
  255. package/modal-v2/modal-v2.js.map +1 -1
  256. package/modal-v2/slots/card.js +1 -1
  257. package/modal-v2/slots/card.js.map +1 -1
  258. package/modal-v2/types.d.ts +75 -8
  259. package/navbar/navbar.d.ts +7 -0
  260. package/navbar/navbar.js.map +1 -1
  261. package/navbar/types.d.ts +200 -13
  262. package/notification-banner/notification-banner-hoc.d.ts +6 -0
  263. package/notification-banner/notification-banner-hoc.js.map +1 -1
  264. package/notification-banner/notification-banner.d.ts +7 -0
  265. package/notification-banner/notification-banner.js.map +1 -1
  266. package/notification-banner/types.d.ts +57 -2
  267. package/otp-input/otp-input.d.ts +7 -0
  268. package/otp-input/otp-input.js.map +1 -1
  269. package/otp-input/types.d.ts +54 -11
  270. package/otp-verification/internal-types.d.ts +22 -5
  271. package/otp-verification/otp-verification.d.ts +6 -0
  272. package/otp-verification/otp-verification.js.map +1 -1
  273. package/otp-verification/types.d.ts +125 -6
  274. package/overlay/overlay.d.ts +7 -0
  275. package/overlay/overlay.js.map +1 -1
  276. package/overlay/types.d.ts +57 -2
  277. package/package.json +1 -1
  278. package/pagination/pagination.d.ts +5 -0
  279. package/pagination/pagination.js.map +1 -1
  280. package/pagination/types.d.ts +48 -0
  281. package/phone-number-input/phone-number-input.d.ts +7 -0
  282. package/phone-number-input/phone-number-input.js.map +1 -1
  283. package/phone-number-input/types.d.ts +78 -13
  284. package/pill/pill.d.ts +6 -0
  285. package/pill/pill.js.map +1 -1
  286. package/pill/types.d.ts +19 -0
  287. package/popover/popover-inline/popover-inline.d.ts +5 -0
  288. package/popover/popover-inline/popover-inline.js.map +1 -1
  289. package/popover/popover-trigger.d.ts +6 -0
  290. package/popover/popover-trigger.js.map +1 -1
  291. package/popover/popover.d.ts +6 -0
  292. package/popover/popover.js +1 -1
  293. package/popover/popover.js.map +1 -1
  294. package/popover/types.d.ts +150 -3
  295. package/predictive-text-input/predictive-text-input.d.ts +6 -0
  296. package/predictive-text-input/predictive-text-input.js.map +1 -1
  297. package/predictive-text-input/types.d.ts +65 -11
  298. package/progress-indicator/progress-indicator.d.ts +7 -0
  299. package/progress-indicator/progress-indicator.js.map +1 -1
  300. package/progress-indicator/types.d.ts +18 -0
  301. package/radio-button/radio-button.d.ts +5 -0
  302. package/radio-button/radio-button.js.map +1 -1
  303. package/radio-button/types.d.ts +11 -0
  304. package/schedule/internal-types.d.ts +18 -0
  305. package/schedule/schedule-day-view/types.d.ts +2 -1
  306. package/schedule/schedule-week-view/types.d.ts +2 -1
  307. package/schedule/schedule.d.ts +3 -0
  308. package/schedule/schedule.js.map +1 -1
  309. package/schedule/shared/with-optional-popover.js +1 -1
  310. package/schedule/shared/with-optional-popover.js.map +1 -1
  311. package/schedule/types.d.ts +129 -10
  312. package/select-histogram/select-histogram.d.ts +5 -0
  313. package/select-histogram/select-histogram.js.map +1 -1
  314. package/select-histogram/types.d.ts +57 -4
  315. package/shared/dropdown-list/types.d.ts +52 -19
  316. package/shared/dropdown-wrapper/types.d.ts +6 -0
  317. package/sidenav/sidenav.d.ts +10 -0
  318. package/sidenav/sidenav.js.map +1 -1
  319. package/sidenav/types.d.ts +70 -21
  320. package/singpass-button/singpass-button.d.ts +6 -0
  321. package/singpass-button/singpass-button.js.map +1 -1
  322. package/singpass-button/types.d.ts +29 -2
  323. package/smart-app-banner/smart-app-banner.d.ts +5 -0
  324. package/smart-app-banner/smart-app-banner.js.map +1 -1
  325. package/smart-app-banner/types.d.ts +54 -0
  326. package/tab/tab.d.ts +7 -0
  327. package/tab/tab.js.map +1 -1
  328. package/tab/types.d.ts +55 -6
  329. package/table/table.d.ts +21 -0
  330. package/table/table.js.map +1 -1
  331. package/table/table.styles.js +1 -1
  332. package/table/table.styles.js.map +1 -1
  333. package/{cjs/table/table.styles_1af5ipv.css → table/table.styles_1vjx31g.css} +1 -1
  334. package/tag/tag.d.ts +5 -0
  335. package/tag/tag.js.map +1 -1
  336. package/tag/types.d.ts +24 -0
  337. package/text-list/index.d.ts +17 -0
  338. package/text-list/index.js.map +1 -1
  339. package/text-list/types.d.ts +33 -4
  340. package/theme/theme-provider/breakpoint.d.ts +0 -1
  341. package/theme/theme-provider/breakpoint.js +1 -1
  342. package/theme/theme-provider/breakpoint.js.map +1 -1
  343. package/theme/theme-provider/hooks.d.ts +16 -0
  344. package/theme/theme-provider/hooks.js.map +1 -1
  345. package/theme/theme-provider/index.d.ts +7 -0
  346. package/theme/theme-provider/index.js.map +1 -1
  347. package/theme/theme-provider/types.d.ts +14 -0
  348. package/theme/tokens/border.d.ts +3 -0
  349. package/theme/tokens/border.js.map +1 -1
  350. package/theme/tokens/breakpoint.d.ts +3 -0
  351. package/theme/tokens/breakpoint.js.map +1 -1
  352. package/theme/tokens/colour.d.ts +3 -0
  353. package/theme/tokens/colour.js.map +1 -1
  354. package/theme/tokens/component.d.ts +1 -0
  355. package/theme/tokens/component.js.map +1 -1
  356. package/theme/tokens/font.d.ts +2 -0
  357. package/theme/tokens/font.js.map +1 -1
  358. package/theme/tokens/media-query.d.ts +1 -0
  359. package/theme/tokens/media-query.js.map +1 -1
  360. package/theme/tokens/motion.d.ts +1 -0
  361. package/theme/tokens/motion.js.map +1 -1
  362. package/theme/tokens/radius.d.ts +1 -0
  363. package/theme/tokens/radius.js.map +1 -1
  364. package/theme/tokens/shadow.d.ts +1 -0
  365. package/theme/tokens/shadow.js.map +1 -1
  366. package/theme/tokens/spacing.d.ts +1 -0
  367. package/theme/tokens/spacing.js.map +1 -1
  368. package/theme/types.d.ts +23 -3
  369. package/theme/types.js.map +1 -1
  370. package/theme/utils/css-variable.d.ts +10 -2
  371. package/theme/utils/css-variable.js.map +1 -1
  372. package/theme/utils/font.d.ts +2 -1
  373. package/theme/utils/font.js.map +1 -1
  374. package/theme/utils/use-apply-styles.d.ts +8 -2
  375. package/theme/utils/use-apply-styles.js +1 -1
  376. package/theme/utils/use-apply-styles.js.map +1 -1
  377. package/theme/utils/use-design-token-override.d.ts +9 -1
  378. package/theme/utils/use-design-token-override.js.map +1 -1
  379. package/theme/utils/use-design-token.d.ts +9 -0
  380. package/theme/utils/use-design-token.js.map +1 -1
  381. package/theme/utils/use-media-query.d.ts +41 -3
  382. package/theme/utils/use-media-query.js.map +1 -1
  383. package/time-range-picker/combobox-picker/combobox-picker.js +1 -1
  384. package/time-range-picker/combobox-picker/combobox-picker.js.map +1 -1
  385. package/time-range-picker/common.styles.d.ts +1 -0
  386. package/time-range-picker/common.styles.js +1 -1
  387. package/time-range-picker/common.styles.js.map +1 -1
  388. package/{cjs/time-range-picker/common.styles_1qwp4xa.css → time-range-picker/common.styles_cnkkax.css} +2 -1
  389. package/time-range-picker/dial-picker/dial-picker.js +1 -1
  390. package/time-range-picker/dial-picker/dial-picker.js.map +1 -1
  391. package/time-range-picker/time-range-picker.d.ts +5 -0
  392. package/time-range-picker/time-range-picker.js.map +1 -1
  393. package/time-range-picker/types.d.ts +85 -25
  394. package/time-slot-bar/internal-types.d.ts +1 -0
  395. package/time-slot-bar/time-slot-bar.d.ts +7 -0
  396. package/time-slot-bar/time-slot-bar.js.map +1 -1
  397. package/time-slot-bar/types.d.ts +112 -20
  398. package/time-slot-bar-week/time-slot-bar-week.d.ts +8 -0
  399. package/time-slot-bar-week/time-slot-bar-week.js.map +1 -1
  400. package/time-slot-bar-week/types.d.ts +74 -13
  401. package/time-slot-week-view/time-slot-week-view.d.ts +7 -0
  402. package/time-slot-week-view/time-slot-week-view.js.map +1 -1
  403. package/time-slot-week-view/types.d.ts +53 -10
  404. package/timeline/timeline.d.ts +6 -0
  405. package/timeline/timeline.js.map +1 -1
  406. package/timeline/types.d.ts +58 -4
  407. package/timepicker/timepicker.d.ts +5 -0
  408. package/timepicker/timepicker.js +1 -1
  409. package/timepicker/timepicker.js.map +1 -1
  410. package/timepicker/timepicker.styles.d.ts +1 -0
  411. package/timepicker/timepicker.styles.js +1 -1
  412. package/timepicker/timepicker.styles.js.map +1 -1
  413. package/timepicker/timepicker.styles_lyizvq.css +2 -0
  414. package/timepicker/types.d.ts +49 -14
  415. package/timetable/timetable-row/with-optional-popover.js +1 -1
  416. package/timetable/timetable-row/with-optional-popover.js.map +1 -1
  417. package/timetable/timetable.d.ts +6 -0
  418. package/timetable/timetable.js +1 -1
  419. package/timetable/timetable.js.map +1 -1
  420. package/timetable/types.d.ts +175 -50
  421. package/toast/toast.d.ts +6 -0
  422. package/toast/toast.js.map +1 -1
  423. package/toast/types.d.ts +42 -8
  424. package/toggle/toggle.d.ts +6 -0
  425. package/toggle/toggle.js.map +1 -1
  426. package/toggle/types.d.ts +95 -17
  427. package/typography/index.d.ts +29 -0
  428. package/typography/index.js.map +1 -1
  429. package/typography/types.d.ts +51 -8
  430. package/uneditable-section/index.d.ts +15 -0
  431. package/uneditable-section/index.js.map +1 -1
  432. package/uneditable-section/types.d.ts +66 -23
  433. package/unit-number/types.d.ts +30 -4
  434. package/unit-number/unit-number-input.d.ts +6 -0
  435. package/unit-number/unit-number-input.js.map +1 -1
  436. package/util/index.d.ts +1 -0
  437. package/util/merge-refs.d.ts +1 -1
  438. package/util/merge-refs.js.map +1 -1
  439. package/util/use-throttle.d.ts +1 -0
  440. package/util/use-throttle.js +2 -0
  441. package/util/use-throttle.js.map +1 -0
  442. package/cjs/data-table/data-table.styles_1iqq1g7.css +0 -26
  443. package/cjs/timepicker/timepicker.styles_1jm33yw.css +0 -1
  444. package/data-table/data-table.styles_1iqq1g7.css +0 -26
  445. package/timepicker/timepicker.styles_1jm33yw.css +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"card.js","sources":["../../../../src/modal-v2/slots/card.tsx"],"sourcesContent":["import clsx from \"clsx\";\nimport type { NamedExoticComponent } from \"react\";\nimport React from \"react\";\n\nimport isStyledComponent from \"../../util/is-styled-components\";\nimport type { ModalCardProps } from \"../types\";\nimport { CloseButton } from \"./close-button\";\nimport { Content } from \"./content\";\nimport { Footer } from \"./footer\";\nimport * as styles from \"./slot-styles\";\n\nfunction CardInner(\n {\n id,\n \"data-testid\": testId = \"modal-card\",\n children,\n className,\n ...otherProps\n }: ModalCardProps,\n ref: React.ForwardedRef<HTMLDivElement>\n) {\n // =============================================================================\n // EVENT HANDLERS\n // =============================================================================\n const handleOnClick = (event: React.MouseEvent) => {\n event.stopPropagation();\n };\n\n // =========================================================================\n // HELPERS\n // =========================================================================\n const isComponentType = (child: React.ReactPortal, type: any) =>\n isStyledComponent(child.type)\n ? (child.type as unknown as { target: any }).target === type\n : child.type === type;\n\n const findComponentOfType = (type: any) => {\n return React.Children.toArray(children).find((child) =>\n isComponentType(child as React.ReactPortal, type)\n );\n };\n\n // =============================================================================\n // RENDER FUNCTIONS\n // =============================================================================\n const CloseButtonSlot = findComponentOfType(CloseButton);\n const ContentSlot = findComponentOfType(Content);\n const FooterSlot = findComponentOfType(Footer);\n\n const hasCloseButton = !!CloseButtonSlot;\n\n return (\n <div\n ref={ref}\n id={id}\n data-testid={testId}\n {...otherProps}\n onClick={handleOnClick}\n className={clsx(styles.modalCard, className)}\n >\n <div\n data-has-close-button={hasCloseButton ? \"true\" : \"false\"}\n className={clsx(styles.slotSpacer)}\n >\n {ContentSlot}\n {FooterSlot}\n </div>\n {hasCloseButton && CloseButtonSlot}\n </div>\n );\n}\n\nexport const Card = React.forwardRef<HTMLDivElement, ModalCardProps>(CardInner);\n\n(Card as NamedExoticComponent).displayName = \"ModalV2.Card\";\n"],"names":["Card","React","forwardRef","_a","ref","id","testId","children","className","otherProps","__rest","findComponentOfType","type","Children","toArray","find","child","isStyledComponent","target","isComponentType","CloseButtonSlot","CloseButton","ContentSlot","Content","FooterSlot","Footer","hasCloseButton","_jsxs","Object","assign","onClick","event","stopPropagation","clsx","styles.modalCard","styles.slotSpacer","displayName"],"mappings":"qXAwEO,MAAMA,EAAOC,EAAAA,QAAMC,YA7D1B,SACIC,EAOAC,GAPA,IAAAC,GACIA,EACA,cAAeC,EAAS,aAAYC,SACpCA,EAAQC,UACRA,GAASL,EACNM,EAAUC,EAAAA,OAAAP,EALjB,6CAYA,MAYMQ,EAAuBC,GAClBX,UAAMY,SAASC,QAAQP,GAAUQ,MAAMC,GAN1B,EAACA,EAA0BJ,IAC/CK,EAAAA,QAAkBD,EAAMJ,MACjBI,EAAMJ,KAAoCM,SAAWN,EACtDI,EAAMJ,OAASA,EAIjBO,CAAgBH,EAA4BJ,KAO9CQ,EAAkBT,EAAoBU,eACtCC,EAAcX,EAAoBY,WAClCC,EAAab,EAAoBc,UAEjCC,IAAmBN,EAEzB,OACIO,EAAAA,KAAA,MAAAC,OAAAC,OAAA,CACIzB,IAAKA,EACLC,GAAIA,EAAE,cACOC,GACTG,EAAU,CACdqB,QAjCeC,IACnBA,EAAMC,iBAAiB,EAiCnBxB,UAAWyB,EAAAA,QAAKC,EAAAA,UAAkB1B,GAAUD,SAAA,CAE5CoB,EAAAA,KAAA,MAAA,CAAA,wBAC2BD,EAAiB,OAAS,QACjDlB,UAAWyB,EAAAA,QAAKE,EAAAA,YAAkB5B,SAAA,CAEjCe,EACAE,KAEJE,GAAkBN,KAG/B,IAICpB,EAA8BoC,YAAc"}
1
+ {"version":3,"file":"card.js","sources":["../../../../src/modal-v2/slots/card.tsx"],"sourcesContent":["import clsx from \"clsx\";\nimport type { NamedExoticComponent } from \"react\";\nimport React from \"react\";\n\nimport { mergeRefs } from \"../../util\";\nimport isStyledComponent from \"../../util/is-styled-components\";\nimport type { ModalCardProps } from \"../types\";\nimport { CloseButton } from \"./close-button\";\nimport { Content } from \"./content\";\nimport { Footer } from \"./footer\";\nimport * as styles from \"./slot-styles\";\n\nfunction CardInner(\n {\n id,\n \"data-testid\": testId = \"modal-card\",\n children,\n className,\n elementRef,\n ...otherProps\n }: ModalCardProps,\n ref: React.ForwardedRef<HTMLDivElement>\n) {\n // =============================================================================\n // EVENT HANDLERS\n // =============================================================================\n const handleOnClick = (event: React.MouseEvent) => {\n event.stopPropagation();\n };\n\n // =========================================================================\n // HELPERS\n // =========================================================================\n const isComponentType = (child: React.ReactPortal, type: any) =>\n isStyledComponent(child.type)\n ? (child.type as unknown as { target: any }).target === type\n : child.type === type;\n\n const findComponentOfType = (type: any) => {\n return React.Children.toArray(children).find((child) =>\n isComponentType(child as React.ReactPortal, type)\n );\n };\n\n // =============================================================================\n // RENDER FUNCTIONS\n // =============================================================================\n const CloseButtonSlot = findComponentOfType(CloseButton);\n const ContentSlot = findComponentOfType(Content);\n const FooterSlot = findComponentOfType(Footer);\n\n const hasCloseButton = !!CloseButtonSlot;\n\n return (\n <div\n ref={mergeRefs(ref, elementRef)}\n id={id}\n data-testid={testId}\n {...otherProps}\n onClick={handleOnClick}\n className={clsx(styles.modalCard, className)}\n >\n <div\n data-has-close-button={hasCloseButton ? \"true\" : \"false\"}\n className={clsx(styles.slotSpacer)}\n >\n {ContentSlot}\n {FooterSlot}\n </div>\n {hasCloseButton && CloseButtonSlot}\n </div>\n );\n}\n\nexport const Card = React.forwardRef<HTMLDivElement, ModalCardProps>(CardInner);\n\n(Card as NamedExoticComponent).displayName = \"ModalV2.Card\";\n"],"names":["Card","React","forwardRef","_a","ref","id","testId","children","className","elementRef","otherProps","__rest","findComponentOfType","type","Children","toArray","find","child","isStyledComponent","target","isComponentType","CloseButtonSlot","CloseButton","ContentSlot","Content","FooterSlot","Footer","hasCloseButton","_jsxs","Object","assign","mergeRefs","onClick","event","stopPropagation","clsx","styles.modalCard","styles.slotSpacer","displayName"],"mappings":"mnBA0EO,MAAMA,EAAOC,EAAAA,QAAMC,YA9D1B,SACIC,EAQAC,GARA,IAAAC,GACIA,EACA,cAAeC,EAAS,aAAYC,SACpCA,EAAQC,UACRA,EAASC,WACTA,GAAUN,EACPO,EAAUC,EAAAA,OAAAR,EANjB,0DAaA,MAYMS,EAAuBC,GAClBZ,UAAMa,SAASC,QAAQR,GAAUS,MAAMC,GAN1B,EAACA,EAA0BJ,IAC/CK,EAAAA,QAAkBD,EAAMJ,MACjBI,EAAMJ,KAAoCM,SAAWN,EACtDI,EAAMJ,OAASA,EAIjBO,CAAgBH,EAA4BJ,KAO9CQ,EAAkBT,EAAoBU,eACtCC,EAAcX,EAAoBY,WAClCC,EAAab,EAAoBc,UAEjCC,IAAmBN,EAEzB,OACIO,EAAAA,KAAA,MAAAC,OAAAC,OAAA,CACI1B,IAAK2B,EAAAA,UAAU3B,EAAKK,GACpBJ,GAAIA,EAAE,cACOC,GACTI,EAAU,CACdsB,QAjCeC,IACnBA,EAAMC,iBAAiB,EAiCnB1B,UAAW2B,EAAAA,QAAKC,EAAAA,UAAkB5B,GAAUD,SAAA,CAE5CqB,EAAAA,KAAA,MAAA,CAAA,wBAC2BD,EAAiB,OAAS,QACjDnB,UAAW2B,EAAAA,QAAKE,EAAAA,YAAkB9B,SAAA,CAEjCgB,EACAE,KAEJE,GAAkBN,KAG/B,IAICrB,EAA8BsC,YAAc"}
@@ -1 +1 @@
1
- {"version":3,"file":"navbar.js","sources":["../../../src/navbar/navbar.tsx"],"sourcesContent":["import { MenuIcon } from \"@lifesg/react-icons/menu\";\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\";\n\nimport { Layout } from \"../layout\";\nimport { Masthead } from \"../masthead/masthead\";\nimport { Overlay } from \"../overlay/overlay\";\nimport { ClickableIcon } from \"../shared/clickable-icon\";\nimport {\n Breakpoint,\n parsePxOrRemValue,\n useResolvedBreakpointToken,\n} from \"../theme\";\nimport { ThemeContext } from \"../theme/theme-provider/context\";\nimport { Brand } from \"./brand\";\nimport { Drawer } from \"./drawer\";\nimport * as styles from \"./navbar.styles\";\nimport { NavbarActionButtons } from \"./navbar-action-buttons\";\nimport { NavbarHelper } from \"./navbar-helper\";\nimport { NavbarItems } from \"./navbar-items\";\nimport { getDefaultResourceLogo } from \"./navbar-logo-data\";\nimport type {\n BrandType,\n DrawerDismissalMethod,\n NavbarActionButtonsProps,\n NavbarButtonProps,\n NavbarDrawerApi,\n NavbarDrawerHandle,\n NavbarProps,\n NavItemCommonProps,\n NavItemProps,\n} from \"./types\";\n\nconst Component = <T,>(\n {\n items,\n className,\n id,\n selectedId,\n compress = false,\n fixed = true,\n resources,\n hideNavElements = false,\n hideNavBranding = false,\n hideLinkIndicator = false,\n drawerDismissalExclusions: blockDrawerDismissalMethods = [],\n actionButtons,\n onItemClick,\n onActionButtonClick,\n onBrandClick,\n masthead = true,\n layout = \"default\",\n headerLabel = \"Main navigation menu\",\n drawerLabel,\n ...otherProps\n }: NavbarProps<T>,\n ref: React.Ref<NavbarDrawerHandle>\n) => {\n // =============================================================================\n // CONST, STATE, REFS\n // =============================================================================\n const [showDrawer, setShowDrawer] = useState<boolean>(false);\n const [showOverlay, setShowOverlay] = useState<boolean>(false);\n const mobileMenuRef = useRef<HTMLButtonElement>(null);\n const isStretch = layout === \"stretch\";\n const elementRef = useRef<HTMLDivElement>(null);\n const theme = useContext(ThemeContext);\n const defaultResource = getDefaultResourceLogo(theme?.theme);\n const tabletWidth = parsePxOrRemValue(\n useResolvedBreakpointToken(Breakpoint[\"lg-max\"])\n );\n\n const primary = resources?.primary || defaultResource.primary;\n const secondary = resources?.secondary;\n\n useImperativeHandle(\n ref,\n () =>\n Object.assign<HTMLDivElement, NavbarDrawerApi>(\n elementRef.current!,\n {\n dismissDrawer: () => {\n dismissDrawer();\n },\n }\n ),\n [showDrawer]\n );\n\n // =============================================================================\n // EFFECTS\n // =============================================================================\n useEffect(() => {\n handleResize();\n window.addEventListener(\"resize\", handleResize);\n\n return () => {\n window.removeEventListener(\"resize\", handleResize);\n };\n }, []);\n\n // =============================================================================\n // HELPER FUNCTIONS\n // =============================================================================\n const dismissDrawer = () => {\n setShowDrawer(false);\n setTimeout(() => {\n setShowOverlay(false);\n }, 550); // For drawer animation to complete + buffer\n };\n\n const shouldDismissDrawer = (dismissalMethod: DrawerDismissalMethod) => {\n return (\n showDrawer &&\n blockDrawerDismissalMethods.indexOf(dismissalMethod) === -1\n );\n };\n\n const hasCollapsibleActionButtons = (\n actionButtons: NavbarActionButtonsProps\n ) => {\n const drawerActionButtons =\n actionButtons.mobile || actionButtons.desktop;\n if (drawerActionButtons) {\n return (\n drawerActionButtons.length &&\n drawerActionButtons.some(\n (actionButton) => !actionButton.uncollapsible\n )\n );\n }\n\n return false;\n };\n\n // =============================================================================\n // EVENT HANDLER\n // =============================================================================\n const handleResize = () => {\n if (window.innerWidth <= tabletWidth && showDrawer) {\n dismissDrawer();\n }\n };\n\n const handleBrandClick = (\n _event: React.MouseEvent<HTMLAnchorElement>,\n type: BrandType\n ) => {\n if (onBrandClick) {\n onBrandClick(type);\n }\n\n if (shouldDismissDrawer(\"brand-click\")) {\n dismissDrawer();\n }\n };\n\n const handleNavItemClick = <K extends T>(\n event: React.MouseEvent<HTMLAnchorElement>,\n item: NavItemProps<K> | NavItemCommonProps<K>\n ) => {\n if (NavbarHelper.isNavItemCommon(item) && item.onClick) {\n item.onClick(event);\n } else if (onItemClick) {\n event.preventDefault();\n onItemClick(item);\n }\n\n if (\n NavbarHelper.isNavItemLink(item) &&\n !item.subMenu &&\n shouldDismissDrawer(\"item-click\")\n ) {\n dismissDrawer();\n }\n };\n\n const handleActionButtonClick = (\n event: React.MouseEvent<HTMLButtonElement> | React.MouseEvent<Element>,\n actionButton: NavbarButtonProps\n ) => {\n if (\n (actionButton.type === \"button\" ||\n actionButton.type === \"download\") &&\n actionButton.args?.onClick\n ) {\n actionButton.args.onClick(\n event as React.MouseEvent<HTMLButtonElement>\n );\n } else if (onActionButtonClick) {\n event.preventDefault();\n onActionButtonClick(actionButton);\n }\n\n if (shouldDismissDrawer(\"item-click\")) {\n dismissDrawer();\n }\n };\n\n const handleMobileMenuButtonClick = () => {\n setShowDrawer(true);\n setShowOverlay(true);\n };\n\n const handleDrawerClose = () => {\n if (shouldDismissDrawer(\"close-button-click\")) {\n dismissDrawer();\n }\n };\n\n // =============================================================================\n // RENDER FUNCTIONS\n // =============================================================================\n\n const renderDrawer = () => (\n <Overlay\n show={showOverlay}\n enableOverlayClick\n onOverlayClick={handleDrawerClose}\n >\n <Drawer\n show={showDrawer}\n resources={{ primary, secondary }}\n onClose={handleDrawerClose}\n onBrandClick={handleBrandClick}\n actionButtons={actionButtons}\n hideNavBranding={hideNavBranding}\n mobileMenuRef={mobileMenuRef}\n drawerLabel={drawerLabel}\n >\n <NavbarItems\n items={items.mobile || items.desktop}\n onItemClick={handleNavItemClick}\n selectedId={selectedId}\n mobile\n hideLinkIndicator={hideLinkIndicator}\n />\n <NavbarActionButtons\n actionButtons={actionButtons}\n onActionButtonClick={handleActionButtonClick}\n mobile\n />\n </Drawer>\n </Overlay>\n );\n\n const renderBrand = () => (\n <div\n className={clsx(\n styles.navBrandContainer,\n compress\n ? styles.navBrandContainerCompressed\n : styles.navBrandContainerFull,\n styles.navBrandContainerResponsive\n )}\n data-id=\"brand-container\"\n >\n {primary && (\n <Brand\n resources={primary}\n onClick={handleBrandClick}\n data-id=\"brand-primary\"\n data-testid=\"main__brand\"\n type=\"primary\"\n />\n )}\n {secondary && (\n <>\n <div\n className={clsx(\n styles.navSeparator,\n compress\n ? styles.navSeparatorCompressed\n : styles.navSeparatorFull,\n styles.navSeparatorResponsive\n )}\n />\n <Brand\n resources={secondary}\n onClick={handleBrandClick}\n data-id=\"brand-secondary\"\n data-testid=\"main__brand-secondary\"\n type=\"secondary\"\n />\n </>\n )}\n </div>\n );\n\n const renderMobileMenuButton = () => {\n const drawerItems = items.mobile || items.desktop;\n if (\n (drawerItems && drawerItems.length > 0) ||\n (actionButtons && hasCollapsibleActionButtons(actionButtons))\n ) {\n return (\n <ClickableIcon\n ref={mobileMenuRef}\n className={styles.mobileMenuButton}\n aria-label={showDrawer ? \"Close nav menu\" : \"Open nav menu\"}\n aria-expanded={showDrawer}\n data-testid=\"button__mobile-menu\"\n onClick={handleMobileMenuButtonClick}\n focusHighlight={true}\n >\n <MenuIcon className={styles.mobileMenuIcon} />\n </ClickableIcon>\n );\n }\n\n return null;\n };\n\n const renderNavbar = () => {\n return (\n <Layout.Content stretch={isStretch}>\n <nav\n className={clsx(\n styles.nav,\n compress && styles.navCompressed,\n theme?.mode === \"dark\" && styles.navDark\n )}\n aria-label={headerLabel}\n >\n {!hideNavBranding && renderBrand()}\n {!hideNavElements && (\n <div\n className={clsx(\n styles.navElementsContainer,\n !hideNavBranding &&\n styles.navElementsContainerWithBranding\n )}\n >\n <NavbarItems\n items={items.desktop}\n onItemClick={handleNavItemClick}\n selectedId={selectedId}\n hideNavBranding={hideNavBranding}\n hideLinkIndicator={hideLinkIndicator}\n />\n <NavbarActionButtons\n actionButtons={actionButtons}\n onActionButtonClick={handleActionButtonClick}\n />\n {renderMobileMenuButton()}\n </div>\n )}\n </nav>\n\n {!hideNavElements && renderDrawer()}\n </Layout.Content>\n );\n };\n\n return (\n <div\n ref={elementRef}\n className={clsx(\n styles.wrapper,\n fixed ? styles.wrapperFixed : styles.wrapperRelative,\n theme?.mode === \"dark\"\n ? styles.wrapperDark\n : styles.wrapperLight,\n className\n )}\n id={id || \"navbar-wrapper\"}\n data-testid={otherProps[\"data-testid\"] || \"navbar-wrapper\"}\n >\n {masthead && <Masthead stretch={isStretch} />}\n {renderNavbar()}\n </div>\n );\n};\n\nexport const Navbar = forwardRef(Component);\n"],"names":["Navbar","forwardRef","_a","ref","items","className","id","selectedId","compress","fixed","resources","hideNavElements","hideNavBranding","hideLinkIndicator","drawerDismissalExclusions","blockDrawerDismissalMethods","actionButtons","onItemClick","onActionButtonClick","onBrandClick","masthead","layout","headerLabel","drawerLabel","otherProps","__rest","showDrawer","setShowDrawer","useState","showOverlay","setShowOverlay","mobileMenuRef","useRef","isStretch","elementRef","theme","useContext","ThemeContext","defaultResource","getDefaultResourceLogo","tabletWidth","parsePxOrRemValue","useResolvedBreakpointToken","Breakpoint","primary","secondary","useImperativeHandle","Object","assign","current","dismissDrawer","useEffect","handleResize","window","addEventListener","removeEventListener","setTimeout","shouldDismissDrawer","dismissalMethod","indexOf","innerWidth","handleBrandClick","_event","type","handleNavItemClick","event","item","NavbarHelper","isNavItemCommon","onClick","preventDefault","isNavItemLink","subMenu","handleActionButtonClick","actionButton","args","handleMobileMenuButtonClick","handleDrawerClose","renderMobileMenuButton","drawerItems","mobile","desktop","length","drawerActionButtons","some","uncollapsible","hasCollapsibleActionButtons","_jsx","ClickableIcon","styles.mobileMenuButton","focusHighlight","children","MenuIcon","styles.mobileMenuIcon","_jsxs","clsx","styles.wrapper","styles.wrapperFixed","styles.wrapperRelative","mode","styles.wrapperDark","styles.wrapperLight","Masthead","stretch","Layout","Content","styles.nav","styles.navCompressed","styles.navDark","styles.navBrandContainer","styles.navBrandContainerCompressed","styles.navBrandContainerFull","styles.navBrandContainerResponsive","Brand","_Fragment","styles.navSeparator","styles.navSeparatorCompressed","styles.navSeparatorFull","styles.navSeparatorResponsive","styles.navElementsContainer","styles.navElementsContainerWithBranding","NavbarItems","NavbarActionButtons","Overlay","show","enableOverlayClick","onOverlayClick","Drawer","onClose"],"mappings":"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"}
1
+ {"version":3,"file":"navbar.js","sources":["../../../src/navbar/navbar.tsx"],"sourcesContent":["import { MenuIcon } from \"@lifesg/react-icons/menu\";\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\";\n\nimport { Layout } from \"../layout\";\nimport { Masthead } from \"../masthead/masthead\";\nimport { Overlay } from \"../overlay/overlay\";\nimport { ClickableIcon } from \"../shared/clickable-icon\";\nimport {\n Breakpoint,\n parsePxOrRemValue,\n useResolvedBreakpointToken,\n} from \"../theme\";\nimport { ThemeContext } from \"../theme/theme-provider/context\";\nimport { Brand } from \"./brand\";\nimport { Drawer } from \"./drawer\";\nimport * as styles from \"./navbar.styles\";\nimport { NavbarActionButtons } from \"./navbar-action-buttons\";\nimport { NavbarHelper } from \"./navbar-helper\";\nimport { NavbarItems } from \"./navbar-items\";\nimport { getDefaultResourceLogo } from \"./navbar-logo-data\";\nimport type {\n BrandType,\n DrawerDismissalMethod,\n NavbarActionButtonsProps,\n NavbarButtonProps,\n NavbarDrawerApi,\n NavbarDrawerHandle,\n NavbarProps,\n NavItemCommonProps,\n NavItemProps,\n} from \"./types\";\n\nconst Component = <T,>(\n {\n items,\n className,\n id,\n selectedId,\n compress = false,\n fixed = true,\n resources,\n hideNavElements = false,\n hideNavBranding = false,\n hideLinkIndicator = false,\n drawerDismissalExclusions: blockDrawerDismissalMethods = [],\n actionButtons,\n onItemClick,\n onActionButtonClick,\n onBrandClick,\n masthead = true,\n layout = \"default\",\n headerLabel = \"Main navigation menu\",\n drawerLabel,\n ...otherProps\n }: NavbarProps<T>,\n ref: React.Ref<NavbarDrawerHandle>\n) => {\n // =============================================================================\n // CONST, STATE, REFS\n // =============================================================================\n const [showDrawer, setShowDrawer] = useState<boolean>(false);\n const [showOverlay, setShowOverlay] = useState<boolean>(false);\n const mobileMenuRef = useRef<HTMLButtonElement>(null);\n const isStretch = layout === \"stretch\";\n const elementRef = useRef<HTMLDivElement>(null);\n const theme = useContext(ThemeContext);\n const defaultResource = getDefaultResourceLogo(theme?.theme);\n const tabletWidth = parsePxOrRemValue(\n useResolvedBreakpointToken(Breakpoint[\"lg-max\"])\n );\n\n const primary = resources?.primary || defaultResource.primary;\n const secondary = resources?.secondary;\n\n useImperativeHandle(\n ref,\n () =>\n Object.assign<HTMLDivElement, NavbarDrawerApi>(\n elementRef.current!,\n {\n dismissDrawer: () => {\n dismissDrawer();\n },\n }\n ),\n [showDrawer]\n );\n\n // =============================================================================\n // EFFECTS\n // =============================================================================\n useEffect(() => {\n handleResize();\n window.addEventListener(\"resize\", handleResize);\n\n return () => {\n window.removeEventListener(\"resize\", handleResize);\n };\n }, []);\n\n // =============================================================================\n // HELPER FUNCTIONS\n // =============================================================================\n const dismissDrawer = () => {\n setShowDrawer(false);\n setTimeout(() => {\n setShowOverlay(false);\n }, 550); // For drawer animation to complete + buffer\n };\n\n const shouldDismissDrawer = (dismissalMethod: DrawerDismissalMethod) => {\n return (\n showDrawer &&\n blockDrawerDismissalMethods.indexOf(dismissalMethod) === -1\n );\n };\n\n const hasCollapsibleActionButtons = (\n actionButtons: NavbarActionButtonsProps\n ) => {\n const drawerActionButtons =\n actionButtons.mobile || actionButtons.desktop;\n if (drawerActionButtons) {\n return (\n drawerActionButtons.length &&\n drawerActionButtons.some(\n (actionButton) => !actionButton.uncollapsible\n )\n );\n }\n\n return false;\n };\n\n // =============================================================================\n // EVENT HANDLER\n // =============================================================================\n const handleResize = () => {\n if (window.innerWidth <= tabletWidth && showDrawer) {\n dismissDrawer();\n }\n };\n\n const handleBrandClick = (\n _event: React.MouseEvent<HTMLAnchorElement>,\n type: BrandType\n ) => {\n if (onBrandClick) {\n onBrandClick(type);\n }\n\n if (shouldDismissDrawer(\"brand-click\")) {\n dismissDrawer();\n }\n };\n\n const handleNavItemClick = <K extends T>(\n event: React.MouseEvent<HTMLAnchorElement>,\n item: NavItemProps<K> | NavItemCommonProps<K>\n ) => {\n if (NavbarHelper.isNavItemCommon(item) && item.onClick) {\n item.onClick(event);\n } else if (onItemClick) {\n event.preventDefault();\n onItemClick(item);\n }\n\n if (\n NavbarHelper.isNavItemLink(item) &&\n !item.subMenu &&\n shouldDismissDrawer(\"item-click\")\n ) {\n dismissDrawer();\n }\n };\n\n const handleActionButtonClick = (\n event: React.MouseEvent<HTMLButtonElement> | React.MouseEvent<Element>,\n actionButton: NavbarButtonProps\n ) => {\n if (\n (actionButton.type === \"button\" ||\n actionButton.type === \"download\") &&\n actionButton.args?.onClick\n ) {\n actionButton.args.onClick(\n event as React.MouseEvent<HTMLButtonElement>\n );\n } else if (onActionButtonClick) {\n event.preventDefault();\n onActionButtonClick(actionButton);\n }\n\n if (shouldDismissDrawer(\"item-click\")) {\n dismissDrawer();\n }\n };\n\n const handleMobileMenuButtonClick = () => {\n setShowDrawer(true);\n setShowOverlay(true);\n };\n\n const handleDrawerClose = () => {\n if (shouldDismissDrawer(\"close-button-click\")) {\n dismissDrawer();\n }\n };\n\n // =============================================================================\n // RENDER FUNCTIONS\n // =============================================================================\n\n const renderDrawer = () => (\n <Overlay\n show={showOverlay}\n enableOverlayClick\n onOverlayClick={handleDrawerClose}\n >\n <Drawer\n show={showDrawer}\n resources={{ primary, secondary }}\n onClose={handleDrawerClose}\n onBrandClick={handleBrandClick}\n actionButtons={actionButtons}\n hideNavBranding={hideNavBranding}\n mobileMenuRef={mobileMenuRef}\n drawerLabel={drawerLabel}\n >\n <NavbarItems\n items={items.mobile || items.desktop}\n onItemClick={handleNavItemClick}\n selectedId={selectedId}\n mobile\n hideLinkIndicator={hideLinkIndicator}\n />\n <NavbarActionButtons\n actionButtons={actionButtons}\n onActionButtonClick={handleActionButtonClick}\n mobile\n />\n </Drawer>\n </Overlay>\n );\n\n const renderBrand = () => (\n <div\n className={clsx(\n styles.navBrandContainer,\n compress\n ? styles.navBrandContainerCompressed\n : styles.navBrandContainerFull,\n styles.navBrandContainerResponsive\n )}\n data-id=\"brand-container\"\n >\n {primary && (\n <Brand\n resources={primary}\n onClick={handleBrandClick}\n data-id=\"brand-primary\"\n data-testid=\"main__brand\"\n type=\"primary\"\n />\n )}\n {secondary && (\n <>\n <div\n className={clsx(\n styles.navSeparator,\n compress\n ? styles.navSeparatorCompressed\n : styles.navSeparatorFull,\n styles.navSeparatorResponsive\n )}\n />\n <Brand\n resources={secondary}\n onClick={handleBrandClick}\n data-id=\"brand-secondary\"\n data-testid=\"main__brand-secondary\"\n type=\"secondary\"\n />\n </>\n )}\n </div>\n );\n\n const renderMobileMenuButton = () => {\n const drawerItems = items.mobile || items.desktop;\n if (\n (drawerItems && drawerItems.length > 0) ||\n (actionButtons && hasCollapsibleActionButtons(actionButtons))\n ) {\n return (\n <ClickableIcon\n ref={mobileMenuRef}\n className={styles.mobileMenuButton}\n aria-label={showDrawer ? \"Close nav menu\" : \"Open nav menu\"}\n aria-expanded={showDrawer}\n data-testid=\"button__mobile-menu\"\n onClick={handleMobileMenuButtonClick}\n focusHighlight={true}\n >\n <MenuIcon className={styles.mobileMenuIcon} />\n </ClickableIcon>\n );\n }\n\n return null;\n };\n\n const renderNavbar = () => {\n return (\n <Layout.Content stretch={isStretch}>\n <nav\n className={clsx(\n styles.nav,\n compress && styles.navCompressed,\n theme?.mode === \"dark\" && styles.navDark\n )}\n aria-label={headerLabel}\n >\n {!hideNavBranding && renderBrand()}\n {!hideNavElements && (\n <div\n className={clsx(\n styles.navElementsContainer,\n !hideNavBranding &&\n styles.navElementsContainerWithBranding\n )}\n >\n <NavbarItems\n items={items.desktop}\n onItemClick={handleNavItemClick}\n selectedId={selectedId}\n hideNavBranding={hideNavBranding}\n hideLinkIndicator={hideLinkIndicator}\n />\n <NavbarActionButtons\n actionButtons={actionButtons}\n onActionButtonClick={handleActionButtonClick}\n />\n {renderMobileMenuButton()}\n </div>\n )}\n </nav>\n\n {!hideNavElements && renderDrawer()}\n </Layout.Content>\n );\n };\n\n return (\n <div\n ref={elementRef}\n className={clsx(\n styles.wrapper,\n fixed ? styles.wrapperFixed : styles.wrapperRelative,\n theme?.mode === \"dark\"\n ? styles.wrapperDark\n : styles.wrapperLight,\n className\n )}\n id={id || \"navbar-wrapper\"}\n data-testid={otherProps[\"data-testid\"] || \"navbar-wrapper\"}\n >\n {masthead && <Masthead stretch={isStretch} />}\n {renderNavbar()}\n </div>\n );\n};\n\n/**\n * The main site navigation bar with desktop and mobile drawer views.\n *\n * Use `Navbar` to render the primary navigation header. It displays brand\n * logos, navigation items, and action buttons in a desktop bar, and\n * automatically collapses items into a slide-in drawer for mobile viewports.\n */\nexport const Navbar = forwardRef(Component);\n"],"names":["Navbar","forwardRef","_a","ref","items","className","id","selectedId","compress","fixed","resources","hideNavElements","hideNavBranding","hideLinkIndicator","drawerDismissalExclusions","blockDrawerDismissalMethods","actionButtons","onItemClick","onActionButtonClick","onBrandClick","masthead","layout","headerLabel","drawerLabel","otherProps","__rest","showDrawer","setShowDrawer","useState","showOverlay","setShowOverlay","mobileMenuRef","useRef","isStretch","elementRef","theme","useContext","ThemeContext","defaultResource","getDefaultResourceLogo","tabletWidth","parsePxOrRemValue","useResolvedBreakpointToken","Breakpoint","primary","secondary","useImperativeHandle","Object","assign","current","dismissDrawer","useEffect","handleResize","window","addEventListener","removeEventListener","setTimeout","shouldDismissDrawer","dismissalMethod","indexOf","innerWidth","handleBrandClick","_event","type","handleNavItemClick","event","item","NavbarHelper","isNavItemCommon","onClick","preventDefault","isNavItemLink","subMenu","handleActionButtonClick","actionButton","args","handleMobileMenuButtonClick","handleDrawerClose","renderMobileMenuButton","drawerItems","mobile","desktop","length","drawerActionButtons","some","uncollapsible","hasCollapsibleActionButtons","_jsx","ClickableIcon","styles.mobileMenuButton","focusHighlight","children","MenuIcon","styles.mobileMenuIcon","_jsxs","clsx","styles.wrapper","styles.wrapperFixed","styles.wrapperRelative","mode","styles.wrapperDark","styles.wrapperLight","Masthead","stretch","Layout","Content","styles.nav","styles.navCompressed","styles.navDark","styles.navBrandContainer","styles.navBrandContainerCompressed","styles.navBrandContainerFull","styles.navBrandContainerResponsive","Brand","_Fragment","styles.navSeparator","styles.navSeparatorCompressed","styles.navSeparatorFull","styles.navSeparatorResponsive","styles.navElementsContainer","styles.navElementsContainerWithBranding","NavbarItems","NavbarActionButtons","Overlay","show","enableOverlayClick","onOverlayClick","Drawer","onClose"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"notification-banner-hoc.js","sources":["../../../src/notification-banner/notification-banner-hoc.tsx"],"sourcesContent":["import DOMPurify from \"dompurify\";\nimport React from \"react\";\n\nimport { NBComponent, NotificationBanner } from \"./notification-banner\";\nimport type {\n ContentLinkAttributes,\n ContentTextAttributes,\n NotificationBannerWithForwardedRefProps,\n NotificationContentAttributes,\n} from \"./types\";\n\nexport const withNotificationBanner = (\n data: NotificationContentAttributes[]\n) => {\n const ComponentToReturn = (\n props: NotificationBannerWithForwardedRefProps,\n ref: React.Ref<HTMLDivElement>\n ) => {\n const renderContent = () => {\n if (data.length > 0) {\n return data.map((attribute, index) => {\n if (attribute.type === \"text\") {\n const otherAttributes =\n attribute.otherAttributes as ContentTextAttributes;\n\n const sanitizedContent = DOMPurify.sanitize(\n attribute.content\n );\n return (\n <p\n key={index}\n {...otherAttributes}\n dangerouslySetInnerHTML={{\n __html: sanitizedContent,\n }}\n />\n );\n } else {\n const otherAttributes =\n attribute.otherAttributes as ContentLinkAttributes;\n return (\n <NotificationBanner.Link\n key={index}\n {...otherAttributes}\n >\n {attribute.content}\n </NotificationBanner.Link>\n );\n }\n });\n }\n\n console.error(\"[NotificationBannerHOC] Empty data passed\");\n return null;\n };\n\n return (\n <NBComponent forwardedRef={ref} {...props}>\n {renderContent()}\n </NBComponent>\n );\n };\n\n return React.forwardRef(ComponentToReturn);\n};\n"],"names":["data","React","forwardRef","props","ref","_jsx","NBComponent","Object","assign","forwardedRef","children","length","map","attribute","index","type","otherAttributes","sanitizedContent","DOMPurify","sanitize","content","dangerouslySetInnerHTML","__html","NotificationBanner","Link","console","error"],"mappings":"gRAYIA,GAmDOC,EAAAA,QAAMC,YAjDa,CACtBC,EACAC,IAyCIC,EAAAA,IAACC,EAAAA,YAAWC,OAAAC,OAAA,CAACC,aAAcL,GAASD,EAAK,CAAAO,SAtCrCV,EAAKW,OAAS,EACPX,EAAKY,KAAI,CAACC,EAAWC,KACxB,GAAuB,SAAnBD,EAAUE,KAAiB,CAC3B,MAAMC,EACFH,EAAUG,gBAERC,EAAmBC,EAAAA,QAAUC,SAC/BN,EAAUO,SAEd,OACIf,EAAAA,IAAA,IAAAE,OAAAC,OAAA,GAEQQ,EAAe,CACnBK,wBAAyB,CACrBC,OAAQL,KAHPH,EAOjB,CAAO,CACH,MAAME,EACFH,EAAUG,gBACd,OACIX,EAAAA,IAACkB,EAAAA,mBAAmBC,KAAIjB,OAAAC,OAAA,CAAA,EAEhBQ,EAAe,CAAAN,SAElBG,EAAUO,UAHNN,EAMjB,MAIRW,QAAQC,MAAM,6CACP"}
1
+ {"version":3,"file":"notification-banner-hoc.js","sources":["../../../src/notification-banner/notification-banner-hoc.tsx"],"sourcesContent":["import DOMPurify from \"dompurify\";\nimport React from \"react\";\n\nimport { NBComponent, NotificationBanner } from \"./notification-banner\";\nimport type {\n ContentLinkAttributes,\n ContentTextAttributes,\n NotificationBannerWithForwardedRefProps,\n NotificationContentAttributes,\n} from \"./types\";\n\n/**\n * Higher-order component that wraps `NotificationBanner` and renders its\n * content from a structured data array.\n * *\n * @param data Content items to render inside the banner.\n */\nexport const withNotificationBanner = (\n data: NotificationContentAttributes[]\n) => {\n const ComponentToReturn = (\n props: NotificationBannerWithForwardedRefProps,\n ref: React.Ref<HTMLDivElement>\n ) => {\n const renderContent = () => {\n if (data.length > 0) {\n return data.map((attribute, index) => {\n if (attribute.type === \"text\") {\n const otherAttributes =\n attribute.otherAttributes as ContentTextAttributes;\n\n const sanitizedContent = DOMPurify.sanitize(\n attribute.content\n );\n return (\n <p\n key={index}\n {...otherAttributes}\n dangerouslySetInnerHTML={{\n __html: sanitizedContent,\n }}\n />\n );\n } else {\n const otherAttributes =\n attribute.otherAttributes as ContentLinkAttributes;\n return (\n <NotificationBanner.Link\n key={index}\n {...otherAttributes}\n >\n {attribute.content}\n </NotificationBanner.Link>\n );\n }\n });\n }\n\n console.error(\"[NotificationBannerHOC] Empty data passed\");\n return null;\n };\n\n return (\n <NBComponent forwardedRef={ref} {...props}>\n {renderContent()}\n </NBComponent>\n );\n };\n\n return React.forwardRef(ComponentToReturn);\n};\n"],"names":["data","React","forwardRef","props","ref","_jsx","NBComponent","Object","assign","forwardedRef","children","length","map","attribute","index","type","otherAttributes","sanitizedContent","DOMPurify","sanitize","content","dangerouslySetInnerHTML","__html","NotificationBanner","Link","console","error"],"mappings":"gRAkBIA,GAmDOC,EAAAA,QAAMC,YAjDa,CACtBC,EACAC,IAyCIC,EAAAA,IAACC,EAAAA,YAAWC,OAAAC,OAAA,CAACC,aAAcL,GAASD,EAAK,CAAAO,SAtCrCV,EAAKW,OAAS,EACPX,EAAKY,KAAI,CAACC,EAAWC,KACxB,GAAuB,SAAnBD,EAAUE,KAAiB,CAC3B,MAAMC,EACFH,EAAUG,gBAERC,EAAmBC,EAAAA,QAAUC,SAC/BN,EAAUO,SAEd,OACIf,EAAAA,IAAA,IAAAE,OAAAC,OAAA,GAEQQ,EAAe,CACnBK,wBAAyB,CACrBC,OAAQL,KAHPH,EAOjB,CAAO,CACH,MAAME,EACFH,EAAUG,gBACd,OACIX,EAAAA,IAACkB,EAAAA,mBAAmBC,KAAIjB,OAAAC,OAAA,CAAA,EAEhBQ,EAAe,CAAAN,SAElBG,EAAUO,UAHNN,EAMjB,MAIRW,QAAQC,MAAM,6CACP"}
@@ -1 +1 @@
1
- {"version":3,"file":"notification-banner.js","sources":["../../../src/notification-banner/notification-banner.tsx"],"sourcesContent":["import { CrossIcon } from \"@lifesg/react-icons\";\nimport clsx from \"clsx\";\nimport type { NamedExoticComponent } from \"react\";\nimport React, { useEffect, useRef, useState } from \"react\";\nimport { useResizeDetector } from \"react-resize-detector\";\n\nimport { Layout } from \"../layout\";\nimport { VisuallyHidden } from \"../shared/accessibility\";\nimport { ClickableIcon } from \"../shared/clickable-icon\";\nimport { formatUnitValue, useApplyStyle } from \"../theme\";\nimport { Typography } from \"../typography\";\nimport * as styles from \"./notification-banner.styles\";\nimport type {\n NotificationBannerProps,\n NotificationBannerWithForwardedRefProps,\n} from \"./types\";\n\nexport const NBComponent = ({\n children,\n visible = true,\n dismissible = true,\n sticky = true,\n onDismiss,\n id,\n forwardedRef,\n maxCollapsedHeight,\n onClick,\n actionButton,\n icon,\n className,\n ...otherProps\n}: NotificationBannerWithForwardedRefProps) => {\n // =============================================================================\n // CONST, STATE, REF\n // =============================================================================\n const testId = otherProps[\"data-testid\"];\n\n const [isVisible, setVisible] = useState<boolean>(visible);\n const { height: contentHeight = 0, ref: contentRef } = useResizeDetector();\n const contentTextRef = useRef<HTMLDivElement>(null);\n\n const isCollapsed =\n maxCollapsedHeight && contentHeight > maxCollapsedHeight;\n\n useApplyStyle(contentTextRef, {\n [styles.tokens.contentText.maxCollapsedHeight]: isCollapsed\n ? formatUnitValue(maxCollapsedHeight, \"px\")\n : undefined,\n });\n\n // =============================================================================\n // EFFECTS\n // =============================================================================\n useEffect(() => {\n setVisible(visible);\n }, [visible]);\n\n // =============================================================================\n // EVENT HANDLERS\n // =============================================================================\n const handleDismiss = (event: React.MouseEvent<HTMLButtonElement>) => {\n event.stopPropagation();\n setVisible(false);\n\n if (dismissible && onDismiss) onDismiss();\n };\n\n const handleActionButtonOnClick = (\n event: React.MouseEvent<HTMLButtonElement>\n ) => {\n if (!actionButton?.onClick) {\n // let it bubble\n return;\n }\n event.stopPropagation();\n actionButton.onClick(event);\n };\n\n // =============================================================================\n // RENDER FUNCTIONS\n // =============================================================================\n if (!isVisible) return null;\n\n const renderDismissButton = () => (\n <ClickableIcon\n className={styles.dismissButton}\n tabIndex={0}\n onClick={handleDismiss}\n id={formatId(\"dismiss-button\", id)}\n data-testid={formatId(\"dismiss-button\", testId)}\n focusOutline=\"browser\"\n focusHighlight={false}\n type=\"button\"\n aria-label=\"close\"\n >\n <CrossIcon aria-hidden />\n </ClickableIcon>\n );\n\n const renderActionButton = () => {\n if (!actionButton) return null;\n\n return (\n <button\n className={styles.actionButton}\n id={formatId(\"action-button\", id)}\n data-testid={formatId(\"action-button\", testId)}\n type=\"button\"\n {...actionButton}\n onClick={handleActionButtonOnClick}\n >\n {actionButton.children}\n </button>\n );\n };\n\n const renderContent = () => (\n <div\n className={styles.content}\n data-testid={formatId(\"text-content\", testId)}\n >\n <div className={styles.contentWrapper}>\n <div\n ref={contentTextRef}\n className={clsx(\n styles.contentText,\n isCollapsed && styles.contentTextCollapsed\n )}\n >\n <div ref={contentRef}>{children}</div>\n </div>\n {renderActionButton()}\n </div>\n </div>\n );\n\n const renderAccessibleBannerButton = () => (\n <VisuallyHidden>\n <button aria-label={\"Clickable banner\"} type=\"button\" />\n </VisuallyHidden>\n );\n\n return (\n <div\n ref={forwardedRef}\n className={clsx(\n styles.wrapper,\n sticky && styles.wrapperSticky,\n !!onClick && styles.wrapperClickable,\n className\n )}\n onClick={onClick}\n role=\"region\"\n {...otherProps}\n >\n <Layout.Content id={formatId(\"container\", id)}>\n {icon && (\n <div className={styles.iconContainer} aria-hidden>\n {icon}\n </div>\n )}\n <div className={styles.contentContainer}>{renderContent()}</div>\n {dismissible && renderDismissButton()}\n </Layout.Content>\n {onClick && renderAccessibleBannerButton()}\n </div>\n );\n};\n\n/**\n * Intermediate component to handle passing the ref as a prop\n */\nconst NBWithRef = (\n props: NotificationBannerProps,\n ref: React.Ref<HTMLDivElement>\n) => {\n return <NBComponent {...props} forwardedRef={ref} />;\n};\n\nconst NBLink = React.forwardRef<\n HTMLAnchorElement,\n React.ComponentProps<typeof Typography.LinkBL>\n>(function NotificationBannerLink(props, ref) {\n return (\n <Typography.LinkBL\n ref={ref}\n className={clsx(styles.contentLink, props.className)}\n {...props}\n />\n );\n});\n(NBLink as NamedExoticComponent).displayName = \"NotificationBanner.Link\";\n\n// =============================================================================\n// HELPER FUNCTIONS\n// =============================================================================\nconst formatId = (componentName: string, id = \"wrapper\"): string => {\n return `${id}-${componentName}`;\n};\n\n// =============================================================================\n// EXPORTABLE\n// =============================================================================\nconst Base = React.forwardRef(NBWithRef);\n(Base as NamedExoticComponent).displayName = \"NotificationBanner\";\nexport const NotificationBanner = Object.assign(Base, {\n Link: NBLink,\n});\n"],"names":["NBComponent","_a","children","visible","dismissible","sticky","onDismiss","id","forwardedRef","maxCollapsedHeight","onClick","actionButton","icon","className","otherProps","__rest","testId","isVisible","setVisible","useState","height","contentHeight","ref","contentRef","useResizeDetector","contentTextRef","useRef","isCollapsed","useApplyStyle","styles.tokens","contentText","formatUnitValue","undefined","useEffect","handleDismiss","event","stopPropagation","handleActionButtonOnClick","_jsxs","clsx","styles.wrapper","styles.wrapperSticky","styles.wrapperClickable","role","Layout","Content","formatId","_jsx","styles.iconContainer","styles.contentContainer","styles.content","styles.contentWrapper","styles.contentText","styles.contentTextCollapsed","Object","assign","styles.actionButton","type","ClickableIcon","styles.dismissButton","tabIndex","focusOutline","focusHighlight","CrossIcon","VisuallyHidden","NBLink","React","forwardRef","props","Typography","LinkBL","styles.contentLink","displayName","componentName","Base","NotificationBanner","Link"],"mappings":"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"}
1
+ {"version":3,"file":"notification-banner.js","sources":["../../../src/notification-banner/notification-banner.tsx"],"sourcesContent":["import { CrossIcon } from \"@lifesg/react-icons\";\nimport clsx from \"clsx\";\nimport type { NamedExoticComponent } from \"react\";\nimport React, { useEffect, useRef, useState } from \"react\";\nimport { useResizeDetector } from \"react-resize-detector\";\n\nimport { Layout } from \"../layout\";\nimport { VisuallyHidden } from \"../shared/accessibility\";\nimport { ClickableIcon } from \"../shared/clickable-icon\";\nimport { formatUnitValue, useApplyStyle } from \"../theme\";\nimport { Typography } from \"../typography\";\nimport * as styles from \"./notification-banner.styles\";\nimport type {\n NotificationBannerProps,\n NotificationBannerWithForwardedRefProps,\n} from \"./types\";\n\nexport const NBComponent = ({\n children,\n visible = true,\n dismissible = true,\n sticky = true,\n onDismiss,\n id,\n forwardedRef,\n maxCollapsedHeight,\n onClick,\n actionButton,\n icon,\n className,\n ...otherProps\n}: NotificationBannerWithForwardedRefProps) => {\n // =============================================================================\n // CONST, STATE, REF\n // =============================================================================\n const testId = otherProps[\"data-testid\"];\n\n const [isVisible, setVisible] = useState<boolean>(visible);\n const { height: contentHeight = 0, ref: contentRef } = useResizeDetector();\n const contentTextRef = useRef<HTMLDivElement>(null);\n\n const isCollapsed =\n maxCollapsedHeight && contentHeight > maxCollapsedHeight;\n\n useApplyStyle(contentTextRef, {\n [styles.tokens.contentText.maxCollapsedHeight]: isCollapsed\n ? formatUnitValue(maxCollapsedHeight, \"px\")\n : undefined,\n });\n\n // =============================================================================\n // EFFECTS\n // =============================================================================\n useEffect(() => {\n setVisible(visible);\n }, [visible]);\n\n // =============================================================================\n // EVENT HANDLERS\n // =============================================================================\n const handleDismiss = (event: React.MouseEvent<HTMLButtonElement>) => {\n event.stopPropagation();\n setVisible(false);\n\n if (dismissible && onDismiss) onDismiss();\n };\n\n const handleActionButtonOnClick = (\n event: React.MouseEvent<HTMLButtonElement>\n ) => {\n if (!actionButton?.onClick) {\n // let it bubble\n return;\n }\n event.stopPropagation();\n actionButton.onClick(event);\n };\n\n // =============================================================================\n // RENDER FUNCTIONS\n // =============================================================================\n if (!isVisible) return null;\n\n const renderDismissButton = () => (\n <ClickableIcon\n className={styles.dismissButton}\n tabIndex={0}\n onClick={handleDismiss}\n id={formatId(\"dismiss-button\", id)}\n data-testid={formatId(\"dismiss-button\", testId)}\n focusOutline=\"browser\"\n focusHighlight={false}\n type=\"button\"\n aria-label=\"close\"\n >\n <CrossIcon aria-hidden />\n </ClickableIcon>\n );\n\n const renderActionButton = () => {\n if (!actionButton) return null;\n\n return (\n <button\n className={styles.actionButton}\n id={formatId(\"action-button\", id)}\n data-testid={formatId(\"action-button\", testId)}\n type=\"button\"\n {...actionButton}\n onClick={handleActionButtonOnClick}\n >\n {actionButton.children}\n </button>\n );\n };\n\n const renderContent = () => (\n <div\n className={styles.content}\n data-testid={formatId(\"text-content\", testId)}\n >\n <div className={styles.contentWrapper}>\n <div\n ref={contentTextRef}\n className={clsx(\n styles.contentText,\n isCollapsed && styles.contentTextCollapsed\n )}\n >\n <div ref={contentRef}>{children}</div>\n </div>\n {renderActionButton()}\n </div>\n </div>\n );\n\n const renderAccessibleBannerButton = () => (\n <VisuallyHidden>\n <button aria-label={\"Clickable banner\"} type=\"button\" />\n </VisuallyHidden>\n );\n\n return (\n <div\n ref={forwardedRef}\n className={clsx(\n styles.wrapper,\n sticky && styles.wrapperSticky,\n !!onClick && styles.wrapperClickable,\n className\n )}\n onClick={onClick}\n role=\"region\"\n {...otherProps}\n >\n <Layout.Content id={formatId(\"container\", id)}>\n {icon && (\n <div className={styles.iconContainer} aria-hidden>\n {icon}\n </div>\n )}\n <div className={styles.contentContainer}>{renderContent()}</div>\n {dismissible && renderDismissButton()}\n </Layout.Content>\n {onClick && renderAccessibleBannerButton()}\n </div>\n );\n};\n\n/**\n * Intermediate component to handle passing the ref as a prop\n */\nconst NBWithRef = (\n props: NotificationBannerProps,\n ref: React.Ref<HTMLDivElement>\n) => {\n return <NBComponent {...props} forwardedRef={ref} />;\n};\n\nconst NBLink = React.forwardRef<\n HTMLAnchorElement,\n React.ComponentProps<typeof Typography.LinkBL>\n>(function NotificationBannerLink(props, ref) {\n return (\n <Typography.LinkBL\n ref={ref}\n className={clsx(styles.contentLink, props.className)}\n {...props}\n />\n );\n});\n(NBLink as NamedExoticComponent).displayName = \"NotificationBanner.Link\";\n\n// =============================================================================\n// HELPER FUNCTIONS\n// =============================================================================\nconst formatId = (componentName: string, id = \"wrapper\"): string => {\n return `${id}-${componentName}`;\n};\n\n// =============================================================================\n// EXPORTABLE\n// =============================================================================\nconst Base = React.forwardRef(NBWithRef);\n(Base as NamedExoticComponent).displayName = \"NotificationBanner\";\n\n/**\n * A full-width informational banner that sits at the top of the page.\n *\n * Use `NotificationBanner` to surface important or persistent messages that\n * should remain visible until the user dismisses them.\n */\nexport const NotificationBanner = Object.assign(Base, {\n /** Renders an inline link styled for use inside a `NotificationBanner`. */\n Link: NBLink,\n});\n"],"names":["NBComponent","_a","children","visible","dismissible","sticky","onDismiss","id","forwardedRef","maxCollapsedHeight","onClick","actionButton","icon","className","otherProps","__rest","testId","isVisible","setVisible","useState","height","contentHeight","ref","contentRef","useResizeDetector","contentTextRef","useRef","isCollapsed","useApplyStyle","styles.tokens","contentText","formatUnitValue","undefined","useEffect","handleDismiss","event","stopPropagation","handleActionButtonOnClick","_jsxs","clsx","styles.wrapper","styles.wrapperSticky","styles.wrapperClickable","role","Layout","Content","formatId","_jsx","styles.iconContainer","styles.contentContainer","styles.content","styles.contentWrapper","styles.contentText","styles.contentTextCollapsed","Object","assign","styles.actionButton","type","ClickableIcon","styles.dismissButton","tabIndex","focusOutline","focusHighlight","CrossIcon","VisuallyHidden","NBLink","React","forwardRef","props","Typography","LinkBL","styles.contentLink","displayName","componentName","Base","NotificationBanner","Link"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"otp-input.js","sources":["../../../src/otp-input/otp-input.tsx"],"sourcesContent":["import clsx from \"clsx\";\nimport type React from \"react\";\nimport {\n forwardRef,\n useEffect,\n useImperativeHandle,\n useRef,\n useState,\n} from \"react\";\n\nimport { Button } from \"../button\";\nimport { FormErrorMessage } from \"../form/form-label\";\nimport { Input } from \"../input\";\nimport { VisuallyHidden } from \"../shared/accessibility\";\nimport { Typography } from \"../typography\";\nimport { StringHelper, useId } from \"../util\";\nimport * as styles from \"./otp-input.styles\";\nimport type { OtpInputProps, OtpInputRef } from \"./types\";\nimport { stripOtpFromAutofill, validateUserInput } from \"./utils\";\n\nconst Component = (\n {\n id,\n value = [],\n \"data-testid\": dataTestId,\n className,\n cooldownDuration,\n actionButtonProps,\n errorMessage,\n numOfInput,\n prefix,\n onChange,\n onCooldownStart,\n onCooldownEnd,\n otpOnly,\n onCountdownChange,\n ...otherProps\n }: OtpInputProps,\n ref: React.Ref<OtpInputRef>\n) => {\n // =============================================================================\n // CONST, STATE, REF\n // =============================================================================\n const {\n disabled,\n onClick,\n styleType = \"secondary\",\n ...otherCtaProps\n } = actionButtonProps ?? {};\n\n const inputRefs = useRef<(HTMLInputElement | null)[]>([]);\n const onChangeRef = useRef(onChange);\n\n const [otpValues, setOtpValues] = useState<string[]>(\n new Array(numOfInput).fill(\"\")\n );\n const [countDown, setCountDown] = useState<number>(cooldownDuration);\n const [lastCtaTimestamp, setLastCtaTimestamp] = useState<Date>(new Date());\n const internalId = useId();\n\n const hasError = !!errorMessage;\n const errorId = `${internalId}-error`;\n const timerId = `${internalId}-timer`;\n\n // =============================================================================\n // EFFECTS\n // =============================================================================\n useEffect(() => {\n inputRefs?.current[0]?.focus();\n document.addEventListener(\"paste\", handlePaste);\n return () => document.removeEventListener(\"paste\", handlePaste);\n }, []);\n\n useEffect(() => {\n if (cooldownDuration !== 0) {\n if (onCooldownStart) onCooldownStart();\n const cleanup = beginCountdown();\n\n return () => cleanup();\n }\n }, [lastCtaTimestamp]);\n\n useImperativeHandle(ref, () => ({\n startCooldown: () => {\n setLastCtaTimestamp(new Date());\n setCountDown(cooldownDuration);\n },\n }));\n\n useEffect(() => {\n onChangeRef.current = onChange;\n }, [onChange]);\n\n useEffect(() => {\n if (value.length === numOfInput) {\n setOtpValues(value);\n }\n }, [value]);\n\n // =============================================================================\n // EVENT HANDLERS\n // =============================================================================\n const handleInputFullValue = (incomingValue: string) => {\n if (incomingValue && validateUserInput(incomingValue, numOfInput)) {\n const incomingValueArr = incomingValue.split(\"\");\n setOtpValues(incomingValueArr);\n if (onChangeRef.current) {\n onChangeRef.current(incomingValueArr);\n }\n\n return true;\n }\n\n return false;\n };\n\n const handleChange =\n (index: number) => (event: React.ChangeEvent<HTMLInputElement>) => {\n const eventValue = event.target.value;\n\n /* handle autofill */\n const fieldIsEmpty = otpValues.every((num) => num === \"\");\n const autofillOtp = stripOtpFromAutofill(\n eventValue,\n numOfInput,\n prefix\n );\n if (fieldIsEmpty && handleInputFullValue(autofillOtp)) {\n return;\n }\n\n /* handle normal input */\n const value = eventValue.replace(/[^0-9]/g, \"\");\n if (validateUserInput(value)) {\n const newOtpValues = [...otpValues];\n\n newOtpValues[index] = value.substring(value.length - 1);\n inputRefs.current[index + 1]?.focus();\n\n setOtpValues(newOtpValues);\n\n if (onChange) {\n onChange(newOtpValues);\n }\n }\n };\n\n const handleKeyDown =\n (index: number) => (event: React.KeyboardEvent<HTMLInputElement>) => {\n const { key, code } = event;\n\n if (key === \"Backspace\" || code === \"Backspace\") {\n const newOtpValues = [...otpValues];\n if (newOtpValues[index] !== \"\") {\n newOtpValues[index] = \"\";\n } else if (index !== 0) {\n newOtpValues[index - 1] = \"\";\n inputRefs.current[index - 1]?.focus();\n }\n\n setOtpValues(newOtpValues);\n\n if (onChange) {\n onChange(newOtpValues);\n }\n } else if (event.code === \"ArrowRight\") {\n inputRefs.current[index + 1]?.focus();\n } else if (event.code === \"ArrowLeft\") {\n inputRefs.current[index - 1]?.focus();\n }\n };\n\n const handlePaste = (event: ClipboardEvent): void => {\n if (!event.clipboardData) return;\n\n const pastedValue = event.clipboardData.getData(\"text\");\n const autofillOtp = stripOtpFromAutofill(\n pastedValue,\n numOfInput,\n prefix\n );\n if (!handleInputFullValue(autofillOtp)) {\n event.preventDefault();\n }\n };\n\n const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {\n setOtpValues(new Array(numOfInput).fill(\"\"));\n\n if (!isWithinCooldown()) {\n setLastCtaTimestamp(new Date());\n setCountDown(cooldownDuration);\n }\n\n if (onClick) {\n onClick(event);\n }\n };\n\n // =========================================================================\n // HELPER FUNCTIONS\n // =========================================================================\n const isWithinCooldown = (): boolean => {\n const currentTime = Date.now();\n const coolDownInMilliseconds = cooldownDuration * 1000;\n\n return (\n currentTime < lastCtaTimestamp.valueOf() + coolDownInMilliseconds\n );\n };\n\n const beginCountdown = () => {\n const interval = setInterval(() => {\n const currentTime = Date.now();\n const coolDownInMilliseconds = cooldownDuration * 1000;\n\n const timer = Math.ceil(\n (lastCtaTimestamp.valueOf() +\n coolDownInMilliseconds -\n currentTime) /\n 1000\n );\n setCountDown(timer);\n if (timer <= 0) {\n if (onCooldownEnd) onCooldownEnd();\n clearInterval(interval);\n } else if (onCountdownChange) {\n onCountdownChange(timer);\n }\n }, 1000);\n\n return () => {\n clearInterval(interval);\n };\n };\n\n const generateId = (index: number, name: string, prefix?: string) => {\n return prefix\n ? `${prefix}-${name}-${index + 1}`\n : `${name}-${index + 1}`;\n };\n\n const displaySeconds = (time: number) => {\n return `${time} second${time === 1 ? \"\" : \"s\"}`;\n };\n\n const getCTALabelProps = (): Partial<\n React.HTMLAttributes<HTMLButtonElement>\n > => {\n return otherCtaProps.children\n ? { children: otherCtaProps.children }\n : {\n children:\n countDown > 0\n ? `Resend OTP in ${displaySeconds(countDown)}`\n : \"Resend OTP\",\n // use a fixed label to avoid repeated screen reader updates when the button is focused\n \"aria-label\":\n countDown > 0\n ? `Resend OTP in ${displaySeconds(cooldownDuration)}`\n : \"Resend OTP\",\n // use a secondary element to reflect the latest countdown\n \"aria-describedby\": timerId,\n };\n };\n\n // =============================================================================\n // RENDER FUNCTIONS\n // =============================================================================\n return (\n <div\n id={id}\n data-testid={dataTestId}\n className={clsx(styles.wrapper, className)}\n >\n <div\n className={styles.inputContainer}\n role=\"group\"\n aria-label={`${numOfInput}-digit OTP input field`}\n >\n {prefix && (\n <Typography.BodyBL\n as=\"span\"\n className={styles.prefix}\n data-testid=\"otp-prefix\"\n weight=\"semibold\"\n >\n <VisuallyHidden>O T P prefix</VisuallyHidden>\n {`${prefix.value} ${prefix.separator}`}\n </Typography.BodyBL>\n )}\n {otpValues.map((data, index) => {\n return (\n <Input\n className={styles.inputField}\n id={generateId(index, \"otp-input\", id)}\n data-testid={generateId(\n index,\n \"otp-input\",\n dataTestId\n )}\n aria-label={`${StringHelper.formatOrdinal(\n index + 1\n )} digit`}\n aria-invalid={hasError}\n aria-describedby={hasError ? errorId : undefined}\n key={index}\n ref={(el) => (inputRefs.current[index] = el)}\n type=\"text\"\n inputMode=\"numeric\"\n value={data}\n error={hasError}\n onChange={handleChange(index)}\n onKeyDown={handleKeyDown(index)}\n autoComplete=\"off\"\n {...otherProps}\n />\n );\n })}\n </div>\n {errorMessage && (\n <FormErrorMessage id={errorId} data-testid=\"otp-error-message\">\n {errorMessage}\n </FormErrorMessage>\n )}\n {/* visually hidden elements need to be rendered before the button so that Voiceover/Chrome doesn't skip the button */}\n <VisuallyHidden role=\"timer\" id={timerId}>\n {displaySeconds(countDown)} remaining\n </VisuallyHidden>\n <VisuallyHidden aria-live=\"polite\">\n {countDown > 0 ? \"\" : \"Ready to resend OTP\"}\n </VisuallyHidden>\n {!otpOnly && (\n <Button\n className={styles.ctaButton}\n styleType={styleType}\n type=\"button\"\n sizeType=\"small\"\n {...otherCtaProps}\n onClick={handleClick}\n disabled={disabled || isWithinCooldown()}\n {...getCTALabelProps()}\n />\n )}\n </div>\n );\n};\n\nexport const OtpInput = forwardRef(Component);\n"],"names":["OtpInput","forwardRef","_a","ref","id","value","dataTestId","className","cooldownDuration","actionButtonProps","errorMessage","numOfInput","prefix","onChange","onCooldownStart","onCooldownEnd","otpOnly","onCountdownChange","otherProps","__rest","_b","disabled","onClick","styleType","otherCtaProps","inputRefs","useRef","onChangeRef","otpValues","setOtpValues","useState","Array","fill","countDown","setCountDown","lastCtaTimestamp","setLastCtaTimestamp","Date","internalId","useId","hasError","errorId","timerId","useEffect","current","focus","document","addEventListener","handlePaste","removeEventListener","cleanup","beginCountdown","useImperativeHandle","startCooldown","length","handleInputFullValue","incomingValue","validateUserInput","incomingValueArr","split","handleChange","index","event","eventValue","target","fieldIsEmpty","every","num","autofillOtp","stripOtpFromAutofill","replace","newOtpValues","substring","handleKeyDown","key","code","_c","clipboardData","pastedValue","getData","preventDefault","isWithinCooldown","currentTime","now","coolDownInMilliseconds","valueOf","interval","setInterval","timer","Math","ceil","clearInterval","generateId","name","displaySeconds","time","_jsxs","clsx","styles.wrapper","children","styles.inputContainer","role","Typography","BodyBL","as","styles.prefix","weight","_jsx","VisuallyHidden","separator","map","data","Input","Object","assign","styles.inputField","StringHelper","formatOrdinal","undefined","el","type","inputMode","error","onKeyDown","autoComplete","FormErrorMessage","Button","styles.ctaButton","sizeType"],"mappings":"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"}
1
+ {"version":3,"file":"otp-input.js","sources":["../../../src/otp-input/otp-input.tsx"],"sourcesContent":["import clsx from \"clsx\";\nimport type React from \"react\";\nimport {\n forwardRef,\n useEffect,\n useImperativeHandle,\n useRef,\n useState,\n} from \"react\";\n\nimport { Button } from \"../button\";\nimport { FormErrorMessage } from \"../form/form-label\";\nimport { Input } from \"../input\";\nimport { VisuallyHidden } from \"../shared/accessibility\";\nimport { Typography } from \"../typography\";\nimport { StringHelper, useId } from \"../util\";\nimport * as styles from \"./otp-input.styles\";\nimport type { OtpInputProps, OtpInputRef } from \"./types\";\nimport { stripOtpFromAutofill, validateUserInput } from \"./utils\";\n\nconst Component = (\n {\n id,\n value = [],\n \"data-testid\": dataTestId,\n className,\n cooldownDuration,\n actionButtonProps,\n errorMessage,\n numOfInput,\n prefix,\n onChange,\n onCooldownStart,\n onCooldownEnd,\n otpOnly,\n onCountdownChange,\n ...otherProps\n }: OtpInputProps,\n ref: React.Ref<OtpInputRef>\n) => {\n // =============================================================================\n // CONST, STATE, REF\n // =============================================================================\n const {\n disabled,\n onClick,\n styleType = \"secondary\",\n ...otherCtaProps\n } = actionButtonProps ?? {};\n\n const inputRefs = useRef<(HTMLInputElement | null)[]>([]);\n const onChangeRef = useRef(onChange);\n\n const [otpValues, setOtpValues] = useState<string[]>(\n new Array(numOfInput).fill(\"\")\n );\n const [countDown, setCountDown] = useState<number>(cooldownDuration);\n const [lastCtaTimestamp, setLastCtaTimestamp] = useState<Date>(new Date());\n const internalId = useId();\n\n const hasError = !!errorMessage;\n const errorId = `${internalId}-error`;\n const timerId = `${internalId}-timer`;\n\n // =============================================================================\n // EFFECTS\n // =============================================================================\n useEffect(() => {\n inputRefs?.current[0]?.focus();\n document.addEventListener(\"paste\", handlePaste);\n return () => document.removeEventListener(\"paste\", handlePaste);\n }, []);\n\n useEffect(() => {\n if (cooldownDuration !== 0) {\n if (onCooldownStart) onCooldownStart();\n const cleanup = beginCountdown();\n\n return () => cleanup();\n }\n }, [lastCtaTimestamp]);\n\n useImperativeHandle(ref, () => ({\n startCooldown: () => {\n setLastCtaTimestamp(new Date());\n setCountDown(cooldownDuration);\n },\n }));\n\n useEffect(() => {\n onChangeRef.current = onChange;\n }, [onChange]);\n\n useEffect(() => {\n if (value.length === numOfInput) {\n setOtpValues(value);\n }\n }, [value]);\n\n // =============================================================================\n // EVENT HANDLERS\n // =============================================================================\n const handleInputFullValue = (incomingValue: string) => {\n if (incomingValue && validateUserInput(incomingValue, numOfInput)) {\n const incomingValueArr = incomingValue.split(\"\");\n setOtpValues(incomingValueArr);\n if (onChangeRef.current) {\n onChangeRef.current(incomingValueArr);\n }\n\n return true;\n }\n\n return false;\n };\n\n const handleChange =\n (index: number) => (event: React.ChangeEvent<HTMLInputElement>) => {\n const eventValue = event.target.value;\n\n /* handle autofill */\n const fieldIsEmpty = otpValues.every((num) => num === \"\");\n const autofillOtp = stripOtpFromAutofill(\n eventValue,\n numOfInput,\n prefix\n );\n if (fieldIsEmpty && handleInputFullValue(autofillOtp)) {\n return;\n }\n\n /* handle normal input */\n const value = eventValue.replace(/[^0-9]/g, \"\");\n if (validateUserInput(value)) {\n const newOtpValues = [...otpValues];\n\n newOtpValues[index] = value.substring(value.length - 1);\n inputRefs.current[index + 1]?.focus();\n\n setOtpValues(newOtpValues);\n\n if (onChange) {\n onChange(newOtpValues);\n }\n }\n };\n\n const handleKeyDown =\n (index: number) => (event: React.KeyboardEvent<HTMLInputElement>) => {\n const { key, code } = event;\n\n if (key === \"Backspace\" || code === \"Backspace\") {\n const newOtpValues = [...otpValues];\n if (newOtpValues[index] !== \"\") {\n newOtpValues[index] = \"\";\n } else if (index !== 0) {\n newOtpValues[index - 1] = \"\";\n inputRefs.current[index - 1]?.focus();\n }\n\n setOtpValues(newOtpValues);\n\n if (onChange) {\n onChange(newOtpValues);\n }\n } else if (event.code === \"ArrowRight\") {\n inputRefs.current[index + 1]?.focus();\n } else if (event.code === \"ArrowLeft\") {\n inputRefs.current[index - 1]?.focus();\n }\n };\n\n const handlePaste = (event: ClipboardEvent): void => {\n if (!event.clipboardData) return;\n\n const pastedValue = event.clipboardData.getData(\"text\");\n const autofillOtp = stripOtpFromAutofill(\n pastedValue,\n numOfInput,\n prefix\n );\n if (!handleInputFullValue(autofillOtp)) {\n event.preventDefault();\n }\n };\n\n const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {\n setOtpValues(new Array(numOfInput).fill(\"\"));\n\n if (!isWithinCooldown()) {\n setLastCtaTimestamp(new Date());\n setCountDown(cooldownDuration);\n }\n\n if (onClick) {\n onClick(event);\n }\n };\n\n // =========================================================================\n // HELPER FUNCTIONS\n // =========================================================================\n const isWithinCooldown = (): boolean => {\n const currentTime = Date.now();\n const coolDownInMilliseconds = cooldownDuration * 1000;\n\n return (\n currentTime < lastCtaTimestamp.valueOf() + coolDownInMilliseconds\n );\n };\n\n const beginCountdown = () => {\n const interval = setInterval(() => {\n const currentTime = Date.now();\n const coolDownInMilliseconds = cooldownDuration * 1000;\n\n const timer = Math.ceil(\n (lastCtaTimestamp.valueOf() +\n coolDownInMilliseconds -\n currentTime) /\n 1000\n );\n setCountDown(timer);\n if (timer <= 0) {\n if (onCooldownEnd) onCooldownEnd();\n clearInterval(interval);\n } else if (onCountdownChange) {\n onCountdownChange(timer);\n }\n }, 1000);\n\n return () => {\n clearInterval(interval);\n };\n };\n\n const generateId = (index: number, name: string, prefix?: string) => {\n return prefix\n ? `${prefix}-${name}-${index + 1}`\n : `${name}-${index + 1}`;\n };\n\n const displaySeconds = (time: number) => {\n return `${time} second${time === 1 ? \"\" : \"s\"}`;\n };\n\n const getCTALabelProps = (): Partial<\n React.HTMLAttributes<HTMLButtonElement>\n > => {\n return otherCtaProps.children\n ? { children: otherCtaProps.children }\n : {\n children:\n countDown > 0\n ? `Resend OTP in ${displaySeconds(countDown)}`\n : \"Resend OTP\",\n // use a fixed label to avoid repeated screen reader updates when the button is focused\n \"aria-label\":\n countDown > 0\n ? `Resend OTP in ${displaySeconds(cooldownDuration)}`\n : \"Resend OTP\",\n // use a secondary element to reflect the latest countdown\n \"aria-describedby\": timerId,\n };\n };\n\n // =============================================================================\n // RENDER FUNCTIONS\n // =============================================================================\n return (\n <div\n id={id}\n data-testid={dataTestId}\n className={clsx(styles.wrapper, className)}\n >\n <div\n className={styles.inputContainer}\n role=\"group\"\n aria-label={`${numOfInput}-digit OTP input field`}\n >\n {prefix && (\n <Typography.BodyBL\n as=\"span\"\n className={styles.prefix}\n data-testid=\"otp-prefix\"\n weight=\"semibold\"\n >\n <VisuallyHidden>O T P prefix</VisuallyHidden>\n {`${prefix.value} ${prefix.separator}`}\n </Typography.BodyBL>\n )}\n {otpValues.map((data, index) => {\n return (\n <Input\n className={styles.inputField}\n id={generateId(index, \"otp-input\", id)}\n data-testid={generateId(\n index,\n \"otp-input\",\n dataTestId\n )}\n aria-label={`${StringHelper.formatOrdinal(\n index + 1\n )} digit`}\n aria-invalid={hasError}\n aria-describedby={hasError ? errorId : undefined}\n key={index}\n ref={(el) => (inputRefs.current[index] = el)}\n type=\"text\"\n inputMode=\"numeric\"\n value={data}\n error={hasError}\n onChange={handleChange(index)}\n onKeyDown={handleKeyDown(index)}\n autoComplete=\"off\"\n {...otherProps}\n />\n );\n })}\n </div>\n {errorMessage && (\n <FormErrorMessage id={errorId} data-testid=\"otp-error-message\">\n {errorMessage}\n </FormErrorMessage>\n )}\n {/* visually hidden elements need to be rendered before the button so that Voiceover/Chrome doesn't skip the button */}\n <VisuallyHidden role=\"timer\" id={timerId}>\n {displaySeconds(countDown)} remaining\n </VisuallyHidden>\n <VisuallyHidden aria-live=\"polite\">\n {countDown > 0 ? \"\" : \"Ready to resend OTP\"}\n </VisuallyHidden>\n {!otpOnly && (\n <Button\n className={styles.ctaButton}\n styleType={styleType}\n type=\"button\"\n sizeType=\"small\"\n {...otherCtaProps}\n onClick={handleClick}\n disabled={disabled || isWithinCooldown()}\n {...getCTALabelProps()}\n />\n )}\n </div>\n );\n};\n\n/**\n * A field composed of individual inputs for a numeric one-time password\n * with an in-built countdown mechanism.\n *\n * Use `OtpInput` when users must enter the one-time password (OTP)\n * for multi-factored authentication methods.\n */\nexport const OtpInput = forwardRef(Component);\n"],"names":["OtpInput","forwardRef","_a","ref","id","value","dataTestId","className","cooldownDuration","actionButtonProps","errorMessage","numOfInput","prefix","onChange","onCooldownStart","onCooldownEnd","otpOnly","onCountdownChange","otherProps","__rest","_b","disabled","onClick","styleType","otherCtaProps","inputRefs","useRef","onChangeRef","otpValues","setOtpValues","useState","Array","fill","countDown","setCountDown","lastCtaTimestamp","setLastCtaTimestamp","Date","internalId","useId","hasError","errorId","timerId","useEffect","current","focus","document","addEventListener","handlePaste","removeEventListener","cleanup","beginCountdown","useImperativeHandle","startCooldown","length","handleInputFullValue","incomingValue","validateUserInput","incomingValueArr","split","handleChange","index","event","eventValue","target","fieldIsEmpty","every","num","autofillOtp","stripOtpFromAutofill","replace","newOtpValues","substring","handleKeyDown","key","code","_c","clipboardData","pastedValue","getData","preventDefault","isWithinCooldown","currentTime","now","coolDownInMilliseconds","valueOf","interval","setInterval","timer","Math","ceil","clearInterval","generateId","name","displaySeconds","time","_jsxs","clsx","styles.wrapper","children","styles.inputContainer","role","Typography","BodyBL","as","styles.prefix","weight","_jsx","VisuallyHidden","separator","map","data","Input","Object","assign","styles.inputField","StringHelper","formatOrdinal","undefined","el","type","inputMode","error","onKeyDown","autoComplete","FormErrorMessage","Button","styles.ctaButton","sizeType"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"otp-verification.js","sources":["../../../src/otp-verification/otp-verification.tsx"],"sourcesContent":["import { announce, clearAnnouncer } from \"@react-aria/live-announcer\";\nimport clsx from \"clsx\";\nimport { useState } from \"react\";\n\nimport { useCountdown } from \"../util\";\nimport { ContactInputSection } from \"./contact-input-section\";\nimport * as styles from \"./otp-verification.styles\";\nimport type { OtpVerificationProps } from \"./types\";\nimport { VerificationSection } from \"./verification-section\";\n\nexport const OtpVerification = (props: OtpVerificationProps) => {\n // =============================================================================\n // CONST, STATE, REF\n // =============================================================================\n const {\n id,\n \"data-testid\": dataTestId,\n className,\n inputId,\n onSendOtp,\n onVerifyOtp,\n verifyOtpCountdownTimer = 60,\n sendOtpError,\n verifyOtpError,\n otpValue,\n onOtpChange,\n otpState,\n onOtpStateChange,\n otpReminderInterval = 120,\n } = props;\n\n const [isLoading, setIsLoading] = useState(false);\n const [isVerifyLoading, setIsVerifyLoading] = useState(false);\n\n const countdown = useCountdown({\n duration: verifyOtpCountdownTimer,\n reminderInterval: otpReminderInterval,\n getStartMessage: (duration) =>\n `You can resend the OTP in ${duration} seconds`,\n getIntervalMessage: (remaining) => `${remaining} seconds remaining`,\n getCompletionMessage: () => \"You can now resend the OTP\",\n });\n\n // =============================================================================\n // EVENT HANDLERS\n // =============================================================================\n // Send OTP\n const handleSendOtp = async () => {\n if (!onSendOtp || isLoading) return;\n\n try {\n setIsLoading(true);\n await onSendOtp();\n onOtpStateChange(\"sent\");\n countdown.reset();\n countdown.start();\n } catch {\n // do nothing\n } finally {\n setIsLoading(false);\n }\n };\n\n // Verify OTP\n const handleVerifyOtp = async () => {\n if (!onVerifyOtp || isVerifyLoading || !otpValue?.value) return;\n\n try {\n setIsVerifyLoading(true);\n await onVerifyOtp(otpValue.value);\n\n onOtpStateChange(\"verified\");\n\n clearAnnouncer(\"polite\");\n announce(\n \"Success. Your email or mobile number has been verified.\",\n \"polite\"\n );\n\n // Reset the countdown and clear the OTP code in case user enter new OTP later\n countdown.reset();\n onOtpChange?.(\"\");\n } catch {\n // do nothing\n } finally {\n setIsVerifyLoading(false);\n }\n };\n\n // =============================================================================\n // HELPER FUNCTIONS\n // =============================================================================\n const resetToDefault = () => {\n if (otpState === \"verified\") {\n onOtpStateChange(\"default\");\n }\n };\n\n // =============================================================================\n // RENDER FUNCTIONS\n // =============================================================================\n return (\n <div\n id={id}\n data-testid={dataTestId}\n className={clsx(styles.otpInputWrapper, className)}\n >\n <ContactInputSection\n {...props}\n inputId={inputId}\n data-testid={dataTestId ? `${dataTestId}-contact` : undefined}\n isLoading={isLoading}\n isVerified={otpState === \"verified\"}\n countdown={countdown}\n onSendOtp={handleSendOtp}\n onStateReset={resetToDefault}\n sendOtpError={sendOtpError}\n fixedCountry={\n props.type === \"phone-number\" ? props.fixedCountry : true\n }\n />\n\n {otpState === \"sent\" && (\n <VerificationSection\n {...props}\n data-testid={\n dataTestId ? `${dataTestId}-verification` : undefined\n }\n otpCode={otpValue?.value}\n otpPrefix={otpValue?.prefix}\n otpSeparator={otpValue?.separator}\n setOtpCode={onOtpChange}\n isVerifyLoading={isVerifyLoading}\n countdown={countdown}\n onVerifyOtp={handleVerifyOtp}\n verifyOtpError={verifyOtpError}\n />\n )}\n </div>\n );\n};\n"],"names":["props","id","dataTestId","className","inputId","onSendOtp","onVerifyOtp","verifyOtpCountdownTimer","sendOtpError","verifyOtpError","otpValue","onOtpChange","otpState","onOtpStateChange","otpReminderInterval","isLoading","setIsLoading","useState","isVerifyLoading","setIsVerifyLoading","countdown","useCountdown","duration","reminderInterval","getStartMessage","getIntervalMessage","remaining","getCompletionMessage","_jsxs","clsx","styles.otpInputWrapper","children","_jsx","ContactInputSection","Object","assign","undefined","isVerified","__awaiter","reset","start","_a","onStateReset","fixedCountry","type","VerificationSection","otpCode","value","otpPrefix","prefix","otpSeparator","separator","setOtpCode","clearAnnouncer","announce"],"mappings":"4kBAUgCA,IAI5B,MAAMC,GACFA,EACA,cAAeC,EAAUC,UACzBA,EAASC,QACTA,EAAOC,UACPA,EAASC,YACTA,EAAWC,wBACXA,EAA0B,GAAEC,aAC5BA,EAAYC,eACZA,EAAcC,SACdA,EAAQC,YACRA,EAAWC,SACXA,EAAQC,iBACRA,EAAgBC,oBAChBA,EAAsB,KACtBd,GAEGe,EAAWC,GAAgBC,EAAAA,UAAS,IACpCC,EAAiBC,GAAsBF,EAAAA,UAAS,GAEjDG,EAAYC,EAAAA,aAAa,CAC3BC,SAAUf,EACVgB,iBAAkBT,EAClBU,gBAAkBF,GACd,6BAA6BA,YACjCG,mBAAqBC,GAAc,GAAGA,sBACtCC,qBAAsB,IAAM,+BA6DhC,OACIC,OAAA,MAAA,CACI3B,GAAIA,gBACSC,EACbC,UAAW0B,UAAKC,EAAAA,gBAAwB3B,GAAU4B,SAAA,CAElDC,MAACC,EAAAA,oBAAmBC,OAAAC,OAAA,CAAA,EACZnC,EAAK,CACTI,QAASA,EAAO,cACHF,EAAa,GAAGA,iBAAuBkC,EACpDrB,UAAWA,EACXsB,WAAyB,aAAbzB,EACZQ,UAAWA,EACXf,UAnEU,IAAWiC,EAAAA,eAAA,OAAA,OAAA,GAAA,YAC7B,GAAKjC,IAAaU,EAElB,IACIC,GAAa,SACPX,IACNQ,EAAiB,QACjBO,EAAUmB,QACVnB,EAAUoB,OACd,CAAE,MAAAC,GAEF,SACIzB,GAAa,EACjB,CACJ,IAsDY0B,aAvBW,KACF,aAAb9B,GACAC,EAAiB,UACrB,EAqBQL,aAAcA,EACdmC,aACmB,iBAAf3C,EAAM4C,MAA0B5C,EAAM2C,gBAIhC,SAAb/B,GACGoB,EAAAA,IAACa,EAAAA,qCACO7C,EAAK,CAAA,cAELE,EAAa,GAAGA,sBAA4BkC,EAEhDU,QAASpC,eAAAA,EAAUqC,MACnBC,UAAWtC,aAAQ,EAARA,EAAUuC,OACrBC,aAAcxC,aAAQ,EAARA,EAAUyC,UACxBC,WAAYzC,EACZO,gBAAiBA,EACjBE,UAAWA,EACXd,YAtEQ,IAAWgC,EAAAA,eAAA,OAAA,OAAA,GAAA,YAC/B,GAAKhC,IAAeY,IAAoBR,aAAQ,EAARA,EAAUqC,OAElD,IACI5B,GAAmB,SACbb,EAAYI,EAASqC,OAE3BlC,EAAiB,YAEjBwC,EAAAA,eAAe,UACfC,EAAAA,SACI,0DACA,UAIJlC,EAAUmB,QACV5B,SAAAA,EAAc,GAClB,CAAE,MAAA8B,GAEF,SACItB,GAAmB,EACvB,CACJ,IAgDgBV,eAAgBA,OAGtB"}
1
+ {"version":3,"file":"otp-verification.js","sources":["../../../src/otp-verification/otp-verification.tsx"],"sourcesContent":["import { announce, clearAnnouncer } from \"@react-aria/live-announcer\";\nimport clsx from \"clsx\";\nimport { useState } from \"react\";\n\nimport { useCountdown } from \"../util\";\nimport { ContactInputSection } from \"./contact-input-section\";\nimport * as styles from \"./otp-verification.styles\";\nimport type { OtpVerificationProps } from \"./types\";\nimport { VerificationSection } from \"./verification-section\";\n\n/**\n * A multi-step form component that guides users through OTP-based verification.\n *\n * Use `OtpVerification` when you need to verify a user's identity through\n * email address or phone number.\n */\nexport const OtpVerification = (props: OtpVerificationProps) => {\n // =============================================================================\n // CONST, STATE, REF\n // =============================================================================\n const {\n id,\n \"data-testid\": dataTestId,\n className,\n inputId,\n onSendOtp,\n onVerifyOtp,\n verifyOtpCountdownTimer = 60,\n sendOtpError,\n verifyOtpError,\n otpValue,\n onOtpChange,\n otpState,\n onOtpStateChange,\n otpReminderInterval = 120,\n } = props;\n\n const [isLoading, setIsLoading] = useState(false);\n const [isVerifyLoading, setIsVerifyLoading] = useState(false);\n\n const countdown = useCountdown({\n duration: verifyOtpCountdownTimer,\n reminderInterval: otpReminderInterval,\n getStartMessage: (duration) =>\n `You can resend the OTP in ${duration} seconds`,\n getIntervalMessage: (remaining) => `${remaining} seconds remaining`,\n getCompletionMessage: () => \"You can now resend the OTP\",\n });\n\n // =============================================================================\n // EVENT HANDLERS\n // =============================================================================\n // Send OTP\n const handleSendOtp = async () => {\n if (!onSendOtp || isLoading) return;\n\n try {\n setIsLoading(true);\n await onSendOtp();\n onOtpStateChange(\"sent\");\n countdown.reset();\n countdown.start();\n } catch {\n // do nothing\n } finally {\n setIsLoading(false);\n }\n };\n\n // Verify OTP\n const handleVerifyOtp = async () => {\n if (!onVerifyOtp || isVerifyLoading || !otpValue?.value) return;\n\n try {\n setIsVerifyLoading(true);\n await onVerifyOtp(otpValue.value);\n\n onOtpStateChange(\"verified\");\n\n clearAnnouncer(\"polite\");\n announce(\n \"Success. Your email or mobile number has been verified.\",\n \"polite\"\n );\n\n // Reset the countdown and clear the OTP code in case user enter new OTP later\n countdown.reset();\n onOtpChange?.(\"\");\n } catch {\n // do nothing\n } finally {\n setIsVerifyLoading(false);\n }\n };\n\n // =============================================================================\n // HELPER FUNCTIONS\n // =============================================================================\n const resetToDefault = () => {\n if (otpState === \"verified\") {\n onOtpStateChange(\"default\");\n }\n };\n\n // =============================================================================\n // RENDER FUNCTIONS\n // =============================================================================\n return (\n <div\n id={id}\n data-testid={dataTestId}\n className={clsx(styles.otpInputWrapper, className)}\n >\n <ContactInputSection\n {...props}\n inputId={inputId}\n data-testid={dataTestId ? `${dataTestId}-contact` : undefined}\n isLoading={isLoading}\n isVerified={otpState === \"verified\"}\n countdown={countdown}\n onSendOtp={handleSendOtp}\n onStateReset={resetToDefault}\n sendOtpError={sendOtpError}\n fixedCountry={\n props.type === \"phone-number\" ? props.fixedCountry : true\n }\n />\n\n {otpState === \"sent\" && (\n <VerificationSection\n {...props}\n data-testid={\n dataTestId ? `${dataTestId}-verification` : undefined\n }\n otpCode={otpValue?.value}\n otpPrefix={otpValue?.prefix}\n otpSeparator={otpValue?.separator}\n setOtpCode={onOtpChange}\n isVerifyLoading={isVerifyLoading}\n countdown={countdown}\n onVerifyOtp={handleVerifyOtp}\n verifyOtpError={verifyOtpError}\n />\n )}\n </div>\n );\n};\n"],"names":["props","id","dataTestId","className","inputId","onSendOtp","onVerifyOtp","verifyOtpCountdownTimer","sendOtpError","verifyOtpError","otpValue","onOtpChange","otpState","onOtpStateChange","otpReminderInterval","isLoading","setIsLoading","useState","isVerifyLoading","setIsVerifyLoading","countdown","useCountdown","duration","reminderInterval","getStartMessage","getIntervalMessage","remaining","getCompletionMessage","_jsxs","clsx","styles.otpInputWrapper","children","_jsx","ContactInputSection","Object","assign","undefined","isVerified","__awaiter","reset","start","_a","onStateReset","fixedCountry","type","VerificationSection","otpCode","value","otpPrefix","prefix","otpSeparator","separator","setOtpCode","clearAnnouncer","announce"],"mappings":"4kBAgBgCA,IAI5B,MAAMC,GACFA,EACA,cAAeC,EAAUC,UACzBA,EAASC,QACTA,EAAOC,UACPA,EAASC,YACTA,EAAWC,wBACXA,EAA0B,GAAEC,aAC5BA,EAAYC,eACZA,EAAcC,SACdA,EAAQC,YACRA,EAAWC,SACXA,EAAQC,iBACRA,EAAgBC,oBAChBA,EAAsB,KACtBd,GAEGe,EAAWC,GAAgBC,EAAAA,UAAS,IACpCC,EAAiBC,GAAsBF,EAAAA,UAAS,GAEjDG,EAAYC,EAAAA,aAAa,CAC3BC,SAAUf,EACVgB,iBAAkBT,EAClBU,gBAAkBF,GACd,6BAA6BA,YACjCG,mBAAqBC,GAAc,GAAGA,sBACtCC,qBAAsB,IAAM,+BA6DhC,OACIC,OAAA,MAAA,CACI3B,GAAIA,gBACSC,EACbC,UAAW0B,UAAKC,EAAAA,gBAAwB3B,GAAU4B,SAAA,CAElDC,MAACC,EAAAA,oBAAmBC,OAAAC,OAAA,CAAA,EACZnC,EAAK,CACTI,QAASA,EAAO,cACHF,EAAa,GAAGA,iBAAuBkC,EACpDrB,UAAWA,EACXsB,WAAyB,aAAbzB,EACZQ,UAAWA,EACXf,UAnEU,IAAWiC,EAAAA,eAAA,OAAA,OAAA,GAAA,YAC7B,GAAKjC,IAAaU,EAElB,IACIC,GAAa,SACPX,IACNQ,EAAiB,QACjBO,EAAUmB,QACVnB,EAAUoB,OACd,CAAE,MAAAC,GAEF,SACIzB,GAAa,EACjB,CACJ,IAsDY0B,aAvBW,KACF,aAAb9B,GACAC,EAAiB,UACrB,EAqBQL,aAAcA,EACdmC,aACmB,iBAAf3C,EAAM4C,MAA0B5C,EAAM2C,gBAIhC,SAAb/B,GACGoB,EAAAA,IAACa,EAAAA,qCACO7C,EAAK,CAAA,cAELE,EAAa,GAAGA,sBAA4BkC,EAEhDU,QAASpC,eAAAA,EAAUqC,MACnBC,UAAWtC,aAAQ,EAARA,EAAUuC,OACrBC,aAAcxC,aAAQ,EAARA,EAAUyC,UACxBC,WAAYzC,EACZO,gBAAiBA,EACjBE,UAAWA,EACXd,YAtEQ,IAAWgC,EAAAA,eAAA,OAAA,OAAA,GAAA,YAC/B,GAAKhC,IAAeY,IAAoBR,aAAQ,EAARA,EAAUqC,OAElD,IACI5B,GAAmB,SACbb,EAAYI,EAASqC,OAE3BlC,EAAiB,YAEjBwC,EAAAA,eAAe,UACfC,EAAAA,SACI,0DACA,UAIJlC,EAAUmB,QACV5B,SAAAA,EAAc,GAClB,CAAE,MAAA8B,GAEF,SACItB,GAAmB,EACvB,CACJ,IAgDgBV,eAAgBA,OAGtB"}
@@ -1 +1 @@
1
- {"version":3,"file":"overlay.js","sources":["../../../src/overlay/overlay.tsx"],"sourcesContent":["import {\n FloatingNode,\n FloatingTree,\n useFloatingNodeId,\n} from \"@floating-ui/react\";\nimport clsx from \"clsx\";\nimport type React from \"react\";\nimport { useEffect, useRef, useState } from \"react\";\nimport ReactDOM from \"react-dom\";\n\nimport { useApplyStyle, useInheritedThemeScope } from \"../theme\";\nimport { useId } from \"../util\";\nimport * as styles from \"./overlay.styles\";\nimport type { OverlayProps } from \"./types\";\nimport { useFloatingParent } from \"./use-floating-context\";\n\nconst OverlayComponent = ({\n show = false,\n rootId,\n onOverlayClick,\n children,\n backgroundBlur = true,\n disableTransition = false,\n enableOverlayClick = false,\n zIndex: customZIndex,\n id,\n containerRef,\n}: OverlayProps): JSX.Element | null => {\n // =============================================================================\n // CONST, STATE, REF\n // =============================================================================\n const [rootElement, setRootElement] = useState<HTMLElement | null>(null);\n const [isStacked, _setIsStacked] = useState<boolean>();\n const uid = useId();\n const nodeId = useFloatingNodeId();\n\n const stacked = useRef<boolean>();\n // Track where mousedown started to prevent closing drawer during text selection drag\n const mouseDownInsideModalRef = useRef(false);\n const rootRef = useRef<HTMLDivElement>(null);\n const wrapperRef = useRef<HTMLDivElement>(null);\n\n const overlayRootId = id\n ? `lifesg-ds-overlay-root-${id}`\n : \"lifesg-ds-overlay-root\";\n const zIndex = customZIndex ?? (isStacked ? 99999 : 99998);\n const { themeProps, themeStyle } = useInheritedThemeScope(show);\n\n useFloatingParent(zIndex);\n\n useApplyStyle(rootRef, { [styles.tokens.root.zIndex]: zIndex });\n\n // =============================================================================\n // EFFECTS\n // =============================================================================\n useEffect(() => {\n initialiseStylesForDocumentBody();\n setRootElement(getRootElement());\n\n return () => {\n removeOverlay();\n\n if (getOverlayOrder().length < 1) {\n if (isIOS()) {\n applyScrollLockClassForIOS(\"remove\");\n scrollToLastScrollPositionForIOS();\n }\n\n applyBodyStyleClass(\"remove\");\n }\n };\n }, []);\n\n useEffect(() => {\n if (show) {\n const isStacked = checkIfStacked();\n setStacked(isStacked);\n\n addOverlay();\n\n if (isIOS() && getOverlayOrder().length === 1) {\n saveScrollPosition();\n applyScrollLockClassForIOS(\"add\");\n }\n\n const timerId = setTimeout(() => {\n applyBodyStyleClass(\"add\");\n }, 200); // Allow overlay animations to complete\n\n return () => clearTimeout(timerId);\n } else {\n removeOverlay();\n\n if (isIOS() && getOverlayOrder().length < 1) {\n applyScrollLockClassForIOS(\"remove\");\n scrollToLastScrollPositionForIOS();\n }\n\n const timerId = setTimeout(() => {\n if (getOverlayOrder().length < 1) {\n applyBodyStyleClass(\"remove\");\n }\n }, 200); // Allow overlay animations to complete\n\n return () => clearTimeout(timerId);\n }\n }, [show]);\n\n // Track mousedown origin to distinguish clicks from text selection drags\n useEffect(() => {\n if (!show) return;\n\n document.addEventListener(\"mousedown\", handleDocumentMouseDown, true);\n return () => {\n document.removeEventListener(\n \"mousedown\",\n handleDocumentMouseDown,\n true\n );\n };\n }, [show]);\n\n // =============================================================================\n // REF FUNCTIONS\n // =============================================================================\n const setStacked = (data: boolean) => {\n stacked.current = data;\n _setIsStacked(data);\n };\n\n // =============================================================================\n // HELPER FUNCTIONS\n // =============================================================================\n const isIOS = () => /(iPad|iPhone|iPod)/g.test(navigator.userAgent);\n\n const getRootElement = (): HTMLElement | null => {\n if (document && rootId) {\n return document.getElementById(rootId);\n } else if (document) {\n // If rootId not specified, we'll use body\n return document.body;\n } else {\n return null;\n }\n };\n\n const checkIfStacked = () => {\n return getOverlayOrder().length > 0;\n };\n\n const initialiseStylesForDocumentBody = () => {\n const documentWidth = document.documentElement.clientWidth;\n const windowWidth = window.innerWidth;\n const scrollBarWidth = windowWidth - documentWidth;\n\n document.documentElement.style.setProperty(\n styles.tokens.global.scrollbarWidth,\n `${scrollBarWidth}px`\n );\n };\n\n /**\n * This sets the style of <body> to hide the scrollbar\n */\n const applyBodyStyleClass = (action: \"add\" | \"remove\") => {\n const isOverlayStyleClassApplied = document.body.classList.contains(\n styles.tokens.global.overlayOpenClass\n );\n\n if (action === \"add\" && !isOverlayStyleClassApplied) {\n document.body.classList.add(styles.tokens.global.overlayOpenClass);\n } else if (action === \"remove\" && isOverlayStyleClassApplied) {\n document.body.classList.remove(\n styles.tokens.global.overlayOpenClass\n );\n }\n };\n\n const getOverlayOrder = () => {\n const attr = document.body.dataset.lifesgDsOverlayOrder;\n return attr ? attr.split(\",\") : [];\n };\n\n const addOverlay = () => {\n const order = getOverlayOrder();\n document.body.dataset.lifesgDsOverlayOrder = [...order, uid].join(\",\");\n };\n\n const removeOverlay = () => {\n const order = getOverlayOrder();\n document.body.dataset.lifesgDsOverlayOrder = order\n .filter((o) => o !== uid)\n .join(\",\");\n };\n\n /**\n * This sets the style of <body> to further prevent scrolling on iOS\n *\n * ref: https://stackoverflow.com/a/57455820/3932279\n * `overflow: hidden` and `overscroll-behavior` is ignored by iOS, this is\n * an alternative solution\n *\n * as a side effect this causes the scroll position to reset, so additional\n * logic to restore the scroll on close is required\n */\n const applyScrollLockClassForIOS = (action: \"add\" | \"remove\") => {\n if (!isIOS()) {\n return;\n }\n\n const isClassApplied = document.body.classList.contains(\n styles.tokens.global.overlayScrollLockClass\n );\n\n if (action === \"add\" && !isClassApplied) {\n document.body.classList.add(\n styles.tokens.global.overlayScrollLockClass\n );\n } else if (action === \"remove\" && isClassApplied) {\n document.body.classList.remove(\n styles.tokens.global.overlayScrollLockClass\n );\n }\n };\n\n const saveScrollPosition = () => {\n const bodyStyle = document.body.style;\n const scrollY = bodyStyle.top ? bodyStyle.top : window.scrollY + \"px\";\n\n document.body.style.setProperty(styles.tokens.global.scrollY, scrollY);\n };\n\n const scrollToLastScrollPositionForIOS = () => {\n if (!isIOS()) {\n return;\n }\n\n const scrollY = document.body.style.getPropertyValue(\n styles.tokens.global.scrollY\n );\n requestAnimationFrame(() => {\n window.scrollTo({\n top: parseFloat(scrollY),\n });\n });\n };\n\n // =============================================================================\n // EVENT HANDLERS\n // =============================================================================\n const handleDocumentMouseDown = (e: MouseEvent) => {\n const container = containerRef?.current ?? wrapperRef.current;\n const wrapper = wrapperRef.current;\n if (!container) {\n mouseDownInsideModalRef.current = false;\n return;\n }\n\n const target = e.target as Node;\n const clickedOnWrapper = wrapper === target;\n const clickedOnContainer = container === target;\n const clickedInsideContainer = container.contains(target);\n\n // Track if mousedown started inside modal content\n mouseDownInsideModalRef.current =\n !clickedOnWrapper && (clickedOnContainer || clickedInsideContainer);\n };\n\n const handleWrapperClick = (event: React.MouseEvent<HTMLDivElement>) => {\n const container = containerRef?.current ?? wrapperRef.current;\n const wrapper = wrapperRef.current;\n if (!container) {\n mouseDownInsideModalRef.current = false;\n return;\n }\n\n const target = event.target as Node;\n const clickedOnWrapper = wrapper === target;\n const clickedOnContainer = container === target;\n const clickedInsideContainer = container.contains(target);\n const clickedInsideModal = clickedOnContainer || clickedInsideContainer;\n\n // Only close if both mousedown AND click happened outside modal\n if (\n (clickedOnWrapper || !clickedInsideModal) &&\n !mouseDownInsideModalRef.current &&\n onOverlayClick &&\n enableOverlayClick\n ) {\n event.preventDefault();\n onOverlayClick();\n }\n\n mouseDownInsideModalRef.current = false;\n };\n\n // =============================================================================\n // RENDER\n // =============================================================================\n const renderWrapper = () => (\n <FloatingNode id={nodeId}>\n <div\n ref={wrapperRef}\n data-testid=\"overlay-wrapper\"\n className={clsx(\n styles.wrapper,\n show ? styles.wrapperShow : styles.wrapperHide,\n isStacked && styles.wrapperStacked,\n backgroundBlur && styles.wrapperBackgroundBlur,\n disableTransition && styles.wrapperDisableTransition\n )}\n onClick={handleWrapperClick}\n >\n {children}\n </div>\n </FloatingNode>\n );\n\n const renderComponent = () => (\n <div\n ref={rootRef}\n id={overlayRootId}\n data-testid={overlayRootId}\n className={clsx(styles.root, show && styles.rootShow)}\n {...themeProps}\n style={themeStyle}\n >\n {children && renderWrapper()}\n </div>\n );\n\n return rootElement\n ? ReactDOM.createPortal(renderComponent(), rootElement)\n : null;\n};\n\nexport const Overlay = (props: OverlayProps) => {\n return (\n <FloatingTree>\n <OverlayComponent {...props} />\n </FloatingTree>\n );\n};\n"],"names":["OverlayComponent","show","rootId","onOverlayClick","children","backgroundBlur","disableTransition","enableOverlayClick","zIndex","customZIndex","id","containerRef","rootElement","setRootElement","useState","isStacked","_setIsStacked","uid","useId","nodeId","useFloatingNodeId","stacked","useRef","mouseDownInsideModalRef","rootRef","wrapperRef","overlayRootId","themeProps","themeStyle","useInheritedThemeScope","useFloatingParent","useApplyStyle","styles.tokens","root","useEffect","initialiseStylesForDocumentBody","getRootElement","removeOverlay","getOverlayOrder","length","isIOS","applyScrollLockClassForIOS","scrollToLastScrollPositionForIOS","applyBodyStyleClass","checkIfStacked","setStacked","addOverlay","saveScrollPosition","timerId","setTimeout","clearTimeout","document","addEventListener","handleDocumentMouseDown","removeEventListener","data","current","test","navigator","userAgent","getElementById","body","documentWidth","documentElement","clientWidth","scrollBarWidth","window","innerWidth","style","setProperty","global","scrollbarWidth","action","isOverlayStyleClassApplied","classList","contains","overlayOpenClass","remove","add","attr","dataset","lifesgDsOverlayOrder","split","order","join","filter","o","isClassApplied","overlayScrollLockClass","bodyStyle","scrollY","top","getPropertyValue","requestAnimationFrame","scrollTo","parseFloat","e","container","_a","wrapper","target","clickedOnWrapper","clickedOnContainer","clickedInsideContainer","handleWrapperClick","event","preventDefault","ReactDOM","createPortal","_jsx","Object","assign","ref","className","clsx","styles.root","styles.rootShow","FloatingNode","styles.wrapper","styles.wrapperShow","styles.wrapperHide","styles.wrapperStacked","styles.wrapperBackgroundBlur","styles.wrapperDisableTransition","onClick","props","FloatingTree"],"mappings":"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"}
1
+ {"version":3,"file":"overlay.js","sources":["../../../src/overlay/overlay.tsx"],"sourcesContent":["import {\n FloatingNode,\n FloatingTree,\n useFloatingNodeId,\n} from \"@floating-ui/react\";\nimport clsx from \"clsx\";\nimport type React from \"react\";\nimport { useEffect, useRef, useState } from \"react\";\nimport ReactDOM from \"react-dom\";\n\nimport { useApplyStyle, useInheritedThemeScope } from \"../theme\";\nimport { useId } from \"../util\";\nimport * as styles from \"./overlay.styles\";\nimport type { OverlayProps } from \"./types\";\nimport { useFloatingParent } from \"./use-floating-context\";\n\nconst OverlayComponent = ({\n show = false,\n rootId,\n onOverlayClick,\n children,\n backgroundBlur = true,\n disableTransition = false,\n enableOverlayClick = false,\n zIndex: customZIndex,\n id,\n containerRef,\n}: OverlayProps): JSX.Element | null => {\n // =============================================================================\n // CONST, STATE, REF\n // =============================================================================\n const [rootElement, setRootElement] = useState<HTMLElement | null>(null);\n const [isStacked, _setIsStacked] = useState<boolean>();\n const uid = useId();\n const nodeId = useFloatingNodeId();\n\n const stacked = useRef<boolean>();\n // Track where mousedown started to prevent closing drawer during text selection drag\n const mouseDownInsideModalRef = useRef(false);\n const rootRef = useRef<HTMLDivElement>(null);\n const wrapperRef = useRef<HTMLDivElement>(null);\n\n const overlayRootId = id\n ? `lifesg-ds-overlay-root-${id}`\n : \"lifesg-ds-overlay-root\";\n const zIndex = customZIndex ?? (isStacked ? 99999 : 99998);\n const { themeProps, themeStyle } = useInheritedThemeScope(show);\n\n useFloatingParent(zIndex);\n\n useApplyStyle(rootRef, { [styles.tokens.root.zIndex]: zIndex });\n\n // =============================================================================\n // EFFECTS\n // =============================================================================\n useEffect(() => {\n initialiseStylesForDocumentBody();\n setRootElement(getRootElement());\n\n return () => {\n removeOverlay();\n\n if (getOverlayOrder().length < 1) {\n if (isIOS()) {\n applyScrollLockClassForIOS(\"remove\");\n scrollToLastScrollPositionForIOS();\n }\n\n applyBodyStyleClass(\"remove\");\n }\n };\n }, []);\n\n useEffect(() => {\n if (show) {\n const isStacked = checkIfStacked();\n setStacked(isStacked);\n\n addOverlay();\n\n if (isIOS() && getOverlayOrder().length === 1) {\n saveScrollPosition();\n applyScrollLockClassForIOS(\"add\");\n }\n\n const timerId = setTimeout(() => {\n applyBodyStyleClass(\"add\");\n }, 200); // Allow overlay animations to complete\n\n return () => clearTimeout(timerId);\n } else {\n removeOverlay();\n\n if (isIOS() && getOverlayOrder().length < 1) {\n applyScrollLockClassForIOS(\"remove\");\n scrollToLastScrollPositionForIOS();\n }\n\n const timerId = setTimeout(() => {\n if (getOverlayOrder().length < 1) {\n applyBodyStyleClass(\"remove\");\n }\n }, 200); // Allow overlay animations to complete\n\n return () => clearTimeout(timerId);\n }\n }, [show]);\n\n // Track mousedown origin to distinguish clicks from text selection drags\n useEffect(() => {\n if (!show) return;\n\n document.addEventListener(\"mousedown\", handleDocumentMouseDown, true);\n return () => {\n document.removeEventListener(\n \"mousedown\",\n handleDocumentMouseDown,\n true\n );\n };\n }, [show]);\n\n // =============================================================================\n // REF FUNCTIONS\n // =============================================================================\n const setStacked = (data: boolean) => {\n stacked.current = data;\n _setIsStacked(data);\n };\n\n // =============================================================================\n // HELPER FUNCTIONS\n // =============================================================================\n const isIOS = () => /(iPad|iPhone|iPod)/g.test(navigator.userAgent);\n\n const getRootElement = (): HTMLElement | null => {\n if (document && rootId) {\n return document.getElementById(rootId);\n } else if (document) {\n // If rootId not specified, we'll use body\n return document.body;\n } else {\n return null;\n }\n };\n\n const checkIfStacked = () => {\n return getOverlayOrder().length > 0;\n };\n\n const initialiseStylesForDocumentBody = () => {\n const documentWidth = document.documentElement.clientWidth;\n const windowWidth = window.innerWidth;\n const scrollBarWidth = windowWidth - documentWidth;\n\n document.documentElement.style.setProperty(\n styles.tokens.global.scrollbarWidth,\n `${scrollBarWidth}px`\n );\n };\n\n /**\n * This sets the style of <body> to hide the scrollbar\n */\n const applyBodyStyleClass = (action: \"add\" | \"remove\") => {\n const isOverlayStyleClassApplied = document.body.classList.contains(\n styles.tokens.global.overlayOpenClass\n );\n\n if (action === \"add\" && !isOverlayStyleClassApplied) {\n document.body.classList.add(styles.tokens.global.overlayOpenClass);\n } else if (action === \"remove\" && isOverlayStyleClassApplied) {\n document.body.classList.remove(\n styles.tokens.global.overlayOpenClass\n );\n }\n };\n\n const getOverlayOrder = () => {\n const attr = document.body.dataset.lifesgDsOverlayOrder;\n return attr ? attr.split(\",\") : [];\n };\n\n const addOverlay = () => {\n const order = getOverlayOrder();\n document.body.dataset.lifesgDsOverlayOrder = [...order, uid].join(\",\");\n };\n\n const removeOverlay = () => {\n const order = getOverlayOrder();\n document.body.dataset.lifesgDsOverlayOrder = order\n .filter((o) => o !== uid)\n .join(\",\");\n };\n\n /**\n * This sets the style of <body> to further prevent scrolling on iOS\n *\n * ref: https://stackoverflow.com/a/57455820/3932279\n * `overflow: hidden` and `overscroll-behavior` is ignored by iOS, this is\n * an alternative solution\n *\n * as a side effect this causes the scroll position to reset, so additional\n * logic to restore the scroll on close is required\n */\n const applyScrollLockClassForIOS = (action: \"add\" | \"remove\") => {\n if (!isIOS()) {\n return;\n }\n\n const isClassApplied = document.body.classList.contains(\n styles.tokens.global.overlayScrollLockClass\n );\n\n if (action === \"add\" && !isClassApplied) {\n document.body.classList.add(\n styles.tokens.global.overlayScrollLockClass\n );\n } else if (action === \"remove\" && isClassApplied) {\n document.body.classList.remove(\n styles.tokens.global.overlayScrollLockClass\n );\n }\n };\n\n const saveScrollPosition = () => {\n const bodyStyle = document.body.style;\n const scrollY = bodyStyle.top ? bodyStyle.top : window.scrollY + \"px\";\n\n document.body.style.setProperty(styles.tokens.global.scrollY, scrollY);\n };\n\n const scrollToLastScrollPositionForIOS = () => {\n if (!isIOS()) {\n return;\n }\n\n const scrollY = document.body.style.getPropertyValue(\n styles.tokens.global.scrollY\n );\n requestAnimationFrame(() => {\n window.scrollTo({\n top: parseFloat(scrollY),\n });\n });\n };\n\n // =============================================================================\n // EVENT HANDLERS\n // =============================================================================\n const handleDocumentMouseDown = (e: MouseEvent) => {\n const container = containerRef?.current ?? wrapperRef.current;\n const wrapper = wrapperRef.current;\n if (!container) {\n mouseDownInsideModalRef.current = false;\n return;\n }\n\n const target = e.target as Node;\n const clickedOnWrapper = wrapper === target;\n const clickedOnContainer = container === target;\n const clickedInsideContainer = container.contains(target);\n\n // Track if mousedown started inside modal content\n mouseDownInsideModalRef.current =\n !clickedOnWrapper && (clickedOnContainer || clickedInsideContainer);\n };\n\n const handleWrapperClick = (event: React.MouseEvent<HTMLDivElement>) => {\n const container = containerRef?.current ?? wrapperRef.current;\n const wrapper = wrapperRef.current;\n if (!container) {\n mouseDownInsideModalRef.current = false;\n return;\n }\n\n const target = event.target as Node;\n const clickedOnWrapper = wrapper === target;\n const clickedOnContainer = container === target;\n const clickedInsideContainer = container.contains(target);\n const clickedInsideModal = clickedOnContainer || clickedInsideContainer;\n\n // Only close if both mousedown AND click happened outside modal\n if (\n (clickedOnWrapper || !clickedInsideModal) &&\n !mouseDownInsideModalRef.current &&\n onOverlayClick &&\n enableOverlayClick\n ) {\n event.preventDefault();\n onOverlayClick();\n }\n\n mouseDownInsideModalRef.current = false;\n };\n\n // =============================================================================\n // RENDER\n // =============================================================================\n const renderWrapper = () => (\n <FloatingNode id={nodeId}>\n <div\n ref={wrapperRef}\n data-testid=\"overlay-wrapper\"\n className={clsx(\n styles.wrapper,\n show ? styles.wrapperShow : styles.wrapperHide,\n isStacked && styles.wrapperStacked,\n backgroundBlur && styles.wrapperBackgroundBlur,\n disableTransition && styles.wrapperDisableTransition\n )}\n onClick={handleWrapperClick}\n >\n {children}\n </div>\n </FloatingNode>\n );\n\n const renderComponent = () => (\n <div\n ref={rootRef}\n id={overlayRootId}\n data-testid={overlayRootId}\n className={clsx(styles.root, show && styles.rootShow)}\n {...themeProps}\n style={themeStyle}\n >\n {children && renderWrapper()}\n </div>\n );\n\n return rootElement\n ? ReactDOM.createPortal(renderComponent(), rootElement)\n : null;\n};\n\n/**\n * A full-screen dimmed overlay backdrop.\n *\n * Use `Overlay` as the backdrop for modal dialogs, drawers, and similar\n * blocking UI patterns. It manages body scroll-lock automatically and stacks\n * correctly when multiple overlays are open at once.\n */\nexport const Overlay = (props: OverlayProps) => {\n return (\n <FloatingTree>\n <OverlayComponent {...props} />\n </FloatingTree>\n );\n};\n"],"names":["OverlayComponent","show","rootId","onOverlayClick","children","backgroundBlur","disableTransition","enableOverlayClick","zIndex","customZIndex","id","containerRef","rootElement","setRootElement","useState","isStacked","_setIsStacked","uid","useId","nodeId","useFloatingNodeId","stacked","useRef","mouseDownInsideModalRef","rootRef","wrapperRef","overlayRootId","themeProps","themeStyle","useInheritedThemeScope","useFloatingParent","useApplyStyle","styles.tokens","root","useEffect","initialiseStylesForDocumentBody","getRootElement","removeOverlay","getOverlayOrder","length","isIOS","applyScrollLockClassForIOS","scrollToLastScrollPositionForIOS","applyBodyStyleClass","checkIfStacked","setStacked","addOverlay","saveScrollPosition","timerId","setTimeout","clearTimeout","document","addEventListener","handleDocumentMouseDown","removeEventListener","data","current","test","navigator","userAgent","getElementById","body","documentWidth","documentElement","clientWidth","scrollBarWidth","window","innerWidth","style","setProperty","global","scrollbarWidth","action","isOverlayStyleClassApplied","classList","contains","overlayOpenClass","remove","add","attr","dataset","lifesgDsOverlayOrder","split","order","join","filter","o","isClassApplied","overlayScrollLockClass","bodyStyle","scrollY","top","getPropertyValue","requestAnimationFrame","scrollTo","parseFloat","e","container","_a","wrapper","target","clickedOnWrapper","clickedOnContainer","clickedInsideContainer","handleWrapperClick","event","preventDefault","ReactDOM","createPortal","_jsx","Object","assign","ref","className","clsx","styles.root","styles.rootShow","FloatingNode","styles.wrapper","styles.wrapperShow","styles.wrapperHide","styles.wrapperStacked","styles.wrapperBackgroundBlur","styles.wrapperDisableTransition","onClick","props","FloatingTree"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"pagination.js","sources":["../../../src/pagination/pagination.tsx"],"sourcesContent":["import { Chevron2LeftIcon } from \"@lifesg/react-icons/chevron-2-left\";\nimport { Chevron2RightIcon } from \"@lifesg/react-icons/chevron-2-right\";\nimport { ChevronLeftIcon } from \"@lifesg/react-icons/chevron-left\";\nimport { ChevronLineLeftIcon } from \"@lifesg/react-icons/chevron-line-left\";\nimport { ChevronLineRightIcon } from \"@lifesg/react-icons/chevron-line-right\";\nimport { ChevronRightIcon } from \"@lifesg/react-icons/chevron-right\";\nimport { EllipsisHorizontalIcon } from \"@lifesg/react-icons/ellipsis-horizontal\";\nimport clsx from \"clsx\";\nimport React, { useEffect, useState } from \"react\";\n\nimport { Input } from \"../input\";\nimport { InputSelect } from \"../input-select\";\nimport { VisuallyHidden } from \"../shared/accessibility\";\nimport { ClickableIcon } from \"../shared/clickable-icon\";\nimport { useMaxWidthMediaQuery } from \"../theme\";\nimport { Typography } from \"../typography\";\nimport { useId, useIsMounted } from \"../util\";\nimport * as styles from \"./pagination.styles\";\nimport type { PageSizeItemProps, PaginationProps } from \"./types\";\n\nconst Component = (\n {\n id,\n \"data-testid\": dataTestId,\n className,\n pageSize = 10,\n totalItems,\n activePage,\n pageSizeOptions = DEFAULT_OPTIONS,\n showFirstAndLastNav,\n showPageSizeChanger = false,\n onPageChange,\n onPageSizeChange,\n }: PaginationProps,\n ref: React.Ref<HTMLDivElement>\n) => {\n // =============================================================================\n // CONST, STATE, REF\n // =============================================================================\n\n const isMounted = useIsMounted();\n const isMobile = useMaxWidthMediaQuery(\"sm\");\n const [hoverRightButton, setHoverRightButton] = useState(false);\n const [hoverLeftButton, setHoverLeftButton] = useState(false);\n const [inputText, setInputText] = useState<string>(\"\");\n\n const [selectedOption, setSelectedOption] = useState<\n PageSizeItemProps | undefined\n >(pageSizeOptions[0]);\n const [pageSizeLocal, setPageSize] = useState<number>(\n !isMobile && showPageSizeChanger\n ? selectedOption\n ? selectedOption.value\n : pageSize\n : pageSize\n );\n\n const boundaryRange = 1;\n const siblingRange = 1;\n\n const internalId = useId();\n const paginationId = `${internalId}-pagination`;\n\n const totalPages = Math.ceil(totalItems / pageSizeLocal);\n const isFirstPage = activePage === 1;\n const isLastPage = activePage === totalPages;\n\n const firstPaginationItem =\n activePage > 1 ? () => handlePaginationItemClick(1) : undefined;\n const lastPaginationItem =\n activePage < totalPages\n ? () => handlePaginationItemClick(totalPages)\n : undefined;\n const prevPaginationItem =\n activePage > 1\n ? () => handlePaginationItemClick(activePage - 1)\n : undefined;\n const nextPaginationItem =\n activePage < totalPages\n ? () =>\n handlePaginationItemClick(parseInt(activePage.toString()) + 1)\n : undefined;\n\n // =============================================================================\n // EFFECTS\n // =============================================================================\n useEffect(() => {\n if (activePage) {\n setInputValue(activePage);\n }\n }, [activePage]);\n\n useEffect(() => {\n setPageSize(pageSize);\n setSelectedOption(\n pageSizeOptions.find((option) => option.value === pageSize)\n );\n }, [pageSize]);\n\n // =============================================================================\n // HELPER FUNCTIONS\n // =============================================================================\n const setInputValue = (value: number) => {\n setInputText(value.toString());\n };\n\n const closeAllTooltips = () => {\n setHoverRightButton(false);\n setHoverLeftButton(false);\n };\n\n // =============================================================================\n // EVENT HANDLERS\n // =============================================================================\n const handlePaginationItemClick = (pageIndex: number) => {\n if (onPageChange) {\n onPageChange(pageIndex);\n setInputValue(pageIndex);\n }\n };\n\n const handleFastForwardClick = () => {\n const currentIndex = Math.min(totalPages, activePage + 5);\n handlePaginationItemClick(currentIndex);\n setInputValue(currentIndex);\n setHoverRightButton(true);\n setHoverLeftButton(false);\n };\n\n const handleFastBackwardClick = () => {\n const currentIndex = Math.max(1, activePage - 5);\n handlePaginationItemClick(currentIndex);\n setInputValue(currentIndex);\n setHoverRightButton(false);\n setHoverLeftButton(true);\n };\n\n const handleInput = (event: React.ChangeEvent<HTMLInputElement>) => {\n const value = event.target.value;\n const numericRegex = /^[0-9]+$/;\n if (value === undefined || value.length === 0) {\n setInputText(\"\");\n } else if (!numericRegex.test(value)) {\n setInputText(value.replace(/[^0-9]/g, \"\"));\n } else {\n const newPage = parseInt(value.replace(/[^0-9]/g, \"\"));\n setInputValue(Math.max(1, Math.min(totalPages, newPage)));\n }\n };\n\n const handleInputSubmit = (event: React.FormEvent) => {\n event.preventDefault();\n if (inputText) {\n onPageChange?.(parseInt(inputText));\n }\n };\n\n const onHoverRightButton = () => {\n setHoverRightButton(true);\n };\n\n const onBlurRightButton = () => {\n setHoverRightButton(false);\n };\n\n const onHoverLeftButton = () => {\n setHoverLeftButton(true);\n };\n\n const onBlurLeftButton = () => {\n setHoverLeftButton(false);\n };\n\n const handleListItemClick = (item: PageSizeItemProps) => {\n setSelectedOption(item);\n const pagesize = item.value;\n const totalPage = Math.ceil(totalItems / pagesize);\n\n setPageSize(pagesize);\n\n const page = activePage >= totalPage ? totalPage : activePage;\n\n if (onPageSizeChange) {\n onPageSizeChange(page, pagesize);\n }\n };\n\n // =============================================================================\n // RENDER FUNCTIONS\n // =============================================================================\n const renderPaginationItems = () => {\n return [...Array(totalPages)].map((e, i) => {\n const pageIndex = i + 1;\n const startRange = boundaryRange + 2 + siblingRange * 2;\n const endRange = totalPages - startRange;\n const totalRange = (boundaryRange + siblingRange) * 2 + 3;\n const active = activePage === pageIndex;\n if (totalPages <= totalRange) {\n return (\n <button\n key={pageIndex}\n onClick={() => handlePaginationItemClick(pageIndex)}\n className={clsx(\n styles.pageItem,\n active && styles.pageItemSelected\n )}\n aria-label={`page ${pageIndex} of ${totalPages}`}\n aria-current={active ? \"page\" : false}\n onMouseOver={closeAllTooltips}\n onFocus={closeAllTooltips}\n >\n {pageIndex}\n </button>\n );\n }\n\n const ellipsisStart =\n activePage + siblingRange > startRange &&\n pageIndex === boundaryRange + 1;\n if (ellipsisStart) {\n return renderStartEllipsis(pageIndex);\n }\n\n const ellipsisEnd =\n activePage - siblingRange <= endRange &&\n pageIndex === totalPages - boundaryRange - 1;\n if (ellipsisEnd) {\n return renderEndEllipsis(pageIndex);\n }\n\n const paginationStart =\n (pageIndex <= startRange &&\n activePage + siblingRange <= startRange) ||\n pageIndex <= boundaryRange;\n const paginationMiddle =\n pageIndex === activePage ||\n (pageIndex <= activePage + siblingRange &&\n pageIndex >= activePage - siblingRange - 1);\n const paginationEnd =\n (pageIndex > endRange &&\n activePage - siblingRange > endRange) ||\n pageIndex > totalPages - boundaryRange;\n if (paginationStart || paginationMiddle || paginationEnd) {\n return (\n <button\n key={pageIndex}\n onClick={() => handlePaginationItemClick(pageIndex)}\n className={clsx(\n styles.pageItem,\n active && styles.pageItemSelected\n )}\n aria-label={`page ${pageIndex} of ${totalPages}`}\n aria-current={active ? \"page\" : false}\n onMouseOver={closeAllTooltips}\n onFocus={closeAllTooltips}\n >\n {pageIndex}\n </button>\n );\n }\n\n return null;\n });\n };\n\n const renderStartEllipsis = (pageIndex: number) => (\n <div key={pageIndex} className={styles.ellipsisContainer}>\n <ClickableIcon\n className={styles.iconButton}\n focusHighlight={false}\n focusOutline=\"browser\"\n aria-label={\"Previous 5 pages\"}\n onMouseEnter={onHoverLeftButton}\n onMouseLeave={onBlurLeftButton}\n onFocus={onHoverLeftButton}\n onBlur={onBlurLeftButton}\n onClick={handleFastBackwardClick}\n >\n {hoverLeftButton ? (\n <Chevron2LeftIcon aria-hidden />\n ) : (\n <EllipsisHorizontalIcon aria-hidden />\n )}\n </ClickableIcon>\n {hoverLeftButton && (\n <div className={styles.hover}>Previous 5 pages</div>\n )}\n </div>\n );\n\n const renderEndEllipsis = (pageIndex: number) => (\n <div key={pageIndex} className={styles.ellipsisContainer}>\n <ClickableIcon\n className={styles.iconButton}\n focusHighlight={false}\n focusOutline=\"browser\"\n aria-label={\"Next 5 pages\"}\n onMouseEnter={onHoverRightButton}\n onMouseLeave={onBlurRightButton}\n onFocus={onHoverRightButton}\n onBlur={onBlurRightButton}\n onClick={handleFastForwardClick}\n >\n {hoverRightButton ? (\n <Chevron2RightIcon aria-hidden />\n ) : (\n <EllipsisHorizontalIcon aria-hidden />\n )}\n </ClickableIcon>\n {hoverRightButton && (\n <div className={styles.hover}>Next 5 pages</div>\n )}\n </div>\n );\n\n const renderMobile = () => (\n <div className={styles.paginationMobileInput}>\n <form onSubmit={handleInputSubmit}>\n <Input\n className={styles.inputView}\n value={inputText}\n onChange={handleInput}\n autoComplete=\"off\"\n type=\"numeric\"\n id={(id || \"pagination\") + \"-input\"}\n data-testid={(dataTestId || \"pagination\") + \"-input\"}\n aria-label={`Page ${activePage} of ${totalPages}`}\n />\n </form>\n <Typography.BodyBL className={styles.labelDivider}>\n /\n </Typography.BodyBL>\n <Typography.BodyBL className={styles.label}>\n {totalPages}\n </Typography.BodyBL>\n </div>\n );\n\n return (\n <nav\n className={clsx(styles.paginationWrapper, className)}\n ref={ref}\n id={id || \"pagination-wrapper\"}\n data-testid={dataTestId || \"pagination\"}\n aria-labelledby={paginationId}\n >\n <VisuallyHidden id={paginationId} aria-hidden>\n pagination\n </VisuallyHidden>\n <div className={styles.paginationList}>\n <div className={styles.paginationMenu}>\n {showFirstAndLastNav && (\n <ClickableIcon\n className={clsx(\n styles.iconButton,\n styles.iconButtonNavigation\n )}\n onClick={firstPaginationItem}\n disabled={isFirstPage}\n focusHighlight={false}\n aria-label=\"First page\"\n focusOutline=\"browser\"\n >\n <ChevronLineLeftIcon aria-hidden />\n </ClickableIcon>\n )}\n <ClickableIcon\n className={clsx(\n styles.iconButton,\n styles.iconButtonNavigation\n )}\n onClick={prevPaginationItem}\n disabled={isFirstPage}\n focusHighlight={false}\n aria-label=\"Previous page\"\n focusOutline=\"browser\"\n >\n <ChevronLeftIcon aria-hidden />\n </ClickableIcon>\n {isMounted && isMobile\n ? renderMobile()\n : renderPaginationItems()}\n <ClickableIcon\n className={clsx(\n styles.iconButton,\n styles.iconButtonNavigation\n )}\n onClick={nextPaginationItem}\n disabled={isLastPage}\n focusHighlight={false}\n aria-label=\"Next page\"\n focusOutline=\"browser\"\n >\n <ChevronRightIcon aria-hidden />\n </ClickableIcon>\n {showFirstAndLastNav && (\n <ClickableIcon\n className={clsx(\n styles.iconButton,\n styles.iconButtonNavigation\n )}\n onClick={lastPaginationItem}\n disabled={isLastPage}\n focusHighlight={false}\n aria-label=\"Last page\"\n focusOutline=\"browser\"\n >\n <ChevronLineRightIcon aria-hidden />\n </ClickableIcon>\n )}\n </div>\n </div>\n {showPageSizeChanger && !isMobile && (\n <div className={styles.inputSelectWrapper}>\n <VisuallyHidden id={`${paginationId}-page-size`}>\n Items per page\n </VisuallyHidden>\n <InputSelect\n aria-labelledby={`${paginationId}-page-size`}\n options={pageSizeOptions}\n valueExtractor={(item) => item.value}\n listExtractor={(item) => item.label}\n displayValueExtractor={(item) => item.label}\n selectedOption={selectedOption}\n onSelectOption={handleListItemClick}\n />\n </div>\n )}\n </nav>\n );\n};\nexport const Pagination = React.forwardRef(Component);\n\nconst DEFAULT_OPTIONS: PageSizeItemProps[] = [\n { value: 10, label: \"10 per page\" },\n { value: 20, label: \"20 per page\" },\n { value: 30, label: \"30 per page\" },\n];\n"],"names":["Pagination","React","forwardRef","id","dataTestId","className","pageSize","totalItems","activePage","pageSizeOptions","DEFAULT_OPTIONS","showFirstAndLastNav","showPageSizeChanger","onPageChange","onPageSizeChange","ref","isMounted","useIsMounted","isMobile","useMaxWidthMediaQuery","hoverRightButton","setHoverRightButton","useState","hoverLeftButton","setHoverLeftButton","inputText","setInputText","selectedOption","setSelectedOption","pageSizeLocal","setPageSize","value","paginationId","useId","totalPages","Math","ceil","isFirstPage","isLastPage","firstPaginationItem","handlePaginationItemClick","undefined","lastPaginationItem","prevPaginationItem","nextPaginationItem","parseInt","toString","useEffect","setInputValue","find","option","closeAllTooltips","pageIndex","handleFastForwardClick","currentIndex","min","handleFastBackwardClick","max","handleInput","event","target","length","test","newPage","replace","handleInputSubmit","preventDefault","onHoverRightButton","onBlurRightButton","onHoverLeftButton","onBlurLeftButton","renderStartEllipsis","_jsxs","styles.ellipsisContainer","children","_jsx","ClickableIcon","styles.iconButton","focusHighlight","focusOutline","onMouseEnter","onMouseLeave","onFocus","onBlur","onClick","Chevron2LeftIcon","EllipsisHorizontalIcon","styles.hover","renderEndEllipsis","Chevron2RightIcon","clsx","styles.paginationWrapper","VisuallyHidden","styles.paginationList","styles.paginationMenu","styles.iconButtonNavigation","disabled","ChevronLineLeftIcon","ChevronLeftIcon","styles.paginationMobileInput","onSubmit","Input","styles.inputView","onChange","autoComplete","type","Typography","BodyBL","styles.labelDivider","styles.label","Array","map","e","i","endRange","boundaryRange","active","styles.pageItem","styles.pageItemSelected","onMouseOver","ChevronRightIcon","ChevronLineRightIcon","styles.inputSelectWrapper","InputSelect","options","valueExtractor","item","listExtractor","label","displayValueExtractor","onSelectOption","pagesize","totalPage"],"mappings":"4wCAoBA,MA2ZaA,OAAaC,QAAMC,YA3Zd,EAEVC,KACA,cAAeC,EACfC,YACAC,WAAW,GACXC,aACAC,aACAC,kBAAkBC,EAClBC,sBACAC,uBAAsB,EACtBC,eACAC,oBAEJC,KAMA,MAAMC,EAAYC,EAAAA,eACZC,EAAWC,EAAAA,sBAAsB,OAChCC,EAAkBC,GAAuBC,EAAAA,UAAS,IAClDC,EAAiBC,GAAsBF,EAAAA,UAAS,IAChDG,EAAWC,GAAgBJ,EAAAA,SAAiB,KAE5CK,EAAgBC,GAAqBN,EAAAA,SAE1Cb,EAAgB,KACXoB,EAAeC,GAAeR,EAAAA,UAChCJ,GAAYN,GACPe,EACIA,EAAeI,MAEnBzB,GAOJ0B,EAAe,GADFC,EAAAA,qBAGbC,EAAaC,KAAKC,KAAK7B,EAAasB,GACpCQ,EAA6B,IAAf7B,EACd8B,EAAa9B,IAAe0B,EAE5BK,EACF/B,EAAa,EAAI,IAAMgC,GAA0B,QAAKC,EACpDC,EACFlC,EAAa0B,EACP,IAAMM,GAA0BN,QAChCO,EACJE,EACFnC,EAAa,EACP,IAAMgC,GAA0BhC,EAAa,QAC7CiC,EACJG,EACFpC,EAAa0B,EACP,IACIM,GAA0BK,SAASrC,EAAWsC,YAAc,QAChEL,EAKVM,EAAAA,WAAU,KACFvC,GACAwC,EAAcxC,EAClB,GACD,CAACA,IAEJuC,EAAAA,WAAU,KACNjB,EAAYxB,GACZsB,EACInB,EAAgBwC,MAAMC,GAAWA,EAAOnB,QAAUzB,IACrD,GACF,CAACA,IAKJ,MAAM0C,EAAiBjB,IACnBL,EAAaK,EAAMe,WAAW,EAG5BK,EAAmB,KACrB9B,GAAoB,GACpBG,GAAmB,EAAM,EAMvBgB,GAA6BY,IAC3BvC,IACAA,EAAauC,GACbJ,EAAcI,GAClB,EAGEC,GAAyB,KAC3B,MAAMC,EAAenB,KAAKoB,IAAIrB,EAAY1B,EAAa,GACvDgC,GAA0Bc,GAC1BN,EAAcM,GACdjC,GAAoB,GACpBG,GAAmB,EAAM,EAGvBgC,GAA0B,KAC5B,MAAMF,EAAenB,KAAKsB,IAAI,EAAGjD,EAAa,GAC9CgC,GAA0Bc,GAC1BN,EAAcM,GACdjC,GAAoB,GACpBG,GAAmB,EAAK,EAGtBkC,GAAeC,IACjB,MAAM5B,EAAQ4B,EAAMC,OAAO7B,MAE3B,QAAcU,IAAVV,GAAwC,IAAjBA,EAAM8B,OAC7BnC,EAAa,SACV,GAHc,WAGIoC,KAAK/B,GAEvB,CACH,MAAMgC,EAAUlB,SAASd,EAAMiC,QAAQ,UAAW,KAClDhB,EAAcb,KAAKsB,IAAI,EAAGtB,KAAKoB,IAAIrB,EAAY6B,IACnD,MAJIrC,EAAaK,EAAMiC,QAAQ,UAAW,IAI1C,EAGEC,GAAqBN,IACvBA,EAAMO,iBACFzC,IACAZ,SAAAA,EAAegC,SAASpB,IAC5B,EAGE0C,GAAqB,KACvB9C,GAAoB,EAAK,EAGvB+C,GAAoB,KACtB/C,GAAoB,EAAM,EAGxBgD,GAAoB,KACtB7C,GAAmB,EAAK,EAGtB8C,GAAmB,KACrB9C,GAAmB,EAAM,EA+FvB+C,GAAuBnB,GACzBoB,EAAAA,KAAA,MAAA,CAAqBnE,UAAWoE,EAAAA,kBAAwBC,SAAA,CACpDC,EAAAA,IAACC,EAAAA,cAAa,CACVvE,UAAWwE,EAAAA,WACXC,gBAAgB,EAChBC,aAAa,UAAS,aACV,mBACZC,aAAcX,GACdY,aAAcX,GACdY,QAASb,GACTc,OAAQb,GACRc,QAAS5B,GAAuBkB,SAE/BnD,EACGoD,EAAAA,IAACU,EAAAA,qCAEDV,EAAAA,IAACW,+CAGR/D,GACGoD,MAAA,MAAA,CAAKtE,UAAWkF,QAAYb,SAAA,uBAnB1BtB,GAwBRoC,GAAqBpC,GACvBoB,EAAAA,KAAA,MAAA,CAAqBnE,UAAWoE,EAAAA,kBAAwBC,SAAA,CACpDC,EAAAA,IAACC,EAAAA,cAAa,CACVvE,UAAWwE,EAAAA,WACXC,gBAAgB,EAChBC,aAAa,UAAS,aACV,eACZC,aAAcb,GACdc,aAAcb,GACdc,QAASf,GACTgB,OAAQf,GACRgB,QAAS/B,GAAsBqB,SAE9BtD,EACGuD,EAAAA,IAACc,EAAAA,sCAEDd,EAAAA,IAACW,+CAGRlE,GACGuD,MAAA,MAAA,CAAKtE,UAAWkF,QAAYb,SAAA,mBAnB1BtB,GA+Cd,OACIoB,EAAAA,KAAA,MAAA,CACInE,UAAWqF,EAAAA,QAAKC,EAAAA,kBAA0BtF,GAC1CU,IAAKA,EACLZ,GAAIA,GAAM,qBAAoB,cACjBC,GAAc,aAAY,kBACtB4B,EAAY0C,SAAA,CAE7BC,MAACiB,EAAAA,eAAc,CAACzF,GAAI6B,EAAY,eAAA,EAAA0C,SAAA,eAGhCC,EAAAA,IAAA,MAAA,CAAKtE,UAAWwF,iBAAqBnB,SACjCF,EAAAA,KAAA,MAAA,CAAKnE,UAAWyF,EAAAA,eAAqBpB,SAAA,CAChC/D,GACGgE,MAACC,EAAAA,cAAa,CACVvE,UAAWqF,EAAAA,QACPb,EAAAA,WACAkB,wBAEJX,QAAS7C,EACTyD,SAAU3D,EACVyC,gBAAgB,eACL,aACXC,aAAa,UAASL,SAEtBC,EAAAA,IAACsB,EAAAA,0CAGTtB,EAAAA,IAACC,gBAAa,CACVvE,UAAWqF,UACPb,EAAAA,WACAkB,EAAAA,sBAEJX,QAASzC,EACTqD,SAAU3D,EACVyC,gBAAgB,EAAK,aACV,gBACXC,aAAa,UAASL,SAEtBC,EAAAA,IAACuB,EAAAA,gBAAe,CAAA,eAAA,MAEnBlF,GAAaE,EA/D1BsD,EAAAA,KAAA,MAAA,CAAKnE,UAAW8F,EAAAA,sBAA4BzB,SAAA,CACxCC,EAAAA,YAAMyB,SAAUnC,GAAiBS,SAC7BC,EAAAA,IAAC0B,EAAAA,MAAK,CACFhG,UAAWiG,EAAAA,UACXvE,MAAON,EACP8E,SAAU7C,GACV8C,aAAa,MACbC,KAAK,UACLtG,IAAKA,GAAM,cAAgB,SAAQ,eACrBC,GAAc,cAAgB,sBAChC,QAAQI,QAAiB0B,QAG7CyC,EAAAA,IAAC+B,EAAAA,WAAWC,QAAOtG,UAAWuG,EAAAA,4BAG9BjC,EAAAA,IAAC+B,EAAAA,WAAWC,QAAOtG,UAAWwG,EAAAA,eACzB3E,OA9IF,IAAI4E,MAAM5E,IAAa6E,KAAI,CAACC,EAAGC,KAClC,MAAM7D,EAAY6D,EAAI,EAEhBC,EAAWhF,EADEiF,EAGbC,EAAS5G,IAAe4C,EAC9B,OAAIlB,GAFe,EAIXyC,EAAAA,IAAA,SAAA,CAEIS,QAAS,IAAM5C,GAA0BY,GACzC/C,UAAWqF,EAAAA,QACP2B,EAAAA,SACAD,GAAUE,EAAAA,kBACb,aACW,QAAQlE,QAAgBlB,IAAY,iBAClCkF,GAAS,OACvBG,YAAapE,EACb+B,QAAS/B,EAAgBuB,SAExBtB,GAXIA,GAiBb5C,EA/JS,EAuIM2G,GAyBDA,IAAd/D,EAEOmB,GAAoBnB,GAI3B5C,EAtKS,GAsKoB0G,GAC7B9D,IAAclB,EAxKJ,EAwKiC,EAEpCsD,GAAkBpC,GAIxBA,GAtCc+D,GAuCX3G,EA9KK,GAuIM2G,GAwCf/D,GAhLU,GAkLVA,IAAc5C,GACb4C,GAAa5C,EAlLL,GAmLL4C,GAAa5C,EAnLR,EAmLoC,GAE5C4C,EAAY8D,GACT1G,EAtLK,EAsLuB0G,GAChC9D,EAAYlB,EAxLF,EA2LNyC,EAAAA,IAAA,SAAA,CAEIS,QAAS,IAAM5C,GAA0BY,GACzC/C,UAAWqF,EAAAA,QACP2B,EAAAA,SACAD,GAAUE,EAAAA,kBACb,aACW,QAAQlE,QAAgBlB,IAAY,iBAClCkF,GAAS,OACvBG,YAAapE,EACb+B,QAAS/B,EAAgBuB,SAExBtB,GAXIA,GAgBV,IAAI,IAyHHuB,EAAAA,IAACC,EAAAA,cAAa,CACVvE,UAAWqF,EAAAA,QACPb,EAAAA,WACAkB,wBAEJX,QAASxC,EACToD,SAAU1D,EACVwC,gBAAgB,eACL,YACXC,aAAa,mBAEbJ,EAAAA,IAAC6C,EAAAA,iBAAgB,CAAA,eAAA,MAEpB7G,GACGgE,EAAAA,IAACC,gBAAa,CACVvE,UAAWqF,EAAAA,QACPb,aACAkB,EAAAA,sBAEJX,QAAS1C,EACTsD,SAAU1D,EACVwC,gBAAgB,EAAK,aACV,YACXC,aAAa,UAASL,SAEtBC,EAAAA,IAAC8C,EAAAA,qBAAoB,CAAA,eAAA,WAKpC7G,IAAwBM,GACrBsD,EAAAA,KAAA,MAAA,CAAKnE,UAAWqH,EAAAA,mBAAyBhD,SAAA,CACrCC,EAAAA,IAACiB,EAAAA,eAAc,CAACzF,GAAI,GAAG6B,0CAGvB2C,EAAAA,IAACgD,cAAW,CAAA,kBACS,GAAG3F,cACpB4F,QAASnH,EACToH,eAAiBC,GAASA,EAAK/F,MAC/BgG,cAAgBD,GAASA,EAAKE,MAC9BC,sBAAwBH,GAASA,EAAKE,MACtCrG,eAAgBA,EAChBuG,eA3PSJ,IACzBlG,EAAkBkG,GAClB,MAAMK,EAAWL,EAAK/F,MAChBqG,EAAYjG,KAAKC,KAAK7B,EAAa4H,GAEzCrG,EAAYqG,GAIRrH,GACAA,EAHSN,GAAc4H,EAAYA,EAAY5H,EAGxB2H,EAC3B,SAoPM,IAKRzH,EAAuC,CACzC,CAAEqB,MAAO,GAAIiG,MAAO,eACpB,CAAEjG,MAAO,GAAIiG,MAAO,eACpB,CAAEjG,MAAO,GAAIiG,MAAO"}
1
+ {"version":3,"file":"pagination.js","sources":["../../../src/pagination/pagination.tsx"],"sourcesContent":["import { Chevron2LeftIcon } from \"@lifesg/react-icons/chevron-2-left\";\nimport { Chevron2RightIcon } from \"@lifesg/react-icons/chevron-2-right\";\nimport { ChevronLeftIcon } from \"@lifesg/react-icons/chevron-left\";\nimport { ChevronLineLeftIcon } from \"@lifesg/react-icons/chevron-line-left\";\nimport { ChevronLineRightIcon } from \"@lifesg/react-icons/chevron-line-right\";\nimport { ChevronRightIcon } from \"@lifesg/react-icons/chevron-right\";\nimport { EllipsisHorizontalIcon } from \"@lifesg/react-icons/ellipsis-horizontal\";\nimport clsx from \"clsx\";\nimport React, { useEffect, useState } from \"react\";\n\nimport { Input } from \"../input\";\nimport { InputSelect } from \"../input-select\";\nimport { VisuallyHidden } from \"../shared/accessibility\";\nimport { ClickableIcon } from \"../shared/clickable-icon\";\nimport { useMaxWidthMediaQuery } from \"../theme\";\nimport { Typography } from \"../typography\";\nimport { useId, useIsMounted } from \"../util\";\nimport * as styles from \"./pagination.styles\";\nimport type { PageSizeItemProps, PaginationProps } from \"./types\";\n\nconst Component = (\n {\n id,\n \"data-testid\": dataTestId,\n className,\n pageSize = 10,\n totalItems,\n activePage,\n pageSizeOptions = DEFAULT_OPTIONS,\n showFirstAndLastNav,\n showPageSizeChanger = false,\n onPageChange,\n onPageSizeChange,\n }: PaginationProps,\n ref: React.Ref<HTMLDivElement>\n) => {\n // =============================================================================\n // CONST, STATE, REF\n // =============================================================================\n\n const isMounted = useIsMounted();\n const isMobile = useMaxWidthMediaQuery(\"sm\");\n const [hoverRightButton, setHoverRightButton] = useState(false);\n const [hoverLeftButton, setHoverLeftButton] = useState(false);\n const [inputText, setInputText] = useState<string>(\"\");\n\n const [selectedOption, setSelectedOption] = useState<\n PageSizeItemProps | undefined\n >(pageSizeOptions[0]);\n const [pageSizeLocal, setPageSize] = useState<number>(\n !isMobile && showPageSizeChanger\n ? selectedOption\n ? selectedOption.value\n : pageSize\n : pageSize\n );\n\n const boundaryRange = 1;\n const siblingRange = 1;\n\n const internalId = useId();\n const paginationId = `${internalId}-pagination`;\n\n const totalPages = Math.ceil(totalItems / pageSizeLocal);\n const isFirstPage = activePage === 1;\n const isLastPage = activePage === totalPages;\n\n const firstPaginationItem =\n activePage > 1 ? () => handlePaginationItemClick(1) : undefined;\n const lastPaginationItem =\n activePage < totalPages\n ? () => handlePaginationItemClick(totalPages)\n : undefined;\n const prevPaginationItem =\n activePage > 1\n ? () => handlePaginationItemClick(activePage - 1)\n : undefined;\n const nextPaginationItem =\n activePage < totalPages\n ? () =>\n handlePaginationItemClick(parseInt(activePage.toString()) + 1)\n : undefined;\n\n // =============================================================================\n // EFFECTS\n // =============================================================================\n useEffect(() => {\n if (activePage) {\n setInputValue(activePage);\n }\n }, [activePage]);\n\n useEffect(() => {\n setPageSize(pageSize);\n setSelectedOption(\n pageSizeOptions.find((option) => option.value === pageSize)\n );\n }, [pageSize]);\n\n // =============================================================================\n // HELPER FUNCTIONS\n // =============================================================================\n const setInputValue = (value: number) => {\n setInputText(value.toString());\n };\n\n const closeAllTooltips = () => {\n setHoverRightButton(false);\n setHoverLeftButton(false);\n };\n\n // =============================================================================\n // EVENT HANDLERS\n // =============================================================================\n const handlePaginationItemClick = (pageIndex: number) => {\n if (onPageChange) {\n onPageChange(pageIndex);\n setInputValue(pageIndex);\n }\n };\n\n const handleFastForwardClick = () => {\n const currentIndex = Math.min(totalPages, activePage + 5);\n handlePaginationItemClick(currentIndex);\n setInputValue(currentIndex);\n setHoverRightButton(true);\n setHoverLeftButton(false);\n };\n\n const handleFastBackwardClick = () => {\n const currentIndex = Math.max(1, activePage - 5);\n handlePaginationItemClick(currentIndex);\n setInputValue(currentIndex);\n setHoverRightButton(false);\n setHoverLeftButton(true);\n };\n\n const handleInput = (event: React.ChangeEvent<HTMLInputElement>) => {\n const value = event.target.value;\n const numericRegex = /^[0-9]+$/;\n if (value === undefined || value.length === 0) {\n setInputText(\"\");\n } else if (!numericRegex.test(value)) {\n setInputText(value.replace(/[^0-9]/g, \"\"));\n } else {\n const newPage = parseInt(value.replace(/[^0-9]/g, \"\"));\n setInputValue(Math.max(1, Math.min(totalPages, newPage)));\n }\n };\n\n const handleInputSubmit = (event: React.FormEvent) => {\n event.preventDefault();\n if (inputText) {\n onPageChange?.(parseInt(inputText));\n }\n };\n\n const onHoverRightButton = () => {\n setHoverRightButton(true);\n };\n\n const onBlurRightButton = () => {\n setHoverRightButton(false);\n };\n\n const onHoverLeftButton = () => {\n setHoverLeftButton(true);\n };\n\n const onBlurLeftButton = () => {\n setHoverLeftButton(false);\n };\n\n const handleListItemClick = (item: PageSizeItemProps) => {\n setSelectedOption(item);\n const pagesize = item.value;\n const totalPage = Math.ceil(totalItems / pagesize);\n\n setPageSize(pagesize);\n\n const page = activePage >= totalPage ? totalPage : activePage;\n\n if (onPageSizeChange) {\n onPageSizeChange(page, pagesize);\n }\n };\n\n // =============================================================================\n // RENDER FUNCTIONS\n // =============================================================================\n const renderPaginationItems = () => {\n return [...Array(totalPages)].map((e, i) => {\n const pageIndex = i + 1;\n const startRange = boundaryRange + 2 + siblingRange * 2;\n const endRange = totalPages - startRange;\n const totalRange = (boundaryRange + siblingRange) * 2 + 3;\n const active = activePage === pageIndex;\n if (totalPages <= totalRange) {\n return (\n <button\n key={pageIndex}\n onClick={() => handlePaginationItemClick(pageIndex)}\n className={clsx(\n styles.pageItem,\n active && styles.pageItemSelected\n )}\n aria-label={`page ${pageIndex} of ${totalPages}`}\n aria-current={active ? \"page\" : false}\n onMouseOver={closeAllTooltips}\n onFocus={closeAllTooltips}\n >\n {pageIndex}\n </button>\n );\n }\n\n const ellipsisStart =\n activePage + siblingRange > startRange &&\n pageIndex === boundaryRange + 1;\n if (ellipsisStart) {\n return renderStartEllipsis(pageIndex);\n }\n\n const ellipsisEnd =\n activePage - siblingRange <= endRange &&\n pageIndex === totalPages - boundaryRange - 1;\n if (ellipsisEnd) {\n return renderEndEllipsis(pageIndex);\n }\n\n const paginationStart =\n (pageIndex <= startRange &&\n activePage + siblingRange <= startRange) ||\n pageIndex <= boundaryRange;\n const paginationMiddle =\n pageIndex === activePage ||\n (pageIndex <= activePage + siblingRange &&\n pageIndex >= activePage - siblingRange - 1);\n const paginationEnd =\n (pageIndex > endRange &&\n activePage - siblingRange > endRange) ||\n pageIndex > totalPages - boundaryRange;\n if (paginationStart || paginationMiddle || paginationEnd) {\n return (\n <button\n key={pageIndex}\n onClick={() => handlePaginationItemClick(pageIndex)}\n className={clsx(\n styles.pageItem,\n active && styles.pageItemSelected\n )}\n aria-label={`page ${pageIndex} of ${totalPages}`}\n aria-current={active ? \"page\" : false}\n onMouseOver={closeAllTooltips}\n onFocus={closeAllTooltips}\n >\n {pageIndex}\n </button>\n );\n }\n\n return null;\n });\n };\n\n const renderStartEllipsis = (pageIndex: number) => (\n <div key={pageIndex} className={styles.ellipsisContainer}>\n <ClickableIcon\n className={styles.iconButton}\n focusHighlight={false}\n focusOutline=\"browser\"\n aria-label={\"Previous 5 pages\"}\n onMouseEnter={onHoverLeftButton}\n onMouseLeave={onBlurLeftButton}\n onFocus={onHoverLeftButton}\n onBlur={onBlurLeftButton}\n onClick={handleFastBackwardClick}\n >\n {hoverLeftButton ? (\n <Chevron2LeftIcon aria-hidden />\n ) : (\n <EllipsisHorizontalIcon aria-hidden />\n )}\n </ClickableIcon>\n {hoverLeftButton && (\n <div className={styles.hover}>Previous 5 pages</div>\n )}\n </div>\n );\n\n const renderEndEllipsis = (pageIndex: number) => (\n <div key={pageIndex} className={styles.ellipsisContainer}>\n <ClickableIcon\n className={styles.iconButton}\n focusHighlight={false}\n focusOutline=\"browser\"\n aria-label={\"Next 5 pages\"}\n onMouseEnter={onHoverRightButton}\n onMouseLeave={onBlurRightButton}\n onFocus={onHoverRightButton}\n onBlur={onBlurRightButton}\n onClick={handleFastForwardClick}\n >\n {hoverRightButton ? (\n <Chevron2RightIcon aria-hidden />\n ) : (\n <EllipsisHorizontalIcon aria-hidden />\n )}\n </ClickableIcon>\n {hoverRightButton && (\n <div className={styles.hover}>Next 5 pages</div>\n )}\n </div>\n );\n\n const renderMobile = () => (\n <div className={styles.paginationMobileInput}>\n <form onSubmit={handleInputSubmit}>\n <Input\n className={styles.inputView}\n value={inputText}\n onChange={handleInput}\n autoComplete=\"off\"\n type=\"numeric\"\n id={(id || \"pagination\") + \"-input\"}\n data-testid={(dataTestId || \"pagination\") + \"-input\"}\n aria-label={`Page ${activePage} of ${totalPages}`}\n />\n </form>\n <Typography.BodyBL className={styles.labelDivider}>\n /\n </Typography.BodyBL>\n <Typography.BodyBL className={styles.label}>\n {totalPages}\n </Typography.BodyBL>\n </div>\n );\n\n return (\n <nav\n className={clsx(styles.paginationWrapper, className)}\n ref={ref}\n id={id || \"pagination-wrapper\"}\n data-testid={dataTestId || \"pagination\"}\n aria-labelledby={paginationId}\n >\n <VisuallyHidden id={paginationId} aria-hidden>\n pagination\n </VisuallyHidden>\n <div className={styles.paginationList}>\n <div className={styles.paginationMenu}>\n {showFirstAndLastNav && (\n <ClickableIcon\n className={clsx(\n styles.iconButton,\n styles.iconButtonNavigation\n )}\n onClick={firstPaginationItem}\n disabled={isFirstPage}\n focusHighlight={false}\n aria-label=\"First page\"\n focusOutline=\"browser\"\n >\n <ChevronLineLeftIcon aria-hidden />\n </ClickableIcon>\n )}\n <ClickableIcon\n className={clsx(\n styles.iconButton,\n styles.iconButtonNavigation\n )}\n onClick={prevPaginationItem}\n disabled={isFirstPage}\n focusHighlight={false}\n aria-label=\"Previous page\"\n focusOutline=\"browser\"\n >\n <ChevronLeftIcon aria-hidden />\n </ClickableIcon>\n {isMounted && isMobile\n ? renderMobile()\n : renderPaginationItems()}\n <ClickableIcon\n className={clsx(\n styles.iconButton,\n styles.iconButtonNavigation\n )}\n onClick={nextPaginationItem}\n disabled={isLastPage}\n focusHighlight={false}\n aria-label=\"Next page\"\n focusOutline=\"browser\"\n >\n <ChevronRightIcon aria-hidden />\n </ClickableIcon>\n {showFirstAndLastNav && (\n <ClickableIcon\n className={clsx(\n styles.iconButton,\n styles.iconButtonNavigation\n )}\n onClick={lastPaginationItem}\n disabled={isLastPage}\n focusHighlight={false}\n aria-label=\"Last page\"\n focusOutline=\"browser\"\n >\n <ChevronLineRightIcon aria-hidden />\n </ClickableIcon>\n )}\n </div>\n </div>\n {showPageSizeChanger && !isMobile && (\n <div className={styles.inputSelectWrapper}>\n <VisuallyHidden id={`${paginationId}-page-size`}>\n Items per page\n </VisuallyHidden>\n <InputSelect\n aria-labelledby={`${paginationId}-page-size`}\n options={pageSizeOptions}\n valueExtractor={(item) => item.value}\n listExtractor={(item) => item.label}\n displayValueExtractor={(item) => item.label}\n selectedOption={selectedOption}\n onSelectOption={handleListItemClick}\n />\n </div>\n )}\n </nav>\n );\n};\n/**\n * A navigation control for moving through paged content.\n *\n * Use `Pagination` to let users navigate between pages of a data set.\n */\nexport const Pagination = React.forwardRef(Component);\n\nconst DEFAULT_OPTIONS: PageSizeItemProps[] = [\n { value: 10, label: \"10 per page\" },\n { value: 20, label: \"20 per page\" },\n { value: 30, label: \"30 per page\" },\n];\n"],"names":["Pagination","React","forwardRef","id","dataTestId","className","pageSize","totalItems","activePage","pageSizeOptions","DEFAULT_OPTIONS","showFirstAndLastNav","showPageSizeChanger","onPageChange","onPageSizeChange","ref","isMounted","useIsMounted","isMobile","useMaxWidthMediaQuery","hoverRightButton","setHoverRightButton","useState","hoverLeftButton","setHoverLeftButton","inputText","setInputText","selectedOption","setSelectedOption","pageSizeLocal","setPageSize","value","paginationId","useId","totalPages","Math","ceil","isFirstPage","isLastPage","firstPaginationItem","handlePaginationItemClick","undefined","lastPaginationItem","prevPaginationItem","nextPaginationItem","parseInt","toString","useEffect","setInputValue","find","option","closeAllTooltips","pageIndex","handleFastForwardClick","currentIndex","min","handleFastBackwardClick","max","handleInput","event","target","length","test","newPage","replace","handleInputSubmit","preventDefault","onHoverRightButton","onBlurRightButton","onHoverLeftButton","onBlurLeftButton","renderStartEllipsis","_jsxs","styles.ellipsisContainer","children","_jsx","ClickableIcon","styles.iconButton","focusHighlight","focusOutline","onMouseEnter","onMouseLeave","onFocus","onBlur","onClick","Chevron2LeftIcon","EllipsisHorizontalIcon","styles.hover","renderEndEllipsis","Chevron2RightIcon","clsx","styles.paginationWrapper","VisuallyHidden","styles.paginationList","styles.paginationMenu","styles.iconButtonNavigation","disabled","ChevronLineLeftIcon","ChevronLeftIcon","styles.paginationMobileInput","onSubmit","Input","styles.inputView","onChange","autoComplete","type","Typography","BodyBL","styles.labelDivider","styles.label","Array","map","e","i","endRange","boundaryRange","active","styles.pageItem","styles.pageItemSelected","onMouseOver","ChevronRightIcon","ChevronLineRightIcon","styles.inputSelectWrapper","InputSelect","options","valueExtractor","item","listExtractor","label","displayValueExtractor","onSelectOption","pagesize","totalPage"],"mappings":"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"}