@brandsync/wc 1.8.0 → 1.10.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 (280) hide show
  1. package/custom-elements.json +4493 -3458
  2. package/dist/brandsync-wc/brandsync-wc.esm.js +1 -1
  3. package/dist/brandsync-wc/{p-c4de155c.entry.js → p-0132a2d1.entry.js} +1 -1
  4. package/dist/brandsync-wc/{p-051d3064.entry.js → p-041776c0.entry.js} +1 -1
  5. package/dist/brandsync-wc/{p-a09e157f.entry.js → p-08c99a60.entry.js} +1 -1
  6. package/dist/brandsync-wc/{p-70f64b25.entry.js → p-18c3c22c.entry.js} +1 -1
  7. package/dist/brandsync-wc/p-1c3a43c7.entry.js +1 -0
  8. package/dist/brandsync-wc/{p-fddc7bd1.entry.js → p-1c427ffb.entry.js} +1 -1
  9. package/dist/brandsync-wc/p-2181378f.entry.js +1 -0
  10. package/dist/brandsync-wc/{p-29027559.entry.js → p-2e958566.entry.js} +1 -1
  11. package/dist/brandsync-wc/{p-235ae012.entry.js → p-301b2455.entry.js} +1 -1
  12. package/dist/brandsync-wc/{p-8ee0153b.entry.js → p-32cd69f1.entry.js} +1 -1
  13. package/dist/brandsync-wc/p-4f2c4929.entry.js +1 -0
  14. package/dist/brandsync-wc/{p-a0d5a620.entry.js → p-50a251a4.entry.js} +1 -1
  15. package/dist/brandsync-wc/{p-0e39b9cc.entry.js → p-5f3cd501.entry.js} +1 -1
  16. package/dist/brandsync-wc/p-701ebf4a.entry.js +1 -0
  17. package/dist/brandsync-wc/p-763876f5.entry.js +1 -0
  18. package/dist/brandsync-wc/{p-f7d47c17.entry.js → p-76e1c295.entry.js} +1 -1
  19. package/dist/brandsync-wc/p-790db8b3.entry.js +1 -0
  20. package/dist/brandsync-wc/{p-4e5dcaff.entry.js → p-796a1860.entry.js} +1 -1
  21. package/dist/brandsync-wc/p-806a5347.entry.js +1 -0
  22. package/dist/brandsync-wc/{p-6331de9c.entry.js → p-8eba7f90.entry.js} +1 -1
  23. package/dist/brandsync-wc/p-96ed9386.entry.js +1 -0
  24. package/dist/brandsync-wc/{p-cfcf3f0a.entry.js → p-9e88f19c.entry.js} +1 -1
  25. package/dist/brandsync-wc/p-9f6fe37d.entry.js +1 -0
  26. package/dist/brandsync-wc/{p-de7c946d.entry.js → p-a71d2811.entry.js} +1 -1
  27. package/dist/brandsync-wc/{p-33e44094.entry.js → p-a8e2a829.entry.js} +1 -1
  28. package/dist/brandsync-wc/p-addfa0a0.entry.js +1 -0
  29. package/dist/brandsync-wc/{p-4574a707.entry.js → p-af2bf957.entry.js} +1 -1
  30. package/dist/brandsync-wc/{p-6bf2f116.entry.js → p-b2074a32.entry.js} +1 -1
  31. package/dist/brandsync-wc/{p-03b08508.entry.js → p-c3f72584.entry.js} +1 -1
  32. package/dist/brandsync-wc/{p-7c94e6ae.entry.js → p-c99b6a66.entry.js} +1 -1
  33. package/dist/brandsync-wc/{p-2891d40b.entry.js → p-c9a72416.entry.js} +1 -1
  34. package/dist/brandsync-wc/{p-9f65f998.entry.js → p-d3f44cb7.entry.js} +1 -1
  35. package/dist/brandsync-wc/p-d42b1c2b.entry.js +1 -0
  36. package/dist/brandsync-wc/{p-3ec74d35.entry.js → p-daab6b22.entry.js} +1 -1
  37. package/dist/brandsync-wc/{p-ee7da23d.entry.js → p-dbcbe682.entry.js} +1 -1
  38. package/dist/brandsync-wc/{p-3176d1d3.entry.js → p-e8a5b8eb.entry.js} +1 -1
  39. package/dist/brandsync-wc/{p-062cfa34.entry.js → p-ea4e20ef.entry.js} +1 -1
  40. package/dist/brandsync-wc/p-f370b8fa.entry.js +1 -0
  41. package/dist/brandsync-wc/{p-05c7de28.entry.js → p-f89de457.entry.js} +1 -1
  42. package/dist/brandsync-wc/{p-114d2fd8.entry.js → p-fd254972.entry.js} +1 -1
  43. package/dist/cjs/brandsync-wc.cjs.js +1 -1
  44. package/dist/cjs/bs-ai-disclaimer.cjs.entry.js +1 -1
  45. package/dist/cjs/bs-ai-greeting.cjs.entry.js +1 -1
  46. package/dist/cjs/bs-ai-thinking.cjs.entry.js +1 -1
  47. package/dist/cjs/bs-attachment-list.cjs.entry.js +1 -1
  48. package/dist/cjs/bs-breadcrumb-overflow.cjs.entry.js +13 -1
  49. package/dist/cjs/bs-breadcrumb.cjs.entry.js +15 -1
  50. package/dist/cjs/bs-breadcrumbs.cjs.entry.js +1 -1
  51. package/dist/cjs/bs-button-skeleton.cjs.entry.js +1 -1
  52. package/dist/cjs/bs-chatbot-feedback.cjs.entry.js +1 -1
  53. package/dist/cjs/bs-chatbot-header.cjs.entry.js +1 -1
  54. package/dist/cjs/bs-chatbot-response-action.cjs.entry.js +1 -1
  55. package/dist/cjs/bs-chatbot-sources-drawer.cjs.entry.js +1 -1
  56. package/dist/cjs/bs-chatbot-suggestion-button.cjs.entry.js +1 -1
  57. package/dist/cjs/bs-checkbox-skeleton.cjs.entry.js +1 -1
  58. package/dist/cjs/bs-data-table.cjs.entry.js +18 -4
  59. package/dist/cjs/bs-datepicker.cjs.entry.js +410 -0
  60. package/dist/cjs/bs-file-upload-item.cjs.entry.js +1 -1
  61. package/dist/cjs/bs-file-upload.cjs.entry.js +1 -1
  62. package/dist/cjs/bs-icon-button.cjs.entry.js +2 -2
  63. package/dist/cjs/bs-inline-tab.cjs.entry.js +5 -1
  64. package/dist/cjs/{bs-input.cjs.entry.js → bs-input_2.cjs.entry.js} +37 -4
  65. package/dist/cjs/bs-menu.cjs.entry.js +1 -1
  66. package/dist/cjs/bs-navigation-drawer-item.cjs.entry.js +1 -1
  67. package/dist/cjs/bs-navigation-drawer.cjs.entry.js +118 -5
  68. package/dist/cjs/bs-navigation-header.cjs.entry.js +2 -2
  69. package/dist/cjs/bs-pagination.cjs.entry.js +1 -1
  70. package/dist/cjs/bs-progress-linear.cjs.entry.js +2 -2
  71. package/dist/cjs/bs-progress.cjs.entry.js +2 -2
  72. package/dist/cjs/bs-radio.cjs.entry.js +1 -1
  73. package/dist/cjs/bs-slider.cjs.entry.js +1 -1
  74. package/dist/cjs/bs-snackbar.cjs.entry.js +1 -1
  75. package/dist/cjs/bs-source-link.cjs.entry.js +2 -2
  76. package/dist/cjs/bs-stepper-step.cjs.entry.js +1 -1
  77. package/dist/cjs/bs-stepper.cjs.entry.js +1 -1
  78. package/dist/cjs/bs-switch.cjs.entry.js +1 -1
  79. package/dist/cjs/bs-tab.cjs.entry.js +5 -1
  80. package/dist/cjs/bs-tabs.cjs.entry.js +47 -2
  81. package/dist/cjs/bs-timepicker.cjs.entry.js +209 -0
  82. package/dist/cjs/bs-toast.cjs.entry.js +1 -1
  83. package/dist/cjs/bs-tooltip.cjs.entry.js +1 -1
  84. package/dist/cjs/loader.cjs.js +1 -1
  85. package/dist/collection/collection-manifest.json +2 -0
  86. package/dist/collection/components/bs-a11y.cmp.test.js +4 -0
  87. package/dist/collection/components/bs-ai-disclaimer/bs-ai-disclaimer.js +1 -1
  88. package/dist/collection/components/bs-ai-greeting/bs-ai-greeting.js +1 -1
  89. package/dist/collection/components/bs-ai-thinking/bs-ai-thinking.js +1 -1
  90. package/dist/collection/components/bs-attachment-list/bs-attachment-list.js +1 -1
  91. package/dist/collection/components/bs-breadcrumb/bs-breadcrumb/bs-breadcrumb.cmp.test.js +63 -0
  92. package/dist/collection/components/bs-breadcrumb/bs-breadcrumb/bs-breadcrumb.js +32 -1
  93. package/dist/collection/components/bs-breadcrumb/bs-breadcrumb-overflow/bs-breadcrumb-overflow.cmp.test.js +45 -0
  94. package/dist/collection/components/bs-breadcrumb/bs-breadcrumb-overflow/bs-breadcrumb-overflow.js +30 -1
  95. package/dist/collection/components/bs-breadcrumb/bs-breadcrumbs/bs-breadcrumbs.js +1 -1
  96. package/dist/collection/components/bs-button/bs-icon-button/bs-icon-button.cmp.test.js +20 -0
  97. package/dist/collection/components/bs-button/bs-icon-button/bs-icon-button.css +21 -4
  98. package/dist/collection/components/bs-button/bs-icon-button/bs-icon-button.js +3 -2
  99. package/dist/collection/components/bs-button/bs-icon-button/bs-icon-button.stories.js +10 -0
  100. package/dist/collection/components/bs-button-skeleton/bs-button-skeleton.js +1 -1
  101. package/dist/collection/components/bs-chatbot-feedback/bs-chatbot-feedback.js +1 -1
  102. package/dist/collection/components/bs-chatbot-header/bs-chatbot-header.js +1 -1
  103. package/dist/collection/components/bs-chatbot-response-action/bs-chatbot-response-action.js +1 -1
  104. package/dist/collection/components/bs-chatbot-sources-drawer/bs-chatbot-sources-drawer.js +1 -1
  105. package/dist/collection/components/bs-chatbot-suggestion-button/bs-chatbot-suggestion-button.js +1 -1
  106. package/dist/collection/components/bs-checkbox/bs-checkbox-skeleton/bs-checkbox-skeleton.js +1 -1
  107. package/dist/collection/components/bs-data-table/bs-data-table.cmp.test.js +19 -0
  108. package/dist/collection/components/bs-data-table/bs-data-table.js +19 -5
  109. package/dist/collection/components/bs-data-table/bs-data-table.stories.js +8 -1
  110. package/dist/collection/components/bs-datepicker/bs-datepicker.cmp.test.js +182 -0
  111. package/dist/collection/components/bs-datepicker/bs-datepicker.css +315 -0
  112. package/dist/collection/components/bs-datepicker/bs-datepicker.js +782 -0
  113. package/dist/collection/components/bs-datepicker/bs-datepicker.stories.js +63 -0
  114. package/dist/collection/components/bs-file-upload/bs-file-upload.js +1 -1
  115. package/dist/collection/components/bs-file-upload-item/bs-file-upload-item.js +1 -1
  116. package/dist/collection/components/bs-input/bs-input.js +7 -4
  117. package/dist/collection/components/bs-logo/bs-logo.cmp.test.js +52 -3
  118. package/dist/collection/components/bs-menu/bs-menu.js +1 -1
  119. package/dist/collection/components/bs-menu/bs-menu.stories.js +54 -0
  120. package/dist/collection/components/bs-menu-item/bs-menu-item.js +1 -1
  121. package/dist/collection/components/bs-pagination/bs-pagination.js +1 -1
  122. package/dist/collection/components/bs-progress/bs-progress.js +2 -2
  123. package/dist/collection/components/bs-progress-linear/bs-progress-linear.js +2 -2
  124. package/dist/collection/components/bs-radio/bs-radio.js +1 -1
  125. package/dist/collection/components/bs-slider/bs-slider.js +1 -1
  126. package/dist/collection/components/bs-snackbar/bs-snackbar.js +1 -1
  127. package/dist/collection/components/bs-source-link/bs-source-link.js +2 -2
  128. package/dist/collection/components/bs-stepper/bs-stepper/bs-stepper.js +1 -1
  129. package/dist/collection/components/bs-stepper/bs-stepper-step/bs-stepper-step.js +1 -1
  130. package/dist/collection/components/bs-switch/bs-switch.js +1 -1
  131. package/dist/collection/components/bs-tab/bs-inline-tab/bs-inline-tab.js +24 -1
  132. package/dist/collection/components/bs-tab/bs-tab/bs-tab.js +24 -1
  133. package/dist/collection/components/bs-tab/bs-tabs/bs-tabs.cmp.test.js +88 -0
  134. package/dist/collection/components/bs-tab/bs-tabs/bs-tabs.js +83 -2
  135. package/dist/collection/components/bs-tab/bs-tabs/bs-tabs.stories.js +24 -0
  136. package/dist/collection/components/bs-timepicker/bs-timepicker.cmp.test.js +141 -0
  137. package/dist/collection/components/bs-timepicker/bs-timepicker.css +200 -0
  138. package/dist/collection/components/bs-timepicker/bs-timepicker.js +509 -0
  139. package/dist/collection/components/bs-timepicker/bs-timepicker.stories.js +44 -0
  140. package/dist/collection/components/bs-toast/bs-toast.js +1 -1
  141. package/dist/collection/components/bs-tooltip/bs-tooltip.js +1 -1
  142. package/dist/collection/components/ui-shell/bs-navigation-drawer/bs-navigation-drawer/bs-navigation-drawer.cmp.test.js +173 -5
  143. package/dist/collection/components/ui-shell/bs-navigation-drawer/bs-navigation-drawer/bs-navigation-drawer.css +106 -34
  144. package/dist/collection/components/ui-shell/bs-navigation-drawer/bs-navigation-drawer/bs-navigation-drawer.js +181 -5
  145. package/dist/collection/components/ui-shell/bs-navigation-drawer/bs-navigation-drawer/bs-navigation-drawer.stories.js +48 -0
  146. package/dist/collection/components/ui-shell/bs-navigation-drawer/bs-navigation-drawer-item/bs-navigation-drawer-item.js +1 -1
  147. package/dist/collection/components/ui-shell/bs-navigation-header/bs-navigation-header/bs-navigation-header.cmp.test.js +68 -0
  148. package/dist/collection/components/ui-shell/bs-navigation-header/bs-navigation-header/bs-navigation-header.css +31 -17
  149. package/dist/collection/components/ui-shell/bs-navigation-header/bs-navigation-header/bs-navigation-header.js +1 -1
  150. package/dist/components/bs-ai-disclaimer.js +1 -1
  151. package/dist/components/bs-ai-greeting.js +1 -1
  152. package/dist/components/bs-ai-thinking.js +1 -1
  153. package/dist/components/bs-attachment-list.js +1 -1
  154. package/dist/components/bs-attachment.js +1 -1
  155. package/dist/components/bs-breadcrumb-overflow.js +1 -1
  156. package/dist/components/bs-breadcrumb.js +1 -1
  157. package/dist/components/bs-breadcrumbs.js +1 -1
  158. package/dist/components/bs-button-skeleton.js +1 -1
  159. package/dist/components/bs-carousel.js +1 -1
  160. package/dist/components/bs-chatbot-feedback.js +1 -1
  161. package/dist/components/bs-chatbot-header.js +1 -1
  162. package/dist/components/bs-chatbot-response-action.js +1 -1
  163. package/dist/components/bs-chatbot-sources-drawer.js +1 -1
  164. package/dist/components/bs-chatbot-suggestion-button.js +1 -1
  165. package/dist/components/bs-checkbox-skeleton.js +1 -1
  166. package/dist/components/bs-data-table.js +1 -1
  167. package/dist/components/bs-datepicker.d.ts +11 -0
  168. package/dist/components/bs-datepicker.js +1 -0
  169. package/dist/components/bs-dialog.js +1 -1
  170. package/dist/components/bs-file-upload-item.js +1 -1
  171. package/dist/components/bs-file-upload.js +1 -1
  172. package/dist/components/bs-icon-button.js +1 -1
  173. package/dist/components/bs-inline-tab.js +1 -1
  174. package/dist/components/bs-input.js +1 -1
  175. package/dist/components/bs-menu-item.js +1 -1
  176. package/dist/components/bs-menu.js +1 -1
  177. package/dist/components/bs-navigation-drawer-item.js +1 -1
  178. package/dist/components/bs-navigation-drawer.js +1 -1
  179. package/dist/components/bs-navigation-header.js +1 -1
  180. package/dist/components/bs-pagination.js +1 -1
  181. package/dist/components/bs-progress-linear.js +1 -1
  182. package/dist/components/bs-progress.js +1 -1
  183. package/dist/components/bs-radio.js +1 -1
  184. package/dist/components/bs-slider.js +1 -1
  185. package/dist/components/bs-snackbar.js +1 -1
  186. package/dist/components/bs-source-link.js +1 -1
  187. package/dist/components/bs-stepper-step.js +1 -1
  188. package/dist/components/bs-stepper.js +1 -1
  189. package/dist/components/bs-switch.js +1 -1
  190. package/dist/components/bs-tab.js +1 -1
  191. package/dist/components/bs-tabs.js +1 -1
  192. package/dist/components/bs-timepicker.d.ts +11 -0
  193. package/dist/components/bs-timepicker.js +1 -0
  194. package/dist/components/bs-toast.js +1 -1
  195. package/dist/components/bs-tooltip.js +1 -1
  196. package/dist/components/{p-BA3c9Rom.js → p-B7Icv1ho.js} +1 -1
  197. package/dist/components/{p-wei0Ija2.js → p-BTvme8CE.js} +1 -1
  198. package/dist/components/p-BYR_ZC8v.js +1 -0
  199. package/dist/components/p-Ba860ej1.js +1 -0
  200. package/dist/components/p-CPvqZNO8.js +1 -0
  201. package/dist/components/{p-EtXc94lJ.js → p-DkIVyFOP.js} +1 -1
  202. package/dist/components/{p-BfEyD6Ku.js → p-ZK8p5zax.js} +1 -1
  203. package/dist/components/p-jDO25SfF.js +1 -0
  204. package/dist/esm/brandsync-wc.js +1 -1
  205. package/dist/esm/bs-ai-disclaimer.entry.js +1 -1
  206. package/dist/esm/bs-ai-greeting.entry.js +1 -1
  207. package/dist/esm/bs-ai-thinking.entry.js +1 -1
  208. package/dist/esm/bs-attachment-list.entry.js +1 -1
  209. package/dist/esm/bs-breadcrumb-overflow.entry.js +14 -2
  210. package/dist/esm/bs-breadcrumb.entry.js +16 -2
  211. package/dist/esm/bs-breadcrumbs.entry.js +1 -1
  212. package/dist/esm/bs-button-skeleton.entry.js +1 -1
  213. package/dist/esm/bs-chatbot-feedback.entry.js +1 -1
  214. package/dist/esm/bs-chatbot-header.entry.js +1 -1
  215. package/dist/esm/bs-chatbot-response-action.entry.js +1 -1
  216. package/dist/esm/bs-chatbot-sources-drawer.entry.js +1 -1
  217. package/dist/esm/bs-chatbot-suggestion-button.entry.js +1 -1
  218. package/dist/esm/bs-checkbox-skeleton.entry.js +1 -1
  219. package/dist/esm/bs-data-table.entry.js +18 -4
  220. package/dist/esm/bs-datepicker.entry.js +408 -0
  221. package/dist/esm/bs-file-upload-item.entry.js +1 -1
  222. package/dist/esm/bs-file-upload.entry.js +1 -1
  223. package/dist/esm/bs-icon-button.entry.js +2 -2
  224. package/dist/esm/bs-inline-tab.entry.js +5 -1
  225. package/dist/esm/{bs-input.entry.js → bs-input_2.entry.js} +37 -5
  226. package/dist/esm/bs-menu.entry.js +1 -1
  227. package/dist/esm/bs-navigation-drawer-item.entry.js +1 -1
  228. package/dist/esm/bs-navigation-drawer.entry.js +119 -6
  229. package/dist/esm/bs-navigation-header.entry.js +2 -2
  230. package/dist/esm/bs-pagination.entry.js +1 -1
  231. package/dist/esm/bs-progress-linear.entry.js +2 -2
  232. package/dist/esm/bs-progress.entry.js +2 -2
  233. package/dist/esm/bs-radio.entry.js +1 -1
  234. package/dist/esm/bs-slider.entry.js +1 -1
  235. package/dist/esm/bs-snackbar.entry.js +1 -1
  236. package/dist/esm/bs-source-link.entry.js +2 -2
  237. package/dist/esm/bs-stepper-step.entry.js +1 -1
  238. package/dist/esm/bs-stepper.entry.js +1 -1
  239. package/dist/esm/bs-switch.entry.js +1 -1
  240. package/dist/esm/bs-tab.entry.js +5 -1
  241. package/dist/esm/bs-tabs.entry.js +48 -3
  242. package/dist/esm/bs-timepicker.entry.js +207 -0
  243. package/dist/esm/bs-toast.entry.js +1 -1
  244. package/dist/esm/bs-tooltip.entry.js +1 -1
  245. package/dist/esm/loader.js +1 -1
  246. package/dist/types/components/bs-breadcrumb/bs-breadcrumb/bs-breadcrumb.d.ts +10 -0
  247. package/dist/types/components/bs-breadcrumb/bs-breadcrumb-overflow/bs-breadcrumb-overflow.d.ts +8 -0
  248. package/dist/types/components/bs-button/bs-icon-button/bs-icon-button.d.ts +2 -1
  249. package/dist/types/components/bs-button/bs-icon-button/bs-icon-button.stories.d.ts +1 -0
  250. package/dist/types/components/bs-data-table/bs-data-table.d.ts +16 -2
  251. package/dist/types/components/bs-datepicker/bs-datepicker.cmp.test.d.ts +1 -0
  252. package/dist/types/components/bs-datepicker/bs-datepicker.d.ts +136 -0
  253. package/dist/types/components/bs-datepicker/bs-datepicker.stories.d.ts +20 -0
  254. package/dist/types/components/bs-menu/bs-menu.stories.d.ts +1 -0
  255. package/dist/types/components/bs-tab/bs-inline-tab/bs-inline-tab.d.ts +4 -0
  256. package/dist/types/components/bs-tab/bs-tab/bs-tab.d.ts +4 -0
  257. package/dist/types/components/bs-tab/bs-tabs/bs-tabs.d.ts +17 -0
  258. package/dist/types/components/bs-tab/bs-tabs/bs-tabs.stories.d.ts +1 -0
  259. package/dist/types/components/bs-timepicker/bs-timepicker.cmp.test.d.ts +1 -0
  260. package/dist/types/components/bs-timepicker/bs-timepicker.d.ts +101 -0
  261. package/dist/types/components/bs-timepicker/bs-timepicker.stories.d.ts +14 -0
  262. package/dist/types/components/ui-shell/bs-navigation-drawer/bs-navigation-drawer/bs-navigation-drawer.d.ts +50 -1
  263. package/dist/types/components/ui-shell/bs-navigation-drawer/bs-navigation-drawer/bs-navigation-drawer.stories.d.ts +2 -0
  264. package/dist/types/components.d.ts +645 -2
  265. package/package.json +1 -1
  266. package/dist/brandsync-wc/p-002d258d.entry.js +0 -1
  267. package/dist/brandsync-wc/p-153da845.entry.js +0 -1
  268. package/dist/brandsync-wc/p-2e7a1082.entry.js +0 -1
  269. package/dist/brandsync-wc/p-612cf79c.entry.js +0 -1
  270. package/dist/brandsync-wc/p-652d4068.entry.js +0 -1
  271. package/dist/brandsync-wc/p-7b00dd36.entry.js +0 -1
  272. package/dist/brandsync-wc/p-ae978c9a.entry.js +0 -1
  273. package/dist/brandsync-wc/p-bc69a96c.entry.js +0 -1
  274. package/dist/brandsync-wc/p-bf53ad52.entry.js +0 -1
  275. package/dist/brandsync-wc/p-c10d2529.entry.js +0 -1
  276. package/dist/brandsync-wc/p-c7f4c114.entry.js +0 -1
  277. package/dist/cjs/bs-menu-item.cjs.entry.js +0 -34
  278. package/dist/components/p-BkHYJIyj.js +0 -1
  279. package/dist/components/p-Buly0d5G.js +0 -1
  280. package/dist/esm/bs-menu-item.entry.js +0 -32
@@ -1,5 +1,21 @@
1
1
  import { render, h, describe, it, expect } from "@stencil/vitest";
2
+ import { afterEach, beforeEach } from "vitest";
2
3
  import { page } from "vitest/browser";
4
+ import { runAxeCheck } from "../../../../test/helpers/conventions";
5
+ // The test browser (and its viewport) is shared across test files, so every test here starts from a
6
+ // known viewport and restores whatever it found. The default 414px viewport is inside the drawer's
7
+ // small-screen (<= 768px) overlay mode, so the original tests -- written for the desktop drawer --
8
+ // run at 1024px; the overlay has its own describe at 390px below.
9
+ const previousViewport = { w: 0, h: 0 };
10
+ beforeEach(async () => {
11
+ previousViewport.w = window.innerWidth;
12
+ previousViewport.h = window.innerHeight;
13
+ await page.viewport(1024, 768);
14
+ });
15
+ afterEach(async () => {
16
+ await page.viewport(previousViewport.w, previousViewport.h);
17
+ document.body.style.overflow = '';
18
+ });
3
19
  describe('bs-navigation-drawer', () => {
4
20
  it('renders a <nav> landmark with the logo', async () => {
5
21
  const { root } = await render(h("bs-navigation-drawer", null));
@@ -110,11 +126,8 @@ describe('bs-navigation-drawer', () => {
110
126
  expect(searchClickSpy).toHaveReceivedEventTimes(1);
111
127
  });
112
128
  it('hides the search-trigger button when not collapsed', async () => {
113
- // The default test viewport (414px) is inside this component's own <= 768px small-screen
114
- // breakpoint (see bs-navigation-drawer.css), which forces the same visual treatment as
115
- // `collapsed` regardless of the prop -- widen the viewport here so this test is isolated to
116
- // the `collapsed` *prop*'s own behavior, not the viewport-driven treatment.
117
- await page.viewport(1024, 768);
129
+ // Desktop viewport (set for the whole file above), so this is isolated to the `collapsed`
130
+ // *prop*'s own behavior, not the small-screen overlay.
118
131
  const { root } = await render(h("bs-navigation-drawer", null));
119
132
  const trigger = root.shadowRoot.querySelector('[part="search-trigger"]');
120
133
  expect(getComputedStyle(trigger).display).toBe('none');
@@ -147,3 +160,158 @@ describe('bs-navigation-drawer', () => {
147
160
  });
148
161
  });
149
162
  });
163
+ describe('bs-navigation-drawer: small-screen overlay (<= 768px)', () => {
164
+ const frame = () => new Promise(r => requestAnimationFrame(() => requestAnimationFrame(() => r())));
165
+ const nav = (root) => root.shadowRoot.querySelector('nav');
166
+ const backdrop = (root) => root.shadowRoot.querySelector('[part="backdrop"]');
167
+ const css = (el) => getComputedStyle(el);
168
+ const renderDrawer = async (props = {}) => {
169
+ await page.viewport(390, 800);
170
+ const result = await render(h("bs-navigation-drawer", { ...props }, h("bs-navigation-drawer-item", null, "Home"), h("bs-navigation-drawer-item", { expandable: true, expanded: true }, "Reports", h("bs-navigation-drawer-item", { slot: "children", nested: true }, "Sales"))));
171
+ await result.waitForChanges();
172
+ return result;
173
+ };
174
+ it('is closed by default: off-canvas, hidden from the tab order and the accessibility tree', async () => {
175
+ const { root } = await renderDrawer();
176
+ expect(css(nav(root)).visibility).toBe('hidden');
177
+ expect(nav(root)).not.toHaveClass('bs-navigation-drawer--open');
178
+ expect(nav(root).getAttribute('role')).toBeNull();
179
+ expect(css(backdrop(root)).visibility).toBe('hidden');
180
+ });
181
+ it('takes no space in the page flow (position: fixed)', async () => {
182
+ const { root } = await renderDrawer();
183
+ expect(css(nav(root)).position).toBe('fixed');
184
+ });
185
+ it('open shows the drawer fully expanded over a backdrop', async () => {
186
+ const { root, waitForChanges } = await renderDrawer();
187
+ root.open = true;
188
+ await waitForChanges();
189
+ await new Promise(r => setTimeout(r, 350)); // let the slide-in finish
190
+ expect(css(nav(root)).visibility).toBe('visible');
191
+ expect(Math.round(nav(root).getBoundingClientRect().left)).toBe(0);
192
+ expect(Math.round(nav(root).getBoundingClientRect().width)).toBe(280);
193
+ // still the plain nav landmark: ARIA does not allow role="dialog" on <nav>
194
+ expect(nav(root).getAttribute('role')).toBeNull();
195
+ expect(css(backdrop(root)).visibility).toBe('visible');
196
+ // full wordmark + title, not the rail's mark; no collapse toggle or compact search trigger
197
+ expect(css(root.shadowRoot.querySelector('.bs-navigation-drawer__logo--full')).display).not.toBe('none');
198
+ expect(css(root.shadowRoot.querySelector('.bs-navigation-drawer__logo--mark')).display).toBe('none');
199
+ expect(css(root.shadowRoot.querySelector('[part="title"]')).display).not.toBe('none');
200
+ expect(css(root.shadowRoot.querySelector('[part="collapse"]')).display).toBe('none');
201
+ expect(css(root.shadowRoot.querySelector('[part="search-trigger"]')).display).toBe('none');
202
+ });
203
+ it('forces the items to their expanded layout, even when the drawer has collapsed set', async () => {
204
+ const { root, waitForChanges } = await renderDrawer({ collapsed: true });
205
+ root.open = true;
206
+ await waitForChanges();
207
+ const topLevel = Array.from(root.querySelectorAll(':scope > bs-navigation-drawer-item'));
208
+ expect(topLevel.map(i => i.collapsed)).toEqual([false, false]);
209
+ // the expandable item's children are reachable (its children wrapper is shown)
210
+ const children = topLevel[1].shadowRoot.querySelector('[part="children"]');
211
+ expect(children).not.toBeNull();
212
+ expect(css(children).display).not.toBe('none');
213
+ });
214
+ it('Escape closes the overlay, sets open back to false and emits bsClose once', async () => {
215
+ const { root, waitForChanges, spyOnEvent } = await renderDrawer();
216
+ const spy = spyOnEvent('bsClose');
217
+ root.open = true;
218
+ await waitForChanges();
219
+ document.dispatchEvent(new KeyboardEvent('keydown', { key: 'Escape', bubbles: true }));
220
+ await waitForChanges();
221
+ expect(root.open).toBe(false);
222
+ expect(root.hasAttribute('open')).toBe(false);
223
+ expect(spy).toHaveReceivedEventTimes(1);
224
+ });
225
+ it('clicking the backdrop closes the overlay and emits bsClose', async () => {
226
+ const { root, waitForChanges, spyOnEvent } = await renderDrawer();
227
+ const spy = spyOnEvent('bsClose');
228
+ root.open = true;
229
+ await waitForChanges();
230
+ backdrop(root).click();
231
+ await waitForChanges();
232
+ expect(root.open).toBe(false);
233
+ expect(spy).toHaveReceivedEventTimes(1);
234
+ });
235
+ it('setting open = false from code does not emit bsClose', async () => {
236
+ const { root, waitForChanges, spyOnEvent } = await renderDrawer({ open: true });
237
+ const spy = spyOnEvent('bsClose');
238
+ root.open = false;
239
+ await waitForChanges();
240
+ expect(spy).not.toHaveReceivedEvent();
241
+ });
242
+ it('Escape does nothing while the overlay is closed', async () => {
243
+ const { waitForChanges, spyOnEvent } = await renderDrawer();
244
+ const spy = spyOnEvent('bsClose');
245
+ document.dispatchEvent(new KeyboardEvent('keydown', { key: 'Escape', bubbles: true }));
246
+ await waitForChanges();
247
+ expect(spy).not.toHaveReceivedEvent();
248
+ });
249
+ it('moves focus into the overlay on open and returns it to the trigger on close', async () => {
250
+ await page.viewport(390, 800);
251
+ const { root, waitForChanges } = await render(h("div", null, h("button", { id: "hamburger" }, "Menu"), h("bs-navigation-drawer", null, h("bs-navigation-drawer-item", null, "Home"))));
252
+ const trigger = root.querySelector('#hamburger');
253
+ const drawer = root.querySelector('bs-navigation-drawer');
254
+ trigger.focus();
255
+ drawer.open = true;
256
+ await waitForChanges();
257
+ await frame();
258
+ expect(drawer.shadowRoot.activeElement).toBe(nav(drawer));
259
+ drawer.open = false;
260
+ await waitForChanges();
261
+ expect(document.activeElement).toBe(trigger);
262
+ });
263
+ it('keeps focus inside the open overlay: focus that lands outside is pulled back in', async () => {
264
+ await page.viewport(390, 800);
265
+ const { root, waitForChanges } = await render(h("div", null, h("button", { id: "outside" }, "Outside"), h("bs-navigation-drawer", { open: true }, h("bs-navigation-drawer-item", null, "Home"))));
266
+ await waitForChanges();
267
+ await frame();
268
+ const drawer = root.querySelector('bs-navigation-drawer');
269
+ root.querySelector('#outside').focus();
270
+ await frame();
271
+ expect(drawer.shadowRoot.activeElement).toBe(nav(drawer));
272
+ });
273
+ it('locks page scroll while open and restores it on close', async () => {
274
+ const { root, waitForChanges } = await renderDrawer();
275
+ expect(document.body.style.overflow).toBe('');
276
+ root.open = true;
277
+ await waitForChanges();
278
+ expect(document.body.style.overflow).toBe('hidden');
279
+ root.open = false;
280
+ await waitForChanges();
281
+ expect(document.body.style.overflow).toBe('');
282
+ });
283
+ it('on wider screens open is ignored: in the page flow, no backdrop, no scroll lock', async () => {
284
+ await page.viewport(1024, 768);
285
+ const { root, waitForChanges } = await render(h("bs-navigation-drawer", { open: true }));
286
+ await waitForChanges();
287
+ expect(css(nav(root)).position).not.toBe('fixed');
288
+ expect(css(nav(root)).visibility).toBe('visible');
289
+ expect(backdrop(root)).toBeNull();
290
+ expect(document.body.style.overflow).toBe('');
291
+ expect(nav(root).getAttribute('role')).toBeNull();
292
+ });
293
+ it('widening the viewport while the overlay is open returns to the normal drawer and releases scroll', async () => {
294
+ const { root, waitForChanges } = await renderDrawer({ open: true });
295
+ expect(document.body.style.overflow).toBe('hidden');
296
+ await page.viewport(1024, 768);
297
+ await new Promise(r => setTimeout(r, 150));
298
+ await waitForChanges();
299
+ expect(css(nav(root)).position).not.toBe('fixed');
300
+ expect(document.body.style.overflow).toBe('');
301
+ expect(backdrop(root)).toBeNull();
302
+ });
303
+ it('is off-canvas on the inline-end side in RTL', async () => {
304
+ await page.viewport(390, 800);
305
+ const { root, waitForChanges } = await render(h("div", { dir: "rtl" }, h("bs-navigation-drawer", null)));
306
+ await waitForChanges();
307
+ const drawer = root.querySelector('bs-navigation-drawer');
308
+ // closed: translated by +100% of its width (to the right, off-screen) rather than -100%
309
+ expect(new DOMMatrix(css(nav(drawer)).transform).m41).toBeGreaterThan(0);
310
+ });
311
+ it('has no axe-core violations while open', async () => {
312
+ const { root, waitForChanges } = await renderDrawer({ open: true });
313
+ await waitForChanges();
314
+ await new Promise(r => setTimeout(r, 350));
315
+ await runAxeCheck(root);
316
+ });
317
+ });
@@ -12,10 +12,9 @@
12
12
  * rhythm) -- bumped up from the originally Figma-measured --bs-spacing-150 (12px) at the user's
13
13
  * request after seeing it rendered (felt cramped in practice), not a Figma re-measurement.
14
14
  * @prop --bs-navigation-drawer-width: Default width of the drawer. 280px, matching Figma's own
15
- * frame -- overridable by a consumer that needs a different fixed width. Below a 768px viewport
16
- * width, this is overridden by a `@media (max-width: 768px)` rule that forces the existing
17
- * `collapsed` 96px icon-only rail treatment instead (see --bs-navigation-drawer-collapsed-width
18
- * below), so the drawer stops reserving a permanent 280px of layout width on small screens.
15
+ * frame -- overridable by a consumer that needs a different fixed width. At 768px and below the
16
+ * drawer is an off-canvas overlay (see `open`) of this same width (capped at the viewport
17
+ * width), so it stops reserving a permanent 280px of layout width on small screens.
19
18
  * @prop --bs-navigation-drawer-title-font-family: Title text font family. Aliased to
20
19
  * --bs-typography-font-family-heading.
21
20
  * @prop --bs-navigation-drawer-title-font-weight: Title text font weight. Aliased to
@@ -50,6 +49,14 @@
50
49
  * --bs-border-neutral-container (same border color as the drawer's own right edge).
51
50
  * @prop --bs-navigation-drawer-search-trigger-icon: Search-trigger icon color. Aliased to
52
51
  * --bs-icon-default.
52
+ * @prop --bs-navigation-drawer-backdrop: Scrim behind the small-screen overlay. Aliased to
53
+ * --bs-surface-overlay-level-2.
54
+ * @prop --bs-navigation-drawer-overlay-shadow: Shadow of the small-screen overlay panel. Aliased
55
+ * to --bs-shadow-lg.
56
+ * @prop --bs-navigation-drawer-overlay-z-index: Stacking order of the small-screen overlay (the
57
+ * panel sits one above its backdrop). Aliased to --bs-z-index-modal.
58
+ * @prop --bs-navigation-drawer-overlay-duration: Slide/fade duration of the small-screen overlay.
59
+ * Aliased to --bs-duration-default.
53
60
  */
54
61
  :host {
55
62
  display: block;
@@ -82,6 +89,11 @@
82
89
  --bs-navigation-drawer-search-trigger-bg: var(--bs-color-neutral-container);
83
90
  --bs-navigation-drawer-search-trigger-border: var(--bs-border-neutral-container);
84
91
  --bs-navigation-drawer-search-trigger-icon: var(--bs-icon-default);
92
+
93
+ --bs-navigation-drawer-backdrop: var(--bs-surface-overlay-level-2);
94
+ --bs-navigation-drawer-overlay-shadow: var(--bs-shadow-lg);
95
+ --bs-navigation-drawer-overlay-z-index: var(--bs-z-index-modal);
96
+ --bs-navigation-drawer-overlay-duration: var(--bs-duration-default);
85
97
  }
86
98
 
87
99
  .bs-navigation-drawer {
@@ -259,41 +271,101 @@
259
271
  display: none;
260
272
  }
261
273
 
262
- /* Below 768px (a standard tablet/small-screen breakpoint, and the narrow end of this component's
263
- normal tablet-and-up usage) a permanently-reserved 280px-wide drawer pushes page content down to
264
- an unusably narrow remainder on real small-screen viewports (e.g. 390px). This library has no
265
- existing width-based @media breakpoint convention to follow (grepping every other component's
266
- CSS only turns up `@media (prefers-reduced-motion: reduce)`), so rather than inventing new
267
- open/closed overlay API, this reuses the drawer's own existing `collapsed` 96px icon-only rail
268
- treatment (see the `:host([collapsed])` rules above) and applies it unconditionally at this
269
- width -- same rail, now driven by viewport instead of only by the `collapsed` prop/toggle. Placed
270
- last in this file so it wins over the unscoped `.bs-navigation-drawer`/`__title`/etc. rules above
271
- on specificity ties, regardless of whether `collapsed` happens to be reflected on the host. */
272
- @media (max-width: 768px) {
273
- .bs-navigation-drawer {
274
- width: var(--bs-navigation-drawer-collapsed-width);
275
- padding-left: 0;
276
- padding-right: 0;
277
- align-items: center;
278
- }
274
+ /* Small screens (768px and below, tracked in bs-navigation-drawer.tsx with matchMedia, which sets
275
+ the `data-overlay` attribute on the host): instead of a permanent rail the drawer becomes an
276
+ off-canvas overlay -- hidden until `open`, then sliding in over the page with a backdrop. A rail
277
+ clipped item labels inside 96px and offered no way to reach nested items, so the overlay shows the
278
+ drawer fully expanded (the items are switched to their expanded layout in the component). The
279
+ overrides below intentionally come after, and match the specificity of, the `:host([collapsed])`
280
+ rules above, so a `collapsed` set for desktop never leaks into the overlay. */
281
+ .bs-navigation-drawer:focus {
282
+ outline: none; /* programmatic focus target only (tabindex="-1"), see the component */
283
+ }
279
284
 
280
- .bs-navigation-drawer__logo--full {
281
- display: none;
282
- }
285
+ :host([data-overlay]) .bs-navigation-drawer {
286
+ position: fixed;
287
+ inset-block: 0;
288
+ inset-inline-start: 0;
289
+ z-index: calc(var(--bs-navigation-drawer-overlay-z-index) + 1);
290
+ width: var(--bs-navigation-drawer-width);
291
+ max-width: 100vw;
292
+ padding: var(--bs-navigation-drawer-padding-y) var(--bs-navigation-drawer-padding-right) var(--bs-navigation-drawer-padding-y)
293
+ var(--bs-navigation-drawer-padding-left);
294
+ align-items: stretch;
295
+ box-shadow: var(--bs-navigation-drawer-overlay-shadow);
296
+ /* Closed: off-canvas and hidden from the tab order / accessibility tree. `visibility` flips after
297
+ the slide-out finishes (delayed transition) so the exit is still seen. */
298
+ transform: translateX(-100%);
299
+ visibility: hidden;
300
+ transition:
301
+ transform var(--bs-navigation-drawer-overlay-duration) var(--bs-easing-standard),
302
+ visibility 0s linear var(--bs-navigation-drawer-overlay-duration);
303
+ }
283
304
 
284
- .bs-navigation-drawer__logo--mark {
285
- display: flex;
286
- }
305
+ :host([data-overlay]:dir(rtl)) .bs-navigation-drawer {
306
+ transform: translateX(100%);
307
+ }
287
308
 
288
- .bs-navigation-drawer__title {
289
- display: none;
290
- }
309
+ :host([data-overlay]) .bs-navigation-drawer.bs-navigation-drawer--open {
310
+ transform: none;
311
+ visibility: visible;
312
+ transition:
313
+ transform var(--bs-navigation-drawer-overlay-duration) var(--bs-easing-standard),
314
+ visibility 0s;
315
+ }
316
+
317
+ /* Fully expanded inside the overlay, whatever `collapsed` says. Nothing sits behind the collapse
318
+ toggle or the compact search trigger here, so neither is shown. */
319
+ :host([data-overlay]) .bs-navigation-drawer__logo--full {
320
+ display: flex;
321
+ }
322
+
323
+ :host([data-overlay]) .bs-navigation-drawer__logo--mark {
324
+ display: none;
325
+ }
326
+
327
+ :host([data-overlay]) .bs-navigation-drawer__title {
328
+ display: block;
329
+ }
330
+
331
+ :host([data-overlay]) .bs-navigation-drawer__search {
332
+ display: block;
333
+ }
334
+
335
+ :host([data-overlay]) .bs-navigation-drawer__search-trigger,
336
+ :host([data-overlay]) .bs-navigation-drawer__collapse {
337
+ display: none;
338
+ }
339
+
340
+ .bs-navigation-drawer__backdrop {
341
+ position: fixed;
342
+ inset: 0;
343
+ z-index: var(--bs-navigation-drawer-overlay-z-index);
344
+ background: var(--bs-navigation-drawer-backdrop);
345
+ opacity: 0;
346
+ visibility: hidden;
347
+ transition:
348
+ opacity var(--bs-navigation-drawer-overlay-duration) var(--bs-easing-standard),
349
+ visibility 0s linear var(--bs-navigation-drawer-overlay-duration);
350
+ }
291
351
 
292
- .bs-navigation-drawer__search {
293
- display: none;
352
+ :host([open]) .bs-navigation-drawer__backdrop {
353
+ opacity: 1;
354
+ visibility: visible;
355
+ transition:
356
+ opacity var(--bs-navigation-drawer-overlay-duration) var(--bs-easing-standard),
357
+ visibility 0s;
358
+ }
359
+
360
+ @media (prefers-reduced-motion: reduce) {
361
+ :host([data-overlay]) .bs-navigation-drawer,
362
+ .bs-navigation-drawer__backdrop {
363
+ transition: none;
294
364
  }
365
+ }
295
366
 
296
- .bs-navigation-drawer__search-trigger {
297
- display: inline-flex;
367
+ @media (forced-colors: active) {
368
+ :host([data-overlay]) .bs-navigation-drawer {
369
+ border: 1px solid CanvasText;
298
370
  }
299
371
  }
@@ -1,4 +1,4 @@
1
- import { h } from "@stencil/core";
1
+ import { Host, h } from "@stencil/core";
2
2
  /**
3
3
  * A left-side persistent navigation sidebar: the BrandSync logo, a "Main Menu" title with a
4
4
  * collapse toggle, a reserved slot for a search field, and a scrollable list of nav items.
@@ -37,6 +37,14 @@ import { h } from "@stencil/core";
37
37
  * that state, so this deliberately does not add the same "flip on toggle" idiom the drawer item's
38
38
  * own disclosure chevron does (that one really is an unconfirmed addition; this one was checked).
39
39
  *
40
+ * **Small screens (768px and below)** switch to an off-canvas overlay instead of a permanent rail:
41
+ * the drawer is hidden until `open` is set, then slides in over the page with a backdrop, fully
42
+ * expanded (labels visible, nested items reachable). Escape or a click on the backdrop closes it and
43
+ * emits `bsClose`; focus moves into it on open and back to whatever opened it on close. The
44
+ * collapse toggle and the compact search trigger are not shown in this mode (nothing sits behind
45
+ * them). The drawer has no trigger of its own -- put a button in your header and set `open` from it.
46
+ * On wider screens `open` is ignored and nothing changes.
47
+ *
40
48
  * @slot search - Reserved for a search field, e.g. a `bs-input type="search"`. This component
41
49
  * does not build one itself. Hidden while `collapsed` (see above).
42
50
  * @slot - Default slot: the scrollable list of nav items, typically one or more
@@ -52,6 +60,7 @@ import { h } from "@stencil/core";
52
60
  * @part search - The wrapper around the `search` slot.
53
61
  * @part search-trigger - The compact search button shown instead of the `search` slot while `collapsed`.
54
62
  * @part items - The wrapper around the default (items) slot.
63
+ * @part backdrop - The scrim behind the overlay (small screens only; clicking it closes the overlay).
55
64
  */
56
65
  // Note: this component's CSS Custom Properties are documented via @prop comments in
57
66
  // bs-navigation-drawer.css, not here -- see bs-navigation-header.css's identical note.
@@ -92,11 +101,112 @@ export class BsNavigationDrawer {
92
101
  * pairing works too: a header that keeps its own logo (`alignment="default"`) paired with this
93
102
  * drawer set to `showLogo={false}`, so the brand mark only ever appears once. */
94
103
  showLogo = true;
95
- onCollapsedChange(collapsed) {
96
- this.syncItemsCollapsed(collapsed);
104
+ /** Small screens only (768px and below): whether the off-canvas overlay is shown. Mutable and
105
+ * reflected -- the drawer sets it back to `false` itself when the user dismisses it (Escape or
106
+ * the backdrop), and emits `bsClose`. Ignored on wider screens, where the drawer is always in
107
+ * the page flow. There is no built-in trigger: set this from your own button. */
108
+ open = false;
109
+ /** Fires when the user dismisses the overlay (Escape, or a click on the backdrop), after `open`
110
+ * has been set back to `false`. Does not fire when you set `open = false` yourself. */
111
+ bsClose;
112
+ /** Whether the viewport is in the small-screen range (<= 768px), tracked with `matchMedia`. */
113
+ mobile = false;
114
+ mediaQuery;
115
+ focusPending = false;
116
+ navRef;
117
+ previouslyFocused;
118
+ bodyOverflowBefore;
119
+ get overlayOpen() {
120
+ return this.mobile && this.open;
121
+ }
122
+ connectedCallback() {
123
+ this.mediaQuery = window.matchMedia?.('(max-width: 768px)');
124
+ if (this.mediaQuery) {
125
+ this.mobile = this.mediaQuery.matches;
126
+ this.mediaQuery.addEventListener('change', this.onMediaChange);
127
+ }
128
+ }
129
+ disconnectedCallback() {
130
+ this.mediaQuery?.removeEventListener('change', this.onMediaChange);
131
+ this.unlockScroll();
132
+ }
133
+ onMediaChange = (ev) => {
134
+ this.mobile = ev.matches;
135
+ };
136
+ onCollapsedChange() {
137
+ this.syncItems();
138
+ }
139
+ onMobileChange() {
140
+ this.syncItems();
141
+ this.applyOverlayState();
142
+ }
143
+ onOpenChange() {
144
+ this.applyOverlayState();
97
145
  }
98
146
  componentDidLoad() {
99
- this.syncItemsCollapsed(this.collapsed);
147
+ this.syncItems();
148
+ this.applyOverlayState();
149
+ this.flushFocus();
150
+ }
151
+ componentDidRender() {
152
+ this.flushFocus();
153
+ }
154
+ /** Focus is moved only after the render that makes the panel visible -- focusing earlier races the
155
+ * re-render (the panel is still `visibility: hidden`), and a hidden element can't take focus. */
156
+ flushFocus() {
157
+ if (this.focusPending && this.overlayOpen) {
158
+ this.focusPending = false;
159
+ requestAnimationFrame(() => this.navRef?.focus());
160
+ }
161
+ }
162
+ /** In the small-screen overlay the items always use their expanded layout -- the collapsed
163
+ * (icon-above-caption) layout is for the desktop rail, and would clip labels in a full-width
164
+ * panel and hide nested items. */
165
+ syncItems() {
166
+ this.syncItemsCollapsed(this.mobile ? false : this.collapsed);
167
+ }
168
+ /** Scroll lock, focus entry and focus return for the overlay, mirroring `bs-dialog`: the focus
169
+ * move is deferred a frame because focusing right after the panel becomes visible does not
170
+ * reliably land. */
171
+ applyOverlayState() {
172
+ if (this.overlayOpen) {
173
+ if (this.bodyOverflowBefore === undefined) {
174
+ this.bodyOverflowBefore = document.body.style.overflow;
175
+ document.body.style.overflow = 'hidden';
176
+ }
177
+ if (!this.previouslyFocused) {
178
+ this.previouslyFocused = document.activeElement;
179
+ }
180
+ this.focusPending = true;
181
+ }
182
+ else {
183
+ this.focusPending = false;
184
+ this.unlockScroll();
185
+ if (this.previouslyFocused?.isConnected)
186
+ this.previouslyFocused.focus();
187
+ this.previouslyFocused = undefined;
188
+ }
189
+ }
190
+ unlockScroll() {
191
+ if (this.bodyOverflowBefore !== undefined) {
192
+ document.body.style.overflow = this.bodyOverflowBefore;
193
+ this.bodyOverflowBefore = undefined;
194
+ }
195
+ }
196
+ requestClose = () => {
197
+ this.open = false;
198
+ this.bsClose.emit();
199
+ };
200
+ onDocumentKeydown(ev) {
201
+ if (this.overlayOpen && ev.key === 'Escape')
202
+ this.requestClose();
203
+ }
204
+ /** Keeps focus inside the open overlay: focus that lands anywhere outside this component is
205
+ * pulled back in. `composedPath()` is used so this works across shadow-DOM boundaries (same
206
+ * approach as `bs-dialog`). */
207
+ onDocumentFocusIn(ev) {
208
+ if (this.overlayOpen && !ev.composedPath().includes(this.el))
209
+ this.navRef?.focus();
100
210
  }
101
211
  /** Keeps every direct-child `bs-navigation-drawer-item`'s `collapsed` prop in sync with this
102
212
  * component's own -- same direct-children-prop-sync approach `bs-tabs` uses for `selected`
@@ -117,7 +227,12 @@ export class BsNavigationDrawer {
117
227
  this.bsSearchClick.emit();
118
228
  };
119
229
  render() {
120
- return (h("nav", { key: '8be5fb4e45d6919408ff7057b963c2d95281b470', class: "bs-navigation-drawer", "aria-label": this.heading }, this.showLogo && (h("div", { key: 'f66ec1272c4c226d1a67fb7321b1247c3be54fb1', part: "logo", class: "bs-navigation-drawer__logo bs-navigation-drawer__logo--full" }, h("bs-logo", { key: '88cddd1d8696f895b33dd141bc2f5bfd3bd260b4', variant: "full", background: this.logoBackground }))), this.showLogo && (h("div", { key: '89b4efebeac6b934cbdd6cf3d25caaf5a36c86e8', part: "logo", class: "bs-navigation-drawer__logo bs-navigation-drawer__logo--mark" }, h("bs-logo", { key: '4f9ef53f8a02d9bb21b134e6a73caf28d9e864fc', variant: "mark", background: this.logoBackground }))), h("div", { key: '841040ad4770b0590ce632db1ce7122766c27ef6', class: "bs-navigation-drawer__title-row" }, h("span", { key: '857e9420aae428b44c2086bec5a2b4205a3dda04', part: "title", class: "bs-navigation-drawer__title" }, this.heading), this.collapsible && (h("button", { key: 'c109b6f3b54268cf729e114a249864fbd57203cc', type: "button", part: "collapse", class: "bs-navigation-drawer__collapse", "aria-label": this.collapsed ? 'Expand' : 'Collapse', "aria-pressed": this.collapsed ? 'true' : 'false', onClick: this.onCollapseClick }, h(CaretLeftIcon, { key: 'e46c9d2569b59e76398772d7a48e7a02d6b36ba3' })))), h("div", { key: '88031f0fd6cffb8480f2a086efb93a9d6418b4fc', part: "search", class: "bs-navigation-drawer__search" }, h("slot", { key: 'c86cb8c32f754fe81d91b76d8e1a352f9de5b31b', name: "search" })), h("button", { key: '90ade94c988aac8a1b2c855da7b193167b4eeee6', type: "button", part: "search-trigger", class: "bs-navigation-drawer__search-trigger", "aria-label": "Search", onClick: this.onSearchTriggerClick }, h(SearchIcon, { key: 'ff02c6f7f07de15b98bc5799914756e2245e36b9' })), h("div", { key: '41203613ef27dba8768c2755b8653d17c65d02c6', part: "items", class: "bs-navigation-drawer__items" }, h("slot", { key: 'd120d4a7477e748f5be81a5af742bfa558bf00bd' }))));
230
+ const classes = ['bs-navigation-drawer', this.mobile ? 'bs-navigation-drawer--overlay' : '', this.overlayOpen ? 'bs-navigation-drawer--open' : ''].filter(Boolean).join(' ');
231
+ return (h(Host, { key: 'c1e563e7b2a9474286671a3f6e1f2d3aed312620', "data-overlay": this.mobile ? '' : undefined }, this.mobile && h("div", { key: 'f6885e88df1607bb9e85a27c4e1cb616ce6b6c0d', part: "backdrop", class: "bs-navigation-drawer__backdrop", onClick: this.requestClose }), h("nav", { key: 'a3086b5203fd3724fce5fe82be394a77a6d9a1e1', ref: el => (this.navRef = el), class: classes, "aria-label": this.heading,
232
+ // Stays a plain <nav> landmark in every state: ARIA does not allow role="dialog" on <nav>
233
+ // (axe: aria-allowed-role). Modality is behavioral -- focus is held inside, the page behind is
234
+ // scrimmed, Escape closes -- rather than announced through aria-modal.
235
+ tabIndex: this.mobile ? -1 : undefined }, this.showLogo && (h("div", { key: 'c1b8700d6936ae14acf900d3cc83c6a8a7d79a20', part: "logo", class: "bs-navigation-drawer__logo bs-navigation-drawer__logo--full" }, h("bs-logo", { key: '27f4205dcdd609c4709a09dbeb7d4d59a41340db', variant: "full", background: this.logoBackground }))), this.showLogo && (h("div", { key: 'b8474734a50dbd690a9a8d8febd6cda084498d02', part: "logo", class: "bs-navigation-drawer__logo bs-navigation-drawer__logo--mark" }, h("bs-logo", { key: 'c89909a16f7255d24ddaae54ddd2c6cfca361572', variant: "mark", background: this.logoBackground }))), h("div", { key: '83b7641c3c1f8b8307bf8006bbef147ccfdc917c', class: "bs-navigation-drawer__title-row" }, h("span", { key: '97075d0df805b02f3f520c42ef4eceaa377e7064', part: "title", class: "bs-navigation-drawer__title" }, this.heading), this.collapsible && (h("button", { key: '184f4f2f35f74f145621d2854a6a50e52006ebd1', type: "button", part: "collapse", class: "bs-navigation-drawer__collapse", "aria-label": this.collapsed ? 'Expand' : 'Collapse', "aria-pressed": this.collapsed ? 'true' : 'false', onClick: this.onCollapseClick }, h(CaretLeftIcon, { key: '168c4a4f30f9cf92afd5cffc63e989e0a3d4e45a' })))), h("div", { key: 'd93ec72e4f6ba6f01d4fdc8fc3d9e0c9f0649242', part: "search", class: "bs-navigation-drawer__search" }, h("slot", { key: '3441fb753d206b84e68bb777e60ec849185882b9', name: "search" })), h("button", { key: '98b3bf5e4807afb1ba5a91e2b5238d917f584ab8', type: "button", part: "search-trigger", class: "bs-navigation-drawer__search-trigger", "aria-label": "Search", onClick: this.onSearchTriggerClick }, h(SearchIcon, { key: 'c61c32465503084caab0b3741bc95e3f0f274214' })), h("div", { key: 'f75111a609795d6ed83e3e843a433440a932b730', part: "items", class: "bs-navigation-drawer__items" }, h("slot", { key: '50f7cee1ae4e352b56561740bfc6ff035d521354' })))));
121
236
  }
122
237
  static get is() { return "bs-navigation-drawer"; }
123
238
  static get encapsulation() { return "shadow"; }
@@ -232,9 +347,34 @@ export class BsNavigationDrawer {
232
347
  "reflect": false,
233
348
  "attribute": "show-logo",
234
349
  "defaultValue": "true"
350
+ },
351
+ "open": {
352
+ "type": "boolean",
353
+ "mutable": true,
354
+ "complexType": {
355
+ "original": "boolean",
356
+ "resolved": "boolean",
357
+ "references": {}
358
+ },
359
+ "required": false,
360
+ "optional": false,
361
+ "docs": {
362
+ "tags": [],
363
+ "text": "Small screens only (768px and below): whether the off-canvas overlay is shown. Mutable and\nreflected -- the drawer sets it back to `false` itself when the user dismisses it (Escape or\nthe backdrop), and emits `bsClose`. Ignored on wider screens, where the drawer is always in\nthe page flow. There is no built-in trigger: set this from your own button."
364
+ },
365
+ "getter": false,
366
+ "setter": false,
367
+ "reflect": true,
368
+ "attribute": "open",
369
+ "defaultValue": "false"
235
370
  }
236
371
  };
237
372
  }
373
+ static get states() {
374
+ return {
375
+ "mobile": {}
376
+ };
377
+ }
238
378
  static get events() {
239
379
  return [{
240
380
  "method": "bsCollapse",
@@ -266,6 +406,21 @@ export class BsNavigationDrawer {
266
406
  "resolved": "void",
267
407
  "references": {}
268
408
  }
409
+ }, {
410
+ "method": "bsClose",
411
+ "name": "bsClose",
412
+ "bubbles": true,
413
+ "cancelable": true,
414
+ "composed": true,
415
+ "docs": {
416
+ "tags": [],
417
+ "text": "Fires when the user dismisses the overlay (Escape, or a click on the backdrop), after `open`\nhas been set back to `false`. Does not fire when you set `open = false` yourself."
418
+ },
419
+ "complexType": {
420
+ "original": "void",
421
+ "resolved": "void",
422
+ "references": {}
423
+ }
269
424
  }];
270
425
  }
271
426
  static get elementRef() { return "el"; }
@@ -273,6 +428,27 @@ export class BsNavigationDrawer {
273
428
  return [{
274
429
  "propName": "collapsed",
275
430
  "methodName": "onCollapsedChange"
431
+ }, {
432
+ "propName": "mobile",
433
+ "methodName": "onMobileChange"
434
+ }, {
435
+ "propName": "open",
436
+ "methodName": "onOpenChange"
437
+ }];
438
+ }
439
+ static get listeners() {
440
+ return [{
441
+ "name": "keydown",
442
+ "method": "onDocumentKeydown",
443
+ "target": "document",
444
+ "capture": false,
445
+ "passive": false
446
+ }, {
447
+ "name": "focusin",
448
+ "method": "onDocumentFocusIn",
449
+ "target": "document",
450
+ "capture": false,
451
+ "passive": false
276
452
  }];
277
453
  }
278
454
  }