bitboss-ui 3.0.0-beta.48 → 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 +115 -13
- package/dist/ai/BbAvatar.md +1 -1
- package/dist/ai/BbBreadcrumbs.md +65 -65
- package/dist/ai/BbButton.md +16 -5
- package/dist/ai/BbCheckbox.md +0 -2
- package/dist/ai/BbCheckboxGroup.md +13 -20
- 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 +4 -2
- package/dist/ai/BbNumberInput.md +88 -21
- package/dist/ai/BbPopover.md +29 -23
- 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 +106 -105
- package/dist/ai/BbTabsList.md +2 -2
- package/dist/ai/BbTabsPanels.md +1 -1
- package/dist/ai/BbTabsRoot.md +2 -2
- package/dist/ai/BbTooltip.md +24 -10
- package/dist/ai/BbTree.md +14 -11
- package/dist/ai/changelog.json +256 -5
- package/dist/ai/components.json +36 -34
- 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 +43 -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 +114 -17
- 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 +2 -2
- 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/BbBreadcrumbs.json +10 -6
- package/dist/ai/manifest/components/BbBreadcrumbs.tree.json +1 -1
- package/dist/ai/manifest/components/BbButton.json +1 -1
- package/dist/ai/manifest/components/BbCheckboxGroup.json +2 -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/BbNumberInput.json +6 -1
- package/dist/ai/manifest/components/BbNumberInput.tree.json +2 -1
- package/dist/ai/manifest/components/BbPopover.json +1 -0
- 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/BbSelectPopover.json +2 -2
- package/dist/ai/manifest/components/BbSwitchGroup.json +2 -2
- package/dist/ai/manifest/components/BbTabs.json +7 -6
- 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 +5 -4
- package/dist/ai/manifest/components/BbTooltip.json +1 -1
- package/dist/ai/manifest/index.json +2 -2
- package/dist/ai/manifest/meta.json +2 -0
- package/dist/ai/manifest/types.advanced.json +10 -9
- package/dist/ai/manifest/types.api.json +5 -4
- 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 +2 -2
- package/dist/ai/source/BbBadgeButton.md +5 -4
- 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 +71 -33
- 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/BbColorInput.md +10 -9
- package/dist/ai/source/BbConfirm.md +1 -1
- package/dist/ai/source/BbConfirmPortal.md +1 -1
- 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 +230 -158
- package/dist/ai/source/BbDropdownButton.md +19 -12
- package/dist/ai/source/BbDropdownGroup.md +126 -93
- package/dist/ai/source/BbForm.md +25 -1
- 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 +152 -8
- package/dist/ai/source/BbPopoverPortal.md +11 -0
- 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 +27 -23
- package/dist/ai/source/BbTabsList.md +26 -22
- package/dist/ai/source/BbTabsPanels.md +26 -22
- package/dist/ai/source/BbTabsRoot.md +25 -21
- 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 +54 -8
- 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 +6 -0
- 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 +84 -71
- package/dist/components/BbButton/toggleRoving.d.ts +6 -0
- package/dist/components/BbButton/toggleRoving.js +45 -0
- package/dist/components/BbButton/types.d.ts +4 -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/BbColorInput/BbColorInput.vue_vue_type_script_setup_true_lang.js +69 -69
- 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 +119 -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/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 -164
- package/dist/components/BbPopover/types.d.ts +11 -0
- 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 +25 -21
- 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 +102 -97
- package/dist/components/BbTooltip/tooltipWarmup.d.ts +23 -0
- package/dist/components/BbTooltip/tooltipWarmup.js +7 -0
- package/dist/components/BbTooltip/types.d.ts +7 -2
- 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/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/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 +1 -1
- package/dist/index.js +4 -4
- package/dist/llms-full.txt +1785 -1637
- package/dist/llms-medium.txt +74 -46
- package/dist/llms.txt +7 -7
- package/dist/locale-blueprint.json +16 -13
- package/dist/styles.css +2 -2
- package/dist/types/ptComponentMap.d.ts +1 -1
- 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 +12 -4
- package/scripts/lib/eslint-plugin.d.ts +5 -1
- package/scripts/lib/eslint-plugin.mjs +187 -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/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/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
|
|
|
@@ -92,7 +92,7 @@
|
|
|
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',
|
|
@@ -485,6 +487,113 @@ const onDocumentClick = (event: MouseEvent) => {
|
|
|
485
487
|
}
|
|
486
488
|
};
|
|
487
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
|
+
|
|
488
597
|
// Identifies this popover instance in the module-level Escape stack.
|
|
489
598
|
const escapeKey = Symbol('bb-popover');
|
|
490
599
|
|
|
@@ -503,8 +612,26 @@ const addGlobalListeners = () => {
|
|
|
503
612
|
// inside it (Q63.7).
|
|
504
613
|
pushEscapeEntry(escapeKey, { element: () => popoverEl.value });
|
|
505
614
|
listenersAddedAt = performance.now();
|
|
506
|
-
|
|
507
|
-
|
|
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
|
+
}
|
|
508
635
|
document.addEventListener('keydown', onKeydown, { capture: true });
|
|
509
636
|
};
|
|
510
637
|
|
|
@@ -512,6 +639,12 @@ const removeGlobalListeners = () => {
|
|
|
512
639
|
removeEscapeEntry(escapeKey);
|
|
513
640
|
document.removeEventListener('click', onDocumentClick);
|
|
514
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);
|
|
515
648
|
document.removeEventListener('keydown', onKeydown, { capture: true });
|
|
516
649
|
};
|
|
517
650
|
|
|
@@ -567,9 +700,9 @@ const runCloseEffects = () => {
|
|
|
567
700
|
|
|
568
701
|
removeGlobalListeners();
|
|
569
702
|
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
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();
|
|
573
706
|
};
|
|
574
707
|
|
|
575
708
|
// Set by a floating close until CommonPopover reports `hidden`. A close that
|
|
@@ -869,6 +1002,17 @@ export type BbPopoverProps = {
|
|
|
869
1002
|
* Generated when omitted.
|
|
870
1003
|
*/
|
|
871
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;
|
|
872
1016
|
/**
|
|
873
1017
|
* Space the floating container will maintain from the activator.
|
|
874
1018
|
*
|
|
@@ -145,6 +145,17 @@ export type BbPopoverProps = {
|
|
|
145
145
|
* Generated when omitted.
|
|
146
146
|
*/
|
|
147
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;
|
|
148
159
|
/**
|
|
149
160
|
* Space the floating container will maintain from the activator.
|
|
150
161
|
*
|
|
@@ -10,15 +10,16 @@
|
|
|
10
10
|
:aria-label="label || undefined"
|
|
11
11
|
:aria-valuemax="max"
|
|
12
12
|
:aria-valuemin="min"
|
|
13
|
-
:aria-valuenow="ariaValueNow"
|
|
13
|
+
:aria-valuenow="indeterminate ? undefined : ariaValueNow"
|
|
14
14
|
class="bb-progress"
|
|
15
|
+
:class="{ 'bb-progress--indeterminate': indeterminate }"
|
|
15
16
|
role="progressbar"
|
|
16
17
|
:style="containerStyle"
|
|
17
|
-
v-bind="
|
|
18
|
+
v-bind="rootAttrs"
|
|
18
19
|
>
|
|
19
20
|
<div
|
|
20
21
|
class="bb-progress__bar"
|
|
21
|
-
:style="barStyle"
|
|
22
|
+
:style="indeterminate ? undefined : barStyle"
|
|
22
23
|
v-bind="passthrough.bar"
|
|
23
24
|
></div>
|
|
24
25
|
</div>
|
|
@@ -44,7 +45,7 @@ const props = withDefaults(defineProps<BbProgressProps>(), {
|
|
|
44
45
|
});
|
|
45
46
|
|
|
46
47
|
/**
|
|
47
|
-
* Passthrough (plans/passthrough/BbProgress.md). `root` (the track) and `bar` (the fill);
|
|
48
|
+
* Passthrough (plans/passthrough/BbProgress.md). `root` (the track) and `bar` (the fill); one state, `indeterminate`.
|
|
48
49
|
*/
|
|
49
50
|
const passthrough = usePassthrough({
|
|
50
51
|
component: 'BbProgress',
|
|
@@ -52,14 +53,25 @@ const passthrough = usePassthrough({
|
|
|
52
53
|
props,
|
|
53
54
|
parts: BB_PROGRESS_PT.parts,
|
|
54
55
|
states: BB_PROGRESS_PT.states,
|
|
55
|
-
active: {},
|
|
56
|
+
active: { indeterminate: () => !!props.indeterminate },
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
/*
|
|
60
|
+
* Q60.29: an indeterminate bar reports no value, so a consumer's
|
|
61
|
+
* `aria-valuetext` (the guide suggests one for units) is held back while it is
|
|
62
|
+
* on and returns with the value.
|
|
63
|
+
*/
|
|
64
|
+
const rootAttrs = computed(() => {
|
|
65
|
+
const attrs = passthrough.rootAttrs as Record<string, unknown>;
|
|
66
|
+
if (!props.indeterminate || !('aria-valuetext' in attrs)) return attrs;
|
|
67
|
+
const { 'aria-valuetext': _valuetext, ...rest } = attrs;
|
|
68
|
+
return rest;
|
|
56
69
|
});
|
|
57
70
|
|
|
58
71
|
// aria-valuenow must sit within [valuemin, valuemax], so it mirrors the
|
|
59
|
-
// clamped visual fill.
|
|
60
|
-
// indeterminate
|
|
61
|
-
//
|
|
62
|
-
// "indeterminate" to assistive tech.
|
|
72
|
+
// clamped visual fill. Only `indeterminate` omits it (Q60.29: omission is how
|
|
73
|
+
// a progressbar says "indeterminate" to assistive tech): a `null` value
|
|
74
|
+
// reports `min`, matching the empty bar it renders.
|
|
63
75
|
// NaN (a calc glitch upstream) degrades like `null`: `clamp` would pass it
|
|
64
76
|
// through to aria-valuenow="NaN" and a dropped transform (a full bar).
|
|
65
77
|
// ±Infinity already clamps to an end.
|
|
@@ -110,8 +122,7 @@ import type { PtMap, PtValue } from '@/types/passthrough';
|
|
|
110
122
|
* Props for BbProgress.
|
|
111
123
|
*/
|
|
112
124
|
/**
|
|
113
|
-
* Passthrough parts of `BbProgress` (plans/passthrough/BbProgress.md).
|
|
114
|
-
* it paints is a state.
|
|
125
|
+
* Passthrough parts of `BbProgress` (plans/passthrough/BbProgress.md).
|
|
115
126
|
*
|
|
116
127
|
* @part root - The track (the `progressbar` element); the bar follows it
|
|
117
128
|
* through its locals (`--track`, `--track-color`, `--accent`, `--r`, the
|
|
@@ -121,27 +132,45 @@ import type { PtMap, PtValue } from '@/types/passthrough';
|
|
|
121
132
|
* never its position.
|
|
122
133
|
*/
|
|
123
134
|
export type BbProgressPtPart = 'root' | 'bar';
|
|
124
|
-
/**
|
|
135
|
+
/**
|
|
136
|
+
* Passthrough states of `BbProgress`.
|
|
137
|
+
*
|
|
138
|
+
* @state indeterminate - Component-wide: `indeterminate` is on; the bar
|
|
139
|
+
* slides (pulses under reduced motion) instead of showing a value.
|
|
140
|
+
*/
|
|
141
|
+
export type BbProgressPtState = 'indeterminate';
|
|
142
|
+
/** The runtime lists the resolver is wired with. */
|
|
125
143
|
export const BB_PROGRESS_PT = {
|
|
126
144
|
parts: ['root', 'bar'],
|
|
127
|
-
states: [],
|
|
145
|
+
states: ['indeterminate'],
|
|
128
146
|
} as const satisfies {
|
|
129
147
|
parts: readonly BbProgressPtPart[];
|
|
130
|
-
states: readonly
|
|
148
|
+
states: readonly BbProgressPtState[];
|
|
131
149
|
};
|
|
132
150
|
|
|
133
151
|
// Spelled INLINE with this component's own union (Vue's SFC type resolver
|
|
134
152
|
// does not substitute a generic alias's type parameters — PASSTHROUGH.md T20).
|
|
135
|
-
// No state axis: a `never` state does not resolve to finite keys.
|
|
136
153
|
// eslint-disable-next-line @typescript-eslint/consistent-indexed-object-style
|
|
137
154
|
export type BbProgressProps = {
|
|
138
|
-
[K in
|
|
155
|
+
[K in
|
|
156
|
+
| `pt:${BbProgressPtPart}`
|
|
157
|
+
| `pt:${BbProgressPtPart}:${BbProgressPtState}`]?: PtValue;
|
|
139
158
|
} & {
|
|
140
159
|
/**
|
|
141
160
|
* Passthrough, object form: the same keys as the `pt:*` attributes
|
|
142
|
-
* without the prefix.
|
|
161
|
+
* without the prefix. Parts: `root`, `bar`; state: `indeterminate`.
|
|
162
|
+
*/
|
|
163
|
+
pt?: PtMap<BbProgressPtPart, BbProgressPtState>;
|
|
164
|
+
/**
|
|
165
|
+
* A wait you cannot measure yet: the bar slides back and forth (a calm
|
|
166
|
+
* pulse under `prefers-reduced-motion`) and the progressbar reports no
|
|
167
|
+
* value (`aria-valuenow` is omitted, as the ARIA pattern asks). The
|
|
168
|
+
* `modelValue` is kept and shows again when this turns off. A `null`
|
|
169
|
+
* `modelValue` alone is still an empty bar, not this.
|
|
170
|
+
*
|
|
171
|
+
* @defaultValue `false`
|
|
143
172
|
*/
|
|
144
|
-
|
|
173
|
+
indeterminate?: boolean;
|
|
145
174
|
/**
|
|
146
175
|
* The current progress value — a number between `min` and `max`. This is a
|
|
147
176
|
* one-way input prop (BbProgress is a display component and never emits
|
|
@@ -215,4 +244,39 @@ export type BbProgressProps = {
|
|
|
215
244
|
transition: transform var(--transition-duration);
|
|
216
245
|
width: 100%;
|
|
217
246
|
}
|
|
247
|
+
|
|
248
|
+
/*
|
|
249
|
+
* Q60.29 — `indeterminate`: a wait with no measurable end. A short bar slides
|
|
250
|
+
* across the track (transform only: composited). Under reduced motion the
|
|
251
|
+
* full bar breathes instead, slowly, without moving.
|
|
252
|
+
*/
|
|
253
|
+
.bb-progress--indeterminate > .bb-progress__bar {
|
|
254
|
+
animation: bb-progress-slide 1.6s var(--bb-ease) infinite;
|
|
255
|
+
transition: none;
|
|
256
|
+
width: 40%;
|
|
257
|
+
|
|
258
|
+
@media (prefers-reduced-motion: reduce) {
|
|
259
|
+
animation: bb-progress-pulse 2.4s ease-in-out infinite;
|
|
260
|
+
width: 100%;
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
@keyframes bb-progress-slide {
|
|
265
|
+
from {
|
|
266
|
+
transform: translateX(-100%);
|
|
267
|
+
}
|
|
268
|
+
to {
|
|
269
|
+
transform: translateX(250%);
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
@keyframes bb-progress-pulse {
|
|
274
|
+
0%,
|
|
275
|
+
100% {
|
|
276
|
+
opacity: 1;
|
|
277
|
+
}
|
|
278
|
+
50% {
|
|
279
|
+
opacity: 0.4;
|
|
280
|
+
}
|
|
281
|
+
}
|
|
218
282
|
```
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
:loading="loading"
|
|
30
30
|
:name="resolvedName"
|
|
31
31
|
:passthrough="containerPassthrough"
|
|
32
|
-
:readonly="
|
|
32
|
+
:readonly="fieldReadonly"
|
|
33
33
|
:reverse="reverse"
|
|
34
34
|
:show-asterisk="showAsterisk"
|
|
35
35
|
:show-hint="showHint"
|
|
@@ -53,7 +53,7 @@
|
|
|
53
53
|
<OptionsContainer
|
|
54
54
|
:ref="setOptionsElement"
|
|
55
55
|
:aria-labelledby="hasLegend() ? `${fieldId}__label` : undefined"
|
|
56
|
-
:aria-readonly="hasLegend() &&
|
|
56
|
+
:aria-readonly="hasLegend() && fieldReadonly ? true : undefined"
|
|
57
57
|
:aria-required="hasLegend() ? fieldAriaRequired : undefined"
|
|
58
58
|
block="bb-radio-group"
|
|
59
59
|
:empty-text="emptyText"
|
|
@@ -115,7 +115,7 @@
|
|
|
115
115
|
:focused="rowFocus.focused(option.valueHash)"
|
|
116
116
|
:has-errors="!!fieldHasErrors"
|
|
117
117
|
:has-warnings="!!fieldHasWarnings && !fieldHasErrors"
|
|
118
|
-
:readonly="!!
|
|
118
|
+
:readonly="!!fieldReadonly"
|
|
119
119
|
v-bind="passthrough.part('icon', rowStates, option.item)"
|
|
120
120
|
/>
|
|
121
121
|
<!-- eslint-enable vue/attributes-order -->
|
|
@@ -196,6 +196,7 @@ const {
|
|
|
196
196
|
showAsterisk,
|
|
197
197
|
errors: fieldErrors,
|
|
198
198
|
ariaRequired: fieldAriaRequired,
|
|
199
|
+
readonly: fieldReadonly,
|
|
199
200
|
} = useFormBinding(declaredProps, declaredEmit, {
|
|
200
201
|
componentName: 'BbRadioGroup',
|
|
201
202
|
identifierFallback: () => declaredProps.legend,
|
|
@@ -321,6 +322,7 @@ const { options } = useBaseOptions({
|
|
|
321
322
|
itemText: props.itemText as any,
|
|
322
323
|
itemProps: toRef(props, 'itemProps'),
|
|
323
324
|
itemValue: props.itemValue as any,
|
|
325
|
+
optionDefaults: true,
|
|
324
326
|
max: Infinity,
|
|
325
327
|
selectable: toRef(props, 'selectable'),
|
|
326
328
|
selectedIndexedByHash: modelValueIndexedByHash,
|
|
@@ -740,14 +742,18 @@ export type BbRadioGroupProps<T> = {
|
|
|
740
742
|
/**
|
|
741
743
|
* Defines a path that returns a property of the object to use as text or a function that returns a string.
|
|
742
744
|
*
|
|
743
|
-
*
|
|
745
|
+
* Unset: own `label`, else `text` (`{ label, value }` needs no accessor).
|
|
746
|
+
*
|
|
747
|
+
* @defaultValue own `label`, else `text`, else `JSON.stringify(item)`
|
|
744
748
|
*/
|
|
745
749
|
itemText?: ItemAccessor<T, string>;
|
|
746
750
|
|
|
747
751
|
/**
|
|
748
752
|
* Defines a path that returns a property of the object to use as value or a function that returns any value.
|
|
749
753
|
*
|
|
750
|
-
*
|
|
754
|
+
* Unset: own `value`, even `null`.
|
|
755
|
+
*
|
|
756
|
+
* @defaultValue own `value`, else the whole item
|
|
751
757
|
*/
|
|
752
758
|
itemValue?: ItemAccessor<T>;
|
|
753
759
|
|
|
@@ -1054,6 +1060,7 @@ export type BbRadioGroupSlots<T> = {
|
|
|
1054
1060
|
.bb-radio-group {
|
|
1055
1061
|
.bb-field__layout--horizontal {
|
|
1056
1062
|
.bb-field__label {
|
|
1063
|
+
/* stylelint-disable-next-line declaration-property-value-disallowed-list -- support: `float: inline-start` needs Chrome 118, above the 114 floor */
|
|
1057
1064
|
float: left;
|
|
1058
1065
|
}
|
|
1059
1066
|
}
|