bitboss-ui 3.0.0-beta.43 → 3.0.0-beta.45

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 (411) hide show
  1. package/README.md +10 -7
  2. package/bin/bitboss-ui-mcp.mjs +119 -15
  3. package/bin/bitboss-ui.mjs +163 -32
  4. package/dist/ai/BbAlert.md +8 -2
  5. package/dist/ai/BbAvatar.md +8 -3
  6. package/dist/ai/BbBadge.md +4 -1
  7. package/dist/ai/BbBreadcrumbs.md +1 -1
  8. package/dist/ai/BbButton.md +10 -6
  9. package/dist/ai/BbCalendar.md +9 -9
  10. package/dist/ai/BbCheckbox.md +8 -1
  11. package/dist/ai/BbCheckboxGroup.md +25 -14
  12. package/dist/ai/BbColorInput.md +4 -1
  13. package/dist/ai/BbDatePicker.md +8 -8
  14. package/dist/ai/BbDatePickerInput.md +24 -18
  15. package/dist/ai/BbDialog.md +6 -4
  16. package/dist/ai/BbDropdown.md +62 -38
  17. package/dist/ai/BbDropdownButton.md +8 -4
  18. package/dist/ai/BbDropdownGroup.md +3 -3
  19. package/dist/ai/BbDropzone.md +232 -28
  20. package/dist/ai/BbForm.md +16 -3
  21. package/dist/ai/BbIcon.md +25 -9
  22. package/dist/ai/BbNumberInput.md +4 -1
  23. package/dist/ai/BbOffCanvas.md +6 -4
  24. package/dist/ai/BbPagination.md +2 -2
  25. package/dist/ai/BbPopover.md +1 -1
  26. package/dist/ai/BbRadio.md +8 -1
  27. package/dist/ai/BbRadioGroup.md +25 -19
  28. package/dist/ai/BbRating.md +6 -3
  29. package/dist/ai/BbSelect.md +422 -154
  30. package/dist/ai/BbSelectPopover.md +239 -57
  31. package/dist/ai/BbSlider.md +4 -1
  32. package/dist/ai/BbSpinner.md +1 -1
  33. package/dist/ai/BbSwitch.md +21 -1
  34. package/dist/ai/BbSwitchGroup.md +31 -20
  35. package/dist/ai/BbTable.md +283 -137
  36. package/dist/ai/BbTabs.md +8 -8
  37. package/dist/ai/BbTabsList.md +2 -2
  38. package/dist/ai/BbTag.md +6 -2
  39. package/dist/ai/BbTextInput.md +41 -4
  40. package/dist/ai/BbTextarea.md +96 -42
  41. package/dist/ai/BbTimePicker.md +3 -2
  42. package/dist/ai/BbTimePickerInput.md +8 -3
  43. package/dist/ai/BbToast.md +2 -1
  44. package/dist/ai/BbTooltip.md +1 -1
  45. package/dist/ai/BbTree.md +1 -1
  46. package/dist/ai/CommonField.md +5 -2
  47. package/dist/ai/CommonPopover.md +1 -1
  48. package/dist/ai/CommonTimeSelector.md +1 -1
  49. package/dist/ai/FlatListBox.md +2 -1
  50. package/dist/ai/GroupedListBox.md +2 -1
  51. package/dist/ai/ListBox.md +3 -2
  52. package/dist/ai/OptionsContainer.md +5 -1
  53. package/dist/ai/changelog.json +285 -8
  54. package/dist/ai/components.json +64 -55
  55. package/dist/ai/design-tokens.json +4 -4
  56. package/dist/ai/guides/agent-contract.md +26 -24
  57. package/dist/ai/guides/ai-router.md +23 -21
  58. package/dist/ai/guides/coherence-playbook.md +24 -20
  59. package/dist/ai/guides/component-picker.md +4 -4
  60. package/dist/ai/guides/design-language.md +2 -1
  61. package/dist/ai/guides/design-tokens.md +15 -7
  62. package/dist/ai/guides/fetch-items-playbook.md +127 -87
  63. package/dist/ai/guides/icons-policy.md +2 -2
  64. package/dist/ai/guides/inertia-helpers.md +88 -25
  65. package/dist/ai/guides/installation-and-plugin-setup.md +16 -3
  66. package/dist/ai/guides/migration/components/bb-checkbox-group.md +1 -1
  67. package/dist/ai/guides/migration/components/bb-date-picker-input.md +10 -10
  68. package/dist/ai/guides/migration/components/bb-select-popover.md +5 -0
  69. package/dist/ai/guides/migration/components/bb-select.md +8 -2
  70. package/dist/ai/guides/migration/components/bb-table.md +31 -19
  71. package/dist/ai/guides/migration/components/bb-tabs.md +17 -17
  72. package/dist/ai/guides/migration/v2-to-v3.md +207 -69
  73. package/dist/ai/guides/migration/v3-beta-tooling.md +5 -1
  74. package/dist/ai/guides/page-shell.md +12 -6
  75. package/dist/ai/guides/passthrough.md +6 -5
  76. package/dist/ai/guides/preset-components.md +10 -2
  77. package/dist/ai/index.md +7 -8
  78. package/dist/ai/manifest/components/BbAlert.json +1 -1
  79. package/dist/ai/manifest/components/BbAvatar.json +1 -1
  80. package/dist/ai/manifest/components/BbBreadcrumbs.tree.json +1 -1
  81. package/dist/ai/manifest/components/BbCalendar.json +5 -3
  82. package/dist/ai/manifest/components/BbCheckbox.json +2 -0
  83. package/dist/ai/manifest/components/BbCheckbox.tree.json +1 -1
  84. package/dist/ai/manifest/components/BbCheckboxGroup.json +9 -3
  85. package/dist/ai/manifest/components/BbCheckboxGroup.tree.json +10 -1
  86. package/dist/ai/manifest/components/BbColorInput.json +3 -1
  87. package/dist/ai/manifest/components/BbColorInput.tree.json +1 -1
  88. package/dist/ai/manifest/components/BbColorPalette.json +2 -2
  89. package/dist/ai/manifest/components/BbDatePicker.json +8 -6
  90. package/dist/ai/manifest/components/BbDatePickerInput.json +8 -4
  91. package/dist/ai/manifest/components/BbDatePickerInput.tree.json +1 -1
  92. package/dist/ai/manifest/components/BbDialog.json +3 -3
  93. package/dist/ai/manifest/components/BbDropdown.json +9 -8
  94. package/dist/ai/manifest/components/BbDropdown.tree.json +3 -1
  95. package/dist/ai/manifest/components/BbDropdownButton.json +6 -6
  96. package/dist/ai/manifest/components/BbDropdownButton.tree.json +1 -1
  97. package/dist/ai/manifest/components/BbDropdownGroup.json +3 -3
  98. package/dist/ai/manifest/components/BbDropzone.json +3 -1
  99. package/dist/ai/manifest/components/BbDropzone.tree.json +1 -0
  100. package/dist/ai/manifest/components/BbForm.json +1 -1
  101. package/dist/ai/manifest/components/BbIcon.json +1 -1
  102. package/dist/ai/manifest/components/BbNumberInput.json +2 -0
  103. package/dist/ai/manifest/components/BbNumberInput.tree.json +1 -1
  104. package/dist/ai/manifest/components/BbOffCanvas.json +2 -2
  105. package/dist/ai/manifest/components/BbPopover.json +3 -3
  106. package/dist/ai/manifest/components/BbRadio.json +2 -0
  107. package/dist/ai/manifest/components/BbRadio.tree.json +1 -1
  108. package/dist/ai/manifest/components/BbRadioGroup.json +9 -3
  109. package/dist/ai/manifest/components/BbRadioGroup.tree.json +10 -1
  110. package/dist/ai/manifest/components/BbRating.json +4 -2
  111. package/dist/ai/manifest/components/BbRating.tree.json +1 -1
  112. package/dist/ai/manifest/components/BbSelect.json +9 -5
  113. package/dist/ai/manifest/components/BbSelect.tree.json +2 -2
  114. package/dist/ai/manifest/components/BbSelectPopover.json +9 -7
  115. package/dist/ai/manifest/components/BbSelectPopover.tree.json +5 -1
  116. package/dist/ai/manifest/components/BbSlider.json +2 -0
  117. package/dist/ai/manifest/components/BbSlider.tree.json +1 -1
  118. package/dist/ai/manifest/components/BbSpinner.json +1 -1
  119. package/dist/ai/manifest/components/BbSwitch.json +2 -0
  120. package/dist/ai/manifest/components/BbSwitch.tree.json +1 -1
  121. package/dist/ai/manifest/components/BbSwitchGroup.json +9 -3
  122. package/dist/ai/manifest/components/BbSwitchGroup.tree.json +10 -1
  123. package/dist/ai/manifest/components/BbTable.json +28 -15
  124. package/dist/ai/manifest/components/BbTable.tree.json +16 -1
  125. package/dist/ai/manifest/components/BbTabs.json +4 -3
  126. package/dist/ai/manifest/components/BbTabsList.json +4 -3
  127. package/dist/ai/manifest/components/BbTag.json +2 -0
  128. package/dist/ai/manifest/components/BbTag.tree.json +1 -1
  129. package/dist/ai/manifest/components/BbTextInput.json +8 -2
  130. package/dist/ai/manifest/components/BbTextInput.tree.json +1 -1
  131. package/dist/ai/manifest/components/BbTextarea.json +8 -2
  132. package/dist/ai/manifest/components/BbTextarea.tree.json +1 -1
  133. package/dist/ai/manifest/components/BbTimePicker.json +3 -3
  134. package/dist/ai/manifest/components/BbTimePickerInput.json +3 -1
  135. package/dist/ai/manifest/components/BbTimePickerInput.tree.json +1 -1
  136. package/dist/ai/manifest/components/BbTooltip.json +2 -2
  137. package/dist/ai/manifest/components/BbTree.json +1 -1
  138. package/dist/ai/manifest/components/CommonField.json +4 -1
  139. package/dist/ai/manifest/components/CommonField.tree.json +18 -0
  140. package/dist/ai/manifest/components/CommonPopover.json +2 -2
  141. package/dist/ai/manifest/components/CommonTimeSelector.json +1 -1
  142. package/dist/ai/manifest/components/FlatListBox.json +1 -0
  143. package/dist/ai/manifest/components/FlatListBox.tree.json +2 -1
  144. package/dist/ai/manifest/components/GroupedListBox.json +1 -0
  145. package/dist/ai/manifest/components/GroupedListBox.tree.json +2 -1
  146. package/dist/ai/manifest/components/ListBox.json +1 -0
  147. package/dist/ai/manifest/components/ListBox.tree.json +2 -2
  148. package/dist/ai/manifest/components/OptionsContainer.json +5 -1
  149. package/dist/ai/manifest/index.json +2 -2
  150. package/dist/ai/manifest/meta.json +9 -0
  151. package/dist/ai/manifest/types.advanced.json +8 -4
  152. package/dist/ai/manifest/types.api.json +9 -4
  153. package/dist/ai/recipes/inertia/approvals-inbox.md +160 -109
  154. package/dist/ai/recipes/inertia/inline-edit-workspace.md +151 -82
  155. package/dist/ai/recipes/inertia/layout-scaffold.md +71 -40
  156. package/dist/ai/recipes/inertia/onboarding.md +80 -71
  157. package/dist/ai/recipes/inertia/ownership-atlas.md +251 -271
  158. package/dist/ai/recipes/inertia/record-form.md +356 -201
  159. package/dist/ai/recipes/inertia/records-workspace.md +466 -234
  160. package/dist/ai/recipes/inertia/settings-workspace.md +317 -1046
  161. package/dist/ai/recipes/inertia/upload-center.md +115 -106
  162. package/dist/ai/recipes/inertia/wizard-form.md +144 -86
  163. package/dist/ai/recipes/nuxt/approvals-inbox.md +237 -140
  164. package/dist/ai/recipes/nuxt/inline-edit-workspace.md +218 -92
  165. package/dist/ai/recipes/nuxt/layout-scaffold.md +72 -41
  166. package/dist/ai/recipes/nuxt/onboarding.md +148 -105
  167. package/dist/ai/recipes/nuxt/ownership-atlas.md +1408 -0
  168. package/dist/ai/recipes/nuxt/record-form.md +446 -207
  169. package/dist/ai/recipes/nuxt/records-workspace.md +532 -234
  170. package/dist/ai/recipes/nuxt/settings-workspace.md +336 -1065
  171. package/dist/ai/recipes/nuxt/upload-center.md +254 -166
  172. package/dist/ai/recipes/nuxt/wizard-form.md +168 -95
  173. package/dist/ai/recipes/vue/approvals-inbox.md +211 -126
  174. package/dist/ai/recipes/vue/inline-edit-workspace.md +197 -82
  175. package/dist/ai/recipes/vue/layout-scaffold.md +71 -40
  176. package/dist/ai/recipes/vue/onboarding.md +80 -71
  177. package/dist/ai/recipes/vue/ownership-atlas.md +1362 -0
  178. package/dist/ai/recipes/vue/record-form.md +175 -81
  179. package/dist/ai/recipes/vue/records-workspace.md +486 -215
  180. package/dist/ai/recipes/vue/settings-workspace.md +316 -1042
  181. package/dist/ai/recipes/vue/upload-center.md +200 -151
  182. package/dist/ai/recipes/vue/wizard-form.md +108 -78
  183. package/dist/ai/source/BbButton.md +13 -1
  184. package/dist/ai/source/BbCalendar.md +43 -18
  185. package/dist/ai/source/BbCheckbox.md +21 -2
  186. package/dist/ai/source/BbCheckboxGroup.md +153 -15
  187. package/dist/ai/source/BbCollapsible.md +1 -1
  188. package/dist/ai/source/BbColorInput.md +17 -1
  189. package/dist/ai/source/BbDatePicker.md +11 -9
  190. package/dist/ai/source/BbDatePickerInput.md +101 -48
  191. package/dist/ai/source/BbDialog.md +21 -4
  192. package/dist/ai/source/BbDropdown.md +230 -51
  193. package/dist/ai/source/BbDropdownButton.md +14 -2
  194. package/dist/ai/source/BbDropdownGroup.md +268 -73
  195. package/dist/ai/source/BbDropzone.md +80 -9
  196. package/dist/ai/source/BbForm.md +2 -2
  197. package/dist/ai/source/BbIcon.md +5 -0
  198. package/dist/ai/source/BbNumberInput.md +23 -3
  199. package/dist/ai/source/BbOffCanvas.md +24 -6
  200. package/dist/ai/source/BbPagination.md +7 -1
  201. package/dist/ai/source/BbPopover.md +1 -1
  202. package/dist/ai/source/BbRadio.md +21 -2
  203. package/dist/ai/source/BbRadioGroup.md +133 -15
  204. package/dist/ai/source/BbRating.md +23 -4
  205. package/dist/ai/source/BbSelect.md +72 -9
  206. package/dist/ai/source/BbSelectPopover.md +327 -100
  207. package/dist/ai/source/BbSlider.md +21 -2
  208. package/dist/ai/source/BbSmoothHeight.md +5 -0
  209. package/dist/ai/source/BbSwitch.md +6 -1
  210. package/dist/ai/source/BbSwitchGroup.md +73 -12
  211. package/dist/ai/source/BbTable.md +501 -174
  212. package/dist/ai/source/BbTabs.md +5 -5
  213. package/dist/ai/source/BbTabsList.md +3 -3
  214. package/dist/ai/source/BbTabsPanels.md +3 -3
  215. package/dist/ai/source/BbTabsRoot.md +3 -3
  216. package/dist/ai/source/BbTag.md +26 -3
  217. package/dist/ai/source/BbTextInput.md +56 -7
  218. package/dist/ai/source/BbTextarea.md +56 -7
  219. package/dist/ai/source/BbTimePickerInput.md +55 -12
  220. package/dist/ai/source/BbTooltip.md +1 -1
  221. package/dist/ai/source/BbTree.md +2 -2
  222. package/dist/ai/source/CommonField.md +191 -17
  223. package/dist/ai/source/CommonFieldInput.md +6 -0
  224. package/dist/ai/source/CommonPopover.md +1 -1
  225. package/dist/ai/source/CommonTimeSelector.md +12 -5
  226. package/dist/ai/source/FlatListBox.md +27 -2
  227. package/dist/ai/source/GroupedListBox.md +27 -2
  228. package/dist/ai/source/ListBox.md +7 -0
  229. package/dist/ai/source/OptionsContainer.md +62 -5
  230. package/dist/components/BbAlert/BbAlert.vue.d.ts +1 -3
  231. package/dist/components/BbAvatar/BbAvatar.vue.d.ts +1 -3
  232. package/dist/components/BbCalendar/BbCalendar.vue_vue_type_script_setup_true_lang.js +143 -140
  233. package/dist/components/BbCalendar/types.d.ts +5 -5
  234. package/dist/components/BbCalendar/useCalendarGrid.js +143 -137
  235. package/dist/components/BbCalendar/useDayGrid.js +164 -122
  236. package/dist/components/BbCalendar/useDayjsLocale.d.ts +31 -0
  237. package/dist/components/BbCalendar/useDayjsLocale.js +34 -0
  238. package/dist/components/BbCheckbox/BbCheckbox.vue_vue_type_script_setup_true_lang.js +6 -0
  239. package/dist/components/BbCheckbox/types.d.ts +13 -1
  240. package/dist/components/BbCheckboxGroup/BbCheckboxGroup.vue_vue_type_script_setup_true_lang.js +41 -51
  241. package/dist/components/BbCheckboxGroup/types.d.ts +59 -5
  242. package/dist/components/BbColorInput/BbColorInput.vue_vue_type_script_setup_true_lang.js +6 -0
  243. package/dist/components/BbColorInput/types.d.ts +13 -1
  244. package/dist/components/BbDatePicker/BbDatePicker.vue_vue_type_script_setup_true_lang.js +96 -93
  245. package/dist/components/BbDatePicker/types.d.ts +4 -4
  246. package/dist/components/BbDatePickerInput/BbDatePickerInput.vue_vue_type_script_setup_true_lang.js +328 -306
  247. package/dist/components/BbDatePickerInput/dateFieldLayout.d.ts +23 -0
  248. package/dist/components/BbDatePickerInput/dateFieldLayout.js +38 -0
  249. package/dist/components/BbDatePickerInput/types.d.ts +16 -4
  250. package/dist/components/BbDialog/BbDialog.vue_vue_type_script_setup_true_lang.js +126 -121
  251. package/dist/components/BbDialog/types.d.ts +6 -1
  252. package/dist/components/BbDropdown/AdaptiveDropdown.vue_vue_type_script_setup_true_lang.js +76 -68
  253. package/dist/components/BbDropdown/BbDropdown.vue_vue_type_script_setup_true_lang.js +249 -216
  254. package/dist/components/BbDropdown/BbDropdownGroup.vue.d.ts +11 -4
  255. package/dist/components/BbDropdown/BbDropdownGroup.vue_vue_type_script_setup_true_lang.js +48 -19
  256. package/dist/components/BbDropdown/BbDropdownList.vue_vue_type_script_setup_true_lang.js +245 -239
  257. package/dist/components/BbDropdown/DropdownPipelineResolver.vue_vue_type_script_setup_true_lang.js +120 -103
  258. package/dist/components/BbDropdown/types.d.ts +84 -39
  259. package/dist/components/BbDropdown/useDropdownContext.d.ts +2 -0
  260. package/dist/components/BbDropdown/useDropdownGroupRegistry.d.ts +61 -0
  261. package/dist/components/BbDropdownButton/BbDropdownButton.vue_vue_type_script_setup_true_lang.js +52 -50
  262. package/dist/components/BbDropzone/BbDropzone.vue_vue_type_script_setup_true_lang.js +149 -123
  263. package/dist/components/BbDropzone/types.d.ts +18 -3
  264. package/dist/components/BbDropzone/types.js +1 -0
  265. package/dist/components/BbForm/BbForm.vue.d.ts +2 -2
  266. package/dist/components/BbIcon/BbIcon.vue.d.ts +1 -3
  267. package/dist/components/BbNumberInput/BbNumberInput.vue_vue_type_script_setup_true_lang.js +7 -1
  268. package/dist/components/BbNumberInput/types.d.ts +13 -1
  269. package/dist/components/BbOffCanvas/BbOffCanvas.vue.d.ts +1 -3
  270. package/dist/components/BbOffCanvas/BbOffCanvas.vue_vue_type_script_setup_true_lang.js +197 -192
  271. package/dist/components/BbOffCanvas/hostCloseLabel.d.ts +3 -0
  272. package/dist/components/BbOffCanvas/hostCloseLabel.js +8 -0
  273. package/dist/components/BbOffCanvas/types.d.ts +6 -1
  274. package/dist/components/BbPagination/BbPagination.vue_vue_type_script_setup_true_lang.js +101 -100
  275. package/dist/components/BbRadio/BbRadio.vue_vue_type_script_setup_true_lang.js +6 -0
  276. package/dist/components/BbRadio/types.d.ts +13 -1
  277. package/dist/components/BbRadioGroup/BbRadioGroup.vue_vue_type_script_setup_true_lang.js +38 -48
  278. package/dist/components/BbRadioGroup/types.d.ts +58 -5
  279. package/dist/components/BbRating/BbRating.vue_vue_type_script_setup_true_lang.js +6 -0
  280. package/dist/components/BbRating/types.d.ts +17 -3
  281. package/dist/components/BbSelect/BbSelect.vue_vue_type_script_setup_true_lang.js +196 -215
  282. package/dist/components/BbSelect/types.d.ts +58 -4
  283. package/dist/components/BbSelectPopover/BbSelectPopover.vue_vue_type_script_setup_true_lang.js +404 -352
  284. package/dist/components/BbSelectPopover/types.d.ts +46 -6
  285. package/dist/components/BbSlider/BbSlider.vue_vue_type_script_setup_true_lang.js +7 -0
  286. package/dist/components/BbSlider/types.d.ts +13 -1
  287. package/dist/components/BbSpinner/BbSpinner.vue.d.ts +1 -3
  288. package/dist/components/BbSwitch/BbSwitch.vue_vue_type_script_setup_true_lang.js +6 -0
  289. package/dist/components/BbSwitchGroup/BbSwitchGroup.vue_vue_type_script_setup_true_lang.js +138 -148
  290. package/dist/components/BbSwitchGroup/types.d.ts +7 -2
  291. package/dist/components/BbTable/BbTable.vue.d.ts +10 -50
  292. package/dist/components/BbTable/BbTable.vue_vue_type_script_setup_true_lang.js +1112 -1010
  293. package/dist/components/BbTable/BbTableEdgeRow.d.ts +110 -0
  294. package/dist/components/BbTable/BbTableEdgeRow.js +65 -0
  295. package/dist/components/BbTable/types.d.ts +125 -55
  296. package/dist/components/BbTable/types.js +2 -0
  297. package/dist/components/BbTable/utils.js +11 -4
  298. package/dist/components/BbTabs/types.d.ts +3 -3
  299. package/dist/components/BbTag/BbTag.vue_vue_type_script_setup_true_lang.js +140 -134
  300. package/dist/components/BbTag/types.d.ts +13 -1
  301. package/dist/components/BbTextInput/BbTextInput.vue_vue_type_script_setup_true_lang.js +129 -106
  302. package/dist/components/BbTextInput/types.d.ts +29 -7
  303. package/dist/components/BbTextInput/types.js +9 -5
  304. package/dist/components/BbTextarea/BbTextarea.vue_vue_type_script_setup_true_lang.js +124 -100
  305. package/dist/components/BbTextarea/types.d.ts +29 -7
  306. package/dist/components/BbTextarea/types.js +9 -5
  307. package/dist/components/BbTimePickerInput/BbTimePickerInput.vue_vue_type_script_setup_true_lang.js +245 -239
  308. package/dist/components/BbTimePickerInput/types.d.ts +13 -1
  309. package/dist/components/BbTree/types.d.ts +1 -1
  310. package/dist/components/CommonField/CommonField.vue.d.ts +1 -1
  311. package/dist/components/CommonField/CommonField.vue_vue_type_script_setup_true_lang.js +114 -78
  312. package/dist/components/CommonField/types.d.ts +22 -3
  313. package/dist/components/CommonFieldInput/CommonFieldInput.vue_vue_type_script_setup_true_lang.js +4 -4
  314. package/dist/components/CommonTimeSelector/CommonTimeSelector.vue.d.ts +1 -1
  315. package/dist/components/CommonTimeSelector/CommonTimeSelector.vue_vue_type_script_setup_true_lang.js +97 -92
  316. package/dist/components/CommonTimeSelector/useMeridiem.d.ts +19 -0
  317. package/dist/components/CommonTimeSelector/useMeridiem.js +41 -0
  318. package/dist/components/FlatListBox/FlatListBox.vue_vue_type_script_setup_true_lang.js +70 -62
  319. package/dist/components/FlatListBox/types.d.ts +5 -0
  320. package/dist/components/GroupedListBox/GroupedListBox.vue_vue_type_script_setup_true_lang.js +142 -134
  321. package/dist/components/GroupedListBox/types.d.ts +5 -0
  322. package/dist/components/ListBox/ListBox.vue_vue_type_script_setup_true_lang.js +5 -0
  323. package/dist/components/ListBox/types.d.ts +5 -0
  324. package/dist/components/OptionsContainer/OptionsContainer.vue_vue_type_script_setup_true_lang.js +73 -65
  325. package/dist/components/OptionsContainer/types.d.ts +28 -3
  326. package/dist/composables/useBbTabsContext.d.ts +1 -1
  327. package/dist/composables/useBbTabsContext.js +1 -1
  328. package/dist/composables/useCharacterCounter.d.ts +33 -0
  329. package/dist/composables/useCharacterCounter.js +29 -0
  330. package/dist/composables/useHydrated.d.ts +16 -4
  331. package/dist/composables/useHydrated.js +27 -9
  332. package/dist/composables/useItemsGetter.d.ts +41 -9
  333. package/dist/composables/useItemsGetter.js +67 -45
  334. package/dist/composables/usePrefill.d.ts +4 -3
  335. package/dist/composables/usePrefill.js +2 -2
  336. package/dist/deprecation/ai-deprecations.json.d.ts +143 -0
  337. package/dist/deprecation/ai-deprecations.json.js +1 -1
  338. package/dist/directives/createPopoverDirective.js +17 -7
  339. package/dist/i18n/locales/cs.json +12 -3
  340. package/dist/i18n/locales/da.json +12 -3
  341. package/dist/i18n/locales/de.json +12 -3
  342. package/dist/i18n/locales/el.json +12 -3
  343. package/dist/i18n/locales/en.json +10 -1
  344. package/dist/i18n/locales/es.json +10 -1
  345. package/dist/i18n/locales/fi.json +12 -3
  346. package/dist/i18n/locales/fr.json +10 -1
  347. package/dist/i18n/locales/hu.json +12 -3
  348. package/dist/i18n/locales/it.json +10 -1
  349. package/dist/i18n/locales/ja.json +12 -3
  350. package/dist/i18n/locales/ko.json +12 -3
  351. package/dist/i18n/locales/nb.json +12 -3
  352. package/dist/i18n/locales/nl.json +12 -3
  353. package/dist/i18n/locales/pl.json +12 -3
  354. package/dist/i18n/locales/pt.json +10 -1
  355. package/dist/i18n/locales/ro.json +12 -3
  356. package/dist/i18n/locales/ru.json +12 -3
  357. package/dist/i18n/locales/sv.json +12 -3
  358. package/dist/i18n/locales/tr.json +12 -3
  359. package/dist/i18n/locales/uk.json +12 -3
  360. package/dist/i18n/locales/zh-cn.json +12 -3
  361. package/dist/index.d.ts +9 -0
  362. package/dist/llms-full.txt +23265 -19932
  363. package/dist/llms-medium.txt +71 -53
  364. package/dist/llms.txt +5 -6
  365. package/dist/locale-blueprint.json +10 -1
  366. package/dist/plugin.js +6 -4
  367. package/dist/runtime/nuxt-plugin.js +2 -2
  368. package/dist/styles.css +2 -2
  369. package/dist/types/CommonProps.d.ts +13 -3
  370. package/dist/types/FieldLayout.d.ts +7 -0
  371. package/dist/types/FieldLayout.js +8 -0
  372. package/dist/types/ItemsProvider.d.ts +94 -0
  373. package/dist/types/passthrough.d.ts +17 -1
  374. package/dist/types/passthrough.js +8 -8
  375. package/dist/types/ptComponentMap.d.ts +4 -4
  376. package/dist/utilities/functions/animationsSettled.d.ts +7 -0
  377. package/dist/utilities/functions/animationsSettled.js +6 -0
  378. package/dist/utilities/functions/elementLabel.d.ts +8 -0
  379. package/dist/utilities/functions/elementLabel.js +6 -0
  380. package/dist/utilities/functions/parseSize.d.ts +2 -1
  381. package/dist/utilities/functions/readableValue.d.ts +6 -0
  382. package/dist/utilities/functions/readableValue.js +4 -0
  383. package/dist/utilities/functions/settlesVisible.d.ts +20 -0
  384. package/dist/utilities/functions/settlesVisible.js +18 -0
  385. package/dist/utilities/functions/throttle.d.ts +1 -4
  386. package/dist/utilities/functions/throttle.js +1 -4
  387. package/dist/utilities/functions/warnRemovedAttrs.d.ts +12 -0
  388. package/dist/utilities/functions/warnRemovedAttrs.js +12 -12
  389. package/dist/utils/versionCheck.js +1 -1
  390. package/dist/vite.js +1 -1
  391. package/llms.txt +5 -6
  392. package/package.json +28 -17
  393. package/scripts/README.md +35 -33
  394. package/scripts/lib/css-class-check.mjs +4 -1
  395. package/scripts/lib/css-local-check.mjs +198 -33
  396. package/scripts/lib/ensure-manifest.mjs +80 -7
  397. package/scripts/lib/eslint-disable.mjs +4 -0
  398. package/scripts/lib/eslint-plugin.d.ts +5 -1
  399. package/scripts/lib/eslint-plugin.mjs +180 -2
  400. package/scripts/lib/example-checks.mjs +337 -0
  401. package/scripts/lib/guide-claims.mjs +452 -0
  402. package/scripts/lib/hand-imported-styles.mjs +7 -2
  403. package/scripts/lib/items-provider-context.mjs +842 -0
  404. package/scripts/lib/linked-target.mjs +30 -0
  405. package/scripts/lib/mcp-config.mjs +6 -0
  406. package/scripts/lib/slot-renames.mjs +5 -6
  407. package/scripts/lib/toolchain-check.mjs +224 -0
  408. package/scripts/lib/validate-bb-markup.mjs +452 -25
  409. package/dist/ai/recipes/inertia/command-palette.md +0 -311
  410. package/dist/ai/recipes/nuxt/command-palette.md +0 -300
  411. package/dist/ai/recipes/vue/command-palette.md +0 -297
package/README.md CHANGED
@@ -327,13 +327,13 @@ part you need.
327
327
 
328
328
  ### CLI commands
329
329
 
330
- | Command | What it does |
331
- | ------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------ |
332
- | `npx bitboss-ui ai-init [--update] [--no-mcp]` | Writes the agent pointer files and registers the MCP server (installs its optional peers). |
333
- | `npx bitboss-ui check [paths…] [--fix] [--json]` | Validates `Bb*` markup in `.vue` / `.md` files against the installed version; `--fix` applies the v2 → v3 renames first. |
334
- | `npx bitboss-ui changelog --since <version> [--until <version>] [--json]` | Lists the **breaking** changes between the version you are on and the installed one — what breaks if you bump. |
335
- | `npx bitboss-ui mcp` | Starts the MCP server on stdio (harnesses launch it for you after `ai-init`). |
336
- | `npx bitboss-ui --help` | Every command and flag. |
330
+ | Command | What it does |
331
+ | ------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
332
+ | `npx bitboss-ui ai-init [--update] [--no-mcp]` | Writes the agent pointer files and registers the MCP server (installs its optional peers). |
333
+ | `npx bitboss-ui check [paths… \| --changed] [--fix] [--json]` | Validates `Bb*` markup in `.vue` / `.md` files against the installed version; `--fix` applies the v2 → v3 renames first; `--changed` checks only the files git sees changed vs HEAD (plus untracked). |
334
+ | `npx bitboss-ui changelog --since <version> [--until <version>] [--json]` | Lists the **breaking** changes between the version you are on and the installed one — what breaks if you bump. |
335
+ | `npx bitboss-ui mcp` | Starts the MCP server on stdio (harnesses launch it for you after `ai-init`). |
336
+ | `npx bitboss-ui --help` | Every command and flag. |
337
337
 
338
338
  ### ESLint plugin
339
339
 
@@ -482,6 +482,9 @@ still name the button:
482
482
  ```
483
483
 
484
484
  `BbSpinner` is not covered: without `label` it is decorative, which is correct.
485
+ A `BbBadge` or `BbProgress` marked `aria-hidden="true"` (or `:aria-hidden="true"`)
486
+ is decorative too and is skipped (a `BbButton` is not: it stays focusable); a dynamic `:aria-hidden="flag"` is still checked, since it
487
+ needs a name whenever it is `false`.
485
488
  For raw HTML controls, use `eslint-plugin-vuejs-accessibility`.
486
489
 
487
490
  #### v-model on a const reactive(): `no-reactive-v-model`
@@ -891,6 +891,96 @@ function historyLines(entry) {
891
891
  ];
892
892
  }
893
893
 
894
+ /**
895
+ * Q57.6: the `css.classes` of the internal parts a component mounts
896
+ * (`CommonPopover`, `CommonField`, the listboxes), by part. The class surface
897
+ * lists a block once, on its owner, and an internal owner is no component a
898
+ * consumer asks about: `.bb-common-popover__bubble` was on no BbDropdown or
899
+ * BbPopover answer. A public child (BbBaseButton) answers for its own.
900
+ */
901
+ function internalClasses(entry, manifest) {
902
+ const byName = new Map(manifest.components.map((c) => [c.name, c]));
903
+ const out = {};
904
+ const walk = (nodes = []) => {
905
+ for (const node of nodes) {
906
+ if (node.kind !== 'internal') continue;
907
+ const classes = byName.get(node.name)?.css?.classes;
908
+ if (classes && !out[node.name]) out[node.name] = classes;
909
+ walk(node.children);
910
+ }
911
+ };
912
+ walk(entry.tree?.nodes);
913
+ return out;
914
+ }
915
+
916
+ /** `css` of a get_component answer: its own classes, plus `shared` (Q57.6). */
917
+ function cssAnswer(entry, manifest) {
918
+ const shared = internalClasses(entry, manifest);
919
+ return Object.keys(shared).length ? { ...entry.css, shared } : entry.css;
920
+ }
921
+
922
+ /** Every `.bb-*` block a component renders, its own and its internal parts'. */
923
+ function renderedBlocks(entry, manifest) {
924
+ return new Set([
925
+ ...Object.keys(entry.css?.classes ?? {}),
926
+ ...Object.values(internalClasses(entry, manifest)).flatMap(Object.keys),
927
+ ]);
928
+ }
929
+
930
+ /**
931
+ * Q57.7: does a changelog row reach this component? By name, or — for a CSS
932
+ * rename (`surface: cssVar | class`), whose Component cell is a selector
933
+ * (`.bb-table`) or prose ("every form control") — by a `.bb-*` block of the
934
+ * row the component renders: `--padding-y → --py` on `.bb-table` never
935
+ * reached BbTable's history or `list_changes({ component: 'BbTable' })`.
936
+ */
937
+ function rowReaches(row, name, blocks) {
938
+ if (
939
+ (row.components ?? []).some((c) => c.toLowerCase() === name.toLowerCase())
940
+ )
941
+ return true;
942
+ if (!blocks || (row.surface !== 'cssVar' && row.surface !== 'class'))
943
+ return false;
944
+ const text = [...(row.components ?? []), row.from, row.to].join(' ');
945
+ return [...text.matchAll(/\.(bb-[a-z0-9]+(?:-[a-z0-9]+)*)/g)].some((m) =>
946
+ blocks.has(m[1])
947
+ );
948
+ }
949
+
950
+ /** The CSS renames (cssVar, class) that reach a component, one line each. */
951
+ function cssRenameLines(entry, manifest) {
952
+ if (!existsSync(CHANGELOG_PATH)) return [];
953
+ const doc = JSON.parse(readFileSync(CHANGELOG_PATH, 'utf-8'));
954
+ const blocks = renderedBlocks(entry, manifest);
955
+ return (doc.breaking ?? [])
956
+ .filter(
957
+ (row) =>
958
+ (row.surface === 'cssVar' || row.surface === 'class') &&
959
+ rowReaches(row, entry.name, blocks)
960
+ )
961
+ .map(
962
+ (row) =>
963
+ `${/^f\d/.test(row.id) ? `${row.id} ` : ''}${row.surface} ${row.from} → ${row.to ?? 'removed'}${row.firstReleasedIn ? ` (${row.firstReleasedIn})` : ''}`
964
+ );
965
+ }
966
+
967
+ /**
968
+ * The history lines, plus the CSS locals renamed on the component's blocks;
969
+ * the class renames only as a count (include: ['history'] lists them).
970
+ */
971
+ function historyWithCss(entry, manifest) {
972
+ const css = cssRenameLines(entry, manifest);
973
+ const vars = css.filter((line) => / cssVar |^cssVar /.test(line));
974
+ const classes = css.length - vars.length;
975
+ return [
976
+ ...historyLines(entry),
977
+ ...vars,
978
+ ...(classes
979
+ ? [`${classes} .bb-* class rename(s) on its blocks: include: ['history']`]
980
+ : []),
981
+ ];
982
+ }
983
+
894
984
  /** The compact `component` of the summary answer. */
895
985
  function summarizeComponent(entry, manifest) {
896
986
  const shared = sharedProps(manifest);
@@ -932,9 +1022,10 @@ function summarizeComponent(entry, manifest) {
932
1022
  ...(entry.cssProps?.length
933
1023
  ? { cssProps: entry.cssProps.map((c) => c.name ?? c) }
934
1024
  : {}),
935
- ...(entry.removed?.length || entry.renamed?.length
936
- ? { history: historyLines(entry) }
937
- : {}),
1025
+ ...(() => {
1026
+ const history = historyWithCss(entry, manifest);
1027
+ return history.length ? { history } : {};
1028
+ })(),
938
1029
  ...(entry.attrTargets ? { attrTargets: entry.attrTargets } : {}),
939
1030
  ...(entry.referenceOnly ? { referenceOnly: true } : {}),
940
1031
  };
@@ -1233,7 +1324,9 @@ function getComponent({
1233
1324
  ...(wanted.has('cssProps') && entry.cssProps
1234
1325
  ? { cssProps: entry.cssProps }
1235
1326
  : {}),
1236
- ...(wanted.has('css') && entry.css ? { css: entry.css } : {}),
1327
+ ...(wanted.has('css') && entry.css
1328
+ ? { css: cssAnswer(entry, manifest) }
1329
+ : {}),
1237
1330
  ...(wanted.has('ptProps')
1238
1331
  ? (() => {
1239
1332
  const { kept, ...rest } = capParts(ptRows, 'PtProps');
@@ -1241,7 +1334,11 @@ function getComponent({
1241
1334
  })()
1242
1335
  : {}),
1243
1336
  ...(wanted.has('history')
1244
- ? { removed: entry.removed ?? [], renamed: entry.renamed ?? [] }
1337
+ ? {
1338
+ removed: entry.removed ?? [],
1339
+ renamed: entry.renamed ?? [],
1340
+ cssRenames: cssRenameLines(entry, manifest),
1341
+ }
1245
1342
  : {}),
1246
1343
  ...(wanted.has('contract')
1247
1344
  ? (() => {
@@ -1308,15 +1405,19 @@ function getComponent({
1308
1405
  ...(wanted.has('tree') && entry.tree ? { tree: entry.tree } : {}),
1309
1406
  // The rendered `.bb-*` classes (Q46.5) are for tools (`check`,
1310
1407
  // `validate`); an agent restyles through pt and the locals.
1311
- ...(wanted.has('css') && entry.css ? { css: entry.css } : {}),
1408
+ ...(wanted.has('css') && entry.css
1409
+ ? { css: cssAnswer(entry, manifest) }
1410
+ : {}),
1312
1411
  };
1313
1412
  // `removed` and `renamed` repeat each other with migration metadata; one
1314
1413
  // line per old name answers "what happened to X" (include 'history' for
1315
1414
  // the records the fixers use).
1316
1415
  if (wanted.has('history')) {
1317
1416
  if (entry.renamed) component.renamed = entry.renamed;
1318
- } else if (entry.removed?.length || entry.renamed?.length) {
1319
- component.history = historyLines(entry);
1417
+ component.cssRenames = cssRenameLines(entry, manifest);
1418
+ } else {
1419
+ const history = historyWithCss(entry, manifest);
1420
+ if (history.length) component.history = history;
1320
1421
  delete component.removed;
1321
1422
  }
1322
1423
 
@@ -1373,7 +1474,7 @@ function getComponent({
1373
1474
  : {}),
1374
1475
  }
1375
1476
  : {}),
1376
- hint: `Structured API above is complete. Read guide sections with get_component({ name: '${entry.name}', sections: ['<title from guide.sections>'] }); add include: ['tree' | 'cssProps' | 'css' | 'ptProps' | 'history' | 'contract'] for the component tree, CSS variables with descriptions, the .bb-* classes it renders, every pt:* row, the full v2/beta rename records, or the whole contract. search_docs finds a topic across all docs.`,
1477
+ hint: `Structured API above is complete. Read guide sections with get_component({ name: '${entry.name}', sections: ['<title from guide.sections>'] }); add include: ['tree' | 'cssProps' | 'css' | 'ptProps' | 'history' | 'contract'] for the component tree, CSS variables with descriptions, the .bb-* classes it renders (css.shared: the ones its internal parts render), every pt:* row, the full v2/beta rename records (cssRenames: the CSS local and class renames on its blocks), or the whole contract. search_docs finds a topic across all docs.`,
1377
1478
  };
1378
1479
  }
1379
1480
 
@@ -1590,7 +1691,7 @@ function listTokens({ filter } = {}) {
1590
1691
  needle && tokens.length === 0
1591
1692
  ? `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. ${FONT_NOTE}`
1592
1693
  : FONT_NOTE +
1593
- ' 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. `conditional` is a value that applies only under an @supports condition (`when`) — e.g. an auto-contrast formula with literal fallbacks for older browsers; pinning a fallback literal defeats the formula. `kind` says what you may set: "knob" is yours; "derived" is a formula recomputed at every theme boundary, so setting it stops it tracking the knob it came from — set that knob instead; "knob-tracking" is a knob that follows another until you pin it, and the pin must be repeated at every boundary you use, .dark included. Component-level unprefixed tokens are documented per component; see the design-tokens guide via get_guide.',
1694
+ ' 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. `conditional` is a value that applies only under an @supports condition (`when`) — e.g. an auto-contrast formula with literal fallbacks for older browsers; pinning a fallback literal defeats the formula. `kind` says what you may set: "knob" is yours; "derived" is a formula recomputed at every theme boundary: theme-wide, set the knob it came from (a derived value you set stops tracking it); a scoped override (one `.bb-table`) is fine, but stops at a nested .dark / .bb-theme; "knob-tracking" is a knob that follows another until you pin it, and the pin must be repeated at every boundary you use, .dark included. Component-level unprefixed tokens are documented per component; see the design-tokens guide via get_guide.',
1594
1695
  };
1595
1696
  }
1596
1697
 
@@ -2557,6 +2658,7 @@ function listChanges({
2557
2658
  // Resolve the component the way get_component does ('bb-select',
2558
2659
  // 'Select'), and say so when it is no component at all — an empty list
2559
2660
  // would read as "nothing breaks".
2661
+ let blocks = null;
2560
2662
  if (component) {
2561
2663
  const resolved = resolveComponent(loadComponentsManifest(), component);
2562
2664
  // A retired name (BbTabsPanes) is still a key in the rows it renamed.
@@ -2568,15 +2670,17 @@ function listChanges({
2568
2670
  didYouMean: nearestComponents(loadComponentsManifest(), component),
2569
2671
  };
2570
2672
  }
2571
- if (resolved?.entry) component = resolved.entry.name;
2673
+ if (resolved?.entry) {
2674
+ component = resolved.entry.name;
2675
+ // Q57.7: a CSS rename reaches it through the blocks it renders.
2676
+ blocks = renderedBlocks(resolved.entry, loadComponentsManifest());
2677
+ }
2572
2678
  }
2679
+
2573
2680
  const rows = detail === 'rows';
2574
2681
  const filtered = (doc.breaking ?? []).filter(
2575
2682
  (row) =>
2576
- (!component ||
2577
- (row.components ?? []).some(
2578
- (c) => c.toLowerCase() === String(component).toLowerCase()
2579
- )) &&
2683
+ (!component || rowReaches(row, String(component), blocks)) &&
2580
2684
  (!surface ||
2581
2685
  (row.surface ?? (row.kind === 'rename' ? 'prop' : null)) === surface) &&
2582
2686
  (!kind || row.kind === kind)
@@ -11,6 +11,8 @@
11
11
  * - .github/copilot-instructions.md fragment (GitHub Copilot)
12
12
  * - .claude/skills/bitboss-ui/SKILL.md (Claude Code)
13
13
  * - .windsurf/rules/bitboss-ui.md (Windsurf)
14
+ * - `vueCompilerOptions.checkUnknownComponents: true` in the
15
+ * tsconfig (Q60.6), unless the project already names it
14
16
  * Also registers the `bitboss-ui mcp` server for Claude Code,
15
17
  * Cursor and VS Code and installs its optional peers
16
18
  * (`@modelcontextprotocol/sdk`, `zod`) with the project's package
@@ -85,6 +87,11 @@ import {
85
87
  handImportedStylesFindings,
86
88
  } from '../scripts/lib/hand-imported-styles.mjs';
87
89
  import { syncProjectVariantDts } from '../scripts/lib/project-variant-dts.mjs';
90
+ import { refuseLinkedTarget } from '../scripts/lib/linked-target.mjs';
91
+ import {
92
+ ensureCheckUnknownComponents,
93
+ toolchainWarnings,
94
+ } from '../scripts/lib/toolchain-check.mjs';
88
95
  import { dirname, isAbsolute, join, relative, resolve } from 'node:path';
89
96
  import { fileURLToPath, pathToFileURL } from 'node:url';
90
97
  import { parseArgs } from 'node:util';
@@ -99,6 +106,7 @@ import {
99
106
  import {
100
107
  loadManifest,
101
108
  registeredRuleNames,
109
+ presetDefinitions,
102
110
  validateMarkdown,
103
111
  validateVueSnippet,
104
112
  } from '../scripts/lib/validate-bb-markup.mjs';
@@ -141,7 +149,7 @@ function coreRules(version) {
141
149
  11. **Variants are yours to add**: the shipped \`variant\` names are a floor, not a ceiling. When the design needs a colour the library doesn't ship (soft status badges, a brand button tone), **register the name** in the build plugin's \`badgeVariants\`/\`buttonVariants\`/\`alertVariants\`/… and **style \`.bb-badge--<name>\`** (etc.) in a project stylesheet loaded after \`bitboss-ui/styles.css\`. Do both halves — a registered name with no CSS ships an unstyled pill, and CSS with no registration fails \`vue-tsc\`. After registering, run \`npx bitboss-ui check\`: it writes the project's \`bitboss-ui.d.ts\` so the new name type-checks before Vite has run. Never write an unregistered name, and never downgrade the design to a neutral shipped variant to avoid registering. Canonical palette + snippet: \`${KNOWLEDGE_BASE}/guides/design-language.md\` § Getting soft semantic badges.
142
150
  12. **Never name your own components \`Bb…\`** — that prefix is bitboss-ui's. Use your app's prefix (\`App…\`, \`Acme…\`). \`check\` leaves an app's own \`Bb*\` component alone but warns: a future bitboss-ui component could take the name.
143
151
  13. **Set \`locale\` explicitly** in the build plugin (\`bitbossUi({ locale: 'it' })\` / nuxt \`bitboss: { locale: 'it' }\`) for any app that is not English: the built-in strings default to English (\`'en'\`, since 3.0.0-beta.41; it was \`'it'\`).
144
- 14. **After writing bitboss-ui markup**, run \`npx bitboss-ui check\` — validates \`Bb*\` usage against the installed \`components.json\` and catches invented/removed props before review.
152
+ 14. **After writing bitboss-ui markup**, run \`npx bitboss-ui check\` — validates \`Bb*\` usage against the installed \`components.json\` and catches invented/removed props before review. In an edit loop, \`npx bitboss-ui check --changed\` checks only the files git sees changed; run the full check before you finish.
145
153
 
146
154
  After upgrading bitboss-ui, re-run: \`npx bitboss-ui ai-init\``;
147
155
  }
@@ -204,6 +212,7 @@ ${coreRules(version)}
204
212
  }
205
213
 
206
214
  function upsertMarkedFile(filePath, fragment, { createHeader } = {}) {
215
+ refuseLinkedTarget(filePath);
207
216
  const existed = existsSync(filePath);
208
217
 
209
218
  if (!existed) {
@@ -231,6 +240,7 @@ function upsertMarkedFile(filePath, fragment, { createHeader } = {}) {
231
240
  }
232
241
 
233
242
  function writeWholeFile(filePath, content) {
243
+ refuseLinkedTarget(filePath);
234
244
  const existed = existsSync(filePath);
235
245
  mkdirSync(dirname(filePath), { recursive: true });
236
246
  writeFileSync(filePath, content, 'utf-8');
@@ -294,6 +304,15 @@ function aiInit({ mcp = true } = {}) {
294
304
  )
295
305
  ),
296
306
  ];
307
+ // Q60.6: unknown-component checking is opt-in in Vue Language Tools 3.
308
+ const flag = tryWrite('tsconfig checkUnknownComponents', () =>
309
+ ensureCheckUnknownComponents(projectRoot)
310
+ );
311
+ if (flag)
312
+ results.push({
313
+ ...flag,
314
+ path: flag.reason ? `${flag.path} (${flag.reason})` : flag.path,
315
+ });
297
316
 
298
317
  if (mcp) {
299
318
  for (const result of ensureMcpConfigs(projectRoot)) {
@@ -352,6 +371,10 @@ function aiInit({ mcp = true } = {}) {
352
371
  'MCP: skipped (--no-mcp). Re-run without it to let agents query the knowledge base through the bitboss-ui MCP server instead of reading files.'
353
372
  );
354
373
  }
374
+ // Q61.7: Laravel's vue-starter-kit (and others) git-ignore these.
375
+ console.log(
376
+ "Some starters (Laravel's vue-starter-kit) git-ignore AGENTS.md, CLAUDE.md, .claude, .cursor and .mcp.json: teammates won't see these files until you un-ignore them."
377
+ );
355
378
  console.log('Re-run after upgrading bitboss-ui to refresh the pointers.');
356
379
  console.log(
357
380
  'Tip: `npx bitboss-ui ai-init --update` is the same command (idempotent).'
@@ -500,6 +523,45 @@ function resolveCheckFiles(cwd, patterns) {
500
523
  return [...matched].sort();
501
524
  }
502
525
 
526
+ /**
527
+ * `check --changed` (Q57.11): the files git reports changed against HEAD
528
+ * (staged or not) plus the untracked ones, under `cwd`, minus the sweep's skip
529
+ * list. `files` are the .vue/.md ones `check` validates; `all` (any extension)
530
+ * feeds the stylesheet and styles-import scans, which read other files too.
531
+ * @returns {{ files: string[], all: string[] } | { error: string }}
532
+ */
533
+ function changedCheckFiles(cwd) {
534
+ const git = (args) =>
535
+ spawnSync('git', args, {
536
+ cwd,
537
+ encoding: 'utf-8',
538
+ maxBuffer: 64 * 1024 * 1024,
539
+ });
540
+ const diff = git(['diff', '--name-only', '--relative', '-z', 'HEAD', '--']);
541
+ const untracked = git(['ls-files', '--others', '--exclude-standard', '-z']);
542
+ const failed = [diff, untracked].find((r) => r.error || r.status !== 0);
543
+ if (failed)
544
+ return {
545
+ error:
546
+ 'check --changed: git could not list the changed files here (not a git repository, git missing, or no commit yet): ' +
547
+ (failed.error?.message ?? failed.stderr.trim().split('\n')[0]),
548
+ };
549
+ const all = [
550
+ ...new Set(`${diff.stdout}${untracked.stdout}`.split('\0').filter(Boolean)),
551
+ ]
552
+ .filter((rel) => !inSkippedDir(rel))
553
+ .map((rel) => join(cwd, rel))
554
+ // A deleted file is a change with nothing left to check.
555
+ .filter((path) => existsSync(path) && statSync(path).isFile())
556
+ .sort();
557
+ return {
558
+ files: all.filter((path) =>
559
+ CHECK_EXTENSIONS.some((ext) => path.endsWith(ext))
560
+ ),
561
+ all,
562
+ };
563
+ }
564
+
503
565
  /**
504
566
  * `4 .vue + 8 .md` — a plain file count on its own ("715 file(s)") reads as
505
567
  * "715 files carefully checked" when SNT-007 showed it can just as easily be
@@ -774,9 +836,19 @@ async function checkCommand(
774
836
  allowComponents,
775
837
  manifest: manifestOverride,
776
838
  fix,
839
+ changed: changedOnly,
777
840
  }
778
841
  ) {
779
842
  const projectRoot = process.cwd();
843
+ if (changedOnly && globs.length) {
844
+ console.error('[bitboss-ui] check: pass paths or `--changed`, not both.');
845
+ process.exit(1);
846
+ }
847
+ const changed = changedOnly ? changedCheckFiles(projectRoot) : null;
848
+ if (changed && 'error' in changed) {
849
+ console.error(`[bitboss-ui] ${changed.error}`);
850
+ process.exit(1);
851
+ }
780
852
 
781
853
  /*
782
854
  * `--manifest` answers the question `check` could not: "which of my files
@@ -847,7 +919,7 @@ async function checkCommand(
847
919
  ? join(dirname(dirname(manifestPath)), 'styles.css')
848
920
  : join(PACKAGE_ROOT, 'dist', 'styles.css');
849
921
  const knownTokens = loadKnownTokens(stylesPath);
850
- const files = resolveCheckFiles(projectRoot, globs);
922
+ const files = changed ? changed.files : resolveCheckFiles(projectRoot, globs);
851
923
 
852
924
  // CHK-ALLOWCOMPONENTS: `Bb` is a naming convention, not proof of ownership.
853
925
  // An app component called `BbRichEditor` is not invalid library markup, and
@@ -894,15 +966,22 @@ async function checkCommand(
894
966
  // Q46.6: every `var(--x)` the project reads, from a whole-project sweep
895
967
  // (explicit paths included): a local or token the app reads itself is its
896
968
  // own, never "set and unread".
897
- const projectReads = new Set();
898
- for (const path of collectCheckFiles(
969
+ // Q57.11: one walk and one read per file serve every project-wide sweep
970
+ // below (reads, registered rules, the style scan) and the per-file loop.
971
+ const projectSources = collectCheckFiles(
899
972
  projectRoot,
900
973
  projectRoot,
901
974
  HAND_IMPORTED_STYLES_EXTENSIONS
902
- ))
975
+ );
976
+ const texts = new Map();
977
+ const readText = (path) => {
978
+ if (!texts.has(path)) texts.set(path, readFileSync(path, 'utf-8'));
979
+ return texts.get(path);
980
+ };
981
+ const projectReads = new Set();
982
+ for (const path of projectSources)
903
983
  try {
904
- for (const name of localReads(readFileSync(path, 'utf-8')))
905
- projectReads.add(name);
984
+ for (const name of localReads(readText(path))) projectReads.add(name);
906
985
  } catch {
907
986
  /* unreadable: its reads are unknown, which only means fewer passes */
908
987
  }
@@ -918,15 +997,17 @@ async function checkCommand(
918
997
  // Q54.2: the rules the project registers with `defineRule`, from the same
919
998
  // whole-project sweep, so a string rule nobody registered is caught.
920
999
  const registeredRules = { names: new Set(), dynamic: false };
921
- for (const path of collectCheckFiles(projectRoot, projectRoot, [
922
- '.ts',
923
- '.js',
924
- '.mjs',
925
- '.cjs',
926
- '.vue',
927
- ]))
1000
+ const presets = new Map();
1001
+ const RULE_EXTENSIONS = ['.ts', '.js', '.mjs', '.cjs', '.vue'];
1002
+ for (const path of projectSources.filter((file) =>
1003
+ RULE_EXTENSIONS.some((ext) => file.endsWith(ext))
1004
+ ))
928
1005
  try {
929
- const found = registeredRuleNames(readFileSync(path, 'utf-8'));
1006
+ const text = readText(path);
1007
+ // Q57.3: the project's `definePreset` wrappers, by name.
1008
+ for (const [name, preset] of presetDefinitions(text))
1009
+ presets.set(name, preset);
1010
+ const found = registeredRuleNames(text);
930
1011
  for (const name of found.names) registeredRules.names.add(name);
931
1012
  if (found.dynamic) registeredRules.dynamic = true;
932
1013
  } catch {
@@ -937,6 +1018,7 @@ async function checkCommand(
937
1018
  allowComponents: allowedComponents,
938
1019
  projectReads,
939
1020
  registeredRules,
1021
+ presets,
940
1022
  };
941
1023
 
942
1024
  const findings = [];
@@ -959,7 +1041,7 @@ async function checkCommand(
959
1041
  const wantHints = !process.argv.includes('--no-hints');
960
1042
  for (const file of files) {
961
1043
  const relPath = relative(projectRoot, file);
962
- const content = readFileSync(file, 'utf-8');
1044
+ const content = readText(file);
963
1045
  const { findings: fileFindings } = file.endsWith('.md')
964
1046
  ? validateMarkdown(content, manifest, validateOptions)
965
1047
  : validateVueSnippet(content, manifest, validateOptions);
@@ -994,21 +1076,24 @@ async function checkCommand(
994
1076
  }
995
1077
 
996
1078
  for (const [name, file] of projectLocal) warnLocal(name, file);
1079
+ // Q60.6: a `vue-tsc` below 3 and a missing `checkUnknownComponents`, read
1080
+ // from package.json and the tsconfig. One line each, never fatal.
1081
+ warnings.push(...toolchainWarnings(projectRoot));
997
1082
 
998
1083
  // Q25: a hand import of `bitboss-ui/styles.css` while the runtime plugin
999
1084
  // injects it. Project-level — the answer needs the build config — so it
1000
1085
  // reads the style and script files too; with explicit paths, only those.
1001
- const styleScan = globs.length
1002
- ? files
1003
- : collectCheckFiles(
1004
- projectRoot,
1005
- projectRoot,
1006
- HAND_IMPORTED_STYLES_EXTENSIONS
1007
- );
1086
+ // `--changed`: every changed file, stylesheets and scripts included.
1087
+ const styleScan = changed
1088
+ ? changed.all
1089
+ : globs.length
1090
+ ? files
1091
+ : projectSources;
1008
1092
  findings.push(
1009
1093
  ...handImportedStylesFindings(
1010
1094
  projectRoot,
1011
- styleScan.map((path) => ({ path, relPath: relative(projectRoot, path) }))
1095
+ styleScan.map((path) => ({ path, relPath: relative(projectRoot, path) })),
1096
+ readText
1012
1097
  )
1013
1098
  );
1014
1099
  // Q46.5: `.bb-*` selectors in the app's stylesheets (the `.vue` `<style>`
@@ -1016,7 +1101,7 @@ async function checkCommand(
1016
1101
  for (const path of styleScan) {
1017
1102
  if (!/\.(?:css|scss|sass|less|pcss|postcss|styl)$/.test(path)) continue;
1018
1103
  const relPath = relative(projectRoot, path);
1019
- const content = readFileSync(path, 'utf-8');
1104
+ const content = readText(path);
1020
1105
  for (const finding of [
1021
1106
  ...cssClassFindings(content, manifest.cssSurface, { stylesheet: true }),
1022
1107
  // Q46.6: custom properties set where nothing reads them.
@@ -1074,6 +1159,14 @@ async function checkCommand(
1074
1159
  const judgedAgainst = manifestOverride
1075
1160
  ? manifestVersionOf(manifestPath)
1076
1161
  : packageVersion();
1162
+ if (changed && !jsonMode) {
1163
+ console.log(
1164
+ `[bitboss-ui] check --changed: ${files.length} .vue/.md file(s) changed vs HEAD (untracked included).\n` +
1165
+ ' Unchanged files are not validated, and the styles-import scan reads only the\n' +
1166
+ ' changed files; the project-wide context (var() reads, defineRule names, local\n' +
1167
+ ' Bb* components) still comes from the whole project. Run a full `check` before merging.'
1168
+ );
1169
+ }
1077
1170
  if (manifestOverride && !jsonMode) {
1078
1171
  console.log(
1079
1172
  `[bitboss-ui] check: judging against bitboss-ui ${judgedAgainst} (--manifest), NOT the installed ${packageVersion()}.\n` +
@@ -1090,6 +1183,7 @@ async function checkCommand(
1090
1183
  hints,
1091
1184
  suppressed,
1092
1185
  files: files.length,
1186
+ ...(changed ? { changed: true } : {}),
1093
1187
  manifestVersion: judgedAgainst,
1094
1188
  installedVersion: packageVersion(),
1095
1189
  },
@@ -1109,6 +1203,12 @@ async function checkCommand(
1109
1203
  // markup is itself the thing that broke, silently (SWP-016). A bare
1110
1204
  // sweep finding nothing is a different, legitimate case (a package with
1111
1205
  // no .vue files yet), so it still passes.
1206
+ if (changed) {
1207
+ console.log(
1208
+ '[bitboss-ui] check --changed: no changed .vue/.md files — nothing to validate.'
1209
+ );
1210
+ return;
1211
+ }
1112
1212
  if (globs.length > 0 && !allowEmpty) {
1113
1213
  console.error(
1114
1214
  `[bitboss-ui] check: no .vue/.md files matched ${globs.map((g) => `\`${g}\``).join(', ')} — nothing was validated. ` +
@@ -1184,10 +1284,12 @@ Commands:
1184
1284
  server for Claude Code (.mcp.json), Cursor
1185
1285
  (.cursor/mcp.json) and VS Code/Copilot (.vscode/mcp.json) —
1186
1286
  merges, never overwrites other servers — and install its
1187
- optional peers with the project's package manager.
1287
+ optional peers with the project's package manager. Sets
1288
+ \`vueCompilerOptions.checkUnknownComponents: true\` in the
1289
+ tsconfig unless it is already named (Nuxt: says where).
1188
1290
  \`--no-mcp\` skips the server and the install. Idempotent —
1189
1291
  safe to re-run after upgrades.
1190
- check [glob…] [--json] [--allow-empty] [--allow-component <Name>]
1292
+ check [glob…] [--changed] [--json] [--allow-empty] [--allow-component <Name>]
1191
1293
  [--no-hints] [--manifest <path>] [--fix]
1192
1294
  Validate \`Bb*\` markup in .vue/.md files against the
1193
1295
  installed components.json manifest (unknown/removed props,
@@ -1201,6 +1303,16 @@ Commands:
1201
1303
  nothing (a typo'd CI path validates zero files silently) —
1202
1304
  pass \`--allow-empty\` when an empty match is expected.
1203
1305
 
1306
+ \`--changed\` validates only the .vue/.md files git reports
1307
+ changed against HEAD (staged or not) plus untracked ones —
1308
+ the fast loop after an edit. Unchanged files are not
1309
+ validated and the styles-import scan reads only the
1310
+ changed files; what a finding depends on elsewhere (the
1311
+ project's var() reads, defineRule names, local Bb*
1312
+ components) is still read from the whole project. Nothing
1313
+ changed → exit 0. Not with paths. Run a full \`check\`
1314
+ before merging.
1315
+
1204
1316
  It also writes your project's \`bitboss-ui.d.ts\` (the
1205
1317
  file the Vite plugin writes on start) from the variant
1206
1318
  options in vite.config / nuxt.config, so a newly
@@ -1241,7 +1353,8 @@ Commands:
1241
1353
  so both gates configure alike.
1242
1354
 
1243
1355
  \`--json\` prints \`{ findings: [...], warnings: [...], hints: [...],
1244
- suppressed, files, manifestVersion, installedVersion }\`.
1356
+ suppressed, files, manifestVersion, installedVersion }\`
1357
+ (plus \`changed: true\` under \`--changed\`).
1245
1358
  Each finding: \`{ file, line, component, attr, kind,
1246
1359
  message, hint?, to? }\` (plus \`fenceIndex\`/\`fenceInfo\`
1247
1360
  inside a markdown fence; \`line\` is absolute in the file).
@@ -1281,11 +1394,18 @@ Commands:
1281
1394
  \`form-v-model\` (\`v-model\`, \`:model-value\` or an
1282
1395
  \`@update:model-value\` listener on a \`BbForm\`: it
1283
1396
  takes its object one way, \`:model="draft"\`),
1397
+ \`positional-provider\` (an \`items\` provider with
1398
+ positional arguments: it receives one object,
1399
+ \`({ query, reason, modelValue, signal })\`),
1284
1400
  \`rules-ignored-by-schema\` (a validated field's
1285
1401
  \`rules\` inside a \`BbForm\` that has a \`schema\`:
1286
1402
  vee-validate reads only the schema),
1287
1403
  \`row-without-name\` (a form control in a \`v-for\`
1288
1404
  inside a \`BbForm\` with a bound label and no \`name\`),
1405
+ \`field-without-name\` (a field with its own
1406
+ \`v-model\` and no \`name\` in a \`BbForm\` with
1407
+ \`field-errors\`: its errors never reach it; your
1408
+ \`definePreset\` wrappers count as their Bb* control),
1289
1409
  \`retired-entrypoint\` (an import from
1290
1410
  \`bitboss-ui/validated\`, retired: everything is in
1291
1411
  \`bitboss-ui\`; \`--fix\` rewrites it in .vue files),
@@ -1322,15 +1442,24 @@ Commands:
1322
1442
  (\`class\`, \`:class\`, \`pt:*\`), \`inert-token\` (a
1323
1443
  \`--bb-*\` SET that the library neither declares nor
1324
1444
  reads; \`suggestion\` = the nearest token),
1325
- \`inert-local\` (a local set on a \`.bb-*\` block whose
1326
- component, and what it mounts, never reads it; \`to\`
1327
- when it was renamed). A local on your own ancestor
1445
+ \`inert-local\` (a local set on a \`.bb-*\` block, nested
1446
+ rules included, or on a Bb* tag's \`style\` / \`:style\` /
1447
+ \`[--x:…]\` class, whose component, and what it mounts,
1448
+ never reads it; \`to\` when it was renamed). A local on your own ancestor
1328
1449
  element, or one your CSS reads, is never judged.
1329
1450
  \`warnings[]\` (never fail the run) use the same shape with
1330
1451
  \`severity: "warning"\`: \`likely-squashed-slot\` (a slot
1331
1452
  name that looks like a camelCase key squashed, e.g.
1332
1453
  \`#createdat\`), \`local-bb-component\` (your own
1333
- component uses the \`Bb\` prefix; rename it).
1454
+ component uses the \`Bb\` prefix; rename it),
1455
+ \`single-reason\` (an \`items\` provider that tests
1456
+ \`reason\` against one cause other than \`'search'\`;
1457
+ check \`reason !== 'search'\`), \`vue-tsc-major\`
1458
+ (\`vue-tsc\` below 3 in package.json: the generic
1459
+ components' props go unchecked),
1460
+ \`check-unknown-components\` (no
1461
+ \`vueCompilerOptions.checkUnknownComponents: true\` in
1462
+ the tsconfig; \`ai-init\` writes it).
1334
1463
  changelog [--since <version>] [--until <version>] [--json]
1335
1464
  Breaking changes between two releases — "what breaks if I
1336
1465
  bump". \`--since\` is the version you are ON, and is
@@ -1393,6 +1522,7 @@ switch (command) {
1393
1522
  'allow-component': { type: 'string', multiple: true },
1394
1523
  fix: { type: 'boolean' },
1395
1524
  manifest: { type: 'string' },
1525
+ changed: { type: 'boolean' },
1396
1526
  // Accepted and ignored here — read straight off argv inside
1397
1527
  // checkCommand, but parseArgs is strict, so it must be declared.
1398
1528
  'no-hints': { type: 'boolean' },
@@ -1405,6 +1535,7 @@ switch (command) {
1405
1535
  allowEmpty: values['allow-empty'] ?? false,
1406
1536
  allowComponents: values['allow-component'] ?? [],
1407
1537
  manifest: values.manifest,
1538
+ changed: values.changed ?? false,
1408
1539
  });
1409
1540
  break;
1410
1541
  }