bitboss-ui 3.0.0-beta.64 → 3.0.0-beta.66

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 (540) hide show
  1. package/README.md +78 -16
  2. package/bin/bitboss-ui-mcp.mjs +8 -8
  3. package/bin/bitboss-ui.mjs +73 -12
  4. package/dist/ai/BbAccordion.md +4 -3
  5. package/dist/ai/BbAlert.md +1 -1
  6. package/dist/ai/BbBadge.md +1 -0
  7. package/dist/ai/BbBadgeButton.md +4 -3
  8. package/dist/ai/BbBaseButton.md +25 -20
  9. package/dist/ai/BbBaseCheckboxIcon.md +1 -0
  10. package/dist/ai/BbBaseRadioIcon.md +1 -0
  11. package/dist/ai/BbBaseSwitchIcon.md +1 -0
  12. package/dist/ai/BbBreadcrumbs.md +8 -0
  13. package/dist/ai/BbButton.md +67 -21
  14. package/dist/ai/BbCalendar.md +56 -3
  15. package/dist/ai/BbCheckbox.md +1 -1
  16. package/dist/ai/BbCheckboxGroup.md +44 -8
  17. package/dist/ai/BbColorInput.md +3 -2
  18. package/dist/ai/BbColorPalette.md +7 -3
  19. package/dist/ai/BbConfirm.md +36 -80
  20. package/dist/ai/BbConfirmPortal.md +1 -1
  21. package/dist/ai/BbDatePicker.md +41 -5
  22. package/dist/ai/BbDatePickerInput.md +38 -6
  23. package/dist/ai/BbDialog.md +63 -58
  24. package/dist/ai/BbDropdown.md +25 -24
  25. package/dist/ai/BbDropdownButton.md +5 -12
  26. package/dist/ai/BbDropzone.md +2 -3
  27. package/dist/ai/BbForm.md +66 -42
  28. package/dist/ai/BbHost.md +29 -41
  29. package/dist/ai/BbIcon.md +3 -0
  30. package/dist/ai/BbNumberInput.md +2 -2
  31. package/dist/ai/BbOffCanvas.md +16 -9
  32. package/dist/ai/BbPagination.md +17 -17
  33. package/dist/ai/BbPopover.md +8 -3
  34. package/dist/ai/BbPtScope.md +5 -5
  35. package/dist/ai/BbRadio.md +1 -1
  36. package/dist/ai/BbRadioGroup.md +44 -7
  37. package/dist/ai/BbRating.md +1 -0
  38. package/dist/ai/BbSelect.md +146 -21
  39. package/dist/ai/BbSelectPopover.md +16 -12
  40. package/dist/ai/BbSlider.md +5 -3
  41. package/dist/ai/BbSwitch.md +1 -1
  42. package/dist/ai/BbTable.md +51 -39
  43. package/dist/ai/BbTabs.md +127 -63
  44. package/dist/ai/BbTabsList.md +4 -2
  45. package/dist/ai/BbTabsPanels.md +3 -1
  46. package/dist/ai/BbTabsRoot.md +4 -4
  47. package/dist/ai/BbTag.md +2 -2
  48. package/dist/ai/BbTextInput.md +23 -9
  49. package/dist/ai/BbTextarea.md +3 -3
  50. package/dist/ai/BbTimePicker.md +5 -4
  51. package/dist/ai/BbTimePickerInput.md +3 -3
  52. package/dist/ai/BbToast.md +33 -87
  53. package/dist/ai/BbToastPortal.md +1 -1
  54. package/dist/ai/CommonFieldInput.md +2 -1
  55. package/dist/ai/FlatListBox.md +1 -1
  56. package/dist/ai/GroupedListBox.md +1 -1
  57. package/dist/ai/ListBox.md +1 -1
  58. package/dist/ai/OptionsContainer.md +1 -1
  59. package/dist/ai/changelog.json +444 -4
  60. package/dist/ai/components.json +87 -83
  61. package/dist/ai/composables/useBbConfig.md +8 -1
  62. package/dist/ai/composables/{useBbDialogContext.md → useBbDialog.md} +18 -18
  63. package/dist/ai/composables/{useBbDropdownContext.md → useBbDropdown.md} +31 -31
  64. package/dist/ai/composables/{useBbFormContext.md → useBbForm.md} +11 -11
  65. package/dist/ai/composables/useBbFormField.md +2 -2
  66. package/dist/ai/composables/{useBbOffCanvasContext.md → useBbOffCanvas.md} +13 -13
  67. package/dist/ai/composables/{useBbTableContext.md → useBbTable.md} +20 -20
  68. package/dist/ai/composables/{useBbTabsContext.md → useBbTabs.md} +12 -12
  69. package/dist/ai/composables/useConfirm.md +42 -54
  70. package/dist/ai/composables/useToast.md +9 -26
  71. package/dist/ai/guides/agent-contract.md +57 -43
  72. package/dist/ai/guides/ai-router.md +1 -1
  73. package/dist/ai/guides/app-layout.md +32 -23
  74. package/dist/ai/guides/coherence-playbook.md +4 -2
  75. package/dist/ai/guides/component-picker.md +35 -32
  76. package/dist/ai/guides/design-language.md +26 -12
  77. package/dist/ai/guides/design-tokens.md +73 -32
  78. package/dist/ai/guides/eslint-rules.md +8 -4
  79. package/dist/ai/guides/fetch-items-playbook.md +3 -3
  80. package/dist/ai/guides/floating-bottom-panel.md +1 -1
  81. package/dist/ai/guides/inertia-helpers.md +1640 -337
  82. package/dist/ai/guides/installation-and-plugin-setup.md +6 -3
  83. package/dist/ai/guides/migration/adoption-checklist.md +44 -2
  84. package/dist/ai/guides/migration/components/bb-dialog.md +13 -13
  85. package/dist/ai/guides/migration/components/bb-dropdown.md +16 -16
  86. package/dist/ai/guides/migration/components/bb-host.md +15 -14
  87. package/dist/ai/guides/migration/components/bb-offcanvas.md +10 -10
  88. package/dist/ai/guides/migration/components/bb-pagination.md +9 -9
  89. package/dist/ai/guides/migration/components/bb-select.md +1 -1
  90. package/dist/ai/guides/migration/components/bb-table.md +12 -12
  91. package/dist/ai/guides/migration/components/bb-tabs.md +1 -1
  92. package/dist/ai/guides/migration/from-async-validator.md +9 -9
  93. package/dist/ai/guides/migration/v2-to-v3.md +206 -13
  94. package/dist/ai/guides/options-items-playbook.md +2 -2
  95. package/dist/ai/guides/page-shell.md +15 -3
  96. package/dist/ai/guides/passthrough.md +13 -7
  97. package/dist/ai/guides/preset-components.md +102 -43
  98. package/dist/ai/guides/typescript-generic-components.md +21 -5
  99. package/dist/ai/guides/validated-forms.md +20 -11
  100. package/dist/ai/guides/validation-providers.md +3 -3
  101. package/dist/ai/helpers/definePreset.json +11 -4
  102. package/dist/ai/helpers/definePreset.ts +98 -41
  103. package/dist/ai/helpers/inertia/manifest.json +332 -91
  104. package/dist/ai/helpers/inertia/messages.ts +33 -0
  105. package/dist/ai/helpers/inertia/useConfirmOnRouteLeave.ts +133 -21
  106. package/dist/ai/helpers/inertia/useHasChanged.ts +34 -16
  107. package/dist/ai/helpers/inertia/useLazyProp.ts +102 -36
  108. package/dist/ai/helpers/inertia/useLazyPropGetter.ts +3 -1
  109. package/dist/ai/helpers/inertia/usePaginatedResponseContext.ts +129 -24
  110. package/dist/ai/helpers/inertia/usePromiseForm.ts +38 -44
  111. package/dist/ai/helpers/inertia/usePromiseRouter.ts +295 -0
  112. package/dist/ai/helpers/inertia/useQuery.ts +133 -11
  113. package/dist/ai/helpers/inertia/useQueryObject.ts +104 -66
  114. package/dist/ai/helpers/inertia/useResourceContext.ts +60 -14
  115. package/dist/ai/helpers/inertia/useRouteQuery.ts +57 -33
  116. package/dist/ai/helpers/inertia/useScreenSizes.ts +9 -7
  117. package/dist/ai/helpers/inertia/useTableContext.ts +5 -2
  118. package/dist/ai/helpers/inertia/utils.ts +57 -0
  119. package/dist/ai/index.md +15 -15
  120. package/dist/ai/manifest/common.json +2 -1
  121. package/dist/ai/manifest/components/BbAccordion.tree.json +3 -1
  122. package/dist/ai/manifest/components/BbAlert.json +1 -1
  123. package/dist/ai/manifest/components/BbBadge.tree.json +3 -1
  124. package/dist/ai/manifest/components/BbBadgeButton.json +9 -4
  125. package/dist/ai/manifest/components/BbBadgeButton.tree.json +1 -0
  126. package/dist/ai/manifest/components/BbBaseButton.json +9 -4
  127. package/dist/ai/manifest/components/BbBaseCheckboxIcon.tree.json +3 -1
  128. package/dist/ai/manifest/components/BbBaseRadioIcon.tree.json +3 -1
  129. package/dist/ai/manifest/components/BbBaseSwitchIcon.tree.json +3 -1
  130. package/dist/ai/manifest/components/BbBreadcrumbs.tree.json +7 -3
  131. package/dist/ai/manifest/components/BbButton.json +9 -4
  132. package/dist/ai/manifest/components/BbButton.tree.json +5 -3
  133. package/dist/ai/manifest/components/BbCalendar.json +4 -3
  134. package/dist/ai/manifest/components/BbCalendar.tree.json +10 -1
  135. package/dist/ai/manifest/components/BbCheckbox.json +1 -1
  136. package/dist/ai/manifest/components/BbCheckbox.tree.json +1 -1
  137. package/dist/ai/manifest/components/BbCheckboxGroup.json +1 -1
  138. package/dist/ai/manifest/components/BbCheckboxGroup.tree.json +62 -3
  139. package/dist/ai/manifest/components/BbCollapsible.json +4 -1
  140. package/dist/ai/manifest/components/BbColorInput.json +1 -1
  141. package/dist/ai/manifest/components/BbColorInput.tree.json +5 -3
  142. package/dist/ai/manifest/components/BbColorPalette.json +3 -0
  143. package/dist/ai/manifest/components/BbColorPalette.tree.json +7 -2
  144. package/dist/ai/manifest/components/BbConfirm.tree.json +2 -2
  145. package/dist/ai/manifest/components/BbDatePicker.json +7 -3
  146. package/dist/ai/manifest/components/BbDatePicker.tree.json +3 -4
  147. package/dist/ai/manifest/components/BbDatePickerInput.json +4 -3
  148. package/dist/ai/manifest/components/BbDatePickerInput.tree.json +5 -3
  149. package/dist/ai/manifest/components/BbDialog.json +1 -1
  150. package/dist/ai/manifest/components/BbDialog.tree.json +2 -2
  151. package/dist/ai/manifest/components/BbDropdown.json +3 -3
  152. package/dist/ai/manifest/components/BbDropdown.tree.json +2 -2
  153. package/dist/ai/manifest/components/BbDropdownButton.json +11 -6
  154. package/dist/ai/manifest/components/BbDropdownButton.tree.json +2 -3
  155. package/dist/ai/manifest/components/BbDropzone.json +4 -1
  156. package/dist/ai/manifest/components/BbForm.json +2 -2
  157. package/dist/ai/manifest/components/BbHost.json +1 -1
  158. package/dist/ai/manifest/components/BbHost.tree.json +1 -1
  159. package/dist/ai/manifest/components/BbHoverCard.json +1 -1
  160. package/dist/ai/manifest/components/BbNumberInput.json +1 -1
  161. package/dist/ai/manifest/components/BbNumberInput.tree.json +1 -1
  162. package/dist/ai/manifest/components/BbOffCanvas.json +1 -1
  163. package/dist/ai/manifest/components/BbOffCanvas.tree.json +3 -1
  164. package/dist/ai/manifest/components/BbPagination.json +4 -4
  165. package/dist/ai/manifest/components/BbPagination.tree.json +2 -1
  166. package/dist/ai/manifest/components/BbPopover.json +1 -1
  167. package/dist/ai/manifest/components/BbPopover.tree.json +1 -1
  168. package/dist/ai/manifest/components/BbProgress.json +4 -1
  169. package/dist/ai/manifest/components/BbRadio.json +1 -1
  170. package/dist/ai/manifest/components/BbRadio.tree.json +1 -1
  171. package/dist/ai/manifest/components/BbRadioGroup.json +5 -5
  172. package/dist/ai/manifest/components/BbRadioGroup.tree.json +62 -3
  173. package/dist/ai/manifest/components/BbRating.tree.json +3 -1
  174. package/dist/ai/manifest/components/BbSelect.json +5 -5
  175. package/dist/ai/manifest/components/BbSelect.tree.json +3 -3
  176. package/dist/ai/manifest/components/BbSelectPopover.json +7 -3
  177. package/dist/ai/manifest/components/BbSelectPopover.tree.json +2 -2
  178. package/dist/ai/manifest/components/BbSlider.json +3 -3
  179. package/dist/ai/manifest/components/BbSlider.tree.json +3 -0
  180. package/dist/ai/manifest/components/BbSmoothHeight.json +4 -1
  181. package/dist/ai/manifest/components/BbSwitch.json +1 -1
  182. package/dist/ai/manifest/components/BbSwitch.tree.json +1 -1
  183. package/dist/ai/manifest/components/BbSwitchGroup.tree.json +1 -1
  184. package/dist/ai/manifest/components/BbTable.json +6 -2
  185. package/dist/ai/manifest/components/BbTable.tree.json +4 -1
  186. package/dist/ai/manifest/components/BbTabs.json +9 -12
  187. package/dist/ai/manifest/components/BbTabs.tree.json +4 -1
  188. package/dist/ai/manifest/components/BbTabsList.json +4 -7
  189. package/dist/ai/manifest/components/BbTabsList.tree.json +4 -1
  190. package/dist/ai/manifest/components/BbTabsPanels.json +1 -1
  191. package/dist/ai/manifest/components/BbTabsPanels.tree.json +4 -1
  192. package/dist/ai/manifest/components/BbTabsRoot.json +5 -5
  193. package/dist/ai/manifest/components/BbTag.json +1 -1
  194. package/dist/ai/manifest/components/BbTag.tree.json +2 -2
  195. package/dist/ai/manifest/components/BbTextInput.json +4 -4
  196. package/dist/ai/manifest/components/BbTextInput.tree.json +1 -1
  197. package/dist/ai/manifest/components/BbTextarea.json +2 -2
  198. package/dist/ai/manifest/components/BbTextarea.tree.json +1 -1
  199. package/dist/ai/manifest/components/BbTimePicker.json +4 -1
  200. package/dist/ai/manifest/components/BbTimePicker.tree.json +5 -3
  201. package/dist/ai/manifest/components/BbTimePickerInput.json +2 -2
  202. package/dist/ai/manifest/components/BbTimePickerInput.tree.json +5 -3
  203. package/dist/ai/manifest/components/BbToast.json +1 -1
  204. package/dist/ai/manifest/components/BbToast.tree.json +3 -1
  205. package/dist/ai/manifest/components/BbTooltip.json +3 -0
  206. package/dist/ai/manifest/components/ChipsBox.tree.json +1 -1
  207. package/dist/ai/manifest/components/CommonField.tree.json +1 -0
  208. package/dist/ai/manifest/components/CommonFieldInput.tree.json +4 -2
  209. package/dist/ai/manifest/components/CommonTimeSelector.tree.json +1 -0
  210. package/dist/ai/manifest/components/FlatListBox.json +1 -1
  211. package/dist/ai/manifest/components/GroupedListBox.json +1 -1
  212. package/dist/ai/manifest/components/ListBox.json +1 -1
  213. package/dist/ai/manifest/components/OptionsContainer.json +2 -2
  214. package/dist/ai/manifest/index.json +3 -3
  215. package/dist/ai/manifest/meta.json +31 -16
  216. package/dist/ai/manifest/types.advanced.json +15 -11
  217. package/dist/ai/manifest/types.api.json +2 -2
  218. package/dist/ai/recipes/inertia/approvals-inbox.md +87 -116
  219. package/dist/ai/recipes/inertia/inline-edit-workspace.md +113 -121
  220. package/dist/ai/recipes/inertia/layout-scaffold.md +15 -4
  221. package/dist/ai/recipes/inertia/onboarding.md +76 -58
  222. package/dist/ai/recipes/inertia/ownership-atlas.md +75 -106
  223. package/dist/ai/recipes/inertia/record-form.md +18 -7
  224. package/dist/ai/recipes/inertia/records-workspace.md +107 -128
  225. package/dist/ai/recipes/inertia/settings-workspace.md +131 -73
  226. package/dist/ai/recipes/inertia/upload-center.md +98 -122
  227. package/dist/ai/recipes/inertia/wizard-form.md +25 -15
  228. package/dist/ai/recipes/nuxt/approvals-inbox.md +67 -48
  229. package/dist/ai/recipes/nuxt/inline-edit-workspace.md +73 -58
  230. package/dist/ai/recipes/nuxt/layout-scaffold.md +15 -4
  231. package/dist/ai/recipes/nuxt/onboarding.md +27 -10
  232. package/dist/ai/recipes/nuxt/ownership-atlas.md +40 -22
  233. package/dist/ai/recipes/nuxt/record-form.md +20 -7
  234. package/dist/ai/recipes/nuxt/records-workspace.md +120 -96
  235. package/dist/ai/recipes/nuxt/settings-workspace.md +36 -23
  236. package/dist/ai/recipes/nuxt/upload-center.md +63 -37
  237. package/dist/ai/recipes/nuxt/wizard-form.md +28 -16
  238. package/dist/ai/recipes/vue/approvals-inbox.md +74 -46
  239. package/dist/ai/recipes/vue/inline-edit-workspace.md +83 -56
  240. package/dist/ai/recipes/vue/layout-scaffold.md +15 -4
  241. package/dist/ai/recipes/vue/onboarding.md +27 -10
  242. package/dist/ai/recipes/vue/ownership-atlas.md +40 -22
  243. package/dist/ai/recipes/vue/record-form.md +20 -7
  244. package/dist/ai/recipes/vue/records-workspace.md +132 -95
  245. package/dist/ai/recipes/vue/settings-workspace.md +36 -23
  246. package/dist/ai/recipes/vue/upload-center.md +73 -37
  247. package/dist/ai/recipes/vue/wizard-form.md +28 -16
  248. package/dist/ai/source/BbAccordion.md +36 -6
  249. package/dist/ai/source/BbAlert.md +11 -5
  250. package/dist/ai/source/BbAsterisk.md +4 -1
  251. package/dist/ai/source/BbAvatar.md +11 -5
  252. package/dist/ai/source/BbBadge.md +42 -11
  253. package/dist/ai/source/BbBadgeButton.md +41 -8
  254. package/dist/ai/source/BbBaseButton.md +57 -15
  255. package/dist/ai/source/BbBaseCheckboxIcon.md +37 -13
  256. package/dist/ai/source/BbBaseRadioIcon.md +32 -9
  257. package/dist/ai/source/BbBaseSwitchIcon.md +31 -7
  258. package/dist/ai/source/BbBreadcrumbs.md +32 -9
  259. package/dist/ai/source/BbButton.md +91 -27
  260. package/dist/ai/source/BbCalendar.md +571 -300
  261. package/dist/ai/source/BbCheckbox.md +18 -7
  262. package/dist/ai/source/BbCheckboxGroup.md +16 -5
  263. package/dist/ai/source/BbCollapsible.md +15 -6
  264. package/dist/ai/source/BbColorInput.md +68 -20
  265. package/dist/ai/source/BbColorPalette.md +107 -23
  266. package/dist/ai/source/BbConfirmPortal.md +1 -1
  267. package/dist/ai/source/BbDatePicker.md +106 -25
  268. package/dist/ai/source/BbDatePickerInput.md +105 -42
  269. package/dist/ai/source/BbDialog.md +60 -44
  270. package/dist/ai/source/BbDropdown.md +44 -32
  271. package/dist/ai/source/BbDropdownButton.md +26 -20
  272. package/dist/ai/source/BbDropdownGroup.md +5 -5
  273. package/dist/ai/source/BbDropzone.md +53 -16
  274. package/dist/ai/source/BbForm.md +18 -7
  275. package/dist/ai/source/BbHost.md +25 -12
  276. package/dist/ai/source/BbHoverCard.md +20 -9
  277. package/dist/ai/source/BbIcon.md +9 -3
  278. package/dist/ai/source/BbIndicator.md +11 -4
  279. package/dist/ai/source/BbNumberInput.md +23 -6
  280. package/dist/ai/source/BbOffCanvas.md +73 -32
  281. package/dist/ai/source/BbPagination.md +59 -31
  282. package/dist/ai/source/BbPopover.md +28 -16
  283. package/dist/ai/source/BbProgress.md +13 -5
  284. package/dist/ai/source/BbRadio.md +16 -9
  285. package/dist/ai/source/BbRadioGroup.md +15 -4
  286. package/dist/ai/source/BbRating.md +51 -10
  287. package/dist/ai/source/BbSelect.md +56 -27
  288. package/dist/ai/source/BbSelectPopover.md +106 -36
  289. package/dist/ai/source/BbSlider.md +111 -33
  290. package/dist/ai/source/BbSmoothHeight.md +16 -7
  291. package/dist/ai/source/BbSpinner.md +9 -3
  292. package/dist/ai/source/BbSwitch.md +16 -9
  293. package/dist/ai/source/BbSwitchGroup.md +18 -7
  294. package/dist/ai/source/BbTable.md +172 -38
  295. package/dist/ai/source/BbTabs.md +58 -40
  296. package/dist/ai/source/BbTabsList.md +109 -50
  297. package/dist/ai/source/BbTabsPanels.md +65 -31
  298. package/dist/ai/source/BbTabsRoot.md +35 -24
  299. package/dist/ai/source/BbTag.md +18 -4
  300. package/dist/ai/source/BbTextInput.md +20 -3
  301. package/dist/ai/source/BbTextarea.md +15 -1
  302. package/dist/ai/source/BbTimePicker.md +81 -21
  303. package/dist/ai/source/BbTimePickerInput.md +63 -15
  304. package/dist/ai/source/BbToast.md +20 -3
  305. package/dist/ai/source/BbToastPortal.md +21 -4
  306. package/dist/ai/source/BbTooltip.md +16 -8
  307. package/dist/ai/source/BbTree.md +10 -3
  308. package/dist/ai/source/ClearableButton.md +5 -1
  309. package/dist/ai/source/CommonField.md +65 -9
  310. package/dist/ai/source/CommonFieldInput.md +61 -27
  311. package/dist/ai/source/CommonPopover.md +17 -6
  312. package/dist/ai/source/CommonTimeSelector.md +21 -2
  313. package/dist/ai/source/ErrorIcon.md +4 -0
  314. package/dist/ai/source/ListBox.md +9 -1
  315. package/dist/ai/source/OptionsContainer.md +5 -1
  316. package/dist/ai/source/WarningIcon.md +4 -0
  317. package/dist/components/BbAccordion/BbAccordion.vue.d.ts +2 -1
  318. package/dist/components/BbAccordion/BbAccordion.vue_vue_type_script_setup_true_lang.js +6 -6
  319. package/dist/components/BbAlert/BbAlert.vue.d.ts +2 -1
  320. package/dist/components/BbAlert/BbAlert.vue_vue_type_script_setup_true_lang.js +10 -10
  321. package/dist/components/BbAsterisk/BbAsterisk.vue.d.ts +3 -1
  322. package/dist/components/BbAvatar/BbAvatar.vue.d.ts +3 -1
  323. package/dist/components/BbAvatar/BbAvatar.vue_vue_type_script_setup_true_lang.js +7 -7
  324. package/dist/components/BbBadge/BbBadge.vue.d.ts +5 -3
  325. package/dist/components/BbBadge/BbBadge.vue_vue_type_script_setup_true_lang.js +7 -7
  326. package/dist/components/BbBadge/BbBadgeButton.vue.d.ts +3 -1
  327. package/dist/components/BbBadge/BbBadgeButton.vue_vue_type_script_setup_true_lang.js +7 -7
  328. package/dist/components/BbBaseButton/BbBaseButton.vue.d.ts +3 -1
  329. package/dist/components/BbBaseButton/BbBaseButton.vue_vue_type_script_setup_true_lang.js +85 -85
  330. package/dist/components/BbBaseButton/types.d.ts +8 -5
  331. package/dist/components/BbBaseButton/useLinkState.d.ts +2 -0
  332. package/dist/components/BbBaseButton/useLinkState.js +21 -20
  333. package/dist/components/BbBaseCheckboxIcon/BbBaseCheckboxIcon.vue.d.ts +3 -1
  334. package/dist/components/BbBaseRadioIcon/BbBaseRadioIcon.vue.d.ts +3 -1
  335. package/dist/components/BbBaseSwitchIcon/BbBaseSwitchIcon.vue.d.ts +3 -1
  336. package/dist/components/BbBreadcrumbs/BbBreadcrumbs.vue.d.ts +3 -1
  337. package/dist/components/BbBreadcrumbs/BbBreadcrumbs.vue_vue_type_script_setup_true_lang.js +7 -7
  338. package/dist/components/BbButton/BbButton.vue.d.ts +2 -1
  339. package/dist/components/BbButton/BbButton.vue_vue_type_script_setup_true_lang.js +93 -93
  340. package/dist/components/BbButton/types.d.ts +7 -4
  341. package/dist/components/BbCalendar/BbCalendar.vue.d.ts +157 -30
  342. package/dist/components/BbCalendar/BbCalendar.vue_vue_type_script_setup_true_lang.js +364 -331
  343. package/dist/components/BbCalendar/CalendarMonthPanel.vue_vue_type_script_setup_true_lang.js +5 -5
  344. package/dist/components/BbCalendar/types.d.ts +36 -8
  345. package/dist/components/BbCalendar/useCalendarGrid.d.ts +133 -0
  346. package/dist/components/BbCalendar/useCalendarGrid.js +193 -183
  347. package/dist/components/BbCalendar/useDayGrid.d.ts +24 -19
  348. package/dist/components/BbCalendar/useDayGrid.js +105 -102
  349. package/dist/components/BbCheckbox/BbCheckbox.vue.d.ts +4 -2
  350. package/dist/components/BbCheckboxGroup/BbCheckboxGroup.vue.d.ts +327 -2
  351. package/dist/components/BbCollapsible/BbCollapsible.vue.d.ts +3 -1
  352. package/dist/components/BbCollapsible/BbCollapsible.vue_vue_type_script_setup_true_lang.js +6 -6
  353. package/dist/components/BbColorInput/BbColorInput.vue.d.ts +8 -5
  354. package/dist/components/BbColorInput/BbColorInput.vue_vue_type_script_setup_true_lang.js +5 -5
  355. package/dist/components/BbColorInput/types.d.ts +2 -0
  356. package/dist/components/BbColorPalette/BbColorPalette.vue.d.ts +7 -5
  357. package/dist/components/BbColorPalette/BbColorPalette.vue_vue_type_script_setup_true_lang.js +216 -215
  358. package/dist/components/BbConfirm/BbConfirm.vue_vue_type_script_setup_true_lang.js +25 -25
  359. package/dist/components/BbDatePicker/BbDatePicker.vue.d.ts +206 -41
  360. package/dist/components/BbDatePicker/BbDatePicker.vue_vue_type_script_setup_true_lang.js +112 -106
  361. package/dist/components/BbDatePicker/types.d.ts +27 -8
  362. package/dist/components/BbDatePickerInput/BbDatePickerInput.vue.d.ts +519 -37
  363. package/dist/components/BbDatePickerInput/BbDatePickerInput.vue_vue_type_script_setup_true_lang.js +11 -8
  364. package/dist/components/BbDatePickerInput/types.d.ts +31 -9
  365. package/dist/components/BbDialog/BbDialog.vue.d.ts +6 -5
  366. package/dist/components/BbDialog/BbDialog.vue_vue_type_script_setup_true_lang.js +231 -233
  367. package/dist/components/BbDialog/types.d.ts +7 -7
  368. package/dist/components/BbDialog/useDialogStack.d.ts +2 -0
  369. package/dist/components/BbDialog/useDialogStack.js +6 -2
  370. package/dist/components/BbDropdown/AdaptiveDropdown.vue_vue_type_script_setup_true_lang.js +25 -25
  371. package/dist/components/BbDropdown/BbDropdown.vue.d.ts +8 -6
  372. package/dist/components/BbDropdown/BbDropdown.vue_vue_type_script_setup_true_lang.js +226 -225
  373. package/dist/components/BbDropdown/BbDropdownList.vue_vue_type_script_setup_true_lang.js +49 -49
  374. package/dist/components/BbDropdown/DropdownPipelineResolver.vue_vue_type_script_setup_true_lang.js +7 -7
  375. package/dist/components/BbDropdown/normalizeGroups.js +14 -14
  376. package/dist/components/BbDropdown/types.d.ts +5 -5
  377. package/dist/components/BbDropdown/useDropdownContext.js +1 -1
  378. package/dist/components/BbDropdown/useDropdownGroupRegistry.d.ts +1 -1
  379. package/dist/components/BbDropdownButton/BbDropdownButton.vue.d.ts +6 -4
  380. package/dist/components/BbDropdownButton/BbDropdownButton.vue_vue_type_script_setup_true_lang.js +36 -38
  381. package/dist/components/BbDropdownButton/types.js +4 -4
  382. package/dist/components/BbDropzone/BbDropzone.vue.d.ts +57 -22
  383. package/dist/components/BbDropzone/BbDropzone.vue_vue_type_script_setup_true_lang.js +4 -4
  384. package/dist/components/BbDropzone/types.d.ts +16 -4
  385. package/dist/components/BbForm/BbForm.vue.d.ts +52 -4
  386. package/dist/components/BbForm/BbForm.vue_vue_type_script_setup_true_lang.js +1 -1
  387. package/dist/components/BbHost/BbHost.vue_vue_type_script_setup_true_lang.js +19 -23
  388. package/dist/components/BbHost/BbHostOpening.js +1 -1
  389. package/dist/components/BbHoverCard/BbHoverCard.vue.d.ts +5 -4
  390. package/dist/components/BbHoverCard/BbHoverCard.vue_vue_type_script_setup_true_lang.js +116 -116
  391. package/dist/components/BbIcon/BbIcon.vue.d.ts +3 -1
  392. package/dist/components/BbIcon/BbIcon.vue_vue_type_script_setup_true_lang.js +7 -7
  393. package/dist/components/BbIndicator/BbIndicator.vue.d.ts +3 -1
  394. package/dist/components/BbNumberInput/BbNumberInput.vue.d.ts +6 -3
  395. package/dist/components/BbNumberInput/types.d.ts +2 -0
  396. package/dist/components/BbOffCanvas/BbOffCanvas.vue.d.ts +5 -4
  397. package/dist/components/BbOffCanvas/BbOffCanvas.vue_vue_type_script_setup_true_lang.js +366 -369
  398. package/dist/components/BbOffCanvas/sheetAttrs.d.ts +9 -0
  399. package/dist/components/BbOffCanvas/sheetAttrs.js +10 -0
  400. package/dist/components/BbOffCanvas/types.d.ts +7 -7
  401. package/dist/components/BbOffCanvas/useOffCanvasStack.d.ts +2 -0
  402. package/dist/components/BbOffCanvas/useOffCanvasStack.js +7 -3
  403. package/dist/components/BbPagination/BbPagination.vue.d.ts +2 -1
  404. package/dist/components/BbPagination/BbPagination.vue_vue_type_script_setup_true_lang.js +8 -8
  405. package/dist/components/BbPagination/types.d.ts +5 -5
  406. package/dist/components/BbPopover/BbPopover.vue.d.ts +5 -4
  407. package/dist/components/BbPopover/BbPopover.vue_vue_type_script_setup_true_lang.js +92 -91
  408. package/dist/components/BbProgress/BbProgress.vue.d.ts +6 -1
  409. package/dist/components/BbRadio/BbRadio.vue.d.ts +4 -2
  410. package/dist/components/BbRadioGroup/BbRadioGroup.vue.d.ts +281 -1
  411. package/dist/components/BbRating/BbRating.vue.d.ts +4 -2
  412. package/dist/components/BbRating/BbRating.vue_vue_type_script_setup_true_lang.js +7 -7
  413. package/dist/components/BbSelect/BbSelect.vue.d.ts +575 -4
  414. package/dist/components/BbSelect/BbSelect.vue_vue_type_script_setup_true_lang.js +7 -7
  415. package/dist/components/BbSelect/types.d.ts +12 -2
  416. package/dist/components/BbSelectPopover/BbSelectPopover.vue.d.ts +105 -3
  417. package/dist/components/BbSelectPopover/BbSelectPopover.vue_vue_type_script_setup_true_lang.js +695 -680
  418. package/dist/components/BbSelectPopover/types.d.ts +9 -1
  419. package/dist/components/BbSlider/BbSlider.vue.d.ts +135 -33
  420. package/dist/components/BbSlider/BbSlider.vue_vue_type_script_setup_true_lang.js +5 -5
  421. package/dist/components/BbSlider/types.d.ts +19 -4
  422. package/dist/components/BbSmoothHeight/BbSmoothHeight.vue.d.ts +3 -1
  423. package/dist/components/BbSpinner/BbSpinner.vue.d.ts +3 -1
  424. package/dist/components/BbSwitch/BbSwitch.vue.d.ts +4 -2
  425. package/dist/components/BbSwitchGroup/BbSwitchGroup.vue.d.ts +131 -1
  426. package/dist/components/BbTable/BbTable.vue.d.ts +5 -2
  427. package/dist/components/BbTable/BbTable.vue_vue_type_script_setup_true_lang.js +593 -578
  428. package/dist/components/BbTable/types.d.ts +14 -1
  429. package/dist/components/BbTable/utils.d.ts +2 -1
  430. package/dist/components/BbTable/utils.js +37 -38
  431. package/dist/components/BbTabs/BbTabs.vue.d.ts +96 -2
  432. package/dist/components/BbTabs/BbTabs.vue_vue_type_script_setup_true_lang.js +8 -6
  433. package/dist/components/BbTabs/BbTabsList.vue.d.ts +11 -1
  434. package/dist/components/BbTabs/BbTabsList.vue_vue_type_script_setup_true_lang.js +102 -92
  435. package/dist/components/BbTabs/BbTabsPanels.vue.d.ts +9 -1
  436. package/dist/components/BbTabs/BbTabsPanels.vue_vue_type_script_setup_true_lang.js +20 -17
  437. package/dist/components/BbTabs/BbTabsRoot.vue_vue_type_script_setup_true_lang.js +1 -1
  438. package/dist/components/BbTabs/types.d.ts +34 -23
  439. package/dist/components/BbTag/BbTag.vue.d.ts +5 -2
  440. package/dist/components/BbTag/types.d.ts +2 -0
  441. package/dist/components/BbTextInput/BbTextInput.vue.d.ts +195 -2
  442. package/dist/components/BbTextInput/BbTextInput.vue_vue_type_script_setup_true_lang.js +5 -5
  443. package/dist/components/BbTextInput/types.d.ts +2 -0
  444. package/dist/components/BbTextarea/BbTextarea.vue.d.ts +193 -2
  445. package/dist/components/BbTextarea/types.d.ts +2 -0
  446. package/dist/components/BbTimePicker/BbTimePicker.vue.d.ts +78 -38
  447. package/dist/components/BbTimePicker/BbTimePicker.vue_vue_type_script_setup_true_lang.js +138 -137
  448. package/dist/components/BbTimePicker/types.d.ts +18 -4
  449. package/dist/components/BbTimePickerInput/BbTimePickerInput.vue.d.ts +272 -33
  450. package/dist/components/BbTimePickerInput/BbTimePickerInput.vue_vue_type_script_setup_true_lang.js +16 -16
  451. package/dist/components/BbTimePickerInput/types.d.ts +20 -5
  452. package/dist/components/BbToast/BbToastMessage.vue_vue_type_script_setup_true_lang.js +6 -6
  453. package/dist/components/BbToast/BbToastRegion.vue_vue_type_script_setup_true_lang.js +20 -20
  454. package/dist/components/BbTooltip/BbTooltip.vue.d.ts +3 -2
  455. package/dist/components/BbTooltip/BbTooltip.vue_vue_type_script_setup_true_lang.js +109 -109
  456. package/dist/components/BbTree/BbTree.vue.d.ts +1 -1
  457. package/dist/components/ClearableButton/ClearableButton.vue.d.ts +3 -1
  458. package/dist/components/CloseIcon/CloseButton.vue.d.ts +3 -1
  459. package/dist/components/CloseIcon/CloseButton.vue.js +1 -1
  460. package/dist/components/CommonField/CommonField.vue.d.ts +3 -1
  461. package/dist/components/CommonFieldInput/CommonFieldInput.vue.d.ts +5 -3
  462. package/dist/components/CommonPopover/CommonPopover.vue.d.ts +5 -4
  463. package/dist/components/CommonPopover/CommonPopover.vue_vue_type_script_setup_true_lang.js +55 -55
  464. package/dist/components/ErrorIcon/ErrorIcon.vue.d.ts +3 -1
  465. package/dist/components/FlatListBox/FlatListBox.vue_vue_type_script_setup_true_lang.js +124 -124
  466. package/dist/components/GroupedListBox/GroupedListBox.vue_vue_type_script_setup_true_lang.js +71 -71
  467. package/dist/components/ListBox/ListBox.vue.d.ts +1 -1
  468. package/dist/components/OptionsContainer/OptionsContainer.vue.d.ts +1 -1
  469. package/dist/components/OptionsContainer/OptionsContainer.vue_vue_type_script_setup_true_lang.js +4 -4
  470. package/dist/components/Transitions/Slide.vue.d.ts +1 -1
  471. package/dist/components/WarningIcon/WarningIcon.vue.d.ts +3 -1
  472. package/dist/composables/autoHost.d.ts +22 -0
  473. package/dist/composables/autoHost.js +20 -0
  474. package/dist/composables/hostOpenings.d.ts +3 -3
  475. package/dist/composables/hostOpenings.js +1 -1
  476. package/dist/composables/hostRegistry.d.ts +10 -2
  477. package/dist/composables/hostRegistry.js +5 -3
  478. package/dist/composables/overlayRegistry.d.ts +1 -1
  479. package/dist/composables/overlayRegistry.js +2 -2
  480. package/dist/composables/useBbConfig.d.ts +1 -0
  481. package/dist/composables/useBbConfig.js +11 -7
  482. package/dist/composables/{useBbDialogContext.d.ts → useBbDialog.d.ts} +9 -9
  483. package/dist/composables/{useBbDialogContext.js → useBbDialog.js} +4 -4
  484. package/dist/composables/{useBbDropdownContext.d.ts → useBbDropdown.d.ts} +14 -14
  485. package/dist/composables/{useBbDropdownContext.js → useBbDropdown.js} +2 -2
  486. package/dist/composables/{useBbFormContext.d.ts → useBbForm.d.ts} +8 -8
  487. package/dist/composables/{useBbFormContext.js → useBbForm.js} +3 -3
  488. package/dist/composables/useBbOffCanvas.d.ts +23 -0
  489. package/dist/composables/{useBbOffCanvasContext.js → useBbOffCanvas.js} +3 -3
  490. package/dist/composables/{useBbTableContext.d.ts → useBbTable.d.ts} +29 -29
  491. package/dist/composables/{useBbTableContext.js → useBbTable.js} +2 -2
  492. package/dist/composables/{useBbTabsContext.d.ts → useBbTabs.d.ts} +19 -3
  493. package/dist/composables/useBbTabs.js +266 -0
  494. package/dist/composables/useConfirm.d.ts +6 -7
  495. package/dist/composables/useConfirm.js +1 -1
  496. package/dist/composables/useOnDemandOpener.d.ts +4 -4
  497. package/dist/composables/useOnDemandOpener.js +1 -1
  498. package/dist/composables/useToast.d.ts +4 -5
  499. package/dist/composables/useToast.js +1 -1
  500. package/dist/directives/bbDialog.d.ts +1 -1
  501. package/dist/directives/bbDropdown.js +3 -3
  502. package/dist/directives/bbOffCanvas.d.ts +1 -1
  503. package/dist/directives/overlayTrigger.js +18 -18
  504. package/dist/index.d.ts +15 -15
  505. package/dist/index.js +55 -55
  506. package/dist/llms-full.txt +5397 -2894
  507. package/dist/llms-medium.txt +127 -93
  508. package/dist/llms.txt +12 -12
  509. package/dist/nuxt-auto-imports.js +6 -6
  510. package/dist/nuxt.js +1 -1
  511. package/dist/plugin.js +30 -28
  512. package/dist/runtime/nuxt-plugin.js +30 -28
  513. package/dist/styles.css +2 -2
  514. package/dist/types/ShapeErased.d.ts +15 -0
  515. package/dist/types/fallthrough.d.ts +134 -0
  516. package/dist/utilities/functions/normalizeDateBound.d.ts +7 -5
  517. package/dist/utilities/functions/normalizeDateBound.js +9 -9
  518. package/dist/utils/versionCheck.js +1 -1
  519. package/llms.txt +12 -12
  520. package/package.json +3 -2
  521. package/scripts/lib/adoption-checklist.json +2 -1
  522. package/scripts/lib/css-class-surface.mjs +39 -3
  523. package/scripts/lib/eslint-disable.mjs +9 -1
  524. package/scripts/lib/eslint-plugin.d.ts +7 -1
  525. package/scripts/lib/eslint-plugin.mjs +280 -3
  526. package/scripts/lib/form-v-model.mjs +2 -2
  527. package/scripts/lib/helper-canon.mjs +34 -2
  528. package/scripts/lib/helpers-add.mjs +106 -15
  529. package/scripts/lib/hidden-label-placeholder.mjs +138 -0
  530. package/scripts/lib/html-attributes.mjs +82 -0
  531. package/scripts/lib/idiom-scan.mjs +175 -2
  532. package/scripts/lib/portal-names.mjs +3 -3
  533. package/scripts/lib/prefer-v-bb-dialog.mjs +1 -1
  534. package/scripts/lib/tab-links.mjs +209 -0
  535. package/scripts/lib/token-color-mix.mjs +114 -0
  536. package/scripts/lib/toolchain-check.mjs +34 -3
  537. package/scripts/lib/unstyled-variants.mjs +57 -0
  538. package/scripts/lib/validate-bb-markup.mjs +72 -1
  539. package/dist/composables/useBbOffCanvasContext.d.ts +0 -23
  540. package/dist/composables/useBbTabsContext.js +0 -252
@@ -1,13 +1,13 @@
1
1
  ---
2
2
  title: Records Workspace (Nuxt)
3
- summary: Full-anatomy invoices workspace for Nuxt — breadcrumbs + page search, chip filter rail (one Filters menu + editable filter chips), href tabs with counts, one-click status cells, bulk bottom panel, and a stacked peek sidebar, filters URL-synced and data fetched with useAsyncData, all through one coopting page context.
3
+ summary: Full-anatomy invoices workspace for Nuxt — breadcrumbs + page search, chip filter rail (one Filters menu + editable filter chips), URL status strip with counts, one-click status cells, bulk bottom panel, and a stacked peek sidebar, filters URL-synced and data fetched with useAsyncData, all through one coopting page context.
4
4
  ---
5
5
 
6
6
  # Recipe: Records Workspace (Nuxt)
7
7
 
8
8
  The flagship advanced-page recipe adapted for **Nuxt**: the same Stripe-
9
9
  invoices × Linear list workspace — app chrome, breadcrumbs + page search,
10
- chip filter rail (one Filters menu + editable filter chips), href tabs with live counts, a dense server-paged table, a
10
+ chip filter rail (one Filters menu + editable filter chips), a URL status strip with live counts, a dense server-paged table, a
11
11
  floating bulk-action bar, and a stacked peek sidebar — but filters and the
12
12
  active tab live in the URL and the list loads through `useAsyncData`
13
13
  watching `route.query`. Anatomy, components, the context shape, copy and
@@ -25,7 +25,6 @@ Sibling recipes: [Vue](../vue/records-workspace.md) ·
25
25
  those files before anything below, and do not hand-roll replacements —
26
26
  the peek stack, the close semantics and the sidebar's out-of-flow
27
27
  behaviour are all load-bearing here.
28
- - `<BbHost />` mounted once in `app.vue` — never in a page.
29
28
  - Each toast and alert variant's icon set once in the build config; the
30
29
  code below passes no `icon` for them:
31
30
  `toastVariants: { success: { icon: 'lucide:circle-check' }, destructive: { icon: 'lucide:circle-x' } }`
@@ -53,7 +52,7 @@ Sibling recipes: [Vue](../vue/records-workspace.md) ·
53
52
  ## Key ideas
54
53
 
55
54
  - **One coopting page context.** `provideInvoicesWorkspace()` joins the
56
- page-shell stack and the table context once, owns filters/tab and when the
55
+ page-shell stack and the table handle once, owns filters/tab and when the
57
56
  record-payment dialog opens, and exposes complete actions. Every leaf calls `useInvoicesWorkspace()`
58
57
  and nothing else — zero prop drilling anywhere on the page.
59
58
  - **Filters and tab live in the URL, not in local refs.** They are seeded
@@ -62,7 +61,7 @@ Sibling recipes: [Vue](../vue/records-workspace.md) ·
62
61
  - **`useAsyncData` watches `route.query`.** That single watch source is
63
62
  the whole refetch trigger — filters, tab and page changes all funnel
64
63
  through the URL first, so there is exactly one fetch path.
65
- - **The table keeps its selection/paging context.** `useBbTableContext`
64
+ - **The table keeps its selection/paging handle.** `useBbTable`
66
65
  still owns `page`/`perPage`/`selected`/`totalItems` by id — only the _items_
67
66
  become a resolved array (`:items` + `:loading`) instead of an items
68
67
  function, since the page now owns the fetch. Select-all is the "all across
@@ -87,7 +86,7 @@ Sibling recipes: [Vue](../vue/records-workspace.md) ·
87
86
  selectable/searchable group (Status, Customer); one chip per APPLIED facet
88
87
  — never one per value — renders below it, each a small `BbDropdown` scoped
89
88
  to that same group via an external `activator` ref, reading its label from
90
- `useBbDropdownContext` so it never re-fetches what the menu already
89
+ `useBbDropdown` so it never re-fetches what the menu already
91
90
  resolved. **Never** `BbSelectPopover` + an imperative `ref.open()`: it
92
91
  exposes nothing to call, and its floating mode closes an
93
92
  `sr-only`/off-screen activator the instant it opens. Due date is a
@@ -140,7 +139,7 @@ Chrome assumed from the guides: [App Layout](../../guides/app-layout.md)
140
139
  | 3b | Filter due date | date-range pill | `BbDatePickerInput` range — not a Filters-menu facet |
141
140
  | 4 | Clear a filter | chip clear button / date pill | badge `@click:clear` (status/customer) or input `clearable` (due) |
142
141
  | 4b | Clear every filter | the rail's last chip, while a filter is active | `Clear all` badge → `ctx.clearFilters` |
143
- | 5 | Switch tab | href tabs with counts | URL + `useAsyncData` refetch |
142
+ | 5 | Switch tab | URL status strip with counts | URL + `useAsyncData` refetch |
144
143
  | 6 | Peek invoice | row click, peek lists | `v-model:highlighted` / `peekInvoice(id)` → shell stack |
145
144
  | 7 | Peek customer (stacked) | customer cell / inside peeks | `stackCustomer(id)` → back arrow |
146
145
  | 8 | Change status inline | status badge in row & peek | one-click `BbSelectPopover`; the toast's Undo saves the old status back |
@@ -149,7 +148,7 @@ Chrome assumed from the guides: [App Layout](../../guides/app-layout.md)
149
148
  | 10 | Edit / duplicate | row `…` dropdown | navigation (`to`) / context action |
150
149
  | 11 | Archive / delete | row `…`, bulk bar | destructive behind `useConfirm` |
151
150
  | 12 | Bulk mark paid / remind | floating bottom panel | context actions on the table selection: `{ ids }`, or `{ all, unselected, filters }` |
152
- | 13 | Select rows / select all | table checkboxes | table context |
151
+ | 13 | Select rows / select all | table checkboxes | table handle |
153
152
  | 14 | Open full invoice | invoice number cell, peek footer | navigation (`to="/invoices/:id"`) |
154
153
  | 15 | Back / close peek | shell chrome | shell stack pop / close |
155
154
 
@@ -187,11 +186,11 @@ import {
187
186
  type Ref,
188
187
  } from 'vue';
189
188
  import {
190
- useBbDialogContext,
191
- useBbTableContext,
189
+ useBbDialog,
190
+ useBbTable,
192
191
  useConfirm,
193
192
  useToast,
194
- type BbTableContext,
193
+ type BbTableHandle,
195
194
  type BadgeVariantType,
196
195
  } from 'bitboss-ui';
197
196
  import {
@@ -253,7 +252,7 @@ export const PAYMENT_METHOD_OPTIONS = [
253
252
  ];
254
253
 
255
254
  export interface InvoiceFilters {
256
- search: string;
255
+ search: string | null;
257
256
  status: InvoiceStatus[];
258
257
  customerId: number | null;
259
258
  /**
@@ -270,9 +269,9 @@ type InvoiceListResponse = {
270
269
  };
271
270
 
272
271
  export interface InvoicesWorkspaceContext {
273
- // -- Coopted contexts ------------------------------------------------------
272
+ // -- Coopted contexts and handles ------------------------------------------
274
273
  shell: PageShellContext<PeekItem>;
275
- table: BbTableContext;
274
+ table: BbTableHandle;
276
275
  // -- Page-owned state ------------------------------------------------------
277
276
  filters: InvoiceFilters;
278
277
  hasActiveFilters: ComputedRef<boolean>;
@@ -314,12 +313,26 @@ const toArray = (value: unknown): string[] | null => {
314
313
 
315
314
  export function provideInvoicesWorkspace(): InvoicesWorkspaceContext {
316
315
  const { toast } = useToast();
316
+ // A write that fails tells the user instead of escaping as an
317
+ // `Uncaught (in promise)`: the action resolves, the page stays as it was.
318
+ const failSoft =
319
+ <A extends unknown[]>(action: (...args: A) => Promise<unknown>) =>
320
+ async (...args: A) => {
321
+ try {
322
+ await action(...args);
323
+ } catch {
324
+ toast({
325
+ title: 'That did not go through. Try again.',
326
+ variant: 'destructive',
327
+ });
328
+ }
329
+ };
317
330
  const { confirm } = useConfirm();
318
331
  const route = useRoute();
319
332
 
320
- // -- Coopt the specific contexts: once, here, for the whole page. ----------
333
+ // -- Coopt the shell and the table handle: once, for the whole page. -------
321
334
  const shell = usePageShellContext<PeekItem>();
322
- const table = useBbTableContext('invoices-table', { perPage: 25 });
335
+ const table = useBbTable('invoices-table', { perPage: 25 });
323
336
 
324
337
  // -- Filters + tab: seeded from the URL, the single source of truth. -------
325
338
  const filters = reactive<InvoiceFilters>({
@@ -332,7 +345,7 @@ export function provideInvoicesWorkspace(): InvoicesWorkspaceContext {
332
345
 
333
346
  const hasActiveFilters = computed(
334
347
  () =>
335
- filters.search !== '' ||
348
+ !!filters.search ||
336
349
  filters.status.length > 0 ||
337
350
  filters.customerId !== null ||
338
351
  filters.dueBetween.length > 0
@@ -407,7 +420,7 @@ export function provideInvoicesWorkspace(): InvoicesWorkspaceContext {
407
420
  // payment with the invoice as `data` (the peek's button through
408
421
  // `v-bb-dialog`, the row menu through this), and it closes itself once the
409
422
  // payment is recorded. Nothing on the page renders it or reads its state.
410
- const paymentDialog = useBbDialogContext<Invoice>(RecordPaymentDialog);
423
+ const paymentDialog = useBbDialog<Invoice>(RecordPaymentDialog);
411
424
  const openRecordPayment = (invoice: Invoice) => {
412
425
  void paymentDialog.show(invoice);
413
426
  };
@@ -433,32 +446,34 @@ export function provideInvoicesWorkspace(): InvoicesWorkspaceContext {
433
446
  shell.stackItem({ type: 'customer', id, title: customerTitle(id) });
434
447
 
435
448
  // -- Actions --------------------------------------------------------------------
436
- const updateStatus = async (invoice: Invoice, status: InvoiceStatus) => {
437
- // Undoable: the pre-edit value comes from the row snapshot, and Undo
438
- // is the same save back to it — a real round-trip, not a guess.
439
- const previous = invoice.status;
440
- const save = async (value: InvoiceStatus) => {
441
- await $fetch(`/api/invoices/${invoice.id}`, {
442
- method: 'PATCH',
443
- body: { status: value },
449
+ const updateStatus = failSoft(
450
+ async (invoice: Invoice, status: InvoiceStatus) => {
451
+ // Undoable: the pre-edit value comes from the row snapshot, and Undo
452
+ // is the same save back to it — a real round-trip, not a guess.
453
+ const previous = invoice.status;
454
+ const save = async (value: InvoiceStatus) => {
455
+ await $fetch(`/api/invoices/${invoice.id}`, {
456
+ method: 'PATCH',
457
+ body: { status: value },
458
+ });
459
+ await refresh();
460
+ };
461
+ await save(status);
462
+ toast({
463
+ title: `${invoice.number} moved to ${status}.`,
464
+ variant: 'success',
465
+ actions: [
466
+ {
467
+ text: 'Undo',
468
+ 'prepend:icon': 'lucide:undo-2',
469
+ onClick: () => save(previous),
470
+ },
471
+ ],
444
472
  });
445
- await refresh();
446
- };
447
- await save(status);
448
- toast({
449
- title: `${invoice.number} moved to ${status}.`,
450
- variant: 'success',
451
- actions: [
452
- {
453
- text: 'Undo',
454
- 'prepend:icon': 'lucide:undo-2',
455
- onClick: () => save(previous),
456
- },
457
- ],
458
- });
459
- };
473
+ }
474
+ );
460
475
 
461
- const updateDueDate = async (invoice: Invoice, dueDate: string) => {
476
+ const updateDueDate = failSoft(async (invoice: Invoice, dueDate: string) => {
462
477
  // Undoable: the pre-edit value comes from the row snapshot, and Undo
463
478
  // is the same save back to it — a real round-trip, not a guess.
464
479
  const previous = invoice.dueDate;
@@ -481,9 +496,9 @@ export function provideInvoicesWorkspace(): InvoicesWorkspaceContext {
481
496
  },
482
497
  ],
483
498
  });
484
- };
499
+ });
485
500
 
486
- const duplicateInvoice = async (invoice: Invoice) => {
501
+ const duplicateInvoice = failSoft(async (invoice: Invoice) => {
487
502
  const copy = await $fetch<Invoice>(
488
503
  `/api/invoices/${invoice.id}/duplicate`,
489
504
  {
@@ -495,30 +510,32 @@ export function provideInvoicesWorkspace(): InvoicesWorkspaceContext {
495
510
  title: `Duplicated as ${copy.number}.`,
496
511
  variant: 'success',
497
512
  });
498
- };
513
+ });
499
514
 
500
- const recordPayment = async (invoice: Invoice, draft: PaymentDraft) => {
501
- await $fetch(`/api/invoices/${invoice.id}/payments`, {
502
- method: 'POST',
503
- body: draft,
504
- });
505
- await refresh();
506
- toast({
507
- title: `Payment recorded on ${invoice.number}.`,
508
- variant: 'success',
509
- });
510
- };
515
+ const recordPayment = failSoft(
516
+ async (invoice: Invoice, draft: PaymentDraft) => {
517
+ await $fetch(`/api/invoices/${invoice.id}/payments`, {
518
+ method: 'POST',
519
+ body: draft,
520
+ });
521
+ await refresh();
522
+ toast({
523
+ title: `Payment recorded on ${invoice.number}.`,
524
+ variant: 'success',
525
+ });
526
+ }
527
+ );
511
528
 
512
- const archiveInvoice = async (invoice: Invoice) => {
529
+ const archiveInvoice = failSoft(async (invoice: Invoice) => {
513
530
  await $fetch(`/api/invoices/${invoice.id}/archive`, { method: 'PATCH' });
514
531
  await refresh();
515
532
  toast({
516
533
  title: `${invoice.number} archived.`,
517
534
  variant: 'success',
518
535
  });
519
- };
536
+ });
520
537
 
521
- const deleteInvoice = async (invoice: Invoice) => {
538
+ const deleteInvoice = failSoft(async (invoice: Invoice) => {
522
539
  const ok = await confirm({
523
540
  variant: 'destructive',
524
541
  title: 'Delete invoice',
@@ -533,9 +550,9 @@ export function provideInvoicesWorkspace(): InvoicesWorkspaceContext {
533
550
  title: `${invoice.number} deleted.`,
534
551
  variant: 'success',
535
552
  });
536
- };
553
+ });
537
554
 
538
- // Bulk actions read and clear the coopted table context themselves. The
555
+ // Bulk actions read and clear the coopted table handle themselves. The
539
556
  // header checkbox is BbTable's "all across pages" select-all: it enumerates
540
557
  // no ids, so the body becomes `{ all, unselected, filters }` — what is on
541
558
  // screen minus the exceptions — and the count is the total minus those
@@ -563,7 +580,7 @@ export function provideInvoicesWorkspace(): InvoicesWorkspaceContext {
563
580
  table.all.value = false;
564
581
  };
565
582
 
566
- const bulkMarkPaid = async () => {
583
+ const bulkMarkPaid = failSoft(async () => {
567
584
  const count = selectedCount.value;
568
585
  await $fetch('/api/invoices/bulk/mark-paid', {
569
586
  method: 'PATCH',
@@ -575,9 +592,9 @@ export function provideInvoicesWorkspace(): InvoicesWorkspaceContext {
575
592
  title: `${count} invoices marked as paid.`,
576
593
  variant: 'success',
577
594
  });
578
- };
595
+ });
579
596
 
580
- const bulkRemind = async () => {
597
+ const bulkRemind = failSoft(async () => {
581
598
  const count = selectedCount.value;
582
599
  await $fetch('/api/invoices/bulk/remind', {
583
600
  method: 'POST',
@@ -588,9 +605,9 @@ export function provideInvoicesWorkspace(): InvoicesWorkspaceContext {
588
605
  title: `Reminder sent for ${count} invoices.`,
589
606
  variant: 'success',
590
607
  });
591
- };
608
+ });
592
609
 
593
- const bulkArchive = async () => {
610
+ const bulkArchive = failSoft(async () => {
594
611
  const count = selectedCount.value;
595
612
  const ok = await confirm({
596
613
  variant: 'destructive',
@@ -610,7 +627,7 @@ export function provideInvoicesWorkspace(): InvoicesWorkspaceContext {
610
627
  title: `${count} invoices archived.`,
611
628
  variant: 'success',
612
629
  });
613
- };
630
+ });
614
631
 
615
632
  const ctx: InvoicesWorkspaceContext = {
616
633
  shell,
@@ -692,35 +709,39 @@ export function useInvoicesWorkspace(): InvoicesWorkspaceContext {
692
709
  </template>
693
710
 
694
711
  <div class="flex flex-col gap-3 p-4">
712
+ <!-- The page owns one h1. The breadcrumb is the visible title, so the
713
+ heading is for screen readers only. -->
714
+ <h1 class="sr-only">Invoices</h1>
695
715
  <FilterRail />
696
716
 
697
- <!-- Tabs as URL filters: href updates the query, the key feeds the
698
- fetch. Counts come from the server on every fetch. -->
699
- <BbTabs
717
+ <!-- The status filter: one value over one table, so a radio group
718
+ with the tabs look (a tablist would promise panels). The context
719
+ keeps it in `?tab=`; the counts come from the server on every
720
+ fetch. -->
721
+ <BbRadioGroup
700
722
  v-model="ctx.tab.value"
701
723
  compact
724
+ hide-legend
702
725
  :items="[
703
726
  {
704
727
  value: 'all',
705
728
  label: `All · ${ctx.tabCounts.value.all}`,
706
- href: '?tab=all',
707
729
  },
708
730
  {
709
731
  value: 'outstanding',
710
732
  label: `Outstanding · ${ctx.tabCounts.value.outstanding}`,
711
- href: '?tab=outstanding',
712
733
  },
713
734
  {
714
735
  value: 'paid',
715
736
  label: `Paid · ${ctx.tabCounts.value.paid}`,
716
- href: '?tab=paid',
717
737
  },
718
738
  {
719
739
  value: 'archived',
720
740
  label: `Archived · ${ctx.tabCounts.value.archived}`,
721
- href: '?tab=archived',
722
741
  },
723
742
  ]"
743
+ legend="Status"
744
+ variant="pill"
724
745
  />
725
746
 
726
747
  <BbTable
@@ -797,7 +818,7 @@ export function useInvoicesWorkspace(): InvoicesWorkspaceContext {
797
818
  </template>
798
819
  </BbTable>
799
820
 
800
- <!-- Joins the table context by id: no page/totalPages wiring at all. -->
821
+ <!-- Joins the table by id: no page/totalPages wiring at all. -->
801
822
  <BbPagination table-id="invoices-table" />
802
823
  </div>
803
824
 
@@ -830,8 +851,8 @@ import {
830
851
  BbBreadcrumbs,
831
852
  BbButton,
832
853
  BbPagination,
854
+ BbRadioGroup,
833
855
  BbTable,
834
- BbTabs,
835
856
  BbTextInput,
836
857
  } from 'bitboss-ui';
837
858
  import PageShell from '~/components/PageShell.vue';
@@ -965,7 +986,9 @@ const rowClass = (item: Invoice) =>
965
986
  <!-- Clear-all is the LAST CHIP, not a ghost button floated to the far
966
987
  end by `ml-auto`: it acts on the chips, so it belongs in their row
967
988
  and at their scale. Keep the ghost "Clear filters" for the empty
968
- state (`#empty`), where there are no chips to sit beside. -->
989
+ state (`#empty`), where there are no chips to sit beside. Its text
990
+ stays plain: one control per action. A BbBadgeButton body would be
991
+ a second tab stop doing what the × already does. -->
969
992
  <BbBadge
970
993
  v-if="ctx.hasActiveFilters.value"
971
994
  clearable
@@ -1047,7 +1070,7 @@ const searchCustomers = async ({
1047
1070
  };
1048
1071
 
1049
1072
  // Static enum facet: item text resolves synchronously, so its chip reads
1050
- // `useBbDropdownContext` (in FilterChip.vue) with zero extra fetch.
1073
+ // `useBbDropdown` (in FilterChip.vue) with zero extra fetch.
1051
1074
  const statusGroup: BbDropdownItem = {
1052
1075
  id: 'status',
1053
1076
  label: 'Status',
@@ -1143,13 +1166,13 @@ import {
1143
1166
  BbBadgeButton,
1144
1167
  BbDropdown,
1145
1168
  BbDropdownGroup,
1146
- useBbDropdownContext,
1169
+ useBbDropdown,
1147
1170
  } from 'bitboss-ui';
1148
1171
  import type { BbDropdownItem } from 'bitboss-ui';
1149
1172
 
1150
1173
  const props = defineProps<{
1151
1174
  /** Matches the group's `id` in the Filters menu, and its entry in
1152
- * `useBbDropdownContext('invoice-filters').groups`. */
1175
+ * `useBbDropdown('invoice-filters').groups`. */
1153
1176
  groupKey: string;
1154
1177
  /** Static fallback/prefix text — the group itself sets `hideLabel`. */
1155
1178
  label: string;
@@ -1171,7 +1194,7 @@ const chipRef = useTemplateRef('chipRef');
1171
1194
  // this second dropdown repeated the menu's `prefill: true` verbatim, each
1172
1195
  // seeded pipeline facet would be fetched TWICE on page load, and the chip's
1173
1196
  // copy of the result would feed nothing (the label below comes from the
1174
- // menu's resolution via context). `'interaction'` defers this copy's fetch
1197
+ // menu's resolution via `useBbDropdown`). `'interaction'` defers this copy's fetch
1175
1198
  // to the moment the chip's dropdown is actually opened. For static array
1176
1199
  // facets the override is inert — arrays resolve synchronously either way.
1177
1200
  const chipGroup = computed<BbDropdownItem>(() => ({
@@ -1183,7 +1206,7 @@ const chipGroup = computed<BbDropdownItem>(() => ({
1183
1206
  // pipeline group needs `prefill: true` (set on the MENU's copy of `group` by
1184
1207
  // FilterRail) so this never sits on a bare id/value while the menu's own
1185
1208
  // submenu is unopened.
1186
- const dropdownFilters = useBbDropdownContext('invoice-filters');
1209
+ const dropdownFilters = useBbDropdown('invoice-filters');
1187
1210
  const chipText = computed(() => {
1188
1211
  const options =
1189
1212
  dropdownFilters.groups.value[props.groupKey]?.selectedOptions ?? [];
@@ -1375,12 +1398,12 @@ import {
1375
1398
  BbCalendar,
1376
1399
  BbDatePickerInput,
1377
1400
  BbOffCanvas,
1378
- useBbOffCanvasContext,
1401
+ useBbOffCanvas,
1379
1402
  } from 'bitboss-ui';
1380
1403
  import { useInvoicesWorkspace } from './context';
1381
1404
 
1382
1405
  const ctx = useInvoicesWorkspace();
1383
- const sheet = useBbOffCanvasContext('due-date-sheet');
1406
+ const sheet = useBbOffCanvas('due-date-sheet');
1384
1407
 
1385
1408
  // A draft, committed on Apply: picking a range does not refetch per tap.
1386
1409
  const from = ref<string | null>(null);
@@ -1891,7 +1914,7 @@ import {
1891
1914
  BbForm,
1892
1915
  BbNumberInput,
1893
1916
  BbSelect,
1894
- useBbDialogContext,
1917
+ useBbDialog,
1895
1918
  } from 'bitboss-ui';
1896
1919
  import { PAYMENT_METHOD_OPTIONS, useInvoicesWorkspace } from './context';
1897
1920
  import type { Invoice, PaymentDraft } from '~/types';
@@ -1899,7 +1922,7 @@ import type { Invoice, PaymentDraft } from '~/types';
1899
1922
  const ctx = useInvoicesWorkspace();
1900
1923
 
1901
1924
  // The invoice the opener handed over: on demand it is already here in setup.
1902
- const { data: invoice } = useBbDialogContext<Invoice>('record-payment');
1925
+ const { data: invoice } = useBbDialog<Invoice>('record-payment');
1903
1926
 
1904
1927
  // Default to paying the remaining balance today.
1905
1928
  const draft = reactive<PaymentDraft>({
@@ -1923,7 +1946,7 @@ const draft = reactive<PaymentDraft>({
1923
1946
  `navigateTo` on every change (debounced for free text), and
1924
1947
  `useAsyncData('invoices', …, { watch: [() => route.query, table.page] })`
1925
1948
  is the single refetch trigger — there is exactly one place data loads.
1926
- - **The table context still owns paging and selection.** `useBbTableContext`
1949
+ - **The table handle still owns paging and selection.** `useBbTable`
1927
1950
  is unchanged from the Vue recipe: it seeds `perPage`, `BbPagination`
1928
1951
  joins by `table-id`, and the context derives `selectedCount` from
1929
1952
  `selected`/`all`/`unselected` for the `SelectionBar` — only the _items_
@@ -1933,10 +1956,11 @@ const draft = reactive<PaymentDraft>({
1933
1956
  drill-downs push; the shell renders the back arrow when depth > 1. The
1934
1957
  grammar lives in the context — a leaf cannot accidentally nuke the
1935
1958
  stack.
1936
- - **Tabs carry `href` and live counts**, exactly as in the Vue recipe — the
1937
- client-side pushState they perform keeps `route.query.tab` in sync, which
1938
- is what seeds `tab` on load and what `useAsyncData`'s `route.query` watch
1939
- reacts to.
1959
+ - **The strip keeps the URL and live counts**, like the Vue recipe: the
1960
+ context owns the URL, a tab change runs the same `navigateTo` as a filter
1961
+ change, so `route.query.tab` seeds `tab` on load and is what
1962
+ `useAsyncData`'s `route.query` watch reacts to. The strip is a plain
1963
+ `BbRadioGroup` with no URL wiring of its own, so there is one writer.
1940
1964
  - **Internal links use `to`, not `href`.** `to` renders a real Vue Router
1941
1965
  link (client-side navigation); a raw `href` would force a full page
1942
1966
  reload. Every same-app link in this recipe — the primary "New invoice"
@@ -1946,7 +1970,7 @@ const draft = reactive<PaymentDraft>({
1946
1970
  the peek's button opens it with
1947
1971
  `v-bb-dialog="{ component: RecordPaymentDialog, data: invoice }"`, the row
1948
1972
  menu with the context's `openRecordPayment(invoice)` →
1949
- `useBbDialogContext<Invoice>(RecordPaymentDialog).show(invoice)`, and
1973
+ `useBbDialog<Invoice>(RecordPaymentDialog).show(invoice)`, and
1950
1974
  `<BbHost />` mounts a fresh instance per payment, its invoice already
1951
1975
  readable in setup (so the draft is built there, with no reset). Its form
1952
1976
  is a `BbForm`: while the payment is recorded the dialog refuses Cancel,
@@ -2000,12 +2024,12 @@ const draft = reactive<PaymentDraft>({
2000
2024
  answer until the app has hydrated, so a phone hydrates the input and swaps
2001
2025
  to the sheet right after: no `<ClientOnly>` around the switch.
2002
2026
 
2003
- ### Tabs are lifecycle; chips are facets
2027
+ ### The status strip is lifecycle; chips are facets
2004
2028
 
2005
- The rail and the tab strip answer two different questions, and twinning them is
2029
+ The rail and the status strip answer two different questions, and twinning them is
2006
2030
  the fastest way to make a workspace feel arbitrary:
2007
2031
 
2008
- - **Tabs = one lifecycle segment.** Where the record _is_ in its own flow —
2032
+ - **The strip = one lifecycle segment.** Where the record _is_ in its own flow —
2009
2033
  All / Outstanding / Paid / Archived. Mutually exclusive, always visible,
2010
2034
  carrying the counts.
2011
2035
  - **Chips = cross-cutting facets.** Anything that can apply to a record in any
@@ -2013,7 +2037,7 @@ the fastest way to make a workspace feel arbitrary:
2013
2037
  applied.
2014
2038
 
2015
2039
  Never expose the same dimension both ways: a `status` facet inside the Filters
2016
- menu next to a status tab strip lets the user set two conflicting answers to one
2040
+ menu next to a status strip lets the user set two conflicting answers to one
2017
2041
  question, and neither control shows the other's state. If a dimension deserves
2018
2042
  both roles (a lifecycle you also want to combine), pick one and give the other
2019
2043
  distinct chrome — never the same values with different affordances.