@brandsync/wc 1.7.0 → 1.9.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 (345) hide show
  1. package/custom-elements.json +340 -24
  2. package/dist/brandsync-wc/brandsync-wc.esm.js +1 -1
  3. package/dist/brandsync-wc/{p-fde5e9f1.entry.js → p-051d3064.entry.js} +1 -1
  4. package/dist/brandsync-wc/{p-f243683f.entry.js → p-05c7de28.entry.js} +1 -1
  5. package/dist/brandsync-wc/{p-2d6955d6.entry.js → p-062cfa34.entry.js} +1 -1
  6. package/dist/brandsync-wc/p-0e39b9cc.entry.js +1 -0
  7. package/dist/brandsync-wc/p-0eed6813.entry.js +1 -0
  8. package/dist/brandsync-wc/{p-d25b7b74.entry.js → p-107b1c5d.entry.js} +1 -1
  9. package/dist/brandsync-wc/{p-538cc08e.entry.js → p-114d2fd8.entry.js} +1 -1
  10. package/dist/brandsync-wc/{p-6754dfa9.entry.js → p-1c0db4d6.entry.js} +1 -1
  11. package/dist/brandsync-wc/{p-4a1a5d6e.entry.js → p-1f7208cb.entry.js} +1 -1
  12. package/dist/brandsync-wc/p-2181378f.entry.js +1 -0
  13. package/dist/brandsync-wc/{p-d06543a5.entry.js → p-235ae012.entry.js} +1 -1
  14. package/dist/brandsync-wc/{p-2700a63e.entry.js → p-275072dd.entry.js} +1 -1
  15. package/dist/brandsync-wc/p-27bbed83.entry.js +1 -0
  16. package/dist/brandsync-wc/p-2891d40b.entry.js +1 -0
  17. package/dist/brandsync-wc/p-29027559.entry.js +1 -0
  18. package/dist/brandsync-wc/{p-a36a0e6a.entry.js → p-3176d1d3.entry.js} +1 -1
  19. package/dist/brandsync-wc/{p-0d86c22d.entry.js → p-33e44094.entry.js} +1 -1
  20. package/dist/brandsync-wc/{p-e427bbda.entry.js → p-360452c2.entry.js} +1 -1
  21. package/dist/brandsync-wc/p-36bf37d9.entry.js +1 -0
  22. package/dist/brandsync-wc/p-3b64e3cd.entry.js +1 -0
  23. package/dist/brandsync-wc/p-3ec74d35.entry.js +1 -0
  24. package/dist/brandsync-wc/p-4574a707.entry.js +1 -0
  25. package/dist/brandsync-wc/p-4e5dcaff.entry.js +1 -0
  26. package/dist/brandsync-wc/{p-61db6ce2.entry.js → p-61c1a2a3.entry.js} +1 -1
  27. package/dist/brandsync-wc/{p-85c70f6d.entry.js → p-6331de9c.entry.js} +1 -1
  28. package/dist/brandsync-wc/{p-9c1be2a0.entry.js → p-6bf2f116.entry.js} +1 -1
  29. package/dist/brandsync-wc/p-6fd7dd6a.entry.js +1 -0
  30. package/dist/brandsync-wc/{p-c3a28a89.entry.js → p-70f64b25.entry.js} +1 -1
  31. package/dist/brandsync-wc/{p-06e9b45d.entry.js → p-7b00dd36.entry.js} +1 -1
  32. package/dist/brandsync-wc/{p-13e4966c.entry.js → p-7c94e6ae.entry.js} +1 -1
  33. package/dist/brandsync-wc/p-835a8dc7.entry.js +1 -0
  34. package/dist/brandsync-wc/{p-77433277.entry.js → p-8ee0153b.entry.js} +1 -1
  35. package/dist/brandsync-wc/{p-e1069ba9.entry.js → p-9f65f998.entry.js} +1 -1
  36. package/dist/brandsync-wc/p-9f6fe37d.entry.js +1 -0
  37. package/dist/brandsync-wc/{p-b2dc9886.entry.js → p-9f8852a0.entry.js} +1 -1
  38. package/dist/brandsync-wc/{p-DuyFft7h.js → p-AgoOSYvW.js} +2 -2
  39. package/dist/brandsync-wc/{p-fba01c96.entry.js → p-a09e157f.entry.js} +1 -1
  40. package/dist/brandsync-wc/{p-55e6438c.entry.js → p-a0d5a620.entry.js} +1 -1
  41. package/dist/brandsync-wc/{p-8b2ab522.entry.js → p-a5feaad4.entry.js} +1 -1
  42. package/dist/brandsync-wc/{p-cbaa19ab.entry.js → p-a92eec48.entry.js} +1 -1
  43. package/dist/brandsync-wc/{p-3eab22a5.entry.js → p-ae978c9a.entry.js} +1 -1
  44. package/dist/brandsync-wc/{p-f2ce9a1f.entry.js → p-bbcc47b0.entry.js} +1 -1
  45. package/dist/brandsync-wc/{p-80cf96ff.entry.js → p-be2c1740.entry.js} +1 -1
  46. package/dist/brandsync-wc/p-c10d2529.entry.js +1 -0
  47. package/dist/brandsync-wc/{p-819a3dae.entry.js → p-c3f72584.entry.js} +1 -1
  48. package/dist/brandsync-wc/{p-8b57f606.entry.js → p-c4de155c.entry.js} +1 -1
  49. package/dist/brandsync-wc/{p-c197cc95.entry.js → p-cfcf3f0a.entry.js} +1 -1
  50. package/dist/brandsync-wc/{p-f8f03334.entry.js → p-de7c946d.entry.js} +1 -1
  51. package/dist/brandsync-wc/{p-600b5434.entry.js → p-e9b43754.entry.js} +1 -1
  52. package/dist/brandsync-wc/{p-4bff9b4b.entry.js → p-f006d962.entry.js} +1 -1
  53. package/dist/brandsync-wc/p-f074f94e.entry.js +1 -0
  54. package/dist/brandsync-wc/{p-7ed5670e.entry.js → p-f7d47c17.entry.js} +1 -1
  55. package/dist/brandsync-wc/p-fc240aa0.entry.js +1 -0
  56. package/dist/brandsync-wc/{p-f518f486.entry.js → p-fc58c663.entry.js} +1 -1
  57. package/dist/brandsync-wc/{p-be14f99f.entry.js → p-fddc7bd1.entry.js} +1 -1
  58. package/dist/cjs/brandsync-wc.cjs.js +2 -2
  59. package/dist/cjs/bs-accordion.cjs.entry.js +2 -2
  60. package/dist/cjs/bs-ai-disclaimer.cjs.entry.js +1 -1
  61. package/dist/cjs/bs-ai-greeting.cjs.entry.js +1 -1
  62. package/dist/cjs/bs-ai-thinking.cjs.entry.js +1 -1
  63. package/dist/cjs/bs-attachment-list.cjs.entry.js +2 -2
  64. package/dist/cjs/bs-attachment.cjs.entry.js +2 -2
  65. package/dist/cjs/bs-avatar.cjs.entry.js +1 -1
  66. package/dist/cjs/bs-badge.cjs.entry.js +1 -1
  67. package/dist/cjs/bs-breadcrumb-overflow.cjs.entry.js +15 -3
  68. package/dist/cjs/bs-breadcrumb.cjs.entry.js +16 -2
  69. package/dist/cjs/bs-breadcrumbs.cjs.entry.js +1 -1
  70. package/dist/cjs/bs-button-skeleton.cjs.entry.js +1 -1
  71. package/dist/cjs/bs-button.cjs.entry.js +23 -4
  72. package/dist/cjs/bs-card.cjs.entry.js +2 -2
  73. package/dist/cjs/bs-carousel.cjs.entry.js +1 -1
  74. package/dist/cjs/bs-chatbot-feedback.cjs.entry.js +2 -2
  75. package/dist/cjs/bs-chatbot-header.cjs.entry.js +1 -1
  76. package/dist/cjs/bs-chatbot-response-action.cjs.entry.js +2 -2
  77. package/dist/cjs/bs-chatbot-sources-drawer.cjs.entry.js +1 -1
  78. package/dist/cjs/bs-chatbot-suggestion-button.cjs.entry.js +1 -1
  79. package/dist/cjs/bs-checkbox-skeleton.cjs.entry.js +1 -1
  80. package/dist/cjs/bs-checkbox.cjs.entry.js +48 -3
  81. package/dist/cjs/bs-chip-filter.cjs.entry.js +2 -2
  82. package/dist/cjs/bs-chip-informative.cjs.entry.js +2 -2
  83. package/dist/cjs/bs-chip-input.cjs.entry.js +2 -2
  84. package/dist/cjs/bs-composer-status-banner.cjs.entry.js +1 -1
  85. package/dist/cjs/bs-composer.cjs.entry.js +1 -1
  86. package/dist/cjs/bs-data-table.cjs.entry.js +20 -6
  87. package/dist/cjs/bs-dialog.cjs.entry.js +2 -2
  88. package/dist/cjs/bs-file-upload-item.cjs.entry.js +1 -1
  89. package/dist/cjs/bs-file-upload.cjs.entry.js +1 -1
  90. package/dist/cjs/bs-icon-button.cjs.entry.js +23 -4
  91. package/dist/cjs/bs-inline-tab.cjs.entry.js +11 -3
  92. package/dist/cjs/bs-input.cjs.entry.js +69 -5
  93. package/dist/cjs/bs-logo.cjs.entry.js +1 -1
  94. package/dist/cjs/bs-menu-item.cjs.entry.js +1 -1
  95. package/dist/cjs/bs-menu.cjs.entry.js +25 -3
  96. package/dist/cjs/bs-navigation-drawer-item.cjs.entry.js +2 -2
  97. package/dist/cjs/bs-navigation-drawer.cjs.entry.js +119 -6
  98. package/dist/cjs/bs-navigation-header.cjs.entry.js +2 -2
  99. package/dist/cjs/bs-pagination.cjs.entry.js +1 -1
  100. package/dist/cjs/bs-progress-linear.cjs.entry.js +1 -1
  101. package/dist/cjs/bs-progress.cjs.entry.js +8 -3
  102. package/dist/cjs/bs-radio.cjs.entry.js +81 -12
  103. package/dist/cjs/bs-slider.cjs.entry.js +54 -2
  104. package/dist/cjs/bs-snackbar.cjs.entry.js +1 -1
  105. package/dist/cjs/bs-source-link.cjs.entry.js +2 -2
  106. package/dist/cjs/bs-stepper-step.cjs.entry.js +2 -2
  107. package/dist/cjs/bs-stepper.cjs.entry.js +3 -2
  108. package/dist/cjs/bs-switch.cjs.entry.js +36 -3
  109. package/dist/cjs/bs-tab.cjs.entry.js +11 -3
  110. package/dist/cjs/bs-tabs.cjs.entry.js +97 -3
  111. package/dist/cjs/bs-toast.cjs.entry.js +1 -1
  112. package/dist/cjs/bs-tooltip.cjs.entry.js +2 -2
  113. package/dist/cjs/{index-D7e6DfLV.js → index-kk9YXF2S.js} +43 -5
  114. package/dist/cjs/loader.cjs.js +2 -2
  115. package/dist/collection/components/bs-a11y.cmp.test.js +54 -0
  116. package/dist/collection/components/bs-accordion/bs-accordion.css +5 -5
  117. package/dist/collection/components/bs-attachment/bs-attachment.css +1 -1
  118. package/dist/collection/components/bs-attachment-list/bs-attachment-list.css +1 -1
  119. package/dist/collection/components/bs-breadcrumb/bs-breadcrumb/bs-breadcrumb.cmp.test.js +63 -0
  120. package/dist/collection/components/bs-breadcrumb/bs-breadcrumb/bs-breadcrumb.js +32 -1
  121. package/dist/collection/components/bs-breadcrumb/bs-breadcrumb-overflow/bs-breadcrumb-overflow.cmp.test.js +45 -0
  122. package/dist/collection/components/bs-breadcrumb/bs-breadcrumb-overflow/bs-breadcrumb-overflow.css +1 -1
  123. package/dist/collection/components/bs-breadcrumb/bs-breadcrumb-overflow/bs-breadcrumb-overflow.js +30 -1
  124. package/dist/collection/components/bs-button/bs-button/bs-button.css +17 -10
  125. package/dist/collection/components/bs-button/bs-button/bs-button.js +16 -3
  126. package/dist/collection/components/bs-button/bs-icon-button/bs-icon-button.cmp.test.js +20 -0
  127. package/dist/collection/components/bs-button/bs-icon-button/bs-icon-button.css +21 -4
  128. package/dist/collection/components/bs-button/bs-icon-button/bs-icon-button.js +18 -4
  129. package/dist/collection/components/bs-button/bs-icon-button/bs-icon-button.stories.js +10 -0
  130. package/dist/collection/components/bs-card/bs-card.css +4 -0
  131. package/dist/collection/components/bs-chatbot-feedback/bs-chatbot-feedback.css +1 -1
  132. package/dist/collection/components/bs-chatbot-response-action/bs-chatbot-response-action.css +3 -3
  133. package/dist/collection/components/bs-checkbox/bs-checkbox.css +8 -1
  134. package/dist/collection/components/bs-checkbox/bs-checkbox.js +100 -2
  135. package/dist/collection/components/bs-chip/bs-chip-filter/bs-chip-filter.css +4 -4
  136. package/dist/collection/components/bs-chip/bs-chip-informative/bs-chip-informative.css +4 -4
  137. package/dist/collection/components/bs-chip/bs-chip-input/bs-chip-input.css +5 -5
  138. package/dist/collection/components/bs-data-table/bs-data-table.cmp.test.js +19 -0
  139. package/dist/collection/components/bs-data-table/bs-data-table.css +1 -1
  140. package/dist/collection/components/bs-data-table/bs-data-table.js +19 -5
  141. package/dist/collection/components/bs-data-table/bs-data-table.stories.js +8 -1
  142. package/dist/collection/components/bs-dialog/bs-dialog.css +5 -1
  143. package/dist/collection/components/bs-form-association.cmp.test.js +172 -0
  144. package/dist/collection/components/bs-input/bs-input.css +10 -4
  145. package/dist/collection/components/bs-input/bs-input.js +82 -4
  146. package/dist/collection/components/bs-keyboard-nav.cmp.test.js +100 -0
  147. package/dist/collection/components/bs-logo/bs-logo.cmp.test.js +52 -3
  148. package/dist/collection/components/bs-menu/bs-menu.css +4 -0
  149. package/dist/collection/components/bs-menu/bs-menu.js +33 -1
  150. package/dist/collection/components/bs-menu/bs-menu.stories.js +54 -0
  151. package/dist/collection/components/bs-progress/bs-progress.js +27 -2
  152. package/dist/collection/components/bs-radio/bs-radio.cmp.test.js +4 -10
  153. package/dist/collection/components/bs-radio/bs-radio.css +7 -1
  154. package/dist/collection/components/bs-radio/bs-radio.js +92 -14
  155. package/dist/collection/components/bs-radio/bs-radio.stories.js +1 -10
  156. package/dist/collection/components/bs-slider/bs-slider.js +68 -2
  157. package/dist/collection/components/bs-source-link/bs-source-link.css +2 -2
  158. package/dist/collection/components/bs-stepper/bs-stepper/bs-stepper.js +3 -2
  159. package/dist/collection/components/bs-stepper/bs-stepper-step/bs-stepper-step.css +3 -3
  160. package/dist/collection/components/bs-switch/bs-switch.css +10 -1
  161. package/dist/collection/components/bs-switch/bs-switch.js +69 -2
  162. package/dist/collection/components/bs-tab/bs-inline-tab/bs-inline-tab.css +2 -2
  163. package/dist/collection/components/bs-tab/bs-inline-tab/bs-inline-tab.js +47 -1
  164. package/dist/collection/components/bs-tab/bs-tab/bs-tab.css +2 -2
  165. package/dist/collection/components/bs-tab/bs-tab/bs-tab.js +47 -1
  166. package/dist/collection/components/bs-tab/bs-tabs/bs-tabs.cmp.test.js +88 -0
  167. package/dist/collection/components/bs-tab/bs-tabs/bs-tabs.js +139 -2
  168. package/dist/collection/components/bs-tab/bs-tabs/bs-tabs.stories.js +24 -0
  169. package/dist/collection/components/bs-tooltip/bs-tooltip.js +1 -1
  170. package/dist/collection/components/forms/forms.stories.js +63 -0
  171. package/dist/collection/components/ui-shell/bs-navigation-drawer/bs-navigation-drawer/bs-navigation-drawer.cmp.test.js +173 -5
  172. package/dist/collection/components/ui-shell/bs-navigation-drawer/bs-navigation-drawer/bs-navigation-drawer.css +106 -34
  173. package/dist/collection/components/ui-shell/bs-navigation-drawer/bs-navigation-drawer/bs-navigation-drawer.js +181 -5
  174. package/dist/collection/components/ui-shell/bs-navigation-drawer/bs-navigation-drawer/bs-navigation-drawer.stories.js +48 -0
  175. package/dist/collection/components/ui-shell/bs-navigation-drawer/bs-navigation-drawer-item/bs-navigation-drawer-item.js +1 -1
  176. package/dist/collection/components/ui-shell/bs-navigation-header/bs-navigation-header/bs-navigation-header.cmp.test.js +68 -0
  177. package/dist/collection/components/ui-shell/bs-navigation-header/bs-navigation-header/bs-navigation-header.css +31 -17
  178. package/dist/components/bs-accordion.js +1 -1
  179. package/dist/components/bs-ai-disclaimer.js +1 -1
  180. package/dist/components/bs-ai-greeting.js +1 -1
  181. package/dist/components/bs-ai-thinking.js +1 -1
  182. package/dist/components/bs-attachment-list.js +1 -1
  183. package/dist/components/bs-attachment.js +1 -1
  184. package/dist/components/bs-avatar.js +1 -1
  185. package/dist/components/bs-badge.js +1 -1
  186. package/dist/components/bs-breadcrumb-overflow.js +1 -1
  187. package/dist/components/bs-breadcrumb.js +1 -1
  188. package/dist/components/bs-breadcrumbs.js +1 -1
  189. package/dist/components/bs-button-skeleton.js +1 -1
  190. package/dist/components/bs-button.js +1 -1
  191. package/dist/components/bs-card.js +1 -1
  192. package/dist/components/bs-carousel.js +1 -1
  193. package/dist/components/bs-chatbot-feedback.js +1 -1
  194. package/dist/components/bs-chatbot-header.js +1 -1
  195. package/dist/components/bs-chatbot-response-action.js +1 -1
  196. package/dist/components/bs-chatbot-sources-drawer.js +1 -1
  197. package/dist/components/bs-chatbot-suggestion-button.js +1 -1
  198. package/dist/components/bs-checkbox-skeleton.js +1 -1
  199. package/dist/components/bs-checkbox.js +1 -1
  200. package/dist/components/bs-chip-filter.js +1 -1
  201. package/dist/components/bs-chip-informative.js +1 -1
  202. package/dist/components/bs-chip-input.js +1 -1
  203. package/dist/components/bs-composer-status-banner.js +1 -1
  204. package/dist/components/bs-composer.js +1 -1
  205. package/dist/components/bs-data-table.js +1 -1
  206. package/dist/components/bs-dialog.js +1 -1
  207. package/dist/components/bs-file-upload-item.js +1 -1
  208. package/dist/components/bs-file-upload.js +1 -1
  209. package/dist/components/bs-icon-button.js +1 -1
  210. package/dist/components/bs-inline-tab.js +1 -1
  211. package/dist/components/bs-input.js +1 -1
  212. package/dist/components/bs-logo.js +1 -1
  213. package/dist/components/bs-menu-item.js +1 -1
  214. package/dist/components/bs-menu.js +1 -1
  215. package/dist/components/bs-navigation-drawer-item.js +1 -1
  216. package/dist/components/bs-navigation-drawer.js +1 -1
  217. package/dist/components/bs-navigation-header.js +1 -1
  218. package/dist/components/bs-pagination.js +1 -1
  219. package/dist/components/bs-progress-linear.js +1 -1
  220. package/dist/components/bs-progress.js +1 -1
  221. package/dist/components/bs-radio.js +1 -1
  222. package/dist/components/bs-slider.js +1 -1
  223. package/dist/components/bs-snackbar.js +1 -1
  224. package/dist/components/bs-source-link.js +1 -1
  225. package/dist/components/bs-stepper-step.js +1 -1
  226. package/dist/components/bs-stepper.js +1 -1
  227. package/dist/components/bs-switch.js +1 -1
  228. package/dist/components/bs-tab.js +1 -1
  229. package/dist/components/bs-tabs.js +1 -1
  230. package/dist/components/bs-toast.js +1 -1
  231. package/dist/components/bs-tooltip.js +1 -1
  232. package/dist/components/index.js +1 -1
  233. package/dist/components/{p-LYvoWZt4.js → p-BA3c9Rom.js} +1 -1
  234. package/dist/components/{p-Dqt-Qp4W.js → p-BfEyD6Ku.js} +1 -1
  235. package/dist/components/p-BoeorHNv.js +1 -0
  236. package/dist/components/p-Buly0d5G.js +1 -0
  237. package/dist/components/p-CpUHnsq9.js +1 -0
  238. package/dist/components/{p-BxFJ74fI.js → p-EtXc94lJ.js} +1 -1
  239. package/dist/components/{p-mnGJPH85.js → p-JYlmcxBn.js} +1 -1
  240. package/dist/components/{p-BhvV55-6.js → p-R2MlkUzD.js} +1 -1
  241. package/dist/components/{p-Dx8gAOVC.js → p-wei0Ija2.js} +1 -1
  242. package/dist/esm/brandsync-wc.js +3 -3
  243. package/dist/esm/bs-accordion.entry.js +2 -2
  244. package/dist/esm/bs-ai-disclaimer.entry.js +1 -1
  245. package/dist/esm/bs-ai-greeting.entry.js +1 -1
  246. package/dist/esm/bs-ai-thinking.entry.js +1 -1
  247. package/dist/esm/bs-attachment-list.entry.js +2 -2
  248. package/dist/esm/bs-attachment.entry.js +2 -2
  249. package/dist/esm/bs-avatar.entry.js +1 -1
  250. package/dist/esm/bs-badge.entry.js +1 -1
  251. package/dist/esm/bs-breadcrumb-overflow.entry.js +15 -3
  252. package/dist/esm/bs-breadcrumb.entry.js +16 -2
  253. package/dist/esm/bs-breadcrumbs.entry.js +1 -1
  254. package/dist/esm/bs-button-skeleton.entry.js +1 -1
  255. package/dist/esm/bs-button.entry.js +23 -4
  256. package/dist/esm/bs-card.entry.js +2 -2
  257. package/dist/esm/bs-carousel.entry.js +1 -1
  258. package/dist/esm/bs-chatbot-feedback.entry.js +2 -2
  259. package/dist/esm/bs-chatbot-header.entry.js +1 -1
  260. package/dist/esm/bs-chatbot-response-action.entry.js +2 -2
  261. package/dist/esm/bs-chatbot-sources-drawer.entry.js +1 -1
  262. package/dist/esm/bs-chatbot-suggestion-button.entry.js +1 -1
  263. package/dist/esm/bs-checkbox-skeleton.entry.js +1 -1
  264. package/dist/esm/bs-checkbox.entry.js +48 -3
  265. package/dist/esm/bs-chip-filter.entry.js +2 -2
  266. package/dist/esm/bs-chip-informative.entry.js +2 -2
  267. package/dist/esm/bs-chip-input.entry.js +2 -2
  268. package/dist/esm/bs-composer-status-banner.entry.js +1 -1
  269. package/dist/esm/bs-composer.entry.js +1 -1
  270. package/dist/esm/bs-data-table.entry.js +20 -6
  271. package/dist/esm/bs-dialog.entry.js +2 -2
  272. package/dist/esm/bs-file-upload-item.entry.js +1 -1
  273. package/dist/esm/bs-file-upload.entry.js +1 -1
  274. package/dist/esm/bs-icon-button.entry.js +23 -4
  275. package/dist/esm/bs-inline-tab.entry.js +11 -3
  276. package/dist/esm/bs-input.entry.js +69 -5
  277. package/dist/esm/bs-logo.entry.js +1 -1
  278. package/dist/esm/bs-menu-item.entry.js +1 -1
  279. package/dist/esm/bs-menu.entry.js +25 -3
  280. package/dist/esm/bs-navigation-drawer-item.entry.js +2 -2
  281. package/dist/esm/bs-navigation-drawer.entry.js +119 -6
  282. package/dist/esm/bs-navigation-header.entry.js +2 -2
  283. package/dist/esm/bs-pagination.entry.js +1 -1
  284. package/dist/esm/bs-progress-linear.entry.js +1 -1
  285. package/dist/esm/bs-progress.entry.js +8 -3
  286. package/dist/esm/bs-radio.entry.js +81 -12
  287. package/dist/esm/bs-slider.entry.js +54 -2
  288. package/dist/esm/bs-snackbar.entry.js +1 -1
  289. package/dist/esm/bs-source-link.entry.js +2 -2
  290. package/dist/esm/bs-stepper-step.entry.js +2 -2
  291. package/dist/esm/bs-stepper.entry.js +3 -2
  292. package/dist/esm/bs-switch.entry.js +36 -3
  293. package/dist/esm/bs-tab.entry.js +11 -3
  294. package/dist/esm/bs-tabs.entry.js +97 -3
  295. package/dist/esm/bs-toast.entry.js +1 -1
  296. package/dist/esm/bs-tooltip.entry.js +2 -2
  297. package/dist/esm/{index-DuyFft7h.js → index-AgoOSYvW.js} +43 -5
  298. package/dist/esm/loader.js +3 -3
  299. package/dist/types/components/bs-a11y.cmp.test.d.ts +1 -0
  300. package/dist/types/components/bs-breadcrumb/bs-breadcrumb/bs-breadcrumb.d.ts +10 -0
  301. package/dist/types/components/bs-breadcrumb/bs-breadcrumb-overflow/bs-breadcrumb-overflow.d.ts +8 -0
  302. package/dist/types/components/bs-button/bs-button/bs-button.d.ts +4 -1
  303. package/dist/types/components/bs-button/bs-icon-button/bs-icon-button.d.ts +6 -2
  304. package/dist/types/components/bs-button/bs-icon-button/bs-icon-button.stories.d.ts +1 -0
  305. package/dist/types/components/bs-checkbox/bs-checkbox.d.ts +12 -0
  306. package/dist/types/components/bs-data-table/bs-data-table.d.ts +16 -2
  307. package/dist/types/components/bs-form-association.cmp.test.d.ts +1 -0
  308. package/dist/types/components/bs-input/bs-input.d.ts +12 -0
  309. package/dist/types/components/bs-keyboard-nav.cmp.test.d.ts +1 -0
  310. package/dist/types/components/bs-menu/bs-menu.d.ts +4 -0
  311. package/dist/types/components/bs-menu/bs-menu.stories.d.ts +1 -0
  312. package/dist/types/components/bs-progress/bs-progress.d.ts +5 -0
  313. package/dist/types/components/bs-radio/bs-radio.d.ts +23 -9
  314. package/dist/types/components/bs-slider/bs-slider.d.ts +9 -0
  315. package/dist/types/components/bs-switch/bs-switch.d.ts +10 -0
  316. package/dist/types/components/bs-tab/bs-inline-tab/bs-inline-tab.d.ts +8 -0
  317. package/dist/types/components/bs-tab/bs-tab/bs-tab.d.ts +8 -0
  318. package/dist/types/components/bs-tab/bs-tabs/bs-tabs.d.ts +24 -0
  319. package/dist/types/components/bs-tab/bs-tabs/bs-tabs.stories.d.ts +1 -0
  320. package/dist/types/components/forms/forms.stories.d.ts +6 -0
  321. package/dist/types/components/ui-shell/bs-navigation-drawer/bs-navigation-drawer/bs-navigation-drawer.d.ts +50 -1
  322. package/dist/types/components/ui-shell/bs-navigation-drawer/bs-navigation-drawer/bs-navigation-drawer.stories.d.ts +2 -0
  323. package/dist/types/components.d.ts +271 -9
  324. package/package.json +1 -1
  325. package/readme.md +14 -0
  326. package/dist/brandsync-wc/p-18021c05.entry.js +0 -1
  327. package/dist/brandsync-wc/p-1c8160c2.entry.js +0 -1
  328. package/dist/brandsync-wc/p-21c14465.entry.js +0 -1
  329. package/dist/brandsync-wc/p-27100489.entry.js +0 -1
  330. package/dist/brandsync-wc/p-309f920e.entry.js +0 -1
  331. package/dist/brandsync-wc/p-30d6a6d0.entry.js +0 -1
  332. package/dist/brandsync-wc/p-387ed85f.entry.js +0 -1
  333. package/dist/brandsync-wc/p-4b0938a5.entry.js +0 -1
  334. package/dist/brandsync-wc/p-5312b6a5.entry.js +0 -1
  335. package/dist/brandsync-wc/p-70e035ed.entry.js +0 -1
  336. package/dist/brandsync-wc/p-777a9dbf.entry.js +0 -1
  337. package/dist/brandsync-wc/p-a96856fd.entry.js +0 -1
  338. package/dist/brandsync-wc/p-b0634051.entry.js +0 -1
  339. package/dist/brandsync-wc/p-bcee3d60.entry.js +0 -1
  340. package/dist/brandsync-wc/p-d03eba2b.entry.js +0 -1
  341. package/dist/brandsync-wc/p-e61efe4d.entry.js +0 -1
  342. package/dist/brandsync-wc/p-f14bda01.entry.js +0 -1
  343. package/dist/components/p-BaxFLlKS.js +0 -1
  344. package/dist/components/p-DI5GgSqL.js +0 -1
  345. package/dist/components/p-v4T0qPVn.js +0 -1
@@ -70,7 +70,7 @@
70
70
  .bs-dialog__close--floating {
71
71
  position: absolute;
72
72
  top: var(--bs-spacing-200);
73
- right: var(--bs-spacing-200);
73
+ inset-inline-end: var(--bs-spacing-200);
74
74
  z-index: 1;
75
75
  }
76
76
 
@@ -128,3 +128,7 @@
128
128
  justify-content: center;
129
129
  text-align: center;
130
130
  }
131
+
132
+ @media (forced-colors: active) {
133
+ .bs-dialog__dialog { border: 1px solid CanvasText; }
134
+ }
@@ -0,0 +1,172 @@
1
+ import { render, h, describe, it, expect } from "@stencil/vitest";
2
+ // Cross-component coverage for native <form> participation (FormData, validation, reset) and the
3
+ // radio group keyboard pattern. Lives beside the components, not in one of them, since it exercises
4
+ // several together inside a real <form>.
5
+ async function renderForm(children) {
6
+ const { root, waitForChanges } = await render(h("form", null, children));
7
+ return { form: root, waitForChanges };
8
+ }
9
+ describe('form association', () => {
10
+ it('bs-input submits its value under name', async () => {
11
+ const { form, waitForChanges } = await renderForm(h("bs-input", { name: "email", value: "a@b.co" }));
12
+ await waitForChanges();
13
+ expect(new FormData(form).get('email')).toBe('a@b.co');
14
+ });
15
+ it('bs-input updates FormData as the user types, and resets with the form', async () => {
16
+ const { form, waitForChanges } = await renderForm(h("bs-input", { name: "q", value: "start" }));
17
+ const input = form.querySelector('bs-input').shadowRoot.querySelector('input');
18
+ input.value = 'typed';
19
+ input.dispatchEvent(new InputEvent('input', { bubbles: true, composed: true }));
20
+ await waitForChanges();
21
+ expect(new FormData(form).get('q')).toBe('typed');
22
+ form.reset();
23
+ await waitForChanges();
24
+ expect(new FormData(form).get('q')).toBe('start');
25
+ });
26
+ it('a required, empty bs-input makes the form invalid', async () => {
27
+ const { form, waitForChanges } = await renderForm(h("bs-input", { name: "n", required: true }));
28
+ await waitForChanges();
29
+ expect(form.checkValidity()).toBe(false);
30
+ });
31
+ it('bs-checkbox and bs-switch submit only while checked', async () => {
32
+ const { form, waitForChanges } = await renderForm(h("div", null, h("bs-checkbox", { name: "terms", value: "yes" }), h("bs-switch", { name: "alerts", checked: true })));
33
+ await waitForChanges();
34
+ expect(new FormData(form).get('terms')).toBeNull();
35
+ expect(new FormData(form).get('alerts')).toBe('on');
36
+ form.querySelector('bs-checkbox').shadowRoot.querySelector('input').click();
37
+ await waitForChanges();
38
+ expect(new FormData(form).get('terms')).toBe('yes');
39
+ form.reset();
40
+ await waitForChanges();
41
+ expect(new FormData(form).get('terms')).toBeNull();
42
+ });
43
+ it('a required, unchecked bs-checkbox makes the form invalid', async () => {
44
+ const { form, waitForChanges } = await renderForm(h("bs-checkbox", { name: "t", required: true }));
45
+ await waitForChanges();
46
+ expect(form.checkValidity()).toBe(false);
47
+ });
48
+ });
49
+ describe('bs-radio group', () => {
50
+ const group = () => (h("div", null, h("bs-radio", { name: "fruit", value: "a" }), h("bs-radio", { name: "fruit", value: "b" }), h("bs-radio", { name: "fruit", value: "c", disabled: true })));
51
+ const inputOf = (r) => r.shadowRoot.querySelector('input');
52
+ it('checking one unchecks the others and submits its value', async () => {
53
+ const { form, waitForChanges } = await renderForm(group());
54
+ const [a, b] = Array.from(form.querySelectorAll('bs-radio'));
55
+ inputOf(a).click();
56
+ await waitForChanges();
57
+ inputOf(b).click();
58
+ await waitForChanges();
59
+ expect(a.checked).toBe(false);
60
+ expect(b.checked).toBe(true);
61
+ expect(new FormData(form).get('fruit')).toBe('b');
62
+ });
63
+ it('arrow keys move selection to the next enabled radio, wrapping', async () => {
64
+ const { form, waitForChanges } = await renderForm(group());
65
+ const [a, b] = Array.from(form.querySelectorAll('bs-radio'));
66
+ inputOf(a).click();
67
+ await waitForChanges();
68
+ inputOf(a).dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowDown', bubbles: true, composed: true, cancelable: true }));
69
+ await waitForChanges();
70
+ expect(b.checked).toBe(true);
71
+ inputOf(b).dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowRight', bubbles: true, composed: true, cancelable: true }));
72
+ await waitForChanges();
73
+ expect(a.checked).toBe(true); // skipped the disabled third radio and wrapped
74
+ });
75
+ it('only the checked radio is in the tab order once the group has a selection', async () => {
76
+ const { form, waitForChanges } = await renderForm(group());
77
+ const [a, b] = Array.from(form.querySelectorAll('bs-radio'));
78
+ inputOf(a).click();
79
+ await waitForChanges();
80
+ expect(inputOf(a).tabIndex).toBe(0);
81
+ expect(inputOf(b).tabIndex).toBe(-1);
82
+ });
83
+ });
84
+ describe('bs-button / bs-icon-button inside a form', () => {
85
+ const click = (el) => el.shadowRoot.querySelector('button').click();
86
+ it('type="submit" submits the surrounding form (and runs validation first)', async () => {
87
+ let submits = 0;
88
+ const { root, waitForChanges } = await render(h("form", { onSubmit: (e) => { e.preventDefault(); submits++; } }, h("bs-input", { name: "n", required: true }), h("bs-button", { type: "submit" }, "Go"), h("bs-icon-button", { type: "submit", ariaLabel: "Go" }, "x")));
89
+ const form = root;
90
+ await waitForChanges();
91
+ click(form.querySelector('bs-button'));
92
+ click(form.querySelector('bs-icon-button'));
93
+ expect(submits).toBe(0); // required field empty -> blocked by validation
94
+ form.querySelector('bs-input').value = 'x';
95
+ await waitForChanges();
96
+ click(form.querySelector('bs-button'));
97
+ click(form.querySelector('bs-icon-button'));
98
+ expect(submits).toBe(2);
99
+ });
100
+ it('type="reset" resets the form; type="button" does neither', async () => {
101
+ let submits = 0;
102
+ const { root, waitForChanges } = await render(h("form", { onSubmit: (e) => { e.preventDefault(); submits++; } }, h("bs-input", { name: "q", value: "start" }), h("bs-button", { type: "reset" }, "Reset"), h("bs-button", null, "Plain")));
103
+ const form = root;
104
+ await waitForChanges();
105
+ form.querySelector('bs-input').value = 'changed';
106
+ await waitForChanges();
107
+ click(form.querySelectorAll('bs-button')[1]);
108
+ expect(submits).toBe(0);
109
+ expect(new FormData(form).get('q')).toBe('changed');
110
+ click(form.querySelectorAll('bs-button')[0]);
111
+ await waitForChanges();
112
+ expect(new FormData(form).get('q')).toBe('start');
113
+ });
114
+ });
115
+ // The Angular ControlValueAccessors and Vue v-model bindings (generated in stencil.config.ts) read
116
+ // `event.target.value` / `.checked` straight off the host inside the `bsChange` handler. That only
117
+ // works if the host property is already updated when `bsChange` fires -- pin that contract here.
118
+ describe('bsChange framework-binding contract', () => {
119
+ it('bs-input: host.value is already the new value inside bsChange', async () => {
120
+ const { root, waitForChanges } = await render(h("bs-input", null));
121
+ const seen = [];
122
+ root.addEventListener('bsChange', (e) => seen.push(e.target.value));
123
+ const input = root.shadowRoot.querySelector('input');
124
+ input.value = 'hello';
125
+ input.dispatchEvent(new Event('change', { bubbles: true }));
126
+ await waitForChanges();
127
+ expect(seen).toEqual(['hello']);
128
+ });
129
+ it('bs-checkbox and bs-switch: host.checked is already updated inside bsChange', async () => {
130
+ const { root, waitForChanges } = await render(h("div", null, h("bs-checkbox", null), h("bs-switch", null)));
131
+ const seen = [];
132
+ root.addEventListener('bsChange', (e) => seen.push(e.target.checked));
133
+ root.querySelector('bs-checkbox').shadowRoot.querySelector('input').click();
134
+ root.querySelector('bs-switch').shadowRoot.querySelector('input').click();
135
+ await waitForChanges();
136
+ expect(seen).toEqual([true, true]);
137
+ });
138
+ it('bs-slider: host.value is already updated inside bsChange', async () => {
139
+ const { root, waitForChanges } = await render(h("bs-slider", { value: 10 }));
140
+ const seen = [];
141
+ root.addEventListener('bsChange', (e) => seen.push(e.target.value));
142
+ const range = root.shadowRoot.querySelector('input[type="range"]');
143
+ range.value = '55';
144
+ range.dispatchEvent(new Event('input', { bubbles: true }));
145
+ range.dispatchEvent(new Event('change', { bubbles: true }));
146
+ await waitForChanges();
147
+ expect(seen.length).toBeGreaterThan(0);
148
+ expect(seen[seen.length - 1]).toBe(55);
149
+ });
150
+ });
151
+ const keysOf = (f) => {
152
+ const keys = [];
153
+ new FormData(f).forEach((_v, k) => keys.push(k));
154
+ return keys;
155
+ };
156
+ describe('disabled controls', () => {
157
+ it('a disabled control is excluded from FormData and validation, like a native disabled input', async () => {
158
+ const { root, waitForChanges } = await render(h("form", null, h("bs-input", { name: "i", value: "x", required: true, disabled: true }), h("bs-checkbox", { name: "c", checked: true, disabled: true }), h("bs-switch", { name: "s", checked: true, disabled: true }), h("bs-radio", { name: "r", value: "a", checked: true, disabled: true }), h("bs-slider", { name: "v", value: 20, disabled: true })));
159
+ const form = root;
160
+ await waitForChanges();
161
+ expect(keysOf(form)).toEqual([]);
162
+ expect(form.checkValidity()).toBe(true);
163
+ Array.from(form.querySelectorAll('bs-input, bs-checkbox, bs-switch, bs-radio, bs-slider')).forEach(el => (el.disabled = false));
164
+ await waitForChanges();
165
+ expect(keysOf(form).sort()).toEqual(['c', 'i', 'r', 's', 'v']);
166
+ });
167
+ it('a control inside <fieldset disabled> is excluded from FormData', async () => {
168
+ const { root, waitForChanges } = await render(h("form", null, h("fieldset", { disabled: true }, h("bs-input", { name: "fs", value: "x" }))));
169
+ await waitForChanges();
170
+ expect(keysOf(root)).toEqual([]);
171
+ });
172
+ });
@@ -84,7 +84,7 @@
84
84
 
85
85
  .bs-input__required {
86
86
  color: var(--bs-input-error-color);
87
- margin-left: 2px;
87
+ margin-inline-start: 2px;
88
88
  }
89
89
 
90
90
  .bs-input__field {
@@ -148,7 +148,7 @@
148
148
  visibility: hidden;
149
149
  pointer-events: none;
150
150
  position: absolute;
151
- right: 0;
151
+ inset-inline-end: 0;
152
152
  }
153
153
 
154
154
  .bs-input__control::-webkit-textfield-decoration-container {
@@ -282,8 +282,8 @@
282
282
  .bs-input__dropdown-menu {
283
283
  position: absolute;
284
284
  top: calc(100% + var(--bs-input-stack-gap));
285
- left: 0;
286
- right: 0;
285
+ inset-inline-start: 0;
286
+ inset-inline-end: 0;
287
287
  z-index: 1;
288
288
  }
289
289
 
@@ -450,3 +450,9 @@
450
450
  .bs-input__field--pin.bs-input__field--error .bs-input__pin-cell {
451
451
  border-color: var(--bs-input-field-border-error);
452
452
  }
453
+
454
+ /* Windows High Contrast: keep the field boundary visible. */
455
+ @media (forced-colors: active) {
456
+ .bs-input__control { border: 1px solid FieldText; }
457
+ .bs-input__control:focus-visible { outline: 2px solid Highlight; outline-offset: 2px; }
458
+ }
@@ -49,6 +49,10 @@ import { h } from "@stencil/core";
49
49
  // comments (see stencil.js's parseStyleDocs/parseCssComment), not the class-level JSDoc.
50
50
  export class BsInput {
51
51
  el;
52
+ internals;
53
+ initialValue = '';
54
+ /** The `name` the value is submitted under in a surrounding `<form>`'s `FormData`. */
55
+ name;
52
56
  /** Current value. Native `input`/`change` events don't cross the Shadow DOM boundary, so this
53
57
  * component re-dispatches them as `bsInput`/`bsChange` custom events instead. Mutable so the
54
58
  * `number` type's stepper buttons can update it directly. */
@@ -124,9 +128,44 @@ export class BsInput {
124
128
  * children, before first render -- see `bs-button`'s `componentWillLoad` for why `slotchange`
125
129
  * alone isn't enough for a slot that starts (and stays) empty. */
126
130
  componentWillLoad() {
131
+ this.initialValue = this.value;
132
+ this.syncFormValue();
127
133
  this.hasIcon = this.hasSlottedContent('icon');
128
134
  this.hasEndIcon = this.hasSlottedContent('end-icon');
129
135
  }
136
+ onFormStateChange() {
137
+ this.syncFormValue();
138
+ }
139
+ /** Pushes the current value + validity to the surrounding form. `chip` submits one entry per
140
+ * chip under `name`; every other type submits `value` as a single string. */
141
+ syncFormValue() {
142
+ if (!this.internals?.setFormValue)
143
+ return;
144
+ if (this.type === 'chip' && this.name) {
145
+ const data = new FormData();
146
+ this.chips.forEach(c => data.append(this.name, c));
147
+ this.internals.setFormValue(data);
148
+ }
149
+ else {
150
+ this.internals.setFormValue(this.value ?? '');
151
+ }
152
+ const empty = this.type === 'chip' ? this.chips.length === 0 : !this.value;
153
+ if (this.required && empty) {
154
+ this.internals.setValidity({ valueMissing: true }, 'Please fill out this field.');
155
+ }
156
+ else {
157
+ this.internals.setValidity({});
158
+ }
159
+ }
160
+ /** Called by the browser when the surrounding `<form>` is reset. */
161
+ formResetCallback() {
162
+ this.value = this.initialValue;
163
+ }
164
+ /** Called when the browser restores form state (back/forward navigation, autofill). */
165
+ formStateRestoreCallback(state) {
166
+ if (typeof state === 'string')
167
+ this.value = state;
168
+ }
130
169
  hasSlottedContent(slotName) {
131
170
  return Array.from(this.el.childNodes).some(node => node.nodeType === Node.ELEMENT_NODE && node.getAttribute('slot') === slotName);
132
171
  }
@@ -138,10 +177,12 @@ export class BsInput {
138
177
  };
139
178
  onInput = (ev) => {
140
179
  const value = ev.target.value;
180
+ this.value = value;
141
181
  this.bsInput.emit(value);
142
182
  };
143
183
  onChange = (ev) => {
144
184
  const value = ev.target.value;
185
+ this.value = value;
145
186
  this.bsChange.emit(value);
146
187
  };
147
188
  clampNumber(n) {
@@ -236,7 +277,8 @@ export class BsInput {
236
277
  if (value && index < this.length - 1) {
237
278
  this.pinInputs[index + 1]?.focus();
238
279
  }
239
- this.bsChange.emit(this.pinInputs.map(i => i?.value ?? '').join(''));
280
+ this.value = this.pinInputs.map(i => i?.value ?? '').join('');
281
+ this.bsChange.emit(this.value);
240
282
  };
241
283
  onPinKeydown = (index) => (ev) => {
242
284
  if (ev.key === 'Backspace' && !ev.target.value && index > 0) {
@@ -341,14 +383,15 @@ export class BsInput {
341
383
  return (h("div", { part: "field", class: `bs-input__field bs-input__field--pin ${errorClass} ${disabledClass}` }, Array.from({ length: this.length }).map((_, i) => (h("input", { id: i === 0 ? 'control' : undefined, ref: el => (this.pinInputs[i] = el), part: "control", class: "bs-input__pin-cell", type: "text", inputMode: "numeric", maxLength: 1, value: this.value[i] ?? '', disabled: this.disabled, "aria-required": this.required ? 'true' : undefined, onInput: this.onPinInput(i), onKeyDown: this.onPinKeydown(i) })))));
342
384
  }
343
385
  render() {
344
- return (h("div", { key: 'd65ab3191cd18c77385ffbb8b827e6161dafceaf', class: `bs-input ${this.error ? 'bs-input--error' : ''}` }, this.label && (
386
+ return (h("div", { key: '1149cfe8eaa6085007a8d9a963b6c909bb6cda13', class: `bs-input ${this.error ? 'bs-input--error' : ''}` }, this.label && (
345
387
  // "control" is a fixed id, not a generated one -- safe because Shadow DOM scopes ids
346
388
  // to this instance's own shadow root, so it can never collide with another bs-input.
347
- h("label", { key: '762c10bb8afcd1f0609ba75b0d6d8162c483b5b5', part: "label", class: "bs-input__label", htmlFor: "control" }, this.label, this.required && (h("span", { key: '9a74743816c07b81b4db39616cee80ef69d60ca1', part: "required", class: "bs-input__required", "aria-hidden": "true" }, "*")))), this.type === 'pin' ? this.renderPinField() : this.type === 'initials' ? this.renderInitialsField() : this.renderField(), this.error ? (h("span", { id: "description-or-error", part: "error", class: "bs-input__error" }, h("svg", { part: "error-icon", class: "bs-input__error-icon", viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true" }, h("circle", { cx: "8", cy: "8", r: "6.5", stroke: "currentColor", "stroke-width": "1.2" }), h("path", { d: "M8 5V8.5", stroke: "currentColor", "stroke-width": "1.2", "stroke-linecap": "round" }), h("circle", { cx: "8", cy: "11", r: "0.75", fill: "currentColor" })), this.error)) : this.description ? (h("span", { id: "description-or-error", part: "description", class: "bs-input__description" }, this.description)) : null));
389
+ h("label", { key: 'd737018c1e1ebcde529710d8ea58c6bed76f2abf', part: "label", class: "bs-input__label", htmlFor: "control" }, this.label, this.required && (h("span", { key: '5993b19cbfcb8725550c1292c00795c8463e554c', part: "required", class: "bs-input__required", "aria-hidden": "true" }, "*")))), this.type === 'pin' ? this.renderPinField() : this.type === 'initials' ? this.renderInitialsField() : this.renderField(), this.error ? (h("span", { id: "description-or-error", part: "error", class: "bs-input__error" }, h("svg", { part: "error-icon", class: "bs-input__error-icon", viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true" }, h("circle", { cx: "8", cy: "8", r: "6.5", stroke: "currentColor", "stroke-width": "1.2" }), h("path", { d: "M8 5V8.5", stroke: "currentColor", "stroke-width": "1.2", "stroke-linecap": "round" }), h("circle", { cx: "8", cy: "11", r: "0.75", fill: "currentColor" })), this.error)) : this.description ? (h("span", { id: "description-or-error", part: "description", class: "bs-input__description" }, this.description)) : null));
348
390
  }
349
391
  static get is() { return "bs-input"; }
350
392
  static get encapsulation() { return "shadow"; }
351
393
  static get delegatesFocus() { return true; }
394
+ static get formAssociated() { return true; }
352
395
  static get originalStyleUrls() {
353
396
  return {
354
397
  "$": ["bs-input.css"]
@@ -361,6 +404,25 @@ export class BsInput {
361
404
  }
362
405
  static get properties() {
363
406
  return {
407
+ "name": {
408
+ "type": "string",
409
+ "mutable": false,
410
+ "complexType": {
411
+ "original": "string",
412
+ "resolved": "string",
413
+ "references": {}
414
+ },
415
+ "required": false,
416
+ "optional": true,
417
+ "docs": {
418
+ "tags": [],
419
+ "text": "The `name` the value is submitted under in a surrounding `<form>`'s `FormData`."
420
+ },
421
+ "getter": false,
422
+ "setter": false,
423
+ "reflect": true,
424
+ "attribute": "name"
425
+ },
364
426
  "value": {
365
427
  "type": "string",
366
428
  "mutable": true,
@@ -493,7 +555,7 @@ export class BsInput {
493
555
  },
494
556
  "getter": false,
495
557
  "setter": false,
496
- "reflect": false,
558
+ "reflect": true,
497
559
  "attribute": "disabled",
498
560
  "defaultValue": "false"
499
561
  },
@@ -866,6 +928,21 @@ export class BsInput {
866
928
  }];
867
929
  }
868
930
  static get elementRef() { return "el"; }
931
+ static get watchers() {
932
+ return [{
933
+ "propName": "value",
934
+ "methodName": "onFormStateChange"
935
+ }, {
936
+ "propName": "type",
937
+ "methodName": "onFormStateChange"
938
+ }, {
939
+ "propName": "chips",
940
+ "methodName": "onFormStateChange"
941
+ }, {
942
+ "propName": "required",
943
+ "methodName": "onFormStateChange"
944
+ }];
945
+ }
869
946
  static get listeners() {
870
947
  return [{
871
948
  "name": "keydown",
@@ -881,4 +958,5 @@ export class BsInput {
881
958
  "passive": false
882
959
  }];
883
960
  }
961
+ static get attachInternalsMemberName() { return "internals"; }
884
962
  }
@@ -0,0 +1,100 @@
1
+ import { render, h, describe, it, expect } from "@stencil/vitest";
2
+ // Cross-component coverage for WAI-ARIA keyboard patterns (tabs, menu) and slider form submission.
3
+ const key = (el, k) => el.dispatchEvent(new KeyboardEvent('keydown', { key: k, bubbles: true, composed: true, cancelable: true }));
4
+ const btn = (el) => el.shadowRoot.querySelector('button');
5
+ describe('bs-tabs keyboard', () => {
6
+ const tabs = (orientation = 'horizontal') => (h("bs-tabs", { orientation: orientation }, h("bs-tab", { selected: true }, "One"), h("bs-tab", null, "Two"), h("bs-tab", { disabled: true }, "Three"), h("bs-tab", null, "Four")));
7
+ it('roving tabindex: only the selected tab is tabbable', async () => {
8
+ const { root, waitForChanges } = await render(tabs());
9
+ await waitForChanges();
10
+ const [a, b] = Array.from(root.querySelectorAll('bs-tab'));
11
+ expect(btn(a).tabIndex).toBe(0);
12
+ expect(btn(b).tabIndex).toBe(-1);
13
+ });
14
+ it('ArrowRight selects the next enabled tab (skipping disabled) and wraps', async () => {
15
+ const { root, waitForChanges } = await render(tabs());
16
+ const els = Array.from(root.querySelectorAll('bs-tab'));
17
+ key(btn(els[0]), 'ArrowRight');
18
+ await waitForChanges();
19
+ expect(els[1].selected).toBe(true);
20
+ key(btn(els[1]), 'ArrowRight');
21
+ await waitForChanges();
22
+ expect(els[3].selected).toBe(true);
23
+ key(btn(els[3]), 'ArrowRight');
24
+ await waitForChanges();
25
+ expect(els[0].selected).toBe(true);
26
+ expect(btn(els[0]).tabIndex).toBe(0);
27
+ expect(btn(els[3]).tabIndex).toBe(-1);
28
+ });
29
+ it('Home/End jump to first/last enabled tab', async () => {
30
+ const { root, waitForChanges } = await render(tabs());
31
+ const els = Array.from(root.querySelectorAll('bs-tab'));
32
+ key(btn(els[0]), 'End');
33
+ await waitForChanges();
34
+ expect(els[3].selected).toBe(true);
35
+ key(btn(els[3]), 'Home');
36
+ await waitForChanges();
37
+ expect(els[0].selected).toBe(true);
38
+ });
39
+ it('vertical orientation uses Up/Down and ignores Left/Right', async () => {
40
+ const { root, waitForChanges } = await render(tabs('vertical'));
41
+ const els = Array.from(root.querySelectorAll('bs-tab'));
42
+ key(btn(els[0]), 'ArrowRight');
43
+ await waitForChanges();
44
+ expect(els[0].selected).toBe(true);
45
+ key(btn(els[0]), 'ArrowDown');
46
+ await waitForChanges();
47
+ expect(els[1].selected).toBe(true);
48
+ });
49
+ it('with nothing selected, the first enabled tab is the tab stop', async () => {
50
+ const { root, waitForChanges } = await render(h("bs-tabs", null, h("bs-tab", { disabled: true }, "A"), h("bs-tab", null, "B"), h("bs-tab", null, "C")));
51
+ await waitForChanges();
52
+ const els = Array.from(root.querySelectorAll('bs-tab'));
53
+ expect(btn(els[1]).tabIndex).toBe(0);
54
+ expect(btn(els[2]).tabIndex).toBe(-1);
55
+ });
56
+ });
57
+ describe('bs-menu keyboard', () => {
58
+ const menu = () => (h("bs-menu", null, h("bs-menu-item", null, "Edit"), h("bs-menu-item", { disabled: true }, "Copy"), h("bs-menu-item", null, "Delete")));
59
+ it('ArrowDown/ArrowUp move focus between enabled items, wrapping', async () => {
60
+ const { root, waitForChanges } = await render(menu());
61
+ const [a, , c] = Array.from(root.querySelectorAll('bs-menu-item'));
62
+ btn(a).focus();
63
+ key(btn(a), 'ArrowDown');
64
+ await waitForChanges();
65
+ expect(c.shadowRoot.activeElement).toBe(btn(c));
66
+ key(btn(c), 'ArrowDown');
67
+ expect(a.shadowRoot.activeElement).toBe(btn(a));
68
+ key(btn(a), 'ArrowUp');
69
+ expect(c.shadowRoot.activeElement).toBe(btn(c));
70
+ });
71
+ it('Home/End jump to first/last enabled item', async () => {
72
+ const { root } = await render(menu());
73
+ const [a, , c] = Array.from(root.querySelectorAll('bs-menu-item'));
74
+ btn(a).focus();
75
+ key(btn(a), 'End');
76
+ expect(c.shadowRoot.activeElement).toBe(btn(c));
77
+ key(btn(c), 'Home');
78
+ expect(a.shadowRoot.activeElement).toBe(btn(a));
79
+ });
80
+ });
81
+ describe('bs-slider form association', () => {
82
+ it('submits its value under name and resets with the form', async () => {
83
+ const { root, waitForChanges } = await render(h("form", null, h("bs-slider", { name: "vol", value: 30 })));
84
+ const form = root;
85
+ await waitForChanges();
86
+ expect(new FormData(form).get('vol')).toBe('30');
87
+ const slider = form.querySelector('bs-slider');
88
+ slider.value = 70;
89
+ await waitForChanges();
90
+ expect(new FormData(form).get('vol')).toBe('70');
91
+ form.reset();
92
+ await waitForChanges();
93
+ expect(new FormData(form).get('vol')).toBe('30');
94
+ });
95
+ it('range type submits start then end under the same name', async () => {
96
+ const { root, waitForChanges } = await render(h("form", null, h("bs-slider", { name: "price", type: "range", valueStart: 10, valueEnd: 90 })));
97
+ await waitForChanges();
98
+ expect(new FormData(root).getAll('price')).toEqual(['10', '90']);
99
+ });
100
+ });
@@ -1,4 +1,5 @@
1
1
  import { render, h, describe, it, expect } from "@stencil/vitest";
2
+ import { vi } from "vitest";
2
3
  describe('bs-logo', () => {
3
4
  it('renders role="img" and aria-label="BrandSync"', async () => {
4
5
  const { root } = await render(h("bs-logo", null));
@@ -37,9 +38,9 @@ describe('bs-logo', () => {
37
38
  expect(getComputedStyle(darkAsset).display).toBe('none');
38
39
  });
39
40
  it('shows the dark asset and hides the light one when an ambient dark theme sets --bs-logo-asset-*-display', async () => {
40
- // Simulates what src/global/base.css's [data-theme="dark"] rule sets on <html> in a real
41
- // app -- setting the same custom properties directly on the render stage container here,
42
- // since this isolated component test doesn't load that global stylesheet. CSS custom
41
+ // Simulates what src/global/base.css's [data-theme="dark"] rule sets, by setting the same
42
+ // custom properties directly on the render stage container. (The real selector is exercised
43
+ // in the "follows the real [data-theme="dark"] attribute" tests below.) CSS custom
43
44
  // properties inherit through the shadow boundary regardless of where they're defined.
44
45
  const { root } = await render(h("bs-logo", null), {
45
46
  stageAttrs: { style: '--bs-logo-asset-light-display: none; --bs-logo-asset-dark-display: block;' },
@@ -50,6 +51,54 @@ describe('bs-logo', () => {
50
51
  expect(getComputedStyle(darkAsset).display).not.toBe('none');
51
52
  });
52
53
  });
54
+ // The tests above set the --bs-logo-asset-*-display variables by hand. These exercise the real
55
+ // `[data-theme="dark"]` rule from src/global/base.css (loaded by vitest-setup.ts), i.e. what a
56
+ // consuming app actually does -- including WHERE the attribute may sit (issue: dark logo on a dark
57
+ // theme).
58
+ describe('background="auto" follows the real [data-theme="dark"] attribute', () => {
59
+ const shown = (root) => ({
60
+ light: getComputedStyle(root.shadowRoot.querySelector('.bs-logo__asset--light')).display !== 'none',
61
+ dark: getComputedStyle(root.shadowRoot.querySelector('.bs-logo__asset--dark')).display !== 'none',
62
+ });
63
+ it('flips to the dark asset when data-theme="dark" is on <html>', async () => {
64
+ document.documentElement.setAttribute('data-theme', 'dark');
65
+ try {
66
+ const { root } = await render(h("bs-logo", null));
67
+ expect(shown(root)).toEqual({ light: false, dark: true });
68
+ }
69
+ finally {
70
+ document.documentElement.removeAttribute('data-theme');
71
+ }
72
+ });
73
+ it('flips to the dark asset when data-theme="dark" is on <body>', async () => {
74
+ document.body.setAttribute('data-theme', 'dark');
75
+ try {
76
+ const { root } = await render(h("bs-logo", null));
77
+ expect(shown(root)).toEqual({ light: false, dark: true });
78
+ }
79
+ finally {
80
+ document.body.removeAttribute('data-theme');
81
+ }
82
+ });
83
+ it('flips to the dark asset when data-theme="dark" is on any ancestor wrapper', async () => {
84
+ const { root } = await render(h("div", { "data-theme": "dark" }, h("bs-logo", null)));
85
+ expect(shown(root.querySelector('bs-logo'))).toEqual({ light: false, dark: true });
86
+ });
87
+ it('does NOT flip for a logo outside the data-theme="dark" element', async () => {
88
+ const { root } = await render(h("div", null, h("div", { "data-theme": "dark" }), h("bs-logo", null)));
89
+ expect(shown(root.querySelector('bs-logo'))).toEqual({ light: true, dark: false });
90
+ });
91
+ it('does not follow prefers-color-scheme (only the data-theme attribute)', async () => {
92
+ const spy = vi.spyOn(window, 'matchMedia').mockImplementation((q) => ({ matches: q.includes('prefers-color-scheme: dark'), media: q, addEventListener: () => undefined, removeEventListener: () => undefined, addListener: () => undefined, removeListener: () => undefined, onchange: null, dispatchEvent: () => false }));
93
+ try {
94
+ const { root } = await render(h("bs-logo", null));
95
+ expect(shown(root)).toEqual({ light: true, dark: false });
96
+ }
97
+ finally {
98
+ spy.mockRestore();
99
+ }
100
+ });
101
+ });
53
102
  describe('background="light"/"dark" (explicit)', () => {
54
103
  it('pins the light asset even when an ambient dark theme is set', async () => {
55
104
  const { root } = await render(h("bs-logo", { background: "light" }), {
@@ -18,3 +18,7 @@
18
18
  box-shadow: var(--bs-menu-shadow);
19
19
  font-family: inherit;
20
20
  }
21
+
22
+ @media (forced-colors: active) {
23
+ .bs-menu { border: 1px solid CanvasText; }
24
+ }
@@ -21,8 +21,30 @@ import { h } from "@stencil/core";
21
21
  * @prop --bs-menu-shadow - Elevation shadow of the menu box. Aliased to `--bs-shadow-sm`.
22
22
  */
23
23
  export class BsMenu {
24
+ el;
25
+ /** WAI-ARIA menu pattern: Up/Down move focus between enabled items (wrapping), Home/End jump
26
+ * to the first/last. Items are the slotted `bs-menu-item` children. */
27
+ onKeyDown(ev) {
28
+ if (!['ArrowDown', 'ArrowUp', 'Home', 'End'].includes(ev.key))
29
+ return;
30
+ const items = Array.from(this.el.querySelectorAll('bs-menu-item')).filter(i => !i.disabled);
31
+ if (items.length === 0)
32
+ return;
33
+ const current = items.findIndex(i => i === ev.target || i.contains(ev.target));
34
+ ev.preventDefault();
35
+ let next;
36
+ if (ev.key === 'Home')
37
+ next = 0;
38
+ else if (ev.key === 'End')
39
+ next = items.length - 1;
40
+ else if (ev.key === 'ArrowDown')
41
+ next = current === -1 ? 0 : (current + 1) % items.length;
42
+ else
43
+ next = current === -1 ? items.length - 1 : (current - 1 + items.length) % items.length;
44
+ items[next].shadowRoot?.querySelector('button')?.focus();
45
+ }
24
46
  render() {
25
- return (h("div", { key: '6d24ccbadf6c68bba52b6737e91c4d131fbce331', part: "list", class: "bs-menu", role: "menu" }, h("slot", { key: '94cc6884049a7836b3438a2fc112f0a2c7a1473a' })));
47
+ return (h("div", { key: '4f2995d0f53f85656de8595fb6a9909833c6369d', part: "list", class: "bs-menu", role: "menu" }, h("slot", { key: '0824f2a784eb4cfa28a2868f19c056570b56ba63' })));
26
48
  }
27
49
  static get is() { return "bs-menu"; }
28
50
  static get encapsulation() { return "shadow"; }
@@ -36,4 +58,14 @@ export class BsMenu {
36
58
  "$": ["bs-menu.css"]
37
59
  };
38
60
  }
61
+ static get elementRef() { return "el"; }
62
+ static get listeners() {
63
+ return [{
64
+ "name": "keydown",
65
+ "method": "onKeyDown",
66
+ "target": undefined,
67
+ "capture": false,
68
+ "passive": false
69
+ }];
70
+ }
39
71
  }