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.
- package/LICENSE +21 -0
- package/README.md +244 -21
- package/bin/bitboss-ui-mcp.mjs +557 -0
- package/bin/bitboss-ui.mjs +626 -0
- package/dist/ai/BbAccordion.md +522 -113
- package/dist/ai/BbAlert.md +377 -197
- package/dist/ai/BbAsterisk.md +46 -0
- package/dist/ai/BbAvatar.md +454 -178
- package/dist/ai/BbBadge.md +695 -225
- package/dist/ai/BbBadgeButton.md +54 -0
- package/dist/ai/BbBaseButton.md +489 -0
- package/dist/ai/BbBaseCheckbox.md +49 -0
- package/dist/ai/BbBaseCheckboxGroup.md +64 -0
- package/dist/ai/BbBaseCheckboxIcon.md +174 -0
- package/dist/ai/BbBaseColorInput.md +64 -0
- package/dist/ai/BbBaseColorPalette.md +39 -0
- package/dist/ai/BbBaseDatePicker.md +42 -0
- package/dist/ai/BbBaseDatePickerInput.md +73 -0
- package/dist/ai/BbBaseInputContainer.md +48 -0
- package/dist/ai/BbBaseNumberInput.md +71 -0
- package/dist/ai/BbBaseRadio.md +46 -0
- package/dist/ai/BbBaseRadioGroup.md +63 -0
- package/dist/ai/BbBaseRadioIcon.md +187 -0
- package/dist/ai/BbBaseRating.md +51 -0
- package/dist/ai/BbBaseSelect.md +88 -0
- package/dist/ai/BbBaseSlider.md +56 -0
- package/dist/ai/BbBaseSwitch.md +49 -0
- package/dist/ai/BbBaseSwitchGroup.md +64 -0
- package/dist/ai/BbBaseSwitchIcon.md +184 -0
- package/dist/ai/BbBaseTag.md +68 -0
- package/dist/ai/BbBaseTextInput.md +75 -0
- package/dist/ai/BbBaseTextarea.md +62 -0
- package/dist/ai/BbBaseTimePickerInput.md +62 -0
- package/dist/ai/BbBreadcrumbs.md +542 -503
- package/dist/ai/BbButton.md +767 -636
- package/dist/ai/BbCheckbox.md +572 -254
- package/dist/ai/BbCheckboxGroup.md +561 -361
- package/dist/ai/BbCollapsible.md +419 -103
- package/dist/ai/BbColorInput.md +529 -323
- package/dist/ai/BbColorPalette.md +565 -330
- package/dist/ai/BbConfirm.md +612 -136
- package/dist/ai/BbConfirmPortal.md +28 -0
- package/dist/ai/BbDatePicker.md +244 -0
- package/dist/ai/BbDatePickerInput.md +706 -388
- package/dist/ai/BbDialog.md +770 -99
- package/dist/ai/BbDropdown.md +1054 -763
- package/dist/ai/BbDropdownButton.md +511 -615
- package/dist/ai/BbDropdownGroup.md +34 -0
- package/dist/ai/BbDropzone.md +1148 -436
- package/dist/ai/BbForm.md +239 -0
- package/dist/ai/BbIcon.md +379 -212
- package/dist/ai/BbIndicator.md +283 -0
- package/dist/ai/BbNumberInput.md +713 -355
- package/dist/ai/BbOffCanvas.md +875 -498
- package/dist/ai/BbPagination.md +483 -535
- package/dist/ai/BbPopover.md +583 -546
- package/dist/ai/BbProgress.md +456 -69
- package/dist/ai/BbRadio.md +343 -229
- package/dist/ai/BbRadioGroup.md +426 -353
- package/dist/ai/BbRating.md +361 -226
- package/dist/ai/BbSelect.md +1380 -536
- package/dist/ai/BbSelectPopover.md +1240 -1579
- package/dist/ai/BbSlider.md +478 -257
- package/dist/ai/BbSmoothHeight.md +472 -139
- package/dist/ai/BbSpinner.md +718 -131
- package/dist/ai/BbSwitch.md +549 -119
- package/dist/ai/BbSwitchGroup.md +503 -214
- package/dist/ai/BbTable.md +1956 -2358
- package/dist/ai/BbTabs.md +1113 -0
- package/dist/ai/BbTabsList.md +29 -0
- package/dist/ai/BbTabsPanes.md +27 -0
- package/dist/ai/BbTabsRoot.md +57 -0
- package/dist/ai/BbTag.md +393 -292
- package/dist/ai/BbTextInput.md +852 -333
- package/dist/ai/BbTextarea.md +836 -255
- package/dist/ai/BbTimePicker.md +231 -0
- package/dist/ai/BbTimePickerInput.md +196 -0
- package/dist/ai/BbToast.md +624 -196
- package/dist/ai/BbToastPortal.md +28 -0
- package/dist/ai/BbTooltip.md +443 -346
- package/dist/ai/BbTree.md +984 -235
- package/dist/ai/ChipsBox.md +27 -199
- package/dist/ai/ClearableButton.md +21 -55
- package/dist/ai/CommaBox.md +25 -200
- package/dist/ai/CommonInputWrapper.md +42 -0
- package/dist/ai/CommonPopover.md +30 -510
- package/dist/ai/ErrorIcon.md +19 -56
- package/dist/ai/FlatListBox.md +35 -379
- package/dist/ai/GroupedListBox.md +37 -535
- package/dist/ai/GuidesComponent.md +21 -0
- package/dist/ai/ListBox.md +38 -231
- package/dist/ai/OptionsContainer.md +34 -253
- package/dist/ai/WarningIcon.md +21 -0
- package/dist/ai/components.json +15883 -0
- package/dist/ai/composables/useBbConfig.md +80 -0
- package/dist/ai/composables/useBbFormContext.md +110 -0
- package/dist/ai/composables/useBbTableContext.md +164 -0
- package/dist/ai/composables/useBbTabsContext.md +118 -0
- package/dist/ai/composables/useBroadcastChannelInstance.md +97 -0
- package/dist/ai/composables/useConfirm.md +306 -0
- package/dist/ai/composables/useCountdown.md +84 -0
- package/dist/ai/composables/useId.md +60 -0
- package/dist/ai/composables/useMobile.md +85 -0
- package/dist/ai/composables/useToast.md +230 -0
- package/dist/ai/guides/agent-contract.md +108 -0
- package/dist/ai/guides/ai-router.md +111 -0
- package/dist/ai/guides/app-layout.md +295 -0
- package/dist/ai/guides/coherence-playbook.md +136 -0
- package/dist/ai/guides/component-picker.md +195 -0
- package/dist/ai/guides/design-language.md +461 -0
- package/dist/ai/guides/design-tokens.md +424 -0
- package/dist/ai/guides/fetch-items-playbook.md +161 -0
- package/dist/ai/guides/floating-bottom-panel.md +191 -0
- package/dist/ai/guides/icons-policy.md +257 -0
- package/dist/ai/guides/inertia-helpers.md +1394 -0
- package/dist/ai/guides/inline-edit-playbook.md +258 -0
- package/dist/ai/guides/installation-and-plugin-setup.md +377 -0
- package/dist/ai/guides/migration/components/bb-alert.md +37 -0
- package/dist/ai/guides/migration/components/bb-avatar.md +24 -0
- package/dist/ai/guides/migration/components/bb-badge.md +110 -0
- package/dist/ai/guides/migration/components/bb-breadcrumbs.md +26 -0
- package/dist/ai/guides/migration/components/bb-button.md +55 -0
- package/dist/ai/guides/migration/components/bb-checkbox-group.md +54 -0
- package/dist/ai/guides/migration/components/bb-checkbox.md +45 -0
- package/dist/ai/guides/migration/components/bb-chip.md +35 -0
- package/dist/ai/guides/migration/components/bb-collapsible.md +26 -0
- package/dist/ai/guides/migration/components/bb-color-input.md +23 -0
- package/dist/ai/guides/migration/components/bb-color-palette.md +31 -0
- package/dist/ai/guides/migration/components/bb-date-picker-input.md +84 -0
- package/dist/ai/guides/migration/components/bb-dialog.md +46 -0
- package/dist/ai/guides/migration/components/bb-dropdown-button.md +31 -0
- package/dist/ai/guides/migration/components/bb-dropdown.md +36 -0
- package/dist/ai/guides/migration/components/bb-dropzone.md +27 -0
- package/dist/ai/guides/migration/components/bb-icon.md +27 -0
- package/dist/ai/guides/migration/components/bb-off-canvas.md +25 -0
- package/dist/ai/guides/migration/components/bb-offcanvas.md +54 -0
- package/dist/ai/guides/migration/components/bb-pagination.md +24 -0
- package/dist/ai/guides/migration/components/bb-popover.md +52 -0
- package/dist/ai/guides/migration/components/bb-rating.md +24 -0
- package/dist/ai/guides/migration/components/bb-select-popover.md +58 -0
- package/dist/ai/guides/migration/components/bb-select.md +68 -0
- package/dist/ai/guides/migration/components/bb-slider.md +25 -0
- package/dist/ai/guides/migration/components/bb-smooth-height.md +45 -0
- package/dist/ai/guides/migration/components/bb-spinner.md +23 -0
- package/dist/ai/guides/migration/components/bb-table.md +66 -0
- package/dist/ai/guides/migration/components/bb-tabs.md +47 -0
- package/dist/ai/guides/migration/components/bb-tag.md +29 -0
- package/dist/ai/guides/migration/components/bb-text-input.md +37 -0
- package/dist/ai/guides/migration/components/bb-toast.md +47 -0
- package/dist/ai/guides/migration/components/bb-tooltip.md +34 -0
- package/dist/ai/guides/migration/components/bb-tree.md +77 -0
- package/dist/ai/guides/migration/components/use-confirm.md +46 -0
- package/dist/ai/guides/migration/v2-to-v3.md +649 -0
- package/dist/ai/guides/options-items-playbook.md +222 -0
- package/dist/ai/guides/page-shell.md +314 -0
- package/dist/ai/guides/validated-forms.md +177 -0
- package/dist/ai/index.md +156 -32
- package/dist/ai/recipes/inertia/approvals-inbox.md +1598 -0
- package/dist/ai/recipes/inertia/inline-edit-workspace.md +1733 -0
- package/dist/ai/recipes/inertia/onboarding.md +1765 -0
- package/dist/ai/recipes/inertia/ownership-atlas.md +1281 -0
- package/dist/ai/recipes/inertia/record-form.md +1442 -0
- package/dist/ai/recipes/inertia/records-workspace.md +1328 -0
- package/dist/ai/recipes/inertia/upload-center.md +1926 -0
- package/dist/ai/recipes/inertia/wizard-form.md +1477 -0
- package/dist/ai/recipes/nuxt/approvals-inbox.md +1561 -0
- package/dist/ai/recipes/nuxt/inline-edit-workspace.md +1690 -0
- package/dist/ai/recipes/nuxt/onboarding.md +1698 -0
- package/dist/ai/recipes/nuxt/record-form.md +1456 -0
- package/dist/ai/recipes/nuxt/records-workspace.md +1314 -0
- package/dist/ai/recipes/nuxt/upload-center.md +1847 -0
- package/dist/ai/recipes/nuxt/wizard-form.md +1486 -0
- package/dist/ai/recipes/vue/approvals-inbox.md +1479 -0
- package/dist/ai/recipes/vue/inline-edit-workspace.md +1581 -0
- package/dist/ai/recipes/vue/onboarding.md +1653 -0
- package/dist/ai/recipes/vue/record-form.md +1540 -0
- package/dist/ai/recipes/vue/records-workspace.md +1230 -0
- package/dist/ai/recipes/vue/upload-center.md +1806 -0
- package/dist/ai/recipes/vue/wizard-form.md +1418 -0
- package/dist/ai/source/BbAccordion.md +122 -0
- package/dist/ai/source/BbAlert.md +396 -0
- package/dist/ai/source/BbAsterisk.md +32 -0
- package/dist/ai/source/BbAvatar.md +256 -0
- package/dist/ai/source/BbBadge.md +560 -0
- package/dist/ai/source/BbBadgeButton.md +490 -0
- package/dist/ai/source/BbBaseButton.md +682 -0
- package/dist/ai/source/BbBaseCheckbox.md +459 -0
- package/dist/ai/source/BbBaseCheckboxGroup.md +554 -0
- package/dist/ai/source/BbBaseCheckboxIcon.md +201 -0
- package/dist/ai/source/BbBaseColorInput.md +413 -0
- package/dist/ai/source/BbBaseColorPalette.md +934 -0
- package/dist/ai/source/BbBaseDatePicker.md +1001 -0
- package/dist/ai/source/BbBaseDatePickerInput.md +1781 -0
- package/dist/ai/source/BbBaseInputContainer.md +1148 -0
- package/dist/ai/source/BbBaseNumberInput.md +615 -0
- package/dist/ai/source/BbBaseRadio.md +377 -0
- package/dist/ai/source/BbBaseRadioGroup.md +499 -0
- package/dist/ai/source/BbBaseRadioIcon.md +153 -0
- package/dist/ai/source/BbBaseRating.md +573 -0
- package/dist/ai/source/BbBaseSelect.md +895 -0
- package/dist/ai/source/BbBaseSlider.md +1085 -0
- package/dist/ai/source/BbBaseSwitch.md +246 -0
- package/dist/ai/source/BbBaseSwitchGroup.md +302 -0
- package/dist/ai/source/BbBaseSwitchIcon.md +206 -0
- package/dist/ai/source/BbBaseTag.md +688 -0
- package/dist/ai/source/BbBaseTextInput.md +511 -0
- package/dist/ai/source/BbBaseTextarea.md +480 -0
- package/dist/ai/source/BbBaseTimePickerInput.md +1013 -0
- package/dist/ai/source/BbBreadcrumbs.md +811 -0
- package/dist/ai/source/BbButton.md +990 -0
- package/dist/ai/source/BbCheckbox.md +319 -0
- package/dist/ai/source/BbCheckboxGroup.md +412 -0
- package/dist/ai/source/BbCollapsible.md +133 -0
- package/dist/ai/source/BbColorInput.md +315 -0
- package/dist/ai/source/BbColorPalette.md +361 -0
- package/dist/ai/source/BbConfirm.md +173 -0
- package/dist/ai/source/BbConfirmPortal.md +74 -0
- package/dist/ai/source/BbDatePicker.md +725 -0
- package/dist/ai/source/BbDatePickerInput.md +518 -0
- package/dist/ai/source/BbDialog.md +812 -0
- package/dist/ai/source/BbDropdown.md +2369 -0
- package/dist/ai/source/BbDropdownButton.md +313 -0
- package/dist/ai/source/BbDropdownGroup.md +1249 -0
- package/dist/ai/source/BbDropzone.md +749 -0
- package/dist/ai/source/BbForm.md +100 -0
- package/dist/ai/source/BbIcon.md +212 -0
- package/dist/ai/source/BbIndicator.md +298 -0
- package/dist/ai/source/BbNumberInput.md +365 -0
- package/dist/ai/source/BbOffCanvas.md +1260 -0
- package/dist/ai/source/BbPagination.md +829 -0
- package/dist/ai/source/BbPopover.md +853 -0
- package/dist/ai/source/BbProgress.md +140 -0
- package/dist/ai/source/BbRadio.md +294 -0
- package/dist/ai/source/BbRadioGroup.md +401 -0
- package/dist/ai/source/BbRating.md +362 -0
- package/dist/ai/source/BbSelect.md +681 -0
- package/dist/ai/source/BbSelectPopover.md +2209 -0
- package/dist/ai/source/BbSlider.md +371 -0
- package/dist/ai/source/BbSmoothHeight.md +261 -0
- package/dist/ai/source/BbSpinner.md +127 -0
- package/dist/ai/source/BbSwitch.md +175 -0
- package/dist/ai/source/BbSwitchGroup.md +240 -0
- package/dist/ai/source/BbTable.md +3348 -0
- package/dist/ai/source/BbTabs.md +403 -0
- package/dist/ai/source/BbTabsList.md +578 -0
- package/dist/ai/source/BbTabsPanes.md +368 -0
- package/dist/ai/source/BbTabsRoot.md +372 -0
- package/dist/ai/source/BbTag.md +383 -0
- package/dist/ai/source/BbTextInput.md +345 -0
- package/dist/ai/source/BbTextarea.md +330 -0
- package/dist/ai/source/BbTimePicker.md +591 -0
- package/dist/ai/source/BbTimePickerInput.md +367 -0
- package/dist/ai/source/BbToast.md +524 -0
- package/dist/ai/source/BbToastPortal.md +482 -0
- package/dist/ai/source/BbTooltip.md +508 -0
- package/dist/ai/source/BbTree.md +319 -0
- package/dist/ai/source/ChipsBox.md +201 -0
- package/dist/ai/source/ClearableButton.md +70 -0
- package/dist/ai/source/CommaBox.md +202 -0
- package/dist/ai/source/CommonInputWrapper.md +554 -0
- package/dist/ai/source/CommonPopover.md +606 -0
- package/dist/ai/source/ErrorIcon.md +43 -0
- package/dist/ai/source/FlatListBox.md +396 -0
- package/dist/ai/source/GroupedListBox.md +540 -0
- package/dist/ai/source/GuidesComponent.md +383 -0
- package/dist/ai/source/ListBox.md +238 -0
- package/dist/ai/source/OptionsContainer.md +191 -0
- package/dist/ai/source/WarningIcon.md +47 -0
- package/dist/alert-variants.d.ts +12 -0
- package/dist/assets/css/reset.css_inline.js +4 -0
- package/dist/assets/svgs/alert.svg_raw.js +4 -0
- package/dist/assets/svgs/calendar.svg_raw.js +4 -0
- package/dist/assets/svgs/check_stroke.svg_raw.js +4 -0
- package/dist/assets/svgs/chevron_down.svg_raw.js +4 -0
- package/dist/assets/svgs/chevron_right.svg_raw.js +4 -0
- package/dist/assets/svgs/clear.svg_raw.js +4 -0
- package/dist/assets/svgs/clock.svg_raw.js +4 -0
- package/dist/assets/svgs/error.svg_raw.js +4 -0
- package/dist/assets/svgs/search.svg_raw.js +4 -0
- package/dist/assets/svgs/sort.svg_raw.js +4 -0
- package/dist/assets/svgs/spinner.svg_raw.js +4 -0
- package/dist/assets/svgs/user.svg_raw.js +4 -0
- package/dist/badge-variants.d.ts +18 -0
- package/dist/button-variants.d.ts +15 -0
- package/dist/components/BbAccordion/BbAccordion.vue.d.ts +9 -3
- package/dist/components/BbAccordion/BbAccordion.vue.js +6 -0
- package/dist/components/BbAccordion/BbAccordion.vue_vue_type_script_setup_true_lang.js +66 -0
- package/dist/components/BbAccordion/types.d.ts +10 -7
- package/dist/components/BbAlert/BbAlert.vue.d.ts +12 -3
- package/dist/components/BbAlert/BbAlert.vue.js +6 -0
- package/dist/components/BbAlert/BbAlert.vue_vue_type_script_setup_true_lang.js +65 -0
- package/dist/components/BbAlert/types.d.ts +51 -12
- package/dist/components/BbAsterisk/BbAsterisk.vue.d.ts +3 -0
- package/dist/components/BbAsterisk/BbAsterisk.vue.js +6 -0
- package/dist/components/BbAsterisk/BbAsterisk.vue_vue_type_script_setup_true_lang.js +13 -0
- package/dist/components/BbAvatar/BbAvatar.vue.d.ts +5 -0
- package/dist/components/BbAvatar/BbAvatar.vue.js +6 -0
- package/dist/components/BbAvatar/BbAvatar.vue_vue_type_script_setup_true_lang.js +78 -0
- package/dist/components/BbAvatar/types.d.ts +4 -5
- package/dist/components/BbBadge/BadgeAppendIcon.vue.d.ts +3 -0
- package/dist/components/BbBadge/BadgeAppendIcon.vue.js +5 -0
- package/dist/components/BbBadge/BadgeAppendIcon.vue_vue_type_script_setup_true_lang.js +22 -0
- package/dist/components/BbBadge/BadgeBodyContent.vue.d.ts +15 -0
- package/dist/components/BbBadge/BadgeBodyContent.vue.js +5 -0
- package/dist/components/BbBadge/BadgeBodyContent.vue_vue_type_script_setup_true_lang.js +34 -0
- package/dist/components/BbBadge/BbBadge.vue.d.ts +8 -1
- package/dist/components/BbBadge/BbBadge.vue.js +6 -0
- package/dist/components/BbBadge/BbBadge.vue_vue_type_script_setup_true_lang.js +83 -0
- package/dist/components/BbBadge/BbBadgeButton.vue.d.ts +12 -0
- package/dist/components/BbBadge/BbBadgeButton.vue.js +5 -0
- package/dist/components/BbBadge/BbBadgeButton.vue_vue_type_script_setup_true_lang.js +54 -0
- package/dist/components/BbBadge/badgeButtonContext.d.ts +27 -0
- package/dist/components/BbBadge/badgeButtonContext.js +5 -0
- package/dist/components/BbBadge/types.d.ts +61 -16
- package/dist/components/BbBaseButton/BbBaseButton.vue.d.ts +13 -0
- package/dist/components/BbBaseButton/BbBaseButton.vue.js +6 -0
- package/dist/components/BbBaseButton/BbBaseButton.vue_vue_type_script_setup_true_lang.js +171 -0
- package/dist/components/BbBaseButton/RouterComponent.vue.js +5 -0
- package/dist/components/BbBaseButton/RouterComponent.vue_vue_type_script_setup_true_lang.js +28 -0
- package/dist/components/BbBaseButton/types.d.ts +191 -0
- package/dist/components/BbBaseButton/types.js +33 -0
- package/dist/components/BbBaseCheckbox/BbBaseCheckbox.vue.d.ts +40 -0
- package/dist/components/BbBaseCheckbox/BbBaseCheckbox.vue.js +6 -0
- package/dist/components/BbBaseCheckbox/BbBaseCheckbox.vue_vue_type_script_setup_true_lang.js +145 -0
- package/dist/components/BbBaseCheckbox/types.d.ts +222 -0
- package/dist/components/BbBaseCheckboxGroup/BbBaseCheckboxGroup.vue.d.ts +19 -0
- package/dist/components/BbBaseCheckboxGroup/BbBaseCheckboxGroup.vue.js +6 -0
- package/dist/components/BbBaseCheckboxGroup/BbBaseCheckboxGroup.vue_vue_type_script_setup_true_lang.js +190 -0
- package/dist/components/BbBaseCheckboxGroup/types.d.ts +257 -0
- package/dist/components/BbBaseCheckboxIcon/BbBaseCheckboxIcon.vue.d.ts +4 -0
- package/dist/components/BbBaseCheckboxIcon/BbBaseCheckboxIcon.vue.js +6 -0
- package/dist/components/BbBaseCheckboxIcon/BbBaseCheckboxIcon.vue_vue_type_script_setup_true_lang.js +43 -0
- package/dist/components/BbBaseCheckboxIcon/types.d.ts +47 -0
- package/dist/components/BbBaseColorInput/BbBaseColorInput.vue.d.ts +42 -0
- package/dist/components/BbBaseColorInput/BbBaseColorInput.vue.js +6 -0
- package/dist/components/BbBaseColorInput/BbBaseColorInput.vue_vue_type_script_setup_true_lang.js +178 -0
- package/dist/components/BbBaseColorInput/types.d.ts +207 -0
- package/dist/components/BbBaseColorPalette/BbBaseColorPalette.vue.d.ts +13 -0
- package/dist/components/BbBaseColorPalette/BbBaseColorPalette.vue.js +6 -0
- package/dist/components/BbBaseColorPalette/BbBaseColorPalette.vue_vue_type_script_setup_true_lang.js +395 -0
- package/dist/components/BbBaseColorPalette/types.d.ts +40 -0
- package/dist/components/BbBaseDatePicker/BbBaseDatePicker.vue.js +6 -0
- package/dist/components/BbBaseDatePicker/BbBaseDatePicker.vue_vue_type_script_setup_true_lang.js +300 -0
- package/dist/components/BbBaseDatePicker/BbBaseDatePickerInputDaySelector.vue.d.ts +44 -0
- package/dist/components/BbBaseDatePicker/BbBaseDatePickerInputDaySelector.vue.js +5 -0
- package/dist/components/BbBaseDatePicker/BbBaseDatePickerInputDaySelector.vue_vue_type_script_setup_true_lang.js +310 -0
- package/dist/components/BbBaseDatePicker/BbBaseDatePickerMonthSelector.vue.d.ts +5 -0
- package/dist/components/BbBaseDatePicker/BbBaseDatePickerMonthSelector.vue.js +5 -0
- package/dist/components/BbBaseDatePicker/BbBaseDatePickerMonthSelector.vue_vue_type_script_setup_true_lang.js +63 -0
- package/dist/components/BbBaseDatePicker/BbBaseDatePickerYearSelector.vue.d.ts +5 -0
- package/dist/components/BbBaseDatePicker/BbBaseDatePickerYearSelector.vue.js +5 -0
- package/dist/components/BbBaseDatePicker/BbBaseDatePickerYearSelector.vue_vue_type_script_setup_true_lang.js +75 -0
- package/dist/components/BbBaseDatePicker/typeahead.d.ts +112 -0
- package/dist/components/BbBaseDatePicker/typeahead.js +37 -0
- package/dist/components/BbBaseDatePicker/types.d.ts +97 -0
- package/dist/components/BbBaseDatePicker/useDatePickerContext.d.ts +58 -0
- package/dist/components/BbBaseDatePicker/useDatePickerContext.js +11 -0
- package/dist/components/BbBaseDatePickerInput/BbBaseDatePickerInput.vue.d.ts +30 -0
- package/dist/components/BbBaseDatePickerInput/BbBaseDatePickerInput.vue.js +6 -0
- package/dist/components/BbBaseDatePickerInput/BbBaseDatePickerInput.vue_vue_type_script_setup_true_lang.js +713 -0
- package/dist/components/BbBaseDatePickerInput/BbBaseDatePickerTimeSelector.vue.d.ts +30 -0
- package/dist/components/BbBaseDatePickerInput/BbBaseDatePickerTimeSelector.vue.js +6 -0
- package/dist/components/BbBaseDatePickerInput/BbBaseDatePickerTimeSelector.vue_vue_type_script_setup_true_lang.js +204 -0
- package/dist/components/BbBaseDatePickerInput/types.d.ts +309 -0
- package/dist/components/BbBaseInputContainer/BbBaseInputContainer.vue.d.ts +17 -0
- package/dist/components/BbBaseInputContainer/BbBaseInputContainer.vue.js +6 -0
- package/dist/components/BbBaseInputContainer/BbBaseInputContainer.vue_vue_type_script_setup_true_lang.js +184 -0
- package/dist/components/BbBaseInputContainer/types.d.ts +185 -0
- package/dist/components/BbBaseNumberInput/BbBaseNumberInput.vue.d.ts +52 -0
- package/dist/components/BbBaseNumberInput/BbBaseNumberInput.vue.js +6 -0
- package/dist/components/BbBaseNumberInput/BbBaseNumberInput.vue_vue_type_script_setup_true_lang.js +211 -0
- package/dist/components/BbBaseNumberInput/types.d.ts +211 -0
- package/dist/components/BbBaseRadio/BbBaseRadio.vue.d.ts +33 -0
- package/dist/components/BbBaseRadio/BbBaseRadio.vue.js +6 -0
- package/dist/components/BbBaseRadio/BbBaseRadio.vue_vue_type_script_setup_true_lang.js +114 -0
- package/dist/components/BbBaseRadio/types.d.ts +179 -0
- package/dist/components/BbBaseRadioGroup/BbBaseRadioGroup.vue.d.ts +19 -0
- package/dist/components/BbBaseRadioGroup/BbBaseRadioGroup.vue.js +6 -0
- package/dist/components/BbBaseRadioGroup/BbBaseRadioGroup.vue_vue_type_script_setup_true_lang.js +172 -0
- package/dist/components/BbBaseRadioGroup/types.d.ts +215 -0
- package/dist/components/BbBaseRadioIcon/BbBaseRadioIcon.vue.d.ts +4 -0
- package/dist/components/BbBaseRadioIcon/BbBaseRadioIcon.vue.js +6 -0
- package/dist/components/BbBaseRadioIcon/BbBaseRadioIcon.vue_vue_type_script_setup_true_lang.js +28 -0
- package/dist/components/BbBaseRadioIcon/types.d.ts +41 -0
- package/dist/components/BbBaseRating/BbBaseRating.vue.d.ts +38 -0
- package/dist/components/BbBaseRating/BbBaseRating.vue.js +6 -0
- package/dist/components/BbBaseRating/BbBaseRating.vue_vue_type_script_setup_true_lang.js +184 -0
- package/dist/components/BbBaseRating/types.d.ts +168 -0
- package/dist/components/BbBaseSelect/BbBaseSelect.vue.d.ts +19 -0
- package/dist/components/BbBaseSelect/BbBaseSelect.vue.js +6 -0
- package/dist/components/BbBaseSelect/BbBaseSelect.vue_vue_type_script_setup_true_lang.js +307 -0
- package/dist/components/BbBaseSelect/types.d.ts +294 -0
- package/dist/components/BbBaseSlider/BbBaseSlider.vue.d.ts +35 -0
- package/dist/components/BbBaseSlider/BbBaseSlider.vue.js +6 -0
- package/dist/components/BbBaseSlider/BbBaseSlider.vue_vue_type_script_setup_true_lang.js +324 -0
- package/dist/components/BbBaseSlider/types.d.ts +200 -0
- package/dist/components/BbBaseSwitch/BbBaseSwitch.vue.d.ts +35 -0
- package/dist/components/BbBaseSwitch/BbBaseSwitch.vue.js +6 -0
- package/dist/components/BbBaseSwitch/BbBaseSwitch.vue_vue_type_script_setup_true_lang.js +146 -0
- package/dist/components/BbBaseSwitch/types.d.ts +10 -0
- package/dist/components/BbBaseSwitchGroup/BbBaseSwitchGroup.vue.d.ts +19 -0
- package/dist/components/BbBaseSwitchGroup/BbBaseSwitchGroup.vue.js +6 -0
- package/dist/components/BbBaseSwitchGroup/BbBaseSwitchGroup.vue_vue_type_script_setup_true_lang.js +190 -0
- package/dist/components/BbBaseSwitchGroup/types.d.ts +8 -0
- package/dist/components/BbBaseSwitchIcon/BbBaseSwitchIcon.vue.d.ts +4 -0
- package/dist/components/BbBaseSwitchIcon/BbBaseSwitchIcon.vue.js +6 -0
- package/dist/components/BbBaseSwitchIcon/BbBaseSwitchIcon.vue_vue_type_script_setup_true_lang.js +30 -0
- package/dist/components/BbBaseSwitchIcon/types.d.ts +48 -0
- package/dist/components/BbBaseTag/BbBaseTag.vue.d.ts +50 -0
- package/dist/components/BbBaseTag/BbBaseTag.vue.js +6 -0
- package/dist/components/BbBaseTag/BbBaseTag.vue_vue_type_script_setup_true_lang.js +266 -0
- package/dist/components/BbBaseTag/types.d.ts +160 -0
- package/dist/components/BbBaseTextInput/BbBaseTextInput.vue.d.ts +45 -0
- package/dist/components/BbBaseTextInput/BbBaseTextInput.vue.js +6 -0
- package/dist/components/BbBaseTextInput/BbBaseTextInput.vue_vue_type_script_setup_true_lang.js +200 -0
- package/dist/components/BbBaseTextInput/types.d.ts +209 -0
- package/dist/components/BbBaseTextarea/BbBaseTextarea.vue.d.ts +39 -0
- package/dist/components/BbBaseTextarea/BbBaseTextarea.vue.js +6 -0
- package/dist/components/BbBaseTextarea/BbBaseTextarea.vue_vue_type_script_setup_true_lang.js +175 -0
- package/dist/components/BbBaseTextarea/types.d.ts +170 -0
- package/dist/components/BbBaseTimePickerInput/BbBaseTimePickerInput.vue.d.ts +27 -0
- package/dist/components/BbBaseTimePickerInput/BbBaseTimePickerInput.vue.js +6 -0
- package/dist/components/BbBaseTimePickerInput/BbBaseTimePickerInput.vue_vue_type_script_setup_true_lang.js +517 -0
- package/dist/components/BbBaseTimePickerInput/types.d.ts +151 -0
- package/dist/components/BbBreadcrumbs/BbBreadcrumbs.vue.d.ts +0 -1
- package/dist/components/BbBreadcrumbs/BbBreadcrumbs.vue.js +6 -0
- package/dist/components/BbBreadcrumbs/BbBreadcrumbs.vue_vue_type_script_setup_true_lang.js +224 -0
- package/dist/components/BbBreadcrumbs/estimateBreadcrumbItemWidth.js +47 -0
- package/dist/components/BbBreadcrumbs/types.d.ts +33 -22
- package/dist/components/BbButton/BbButton.vue.d.ts +6 -5
- package/dist/components/BbButton/BbButton.vue.js +6 -0
- package/dist/components/BbButton/BbButton.vue_vue_type_script_setup_true_lang.js +177 -0
- package/dist/components/BbButton/types.d.ts +48 -47
- package/dist/components/BbCheckbox/BbCheckbox.vue.d.ts +4 -3
- package/dist/components/BbCheckbox/BbCheckbox.vue.js +6 -0
- package/dist/components/BbCheckbox/BbCheckbox.vue_vue_type_script_setup_true_lang.js +146 -0
- package/dist/components/BbCheckbox/types.d.ts +24 -10
- package/dist/components/BbCheckboxGroup/BbCheckboxGroup.vue.d.ts +2 -13
- package/dist/components/BbCheckboxGroup/BbCheckboxGroup.vue.js +6 -0
- package/dist/components/BbCheckboxGroup/BbCheckboxGroup.vue_vue_type_script_setup_true_lang.js +190 -0
- package/dist/components/BbCheckboxGroup/types.d.ts +44 -23
- package/dist/components/BbCollapsible/BbCollapsible.vue.d.ts +2 -1
- package/dist/components/BbCollapsible/BbCollapsible.vue.js +6 -0
- package/dist/components/BbCollapsible/BbCollapsible.vue_vue_type_script_setup_true_lang.js +31 -0
- package/dist/components/BbCollapsible/types.d.ts +10 -9
- package/dist/components/BbColorInput/BbColorInput.vue.d.ts +10 -1
- package/dist/components/BbColorInput/BbColorInput.vue.js +6 -0
- package/dist/components/BbColorInput/BbColorInput.vue_vue_type_script_setup_true_lang.js +177 -0
- package/dist/components/BbColorInput/types.d.ts +37 -11
- package/dist/components/BbColorPalette/BbColorPalette.vue.d.ts +5 -8
- package/dist/components/BbColorPalette/BbColorPalette.vue.js +5 -0
- package/dist/components/BbColorPalette/BbColorPalette.vue_vue_type_script_setup_true_lang.js +125 -0
- package/dist/components/BbColorPalette/types.d.ts +66 -53
- package/dist/components/BbConfirm/BbConfirm.vue.js +6 -0
- package/dist/components/BbConfirm/BbConfirm.vue_vue_type_script_setup_true_lang.js +130 -0
- package/dist/components/BbConfirm/BbConfirmPortal.vue.d.ts +5 -6
- package/dist/components/BbConfirm/BbConfirmPortal.vue.js +5 -0
- package/dist/components/BbConfirm/BbConfirmPortal.vue_vue_type_script_setup_true_lang.js +19 -0
- package/dist/components/BbDatePicker/BbDatePicker.vue.d.ts +37 -0
- package/dist/components/BbDatePicker/BbDatePicker.vue.js +6 -0
- package/dist/components/BbDatePicker/BbDatePicker.vue_vue_type_script_setup_true_lang.js +319 -0
- package/dist/components/BbDatePicker/types.d.ts +155 -0
- package/dist/components/BbDatePickerInput/BbDatePickerInput.vue.d.ts +3 -1
- package/dist/components/BbDatePickerInput/BbDatePickerInput.vue.js +6 -0
- package/dist/components/BbDatePickerInput/BbDatePickerInput.vue_vue_type_script_setup_true_lang.js +179 -0
- package/dist/components/BbDatePickerInput/types.d.ts +127 -16
- package/dist/components/BbDialog/BbDialog.vue.d.ts +8 -6
- package/dist/components/BbDialog/BbDialog.vue.js +6 -0
- package/dist/components/BbDialog/BbDialog.vue_vue_type_script_setup_true_lang.js +214 -0
- package/dist/components/BbDialog/types.d.ts +146 -1
- package/dist/components/BbDialog/useDialogStack.d.ts +5 -0
- package/dist/components/BbDialog/useDialogStack.js +20 -0
- package/dist/components/BbDropdown/AdaptiveDropdown.vue.d.ts +18 -0
- package/dist/components/BbDropdown/AdaptiveDropdown.vue.js +6 -0
- package/dist/components/BbDropdown/AdaptiveDropdown.vue_vue_type_script_setup_true_lang.js +116 -0
- package/dist/components/BbDropdown/BbDropdown.vue.d.ts +14 -7
- package/dist/components/BbDropdown/BbDropdown.vue.js +6 -0
- package/dist/components/BbDropdown/BbDropdown.vue_vue_type_script_setup_true_lang.js +560 -0
- package/dist/components/BbDropdown/BbDropdownGroup.vue.d.ts +44 -0
- package/dist/components/BbDropdown/BbDropdownGroup.vue.js +5 -0
- package/dist/components/BbDropdown/BbDropdownGroup.vue_vue_type_script_setup_true_lang.js +36 -0
- package/dist/components/BbDropdown/BbDropdownList.vue.d.ts +27 -0
- package/dist/components/BbDropdown/BbDropdownList.vue.js +6 -0
- package/dist/components/BbDropdown/BbDropdownList.vue_vue_type_script_setup_true_lang.js +464 -0
- package/dist/components/BbDropdown/DropdownPipelineResolver.vue.d.ts +16 -0
- package/dist/components/BbDropdown/DropdownPipelineResolver.vue.js +5 -0
- package/dist/components/BbDropdown/DropdownPipelineResolver.vue_vue_type_script_setup_true_lang.js +168 -0
- package/dist/components/BbDropdown/normalizeGroups.d.ts +18 -0
- package/dist/components/BbDropdown/normalizeGroups.js +46 -0
- package/dist/components/BbDropdown/types.d.ts +457 -45
- package/dist/components/BbDropdown/types.js +4 -0
- package/dist/components/BbDropdown/useDropdownContext.d.ts +89 -0
- package/dist/components/BbDropdown/useDropdownContext.js +9 -0
- package/dist/components/BbDropdown/useDropdownGroupRegistry.d.ts +108 -0
- package/dist/components/BbDropdown/useDropdownGroupRegistry.js +5 -0
- package/dist/components/BbDropdownButton/BbDropdownButton.vue.d.ts +3 -3
- package/dist/components/BbDropdownButton/BbDropdownButton.vue.js +6 -0
- package/dist/components/BbDropdownButton/BbDropdownButton.vue_vue_type_script_setup_true_lang.js +119 -0
- package/dist/components/BbDropdownButton/types.d.ts +45 -52
- package/dist/components/BbDropzone/BbDropzone.vue.d.ts +5 -4
- package/dist/components/BbDropzone/BbDropzone.vue.js +6 -0
- package/dist/components/BbDropzone/BbDropzone.vue_vue_type_script_setup_true_lang.js +284 -0
- package/dist/components/BbDropzone/types.d.ts +55 -7
- package/dist/components/BbIcon/BbIcon.vue.d.ts +3 -2
- package/dist/components/BbIcon/BbIcon.vue.js +6 -0
- package/dist/components/BbIcon/BbIcon.vue_vue_type_script_setup_true_lang.js +65 -0
- package/dist/components/BbIcon/types.d.ts +6 -19
- package/dist/components/BbIndicator/BbIndicator.vue.d.ts +14 -0
- package/dist/components/BbIndicator/BbIndicator.vue.js +6 -0
- package/dist/components/BbIndicator/BbIndicator.vue_vue_type_script_setup_true_lang.js +56 -0
- package/dist/components/BbIndicator/types.d.ts +49 -0
- package/dist/components/BbNumberInput/BbNumberInput.vue.d.ts +12 -6
- package/dist/components/BbNumberInput/BbNumberInput.vue.js +6 -0
- package/dist/components/BbNumberInput/BbNumberInput.vue_vue_type_script_setup_true_lang.js +194 -0
- package/dist/components/BbNumberInput/types.d.ts +31 -4
- package/dist/components/BbOffCanvas/BbOffCanvas.vue.d.ts +10 -10
- package/dist/components/BbOffCanvas/BbOffCanvas.vue.js +6 -0
- package/dist/components/BbOffCanvas/BbOffCanvas.vue_vue_type_script_setup_true_lang.js +284 -0
- package/dist/components/BbOffCanvas/types.d.ts +71 -39
- package/dist/components/BbOffCanvas/useOffCanvasStack.d.ts +25 -0
- package/dist/components/BbOffCanvas/useOffCanvasStack.js +68 -0
- package/dist/components/BbPagination/BbPagination.vue.d.ts +3 -4
- package/dist/components/BbPagination/BbPagination.vue.js +6 -0
- package/dist/components/BbPagination/BbPagination.vue_vue_type_script_setup_true_lang.js +244 -0
- package/dist/components/BbPagination/paginationFit.d.ts +38 -0
- package/dist/components/BbPagination/paginationFit.js +13 -0
- package/dist/components/BbPagination/types.d.ts +51 -16
- package/dist/components/BbPopover/BbPopover.vue.d.ts +10 -15
- package/dist/components/BbPopover/BbPopover.vue.js +6 -0
- package/dist/components/BbPopover/BbPopover.vue_vue_type_script_setup_true_lang.js +310 -0
- package/dist/components/BbPopover/escapeStack.d.ts +6 -0
- package/dist/components/BbPopover/escapeStack.js +10 -0
- package/dist/components/BbPopover/types.d.ts +84 -31
- package/dist/components/BbProgress/BbProgress.vue.d.ts +1 -0
- package/dist/components/BbProgress/BbProgress.vue.js +6 -0
- package/dist/components/BbProgress/BbProgress.vue_vue_type_script_setup_true_lang.js +36 -0
- package/dist/components/BbProgress/types.d.ts +15 -1
- package/dist/components/BbRadio/BbRadio.vue.d.ts +5 -3
- package/dist/components/BbRadio/BbRadio.vue.js +6 -0
- package/dist/components/BbRadio/BbRadio.vue_vue_type_script_setup_true_lang.js +133 -0
- package/dist/components/BbRadio/types.d.ts +23 -9
- package/dist/components/BbRadioGroup/BbRadioGroup.vue.d.ts +4 -14
- package/dist/components/BbRadioGroup/BbRadioGroup.vue.js +6 -0
- package/dist/components/BbRadioGroup/BbRadioGroup.vue_vue_type_script_setup_true_lang.js +184 -0
- package/dist/components/BbRadioGroup/types.d.ts +41 -22
- package/dist/components/BbRating/BbRating.vue.d.ts +4 -1
- package/dist/components/BbRating/BbRating.vue.js +6 -0
- package/dist/components/BbRating/BbRating.vue_vue_type_script_setup_true_lang.js +150 -0
- package/dist/components/BbRating/types.d.ts +37 -10
- package/dist/components/BbSelect/BbSelect.vue.d.ts +2 -11
- package/dist/components/BbSelect/BbSelect.vue.js +6 -0
- package/dist/components/BbSelect/BbSelect.vue_vue_type_script_setup_true_lang.js +241 -0
- package/dist/components/BbSelect/types.d.ts +105 -59
- package/dist/components/BbSelectPopover/BbSelectPopover.vue.d.ts +1 -10
- package/dist/components/BbSelectPopover/BbSelectPopover.vue.js +6 -0
- package/dist/components/BbSelectPopover/BbSelectPopover.vue_vue_type_script_setup_true_lang.js +637 -0
- package/dist/components/BbSelectPopover/types.d.ts +189 -102
- package/dist/components/BbSlider/BbSlider.vue.d.ts +3 -6
- package/dist/components/BbSlider/BbSlider.vue.js +6 -0
- package/dist/components/BbSlider/BbSlider.vue_vue_type_script_setup_true_lang.js +166 -0
- package/dist/components/BbSlider/types.d.ts +37 -13
- package/dist/components/BbSmoothHeight/BbSmoothHeight.vue.d.ts +3 -1
- package/dist/components/BbSmoothHeight/BbSmoothHeight.vue.js +6 -0
- package/dist/components/BbSmoothHeight/BbSmoothHeight.vue_vue_type_script_setup_true_lang.js +79 -0
- package/dist/components/BbSmoothHeight/types.d.ts +13 -2
- package/dist/components/BbSpinner/BbSpinner.vue.d.ts +1 -1
- package/dist/components/BbSpinner/BbSpinner.vue.js +6 -0
- package/dist/components/BbSpinner/BbSpinner.vue_vue_type_script_setup_true_lang.js +30 -0
- package/dist/components/BbSpinner/types.d.ts +10 -3
- package/dist/components/BbSwitch/BbSwitch.vue.d.ts +5 -3
- package/dist/components/BbSwitch/BbSwitch.vue.js +6 -0
- package/dist/components/BbSwitch/BbSwitch.vue_vue_type_script_setup_true_lang.js +142 -0
- package/dist/components/BbSwitch/types.d.ts +3 -1
- package/dist/components/BbSwitchGroup/BbSwitchGroup.vue.d.ts +4 -14
- package/dist/components/BbSwitchGroup/BbSwitchGroup.vue.js +6 -0
- package/dist/components/BbSwitchGroup/BbSwitchGroup.vue_vue_type_script_setup_true_lang.js +190 -0
- package/dist/components/BbSwitchGroup/types.d.ts +3 -22
- package/dist/components/BbTable/BbTable.vue.d.ts +53 -31
- package/dist/components/BbTable/BbTable.vue.js +6 -0
- package/dist/components/BbTable/BbTable.vue_vue_type_script_setup_true_lang.js +889 -0
- package/dist/components/BbTable/types.d.ts +176 -37
- package/dist/components/BbTable/utils.d.ts +9 -1
- package/dist/components/BbTable/utils.js +53 -0
- package/dist/components/BbTabs/BbTabs.vue.d.ts +20 -0
- package/dist/components/BbTabs/BbTabs.vue.js +6 -0
- package/dist/components/BbTabs/BbTabs.vue_vue_type_script_setup_true_lang.js +64 -0
- package/dist/components/BbTabs/BbTabsList.vue.d.ts +19 -0
- package/dist/components/BbTabs/BbTabsList.vue.js +6 -0
- package/dist/components/BbTabs/BbTabsList.vue_vue_type_script_setup_true_lang.js +123 -0
- package/dist/components/BbTabs/BbTabsPanes.vue.d.ts +16 -0
- package/dist/components/BbTabs/BbTabsPanes.vue.js +6 -0
- package/dist/components/BbTabs/BbTabsPanes.vue_vue_type_script_setup_true_lang.js +35 -0
- package/dist/components/BbTabs/BbTabsRoot.vue.d.ts +20 -0
- package/dist/components/BbTabs/BbTabsRoot.vue.js +5 -0
- package/dist/components/BbTabs/BbTabsRoot.vue_vue_type_script_setup_true_lang.js +55 -0
- package/dist/components/BbTabs/types.d.ts +264 -0
- package/dist/components/BbTag/BbTag.vue.d.ts +19 -6
- package/dist/components/BbTag/BbTag.vue.js +6 -0
- package/dist/components/BbTag/BbTag.vue_vue_type_script_setup_true_lang.js +187 -0
- package/dist/components/BbTag/types.d.ts +48 -17
- package/dist/components/BbTextInput/BbTextInput.vue.d.ts +10 -1
- package/dist/components/BbTextInput/BbTextInput.vue.js +6 -0
- package/dist/components/BbTextInput/BbTextInput.vue_vue_type_script_setup_true_lang.js +195 -0
- package/dist/components/BbTextInput/types.d.ts +24 -4
- package/dist/components/BbTextarea/BbTextarea.vue.d.ts +10 -1
- package/dist/components/BbTextarea/BbTextarea.vue.js +6 -0
- package/dist/components/BbTextarea/BbTextarea.vue_vue_type_script_setup_true_lang.js +178 -0
- package/dist/components/BbTextarea/types.d.ts +26 -2
- package/dist/components/BbTimePicker/BbTimePicker.vue.d.ts +33 -0
- package/dist/components/BbTimePicker/BbTimePicker.vue.js +6 -0
- package/dist/components/BbTimePicker/BbTimePicker.vue_vue_type_script_setup_true_lang.js +244 -0
- package/dist/components/BbTimePicker/types.d.ts +129 -0
- package/dist/components/BbTimePickerInput/BbTimePickerInput.vue.d.ts +25 -0
- package/dist/components/BbTimePickerInput/BbTimePickerInput.vue.js +6 -0
- package/dist/components/BbTimePickerInput/BbTimePickerInput.vue_vue_type_script_setup_true_lang.js +157 -0
- package/dist/components/BbTimePickerInput/types.d.ts +165 -0
- package/dist/components/BbToast/BbToast.vue.d.ts +2 -3
- package/dist/components/BbToast/BbToast.vue.js +6 -0
- package/dist/components/BbToast/BbToast.vue_vue_type_script_setup_true_lang.js +35 -0
- package/dist/components/BbToast/BbToastMessage.vue.d.ts +17 -8
- package/dist/components/BbToast/BbToastMessage.vue.js +5 -0
- package/dist/components/BbToast/BbToastMessage.vue_vue_type_script_setup_true_lang.js +170 -0
- package/dist/components/BbToast/BbToastPortal.vue.d.ts +30 -0
- package/dist/components/BbToast/BbToastPortal.vue.js +5 -0
- package/dist/components/BbToast/BbToastPortal.vue_vue_type_script_setup_true_lang.js +19 -0
- package/dist/components/BbToast/BbToastRegion.vue.d.ts +8 -0
- package/dist/components/BbToast/BbToastRegion.vue.js +5 -0
- package/dist/components/BbToast/BbToastRegion.vue_vue_type_script_setup_true_lang.js +100 -0
- package/dist/components/BbToast/types.d.ts +69 -5
- package/dist/components/BbTooltip/BbTooltip.vue.d.ts +4 -3
- package/dist/components/BbTooltip/BbTooltip.vue.js +6 -0
- package/dist/components/BbTooltip/BbTooltip.vue_vue_type_script_setup_true_lang.js +160 -0
- package/dist/components/BbTooltip/types.d.ts +61 -11
- package/dist/components/BbTree/BbTree.vue.d.ts +26 -13
- package/dist/components/BbTree/BbTree.vue.js +6 -0
- package/dist/components/BbTree/BbTree.vue_vue_type_script_setup_true_lang.js +55 -0
- package/dist/components/BbTree/BbTreeLevel.vue.d.ts +19 -0
- package/dist/components/BbTree/BbTreeLevel.vue.js +5 -0
- package/dist/components/BbTree/BbTreeLevel.vue_vue_type_script_setup_true_lang.js +94 -0
- package/dist/components/BbTree/context.d.ts +17 -0
- package/dist/components/BbTree/context.js +4 -0
- package/dist/components/BbTree/types.d.ts +93 -42
- package/dist/components/ChipsBox/ChipsBox.vue.d.ts +2 -1
- package/dist/components/ChipsBox/ChipsBox.vue.js +5 -0
- package/dist/components/ChipsBox/ChipsBox.vue_vue_type_script_setup_true_lang.js +98 -0
- package/dist/components/ChipsBox/types.d.ts +12 -5
- package/dist/components/ClearableButton/ClearableButton.vue.d.ts +2 -1
- package/dist/components/ClearableButton/ClearableButton.vue.js +6 -0
- package/dist/components/ClearableButton/ClearableButton.vue_vue_type_script_setup_true_lang.js +19 -0
- package/dist/components/ClearableButton/types.d.ts +7 -1
- package/dist/components/CloseIcon/CloseButton.vue.d.ts +5 -0
- package/dist/components/CloseIcon/CloseButton.vue.js +7 -0
- package/dist/components/CloseIcon/CloseButton.vue_vue_type_script_setup_true_lang.js +23 -0
- package/dist/components/CloseIcon/types.d.ts +2 -0
- package/dist/components/CommaBox/CommaBox.vue.d.ts +2 -1
- package/dist/components/CommaBox/CommaBox.vue.js +6 -0
- package/dist/components/CommaBox/CommaBox.vue_vue_type_script_setup_true_lang.js +81 -0
- package/dist/components/CommaBox/types.d.ts +6 -7
- package/dist/components/CommonInputWrapper/CommonInputWrapper.vue.d.ts +19 -0
- package/dist/components/CommonInputWrapper/CommonInputWrapper.vue.js +6 -0
- package/dist/components/CommonInputWrapper/CommonInputWrapper.vue_vue_type_script_setup_true_lang.js +107 -0
- package/dist/components/CommonInputWrapper/types.d.ts +96 -0
- package/dist/components/CommonPopover/CommonPopover.vue.d.ts +3 -3
- package/dist/components/CommonPopover/CommonPopover.vue.js +6 -0
- package/dist/components/CommonPopover/CommonPopover.vue_vue_type_script_setup_true_lang.js +160 -0
- package/dist/components/CommonPopover/types.d.ts +61 -16
- package/dist/components/ErrorIcon/ErrorIcon.vue.d.ts +2 -0
- package/dist/components/ErrorIcon/ErrorIcon.vue.js +6 -0
- package/dist/components/ErrorIcon/ErrorIcon.vue_vue_type_script_setup_true_lang.js +16 -0
- package/dist/components/FlatListBox/FlatListBox.vue.d.ts +2 -5
- package/dist/components/FlatListBox/FlatListBox.vue.js +5 -0
- package/dist/components/FlatListBox/FlatListBox.vue_vue_type_script_setup_true_lang.js +167 -0
- package/dist/components/FlatListBox/types.d.ts +1 -1
- package/dist/components/GroupedListBox/GroupedListBox.vue.d.ts +2 -5
- package/dist/components/GroupedListBox/GroupedListBox.vue.js +5 -0
- package/dist/components/GroupedListBox/GroupedListBox.vue_vue_type_script_setup_true_lang.js +218 -0
- package/dist/components/ListBox/ListBox.vue.d.ts +3 -6
- package/dist/components/ListBox/ListBox.vue.js +5 -0
- package/dist/components/ListBox/ListBox.vue_vue_type_script_setup_true_lang.js +112 -0
- package/dist/components/ListBox/types.d.ts +1 -1
- package/dist/components/OptionsContainer/OptionsContainer.vue.d.ts +1 -0
- package/dist/components/OptionsContainer/OptionsContainer.vue.js +5 -0
- package/dist/components/OptionsContainer/OptionsContainer.vue_vue_type_script_setup_true_lang.js +52 -0
- package/dist/components/OptionsContainer/types.d.ts +14 -24
- package/dist/components/Transitions/ScaleFade.vue.js +5 -0
- package/dist/components/Transitions/ScaleFade.vue_vue_type_script_setup_true_lang.js +47 -0
- package/dist/components/Transitions/Slide.vue.js +7 -0
- package/dist/components/Transitions/Slide.vue_vue_type_script_setup_true_lang.js +28 -0
- package/dist/components/WarningIcon/WarningIcon.vue.d.ts +5 -0
- package/dist/components/WarningIcon/WarningIcon.vue.js +6 -0
- package/dist/components/WarningIcon/WarningIcon.vue_vue_type_script_setup_true_lang.js +16 -0
- package/dist/components/WarningIcon/types.d.ts +3 -0
- package/dist/composables/__testResets.d.ts +1 -0
- package/dist/composables/useActiveInactiveState.d.ts +4 -0
- package/dist/composables/useActiveInactiveState.js +21 -0
- package/dist/composables/useBaseOptions.d.ts +3 -3
- package/dist/composables/useBaseOptions.js +31 -0
- package/dist/composables/useBbConfig.d.ts +8 -37
- package/dist/composables/useBbConfig.js +5 -0
- package/dist/composables/useBbDropdownContext.d.ts +89 -0
- package/dist/composables/useBbDropdownContext.js +46 -0
- package/dist/composables/useBbFormContext.d.ts +90 -0
- package/dist/composables/useBbFormContext.js +69 -0
- package/dist/composables/useBbTableContext.d.ts +195 -0
- package/dist/composables/useBbTableContext.js +208 -0
- package/dist/composables/useBbTabsContext.d.ts +111 -0
- package/dist/composables/useBbTabsContext.js +219 -0
- package/dist/composables/useBreakpoint.d.ts +13 -0
- package/dist/composables/useBreakpoint.js +39 -0
- package/dist/composables/useBroadcastChannelInstance.d.ts +1 -3
- package/dist/composables/useBroadcastChannelInstance.js +39 -0
- package/dist/composables/useCancelableFunction.js +37 -0
- package/dist/composables/useCoherence.js +16 -0
- package/dist/composables/useConfirm.d.ts +257 -67
- package/dist/composables/useConfirm.js +122 -0
- package/dist/composables/useCountdown.js +42 -0
- package/dist/composables/useHashedWatcher.d.ts +17 -0
- package/dist/composables/useHashedWatcher.js +14 -0
- package/dist/composables/useId.d.ts +3 -2
- package/dist/composables/useIndexById.js +16 -0
- package/dist/composables/useInertiaPage.d.ts +10 -0
- package/dist/composables/useInertiaPage.js +8 -0
- package/dist/composables/useItemText.js +17 -0
- package/dist/composables/useItemValue.js +9 -0
- package/dist/composables/useItemsGetter.d.ts +1 -1
- package/dist/composables/useItemsGetter.js +30 -0
- package/dist/composables/useListboxFocus.js +66 -0
- package/dist/composables/useLocale.d.ts +1 -1
- package/dist/composables/useLocale.js +11 -0
- package/dist/composables/useLogger.d.ts +1 -1
- package/dist/composables/useLogger.js +10 -0
- package/dist/composables/useMinimalQueue.d.ts +1 -1
- package/dist/composables/useMobile.js +7 -0
- package/dist/composables/useOnFalsy.d.ts +2 -0
- package/dist/composables/useOnFalsy.js +9 -0
- package/dist/composables/useOnTruthy.d.ts +7 -0
- package/dist/composables/useOnTruthy.js +9 -0
- package/dist/composables/usePrefill.d.ts +2 -1
- package/dist/composables/usePrefill.js +24 -0
- package/dist/composables/useQuery.d.ts +15 -3
- package/dist/composables/useQuery.js +42 -0
- package/dist/composables/useRoute.js +11 -0
- package/dist/composables/useRouter.js +8 -0
- package/dist/composables/useSafeArea.d.ts +51 -0
- package/dist/composables/useSafeArea.js +16 -0
- package/dist/composables/useSegmentedFields.d.ts +103 -0
- package/dist/composables/useSegmentedFields.js +152 -0
- package/dist/composables/useTableWidthContext.d.ts +5 -0
- package/dist/composables/useTableWidthContext.js +42 -0
- package/dist/composables/useToast.d.ts +17 -73
- package/dist/composables/useToast.js +49 -0
- package/dist/composables/useTopLayer.d.ts +9 -0
- package/dist/composables/useTopLayer.js +7 -0
- package/dist/composables/useUntil.js +13 -0
- package/dist/composables/useViewportWidth.d.ts +17 -0
- package/dist/composables/useViewportWidth.js +6 -0
- package/dist/confirm-variants.d.ts +10 -0
- package/dist/deprecation/ai-deprecations.json.d.ts +784 -0
- package/dist/deprecation/ai-deprecations.json.js +4 -0
- package/dist/deprecation/removedProps.d.ts +3 -0
- package/dist/deprecation/removedProps.js +13 -0
- package/dist/directives/bbColor.d.ts +65 -0
- package/dist/directives/bbColor.js +24 -0
- package/dist/directives/bbDate.d.ts +66 -0
- package/dist/directives/bbDate.js +24 -0
- package/dist/directives/bbDropdown.d.ts +15 -11
- package/dist/directives/bbDropdown.js +23 -0
- package/dist/directives/bbTime.d.ts +64 -0
- package/dist/directives/bbTime.js +24 -0
- package/dist/directives/bbTooltip.d.ts +16 -11
- package/dist/directives/bbTooltip.js +24 -0
- package/dist/dropdown-item-variants.d.ts +10 -0
- package/dist/i18n/index.d.ts +51 -3
- package/dist/i18n/index.js +27 -0
- package/dist/i18n/locales/cs.json +115 -0
- package/dist/i18n/locales/da.json +115 -0
- package/dist/i18n/locales/de.json +115 -0
- package/dist/i18n/locales/el.json +115 -0
- package/dist/i18n/locales/en.json +115 -0
- package/dist/i18n/locales/es.json +115 -0
- package/dist/i18n/locales/fi.json +115 -0
- package/dist/i18n/locales/fr.json +115 -0
- package/dist/i18n/locales/hu.json +115 -0
- package/dist/i18n/locales/it.json +115 -0
- package/dist/i18n/locales/ja.json +115 -0
- package/dist/i18n/locales/ko.json +115 -0
- package/dist/i18n/locales/nb.json +115 -0
- package/dist/i18n/locales/nl.json +115 -0
- package/dist/i18n/locales/pl.json +115 -0
- package/dist/i18n/locales/pt.json +115 -0
- package/dist/i18n/locales/ro.json +115 -0
- package/dist/i18n/locales/ru.json +115 -0
- package/dist/i18n/locales/sv.json +115 -0
- package/dist/i18n/locales/tr.json +115 -0
- package/dist/i18n/locales/uk.json +115 -0
- package/dist/i18n/locales/zh-cn.json +115 -0
- package/dist/icons-whitelist.d.ts +8 -0
- package/dist/index.d.ts +94 -79
- package/dist/index.js +76 -82
- package/dist/indicator-variants.d.ts +13 -0
- package/dist/llms-full.txt +77073 -0
- package/dist/llms-medium.txt +1334 -0
- package/dist/llms.txt +103 -0
- package/dist/locale-blueprint.json +141 -0
- package/dist/nuxt-module.d.ts +3 -0
- package/dist/nuxt.js +19 -0
- package/dist/plugin.d.ts +4 -0
- package/dist/plugin.js +22 -0
- package/dist/reset.css +1 -0
- package/dist/reset.d.ts +0 -0
- package/dist/runtime/nuxt-plugin.d.ts +2 -0
- package/dist/runtime/nuxt-plugin.js +24 -0
- package/dist/styles.css +2 -0
- package/dist/styles.d.ts +0 -0
- package/dist/toast-variants.d.ts +13 -0
- package/dist/tooltip-variants.d.ts +10 -0
- package/dist/types/ActionButton.d.ts +32 -0
- package/dist/types/AlertVariant.d.ts +16 -0
- package/dist/types/BadgeVariant.d.ts +16 -0
- package/dist/types/ButtonVariant.d.ts +17 -0
- package/dist/types/Classes.d.ts +1 -1
- package/dist/types/ColumnName.d.ts +1 -1
- package/dist/types/CommonProps.d.ts +66 -279
- package/dist/types/Config.d.ts +84 -0
- package/dist/types/ConfirmVariant.d.ts +15 -0
- package/dist/types/DropdownItemVariant.d.ts +18 -0
- package/dist/types/Icon.d.ts +5 -7
- package/dist/types/IndicatorVariant.d.ts +16 -0
- package/dist/types/InputDirection.d.ts +15 -0
- package/dist/types/ItemAccessor.d.ts +21 -0
- package/dist/types/Placement.d.ts +6 -0
- package/dist/types/ResponsiveSize.d.ts +20 -0
- package/dist/types/SizeScale.d.ts +8 -0
- package/dist/types/ToastVariant.d.ts +17 -0
- package/dist/types/TooltipVariant.d.ts +18 -0
- package/dist/utilities/functions/bytesToUnit.d.ts +2 -0
- package/dist/utilities/functions/bytesToUnit.js +18 -0
- package/dist/utilities/functions/clampPrecision.js +10 -0
- package/dist/utilities/functions/convertDateValue.d.ts +23 -10
- package/dist/utilities/functions/convertDateValue.js +12 -0
- package/dist/utilities/functions/deburr.js +5 -0
- package/dist/utilities/functions/empty.js +5 -0
- package/dist/utilities/functions/flattenTree.d.ts +1 -1
- package/dist/utilities/functions/hash.js +5 -0
- package/dist/utilities/functions/isDateDisabled.d.ts +1 -0
- package/dist/utilities/functions/isDateDisabled.js +20 -0
- package/dist/utilities/functions/isEqual.js +5 -0
- package/dist/utilities/functions/isNotEmpty.js +5 -0
- package/dist/utilities/functions/matchAnyKey.d.ts +1 -1
- package/dist/utilities/functions/matchAnyKey.js +15 -0
- package/dist/utilities/functions/parseSize.d.ts +1 -1
- package/dist/utilities/functions/parseSize.js +15 -0
- package/dist/utilities/functions/percentage.js +11 -0
- package/dist/utilities/functions/pipe.d.ts +1 -1
- package/dist/utilities/functions/reject.d.ts +25 -0
- package/dist/utilities/functions/reject.js +28 -0
- package/dist/utilities/functions/resolveEnumProp.d.ts +19 -0
- package/dist/utilities/functions/resolveEnumProp.js +5 -0
- package/dist/utilities/functions/slotKey.d.ts +13 -0
- package/dist/utilities/functions/slotKey.js +4 -0
- package/dist/utilities/functions/sort.d.ts +2 -2
- package/dist/utilities/functions/sort.js +19 -0
- package/dist/utilities/functions/throttle.js +5 -0
- package/dist/utilities/functions/waitFor.d.ts +9 -2
- package/dist/utilities/functions/waitFor.js +14 -0
- package/dist/utilities/functions/warnRemovedAttrs.d.ts +11 -0
- package/dist/utilities/functions/warnRemovedAttrs.js +20 -0
- package/dist/utilities/functions/when.js +5 -0
- package/dist/utilities/misc/iconsInjectionKey.d.ts +15 -0
- package/dist/utilities/misc/iconsInjectionKey.js +4 -0
- package/dist/utilities/misc/transitions.d.ts +5 -0
- package/dist/utilities/misc/transitions.js +8 -0
- package/dist/utils/injectLibraryStyles.d.ts +6 -0
- package/dist/utils/injectLibraryStyles.js +38 -0
- package/dist/validated/BbCheckbox.vue.d.ts +29 -0
- package/dist/validated/BbCheckbox.vue.js +5 -0
- package/dist/validated/BbCheckbox.vue_vue_type_script_setup_true_lang.js +75 -0
- package/dist/validated/BbCheckboxGroup.vue.d.ts +34 -0
- package/dist/validated/BbCheckboxGroup.vue.js +5 -0
- package/dist/validated/BbCheckboxGroup.vue_vue_type_script_setup_true_lang.js +76 -0
- package/dist/validated/BbColorInput.vue.d.ts +36 -0
- package/dist/validated/BbColorInput.vue.js +5 -0
- package/dist/validated/BbColorInput.vue_vue_type_script_setup_true_lang.js +71 -0
- package/dist/validated/BbDatePickerInput.vue.d.ts +40 -0
- package/dist/validated/BbDatePickerInput.vue.js +5 -0
- package/dist/validated/BbDatePickerInput.vue_vue_type_script_setup_true_lang.js +87 -0
- package/dist/validated/BbDropzone.vue.d.ts +24 -0
- package/dist/validated/BbDropzone.vue.js +5 -0
- package/dist/validated/BbDropzone.vue_vue_type_script_setup_true_lang.js +45 -0
- package/dist/validated/BbForm.vue.d.ts +28 -0
- package/dist/validated/BbForm.vue.js +5 -0
- package/dist/validated/BbForm.vue_vue_type_script_setup_true_lang.js +42 -0
- package/dist/validated/BbNumberInput.vue.d.ts +36 -0
- package/dist/validated/BbNumberInput.vue.js +5 -0
- package/dist/validated/BbNumberInput.vue_vue_type_script_setup_true_lang.js +72 -0
- package/dist/validated/BbRadioGroup.vue.d.ts +34 -0
- package/dist/validated/BbRadioGroup.vue.js +5 -0
- package/dist/validated/BbRadioGroup.vue_vue_type_script_setup_true_lang.js +75 -0
- package/dist/validated/BbRating.vue.d.ts +30 -0
- package/dist/validated/BbRating.vue.js +5 -0
- package/dist/validated/BbRating.vue_vue_type_script_setup_true_lang.js +63 -0
- package/dist/validated/BbSelect.vue.d.ts +46 -0
- package/dist/validated/BbSelect.vue.js +5 -0
- package/dist/validated/BbSelect.vue_vue_type_script_setup_true_lang.js +100 -0
- package/dist/validated/BbSlider.vue.d.ts +36 -0
- package/dist/validated/BbSlider.vue.js +5 -0
- package/dist/validated/BbSlider.vue_vue_type_script_setup_true_lang.js +69 -0
- package/dist/validated/BbSwitch.vue.d.ts +29 -0
- package/dist/validated/BbSwitch.vue.js +5 -0
- package/dist/validated/BbSwitch.vue_vue_type_script_setup_true_lang.js +75 -0
- package/dist/validated/BbSwitchGroup.vue.d.ts +34 -0
- package/dist/validated/BbSwitchGroup.vue.js +5 -0
- package/dist/validated/BbSwitchGroup.vue_vue_type_script_setup_true_lang.js +76 -0
- package/dist/validated/BbTag.vue.d.ts +36 -0
- package/dist/validated/BbTag.vue.js +5 -0
- package/dist/validated/BbTag.vue_vue_type_script_setup_true_lang.js +72 -0
- package/dist/validated/BbTextInput.vue.d.ts +36 -0
- package/dist/validated/BbTextInput.vue.js +5 -0
- package/dist/validated/BbTextInput.vue_vue_type_script_setup_true_lang.js +72 -0
- package/dist/validated/BbTextarea.vue.d.ts +36 -0
- package/dist/validated/BbTextarea.vue.js +5 -0
- package/dist/validated/BbTextarea.vue_vue_type_script_setup_true_lang.js +70 -0
- package/dist/validated/BbTimePickerInput.vue.d.ts +36 -0
- package/dist/validated/BbTimePickerInput.vue.js +5 -0
- package/dist/validated/BbTimePickerInput.vue_vue_type_script_setup_true_lang.js +78 -0
- package/dist/validated/index.d.ts +29 -0
- package/dist/validated/useValidatedField.d.ts +52 -0
- package/dist/validated/useValidatedField.js +51 -0
- package/dist/validated.js +21 -0
- package/dist/vite-plugin.d.ts +217 -0
- package/dist/vite.js +530 -0
- package/llms.txt +105 -0
- package/package.json +161 -59
- package/scripts/lib/__fixtures__/validated-manifest.json +65 -0
- package/scripts/lib/ensure-manifest.mjs +39 -0
- package/scripts/lib/eslint-plugin-autofix.node.test.mjs +109 -0
- package/scripts/lib/eslint-plugin.mjs +285 -0
- package/scripts/lib/eslint-plugin.node.test.mjs +161 -0
- package/scripts/lib/html-attributes.mjs +191 -0
- package/scripts/lib/mcp-config.mjs +126 -0
- package/scripts/lib/migrate-fix.mjs +115 -0
- package/scripts/lib/validate-bb-markup.mjs +421 -0
- package/dist/ai/BaseButton.md +0 -449
- package/dist/ai/BaseCheckbox.md +0 -512
- package/dist/ai/BaseCheckboxGroup.md +0 -597
- package/dist/ai/BaseColorInput.md +0 -461
- package/dist/ai/BaseDatePicker.md +0 -739
- package/dist/ai/BaseDatePickerInput.md +0 -1517
- package/dist/ai/BaseDialog.md +0 -610
- package/dist/ai/BaseInputContainer.md +0 -570
- package/dist/ai/BaseNumberInput.md +0 -509
- package/dist/ai/BaseRadio.md +0 -405
- package/dist/ai/BaseRadioGroup.md +0 -535
- package/dist/ai/BaseRating.md +0 -489
- package/dist/ai/BaseSelect.md +0 -1742
- package/dist/ai/BaseSlider.md +0 -871
- package/dist/ai/BaseSwitch.md +0 -322
- package/dist/ai/BaseSwitchGroup.md +0 -298
- package/dist/ai/BaseTag.md +0 -623
- package/dist/ai/BaseTextInput.md +0 -392
- package/dist/ai/BaseTextarea.md +0 -398
- package/dist/ai/BbChip.md +0 -147
- package/dist/ai/BbIntersection.md +0 -120
- package/dist/ai/BbRatio.md +0 -61
- package/dist/ai/BbRows.md +0 -307
- package/dist/ai/BbTab.md +0 -950
- package/dist/ai/CommonInputInnerContainer.md +0 -414
- package/dist/ai/CommonInputOuterContainer.md +0 -55
- package/dist/components/BaseButton/BaseButton.vue.d.ts +0 -14
- package/dist/components/BaseButton/types.d.ts +0 -159
- package/dist/components/BaseCheckbox/BaseCheckbox.vue.d.ts +0 -39
- package/dist/components/BaseCheckbox/types.d.ts +0 -213
- package/dist/components/BaseCheckboxGroup/BaseCheckboxGroup.vue.d.ts +0 -30
- package/dist/components/BaseCheckboxGroup/types.d.ts +0 -282
- package/dist/components/BaseColorInput/BaseColorInput.vue.d.ts +0 -35
- package/dist/components/BaseColorInput/ColorPalette.vue.d.ts +0 -13
- package/dist/components/BaseColorInput/types.d.ts +0 -233
- package/dist/components/BaseDatePicker/BaseDatePickerHeader.vue.d.ts +0 -15
- package/dist/components/BaseDatePicker/BaseDatePickerInputDaySelector.vue.d.ts +0 -58
- package/dist/components/BaseDatePicker/BaseDatePickerMonthSelector.vue.d.ts +0 -12
- package/dist/components/BaseDatePicker/BaseDatePickerYearSelector.vue.d.ts +0 -12
- package/dist/components/BaseDatePicker/types.d.ts +0 -100
- package/dist/components/BaseDatePickerInput/BaseDatePickerInput.vue.d.ts +0 -26
- package/dist/components/BaseDatePickerInput/types.d.ts +0 -206
- package/dist/components/BaseDialog/BaseDialog.vue.d.ts +0 -37
- package/dist/components/BaseDialog/types.d.ts +0 -180
- package/dist/components/BaseInputContainer/BaseInputContainer.vue.d.ts +0 -18
- package/dist/components/BaseInputContainer/types.d.ts +0 -126
- package/dist/components/BaseNumberInput/BaseNumberInput.vue.d.ts +0 -46
- package/dist/components/BaseNumberInput/types.d.ts +0 -191
- package/dist/components/BaseRadio/BaseRadio.vue.d.ts +0 -31
- package/dist/components/BaseRadio/types.d.ts +0 -173
- package/dist/components/BaseRadioGroup/BaseRadioGroup.vue.d.ts +0 -30
- package/dist/components/BaseRadioGroup/types.d.ts +0 -240
- package/dist/components/BaseRating/BaseRating.vue.d.ts +0 -35
- package/dist/components/BaseRating/types.d.ts +0 -144
- package/dist/components/BaseSelect/BaseSelect.vue.d.ts +0 -28
- package/dist/components/BaseSelect/types.d.ts +0 -470
- package/dist/components/BaseSlider/BaseSlider.vue.d.ts +0 -38
- package/dist/components/BaseSlider/types.d.ts +0 -201
- package/dist/components/BaseSwitch/BaseSwitch.vue.d.ts +0 -34
- package/dist/components/BaseSwitch/types.d.ts +0 -25
- package/dist/components/BaseSwitchGroup/BaseSwitchGroup.vue.d.ts +0 -30
- package/dist/components/BaseSwitchGroup/types.d.ts +0 -8
- package/dist/components/BaseTag/BaseTag.vue.d.ts +0 -37
- package/dist/components/BaseTag/types.d.ts +0 -136
- package/dist/components/BaseTextInput/BaseTextInput.vue.d.ts +0 -33
- package/dist/components/BaseTextInput/types.d.ts +0 -166
- package/dist/components/BaseTextarea/BaseTextarea.vue.d.ts +0 -31
- package/dist/components/BaseTextarea/types.d.ts +0 -151
- package/dist/components/BbChip/BbChip.vue.d.ts +0 -17
- package/dist/components/BbChip/types.d.ts +0 -23
- package/dist/components/BbIntersection/BbIntersection.vue.d.ts +0 -23
- package/dist/components/BbIntersection/types.d.ts +0 -36
- package/dist/components/BbRatio/BbRatio.vue.d.ts +0 -14
- package/dist/components/BbRatio/types.d.ts +0 -15
- package/dist/components/BbRows/BbRows.vue.d.ts +0 -62
- package/dist/components/BbRows/types.d.ts +0 -21
- package/dist/components/BbTab/BbTab.vue.d.ts +0 -27
- package/dist/components/BbTab/types.d.ts +0 -186
- package/dist/components/CommonInputInnerContainer/CommonInputInnerContainer.vue.d.ts +0 -15
- package/dist/components/CommonInputInnerContainer/types.d.ts +0 -47
- package/dist/components/CommonInputOuterContainer/CommonInputOuterContainer.vue.d.ts +0 -11
- package/dist/components/CommonInputOuterContainer/types.d.ts +0 -16
- package/dist/composables/useModalsState.d.ts +0 -5
- package/dist/composables/useQueue.d.ts +0 -58
- package/dist/composables/useWizard.d.ts +0 -85
- package/dist/i18n/en.d.ts +0 -67
- package/dist/i18n/it.d.ts +0 -67
- package/dist/index.css +0 -2
- package/dist/index100.js +0 -6
- package/dist/index101.js +0 -300
- package/dist/index102.js +0 -16
- package/dist/index103.js +0 -16
- package/dist/index104.js +0 -27
- package/dist/index109.js +0 -19
- package/dist/index11.js +0 -42
- package/dist/index110.js +0 -12
- package/dist/index111.js +0 -19
- package/dist/index112.js +0 -25
- package/dist/index114.js +0 -7
- package/dist/index115.js +0 -241
- package/dist/index116.js +0 -5
- package/dist/index117.js +0 -42
- package/dist/index118.js +0 -5
- package/dist/index119.js +0 -53
- package/dist/index120.js +0 -5
- package/dist/index121.js +0 -32
- package/dist/index122.js +0 -5
- package/dist/index124.js +0 -52
- package/dist/index125.js +0 -5
- package/dist/index126.js +0 -223
- package/dist/index128.js +0 -6
- package/dist/index129.js +0 -162
- package/dist/index13.js +0 -92
- package/dist/index130.js +0 -25
- package/dist/index131.js +0 -51
- package/dist/index132.js +0 -5
- package/dist/index133.js +0 -607
- package/dist/index135.js +0 -6
- package/dist/index136.js +0 -14
- package/dist/index137.js +0 -153
- package/dist/index139.js +0 -6
- package/dist/index14.js +0 -306
- package/dist/index140.js +0 -224
- package/dist/index141.js +0 -5
- package/dist/index143.js +0 -128
- package/dist/index145.js +0 -6
- package/dist/index146.js +0 -8
- package/dist/index147.js +0 -182
- package/dist/index149.js +0 -6
- package/dist/index15.js +0 -10
- package/dist/index151.js +0 -4
- package/dist/index152.js +0 -95
- package/dist/index154.js +0 -6
- package/dist/index155.js +0 -168
- package/dist/index157.js +0 -6
- package/dist/index158.js +0 -145
- package/dist/index16.js +0 -59
- package/dist/index160.js +0 -6
- package/dist/index161.js +0 -53
- package/dist/index163.js +0 -6
- package/dist/index164.js +0 -16
- package/dist/index166.js +0 -35
- package/dist/index168.js +0 -6
- package/dist/index169.js +0 -89
- package/dist/index171.js +0 -6
- package/dist/index172.js +0 -82
- package/dist/index174.js +0 -6
- package/dist/index175.js +0 -38
- package/dist/index176.js +0 -461
- package/dist/index177.js +0 -28
- package/dist/index178.js +0 -66
- package/dist/index18.js +0 -35
- package/dist/index180.js +0 -162
- package/dist/index181.js +0 -5
- package/dist/index182.js +0 -217
- package/dist/index183.js +0 -5
- package/dist/index184.js +0 -112
- package/dist/index185.js +0 -5
- package/dist/index186.js +0 -459
- package/dist/index188.js +0 -6
- package/dist/index19.js +0 -4
- package/dist/index192.js +0 -268
- package/dist/index194.js +0 -6
- package/dist/index195.js +0 -124
- package/dist/index197.js +0 -6
- package/dist/index198.js +0 -174
- package/dist/index2.js +0 -20
- package/dist/index20.js +0 -9
- package/dist/index200.js +0 -6
- package/dist/index201.js +0 -224
- package/dist/index203.js +0 -6
- package/dist/index204.js +0 -135
- package/dist/index206.js +0 -6
- package/dist/index207.js +0 -5
- package/dist/index208.js +0 -170
- package/dist/index21.js +0 -35
- package/dist/index210.js +0 -6
- package/dist/index211.js +0 -37
- package/dist/index213.js +0 -6
- package/dist/index214.js +0 -63
- package/dist/index216.js +0 -6
- package/dist/index217.js +0 -74
- package/dist/index219.js +0 -6
- package/dist/index22.js +0 -6
- package/dist/index220.js +0 -65
- package/dist/index222.js +0 -6
- package/dist/index223.js +0 -67
- package/dist/index225.js +0 -6
- package/dist/index226.js +0 -41
- package/dist/index228.js +0 -6
- package/dist/index229.js +0 -10
- package/dist/index23.js +0 -7
- package/dist/index230.js +0 -22
- package/dist/index232.js +0 -8
- package/dist/index233.js +0 -297
- package/dist/index235.js +0 -6
- package/dist/index236.js +0 -47
- package/dist/index237.js +0 -165
- package/dist/index239.js +0 -6
- package/dist/index24.js +0 -9
- package/dist/index241.js +0 -159
- package/dist/index243.js +0 -6
- package/dist/index244.js +0 -134
- package/dist/index246.js +0 -6
- package/dist/index247.js +0 -167
- package/dist/index249.js +0 -6
- package/dist/index25.js +0 -24
- package/dist/index250.js +0 -147
- package/dist/index252.js +0 -6
- package/dist/index253.js +0 -35
- package/dist/index255.js +0 -6
- package/dist/index256.js +0 -65
- package/dist/index258.js +0 -6
- package/dist/index259.js +0 -19
- package/dist/index260.js +0 -5
- package/dist/index261.js +0 -160
- package/dist/index263.js +0 -6
- package/dist/index264.js +0 -60
- package/dist/index266.js +0 -6
- package/dist/index267.js +0 -134
- package/dist/index269.js +0 -6
- package/dist/index27.js +0 -4
- package/dist/index271.js +0 -206
- package/dist/index273.js +0 -6
- package/dist/index274.js +0 -85
- package/dist/index275.js +0 -5
- package/dist/index276.js +0 -55
- package/dist/index277.js +0 -5
- package/dist/index278.js +0 -164
- package/dist/index28.js +0 -8
- package/dist/index280.js +0 -6
- package/dist/index281.js +0 -145
- package/dist/index283.js +0 -6
- package/dist/index284.js +0 -11
- package/dist/index285.js +0 -200
- package/dist/index287.js +0 -6
- package/dist/index288.js +0 -241
- package/dist/index29.js +0 -7
- package/dist/index290.js +0 -6
- package/dist/index291.js +0 -21
- package/dist/index293.js +0 -6
- package/dist/index294.js +0 -125
- package/dist/index296.js +0 -6
- package/dist/index297.js +0 -161
- package/dist/index299.js +0 -6
- package/dist/index30.js +0 -118
- package/dist/index300.js +0 -127
- package/dist/index302.js +0 -6
- package/dist/index303.js +0 -20
- package/dist/index305.js +0 -6
- package/dist/index306.js +0 -116
- package/dist/index307.js +0 -5
- package/dist/index308.js +0 -507
- package/dist/index31.js +0 -10
- package/dist/index310.js +0 -6
- package/dist/index311.js +0 -196
- package/dist/index313.js +0 -6
- package/dist/index314.js +0 -142
- package/dist/index316.js +0 -6
- package/dist/index317.js +0 -134
- package/dist/index319.js +0 -6
- package/dist/index32.js +0 -28
- package/dist/index320.js +0 -162
- package/dist/index322.js +0 -6
- package/dist/index323.js +0 -319
- package/dist/index325.js +0 -6
- package/dist/index326.js +0 -40
- package/dist/index327.js +0 -43
- package/dist/index328.js +0 -665
- package/dist/index33.js +0 -5
- package/dist/index330.js +0 -6
- package/dist/index331.js +0 -155
- package/dist/index333.js +0 -6
- package/dist/index334.js +0 -142
- package/dist/index336.js +0 -6
- package/dist/index337.js +0 -155
- package/dist/index339.js +0 -6
- package/dist/index34.js +0 -112
- package/dist/index340.js +0 -58
- package/dist/index341.js +0 -5
- package/dist/index342.js +0 -20
- package/dist/index344.js +0 -6
- package/dist/index345.js +0 -142
- package/dist/index347.js +0 -6
- package/dist/index349.js +0 -109
- package/dist/index351.js +0 -6
- package/dist/index353.js +0 -24
- package/dist/index354.js +0 -23
- package/dist/index355.js +0 -839
- package/dist/index356.js +0 -474
- package/dist/index357.js +0 -52
- package/dist/index358.js +0 -7
- package/dist/index36.js +0 -6
- package/dist/index38.js +0 -63
- package/dist/index39.js +0 -63
- package/dist/index40.js +0 -9
- package/dist/index42.js +0 -8
- package/dist/index43.js +0 -179
- package/dist/index44.js +0 -21
- package/dist/index46.js +0 -385
- package/dist/index48.js +0 -6
- package/dist/index49.js +0 -33
- package/dist/index5.js +0 -34
- package/dist/index50.js +0 -12
- package/dist/index51.js +0 -8
- package/dist/index52.js +0 -106
- package/dist/index53.js +0 -330
- package/dist/index54.js +0 -97
- package/dist/index55.js +0 -328
- package/dist/index56.js +0 -28
- package/dist/index57.js +0 -102
- package/dist/index58.js +0 -157
- package/dist/index6.js +0 -38
- package/dist/index60.js +0 -6
- package/dist/index61.js +0 -131
- package/dist/index62.js +0 -5
- package/dist/index65.js +0 -35
- package/dist/index66.js +0 -26
- package/dist/index68.js +0 -6
- package/dist/index69.js +0 -54
- package/dist/index7.js +0 -58
- package/dist/index71.js +0 -6
- package/dist/index72.js +0 -14
- package/dist/index74.js +0 -6
- package/dist/index75.js +0 -159
- package/dist/index77.js +0 -6
- package/dist/index78.js +0 -4
- package/dist/index79.js +0 -4
- package/dist/index80.js +0 -54
- package/dist/index81.js +0 -5
- package/dist/index82.js +0 -5
- package/dist/index83.js +0 -141
- package/dist/index85.js +0 -6
- package/dist/index86.js +0 -65
- package/dist/index88.js +0 -6
- package/dist/index89.js +0 -30
- package/dist/index9.js +0 -11
- package/dist/index90.js +0 -19
- package/dist/index91.js +0 -17
- package/dist/index92.js +0 -9
- package/dist/index93.js +0 -34
- package/dist/index95.js +0 -16
- package/dist/index96.js +0 -10
- package/dist/index97.js +0 -18
- package/dist/index98.js +0 -189
- package/dist/types/VoidHtmlElements.d.ts +0 -1
- package/dist/utilities/functions/add.d.ts +0 -1
- package/dist/utilities/functions/booleanishToBoolean.d.ts +0 -6
- package/dist/utilities/functions/capitalize.d.ts +0 -4
- package/dist/utilities/functions/cloneDeep.d.ts +0 -1
- package/dist/utilities/functions/debounce.d.ts +0 -1
- package/dist/utilities/functions/drop.d.ts +0 -1
- package/dist/utilities/functions/exceedsPrecision.d.ts +0 -1
- package/dist/utilities/functions/findRight.d.ts +0 -4
- package/dist/utilities/functions/findRightIndex.d.ts +0 -4
- package/dist/utilities/functions/flow.d.ts +0 -1
- package/dist/utilities/functions/getHueFromRGB.d.ts +0 -9
- package/dist/utilities/functions/groupBy.d.ts +0 -6
- package/dist/utilities/functions/gt.d.ts +0 -7
- package/dist/utilities/functions/hexToRGB.d.ts +0 -7
- package/dist/utilities/functions/hslToHex.d.ts +0 -1
- package/dist/utilities/functions/includes.d.ts +0 -1
- package/dist/utilities/functions/initial.d.ts +0 -1
- package/dist/utilities/functions/isCssColor.d.ts +0 -5
- package/dist/utilities/functions/lt.d.ts +0 -7
- package/dist/utilities/functions/makeUrl.d.ts +0 -1
- package/dist/utilities/functions/mapKeys.d.ts +0 -5
- package/dist/utilities/functions/mapValues.d.ts +0 -1
- package/dist/utilities/functions/matchesPropertyInsensitive.d.ts +0 -1
- package/dist/utilities/functions/max.d.ts +0 -2
- package/dist/utilities/functions/mean.d.ts +0 -4
- package/dist/utilities/functions/merge.d.ts +0 -11
- package/dist/utilities/functions/millisecondsTo.d.ts +0 -1
- package/dist/utilities/functions/negate.d.ts +0 -4
- package/dist/utilities/functions/normalizeItemGroups.d.ts +0 -13
- package/dist/utilities/functions/omit.d.ts +0 -2
- package/dist/utilities/functions/overEvery.d.ts +0 -4
- package/dist/utilities/functions/pick.d.ts +0 -1
- package/dist/utilities/functions/replace.d.ts +0 -1
- package/dist/utilities/functions/replaceInTree.d.ts +0 -4
- package/dist/utilities/functions/retry.d.ts +0 -5
- package/dist/utilities/functions/roundToTheNearest.d.ts +0 -8
- package/dist/utilities/functions/set.d.ts +0 -15
- package/dist/utilities/functions/stub.d.ts +0 -6
- package/dist/utilities/functions/transposePercent.d.ts +0 -9
- package/dist/utilities/functions/tryTo.d.ts +0 -2
- package/dist/utilities/functions/uniqBy.d.ts +0 -1
- /package/dist/{index64.js → _virtual/_plugin-vue_export-helper.js} +0 -0
- /package/dist/components/{BaseButton → BbBaseButton}/RouterComponent.vue.d.ts +0 -0
- /package/dist/components/{BaseDatePicker/BaseDatePicker.vue.d.ts → BbBaseDatePicker/BbBaseDatePicker.vue.d.ts} +0 -0
- /package/dist/{index165.js → composables/useArray.js} +0 -0
- /package/dist/{index17.js → composables/useFrameworkDetection.js} +0 -0
- /package/dist/{index12.js → composables/useId.js} +0 -0
- /package/dist/{index352.js → directives/createPopoverDirective.js} +0 -0
- /package/dist/{index107.js → utilities/functions/chunk.js} +0 -0
- /package/dist/{index8.js → utilities/functions/clamp.js} +0 -0
- /package/dist/{index150.js → utilities/functions/curry.js} +0 -0
- /package/dist/{index45.js → utilities/functions/extractDomContainer.js} +0 -0
- /package/dist/{index270.js → utilities/functions/findInTree.js} +0 -0
- /package/dist/{index348.js → utilities/functions/flattenTree.js} +0 -0
- /package/dist/{index41.js → utilities/functions/get.js} +0 -0
- /package/dist/{index189.js → utilities/functions/head.js} +0 -0
- /package/dist/{index108.js → utilities/functions/identity.js} +0 -0
- /package/dist/{index179.js → utilities/functions/indexBy.js} +0 -0
- /package/dist/{index37.js → utilities/functions/isHex.js} +0 -0
- /package/dist/{index94.js → utilities/functions/isNil.js} +0 -0
- /package/dist/{index26.js → utilities/functions/isNotNil.js} +0 -0
- /package/dist/{index105.js → utilities/functions/last.js} +0 -0
- /package/dist/{index142.js → utilities/functions/noop.js} +0 -0
- /package/dist/{index231.js → utilities/functions/parseWidthString.js} +0 -0
- /package/dist/{index240.js → utilities/functions/pickBy.js} +0 -0
- /package/dist/{index123.js → utilities/functions/range.js} +0 -0
- /package/dist/{index190.js → utilities/functions/snapToStep.js} +0 -0
- /package/dist/{index191.js → utilities/functions/transpose.js} +0 -0
- /package/dist/{index106.js → utilities/functions/validateDateFormat.js} +0 -0
- /package/dist/{index10.js → utilities/functions/wait.js} +0 -0
|
@@ -0,0 +1,1765 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Workspace Onboarding (Inertia)
|
|
3
|
+
summary: Full-anatomy workspace onboarding for Laravel + Inertia — a live BbProgress header, an accordion checklist whose steps do the real work inline (integration switches, tag-input invites, a mini project form, CSV import via useForm multipart), the checklist seeded from a page prop and mutations resolved through promise-wrapped visits, all through one page context that coopts the Inertia Helpers toolkit.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Recipe: Workspace Onboarding (Inertia)
|
|
7
|
+
|
|
8
|
+
The onboarding checklist adapted for **Laravel + Inertia**: the same live
|
|
9
|
+
progress header, single-open accordion whose steps carry the real actions
|
|
10
|
+
inline, and "see what you'll get" preview peeks — but the checklist state
|
|
11
|
+
arrives as a page prop, every mutation is a promise-wrapped `router.visit`
|
|
12
|
+
with `only: ['onboarding']` so statuses re-arrive in the same round trip,
|
|
13
|
+
the invite and project steps submit through
|
|
14
|
+
[`usePromiseForm`](../../guides/inertia-helpers.md) with 422 errors mapped
|
|
15
|
+
onto their fields, and the CSV import binds the file into a native `useForm`
|
|
16
|
+
that serializes multipart automatically. Anatomy, components, the context
|
|
17
|
+
shape, copy and data are identical to the Vue recipe; only the
|
|
18
|
+
data/mutation layer changes.
|
|
19
|
+
|
|
20
|
+
Sibling recipes: [Vue](../vue/onboarding.md) · [Nuxt](../nuxt/onboarding.md).
|
|
21
|
+
|
|
22
|
+
## Prerequisites
|
|
23
|
+
|
|
24
|
+
- `<BbConfirm />` and `<BbToast />` mounted once in the app layout.
|
|
25
|
+
- From the [Inertia Helpers](../../guides/inertia-helpers.md) toolkit:
|
|
26
|
+
`useProp`, `usePromiseForm`.
|
|
27
|
+
- Controller: `Inertia::render('Onboarding/Index', ['onboarding' => [
|
|
28
|
+
'steps' => [...], 'connectedIntegrations' => [...], 'workspace' => ...,
|
|
29
|
+
'invites' => [...], 'firstProject' => ..., 'importedCustomers' => ...,
|
|
30
|
+
'reminders' => ['enabled' => ..., 'cadence' => ...]]])` — one compound
|
|
31
|
+
prop is the whole checklist's server truth, re-sent on every partial
|
|
32
|
+
reload the page triggers (`only: ['onboarding']`). Mutation routes are
|
|
33
|
+
plain Laravel routes that redirect back (`PATCH /onboarding/steps/:id`,
|
|
34
|
+
`POST /onboarding/integrations/:id/connect`, `POST /onboarding/invites`,
|
|
35
|
+
`POST /onboarding/project`, `POST /onboarding/customers/import`,
|
|
36
|
+
`PATCH /onboarding/reminders`, `POST /onboarding/dismiss`); the mutation
|
|
37
|
+
that changes a step's real state (connecting an integration, sending
|
|
38
|
+
invites, importing customers, enabling reminders) also flips that step's
|
|
39
|
+
status server-side, so the client never computes completion itself.
|
|
40
|
+
|
|
41
|
+
## Key ideas
|
|
42
|
+
|
|
43
|
+
- **One coopting page context.** `provideOnboardingWorkspace()` joins the
|
|
44
|
+
page-shell stack once, owns the step statuses, the integration and invite
|
|
45
|
+
state, and every action. Every leaf calls `useOnboardingWorkspace()` and
|
|
46
|
+
nothing else — zero prop drilling anywhere on the page.
|
|
47
|
+
- **`onboarding` is a page prop, not a client fetch.** `useProp<...>('onboarding')`
|
|
48
|
+
gives a reactive read of the server's current checklist state; a single
|
|
49
|
+
`watch` re-seeds `steps`, `integrations`, `invites`, `firstProject` and
|
|
50
|
+
`reminders` from it every time a visit lands a fresh copy — there is no
|
|
51
|
+
separate load call and no `persistStatus` writer, because the server
|
|
52
|
+
already recomputes step statuses as part of each mutation response.
|
|
53
|
+
- **Mutations are promise-wrapped `router.visit` calls.** A tiny local
|
|
54
|
+
`visit()` helper turns Inertia's callback-based API into a promise, so
|
|
55
|
+
most context actions stay `async function`s exactly like the Vue/Nuxt
|
|
56
|
+
versions — `await ctx.toggleIntegration(...)` reads the same everywhere.
|
|
57
|
+
- **Invites and the project form use `usePromiseForm`, with 422 on the
|
|
58
|
+
fields.** These two steps carry real user input, so their context actions
|
|
59
|
+
wrap `usePromiseForm` instead of the generic `visit()` helper; a failed
|
|
60
|
+
submit rejects with Laravel's field-keyed error bag, and the step's own
|
|
61
|
+
`inviteError`/`nameError` display catches and maps it — the same local
|
|
62
|
+
error slot the client-side checks already use.
|
|
63
|
+
- **The CSV import binds the file into a `useForm`.** Inertia serializes a
|
|
64
|
+
bound `File` as multipart automatically and exposes real upload bytes via
|
|
65
|
+
`onProgress`, so the import step needs no manual `FormData` or XHR
|
|
66
|
+
wiring — unlike the Nuxt adaptation, which has to reach for a raw
|
|
67
|
+
`XMLHttpRequest` because `ofetch` has no progress hook.
|
|
68
|
+
- **Single-open accordion, modeled — not wrapped.** `BbAccordion` is one
|
|
69
|
+
panel per boolean; there is no group component by design. One
|
|
70
|
+
`activeStep` key in the context derives every panel's `model-value`, and
|
|
71
|
+
finishing a step advances the key to the next unfinished one.
|
|
72
|
+
- **Previews ride the shell stack.** "See what you'll get" pushes a
|
|
73
|
+
`step-preview` peek (replace semantics — previews never stack); the peek
|
|
74
|
+
is a workbench: identity header, benefit list, a stat, and a "Set it up
|
|
75
|
+
now" action that jumps back to the step.
|
|
76
|
+
- **Checklist archetype, so rows 4/5/7/8 of the standard anatomy don't
|
|
77
|
+
apply**: no filter rail, no tabs, no pagination, no selection/bulk bar —
|
|
78
|
+
and no page search, since the page has no filterable collection. Page
|
|
79
|
+
Shell, breadcrumbs topbar and the stacked peek sidebar stay.
|
|
80
|
+
- **Buttons are `md` by default**; one `variant="primary"` on the page
|
|
81
|
+
("Go to dashboard" in the topbar); step submits are `secondary`,
|
|
82
|
+
done/skip/preview are `ghost`; "Dismiss onboarding" rides `useConfirm`.
|
|
83
|
+
|
|
84
|
+
## Page anatomy
|
|
85
|
+
|
|
86
|
+
```
|
|
87
|
+
OnboardingChecklist/
|
|
88
|
+
Index.vue ← assembly: PageShell slots, accordion loop, thin
|
|
89
|
+
context.ts ← coopting page context (shell + onboarding prop + actions)
|
|
90
|
+
ProgressHeader.vue ← title, dismiss, BbProgress + "4 of 7 complete"
|
|
91
|
+
StepHeader.vue ← status icon, title, minutes, chevron (in the header button)
|
|
92
|
+
StepActions.vue ← per-step done / skip / preview footer row
|
|
93
|
+
ProfileStep.vue ← step 1 body: completed-at-signup summary + edit link
|
|
94
|
+
IntegrationsStep.vue ← step 2 body: BbSwitch rows (Stripe, QuickBooks, Slack, Drive)
|
|
95
|
+
InviteStep.vue ← step 3 body: BbTag emails + role BbSelect + send
|
|
96
|
+
FirstProjectStep.vue ← step 4 body: mini create-project form
|
|
97
|
+
ImportCustomersStep.vue ← step 5 body: BbDropzone CSV + BbProgress upload
|
|
98
|
+
FirstInvoiceStep.vue ← step 6 body: link-out to the invoice composer
|
|
99
|
+
RemindersStep.vue ← step 7 body: reminders switch + cadence select
|
|
100
|
+
StepPreviewPeek.vue ← sidebar "what you'll get" workbench per step
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
Chrome assumed from the guides: [App Layout](../../guides/app-layout.md)
|
|
104
|
+
(left nav + fat footer) and [Page Shell](../../guides/page-shell.md). The
|
|
105
|
+
dismiss confirmation renders through the app-wide `useConfirm` host, so this
|
|
106
|
+
page needs no `#dialogs` content of its own.
|
|
107
|
+
|
|
108
|
+
## Action inventory
|
|
109
|
+
|
|
110
|
+
| # | Action | Trigger | Mechanism |
|
|
111
|
+
| --- | -------------------------------- | ----------------------------------- | ----------------------------------------------------------------------- |
|
|
112
|
+
| 1 | Go to dashboard | topbar, the page's one `primary` | navigation (`href="/dashboard"`) |
|
|
113
|
+
| 2 | Dismiss onboarding | progress header, ghost | `useConfirm` (destructive) → `router.post` + toast, server redirects |
|
|
114
|
+
| 3 | Expand / collapse a step | accordion header (single-open) | `activeStep` key derives each panel's `model-value` |
|
|
115
|
+
| 4 | See what you'll get | every step footer | `previewStep(id)` → shell peek (replace) |
|
|
116
|
+
| 5 | Mark step done / skip step | step footer ghosts | `completeStep` / `skipStep` → promise-wrapped visit |
|
|
117
|
+
| 6 | Connect / disconnect integration | switch rows in _Connect your tools_ | optimistic toggle, `readonly` in flight, revert + toast on failure |
|
|
118
|
+
| 7 | Compose the invite list | `BbTag` (Enter/comma, max 10) | local ref; `duplicate`/`max` surfaced via `errors` |
|
|
119
|
+
| 8 | Choose the invite role | `BbSelect` beside the tags | local ref |
|
|
120
|
+
| 9 | Send invitations | secondary button in step body | `sendInvites` → `usePromiseForm`, 422 → `inviteError` |
|
|
121
|
+
| 10 | Create the first project | mini form submit | `createProject` → `usePromiseForm`, 422 → `nameError` |
|
|
122
|
+
| 11 | Import customers CSV | `BbDropzone` + Import button | `importCustomers` → `useForm` multipart; `BbProgress` from `onProgress` |
|
|
123
|
+
| 12 | Open the invoice composer | outline button in step 6 | navigation (`href="/invoices/create"`) |
|
|
124
|
+
| 13 | Turn reminders on / pick cadence | switch + select in step 7 | `setReminders` / `setReminderCadence` + toast |
|
|
125
|
+
| 14 | Jump to a step from its preview | peek footer | `jumpToStep(id)` → open step + close peek |
|
|
126
|
+
| 15 | Edit the workspace profile | link in the completed profile step | navigation (`href="/settings/general"`) |
|
|
127
|
+
| 16 | Close the peek | shell chrome | shell stack close |
|
|
128
|
+
|
|
129
|
+
## The code
|
|
130
|
+
|
|
131
|
+
### context.ts
|
|
132
|
+
|
|
133
|
+
```ts
|
|
134
|
+
// OnboardingChecklist/context.ts
|
|
135
|
+
import {
|
|
136
|
+
computed,
|
|
137
|
+
inject,
|
|
138
|
+
provide,
|
|
139
|
+
reactive,
|
|
140
|
+
ref,
|
|
141
|
+
watch,
|
|
142
|
+
type ComputedRef,
|
|
143
|
+
type InjectionKey,
|
|
144
|
+
type Ref,
|
|
145
|
+
} from 'vue';
|
|
146
|
+
import { router, useForm } from '@inertiajs/vue3';
|
|
147
|
+
import type { RequestPayload } from '@inertiajs/core';
|
|
148
|
+
import { useConfirm, useToast } from 'bitboss-ui';
|
|
149
|
+
import {
|
|
150
|
+
usePageShellContext,
|
|
151
|
+
type PageShellContext,
|
|
152
|
+
} from '@/components/layout/usePageShellContext';
|
|
153
|
+
import { useProp } from '@/composables/useProp';
|
|
154
|
+
import { usePromiseForm } from '@/composables/usePromiseForm';
|
|
155
|
+
import type {
|
|
156
|
+
InviteRole,
|
|
157
|
+
PendingInvite,
|
|
158
|
+
Project,
|
|
159
|
+
ProjectDraft,
|
|
160
|
+
ReminderCadence,
|
|
161
|
+
WorkspaceProfile,
|
|
162
|
+
} from '@/types';
|
|
163
|
+
|
|
164
|
+
export type StepId =
|
|
165
|
+
| 'profile'
|
|
166
|
+
| 'integrations'
|
|
167
|
+
| 'invites'
|
|
168
|
+
| 'first-project'
|
|
169
|
+
| 'import-customers'
|
|
170
|
+
| 'first-invoice'
|
|
171
|
+
| 'reminders';
|
|
172
|
+
|
|
173
|
+
export type StepStatus = 'todo' | 'complete' | 'skipped';
|
|
174
|
+
|
|
175
|
+
export interface OnboardingStep {
|
|
176
|
+
id: StepId;
|
|
177
|
+
title: string;
|
|
178
|
+
description: string;
|
|
179
|
+
/** Rough time estimate shown in the header while the step is open. */
|
|
180
|
+
minutes: number;
|
|
181
|
+
status: StepStatus;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
export interface WorkspaceIntegration {
|
|
185
|
+
id: string;
|
|
186
|
+
name: string;
|
|
187
|
+
description: string;
|
|
188
|
+
/** Full static literal — the production icon scanner only bundles names it can see. */
|
|
189
|
+
icon: string;
|
|
190
|
+
connected: boolean;
|
|
191
|
+
/** True while a connect/disconnect request is in flight (drives `readonly`). */
|
|
192
|
+
busy: boolean;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/** What the stacked sidebar can show: the per-step "what you'll get" preview. */
|
|
196
|
+
export type PeekItem = { type: 'step-preview'; stepId: StepId };
|
|
197
|
+
|
|
198
|
+
/** The whole `onboarding` page prop — the server's checklist truth. */
|
|
199
|
+
type OnboardingProp = {
|
|
200
|
+
steps: Record<StepId, StepStatus>;
|
|
201
|
+
connectedIntegrations: string[];
|
|
202
|
+
workspace: WorkspaceProfile;
|
|
203
|
+
invites: PendingInvite[];
|
|
204
|
+
firstProject: Project | null;
|
|
205
|
+
importedCustomers: number | null;
|
|
206
|
+
reminders: { enabled: boolean; cadence: ReminderCadence };
|
|
207
|
+
};
|
|
208
|
+
|
|
209
|
+
const RELOAD_PROPS = ['onboarding'] as const;
|
|
210
|
+
|
|
211
|
+
/** Inertia's callback-based visit, wrapped as a promise — so every simple
|
|
212
|
+
* context action stays `async`, exactly like the Vue/Nuxt versions. Always a
|
|
213
|
+
* partial reload of `onboarding`, the only prop this page depends on. */
|
|
214
|
+
const visit = (
|
|
215
|
+
method: 'post' | 'patch' | 'delete',
|
|
216
|
+
url: string,
|
|
217
|
+
// Inertia's own payload type — strings/numbers/booleans/arrays/files.
|
|
218
|
+
// (`Record<string, unknown>` does not satisfy it.)
|
|
219
|
+
data: RequestPayload = {}
|
|
220
|
+
): Promise<void> =>
|
|
221
|
+
new Promise((resolve, reject) => {
|
|
222
|
+
router.visit(url, {
|
|
223
|
+
method,
|
|
224
|
+
data,
|
|
225
|
+
only: [...RELOAD_PROPS],
|
|
226
|
+
preserveScroll: true,
|
|
227
|
+
preserveState: true,
|
|
228
|
+
onSuccess: () => resolve(),
|
|
229
|
+
onError: (errors) => reject(errors),
|
|
230
|
+
});
|
|
231
|
+
});
|
|
232
|
+
|
|
233
|
+
const STEP_DEFS: Record<StepId, Omit<OnboardingStep, 'status'>> = {
|
|
234
|
+
profile: {
|
|
235
|
+
id: 'profile',
|
|
236
|
+
title: 'Set up your company profile',
|
|
237
|
+
description: 'Legal name, billing address and tax details.',
|
|
238
|
+
minutes: 2,
|
|
239
|
+
},
|
|
240
|
+
integrations: {
|
|
241
|
+
id: 'integrations',
|
|
242
|
+
title: 'Connect your tools',
|
|
243
|
+
description:
|
|
244
|
+
'Stripe for payments, QuickBooks for the books, Slack for alerts.',
|
|
245
|
+
minutes: 3,
|
|
246
|
+
},
|
|
247
|
+
invites: {
|
|
248
|
+
id: 'invites',
|
|
249
|
+
title: 'Invite your teammates',
|
|
250
|
+
description:
|
|
251
|
+
'Billing works better when the whole team sees the same numbers.',
|
|
252
|
+
minutes: 2,
|
|
253
|
+
},
|
|
254
|
+
'first-project': {
|
|
255
|
+
id: 'first-project',
|
|
256
|
+
title: 'Create your first project',
|
|
257
|
+
description:
|
|
258
|
+
'Projects group invoices, budgets and time entries per client.',
|
|
259
|
+
minutes: 1,
|
|
260
|
+
},
|
|
261
|
+
'import-customers': {
|
|
262
|
+
id: 'import-customers',
|
|
263
|
+
title: 'Import your customers',
|
|
264
|
+
description: 'Bring your existing customer list over as a CSV.',
|
|
265
|
+
minutes: 5,
|
|
266
|
+
},
|
|
267
|
+
'first-invoice': {
|
|
268
|
+
id: 'first-invoice',
|
|
269
|
+
title: 'Send your first invoice',
|
|
270
|
+
description: 'Compose, preview and send — payment link included.',
|
|
271
|
+
minutes: 4,
|
|
272
|
+
},
|
|
273
|
+
reminders: {
|
|
274
|
+
id: 'reminders',
|
|
275
|
+
title: 'Turn on payment reminders',
|
|
276
|
+
description: 'Stop chasing overdue invoices by hand.',
|
|
277
|
+
minutes: 1,
|
|
278
|
+
},
|
|
279
|
+
};
|
|
280
|
+
const STEP_ORDER: StepId[] = [
|
|
281
|
+
'profile',
|
|
282
|
+
'integrations',
|
|
283
|
+
'invites',
|
|
284
|
+
'first-project',
|
|
285
|
+
'import-customers',
|
|
286
|
+
'first-invoice',
|
|
287
|
+
'reminders',
|
|
288
|
+
];
|
|
289
|
+
|
|
290
|
+
export interface OnboardingWorkspaceContext {
|
|
291
|
+
// -- Coopted contexts ------------------------------------------------------
|
|
292
|
+
shell: PageShellContext<PeekItem>;
|
|
293
|
+
// -- Page-owned state (seeded + re-seeded from the `onboarding` prop) ------
|
|
294
|
+
steps: OnboardingStep[];
|
|
295
|
+
/** The one open panel; `null` collapses everything (single-open accordion). */
|
|
296
|
+
activeStep: Ref<StepId | null>;
|
|
297
|
+
/** Steps no longer todo (complete or skipped) — drives the progress bar. */
|
|
298
|
+
doneCount: ComputedRef<number>;
|
|
299
|
+
allDone: ComputedRef<boolean>;
|
|
300
|
+
workspace: Ref<WorkspaceProfile | null>;
|
|
301
|
+
integrations: WorkspaceIntegration[];
|
|
302
|
+
invites: Ref<PendingInvite[]>;
|
|
303
|
+
firstProject: Ref<Project | null>;
|
|
304
|
+
importState: {
|
|
305
|
+
uploading: boolean;
|
|
306
|
+
sentBytes: number;
|
|
307
|
+
totalBytes: number;
|
|
308
|
+
importedCount: number | null;
|
|
309
|
+
};
|
|
310
|
+
reminders: { enabled: boolean; cadence: ReminderCadence };
|
|
311
|
+
// -- Step grammar ----------------------------------------------------------
|
|
312
|
+
openStep: (id: StepId | null) => void;
|
|
313
|
+
previewStep: (id: StepId) => void;
|
|
314
|
+
jumpToStep: (id: StepId) => void;
|
|
315
|
+
// -- Actions (complete: visit + toast; the server recomputes statuses) -----
|
|
316
|
+
completeStep: (id: StepId) => Promise<void>;
|
|
317
|
+
skipStep: (id: StepId) => Promise<void>;
|
|
318
|
+
toggleIntegration: (
|
|
319
|
+
integration: WorkspaceIntegration,
|
|
320
|
+
next: boolean
|
|
321
|
+
) => Promise<void>;
|
|
322
|
+
/** Rejects with Laravel's field-keyed error bag on 422 — steps map it locally. */
|
|
323
|
+
sendInvites: (emails: string[], role: InviteRole) => Promise<void>;
|
|
324
|
+
createProject: (draft: ProjectDraft) => Promise<void>;
|
|
325
|
+
importCustomers: (file: File) => Promise<void>;
|
|
326
|
+
setReminders: (enabled: boolean) => Promise<void>;
|
|
327
|
+
setReminderCadence: (cadence: ReminderCadence) => Promise<void>;
|
|
328
|
+
dismissOnboarding: () => Promise<void>;
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
const key: InjectionKey<OnboardingWorkspaceContext> = Symbol(
|
|
332
|
+
'onboarding-workspace'
|
|
333
|
+
);
|
|
334
|
+
|
|
335
|
+
export function provideOnboardingWorkspace(): OnboardingWorkspaceContext {
|
|
336
|
+
const { toast } = useToast();
|
|
337
|
+
const { confirm } = useConfirm();
|
|
338
|
+
|
|
339
|
+
// -- Coopt the specific contexts: once, here, for the whole page. ----------
|
|
340
|
+
const shell = usePageShellContext<PeekItem>();
|
|
341
|
+
|
|
342
|
+
// -- Reactive read of the server's checklist truth. -------------------------
|
|
343
|
+
const onboarding = useProp<OnboardingProp>('onboarding');
|
|
344
|
+
|
|
345
|
+
// -- The checklist definition lives client-side; the server owns statuses. -
|
|
346
|
+
const steps = reactive<OnboardingStep[]>(
|
|
347
|
+
STEP_ORDER.map((id) => ({ ...STEP_DEFS[id], status: 'todo' }))
|
|
348
|
+
);
|
|
349
|
+
|
|
350
|
+
// Icon names are full static literals: the production icon scanner bundles
|
|
351
|
+
// only literals it can see, and brand SVGs live in the app's iconDir.
|
|
352
|
+
const integrations = reactive<WorkspaceIntegration[]>([
|
|
353
|
+
{
|
|
354
|
+
id: 'stripe',
|
|
355
|
+
name: 'Stripe',
|
|
356
|
+
description: 'Accept card payments; payouts reconcile against invoices.',
|
|
357
|
+
icon: 'local:stripe',
|
|
358
|
+
connected: false,
|
|
359
|
+
busy: false,
|
|
360
|
+
},
|
|
361
|
+
{
|
|
362
|
+
id: 'quickbooks',
|
|
363
|
+
name: 'QuickBooks Online',
|
|
364
|
+
description: 'Push paid invoices straight into your accounting.',
|
|
365
|
+
icon: 'local:quickbooks',
|
|
366
|
+
connected: false,
|
|
367
|
+
busy: false,
|
|
368
|
+
},
|
|
369
|
+
{
|
|
370
|
+
id: 'slack',
|
|
371
|
+
name: 'Slack',
|
|
372
|
+
description: 'A message in #finance when an invoice is paid or overdue.',
|
|
373
|
+
icon: 'local:slack',
|
|
374
|
+
connected: false,
|
|
375
|
+
busy: false,
|
|
376
|
+
},
|
|
377
|
+
{
|
|
378
|
+
id: 'google-drive',
|
|
379
|
+
name: 'Google Drive',
|
|
380
|
+
description: 'Attach contracts and receipts from your shared drives.',
|
|
381
|
+
icon: 'local:google-drive',
|
|
382
|
+
connected: false,
|
|
383
|
+
busy: false,
|
|
384
|
+
},
|
|
385
|
+
]);
|
|
386
|
+
|
|
387
|
+
const activeStep = ref<StepId | null>(null);
|
|
388
|
+
const workspace = ref<WorkspaceProfile | null>(null);
|
|
389
|
+
const invites = ref<PendingInvite[]>([]);
|
|
390
|
+
const firstProject = ref<Project | null>(null);
|
|
391
|
+
const importState = reactive({
|
|
392
|
+
uploading: false,
|
|
393
|
+
sentBytes: 0,
|
|
394
|
+
totalBytes: 0,
|
|
395
|
+
importedCount: null as number | null,
|
|
396
|
+
});
|
|
397
|
+
const reminders = reactive({
|
|
398
|
+
enabled: false,
|
|
399
|
+
cadence: '3-7-14' as ReminderCadence,
|
|
400
|
+
});
|
|
401
|
+
|
|
402
|
+
// Re-seed every local field whenever a visit lands a fresh `onboarding`
|
|
403
|
+
// prop — the only place server truth flows into page state.
|
|
404
|
+
const applyState = (state: OnboardingProp) => {
|
|
405
|
+
for (const item of steps) item.status = state.steps[item.id];
|
|
406
|
+
const connected = new Set(state.connectedIntegrations);
|
|
407
|
+
for (const integration of integrations)
|
|
408
|
+
integration.connected = connected.has(integration.id);
|
|
409
|
+
workspace.value = state.workspace;
|
|
410
|
+
invites.value = state.invites;
|
|
411
|
+
firstProject.value = state.firstProject;
|
|
412
|
+
importState.importedCount = state.importedCustomers;
|
|
413
|
+
reminders.enabled = state.reminders.enabled;
|
|
414
|
+
reminders.cadence = state.reminders.cadence;
|
|
415
|
+
};
|
|
416
|
+
applyState(onboarding.value);
|
|
417
|
+
watch(onboarding, applyState);
|
|
418
|
+
|
|
419
|
+
// Open the first unfinished step, right after the initial page load —
|
|
420
|
+
// Inertia props are already hydrated before this runs, so no separate
|
|
421
|
+
// loading state is needed the way the Nuxt adaptation needs one.
|
|
422
|
+
activeStep.value =
|
|
423
|
+
steps.find((candidate) => candidate.status === 'todo')?.id ?? null;
|
|
424
|
+
|
|
425
|
+
// Skipped counts as done: the bar rewards moving on, like Linear's checklist.
|
|
426
|
+
const doneCount = computed(
|
|
427
|
+
() => steps.filter((step) => step.status !== 'todo').length
|
|
428
|
+
);
|
|
429
|
+
const allDone = computed(() => doneCount.value === steps.length);
|
|
430
|
+
|
|
431
|
+
const step = (id: StepId): OnboardingStep =>
|
|
432
|
+
steps.find((candidate) => candidate.id === id)!;
|
|
433
|
+
|
|
434
|
+
// -- Step grammar ----------------------------------------------------------------
|
|
435
|
+
const openStep = (id: StepId | null) => {
|
|
436
|
+
activeStep.value = id;
|
|
437
|
+
};
|
|
438
|
+
// Previews replace: a checklist preview never stacks on another preview.
|
|
439
|
+
const previewStep = (id: StepId) =>
|
|
440
|
+
shell.push({ type: 'step-preview', stepId: id }, true);
|
|
441
|
+
// From the peek back into the page: open the step and drop the sidebar.
|
|
442
|
+
const jumpToStep = (id: StepId) => {
|
|
443
|
+
activeStep.value = id;
|
|
444
|
+
shell.close();
|
|
445
|
+
};
|
|
446
|
+
const openNextTodo = (after: StepId) => {
|
|
447
|
+
const index = steps.findIndex((candidate) => candidate.id === after);
|
|
448
|
+
const next = [...steps.slice(index + 1), ...steps.slice(0, index)].find(
|
|
449
|
+
(candidate) => candidate.status === 'todo'
|
|
450
|
+
);
|
|
451
|
+
activeStep.value = next?.id ?? null;
|
|
452
|
+
};
|
|
453
|
+
|
|
454
|
+
// -- Actions --------------------------------------------------------------------
|
|
455
|
+
// Manual done/skip: the same status endpoint the domain mutations below
|
|
456
|
+
// hit implicitly server-side. The response's `onboarding` prop already
|
|
457
|
+
// carries the new status by the time this promise resolves.
|
|
458
|
+
const completeStep = async (id: StepId) => {
|
|
459
|
+
const title = step(id).title;
|
|
460
|
+
await visit('patch', `/onboarding/steps/${id}`, { status: 'complete' });
|
|
461
|
+
toast({ title: `"${title}" checked off.`, variant: 'success' });
|
|
462
|
+
openNextTodo(id);
|
|
463
|
+
};
|
|
464
|
+
|
|
465
|
+
// Skipping is quiet: it is a dismissal, not an achievement.
|
|
466
|
+
const skipStep = async (id: StepId) => {
|
|
467
|
+
await visit('patch', `/onboarding/steps/${id}`, { status: 'skipped' });
|
|
468
|
+
openNextTodo(id);
|
|
469
|
+
};
|
|
470
|
+
|
|
471
|
+
// Optimistic, per the BbSwitch doctrine: flip now, revert + toast on failure.
|
|
472
|
+
// `busy` drives `readonly` so conflicting toggles cannot queue. The server
|
|
473
|
+
// flips the 'integrations' step to complete on a successful connect; the
|
|
474
|
+
// partial reload brings that back with everything else.
|
|
475
|
+
const toggleIntegration = async (
|
|
476
|
+
integration: WorkspaceIntegration,
|
|
477
|
+
next: boolean
|
|
478
|
+
) => {
|
|
479
|
+
integration.busy = true;
|
|
480
|
+
integration.connected = next;
|
|
481
|
+
try {
|
|
482
|
+
await visit(
|
|
483
|
+
'post',
|
|
484
|
+
`/onboarding/integrations/${integration.id}/${next ? 'connect' : 'disconnect'}`
|
|
485
|
+
);
|
|
486
|
+
toast({
|
|
487
|
+
title: `${integration.name} ${next ? 'connected' : 'disconnected'}.`,
|
|
488
|
+
variant: 'success',
|
|
489
|
+
});
|
|
490
|
+
} catch {
|
|
491
|
+
integration.connected = !next;
|
|
492
|
+
toast({
|
|
493
|
+
title: `Could not ${next ? 'connect' : 'disconnect'} ${integration.name}.`,
|
|
494
|
+
variant: 'destructive',
|
|
495
|
+
});
|
|
496
|
+
} finally {
|
|
497
|
+
integration.busy = false;
|
|
498
|
+
}
|
|
499
|
+
};
|
|
500
|
+
|
|
501
|
+
// Carries real user input, so it rides usePromiseForm instead of the
|
|
502
|
+
// generic visit() helper: a 422 rejects with Laravel's field-keyed error
|
|
503
|
+
// bag, which InviteStep maps onto its own `inviteError` display.
|
|
504
|
+
const invitesForm = usePromiseForm<{ emails: string[]; role: InviteRole }>({
|
|
505
|
+
emails: [],
|
|
506
|
+
role: 'member',
|
|
507
|
+
});
|
|
508
|
+
const sendInvites = async (emails: string[], role: InviteRole) => {
|
|
509
|
+
invitesForm.form.emails = emails;
|
|
510
|
+
invitesForm.form.role = role;
|
|
511
|
+
await invitesForm.post('/onboarding/invites', {
|
|
512
|
+
only: [...RELOAD_PROPS],
|
|
513
|
+
});
|
|
514
|
+
toast({
|
|
515
|
+
title: `${emails.length} invitation${emails.length === 1 ? '' : 's'} sent.`,
|
|
516
|
+
variant: 'success',
|
|
517
|
+
});
|
|
518
|
+
};
|
|
519
|
+
|
|
520
|
+
const projectForm = usePromiseForm<{ name: string; client: string }>({
|
|
521
|
+
name: '',
|
|
522
|
+
client: '',
|
|
523
|
+
});
|
|
524
|
+
const createProject = async (draft: ProjectDraft) => {
|
|
525
|
+
projectForm.form.name = draft.name;
|
|
526
|
+
projectForm.form.client = draft.client;
|
|
527
|
+
await projectForm.post('/onboarding/project', {
|
|
528
|
+
only: [...RELOAD_PROPS],
|
|
529
|
+
});
|
|
530
|
+
toast({ title: `${draft.name} created.`, variant: 'success' });
|
|
531
|
+
};
|
|
532
|
+
|
|
533
|
+
// The bound File serializes as multipart automatically; onProgress gives
|
|
534
|
+
// real upload bytes natively — no manual FormData/XHR wiring needed.
|
|
535
|
+
const importForm = useForm<{ file: File | null }>({ file: null });
|
|
536
|
+
const importCustomers = (file: File): Promise<void> => {
|
|
537
|
+
importState.uploading = true;
|
|
538
|
+
importState.totalBytes = file.size;
|
|
539
|
+
importState.sentBytes = 0;
|
|
540
|
+
importForm.file = file;
|
|
541
|
+
return new Promise((resolve, reject) => {
|
|
542
|
+
importForm.post('/onboarding/customers/import', {
|
|
543
|
+
only: [...RELOAD_PROPS],
|
|
544
|
+
forceFormData: true,
|
|
545
|
+
onProgress: (event) => {
|
|
546
|
+
if (event?.total) {
|
|
547
|
+
importState.sentBytes = event.loaded ?? 0;
|
|
548
|
+
importState.totalBytes = event.total;
|
|
549
|
+
}
|
|
550
|
+
},
|
|
551
|
+
onSuccess: () => {
|
|
552
|
+
importState.uploading = false;
|
|
553
|
+
toast({
|
|
554
|
+
title: `${onboarding.value.importedCustomers ?? 0} customers imported.`,
|
|
555
|
+
variant: 'success',
|
|
556
|
+
});
|
|
557
|
+
resolve();
|
|
558
|
+
},
|
|
559
|
+
onError: (errors) => {
|
|
560
|
+
importState.uploading = false;
|
|
561
|
+
reject(errors);
|
|
562
|
+
},
|
|
563
|
+
});
|
|
564
|
+
});
|
|
565
|
+
};
|
|
566
|
+
|
|
567
|
+
const setReminders = async (enabled: boolean) => {
|
|
568
|
+
reminders.enabled = enabled;
|
|
569
|
+
try {
|
|
570
|
+
await visit('patch', '/onboarding/reminders', {
|
|
571
|
+
enabled,
|
|
572
|
+
cadence: reminders.cadence,
|
|
573
|
+
});
|
|
574
|
+
toast({
|
|
575
|
+
title: enabled
|
|
576
|
+
? 'Payment reminders are on.'
|
|
577
|
+
: 'Payment reminders turned off.',
|
|
578
|
+
variant: 'success',
|
|
579
|
+
});
|
|
580
|
+
} catch {
|
|
581
|
+
reminders.enabled = !enabled;
|
|
582
|
+
toast({ title: 'Could not update reminders.', variant: 'destructive' });
|
|
583
|
+
}
|
|
584
|
+
};
|
|
585
|
+
|
|
586
|
+
const setReminderCadence = async (cadence: ReminderCadence) => {
|
|
587
|
+
reminders.cadence = cadence;
|
|
588
|
+
await visit('patch', '/onboarding/reminders', {
|
|
589
|
+
enabled: reminders.enabled,
|
|
590
|
+
cadence,
|
|
591
|
+
});
|
|
592
|
+
toast({ title: 'Reminder schedule updated.', variant: 'success' });
|
|
593
|
+
};
|
|
594
|
+
|
|
595
|
+
const dismissOnboarding = async () => {
|
|
596
|
+
const ok = await confirm({
|
|
597
|
+
variant: 'destructive',
|
|
598
|
+
title: 'Dismiss onboarding',
|
|
599
|
+
text: 'Hide the setup checklist for everyone in this workspace? Unfinished steps stay available under Settings → Setup.',
|
|
600
|
+
yes: 'Dismiss',
|
|
601
|
+
no: 'Keep it',
|
|
602
|
+
});
|
|
603
|
+
if (!ok) return;
|
|
604
|
+
// A full visit, not a partial reload: the server redirects to the
|
|
605
|
+
// dashboard, so there is no `onboarding` prop left to re-seed from.
|
|
606
|
+
router.visit('/onboarding/dismiss', { method: 'post' });
|
|
607
|
+
toast({
|
|
608
|
+
title: 'Onboarding dismissed. Find it again under Settings → Setup.',
|
|
609
|
+
variant: 'success',
|
|
610
|
+
});
|
|
611
|
+
};
|
|
612
|
+
|
|
613
|
+
const ctx: OnboardingWorkspaceContext = {
|
|
614
|
+
shell,
|
|
615
|
+
steps,
|
|
616
|
+
activeStep,
|
|
617
|
+
doneCount,
|
|
618
|
+
allDone,
|
|
619
|
+
workspace,
|
|
620
|
+
integrations,
|
|
621
|
+
invites,
|
|
622
|
+
firstProject,
|
|
623
|
+
importState,
|
|
624
|
+
reminders,
|
|
625
|
+
openStep,
|
|
626
|
+
previewStep,
|
|
627
|
+
jumpToStep,
|
|
628
|
+
completeStep,
|
|
629
|
+
skipStep,
|
|
630
|
+
toggleIntegration,
|
|
631
|
+
sendInvites,
|
|
632
|
+
createProject,
|
|
633
|
+
importCustomers,
|
|
634
|
+
setReminders,
|
|
635
|
+
setReminderCadence,
|
|
636
|
+
dismissOnboarding,
|
|
637
|
+
};
|
|
638
|
+
provide(key, ctx);
|
|
639
|
+
return ctx;
|
|
640
|
+
}
|
|
641
|
+
|
|
642
|
+
export function useOnboardingWorkspace(): OnboardingWorkspaceContext {
|
|
643
|
+
const ctx = inject(key);
|
|
644
|
+
if (!ctx)
|
|
645
|
+
throw new Error(
|
|
646
|
+
'useOnboardingWorkspace() called outside OnboardingChecklist'
|
|
647
|
+
);
|
|
648
|
+
return ctx;
|
|
649
|
+
}
|
|
650
|
+
```
|
|
651
|
+
|
|
652
|
+
### Index.vue — the assembly
|
|
653
|
+
|
|
654
|
+
```vue
|
|
655
|
+
<!-- OnboardingChecklist/Index.vue -->
|
|
656
|
+
<template>
|
|
657
|
+
<PageShell>
|
|
658
|
+
<!-- Topbar: breadcrumbs left, the page's one primary action right. -->
|
|
659
|
+
<template #topbar>
|
|
660
|
+
<div class="flex items-center justify-between gap-4 border-b px-4 py-2">
|
|
661
|
+
<!-- Breadcrumbs take the row's slack on a stable basis (min-w-0 flex-auto);
|
|
662
|
+
without it their overflow recompute fights the flex layout every frame. -->
|
|
663
|
+
<BbBreadcrumbs
|
|
664
|
+
class="min-w-0 flex-auto"
|
|
665
|
+
:items="[
|
|
666
|
+
{ key: 'dashboard', text: 'Dashboard', href: '/dashboard' },
|
|
667
|
+
{ key: 'getting-started', text: 'Getting started' },
|
|
668
|
+
]"
|
|
669
|
+
/>
|
|
670
|
+
<BbButton
|
|
671
|
+
append:icon="lucide:arrow-right"
|
|
672
|
+
class="shrink-0"
|
|
673
|
+
href="/dashboard"
|
|
674
|
+
variant="primary"
|
|
675
|
+
>
|
|
676
|
+
Go to dashboard
|
|
677
|
+
</BbButton>
|
|
678
|
+
</div>
|
|
679
|
+
</template>
|
|
680
|
+
|
|
681
|
+
<div class="mx-auto flex w-full max-w-3xl flex-col gap-6 p-4">
|
|
682
|
+
<ProgressHeader />
|
|
683
|
+
|
|
684
|
+
<!-- Single-open checklist: one active key in the context derives every
|
|
685
|
+
panel's model-value; opening one closes the rest, and clicking the
|
|
686
|
+
open header collapses everything (payload is false → key null). -->
|
|
687
|
+
<div class="flex flex-col divide-y rounded-[var(--bb-radius)] border">
|
|
688
|
+
<BbAccordion
|
|
689
|
+
v-for="item in ctx.steps"
|
|
690
|
+
:key="item.id"
|
|
691
|
+
:model-value="ctx.activeStep.value === item.id"
|
|
692
|
+
@update:model-value="(open) => ctx.openStep(open ? item.id : null)"
|
|
693
|
+
>
|
|
694
|
+
<template #header="{ value }">
|
|
695
|
+
<StepHeader :open="value" :step="item" />
|
|
696
|
+
</template>
|
|
697
|
+
<div class="flex flex-col gap-4 px-11 pb-4">
|
|
698
|
+
<component :is="stepBodies[item.id]" />
|
|
699
|
+
<StepActions :step="item" />
|
|
700
|
+
</div>
|
|
701
|
+
</BbAccordion>
|
|
702
|
+
</div>
|
|
703
|
+
|
|
704
|
+
<p class="text-xs text-gray-500">
|
|
705
|
+
Stuck on a step?
|
|
706
|
+
<BbButton href="/docs/setup" size="sm" variant="link"
|
|
707
|
+
>Read the setup guide</BbButton
|
|
708
|
+
>
|
|
709
|
+
— it covers every integration and the CSV format.
|
|
710
|
+
</p>
|
|
711
|
+
</div>
|
|
712
|
+
|
|
713
|
+
<!-- The peek sidebar: the shell owns back/close; we render by type. -->
|
|
714
|
+
<template #sidebar>
|
|
715
|
+
<StepPreviewPeek
|
|
716
|
+
v-if="ctx.shell.current.value?.type === 'step-preview'"
|
|
717
|
+
:step-id="ctx.shell.current.value.stepId"
|
|
718
|
+
/>
|
|
719
|
+
</template>
|
|
720
|
+
</PageShell>
|
|
721
|
+
</template>
|
|
722
|
+
|
|
723
|
+
<script setup lang="ts">
|
|
724
|
+
import type { Component } from 'vue';
|
|
725
|
+
import { BbAccordion, BbBreadcrumbs, BbButton } from 'bitboss-ui';
|
|
726
|
+
import PageShell from '@/components/layout/PageShell.vue';
|
|
727
|
+
import { provideOnboardingWorkspace, type StepId } from './context';
|
|
728
|
+
import FirstInvoiceStep from './FirstInvoiceStep.vue';
|
|
729
|
+
import FirstProjectStep from './FirstProjectStep.vue';
|
|
730
|
+
import ImportCustomersStep from './ImportCustomersStep.vue';
|
|
731
|
+
import IntegrationsStep from './IntegrationsStep.vue';
|
|
732
|
+
import InviteStep from './InviteStep.vue';
|
|
733
|
+
import ProfileStep from './ProfileStep.vue';
|
|
734
|
+
import ProgressHeader from './ProgressHeader.vue';
|
|
735
|
+
import RemindersStep from './RemindersStep.vue';
|
|
736
|
+
import StepActions from './StepActions.vue';
|
|
737
|
+
import StepHeader from './StepHeader.vue';
|
|
738
|
+
import StepPreviewPeek from './StepPreviewPeek.vue';
|
|
739
|
+
|
|
740
|
+
const ctx = provideOnboardingWorkspace();
|
|
741
|
+
|
|
742
|
+
// Each step body is its own component — a lookup, not a `type` prop.
|
|
743
|
+
const stepBodies: Record<StepId, Component> = {
|
|
744
|
+
profile: ProfileStep,
|
|
745
|
+
integrations: IntegrationsStep,
|
|
746
|
+
invites: InviteStep,
|
|
747
|
+
'first-project': FirstProjectStep,
|
|
748
|
+
'import-customers': ImportCustomersStep,
|
|
749
|
+
'first-invoice': FirstInvoiceStep,
|
|
750
|
+
reminders: RemindersStep,
|
|
751
|
+
};
|
|
752
|
+
</script>
|
|
753
|
+
```
|
|
754
|
+
|
|
755
|
+
### ProgressHeader.vue
|
|
756
|
+
|
|
757
|
+
```vue
|
|
758
|
+
<!-- OnboardingChecklist/ProgressHeader.vue -->
|
|
759
|
+
<template>
|
|
760
|
+
<header class="flex flex-col gap-3">
|
|
761
|
+
<div class="flex items-start justify-between gap-4">
|
|
762
|
+
<div class="flex flex-col gap-1">
|
|
763
|
+
<h1 class="text-xl font-semibold">Set up Acme</h1>
|
|
764
|
+
<p class="text-sm text-gray-500">
|
|
765
|
+
A few steps to get your billing workspace ready for the whole team.
|
|
766
|
+
</p>
|
|
767
|
+
</div>
|
|
768
|
+
<BbButton variant="ghost" @click="ctx.dismissOnboarding">
|
|
769
|
+
Dismiss onboarding
|
|
770
|
+
</BbButton>
|
|
771
|
+
</div>
|
|
772
|
+
|
|
773
|
+
<div class="flex flex-col gap-1.5">
|
|
774
|
+
<div class="flex items-center justify-between gap-4 text-sm">
|
|
775
|
+
<span class="font-medium">
|
|
776
|
+
{{
|
|
777
|
+
ctx.allDone.value
|
|
778
|
+
? 'All set — your workspace is ready.'
|
|
779
|
+
: 'Your setup checklist'
|
|
780
|
+
}}
|
|
781
|
+
</span>
|
|
782
|
+
<span class="text-gray-500">
|
|
783
|
+
{{ ctx.doneCount.value }} of {{ ctx.steps.length }} complete
|
|
784
|
+
</span>
|
|
785
|
+
</div>
|
|
786
|
+
<!-- Real units in, no pre-computed percentage: max = number of steps. -->
|
|
787
|
+
<BbProgress
|
|
788
|
+
aria-label="Setup progress"
|
|
789
|
+
:aria-valuetext="`${ctx.doneCount.value} of ${ctx.steps.length} steps complete`"
|
|
790
|
+
:max="ctx.steps.length"
|
|
791
|
+
:model-value="ctx.doneCount.value"
|
|
792
|
+
/>
|
|
793
|
+
</div>
|
|
794
|
+
</header>
|
|
795
|
+
</template>
|
|
796
|
+
|
|
797
|
+
<script setup lang="ts">
|
|
798
|
+
import { BbButton, BbProgress } from 'bitboss-ui';
|
|
799
|
+
import { useOnboardingWorkspace } from './context';
|
|
800
|
+
|
|
801
|
+
const ctx = useOnboardingWorkspace();
|
|
802
|
+
</script>
|
|
803
|
+
```
|
|
804
|
+
|
|
805
|
+
### StepHeader.vue
|
|
806
|
+
|
|
807
|
+
```vue
|
|
808
|
+
<!-- OnboardingChecklist/StepHeader.vue -->
|
|
809
|
+
<template>
|
|
810
|
+
<!-- Rendered INSIDE the accordion's header button: everything here is
|
|
811
|
+
non-interactive and click-transparent by design — the whole row toggles. -->
|
|
812
|
+
<span class="flex w-full items-center gap-3 px-3 py-3 text-left">
|
|
813
|
+
<BbIcon
|
|
814
|
+
class="shrink-0"
|
|
815
|
+
:class="step.status === 'complete' ? 'text-green-600' : 'text-gray-400'"
|
|
816
|
+
:icon="statusIcon"
|
|
817
|
+
size="20"
|
|
818
|
+
/>
|
|
819
|
+
<span class="flex min-w-0 flex-1 flex-col">
|
|
820
|
+
<span
|
|
821
|
+
class="text-sm font-medium"
|
|
822
|
+
:class="step.status === 'todo' ? '' : 'text-gray-500'"
|
|
823
|
+
>
|
|
824
|
+
{{ step.title }}
|
|
825
|
+
</span>
|
|
826
|
+
<span class="truncate text-xs text-gray-500">{{ step.description }}</span>
|
|
827
|
+
</span>
|
|
828
|
+
<span
|
|
829
|
+
v-if="step.status === 'skipped'"
|
|
830
|
+
class="shrink-0 text-xs uppercase tracking-wide text-gray-400"
|
|
831
|
+
>
|
|
832
|
+
Skipped
|
|
833
|
+
</span>
|
|
834
|
+
<span
|
|
835
|
+
v-else-if="step.status === 'todo'"
|
|
836
|
+
class="shrink-0 text-xs text-gray-400"
|
|
837
|
+
>
|
|
838
|
+
~{{ step.minutes }} min
|
|
839
|
+
</span>
|
|
840
|
+
<BbIcon
|
|
841
|
+
class="shrink-0 text-gray-400 transition-transform"
|
|
842
|
+
:class="open ? 'rotate-180' : ''"
|
|
843
|
+
icon="lucide:chevron-down"
|
|
844
|
+
size="16"
|
|
845
|
+
/>
|
|
846
|
+
</span>
|
|
847
|
+
</template>
|
|
848
|
+
|
|
849
|
+
<script setup lang="ts">
|
|
850
|
+
import { computed } from 'vue';
|
|
851
|
+
import { BbIcon } from 'bitboss-ui';
|
|
852
|
+
import type { OnboardingStep } from './context';
|
|
853
|
+
|
|
854
|
+
const props = defineProps<{ open: boolean; step: OnboardingStep }>();
|
|
855
|
+
|
|
856
|
+
// Full literals — the production icon scanner needs complete names.
|
|
857
|
+
const icons = {
|
|
858
|
+
todo: 'lucide:circle-dashed',
|
|
859
|
+
complete: 'lucide:circle-check',
|
|
860
|
+
skipped: 'lucide:circle-check',
|
|
861
|
+
} as const;
|
|
862
|
+
const statusIcon = computed(() => icons[props.step.status]);
|
|
863
|
+
</script>
|
|
864
|
+
```
|
|
865
|
+
|
|
866
|
+
### StepActions.vue
|
|
867
|
+
|
|
868
|
+
```vue
|
|
869
|
+
<!-- OnboardingChecklist/StepActions.vue -->
|
|
870
|
+
<template>
|
|
871
|
+
<footer class="flex flex-wrap items-center gap-2 border-t pt-3">
|
|
872
|
+
<template v-if="step.status === 'todo'">
|
|
873
|
+
<BbButton
|
|
874
|
+
prepend:icon="lucide:check"
|
|
875
|
+
variant="ghost"
|
|
876
|
+
@click="() => ctx.completeStep(step.id)"
|
|
877
|
+
>
|
|
878
|
+
Mark as done
|
|
879
|
+
</BbButton>
|
|
880
|
+
<BbButton variant="ghost" @click="() => ctx.skipStep(step.id)">
|
|
881
|
+
Skip for now
|
|
882
|
+
</BbButton>
|
|
883
|
+
</template>
|
|
884
|
+
<span v-else class="text-xs text-gray-500">
|
|
885
|
+
{{ step.status === 'complete' ? 'Completed' : 'Skipped' }} — revisit any
|
|
886
|
+
time from Settings → Setup.
|
|
887
|
+
</span>
|
|
888
|
+
<BbButton
|
|
889
|
+
append:icon="lucide:chevron-right"
|
|
890
|
+
class="ml-auto"
|
|
891
|
+
variant="ghost"
|
|
892
|
+
@click="() => ctx.previewStep(step.id)"
|
|
893
|
+
>
|
|
894
|
+
See what you'll get
|
|
895
|
+
</BbButton>
|
|
896
|
+
</footer>
|
|
897
|
+
</template>
|
|
898
|
+
|
|
899
|
+
<script setup lang="ts">
|
|
900
|
+
import { BbButton } from 'bitboss-ui';
|
|
901
|
+
import { useOnboardingWorkspace } from './context';
|
|
902
|
+
import type { OnboardingStep } from './context';
|
|
903
|
+
|
|
904
|
+
defineProps<{ step: OnboardingStep }>();
|
|
905
|
+
|
|
906
|
+
const ctx = useOnboardingWorkspace();
|
|
907
|
+
</script>
|
|
908
|
+
```
|
|
909
|
+
|
|
910
|
+
### ProfileStep.vue
|
|
911
|
+
|
|
912
|
+
```vue
|
|
913
|
+
<!-- OnboardingChecklist/ProfileStep.vue -->
|
|
914
|
+
<template>
|
|
915
|
+
<div v-if="ctx.workspace.value" class="flex flex-col gap-3 text-sm">
|
|
916
|
+
<p class="text-gray-600">
|
|
917
|
+
Done at signup — these details appear on every invoice you send.
|
|
918
|
+
</p>
|
|
919
|
+
<dl class="grid grid-cols-[auto_1fr] gap-x-6 gap-y-1.5">
|
|
920
|
+
<dt class="text-gray-500">Company</dt>
|
|
921
|
+
<dd>{{ ctx.workspace.value.company }}</dd>
|
|
922
|
+
<dt class="text-gray-500">Billing address</dt>
|
|
923
|
+
<dd>{{ ctx.workspace.value.address }}</dd>
|
|
924
|
+
<dt class="text-gray-500">Tax ID</dt>
|
|
925
|
+
<dd>{{ ctx.workspace.value.taxId }}</dd>
|
|
926
|
+
<dt class="text-gray-500">Currency</dt>
|
|
927
|
+
<dd>{{ ctx.workspace.value.currency }}</dd>
|
|
928
|
+
</dl>
|
|
929
|
+
<div>
|
|
930
|
+
<BbButton
|
|
931
|
+
href="/settings/general"
|
|
932
|
+
prepend:icon="lucide:pencil"
|
|
933
|
+
size="sm"
|
|
934
|
+
variant="link"
|
|
935
|
+
>
|
|
936
|
+
Edit workspace profile
|
|
937
|
+
</BbButton>
|
|
938
|
+
</div>
|
|
939
|
+
</div>
|
|
940
|
+
</template>
|
|
941
|
+
|
|
942
|
+
<script setup lang="ts">
|
|
943
|
+
import { BbButton } from 'bitboss-ui';
|
|
944
|
+
import { useOnboardingWorkspace } from './context';
|
|
945
|
+
|
|
946
|
+
const ctx = useOnboardingWorkspace();
|
|
947
|
+
</script>
|
|
948
|
+
```
|
|
949
|
+
|
|
950
|
+
### IntegrationsStep.vue
|
|
951
|
+
|
|
952
|
+
```vue
|
|
953
|
+
<!-- OnboardingChecklist/IntegrationsStep.vue -->
|
|
954
|
+
<template>
|
|
955
|
+
<div class="flex flex-col text-sm">
|
|
956
|
+
<p class="pb-1 text-gray-600">
|
|
957
|
+
Flip a switch to connect — you'll be sent through the provider's consent
|
|
958
|
+
screen the first time.
|
|
959
|
+
</p>
|
|
960
|
+
<div
|
|
961
|
+
v-for="integration in ctx.integrations"
|
|
962
|
+
:key="integration.id"
|
|
963
|
+
class="flex items-center gap-3 border-b py-2.5 last:border-b-0"
|
|
964
|
+
>
|
|
965
|
+
<BbIcon class="shrink-0" :icon="integration.icon" size="20" />
|
|
966
|
+
<div class="flex min-w-0 flex-1 flex-col">
|
|
967
|
+
<span class="font-medium">{{ integration.name }}</span>
|
|
968
|
+
<span class="truncate text-xs text-gray-500">
|
|
969
|
+
{{ integration.description }}
|
|
970
|
+
</span>
|
|
971
|
+
</div>
|
|
972
|
+
<!-- Instant-effect toggle: the context flips optimistically, holds the
|
|
973
|
+
switch readonly while in flight, and reverts + toasts on failure. -->
|
|
974
|
+
<BbSwitch
|
|
975
|
+
hide-label
|
|
976
|
+
:label="`Connect ${integration.name}`"
|
|
977
|
+
:model-value="integration.connected"
|
|
978
|
+
:name="`integration-${integration.id}`"
|
|
979
|
+
:readonly="integration.busy"
|
|
980
|
+
@update:model-value="(next) => ctx.toggleIntegration(integration, next)"
|
|
981
|
+
/>
|
|
982
|
+
</div>
|
|
983
|
+
</div>
|
|
984
|
+
</template>
|
|
985
|
+
|
|
986
|
+
<script setup lang="ts">
|
|
987
|
+
import { BbIcon, BbSwitch } from 'bitboss-ui';
|
|
988
|
+
import { useOnboardingWorkspace } from './context';
|
|
989
|
+
|
|
990
|
+
const ctx = useOnboardingWorkspace();
|
|
991
|
+
</script>
|
|
992
|
+
```
|
|
993
|
+
|
|
994
|
+
### InviteStep.vue
|
|
995
|
+
|
|
996
|
+
```vue
|
|
997
|
+
<!-- OnboardingChecklist/InviteStep.vue -->
|
|
998
|
+
<template>
|
|
999
|
+
<div class="flex flex-col gap-3 text-sm">
|
|
1000
|
+
<p class="text-gray-600">
|
|
1001
|
+
Paste addresses or type them — Enter or a comma adds each one.
|
|
1002
|
+
</p>
|
|
1003
|
+
|
|
1004
|
+
<div class="flex flex-wrap items-end gap-2">
|
|
1005
|
+
<BbTag
|
|
1006
|
+
v-model="emails"
|
|
1007
|
+
class="min-w-64 flex-1"
|
|
1008
|
+
compact
|
|
1009
|
+
:divider="['Enter', ',']"
|
|
1010
|
+
:errors="inviteError"
|
|
1011
|
+
label="Email addresses"
|
|
1012
|
+
:max="10"
|
|
1013
|
+
placeholder="ada.rossi@acme.com"
|
|
1014
|
+
prepend:icon="lucide:mail"
|
|
1015
|
+
@duplicate="
|
|
1016
|
+
(email) => (inviteError = `${email} is already in the list.`)
|
|
1017
|
+
"
|
|
1018
|
+
@max="() => (inviteError = 'You can invite up to 10 people at once.')"
|
|
1019
|
+
/>
|
|
1020
|
+
<BbSelect
|
|
1021
|
+
v-model="role"
|
|
1022
|
+
class="w-44"
|
|
1023
|
+
compact
|
|
1024
|
+
item-text="label"
|
|
1025
|
+
item-value="value"
|
|
1026
|
+
:items="roles"
|
|
1027
|
+
label="Role"
|
|
1028
|
+
label-mode="outside"
|
|
1029
|
+
/>
|
|
1030
|
+
<BbButton prepend:icon="lucide:send" variant="secondary" @click="send">
|
|
1031
|
+
Send invitations
|
|
1032
|
+
</BbButton>
|
|
1033
|
+
</div>
|
|
1034
|
+
|
|
1035
|
+
<ul v-if="ctx.invites.value.length" class="flex flex-col gap-1">
|
|
1036
|
+
<li
|
|
1037
|
+
v-for="invite in ctx.invites.value"
|
|
1038
|
+
:key="invite.email"
|
|
1039
|
+
class="flex items-center justify-between gap-2 text-xs"
|
|
1040
|
+
>
|
|
1041
|
+
<span>{{ invite.email }}</span>
|
|
1042
|
+
<span class="text-gray-500"
|
|
1043
|
+
>{{ invite.role }} · invited {{ invite.sentAt }}</span
|
|
1044
|
+
>
|
|
1045
|
+
</li>
|
|
1046
|
+
</ul>
|
|
1047
|
+
</div>
|
|
1048
|
+
</template>
|
|
1049
|
+
|
|
1050
|
+
<script setup lang="ts">
|
|
1051
|
+
import { ref } from 'vue';
|
|
1052
|
+
import { BbButton, BbSelect, BbTag } from 'bitboss-ui';
|
|
1053
|
+
import { useOnboardingWorkspace } from './context';
|
|
1054
|
+
import type { InviteRole } from '@/types';
|
|
1055
|
+
|
|
1056
|
+
const ctx = useOnboardingWorkspace();
|
|
1057
|
+
|
|
1058
|
+
// Draft state only this leaf touches: local refs, not context fields.
|
|
1059
|
+
const emails = ref<string[]>([]);
|
|
1060
|
+
const role = ref<InviteRole>('member');
|
|
1061
|
+
const inviteError = ref('');
|
|
1062
|
+
|
|
1063
|
+
const roles: { value: InviteRole; label: string }[] = [
|
|
1064
|
+
{ value: 'admin', label: 'Admin' },
|
|
1065
|
+
{ value: 'member', label: 'Member' },
|
|
1066
|
+
{ value: 'accountant', label: 'Accountant' },
|
|
1067
|
+
];
|
|
1068
|
+
|
|
1069
|
+
// Returning the promise lets the button's automatic loading track the send.
|
|
1070
|
+
const send = async () => {
|
|
1071
|
+
inviteError.value = '';
|
|
1072
|
+
if (emails.value.length === 0) {
|
|
1073
|
+
inviteError.value = 'Add at least one email address.';
|
|
1074
|
+
return;
|
|
1075
|
+
}
|
|
1076
|
+
const invalid = emails.value.filter((email) => !email.includes('@'));
|
|
1077
|
+
if (invalid.length > 0) {
|
|
1078
|
+
inviteError.value = `${invalid.join(', ')} ${invalid.length === 1 ? 'is' : 'are'} not a valid address.`;
|
|
1079
|
+
return;
|
|
1080
|
+
}
|
|
1081
|
+
try {
|
|
1082
|
+
await ctx.sendInvites(emails.value, role.value);
|
|
1083
|
+
emails.value = [];
|
|
1084
|
+
} catch (errors) {
|
|
1085
|
+
// Server-side (422) validation lands here as Laravel's field-keyed
|
|
1086
|
+
// error bag — usePromiseForm rejects with it unchanged.
|
|
1087
|
+
const bag = errors as Record<string, string | string[]>;
|
|
1088
|
+
const message = bag.emails ?? bag.role;
|
|
1089
|
+
inviteError.value = Array.isArray(message)
|
|
1090
|
+
? message[0]
|
|
1091
|
+
: (message ?? 'Could not send invitations.');
|
|
1092
|
+
}
|
|
1093
|
+
};
|
|
1094
|
+
</script>
|
|
1095
|
+
```
|
|
1096
|
+
|
|
1097
|
+
### FirstProjectStep.vue
|
|
1098
|
+
|
|
1099
|
+
```vue
|
|
1100
|
+
<!-- OnboardingChecklist/FirstProjectStep.vue -->
|
|
1101
|
+
<template>
|
|
1102
|
+
<!-- Already created (by this session or a teammate): show it, not the form. -->
|
|
1103
|
+
<div v-if="ctx.firstProject.value" class="flex items-center gap-2 text-sm">
|
|
1104
|
+
<BbIcon class="text-green-600" icon="lucide:circle-check" size="16" />
|
|
1105
|
+
<span>
|
|
1106
|
+
<span class="font-medium">{{ ctx.firstProject.value.name }}</span>
|
|
1107
|
+
is ready for its first invoice.
|
|
1108
|
+
</span>
|
|
1109
|
+
<BbButton
|
|
1110
|
+
append:icon="lucide:arrow-up-right"
|
|
1111
|
+
:href="`/projects/${ctx.firstProject.value.id}`"
|
|
1112
|
+
size="sm"
|
|
1113
|
+
variant="link"
|
|
1114
|
+
>
|
|
1115
|
+
Open project
|
|
1116
|
+
</BbButton>
|
|
1117
|
+
</div>
|
|
1118
|
+
|
|
1119
|
+
<form
|
|
1120
|
+
v-else
|
|
1121
|
+
class="flex flex-col gap-3 text-sm"
|
|
1122
|
+
novalidate
|
|
1123
|
+
@submit.prevent="submit"
|
|
1124
|
+
>
|
|
1125
|
+
<p class="text-gray-600">
|
|
1126
|
+
A project keeps one client's invoices, budget and time entries together.
|
|
1127
|
+
</p>
|
|
1128
|
+
<div class="flex flex-wrap items-end gap-2">
|
|
1129
|
+
<BbTextInput
|
|
1130
|
+
v-model="draft.name"
|
|
1131
|
+
class="min-w-56 flex-1"
|
|
1132
|
+
compact
|
|
1133
|
+
:errors="nameError"
|
|
1134
|
+
label="Project name"
|
|
1135
|
+
label-mode="outside"
|
|
1136
|
+
placeholder="Website redesign"
|
|
1137
|
+
/>
|
|
1138
|
+
<BbTextInput
|
|
1139
|
+
v-model="draft.client"
|
|
1140
|
+
class="min-w-56 flex-1"
|
|
1141
|
+
compact
|
|
1142
|
+
label="Client"
|
|
1143
|
+
label-mode="outside"
|
|
1144
|
+
placeholder="Globex Corporation"
|
|
1145
|
+
/>
|
|
1146
|
+
<BbButton prepend:icon="lucide:plus" type="submit" variant="secondary">
|
|
1147
|
+
Create project
|
|
1148
|
+
</BbButton>
|
|
1149
|
+
</div>
|
|
1150
|
+
</form>
|
|
1151
|
+
</template>
|
|
1152
|
+
|
|
1153
|
+
<script setup lang="ts">
|
|
1154
|
+
import { reactive, ref } from 'vue';
|
|
1155
|
+
import { BbButton, BbIcon, BbTextInput } from 'bitboss-ui';
|
|
1156
|
+
import { useOnboardingWorkspace } from './context';
|
|
1157
|
+
|
|
1158
|
+
const ctx = useOnboardingWorkspace();
|
|
1159
|
+
|
|
1160
|
+
const draft = reactive({ name: '', client: '' });
|
|
1161
|
+
const nameError = ref('');
|
|
1162
|
+
|
|
1163
|
+
// Returning the promise lets the submit button track the async work.
|
|
1164
|
+
const submit = async () => {
|
|
1165
|
+
nameError.value = '';
|
|
1166
|
+
if (!draft.name.trim()) {
|
|
1167
|
+
nameError.value = 'Give the project a name.';
|
|
1168
|
+
return;
|
|
1169
|
+
}
|
|
1170
|
+
try {
|
|
1171
|
+
await ctx.createProject({ ...draft });
|
|
1172
|
+
} catch (errors) {
|
|
1173
|
+
// Server-side (422) validation lands here as Laravel's field-keyed
|
|
1174
|
+
// error bag — usePromiseForm rejects with it unchanged.
|
|
1175
|
+
const bag = errors as Record<string, string | string[]>;
|
|
1176
|
+
const message = bag.name ?? bag.client;
|
|
1177
|
+
nameError.value = Array.isArray(message)
|
|
1178
|
+
? message[0]
|
|
1179
|
+
: (message ?? 'Could not create the project.');
|
|
1180
|
+
}
|
|
1181
|
+
};
|
|
1182
|
+
</script>
|
|
1183
|
+
```
|
|
1184
|
+
|
|
1185
|
+
### ImportCustomersStep.vue
|
|
1186
|
+
|
|
1187
|
+
```vue
|
|
1188
|
+
<!-- OnboardingChecklist/ImportCustomersStep.vue -->
|
|
1189
|
+
<template>
|
|
1190
|
+
<div class="flex flex-col gap-3 text-sm">
|
|
1191
|
+
<!-- Already imported: report it instead of showing an empty dropzone. -->
|
|
1192
|
+
<div
|
|
1193
|
+
v-if="ctx.importState.importedCount !== null"
|
|
1194
|
+
class="flex items-center gap-2"
|
|
1195
|
+
>
|
|
1196
|
+
<BbIcon class="text-green-600" icon="lucide:circle-check" size="16" />
|
|
1197
|
+
<span>
|
|
1198
|
+
<span class="font-medium">{{ ctx.importState.importedCount }}</span>
|
|
1199
|
+
customers imported.
|
|
1200
|
+
</span>
|
|
1201
|
+
<BbButton
|
|
1202
|
+
append:icon="lucide:arrow-up-right"
|
|
1203
|
+
href="/customers"
|
|
1204
|
+
size="sm"
|
|
1205
|
+
variant="link"
|
|
1206
|
+
>
|
|
1207
|
+
View customers
|
|
1208
|
+
</BbButton>
|
|
1209
|
+
</div>
|
|
1210
|
+
|
|
1211
|
+
<template v-else>
|
|
1212
|
+
<!-- MIME + extension pairing: Excel exports often carry a non-CSV MIME
|
|
1213
|
+
type (or none at all on drag-drop) — '.csv' is what admits them. -->
|
|
1214
|
+
<BbDropzone
|
|
1215
|
+
v-model="file"
|
|
1216
|
+
:accept="['text/csv', '.csv']"
|
|
1217
|
+
:disabled="ctx.importState.uploading"
|
|
1218
|
+
:errors="fileError"
|
|
1219
|
+
:max-size="10 * 1024 * 1024"
|
|
1220
|
+
@error="onReject"
|
|
1221
|
+
>
|
|
1222
|
+
<template #default="{ dragging, focused, open }">
|
|
1223
|
+
<div
|
|
1224
|
+
class="flex flex-col items-center gap-2 rounded-[var(--bb-radius)] border-2 border-dashed p-6 text-center transition-colors"
|
|
1225
|
+
:class="[
|
|
1226
|
+
dragging
|
|
1227
|
+
? 'border-[color:var(--bb-primary)] bg-[color:var(--bb-panel)]'
|
|
1228
|
+
: '',
|
|
1229
|
+
focused ? 'ring-2 ring-[color:var(--bb-ring)]' : '',
|
|
1230
|
+
]"
|
|
1231
|
+
>
|
|
1232
|
+
<BbIcon
|
|
1233
|
+
class="text-gray-400"
|
|
1234
|
+
icon="lucide:file-spreadsheet"
|
|
1235
|
+
size="24"
|
|
1236
|
+
/>
|
|
1237
|
+
<p class="font-medium">
|
|
1238
|
+
{{
|
|
1239
|
+
dragging ? 'Drop your CSV here' : 'Drag your customers CSV here'
|
|
1240
|
+
}}
|
|
1241
|
+
</p>
|
|
1242
|
+
<p class="text-xs text-gray-500">
|
|
1243
|
+
We map name, email, VAT number and address columns. Up to 10 MB.
|
|
1244
|
+
</p>
|
|
1245
|
+
<BbButton size="sm" variant="ghost" @click="open"
|
|
1246
|
+
>or browse files</BbButton
|
|
1247
|
+
>
|
|
1248
|
+
</div>
|
|
1249
|
+
</template>
|
|
1250
|
+
</BbDropzone>
|
|
1251
|
+
|
|
1252
|
+
<!-- Captured, not yet imported: confirm before touching the workspace. -->
|
|
1253
|
+
<div v-if="file" class="flex items-center gap-2">
|
|
1254
|
+
<BbIcon
|
|
1255
|
+
class="shrink-0 text-gray-400"
|
|
1256
|
+
icon="lucide:file-text"
|
|
1257
|
+
size="16"
|
|
1258
|
+
/>
|
|
1259
|
+
<span class="min-w-0 flex-1 truncate">
|
|
1260
|
+
{{ file.name }}
|
|
1261
|
+
<span class="text-xs text-gray-500"
|
|
1262
|
+
>· {{ formatSize(file.size) }}</span
|
|
1263
|
+
>
|
|
1264
|
+
</span>
|
|
1265
|
+
<BbButton
|
|
1266
|
+
aria-label="Remove selected file"
|
|
1267
|
+
:disabled="ctx.importState.uploading"
|
|
1268
|
+
icon="lucide:x"
|
|
1269
|
+
size="sm"
|
|
1270
|
+
variant="ghost"
|
|
1271
|
+
@click="() => (file = null)"
|
|
1272
|
+
/>
|
|
1273
|
+
<BbButton
|
|
1274
|
+
:disabled="ctx.importState.uploading"
|
|
1275
|
+
prepend:icon="lucide:upload"
|
|
1276
|
+
variant="secondary"
|
|
1277
|
+
@click="startImport"
|
|
1278
|
+
>
|
|
1279
|
+
Import customers
|
|
1280
|
+
</BbButton>
|
|
1281
|
+
</div>
|
|
1282
|
+
|
|
1283
|
+
<!-- The dropzone captures; the context uploads and drives the bar. -->
|
|
1284
|
+
<div v-if="ctx.importState.uploading" class="flex flex-col gap-1">
|
|
1285
|
+
<BbProgress
|
|
1286
|
+
aria-label="Upload progress"
|
|
1287
|
+
:max="ctx.importState.totalBytes"
|
|
1288
|
+
:model-value="ctx.importState.sentBytes"
|
|
1289
|
+
/>
|
|
1290
|
+
<span class="text-xs text-gray-500">
|
|
1291
|
+
Uploading… {{ formatSize(ctx.importState.sentBytes) }} of
|
|
1292
|
+
{{ formatSize(ctx.importState.totalBytes) }}
|
|
1293
|
+
</span>
|
|
1294
|
+
</div>
|
|
1295
|
+
</template>
|
|
1296
|
+
</div>
|
|
1297
|
+
</template>
|
|
1298
|
+
|
|
1299
|
+
<script setup lang="ts">
|
|
1300
|
+
import { ref } from 'vue';
|
|
1301
|
+
import { BbButton, BbDropzone, BbIcon, BbProgress } from 'bitboss-ui';
|
|
1302
|
+
import type { DropZoneError } from 'bitboss-ui';
|
|
1303
|
+
import { useOnboardingWorkspace } from './context';
|
|
1304
|
+
|
|
1305
|
+
const ctx = useOnboardingWorkspace();
|
|
1306
|
+
|
|
1307
|
+
// The captured-but-not-imported file is this leaf's own state.
|
|
1308
|
+
const file = ref<File | null>(null);
|
|
1309
|
+
const fileError = ref('');
|
|
1310
|
+
|
|
1311
|
+
// Rejects never reach the model — map the typed error to a message and feed
|
|
1312
|
+
// it back through `errors` (the display is a round-trip, not automatic).
|
|
1313
|
+
const onReject = (error: DropZoneError) => {
|
|
1314
|
+
fileError.value =
|
|
1315
|
+
error.type === 'maxSize'
|
|
1316
|
+
? `${error.filename} is ${error.formattedSize} — the limit is ${error.formattedMaxSize}.`
|
|
1317
|
+
: error.type === 'accept'
|
|
1318
|
+
? `${error.filename} is not a CSV file.`
|
|
1319
|
+
: `${error.filename} was rejected.`;
|
|
1320
|
+
};
|
|
1321
|
+
|
|
1322
|
+
const startImport = async () => {
|
|
1323
|
+
if (!file.value) return;
|
|
1324
|
+
fileError.value = '';
|
|
1325
|
+
await ctx.importCustomers(file.value);
|
|
1326
|
+
file.value = null;
|
|
1327
|
+
};
|
|
1328
|
+
|
|
1329
|
+
const formatSize = (bytes: number) =>
|
|
1330
|
+
bytes >= 1024 * 1024
|
|
1331
|
+
? `${(bytes / 1024 / 1024).toFixed(1)} MB`
|
|
1332
|
+
: `${Math.max(1, Math.round(bytes / 1024))} KB`;
|
|
1333
|
+
</script>
|
|
1334
|
+
```
|
|
1335
|
+
|
|
1336
|
+
### FirstInvoiceStep.vue
|
|
1337
|
+
|
|
1338
|
+
```vue
|
|
1339
|
+
<!-- OnboardingChecklist/FirstInvoiceStep.vue -->
|
|
1340
|
+
<template>
|
|
1341
|
+
<div class="flex flex-col gap-3 text-sm">
|
|
1342
|
+
<p class="text-gray-600">
|
|
1343
|
+
The composer walks you through line items, taxes and payment terms. Every
|
|
1344
|
+
invoice goes out with a payment link — customers pay by card or bank
|
|
1345
|
+
transfer without creating an account. This step checks itself off when
|
|
1346
|
+
your first invoice is sent.
|
|
1347
|
+
</p>
|
|
1348
|
+
<div>
|
|
1349
|
+
<BbButton
|
|
1350
|
+
append:icon="lucide:arrow-up-right"
|
|
1351
|
+
href="/invoices/create"
|
|
1352
|
+
prepend:icon="lucide:receipt"
|
|
1353
|
+
variant="outline"
|
|
1354
|
+
>
|
|
1355
|
+
Open the invoice composer
|
|
1356
|
+
</BbButton>
|
|
1357
|
+
</div>
|
|
1358
|
+
</div>
|
|
1359
|
+
</template>
|
|
1360
|
+
|
|
1361
|
+
<script setup lang="ts">
|
|
1362
|
+
import { BbButton } from 'bitboss-ui';
|
|
1363
|
+
</script>
|
|
1364
|
+
```
|
|
1365
|
+
|
|
1366
|
+
### RemindersStep.vue
|
|
1367
|
+
|
|
1368
|
+
```vue
|
|
1369
|
+
<!-- OnboardingChecklist/RemindersStep.vue -->
|
|
1370
|
+
<template>
|
|
1371
|
+
<div class="flex flex-col gap-3 text-sm">
|
|
1372
|
+
<!-- Instant-effect switch: the context applies optimistically and reverts
|
|
1373
|
+
with a toast if the server rejects the change. -->
|
|
1374
|
+
<BbSwitch
|
|
1375
|
+
description="Email customers automatically when an invoice goes overdue. Replies land in your inbox."
|
|
1376
|
+
label="Automatic payment reminders"
|
|
1377
|
+
:model-value="ctx.reminders.enabled"
|
|
1378
|
+
name="payment-reminders"
|
|
1379
|
+
@update:model-value="(next) => ctx.setReminders(next)"
|
|
1380
|
+
/>
|
|
1381
|
+
<BbSelect
|
|
1382
|
+
v-if="ctx.reminders.enabled"
|
|
1383
|
+
class="max-w-72"
|
|
1384
|
+
compact
|
|
1385
|
+
item-text="label"
|
|
1386
|
+
item-value="value"
|
|
1387
|
+
:items="cadences"
|
|
1388
|
+
label="Reminder schedule"
|
|
1389
|
+
label-mode="outside"
|
|
1390
|
+
:model-value="ctx.reminders.cadence"
|
|
1391
|
+
@update:model-value="(cadence) => ctx.setReminderCadence(cadence)"
|
|
1392
|
+
/>
|
|
1393
|
+
</div>
|
|
1394
|
+
</template>
|
|
1395
|
+
|
|
1396
|
+
<script setup lang="ts">
|
|
1397
|
+
import { BbSelect, BbSwitch } from 'bitboss-ui';
|
|
1398
|
+
import { useOnboardingWorkspace } from './context';
|
|
1399
|
+
import type { ReminderCadence } from '@/types';
|
|
1400
|
+
|
|
1401
|
+
const ctx = useOnboardingWorkspace();
|
|
1402
|
+
|
|
1403
|
+
const cadences: { value: ReminderCadence; label: string }[] = [
|
|
1404
|
+
{ value: '3-7-14', label: '3, 7 and 14 days overdue' },
|
|
1405
|
+
{ value: '7', label: '7 days overdue' },
|
|
1406
|
+
{ value: '7-30', label: '7 and 30 days overdue' },
|
|
1407
|
+
];
|
|
1408
|
+
</script>
|
|
1409
|
+
```
|
|
1410
|
+
|
|
1411
|
+
### StepPreviewPeek.vue
|
|
1412
|
+
|
|
1413
|
+
```vue
|
|
1414
|
+
<!-- OnboardingChecklist/StepPreviewPeek.vue -->
|
|
1415
|
+
<template>
|
|
1416
|
+
<div class="flex flex-col gap-4 text-sm">
|
|
1417
|
+
<!-- Identity header. -->
|
|
1418
|
+
<header class="flex items-center gap-3">
|
|
1419
|
+
<span
|
|
1420
|
+
class="flex h-9 w-9 shrink-0 items-center justify-center rounded-[var(--bb-radius)] border"
|
|
1421
|
+
>
|
|
1422
|
+
<BbIcon :icon="preview.icon" size="18" />
|
|
1423
|
+
</span>
|
|
1424
|
+
<div class="flex min-w-0 flex-col">
|
|
1425
|
+
<h2 class="text-base font-semibold">{{ preview.title }}</h2>
|
|
1426
|
+
<p class="text-xs text-gray-500">{{ preview.tagline }}</p>
|
|
1427
|
+
</div>
|
|
1428
|
+
</header>
|
|
1429
|
+
|
|
1430
|
+
<p
|
|
1431
|
+
v-if="step.status !== 'todo'"
|
|
1432
|
+
class="flex items-center gap-1.5 text-xs text-gray-500"
|
|
1433
|
+
>
|
|
1434
|
+
<!-- Green is earned: skipped reads as reached-but-unmeasured, not done. -->
|
|
1435
|
+
<BbIcon
|
|
1436
|
+
:class="step.status === 'complete' ? 'text-green-600' : 'text-gray-400'"
|
|
1437
|
+
icon="lucide:circle-check"
|
|
1438
|
+
size="14"
|
|
1439
|
+
/>
|
|
1440
|
+
{{
|
|
1441
|
+
step.status === 'complete'
|
|
1442
|
+
? 'Already done in this workspace.'
|
|
1443
|
+
: 'Skipped — you can still set it up.'
|
|
1444
|
+
}}
|
|
1445
|
+
</p>
|
|
1446
|
+
|
|
1447
|
+
<!-- What you'll get. -->
|
|
1448
|
+
<section class="flex flex-col gap-2.5">
|
|
1449
|
+
<h3 class="text-xs font-semibold uppercase tracking-wide text-gray-500">
|
|
1450
|
+
What you'll get
|
|
1451
|
+
</h3>
|
|
1452
|
+
<ul class="flex flex-col gap-2.5">
|
|
1453
|
+
<li
|
|
1454
|
+
v-for="bullet in preview.bullets"
|
|
1455
|
+
:key="bullet.title"
|
|
1456
|
+
class="flex gap-2"
|
|
1457
|
+
>
|
|
1458
|
+
<BbIcon
|
|
1459
|
+
class="mt-0.5 shrink-0 text-gray-400"
|
|
1460
|
+
:icon="bullet.icon"
|
|
1461
|
+
size="14"
|
|
1462
|
+
/>
|
|
1463
|
+
<div class="flex flex-col">
|
|
1464
|
+
<span class="font-medium">{{ bullet.title }}</span>
|
|
1465
|
+
<span class="text-xs text-gray-500">{{ bullet.text }}</span>
|
|
1466
|
+
</div>
|
|
1467
|
+
</li>
|
|
1468
|
+
</ul>
|
|
1469
|
+
</section>
|
|
1470
|
+
|
|
1471
|
+
<!-- One concrete number beats three adjectives. -->
|
|
1472
|
+
<div class="rounded-[var(--bb-radius)] border p-3">
|
|
1473
|
+
<p class="text-lg font-semibold">{{ preview.stat.value }}</p>
|
|
1474
|
+
<p class="text-xs text-gray-500">{{ preview.stat.label }}</p>
|
|
1475
|
+
</div>
|
|
1476
|
+
|
|
1477
|
+
<footer class="mt-2 flex items-center gap-2 border-t pt-3">
|
|
1478
|
+
<BbButton
|
|
1479
|
+
v-if="step.status === 'todo'"
|
|
1480
|
+
prepend:icon="lucide:check"
|
|
1481
|
+
variant="secondary"
|
|
1482
|
+
@click="() => ctx.jumpToStep(stepId)"
|
|
1483
|
+
>
|
|
1484
|
+
Set it up now
|
|
1485
|
+
</BbButton>
|
|
1486
|
+
<BbButton v-else variant="ghost" @click="() => ctx.jumpToStep(stepId)">
|
|
1487
|
+
Review this step
|
|
1488
|
+
</BbButton>
|
|
1489
|
+
</footer>
|
|
1490
|
+
</div>
|
|
1491
|
+
</template>
|
|
1492
|
+
|
|
1493
|
+
<script setup lang="ts">
|
|
1494
|
+
import { computed } from 'vue';
|
|
1495
|
+
import { BbButton, BbIcon } from 'bitboss-ui';
|
|
1496
|
+
import { useOnboardingWorkspace, type StepId } from './context';
|
|
1497
|
+
|
|
1498
|
+
const props = defineProps<{ stepId: StepId }>();
|
|
1499
|
+
|
|
1500
|
+
const ctx = useOnboardingWorkspace();
|
|
1501
|
+
|
|
1502
|
+
const step = computed(
|
|
1503
|
+
() => ctx.steps.find((candidate) => candidate.id === props.stepId)!
|
|
1504
|
+
);
|
|
1505
|
+
const preview = computed(() => previews[props.stepId]);
|
|
1506
|
+
|
|
1507
|
+
interface StepPreview {
|
|
1508
|
+
icon: string;
|
|
1509
|
+
title: string;
|
|
1510
|
+
tagline: string;
|
|
1511
|
+
bullets: { icon: string; title: string; text: string }[];
|
|
1512
|
+
stat: { value: string; label: string };
|
|
1513
|
+
}
|
|
1514
|
+
|
|
1515
|
+
// Presentation content with a single consumer: it lives in the leaf, not the
|
|
1516
|
+
// context. Icon names are full static literals for the production scanner.
|
|
1517
|
+
const previews: Record<StepId, StepPreview> = {
|
|
1518
|
+
profile: {
|
|
1519
|
+
icon: 'lucide:building-2',
|
|
1520
|
+
title: 'A complete company profile',
|
|
1521
|
+
tagline: 'Set once, printed on every document.',
|
|
1522
|
+
bullets: [
|
|
1523
|
+
{
|
|
1524
|
+
icon: 'lucide:file-text',
|
|
1525
|
+
title: 'Compliant invoices',
|
|
1526
|
+
text: 'Legal name, address and tax ID appear on every PDF automatically.',
|
|
1527
|
+
},
|
|
1528
|
+
{
|
|
1529
|
+
icon: 'lucide:euro',
|
|
1530
|
+
title: 'One currency for the books',
|
|
1531
|
+
text: 'Amounts, totals and reports all use your workspace currency.',
|
|
1532
|
+
},
|
|
1533
|
+
],
|
|
1534
|
+
stat: {
|
|
1535
|
+
value: '2 min',
|
|
1536
|
+
label: 'to update it later under Settings → General',
|
|
1537
|
+
},
|
|
1538
|
+
},
|
|
1539
|
+
integrations: {
|
|
1540
|
+
icon: 'lucide:link',
|
|
1541
|
+
title: 'Your tools, wired together',
|
|
1542
|
+
tagline:
|
|
1543
|
+
'Payments, accounting and alerts stop being three separate chores.',
|
|
1544
|
+
bullets: [
|
|
1545
|
+
{
|
|
1546
|
+
icon: 'lucide:credit-card',
|
|
1547
|
+
title: 'Payments reconcile themselves',
|
|
1548
|
+
text: 'Stripe payouts are matched against open invoices automatically.',
|
|
1549
|
+
},
|
|
1550
|
+
{
|
|
1551
|
+
icon: 'lucide:receipt',
|
|
1552
|
+
title: 'Books stay current',
|
|
1553
|
+
text: 'Paid invoices flow into QuickBooks the moment they settle.',
|
|
1554
|
+
},
|
|
1555
|
+
{
|
|
1556
|
+
icon: 'lucide:bell',
|
|
1557
|
+
title: 'The team finds out in Slack',
|
|
1558
|
+
text: '#finance gets a message on every paid and overdue invoice.',
|
|
1559
|
+
},
|
|
1560
|
+
],
|
|
1561
|
+
stat: {
|
|
1562
|
+
value: '9 days',
|
|
1563
|
+
label: 'faster average payment for teams with Stripe connected',
|
|
1564
|
+
},
|
|
1565
|
+
},
|
|
1566
|
+
invites: {
|
|
1567
|
+
icon: 'lucide:users',
|
|
1568
|
+
title: 'Everyone on the same numbers',
|
|
1569
|
+
tagline: 'Roles keep access right-sized from day one.',
|
|
1570
|
+
bullets: [
|
|
1571
|
+
{
|
|
1572
|
+
icon: 'lucide:user-plus',
|
|
1573
|
+
title: 'Sign-in with work email',
|
|
1574
|
+
text: 'Invitees join with their address — no shared passwords.',
|
|
1575
|
+
},
|
|
1576
|
+
{
|
|
1577
|
+
icon: 'lucide:key-round',
|
|
1578
|
+
title: 'Permissions per role',
|
|
1579
|
+
text: 'Accountants see reports; members see their own projects.',
|
|
1580
|
+
},
|
|
1581
|
+
{
|
|
1582
|
+
icon: 'lucide:clock',
|
|
1583
|
+
title: 'Invitations expire safely',
|
|
1584
|
+
text: 'Unaccepted invites lapse after 7 days and can be re-sent.',
|
|
1585
|
+
},
|
|
1586
|
+
],
|
|
1587
|
+
stat: { value: '10', label: 'invitations per batch' },
|
|
1588
|
+
},
|
|
1589
|
+
'first-project': {
|
|
1590
|
+
icon: 'lucide:folder',
|
|
1591
|
+
title: 'A home for each client',
|
|
1592
|
+
tagline: 'Projects keep invoices, budgets and time in one place.',
|
|
1593
|
+
bullets: [
|
|
1594
|
+
{
|
|
1595
|
+
icon: 'lucide:folder-open',
|
|
1596
|
+
title: 'Everything grouped',
|
|
1597
|
+
text: 'Invoices, budgets and time entries organized per client.',
|
|
1598
|
+
},
|
|
1599
|
+
{
|
|
1600
|
+
icon: 'lucide:chart-line',
|
|
1601
|
+
title: 'Profitability from day one',
|
|
1602
|
+
text: 'A per-project margin view as soon as the first invoice is paid.',
|
|
1603
|
+
},
|
|
1604
|
+
],
|
|
1605
|
+
stat: {
|
|
1606
|
+
value: '3',
|
|
1607
|
+
label: 'projects created by the average team in week one',
|
|
1608
|
+
},
|
|
1609
|
+
},
|
|
1610
|
+
'import-customers': {
|
|
1611
|
+
icon: 'lucide:file-spreadsheet',
|
|
1612
|
+
title: 'Your customer list, moved over',
|
|
1613
|
+
tagline: 'The CSV you already have is enough.',
|
|
1614
|
+
bullets: [
|
|
1615
|
+
{
|
|
1616
|
+
icon: 'lucide:upload',
|
|
1617
|
+
title: 'Columns mapped for you',
|
|
1618
|
+
text: 'Name, email, VAT number and address are detected automatically.',
|
|
1619
|
+
},
|
|
1620
|
+
{
|
|
1621
|
+
icon: 'lucide:check',
|
|
1622
|
+
title: 'No double imports',
|
|
1623
|
+
text: 'Rows are merged by email — re-running an import never duplicates.',
|
|
1624
|
+
},
|
|
1625
|
+
],
|
|
1626
|
+
stat: { value: '5,000', label: 'rows per import' },
|
|
1627
|
+
},
|
|
1628
|
+
'first-invoice': {
|
|
1629
|
+
icon: 'lucide:receipt',
|
|
1630
|
+
title: 'Your first invoice, out the door',
|
|
1631
|
+
tagline: 'Composed, sent and tracked in one flow.',
|
|
1632
|
+
bullets: [
|
|
1633
|
+
{
|
|
1634
|
+
icon: 'lucide:send',
|
|
1635
|
+
title: 'Sent from your domain',
|
|
1636
|
+
text: 'Invoices arrive from billing@your-company, not a noreply void.',
|
|
1637
|
+
},
|
|
1638
|
+
{
|
|
1639
|
+
icon: 'lucide:banknote',
|
|
1640
|
+
title: 'Payment link included',
|
|
1641
|
+
text: 'Customers pay by card or bank transfer without an account.',
|
|
1642
|
+
},
|
|
1643
|
+
{
|
|
1644
|
+
icon: 'lucide:clock',
|
|
1645
|
+
title: 'Overdue tracking starts itself',
|
|
1646
|
+
text: 'Due dates and aging are tracked from the moment you hit send.',
|
|
1647
|
+
},
|
|
1648
|
+
],
|
|
1649
|
+
stat: {
|
|
1650
|
+
value: '2×',
|
|
1651
|
+
label: 'faster payment on invoices with a payment link',
|
|
1652
|
+
},
|
|
1653
|
+
},
|
|
1654
|
+
reminders: {
|
|
1655
|
+
icon: 'lucide:bell',
|
|
1656
|
+
title: 'Overdue chasing, automated',
|
|
1657
|
+
tagline: 'Polite nudges on a schedule you choose.',
|
|
1658
|
+
bullets: [
|
|
1659
|
+
{
|
|
1660
|
+
icon: 'lucide:clock',
|
|
1661
|
+
title: 'A schedule, not a scramble',
|
|
1662
|
+
text: 'Reminders at 3, 7 and 14 days overdue — or the cadence you pick.',
|
|
1663
|
+
},
|
|
1664
|
+
{
|
|
1665
|
+
icon: 'lucide:mail',
|
|
1666
|
+
title: 'Replies reach a human',
|
|
1667
|
+
text: 'Customers answer straight into your inbox thread.',
|
|
1668
|
+
},
|
|
1669
|
+
],
|
|
1670
|
+
stat: {
|
|
1671
|
+
value: '38%',
|
|
1672
|
+
label: 'fewer invoices reach 30 days overdue with reminders on',
|
|
1673
|
+
},
|
|
1674
|
+
},
|
|
1675
|
+
};
|
|
1676
|
+
</script>
|
|
1677
|
+
```
|
|
1678
|
+
|
|
1679
|
+
## Why it is built this way
|
|
1680
|
+
|
|
1681
|
+
- **The context coopts the shell, leaves consume.** The only specific
|
|
1682
|
+
context on a checklist page is the peek stack; `provideOnboardingWorkspace()`
|
|
1683
|
+
joins it once and thirteen components share step state, integration
|
|
1684
|
+
state and every action through one `useOnboardingWorkspace()` call. No
|
|
1685
|
+
component receives a callback prop; the only data props are the `step` /
|
|
1686
|
+
`stepId` an item renders (`StepHeader`, `StepActions`, `StepPreviewPeek`)
|
|
1687
|
+
— everything else is injection.
|
|
1688
|
+
- **The server recomputes step statuses, so the client never has to.**
|
|
1689
|
+
Every mutation route — connect an integration, send invites, create the
|
|
1690
|
+
project, import customers, enable reminders — flips the relevant step's
|
|
1691
|
+
status server-side as part of the same request; the partial reload
|
|
1692
|
+
(`only: ['onboarding']`) brings that back in one round trip. There is no
|
|
1693
|
+
`persistStatus` writer like the Vue/Nuxt versions: the local `steps`
|
|
1694
|
+
array is purely a mirror of `applyState`, re-run by a `watch` every time
|
|
1695
|
+
the prop changes.
|
|
1696
|
+
- **`sendInvites`/`createProject` ride `usePromiseForm`, not the generic
|
|
1697
|
+
`visit()` helper.** They carry real user input with server-side
|
|
1698
|
+
validation, so a 422 needs to reach specific fields. `usePromiseForm`
|
|
1699
|
+
rejects with Laravel's field-keyed error bag on failure; `InviteStep` and
|
|
1700
|
+
`FirstProjectStep` are the only two leaves with a `try`/`catch` around
|
|
1701
|
+
their context call, mapping the bag onto the same `inviteError`/
|
|
1702
|
+
`nameError` display the client-side checks already populate — one error
|
|
1703
|
+
surface per field, whether the rejection came from the browser or the
|
|
1704
|
+
server.
|
|
1705
|
+
- **The CSV import binds the file into a `useForm`, not `FormData`.**
|
|
1706
|
+
Inertia detects the bound `File` and switches the request to multipart
|
|
1707
|
+
automatically, and `onProgress` reports real `loaded`/`total` bytes
|
|
1708
|
+
natively — no manual `FormData` assembly and no `XMLHttpRequest`, unlike
|
|
1709
|
+
the Nuxt adaptation (`ofetch` has no upload-progress hook, so that one
|
|
1710
|
+
forces a raw XHR).
|
|
1711
|
+
- **Single-open is one key, per the BbAccordion doctrine.** `BbAccordion`
|
|
1712
|
+
is deliberately one panel per boolean with no group wrapper; the
|
|
1713
|
+
`activeStep` key derives each `model-value`, the `update:modelValue`
|
|
1714
|
+
payload (`false` on closing the open header) resets it to `null`, and
|
|
1715
|
+
`openNextTodo` gives the Linear feel of the checklist walking itself
|
|
1716
|
+
forward. No watchers force-closing siblings.
|
|
1717
|
+
- **Headers stay passive, actions live in the body.** The accordion header
|
|
1718
|
+
is already a `<button>`; the status icon, minutes estimate and chevron in
|
|
1719
|
+
`StepHeader` are click-transparent metadata. Everything interactive —
|
|
1720
|
+
done, skip, preview, the step's real controls — is body content, so the
|
|
1721
|
+
markup stays valid and the click target stays whole.
|
|
1722
|
+
- **Every rung of the state ladder is deliberate.** Draft state one leaf
|
|
1723
|
+
touches is a local ref (invite emails and role, the project draft, the
|
|
1724
|
+
captured CSV file, the reject message); everything two components read
|
|
1725
|
+
sits on the context (statuses, `importState` driving `BbProgress`,
|
|
1726
|
+
reminders); nothing on this page outlives it, so no store is involved.
|
|
1727
|
+
- **The switch promise is kept.** Integration and reminder toggles apply
|
|
1728
|
+
optimistically, hold the control `readonly` while the request flies, and
|
|
1729
|
+
revert with a `destructive` toast on failure — the async-save pattern
|
|
1730
|
+
from the BbSwitch guide, owned by context actions so no leaf ever issues
|
|
1731
|
+
a visit or toasts on its own.
|
|
1732
|
+
- **Previews are peeks, not dialogs.** "See what you'll get" is the
|
|
1733
|
+
checklist's version of clicking a record's name: `previewStep` pushes
|
|
1734
|
+
onto the coopted shell stack with `replace` (previews never stack), and
|
|
1735
|
+
`jumpToStep` owns the way back — leaves never touch the stack grammar
|
|
1736
|
+
directly.
|
|
1737
|
+
- **Dismissal is a real redirect, not a partial reload.** `router.post`
|
|
1738
|
+
with no `only` list lets the server's redirect land on the dashboard;
|
|
1739
|
+
there is no `onboarding` prop left to re-seed from after it, so the
|
|
1740
|
+
action doesn't await one.
|
|
1741
|
+
- **Sizing and variants:** `md`-first throughout the bodies (28px buttons
|
|
1742
|
+
flush beside `compact` inputs in the invite and project rows); `sm` only
|
|
1743
|
+
for genuinely dense spots (inline links, the file-row remove); exactly
|
|
1744
|
+
one `variant="primary"` (Go to dashboard); step submits are `secondary`;
|
|
1745
|
+
dismissal is a ghost gated by a `destructive` `useConfirm`.
|
|
1746
|
+
|
|
1747
|
+
## Variations
|
|
1748
|
+
|
|
1749
|
+
- **Personal onboarding**: scope statuses per user instead of per
|
|
1750
|
+
workspace (`Inertia::render('Onboarding/Index', ['onboarding' =>
|
|
1751
|
+
OnboardingState::for($request->user())])`) and drop the workspace-wide
|
|
1752
|
+
dismiss confirm copy; the page shape is unchanged.
|
|
1753
|
+
- **Sequential (gated) steps**: lock each accordion until the previous
|
|
1754
|
+
step is done by rendering the body's controls `disabled` with an
|
|
1755
|
+
explanatory line; for hard gates with per-step validation, the
|
|
1756
|
+
wizard-form recipe is the full treatment.
|
|
1757
|
+
- **Preview follows the open step**: call `previewStep(id)` from
|
|
1758
|
+
`openStep` so the sidebar always previews the active step; keep the
|
|
1759
|
+
explicit footer button for touch users.
|
|
1760
|
+
- **All-done celebration**: when `allDone` flips, swap `ProgressHeader`'s
|
|
1761
|
+
copy block for a success panel with the dashboard CTA and a "book an
|
|
1762
|
+
onboarding call" link.
|
|
1763
|
+
- **Lazy integration catalog**: if the integrations list grows large or
|
|
1764
|
+
varies per plan, share it as `Inertia::lazy()` and read it with
|
|
1765
|
+
`useLazyProp` instead of hardcoding the four entries in `context.ts`.
|