@lifesg/react-design-system 4.0.0-alpha.12 → 4.0.0-alpha.14

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 (323) hide show
  1. package/breadcrumb/breadcrumb.js +1 -1
  2. package/breadcrumb/breadcrumb.js.map +1 -1
  3. package/breadcrumb/breadcrumb.styles.d.ts +0 -8
  4. package/breadcrumb/breadcrumb.styles.js +1 -1
  5. package/breadcrumb/breadcrumb.styles.js.map +1 -1
  6. package/breadcrumb/breadcrumb.styles_1blzn8n.css +7 -0
  7. package/breadcrumb/types.d.ts +2 -13
  8. package/cjs/breadcrumb/breadcrumb.js +1 -1
  9. package/cjs/breadcrumb/breadcrumb.js.map +1 -1
  10. package/cjs/breadcrumb/breadcrumb.styles.js +1 -1
  11. package/cjs/breadcrumb/breadcrumb.styles.js.map +1 -1
  12. package/cjs/breadcrumb/breadcrumb.styles_1blzn8n.css +7 -0
  13. package/cjs/drawer/drawer.js +1 -1
  14. package/cjs/drawer/drawer.js.map +1 -1
  15. package/cjs/drawer/drawer.styles.js +1 -1
  16. package/cjs/drawer/drawer.styles.js.map +1 -1
  17. package/{drawer/drawer.styles_94hx3y.css → cjs/drawer/drawer.styles_a4bwe0.css} +6 -3
  18. package/cjs/external/dompurify/dist/purify.es.js +4 -2
  19. package/cjs/external/dompurify/dist/purify.es.js.map +1 -1
  20. package/cjs/file-upload/file-list/file-list.js +1 -1
  21. package/cjs/file-upload/file-list/file-list.js.map +1 -1
  22. package/cjs/file-upload/file-list/file-list.styles.js +1 -1
  23. package/cjs/file-upload/file-list/file-list.styles.js.map +1 -1
  24. package/cjs/file-upload/file-list/file-list.styles_1xbypnh.css +2 -0
  25. package/cjs/file-upload/file-list-item/file-item-actions.js +2 -0
  26. package/cjs/file-upload/file-list-item/file-item-actions.js.map +1 -0
  27. package/cjs/file-upload/file-list-item/file-item-actions.styles.js +2 -0
  28. package/cjs/file-upload/file-list-item/file-item-actions.styles.js.map +1 -0
  29. package/cjs/file-upload/file-list-item/file-item-actions.styles_1quulgy.css +8 -0
  30. package/cjs/file-upload/file-list-item/file-item-details.js +2 -0
  31. package/cjs/file-upload/file-list-item/file-item-details.js.map +1 -0
  32. package/cjs/file-upload/file-list-item/file-item-details.styles.js +2 -0
  33. package/cjs/file-upload/file-list-item/file-item-details.styles.js.map +1 -0
  34. package/cjs/file-upload/file-list-item/file-item-details.styles_1ce9akx.css +7 -0
  35. package/cjs/file-upload/file-list-item/file-list-item.js +1 -1
  36. package/cjs/file-upload/file-list-item/file-list-item.js.map +1 -1
  37. package/cjs/file-upload/file-list-item/file-list-item.styles.js +1 -1
  38. package/cjs/file-upload/file-list-item/file-list-item.styles.js.map +1 -1
  39. package/cjs/file-upload/file-list-item/file-list-item.styles_x3a500.css +10 -0
  40. package/cjs/file-upload/file-list-item/use-truncated-name.js +2 -0
  41. package/cjs/file-upload/file-list-item/use-truncated-name.js.map +1 -0
  42. package/cjs/local-nav/local-nav-dropdown/local-nav-dropdown.js +1 -1
  43. package/cjs/local-nav/local-nav-dropdown/local-nav-dropdown.js.map +1 -1
  44. package/cjs/local-nav/local-nav-dropdown/local-nav-dropdown.styles.js +1 -1
  45. package/cjs/local-nav/local-nav-dropdown/local-nav-dropdown.styles.js.map +1 -1
  46. package/{local-nav/local-nav-dropdown/local-nav-dropdown.styles_uhd4xl.css → cjs/local-nav/local-nav-dropdown/local-nav-dropdown.styles_kpel1m.css} +9 -6
  47. package/cjs/local-nav/local-nav-menu/local-nav-menu.js +1 -1
  48. package/cjs/local-nav/local-nav-menu/local-nav-menu.js.map +1 -1
  49. package/cjs/local-nav/local-nav-menu/local-nav-menu.styles.js +1 -1
  50. package/cjs/local-nav/local-nav-menu/local-nav-menu.styles.js.map +1 -1
  51. package/cjs/local-nav/local-nav-menu/local-nav-menu.styles_67fcyc.css +8 -0
  52. package/cjs/menu/menu-content.js +1 -1
  53. package/cjs/menu/menu-content.js.map +1 -1
  54. package/cjs/menu/menu-content.styles.js +1 -1
  55. package/cjs/menu/menu-content.styles.js.map +1 -1
  56. package/cjs/menu/menu-content.styles_1r8oxtk.css +5 -0
  57. package/cjs/menu/menu-item.styles.js +1 -1
  58. package/cjs/menu/menu-item.styles.js.map +1 -1
  59. package/cjs/menu/{menu-item.styles_liyed8.css → menu-item.styles_eut2j9.css} +1 -1
  60. package/cjs/menu/menu-link.styles.js +1 -1
  61. package/cjs/menu/menu-link.styles.js.map +1 -1
  62. package/cjs/menu/menu-link.styles_rng7n7.css +2 -0
  63. package/cjs/menu/menu-section.js +1 -1
  64. package/cjs/menu/menu-section.js.map +1 -1
  65. package/cjs/menu/menu-section.styles.js +1 -1
  66. package/cjs/menu/menu-section.styles.js.map +1 -1
  67. package/cjs/menu/menu-section.styles_1n0ppxl.css +5 -0
  68. package/cjs/modal-v2/slots/slot-styles.js +1 -1
  69. package/cjs/modal-v2/slots/slot-styles.js.map +1 -1
  70. package/cjs/modal-v2/slots/{slot-styles_ayb9il.css → slot-styles_ygu6zc.css} +1 -1
  71. package/cjs/navbar/navbar-items.js +1 -1
  72. package/cjs/navbar/navbar-items.js.map +1 -1
  73. package/cjs/notification-banner/notification-banner-hoc.js +1 -1
  74. package/cjs/notification-banner/notification-banner-hoc.js.map +1 -1
  75. package/cjs/pagination/pagination.js +1 -1
  76. package/cjs/pagination/pagination.js.map +1 -1
  77. package/cjs/shared/dropdown-list/dropdown-label.js +1 -1
  78. package/cjs/shared/dropdown-list/dropdown-label.js.map +1 -1
  79. package/cjs/shared/fade-wrapper/fade-wrapper.js +1 -1
  80. package/cjs/shared/fade-wrapper/fade-wrapper.js.map +1 -1
  81. package/cjs/theme/tokens/colour.js +1 -1
  82. package/cjs/theme/tokens/colour.js.map +1 -1
  83. package/cjs/theme/tokens/radius.js +1 -1
  84. package/cjs/theme/tokens/radius.js.map +1 -1
  85. package/codemods/run-codemod.js +8 -2
  86. package/codemods/run-codemod.js.map +1 -1
  87. package/codemods/run-codemod.ts +13 -4
  88. package/drawer/drawer.d.ts +1 -1
  89. package/drawer/drawer.js +1 -1
  90. package/drawer/drawer.js.map +1 -1
  91. package/drawer/drawer.styles.d.ts +3 -0
  92. package/drawer/drawer.styles.js +1 -1
  93. package/drawer/drawer.styles.js.map +1 -1
  94. package/{cjs/drawer/drawer.styles_94hx3y.css → drawer/drawer.styles_a4bwe0.css} +6 -3
  95. package/drawer/types.d.ts +7 -0
  96. package/external/dompurify/dist/purify.es.js +4 -2
  97. package/external/dompurify/dist/purify.es.js.map +1 -1
  98. package/file-upload/file-list/file-list.js +1 -1
  99. package/file-upload/file-list/file-list.js.map +1 -1
  100. package/file-upload/file-list/file-list.styles.d.ts +0 -1
  101. package/file-upload/file-list/file-list.styles.js +1 -1
  102. package/file-upload/file-list/file-list.styles.js.map +1 -1
  103. package/file-upload/file-list/file-list.styles_1xbypnh.css +2 -0
  104. package/file-upload/file-list-item/file-item-actions.d.ts +30 -0
  105. package/file-upload/file-list-item/file-item-actions.js +2 -0
  106. package/file-upload/file-list-item/file-item-actions.js.map +1 -0
  107. package/file-upload/file-list-item/file-item-actions.styles.d.ts +6 -0
  108. package/file-upload/file-list-item/file-item-actions.styles.js +2 -0
  109. package/file-upload/file-list-item/file-item-actions.styles.js.map +1 -0
  110. package/file-upload/file-list-item/file-item-actions.styles_1quulgy.css +8 -0
  111. package/file-upload/file-list-item/file-item-details.d.ts +15 -0
  112. package/file-upload/file-list-item/file-item-details.js +2 -0
  113. package/file-upload/file-list-item/file-item-details.js.map +1 -0
  114. package/file-upload/file-list-item/file-item-details.styles.d.ts +7 -0
  115. package/file-upload/file-list-item/file-item-details.styles.js +2 -0
  116. package/file-upload/file-list-item/file-item-details.styles.js.map +1 -0
  117. package/file-upload/file-list-item/file-item-details.styles_1ce9akx.css +7 -0
  118. package/file-upload/file-list-item/file-list-item.d.ts +1 -7
  119. package/file-upload/file-list-item/file-list-item.js +1 -1
  120. package/file-upload/file-list-item/file-list-item.js.map +1 -1
  121. package/file-upload/file-list-item/file-list-item.styles.d.ts +6 -13
  122. package/file-upload/file-list-item/file-list-item.styles.js +1 -1
  123. package/file-upload/file-list-item/file-list-item.styles.js.map +1 -1
  124. package/file-upload/file-list-item/file-list-item.styles_x3a500.css +10 -0
  125. package/file-upload/file-list-item/types.d.ts +10 -3
  126. package/file-upload/file-list-item/use-truncated-name.d.ts +1 -0
  127. package/file-upload/file-list-item/use-truncated-name.js +2 -0
  128. package/file-upload/file-list-item/use-truncated-name.js.map +1 -0
  129. package/input-group/types.d.ts +4 -1
  130. package/input-select/types.d.ts +1 -0
  131. package/local-nav/local-nav-dropdown/local-nav-dropdown.js +1 -1
  132. package/local-nav/local-nav-dropdown/local-nav-dropdown.js.map +1 -1
  133. package/local-nav/local-nav-dropdown/local-nav-dropdown.styles.d.ts +3 -0
  134. package/local-nav/local-nav-dropdown/local-nav-dropdown.styles.js +1 -1
  135. package/local-nav/local-nav-dropdown/local-nav-dropdown.styles.js.map +1 -1
  136. package/{cjs/local-nav/local-nav-dropdown/local-nav-dropdown.styles_uhd4xl.css → local-nav/local-nav-dropdown/local-nav-dropdown.styles_kpel1m.css} +9 -6
  137. package/local-nav/local-nav-menu/local-nav-menu.js +1 -1
  138. package/local-nav/local-nav-menu/local-nav-menu.js.map +1 -1
  139. package/local-nav/local-nav-menu/local-nav-menu.styles.d.ts +3 -0
  140. package/local-nav/local-nav-menu/local-nav-menu.styles.js +1 -1
  141. package/local-nav/local-nav-menu/local-nav-menu.styles.js.map +1 -1
  142. package/local-nav/local-nav-menu/local-nav-menu.styles_67fcyc.css +8 -0
  143. package/local-nav/types.d.ts +17 -0
  144. package/masked-input/types.d.ts +1 -2
  145. package/menu/menu-content.js +1 -1
  146. package/menu/menu-content.js.map +1 -1
  147. package/menu/menu-content.styles.d.ts +1 -0
  148. package/menu/menu-content.styles.js +1 -1
  149. package/menu/menu-content.styles.js.map +1 -1
  150. package/menu/menu-content.styles_1r8oxtk.css +5 -0
  151. package/menu/menu-item.styles.js +1 -1
  152. package/menu/menu-item.styles.js.map +1 -1
  153. package/menu/{menu-item.styles_liyed8.css → menu-item.styles_eut2j9.css} +1 -1
  154. package/menu/menu-link.styles.js +1 -1
  155. package/menu/menu-link.styles.js.map +1 -1
  156. package/menu/menu-link.styles_rng7n7.css +2 -0
  157. package/menu/menu-section.d.ts +1 -1
  158. package/menu/menu-section.js +1 -1
  159. package/menu/menu-section.js.map +1 -1
  160. package/menu/menu-section.styles.d.ts +7 -0
  161. package/menu/menu-section.styles.js +1 -1
  162. package/menu/menu-section.styles.js.map +1 -1
  163. package/menu/menu-section.styles_1n0ppxl.css +5 -0
  164. package/menu/menu.d.ts +1 -1
  165. package/menu/types.d.ts +10 -2
  166. package/modal-v2/slots/slot-styles.js +1 -1
  167. package/modal-v2/slots/slot-styles.js.map +1 -1
  168. package/modal-v2/slots/{slot-styles_ayb9il.css → slot-styles_ygu6zc.css} +1 -1
  169. package/navbar/navbar-items.js +1 -1
  170. package/navbar/navbar-items.js.map +1 -1
  171. package/navbar/types.d.ts +9 -0
  172. package/notification-banner/notification-banner-hoc.js +1 -1
  173. package/notification-banner/notification-banner-hoc.js.map +1 -1
  174. package/package.json +3 -4
  175. package/pagination/pagination.js +1 -1
  176. package/pagination/pagination.js.map +1 -1
  177. package/pagination/types.d.ts +8 -1
  178. package/scripts/cli.js +18 -0
  179. package/select-histogram/types.d.ts +1 -0
  180. package/shared/dropdown-list/dropdown-label.d.ts +2 -2
  181. package/shared/dropdown-list/dropdown-label.js +1 -1
  182. package/shared/dropdown-list/dropdown-label.js.map +1 -1
  183. package/shared/dropdown-list/types.d.ts +6 -2
  184. package/shared/fade-wrapper/fade-wrapper.js +1 -1
  185. package/shared/fade-wrapper/fade-wrapper.js.map +1 -1
  186. package/shared/fade-wrapper/types.d.ts +1 -0
  187. package/shared/styles/index.d.ts +5 -0
  188. package/skills/fds-build/SKILL.md +167 -0
  189. package/skills/fds-build/catalogue.md +181 -0
  190. package/skills/fds-build/evals/evals.json +519 -0
  191. package/skills/fds-build/resources/components/accordion.md +128 -0
  192. package/skills/fds-build/resources/components/alert.md +54 -0
  193. package/skills/fds-build/resources/components/animation.md +18 -0
  194. package/skills/fds-build/resources/components/avatar.md +10 -0
  195. package/skills/fds-build/resources/components/badge.md +18 -0
  196. package/skills/fds-build/resources/components/box-container.md +61 -0
  197. package/skills/fds-build/resources/components/breadcrumb.md +60 -0
  198. package/skills/fds-build/resources/components/button.md +74 -0
  199. package/skills/fds-build/resources/components/calendar.md +113 -0
  200. package/skills/fds-build/resources/components/card.md +43 -0
  201. package/skills/fds-build/resources/components/checkbox.md +53 -0
  202. package/skills/fds-build/resources/components/countdown-timer.md +20 -0
  203. package/skills/fds-build/resources/components/data-table.md +142 -0
  204. package/skills/fds-build/resources/components/date-navigator.md +25 -0
  205. package/skills/fds-build/resources/components/divider.md +23 -0
  206. package/skills/fds-build/resources/components/drawer.md +78 -0
  207. package/skills/fds-build/resources/components/error-display.md +137 -0
  208. package/skills/fds-build/resources/components/feedback-rating.md +61 -0
  209. package/skills/fds-build/resources/components/file-download.md +54 -0
  210. package/skills/fds-build/resources/components/file-upload.md +105 -0
  211. package/skills/fds-build/resources/components/filter.md +228 -0
  212. package/skills/fds-build/resources/components/footer.md +94 -0
  213. package/skills/fds-build/resources/components/form-date-input.md +85 -0
  214. package/skills/fds-build/resources/components/form-date-range-input.md +146 -0
  215. package/skills/fds-build/resources/components/form-e-signature.md +55 -0
  216. package/skills/fds-build/resources/components/form-input.md +65 -0
  217. package/skills/fds-build/resources/components/form-masked-input.md +69 -0
  218. package/skills/fds-build/resources/components/form-multi-select.md +100 -0
  219. package/skills/fds-build/resources/components/form-nested-multi-select.md +159 -0
  220. package/skills/fds-build/resources/components/form-nested-select.md +151 -0
  221. package/skills/fds-build/resources/components/form-otp-verification.md +175 -0
  222. package/skills/fds-build/resources/components/form-phone-number-input.md +87 -0
  223. package/skills/fds-build/resources/components/form-predictive-text-input.md +108 -0
  224. package/skills/fds-build/resources/components/form-select.md +103 -0
  225. package/skills/fds-build/resources/components/form-slider.md +116 -0
  226. package/skills/fds-build/resources/components/form-textarea.md +116 -0
  227. package/skills/fds-build/resources/components/form-time-range-picker.md +98 -0
  228. package/skills/fds-build/resources/components/form-timepicker.md +77 -0
  229. package/skills/fds-build/resources/components/form-unit-number-input.md +138 -0
  230. package/skills/fds-build/resources/components/fullscreen-image-carousel.md +159 -0
  231. package/skills/fds-build/resources/components/histogram-slider.md +41 -0
  232. package/skills/fds-build/resources/components/icon.md +167 -0
  233. package/skills/fds-build/resources/components/image-button.md +12 -0
  234. package/skills/fds-build/resources/components/input.md +51 -0
  235. package/skills/fds-build/resources/components/language-switcher.md +15 -0
  236. package/skills/fds-build/resources/components/layout.md +156 -0
  237. package/skills/fds-build/resources/components/link-list.md +120 -0
  238. package/skills/fds-build/resources/components/local-nav.md +119 -0
  239. package/skills/fds-build/resources/components/masthead.md +14 -0
  240. package/skills/fds-build/resources/components/menu.md +109 -0
  241. package/skills/fds-build/resources/components/modal.md +150 -0
  242. package/skills/fds-build/resources/components/navbar.md +270 -0
  243. package/skills/fds-build/resources/components/notification-banner.md +106 -0
  244. package/skills/fds-build/resources/components/pagination.md +104 -0
  245. package/skills/fds-build/resources/components/pill.md +55 -0
  246. package/skills/fds-build/resources/components/popover.md +80 -0
  247. package/skills/fds-build/resources/components/progress-indicator.md +47 -0
  248. package/skills/fds-build/resources/components/radio-button.md +66 -0
  249. package/skills/fds-build/resources/components/schedule.md +78 -0
  250. package/skills/fds-build/resources/components/sidenav.md +183 -0
  251. package/skills/fds-build/resources/components/singpass-button.md +14 -0
  252. package/skills/fds-build/resources/components/smart-app-banner.md +28 -0
  253. package/skills/fds-build/resources/components/tab.md +107 -0
  254. package/skills/fds-build/resources/components/table.md +65 -0
  255. package/skills/fds-build/resources/components/tag.md +68 -0
  256. package/skills/fds-build/resources/components/text-list.md +44 -0
  257. package/skills/fds-build/resources/components/time-slot-bar-week.md +66 -0
  258. package/skills/fds-build/resources/components/time-slot-bar.md +57 -0
  259. package/skills/fds-build/resources/components/time-slot-week-view.md +70 -0
  260. package/skills/fds-build/resources/components/timeline.md +69 -0
  261. package/skills/fds-build/resources/components/timetable.md +123 -0
  262. package/skills/fds-build/resources/components/toast.md +72 -0
  263. package/skills/fds-build/resources/components/toggle.md +119 -0
  264. package/skills/fds-build/resources/components/typography.md +86 -0
  265. package/skills/fds-build/resources/components/uneditable-section.md +84 -0
  266. package/skills/fds-build/resources/foundations/layout-composition-patterns.md +53 -0
  267. package/skills/fds-build/resources/foundations/tokens.md +547 -0
  268. package/skills/fds-build/resources/patterns/states.md +300 -0
  269. package/skills/fds-build/resources/setup/setup.md +202 -0
  270. package/skills/fds-build/resources/templates/form.md +427 -0
  271. package/skills/fds-build/resources/templates/listing.md +435 -0
  272. package/theme/styles/a11y-playground.css +52 -40
  273. package/theme/styles/bookingsg.css +52 -40
  274. package/theme/styles/careercompass.css +52 -40
  275. package/theme/styles/ccube.css +52 -40
  276. package/theme/styles/imda.css +52 -40
  277. package/theme/styles/lifesg.css +52 -40
  278. package/theme/styles/mylegacy.css +52 -40
  279. package/theme/styles/oneservice.css +52 -40
  280. package/theme/styles/pa.css +28 -22
  281. package/theme/styles/rbs.css +52 -40
  282. package/theme/styles/sgw-digital-lobby.css +52 -40
  283. package/theme/styles/smgs.css +52 -40
  284. package/theme/styles/spf.css +28 -27
  285. package/theme/styles/sportsg-orange.css +52 -40
  286. package/theme/styles/supportgowhere.css +52 -40
  287. package/theme/styles/tote-board.css +52 -40
  288. package/theme/styles/vica.css +52 -40
  289. package/theme/styles/websg.css +52 -40
  290. package/theme/styles/wise.css +52 -40
  291. package/theme/styles/wogaa.css +52 -40
  292. package/theme/tokens/colour.d.ts +6 -0
  293. package/theme/tokens/colour.js +1 -1
  294. package/theme/tokens/colour.js.map +1 -1
  295. package/theme/tokens/radius.d.ts +3 -0
  296. package/theme/tokens/radius.js +1 -1
  297. package/theme/tokens/radius.js.map +1 -1
  298. package/breadcrumb/breadcrumb.styles_1nl4aua.css +0 -18
  299. package/cjs/breadcrumb/breadcrumb.styles_1nl4aua.css +0 -18
  300. package/cjs/file-upload/file-item-edit.js +0 -2
  301. package/cjs/file-upload/file-item-edit.js.map +0 -1
  302. package/cjs/file-upload/file-item-edit.styles.js +0 -2
  303. package/cjs/file-upload/file-item-edit.styles.js.map +0 -1
  304. package/cjs/file-upload/file-item-edit.styles_19bvztn.css +0 -11
  305. package/cjs/file-upload/file-list/file-list.styles_1w7so98.css +0 -3
  306. package/cjs/file-upload/file-list-item/file-list-item.styles_kgtfke.css +0 -17
  307. package/cjs/local-nav/local-nav-menu/local-nav-menu.styles_pq19dh.css +0 -5
  308. package/cjs/menu/menu-content.styles_p7ijll.css +0 -2
  309. package/cjs/menu/menu-link.styles_hfxoez.css +0 -2
  310. package/cjs/menu/menu-section.styles_g7my4d.css +0 -3
  311. package/file-upload/file-item-edit.d.ts +0 -14
  312. package/file-upload/file-item-edit.js +0 -2
  313. package/file-upload/file-item-edit.js.map +0 -1
  314. package/file-upload/file-item-edit.styles.d.ts +0 -9
  315. package/file-upload/file-item-edit.styles.js +0 -2
  316. package/file-upload/file-item-edit.styles.js.map +0 -1
  317. package/file-upload/file-item-edit.styles_19bvztn.css +0 -11
  318. package/file-upload/file-list/file-list.styles_1w7so98.css +0 -3
  319. package/file-upload/file-list-item/file-list-item.styles_kgtfke.css +0 -17
  320. package/local-nav/local-nav-menu/local-nav-menu.styles_pq19dh.css +0 -5
  321. package/menu/menu-content.styles_p7ijll.css +0 -2
  322. package/menu/menu-link.styles_hfxoez.css +0 -2
  323. package/menu/menu-section.styles_g7my4d.css +0 -3
@@ -1,2 +1,2 @@
1
- import"./menu-item.styles_liyed8.css";const s="m1ddqpur",t="tor9xcz",e="s12tso9";export{s as menuItemDiv,e as subLabel,t as text};
1
+ import"./menu-item.styles_eut2j9.css";const t="m1ddqpur",s="tor9xcz",e="s12tso9";export{t as menuItemDiv,e as subLabel,s as text};
2
2
  //# sourceMappingURL=menu-item.styles.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"menu-item.styles.js","sources":["../../src/menu/menu-item.styles.ts"],"sourcesContent":["import { css } from \"@linaria/core\";\n\nimport { Colour, Spacing } from \"../theme/tokens\";\n\nexport const menuItemDiv = css`\n display: flex;\n flex-direction: column;\n padding: ${Spacing[\"spacing-8\"]} ${Spacing[\"spacing-16\"]};\n`;\n\nexport const text = css`\n color: ${Colour[\"text\"]};\n`;\n\nexport const subLabel = css`\n color: ${Colour[\"text-subtler\"]};\n`;\n"],"names":["menuItemDiv","text","subLabel"],"mappings":"0DAIO,MAAMA,EAAW,WAMXC,EAAI,UAIJC,EAAQ"}
1
+ {"version":3,"file":"menu-item.styles.js","sources":["../../src/menu/menu-item.styles.ts"],"sourcesContent":["import { css } from \"@linaria/core\";\n\nimport { Colour, Spacing } from \"../theme/tokens\";\n\nexport const menuItemDiv = css`\n display: flex;\n flex-direction: column;\n padding: ${Spacing[\"spacing-12\"]} ${Spacing[\"spacing-16\"]};\n`;\n\nexport const text = css`\n color: ${Colour[\"text\"]};\n`;\n\nexport const subLabel = css`\n color: ${Colour[\"text-subtler\"]};\n`;\n"],"names":["menuItemDiv","text","subLabel"],"mappings":"0DAIO,MAAMA,EAAW,WAMXC,EAAI,UAIJC,EAAQ"}
@@ -1,3 +1,3 @@
1
- @layer fds{.m1ddqpur{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;padding:var(--fds-spacing-8) var(--fds-spacing-16);}
1
+ @layer fds{.m1ddqpur{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;padding:var(--fds-spacing-12) var(--fds-spacing-16);}
2
2
  .tor9xcz{color:var(--fds-colour-text);}
3
3
  .s12tso9{color:var(--fds-colour-text-subtler);}}
@@ -1,2 +1,2 @@
1
- import"./menu-link.styles_hfxoez.css";const m="mmmrhdq",e="l5rk4za";export{e as link,m as menuLinkDiv};
1
+ import"./menu-link.styles_rng7n7.css";const m="mmmrhdq",n="l5rk4za";export{n as link,m as menuLinkDiv};
2
2
  //# sourceMappingURL=menu-link.styles.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"menu-link.styles.js","sources":["../../src/menu/menu-link.styles.ts"],"sourcesContent":["import { css } from \"@linaria/core\";\n\nimport { lineClampCss } from \"../shared/styles\";\nimport { Border, Colour, Radius, Spacing } from \"../theme/tokens\";\n\nexport const menuLinkDiv = css`\n display: flex;\n flex-direction: column;\n`;\n\nexport const link = css`\n color: ${Colour[\"text\"]};\n\n margin: 0 ${Spacing[\"spacing-8\"]};\n\n border: ${Border[\"solid\"]} transparent;\n border-width: ${Spacing[\"spacing-8\"]} ${Spacing[\"spacing-8\"]};\n\n border-radius: ${Radius[\"md\"]};\n\n ${lineClampCss(2)}\n white-space: pre-wrap;\n\n &:hover,\n &:active,\n &:focus {\n background-color: ${Colour[\"bg-hover\"]};\n color: ${Colour[\"text\"]};\n }\n\n &:focus-visible {\n outline: 2px solid ${Colour[\"focus-ring\"]};\n outline-offset: 0;\n }\n`;\n"],"names":["menuLinkDiv","link"],"mappings":"0DAKO,MAAMA,EAAW,UAKXC,EAAI"}
1
+ {"version":3,"file":"menu-link.styles.js","sources":["../../src/menu/menu-link.styles.ts"],"sourcesContent":["import { css } from \"@linaria/core\";\n\nimport { lineClampCss } from \"../shared/styles\";\nimport { Border, Colour, Radius, Spacing } from \"../theme/tokens\";\n\nexport const menuLinkDiv = css`\n display: flex;\n flex-direction: column;\n`;\n\nexport const link = css`\n color: ${Colour[\"text\"]};\n\n margin: 0 ${Spacing[\"spacing-8\"]};\n\n border: ${Border[\"solid\"]} transparent;\n border-width: ${Spacing[\"spacing-12\"]} ${Spacing[\"spacing-8\"]};\n\n border-radius: ${Radius[\"md\"]};\n\n ${lineClampCss(2)}\n white-space: pre-wrap;\n\n &:hover,\n &:active,\n &:focus {\n background-color: ${Colour[\"bg-hover\"]};\n color: ${Colour[\"text\"]};\n }\n\n &:focus-visible {\n outline: 2px solid ${Colour[\"focus-ring\"]};\n outline-offset: 0;\n }\n`;\n"],"names":["menuLinkDiv","link"],"mappings":"0DAKO,MAAMA,EAAW,UAKXC,EAAI"}
@@ -0,0 +1,2 @@
1
+ @layer fds{.mmmrhdq{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;}
2
+ .l5rk4za{color:var(--fds-colour-text);margin:0 var(--fds-spacing-8);border:var(--fds-border-style-solid) transparent;border-width:var(--fds-spacing-12) var(--fds-spacing-8);border-radius:var(--fds-radius-md);display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;white-space:pre-wrap;}.l5rk4za:hover,.l5rk4za:active,.l5rk4za:focus{background-color:var(--fds-colour-bg-hover);color:var(--fds-colour-text);}.l5rk4za:focus-visible{outline:2px solid var(--fds-colour-focus-ring);outline-offset:0;}}
@@ -1,5 +1,5 @@
1
1
  import type { MenuSectionProps } from "./types";
2
2
  export declare const MenuSection: {
3
- ({ children, label, showDivider, className, "data-testid": testId, ...otherProps }: MenuSectionProps): JSX.Element;
3
+ ({ children, label, showDivider, className, columns, "data-testid": testId, ...otherProps }: MenuSectionProps): JSX.Element;
4
4
  displayName: string;
5
5
  };
@@ -1,2 +1,2 @@
1
- import{__rest as e}from"../_virtual/_tslib.js";import{jsxs as i,jsx as r}from"react/jsx-runtime";import t from"clsx";import{Typography as a}from"../typography/index.js";import"../util/calendar-helper.js";import"../external/dayjs/dayjs.min.js";import"react";import{useId as s}from"../util/simple-id-generator.js";import"../util/string-helper.js";import"@react-aria/live-announcer";import{section as l,sectionWithDivider as o,label as m}from"./menu-section.styles.js";const n=n=>{var{children:d,label:c,showDivider:p=!0,className:j,"data-testid":u="menu-section"}=n,h=e(n,["children","label","showDivider","className","data-testid"]);const y=s();return i("ul",Object.assign({"data-testid":u,"aria-labelledby":y,className:t(l,p&&o,j)},h,{children:[c&&r(a.BodyXS,{className:m,weight:"semibold",id:y,children:c}),d]}))};n.displayName="Menu.Section";export{n as MenuSection};
1
+ import{__rest as e}from"../_virtual/_tslib.js";import{jsx as t,jsxs as i}from"react/jsx-runtime";import r from"clsx";import{useRef as s,useMemo as o,Children as m}from"react";import"../theme/theme-provider/index.js";import"../theme/theme-provider/context.js";import"../theme/tokens/border.js";import"../theme/tokens/colour.js";import"../theme/tokens/font.js";import"../theme/tokens/media-query.js";import{useApplyStyle as a}from"../theme/utils/use-apply-styles.js";import"../theme/utils/use-media-query.js";import{Typography as l}from"../typography/index.js";import"../util/calendar-helper.js";import"../external/dayjs/dayjs.min.js";import{useId as n}from"../util/simple-id-generator.js";import"../util/string-helper.js";import"@react-aria/live-announcer";import{gridTokens as d,label as p,list as c,listColumns as h,section as u,sectionWithDivider as j}from"./menu-section.styles.js";const v=v=>{var{children:y,label:f,showDivider:b=!0,className:x,columns:g,"data-testid":N="menu-section"}=v,k=e(v,["children","label","showDivider","className","columns","data-testid"]);const w=n(),M=s(null),S=o((()=>void 0!==g?Math.ceil(m.count(y)/Math.max(1,g)):void 0),[g,y]);a(M,void 0!==S?{[d.rows]:String(S)}:void 0);const q=f?t(l.BodyXS,{className:p,weight:"semibold",id:w,children:f}):null;return i("div",{className:r(u,b&&j,x),children:[q,t("ul",Object.assign({ref:M,"data-testid":N,"aria-labelledby":w,className:r(c,g&&h)},k,{children:y}))]})};v.displayName="Menu.Section";export{v as MenuSection};
2
2
  //# sourceMappingURL=menu-section.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"menu-section.js","sources":["../../src/menu/menu-section.tsx"],"sourcesContent":["import clsx from \"clsx\";\n\nimport { Typography } from \"../typography\";\nimport { useId } from \"../util\";\nimport * as styles from \"./menu-section.styles\";\nimport type { MenuSectionProps } from \"./types\";\n\nexport const MenuSection = ({\n children,\n label,\n showDivider = true,\n className,\n \"data-testid\": testId = \"menu-section\",\n ...otherProps\n}: MenuSectionProps): JSX.Element => {\n // =============================================================================\n // CONST, STATE, REF\n // =============================================================================\n const internalId = useId();\n\n // =============================================================================\n // RENDER FUNCTIONS\n // =============================================================================\n return (\n <ul\n data-testid={testId}\n aria-labelledby={internalId}\n className={clsx(\n styles.section,\n showDivider && styles.sectionWithDivider,\n className\n )}\n {...otherProps}\n >\n {label && (\n <Typography.BodyXS\n className={styles.label}\n weight=\"semibold\"\n id={internalId}\n >\n {label}\n </Typography.BodyXS>\n )}\n {children}\n </ul>\n );\n};\n\nMenuSection.displayName = \"Menu.Section\";\n"],"names":["MenuSection","_a","children","label","showDivider","className","testId","otherProps","__rest","internalId","useId","_jsxs","Object","assign","clsx","styles.section","styles.sectionWithDivider","_jsx","Typography","BodyXS","styles.label","weight","id","displayName"],"mappings":"kdAOO,MAAMA,EAAeC,QAAAC,SACxBA,EAAQC,MACRA,EAAKC,YACLA,GAAc,EAAIC,UAClBA,EACA,cAAeC,EAAS,gBAAcL,EACnCM,EAAUC,EAAAP,EANW,8DAWxB,MAAMQ,EAAaC,IAKnB,OACIC,EAAA,KAAAC,OAAAC,OAAA,CAAA,cACiBP,EAAM,kBACFG,EACjBJ,UAAWS,EACPC,EACAX,GAAeY,EACfX,IAEAE,EAAU,CAAAL,SAAA,CAEbC,GACGc,EAACC,EAAWC,OAAM,CACdd,UAAWe,EACXC,OAAO,WACPC,GAAIb,EAAUP,SAEbC,IAGRD,KACA,EAIbF,EAAYuB,YAAc"}
1
+ {"version":3,"file":"menu-section.js","sources":["../../src/menu/menu-section.tsx"],"sourcesContent":["import clsx from \"clsx\";\nimport { Children, useMemo, useRef } from \"react\";\n\nimport { useApplyStyle } from \"../theme\";\nimport { Typography } from \"../typography\";\nimport { useId } from \"../util\";\nimport * as styles from \"./menu-section.styles\";\nimport type { MenuSectionProps } from \"./types\";\n\nexport const MenuSection = ({\n children,\n label,\n showDivider = true,\n className,\n columns,\n \"data-testid\": testId = \"menu-section\",\n ...otherProps\n}: MenuSectionProps): JSX.Element => {\n // =============================================================================\n // CONST, STATE, REF\n // =============================================================================\n const internalId = useId();\n const ulRef = useRef<HTMLUListElement>(null);\n const gridRows = useMemo(\n () =>\n columns !== undefined\n ? Math.ceil(Children.count(children) / Math.max(1, columns))\n : undefined,\n [columns, children]\n );\n\n // =========================================================================\n // EFFECTS\n // =========================================================================\n useApplyStyle(\n ulRef,\n gridRows !== undefined\n ? { [styles.gridTokens.rows]: String(gridRows) }\n : undefined\n );\n\n // =============================================================================\n // RENDER FUNCTIONS\n // =============================================================================\n const labelElement = label ? (\n <Typography.BodyXS\n className={styles.label}\n weight=\"semibold\"\n id={internalId}\n >\n {label}\n </Typography.BodyXS>\n ) : null;\n\n return (\n <div\n className={clsx(\n styles.section,\n showDivider && styles.sectionWithDivider,\n className\n )}\n >\n {labelElement}\n <ul\n ref={ulRef}\n data-testid={testId}\n aria-labelledby={internalId}\n className={clsx(styles.list, columns && styles.listColumns)}\n {...otherProps}\n >\n {children}\n </ul>\n </div>\n );\n};\n\nMenuSection.displayName = \"Menu.Section\";\n"],"names":["MenuSection","_a","children","label","showDivider","className","columns","testId","otherProps","__rest","internalId","useId","ulRef","useRef","gridRows","useMemo","undefined","Math","ceil","Children","count","max","useApplyStyle","styles.gridTokens","rows","String","labelElement","_jsx","Typography","BodyXS","styles.label","weight","id","_jsxs","clsx","styles.section","styles.sectionWithDivider","Object","assign","ref","styles.list","styles.listColumns","displayName"],"mappings":"q3BASO,MAAMA,EAAeC,QAAAC,SACxBA,QACAC,EAAKC,YACLA,GAAc,EAAIC,UAClBA,EAASC,QACTA,EACA,cAAeC,EAAS,kBACrBC,EAAUC,EAAAR,EAPW,CAAA,WAAA,QAAA,cAAA,YAAA,UAAA,gBAYxB,MAAMS,EAAaC,IACbC,EAAQC,EAAyB,MACjCC,EAAWC,GACb,SACgBC,IAAZV,EACMW,KAAKC,KAAKC,EAASC,MAAMlB,GAAYe,KAAKI,IAAI,EAAGf,SACjDU,GACV,CAACV,EAASJ,IAMdoB,EACIV,OACaI,IAAbF,EACM,CAAE,CAACS,EAAkBC,MAAOC,OAAOX,SACnCE,GAMV,MAAMU,EAAevB,EACjBwB,EAACC,EAAWC,OAAM,CACdxB,UAAWyB,EACXC,OAAO,WACPC,GAAItB,EAAUR,SAEbC,IAEL,KAEJ,OACI8B,SACI5B,UAAW6B,EACPC,EACA/B,GAAegC,EACf/B,aAGHqB,EACDC,EAAA,KAAAU,OAAAC,OAAA,CACIC,IAAK3B,gBACQL,EAAM,kBACFG,EACjBL,UAAW6B,EAAKM,EAAalC,GAAWmC,IACpCjC,YAEHN,OAEH,EAIdF,EAAY0C,YAAc"}
@@ -1,3 +1,10 @@
1
+ export declare const gridTokens: {
2
+ readonly rows: "--fds-menu-section-grid-rows";
3
+ };
4
+ export declare const GRID_COLUMN_WIDTH_PX = 383;
5
+ export declare const GRID_COLUMN_GAP_PX = 8;
1
6
  export declare const section: import("@linaria/core").LinariaClassName;
2
7
  export declare const sectionWithDivider: import("@linaria/core").LinariaClassName;
3
8
  export declare const label: import("@linaria/core").LinariaClassName;
9
+ export declare const list: import("@linaria/core").LinariaClassName;
10
+ export declare const listColumns: import("@linaria/core").LinariaClassName;
@@ -1,2 +1,2 @@
1
- import"./menu-section.styles_g7my4d.css";const s="s1fmxqsy",t="s1o971t2",e="llhca5j";export{e as label,s as section,t as sectionWithDivider};
1
+ import"./menu-section.styles_1n0ppxl.css";const s={rows:"--fds-menu-section-grid-rows"},o=383,e=8,l="s1fmxqsy",n="s1o971t2",t="llhca5j",c="l7qikvl",i="l6d0215";export{e as GRID_COLUMN_GAP_PX,o as GRID_COLUMN_WIDTH_PX,s as gridTokens,t as label,c as list,i as listColumns,l as section,n as sectionWithDivider};
2
2
  //# sourceMappingURL=menu-section.styles.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"menu-section.styles.js","sources":["../../src/menu/menu-section.styles.ts"],"sourcesContent":["import { css } from \"@linaria/core\";\n\nimport { Border, Colour, Spacing } from \"../theme/tokens\";\n\nexport const section = css`\n padding: ${Spacing[\"spacing-8\"]} 0;\n margin: 0;\n list-style: none;\n`;\nexport const sectionWithDivider = css`\n border-top: ${Border[\"width-010\"]} ${Border[\"solid\"]} ${Colour[\"border\"]};\n`;\n\nexport const label = css`\n margin: 0 ${Spacing[\"spacing-16\"]} ${Spacing[\"spacing-8\"]};\n color: ${Colour[\"text-subtler\"]};\n`;\n"],"names":["section","sectionWithDivider","label"],"mappings":"6DAIO,MAAMA,EAAO,WAKPC,EAAkB,WAIlBC,EAAK"}
1
+ {"version":3,"file":"menu-section.styles.js","sources":["../../src/menu/menu-section.styles.ts"],"sourcesContent":["import { css } from \"@linaria/core\";\n\nimport { Border, Colour, MediaQuery, Spacing } from \"../theme/tokens\";\n\nexport const gridTokens = {\n rows: \"--fds-menu-section-grid-rows\",\n} as const;\n\n// 367px max content width (Figma) + 8px padding per side; used to cap the panel maxWidth in MenuContent\nexport const GRID_COLUMN_WIDTH_PX = 383;\n// matches Spacing[\"spacing-8\"]\nexport const GRID_COLUMN_GAP_PX = 8;\n\nexport const section = css`\n padding: ${Spacing[\"spacing-8\"]} 0;\n margin: 0;\n`;\n\nexport const sectionWithDivider = css`\n border-top: ${Border[\"width-010\"]} ${Border[\"solid\"]} ${Colour[\"border\"]};\n`;\n\nexport const label = css`\n margin: 0 ${Spacing[\"spacing-16\"]} ${Spacing[\"spacing-8\"]};\n color: ${Colour[\"text-subtler\"]};\n`;\n\nexport const list = css`\n list-style: none;\n`;\n\nexport const listColumns = css`\n ${gridTokens.rows}: initial;\n\n display: grid;\n grid-template-rows: repeat(var(${gridTokens.rows}), auto);\n grid-auto-flow: column;\n grid-auto-columns: minmax(0, 1fr);\n column-gap: ${Spacing[\"spacing-8\"]};\n\n ${MediaQuery.MaxWidth.lg} {\n grid-template-rows: none;\n grid-auto-flow: row;\n }\n`;\n"],"names":["gridTokens","rows","GRID_COLUMN_WIDTH_PX","GRID_COLUMN_GAP_PX","section","sectionWithDivider","label","list","listColumns"],"mappings":"8DAIO,MAAMA,EAAa,CACtBC,KAAM,gCAIGC,EAAuB,IAEvBC,EAAqB,EAErBC,EAAO,WAKPC,EAAkB,WAIlBC,EAAK,UAKLC,EAAI,UAIJC,EAAW"}
@@ -0,0 +1,5 @@
1
+ @layer fds{.s1fmxqsy{padding:var(--fds-spacing-8) 0;margin:0;}
2
+ .s1o971t2{border-top:var(--fds-border-width-010) var(--fds-border-style-solid) var(--fds-colour-border);}
3
+ .llhca5j{margin:0 var(--fds-spacing-16) var(--fds-spacing-8);color:var(--fds-colour-text-subtler);}
4
+ .l7qikvl{list-style:none;}
5
+ .l6d0215{--fds-menu-section-grid-rows:initial;display:-ms-grid;display:grid;-ms-grid-rows:repeat(var(--fds-menu-section-grid-rows), auto);grid-template-rows:repeat(var(--fds-menu-section-grid-rows), auto);-ms-grid-auto-flow:column;grid-auto-flow:column;-ms-grid-auto-columns:minmax(0, 1fr);grid-auto-columns:minmax(0, 1fr);-webkit-column-gap:var(--fds-spacing-8);column-gap:var(--fds-spacing-8);}:where(body.fds-breakpoint-lg-max) .l6d0215{-ms-grid-rows:none;grid-template-rows:none;-ms-grid-auto-flow:row;grid-auto-flow:row;}}
package/menu/menu.d.ts CHANGED
@@ -38,7 +38,7 @@ export declare const Menu: (({ children, position, menuContent, "data-testid": t
38
38
  };
39
39
  /** Groups related menu entries. */
40
40
  Section: {
41
- ({ children, label, showDivider, className, "data-testid": testId, ...otherProps }: import("./types").MenuSectionProps): JSX.Element;
41
+ ({ children, label, showDivider, className, columns, "data-testid": testId, ...otherProps }: import("./types").MenuSectionProps): JSX.Element;
42
42
  displayName: string;
43
43
  };
44
44
  };
package/menu/types.d.ts CHANGED
@@ -2,7 +2,6 @@ import type { AnchorHTMLAttributes, FunctionComponentElement, HTMLAttributes, Re
2
2
  import type { PopoverPosition, PopoverRenderProps, PopoverTriggerProps } from "../popover";
3
3
  import type { MenuItem } from "./menu-item";
4
4
  import type { MenuLink } from "./menu-link";
5
- import type { MenuSection } from "./menu-section";
6
5
  /**
7
6
  * Props for the `Menu` component.
8
7
  *
@@ -24,7 +23,7 @@ export interface MenuProps extends Omit<PopoverTriggerProps, "popoverContent"> {
24
23
  */
25
24
  export interface MenuContentProps extends HTMLAttributes<HTMLDivElement>, PopoverRenderProps {
26
25
  /** One or more `Menu.Section` elements that make up the panel body. */
27
- children: ReactElement<typeof MenuSection> | ReactElement<typeof MenuSection>[];
26
+ children: ReactElement<MenuSectionProps> | ReactElement<MenuSectionProps>[];
28
27
  "data-testid"?: string | undefined;
29
28
  }
30
29
  type MenuSectionItem = ReactElement<typeof MenuItem> | ReactElement<typeof MenuLink>;
@@ -40,6 +39,15 @@ export interface MenuSectionProps extends HTMLAttributes<HTMLUListElement> {
40
39
  * @default true
41
40
  */
42
41
  showDivider?: boolean | undefined;
42
+ /**
43
+ * Renders section children in a grid with the given number of columns
44
+ * on desktop. Items flow vertically (top-to-bottom) within each column
45
+ * before wrapping to the next. Has no effect on mobile viewports, which
46
+ * always render as a single column.
47
+ *
48
+ * @minimum 1
49
+ */
50
+ columns?: number | undefined;
43
51
  /**
44
52
  * Accessible group label rendered above the section items.
45
53
  */
@@ -1,2 +1,2 @@
1
- import"./slot-styles_ayb9il.css";const s="cetykyj",t="m1247joo",o="ft53q25",l="c1ls09wh",a="s1s12qxk",c="c1vsayl1",h="f1adf5mq",r="sii7rdr",e="fa88pah",f="h3mtfiz",i="h1evnebr",m="ht9zr8k",y="hjbud0c";export{s as cardBase,l as closeButtonContainer,c as contentContainer,h as footerContainer,o as fullscreenModalCard,e as fullscreenSlotSpacer,m as headerCloseButton,f as headerContainer,y as headerSpacer,i as headerTitle,t as modalCard,r as slotSpacer,a as styledClickableIcon};
1
+ import"./slot-styles_ygu6zc.css";const s="cetykyj",t="m1247joo",o="ft53q25",c="c1ls09wh",h="s1s12qxk",l="c1vsayl1",r="f1adf5mq",a="sii7rdr",e="fa88pah",f="h3mtfiz",m="h1evnebr",y="ht9zr8k",d="hjbud0c";export{s as cardBase,c as closeButtonContainer,l as contentContainer,r as footerContainer,o as fullscreenModalCard,e as fullscreenSlotSpacer,y as headerCloseButton,f as headerContainer,d as headerSpacer,m as headerTitle,t as modalCard,a as slotSpacer,h as styledClickableIcon};
2
2
  //# sourceMappingURL=slot-styles.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"slot-styles.js","sources":["../../../src/modal-v2/slots/slot-styles.ts"],"sourcesContent":["import { css } from \"@linaria/core\";\n\nimport {\n Breakpoint,\n Colour,\n Font,\n MediaQuery,\n Radius,\n Shadow,\n Spacing,\n} from \"../../theme\";\n\n// =============================================================================\n// Tokens and attributes\n// =============================================================================\nexport const slotSpacerHasCloseButtonAttribute = \"data-has-close-button\";\nconst internalSlotSpacerTokens = {\n firstChildMarginTop:\n \"--fds-internal-modalV2-slotSpacer-firstChildMarginTop\",\n} as const;\n\nexport const slotSpacerTokens = {\n firstChildMarginTopWithCloseButton:\n \"--fds-internal-modalV2-slotSpacer-firstChildMarginTopWithCloseButton\",\n firstChildMarginTopNoCloseButton:\n \"--fds-internal-modalV2-slotSpacer-firstChildMarginTopNoCloseButton\",\n\n contentLastChildMarginBottom:\n \"--fds-internal-modalV2-slotSpacer-contentLastChildMarginBottom\",\n\n footerNotFirstChildMarginTop:\n \"--fds-internal-modalV2-slotSpacer-footerNotFirstChildMarginTop\",\n footerLastChildMarginBottom:\n \"--fds-internal-modalV2-slotSpacer-footerLastChildMarginBottom\",\n} as const;\n\n// =============================================================================\n// STYLING\n// =============================================================================\n/** Shared by both the windowed (`modalCard`) and `fullscreenModalCard` variants. */\nexport const cardBase = css`\n background: ${Colour.bg};\n\n display: flex;\n flex-direction: column-reverse;\n`;\n\nexport const modalCard = css`\n width: 40rem;\n margin: ${Spacing[\"spacing-64\"]} auto;\n box-shadow: ${Shadow[\"xs-strong\"]};\n border-radius: ${Radius[\"lg\"]};\n\n max-width: calc(100% - ${Breakpoint[\"xxl-margin\"]} * 2);\n\n ${MediaQuery.MaxWidth.xl} {\n max-width: calc(100% - ${Breakpoint[\"xl-margin\"]} * 2);\n }\n\n ${MediaQuery.MaxWidth.lg} {\n max-width: calc(100% - ${Breakpoint[\"lg-margin\"]} * 2);\n }\n\n ${MediaQuery.MaxWidth.md} {\n max-width: calc(100% - ${Breakpoint[\"md-margin\"]} * 2);\n }\n\n ${MediaQuery.MaxWidth.sm} {\n max-width: calc(100% - ${Breakpoint[\"sm-margin\"]} * 2);\n }\n\n ${MediaQuery.MaxWidth.xs} {\n max-width: calc(100% - ${Breakpoint[\"xs-margin\"]} * 2);\n }\n\n ${MediaQuery.MaxWidth.xxs} {\n max-width: calc(100% - ${Breakpoint[\"xxs-margin\"]} * 2);\n }\n`;\n\nexport const fullscreenModalCard = css`\n width: 100%;\n height: 100vh;\n`;\n\nexport const closeButtonContainer = css`\n margin-right: ${Spacing[\"spacing-16\"]};\n margin-left: auto;\n margin-top: ${Spacing[\"spacing-16\"]};\n margin-bottom: ${Spacing[\"spacing-16\"]};\n`;\n\nexport const styledClickableIcon = css`\n padding: 0;\n color: ${Colour.icon};\n\n & svg {\n height: 2rem;\n width: 2rem;\n }\n`;\n\nexport const contentContainer = css`\n margin-right: ${Spacing[\"spacing-64\"]};\n margin-left: ${Spacing[\"spacing-64\"]};\n\n ${MediaQuery.MaxWidth.sm} {\n margin-right: ${Spacing[\"spacing-20\"]};\n margin-left: ${Spacing[\"spacing-20\"]};\n }\n`;\n\nexport const footerContainer = css`\n margin-right: ${Spacing[\"spacing-64\"]};\n margin-left: ${Spacing[\"spacing-64\"]};\n\n ${MediaQuery.MaxWidth.sm} {\n margin-right: ${Spacing[\"spacing-20\"]};\n margin-left: ${Spacing[\"spacing-20\"]};\n }\n\n display: flex;\n flex-direction: row-reverse; /* primary button on right */\n column-gap: ${Spacing[\"spacing-32\"]};\n row-gap: ${Spacing[\"spacing-16\"]};\n\n & > button {\n flex: 1;\n }\n\n ${MediaQuery.MaxWidth.md} {\n flex-direction: column;\n }\n`;\n\nexport const slotSpacer = css`\n ${slotSpacerTokens.contentLastChildMarginBottom}: initial;\n ${slotSpacerTokens.footerNotFirstChildMarginTop}: initial;\n ${slotSpacerTokens.footerLastChildMarginBottom}: initial;\n ${slotSpacerTokens.firstChildMarginTopWithCloseButton}: initial;\n ${slotSpacerTokens.firstChildMarginTopNoCloseButton}: initial;\n\n ${internalSlotSpacerTokens.firstChildMarginTop}: var(\n ${slotSpacerTokens.firstChildMarginTopNoCloseButton},\n ${Spacing[\"spacing-64\"]}\n );\n\n & > :where(.${contentContainer}:last-child) {\n margin-bottom: var(\n ${slotSpacerTokens.contentLastChildMarginBottom},\n ${Spacing[\"spacing-64\"]}\n );\n }\n\n & > :where(.${footerContainer}:not(:first-child)) {\n margin-top: var(\n ${slotSpacerTokens.footerNotFirstChildMarginTop},\n ${Spacing[\"spacing-32\"]}\n );\n }\n\n & > :where(.${footerContainer}:last-child) {\n margin-bottom: var(\n ${slotSpacerTokens.footerLastChildMarginBottom},\n ${Spacing[\"spacing-64\"]}\n );\n }\n\n &\n > :where(\n .${contentContainer}:first-child, .${footerContainer}:first-child\n ) {\n margin-top: var(${internalSlotSpacerTokens.firstChildMarginTop});\n }\n\n &[${slotSpacerHasCloseButtonAttribute}=\"true\"] {\n ${internalSlotSpacerTokens.firstChildMarginTop}: var(\n ${slotSpacerTokens.firstChildMarginTopWithCloseButton},\n 0\n );\n }\n\n &[${slotSpacerHasCloseButtonAttribute}=\"false\"] {\n ${internalSlotSpacerTokens.firstChildMarginTop}: var(\n ${slotSpacerTokens.firstChildMarginTopNoCloseButton},\n ${Spacing[\"spacing-64\"]}\n );\n }\n`;\n\nexport const fullscreenSlotSpacer = css`\n flex-grow: 1;\n\n display: flex;\n flex-direction: column;\n justify-content: space-between;\n`;\n\nexport const headerContainer = css`\n display: flex;\n align-items: center;\n padding: ${Spacing[\"spacing-16\"]};\n\n &[data-close-button-position=\"right\"] {\n flex-direction: row-reverse;\n }\n`;\n\nexport const headerTitle = css`\n ${Font[\"heading-xs-semibold\"]}\n color: ${Colour.text};\n flex: 1;\n text-align: center;\n`;\n\nexport const headerCloseButton = css`\n padding: 0;\n color: ${Colour.icon};\n flex-shrink: 0;\n\n & svg {\n height: 2rem;\n width: 2rem;\n }\n`;\n\nexport const headerSpacer = css`\n width: 2rem;\n flex-shrink: 0;\n`;\n"],"names":["cardBase","modalCard","fullscreenModalCard","closeButtonContainer","styledClickableIcon","contentContainer","footerContainer","slotSpacer","fullscreenSlotSpacer","headerContainer","headerTitle","headerCloseButton","headerSpacer"],"mappings":"+DAwCO,MAAMA,EAAQ,UAORC,EAAS,WAiCTC,EAAmB,UAKnBC,EAAoB,WAOpBC,EAAmB,WAUnBC,EAAgB,WAUhBC,EAAe,WAuBfC,EAAU,UAuDVC,EAAoB,UAQpBC,EAAe,UAUfC,EAAW,WAOXC,EAAiB,UAWjBC,EAAY"}
1
+ {"version":3,"file":"slot-styles.js","sources":["../../../src/modal-v2/slots/slot-styles.ts"],"sourcesContent":["import { css } from \"@linaria/core\";\n\nimport {\n Breakpoint,\n Colour,\n Font,\n MediaQuery,\n Radius,\n Shadow,\n Spacing,\n} from \"../../theme\";\n\n// =============================================================================\n// Tokens and attributes\n// =============================================================================\nexport const slotSpacerHasCloseButtonAttribute = \"data-has-close-button\";\nconst internalSlotSpacerTokens = {\n firstChildMarginTop:\n \"--fds-internal-modalV2-slotSpacer-firstChildMarginTop\",\n} as const;\n\nexport const slotSpacerTokens = {\n firstChildMarginTopWithCloseButton:\n \"--fds-internal-modalV2-slotSpacer-firstChildMarginTopWithCloseButton\",\n firstChildMarginTopNoCloseButton:\n \"--fds-internal-modalV2-slotSpacer-firstChildMarginTopNoCloseButton\",\n\n contentLastChildMarginBottom:\n \"--fds-internal-modalV2-slotSpacer-contentLastChildMarginBottom\",\n\n footerNotFirstChildMarginTop:\n \"--fds-internal-modalV2-slotSpacer-footerNotFirstChildMarginTop\",\n footerLastChildMarginBottom:\n \"--fds-internal-modalV2-slotSpacer-footerLastChildMarginBottom\",\n} as const;\n\n// =============================================================================\n// STYLING\n// =============================================================================\n/** Shared by both the windowed (`modalCard`) and `fullscreenModalCard` variants. */\nexport const cardBase = css`\n background: ${Colour.bg};\n\n display: flex;\n flex-direction: column-reverse;\n`;\n\nexport const modalCard = css`\n width: 40rem;\n margin: ${Spacing[\"spacing-64\"]} auto;\n box-shadow: ${Shadow[\"lg-strong\"]};\n border-radius: ${Radius[\"lg\"]};\n\n max-width: calc(100% - ${Breakpoint[\"xxl-margin\"]} * 2);\n\n ${MediaQuery.MaxWidth.xl} {\n max-width: calc(100% - ${Breakpoint[\"xl-margin\"]} * 2);\n }\n\n ${MediaQuery.MaxWidth.lg} {\n max-width: calc(100% - ${Breakpoint[\"lg-margin\"]} * 2);\n }\n\n ${MediaQuery.MaxWidth.md} {\n max-width: calc(100% - ${Breakpoint[\"md-margin\"]} * 2);\n }\n\n ${MediaQuery.MaxWidth.sm} {\n max-width: calc(100% - ${Breakpoint[\"sm-margin\"]} * 2);\n }\n\n ${MediaQuery.MaxWidth.xs} {\n max-width: calc(100% - ${Breakpoint[\"xs-margin\"]} * 2);\n }\n\n ${MediaQuery.MaxWidth.xxs} {\n max-width: calc(100% - ${Breakpoint[\"xxs-margin\"]} * 2);\n }\n`;\n\nexport const fullscreenModalCard = css`\n width: 100%;\n height: 100vh;\n`;\n\nexport const closeButtonContainer = css`\n margin-right: ${Spacing[\"spacing-16\"]};\n margin-left: auto;\n margin-top: ${Spacing[\"spacing-16\"]};\n margin-bottom: ${Spacing[\"spacing-16\"]};\n`;\n\nexport const styledClickableIcon = css`\n padding: 0;\n color: ${Colour.icon};\n\n & svg {\n height: 2rem;\n width: 2rem;\n }\n`;\n\nexport const contentContainer = css`\n margin-right: ${Spacing[\"spacing-64\"]};\n margin-left: ${Spacing[\"spacing-64\"]};\n\n ${MediaQuery.MaxWidth.sm} {\n margin-right: ${Spacing[\"spacing-20\"]};\n margin-left: ${Spacing[\"spacing-20\"]};\n }\n`;\n\nexport const footerContainer = css`\n margin-right: ${Spacing[\"spacing-64\"]};\n margin-left: ${Spacing[\"spacing-64\"]};\n\n ${MediaQuery.MaxWidth.sm} {\n margin-right: ${Spacing[\"spacing-20\"]};\n margin-left: ${Spacing[\"spacing-20\"]};\n }\n\n display: flex;\n flex-direction: row-reverse; /* primary button on right */\n column-gap: ${Spacing[\"spacing-32\"]};\n row-gap: ${Spacing[\"spacing-16\"]};\n\n & > button {\n flex: 1;\n }\n\n ${MediaQuery.MaxWidth.md} {\n flex-direction: column;\n }\n`;\n\nexport const slotSpacer = css`\n ${slotSpacerTokens.contentLastChildMarginBottom}: initial;\n ${slotSpacerTokens.footerNotFirstChildMarginTop}: initial;\n ${slotSpacerTokens.footerLastChildMarginBottom}: initial;\n ${slotSpacerTokens.firstChildMarginTopWithCloseButton}: initial;\n ${slotSpacerTokens.firstChildMarginTopNoCloseButton}: initial;\n\n ${internalSlotSpacerTokens.firstChildMarginTop}: var(\n ${slotSpacerTokens.firstChildMarginTopNoCloseButton},\n ${Spacing[\"spacing-64\"]}\n );\n\n & > :where(.${contentContainer}:last-child) {\n margin-bottom: var(\n ${slotSpacerTokens.contentLastChildMarginBottom},\n ${Spacing[\"spacing-64\"]}\n );\n }\n\n & > :where(.${footerContainer}:not(:first-child)) {\n margin-top: var(\n ${slotSpacerTokens.footerNotFirstChildMarginTop},\n ${Spacing[\"spacing-32\"]}\n );\n }\n\n & > :where(.${footerContainer}:last-child) {\n margin-bottom: var(\n ${slotSpacerTokens.footerLastChildMarginBottom},\n ${Spacing[\"spacing-64\"]}\n );\n }\n\n &\n > :where(\n .${contentContainer}:first-child, .${footerContainer}:first-child\n ) {\n margin-top: var(${internalSlotSpacerTokens.firstChildMarginTop});\n }\n\n &[${slotSpacerHasCloseButtonAttribute}=\"true\"] {\n ${internalSlotSpacerTokens.firstChildMarginTop}: var(\n ${slotSpacerTokens.firstChildMarginTopWithCloseButton},\n 0\n );\n }\n\n &[${slotSpacerHasCloseButtonAttribute}=\"false\"] {\n ${internalSlotSpacerTokens.firstChildMarginTop}: var(\n ${slotSpacerTokens.firstChildMarginTopNoCloseButton},\n ${Spacing[\"spacing-64\"]}\n );\n }\n`;\n\nexport const fullscreenSlotSpacer = css`\n flex-grow: 1;\n\n display: flex;\n flex-direction: column;\n justify-content: space-between;\n`;\n\nexport const headerContainer = css`\n display: flex;\n align-items: center;\n padding: ${Spacing[\"spacing-16\"]};\n\n &[data-close-button-position=\"right\"] {\n flex-direction: row-reverse;\n }\n`;\n\nexport const headerTitle = css`\n ${Font[\"heading-xs-semibold\"]}\n color: ${Colour.text};\n flex: 1;\n text-align: center;\n`;\n\nexport const headerCloseButton = css`\n padding: 0;\n color: ${Colour.icon};\n flex-shrink: 0;\n\n & svg {\n height: 2rem;\n width: 2rem;\n }\n`;\n\nexport const headerSpacer = css`\n width: 2rem;\n flex-shrink: 0;\n`;\n"],"names":["cardBase","modalCard","fullscreenModalCard","closeButtonContainer","styledClickableIcon","contentContainer","footerContainer","slotSpacer","fullscreenSlotSpacer","headerContainer","headerTitle","headerCloseButton","headerSpacer"],"mappings":"+DAwCO,MAAMA,EAAQ,UAORC,EAAS,WAiCTC,EAAmB,UAKnBC,EAAoB,WAOpBC,EAAmB,WAUnBC,EAAgB,WAUhBC,EAAe,WAuBfC,EAAU,UAuDVC,EAAoB,UAQpBC,EAAe,UAUfC,EAAW,WAOXC,EAAiB,UAWjBC,EAAY"}
@@ -1,5 +1,5 @@
1
1
  @layer fds{.cetykyj{background:var(--fds-colour-bg);display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:column-reverse;-ms-flex-direction:column-reverse;flex-direction:column-reverse;}
2
- .m1247joo{width:40rem;margin:var(--fds-spacing-64) auto;box-shadow:var(--fds-shadow-xs-strong);border-radius:var(--fds-radius-lg);max-width:calc(100% - var(--fds-breakpoint-margin-xxl) * 2);}:where(body.fds-breakpoint-xl-max) .m1247joo{max-width:calc(100% - var(--fds-breakpoint-margin-xl) * 2);}:where(body.fds-breakpoint-lg-max) .m1247joo{max-width:calc(100% - var(--fds-breakpoint-margin-lg) * 2);}:where(body.fds-breakpoint-md-max) .m1247joo{max-width:calc(100% - var(--fds-breakpoint-margin-md) * 2);}:where(body.fds-breakpoint-sm-max) .m1247joo{max-width:calc(100% - var(--fds-breakpoint-margin-sm) * 2);}:where(body.fds-breakpoint-xs-max) .m1247joo{max-width:calc(100% - var(--fds-breakpoint-margin-xs) * 2);}:where(body.fds-breakpoint-xxs-max) .m1247joo{max-width:calc(100% - var(--fds-breakpoint-margin-xxs) * 2);}
2
+ .m1247joo{width:40rem;margin:var(--fds-spacing-64) auto;box-shadow:var(--fds-shadow-lg-strong);border-radius:var(--fds-radius-lg);max-width:calc(100% - var(--fds-breakpoint-margin-xxl) * 2);}:where(body.fds-breakpoint-xl-max) .m1247joo{max-width:calc(100% - var(--fds-breakpoint-margin-xl) * 2);}:where(body.fds-breakpoint-lg-max) .m1247joo{max-width:calc(100% - var(--fds-breakpoint-margin-lg) * 2);}:where(body.fds-breakpoint-md-max) .m1247joo{max-width:calc(100% - var(--fds-breakpoint-margin-md) * 2);}:where(body.fds-breakpoint-sm-max) .m1247joo{max-width:calc(100% - var(--fds-breakpoint-margin-sm) * 2);}:where(body.fds-breakpoint-xs-max) .m1247joo{max-width:calc(100% - var(--fds-breakpoint-margin-xs) * 2);}:where(body.fds-breakpoint-xxs-max) .m1247joo{max-width:calc(100% - var(--fds-breakpoint-margin-xxs) * 2);}
3
3
  .ft53q25{width:100%;height:100vh;}
4
4
  .c1ls09wh{margin-right:var(--fds-spacing-16);margin-left:auto;margin-top:var(--fds-spacing-16);margin-bottom:var(--fds-spacing-16);}
5
5
  .s1s12qxk{padding:0;color:var(--fds-colour-icon);}.s1s12qxk svg{height:2rem;width:2rem;}
@@ -1,2 +1,2 @@
1
- import{__rest as e}from"../_virtual/_tslib.js";import{jsx as n,Fragment as i,jsxs as r}from"react/jsx-runtime";import{ChevronUpIcon as t}from"@lifesg/react-icons/chevron-up";import l from"clsx";import{useState as a,useRef as s,useEffect as o}from"react";import{Menu as c}from"../menu/menu.js";import{ClickableIcon as d}from"../shared/clickable-icon/clickable-icon.js";import"../util/calendar-helper.js";import"../external/dayjs/dayjs.min.js";import{useId as m}from"../util/simple-id-generator.js";import"../util/string-helper.js";import"@react-aria/live-announcer";import{Menu as u}from"./menu.js";import{mobileWrapper as p,wrapper as h,wrapperAlignLeft as b,link as v,linkSelected as f,linkItem as g,linkItemHiddenBranding as j,linkWeightRegular as N,linkWeightSemibold as k,linkWeightBold as x,linkLabel as I,linkButton as $,chevronIcon as C,chevronIconDesktop as y,chevronIconSelected as M,subMenuExpanded as O,linkIndicator as _,linkIndicatorSelected as L,linkIconContainer as P,expandCollapseButton as w}from"./navbar-items.styles.js";const E=({items:E,selectedId:D,mobile:T=!1,hideNavBranding:A,hideLinkIndicator:B=!1,onItemClick:F})=>{const[H,S]=a(null),q=s(null),z=m(),G=e=>{var n;return!!(null===(n=e.subMenu)||void 0===n?void 0:n.some((e=>e.id===D)))},J=T?E.findIndex((e=>"component"!==e.itemType&&G(e))):-1,K=J<0?null:J;o((()=>{T&&S(K)}),[T,K]),o((()=>{if(T)return;const e=e=>{q.current&&!q.current.contains(e.target)&&S(null)};return document.addEventListener("click",e,!0),()=>{document.removeEventListener("click",e,!0)}}),[T]);const Q=(e,n)=>i=>{i.stopPropagation(),T&&S((i=>{var r;return(null===(r=e.subMenu)||void 0===r?void 0:r.length)&&i!==n?n:null})),F(i,e)},R=(e,n)=>{e.stopPropagation(),F(e,n)},U=(e,i)=>n(c.Content,{id:i,children:n(c.Section,{showDivider:!1,children:e.map(((e,i)=>n(c.Link,{href:e.href,children:e.children},`${e.id}-${i}`)))})}),V=e=>n(u,{items:e,selectedId:D,onItemClick:R}),W=(a,s)=>{const{children:o,options:m,subMenu:u}=a,p=e(a,["children","options","subMenu"]),h=!!(null==u?void 0:u.length),b=(e=>e.id===D||G(e))(a),F=!T&&h&&H===s,q=T&&h&&H===s,J=F||q,K=T||null===H?b:H===s,R=!B&&K,W=T?`link__mobile-${s+1}`:`link__${s+1}`,X=()=>R?n("div",{"data-testid":`${W}-indicator`,className:l(_,K&&L)}):null,Y=l(v,(e=>{switch(e){case"bold":return x;case"semibold":return k;default:return N}})(K?T?"bold":"semibold":"regular"),K&&f);return n("li",{className:l(g,A&&j),children:h?(e=>{const v=`navbar-submenu-${z}-${a.id}`;return T?r(i,{children:[r("a",Object.assign({"data-testid":W,className:Y},p,{"aria-current":b?"page":void 0,"aria-haspopup":"menu","aria-expanded":J,onClick:Q(a,s)},m,{children:[n("div",{className:I,children:o}),X(),T&&h?n("div",{className:P,children:n(d,{"data-testid":`${W}-expand-collapse-button`,className:l(w,q&&O),focusHighlight:!1,focusOutline:"browser","aria-label":q?"Collapse":"Expand",children:n(t,{className:l(C,K&&M)})})}):null]})),q&&V(u)]}):n(c,{position:e?"bottom-end":"bottom",customOffset:0,menuContent:U(u,v),triggerOnFocus:!0,isModal:!1,onPopoverAppear:()=>{S(s)},onPopoverDismiss:()=>{S((e=>e===s?null:e))},children:r("button",Object.assign({type:"button",tabIndex:0,"data-testid":W,className:l(Y,$),"aria-haspopup":"menu","aria-expanded":J},m,{children:[n("div",{className:I,children:o}),X(),n(t,{className:l(C,y,K&&M,F&&O)})]}))})})(s===E.length-1):r("a",Object.assign({tabIndex:0,"data-testid":W,className:Y},p,{"aria-current":b?"page":void 0,onClick:Q(a,s)},m,{children:[n("div",{className:I,children:o}),X()]}))},s)},X=()=>E.map(((e,i)=>{var r;return"component"===e.itemType?n("li",{children:null!==(r=e.children)&&void 0!==r?r:null},i):W(e,i)}));return E&&E.length>0?n("ul",T?{ref:q,className:p,children:X()}:{ref:q,className:l(h,A&&b),children:X()}):n(i,{})};export{E as NavbarItems};
1
+ import{__rest as e}from"../_virtual/_tslib.js";import{jsx as n,Fragment as i,jsxs as r}from"react/jsx-runtime";import{ChevronUpIcon as t}from"@lifesg/react-icons/chevron-up";import l from"clsx";import{useState as a,useRef as s,useEffect as o}from"react";import{Menu as c}from"../menu/menu.js";import{ClickableIcon as d}from"../shared/clickable-icon/clickable-icon.js";import"../util/calendar-helper.js";import"../external/dayjs/dayjs.min.js";import{useId as u}from"../util/simple-id-generator.js";import"../util/string-helper.js";import"@react-aria/live-announcer";import{Menu as m}from"./menu.js";import{mobileWrapper as p,wrapper as h,wrapperAlignLeft as b,link as v,linkSelected as f,linkItem as g,linkItemHiddenBranding as j,linkWeightRegular as N,linkWeightSemibold as k,linkWeightBold as x,linkLabel as C,linkButton as I,chevronIcon as M,chevronIconDesktop as $,chevronIconSelected as y,subMenuExpanded as O,linkIndicator as _,linkIndicatorSelected as L,linkIconContainer as P,expandCollapseButton as w}from"./navbar-items.styles.js";const E=({items:E,selectedId:D,mobile:T=!1,hideNavBranding:z,hideLinkIndicator:A=!1,onItemClick:B})=>{const[F,H]=a(null),R=s(null),S=u(),q=e=>{var n;return!!(null===(n=e.subMenu)||void 0===n?void 0:n.some((e=>e.id===D)))},G=T?E.findIndex((e=>"component"!==e.itemType&&q(e))):-1,J=G<0?null:G;o((()=>{T&&H(J)}),[T,J]),o((()=>{if(T)return;const e=e=>{R.current&&!R.current.contains(e.target)&&H(null)};return document.addEventListener("click",e,!0),()=>{document.removeEventListener("click",e,!0)}}),[T]);const K=(e,n)=>i=>{i.stopPropagation(),T&&H((i=>{var r;return(null===(r=e.subMenu)||void 0===r?void 0:r.length)&&i!==n?n:null})),B(i,e)},Q=(e,n)=>{e.stopPropagation(),B(e,n)},U=(e,i,r)=>n(c.Content,{id:i,children:n(c.Section,{showDivider:!1,columns:r,children:e.map(((e,i)=>n(c.Link,{href:e.href,children:e.children},`${e.id}-${i}`)))})}),V=e=>n(m,{items:e,selectedId:D,onItemClick:Q}),W=(a,s)=>{const{children:o,options:u,subMenu:m,subMenuColumns:p}=a,h=e(a,["children","options","subMenu","subMenuColumns"]),b=!!(null==m?void 0:m.length),B=(e=>e.id===D||q(e))(a),R=!T&&b&&F===s,G=T&&b&&F===s,J=R||G,Q=T||null===F?B:F===s,W=!A&&Q,X=T?`link__mobile-${s+1}`:`link__${s+1}`,Y=()=>W?n("div",{"data-testid":`${X}-indicator`,className:l(_,Q&&L)}):null,Z=l(v,(e=>{switch(e){case"bold":return x;case"semibold":return k;default:return N}})(Q?T?"bold":"semibold":"regular"),Q&&f);return n("li",{className:l(g,z&&j),children:b?(e=>{const v=`navbar-submenu-${S}-${a.id}`;return T?r(i,{children:[r("a",Object.assign({"data-testid":X,className:Z},h,{"aria-current":B?"page":void 0,"aria-haspopup":"menu","aria-expanded":J,onClick:K(a,s)},u,{children:[n("div",{className:C,children:o}),Y(),T&&b?n("div",{className:P,children:n(d,{"data-testid":`${X}-expand-collapse-button`,className:l(w,G&&O),focusHighlight:!1,focusOutline:"browser","aria-label":G?"Collapse":"Expand",children:n(t,{className:l(M,Q&&y)})})}):null]})),G&&V(m)]}):n(c,{position:e?"bottom-end":"bottom",customOffset:0,menuContent:U(m,v,p),enableResize:!0,triggerOnFocus:!0,isModal:!1,onPopoverAppear:()=>{H(s)},onPopoverDismiss:()=>{H((e=>e===s?null:e))},children:r("button",Object.assign({type:"button",tabIndex:0,"data-testid":X,className:l(Z,I),"aria-haspopup":"menu","aria-expanded":J},u,{children:[n("div",{className:C,children:o}),Y(),n(t,{className:l(M,$,Q&&y,R&&O)})]}))})})(s===E.length-1):r("a",Object.assign({tabIndex:0,"data-testid":X,className:Z},h,{"aria-current":B?"page":void 0,onClick:K(a,s)},u,{children:[n("div",{className:C,children:o}),Y()]}))},s)},X=()=>E.map(((e,i)=>{var r;return"component"===e.itemType?n("li",{children:null!==(r=e.children)&&void 0!==r?r:null},i):W(e,i)}));return E&&E.length>0?n("ul",T?{ref:R,className:p,children:X()}:{ref:R,className:l(h,z&&b),children:X()}):n(i,{})};export{E as NavbarItems};
2
2
  //# sourceMappingURL=navbar-items.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"navbar-items.js","sources":["../../src/navbar/navbar-items.tsx"],"sourcesContent":["import { ChevronUpIcon } from \"@lifesg/react-icons/chevron-up\";\nimport clsx from \"clsx\";\nimport type React from \"react\";\nimport { useEffect, useRef, useState } from \"react\";\n\nimport { Menu as DesktopMenu } from \"../menu\";\nimport { ClickableIcon } from \"../shared/clickable-icon\";\nimport type { TypographyWeight } from \"../typography\";\nimport { useId } from \"../util\";\nimport { Menu as MobileMenu } from \"./menu\";\nimport * as styles from \"./navbar-items.styles\";\nimport type {\n NavItemCommonProps,\n NavItemLinkProps,\n NavItemProps,\n} from \"./types\";\n\nconst getLinkWeightClass = (weight: TypographyWeight) => {\n switch (weight) {\n case \"bold\":\n return styles.linkWeightBold;\n case \"semibold\":\n return styles.linkWeightSemibold;\n case \"regular\":\n default:\n return styles.linkWeightRegular;\n }\n};\n\ninterface Props<T> {\n items: NavItemProps<T>[];\n selectedId?: string | undefined;\n /** toggle for mobile or desktop view */\n mobile?: boolean | undefined;\n hideNavBranding?: boolean | undefined;\n /** hide the selected LinkIndicator */\n hideLinkIndicator?: boolean | undefined;\n onItemClick: (\n event: React.MouseEvent<HTMLAnchorElement>,\n item: NavItemProps<T> | NavItemCommonProps<T>\n ) => void;\n}\n\nexport const NavbarItems = <T,>({\n items,\n selectedId,\n mobile = false,\n hideNavBranding,\n hideLinkIndicator = false,\n onItemClick,\n}: Props<T>): JSX.Element => {\n // =============================================================================\n // CONST, STATE, REFS\n // =============================================================================\n const [selectedIndex, setSelectedIndex] = useState<number | null>(null);\n const listRef = useRef<HTMLUListElement>(null);\n const instanceId = useId();\n\n // =============================================================================\n // HELPERS\n // =============================================================================\n const hasSelectedSubMenuItem = (item: NavItemLinkProps<T>): boolean =>\n !!item.subMenu?.some((subItem) => subItem.id === selectedId);\n\n const checkSelected = (item: NavItemLinkProps<T>): boolean =>\n item.id === selectedId || hasSelectedSubMenuItem(item);\n\n const itemIndexWithSelectedSubItem = mobile\n ? items.findIndex(\n (item) =>\n item.itemType !== \"component\" &&\n hasSelectedSubMenuItem(item as NavItemLinkProps<T>)\n )\n : -1;\n const initialExpandedItemIndex =\n itemIndexWithSelectedSubItem < 0 ? null : itemIndexWithSelectedSubItem;\n\n // =========================================================================\n // EFFECTS\n // =========================================================================\n\n useEffect(() => {\n if (!mobile) return;\n\n setSelectedIndex(initialExpandedItemIndex);\n }, [mobile, initialExpandedItemIndex]);\n\n useEffect(() => {\n if (mobile) return;\n\n const handleClickOutside = (event: MouseEvent) => {\n if (\n listRef.current &&\n !listRef.current.contains(event.target as Node)\n ) {\n setSelectedIndex(null);\n }\n };\n document.addEventListener(\"click\", handleClickOutside, true);\n return () => {\n document.removeEventListener(\"click\", handleClickOutside, true);\n };\n }, [mobile]);\n\n // =============================================================================\n // EVENT HANDLERS\n // =============================================================================\n const handleLinkClick = (item: NavItemLinkProps<T>, index: number) => {\n return (event: React.MouseEvent<HTMLAnchorElement>) => {\n event.stopPropagation();\n\n // mobile expands inline when link has submenu\n if (mobile) {\n setSelectedIndex((prev) =>\n item.subMenu?.length && prev !== index ? index : null\n );\n }\n\n onItemClick(event, item);\n };\n };\n\n const handleMobileSubLinkClick = (\n event: React.MouseEvent<HTMLAnchorElement>,\n item: NavItemCommonProps<T>\n ) => {\n event.stopPropagation();\n onItemClick(event, item);\n };\n\n // =============================================================================\n // RENDER FUNCTIONS\n // =============================================================================\n const renderDesktopSubMenu = (\n subMenu: NavItemCommonProps<T>[],\n subMenuId: string\n ) => (\n <DesktopMenu.Content id={subMenuId}>\n <DesktopMenu.Section showDivider={false}>\n {subMenu.map((item, subIndex) => (\n <DesktopMenu.Link\n key={`${item.id}-${subIndex}`}\n href={item.href}\n >\n {item.children}\n </DesktopMenu.Link>\n ))}\n </DesktopMenu.Section>\n </DesktopMenu.Content>\n );\n\n const renderMobileSubMenu = (subMenu: NavItemCommonProps<T>[]) => (\n <MobileMenu\n items={subMenu}\n selectedId={selectedId}\n onItemClick={handleMobileSubLinkClick}\n />\n );\n\n const renderLinkItem = (item: NavItemLinkProps<T>, index: number) => {\n const { children, options, subMenu, ...otherItemAttrs } = item;\n\n const hasSubMenu = !!subMenu?.length;\n\n const isRouteSelected = checkSelected(item);\n\n // desktop popover open state\n const isDesktopExpanded =\n !mobile && hasSubMenu && selectedIndex === index;\n\n // mobile inline expanded state\n const isMobileExpanded =\n mobile && hasSubMenu && selectedIndex === index;\n\n const isExpanded = isDesktopExpanded || isMobileExpanded;\n\n const selected =\n !mobile && selectedIndex !== null\n ? selectedIndex === index\n : isRouteSelected;\n\n const showIndicator = !hideLinkIndicator && selected;\n\n const textWeight: TypographyWeight = selected\n ? mobile\n ? \"bold\"\n : \"semibold\"\n : \"regular\";\n\n const testId = mobile\n ? `link__mobile-${index + 1}`\n : `link__${index + 1}`;\n\n const renderIndicator = () =>\n showIndicator ? (\n <div\n data-testid={`${testId}-indicator`}\n className={clsx(\n styles.linkIndicator,\n selected && styles.linkIndicatorSelected\n )}\n />\n ) : null;\n\n const renderMobileChevron = () =>\n mobile && hasSubMenu ? (\n <div className={styles.linkIconContainer}>\n <ClickableIcon\n data-testid={`${testId}-expand-collapse-button`}\n className={clsx(\n styles.expandCollapseButton,\n isMobileExpanded && styles.subMenuExpanded\n )}\n focusHighlight={false}\n focusOutline=\"browser\"\n aria-label={isMobileExpanded ? \"Collapse\" : \"Expand\"}\n >\n <ChevronUpIcon\n className={clsx(\n styles.chevronIcon,\n selected && styles.chevronIconSelected\n )}\n />\n </ClickableIcon>\n </div>\n ) : null;\n\n const linkClassName = clsx(\n styles.link,\n getLinkWeightClass(textWeight),\n selected && styles.linkSelected\n );\n\n const renderLink = () => (\n <a\n tabIndex={0}\n data-testid={testId}\n className={linkClassName}\n {...otherItemAttrs}\n aria-current={isRouteSelected ? \"page\" : undefined}\n onClick={handleLinkClick(item, index)}\n {...options}\n >\n <div className={styles.linkLabel}>{children}</div>\n {renderIndicator()}\n </a>\n );\n\n const renderLinkWithSubmenu = (isLastItem: boolean) => {\n const subMenuId = `navbar-submenu-${instanceId}-${item.id}`;\n\n if (mobile) {\n return (\n <>\n <a\n data-testid={testId}\n className={linkClassName}\n {...otherItemAttrs}\n aria-current={isRouteSelected ? \"page\" : undefined}\n aria-haspopup=\"menu\"\n aria-expanded={isExpanded}\n onClick={handleLinkClick(item, index)}\n {...options}\n >\n <div className={styles.linkLabel}>{children}</div>\n {renderIndicator()}\n {renderMobileChevron()}\n </a>\n\n {isMobileExpanded && renderMobileSubMenu(subMenu!)}\n </>\n );\n }\n\n return (\n <DesktopMenu\n position={isLastItem ? \"bottom-end\" : \"bottom\"}\n customOffset={0}\n menuContent={renderDesktopSubMenu(subMenu!, subMenuId)}\n triggerOnFocus\n isModal={false}\n onPopoverAppear={() => {\n setSelectedIndex(index);\n }}\n onPopoverDismiss={() => {\n setSelectedIndex((prev) =>\n prev === index ? null : prev\n );\n }}\n >\n <button\n type=\"button\"\n tabIndex={0}\n data-testid={testId}\n className={clsx(linkClassName, styles.linkButton)}\n aria-haspopup=\"menu\"\n aria-expanded={isExpanded}\n {...options}\n >\n <div className={styles.linkLabel}>{children}</div>\n {renderIndicator()}\n <ChevronUpIcon\n className={clsx(\n styles.chevronIcon,\n styles.chevronIconDesktop,\n selected && styles.chevronIconSelected,\n isDesktopExpanded && styles.subMenuExpanded\n )}\n />\n </button>\n </DesktopMenu>\n );\n };\n\n return (\n <li\n key={index}\n className={clsx(\n styles.linkItem,\n hideNavBranding && styles.linkItemHiddenBranding\n )}\n >\n {hasSubMenu\n ? renderLinkWithSubmenu(index === items.length - 1)\n : renderLink()}\n </li>\n );\n };\n\n const renderItems = () =>\n items.map((item, index) => {\n switch (item.itemType) {\n case \"component\": {\n return <li key={index}>{item.children ?? null}</li>;\n }\n case \"link\":\n default: {\n return renderLinkItem(item as NavItemLinkProps<T>, index);\n }\n }\n });\n\n if (items && items.length > 0) {\n return mobile ? (\n <ul ref={listRef} className={styles.mobileWrapper}>\n {renderItems()}\n </ul>\n ) : (\n <ul\n ref={listRef}\n className={clsx(\n styles.wrapper,\n hideNavBranding && styles.wrapperAlignLeft\n )}\n >\n {renderItems()}\n </ul>\n );\n }\n\n return <></>;\n};\n"],"names":["NavbarItems","items","selectedId","mobile","hideNavBranding","hideLinkIndicator","onItemClick","selectedIndex","setSelectedIndex","useState","listRef","useRef","instanceId","useId","hasSelectedSubMenuItem","item","_a","subMenu","some","subItem","id","itemIndexWithSelectedSubItem","findIndex","itemType","initialExpandedItemIndex","useEffect","handleClickOutside","event","current","contains","target","document","addEventListener","removeEventListener","handleLinkClick","index","stopPropagation","prev","length","handleMobileSubLinkClick","renderDesktopSubMenu","subMenuId","_jsx","DesktopMenu","Content","children","Section","showDivider","map","subIndex","Link","href","renderMobileSubMenu","MobileMenu","renderLinkItem","options","otherItemAttrs","__rest","hasSubMenu","isRouteSelected","checkSelected","isDesktopExpanded","isMobileExpanded","isExpanded","selected","showIndicator","testId","renderIndicator","className","clsx","styles.linkIndicator","styles.linkIndicatorSelected","linkClassName","styles.link","weight","styles.linkWeightBold","styles.linkWeightSemibold","styles.linkWeightRegular","getLinkWeightClass","styles.linkSelected","styles.linkItem","styles.linkItemHiddenBranding","isLastItem","_jsxs","_Fragment","Object","assign","undefined","onClick","styles.linkLabel","styles.linkIconContainer","ClickableIcon","styles.expandCollapseButton","styles.subMenuExpanded","focusHighlight","focusOutline","ChevronUpIcon","styles.chevronIcon","styles.chevronIconSelected","position","customOffset","menuContent","triggerOnFocus","isModal","onPopoverAppear","onPopoverDismiss","type","tabIndex","styles.linkButton","styles.chevronIconDesktop","renderLinkWithSubmenu","renderItems","ref","styles.mobileWrapper","styles.wrapper","styles.wrapperAlignLeft"],"mappings":"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"}
1
+ {"version":3,"file":"navbar-items.js","sources":["../../src/navbar/navbar-items.tsx"],"sourcesContent":["import { ChevronUpIcon } from \"@lifesg/react-icons/chevron-up\";\nimport clsx from \"clsx\";\nimport type React from \"react\";\nimport { useEffect, useRef, useState } from \"react\";\n\nimport { Menu as DesktopMenu } from \"../menu\";\nimport { ClickableIcon } from \"../shared/clickable-icon\";\nimport type { TypographyWeight } from \"../typography\";\nimport { useId } from \"../util\";\nimport { Menu as MobileMenu } from \"./menu\";\nimport * as styles from \"./navbar-items.styles\";\nimport type {\n NavItemCommonProps,\n NavItemLinkProps,\n NavItemProps,\n} from \"./types\";\n\nconst getLinkWeightClass = (weight: TypographyWeight) => {\n switch (weight) {\n case \"bold\":\n return styles.linkWeightBold;\n case \"semibold\":\n return styles.linkWeightSemibold;\n case \"regular\":\n default:\n return styles.linkWeightRegular;\n }\n};\n\ninterface Props<T> {\n items: NavItemProps<T>[];\n selectedId?: string | undefined;\n /** toggle for mobile or desktop view */\n mobile?: boolean | undefined;\n hideNavBranding?: boolean | undefined;\n /** hide the selected LinkIndicator */\n hideLinkIndicator?: boolean | undefined;\n onItemClick: (\n event: React.MouseEvent<HTMLAnchorElement>,\n item: NavItemProps<T> | NavItemCommonProps<T>\n ) => void;\n}\n\nexport const NavbarItems = <T,>({\n items,\n selectedId,\n mobile = false,\n hideNavBranding,\n hideLinkIndicator = false,\n onItemClick,\n}: Props<T>): JSX.Element => {\n // =============================================================================\n // CONST, STATE, REFS\n // =============================================================================\n const [selectedIndex, setSelectedIndex] = useState<number | null>(null);\n const listRef = useRef<HTMLUListElement>(null);\n const instanceId = useId();\n\n // =============================================================================\n // HELPERS\n // =============================================================================\n const hasSelectedSubMenuItem = (item: NavItemLinkProps<T>): boolean =>\n !!item.subMenu?.some((subItem) => subItem.id === selectedId);\n\n const checkSelected = (item: NavItemLinkProps<T>): boolean =>\n item.id === selectedId || hasSelectedSubMenuItem(item);\n\n const itemIndexWithSelectedSubItem = mobile\n ? items.findIndex(\n (item) =>\n item.itemType !== \"component\" &&\n hasSelectedSubMenuItem(item as NavItemLinkProps<T>)\n )\n : -1;\n const initialExpandedItemIndex =\n itemIndexWithSelectedSubItem < 0 ? null : itemIndexWithSelectedSubItem;\n\n // =========================================================================\n // EFFECTS\n // =========================================================================\n\n useEffect(() => {\n if (!mobile) return;\n\n setSelectedIndex(initialExpandedItemIndex);\n }, [mobile, initialExpandedItemIndex]);\n\n useEffect(() => {\n if (mobile) return;\n\n const handleClickOutside = (event: MouseEvent) => {\n if (\n listRef.current &&\n !listRef.current.contains(event.target as Node)\n ) {\n setSelectedIndex(null);\n }\n };\n document.addEventListener(\"click\", handleClickOutside, true);\n return () => {\n document.removeEventListener(\"click\", handleClickOutside, true);\n };\n }, [mobile]);\n\n // =============================================================================\n // EVENT HANDLERS\n // =============================================================================\n const handleLinkClick = (item: NavItemLinkProps<T>, index: number) => {\n return (event: React.MouseEvent<HTMLAnchorElement>) => {\n event.stopPropagation();\n\n // mobile expands inline when link has submenu\n if (mobile) {\n setSelectedIndex((prev) =>\n item.subMenu?.length && prev !== index ? index : null\n );\n }\n\n onItemClick(event, item);\n };\n };\n\n const handleMobileSubLinkClick = (\n event: React.MouseEvent<HTMLAnchorElement>,\n item: NavItemCommonProps<T>\n ) => {\n event.stopPropagation();\n onItemClick(event, item);\n };\n\n // =============================================================================\n // RENDER FUNCTIONS\n // =============================================================================\n const renderDesktopSubMenu = (\n subMenu: NavItemCommonProps<T>[],\n subMenuId: string,\n columns?: number\n ) => (\n <DesktopMenu.Content id={subMenuId}>\n <DesktopMenu.Section showDivider={false} columns={columns}>\n {subMenu.map((item, subIndex) => (\n <DesktopMenu.Link\n key={`${item.id}-${subIndex}`}\n href={item.href}\n >\n {item.children}\n </DesktopMenu.Link>\n ))}\n </DesktopMenu.Section>\n </DesktopMenu.Content>\n );\n\n const renderMobileSubMenu = (subMenu: NavItemCommonProps<T>[]) => (\n <MobileMenu\n items={subMenu}\n selectedId={selectedId}\n onItemClick={handleMobileSubLinkClick}\n />\n );\n\n const renderLinkItem = (item: NavItemLinkProps<T>, index: number) => {\n const {\n children,\n options,\n subMenu,\n subMenuColumns,\n ...otherItemAttrs\n } = item;\n\n const hasSubMenu = !!subMenu?.length;\n\n const isRouteSelected = checkSelected(item);\n\n // desktop popover open state\n const isDesktopExpanded =\n !mobile && hasSubMenu && selectedIndex === index;\n\n // mobile inline expanded state\n const isMobileExpanded =\n mobile && hasSubMenu && selectedIndex === index;\n\n const isExpanded = isDesktopExpanded || isMobileExpanded;\n\n const selected =\n !mobile && selectedIndex !== null\n ? selectedIndex === index\n : isRouteSelected;\n\n const showIndicator = !hideLinkIndicator && selected;\n\n const textWeight: TypographyWeight = selected\n ? mobile\n ? \"bold\"\n : \"semibold\"\n : \"regular\";\n\n const testId = mobile\n ? `link__mobile-${index + 1}`\n : `link__${index + 1}`;\n\n const renderIndicator = () =>\n showIndicator ? (\n <div\n data-testid={`${testId}-indicator`}\n className={clsx(\n styles.linkIndicator,\n selected && styles.linkIndicatorSelected\n )}\n />\n ) : null;\n\n const renderMobileChevron = () =>\n mobile && hasSubMenu ? (\n <div className={styles.linkIconContainer}>\n <ClickableIcon\n data-testid={`${testId}-expand-collapse-button`}\n className={clsx(\n styles.expandCollapseButton,\n isMobileExpanded && styles.subMenuExpanded\n )}\n focusHighlight={false}\n focusOutline=\"browser\"\n aria-label={isMobileExpanded ? \"Collapse\" : \"Expand\"}\n >\n <ChevronUpIcon\n className={clsx(\n styles.chevronIcon,\n selected && styles.chevronIconSelected\n )}\n />\n </ClickableIcon>\n </div>\n ) : null;\n\n const linkClassName = clsx(\n styles.link,\n getLinkWeightClass(textWeight),\n selected && styles.linkSelected\n );\n\n const renderLink = () => (\n <a\n tabIndex={0}\n data-testid={testId}\n className={linkClassName}\n {...otherItemAttrs}\n aria-current={isRouteSelected ? \"page\" : undefined}\n onClick={handleLinkClick(item, index)}\n {...options}\n >\n <div className={styles.linkLabel}>{children}</div>\n {renderIndicator()}\n </a>\n );\n\n const renderLinkWithSubmenu = (isLastItem: boolean) => {\n const subMenuId = `navbar-submenu-${instanceId}-${item.id}`;\n\n if (mobile) {\n return (\n <>\n <a\n data-testid={testId}\n className={linkClassName}\n {...otherItemAttrs}\n aria-current={isRouteSelected ? \"page\" : undefined}\n aria-haspopup=\"menu\"\n aria-expanded={isExpanded}\n onClick={handleLinkClick(item, index)}\n {...options}\n >\n <div className={styles.linkLabel}>{children}</div>\n {renderIndicator()}\n {renderMobileChevron()}\n </a>\n\n {isMobileExpanded && renderMobileSubMenu(subMenu!)}\n </>\n );\n }\n\n return (\n <DesktopMenu\n position={isLastItem ? \"bottom-end\" : \"bottom\"}\n customOffset={0}\n menuContent={renderDesktopSubMenu(\n subMenu!,\n subMenuId,\n subMenuColumns\n )}\n enableResize\n triggerOnFocus\n isModal={false}\n onPopoverAppear={() => {\n setSelectedIndex(index);\n }}\n onPopoverDismiss={() => {\n setSelectedIndex((prev) =>\n prev === index ? null : prev\n );\n }}\n >\n <button\n type=\"button\"\n tabIndex={0}\n data-testid={testId}\n className={clsx(linkClassName, styles.linkButton)}\n aria-haspopup=\"menu\"\n aria-expanded={isExpanded}\n {...options}\n >\n <div className={styles.linkLabel}>{children}</div>\n {renderIndicator()}\n <ChevronUpIcon\n className={clsx(\n styles.chevronIcon,\n styles.chevronIconDesktop,\n selected && styles.chevronIconSelected,\n isDesktopExpanded && styles.subMenuExpanded\n )}\n />\n </button>\n </DesktopMenu>\n );\n };\n\n return (\n <li\n key={index}\n className={clsx(\n styles.linkItem,\n hideNavBranding && styles.linkItemHiddenBranding\n )}\n >\n {hasSubMenu\n ? renderLinkWithSubmenu(index === items.length - 1)\n : renderLink()}\n </li>\n );\n };\n\n const renderItems = () =>\n items.map((item, index) => {\n switch (item.itemType) {\n case \"component\": {\n return <li key={index}>{item.children ?? null}</li>;\n }\n case \"link\":\n default: {\n return renderLinkItem(item as NavItemLinkProps<T>, index);\n }\n }\n });\n\n if (items && items.length > 0) {\n return mobile ? (\n <ul ref={listRef} className={styles.mobileWrapper}>\n {renderItems()}\n </ul>\n ) : (\n <ul\n ref={listRef}\n className={clsx(\n styles.wrapper,\n hideNavBranding && styles.wrapperAlignLeft\n )}\n >\n {renderItems()}\n </ul>\n );\n }\n\n return <></>;\n};\n"],"names":["NavbarItems","items","selectedId","mobile","hideNavBranding","hideLinkIndicator","onItemClick","selectedIndex","setSelectedIndex","useState","listRef","useRef","instanceId","useId","hasSelectedSubMenuItem","item","_a","subMenu","some","subItem","id","itemIndexWithSelectedSubItem","findIndex","itemType","initialExpandedItemIndex","useEffect","handleClickOutside","event","current","contains","target","document","addEventListener","removeEventListener","handleLinkClick","index","stopPropagation","prev","length","handleMobileSubLinkClick","renderDesktopSubMenu","subMenuId","columns","_jsx","DesktopMenu","Content","children","Section","showDivider","map","subIndex","Link","href","renderMobileSubMenu","MobileMenu","renderLinkItem","options","subMenuColumns","otherItemAttrs","__rest","hasSubMenu","isRouteSelected","checkSelected","isDesktopExpanded","isMobileExpanded","isExpanded","selected","showIndicator","testId","renderIndicator","className","clsx","styles.linkIndicator","styles.linkIndicatorSelected","linkClassName","styles.link","weight","styles.linkWeightBold","styles.linkWeightSemibold","styles.linkWeightRegular","getLinkWeightClass","styles.linkSelected","styles.linkItem","styles.linkItemHiddenBranding","isLastItem","_jsxs","_Fragment","Object","assign","undefined","onClick","styles.linkLabel","styles.linkIconContainer","ClickableIcon","styles.expandCollapseButton","styles.subMenuExpanded","focusHighlight","focusOutline","ChevronUpIcon","styles.chevronIcon","styles.chevronIconSelected","position","customOffset","menuContent","enableResize","triggerOnFocus","isModal","onPopoverAppear","onPopoverDismiss","type","tabIndex","styles.linkButton","styles.chevronIconDesktop","renderLinkWithSubmenu","renderItems","ref","styles.mobileWrapper","styles.wrapper","styles.wrapperAlignLeft"],"mappings":"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"}
package/navbar/types.d.ts CHANGED
@@ -6,6 +6,15 @@ import type { TypographyLinkProps } from "../typography";
6
6
  export interface NavItemLinkProps<T> extends NavItemCommonProps<T> {
7
7
  itemType?: "link";
8
8
  subMenu?: NavItemCommonProps<T>[] | undefined;
9
+ /**
10
+ * Renders `subMenu` as a multi-column layout on desktop. Items flow
11
+ * vertically (top-to-bottom) within each column before wrapping to the
12
+ * next. Has no effect on the mobile drawer, which always renders `subMenu`
13
+ * as an expandable vertical list.
14
+ *
15
+ * @minimum 1
16
+ */
17
+ subMenuColumns?: number | undefined;
9
18
  }
10
19
  /**
11
20
  * Props for a custom component slot navigation item.
@@ -1,2 +1,2 @@
1
- import{jsx as t}from"react/jsx-runtime";import r from"../external/dompurify/dist/purify.es.js";import e from"react";import{NBComponent as n,NotificationBanner as o}from"./notification-banner.js";const i=i=>e.forwardRef(((e,s)=>t(n,Object.assign({forwardedRef:s},e,{children:i.length>0?i.map(((e,n)=>{if("text"===e.type){const o=e.otherAttributes,i=r.sanitize(e.content);return t("p",Object.assign({},o,{dangerouslySetInnerHTML:{__html:i}}),n)}{const r=e.otherAttributes;return t(o.Link,Object.assign({},r,{children:e.content}),n)}})):(console.error("[NotificationBannerHOC] Empty data passed"),null)}))));export{i as withNotificationBanner};
1
+ import{__rest as t}from"../_virtual/_tslib.js";import{jsx as r}from"react/jsx-runtime";import e from"../external/dompurify/dist/purify.es.js";import n from"react";import{NBComponent as i,NotificationBanner as o}from"./notification-banner.js";const s=s=>n.forwardRef(((n,a)=>r(i,Object.assign({forwardedRef:a},n,{children:s.length>0?s.map(((n,i)=>{var s;if("text"===n.type){const t=n.otherAttributes,o=e.isSupported?e.sanitize(n.content):"";return r("p",Object.assign({},t,{dangerouslySetInnerHTML:{__html:o}}),i)}{const a=function(r){const{href:n}=r,i=t(r,["href"]);return"string"==typeof n&&e.isValidAttribute("a","href",n)?r:i}(null!==(s=n.otherAttributes)&&void 0!==s?s:{});return r(o.Link,Object.assign({},a,{children:n.content}),i)}})):(console.error("[NotificationBannerHOC] Empty data passed"),null)}))));export{s as withNotificationBanner};
2
2
  //# sourceMappingURL=notification-banner-hoc.js.map
@@ -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\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":["withNotificationBanner","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":"mMAiBO,MAAMA,EACTC,GAmDOC,EAAMC,YAjDa,CACtBC,EACAC,IAyCIC,EAACC,EAAWC,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,EAAUC,SAC/BN,EAAUO,SAEd,OACIf,EAAA,IAAAE,OAAAC,OAAA,GAEQQ,EAAe,CACnBK,wBAAyB,CACrBC,OAAQL,KAHPH,EAOjB,CAAO,CACH,MAAME,EACFH,EAAUG,gBACd,OACIX,EAACkB,EAAmBC,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\nfunction sanitizeLinkAttributes(\n attrs: ContentLinkAttributes\n): ContentLinkAttributes {\n const { href, ...rest } = attrs;\n\n if (\n typeof href !== \"string\" ||\n !DOMPurify.isValidAttribute(\"a\", \"href\", href)\n ) {\n return rest;\n }\n\n return attrs;\n}\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.isSupported\n ? DOMPurify.sanitize(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 = sanitizeLinkAttributes(\n (attribute.otherAttributes ??\n {}) as ContentLinkAttributes\n );\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":["withNotificationBanner","data","React","forwardRef","props","ref","_jsx","NBComponent","Object","assign","forwardedRef","children","length","map","attribute","index","type","otherAttributes","sanitizedContent","DOMPurify","isSupported","sanitize","content","dangerouslySetInnerHTML","__html","attrs","href","rest","__rest","isValidAttribute","sanitizeLinkAttributes","_a","NotificationBanner","Link","console","error"],"mappings":"kPAgCO,MAAMA,EACTC,GAqDOC,EAAMC,YAnDa,CACtBC,EACAC,IA2CIC,EAACC,EAAWC,OAAAC,OAAA,CAACC,aAAcL,GAASD,EAAK,CAAAO,SAxCrCV,EAAKW,OAAS,EACPX,EAAKY,KAAI,CAACC,EAAWC,WACxB,GAAuB,SAAnBD,EAAUE,KAAiB,CAC3B,MAAMC,EACFH,EAAUG,gBAERC,EAAmBC,EAAUC,YAC7BD,EAAUE,SAASP,EAAUQ,SAC7B,GACN,OACIhB,EAAA,IAAAE,OAAAC,OAAA,GAEQQ,EAAe,CACnBM,wBAAyB,CACrBC,OAAQN,KAHPH,EAOjB,CAAO,CACH,MAAME,EAhD9B,SACIQ,GAEA,MAAMC,KAAEA,GAAkBD,EAATE,EAAIC,EAAKH,EAApB,CAAA,SAEN,MACoB,iBAATC,GACNP,EAAUU,iBAAiB,IAAK,OAAQH,GAKtCD,EAHIE,CAIf,CAmCgDG,CACM,QAAzBC,EAAAjB,EAAUG,uBAAe,IAAAc,EAAAA,EACtB,CAAA,GAER,OACIzB,EAAC0B,EAAmBC,KAAIzB,OAAAC,OAAA,CAAA,EAEhBQ,EAAe,CAAAN,SAElBG,EAAUQ,UAHNP,EAMjB,MAIRmB,QAAQC,MAAM,6CACP"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lifesg/react-design-system",
3
- "version": "4.0.0-alpha.12",
3
+ "version": "4.0.0-alpha.14",
4
4
  "description": "A component design system for LifeSG web apps",
5
5
  "keywords": [
6
6
  "design-system"
@@ -18,7 +18,7 @@
18
18
  "module": "./index.js",
19
19
  "types": "./index.d.ts",
20
20
  "bin": {
21
- "lifesg-react-design-system": "./codemods/run-codemod.js"
21
+ "lifesg-react-design-system": "./scripts/cli.js"
22
22
  },
23
23
  "exports": {
24
24
  ".": {
@@ -28,8 +28,7 @@
28
28
  "default": "./index.js"
29
29
  },
30
30
  "./theme/styles/*.css": {
31
- "import": "./theme/styles/*.css",
32
- "require": "./theme/styles/*.css"
31
+ "default": "./theme/styles/*.css"
33
32
  },
34
33
  "./accordion": {
35
34
  "types": "./accordion/index.d.ts",
@@ -1,2 +1,2 @@
1
- import{jsxs as e,jsx as i}from"react/jsx-runtime";import{Chevron2LeftIcon as a}from"@lifesg/react-icons/chevron-2-left";import{Chevron2RightIcon as r}from"@lifesg/react-icons/chevron-2-right";import{ChevronLeftIcon as o}from"@lifesg/react-icons/chevron-left";import{ChevronLineLeftIcon as t}from"@lifesg/react-icons/chevron-line-left";import{ChevronLineRightIcon as s}from"@lifesg/react-icons/chevron-line-right";import{ChevronRightIcon as l}from"@lifesg/react-icons/chevron-right";import{EllipsisHorizontalIcon as n}from"@lifesg/react-icons/ellipsis-horizontal";import c from"clsx";import m,{useState as d,useEffect as p}from"react";import{Input as h}from"../input/input.js";import{InputSelect as u}from"../input-select/input-select.js";import{VisuallyHidden as g}from"../shared/accessibility/index.js";import{ClickableIcon as f}from"../shared/clickable-icon/clickable-icon.js";import"../theme/theme-provider/index.js";import"../theme/theme-provider/context.js";import"../theme/tokens/border.js";import"../theme/tokens/colour.js";import"../theme/tokens/font.js";import"../theme/tokens/media-query.js";import"../util/calendar-helper.js";import"../external/dayjs/dayjs.min.js";import{useId as v}from"../util/simple-id-generator.js";import"../util/string-helper.js";import"@react-aria/live-announcer";import{useIsMounted as b}from"../util/use-mount.js";import{useMaxWidthMediaQuery as N}from"../theme/utils/use-media-query.js";import{Typography as j}from"../typography/index.js";import{paginationList as x,paginationMenu as y,iconButton as k,iconButtonNavigation as C,inputSelectWrapper as M,paginationWrapper as O,paginationMobileInput as w,inputView as $,labelDivider as P,label as S,pageItem as z,pageItemSelected as B,ellipsisContainer as F,hover as H}from"./pagination.styles.js";const L=m.forwardRef((({id:m,"data-testid":L,className:I,pageSize:q=10,totalItems:A,activePage:D,pageSizeOptions:R=E,showFirstAndLastNav:V,showPageSizeChanger:G=!1,onPageChange:J,onPageSizeChange:K},Q)=>{const T=b(),U=N("sm"),[W,X]=d(!1),[Y,Z]=d(!1),[_,ee]=d(""),[ie,ae]=d(R[0]),[re,oe]=d(!U&&G&&ie?ie.value:q),te=`${v()}-pagination`,se=Math.ceil(A/re),le=1===D,ne=D===se,ce=D>1?()=>ge(1):void 0,me=D<se?()=>ge(se):void 0,de=D>1?()=>ge(D-1):void 0,pe=D<se?()=>ge(parseInt(D.toString())+1):void 0;p((()=>{D&&he(D)}),[D]),p((()=>{oe(q),ae(R.find((e=>e.value===q)))}),[q]);const he=e=>{ee(e.toString())},ue=()=>{X(!1),Z(!1)},ge=e=>{J&&(J(e),he(e))},fe=()=>{const e=Math.min(se,D+5);ge(e),he(e),X(!0),Z(!1)},ve=()=>{const e=Math.max(1,D-5);ge(e),he(e),X(!1),Z(!0)},be=e=>{const i=e.target.value;if(void 0===i||0===i.length)ee("");else if(/^[0-9]+$/.test(i)){const e=parseInt(i.replace(/[^0-9]/g,""));he(Math.max(1,Math.min(se,e)))}else ee(i.replace(/[^0-9]/g,""))},Ne=e=>{e.preventDefault(),_&&(null==J||J(parseInt(_)))},je=()=>{X(!0)},xe=()=>{X(!1)},ye=()=>{Z(!0)},ke=()=>{Z(!1)},Ce=r=>e("div",{className:F,children:[i(f,{className:k,focusHighlight:!1,focusOutline:"browser","aria-label":"Previous 5 pages",onMouseEnter:ye,onMouseLeave:ke,onFocus:ye,onBlur:ke,onClick:ve,children:i(Y?a:n,{"aria-hidden":!0})}),Y&&i("div",{className:H,children:"Previous 5 pages"})]},r),Me=a=>e("div",{className:F,children:[i(f,{className:k,focusHighlight:!1,focusOutline:"browser","aria-label":"Next 5 pages",onMouseEnter:je,onMouseLeave:xe,onFocus:je,onBlur:xe,onClick:fe,children:i(W?r:n,{"aria-hidden":!0})}),W&&i("div",{className:H,children:"Next 5 pages"})]},a);return e("nav",{className:c(O,I),ref:Q,id:m||"pagination-wrapper","data-testid":L||"pagination","aria-labelledby":te,children:[i(g,{id:te,"aria-hidden":!0,children:"pagination"}),i("div",{className:x,children:e("div",{className:y,children:[V&&i(f,{className:c(k,C),onClick:ce,disabled:le,focusHighlight:!1,"aria-label":"First page",focusOutline:"browser",children:i(t,{"aria-hidden":!0})}),i(f,{className:c(k,C),onClick:de,disabled:le,focusHighlight:!1,"aria-label":"Previous page",focusOutline:"browser",children:i(o,{"aria-hidden":!0})}),T&&U?e("div",{className:w,children:[i("form",{onSubmit:Ne,children:i(h,{className:$,value:_,onChange:be,autoComplete:"off",type:"numeric",id:(m||"pagination")+"-input","data-testid":(L||"pagination")+"-input","aria-label":`Page ${D} of ${se}`})}),i(j.BodyBL,{className:P,children:"/"}),i(j.BodyBL,{className:S,children:se})]}):[...Array(se)].map(((e,a)=>{const r=a+1,o=se-5,t=D===r;return se<=7?i("button",{onClick:()=>ge(r),className:c(z,t&&B),"aria-label":`page ${r} of ${se}`,"aria-current":!!t&&"page",onMouseOver:ue,onFocus:ue,children:r},r):D+1>5&&2===r?Ce(r):D-1<=o&&r===se-1-1?Me(r):r<=5&&D+1<=5||r<=1||r===D||r<=D+1&&r>=D-1-1||r>o&&D-1>o||r>se-1?i("button",{onClick:()=>ge(r),className:c(z,t&&B),"aria-label":`page ${r} of ${se}`,"aria-current":!!t&&"page",onMouseOver:ue,onFocus:ue,children:r},r):null})),i(f,{className:c(k,C),onClick:pe,disabled:ne,focusHighlight:!1,"aria-label":"Next page",focusOutline:"browser",children:i(l,{"aria-hidden":!0})}),V&&i(f,{className:c(k,C),onClick:me,disabled:ne,focusHighlight:!1,"aria-label":"Last page",focusOutline:"browser",children:i(s,{"aria-hidden":!0})})]})}),G&&!U&&e("div",{className:M,children:[i(g,{id:`${te}-page-size`,children:"Items per page"}),i(u,{"aria-labelledby":`${te}-page-size`,options:R,valueExtractor:e=>e.value,listExtractor:e=>e.label,displayValueExtractor:e=>e.label,selectedOption:ie,onSelectOption:e=>{ae(e);const i=e.value,a=Math.ceil(A/i);oe(i);K&&K(D>=a?a:D,i)}})]})]})})),E=[{value:10,label:"10 per page"},{value:20,label:"20 per page"},{value:30,label:"30 per page"}];export{L as Pagination};
1
+ import{jsxs as e,jsx as a}from"react/jsx-runtime";import{Chevron2LeftIcon as i}from"@lifesg/react-icons/chevron-2-left";import{Chevron2RightIcon as r}from"@lifesg/react-icons/chevron-2-right";import{ChevronLeftIcon as o}from"@lifesg/react-icons/chevron-left";import{ChevronLineLeftIcon as t}from"@lifesg/react-icons/chevron-line-left";import{ChevronLineRightIcon as l}from"@lifesg/react-icons/chevron-line-right";import{ChevronRightIcon as s}from"@lifesg/react-icons/chevron-right";import{EllipsisHorizontalIcon as n}from"@lifesg/react-icons/ellipsis-horizontal";import c from"clsx";import m,{useState as d,useEffect as p}from"react";import{Input as u}from"../input/input.js";import{InputSelect as h}from"../input-select/input-select.js";import{VisuallyHidden as g}from"../shared/accessibility/index.js";import{ClickableIcon as f}from"../shared/clickable-icon/clickable-icon.js";import"../theme/theme-provider/index.js";import"../theme/theme-provider/context.js";import"../theme/tokens/border.js";import"../theme/tokens/colour.js";import"../theme/tokens/font.js";import"../theme/tokens/media-query.js";import"../util/calendar-helper.js";import"../external/dayjs/dayjs.min.js";import{useId as v}from"../util/simple-id-generator.js";import"../util/string-helper.js";import"@react-aria/live-announcer";import{useIsMounted as b}from"../util/use-mount.js";import{useMaxWidthMediaQuery as N}from"../theme/utils/use-media-query.js";import{Typography as j}from"../typography/index.js";import{paginationList as x,paginationMenu as y,iconButton as k,iconButtonNavigation as C,inputSelectWrapper as M,paginationWrapper as O,paginationMobileInput as w,inputView as $,labelDivider as P,label as S,pageItem as z,pageItemSelected as B,ellipsisContainer as F,hover as H}from"./pagination.styles.js";const L=m.forwardRef((({id:m,"data-testid":L,className:I,variant:q="default",pageSize:A=10,totalItems:D,activePage:R,pageSizeOptions:V=E,showFirstAndLastNav:G,showPageSizeChanger:J=!1,onPageChange:K,onPageSizeChange:Q},T)=>{const U=b(),W=N("sm"),X="default"===q?U&&W?"compact":"full":q,Y="compact"===X,Z=J&&"full"===X,[_,ee]=d(!1),[ae,ie]=d(!1),[re,oe]=d(""),[te,le]=d(A),se=((e,a)=>{var i;return null!==(i=e.find((e=>e.value===a)))&&void 0!==i?i:e[0]})(V,te),ne=`${v()}-pagination`,ce=Math.ceil(D/te),me=1===R,de=R===ce,pe=R>1?()=>be(1):void 0,ue=R<ce?()=>be(ce):void 0,he=R>1?()=>be(R-1):void 0,ge=R<ce?()=>be(parseInt(R.toString())+1):void 0;p((()=>{R&&fe(R)}),[R]),p((()=>{le(A)}),[A]);const fe=e=>{oe(e.toString())},ve=()=>{ee(!1),ie(!1)},be=e=>{K&&(K(e),fe(e))},Ne=()=>{const e=Math.min(ce,R+5);be(e),fe(e),ee(!0),ie(!1)},je=()=>{const e=Math.max(1,R-5);be(e),fe(e),ee(!1),ie(!0)},xe=e=>{const a=e.target.value;if(void 0===a||0===a.length)oe("");else if(/^[0-9]+$/.test(a)){const e=parseInt(a.replace(/[^0-9]/g,""));fe(Math.max(1,Math.min(ce,e)))}else oe(a.replace(/[^0-9]/g,""))},ye=e=>{e.preventDefault(),re&&(null==K||K(parseInt(re)))},ke=()=>{ee(!0)},Ce=()=>{ee(!1)},Me=()=>{ie(!0)},Oe=()=>{ie(!1)},we=r=>e("div",{className:F,children:[a(f,{className:k,focusHighlight:!1,focusOutline:"browser","aria-label":"Previous 5 pages",onMouseEnter:Me,onMouseLeave:Oe,onFocus:Me,onBlur:Oe,onClick:je,children:a(ae?i:n,{"aria-hidden":!0})}),ae&&a("div",{className:H,children:"Previous 5 pages"})]},r),$e=i=>e("div",{className:F,children:[a(f,{className:k,focusHighlight:!1,focusOutline:"browser","aria-label":"Next 5 pages",onMouseEnter:ke,onMouseLeave:Ce,onFocus:ke,onBlur:Ce,onClick:Ne,children:a(_?r:n,{"aria-hidden":!0})}),_&&a("div",{className:H,children:"Next 5 pages"})]},i);return e("nav",{className:c(O,I),ref:T,id:m||"pagination-wrapper","data-testid":L||"pagination","aria-labelledby":ne,children:[a(g,{id:ne,"aria-hidden":!0,children:"pagination"}),a("div",{className:x,children:e("div",{className:y,children:[G&&a(f,{className:c(k,C),onClick:pe,disabled:me,focusHighlight:!1,"aria-label":"First page",focusOutline:"browser",children:a(t,{"aria-hidden":!0})}),a(f,{className:c(k,C),onClick:he,disabled:me,focusHighlight:!1,"aria-label":"Previous page",focusOutline:"browser",children:a(o,{"aria-hidden":!0})}),Y?e("div",{className:w,children:[a("form",{onSubmit:ye,children:a(u,{className:$,value:re,onChange:xe,autoComplete:"off",type:"numeric",id:(m||"pagination")+"-input","data-testid":(L||"pagination")+"-input","aria-label":`Page ${R} of ${ce}`})}),a(j.BodyBL,{className:P,children:"/"}),a(j.BodyBL,{className:S,children:ce})]}):[...Array(ce)].map(((e,i)=>{const r=i+1,o=ce-5,t=R===r;return ce<=7?a("button",{onClick:()=>be(r),className:c(z,t&&B),"aria-label":`page ${r} of ${ce}`,"aria-current":!!t&&"page",onMouseOver:ve,onFocus:ve,children:r},r):R+1>5&&2===r?we(r):R-1<=o&&r===ce-1-1?$e(r):r<=5&&R+1<=5||r<=1||r===R||r<=R+1&&r>=R-1-1||r>o&&R-1>o||r>ce-1?a("button",{onClick:()=>be(r),className:c(z,t&&B),"aria-label":`page ${r} of ${ce}`,"aria-current":!!t&&"page",onMouseOver:ve,onFocus:ve,children:r},r):null})),a(f,{className:c(k,C),onClick:ge,disabled:de,focusHighlight:!1,"aria-label":"Next page",focusOutline:"browser",children:a(s,{"aria-hidden":!0})}),G&&a(f,{className:c(k,C),onClick:ue,disabled:de,focusHighlight:!1,"aria-label":"Last page",focusOutline:"browser",children:a(l,{"aria-hidden":!0})})]})}),Z&&e("div",{className:M,children:[a(g,{id:`${ne}-page-size`,children:"Items per page"}),a(h,{"aria-labelledby":`${ne}-page-size`,options:V,valueExtractor:e=>e.value,listExtractor:e=>e.label,displayValueExtractor:e=>e.label,selectedOption:se,onSelectOption:e=>{const a=e.value,i=Math.ceil(D/a);le(a);Q&&Q(R>=i?i:R,a)}})]})]})})),E=[{value:10,label:"10 per page"},{value:20,label:"20 per page"},{value:30,label:"30 per page"}];export{L as Pagination};
2
2
  //# sourceMappingURL=pagination.js.map