bitboss-ui 3.0.0-beta.2 → 3.0.0-beta.21
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/README.md +72 -33
- package/dist/ai/BbAccordion.md +3 -3
- package/dist/ai/BbAlert.md +9 -5
- package/dist/ai/BbAsterisk.md +17 -0
- package/dist/ai/BbAvatar.md +12 -3
- package/dist/ai/BbBadge.md +15 -10
- package/dist/ai/BbBadgeButton.md +16 -16
- package/dist/ai/BbBaseButton.md +16 -16
- package/dist/ai/BbBaseCheckbox.md +8 -8
- package/dist/ai/BbBaseCheckboxGroup.md +13 -13
- package/dist/ai/BbBaseCheckboxIcon.md +26 -9
- package/dist/ai/BbBaseColorInput.md +11 -11
- package/dist/ai/BbBaseDatePicker.md +6 -6
- package/dist/ai/BbBaseDatePickerInput.md +15 -15
- package/dist/ai/BbBaseInputContainer.md +12 -12
- package/dist/ai/BbBaseNumberInput.md +8 -8
- package/dist/ai/BbBaseRadio.md +5 -5
- package/dist/ai/BbBaseRadioGroup.md +7 -7
- package/dist/ai/BbBaseRadioIcon.md +25 -9
- package/dist/ai/BbBaseRating.md +5 -5
- package/dist/ai/BbBaseSelect.md +22 -21
- package/dist/ai/BbBaseSlider.md +9 -9
- package/dist/ai/BbBaseSwitch.md +8 -8
- package/dist/ai/BbBaseSwitchGroup.md +13 -13
- package/dist/ai/BbBaseSwitchIcon.md +28 -10
- package/dist/ai/BbBaseTag.md +10 -10
- package/dist/ai/BbBaseTextInput.md +9 -9
- package/dist/ai/BbBaseTextarea.md +9 -9
- package/dist/ai/BbBaseTimePickerInput.md +13 -13
- package/dist/ai/BbBreadcrumbs.md +2 -2
- package/dist/ai/BbButton.md +15 -15
- package/dist/ai/BbCheckbox.md +18 -17
- package/dist/ai/BbCheckboxGroup.md +15 -14
- package/dist/ai/BbCollapsible.md +11 -9
- package/dist/ai/BbColorInput.md +15 -15
- package/dist/ai/BbColorPalette.md +12 -6
- package/dist/ai/BbConfirm.md +12 -5
- package/dist/ai/BbDatePicker.md +13 -13
- package/dist/ai/BbDatePickerInput.md +20 -20
- package/dist/ai/BbDialog.md +78 -12
- package/dist/ai/BbDropdown.md +132 -22
- package/dist/ai/BbDropdownButton.md +12 -12
- package/dist/ai/BbDropdownGroup.md +1 -1
- package/dist/ai/BbDropzone.md +4 -4
- package/dist/ai/BbForm.md +49 -14
- package/dist/ai/BbIcon.md +6 -0
- package/dist/ai/BbIndicator.md +5 -5
- package/dist/ai/BbNumberInput.md +11 -11
- package/dist/ai/BbOffCanvas.md +90 -20
- package/dist/ai/BbPagination.md +3 -3
- package/dist/ai/BbPopover.md +32 -17
- package/dist/ai/BbProgress.md +7 -4
- package/dist/ai/BbRadio.md +16 -15
- package/dist/ai/BbRadioGroup.md +20 -17
- package/dist/ai/BbRating.md +11 -11
- package/dist/ai/BbSelect.md +138 -37
- package/dist/ai/BbSelectPopover.md +40 -41
- package/dist/ai/BbSlider.md +37 -22
- package/dist/ai/BbSmoothHeight.md +1 -1
- package/dist/ai/BbSwitch.md +25 -10
- package/dist/ai/BbSwitchGroup.md +17 -14
- package/dist/ai/BbTable.md +920 -109
- package/dist/ai/BbTabs.md +28 -14
- package/dist/ai/BbTabsList.md +1 -1
- package/dist/ai/BbTabsPanes.md +1 -1
- package/dist/ai/BbTabsRoot.md +10 -10
- package/dist/ai/BbTag.md +14 -14
- package/dist/ai/BbTextInput.md +16 -15
- package/dist/ai/BbTextarea.md +13 -13
- package/dist/ai/BbTimePicker.md +10 -10
- package/dist/ai/BbTimePickerInput.md +17 -17
- package/dist/ai/BbToast.md +1 -1
- package/dist/ai/BbToastPortal.md +1 -1
- package/dist/ai/BbTooltip.md +12 -10
- package/dist/ai/BbTree.md +1 -1
- package/dist/ai/ChipsBox.md +1 -1
- package/dist/ai/CommonInputWrapper.md +10 -10
- package/dist/ai/CommonPopover.md +6 -6
- package/dist/ai/FlatListBox.md +5 -5
- package/dist/ai/GroupedListBox.md +5 -5
- package/dist/ai/ListBox.md +4 -4
- package/dist/ai/OptionsContainer.md +4 -4
- package/dist/ai/changelog.json +128 -2
- package/dist/ai/components.json +917 -100
- package/dist/ai/composables/useBbConfig.md +72 -11
- package/dist/ai/composables/useConfirm.md +5 -3
- package/dist/ai/guides/ai-router.md +9 -4
- package/dist/ai/guides/component-picker.md +18 -18
- package/dist/ai/guides/design-language.md +14 -14
- package/dist/ai/guides/design-tokens.md +25 -18
- package/dist/ai/guides/fetch-items-playbook.md +1 -1
- package/dist/ai/guides/icons-policy.md +11 -5
- package/dist/ai/guides/installation-and-plugin-setup.md +85 -23
- package/dist/ai/guides/migration/components/bb-checkbox-group.md +30 -0
- package/dist/ai/guides/migration/components/bb-checkbox.md +37 -3
- package/dist/ai/guides/migration/components/bb-collapsible.md +5 -5
- package/dist/ai/guides/migration/components/bb-dialog.md +62 -34
- package/dist/ai/guides/migration/components/bb-offcanvas.md +29 -13
- package/dist/ai/guides/migration/components/bb-rating.md +8 -2
- package/dist/ai/guides/migration/components/bb-select.md +5 -2
- package/dist/ai/guides/migration/components/bb-table.md +560 -28
- package/dist/ai/guides/migration/components/bb-text-input.md +6 -6
- package/dist/ai/guides/migration/v2-to-v3.md +260 -89
- package/dist/ai/guides/ssr-prefill.md +120 -0
- package/dist/ai/index.md +10 -9
- package/dist/ai/recipes/inertia/approvals-inbox.md +0 -1
- package/dist/ai/recipes/inertia/inline-edit-workspace.md +0 -1
- package/dist/ai/recipes/inertia/layout-scaffold.md +5 -1
- package/dist/ai/recipes/inertia/ownership-atlas.md +49 -29
- package/dist/ai/recipes/inertia/record-form.md +0 -1
- package/dist/ai/recipes/inertia/records-workspace.md +26 -8
- package/dist/ai/recipes/inertia/upload-center.md +0 -1
- package/dist/ai/recipes/nuxt/approvals-inbox.md +0 -1
- package/dist/ai/recipes/nuxt/inline-edit-workspace.md +0 -1
- package/dist/ai/recipes/nuxt/layout-scaffold.md +5 -1
- package/dist/ai/recipes/nuxt/record-form.md +0 -1
- package/dist/ai/recipes/nuxt/records-workspace.md +26 -8
- package/dist/ai/recipes/nuxt/upload-center.md +0 -1
- package/dist/ai/recipes/vue/approvals-inbox.md +0 -1
- package/dist/ai/recipes/vue/inline-edit-workspace.md +0 -1
- package/dist/ai/recipes/vue/layout-scaffold.md +5 -1
- package/dist/ai/recipes/vue/records-workspace.md +26 -8
- package/dist/ai/recipes/vue/upload-center.md +0 -1
- package/dist/ai/source/BbAlert.md +60 -2
- package/dist/ai/source/BbAvatar.md +3 -3
- package/dist/ai/source/BbBadge.md +60 -15
- package/dist/ai/source/BbBadgeButton.md +8 -2
- package/dist/ai/source/BbBaseButton.md +3 -1
- package/dist/ai/source/BbBaseCheckboxGroup.md +6 -2
- package/dist/ai/source/BbBaseDatePicker.md +3 -1
- package/dist/ai/source/BbBaseDatePickerInput.md +5 -1
- package/dist/ai/source/BbBaseInputContainer.md +52 -1
- package/dist/ai/source/BbBaseRadioGroup.md +4 -0
- package/dist/ai/source/BbBaseRating.md +3 -1
- package/dist/ai/source/BbBaseSelect.md +71 -16
- package/dist/ai/source/BbBaseSwitchGroup.md +4 -0
- package/dist/ai/source/BbBaseTimePickerInput.md +5 -1
- package/dist/ai/source/BbBreadcrumbs.md +31 -0
- package/dist/ai/source/BbButton.md +51 -24
- package/dist/ai/source/BbCheckbox.md +15 -1
- package/dist/ai/source/BbCheckboxGroup.md +2 -1
- package/dist/ai/source/BbCollapsible.md +7 -1
- package/dist/ai/source/BbColorInput.md +3 -4
- package/dist/ai/source/BbColorPalette.md +3 -4
- package/dist/ai/source/BbDatePicker.md +5 -1
- package/dist/ai/source/BbDatePickerInput.md +5 -1
- package/dist/ai/source/BbDialog.md +175 -19
- package/dist/ai/source/BbDropdown.md +376 -69
- package/dist/ai/source/BbDropdownGroup.md +330 -59
- package/dist/ai/source/BbForm.md +93 -5
- package/dist/ai/source/BbIcon.md +46 -36
- package/dist/ai/source/BbNumberInput.md +3 -4
- package/dist/ai/source/BbOffCanvas.md +474 -194
- package/dist/ai/source/BbPopover.md +24 -17
- package/dist/ai/source/BbProgress.md +2 -2
- package/dist/ai/source/BbRadio.md +15 -1
- package/dist/ai/source/BbRadioGroup.md +3 -1
- package/dist/ai/source/BbSelect.md +50 -2
- package/dist/ai/source/BbSelectPopover.md +171 -23
- package/dist/ai/source/BbSlider.md +3 -4
- package/dist/ai/source/BbSwitch.md +15 -1
- package/dist/ai/source/BbSwitchGroup.md +8 -5
- package/dist/ai/source/BbTable.md +5092 -1446
- package/dist/ai/source/BbTabs.md +6 -7
- package/dist/ai/source/BbTabsList.md +6 -7
- package/dist/ai/source/BbTabsPanes.md +6 -7
- package/dist/ai/source/BbTabsRoot.md +6 -7
- package/dist/ai/source/BbTag.md +3 -4
- package/dist/ai/source/BbTextInput.md +3 -4
- package/dist/ai/source/BbTextarea.md +3 -4
- package/dist/ai/source/BbTimePicker.md +4 -1
- package/dist/ai/source/BbTimePickerInput.md +5 -1
- package/dist/ai/source/BbToast.md +3 -1
- package/dist/ai/source/BbTooltip.md +5 -1
- package/dist/ai/source/CommonInputWrapper.md +4 -0
- package/dist/ai/source/CommonPopover.md +6 -0
- package/dist/ai/source/FlatListBox.md +11 -5
- package/dist/ai/source/GroupedListBox.md +7 -5
- package/dist/components/BbAlert/BbAlert.vue_vue_type_script_setup_true_lang.js +4 -4
- package/dist/components/BbAlert/types.d.ts +10 -1
- package/dist/components/BbAvatar/BbAvatar.vue.d.ts +1 -1
- package/dist/components/BbAvatar/BbAvatar.vue_vue_type_script_setup_true_lang.js +33 -33
- package/dist/components/BbBadge/BadgeBodyContent.vue_vue_type_script_setup_true_lang.js +22 -16
- package/dist/components/BbBadge/BbBadge.vue_vue_type_script_setup_true_lang.js +36 -15
- package/dist/components/BbBadge/badgeButtonContext.d.ts +21 -8
- package/dist/components/BbBadge/types.d.ts +8 -2
- package/dist/components/BbBaseButton/BbBaseButton.vue_vue_type_script_setup_true_lang.js +47 -47
- package/dist/components/BbBaseButton/RouterComponent.vue_vue_type_script_setup_true_lang.js +14 -14
- package/dist/components/BbBaseCheckboxGroup/BbBaseCheckboxGroup.vue_vue_type_script_setup_true_lang.js +30 -28
- package/dist/components/BbBaseCheckboxGroup/types.d.ts +2 -2
- package/dist/components/BbBaseDatePicker/BbBaseDatePicker.vue_vue_type_script_setup_true_lang.js +167 -167
- package/dist/components/BbBaseDatePicker/BbBaseDatePickerInputDaySelector.vue.d.ts +9 -9
- package/dist/components/BbBaseDatePicker/BbBaseDatePickerInputDaySelector.vue_vue_type_script_setup_true_lang.js +78 -78
- package/dist/components/BbBaseDatePicker/BbBaseDatePickerMonthSelector.vue_vue_type_script_setup_true_lang.js +64 -64
- package/dist/components/BbBaseDatePickerInput/BbBaseDatePickerInput.vue.d.ts +1 -1
- package/dist/components/BbBaseDatePickerInput/BbBaseDatePickerInput.vue_vue_type_script_setup_true_lang.js +138 -138
- package/dist/components/BbBaseInputContainer/BbBaseInputContainer.vue_vue_type_script_setup_true_lang.js +2 -2
- package/dist/components/BbBaseRadioGroup/BbBaseRadioGroup.vue_vue_type_script_setup_true_lang.js +24 -22
- package/dist/components/BbBaseRating/BbBaseRating.vue_vue_type_script_setup_true_lang.js +40 -40
- package/dist/components/BbBaseSelect/BbBaseSelect.vue_vue_type_script_setup_true_lang.js +74 -65
- package/dist/components/BbBaseSelect/types.d.ts +22 -0
- package/dist/components/BbBaseSlider/BbBaseSlider.vue_vue_type_script_setup_true_lang.js +5 -5
- package/dist/components/BbBaseSwitchGroup/BbBaseSwitchGroup.vue_vue_type_script_setup_true_lang.js +30 -28
- package/dist/components/BbBaseTimePickerInput/BbBaseTimePickerInput.vue.d.ts +1 -1
- package/dist/components/BbBaseTimePickerInput/BbBaseTimePickerInput.vue_vue_type_script_setup_true_lang.js +104 -104
- package/dist/components/BbBreadcrumbs/BbBreadcrumbs.vue_vue_type_script_setup_true_lang.js +35 -35
- package/dist/components/BbButton/BbButton.vue_vue_type_script_setup_true_lang.js +85 -81
- package/dist/components/BbCheckboxGroup/types.d.ts +2 -1
- package/dist/components/BbCollapsible/types.d.ts +7 -1
- package/dist/components/BbColorInput/BbColorInput.vue.d.ts +1 -1
- package/dist/components/BbColorInput/BbColorInput.vue_vue_type_script_setup_true_lang.js +18 -18
- package/dist/components/BbColorPalette/BbColorPalette.vue.d.ts +2 -2
- package/dist/components/BbColorPalette/BbColorPalette.vue_vue_type_script_setup_true_lang.js +50 -50
- package/dist/components/BbConfirm/BbConfirm.vue_vue_type_script_setup_true_lang.js +17 -17
- package/dist/components/BbDatePicker/BbDatePicker.vue.d.ts +1 -1
- package/dist/components/BbDatePicker/BbDatePicker.vue_vue_type_script_setup_true_lang.js +100 -100
- package/dist/components/BbDatePickerInput/BbDatePickerInput.vue_vue_type_script_setup_true_lang.js +21 -21
- package/dist/components/BbDialog/BbDialog.vue.d.ts +1 -1
- package/dist/components/BbDialog/BbDialog.vue_vue_type_script_setup_true_lang.js +133 -107
- package/dist/components/BbDialog/types.d.ts +29 -2
- package/dist/components/BbDropdown/AdaptiveDropdown.vue.d.ts +2 -0
- package/dist/components/BbDropdown/AdaptiveDropdown.vue_vue_type_script_setup_true_lang.js +99 -100
- package/dist/components/BbDropdown/BbDropdown.vue.d.ts +2 -2
- package/dist/components/BbDropdown/BbDropdown.vue_vue_type_script_setup_true_lang.js +208 -201
- package/dist/components/BbDropdown/BbDropdownList.vue_vue_type_script_setup_true_lang.js +225 -208
- package/dist/components/BbDropdown/DropdownPipelineResolver.vue_vue_type_script_setup_true_lang.js +21 -21
- package/dist/components/BbDropdown/types.d.ts +20 -5
- package/dist/components/BbDropdownButton/BbDropdownButton.vue_vue_type_script_setup_true_lang.js +5 -5
- package/dist/components/BbIcon/BbIcon.vue_vue_type_script_setup_true_lang.js +46 -46
- package/dist/components/BbIcon/iconCache.d.ts +33 -0
- package/dist/components/BbIcon/iconCache.js +17 -0
- package/dist/components/BbNumberInput/BbNumberInput.vue.d.ts +1 -1
- package/dist/components/BbNumberInput/BbNumberInput.vue_vue_type_script_setup_true_lang.js +15 -15
- package/dist/components/BbOffCanvas/BbOffCanvas.vue.d.ts +1 -1
- package/dist/components/BbOffCanvas/BbOffCanvas.vue_vue_type_script_setup_true_lang.js +254 -208
- package/dist/components/BbOffCanvas/types.d.ts +30 -5
- package/dist/components/BbPagination/BbPagination.vue.d.ts +1 -1
- package/dist/components/BbPopover/BbPopover.vue.d.ts +2 -2
- package/dist/components/BbPopover/BbPopover.vue_vue_type_script_setup_true_lang.js +149 -146
- package/dist/components/BbPopover/types.d.ts +3 -2
- package/dist/components/BbRadioGroup/types.d.ts +3 -1
- package/dist/components/BbSelect/BbSelect.vue_vue_type_script_setup_true_lang.js +27 -23
- package/dist/components/BbSelect/types.d.ts +32 -0
- package/dist/components/BbSelectPopover/BbSelectPopover.vue_vue_type_script_setup_true_lang.js +221 -213
- package/dist/components/BbSlider/BbSlider.vue.d.ts +1 -1
- package/dist/components/BbSlider/BbSlider.vue_vue_type_script_setup_true_lang.js +20 -20
- package/dist/components/BbTable/BbTable.vue.d.ts +10 -4
- package/dist/components/BbTable/BbTable.vue_vue_type_script_setup_true_lang.js +1433 -600
- package/dist/components/BbTable/BbTableDataRow.d.ts +162 -0
- package/dist/components/BbTable/BbTableDataRow.js +136 -0
- package/dist/components/BbTable/BbTableExpandRow.d.ts +73 -0
- package/dist/components/BbTable/BbTableExpandRow.js +52 -0
- package/dist/components/BbTable/types.d.ts +324 -111
- package/dist/components/BbTable/utils.d.ts +92 -4
- package/dist/components/BbTable/utils.js +71 -36
- package/dist/components/BbTabs/types.d.ts +0 -8
- package/dist/components/BbTag/BbTag.vue.d.ts +1 -1
- package/dist/components/BbTag/BbTag.vue_vue_type_script_setup_true_lang.js +18 -18
- package/dist/components/BbTextInput/BbTextInput.vue.d.ts +1 -1
- package/dist/components/BbTextInput/BbTextInput.vue_vue_type_script_setup_true_lang.js +18 -18
- package/dist/components/BbTextarea/BbTextarea.vue.d.ts +1 -1
- package/dist/components/BbTextarea/BbTextarea.vue_vue_type_script_setup_true_lang.js +54 -54
- package/dist/components/BbTimePicker/BbTimePicker.vue.d.ts +1 -1
- package/dist/components/BbTimePicker/BbTimePicker.vue_vue_type_script_setup_true_lang.js +80 -80
- package/dist/components/BbTimePickerInput/BbTimePickerInput.vue_vue_type_script_setup_true_lang.js +61 -61
- package/dist/components/BbToast/BbToast.vue_vue_type_script_setup_true_lang.js +17 -17
- package/dist/components/BbToast/BbToastMessage.vue_vue_type_script_setup_true_lang.js +13 -13
- package/dist/components/BbTooltip/types.d.ts +5 -1
- package/dist/components/ChipsBox/ChipsBox.vue_vue_type_script_setup_true_lang.js +17 -17
- package/dist/components/ClearableButton/ClearableButton.vue_vue_type_script_setup_true_lang.js +5 -5
- package/dist/components/CommonPopover/CommonPopover.vue_vue_type_script_setup_true_lang.js +2 -1
- package/dist/components/FlatListBox/FlatListBox.vue_vue_type_script_setup_true_lang.js +83 -83
- package/dist/components/GroupedListBox/GroupedListBox.vue_vue_type_script_setup_true_lang.js +56 -56
- package/dist/composables/useBaseOptions.js +30 -20
- package/dist/composables/useBbConfig.d.ts +27 -6
- package/dist/composables/useBbConfig.js +8 -2
- package/dist/composables/useConfig.d.ts +59 -0
- package/dist/composables/useConfig.js +9 -0
- package/dist/composables/useItemsGetter.d.ts +11 -0
- package/dist/composables/useItemsGetter.js +44 -18
- package/dist/composables/useLocale.js +10 -7
- package/dist/composables/useMobile.js +5 -5
- package/dist/composables/usePrefill.d.ts +21 -2
- package/dist/composables/usePrefill.js +25 -19
- package/dist/composables/useSsrState.d.ts +20 -0
- package/dist/composables/useSsrState.js +13 -0
- package/dist/composables/useTableWidthContext.d.ts +24 -4
- package/dist/composables/useTableWidthContext.js +31 -28
- package/dist/composables/useToast.js +5 -5
- package/dist/deprecation/ai-deprecations.json.d.ts +121 -11
- package/dist/deprecation/ai-deprecations.json.js +1 -1
- package/dist/directives/bbDropdown.d.ts +15 -4
- package/dist/directives/bbDropdown.js +31 -9
- package/dist/directives/createPopoverDirective.d.ts +62 -0
- package/dist/directives/createPopoverDirective.js +63 -23
- package/dist/i18n/locales/cs.json +4 -1
- package/dist/i18n/locales/da.json +4 -1
- package/dist/i18n/locales/de.json +4 -1
- package/dist/i18n/locales/el.json +4 -1
- package/dist/i18n/locales/en.json +4 -1
- package/dist/i18n/locales/es.json +4 -1
- package/dist/i18n/locales/fi.json +4 -1
- package/dist/i18n/locales/fr.json +4 -1
- package/dist/i18n/locales/hu.json +4 -1
- package/dist/i18n/locales/it.json +4 -1
- package/dist/i18n/locales/ja.json +4 -1
- package/dist/i18n/locales/ko.json +4 -1
- package/dist/i18n/locales/nb.json +4 -1
- package/dist/i18n/locales/nl.json +4 -1
- package/dist/i18n/locales/pl.json +4 -1
- package/dist/i18n/locales/pt.json +4 -1
- package/dist/i18n/locales/ro.json +4 -1
- package/dist/i18n/locales/ru.json +4 -1
- package/dist/i18n/locales/sv.json +4 -1
- package/dist/i18n/locales/tr.json +4 -1
- package/dist/i18n/locales/uk.json +4 -1
- package/dist/i18n/locales/zh-cn.json +4 -1
- package/dist/index.d.ts +7 -2
- package/dist/index.js +69 -67
- package/dist/llms-full.txt +3997 -1458
- package/dist/llms-medium.txt +140 -73
- package/dist/llms.txt +7 -6
- package/dist/locale-blueprint.json +4 -1
- package/dist/nuxt-auto-imports.d.ts +100 -0
- package/dist/nuxt-auto-imports.js +55 -0
- package/dist/nuxt-module.d.ts +22 -1
- package/dist/nuxt.js +22 -8
- package/dist/plugin.d.ts +10 -1
- package/dist/plugin.js +20 -19
- package/dist/runtime/nuxt-plugin.js +28 -21
- package/dist/styles.css +1 -1
- package/dist/utilities/misc/listboxMetrics.d.ts +3 -3
- package/dist/utilities/misc/listboxMetrics.js +2 -2
- package/dist/utilities/misc/ssrStateInjectionKey.d.ts +42 -0
- package/dist/utilities/misc/ssrStateInjectionKey.js +4 -0
- package/dist/validated/BbForm.vue_vue_type_script_setup_true_lang.js +45 -27
- package/dist/validated/BbSelect.vue.d.ts +2 -0
- package/dist/validated/BbSelect.vue_vue_type_script_setup_true_lang.js +1 -0
- package/dist/validated/useValidatedField.js +25 -23
- package/dist/vite.js +7 -3
- package/llms.txt +8 -7
- package/package.json +2 -2
- package/scripts/lib/eslint-plugin.d.ts +19 -1
- package/scripts/lib/eslint-plugin.mjs +155 -14
- package/scripts/lib/html-attributes.mjs +91 -0
- package/scripts/lib/validate-bb-markup.mjs +59 -11
- package/dist/assets/svgs/sort.svg_raw.js +0 -4
- package/dist/components/BbBadge/BadgeAppendIcon.vue.d.ts +0 -3
- package/dist/components/BbBadge/BadgeAppendIcon.vue.js +0 -5
- package/dist/components/BbBadge/BadgeAppendIcon.vue_vue_type_script_setup_true_lang.js +0 -22
|
@@ -333,11 +333,14 @@ export type InternalGroup = DropdownEntryBase & {
|
|
|
333
333
|
* predictable size regardless of row content. A `number` is pixels; a `string`
|
|
334
334
|
* is any CSS length (`'50vh'`, `'20rem'`). `'none'` (or `0`) removes the cap.
|
|
335
335
|
*
|
|
336
|
-
* `searchable` groups default to `280` (≈ 10 rows of 28px)
|
|
337
|
-
* list is usually long; set your own value to tweak, or
|
|
338
|
-
*
|
|
336
|
+
* `searchable` groups default to `280` (≈ 10 rows of 28px) **on the flyout**,
|
|
337
|
+
* since a searched list is usually long; set your own value to tweak, or
|
|
338
|
+
* `'none'` to uncap. The adaptive sheet ignores the cap so the OffCanvas
|
|
339
|
+
* body stays the only scroller (nested group overflow trapped swipes that
|
|
340
|
+
* started on a row). Non-searchable flyout groups are uncapped unless you
|
|
341
|
+
* set this.
|
|
339
342
|
*
|
|
340
|
-
* @defaultValue `280` for `searchable` groups, otherwise unset
|
|
343
|
+
* @defaultValue `280` for `searchable` flyout groups, otherwise unset
|
|
341
344
|
*/
|
|
342
345
|
maxHeight?: number | string;
|
|
343
346
|
/**
|
|
@@ -506,6 +509,17 @@ export type BbDropdownProps = {
|
|
|
506
509
|
* @defaultValue `config.adaptive` (`true`)
|
|
507
510
|
*/
|
|
508
511
|
adaptive?: boolean;
|
|
512
|
+
/**
|
|
513
|
+
* Apply the compact density variant — the same ladder `BbSelect` uses, on
|
|
514
|
+
* both surfaces: flyout rows go 28px → 24px, sheet rows 44px → 36px. The
|
|
515
|
+
* label size does not change; density here is height, as it is for a select.
|
|
516
|
+
*
|
|
517
|
+
* A menu row is a touch target in a way a select option is not quite — a
|
|
518
|
+
* mis-tap fires the neighbouring COMMAND rather than picking the wrong value
|
|
519
|
+
* — so the compact sheet stops at 36px and never follows the flyout down to
|
|
520
|
+
* 24px. That is the same floor the select's sheet holds.
|
|
521
|
+
*/
|
|
522
|
+
compact?: boolean;
|
|
509
523
|
/**
|
|
510
524
|
* Element the panel positions itself against, when it should differ from the
|
|
511
525
|
* activator — e.g. a wrapper that the activator is only a part of, so the menu
|
|
@@ -585,7 +599,8 @@ export type BbDropdownProps = {
|
|
|
585
599
|
padding?: number;
|
|
586
600
|
/**
|
|
587
601
|
* Position of the dropdown relative to the activator.
|
|
588
|
-
* Use `'cursor'` to anchor at the mouse/touch coordinates
|
|
602
|
+
* Use `'cursor'` to anchor at the mouse/touch coordinates.
|
|
603
|
+
* (No arrow is drawn either way — arrows are tooltip-only in v3.)
|
|
589
604
|
*
|
|
590
605
|
* @defaultValue `'bottom'`
|
|
591
606
|
*/
|
|
@@ -786,7 +801,9 @@ export type BbDropdownGroupEvents = {
|
|
|
786
801
|
## Styles
|
|
787
802
|
|
|
788
803
|
```css
|
|
789
|
-
/* @inherit --transition-duration — set inline by the adaptive surface
|
|
804
|
+
/* @inherit --transition-duration — set inline by the adaptive surface;
|
|
805
|
+
@inherit --py — the adaptive sheet's rules target BbOffCanvas elements, which
|
|
806
|
+
declare it on the panel */
|
|
790
807
|
.bb-dropdown {
|
|
791
808
|
overflow: visible;
|
|
792
809
|
|
|
@@ -999,7 +1016,11 @@ export type BbDropdownGroupEvents = {
|
|
|
999
1016
|
* is inert there and `max-height` alone caps it. */
|
|
1000
1017
|
flex: 1 1 auto;
|
|
1001
1018
|
flex-direction: column;
|
|
1002
|
-
|
|
1019
|
+
/* `--bb-fs`, matching the select's option label. These two menus sit at
|
|
1020
|
+
the same 28px row height on the same screen and their labels were a
|
|
1021
|
+
pixel apart (13 against 14) — the desktop twin of the sheet drift, and
|
|
1022
|
+
the kind of difference nobody can name but everybody sees. */
|
|
1023
|
+
font-size: var(--bb-fs);
|
|
1003
1024
|
gap: 1px;
|
|
1004
1025
|
line-height: 1.2;
|
|
1005
1026
|
max-height: var(--max-h, none);
|
|
@@ -1092,9 +1113,11 @@ export type BbDropdownGroupEvents = {
|
|
|
1092
1113
|
/* Keep natural row height under a capped, scrolling container. */
|
|
1093
1114
|
flex-shrink: 0;
|
|
1094
1115
|
height: 28px;
|
|
1095
|
-
/* Let the row sit inside a fixed `--w` panel instead of expanding it.
|
|
1116
|
+
/* Let the row sit inside a fixed `--w` panel instead of expanding it.
|
|
1117
|
+
* Also the containing block for the absolute selection check. */
|
|
1096
1118
|
min-width: 0;
|
|
1097
1119
|
padding: 2px 6px;
|
|
1120
|
+
position: relative;
|
|
1098
1121
|
text-align: left;
|
|
1099
1122
|
width: 100%;
|
|
1100
1123
|
|
|
@@ -1132,8 +1155,7 @@ export type BbDropdownGroupEvents = {
|
|
|
1132
1155
|
}
|
|
1133
1156
|
|
|
1134
1157
|
.item__prepend-icon,
|
|
1135
|
-
.item__append-icon
|
|
1136
|
-
.item__check {
|
|
1158
|
+
.item__append-icon {
|
|
1137
1159
|
--size: 16px;
|
|
1138
1160
|
flex-shrink: 0;
|
|
1139
1161
|
font-size: 15px;
|
|
@@ -1179,21 +1201,42 @@ export type BbDropdownGroupEvents = {
|
|
|
1179
1201
|
|
|
1180
1202
|
.item__prepend-icon,
|
|
1181
1203
|
.item__append-icon,
|
|
1182
|
-
.item__check,
|
|
1183
1204
|
.item__chevron {
|
|
1184
1205
|
margin-top: 2px;
|
|
1185
1206
|
}
|
|
1207
|
+
|
|
1208
|
+
/* Absolute check: pin to the title line, not the row mid-point. */
|
|
1209
|
+
.item__check {
|
|
1210
|
+
margin-top: 0;
|
|
1211
|
+
top: 6px;
|
|
1212
|
+
transform: none;
|
|
1213
|
+
}
|
|
1186
1214
|
}
|
|
1187
1215
|
|
|
1188
|
-
.item__check,
|
|
1189
1216
|
.item__chevron {
|
|
1190
1217
|
--size: 16px;
|
|
1191
1218
|
color: var(--bb-text-muted);
|
|
1219
|
+
flex-shrink: 0;
|
|
1220
|
+
font-size: 19px;
|
|
1192
1221
|
margin-inline-start: auto;
|
|
1193
1222
|
}
|
|
1194
1223
|
|
|
1224
|
+
/*
|
|
1225
|
+
* Selection check is out of flow. Selectable groups always mount the
|
|
1226
|
+
* glyph (stroke animates in when selected); leaving it in flex would
|
|
1227
|
+
* reserve ~24px on EVERY row and make ellipsis truncate as if an
|
|
1228
|
+
* append icon were present. Absolute + pad-only-when-selected lets
|
|
1229
|
+
* unselected labels use the full row.
|
|
1230
|
+
*/
|
|
1195
1231
|
.item__check {
|
|
1232
|
+
--size: 16px;
|
|
1196
1233
|
color: var(--bb-text);
|
|
1234
|
+
font-size: 15px;
|
|
1235
|
+
inset-inline-end: 6px;
|
|
1236
|
+
pointer-events: none;
|
|
1237
|
+
position: absolute;
|
|
1238
|
+
top: 50%;
|
|
1239
|
+
transform: translateY(-50%);
|
|
1197
1240
|
|
|
1198
1241
|
path {
|
|
1199
1242
|
stroke-dasharray: 30;
|
|
@@ -1204,16 +1247,14 @@ export type BbDropdownGroupEvents = {
|
|
|
1204
1247
|
}
|
|
1205
1248
|
|
|
1206
1249
|
&.bb-dropdown__item--selected {
|
|
1250
|
+
/* Keep the label clear of the absolute check. */
|
|
1251
|
+
padding-inline-end: calc(6px + 16px + 4px);
|
|
1252
|
+
|
|
1207
1253
|
.item__check path {
|
|
1208
1254
|
stroke-dashoffset: 0;
|
|
1209
1255
|
}
|
|
1210
1256
|
}
|
|
1211
1257
|
|
|
1212
|
-
.item__chevron {
|
|
1213
|
-
flex-shrink: 0;
|
|
1214
|
-
font-size: 19px;
|
|
1215
|
-
}
|
|
1216
|
-
|
|
1217
1258
|
&.bb-dropdown__item--variant-destructive {
|
|
1218
1259
|
color: var(--bb-danger);
|
|
1219
1260
|
|
|
@@ -1251,6 +1292,24 @@ export type BbDropdownGroupEvents = {
|
|
|
1251
1292
|
}
|
|
1252
1293
|
}
|
|
1253
1294
|
|
|
1295
|
+
/* ---- Compact density --------------------------------------------------
|
|
1296
|
+
* The same ladder `BbSelect` walks, so a dense toolbar can hold a select and a
|
|
1297
|
+
* menu that agree: the flyout drops 28px → 24px here, and the SHEET drops
|
|
1298
|
+
* 44px → 36px through `--sheet-row-h` (AdaptiveDropdown reads
|
|
1299
|
+
* `listboxOptionHeight`, the helper the listbox reads, so neither can drift).
|
|
1300
|
+
* The label does not shrink — density is height, exactly as it is for a select
|
|
1301
|
+
* — and the sheet never follows the flyout to 24px, because a menu row is a
|
|
1302
|
+
* touch target whose mis-tap fires the neighbouring COMMAND. */
|
|
1303
|
+
.bb-dropdown.bb-dropdown--compact {
|
|
1304
|
+
.bb-dropdown__item {
|
|
1305
|
+
height: 24px;
|
|
1306
|
+
}
|
|
1307
|
+
|
|
1308
|
+
.bb-dropdown__placeholder {
|
|
1309
|
+
min-height: 24px;
|
|
1310
|
+
}
|
|
1311
|
+
}
|
|
1312
|
+
|
|
1254
1313
|
/* ---- Adaptive drill-down sheet ----------------------------------------
|
|
1255
1314
|
* The mobile surface (`AdaptiveDropdown`) reuses the `.bb-dropdown` classes
|
|
1256
1315
|
* above by carrying `.bb-dropdown` on the off-canvas root; these rules only
|
|
@@ -1260,7 +1319,104 @@ export type BbDropdownGroupEvents = {
|
|
|
1260
1319
|
/* Shrink the off-canvas chrome so the sheet reads as compact as the desktop
|
|
1261
1320
|
panel rather than a full dialog. */
|
|
1262
1321
|
--dialog-gap: 8px;
|
|
1263
|
-
|
|
1322
|
+
/* The title tracks the row label rather than the off-canvas default. It was
|
|
1323
|
+
pulled DOWN to `--bb-fs - 1` (13px) once, which put it under the rows it
|
|
1324
|
+
heads; the default (`--bb-fs + 2`) fixed that until the rows moved to 18px
|
|
1325
|
+
and passed it again. Tied to the same constant, a title can no longer end
|
|
1326
|
+
up smaller than the list beneath it whatever that constant becomes. */
|
|
1327
|
+
--dialog-title-fs: var(--sheet-option-fs, 1rem);
|
|
1328
|
+
|
|
1329
|
+
/* Root sheet title via `offCanvasProps.title` (no drill nav / custom
|
|
1330
|
+
`#header`): centre it and tighten the title→divider air like BbSelect.
|
|
1331
|
+
`:not(:has(.bb-dropdown__nav))` keeps consumer `#header` content and the
|
|
1332
|
+
drill nav on their own layouts. */
|
|
1333
|
+
.bb-offcanvas__header:not(:has(.bb-dropdown__nav)) {
|
|
1334
|
+
border-bottom: var(--bb-border-w) solid var(--bb-border);
|
|
1335
|
+
padding-bottom: calc(var(--py) - 6px);
|
|
1336
|
+
|
|
1337
|
+
> .bb-offcanvas__title {
|
|
1338
|
+
flex: 1 1 auto;
|
|
1339
|
+
text-align: center;
|
|
1340
|
+
}
|
|
1341
|
+
}
|
|
1342
|
+
|
|
1343
|
+
/* Drill nav owns the title→body air. Drop the OffCanvas header's own bottom
|
|
1344
|
+
pad so it does not stack under the nav and push chips / search below
|
|
1345
|
+
BbSelect's. */
|
|
1346
|
+
.bb-offcanvas__header:has(.bb-dropdown__nav--drill) {
|
|
1347
|
+
padding-bottom: 0;
|
|
1348
|
+
}
|
|
1349
|
+
|
|
1350
|
+
/* Body used to start flush under the header. Match BbSelect's step down
|
|
1351
|
+
from the title rule. Specificity beats OffCanvas's nested shorthand.
|
|
1352
|
+
Skip headerless sheets (`--no-header`): OffCanvas already supplies the
|
|
1353
|
+
top inset (and the handle clearance) that this would otherwise crush to
|
|
1354
|
+
0.5rem — the filters root with no title / drill nav / `#header`. */
|
|
1355
|
+
&.bb-offcanvas:not(.bb-offcanvas--no-header)
|
|
1356
|
+
.bb-offcanvas__body
|
|
1357
|
+
.bb-offcanvas__body-content {
|
|
1358
|
+
padding-top: 0.5rem;
|
|
1359
|
+
}
|
|
1360
|
+
|
|
1361
|
+
/* Flat multi-group sheets: space a following section after the previous
|
|
1362
|
+
group's items/search. */
|
|
1363
|
+
.bb-dropdown__group-items + .bb-dropdown__group-title,
|
|
1364
|
+
.bb-dropdown__group-search + .bb-dropdown__group-title,
|
|
1365
|
+
.bb-dropdown__divider + .bb-dropdown__group-title {
|
|
1366
|
+
margin-top: 0.5rem;
|
|
1367
|
+
}
|
|
1368
|
+
|
|
1369
|
+
/* Group headers on the sheet read as BbSelect's sheet label — centred title
|
|
1370
|
+
weight/size, not the flyout's faint left-aligned section caption. No
|
|
1371
|
+
hairline here: the select sheet label's rule lives on the OffCanvas
|
|
1372
|
+
header, and repeating it under every group stacked like extra chrome.
|
|
1373
|
+
Nested drills with `hideLabel` skip this entirely; the drill nav title is
|
|
1374
|
+
already that label. */
|
|
1375
|
+
.bb-dropdown__group-title {
|
|
1376
|
+
align-items: center;
|
|
1377
|
+
border-bottom: 0;
|
|
1378
|
+
color: var(--bb-text);
|
|
1379
|
+
column-gap: 6px;
|
|
1380
|
+
display: flex;
|
|
1381
|
+
font-size: var(--dialog-title-fs, var(--sheet-option-fs, 1rem));
|
|
1382
|
+
font-weight: 500;
|
|
1383
|
+
justify-content: center;
|
|
1384
|
+
letter-spacing: normal;
|
|
1385
|
+
/* Match select's title→body air (`padding-bottom: calc(var(--py) - 6px)`
|
|
1386
|
+
on the OffCanvas header) so the label sits above the soft search the
|
|
1387
|
+
same way City sits above its field. */
|
|
1388
|
+
padding: 0.25rem 0 calc(var(--py, var(--bb-panel-p)) - 6px);
|
|
1389
|
+
|
|
1390
|
+
.group-title__content {
|
|
1391
|
+
flex: 1 1 auto;
|
|
1392
|
+
line-height: normal;
|
|
1393
|
+
overflow-x: clip;
|
|
1394
|
+
overflow-y: visible;
|
|
1395
|
+
text-align: center;
|
|
1396
|
+
}
|
|
1397
|
+
|
|
1398
|
+
.group-title__prepend-icon,
|
|
1399
|
+
.group-title__append-icon {
|
|
1400
|
+
--size: 1.25rem;
|
|
1401
|
+
font-size: var(--size);
|
|
1402
|
+
}
|
|
1403
|
+
}
|
|
1404
|
+
|
|
1405
|
+
/* Headerless sheet: the first group title IS the sheet label (Flat filters'
|
|
1406
|
+
"Status" beside BbSelect's "City"). Body already clears the handle via
|
|
1407
|
+
`--no-header` padding (`calc(var(--py) + 12px)`); the items-container's
|
|
1408
|
+
4px (meant for air under a nav divider) and the title's own 0.25rem top
|
|
1409
|
+
pad were stacking on top and dropping the label ~8px below City.
|
|
1410
|
+
Measured: City title @29px, Flat Status @33–37px before this. */
|
|
1411
|
+
&.bb-offcanvas--no-header .bb-dropdown__items-container {
|
|
1412
|
+
padding-top: 0;
|
|
1413
|
+
}
|
|
1414
|
+
|
|
1415
|
+
&.bb-offcanvas--no-header
|
|
1416
|
+
.bb-dropdown__items-container
|
|
1417
|
+
> .bb-dropdown__group-title:first-child {
|
|
1418
|
+
padding-top: 0;
|
|
1419
|
+
}
|
|
1264
1420
|
|
|
1265
1421
|
/* Clip the sideways level slide so it never spills a horizontal scrollbar. */
|
|
1266
1422
|
.bb-dropdown__adaptive-body {
|
|
@@ -1290,55 +1446,132 @@ export type BbDropdownGroupEvents = {
|
|
|
1290
1446
|
* construction, so this selector needs no viewport clause of its own. The
|
|
1291
1447
|
* JS half lives in `useTouchRowLadder`, for the virtualized option lists
|
|
1292
1448
|
* whose row heights feed a virtualizer instead of a stylesheet. */
|
|
1449
|
+
/* Belt for an explicit `maxHeight` leaking onto the sheet: never nest a
|
|
1450
|
+
second scrollport inside the OffCanvas body. */
|
|
1451
|
+
.bb-dropdown__group-items--capped {
|
|
1452
|
+
display: contents;
|
|
1453
|
+
max-height: none;
|
|
1454
|
+
overflow: visible;
|
|
1455
|
+
}
|
|
1456
|
+
|
|
1293
1457
|
.bb-dropdown__items-container {
|
|
1294
|
-
|
|
1458
|
+
/* Published by AdaptiveDropdown from `listboxMetrics`, the same helpers the
|
|
1459
|
+
select's sheet reads. The fallbacks are the shipped touch values, so the
|
|
1460
|
+
stylesheet still reads on its own. */
|
|
1461
|
+
font-size: var(--sheet-option-fs, 1rem);
|
|
1295
1462
|
max-height: none;
|
|
1296
1463
|
min-width: 0;
|
|
1297
1464
|
overflow-y: visible;
|
|
1298
|
-
|
|
1465
|
+
/* Horizontal inset is the OffCanvas body's `--px`. Do not re-pad here
|
|
1466
|
+
(or on the rows) to fake alignment with search/chips. */
|
|
1467
|
+
padding: 4px 0 0;
|
|
1299
1468
|
width: 100%;
|
|
1300
1469
|
|
|
1301
1470
|
.bb-dropdown__item {
|
|
1302
|
-
height: 44px;
|
|
1303
|
-
|
|
1471
|
+
height: var(--sheet-row-h, 44px);
|
|
1472
|
+
/* Flyout rows are `2px 6px`. +4px start so the label shares the
|
|
1473
|
+
search field's text edge (`padding-inline: 0.75rem` on the fill). */
|
|
1474
|
+
padding-left: calc(6px + 4px);
|
|
1475
|
+
/* iOS treats a <button> as a tap target and will not hand the pan to
|
|
1476
|
+
the sheet body unless the control itself opts into vertical panning.
|
|
1477
|
+
Without this, dismiss/scroll work on the handle and miss on rows. */
|
|
1478
|
+
touch-action: pan-y;
|
|
1304
1479
|
|
|
1305
1480
|
&.bb-dropdown__item--description {
|
|
1306
|
-
min-height: 44px;
|
|
1481
|
+
min-height: var(--sheet-row-h, 44px);
|
|
1307
1482
|
}
|
|
1308
1483
|
|
|
1484
|
+
.item__content {
|
|
1485
|
+
line-height: normal;
|
|
1486
|
+
overflow-x: clip;
|
|
1487
|
+
overflow-y: visible;
|
|
1488
|
+
}
|
|
1489
|
+
|
|
1490
|
+
/* One step under the row label, the same step the listbox puts between
|
|
1491
|
+
an option and its group header — so the two sheets' secondary text
|
|
1492
|
+
agrees as well as their primary. */
|
|
1309
1493
|
.item__description {
|
|
1310
|
-
font-size: calc(var(--
|
|
1494
|
+
font-size: calc(var(--sheet-option-fs, 1rem) - 2px);
|
|
1311
1495
|
line-height: 18px;
|
|
1312
1496
|
}
|
|
1313
1497
|
}
|
|
1314
1498
|
|
|
1315
1499
|
.bb-dropdown__placeholder {
|
|
1316
|
-
min-height: 44px;
|
|
1317
|
-
padding:
|
|
1500
|
+
min-height: var(--sheet-row-h, 44px);
|
|
1501
|
+
padding-left: calc(6px + 4px);
|
|
1318
1502
|
}
|
|
1319
1503
|
|
|
1320
|
-
.
|
|
1321
|
-
|
|
1322
|
-
|
|
1504
|
+
/* Icons scale with the label they sit beside. The desktop sizes (16px
|
|
1505
|
+
glyphs against a 13px label) were tuned for a 28px row; left alone in a
|
|
1506
|
+
44px row with an 18px label they read as undersized — the chevron that
|
|
1507
|
+
says "this opens another level" ended up the smallest thing in the row.
|
|
1508
|
+
One step up, so the glyph keeps roughly the proportion to its label that
|
|
1509
|
+
it has on the desktop panel. BbIcon reads `--size`; keep `font-size` on
|
|
1510
|
+
the same token so the glyph box and the type size cannot drift. */
|
|
1511
|
+
.item__prepend-icon,
|
|
1512
|
+
.item__append-icon,
|
|
1513
|
+
.item__check,
|
|
1514
|
+
.item__chevron {
|
|
1515
|
+
--size: 1.25rem;
|
|
1516
|
+
font-size: var(--size);
|
|
1323
1517
|
}
|
|
1518
|
+
|
|
1519
|
+
/* Group titles are restyled as select-sheet labels on `--adaptive`
|
|
1520
|
+
(see block above); do not re-apply the flyout caption metrics here. */
|
|
1324
1521
|
}
|
|
1325
1522
|
|
|
1523
|
+
/* Soft filled search — mirrors BbSelectPopover's sheet field: no underline
|
|
1524
|
+
rule, faint `--bb-muted` wash, and the same inset as sheet chips / row
|
|
1525
|
+
padding so the fill lines up. */
|
|
1326
1526
|
.bb-dropdown__group-search {
|
|
1327
|
-
|
|
1527
|
+
background-color: var(--bb-muted);
|
|
1528
|
+
border-bottom: 0;
|
|
1529
|
+
border-radius: var(--bb-radius);
|
|
1530
|
+
/* Undo the flyout's full-bleed negative margins. No extra inline inset —
|
|
1531
|
+
the OffCanvas body already pads `--px`. */
|
|
1532
|
+
margin: 0 0 0.25rem;
|
|
1533
|
+
padding: 0.625rem 0.75rem;
|
|
1534
|
+
position: relative;
|
|
1535
|
+
top: auto;
|
|
1536
|
+
transition: background-color var(--bb-transition-fast) ease;
|
|
1537
|
+
/* Flyout search is sticky `z-index: 1`; that same stacking painted over
|
|
1538
|
+
the sheet's grab handle once the body scrolled. */
|
|
1539
|
+
z-index: auto;
|
|
1540
|
+
|
|
1541
|
+
/* One emphasis stop above the resting --bb-muted (6%) fill. */
|
|
1542
|
+
&:focus-within {
|
|
1543
|
+
background-color: color-mix(in oklab, var(--bb-text) 8%, var(--bb-panel));
|
|
1544
|
+
}
|
|
1545
|
+
|
|
1546
|
+
/* Lens on the trailing edge, same side as BbSelect's sheet search. */
|
|
1547
|
+
.bb-dropdown__search-icon {
|
|
1548
|
+
order: 1;
|
|
1549
|
+
}
|
|
1550
|
+
|
|
1551
|
+
.bb-dropdown__search-input {
|
|
1552
|
+
font-size: var(--bb-input-fs);
|
|
1553
|
+
order: 0;
|
|
1554
|
+
}
|
|
1555
|
+
|
|
1556
|
+
/* Busy strip sits on the field's bottom edge (no border to overlay). */
|
|
1557
|
+
.bb-dropdown__group-loading {
|
|
1558
|
+
border-radius: 0 0 var(--bb-radius) var(--bb-radius);
|
|
1559
|
+
bottom: 0;
|
|
1560
|
+
}
|
|
1328
1561
|
}
|
|
1329
1562
|
|
|
1330
1563
|
/* Removable selection chips for the current multi-select level — sit above the
|
|
1331
1564
|
menu (and its search), mirroring BbSelect's sheet. */
|
|
1332
1565
|
.bb-dropdown__sheet-selection {
|
|
1333
1566
|
flex-shrink: 0;
|
|
1334
|
-
padding: 0
|
|
1567
|
+
padding: 0 0 0.5rem;
|
|
1335
1568
|
text-align: left;
|
|
1336
1569
|
}
|
|
1337
1570
|
|
|
1338
1571
|
.bb-dropdown__sheet-chips {
|
|
1339
1572
|
display: flex;
|
|
1340
1573
|
flex-wrap: wrap;
|
|
1341
|
-
gap:
|
|
1574
|
+
gap: 0.5rem;
|
|
1342
1575
|
}
|
|
1343
1576
|
|
|
1344
1577
|
/* Touch target: the xl badge is a ~24px pill — fine inline on desktop, too
|
|
@@ -1347,9 +1580,9 @@ export type BbDropdownGroupEvents = {
|
|
|
1347
1580
|
padding and a bigger clear glyph; the badge API stays untouched. Mirrors
|
|
1348
1581
|
BbSelectPopover's sheet chips. */
|
|
1349
1582
|
.bb-dropdown__sheet-chip {
|
|
1350
|
-
--min-size:
|
|
1351
|
-
--padding-inline:
|
|
1352
|
-
--clear-size:
|
|
1583
|
+
--min-size: 2.125rem;
|
|
1584
|
+
--padding-inline: 0.75rem;
|
|
1585
|
+
--clear-size: 1.25rem;
|
|
1353
1586
|
}
|
|
1354
1587
|
|
|
1355
1588
|
.bb-dropdown__nav {
|
|
@@ -1357,42 +1590,69 @@ export type BbDropdownGroupEvents = {
|
|
|
1357
1590
|
column-gap: 6px;
|
|
1358
1591
|
display: flex;
|
|
1359
1592
|
width: 100%;
|
|
1360
|
-
}
|
|
1361
1593
|
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1594
|
+
/* Drilled in: a navigation bar. The TITLE LINE sets the bar height — same
|
|
1595
|
+
as BbSelect's OffCanvas title — so City and Status share one baseline.
|
|
1596
|
+
The back control is a BbButton ghost sm, absolutely pinned to the
|
|
1597
|
+
OffCanvas header with equal inset from the sheet's top and left. */
|
|
1598
|
+
&--drill {
|
|
1599
|
+
/* Title line sets the bar height — same as BbSelect's OffCanvas title.
|
|
1600
|
+
Sit in the header's `--px`; do not pull out and re-pad to fake a
|
|
1601
|
+
full-bleed bar. Bottom pad matches BbSelect's
|
|
1602
|
+
`calc(var(--py) - 6px)`. No `position: relative` — the back button's
|
|
1603
|
+
containing block is the header. */
|
|
1604
|
+
display: block;
|
|
1605
|
+
padding-bottom: calc(var(--py, var(--bb-panel-p)) - 6px);
|
|
1606
|
+
|
|
1607
|
+
/* Equal inset from the sheet edges. Header is `position: relative`
|
|
1608
|
+
in OffCanvas. Size/chrome come from BbButton ghost sm.
|
|
1609
|
+
Use `--bb-panel-p`, not `--px`: BbButton redefines `--px` as its
|
|
1610
|
+
own padding token, which collapsed the inset to 10px. */
|
|
1611
|
+
.bb-dropdown__nav-back {
|
|
1612
|
+
left: var(--bb-panel-p);
|
|
1613
|
+
position: absolute;
|
|
1614
|
+
top: var(--bb-panel-p);
|
|
1615
|
+
|
|
1616
|
+
/* Same chevron_right asset the submenu rows use, pointed back. */
|
|
1617
|
+
.bb-button__icon {
|
|
1618
|
+
transform: rotate(180deg);
|
|
1619
|
+
}
|
|
1620
|
+
}
|
|
1376
1621
|
|
|
1377
|
-
|
|
1378
|
-
|
|
1622
|
+
/* Spacer kept in the DOM for the drill a11y tests; layout is now the
|
|
1623
|
+
title's equal inline gutters below. */
|
|
1624
|
+
.bb-dropdown__nav-gutter {
|
|
1625
|
+
display: none;
|
|
1626
|
+
}
|
|
1379
1627
|
}
|
|
1628
|
+
}
|
|
1380
1629
|
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
}
|
|
1630
|
+
/* Pure spacer, mirroring the back button's box (root / non-drill layouts). */
|
|
1631
|
+
.bb-dropdown__nav-gutter {
|
|
1632
|
+
height: 24px;
|
|
1633
|
+
width: 24px;
|
|
1386
1634
|
}
|
|
1387
1635
|
|
|
1388
|
-
.bb-dropdown__nav-title {
|
|
1636
|
+
.bb-offcanvas__title.bb-dropdown__nav-title {
|
|
1389
1637
|
flex: auto;
|
|
1390
1638
|
font-weight: 500;
|
|
1639
|
+
/* Same 1em line box as BbSelect's sheet title so the cap sits on the
|
|
1640
|
+
same baseline. Descenders ("Tags") paint into the drill nav's bottom
|
|
1641
|
+
pad — `overflow-y: visible`; ellipsis still clips on X only. */
|
|
1391
1642
|
min-width: 0;
|
|
1392
|
-
overflow:
|
|
1643
|
+
overflow-x: clip;
|
|
1644
|
+
overflow-y: visible;
|
|
1393
1645
|
text-overflow: ellipsis;
|
|
1394
1646
|
white-space: nowrap;
|
|
1395
1647
|
}
|
|
1648
|
+
|
|
1649
|
+
.bb-dropdown__nav--drill .bb-dropdown__nav-title {
|
|
1650
|
+
/* Equal side gutters matching BbButton sm icon-only (24px) so the label
|
|
1651
|
+
centres. */
|
|
1652
|
+
display: block;
|
|
1653
|
+
padding-inline: 24px;
|
|
1654
|
+
text-align: center;
|
|
1655
|
+
}
|
|
1396
1656
|
}
|
|
1397
1657
|
|
|
1398
1658
|
/* Level slide: drilling in enters from the right and the old level exits left;
|
|
@@ -1428,4 +1688,15 @@ export type BbDropdownGroupEvents = {
|
|
|
1428
1688
|
opacity: 0;
|
|
1429
1689
|
transform: translateX(28px);
|
|
1430
1690
|
}
|
|
1691
|
+
|
|
1692
|
+
/*
|
|
1693
|
+
* Q14.3 — see `reservesCheckSpace` in BbDropdown.vue for why this is scoped to
|
|
1694
|
+
* an auto-width panel. `:has(.item__check)` targets exactly the rows a
|
|
1695
|
+
* selectable group mounts a check on, so a non-selectable group in the same
|
|
1696
|
+
* menu is untouched. The value matches the `--selected` rule's clearance; when
|
|
1697
|
+
* both apply they agree, so nothing shifts on selection.
|
|
1698
|
+
*/
|
|
1699
|
+
.bb-dropdown__panel--reserve-check .bb-dropdown__item:has(.item__check) {
|
|
1700
|
+
padding-inline-end: calc(6px + 16px + 4px);
|
|
1701
|
+
}
|
|
1431
1702
|
```
|
package/dist/ai/source/BbForm.md
CHANGED
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
</template>
|
|
28
28
|
|
|
29
29
|
<script setup lang="ts">
|
|
30
|
-
import { useTemplateRef } from 'vue';
|
|
30
|
+
import { getCurrentInstance, useTemplateRef } from 'vue';
|
|
31
31
|
import { useForm } from 'vee-validate';
|
|
32
32
|
import { useBbFormContextHost } from '@/composables/useBbFormContext';
|
|
33
33
|
|
|
@@ -41,7 +41,10 @@ const props = defineProps<{
|
|
|
41
41
|
id?: string;
|
|
42
42
|
}>();
|
|
43
43
|
|
|
44
|
-
|
|
44
|
+
// Declared for the public typing and the manifest. The handler is INVOKED
|
|
45
|
+
// directly (see `runSubmitListeners`) rather than through the returned `emit`,
|
|
46
|
+
// so the returned function is deliberately unused.
|
|
47
|
+
defineEmits<{
|
|
45
48
|
/** Fired only when every field passes; carries the collected form values. */
|
|
46
49
|
submit: [values: Record<string, unknown>];
|
|
47
50
|
}>();
|
|
@@ -57,9 +60,94 @@ const {
|
|
|
57
60
|
validate,
|
|
58
61
|
} = useForm();
|
|
59
62
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
+
/*
|
|
64
|
+
* Validates all fields on native submit, then runs the consumer's `@submit`
|
|
65
|
+
* with the values — only when the form is valid (and preventDefault's the
|
|
66
|
+
* native navigation).
|
|
67
|
+
*
|
|
68
|
+
* Q18.3 — why this calls the listener instead of `emit('submit', …)`.
|
|
69
|
+
* vee-validate decides "is a submit still in flight?" from what the handler
|
|
70
|
+
* RETURNS: return a thenable and `isSubmitting` stays true until it settles;
|
|
71
|
+
* return nothing and it clears immediately. Vue's `emit` always returns
|
|
72
|
+
* undefined, so `isSubmitting` used to drop as soon as VALIDATION resolved —
|
|
73
|
+
* measured over 10 ticks, `[true,false,false,…]` against `[true,true,true,…]`
|
|
74
|
+
* for a handler whose promise is returned. Every guide and the manifest tell
|
|
75
|
+
* you to bind a button's `loading` to it, so the spinner flashed for one frame
|
|
76
|
+
* and the user could double-submit a save that was still running.
|
|
77
|
+
*
|
|
78
|
+
* `vnode.props.onSubmit` rather than `useAttrs()`: `submit` is a DECLARED
|
|
79
|
+
* emit, so Vue strips it from `$attrs`. The raw prop is still on the vnode.
|
|
80
|
+
*
|
|
81
|
+
* The shape is preserved in both directions — an array of listeners (two
|
|
82
|
+
* `@submit` handlers) is called in order, and a sync handler returns undefined
|
|
83
|
+
* exactly as before, so nothing about existing behaviour changes except that
|
|
84
|
+
* an async handler is now awaited.
|
|
85
|
+
*/
|
|
86
|
+
const instance = getCurrentInstance();
|
|
87
|
+
|
|
88
|
+
type SubmitListener = (values: Record<string, unknown>) => unknown;
|
|
89
|
+
|
|
90
|
+
/** `@submit.once` compiles to a SEPARATE `onSubmitOnce` prop — Vue's own emit
|
|
91
|
+
* reads both and guards the once-handler with a fired flag. Mirror that, or a
|
|
92
|
+
* `.once` listener would silently never run. */
|
|
93
|
+
let onceFired = false;
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Route a listener failure the way `emit` did.
|
|
97
|
+
*
|
|
98
|
+
* Vue wraps event handlers in `callWithAsyncErrorHandling`, which sends both
|
|
99
|
+
* sync throws and promise rejections to `app.config.errorHandler`. Calling the
|
|
100
|
+
* prop directly skips that, so a project with a global reporter (Sentry, a
|
|
101
|
+
* toast-on-error boundary) would stop seeing submit failures. Report through
|
|
102
|
+
* the same channel, then let the submit settle — a rejected save must still
|
|
103
|
+
* clear `isSubmitting`, or the button spins forever.
|
|
104
|
+
*/
|
|
105
|
+
const reportListenerError = (error: unknown) => {
|
|
106
|
+
const handler = instance?.appContext.config.errorHandler;
|
|
107
|
+
if (handler)
|
|
108
|
+
handler(error, instance?.proxy ?? null, 'component event handler');
|
|
109
|
+
else console.error(error);
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
const isThenable = (value: unknown): value is PromiseLike<unknown> =>
|
|
113
|
+
typeof (value as PromiseLike<unknown>)?.then === 'function';
|
|
114
|
+
|
|
115
|
+
const runSubmitListeners = (formValues: Record<string, unknown>) => {
|
|
116
|
+
const props = instance?.vnode.props as Record<string, unknown> | undefined;
|
|
117
|
+
const collect = (value: unknown): SubmitListener[] =>
|
|
118
|
+
Array.isArray(value)
|
|
119
|
+
? (value as SubmitListener[])
|
|
120
|
+
: typeof value === 'function'
|
|
121
|
+
? [value as SubmitListener]
|
|
122
|
+
: [];
|
|
123
|
+
|
|
124
|
+
const listeners = collect(props?.onSubmit);
|
|
125
|
+
if (!onceFired) {
|
|
126
|
+
const once = collect(props?.onSubmitOnce);
|
|
127
|
+
if (once.length) {
|
|
128
|
+
onceFired = true;
|
|
129
|
+
listeners.push(...once);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
if (!listeners.length) return undefined;
|
|
133
|
+
|
|
134
|
+
const pending: Array<PromiseLike<unknown>> = [];
|
|
135
|
+
for (const listener of listeners) {
|
|
136
|
+
try {
|
|
137
|
+
const result = listener(formValues);
|
|
138
|
+
if (isThenable(result)) {
|
|
139
|
+
pending.push(Promise.resolve(result).catch(reportListenerError));
|
|
140
|
+
}
|
|
141
|
+
} catch (error) {
|
|
142
|
+
reportListenerError(error);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
// Await only what is actually awaitable, so a sync handler keeps the exact
|
|
146
|
+
// timing it has today rather than being pushed a microtask later.
|
|
147
|
+
return pending.length ? Promise.all(pending) : undefined;
|
|
148
|
+
};
|
|
149
|
+
|
|
150
|
+
const onSubmit = handleSubmit((formValues) => runSubmitListeners(formValues));
|
|
63
151
|
|
|
64
152
|
/**
|
|
65
153
|
* The rendered `<form>`, exposed as `$el` the way `BbButton` does it.
|