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
@@ -6,10 +6,14 @@ summary: App-side toolkit for Laravel + Inertia apps — typed page props, lazy
6
6
  # Inertia Helpers
7
7
 
8
8
  A curated toolkit of composables for **Laravel + Inertia (Vue 3)** apps built
9
- on bitboss-ui. These are _app-side_ code: copy the ones you need into your
10
- project (conventionally `src/composables/`) — they are not exported by the
11
- `bitboss-ui` package. The [Inertia recipes](../recipes/inertia/records-workspace.md)
12
- assume this toolkit.
9
+ on bitboss-ui. These are _app-side_ code, not exported by the `bitboss-ui`
10
+ package: one folder, `inertia-helpers/`, that lives in your app
11
+ (`resources/js/composables/inertia-helpers/` in a Laravel app). Inside it the
12
+ files import each other by relative path (`./utils`, `./useQuery`), so the
13
+ folder works wherever it sits and never touches your own `@/utils` or
14
+ `@/types`. Pages import from it by path:
15
+ `import { useQuery } from '@/composables/inertia-helpers/useQuery'`. The
16
+ [Inertia recipes](../recipes/inertia/records-workspace.md) assume this toolkit.
13
17
 
14
18
  Why it exists: in Inertia there is no client data layer — data arrives as
15
19
  **page props** and changes through **visits**. These helpers give that model
@@ -18,14 +22,67 @@ filters live in the URL, paginated data and selection are shared through
18
22
  keyed contexts instead of prop drilling, and forms return promises that
19
23
  bitboss-ui buttons and dialogs can await.
20
24
 
21
- Copying this toolkit pulls in real npm dependencies beyond the app's own
22
- `@inertiajs/vue3`/`vue` — install them explicitly rather than relying on them
23
- already being hoisted transitively through `bitboss-ui`'s own `dependencies`
24
- (that works today by npm hoisting luck, and breaks under pnpm/Yarn PnP or the
25
- next time `bitboss-ui` changes what it depends on):
25
+ ## Install: `npx bitboss-ui add`
26
26
 
27
+ Install a helper with the CLI, from the app root. Never paste one from this
28
+ guide:
29
+
30
+ ```sh
31
+ npx bitboss-ui add useQueryObject useTableContext
32
+ npx bitboss-ui add --all # the whole toolkit
33
+ npx bitboss-ui helpers list # every id, what it does, its state here
27
34
  ```
28
- npm i @vueuse/core @vueuse/shared object-code query-string
35
+
36
+ `add` copies each named helper and every file it imports into
37
+ `resources/js/composables/inertia-helpers/` (`src/composables/inertia-helpers/`
38
+ outside a Laravel layout, or `--dir <path>` on the first run) and records them
39
+ in `bitboss-ui.lock.json` at the app root. Commit both the folder and the lock.
40
+ `add` never changes a file that already exists. It prints the import line for
41
+ each helper and the install command for any npm package the app lacks; it
42
+ never runs it. `--dry-run` shows the plan and writes nothing. The app must be
43
+ TypeScript with `moduleResolution: "bundler"`; JavaScript apps are refused.
44
+
45
+ The files are yours, so edit them freely:
46
+
47
+ - **Formatting never counts as an edit**, and neither do comments: your
48
+ formatter can reformat the folder, and nothing needs to be excluded from it.
49
+ Any code change does count, including one made by a linter's `--fix`.
50
+ - **`npm update bitboss-ui` does not change your copies.** After an upgrade
51
+ run `npx bitboss-ui helpers diff`, then `npx bitboss-ui helpers update`. It
52
+ replaces only the files that still hold an older bitboss-ui version and
53
+ keeps every file you edited.
54
+ - **Comments are not edits, so `helpers update` replaces a file whose only
55
+ change is a comment, and the comment is lost.** `helpers diff` and
56
+ `helpers update --dry-run` mark those files `your comments differ`; copy
57
+ any comment you want to keep before updating.
58
+ - If you edited a file that bitboss-ui also changed, `update` leaves that
59
+ group of helpers alone and says so; `npx bitboss-ui helpers diff <id>` shows
60
+ both sides. To take bitboss-ui's version over your edit, delete the file and
61
+ run `add` again. There is no `--force`.
62
+ - To uninstall a helper, delete its file and remove its id from `ids` in the
63
+ lock. Shared files (`utils.ts`, `types.ts`) stay while another helper uses
64
+ them.
65
+
66
+ Run the app's own copy of the CLI. `add` refuses to run as a bitboss-ui other
67
+ than the one in `node_modules` (npm's `latest` tag is still v2), and prints
68
+ the command to use instead (`npm exec -- bitboss-ui add …`,
69
+ `pnpm exec bitboss-ui add …`).
70
+
71
+ **Coming from hand-copied helpers** (an older version of this guide had you
72
+ paste them into `src/composables/` with `@/utils` imports): run `add` for the
73
+ helpers you use, switch your pages' imports to
74
+ `@/composables/inertia-helpers/<name>`, then delete the old copies once
75
+ nothing imports them. Your own `@/utils` and `@/types` stay yours. If the app
76
+ auto-imports `composables/**`, exclude one of the two trees until the old
77
+ copies are gone, or both export `useQuery`.
78
+
79
+ The helpers need these npm packages beyond the app's own
80
+ `@inertiajs/vue3`/`vue` (`add` prints the ones a helper needs). Install them
81
+ explicitly rather than relying on them being hoisted through `bitboss-ui`'s own
82
+ `dependencies`, which breaks under pnpm and Yarn PnP:
83
+
84
+ ```
85
+ npm i @vueuse/core object-code query-string
29
86
  npm i -D @inertiajs/core
30
87
  ```
31
88
 
@@ -33,17 +90,16 @@ npm i -D @inertiajs/core
33
90
  (`usePaginatedResponseContext`, `useTableSelectionContext`, `useTableContext`,
34
91
  `usePageShellContext`) and `useDeleteCmd`/`useScreenSizes`; `object-code`
35
92
  powers the `isEqual` hash-comparison utility below; `query-string` backs
36
- `useQuery`/`useRouteQuery`/`useQueryObject`; `@vueuse/shared` supplies
37
- `createSharedComposable` to `useScreenSizes`; `@inertiajs/core` is a type-only
93
+ `useQuery`/`useRouteQuery`/`useQueryObject`; `@inertiajs/core` is a type-only
38
94
  import (`PageProps` in `usePaginatedResponseContext`) that `@inertiajs/vue3`
39
- does not re-export, so a strict pnpm app fails to type-check without it. A few
40
- tiny utilities are assumed
41
- under `@/utils` and defined below.
95
+ does not re-export, so a strict pnpm app fails to type-check without it. The
96
+ helpers' shared types and tiny utilities are two files of the folder,
97
+ `types.ts` and `utils.ts`, below.
42
98
 
43
99
  ## Shared types and utilities
44
100
 
45
101
  ```ts
46
- // src/types/index.ts
102
+ // inertia-helpers/types.ts
47
103
  // the Laravel paginator shape and base page props
48
104
  export type PaginatedResponse<T> = {
49
105
  data: T[];
@@ -69,7 +125,7 @@ below before wiring a paginated prop — passing a raw paginator straight
69
125
  through leaves `meta` `undefined` and the composable silently reads zeros.
70
126
 
71
127
  ```ts
72
- // src/utils/index.ts
128
+ // inertia-helpers/utils.ts
73
129
  // micro-utilities the helpers share
74
130
  import { hash } from 'object-code';
75
131
 
@@ -113,7 +169,7 @@ again: a persistent layout or a store that keeps reading a prop the new page
113
169
  doesn't share still fails loudly, one tick later.
114
170
 
115
171
  ```ts
116
- // src/composables/useProp.ts
172
+ // inertia-helpers/useProp.ts
117
173
  import { usePage } from '@inertiajs/vue3';
118
174
  import { computed, nextTick, ref, type ComputedRef } from 'vue';
119
175
 
@@ -187,8 +243,8 @@ when the data lands. `loading`/`loaded`/`error` expose the fetch state;
187
243
  `execute()` forces the load imperatively.
188
244
 
189
245
  ```ts
190
- // src/composables/useLazyProp.ts
191
- import { isEqual, isNil, isNotNil } from '@/utils';
246
+ // inertia-helpers/useLazyProp.ts
247
+ import { isEqual, isNil, isNotNil } from './utils';
192
248
  import { router, usePage } from '@inertiajs/vue3';
193
249
  import type { Ref } from 'vue';
194
250
  import { customRef, onBeforeUnmount, readonly, ref, watch } from 'vue';
@@ -245,7 +301,7 @@ export function useLazyProp<T>(
245
301
  router.reload({
246
302
  only: [propName],
247
303
  replace: true,
248
- headers: options.headers,
304
+ ...(options.headers ? { headers: options.headers } : {}),
249
305
  onStart: () => {
250
306
  loading.value = true;
251
307
  },
@@ -352,12 +408,9 @@ loads on first demand (e.g. when the select opens) instead of inflating the
352
408
  initial page load.
353
409
 
354
410
  ```ts
355
- // src/composables/useLazyPropGetter.ts
356
- import {
357
- useLazyProp,
358
- type UseLazyPropOptions,
359
- } from '@/composables/useLazyProp';
360
- import { isNil } from '@/utils';
411
+ // inertia-helpers/useLazyPropGetter.ts
412
+ import { useLazyProp, type UseLazyPropOptions } from './useLazyProp';
413
+ import { isNil } from './utils';
361
414
  import type { Ref } from 'vue';
362
415
 
363
416
  export type UseLazyPropGetter<U> = {
@@ -438,7 +491,7 @@ Parses the current page URL's query string into an object. Snapshot, not
438
491
  reactive — used by the writers below.
439
492
 
440
493
  ```ts
441
- // src/composables/useQuery.ts
494
+ // inertia-helpers/useQuery.ts
442
495
  // requires: npm i query-string
443
496
  import { usePage } from '@inertiajs/vue3';
444
497
  import qs, { type StringifyOptions } from 'query-string';
@@ -478,7 +531,7 @@ server re-renders with the new value. Writing the current value is a no-op —
478
531
  safe to sync from server responses without visit loops.
479
532
 
480
533
  ```ts
481
- // src/composables/useRouteQuery.ts
534
+ // inertia-helpers/useRouteQuery.ts
482
535
  // requires: npm i query-string
483
536
  import { router, usePage } from '@inertiajs/vue3';
484
537
  import qs from 'query-string';
@@ -516,7 +569,7 @@ export function useRouteQuery<T = string>(
516
569
  const nextRaw = String(next);
517
570
  if (nextRaw === readRaw()) return;
518
571
 
519
- const [path, queryString = ''] = page.url.split('?');
572
+ const [path = '', queryString = ''] = page.url.split('?');
520
573
  const query = qs.parse(queryString);
521
574
  if (nextRaw === defaultValue) {
522
575
  delete query[key]; // keep URLs clean at the default
@@ -542,10 +595,10 @@ seen are cleaned up when they empty out; the `page` parameter resets on
542
595
  every filter change so results are never hidden on an out-of-range page.
543
596
 
544
597
  ```ts
545
- // src/composables/useQueryObject.ts
598
+ // inertia-helpers/useQueryObject.ts
546
599
  // requires: npm i query-string
547
- import { useQuery } from '@/composables/useQuery';
548
- import { isEmpty, isNil } from '@/utils';
600
+ import { useQuery } from './useQuery';
601
+ import { isEmpty, isNil } from './utils';
549
602
  import { router, usePage } from '@inertiajs/vue3';
550
603
  import qs, { type StringifyOptions } from 'query-string';
551
604
  import { toValue, watch, type MaybeRefOrGetter } from 'vue';
@@ -716,10 +769,10 @@ context: `items` (editable until next navigation), `totalItems`,
716
769
  visit the context re-syncs from the fresh prop.
717
770
 
718
771
  ```ts
719
- // src/composables/usePaginatedResponseContext.ts
720
- import { useRouteQuery } from '@/composables/useRouteQuery';
721
- import type { PaginatedResponse } from '@/types';
722
- import { isNotNil } from '@/utils';
772
+ // inertia-helpers/usePaginatedResponseContext.ts
773
+ import { useRouteQuery } from './useRouteQuery';
774
+ import type { PaginatedResponse } from './types';
775
+ import { isNotNil } from './utils';
723
776
  import type { PageProps } from '@inertiajs/core';
724
777
  import { router, usePage } from '@inertiajs/vue3';
725
778
  import { injectLocal, provideLocal } from '@vueuse/core';
@@ -755,7 +808,9 @@ export const usePaginatedResponseContext = <T = object>(
755
808
  // either way, augmented or not.
756
809
  const paginated = computed(
757
810
  () =>
758
- usePage<PageProps & Record<string, PaginatedResponse<T>>>().props[dataKey]
811
+ usePage<PageProps & Record<string, PaginatedResponse<T>>>().props[
812
+ dataKey
813
+ ] as PaginatedResponse<T>
759
814
  );
760
815
 
761
816
  const items = ref<T[]>(paginated.value.data ?? []) as Ref<T[]>;
@@ -863,8 +918,8 @@ combines `all` + `unselected` instead). Bind these to `BbTable`'s
863
918
  `v-model`, `v-model:unselected-items` and `v-model:select-all`.
864
919
 
865
920
  ```ts
866
- // src/composables/useTableSelectionContext.ts
867
- import { isNotNil } from '@/utils';
921
+ // inertia-helpers/useTableSelectionContext.ts
922
+ import { isNotNil } from './utils';
868
923
  import { injectLocal, provideLocal } from '@vueuse/core';
869
924
  import { ref, type Ref } from 'vue';
870
925
 
@@ -921,16 +976,16 @@ what the [Inertia CRUD listing recipe](../recipes/inertia/records-workspace.md)
921
976
  builds on.
922
977
 
923
978
  ```ts
924
- // src/composables/useTableContext.ts
979
+ // inertia-helpers/useTableContext.ts
925
980
  import {
926
981
  usePaginatedResponseContext,
927
982
  type PaginatedResponseContext,
928
- } from '@/composables/usePaginatedResponseContext';
983
+ } from './usePaginatedResponseContext';
929
984
  import {
930
985
  useTableSelectionContext,
931
986
  type TableSelectionContext,
932
- } from '@/composables/useTableSelectionContext';
933
- import { isNotNil } from '@/utils';
987
+ } from './useTableSelectionContext';
988
+ import { isNotNil } from './utils';
934
989
  import { injectLocal, provideLocal } from '@vueuse/core';
935
990
 
936
991
  export type TableContext<T, U> = TableSelectionContext<U> &
@@ -1002,8 +1057,8 @@ are. The same applies to any nested shape (a line-item row, say). It is a
1002
1057
  TypeScript quirk, not a statement about your data.
1003
1058
 
1004
1059
  ```ts
1005
- // src/composables/usePromiseForm.ts
1006
- import { useLoading } from '@/composables/useLoading';
1060
+ // inertia-helpers/usePromiseForm.ts
1061
+ import { useLoading } from './useLoading';
1007
1062
  import {
1008
1063
  useForm,
1009
1064
  type InertiaForm,
@@ -1102,7 +1157,7 @@ export type NullableKeys<T> = {
1102
1157
  ```
1103
1158
 
1104
1159
  ```ts
1105
- import { usePromiseForm } from '@/composables/usePromiseForm';
1160
+ import { usePromiseForm } from '@/composables/inertia-helpers/usePromiseForm';
1106
1161
  import type { NullableKeys } from '@/types/nullable-keys';
1107
1162
  import type { InvoiceRequest } from '@/types';
1108
1163
 
@@ -1126,8 +1181,8 @@ state is not a single Inertia form (multiple forms, ad-hoc refs). For a
1126
1181
  single `usePromiseForm`, prefer the built-in `form.isDirty`.
1127
1182
 
1128
1183
  ```ts
1129
- // src/composables/useHasChanged.ts
1130
- import { isEqual } from '@/utils';
1184
+ // inertia-helpers/useHasChanged.ts
1185
+ import { isEqual } from './utils';
1131
1186
  import { computed, ref, toValue, type WatchSource } from 'vue';
1132
1187
 
1133
1188
  export function useHasChanged<T extends WatchSource<unknown>[]>(
@@ -1173,7 +1228,7 @@ whitelisted action carry the `X-Whitelisted-Action` header so a saving
1173
1228
  visit's redirect is never blocked by its own guard.
1174
1229
 
1175
1230
  ```ts
1176
- // src/composables/useConfirmOnRouteLeave.ts
1231
+ // inertia-helpers/useConfirmOnRouteLeave.ts
1177
1232
  import { router } from '@inertiajs/vue3';
1178
1233
  import { useConfirm } from 'bitboss-ui';
1179
1234
  import { onScopeDispose, toValue, type MaybeRefOrGetter } from 'vue';
@@ -1287,7 +1342,7 @@ Wraps any async function with a concurrent-safe `loading` flag (a counter,
1287
1342
  so overlapping calls don't flicker it off early).
1288
1343
 
1289
1344
  ```ts
1290
- // src/composables/useLoading.ts
1345
+ // inertia-helpers/useLoading.ts
1291
1346
  import { computed, ref } from 'vue';
1292
1347
 
1293
1348
  export const useLoading = <TArgs extends unknown[], TResult>(
@@ -1317,8 +1372,8 @@ per run, auto-abort of the previous run on re-execute, and abort on
1317
1372
  unmount.
1318
1373
 
1319
1374
  ```ts
1320
- // src/composables/useAsyncFn.ts
1321
- import { isPlainObject } from '@/utils';
1375
+ // inertia-helpers/useAsyncFn.ts
1376
+ import { isPlainObject } from './utils';
1322
1377
  import {
1323
1378
  onBeforeMount,
1324
1379
  onBeforeUnmount,
@@ -1408,8 +1463,7 @@ export function useAsyncFn<T>(
1408
1463
  error.value = new Error(err);
1409
1464
  } else if (isPlainObject(err)) {
1410
1465
  // Laravel validation bag: surface the first message.
1411
- const firstKey = Object.keys(err)[0];
1412
- error.value = new Error(String(err[firstKey]));
1466
+ error.value = new Error(String(Object.values(err)[0]));
1413
1467
  }
1414
1468
  } finally {
1415
1469
  loading.value = false;
@@ -1438,9 +1492,9 @@ changes, resets to `null` when the id clears, exposes `loading` and
1438
1492
  it the highlighted row's id.
1439
1493
 
1440
1494
  ```ts
1441
- // src/composables/useResourceContext.ts
1442
- import { useLoading } from '@/composables/useLoading';
1443
- import { noop } from '@/utils';
1495
+ // inertia-helpers/useResourceContext.ts
1496
+ import { useLoading } from './useLoading';
1497
+ import { noop } from './utils';
1444
1498
  import { ref, toValue, watch, type MaybeRefOrGetter, type Ref } from 'vue';
1445
1499
 
1446
1500
  type UseResourceContextOptions<T, ID> = {
@@ -1533,7 +1587,7 @@ contenteditable is focused. Pairs with table selection: select rows, hit
1533
1587
  Delete, dispatch the same confirm-guarded bulk action as the button.
1534
1588
 
1535
1589
  ```ts
1536
- // src/composables/useDeleteCmd.ts
1590
+ // inertia-helpers/useDeleteCmd.ts
1537
1591
  import { useMagicKeys, whenever } from '@vueuse/core';
1538
1592
  import { toValue, type MaybeRefOrGetter } from 'vue';
1539
1593
 
@@ -1560,8 +1614,8 @@ export function useDeleteCmd(
1560
1614
  if (!toValue(options.disabled)) onDelete();
1561
1615
  };
1562
1616
 
1563
- whenever(keys['delete'], handleDelete);
1564
- whenever(keys['backspace'], handleDelete);
1617
+ whenever(() => keys['delete']?.value, handleDelete);
1618
+ whenever(() => keys['backspace']?.value, handleDelete);
1565
1619
  }
1566
1620
  ```
1567
1621
 
@@ -1571,9 +1625,8 @@ Shared reactive breakpoints aligned with Tailwind `md`/`lg` — one window
1571
1625
  listener for the whole app via `createSharedComposable`.
1572
1626
 
1573
1627
  ```ts
1574
- // src/composables/useScreenSizes.ts
1575
- import { useWindowSize } from '@vueuse/core';
1576
- import { createSharedComposable } from '@vueuse/shared';
1628
+ // inertia-helpers/useScreenSizes.ts
1629
+ import { createSharedComposable, useWindowSize } from '@vueuse/core';
1577
1630
  import { computed } from 'vue';
1578
1631
 
1579
1632
  /** Tailwind md breakpoint (px). Mobile when width < 768. */
@@ -1603,7 +1656,7 @@ Index an item list by key for O(1) lookups — e.g. mapping the ids in a
1603
1656
  selection context back to full rows for a bulk-action payload.
1604
1657
 
1605
1658
  ```ts
1606
- // src/composables/useIndexById.ts
1659
+ // inertia-helpers/useIndexById.ts
1607
1660
  import { computed, unref, type MaybeRef } from 'vue';
1608
1661
 
1609
1662
  type Options<TItem> = {
@@ -1634,8 +1687,8 @@ A ref that flips once, the first time a condition becomes true, then stops
1634
1687
  watching — for one-shot reveals ("has ever loaded", onboarding hints).
1635
1688
 
1636
1689
  ```ts
1637
- // src/composables/useUntil.ts
1638
- import { noop } from '@/utils';
1690
+ // inertia-helpers/useUntil.ts
1691
+ import { noop } from './utils';
1639
1692
  import { ref, toValue, watch, type MaybeRefOrGetter } from 'vue';
1640
1693
 
1641
1694
  type Options<T, U> = {
@@ -955,9 +955,10 @@ payload the same way.
955
955
  English since 3.0.0-beta.41 (it was `'it'`): an Italian app sets `locale: 'it'`.
956
956
 
957
957
  Global locale for the library's built-in strings (empty states, close/clear
958
- labels, screen-reader announcements, confirm buttons, …). The library ships
959
- **22 built-in dictionaries** — it, en, es, fr, de, pt (Brazilian-leaning), nl,
960
- pl, tr, ru, uk, cs, ro, hu, el, sv, da, nb, fi, ja, ko, zh-cn — but shipping ≠
958
+ labels, screen-reader announcements, confirm buttons, …) and for the formats
959
+ around them (dates, numbers, week start). The list is fixed and typed (see
960
+ [Locales](#locales) below): a language (`it`, `de`, …), a region (`en-GB`,
961
+ `de-CH`, `fr-CA`, …), or `pt-BR` / `pt-PT` / `zh-CN` / `zh-TW`. Shipping ≠
961
962
  bundling: only the **enabled** locales enter your build (next option). Runtime
962
963
  switching: `useBbConfig().setConfig({ locale })` — to a locale you enabled.
963
964
 
@@ -989,8 +990,8 @@ a locale can.
989
990
 
990
991
  ### `enabledLocales?: BuiltinLocaleKey[]` (default: your `locale` + `'en'`)
991
992
 
992
- Which built-in dictionaries (and their dayjs calendar packs) actually ship in
993
- the bundle. The unset default is the minimal set — the `locale` you configured
993
+ Which built-in locales (their dictionaries and dayjs calendar packs) actually
994
+ ship in the bundle; regions of one language share its dictionary. The unset default is the minimal set — the `locale` you configured
994
995
  plus `en` (the per-key fallback anchor) — roughly 4KB of strings, so a
995
996
  single-language app pays for exactly what it uses without configuring
996
997
  anything. Apps that switch locales at runtime list what they offer:
@@ -1016,18 +1017,43 @@ fallback: your project's `bitboss-ui.d.ts` (see
1016
1017
  Start the dev server or run a build once after changing the list, and commit
1017
1018
  the file. Before that file exists, every built-in locale type-checks.
1018
1019
 
1019
- ### Custom locales are not a supported surface
1020
-
1021
- The library ships **22 dictionaries** and that is the whole set:
1022
-
1023
- ```
1024
- cs da de el en es fi fr hu it ja ko nb nl pl pt ro ru sv tr uk zh-cn
1025
- ```
1020
+ ### Locales
1021
+
1022
+ One fixed list (owner ruling, 2026-10-07). A bare language is its default
1023
+ region (CLDR likely subtags): `it` is `it-IT`, `de` `de-DE`, `en` `en-US`, `pt`
1024
+ `pt-BR`, `zh` `zh-CN` (Simplified).
1025
+
1026
+ | Language | Default | Regions (same words, own formats) | Own dictionary |
1027
+ | --------------- | ---------------------------------------------------------------- | ------------------------------------------------------------- | --------------------------------------------------------------- |
1028
+ | English | `en` (US) | `en-GB`, `en-AU`, `en-CA`, `en-IE` (British spelling: colour) | |
1029
+ | German | `de` | `de-AT` | `de-CH` (ss for ß) |
1030
+ | French | `fr` | `fr-BE`, `fr-CA`, `fr-CH` | |
1031
+ | Italian | `it` | `it-CH` | |
1032
+ | Dutch | `nl` | `nl-BE` | |
1033
+ | Swedish | `sv` | `sv-FI` | |
1034
+ | Spanish | `es` (Spain) | | `es-MX` (Mexico) |
1035
+ | Portuguese | `pt-BR` | | `pt-PT` (European; week from Sunday, CLDR) |
1036
+ | Chinese | `zh-CN` (Simplified) | | `zh-TW` (Traditional, Taiwan), `zh-HK` (Traditional, Hong Kong) |
1037
+ | One region each | `cs` `da` `el` `fi` `hu` `ja` `ko` `nb` `pl` `ro` `ru` `tr` `uk` | | |
1038
+
1039
+ A region reads its language's dictionary and follows its own formats: the
1040
+ long date and the number grouping (`Intl`, through the region's tag:
1041
+ `de-CH` groups `1’234.5`), the week start (its dayjs pack: `en-GB` Monday,
1042
+ `en-CA` Sunday), and the date-input field order and AM / PM words (`fr-CA`
1043
+ types `AAAA-MM-JJ`, `en-GB` `DD/MM/YYYY`). A region is on the list only where
1044
+ its language's words are right there; where they are not (`es-MX`, `zh-HK`),
1045
+ the region has its own dictionary.
1046
+
1047
+ Codes are case-insensitive (`zh-cn`, the spelling before 3.0.0-beta.49, still
1048
+ works), and the full code of a default region is the same locale (`it-IT` is
1049
+ `it`). A code that is not on the list is a type error, and
1050
+ `npx bitboss-ui check` names the nearest one (`unknown-locale`: `en-UK` →
1051
+ `en-GB`).
1026
1052
 
1027
1053
  There is no `additionalLocales` option and no `npx bitboss-ui locale` blueprint
1028
1054
  generator — both were removed deliberately (owner ruling, 2026-08-08). If your
1029
- language is not on that list, the supported answer is to ask for it to be
1030
- added upstream rather than to author a dictionary in your app.
1055
+ language or region is not on the list, the supported answer is to ask for it
1056
+ to be added upstream rather than to author a dictionary in your app.
1031
1057
 
1032
1058
  Locale selection is **build-time**: `enabledLocales` decides what ships, and
1033
1059
  only the active `locale` switches at runtime, among what the build enabled.
@@ -1241,7 +1267,7 @@ For a human-in-the-loop (and agent) safety net, add the `bitboss-ui/eslint-plugi
1241
1267
 
1242
1268
  Two rules in `recommended` are `warn` rather than `error`, because each describes markup that may be deliberate. `bitboss-ui/no-unknown-event` flags an `@event` the component does not emit (it falls through to the root element, so it may be a considered native listener). `bitboss-ui/no-unknown-token` flags a bare `var(--bb-…)` naming a token the installed package does not declare, in a `<style>` block or a static `style="…"` attribute — an undefined custom property is invalid-at-computed-value-time, so CSS discards the **entire declaration** and the rule silently does nothing at runtime. Supplying a fallback (`var(--bb-canvas, #f8fafc)`) is defined behaviour and is never reported; `allowTokens` exempts names you define yourself. The token list is read from the `dist/styles.css` you installed, so it cannot claim a token is invented when your version declares it, and with no stylesheet present the rule stays silent. Before reaching for a `--bb-*` name at all, re-read the two tiers above: a name the library does not declare usually means the knob you want is a **component** token, not a gap in the global set. `bitboss-ui check` carries two further advisory hints that are deliberately not ESLint rules — the hand-rolled avatar and spinner detectors — because both are guesses, and a lint rule that fires on correct code teaches people to ignore all of them.
1243
1269
 
1244
- `bitboss-ui check` also has one finding with no ESLint twin: `object-items-without-text`. It flags object `items` on an item-driven control (`BbSelect`, `BbSelectPopover`, `BbRadioGroup`, `BbCheckboxGroup`, `BbSwitchGroup`, and each `BbDropdown` group with `group: true`) when `item-text` (a group's `itemText`) is not set. Without it every label is `JSON.stringify(item)`, and without `item-value` the whole object is the value. Setting `item-text` without `item-value` is a deliberate whole-object value and is not flagged, and string items never are. **Its reach is the same file only:** an inline `:items="[…]"`, or a top-level `const x = […]` (or `ref([…])` / `reactive([…])`) in the file's `<script setup>` bound as `:items="x"`. An imported array, a computed or a fetched list is not read, and `check` never guesses at one. Silence one site with `<!-- eslint-disable-next-line bitboss-ui/require-partner-prop -->`.
1270
+ `bitboss-ui check` also has one finding with no ESLint twin: `object-items-without-text`. With no `item-text` an option reads its own `label`, else its own `text`, and with no `item-value` its own `value`, so `{ label, value }` and `{ text, value }` items need no accessor. The finding flags object `items` on an item-driven control (`BbSelect`, `BbSelectPopover`, `BbRadioGroup`, `BbCheckboxGroup`, `BbSwitchGroup`) when `item-text` is not set and an item has neither `label` nor `text`: that option's label is `JSON.stringify(item)`. On `BbDropdown` it flags a hand-written group (`group: true`, no mapper) whose rows have neither `label` nor `text`, since hand-written rows are labelled by `label`: give each row one, or make it a mapped group (an `items` getter, or `itemText` / `itemValue`), which reads `label` / `text` and `value` by default. Setting `item-text` without `item-value` is a deliberate whole-object value and is not flagged, and string items never are. **Its reach is the same file only:** an inline `:items="[…]"`, or a top-level `const x = […]` (or `ref([…])` / `reactive([…])`) in the file's `<script setup>` bound as `:items="x"`. An imported array, a computed or a fetched list is not read, and `check` never guesses at one. Silence one site with `<!-- eslint-disable-next-line bitboss-ui/require-partner-prop -->`.
1245
1271
 
1246
1272
  **The manifest ships with the package** — `dist/ai/components.json` is inside
1247
1273
  the tarball, and the rules resolve it relative to their own file, so a normal
@@ -1305,6 +1331,8 @@ for it to quieten a `Bb*` name the library itself exports.
1305
1331
 
1306
1332
  `recommended` also enables **`bitboss-ui/form-model`**: `<BbForm>` takes the object it fills one way, `:model="draft"` — any reactive object (`reactive()`, `ref`, Pinia state, Inertia `useForm()`), written in place, never replaced. The rule fixes `v-model="…"` and `:model-value="…"` on `<BbForm>` to `:model="…"`, and reports without a fix an `@update:model-value` listener (the form emits none: `watch(draft, …, { deep: true })` or `useBbFormContext(id).values`) and a writable `computed` bound as the model (the form writes into what the getter returns and never calls the setter). `bitboss-ui check` reports the same finding as `form-v-model`.
1307
1333
 
1334
+ `recommended` also enables **`bitboss-ui/no-redundant-item-accessor`** (warn), with an autofix that deletes the attribute: an accessor that restates the option default. That covers `item-text="label"`, `item-text="text"` and `item-value="value"` (static or `:item-text="'label'"`, kebab or camel) on `BbSelect`, `BbSelectPopover`, `BbRadioGroup`, `BbCheckboxGroup` and `BbSwitchGroup`, and `itemText: 'label'` / `'text'` / `itemValue: 'value'` in a `BbDropdown` / `BbDropdownButton` group. It only reports what removing cannot change. `item-text="text"` is kept when any item also has `label` (the default would read `label`), and on items the file cannot see only `item-text="label"` and `item-value="value"` are reported. A visible item that is a primitive or lacks the field keeps its accessor. A dropdown group whose only mapper is the redundant one keeps it, since without it the group turns hand-written. `bitboss-ui check` reports the same finding as `redundant-item-accessor` (a warning).
1335
+
1308
1336
  `recommended` also enables **`bitboss-ui/items-provider-context`** (error) and **`bitboss-ui/items-provider-reason`** (warn). Every `items` provider receives one context object, `({ query, reason, modelValue, signal })` (`query` only on `BbSelect`, `BbSelectPopover` and a `searchable` `BbDropdown` group). `items-provider-context` reports a positional provider bound to `:items` (an inline function, or a function / const in the same file; on `BbDropdown` / `BbDropdownButton` and in a `v-bb-dropdown` directive's value, each group's `items:`): two or more parameters, or one parameter typed `string` / `boolean` or named like a query or a prefill flag. Untyped, an old `(query) => …` reads the whole object as its query (`q=[object Object]`). Annotate it with its component's context type (`BbSelectItemsContext`, `BbTableItemsContext`, `BbCheckboxGroupItemsContext`, … `BbDropdownGroupItemsContext`); the message names the one to use. The fix, for untyped parameters, destructures by position: `(query, prefill, m)` → `({ query, reason, modelValue: m })`, each use of `prefill` rewritten as `reason !== 'search'`; a typed provider (vue-tsc already fails it), a group whose `searchable` is not a literal, and a body that already uses `reason` are reported without a fix. `items-provider-reason` warns when a provider compares `reason` with one cause other than `'search'` (`reason === 'initial'`; the causes are `'search'`, `'initial'`, `'dependencies'`, `'model'`, `'reopen'` and, on `BbTable`, `'pagination'`) or switches on it without a `default`: an id lookup that runs on one cause loses the selected labels on the others, so check `reason !== 'search'`. Imported providers are left to TypeScript. `bitboss-ui check` reports the same findings as `positional-provider` and `single-reason` (a warning).
1309
1337
 
1310
1338
  It also enables `bitboss-ui/require-partner-prop`: an opt-in prop set without its documented required partner — BbTable `keyboard-navigation` / `v-model:highlighted` without `row-class` (the shipped tint says "current row"; `row-class` says why, and is how you override it), `loading-text` without `:loading` bound, or `method` on BbButton / BbBadgeButton / BbBaseButton without `href` (only an `href` becomes an Inertia visit; `to` is a RouterLink) — compiles and mounts clean and just does nothing; the rule names the missing partner and quotes why.
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  title: 'Migration v2→v3: BbBreadcrumbs'
3
- summary: Item keys must be strings, the text divider prop is gone, per-item slot names are normalized.
3
+ summary: Items are { label, value } (were { key, text }), the text divider prop is gone, per-item slot names are normalized.
4
4
  ---
5
5
 
6
6
  # BbBreadcrumbs — v2 → v3
@@ -16,12 +16,13 @@ summary: Item keys must be strings, the text divider prop is gone, per-item slot
16
16
  | — | item `prepend:icon` / `append:icon`, per-key `:prepend`/`:append` slots, overflow forwarding | additive |
17
17
  | _(v3 prereleases only)_ glyphs and `item:prepend` / `item:append` content beside the crumb's link, both inside `.bb-breadcrumbs__breadcrumb-container` | inside the link (`.bb-breadcrumbs__breadcrumb > .bb-breadcrumbs__item-icon`), which is now the item's direct child; the label is wrapped in `.bb-breadcrumbs__text`; `.bb-breadcrumbs__breadcrumb-container` no longer exists (nor around the overflow `…` button) | DOM + behaviour: the whole crumb is the click target. Any rule on `.bb-breadcrumbs__breadcrumb-container` matches nothing. The hover colour and the disabled fade moved from the link to `.bb-breadcrumbs__text`, so a rule on `.bb-breadcrumbs__breadcrumb:disabled { opacity }` now also fades the glyphs. Slot content inside the link joins its accessible name — mark decorative content `aria-hidden`. |
18
18
  | the last crumb is the current page by position (`aria-current="page"`, bold), even with an `href` / `to` / `onClick` | only a last crumb **without** a target is the current page; one with a target is an ordinary working link, flat | **⚠ silent** behaviour: a trail ending on a linked crumb loses its bold current page. Drop the target from the last crumb to keep it; keep the target when the trail lists ancestors only |
19
+ | item `{ key, text }` (v2, and v3 up to beta.48) | item `{ value, label }` — `value` (a string, like the v3 `key`: wrap a number in `String(...)`) names the crumb's `#<value>` slots, and its slot scope says `label` (was `text`); a crumb hidden in the overflow menu is a dropdown row with the same fields | hard rename — `npx bitboss-ui check --fix` rewrites literal items |
19
20
 
20
21
  ## Edits
21
22
 
22
23
  ```diff
23
24
  - <BbBreadcrumbs :items="[{ key: 1, text: 'Home', href: '/' }]" divider=">">
24
- + <BbBreadcrumbs :items="[{ key: 'home', text: 'Home', href: '/' }]">
25
+ + <BbBreadcrumbs :items="[{ value: 'home', label: 'Home', href: '/' }]">
25
26
  - <template #Order History>…</template>
26
27
  + <template #order-history>…</template>
27
28
  </BbBreadcrumbs>
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  title: 'Migration v2→v3: BbCheckboxGroup / BbRadioGroup / BbSwitchGroup'
3
- summary: labelPosition renamed legendPosition, per-item disabled is now inert (use selectable), color and the option affix slots removed, BbRadioGroup's name no longer required, the shared bb-cr-container CSS block split into one per group, and the --bb-checkbox-* / --bb-radio-* / --bb-switch-* globals replaced by glyph locals.
3
+ summary: labelPosition renamed legendPosition, per-item disabled is now inert (use selectable), color and the option affix slots removed, BbRadioGroup's name no longer required, the shared bb-cr-container CSS block split into one per group, and the --bb-checkbox-* / --bb-radio-* / --bb-switch-* globals replaced by glyph locals, and object items now read their own label / value by default.
4
4
  ---
5
5
 
6
6
  # BbCheckboxGroup / BbRadioGroup / BbSwitchGroup — v2 → v3
@@ -10,21 +10,21 @@ The three groups share their surface (`BbSwitchGroup` re-exports
10
10
 
11
11
  ## Changes
12
12
 
13
- | v2 | v3 | Kind |
14
- | ------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
15
- | `direction` | `layout` (`FieldLayout`) | family-wide rename + retype (adds `'label-fill'` / `'input-fill'`); the ESLint plugin's `--fix` renames it |
16
- | `inputDirection` | `listLayout` (`ListLayout`: `'horizontal'` / `'vertical'` / `'vertical-stretch'` / `'tiles'`) | **⚠ silent** — v2 `'vertical'` rows spanned the list; v3 `'vertical'` rows keep their own width and `'vertical-stretch'` is the v2 look. `--fix` maps a static `'vertical'` to `'vertical-stretch'`; a bound value is only renamed, so check it |
17
- | — | `itemLayout` (one row: input against label, the `layout` keywords), `itemReverse` | additive |
18
- | `labelPosition?: 'left' \| 'center' \| 'right'` | `legendPosition` | rename |
19
- | a click the parent did not apply still showed as checked on the row | rows show the model; a click only emits until the parent applies it | **⚠ behaviour** — bind `v-model`, or apply the update yourself |
20
- | per-item `disabled` honored (with a deprecation warning) | **inert** — plain data, no warning | **⚠ silent** — use `selectable?: boolean \| ((item) => boolean)` |
21
- | `color?: string` | removed | style via tokens/CSS |
22
- | `#option:prepend` / `#option:append` slots | removed | use the `#label` slot (scoped `{ item, text, checked }`) to decorate options |
23
- | `items` provider unions, `itemText` / `itemValue` | unified provider signature + `ItemAccessor` | retype — plain arrays and zero-argument providers unchanged; a provider now receives ONE object `({ reason, modelValue, signal }: BbCheckboxGroupItemsContext)` ([§6 item 37](../v2-to-v3.md)) |
24
- | `name: string` required (**BbRadioGroup** only; the other two already optional) | `name?: string` (auto-generated per group when omitted) | relaxation — the generated name is unique per group instance, so options still group and two groups never collide |
25
- | — | `legendMode: 'outside' \| 'inside'`, `description` | additive |
26
- | `BbSwitchGroup` `multiple: false` silently ignored (always array emit) | honored — emits a bare value in single-select mode | **⚠ behavioral** (bugfix: the prop was advertised but never forwarded; fixed 2026-07-18) |
27
- | `disabled` / `selectable: false` left a **selected** option interactive | a selected option is disabled like any other | **⚠ behavioral** (bugfix, 2026-08-31 — see below) |
13
+ | v2 | v3 | Kind |
14
+ | ------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
15
+ | `direction` | `layout` (`FieldLayout`) | family-wide rename + retype (adds `'label-fill'` / `'input-fill'`); the ESLint plugin's `--fix` renames it |
16
+ | `inputDirection` | `listLayout` (`ListLayout`: `'horizontal'` / `'vertical'` / `'vertical-stretch'` / `'tiles'`) | **⚠ silent** — v2 `'vertical'` rows spanned the list; v3 `'vertical'` rows keep their own width and `'vertical-stretch'` is the v2 look. `--fix` maps a static `'vertical'` to `'vertical-stretch'`; a bound value is only renamed, so check it |
17
+ | — | `itemLayout` (one row: input against label, the `layout` keywords), `itemReverse` | additive |
18
+ | `labelPosition?: 'left' \| 'center' \| 'right'` | `legendPosition` | rename |
19
+ | a click the parent did not apply still showed as checked on the row | rows show the model; a click only emits until the parent applies it | **⚠ behaviour** — bind `v-model`, or apply the update yourself |
20
+ | per-item `disabled` honored (with a deprecation warning) | **inert** — plain data, no warning | **⚠ silent** — use `selectable?: boolean \| ((item) => boolean)` |
21
+ | `color?: string` | removed | style via tokens/CSS |
22
+ | `#option:prepend` / `#option:append` slots | removed | use the `#label` slot (scoped `{ item, text, checked }`) to decorate options |
23
+ | `items` provider unions, `itemText` / `itemValue` | unified provider signature + `ItemAccessor` | retype; left out, an object item reads its own `label` (else `text`) and `value` (else the whole item) — **⚠ silent** for items with a `value` key: `v-model` gets that value ([§6 item 49](../v2-to-v3.md)); plain arrays and zero-argument providers unchanged; a provider now receives ONE object `({ reason, modelValue, signal }: BbCheckboxGroupItemsContext)` ([§6 item 37](../v2-to-v3.md)) |
24
+ | `name: string` required (**BbRadioGroup** only; the other two already optional) | `name?: string` (auto-generated per group when omitted) | relaxation — the generated name is unique per group instance, so options still group and two groups never collide |
25
+ | — | `legendMode: 'outside' \| 'inside'`, `description` | additive |
26
+ | `BbSwitchGroup` `multiple: false` silently ignored (always array emit) | honored — emits a bare value in single-select mode | **⚠ behavioral** (bugfix: the prop was advertised but never forwarded; fixed 2026-07-18) |
27
+ | `disabled` / `selectable: false` left a **selected** option interactive | a selected option is disabled like any other | **⚠ behavioral** (bugfix, 2026-08-31 — see below) |
28
28
 
29
29
  `max` (checkbox/switch), `required` (radio), and `multiple` defaults are
30
30
  unchanged.