bitboss-ui 3.0.0-beta.47 → 3.0.0-beta.49
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 +24 -7
- package/bin/bitboss-ui-mcp.mjs +15 -3
- package/bin/bitboss-ui.mjs +167 -14
- package/dist/ai/BbAccordion.md +1 -1
- package/dist/ai/BbAvatar.md +1 -1
- package/dist/ai/BbBreadcrumbs.md +65 -65
- package/dist/ai/BbButton.md +28 -8
- package/dist/ai/BbCheckbox.md +0 -2
- package/dist/ai/BbCheckboxGroup.md +13 -20
- package/dist/ai/BbCollapsible.md +1 -1
- package/dist/ai/BbColorPalette.md +1 -1
- package/dist/ai/BbConfirm.md +8 -0
- package/dist/ai/BbConfirmPortal.md +1 -1
- package/dist/ai/BbDatePickerInput.md +4 -2
- package/dist/ai/BbDialog.md +1 -8
- package/dist/ai/BbDropdown.md +231 -220
- package/dist/ai/BbDropdownButton.md +65 -65
- package/dist/ai/BbDropdownGroup.md +2 -2
- package/dist/ai/BbDropzone.md +10 -10
- package/dist/ai/BbForm.md +43 -52
- package/dist/ai/BbHoverCard.md +19 -7
- package/dist/ai/BbHoverCardPortal.md +1 -1
- package/dist/ai/BbNumberInput.md +88 -21
- package/dist/ai/BbPopover.md +47 -40
- package/dist/ai/BbPopoverPortal.md +1 -1
- package/dist/ai/BbProgress.md +48 -22
- package/dist/ai/BbRadioGroup.md +13 -19
- package/dist/ai/BbSelect.md +16 -36
- package/dist/ai/BbSelectPopover.md +14 -30
- package/dist/ai/BbSmoothHeight.md +0 -2
- package/dist/ai/BbSwitchGroup.md +13 -20
- package/dist/ai/BbTable.md +11 -10
- package/dist/ai/BbTabs.md +107 -106
- package/dist/ai/BbTabsList.md +2 -2
- package/dist/ai/BbTabsPanels.md +1 -1
- package/dist/ai/BbTabsRoot.md +3 -3
- package/dist/ai/BbTooltip.md +29 -13
- package/dist/ai/BbTree.md +14 -11
- package/dist/ai/CommonPopover.md +1 -1
- package/dist/ai/changelog.json +297 -6
- package/dist/ai/components.json +50 -45
- package/dist/ai/composables/useBbDropdownContext.md +16 -16
- package/dist/ai/composables/useBbFormField.md +5 -1
- package/dist/ai/composables/useBbTabsContext.md +14 -14
- package/dist/ai/guides/agent-contract.md +27 -27
- package/dist/ai/guides/ai-router.md +1 -1
- package/dist/ai/guides/component-picker.md +3 -3
- package/dist/ai/guides/fetch-items-playbook.md +1 -1
- package/dist/ai/guides/icons-policy.md +10 -10
- package/dist/ai/guides/inertia-helpers.md +120 -67
- package/dist/ai/guides/installation-and-plugin-setup.md +45 -15
- package/dist/ai/guides/migration/components/bb-breadcrumbs.md +3 -2
- package/dist/ai/guides/migration/components/bb-checkbox-group.md +16 -16
- package/dist/ai/guides/migration/components/bb-dropdown-button.md +9 -8
- package/dist/ai/guides/migration/components/bb-dropdown.md +15 -14
- package/dist/ai/guides/migration/components/bb-radio-group.md +2 -1
- package/dist/ai/guides/migration/components/bb-select-popover.md +6 -1
- package/dist/ai/guides/migration/components/bb-select.md +10 -2
- package/dist/ai/guides/migration/components/bb-switch-group.md +2 -1
- package/dist/ai/guides/migration/components/bb-tabs.md +9 -8
- package/dist/ai/guides/migration/components/bb-tooltip.md +1 -1
- package/dist/ai/guides/migration/v2-to-v3.md +143 -28
- package/dist/ai/guides/migration/v3-beta-css-classes.md +29 -27
- package/dist/ai/guides/migration/v3-beta-tooling.md +11 -0
- package/dist/ai/guides/options-items-playbook.md +30 -24
- package/dist/ai/guides/passthrough.md +4 -4
- package/dist/ai/guides/preset-components.md +18 -3
- package/dist/ai/guides/typescript-generic-components.md +1 -1
- package/dist/ai/guides/validated-forms.md +11 -22
- package/dist/ai/guides/validation-providers.md +4 -3
- package/dist/ai/helpers/inertia/manifest.json +636 -0
- package/dist/ai/helpers/inertia/types.ts +15 -0
- package/dist/ai/helpers/inertia/useAsyncFn.ts +110 -0
- package/dist/ai/helpers/inertia/useConfirmOnRouteLeave.ts +102 -0
- package/dist/ai/helpers/inertia/useDeleteCmd.ts +30 -0
- package/dist/ai/helpers/inertia/useHasChanged.ts +36 -0
- package/dist/ai/helpers/inertia/useIndexById.ts +23 -0
- package/dist/ai/helpers/inertia/useLazyProp.ts +148 -0
- package/dist/ai/helpers/inertia/useLazyPropGetter.ts +50 -0
- package/dist/ai/helpers/inertia/useLoading.ts +20 -0
- package/dist/ai/helpers/inertia/usePaginatedResponseContext.ts +88 -0
- package/dist/ai/helpers/inertia/usePromiseForm.ts +62 -0
- package/dist/ai/helpers/inertia/useProp.ts +63 -0
- package/dist/ai/helpers/inertia/useQuery.ts +19 -0
- package/dist/ai/helpers/inertia/useQueryObject.ts +116 -0
- package/dist/ai/helpers/inertia/useResourceContext.ts +69 -0
- package/dist/ai/helpers/inertia/useRouteQuery.ts +54 -0
- package/dist/ai/helpers/inertia/useScreenSizes.ts +23 -0
- package/dist/ai/helpers/inertia/useTableContext.ts +34 -0
- package/dist/ai/helpers/inertia/useTableSelectionContext.ts +48 -0
- package/dist/ai/helpers/inertia/useUntil.ts +33 -0
- package/dist/ai/helpers/inertia/utils.ts +24 -0
- package/dist/ai/index.md +6 -6
- package/dist/ai/manifest/components/BbAccordion.json +1 -1
- package/dist/ai/manifest/components/BbBreadcrumbs.json +10 -6
- package/dist/ai/manifest/components/BbBreadcrumbs.tree.json +1 -1
- package/dist/ai/manifest/components/BbButton.json +2 -1
- package/dist/ai/manifest/components/BbButton.tree.json +1 -1
- package/dist/ai/manifest/components/BbCheckboxGroup.json +2 -2
- package/dist/ai/manifest/components/BbCollapsible.json +1 -1
- package/dist/ai/manifest/components/BbColorPalette.json +1 -1
- package/dist/ai/manifest/components/BbConfirmPortal.json +5 -2
- package/dist/ai/manifest/components/BbDropdown.json +23 -20
- package/dist/ai/manifest/components/BbDropdown.tree.json +2 -2
- package/dist/ai/manifest/components/BbDropdownButton.json +22 -19
- package/dist/ai/manifest/components/BbDropdownButton.tree.json +1 -1
- package/dist/ai/manifest/components/BbDropdownGroup.json +2 -2
- package/dist/ai/manifest/components/BbForm.json +1 -0
- package/dist/ai/manifest/components/BbHoverCard.json +1 -1
- package/dist/ai/manifest/components/BbHoverCardPortal.json +2 -2
- package/dist/ai/manifest/components/BbNumberInput.json +6 -1
- package/dist/ai/manifest/components/BbNumberInput.tree.json +2 -1
- package/dist/ai/manifest/components/BbPopover.json +2 -1
- package/dist/ai/manifest/components/BbPopoverPortal.json +2 -2
- package/dist/ai/manifest/components/BbProgress.json +6 -6
- package/dist/ai/manifest/components/BbProgress.tree.json +1 -0
- package/dist/ai/manifest/components/BbRadioGroup.json +2 -2
- package/dist/ai/manifest/components/BbSelect.json +2 -2
- package/dist/ai/manifest/components/BbSelect.tree.json +2 -2
- package/dist/ai/manifest/components/BbSelectPopover.json +2 -2
- package/dist/ai/manifest/components/BbSelectPopover.tree.json +1 -1
- package/dist/ai/manifest/components/BbSwitchGroup.json +2 -2
- package/dist/ai/manifest/components/BbTabs.json +8 -7
- package/dist/ai/manifest/components/BbTabsList.json +3 -3
- package/dist/ai/manifest/components/BbTabsPanels.json +1 -1
- package/dist/ai/manifest/components/BbTabsRoot.json +6 -5
- package/dist/ai/manifest/components/BbTag.tree.json +1 -1
- package/dist/ai/manifest/components/BbTooltip.json +2 -2
- package/dist/ai/manifest/components/ChipsBox.tree.json +1 -1
- package/dist/ai/manifest/components/CommonPopover.json +1 -1
- package/dist/ai/manifest/index.json +2 -2
- package/dist/ai/manifest/meta.json +5 -0
- package/dist/ai/manifest/types.advanced.json +10 -9
- package/dist/ai/manifest/types.api.json +8 -5
- package/dist/ai/manifest/types.wrapper.json +1 -0
- package/dist/ai/recipes/inertia/approvals-inbox.md +16 -18
- package/dist/ai/recipes/inertia/inline-edit-workspace.md +23 -33
- package/dist/ai/recipes/inertia/layout-scaffold.md +16 -16
- package/dist/ai/recipes/inertia/onboarding.md +6 -10
- package/dist/ai/recipes/inertia/ownership-atlas.md +15 -18
- package/dist/ai/recipes/inertia/record-form.md +11 -11
- package/dist/ai/recipes/inertia/records-workspace.md +38 -41
- package/dist/ai/recipes/inertia/settings-workspace.md +26 -38
- package/dist/ai/recipes/inertia/upload-center.md +31 -39
- package/dist/ai/recipes/inertia/wizard-form.md +10 -19
- package/dist/ai/recipes/nuxt/approvals-inbox.md +7 -8
- package/dist/ai/recipes/nuxt/inline-edit-workspace.md +14 -24
- package/dist/ai/recipes/nuxt/layout-scaffold.md +16 -16
- package/dist/ai/recipes/nuxt/onboarding.md +2 -6
- package/dist/ai/recipes/nuxt/ownership-atlas.md +7 -9
- package/dist/ai/recipes/nuxt/record-form.md +5 -5
- package/dist/ai/recipes/nuxt/records-workspace.md +29 -31
- package/dist/ai/recipes/nuxt/settings-workspace.md +22 -34
- package/dist/ai/recipes/nuxt/upload-center.md +22 -29
- package/dist/ai/recipes/nuxt/wizard-form.md +3 -11
- package/dist/ai/recipes/vue/approvals-inbox.md +7 -8
- package/dist/ai/recipes/vue/inline-edit-workspace.md +14 -24
- package/dist/ai/recipes/vue/layout-scaffold.md +16 -16
- package/dist/ai/recipes/vue/onboarding.md +2 -6
- package/dist/ai/recipes/vue/ownership-atlas.md +7 -9
- package/dist/ai/recipes/vue/record-form.md +5 -5
- package/dist/ai/recipes/vue/records-workspace.md +29 -31
- package/dist/ai/recipes/vue/settings-workspace.md +22 -34
- package/dist/ai/recipes/vue/upload-center.md +22 -29
- package/dist/ai/recipes/vue/wizard-form.md +3 -11
- package/dist/ai/source/BbAccordion.md +1 -1
- package/dist/ai/source/BbAlert.md +3 -3
- package/dist/ai/source/BbBadge.md +14 -10
- package/dist/ai/source/BbBadgeButton.md +17 -12
- package/dist/ai/source/BbBaseButton.md +1 -1
- package/dist/ai/source/BbBaseRadioIcon.md +1 -0
- package/dist/ai/source/BbBaseSwitchIcon.md +1 -0
- package/dist/ai/source/BbBreadcrumbs.md +63 -42
- package/dist/ai/source/BbButton.md +84 -38
- package/dist/ai/source/BbCalendar.md +17 -16
- package/dist/ai/source/BbCheckbox.md +3 -2
- package/dist/ai/source/BbCheckboxGroup.md +11 -4
- package/dist/ai/source/BbCollapsible.md +2 -1
- package/dist/ai/source/BbColorInput.md +10 -9
- package/dist/ai/source/BbColorPalette.md +2 -1
- package/dist/ai/source/BbConfirm.md +18 -1
- package/dist/ai/source/BbConfirmPortal.md +20 -6
- package/dist/ai/source/BbDatePicker.md +2 -2
- package/dist/ai/source/BbDatePickerInput.md +47 -20
- package/dist/ai/source/BbDialog.md +5 -5
- package/dist/ai/source/BbDropdown.md +231 -158
- package/dist/ai/source/BbDropdownButton.md +19 -12
- package/dist/ai/source/BbDropdownGroup.md +127 -93
- package/dist/ai/source/BbForm.md +25 -1
- package/dist/ai/source/BbHoverCard.md +30 -3
- package/dist/ai/source/BbHoverCardPortal.md +18 -3
- package/dist/ai/source/BbIndicator.md +4 -0
- package/dist/ai/source/BbNumberInput.md +855 -19
- package/dist/ai/source/BbOffCanvas.md +27 -11
- package/dist/ai/source/BbPagination.md +3 -3
- package/dist/ai/source/BbPopover.md +185 -12
- package/dist/ai/source/BbPopoverPortal.md +30 -3
- package/dist/ai/source/BbProgress.md +82 -18
- package/dist/ai/source/BbRadioGroup.md +12 -5
- package/dist/ai/source/BbRating.md +11 -9
- package/dist/ai/source/BbSelect.md +16 -10
- package/dist/ai/source/BbSelectPopover.md +29 -23
- package/dist/ai/source/BbSlider.md +12 -6
- package/dist/ai/source/BbSwitch.md +3 -2
- package/dist/ai/source/BbSwitchGroup.md +5 -2
- package/dist/ai/source/BbTable.md +102 -18
- package/dist/ai/source/BbTabs.md +30 -24
- package/dist/ai/source/BbTabsList.md +29 -23
- package/dist/ai/source/BbTabsPanels.md +29 -23
- package/dist/ai/source/BbTabsRoot.md +28 -22
- package/dist/ai/source/BbTag.md +10 -9
- package/dist/ai/source/BbTextInput.md +5 -4
- package/dist/ai/source/BbTextarea.md +6 -5
- package/dist/ai/source/BbTimePicker.md +1 -1
- package/dist/ai/source/BbTimePickerInput.md +46 -9
- package/dist/ai/source/BbToast.md +10 -7
- package/dist/ai/source/BbToastPortal.md +10 -7
- package/dist/ai/source/BbTooltip.md +88 -11
- package/dist/ai/source/BbTree.md +21 -3
- package/dist/ai/source/CommonField.md +6 -4
- package/dist/ai/source/CommonFieldInput.md +15 -10
- package/dist/ai/source/CommonPopover.md +8 -1
- package/dist/ai/source/CommonTimeSelector.md +5 -4
- package/dist/components/BbBadge/BbBadgeButton.vue_vue_type_script_setup_true_lang.js +10 -8
- package/dist/components/BbBaseButton/BbBaseButton.vue_vue_type_script_setup_true_lang.js +8 -8
- package/dist/components/BbBreadcrumbs/BbBreadcrumbs.vue_vue_type_script_setup_true_lang.js +45 -45
- package/dist/components/BbBreadcrumbs/types.d.ts +25 -17
- package/dist/components/BbButton/BbButton.vue_vue_type_script_setup_true_lang.js +88 -70
- package/dist/components/BbButton/toggleRoving.d.ts +6 -0
- package/dist/components/BbButton/toggleRoving.js +45 -0
- package/dist/components/BbButton/types.d.ts +12 -4
- package/dist/components/BbButton/types.js +5 -1
- package/dist/components/BbCalendar/BbCalendar.vue_vue_type_script_setup_true_lang.js +178 -178
- package/dist/components/BbCalendar/CalendarMonthPanel.vue_vue_type_script_setup_true_lang.js +15 -15
- package/dist/components/BbCalendar/CalendarYearPanel.vue_vue_type_script_setup_true_lang.js +28 -28
- package/dist/components/BbCalendar/useCalendarGrid.js +141 -139
- package/dist/components/BbCalendar/useDayjsLocale.d.ts +38 -15
- package/dist/components/BbCalendar/useDayjsLocale.js +31 -30
- package/dist/components/BbCheckbox/BbCheckbox.vue_vue_type_script_setup_true_lang.js +48 -48
- package/dist/components/BbCheckboxGroup/BbCheckboxGroup.vue_vue_type_script_setup_true_lang.js +81 -80
- package/dist/components/BbCheckboxGroup/types.d.ts +6 -2
- package/dist/components/BbCollapsible/types.d.ts +2 -1
- package/dist/components/BbColorInput/BbColorInput.vue_vue_type_script_setup_true_lang.js +69 -69
- package/dist/components/BbColorPalette/types.d.ts +2 -1
- package/dist/components/BbConfirm/BbConfirmPortal.vue.d.ts +2 -5
- package/dist/components/BbConfirm/types.d.ts +15 -0
- package/dist/components/BbDatePickerInput/BbDatePickerInput.vue_vue_type_script_setup_true_lang.js +363 -349
- package/dist/components/BbDropdown/AdaptiveDropdown.vue_vue_type_script_setup_true_lang.js +91 -86
- package/dist/components/BbDropdown/BbDropdown.vue_vue_type_script_setup_true_lang.js +298 -289
- package/dist/components/BbDropdown/BbDropdownList.vue_vue_type_script_setup_true_lang.js +322 -356
- package/dist/components/BbDropdown/DropdownPipelineResolver.vue_vue_type_script_setup_true_lang.js +17 -15
- package/dist/components/BbDropdown/DropdownRow.vue.d.ts +40 -0
- package/dist/components/BbDropdown/DropdownRow.vue.js +5 -0
- package/dist/components/BbDropdown/DropdownRow.vue_vue_type_script_setup_true_lang.js +60 -0
- package/dist/components/BbDropdown/normalizeGroups.d.ts +8 -2
- package/dist/components/BbDropdown/normalizeGroups.js +60 -46
- package/dist/components/BbDropdown/types.d.ts +120 -88
- package/dist/components/BbDropdownButton/BbDropdownButton.vue_vue_type_script_setup_true_lang.js +11 -2
- package/dist/components/BbDropdownButton/types.d.ts +2 -2
- package/dist/components/BbForm/BbForm.vue.d.ts +9 -0
- package/dist/components/BbForm/BbForm.vue_vue_type_script_setup_true_lang.js +114 -105
- package/dist/components/BbForm/BbFormCustomField.js +1 -1
- package/dist/components/BbForm/bindFormField.js +2 -1
- package/dist/components/BbForm/formFields.d.ts +5 -0
- package/dist/components/BbHoverCard/BbHoverCard.vue_vue_type_script_setup_true_lang.js +145 -142
- package/dist/components/BbHoverCard/BbHoverCardPortal.vue.d.ts +2 -2
- package/dist/components/BbHoverCard/types.d.ts +14 -1
- package/dist/components/BbNumberInput/BbNumberInput.vue.d.ts +0 -1
- package/dist/components/BbNumberInput/BbNumberInput.vue_vue_type_script_setup_true_lang.js +452 -125
- package/dist/components/BbNumberInput/numberDisplay.d.ts +256 -0
- package/dist/components/BbNumberInput/numberDisplay.js +499 -0
- package/dist/components/BbNumberInput/types.d.ts +54 -1
- package/dist/components/BbNumberInput/warroom/corpus.d.ts +58 -0
- package/dist/components/BbNumberInput/warroom/currency-verify.rows.d.ts +28 -0
- package/dist/components/BbNumberInput/warroom/currency.rows.d.ts +2 -0
- package/dist/components/BbNumberInput/warroom/harness.d.ts +217 -0
- package/dist/components/BbNumberInput/warroom/oracle.d.ts +150 -0
- package/dist/components/BbPagination/BbPagination.vue_vue_type_script_setup_true_lang.js +7 -7
- package/dist/components/BbPopover/BbPopover.vue.d.ts +1 -0
- package/dist/components/BbPopover/BbPopover.vue_vue_type_script_setup_true_lang.js +207 -162
- package/dist/components/BbPopover/BbPopoverPortal.vue.d.ts +2 -2
- package/dist/components/BbPopover/types.d.ts +26 -1
- package/dist/components/BbProgress/BbProgress.vue_vue_type_script_setup_true_lang.js +15 -7
- package/dist/components/BbProgress/types.d.ts +23 -7
- package/dist/components/BbProgress/types.js +1 -1
- package/dist/components/BbRadioGroup/BbRadioGroup.vue_vue_type_script_setup_true_lang.js +102 -101
- package/dist/components/BbRadioGroup/types.d.ts +6 -2
- package/dist/components/BbRating/BbRating.vue_vue_type_script_setup_true_lang.js +63 -63
- package/dist/components/BbSelect/BbSelect.vue_vue_type_script_setup_true_lang.js +156 -154
- package/dist/components/BbSelect/types.d.ts +6 -2
- package/dist/components/BbSelectPopover/BbSelectPopover.vue_vue_type_script_setup_true_lang.js +2 -1
- package/dist/components/BbSelectPopover/types.d.ts +6 -2
- package/dist/components/BbSlider/BbSlider.vue_vue_type_script_setup_true_lang.js +153 -153
- package/dist/components/BbSwitch/BbSwitch.vue_vue_type_script_setup_true_lang.js +62 -62
- package/dist/components/BbSwitchGroup/BbSwitchGroup.vue_vue_type_script_setup_true_lang.js +131 -130
- package/dist/components/BbTable/BbTable.vue_vue_type_script_setup_true_lang.js +711 -676
- package/dist/components/BbTabs/BbTabs.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/components/BbTabs/BbTabsList.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/components/BbTabs/types.d.ts +28 -22
- package/dist/components/BbTag/BbTag.vue_vue_type_script_setup_true_lang.js +76 -76
- package/dist/components/BbTextInput/BbTextInput.vue_vue_type_script_setup_true_lang.js +58 -58
- package/dist/components/BbTextarea/BbTextarea.vue_vue_type_script_setup_true_lang.js +82 -82
- package/dist/components/BbTimePickerInput/BbTimePickerInput.vue_vue_type_script_setup_true_lang.js +246 -236
- package/dist/components/BbTooltip/BbTooltip.vue_vue_type_script_setup_true_lang.js +99 -86
- package/dist/components/BbTooltip/tooltipWarmup.d.ts +23 -0
- package/dist/components/BbTooltip/tooltipWarmup.js +7 -0
- package/dist/components/BbTooltip/types.d.ts +10 -3
- package/dist/components/BbTree/BbTree.vue_vue_type_script_setup_true_lang.js +29 -21
- package/dist/components/BbTree/BbTreeLevel.vue_vue_type_script_setup_true_lang.js +10 -7
- package/dist/components/CommonFieldInput/CommonFieldInput.vue_vue_type_script_setup_true_lang.js +37 -36
- package/dist/components/CommonPopover/types.d.ts +2 -1
- package/dist/components/CommonTimeSelector/CommonTimeSelector.vue_vue_type_script_setup_true_lang.js +9 -9
- package/dist/composables/formSubmitLock.d.ts +6 -0
- package/dist/composables/formSubmitLock.js +4 -0
- package/dist/composables/useBaseOptions.d.ts +7 -1
- package/dist/composables/useBaseOptions.js +32 -32
- package/dist/composables/useBbDropdownContext.d.ts +8 -8
- package/dist/composables/useBbFormField.d.ts +9 -0
- package/dist/composables/useBbFormField.js +5 -3
- package/dist/composables/useBbTabsContext.d.ts +10 -10
- package/dist/composables/useBbTabsContext.js +18 -18
- package/dist/composables/useFormBinding.d.ts +11 -0
- package/dist/composables/useFormBinding.js +15 -13
- package/dist/composables/useItemText.d.ts +5 -1
- package/dist/composables/useItemText.js +8 -3
- package/dist/composables/useItemValue.d.ts +5 -1
- package/dist/composables/useItemValue.js +8 -3
- package/dist/composables/useLocale.js +10 -9
- package/dist/deprecation/ai-deprecations.json.d.ts +130 -0
- package/dist/deprecation/ai-deprecations.json.js +1 -1
- package/dist/deprecation/removedProps.js +1 -1
- package/dist/directives/bbDropdown.js +1 -1
- package/dist/directives/directivePortal.d.ts +13 -7
- package/dist/directives/directivePortal.js +1 -4
- package/dist/i18n/index.d.ts +7 -12
- package/dist/i18n/locales/cs.json +11 -14
- package/dist/i18n/locales/da.json +13 -16
- package/dist/i18n/locales/de-CH.json +137 -0
- package/dist/i18n/locales/de.json +14 -17
- package/dist/i18n/locales/el.json +10 -13
- package/dist/i18n/locales/en-GB.json +137 -0
- package/dist/i18n/locales/en.json +8 -11
- package/dist/i18n/locales/es-MX.json +137 -0
- package/dist/i18n/locales/es.json +16 -19
- package/dist/i18n/locales/fi.json +8 -11
- package/dist/i18n/locales/fr.json +23 -26
- package/dist/i18n/locales/hu.json +8 -11
- package/dist/i18n/locales/it.json +12 -15
- package/dist/i18n/locales/ja.json +13 -16
- package/dist/i18n/locales/ko.json +10 -13
- package/dist/i18n/locales/nb.json +13 -16
- package/dist/i18n/locales/nl.json +21 -24
- package/dist/i18n/locales/pl.json +10 -13
- package/dist/i18n/locales/{pt.json → pt-BR.json} +19 -22
- package/dist/i18n/locales/pt-PT.json +137 -0
- package/dist/i18n/locales/ro.json +22 -25
- package/dist/i18n/locales/ru.json +11 -14
- package/dist/i18n/locales/sv.json +16 -19
- package/dist/i18n/locales/tr.json +14 -17
- package/dist/i18n/locales/uk.json +11 -14
- package/dist/i18n/locales/{zh-cn.json → zh-CN.json} +10 -13
- package/dist/i18n/locales/zh-HK.json +137 -0
- package/dist/i18n/locales/zh-TW.json +137 -0
- package/dist/i18n/regionHints.d.ts +16 -0
- package/dist/i18n/regionHints.js +49 -0
- package/dist/i18n/regions.d.ts +286 -0
- package/dist/i18n/regions.js +265 -0
- package/dist/index.d.ts +4 -4
- package/dist/index.js +4 -4
- package/dist/llms-full.txt +1914 -1714
- package/dist/llms-medium.txt +76 -46
- package/dist/llms.txt +7 -7
- package/dist/locale-blueprint.json +16 -13
- package/dist/styles.css +2 -2
- package/dist/types/passthrough.d.ts +1 -1
- package/dist/types/ptComponentMap.d.ts +2 -2
- package/dist/utilities/functions/slotKey.d.ts +2 -2
- package/dist/utils/versionCheck.js +1 -1
- package/dist/vite-plugin.d.ts +22 -19
- package/dist/vite.js +309 -297
- package/llms.txt +7 -7
- package/package.json +5 -3
- package/scripts/lib/agent-manifest.mjs +2 -1
- package/scripts/lib/eslint-disable.mjs +17 -4
- package/scripts/lib/eslint-plugin.d.ts +9 -1
- package/scripts/lib/eslint-plugin.mjs +256 -6
- package/scripts/lib/helper-canon.mjs +176 -0
- package/scripts/lib/helpers-add.mjs +1303 -0
- package/scripts/lib/local-components.mjs +33 -4
- package/scripts/lib/locale-check.mjs +165 -0
- package/scripts/lib/portal-names.mjs +458 -0
- package/scripts/lib/redundant-item-accessor.mjs +398 -0
- package/scripts/lib/renamed-item-field.mjs +343 -0
- package/scripts/lib/slot-key.mjs +2 -2
- package/scripts/lib/slot-renames.mjs +1 -1
- package/scripts/lib/unimported-components.mjs +5 -2
- package/scripts/lib/validate-bb-markup.mjs +123 -56
- package/dist/i18n/index.js +0 -27
|
@@ -1428,12 +1428,14 @@ export type BbOffCanvasSlots = {
|
|
|
1428
1428
|
}
|
|
1429
1429
|
&.bb-offcanvas--right::after {
|
|
1430
1430
|
bottom: 0;
|
|
1431
|
+
/* stylelint-disable-next-line property-disallowed-list -- geometry: the `side` prop names a physical edge */
|
|
1431
1432
|
left: 100%;
|
|
1432
1433
|
top: 0;
|
|
1433
1434
|
width: var(--stack-fill);
|
|
1434
1435
|
}
|
|
1435
1436
|
&.bb-offcanvas--left::after {
|
|
1436
1437
|
bottom: 0;
|
|
1438
|
+
/* stylelint-disable-next-line property-disallowed-list -- geometry: the `side` prop names a physical edge */
|
|
1437
1439
|
right: 100%;
|
|
1438
1440
|
top: 0;
|
|
1439
1441
|
width: var(--stack-fill);
|
|
@@ -1441,13 +1443,13 @@ export type BbOffCanvasSlots = {
|
|
|
1441
1443
|
&.bb-offcanvas--top::after {
|
|
1442
1444
|
bottom: 100%;
|
|
1443
1445
|
height: var(--stack-fill);
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
+
inset-inline-end: 0;
|
|
1447
|
+
inset-inline-start: 0;
|
|
1446
1448
|
}
|
|
1447
1449
|
&.bb-offcanvas--bottom::after {
|
|
1448
1450
|
height: var(--stack-fill);
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
+
inset-inline-end: 0;
|
|
1452
|
+
inset-inline-start: 0;
|
|
1451
1453
|
top: 100%;
|
|
1452
1454
|
}
|
|
1453
1455
|
|
|
@@ -1474,6 +1476,7 @@ export type BbOffCanvasSlots = {
|
|
|
1474
1476
|
--inset-left: var(--safe-left);
|
|
1475
1477
|
--translate-x: -100%;
|
|
1476
1478
|
border-radius: 0 var(--bb-radius-surface) var(--bb-radius-surface) 0;
|
|
1479
|
+
/* stylelint-disable-next-line property-disallowed-list -- geometry: the `side` prop names a physical edge */
|
|
1477
1480
|
left: 0px;
|
|
1478
1481
|
transform-origin: left center;
|
|
1479
1482
|
}
|
|
@@ -1483,14 +1486,17 @@ export type BbOffCanvasSlots = {
|
|
|
1483
1486
|
--inset-bottom: var(--safe-bottom);
|
|
1484
1487
|
--translate-x: 100%;
|
|
1485
1488
|
border-radius: var(--bb-radius-surface) 0 0 var(--bb-radius-surface);
|
|
1489
|
+
/* stylelint-disable-next-line property-disallowed-list -- geometry: the `side` prop names a physical edge */
|
|
1486
1490
|
left: auto;
|
|
1491
|
+
/* stylelint-disable-next-line property-disallowed-list -- geometry: the `side` prop names a physical edge */
|
|
1487
1492
|
right: 0px;
|
|
1488
1493
|
transform-origin: right center;
|
|
1489
1494
|
}
|
|
1490
1495
|
&.bb-offcanvas--top,
|
|
1491
1496
|
&.bb-offcanvas--bottom {
|
|
1492
1497
|
height: var(--max-size);
|
|
1493
|
-
|
|
1498
|
+
inset-inline-end: 0;
|
|
1499
|
+
inset-inline-start: 0;
|
|
1494
1500
|
/* `height` already applies `--max-size` (a length or the `fit-content`
|
|
1495
1501
|
keyword for `size="auto"`); this only caps the panel to the viewport so a
|
|
1496
1502
|
tall/auto sheet scrolls internally instead of overflowing off-screen. Must
|
|
@@ -1498,7 +1504,6 @@ export type BbOffCanvasSlots = {
|
|
|
1498
1504
|
drop the cap entirely, letting a bottom sheet run past the top edge. */
|
|
1499
1505
|
max-height: 100%;
|
|
1500
1506
|
max-width: 100%;
|
|
1501
|
-
right: 0;
|
|
1502
1507
|
width: 100%;
|
|
1503
1508
|
}
|
|
1504
1509
|
&.bb-offcanvas--top {
|
|
@@ -1630,10 +1635,12 @@ export type BbOffCanvasSlots = {
|
|
|
1630
1635
|
top-right), a right drawer (its top-left). */
|
|
1631
1636
|
&.bb-offcanvas--bottom > .bb-offcanvas__header,
|
|
1632
1637
|
&.bb-offcanvas--bottom.bb-offcanvas--no-header > .bb-offcanvas__content {
|
|
1638
|
+
/* stylelint-disable-next-line property-disallowed-list -- geometry: the `side` prop names a physical edge */
|
|
1633
1639
|
border-top-left-radius: max(
|
|
1634
1640
|
0px,
|
|
1635
1641
|
calc(var(--bb-radius-surface) - var(--bb-border-w))
|
|
1636
1642
|
);
|
|
1643
|
+
/* stylelint-disable-next-line property-disallowed-list -- geometry: the `side` prop names a physical edge */
|
|
1637
1644
|
border-top-right-radius: max(
|
|
1638
1645
|
0px,
|
|
1639
1646
|
calc(var(--bb-radius-surface) - var(--bb-border-w))
|
|
@@ -1641,6 +1648,7 @@ export type BbOffCanvasSlots = {
|
|
|
1641
1648
|
}
|
|
1642
1649
|
&.bb-offcanvas--left > .bb-offcanvas__header,
|
|
1643
1650
|
&.bb-offcanvas--left.bb-offcanvas--no-header > .bb-offcanvas__content {
|
|
1651
|
+
/* stylelint-disable-next-line property-disallowed-list -- geometry: the `side` prop names a physical edge */
|
|
1644
1652
|
border-top-right-radius: max(
|
|
1645
1653
|
0px,
|
|
1646
1654
|
calc(var(--bb-radius-surface) - var(--bb-border-w))
|
|
@@ -1648,6 +1656,7 @@ export type BbOffCanvasSlots = {
|
|
|
1648
1656
|
}
|
|
1649
1657
|
&.bb-offcanvas--right > .bb-offcanvas__header,
|
|
1650
1658
|
&.bb-offcanvas--right.bb-offcanvas--no-header > .bb-offcanvas__content {
|
|
1659
|
+
/* stylelint-disable-next-line property-disallowed-list -- geometry: the `side` prop names a physical edge */
|
|
1651
1660
|
border-top-left-radius: max(
|
|
1652
1661
|
0px,
|
|
1653
1662
|
calc(var(--bb-radius-surface) - var(--bb-border-w))
|
|
@@ -1660,10 +1669,12 @@ export type BbOffCanvasSlots = {
|
|
|
1660
1669
|
&.bb-offcanvas--top > .bb-offcanvas__footer,
|
|
1661
1670
|
&.bb-offcanvas--top:not(:has(> .bb-offcanvas__footer:not(:empty)))
|
|
1662
1671
|
> .bb-offcanvas__content {
|
|
1672
|
+
/* stylelint-disable-next-line property-disallowed-list -- geometry: the `side` prop names a physical edge */
|
|
1663
1673
|
border-bottom-left-radius: max(
|
|
1664
1674
|
0px,
|
|
1665
1675
|
calc(var(--bb-radius-surface) - var(--bb-border-w))
|
|
1666
1676
|
);
|
|
1677
|
+
/* stylelint-disable-next-line property-disallowed-list -- geometry: the `side` prop names a physical edge */
|
|
1667
1678
|
border-bottom-right-radius: max(
|
|
1668
1679
|
0px,
|
|
1669
1680
|
calc(var(--bb-radius-surface) - var(--bb-border-w))
|
|
@@ -1672,6 +1683,7 @@ export type BbOffCanvasSlots = {
|
|
|
1672
1683
|
&.bb-offcanvas--left > .bb-offcanvas__footer,
|
|
1673
1684
|
&.bb-offcanvas--left:not(:has(> .bb-offcanvas__footer:not(:empty)))
|
|
1674
1685
|
> .bb-offcanvas__content {
|
|
1686
|
+
/* stylelint-disable-next-line property-disallowed-list -- geometry: the `side` prop names a physical edge */
|
|
1675
1687
|
border-bottom-right-radius: max(
|
|
1676
1688
|
0px,
|
|
1677
1689
|
calc(var(--bb-radius-surface) - var(--bb-border-w))
|
|
@@ -1680,6 +1692,7 @@ export type BbOffCanvasSlots = {
|
|
|
1680
1692
|
&.bb-offcanvas--right > .bb-offcanvas__footer,
|
|
1681
1693
|
&.bb-offcanvas--right:not(:has(> .bb-offcanvas__footer:not(:empty)))
|
|
1682
1694
|
> .bb-offcanvas__content {
|
|
1695
|
+
/* stylelint-disable-next-line property-disallowed-list -- geometry: the `side` prop names a physical edge */
|
|
1683
1696
|
border-bottom-left-radius: max(
|
|
1684
1697
|
0px,
|
|
1685
1698
|
calc(var(--bb-radius-surface) - var(--bb-border-w))
|
|
@@ -1789,6 +1802,7 @@ export type BbOffCanvasSlots = {
|
|
|
1789
1802
|
&.bb-offcanvas--bottom .bb-offcanvas__handle,
|
|
1790
1803
|
&.bb-offcanvas--top .bb-offcanvas__handle {
|
|
1791
1804
|
height: var(--handle-h);
|
|
1805
|
+
/* stylelint-disable-next-line property-disallowed-list -- geometry: centred with a physical translate */
|
|
1792
1806
|
left: 50%;
|
|
1793
1807
|
translate: -50% 0;
|
|
1794
1808
|
width: var(--handle-w);
|
|
@@ -1808,9 +1822,11 @@ export type BbOffCanvasSlots = {
|
|
|
1808
1822
|
width: var(--handle-h);
|
|
1809
1823
|
}
|
|
1810
1824
|
&.bb-offcanvas--left .bb-offcanvas__handle {
|
|
1825
|
+
/* stylelint-disable-next-line property-disallowed-list -- geometry: the `side` prop names a physical edge */
|
|
1811
1826
|
right: 8px;
|
|
1812
1827
|
}
|
|
1813
1828
|
&.bb-offcanvas--right .bb-offcanvas__handle {
|
|
1829
|
+
/* stylelint-disable-next-line property-disallowed-list -- geometry: the `side` prop names a physical edge */
|
|
1814
1830
|
left: 8px;
|
|
1815
1831
|
}
|
|
1816
1832
|
|
|
@@ -1866,7 +1882,7 @@ export type BbOffCanvasSlots = {
|
|
|
1866
1882
|
* the space here instead — only when there is actually a control to
|
|
1867
1883
|
* clear, so `hideClose` keeps the full width. */
|
|
1868
1884
|
&:has(~ .bb-close-button) {
|
|
1869
|
-
padding-
|
|
1885
|
+
padding-inline-end: calc(var(--close-size) + 4px);
|
|
1870
1886
|
}
|
|
1871
1887
|
}
|
|
1872
1888
|
/* Only when a description is present. A header without one keeps its
|
|
@@ -1888,7 +1904,7 @@ export type BbOffCanvasSlots = {
|
|
|
1888
1904
|
does. The × sits at the top-right, and a one-line title is short
|
|
1889
1905
|
enough that the description's first line can still run under it. */
|
|
1890
1906
|
&:has(~ .bb-close-button) {
|
|
1891
|
-
padding-
|
|
1907
|
+
padding-inline-end: calc(var(--close-size) + 4px);
|
|
1892
1908
|
}
|
|
1893
1909
|
}
|
|
1894
1910
|
|
|
@@ -1900,8 +1916,8 @@ export type BbOffCanvasSlots = {
|
|
|
1900
1916
|
> .bb-close-button {
|
|
1901
1917
|
--size: var(--close-size);
|
|
1902
1918
|
--p: 7px;
|
|
1919
|
+
inset-inline-end: calc(var(--px) - var(--p));
|
|
1903
1920
|
position: absolute;
|
|
1904
|
-
right: calc(var(--px) - var(--p));
|
|
1905
1921
|
top: calc(var(--py) - var(--p));
|
|
1906
1922
|
}
|
|
1907
1923
|
}
|
|
@@ -1956,8 +1972,8 @@ export type BbOffCanvasSlots = {
|
|
|
1956
1972
|
> .bb-close-button {
|
|
1957
1973
|
--size: 28px;
|
|
1958
1974
|
--p: 7px;
|
|
1975
|
+
inset-inline-end: calc(var(--px) - var(--p));
|
|
1959
1976
|
position: absolute;
|
|
1960
|
-
right: calc(var(--px) - var(--p));
|
|
1961
1977
|
top: calc(var(--py) - var(--p));
|
|
1962
1978
|
}
|
|
1963
1979
|
}
|
|
@@ -2042,7 +2058,7 @@ export type BbOffCanvasSlots = {
|
|
|
2042
2058
|
|
|
2043
2059
|
body:has(.bb-offcanvas--visible) {
|
|
2044
2060
|
overflow: hidden;
|
|
2045
|
-
padding-
|
|
2061
|
+
padding-inline-end: var(--scrollbar-width);
|
|
2046
2062
|
}
|
|
2047
2063
|
|
|
2048
2064
|
@keyframes bb-offcanvas-deny-bounce-x {
|
|
@@ -864,13 +864,13 @@ export type BbPaginationSlots = {
|
|
|
864
864
|
|
|
865
865
|
&--right {
|
|
866
866
|
.bb-pagination__pages {
|
|
867
|
-
margin-
|
|
867
|
+
margin-inline-start: auto;
|
|
868
868
|
}
|
|
869
869
|
}
|
|
870
870
|
&--center {
|
|
871
871
|
.bb-pagination__pages {
|
|
872
|
-
margin-
|
|
873
|
-
margin-
|
|
872
|
+
margin-inline-end: auto;
|
|
873
|
+
margin-inline-start: auto;
|
|
874
874
|
}
|
|
875
875
|
}
|
|
876
876
|
|
|
@@ -88,11 +88,11 @@
|
|
|
88
88
|
ref="popover-ref"
|
|
89
89
|
v-model="isOpen"
|
|
90
90
|
:anchor="effectiveAnchor"
|
|
91
|
-
:aria-labelledby="hasOpenedOnce ?
|
|
91
|
+
:aria-labelledby="hasOpenedOnce ? labelledById : undefined"
|
|
92
92
|
:boundary="boundary"
|
|
93
93
|
:bubble-attrs="panelAttrs"
|
|
94
94
|
class="bb-popover"
|
|
95
|
-
dialog
|
|
95
|
+
:dialog="modal"
|
|
96
96
|
:eager="eager"
|
|
97
97
|
hide-arrow
|
|
98
98
|
:offset="offset"
|
|
@@ -100,7 +100,7 @@
|
|
|
100
100
|
:placement="placement === 'cursor' ? 'bottom-start' : placement"
|
|
101
101
|
:style="{ width: parsedWidth }"
|
|
102
102
|
:transition-duration="transitionDuration"
|
|
103
|
-
v-bind="mergeProps($attrs, passthrough.root)"
|
|
103
|
+
v-bind="mergeProps(nonModalAttrs, $attrs, passthrough.root)"
|
|
104
104
|
@hidden="onPanelHidden"
|
|
105
105
|
@shown="emit('shown')"
|
|
106
106
|
>
|
|
@@ -150,7 +150,7 @@
|
|
|
150
150
|
</template>
|
|
151
151
|
|
|
152
152
|
<script setup lang="ts">
|
|
153
|
-
// Attributes land on the floating panel
|
|
153
|
+
// Attributes land on the floating panel on desktop (a `<dialog>` when `modal`, else a `<div role="dialog">`), the sheet's `<dialog>` on a phone (without `class` there).
|
|
154
154
|
// Measured 2026-09-23 (Q49.23); read by components.json.
|
|
155
155
|
// @attrTargets dialog
|
|
156
156
|
import {
|
|
@@ -168,6 +168,7 @@ import {
|
|
|
168
168
|
pushEscapeEntry,
|
|
169
169
|
removeEscapeEntry,
|
|
170
170
|
isTopEscapeEntry,
|
|
171
|
+
topDeliberateSurface,
|
|
171
172
|
} from '@/utils/overlayEscapeStack';
|
|
172
173
|
import { useId } from '@/composables/useId';
|
|
173
174
|
import { useElementSize, useIntersectionObserver } from '@vueuse/core';
|
|
@@ -209,6 +210,7 @@ const props = withDefaults(defineProps<BbPopoverProps>(), {
|
|
|
209
210
|
// A declared default disables that absent→false cast while still keeping the
|
|
210
211
|
// Boolean type — so the `<Popover adaptive>` shorthand (valueless→`true`) works.
|
|
211
212
|
adaptive: undefined,
|
|
213
|
+
modal: false,
|
|
212
214
|
offset: 4,
|
|
213
215
|
padding: 10,
|
|
214
216
|
placement: 'bottom',
|
|
@@ -231,6 +233,15 @@ const activatorId = props.id ?? id.value;
|
|
|
231
233
|
const popoverId = `bbp_${activatorId}`;
|
|
232
234
|
|
|
233
235
|
const activatorEl = ref<HTMLElement>();
|
|
236
|
+
/**
|
|
237
|
+
* The id the panel is labelled by. An external activator that already has an
|
|
238
|
+
* id keeps it (like BbDropdown and BbSelectPopover): overwriting it broke the
|
|
239
|
+
* consumer's own `id` (an anchor target, a `<label for>`, a test hook). Only an
|
|
240
|
+
* element with no id gets `activatorId`.
|
|
241
|
+
*/
|
|
242
|
+
const labelledById = computed(
|
|
243
|
+
() => (hasExternalActivator.value && activatorEl.value?.id) || activatorId
|
|
244
|
+
);
|
|
234
245
|
const popoverRef = useTemplateRef('popover-ref');
|
|
235
246
|
const popoverEl = computed(() => extractDomContainer(popoverRef.value));
|
|
236
247
|
|
|
@@ -286,7 +297,7 @@ const offcanvasBindings = computed(() => ({
|
|
|
286
297
|
// BbOffCanvas already points `aria-labelledby` at that heading, and this
|
|
287
298
|
// fallthrough attribute would win over it.
|
|
288
299
|
...(hasOpenedOnce.value && !props.offCanvasProps?.title
|
|
289
|
-
? { 'aria-labelledby':
|
|
300
|
+
? { 'aria-labelledby': labelledById.value }
|
|
290
301
|
: {}),
|
|
291
302
|
}));
|
|
292
303
|
|
|
@@ -405,12 +416,17 @@ watch(
|
|
|
405
416
|
}
|
|
406
417
|
|
|
407
418
|
el.setAttribute('aria-haspopup', 'dialog');
|
|
419
|
+
// Adopt an existing id; assign one only when absent, and take back only
|
|
420
|
+
// what was assigned.
|
|
421
|
+
const assignedId = !el.id;
|
|
422
|
+
if (assignedId) el.setAttribute('id', activatorId);
|
|
408
423
|
|
|
409
424
|
onCleanup(() => {
|
|
410
425
|
removers.forEach((fn) => fn());
|
|
411
426
|
el.removeAttribute('aria-expanded');
|
|
412
427
|
el.removeAttribute('aria-controls');
|
|
413
428
|
el.removeAttribute('aria-haspopup');
|
|
429
|
+
if (assignedId && el.id === activatorId) el.removeAttribute('id');
|
|
414
430
|
});
|
|
415
431
|
},
|
|
416
432
|
{ immediate: true }
|
|
@@ -421,7 +437,6 @@ watch(
|
|
|
421
437
|
[activatorEl, isOpen, hasOpenedOnce] as const,
|
|
422
438
|
([el, open, opened]) => {
|
|
423
439
|
if (!el || !hasExternalActivator.value || !opened) return;
|
|
424
|
-
el.setAttribute('id', activatorId);
|
|
425
440
|
el.setAttribute('aria-expanded', String(open));
|
|
426
441
|
el.setAttribute('aria-controls', popoverId);
|
|
427
442
|
},
|
|
@@ -472,6 +487,113 @@ const onDocumentClick = (event: MouseEvent) => {
|
|
|
472
487
|
}
|
|
473
488
|
};
|
|
474
489
|
|
|
490
|
+
// --- Non-modal dismissal (Q60.10) ---
|
|
491
|
+
//
|
|
492
|
+
// Without `modal` the panel is a plain top-layer popover: the page stays live,
|
|
493
|
+
// so leaving the panel is how it closes. A press outside (the press itself
|
|
494
|
+
// still lands on what it hit: nothing here prevents it), or focus moving out
|
|
495
|
+
// (Tab past the last control, Shift+Tab before the first, a click that focuses
|
|
496
|
+
// something else), closes it. Neither returns focus to the activator, which
|
|
497
|
+
// would steal it from where the user just went.
|
|
498
|
+
|
|
499
|
+
/** The `role` a non-modal panel needs: a `<div>` is no dialog on its own. */
|
|
500
|
+
const nonModalAttrs = computed(() =>
|
|
501
|
+
props.modal ? {} : { role: 'dialog' as const }
|
|
502
|
+
);
|
|
503
|
+
|
|
504
|
+
/** Set by an outside dismissal, so the close leaves focus where it went. */
|
|
505
|
+
let dismissedOutside = false;
|
|
506
|
+
|
|
507
|
+
/**
|
|
508
|
+
* True from a press on the activator until the task that delivers it ends.
|
|
509
|
+
* The press focuses the activator before its click toggles the panel; that
|
|
510
|
+
* `focusin` is not the user leaving (the click owns the toggle). A keyboard
|
|
511
|
+
* move onto the activator (Shift+Tab out of the panel) is not a press, and
|
|
512
|
+
* still closes. Same guard as BbDropdown.
|
|
513
|
+
*/
|
|
514
|
+
let activatorPress = false;
|
|
515
|
+
|
|
516
|
+
/**
|
|
517
|
+
* Whether `target` belongs to an overlay opened on top of this panel (a menu or
|
|
518
|
+
* a dialog launched from inside it): that overlay owns the interaction, as it
|
|
519
|
+
* owns Escape. A press outside everything still closes both.
|
|
520
|
+
*/
|
|
521
|
+
const ownedByOverlayOnTop = (target: Node) => {
|
|
522
|
+
if (isTopEscapeEntry(escapeKey)) return false;
|
|
523
|
+
const top = topDeliberateSurface();
|
|
524
|
+
if (!top) return false;
|
|
525
|
+
return !top.element || top.element.contains(target);
|
|
526
|
+
};
|
|
527
|
+
|
|
528
|
+
/**
|
|
529
|
+
* The `<dialog>`s around the activator that were already open when the panel
|
|
530
|
+
* opened. One that opens later (a dialog mounted open with this popover open
|
|
531
|
+
* inside it) moves focus to its own first control: that is the dialog's
|
|
532
|
+
* initial focus, not the user leaving, so its first `focusin` is let through.
|
|
533
|
+
*/
|
|
534
|
+
let hostDialogs = new Set<HTMLDialogElement>();
|
|
535
|
+
const collectHostDialogs = () => {
|
|
536
|
+
hostDialogs = new Set();
|
|
537
|
+
let dialog = activatorEl.value?.closest('dialog');
|
|
538
|
+
while (dialog) {
|
|
539
|
+
if (dialog.open) hostDialogs.add(dialog);
|
|
540
|
+
dialog = dialog.parentElement?.closest('dialog');
|
|
541
|
+
}
|
|
542
|
+
};
|
|
543
|
+
|
|
544
|
+
const dismissOutside = () => {
|
|
545
|
+
dismissedOutside = true;
|
|
546
|
+
close();
|
|
547
|
+
};
|
|
548
|
+
|
|
549
|
+
const onDocumentPointerDown = (event: PointerEvent) => {
|
|
550
|
+
if (event.timeStamp <= listenersAddedAt) return;
|
|
551
|
+
const target = event.target;
|
|
552
|
+
if (!(target instanceof Node)) return;
|
|
553
|
+
if (activatorEl.value?.contains(target)) {
|
|
554
|
+
activatorPress = true;
|
|
555
|
+
setTimeout(() => (activatorPress = false), 0);
|
|
556
|
+
return;
|
|
557
|
+
}
|
|
558
|
+
if (popoverEl.value?.contains(target)) return;
|
|
559
|
+
if (ownedByOverlayOnTop(target)) return;
|
|
560
|
+
dismissOutside();
|
|
561
|
+
};
|
|
562
|
+
|
|
563
|
+
/**
|
|
564
|
+
* A click outside with no press before it (a scripted `.click()`, a keyboard
|
|
565
|
+
* activation of an outside control) closes too. After a real press the panel
|
|
566
|
+
* is already closed and this does nothing.
|
|
567
|
+
*/
|
|
568
|
+
const onDocumentOutsideClick = (event: MouseEvent) => {
|
|
569
|
+
if (!isOpen.value || event.timeStamp <= listenersAddedAt) return;
|
|
570
|
+
const target = event.target;
|
|
571
|
+
if (!(target instanceof Node)) return;
|
|
572
|
+
if (activatorEl.value?.contains(target)) return;
|
|
573
|
+
if (popoverEl.value?.contains(target)) return;
|
|
574
|
+
if (ownedByOverlayOnTop(target)) return;
|
|
575
|
+
dismissOutside();
|
|
576
|
+
};
|
|
577
|
+
|
|
578
|
+
const onDocumentFocusIn = (event: FocusEvent) => {
|
|
579
|
+
const target = event.target;
|
|
580
|
+
if (!(target instanceof Node)) return;
|
|
581
|
+
const panel = popoverEl.value;
|
|
582
|
+
if (panel?.contains(target)) return;
|
|
583
|
+
if (activatorPress && activatorEl.value?.contains(target)) return;
|
|
584
|
+
// Focus landing on an ANCESTOR of the panel is the browser's fallback for a
|
|
585
|
+
// press on non-focusable panel content (the panel renders in place), not
|
|
586
|
+
// the user going elsewhere.
|
|
587
|
+
if (target instanceof Element && panel && target.contains(panel)) return;
|
|
588
|
+
const host = target instanceof Element ? target.closest('dialog') : null;
|
|
589
|
+
if (host && panel && host.contains(panel) && !hostDialogs.has(host)) {
|
|
590
|
+
hostDialogs.add(host);
|
|
591
|
+
return;
|
|
592
|
+
}
|
|
593
|
+
if (ownedByOverlayOnTop(target)) return;
|
|
594
|
+
dismissOutside();
|
|
595
|
+
};
|
|
596
|
+
|
|
475
597
|
// Identifies this popover instance in the module-level Escape stack.
|
|
476
598
|
const escapeKey = Symbol('bb-popover');
|
|
477
599
|
|
|
@@ -490,8 +612,26 @@ const addGlobalListeners = () => {
|
|
|
490
612
|
// inside it (Q63.7).
|
|
491
613
|
pushEscapeEntry(escapeKey, { element: () => popoverEl.value });
|
|
492
614
|
listenersAddedAt = performance.now();
|
|
493
|
-
|
|
494
|
-
|
|
615
|
+
if (props.modal) {
|
|
616
|
+
document.addEventListener('click', onDocumentClick, { passive: true });
|
|
617
|
+
document.addEventListener('contextmenu', onDocumentClick, {
|
|
618
|
+
passive: true,
|
|
619
|
+
});
|
|
620
|
+
} else {
|
|
621
|
+
dismissedOutside = false;
|
|
622
|
+
collectHostDialogs();
|
|
623
|
+
document.addEventListener('pointerdown', onDocumentPointerDown, {
|
|
624
|
+
passive: true,
|
|
625
|
+
capture: true,
|
|
626
|
+
});
|
|
627
|
+
document.addEventListener('focusin', onDocumentFocusIn, { passive: true });
|
|
628
|
+
document.addEventListener('click', onDocumentOutsideClick, {
|
|
629
|
+
passive: true,
|
|
630
|
+
});
|
|
631
|
+
document.addEventListener('contextmenu', onDocumentOutsideClick, {
|
|
632
|
+
passive: true,
|
|
633
|
+
});
|
|
634
|
+
}
|
|
495
635
|
document.addEventListener('keydown', onKeydown, { capture: true });
|
|
496
636
|
};
|
|
497
637
|
|
|
@@ -499,6 +639,12 @@ const removeGlobalListeners = () => {
|
|
|
499
639
|
removeEscapeEntry(escapeKey);
|
|
500
640
|
document.removeEventListener('click', onDocumentClick);
|
|
501
641
|
document.removeEventListener('contextmenu', onDocumentClick);
|
|
642
|
+
document.removeEventListener('pointerdown', onDocumentPointerDown, {
|
|
643
|
+
capture: true,
|
|
644
|
+
});
|
|
645
|
+
document.removeEventListener('focusin', onDocumentFocusIn);
|
|
646
|
+
document.removeEventListener('click', onDocumentOutsideClick);
|
|
647
|
+
document.removeEventListener('contextmenu', onDocumentOutsideClick);
|
|
502
648
|
document.removeEventListener('keydown', onKeydown, { capture: true });
|
|
503
649
|
};
|
|
504
650
|
|
|
@@ -554,9 +700,9 @@ const runCloseEffects = () => {
|
|
|
554
700
|
|
|
555
701
|
removeGlobalListeners();
|
|
556
702
|
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
703
|
+
// An outside dismissal leaves focus where the user took it (Q60.10).
|
|
704
|
+
if (dismissedOutside) dismissedOutside = false;
|
|
705
|
+
else if (activatorEl.value) activatorEl.value.focus();
|
|
560
706
|
};
|
|
561
707
|
|
|
562
708
|
// Set by a floating close until CommonPopover reports `hidden`. A close that
|
|
@@ -842,7 +988,8 @@ export type BbPopoverProps = {
|
|
|
842
988
|
*/
|
|
843
989
|
disabled?: boolean;
|
|
844
990
|
/**
|
|
845
|
-
*
|
|
991
|
+
* Renders the panel's content at mount instead of on the first open
|
|
992
|
+
* (the phone sheet's too).
|
|
846
993
|
*/
|
|
847
994
|
eager?: boolean;
|
|
848
995
|
/**
|
|
@@ -855,6 +1002,17 @@ export type BbPopoverProps = {
|
|
|
855
1002
|
* Generated when omitted.
|
|
856
1003
|
*/
|
|
857
1004
|
id?: HTMLAttributes['id'];
|
|
1005
|
+
/**
|
|
1006
|
+
* Makes the floating panel modal: the page behind it goes inert and
|
|
1007
|
+
* cannot scroll, and Tab stays inside the panel until it closes. Off by
|
|
1008
|
+
* default, the panel is a non-modal dialog: the page stays usable, a
|
|
1009
|
+
* click outside closes it and still reaches what was clicked, and Tab
|
|
1010
|
+
* past its last control (or Shift+Tab before its first) leaves it and
|
|
1011
|
+
* closes it. The phone sheet is modal either way.
|
|
1012
|
+
*
|
|
1013
|
+
* @defaultValue `false`
|
|
1014
|
+
*/
|
|
1015
|
+
modal?: boolean;
|
|
858
1016
|
/**
|
|
859
1017
|
* Space the floating container will maintain from the activator.
|
|
860
1018
|
*
|
|
@@ -986,6 +1144,21 @@ export type BbPopoverSlots = {
|
|
|
986
1144
|
*/
|
|
987
1145
|
footer?: (props: BbPopoverDefaultSlotProps) => any;
|
|
988
1146
|
};
|
|
1147
|
+
|
|
1148
|
+
/**
|
|
1149
|
+
* The default slot scope of `<BbPopoverPortal>`: the ONE place this family's
|
|
1150
|
+
* portal slot is typed (Q63.8), so tooling that infers `props` from the call
|
|
1151
|
+
* sites hooks a single type: `P`, the type of `props`, is the seam it will
|
|
1152
|
+
* feed (through a type-only prop on the portal component). Until then `P` is
|
|
1153
|
+
* `any`, so `props.person.name` type-checks with no cast.
|
|
1154
|
+
*/
|
|
1155
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- the default is the point (Q63.8)
|
|
1156
|
+
export type BbPopoverPortalSlotProps<P = any> = {
|
|
1157
|
+
/** The `portalProps` the `v-bb-popover` passed. */
|
|
1158
|
+
props: P;
|
|
1159
|
+
/** Closes the popover. */
|
|
1160
|
+
close: () => void;
|
|
1161
|
+
};
|
|
989
1162
|
```
|
|
990
1163
|
|
|
991
1164
|
## Styles
|
|
@@ -8,8 +8,8 @@
|
|
|
8
8
|
<template><!-- registers content; renders nothing of its own --></template>
|
|
9
9
|
<script setup lang="ts">
|
|
10
10
|
import { watchEffect } from 'vue';
|
|
11
|
+
import type { BbPopoverPortalSlotProps } from './types';
|
|
11
12
|
import {
|
|
12
|
-
type DirectivePortalSlotProps,
|
|
13
13
|
popoverPortals,
|
|
14
14
|
useDirectivePortal,
|
|
15
15
|
} from '@/directives/directivePortal';
|
|
@@ -25,7 +25,7 @@ const props = defineProps<{
|
|
|
25
25
|
}>();
|
|
26
26
|
const slots = defineSlots<{
|
|
27
27
|
/** The popover body. `props` is the directive's `portalProps`; `close` closes the popover. */
|
|
28
|
-
default?: (props:
|
|
28
|
+
default?: (props: BbPopoverPortalSlotProps) => any;
|
|
29
29
|
}>();
|
|
30
30
|
|
|
31
31
|
watchEffect(
|
|
@@ -131,7 +131,8 @@ export type BbPopoverProps = {
|
|
|
131
131
|
*/
|
|
132
132
|
disabled?: boolean;
|
|
133
133
|
/**
|
|
134
|
-
*
|
|
134
|
+
* Renders the panel's content at mount instead of on the first open
|
|
135
|
+
* (the phone sheet's too).
|
|
135
136
|
*/
|
|
136
137
|
eager?: boolean;
|
|
137
138
|
/**
|
|
@@ -144,6 +145,17 @@ export type BbPopoverProps = {
|
|
|
144
145
|
* Generated when omitted.
|
|
145
146
|
*/
|
|
146
147
|
id?: HTMLAttributes['id'];
|
|
148
|
+
/**
|
|
149
|
+
* Makes the floating panel modal: the page behind it goes inert and
|
|
150
|
+
* cannot scroll, and Tab stays inside the panel until it closes. Off by
|
|
151
|
+
* default, the panel is a non-modal dialog: the page stays usable, a
|
|
152
|
+
* click outside closes it and still reaches what was clicked, and Tab
|
|
153
|
+
* past its last control (or Shift+Tab before its first) leaves it and
|
|
154
|
+
* closes it. The phone sheet is modal either way.
|
|
155
|
+
*
|
|
156
|
+
* @defaultValue `false`
|
|
157
|
+
*/
|
|
158
|
+
modal?: boolean;
|
|
147
159
|
/**
|
|
148
160
|
* Space the floating container will maintain from the activator.
|
|
149
161
|
*
|
|
@@ -275,6 +287,21 @@ export type BbPopoverSlots = {
|
|
|
275
287
|
*/
|
|
276
288
|
footer?: (props: BbPopoverDefaultSlotProps) => any;
|
|
277
289
|
};
|
|
290
|
+
|
|
291
|
+
/**
|
|
292
|
+
* The default slot scope of `<BbPopoverPortal>`: the ONE place this family's
|
|
293
|
+
* portal slot is typed (Q63.8), so tooling that infers `props` from the call
|
|
294
|
+
* sites hooks a single type: `P`, the type of `props`, is the seam it will
|
|
295
|
+
* feed (through a type-only prop on the portal component). Until then `P` is
|
|
296
|
+
* `any`, so `props.person.name` type-checks with no cast.
|
|
297
|
+
*/
|
|
298
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- the default is the point (Q63.8)
|
|
299
|
+
export type BbPopoverPortalSlotProps<P = any> = {
|
|
300
|
+
/** The `portalProps` the `v-bb-popover` passed. */
|
|
301
|
+
props: P;
|
|
302
|
+
/** Closes the popover. */
|
|
303
|
+
close: () => void;
|
|
304
|
+
};
|
|
278
305
|
```
|
|
279
306
|
|
|
280
307
|
## Styles
|