bitboss-ui 3.0.0-alpha.1 → 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 (467) hide show
  1. package/README.md +43 -14
  2. package/bin/bitboss-ui-mcp.mjs +146 -25
  3. package/bin/bitboss-ui.mjs +140 -27
  4. package/dist/ai/BbAccordion.md +14 -8
  5. package/dist/ai/BbAlert.md +14 -4
  6. package/dist/ai/BbAvatar.md +67 -34
  7. package/dist/ai/BbBadge.md +29 -10
  8. package/dist/ai/BbBaseButton.md +17 -9
  9. package/dist/ai/BbBaseCheckbox.md +1 -1
  10. package/dist/ai/BbBaseCheckboxIcon.md +8 -6
  11. package/dist/ai/BbBaseColorInput.md +2 -1
  12. package/dist/ai/BbBaseDatePicker.md +3 -2
  13. package/dist/ai/BbBaseDatePickerInput.md +6 -6
  14. package/dist/ai/BbBaseInputContainer.md +5 -5
  15. package/dist/ai/BbBaseRadioGroup.md +1 -0
  16. package/dist/ai/BbBaseRadioIcon.md +11 -7
  17. package/dist/ai/BbBaseSelect.md +1 -1
  18. package/dist/ai/BbBaseSlider.md +1 -1
  19. package/dist/ai/BbBaseSwitch.md +1 -1
  20. package/dist/ai/BbBaseSwitchIcon.md +9 -7
  21. package/dist/ai/BbBreadcrumbs.md +22 -11
  22. package/dist/ai/BbButton.md +113 -24
  23. package/dist/ai/BbCheckbox.md +36 -23
  24. package/dist/ai/BbCheckboxGroup.md +28 -16
  25. package/dist/ai/BbCollapsible.md +15 -9
  26. package/dist/ai/BbColorInput.md +32 -12
  27. package/dist/ai/BbColorPalette.md +38 -8
  28. package/dist/ai/BbConfirm.md +69 -22
  29. package/dist/ai/BbConfirmPortal.md +1 -1
  30. package/dist/ai/BbDatePicker.md +80 -14
  31. package/dist/ai/BbDatePickerInput.md +83 -28
  32. package/dist/ai/BbDialog.md +21 -13
  33. package/dist/ai/BbDropdown.md +64 -27
  34. package/dist/ai/BbDropdownButton.md +31 -16
  35. package/dist/ai/BbDropzone.md +120 -62
  36. package/dist/ai/BbIcon.md +12 -9
  37. package/dist/ai/BbIndicator.md +5 -5
  38. package/dist/ai/BbNumberInput.md +20 -16
  39. package/dist/ai/BbOffCanvas.md +55 -16
  40. package/dist/ai/BbPagination.md +36 -22
  41. package/dist/ai/BbPopover.md +29 -11
  42. package/dist/ai/BbProgress.md +25 -19
  43. package/dist/ai/BbRadio.md +35 -17
  44. package/dist/ai/BbRadioGroup.md +116 -8
  45. package/dist/ai/BbRating.md +24 -12
  46. package/dist/ai/BbSelect.md +70 -36
  47. package/dist/ai/BbSelectPopover.md +91 -25
  48. package/dist/ai/BbSlider.md +43 -17
  49. package/dist/ai/BbSmoothHeight.md +24 -11
  50. package/dist/ai/BbSpinner.md +3 -3
  51. package/dist/ai/BbSwitch.md +55 -31
  52. package/dist/ai/BbSwitchGroup.md +37 -19
  53. package/dist/ai/BbTable.md +196 -45
  54. package/dist/ai/BbTabs.md +78 -35
  55. package/dist/ai/BbTag.md +40 -17
  56. package/dist/ai/BbTextInput.md +84 -21
  57. package/dist/ai/BbTextarea.md +39 -25
  58. package/dist/ai/BbTimePickerInput.md +14 -8
  59. package/dist/ai/BbToast.md +69 -18
  60. package/dist/ai/BbToastPortal.md +1 -1
  61. package/dist/ai/BbTooltip.md +16 -6
  62. package/dist/ai/BbTree.md +59 -29
  63. package/dist/ai/CommonPopover.md +1 -1
  64. package/dist/ai/FlatListBox.md +2 -1
  65. package/dist/ai/GroupedListBox.md +3 -2
  66. package/dist/ai/ListBox.md +2 -1
  67. package/dist/ai/components.json +272 -162
  68. package/dist/ai/composables/useBbConfig.md +74 -5
  69. package/dist/ai/composables/useBbTableContext.md +15 -12
  70. package/dist/ai/composables/useBbTabsContext.md +1 -1
  71. package/dist/ai/composables/useBroadcastChannelInstance.md +1 -1
  72. package/dist/ai/composables/useConfirm.md +14 -7
  73. package/dist/ai/composables/useCountdown.md +8 -6
  74. package/dist/ai/composables/useSafeArea.md +163 -0
  75. package/dist/ai/composables/useToast.md +17 -9
  76. package/dist/ai/guides/agent-contract.md +119 -1
  77. package/dist/ai/guides/ai-router.md +15 -11
  78. package/dist/ai/guides/app-layout.md +42 -11
  79. package/dist/ai/guides/component-picker.md +71 -28
  80. package/dist/ai/guides/design-language.md +136 -14
  81. package/dist/ai/guides/design-tokens.md +158 -12
  82. package/dist/ai/guides/fetch-items-playbook.md +1 -1
  83. package/dist/ai/guides/floating-bottom-panel.md +44 -105
  84. package/dist/ai/guides/icons-policy.md +1 -1
  85. package/dist/ai/guides/inertia-helpers.md +160 -10
  86. package/dist/ai/guides/inline-edit-playbook.md +43 -1
  87. package/dist/ai/guides/installation-and-plugin-setup.md +88 -7
  88. package/dist/ai/guides/migration/components/bb-checkbox-group.md +14 -13
  89. package/dist/ai/guides/migration/components/bb-checkbox.md +10 -9
  90. package/dist/ai/guides/migration/components/bb-date-picker-input.md +30 -0
  91. package/dist/ai/guides/migration/components/bb-icon.md +1 -1
  92. package/dist/ai/guides/migration/components/bb-offcanvas.md +28 -19
  93. package/dist/ai/guides/migration/components/bb-pagination.md +16 -2
  94. package/dist/ai/guides/migration/components/bb-select-popover.md +1 -0
  95. package/dist/ai/guides/migration/components/bb-select.md +13 -12
  96. package/dist/ai/guides/migration/components/bb-table.md +45 -8
  97. package/dist/ai/guides/migration/v2-to-v3.md +7 -3
  98. package/dist/ai/guides/page-shell.md +142 -239
  99. package/dist/ai/guides/validated-forms.md +1 -1
  100. package/dist/ai/index.md +18 -12
  101. package/dist/ai/recipes/inertia/approvals-inbox.md +84 -37
  102. package/dist/ai/recipes/inertia/command-palette.md +311 -0
  103. package/dist/ai/recipes/inertia/inline-edit-workspace.md +117 -39
  104. package/dist/ai/recipes/inertia/layout-scaffold.md +641 -0
  105. package/dist/ai/recipes/inertia/onboarding.md +60 -34
  106. package/dist/ai/recipes/inertia/ownership-atlas.md +147 -39
  107. package/dist/ai/recipes/inertia/record-form.md +80 -33
  108. package/dist/ai/recipes/inertia/records-workspace.md +460 -146
  109. package/dist/ai/recipes/inertia/upload-center.md +153 -68
  110. package/dist/ai/recipes/inertia/wizard-form.md +56 -33
  111. package/dist/ai/recipes/nuxt/approvals-inbox.md +44 -23
  112. package/dist/ai/recipes/nuxt/command-palette.md +300 -0
  113. package/dist/ai/recipes/nuxt/inline-edit-workspace.md +96 -33
  114. package/dist/ai/recipes/nuxt/layout-scaffold.md +641 -0
  115. package/dist/ai/recipes/nuxt/onboarding.md +60 -34
  116. package/dist/ai/recipes/nuxt/record-form.md +78 -32
  117. package/dist/ai/recipes/nuxt/records-workspace.md +378 -132
  118. package/dist/ai/recipes/nuxt/upload-center.md +95 -48
  119. package/dist/ai/recipes/nuxt/wizard-form.md +56 -33
  120. package/dist/ai/recipes/vue/approvals-inbox.md +44 -23
  121. package/dist/ai/recipes/vue/command-palette.md +297 -0
  122. package/dist/ai/recipes/vue/inline-edit-workspace.md +96 -32
  123. package/dist/ai/recipes/vue/layout-scaffold.md +641 -0
  124. package/dist/ai/recipes/vue/onboarding.md +60 -34
  125. package/dist/ai/recipes/vue/record-form.md +82 -36
  126. package/dist/ai/recipes/vue/records-workspace.md +379 -133
  127. package/dist/ai/recipes/vue/upload-center.md +96 -49
  128. package/dist/ai/recipes/vue/wizard-form.md +56 -33
  129. package/dist/ai/source/BbAccordion.md +2 -1
  130. package/dist/ai/source/BbAlert.md +5 -0
  131. package/dist/ai/source/BbAvatar.md +2 -0
  132. package/dist/ai/source/BbBadge.md +1 -1
  133. package/dist/ai/source/BbBadgeButton.md +1 -1
  134. package/dist/ai/source/BbBaseButton.md +34 -18
  135. package/dist/ai/source/BbBaseCheckbox.md +3 -1
  136. package/dist/ai/source/BbBaseColorInput.md +21 -3
  137. package/dist/ai/source/BbBaseColorPalette.md +3 -3
  138. package/dist/ai/source/BbBaseDatePicker.md +481 -49
  139. package/dist/ai/source/BbBaseDatePickerInput.md +222 -74
  140. package/dist/ai/source/BbBaseInputContainer.md +85 -21
  141. package/dist/ai/source/BbBaseNumberInput.md +2 -0
  142. package/dist/ai/source/BbBaseRadioGroup.md +35 -1
  143. package/dist/ai/source/BbBaseRadioIcon.md +16 -7
  144. package/dist/ai/source/BbBaseSelect.md +12 -4
  145. package/dist/ai/source/BbBaseSlider.md +58 -8
  146. package/dist/ai/source/BbBaseTag.md +7 -1
  147. package/dist/ai/source/BbBaseTextarea.md +26 -2
  148. package/dist/ai/source/BbBaseTimePickerInput.md +19 -1
  149. package/dist/ai/source/BbBreadcrumbs.md +6 -2
  150. package/dist/ai/source/BbButton.md +17 -1
  151. package/dist/ai/source/BbCheckbox.md +9 -2
  152. package/dist/ai/source/BbCheckboxGroup.md +9 -2
  153. package/dist/ai/source/BbCollapsible.md +4 -0
  154. package/dist/ai/source/BbColorInput.md +26 -3
  155. package/dist/ai/source/BbColorPalette.md +138 -10
  156. package/dist/ai/source/BbConfirm.md +32 -2
  157. package/dist/ai/source/BbDatePicker.md +156 -37
  158. package/dist/ai/source/BbDatePickerInput.md +31 -10
  159. package/dist/ai/source/BbDialog.md +36 -9
  160. package/dist/ai/source/BbDropdown.md +249 -44
  161. package/dist/ai/source/BbDropdownButton.md +2 -0
  162. package/dist/ai/source/BbDropdownGroup.md +150 -36
  163. package/dist/ai/source/BbDropzone.md +135 -8
  164. package/dist/ai/source/BbIcon.md +47 -4
  165. package/dist/ai/source/BbIndicator.md +1 -1
  166. package/dist/ai/source/BbNumberInput.md +11 -10
  167. package/dist/ai/source/BbOffCanvas.md +35 -11
  168. package/dist/ai/source/BbPagination.md +11 -15
  169. package/dist/ai/source/BbPopover.md +16 -9
  170. package/dist/ai/source/BbProgress.md +18 -2
  171. package/dist/ai/source/BbRadio.md +30 -7
  172. package/dist/ai/source/BbRadioGroup.md +41 -8
  173. package/dist/ai/source/BbRating.md +10 -3
  174. package/dist/ai/source/BbSelect.md +16 -7
  175. package/dist/ai/source/BbSelectPopover.md +277 -45
  176. package/dist/ai/source/BbSlider.md +9 -2
  177. package/dist/ai/source/BbSmoothHeight.md +4 -0
  178. package/dist/ai/source/BbTable.md +277 -59
  179. package/dist/ai/source/BbTag.md +18 -2
  180. package/dist/ai/source/BbTextInput.md +9 -2
  181. package/dist/ai/source/BbTextarea.md +9 -2
  182. package/dist/ai/source/BbTimePicker.md +5 -1
  183. package/dist/ai/source/BbTimePickerInput.md +12 -3
  184. package/dist/ai/source/BbToast.md +14 -13
  185. package/dist/ai/source/BbTooltip.md +14 -0
  186. package/dist/ai/source/BbTree.md +4 -0
  187. package/dist/ai/source/CommonInputWrapper.md +41 -11
  188. package/dist/ai/source/CommonPopover.md +18 -3
  189. package/dist/ai/source/FlatListBox.md +80 -50
  190. package/dist/ai/source/GroupedListBox.md +96 -35
  191. package/dist/ai/source/ListBox.md +9 -1
  192. package/dist/alert-variants.d.ts +7 -0
  193. package/dist/assets/css/reset.css_inline.js +1 -1
  194. package/dist/badge-variants.d.ts +9 -2
  195. package/dist/button-variants.d.ts +7 -0
  196. package/dist/components/BbAccordion/types.d.ts +2 -1
  197. package/dist/components/BbAlert/types.d.ts +5 -0
  198. package/dist/components/BbAvatar/types.d.ts +2 -0
  199. package/dist/components/BbBadge/types.d.ts +1 -1
  200. package/dist/components/BbBaseButton/BbBaseButton.vue_vue_type_script_setup_true_lang.js +82 -89
  201. package/dist/components/BbBaseButton/RouterComponent.vue_vue_type_script_setup_true_lang.js +13 -12
  202. package/dist/components/BbBaseCheckbox/BbBaseCheckbox.vue.d.ts +2 -2
  203. package/dist/components/BbBaseCheckbox/types.d.ts +3 -1
  204. package/dist/components/BbBaseColorInput/BbBaseColorInput.vue.d.ts +3 -2
  205. package/dist/components/BbBaseColorInput/BbBaseColorInput.vue_vue_type_script_setup_true_lang.js +6 -0
  206. package/dist/components/BbBaseColorInput/types.d.ts +15 -3
  207. package/dist/components/BbBaseColorPalette/types.d.ts +2 -2
  208. package/dist/components/BbBaseDatePicker/BbBaseDatePicker.vue.d.ts +1 -0
  209. package/dist/components/BbBaseDatePicker/BbBaseDatePicker.vue_vue_type_script_setup_true_lang.js +234 -127
  210. package/dist/components/BbBaseDatePicker/BbBaseDatePickerInputDaySelector.vue.d.ts +3 -0
  211. package/dist/components/BbBaseDatePicker/BbBaseDatePickerInputDaySelector.vue_vue_type_script_setup_true_lang.js +73 -66
  212. package/dist/components/BbBaseDatePicker/BbBaseDatePickerMonthSelector.vue_vue_type_script_setup_true_lang.js +87 -38
  213. package/dist/components/BbBaseDatePicker/BbBaseDatePickerYearSelector.vue_vue_type_script_setup_true_lang.js +86 -46
  214. package/dist/components/BbBaseDatePicker/types.d.ts +12 -1
  215. package/dist/components/BbBaseDatePicker/useDatePickerContext.d.ts +29 -0
  216. package/dist/components/BbBaseDatePickerInput/BbBaseDatePickerInput.vue.d.ts +1 -0
  217. package/dist/components/BbBaseDatePickerInput/BbBaseDatePickerInput.vue_vue_type_script_setup_true_lang.js +272 -248
  218. package/dist/components/BbBaseDatePickerInput/types.d.ts +24 -8
  219. package/dist/components/BbBaseInputContainer/BbBaseInputContainer.vue_vue_type_script_setup_true_lang.js +55 -48
  220. package/dist/components/BbBaseInputContainer/types.d.ts +21 -8
  221. package/dist/components/BbBaseNumberInput/BbBaseNumberInput.vue.d.ts +2 -2
  222. package/dist/components/BbBaseNumberInput/BbBaseNumberInput.vue_vue_type_script_setup_true_lang.js +4 -0
  223. package/dist/components/BbBaseRadio/BbBaseRadio.vue.d.ts +2 -2
  224. package/dist/components/BbBaseRadioGroup/BbBaseRadioGroup.vue_vue_type_script_setup_true_lang.js +60 -55
  225. package/dist/components/BbBaseRadioGroup/types.d.ts +8 -0
  226. package/dist/components/BbBaseRating/BbBaseRating.vue.d.ts +2 -2
  227. package/dist/components/BbBaseSelect/BbBaseSelect.vue_vue_type_script_setup_true_lang.js +105 -104
  228. package/dist/components/BbBaseSelect/types.d.ts +4 -1
  229. package/dist/components/BbBaseSlider/BbBaseSlider.vue.d.ts +2 -2
  230. package/dist/components/BbBaseSlider/BbBaseSlider.vue_vue_type_script_setup_true_lang.js +181 -169
  231. package/dist/components/BbBaseSlider/types.d.ts +7 -7
  232. package/dist/components/BbBaseSwitch/BbBaseSwitch.vue.d.ts +2 -2
  233. package/dist/components/BbBaseTag/BbBaseTag.vue.d.ts +2 -2
  234. package/dist/components/BbBaseTag/BbBaseTag.vue_vue_type_script_setup_true_lang.js +1 -1
  235. package/dist/components/BbBaseTextInput/BbBaseTextInput.vue.d.ts +2 -2
  236. package/dist/components/BbBaseTextarea/BbBaseTextarea.vue.d.ts +2 -2
  237. package/dist/components/BbBaseTextarea/BbBaseTextarea.vue_vue_type_script_setup_true_lang.js +23 -11
  238. package/dist/components/BbBaseTimePickerInput/BbBaseTimePickerInput.vue_vue_type_script_setup_true_lang.js +117 -112
  239. package/dist/components/BbBreadcrumbs/types.d.ts +4 -0
  240. package/dist/components/BbButton/BbButton.vue_vue_type_script_setup_true_lang.js +49 -45
  241. package/dist/components/BbCheckbox/BbCheckbox.vue.d.ts +2 -2
  242. package/dist/components/BbCheckbox/types.d.ts +9 -2
  243. package/dist/components/BbCheckboxGroup/types.d.ts +9 -2
  244. package/dist/components/BbCollapsible/types.d.ts +4 -0
  245. package/dist/components/BbColorInput/BbColorInput.vue.d.ts +5 -3
  246. package/dist/components/BbColorInput/BbColorInput.vue_vue_type_script_setup_true_lang.js +6 -0
  247. package/dist/components/BbColorInput/types.d.ts +18 -2
  248. package/dist/components/BbColorPalette/BbColorPalette.vue.d.ts +1 -0
  249. package/dist/components/BbColorPalette/BbColorPalette.vue.js +1 -0
  250. package/dist/components/BbColorPalette/BbColorPalette.vue_vue_type_script_setup_true_lang.js +141 -90
  251. package/dist/components/BbColorPalette/types.d.ts +15 -0
  252. package/dist/components/BbConfirm/BbConfirm.vue_vue_type_script_setup_true_lang.js +76 -64
  253. package/dist/components/BbDatePicker/BbDatePicker.vue.d.ts +1 -0
  254. package/dist/components/BbDatePicker/BbDatePicker.vue_vue_type_script_setup_true_lang.js +108 -99
  255. package/dist/components/BbDatePicker/types.d.ts +69 -22
  256. package/dist/components/BbDatePickerInput/BbDatePickerInput.vue_vue_type_script_setup_true_lang.js +3 -3
  257. package/dist/components/BbDatePickerInput/types.d.ts +30 -9
  258. package/dist/components/BbDialog/BbDialog.vue.d.ts +6 -0
  259. package/dist/components/BbDialog/BbDialog.vue_vue_type_script_setup_true_lang.js +79 -81
  260. package/dist/components/BbDropdown/AdaptiveDropdown.vue.d.ts +6 -0
  261. package/dist/components/BbDropdown/AdaptiveDropdown.vue_vue_type_script_setup_true_lang.js +92 -62
  262. package/dist/components/BbDropdown/BbDropdown.vue_vue_type_script_setup_true_lang.js +235 -207
  263. package/dist/components/BbDropdown/BbDropdownList.vue.d.ts +5 -1
  264. package/dist/components/BbDropdown/BbDropdownList.vue_vue_type_script_setup_true_lang.js +292 -216
  265. package/dist/components/BbDropdown/normalizeGroups.d.ts +9 -0
  266. package/dist/components/BbDropdown/normalizeGroups.js +2 -2
  267. package/dist/components/BbDropdown/types.d.ts +12 -2
  268. package/dist/components/BbDropdown/useDropdownContext.d.ts +26 -0
  269. package/dist/components/BbDropdownButton/types.d.ts +2 -0
  270. package/dist/components/BbDropzone/BbDropzone.vue.d.ts +2 -2
  271. package/dist/components/BbDropzone/BbDropzone.vue_vue_type_script_setup_true_lang.js +140 -116
  272. package/dist/components/BbDropzone/types.d.ts +24 -3
  273. package/dist/components/BbIcon/BbIcon.vue_vue_type_script_setup_true_lang.js +16 -11
  274. package/dist/components/BbIndicator/types.d.ts +1 -1
  275. package/dist/components/BbNumberInput/BbNumberInput.vue.d.ts +2 -2
  276. package/dist/components/BbNumberInput/types.d.ts +11 -2
  277. package/dist/components/BbOffCanvas/BbOffCanvas.vue.d.ts +6 -0
  278. package/dist/components/BbOffCanvas/BbOffCanvas.vue_vue_type_script_setup_true_lang.js +154 -156
  279. package/dist/components/BbOffCanvas/useOffCanvasStack.d.ts +10 -0
  280. package/dist/components/BbPagination/BbPagination.vue.d.ts +6 -0
  281. package/dist/components/BbPagination/BbPagination.vue_vue_type_script_setup_true_lang.js +84 -90
  282. package/dist/components/BbPopover/BbPopover.vue.d.ts +6 -0
  283. package/dist/components/BbPopover/BbPopover.vue_vue_type_script_setup_true_lang.js +117 -118
  284. package/dist/components/BbPopover/types.d.ts +6 -0
  285. package/dist/components/BbProgress/BbProgress.vue_vue_type_script_setup_true_lang.js +2 -2
  286. package/dist/components/BbRadio/BbRadio.vue.d.ts +2 -2
  287. package/dist/components/BbRadio/BbRadio.vue_vue_type_script_setup_true_lang.js +49 -48
  288. package/dist/components/BbRadio/types.d.ts +18 -4
  289. package/dist/components/BbRadioGroup/BbRadioGroup.vue_vue_type_script_setup_true_lang.js +41 -38
  290. package/dist/components/BbRadioGroup/types.d.ts +16 -4
  291. package/dist/components/BbRating/BbRating.vue.d.ts +2 -2
  292. package/dist/components/BbRating/types.d.ts +10 -3
  293. package/dist/components/BbSelect/types.d.ts +16 -7
  294. package/dist/components/BbSelectPopover/BbSelectPopover.vue_vue_type_script_setup_true_lang.js +346 -319
  295. package/dist/components/BbSelectPopover/types.d.ts +15 -7
  296. package/dist/components/BbSlider/BbSlider.vue.d.ts +2 -2
  297. package/dist/components/BbSlider/types.d.ts +9 -2
  298. package/dist/components/BbSmoothHeight/types.d.ts +4 -0
  299. package/dist/components/BbSwitch/BbSwitch.vue.d.ts +2 -2
  300. package/dist/components/BbTable/BbTable.vue.d.ts +6 -1
  301. package/dist/components/BbTable/BbTable.vue_vue_type_script_setup_true_lang.js +409 -382
  302. package/dist/components/BbTable/types.d.ts +80 -11
  303. package/dist/components/BbTag/BbTag.vue.d.ts +2 -2
  304. package/dist/components/BbTag/BbTag.vue_vue_type_script_setup_true_lang.js +5 -3
  305. package/dist/components/BbTag/types.d.ts +9 -2
  306. package/dist/components/BbTextInput/BbTextInput.vue.d.ts +2 -2
  307. package/dist/components/BbTextInput/types.d.ts +9 -2
  308. package/dist/components/BbTextarea/BbTextarea.vue.d.ts +2 -2
  309. package/dist/components/BbTextarea/types.d.ts +9 -2
  310. package/dist/components/BbTimePicker/types.d.ts +5 -1
  311. package/dist/components/BbTimePickerInput/types.d.ts +12 -3
  312. package/dist/components/BbToast/BbToast.vue_vue_type_script_setup_true_lang.js +23 -19
  313. package/dist/components/BbToast/BbToastRegion.vue_vue_type_script_setup_true_lang.js +70 -68
  314. package/dist/components/BbTooltip/BbTooltip.vue.d.ts +6 -0
  315. package/dist/components/BbTooltip/types.d.ts +8 -0
  316. package/dist/components/BbTree/BbTree.vue.d.ts +2 -0
  317. package/dist/components/BbTree/BbTreeLevel.vue_vue_type_script_setup_true_lang.js +8 -8
  318. package/dist/components/BbTree/types.d.ts +2 -0
  319. package/dist/components/CommonPopover/CommonPopover.vue.d.ts +6 -0
  320. package/dist/components/CommonPopover/CommonPopover.vue_vue_type_script_setup_true_lang.js +73 -76
  321. package/dist/components/CommonPopover/types.d.ts +4 -0
  322. package/dist/components/FlatListBox/FlatListBox.vue_vue_type_script_setup_true_lang.js +107 -103
  323. package/dist/components/FlatListBox/types.d.ts +7 -1
  324. package/dist/components/GroupedListBox/GroupedListBox.vue_vue_type_script_setup_true_lang.js +138 -131
  325. package/dist/components/GroupedListBox/types.d.ts +9 -2
  326. package/dist/components/ListBox/ListBox.vue_vue_type_script_setup_true_lang.js +5 -0
  327. package/dist/components/ListBox/types.d.ts +7 -1
  328. package/dist/components/Transitions/ScaleFade.vue.d.ts +2 -2
  329. package/dist/components/Transitions/Slide.vue.d.ts +15 -0
  330. package/dist/components/Transitions/Slide.vue.js +1 -1
  331. package/dist/composables/useBaseOptions.d.ts +4 -1
  332. package/dist/composables/useBaseOptions.js +22 -9
  333. package/dist/composables/useBbTableContext.d.ts +10 -10
  334. package/dist/composables/useBbTableContext.js +13 -13
  335. package/dist/composables/useBbTabsContext.js +39 -33
  336. package/dist/composables/useClosingInert.d.ts +28 -0
  337. package/dist/composables/useClosingInert.js +23 -0
  338. package/dist/composables/useCoarsePointer.d.ts +9 -0
  339. package/dist/composables/useCoarsePointer.js +13 -0
  340. package/dist/composables/useConfirm.d.ts +25 -5
  341. package/dist/composables/useConfirm.js +61 -53
  342. package/dist/composables/useHydrated.d.ts +7 -0
  343. package/dist/composables/useHydrated.js +9 -0
  344. package/dist/composables/useImeDismissBlur.d.ts +103 -0
  345. package/dist/composables/useImeDismissBlur.js +38 -0
  346. package/dist/composables/useItemsGetter.d.ts +1 -1
  347. package/dist/composables/useItemsGetter.js +18 -18
  348. package/dist/composables/useMobile.d.ts +6 -0
  349. package/dist/composables/useMobile.js +12 -5
  350. package/dist/composables/useQuery.d.ts +14 -2
  351. package/dist/composables/useQuery.js +2 -2
  352. package/dist/composables/useSafeArea.d.ts +96 -48
  353. package/dist/composables/useSafeArea.js +28 -13
  354. package/dist/composables/useSafeAreaInternal.d.ts +79 -0
  355. package/dist/composables/useSafeAreaInternal.js +41 -0
  356. package/dist/composables/useSegmentedFields.d.ts +2 -1
  357. package/dist/composables/useSegmentedFields.js +93 -80
  358. package/dist/composables/useSheetSurface.d.ts +39 -0
  359. package/dist/composables/useSheetSurface.js +10 -0
  360. package/dist/composables/useTableWidthContext.js +1 -1
  361. package/dist/composables/useToast.d.ts +26 -0
  362. package/dist/composables/useToast.js +22 -13
  363. package/dist/composables/useViewportWidth.d.ts +18 -1
  364. package/dist/composables/useViewportWidth.js +5 -2
  365. package/dist/confirm-variants.d.ts +7 -0
  366. package/dist/deprecation/ai-deprecations.json.d.ts +23 -1
  367. package/dist/deprecation/ai-deprecations.json.js +1 -1
  368. package/dist/directives/bbDate.d.ts +15 -6
  369. package/dist/directives/createPopoverDirective.js +2 -3
  370. package/dist/dropdown-item-variants.d.ts +7 -0
  371. package/dist/i18n/locales/cs.json +14 -2
  372. package/dist/i18n/locales/da.json +14 -2
  373. package/dist/i18n/locales/de.json +14 -2
  374. package/dist/i18n/locales/el.json +14 -2
  375. package/dist/i18n/locales/en.json +14 -2
  376. package/dist/i18n/locales/es.json +14 -2
  377. package/dist/i18n/locales/fi.json +14 -2
  378. package/dist/i18n/locales/fr.json +14 -2
  379. package/dist/i18n/locales/hu.json +14 -2
  380. package/dist/i18n/locales/it.json +14 -2
  381. package/dist/i18n/locales/ja.json +14 -2
  382. package/dist/i18n/locales/ko.json +14 -2
  383. package/dist/i18n/locales/nb.json +14 -2
  384. package/dist/i18n/locales/nl.json +14 -2
  385. package/dist/i18n/locales/pl.json +14 -2
  386. package/dist/i18n/locales/pt.json +14 -2
  387. package/dist/i18n/locales/ro.json +14 -2
  388. package/dist/i18n/locales/ru.json +14 -2
  389. package/dist/i18n/locales/sv.json +14 -2
  390. package/dist/i18n/locales/tr.json +14 -2
  391. package/dist/i18n/locales/uk.json +14 -2
  392. package/dist/i18n/locales/zh-cn.json +14 -2
  393. package/dist/index.d.ts +7 -3
  394. package/dist/index.js +48 -47
  395. package/dist/indicator-variants.d.ts +7 -0
  396. package/dist/llms-full.txt +9314 -2544
  397. package/dist/llms-medium.txt +429 -61
  398. package/dist/llms.txt +17 -11
  399. package/dist/locale-blueprint.json +14 -2
  400. package/dist/locale-registry.d.ts +16 -0
  401. package/dist/reset.css +1 -1
  402. package/dist/styles.css +1 -1
  403. package/dist/toast-variants.d.ts +7 -0
  404. package/dist/tooltip-variants.d.ts +7 -0
  405. package/dist/types/CommonProps.d.ts +4 -0
  406. package/dist/types/Config.d.ts +9 -6
  407. package/dist/types/DatePickerType.d.ts +32 -0
  408. package/dist/types/DatePickerType.js +4 -0
  409. package/dist/utilities/functions/convertDateValue.d.ts +13 -0
  410. package/dist/utilities/functions/convertDateValue.js +13 -8
  411. package/dist/utilities/functions/isDateDisabled.d.ts +3 -0
  412. package/dist/utilities/functions/isDateDisabled.js +17 -15
  413. package/dist/utilities/functions/normalizeDateBound.d.ts +20 -0
  414. package/dist/utilities/functions/normalizeDateBound.js +12 -0
  415. package/dist/utilities/functions/parsePaginationNumber.d.ts +22 -0
  416. package/dist/utilities/functions/parsePaginationNumber.js +11 -0
  417. package/dist/utilities/misc/listboxMetrics.d.ts +41 -0
  418. package/dist/utilities/misc/listboxMetrics.js +4 -0
  419. package/dist/utils/overlayEscapeStack.d.ts +14 -0
  420. package/dist/{components/BbPopover/escapeStack.js → utils/overlayEscapeStack.js} +2 -2
  421. package/dist/utils/overlaySurfaceIsolation.d.ts +1 -0
  422. package/dist/utils/overlaySurfaceIsolation.js +11 -0
  423. package/dist/validated/BbCheckbox.vue.d.ts +3 -3
  424. package/dist/validated/BbCheckbox.vue_vue_type_script_setup_true_lang.js +8 -8
  425. package/dist/validated/BbCheckboxGroup.vue.d.ts +2 -2
  426. package/dist/validated/BbCheckboxGroup.vue_vue_type_script_setup_true_lang.js +10 -4
  427. package/dist/validated/BbColorInput.vue.d.ts +3 -2
  428. package/dist/validated/BbColorInput.vue_vue_type_script_setup_true_lang.js +6 -2
  429. package/dist/validated/BbDatePickerInput.vue.d.ts +3 -2
  430. package/dist/validated/BbDatePickerInput.vue_vue_type_script_setup_true_lang.js +7 -4
  431. package/dist/validated/BbDropzone.vue.d.ts +2 -2
  432. package/dist/validated/BbDropzone.vue_vue_type_script_setup_true_lang.js +2 -2
  433. package/dist/validated/BbNumberInput.vue.d.ts +2 -2
  434. package/dist/validated/BbNumberInput.vue_vue_type_script_setup_true_lang.js +2 -2
  435. package/dist/validated/BbRadioGroup.vue.d.ts +2 -2
  436. package/dist/validated/BbRadioGroup.vue_vue_type_script_setup_true_lang.js +6 -3
  437. package/dist/validated/BbRating.vue.d.ts +2 -2
  438. package/dist/validated/BbRating.vue_vue_type_script_setup_true_lang.js +2 -2
  439. package/dist/validated/BbSelect.vue.d.ts +2 -2
  440. package/dist/validated/BbSelect.vue_vue_type_script_setup_true_lang.js +14 -5
  441. package/dist/validated/BbSlider.vue.d.ts +2 -2
  442. package/dist/validated/BbSlider.vue_vue_type_script_setup_true_lang.js +2 -2
  443. package/dist/validated/BbSwitch.vue.d.ts +3 -3
  444. package/dist/validated/BbSwitch.vue_vue_type_script_setup_true_lang.js +8 -8
  445. package/dist/validated/BbSwitchGroup.vue.d.ts +2 -2
  446. package/dist/validated/BbSwitchGroup.vue_vue_type_script_setup_true_lang.js +10 -4
  447. package/dist/validated/BbTag.vue.d.ts +2 -2
  448. package/dist/validated/BbTag.vue_vue_type_script_setup_true_lang.js +2 -2
  449. package/dist/validated/BbTextInput.vue.d.ts +2 -2
  450. package/dist/validated/BbTextInput.vue_vue_type_script_setup_true_lang.js +2 -2
  451. package/dist/validated/BbTextarea.vue.d.ts +2 -2
  452. package/dist/validated/BbTextarea.vue_vue_type_script_setup_true_lang.js +2 -2
  453. package/dist/validated/BbTimePickerInput.vue.d.ts +3 -2
  454. package/dist/validated/BbTimePickerInput.vue_vue_type_script_setup_true_lang.js +6 -3
  455. package/dist/validated/useValidatedField.d.ts +43 -2
  456. package/dist/vite-plugin.d.ts +81 -0
  457. package/dist/vite.js +335 -110
  458. package/llms.txt +17 -11
  459. package/package.json +53 -22
  460. package/scripts/lib/eslint-plugin.mjs +734 -11
  461. package/scripts/lib/mcp-config.mjs +36 -1
  462. package/scripts/lib/validate-bb-markup.mjs +607 -8
  463. package/dist/ai/guides/migration/components/bb-off-canvas.md +0 -25
  464. package/dist/components/BbPopover/escapeStack.d.ts +0 -6
  465. package/scripts/lib/__fixtures__/validated-manifest.json +0 -65
  466. package/scripts/lib/eslint-plugin-autofix.node.test.mjs +0 -109
  467. package/scripts/lib/eslint-plugin.node.test.mjs +0 -161
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
 
@@ -70,7 +71,7 @@ For most **Base\*** and **Bb\*** components, the package exports matching **prop
70
71
 
71
72
  The same knowledge base the npm package ships is served publicly over a CDN, so
72
73
  an agent can read it before anything is installed. `@alpha` tracks the latest
73
- v3 prerelease; pin an exact version (`bitboss-ui@3.0.0-alpha.1`) for stable
74
+ v3 prerelease; pin an exact version (`bitboss-ui@3.0.0-alpha.4`) for stable
74
75
  links.
75
76
 
76
77
  - [Core knowledge base](https://cdn.jsdelivr.net/npm/bitboss-ui@alpha/dist/llms-medium.txt) (~74 KB) — **start here if you can only fetch one file.** Hard rules, setup, component picker, design language, and the full component catalogue.
@@ -94,18 +95,25 @@ This package is developed and maintained by [BitBoss](https://www.bitboss.it/),
94
95
 
95
96
  ## Installation
96
97
 
98
+ **v3 is a prerelease: the `@alpha` tag is required.** A bare
99
+ `npm install bitboss-ui` resolves to the v2 line, which has no build plugin and
100
+ no `dist/ai` knowledge base — if you are following the v3 docs, that install
101
+ will not work.
102
+
97
103
  ```bash
98
- npm install bitboss-ui
104
+ npm install bitboss-ui@alpha
99
105
  ```
100
106
 
101
107
  ```bash
102
- pnpm add bitboss-ui
108
+ pnpm add bitboss-ui@alpha
103
109
  ```
104
110
 
105
111
  ```bash
106
- yarn add bitboss-ui
112
+ yarn add bitboss-ui@alpha
107
113
  ```
108
114
 
115
+ Verify with `npm ls bitboss-ui` — it must report `3.0.0-alpha.*`.
116
+
109
117
  ---
110
118
 
111
119
  ## Quick start
@@ -199,7 +207,8 @@ markup) instead of reading files blind:
199
207
  npx bitboss-ui ai-init --mcp
200
208
  ```
201
209
 
202
- 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 —
203
212
  you never run it by hand. `--mcp` merges the server entry into each harness's
204
213
  own config (never overwriting other servers you've registered), and each write
205
214
  is idempotent:
@@ -236,13 +245,33 @@ manifest checks as `bitboss-ui check`, so editor, CLI, and CI agree. It reuses
236
245
  your existing `vue-eslint-parser` setup (from `eslint-plugin-vue`) and no-ops on
237
246
  non-Vue files.
238
247
 
248
+ **Needs the TypeScript parser wired for `.ts` and `.vue`.** This library is
249
+ TS-first — recipes ship `<script setup lang="ts">`, some with `generic="T"` —
250
+ and without the two blocks below, `vue-eslint-parser` throws a `Parsing error`
251
+ on those files. A parsing error means **no rule runs on that file at all**,
252
+ `no-unknown-attributes` included, so the safety net silently goes dark on
253
+ exactly the files it matters most for.
254
+
255
+ ```bash
256
+ npm i -D @typescript-eslint/parser
257
+ ```
258
+
239
259
  ```js
240
260
  // eslint.config.js (flat config)
241
261
  import vue from 'eslint-plugin-vue';
262
+ import tsParser from '@typescript-eslint/parser';
242
263
  import bitbossUi from 'bitboss-ui/eslint-plugin';
243
264
 
244
265
  export default [
245
266
  ...vue.configs['flat/recommended'],
267
+ {
268
+ files: ['**/*.ts'],
269
+ languageOptions: { parser: tsParser },
270
+ },
271
+ {
272
+ files: ['**/*.vue'],
273
+ languageOptions: { parserOptions: { parser: tsParser } },
274
+ },
246
275
  ...bitbossUi.configs.recommended, // enables no-unknown-attributes on **/*.vue
247
276
  ];
248
277
  ```
@@ -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 {
@@ -81,7 +81,8 @@ function searchComponents({ query, limit, includeReferenceOnly } = {}) {
81
81
  const needle = String(query ?? '')
82
82
  .toLowerCase()
83
83
  .trim();
84
- const max = Number.isFinite(limit) && limit > 0 ? limit : SEARCH_DEFAULT_LIMIT;
84
+ const max =
85
+ Number.isFinite(limit) && limit > 0 ? limit : SEARCH_DEFAULT_LIMIT;
85
86
 
86
87
  // Consumer-first: reference-only internals are excluded unless explicitly
87
88
  // requested — recommending them is an agent-contract violation.
@@ -198,13 +199,83 @@ function getComponent({ name, maxChars } = {}) {
198
199
  /** Shipped stylesheet that carries every resolved `--bb-*` theme token. */
199
200
  const STYLES_CSS = join(PACKAGE_ROOT, 'dist', 'styles.css');
200
201
 
202
+ /**
203
+ * Selectors that carry a THEME value rather than a component-local rebind:
204
+ * the root scopes a consumer themes on. A selector list qualifies only when
205
+ * every comma-part is built solely from these — `:root`, `.light`, `:root.dark`
206
+ * and `html.dark` are theme roots; `.bb-tooltip .bb-common-popover__bubble` is
207
+ * not, however many `--bb-*` it redeclares.
208
+ */
209
+ const THEME_ROOT_PART = /^(?::root|html|body|\.light|\.dark)+$/;
210
+ function isThemeSelector(selector) {
211
+ return selector
212
+ .split(',')
213
+ .every((part) =>
214
+ THEME_ROOT_PART.test(part.replace(/[\s>+~]+/g, '').trim())
215
+ );
216
+ }
217
+
218
+ /**
219
+ * Walk a stylesheet and yield every `--bb-*` declaration WITH the selector that
220
+ * owns it. A flat regex cannot do this: it sees a declaration but not its
221
+ * scope, so a component that locally rebinds a theme token is indistinguishable
222
+ * from the dark theme redefining it. Brace-depth scanning (quote-aware, and
223
+ * tolerant of the missing final semicolon that minified CSS emits) is the
224
+ * cheapest way to keep the scope — and this file ships in the package, so it
225
+ * may not reach for postcss the way the dev-only `check:tokens` script does.
226
+ */
227
+ function* eachTokenDeclaration(css) {
228
+ const stack = [];
229
+ let buffer = '';
230
+ let quote = null;
231
+ const declaration = () => {
232
+ const m = buffer.match(/(--bb-[a-z0-9-]+)\s*:\s*([\s\S]+)/);
233
+ buffer = '';
234
+ return m ? { name: m[1], value: m[2].trim() } : null;
235
+ };
236
+ for (const char of css) {
237
+ if (quote) {
238
+ buffer += char;
239
+ if (char === quote) quote = null;
240
+ continue;
241
+ }
242
+ if (char === '"' || char === "'") {
243
+ quote = char;
244
+ buffer += char;
245
+ } else if (char === '{') {
246
+ stack.push(buffer.trim());
247
+ buffer = '';
248
+ } else if (char === '}' || char === ';') {
249
+ const decl = declaration();
250
+ if (decl) yield { ...decl, selector: stack[stack.length - 1] ?? '' };
251
+ if (char === '}') stack.pop();
252
+ } else {
253
+ buffer += char;
254
+ }
255
+ }
256
+ }
257
+
201
258
  /**
202
259
  * `list_tokens({ filter })` — the `--bb-*` design tokens with their values,
203
- * read from the shipped stylesheet (the same set `check:tokens` counts).
260
+ * read from the shipped stylesheet (the same 90 `check:tokens` counts).
204
261
  *
205
- * A token declared more than once is a theme override: the first value is the
206
- * light/base one, later values are dark-theme overrides, so both are reported
207
- * rather than one silently winning.
262
+ * WHY ONLY `--bb-*` and why there is no opt-in for the unprefixed ones, even
263
+ * though `search_components` has `includeReferenceOnly`. The two tiers are not
264
+ * the same kind of thing. `--bb-*` is a flat, global, consumer-settable
265
+ * contract. Unprefixed component tokens are *sealed to the file that consumes
266
+ * them* (`check:tokens` rule 3), so the same name means different things in
267
+ * different components and is only meaningful inside that component's scope.
268
+ * Serving them as one flat list would invite exactly the wrong move — an agent
269
+ * writing `:root { --gap: … }` and wondering why nothing changed. They are
270
+ * documented per component, which `get_component` already serves.
271
+ *
272
+ * WHY `dist/styles.css` AND NOT `src/assets/css/variables.css`: `src/` is not
273
+ * in the published package, so the source file does not exist for the consumer
274
+ * this server runs inside. The shipped sheet also carries *resolved* values.
275
+ *
276
+ * There is no `limit`/`maxChars` here by design: the whole set is ~9 KB, and a
277
+ * half-list of tokens is the same failure as a half-list of props — it makes an
278
+ * agent invent the missing ones.
208
279
  */
209
280
  function listTokens({ filter } = {}) {
210
281
  if (!existsSync(STYLES_CSS)) {
@@ -216,12 +287,18 @@ function listTokens({ filter } = {}) {
216
287
  }
217
288
  const css = readFileSync(STYLES_CSS, 'utf-8');
218
289
  const byName = new Map();
219
- for (const m of css.matchAll(/(--bb-[a-z0-9-]+)\s*:\s*([^;}]+)/gi)) {
220
- const name = m[1];
221
- const value = m[2].trim();
222
- const values = byName.get(name) ?? [];
223
- if (!values.includes(value)) values.push(value);
224
- byName.set(name, values);
290
+ for (const { name, value, selector } of eachTokenDeclaration(css)) {
291
+ const entry = byName.get(name) ?? { theme: [], local: [] };
292
+ if (isThemeSelector(selector)) {
293
+ // Light first, dark after: report both rather than let one win.
294
+ if (!entry.theme.includes(value)) entry.theme.push(value);
295
+ } else if (!entry.local.some((r) => r.selector === selector)) {
296
+ // A component rebinding a theme token for its own subtree. Reporting
297
+ // this as a `themeOverride` is a lie an agent acts on — it reads
298
+ // `--bb-arrow: 0` as "the dark theme hides arrows".
299
+ entry.local.push({ selector, value });
300
+ }
301
+ byName.set(name, entry);
225
302
  }
226
303
  const needle = String(filter ?? '')
227
304
  .toLowerCase()
@@ -229,16 +306,20 @@ function listTokens({ filter } = {}) {
229
306
  const tokens = [...byName.entries()]
230
307
  .filter(([name]) => !needle || name.toLowerCase().includes(needle))
231
308
  .sort(([a], [b]) => a.localeCompare(b))
232
- .map(([name, values]) => ({
309
+ .map(([name, { theme, local }]) => ({
233
310
  name,
234
- value: values[0],
235
- ...(values.length > 1 ? { themeOverrides: values.slice(1) } : {}),
311
+ value: theme[0],
312
+ ...(theme.length > 1 ? { themeOverrides: theme.slice(1) } : {}),
313
+ ...(local.length > 0 ? { localRebinds: local } : {}),
236
314
  }));
237
315
  return {
238
316
  count: tokens.length,
239
317
  ...(needle ? { filter: needle } : { total: byName.size }),
240
318
  tokens,
241
- hint: 'Theme tokens are set by the consumer app (e.g. on :root / .dark). Component-level unprefixed tokens are documented per component; see the design-tokens guide via get_guide.',
319
+ hint:
320
+ needle && tokens.length === 0
321
+ ? `No token name contains '${needle}'. Call list_tokens with no filter for all ${byName.size} — the names are semantic (primary/danger/panel/text/border/radius/…), not literal colours.`
322
+ : 'Theme tokens are set by the consumer app (e.g. on :root / .dark); `themeOverrides` is the dark-theme value. `localRebinds` is a component rebinding the token inside its own subtree — not something to copy. Component-level unprefixed tokens are documented per component; see the design-tokens guide via get_guide.',
242
323
  };
243
324
  }
244
325
 
@@ -248,7 +329,8 @@ function collectGuidePaths(dir, prefix = '') {
248
329
  if (!existsSync(dir)) return out;
249
330
  for (const entry of readdirSync(dir, { withFileTypes: true })) {
250
331
  const rel = prefix ? `${prefix}/${entry.name}` : entry.name;
251
- if (entry.isDirectory()) out.push(...collectGuidePaths(join(dir, entry.name), rel));
332
+ if (entry.isDirectory())
333
+ out.push(...collectGuidePaths(join(dir, entry.name), rel));
252
334
  else if (entry.name.endsWith('.md')) out.push(rel);
253
335
  }
254
336
  return out;
@@ -269,7 +351,11 @@ function getGuide({ name, maxChars } = {}) {
269
351
  const rel = String(name ?? '').replace(/^\/+/, '');
270
352
  // Contain reads to the guides dir — no traversal out of the knowledge base.
271
353
  if (!rel || rel.includes('..')) {
272
- return { found: false, error: `Invalid guide name '${name}'.` };
354
+ return {
355
+ found: false,
356
+ error: `Invalid guide name '${name}'.`,
357
+ hint: 'Call list_guides for the available names.',
358
+ };
273
359
  }
274
360
  const fileName = rel.endsWith('.md') ? rel : `${rel}.md`;
275
361
  const guidesDir = join(AI_ROOT, 'guides');
@@ -319,12 +405,28 @@ function getRecipe({ platform, name, maxChars } = {}) {
319
405
  error: `Unknown platform '${platform}' — expected one of ${RECIPE_PLATFORMS.join(', ')}`,
320
406
  };
321
407
  }
322
- const fileName = String(name ?? '').endsWith('.md')
323
- ? String(name)
324
- : `${name}.md`;
325
- const filePath = join(AI_ROOT, 'recipes', platform, fileName);
326
- if (!existsSync(filePath)) {
327
- 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
+ };
328
430
  }
329
431
  const { content, ...meta } = truncateMarkdown(
330
432
  readFileSync(filePath, 'utf-8'),
@@ -384,7 +486,7 @@ function buildServer() {
384
486
  'search_components',
385
487
  {
386
488
  description:
387
- "Search the bitboss-ui component manifest by name and description, ranked by relevance (exact/prefix name matches first, description matches last). Returns consumer-API components only by default. Use this to find the right Bb* component before writing usage code.",
489
+ 'Search the bitboss-ui component manifest by name and description, ranked by relevance (exact/prefix name matches first, description matches last). Returns consumer-API components only by default. Use this to find the right Bb* component before writing usage code.',
388
490
  inputSchema: {
389
491
  query: z
390
492
  .string()
@@ -550,6 +652,25 @@ export async function main() {
550
652
 
551
653
  export const start = main;
552
654
 
655
+ /**
656
+ * The knowledge-base half, exported for in-process callers that want the same
657
+ * answers an MCP client gets without paying for a subprocess and a handshake —
658
+ * today, `scripts/run-eval-agent.mjs`, which hands these to a model as tools so
659
+ * the benchmark measures the knowledge base this server actually serves. Pure
660
+ * functions of the installed `dist/`: no transport, no state, safe to call
661
+ * concurrently. Importing this module does not start a server.
662
+ */
663
+ export {
664
+ searchComponents,
665
+ getComponent,
666
+ listTokens,
667
+ listGuides,
668
+ getGuide,
669
+ listRecipes,
670
+ getRecipe,
671
+ validateCode,
672
+ };
673
+
553
674
  const isDirectRun =
554
675
  process.argv[1] && import.meta.url === `file://${process.argv[1]}`;
555
676
  if (isDirectRun) {
@@ -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.
@@ -370,33 +372,79 @@ export default ${localeObjectLiteral(template)} satisfies LocaleOverrides;
370
372
  console.log(` ${dayjsHint}`);
371
373
  }
372
374
 
373
- const CHECK_SKIP_DIRS = new Set(['node_modules', 'dist', '.git']);
375
+ // SNT-007: a bare-segment skip list of `node_modules`/`dist`/`.git` let a
376
+ // default (no-glob) `check` sweep straight through a Laravel-style consumer's
377
+ // `vendor/`, `storage/`, and `public/` trees — hundreds of vendored
378
+ // `README.md`s outnumbering the app's own `.vue`/`.md` files 20:1. These are
379
+ // all directories no project authors `Bb*` markup into, so they're safe
380
+ // blanket exclusions; framework build caches (`.nuxt`, `.output`) get the
381
+ // same treatment.
382
+ const CHECK_SKIP_DIRS = new Set([
383
+ 'node_modules',
384
+ 'dist',
385
+ '.git',
386
+ 'vendor',
387
+ 'storage',
388
+ 'public',
389
+ '.output',
390
+ '.nuxt',
391
+ ]);
392
+ // Composite (multi-segment) skips: too narrow to earn a bare-segment entry —
393
+ // skipping all of `bootstrap/` would also hide a project's own
394
+ // `bootstrap/*.md` — but `bootstrap/cache` specifically is Laravel's compiled
395
+ // config/routes cache, never hand-authored.
396
+ const CHECK_SKIP_SUBPATHS = ['bootstrap/cache'];
374
397
  const CHECK_EXTENSIONS = ['.vue', '.md'];
375
398
 
376
- /** True when any path segment is a directory `check` never descends into. */
399
+ /** True when a path segment (by itself) is a directory `check` never descends into. */
400
+ function isSkippedSegment(name) {
401
+ return CHECK_SKIP_DIRS.has(name);
402
+ }
403
+
404
+ /** True when the relative path IS, or falls under, a skipped multi-segment subpath. */
405
+ function isSkippedSubpath(relPath) {
406
+ const normalized = relPath.split(/[\\/]/).join('/');
407
+ return CHECK_SKIP_SUBPATHS.some(
408
+ (sub) => normalized === sub || normalized.startsWith(`${sub}/`)
409
+ );
410
+ }
411
+
412
+ /** True when any path segment (or composite subpath) is skipped. */
377
413
  function inSkippedDir(relPath) {
378
- return relPath.split(/[\\/]/).some((segment) => CHECK_SKIP_DIRS.has(segment));
414
+ return (
415
+ relPath.split(/[\\/]/).some((segment) => isSkippedSegment(segment)) ||
416
+ isSkippedSubpath(relPath)
417
+ );
379
418
  }
380
419
 
381
420
  /**
382
- * Every `.vue`/`.md` file under `dir`, excluding node_modules/dist/.git at any
383
- * depth. Recursive readdir rather than `globSync` because glob's `**` never
384
- * traverses dot-directories (and there is no `dot` option) the sweep must
385
- * keep matching files like `.github/copilot-instructions.md`.
421
+ * Every `.vue`/`.md` file under `dir`, excluding the skip list (see
422
+ * `CHECK_SKIP_DIRS`/`CHECK_SKIP_SUBPATHS`) at any depth. A hand-rolled
423
+ * recursive walk rather than `globSync` because glob's `**` never traverses
424
+ * dot-directories (and there is no `dot` option) — the sweep must keep
425
+ * matching files like `.github/copilot-instructions.md`. Pruning skipped
426
+ * directories BEFORE descending (rather than filtering after a flat
427
+ * `recursive: true` readdir) is what keeps a multi-thousand-file `vendor/`
428
+ * tree from being walked at all.
386
429
  */
387
- function collectCheckFiles(dir) {
430
+ function collectCheckFiles(dir, relBase = dir) {
388
431
  let entries;
389
432
  try {
390
- entries = readdirSync(dir, { recursive: true, withFileTypes: true });
433
+ entries = readdirSync(dir, { withFileTypes: true });
391
434
  } catch {
392
435
  return [];
393
436
  }
394
437
  const out = [];
395
438
  for (const entry of entries) {
439
+ const full = join(dir, entry.name);
440
+ if (entry.isDirectory()) {
441
+ if (isSkippedSegment(entry.name)) continue;
442
+ if (isSkippedSubpath(relative(relBase, full))) continue;
443
+ out.push(...collectCheckFiles(full, relBase));
444
+ continue;
445
+ }
396
446
  if (!entry.isFile()) continue;
397
447
  if (!CHECK_EXTENSIONS.some((ext) => entry.name.endsWith(ext))) continue;
398
- const full = join(entry.parentPath, entry.name);
399
- if (inSkippedDir(relative(dir, full))) continue;
400
448
  out.push(full);
401
449
  }
402
450
  return out;
@@ -404,10 +452,16 @@ function collectCheckFiles(dir) {
404
452
 
405
453
  /**
406
454
  * Resolve the file list for `check`: explicit globs/paths if given, otherwise
407
- * every `.vue`/`.md` file under `cwd` (excluding node_modules/dist/.git).
408
- * Literal paths resolve directly (files of any extension as-is, directories
409
- * swept recursively); glob patterns (`*`, `**`, `?`, `{a,b}`) go through
410
- * `node:fs` globSync, restricted to `.vue`/`.md` outside the skipped dirs.
455
+ * every `.vue`/`.md` file under `cwd` (excluding `CHECK_SKIP_DIRS`/
456
+ * `CHECK_SKIP_SUBPATHS` node_modules, dist, .git, vendor, storage, public,
457
+ * .output, .nuxt, bootstrap/cache). Literal paths resolve directly: a literal
458
+ * FILE is always included (even one that lives inside a skipped dir — asking
459
+ * for it by name is the widen-the-scan escape hatch), a literal DIRECTORY is
460
+ * swept recursively and only its descendants are checked against the skip
461
+ * list (so `check vendor/some-pkg` still works even though a bare sweep would
462
+ * never enter `vendor/` on its own). Glob patterns (`*`, `**`, `?`, `{a,b}`)
463
+ * go through `node:fs` globSync, restricted to `.vue`/`.md` outside the
464
+ * skipped dirs.
411
465
  */
412
466
  function resolveCheckFiles(cwd, patterns) {
413
467
  if (patterns.length === 0) return collectCheckFiles(cwd).sort();
@@ -451,10 +505,41 @@ function resolveCheckFiles(cwd, patterns) {
451
505
  }
452
506
 
453
507
  /**
454
- * `npx bitboss-ui check [glob…] [--json]` — validate `Bb*` markup in `.vue`
455
- * and `.md` files against the installed components.json manifest.
508
+ * `4 .vue + 8 .md` — a plain file count on its own ("715 file(s)") reads as
509
+ * "715 files carefully checked" when SNT-007 showed it can just as easily be
510
+ * "701 vendored READMEs + 14 real files"; splitting by extension makes the
511
+ * number honest about what was actually covered. `.vue`/`.md` sort first
512
+ * (the extensions `check` targets by default); any other extension a literal
513
+ * path argument pulled in — see `resolveCheckFiles` — sorts after, A-Z.
456
514
  */
457
- function checkCommand(globs, jsonMode) {
515
+ function summarizeFileCounts(files) {
516
+ const counts = new Map();
517
+ for (const file of files) {
518
+ const base = file.split(/[\\/]/).pop() ?? file;
519
+ const dot = base.lastIndexOf('.');
520
+ const ext = dot === -1 ? '(no extension)' : base.slice(dot);
521
+ counts.set(ext, (counts.get(ext) ?? 0) + 1);
522
+ }
523
+ const priority = ['.vue', '.md'];
524
+ const exts = [...counts.keys()].sort((a, b) => {
525
+ const pa = priority.indexOf(a);
526
+ const pb = priority.indexOf(b);
527
+ if (pa !== -1 || pb !== -1) {
528
+ return (
529
+ (pa === -1 ? priority.length : pa) - (pb === -1 ? priority.length : pb)
530
+ );
531
+ }
532
+ return a.localeCompare(b);
533
+ });
534
+ return exts.map((ext) => `${counts.get(ext)} ${ext}`).join(' + ');
535
+ }
536
+
537
+ /**
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.
541
+ */
542
+ function checkCommand(globs, jsonMode, allowEmpty = false) {
458
543
  const projectRoot = process.cwd();
459
544
 
460
545
  const manifestPath = join(PACKAGE_ROOT, 'dist', 'ai', 'components.json');
@@ -480,12 +565,26 @@ function checkCommand(globs, jsonMode) {
480
565
  }
481
566
 
482
567
  if (jsonMode) {
483
- console.log(JSON.stringify({ findings }, null, 2));
568
+ console.log(JSON.stringify({ findings, files: files.length }, null, 2));
484
569
  if (findings.length > 0) process.exit(1);
570
+ if (files.length === 0 && globs.length > 0 && !allowEmpty) process.exit(1);
485
571
  return;
486
572
  }
487
573
 
488
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
+ }
489
588
  console.log(
490
589
  '[bitboss-ui] check: no .vue/.md files matched — nothing to do.'
491
590
  );
@@ -494,7 +593,7 @@ function checkCommand(globs, jsonMode) {
494
593
 
495
594
  if (findings.length === 0) {
496
595
  console.log(
497
- `[bitboss-ui] check OK — ${files.length} 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.`
498
597
  );
499
598
  return;
500
599
  }
@@ -539,12 +638,19 @@ Commands:
539
638
  server for Claude Code (.mcp.json), Cursor (.cursor/mcp.json),
540
639
  VS Code/Copilot (.vscode/mcp.json), and Windsurf (~/.codeium
541
640
  global) — merges, never overwrites other servers.
542
- check [glob…] [--json]
641
+ check [glob…] [--json] [--allow-empty]
543
642
  Validate \`Bb*\` markup in .vue/.md files against the
544
643
  installed components.json manifest (unknown/removed props,
545
- bad v-models). Defaults to every .vue/.md file under the
546
- current directory (node_modules/dist/.git excluded).
547
- Exits 1 on findings; \`--json\` prints \`{ findings: [...] }\`.
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,
648
+ storage, public, .output, .nuxt, bootstrap/cache
649
+ excluded — pass an explicit glob/path to widen the scan).
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 }\`.
548
654
  mcp Start a stdio MCP server exposing the dist/ai knowledge
549
655
  base (search_components, get_component, list_recipes,
550
656
  get_recipe, validate) to MCP-capable agent harnesses.
@@ -590,10 +696,17 @@ switch (command) {
590
696
  const { values, positionals } = parseCommandArgs(
591
697
  command,
592
698
  commandArgs,
593
- { json: { type: 'boolean' } },
699
+ {
700
+ json: { type: 'boolean' },
701
+ 'allow-empty': { type: 'boolean' },
702
+ },
594
703
  { allowPositionals: true }
595
704
  );
596
- checkCommand(positionals, values.json ?? false);
705
+ checkCommand(
706
+ positionals,
707
+ values.json ?? false,
708
+ values['allow-empty'] ?? false
709
+ );
597
710
  break;
598
711
  }
599
712
  case 'mcp': {