bitboss-ui 3.0.0-alpha.4 → 3.0.0-alpha.5

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 (327) hide show
  1. package/README.md +12 -10
  2. package/bin/bitboss-ui-mcp.mjs +24 -8
  3. package/bin/bitboss-ui.mjs +41 -12
  4. package/dist/ai/BbAlert.md +7 -0
  5. package/dist/ai/BbAvatar.md +54 -25
  6. package/dist/ai/BbBadge.md +21 -4
  7. package/dist/ai/BbBaseButton.md +11 -5
  8. package/dist/ai/BbBaseColorInput.md +1 -0
  9. package/dist/ai/BbBaseDatePicker.md +3 -2
  10. package/dist/ai/BbBaseDatePickerInput.md +6 -6
  11. package/dist/ai/BbBaseInputContainer.md +1 -1
  12. package/dist/ai/BbBaseSlider.md +1 -1
  13. package/dist/ai/BbButton.md +24 -9
  14. package/dist/ai/BbCheckbox.md +1 -1
  15. package/dist/ai/BbCheckboxGroup.md +1 -1
  16. package/dist/ai/BbColorInput.md +15 -2
  17. package/dist/ai/BbColorPalette.md +27 -1
  18. package/dist/ai/BbDatePicker.md +80 -14
  19. package/dist/ai/BbDatePickerInput.md +54 -13
  20. package/dist/ai/BbDropdown.md +25 -6
  21. package/dist/ai/BbDropzone.md +4 -4
  22. package/dist/ai/BbIndicator.md +4 -4
  23. package/dist/ai/BbNumberInput.md +2 -2
  24. package/dist/ai/BbOffCanvas.md +19 -2
  25. package/dist/ai/BbPagination.md +17 -9
  26. package/dist/ai/BbPopover.md +11 -1
  27. package/dist/ai/BbProgress.md +3 -3
  28. package/dist/ai/BbRadio.md +17 -8
  29. package/dist/ai/BbRadioGroup.md +100 -3
  30. package/dist/ai/BbRating.md +1 -1
  31. package/dist/ai/BbSelect.md +27 -12
  32. package/dist/ai/BbSelectPopover.md +64 -14
  33. package/dist/ai/BbSlider.md +6 -3
  34. package/dist/ai/BbSwitch.md +1 -1
  35. package/dist/ai/BbSwitchGroup.md +1 -1
  36. package/dist/ai/BbTable.md +141 -23
  37. package/dist/ai/BbTabs.md +9 -0
  38. package/dist/ai/BbTag.md +1 -1
  39. package/dist/ai/BbTextInput.md +38 -1
  40. package/dist/ai/BbTextarea.md +2 -2
  41. package/dist/ai/BbTimePickerInput.md +5 -3
  42. package/dist/ai/BbToast.md +7 -1
  43. package/dist/ai/BbTree.md +40 -20
  44. package/dist/ai/FlatListBox.md +2 -1
  45. package/dist/ai/GroupedListBox.md +3 -2
  46. package/dist/ai/ListBox.md +2 -1
  47. package/dist/ai/components.json +184 -88
  48. package/dist/ai/composables/useBbConfig.md +73 -4
  49. package/dist/ai/composables/useBbTableContext.md +10 -10
  50. package/dist/ai/composables/useSafeArea.md +163 -0
  51. package/dist/ai/guides/agent-contract.md +72 -11
  52. package/dist/ai/guides/ai-router.md +2 -0
  53. package/dist/ai/guides/app-layout.md +14 -6
  54. package/dist/ai/guides/component-picker.md +24 -22
  55. package/dist/ai/guides/design-language.md +120 -15
  56. package/dist/ai/guides/design-tokens.md +143 -23
  57. package/dist/ai/guides/fetch-items-playbook.md +1 -1
  58. package/dist/ai/guides/inertia-helpers.md +103 -2
  59. package/dist/ai/guides/inline-edit-playbook.md +34 -1
  60. package/dist/ai/guides/installation-and-plugin-setup.md +21 -3
  61. package/dist/ai/guides/migration/components/bb-checkbox-group.md +14 -13
  62. package/dist/ai/guides/migration/components/bb-checkbox.md +10 -9
  63. package/dist/ai/guides/migration/components/bb-date-picker-input.md +30 -0
  64. package/dist/ai/guides/migration/components/bb-pagination.md +16 -2
  65. package/dist/ai/guides/migration/components/bb-select.md +13 -13
  66. package/dist/ai/guides/migration/components/bb-table.md +45 -8
  67. package/dist/ai/guides/migration/v2-to-v3.md +6 -2
  68. package/dist/ai/guides/page-shell.md +112 -8
  69. package/dist/ai/index.md +8 -4
  70. package/dist/ai/recipes/inertia/approvals-inbox.md +19 -9
  71. package/dist/ai/recipes/inertia/command-palette.md +311 -0
  72. package/dist/ai/recipes/inertia/inline-edit-workspace.md +62 -16
  73. package/dist/ai/recipes/inertia/layout-scaffold.md +259 -3
  74. package/dist/ai/recipes/inertia/ownership-atlas.md +64 -2
  75. package/dist/ai/recipes/inertia/record-form.md +2 -2
  76. package/dist/ai/recipes/inertia/records-workspace.md +342 -116
  77. package/dist/ai/recipes/inertia/upload-center.md +19 -11
  78. package/dist/ai/recipes/nuxt/approvals-inbox.md +6 -2
  79. package/dist/ai/recipes/nuxt/command-palette.md +300 -0
  80. package/dist/ai/recipes/nuxt/inline-edit-workspace.md +66 -16
  81. package/dist/ai/recipes/nuxt/layout-scaffold.md +259 -3
  82. package/dist/ai/recipes/nuxt/record-form.md +2 -2
  83. package/dist/ai/recipes/nuxt/records-workspace.md +344 -113
  84. package/dist/ai/recipes/nuxt/upload-center.md +21 -13
  85. package/dist/ai/recipes/vue/approvals-inbox.md +6 -2
  86. package/dist/ai/recipes/vue/command-palette.md +297 -0
  87. package/dist/ai/recipes/vue/inline-edit-workspace.md +67 -16
  88. package/dist/ai/recipes/vue/layout-scaffold.md +259 -3
  89. package/dist/ai/recipes/vue/record-form.md +2 -2
  90. package/dist/ai/recipes/vue/records-workspace.md +345 -114
  91. package/dist/ai/recipes/vue/upload-center.md +21 -13
  92. package/dist/ai/source/BbBaseButton.md +34 -18
  93. package/dist/ai/source/BbBaseColorInput.md +15 -0
  94. package/dist/ai/source/BbBaseColorPalette.md +1 -1
  95. package/dist/ai/source/BbBaseDatePicker.md +481 -49
  96. package/dist/ai/source/BbBaseDatePickerInput.md +218 -74
  97. package/dist/ai/source/BbBaseInputContainer.md +7 -5
  98. package/dist/ai/source/BbBaseRadioIcon.md +16 -7
  99. package/dist/ai/source/BbBaseSelect.md +8 -3
  100. package/dist/ai/source/BbBaseSlider.md +58 -8
  101. package/dist/ai/source/BbBaseTextarea.md +26 -2
  102. package/dist/ai/source/BbBreadcrumbs.md +2 -2
  103. package/dist/ai/source/BbCheckbox.md +1 -1
  104. package/dist/ai/source/BbCheckboxGroup.md +1 -1
  105. package/dist/ai/source/BbColorInput.md +18 -2
  106. package/dist/ai/source/BbColorPalette.md +128 -10
  107. package/dist/ai/source/BbConfirm.md +11 -1
  108. package/dist/ai/source/BbDatePicker.md +151 -36
  109. package/dist/ai/source/BbDatePickerInput.md +23 -9
  110. package/dist/ai/source/BbDialog.md +30 -9
  111. package/dist/ai/source/BbDropdown.md +228 -41
  112. package/dist/ai/source/BbDropdownGroup.md +138 -34
  113. package/dist/ai/source/BbDropzone.md +15 -3
  114. package/dist/ai/source/BbIcon.md +43 -2
  115. package/dist/ai/source/BbNumberInput.md +1 -9
  116. package/dist/ai/source/BbOffCanvas.md +29 -11
  117. package/dist/ai/source/BbPagination.md +5 -15
  118. package/dist/ai/source/BbPopover.md +1 -1
  119. package/dist/ai/source/BbProgress.md +18 -2
  120. package/dist/ai/source/BbRadio.md +20 -6
  121. package/dist/ai/source/BbRadioGroup.md +20 -6
  122. package/dist/ai/source/BbRating.md +2 -2
  123. package/dist/ai/source/BbSelect.md +8 -6
  124. package/dist/ai/source/BbSelectPopover.md +245 -38
  125. package/dist/ai/source/BbSlider.md +1 -1
  126. package/dist/ai/source/BbTable.md +191 -58
  127. package/dist/ai/source/BbTag.md +10 -1
  128. package/dist/ai/source/BbTextInput.md +1 -1
  129. package/dist/ai/source/BbTextarea.md +1 -1
  130. package/dist/ai/source/BbTimePickerInput.md +1 -1
  131. package/dist/ai/source/CommonInputWrapper.md +41 -11
  132. package/dist/ai/source/CommonPopover.md +8 -3
  133. package/dist/ai/source/FlatListBox.md +80 -50
  134. package/dist/ai/source/GroupedListBox.md +96 -35
  135. package/dist/ai/source/ListBox.md +9 -1
  136. package/dist/badge-variants.d.ts +6 -0
  137. package/dist/button-variants.d.ts +1 -0
  138. package/dist/components/BbBaseButton/BbBaseButton.vue_vue_type_script_setup_true_lang.js +82 -89
  139. package/dist/components/BbBaseCheckbox/BbBaseCheckbox.vue.d.ts +2 -2
  140. package/dist/components/BbBaseColorInput/BbBaseColorInput.vue.d.ts +3 -2
  141. package/dist/components/BbBaseColorInput/BbBaseColorInput.vue_vue_type_script_setup_true_lang.js +6 -0
  142. package/dist/components/BbBaseColorInput/types.d.ts +9 -0
  143. package/dist/components/BbBaseDatePicker/BbBaseDatePicker.vue.d.ts +1 -0
  144. package/dist/components/BbBaseDatePicker/BbBaseDatePicker.vue_vue_type_script_setup_true_lang.js +234 -127
  145. package/dist/components/BbBaseDatePicker/BbBaseDatePickerInputDaySelector.vue.d.ts +3 -0
  146. package/dist/components/BbBaseDatePicker/BbBaseDatePickerInputDaySelector.vue_vue_type_script_setup_true_lang.js +73 -66
  147. package/dist/components/BbBaseDatePicker/BbBaseDatePickerMonthSelector.vue_vue_type_script_setup_true_lang.js +87 -38
  148. package/dist/components/BbBaseDatePicker/BbBaseDatePickerYearSelector.vue_vue_type_script_setup_true_lang.js +86 -46
  149. package/dist/components/BbBaseDatePicker/types.d.ts +12 -1
  150. package/dist/components/BbBaseDatePicker/useDatePickerContext.d.ts +29 -0
  151. package/dist/components/BbBaseDatePickerInput/BbBaseDatePickerInput.vue.d.ts +1 -0
  152. package/dist/components/BbBaseDatePickerInput/BbBaseDatePickerInput.vue_vue_type_script_setup_true_lang.js +270 -249
  153. package/dist/components/BbBaseDatePickerInput/types.d.ts +22 -8
  154. package/dist/components/BbBaseInputContainer/types.d.ts +4 -3
  155. package/dist/components/BbBaseNumberInput/BbBaseNumberInput.vue.d.ts +2 -2
  156. package/dist/components/BbBaseRadio/BbBaseRadio.vue.d.ts +2 -2
  157. package/dist/components/BbBaseRating/BbBaseRating.vue.d.ts +2 -2
  158. package/dist/components/BbBaseSelect/BbBaseSelect.vue_vue_type_script_setup_true_lang.js +105 -104
  159. package/dist/components/BbBaseSlider/BbBaseSlider.vue.d.ts +2 -2
  160. package/dist/components/BbBaseSlider/BbBaseSlider.vue_vue_type_script_setup_true_lang.js +181 -169
  161. package/dist/components/BbBaseSlider/types.d.ts +7 -7
  162. package/dist/components/BbBaseSwitch/BbBaseSwitch.vue.d.ts +2 -2
  163. package/dist/components/BbBaseTag/BbBaseTag.vue.d.ts +2 -2
  164. package/dist/components/BbBaseTextInput/BbBaseTextInput.vue.d.ts +2 -2
  165. package/dist/components/BbBaseTextarea/BbBaseTextarea.vue.d.ts +2 -2
  166. package/dist/components/BbBaseTextarea/BbBaseTextarea.vue_vue_type_script_setup_true_lang.js +23 -11
  167. package/dist/components/BbCheckbox/BbCheckbox.vue.d.ts +2 -2
  168. package/dist/components/BbCheckbox/types.d.ts +1 -1
  169. package/dist/components/BbCheckboxGroup/types.d.ts +1 -1
  170. package/dist/components/BbColorInput/BbColorInput.vue.d.ts +5 -3
  171. package/dist/components/BbColorInput/BbColorInput.vue_vue_type_script_setup_true_lang.js +6 -0
  172. package/dist/components/BbColorInput/types.d.ts +10 -1
  173. package/dist/components/BbColorPalette/BbColorPalette.vue.d.ts +1 -0
  174. package/dist/components/BbColorPalette/BbColorPalette.vue.js +1 -0
  175. package/dist/components/BbColorPalette/BbColorPalette.vue_vue_type_script_setup_true_lang.js +141 -91
  176. package/dist/components/BbColorPalette/types.d.ts +9 -0
  177. package/dist/components/BbConfirm/BbConfirm.vue_vue_type_script_setup_true_lang.js +73 -69
  178. package/dist/components/BbDatePicker/BbDatePicker.vue.d.ts +1 -0
  179. package/dist/components/BbDatePicker/BbDatePicker.vue_vue_type_script_setup_true_lang.js +108 -99
  180. package/dist/components/BbDatePicker/types.d.ts +64 -21
  181. package/dist/components/BbDatePickerInput/BbDatePickerInput.vue_vue_type_script_setup_true_lang.js +3 -3
  182. package/dist/components/BbDatePickerInput/types.d.ts +22 -8
  183. package/dist/components/BbDialog/BbDialog.vue_vue_type_script_setup_true_lang.js +79 -81
  184. package/dist/components/BbDropdown/AdaptiveDropdown.vue_vue_type_script_setup_true_lang.js +92 -62
  185. package/dist/components/BbDropdown/BbDropdown.vue_vue_type_script_setup_true_lang.js +243 -216
  186. package/dist/components/BbDropdown/BbDropdownList.vue_vue_type_script_setup_true_lang.js +301 -231
  187. package/dist/components/BbDropdown/normalizeGroups.d.ts +9 -0
  188. package/dist/components/BbDropdown/normalizeGroups.js +2 -2
  189. package/dist/components/BbDropdown/useDropdownContext.d.ts +26 -0
  190. package/dist/components/BbDropzone/BbDropzone.vue.d.ts +2 -2
  191. package/dist/components/BbDropzone/BbDropzone.vue_vue_type_script_setup_true_lang.js +1 -1
  192. package/dist/components/BbDropzone/types.d.ts +2 -2
  193. package/dist/components/BbIcon/BbIcon.vue_vue_type_script_setup_true_lang.js +15 -10
  194. package/dist/components/BbNumberInput/BbNumberInput.vue.d.ts +2 -2
  195. package/dist/components/BbNumberInput/types.d.ts +1 -1
  196. package/dist/components/BbOffCanvas/BbOffCanvas.vue_vue_type_script_setup_true_lang.js +154 -156
  197. package/dist/components/BbOffCanvas/useOffCanvasStack.d.ts +10 -0
  198. package/dist/components/BbPagination/BbPagination.vue_vue_type_script_setup_true_lang.js +84 -90
  199. package/dist/components/BbPopover/BbPopover.vue_vue_type_script_setup_true_lang.js +10 -10
  200. package/dist/components/BbProgress/BbProgress.vue_vue_type_script_setup_true_lang.js +2 -2
  201. package/dist/components/BbRadio/BbRadio.vue.d.ts +2 -2
  202. package/dist/components/BbRadio/BbRadio.vue_vue_type_script_setup_true_lang.js +49 -48
  203. package/dist/components/BbRadio/types.d.ts +8 -3
  204. package/dist/components/BbRadioGroup/BbRadioGroup.vue_vue_type_script_setup_true_lang.js +40 -39
  205. package/dist/components/BbRadioGroup/types.d.ts +8 -3
  206. package/dist/components/BbRating/BbRating.vue.d.ts +2 -2
  207. package/dist/components/BbRating/types.d.ts +2 -2
  208. package/dist/components/BbSelect/types.d.ts +8 -6
  209. package/dist/components/BbSelectPopover/BbSelectPopover.vue_vue_type_script_setup_true_lang.js +302 -277
  210. package/dist/components/BbSelectPopover/types.d.ts +7 -4
  211. package/dist/components/BbSlider/BbSlider.vue.d.ts +2 -2
  212. package/dist/components/BbSlider/types.d.ts +1 -1
  213. package/dist/components/BbSwitch/BbSwitch.vue.d.ts +2 -2
  214. package/dist/components/BbTable/BbTable.vue.d.ts +1 -1
  215. package/dist/components/BbTable/BbTable.vue_vue_type_script_setup_true_lang.js +267 -251
  216. package/dist/components/BbTable/types.d.ts +43 -11
  217. package/dist/components/BbTag/BbTag.vue.d.ts +2 -2
  218. package/dist/components/BbTag/BbTag.vue_vue_type_script_setup_true_lang.js +5 -3
  219. package/dist/components/BbTag/types.d.ts +1 -1
  220. package/dist/components/BbTextInput/BbTextInput.vue.d.ts +2 -2
  221. package/dist/components/BbTextInput/types.d.ts +1 -1
  222. package/dist/components/BbTextarea/BbTextarea.vue.d.ts +2 -2
  223. package/dist/components/BbTextarea/types.d.ts +1 -1
  224. package/dist/components/BbTimePickerInput/types.d.ts +1 -1
  225. package/dist/components/BbToast/BbToastRegion.vue_vue_type_script_setup_true_lang.js +70 -68
  226. package/dist/components/BbTree/BbTreeLevel.vue_vue_type_script_setup_true_lang.js +8 -8
  227. package/dist/components/CommonPopover/CommonPopover.vue_vue_type_script_setup_true_lang.js +73 -76
  228. package/dist/components/FlatListBox/FlatListBox.vue_vue_type_script_setup_true_lang.js +107 -103
  229. package/dist/components/FlatListBox/types.d.ts +7 -1
  230. package/dist/components/GroupedListBox/GroupedListBox.vue_vue_type_script_setup_true_lang.js +138 -131
  231. package/dist/components/GroupedListBox/types.d.ts +9 -2
  232. package/dist/components/ListBox/ListBox.vue_vue_type_script_setup_true_lang.js +5 -0
  233. package/dist/components/ListBox/types.d.ts +7 -1
  234. package/dist/composables/useBaseOptions.d.ts +4 -1
  235. package/dist/composables/useBaseOptions.js +22 -9
  236. package/dist/composables/useBbTableContext.d.ts +10 -10
  237. package/dist/composables/useBbTableContext.js +13 -13
  238. package/dist/composables/useBbTabsContext.js +1 -1
  239. package/dist/composables/useCoarsePointer.d.ts +9 -0
  240. package/dist/composables/useCoarsePointer.js +13 -0
  241. package/dist/composables/useHydrated.d.ts +7 -0
  242. package/dist/composables/useHydrated.js +9 -0
  243. package/dist/composables/useImeDismissBlur.d.ts +103 -0
  244. package/dist/composables/useImeDismissBlur.js +38 -0
  245. package/dist/composables/useItemsGetter.d.ts +1 -1
  246. package/dist/composables/useItemsGetter.js +18 -18
  247. package/dist/composables/useMobile.d.ts +6 -0
  248. package/dist/composables/useMobile.js +12 -5
  249. package/dist/composables/useQuery.d.ts +14 -2
  250. package/dist/composables/useQuery.js +2 -2
  251. package/dist/composables/useSafeArea.d.ts +96 -48
  252. package/dist/composables/useSafeArea.js +28 -13
  253. package/dist/composables/useSafeAreaInternal.d.ts +79 -0
  254. package/dist/composables/useSafeAreaInternal.js +41 -0
  255. package/dist/composables/useSegmentedFields.js +16 -10
  256. package/dist/composables/useSheetSurface.d.ts +39 -0
  257. package/dist/composables/useSheetSurface.js +10 -0
  258. package/dist/composables/useTableWidthContext.js +1 -1
  259. package/dist/composables/useViewportWidth.d.ts +18 -1
  260. package/dist/composables/useViewportWidth.js +5 -2
  261. package/dist/deprecation/ai-deprecations.json.d.ts +22 -0
  262. package/dist/deprecation/ai-deprecations.json.js +1 -1
  263. package/dist/directives/bbDate.d.ts +15 -6
  264. package/dist/i18n/locales/cs.json +14 -2
  265. package/dist/i18n/locales/da.json +14 -2
  266. package/dist/i18n/locales/de.json +14 -2
  267. package/dist/i18n/locales/el.json +14 -2
  268. package/dist/i18n/locales/en.json +14 -2
  269. package/dist/i18n/locales/es.json +14 -2
  270. package/dist/i18n/locales/fi.json +14 -2
  271. package/dist/i18n/locales/fr.json +14 -2
  272. package/dist/i18n/locales/hu.json +14 -2
  273. package/dist/i18n/locales/it.json +14 -2
  274. package/dist/i18n/locales/ja.json +14 -2
  275. package/dist/i18n/locales/ko.json +14 -2
  276. package/dist/i18n/locales/nb.json +14 -2
  277. package/dist/i18n/locales/nl.json +14 -2
  278. package/dist/i18n/locales/pl.json +14 -2
  279. package/dist/i18n/locales/pt.json +14 -2
  280. package/dist/i18n/locales/ro.json +14 -2
  281. package/dist/i18n/locales/ru.json +14 -2
  282. package/dist/i18n/locales/sv.json +14 -2
  283. package/dist/i18n/locales/tr.json +14 -2
  284. package/dist/i18n/locales/uk.json +14 -2
  285. package/dist/i18n/locales/zh-cn.json +14 -2
  286. package/dist/index.d.ts +2 -0
  287. package/dist/index.js +48 -47
  288. package/dist/llms-full.txt +4961 -821
  289. package/dist/llms-medium.txt +239 -51
  290. package/dist/llms.txt +8 -4
  291. package/dist/locale-blueprint.json +14 -2
  292. package/dist/locale-registry.d.ts +0 -21
  293. package/dist/styles.css +1 -1
  294. package/dist/types/Config.d.ts +9 -6
  295. package/dist/types/DatePickerType.d.ts +32 -0
  296. package/dist/types/DatePickerType.js +4 -0
  297. package/dist/utilities/functions/convertDateValue.d.ts +13 -0
  298. package/dist/utilities/functions/convertDateValue.js +13 -8
  299. package/dist/utilities/functions/isDateDisabled.d.ts +3 -0
  300. package/dist/utilities/functions/isDateDisabled.js +17 -15
  301. package/dist/utilities/functions/normalizeDateBound.d.ts +20 -0
  302. package/dist/utilities/functions/normalizeDateBound.js +12 -0
  303. package/dist/utilities/functions/parsePaginationNumber.d.ts +22 -0
  304. package/dist/utilities/functions/parsePaginationNumber.js +11 -0
  305. package/dist/utilities/misc/listboxMetrics.d.ts +41 -0
  306. package/dist/utilities/misc/listboxMetrics.js +4 -0
  307. package/dist/utils/overlayEscapeStack.d.ts +14 -0
  308. package/dist/{components/BbPopover/escapeStack.js → utils/overlayEscapeStack.js} +2 -2
  309. package/dist/utils/overlaySurfaceIsolation.d.ts +1 -0
  310. package/dist/utils/overlaySurfaceIsolation.js +11 -0
  311. package/dist/validated/BbColorInput.vue.d.ts +1 -0
  312. package/dist/validated/BbColorInput.vue_vue_type_script_setup_true_lang.js +4 -0
  313. package/dist/validated/BbDatePickerInput.vue_vue_type_script_setup_true_lang.js +1 -1
  314. package/dist/vite-plugin.d.ts +37 -0
  315. package/dist/vite.js +280 -128
  316. package/llms.txt +8 -4
  317. package/package.json +23 -11
  318. package/scripts/lib/eslint-plugin.mjs +409 -103
  319. package/scripts/lib/mcp-config.mjs +36 -1
  320. package/scripts/lib/validate-bb-markup.mjs +538 -6
  321. package/bin/bitboss-ui.node.test.mjs +0 -113
  322. package/dist/components/BbPopover/escapeStack.d.ts +0 -6
  323. package/scripts/lib/__fixtures__/validated-manifest.json +0 -65
  324. package/scripts/lib/eslint-plugin-autofix.node.test.mjs +0 -109
  325. package/scripts/lib/eslint-plugin-recommended.node.test.mjs +0 -87
  326. package/scripts/lib/eslint-plugin-slots.node.test.mjs +0 -271
  327. package/scripts/lib/eslint-plugin.node.test.mjs +0 -193
package/README.md CHANGED
@@ -18,15 +18,16 @@ Published artifacts are **`dist/`** (ESM JavaScript, `.d.ts`, and **`index.css`*
18
18
 
19
19
  ### Composables
20
20
 
21
- | Composable | Role |
22
- | ----------------------------- | --------------------------------------------------------- |
23
- | `useBbConfig` | Global options for the kit (locale, defaults, etc.). |
24
- | `useBroadcastChannelInstance` | Shared `BroadcastChannel` helper for cross-tab messaging. |
25
- | `useConfirm` | Programmatic confirm / modal flows. |
26
- | `useCountdown` | Countdown timer state. |
27
- | `useMobile` | Mobile / viewport-oriented behaviour. |
28
- | `useQueue` | Simple async task queue. |
29
- | `useToast` | Toast notifications API. |
21
+ | Composable | Role |
22
+ | ----------------------------- | ---------------------------------------------------------- |
23
+ | `useBbConfig` | Global options for the kit (locale, defaults, etc.). |
24
+ | `useBroadcastChannelInstance` | Shared `BroadcastChannel` helper for cross-tab messaging. |
25
+ | `useConfirm` | Programmatic confirm / modal flows. |
26
+ | `useCountdown` | Countdown timer state. |
27
+ | `useMobile` | Mobile / viewport-oriented behaviour. |
28
+ | `useQueue` | Simple async task queue. |
29
+ | `useSafeArea` | Claim a screen edge for a docked panel so toasts avoid it. |
30
+ | `useToast` | Toast notifications API. |
30
31
 
31
32
  ### Base\* components (primitives) _(reference-only - prefer `Bb*` equivalents for consumer code)_
32
33
 
@@ -206,7 +207,8 @@ markup) instead of reading files blind:
206
207
  npx bitboss-ui ai-init --mcp
207
208
  ```
208
209
 
209
- The agent harness launches the server itself (`npx bitboss-ui mcp`) on demand —
210
+ The agent harness launches the server itself (`npx bitboss-ui@<installed version> mcp`,
211
+ pinned so npx can never fall back to fetching a different version from the registry) on demand —
210
212
  you never run it by hand. `--mcp` merges the server entry into each harness's
211
213
  own config (never overwriting other servers you've registered), and each write
212
214
  is idempotent:
@@ -17,7 +17,7 @@
17
17
  import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
18
18
  import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
19
19
  import { existsSync, readFileSync, readdirSync } from 'node:fs';
20
- import { dirname, join } from 'node:path';
20
+ import { dirname, join, sep } from 'node:path';
21
21
  import { fileURLToPath } from 'node:url';
22
22
  import { z } from 'zod';
23
23
  import {
@@ -257,7 +257,7 @@ function* eachTokenDeclaration(css) {
257
257
 
258
258
  /**
259
259
  * `list_tokens({ filter })` — the `--bb-*` design tokens with their values,
260
- * read from the shipped stylesheet (the same 89 `check:tokens` counts).
260
+ * read from the shipped stylesheet (the same 90 `check:tokens` counts).
261
261
  *
262
262
  * WHY ONLY `--bb-*` — and why there is no opt-in for the unprefixed ones, even
263
263
  * though `search_components` has `includeReferenceOnly`. The two tiers are not
@@ -405,12 +405,28 @@ function getRecipe({ platform, name, maxChars } = {}) {
405
405
  error: `Unknown platform '${platform}' — expected one of ${RECIPE_PLATFORMS.join(', ')}`,
406
406
  };
407
407
  }
408
- const fileName = String(name ?? '').endsWith('.md')
409
- ? String(name)
410
- : `${name}.md`;
411
- const filePath = join(AI_ROOT, 'recipes', platform, fileName);
412
- if (!existsSync(filePath)) {
413
- return { found: false, error: `Recipe not found: ${platform}/${fileName}` };
408
+ // Contain reads to the platform's recipe dir — no traversal out of the
409
+ // knowledge base. `platform` is already allow-listed above, but `name` is
410
+ // free text, so it gets the same treatment as `get_guide`'s: leading
411
+ // separators stripped, `..` rejected outright, and the joined path checked
412
+ // to still sit under the recipe dir.
413
+ const rel = String(name ?? '').replace(/^\/+/, '');
414
+ if (!rel || rel.includes('..')) {
415
+ return {
416
+ found: false,
417
+ error: `Invalid recipe name '${name}'.`,
418
+ hint: 'Call list_recipes for the available names.',
419
+ };
420
+ }
421
+ const fileName = rel.endsWith('.md') ? rel : `${rel}.md`;
422
+ const recipesDir = join(AI_ROOT, 'recipes', platform);
423
+ const filePath = join(recipesDir, fileName);
424
+ if (!filePath.startsWith(`${recipesDir}${sep}`) || !existsSync(filePath)) {
425
+ return {
426
+ found: false,
427
+ error: `Recipe not found: ${platform}/${fileName}`,
428
+ hint: 'Call list_recipes for the available names.',
429
+ };
414
430
  }
415
431
  const { content, ...meta } = truncateMarkdown(
416
432
  readFileSync(filePath, 'utf-8'),
@@ -16,7 +16,9 @@
16
16
  * locale Generate a custom locale blueprint (.locale.ts)
17
17
  * check Validate Bb* markup in .vue/.md files against the installed
18
18
  * components.json manifest (unknown props, removed props, bad
19
- * v-models). Exits 1 on findings; supports --json output.
19
+ * v-models, unknown `<template #slot>` names, `href`/`to`/
20
+ * `method` on a component that doesn't declare them). Exits 1
21
+ * on findings; supports --json output.
20
22
  * mcp Start a stdio MCP server exposing the dist/ai knowledge base
21
23
  * (search_components, get_component, list_recipes, get_recipe,
22
24
  * validate) to MCP-capable agent harnesses.
@@ -533,10 +535,11 @@ function summarizeFileCounts(files) {
533
535
  }
534
536
 
535
537
  /**
536
- * `npx bitboss-ui check [glob…] [--json]` — validate `Bb*` markup in `.vue`
537
- * and `.md` files against the installed components.json manifest.
538
+ * `npx bitboss-ui check [glob…] [--json]` — validate `Bb*` markup (props,
539
+ * v-models, and `<template #slot>` names) in `.vue` and `.md` files against
540
+ * the installed components.json manifest.
538
541
  */
539
- function checkCommand(globs, jsonMode) {
542
+ function checkCommand(globs, jsonMode, allowEmpty = false) {
540
543
  const projectRoot = process.cwd();
541
544
 
542
545
  const manifestPath = join(PACKAGE_ROOT, 'dist', 'ai', 'components.json');
@@ -562,12 +565,26 @@ function checkCommand(globs, jsonMode) {
562
565
  }
563
566
 
564
567
  if (jsonMode) {
565
- console.log(JSON.stringify({ findings }, null, 2));
568
+ console.log(JSON.stringify({ findings, files: files.length }, null, 2));
566
569
  if (findings.length > 0) process.exit(1);
570
+ if (files.length === 0 && globs.length > 0 && !allowEmpty) process.exit(1);
567
571
  return;
568
572
  }
569
573
 
570
574
  if (files.length === 0) {
575
+ // An EXPLICIT pattern that matched nothing is almost always a typo'd or
576
+ // stale CI path, and answering it with exit 0 means the step goes green
577
+ // having validated nothing — the check that was meant to catch bad
578
+ // markup is itself the thing that broke, silently (SWP-016). A bare
579
+ // sweep finding nothing is a different, legitimate case (a package with
580
+ // no .vue files yet), so it still passes.
581
+ if (globs.length > 0 && !allowEmpty) {
582
+ console.error(
583
+ `[bitboss-ui] check: no .vue/.md files matched ${globs.map((g) => `\`${g}\``).join(', ')} — nothing was validated. ` +
584
+ 'Fix the path, or pass `--allow-empty` if an empty match is expected.'
585
+ );
586
+ process.exit(1);
587
+ }
571
588
  console.log(
572
589
  '[bitboss-ui] check: no .vue/.md files matched — nothing to do.'
573
590
  );
@@ -576,7 +593,7 @@ function checkCommand(globs, jsonMode) {
576
593
 
577
594
  if (findings.length === 0) {
578
595
  console.log(
579
- `[bitboss-ui] check OK — ${summarizeFileCounts(files)} file(s), zero unknown Bb* props/v-models.`
596
+ `[bitboss-ui] check OK — ${summarizeFileCounts(files)} file(s), zero unknown Bb* props/v-models/slots/nav-attrs.`
580
597
  );
581
598
  return;
582
599
  }
@@ -621,14 +638,19 @@ Commands:
621
638
  server for Claude Code (.mcp.json), Cursor (.cursor/mcp.json),
622
639
  VS Code/Copilot (.vscode/mcp.json), and Windsurf (~/.codeium
623
640
  global) — merges, never overwrites other servers.
624
- check [glob…] [--json]
641
+ check [glob…] [--json] [--allow-empty]
625
642
  Validate \`Bb*\` markup in .vue/.md files against the
626
643
  installed components.json manifest (unknown/removed props,
627
- bad v-models). Defaults to every .vue/.md file under the
628
- current directory (node_modules, dist, .git, vendor,
644
+ bad v-models, unknown \`<template #slot>\` names,
645
+ \`href\`/\`to\`/\`method\` on a component that doesn't declare
646
+ them). Defaults to every .vue/.md file under the current directory
647
+ (node_modules, dist, .git, vendor,
629
648
  storage, public, .output, .nuxt, bootstrap/cache
630
649
  excluded — pass an explicit glob/path to widen the scan).
631
- Exits 1 on findings; \`--json\` prints \`{ findings: [...] }\`.
650
+ Exits 1 on findings, and on an explicit glob that matched
651
+ nothing (a typo'd CI path validates zero files silently) —
652
+ pass \`--allow-empty\` when an empty match is expected.
653
+ \`--json\` prints \`{ findings: [...], files }\`.
632
654
  mcp Start a stdio MCP server exposing the dist/ai knowledge
633
655
  base (search_components, get_component, list_recipes,
634
656
  get_recipe, validate) to MCP-capable agent harnesses.
@@ -674,10 +696,17 @@ switch (command) {
674
696
  const { values, positionals } = parseCommandArgs(
675
697
  command,
676
698
  commandArgs,
677
- { json: { type: 'boolean' } },
699
+ {
700
+ json: { type: 'boolean' },
701
+ 'allow-empty': { type: 'boolean' },
702
+ },
678
703
  { allowPositionals: true }
679
704
  );
680
- checkCommand(positionals, values.json ?? false);
705
+ checkCommand(
706
+ positionals,
707
+ values.json ?? false,
708
+ values['allow-empty'] ?? false
709
+ );
681
710
  break;
682
711
  }
683
712
  case 'mcp': {
@@ -76,6 +76,13 @@ icon as a pair.
76
76
  The default variant is `outline`. `warning` and `destructive` are treated as
77
77
  high-priority for accessibility (see below).
78
78
 
79
+ There is no `success` (or `positive`) variant, and it will not be added — the
80
+ shared status vocabulary is closed to `danger`/`warn` by ruling, see
81
+ [Design Tokens § Brand knobs](./guides/design-tokens.md#brand-knobs-what-a-theme-builder-sets)
82
+ ("state colors are project-owned"). Reach for `primary` for a positive
83
+ confirmation, or register your own variant (below) if the project needs a
84
+ distinct success tone.
85
+
79
86
  #### Registering project variants
80
87
 
81
88
  Variants are an open registry, not a closed enum. The vite/nuxt plugin's
@@ -39,9 +39,14 @@ accessible name.
39
39
 
40
40
  ```vue
41
41
  <div class="flex items-center gap-3">
42
- <BbAvatar size="xl" src="https://i.pravatar.cc/128?img=47" alt="Ada Lovelace" />
43
- <BbAvatar size="xl" alt="Grace Hopper">GH</BbAvatar>
44
- <BbAvatar size="xl" alt="Unknown user" />
42
+ <BbAvatar
43
+ size="56"
44
+ src="https://images.unsplash.com/photo-1494790108377-be9c29b29330?w=256&h=256&fit=crop&crop=faces&auto=format"
45
+ :timeout="4000"
46
+ alt="Ada Lovelace"
47
+ />
48
+ <BbAvatar size="56" alt="Grace Hopper">GH</BbAvatar>
49
+ <BbAvatar size="56" alt="Unknown user" />
45
50
  </div>
46
51
  ```
47
52
 
@@ -56,9 +61,10 @@ sources don't need to be pre-cropped square.
56
61
 
57
62
  ```vue
58
63
  <BbAvatar
59
- size="xl"
60
- srcset="https://i.pravatar.cc/64?img=32 64w, https://i.pravatar.cc/128?img=32 128w"
61
- sizes="36px"
64
+ size="56"
65
+ srcset="https://images.unsplash.com/photo-1580489944761-15a19d654956?w=128&h=128&fit=crop&crop=faces&auto=format 128w, https://images.unsplash.com/photo-1580489944761-15a19d654956?w=256&h=256&fit=crop&crop=faces&auto=format 256w"
66
+ sizes="56px"
67
+ :timeout="4000"
62
68
  alt="Margaret Hamilton"
63
69
  />
64
70
  ```
@@ -70,6 +76,10 @@ library-wide by the `iconDefaultSizes` plugin option), a number (px), a CSS
70
76
  dimension string (`"3rem"`), or a percentage (`"100%"` fills a square parent).
71
77
  The built-in fallback icon scales with the avatar automatically.
72
78
 
79
+ Composed demos below use the larger end of that range (and a few explicit px
80
+ sizes) so faces stay readable in Storybook — `xs`/`sm` are for dense chrome,
81
+ not hero examples.
82
+
73
83
  The fallback surface is **always painted with the primary design token** —
74
84
  `--bb-primary` behind, `--bb-primary-fg` for the initials/icon, the same
75
85
  pairing as a primary button — so initials stay legible in light and dark and
@@ -80,11 +90,11 @@ API: theming happens through the tokens, not a prop.
80
90
 
81
91
  ```vue
82
92
  <div class="flex items-end gap-3">
83
- <BbAvatar size="sm" src="https://i.pravatar.cc/128?img=5" alt="Joan Clarke" />
84
- <BbAvatar size="md" src="https://i.pravatar.cc/128?img=5" alt="Joan Clarke" />
85
- <BbAvatar size="lg" src="https://i.pravatar.cc/128?img=5" alt="Joan Clarke" />
86
- <BbAvatar size="xl" src="https://i.pravatar.cc/128?img=5" alt="Joan Clarke" />
87
- <BbAvatar size="2xl" src="https://i.pravatar.cc/128?img=5" alt="Joan Clarke" />
93
+ <BbAvatar size="md" src="https://images.unsplash.com/photo-1534528741775-53994a69daeb?w=256&h=256&fit=crop&crop=faces&auto=format" :timeout="4000" alt="Joan Clarke" />
94
+ <BbAvatar size="lg" src="https://images.unsplash.com/photo-1534528741775-53994a69daeb?w=256&h=256&fit=crop&crop=faces&auto=format" :timeout="4000" alt="Joan Clarke" />
95
+ <BbAvatar size="xl" src="https://images.unsplash.com/photo-1534528741775-53994a69daeb?w=256&h=256&fit=crop&crop=faces&auto=format" :timeout="4000" alt="Joan Clarke" />
96
+ <BbAvatar size="2xl" src="https://images.unsplash.com/photo-1534528741775-53994a69daeb?w=256&h=256&fit=crop&crop=faces&auto=format" :timeout="4000" alt="Joan Clarke" />
97
+ <BbAvatar size="56" src="https://images.unsplash.com/photo-1534528741775-53994a69daeb?w=256&h=256&fit=crop&crop=faces&auto=format" :timeout="4000" alt="Joan Clarke" />
88
98
  </div>
89
99
  ```
90
100
 
@@ -101,10 +111,15 @@ too, since the dot alone is not announced.
101
111
  ```vue
102
112
  <div class="flex items-center gap-3">
103
113
  <BbIndicator bottom dot variant="success">
104
- <BbAvatar size="md" src="https://i.pravatar.cc/128?img=12" alt="Ada Lovelace — online" />
114
+ <BbAvatar
115
+ size="40"
116
+ src="https://images.unsplash.com/photo-1494790108377-be9c29b29330?w=256&h=256&fit=crop&crop=faces&auto=format"
117
+ :timeout="4000"
118
+ alt="Ada Lovelace — online"
119
+ />
105
120
  </BbIndicator>
106
121
  <BbIndicator bottom dot :style="{ '--bg': 'var(--bb-text-muted)' }">
107
- <BbAvatar size="md" alt="Grace Hopper — away">GH</BbAvatar>
122
+ <BbAvatar size="40" alt="Grace Hopper — away">GH</BbAvatar>
108
123
  </BbIndicator>
109
124
  </div>
110
125
  ```
@@ -142,15 +157,16 @@ separates them with a panel-colored ring (an explicit override of the
142
157
  v-for="reviewer in visible"
143
158
  :key="reviewer.name"
144
159
  :alt="reviewer.name"
145
- size="sm"
160
+ size="40"
146
161
  :src="reviewer.src"
162
+ :timeout="demoAvatarTimeout"
147
163
  >
148
164
  {{ reviewer.initials }}
149
165
  </BbAvatar>
150
166
  <BbAvatar
151
167
  v-if="!expanded && hiddenCount > 0"
152
168
  :alt="`${hiddenCount} more reviewers`"
153
- size="sm"
169
+ size="40"
154
170
  >
155
171
  +{{ hiddenCount }}
156
172
  </BbAvatar>
@@ -161,6 +177,7 @@ separates them with a panel-colored ring (an explicit override of the
161
177
  <script setup lang="ts">
162
178
  import { computed, ref } from 'vue';
163
179
  import { BbAvatar, BbButton } from 'bitboss-ui';
180
+ import { demoAvatarTimeout, demoFaces } from './demoAvatars';
164
181
 
165
182
  type Reviewer = {
166
183
  name: string;
@@ -171,11 +188,11 @@ type Reviewer = {
171
188
  // The overflow indicator is just another avatar with the count in its slot —
172
189
  // same size, same ring, no special markup.
173
190
  const reviewers: Reviewer[] = [
174
- { name: 'Ada Lovelace', src: 'https://i.pravatar.cc/96?img=47' },
191
+ { name: 'Ada Lovelace', src: demoFaces.ada },
175
192
  { name: 'Grace Hopper', initials: 'GH' },
176
- { name: 'Alan Turing', src: 'https://i.pravatar.cc/96?img=13' },
193
+ { name: 'Alan Turing', src: demoFaces.alan },
177
194
  { name: 'Katherine Johnson', initials: 'KJ' },
178
- { name: 'Margaret Hamilton', src: 'https://i.pravatar.cc/96?img=32' },
195
+ { name: 'Margaret Hamilton', src: demoFaces.margaret },
179
196
  ];
180
197
  const maxVisible = 3;
181
198
 
@@ -201,7 +218,7 @@ const hiddenCount = computed(() => reviewers.length - maxVisible);
201
218
  }
202
219
 
203
220
  .stack :deep(.bb-avatar + .bb-avatar) {
204
- margin-left: -6px;
221
+ margin-left: -12px;
205
222
  }
206
223
  </style>
207
224
  ```
@@ -244,7 +261,12 @@ list — the row markup stays identical whether a member has a photo or not.
244
261
  "
245
262
  :variant="member.online ? 'success' : 'default'"
246
263
  >
247
- <BbAvatar :alt="member.name" size="sm" :src="member.src">
264
+ <BbAvatar
265
+ :alt="member.name"
266
+ size="40"
267
+ :src="member.src"
268
+ :timeout="demoAvatarTimeout"
269
+ >
248
270
  {{ member.initials }}
249
271
  </BbAvatar>
250
272
  </BbIndicator>
@@ -262,6 +284,7 @@ list — the row markup stays identical whether a member has a photo or not.
262
284
  <script setup lang="ts">
263
285
  import { computed, ref } from 'vue';
264
286
  import { BbAvatar, BbIndicator, BbButton } from 'bitboss-ui';
287
+ import { demoAvatarTimeout, demoFaces } from './demoAvatars';
265
288
 
266
289
  type Member = {
267
290
  name: string;
@@ -278,7 +301,7 @@ const members: Member[] = [
278
301
  name: 'Ada Lovelace',
279
302
  role: 'Engineering',
280
303
  online: true,
281
- src: 'https://i.pravatar.cc/96?img=47',
304
+ src: demoFaces.ada,
282
305
  },
283
306
  {
284
307
  name: 'Grace Hopper',
@@ -290,7 +313,7 @@ const members: Member[] = [
290
313
  name: 'Alan Turing',
291
314
  role: 'Research',
292
315
  online: false,
293
- src: 'https://i.pravatar.cc/96?img=13',
316
+ src: demoFaces.alan,
294
317
  },
295
318
  {
296
319
  name: 'Katherine Johnson',
@@ -341,8 +364,13 @@ it for you.
341
364
 
342
365
  <ul class="flex flex-col gap-2">
343
366
  <li v-for="entry in feed" :key="entry.id" class="flex items-center gap-2">
344
- <BbAvatar :alt="entry.actor" size="sm" :src="entry.src">
345
- <BbIcon v-if="entry.bot" :icon="releaseBotMark" size="xs" />
367
+ <BbAvatar
368
+ :alt="entry.actor"
369
+ size="40"
370
+ :src="entry.src"
371
+ :timeout="demoAvatarTimeout"
372
+ >
373
+ <BbIcon v-if="entry.bot" :icon="releaseBotMark" size="sm" />
346
374
  <template v-else>{{ entry.initials }}</template>
347
375
  </BbAvatar>
348
376
  <span class="flex min-w-0 flex-1 flex-col">
@@ -365,6 +393,7 @@ import { BbAvatar, BbIcon } from 'bitboss-ui';
365
393
  // brand art that lives in no icon collection. It paints in `currentColor`,
366
394
  // so on the avatar's fallback surface it inherits `--bb-primary-fg`.
367
395
  import releaseBotMark from '@/assets/icons/sparkles.svg?raw';
396
+ import { demoAvatarTimeout, demoFaces } from './demoAvatars';
368
397
 
369
398
  type FeedEntry = {
370
399
  id: number;
@@ -391,7 +420,7 @@ const feed: FeedEntry[] = [
391
420
  actor: 'Ada Lovelace',
392
421
  action: 'approved the release',
393
422
  time: '14 minutes ago',
394
- src: 'https://i.pravatar.cc/96?img=47',
423
+ src: demoFaces.ada,
395
424
  initials: 'AL',
396
425
  },
397
426
  {
@@ -331,6 +331,23 @@ swap the inputs use); and **`icon`** (icon-only) becomes a removable glyph.
331
331
  Active filters are the classic product shape: a chip row, each badge owned by
332
332
  your state, cleared one-by-one or all at once.
333
333
 
334
+ **Size rule — match the pair, don't memorise a constant.** Badge scale is not
335
+ button scale, so the number that looks right depends on the button standing
336
+ next to it. A rail picks **one matched pair** and uses it for every chip:
337
+
338
+ | Badge size | Height | Pairs with button |
339
+ | -------------- | ------ | ------------------------------- |
340
+ | `md` (default) | ≈16px | — (inline token, opens nothing) |
341
+ | `lg` | ≈20px | `xs` |
342
+ | `xl` | ≈24px | `sm` |
343
+ | `2xl` | ≈28px | `md` |
344
+
345
+ So a rail whose Filters trigger is a `sm` button wants `xl` chips; drop the
346
+ trigger to `xs` and the chips go to `lg`. Copying `sm`/`md` from an inline
347
+ example into a rail is what makes chips look toy-sized next to their own
348
+ button. Reserve `sm` for dense in-table status pills, and omit `size`
349
+ (default `md`) only for a plain inline token that opens nothing.
350
+
334
351
  **A removable filter bar**
335
352
 
336
353
  ```vue
@@ -351,7 +368,7 @@ your state, cleared one-by-one or all at once.
351
368
  clearable
352
369
  :clearable-label="`Remove ${filter.label}`"
353
370
  :prepend:icon="filter.icon"
354
- size="sm"
371
+ size="lg"
355
372
  variant="secondary"
356
373
  @click:clear="onClear(filter.id)"
357
374
  >{{ filter.label }}</BbBadge
@@ -484,10 +501,10 @@ press the × to remove. The two actions are two tab stops, which is correct.
484
501
 
485
502
  ```vue
486
503
  <div class="flex flex-wrap items-center gap-2">
487
- <BbBadge clearable prepend:icon="lucide:tag" variant="secondary">
504
+ <BbBadge clearable prepend:icon="lucide:tag" size="xl" variant="secondary">
488
505
  <BbBadgeButton @click="() => {}">Label: frontend</BbBadgeButton>
489
506
  </BbBadge>
490
- <BbBadge clearable append:icon="lucide:chevron-down" variant="secondary">
507
+ <BbBadge clearable append:icon="lucide:chevron-down" size="xl" variant="secondary">
491
508
  <BbBadgeButton @click="() => {}">Priority: high</BbBadgeButton>
492
509
  </BbBadge>
493
510
  </div>
@@ -528,7 +545,7 @@ anchor an overlay directly — no wrapper element, no `defineExpose`:
528
545
  clearable
529
546
  clearable-label="Remove status filter"
530
547
  prepend:icon="lucide:circle-dot"
531
- size="sm"
548
+ size="lg"
532
549
  variant="secondary"
533
550
  @click:clear="status = 'Open'"
534
551
  >
@@ -207,7 +207,8 @@ destination onto these props instead of an `@click` handler:
207
207
 
208
208
  - **`href`** — renders an `<a>`; in an Inertia app a same-origin `href` (no
209
209
  `target`) upgrades to an Inertia visit. `target` forces a plain anchor, and
210
- `target="_blank"` automatically merges `noopener noreferrer` into `rel`.
210
+ any target other than `_self` (`_blank`, named windows, …) automatically
211
+ merges `noopener noreferrer` into `rel`.
211
212
  - **`to`** — a Vue Router `RouteLocationRaw`, rendered as a router/Nuxt link.
212
213
  - **`replace`** — history replacement (`router.replace` under Vue Router, a
213
214
  replace visit under Inertia).
@@ -418,9 +419,13 @@ const sent = ref(false);
418
419
 
419
420
  ### Gotchas & anti-patterns
420
421
 
421
- - Don't use it just to get a plain-looking button that's `variant="ghost"` /
422
- `variant="link"` on `BbButton`. Reach for the base only to escape button
423
- chrome entirely.
422
+ - Don't use it just to get a plain-looking **standalone** button among other
423
+ buttons — that's `variant="ghost"` / `variant="link"` on `BbButton`. But **do**
424
+ use it for an **inline** link — a record-identity cell, an in-text link, a
425
+ property-grid value: `variant="link"` keeps the button box (height + padding)
426
+ and breaks the line, whereas `BbBaseButton` + your own link class (e.g.
427
+ `.plain-link`) flows inline. Reach for the base to escape button chrome
428
+ entirely — including whenever the link must sit inline in text.
424
429
  - `to` and Inertia links need their framework present; without a router a `to`
425
430
  link can't resolve. Use `href` for router-free contexts.
426
431
  - `tag="div"`/`tag="span"` throws away native button semantics — only do it when a
@@ -438,7 +443,8 @@ const sent = ref(false);
438
443
  leave the tab order — communicated to assistive tech without vanishing.
439
444
  - **Exact-active** links expose `aria-current` (default `page`) on every
440
445
  platform — Vue Router, Inertia, and plain apps.
441
- - **`target="_blank"`** is secured with `rel="noopener noreferrer"` automatically.
446
+ - **Any `target` other than `_self`** (`_blank`, named windows, …) is secured
447
+ with `rel="noopener noreferrer"` automatically.
442
448
  - **Provide a visible focus style** and, if you use a non-`button` `tag`, restore
443
449
  the keyboard interaction the native element would have given you.
444
450
 
@@ -16,6 +16,7 @@
16
16
 
17
17
  | Prop | Type | Default | Required | Description |
18
18
  | --- | --- | --- | --- | --- |
19
+ | `adaptive` | `boolean \| undefined` | `undefined` | | When `true`, the palette opens as a bottom off-canvas sheet on mobile viewports instead of a floating popover. Forwarded to `BbColorPalette`, which resolves the fallback. When unset, falls back to the global `config.adaptive`. |
19
20
  | `alpha` | `boolean \| undefined` | `false` | | Enable the alpha channel. When true the picker shows an opacity slider and emits / accepts `#RRGGBBAA` hex8 values. |
20
21
  | `append:icon` | `string \| undefined` | | | Name of the icon to render at the right hand side of the input. |
21
22
  | `ariaDescribedby` | `string \| undefined` | | | Id(s) of element(s) describing this input for assistive tech (space-separated). Typically includes the container hint id if used within a BaseInputContainer. |
@@ -18,7 +18,7 @@
18
18
  | --- | --- | --- | --- | --- |
19
19
  | `disabled` | `boolean \| undefined` | | | Disables the component. |
20
20
  | `firstDayOfWeek` | `0 \| 1 \| 2 \| 3 \| 4 \| 5 \| 6 \| undefined` | `1` | | Defines the first day of the week with `0` meaning Sunday and `6` meaning Saturday. |
21
- | `floating` | `boolean \| undefined` | | | If true the date will have a format YYYY-MM-DD instead of the default ISO string. |
21
+ | `floating` | `boolean \| undefined` | | | If true the value is a plain calendar string (`YYYY-MM-DD`, or the shape `type` dictates) instead of the default ISO instant. |
22
22
  | `id` | `string \| undefined` | | | The identifier of the component. |
23
23
  | `max` | `string \| undefined` | | | Maximum selectable date. |
24
24
  | `min` | `string \| undefined` | | | Minimum selectable date. |
@@ -26,7 +26,8 @@
26
26
  | `multiple` | `boolean \| undefined` | | | Allows the selection of multiple items. |
27
27
  | `range` | `boolean \| undefined` | | | Selects a range of dates between two dates. It selects all of the days between start and end. |
28
28
  | `readonly` | `boolean \| undefined` | | | Sets the input in a readonly state. |
29
- | `selectable` | `((date: string) => boolean) \| undefined` | | | Function that accepts a date string and returns a boolean. Returning `false` means the date cannot be selected. |
29
+ | `selectable` | `((date: string) => boolean) \| undefined` | | | Function that accepts a date string and returns a boolean. Returning `false` means the date cannot be selected. The string is shaped by `type`: `YYYY-MM` under `month`, `YYYY` under `year`. |
30
+ | `type` | `DatePickerType \| undefined` | `"date"` | | What the grid selects: a day (`date`/`datetime`), a month, or a year. The coarse types make the month/year panel terminal instead of a navigation step, and emit `YYYY-MM` / `YYYY`. |
30
31
  | `utc` | `boolean \| undefined` | | | Emits values as UTC ISO strings (`...Z`) instead of ISO strings carrying the local offset (`...+01:00`). Emission-only: incoming values are parsed identically either way, so the prop can be added or removed without touching stored values. I… |
31
32
 
32
33
  ## Events
@@ -18,14 +18,13 @@
18
18
  | Prop | Type | Default | Required | Description |
19
19
  | --- | --- | --- | --- | --- |
20
20
  | `adaptive` | `boolean \| undefined` | `undefined` | | On mobile the calendar opens inside a bottom off-canvas sheet instead of a floating popover, mirroring the adaptive behaviour of `BbPopover`/`BbSelectPopover`. When unset, falls back to the global `config.adaptive`. |
21
- | `ampm` | `boolean \| undefined` | | | 12-hour display with an AM/PM segment (requires `datetime`). Purely a field-composition concern: `modelValue` and the `time` model stay 24-hour regardless. Type `A`/`P` (or ArrowUp/Down) to set the meridiem. |
21
+ | `ampm` | `boolean \| undefined` | | | 12-hour display with an AM/PM segment (requires `type="datetime"`). Purely a field-composition concern: `modelValue` and the `time` model stay 24-hour regardless. Type `A`/`P` (or ArrowUp/Down) to set the meridiem. |
22
22
  | `append:icon` | `string \| undefined` | | | Name of the icon to render at the right hand side of the input. |
23
23
  | `ariaDescribedby` | `string \| undefined` | | | Additional description id(s) announced by assistive technologies. Usually provided by an outer input container to link hint/error text. |
24
24
  | `autocomplete` | `string \| undefined` | `"off"` | | Browser autocomplete hint for the input. |
25
25
  | `autofocus` | `Booleanish \| undefined` | | | Focus the first text field automatically when the component mounts. |
26
26
  | `clearable` | `boolean \| undefined` | | | Displays a clear button whenever a value is present and the control is interactive. |
27
27
  | `compact` | `boolean \| undefined` | | | Applies the compact density styles to the control. |
28
- | `datetime` | `boolean \| undefined` | | | Adds time selection beside date selection: `HH:mm` segments in the text field (24-hour) and time columns under the calendar. A picked or typed date with a blank time commits at `00:00`. Non-floating values carry the time inside `modelValue`… |
29
28
  | `disableCalendar` | `boolean \| "mobile" \| "desktop" \| undefined` | `false` | | Disables the calendar: hides the trigger button and prevents the popover from opening. Use `'desktop'` to disable it on desktop only (keyboard-first there, calendar-first on mobile — complementing `disableWriting: 'mobile'`) or `'mobile'` t… |
30
29
  | `disabled` | `boolean \| undefined` | | | Disables the input, calendar trigger, and popover. |
31
30
  | `disableWriting` | `boolean \| "mobile" \| "desktop" \| undefined` | `false` | | Controls whether manual typing is disabled inside the text fields. Use `'mobile'` to disable typing only on mobile, `'desktop'` to disable typing only on desktop. Applies to both single and range modes. |
@@ -35,8 +34,8 @@
35
34
  | `hasWarning` | `boolean \| undefined` | | | Apply warning styling (same chrome as errors, `--bb-warn` color). Suppressed when `hasErrors` is also set. |
36
35
  | `id` | `string \| undefined` | | | Explicit id for the input element. Falls back to an auto-generated `bdpi-<uid>` value. |
37
36
  | `loading` | `boolean \| undefined` | | | Shows loading visuals on the input. |
38
- | `max` | `string \| undefined` | | | Maximum selectable date in `YYYY-MM-DD` format — or, with `datetime`, `YYYY-MM-DDTHH:mm` to tighten the boundary day to a minute. Values outside both patterns throw during setup to surface configuration mistakes. |
39
- | `min` | `string \| undefined` | | | Minimum selectable date in `YYYY-MM-DD` format — or, with `datetime`, `YYYY-MM-DDTHH:mm` to tighten the boundary day to a minute. Values outside both patterns throw during setup to surface configuration mistakes. |
37
+ | `max` | `string \| undefined` | | | Maximum selectable date in `YYYY-MM-DD` format — or, with `type="datetime"`, `YYYY-MM-DDTHH:mm` to tighten the boundary day to a minute. Values outside both patterns throw during setup to surface configuration mistakes. |
38
+ | `min` | `string \| undefined` | | | Minimum selectable date in `YYYY-MM-DD` format — or, with `type="datetime"`, `YYYY-MM-DDTHH:mm` to tighten the boundary day to a minute. Values outside both patterns throw during setup to surface configuration mistakes. |
40
39
  | `modelValue` | `string \| string[] \| null` | | yes | v-model value. Use `null` for empty, a single string for single selection, or a two-element string array (`[start, end]`) when `range` is true. |
41
40
  | `name` | `string \| undefined` | | | Name attribute forwarded to the native inputs. In single mode fields are named `${name}-day`, `${name}-month`, `${name}-year`; in range mode they are prefixed with the segment (`${name}-start-day`, `${name}-end-day`, …). |
42
41
  | `offCanvasProps` | `Partial<BbOffCanvasProps> \| undefined` | | | Extra props forwarded to the `BbOffCanvas` sheet when `adaptive` is active on mobile (e.g. `title`, `size`, `persistent`). |
@@ -45,11 +44,12 @@
45
44
  | `range` | `boolean \| undefined` | | | Enables range selection. When active, v-model expects a two-element array `[start, end]`. Users can still type into the start and end segments unless `disableWriting` disables typing. |
46
45
  | `readonly` | `boolean \| undefined` | | | Makes the text fields read-only and prevents opening the calendar. |
47
46
  | `required` | `boolean \| undefined` | | | Marks the inputs as required to the browser. |
48
- | `seconds` | `boolean \| undefined` | | | Adds the seconds segment (requires `datetime`). Without it, an incoming value carrying seconds displays truncated and is left untouched until the user commits an edit, at which point seconds zero out. |
47
+ | `seconds` | `boolean \| undefined` | | | Adds the seconds segment (requires `type="datetime"`). Without it, an incoming value carrying seconds displays truncated and is left untouched until the user commits an edit, at which point seconds zero out. |
49
48
  | `selectable` | `((date: string) => boolean) \| undefined` | | | Predicate invoked for each candidate date. Return `false` to disable selection for that value. |
50
- | `step` | `number \| undefined` | | | Minute granularity for the calendar's minute column and arrow stepping (requires `datetime`). Constrains what the component produces, never what it accepts: a typed off-grid value (e.g. `10:07` with `step: 15`) is emitted verbatim, and no c… |
49
+ | `step` | `number \| undefined` | | | Minute granularity for the calendar's minute column and arrow stepping (requires `type="datetime"`). Constrains what the component produces, never what it accepts: a typed off-grid value (e.g. `10:07` with `step: 15`) is emitted verbatim, a… |
51
50
  | `time` | `string \| string[] \| null \| undefined` | | | Companion model for the time part (`v-model:time`), always 24-hour `HH:mm` / `HH:mm:ss` regardless of display. With `floating` it is the only carrier of the time; otherwise it mirrors the time inside `modelValue` (same digits) and writing i… |
52
51
  | `transitionDuration` | `number \| undefined` | | | Transition duration, in milliseconds, for the popover appearance. |
52
+ | `type` | `DatePickerType \| undefined` | `"date"` | | What the field edits, and therefore its segments and emitted shape. - `date` (default) — `DD/MM/YYYY`. - `datetime` — adds the time segments and the calendar's time rail. - `month` — `MM/YYYY`, emitting `YYYY-MM`. - `year` — `YYYY`, emittin… |
53
53
  | `utc` | `boolean \| undefined` | | | Emits values as UTC ISO strings (`...Z`) instead of ISO strings carrying the local offset (`...+01:00`). Emission-only: incoming values are parsed identically either way, so the prop can be added or removed without touching stored values. F… |
54
54
 
55
55
  ## Events
@@ -36,7 +36,7 @@
36
36
  | `reverse` | `boolean \| undefined` | `false` | | Swap the label and input columns. |
37
37
  | `showHint` | `boolean \| undefined` | | | Keep the hint permanently visible, regardless of focus. |
38
38
  | `tag` | `ContainerTag \| undefined` | `"span"` | | Element used for the inner wrapper: `span` (default) to remain inline, `div` for a block wrapper, `fieldset` for grouped controls (pair it with `labelTag="legend"`), or `label` to make the whole wrapper activate the control. |
39
- | `warnings` | `string \| string[] \| undefined` | | | Warning messages displayed beneath the input, in their own `aria-live` region. Accepts a string or array; values are rendered one per line, in `--bb-warn` amber. A non-empty list implies the warning state (mirroring how `errors` implies the… |
39
+ | `warnings` | `string \| string[] \| undefined` | | | Warning messages displayed beneath the input, in their own `aria-live` region. Accepts a string or array; values are rendered one per line, in `--bb-text-warn` amber (the text-contrast half of the warning pair the chrome stays on `--bb-wa… |
40
40
 
41
41
  ## Events
42
42
 
@@ -44,7 +44,7 @@
44
44
  - `pointerdown` — `(event: "pointerdown", event: PointerEvent): void`
45
45
  - `pointermove` — `(event: "pointermove", event: PointerEvent): void`
46
46
  - `pointerup` — `(event: "pointerup", event: PointerEvent): void`
47
- - `update:modelValue` — `(event: "update:modelValue", event: number \| number[]): void`
47
+ - `update:modelValue` — `(event: "update:modelValue", value: number \| number[]): void`
48
48
 
49
49
  ## Slots
50
50