bitboss-ui 3.0.0-beta.48 → 3.0.0-beta.49

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 (356) hide show
  1. package/README.md +24 -7
  2. package/bin/bitboss-ui-mcp.mjs +15 -3
  3. package/bin/bitboss-ui.mjs +115 -13
  4. package/dist/ai/BbAvatar.md +1 -1
  5. package/dist/ai/BbBreadcrumbs.md +65 -65
  6. package/dist/ai/BbButton.md +16 -5
  7. package/dist/ai/BbCheckbox.md +0 -2
  8. package/dist/ai/BbCheckboxGroup.md +13 -20
  9. package/dist/ai/BbDatePickerInput.md +4 -2
  10. package/dist/ai/BbDialog.md +1 -8
  11. package/dist/ai/BbDropdown.md +231 -220
  12. package/dist/ai/BbDropdownButton.md +65 -65
  13. package/dist/ai/BbDropdownGroup.md +2 -2
  14. package/dist/ai/BbDropzone.md +10 -10
  15. package/dist/ai/BbForm.md +43 -52
  16. package/dist/ai/BbHoverCard.md +4 -2
  17. package/dist/ai/BbNumberInput.md +88 -21
  18. package/dist/ai/BbPopover.md +29 -23
  19. package/dist/ai/BbProgress.md +48 -22
  20. package/dist/ai/BbRadioGroup.md +13 -19
  21. package/dist/ai/BbSelect.md +16 -36
  22. package/dist/ai/BbSelectPopover.md +14 -30
  23. package/dist/ai/BbSmoothHeight.md +0 -2
  24. package/dist/ai/BbSwitchGroup.md +13 -20
  25. package/dist/ai/BbTable.md +11 -10
  26. package/dist/ai/BbTabs.md +106 -105
  27. package/dist/ai/BbTabsList.md +2 -2
  28. package/dist/ai/BbTabsPanels.md +1 -1
  29. package/dist/ai/BbTabsRoot.md +2 -2
  30. package/dist/ai/BbTooltip.md +24 -10
  31. package/dist/ai/BbTree.md +14 -11
  32. package/dist/ai/changelog.json +256 -5
  33. package/dist/ai/components.json +36 -34
  34. package/dist/ai/composables/useBbDropdownContext.md +16 -16
  35. package/dist/ai/composables/useBbFormField.md +5 -1
  36. package/dist/ai/composables/useBbTabsContext.md +14 -14
  37. package/dist/ai/guides/agent-contract.md +27 -27
  38. package/dist/ai/guides/ai-router.md +1 -1
  39. package/dist/ai/guides/component-picker.md +3 -3
  40. package/dist/ai/guides/fetch-items-playbook.md +1 -1
  41. package/dist/ai/guides/icons-policy.md +10 -10
  42. package/dist/ai/guides/inertia-helpers.md +120 -67
  43. package/dist/ai/guides/installation-and-plugin-setup.md +43 -15
  44. package/dist/ai/guides/migration/components/bb-breadcrumbs.md +3 -2
  45. package/dist/ai/guides/migration/components/bb-checkbox-group.md +16 -16
  46. package/dist/ai/guides/migration/components/bb-dropdown-button.md +9 -8
  47. package/dist/ai/guides/migration/components/bb-dropdown.md +15 -14
  48. package/dist/ai/guides/migration/components/bb-radio-group.md +2 -1
  49. package/dist/ai/guides/migration/components/bb-select-popover.md +6 -1
  50. package/dist/ai/guides/migration/components/bb-select.md +10 -2
  51. package/dist/ai/guides/migration/components/bb-switch-group.md +2 -1
  52. package/dist/ai/guides/migration/components/bb-tabs.md +9 -8
  53. package/dist/ai/guides/migration/components/bb-tooltip.md +1 -1
  54. package/dist/ai/guides/migration/v2-to-v3.md +114 -17
  55. package/dist/ai/guides/migration/v3-beta-tooling.md +11 -0
  56. package/dist/ai/guides/options-items-playbook.md +30 -24
  57. package/dist/ai/guides/passthrough.md +2 -2
  58. package/dist/ai/guides/preset-components.md +18 -3
  59. package/dist/ai/guides/typescript-generic-components.md +1 -1
  60. package/dist/ai/guides/validated-forms.md +11 -22
  61. package/dist/ai/guides/validation-providers.md +4 -3
  62. package/dist/ai/helpers/inertia/manifest.json +636 -0
  63. package/dist/ai/helpers/inertia/types.ts +15 -0
  64. package/dist/ai/helpers/inertia/useAsyncFn.ts +110 -0
  65. package/dist/ai/helpers/inertia/useConfirmOnRouteLeave.ts +102 -0
  66. package/dist/ai/helpers/inertia/useDeleteCmd.ts +30 -0
  67. package/dist/ai/helpers/inertia/useHasChanged.ts +36 -0
  68. package/dist/ai/helpers/inertia/useIndexById.ts +23 -0
  69. package/dist/ai/helpers/inertia/useLazyProp.ts +148 -0
  70. package/dist/ai/helpers/inertia/useLazyPropGetter.ts +50 -0
  71. package/dist/ai/helpers/inertia/useLoading.ts +20 -0
  72. package/dist/ai/helpers/inertia/usePaginatedResponseContext.ts +88 -0
  73. package/dist/ai/helpers/inertia/usePromiseForm.ts +62 -0
  74. package/dist/ai/helpers/inertia/useProp.ts +63 -0
  75. package/dist/ai/helpers/inertia/useQuery.ts +19 -0
  76. package/dist/ai/helpers/inertia/useQueryObject.ts +116 -0
  77. package/dist/ai/helpers/inertia/useResourceContext.ts +69 -0
  78. package/dist/ai/helpers/inertia/useRouteQuery.ts +54 -0
  79. package/dist/ai/helpers/inertia/useScreenSizes.ts +23 -0
  80. package/dist/ai/helpers/inertia/useTableContext.ts +34 -0
  81. package/dist/ai/helpers/inertia/useTableSelectionContext.ts +48 -0
  82. package/dist/ai/helpers/inertia/useUntil.ts +33 -0
  83. package/dist/ai/helpers/inertia/utils.ts +24 -0
  84. package/dist/ai/index.md +6 -6
  85. package/dist/ai/manifest/components/BbBreadcrumbs.json +10 -6
  86. package/dist/ai/manifest/components/BbBreadcrumbs.tree.json +1 -1
  87. package/dist/ai/manifest/components/BbButton.json +1 -1
  88. package/dist/ai/manifest/components/BbCheckboxGroup.json +2 -2
  89. package/dist/ai/manifest/components/BbDropdown.json +23 -20
  90. package/dist/ai/manifest/components/BbDropdown.tree.json +2 -2
  91. package/dist/ai/manifest/components/BbDropdownButton.json +22 -19
  92. package/dist/ai/manifest/components/BbDropdownButton.tree.json +1 -1
  93. package/dist/ai/manifest/components/BbDropdownGroup.json +2 -2
  94. package/dist/ai/manifest/components/BbForm.json +1 -0
  95. package/dist/ai/manifest/components/BbNumberInput.json +6 -1
  96. package/dist/ai/manifest/components/BbNumberInput.tree.json +2 -1
  97. package/dist/ai/manifest/components/BbPopover.json +1 -0
  98. package/dist/ai/manifest/components/BbProgress.json +6 -6
  99. package/dist/ai/manifest/components/BbProgress.tree.json +1 -0
  100. package/dist/ai/manifest/components/BbRadioGroup.json +2 -2
  101. package/dist/ai/manifest/components/BbSelect.json +2 -2
  102. package/dist/ai/manifest/components/BbSelectPopover.json +2 -2
  103. package/dist/ai/manifest/components/BbSwitchGroup.json +2 -2
  104. package/dist/ai/manifest/components/BbTabs.json +7 -6
  105. package/dist/ai/manifest/components/BbTabsList.json +3 -3
  106. package/dist/ai/manifest/components/BbTabsPanels.json +1 -1
  107. package/dist/ai/manifest/components/BbTabsRoot.json +5 -4
  108. package/dist/ai/manifest/components/BbTooltip.json +1 -1
  109. package/dist/ai/manifest/index.json +2 -2
  110. package/dist/ai/manifest/meta.json +2 -0
  111. package/dist/ai/manifest/types.advanced.json +10 -9
  112. package/dist/ai/manifest/types.api.json +5 -4
  113. package/dist/ai/recipes/inertia/approvals-inbox.md +16 -18
  114. package/dist/ai/recipes/inertia/inline-edit-workspace.md +23 -33
  115. package/dist/ai/recipes/inertia/layout-scaffold.md +16 -16
  116. package/dist/ai/recipes/inertia/onboarding.md +6 -10
  117. package/dist/ai/recipes/inertia/ownership-atlas.md +15 -18
  118. package/dist/ai/recipes/inertia/record-form.md +11 -11
  119. package/dist/ai/recipes/inertia/records-workspace.md +38 -41
  120. package/dist/ai/recipes/inertia/settings-workspace.md +26 -38
  121. package/dist/ai/recipes/inertia/upload-center.md +31 -39
  122. package/dist/ai/recipes/inertia/wizard-form.md +10 -19
  123. package/dist/ai/recipes/nuxt/approvals-inbox.md +7 -8
  124. package/dist/ai/recipes/nuxt/inline-edit-workspace.md +14 -24
  125. package/dist/ai/recipes/nuxt/layout-scaffold.md +16 -16
  126. package/dist/ai/recipes/nuxt/onboarding.md +2 -6
  127. package/dist/ai/recipes/nuxt/ownership-atlas.md +7 -9
  128. package/dist/ai/recipes/nuxt/record-form.md +5 -5
  129. package/dist/ai/recipes/nuxt/records-workspace.md +29 -31
  130. package/dist/ai/recipes/nuxt/settings-workspace.md +22 -34
  131. package/dist/ai/recipes/nuxt/upload-center.md +22 -29
  132. package/dist/ai/recipes/nuxt/wizard-form.md +3 -11
  133. package/dist/ai/recipes/vue/approvals-inbox.md +7 -8
  134. package/dist/ai/recipes/vue/inline-edit-workspace.md +14 -24
  135. package/dist/ai/recipes/vue/layout-scaffold.md +16 -16
  136. package/dist/ai/recipes/vue/onboarding.md +2 -6
  137. package/dist/ai/recipes/vue/ownership-atlas.md +7 -9
  138. package/dist/ai/recipes/vue/record-form.md +5 -5
  139. package/dist/ai/recipes/vue/records-workspace.md +29 -31
  140. package/dist/ai/recipes/vue/settings-workspace.md +22 -34
  141. package/dist/ai/recipes/vue/upload-center.md +22 -29
  142. package/dist/ai/recipes/vue/wizard-form.md +3 -11
  143. package/dist/ai/source/BbAccordion.md +1 -1
  144. package/dist/ai/source/BbAlert.md +3 -3
  145. package/dist/ai/source/BbBadge.md +2 -2
  146. package/dist/ai/source/BbBadgeButton.md +5 -4
  147. package/dist/ai/source/BbBaseButton.md +1 -1
  148. package/dist/ai/source/BbBaseRadioIcon.md +1 -0
  149. package/dist/ai/source/BbBaseSwitchIcon.md +1 -0
  150. package/dist/ai/source/BbBreadcrumbs.md +63 -42
  151. package/dist/ai/source/BbButton.md +71 -33
  152. package/dist/ai/source/BbCalendar.md +17 -16
  153. package/dist/ai/source/BbCheckbox.md +3 -2
  154. package/dist/ai/source/BbCheckboxGroup.md +11 -4
  155. package/dist/ai/source/BbColorInput.md +10 -9
  156. package/dist/ai/source/BbConfirm.md +1 -1
  157. package/dist/ai/source/BbConfirmPortal.md +1 -1
  158. package/dist/ai/source/BbDatePicker.md +2 -2
  159. package/dist/ai/source/BbDatePickerInput.md +47 -20
  160. package/dist/ai/source/BbDialog.md +5 -5
  161. package/dist/ai/source/BbDropdown.md +230 -158
  162. package/dist/ai/source/BbDropdownButton.md +19 -12
  163. package/dist/ai/source/BbDropdownGroup.md +126 -93
  164. package/dist/ai/source/BbForm.md +25 -1
  165. package/dist/ai/source/BbIndicator.md +4 -0
  166. package/dist/ai/source/BbNumberInput.md +855 -19
  167. package/dist/ai/source/BbOffCanvas.md +27 -11
  168. package/dist/ai/source/BbPagination.md +3 -3
  169. package/dist/ai/source/BbPopover.md +152 -8
  170. package/dist/ai/source/BbPopoverPortal.md +11 -0
  171. package/dist/ai/source/BbProgress.md +82 -18
  172. package/dist/ai/source/BbRadioGroup.md +12 -5
  173. package/dist/ai/source/BbRating.md +11 -9
  174. package/dist/ai/source/BbSelect.md +16 -10
  175. package/dist/ai/source/BbSelectPopover.md +29 -23
  176. package/dist/ai/source/BbSlider.md +12 -6
  177. package/dist/ai/source/BbSwitch.md +3 -2
  178. package/dist/ai/source/BbSwitchGroup.md +5 -2
  179. package/dist/ai/source/BbTable.md +102 -18
  180. package/dist/ai/source/BbTabs.md +27 -23
  181. package/dist/ai/source/BbTabsList.md +26 -22
  182. package/dist/ai/source/BbTabsPanels.md +26 -22
  183. package/dist/ai/source/BbTabsRoot.md +25 -21
  184. package/dist/ai/source/BbTag.md +10 -9
  185. package/dist/ai/source/BbTextInput.md +5 -4
  186. package/dist/ai/source/BbTextarea.md +6 -5
  187. package/dist/ai/source/BbTimePicker.md +1 -1
  188. package/dist/ai/source/BbTimePickerInput.md +46 -9
  189. package/dist/ai/source/BbToast.md +10 -7
  190. package/dist/ai/source/BbToastPortal.md +10 -7
  191. package/dist/ai/source/BbTooltip.md +54 -8
  192. package/dist/ai/source/BbTree.md +21 -3
  193. package/dist/ai/source/CommonField.md +6 -4
  194. package/dist/ai/source/CommonFieldInput.md +15 -10
  195. package/dist/ai/source/CommonPopover.md +6 -0
  196. package/dist/ai/source/CommonTimeSelector.md +5 -4
  197. package/dist/components/BbBadge/BbBadgeButton.vue_vue_type_script_setup_true_lang.js +10 -8
  198. package/dist/components/BbBaseButton/BbBaseButton.vue_vue_type_script_setup_true_lang.js +8 -8
  199. package/dist/components/BbBreadcrumbs/BbBreadcrumbs.vue_vue_type_script_setup_true_lang.js +45 -45
  200. package/dist/components/BbBreadcrumbs/types.d.ts +25 -17
  201. package/dist/components/BbButton/BbButton.vue_vue_type_script_setup_true_lang.js +84 -71
  202. package/dist/components/BbButton/toggleRoving.d.ts +6 -0
  203. package/dist/components/BbButton/toggleRoving.js +45 -0
  204. package/dist/components/BbButton/types.d.ts +4 -1
  205. package/dist/components/BbCalendar/BbCalendar.vue_vue_type_script_setup_true_lang.js +178 -178
  206. package/dist/components/BbCalendar/CalendarMonthPanel.vue_vue_type_script_setup_true_lang.js +15 -15
  207. package/dist/components/BbCalendar/CalendarYearPanel.vue_vue_type_script_setup_true_lang.js +28 -28
  208. package/dist/components/BbCalendar/useCalendarGrid.js +141 -139
  209. package/dist/components/BbCalendar/useDayjsLocale.d.ts +38 -15
  210. package/dist/components/BbCalendar/useDayjsLocale.js +31 -30
  211. package/dist/components/BbCheckbox/BbCheckbox.vue_vue_type_script_setup_true_lang.js +48 -48
  212. package/dist/components/BbCheckboxGroup/BbCheckboxGroup.vue_vue_type_script_setup_true_lang.js +81 -80
  213. package/dist/components/BbCheckboxGroup/types.d.ts +6 -2
  214. package/dist/components/BbColorInput/BbColorInput.vue_vue_type_script_setup_true_lang.js +69 -69
  215. package/dist/components/BbDatePickerInput/BbDatePickerInput.vue_vue_type_script_setup_true_lang.js +363 -349
  216. package/dist/components/BbDropdown/AdaptiveDropdown.vue_vue_type_script_setup_true_lang.js +91 -86
  217. package/dist/components/BbDropdown/BbDropdown.vue_vue_type_script_setup_true_lang.js +298 -289
  218. package/dist/components/BbDropdown/BbDropdownList.vue_vue_type_script_setup_true_lang.js +322 -356
  219. package/dist/components/BbDropdown/DropdownPipelineResolver.vue_vue_type_script_setup_true_lang.js +17 -15
  220. package/dist/components/BbDropdown/DropdownRow.vue.d.ts +40 -0
  221. package/dist/components/BbDropdown/DropdownRow.vue.js +5 -0
  222. package/dist/components/BbDropdown/DropdownRow.vue_vue_type_script_setup_true_lang.js +60 -0
  223. package/dist/components/BbDropdown/normalizeGroups.d.ts +8 -2
  224. package/dist/components/BbDropdown/normalizeGroups.js +60 -46
  225. package/dist/components/BbDropdown/types.d.ts +119 -88
  226. package/dist/components/BbDropdownButton/BbDropdownButton.vue_vue_type_script_setup_true_lang.js +11 -2
  227. package/dist/components/BbDropdownButton/types.d.ts +2 -2
  228. package/dist/components/BbForm/BbForm.vue.d.ts +9 -0
  229. package/dist/components/BbForm/BbForm.vue_vue_type_script_setup_true_lang.js +114 -105
  230. package/dist/components/BbForm/BbFormCustomField.js +1 -1
  231. package/dist/components/BbForm/bindFormField.js +2 -1
  232. package/dist/components/BbForm/formFields.d.ts +5 -0
  233. package/dist/components/BbNumberInput/BbNumberInput.vue.d.ts +0 -1
  234. package/dist/components/BbNumberInput/BbNumberInput.vue_vue_type_script_setup_true_lang.js +452 -125
  235. package/dist/components/BbNumberInput/numberDisplay.d.ts +256 -0
  236. package/dist/components/BbNumberInput/numberDisplay.js +499 -0
  237. package/dist/components/BbNumberInput/types.d.ts +54 -1
  238. package/dist/components/BbNumberInput/warroom/corpus.d.ts +58 -0
  239. package/dist/components/BbNumberInput/warroom/currency-verify.rows.d.ts +28 -0
  240. package/dist/components/BbNumberInput/warroom/currency.rows.d.ts +2 -0
  241. package/dist/components/BbNumberInput/warroom/harness.d.ts +217 -0
  242. package/dist/components/BbNumberInput/warroom/oracle.d.ts +150 -0
  243. package/dist/components/BbPagination/BbPagination.vue_vue_type_script_setup_true_lang.js +7 -7
  244. package/dist/components/BbPopover/BbPopover.vue.d.ts +1 -0
  245. package/dist/components/BbPopover/BbPopover.vue_vue_type_script_setup_true_lang.js +207 -164
  246. package/dist/components/BbPopover/types.d.ts +11 -0
  247. package/dist/components/BbProgress/BbProgress.vue_vue_type_script_setup_true_lang.js +15 -7
  248. package/dist/components/BbProgress/types.d.ts +23 -7
  249. package/dist/components/BbProgress/types.js +1 -1
  250. package/dist/components/BbRadioGroup/BbRadioGroup.vue_vue_type_script_setup_true_lang.js +102 -101
  251. package/dist/components/BbRadioGroup/types.d.ts +6 -2
  252. package/dist/components/BbRating/BbRating.vue_vue_type_script_setup_true_lang.js +63 -63
  253. package/dist/components/BbSelect/BbSelect.vue_vue_type_script_setup_true_lang.js +156 -154
  254. package/dist/components/BbSelect/types.d.ts +6 -2
  255. package/dist/components/BbSelectPopover/BbSelectPopover.vue_vue_type_script_setup_true_lang.js +2 -1
  256. package/dist/components/BbSelectPopover/types.d.ts +6 -2
  257. package/dist/components/BbSlider/BbSlider.vue_vue_type_script_setup_true_lang.js +153 -153
  258. package/dist/components/BbSwitch/BbSwitch.vue_vue_type_script_setup_true_lang.js +62 -62
  259. package/dist/components/BbSwitchGroup/BbSwitchGroup.vue_vue_type_script_setup_true_lang.js +131 -130
  260. package/dist/components/BbTable/BbTable.vue_vue_type_script_setup_true_lang.js +711 -676
  261. package/dist/components/BbTabs/BbTabs.vue_vue_type_script_setup_true_lang.js +1 -1
  262. package/dist/components/BbTabs/BbTabsList.vue_vue_type_script_setup_true_lang.js +1 -1
  263. package/dist/components/BbTabs/types.d.ts +25 -21
  264. package/dist/components/BbTag/BbTag.vue_vue_type_script_setup_true_lang.js +76 -76
  265. package/dist/components/BbTextInput/BbTextInput.vue_vue_type_script_setup_true_lang.js +58 -58
  266. package/dist/components/BbTextarea/BbTextarea.vue_vue_type_script_setup_true_lang.js +82 -82
  267. package/dist/components/BbTimePickerInput/BbTimePickerInput.vue_vue_type_script_setup_true_lang.js +246 -236
  268. package/dist/components/BbTooltip/BbTooltip.vue_vue_type_script_setup_true_lang.js +102 -97
  269. package/dist/components/BbTooltip/tooltipWarmup.d.ts +23 -0
  270. package/dist/components/BbTooltip/tooltipWarmup.js +7 -0
  271. package/dist/components/BbTooltip/types.d.ts +7 -2
  272. package/dist/components/BbTree/BbTree.vue_vue_type_script_setup_true_lang.js +29 -21
  273. package/dist/components/BbTree/BbTreeLevel.vue_vue_type_script_setup_true_lang.js +10 -7
  274. package/dist/components/CommonFieldInput/CommonFieldInput.vue_vue_type_script_setup_true_lang.js +37 -36
  275. package/dist/components/CommonTimeSelector/CommonTimeSelector.vue_vue_type_script_setup_true_lang.js +9 -9
  276. package/dist/composables/formSubmitLock.d.ts +6 -0
  277. package/dist/composables/formSubmitLock.js +4 -0
  278. package/dist/composables/useBaseOptions.d.ts +7 -1
  279. package/dist/composables/useBaseOptions.js +32 -32
  280. package/dist/composables/useBbDropdownContext.d.ts +8 -8
  281. package/dist/composables/useBbFormField.d.ts +9 -0
  282. package/dist/composables/useBbFormField.js +5 -3
  283. package/dist/composables/useBbTabsContext.d.ts +10 -10
  284. package/dist/composables/useBbTabsContext.js +18 -18
  285. package/dist/composables/useFormBinding.d.ts +11 -0
  286. package/dist/composables/useFormBinding.js +15 -13
  287. package/dist/composables/useItemText.d.ts +5 -1
  288. package/dist/composables/useItemText.js +8 -3
  289. package/dist/composables/useItemValue.d.ts +5 -1
  290. package/dist/composables/useItemValue.js +8 -3
  291. package/dist/composables/useLocale.js +10 -9
  292. package/dist/deprecation/ai-deprecations.json.d.ts +130 -0
  293. package/dist/deprecation/ai-deprecations.json.js +1 -1
  294. package/dist/deprecation/removedProps.js +1 -1
  295. package/dist/directives/bbDropdown.js +1 -1
  296. package/dist/i18n/index.d.ts +7 -12
  297. package/dist/i18n/locales/cs.json +11 -14
  298. package/dist/i18n/locales/da.json +13 -16
  299. package/dist/i18n/locales/de-CH.json +137 -0
  300. package/dist/i18n/locales/de.json +14 -17
  301. package/dist/i18n/locales/el.json +10 -13
  302. package/dist/i18n/locales/en-GB.json +137 -0
  303. package/dist/i18n/locales/en.json +8 -11
  304. package/dist/i18n/locales/es-MX.json +137 -0
  305. package/dist/i18n/locales/es.json +16 -19
  306. package/dist/i18n/locales/fi.json +8 -11
  307. package/dist/i18n/locales/fr.json +23 -26
  308. package/dist/i18n/locales/hu.json +8 -11
  309. package/dist/i18n/locales/it.json +12 -15
  310. package/dist/i18n/locales/ja.json +13 -16
  311. package/dist/i18n/locales/ko.json +10 -13
  312. package/dist/i18n/locales/nb.json +13 -16
  313. package/dist/i18n/locales/nl.json +21 -24
  314. package/dist/i18n/locales/pl.json +10 -13
  315. package/dist/i18n/locales/{pt.json → pt-BR.json} +19 -22
  316. package/dist/i18n/locales/pt-PT.json +137 -0
  317. package/dist/i18n/locales/ro.json +22 -25
  318. package/dist/i18n/locales/ru.json +11 -14
  319. package/dist/i18n/locales/sv.json +16 -19
  320. package/dist/i18n/locales/tr.json +14 -17
  321. package/dist/i18n/locales/uk.json +11 -14
  322. package/dist/i18n/locales/{zh-cn.json → zh-CN.json} +10 -13
  323. package/dist/i18n/locales/zh-HK.json +137 -0
  324. package/dist/i18n/locales/zh-TW.json +137 -0
  325. package/dist/i18n/regionHints.d.ts +16 -0
  326. package/dist/i18n/regionHints.js +49 -0
  327. package/dist/i18n/regions.d.ts +286 -0
  328. package/dist/i18n/regions.js +265 -0
  329. package/dist/index.d.ts +1 -1
  330. package/dist/index.js +4 -4
  331. package/dist/llms-full.txt +1785 -1637
  332. package/dist/llms-medium.txt +74 -46
  333. package/dist/llms.txt +7 -7
  334. package/dist/locale-blueprint.json +16 -13
  335. package/dist/styles.css +2 -2
  336. package/dist/types/ptComponentMap.d.ts +1 -1
  337. package/dist/utilities/functions/slotKey.d.ts +2 -2
  338. package/dist/utils/versionCheck.js +1 -1
  339. package/dist/vite-plugin.d.ts +22 -19
  340. package/dist/vite.js +309 -297
  341. package/llms.txt +7 -7
  342. package/package.json +5 -3
  343. package/scripts/lib/agent-manifest.mjs +2 -1
  344. package/scripts/lib/eslint-disable.mjs +12 -4
  345. package/scripts/lib/eslint-plugin.d.ts +5 -1
  346. package/scripts/lib/eslint-plugin.mjs +187 -6
  347. package/scripts/lib/helper-canon.mjs +176 -0
  348. package/scripts/lib/helpers-add.mjs +1303 -0
  349. package/scripts/lib/local-components.mjs +33 -4
  350. package/scripts/lib/locale-check.mjs +165 -0
  351. package/scripts/lib/redundant-item-accessor.mjs +398 -0
  352. package/scripts/lib/renamed-item-field.mjs +343 -0
  353. package/scripts/lib/slot-key.mjs +2 -2
  354. package/scripts/lib/slot-renames.mjs +1 -1
  355. package/scripts/lib/validate-bb-markup.mjs +123 -56
  356. package/dist/i18n/index.js +0 -27
package/README.md CHANGED
@@ -327,13 +327,13 @@ part you need.
327
327
 
328
328
  ### CLI commands
329
329
 
330
- | Command | What it does |
331
- | ------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
332
- | `npx bitboss-ui ai-init [--update] [--no-mcp]` | Writes the agent pointer files and registers the MCP server (installs its optional peers). |
333
- | `npx bitboss-ui check [paths… \| --changed] [--fix] [--json]` | Validates `Bb*` markup in `.vue` / `.md` files against the installed version; `--fix` applies the v2 → v3 renames first; `--changed` checks only the files git sees changed vs HEAD (plus untracked). |
334
- | `npx bitboss-ui changelog --since <version> [--until <version>] [--json]` | Lists the **breaking** changes between the version you are on and the installed one — what breaks if you bump. |
335
- | `npx bitboss-ui mcp` | Starts the MCP server on stdio (harnesses launch it for you after `ai-init`). |
336
- | `npx bitboss-ui --help` | Every command and flag. |
330
+ | Command | What it does |
331
+ | ------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
332
+ | `npx bitboss-ui ai-init [--update] [--no-mcp]` | Writes the agent pointer files and registers the MCP server (installs its optional peers). |
333
+ | `npx bitboss-ui check [paths… \| --changed] [--fix] [--json]` | Validates `Bb*` markup in `.vue` / `.md` files against the installed version; `--fix` applies the library's renames first (v2 → v3, and between 3.0 betas); `--changed` checks only the files git sees changed vs HEAD (plus untracked). |
334
+ | `npx bitboss-ui changelog --since <version> [--until <version>] [--json]` | Lists the **breaking** changes between the version you are on and the installed one — what breaks if you bump. |
335
+ | `npx bitboss-ui mcp` | Starts the MCP server on stdio (harnesses launch it for you after `ai-init`). |
336
+ | `npx bitboss-ui --help` | Every command and flag. |
337
337
 
338
338
  ### ESLint plugin
339
339
 
@@ -533,6 +533,23 @@ const draft = reactive({ name: '' });
533
533
 
534
534
  `bitboss-ui check` reports the same as `form-v-model`.
535
535
 
536
+ #### Item fields: `no-renamed-item-field` and `no-redundant-item-accessor`
537
+
538
+ Dropdown, tab and breadcrumb items take `value` and `label` (dropdown groups:
539
+ `id`). `bitboss-ui/no-renamed-item-field` (error) rewrites an item literal still
540
+ spelled the old way: `{ key: 'edit', text: 'Edit' }` → `{ value: 'edit', label:
541
+ 'Edit' }` on a `BbDropdown` / `BbDropdownButton` row or a crumb, a tab's `key` →
542
+ `value`, a dropdown group's `key` → `id`.
543
+
544
+ Object items are read by their own `label` (else `text`) and `value`, so an
545
+ accessor naming those fields restates the default.
546
+ `bitboss-ui/no-redundant-item-accessor` (warn) deletes it: `item-text="label"`,
547
+ `item-value="value"`, and `item-text="text"` when no item has a `label`. It only
548
+ reports what removing cannot change.
549
+
550
+ `bitboss-ui check` reports the same as `renamed-item-field` and
551
+ `redundant-item-accessor`.
552
+
536
553
  #### Rating star colours: `no-star-color`
537
554
 
538
555
  `bitboss-ui/no-star-color` flags any colour utility in `BbRating`'s `pt:item`,
@@ -2852,7 +2852,7 @@ const SERVER_INSTRUCTIONS = [
2852
2852
  '- Which component: search_components (empty query = the whole catalog). One component: get_component({ name }), one line per member; members: [names] for whole rows, sections for prose.',
2853
2853
  '- A type in a props table (BbTableColumn, ButtonVariantType): get_component({ name }) returns its definition and values.',
2854
2854
  '- After writing markup: validate. Before custom CSS: list_tokens.',
2855
- '- An old name (v2 or earlier-beta prop, slot, pt key, class) that stopped working: search_docs(the old name). What a bump breaks: list_changes({ since: <your version> }), one line per change.',
2855
+ '- An old name (v2 or earlier-beta prop, slot, item field, pt key, class) that stopped working: search_docs(the old name). What a bump breaks: list_changes({ since: <your version> }), one line per change.',
2856
2856
  "- pt in <script> (a const, a wrapper's prop): type it <Name>Props['pt']; Pt* types are not exported.",
2857
2857
  '- Composables: get_composable. Whole pages: list_recipes, get_recipe (prose + files). Long docs answer with an outline: pass sections.',
2858
2858
  ].join('\n');
@@ -3018,9 +3018,21 @@ function buildServer() {
3018
3018
  .optional()
3019
3019
  .describe("Only this component's breaks, e.g. 'BbSelect'."),
3020
3020
  surface: z
3021
- .enum(['prop', 'slot', 'pt', 'cssVar', 'class', 'option', 'method'])
3021
+ .enum([
3022
+ 'prop',
3023
+ 'slot',
3024
+ 'pt',
3025
+ 'cssVar',
3026
+ 'class',
3027
+ 'option',
3028
+ 'method',
3029
+ 'event',
3030
+ 'item',
3031
+ ])
3022
3032
  .optional()
3023
- .describe('Only renames of this surface.'),
3033
+ .describe(
3034
+ 'Only renames of this surface (`item` = a field of an `items` entry, e.g. a dropdown row `key` → `value`).'
3035
+ ),
3024
3036
  kind: z
3025
3037
  .enum(['rename', 'behaviour'])
3026
3038
  .optional()
@@ -37,6 +37,9 @@
37
37
  * it may never have been one anywhere. `printFindingLegend` says
38
38
  * so in the output, because two migrating fleets each spent real
39
39
  * time discovering it the hard way.
40
+ * add Copy Inertia helpers into the app as files it owns
41
+ * (scripts/lib/helpers-add.mjs); `helpers list|diff|update`
42
+ * reports on them and refreshes the ones the app has not edited.
40
43
  * changelog Breaking changes between two releases — `--since <version>`
41
44
  * answers "what breaks if I bump", without MCP. Reads the
42
45
  * installed `dist/ai/changelog.json`.
@@ -93,6 +96,7 @@ import {
93
96
  HAND_IMPORTED_STYLES_EXTENSIONS,
94
97
  handImportedStylesFindings,
95
98
  } from '../scripts/lib/hand-imported-styles.mjs';
99
+ import { unknownLocaleFindings } from '../scripts/lib/locale-check.mjs';
96
100
  import { syncProjectVariantDts } from '../scripts/lib/project-variant-dts.mjs';
97
101
  import { refuseLinkedTarget } from '../scripts/lib/linked-target.mjs';
98
102
  import {
@@ -148,7 +152,7 @@ function coreRules(version) {
148
152
  3. **Prefer \`Bb*\` consumer components**; never use entries marked "Reference Only - Internal" unless the user explicitly asks for internals. (\`BbBaseButton\` and the \`BbBase*Icon\` glyphs are consumer API; the \`Common*\` building blocks are not.)
149
153
  4. **Never invent prop/event/slot names** — open \`${KNOWLEDGE_BASE}/<ComponentName>.md\` (Usage & Guidelines first) or its API file \`${KNOWLEDGE_BASE}/manifest/components/<ComponentName>.json\` (one member per line; the list is \`${KNOWLEDGE_BASE}/manifest/index.json\`). Never read \`components.json\` whole: it is the 1.2 MB file the tools use.
150
154
  5. **Icons**: discover names first; never invent them (\`${KNOWLEDGE_BASE}/guides/icons-policy.md\`).
151
- 6. **Item-driven components**: declarative \`items\` / \`item-text\` / \`item-value\`, \`dependencies\`, \`enforce-coherence\` — no manual watchers for coherence.
155
+ 6. **Item-driven components**: declarative \`items\` (an object row reads its own \`label\` and \`value\`; \`item-text\` / \`item-value\` only for other field names, never to restate those two), \`dependencies\`, \`enforce-coherence\` — no manual watchers for coherence.
152
156
  7. **Whole pages**: one recipe under \`${KNOWLEDGE_BASE}/recipes/{vue|nuxt|inertia}/\` (see the router table).
153
157
  8. **CSS near components**: \`${KNOWLEDGE_BASE}/guides/design-language.md\`. Paint as data is \`${KNOWLEDGE_BASE}/design-tokens.json\` and \`design-tokens.manifest.yaml\` (DESIGN.md-shaped). Grep \`--bb-*\`, not \`--color-*\` or \`--radius-*\`. A repo-root DESIGN.md is not this library. Two token tiers, and reaching for the wrong one is why apps end up re-skinning by class: \`--bb-*\` is the small GLOBAL theme tier (brand knobs, no numeric ramp — there is no \`--bb-primary-800\`), while each component declares its own **unprefixed** \`--*\` tokens for its look (\`.bb-table { --cell-h: 32px }\`). A missing \`--bb-*\` name is not a gap in the library — it means the knob you want is a component token. Set it on the element that DECLARES it (grep \`${KNOWLEDGE_BASE}/source/<ComponentName>.md\`); a value set further out is masked, not inherited. Prefer tokens, variants and \`pt\`; CSS on \`.bb-*__*\` internals is allowed for fine-tuning but unsupported: it can break on upgrade. \`.bb-common-*\` / \`.bb-field*\` internals: expect it to break. (\`.bb-base-button\` and the three \`.bb-base-*-icon\` glyph classes are consumer API — a supported hook, not an internal.) An override on an internal is a signal to check for a \`pt\` part or request one. A Tailwind utility on a \`Bb*\` component that does nothing is rule 9, not a library bug. One primary action per view region.
154
158
  9. **Tailwind v4 app: turn on cascade layers when you set bitboss-ui up**, not later when a class "doesn't work". In the build plugin: \`import { bitbossUi, TAILWIND_V4_LAYERS } from 'bitboss-ui/vite'\` and \`bitbossUi({ cssLayers: TAILWIND_V4_LAYERS })\` (Nuxt: \`bitboss: { cssLayers: TAILWIND_V4_LAYERS }\`, same import). Tailwind v4 emits layered CSS; without this the library's CSS is unlayered and beats every utility you put on a \`Bb*\` component or a \`pt:*\` part, whatever the specificity. With it, your utilities win. You still need the runtime plugin (\`app.use(bitbossUiPlugin)\`; Nuxt does it for you): it is what injects the sheet, into that layer. **Do not also \`@import 'bitboss-ui/styles.css'\`**: a hand import adds a second, unlayered copy and undoes the setting. Tailwind v3 or plain CSS: leave it unset. Details: \`${KNOWLEDGE_BASE}/guides/installation-and-plugin-setup.md\` § Cascade layers.
@@ -157,8 +161,9 @@ function coreRules(version) {
157
161
  12. **Never name your own components \`Bb…\`** — that prefix is bitboss-ui's. Use your app's prefix (\`App…\`, \`Acme…\`). \`check\` leaves an app's own \`Bb*\` component alone but warns: a future bitboss-ui component could take the name.
158
162
  13. **Set \`locale\` explicitly** in the build plugin (\`bitbossUi({ locale: 'it' })\` / nuxt \`bitboss: { locale: 'it' }\`) for any app that is not English: the built-in strings default to English (\`'en'\`, since 3.0.0-beta.41; it was \`'it'\`).
159
163
  14. **After writing bitboss-ui markup**, run \`npx bitboss-ui check\` — validates \`Bb*\` usage against the installed \`components.json\` and catches invented/removed props before review. In an edit loop, \`npx bitboss-ui check --changed\` checks only the files git sees changed; run the full check before you finish.
164
+ 15. **Inertia apps: install the app-side helpers with \`npx bitboss-ui add <name>\`** (\`useQueryObject\`, \`usePromiseForm\`, \`useTableContext\`, …; \`npx bitboss-ui helpers list\` names them). Never paste them from the guide. If \`add\` or \`helpers update\` refuses, stop and show the user its output and \`npx bitboss-ui helpers diff <name>\`; never edit \`bitboss-ui.lock.json\`, and never delete a helper file to get past a refusal.
160
165
 
161
- After upgrading bitboss-ui, re-run: \`npx bitboss-ui ai-init\``;
166
+ After upgrading bitboss-ui, re-run: \`npx bitboss-ui ai-init\` (Inertia apps: then \`npx bitboss-ui helpers update\`)`;
162
167
  }
163
168
 
164
169
  // A blank line after the start marker and before the end marker: an HTML
@@ -1147,6 +1152,16 @@ async function checkCommand(
1147
1152
  readText
1148
1153
  )
1149
1154
  );
1155
+ // A locale the library does not ship, in the build config and in
1156
+ // `setConfig({ locale })` (owner 2026-10-07: `en-UK` → `en-GB`).
1157
+ findings.push(
1158
+ ...unknownLocaleFindings(
1159
+ projectRoot,
1160
+ styleScan.map((path) => ({ path, relPath: relative(projectRoot, path) })),
1161
+ manifest,
1162
+ readText
1163
+ )
1164
+ );
1150
1165
  // Q46.5: `.bb-*` selectors in the app's stylesheets (the `.vue` `<style>`
1151
1166
  // blocks are read by the validator above).
1152
1167
  for (const path of styleScan) {
@@ -1340,6 +1355,37 @@ Commands:
1340
1355
  tsconfig unless it is already named (Nuxt: says where).
1341
1356
  \`--no-mcp\` skips the server and the install. Idempotent —
1342
1357
  safe to re-run after upgrades.
1358
+ add <id…> | --all [--dir <path>] [--dry-run] [--json]
1359
+ Copy Inertia helpers (\`helpers list\`; --all for every
1360
+ one) into the app as
1361
+ files it owns, with every file they import, and record
1362
+ them in bitboss-ui.lock.json. Creates missing files and
1363
+ adopts identical ones; never changes an existing file.
1364
+ Prints the install line for missing npm packages; never
1365
+ runs it. First run: --dir, else
1366
+ resources/js/composables/inertia-helpers (Laravel) or
1367
+ src/composables/inertia-helpers.
1368
+ helpers [list] [--json]
1369
+ Every helper id, what it does, its files and packages,
1370
+ and its state in this app.
1371
+ helpers diff [id…] [--json]
1372
+ The state of every installed helper file; with ids, the
1373
+ difference between your copy and this bitboss-ui's.
1374
+ Exit 1 when something differs. Comments never count as
1375
+ edits: a stale file's comments are replaced by update.
1376
+ helpers update [id…] [--dry-run] [--json]
1377
+ Replace helper files that hold an older bitboss-ui
1378
+ version (formatting does not matter); keep the files
1379
+ you edited; refuse a group of helpers where you edited a
1380
+ file bitboss-ui also changed. \`npm update bitboss-ui\`
1381
+ does not touch your copies: run this after upgrading.
1382
+ add/helpers exit codes: 0 done or nothing to do; 1 usage
1383
+ error or diff found a difference; 2 refused (add wrote
1384
+ nothing); 3 a precondition failed, nothing written; 4 a
1385
+ write failed and was rolled back. No --force: to take
1386
+ bitboss-ui's copy over your edit, delete the file and
1387
+ run add again. --yes is accepted and does nothing (the
1388
+ commands never prompt).
1343
1389
  check [glob…] [--changed] [--json] [--allow-empty] [--allow-component <Name>]
1344
1390
  [--no-hints] [--manifest <path>] [--fix]
1345
1391
  Validate \`Bb*\` markup in .vue/.md files against the
@@ -1372,8 +1418,8 @@ Commands:
1372
1418
  under \`--manifest\`.
1373
1419
 
1374
1420
  \`--fix\` first applies the ESLint plugin's fixes (the
1375
- registered v2→v3 renames, polarity flips and value
1376
- remaps) to the matched .vue files with ONLY the
1421
+ registered renames — v2→v3 and between 3.0 betas, item
1422
+ fields included — polarity flips and value remaps) to the matched .vue files with ONLY the
1377
1423
  bitboss-ui rules — your own ESLint config is not used —
1378
1424
  then reports what is left. Needs \`eslint\` and
1379
1425
  \`vue-eslint-parser\` in the project.
@@ -1430,9 +1476,18 @@ Commands:
1430
1476
  \`dist/\`), \`not-exported-type\` (a \`Pt*\` pt type
1431
1477
  imported from bitboss-ui: type pt through
1432
1478
  \`<Component>Props['pt']\` instead),
1433
- \`missing-key\` / \`duplicate-row-text\` (a
1434
- BbDropdown row or group that needs a \`key\`: selectable,
1435
- or identical keyless text in one group),
1479
+ \`missing-value\` / \`missing-id\` /
1480
+ \`duplicate-row-label\` (a BbDropdown row in a
1481
+ selectable group without a \`value\`, a selectable
1482
+ group without an \`id\`, or two value-less rows with
1483
+ the same \`label\` in one group; before
1484
+ 3.0.0-beta.49 \`missing-key\` / \`duplicate-row-text\`),
1485
+ \`renamed-item-field\` (a dropdown row \`key\` /
1486
+ \`text\`, a dropdown group \`key\`, a tab \`key\` or a
1487
+ crumb \`key\` / \`text\` in an inline or same-file
1488
+ items array: rows and crumbs take \`value\` /
1489
+ \`label\`, tabs \`value\`, groups \`id\`; \`--fix\`
1490
+ rewrites it),
1436
1491
  \`unknown-variant\` (a variant name from another
1437
1492
  library, e.g. \`danger\` on BbAlert / BbBadge; the
1438
1493
  message names ours),
@@ -1488,17 +1543,23 @@ Commands:
1488
1543
  \`--fix\` rewrites it), \`missing-partner-prop\`,
1489
1544
  \`partner-prop\`,
1490
1545
  \`validated-only-prop\`, \`object-items-without-text\`
1491
- (object \`items\` with no \`item-text\`; reads only
1546
+ (object \`items\` with neither a \`label\` nor a
1547
+ \`text\` field and no \`item-text\`; reads only
1492
1548
  an inline array, or a \`const\` array, \`ref([…])\` or
1493
1549
  \`reactive([…])\` in the same file's
1494
- \`<script setup>\`), \`reserved-key\` (a key
1495
- whose slot name is one of the component's own slots,
1496
- e.g. a BbTable column keyed \`actions\`; read from the
1497
- manifest, same-file keys only), \`hand-imported-styles\`
1550
+ \`<script setup>\`), \`reserved-key\` (a column
1551
+ \`key\` or item \`value\` whose slot name is one of
1552
+ the component's own slots, e.g. a BbTable column keyed
1553
+ \`actions\`; read from the manifest, same-file items
1554
+ only), \`hand-imported-styles\`
1498
1555
  (\`bitboss-ui/styles.css\` imported in CSS, a script or
1499
1556
  Nuxt's \`css\` while \`injectStyles\` is on: delete it;
1500
1557
  read only when vite.config / nuxt.config says so),
1501
- \`unknown-class\` (a selector on a \`.bb-*\` class the
1558
+ \`unknown-locale\` (a \`locale\` / \`enabledLocales\`
1559
+ literal in vite.config / nuxt.config, or a
1560
+ \`setConfig({ locale })\`, that bitboss-ui does not
1561
+ ship; \`suggestion\` is the nearest one: en-UK →
1562
+ en-GB), \`unknown-class\` (a selector on a \`.bb-*\` class the
1502
1563
  library does not render, in a stylesheet or a
1503
1564
  \`<style>\` block; \`suggestion\` is the nearest real
1504
1565
  one), \`renamed-class\` (a class the library renamed;
@@ -1666,6 +1727,47 @@ switch (command) {
1666
1727
  await main();
1667
1728
  break;
1668
1729
  }
1730
+ case 'add':
1731
+ case 'helpers': {
1732
+ const { values, positionals } = parseCommandArgs(
1733
+ command,
1734
+ commandArgs,
1735
+ {
1736
+ json: { type: 'boolean' },
1737
+ 'dry-run': { type: 'boolean' },
1738
+ yes: { type: 'boolean', short: 'y' },
1739
+ ...(command === 'add'
1740
+ ? { dir: { type: 'string' }, all: { type: 'boolean' } }
1741
+ : {}),
1742
+ },
1743
+ { allowPositionals: true }
1744
+ );
1745
+ const [sub, ...rest] =
1746
+ command === 'add' ? ['add', ...positionals] : positionals;
1747
+ const subcommand = command === 'add' ? 'add' : (sub ?? 'list');
1748
+ if (subcommand === 'list' && values['dry-run']) {
1749
+ console.error(
1750
+ '[bitboss-ui] helpers list: --dry-run applies to add and update'
1751
+ );
1752
+ process.exit(1);
1753
+ }
1754
+ const { runHelpers } = await import('../scripts/lib/helpers-add.mjs');
1755
+ const result = await runHelpers({
1756
+ command: subcommand,
1757
+ ids: command === 'add' ? positionals : rest,
1758
+ options: {
1759
+ dir: values.dir,
1760
+ dryRun: values['dry-run'] ?? false,
1761
+ all: values.all ?? false,
1762
+ },
1763
+ cwd: process.cwd(),
1764
+ packageRoot: PACKAGE_ROOT,
1765
+ });
1766
+ if (values.json) console.log(JSON.stringify(result.report));
1767
+ else (result.stderr ? console.error : console.log)(result.lines.join('\n'));
1768
+ process.exitCode = result.code;
1769
+ break;
1770
+ }
1669
1771
  case 'help':
1670
1772
  case '--help':
1671
1773
  case '-h':
@@ -257,7 +257,7 @@ const hiddenCount = computed(() => reviewers.length - maxVisible);
257
257
  }
258
258
 
259
259
  .stack :deep(.bb-avatar + .bb-avatar) {
260
- margin-left: -12px;
260
+ margin-inline-start: -12px;
261
261
  }
262
262
  </style>
263
263
  ```
@@ -36,9 +36,9 @@ use `BbPagination`. Show at most one breadcrumb trail per view.
36
36
 
37
37
  ### Build the trail from `items`
38
38
 
39
- Each item is `{ key, text }` plus a navigation target. `key` must be unique (it
40
- also becomes the crumb's named-slot name and the label fallback when `text` is
41
- missing). Navigation is always the item's job — give a crumb an `href` (or
39
+ Each item is `{ label, value }` plus a navigation target. `label` is the
40
+ crumb's text; `value` is optional and, when set, must be unique (it names the
41
+ crumb's own slots). Navigation is always the item's job — give a crumb an `href` (or
42
42
  `to`, or an `onClick`) and it renders as a real link; **never** wrap a crumb in
43
43
  your own click-to-route handler. Leave the **last** item without a target: a
44
44
  last crumb with no target is the current page, and the component marks it
@@ -51,10 +51,10 @@ it) never marks the parent current.
51
51
  ```vue
52
52
  <BbBreadcrumbs
53
53
  :items="[
54
- { key: 'dashboard', text: 'Dashboard', href: '#dashboard' },
55
- { key: 'billing', text: 'Billing', href: '#billing' },
56
- { key: 'invoices', text: 'Invoices', href: '#invoices' },
57
- { key: 'invoice', text: 'Invoice #1042' },
54
+ { value: 'dashboard', label: 'Dashboard', href: '#dashboard' },
55
+ { value: 'billing', label: 'Billing', href: '#billing' },
56
+ { value: 'invoices', label: 'Invoices', href: '#invoices' },
57
+ { value: 'invoice', label: 'Invoice #1042' },
58
58
  ]"
59
59
  />
60
60
  ```
@@ -124,20 +124,20 @@ import type { BbBreadcrumbsItem } from 'bitboss-ui';
124
124
  // crumb is a real link; the current page stays without a target.
125
125
  const trail: BbBreadcrumbsItem[] = [
126
126
  {
127
- key: 'settings',
128
- text: 'Settings',
127
+ value: 'settings',
128
+ label: 'Settings',
129
129
  href: '#settings',
130
130
  'prepend:icon': 'lucide:settings',
131
131
  },
132
132
  {
133
- key: 'team',
134
- text: 'Team',
133
+ value: 'team',
134
+ label: 'Team',
135
135
  href: '#team',
136
136
  'prepend:icon': 'lucide:users',
137
137
  },
138
138
  {
139
- key: 'members',
140
- text: 'Members',
139
+ value: 'members',
140
+ label: 'Members',
141
141
  'prepend:icon': 'lucide:user-round',
142
142
  },
143
143
  ];
@@ -164,7 +164,7 @@ other crumb goes into the menu and the current page stays, its label truncated
164
164
  with an ellipsis (the full text in a tooltip and to assistive tech). That is the
165
165
  floor: in a very narrow toolbar the trail reads `… / Quarterly rev…`. If that is
166
166
  too little, give the trail its own full-width row, or shorten the last label
167
- (`text` is yours).
167
+ (`label` is yours).
168
168
 
169
169
  **Overflow folds into an ellipsis menu**
170
170
 
@@ -172,12 +172,12 @@ too little, give the trail its own full-width row, or shorten the last label
172
172
  <div class="max-w-xs">
173
173
  <BbBreadcrumbs
174
174
  :items="[
175
- { key: 'workspace', text: 'Workspace', href: '#workspace' },
176
- { key: 'engineering', text: 'Engineering', href: '#engineering' },
177
- { key: 'frontend', text: 'Frontend', href: '#frontend' },
178
- { key: 'design-system', text: 'Design System', href: '#design-system' },
179
- { key: 'components', text: 'Components', href: '#components' },
180
- { key: 'breadcrumbs', text: 'Breadcrumbs' },
175
+ { value: 'workspace', label: 'Workspace', href: '#workspace' },
176
+ { value: 'engineering', label: 'Engineering', href: '#engineering' },
177
+ { value: 'frontend', label: 'Frontend', href: '#frontend' },
178
+ { value: 'design-system', label: 'Design System', href: '#design-system' },
179
+ { value: 'components', label: 'Components', href: '#components' },
180
+ { value: 'breadcrumbs', label: 'Breadcrumbs' },
181
181
  ]"
182
182
  />
183
183
  </div>
@@ -250,8 +250,8 @@ When slot (or icon) content adds width the estimator cannot see, set
250
250
  <BbBreadcrumbs
251
251
  :offset-width="96"
252
252
  :items="[
253
- { key: 'settings', text: 'Settings', href: '#settings' },
254
- { key: 'notifications', text: 'Notifications' },
253
+ { value: 'settings', label: 'Settings', href: '#settings' },
254
+ { value: 'notifications', label: 'Notifications' },
255
255
  ]"
256
256
  >
257
257
  <template #prepend>
@@ -260,7 +260,7 @@ When slot (or icon) content adds width the estimator cannot see, set
260
260
  <template #item:prepend="{ item }">
261
261
  <BbIcon
262
262
  class="mr-1"
263
- :icon="item.key === 'settings' ? 'lucide:settings' : 'lucide:bell'"
263
+ :icon="item.value === 'settings' ? 'lucide:settings' : 'lucide:bell'"
264
264
  size="14"
265
265
  />
266
266
  </template>
@@ -310,10 +310,10 @@ import type { BbBreadcrumbsItem } from 'bitboss-ui';
310
310
  // File-view header: trail says where you are; compact `append` actions act on
311
311
  // the file. Declare their width with `offset-width` so overflow stays honest.
312
312
  const items: BbBreadcrumbsItem[] = [
313
- { key: 'repo', text: 'acme-ui', href: '#repo' },
314
- { key: 'src', text: 'src', href: '#src' },
315
- { key: 'components', text: 'components', href: '#components' },
316
- { key: 'button', text: 'Button.tsx' },
313
+ { value: 'repo', label: 'acme-ui', href: '#repo' },
314
+ { value: 'src', label: 'src', href: '#src' },
315
+ { value: 'components', label: 'components', href: '#components' },
316
+ { value: 'button', label: 'Button.tsx' },
317
317
  ];
318
318
 
319
319
  const copied = ref(false);
@@ -330,17 +330,17 @@ const onCopyPath = () => {
330
330
 
331
331
  ### Own one crumb's label with its named slot
332
332
 
333
- Every item also gets a slot named after its `key`, replacing that crumb's
334
- default text (same scope as `item:prepend`). Use it when a single crumb needs
335
- richer content — a status dot on the current record, a badge on one level —
336
- while the rest of the trail stays plain. A crumb's `key` is optional unless
337
- it has a slot of its own — a keyless crumb renders with the generic `item:*`
338
- slots and its text, and its slot name is never derived from the text (a label
339
- changes with translation; a slot name must not). The slot name is the key through
333
+ Every item with a `value` also gets a slot named after it, replacing that
334
+ crumb's default label (same scope as `item:prepend`). Use it when a single crumb
335
+ needs richer content — a status dot on the current record, a badge on one level —
336
+ while the rest of the trail stays plain. A crumb's `value` is optional unless
337
+ it has a slot of its own — a crumb without one renders with the generic `item:*`
338
+ slots and its label, and its slot name is never derived from the label (a label
339
+ changes with translation; a slot name must not). The slot name is the value through
340
340
  `slotKey`, which is kebab-case — `'Order History'` → `#order-history`,
341
341
  `'orderHistory'` → `#order-history`, `'order_history'` → `#order-history`; for
342
- a key with accents or other scripts write `#[slotKey('Qualità')]` (`import {
343
- slotKey } from 'bitboss-ui'`). Because keys become slot names, a key spelled
342
+ a value with accents or other scripts write `#[slotKey('Qualità')]` (`import {
343
+ slotKey } from 'bitboss-ui'`). Because values become slot names, a value spelled
344
344
  like a reserved slot (`prepend`, `append`, `divider`, `ellipsis`, `item`) is an
345
345
  error: `bitboss-ui check` flags it when `items` is in the same file.
346
346
 
@@ -349,16 +349,16 @@ error: `bitboss-ui check` flags it when `items` is in the same file.
349
349
  ```vue
350
350
  <BbBreadcrumbs
351
351
  :items="[
352
- { key: 'deployments', text: 'Deployments', href: '#deployments' },
353
- { key: 'release', text: 'v2.4.0' },
352
+ { value: 'deployments', label: 'Deployments', href: '#deployments' },
353
+ { value: 'release', label: 'v2.4.0' },
354
354
  ]"
355
355
  >
356
- <template #release="{ text }">
356
+ <template #release="{ label }">
357
357
  <span class="inline-flex items-center gap-1.5">
358
358
  <span
359
359
  class="size-2 rounded-full bg-(--bb-primary)"
360
360
  ></span>
361
- {{ text }}
361
+ {{ label }}
362
362
  </span>
363
363
  </template>
364
364
  </BbBreadcrumbs>
@@ -380,10 +380,10 @@ wider than `…`, pair it with `ellipsis-width`.
380
380
  <BbBreadcrumbs
381
381
  :ellipsis-width="40"
382
382
  :items="[
383
- { key: 'library', text: 'Library', href: '#library' },
384
- { key: 'photos', text: 'Photos', href: '#photos' },
385
- { key: 'albums', text: 'Albums', href: '#albums' },
386
- { key: 'summer', text: 'Summer 2026' },
383
+ { value: 'library', label: 'Library', href: '#library' },
384
+ { value: 'photos', label: 'Photos', href: '#photos' },
385
+ { value: 'albums', label: 'Albums', href: '#albums' },
386
+ { value: 'summer', label: 'Summer 2026' },
387
387
  ]"
388
388
  >
389
389
  <template #divider>
@@ -482,8 +482,8 @@ const items = computed<BbBreadcrumbsItem[]>(() =>
482
482
  path.value.map((name, index) => {
483
483
  const isCurrent = index === path.value.length - 1;
484
484
  return {
485
- key: `${index}-${name}`,
486
- text: name,
485
+ value: `${index}-${name}`,
486
+ label: name,
487
487
  'prepend:icon': 'lucide:folder',
488
488
  ...(isCurrent
489
489
  ? {}
@@ -507,9 +507,9 @@ active-class props are wired for you:
507
507
  ```vue
508
508
  <BbBreadcrumbs
509
509
  :items="[
510
- { key: 'home', text: 'Home', to: { name: 'index' } },
511
- { key: 'team', text: 'Team', to: '/team' },
512
- { key: 'member', text: 'Ada Lovelace' },
510
+ { value: 'home', label: 'Home', to: { name: 'index' } },
511
+ { value: 'team', label: 'Team', to: '/team' },
512
+ { value: 'member', label: 'Ada Lovelace' },
513
513
  ]"
514
514
  />
515
515
  ```
@@ -521,9 +521,9 @@ visit:
521
521
  ```vue
522
522
  <BbBreadcrumbs
523
523
  :items="[
524
- { key: 'dashboard', text: 'Dashboard', href: '/dashboard' },
525
- { key: 'orders', text: 'Orders', href: '/orders', preserveScroll: true },
526
- { key: 'order', text: 'Order #8842' },
524
+ { value: 'dashboard', label: 'Dashboard', href: '/dashboard' },
525
+ { value: 'orders', label: 'Orders', href: '/orders', preserveScroll: true },
526
+ { value: 'order', label: 'Order #8842' },
527
527
  ]"
528
528
  />
529
529
  ```
@@ -597,20 +597,20 @@ import type { BbBreadcrumbsItem } from 'bitboss-ui';
597
597
 
598
598
  const trail: BbBreadcrumbsItem[] = [
599
599
  {
600
- key: 'settings',
601
- text: 'Settings',
600
+ value: 'settings',
601
+ label: 'Settings',
602
602
  href: '#settings',
603
603
  'prepend:icon': 'lucide:settings',
604
604
  },
605
605
  {
606
- key: 'team',
607
- text: 'Team',
606
+ value: 'team',
607
+ label: 'Team',
608
608
  href: '#team',
609
609
  'prepend:icon': 'lucide:users',
610
610
  },
611
611
  {
612
- key: 'members',
613
- text: 'Members',
612
+ value: 'members',
613
+ label: 'Members',
614
614
  'prepend:icon': 'lucide:user-round',
615
615
  },
616
616
  ];
@@ -682,7 +682,7 @@ A `pt` value written in `<script>` (a constant, a preset, a wrapper's
682
682
  when its URL is the page you are on. Do not link the page the user is
683
683
  already on.
684
684
  - The overflow button is a real `button` with a localized, count-aware label
685
- ("Show N hidden breadcrumbs"); its menu is a `BbDropdown` with full keyboard
685
+ ("Show hidden breadcrumbs (N)"); its menu is a `BbDropdown` with full keyboard
686
686
  support — nothing to add on your side.
687
687
  - The dividers are decorative (`aria-hidden`); never encode meaning in them.
688
688
  - `disabled` on the component (or an item) removes `href` and exposes
@@ -728,12 +728,12 @@ States are listed in precedence order: when two are on at once and their entries
728
728
  - `append` — scope: `BbBreadcrumbsEdgeSlotProps` `{ disabled?: boolean }` — Content rendered after the breadcrumb list, in a dedicated append region.
729
729
  - `divider` — scope: `Record<string, never>` — Replaces the default separator rendered between breadcrumb items.
730
730
  - `ellipsis` — scope: `BbBreadcrumbsEllipsisSlotProps` `{ props: { ref: (reference: unknown) => void; }; disabled?: boolean; overflowCount: number; ellipsisWidth: number }` — Replaces the default `…` overflow button shown when items overflow.
731
- - `item:append` — scope: `BbBreadcrumbsItemSlotProps` `{ disabled: boolean; index: number; item: Item; text?: string }` — Content rendered after **every** breadcrumb item's link/button. Generic fallback below a per-item `<key>:append` slot and above the item's `append:icon`.
732
- - `item:prepend` — scope: `BbBreadcrumbsItemSlotProps` `{ disabled: boolean; index: number; item: Item; text?: string }` — Content rendered before **every** breadcrumb item's link/button, in the leading edge region. Generic fallback: a per-item `<key>:prepend` slot takes precedence, and the item's `prepend:icon` is used when neither slot is present.
731
+ - `item:append` — scope: `BbBreadcrumbsItemSlotProps` `{ disabled: boolean; index: number; item: Item; label?: string }` — Content rendered after **every** breadcrumb item's link/button. Generic fallback below a per-item `<value>:append` slot and above the item's `append:icon`.
732
+ - `item:prepend` — scope: `BbBreadcrumbsItemSlotProps` `{ disabled: boolean; index: number; item: Item; label?: string }` — Content rendered before **every** breadcrumb item's link/button, in the leading edge region. Generic fallback: a per-item `<value>:prepend` slot takes precedence, and the item's `prepend:icon` is used when neither slot is present.
733
733
  - `prepend` — scope: `BbBreadcrumbsEdgeSlotProps` `{ disabled?: boolean }` — Content rendered before the breadcrumb list, in a dedicated prepend region.
734
- - `#<key>` (named from data) — scope: `BbBreadcrumbsItemSlotProps` — One crumb's label, by its `key` through `slotKey`; falls back to `item.text`. A crumb folded into the overflow menu follows BbDropdown's slot rules instead. Reserved keys (their slot is one of this component's own, so a key spelled like them is an error): `append`, `divider`, `ellipsis`, `item`, `prepend`.
735
- - `#<key>:prepend` (named from data) — scope: `BbBreadcrumbsItemSlotProps` — The glyph before one crumb's label; beats `item:prepend`, which beats its `prepend:icon`.
736
- - `#<key>:append` (named from data) — scope: `BbBreadcrumbsItemSlotProps` — The glyph after one crumb's label; beats `item:append`, which beats its `append:icon`.
734
+ - `#<value>` (named from data) — scope: `BbBreadcrumbsItemSlotProps` — One crumb's label, by its `value` through `slotKey`; falls back to `item.label`. A crumb folded into the overflow menu follows BbDropdown's slot rules instead (the same `#<value>` names). Reserved names (their slot is one of this component's own, so an item value or column key spelled like them is an error): `append`, `divider`, `ellipsis`, `item`, `prepend`.
735
+ - `#<value>:prepend` (named from data) — scope: `BbBreadcrumbsItemSlotProps` — The glyph before one crumb's label; beats `item:prepend`, which beats its `prepend:icon`.
736
+ - `#<value>:append` (named from data) — scope: `BbBreadcrumbsItemSlotProps` — The glyph after one crumb's label; beats `item:append`, which beats its `append:icon`.
737
737
 
738
738
  ## Component tree
739
739
 
@@ -747,7 +747,7 @@ States are listed in precedence order: when two are on at once and their entries
747
747
  - `BbBreadcrumbs` _(this component)_ — its own template binds: `item` → `li.bb-breadcrumbs__item`, `icon` → `BbIcon`, `text` → `span.bb-breadcrumbs__text`
748
748
  - `BbBaseButton` _(public — [contract](./BbBaseButton.md))_ — its own pt parts (`BbBaseButton`): `root` → `RouterComponent`, `root` → `a`, `root` → `component`; also mounts `RouterComponent`
749
749
  - `BbDropdown` _(public — [contract](./BbDropdown.md))_ — its own pt parts (`BbDropdown`): `panel` → `CommonPopover`, `root` → `CommonPopover`, `header` → `div.bb-dropdown__header`, `list` → `span.bb-dropdown__list`, `footer` → `div.bb-dropdown__footer`; documented CSS variables: `--menu-inset`; also mounts `CommonPopover`, `DropdownPipelineResolver`
750
- - `BbDropdownList` _(internal — not importable, reach it through `BbDropdown`)_ — also mounts `BbBaseButton`, `BbIcon`, `ErrorIcon`, `CommonPopover`, `BbDropdownList`
750
+ - `BbDropdownList` _(internal — not importable, reach it through `BbDropdown`)_ — also mounts `BbIcon`, `ErrorIcon`, `CommonPopover`, `BbDropdownList`
751
751
  - `BbBadge` _(public — [contract](./BbBadge.md))_ — its own pt parts (`BbBadge`): `spinner` → `BbSpinner`, `icon` → `BbIcon`, `clear` → `button.bb-badge__clear`; documented CSS variables: `--bg`, `--fg`, `--bw`, `--ring-color`, `--ring-size`, `--min-size-md`, `--min-size`, `--elev`, `--r`, `--fs`, `--icon-size`, `--gap`, `--px`, `--clear-size`, `--bg-disabled`, `--fg-disabled`, `--border-disabled`, `--pad-left`; also mounts `BbIcon`, `BbSpinner`, `BadgeBodyContent`
752
752
  - `AdaptiveDropdown` _(internal — not importable, reach it through `BbDropdown`)_ — hands `BbOffCanvas` the pt map `{ header: 'header', footer: 'footer', panel: 'root', sheet: 'root' }` (ours → theirs); also mounts `BbSmoothHeight`, `BbDropdownList`
753
753
  - `BbOffCanvas` _(public — [contract](./BbOffCanvas.md))_ — its own pt parts (`BbOffCanvas`): `header` → `div.bb-offcanvas__header`, `title` → `span.bb-offcanvas__title`, `description` → `p.bb-offcanvas__description`, `close` → `CloseButton`, `content` → `div.bb-offcanvas__content`, `footer` → `div.bb-offcanvas__footer`; documented CSS variables: `--stack-x`, `--stack-fill`, `--stack-transition-duration`, `--px`, `--handle-w`, `--handle-h`, `--handle-bg`, `--safe-top`, `--close-size`
@@ -410,9 +410,15 @@ live example below uses this shape). The mistake above only becomes possible
410
410
  once that loop is unrolled into separate elements with their own literal
411
411
  strings.
412
412
 
413
- Add `group` to fuse adjacent buttons into one visual segment control. It is
414
- purely visual (shared borders/radius between siblings) — each button keeps its
415
- own semantics, and there is no arrow-key roving between them.
413
+ Add `group` to fuse adjacent buttons into one visual segment control (shared
414
+ borders and radius between siblings). Each button keeps its own semantics: a
415
+ toggle still announces as a toggle button with its pressed state. Adjacent
416
+ `group` **toggles** are also one Tab stop: Tab lands on the pressed button (or
417
+ the one last focused, or the first), ArrowLeft / ArrowRight move between the
418
+ buttons (mirrored under `dir="rtl"`, wrapping at the ends), Home / End jump to
419
+ the first / last, and Space / Enter toggle. Disabled and loading buttons are
420
+ skipped. Any other element between two buttons splits them into two sets, and
421
+ `group` buttons without a `v-model` keep one Tab stop each.
416
422
 
417
423
  **Exclusive toggle groups**
418
424
 
@@ -1051,7 +1057,10 @@ Gotchas (real behavior, verified against source):
1051
1057
  attribute and drops yours. A hand-rolled toggle (`:aria-pressed` plus a
1052
1058
  `variant` swap) therefore looks right and is invisible to assistive tech.
1053
1059
  Use `v-model` — see [Toggle buttons](#toggle-buttons). Dev builds warn.
1054
- - `group` fuses looks only; it adds no radio semantics or arrow-key navigation.
1060
+ - `group` adds no radio semantics: an exclusive set is still toggle buttons
1061
+ with `aria-pressed`. Adjacent `group` toggles share one Tab stop and move
1062
+ with the arrow keys (see [Toggle buttons](#toggle-buttons)); keep a set's
1063
+ buttons side by side in one parent, since anything between them splits it.
1055
1064
  - Responsive `size` maps change height/font/gap per breakpoint; padding, icon
1056
1065
  size and radius follow the `default` entry.
1057
1066
  - Auto-loading tracks the promise **returned** from `@click`; a handler that
@@ -1080,6 +1089,8 @@ Anti-patterns:
1080
1089
  report one as an error.
1081
1090
  - Toggles expose `aria-pressed` (`true`/`false`) automatically — never add your
1082
1091
  own.
1092
+ - A set of adjacent `group` toggles is one Tab stop (roving `tabindex`), with
1093
+ ArrowLeft / ArrowRight / Home / End inside it — the APG toolbar pattern.
1083
1094
  - While loading: `aria-disabled="true"`, `tabindex="-1"`, and a localized
1084
1095
  visually-hidden loading announcement.
1085
1096
  - Disabled links render with `role="link"`, `aria-disabled="true"`, no `href`,
@@ -1115,7 +1126,7 @@ Anti-patterns:
1115
1126
  | `except` | `string[] \| undefined` | | | Inertia: the inverse of `only` — properties to EXCLUDE from a partial reload. Pass one or the other, not both. |
1116
1127
  | `external` | `boolean \| undefined` | `false` | | Forces an `href` link to render as a plain `<a>` (native navigation), bypassing Inertia/router interception — same intent as Nuxt's `external`. A native-anchor signal alongside `target` and `download`. |
1117
1128
  | `falseValue` | `any` | `false` | | Value emitted when the toggle is deactivated. |
1118
- | `group` | `boolean \| undefined` | `false` | | Identifies the button as part of a button group. |
1129
+ | `group` | `boolean \| undefined` | `false` | | Identifies the button as part of a button group: adjacent `group` buttons fuse into one segment (shared borders and radius). Adjacent `group` toggles (each with a `v-model`) are also one Tab stop, with ArrowLeft / ArrowRight / Home / End moving between them. |
1119
1130
  | `headers` | `object \| undefined` | | | Additional HTTP headers forwarded to Inertia when navigating via `href` in an Inertia-enabled app. |
1120
1131
  | `href` | `string \| undefined` | | | Returns the hyperlink's URL. Can be set, to change the URL. |
1121
1132
  | `icon` | `string \| undefined` | | | Used when only an icon with no text should be displayed. |