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
@@ -217,14 +217,41 @@ field goes through `2`). Leave the field below `min`, or press Enter in it, and
217
217
  it rises to `min` — Enter corrects it before a surrounding form submits, so
218
218
  `@submit` never receives a value below `min` (defaults are
219
219
  the safe-integer bounds, i.e. effectively unbounded). `maxPrecision` caps the number of decimal places (default `8`),
220
- which is how you pin a field to whole numbers (`0`) or currency (`2`). Commas are
221
- accepted as the decimal separator and normalised to a period, so European
222
- keyboards work without configuration. Grouping separators are read too: with
223
- both `.` and `,` in the value the last one is the decimal (a pasted `1.234,56`
224
- or `1,234.56` is 1234.56), and a separator that repeats groups (`1.234.567`).
225
- Typed key by key, only the European form survives — the field rewrites as you
226
- type, so a typed `1,234.56` has already turned its first comma into a decimal
227
- point.
220
+ which is how you pin a field to whole numbers (`0`); for money set `currency`,
221
+ which brings its own decimals. Extra decimals are refused as typed, never
222
+ rounded: with `0`, a typed `,` or `.` stays until blur and the digits after it
223
+ are refused (`12,5` is 12). `minPrecision` (default `0`) is
224
+ its twin: with `2` the field always shows two decimals (`1` shows `1,00`),
225
+ padding with zeros the user types over, while the model stays the number
226
+ (`1.5`).
227
+
228
+ ### Locale display
229
+
230
+ The field shows its number the way the app's locale writes numbers, while the
231
+ user types: in Italian `10005,6` shows `10.005,6`, in English `10,005.6`.
232
+ Grouping follows each locale (Italian shows `1000` and starts grouping at
233
+ `10.000`). **Type the digits; the field groups them for you; `,` or `.` starts
234
+ the decimals** — whichever key the user presses. An Italian who types the
235
+ thousands dot out of habit (`1.234,56`) still gets 1234.56: the later comma
236
+ turns the earlier dot into grouping. That needs every digit kept, so a field
237
+ with fewer than 3 decimals (`maxPrecision` 0–2, a currency field) refuses a
238
+ second `,` or `.` once a decimal exists: `1.234,50` in a euro field stays
239
+ `1,23 €`. `-` typed anywhere flips the sign, and the caret stays on its digit. A pasted number written the locale's way
240
+ is read that way (`1.000` pasted in Italian is 1000); anything else is read
241
+ like typed text. The paste keeps only the number, the first one when the
242
+ text holds several (`$1,234.56 - $2,000` is 1234.56): `15 m²` is 15,
243
+ accounting brackets `(1,234.56)` are negative, and `1.2E+05` is 120000. With
244
+ `minPrecision`, Backspace at the end walks back over the placeholder zeros
245
+ and the mark first (`1,00|` → `1|,00`, the value kept); the next one deletes
246
+ the digit. A field holds 20 characters; a key, a paste or an autofill past that is
247
+ refused (the field keeps its number), never cut short. On blur the field rebuilds the text from the value, so
248
+ `1,50` shows `1,5` and `007` shows `7` (keep the zeros with `minPrecision`).
249
+
250
+ The model is always a plain number, and a form posts the raw value (`10005.6`)
251
+ through a hidden input that carries `name`; the visible input has no `name`.
252
+ `event.target.value` and a `pt:input` listener see the formatted text.
253
+ `disable-formatting` shows the number as typed, with a period decimal and no
254
+ grouping, as the field did before.
228
255
 
229
256
  **Clamped office setpoint, 16–28 °C**
230
257
 
@@ -336,11 +363,30 @@ const formattedSubtotal = computed(() =>
336
363
 
337
364
  ### Currency & unit fields
338
365
 
339
- Combine `maxPrecision="2"`, `min="0"` and the `prefix` / `suffix` slots for money
340
- and measurement inputs. The affixes are inert decoration inside the field; the
341
- model stays a clean number.
342
-
343
- **Invoice unit price with currency affixes**
366
+ `currency="EUR"` (an ISO 4217 code) shows the amount the locale's way, symbol
367
+ included, inside the text: `1.234,56 €` in Italian, `$1,234.56` in English,
368
+ `CHF-1’234.56` in Swiss German. The decimals follow the currency (2 for EUR,
369
+ 0 for JPY, 3 for KWD); `minPrecision` / `maxPrecision` win when you set them.
370
+ `unit="kilogram"` does the same for a measure (`20 kg`, any unit
371
+ `Intl.NumberFormat` knows); `unit="percent"` holds the number you see, so `15%`
372
+ is `15`, not `0.15`. Set one or the other; with both, `currency` wins. The
373
+ model is always the plain number, and `#prefix` / `#suffix` stay free for icons.
374
+
375
+ The caret stays on the number: a click, Home / End or an arrow on the symbol
376
+ lands at the nearest digit (Home / End move the caret, never the value),
377
+ Backspace after a prefix does nothing, and `-` typed anywhere flips the sign.
378
+ A selection may cover the symbol (select-all copies it), but deleting the
379
+ symbol alone does nothing. Clearing the last digit leaves the field empty (no
380
+ lone `$`), so the placeholder and `required` keep working. A pasted amount,
381
+ symbol and all (`$1,234.56`, `1.234,56 €`, `1,234 kg`), is read as the number;
382
+ another currency's symbol is dropped and the amount kept, with no conversion.
383
+ The unit follows the number's plural (`1 hr`, `2 hrs`), and at rest a screen
384
+ reader hears the amount spelled out (`1,234.50 US dollars`, `20 kilograms`).
385
+ Percent is written the locale's way: `15%` in English and Italian, `15 %` in
386
+ German and French, `%15` in Turkish. `unit` is typed: `kilowatt` and
387
+ `square-meter` are not `Intl` units, so they are type errors.
388
+
389
+ **Invoice unit price in dollars, discount in percent**
344
390
 
345
391
  ```vue
346
392
  <template>
@@ -348,21 +394,27 @@ model stays a clean number.
348
394
  <div>
349
395
  <p class="text-sm font-medium">Line item · INV-2048</p>
350
396
  <p class="text-xs text-(--bb-text-muted)">
351
- Currency stays in the chrome; the model is a clean number.
397
+ The symbol sits in the text; the model is a clean number.
352
398
  </p>
353
399
  </div>
354
400
  <BbNumberInput
355
401
  v-model="price"
356
402
  compact
403
+ currency="USD"
357
404
  label="Unit price"
358
- :max-precision="2"
359
405
  :min="0"
360
406
  name="unit-price"
361
407
  :step="0.5"
362
- >
363
- <template #prefix>$</template>
364
- <template #suffix>USD</template>
365
- </BbNumberInput>
408
+ />
409
+ <BbNumberInput
410
+ v-model="discount"
411
+ compact
412
+ label="Discount"
413
+ :max="100"
414
+ :min="0"
415
+ name="discount"
416
+ unit="percent"
417
+ />
366
418
  </div>
367
419
  </template>
368
420
  <script setup lang="ts">
@@ -370,6 +422,8 @@ import { ref } from 'vue';
370
422
  import { BbNumberInput } from 'bitboss-ui';
371
423
 
372
424
  const price = ref<number | null>(49.99);
425
+ // `unit="percent"` holds the number you see: 15 shows `15%`.
426
+ const discount = ref<number | null>(15);
373
427
  </script>
374
428
  ```
375
429
 
@@ -762,6 +816,10 @@ A `pt` value written in `<script>` (a constant, a preset, a wrapper's
762
816
  - Don't rebuild parsing/clamping in a watcher; the component already sanitises,
763
817
  clamps and limits precision.
764
818
  - Icon-only stepper buttons **require** an `aria-label`.
819
+ - Don't put a currency symbol in `#prefix` / `#suffix` text: use `currency`,
820
+ which places it the locale's way and sets the decimals. With `currency` or
821
+ `unit`, `maxlength`, `pattern`, `event.target.value` and a `pt:input`
822
+ listener see the symbol too; `disable-formatting` drops both.
765
823
  - `layout` is ignored under `labelMode="floating"`/`"inside"` — those modes
766
824
  embed the label in the field and force the vertical layout; it works with the
767
825
  default `'outside'` mode.
@@ -771,6 +829,11 @@ A `pt` value written in `<script>` (a constant, a preset, a wrapper's
771
829
  - The field carries `role="spinbutton"` and mirrors `min` / `max` / current
772
830
  value into `aria-valuemin` / `aria-valuemax` / `aria-valuenow`, so keep `min`
773
831
  and `max` set when the range is known.
832
+ - At rest the field sets `aria-valuetext` to the formatted text (`12.345,5`);
833
+ while it has focus it sets none, so the value is not announced again on
834
+ every keystroke. With `currency` / `unit` it is the spoken amount
835
+ (`1,234.50 US dollars`, `20 kilograms`); `aria-valuenow` stays the number.
836
+ - Grouped text is wider: check a narrow fixed-width field at 200% zoom.
774
837
  - ArrowUp / ArrowDown step the value natively — don't rebuild that with custom
775
838
  key handlers.
776
839
  - `hasErrors` / non-empty `errors` set `aria-invalid`; `disabled` / `readonly`
@@ -792,8 +855,10 @@ A `pt` value written in `<script>` (a constant, a preset, a wrapper's
792
855
  | `autofocus` | `Booleanish \| undefined` | | | Sets autofocus on page load. |
793
856
  | `clearable` | `boolean \| undefined` | `false` | | Displays a clear button when the input has a value and is being interacted with. |
794
857
  | `compact` | `boolean \| undefined` | `false` | | Compact density. Swaps `--bb-input-h`, `--bb-input-py` and `--bb-label-spacing-y` for their `-compact` twins on the field, so a `--bb-input-h` you set on the component is ignored while `compact` is on: size a compact field with `--bb-input-h-compact` (and `--bb-input-py-compact`) instead. |
858
+ | `currency` | `string \| undefined` | | | An ISO 4217 code (`'EUR'`, `'USD'`, `'JPY'`): the field shows the amount the locale's way, symbol included (`1.234,56 €` in Italian, `$1,234.56` in English), inside the text, so `#prefix` / `#suffix` stay free. The model is the number (`1234.56`). The decimals default to the currency's own; `minPrecision` / `maxPrecision` win when set. One or the other with `unit`. |
795
859
  | `description` | `string \| undefined` | | | Descriptive text displayed below the label and above the input. Unlike the hint it is always visible, and it is linked to the input via `aria-describedby` (after any `errors` / `warnings`, before the `hint`). |
796
860
  | `disabled` | `boolean \| undefined` | `false` | | Disables the component. |
861
+ | `disableFormatting` | `boolean \| undefined` | `false` | | Shows the number as typed, with a period decimal and no grouping — the field before Q60.25: no locale display, `name` on the visible input. Without it the field shows the number the locale's way while the user types (`10.005,6` in Italian), groups it for them, and posts the raw value (`10005.6`) through a hidden input carrying `name`. |
797
862
  | `errors` | `string \| string[] \| undefined` | | | Can be a string or an array of string containing the messages to display. They render in an `aria-live="polite"` region (announced when they appear) and, while the list is non-empty, are referenced FIRST from the control's `aria-describedby`, so the reason the field is invalid is re-read whenever the control regains focus. |
798
863
  | `formless` | `boolean \| undefined` | `false` | | Keep this control out of the enclosing `BbForm` entirely: not submitted, not dirty, not reset, not validated. For a control that is not form data (a filter, a "show advanced" switch). |
799
864
  | `hasErrors` | `boolean \| undefined` | `false` | | Define if the component should be in an error state. It usually attaches a CSS class for styling purposes. |
@@ -809,8 +874,9 @@ A `pt` value written in `<script>` (a constant, a preset, a wrapper's
809
874
  | `layout` | `FieldLayout \| undefined` | | | How the label and the input sit together: `'vertical'`, `'horizontal'` (50/50), `'auto'`, `'label-fill'` (the label takes the free space, the input keeps its size), `'input-fill'` (the other way round), or a two-word ratio pattern like `'xx xxxxx'`. |
810
875
  | `loading` | `boolean \| undefined` | `false` | | Sets the component in a loading state, usually triggering some visual styles. |
811
876
  | `max` | `number \| undefined` | `Number.MAX_SAFE_INTEGER` | | Maximum value cap. |
812
- | `maxPrecision` | `number \| undefined` | `8` | | Maximum precision of the number. |
877
+ | `maxPrecision` | `number \| undefined` | `8` | | Maximum precision of the number: fraction digits past it are refused as typed (never rounded). With `currency`, the currency's own digits (`2` for EUR, `0` for JPY, `3` for KWD), or `minPrecision` when that is larger. |
813
878
  | `min` | `number \| undefined` | `Number.MIN_SAFE_INTEGER` | | Minimum value cap. Applied on blur and on Enter (before a surrounding form submits), not while typing, so a value above a `min` greater than 1 can be typed digit by digit. |
879
+ | `minPrecision` | `number \| undefined` | `0` | | Fraction digits always shown (`2`: `1` shows `1,00`, `1,5` shows `1,50`), also while typing, where the padding zeros are placeholders the user types over. The model stays the number (`1.5`). A `minPrecision` above `maxPrecision` gives way to it. Applies with `disableFormatting` too (the padding only, period decimal). With `currency`, the currency's own digits (`2` for EUR, `0` for JPY). |
814
880
  | `modelValue` | `string \| number \| null \| undefined` | `null` | | Used by v-model. |
815
881
  | `name` | `string \| undefined` | | | Defines the name of the input. |
816
882
  | `persistentHint` | `boolean \| undefined` | `false` | | Keeps the hint displayed. |
@@ -821,6 +887,7 @@ A `pt` value written in `<script>` (a constant, a preset, a wrapper's
821
887
  | `reverse` | `boolean \| undefined` | `false` | | Reverses the layout. Applicable in every direction the order of the label and the input is swapped. |
822
888
  | `rules` | `RuleExpression<string \| number \| null>` | | | vee-validate rules for this field. Only inside a `BbForm`. |
823
889
  | `step` | `number \| undefined` | `1` | | Incremental unit used by ArrowUp / ArrowDown and by the `increase` and `decrease` functions the slots receive. It is NOT applied to manual input as a step of 5 would prevent the user from inserting a value like `115` because of rounding down. |
890
+ | `unit` | `BbNumberUnit \| undefined` | | | A unit `Intl.NumberFormat` knows (`'kilogram'`, `'kilometer-per-hour'`, `'celsius'`, `'percent'`; a typo is a type error): the field shows it the locale's way inside the text (`20 kg`, `15 %`). The model is the number you see: `unit="percent"` showing `15 %` holds `15`, not `0.15`. One or the other with `currency` (set both and `currency` wins). |
824
891
  | `validationLabel` | `string \| undefined` | | | The field's name in validation messages (`{field}`): "Email is not valid". Defaults to the `label` (or `legend`), then "This field"; the field's `name` never shows. Set it when the label is not a good noun for a sentence (an icon-only label, a question) or is hidden. Only inside a `BbForm`. |
825
892
  | `validationMode` | `'aggressive'` \| `'balanced'` \| `'lazy'` \| `'submit-only'` \| `'submit-live'` | | | When this field checks itself while the user works: `aggressive` (every change), `balanced` (on leave, then every change while it shows an error), `lazy` (on leave only), `submit-only` (on submit only) or `submit-live` (on submit, then every change while it shows an error). "Leave" is blur for a text-like control, and focus leaving the whole control for a picker or a group; a checkbox or switch commits on click. Unset, the enclosing `BbForm`'s `validation-mode` applies, then the app's `formControls.validationMode` (`'balanced'`). Only inside a `BbForm`. |
826
893
  | `variant` | `'outline'` \| `'secondary'` \| `'none'` \| `'ghost'` | `'outline'` | | Visual variant of the field box — the same names and tokens as the `BbButton` variants. Colours only: height, padding and border width are identical across variants, so a form never reflows when one changes. `'ghost'` has no border in any state (errors and warnings show through the icon and the messages); every variant keeps the focus ring. Register extra names with the plugin's `inputVariants` option. `'none'` is a blank starting point: the field keeps its structure and behaviour but takes no look, so your own classes don't fight a built-in one. You then own hover, focus, disabled and the error / warning states. Fine for a one-off; keep inline styling short, and register a real variant (`inputVariants`) when the look recurs. |
@@ -902,7 +969,7 @@ Set these on the element, or on a class you put on it, to retune this component
902
969
  - **CSS custom properties** listed on a node are declared on THAT node's root and read by elements inside it. Set one on that node's root or on the element inside it that reads it — the pt part that lands there is how you reach it (`pt:box="[--border-color:…]"` on a text input) — never on `BbNumberInput`'s root, where the node's own declaration masks it (design-tokens guide, _Overriding one from a consumer app_, rule 0).
903
970
  - Listed nodes are the ones `BbNumberInput`'s API reaches or that declare a documented CSS variable; the rest fold into "also mounts". The complete tree, repeats and undocumented locals included, is `manifest/components/BbNumberInput.tree.json`.
904
971
 
905
- - `BbNumberInput` _(this component)_ — its own template binds: `controlAttrs` → `input.bb-number-input__input`, `input` → `input.bb-number-input__input`
972
+ - `BbNumberInput` _(this component)_ — its own template binds: `controlAttrs` → `input.bb-number-input__input`, `input` → `input.bb-number-input__input`, `controlAttrs` → `input`
906
973
  - `CommonField` _(internal — not importable, reach it through `BbNumberInput`)_ — `BbNumberInput`'s pt parts land here: `root` → `div.bb-field`, `label` → `component`, `description` → `span.bb-field__description`, `hint` → `span.bb-field__hint`, `counter` → `span.bb-field__counter`, `message` → `div.bb-field__message`; documented CSS variables: `--ctrl-line`; also mounts `BbAsterisk`
907
974
  - `CommonFieldInput` _(internal — not importable, reach it through `BbNumberInput`)_ — `BbNumberInput`'s pt parts land here: `box` → `span.bb-field-input__box`, `prefix` → `span.bb-field-input__prefix`, `icon` → `BbIcon`, `clear` → `ClearableButton`, `spinner` → `BbSpinner`, `suffix` → `span.bb-field-input__suffix`; documented CSS variables: `--bg`, `--bg-hover`, `--bg-focus`, `--bg-disabled`, `--fg-disabled`, `--border-color`, `--border-focus`, `--ring-size`, `--ring-color`, `--elev`, `--frost`, `--inside-label-clearance`; also mounts `ErrorIcon`, `WarningIcon`, `ClearableButton`, `BbIcon`, `BbSpinner`
908
975
 
@@ -42,12 +42,12 @@ Pick a sibling when the shape is more specific:
42
42
  - A focused, page-blocking task → `BbDialog`; supplementary side content →
43
43
  `BbOffCanvas`.
44
44
 
45
- `BbPopover` looks lightweight — it does not dim the page, and an outside click
46
- dismisses it — but it **is** modal underneath: a `<dialog>` opened with
47
- `showModal()`, so focus is trapped and the page behind is inert while it is
48
- open (see Accessibility). Plan for that: the user cannot interact with the page
49
- until they dismiss it. If the surface should also _look_ like it owns the
50
- user's attention until resolved, that is `BbDialog`.
45
+ `BbPopover` is lightweight, and it behaves that way: it does not dim the page,
46
+ the page behind stays live while it is open, and a click outside closes it and
47
+ still reaches what was clicked (see Accessibility). Set `modal` when the panel
48
+ must hold the user until they dismiss it: the page goes inert and Tab stays
49
+ inside. If the surface should also _look_ like it owns the user's attention
50
+ until resolved, that is `BbDialog`.
51
51
 
52
52
  ### Activator and content
53
53
 
@@ -668,12 +668,13 @@ height; without it a tall panel grows freely.
668
668
  - `transition-duration` (ms) times the open/close animation.
669
669
  - For imperative open/close, use `v-model`: write `true` to open and `false` to
670
670
  close, and the popover writes it back on every dismiss (outside click, Escape,
671
- backdrop) — the self-correcting two-way model `BbDialog`/`BbOffCanvas` use.
671
+ Tab out) — the self-correcting two-way model `BbDialog`/`BbOffCanvas` use.
672
672
  There is no template-ref `show()`/`close()` API; the boolean model is it.
673
673
 
674
674
  ### Top layer: escaping overflow and z-index
675
675
 
676
- The floating panel opens in the browser **top layer** (a native `<dialog>`), so
676
+ The floating panel opens in the browser **top layer** (a native popover, or a
677
+ `<dialog>` with `modal`), so
677
678
  it paints above every `z-index`, sticky header, `overflow: hidden` clip, or
678
679
  transformed ancestor — there is nothing to z-index-manage, and a popover inside
679
680
  a scrolling card or table cell is not clipped by it. A popover, select, or
@@ -821,8 +822,8 @@ A `pt` value written in `<script>` (a constant, a preset, a wrapper's
821
822
 
822
823
  - **Don't forget to spread `props`** onto the activator (or pass an `activator`
823
824
  ref) — without it there is no anchor, no ARIA, and no open handler.
824
- - **Don't put a blocking task in a popover** — it doesn't lock the page and
825
- dismisses on outside click; use `BbDialog`.
825
+ - **Don't put a blocking task in a popover** — it doesn't dim the page and
826
+ dismisses on outside click, even with `modal`; use `BbDialog`.
826
827
  - **Don't reach for a popover when you mean a menu** — a plain list of actions is
827
828
  `BbDropdown`.
828
829
  - **Don't set `width` and expect it on mobile** — the adaptive sheet ignores it;
@@ -840,19 +841,23 @@ A `pt` value written in `<script>` (a constant, a preset, a wrapper's
840
841
  `activator`); that is what publishes `aria-expanded` / `aria-controls` /
841
842
  `aria-haspopup` and makes the trigger operable by keyboard.
842
843
  - Focus moves into the panel on open and returns to the activator on close;
843
- `focus-target` overrides where it lands first.
844
- - **The popover is modal, despite looking like it isn't.** It renders as a
845
- `<dialog>` opened with `showModal()` (in `CommonPopover.vue`), so while it is
846
- open Tab is trapped inside it and the rest of the document is inert —
847
- `dialog.matches(':modal')` is `true`. What makes it _read_ as non-modal is
848
- that the `::backdrop` is merely `background-color: transparent`: the page
849
- behind stays fully visible and un-dimmed. That transparent backdrop is also
850
- what makes click-outside-to-close work — the outside click lands on it, and
851
- `@click.self` closes the panel.
852
- Consequence for design: do **not** plan a flow where the user keeps working
853
- behind an open popover. They cannot. If the surrounding page must stay live,
854
- use a non-modal surface instead. For a blocking task that should _look_
855
- blocking, use `BbDialog`, which dims its backdrop.
844
+ `focus-target` overrides where it lands first. A click outside is the
845
+ exception: the popover closes and focus stays where the user clicked.
846
+ - **The popover is a non-modal dialog.** The panel is `role="dialog"` without
847
+ `aria-modal`: the page behind stays clickable, focusable and scrollable while
848
+ it is open. A click outside closes it _and_ reaches what was clicked, so one
849
+ click both dismisses the popover and presses the button behind it. Tab past
850
+ the last control (or Shift+Tab before the first) leaves the panel and closes
851
+ it; Escape closes it and returns focus to the activator.
852
+ - **`modal` makes it a modal dialog.** The panel becomes a `<dialog>` opened
853
+ with `showModal()`: Tab stays inside, the rest of the document is inert and
854
+ the page cannot scroll, and an outside click only closes the panel (it lands
855
+ on the transparent backdrop, not on the page). Reach for it when the user
856
+ must finish or dismiss the panel before touching the page, and for a
857
+ blocking task that should _look_ blocking, use `BbDialog`, which dims its
858
+ backdrop.
859
+ - **The phone sheet is always modal**, whatever `modal` says: it is a
860
+ `BbOffCanvas` that covers the bottom of the screen.
856
861
  - Give an icon-only activator its own `aria-label`; the popover does not name it.
857
862
 
858
863
  ## v-model
@@ -871,6 +876,7 @@ A `pt` value written in `<script>` (a constant, a preset, a wrapper's
871
876
  | `eager` | `boolean \| undefined` | `false` | | Renders the panel's content at mount instead of on the first open (the phone sheet's too). |
872
877
  | `focusTarget` | `string \| undefined` | | | Selector for the element that receives focus after opening. Defaults to the first focusable element inside the popover. |
873
878
  | `id` | `string \| undefined` | | | The activator's id (the panel is `bbp_<id>` and is labelled by it). Generated when omitted. |
879
+ | `modal` | `boolean \| undefined` | `false` | | Makes the floating panel modal: the page behind it goes inert and cannot scroll, and Tab stays inside the panel until it closes. Off by default, the panel is a non-modal dialog: the page stays usable, a click outside closes it and still reaches what was clicked, and Tab past its last control (or Shift+Tab before its first) leaves it and closes it. The phone sheet is modal either way. |
874
880
  | `modelValue` | `boolean \| undefined` | `false` | | Used by v-model to open / close the popover. A popover with no `v-model` starts closed and is driven by its `trigger`. |
875
881
  | `offCanvasProps` | `Partial<BbOffCanvasProps> \| undefined` | | | Props for the phone sheet. A `pt` inside it, object or colon keys, styles only that sheet. Overrides forwarded to the underlying `BbOffCanvas` when `adaptive` renders the sheet on mobile. Merged over the adaptive defaults (`side: 'bottom'`, `size: 'auto'`, `draggable: true`). Ignored when `adaptive` is `false`. A `pt` inside it styles ONLY the sheet, in `BbOffCanvas`'s part words (`root`, `header`, `title`, `description`, `content`, `footer`, `close`; state `open`), object (`{ pt: { header: '…' } }`) or colon keys (`{ 'pt:header': '…' }`) alike. It merges after what this component forwards to its sheet, so it wins a conflict and drops nothing — see the passthrough guide § Inside the sheet. |
876
882
  | `offset` | `number \| undefined` | `4` | | Space the floating container will maintain from the activator. |
@@ -12,11 +12,12 @@
12
12
 
13
13
  ### When to use
14
14
 
15
- `BbProgress` is for **determinate** progress — a task whose completion you can
16
- measure: an upload, a multi-step setup, a storage quota. Bind the current value
17
- with `:model-value` and the bar fills from `min` to `max`. If the wait has no
18
- measurable end, use [`BbSpinner`](./BbSpinner.md) instead — passing `null` here
19
- renders an _empty_ bar, not an animated indeterminate state.
15
+ `BbProgress` is for progress you can show as a bar: an upload, a multi-step
16
+ setup, a storage quota. Bind the current value with `:model-value` and the bar
17
+ fills from `min` to `max`. While the wait has no measurable end yet, set
18
+ `indeterminate`: the bar slides and reports no value. Passing `null` alone
19
+ renders an _empty_ bar, not the indeterminate one. For a wait with no bar at all
20
+ (a button, a small inline busy mark), use [`BbSpinner`](./BbSpinner.md).
20
21
 
21
22
  The component is purely presentational: it emits no events and never changes the
22
23
  value on its own. `v-model` compiles but has nothing to write back — prefer the
@@ -197,14 +198,29 @@ toast({
197
198
  });
198
199
  ```
199
200
 
201
+ ### A wait with no measurable end: `indeterminate`
202
+
203
+ `indeterminate` slides a short bar across the track (a slow pulse in place
204
+ under `prefers-reduced-motion`) and the progressbar reports no value, which is
205
+ how assistive tech hears "busy, amount unknown". The `model-value` is kept:
206
+ turn `indeterminate` off and the bar shows it again.
207
+
208
+ **Preparing an export**
209
+
210
+ ```vue
211
+ <div class="flex max-w-sm flex-col gap-2">
212
+ <span class="text-sm">Preparing your export…</span>
213
+ <BbProgress indeterminate label="Export" :model-value="0" />
214
+ </div>
215
+ ```
216
+
200
217
  ### Handing off to an unmeasurable phase
201
218
 
202
219
  Uploads often finish before the work does: the server still parses rows,
203
- transcodes, indexes — with no measurable progress. Swap the bar for
204
- [`BbSpinner`](./BbSpinner.md) at that boundary instead of faking a bar that
205
- creeps toward 99%. The determinate phase gets `BbProgress`, the indeterminate
206
- one gets a spinner, and completion is derived from your own state — the bar
207
- emits nothing.
220
+ transcodes, indexes — with no measurable progress. Don't fake a bar that
221
+ creeps toward 99%: switch the same bar to `indeterminate` at that boundary, or
222
+ swap it for [`BbSpinner`](./BbSpinner.md) as the example below does. Completion
223
+ is derived from your own state — the bar emits nothing.
208
224
 
209
225
  **CSV import: upload, then processing**
210
226
 
@@ -411,8 +427,9 @@ scattered per-usage.
411
427
  `pt` reaches a named part with a class list — or, in the object form, a
412
428
  style and attributes. Parts: `root` (the track; the bar follows it through
413
429
  `--track`, `--track-color`, `--accent` and `--r`) and `bar` (the fill
414
- itself, `.bb-progress__bar`). No states — nothing it
415
- paints is a state.
430
+ itself, `.bb-progress__bar`). One state, `indeterminate`, on while the
431
+ bar slides: `pt:bar:indeterminate="bg-(--bb-info)"` tints only the sliding
432
+ bar.
416
433
 
417
434
  `pt:root` is plain `class` with extra letters: on the track, write `class` /
418
435
  `style` on the tag. Reach for `pt:bar` when the fill needs more than a
@@ -449,9 +466,9 @@ A `pt` value written in `<script>` (a constant, a preset, a wrapper's
449
466
  ### Works well with
450
467
 
451
468
  - `BbDropzone` — captures the files; you upload and drive the bar (see above).
452
- - [`BbSpinner`](./BbSpinner.md) — for the phases you _can't_ measure (e.g.
453
- server-side processing after the upload hits 100%). Swap components, don't
454
- fake a creeping bar — see the CSV import example above.
469
+ - [`BbSpinner`](./BbSpinner.md) — for a busy mark with no bar at all (a
470
+ button, an inline status). Inside a bar, an unmeasurable phase is
471
+ `indeterminate`, not a creeping fake — see the CSV import example above.
455
472
  - `useToast` — announce completion once the task finishes; the bar alone is a
456
473
  silent visual.
457
474
  - `BbTable` — for table data loads use its built-in `loading` skeleton, not a
@@ -459,8 +476,8 @@ A `pt` value written in `<script>` (a constant, a preset, a wrapper's
459
476
 
460
477
  ### Gotchas & anti-patterns
461
478
 
462
- - **`modelValue: null` renders an empty bar.** There is no indeterminate
463
- animation; for unknown waits use `BbSpinner`.
479
+ - **`modelValue: null` renders an empty bar**, not an indeterminate one: set
480
+ `indeterminate` for a wait with no measurable end.
464
481
  - **Don't restate the built-in ARIA.** The bar already exposes
465
482
  `role="progressbar"` with `aria-valuemin/max/now` — wrapping it in another
466
483
  `role="progressbar"` double-announces (see Accessibility). Add a label, not
@@ -478,10 +495,12 @@ A `pt` value written in `<script>` (a constant, a preset, a wrapper's
478
495
  The bar carries its own ARIA: `role="progressbar"` with `aria-valuemin`,
479
496
  `aria-valuemax`, and `aria-valuenow` kept in sync with `min`/`max`/the model
480
497
  value (out-of-range values are clamped, matching the visual fill). A `null`
481
- value reports `aria-valuenow` = `min`, matching the empty bar it renders —
482
- the component never signals "indeterminate" to assistive tech, because it has
483
- no indeterminate mode (that's `BbSpinner`). Do **not** wrap the component in
484
- another `role="progressbar"`.
498
+ value reports `aria-valuenow` = `min`, matching the empty bar it renders. With
499
+ `indeterminate` the bar omits `aria-valuenow` (and holds back an
500
+ `aria-valuetext` you passed), which is how a progressbar says "indeterminate";
501
+ both come back when it turns off. If the bar describes a region that is
502
+ loading, mark that region `aria-busy="true"` meanwhile. Do **not** wrap the
503
+ component in another `role="progressbar"`.
485
504
 
486
505
  What's still on you:
487
506
 
@@ -516,7 +535,8 @@ What's still on you:
516
535
 
517
536
  | Prop | Type | Default | Required | Description |
518
537
  | --- | --- | --- | --- | --- |
519
- | `pt:<part>`, `pt:<part>:<state>`, `pt` | `PtValue` | | | Passthrough — a class list, or `{ class, style, attrs }`, bound to one named part of the component; the state form applies only while that state is on. Parts: `bar`, `root`. States: —. What each one is: _Passthrough parts and states_ below. `pt` is the object form with the same keys minus the prefix (`{ icon: '…', 'icon:loading': '…' }`). See `guides/passthrough.md`. In `<script>` a `pt` value is typed `BbProgressProps['pt']` (`PtValue` is not exported): § Typing `pt` in `<script>`. |
538
+ | `pt:<part>`, `pt:<part>:<state>`, `pt` | `PtValue` | | | Passthrough — a class list, or `{ class, style, attrs }`, bound to one named part of the component; the state form applies only while that state is on. Parts: `bar`, `root`. States: `indeterminate`. What each one is: _Passthrough parts and states_ below. `pt` is the object form with the same keys minus the prefix (`{ icon: '…', 'icon:loading': '…' }`). See `guides/passthrough.md`. In `<script>` a `pt` value is typed `BbProgressProps['pt']` (`PtValue` is not exported): § Typing `pt` in `<script>`. |
539
+ | `indeterminate` | `boolean \| undefined` | `false` | | A wait you cannot measure yet: the bar slides back and forth (a calm pulse under `prefers-reduced-motion`) and the progressbar reports no value (`aria-valuenow` is omitted, as the ARIA pattern asks). The `modelValue` is kept and shows again when this turns off. A `null` `modelValue` alone is still an empty bar, not this. |
520
540
  | `label` | `string \| undefined` | `undefined` | | Accessible name for the progress bar, forwarded to `aria-label`. A `progressbar` with no name is announced only as a bare percentage, so give it one whenever the surrounding text doesn't already name it (e.g. `"Upload"`). Matches the `label` naming prop on BbSpinner / BbIcon. |
521
541
  | `max` | `number \| undefined` | `100` | | Maximum value. Upper cap. |
522
542
  | `min` | `number \| undefined` | `0` | | Minimum value. Lower cap. |
@@ -531,6 +551,12 @@ What's still on you:
531
551
  | `root` | The track (the `progressbar` element); the bar follows it through its locals (`--track`, `--track-color`, `--accent`, `--r`, the same words as BbSlider's rail and bar). |
532
552
  | `bar` | The fill itself. Its inline `transform` IS the value (it slides from -100% to 0), so style its look here — colour, gradient, radius — never its position. |
533
553
 
554
+ States are listed in precedence order: when two are on at once and their entries conflict, the later one wins.
555
+
556
+ | State | When it is on |
557
+ | --- | --- |
558
+ | `indeterminate` | Component-wide: `indeterminate` is on; the bar slides (pulses under reduced motion) instead of showing a value. |
559
+
534
560
  ## Events
535
561
 
536
562
  - None.
@@ -54,18 +54,14 @@ Choose by shape:
54
54
 
55
55
  ### Items and value mapping
56
56
 
57
- **Object items need `item-text`.** Without it each label is
58
- `JSON.stringify(item)`, and without `item-value` the whole object is the value.
59
- `{ label, value }` items take both:
57
+ **`{ label, value }` and `{ text, value }` items work as they are; any other
58
+ shape needs `item-text` / `item-value`.** With neither prop an option reads its
59
+ own `label` (else its own `text`) and its own `value`, whatever it holds (`null`
60
+ included). An object with none of those fields falls back to
61
+ `JSON.stringify(item)` as text and the whole object as value.
60
62
 
61
63
  ```vue
62
- <BbRadioGroup
63
- v-model="plan"
64
- legend="Plan"
65
- :items="plans"
66
- item-text="label"
67
- item-value="value"
68
- />
64
+ <BbRadioGroup v-model="plan" legend="Plan" :items="plans" />
69
65
  ```
70
66
 
71
67
  Pass domain objects to `items` and resolve the display text and stored value
@@ -121,7 +117,8 @@ const plan = ref<string>('pro');
121
117
 
122
118
  #### Additional row fields: `item-props`
123
119
 
124
- `item-text` and `item-value` are the option's label and identity. Anything
120
+ The option's text and value (from `item-text` / `item-value`, or the item's own
121
+ `label` and `value`) are its label and identity. Anything
125
122
  **additional** about a row comes from `item-props` — for option groups that is
126
123
  one field, `description`: a muted line **under** the option's label, beside the
127
124
  control.
@@ -461,7 +458,6 @@ valid yet" and gate the submit on it.
461
458
  <BbRadioGroup
462
459
  v-model="branch"
463
460
  compact
464
- item-text="label"
465
461
  item-value="id"
466
462
  :items="branches"
467
463
  legend="Target branch"
@@ -475,7 +471,6 @@ valid yet" and gate the submit on it.
475
471
  :deps-debounce-time="150"
476
472
  enforce-coherence
477
473
  hint="Protected branches require a linear history."
478
- item-text="label"
479
474
  item-value="id"
480
475
  :items="loadStrategies"
481
476
  legend="Merge strategy"
@@ -561,7 +556,6 @@ whenever the slot is empty.
561
556
  v-model="theme"
562
557
  class="theme-tiles"
563
558
  item-layout="vertical"
564
- item-text="label"
565
559
  item-value="id"
566
560
  :items="themes"
567
561
  legend="Appearance"
@@ -752,7 +746,6 @@ const plan = ref<string>('pro');
752
746
  <BbRadioGroup
753
747
  v-model="theme"
754
748
  item-layout="vertical"
755
- item-text="label"
756
749
  item-value="id"
757
750
  :items="themes"
758
751
  legend="Appearance"
@@ -829,8 +822,9 @@ for a preset that fits any row type (never `<any>`), not an imported
829
822
  nothing.
830
823
  - `readonly` still submits its value and stays focusable; use `disabled` only
831
824
  when the whole choice doesn't apply.
832
- - Don't pre-map `items` into `{ label, value }` — pass raw rows and resolve with
833
- `item-text` / `item-value`.
825
+ - Don't pre-map domain rows into `{ label, value }` copies — pass raw rows and
826
+ resolve with `item-text` / `item-value` (a list that already is
827
+ `{ label, value }` needs neither).
834
828
 
835
829
  ### Accessibility
836
830
 
@@ -889,8 +883,8 @@ for a preset that fits any row type (never `<any>`), not an imported
889
883
  | `itemProps` | `BbOptionGroupItemProps<T> \| undefined` | | | ADDITIONAL row fields resolved from each item — never its text or value (those stay on `itemText` / `itemValue`). Option groups accept one field: - `description` — a muted line under the option label, beside the control; it may wrap. Either an object with a path or getter per field (`{ description: 'email' }`) or a function returning the fields (`(item) => ({ description: item.email })`). Without it no field renders — an item's own `description` is never read implicitly — and an empty value renders nothing for that item. The description is announced as the option's description, never part of its name. To disable individual options use `selectable`. |
890
884
  | `itemReverse` | `boolean \| undefined` | `false` | | Swaps each row's input and label from their natural order (input first), in every `item-layout`. `reverse` swaps the legend and the options instead. |
891
885
  | `items` | `T[] \| ((context: BbRadioGroupItemsContext) => T[] \| Promise<T[]>)` | | yes | The options: an array, or a provider function called with ONE context object and returning the rows, sync or async. The context carries: - `reason` — why this call happened: `'initial'` (the first load, on mount), `'dependencies'` (a `dependencies` entry or the `items` function changed; a retry arrives this way) or `'model'` (the model changed from outside and the options cannot resolve it). The group has no search field, so it never passes `query`; - `modelValue` — the `v-model` as-is; - `signal` — an `AbortSignal`, aborted when a newer call starts or the group is disposed; pass it to every request. A provider signals a failure by THROWING, never by returning `[]`: the rows are cleared, nothing is pruned, and `#empty` receives the `error` (`failed-text` is shown). Zero-argument providers keep working. Annotate the parameter `BbRadioGroupItemsContext`. |
892
- | `itemText` | `ItemAccessor<T, string> \| undefined` | `JSON.stringify(item)` | | Defines a path that returns a property of the object to use as text or a function that returns a string. |
893
- | `itemValue` | `ItemAccessor<T> \| undefined` | `the whole item` | | Defines a path that returns a property of the object to use as value or a function that returns any value. |
886
+ | `itemText` | `ItemAccessor<T, string> \| undefined` | `own `label`, else `text`, else `JSON.stringify(item)`` | | Defines a path that returns a property of the object to use as text or a function that returns a string. Unset: own `label`, else `text` (`{ label, value }` needs no accessor). |
887
+ | `itemValue` | `ItemAccessor<T> \| undefined` | `own `value`, else the whole item` | | Defines a path that returns a property of the object to use as value or a function that returns any value. Unset: own `value`, even `null`. |
894
888
  | `labelAlign` | `'top'` \| `'center'` \| `'bottom'` | | | Vertical position of the label block in a side-by-side row; not `labelPosition`, the horizontal one. Omitted, the label's first line meets the control's. |
895
889
  | `layout` | `FieldLayout \| undefined` | | | How the label and the input sit together: `'vertical'`, `'horizontal'` (50/50), `'auto'`, `'label-fill'` (the label takes the free space, the input keeps its size), `'input-fill'` (the other way round), or a two-word ratio pattern like `'xx xxxxx'`. |
896
890
  | `legend` | `string` | | yes | Text content of the legend. |