@boostdev/design-system-components 2.7.1 → 2.11.0

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 (535) hide show
  1. package/AGENTS.md +54 -46
  2. package/README.md +34 -20
  3. package/dist/client.cjs +1317 -779
  4. package/dist/client.css +1029 -812
  5. package/dist/client.d.cts +88 -26
  6. package/dist/client.d.ts +88 -26
  7. package/dist/client.js +1278 -732
  8. package/dist/index.cjs +1317 -779
  9. package/dist/index.css +1029 -812
  10. package/dist/index.d.cts +88 -26
  11. package/dist/index.d.ts +88 -26
  12. package/dist/index.js +1278 -732
  13. package/dist/web-components/chunk-2OLVQUBU.js +193 -0
  14. package/dist/web-components/chunk-3AY2YKCM.js +223 -0
  15. package/dist/web-components/chunk-3WAV6MDN.js +212 -0
  16. package/dist/web-components/{chunk-CZBIVR4V.js → chunk-47AT5KZD.js} +88 -16
  17. package/dist/web-components/chunk-4A2YYTYN.js +93 -0
  18. package/dist/web-components/{chunk-Q4T5BJT6.js → chunk-62NK3ZSC.js} +18 -3
  19. package/dist/web-components/chunk-66M6ETWD.js +77 -0
  20. package/dist/web-components/{chunk-NCPQ7AF3.js → chunk-6G22I2CK.js} +18 -3
  21. package/dist/web-components/{chunk-QDST57JC.js → chunk-7ZOJ7N4E.js} +14 -4
  22. package/dist/web-components/{chunk-5R6IFELV.js → chunk-AIBOHNDU.js} +11 -1
  23. package/dist/web-components/{chunk-ITHLKR7Q.js → chunk-AP4RDUL2.js} +16 -5
  24. package/dist/web-components/{chunk-QWPACK5L.js → chunk-BPYKZVDK.js} +11 -1
  25. package/dist/web-components/{chunk-YLVTEY23.js → chunk-BTCMJQKB.js} +53 -21
  26. package/dist/web-components/chunk-CUKQ2L5B.js +245 -0
  27. package/dist/web-components/chunk-DIZDCL7Z.js +14 -0
  28. package/dist/web-components/{chunk-PC3IOQAH.js → chunk-DV5T43ZC.js} +27 -7
  29. package/dist/web-components/{chunk-2QA62WCQ.js → chunk-EF7IVYTY.js} +10 -0
  30. package/dist/web-components/{chunk-L3XHOMN6.js → chunk-F3ZDNHZZ.js} +26 -1
  31. package/dist/web-components/chunk-FEDABOR5.js +248 -0
  32. package/dist/web-components/{chunk-6I2DBFQ7.js → chunk-HGFCJXOQ.js} +36 -5
  33. package/dist/web-components/{chunk-SOQQ7RVJ.js → chunk-IPGHUCJT.js} +23 -8
  34. package/dist/web-components/chunk-ITD2MV5K.js +392 -0
  35. package/dist/web-components/{chunk-CM3KYZ6Z.js → chunk-JH6LQKLK.js} +78 -6
  36. package/dist/web-components/chunk-JMCXAAFK.js +120 -0
  37. package/dist/web-components/{chunk-KUI55GFB.js → chunk-JUPCZVVW.js} +50 -18
  38. package/dist/web-components/chunk-JV5QT2OU.js +146 -0
  39. package/dist/web-components/{chunk-3GFWLSLS.js → chunk-KA3VPKMY.js} +29 -6
  40. package/dist/web-components/{chunk-CR5PGUHV.js → chunk-KJGRFDFI.js} +26 -11
  41. package/dist/web-components/{chunk-PY62FTRW.js → chunk-KZPRFY5P.js} +68 -33
  42. package/dist/web-components/{chunk-X46KL5BK.js → chunk-LDIPCTRN.js} +18 -1
  43. package/dist/web-components/chunk-M3ECULRH.js +174 -0
  44. package/dist/web-components/chunk-NBN2ENWJ.js +90 -0
  45. package/dist/web-components/chunk-NIN3JO6Q.js +189 -0
  46. package/dist/web-components/{chunk-2FGATTGT.js → chunk-NTQ4TCUT.js} +76 -55
  47. package/dist/web-components/chunk-OY74D4X6.js +302 -0
  48. package/dist/web-components/{chunk-3S42DZ7W.js → chunk-P24JYC5V.js} +7 -0
  49. package/dist/web-components/{chunk-BKIHQYJR.js → chunk-PXPPKCLT.js} +17 -2
  50. package/dist/web-components/{chunk-TQ7IQ4GZ.js → chunk-QEF2IRID.js} +71 -29
  51. package/dist/web-components/chunk-QZAIRJ75.js +111 -0
  52. package/dist/web-components/{chunk-6I3CFC26.js → chunk-RSZ3BWBK.js} +20 -5
  53. package/dist/web-components/chunk-RVF7W653.js +101 -0
  54. package/dist/web-components/chunk-SEO2F5KJ.js +234 -0
  55. package/dist/web-components/{chunk-VMMVWLXL.js → chunk-SFZ6Q4BP.js} +10 -0
  56. package/dist/web-components/{chunk-LY62SAVN.js → chunk-SYNLFKD3.js} +12 -2
  57. package/dist/web-components/chunk-TMWXRHGF.js +192 -0
  58. package/dist/web-components/{chunk-65JXQOBA.js → chunk-U3YZE6R6.js} +51 -7
  59. package/dist/web-components/chunk-UO7ROSHD.js +424 -0
  60. package/dist/web-components/chunk-VANAKB6D.js +152 -0
  61. package/dist/web-components/{chunk-PXZWYO6Z.js → chunk-VED2DFJ6.js} +108 -29
  62. package/dist/web-components/chunk-W6H5ID2U.js +161 -0
  63. package/dist/web-components/{chunk-57TRNCWQ.js → chunk-WFVKU4GX.js} +22 -11
  64. package/dist/web-components/{chunk-OQTRTMAB.js → chunk-WIBAN7KP.js} +10 -0
  65. package/dist/web-components/chunk-XI7KRAH7.js +54 -0
  66. package/dist/web-components/{chunk-F5E3IT7G.js → chunk-XIZWAWMJ.js} +50 -11
  67. package/dist/web-components/{chunk-FXURM6D5.js → chunk-YFAXGRPR.js} +10 -0
  68. package/dist/web-components/globals.js +1 -1
  69. package/dist/web-components/index.d.ts +77 -707
  70. package/dist/web-components/index.js +339 -2066
  71. package/dist/web-components/interaction/bds-accordion-item.js +1 -1
  72. package/dist/web-components/interaction/bds-accordion.js +1 -1
  73. package/dist/web-components/interaction/bds-button.d.ts +10 -2
  74. package/dist/web-components/interaction/bds-button.js +1 -1
  75. package/dist/web-components/interaction/bds-collapsible.d.ts +7 -2
  76. package/dist/web-components/interaction/bds-collapsible.js +1 -1
  77. package/dist/web-components/interaction/bds-dialog.d.ts +11 -3
  78. package/dist/web-components/interaction/bds-dialog.js +1 -1
  79. package/dist/web-components/interaction/bds-drawer.d.ts +7 -1
  80. package/dist/web-components/interaction/bds-drawer.js +1 -1
  81. package/dist/web-components/interaction/bds-dropdown-menu-item.d.ts +51 -0
  82. package/dist/web-components/interaction/bds-dropdown-menu-item.js +7 -0
  83. package/dist/web-components/interaction/bds-dropdown-menu.d.ts +70 -0
  84. package/dist/web-components/interaction/bds-dropdown-menu.js +7 -0
  85. package/dist/web-components/interaction/bds-popover.d.ts +14 -3
  86. package/dist/web-components/interaction/bds-popover.js +1 -1
  87. package/dist/web-components/interaction/bds-skip-link.js +1 -1
  88. package/dist/web-components/interaction/bds-tab-panel.js +1 -1
  89. package/dist/web-components/interaction/bds-tab.js +1 -1
  90. package/dist/web-components/interaction/bds-tabs.d.ts +1 -0
  91. package/dist/web-components/interaction/bds-tabs.js +1 -1
  92. package/dist/web-components/interaction/bds-toast-provider.js +1 -1
  93. package/dist/web-components/interaction/bds-tooltip.d.ts +19 -3
  94. package/dist/web-components/interaction/bds-tooltip.js +1 -1
  95. package/dist/web-components/interaction/form/bds-checkbox-group.d.ts +83 -0
  96. package/dist/web-components/interaction/form/bds-checkbox-group.js +7 -0
  97. package/dist/web-components/interaction/form/bds-checkbox.d.ts +6 -0
  98. package/dist/web-components/interaction/form/bds-checkbox.js +1 -1
  99. package/dist/web-components/interaction/form/bds-combobox.d.ts +18 -0
  100. package/dist/web-components/interaction/form/bds-combobox.js +1 -1
  101. package/dist/web-components/interaction/form/bds-field-group.d.ts +89 -0
  102. package/dist/web-components/interaction/form/bds-field-group.js +7 -0
  103. package/dist/web-components/interaction/form/bds-file-input.d.ts +1 -1
  104. package/dist/web-components/interaction/form/bds-file-input.js +1 -1
  105. package/dist/web-components/interaction/form/bds-form-input.d.ts +92 -0
  106. package/dist/web-components/interaction/form/bds-form-input.js +7 -0
  107. package/dist/web-components/interaction/form/bds-number-input.d.ts +18 -1
  108. package/dist/web-components/interaction/form/bds-number-input.js +1 -1
  109. package/dist/web-components/interaction/form/bds-radio-group.d.ts +81 -0
  110. package/dist/web-components/interaction/form/bds-radio-group.js +7 -0
  111. package/dist/web-components/interaction/form/bds-radio.d.ts +34 -6
  112. package/dist/web-components/interaction/form/bds-radio.js +1 -1
  113. package/dist/web-components/interaction/form/bds-segmented-control.d.ts +4 -4
  114. package/dist/web-components/interaction/form/bds-segmented-control.js +1 -1
  115. package/dist/web-components/interaction/form/bds-select.d.ts +22 -1
  116. package/dist/web-components/interaction/form/bds-select.js +1 -1
  117. package/dist/web-components/interaction/form/bds-slider.d.ts +42 -10
  118. package/dist/web-components/interaction/form/bds-slider.js +1 -1
  119. package/dist/web-components/interaction/form/bds-switch.d.ts +20 -0
  120. package/dist/web-components/interaction/form/bds-switch.js +1 -1
  121. package/dist/web-components/interaction/form/bds-textarea.d.ts +23 -3
  122. package/dist/web-components/interaction/form/bds-textarea.js +1 -1
  123. package/dist/web-components/layout/bds-grid-item.d.ts +63 -0
  124. package/dist/web-components/layout/bds-grid-item.js +7 -0
  125. package/dist/web-components/layout/bds-grid.d.ts +108 -0
  126. package/dist/web-components/layout/bds-grid.js +7 -0
  127. package/dist/web-components/ui/bds-alert.d.ts +16 -2
  128. package/dist/web-components/ui/bds-alert.js +1 -1
  129. package/dist/web-components/ui/bds-avatar.d.ts +2 -1
  130. package/dist/web-components/ui/bds-avatar.js +1 -1
  131. package/dist/web-components/ui/bds-badge.js +1 -1
  132. package/dist/web-components/ui/bds-breadcrumb.d.ts +3 -1
  133. package/dist/web-components/ui/bds-breadcrumb.js +1 -1
  134. package/dist/web-components/ui/bds-button-container.d.ts +52 -0
  135. package/dist/web-components/ui/bds-button-container.js +7 -0
  136. package/dist/web-components/ui/bds-button-group.d.ts +21 -0
  137. package/dist/web-components/ui/bds-button-group.js +8 -0
  138. package/dist/web-components/ui/bds-calendar.d.ts +121 -0
  139. package/dist/web-components/ui/bds-calendar.js +7 -0
  140. package/dist/web-components/ui/bds-card.d.ts +12 -3
  141. package/dist/web-components/ui/bds-card.js +1 -1
  142. package/dist/web-components/ui/bds-carousel.d.ts +98 -0
  143. package/dist/web-components/ui/bds-carousel.js +7 -0
  144. package/dist/web-components/ui/bds-description-list.js +1 -1
  145. package/dist/web-components/ui/bds-icon-wrapper.d.ts +0 -9
  146. package/dist/web-components/ui/bds-icon-wrapper.js +1 -1
  147. package/dist/web-components/ui/bds-link.js +1 -1
  148. package/dist/web-components/ui/bds-loading.js +1 -1
  149. package/dist/web-components/ui/bds-notification-banner.js +1 -1
  150. package/dist/web-components/ui/bds-pagination.d.ts +47 -0
  151. package/dist/web-components/ui/bds-pagination.js +7 -0
  152. package/dist/web-components/ui/bds-progress-circle.d.ts +3 -1
  153. package/dist/web-components/ui/bds-progress-circle.js +1 -1
  154. package/dist/web-components/ui/bds-progress.d.ts +3 -1
  155. package/dist/web-components/ui/bds-progress.js +1 -1
  156. package/dist/web-components/ui/bds-rating.js +1 -1
  157. package/dist/web-components/ui/bds-section-header.d.ts +18 -4
  158. package/dist/web-components/ui/bds-section-header.js +1 -1
  159. package/dist/web-components/ui/bds-separator.js +1 -1
  160. package/dist/web-components/ui/bds-skeleton.js +1 -1
  161. package/dist/web-components/ui/bds-table.d.ts +52 -0
  162. package/dist/web-components/ui/bds-table.js +7 -0
  163. package/dist/web-components/ui/bds-typography.d.ts +1 -0
  164. package/dist/web-components/ui/bds-typography.js +1 -1
  165. package/package.json +60 -3
  166. package/src/components/interaction/Button/Button.module.css +23 -14
  167. package/src/components/interaction/Button/Button.spec.tsx +20 -0
  168. package/src/components/interaction/Button/Button.tsx +2 -2
  169. package/src/components/interaction/Command/Command.mdx +5 -2
  170. package/src/components/interaction/Command/Command.module.css +23 -7
  171. package/src/components/interaction/Command/Command.spec.tsx +35 -0
  172. package/src/components/interaction/Command/Command.tsx +15 -4
  173. package/src/components/interaction/Command/index.ts +1 -1
  174. package/src/components/interaction/Dialog/Dialog.mdx +4 -4
  175. package/src/components/interaction/Dialog/Dialog.module.css +20 -0
  176. package/src/components/interaction/Dialog/Dialog.spec.tsx +20 -0
  177. package/src/components/interaction/Dialog/Dialog.tsx +8 -3
  178. package/src/components/interaction/Dialog/index.ts +1 -0
  179. package/src/components/interaction/Drawer/Drawer.mdx +5 -2
  180. package/src/components/interaction/Drawer/Drawer.module.css +34 -3
  181. package/src/components/interaction/Drawer/Drawer.spec.tsx +67 -1
  182. package/src/components/interaction/Drawer/Drawer.tsx +30 -12
  183. package/src/components/interaction/Drawer/index.ts +1 -0
  184. package/src/components/interaction/DropdownMenu/DropdownMenu.mdx +2 -0
  185. package/src/components/interaction/DropdownMenu/DropdownMenu.spec.tsx +34 -0
  186. package/src/components/interaction/DropdownMenu/DropdownMenu.tsx +15 -5
  187. package/src/components/interaction/DropdownMenu/index.ts +1 -0
  188. package/src/components/interaction/Popover/Popover.mdx +6 -2
  189. package/src/components/interaction/Popover/Popover.module.css +26 -18
  190. package/src/components/interaction/Popover/Popover.spec.tsx +38 -0
  191. package/src/components/interaction/Popover/Popover.tsx +19 -5
  192. package/src/components/interaction/Popover/index.ts +1 -0
  193. package/src/components/interaction/Rating/Rating.mdx +1 -1
  194. package/src/components/interaction/Rating/Rating.module.css +2 -2
  195. package/src/components/interaction/Rating/Rating.tsx +1 -1
  196. package/src/components/interaction/Rating/index.ts +1 -0
  197. package/src/components/interaction/Toast/Toast.mdx +3 -0
  198. package/src/components/interaction/Toast/Toast.module.css +35 -5
  199. package/src/components/interaction/Toast/Toast.spec.tsx +69 -1
  200. package/src/components/interaction/Toast/Toast.tsx +15 -9
  201. package/src/components/interaction/form/Checkbox/Checkbox.mdx +3 -0
  202. package/src/components/interaction/form/Checkbox/Checkbox.module.css +13 -6
  203. package/src/components/interaction/form/Checkbox/Checkbox.spec.tsx +6 -0
  204. package/src/components/interaction/form/Checkbox/Checkbox.tsx +1 -1
  205. package/src/components/interaction/form/CheckboxGroup/CheckboxGroup.mdx +16 -1
  206. package/src/components/interaction/form/CheckboxGroup/CheckboxGroup.module.css +24 -8
  207. package/src/components/interaction/form/CheckboxGroup/CheckboxGroup.spec.tsx +32 -2
  208. package/src/components/interaction/form/CheckboxGroup/CheckboxGroup.tsx +14 -2
  209. package/src/components/interaction/form/Combobox/Combobox.mdx +11 -4
  210. package/src/components/interaction/form/Combobox/Combobox.module.css +6 -6
  211. package/src/components/interaction/form/Combobox/Combobox.spec.tsx +47 -0
  212. package/src/components/interaction/form/Combobox/Combobox.tsx +10 -5
  213. package/src/components/interaction/form/FieldGroup/FieldGroup.mdx +9 -10
  214. package/src/components/interaction/form/FieldGroup/FieldGroup.module.css +57 -23
  215. package/src/components/interaction/form/FieldGroup/FieldGroup.spec.tsx +129 -7
  216. package/src/components/interaction/form/FieldGroup/FieldGroup.tsx +72 -12
  217. package/src/components/interaction/form/FileInput/FileInput.mdx +9 -1
  218. package/src/components/interaction/form/FileInput/FileInput.module.css +8 -8
  219. package/src/components/interaction/form/FileInput/FileInput.spec.tsx +89 -1
  220. package/src/components/interaction/form/FileInput/FileInput.tsx +6 -2
  221. package/src/components/interaction/form/FormInput/FormInput.mdx +9 -5
  222. package/src/components/interaction/form/FormInput/FormInput.module.css +17 -8
  223. package/src/components/interaction/form/FormInput/FormInput.spec.tsx +20 -0
  224. package/src/components/interaction/form/FormInput/FormInput.tsx +7 -2
  225. package/src/components/interaction/form/NumberInput/NumberInput.mdx +5 -1
  226. package/src/components/interaction/form/NumberInput/NumberInput.module.css +6 -6
  227. package/src/components/interaction/form/NumberInput/NumberInput.spec.tsx +51 -0
  228. package/src/components/interaction/form/NumberInput/NumberInput.tsx +36 -8
  229. package/src/components/interaction/form/Radio/Radio.mdx +8 -1
  230. package/src/components/interaction/form/Radio/Radio.module.css +20 -7
  231. package/src/components/interaction/form/Radio/Radio.spec.tsx +15 -0
  232. package/src/components/interaction/form/Radio/Radio.tsx +10 -4
  233. package/src/components/interaction/form/RadioGroup/RadioGroup.mdx +16 -1
  234. package/src/components/interaction/form/RadioGroup/RadioGroup.module.css +24 -8
  235. package/src/components/interaction/form/RadioGroup/RadioGroup.spec.tsx +32 -2
  236. package/src/components/interaction/form/RadioGroup/RadioGroup.tsx +14 -2
  237. package/src/components/interaction/form/SegmentedControl/SegmentedControl.mdx +9 -3
  238. package/src/components/interaction/form/SegmentedControl/SegmentedControl.module.css +25 -12
  239. package/src/components/interaction/form/SegmentedControl/SegmentedControl.spec.tsx +86 -5
  240. package/src/components/interaction/form/SegmentedControl/SegmentedControl.tsx +44 -4
  241. package/src/components/interaction/form/Select/Select.mdx +10 -4
  242. package/src/components/interaction/form/Select/Select.module.css +4 -4
  243. package/src/components/interaction/form/Select/Select.spec.tsx +34 -0
  244. package/src/components/interaction/form/Select/Select.tsx +21 -9
  245. package/src/components/interaction/form/Slider/Slider.mdx +4 -1
  246. package/src/components/interaction/form/Slider/Slider.module.css +32 -8
  247. package/src/components/interaction/form/Slider/Slider.spec.tsx +29 -0
  248. package/src/components/interaction/form/Slider/Slider.tsx +9 -7
  249. package/src/components/interaction/form/Switch/Switch.mdx +2 -2
  250. package/src/components/interaction/form/Switch/Switch.module.css +12 -13
  251. package/src/components/interaction/form/Switch/Switch.spec.tsx +20 -0
  252. package/src/components/interaction/form/Switch/Switch.tsx +2 -1
  253. package/src/components/interaction/form/Textarea/Textarea.mdx +5 -0
  254. package/src/components/interaction/form/Textarea/Textarea.module.css +5 -5
  255. package/src/components/interaction/form/Textarea/Textarea.spec.tsx +13 -0
  256. package/src/components/interaction/form/Textarea/Textarea.tsx +3 -1
  257. package/src/components/interaction/form/atoms/Message.module.css +1 -1
  258. package/src/components/interaction/form/atoms/Message.spec.tsx +29 -0
  259. package/src/components/interaction/form/atoms/Message.tsx +1 -1
  260. package/src/components/layout/ButtonGroup/ButtonGroup.mdx +11 -0
  261. package/src/components/layout/ButtonGroup/ButtonGroup.module.css +1 -5
  262. package/src/components/layout/ButtonGroup/ButtonGroup.stories.tsx +14 -0
  263. package/src/components/layout/Card/Card.mdx +6 -1
  264. package/src/components/layout/Card/Card.module.css +26 -5
  265. package/src/components/layout/Card/Card.spec.tsx +7 -0
  266. package/src/components/layout/Card/Card.tsx +4 -3
  267. package/src/components/layout/Grid/Grid.spec.tsx +44 -0
  268. package/src/components/layout/Grid/Grid.tsx +5 -5
  269. package/src/components/layout/Grid/GridItem.tsx +6 -6
  270. package/src/components/layout/Grid/masonry.ts +31 -5
  271. package/src/components/layout/Grid/useIsomorphicLayoutEffect.ts +11 -0
  272. package/src/components/layout/IconWrapper/IconWrapper.mdx +8 -2
  273. package/src/components/layout/IconWrapper/IconWrapper.module.css +9 -6
  274. package/src/components/layout/SectionHeader/SectionHeader.mdx +4 -1
  275. package/src/components/layout/SectionHeader/SectionHeader.module.css +10 -9
  276. package/src/components/ui/Accordion/Accordion.mdx +4 -1
  277. package/src/components/ui/Accordion/Accordion.module.css +2 -1
  278. package/src/components/ui/Alert/Alert.mdx +21 -4
  279. package/src/components/ui/Alert/Alert.module.css +9 -4
  280. package/src/components/ui/Alert/Alert.spec.tsx +20 -0
  281. package/src/components/ui/Avatar/Avatar.mdx +8 -3
  282. package/src/components/ui/Avatar/Avatar.module.css +13 -8
  283. package/src/components/ui/Badge/Badge.mdx +3 -1
  284. package/src/components/ui/Breadcrumb/Breadcrumb.mdx +3 -0
  285. package/src/components/ui/Breadcrumb/Breadcrumb.module.css +4 -0
  286. package/src/components/ui/Breadcrumb/Breadcrumb.spec.tsx +12 -0
  287. package/src/components/ui/Breadcrumb/Breadcrumb.tsx +11 -3
  288. package/src/components/ui/Calendar/Calendar.mdx +6 -0
  289. package/src/components/ui/Calendar/Calendar.module.css +68 -19
  290. package/src/components/ui/Calendar/Calendar.spec.tsx +139 -24
  291. package/src/components/ui/Calendar/Calendar.stories.tsx +14 -0
  292. package/src/components/ui/Calendar/Calendar.tsx +143 -154
  293. package/src/components/ui/Calendar/CalendarRange.mdx +39 -0
  294. package/src/components/ui/Calendar/CalendarRange.spec.tsx +119 -0
  295. package/src/components/ui/Calendar/CalendarRange.stories.tsx +51 -0
  296. package/src/components/ui/Calendar/CalendarRange.tsx +213 -0
  297. package/src/components/ui/Calendar/MonthGrid.tsx +141 -0
  298. package/src/components/ui/Calendar/calendar-core.spec.ts +176 -0
  299. package/src/components/ui/Calendar/calendar-core.ts +164 -0
  300. package/src/components/ui/Calendar/index.ts +1 -0
  301. package/src/components/ui/Carousel/Carousel.mdx +8 -3
  302. package/src/components/ui/Carousel/Carousel.module.css +7 -5
  303. package/src/components/ui/Carousel/Carousel.spec.tsx +67 -0
  304. package/src/components/ui/Carousel/Carousel.tsx +19 -7
  305. package/src/components/ui/Collapsible/Collapsible.mdx +17 -6
  306. package/src/components/ui/Collapsible/Collapsible.module.css +7 -2
  307. package/src/components/ui/Collapsible/Collapsible.spec.tsx +40 -0
  308. package/src/components/ui/Collapsible/Collapsible.tsx +19 -2
  309. package/src/components/ui/DescriptionList/DescriptionList.mdx +2 -0
  310. package/src/components/ui/Link/Link.mdx +4 -2
  311. package/src/components/ui/Loading/Loading.mdx +6 -3
  312. package/src/components/ui/Loading/Loading.module.css +7 -7
  313. package/src/components/ui/Loading/Loading.spec.tsx +12 -0
  314. package/src/components/ui/Loading/Loading.tsx +8 -3
  315. package/src/components/ui/NotificationBanner/NotificationBanner.mdx +4 -0
  316. package/src/components/ui/NotificationBanner/NotificationBanner.module.css +5 -0
  317. package/src/components/ui/NotificationBanner/NotificationBanner.spec.tsx +20 -0
  318. package/src/components/ui/Pagination/Pagination.mdx +29 -7
  319. package/src/components/ui/Pagination/Pagination.module.css +15 -14
  320. package/src/components/ui/Progress/Progress.mdx +6 -2
  321. package/src/components/ui/Progress/Progress.module.css +1 -1
  322. package/src/components/ui/Progress/Progress.spec.tsx +17 -0
  323. package/src/components/ui/Progress/Progress.tsx +2 -2
  324. package/src/components/ui/ProgressCircle/ProgressCircle.mdx +8 -4
  325. package/src/components/ui/ProgressCircle/ProgressCircle.module.css +2 -2
  326. package/src/components/ui/ProgressCircle/ProgressCircle.spec.tsx +11 -1
  327. package/src/components/ui/ProgressCircle/ProgressCircle.tsx +1 -1
  328. package/src/components/ui/Separator/Separator.mdx +7 -0
  329. package/src/components/ui/Separator/Separator.module.css +1 -0
  330. package/src/components/ui/Skeleton/Skeleton.mdx +17 -0
  331. package/src/components/ui/Skeleton/Skeleton.module.css +12 -5
  332. package/src/components/ui/SkipLink/SkipLink.mdx +19 -0
  333. package/src/components/ui/SkipLink/SkipLink.module.css +8 -7
  334. package/src/components/ui/SkipLink/SkipLink.spec.tsx +28 -0
  335. package/src/components/ui/Table/Table.mdx +14 -0
  336. package/src/components/ui/Table/Table.module.css +13 -8
  337. package/src/components/ui/Table/Table.spec.tsx +56 -0
  338. package/src/components/ui/Table/Table.tsx +44 -6
  339. package/src/components/ui/Tabs/Tabs.mdx +16 -0
  340. package/src/components/ui/Tabs/Tabs.module.css +3 -3
  341. package/src/components/ui/Tabs/Tabs.spec.tsx +20 -0
  342. package/src/components/ui/Tabs/Tabs.tsx +5 -1
  343. package/src/components/ui/Tooltip/Tooltip.mdx +9 -0
  344. package/src/components/ui/Tooltip/Tooltip.module.css +32 -12
  345. package/src/components/ui/Tooltip/Tooltip.spec.tsx +56 -0
  346. package/src/components/ui/Tooltip/Tooltip.tsx +26 -7
  347. package/src/components/ui/Typography/Typography.mdx +7 -0
  348. package/src/components/ui/Typography/Typography.module.css +5 -5
  349. package/src/index.ts +7 -3
  350. package/src/stories/DesignSystem/Borders.mdx +14 -9
  351. package/src/stories/DesignSystem/Colors.mdx +43 -41
  352. package/src/stories/DesignSystem/Overview.mdx +4 -3
  353. package/src/stories/Introduction.mdx +5 -5
  354. package/src/web-components/globals.ts +7 -0
  355. package/src/web-components/index.ts +2 -0
  356. package/src/web-components/interaction/BdsAccordion.mdx +10 -1
  357. package/src/web-components/interaction/BdsButton.mdx +15 -4
  358. package/src/web-components/interaction/BdsButton.stories.tsx +1 -1
  359. package/src/web-components/interaction/BdsCollapsible.mdx +3 -3
  360. package/src/web-components/interaction/BdsDialog.mdx +12 -7
  361. package/src/web-components/interaction/BdsDialog.stories.tsx +2 -2
  362. package/src/web-components/interaction/BdsDrawer.mdx +9 -6
  363. package/src/web-components/interaction/BdsDropdownMenu.mdx +20 -1
  364. package/src/web-components/interaction/BdsPopover.mdx +7 -3
  365. package/src/web-components/interaction/BdsSkipLink.mdx +14 -1
  366. package/src/web-components/interaction/BdsTabs.mdx +18 -1
  367. package/src/web-components/interaction/BdsToastProvider.mdx +21 -3
  368. package/src/web-components/interaction/BdsTooltip.mdx +4 -4
  369. package/src/web-components/interaction/bds-accordion-item.ts +10 -0
  370. package/src/web-components/interaction/bds-accordion.spec.ts +41 -0
  371. package/src/web-components/interaction/bds-accordion.ts +28 -2
  372. package/src/web-components/interaction/bds-button.spec.ts +81 -0
  373. package/src/web-components/interaction/bds-button.ts +60 -13
  374. package/src/web-components/interaction/bds-collapsible.spec.ts +93 -2
  375. package/src/web-components/interaction/bds-collapsible.ts +49 -7
  376. package/src/web-components/interaction/bds-dialog.spec.ts +49 -0
  377. package/src/web-components/interaction/bds-dialog.ts +68 -11
  378. package/src/web-components/interaction/bds-drawer.spec.ts +93 -4
  379. package/src/web-components/interaction/bds-drawer.ts +54 -21
  380. package/src/web-components/interaction/bds-dropdown-menu-item.ts +12 -1
  381. package/src/web-components/interaction/bds-dropdown-menu.spec.ts +63 -0
  382. package/src/web-components/interaction/bds-dropdown-menu.ts +45 -7
  383. package/src/web-components/interaction/bds-popover.spec.ts +80 -6
  384. package/src/web-components/interaction/bds-popover.ts +83 -32
  385. package/src/web-components/interaction/bds-skip-link.spec.ts +18 -0
  386. package/src/web-components/interaction/bds-skip-link.ts +29 -8
  387. package/src/web-components/interaction/bds-tab-panel.ts +10 -0
  388. package/src/web-components/interaction/bds-tab.spec.ts +25 -0
  389. package/src/web-components/interaction/bds-tab.ts +20 -5
  390. package/src/web-components/interaction/bds-tabs.spec.ts +92 -5
  391. package/src/web-components/interaction/bds-tabs.ts +42 -1
  392. package/src/web-components/interaction/bds-toast-provider.spec.ts +43 -0
  393. package/src/web-components/interaction/bds-toast-provider.ts +50 -21
  394. package/src/web-components/interaction/bds-tooltip.spec.ts +71 -0
  395. package/src/web-components/interaction/bds-tooltip.ts +100 -5
  396. package/src/web-components/interaction/form/BdsCheckbox.mdx +20 -1
  397. package/src/web-components/interaction/form/BdsCheckbox.stories.tsx +8 -0
  398. package/src/web-components/interaction/form/BdsCheckboxGroup.mdx +4 -3
  399. package/src/web-components/interaction/form/BdsCombobox.mdx +39 -2
  400. package/src/web-components/interaction/form/BdsCombobox.stories.tsx +31 -0
  401. package/src/web-components/interaction/form/BdsFieldGroup.mdx +8 -3
  402. package/src/web-components/interaction/form/BdsFieldGroup.stories.tsx +1 -1
  403. package/src/web-components/interaction/form/BdsFileInput.mdx +26 -5
  404. package/src/web-components/interaction/form/BdsFormInput.mdx +16 -1
  405. package/src/web-components/interaction/form/BdsNumberInput.mdx +34 -2
  406. package/src/web-components/interaction/form/BdsNumberInput.stories.tsx +27 -3
  407. package/src/web-components/interaction/form/BdsRadio.mdx +39 -12
  408. package/src/web-components/interaction/form/BdsRadio.stories.tsx +26 -0
  409. package/src/web-components/interaction/form/BdsRadioGroup.mdx +9 -4
  410. package/src/web-components/interaction/form/BdsSegmentedControl.mdx +37 -11
  411. package/src/web-components/interaction/form/BdsSelect.mdx +22 -4
  412. package/src/web-components/interaction/form/BdsSelect.stories.tsx +33 -0
  413. package/src/web-components/interaction/form/BdsSlider.mdx +36 -19
  414. package/src/web-components/interaction/form/BdsSlider.stories.tsx +24 -0
  415. package/src/web-components/interaction/form/BdsSwitch.mdx +38 -11
  416. package/src/web-components/interaction/form/BdsSwitch.stories.tsx +16 -0
  417. package/src/web-components/interaction/form/BdsTextarea.mdx +42 -16
  418. package/src/web-components/interaction/form/BdsTextarea.stories.tsx +21 -0
  419. package/src/web-components/interaction/form/bds-checkbox-group.spec.ts +99 -0
  420. package/src/web-components/interaction/form/bds-checkbox-group.ts +95 -9
  421. package/src/web-components/interaction/form/bds-checkbox.spec.ts +55 -0
  422. package/src/web-components/interaction/form/bds-checkbox.ts +30 -5
  423. package/src/web-components/interaction/form/bds-combobox.spec.ts +79 -0
  424. package/src/web-components/interaction/form/bds-combobox.ts +102 -17
  425. package/src/web-components/interaction/form/bds-field-group.spec.ts +158 -0
  426. package/src/web-components/interaction/form/bds-field-group.ts +167 -23
  427. package/src/web-components/interaction/form/bds-file-input.spec.ts +73 -5
  428. package/src/web-components/interaction/form/bds-file-input.ts +71 -34
  429. package/src/web-components/interaction/form/bds-form-input.spec.ts +22 -0
  430. package/src/web-components/interaction/form/bds-form-input.ts +27 -16
  431. package/src/web-components/interaction/form/bds-number-input.spec.ts +49 -0
  432. package/src/web-components/interaction/form/bds-number-input.ts +118 -29
  433. package/src/web-components/interaction/form/bds-radio-group.spec.ts +57 -0
  434. package/src/web-components/interaction/form/bds-radio-group.ts +60 -12
  435. package/src/web-components/interaction/form/bds-radio.spec.ts +123 -0
  436. package/src/web-components/interaction/form/bds-radio.ts +136 -23
  437. package/src/web-components/interaction/form/bds-segmented-control.spec.ts +55 -0
  438. package/src/web-components/interaction/form/bds-segmented-control.ts +81 -59
  439. package/src/web-components/interaction/form/bds-select.spec.ts +57 -0
  440. package/src/web-components/interaction/form/bds-select.ts +96 -8
  441. package/src/web-components/interaction/form/bds-slider.spec.ts +83 -0
  442. package/src/web-components/interaction/form/bds-slider.ts +181 -33
  443. package/src/web-components/interaction/form/bds-switch.spec.ts +68 -0
  444. package/src/web-components/interaction/form/bds-switch.ts +142 -41
  445. package/src/web-components/interaction/form/bds-textarea.spec.ts +71 -0
  446. package/src/web-components/interaction/form/bds-textarea.ts +109 -8
  447. package/src/web-components/layout/BdsGrid.mdx +6 -2
  448. package/src/web-components/layout/BdsGrid.stories.tsx +4 -0
  449. package/src/web-components/layout/bds-grid-item.spec.ts +21 -0
  450. package/src/web-components/layout/bds-grid-item.ts +17 -3
  451. package/src/web-components/layout/bds-grid.spec.ts +98 -0
  452. package/src/web-components/layout/bds-grid.ts +139 -19
  453. package/src/web-components/ui/BdsAlert.mdx +6 -5
  454. package/src/web-components/ui/BdsAlert.stories.tsx +6 -6
  455. package/src/web-components/ui/BdsAvatar.mdx +4 -2
  456. package/src/web-components/ui/BdsBreadcrumb.mdx +3 -2
  457. package/src/web-components/ui/BdsButtonContainer.mdx +64 -0
  458. package/src/web-components/ui/BdsButtonContainer.stories.tsx +84 -0
  459. package/src/web-components/ui/BdsCalendar.mdx +29 -4
  460. package/src/web-components/ui/BdsCalendar.stories.tsx +16 -18
  461. package/src/web-components/ui/BdsCalendarRange.mdx +71 -0
  462. package/src/web-components/ui/BdsCalendarRange.stories.tsx +31 -0
  463. package/src/web-components/ui/BdsCard.mdx +7 -3
  464. package/src/web-components/ui/BdsCard.stories.tsx +17 -1
  465. package/src/web-components/ui/BdsCarousel.mdx +40 -12
  466. package/src/web-components/ui/BdsDescriptionList.mdx +6 -1
  467. package/src/web-components/ui/BdsIconWrapper.mdx +3 -2
  468. package/src/web-components/ui/BdsLink.mdx +14 -2
  469. package/src/web-components/ui/BdsNotificationBanner.mdx +18 -0
  470. package/src/web-components/ui/BdsPagination.mdx +40 -1
  471. package/src/web-components/ui/BdsProgress.mdx +8 -2
  472. package/src/web-components/ui/BdsProgressCircle.mdx +5 -2
  473. package/src/web-components/ui/BdsRating.mdx +7 -0
  474. package/src/web-components/ui/BdsSectionHeader.mdx +22 -3
  475. package/src/web-components/ui/BdsSectionHeader.stories.tsx +15 -13
  476. package/src/web-components/ui/BdsTable.mdx +23 -2
  477. package/src/web-components/ui/BdsTable.stories.tsx +8 -2
  478. package/src/web-components/ui/BdsTypography.mdx +17 -1
  479. package/src/web-components/ui/bds-alert.spec.ts +17 -2
  480. package/src/web-components/ui/bds-alert.ts +31 -5
  481. package/src/web-components/ui/bds-avatar.spec.ts +29 -0
  482. package/src/web-components/ui/bds-avatar.ts +30 -12
  483. package/src/web-components/ui/bds-badge.spec.ts +5 -0
  484. package/src/web-components/ui/bds-badge.ts +11 -1
  485. package/src/web-components/ui/bds-breadcrumb.spec.ts +30 -0
  486. package/src/web-components/ui/bds-breadcrumb.ts +26 -4
  487. package/src/web-components/ui/bds-button-container.spec.ts +39 -0
  488. package/src/web-components/ui/bds-button-container.ts +123 -0
  489. package/src/web-components/ui/bds-button-group.spec.ts +14 -20
  490. package/src/web-components/ui/bds-button-group.ts +13 -64
  491. package/src/web-components/ui/bds-calendar-range.spec.ts +123 -0
  492. package/src/web-components/ui/bds-calendar-range.ts +307 -0
  493. package/src/web-components/ui/bds-calendar.spec.ts +176 -0
  494. package/src/web-components/ui/bds-calendar.ts +186 -344
  495. package/src/web-components/ui/bds-card.spec.ts +32 -0
  496. package/src/web-components/ui/bds-card.ts +34 -9
  497. package/src/web-components/ui/bds-carousel.spec.ts +147 -0
  498. package/src/web-components/ui/bds-carousel.ts +113 -36
  499. package/src/web-components/ui/bds-description-list.spec.ts +15 -0
  500. package/src/web-components/ui/bds-description-list.ts +37 -3
  501. package/src/web-components/ui/bds-icon-wrapper.spec.ts +12 -0
  502. package/src/web-components/ui/bds-icon-wrapper.ts +16 -15
  503. package/src/web-components/ui/bds-link.spec.ts +17 -0
  504. package/src/web-components/ui/bds-link.ts +26 -11
  505. package/src/web-components/ui/bds-loading.ts +11 -1
  506. package/src/web-components/ui/bds-notification-banner.spec.ts +13 -0
  507. package/src/web-components/ui/bds-notification-banner.ts +18 -1
  508. package/src/web-components/ui/bds-pagination.spec.ts +44 -0
  509. package/src/web-components/ui/bds-pagination.ts +39 -19
  510. package/src/web-components/ui/bds-progress-circle.spec.ts +21 -0
  511. package/src/web-components/ui/bds-progress-circle.ts +17 -5
  512. package/src/web-components/ui/bds-progress.spec.ts +21 -0
  513. package/src/web-components/ui/bds-progress.ts +19 -6
  514. package/src/web-components/ui/bds-rating.spec.ts +6 -0
  515. package/src/web-components/ui/bds-rating.ts +12 -2
  516. package/src/web-components/ui/bds-section-header.spec.ts +39 -8
  517. package/src/web-components/ui/bds-section-header.ts +47 -13
  518. package/src/web-components/ui/bds-separator.ts +10 -0
  519. package/src/web-components/ui/bds-skeleton.ts +10 -0
  520. package/src/web-components/ui/bds-table.spec.ts +63 -0
  521. package/src/web-components/ui/bds-table.ts +88 -28
  522. package/src/web-components/ui/bds-typography.spec.ts +47 -0
  523. package/src/web-components/ui/bds-typography.ts +28 -10
  524. package/src/web-components/ui/calendar-styles.ts +94 -0
  525. package/dist/web-components/chunk-5TFWOPLH.js +0 -49
  526. package/dist/web-components/chunk-7FMR53BW.js +0 -127
  527. package/dist/web-components/chunk-AGKJTMJI.js +0 -56
  528. package/dist/web-components/chunk-BQLZ7I4G.js +0 -56
  529. package/dist/web-components/chunk-IYGF6CD5.js +0 -118
  530. package/dist/web-components/chunk-QBB6ZX4R.js +0 -107
  531. package/dist/web-components/chunk-Y3POAKGS.js +0 -133
  532. package/dist/web-components/chunk-Y4MAXTMA.js +0 -80
  533. package/dist/web-components/chunk-Y7V7LM6R.js +0 -98
  534. package/src/web-components/ui/BdsButtonGroup.mdx +0 -69
  535. package/src/web-components/ui/BdsButtonGroup.stories.tsx +0 -66
@@ -1,15 +1,28 @@
1
- import { LitElement, css, html } from 'lit';
1
+ import { LitElement, css, html, nothing } from 'lit';
2
2
 
3
3
  /**
4
4
  * `<bds-checkbox-group>` — groups related checkboxes with a shared label.
5
5
  *
6
6
  * Renders a `<fieldset>` with a `<legend>` for accessible grouping.
7
+ * Propagates `disabled` to slotted `<bds-checkbox>` elements — a shadow-DOM
8
+ * `<fieldset disabled>` has no effect on slotted light-DOM content on its
9
+ * own, so the group attribute is explicitly applied to (and removed from)
10
+ * each child. A checkbox individually marked `disabled` in markup stays
11
+ * disabled even after the group re-enables.
12
+ *
13
+ * `required` is surfaced to assistive tech via a visually-hidden "(required)"
14
+ * text alternative in the legend rather than `aria-required` on the fieldset —
15
+ * `aria-required` is only a supported property on the `checkbox`, `combobox`,
16
+ * `gridcell`, `listbox`, `radiogroup`, `spinbutton`, `textbox` and `tree`
17
+ * roles; a bare `<fieldset>` maps to the generic `group` role, which does not
18
+ * support it (there is no ARIA `checkboxgroup` role), so the attribute would
19
+ * be silently ignored by assistive tech.
7
20
  *
8
21
  * Attributes:
9
22
  * label — visible group label (rendered as `<legend>`)
10
23
  * error — error message shown below items
11
24
  * hint — hint text shown below items
12
- * disabled — disables the entire fieldset
25
+ * disabled — disables the entire fieldset and all slotted `<bds-checkbox>` elements
13
26
  * required — marks the group as required
14
27
  *
15
28
  * Slots:
@@ -23,10 +36,25 @@ import { LitElement, css, html } from 'lit';
23
36
  */
24
37
  export class BdsCheckboxGroup extends LitElement {
25
38
  static styles = css`
39
+ /* Shadow DOM does not inherit the global box-sizing reset, so set it
40
+ here; otherwise elements with an explicit size + padding size as
41
+ content-box and layouts drift from the React (light-DOM) versions. */
42
+ :host,
43
+ *,
44
+ *::before,
45
+ *::after {
46
+ box-sizing: border-box;
47
+ }
48
+
26
49
  :host {
27
50
  display: block;
28
51
  }
29
52
 
53
+ :host([disabled]) .legend,
54
+ :host([disabled]) .message {
55
+ opacity: 0.5;
56
+ }
57
+
30
58
  fieldset {
31
59
  border: none;
32
60
  margin: 0;
@@ -36,7 +64,7 @@ export class BdsCheckboxGroup extends LitElement {
36
64
  .legend {
37
65
  font-size: var(--bds-font_size--body--s);
38
66
  font-family: var(--bds-font_family--body);
39
- font-weight: var(--bds-font_weight--semibold);
67
+ font-weight: var(--bds-font_weight--medium);
40
68
  color: var(--bds-color_on-bg);
41
69
  margin-block-end: var(--bds-space_xs);
42
70
  }
@@ -46,6 +74,22 @@ export class BdsCheckboxGroup extends LitElement {
46
74
  margin-inline-start: var(--bds-space_xxxs);
47
75
  }
48
76
 
77
+ /* Visually hidden but still exposed to assistive tech — carries the
78
+ "required" state into the fieldset's accessible name, since the
79
+ visible asterisk above is aria-hidden and aria-required is not
80
+ supported ARIA on a fieldset (role=group). */
81
+ .requiredLabel {
82
+ position: absolute;
83
+ inline-size: 1px;
84
+ block-size: 1px;
85
+ padding: 0;
86
+ margin: -1px;
87
+ overflow: hidden;
88
+ clip: rect(0, 0, 0, 0);
89
+ white-space: nowrap;
90
+ border-width: 0;
91
+ }
92
+
49
93
  .items {
50
94
  display: flex;
51
95
  flex-direction: column;
@@ -59,7 +103,7 @@ export class BdsCheckboxGroup extends LitElement {
59
103
  }
60
104
 
61
105
  .message--error {
62
- color: var(--bds-color_error);
106
+ color: var(--bds-color_error_on-bg);
63
107
  }
64
108
 
65
109
  .message--hint {
@@ -82,6 +126,8 @@ export class BdsCheckboxGroup extends LitElement {
82
126
  declare disabled: boolean;
83
127
  declare required: boolean;
84
128
 
129
+ private readonly _uid = Math.random().toString(36).slice(2, 8);
130
+
85
131
  constructor() {
86
132
  super();
87
133
  this.label = '';
@@ -89,20 +135,60 @@ export class BdsCheckboxGroup extends LitElement {
89
135
  this.required = false;
90
136
  }
91
137
 
138
+ /**
139
+ * Propagates `disabled` to slotted `<bds-checkbox>` elements. Only checkboxes
140
+ * that were enabled before the group disabled them are re-enabled when the
141
+ * group re-enables — a checkbox individually marked `disabled` in markup
142
+ * stays disabled.
143
+ */
144
+ private _propagateDisabled = () => {
145
+ this.querySelectorAll('bds-checkbox').forEach(checkbox => {
146
+ const el = checkbox as HTMLElement;
147
+ if (this.disabled) {
148
+ if (!el.hasAttribute('disabled')) {
149
+ el.setAttribute('data-bds-group-disabled', '');
150
+ }
151
+ el.setAttribute('disabled', '');
152
+ } else if (el.hasAttribute('data-bds-group-disabled')) {
153
+ el.removeAttribute('disabled');
154
+ el.removeAttribute('data-bds-group-disabled');
155
+ }
156
+ });
157
+ };
158
+
159
+ connectedCallback() {
160
+ super.connectedCallback();
161
+ // Propagate after slot content has been parsed
162
+ Promise.resolve().then(this._propagateDisabled);
163
+ }
164
+
165
+ updated(changed: Map<string, unknown>) {
166
+ super.updated(changed);
167
+ if (changed.has('disabled')) {
168
+ this._propagateDisabled();
169
+ }
170
+ }
171
+
92
172
  render() {
173
+ const errorId = `bds-checkbox-group-${this._uid}-error`;
174
+ const hintId = `bds-checkbox-group-${this._uid}-hint`;
175
+ const describedBy = [this.error && errorId, this.hint && hintId].filter(Boolean).join(' ') || undefined;
176
+
93
177
  return html`
94
- <fieldset ?disabled=${this.disabled}>
178
+ <fieldset ?disabled=${this.disabled} aria-describedby=${describedBy ?? nothing}>
95
179
  <legend class="legend">
96
180
  ${this.label}
97
- ${this.required ? html`<span class="required" aria-hidden="true"> *</span>` : ''}
181
+ ${this.required
182
+ ? html`<span class="required" aria-hidden="true"> *</span> <span class="requiredLabel">(required)</span>`
183
+ : ''}
98
184
  </legend>
99
185
  <div class="items">
100
- <slot></slot>
186
+ <slot @slotchange=${this._propagateDisabled}></slot>
101
187
  </div>
102
188
  ${this.error
103
- ? html`<p class="message message--error" role="alert">${this.error}</p>`
189
+ ? html`<p id=${errorId} class="message message--error" role="alert">${this.error}</p>`
104
190
  : this.hint
105
- ? html`<p class="message message--hint">${this.hint}</p>`
191
+ ? html`<p id=${hintId} class="message message--hint">${this.hint}</p>`
106
192
  : ''}
107
193
  </fieldset>
108
194
  `;
@@ -60,4 +60,59 @@ describe('bds-checkbox', () => {
60
60
  it('is form-associated', () => {
61
61
  expect(BdsCheckbox.formAssociated).toBe(true);
62
62
  });
63
+
64
+ it('recomputes required validity when checked changes (not just when required changes)', async () => {
65
+ const setValidity = vi.fn();
66
+ const spy = vi
67
+ .spyOn(HTMLElement.prototype, 'attachInternals')
68
+ .mockReturnValue({ setValidity, setFormValue: vi.fn() } as unknown as ElementInternals);
69
+
70
+ const el = await fixture('<bds-checkbox name="agree" required>Accept</bds-checkbox>') as BdsCheckbox;
71
+ // Initial connect already reports invalid (required + unchecked) — clear that call.
72
+ setValidity.mockClear();
73
+
74
+ const input = el.shadowRoot!.querySelector<HTMLInputElement>('input')!;
75
+ input.checked = true;
76
+ input.dispatchEvent(new Event('change', { bubbles: true }));
77
+ await el.updateComplete;
78
+
79
+ expect(setValidity).toHaveBeenLastCalledWith({});
80
+
81
+ spy.mockRestore();
82
+ cleanup(el);
83
+ });
84
+
85
+ it('reports invalid when a required checkbox becomes unchecked again', async () => {
86
+ const setValidity = vi.fn();
87
+ const spy = vi
88
+ .spyOn(HTMLElement.prototype, 'attachInternals')
89
+ .mockReturnValue({ setValidity, setFormValue: vi.fn() } as unknown as ElementInternals);
90
+
91
+ const el = await fixture('<bds-checkbox name="agree" required checked>Accept</bds-checkbox>') as BdsCheckbox;
92
+ setValidity.mockClear();
93
+
94
+ const input = el.shadowRoot!.querySelector<HTMLInputElement>('input')!;
95
+ input.checked = false;
96
+ input.dispatchEvent(new Event('change', { bubbles: true }));
97
+ await el.updateComplete;
98
+
99
+ expect(setValidity).toHaveBeenLastCalledWith({ valueMissing: true }, 'Required');
100
+
101
+ spy.mockRestore();
102
+ cleanup(el);
103
+ });
104
+
105
+ it('sets aria-invalid on the input when error attribute is set', async () => {
106
+ const el = await fixture('<bds-checkbox name="agree" error>Accept</bds-checkbox>');
107
+ const input = el.shadowRoot!.querySelector<HTMLInputElement>('input')!;
108
+ expect(input.getAttribute('aria-invalid')).toBe('true');
109
+ cleanup(el);
110
+ });
111
+
112
+ it('aria-invalid is false by default', async () => {
113
+ const el = await fixture('<bds-checkbox name="agree">Accept</bds-checkbox>');
114
+ const input = el.shadowRoot!.querySelector<HTMLInputElement>('input')!;
115
+ expect(input.getAttribute('aria-invalid')).toBe('false');
116
+ cleanup(el);
117
+ });
63
118
  });
@@ -13,6 +13,7 @@ import { LitElement, css, html } from 'lit';
13
13
  * checked — boolean; whether the checkbox is checked
14
14
  * required — boolean
15
15
  * disabled — boolean
16
+ * error — boolean; puts the checkbox in an error state (border colour + aria-invalid)
16
17
  *
17
18
  * Slots:
18
19
  * (default) — label text
@@ -27,10 +28,20 @@ export class BdsCheckbox extends LitElement {
27
28
  static formAssociated = true;
28
29
 
29
30
  static styles = css`
31
+ /* Shadow DOM does not inherit the global box-sizing reset, so set it
32
+ here; otherwise elements with an explicit size + padding size as
33
+ content-box and layouts drift from the React (light-DOM) versions. */
34
+ :host,
35
+ *,
36
+ *::before,
37
+ *::after {
38
+ box-sizing: border-box;
39
+ }
40
+
30
41
  :host {
31
42
  display: inline-flex;
32
43
  align-items: flex-start;
33
- gap: var(--bds-space_xs);
44
+ gap: var(--checkbox_gap, var(--bds-space_m));
34
45
  cursor: pointer;
35
46
  font-size: var(--bds-font_size--body);
36
47
  font-family: var(--bds-font_family--body);
@@ -45,16 +56,18 @@ export class BdsCheckbox extends LitElement {
45
56
 
46
57
  .input {
47
58
  --inputSize: calc(var(--bds-space_s) * 2);
48
- margin-block-start: 0.25em;
59
+ margin-block-start: var(--checkbox_offset, 0.25em);
49
60
  inline-size: var(--inputSize);
50
61
  block-size: var(--inputSize);
51
62
  flex-shrink: 0;
52
- --bdc_color: var(--checkbox_border-color, currentcolor);
63
+ /* --checkbox_border-color is a deprecated alias — prefer --checkbox_color (matches React) */
64
+ color: var(--checkbox_color, var(--checkbox_border-color, var(--bds-color_on-bg)));
65
+ --bdc_color: currentcolor;
53
66
  --bdc-outline_radius: var(--bds-border_radius--xs);
54
67
 
55
68
  border-radius: var(--checkbox_radius, var(--bdc-outline_radius));
56
69
  box-shadow: inset 0 0 0 var(--bdc-outline_width) var(--bdc_color), var(--checkbox_shadow, var(--bdc-outline_shadow));
57
- border: none;
70
+ border: var(--checkbox_border, none);
58
71
  appearance: none;
59
72
  background-color: var(--checkbox_color_bg, var(--bds-color_bg));
60
73
  cursor: pointer;
@@ -79,11 +92,19 @@ export class BdsCheckbox extends LitElement {
79
92
  transform: rotate(45deg);
80
93
  }
81
94
 
95
+ .input:focus {
96
+ --bdc_color: var(--bdc_color--focus);
97
+ }
98
+
82
99
  .input:focus-visible {
83
100
  outline: var(--bds-outline_default);
84
101
  outline-offset: var(--bds-outline_offset);
85
102
  }
86
103
 
104
+ :host([error]) .input {
105
+ --bdc_color: var(--bdc_color--error);
106
+ }
107
+
87
108
  label {
88
109
  cursor: pointer;
89
110
  flex: 1;
@@ -96,6 +117,7 @@ export class BdsCheckbox extends LitElement {
96
117
  checked: { type: Boolean, reflect: true },
97
118
  required: { type: Boolean, reflect: true },
98
119
  disabled: { type: Boolean, reflect: true },
120
+ error: { type: Boolean, reflect: true },
99
121
  };
100
122
 
101
123
  declare name: string;
@@ -103,6 +125,7 @@ export class BdsCheckbox extends LitElement {
103
125
  declare checked: boolean;
104
126
  declare required: boolean;
105
127
  declare disabled: boolean;
128
+ declare error: boolean;
106
129
 
107
130
  private _internals!: ElementInternals;
108
131
  private readonly _uid = Math.random().toString(36).slice(2, 8);
@@ -115,6 +138,7 @@ export class BdsCheckbox extends LitElement {
115
138
  this.checked = false;
116
139
  this.required = false;
117
140
  this.disabled = false;
141
+ this.error = false;
118
142
  }
119
143
 
120
144
  updated(changed: Map<string, unknown>) {
@@ -122,7 +146,7 @@ export class BdsCheckbox extends LitElement {
122
146
  if (changed.has('checked') || changed.has('value')) {
123
147
  this._internals.setFormValue?.(this.checked ? this.value : null);
124
148
  }
125
- if (changed.has('required')) {
149
+ if (changed.has('required') || changed.has('checked')) {
126
150
  if (this.required && !this.checked) {
127
151
  this._internals.setValidity?.({ valueMissing: true }, 'Required');
128
152
  } else {
@@ -150,6 +174,7 @@ export class BdsCheckbox extends LitElement {
150
174
  .checked=${this.checked}
151
175
  ?required=${this.required}
152
176
  ?disabled=${this.disabled}
177
+ aria-invalid=${this.error ? 'true' : 'false'}
153
178
  @change=${this._handleChange}
154
179
  />
155
180
  <label for=${id}><slot></slot></label>
@@ -114,4 +114,83 @@ describe('bds-combobox', () => {
114
114
  it('is form-associated', () => {
115
115
  expect(BdsCombobox.formAssociated).toBe(true);
116
116
  });
117
+
118
+ it('associates a visible label with the input via for/id', async () => {
119
+ const el = await fixture(`<bds-combobox name="country" label="Country" options='${OPTIONS}'></bds-combobox>`);
120
+ const label = el.shadowRoot!.querySelector<HTMLLabelElement>('label')!;
121
+ const input = el.shadowRoot!.querySelector<HTMLInputElement>('input')!;
122
+ expect(label).not.toBeNull();
123
+ expect(label.textContent).toBe('Country');
124
+ expect(label.getAttribute('for')).toBe(input.id);
125
+ cleanup(el);
126
+ });
127
+
128
+ it('renders no label when the label attribute is unset', async () => {
129
+ const el = await fixture(`<bds-combobox name="country" options='${OPTIONS}'></bds-combobox>`);
130
+ expect(el.shadowRoot!.querySelector('label')).toBeNull();
131
+ cleanup(el);
132
+ });
133
+
134
+ it('sets aria-controls on the input pointing at the listbox id', async () => {
135
+ const el = await fixture(`<bds-combobox name="country" options='${OPTIONS}'></bds-combobox>`);
136
+ const input = el.shadowRoot!.querySelector<HTMLInputElement>('input')!;
137
+ input.dispatchEvent(new Event('focus'));
138
+ await el.updateComplete;
139
+ const listbox = el.shadowRoot!.querySelector('[role="listbox"]')!;
140
+ expect(input.getAttribute('aria-controls')).toBe(listbox.id);
141
+ cleanup(el);
142
+ });
143
+
144
+ it('sets autocomplete="off" on the input', async () => {
145
+ const el = await fixture(`<bds-combobox name="country" options='${OPTIONS}'></bds-combobox>`);
146
+ const input = el.shadowRoot!.querySelector<HTMLInputElement>('input')!;
147
+ expect(input.getAttribute('autocomplete')).toBe('off');
148
+ cleanup(el);
149
+ });
150
+
151
+ it('updates aria-activedescendant to the focused option id while navigating', async () => {
152
+ const el = await fixture(`<bds-combobox name="country" options='${OPTIONS}'></bds-combobox>`);
153
+ const input = el.shadowRoot!.querySelector<HTMLInputElement>('input')!;
154
+ input.dispatchEvent(new Event('focus'));
155
+ await el.updateComplete;
156
+ expect(input.hasAttribute('aria-activedescendant')).toBe(false);
157
+
158
+ input.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowDown', bubbles: true }));
159
+ await el.updateComplete;
160
+ const options = Array.from(el.shadowRoot!.querySelectorAll('[role="option"]'));
161
+ const focusedOption = options.find(o => o.className.includes('--focused'))!;
162
+ expect(focusedOption).not.toBeUndefined();
163
+ expect(input.getAttribute('aria-activedescendant')).toBe(focusedOption.id);
164
+ cleanup(el);
165
+ });
166
+
167
+ it('gives the no-results item role="presentation" so it is not exposed as an option', async () => {
168
+ const el = await fixture(`<bds-combobox name="country" options='${OPTIONS}'></bds-combobox>`);
169
+ const input = el.shadowRoot!.querySelector<HTMLInputElement>('input')!;
170
+ input.value = 'zzz';
171
+ input.dispatchEvent(new Event('input', { bubbles: true }));
172
+ await el.updateComplete;
173
+ const noResults = el.shadowRoot!.querySelector('.no-results')!;
174
+ expect(noResults.getAttribute('role')).toBe('presentation');
175
+ cleanup(el);
176
+ });
177
+
178
+ it('sets aria-invalid and wires the error message via aria-describedby', async () => {
179
+ const el = await fixture(`<bds-combobox name="country" error="Required field" options='${OPTIONS}'></bds-combobox>`);
180
+ const input = el.shadowRoot!.querySelector<HTMLInputElement>('input')!;
181
+ const error = el.shadowRoot!.querySelector('.message--error')!;
182
+ expect(input.getAttribute('aria-invalid')).toBe('true');
183
+ expect(error.getAttribute('role')).toBe('alert');
184
+ expect(input.getAttribute('aria-describedby')).toBe(error.id);
185
+ cleanup(el);
186
+ });
187
+
188
+ it('wires the hint message via aria-describedby when there is no error', async () => {
189
+ const el = await fixture(`<bds-combobox name="country" hint="Pick a country" options='${OPTIONS}'></bds-combobox>`);
190
+ const input = el.shadowRoot!.querySelector<HTMLInputElement>('input')!;
191
+ const hint = el.shadowRoot!.querySelector('.message--hint')!;
192
+ expect(input.getAttribute('aria-invalid')).toBe('false');
193
+ expect(input.getAttribute('aria-describedby')).toBe(hint.id);
194
+ cleanup(el);
195
+ });
117
196
  });
@@ -1,4 +1,4 @@
1
- import { LitElement, css, html } from 'lit';
1
+ import { LitElement, css, html, nothing } from 'lit';
2
2
 
3
3
  export interface ComboboxOption {
4
4
  value: string;
@@ -17,6 +17,9 @@ export interface ComboboxOption {
17
17
  * value — currently selected value
18
18
  * options — JSON array of `{ value, label, disabled? }` option objects
19
19
  * placeholder — input placeholder text
20
+ * label — visible label text (associated to the input via `<label for>`)
21
+ * hint — helper text shown below the input
22
+ * error — error message; when set the input enters error state
20
23
  * disabled — boolean
21
24
  *
22
25
  * Events:
@@ -25,6 +28,7 @@ export interface ComboboxOption {
25
28
  * @example
26
29
  * <bds-combobox
27
30
  * name="country"
31
+ * label="Country"
28
32
  * placeholder="Search…"
29
33
  * options='[{"value":"nl","label":"Netherlands"},{"value":"be","label":"Belgium"}]'
30
34
  * ></bds-combobox>
@@ -33,6 +37,16 @@ export class BdsCombobox extends LitElement {
33
37
  static formAssociated = true;
34
38
 
35
39
  static styles = css`
40
+ /* Shadow DOM does not inherit the global box-sizing reset, so set it
41
+ here; otherwise elements with an explicit size + padding size as
42
+ content-box and layouts drift from the React (light-DOM) versions. */
43
+ :host,
44
+ *,
45
+ *::before,
46
+ *::after {
47
+ box-sizing: border-box;
48
+ }
49
+
36
50
  :host {
37
51
  display: block;
38
52
  position: relative;
@@ -43,6 +57,15 @@ export class BdsCombobox extends LitElement {
43
57
  pointer-events: none;
44
58
  }
45
59
 
60
+ .label {
61
+ display: block;
62
+ font-size: var(--bds-font_size--body--s);
63
+ font-family: var(--bds-font_family--body);
64
+ font-weight: var(--bds-font_weight--semibold);
65
+ color: var(--bds-color_on-bg);
66
+ margin-block-end: var(--bds-space_xxs);
67
+ }
68
+
46
69
  .wrapper {
47
70
  position: relative;
48
71
  }
@@ -52,10 +75,10 @@ export class BdsCombobox extends LitElement {
52
75
  font-family: var(--bds-font_family--body);
53
76
  font-size: var(--bds-font_size--body);
54
77
  padding: var(--bds-space_s);
55
- padding-inline-end: var(--bds-space_xl);
56
- border: none;
78
+ padding-inline-end: var(--bds-space_xxl);
79
+ border: var(--combobox_border, none);
57
80
  --bdc_color: var(--combobox_border-color, currentcolor);
58
- --bdc-outline_radius: var(--bds-border_radius--xs);
81
+ --bdc-outline_radius: var(--bds-border_radius--full);
59
82
 
60
83
  border-radius: var(--combobox_radius, var(--bdc-outline_radius));
61
84
  box-shadow: inset 0 0 0 var(--bdc-outline_width) var(--bdc_color), var(--combobox_shadow, var(--bdc-outline_shadow));
@@ -74,6 +97,14 @@ export class BdsCombobox extends LitElement {
74
97
  outline-offset: var(--bds-outline_offset);
75
98
  }
76
99
 
100
+ :host([error]) .input {
101
+ --bdc_color: var(--bdc_color--error);
102
+ }
103
+
104
+ :host([error]) .input:focus {
105
+ --bdc_color: var(--bdc_color--error);
106
+ }
107
+
77
108
  .chevron {
78
109
  position: absolute;
79
110
  inset-inline-end: var(--bds-space_s);
@@ -92,31 +123,39 @@ export class BdsCombobox extends LitElement {
92
123
 
93
124
  .listbox {
94
125
  position: absolute;
95
- inset-block-start: calc(100% + var(--bds-space_xs));
126
+ inset-block-start: calc(100% + var(--bds-space_xxs));
96
127
  inset-inline-start: 0;
97
128
  inline-size: 100%;
98
129
  max-block-size: 15rem;
99
- overflow-y: auto;
100
- background-color: var(--combobox_list-bg, var(--bds-color_bg));
101
- border-radius: var(--bds-border_radius--s);
102
- box-shadow: var(--bds-shadow_m);
103
- z-index: var(--combobox_z-index, 100);
104
- padding-block: var(--bds-space_xs);
130
+ overflow-block: auto;
131
+ list-style: none;
132
+ margin: 0;
133
+ border: var(--combobox_listbox-border, none);
134
+ --bdc_color: currentcolor;
135
+ --bdc-outline_radius: var(--bds-border_radius--s);
136
+
137
+ border-radius: var(--combobox_listbox-radius, var(--bdc-outline_radius));
138
+ background-color: var(--combobox_color_bg, var(--bds-color_bg));
139
+ color: var(--combobox_on-color, var(--bds-color_on-bg));
140
+ box-shadow: inset 0 0 0 var(--bdc-outline_width) var(--bdc_color), var(--combobox_listbox-shadow, var(--bds-shadow_m));
141
+ z-index: var(--combobox_z-index, var(--bds-z-index_dropdown));
142
+ padding: var(--bds-space_xxs) 0;
105
143
  }
106
144
 
107
145
  .option {
108
146
  display: block;
109
- padding: var(--bds-space_s) var(--bds-space_m);
147
+ padding: var(--bds-space_xs) var(--bds-space_m);
110
148
  cursor: pointer;
111
149
  font-family: var(--bds-font_family--body);
112
150
  font-size: var(--bds-font_size--body);
113
- color: var(--bds-color_on-bg);
151
+ color: var(--combobox_on-color, var(--bds-color_on-bg));
114
152
  transition: background-color var(--bds-animation_transition-duration) var(--bds-animation_easing);
115
153
  }
116
154
 
117
155
  .option:hover,
118
156
  .option[aria-selected='true'] {
119
- background-color: var(--bds-color_bg--subtle);
157
+ background-color: var(--combobox_option-bg--highlighted, var(--bds-color_bg--subtle));
158
+ color: var(--combobox_option-color--highlighted, var(--bds-color_interactive_on-bg));
120
159
  }
121
160
 
122
161
  .option[aria-disabled='true'] {
@@ -125,7 +164,8 @@ export class BdsCombobox extends LitElement {
125
164
  }
126
165
 
127
166
  .option.--focused {
128
- background-color: var(--bds-color_bg--subtle);
167
+ background-color: var(--combobox_option-bg--highlighted, var(--bds-color_bg--subtle));
168
+ color: var(--combobox_option-color--highlighted, var(--bds-color_interactive_on-bg));
129
169
  outline: none;
130
170
  }
131
171
 
@@ -135,6 +175,21 @@ export class BdsCombobox extends LitElement {
135
175
  font-size: var(--bds-font_size--body--s);
136
176
  color: var(--bds-color_on-bg--subtle);
137
177
  }
178
+
179
+ .message {
180
+ margin-block-start: var(--bds-space_xxs);
181
+ font-size: var(--bds-font_size--body--s);
182
+ font-family: var(--bds-font_family--body);
183
+ }
184
+
185
+ .message--error {
186
+ color: var(--bds-color_error);
187
+ }
188
+
189
+ .message--hint {
190
+ color: var(--bds-color_on-bg--subtle);
191
+ font-style: italic;
192
+ }
138
193
  `;
139
194
 
140
195
  static properties = {
@@ -142,6 +197,9 @@ export class BdsCombobox extends LitElement {
142
197
  value: { type: String },
143
198
  options: { type: String },
144
199
  placeholder: { type: String },
200
+ label: { type: String },
201
+ hint: { type: String },
202
+ error: { type: String, reflect: true },
145
203
  disabled: { type: Boolean, reflect: true },
146
204
  };
147
205
 
@@ -149,9 +207,13 @@ export class BdsCombobox extends LitElement {
149
207
  declare value: string;
150
208
  declare options: string;
151
209
  declare placeholder: string;
210
+ declare label: string;
211
+ declare hint: string | undefined;
212
+ declare error: string | undefined;
152
213
  declare disabled: boolean;
153
214
 
154
215
  private _internals!: ElementInternals;
216
+ private readonly _uid = Math.random().toString(36).slice(2, 8);
155
217
  private _open = false;
156
218
  private _query = '';
157
219
  private _focusedIndex = -1;
@@ -163,6 +225,7 @@ export class BdsCombobox extends LitElement {
163
225
  this.value = '';
164
226
  this.options = '[]';
165
227
  this.placeholder = '';
228
+ this.label = '';
166
229
  this.disabled = false;
167
230
  }
168
231
 
@@ -280,16 +343,32 @@ export class BdsCombobox extends LitElement {
280
343
  render() {
281
344
  const filtered = this._filtered;
282
345
  const inputValue = this._open ? this._query : this._displayLabel;
346
+ const id = `bds-combobox-${this._uid}`;
347
+ const listboxId = `${id}-listbox`;
348
+ const hintId = `${id}-hint`;
349
+ const errorId = `${id}-error`;
350
+ const describedBy = [this.error && errorId, this.hint && hintId].filter(Boolean).join(' ') || undefined;
351
+ const activeDescendant =
352
+ this._focusedIndex >= 0 && this._focusedIndex < filtered.length
353
+ ? `${id}-option-${this._focusedIndex}`
354
+ : undefined;
283
355
 
284
356
  return html`
357
+ ${this.label ? html`<label class="label" for=${id}>${this.label}</label>` : ''}
285
358
  <div class="wrapper">
286
359
  <input
360
+ id=${id}
287
361
  type="text"
288
362
  class="input"
289
363
  role="combobox"
290
364
  aria-expanded=${this._open}
291
365
  aria-autocomplete="list"
292
366
  aria-haspopup="listbox"
367
+ aria-controls=${listboxId}
368
+ aria-activedescendant=${activeDescendant ?? nothing}
369
+ aria-invalid=${this.error ? 'true' : 'false'}
370
+ aria-describedby=${describedBy ?? nothing}
371
+ autocomplete="off"
293
372
  name=${this.name}
294
373
  placeholder=${this.placeholder}
295
374
  .value=${inputValue}
@@ -305,11 +384,12 @@ export class BdsCombobox extends LitElement {
305
384
  </svg>
306
385
  </span>
307
386
  ${this._open ? html`
308
- <ul class="listbox" role="listbox" aria-label="Options">
387
+ <ul id=${listboxId} class="listbox" role="listbox" aria-label="Options">
309
388
  ${filtered.length === 0
310
- ? html`<li class="no-results">No results</li>`
389
+ ? html`<li class="no-results" role="presentation">No results</li>`
311
390
  : filtered.map((opt, i) => html`
312
391
  <li
392
+ id="${id}-option-${i}"
313
393
  class="option ${i === this._focusedIndex ? '--focused' : ''}"
314
394
  role="option"
315
395
  aria-selected=${opt.value === this.value}
@@ -321,6 +401,11 @@ export class BdsCombobox extends LitElement {
321
401
  </ul>
322
402
  ` : ''}
323
403
  </div>
404
+ ${this.error
405
+ ? html`<p id=${errorId} class="message message--error" role="alert">${this.error}</p>`
406
+ : this.hint
407
+ ? html`<p id=${hintId} class="message message--hint">${this.hint}</p>`
408
+ : ''}
324
409
  `;
325
410
  }
326
411
  }