bitboss-ui 2.1.134 → 3.0.0-alpha.1

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 (1358) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +244 -21
  3. package/bin/bitboss-ui-mcp.mjs +557 -0
  4. package/bin/bitboss-ui.mjs +626 -0
  5. package/dist/ai/BbAccordion.md +522 -113
  6. package/dist/ai/BbAlert.md +377 -197
  7. package/dist/ai/BbAsterisk.md +46 -0
  8. package/dist/ai/BbAvatar.md +454 -178
  9. package/dist/ai/BbBadge.md +695 -225
  10. package/dist/ai/BbBadgeButton.md +54 -0
  11. package/dist/ai/BbBaseButton.md +489 -0
  12. package/dist/ai/BbBaseCheckbox.md +49 -0
  13. package/dist/ai/BbBaseCheckboxGroup.md +64 -0
  14. package/dist/ai/BbBaseCheckboxIcon.md +174 -0
  15. package/dist/ai/BbBaseColorInput.md +64 -0
  16. package/dist/ai/BbBaseColorPalette.md +39 -0
  17. package/dist/ai/BbBaseDatePicker.md +42 -0
  18. package/dist/ai/BbBaseDatePickerInput.md +73 -0
  19. package/dist/ai/BbBaseInputContainer.md +48 -0
  20. package/dist/ai/BbBaseNumberInput.md +71 -0
  21. package/dist/ai/BbBaseRadio.md +46 -0
  22. package/dist/ai/BbBaseRadioGroup.md +63 -0
  23. package/dist/ai/BbBaseRadioIcon.md +187 -0
  24. package/dist/ai/BbBaseRating.md +51 -0
  25. package/dist/ai/BbBaseSelect.md +88 -0
  26. package/dist/ai/BbBaseSlider.md +56 -0
  27. package/dist/ai/BbBaseSwitch.md +49 -0
  28. package/dist/ai/BbBaseSwitchGroup.md +64 -0
  29. package/dist/ai/BbBaseSwitchIcon.md +184 -0
  30. package/dist/ai/BbBaseTag.md +68 -0
  31. package/dist/ai/BbBaseTextInput.md +75 -0
  32. package/dist/ai/BbBaseTextarea.md +62 -0
  33. package/dist/ai/BbBaseTimePickerInput.md +62 -0
  34. package/dist/ai/BbBreadcrumbs.md +542 -503
  35. package/dist/ai/BbButton.md +767 -636
  36. package/dist/ai/BbCheckbox.md +572 -254
  37. package/dist/ai/BbCheckboxGroup.md +561 -361
  38. package/dist/ai/BbCollapsible.md +419 -103
  39. package/dist/ai/BbColorInput.md +529 -323
  40. package/dist/ai/BbColorPalette.md +565 -330
  41. package/dist/ai/BbConfirm.md +612 -136
  42. package/dist/ai/BbConfirmPortal.md +28 -0
  43. package/dist/ai/BbDatePicker.md +244 -0
  44. package/dist/ai/BbDatePickerInput.md +706 -388
  45. package/dist/ai/BbDialog.md +770 -99
  46. package/dist/ai/BbDropdown.md +1054 -763
  47. package/dist/ai/BbDropdownButton.md +511 -615
  48. package/dist/ai/BbDropdownGroup.md +34 -0
  49. package/dist/ai/BbDropzone.md +1148 -436
  50. package/dist/ai/BbForm.md +239 -0
  51. package/dist/ai/BbIcon.md +379 -212
  52. package/dist/ai/BbIndicator.md +283 -0
  53. package/dist/ai/BbNumberInput.md +713 -355
  54. package/dist/ai/BbOffCanvas.md +875 -498
  55. package/dist/ai/BbPagination.md +483 -535
  56. package/dist/ai/BbPopover.md +583 -546
  57. package/dist/ai/BbProgress.md +456 -69
  58. package/dist/ai/BbRadio.md +343 -229
  59. package/dist/ai/BbRadioGroup.md +426 -353
  60. package/dist/ai/BbRating.md +361 -226
  61. package/dist/ai/BbSelect.md +1380 -536
  62. package/dist/ai/BbSelectPopover.md +1240 -1579
  63. package/dist/ai/BbSlider.md +478 -257
  64. package/dist/ai/BbSmoothHeight.md +472 -139
  65. package/dist/ai/BbSpinner.md +718 -131
  66. package/dist/ai/BbSwitch.md +549 -119
  67. package/dist/ai/BbSwitchGroup.md +503 -214
  68. package/dist/ai/BbTable.md +1956 -2358
  69. package/dist/ai/BbTabs.md +1113 -0
  70. package/dist/ai/BbTabsList.md +29 -0
  71. package/dist/ai/BbTabsPanes.md +27 -0
  72. package/dist/ai/BbTabsRoot.md +57 -0
  73. package/dist/ai/BbTag.md +393 -292
  74. package/dist/ai/BbTextInput.md +852 -333
  75. package/dist/ai/BbTextarea.md +836 -255
  76. package/dist/ai/BbTimePicker.md +231 -0
  77. package/dist/ai/BbTimePickerInput.md +196 -0
  78. package/dist/ai/BbToast.md +624 -196
  79. package/dist/ai/BbToastPortal.md +28 -0
  80. package/dist/ai/BbTooltip.md +443 -346
  81. package/dist/ai/BbTree.md +984 -235
  82. package/dist/ai/ChipsBox.md +27 -199
  83. package/dist/ai/ClearableButton.md +21 -55
  84. package/dist/ai/CommaBox.md +25 -200
  85. package/dist/ai/CommonInputWrapper.md +42 -0
  86. package/dist/ai/CommonPopover.md +30 -510
  87. package/dist/ai/ErrorIcon.md +19 -56
  88. package/dist/ai/FlatListBox.md +35 -379
  89. package/dist/ai/GroupedListBox.md +37 -535
  90. package/dist/ai/GuidesComponent.md +21 -0
  91. package/dist/ai/ListBox.md +38 -231
  92. package/dist/ai/OptionsContainer.md +34 -253
  93. package/dist/ai/WarningIcon.md +21 -0
  94. package/dist/ai/components.json +15883 -0
  95. package/dist/ai/composables/useBbConfig.md +80 -0
  96. package/dist/ai/composables/useBbFormContext.md +110 -0
  97. package/dist/ai/composables/useBbTableContext.md +164 -0
  98. package/dist/ai/composables/useBbTabsContext.md +118 -0
  99. package/dist/ai/composables/useBroadcastChannelInstance.md +97 -0
  100. package/dist/ai/composables/useConfirm.md +306 -0
  101. package/dist/ai/composables/useCountdown.md +84 -0
  102. package/dist/ai/composables/useId.md +60 -0
  103. package/dist/ai/composables/useMobile.md +85 -0
  104. package/dist/ai/composables/useToast.md +230 -0
  105. package/dist/ai/guides/agent-contract.md +108 -0
  106. package/dist/ai/guides/ai-router.md +111 -0
  107. package/dist/ai/guides/app-layout.md +295 -0
  108. package/dist/ai/guides/coherence-playbook.md +136 -0
  109. package/dist/ai/guides/component-picker.md +195 -0
  110. package/dist/ai/guides/design-language.md +461 -0
  111. package/dist/ai/guides/design-tokens.md +424 -0
  112. package/dist/ai/guides/fetch-items-playbook.md +161 -0
  113. package/dist/ai/guides/floating-bottom-panel.md +191 -0
  114. package/dist/ai/guides/icons-policy.md +257 -0
  115. package/dist/ai/guides/inertia-helpers.md +1394 -0
  116. package/dist/ai/guides/inline-edit-playbook.md +258 -0
  117. package/dist/ai/guides/installation-and-plugin-setup.md +377 -0
  118. package/dist/ai/guides/migration/components/bb-alert.md +37 -0
  119. package/dist/ai/guides/migration/components/bb-avatar.md +24 -0
  120. package/dist/ai/guides/migration/components/bb-badge.md +110 -0
  121. package/dist/ai/guides/migration/components/bb-breadcrumbs.md +26 -0
  122. package/dist/ai/guides/migration/components/bb-button.md +55 -0
  123. package/dist/ai/guides/migration/components/bb-checkbox-group.md +54 -0
  124. package/dist/ai/guides/migration/components/bb-checkbox.md +45 -0
  125. package/dist/ai/guides/migration/components/bb-chip.md +35 -0
  126. package/dist/ai/guides/migration/components/bb-collapsible.md +26 -0
  127. package/dist/ai/guides/migration/components/bb-color-input.md +23 -0
  128. package/dist/ai/guides/migration/components/bb-color-palette.md +31 -0
  129. package/dist/ai/guides/migration/components/bb-date-picker-input.md +84 -0
  130. package/dist/ai/guides/migration/components/bb-dialog.md +46 -0
  131. package/dist/ai/guides/migration/components/bb-dropdown-button.md +31 -0
  132. package/dist/ai/guides/migration/components/bb-dropdown.md +36 -0
  133. package/dist/ai/guides/migration/components/bb-dropzone.md +27 -0
  134. package/dist/ai/guides/migration/components/bb-icon.md +27 -0
  135. package/dist/ai/guides/migration/components/bb-off-canvas.md +25 -0
  136. package/dist/ai/guides/migration/components/bb-offcanvas.md +54 -0
  137. package/dist/ai/guides/migration/components/bb-pagination.md +24 -0
  138. package/dist/ai/guides/migration/components/bb-popover.md +52 -0
  139. package/dist/ai/guides/migration/components/bb-rating.md +24 -0
  140. package/dist/ai/guides/migration/components/bb-select-popover.md +58 -0
  141. package/dist/ai/guides/migration/components/bb-select.md +68 -0
  142. package/dist/ai/guides/migration/components/bb-slider.md +25 -0
  143. package/dist/ai/guides/migration/components/bb-smooth-height.md +45 -0
  144. package/dist/ai/guides/migration/components/bb-spinner.md +23 -0
  145. package/dist/ai/guides/migration/components/bb-table.md +66 -0
  146. package/dist/ai/guides/migration/components/bb-tabs.md +47 -0
  147. package/dist/ai/guides/migration/components/bb-tag.md +29 -0
  148. package/dist/ai/guides/migration/components/bb-text-input.md +37 -0
  149. package/dist/ai/guides/migration/components/bb-toast.md +47 -0
  150. package/dist/ai/guides/migration/components/bb-tooltip.md +34 -0
  151. package/dist/ai/guides/migration/components/bb-tree.md +77 -0
  152. package/dist/ai/guides/migration/components/use-confirm.md +46 -0
  153. package/dist/ai/guides/migration/v2-to-v3.md +649 -0
  154. package/dist/ai/guides/options-items-playbook.md +222 -0
  155. package/dist/ai/guides/page-shell.md +314 -0
  156. package/dist/ai/guides/validated-forms.md +177 -0
  157. package/dist/ai/index.md +156 -32
  158. package/dist/ai/recipes/inertia/approvals-inbox.md +1598 -0
  159. package/dist/ai/recipes/inertia/inline-edit-workspace.md +1733 -0
  160. package/dist/ai/recipes/inertia/onboarding.md +1765 -0
  161. package/dist/ai/recipes/inertia/ownership-atlas.md +1281 -0
  162. package/dist/ai/recipes/inertia/record-form.md +1442 -0
  163. package/dist/ai/recipes/inertia/records-workspace.md +1328 -0
  164. package/dist/ai/recipes/inertia/upload-center.md +1926 -0
  165. package/dist/ai/recipes/inertia/wizard-form.md +1477 -0
  166. package/dist/ai/recipes/nuxt/approvals-inbox.md +1561 -0
  167. package/dist/ai/recipes/nuxt/inline-edit-workspace.md +1690 -0
  168. package/dist/ai/recipes/nuxt/onboarding.md +1698 -0
  169. package/dist/ai/recipes/nuxt/record-form.md +1456 -0
  170. package/dist/ai/recipes/nuxt/records-workspace.md +1314 -0
  171. package/dist/ai/recipes/nuxt/upload-center.md +1847 -0
  172. package/dist/ai/recipes/nuxt/wizard-form.md +1486 -0
  173. package/dist/ai/recipes/vue/approvals-inbox.md +1479 -0
  174. package/dist/ai/recipes/vue/inline-edit-workspace.md +1581 -0
  175. package/dist/ai/recipes/vue/onboarding.md +1653 -0
  176. package/dist/ai/recipes/vue/record-form.md +1540 -0
  177. package/dist/ai/recipes/vue/records-workspace.md +1230 -0
  178. package/dist/ai/recipes/vue/upload-center.md +1806 -0
  179. package/dist/ai/recipes/vue/wizard-form.md +1418 -0
  180. package/dist/ai/source/BbAccordion.md +122 -0
  181. package/dist/ai/source/BbAlert.md +396 -0
  182. package/dist/ai/source/BbAsterisk.md +32 -0
  183. package/dist/ai/source/BbAvatar.md +256 -0
  184. package/dist/ai/source/BbBadge.md +560 -0
  185. package/dist/ai/source/BbBadgeButton.md +490 -0
  186. package/dist/ai/source/BbBaseButton.md +682 -0
  187. package/dist/ai/source/BbBaseCheckbox.md +459 -0
  188. package/dist/ai/source/BbBaseCheckboxGroup.md +554 -0
  189. package/dist/ai/source/BbBaseCheckboxIcon.md +201 -0
  190. package/dist/ai/source/BbBaseColorInput.md +413 -0
  191. package/dist/ai/source/BbBaseColorPalette.md +934 -0
  192. package/dist/ai/source/BbBaseDatePicker.md +1001 -0
  193. package/dist/ai/source/BbBaseDatePickerInput.md +1781 -0
  194. package/dist/ai/source/BbBaseInputContainer.md +1148 -0
  195. package/dist/ai/source/BbBaseNumberInput.md +615 -0
  196. package/dist/ai/source/BbBaseRadio.md +377 -0
  197. package/dist/ai/source/BbBaseRadioGroup.md +499 -0
  198. package/dist/ai/source/BbBaseRadioIcon.md +153 -0
  199. package/dist/ai/source/BbBaseRating.md +573 -0
  200. package/dist/ai/source/BbBaseSelect.md +895 -0
  201. package/dist/ai/source/BbBaseSlider.md +1085 -0
  202. package/dist/ai/source/BbBaseSwitch.md +246 -0
  203. package/dist/ai/source/BbBaseSwitchGroup.md +302 -0
  204. package/dist/ai/source/BbBaseSwitchIcon.md +206 -0
  205. package/dist/ai/source/BbBaseTag.md +688 -0
  206. package/dist/ai/source/BbBaseTextInput.md +511 -0
  207. package/dist/ai/source/BbBaseTextarea.md +480 -0
  208. package/dist/ai/source/BbBaseTimePickerInput.md +1013 -0
  209. package/dist/ai/source/BbBreadcrumbs.md +811 -0
  210. package/dist/ai/source/BbButton.md +990 -0
  211. package/dist/ai/source/BbCheckbox.md +319 -0
  212. package/dist/ai/source/BbCheckboxGroup.md +412 -0
  213. package/dist/ai/source/BbCollapsible.md +133 -0
  214. package/dist/ai/source/BbColorInput.md +315 -0
  215. package/dist/ai/source/BbColorPalette.md +361 -0
  216. package/dist/ai/source/BbConfirm.md +173 -0
  217. package/dist/ai/source/BbConfirmPortal.md +74 -0
  218. package/dist/ai/source/BbDatePicker.md +725 -0
  219. package/dist/ai/source/BbDatePickerInput.md +518 -0
  220. package/dist/ai/source/BbDialog.md +812 -0
  221. package/dist/ai/source/BbDropdown.md +2369 -0
  222. package/dist/ai/source/BbDropdownButton.md +313 -0
  223. package/dist/ai/source/BbDropdownGroup.md +1249 -0
  224. package/dist/ai/source/BbDropzone.md +749 -0
  225. package/dist/ai/source/BbForm.md +100 -0
  226. package/dist/ai/source/BbIcon.md +212 -0
  227. package/dist/ai/source/BbIndicator.md +298 -0
  228. package/dist/ai/source/BbNumberInput.md +365 -0
  229. package/dist/ai/source/BbOffCanvas.md +1260 -0
  230. package/dist/ai/source/BbPagination.md +829 -0
  231. package/dist/ai/source/BbPopover.md +853 -0
  232. package/dist/ai/source/BbProgress.md +140 -0
  233. package/dist/ai/source/BbRadio.md +294 -0
  234. package/dist/ai/source/BbRadioGroup.md +401 -0
  235. package/dist/ai/source/BbRating.md +362 -0
  236. package/dist/ai/source/BbSelect.md +681 -0
  237. package/dist/ai/source/BbSelectPopover.md +2209 -0
  238. package/dist/ai/source/BbSlider.md +371 -0
  239. package/dist/ai/source/BbSmoothHeight.md +261 -0
  240. package/dist/ai/source/BbSpinner.md +127 -0
  241. package/dist/ai/source/BbSwitch.md +175 -0
  242. package/dist/ai/source/BbSwitchGroup.md +240 -0
  243. package/dist/ai/source/BbTable.md +3348 -0
  244. package/dist/ai/source/BbTabs.md +403 -0
  245. package/dist/ai/source/BbTabsList.md +578 -0
  246. package/dist/ai/source/BbTabsPanes.md +368 -0
  247. package/dist/ai/source/BbTabsRoot.md +372 -0
  248. package/dist/ai/source/BbTag.md +383 -0
  249. package/dist/ai/source/BbTextInput.md +345 -0
  250. package/dist/ai/source/BbTextarea.md +330 -0
  251. package/dist/ai/source/BbTimePicker.md +591 -0
  252. package/dist/ai/source/BbTimePickerInput.md +367 -0
  253. package/dist/ai/source/BbToast.md +524 -0
  254. package/dist/ai/source/BbToastPortal.md +482 -0
  255. package/dist/ai/source/BbTooltip.md +508 -0
  256. package/dist/ai/source/BbTree.md +319 -0
  257. package/dist/ai/source/ChipsBox.md +201 -0
  258. package/dist/ai/source/ClearableButton.md +70 -0
  259. package/dist/ai/source/CommaBox.md +202 -0
  260. package/dist/ai/source/CommonInputWrapper.md +554 -0
  261. package/dist/ai/source/CommonPopover.md +606 -0
  262. package/dist/ai/source/ErrorIcon.md +43 -0
  263. package/dist/ai/source/FlatListBox.md +396 -0
  264. package/dist/ai/source/GroupedListBox.md +540 -0
  265. package/dist/ai/source/GuidesComponent.md +383 -0
  266. package/dist/ai/source/ListBox.md +238 -0
  267. package/dist/ai/source/OptionsContainer.md +191 -0
  268. package/dist/ai/source/WarningIcon.md +47 -0
  269. package/dist/alert-variants.d.ts +12 -0
  270. package/dist/assets/css/reset.css_inline.js +4 -0
  271. package/dist/assets/svgs/alert.svg_raw.js +4 -0
  272. package/dist/assets/svgs/calendar.svg_raw.js +4 -0
  273. package/dist/assets/svgs/check_stroke.svg_raw.js +4 -0
  274. package/dist/assets/svgs/chevron_down.svg_raw.js +4 -0
  275. package/dist/assets/svgs/chevron_right.svg_raw.js +4 -0
  276. package/dist/assets/svgs/clear.svg_raw.js +4 -0
  277. package/dist/assets/svgs/clock.svg_raw.js +4 -0
  278. package/dist/assets/svgs/error.svg_raw.js +4 -0
  279. package/dist/assets/svgs/search.svg_raw.js +4 -0
  280. package/dist/assets/svgs/sort.svg_raw.js +4 -0
  281. package/dist/assets/svgs/spinner.svg_raw.js +4 -0
  282. package/dist/assets/svgs/user.svg_raw.js +4 -0
  283. package/dist/badge-variants.d.ts +18 -0
  284. package/dist/button-variants.d.ts +15 -0
  285. package/dist/components/BbAccordion/BbAccordion.vue.d.ts +9 -3
  286. package/dist/components/BbAccordion/BbAccordion.vue.js +6 -0
  287. package/dist/components/BbAccordion/BbAccordion.vue_vue_type_script_setup_true_lang.js +66 -0
  288. package/dist/components/BbAccordion/types.d.ts +10 -7
  289. package/dist/components/BbAlert/BbAlert.vue.d.ts +12 -3
  290. package/dist/components/BbAlert/BbAlert.vue.js +6 -0
  291. package/dist/components/BbAlert/BbAlert.vue_vue_type_script_setup_true_lang.js +65 -0
  292. package/dist/components/BbAlert/types.d.ts +51 -12
  293. package/dist/components/BbAsterisk/BbAsterisk.vue.d.ts +3 -0
  294. package/dist/components/BbAsterisk/BbAsterisk.vue.js +6 -0
  295. package/dist/components/BbAsterisk/BbAsterisk.vue_vue_type_script_setup_true_lang.js +13 -0
  296. package/dist/components/BbAvatar/BbAvatar.vue.d.ts +5 -0
  297. package/dist/components/BbAvatar/BbAvatar.vue.js +6 -0
  298. package/dist/components/BbAvatar/BbAvatar.vue_vue_type_script_setup_true_lang.js +78 -0
  299. package/dist/components/BbAvatar/types.d.ts +4 -5
  300. package/dist/components/BbBadge/BadgeAppendIcon.vue.d.ts +3 -0
  301. package/dist/components/BbBadge/BadgeAppendIcon.vue.js +5 -0
  302. package/dist/components/BbBadge/BadgeAppendIcon.vue_vue_type_script_setup_true_lang.js +22 -0
  303. package/dist/components/BbBadge/BadgeBodyContent.vue.d.ts +15 -0
  304. package/dist/components/BbBadge/BadgeBodyContent.vue.js +5 -0
  305. package/dist/components/BbBadge/BadgeBodyContent.vue_vue_type_script_setup_true_lang.js +34 -0
  306. package/dist/components/BbBadge/BbBadge.vue.d.ts +8 -1
  307. package/dist/components/BbBadge/BbBadge.vue.js +6 -0
  308. package/dist/components/BbBadge/BbBadge.vue_vue_type_script_setup_true_lang.js +83 -0
  309. package/dist/components/BbBadge/BbBadgeButton.vue.d.ts +12 -0
  310. package/dist/components/BbBadge/BbBadgeButton.vue.js +5 -0
  311. package/dist/components/BbBadge/BbBadgeButton.vue_vue_type_script_setup_true_lang.js +54 -0
  312. package/dist/components/BbBadge/badgeButtonContext.d.ts +27 -0
  313. package/dist/components/BbBadge/badgeButtonContext.js +5 -0
  314. package/dist/components/BbBadge/types.d.ts +61 -16
  315. package/dist/components/BbBaseButton/BbBaseButton.vue.d.ts +13 -0
  316. package/dist/components/BbBaseButton/BbBaseButton.vue.js +6 -0
  317. package/dist/components/BbBaseButton/BbBaseButton.vue_vue_type_script_setup_true_lang.js +171 -0
  318. package/dist/components/BbBaseButton/RouterComponent.vue.js +5 -0
  319. package/dist/components/BbBaseButton/RouterComponent.vue_vue_type_script_setup_true_lang.js +28 -0
  320. package/dist/components/BbBaseButton/types.d.ts +191 -0
  321. package/dist/components/BbBaseButton/types.js +33 -0
  322. package/dist/components/BbBaseCheckbox/BbBaseCheckbox.vue.d.ts +40 -0
  323. package/dist/components/BbBaseCheckbox/BbBaseCheckbox.vue.js +6 -0
  324. package/dist/components/BbBaseCheckbox/BbBaseCheckbox.vue_vue_type_script_setup_true_lang.js +145 -0
  325. package/dist/components/BbBaseCheckbox/types.d.ts +222 -0
  326. package/dist/components/BbBaseCheckboxGroup/BbBaseCheckboxGroup.vue.d.ts +19 -0
  327. package/dist/components/BbBaseCheckboxGroup/BbBaseCheckboxGroup.vue.js +6 -0
  328. package/dist/components/BbBaseCheckboxGroup/BbBaseCheckboxGroup.vue_vue_type_script_setup_true_lang.js +190 -0
  329. package/dist/components/BbBaseCheckboxGroup/types.d.ts +257 -0
  330. package/dist/components/BbBaseCheckboxIcon/BbBaseCheckboxIcon.vue.d.ts +4 -0
  331. package/dist/components/BbBaseCheckboxIcon/BbBaseCheckboxIcon.vue.js +6 -0
  332. package/dist/components/BbBaseCheckboxIcon/BbBaseCheckboxIcon.vue_vue_type_script_setup_true_lang.js +43 -0
  333. package/dist/components/BbBaseCheckboxIcon/types.d.ts +47 -0
  334. package/dist/components/BbBaseColorInput/BbBaseColorInput.vue.d.ts +42 -0
  335. package/dist/components/BbBaseColorInput/BbBaseColorInput.vue.js +6 -0
  336. package/dist/components/BbBaseColorInput/BbBaseColorInput.vue_vue_type_script_setup_true_lang.js +178 -0
  337. package/dist/components/BbBaseColorInput/types.d.ts +207 -0
  338. package/dist/components/BbBaseColorPalette/BbBaseColorPalette.vue.d.ts +13 -0
  339. package/dist/components/BbBaseColorPalette/BbBaseColorPalette.vue.js +6 -0
  340. package/dist/components/BbBaseColorPalette/BbBaseColorPalette.vue_vue_type_script_setup_true_lang.js +395 -0
  341. package/dist/components/BbBaseColorPalette/types.d.ts +40 -0
  342. package/dist/components/BbBaseDatePicker/BbBaseDatePicker.vue.js +6 -0
  343. package/dist/components/BbBaseDatePicker/BbBaseDatePicker.vue_vue_type_script_setup_true_lang.js +300 -0
  344. package/dist/components/BbBaseDatePicker/BbBaseDatePickerInputDaySelector.vue.d.ts +44 -0
  345. package/dist/components/BbBaseDatePicker/BbBaseDatePickerInputDaySelector.vue.js +5 -0
  346. package/dist/components/BbBaseDatePicker/BbBaseDatePickerInputDaySelector.vue_vue_type_script_setup_true_lang.js +310 -0
  347. package/dist/components/BbBaseDatePicker/BbBaseDatePickerMonthSelector.vue.d.ts +5 -0
  348. package/dist/components/BbBaseDatePicker/BbBaseDatePickerMonthSelector.vue.js +5 -0
  349. package/dist/components/BbBaseDatePicker/BbBaseDatePickerMonthSelector.vue_vue_type_script_setup_true_lang.js +63 -0
  350. package/dist/components/BbBaseDatePicker/BbBaseDatePickerYearSelector.vue.d.ts +5 -0
  351. package/dist/components/BbBaseDatePicker/BbBaseDatePickerYearSelector.vue.js +5 -0
  352. package/dist/components/BbBaseDatePicker/BbBaseDatePickerYearSelector.vue_vue_type_script_setup_true_lang.js +75 -0
  353. package/dist/components/BbBaseDatePicker/typeahead.d.ts +112 -0
  354. package/dist/components/BbBaseDatePicker/typeahead.js +37 -0
  355. package/dist/components/BbBaseDatePicker/types.d.ts +97 -0
  356. package/dist/components/BbBaseDatePicker/useDatePickerContext.d.ts +58 -0
  357. package/dist/components/BbBaseDatePicker/useDatePickerContext.js +11 -0
  358. package/dist/components/BbBaseDatePickerInput/BbBaseDatePickerInput.vue.d.ts +30 -0
  359. package/dist/components/BbBaseDatePickerInput/BbBaseDatePickerInput.vue.js +6 -0
  360. package/dist/components/BbBaseDatePickerInput/BbBaseDatePickerInput.vue_vue_type_script_setup_true_lang.js +713 -0
  361. package/dist/components/BbBaseDatePickerInput/BbBaseDatePickerTimeSelector.vue.d.ts +30 -0
  362. package/dist/components/BbBaseDatePickerInput/BbBaseDatePickerTimeSelector.vue.js +6 -0
  363. package/dist/components/BbBaseDatePickerInput/BbBaseDatePickerTimeSelector.vue_vue_type_script_setup_true_lang.js +204 -0
  364. package/dist/components/BbBaseDatePickerInput/types.d.ts +309 -0
  365. package/dist/components/BbBaseInputContainer/BbBaseInputContainer.vue.d.ts +17 -0
  366. package/dist/components/BbBaseInputContainer/BbBaseInputContainer.vue.js +6 -0
  367. package/dist/components/BbBaseInputContainer/BbBaseInputContainer.vue_vue_type_script_setup_true_lang.js +184 -0
  368. package/dist/components/BbBaseInputContainer/types.d.ts +185 -0
  369. package/dist/components/BbBaseNumberInput/BbBaseNumberInput.vue.d.ts +52 -0
  370. package/dist/components/BbBaseNumberInput/BbBaseNumberInput.vue.js +6 -0
  371. package/dist/components/BbBaseNumberInput/BbBaseNumberInput.vue_vue_type_script_setup_true_lang.js +211 -0
  372. package/dist/components/BbBaseNumberInput/types.d.ts +211 -0
  373. package/dist/components/BbBaseRadio/BbBaseRadio.vue.d.ts +33 -0
  374. package/dist/components/BbBaseRadio/BbBaseRadio.vue.js +6 -0
  375. package/dist/components/BbBaseRadio/BbBaseRadio.vue_vue_type_script_setup_true_lang.js +114 -0
  376. package/dist/components/BbBaseRadio/types.d.ts +179 -0
  377. package/dist/components/BbBaseRadioGroup/BbBaseRadioGroup.vue.d.ts +19 -0
  378. package/dist/components/BbBaseRadioGroup/BbBaseRadioGroup.vue.js +6 -0
  379. package/dist/components/BbBaseRadioGroup/BbBaseRadioGroup.vue_vue_type_script_setup_true_lang.js +172 -0
  380. package/dist/components/BbBaseRadioGroup/types.d.ts +215 -0
  381. package/dist/components/BbBaseRadioIcon/BbBaseRadioIcon.vue.d.ts +4 -0
  382. package/dist/components/BbBaseRadioIcon/BbBaseRadioIcon.vue.js +6 -0
  383. package/dist/components/BbBaseRadioIcon/BbBaseRadioIcon.vue_vue_type_script_setup_true_lang.js +28 -0
  384. package/dist/components/BbBaseRadioIcon/types.d.ts +41 -0
  385. package/dist/components/BbBaseRating/BbBaseRating.vue.d.ts +38 -0
  386. package/dist/components/BbBaseRating/BbBaseRating.vue.js +6 -0
  387. package/dist/components/BbBaseRating/BbBaseRating.vue_vue_type_script_setup_true_lang.js +184 -0
  388. package/dist/components/BbBaseRating/types.d.ts +168 -0
  389. package/dist/components/BbBaseSelect/BbBaseSelect.vue.d.ts +19 -0
  390. package/dist/components/BbBaseSelect/BbBaseSelect.vue.js +6 -0
  391. package/dist/components/BbBaseSelect/BbBaseSelect.vue_vue_type_script_setup_true_lang.js +307 -0
  392. package/dist/components/BbBaseSelect/types.d.ts +294 -0
  393. package/dist/components/BbBaseSlider/BbBaseSlider.vue.d.ts +35 -0
  394. package/dist/components/BbBaseSlider/BbBaseSlider.vue.js +6 -0
  395. package/dist/components/BbBaseSlider/BbBaseSlider.vue_vue_type_script_setup_true_lang.js +324 -0
  396. package/dist/components/BbBaseSlider/types.d.ts +200 -0
  397. package/dist/components/BbBaseSwitch/BbBaseSwitch.vue.d.ts +35 -0
  398. package/dist/components/BbBaseSwitch/BbBaseSwitch.vue.js +6 -0
  399. package/dist/components/BbBaseSwitch/BbBaseSwitch.vue_vue_type_script_setup_true_lang.js +146 -0
  400. package/dist/components/BbBaseSwitch/types.d.ts +10 -0
  401. package/dist/components/BbBaseSwitchGroup/BbBaseSwitchGroup.vue.d.ts +19 -0
  402. package/dist/components/BbBaseSwitchGroup/BbBaseSwitchGroup.vue.js +6 -0
  403. package/dist/components/BbBaseSwitchGroup/BbBaseSwitchGroup.vue_vue_type_script_setup_true_lang.js +190 -0
  404. package/dist/components/BbBaseSwitchGroup/types.d.ts +8 -0
  405. package/dist/components/BbBaseSwitchIcon/BbBaseSwitchIcon.vue.d.ts +4 -0
  406. package/dist/components/BbBaseSwitchIcon/BbBaseSwitchIcon.vue.js +6 -0
  407. package/dist/components/BbBaseSwitchIcon/BbBaseSwitchIcon.vue_vue_type_script_setup_true_lang.js +30 -0
  408. package/dist/components/BbBaseSwitchIcon/types.d.ts +48 -0
  409. package/dist/components/BbBaseTag/BbBaseTag.vue.d.ts +50 -0
  410. package/dist/components/BbBaseTag/BbBaseTag.vue.js +6 -0
  411. package/dist/components/BbBaseTag/BbBaseTag.vue_vue_type_script_setup_true_lang.js +266 -0
  412. package/dist/components/BbBaseTag/types.d.ts +160 -0
  413. package/dist/components/BbBaseTextInput/BbBaseTextInput.vue.d.ts +45 -0
  414. package/dist/components/BbBaseTextInput/BbBaseTextInput.vue.js +6 -0
  415. package/dist/components/BbBaseTextInput/BbBaseTextInput.vue_vue_type_script_setup_true_lang.js +200 -0
  416. package/dist/components/BbBaseTextInput/types.d.ts +209 -0
  417. package/dist/components/BbBaseTextarea/BbBaseTextarea.vue.d.ts +39 -0
  418. package/dist/components/BbBaseTextarea/BbBaseTextarea.vue.js +6 -0
  419. package/dist/components/BbBaseTextarea/BbBaseTextarea.vue_vue_type_script_setup_true_lang.js +175 -0
  420. package/dist/components/BbBaseTextarea/types.d.ts +170 -0
  421. package/dist/components/BbBaseTimePickerInput/BbBaseTimePickerInput.vue.d.ts +27 -0
  422. package/dist/components/BbBaseTimePickerInput/BbBaseTimePickerInput.vue.js +6 -0
  423. package/dist/components/BbBaseTimePickerInput/BbBaseTimePickerInput.vue_vue_type_script_setup_true_lang.js +517 -0
  424. package/dist/components/BbBaseTimePickerInput/types.d.ts +151 -0
  425. package/dist/components/BbBreadcrumbs/BbBreadcrumbs.vue.d.ts +0 -1
  426. package/dist/components/BbBreadcrumbs/BbBreadcrumbs.vue.js +6 -0
  427. package/dist/components/BbBreadcrumbs/BbBreadcrumbs.vue_vue_type_script_setup_true_lang.js +224 -0
  428. package/dist/components/BbBreadcrumbs/estimateBreadcrumbItemWidth.js +47 -0
  429. package/dist/components/BbBreadcrumbs/types.d.ts +33 -22
  430. package/dist/components/BbButton/BbButton.vue.d.ts +6 -5
  431. package/dist/components/BbButton/BbButton.vue.js +6 -0
  432. package/dist/components/BbButton/BbButton.vue_vue_type_script_setup_true_lang.js +177 -0
  433. package/dist/components/BbButton/types.d.ts +48 -47
  434. package/dist/components/BbCheckbox/BbCheckbox.vue.d.ts +4 -3
  435. package/dist/components/BbCheckbox/BbCheckbox.vue.js +6 -0
  436. package/dist/components/BbCheckbox/BbCheckbox.vue_vue_type_script_setup_true_lang.js +146 -0
  437. package/dist/components/BbCheckbox/types.d.ts +24 -10
  438. package/dist/components/BbCheckboxGroup/BbCheckboxGroup.vue.d.ts +2 -13
  439. package/dist/components/BbCheckboxGroup/BbCheckboxGroup.vue.js +6 -0
  440. package/dist/components/BbCheckboxGroup/BbCheckboxGroup.vue_vue_type_script_setup_true_lang.js +190 -0
  441. package/dist/components/BbCheckboxGroup/types.d.ts +44 -23
  442. package/dist/components/BbCollapsible/BbCollapsible.vue.d.ts +2 -1
  443. package/dist/components/BbCollapsible/BbCollapsible.vue.js +6 -0
  444. package/dist/components/BbCollapsible/BbCollapsible.vue_vue_type_script_setup_true_lang.js +31 -0
  445. package/dist/components/BbCollapsible/types.d.ts +10 -9
  446. package/dist/components/BbColorInput/BbColorInput.vue.d.ts +10 -1
  447. package/dist/components/BbColorInput/BbColorInput.vue.js +6 -0
  448. package/dist/components/BbColorInput/BbColorInput.vue_vue_type_script_setup_true_lang.js +177 -0
  449. package/dist/components/BbColorInput/types.d.ts +37 -11
  450. package/dist/components/BbColorPalette/BbColorPalette.vue.d.ts +5 -8
  451. package/dist/components/BbColorPalette/BbColorPalette.vue.js +5 -0
  452. package/dist/components/BbColorPalette/BbColorPalette.vue_vue_type_script_setup_true_lang.js +125 -0
  453. package/dist/components/BbColorPalette/types.d.ts +66 -53
  454. package/dist/components/BbConfirm/BbConfirm.vue.js +6 -0
  455. package/dist/components/BbConfirm/BbConfirm.vue_vue_type_script_setup_true_lang.js +130 -0
  456. package/dist/components/BbConfirm/BbConfirmPortal.vue.d.ts +5 -6
  457. package/dist/components/BbConfirm/BbConfirmPortal.vue.js +5 -0
  458. package/dist/components/BbConfirm/BbConfirmPortal.vue_vue_type_script_setup_true_lang.js +19 -0
  459. package/dist/components/BbDatePicker/BbDatePicker.vue.d.ts +37 -0
  460. package/dist/components/BbDatePicker/BbDatePicker.vue.js +6 -0
  461. package/dist/components/BbDatePicker/BbDatePicker.vue_vue_type_script_setup_true_lang.js +319 -0
  462. package/dist/components/BbDatePicker/types.d.ts +155 -0
  463. package/dist/components/BbDatePickerInput/BbDatePickerInput.vue.d.ts +3 -1
  464. package/dist/components/BbDatePickerInput/BbDatePickerInput.vue.js +6 -0
  465. package/dist/components/BbDatePickerInput/BbDatePickerInput.vue_vue_type_script_setup_true_lang.js +179 -0
  466. package/dist/components/BbDatePickerInput/types.d.ts +127 -16
  467. package/dist/components/BbDialog/BbDialog.vue.d.ts +8 -6
  468. package/dist/components/BbDialog/BbDialog.vue.js +6 -0
  469. package/dist/components/BbDialog/BbDialog.vue_vue_type_script_setup_true_lang.js +214 -0
  470. package/dist/components/BbDialog/types.d.ts +146 -1
  471. package/dist/components/BbDialog/useDialogStack.d.ts +5 -0
  472. package/dist/components/BbDialog/useDialogStack.js +20 -0
  473. package/dist/components/BbDropdown/AdaptiveDropdown.vue.d.ts +18 -0
  474. package/dist/components/BbDropdown/AdaptiveDropdown.vue.js +6 -0
  475. package/dist/components/BbDropdown/AdaptiveDropdown.vue_vue_type_script_setup_true_lang.js +116 -0
  476. package/dist/components/BbDropdown/BbDropdown.vue.d.ts +14 -7
  477. package/dist/components/BbDropdown/BbDropdown.vue.js +6 -0
  478. package/dist/components/BbDropdown/BbDropdown.vue_vue_type_script_setup_true_lang.js +560 -0
  479. package/dist/components/BbDropdown/BbDropdownGroup.vue.d.ts +44 -0
  480. package/dist/components/BbDropdown/BbDropdownGroup.vue.js +5 -0
  481. package/dist/components/BbDropdown/BbDropdownGroup.vue_vue_type_script_setup_true_lang.js +36 -0
  482. package/dist/components/BbDropdown/BbDropdownList.vue.d.ts +27 -0
  483. package/dist/components/BbDropdown/BbDropdownList.vue.js +6 -0
  484. package/dist/components/BbDropdown/BbDropdownList.vue_vue_type_script_setup_true_lang.js +464 -0
  485. package/dist/components/BbDropdown/DropdownPipelineResolver.vue.d.ts +16 -0
  486. package/dist/components/BbDropdown/DropdownPipelineResolver.vue.js +5 -0
  487. package/dist/components/BbDropdown/DropdownPipelineResolver.vue_vue_type_script_setup_true_lang.js +168 -0
  488. package/dist/components/BbDropdown/normalizeGroups.d.ts +18 -0
  489. package/dist/components/BbDropdown/normalizeGroups.js +46 -0
  490. package/dist/components/BbDropdown/types.d.ts +457 -45
  491. package/dist/components/BbDropdown/types.js +4 -0
  492. package/dist/components/BbDropdown/useDropdownContext.d.ts +89 -0
  493. package/dist/components/BbDropdown/useDropdownContext.js +9 -0
  494. package/dist/components/BbDropdown/useDropdownGroupRegistry.d.ts +108 -0
  495. package/dist/components/BbDropdown/useDropdownGroupRegistry.js +5 -0
  496. package/dist/components/BbDropdownButton/BbDropdownButton.vue.d.ts +3 -3
  497. package/dist/components/BbDropdownButton/BbDropdownButton.vue.js +6 -0
  498. package/dist/components/BbDropdownButton/BbDropdownButton.vue_vue_type_script_setup_true_lang.js +119 -0
  499. package/dist/components/BbDropdownButton/types.d.ts +45 -52
  500. package/dist/components/BbDropzone/BbDropzone.vue.d.ts +5 -4
  501. package/dist/components/BbDropzone/BbDropzone.vue.js +6 -0
  502. package/dist/components/BbDropzone/BbDropzone.vue_vue_type_script_setup_true_lang.js +284 -0
  503. package/dist/components/BbDropzone/types.d.ts +55 -7
  504. package/dist/components/BbIcon/BbIcon.vue.d.ts +3 -2
  505. package/dist/components/BbIcon/BbIcon.vue.js +6 -0
  506. package/dist/components/BbIcon/BbIcon.vue_vue_type_script_setup_true_lang.js +65 -0
  507. package/dist/components/BbIcon/types.d.ts +6 -19
  508. package/dist/components/BbIndicator/BbIndicator.vue.d.ts +14 -0
  509. package/dist/components/BbIndicator/BbIndicator.vue.js +6 -0
  510. package/dist/components/BbIndicator/BbIndicator.vue_vue_type_script_setup_true_lang.js +56 -0
  511. package/dist/components/BbIndicator/types.d.ts +49 -0
  512. package/dist/components/BbNumberInput/BbNumberInput.vue.d.ts +12 -6
  513. package/dist/components/BbNumberInput/BbNumberInput.vue.js +6 -0
  514. package/dist/components/BbNumberInput/BbNumberInput.vue_vue_type_script_setup_true_lang.js +194 -0
  515. package/dist/components/BbNumberInput/types.d.ts +31 -4
  516. package/dist/components/BbOffCanvas/BbOffCanvas.vue.d.ts +10 -10
  517. package/dist/components/BbOffCanvas/BbOffCanvas.vue.js +6 -0
  518. package/dist/components/BbOffCanvas/BbOffCanvas.vue_vue_type_script_setup_true_lang.js +284 -0
  519. package/dist/components/BbOffCanvas/types.d.ts +71 -39
  520. package/dist/components/BbOffCanvas/useOffCanvasStack.d.ts +25 -0
  521. package/dist/components/BbOffCanvas/useOffCanvasStack.js +68 -0
  522. package/dist/components/BbPagination/BbPagination.vue.d.ts +3 -4
  523. package/dist/components/BbPagination/BbPagination.vue.js +6 -0
  524. package/dist/components/BbPagination/BbPagination.vue_vue_type_script_setup_true_lang.js +244 -0
  525. package/dist/components/BbPagination/paginationFit.d.ts +38 -0
  526. package/dist/components/BbPagination/paginationFit.js +13 -0
  527. package/dist/components/BbPagination/types.d.ts +51 -16
  528. package/dist/components/BbPopover/BbPopover.vue.d.ts +10 -15
  529. package/dist/components/BbPopover/BbPopover.vue.js +6 -0
  530. package/dist/components/BbPopover/BbPopover.vue_vue_type_script_setup_true_lang.js +310 -0
  531. package/dist/components/BbPopover/escapeStack.d.ts +6 -0
  532. package/dist/components/BbPopover/escapeStack.js +10 -0
  533. package/dist/components/BbPopover/types.d.ts +84 -31
  534. package/dist/components/BbProgress/BbProgress.vue.d.ts +1 -0
  535. package/dist/components/BbProgress/BbProgress.vue.js +6 -0
  536. package/dist/components/BbProgress/BbProgress.vue_vue_type_script_setup_true_lang.js +36 -0
  537. package/dist/components/BbProgress/types.d.ts +15 -1
  538. package/dist/components/BbRadio/BbRadio.vue.d.ts +5 -3
  539. package/dist/components/BbRadio/BbRadio.vue.js +6 -0
  540. package/dist/components/BbRadio/BbRadio.vue_vue_type_script_setup_true_lang.js +133 -0
  541. package/dist/components/BbRadio/types.d.ts +23 -9
  542. package/dist/components/BbRadioGroup/BbRadioGroup.vue.d.ts +4 -14
  543. package/dist/components/BbRadioGroup/BbRadioGroup.vue.js +6 -0
  544. package/dist/components/BbRadioGroup/BbRadioGroup.vue_vue_type_script_setup_true_lang.js +184 -0
  545. package/dist/components/BbRadioGroup/types.d.ts +41 -22
  546. package/dist/components/BbRating/BbRating.vue.d.ts +4 -1
  547. package/dist/components/BbRating/BbRating.vue.js +6 -0
  548. package/dist/components/BbRating/BbRating.vue_vue_type_script_setup_true_lang.js +150 -0
  549. package/dist/components/BbRating/types.d.ts +37 -10
  550. package/dist/components/BbSelect/BbSelect.vue.d.ts +2 -11
  551. package/dist/components/BbSelect/BbSelect.vue.js +6 -0
  552. package/dist/components/BbSelect/BbSelect.vue_vue_type_script_setup_true_lang.js +241 -0
  553. package/dist/components/BbSelect/types.d.ts +105 -59
  554. package/dist/components/BbSelectPopover/BbSelectPopover.vue.d.ts +1 -10
  555. package/dist/components/BbSelectPopover/BbSelectPopover.vue.js +6 -0
  556. package/dist/components/BbSelectPopover/BbSelectPopover.vue_vue_type_script_setup_true_lang.js +637 -0
  557. package/dist/components/BbSelectPopover/types.d.ts +189 -102
  558. package/dist/components/BbSlider/BbSlider.vue.d.ts +3 -6
  559. package/dist/components/BbSlider/BbSlider.vue.js +6 -0
  560. package/dist/components/BbSlider/BbSlider.vue_vue_type_script_setup_true_lang.js +166 -0
  561. package/dist/components/BbSlider/types.d.ts +37 -13
  562. package/dist/components/BbSmoothHeight/BbSmoothHeight.vue.d.ts +3 -1
  563. package/dist/components/BbSmoothHeight/BbSmoothHeight.vue.js +6 -0
  564. package/dist/components/BbSmoothHeight/BbSmoothHeight.vue_vue_type_script_setup_true_lang.js +79 -0
  565. package/dist/components/BbSmoothHeight/types.d.ts +13 -2
  566. package/dist/components/BbSpinner/BbSpinner.vue.d.ts +1 -1
  567. package/dist/components/BbSpinner/BbSpinner.vue.js +6 -0
  568. package/dist/components/BbSpinner/BbSpinner.vue_vue_type_script_setup_true_lang.js +30 -0
  569. package/dist/components/BbSpinner/types.d.ts +10 -3
  570. package/dist/components/BbSwitch/BbSwitch.vue.d.ts +5 -3
  571. package/dist/components/BbSwitch/BbSwitch.vue.js +6 -0
  572. package/dist/components/BbSwitch/BbSwitch.vue_vue_type_script_setup_true_lang.js +142 -0
  573. package/dist/components/BbSwitch/types.d.ts +3 -1
  574. package/dist/components/BbSwitchGroup/BbSwitchGroup.vue.d.ts +4 -14
  575. package/dist/components/BbSwitchGroup/BbSwitchGroup.vue.js +6 -0
  576. package/dist/components/BbSwitchGroup/BbSwitchGroup.vue_vue_type_script_setup_true_lang.js +190 -0
  577. package/dist/components/BbSwitchGroup/types.d.ts +3 -22
  578. package/dist/components/BbTable/BbTable.vue.d.ts +53 -31
  579. package/dist/components/BbTable/BbTable.vue.js +6 -0
  580. package/dist/components/BbTable/BbTable.vue_vue_type_script_setup_true_lang.js +889 -0
  581. package/dist/components/BbTable/types.d.ts +176 -37
  582. package/dist/components/BbTable/utils.d.ts +9 -1
  583. package/dist/components/BbTable/utils.js +53 -0
  584. package/dist/components/BbTabs/BbTabs.vue.d.ts +20 -0
  585. package/dist/components/BbTabs/BbTabs.vue.js +6 -0
  586. package/dist/components/BbTabs/BbTabs.vue_vue_type_script_setup_true_lang.js +64 -0
  587. package/dist/components/BbTabs/BbTabsList.vue.d.ts +19 -0
  588. package/dist/components/BbTabs/BbTabsList.vue.js +6 -0
  589. package/dist/components/BbTabs/BbTabsList.vue_vue_type_script_setup_true_lang.js +123 -0
  590. package/dist/components/BbTabs/BbTabsPanes.vue.d.ts +16 -0
  591. package/dist/components/BbTabs/BbTabsPanes.vue.js +6 -0
  592. package/dist/components/BbTabs/BbTabsPanes.vue_vue_type_script_setup_true_lang.js +35 -0
  593. package/dist/components/BbTabs/BbTabsRoot.vue.d.ts +20 -0
  594. package/dist/components/BbTabs/BbTabsRoot.vue.js +5 -0
  595. package/dist/components/BbTabs/BbTabsRoot.vue_vue_type_script_setup_true_lang.js +55 -0
  596. package/dist/components/BbTabs/types.d.ts +264 -0
  597. package/dist/components/BbTag/BbTag.vue.d.ts +19 -6
  598. package/dist/components/BbTag/BbTag.vue.js +6 -0
  599. package/dist/components/BbTag/BbTag.vue_vue_type_script_setup_true_lang.js +187 -0
  600. package/dist/components/BbTag/types.d.ts +48 -17
  601. package/dist/components/BbTextInput/BbTextInput.vue.d.ts +10 -1
  602. package/dist/components/BbTextInput/BbTextInput.vue.js +6 -0
  603. package/dist/components/BbTextInput/BbTextInput.vue_vue_type_script_setup_true_lang.js +195 -0
  604. package/dist/components/BbTextInput/types.d.ts +24 -4
  605. package/dist/components/BbTextarea/BbTextarea.vue.d.ts +10 -1
  606. package/dist/components/BbTextarea/BbTextarea.vue.js +6 -0
  607. package/dist/components/BbTextarea/BbTextarea.vue_vue_type_script_setup_true_lang.js +178 -0
  608. package/dist/components/BbTextarea/types.d.ts +26 -2
  609. package/dist/components/BbTimePicker/BbTimePicker.vue.d.ts +33 -0
  610. package/dist/components/BbTimePicker/BbTimePicker.vue.js +6 -0
  611. package/dist/components/BbTimePicker/BbTimePicker.vue_vue_type_script_setup_true_lang.js +244 -0
  612. package/dist/components/BbTimePicker/types.d.ts +129 -0
  613. package/dist/components/BbTimePickerInput/BbTimePickerInput.vue.d.ts +25 -0
  614. package/dist/components/BbTimePickerInput/BbTimePickerInput.vue.js +6 -0
  615. package/dist/components/BbTimePickerInput/BbTimePickerInput.vue_vue_type_script_setup_true_lang.js +157 -0
  616. package/dist/components/BbTimePickerInput/types.d.ts +165 -0
  617. package/dist/components/BbToast/BbToast.vue.d.ts +2 -3
  618. package/dist/components/BbToast/BbToast.vue.js +6 -0
  619. package/dist/components/BbToast/BbToast.vue_vue_type_script_setup_true_lang.js +35 -0
  620. package/dist/components/BbToast/BbToastMessage.vue.d.ts +17 -8
  621. package/dist/components/BbToast/BbToastMessage.vue.js +5 -0
  622. package/dist/components/BbToast/BbToastMessage.vue_vue_type_script_setup_true_lang.js +170 -0
  623. package/dist/components/BbToast/BbToastPortal.vue.d.ts +30 -0
  624. package/dist/components/BbToast/BbToastPortal.vue.js +5 -0
  625. package/dist/components/BbToast/BbToastPortal.vue_vue_type_script_setup_true_lang.js +19 -0
  626. package/dist/components/BbToast/BbToastRegion.vue.d.ts +8 -0
  627. package/dist/components/BbToast/BbToastRegion.vue.js +5 -0
  628. package/dist/components/BbToast/BbToastRegion.vue_vue_type_script_setup_true_lang.js +100 -0
  629. package/dist/components/BbToast/types.d.ts +69 -5
  630. package/dist/components/BbTooltip/BbTooltip.vue.d.ts +4 -3
  631. package/dist/components/BbTooltip/BbTooltip.vue.js +6 -0
  632. package/dist/components/BbTooltip/BbTooltip.vue_vue_type_script_setup_true_lang.js +160 -0
  633. package/dist/components/BbTooltip/types.d.ts +61 -11
  634. package/dist/components/BbTree/BbTree.vue.d.ts +26 -13
  635. package/dist/components/BbTree/BbTree.vue.js +6 -0
  636. package/dist/components/BbTree/BbTree.vue_vue_type_script_setup_true_lang.js +55 -0
  637. package/dist/components/BbTree/BbTreeLevel.vue.d.ts +19 -0
  638. package/dist/components/BbTree/BbTreeLevel.vue.js +5 -0
  639. package/dist/components/BbTree/BbTreeLevel.vue_vue_type_script_setup_true_lang.js +94 -0
  640. package/dist/components/BbTree/context.d.ts +17 -0
  641. package/dist/components/BbTree/context.js +4 -0
  642. package/dist/components/BbTree/types.d.ts +93 -42
  643. package/dist/components/ChipsBox/ChipsBox.vue.d.ts +2 -1
  644. package/dist/components/ChipsBox/ChipsBox.vue.js +5 -0
  645. package/dist/components/ChipsBox/ChipsBox.vue_vue_type_script_setup_true_lang.js +98 -0
  646. package/dist/components/ChipsBox/types.d.ts +12 -5
  647. package/dist/components/ClearableButton/ClearableButton.vue.d.ts +2 -1
  648. package/dist/components/ClearableButton/ClearableButton.vue.js +6 -0
  649. package/dist/components/ClearableButton/ClearableButton.vue_vue_type_script_setup_true_lang.js +19 -0
  650. package/dist/components/ClearableButton/types.d.ts +7 -1
  651. package/dist/components/CloseIcon/CloseButton.vue.d.ts +5 -0
  652. package/dist/components/CloseIcon/CloseButton.vue.js +7 -0
  653. package/dist/components/CloseIcon/CloseButton.vue_vue_type_script_setup_true_lang.js +23 -0
  654. package/dist/components/CloseIcon/types.d.ts +2 -0
  655. package/dist/components/CommaBox/CommaBox.vue.d.ts +2 -1
  656. package/dist/components/CommaBox/CommaBox.vue.js +6 -0
  657. package/dist/components/CommaBox/CommaBox.vue_vue_type_script_setup_true_lang.js +81 -0
  658. package/dist/components/CommaBox/types.d.ts +6 -7
  659. package/dist/components/CommonInputWrapper/CommonInputWrapper.vue.d.ts +19 -0
  660. package/dist/components/CommonInputWrapper/CommonInputWrapper.vue.js +6 -0
  661. package/dist/components/CommonInputWrapper/CommonInputWrapper.vue_vue_type_script_setup_true_lang.js +107 -0
  662. package/dist/components/CommonInputWrapper/types.d.ts +96 -0
  663. package/dist/components/CommonPopover/CommonPopover.vue.d.ts +3 -3
  664. package/dist/components/CommonPopover/CommonPopover.vue.js +6 -0
  665. package/dist/components/CommonPopover/CommonPopover.vue_vue_type_script_setup_true_lang.js +160 -0
  666. package/dist/components/CommonPopover/types.d.ts +61 -16
  667. package/dist/components/ErrorIcon/ErrorIcon.vue.d.ts +2 -0
  668. package/dist/components/ErrorIcon/ErrorIcon.vue.js +6 -0
  669. package/dist/components/ErrorIcon/ErrorIcon.vue_vue_type_script_setup_true_lang.js +16 -0
  670. package/dist/components/FlatListBox/FlatListBox.vue.d.ts +2 -5
  671. package/dist/components/FlatListBox/FlatListBox.vue.js +5 -0
  672. package/dist/components/FlatListBox/FlatListBox.vue_vue_type_script_setup_true_lang.js +167 -0
  673. package/dist/components/FlatListBox/types.d.ts +1 -1
  674. package/dist/components/GroupedListBox/GroupedListBox.vue.d.ts +2 -5
  675. package/dist/components/GroupedListBox/GroupedListBox.vue.js +5 -0
  676. package/dist/components/GroupedListBox/GroupedListBox.vue_vue_type_script_setup_true_lang.js +218 -0
  677. package/dist/components/ListBox/ListBox.vue.d.ts +3 -6
  678. package/dist/components/ListBox/ListBox.vue.js +5 -0
  679. package/dist/components/ListBox/ListBox.vue_vue_type_script_setup_true_lang.js +112 -0
  680. package/dist/components/ListBox/types.d.ts +1 -1
  681. package/dist/components/OptionsContainer/OptionsContainer.vue.d.ts +1 -0
  682. package/dist/components/OptionsContainer/OptionsContainer.vue.js +5 -0
  683. package/dist/components/OptionsContainer/OptionsContainer.vue_vue_type_script_setup_true_lang.js +52 -0
  684. package/dist/components/OptionsContainer/types.d.ts +14 -24
  685. package/dist/components/Transitions/ScaleFade.vue.js +5 -0
  686. package/dist/components/Transitions/ScaleFade.vue_vue_type_script_setup_true_lang.js +47 -0
  687. package/dist/components/Transitions/Slide.vue.js +7 -0
  688. package/dist/components/Transitions/Slide.vue_vue_type_script_setup_true_lang.js +28 -0
  689. package/dist/components/WarningIcon/WarningIcon.vue.d.ts +5 -0
  690. package/dist/components/WarningIcon/WarningIcon.vue.js +6 -0
  691. package/dist/components/WarningIcon/WarningIcon.vue_vue_type_script_setup_true_lang.js +16 -0
  692. package/dist/components/WarningIcon/types.d.ts +3 -0
  693. package/dist/composables/__testResets.d.ts +1 -0
  694. package/dist/composables/useActiveInactiveState.d.ts +4 -0
  695. package/dist/composables/useActiveInactiveState.js +21 -0
  696. package/dist/composables/useBaseOptions.d.ts +3 -3
  697. package/dist/composables/useBaseOptions.js +31 -0
  698. package/dist/composables/useBbConfig.d.ts +8 -37
  699. package/dist/composables/useBbConfig.js +5 -0
  700. package/dist/composables/useBbDropdownContext.d.ts +89 -0
  701. package/dist/composables/useBbDropdownContext.js +46 -0
  702. package/dist/composables/useBbFormContext.d.ts +90 -0
  703. package/dist/composables/useBbFormContext.js +69 -0
  704. package/dist/composables/useBbTableContext.d.ts +195 -0
  705. package/dist/composables/useBbTableContext.js +208 -0
  706. package/dist/composables/useBbTabsContext.d.ts +111 -0
  707. package/dist/composables/useBbTabsContext.js +219 -0
  708. package/dist/composables/useBreakpoint.d.ts +13 -0
  709. package/dist/composables/useBreakpoint.js +39 -0
  710. package/dist/composables/useBroadcastChannelInstance.d.ts +1 -3
  711. package/dist/composables/useBroadcastChannelInstance.js +39 -0
  712. package/dist/composables/useCancelableFunction.js +37 -0
  713. package/dist/composables/useCoherence.js +16 -0
  714. package/dist/composables/useConfirm.d.ts +257 -67
  715. package/dist/composables/useConfirm.js +122 -0
  716. package/dist/composables/useCountdown.js +42 -0
  717. package/dist/composables/useHashedWatcher.d.ts +17 -0
  718. package/dist/composables/useHashedWatcher.js +14 -0
  719. package/dist/composables/useId.d.ts +3 -2
  720. package/dist/composables/useIndexById.js +16 -0
  721. package/dist/composables/useInertiaPage.d.ts +10 -0
  722. package/dist/composables/useInertiaPage.js +8 -0
  723. package/dist/composables/useItemText.js +17 -0
  724. package/dist/composables/useItemValue.js +9 -0
  725. package/dist/composables/useItemsGetter.d.ts +1 -1
  726. package/dist/composables/useItemsGetter.js +30 -0
  727. package/dist/composables/useListboxFocus.js +66 -0
  728. package/dist/composables/useLocale.d.ts +1 -1
  729. package/dist/composables/useLocale.js +11 -0
  730. package/dist/composables/useLogger.d.ts +1 -1
  731. package/dist/composables/useLogger.js +10 -0
  732. package/dist/composables/useMinimalQueue.d.ts +1 -1
  733. package/dist/composables/useMobile.js +7 -0
  734. package/dist/composables/useOnFalsy.d.ts +2 -0
  735. package/dist/composables/useOnFalsy.js +9 -0
  736. package/dist/composables/useOnTruthy.d.ts +7 -0
  737. package/dist/composables/useOnTruthy.js +9 -0
  738. package/dist/composables/usePrefill.d.ts +2 -1
  739. package/dist/composables/usePrefill.js +24 -0
  740. package/dist/composables/useQuery.d.ts +15 -3
  741. package/dist/composables/useQuery.js +42 -0
  742. package/dist/composables/useRoute.js +11 -0
  743. package/dist/composables/useRouter.js +8 -0
  744. package/dist/composables/useSafeArea.d.ts +51 -0
  745. package/dist/composables/useSafeArea.js +16 -0
  746. package/dist/composables/useSegmentedFields.d.ts +103 -0
  747. package/dist/composables/useSegmentedFields.js +152 -0
  748. package/dist/composables/useTableWidthContext.d.ts +5 -0
  749. package/dist/composables/useTableWidthContext.js +42 -0
  750. package/dist/composables/useToast.d.ts +17 -73
  751. package/dist/composables/useToast.js +49 -0
  752. package/dist/composables/useTopLayer.d.ts +9 -0
  753. package/dist/composables/useTopLayer.js +7 -0
  754. package/dist/composables/useUntil.js +13 -0
  755. package/dist/composables/useViewportWidth.d.ts +17 -0
  756. package/dist/composables/useViewportWidth.js +6 -0
  757. package/dist/confirm-variants.d.ts +10 -0
  758. package/dist/deprecation/ai-deprecations.json.d.ts +784 -0
  759. package/dist/deprecation/ai-deprecations.json.js +4 -0
  760. package/dist/deprecation/removedProps.d.ts +3 -0
  761. package/dist/deprecation/removedProps.js +13 -0
  762. package/dist/directives/bbColor.d.ts +65 -0
  763. package/dist/directives/bbColor.js +24 -0
  764. package/dist/directives/bbDate.d.ts +66 -0
  765. package/dist/directives/bbDate.js +24 -0
  766. package/dist/directives/bbDropdown.d.ts +15 -11
  767. package/dist/directives/bbDropdown.js +23 -0
  768. package/dist/directives/bbTime.d.ts +64 -0
  769. package/dist/directives/bbTime.js +24 -0
  770. package/dist/directives/bbTooltip.d.ts +16 -11
  771. package/dist/directives/bbTooltip.js +24 -0
  772. package/dist/dropdown-item-variants.d.ts +10 -0
  773. package/dist/i18n/index.d.ts +51 -3
  774. package/dist/i18n/index.js +27 -0
  775. package/dist/i18n/locales/cs.json +115 -0
  776. package/dist/i18n/locales/da.json +115 -0
  777. package/dist/i18n/locales/de.json +115 -0
  778. package/dist/i18n/locales/el.json +115 -0
  779. package/dist/i18n/locales/en.json +115 -0
  780. package/dist/i18n/locales/es.json +115 -0
  781. package/dist/i18n/locales/fi.json +115 -0
  782. package/dist/i18n/locales/fr.json +115 -0
  783. package/dist/i18n/locales/hu.json +115 -0
  784. package/dist/i18n/locales/it.json +115 -0
  785. package/dist/i18n/locales/ja.json +115 -0
  786. package/dist/i18n/locales/ko.json +115 -0
  787. package/dist/i18n/locales/nb.json +115 -0
  788. package/dist/i18n/locales/nl.json +115 -0
  789. package/dist/i18n/locales/pl.json +115 -0
  790. package/dist/i18n/locales/pt.json +115 -0
  791. package/dist/i18n/locales/ro.json +115 -0
  792. package/dist/i18n/locales/ru.json +115 -0
  793. package/dist/i18n/locales/sv.json +115 -0
  794. package/dist/i18n/locales/tr.json +115 -0
  795. package/dist/i18n/locales/uk.json +115 -0
  796. package/dist/i18n/locales/zh-cn.json +115 -0
  797. package/dist/icons-whitelist.d.ts +8 -0
  798. package/dist/index.d.ts +94 -79
  799. package/dist/index.js +76 -82
  800. package/dist/indicator-variants.d.ts +13 -0
  801. package/dist/llms-full.txt +77073 -0
  802. package/dist/llms-medium.txt +1334 -0
  803. package/dist/llms.txt +103 -0
  804. package/dist/locale-blueprint.json +141 -0
  805. package/dist/nuxt-module.d.ts +3 -0
  806. package/dist/nuxt.js +19 -0
  807. package/dist/plugin.d.ts +4 -0
  808. package/dist/plugin.js +22 -0
  809. package/dist/reset.css +1 -0
  810. package/dist/reset.d.ts +0 -0
  811. package/dist/runtime/nuxt-plugin.d.ts +2 -0
  812. package/dist/runtime/nuxt-plugin.js +24 -0
  813. package/dist/styles.css +2 -0
  814. package/dist/styles.d.ts +0 -0
  815. package/dist/toast-variants.d.ts +13 -0
  816. package/dist/tooltip-variants.d.ts +10 -0
  817. package/dist/types/ActionButton.d.ts +32 -0
  818. package/dist/types/AlertVariant.d.ts +16 -0
  819. package/dist/types/BadgeVariant.d.ts +16 -0
  820. package/dist/types/ButtonVariant.d.ts +17 -0
  821. package/dist/types/Classes.d.ts +1 -1
  822. package/dist/types/ColumnName.d.ts +1 -1
  823. package/dist/types/CommonProps.d.ts +66 -279
  824. package/dist/types/Config.d.ts +84 -0
  825. package/dist/types/ConfirmVariant.d.ts +15 -0
  826. package/dist/types/DropdownItemVariant.d.ts +18 -0
  827. package/dist/types/Icon.d.ts +5 -7
  828. package/dist/types/IndicatorVariant.d.ts +16 -0
  829. package/dist/types/InputDirection.d.ts +15 -0
  830. package/dist/types/ItemAccessor.d.ts +21 -0
  831. package/dist/types/Placement.d.ts +6 -0
  832. package/dist/types/ResponsiveSize.d.ts +20 -0
  833. package/dist/types/SizeScale.d.ts +8 -0
  834. package/dist/types/ToastVariant.d.ts +17 -0
  835. package/dist/types/TooltipVariant.d.ts +18 -0
  836. package/dist/utilities/functions/bytesToUnit.d.ts +2 -0
  837. package/dist/utilities/functions/bytesToUnit.js +18 -0
  838. package/dist/utilities/functions/clampPrecision.js +10 -0
  839. package/dist/utilities/functions/convertDateValue.d.ts +23 -10
  840. package/dist/utilities/functions/convertDateValue.js +12 -0
  841. package/dist/utilities/functions/deburr.js +5 -0
  842. package/dist/utilities/functions/empty.js +5 -0
  843. package/dist/utilities/functions/flattenTree.d.ts +1 -1
  844. package/dist/utilities/functions/hash.js +5 -0
  845. package/dist/utilities/functions/isDateDisabled.d.ts +1 -0
  846. package/dist/utilities/functions/isDateDisabled.js +20 -0
  847. package/dist/utilities/functions/isEqual.js +5 -0
  848. package/dist/utilities/functions/isNotEmpty.js +5 -0
  849. package/dist/utilities/functions/matchAnyKey.d.ts +1 -1
  850. package/dist/utilities/functions/matchAnyKey.js +15 -0
  851. package/dist/utilities/functions/parseSize.d.ts +1 -1
  852. package/dist/utilities/functions/parseSize.js +15 -0
  853. package/dist/utilities/functions/percentage.js +11 -0
  854. package/dist/utilities/functions/pipe.d.ts +1 -1
  855. package/dist/utilities/functions/reject.d.ts +25 -0
  856. package/dist/utilities/functions/reject.js +28 -0
  857. package/dist/utilities/functions/resolveEnumProp.d.ts +19 -0
  858. package/dist/utilities/functions/resolveEnumProp.js +5 -0
  859. package/dist/utilities/functions/slotKey.d.ts +13 -0
  860. package/dist/utilities/functions/slotKey.js +4 -0
  861. package/dist/utilities/functions/sort.d.ts +2 -2
  862. package/dist/utilities/functions/sort.js +19 -0
  863. package/dist/utilities/functions/throttle.js +5 -0
  864. package/dist/utilities/functions/waitFor.d.ts +9 -2
  865. package/dist/utilities/functions/waitFor.js +14 -0
  866. package/dist/utilities/functions/warnRemovedAttrs.d.ts +11 -0
  867. package/dist/utilities/functions/warnRemovedAttrs.js +20 -0
  868. package/dist/utilities/functions/when.js +5 -0
  869. package/dist/utilities/misc/iconsInjectionKey.d.ts +15 -0
  870. package/dist/utilities/misc/iconsInjectionKey.js +4 -0
  871. package/dist/utilities/misc/transitions.d.ts +5 -0
  872. package/dist/utilities/misc/transitions.js +8 -0
  873. package/dist/utils/injectLibraryStyles.d.ts +6 -0
  874. package/dist/utils/injectLibraryStyles.js +38 -0
  875. package/dist/validated/BbCheckbox.vue.d.ts +29 -0
  876. package/dist/validated/BbCheckbox.vue.js +5 -0
  877. package/dist/validated/BbCheckbox.vue_vue_type_script_setup_true_lang.js +75 -0
  878. package/dist/validated/BbCheckboxGroup.vue.d.ts +34 -0
  879. package/dist/validated/BbCheckboxGroup.vue.js +5 -0
  880. package/dist/validated/BbCheckboxGroup.vue_vue_type_script_setup_true_lang.js +76 -0
  881. package/dist/validated/BbColorInput.vue.d.ts +36 -0
  882. package/dist/validated/BbColorInput.vue.js +5 -0
  883. package/dist/validated/BbColorInput.vue_vue_type_script_setup_true_lang.js +71 -0
  884. package/dist/validated/BbDatePickerInput.vue.d.ts +40 -0
  885. package/dist/validated/BbDatePickerInput.vue.js +5 -0
  886. package/dist/validated/BbDatePickerInput.vue_vue_type_script_setup_true_lang.js +87 -0
  887. package/dist/validated/BbDropzone.vue.d.ts +24 -0
  888. package/dist/validated/BbDropzone.vue.js +5 -0
  889. package/dist/validated/BbDropzone.vue_vue_type_script_setup_true_lang.js +45 -0
  890. package/dist/validated/BbForm.vue.d.ts +28 -0
  891. package/dist/validated/BbForm.vue.js +5 -0
  892. package/dist/validated/BbForm.vue_vue_type_script_setup_true_lang.js +42 -0
  893. package/dist/validated/BbNumberInput.vue.d.ts +36 -0
  894. package/dist/validated/BbNumberInput.vue.js +5 -0
  895. package/dist/validated/BbNumberInput.vue_vue_type_script_setup_true_lang.js +72 -0
  896. package/dist/validated/BbRadioGroup.vue.d.ts +34 -0
  897. package/dist/validated/BbRadioGroup.vue.js +5 -0
  898. package/dist/validated/BbRadioGroup.vue_vue_type_script_setup_true_lang.js +75 -0
  899. package/dist/validated/BbRating.vue.d.ts +30 -0
  900. package/dist/validated/BbRating.vue.js +5 -0
  901. package/dist/validated/BbRating.vue_vue_type_script_setup_true_lang.js +63 -0
  902. package/dist/validated/BbSelect.vue.d.ts +46 -0
  903. package/dist/validated/BbSelect.vue.js +5 -0
  904. package/dist/validated/BbSelect.vue_vue_type_script_setup_true_lang.js +100 -0
  905. package/dist/validated/BbSlider.vue.d.ts +36 -0
  906. package/dist/validated/BbSlider.vue.js +5 -0
  907. package/dist/validated/BbSlider.vue_vue_type_script_setup_true_lang.js +69 -0
  908. package/dist/validated/BbSwitch.vue.d.ts +29 -0
  909. package/dist/validated/BbSwitch.vue.js +5 -0
  910. package/dist/validated/BbSwitch.vue_vue_type_script_setup_true_lang.js +75 -0
  911. package/dist/validated/BbSwitchGroup.vue.d.ts +34 -0
  912. package/dist/validated/BbSwitchGroup.vue.js +5 -0
  913. package/dist/validated/BbSwitchGroup.vue_vue_type_script_setup_true_lang.js +76 -0
  914. package/dist/validated/BbTag.vue.d.ts +36 -0
  915. package/dist/validated/BbTag.vue.js +5 -0
  916. package/dist/validated/BbTag.vue_vue_type_script_setup_true_lang.js +72 -0
  917. package/dist/validated/BbTextInput.vue.d.ts +36 -0
  918. package/dist/validated/BbTextInput.vue.js +5 -0
  919. package/dist/validated/BbTextInput.vue_vue_type_script_setup_true_lang.js +72 -0
  920. package/dist/validated/BbTextarea.vue.d.ts +36 -0
  921. package/dist/validated/BbTextarea.vue.js +5 -0
  922. package/dist/validated/BbTextarea.vue_vue_type_script_setup_true_lang.js +70 -0
  923. package/dist/validated/BbTimePickerInput.vue.d.ts +36 -0
  924. package/dist/validated/BbTimePickerInput.vue.js +5 -0
  925. package/dist/validated/BbTimePickerInput.vue_vue_type_script_setup_true_lang.js +78 -0
  926. package/dist/validated/index.d.ts +29 -0
  927. package/dist/validated/useValidatedField.d.ts +52 -0
  928. package/dist/validated/useValidatedField.js +51 -0
  929. package/dist/validated.js +21 -0
  930. package/dist/vite-plugin.d.ts +217 -0
  931. package/dist/vite.js +530 -0
  932. package/llms.txt +105 -0
  933. package/package.json +161 -59
  934. package/scripts/lib/__fixtures__/validated-manifest.json +65 -0
  935. package/scripts/lib/ensure-manifest.mjs +39 -0
  936. package/scripts/lib/eslint-plugin-autofix.node.test.mjs +109 -0
  937. package/scripts/lib/eslint-plugin.mjs +285 -0
  938. package/scripts/lib/eslint-plugin.node.test.mjs +161 -0
  939. package/scripts/lib/html-attributes.mjs +191 -0
  940. package/scripts/lib/mcp-config.mjs +126 -0
  941. package/scripts/lib/migrate-fix.mjs +115 -0
  942. package/scripts/lib/validate-bb-markup.mjs +421 -0
  943. package/dist/ai/BaseButton.md +0 -449
  944. package/dist/ai/BaseCheckbox.md +0 -512
  945. package/dist/ai/BaseCheckboxGroup.md +0 -597
  946. package/dist/ai/BaseColorInput.md +0 -461
  947. package/dist/ai/BaseDatePicker.md +0 -739
  948. package/dist/ai/BaseDatePickerInput.md +0 -1517
  949. package/dist/ai/BaseDialog.md +0 -610
  950. package/dist/ai/BaseInputContainer.md +0 -570
  951. package/dist/ai/BaseNumberInput.md +0 -509
  952. package/dist/ai/BaseRadio.md +0 -405
  953. package/dist/ai/BaseRadioGroup.md +0 -535
  954. package/dist/ai/BaseRating.md +0 -489
  955. package/dist/ai/BaseSelect.md +0 -1742
  956. package/dist/ai/BaseSlider.md +0 -871
  957. package/dist/ai/BaseSwitch.md +0 -322
  958. package/dist/ai/BaseSwitchGroup.md +0 -298
  959. package/dist/ai/BaseTag.md +0 -623
  960. package/dist/ai/BaseTextInput.md +0 -392
  961. package/dist/ai/BaseTextarea.md +0 -398
  962. package/dist/ai/BbChip.md +0 -147
  963. package/dist/ai/BbIntersection.md +0 -120
  964. package/dist/ai/BbRatio.md +0 -61
  965. package/dist/ai/BbRows.md +0 -307
  966. package/dist/ai/BbTab.md +0 -950
  967. package/dist/ai/CommonInputInnerContainer.md +0 -414
  968. package/dist/ai/CommonInputOuterContainer.md +0 -55
  969. package/dist/components/BaseButton/BaseButton.vue.d.ts +0 -14
  970. package/dist/components/BaseButton/types.d.ts +0 -159
  971. package/dist/components/BaseCheckbox/BaseCheckbox.vue.d.ts +0 -39
  972. package/dist/components/BaseCheckbox/types.d.ts +0 -213
  973. package/dist/components/BaseCheckboxGroup/BaseCheckboxGroup.vue.d.ts +0 -30
  974. package/dist/components/BaseCheckboxGroup/types.d.ts +0 -282
  975. package/dist/components/BaseColorInput/BaseColorInput.vue.d.ts +0 -35
  976. package/dist/components/BaseColorInput/ColorPalette.vue.d.ts +0 -13
  977. package/dist/components/BaseColorInput/types.d.ts +0 -233
  978. package/dist/components/BaseDatePicker/BaseDatePickerHeader.vue.d.ts +0 -15
  979. package/dist/components/BaseDatePicker/BaseDatePickerInputDaySelector.vue.d.ts +0 -58
  980. package/dist/components/BaseDatePicker/BaseDatePickerMonthSelector.vue.d.ts +0 -12
  981. package/dist/components/BaseDatePicker/BaseDatePickerYearSelector.vue.d.ts +0 -12
  982. package/dist/components/BaseDatePicker/types.d.ts +0 -100
  983. package/dist/components/BaseDatePickerInput/BaseDatePickerInput.vue.d.ts +0 -26
  984. package/dist/components/BaseDatePickerInput/types.d.ts +0 -206
  985. package/dist/components/BaseDialog/BaseDialog.vue.d.ts +0 -37
  986. package/dist/components/BaseDialog/types.d.ts +0 -180
  987. package/dist/components/BaseInputContainer/BaseInputContainer.vue.d.ts +0 -18
  988. package/dist/components/BaseInputContainer/types.d.ts +0 -126
  989. package/dist/components/BaseNumberInput/BaseNumberInput.vue.d.ts +0 -46
  990. package/dist/components/BaseNumberInput/types.d.ts +0 -191
  991. package/dist/components/BaseRadio/BaseRadio.vue.d.ts +0 -31
  992. package/dist/components/BaseRadio/types.d.ts +0 -173
  993. package/dist/components/BaseRadioGroup/BaseRadioGroup.vue.d.ts +0 -30
  994. package/dist/components/BaseRadioGroup/types.d.ts +0 -240
  995. package/dist/components/BaseRating/BaseRating.vue.d.ts +0 -35
  996. package/dist/components/BaseRating/types.d.ts +0 -144
  997. package/dist/components/BaseSelect/BaseSelect.vue.d.ts +0 -28
  998. package/dist/components/BaseSelect/types.d.ts +0 -470
  999. package/dist/components/BaseSlider/BaseSlider.vue.d.ts +0 -38
  1000. package/dist/components/BaseSlider/types.d.ts +0 -201
  1001. package/dist/components/BaseSwitch/BaseSwitch.vue.d.ts +0 -34
  1002. package/dist/components/BaseSwitch/types.d.ts +0 -25
  1003. package/dist/components/BaseSwitchGroup/BaseSwitchGroup.vue.d.ts +0 -30
  1004. package/dist/components/BaseSwitchGroup/types.d.ts +0 -8
  1005. package/dist/components/BaseTag/BaseTag.vue.d.ts +0 -37
  1006. package/dist/components/BaseTag/types.d.ts +0 -136
  1007. package/dist/components/BaseTextInput/BaseTextInput.vue.d.ts +0 -33
  1008. package/dist/components/BaseTextInput/types.d.ts +0 -166
  1009. package/dist/components/BaseTextarea/BaseTextarea.vue.d.ts +0 -31
  1010. package/dist/components/BaseTextarea/types.d.ts +0 -151
  1011. package/dist/components/BbChip/BbChip.vue.d.ts +0 -17
  1012. package/dist/components/BbChip/types.d.ts +0 -23
  1013. package/dist/components/BbIntersection/BbIntersection.vue.d.ts +0 -23
  1014. package/dist/components/BbIntersection/types.d.ts +0 -36
  1015. package/dist/components/BbRatio/BbRatio.vue.d.ts +0 -14
  1016. package/dist/components/BbRatio/types.d.ts +0 -15
  1017. package/dist/components/BbRows/BbRows.vue.d.ts +0 -62
  1018. package/dist/components/BbRows/types.d.ts +0 -21
  1019. package/dist/components/BbTab/BbTab.vue.d.ts +0 -27
  1020. package/dist/components/BbTab/types.d.ts +0 -186
  1021. package/dist/components/CommonInputInnerContainer/CommonInputInnerContainer.vue.d.ts +0 -15
  1022. package/dist/components/CommonInputInnerContainer/types.d.ts +0 -47
  1023. package/dist/components/CommonInputOuterContainer/CommonInputOuterContainer.vue.d.ts +0 -11
  1024. package/dist/components/CommonInputOuterContainer/types.d.ts +0 -16
  1025. package/dist/composables/useModalsState.d.ts +0 -5
  1026. package/dist/composables/useQueue.d.ts +0 -58
  1027. package/dist/composables/useWizard.d.ts +0 -85
  1028. package/dist/i18n/en.d.ts +0 -67
  1029. package/dist/i18n/it.d.ts +0 -67
  1030. package/dist/index.css +0 -2
  1031. package/dist/index100.js +0 -6
  1032. package/dist/index101.js +0 -300
  1033. package/dist/index102.js +0 -16
  1034. package/dist/index103.js +0 -16
  1035. package/dist/index104.js +0 -27
  1036. package/dist/index109.js +0 -19
  1037. package/dist/index11.js +0 -42
  1038. package/dist/index110.js +0 -12
  1039. package/dist/index111.js +0 -19
  1040. package/dist/index112.js +0 -25
  1041. package/dist/index114.js +0 -7
  1042. package/dist/index115.js +0 -241
  1043. package/dist/index116.js +0 -5
  1044. package/dist/index117.js +0 -42
  1045. package/dist/index118.js +0 -5
  1046. package/dist/index119.js +0 -53
  1047. package/dist/index120.js +0 -5
  1048. package/dist/index121.js +0 -32
  1049. package/dist/index122.js +0 -5
  1050. package/dist/index124.js +0 -52
  1051. package/dist/index125.js +0 -5
  1052. package/dist/index126.js +0 -223
  1053. package/dist/index128.js +0 -6
  1054. package/dist/index129.js +0 -162
  1055. package/dist/index13.js +0 -92
  1056. package/dist/index130.js +0 -25
  1057. package/dist/index131.js +0 -51
  1058. package/dist/index132.js +0 -5
  1059. package/dist/index133.js +0 -607
  1060. package/dist/index135.js +0 -6
  1061. package/dist/index136.js +0 -14
  1062. package/dist/index137.js +0 -153
  1063. package/dist/index139.js +0 -6
  1064. package/dist/index14.js +0 -306
  1065. package/dist/index140.js +0 -224
  1066. package/dist/index141.js +0 -5
  1067. package/dist/index143.js +0 -128
  1068. package/dist/index145.js +0 -6
  1069. package/dist/index146.js +0 -8
  1070. package/dist/index147.js +0 -182
  1071. package/dist/index149.js +0 -6
  1072. package/dist/index15.js +0 -10
  1073. package/dist/index151.js +0 -4
  1074. package/dist/index152.js +0 -95
  1075. package/dist/index154.js +0 -6
  1076. package/dist/index155.js +0 -168
  1077. package/dist/index157.js +0 -6
  1078. package/dist/index158.js +0 -145
  1079. package/dist/index16.js +0 -59
  1080. package/dist/index160.js +0 -6
  1081. package/dist/index161.js +0 -53
  1082. package/dist/index163.js +0 -6
  1083. package/dist/index164.js +0 -16
  1084. package/dist/index166.js +0 -35
  1085. package/dist/index168.js +0 -6
  1086. package/dist/index169.js +0 -89
  1087. package/dist/index171.js +0 -6
  1088. package/dist/index172.js +0 -82
  1089. package/dist/index174.js +0 -6
  1090. package/dist/index175.js +0 -38
  1091. package/dist/index176.js +0 -461
  1092. package/dist/index177.js +0 -28
  1093. package/dist/index178.js +0 -66
  1094. package/dist/index18.js +0 -35
  1095. package/dist/index180.js +0 -162
  1096. package/dist/index181.js +0 -5
  1097. package/dist/index182.js +0 -217
  1098. package/dist/index183.js +0 -5
  1099. package/dist/index184.js +0 -112
  1100. package/dist/index185.js +0 -5
  1101. package/dist/index186.js +0 -459
  1102. package/dist/index188.js +0 -6
  1103. package/dist/index19.js +0 -4
  1104. package/dist/index192.js +0 -268
  1105. package/dist/index194.js +0 -6
  1106. package/dist/index195.js +0 -124
  1107. package/dist/index197.js +0 -6
  1108. package/dist/index198.js +0 -174
  1109. package/dist/index2.js +0 -20
  1110. package/dist/index20.js +0 -9
  1111. package/dist/index200.js +0 -6
  1112. package/dist/index201.js +0 -224
  1113. package/dist/index203.js +0 -6
  1114. package/dist/index204.js +0 -135
  1115. package/dist/index206.js +0 -6
  1116. package/dist/index207.js +0 -5
  1117. package/dist/index208.js +0 -170
  1118. package/dist/index21.js +0 -35
  1119. package/dist/index210.js +0 -6
  1120. package/dist/index211.js +0 -37
  1121. package/dist/index213.js +0 -6
  1122. package/dist/index214.js +0 -63
  1123. package/dist/index216.js +0 -6
  1124. package/dist/index217.js +0 -74
  1125. package/dist/index219.js +0 -6
  1126. package/dist/index22.js +0 -6
  1127. package/dist/index220.js +0 -65
  1128. package/dist/index222.js +0 -6
  1129. package/dist/index223.js +0 -67
  1130. package/dist/index225.js +0 -6
  1131. package/dist/index226.js +0 -41
  1132. package/dist/index228.js +0 -6
  1133. package/dist/index229.js +0 -10
  1134. package/dist/index23.js +0 -7
  1135. package/dist/index230.js +0 -22
  1136. package/dist/index232.js +0 -8
  1137. package/dist/index233.js +0 -297
  1138. package/dist/index235.js +0 -6
  1139. package/dist/index236.js +0 -47
  1140. package/dist/index237.js +0 -165
  1141. package/dist/index239.js +0 -6
  1142. package/dist/index24.js +0 -9
  1143. package/dist/index241.js +0 -159
  1144. package/dist/index243.js +0 -6
  1145. package/dist/index244.js +0 -134
  1146. package/dist/index246.js +0 -6
  1147. package/dist/index247.js +0 -167
  1148. package/dist/index249.js +0 -6
  1149. package/dist/index25.js +0 -24
  1150. package/dist/index250.js +0 -147
  1151. package/dist/index252.js +0 -6
  1152. package/dist/index253.js +0 -35
  1153. package/dist/index255.js +0 -6
  1154. package/dist/index256.js +0 -65
  1155. package/dist/index258.js +0 -6
  1156. package/dist/index259.js +0 -19
  1157. package/dist/index260.js +0 -5
  1158. package/dist/index261.js +0 -160
  1159. package/dist/index263.js +0 -6
  1160. package/dist/index264.js +0 -60
  1161. package/dist/index266.js +0 -6
  1162. package/dist/index267.js +0 -134
  1163. package/dist/index269.js +0 -6
  1164. package/dist/index27.js +0 -4
  1165. package/dist/index271.js +0 -206
  1166. package/dist/index273.js +0 -6
  1167. package/dist/index274.js +0 -85
  1168. package/dist/index275.js +0 -5
  1169. package/dist/index276.js +0 -55
  1170. package/dist/index277.js +0 -5
  1171. package/dist/index278.js +0 -164
  1172. package/dist/index28.js +0 -8
  1173. package/dist/index280.js +0 -6
  1174. package/dist/index281.js +0 -145
  1175. package/dist/index283.js +0 -6
  1176. package/dist/index284.js +0 -11
  1177. package/dist/index285.js +0 -200
  1178. package/dist/index287.js +0 -6
  1179. package/dist/index288.js +0 -241
  1180. package/dist/index29.js +0 -7
  1181. package/dist/index290.js +0 -6
  1182. package/dist/index291.js +0 -21
  1183. package/dist/index293.js +0 -6
  1184. package/dist/index294.js +0 -125
  1185. package/dist/index296.js +0 -6
  1186. package/dist/index297.js +0 -161
  1187. package/dist/index299.js +0 -6
  1188. package/dist/index30.js +0 -118
  1189. package/dist/index300.js +0 -127
  1190. package/dist/index302.js +0 -6
  1191. package/dist/index303.js +0 -20
  1192. package/dist/index305.js +0 -6
  1193. package/dist/index306.js +0 -116
  1194. package/dist/index307.js +0 -5
  1195. package/dist/index308.js +0 -507
  1196. package/dist/index31.js +0 -10
  1197. package/dist/index310.js +0 -6
  1198. package/dist/index311.js +0 -196
  1199. package/dist/index313.js +0 -6
  1200. package/dist/index314.js +0 -142
  1201. package/dist/index316.js +0 -6
  1202. package/dist/index317.js +0 -134
  1203. package/dist/index319.js +0 -6
  1204. package/dist/index32.js +0 -28
  1205. package/dist/index320.js +0 -162
  1206. package/dist/index322.js +0 -6
  1207. package/dist/index323.js +0 -319
  1208. package/dist/index325.js +0 -6
  1209. package/dist/index326.js +0 -40
  1210. package/dist/index327.js +0 -43
  1211. package/dist/index328.js +0 -665
  1212. package/dist/index33.js +0 -5
  1213. package/dist/index330.js +0 -6
  1214. package/dist/index331.js +0 -155
  1215. package/dist/index333.js +0 -6
  1216. package/dist/index334.js +0 -142
  1217. package/dist/index336.js +0 -6
  1218. package/dist/index337.js +0 -155
  1219. package/dist/index339.js +0 -6
  1220. package/dist/index34.js +0 -112
  1221. package/dist/index340.js +0 -58
  1222. package/dist/index341.js +0 -5
  1223. package/dist/index342.js +0 -20
  1224. package/dist/index344.js +0 -6
  1225. package/dist/index345.js +0 -142
  1226. package/dist/index347.js +0 -6
  1227. package/dist/index349.js +0 -109
  1228. package/dist/index351.js +0 -6
  1229. package/dist/index353.js +0 -24
  1230. package/dist/index354.js +0 -23
  1231. package/dist/index355.js +0 -839
  1232. package/dist/index356.js +0 -474
  1233. package/dist/index357.js +0 -52
  1234. package/dist/index358.js +0 -7
  1235. package/dist/index36.js +0 -6
  1236. package/dist/index38.js +0 -63
  1237. package/dist/index39.js +0 -63
  1238. package/dist/index40.js +0 -9
  1239. package/dist/index42.js +0 -8
  1240. package/dist/index43.js +0 -179
  1241. package/dist/index44.js +0 -21
  1242. package/dist/index46.js +0 -385
  1243. package/dist/index48.js +0 -6
  1244. package/dist/index49.js +0 -33
  1245. package/dist/index5.js +0 -34
  1246. package/dist/index50.js +0 -12
  1247. package/dist/index51.js +0 -8
  1248. package/dist/index52.js +0 -106
  1249. package/dist/index53.js +0 -330
  1250. package/dist/index54.js +0 -97
  1251. package/dist/index55.js +0 -328
  1252. package/dist/index56.js +0 -28
  1253. package/dist/index57.js +0 -102
  1254. package/dist/index58.js +0 -157
  1255. package/dist/index6.js +0 -38
  1256. package/dist/index60.js +0 -6
  1257. package/dist/index61.js +0 -131
  1258. package/dist/index62.js +0 -5
  1259. package/dist/index65.js +0 -35
  1260. package/dist/index66.js +0 -26
  1261. package/dist/index68.js +0 -6
  1262. package/dist/index69.js +0 -54
  1263. package/dist/index7.js +0 -58
  1264. package/dist/index71.js +0 -6
  1265. package/dist/index72.js +0 -14
  1266. package/dist/index74.js +0 -6
  1267. package/dist/index75.js +0 -159
  1268. package/dist/index77.js +0 -6
  1269. package/dist/index78.js +0 -4
  1270. package/dist/index79.js +0 -4
  1271. package/dist/index80.js +0 -54
  1272. package/dist/index81.js +0 -5
  1273. package/dist/index82.js +0 -5
  1274. package/dist/index83.js +0 -141
  1275. package/dist/index85.js +0 -6
  1276. package/dist/index86.js +0 -65
  1277. package/dist/index88.js +0 -6
  1278. package/dist/index89.js +0 -30
  1279. package/dist/index9.js +0 -11
  1280. package/dist/index90.js +0 -19
  1281. package/dist/index91.js +0 -17
  1282. package/dist/index92.js +0 -9
  1283. package/dist/index93.js +0 -34
  1284. package/dist/index95.js +0 -16
  1285. package/dist/index96.js +0 -10
  1286. package/dist/index97.js +0 -18
  1287. package/dist/index98.js +0 -189
  1288. package/dist/types/VoidHtmlElements.d.ts +0 -1
  1289. package/dist/utilities/functions/add.d.ts +0 -1
  1290. package/dist/utilities/functions/booleanishToBoolean.d.ts +0 -6
  1291. package/dist/utilities/functions/capitalize.d.ts +0 -4
  1292. package/dist/utilities/functions/cloneDeep.d.ts +0 -1
  1293. package/dist/utilities/functions/debounce.d.ts +0 -1
  1294. package/dist/utilities/functions/drop.d.ts +0 -1
  1295. package/dist/utilities/functions/exceedsPrecision.d.ts +0 -1
  1296. package/dist/utilities/functions/findRight.d.ts +0 -4
  1297. package/dist/utilities/functions/findRightIndex.d.ts +0 -4
  1298. package/dist/utilities/functions/flow.d.ts +0 -1
  1299. package/dist/utilities/functions/getHueFromRGB.d.ts +0 -9
  1300. package/dist/utilities/functions/groupBy.d.ts +0 -6
  1301. package/dist/utilities/functions/gt.d.ts +0 -7
  1302. package/dist/utilities/functions/hexToRGB.d.ts +0 -7
  1303. package/dist/utilities/functions/hslToHex.d.ts +0 -1
  1304. package/dist/utilities/functions/includes.d.ts +0 -1
  1305. package/dist/utilities/functions/initial.d.ts +0 -1
  1306. package/dist/utilities/functions/isCssColor.d.ts +0 -5
  1307. package/dist/utilities/functions/lt.d.ts +0 -7
  1308. package/dist/utilities/functions/makeUrl.d.ts +0 -1
  1309. package/dist/utilities/functions/mapKeys.d.ts +0 -5
  1310. package/dist/utilities/functions/mapValues.d.ts +0 -1
  1311. package/dist/utilities/functions/matchesPropertyInsensitive.d.ts +0 -1
  1312. package/dist/utilities/functions/max.d.ts +0 -2
  1313. package/dist/utilities/functions/mean.d.ts +0 -4
  1314. package/dist/utilities/functions/merge.d.ts +0 -11
  1315. package/dist/utilities/functions/millisecondsTo.d.ts +0 -1
  1316. package/dist/utilities/functions/negate.d.ts +0 -4
  1317. package/dist/utilities/functions/normalizeItemGroups.d.ts +0 -13
  1318. package/dist/utilities/functions/omit.d.ts +0 -2
  1319. package/dist/utilities/functions/overEvery.d.ts +0 -4
  1320. package/dist/utilities/functions/pick.d.ts +0 -1
  1321. package/dist/utilities/functions/replace.d.ts +0 -1
  1322. package/dist/utilities/functions/replaceInTree.d.ts +0 -4
  1323. package/dist/utilities/functions/retry.d.ts +0 -5
  1324. package/dist/utilities/functions/roundToTheNearest.d.ts +0 -8
  1325. package/dist/utilities/functions/set.d.ts +0 -15
  1326. package/dist/utilities/functions/stub.d.ts +0 -6
  1327. package/dist/utilities/functions/transposePercent.d.ts +0 -9
  1328. package/dist/utilities/functions/tryTo.d.ts +0 -2
  1329. package/dist/utilities/functions/uniqBy.d.ts +0 -1
  1330. /package/dist/{index64.js → _virtual/_plugin-vue_export-helper.js} +0 -0
  1331. /package/dist/components/{BaseButton → BbBaseButton}/RouterComponent.vue.d.ts +0 -0
  1332. /package/dist/components/{BaseDatePicker/BaseDatePicker.vue.d.ts → BbBaseDatePicker/BbBaseDatePicker.vue.d.ts} +0 -0
  1333. /package/dist/{index165.js → composables/useArray.js} +0 -0
  1334. /package/dist/{index17.js → composables/useFrameworkDetection.js} +0 -0
  1335. /package/dist/{index12.js → composables/useId.js} +0 -0
  1336. /package/dist/{index352.js → directives/createPopoverDirective.js} +0 -0
  1337. /package/dist/{index107.js → utilities/functions/chunk.js} +0 -0
  1338. /package/dist/{index8.js → utilities/functions/clamp.js} +0 -0
  1339. /package/dist/{index150.js → utilities/functions/curry.js} +0 -0
  1340. /package/dist/{index45.js → utilities/functions/extractDomContainer.js} +0 -0
  1341. /package/dist/{index270.js → utilities/functions/findInTree.js} +0 -0
  1342. /package/dist/{index348.js → utilities/functions/flattenTree.js} +0 -0
  1343. /package/dist/{index41.js → utilities/functions/get.js} +0 -0
  1344. /package/dist/{index189.js → utilities/functions/head.js} +0 -0
  1345. /package/dist/{index108.js → utilities/functions/identity.js} +0 -0
  1346. /package/dist/{index179.js → utilities/functions/indexBy.js} +0 -0
  1347. /package/dist/{index37.js → utilities/functions/isHex.js} +0 -0
  1348. /package/dist/{index94.js → utilities/functions/isNil.js} +0 -0
  1349. /package/dist/{index26.js → utilities/functions/isNotNil.js} +0 -0
  1350. /package/dist/{index105.js → utilities/functions/last.js} +0 -0
  1351. /package/dist/{index142.js → utilities/functions/noop.js} +0 -0
  1352. /package/dist/{index231.js → utilities/functions/parseWidthString.js} +0 -0
  1353. /package/dist/{index240.js → utilities/functions/pickBy.js} +0 -0
  1354. /package/dist/{index123.js → utilities/functions/range.js} +0 -0
  1355. /package/dist/{index190.js → utilities/functions/snapToStep.js} +0 -0
  1356. /package/dist/{index191.js → utilities/functions/transpose.js} +0 -0
  1357. /package/dist/{index106.js → utilities/functions/validateDateFormat.js} +0 -0
  1358. /package/dist/{index10.js → utilities/functions/wait.js} +0 -0
@@ -0,0 +1,1806 @@
1
+ ---
2
+ title: Upload Center (Vue)
3
+ summary: Full-anatomy expense-receipts upload center for a vue-router SPA — multi-file dropzone into an inline-editable table (text, category popover, amount, date cells), per-file progress with inline retry, submit-all with count, bulk bottom panel, and a stacked receipt/merchant peek sidebar, all through one coopting page context.
4
+ ---
5
+
6
+ # Recipe: Upload Center (Vue)
7
+
8
+ An Expensify-grade expense receipts submission page for a **plain Vue SPA
9
+ with vue-router**, at full standard anatomy: a multi-file dropzone feeding
10
+ an inline-editable table, per-file upload progress with inline retry,
11
+ one-click category cells, bulk actions in the floating bottom panel, and a
12
+ stacked receipt/merchant peek sidebar.
13
+
14
+ Sibling recipes: [Nuxt](../nuxt/upload-center.md) ·
15
+ [Inertia](../inertia/upload-center.md).
16
+
17
+ ## Prerequisites
18
+
19
+ - `<BbConfirm />` and `<BbToast />` mounted once in the app root.
20
+ - [App Layout](../../guides/app-layout.md), [Page Shell](../../guides/page-shell.md)
21
+ and [Floating Bottom Panel](../../guides/floating-bottom-panel.md) copied
22
+ into `src/components/layout/` per their guides — every recipe page assumes
23
+ this chrome exists and renders inside it.
24
+ - A `useCategoriesStore()` Pinia store exposing the shared expense-category
25
+ catalog (Travel, Meals & entertainment, Lodging, Rideshare & transit,
26
+ Software & subscriptions, Office supplies, Fuel, Client entertainment).
27
+ - The registered `soft-*` badge variants (`soft-gray` / `soft-amber` /
28
+ `soft-green`) from the [Inline Edit Workspace](./inline-edit-workspace.md)
29
+ recipe — the receipt-status maps in `context.ts` use them
30
+ (design-language § Using color).
31
+
32
+ ## Key ideas
33
+
34
+ - **One coopting page context.** `provideUploadCenter()` joins the
35
+ page-shell stack and the table context once, coopts the shared category
36
+ catalog from `useCategoriesStore()`, owns the filters, the tab, and the
37
+ **upload queue**, and exposes complete actions. Every leaf calls
38
+ `useUploadCenter()` and nothing else.
39
+ - **Capture and transfer are two layers.** `BbDropzone` only validates and
40
+ hands over `File[]`; the context runs the uploads (AbortController +
41
+ progress callback per file) and the dropzone leaf immediately drains its
42
+ model into `ctx.enqueueFiles()`. The component never uploads — that is
43
+ its documented contract.
44
+ - **The drafts table lists two kinds of rows.** In-flight/failed uploads
45
+ (`kind: 'upload'`, local state) render above the server drafts
46
+ (`kind: 'receipt'`, fetched). Progress ticks mutate the live row objects
47
+ — no refetch per tick; only membership changes (enqueue, remove,
48
+ completion) bump `refreshKey`.
49
+ - **Every draft cell edits in place.** Merchant is a text cell committing
50
+ on blur/Enter (§6.3), category is a one-click badge popover (§6.1),
51
+ amount is a `$`-prefixed number cell, date commits on pick. Each cell
52
+ type is its own leaf with a single `receipt` prop; failed saves revert
53
+ via refetch and toast destructive.
54
+ - **Tabs are URL filters.** Drafts / Submitted / Reimbursed carry `href`
55
+ (`?tab=drafts`) and live counts from every fetch; the same table is the
56
+ pane, read-only outside Drafts.
57
+ - **Clicking the name of a thing peeks it.** Filename → receipt peek
58
+ (fresh stack) with preview placeholder, extracted OCR fields and
59
+ activity; the merchant name inside the peek → merchant peek **stacked**
60
+ with a back arrow, whose recent receipts drill back down.
61
+ - **Buttons are `md` by default**; `sm`/`xs` only in the table rows, the
62
+ filter pills, the peek footers and the bottom bar. One
63
+ `variant="primary"`: **Submit all** with its live count.
64
+
65
+ - **Spread the filters object into `dependencies`.** `BbTable` hash-compares
66
+ `dependencies`; it does not deep-watch them. Passing the reactive `filters`
67
+ proxy itself tracks only its identity — which never changes — so the table
68
+ never refetches. `{ ...ctx.filters }` reads every field during render, so any
69
+ field change yields a new, differently-hashed array. Read `.value` off the
70
+ refs for the same reason: context members are not auto-unwrapped in a template.
71
+
72
+ ## Page anatomy
73
+
74
+ ```
75
+ UploadCenter/
76
+ Index.vue ← assembly: PageShell slots, dropzone, tabs, table, pagination
77
+ context.ts ← coopting page context (shell + table + categories + upload queue + actions)
78
+ ReceiptDropzone.vue ← multi-file capture, constraint errors mapped to messages
79
+ FilterRail.vue ← pill filters + clear-all
80
+ ReceiptFileCell.vue ← file icon + name (peek link) + size, both row kinds
81
+ UploadProgressCell.vue ← per-file BbProgress / failed state with inline retry
82
+ MerchantCell.vue ← inline text edit, commit on blur/Enter (§6.3)
83
+ CategoryCell.vue ← one-click badge → BbSelectPopover (§6.1)
84
+ AmountCell.vue ← inline number edit with $ prefix
85
+ DateCell.vue ← date picker cell, commit on pick
86
+ RowActions.vue ← remove-from-queue / per-receipt "…" dropdown
87
+ SelectionBar.vue ← bulk categorize + bulk remove in the floating bottom panel
88
+ ReceiptPeek.vue ← sidebar workbench, stack level 1
89
+ MerchantPeek.vue ← stacked peek, back arrow via the shell
90
+ ```
91
+
92
+ Chrome assumed from the guides: [App Layout](../../guides/app-layout.md)
93
+ (left nav + fat footer), [Page Shell](../../guides/page-shell.md),
94
+ [Floating Bottom Panel](../../guides/floating-bottom-panel.md).
95
+
96
+ ## Action inventory
97
+
98
+ | # | Action | Trigger | Mechanism |
99
+ | --- | --------------------------------- | ---------------------------------- | ----------------------------------------------------- |
100
+ | 1 | Upload receipts | dropzone (drag, click, Browse) | `enqueueFiles()` → per-file upload with progress |
101
+ | 2 | Retry a failed upload | inline in the progress cell | `retryUpload(id)` re-issues the request |
102
+ | 3 | Remove an in-flight upload | row actions (x) | `removeUpload(id)` aborts + drops the row |
103
+ | 4 | Page search | topbar right | `filters.search` → fetch dependency |
104
+ | 5 | Filter category / merchant / date | filter rail pills | `BbSelectPopover` multiple / query-aware / date range |
105
+ | 6 | Clear filters | rail right (only when active) | context `clearFilters()` |
106
+ | 7 | Switch tab | href tabs with counts | URL + fetch dependency |
107
+ | 8 | Edit merchant inline | merchant cell | commit on blur/Enter, Esc reverts (§6.3) |
108
+ | 9 | Change category one-click | category badge in row & peek | `BbSelectPopover` on the badge (§6.1) |
109
+ | 10 | Edit amount inline | amount cell ($ prefix) | commit on blur/Enter, Esc reverts |
110
+ | 11 | Edit expense date inline | date cell | commit on pick |
111
+ | 12 | Submit one receipt | row `…`, peek footer | `submitReceipt()` (API + refresh + toast) |
112
+ | 13 | Submit all with count | topbar, the page's one `primary` | `submitAll()` — count from every fetch |
113
+ | 14 | Remove a draft | row `…`, peek footer | destructive behind `useConfirm` |
114
+ | 15 | Bulk categorize | floating bottom panel popover | `bulkCategorize()` on `table.selected` |
115
+ | 16 | Bulk remove | floating bottom panel | destructive behind `useConfirm`, count in message |
116
+ | 17 | Select rows / select all | table checkboxes (drafts only) | table context, `selectable` predicate |
117
+ | 18 | Peek receipt | filename cell / merchant peek list | `peekReceipt(id)` → shell stack |
118
+ | 19 | Peek merchant (stacked) | merchant name inside the peek | `stackMerchant(name)` → back arrow |
119
+ | 20 | Download original | row `…`, peek footer | navigation (`/receipts/:id/file`) |
120
+
121
+ ## The code
122
+
123
+ ### context.ts
124
+
125
+ ```ts
126
+ // UploadCenter/context.ts
127
+ import {
128
+ computed,
129
+ inject,
130
+ provide,
131
+ reactive,
132
+ ref,
133
+ type ComputedRef,
134
+ type InjectionKey,
135
+ type Ref,
136
+ } from 'vue';
137
+ import {
138
+ useBbTableContext,
139
+ useConfirm,
140
+ useToast,
141
+ type BadgeVariantType,
142
+ type BbTableContext,
143
+ } from 'bitboss-ui';
144
+ import {
145
+ usePageShellContext,
146
+ type PageShellContext,
147
+ } from '@/components/layout/usePageShellContext';
148
+ import { useCategoriesStore } from '@/stores/categories';
149
+ import { api } from '@/api';
150
+ import type { Category, Receipt, ReceiptStatus } from '@/types';
151
+
152
+ /** What the stacked sidebar can show. Clicking a name pushes one of these. */
153
+ export type PeekItem =
154
+ | { type: 'receipt'; id: string }
155
+ | { type: 'merchant'; name: string };
156
+
157
+ export type UploadCenterTab = 'drafts' | 'submitted' | 'reimbursed';
158
+
159
+ export interface ReceiptFilters {
160
+ search: string;
161
+ categoryIds: string[];
162
+ merchant: string | null;
163
+ /**
164
+ * `[start, end]` as `YYYY-MM-DD`, or `[]` when unset. Range mode requires an
165
+ * array modelValue -- binding `null` throws, so the empty filter is `[]`.
166
+ */
167
+ spentBetween: string[];
168
+ }
169
+
170
+ /** A dropped file whose transfer is still in flight (or failed). Local-only. */
171
+ export type UploadRow = {
172
+ /** Local id (`upload-…`) — never collides with server receipt ids. */
173
+ id: string;
174
+ kind: 'upload';
175
+ filename: string;
176
+ size: number;
177
+ /** 0–100. Mutated in place per progress tick — reactive, no refetch. */
178
+ progress: number;
179
+ failed: boolean;
180
+ };
181
+
182
+ /** A server receipt as the table renders it. */
183
+ export type ReceiptRow = Receipt & { kind: 'receipt' };
184
+
185
+ /** What the table actually lists on the Drafts tab: uploads first. */
186
+ export type UploadCenterRow = UploadRow | ReceiptRow;
187
+
188
+ /** The only fields the inline cells may change. */
189
+ export type ReceiptPatch = Partial<
190
+ Pick<Receipt, 'merchant' | 'categoryId' | 'amount' | 'date'>
191
+ >;
192
+
193
+ // -- Receipt-status badge maps: one closed set, mapped once for the whole page.
194
+ // The receipt lifecycle (table rows, the receipt peek header, the merchant
195
+ // peek's recent list) is a small closed set — the textbook case for the soft
196
+ // accents (design-language.md § Using color), registered via badge-variants.d.ts.
197
+ // draft = idle/neutral, submitted = pending approval, reimbursed = done.
198
+ export const STATUS_LABEL: Record<ReceiptStatus, string> = {
199
+ draft: 'Draft',
200
+ submitted: 'Submitted',
201
+ reimbursed: 'Reimbursed',
202
+ };
203
+ export const STATUS_VARIANT: Record<ReceiptStatus, BadgeVariantType> = {
204
+ draft: 'soft-gray',
205
+ submitted: 'soft-amber',
206
+ reimbursed: 'soft-green',
207
+ };
208
+
209
+ export interface UploadCenterContext {
210
+ // -- Coopted contexts ------------------------------------------------------
211
+ shell: PageShellContext<PeekItem>;
212
+ table: BbTableContext;
213
+ /** Shared expense-category catalog, coopted from the store. */
214
+ categories: ComputedRef<Category[]>;
215
+ // -- Page-owned state ------------------------------------------------------
216
+ filters: ReceiptFilters;
217
+ hasActiveFilters: ComputedRef<boolean>;
218
+ tab: Ref<UploadCenterTab>;
219
+ tabCounts: Ref<Record<UploadCenterTab, number>>;
220
+ /** Drafts that are complete (merchant + category + amount + date). */
221
+ readyCount: Ref<number>;
222
+ /** The live upload queue — in-flight and failed transfers. */
223
+ uploads: Ref<UploadRow[]>;
224
+ refreshKey: Ref<number>;
225
+ // -- Data ------------------------------------------------------------------
226
+ fetchRows: () => Promise<UploadCenterRow[]>;
227
+ searchMerchants: (query: string) => Promise<string[]>;
228
+ // -- Peek grammar ----------------------------------------------------------
229
+ peekReceipt: (id: string) => void;
230
+ stackReceipt: (id: string) => void;
231
+ stackMerchant: (name: string) => void;
232
+ // -- Actions (complete: API + refresh + toast) ------------------------------
233
+ clearFilters: () => void;
234
+ enqueueFiles: (files: File[]) => void;
235
+ retryUpload: (id: string) => void;
236
+ removeUpload: (id: string) => void;
237
+ updateReceipt: (receipt: Receipt, patch: ReceiptPatch) => Promise<void>;
238
+ submitReceipt: (receipt: Receipt) => Promise<void>;
239
+ submitAll: () => Promise<void>;
240
+ /** Resolves `true` when the receipt was actually deleted (confirm accepted). */
241
+ deleteReceipt: (receipt: Receipt) => Promise<boolean>;
242
+ bulkCategorize: (categoryId: string) => Promise<void>;
243
+ bulkRemove: () => Promise<void>;
244
+ }
245
+
246
+ const key: InjectionKey<UploadCenterContext> = Symbol('upload-center');
247
+
248
+ export function provideUploadCenter(): UploadCenterContext {
249
+ const { toast } = useToast();
250
+ const { confirm } = useConfirm();
251
+
252
+ // -- Coopt the specific contexts: once, here, for the whole page. ----------
253
+ const shell = usePageShellContext<PeekItem>();
254
+ const table = useBbTableContext('receipts-table', { perPage: 25 });
255
+ const categoriesStore = useCategoriesStore();
256
+ const categories = computed(() => categoriesStore.categories);
257
+ // A shared catalog store does not seed itself just by being read. Kick the
258
+ // load here (idempotent — the store dedupes on an in-flight promise), or the
259
+ // category cells and the bulk-categorize popover stay permanently empty.
260
+ void categoriesStore.load();
261
+
262
+ // -- Page state -------------------------------------------------------------
263
+ const filters = reactive<ReceiptFilters>({
264
+ search: '',
265
+ categoryIds: [],
266
+ merchant: null,
267
+ spentBetween: [],
268
+ });
269
+ const hasActiveFilters = computed(
270
+ () =>
271
+ filters.search !== '' ||
272
+ filters.categoryIds.length > 0 ||
273
+ filters.merchant !== null ||
274
+ filters.spentBetween.length > 0
275
+ );
276
+ const tab = ref<UploadCenterTab>('drafts');
277
+ const tabCounts = ref<Record<UploadCenterTab, number>>({
278
+ drafts: 0,
279
+ submitted: 0,
280
+ reimbursed: 0,
281
+ });
282
+ const readyCount = ref(0);
283
+ const refreshKey = ref(0);
284
+
285
+ const clearFilters = () => {
286
+ filters.search = '';
287
+ filters.categoryIds = [];
288
+ filters.merchant = null;
289
+ filters.spentBetween = [];
290
+ };
291
+
292
+ const refresh = () => {
293
+ refreshKey.value++;
294
+ };
295
+
296
+ // -- Data ---------------------------------------------------------------------
297
+ // The one place the list is fetched. Writes the paging totals into the
298
+ // table context and keeps the tab counts and submit-all count live. A
299
+ // drafts page looks like:
300
+ // { id: 'rcp_3128', filename: 'uber-2026-07-08.pdf', merchant: 'Uber',
301
+ // categoryId: 'cat-rideshare', amount: 42.8, date: '2026-07-08', … }
302
+ // { id: 'rcp_3127', filename: 'IMG_4021.jpg', merchant: 'Starbucks Reserve',
303
+ // categoryId: 'cat-meals', amount: 11.4, date: '2026-07-08', … }
304
+ // { id: 'rcp_3120', filename: 'delta-ticket-0472.pdf', merchant: 'Delta Air Lines',
305
+ // categoryId: 'cat-travel', amount: 428.6, date: '2026-07-06', … }
306
+ // { id: 'rcp_3117', filename: 'marriott-folio.pdf', merchant: 'Marriott Marquis SF',
307
+ // categoryId: 'cat-lodging', amount: 612.33, date: '2026-07-05', … }
308
+ // On the Drafts tab the live upload queue renders above the fetched page.
309
+ const uploads = ref<UploadRow[]>([]);
310
+
311
+ const fetchRows = async (): Promise<UploadCenterRow[]> => {
312
+ const response = await api.receipts.list({
313
+ ...filters,
314
+ tab: tab.value,
315
+ page: table.page.value,
316
+ perPage: table.perPage.value,
317
+ });
318
+ table.total.value = response.total;
319
+ tabCounts.value = response.tabCounts;
320
+ readyCount.value = response.readyCount;
321
+ const rows = response.data.map(
322
+ (receipt): ReceiptRow => ({ ...receipt, kind: 'receipt' })
323
+ );
324
+ return tab.value === 'drafts' ? [...uploads.value, ...rows] : rows;
325
+ };
326
+
327
+ const searchMerchants = (query: string): Promise<string[]> =>
328
+ api.merchants.search(query);
329
+
330
+ // -- Upload machinery ----------------------------------------------------------
331
+ // The queue rows are reactive: progress ticks mutate them in place and the
332
+ // rendered cells update without a refetch. Only membership changes
333
+ // (enqueue, remove, completion) bump refreshKey so the table re-runs its
334
+ // items function. Files and abort controllers live in closure maps — they
335
+ // are not render state.
336
+ const uploadFiles = new Map<string, File>();
337
+ const controllers = new Map<string, AbortController>();
338
+
339
+ const startUpload = async (id: string) => {
340
+ const file = uploadFiles.get(id);
341
+ const row = uploads.value.find((upload) => upload.id === id);
342
+ if (!file || !row) return;
343
+ row.failed = false;
344
+ row.progress = 0;
345
+ const controller = new AbortController();
346
+ controllers.set(id, controller);
347
+ try {
348
+ await api.receipts.upload(file, {
349
+ signal: controller.signal,
350
+ onProgress: (percent) => {
351
+ row.progress = percent;
352
+ },
353
+ });
354
+ // Success: the file re-enters as a server draft with OCR-extracted
355
+ // merchant/amount/date prefilled — the refetch swaps the rows.
356
+ uploads.value = uploads.value.filter((upload) => upload.id !== id);
357
+ uploadFiles.delete(id);
358
+ refresh();
359
+ } catch {
360
+ // Keep the row: the progress cell renders the inline Retry.
361
+ row.failed = true;
362
+ } finally {
363
+ controllers.delete(id);
364
+ }
365
+ };
366
+
367
+ const enqueueFiles = (files: File[]) => {
368
+ for (const file of files) {
369
+ const id = `upload-${crypto.randomUUID()}`;
370
+ uploadFiles.set(id, file);
371
+ uploads.value.push({
372
+ id,
373
+ kind: 'upload',
374
+ filename: file.name,
375
+ size: file.size,
376
+ progress: 0,
377
+ failed: false,
378
+ });
379
+ void startUpload(id);
380
+ }
381
+ refresh();
382
+ };
383
+
384
+ const retryUpload = (id: string) => {
385
+ void startUpload(id);
386
+ };
387
+
388
+ const removeUpload = (id: string) => {
389
+ controllers.get(id)?.abort();
390
+ controllers.delete(id);
391
+ uploadFiles.delete(id);
392
+ uploads.value = uploads.value.filter((upload) => upload.id !== id);
393
+ refresh();
394
+ };
395
+
396
+ // -- Peek grammar ----------------------------------------------------------------
397
+ // peekX opens a fresh stack (from the list); stackX drills down (from a peek).
398
+ const peekReceipt = (id: string) => shell.push({ type: 'receipt', id }, true);
399
+ const stackReceipt = (id: string) => shell.push({ type: 'receipt', id });
400
+ const stackMerchant = (name: string) =>
401
+ shell.push({ type: 'merchant', name });
402
+
403
+ // -- Actions --------------------------------------------------------------------
404
+ const updateReceipt = async (receipt: Receipt, patch: ReceiptPatch) => {
405
+ try {
406
+ await api.receipts.update(receipt.id, patch);
407
+ refresh(); // silent on success — the cell already shows the new value
408
+ } catch {
409
+ refresh(); // the refetch reverts the cell to the server value
410
+ toast({
411
+ title: `Could not save ${receipt.filename}. Changes were reverted.`,
412
+ variant: 'destructive',
413
+ });
414
+ }
415
+ };
416
+
417
+ const submitReceipt = async (receipt: Receipt) => {
418
+ await api.receipts.submit(receipt.id);
419
+ refresh();
420
+ toast({
421
+ title: `${receipt.merchant ?? receipt.filename} submitted for approval.`,
422
+ variant: 'success',
423
+ });
424
+ };
425
+
426
+ const submitAll = async () => {
427
+ const { submitted } = await api.receipts.submitDrafts();
428
+ refresh();
429
+ toast({
430
+ title: `${submitted} receipts submitted for approval.`,
431
+ variant: 'success',
432
+ });
433
+ };
434
+
435
+ const deleteReceipt = async (receipt: Receipt): Promise<boolean> => {
436
+ const ok = await confirm({
437
+ variant: 'destructive',
438
+ title: 'Remove receipt',
439
+ text: `Remove ${receipt.filename}? The file is deleted and cannot be recovered.`,
440
+ yes: 'Remove',
441
+ no: 'Cancel',
442
+ });
443
+ if (!ok) return false;
444
+ await api.receipts.delete(receipt.id);
445
+ refresh();
446
+ toast({ title: `${receipt.filename} removed.`, variant: 'success' });
447
+ return true;
448
+ };
449
+
450
+ // Bulk actions read and clear the coopted table context themselves. Only
451
+ // draft receipt rows are selectable, so `selected` holds receipt ids.
452
+ const bulkIds = (): string[] => table.selected.value;
453
+ const clearSelection = () => {
454
+ table.selected.value = [];
455
+ };
456
+
457
+ const bulkCategorize = async (categoryId: string) => {
458
+ const ids = bulkIds();
459
+ await api.receipts.categorizeMany(ids, categoryId);
460
+ const category = categories.value.find((entry) => entry.id === categoryId);
461
+ clearSelection();
462
+ refresh();
463
+ toast({
464
+ title: `${ids.length} receipts filed under ${category?.name ?? 'the selected category'}.`,
465
+ variant: 'success',
466
+ });
467
+ };
468
+
469
+ const bulkRemove = async () => {
470
+ const ids = bulkIds();
471
+ const ok = await confirm({
472
+ variant: 'destructive',
473
+ title: 'Remove receipts',
474
+ text: `Remove ${ids.length} receipts? Their files are deleted and cannot be recovered.`,
475
+ yes: 'Remove',
476
+ no: 'Cancel',
477
+ });
478
+ if (!ok) return;
479
+ await api.receipts.deleteMany(ids);
480
+ clearSelection();
481
+ refresh();
482
+ toast({ title: `${ids.length} receipts removed.`, variant: 'success' });
483
+ };
484
+
485
+ const ctx: UploadCenterContext = {
486
+ shell,
487
+ table,
488
+ categories,
489
+ filters,
490
+ hasActiveFilters,
491
+ tab,
492
+ tabCounts,
493
+ readyCount,
494
+ uploads,
495
+ refreshKey,
496
+ fetchRows,
497
+ searchMerchants,
498
+ peekReceipt,
499
+ stackReceipt,
500
+ stackMerchant,
501
+ clearFilters,
502
+ enqueueFiles,
503
+ retryUpload,
504
+ removeUpload,
505
+ updateReceipt,
506
+ submitReceipt,
507
+ submitAll,
508
+ deleteReceipt,
509
+ bulkCategorize,
510
+ bulkRemove,
511
+ };
512
+ provide(key, ctx);
513
+ return ctx;
514
+ }
515
+
516
+ export function useUploadCenter(): UploadCenterContext {
517
+ const ctx = inject(key);
518
+ if (!ctx) throw new Error('useUploadCenter() called outside UploadCenter');
519
+ return ctx;
520
+ }
521
+ ```
522
+
523
+ ### Index.vue — the assembly
524
+
525
+ ```vue
526
+ <!-- UploadCenter/Index.vue -->
527
+ <template>
528
+ <PageShell>
529
+ <!-- Topbar: breadcrumbs left, page search + submit-all right. -->
530
+ <template #topbar>
531
+ <div class="flex items-center justify-between gap-4 border-b px-4 py-2">
532
+ <!-- Breadcrumbs take the row's slack on a stable basis (min-w-0 flex-auto);
533
+ without it their overflow recompute fights the flex layout every frame. -->
534
+ <BbBreadcrumbs
535
+ class="min-w-0 flex-auto"
536
+ :items="[
537
+ { key: 'dashboard', text: 'Dashboard', to: '/dashboard' },
538
+ { key: 'expenses', text: 'Expenses', to: '/expenses' },
539
+ { key: 'receipts', text: 'Receipts' },
540
+ ]"
541
+ />
542
+ <div class="flex shrink-0 items-center gap-2">
543
+ <BbTextInput
544
+ v-model="ctx.filters.search"
545
+ clearable
546
+ compact
547
+ hide-label
548
+ label="Search receipts"
549
+ placeholder="Search merchant or filename…"
550
+ prepend:icon="lucide:search"
551
+ />
552
+ <!-- The page's single primary: submit-all with a live count.
553
+ BbButton tracks the async handler, so it shows its own
554
+ loading state while the batch submits. -->
555
+ <BbButton
556
+ :disabled="ctx.readyCount.value === 0"
557
+ prepend:icon="lucide:send"
558
+ variant="primary"
559
+ @click="ctx.submitAll"
560
+ >
561
+ {{ submitLabel }}
562
+ </BbButton>
563
+ </div>
564
+ </div>
565
+ </template>
566
+
567
+ <div class="flex flex-col gap-3 p-4">
568
+ <!-- Capture surface: drafts tab only. -->
569
+ <ReceiptDropzone v-if="ctx.tab.value === 'drafts'" />
570
+
571
+ <FilterRail />
572
+
573
+ <!-- Tabs as URL filters: href updates the query, the key feeds the
574
+ fetch. Counts come from the server on every fetch. -->
575
+ <BbTabs
576
+ v-model="ctx.tab.value"
577
+ compact
578
+ :items="[
579
+ {
580
+ key: 'drafts',
581
+ label: `Drafts · ${ctx.tabCounts.value.drafts}`,
582
+ href: '?tab=drafts',
583
+ },
584
+ {
585
+ key: 'submitted',
586
+ label: `Submitted · ${ctx.tabCounts.value.submitted}`,
587
+ href: '?tab=submitted',
588
+ },
589
+ {
590
+ key: 'reimbursed',
591
+ label: `Reimbursed · ${ctx.tabCounts.value.reimbursed}`,
592
+ href: '?tab=reimbursed',
593
+ },
594
+ ]"
595
+ />
596
+
597
+ <BbTable
598
+ id="receipts-table"
599
+ actions
600
+ caption="Expense receipts"
601
+ :columns="columns"
602
+ compact
603
+ :dependencies="[
604
+ { ...ctx.filters },
605
+ ctx.tab.value,
606
+ ctx.refreshKey.value,
607
+ ]"
608
+ :deps-debounce-time="300"
609
+ item-value="id"
610
+ :items="ctx.fetchRows"
611
+ loading-text="Loading receipts…"
612
+ :row-class="rowClass"
613
+ :selectable="isDraft"
614
+ >
615
+ <!-- Clicking the NAME of a thing peeks it. -->
616
+ <template #filename="{ item }">
617
+ <ReceiptFileCell :row="item" />
618
+ </template>
619
+
620
+ <!-- Editable cells on draft rows; plain text everywhere else. -->
621
+ <template #merchant="{ item }">
622
+ <MerchantCell v-if="isDraft(item)" :receipt="item" />
623
+ <span v-else-if="item.kind === 'upload'" class="text-gray-400"
624
+ >—</span
625
+ >
626
+ <span v-else>{{ item.merchant ?? '—' }}</span>
627
+ </template>
628
+
629
+ <!-- Slot names are normalized: `categoryId` → `#categoryid`. -->
630
+ <template #categoryid="{ item }">
631
+ <CategoryCell v-if="isDraft(item)" :receipt="item" />
632
+ <span v-else-if="item.kind === 'upload'" class="text-gray-400"
633
+ >—</span
634
+ >
635
+ <span v-else>{{ categoryName(item.categoryId) }}</span>
636
+ </template>
637
+
638
+ <template #amount="{ item }">
639
+ <AmountCell v-if="isDraft(item)" :receipt="item" />
640
+ <span v-else-if="item.kind === 'upload'" class="text-gray-400"
641
+ >—</span
642
+ >
643
+ <span v-else>{{
644
+ item.amount === null ? '—' : currency.format(item.amount)
645
+ }}</span>
646
+ </template>
647
+
648
+ <template #date="{ item }">
649
+ <DateCell v-if="isDraft(item)" :receipt="item" />
650
+ <span v-else-if="item.kind === 'upload'" class="text-gray-400"
651
+ >—</span
652
+ >
653
+ <span v-else>{{ item.date ? shortDate(item.date) : '—' }}</span>
654
+ </template>
655
+
656
+ <!-- Status column doubles as the transfer surface for queue rows. -->
657
+ <template #status="{ item }">
658
+ <UploadProgressCell v-if="item.kind === 'upload'" :upload="item" />
659
+ <BbBadge v-else :variant="STATUS_VARIANT[item.status]">{{
660
+ STATUS_LABEL[item.status]
661
+ }}</BbBadge>
662
+ </template>
663
+
664
+ <template #actions="{ item }">
665
+ <RowActions :row="item" />
666
+ </template>
667
+
668
+ <template #no-data>
669
+ <div class="flex flex-col items-center gap-2 p-8 text-center">
670
+ <BbIcon
671
+ aria-hidden="true"
672
+ class="text-gray-400"
673
+ :icon="
674
+ ctx.hasActiveFilters.value
675
+ ? 'lucide:search-x'
676
+ : 'lucide:receipt'
677
+ "
678
+ size="2xl"
679
+ />
680
+ <p class="text-sm font-semibold">
681
+ {{
682
+ ctx.hasActiveFilters.value
683
+ ? 'No matching receipts'
684
+ : ctx.tab.value === 'drafts'
685
+ ? 'No drafts yet'
686
+ : 'Nothing in this tab yet'
687
+ }}
688
+ </p>
689
+ <p class="text-xs text-gray-500">
690
+ {{
691
+ ctx.hasActiveFilters.value
692
+ ? 'Loosen a filter above, or switch tabs to widen the view.'
693
+ : ctx.tab.value === 'drafts'
694
+ ? 'Drop receipts above to get started.'
695
+ : 'Submitted and reimbursed receipts land in their own tabs.'
696
+ }}
697
+ </p>
698
+ <BbButton
699
+ v-if="ctx.hasActiveFilters.value"
700
+ prepend:icon="lucide:x"
701
+ variant="ghost"
702
+ @click="ctx.clearFilters"
703
+ >
704
+ Clear filters
705
+ </BbButton>
706
+ </div>
707
+ </template>
708
+ </BbTable>
709
+
710
+ <!-- Joins the table context by id: no page/totalPages wiring at all. -->
711
+ <BbPagination table-id="receipts-table" />
712
+ </div>
713
+
714
+ <SelectionBar />
715
+
716
+ <!-- Stacked peek sidebar: the shell owns back/close; we render by type. -->
717
+ <template #sidebar>
718
+ <ReceiptPeek
719
+ v-if="ctx.shell.current.value?.type === 'receipt'"
720
+ :receipt-id="ctx.shell.current.value.id"
721
+ />
722
+ <MerchantPeek
723
+ v-else-if="ctx.shell.current.value?.type === 'merchant'"
724
+ :merchant-name="ctx.shell.current.value.name"
725
+ />
726
+ </template>
727
+ </PageShell>
728
+ </template>
729
+
730
+ <script setup lang="ts">
731
+ import { computed } from 'vue';
732
+ import {
733
+ BbBadge,
734
+ BbBreadcrumbs,
735
+ BbButton,
736
+ BbIcon,
737
+ BbPagination,
738
+ BbTable,
739
+ BbTabs,
740
+ BbTextInput,
741
+ } from 'bitboss-ui';
742
+ import PageShell from '@/components/layout/PageShell.vue';
743
+ import {
744
+ provideUploadCenter,
745
+ STATUS_LABEL,
746
+ STATUS_VARIANT,
747
+ type ReceiptRow,
748
+ type UploadCenterRow,
749
+ } from './context';
750
+ import AmountCell from './AmountCell.vue';
751
+ import CategoryCell from './CategoryCell.vue';
752
+ import DateCell from './DateCell.vue';
753
+ import FilterRail from './FilterRail.vue';
754
+ import MerchantCell from './MerchantCell.vue';
755
+ import MerchantPeek from './MerchantPeek.vue';
756
+ import ReceiptDropzone from './ReceiptDropzone.vue';
757
+ import ReceiptFileCell from './ReceiptFileCell.vue';
758
+ import ReceiptPeek from './ReceiptPeek.vue';
759
+ import RowActions from './RowActions.vue';
760
+ import SelectionBar from './SelectionBar.vue';
761
+ import UploadProgressCell from './UploadProgressCell.vue';
762
+
763
+ const ctx = provideUploadCenter();
764
+
765
+ const currency = new Intl.NumberFormat('en-US', {
766
+ style: 'currency',
767
+ currency: 'USD',
768
+ });
769
+ const shortDate = (value: string) =>
770
+ new Date(value).toLocaleDateString('en-US', {
771
+ month: 'short',
772
+ day: 'numeric',
773
+ });
774
+
775
+ // Every cell renders through a slot, so columns stay label-only definitions.
776
+ const columns = [
777
+ { key: 'filename', label: 'Receipt' },
778
+ { key: 'merchant', label: 'Merchant' },
779
+ { key: 'categoryId', label: 'Category' },
780
+ { key: 'amount', label: 'Amount', align: 'right' as const },
781
+ { key: 'date', label: 'Date' },
782
+ { key: 'status', label: 'Status' },
783
+ ];
784
+
785
+ // Only server-side drafts are editable and selectable; queue rows and
786
+ // submitted/reimbursed receipts are not. The narrow predicate keeps the
787
+ // `v-else` (non-draft receipt) branch a real `ReceiptRow`, not `never`.
788
+ const isDraft = (
789
+ item: UploadCenterRow
790
+ ): item is ReceiptRow & { status: 'draft' } =>
791
+ item.kind === 'receipt' && item.status === 'draft';
792
+
793
+ // Failed transfers get a tinted row — public row-class API, no internals.
794
+ const rowClass = (item: UploadCenterRow) =>
795
+ item.kind === 'upload' && item.failed
796
+ ? 'bg-red-50 dark:bg-red-950/20'
797
+ : undefined;
798
+
799
+ const categoryName = (categoryId: string | null) =>
800
+ ctx.categories.value.find((category) => category.id === categoryId)?.name ??
801
+ '—';
802
+
803
+ const submitLabel = computed(() =>
804
+ ctx.readyCount.value === 0
805
+ ? 'Submit receipts'
806
+ : `Submit ${ctx.readyCount.value} ${ctx.readyCount.value === 1 ? 'receipt' : 'receipts'}`
807
+ );
808
+ </script>
809
+ ```
810
+
811
+ ### ReceiptDropzone.vue
812
+
813
+ ```vue
814
+ <!-- UploadCenter/ReceiptDropzone.vue -->
815
+ <template>
816
+ <BbDropzone
817
+ v-model="pending"
818
+ :accept="ACCEPT"
819
+ :errors="dropError"
820
+ :max-files="20"
821
+ :max-size="MAX_SIZE"
822
+ multiple
823
+ @error="onError"
824
+ >
825
+ <template #default="{ dragging, focused, open }">
826
+ <div
827
+ class="flex flex-col items-center gap-2 rounded-[var(--bb-radius)] border-2 border-dashed p-6 text-center transition-colors"
828
+ :class="[
829
+ dragging ? 'border-[var(--bb-primary)]' : 'border-[var(--bb-border)]',
830
+ focused ? 'ring-2 ring-[var(--bb-primary)] ring-offset-2' : '',
831
+ ]"
832
+ >
833
+ <BbIcon class="text-gray-400" icon="lucide:receipt" size="lg" />
834
+ <p class="text-sm font-medium">
835
+ {{ dragging ? 'Drop to add receipts' : 'Drop receipts here' }}
836
+ </p>
837
+ <p class="text-xs text-gray-500">
838
+ JPG, PNG, HEIC or PDF · up to 10 MB each · 20 files per drop
839
+ </p>
840
+ <BbButton
841
+ prepend:icon="lucide:folder-open"
842
+ variant="ghost"
843
+ @click="open"
844
+ >
845
+ Browse files
846
+ </BbButton>
847
+ </div>
848
+ </template>
849
+ </BbDropzone>
850
+ </template>
851
+
852
+ <script setup lang="ts">
853
+ import { ref, watch } from 'vue';
854
+ import { BbButton, BbDropzone, BbIcon, type DropZoneError } from 'bitboss-ui';
855
+ import { useUploadCenter } from './context';
856
+
857
+ // Pair every extension with its MIME type: the MIME rule matches by content
858
+ // type, the .ext rule catches drag-drops where the OS leaves file.type empty.
859
+ const ACCEPT = [
860
+ 'image/jpeg',
861
+ '.jpg',
862
+ '.jpeg',
863
+ 'image/png',
864
+ '.png',
865
+ 'image/heic',
866
+ '.heic',
867
+ 'application/pdf',
868
+ '.pdf',
869
+ ];
870
+ const MAX_SIZE = 10 * 1024 * 1024; // 10 MB per receipt
871
+
872
+ const ctx = useUploadCenter();
873
+
874
+ // BbDropzone captures and validates; the context uploads. The model is a
875
+ // hand-off buffer: drain every validated batch into the queue, then clear it
876
+ // (which also resets the duplicate check for future corrections).
877
+ const pending = ref<File[]>([]);
878
+ watch(pending, (files) => {
879
+ if (files.length === 0) return;
880
+ dropError.value = undefined;
881
+ ctx.enqueueFiles(files);
882
+ pending.value = [];
883
+ });
884
+
885
+ // The errors display is a round-trip: map each typed reject to a sentence
886
+ // and feed it back through the `errors` prop (rendered in the built-in
887
+ // aria-live region). Batch drops emit one error per file; showing the last
888
+ // message keeps the surface calm.
889
+ const dropError = ref<string | undefined>();
890
+ const onError = (error: DropZoneError) => {
891
+ if (error.type === 'maxSize') {
892
+ dropError.value = `${error.filename} is ${error.formattedSize} — receipts are capped at ${error.formattedMaxSize}.`;
893
+ } else if (error.type === 'accept') {
894
+ dropError.value = `${error.filename} is not a JPG, PNG, HEIC or PDF.`;
895
+ } else if (error.type === 'uniqueness') {
896
+ dropError.value = `${error.filename} is already in this drop.`;
897
+ } else {
898
+ dropError.value = `That drop had ${error.totalFiles} files — add at most 20 at a time.`;
899
+ }
900
+ };
901
+ </script>
902
+ ```
903
+
904
+ ### FilterRail.vue
905
+
906
+ ```vue
907
+ <!-- UploadCenter/FilterRail.vue -->
908
+ <template>
909
+ <div class="flex flex-wrap items-center gap-2">
910
+ <!-- Category: multi-select pill over the coopted catalog. -->
911
+ <BbSelectPopover
912
+ v-model="ctx.filters.categoryIds"
913
+ item-text="name"
914
+ item-value="id"
915
+ :items="ctx.categories.value"
916
+ multiple
917
+ width="240px"
918
+ >
919
+ <template #activator="{ props }">
920
+ <BbButton
921
+ v-bind="props"
922
+ append:icon="lucide:chevron-down"
923
+ size="sm"
924
+ variant="outline"
925
+ >
926
+ Category{{
927
+ ctx.filters.categoryIds.length
928
+ ? ` · ${ctx.filters.categoryIds.length}`
929
+ : ''
930
+ }}
931
+ </BbButton>
932
+ </template>
933
+ </BbSelectPopover>
934
+
935
+ <!-- Merchant: query-aware search. Merchant names are their own values,
936
+ so the pill labels itself straight from the filter state. -->
937
+ <BbSelectPopover
938
+ v-model="ctx.filters.merchant"
939
+ :items="ctx.searchMerchants"
940
+ width="240px"
941
+ >
942
+ <template #activator="{ props }">
943
+ <BbButton
944
+ v-bind="props"
945
+ append:icon="lucide:chevron-down"
946
+ size="sm"
947
+ variant="outline"
948
+ >
949
+ {{ ctx.filters.merchant ?? 'Merchant' }}
950
+ </BbButton>
951
+ </template>
952
+ </BbSelectPopover>
953
+
954
+ <!-- Spent-between range: a compact input is 28px — flush with the pills. -->
955
+ <BbDatePickerInput
956
+ v-model="ctx.filters.spentBetween"
957
+ clearable
958
+ compact
959
+ floating
960
+ hide-label
961
+ label="Spent between"
962
+ placeholder="Spent between…"
963
+ range
964
+ />
965
+
966
+ <!-- Clear-all renders only while something is active. -->
967
+ <BbButton
968
+ v-if="ctx.hasActiveFilters.value"
969
+ class="ml-auto"
970
+ prepend:icon="lucide:x"
971
+ size="sm"
972
+ variant="ghost"
973
+ @click="ctx.clearFilters"
974
+ >
975
+ Clear filters
976
+ </BbButton>
977
+ </div>
978
+ </template>
979
+
980
+ <script setup lang="ts">
981
+ import { BbButton, BbDatePickerInput, BbSelectPopover } from 'bitboss-ui';
982
+ import { useUploadCenter } from './context';
983
+
984
+ const ctx = useUploadCenter();
985
+ </script>
986
+ ```
987
+
988
+ ### ReceiptFileCell.vue
989
+
990
+ ```vue
991
+ <!-- UploadCenter/ReceiptFileCell.vue -->
992
+ <template>
993
+ <div class="flex items-center gap-2">
994
+ <BbIcon class="shrink-0 text-gray-400" :icon="fileIcon" size="16" />
995
+ <div class="flex min-w-0 flex-col">
996
+ <!-- Server receipts peek on click; queue rows are not peekable yet. -->
997
+ <BbButton
998
+ v-if="row.kind === 'receipt'"
999
+ class="justify-start"
1000
+ size="sm"
1001
+ variant="link"
1002
+ @click="() => ctx.peekReceipt(row.id)"
1003
+ >
1004
+ {{ row.filename }}
1005
+ </BbButton>
1006
+ <span v-else class="truncate text-sm">{{ row.filename }}</span>
1007
+ <span class="text-xs text-gray-500">{{ formattedSize }}</span>
1008
+ </div>
1009
+ </div>
1010
+ </template>
1011
+
1012
+ <script setup lang="ts">
1013
+ import { computed } from 'vue';
1014
+ import { BbButton, BbIcon } from 'bitboss-ui';
1015
+ import { useUploadCenter, type UploadCenterRow } from './context';
1016
+
1017
+ const props = defineProps<{ row: UploadCenterRow }>();
1018
+
1019
+ const ctx = useUploadCenter();
1020
+
1021
+ const fileIcon = computed(() =>
1022
+ props.row.filename.toLowerCase().endsWith('.pdf')
1023
+ ? 'lucide:file-text'
1024
+ : 'lucide:image'
1025
+ );
1026
+
1027
+ const formattedSize = computed(() => {
1028
+ const bytes =
1029
+ props.row.kind === 'upload' ? props.row.size : props.row.fileSize;
1030
+ return bytes >= 1024 * 1024
1031
+ ? `${(bytes / (1024 * 1024)).toFixed(1)} MB`
1032
+ : `${Math.max(1, Math.round(bytes / 1024))} KB`;
1033
+ });
1034
+ </script>
1035
+ ```
1036
+
1037
+ ### UploadProgressCell.vue
1038
+
1039
+ ```vue
1040
+ <!-- UploadCenter/UploadProgressCell.vue -->
1041
+ <template>
1042
+ <!-- In flight: a live bar. `upload.progress` is a reactive field mutated
1043
+ by the context's progress callback — no refetch per tick. -->
1044
+ <div v-if="!upload.failed" class="flex min-w-32 items-center gap-2">
1045
+ <BbProgress
1046
+ :aria-label="`Uploading ${upload.filename}`"
1047
+ class="flex-1"
1048
+ :model-value="upload.progress"
1049
+ />
1050
+ <span class="text-xs tabular-nums text-gray-500"
1051
+ >{{ upload.progress }}%</span
1052
+ >
1053
+ </div>
1054
+
1055
+ <!-- Failed: say so and retry inline. `xs` is fine here — this is the
1056
+ densest surface on the page. -->
1057
+ <div v-else class="flex items-center gap-2">
1058
+ <span class="text-xs font-medium text-red-600 dark:text-red-400"
1059
+ >Upload failed</span
1060
+ >
1061
+ <BbButton
1062
+ prepend:icon="lucide:rotate-cw"
1063
+ size="xs"
1064
+ variant="outline"
1065
+ @click="() => ctx.retryUpload(upload.id)"
1066
+ >
1067
+ Retry
1068
+ </BbButton>
1069
+ </div>
1070
+ </template>
1071
+
1072
+ <script setup lang="ts">
1073
+ import { BbButton, BbProgress } from 'bitboss-ui';
1074
+ import { useUploadCenter, type UploadRow } from './context';
1075
+
1076
+ defineProps<{ upload: UploadRow }>();
1077
+
1078
+ const ctx = useUploadCenter();
1079
+ </script>
1080
+ ```
1081
+
1082
+ ### MerchantCell.vue
1083
+
1084
+ ```vue
1085
+ <!-- UploadCenter/MerchantCell.vue -->
1086
+ <template>
1087
+ <BbTextInput
1088
+ v-model="draft"
1089
+ compact
1090
+ hide-label
1091
+ label="Merchant"
1092
+ placeholder="Add merchant"
1093
+ @blur="commit"
1094
+ @keydown.enter="commit"
1095
+ @keydown.esc="revert"
1096
+ />
1097
+ </template>
1098
+
1099
+ <script setup lang="ts">
1100
+ import { ref, watch } from 'vue';
1101
+ import { BbTextInput } from 'bitboss-ui';
1102
+ import { useUploadCenter } from './context';
1103
+ import type { Receipt } from '@/types';
1104
+
1105
+ const props = defineProps<{ receipt: Receipt }>();
1106
+
1107
+ const ctx = useUploadCenter();
1108
+
1109
+ // Inline-edit doctrine (§6.3): a local draft, commit on blur/Enter, revert
1110
+ // on Esc. The server value re-seeds the draft whenever a refetch updates the
1111
+ // row — which is also how a failed save reverts.
1112
+ const draft = ref<string | null>(props.receipt.merchant);
1113
+ watch(
1114
+ () => props.receipt.merchant,
1115
+ (value) => {
1116
+ draft.value = value;
1117
+ }
1118
+ );
1119
+
1120
+ const commit = () => {
1121
+ const merchant = draft.value?.trim() || null;
1122
+ if (merchant === props.receipt.merchant) return;
1123
+ void ctx.updateReceipt(props.receipt, { merchant });
1124
+ };
1125
+ const revert = () => {
1126
+ draft.value = props.receipt.merchant;
1127
+ };
1128
+ </script>
1129
+ ```
1130
+
1131
+ ### CategoryCell.vue
1132
+
1133
+ ```vue
1134
+ <!-- UploadCenter/CategoryCell.vue -->
1135
+ <template>
1136
+ <BbSelectPopover
1137
+ compact
1138
+ disable-writing
1139
+ item-text="name"
1140
+ item-value="id"
1141
+ :items="ctx.categories.value"
1142
+ :model-value="receipt.categoryId"
1143
+ width="220px"
1144
+ @update:model-value="(categoryId) => pick(categoryId as string)"
1145
+ >
1146
+ <template #activator="{ props: activatorProps, shown }">
1147
+ <!-- One-click pattern (§6.1): the badge is the focusable trigger —
1148
+ BbBadgeButton takes over the badge body, the trailing chevron says
1149
+ "this can change", and while the save runs `loading` swaps the
1150
+ spinner into the chevron's place. A category is a label, not a
1151
+ semantic status, so a set category reads neutral (`secondary`);
1152
+ only the unset state stays `outline` so empty cells read as
1153
+ quieter to-dos, not values. -->
1154
+ <BbBadge
1155
+ append:icon="lucide:chevron-down"
1156
+ :class="{ 'category-cell--open': shown }"
1157
+ :loading="saving"
1158
+ :variant="receipt.categoryId ? 'secondary' : 'outline'"
1159
+ >
1160
+ <BbBadgeButton v-bind="activatorProps">{{
1161
+ categoryName
1162
+ }}</BbBadgeButton>
1163
+ </BbBadge>
1164
+ </template>
1165
+ </BbSelectPopover>
1166
+ </template>
1167
+
1168
+ <script setup lang="ts">
1169
+ import { computed, ref } from 'vue';
1170
+ import { BbBadge, BbBadgeButton, BbSelectPopover } from 'bitboss-ui';
1171
+ import { useUploadCenter } from './context';
1172
+ import type { Receipt } from '@/types';
1173
+
1174
+ const props = defineProps<{ receipt: Receipt }>();
1175
+
1176
+ const ctx = useUploadCenter();
1177
+
1178
+ // In-flight flag for the save feedback — rung-1 local state, not context.
1179
+ const saving = ref(false);
1180
+ const pick = async (categoryId: string) => {
1181
+ saving.value = true;
1182
+ try {
1183
+ await ctx.updateReceipt(props.receipt, { categoryId });
1184
+ } finally {
1185
+ saving.value = false;
1186
+ }
1187
+ };
1188
+
1189
+ // The trigger labels itself from the coopted catalog, never from the
1190
+ // popover's lazy `text` slot prop.
1191
+ const categoryName = computed(
1192
+ () =>
1193
+ ctx.categories.value.find(
1194
+ (category) => category.id === props.receipt.categoryId
1195
+ )?.name ?? 'Set category'
1196
+ );
1197
+ </script>
1198
+
1199
+ <style scoped>
1200
+ /* Open = the badge's own hue, deepened, plus its variant ring — the same
1201
+ grammar as every badge-activator cell. */
1202
+ .category-cell--open {
1203
+ --bg: color-mix(in oklab, var(--color) 24%, var(--bb-panel));
1204
+ --border-color: color-mix(in oklab, var(--color) 45%, var(--bb-panel));
1205
+ box-shadow: 0 0 0 var(--bb-ring-size) var(--ring);
1206
+ }
1207
+ </style>
1208
+ ```
1209
+
1210
+ ### AmountCell.vue
1211
+
1212
+ ```vue
1213
+ <!-- UploadCenter/AmountCell.vue -->
1214
+ <template>
1215
+ <BbNumberInput
1216
+ v-model="draft"
1217
+ compact
1218
+ hide-label
1219
+ label="Amount"
1220
+ :max-precision="2"
1221
+ :min="0"
1222
+ placeholder="0.00"
1223
+ @blur="commit"
1224
+ @keydown.enter="commit"
1225
+ @keydown.esc="revert"
1226
+ >
1227
+ <template #prefix>$</template>
1228
+ </BbNumberInput>
1229
+ </template>
1230
+
1231
+ <script setup lang="ts">
1232
+ import { ref, watch } from 'vue';
1233
+ import { BbNumberInput } from 'bitboss-ui';
1234
+ import { useUploadCenter } from './context';
1235
+ import type { Receipt } from '@/types';
1236
+
1237
+ const props = defineProps<{ receipt: Receipt }>();
1238
+
1239
+ const ctx = useUploadCenter();
1240
+
1241
+ // Same commit/revert contract as the merchant cell, on the number model.
1242
+ const draft = ref<number | string | null>(props.receipt.amount);
1243
+ watch(
1244
+ () => props.receipt.amount,
1245
+ (value) => {
1246
+ draft.value = value;
1247
+ }
1248
+ );
1249
+
1250
+ const commit = () => {
1251
+ const amount =
1252
+ draft.value === null || draft.value === '' ? null : Number(draft.value);
1253
+ if (amount === props.receipt.amount) return;
1254
+ void ctx.updateReceipt(props.receipt, { amount });
1255
+ };
1256
+ const revert = () => {
1257
+ draft.value = props.receipt.amount;
1258
+ };
1259
+ </script>
1260
+ ```
1261
+
1262
+ ### DateCell.vue
1263
+
1264
+ ```vue
1265
+ <!-- UploadCenter/DateCell.vue -->
1266
+ <template>
1267
+ <!-- Picking a date IS the commit — no blur dance for calendar input.
1268
+ `floating` keeps the model a plain YYYY-MM-DD string. -->
1269
+ <BbDatePickerInput
1270
+ compact
1271
+ floating
1272
+ hide-label
1273
+ label="Expense date"
1274
+ :model-value="receipt.date"
1275
+ placeholder="YYYY-MM-DD"
1276
+ @update:model-value="commit"
1277
+ />
1278
+ </template>
1279
+
1280
+ <script setup lang="ts">
1281
+ import { BbDatePickerInput } from 'bitboss-ui';
1282
+ import { useUploadCenter } from './context';
1283
+ import type { Receipt } from '@/types';
1284
+
1285
+ const props = defineProps<{ receipt: Receipt }>();
1286
+
1287
+ const ctx = useUploadCenter();
1288
+
1289
+ const commit = (value: string | string[] | null) => {
1290
+ const date = Array.isArray(value) ? (value[0] ?? null) : value;
1291
+ if (date === props.receipt.date) return;
1292
+ void ctx.updateReceipt(props.receipt, { date });
1293
+ };
1294
+ </script>
1295
+ ```
1296
+
1297
+ ### RowActions.vue
1298
+
1299
+ ```vue
1300
+ <!-- UploadCenter/RowActions.vue -->
1301
+ <template>
1302
+ <!-- Queue rows: one explicit remove (aborts the transfer). -->
1303
+ <BbButton
1304
+ v-if="row.kind === 'upload'"
1305
+ :aria-label="`Remove ${row.filename} from the queue`"
1306
+ icon="lucide:x"
1307
+ size="sm"
1308
+ variant="ghost"
1309
+ @click="() => ctx.removeUpload(row.id)"
1310
+ />
1311
+
1312
+ <!-- Server receipts: contextual dropdown, entries vary by status. -->
1313
+ <BbDropdown v-else :items="items">
1314
+ <template #activator="{ props }">
1315
+ <BbButton v-bind="props" icon="lucide:ellipsis" size="sm" variant="ghost">
1316
+ Receipt actions
1317
+ </BbButton>
1318
+ </template>
1319
+ </BbDropdown>
1320
+ </template>
1321
+
1322
+ <script setup lang="ts">
1323
+ import { computed } from 'vue';
1324
+ import { BbButton, BbDropdown } from 'bitboss-ui';
1325
+ import { useUploadCenter, type UploadCenterRow } from './context';
1326
+
1327
+ const props = defineProps<{ row: UploadCenterRow }>();
1328
+
1329
+ const ctx = useUploadCenter();
1330
+
1331
+ const items = computed(() => {
1332
+ if (props.row.kind !== 'receipt') return [];
1333
+ const receipt = props.row;
1334
+ const isDraft = receipt.status === 'draft';
1335
+ return [
1336
+ ...(isDraft
1337
+ ? [
1338
+ {
1339
+ key: 'submit',
1340
+ text: 'Submit for approval',
1341
+ 'prepend:icon': 'lucide:send',
1342
+ onClick: () => ctx.submitReceipt(receipt),
1343
+ },
1344
+ ]
1345
+ : []),
1346
+ {
1347
+ key: 'download',
1348
+ text: 'Download original',
1349
+ 'prepend:icon': 'lucide:download',
1350
+ href: `/receipts/${receipt.id}/file`,
1351
+ },
1352
+ ...(isDraft
1353
+ ? [
1354
+ {
1355
+ key: 'remove',
1356
+ text: 'Remove',
1357
+ 'prepend:icon': 'lucide:trash-2',
1358
+ variant: 'destructive' as const,
1359
+ onClick: () => ctx.deleteReceipt(receipt),
1360
+ },
1361
+ ]
1362
+ : []),
1363
+ ];
1364
+ });
1365
+ </script>
1366
+ ```
1367
+
1368
+ ### SelectionBar.vue
1369
+
1370
+ ```vue
1371
+ <!-- UploadCenter/SelectionBar.vue -->
1372
+ <template>
1373
+ <FloatingBottomPanel :open="selectedCount > 0">
1374
+ <span class="px-2 text-sm">{{ selectedCount }} selected</span>
1375
+
1376
+ <!-- Bulk categorize: the picker lives right in the bar — a one-shot
1377
+ popover (model stays null) whose selection IS the action. -->
1378
+ <BbSelectPopover
1379
+ item-text="name"
1380
+ item-value="id"
1381
+ :items="ctx.categories.value"
1382
+ :model-value="null"
1383
+ placement="top"
1384
+ width="220px"
1385
+ @update:model-value="
1386
+ (categoryId) => categoryId && ctx.bulkCategorize(categoryId)
1387
+ "
1388
+ >
1389
+ <template #activator="{ props }">
1390
+ <BbButton
1391
+ v-bind="props"
1392
+ prepend:icon="lucide:tag"
1393
+ size="sm"
1394
+ variant="ghost"
1395
+ >
1396
+ Set category
1397
+ </BbButton>
1398
+ </template>
1399
+ </BbSelectPopover>
1400
+
1401
+ <div class="floating-bottom-panel__right flex items-center gap-1">
1402
+ <BbButton size="sm" variant="destructive" @click="ctx.bulkRemove"
1403
+ >Remove</BbButton
1404
+ >
1405
+ <BbButton
1406
+ aria-label="Clear selection"
1407
+ icon="lucide:x"
1408
+ size="sm"
1409
+ variant="ghost"
1410
+ @click="clearSelection"
1411
+ />
1412
+ </div>
1413
+ </FloatingBottomPanel>
1414
+ </template>
1415
+
1416
+ <script setup lang="ts">
1417
+ import { computed } from 'vue';
1418
+ import { BbButton, BbSelectPopover } from 'bitboss-ui';
1419
+ import FloatingBottomPanel from '@/components/layout/FloatingBottomPanel.vue';
1420
+ import { useUploadCenter } from './context';
1421
+
1422
+ const ctx = useUploadCenter();
1423
+
1424
+ const selectedCount = computed(() => ctx.table.selected.value?.length ?? 0);
1425
+ const clearSelection = () => {
1426
+ ctx.table.selected.value = [];
1427
+ };
1428
+ </script>
1429
+ ```
1430
+
1431
+ ### ReceiptPeek.vue
1432
+
1433
+ ```vue
1434
+ <!-- UploadCenter/ReceiptPeek.vue -->
1435
+ <template>
1436
+ <div v-if="receipt" class="flex flex-col gap-4 text-sm">
1437
+ <!-- Header: merchant identity + amount + status. The merchant name
1438
+ drills DOWN — stacked peek, back arrow via the shell. -->
1439
+ <header class="flex flex-col gap-1.5">
1440
+ <div class="flex items-center justify-between gap-2">
1441
+ <BbButton
1442
+ v-if="receipt.merchant"
1443
+ size="sm"
1444
+ variant="link"
1445
+ @click="() => ctx.stackMerchant(receipt!.merchant!)"
1446
+ >
1447
+ {{ receipt.merchant }}
1448
+ </BbButton>
1449
+ <span v-else class="text-gray-500">No merchant yet</span>
1450
+ <BbBadge variant="outline">{{ receipt.status }}</BbBadge>
1451
+ </div>
1452
+ <p class="text-xl font-semibold">
1453
+ {{
1454
+ receipt.amount === null
1455
+ ? 'Amount missing'
1456
+ : currency.format(receipt.amount)
1457
+ }}
1458
+ </p>
1459
+ <p class="text-xs text-gray-500">
1460
+ {{ receipt.filename }} · spent
1461
+ {{ receipt.date ? longDate(receipt.date) : '—' }}
1462
+ </p>
1463
+ </header>
1464
+
1465
+ <!-- Preview placeholder: the real app renders the scanned image here. -->
1466
+ <div
1467
+ class="flex h-44 flex-col items-center justify-center gap-1 rounded-[var(--bb-radius)] border bg-[var(--bb-panel)] text-gray-400"
1468
+ >
1469
+ <BbIcon icon="lucide:receipt" size="lg" />
1470
+ <span class="text-xs">Receipt preview</span>
1471
+ </div>
1472
+
1473
+ <!-- Extracted fields: what OCR read off the scan, with confidence. -->
1474
+ <section class="flex flex-col gap-1.5">
1475
+ <div class="flex items-center justify-between">
1476
+ <h3 class="text-xs font-semibold uppercase tracking-wide text-gray-500">
1477
+ Extracted fields
1478
+ </h3>
1479
+ <BbBadge size="xs" variant="outline">{{
1480
+ `OCR · ${receipt.extracted.confidence}%`
1481
+ }}</BbBadge>
1482
+ </div>
1483
+ <dl class="grid grid-cols-[auto_1fr] gap-x-4 gap-y-1.5">
1484
+ <dt class="text-gray-500">Merchant</dt>
1485
+ <dd>{{ receipt.extracted.merchant ?? '—' }}</dd>
1486
+ <dt class="text-gray-500">Total</dt>
1487
+ <dd>
1488
+ {{
1489
+ receipt.extracted.total === null
1490
+ ? '—'
1491
+ : currency.format(receipt.extracted.total)
1492
+ }}
1493
+ </dd>
1494
+ <dt class="text-gray-500">Tax</dt>
1495
+ <dd>
1496
+ {{
1497
+ receipt.extracted.tax === null
1498
+ ? '—'
1499
+ : currency.format(receipt.extracted.tax)
1500
+ }}
1501
+ </dd>
1502
+ <dt class="text-gray-500">Date</dt>
1503
+ <dd>
1504
+ {{ receipt.extracted.date ? longDate(receipt.extracted.date) : '—' }}
1505
+ </dd>
1506
+ <dt class="text-gray-500">Paid with</dt>
1507
+ <dd>{{ receipt.extracted.paymentMethod ?? '—' }}</dd>
1508
+ </dl>
1509
+ </section>
1510
+
1511
+ <!-- Properties: the peek is a workbench — the category is the same
1512
+ one-click cell as in the table. -->
1513
+ <section class="flex flex-col gap-1.5">
1514
+ <h3 class="text-xs font-semibold uppercase tracking-wide text-gray-500">
1515
+ Details
1516
+ </h3>
1517
+ <dl class="grid grid-cols-[auto_1fr] items-center gap-x-4 gap-y-1.5">
1518
+ <dt class="text-gray-500">Category</dt>
1519
+ <dd><CategoryCell :receipt="receipt" /></dd>
1520
+ <dt class="text-gray-500">Uploaded</dt>
1521
+ <dd>{{ longDate(receipt.uploadedAt) }}</dd>
1522
+ <dt class="text-gray-500">Report</dt>
1523
+ <dd>{{ receipt.reportName ?? 'Not on a report yet' }}</dd>
1524
+ </dl>
1525
+ </section>
1526
+
1527
+ <!-- Activity feed. -->
1528
+ <section class="flex flex-col gap-1.5">
1529
+ <h3 class="text-xs font-semibold uppercase tracking-wide text-gray-500">
1530
+ Activity
1531
+ </h3>
1532
+ <ul class="flex flex-col gap-2">
1533
+ <li
1534
+ v-for="entry in receipt.activity"
1535
+ :key="entry.id"
1536
+ class="flex gap-2"
1537
+ >
1538
+ <BbIcon
1539
+ class="mt-0.5 shrink-0 text-gray-400"
1540
+ :icon="entry.icon"
1541
+ size="14"
1542
+ />
1543
+ <div class="flex flex-col">
1544
+ <span>{{ entry.text }}</span>
1545
+ <span class="text-xs text-gray-500"
1546
+ >{{ entry.actor }} · {{ longDate(entry.at) }}</span
1547
+ >
1548
+ </div>
1549
+ </li>
1550
+ </ul>
1551
+ </section>
1552
+
1553
+ <!-- Act here, or leave for the original file. -->
1554
+ <footer class="mt-2 flex items-center gap-2 border-t pt-3">
1555
+ <BbButton
1556
+ v-if="receipt.status === 'draft'"
1557
+ prepend:icon="lucide:send"
1558
+ size="sm"
1559
+ variant="secondary"
1560
+ @click="() => ctx.submitReceipt(receipt!)"
1561
+ >
1562
+ Submit
1563
+ </BbButton>
1564
+ <BbButton
1565
+ append:icon="lucide:arrow-up-right"
1566
+ :href="`/receipts/${receipt.id}/file`"
1567
+ size="sm"
1568
+ variant="ghost"
1569
+ >
1570
+ Download original
1571
+ </BbButton>
1572
+ <BbButton
1573
+ v-if="receipt.status === 'draft'"
1574
+ class="ml-auto"
1575
+ prepend:icon="lucide:trash-2"
1576
+ size="sm"
1577
+ variant="destructive"
1578
+ @click="removeAndClose"
1579
+ >
1580
+ Remove
1581
+ </BbButton>
1582
+ </footer>
1583
+ </div>
1584
+
1585
+ <div v-else class="flex justify-center p-8">
1586
+ <BbSpinner />
1587
+ </div>
1588
+ </template>
1589
+
1590
+ <script setup lang="ts">
1591
+ import { ref, watchEffect } from 'vue';
1592
+ import { BbBadge, BbButton, BbIcon, BbSpinner } from 'bitboss-ui';
1593
+ import CategoryCell from './CategoryCell.vue';
1594
+ import { useUploadCenter } from './context';
1595
+ import { api } from '@/api';
1596
+ import type { ReceiptDetail } from '@/types';
1597
+
1598
+ const props = defineProps<{ receiptId: string }>();
1599
+
1600
+ const ctx = useUploadCenter();
1601
+
1602
+ // Re-fetches whenever the stack shows a different receipt; refreshKey makes
1603
+ // inline edits (category, submit) reflect here immediately.
1604
+ const receipt = ref<ReceiptDetail | null>(null);
1605
+ watchEffect(async () => {
1606
+ void ctx.refreshKey.value;
1607
+ receipt.value = await api.receipts.get(props.receiptId);
1608
+ });
1609
+
1610
+ // deleteReceipt resolves true only when the confirm was accepted — don't
1611
+ // close the peek on a cancelled dialog.
1612
+ const removeAndClose = async () => {
1613
+ if (!receipt.value) return;
1614
+ if (await ctx.deleteReceipt(receipt.value)) ctx.shell.close();
1615
+ };
1616
+
1617
+ const currency = new Intl.NumberFormat('en-US', {
1618
+ style: 'currency',
1619
+ currency: 'USD',
1620
+ });
1621
+ const longDate = (value: string) =>
1622
+ new Date(value).toLocaleDateString('en-US', {
1623
+ month: 'short',
1624
+ day: 'numeric',
1625
+ year: 'numeric',
1626
+ });
1627
+ </script>
1628
+ ```
1629
+
1630
+ ### MerchantPeek.vue
1631
+
1632
+ ```vue
1633
+ <!-- UploadCenter/MerchantPeek.vue -->
1634
+ <template>
1635
+ <div v-if="merchant" class="flex flex-col gap-4 text-sm">
1636
+ <header class="flex items-center gap-3">
1637
+ <div
1638
+ class="grid h-9 w-9 shrink-0 place-items-center rounded-[var(--bb-radius)] border"
1639
+ >
1640
+ <BbIcon class="text-gray-400" icon="lucide:store" size="18" />
1641
+ </div>
1642
+ <div class="flex flex-col">
1643
+ <h2 class="text-base font-semibold">{{ merchant.name }}</h2>
1644
+ <p class="text-xs text-gray-500">
1645
+ {{ merchant.defaultCategoryName }} · this year
1646
+ </p>
1647
+ </div>
1648
+ </header>
1649
+
1650
+ <!-- Stat strip. -->
1651
+ <div class="grid grid-cols-3 gap-2">
1652
+ <div class="rounded-[var(--bb-radius)] border p-2">
1653
+ <p class="text-xs text-gray-500">Total spent</p>
1654
+ <p class="font-semibold">{{ currency.format(merchant.totalSpent) }}</p>
1655
+ </div>
1656
+ <div class="rounded-[var(--bb-radius)] border p-2">
1657
+ <p class="text-xs text-gray-500">Receipts</p>
1658
+ <p class="font-semibold">{{ merchant.receiptCount }}</p>
1659
+ </div>
1660
+ <div class="rounded-[var(--bb-radius)] border p-2">
1661
+ <p class="text-xs text-gray-500">Average</p>
1662
+ <p class="font-semibold">
1663
+ {{ currency.format(merchant.averageAmount) }}
1664
+ </p>
1665
+ </div>
1666
+ </div>
1667
+
1668
+ <!-- Recent receipts: names drill down again — the stack keeps growing. -->
1669
+ <section class="flex flex-col gap-1.5">
1670
+ <h3 class="text-xs font-semibold uppercase tracking-wide text-gray-500">
1671
+ Recent receipts
1672
+ </h3>
1673
+ <ul class="flex flex-col">
1674
+ <li
1675
+ v-for="recent in merchant.recentReceipts"
1676
+ :key="recent.id"
1677
+ class="flex items-center justify-between gap-2 border-b py-1.5 last:border-b-0"
1678
+ >
1679
+ <BbButton
1680
+ size="sm"
1681
+ variant="link"
1682
+ @click="() => ctx.stackReceipt(recent.id)"
1683
+ >
1684
+ {{ recent.filename }}
1685
+ </BbButton>
1686
+ <BbBadge variant="outline">{{ recent.status }}</BbBadge>
1687
+ <span class="text-xs tabular-nums text-gray-500">
1688
+ {{ currency.format(recent.amount) }}
1689
+ </span>
1690
+ </li>
1691
+ </ul>
1692
+ </section>
1693
+
1694
+ <footer class="mt-2 flex items-center gap-2 border-t pt-3">
1695
+ <BbButton
1696
+ append:icon="lucide:arrow-up-right"
1697
+ size="sm"
1698
+ :to="`/expenses/receipts?merchant=${encodeURIComponent(merchant.name)}`"
1699
+ variant="ghost"
1700
+ >
1701
+ All receipts from {{ merchant.name }}
1702
+ </BbButton>
1703
+ </footer>
1704
+ </div>
1705
+
1706
+ <div v-else class="flex justify-center p-8">
1707
+ <BbSpinner />
1708
+ </div>
1709
+ </template>
1710
+
1711
+ <script setup lang="ts">
1712
+ import { ref, watchEffect } from 'vue';
1713
+ import { BbBadge, BbButton, BbIcon, BbSpinner } from 'bitboss-ui';
1714
+ import { useUploadCenter } from './context';
1715
+ import { api } from '@/api';
1716
+ import type { MerchantSummary } from '@/types';
1717
+
1718
+ const props = defineProps<{ merchantName: string }>();
1719
+
1720
+ const ctx = useUploadCenter();
1721
+
1722
+ const merchant = ref<MerchantSummary | null>(null);
1723
+ watchEffect(async () => {
1724
+ merchant.value = await api.merchants.get(props.merchantName);
1725
+ });
1726
+
1727
+ const currency = new Intl.NumberFormat('en-US', {
1728
+ style: 'currency',
1729
+ currency: 'USD',
1730
+ });
1731
+ </script>
1732
+ ```
1733
+
1734
+ ## Why it is built this way
1735
+
1736
+ - **The context coopts, leaves consume.** `shell`, `table` **and the
1737
+ category catalog** are joined once in `provideUploadCenter()`; thirteen
1738
+ components share the filters, the queue, selection, the peek stack and
1739
+ every action through one `useUploadCenter()` call. No leaf imports
1740
+ `@/api` or a store directly — even the query-aware merchant pill gets
1741
+ its provider (`ctx.searchMerchants`) from the context, so the page has
1742
+ exactly one import surface.
1743
+ - **Capture ≠ transfer.** `BbDropzone`'s documented contract is "these
1744
+ files are valid", nothing more: no request, no progress, no retry. So
1745
+ the dropzone leaf drains its model into `ctx.enqueueFiles()` and resets
1746
+ it, and the context owns the whole transfer lifecycle — one
1747
+ `AbortController` per file in a closure map (not render state), a
1748
+ progress callback writing into the reactive queue row, retry as a plain
1749
+ re-issue of the same upload. Constraint rejects never reach the model;
1750
+ they arrive as typed `@error` events that the leaf maps to sentences and
1751
+ feeds back through `errors` (the display is a round-trip by design).
1752
+ - **Progress ticks don't refetch.** The items function returns the _live_
1753
+ queue row objects ahead of the fetched page, so a progress mutation
1754
+ re-renders exactly the one cell reading it. Membership changes —
1755
+ enqueue, remove, upload completed — are the only events that bump
1756
+ `refreshKey`; a completed upload re-enters as a server draft with the
1757
+ OCR-extracted fields prefilled, which is the row's "done" feedback (no
1758
+ per-file success toast for a 15-file drop).
1759
+ - **Each editable cell type is its own leaf** — `MerchantCell`,
1760
+ `CategoryCell`, `AmountCell`, `DateCell` — never one `EditableCell` with
1761
+ a `type` prop. All four take exactly one data prop (`receipt`) and call
1762
+ one context action; the text/number cells hold a local draft (rung 1)
1763
+ with commit-on-blur/Enter and Esc-revert, the option/date cells commit
1764
+ on pick. Failed saves converge on the same path: `updateReceipt`
1765
+ refetches (reverting the cell to the server value) and toasts
1766
+ `destructive`.
1767
+ - **The table context is the paging and selection spine.**
1768
+ `useBbTableContext('receipts-table', { perPage: 25 })` seeds paging;
1769
+ `fetchRows` writes `table.total`; `BbPagination table-id` joins by id;
1770
+ the bulk bar reads `table.selected` with zero props from the table. The
1771
+ `selectable` predicate limits selection to server-side drafts, so bulk
1772
+ ids are always submittable receipt ids.
1773
+ - **Tabs carry `href` and live counts** (`?tab=drafts`) and the same table
1774
+ is the pane — outside Drafts the cell slots fall through to plain
1775
+ formatted text, so Submitted/Reimbursed are read-only views of the same
1776
+ columns rather than a second table component.
1777
+ - **`peekX` vs `stackX` is the whole stack grammar.** Filename →
1778
+ `peekReceipt` (replaces the stack); merchant name inside the peek →
1779
+ `stackMerchant` (pushes, back arrow appears); a recent receipt inside
1780
+ the merchant peek → `stackReceipt` (deeper still). The grammar lives in
1781
+ the context — a leaf cannot accidentally nuke the stack. The peek is a
1782
+ workbench: one-click category (the same `CategoryCell`), submit,
1783
+ download, confirm-guarded remove.
1784
+ - **Sizing:** topbar follows `md`-first (`compact` search at 28px flush
1785
+ beside the default-size primary); `sm` appears exactly where the
1786
+ doctrine allows — row actions, pills, peek footers, the bulk bar — and
1787
+ the one `xs` (inline Retry) sits inside a table cell, the densest
1788
+ surface on the page. **One `variant="primary"`** (Submit all, with its
1789
+ live count and auto-tracked loading). Destructive actions — single,
1790
+ bulk, in-peek — all ride `useConfirm` with the filename or count in the
1791
+ message.
1792
+
1793
+ ## Variations
1794
+
1795
+ - **Expense reports**: group receipts into named reports (a `reportId`
1796
+ column + a "Add to report" bulk action feeding a `BbSelectPopover` of
1797
+ open reports); the Submit-all primary becomes "Submit report".
1798
+ - **Policy checks**: server flags out-of-policy drafts
1799
+ (`receipt.policyWarning`); tint the row, badge the amount cell, and
1800
+ render a `BbAlert` above the table summarizing the count.
1801
+ - **Camera-first mobile**: keep `accept` image-heavy and rely on the
1802
+ native picker offering the camera; the dropzone slot collapses to a
1803
+ single "Snap a receipt" affordance under the mobile breakpoint.
1804
+ - **Auto-submit on high confidence**: when `extracted.confidence` ≥ 95 and
1805
+ all four fields resolved, submit server-side on upload and toast an
1806
+ undo — the Drafts tab then only holds receipts needing review.