bitboss-ui 2.1.135 → 3.0.0-alpha.1

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 (1358) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +244 -21
  3. package/bin/bitboss-ui-mcp.mjs +557 -0
  4. package/bin/bitboss-ui.mjs +626 -0
  5. package/dist/ai/BbAccordion.md +522 -113
  6. package/dist/ai/BbAlert.md +377 -197
  7. package/dist/ai/BbAsterisk.md +46 -0
  8. package/dist/ai/BbAvatar.md +454 -178
  9. package/dist/ai/BbBadge.md +695 -225
  10. package/dist/ai/BbBadgeButton.md +54 -0
  11. package/dist/ai/BbBaseButton.md +489 -0
  12. package/dist/ai/BbBaseCheckbox.md +49 -0
  13. package/dist/ai/BbBaseCheckboxGroup.md +64 -0
  14. package/dist/ai/BbBaseCheckboxIcon.md +174 -0
  15. package/dist/ai/BbBaseColorInput.md +64 -0
  16. package/dist/ai/BbBaseColorPalette.md +39 -0
  17. package/dist/ai/BbBaseDatePicker.md +42 -0
  18. package/dist/ai/BbBaseDatePickerInput.md +73 -0
  19. package/dist/ai/BbBaseInputContainer.md +48 -0
  20. package/dist/ai/BbBaseNumberInput.md +71 -0
  21. package/dist/ai/BbBaseRadio.md +46 -0
  22. package/dist/ai/BbBaseRadioGroup.md +63 -0
  23. package/dist/ai/BbBaseRadioIcon.md +187 -0
  24. package/dist/ai/BbBaseRating.md +51 -0
  25. package/dist/ai/BbBaseSelect.md +88 -0
  26. package/dist/ai/BbBaseSlider.md +56 -0
  27. package/dist/ai/BbBaseSwitch.md +49 -0
  28. package/dist/ai/BbBaseSwitchGroup.md +64 -0
  29. package/dist/ai/BbBaseSwitchIcon.md +184 -0
  30. package/dist/ai/BbBaseTag.md +68 -0
  31. package/dist/ai/BbBaseTextInput.md +75 -0
  32. package/dist/ai/BbBaseTextarea.md +62 -0
  33. package/dist/ai/BbBaseTimePickerInput.md +62 -0
  34. package/dist/ai/BbBreadcrumbs.md +542 -503
  35. package/dist/ai/BbButton.md +767 -636
  36. package/dist/ai/BbCheckbox.md +572 -254
  37. package/dist/ai/BbCheckboxGroup.md +561 -361
  38. package/dist/ai/BbCollapsible.md +419 -103
  39. package/dist/ai/BbColorInput.md +529 -323
  40. package/dist/ai/BbColorPalette.md +565 -330
  41. package/dist/ai/BbConfirm.md +612 -136
  42. package/dist/ai/BbConfirmPortal.md +28 -0
  43. package/dist/ai/BbDatePicker.md +244 -0
  44. package/dist/ai/BbDatePickerInput.md +706 -388
  45. package/dist/ai/BbDialog.md +770 -99
  46. package/dist/ai/BbDropdown.md +1054 -763
  47. package/dist/ai/BbDropdownButton.md +511 -615
  48. package/dist/ai/BbDropdownGroup.md +34 -0
  49. package/dist/ai/BbDropzone.md +1148 -436
  50. package/dist/ai/BbForm.md +239 -0
  51. package/dist/ai/BbIcon.md +379 -212
  52. package/dist/ai/BbIndicator.md +283 -0
  53. package/dist/ai/BbNumberInput.md +713 -355
  54. package/dist/ai/BbOffCanvas.md +875 -498
  55. package/dist/ai/BbPagination.md +483 -535
  56. package/dist/ai/BbPopover.md +583 -546
  57. package/dist/ai/BbProgress.md +456 -69
  58. package/dist/ai/BbRadio.md +343 -229
  59. package/dist/ai/BbRadioGroup.md +426 -353
  60. package/dist/ai/BbRating.md +361 -226
  61. package/dist/ai/BbSelect.md +1380 -536
  62. package/dist/ai/BbSelectPopover.md +1240 -1579
  63. package/dist/ai/BbSlider.md +478 -257
  64. package/dist/ai/BbSmoothHeight.md +472 -139
  65. package/dist/ai/BbSpinner.md +718 -131
  66. package/dist/ai/BbSwitch.md +549 -119
  67. package/dist/ai/BbSwitchGroup.md +503 -214
  68. package/dist/ai/BbTable.md +1956 -2358
  69. package/dist/ai/BbTabs.md +1113 -0
  70. package/dist/ai/BbTabsList.md +29 -0
  71. package/dist/ai/BbTabsPanes.md +27 -0
  72. package/dist/ai/BbTabsRoot.md +57 -0
  73. package/dist/ai/BbTag.md +393 -292
  74. package/dist/ai/BbTextInput.md +852 -333
  75. package/dist/ai/BbTextarea.md +836 -255
  76. package/dist/ai/BbTimePicker.md +231 -0
  77. package/dist/ai/BbTimePickerInput.md +196 -0
  78. package/dist/ai/BbToast.md +624 -196
  79. package/dist/ai/BbToastPortal.md +28 -0
  80. package/dist/ai/BbTooltip.md +443 -346
  81. package/dist/ai/BbTree.md +984 -235
  82. package/dist/ai/ChipsBox.md +27 -199
  83. package/dist/ai/ClearableButton.md +21 -55
  84. package/dist/ai/CommaBox.md +25 -200
  85. package/dist/ai/CommonInputWrapper.md +42 -0
  86. package/dist/ai/CommonPopover.md +30 -510
  87. package/dist/ai/ErrorIcon.md +19 -56
  88. package/dist/ai/FlatListBox.md +35 -379
  89. package/dist/ai/GroupedListBox.md +37 -535
  90. package/dist/ai/GuidesComponent.md +21 -0
  91. package/dist/ai/ListBox.md +38 -231
  92. package/dist/ai/OptionsContainer.md +34 -253
  93. package/dist/ai/WarningIcon.md +21 -0
  94. package/dist/ai/components.json +15883 -0
  95. package/dist/ai/composables/useBbConfig.md +80 -0
  96. package/dist/ai/composables/useBbFormContext.md +110 -0
  97. package/dist/ai/composables/useBbTableContext.md +164 -0
  98. package/dist/ai/composables/useBbTabsContext.md +118 -0
  99. package/dist/ai/composables/useBroadcastChannelInstance.md +97 -0
  100. package/dist/ai/composables/useConfirm.md +306 -0
  101. package/dist/ai/composables/useCountdown.md +84 -0
  102. package/dist/ai/composables/useId.md +60 -0
  103. package/dist/ai/composables/useMobile.md +85 -0
  104. package/dist/ai/composables/useToast.md +230 -0
  105. package/dist/ai/guides/agent-contract.md +108 -0
  106. package/dist/ai/guides/ai-router.md +111 -0
  107. package/dist/ai/guides/app-layout.md +295 -0
  108. package/dist/ai/guides/coherence-playbook.md +136 -0
  109. package/dist/ai/guides/component-picker.md +195 -0
  110. package/dist/ai/guides/design-language.md +461 -0
  111. package/dist/ai/guides/design-tokens.md +424 -0
  112. package/dist/ai/guides/fetch-items-playbook.md +161 -0
  113. package/dist/ai/guides/floating-bottom-panel.md +191 -0
  114. package/dist/ai/guides/icons-policy.md +257 -0
  115. package/dist/ai/guides/inertia-helpers.md +1394 -0
  116. package/dist/ai/guides/inline-edit-playbook.md +258 -0
  117. package/dist/ai/guides/installation-and-plugin-setup.md +377 -0
  118. package/dist/ai/guides/migration/components/bb-alert.md +37 -0
  119. package/dist/ai/guides/migration/components/bb-avatar.md +24 -0
  120. package/dist/ai/guides/migration/components/bb-badge.md +110 -0
  121. package/dist/ai/guides/migration/components/bb-breadcrumbs.md +26 -0
  122. package/dist/ai/guides/migration/components/bb-button.md +55 -0
  123. package/dist/ai/guides/migration/components/bb-checkbox-group.md +54 -0
  124. package/dist/ai/guides/migration/components/bb-checkbox.md +45 -0
  125. package/dist/ai/guides/migration/components/bb-chip.md +35 -0
  126. package/dist/ai/guides/migration/components/bb-collapsible.md +26 -0
  127. package/dist/ai/guides/migration/components/bb-color-input.md +23 -0
  128. package/dist/ai/guides/migration/components/bb-color-palette.md +31 -0
  129. package/dist/ai/guides/migration/components/bb-date-picker-input.md +84 -0
  130. package/dist/ai/guides/migration/components/bb-dialog.md +46 -0
  131. package/dist/ai/guides/migration/components/bb-dropdown-button.md +31 -0
  132. package/dist/ai/guides/migration/components/bb-dropdown.md +36 -0
  133. package/dist/ai/guides/migration/components/bb-dropzone.md +27 -0
  134. package/dist/ai/guides/migration/components/bb-icon.md +27 -0
  135. package/dist/ai/guides/migration/components/bb-off-canvas.md +25 -0
  136. package/dist/ai/guides/migration/components/bb-offcanvas.md +54 -0
  137. package/dist/ai/guides/migration/components/bb-pagination.md +24 -0
  138. package/dist/ai/guides/migration/components/bb-popover.md +52 -0
  139. package/dist/ai/guides/migration/components/bb-rating.md +24 -0
  140. package/dist/ai/guides/migration/components/bb-select-popover.md +58 -0
  141. package/dist/ai/guides/migration/components/bb-select.md +68 -0
  142. package/dist/ai/guides/migration/components/bb-slider.md +25 -0
  143. package/dist/ai/guides/migration/components/bb-smooth-height.md +45 -0
  144. package/dist/ai/guides/migration/components/bb-spinner.md +23 -0
  145. package/dist/ai/guides/migration/components/bb-table.md +66 -0
  146. package/dist/ai/guides/migration/components/bb-tabs.md +47 -0
  147. package/dist/ai/guides/migration/components/bb-tag.md +29 -0
  148. package/dist/ai/guides/migration/components/bb-text-input.md +37 -0
  149. package/dist/ai/guides/migration/components/bb-toast.md +47 -0
  150. package/dist/ai/guides/migration/components/bb-tooltip.md +34 -0
  151. package/dist/ai/guides/migration/components/bb-tree.md +77 -0
  152. package/dist/ai/guides/migration/components/use-confirm.md +46 -0
  153. package/dist/ai/guides/migration/v2-to-v3.md +649 -0
  154. package/dist/ai/guides/options-items-playbook.md +222 -0
  155. package/dist/ai/guides/page-shell.md +314 -0
  156. package/dist/ai/guides/validated-forms.md +177 -0
  157. package/dist/ai/index.md +156 -32
  158. package/dist/ai/recipes/inertia/approvals-inbox.md +1598 -0
  159. package/dist/ai/recipes/inertia/inline-edit-workspace.md +1733 -0
  160. package/dist/ai/recipes/inertia/onboarding.md +1765 -0
  161. package/dist/ai/recipes/inertia/ownership-atlas.md +1281 -0
  162. package/dist/ai/recipes/inertia/record-form.md +1442 -0
  163. package/dist/ai/recipes/inertia/records-workspace.md +1328 -0
  164. package/dist/ai/recipes/inertia/upload-center.md +1926 -0
  165. package/dist/ai/recipes/inertia/wizard-form.md +1477 -0
  166. package/dist/ai/recipes/nuxt/approvals-inbox.md +1561 -0
  167. package/dist/ai/recipes/nuxt/inline-edit-workspace.md +1690 -0
  168. package/dist/ai/recipes/nuxt/onboarding.md +1698 -0
  169. package/dist/ai/recipes/nuxt/record-form.md +1456 -0
  170. package/dist/ai/recipes/nuxt/records-workspace.md +1314 -0
  171. package/dist/ai/recipes/nuxt/upload-center.md +1847 -0
  172. package/dist/ai/recipes/nuxt/wizard-form.md +1486 -0
  173. package/dist/ai/recipes/vue/approvals-inbox.md +1479 -0
  174. package/dist/ai/recipes/vue/inline-edit-workspace.md +1581 -0
  175. package/dist/ai/recipes/vue/onboarding.md +1653 -0
  176. package/dist/ai/recipes/vue/record-form.md +1540 -0
  177. package/dist/ai/recipes/vue/records-workspace.md +1230 -0
  178. package/dist/ai/recipes/vue/upload-center.md +1806 -0
  179. package/dist/ai/recipes/vue/wizard-form.md +1418 -0
  180. package/dist/ai/source/BbAccordion.md +122 -0
  181. package/dist/ai/source/BbAlert.md +396 -0
  182. package/dist/ai/source/BbAsterisk.md +32 -0
  183. package/dist/ai/source/BbAvatar.md +256 -0
  184. package/dist/ai/source/BbBadge.md +560 -0
  185. package/dist/ai/source/BbBadgeButton.md +490 -0
  186. package/dist/ai/source/BbBaseButton.md +682 -0
  187. package/dist/ai/source/BbBaseCheckbox.md +459 -0
  188. package/dist/ai/source/BbBaseCheckboxGroup.md +554 -0
  189. package/dist/ai/source/BbBaseCheckboxIcon.md +201 -0
  190. package/dist/ai/source/BbBaseColorInput.md +413 -0
  191. package/dist/ai/source/BbBaseColorPalette.md +934 -0
  192. package/dist/ai/source/BbBaseDatePicker.md +1001 -0
  193. package/dist/ai/source/BbBaseDatePickerInput.md +1781 -0
  194. package/dist/ai/source/BbBaseInputContainer.md +1148 -0
  195. package/dist/ai/source/BbBaseNumberInput.md +615 -0
  196. package/dist/ai/source/BbBaseRadio.md +377 -0
  197. package/dist/ai/source/BbBaseRadioGroup.md +499 -0
  198. package/dist/ai/source/BbBaseRadioIcon.md +153 -0
  199. package/dist/ai/source/BbBaseRating.md +573 -0
  200. package/dist/ai/source/BbBaseSelect.md +895 -0
  201. package/dist/ai/source/BbBaseSlider.md +1085 -0
  202. package/dist/ai/source/BbBaseSwitch.md +246 -0
  203. package/dist/ai/source/BbBaseSwitchGroup.md +302 -0
  204. package/dist/ai/source/BbBaseSwitchIcon.md +206 -0
  205. package/dist/ai/source/BbBaseTag.md +688 -0
  206. package/dist/ai/source/BbBaseTextInput.md +511 -0
  207. package/dist/ai/source/BbBaseTextarea.md +480 -0
  208. package/dist/ai/source/BbBaseTimePickerInput.md +1013 -0
  209. package/dist/ai/source/BbBreadcrumbs.md +811 -0
  210. package/dist/ai/source/BbButton.md +990 -0
  211. package/dist/ai/source/BbCheckbox.md +319 -0
  212. package/dist/ai/source/BbCheckboxGroup.md +412 -0
  213. package/dist/ai/source/BbCollapsible.md +133 -0
  214. package/dist/ai/source/BbColorInput.md +315 -0
  215. package/dist/ai/source/BbColorPalette.md +361 -0
  216. package/dist/ai/source/BbConfirm.md +173 -0
  217. package/dist/ai/source/BbConfirmPortal.md +74 -0
  218. package/dist/ai/source/BbDatePicker.md +725 -0
  219. package/dist/ai/source/BbDatePickerInput.md +518 -0
  220. package/dist/ai/source/BbDialog.md +812 -0
  221. package/dist/ai/source/BbDropdown.md +2369 -0
  222. package/dist/ai/source/BbDropdownButton.md +313 -0
  223. package/dist/ai/source/BbDropdownGroup.md +1249 -0
  224. package/dist/ai/source/BbDropzone.md +749 -0
  225. package/dist/ai/source/BbForm.md +100 -0
  226. package/dist/ai/source/BbIcon.md +212 -0
  227. package/dist/ai/source/BbIndicator.md +298 -0
  228. package/dist/ai/source/BbNumberInput.md +365 -0
  229. package/dist/ai/source/BbOffCanvas.md +1260 -0
  230. package/dist/ai/source/BbPagination.md +829 -0
  231. package/dist/ai/source/BbPopover.md +853 -0
  232. package/dist/ai/source/BbProgress.md +140 -0
  233. package/dist/ai/source/BbRadio.md +294 -0
  234. package/dist/ai/source/BbRadioGroup.md +401 -0
  235. package/dist/ai/source/BbRating.md +362 -0
  236. package/dist/ai/source/BbSelect.md +681 -0
  237. package/dist/ai/source/BbSelectPopover.md +2209 -0
  238. package/dist/ai/source/BbSlider.md +371 -0
  239. package/dist/ai/source/BbSmoothHeight.md +261 -0
  240. package/dist/ai/source/BbSpinner.md +127 -0
  241. package/dist/ai/source/BbSwitch.md +175 -0
  242. package/dist/ai/source/BbSwitchGroup.md +240 -0
  243. package/dist/ai/source/BbTable.md +3348 -0
  244. package/dist/ai/source/BbTabs.md +403 -0
  245. package/dist/ai/source/BbTabsList.md +578 -0
  246. package/dist/ai/source/BbTabsPanes.md +368 -0
  247. package/dist/ai/source/BbTabsRoot.md +372 -0
  248. package/dist/ai/source/BbTag.md +383 -0
  249. package/dist/ai/source/BbTextInput.md +345 -0
  250. package/dist/ai/source/BbTextarea.md +330 -0
  251. package/dist/ai/source/BbTimePicker.md +591 -0
  252. package/dist/ai/source/BbTimePickerInput.md +367 -0
  253. package/dist/ai/source/BbToast.md +524 -0
  254. package/dist/ai/source/BbToastPortal.md +482 -0
  255. package/dist/ai/source/BbTooltip.md +508 -0
  256. package/dist/ai/source/BbTree.md +319 -0
  257. package/dist/ai/source/ChipsBox.md +201 -0
  258. package/dist/ai/source/ClearableButton.md +70 -0
  259. package/dist/ai/source/CommaBox.md +202 -0
  260. package/dist/ai/source/CommonInputWrapper.md +554 -0
  261. package/dist/ai/source/CommonPopover.md +606 -0
  262. package/dist/ai/source/ErrorIcon.md +43 -0
  263. package/dist/ai/source/FlatListBox.md +396 -0
  264. package/dist/ai/source/GroupedListBox.md +540 -0
  265. package/dist/ai/source/GuidesComponent.md +383 -0
  266. package/dist/ai/source/ListBox.md +238 -0
  267. package/dist/ai/source/OptionsContainer.md +191 -0
  268. package/dist/ai/source/WarningIcon.md +47 -0
  269. package/dist/alert-variants.d.ts +12 -0
  270. package/dist/assets/css/reset.css_inline.js +4 -0
  271. package/dist/assets/svgs/alert.svg_raw.js +4 -0
  272. package/dist/assets/svgs/calendar.svg_raw.js +4 -0
  273. package/dist/assets/svgs/check_stroke.svg_raw.js +4 -0
  274. package/dist/assets/svgs/chevron_down.svg_raw.js +4 -0
  275. package/dist/assets/svgs/chevron_right.svg_raw.js +4 -0
  276. package/dist/assets/svgs/clear.svg_raw.js +4 -0
  277. package/dist/assets/svgs/clock.svg_raw.js +4 -0
  278. package/dist/assets/svgs/error.svg_raw.js +4 -0
  279. package/dist/assets/svgs/search.svg_raw.js +4 -0
  280. package/dist/assets/svgs/sort.svg_raw.js +4 -0
  281. package/dist/assets/svgs/spinner.svg_raw.js +4 -0
  282. package/dist/assets/svgs/user.svg_raw.js +4 -0
  283. package/dist/badge-variants.d.ts +18 -0
  284. package/dist/button-variants.d.ts +15 -0
  285. package/dist/components/BbAccordion/BbAccordion.vue.d.ts +9 -3
  286. package/dist/components/BbAccordion/BbAccordion.vue.js +6 -0
  287. package/dist/components/BbAccordion/BbAccordion.vue_vue_type_script_setup_true_lang.js +66 -0
  288. package/dist/components/BbAccordion/types.d.ts +10 -7
  289. package/dist/components/BbAlert/BbAlert.vue.d.ts +12 -3
  290. package/dist/components/BbAlert/BbAlert.vue.js +6 -0
  291. package/dist/components/BbAlert/BbAlert.vue_vue_type_script_setup_true_lang.js +65 -0
  292. package/dist/components/BbAlert/types.d.ts +51 -12
  293. package/dist/components/BbAsterisk/BbAsterisk.vue.d.ts +3 -0
  294. package/dist/components/BbAsterisk/BbAsterisk.vue.js +6 -0
  295. package/dist/components/BbAsterisk/BbAsterisk.vue_vue_type_script_setup_true_lang.js +13 -0
  296. package/dist/components/BbAvatar/BbAvatar.vue.d.ts +5 -0
  297. package/dist/components/BbAvatar/BbAvatar.vue.js +6 -0
  298. package/dist/components/BbAvatar/BbAvatar.vue_vue_type_script_setup_true_lang.js +78 -0
  299. package/dist/components/BbAvatar/types.d.ts +4 -5
  300. package/dist/components/BbBadge/BadgeAppendIcon.vue.d.ts +3 -0
  301. package/dist/components/BbBadge/BadgeAppendIcon.vue.js +5 -0
  302. package/dist/components/BbBadge/BadgeAppendIcon.vue_vue_type_script_setup_true_lang.js +22 -0
  303. package/dist/components/BbBadge/BadgeBodyContent.vue.d.ts +15 -0
  304. package/dist/components/BbBadge/BadgeBodyContent.vue.js +5 -0
  305. package/dist/components/BbBadge/BadgeBodyContent.vue_vue_type_script_setup_true_lang.js +34 -0
  306. package/dist/components/BbBadge/BbBadge.vue.d.ts +8 -1
  307. package/dist/components/BbBadge/BbBadge.vue.js +6 -0
  308. package/dist/components/BbBadge/BbBadge.vue_vue_type_script_setup_true_lang.js +83 -0
  309. package/dist/components/BbBadge/BbBadgeButton.vue.d.ts +12 -0
  310. package/dist/components/BbBadge/BbBadgeButton.vue.js +5 -0
  311. package/dist/components/BbBadge/BbBadgeButton.vue_vue_type_script_setup_true_lang.js +54 -0
  312. package/dist/components/BbBadge/badgeButtonContext.d.ts +27 -0
  313. package/dist/components/BbBadge/badgeButtonContext.js +5 -0
  314. package/dist/components/BbBadge/types.d.ts +61 -16
  315. package/dist/components/BbBaseButton/BbBaseButton.vue.d.ts +13 -0
  316. package/dist/components/BbBaseButton/BbBaseButton.vue.js +6 -0
  317. package/dist/components/BbBaseButton/BbBaseButton.vue_vue_type_script_setup_true_lang.js +171 -0
  318. package/dist/components/BbBaseButton/RouterComponent.vue.js +5 -0
  319. package/dist/components/BbBaseButton/RouterComponent.vue_vue_type_script_setup_true_lang.js +28 -0
  320. package/dist/components/BbBaseButton/types.d.ts +191 -0
  321. package/dist/components/BbBaseButton/types.js +33 -0
  322. package/dist/components/BbBaseCheckbox/BbBaseCheckbox.vue.d.ts +40 -0
  323. package/dist/components/BbBaseCheckbox/BbBaseCheckbox.vue.js +6 -0
  324. package/dist/components/BbBaseCheckbox/BbBaseCheckbox.vue_vue_type_script_setup_true_lang.js +145 -0
  325. package/dist/components/BbBaseCheckbox/types.d.ts +222 -0
  326. package/dist/components/BbBaseCheckboxGroup/BbBaseCheckboxGroup.vue.d.ts +19 -0
  327. package/dist/components/BbBaseCheckboxGroup/BbBaseCheckboxGroup.vue.js +6 -0
  328. package/dist/components/BbBaseCheckboxGroup/BbBaseCheckboxGroup.vue_vue_type_script_setup_true_lang.js +190 -0
  329. package/dist/components/BbBaseCheckboxGroup/types.d.ts +257 -0
  330. package/dist/components/BbBaseCheckboxIcon/BbBaseCheckboxIcon.vue.d.ts +4 -0
  331. package/dist/components/BbBaseCheckboxIcon/BbBaseCheckboxIcon.vue.js +6 -0
  332. package/dist/components/BbBaseCheckboxIcon/BbBaseCheckboxIcon.vue_vue_type_script_setup_true_lang.js +43 -0
  333. package/dist/components/BbBaseCheckboxIcon/types.d.ts +47 -0
  334. package/dist/components/BbBaseColorInput/BbBaseColorInput.vue.d.ts +42 -0
  335. package/dist/components/BbBaseColorInput/BbBaseColorInput.vue.js +6 -0
  336. package/dist/components/BbBaseColorInput/BbBaseColorInput.vue_vue_type_script_setup_true_lang.js +178 -0
  337. package/dist/components/BbBaseColorInput/types.d.ts +207 -0
  338. package/dist/components/BbBaseColorPalette/BbBaseColorPalette.vue.d.ts +13 -0
  339. package/dist/components/BbBaseColorPalette/BbBaseColorPalette.vue.js +6 -0
  340. package/dist/components/BbBaseColorPalette/BbBaseColorPalette.vue_vue_type_script_setup_true_lang.js +395 -0
  341. package/dist/components/BbBaseColorPalette/types.d.ts +40 -0
  342. package/dist/components/BbBaseDatePicker/BbBaseDatePicker.vue.js +6 -0
  343. package/dist/components/BbBaseDatePicker/BbBaseDatePicker.vue_vue_type_script_setup_true_lang.js +300 -0
  344. package/dist/components/BbBaseDatePicker/BbBaseDatePickerInputDaySelector.vue.d.ts +44 -0
  345. package/dist/components/BbBaseDatePicker/BbBaseDatePickerInputDaySelector.vue.js +5 -0
  346. package/dist/components/BbBaseDatePicker/BbBaseDatePickerInputDaySelector.vue_vue_type_script_setup_true_lang.js +310 -0
  347. package/dist/components/BbBaseDatePicker/BbBaseDatePickerMonthSelector.vue.d.ts +5 -0
  348. package/dist/components/BbBaseDatePicker/BbBaseDatePickerMonthSelector.vue.js +5 -0
  349. package/dist/components/BbBaseDatePicker/BbBaseDatePickerMonthSelector.vue_vue_type_script_setup_true_lang.js +63 -0
  350. package/dist/components/BbBaseDatePicker/BbBaseDatePickerYearSelector.vue.d.ts +5 -0
  351. package/dist/components/BbBaseDatePicker/BbBaseDatePickerYearSelector.vue.js +5 -0
  352. package/dist/components/BbBaseDatePicker/BbBaseDatePickerYearSelector.vue_vue_type_script_setup_true_lang.js +75 -0
  353. package/dist/components/BbBaseDatePicker/typeahead.d.ts +112 -0
  354. package/dist/components/BbBaseDatePicker/typeahead.js +37 -0
  355. package/dist/components/BbBaseDatePicker/types.d.ts +97 -0
  356. package/dist/components/BbBaseDatePicker/useDatePickerContext.d.ts +58 -0
  357. package/dist/components/BbBaseDatePicker/useDatePickerContext.js +11 -0
  358. package/dist/components/BbBaseDatePickerInput/BbBaseDatePickerInput.vue.d.ts +30 -0
  359. package/dist/components/BbBaseDatePickerInput/BbBaseDatePickerInput.vue.js +6 -0
  360. package/dist/components/BbBaseDatePickerInput/BbBaseDatePickerInput.vue_vue_type_script_setup_true_lang.js +713 -0
  361. package/dist/components/BbBaseDatePickerInput/BbBaseDatePickerTimeSelector.vue.d.ts +30 -0
  362. package/dist/components/BbBaseDatePickerInput/BbBaseDatePickerTimeSelector.vue.js +6 -0
  363. package/dist/components/BbBaseDatePickerInput/BbBaseDatePickerTimeSelector.vue_vue_type_script_setup_true_lang.js +204 -0
  364. package/dist/components/BbBaseDatePickerInput/types.d.ts +309 -0
  365. package/dist/components/BbBaseInputContainer/BbBaseInputContainer.vue.d.ts +17 -0
  366. package/dist/components/BbBaseInputContainer/BbBaseInputContainer.vue.js +6 -0
  367. package/dist/components/BbBaseInputContainer/BbBaseInputContainer.vue_vue_type_script_setup_true_lang.js +184 -0
  368. package/dist/components/BbBaseInputContainer/types.d.ts +185 -0
  369. package/dist/components/BbBaseNumberInput/BbBaseNumberInput.vue.d.ts +52 -0
  370. package/dist/components/BbBaseNumberInput/BbBaseNumberInput.vue.js +6 -0
  371. package/dist/components/BbBaseNumberInput/BbBaseNumberInput.vue_vue_type_script_setup_true_lang.js +211 -0
  372. package/dist/components/BbBaseNumberInput/types.d.ts +211 -0
  373. package/dist/components/BbBaseRadio/BbBaseRadio.vue.d.ts +33 -0
  374. package/dist/components/BbBaseRadio/BbBaseRadio.vue.js +6 -0
  375. package/dist/components/BbBaseRadio/BbBaseRadio.vue_vue_type_script_setup_true_lang.js +114 -0
  376. package/dist/components/BbBaseRadio/types.d.ts +179 -0
  377. package/dist/components/BbBaseRadioGroup/BbBaseRadioGroup.vue.d.ts +19 -0
  378. package/dist/components/BbBaseRadioGroup/BbBaseRadioGroup.vue.js +6 -0
  379. package/dist/components/BbBaseRadioGroup/BbBaseRadioGroup.vue_vue_type_script_setup_true_lang.js +172 -0
  380. package/dist/components/BbBaseRadioGroup/types.d.ts +215 -0
  381. package/dist/components/BbBaseRadioIcon/BbBaseRadioIcon.vue.d.ts +4 -0
  382. package/dist/components/BbBaseRadioIcon/BbBaseRadioIcon.vue.js +6 -0
  383. package/dist/components/BbBaseRadioIcon/BbBaseRadioIcon.vue_vue_type_script_setup_true_lang.js +28 -0
  384. package/dist/components/BbBaseRadioIcon/types.d.ts +41 -0
  385. package/dist/components/BbBaseRating/BbBaseRating.vue.d.ts +38 -0
  386. package/dist/components/BbBaseRating/BbBaseRating.vue.js +6 -0
  387. package/dist/components/BbBaseRating/BbBaseRating.vue_vue_type_script_setup_true_lang.js +184 -0
  388. package/dist/components/BbBaseRating/types.d.ts +168 -0
  389. package/dist/components/BbBaseSelect/BbBaseSelect.vue.d.ts +19 -0
  390. package/dist/components/BbBaseSelect/BbBaseSelect.vue.js +6 -0
  391. package/dist/components/BbBaseSelect/BbBaseSelect.vue_vue_type_script_setup_true_lang.js +307 -0
  392. package/dist/components/BbBaseSelect/types.d.ts +294 -0
  393. package/dist/components/BbBaseSlider/BbBaseSlider.vue.d.ts +35 -0
  394. package/dist/components/BbBaseSlider/BbBaseSlider.vue.js +6 -0
  395. package/dist/components/BbBaseSlider/BbBaseSlider.vue_vue_type_script_setup_true_lang.js +324 -0
  396. package/dist/components/BbBaseSlider/types.d.ts +200 -0
  397. package/dist/components/BbBaseSwitch/BbBaseSwitch.vue.d.ts +35 -0
  398. package/dist/components/BbBaseSwitch/BbBaseSwitch.vue.js +6 -0
  399. package/dist/components/BbBaseSwitch/BbBaseSwitch.vue_vue_type_script_setup_true_lang.js +146 -0
  400. package/dist/components/BbBaseSwitch/types.d.ts +10 -0
  401. package/dist/components/BbBaseSwitchGroup/BbBaseSwitchGroup.vue.d.ts +19 -0
  402. package/dist/components/BbBaseSwitchGroup/BbBaseSwitchGroup.vue.js +6 -0
  403. package/dist/components/BbBaseSwitchGroup/BbBaseSwitchGroup.vue_vue_type_script_setup_true_lang.js +190 -0
  404. package/dist/components/BbBaseSwitchGroup/types.d.ts +8 -0
  405. package/dist/components/BbBaseSwitchIcon/BbBaseSwitchIcon.vue.d.ts +4 -0
  406. package/dist/components/BbBaseSwitchIcon/BbBaseSwitchIcon.vue.js +6 -0
  407. package/dist/components/BbBaseSwitchIcon/BbBaseSwitchIcon.vue_vue_type_script_setup_true_lang.js +30 -0
  408. package/dist/components/BbBaseSwitchIcon/types.d.ts +48 -0
  409. package/dist/components/BbBaseTag/BbBaseTag.vue.d.ts +50 -0
  410. package/dist/components/BbBaseTag/BbBaseTag.vue.js +6 -0
  411. package/dist/components/BbBaseTag/BbBaseTag.vue_vue_type_script_setup_true_lang.js +266 -0
  412. package/dist/components/BbBaseTag/types.d.ts +160 -0
  413. package/dist/components/BbBaseTextInput/BbBaseTextInput.vue.d.ts +45 -0
  414. package/dist/components/BbBaseTextInput/BbBaseTextInput.vue.js +6 -0
  415. package/dist/components/BbBaseTextInput/BbBaseTextInput.vue_vue_type_script_setup_true_lang.js +200 -0
  416. package/dist/components/BbBaseTextInput/types.d.ts +209 -0
  417. package/dist/components/BbBaseTextarea/BbBaseTextarea.vue.d.ts +39 -0
  418. package/dist/components/BbBaseTextarea/BbBaseTextarea.vue.js +6 -0
  419. package/dist/components/BbBaseTextarea/BbBaseTextarea.vue_vue_type_script_setup_true_lang.js +175 -0
  420. package/dist/components/BbBaseTextarea/types.d.ts +170 -0
  421. package/dist/components/BbBaseTimePickerInput/BbBaseTimePickerInput.vue.d.ts +27 -0
  422. package/dist/components/BbBaseTimePickerInput/BbBaseTimePickerInput.vue.js +6 -0
  423. package/dist/components/BbBaseTimePickerInput/BbBaseTimePickerInput.vue_vue_type_script_setup_true_lang.js +517 -0
  424. package/dist/components/BbBaseTimePickerInput/types.d.ts +151 -0
  425. package/dist/components/BbBreadcrumbs/BbBreadcrumbs.vue.d.ts +0 -1
  426. package/dist/components/BbBreadcrumbs/BbBreadcrumbs.vue.js +6 -0
  427. package/dist/components/BbBreadcrumbs/BbBreadcrumbs.vue_vue_type_script_setup_true_lang.js +224 -0
  428. package/dist/components/BbBreadcrumbs/estimateBreadcrumbItemWidth.js +47 -0
  429. package/dist/components/BbBreadcrumbs/types.d.ts +33 -22
  430. package/dist/components/BbButton/BbButton.vue.d.ts +6 -5
  431. package/dist/components/BbButton/BbButton.vue.js +6 -0
  432. package/dist/components/BbButton/BbButton.vue_vue_type_script_setup_true_lang.js +177 -0
  433. package/dist/components/BbButton/types.d.ts +48 -47
  434. package/dist/components/BbCheckbox/BbCheckbox.vue.d.ts +4 -3
  435. package/dist/components/BbCheckbox/BbCheckbox.vue.js +6 -0
  436. package/dist/components/BbCheckbox/BbCheckbox.vue_vue_type_script_setup_true_lang.js +146 -0
  437. package/dist/components/BbCheckbox/types.d.ts +24 -10
  438. package/dist/components/BbCheckboxGroup/BbCheckboxGroup.vue.d.ts +2 -13
  439. package/dist/components/BbCheckboxGroup/BbCheckboxGroup.vue.js +6 -0
  440. package/dist/components/BbCheckboxGroup/BbCheckboxGroup.vue_vue_type_script_setup_true_lang.js +190 -0
  441. package/dist/components/BbCheckboxGroup/types.d.ts +44 -23
  442. package/dist/components/BbCollapsible/BbCollapsible.vue.d.ts +2 -1
  443. package/dist/components/BbCollapsible/BbCollapsible.vue.js +6 -0
  444. package/dist/components/BbCollapsible/BbCollapsible.vue_vue_type_script_setup_true_lang.js +31 -0
  445. package/dist/components/BbCollapsible/types.d.ts +10 -9
  446. package/dist/components/BbColorInput/BbColorInput.vue.d.ts +10 -1
  447. package/dist/components/BbColorInput/BbColorInput.vue.js +6 -0
  448. package/dist/components/BbColorInput/BbColorInput.vue_vue_type_script_setup_true_lang.js +177 -0
  449. package/dist/components/BbColorInput/types.d.ts +37 -11
  450. package/dist/components/BbColorPalette/BbColorPalette.vue.d.ts +5 -8
  451. package/dist/components/BbColorPalette/BbColorPalette.vue.js +5 -0
  452. package/dist/components/BbColorPalette/BbColorPalette.vue_vue_type_script_setup_true_lang.js +125 -0
  453. package/dist/components/BbColorPalette/types.d.ts +66 -53
  454. package/dist/components/BbConfirm/BbConfirm.vue.js +6 -0
  455. package/dist/components/BbConfirm/BbConfirm.vue_vue_type_script_setup_true_lang.js +130 -0
  456. package/dist/components/BbConfirm/BbConfirmPortal.vue.d.ts +5 -6
  457. package/dist/components/BbConfirm/BbConfirmPortal.vue.js +5 -0
  458. package/dist/components/BbConfirm/BbConfirmPortal.vue_vue_type_script_setup_true_lang.js +19 -0
  459. package/dist/components/BbDatePicker/BbDatePicker.vue.d.ts +37 -0
  460. package/dist/components/BbDatePicker/BbDatePicker.vue.js +6 -0
  461. package/dist/components/BbDatePicker/BbDatePicker.vue_vue_type_script_setup_true_lang.js +319 -0
  462. package/dist/components/BbDatePicker/types.d.ts +155 -0
  463. package/dist/components/BbDatePickerInput/BbDatePickerInput.vue.d.ts +3 -1
  464. package/dist/components/BbDatePickerInput/BbDatePickerInput.vue.js +6 -0
  465. package/dist/components/BbDatePickerInput/BbDatePickerInput.vue_vue_type_script_setup_true_lang.js +179 -0
  466. package/dist/components/BbDatePickerInput/types.d.ts +127 -16
  467. package/dist/components/BbDialog/BbDialog.vue.d.ts +8 -6
  468. package/dist/components/BbDialog/BbDialog.vue.js +6 -0
  469. package/dist/components/BbDialog/BbDialog.vue_vue_type_script_setup_true_lang.js +214 -0
  470. package/dist/components/BbDialog/types.d.ts +146 -1
  471. package/dist/components/BbDialog/useDialogStack.d.ts +5 -0
  472. package/dist/components/BbDialog/useDialogStack.js +20 -0
  473. package/dist/components/BbDropdown/AdaptiveDropdown.vue.d.ts +18 -0
  474. package/dist/components/BbDropdown/AdaptiveDropdown.vue.js +6 -0
  475. package/dist/components/BbDropdown/AdaptiveDropdown.vue_vue_type_script_setup_true_lang.js +116 -0
  476. package/dist/components/BbDropdown/BbDropdown.vue.d.ts +14 -7
  477. package/dist/components/BbDropdown/BbDropdown.vue.js +6 -0
  478. package/dist/components/BbDropdown/BbDropdown.vue_vue_type_script_setup_true_lang.js +560 -0
  479. package/dist/components/BbDropdown/BbDropdownGroup.vue.d.ts +44 -0
  480. package/dist/components/BbDropdown/BbDropdownGroup.vue.js +5 -0
  481. package/dist/components/BbDropdown/BbDropdownGroup.vue_vue_type_script_setup_true_lang.js +36 -0
  482. package/dist/components/BbDropdown/BbDropdownList.vue.d.ts +27 -0
  483. package/dist/components/BbDropdown/BbDropdownList.vue.js +6 -0
  484. package/dist/components/BbDropdown/BbDropdownList.vue_vue_type_script_setup_true_lang.js +464 -0
  485. package/dist/components/BbDropdown/DropdownPipelineResolver.vue.d.ts +16 -0
  486. package/dist/components/BbDropdown/DropdownPipelineResolver.vue.js +5 -0
  487. package/dist/components/BbDropdown/DropdownPipelineResolver.vue_vue_type_script_setup_true_lang.js +168 -0
  488. package/dist/components/BbDropdown/normalizeGroups.d.ts +18 -0
  489. package/dist/components/BbDropdown/normalizeGroups.js +46 -0
  490. package/dist/components/BbDropdown/types.d.ts +457 -45
  491. package/dist/components/BbDropdown/types.js +4 -0
  492. package/dist/components/BbDropdown/useDropdownContext.d.ts +89 -0
  493. package/dist/components/BbDropdown/useDropdownContext.js +9 -0
  494. package/dist/components/BbDropdown/useDropdownGroupRegistry.d.ts +108 -0
  495. package/dist/components/BbDropdown/useDropdownGroupRegistry.js +5 -0
  496. package/dist/components/BbDropdownButton/BbDropdownButton.vue.d.ts +3 -3
  497. package/dist/components/BbDropdownButton/BbDropdownButton.vue.js +6 -0
  498. package/dist/components/BbDropdownButton/BbDropdownButton.vue_vue_type_script_setup_true_lang.js +119 -0
  499. package/dist/components/BbDropdownButton/types.d.ts +45 -52
  500. package/dist/components/BbDropzone/BbDropzone.vue.d.ts +5 -4
  501. package/dist/components/BbDropzone/BbDropzone.vue.js +6 -0
  502. package/dist/components/BbDropzone/BbDropzone.vue_vue_type_script_setup_true_lang.js +284 -0
  503. package/dist/components/BbDropzone/types.d.ts +55 -7
  504. package/dist/components/BbIcon/BbIcon.vue.d.ts +3 -2
  505. package/dist/components/BbIcon/BbIcon.vue.js +6 -0
  506. package/dist/components/BbIcon/BbIcon.vue_vue_type_script_setup_true_lang.js +65 -0
  507. package/dist/components/BbIcon/types.d.ts +6 -19
  508. package/dist/components/BbIndicator/BbIndicator.vue.d.ts +14 -0
  509. package/dist/components/BbIndicator/BbIndicator.vue.js +6 -0
  510. package/dist/components/BbIndicator/BbIndicator.vue_vue_type_script_setup_true_lang.js +56 -0
  511. package/dist/components/BbIndicator/types.d.ts +49 -0
  512. package/dist/components/BbNumberInput/BbNumberInput.vue.d.ts +12 -6
  513. package/dist/components/BbNumberInput/BbNumberInput.vue.js +6 -0
  514. package/dist/components/BbNumberInput/BbNumberInput.vue_vue_type_script_setup_true_lang.js +194 -0
  515. package/dist/components/BbNumberInput/types.d.ts +31 -4
  516. package/dist/components/BbOffCanvas/BbOffCanvas.vue.d.ts +10 -10
  517. package/dist/components/BbOffCanvas/BbOffCanvas.vue.js +6 -0
  518. package/dist/components/BbOffCanvas/BbOffCanvas.vue_vue_type_script_setup_true_lang.js +284 -0
  519. package/dist/components/BbOffCanvas/types.d.ts +71 -39
  520. package/dist/components/BbOffCanvas/useOffCanvasStack.d.ts +25 -0
  521. package/dist/components/BbOffCanvas/useOffCanvasStack.js +68 -0
  522. package/dist/components/BbPagination/BbPagination.vue.d.ts +3 -4
  523. package/dist/components/BbPagination/BbPagination.vue.js +6 -0
  524. package/dist/components/BbPagination/BbPagination.vue_vue_type_script_setup_true_lang.js +244 -0
  525. package/dist/components/BbPagination/paginationFit.d.ts +38 -0
  526. package/dist/components/BbPagination/paginationFit.js +13 -0
  527. package/dist/components/BbPagination/types.d.ts +51 -16
  528. package/dist/components/BbPopover/BbPopover.vue.d.ts +10 -15
  529. package/dist/components/BbPopover/BbPopover.vue.js +6 -0
  530. package/dist/components/BbPopover/BbPopover.vue_vue_type_script_setup_true_lang.js +310 -0
  531. package/dist/components/BbPopover/escapeStack.d.ts +6 -0
  532. package/dist/components/BbPopover/escapeStack.js +10 -0
  533. package/dist/components/BbPopover/types.d.ts +84 -31
  534. package/dist/components/BbProgress/BbProgress.vue.d.ts +1 -0
  535. package/dist/components/BbProgress/BbProgress.vue.js +6 -0
  536. package/dist/components/BbProgress/BbProgress.vue_vue_type_script_setup_true_lang.js +36 -0
  537. package/dist/components/BbProgress/types.d.ts +15 -1
  538. package/dist/components/BbRadio/BbRadio.vue.d.ts +5 -3
  539. package/dist/components/BbRadio/BbRadio.vue.js +6 -0
  540. package/dist/components/BbRadio/BbRadio.vue_vue_type_script_setup_true_lang.js +133 -0
  541. package/dist/components/BbRadio/types.d.ts +23 -9
  542. package/dist/components/BbRadioGroup/BbRadioGroup.vue.d.ts +4 -14
  543. package/dist/components/BbRadioGroup/BbRadioGroup.vue.js +6 -0
  544. package/dist/components/BbRadioGroup/BbRadioGroup.vue_vue_type_script_setup_true_lang.js +184 -0
  545. package/dist/components/BbRadioGroup/types.d.ts +41 -22
  546. package/dist/components/BbRating/BbRating.vue.d.ts +4 -1
  547. package/dist/components/BbRating/BbRating.vue.js +6 -0
  548. package/dist/components/BbRating/BbRating.vue_vue_type_script_setup_true_lang.js +150 -0
  549. package/dist/components/BbRating/types.d.ts +37 -10
  550. package/dist/components/BbSelect/BbSelect.vue.d.ts +2 -11
  551. package/dist/components/BbSelect/BbSelect.vue.js +6 -0
  552. package/dist/components/BbSelect/BbSelect.vue_vue_type_script_setup_true_lang.js +241 -0
  553. package/dist/components/BbSelect/types.d.ts +105 -59
  554. package/dist/components/BbSelectPopover/BbSelectPopover.vue.d.ts +1 -10
  555. package/dist/components/BbSelectPopover/BbSelectPopover.vue.js +6 -0
  556. package/dist/components/BbSelectPopover/BbSelectPopover.vue_vue_type_script_setup_true_lang.js +637 -0
  557. package/dist/components/BbSelectPopover/types.d.ts +189 -102
  558. package/dist/components/BbSlider/BbSlider.vue.d.ts +3 -6
  559. package/dist/components/BbSlider/BbSlider.vue.js +6 -0
  560. package/dist/components/BbSlider/BbSlider.vue_vue_type_script_setup_true_lang.js +166 -0
  561. package/dist/components/BbSlider/types.d.ts +37 -13
  562. package/dist/components/BbSmoothHeight/BbSmoothHeight.vue.d.ts +3 -1
  563. package/dist/components/BbSmoothHeight/BbSmoothHeight.vue.js +6 -0
  564. package/dist/components/BbSmoothHeight/BbSmoothHeight.vue_vue_type_script_setup_true_lang.js +79 -0
  565. package/dist/components/BbSmoothHeight/types.d.ts +13 -2
  566. package/dist/components/BbSpinner/BbSpinner.vue.d.ts +1 -1
  567. package/dist/components/BbSpinner/BbSpinner.vue.js +6 -0
  568. package/dist/components/BbSpinner/BbSpinner.vue_vue_type_script_setup_true_lang.js +30 -0
  569. package/dist/components/BbSpinner/types.d.ts +10 -3
  570. package/dist/components/BbSwitch/BbSwitch.vue.d.ts +5 -3
  571. package/dist/components/BbSwitch/BbSwitch.vue.js +6 -0
  572. package/dist/components/BbSwitch/BbSwitch.vue_vue_type_script_setup_true_lang.js +142 -0
  573. package/dist/components/BbSwitch/types.d.ts +3 -1
  574. package/dist/components/BbSwitchGroup/BbSwitchGroup.vue.d.ts +4 -14
  575. package/dist/components/BbSwitchGroup/BbSwitchGroup.vue.js +6 -0
  576. package/dist/components/BbSwitchGroup/BbSwitchGroup.vue_vue_type_script_setup_true_lang.js +190 -0
  577. package/dist/components/BbSwitchGroup/types.d.ts +3 -22
  578. package/dist/components/BbTable/BbTable.vue.d.ts +53 -31
  579. package/dist/components/BbTable/BbTable.vue.js +6 -0
  580. package/dist/components/BbTable/BbTable.vue_vue_type_script_setup_true_lang.js +889 -0
  581. package/dist/components/BbTable/types.d.ts +176 -37
  582. package/dist/components/BbTable/utils.d.ts +9 -1
  583. package/dist/components/BbTable/utils.js +53 -0
  584. package/dist/components/BbTabs/BbTabs.vue.d.ts +20 -0
  585. package/dist/components/BbTabs/BbTabs.vue.js +6 -0
  586. package/dist/components/BbTabs/BbTabs.vue_vue_type_script_setup_true_lang.js +64 -0
  587. package/dist/components/BbTabs/BbTabsList.vue.d.ts +19 -0
  588. package/dist/components/BbTabs/BbTabsList.vue.js +6 -0
  589. package/dist/components/BbTabs/BbTabsList.vue_vue_type_script_setup_true_lang.js +123 -0
  590. package/dist/components/BbTabs/BbTabsPanes.vue.d.ts +16 -0
  591. package/dist/components/BbTabs/BbTabsPanes.vue.js +6 -0
  592. package/dist/components/BbTabs/BbTabsPanes.vue_vue_type_script_setup_true_lang.js +35 -0
  593. package/dist/components/BbTabs/BbTabsRoot.vue.d.ts +20 -0
  594. package/dist/components/BbTabs/BbTabsRoot.vue.js +5 -0
  595. package/dist/components/BbTabs/BbTabsRoot.vue_vue_type_script_setup_true_lang.js +55 -0
  596. package/dist/components/BbTabs/types.d.ts +264 -0
  597. package/dist/components/BbTag/BbTag.vue.d.ts +19 -6
  598. package/dist/components/BbTag/BbTag.vue.js +6 -0
  599. package/dist/components/BbTag/BbTag.vue_vue_type_script_setup_true_lang.js +187 -0
  600. package/dist/components/BbTag/types.d.ts +48 -17
  601. package/dist/components/BbTextInput/BbTextInput.vue.d.ts +10 -1
  602. package/dist/components/BbTextInput/BbTextInput.vue.js +6 -0
  603. package/dist/components/BbTextInput/BbTextInput.vue_vue_type_script_setup_true_lang.js +195 -0
  604. package/dist/components/BbTextInput/types.d.ts +24 -4
  605. package/dist/components/BbTextarea/BbTextarea.vue.d.ts +10 -1
  606. package/dist/components/BbTextarea/BbTextarea.vue.js +6 -0
  607. package/dist/components/BbTextarea/BbTextarea.vue_vue_type_script_setup_true_lang.js +178 -0
  608. package/dist/components/BbTextarea/types.d.ts +26 -2
  609. package/dist/components/BbTimePicker/BbTimePicker.vue.d.ts +33 -0
  610. package/dist/components/BbTimePicker/BbTimePicker.vue.js +6 -0
  611. package/dist/components/BbTimePicker/BbTimePicker.vue_vue_type_script_setup_true_lang.js +244 -0
  612. package/dist/components/BbTimePicker/types.d.ts +129 -0
  613. package/dist/components/BbTimePickerInput/BbTimePickerInput.vue.d.ts +25 -0
  614. package/dist/components/BbTimePickerInput/BbTimePickerInput.vue.js +6 -0
  615. package/dist/components/BbTimePickerInput/BbTimePickerInput.vue_vue_type_script_setup_true_lang.js +157 -0
  616. package/dist/components/BbTimePickerInput/types.d.ts +165 -0
  617. package/dist/components/BbToast/BbToast.vue.d.ts +2 -3
  618. package/dist/components/BbToast/BbToast.vue.js +6 -0
  619. package/dist/components/BbToast/BbToast.vue_vue_type_script_setup_true_lang.js +35 -0
  620. package/dist/components/BbToast/BbToastMessage.vue.d.ts +17 -8
  621. package/dist/components/BbToast/BbToastMessage.vue.js +5 -0
  622. package/dist/components/BbToast/BbToastMessage.vue_vue_type_script_setup_true_lang.js +170 -0
  623. package/dist/components/BbToast/BbToastPortal.vue.d.ts +30 -0
  624. package/dist/components/BbToast/BbToastPortal.vue.js +5 -0
  625. package/dist/components/BbToast/BbToastPortal.vue_vue_type_script_setup_true_lang.js +19 -0
  626. package/dist/components/BbToast/BbToastRegion.vue.d.ts +8 -0
  627. package/dist/components/BbToast/BbToastRegion.vue.js +5 -0
  628. package/dist/components/BbToast/BbToastRegion.vue_vue_type_script_setup_true_lang.js +100 -0
  629. package/dist/components/BbToast/types.d.ts +69 -5
  630. package/dist/components/BbTooltip/BbTooltip.vue.d.ts +4 -3
  631. package/dist/components/BbTooltip/BbTooltip.vue.js +6 -0
  632. package/dist/components/BbTooltip/BbTooltip.vue_vue_type_script_setup_true_lang.js +160 -0
  633. package/dist/components/BbTooltip/types.d.ts +61 -11
  634. package/dist/components/BbTree/BbTree.vue.d.ts +26 -13
  635. package/dist/components/BbTree/BbTree.vue.js +6 -0
  636. package/dist/components/BbTree/BbTree.vue_vue_type_script_setup_true_lang.js +55 -0
  637. package/dist/components/BbTree/BbTreeLevel.vue.d.ts +19 -0
  638. package/dist/components/BbTree/BbTreeLevel.vue.js +5 -0
  639. package/dist/components/BbTree/BbTreeLevel.vue_vue_type_script_setup_true_lang.js +94 -0
  640. package/dist/components/BbTree/context.d.ts +17 -0
  641. package/dist/components/BbTree/context.js +4 -0
  642. package/dist/components/BbTree/types.d.ts +93 -42
  643. package/dist/components/ChipsBox/ChipsBox.vue.d.ts +2 -1
  644. package/dist/components/ChipsBox/ChipsBox.vue.js +5 -0
  645. package/dist/components/ChipsBox/ChipsBox.vue_vue_type_script_setup_true_lang.js +98 -0
  646. package/dist/components/ChipsBox/types.d.ts +12 -5
  647. package/dist/components/ClearableButton/ClearableButton.vue.d.ts +2 -1
  648. package/dist/components/ClearableButton/ClearableButton.vue.js +6 -0
  649. package/dist/components/ClearableButton/ClearableButton.vue_vue_type_script_setup_true_lang.js +19 -0
  650. package/dist/components/ClearableButton/types.d.ts +7 -1
  651. package/dist/components/CloseIcon/CloseButton.vue.d.ts +5 -0
  652. package/dist/components/CloseIcon/CloseButton.vue.js +7 -0
  653. package/dist/components/CloseIcon/CloseButton.vue_vue_type_script_setup_true_lang.js +23 -0
  654. package/dist/components/CloseIcon/types.d.ts +2 -0
  655. package/dist/components/CommaBox/CommaBox.vue.d.ts +2 -1
  656. package/dist/components/CommaBox/CommaBox.vue.js +6 -0
  657. package/dist/components/CommaBox/CommaBox.vue_vue_type_script_setup_true_lang.js +81 -0
  658. package/dist/components/CommaBox/types.d.ts +6 -7
  659. package/dist/components/CommonInputWrapper/CommonInputWrapper.vue.d.ts +19 -0
  660. package/dist/components/CommonInputWrapper/CommonInputWrapper.vue.js +6 -0
  661. package/dist/components/CommonInputWrapper/CommonInputWrapper.vue_vue_type_script_setup_true_lang.js +107 -0
  662. package/dist/components/CommonInputWrapper/types.d.ts +96 -0
  663. package/dist/components/CommonPopover/CommonPopover.vue.d.ts +3 -3
  664. package/dist/components/CommonPopover/CommonPopover.vue.js +6 -0
  665. package/dist/components/CommonPopover/CommonPopover.vue_vue_type_script_setup_true_lang.js +160 -0
  666. package/dist/components/CommonPopover/types.d.ts +61 -16
  667. package/dist/components/ErrorIcon/ErrorIcon.vue.d.ts +2 -0
  668. package/dist/components/ErrorIcon/ErrorIcon.vue.js +6 -0
  669. package/dist/components/ErrorIcon/ErrorIcon.vue_vue_type_script_setup_true_lang.js +16 -0
  670. package/dist/components/FlatListBox/FlatListBox.vue.d.ts +2 -5
  671. package/dist/components/FlatListBox/FlatListBox.vue.js +5 -0
  672. package/dist/components/FlatListBox/FlatListBox.vue_vue_type_script_setup_true_lang.js +167 -0
  673. package/dist/components/FlatListBox/types.d.ts +1 -1
  674. package/dist/components/GroupedListBox/GroupedListBox.vue.d.ts +2 -5
  675. package/dist/components/GroupedListBox/GroupedListBox.vue.js +5 -0
  676. package/dist/components/GroupedListBox/GroupedListBox.vue_vue_type_script_setup_true_lang.js +218 -0
  677. package/dist/components/ListBox/ListBox.vue.d.ts +3 -6
  678. package/dist/components/ListBox/ListBox.vue.js +5 -0
  679. package/dist/components/ListBox/ListBox.vue_vue_type_script_setup_true_lang.js +112 -0
  680. package/dist/components/ListBox/types.d.ts +1 -1
  681. package/dist/components/OptionsContainer/OptionsContainer.vue.d.ts +1 -0
  682. package/dist/components/OptionsContainer/OptionsContainer.vue.js +5 -0
  683. package/dist/components/OptionsContainer/OptionsContainer.vue_vue_type_script_setup_true_lang.js +52 -0
  684. package/dist/components/OptionsContainer/types.d.ts +14 -24
  685. package/dist/components/Transitions/ScaleFade.vue.js +5 -0
  686. package/dist/components/Transitions/ScaleFade.vue_vue_type_script_setup_true_lang.js +47 -0
  687. package/dist/components/Transitions/Slide.vue.js +7 -0
  688. package/dist/components/Transitions/Slide.vue_vue_type_script_setup_true_lang.js +28 -0
  689. package/dist/components/WarningIcon/WarningIcon.vue.d.ts +5 -0
  690. package/dist/components/WarningIcon/WarningIcon.vue.js +6 -0
  691. package/dist/components/WarningIcon/WarningIcon.vue_vue_type_script_setup_true_lang.js +16 -0
  692. package/dist/components/WarningIcon/types.d.ts +3 -0
  693. package/dist/composables/__testResets.d.ts +1 -0
  694. package/dist/composables/useActiveInactiveState.d.ts +4 -0
  695. package/dist/composables/useActiveInactiveState.js +21 -0
  696. package/dist/composables/useBaseOptions.d.ts +3 -3
  697. package/dist/composables/useBaseOptions.js +31 -0
  698. package/dist/composables/useBbConfig.d.ts +8 -37
  699. package/dist/composables/useBbConfig.js +5 -0
  700. package/dist/composables/useBbDropdownContext.d.ts +89 -0
  701. package/dist/composables/useBbDropdownContext.js +46 -0
  702. package/dist/composables/useBbFormContext.d.ts +90 -0
  703. package/dist/composables/useBbFormContext.js +69 -0
  704. package/dist/composables/useBbTableContext.d.ts +195 -0
  705. package/dist/composables/useBbTableContext.js +208 -0
  706. package/dist/composables/useBbTabsContext.d.ts +111 -0
  707. package/dist/composables/useBbTabsContext.js +219 -0
  708. package/dist/composables/useBreakpoint.d.ts +13 -0
  709. package/dist/composables/useBreakpoint.js +39 -0
  710. package/dist/composables/useBroadcastChannelInstance.d.ts +1 -3
  711. package/dist/composables/useBroadcastChannelInstance.js +39 -0
  712. package/dist/composables/useCancelableFunction.js +37 -0
  713. package/dist/composables/useCoherence.js +16 -0
  714. package/dist/composables/useConfirm.d.ts +257 -67
  715. package/dist/composables/useConfirm.js +122 -0
  716. package/dist/composables/useCountdown.js +42 -0
  717. package/dist/composables/useHashedWatcher.d.ts +17 -0
  718. package/dist/composables/useHashedWatcher.js +14 -0
  719. package/dist/composables/useId.d.ts +3 -2
  720. package/dist/composables/useIndexById.js +16 -0
  721. package/dist/composables/useInertiaPage.d.ts +10 -0
  722. package/dist/composables/useInertiaPage.js +8 -0
  723. package/dist/composables/useItemText.js +17 -0
  724. package/dist/composables/useItemValue.js +9 -0
  725. package/dist/composables/useItemsGetter.d.ts +1 -1
  726. package/dist/composables/useItemsGetter.js +30 -0
  727. package/dist/composables/useListboxFocus.js +66 -0
  728. package/dist/composables/useLocale.d.ts +1 -1
  729. package/dist/composables/useLocale.js +11 -0
  730. package/dist/composables/useLogger.d.ts +1 -1
  731. package/dist/composables/useLogger.js +10 -0
  732. package/dist/composables/useMinimalQueue.d.ts +1 -1
  733. package/dist/composables/useMobile.js +7 -0
  734. package/dist/composables/useOnFalsy.d.ts +2 -0
  735. package/dist/composables/useOnFalsy.js +9 -0
  736. package/dist/composables/useOnTruthy.d.ts +7 -0
  737. package/dist/composables/useOnTruthy.js +9 -0
  738. package/dist/composables/usePrefill.d.ts +2 -1
  739. package/dist/composables/usePrefill.js +24 -0
  740. package/dist/composables/useQuery.d.ts +15 -3
  741. package/dist/composables/useQuery.js +42 -0
  742. package/dist/composables/useRoute.js +11 -0
  743. package/dist/composables/useRouter.js +8 -0
  744. package/dist/composables/useSafeArea.d.ts +51 -0
  745. package/dist/composables/useSafeArea.js +16 -0
  746. package/dist/composables/useSegmentedFields.d.ts +103 -0
  747. package/dist/composables/useSegmentedFields.js +152 -0
  748. package/dist/composables/useTableWidthContext.d.ts +5 -0
  749. package/dist/composables/useTableWidthContext.js +42 -0
  750. package/dist/composables/useToast.d.ts +17 -73
  751. package/dist/composables/useToast.js +49 -0
  752. package/dist/composables/useTopLayer.d.ts +9 -0
  753. package/dist/composables/useTopLayer.js +7 -0
  754. package/dist/composables/useUntil.js +13 -0
  755. package/dist/composables/useViewportWidth.d.ts +17 -0
  756. package/dist/composables/useViewportWidth.js +6 -0
  757. package/dist/confirm-variants.d.ts +10 -0
  758. package/dist/deprecation/ai-deprecations.json.d.ts +784 -0
  759. package/dist/deprecation/ai-deprecations.json.js +4 -0
  760. package/dist/deprecation/removedProps.d.ts +3 -0
  761. package/dist/deprecation/removedProps.js +13 -0
  762. package/dist/directives/bbColor.d.ts +65 -0
  763. package/dist/directives/bbColor.js +24 -0
  764. package/dist/directives/bbDate.d.ts +66 -0
  765. package/dist/directives/bbDate.js +24 -0
  766. package/dist/directives/bbDropdown.d.ts +15 -11
  767. package/dist/directives/bbDropdown.js +23 -0
  768. package/dist/directives/bbTime.d.ts +64 -0
  769. package/dist/directives/bbTime.js +24 -0
  770. package/dist/directives/bbTooltip.d.ts +16 -11
  771. package/dist/directives/bbTooltip.js +24 -0
  772. package/dist/dropdown-item-variants.d.ts +10 -0
  773. package/dist/i18n/index.d.ts +51 -3
  774. package/dist/i18n/index.js +27 -0
  775. package/dist/i18n/locales/cs.json +115 -0
  776. package/dist/i18n/locales/da.json +115 -0
  777. package/dist/i18n/locales/de.json +115 -0
  778. package/dist/i18n/locales/el.json +115 -0
  779. package/dist/i18n/locales/en.json +115 -0
  780. package/dist/i18n/locales/es.json +115 -0
  781. package/dist/i18n/locales/fi.json +115 -0
  782. package/dist/i18n/locales/fr.json +115 -0
  783. package/dist/i18n/locales/hu.json +115 -0
  784. package/dist/i18n/locales/it.json +115 -0
  785. package/dist/i18n/locales/ja.json +115 -0
  786. package/dist/i18n/locales/ko.json +115 -0
  787. package/dist/i18n/locales/nb.json +115 -0
  788. package/dist/i18n/locales/nl.json +115 -0
  789. package/dist/i18n/locales/pl.json +115 -0
  790. package/dist/i18n/locales/pt.json +115 -0
  791. package/dist/i18n/locales/ro.json +115 -0
  792. package/dist/i18n/locales/ru.json +115 -0
  793. package/dist/i18n/locales/sv.json +115 -0
  794. package/dist/i18n/locales/tr.json +115 -0
  795. package/dist/i18n/locales/uk.json +115 -0
  796. package/dist/i18n/locales/zh-cn.json +115 -0
  797. package/dist/icons-whitelist.d.ts +8 -0
  798. package/dist/index.d.ts +94 -79
  799. package/dist/index.js +76 -82
  800. package/dist/indicator-variants.d.ts +13 -0
  801. package/dist/llms-full.txt +77073 -0
  802. package/dist/llms-medium.txt +1334 -0
  803. package/dist/llms.txt +103 -0
  804. package/dist/locale-blueprint.json +141 -0
  805. package/dist/nuxt-module.d.ts +3 -0
  806. package/dist/nuxt.js +19 -0
  807. package/dist/plugin.d.ts +4 -0
  808. package/dist/plugin.js +22 -0
  809. package/dist/reset.css +1 -0
  810. package/dist/reset.d.ts +0 -0
  811. package/dist/runtime/nuxt-plugin.d.ts +2 -0
  812. package/dist/runtime/nuxt-plugin.js +24 -0
  813. package/dist/styles.css +2 -0
  814. package/dist/styles.d.ts +0 -0
  815. package/dist/toast-variants.d.ts +13 -0
  816. package/dist/tooltip-variants.d.ts +10 -0
  817. package/dist/types/ActionButton.d.ts +32 -0
  818. package/dist/types/AlertVariant.d.ts +16 -0
  819. package/dist/types/BadgeVariant.d.ts +16 -0
  820. package/dist/types/ButtonVariant.d.ts +17 -0
  821. package/dist/types/Classes.d.ts +1 -1
  822. package/dist/types/ColumnName.d.ts +1 -1
  823. package/dist/types/CommonProps.d.ts +66 -279
  824. package/dist/types/Config.d.ts +84 -0
  825. package/dist/types/ConfirmVariant.d.ts +15 -0
  826. package/dist/types/DropdownItemVariant.d.ts +18 -0
  827. package/dist/types/Icon.d.ts +5 -7
  828. package/dist/types/IndicatorVariant.d.ts +16 -0
  829. package/dist/types/InputDirection.d.ts +15 -0
  830. package/dist/types/ItemAccessor.d.ts +21 -0
  831. package/dist/types/Placement.d.ts +6 -0
  832. package/dist/types/ResponsiveSize.d.ts +20 -0
  833. package/dist/types/SizeScale.d.ts +8 -0
  834. package/dist/types/ToastVariant.d.ts +17 -0
  835. package/dist/types/TooltipVariant.d.ts +18 -0
  836. package/dist/utilities/functions/bytesToUnit.d.ts +2 -0
  837. package/dist/utilities/functions/bytesToUnit.js +18 -0
  838. package/dist/utilities/functions/clampPrecision.js +10 -0
  839. package/dist/utilities/functions/convertDateValue.d.ts +23 -10
  840. package/dist/utilities/functions/convertDateValue.js +12 -0
  841. package/dist/utilities/functions/deburr.js +5 -0
  842. package/dist/utilities/functions/empty.js +5 -0
  843. package/dist/utilities/functions/flattenTree.d.ts +1 -1
  844. package/dist/utilities/functions/hash.js +5 -0
  845. package/dist/utilities/functions/isDateDisabled.d.ts +1 -0
  846. package/dist/utilities/functions/isDateDisabled.js +20 -0
  847. package/dist/utilities/functions/isEqual.js +5 -0
  848. package/dist/utilities/functions/isNotEmpty.js +5 -0
  849. package/dist/utilities/functions/matchAnyKey.d.ts +1 -1
  850. package/dist/utilities/functions/matchAnyKey.js +15 -0
  851. package/dist/utilities/functions/parseSize.d.ts +1 -1
  852. package/dist/utilities/functions/parseSize.js +15 -0
  853. package/dist/utilities/functions/percentage.js +11 -0
  854. package/dist/utilities/functions/pipe.d.ts +1 -1
  855. package/dist/utilities/functions/reject.d.ts +25 -0
  856. package/dist/utilities/functions/reject.js +28 -0
  857. package/dist/utilities/functions/resolveEnumProp.d.ts +19 -0
  858. package/dist/utilities/functions/resolveEnumProp.js +5 -0
  859. package/dist/utilities/functions/slotKey.d.ts +13 -0
  860. package/dist/utilities/functions/slotKey.js +4 -0
  861. package/dist/utilities/functions/sort.d.ts +2 -2
  862. package/dist/utilities/functions/sort.js +19 -0
  863. package/dist/utilities/functions/throttle.js +5 -0
  864. package/dist/utilities/functions/waitFor.d.ts +9 -2
  865. package/dist/utilities/functions/waitFor.js +14 -0
  866. package/dist/utilities/functions/warnRemovedAttrs.d.ts +11 -0
  867. package/dist/utilities/functions/warnRemovedAttrs.js +20 -0
  868. package/dist/utilities/functions/when.js +5 -0
  869. package/dist/utilities/misc/iconsInjectionKey.d.ts +15 -0
  870. package/dist/utilities/misc/iconsInjectionKey.js +4 -0
  871. package/dist/utilities/misc/transitions.d.ts +5 -0
  872. package/dist/utilities/misc/transitions.js +8 -0
  873. package/dist/utils/injectLibraryStyles.d.ts +6 -0
  874. package/dist/utils/injectLibraryStyles.js +38 -0
  875. package/dist/validated/BbCheckbox.vue.d.ts +29 -0
  876. package/dist/validated/BbCheckbox.vue.js +5 -0
  877. package/dist/validated/BbCheckbox.vue_vue_type_script_setup_true_lang.js +75 -0
  878. package/dist/validated/BbCheckboxGroup.vue.d.ts +34 -0
  879. package/dist/validated/BbCheckboxGroup.vue.js +5 -0
  880. package/dist/validated/BbCheckboxGroup.vue_vue_type_script_setup_true_lang.js +76 -0
  881. package/dist/validated/BbColorInput.vue.d.ts +36 -0
  882. package/dist/validated/BbColorInput.vue.js +5 -0
  883. package/dist/validated/BbColorInput.vue_vue_type_script_setup_true_lang.js +71 -0
  884. package/dist/validated/BbDatePickerInput.vue.d.ts +40 -0
  885. package/dist/validated/BbDatePickerInput.vue.js +5 -0
  886. package/dist/validated/BbDatePickerInput.vue_vue_type_script_setup_true_lang.js +87 -0
  887. package/dist/validated/BbDropzone.vue.d.ts +24 -0
  888. package/dist/validated/BbDropzone.vue.js +5 -0
  889. package/dist/validated/BbDropzone.vue_vue_type_script_setup_true_lang.js +45 -0
  890. package/dist/validated/BbForm.vue.d.ts +28 -0
  891. package/dist/validated/BbForm.vue.js +5 -0
  892. package/dist/validated/BbForm.vue_vue_type_script_setup_true_lang.js +42 -0
  893. package/dist/validated/BbNumberInput.vue.d.ts +36 -0
  894. package/dist/validated/BbNumberInput.vue.js +5 -0
  895. package/dist/validated/BbNumberInput.vue_vue_type_script_setup_true_lang.js +72 -0
  896. package/dist/validated/BbRadioGroup.vue.d.ts +34 -0
  897. package/dist/validated/BbRadioGroup.vue.js +5 -0
  898. package/dist/validated/BbRadioGroup.vue_vue_type_script_setup_true_lang.js +75 -0
  899. package/dist/validated/BbRating.vue.d.ts +30 -0
  900. package/dist/validated/BbRating.vue.js +5 -0
  901. package/dist/validated/BbRating.vue_vue_type_script_setup_true_lang.js +63 -0
  902. package/dist/validated/BbSelect.vue.d.ts +46 -0
  903. package/dist/validated/BbSelect.vue.js +5 -0
  904. package/dist/validated/BbSelect.vue_vue_type_script_setup_true_lang.js +100 -0
  905. package/dist/validated/BbSlider.vue.d.ts +36 -0
  906. package/dist/validated/BbSlider.vue.js +5 -0
  907. package/dist/validated/BbSlider.vue_vue_type_script_setup_true_lang.js +69 -0
  908. package/dist/validated/BbSwitch.vue.d.ts +29 -0
  909. package/dist/validated/BbSwitch.vue.js +5 -0
  910. package/dist/validated/BbSwitch.vue_vue_type_script_setup_true_lang.js +75 -0
  911. package/dist/validated/BbSwitchGroup.vue.d.ts +34 -0
  912. package/dist/validated/BbSwitchGroup.vue.js +5 -0
  913. package/dist/validated/BbSwitchGroup.vue_vue_type_script_setup_true_lang.js +76 -0
  914. package/dist/validated/BbTag.vue.d.ts +36 -0
  915. package/dist/validated/BbTag.vue.js +5 -0
  916. package/dist/validated/BbTag.vue_vue_type_script_setup_true_lang.js +72 -0
  917. package/dist/validated/BbTextInput.vue.d.ts +36 -0
  918. package/dist/validated/BbTextInput.vue.js +5 -0
  919. package/dist/validated/BbTextInput.vue_vue_type_script_setup_true_lang.js +72 -0
  920. package/dist/validated/BbTextarea.vue.d.ts +36 -0
  921. package/dist/validated/BbTextarea.vue.js +5 -0
  922. package/dist/validated/BbTextarea.vue_vue_type_script_setup_true_lang.js +70 -0
  923. package/dist/validated/BbTimePickerInput.vue.d.ts +36 -0
  924. package/dist/validated/BbTimePickerInput.vue.js +5 -0
  925. package/dist/validated/BbTimePickerInput.vue_vue_type_script_setup_true_lang.js +78 -0
  926. package/dist/validated/index.d.ts +29 -0
  927. package/dist/validated/useValidatedField.d.ts +52 -0
  928. package/dist/validated/useValidatedField.js +51 -0
  929. package/dist/validated.js +21 -0
  930. package/dist/vite-plugin.d.ts +217 -0
  931. package/dist/vite.js +530 -0
  932. package/llms.txt +105 -0
  933. package/package.json +162 -60
  934. package/scripts/lib/__fixtures__/validated-manifest.json +65 -0
  935. package/scripts/lib/ensure-manifest.mjs +39 -0
  936. package/scripts/lib/eslint-plugin-autofix.node.test.mjs +109 -0
  937. package/scripts/lib/eslint-plugin.mjs +285 -0
  938. package/scripts/lib/eslint-plugin.node.test.mjs +161 -0
  939. package/scripts/lib/html-attributes.mjs +191 -0
  940. package/scripts/lib/mcp-config.mjs +126 -0
  941. package/scripts/lib/migrate-fix.mjs +115 -0
  942. package/scripts/lib/validate-bb-markup.mjs +421 -0
  943. package/dist/ai/BaseButton.md +0 -449
  944. package/dist/ai/BaseCheckbox.md +0 -512
  945. package/dist/ai/BaseCheckboxGroup.md +0 -597
  946. package/dist/ai/BaseColorInput.md +0 -461
  947. package/dist/ai/BaseDatePicker.md +0 -739
  948. package/dist/ai/BaseDatePickerInput.md +0 -1517
  949. package/dist/ai/BaseDialog.md +0 -610
  950. package/dist/ai/BaseInputContainer.md +0 -570
  951. package/dist/ai/BaseNumberInput.md +0 -509
  952. package/dist/ai/BaseRadio.md +0 -405
  953. package/dist/ai/BaseRadioGroup.md +0 -535
  954. package/dist/ai/BaseRating.md +0 -489
  955. package/dist/ai/BaseSelect.md +0 -1742
  956. package/dist/ai/BaseSlider.md +0 -871
  957. package/dist/ai/BaseSwitch.md +0 -322
  958. package/dist/ai/BaseSwitchGroup.md +0 -298
  959. package/dist/ai/BaseTag.md +0 -623
  960. package/dist/ai/BaseTextInput.md +0 -392
  961. package/dist/ai/BaseTextarea.md +0 -398
  962. package/dist/ai/BbChip.md +0 -147
  963. package/dist/ai/BbIntersection.md +0 -120
  964. package/dist/ai/BbRatio.md +0 -61
  965. package/dist/ai/BbRows.md +0 -307
  966. package/dist/ai/BbTab.md +0 -950
  967. package/dist/ai/CommonInputInnerContainer.md +0 -414
  968. package/dist/ai/CommonInputOuterContainer.md +0 -55
  969. package/dist/components/BaseButton/BaseButton.vue.d.ts +0 -14
  970. package/dist/components/BaseButton/types.d.ts +0 -159
  971. package/dist/components/BaseCheckbox/BaseCheckbox.vue.d.ts +0 -39
  972. package/dist/components/BaseCheckbox/types.d.ts +0 -213
  973. package/dist/components/BaseCheckboxGroup/BaseCheckboxGroup.vue.d.ts +0 -30
  974. package/dist/components/BaseCheckboxGroup/types.d.ts +0 -282
  975. package/dist/components/BaseColorInput/BaseColorInput.vue.d.ts +0 -35
  976. package/dist/components/BaseColorInput/ColorPalette.vue.d.ts +0 -13
  977. package/dist/components/BaseColorInput/types.d.ts +0 -233
  978. package/dist/components/BaseDatePicker/BaseDatePickerHeader.vue.d.ts +0 -15
  979. package/dist/components/BaseDatePicker/BaseDatePickerInputDaySelector.vue.d.ts +0 -58
  980. package/dist/components/BaseDatePicker/BaseDatePickerMonthSelector.vue.d.ts +0 -12
  981. package/dist/components/BaseDatePicker/BaseDatePickerYearSelector.vue.d.ts +0 -12
  982. package/dist/components/BaseDatePicker/types.d.ts +0 -100
  983. package/dist/components/BaseDatePickerInput/BaseDatePickerInput.vue.d.ts +0 -26
  984. package/dist/components/BaseDatePickerInput/types.d.ts +0 -206
  985. package/dist/components/BaseDialog/BaseDialog.vue.d.ts +0 -37
  986. package/dist/components/BaseDialog/types.d.ts +0 -180
  987. package/dist/components/BaseInputContainer/BaseInputContainer.vue.d.ts +0 -18
  988. package/dist/components/BaseInputContainer/types.d.ts +0 -126
  989. package/dist/components/BaseNumberInput/BaseNumberInput.vue.d.ts +0 -46
  990. package/dist/components/BaseNumberInput/types.d.ts +0 -191
  991. package/dist/components/BaseRadio/BaseRadio.vue.d.ts +0 -31
  992. package/dist/components/BaseRadio/types.d.ts +0 -173
  993. package/dist/components/BaseRadioGroup/BaseRadioGroup.vue.d.ts +0 -30
  994. package/dist/components/BaseRadioGroup/types.d.ts +0 -240
  995. package/dist/components/BaseRating/BaseRating.vue.d.ts +0 -35
  996. package/dist/components/BaseRating/types.d.ts +0 -144
  997. package/dist/components/BaseSelect/BaseSelect.vue.d.ts +0 -28
  998. package/dist/components/BaseSelect/types.d.ts +0 -470
  999. package/dist/components/BaseSlider/BaseSlider.vue.d.ts +0 -38
  1000. package/dist/components/BaseSlider/types.d.ts +0 -201
  1001. package/dist/components/BaseSwitch/BaseSwitch.vue.d.ts +0 -34
  1002. package/dist/components/BaseSwitch/types.d.ts +0 -25
  1003. package/dist/components/BaseSwitchGroup/BaseSwitchGroup.vue.d.ts +0 -30
  1004. package/dist/components/BaseSwitchGroup/types.d.ts +0 -8
  1005. package/dist/components/BaseTag/BaseTag.vue.d.ts +0 -37
  1006. package/dist/components/BaseTag/types.d.ts +0 -136
  1007. package/dist/components/BaseTextInput/BaseTextInput.vue.d.ts +0 -33
  1008. package/dist/components/BaseTextInput/types.d.ts +0 -166
  1009. package/dist/components/BaseTextarea/BaseTextarea.vue.d.ts +0 -31
  1010. package/dist/components/BaseTextarea/types.d.ts +0 -151
  1011. package/dist/components/BbChip/BbChip.vue.d.ts +0 -17
  1012. package/dist/components/BbChip/types.d.ts +0 -23
  1013. package/dist/components/BbIntersection/BbIntersection.vue.d.ts +0 -23
  1014. package/dist/components/BbIntersection/types.d.ts +0 -36
  1015. package/dist/components/BbRatio/BbRatio.vue.d.ts +0 -14
  1016. package/dist/components/BbRatio/types.d.ts +0 -15
  1017. package/dist/components/BbRows/BbRows.vue.d.ts +0 -62
  1018. package/dist/components/BbRows/types.d.ts +0 -21
  1019. package/dist/components/BbTab/BbTab.vue.d.ts +0 -27
  1020. package/dist/components/BbTab/types.d.ts +0 -186
  1021. package/dist/components/CommonInputInnerContainer/CommonInputInnerContainer.vue.d.ts +0 -15
  1022. package/dist/components/CommonInputInnerContainer/types.d.ts +0 -47
  1023. package/dist/components/CommonInputOuterContainer/CommonInputOuterContainer.vue.d.ts +0 -11
  1024. package/dist/components/CommonInputOuterContainer/types.d.ts +0 -16
  1025. package/dist/composables/useModalsState.d.ts +0 -5
  1026. package/dist/composables/useQueue.d.ts +0 -58
  1027. package/dist/composables/useWizard.d.ts +0 -85
  1028. package/dist/i18n/en.d.ts +0 -67
  1029. package/dist/i18n/it.d.ts +0 -67
  1030. package/dist/index.css +0 -2
  1031. package/dist/index100.js +0 -6
  1032. package/dist/index101.js +0 -300
  1033. package/dist/index102.js +0 -16
  1034. package/dist/index103.js +0 -16
  1035. package/dist/index104.js +0 -27
  1036. package/dist/index109.js +0 -19
  1037. package/dist/index11.js +0 -42
  1038. package/dist/index110.js +0 -12
  1039. package/dist/index111.js +0 -19
  1040. package/dist/index112.js +0 -25
  1041. package/dist/index114.js +0 -7
  1042. package/dist/index115.js +0 -241
  1043. package/dist/index116.js +0 -5
  1044. package/dist/index117.js +0 -42
  1045. package/dist/index118.js +0 -5
  1046. package/dist/index119.js +0 -53
  1047. package/dist/index120.js +0 -5
  1048. package/dist/index121.js +0 -32
  1049. package/dist/index122.js +0 -5
  1050. package/dist/index124.js +0 -52
  1051. package/dist/index125.js +0 -5
  1052. package/dist/index126.js +0 -223
  1053. package/dist/index128.js +0 -6
  1054. package/dist/index129.js +0 -162
  1055. package/dist/index13.js +0 -92
  1056. package/dist/index130.js +0 -25
  1057. package/dist/index131.js +0 -51
  1058. package/dist/index132.js +0 -5
  1059. package/dist/index133.js +0 -607
  1060. package/dist/index135.js +0 -6
  1061. package/dist/index136.js +0 -14
  1062. package/dist/index137.js +0 -153
  1063. package/dist/index139.js +0 -6
  1064. package/dist/index14.js +0 -306
  1065. package/dist/index140.js +0 -224
  1066. package/dist/index141.js +0 -5
  1067. package/dist/index143.js +0 -128
  1068. package/dist/index145.js +0 -6
  1069. package/dist/index146.js +0 -8
  1070. package/dist/index147.js +0 -182
  1071. package/dist/index149.js +0 -6
  1072. package/dist/index15.js +0 -10
  1073. package/dist/index151.js +0 -4
  1074. package/dist/index152.js +0 -95
  1075. package/dist/index154.js +0 -6
  1076. package/dist/index155.js +0 -168
  1077. package/dist/index157.js +0 -6
  1078. package/dist/index158.js +0 -145
  1079. package/dist/index16.js +0 -59
  1080. package/dist/index160.js +0 -6
  1081. package/dist/index161.js +0 -53
  1082. package/dist/index163.js +0 -6
  1083. package/dist/index164.js +0 -16
  1084. package/dist/index166.js +0 -35
  1085. package/dist/index168.js +0 -6
  1086. package/dist/index169.js +0 -89
  1087. package/dist/index171.js +0 -6
  1088. package/dist/index172.js +0 -82
  1089. package/dist/index174.js +0 -6
  1090. package/dist/index175.js +0 -38
  1091. package/dist/index176.js +0 -461
  1092. package/dist/index177.js +0 -28
  1093. package/dist/index178.js +0 -66
  1094. package/dist/index18.js +0 -35
  1095. package/dist/index180.js +0 -162
  1096. package/dist/index181.js +0 -5
  1097. package/dist/index182.js +0 -217
  1098. package/dist/index183.js +0 -5
  1099. package/dist/index184.js +0 -112
  1100. package/dist/index185.js +0 -5
  1101. package/dist/index186.js +0 -459
  1102. package/dist/index188.js +0 -6
  1103. package/dist/index19.js +0 -4
  1104. package/dist/index192.js +0 -268
  1105. package/dist/index194.js +0 -6
  1106. package/dist/index195.js +0 -124
  1107. package/dist/index197.js +0 -6
  1108. package/dist/index198.js +0 -174
  1109. package/dist/index2.js +0 -20
  1110. package/dist/index20.js +0 -9
  1111. package/dist/index200.js +0 -6
  1112. package/dist/index201.js +0 -224
  1113. package/dist/index203.js +0 -6
  1114. package/dist/index204.js +0 -135
  1115. package/dist/index206.js +0 -6
  1116. package/dist/index207.js +0 -5
  1117. package/dist/index208.js +0 -170
  1118. package/dist/index21.js +0 -35
  1119. package/dist/index210.js +0 -6
  1120. package/dist/index211.js +0 -37
  1121. package/dist/index213.js +0 -6
  1122. package/dist/index214.js +0 -63
  1123. package/dist/index216.js +0 -6
  1124. package/dist/index217.js +0 -74
  1125. package/dist/index219.js +0 -6
  1126. package/dist/index22.js +0 -6
  1127. package/dist/index220.js +0 -65
  1128. package/dist/index222.js +0 -6
  1129. package/dist/index223.js +0 -67
  1130. package/dist/index225.js +0 -6
  1131. package/dist/index226.js +0 -41
  1132. package/dist/index228.js +0 -6
  1133. package/dist/index229.js +0 -10
  1134. package/dist/index23.js +0 -7
  1135. package/dist/index230.js +0 -22
  1136. package/dist/index232.js +0 -8
  1137. package/dist/index233.js +0 -297
  1138. package/dist/index235.js +0 -6
  1139. package/dist/index236.js +0 -47
  1140. package/dist/index237.js +0 -165
  1141. package/dist/index239.js +0 -6
  1142. package/dist/index24.js +0 -9
  1143. package/dist/index241.js +0 -159
  1144. package/dist/index243.js +0 -6
  1145. package/dist/index244.js +0 -134
  1146. package/dist/index246.js +0 -6
  1147. package/dist/index247.js +0 -167
  1148. package/dist/index249.js +0 -6
  1149. package/dist/index25.js +0 -24
  1150. package/dist/index250.js +0 -147
  1151. package/dist/index252.js +0 -6
  1152. package/dist/index253.js +0 -35
  1153. package/dist/index255.js +0 -6
  1154. package/dist/index256.js +0 -65
  1155. package/dist/index258.js +0 -6
  1156. package/dist/index259.js +0 -19
  1157. package/dist/index260.js +0 -5
  1158. package/dist/index261.js +0 -160
  1159. package/dist/index263.js +0 -6
  1160. package/dist/index264.js +0 -60
  1161. package/dist/index266.js +0 -6
  1162. package/dist/index267.js +0 -134
  1163. package/dist/index269.js +0 -6
  1164. package/dist/index27.js +0 -4
  1165. package/dist/index271.js +0 -206
  1166. package/dist/index273.js +0 -6
  1167. package/dist/index274.js +0 -85
  1168. package/dist/index275.js +0 -5
  1169. package/dist/index276.js +0 -55
  1170. package/dist/index277.js +0 -5
  1171. package/dist/index278.js +0 -164
  1172. package/dist/index28.js +0 -8
  1173. package/dist/index280.js +0 -6
  1174. package/dist/index281.js +0 -145
  1175. package/dist/index283.js +0 -6
  1176. package/dist/index284.js +0 -11
  1177. package/dist/index285.js +0 -200
  1178. package/dist/index287.js +0 -6
  1179. package/dist/index288.js +0 -241
  1180. package/dist/index29.js +0 -7
  1181. package/dist/index290.js +0 -6
  1182. package/dist/index291.js +0 -21
  1183. package/dist/index293.js +0 -6
  1184. package/dist/index294.js +0 -125
  1185. package/dist/index296.js +0 -6
  1186. package/dist/index297.js +0 -161
  1187. package/dist/index299.js +0 -6
  1188. package/dist/index30.js +0 -118
  1189. package/dist/index300.js +0 -127
  1190. package/dist/index302.js +0 -6
  1191. package/dist/index303.js +0 -20
  1192. package/dist/index305.js +0 -6
  1193. package/dist/index306.js +0 -116
  1194. package/dist/index307.js +0 -5
  1195. package/dist/index308.js +0 -507
  1196. package/dist/index31.js +0 -10
  1197. package/dist/index310.js +0 -6
  1198. package/dist/index311.js +0 -196
  1199. package/dist/index313.js +0 -6
  1200. package/dist/index314.js +0 -142
  1201. package/dist/index316.js +0 -6
  1202. package/dist/index317.js +0 -134
  1203. package/dist/index319.js +0 -6
  1204. package/dist/index32.js +0 -28
  1205. package/dist/index320.js +0 -162
  1206. package/dist/index322.js +0 -6
  1207. package/dist/index323.js +0 -319
  1208. package/dist/index325.js +0 -6
  1209. package/dist/index326.js +0 -40
  1210. package/dist/index327.js +0 -43
  1211. package/dist/index328.js +0 -665
  1212. package/dist/index33.js +0 -5
  1213. package/dist/index330.js +0 -6
  1214. package/dist/index331.js +0 -155
  1215. package/dist/index333.js +0 -6
  1216. package/dist/index334.js +0 -142
  1217. package/dist/index336.js +0 -6
  1218. package/dist/index337.js +0 -155
  1219. package/dist/index339.js +0 -6
  1220. package/dist/index34.js +0 -112
  1221. package/dist/index340.js +0 -58
  1222. package/dist/index341.js +0 -5
  1223. package/dist/index342.js +0 -20
  1224. package/dist/index344.js +0 -6
  1225. package/dist/index345.js +0 -142
  1226. package/dist/index347.js +0 -6
  1227. package/dist/index349.js +0 -109
  1228. package/dist/index351.js +0 -6
  1229. package/dist/index353.js +0 -24
  1230. package/dist/index354.js +0 -23
  1231. package/dist/index355.js +0 -839
  1232. package/dist/index356.js +0 -474
  1233. package/dist/index357.js +0 -52
  1234. package/dist/index358.js +0 -7
  1235. package/dist/index36.js +0 -6
  1236. package/dist/index38.js +0 -63
  1237. package/dist/index39.js +0 -63
  1238. package/dist/index40.js +0 -9
  1239. package/dist/index42.js +0 -8
  1240. package/dist/index43.js +0 -179
  1241. package/dist/index44.js +0 -21
  1242. package/dist/index46.js +0 -385
  1243. package/dist/index48.js +0 -6
  1244. package/dist/index49.js +0 -33
  1245. package/dist/index5.js +0 -34
  1246. package/dist/index50.js +0 -12
  1247. package/dist/index51.js +0 -8
  1248. package/dist/index52.js +0 -106
  1249. package/dist/index53.js +0 -330
  1250. package/dist/index54.js +0 -97
  1251. package/dist/index55.js +0 -328
  1252. package/dist/index56.js +0 -28
  1253. package/dist/index57.js +0 -102
  1254. package/dist/index58.js +0 -157
  1255. package/dist/index6.js +0 -38
  1256. package/dist/index60.js +0 -6
  1257. package/dist/index61.js +0 -131
  1258. package/dist/index62.js +0 -5
  1259. package/dist/index65.js +0 -35
  1260. package/dist/index66.js +0 -26
  1261. package/dist/index68.js +0 -6
  1262. package/dist/index69.js +0 -54
  1263. package/dist/index7.js +0 -58
  1264. package/dist/index71.js +0 -6
  1265. package/dist/index72.js +0 -14
  1266. package/dist/index74.js +0 -6
  1267. package/dist/index75.js +0 -159
  1268. package/dist/index77.js +0 -6
  1269. package/dist/index78.js +0 -4
  1270. package/dist/index79.js +0 -4
  1271. package/dist/index80.js +0 -54
  1272. package/dist/index81.js +0 -5
  1273. package/dist/index82.js +0 -5
  1274. package/dist/index83.js +0 -141
  1275. package/dist/index85.js +0 -6
  1276. package/dist/index86.js +0 -65
  1277. package/dist/index88.js +0 -6
  1278. package/dist/index89.js +0 -30
  1279. package/dist/index9.js +0 -11
  1280. package/dist/index90.js +0 -19
  1281. package/dist/index91.js +0 -17
  1282. package/dist/index92.js +0 -9
  1283. package/dist/index93.js +0 -34
  1284. package/dist/index95.js +0 -16
  1285. package/dist/index96.js +0 -10
  1286. package/dist/index97.js +0 -18
  1287. package/dist/index98.js +0 -189
  1288. package/dist/types/VoidHtmlElements.d.ts +0 -1
  1289. package/dist/utilities/functions/add.d.ts +0 -1
  1290. package/dist/utilities/functions/booleanishToBoolean.d.ts +0 -6
  1291. package/dist/utilities/functions/capitalize.d.ts +0 -4
  1292. package/dist/utilities/functions/cloneDeep.d.ts +0 -1
  1293. package/dist/utilities/functions/debounce.d.ts +0 -1
  1294. package/dist/utilities/functions/drop.d.ts +0 -1
  1295. package/dist/utilities/functions/exceedsPrecision.d.ts +0 -1
  1296. package/dist/utilities/functions/findRight.d.ts +0 -4
  1297. package/dist/utilities/functions/findRightIndex.d.ts +0 -4
  1298. package/dist/utilities/functions/flow.d.ts +0 -1
  1299. package/dist/utilities/functions/getHueFromRGB.d.ts +0 -9
  1300. package/dist/utilities/functions/groupBy.d.ts +0 -6
  1301. package/dist/utilities/functions/gt.d.ts +0 -7
  1302. package/dist/utilities/functions/hexToRGB.d.ts +0 -7
  1303. package/dist/utilities/functions/hslToHex.d.ts +0 -1
  1304. package/dist/utilities/functions/includes.d.ts +0 -1
  1305. package/dist/utilities/functions/initial.d.ts +0 -1
  1306. package/dist/utilities/functions/isCssColor.d.ts +0 -5
  1307. package/dist/utilities/functions/lt.d.ts +0 -7
  1308. package/dist/utilities/functions/makeUrl.d.ts +0 -1
  1309. package/dist/utilities/functions/mapKeys.d.ts +0 -5
  1310. package/dist/utilities/functions/mapValues.d.ts +0 -1
  1311. package/dist/utilities/functions/matchesPropertyInsensitive.d.ts +0 -1
  1312. package/dist/utilities/functions/max.d.ts +0 -2
  1313. package/dist/utilities/functions/mean.d.ts +0 -4
  1314. package/dist/utilities/functions/merge.d.ts +0 -11
  1315. package/dist/utilities/functions/millisecondsTo.d.ts +0 -1
  1316. package/dist/utilities/functions/negate.d.ts +0 -4
  1317. package/dist/utilities/functions/normalizeItemGroups.d.ts +0 -13
  1318. package/dist/utilities/functions/omit.d.ts +0 -2
  1319. package/dist/utilities/functions/overEvery.d.ts +0 -4
  1320. package/dist/utilities/functions/pick.d.ts +0 -1
  1321. package/dist/utilities/functions/replace.d.ts +0 -1
  1322. package/dist/utilities/functions/replaceInTree.d.ts +0 -4
  1323. package/dist/utilities/functions/retry.d.ts +0 -5
  1324. package/dist/utilities/functions/roundToTheNearest.d.ts +0 -8
  1325. package/dist/utilities/functions/set.d.ts +0 -15
  1326. package/dist/utilities/functions/stub.d.ts +0 -6
  1327. package/dist/utilities/functions/transposePercent.d.ts +0 -9
  1328. package/dist/utilities/functions/tryTo.d.ts +0 -2
  1329. package/dist/utilities/functions/uniqBy.d.ts +0 -1
  1330. /package/dist/{index64.js → _virtual/_plugin-vue_export-helper.js} +0 -0
  1331. /package/dist/components/{BaseButton → BbBaseButton}/RouterComponent.vue.d.ts +0 -0
  1332. /package/dist/components/{BaseDatePicker/BaseDatePicker.vue.d.ts → BbBaseDatePicker/BbBaseDatePicker.vue.d.ts} +0 -0
  1333. /package/dist/{index165.js → composables/useArray.js} +0 -0
  1334. /package/dist/{index17.js → composables/useFrameworkDetection.js} +0 -0
  1335. /package/dist/{index12.js → composables/useId.js} +0 -0
  1336. /package/dist/{index352.js → directives/createPopoverDirective.js} +0 -0
  1337. /package/dist/{index107.js → utilities/functions/chunk.js} +0 -0
  1338. /package/dist/{index8.js → utilities/functions/clamp.js} +0 -0
  1339. /package/dist/{index150.js → utilities/functions/curry.js} +0 -0
  1340. /package/dist/{index45.js → utilities/functions/extractDomContainer.js} +0 -0
  1341. /package/dist/{index270.js → utilities/functions/findInTree.js} +0 -0
  1342. /package/dist/{index348.js → utilities/functions/flattenTree.js} +0 -0
  1343. /package/dist/{index41.js → utilities/functions/get.js} +0 -0
  1344. /package/dist/{index189.js → utilities/functions/head.js} +0 -0
  1345. /package/dist/{index108.js → utilities/functions/identity.js} +0 -0
  1346. /package/dist/{index179.js → utilities/functions/indexBy.js} +0 -0
  1347. /package/dist/{index37.js → utilities/functions/isHex.js} +0 -0
  1348. /package/dist/{index94.js → utilities/functions/isNil.js} +0 -0
  1349. /package/dist/{index26.js → utilities/functions/isNotNil.js} +0 -0
  1350. /package/dist/{index105.js → utilities/functions/last.js} +0 -0
  1351. /package/dist/{index142.js → utilities/functions/noop.js} +0 -0
  1352. /package/dist/{index231.js → utilities/functions/parseWidthString.js} +0 -0
  1353. /package/dist/{index240.js → utilities/functions/pickBy.js} +0 -0
  1354. /package/dist/{index123.js → utilities/functions/range.js} +0 -0
  1355. /package/dist/{index190.js → utilities/functions/snapToStep.js} +0 -0
  1356. /package/dist/{index191.js → utilities/functions/transpose.js} +0 -0
  1357. /package/dist/{index106.js → utilities/functions/validateDateFormat.js} +0 -0
  1358. /package/dist/{index10.js → utilities/functions/wait.js} +0 -0
@@ -1,1669 +1,1330 @@
1
1
  # BbSelectPopover
2
2
 
3
- ## Template & Script
3
+ ## Agent Contract
4
+
5
+ - Safety level: **Consumer API**
6
+ - Group: **Selection**
7
+ - Description: Provides popover-driven option selection and search.
8
+ - Usage rule: Prefer this component for consumer-facing implementations.
9
+ - Implementation source (only when the contract below is not enough): [source/BbSelectPopover.md](./source/BbSelectPopover.md)
10
+
11
+ ## Usage & Guidelines
12
+
13
+ ### When to use
14
+
15
+ `BbSelectPopover` is `BbSelect` with the inline form input removed: **you own the
16
+ trigger**, it owns search, filtering, keyboard navigation, single/multiple
17
+ selection and the virtualized options list. Reach for it when the control that
18
+ opens the picker is _not_ a form field — a status pill, an avatar stack, a role
19
+ badge, a toolbar button, a table-cell chip. It is the right tool for
20
+ command-palette and inline-edit patterns.
21
+
22
+ Prefer a sibling when the shape is different:
23
+
24
+ - You want a **labelled, bordered form control** with hint/error/description
25
+ states → `BbSelect` (`./BbSelect.md`). That is a field, not a trigger.
26
+ - A small, always-visible exclusive choice → `BbRadioGroup`; small static
27
+ multi-choice → `BbCheckboxGroup` / `BbSwitchGroup`.
28
+ - Values the user _invents_ → `BbTag`; a known-but-growable set →
29
+ `BbSelectPopover` (or `BbSelect`) with `option:add`.
30
+
31
+ Everything from the **Options and Items** and **Fetch Items** playbooks carries
32
+ over unchanged — this component shares `BbSelect`'s option engine. This guide
33
+ covers what is _specific_ to the popover: the activator, and the traps of
34
+ driving a trigger you render yourself.
35
+
36
+ ### Map options with `item-text` / `item-value`
37
+
38
+ Pass your domain objects to `items` as they are and name the display/value
39
+ fields with `item-text` / `item-value` (dot-paths or extractor functions). The
40
+ `v-model` holds the resolved **value**, not the whole object. The value-identity
41
+ rules are the shared ones (see the Options and Items playbook), in brief:
42
+
43
+ - Primitive `items` (`string[]` / `number[]`) need no mapping props; for object
44
+ items always set both.
45
+ - Matching compares **value hashes** (deep structural equality), so object
46
+ values survive refetches — but prefer stable primitive ids.
47
+ - Options resolving to a **duplicate value are silently dropped** (first wins).
48
+ - Gate individual options with `selectable` — a boolean (`false` disables every
49
+ option) or a predicate `(item) => boolean`; rejected options render disabled
50
+ and keyboard navigation skips them. A `disabled` field on the item object is
51
+ inert domain data — feed it to the predicate
52
+ (`:selectable="(item) => !item.disabled"`) if it encodes availability.
53
+
54
+ ### Wire up an activator
55
+
56
+ Provide the trigger through the `#activator` slot and **spread its `props` onto
57
+ your element** with `v-bind="props"` — that wires the popover reference and the
58
+ open/close handlers. The full slot scope:
59
+
60
+ - `props` — spread onto the focusable trigger element.
61
+ - `shown` — is the popover open (reflect it visually).
62
+ - `toggle` / `open` / `close` — imperative open-state control (all async).
63
+ - `clear` — empty the selection (and query).
64
+ - `focus` — focus the search field (or the listbox when writing is disabled).
65
+ - `query` — the current search string.
66
+ - `selectedOptions` — the resolved selected options (`.text` / `.value` /
67
+ `.item`) — **popover state** (see below).
68
+ - `text` — display text of the current selection — **popover state** (see below).
69
+ - `disabled` / `readonly` / `loading` — state mirrors for styling the trigger.
70
+
71
+ **The trigger must not depend on the popover's state — label it from your own
72
+ data.** The popover is an _optional_ editing affordance: it may never be opened,
73
+ and whether it has been opened must never change how the trigger reads. `text`
74
+ and `selectedOptions` resolve the model against **loaded options**, so with a
75
+ provider they stay empty until that provider first runs — by default, the first
76
+ open. A trigger fed from them renders blank and then flickers into truth; a
77
+ trigger fed from your own data is correct on first paint and stays that way.
78
+
79
+ The robust pattern — used in the example — is a `computed` that resolves the
80
+ label from the model against your own data:
81
+
82
+ ```ts
83
+ const assigneeLabel = computed(
84
+ () => people.find((p) => p.id === assignee.value)?.name ?? 'Unassigned'
85
+ );
86
+ ```
87
+
88
+ (Array `items` do resolve on mount, so `text` is populated from the first paint
89
+ there — but keep labelling from your own data anyway: it is the same amount of
90
+ code, and it does not change meaning the day the array becomes a provider.)
91
+
92
+ **Filter-pill assignee picker**
4
93
 
5
94
  ```vue
6
95
  <template>
7
- <slot
8
- v-if="!hasExternalActivator"
9
- name="activator"
10
- v-bind="{
11
- props: {
12
- ref: setActivatorRef,
13
- },
14
- shown,
15
- disabled,
16
- readonly,
17
- loading: computedLoading,
18
- query,
19
- selectedOptions,
20
- text: triggerInputValue,
21
- clear: onClear,
22
- open,
23
- close,
24
- toggle,
25
- }"
26
- />
27
- <CommonPopover
28
- v-model="shown"
29
- v-bind="$attrs"
30
- :anchor="activatorEl"
31
- :arrow-padding="arrowPadding"
32
- :boundary="boundary"
33
- class="bb-select-popover"
34
- :class="{
35
- 'bb-select-popover--errors': hasErrors,
36
- 'bb-select-popover--loading': computedLoading,
37
- }"
38
- :flip="flip"
39
- :placement="placement"
40
- :offset="offset"
41
- :padding="padding"
42
- :transition-duration="transitionDuration"
43
- :hide-arrow="hideArrow"
44
- :style="panelStyles"
96
+ <div
97
+ class="flex max-w-sm items-center gap-1.5 rounded-[var(--bb-radius)] border p-2"
45
98
  >
46
- <div
47
- v-if="computedAllowWriting"
48
- class="bb-select-popover__search-container"
99
+ <span class="pr-1 text-xs font-medium text-gray-500">Assignee</span>
100
+ <BbSelectPopover
101
+ v-model="assignee"
102
+ compact
103
+ item-text="fullName"
104
+ item-value="id"
105
+ :items="teammates"
106
+ width="240px"
49
107
  >
50
- <input
51
- :id="`${id}_search`"
52
- ref="searchInput"
53
- v-model="query"
54
- :aria-activedescendant="activeDescendantId"
55
- :aria-controls="renderListBox ? `${id}_listbox` : undefined"
56
- :aria-describedby="computedAriaDescribedby"
57
- :aria-invalid="computedAriaInvalid"
58
- :aria-label="searchInputAriaLabel"
59
- :autocomplete="autocomplete"
60
- class="bb-select-popover__search-input"
61
- :inputmode="inputmode"
62
- :tabindex="shown ? 0 : -1"
63
- role="searchbox"
64
- :type="'text'"
65
- @blur.stop="onSearchInputBlur"
66
- @change.stop="onSearchInputChange"
67
- @focus.stop="onSearchInputFocus"
68
- @input.stop="onSearchInputInput"
69
- @keydown.stop.prevent.down="onArrowDown"
70
- @keydown.stop.prevent.enter="onEnter"
71
- @keydown.stop.prevent.esc="onEscape"
72
- @keydown.stop.prevent.up="onArrowUp"
73
- />
74
- <ErrorIcon
75
- aria-hidden="true"
76
- class="bb-select-popover__search-error-icon"
77
- focusable="false"
78
- />
79
- <BbSpinner
80
- aria-hidden="true"
81
- class="bb-select-popover__search-spinner"
82
- focusable="false"
83
- />
84
- <svg
85
- class="bb-select-popover__search-icon"
86
- xmlns="http://www.w3.org/2000/svg"
87
- viewBox="0 0 24 24"
88
- aria-hidden="true"
89
- >
90
- <path
91
- fill="none"
92
- stroke="currentColor"
93
- stroke-linecap="round"
94
- stroke-linejoin="round"
95
- stroke-width="2"
96
- d="m21 21-4.343-4.343m0 0A8 8 0 1 0 5.343 5.343a8 8 0 0 0 11.314 11.314"
97
- />
98
- </svg>
99
- </div>
100
- <button
101
- v-else
102
- ref="popoverFocusProxy"
103
- class="bb-select-popover__focus-proxy sr-only"
104
- type="button"
105
- :aria-controls="`${id}_listbox`"
106
- :aria-describedby="computedAriaDescribedby"
107
- :aria-invalid="computedAriaInvalid"
108
- :aria-label="searchInputAriaLabel"
109
- tabindex="-1"
110
- @focus="onPopoverFocusProxyFocus"
111
- @keydown.stop.prevent.down="onArrowDown"
112
- @keydown.stop.prevent.up="onArrowUp"
113
- @keydown.stop.prevent.enter="onEnter"
114
- @keydown.stop.prevent.esc="onEscape"
115
- >
116
- Focus options
117
- </button>
118
- <div
119
- class="bb-select-popover__options-outer"
120
- :aria-hidden="shown ? undefined : 'true'"
121
- :inert="!shown"
122
- >
123
- <slot name="options:prepend:outer" :focus="focusPopoverContent" />
124
- </div>
125
- <ListBox
126
- :id="`${id}_listbox`"
127
- ref="optionsContainer"
128
- :compact="compact"
129
- :loading="computedLoading"
130
- :loading-text="loadingText"
131
- :multiple="multiple"
132
- :no-data-text="noDataText"
133
- :open="shown"
134
- :options="groupBy ? undefined : filteredOptions"
135
- :groups="groupBy ? groupedOptions : undefined"
136
- :header-height="headerHeight"
137
- :option-height="itemHeight"
138
- @focused:change="onListboxFocusedChange"
139
- @option:selected="onOptionSelected"
140
- @option:unselected="onOptionUnselected"
141
- >
142
- <template #options:prepend
143
- ><slot name="options:prepend" :focus="focusPopoverContent"
144
- /></template>
145
- <template #loading><slot name="loading" :query="query" /></template>
146
- <template #no-data
147
- ><slot name="no-data" :query="query" :focus="focusPopoverContent"
148
- /></template>
149
- <template #options:append
150
- ><slot name="options:append" :focus="focusPopoverContent"
151
- /></template>
152
- <template #option="data"
153
- ><slot :loading="computedLoading" name="option" v-bind="data"
154
- /></template>
155
- <template #group="data"><slot name="group" v-bind="data" /></template>
156
- </ListBox>
157
- <div
158
- class="bb-select-popover__options-outer"
159
- :aria-hidden="shown ? undefined : 'true'"
160
- :inert="!shown"
161
- >
162
- <slot name="options:append:outer" :focus="focusPopoverContent" />
163
- </div>
164
- </CommonPopover>
108
+ <template #activator="{ props }">
109
+ <!-- The badge IS the trigger — Linear filter-pill grammar. Label
110
+ from our own state, never the slot's `text` (empty until first open
111
+ with a provider). -->
112
+ <BbBadge
113
+ append:icon="lucide:chevron-down"
114
+ prepend:icon="lucide:user"
115
+ size="lg"
116
+ variant="outline"
117
+ >
118
+ <BbBadgeButton v-bind="props">{{
119
+ assigneeLabel || 'Assign'
120
+ }}</BbBadgeButton>
121
+ </BbBadge>
122
+ </template>
123
+ </BbSelectPopover>
124
+ </div>
165
125
  </template>
126
+ <script setup lang="ts">
127
+ import { computed, ref } from 'vue';
128
+ import { BbBadge, BbBadgeButton, BbSelectPopover } from 'bitboss-ui';
166
129
 
167
- <script setup lang="ts" generic="Item = any">
168
- import type { HTMLAttributes, InputHTMLAttributes } from 'vue';
169
- import type { CommonProps } from '@/types/CommonProps';
170
- import type { Option as BaseOption, GroupedOptions } from '@/types/Option';
171
- import { computed, ref, nextTick, watch, onBeforeUnmount } from 'vue';
172
- import { extractDomContainer } from '@/utilities/functions/extractDomContainer';
173
- import { get } from '@/utilities/functions/get';
174
- import { hash } from '@/utilities/functions/hash';
175
- import { isNil } from '@/utilities/functions/isNil';
176
- import { matchAnyKey } from '@/utilities/functions/matchAnyKey';
177
- import { parseWidthString } from '@/utilities/functions/parseWidthString';
178
- import { toRef } from 'vue';
179
- import { useArray } from '@/composables/useArray';
180
- import { useBaseOptions } from '@/composables/useBaseOptions';
181
- import { useCoherence } from '@/composables/useCoherence';
182
- import { useElementSize, useIntersectionObserver } from '@vueuse/core';
183
- import { useHashedWatcher } from '@/composables/useHashedWatcher';
184
- import { useId } from '@/composables/useId';
185
- import { useIndexById } from '@/composables/useIndexById';
186
- import { useItemsGetter } from '@/composables/useItemsGetter';
187
- import { useMobile } from '@/composables/useMobile';
188
- import { usePrefill } from '@/composables/usePrefill';
189
- import { useUntil } from '@/composables/useUntil';
190
- import { wait } from '@/utilities/functions/wait';
191
- import { BbSpinner } from '@/index';
192
- import CommonPopover from '../CommonPopover/CommonPopover.vue';
193
- import ErrorIcon from '../ErrorIcon/ErrorIcon.vue';
194
- import ListBox from '../ListBox/ListBox.vue';
195
- import { waitFor } from '@/utilities/functions/waitFor';
196
- import type {
197
- BbSelectPopoverEvents,
198
- BbSelectPopoverProps,
199
- BbSelectPopoverSlots,
200
- } from './types';
201
-
202
- const props = withDefaults(defineProps<BbSelectPopoverProps<Item>>(), {
203
- allowWriting: true,
204
- arrowPadding: 10,
205
- autocomplete: 'off',
206
- depsDebounceTime: 0,
207
- dependencies: () => [],
208
- filterBy: () => [],
209
- flip: true,
210
- hideArrow: true,
211
- max: Infinity,
212
- modelValueDebounceTime: 0,
213
- offset: 4,
214
- padding: 10,
215
- placement: 'bottom',
216
- prefill: 'interaction',
217
- queryDebounceTime: 500,
218
- transitionDuration: 300,
219
- width: '200',
220
- });
221
-
222
- const emit = defineEmits<BbSelectPopoverEvents>();
223
-
224
- defineSlots<BbSelectPopoverSlots<Item>>();
225
- defineOptions({ inheritAttrs: false });
226
-
227
- if (props.multiple && !Array.isArray(props.modelValue)) {
228
- throw new Error('Multiple is set to "true" but modelValue is not an array.');
229
- }
230
-
231
- /**
232
- * START ELEMENT REFERENCES
233
- */
234
- const activatorEl = ref<HTMLElement>();
235
- const optionsContainer = ref<any | null>(null);
236
- const searchInput = ref<HTMLInputElement | null>(null);
237
- const popoverFocusProxy = ref<HTMLButtonElement | null>(null);
238
- const activeDescendantId = ref<string>();
239
- const { width: activatorWidth } = useElementSize(
240
- activatorEl,
241
- { width: 0, height: 0 },
242
- {
243
- box: 'border-box',
244
- }
245
- );
246
- /**
247
- * END ELEMENT REFERENCES
248
- */
249
-
250
- /**
251
- * START ACTIVATOR MANAGEMENT
252
- */
253
- const hasExternalActivator = computed(() => props.activator != null);
254
-
255
- const setActivatorRef = (reference: unknown) => {
256
- const el = extractDomContainer(reference);
257
- if (!el) return;
258
- activatorEl.value = el;
130
+ type Teammate = {
131
+ id: string;
132
+ fullName: string;
259
133
  };
260
134
 
261
- watch(
262
- () => props.activator,
263
- (val) => {
264
- if (val) setActivatorRef(val);
265
- },
266
- { immediate: true }
267
- );
268
- /**
269
- * END ACTIVATOR MANAGEMENT
270
- */
135
+ const teammates: Teammate[] = [
136
+ { id: 'ada', fullName: 'Ada Lovelace' },
137
+ { id: 'grace', fullName: 'Grace Hopper' },
138
+ { id: 'alan', fullName: 'Alan Turing' },
139
+ { id: 'maggie', fullName: 'Margaret Hamilton' },
140
+ ];
271
141
 
272
- const { isMobile } = useMobile();
273
- const computedAllowWriting = computed(() => {
274
- if (props.allowWriting === 'not-mobile') return !isMobile.value;
275
- return !!props.allowWriting;
276
- });
277
- const inputmode = computed(() =>
278
- props.allowWriting === 'not-mobile' && isMobile.value ? 'none' : undefined
279
- );
280
- const searchInputAriaLabel = computed(
281
- () => props.searchInputAriaLabel ?? 'Search options'
282
- );
142
+ const assignee = ref<string | null>(null);
283
143
 
284
- const id = props.id || useId().id.value;
285
- const computedAriaInvalid = computed(() => {
286
- const isInvalid = props.ariaInvalid ?? !!props.hasErrors;
287
- return isInvalid ? 'true' : undefined;
288
- });
289
- const computedAriaDescribedby = computed(() => {
290
- const describedBy = props.ariaDescribedby;
291
- if (Array.isArray(describedBy)) {
292
- const normalized = describedBy
293
- .map((value) => value.trim())
294
- .filter(Boolean)
295
- .join(' ');
296
- return normalized || undefined;
297
- }
298
- if (typeof describedBy === 'string') {
299
- const normalized = describedBy.trim();
300
- return normalized || undefined;
301
- }
302
- return undefined;
303
- });
304
-
305
- const { resume, pause } = useIntersectionObserver(
306
- activatorEl,
307
- async ([{ intersectionRatio }]) => {
308
- if (intersectionRatio !== 1 && shown.value) {
309
- await close();
310
- }
311
- },
312
- { threshold: [0, 1], immediate: false }
144
+ const assigneeLabel = computed(
145
+ () => teammates.find((t) => t.id === assignee.value)?.fullName ?? ''
313
146
  );
147
+ </script>
148
+ ```
314
149
 
315
- const normalizedWidth = computed(() => {
316
- if (props.width === 'auto') return 'auto';
317
- if (props.width == null || props.width === '') {
318
- return activatorWidth.value ? `${activatorWidth.value}px` : '320px';
319
- }
150
+ ### Multiple selection
320
151
 
321
- try {
322
- const { value, unit } = parseWidthString(props.width);
323
- if (unit === '%') {
324
- if (!activatorWidth.value) return '320px';
325
- return `${activatorWidth.value * (value / 100)}px`;
326
- }
327
- return `${value}${unit}`;
328
- } catch {
329
- if (typeof props.width === 'string') return props.width.trim();
330
- return activatorWidth.value ? `${activatorWidth.value}px` : '320px';
331
- }
332
- });
152
+ Add `multiple` and the model becomes an array — it **must be seeded as one**
153
+ (`ref<string[]>([])`); a non-array model **throws at setup**
154
+ (`"Multiple is set to \"true\" but modelValue is not an array."`). Cap the count
155
+ with `max`: at the cap, unselected options auto-disable while selected ones never
156
+ do, so the user can always deselect. Because the trigger is yours, _you_
157
+ summarise the selection — a count, a chip cluster, an avatar stack — from
158
+ `selectedOptions` or your own model.
333
159
 
334
- const panelStyles = computed(() => ({
335
- '--bb-select-popover-width': normalizedWidth.value,
336
- }));
160
+ **Reviewers filter pill with a live count**
337
161
 
338
- /**
339
- * START FOCUS HELPERS
340
- */
341
- const focusActivator = () => {
342
- activatorEl.value?.focus();
343
- };
344
- const focusSearchInput = () => {
345
- if (searchInput.value instanceof HTMLInputElement) {
346
- searchInput.value.focus();
347
- }
348
- };
349
- const focusPopoverFocusProxy = () => {
350
- if (popoverFocusProxy.value instanceof HTMLButtonElement) {
351
- popoverFocusProxy.value.focus();
352
- }
353
- };
354
- const focusPopoverContent = () => {
355
- if (computedAllowWriting.value) {
356
- focusSearchInput();
357
- return;
358
- }
359
- focusPopoverFocusProxy();
360
- };
361
- /**
362
- * END FOCUS HELPERS
363
- */
162
+ ```vue
163
+ <template>
164
+ <div
165
+ class="flex max-w-sm items-center gap-1.5 rounded-[var(--bb-radius)] border p-2"
166
+ >
167
+ <span class="pr-1 text-xs font-medium text-gray-500">Filters</span>
168
+ <BbSelectPopover
169
+ v-model="reviewers"
170
+ compact
171
+ item-text="name"
172
+ item-value="id"
173
+ :items="people"
174
+ :max="4"
175
+ multiple
176
+ width="240px"
177
+ >
178
+ <template #activator="{ props }">
179
+ <!-- Summarise the multi-select yourself — a live count on the pill. -->
180
+ <BbBadge
181
+ append:icon="lucide:chevron-down"
182
+ prepend:icon="lucide:users"
183
+ size="lg"
184
+ variant="outline"
185
+ >
186
+ <BbBadgeButton v-bind="props"
187
+ >Reviewers ({{ reviewers.length }})</BbBadgeButton
188
+ >
189
+ </BbBadge>
190
+ </template>
191
+ </BbSelectPopover>
192
+ </div>
193
+ </template>
194
+ <script setup lang="ts">
195
+ import { ref } from 'vue';
196
+ import { BbBadge, BbBadgeButton, BbSelectPopover } from 'bitboss-ui';
197
+
198
+ type Person = { id: string; name: string };
199
+
200
+ const people: Person[] = [
201
+ { id: 'ada', name: 'Ada Lovelace' },
202
+ { id: 'grace', name: 'Grace Hopper' },
203
+ { id: 'alan', name: 'Alan Turing' },
204
+ { id: 'katherine', name: 'Katherine Johnson' },
205
+ { id: 'ken', name: 'Ken Thompson' },
206
+ ];
207
+
208
+ // `multiple` requires an array model from the start.
209
+ const reviewers = ref<string[]>(['ada', 'grace']);
210
+ </script>
211
+ ```
364
212
 
365
- /**
366
- * Search input focus keeps the whole control in active state.
367
- */
368
- const onSearchInputFocus = (event: FocusEvent) => {
369
- emit('focus', event);
370
- setActive();
371
- };
213
+ ### Custom option rows
372
214
 
373
- const onSearchInputBlur = (event: FocusEvent) => {
374
- emit('blur', event);
375
- syncActiveStateOnBlur();
376
- };
215
+ The `#option` slot replaces each row — exposing the raw `item`, resolved `text` /
216
+ `value`, the row `index`, and `selected` / `focused` / `disabled` / `loading`
217
+ flags — so options can carry avatars, badges or secondary metadata. Rows are
218
+ fixed-height and virtualized: if your markup is taller than the default 40px
219
+ (compact 32px), set `item-height` to match — and `header-height` for grouped
220
+ headers.
377
221
 
378
- const onSearchInputChange = (event: Event) => {
379
- emit('change', event);
380
- };
222
+ **Option rows with avatar initials**
381
223
 
382
- const onPopoverFocusProxyFocus = (_event: FocusEvent) => {
383
- setActive();
384
- };
224
+ ```vue
225
+ <template>
226
+ <div
227
+ class="flex max-w-sm items-center gap-1.5 rounded-[var(--bb-radius)] border p-2"
228
+ >
229
+ <span class="pr-1 text-xs font-medium text-gray-500">Owner</span>
230
+ <BbSelectPopover
231
+ v-model="owner"
232
+ compact
233
+ :item-height="40"
234
+ item-text="label"
235
+ item-value="value"
236
+ :items="people"
237
+ width="240px"
238
+ >
239
+ <template #activator="{ props }">
240
+ <BbBadge
241
+ append:icon="lucide:chevron-down"
242
+ prepend:icon="lucide:user"
243
+ size="lg"
244
+ variant="outline"
245
+ >
246
+ <BbBadgeButton v-bind="props">{{
247
+ ownerLabel || 'Set owner'
248
+ }}</BbBadgeButton>
249
+ </BbBadge>
250
+ </template>
251
+ <template #option="{ item, text, selected }">
252
+ <span class="flex w-full items-center gap-2">
253
+ <BbAvatar :alt="text" size="sm">{{ item.initials }}</BbAvatar>
254
+ <span class="min-w-0 flex-1 truncate">{{ text }}</span>
255
+ <BbIcon
256
+ v-if="selected"
257
+ class="shrink-0 text-[color:var(--bb-text-muted)]"
258
+ icon="lucide:check"
259
+ :size="14"
260
+ />
261
+ </span>
262
+ </template>
263
+ </BbSelectPopover>
264
+ </div>
265
+ </template>
266
+ <script setup lang="ts">
267
+ import { computed, ref } from 'vue';
268
+ import {
269
+ BbAvatar,
270
+ BbBadge,
271
+ BbBadgeButton,
272
+ BbIcon,
273
+ BbSelectPopover,
274
+ } from 'bitboss-ui';
275
+
276
+ type Person = { label: string; value: string; initials: string };
277
+
278
+ const people: Person[] = [
279
+ { label: 'Ada Lovelace', value: 'ada', initials: 'AL' },
280
+ { label: 'Grace Hopper', value: 'grace', initials: 'GH' },
281
+ { label: 'Alan Turing', value: 'alan', initials: 'AT' },
282
+ ];
283
+
284
+ const owner = ref<string | null>(null);
285
+ const ownerLabel = computed(
286
+ () => people.find((p) => p.value === owner.value)?.label ?? ''
287
+ );
288
+ </script>
289
+ ```
385
290
 
386
- /**
387
- * Search on user typing inside the popover search field.
388
- */
389
- const onSearchInputInput = (event: Event) => {
390
- emit('input', event);
391
- debouncedGetter(query.value, false, props.modelValue);
392
- };
291
+ ### Fetch options with a provider
393
292
 
394
- const onListboxFocusedChange = (id: string | undefined) => {
395
- activeDescendantId.value = id;
396
- };
293
+ When options come from a backend, pass a **function** to `items`. It receives
294
+ `(query, prefill, modelValue)` and returns `Item[]` or a `Promise<Item[]>` — the
295
+ full call matrix is the shared one in the Fetch Items playbook. The essentials:
397
296
 
398
- /**
399
- * On click outside of the activator and popover, close the panel and remove active state.
400
- */
401
- const onOutsideInteraction = async (event: Event) => {
402
- const target =
403
- event.target instanceof Element
404
- ? event.target
405
- : event.target instanceof Text
406
- ? event.target.parentElement
407
- : null;
408
- if (!target) return;
409
- const insideActivator = activatorEl.value?.contains(target);
410
- const insidePopover = !!target.closest('.bb-common-popover');
411
- if (insideActivator || insidePopover) return;
412
- await close();
413
- setInactive();
414
- };
297
+ - `prefill === false` means exactly one thing: **the user typed** — search then.
298
+ - Every component-initiated call (first load, dependency change, model change)
299
+ passes `prefill === true` and expects the current selection to stay resolvable
300
+ in the response so return the selected items (by id) to keep the trigger
301
+ label and chips accurate.
302
+ - `modelValue` is your v-model as-is; the prop types it `any` — an array in
303
+ `multiple` mode, the raw model value (possibly `null`) in single mode.
415
304
 
416
- const canProcessKeyboardBindings = computed(() => {
417
- if (props.readonly) return false;
418
- if (props.disabled) return false;
419
- if (computedLoading.value) return false;
420
- return true;
421
- });
305
+ Runtime guarantees you should not re-implement: **debouncing** (`query-debounce-time`
306
+ default 500ms; `deps-debounce-time` and `model-value-debounce-time` default 0),
307
+ **race protection** (out-of-order responses discarded), **loading** (in-flight
308
+ requests set the slot's `loading` flag automatically — the `loading` prop is only
309
+ for _external_ pending state), and **errors** (a rejected provider is logged and
310
+ the previous items kept — surface failures yourself via `useToast`). Enable
311
+ `stash` to accumulate picked options across searches so chosen values stay
312
+ resolvable even when later responses omit them.
422
313
 
423
- /**
424
- * On first open the listbox is lazily mounted.
425
- * Wait a few micro-cycles so imperative focus calls don't no-op.
426
- */
427
- const waitForOptionsContainer = async () =>
428
- waitFor(() => !!optionsContainer.value, 100);
314
+ **Async, debounced destination picker**
429
315
 
430
- const focusFirstSelectedOption = () => {
431
- const firstSelected = selectedOptions.value[0];
432
- if (firstSelected?.valueHash) {
433
- optionsContainer.value?.focusByHash(firstSelected.valueHash);
434
- return;
435
- }
436
- optionsContainer.value?.focusFirstSelected();
437
- };
316
+ ```vue
317
+ <template>
318
+ <div
319
+ class="flex max-w-sm items-center gap-1.5 rounded-[var(--bb-radius)] border p-2"
320
+ >
321
+ <span class="pr-1 text-xs font-medium text-gray-500">Trip</span>
322
+ <BbSelectPopover
323
+ v-model="destination"
324
+ compact
325
+ item-text="label"
326
+ item-value="value"
327
+ :items="searchCities"
328
+ loading-text="Searching…"
329
+ no-data-text="No city found"
330
+ :query-debounce-time="250"
331
+ width="240px"
332
+ >
333
+ <template #activator="{ props, loading }">
334
+ <!-- Badge `loading` reflects the provider's in-flight fetch. Label
335
+ from our own pool — never the slot's `text`. -->
336
+ <BbBadge
337
+ append:icon="lucide:chevron-down"
338
+ :loading="loading"
339
+ prepend:icon="lucide:map-pin"
340
+ size="lg"
341
+ variant="outline"
342
+ >
343
+ <BbBadgeButton v-bind="props">{{
344
+ destinationLabel || 'Add destination'
345
+ }}</BbBadgeButton>
346
+ </BbBadge>
347
+ </template>
348
+ </BbSelectPopover>
349
+ </div>
350
+ </template>
351
+ <script setup lang="ts">
352
+ import { computed, ref } from 'vue';
353
+ import { BbBadge, BbBadgeButton, BbSelectPopover } from 'bitboss-ui';
354
+
355
+ type City = { label: string; value: string };
356
+
357
+ const pool: City[] = [
358
+ { label: 'Amsterdam', value: 'amsterdam' },
359
+ { label: 'Athens', value: 'athens' },
360
+ { label: 'Barcelona', value: 'barcelona' },
361
+ { label: 'Copenhagen', value: 'copenhagen' },
362
+ { label: 'Dublin', value: 'dublin' },
363
+ { label: 'Prague', value: 'prague' },
364
+ ];
365
+
366
+ const fetchFromApi = (predicate: (city: City) => boolean) =>
367
+ new Promise<City[]>((resolve) => {
368
+ setTimeout(() => resolve(pool.filter(predicate)), 250);
369
+ });
438
370
 
439
- const focusLastSelectedOption = () => {
440
- const lastSelected = selectedOptions.value[selectedOptions.value.length - 1];
441
- if (lastSelected?.valueHash) {
442
- optionsContainer.value?.focusByHash(lastSelected.valueHash);
443
- return;
371
+ const searchCities = (
372
+ query: string,
373
+ prefill: boolean,
374
+ // The raw v-model — type it with your own model shape: a single value (or
375
+ // null) here, an array in multiple mode.
376
+ modelValue: string | null
377
+ ): Promise<City[]> => {
378
+ // Prefill: resolve the current selection so the trigger label stays accurate.
379
+ if (prefill && modelValue) {
380
+ return fetchFromApi((city) => city.value === modelValue);
444
381
  }
445
- optionsContainer.value?.focusLastSelected();
382
+ if (!query.trim()) return Promise.resolve([]);
383
+ const q = query.trim().toLowerCase();
384
+ return fetchFromApi((city) => city.label.toLowerCase().includes(q));
446
385
  };
447
386
 
448
- /**
449
- * On arrow up:
450
- * When the panel is open focus on the previous option
451
- * When the panel is closed — open and focus on the last selected option
452
- */
453
- const onArrowUp = async () => {
454
- if (!canProcessKeyboardBindings.value) return;
455
- if (shown.value) {
456
- optionsContainer.value?.focusPrevious();
457
- } else {
458
- await open({ focusPopoverContent: false });
459
- await waitForOptionsContainer();
460
- await wait(props.transitionDuration);
461
- focusLastSelectedOption();
462
- }
463
- };
387
+ const destination = ref<string | null>(null);
388
+ const destinationLabel = computed(
389
+ () => pool.find((c) => c.value === destination.value)?.label ?? ''
390
+ );
391
+ </script>
392
+ ```
464
393
 
465
- const onArrowDown = async () => {
466
- if (!canProcessKeyboardBindings.value) return;
467
- if (shown.value) {
468
- optionsContainer.value?.focusNext();
469
- } else {
470
- await open({ focusPopoverContent: false });
471
- await waitForOptionsContainer();
472
- await wait(props.transitionDuration);
473
- focusFirstSelectedOption();
474
- }
475
- };
394
+ ### Laziness, prefill and the trigger label
395
+
396
+ `prefill` controls **when the first load happens**: `'interaction'` (default) on
397
+ first open, `true` immediately on mount (and during SSR via `onServerPrefetch`),
398
+ `false` **search-first** — nothing is fetched until the user types a query.
399
+ Opening the panel is not a search, so it loads nothing; until the first query the
400
+ list shows a _"search to begin"_ hint instead of "no data".
401
+
402
+ Reach for `false` when the result set is too large or too expensive to browse and
403
+ the query is the only sensible entry point — a user picker over thousands of
404
+ rows. Note the panel is deliberately empty on open: that is the mode telling the
405
+ user to type.
406
+
407
+ **Search-first needs both a way to search and something to defer**, so `false`
408
+ falls back to loading on open when either is missing:
409
+
410
+ - **Writing is disabled** (`disable-writing`, including the per-surface
411
+ `'mobile'`/`'desktop'` forms) — there is no search field, so a user could never
412
+ trigger the load and the panel would stay empty forever.
413
+ - **The model is non-empty** — its text has to resolve for the selection to
414
+ render. (In-field `BbSelect` upgrades this to a mount prefill; see below.)
415
+
416
+ **Two further cases ignore `prefill` entirely and always load**, because deferring
417
+ would buy nothing or break a promise you made:
418
+
419
+ - **`items` is an array.** There is no request to defer, so laziness would only
420
+ leave the selection unresolved. Options resolve on mount, whatever `prefill`
421
+ says — free, and it makes `text`/`selectedOptions` and coherence work from the
422
+ first paint.
423
+ - **`enforce-coherence` over a non-empty model.** Validating a value is
424
+ impossible without options, so the popover loads and checks on that first load.
425
+ An empty model stays lazy — empty is always coherent, so there is nothing to
426
+ check.
427
+
428
+ Outside those two, a standalone popover with a **provider does not** auto-upgrade
429
+ a seeded model to an eager prefill the way in-field `BbSelect` does. That
430
+ laziness is deliberate: a fetch per instance must be something you ask for (see
431
+ _One popover per table row_).
432
+
433
+ **Do not reach for `prefill: true` to fix a trigger label.** Resolve the label
434
+ from your own state instead (above) — a trigger that needs a fetch to render is
435
+ a trigger that renders wrong until the fetch lands.
436
+
437
+ ### Dependent fields and coherence
438
+
439
+ When one picker constrains another, list the upstream value in `dependencies`:
440
+ the provider re-runs whenever a dependency changes (value-hash compared, so array
441
+ identity churn doesn't refetch), debounced by `deps-debounce-time`. Add
442
+ `enforce-coherence` to auto-clean a now-invalid selection — multiple emits the
443
+ **filtered array**, single emits **`null`**, an already-empty selection stays
444
+ quiet. Because enforcement checks the merged result (fetched + stashed), a
445
+ provider that returns `[]` on a `prefill: true` call **wipes a valid selection** —
446
+ always resolve the current selection on component-initiated calls, or enable
447
+ `stash`. The full mechanics are in the Coherence playbook.
448
+
449
+ **You do not need `prefill: true` to make this work.** Asking for
450
+ `enforce-coherence` over a seeded model _is_ a request to validate it, and that
451
+ is impossible without options — so the popover loads on mount by itself and runs
452
+ the check on that first load. The filter bar below relies on exactly that: no
453
+ `prefill` prop anywhere, yet switching the project re-runs the milestone provider
454
+ and clears a milestone the new project lacks, while a still-valid one survives.
455
+
456
+ What that costs is honest and worth knowing: **`enforce-coherence` opts each
457
+ instance into its own load**. One filter, one request. Fifty rows with a provider
458
+ each, fifty requests. That is the trade you asked for by enabling it — and it is
459
+ the reason the table pattern below hands every row the _same array_ instead.
460
+
461
+ #### Never share one ref across instances
462
+
463
+ Independent popovers each with their own model and their own `enforce-coherence`
464
+ are fine: every instance judges **its own** value against **its own** options, so
465
+ they never interfere. What breaks is binding them all to **one** ref:
476
466
 
477
- const onEnter = async () => {
478
- if (!canProcessKeyboardBindings.value) {
479
- return;
480
- }
481
- if (!shown.value) {
482
- await open({ focusPopoverContent: false });
483
- await waitForOptionsContainer();
484
- await wait(props.transitionDuration);
485
- if (selectedOptions.value.length) {
486
- focusFirstSelectedOption();
487
- } else if (computedAllowWriting.value) {
488
- focusSearchInput();
489
- } else {
490
- focusPopoverFocusProxy();
491
- }
492
- return;
493
- } else if (optionsContainer.value?.getHighlighted()) {
494
- optionsContainer.value.confirmOption();
495
- return;
496
- }
497
- if (!computedAllowWriting.value) return;
498
- const text = query.value.trim();
499
- if (isItemSelected(text)) return;
500
- emit('option:add', text);
501
- query.value = '';
502
- };
467
+ ```vue
468
+ <!-- WRONG: every row writes the same value -->
469
+ <script setup>
470
+ const status = ref(null); // ← one ref, shared by every row
471
+ </script>
472
+ <BbSelectPopover v-for="row in rows" v-model="status" enforce-coherence … />
473
+ ```
503
474
 
504
- const onEscape = async () => {
505
- if (shown.value) {
506
- await close();
507
- focusActivator();
508
- }
509
- };
475
+ Now every instance judges **the same** value against **its own** options, and
476
+ coherence's answer to a value it doesn't recognise is `null`. Pick a value only
477
+ one row's options contain and the others each emit `null` in turn — measured with
478
+ 5 rows: the pick lands, four instances overwrite it, the model ends `null`. The
479
+ user watches their choice vanish, with nothing logged.
510
480
 
511
- const query = ref<string>('');
512
- const hasInteracted = ref(false);
513
-
514
- const {
515
- getter,
516
- debouncedGetter,
517
- items: internalItems,
518
- loading,
519
- } = useItemsGetter({
520
- items: toRef(props, 'items'),
521
- debounce: props.queryDebounceTime,
522
- });
523
-
524
- const {
525
- array: innerStash,
526
- add: addToStash,
527
- remove: removeFromStash,
528
- set: setStash,
529
- } = useArray<BaseOption>();
530
-
531
- const {
532
- hasPrefilled,
533
- isPrefilling,
534
- canLoad,
535
- prefill: prefillItems,
536
- } = usePrefill({
537
- trigger: computed(
538
- () =>
539
- props.prefill === true ||
540
- (props.prefill === 'interaction' && hasInteracted.value)
541
- ),
542
- currentValue: undefined,
543
- multiple: false,
544
- fn: async (isPrefill) => {
545
- await getter(query.value, isPrefill, props.modelValue);
546
- if (props.stash) {
547
- addToStash(...options.value.map((o) => o.item));
548
- }
549
- },
550
- });
551
-
552
- const { data: modelValueIndexedByHash, get: isItemSelected } = useIndexById({
553
- items: computed(() => [].concat(props.modelValue)),
554
- });
555
-
556
- const { options } = useBaseOptions({
557
- disabled: toRef(props, 'disabled'),
558
- items: computed(() => [...internalItems.value, ...innerStash.value]),
559
- itemText: props.itemText,
560
- itemValue: props.itemValue,
561
- max: props.max,
562
- selectable: true,
563
- selectedIndexedByHash: modelValueIndexedByHash,
564
- });
565
-
566
- const { data: optionsIndexedByHash } = useIndexById({
567
- items: options,
568
- key: 'valueHash',
569
- });
570
-
571
- const { coherent, coherentValue } = useCoherence({
572
- modelValue: toRef(props, 'modelValue'),
573
- multiple: props.multiple,
574
- iteratee: (item) => !!optionsIndexedByHash.value[hash(item)],
575
- });
576
-
577
- const selectedOptions = computed<BaseOption[]>(() =>
578
- ([] as any[])
579
- .concat(props.modelValue)
580
- .map((v) => optionsIndexedByHash.value[hash(v)])
581
- .filter(Boolean)
582
- );
481
+ The component cannot catch this for you: it receives a **value**, not a ref
482
+ identity, and two rows legitimately holding the same value is ordinary. Give
483
+ every row its own model.
583
484
 
584
- const computedLoading = computed(() => !!(loading.value || props.loading));
585
- const hasErrors = computed(() => !!props.hasErrors);
586
- const triggerInputValue = computed(() => {
587
- if (props.multiple) return '';
588
- return selectedOptions.value[0]?.text ?? '';
589
- });
590
-
591
- useHashedWatcher(
592
- () => props.modelValue,
593
- async () => {
594
- if (!canLoad.value) return;
595
- if (!coherent.value) {
596
- await getter(query.value, true, props.modelValue);
597
- if (props.enforceCoherence) {
598
- emit('update:modelValue', coherentValue.value);
599
- optionsContainer.value?.blur();
600
- }
601
- }
602
- },
603
- { debounce: props.modelValueDebounceTime }
485
+ **Toolbar filter pills milestone follows project**
486
+
487
+ ```vue
488
+ <template>
489
+ <div
490
+ class="flex max-w-md flex-wrap items-center gap-1.5 rounded-[var(--bb-radius)] border p-2"
491
+ >
492
+ <span class="pr-1 text-xs font-medium text-gray-500">Filters</span>
493
+ <BbSelectPopover
494
+ v-model="project"
495
+ compact
496
+ disable-writing
497
+ item-text="name"
498
+ item-value="id"
499
+ :items="projects"
500
+ width="200px"
501
+ >
502
+ <template #activator="{ props }">
503
+ <BbBadge
504
+ append:icon="lucide:chevron-down"
505
+ prepend:icon="lucide:folder"
506
+ size="lg"
507
+ variant="outline"
508
+ >
509
+ <BbBadgeButton v-bind="props">{{ projectLabel }}</BbBadgeButton>
510
+ </BbBadge>
511
+ </template>
512
+ </BbSelectPopover>
513
+ <BbSelectPopover
514
+ v-model="milestone"
515
+ compact
516
+ :dependencies="[project]"
517
+ :deps-debounce-time="150"
518
+ enforce-coherence
519
+ item-text="title"
520
+ item-value="id"
521
+ :items="fetchMilestones"
522
+ no-data-text="No milestone matches"
523
+ width="220px"
524
+ >
525
+ <template #activator="{ props }">
526
+ <BbBadge
527
+ append:icon="lucide:chevron-down"
528
+ prepend:icon="lucide:flag"
529
+ size="lg"
530
+ variant="outline"
531
+ >
532
+ <BbBadgeButton v-bind="props">{{
533
+ milestoneLabel || 'Milestone'
534
+ }}</BbBadgeButton>
535
+ </BbBadge>
536
+ </template>
537
+ </BbSelectPopover>
538
+ </div>
539
+ </template>
540
+ <script setup lang="ts">
541
+ import { computed, ref } from 'vue';
542
+ import { BbBadge, BbBadgeButton, BbSelectPopover } from 'bitboss-ui';
543
+
544
+ type Project = { id: string; name: string };
545
+ type Milestone = { id: string; title: string; project: string };
546
+
547
+ const projects: Project[] = [
548
+ { id: 'mobile', name: 'Mobile app' },
549
+ { id: 'web', name: 'Web dashboard' },
550
+ { id: 'design', name: 'Design system' },
551
+ ];
552
+
553
+ const milestonePool: Milestone[] = [
554
+ { id: 'ms-beta', title: 'Private beta', project: 'mobile' },
555
+ { id: 'ms-launch', title: 'App Store launch', project: 'mobile' },
556
+ { id: 'ms-ga', title: 'GA rollout', project: 'web' },
557
+ { id: 'ms-audit', title: 'SOC 2 audit', project: 'web' },
558
+ { id: 'ms-tokens', title: 'Token overhaul', project: 'design' },
559
+ ];
560
+
561
+ const project = ref<string>('mobile');
562
+ const milestone = ref<string | null>('ms-beta');
563
+
564
+ // Trigger labels come from our own state — the slot's `text` is empty until
565
+ // the popover first matches the model against loaded items.
566
+ const projectLabel = computed(
567
+ () => projects.find((p) => p.id === project.value)?.name ?? 'Project'
604
568
  );
605
- useHashedWatcher(
606
- () => [props.dependencies, props.items],
607
- async () => {
608
- if (!canLoad.value) return;
609
- await getter(query.value, true, props.modelValue);
610
- if (props.enforceCoherence && !coherent.value) {
611
- emit('update:modelValue', coherentValue.value);
612
- optionsContainer.value?.blur();
613
- }
614
- },
615
- { debounce: props.depsDebounceTime }
569
+ const milestoneLabel = computed(
570
+ () => milestonePool.find((m) => m.id === milestone.value)?.title ?? ''
616
571
  );
617
572
 
618
- const onOptionSelected = async (option: BaseOption) => {
619
- if (props.multiple) {
620
- emit('update:modelValue', props.modelValue.concat(option.value));
621
- if (props.stash) {
622
- addToStash(option.item);
623
- }
624
- } else {
625
- if (props.stash) {
626
- setStash(option.item);
627
- }
628
- emit('update:modelValue', option.value);
629
- await nextTick();
630
- }
631
- if (props.multiple && computedAllowWriting.value && shown.value) {
632
- focusSearchInput();
633
- } else {
634
- focusActivator();
635
- }
636
- if (!props.multiple) {
637
- close();
638
- }
639
- };
640
-
641
- const onOptionUnselected = async (option: BaseOption) => {
642
- removeFromStash((o) => o.valueHash !== option.valueHash);
643
- if (props.multiple) {
644
- const copy = { ...modelValueIndexedByHash.value };
645
- delete copy[option.valueHash];
646
- emit('update:modelValue', Object.values(copy));
647
- } else {
648
- emit('update:modelValue', null);
649
- }
650
- if (props.multiple && computedAllowWriting.value && shown.value) {
651
- focusSearchInput();
652
- } else {
653
- focusActivator();
654
- }
573
+ // Query-aware provider. Component-initiated calls (the mount load, project
574
+ // changes via `dependencies`) pass `prefill === true` and get the project's
575
+ // full list back, so a still-valid selection stays resolvable —
576
+ // `enforce-coherence` then clears only a milestone the new project lacks.
577
+ // No `prefill` prop needed: `enforce-coherence` over a seeded model loads on
578
+ // mount by itself, because validating a value requires having the options.
579
+ const fetchMilestones = (
580
+ query: string,
581
+ prefill: boolean,
582
+ _modelValue: string | null
583
+ ): Promise<Milestone[]> => {
584
+ const inProject = milestonePool.filter((m) => m.project === project.value);
585
+ const q = query.trim().toLowerCase();
586
+ const matches = prefill
587
+ ? inProject
588
+ : inProject.filter((m) => m.title.toLowerCase().includes(q));
589
+ return new Promise((resolve) => setTimeout(() => resolve(matches), 200));
655
590
  };
591
+ </script>
592
+ ```
656
593
 
657
- /**
658
- * Filter options based on the current query.
659
- */
660
- const filteredOptions = computed<BaseOption<Item>[]>(() => {
661
- const queryMatchesASelectedOption = selectedOptions.value.some(
662
- (option: BaseOption) => option.text === query.value
663
- );
664
- const shouldFilter =
665
- (props.multiple && query.value) ||
666
- (props.filterBy === 'not_stashed' && query.value) ||
667
- (query.value && !queryMatchesASelectedOption && !props.multiple);
668
-
669
- if (!shouldFilter || !props.filterBy) return options.value;
670
-
671
- const stashedHashes =
672
- props.filterBy === 'not_stashed'
673
- ? new Set(innerStash.value.map((o) => o.valueHash))
674
- : null;
675
-
676
- return options.value.filter((item: BaseOption) => {
677
- let matchedAnything = false;
678
- if (typeof props.filterBy === 'function') {
679
- matchedAnything = props.filterBy(item.value, item.item, query.value);
680
- } else if (props.filterBy === 'not_stashed' && query.value) {
681
- matchedAnything = !stashedHashes!.has(item.valueHash);
682
- } else if (Array.isArray(props.filterBy) && props.filterBy.length) {
683
- matchedAnything = matchAnyKey(
684
- item.item,
685
- props.filterBy,
686
- query.value.trim()
687
- );
688
- }
689
- return matchedAnything || matchAnyKey(item, ['text'], query.value.trim());
690
- });
691
- });
594
+ ### One popover per table row (inline edit)
692
595
 
693
- const defaultGroupSymbol = Symbol('default');
596
+ The status-pill-in-a-table is the popover's signature use — and the structure of
597
+ the **page** decides whether it scales. Three rules, in priority order:
694
598
 
695
- const getGroupData = (option: BaseOption) => {
696
- if (isNil(props.groupBy)) return defaultGroupSymbol;
697
- if (typeof props.groupBy === 'function') return props.groupBy(option.item);
698
- return (get as any)(option.item, props.groupBy);
699
- };
599
+ **1. Resolve the options once, for the whole page. Pass an array, not a provider.**
600
+ This is the load-bearing decision. A provider is per-instance, so 50 rows means
601
+ 50 popovers each owning a fetch. Lift the fetch to the page, `await` it once, and
602
+ hand every row the same array — 50 rows, **zero** requests, because there is
603
+ nothing left to fetch. Array `items` are never lazy either: every row resolves on
604
+ mount, so selections and coherence work immediately with no `prefill` prop.
700
605
 
701
- const groupedOptions = computed<GroupedOptions[]>(() => {
702
- const groupIndex: Record<GroupedOptions['id'], GroupedOptions> = {};
703
- for (const option of filteredOptions.value) {
704
- const groupData = getGroupData(option);
705
- const groupId = hash(groupData);
706
- if (!groupIndex[groupId]) {
707
- groupIndex[groupId] = {
708
- id: groupId,
709
- data: groupData ?? null,
710
- options: [],
711
- };
712
- }
713
- groupIndex[groupId].options.push(option);
714
- }
715
- return Object.values(groupIndex).filter((g) => g.options.length);
716
- });
606
+ ```ts
607
+ // Page level — once, not per row.
608
+ const statuses = ref<Status[]>([]);
609
+ onMounted(async () => (statuses.value = await api.statuses.list()));
610
+ ```
717
611
 
718
- /**
719
- * START POPOVER STATE
720
- */
721
- const shown = ref(false);
722
- const renderListBox = useUntil(shown);
723
-
724
- const open = async ({
725
- focusPopoverContent = true,
726
- }: { focusPopoverContent?: boolean } = {}) => {
727
- if (props.disabled || props.readonly) return;
728
- if (shown.value) return;
729
- hasInteracted.value = true;
730
- resume();
731
- shown.value = true;
732
-
733
- if (!hasPrefilled.value && !isPrefilling.value) {
734
- await prefillItems();
735
- }
612
+ **2. Hold the edit off the row — a page-level draft map keyed by id.** Never
613
+ `v-model="item.status"`: writing straight back onto the slot's `item` mutates the
614
+ table's data, so any refetch (a filter change, a poll) silently discards the edit,
615
+ and a partially-dirty row has no clean before/after. Instead bind the value _down_
616
+ (`:model-value="valueOf(item, 'status')"`) and commit it _up_ into a `drafts` map
617
+ (`@update:model-value="setField(item, 'status', $event)"`). The map is the dirty
618
+ set **and** the save payload; the row object stays pristine. This is the table
619
+ case of the [inline-edit playbook](../../ai/guides/inline-edit-playbook.md) —
620
+ reach for autosave there instead when the domain wants every pick to persist on
621
+ the spot.
736
622
 
737
- await nextTick();
738
- document.addEventListener('click', onOutsideInteraction);
739
- document.addEventListener('focusin', onOutsideInteraction);
623
+ **3. Label the pill from your own state, not from the popover.**
624
+ `{{ labelFor(valueOf(item, 'status')) }}` resolved against your page-level array —
625
+ never the slot's `text`. The badge must read correctly on first paint for every
626
+ row, including the hundreds nobody ever opens.
740
627
 
741
- if (!focusPopoverContent) return;
628
+ **Inline status cell — soft badge editor**
742
629
 
743
- if (computedAllowWriting.value) {
744
- await wait(0);
745
- focusSearchInput();
746
- } else {
747
- await wait(0);
748
- focusPopoverFocusProxy();
749
- }
750
- };
630
+ ```vue
631
+ <template>
632
+ <div class="flex max-w-xl flex-col gap-1.5">
633
+ <div
634
+ class="overflow-hidden rounded-[var(--bb-radius)] border border-[color:var(--bb-border)]"
635
+ >
636
+ <BbTable
637
+ caption="Tickets — edit statuses, then Save the batch"
638
+ :columns="columns"
639
+ compact
640
+ item-value="id"
641
+ :items="tickets"
642
+ >
643
+ <!-- One popover per row. Three rules keep it cheap and correct:
644
+ 1. `:items="statuses"` is the SAME array for every row — resolved
645
+ once at page level, so N rows cost zero extra requests.
646
+ 2. The edit is held in a page-level `drafts` map keyed by row id,
647
+ NEVER written back onto `item`. Bind the value down with
648
+ `valueOf` and commit up with `setField`; the row object stays
649
+ pristine, so a refetch (filter, poll) can't wipe an edit.
650
+ 3. The pill renders from `valueOf(item, 'status')`, our own state —
651
+ never the slot's `text` — so it is correct on first paint
652
+ whether or not the popover is ever opened. -->
653
+ <template #status="{ item }">
654
+ <BbSelectPopover
655
+ compact
656
+ disable-writing
657
+ item-text="label"
658
+ item-value="value"
659
+ :items="statuses"
660
+ :model-value="valueOf(item, 'status')"
661
+ width="180px"
662
+ @update:model-value="setField(item, 'status', $event as Status)"
663
+ >
664
+ <template #activator="{ props, shown }">
665
+ <!-- Soft status pill: the badge IS the trigger. A dirty pill
666
+ (edited, not yet saved) keeps a deeper border until Save. -->
667
+ <BbBadge
668
+ append:icon="lucide:chevron-down"
669
+ :class="{
670
+ 'status-trigger--editing': shown,
671
+ 'status-trigger--dirty': isDirty(item),
672
+ }"
673
+ size="lg"
674
+ :variant="variantFor(valueOf(item, 'status'))"
675
+ >
676
+ <BbBadgeButton v-bind="props">{{
677
+ labelFor(valueOf(item, 'status'))
678
+ }}</BbBadgeButton>
679
+ </BbBadge>
680
+ </template>
681
+ </BbSelectPopover>
682
+ </template>
683
+ </BbTable>
684
+ </div>
751
685
 
752
- const close = async () => {
753
- if (!shown.value) return;
754
- shown.value = false;
755
- optionsContainer.value?.blur();
756
- activeDescendantId.value = undefined;
757
- pause();
758
- document.removeEventListener('click', onOutsideInteraction);
759
- document.removeEventListener('focusin', onOutsideInteraction);
760
- query.value = '';
761
- };
686
+ <div class="flex items-center gap-2">
687
+ <BbButton :disabled="!dirtyCount" size="sm" @click="save">
688
+ Save{{ dirtyCount ? ` (${dirtyCount})` : '' }}
689
+ </BbButton>
690
+ <span class="text-xs text-gray-500">
691
+ Edits live in a draft map keyed by row id — the map is the save payload.
692
+ Rows are never mutated, so nothing is lost on a refetch.
693
+ </span>
694
+ </div>
695
+ </div>
696
+ </template>
697
+ <script setup lang="ts">
698
+ import { computed, reactive, ref } from 'vue';
699
+ import {
700
+ BbBadge,
701
+ BbBadgeButton,
702
+ BbButton,
703
+ BbSelectPopover,
704
+ BbTable,
705
+ } from 'bitboss-ui';
706
+ import type { BadgeVariantType, BbTableColumn } from 'bitboss-ui';
707
+
708
+ type Status = 'open' | 'in-progress' | 'blocked' | 'done';
709
+ type Ticket = { id: string; ref: string; title: string; status: Status };
710
+ type Patch = Partial<Pick<Ticket, 'status'>>;
762
711
 
763
- const toggle = () => {
764
- if (shown.value) return close();
765
- return open();
766
- };
767
712
  /**
768
- * END POPOVER STATE
713
+ * The option list is resolved ONCE for the whole page and handed to every row as
714
+ * a plain array. With a provider per row, each popover would own its own fetch;
715
+ * as an array there is no request at all, and every row resolves on mount.
769
716
  */
717
+ const statuses: Array<{ value: Status; label: string }> = [
718
+ { value: 'open', label: 'Open' },
719
+ { value: 'in-progress', label: 'In progress' },
720
+ { value: 'blocked', label: 'Blocked' },
721
+ { value: 'done', label: 'Done' },
722
+ ];
723
+
724
+ const tickets = ref<Ticket[]>([
725
+ {
726
+ id: 't-1',
727
+ ref: 'BB-104',
728
+ title: 'Popover drops focus on Esc',
729
+ status: 'open',
730
+ },
731
+ {
732
+ id: 't-2',
733
+ ref: 'BB-118',
734
+ title: 'Table header misaligns at 320px',
735
+ status: 'in-progress',
736
+ },
737
+ {
738
+ id: 't-3',
739
+ ref: 'BB-121',
740
+ title: 'Token audit for dark mode',
741
+ status: 'blocked',
742
+ },
743
+ {
744
+ id: 't-4',
745
+ ref: 'BB-130',
746
+ title: 'Ship the migration guide',
747
+ status: 'done',
748
+ },
749
+ ]);
770
750
 
771
- /**
772
- * START ACTIVE STATE
773
- * Tracks whether the user is inside this whole component.
774
- * We cannot use :focus-within as it doesn't work for teleported elements.
775
- */
776
- const active = ref(false);
751
+ const columns: Array<BbTableColumn<Ticket>> = [
752
+ { key: 'ref', label: 'Ref', width: 90 },
753
+ { key: 'title', label: 'Title' },
754
+ { key: 'status', label: 'Status', width: 140 },
755
+ ];
777
756
 
778
- const setActive = () => {
779
- active.value = true;
780
- };
781
- const setInactive = () => {
782
- if (!active.value) return;
783
- active.value = false;
784
- emit('inactive');
785
- };
757
+ /* ---- Draft map: the edit lives here, never on the row -------------------- */
758
+
759
+ const drafts = reactive<Record<string, Patch>>({});
786
760
 
787
- const isFocusInsideComponent = (target: EventTarget | null) => {
788
- if (!(target instanceof Node)) return false;
789
- const insideActivator = !!activatorEl.value?.contains(target);
790
- const insidePopover = !!optionsContainer.value?.$el
791
- ?.closest('.bb-common-popover')
792
- ?.contains(target);
793
- return insideActivator || insidePopover;
761
+ /**
762
+ * Read-through: the draft wins, the row is the fallback. Use a `key in` check,
763
+ * NOT `??` — a field legitimately drafted to a nullish value would otherwise
764
+ * fall through to the row.
765
+ */
766
+ const valueOf = <K extends keyof Patch>(item: Ticket, key: K): Ticket[K] => {
767
+ const draft = drafts[item.id];
768
+ return draft && key in draft ? (draft[key] as Ticket[K]) : item[key];
794
769
  };
795
770
 
796
- const syncActiveStateOnBlur = () => {
797
- setTimeout(() => {
798
- if (isFocusInsideComponent(document.activeElement)) {
799
- setActive();
800
- return;
771
+ /** One setter covers every field; re-picking the original un-dirties for free. */
772
+ const setField = <K extends keyof Patch>(
773
+ item: Ticket,
774
+ key: K,
775
+ value: Patch[K]
776
+ ) => {
777
+ if (value === item[key]) {
778
+ delete drafts[item.id]?.[key];
779
+ if (drafts[item.id] && !Object.keys(drafts[item.id]).length) {
780
+ delete drafts[item.id];
801
781
  }
802
- setInactive();
803
- }, 0);
782
+ return;
783
+ }
784
+ (drafts[item.id] ??= {})[key] = value;
804
785
  };
805
- /**
806
- * END ACTIVE STATE
807
- */
808
786
 
809
- const onClear = () => {
810
- emit('update:modelValue', props.multiple ? [] : null);
787
+ const isDirty = (item: Ticket) => drafts[item.id]?.status !== undefined;
788
+ const dirtyCount = computed(() => Object.keys(drafts).length);
789
+
790
+ /** The map IS the payload. Here it patches the local rows; a real app PATCHes. */
791
+ const save = () => {
792
+ tickets.value = tickets.value.map((row) =>
793
+ drafts[row.id] ? { ...row, ...drafts[row.id] } : row
794
+ );
795
+ Object.keys(drafts).forEach((id) => delete drafts[id]);
811
796
  };
812
797
 
813
- /**
814
- * START ACTIVATOR LISTENERS
815
- * Programmatically attach accessibility attributes and event listeners
816
- * to the activator element, following the BbDropdown pattern.
817
- */
818
- let cleanupActivator: (() => void) | null = null;
819
-
820
- watch(
821
- activatorEl,
822
- (el) => {
823
- if (cleanupActivator) {
824
- cleanupActivator();
825
- cleanupActivator = null;
826
- }
827
- if (!el) return;
828
-
829
- el.setAttribute('role', 'combobox');
830
- el.setAttribute('aria-haspopup', 'listbox');
831
-
832
- const handleClick = (event: MouseEvent) => {
833
- emit('click', event);
834
- if (props.disabled || props.readonly) return;
835
- event.preventDefault();
836
- toggle();
837
- };
838
-
839
- const handleKeydown = (event: KeyboardEvent) => {
840
- switch (event.key) {
841
- case 'ArrowDown':
842
- event.preventDefault();
843
- onArrowDown();
844
- break;
845
- case 'ArrowUp':
846
- event.preventDefault();
847
- onArrowUp();
848
- break;
849
- case 'Enter':
850
- event.preventDefault();
851
- onEnter();
852
- break;
853
- case 'Escape':
854
- if (shown.value) {
855
- event.preventDefault();
856
- onEscape();
857
- }
858
- break;
859
- }
860
- };
861
-
862
- const handleFocus = (event: FocusEvent) => {
863
- emit('focus', event);
864
- setActive();
865
- };
866
-
867
- const handleBlur = (event: FocusEvent) => {
868
- emit('blur', event);
869
- syncActiveStateOnBlur();
870
- };
871
-
872
- el.addEventListener('click', handleClick);
873
- el.addEventListener('keydown', handleKeydown);
874
- el.addEventListener('focus', handleFocus);
875
- el.addEventListener('blur', handleBlur);
876
-
877
- cleanupActivator = () => {
878
- el.removeEventListener('click', handleClick);
879
- el.removeEventListener('keydown', handleKeydown);
880
- el.removeEventListener('focus', handleFocus);
881
- el.removeEventListener('blur', handleBlur);
882
- el.removeAttribute('role');
883
- el.removeAttribute('aria-haspopup');
884
- el.removeAttribute('aria-expanded');
885
- el.removeAttribute('aria-controls');
886
- el.removeAttribute('aria-invalid');
887
- el.removeAttribute('aria-describedby');
888
- el.removeAttribute('aria-activedescendant');
889
- };
890
- },
891
- { immediate: true }
892
- );
798
+ /* Row labels come from our own state — stable regardless of popover state. */
799
+ const labelFor = (status: Status) =>
800
+ statuses.find((s) => s.value === status)?.label ?? '—';
893
801
 
894
- watch(
895
- [
896
- activatorEl,
897
- shown,
898
- renderListBox,
899
- computedAriaInvalid,
900
- computedAriaDescribedby,
901
- activeDescendantId,
902
- ] as const,
903
- ([el, isShown, hasListBox, ariaInvalid, ariaDescribedby, descendantId]) => {
904
- if (!el) return;
905
- el.setAttribute('aria-expanded', String(isShown));
906
- if (ariaInvalid != null) {
907
- el.setAttribute('aria-invalid', ariaInvalid);
908
- } else {
909
- el.removeAttribute('aria-invalid');
910
- }
911
- if (hasListBox) {
912
- el.setAttribute('aria-controls', `${id}_listbox`);
913
- } else {
914
- el.removeAttribute('aria-controls');
915
- }
916
- if (ariaDescribedby != null) {
917
- el.setAttribute('aria-describedby', ariaDescribedby);
918
- } else {
919
- el.removeAttribute('aria-describedby');
920
- }
921
- if (isShown && descendantId) {
922
- el.setAttribute('aria-activedescendant', descendantId);
923
- } else {
924
- el.removeAttribute('aria-activedescendant');
925
- }
926
- },
927
- { immediate: true }
928
- );
802
+ const VARIANT: Record<Status, BadgeVariantType> = {
803
+ open: 'soft-gray',
804
+ 'in-progress': 'soft-blue',
805
+ blocked: 'soft-red',
806
+ done: 'soft-green',
807
+ };
929
808
 
930
- onBeforeUnmount(() => {
931
- cleanupActivator?.();
932
- document.removeEventListener('click', onOutsideInteraction);
933
- document.removeEventListener('focusin', onOutsideInteraction);
934
- });
935
- /**
936
- * END ACTIVATOR LISTENERS
937
- */
809
+ const variantFor = (status: Status) => VARIANT[status];
938
810
  </script>
939
811
 
940
- <style lang="postcss">
941
- .bb-select-popover {
942
- width: var(--bb-select-popover-width, 320px);
812
+ <!-- Soft status palette — canonical source: ai/guides/design-language.md § Using color.
813
+ Non-scoped so variant classes on the child badge receive the accents. -->
814
+ <style>
815
+ .bb-badge.bb-badge--soft-gray {
816
+ --accent: #64748b;
817
+ }
818
+ .bb-badge.bb-badge--soft-blue {
819
+ --accent: #2563eb;
820
+ }
821
+ .bb-badge.bb-badge--soft-green {
822
+ --accent: #16a34a;
823
+ }
824
+ .bb-badge.bb-badge--soft-red {
825
+ --accent: #dc2626;
826
+ }
827
+ .bb-badge.bb-badge--soft-gray,
828
+ .bb-badge.bb-badge--soft-blue,
829
+ .bb-badge.bb-badge--soft-green,
830
+ .bb-badge.bb-badge--soft-red {
831
+ --bg: color-mix(in oklab, var(--accent) 15%, var(--bb-panel));
832
+ --color: color-mix(in oklab, var(--accent) 80%, var(--bb-text));
833
+ --border-width: 1px;
834
+ --border-color: color-mix(in oklab, var(--accent) 25%, var(--bb-panel));
835
+ --ring: color-mix(in oklab, var(--accent) 45%, transparent);
836
+ }
837
+
838
+ /* Unsaved edit: hold a deeper border until the batch is saved. */
839
+ .status-trigger--dirty {
840
+ --border-width: 1px;
841
+ --border-color: color-mix(in oklab, var(--color) 60%, var(--bb-panel));
842
+ }
943
843
 
944
- .bb-select-popover__search-container {
945
- align-items: center;
946
- border-bottom: 1px solid var(--bb-border);
947
- display: flex;
948
- padding: 0.375rem 0.75rem;
949
- position: relative;
950
- }
844
+ /* While open, deepen the badge's own hue — not a generic indigo ring. */
845
+ .status-trigger--editing {
846
+ --bg: color-mix(in oklab, var(--color) 25%, var(--bb-panel));
847
+ --border-color: color-mix(in oklab, var(--color) 45%, var(--bb-panel));
848
+ box-shadow: 0 0 0 var(--bb-ring-size) var(--ring);
849
+ }
850
+ </style>
851
+ ```
951
852
 
952
- .bb-select-popover__search-icon,
953
- .bb-select-popover__search-spinner,
954
- .bb-select-popover__search-error-icon {
955
- color: var(--bb-icon-color);
956
- flex-shrink: 0;
957
- width: var(--bb-input-icon);
958
- position: absolute;
959
- right: 0.75rem;
960
- top: 50%;
961
- transform: translateY(-50%);
962
- opacity: 0;
963
- transition:
964
- color 0.3s,
965
- opacity 0.3s;
966
- pointer-events: none;
967
- }
853
+ **Why this shape and not the obvious one.** The instinct is to give each row a
854
+ provider and `enforce-coherence` so rows keep themselves honest. That inverts the
855
+ cost: coherence with a seeded model makes every row load, so the table's request
856
+ count tracks its row count, and each row can rewrite its own model from a
857
+ response you never see. The page-level array collapses all of it — one source,
858
+ one fetch, every row consistent by construction, nothing to prune because every
859
+ row already draws from the same list.
860
+
861
+ If rows genuinely need **different** option sets (per-type statuses, say),
862
+ resolve _those_ lists at page level too — one fetch per distinct set, keyed by
863
+ type — and pass the right array down. Still zero per-row requests. Reach for a
864
+ per-row provider only when the options truly depend on that row's identity and
865
+ cannot be batched, and then expect the request count to follow the row count.
866
+
867
+ Pruning stale values in a table is a **page-level** job, not a per-row one: when
868
+ the source list narrows, reconcile the rows yourself in one pass, where you can
869
+ show the user what changed (or ask them) instead of nulling values invisibly.
870
+
871
+ ### Create options on the fly (`option:add`)
872
+
873
+ Pressing Enter in the search field with **no option highlighted** emits
874
+ `option:add` with the trimmed query (it can be `''`, and it won't fire if the
875
+ query already matches a selected option). The component creates nothing itself:
876
+ append the new item to `items` and select it. This is the idiomatic pattern for
877
+ closed-but-growable vocabularies — the same as `BbSelect`. The behaviour is gated
878
+ by the search field existing; `disable-writing` (which removes the field) also
879
+ disables it.
968
880
 
969
- .bb-select-popover__search-input {
970
- background-color: transparent;
971
- border: 0;
972
- color: var(--bb-input-color);
973
- flex: 1 1 auto;
974
- font-size: var(--bb-input-font-size);
975
- line-height: var(--bb-leading);
976
- outline: none;
977
- padding: 0;
978
- padding-right: calc(var(--bb-input-icon) + 0.5rem);
979
- width: 100%;
980
- }
881
+ ```ts
882
+ const roles = ref<string[]>(['Reviewer', 'Approver']);
883
+ const role = ref<string | null>(null);
884
+
885
+ const onAdd = (text: string) => {
886
+ const name = text.trim();
887
+ if (!name || roles.value.includes(name)) return;
888
+ roles.value.push(name);
889
+ role.value = name;
890
+ };
891
+ ```
981
892
 
982
- .bb-select-popover__search-icon {
983
- opacity: 1;
984
- }
893
+ ### Group options
985
894
 
986
- &.bb-select-popover--errors {
987
- .bb-select-popover__search-error-icon {
988
- color: var(--bb-danger);
989
- opacity: 1;
990
- }
895
+ `group-by` (a field path or a function) buckets options under headers; the
896
+ `#group` slot styles each header and receives `{ text, item, index, length,
897
+ disabled }` — `length` is the group size, `index` the list index of its first
898
+ option. Identical to `BbSelect`, anchored to your trigger.
991
899
 
992
- .bb-select-popover__search-icon,
993
- .bb-select-popover__search-spinner {
994
- opacity: 0;
995
- }
996
- }
900
+ **Roles grouped by department**
997
901
 
998
- &.bb-select-popover--loading {
999
- .bb-select-popover__search-spinner {
1000
- opacity: 1;
1001
- }
902
+ ```vue
903
+ <template>
904
+ <div
905
+ class="flex max-w-sm items-center gap-1.5 rounded-[var(--bb-radius)] border p-2"
906
+ >
907
+ <span class="pr-1 text-xs font-medium text-gray-500">Role</span>
908
+ <BbSelectPopover
909
+ v-model="role"
910
+ compact
911
+ group-by="department"
912
+ item-text="label"
913
+ item-value="value"
914
+ :items="roles"
915
+ width="240px"
916
+ >
917
+ <template #activator="{ props }">
918
+ <BbBadge
919
+ append:icon="lucide:chevron-down"
920
+ prepend:icon="lucide:briefcase"
921
+ size="lg"
922
+ variant="outline"
923
+ >
924
+ <BbBadgeButton v-bind="props">{{
925
+ roleLabel || 'Assign role'
926
+ }}</BbBadgeButton>
927
+ </BbBadge>
928
+ </template>
929
+ <template #group="{ text, length }">
930
+ <div
931
+ class="flex items-center justify-between px-2 text-xs font-medium text-gray-500"
932
+ >
933
+ <span>{{ text }}</span>
934
+ <span>{{ length }}</span>
935
+ </div>
936
+ </template>
937
+ </BbSelectPopover>
938
+ </div>
939
+ </template>
940
+ <script setup lang="ts">
941
+ import { computed, ref } from 'vue';
942
+ import { BbBadge, BbBadgeButton, BbSelectPopover } from 'bitboss-ui';
943
+
944
+ type Role = { label: string; value: string; department: string };
945
+
946
+ const roles: Role[] = [
947
+ { label: 'Analyst', value: 'mkt-analyst', department: 'Marketing' },
948
+ { label: 'Manager', value: 'mkt-manager', department: 'Marketing' },
949
+ { label: 'Frontend', value: 'eng-fe', department: 'Engineering' },
950
+ { label: 'Backend', value: 'eng-be', department: 'Engineering' },
951
+ ];
952
+
953
+ const role = ref<string | null>(null);
954
+ const roleLabel = computed(
955
+ () => roles.find((r) => r.value === role.value)?.label ?? ''
956
+ );
957
+ </script>
958
+ ```
1002
959
 
1003
- .bb-select-popover__search-icon,
1004
- .bb-select-popover__search-error-icon {
1005
- opacity: 0;
1006
- }
1007
- }
960
+ ### Panel header, footer and empty/loading states
1008
961
 
1009
- .bb-listbox {
1010
- --option-h: var(--option-height);
1011
- display: block;
962
+ `#header` and `#footer` pin content above the search field and below the options
963
+ list, in **both** the desktop popover and the mobile adaptive sheet. Both receive
964
+ `{ close, clear, focus, query, selectedOptions }` — ideal for a title and a
965
+ "Done" action. Two more panel slots cover async states: `#loading` and
966
+ `#no-data` (both receive `{ query }`; `#no-data` also a `focus()` callback), or
967
+ their string equivalents `loading-text` / `no-data-text`.
1012
968
 
1013
- &.bb-listbox--open {
1014
- transition: min-height 0s 0s;
969
+ **A titled panel with a done action**
970
+
971
+ ```vue
972
+ <template>
973
+ <div
974
+ class="flex max-w-sm items-center gap-1.5 rounded-[var(--bb-radius)] border p-2"
975
+ >
976
+ <span class="pr-1 text-xs font-medium text-gray-500">Destination</span>
977
+ <BbSelectPopover
978
+ v-model="city"
979
+ compact
980
+ item-text="label"
981
+ item-value="value"
982
+ :items="cities"
983
+ width="240px"
984
+ >
985
+ <template #activator="{ props }">
986
+ <BbBadge
987
+ append:icon="lucide:chevron-down"
988
+ prepend:icon="lucide:map-pin"
989
+ size="lg"
990
+ variant="outline"
991
+ >
992
+ <BbBadgeButton v-bind="props">{{
993
+ cityLabel || 'Add destination'
994
+ }}</BbBadgeButton>
995
+ </BbBadge>
996
+ </template>
997
+ <template #header>
998
+ <span class="text-sm font-medium">Popular destinations</span>
999
+ </template>
1000
+ <template #footer="{ close, clear }">
1001
+ <div class="flex w-full items-center gap-2">
1002
+ <BbButton class="mr-auto" variant="ghost" @click="clear"
1003
+ >Clear</BbButton
1004
+ >
1005
+ <BbButton variant="primary" @click="close">Done</BbButton>
1006
+ </div>
1007
+ </template>
1008
+ </BbSelectPopover>
1009
+ </div>
1010
+ </template>
1011
+ <script setup lang="ts">
1012
+ import { computed, ref } from 'vue';
1013
+ import { BbBadge, BbBadgeButton, BbButton, BbSelectPopover } from 'bitboss-ui';
1014
+
1015
+ type City = { label: string; value: string };
1016
+
1017
+ const cities: City[] = [
1018
+ { label: 'Amsterdam', value: 'ams' },
1019
+ { label: 'Berlin', value: 'ber' },
1020
+ { label: 'Lisbon', value: 'lis' },
1021
+ { label: 'Milan', value: 'mil' },
1022
+ ];
1023
+
1024
+ const city = ref<string | null>(null);
1025
+ const cityLabel = computed(
1026
+ () => cities.find((c) => c.value === city.value)?.label ?? ''
1027
+ );
1028
+ </script>
1029
+ ```
1015
1030
 
1016
- .bb-listbox__outer-container {
1017
- grid-template-rows: 1fr;
1018
- opacity: 1;
1019
- transition-delay: 0s, 00ms;
1031
+ ### Search field and filtering
1020
1032
 
1021
- > * {
1022
- opacity: 1;
1023
- transition-delay: calc(var(--transition-duration) * 0.8);
1024
- }
1025
- }
1026
- }
1027
- &.bb-listbox--no-data {
1028
- .bb-listbox__outer-container {
1029
- .bb-listbox__inner-container {
1030
- .bb-listbox__no-data {
1031
- display: block;
1032
- }
1033
- }
1034
- }
1035
- }
1036
- &.bb-listbox--loading {
1037
- .bb-listbox__outer-container {
1038
- .bb-listbox__inner-container {
1039
- .bb-listbox__loading {
1040
- display: block;
1041
- text-align: left;
1042
- }
1043
- .bb-listbox__loading {
1044
- display: hidden;
1045
- }
1046
- }
1047
- }
1048
- }
1033
+ The panel carries a search field (role `searchbox`). Filtering follows the shared
1034
+ semantics (Options/Fetch playbooks): array items filter locally by
1035
+ case-insensitive **substring** against the display text; `filter-by: ['path', …]`
1036
+ searches the listed paths **instead of** the text (every path must exist on every
1037
+ item or matching throws); with a provider, the local substring filter **still
1038
+ applies on top of** the response, so keep server matches substring-compatible.
1049
1039
 
1050
- &.bb-listbox--multiple {
1051
- .autocomplete-option__checkbox {
1052
- display: inline-block !important;
1053
- }
1054
- }
1040
+ `disable-writing` removes the search field entirely — `true` everywhere, or
1041
+ `'mobile'` / `'desktop'` to drop it on one platform only. It is also the
1042
+ supported way to disable typing/filtering (and, with it, `option:add`); use it
1043
+ when the option list is short enough to just scroll.
1055
1044
 
1056
- .bb-listbox__outer-container {
1057
- background-color: var(--bb-panel);
1058
- border-color: var(--bb-primary);
1059
- border-radius: var(--bb-radius);
1060
- border-width: 0px;
1061
- display: grid;
1062
- grid-template-rows: 0fr;
1063
- opacity: 0;
1064
- transition-delay: calc(var(--transition-duration) * 0.25), 0s, 0s;
1065
- transition-duration:
1066
- var(--transition-duration), calc(var(--transition-duration) * 1.4),
1067
- var(--transition-duration);
1068
- transition-property: grid-template-rows, opacity, border;
1069
-
1070
- > * {
1071
- opacity: 0;
1072
- transition-delay: 0s;
1073
- transition-duration: calc(var(--transition-duration) * 2);
1074
- transition-property: opacity;
1075
- }
1076
-
1077
- .bb-listbox__inner-container {
1078
- overflow: auto;
1079
- overflow-x: clip;
1080
- text-align: left;
1081
- /* Always show options up to the bottom of the screen, but not more than 6 options */
1082
- max-height: min(
1083
- calc(var(--option-h) * 6),
1084
- calc(round(down, calc(100dvh - 130px), var(--option-h)) - 1px)
1085
- );
1086
-
1087
- .bb-listbox__loading,
1088
- .bb-listbox__no-data {
1089
- color: var(--bb-text);
1090
- display: none;
1091
- padding-bottom: var(--bb-select-option-py);
1092
- padding-left: var(--bb-select-option-px);
1093
- padding-right: var(--bb-select-option-px);
1094
- padding-top: var(--bb-select-option-py);
1095
- }
1096
-
1097
- span[role='listbox'] {
1098
- position: relative;
1099
- width: 100%;
1100
- display: block;
1101
-
1102
- .bb-listbox__group {
1103
- left: 0;
1104
- position: absolute;
1105
- top: 0;
1106
- width: 100%;
1107
- display: block;
1108
- }
1109
-
1110
- .bb-listbox__group-header {
1111
- display: flex;
1112
- align-items: center;
1113
- height: var(--group-header-height, 32px);
1114
- padding-left: var(--bb-select-option-px);
1115
- padding-right: var(--bb-select-option-px);
1116
-
1117
- user-select: none;
1118
-
1119
- .bb-listbox__group-header-label {
1120
- display: flex;
1121
- align-items: center;
1122
- gap: 16px;
1123
- flex: auto;
1124
- text-align: left;
1125
- overflow: hidden;
1126
- text-overflow: ellipsis;
1127
- white-space: nowrap;
1128
- color: color-mix(in srgb, var(--bb-text) 50%, transparent);
1129
- font-size: 0.75rem;
1130
- font-weight: 600;
1131
- letter-spacing: 0.025em;
1132
- text-transform: uppercase;
1133
-
1134
- &::after {
1135
- content: '';
1136
- display: block;
1137
- width: 100%;
1138
- height: 1px;
1139
- background-color: var(--bb-border);
1140
- }
1141
- }
1142
- }
1143
-
1144
- .bb-listbox__option {
1145
- left: 0;
1146
- position: absolute;
1147
- display: block;
1148
- top: 0;
1149
- width: 100%;
1150
- }
1151
-
1152
- .bb-listbox__group > .bb-listbox__option {
1153
- position: static;
1154
- }
1155
-
1156
- .autocomplete-option {
1157
- --bg-opacity: 0;
1158
- --bg-base-color: var(--bb-text);
1159
- align-items: center;
1160
- background-color: color-mix(
1161
- in srgb,
1162
- var(--bg-base-color) calc(100% * var(--bg-opacity)),
1163
- transparent
1164
- );
1165
- color: var(--bb-text);
1166
- cursor: pointer;
1167
- display: flex;
1168
- flex-grow: 1;
1169
- gap: 8px;
1170
- height: var(--option-h);
1171
- padding-left: var(--bb-select-option-px);
1172
- padding-right: var(--bb-select-option-px);
1173
- transition-duration: 250ms;
1174
- transition-property: color, background-color;
1175
- transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
1176
- width: 100%;
1177
-
1178
- &:hover:not(.autocomplete-option--disabled) {
1179
- --bg-opacity: 0.05;
1180
- --bg-base-color: var(--bb-text);
1181
- }
1182
-
1183
- &--focused {
1184
- --bg-opacity: 0.15;
1185
- --bg-base-color: var(--bb-text);
1186
- }
1187
-
1188
- &--focused:hover:not(.autocomplete-option--disabled) {
1189
- --bg-opacity: 0.2;
1190
- }
1191
-
1192
- &--selected {
1193
- --bg-opacity: 0.1;
1194
- --bg-base-color: var(--bb-primary) !important;
1195
- color: var(--bb-primary);
1196
- }
1197
-
1198
- &--selected:hover:not(.autocomplete-option--disabled) {
1199
- --bg-opacity: 0.15;
1200
- }
1201
-
1202
- &--selected.autocomplete-option--focused {
1203
- --bg-opacity: 0.2;
1204
- }
1205
-
1206
- &--selected.autocomplete-option--focused:hover:not(
1207
- .autocomplete-option--disabled
1208
- ) {
1209
- --bg-opacity: 0.2;
1210
- }
1211
-
1212
- &--disabled {
1213
- cursor: not-allowed;
1214
- opacity: 0.5;
1215
-
1216
- .autocomplete-option__checkbox.autocomplete-option__checkbox {
1217
- background-color: var(--bb-panel-disabled);
1218
- }
1219
- }
1220
-
1221
- .autocomplete-option__checkbox {
1222
- pointer-events: none;
1223
- display: none;
1224
- width: 16px;
1225
- height: 16px;
1226
- background-color: var(--bb-panel);
1227
- border-color: var(--bb-border);
1228
- border-radius: min(6px, var(--bb-radius));
1229
- border-style: solid;
1230
- border-width: 1px;
1231
- margin-left: -6px;
1232
- transition-duration: 300ms;
1233
- transition-property:
1234
- color, background-color, border-color, text-decoration-color,
1235
- box-shadow;
1236
- transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
1237
-
1238
- path {
1239
- stroke: var(--bb-contrasting);
1240
- stroke-dasharray: 105;
1241
- stroke-dashoffset: 105;
1242
- transition: stroke-dashoffset 0.3s;
1243
- }
1244
- }
1245
-
1246
- .autocomplete-option__label {
1247
- display: block;
1248
- flex: auto;
1249
- text-align: left;
1250
- overflow: hidden;
1251
- text-overflow: ellipsis;
1252
- white-space: nowrap;
1253
- }
1254
-
1255
- &.autocomplete-option--selected {
1256
- .autocomplete-option__checkbox {
1257
- background-color: var(--bb-primary);
1258
- border-color: var(--bb-primary);
1259
-
1260
- path {
1261
- stroke-dashoffset: 0;
1262
- }
1263
- }
1264
- }
1265
- }
1266
- }
1267
- }
1268
- }
1269
- }
1270
- }
1271
- </style>
1272
- ```
1045
+ **Scroll-only status pill**
1273
1046
 
1274
- ## Types
1047
+ ```vue
1048
+ <template>
1049
+ <div
1050
+ class="flex max-w-sm items-center gap-1.5 rounded-[var(--bb-radius)] border p-2"
1051
+ >
1052
+ <span class="pr-1 text-xs font-medium text-gray-500">Status</span>
1053
+ <BbSelectPopover
1054
+ v-model="status"
1055
+ compact
1056
+ disable-writing
1057
+ :items="statuses"
1058
+ width="200px"
1059
+ >
1060
+ <template #activator="{ props, shown }">
1061
+ <BbBadge
1062
+ append:icon="lucide:chevron-down"
1063
+ :class="{ 'status-trigger--editing': shown }"
1064
+ size="lg"
1065
+ :variant="variantFor(status)"
1066
+ >
1067
+ <BbBadgeButton v-bind="props">{{
1068
+ status ?? 'Set status'
1069
+ }}</BbBadgeButton>
1070
+ </BbBadge>
1071
+ </template>
1072
+ </BbSelectPopover>
1073
+ </div>
1074
+ </template>
1075
+ <script setup lang="ts">
1076
+ import { BbBadge, BbBadgeButton, BbSelectPopover } from 'bitboss-ui';
1077
+ import type { BadgeVariantType } from 'bitboss-ui';
1078
+ import { ref } from 'vue';
1275
1079
 
1276
- ```ts
1277
- import type { HTMLAttributes, InputHTMLAttributes } from 'vue';
1278
- import type { CommonProps } from '@/types/CommonProps';
1279
-
1280
- export type BbSelectPopoverProps<Item> = {
1281
- /**
1282
- * External activator element or component ref.
1283
- * When provided, the activator slot is not rendered and event listeners
1284
- * are attached programmatically to the referenced element.
1285
- */
1286
- activator?: HTMLElement | Record<string, any> | null;
1287
-
1288
- /**
1289
- * Controls whether the search input is shown inside the popover panel.
1290
- * Use `'not-mobile'` to hide the search input on mobile.
1291
- *
1292
- * @defaultValue `false`
1293
- */
1294
- allowWriting?: boolean | 'not-mobile';
1295
-
1296
- /**
1297
- * Browser autocomplete hint for the popover search input.
1298
- *
1299
- * @defaultValue `'off'`
1300
- */
1301
- autocomplete?: InputHTMLAttributes['autocomplete'];
1302
-
1303
- /**
1304
- * Apply the compact density variant.
1305
- */
1306
- compact?: boolean;
1307
-
1308
- /**
1309
- * Space the arrow keeps from popover edges. Useful with rounded corners.
1310
- *
1311
- * @defaultValue `10`
1312
- */
1313
- arrowPadding?: CommonProps['arrowPadding'];
1314
-
1315
- /**
1316
- * Constrains the popover to a specific boundary element.
1317
- */
1318
- boundary?: HTMLElement | Record<string, any> | string | null;
1319
-
1320
- /**
1321
- * Additional dependencies that trigger item reloading when changed.
1322
- *
1323
- * @defaultValue `[]`
1324
- */
1325
- dependencies?: any[];
1326
-
1327
- /**
1328
- * Debounce delay (ms) for dependency-triggered reloads.
1329
- *
1330
- * @defaultValue `0`
1331
- */
1332
- depsDebounceTime?: number;
1333
-
1334
- /**
1335
- * Disables the component.
1336
- */
1337
- disabled?: boolean;
1338
-
1339
- /**
1340
- * Marks the component as being in error state.
1341
- */
1342
- hasErrors?: boolean;
1343
-
1344
- /**
1345
- * Explicit invalid state for accessibility semantics.
1346
- * Falls back to `hasErrors` when not provided.
1347
- */
1348
- ariaInvalid?: boolean;
1349
-
1350
- /**
1351
- * Space-separated IDREF(s) that describe this field for assistive technologies.
1352
- * Accepts either a string or array of ids.
1353
- */
1354
- ariaDescribedby?: string | string[];
1355
-
1356
- /**
1357
- * Enable or disable floating flip behavior.
1358
- *
1359
- * @defaultValue `true`
1360
- */
1361
- flip?: boolean;
1362
-
1363
- /**
1364
- * Whether the floating arrow is hidden.
1365
- *
1366
- * @defaultValue `true`
1367
- */
1368
- hideArrow?: boolean;
1369
-
1370
- /**
1371
- * Reset modelValue to `null` or empty array if it no longer matches available items.
1372
- */
1373
- enforceCoherence?: boolean;
1374
-
1375
- /**
1376
- * Controls how options are filtered during search.
1377
- *
1378
- * @defaultValue `() => []`
1379
- */
1380
- filterBy?:
1381
- | string
1382
- | string[]
1383
- | false
1384
- | 'not_stashed'
1385
- | ((value: any, item: any, query: string | null) => boolean)
1386
- | null;
1387
-
1388
- /** Path to item property for grouping options. */
1389
- groupBy?: string | ((item: Item) => string | number | symbol);
1390
-
1391
- /**
1392
- * Height of group headers in the listbox (px). Defaults to 24px (compact) or 32px.
1393
- * Only applies when `groupBy` is set.
1394
- */
1395
- headerHeight?: number;
1396
-
1397
- /**
1398
- * Explicit id for the component. Used to generate ids for listbox and options.
1399
- */
1400
- id?: HTMLAttributes['id'];
1401
-
1402
- /**
1403
- * Array of items or function to load them asynchronously.
1404
- * Functions receive `(query, prefill, modelValue)` and can return a promise.
1405
- *
1406
- * @defaultValue `[]`
1407
- */
1408
- items:
1409
- | Item[]
1410
- | ((query: string, prefill: boolean, modelValue: any[]) => Promise<Item[]>)
1411
- | ((query: string, prefill: boolean, modelValue: any[]) => Item[]);
1412
-
1413
- /**
1414
- * Height of the options in the listbox (px).
1415
- *
1416
- * @defaultValue `40`
1417
- */
1418
- itemHeight?: number;
1419
-
1420
- /**
1421
- * Path to item property for display text or function to extract it.
1422
- */
1423
- itemText?: string | ((item: Item) => string) | undefined;
1424
-
1425
- /**
1426
- * Path to item property for value or function to extract it.
1427
- */
1428
- itemValue?: string | ((item: Item) => string) | undefined;
1429
-
1430
- /**
1431
- * Display the loading state styles.
1432
- */
1433
- loading?: boolean;
1434
-
1435
- /**
1436
- * Message shown while items are being loaded.
1437
- */
1438
- loadingText?: string;
1439
-
1440
- /**
1441
- * Maximum number of selectable items (limits selection when `multiple` is true).
1442
- *
1443
- * @defaultValue `Infinity`
1444
- */
1445
- max?: number;
1446
-
1447
- /**
1448
- * v-model value. Single value for single select, array for multiple select.
1449
- */
1450
- modelValue: any;
1451
-
1452
- /**
1453
- * Debounce delay (ms) for modelValue change handling.
1454
- *
1455
- * @defaultValue `0`
1456
- */
1457
- modelValueDebounceTime?: number;
1458
-
1459
- /**
1460
- * Enable multiple item selection. When true, modelValue must be an array.
1461
- */
1462
- multiple?: boolean;
1463
-
1464
- /**
1465
- * Message displayed when no items are available.
1466
- */
1467
- noDataText?: string;
1468
-
1469
- /**
1470
- * Distance (px) between the activator and the popover.
1471
- *
1472
- * @defaultValue `4`
1473
- */
1474
- offset?: number;
1475
-
1476
- /**
1477
- * Minimum page padding used by floating shift middleware.
1478
- *
1479
- * @defaultValue `0`
1480
- */
1481
- padding?: CommonProps['padding'];
1482
-
1483
- /**
1484
- * Floating placement of the popover.
1485
- *
1486
- * @defaultValue `'bottom'`
1487
- */
1488
- placement?: CommonProps['placement'];
1489
-
1490
- /**
1491
- * Controls when items are pre-loaded.
1492
- * `'interaction'` loads on first user interaction, `true` loads immediately,
1493
- * `false` loads only on explicit search/open flows.
1494
- *
1495
- * @defaultValue `'interaction'`
1496
- */
1497
- prefill?: boolean | 'interaction';
1498
-
1499
- /**
1500
- * Debounce delay (ms) before triggering search queries after user input stops.
1501
- *
1502
- * @defaultValue `500`
1503
- */
1504
- queryDebounceTime?: number;
1505
-
1506
- /**
1507
- * Prevents opening the popover while keeping the activator accessible.
1508
- */
1509
- readonly?: boolean;
1510
-
1511
- /**
1512
- * Accessible label used by the search input rendered inside the popover.
1513
- *
1514
- * @defaultValue `'Search options'`
1515
- */
1516
- searchInputAriaLabel?: string;
1517
-
1518
- /**
1519
- * Accumulate selected items across searches instead of replacing them.
1520
- */
1521
- stash?: boolean;
1522
-
1523
- /**
1524
- * Transition duration (ms) for popover show/hide animations.
1525
- *
1526
- * @defaultValue `300`
1527
- */
1528
- transitionDuration?: number;
1529
-
1530
- /**
1531
- * Width of the popover in pixels, percentage, or `'auto'`.
1532
- */
1533
- width?: number | string;
1534
- };
1080
+ const statuses = ['Draft', 'In review', 'Approved', 'Published'];
1081
+ type Status = (typeof statuses)[number];
1535
1082
 
1536
- export type BbSelectPopoverEvents = {
1537
- /**
1538
- * Emitted when the activator loses focus.
1539
- */
1540
- (e: 'blur', event: FocusEvent): void;
1541
- /**
1542
- * Emitted when the value changes via native change event.
1543
- */
1544
- (e: 'change', event: Event): void;
1545
- /**
1546
- * Emitted when the activator is clicked.
1547
- */
1548
- (e: 'click', event: MouseEvent): void;
1549
- /**
1550
- * Emitted when the activator receives focus.
1551
- */
1552
- (e: 'focus', event: FocusEvent): void;
1553
- /**
1554
- * Emitted when focus moves outside the entire component after it was active.
1555
- */
1556
- (e: 'inactive'): void;
1557
- /**
1558
- * Emitted on native input events from the search input.
1559
- */
1560
- (e: 'input', event: Event): void;
1561
- /**
1562
- * Emitted with the next selection value whenever selection changes.
1563
- */
1564
- (e: 'update:modelValue', value: any): void;
1565
- /**
1566
- * Emitted when the user types a new value and confirms it (Enter key) when `allowWriting` is enabled.
1567
- */
1568
- (e: 'option:add', text: string): void;
1569
- };
1083
+ const status = ref<Status | null>(null);
1570
1084
 
1571
- /** Props exposed by the `activator` slot. */
1572
- export type BbSelectPopoverActivatorSlotProps = {
1573
- /** Bind onto the activator element with `v-bind="props"` to wire up the popover reference. */
1574
- props: {
1575
- ref: (reference: unknown) => void;
1576
- };
1577
- /** Whether the popover is currently open. */
1578
- shown: boolean;
1579
- /** Whether the select is disabled. */
1580
- disabled: boolean | undefined;
1581
- /** Whether the select is read-only. */
1582
- readonly: boolean | undefined;
1583
- /** Whether options are currently being fetched. */
1584
- loading: boolean;
1585
- /** The current search query string. */
1586
- query: string;
1587
- /** Clears the current selection and query. */
1588
- clear: () => void;
1589
- /** Opens the popover. */
1590
- open: () => Promise<void>;
1591
- /** Closes the popover. */
1592
- close: () => Promise<void>;
1593
- /** Toggles the popover open/closed. */
1594
- toggle: () => Promise<void>;
1085
+ const VARIANT: Record<Status, BadgeVariantType> = {
1086
+ Draft: 'soft-gray',
1087
+ 'In review': 'soft-amber',
1088
+ Approved: 'soft-blue',
1089
+ Published: 'soft-green',
1595
1090
  };
1596
1091
 
1597
- /** Props exposed by the `option` slot. */
1598
- export type BbSelectPopoverOptionSlotProps<Item> = {
1599
- /** Whether this option is disabled. */
1600
- disabled: boolean;
1601
- /** Whether this option currently has keyboard focus. */
1602
- focused: boolean;
1603
- /** Zero-based index of this option in the list. */
1604
- index: number;
1605
- /** The raw item from the `items` prop. */
1606
- item: Item;
1607
- /** Whether items are still being fetched. */
1608
- loading: boolean;
1609
- /** Whether this option is currently selected. */
1610
- selected: boolean;
1611
- /** The resolved display text for this option. */
1612
- text: string;
1613
- /** The resolved value for this option. */
1614
- value: any;
1615
- };
1092
+ const variantFor = (value: Status | null): BadgeVariantType =>
1093
+ value ? VARIANT[value] : 'outline';
1094
+ </script>
1616
1095
 
1617
- /** Props exposed by the `group` slot. */
1618
- export type BbSelectPopoverGroupSlotProps<Item> = {
1619
- /** The display text for this group. */
1620
- text: string;
1621
- /** The raw group item. */
1622
- item: Item;
1623
- /** Zero-based index of the first option in this group. */
1624
- index: number;
1625
- /** Number of options in this group. */
1626
- length: number;
1627
- /** Whether all options in this group are disabled. */
1628
- disabled: boolean;
1629
- };
1096
+ <!-- Soft status palette canonical source: ai/guides/design-language.md § Using color. -->
1097
+ <style>
1098
+ .bb-badge.bb-badge--soft-gray {
1099
+ --accent: #64748b;
1100
+ }
1101
+ .bb-badge.bb-badge--soft-blue {
1102
+ --accent: #2563eb;
1103
+ }
1104
+ .bb-badge.bb-badge--soft-green {
1105
+ --accent: #16a34a;
1106
+ }
1107
+ .bb-badge.bb-badge--soft-amber {
1108
+ --accent: #d97706;
1109
+ }
1110
+ .bb-badge.bb-badge--soft-gray,
1111
+ .bb-badge.bb-badge--soft-blue,
1112
+ .bb-badge.bb-badge--soft-green,
1113
+ .bb-badge.bb-badge--soft-amber {
1114
+ --bg: color-mix(in oklab, var(--accent) 15%, var(--bb-panel));
1115
+ --color: color-mix(in oklab, var(--accent) 80%, var(--bb-text));
1116
+ --border-width: 1px;
1117
+ --border-color: color-mix(in oklab, var(--accent) 25%, var(--bb-panel));
1118
+ --ring: color-mix(in oklab, var(--accent) 45%, transparent);
1119
+ }
1630
1120
 
1631
- export type BbSelectPopoverSlots<Item> = {
1632
- /**
1633
- * Replaces the default trigger element that opens the select popover.
1634
- */
1635
- activator?: (props: BbSelectPopoverActivatorSlotProps) => any;
1636
- /**
1637
- * Content shown inside the options dropdown while items are loading.
1638
- */
1639
- loading?: (props: { query: string }) => any;
1640
- /**
1641
- * Content shown when no options match the query or the list is empty.
1642
- */
1643
- 'no-data'?: (props: { query: string; focus: () => void }) => any;
1644
- /**
1645
- * Replaces the default rendering of each option row in the dropdown.
1646
- */
1647
- option?: (props: BbSelectPopoverOptionSlotProps<Item>) => any;
1648
- /**
1649
- * Replaces the default group header rendered above grouped options.
1650
- */
1651
- group?: (props: BbSelectPopoverGroupSlotProps<Item>) => any;
1652
- /**
1653
- * Content appended inside the options list, after the last option.
1654
- */
1655
- 'options:append'?: (props: { focus: () => void }) => any;
1656
- /**
1657
- * Content appended outside the options list container.
1658
- */
1659
- 'options:append:outer'?: (props: { focus: () => void }) => any;
1660
- /**
1661
- * Content prepended inside the options list, before the first option.
1662
- */
1663
- 'options:prepend'?: (props: { focus: () => void }) => any;
1664
- /**
1665
- * Content prepended outside the options list container.
1666
- */
1667
- 'options:prepend:outer'?: (props: { focus: () => void }) => any;
1668
- };
1121
+ .status-trigger--editing {
1122
+ --bg: color-mix(in oklab, var(--color) 25%, var(--bb-panel));
1123
+ --border-color: color-mix(in oklab, var(--color) 45%, var(--bb-panel));
1124
+ box-shadow: 0 0 0 var(--bb-ring-size) var(--ring);
1125
+ }
1126
+ </style>
1669
1127
  ```
1128
+
1129
+ ### Sizing and layout
1130
+
1131
+ - `width` sets the popover width — a number (px), a CSS string (`'240px'`,
1132
+ `'100%'`), or `'auto'`. Unlike `BbSelect` (whose panel always matches the
1133
+ control), here the trigger and panel are independent, so size the panel
1134
+ explicitly.
1135
+ - `compact` applies the dense density variant (32px options, 24px group headers).
1136
+ - `item-height` / `header-height` tune the virtualized row heights when you use
1137
+ taller custom `#option` / `#group` markup.
1138
+ - Placement props mirror the palette/dropdown float: `placement`, `offset`
1139
+ (default 4), `padding`, `boundary`, `disable-flip`, `transition-duration`. The
1140
+ panel is a frame, not a bubble — it never shows an arrow.
1141
+
1142
+ ### Adaptive mobile sheet
1143
+
1144
+ With `adaptive` (default: global `config.adaptive`, which is `true`), the panel
1145
+ opens as a bottom off-canvas sheet on mobile viewports (below
1146
+ `config.mobileMaxWidth`) instead of a floating popover — same search, options and
1147
+ `#header`/`#footer` slots, plus a representation of the current selection between
1148
+ them. The surface is **latched per open cycle**: a mid-open resize never swaps
1149
+ popover ↔ sheet. `off-canvas-props` forwards extra `BbOffCanvas` props to the
1150
+ sheet (`size`, `draggable`, `fullscreen`, `stack`); `:adaptive="false"` keeps a
1151
+ floating popover everywhere.
1152
+
1153
+ ### Events and v-model
1154
+
1155
+ - `update:modelValue` — the resolved value (single) or array (multiple), on pick,
1156
+ `clear`, coherence enforcement, and — in `multiple` mode only — deselect.
1157
+ A second click on the current option in single mode emits nothing.
1158
+ - `option:add` — Enter on a non-matching query with nothing highlighted (above).
1159
+ - `focus` / `blur` — the activator gaining/losing focus.
1160
+ - `input` / `change` — native events from the panel search field.
1161
+ - `click` — the activator was clicked.
1162
+ - `inactive` — focus has fully left the component (**trigger and panel**). Because
1163
+ focus legitimately moves into the panel while open, validate/react on
1164
+ `inactive`, not on `blur`.
1165
+
1166
+ ### Config and platform
1167
+
1168
+ - **No teleport** — the popover renders **in the component's own subtree** (it is
1169
+ not portalled to `<body>`), so it inherits your CSS context and is directly
1170
+ queryable (handy for tests: the open panel is `.bb-listbox--open` on the same
1171
+ root, no portal hop).
1172
+ - **Global config** — `config.adaptive` (default for `adaptive`),
1173
+ `config.mobileMaxWidth` (the mobile threshold), `config.locale` (the search
1174
+ field's default accessible name and panel string defaults).
1175
+ - **SSR / Nuxt** — `prefill: true` providers also run in `onServerPrefetch`, so
1176
+ server-rendered pages hydrate with options loaded; keep providers isomorphic
1177
+ (no `window` access).
1178
+
1179
+ ### Works well with
1180
+
1181
+ - `BbSelect` — the same engine as a labelled form field; swap when the trigger
1182
+ should be an inline input with hint/error states.
1183
+ - `BbTable` — popover triggers as inline-edit cells or toolbar filters; list
1184
+ their models in the table provider's `dependencies`.
1185
+ - `BbButton` — the natural activator (it forwards `props` and exposes a
1186
+ `loading` state to reflect fetches).
1187
+ - `useToast` — surface provider failures the component only logs.
1188
+
1189
+ ### Gotchas and constraints
1190
+
1191
+ - `multiple` with a non-array model **throws at setup** — seed `ref([])`.
1192
+ - A seeded model shows **no trigger `text`** until the first load (no eager
1193
+ prefill upgrade, by design) — resolve the label from your own state. Array
1194
+ `items` resolve on mount, so this only bites providers.
1195
+ - The local substring filter also applies to provider results — server matches
1196
+ whose text doesn't contain the query are hidden.
1197
+ - `filter-by` is `string[]` only and matches exactly those paths; each must exist
1198
+ on every item or matching throws.
1199
+ - `prefill: false` is search-first: opening fetches nothing and the panel shows
1200
+ the "search to begin" hint until the user types. It quietly falls back to
1201
+ loading on open when writing is disabled, the model is non-empty, or `items` is
1202
+ an array.
1203
+ - `enforce-coherence` + a provider that drops the selection on component-initiated
1204
+ (`prefill === true`) calls = wiped model — and since the check now runs on the
1205
+ **first** load, that wipe happens at mount rather than later. Resolve the
1206
+ current selection in those responses, or enable `stash`.
1207
+ - `enforce-coherence` opts **each instance** into its own load. One field, one
1208
+ request; N provider-backed rows, N requests.
1209
+ - `option:add` can fire with an empty string — trim and guard.
1210
+ - **Clicking the selected option does not clear a single select** — it re-picks
1211
+ it and closes the panel. Emptying is the `clear` callback (activator/panel
1212
+ slot scope), never an accidental second click. Multiple mode still toggles.
1213
+ - **`null` as a real "All" option** works — it resolves and renders as the
1214
+ selection — but it overloads the value the component uses for _nothing
1215
+ selected_. So a `null` model stays lazy (nothing to resolve, no load, not even
1216
+ with `enforce-coherence`), `clear` is indistinguishable from picking "All", and
1217
+ an `enforce-coherence` prune emits `null` — i.e. a stale value **widens to
1218
+ "All"** rather than clearing. Fine if you want it; use a sentinel
1219
+ (`'all'`) if "everything" and "nothing" must stay distinct.
1220
+
1221
+ ### Anti-patterns
1222
+
1223
+ - Reading `text` (or `selectedOptions`) for the trigger label instead of
1224
+ computing it from your own state — with a provider they are empty until the
1225
+ first load, so the trigger's appearance ends up depending on whether the panel
1226
+ was ever opened.
1227
+ - Binding many instances to **one shared ref**: each judges the same value against
1228
+ its own options and every instance that disagrees emits `null`, so the user's
1229
+ pick is overwritten by its neighbours. One model per row.
1230
+ - Giving every table row its own **provider**: N rows becomes N requests. Resolve
1231
+ the options once at page level and pass the same array down.
1232
+ - Reaching for `prefill: true` to populate a trigger label.
1233
+ - Rebuilding chips, counts or select-all in wrapper markup when `max`,
1234
+ `selectedOptions` and the panel slots cover it.
1235
+ - Hand-rolled debounce/loading refs around the provider.
1236
+ - `watch(filter, refetch)` when `dependencies` exists; blind `model = null`
1237
+ resets when `enforce-coherence` would preserve still-valid values.
1238
+ - Using it where an inline labelled field is wanted (that's `BbSelect`), or for a
1239
+ static three-option choice (that's `BbRadioGroup`).
1240
+
1241
+ ### Accessibility
1242
+
1243
+ - The activator carries the accessible name — make it a real focusable element (a
1244
+ `<button>` or `BbButton`), and give icon-only triggers an `aria-label`.
1245
+ - The in-panel search field is labelled by `search-input-aria-label` (defaults to
1246
+ "Search options"); override it to match your domain.
1247
+ - The component manages listbox roles, `aria-activedescendant`, the full keyboard
1248
+ model and focus return to the trigger on close — do not reimplement them.
1249
+ - Because the trigger is yours, reflect the open state visually (the `shown` slot
1250
+ prop) so keyboard and low-vision users can see the popover is expanded.
1251
+
1252
+ ## v-model
1253
+
1254
+ - `v-model` — type: `any`
1255
+
1256
+ ## Props
1257
+
1258
+ | Prop | Type | Default | Required | Description |
1259
+ | --- | --- | --- | --- | --- |
1260
+ | `activator` | `Record<string, any> \| HTMLElement \| null \| undefined` | | | External activator element or component ref. When provided, the activator slot is not rendered and event listeners are attached programmatically to the referenced element. |
1261
+ | `adaptive` | `boolean \| undefined` | `undefined` | | When `true`, the panel opens as a bottom off-canvas sheet on mobile viewports instead of a floating popover; on desktop it stays a popover. The sheet reuses the same search field and options list, adding a representation of the current sele… |
1262
+ | `anchor` | `Record<string, any> \| HTMLElement \| null \| undefined` | `null` | | Override the element used for popover positioning and width measurement. Useful when the focusable activator is narrower than its visual container (e.g. a button inside a wrapper). Falls back to `activatorEl` when omitted. |
1263
+ | `ariaDescribedby` | `string \| string[] \| undefined` | | | Space-separated IDREF(s) that describe this field for assistive technologies. Accepts either a string or array of ids. |
1264
+ | `ariaInvalid` | `boolean \| undefined` | `undefined` | | Explicit invalid state for accessibility semantics. Falls back to `hasErrors` when not provided. |
1265
+ | `autocomplete` | `string \| undefined` | `"off"` | | Browser autocomplete hint for the popover search input. |
1266
+ | `boundary` | `string \| Record<string, any> \| HTMLElement \| null \| undefined` | | | Constrains the popover to a specific boundary element. |
1267
+ | `clearable` | `boolean \| undefined` | | | Shows a clear button inside the search field's icon stack: it takes the lens' place on hover/focus while there is a query or selection to clear, and resets both. Off by default. Leave it off when the component is wrapped by a control that a… |
1268
+ | `compact` | `boolean \| undefined` | | | Apply the compact density variant. |
1269
+ | `dependencies` | `unknown[] \| undefined` | `[]` | | Additional dependencies that trigger item reloading when changed. |
1270
+ | `depsDebounceTime` | `number \| undefined` | `0` | | Debounce delay (ms) for dependency-triggered reloads. |
1271
+ | `disabled` | `boolean \| undefined` | | | Disables the component. |
1272
+ | `disableFlip` | `boolean \| undefined` | | | Disables the automatic flip to the opposite side when the popover would overflow (flipping is on by default). |
1273
+ | `disableWriting` | `boolean \| "mobile" \| "desktop" \| undefined` | | | Controls whether the search input is shown inside the popover panel. Use `'mobile'` to hide the search input on mobile, `'desktop'` to hide it on desktop. |
1274
+ | `enforceCoherence` | `boolean \| undefined` | | | Reset modelValue to `null` or empty array if it no longer matches available items. |
1275
+ | `filterBy` | `string[] \| undefined` | `[]` | | Property paths used to filter options when the user types in the search input. When empty (default) options are matched against their display text. When non-empty the provided paths are searched instead of the display text. To disable filte… |
1276
+ | `groupBy` | `string \| ((item: Item) => string \| number \| symbol) \| undefined` | | | Path to item property for grouping options. |
1277
+ | `hasErrors` | `boolean \| undefined` | | | Marks the component as being in error state. |
1278
+ | `hasWarning` | `boolean \| undefined` | | | Marks the component as being in a warning state. Visually mirrors `hasErrors` but uses `--bb-warn` chrome; errors take priority when both are set. |
1279
+ | `headerHeight` | `number \| undefined` | | | Height of group headers in the listbox (px). Defaults to 24px (compact) or 32px. Only applies when `groupBy` is set. |
1280
+ | `id` | `string \| undefined` | | | Explicit id for the component. Used to generate ids for listbox and options. |
1281
+ | `itemHeight` | `number \| undefined` | | | Height of the options in the listbox (px). |
1282
+ | `items` | `Item[] \| ((query: string, prefill: boolean, modelValue: any) => Promise<Item[]>) \| ((query: string, prefill: boolean, modelValue: any) => Item[])` | | yes | Array of items or function to load them asynchronously. Functions receive `(query, prefill, modelValue)` and can return a promise. `modelValue` is the raw v-model: an array in `multiple` mode, the raw model value (possibly `null`) in single… |
1283
+ | `itemText` | `ItemAccessor<Item, string> \| undefined` | | | Path to item property for display text or function to extract it. |
1284
+ | `itemValue` | `ItemAccessor<Item> \| undefined` | | | Path to item property for value or function to extract it. |
1285
+ | `loading` | `boolean \| undefined` | | | Display the loading state styles. |
1286
+ | `loadingText` | `string \| undefined` | | | Message shown while items are being loaded. |
1287
+ | `max` | `number \| undefined` | `Infinity` | | Maximum number of selectable items (limits selection when `multiple` is true). |
1288
+ | `modelValue` | `any` | | yes | v-model value. Single value for single select, array for multiple select. |
1289
+ | `modelValueDebounceTime` | `number \| undefined` | `0` | | Debounce delay (ms) for modelValue change handling. |
1290
+ | `multiple` | `boolean \| undefined` | | | Enable multiple item selection. When true, modelValue must be an array. |
1291
+ | `noDataText` | `string \| undefined` | | | Message displayed when no items are available. |
1292
+ | `offCanvasProps` | `Partial<BbOffCanvasProps> \| undefined` | | | Extra props forwarded to the `BbOffCanvas` sheet when `adaptive` is active on mobile (e.g. `size`, `draggable`, `fullscreen`, `stack`). |
1293
+ | `offset` | `number \| undefined` | `4` | | Distance (px) between the activator and the popover. |
1294
+ | `padding` | `number \| undefined` | `10` | | Minimum page padding used by floating shift middleware. |
1295
+ | `placement` | `Placement \| undefined` | `"bottom"` | | Floating placement of the popover. |
1296
+ | `prefill` | `boolean \| "interaction" \| undefined` | `"interaction"` | | Controls when items are pre-loaded. `'interaction'` loads on the first user interaction (opening the popover), `true` loads immediately on mount (and during SSR via `onServerPrefetch`), `false` is *search-first*: nothing is fetched until th… |
1297
+ | `queryDebounceTime` | `number \| undefined` | `500` | | Debounce delay (ms) before triggering search queries after user input stops. |
1298
+ | `readonly` | `boolean \| undefined` | | | Prevents opening the popover while keeping the activator accessible. |
1299
+ | `searchInputAriaLabel` | `string \| undefined` | | | Accessible label used by the search input rendered inside the popover. Falls back to the localized `select.searchLabel` key when omitted. |
1300
+ | `selectable` | `boolean \| ((item: Item) => boolean) \| undefined` | `true` | | Defines whether options are selectable. Can be a global boolean that affects all options or a function that accepts an item and returns a boolean that only affects that item. Non-selectable options are rendered disabled. |
1301
+ | `stash` | `boolean \| undefined` | | | Accumulate selected items across searches instead of replacing them. |
1302
+ | `transitionDuration` | `number \| undefined` | `transitions.medium` | | Transition duration (ms) for popover show/hide animations. |
1303
+ | `width` | `string \| number \| undefined` | `"200"` | | Width of the popover in pixels, percentage, or `'auto'`. |
1304
+
1305
+ ## Events
1306
+
1307
+ - `active` — `(e: "active"): void` — Emitted when the component becomes active (focus enters it).
1308
+ - `blur` — `(e: "blur", event: FocusEvent): void` — Emitted when the activator loses focus.
1309
+ - `change` — `(e: "change", event: Event): void` — Emitted when the value changes via native change event.
1310
+ - `click` — `(e: "click", event: MouseEvent): void` — Emitted when the activator is clicked.
1311
+ - `focus` — `(e: "focus", event: FocusEvent): void` — Emitted when the activator receives focus.
1312
+ - `inactive` — `(e: "inactive"): void` — Emitted when focus moves outside the entire component after it was active.
1313
+ - `input` — `(e: "input", event: Event): void` — Emitted on native input events from the search input.
1314
+ - `option:add` — `(e: "option:add", text: string): void` — Emitted when the user types a new value and confirms it (Enter key) while writing is enabled (i.e. `disableWriting` does not suppress the search input for the current surface).
1315
+ - `update:modelValue` — `(e: "update:modelValue", value: any): void` — Emitted with the next selection value whenever selection changes.
1316
+
1317
+ ## Slots
1318
+
1319
+ - `activator` — scope: `BbSelectPopoverActivatorSlotProps` — Replaces the default trigger element that opens the select popover.
1320
+ - `footer` — scope: `BbSelectPopoverPanelSlotProps` — Content pinned to the bottom of the panel, below the options list. Rendered in both the desktop popover and the adaptive sheet.
1321
+ - `group` — scope: `BbSelectPopoverGroupSlotProps<Item>` — Replaces the default group header rendered above grouped options.
1322
+ - `header` — scope: `BbSelectPopoverPanelSlotProps` — Content pinned to the top of the panel, above the search field. Rendered in both the desktop popover and the adaptive sheet.
1323
+ - `loading` — scope: `{ query: string; }` — Content shown inside the options dropdown while items are loading.
1324
+ - `no-data` — scope: `{ query: string; focus: () => void; }` — Content shown when no options match the query or the list is empty.
1325
+ - `option` — scope: `BbSelectPopoverOptionSlotProps<Item>` — Replaces the default rendering of each option row in the dropdown.
1326
+
1327
+ ## See Also
1328
+
1329
+ - [BbSelect](./BbSelect.md) — Selects one or many options from structured data.
1330
+ - [BbPopover](./BbPopover.md) — Anchors floating content to reference elements.