@brandsync/wc 1.7.0 → 1.9.0
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/custom-elements.json +340 -24
- package/dist/brandsync-wc/brandsync-wc.esm.js +1 -1
- package/dist/brandsync-wc/{p-fde5e9f1.entry.js → p-051d3064.entry.js} +1 -1
- package/dist/brandsync-wc/{p-f243683f.entry.js → p-05c7de28.entry.js} +1 -1
- package/dist/brandsync-wc/{p-2d6955d6.entry.js → p-062cfa34.entry.js} +1 -1
- package/dist/brandsync-wc/p-0e39b9cc.entry.js +1 -0
- package/dist/brandsync-wc/p-0eed6813.entry.js +1 -0
- package/dist/brandsync-wc/{p-d25b7b74.entry.js → p-107b1c5d.entry.js} +1 -1
- package/dist/brandsync-wc/{p-538cc08e.entry.js → p-114d2fd8.entry.js} +1 -1
- package/dist/brandsync-wc/{p-6754dfa9.entry.js → p-1c0db4d6.entry.js} +1 -1
- package/dist/brandsync-wc/{p-4a1a5d6e.entry.js → p-1f7208cb.entry.js} +1 -1
- package/dist/brandsync-wc/p-2181378f.entry.js +1 -0
- package/dist/brandsync-wc/{p-d06543a5.entry.js → p-235ae012.entry.js} +1 -1
- package/dist/brandsync-wc/{p-2700a63e.entry.js → p-275072dd.entry.js} +1 -1
- package/dist/brandsync-wc/p-27bbed83.entry.js +1 -0
- package/dist/brandsync-wc/p-2891d40b.entry.js +1 -0
- package/dist/brandsync-wc/p-29027559.entry.js +1 -0
- package/dist/brandsync-wc/{p-a36a0e6a.entry.js → p-3176d1d3.entry.js} +1 -1
- package/dist/brandsync-wc/{p-0d86c22d.entry.js → p-33e44094.entry.js} +1 -1
- package/dist/brandsync-wc/{p-e427bbda.entry.js → p-360452c2.entry.js} +1 -1
- package/dist/brandsync-wc/p-36bf37d9.entry.js +1 -0
- package/dist/brandsync-wc/p-3b64e3cd.entry.js +1 -0
- package/dist/brandsync-wc/p-3ec74d35.entry.js +1 -0
- package/dist/brandsync-wc/p-4574a707.entry.js +1 -0
- package/dist/brandsync-wc/p-4e5dcaff.entry.js +1 -0
- package/dist/brandsync-wc/{p-61db6ce2.entry.js → p-61c1a2a3.entry.js} +1 -1
- package/dist/brandsync-wc/{p-85c70f6d.entry.js → p-6331de9c.entry.js} +1 -1
- package/dist/brandsync-wc/{p-9c1be2a0.entry.js → p-6bf2f116.entry.js} +1 -1
- package/dist/brandsync-wc/p-6fd7dd6a.entry.js +1 -0
- package/dist/brandsync-wc/{p-c3a28a89.entry.js → p-70f64b25.entry.js} +1 -1
- package/dist/brandsync-wc/{p-06e9b45d.entry.js → p-7b00dd36.entry.js} +1 -1
- package/dist/brandsync-wc/{p-13e4966c.entry.js → p-7c94e6ae.entry.js} +1 -1
- package/dist/brandsync-wc/p-835a8dc7.entry.js +1 -0
- package/dist/brandsync-wc/{p-77433277.entry.js → p-8ee0153b.entry.js} +1 -1
- package/dist/brandsync-wc/{p-e1069ba9.entry.js → p-9f65f998.entry.js} +1 -1
- package/dist/brandsync-wc/p-9f6fe37d.entry.js +1 -0
- package/dist/brandsync-wc/{p-b2dc9886.entry.js → p-9f8852a0.entry.js} +1 -1
- package/dist/brandsync-wc/{p-DuyFft7h.js → p-AgoOSYvW.js} +2 -2
- package/dist/brandsync-wc/{p-fba01c96.entry.js → p-a09e157f.entry.js} +1 -1
- package/dist/brandsync-wc/{p-55e6438c.entry.js → p-a0d5a620.entry.js} +1 -1
- package/dist/brandsync-wc/{p-8b2ab522.entry.js → p-a5feaad4.entry.js} +1 -1
- package/dist/brandsync-wc/{p-cbaa19ab.entry.js → p-a92eec48.entry.js} +1 -1
- package/dist/brandsync-wc/{p-3eab22a5.entry.js → p-ae978c9a.entry.js} +1 -1
- package/dist/brandsync-wc/{p-f2ce9a1f.entry.js → p-bbcc47b0.entry.js} +1 -1
- package/dist/brandsync-wc/{p-80cf96ff.entry.js → p-be2c1740.entry.js} +1 -1
- package/dist/brandsync-wc/p-c10d2529.entry.js +1 -0
- package/dist/brandsync-wc/{p-819a3dae.entry.js → p-c3f72584.entry.js} +1 -1
- package/dist/brandsync-wc/{p-8b57f606.entry.js → p-c4de155c.entry.js} +1 -1
- package/dist/brandsync-wc/{p-c197cc95.entry.js → p-cfcf3f0a.entry.js} +1 -1
- package/dist/brandsync-wc/{p-f8f03334.entry.js → p-de7c946d.entry.js} +1 -1
- package/dist/brandsync-wc/{p-600b5434.entry.js → p-e9b43754.entry.js} +1 -1
- package/dist/brandsync-wc/{p-4bff9b4b.entry.js → p-f006d962.entry.js} +1 -1
- package/dist/brandsync-wc/p-f074f94e.entry.js +1 -0
- package/dist/brandsync-wc/{p-7ed5670e.entry.js → p-f7d47c17.entry.js} +1 -1
- package/dist/brandsync-wc/p-fc240aa0.entry.js +1 -0
- package/dist/brandsync-wc/{p-f518f486.entry.js → p-fc58c663.entry.js} +1 -1
- package/dist/brandsync-wc/{p-be14f99f.entry.js → p-fddc7bd1.entry.js} +1 -1
- package/dist/cjs/brandsync-wc.cjs.js +2 -2
- package/dist/cjs/bs-accordion.cjs.entry.js +2 -2
- package/dist/cjs/bs-ai-disclaimer.cjs.entry.js +1 -1
- package/dist/cjs/bs-ai-greeting.cjs.entry.js +1 -1
- package/dist/cjs/bs-ai-thinking.cjs.entry.js +1 -1
- package/dist/cjs/bs-attachment-list.cjs.entry.js +2 -2
- package/dist/cjs/bs-attachment.cjs.entry.js +2 -2
- package/dist/cjs/bs-avatar.cjs.entry.js +1 -1
- package/dist/cjs/bs-badge.cjs.entry.js +1 -1
- package/dist/cjs/bs-breadcrumb-overflow.cjs.entry.js +15 -3
- package/dist/cjs/bs-breadcrumb.cjs.entry.js +16 -2
- package/dist/cjs/bs-breadcrumbs.cjs.entry.js +1 -1
- package/dist/cjs/bs-button-skeleton.cjs.entry.js +1 -1
- package/dist/cjs/bs-button.cjs.entry.js +23 -4
- package/dist/cjs/bs-card.cjs.entry.js +2 -2
- package/dist/cjs/bs-carousel.cjs.entry.js +1 -1
- package/dist/cjs/bs-chatbot-feedback.cjs.entry.js +2 -2
- package/dist/cjs/bs-chatbot-header.cjs.entry.js +1 -1
- package/dist/cjs/bs-chatbot-response-action.cjs.entry.js +2 -2
- package/dist/cjs/bs-chatbot-sources-drawer.cjs.entry.js +1 -1
- package/dist/cjs/bs-chatbot-suggestion-button.cjs.entry.js +1 -1
- package/dist/cjs/bs-checkbox-skeleton.cjs.entry.js +1 -1
- package/dist/cjs/bs-checkbox.cjs.entry.js +48 -3
- package/dist/cjs/bs-chip-filter.cjs.entry.js +2 -2
- package/dist/cjs/bs-chip-informative.cjs.entry.js +2 -2
- package/dist/cjs/bs-chip-input.cjs.entry.js +2 -2
- package/dist/cjs/bs-composer-status-banner.cjs.entry.js +1 -1
- package/dist/cjs/bs-composer.cjs.entry.js +1 -1
- package/dist/cjs/bs-data-table.cjs.entry.js +20 -6
- package/dist/cjs/bs-dialog.cjs.entry.js +2 -2
- package/dist/cjs/bs-file-upload-item.cjs.entry.js +1 -1
- package/dist/cjs/bs-file-upload.cjs.entry.js +1 -1
- package/dist/cjs/bs-icon-button.cjs.entry.js +23 -4
- package/dist/cjs/bs-inline-tab.cjs.entry.js +11 -3
- package/dist/cjs/bs-input.cjs.entry.js +69 -5
- package/dist/cjs/bs-logo.cjs.entry.js +1 -1
- package/dist/cjs/bs-menu-item.cjs.entry.js +1 -1
- package/dist/cjs/bs-menu.cjs.entry.js +25 -3
- package/dist/cjs/bs-navigation-drawer-item.cjs.entry.js +2 -2
- package/dist/cjs/bs-navigation-drawer.cjs.entry.js +119 -6
- package/dist/cjs/bs-navigation-header.cjs.entry.js +2 -2
- package/dist/cjs/bs-pagination.cjs.entry.js +1 -1
- package/dist/cjs/bs-progress-linear.cjs.entry.js +1 -1
- package/dist/cjs/bs-progress.cjs.entry.js +8 -3
- package/dist/cjs/bs-radio.cjs.entry.js +81 -12
- package/dist/cjs/bs-slider.cjs.entry.js +54 -2
- package/dist/cjs/bs-snackbar.cjs.entry.js +1 -1
- package/dist/cjs/bs-source-link.cjs.entry.js +2 -2
- package/dist/cjs/bs-stepper-step.cjs.entry.js +2 -2
- package/dist/cjs/bs-stepper.cjs.entry.js +3 -2
- package/dist/cjs/bs-switch.cjs.entry.js +36 -3
- package/dist/cjs/bs-tab.cjs.entry.js +11 -3
- package/dist/cjs/bs-tabs.cjs.entry.js +97 -3
- package/dist/cjs/bs-toast.cjs.entry.js +1 -1
- package/dist/cjs/bs-tooltip.cjs.entry.js +2 -2
- package/dist/cjs/{index-D7e6DfLV.js → index-kk9YXF2S.js} +43 -5
- package/dist/cjs/loader.cjs.js +2 -2
- package/dist/collection/components/bs-a11y.cmp.test.js +54 -0
- package/dist/collection/components/bs-accordion/bs-accordion.css +5 -5
- package/dist/collection/components/bs-attachment/bs-attachment.css +1 -1
- package/dist/collection/components/bs-attachment-list/bs-attachment-list.css +1 -1
- package/dist/collection/components/bs-breadcrumb/bs-breadcrumb/bs-breadcrumb.cmp.test.js +63 -0
- package/dist/collection/components/bs-breadcrumb/bs-breadcrumb/bs-breadcrumb.js +32 -1
- package/dist/collection/components/bs-breadcrumb/bs-breadcrumb-overflow/bs-breadcrumb-overflow.cmp.test.js +45 -0
- package/dist/collection/components/bs-breadcrumb/bs-breadcrumb-overflow/bs-breadcrumb-overflow.css +1 -1
- package/dist/collection/components/bs-breadcrumb/bs-breadcrumb-overflow/bs-breadcrumb-overflow.js +30 -1
- package/dist/collection/components/bs-button/bs-button/bs-button.css +17 -10
- package/dist/collection/components/bs-button/bs-button/bs-button.js +16 -3
- package/dist/collection/components/bs-button/bs-icon-button/bs-icon-button.cmp.test.js +20 -0
- package/dist/collection/components/bs-button/bs-icon-button/bs-icon-button.css +21 -4
- package/dist/collection/components/bs-button/bs-icon-button/bs-icon-button.js +18 -4
- package/dist/collection/components/bs-button/bs-icon-button/bs-icon-button.stories.js +10 -0
- package/dist/collection/components/bs-card/bs-card.css +4 -0
- package/dist/collection/components/bs-chatbot-feedback/bs-chatbot-feedback.css +1 -1
- package/dist/collection/components/bs-chatbot-response-action/bs-chatbot-response-action.css +3 -3
- package/dist/collection/components/bs-checkbox/bs-checkbox.css +8 -1
- package/dist/collection/components/bs-checkbox/bs-checkbox.js +100 -2
- package/dist/collection/components/bs-chip/bs-chip-filter/bs-chip-filter.css +4 -4
- package/dist/collection/components/bs-chip/bs-chip-informative/bs-chip-informative.css +4 -4
- package/dist/collection/components/bs-chip/bs-chip-input/bs-chip-input.css +5 -5
- package/dist/collection/components/bs-data-table/bs-data-table.cmp.test.js +19 -0
- package/dist/collection/components/bs-data-table/bs-data-table.css +1 -1
- package/dist/collection/components/bs-data-table/bs-data-table.js +19 -5
- package/dist/collection/components/bs-data-table/bs-data-table.stories.js +8 -1
- package/dist/collection/components/bs-dialog/bs-dialog.css +5 -1
- package/dist/collection/components/bs-form-association.cmp.test.js +172 -0
- package/dist/collection/components/bs-input/bs-input.css +10 -4
- package/dist/collection/components/bs-input/bs-input.js +82 -4
- package/dist/collection/components/bs-keyboard-nav.cmp.test.js +100 -0
- package/dist/collection/components/bs-logo/bs-logo.cmp.test.js +52 -3
- package/dist/collection/components/bs-menu/bs-menu.css +4 -0
- package/dist/collection/components/bs-menu/bs-menu.js +33 -1
- package/dist/collection/components/bs-menu/bs-menu.stories.js +54 -0
- package/dist/collection/components/bs-progress/bs-progress.js +27 -2
- package/dist/collection/components/bs-radio/bs-radio.cmp.test.js +4 -10
- package/dist/collection/components/bs-radio/bs-radio.css +7 -1
- package/dist/collection/components/bs-radio/bs-radio.js +92 -14
- package/dist/collection/components/bs-radio/bs-radio.stories.js +1 -10
- package/dist/collection/components/bs-slider/bs-slider.js +68 -2
- package/dist/collection/components/bs-source-link/bs-source-link.css +2 -2
- package/dist/collection/components/bs-stepper/bs-stepper/bs-stepper.js +3 -2
- package/dist/collection/components/bs-stepper/bs-stepper-step/bs-stepper-step.css +3 -3
- package/dist/collection/components/bs-switch/bs-switch.css +10 -1
- package/dist/collection/components/bs-switch/bs-switch.js +69 -2
- package/dist/collection/components/bs-tab/bs-inline-tab/bs-inline-tab.css +2 -2
- package/dist/collection/components/bs-tab/bs-inline-tab/bs-inline-tab.js +47 -1
- package/dist/collection/components/bs-tab/bs-tab/bs-tab.css +2 -2
- package/dist/collection/components/bs-tab/bs-tab/bs-tab.js +47 -1
- package/dist/collection/components/bs-tab/bs-tabs/bs-tabs.cmp.test.js +88 -0
- package/dist/collection/components/bs-tab/bs-tabs/bs-tabs.js +139 -2
- package/dist/collection/components/bs-tab/bs-tabs/bs-tabs.stories.js +24 -0
- package/dist/collection/components/bs-tooltip/bs-tooltip.js +1 -1
- package/dist/collection/components/forms/forms.stories.js +63 -0
- package/dist/collection/components/ui-shell/bs-navigation-drawer/bs-navigation-drawer/bs-navigation-drawer.cmp.test.js +173 -5
- package/dist/collection/components/ui-shell/bs-navigation-drawer/bs-navigation-drawer/bs-navigation-drawer.css +106 -34
- package/dist/collection/components/ui-shell/bs-navigation-drawer/bs-navigation-drawer/bs-navigation-drawer.js +181 -5
- package/dist/collection/components/ui-shell/bs-navigation-drawer/bs-navigation-drawer/bs-navigation-drawer.stories.js +48 -0
- package/dist/collection/components/ui-shell/bs-navigation-drawer/bs-navigation-drawer-item/bs-navigation-drawer-item.js +1 -1
- package/dist/collection/components/ui-shell/bs-navigation-header/bs-navigation-header/bs-navigation-header.cmp.test.js +68 -0
- package/dist/collection/components/ui-shell/bs-navigation-header/bs-navigation-header/bs-navigation-header.css +31 -17
- package/dist/components/bs-accordion.js +1 -1
- package/dist/components/bs-ai-disclaimer.js +1 -1
- package/dist/components/bs-ai-greeting.js +1 -1
- package/dist/components/bs-ai-thinking.js +1 -1
- package/dist/components/bs-attachment-list.js +1 -1
- package/dist/components/bs-attachment.js +1 -1
- package/dist/components/bs-avatar.js +1 -1
- package/dist/components/bs-badge.js +1 -1
- package/dist/components/bs-breadcrumb-overflow.js +1 -1
- package/dist/components/bs-breadcrumb.js +1 -1
- package/dist/components/bs-breadcrumbs.js +1 -1
- package/dist/components/bs-button-skeleton.js +1 -1
- package/dist/components/bs-button.js +1 -1
- package/dist/components/bs-card.js +1 -1
- package/dist/components/bs-carousel.js +1 -1
- package/dist/components/bs-chatbot-feedback.js +1 -1
- package/dist/components/bs-chatbot-header.js +1 -1
- package/dist/components/bs-chatbot-response-action.js +1 -1
- package/dist/components/bs-chatbot-sources-drawer.js +1 -1
- package/dist/components/bs-chatbot-suggestion-button.js +1 -1
- package/dist/components/bs-checkbox-skeleton.js +1 -1
- package/dist/components/bs-checkbox.js +1 -1
- package/dist/components/bs-chip-filter.js +1 -1
- package/dist/components/bs-chip-informative.js +1 -1
- package/dist/components/bs-chip-input.js +1 -1
- package/dist/components/bs-composer-status-banner.js +1 -1
- package/dist/components/bs-composer.js +1 -1
- package/dist/components/bs-data-table.js +1 -1
- package/dist/components/bs-dialog.js +1 -1
- package/dist/components/bs-file-upload-item.js +1 -1
- package/dist/components/bs-file-upload.js +1 -1
- package/dist/components/bs-icon-button.js +1 -1
- package/dist/components/bs-inline-tab.js +1 -1
- package/dist/components/bs-input.js +1 -1
- package/dist/components/bs-logo.js +1 -1
- package/dist/components/bs-menu-item.js +1 -1
- package/dist/components/bs-menu.js +1 -1
- package/dist/components/bs-navigation-drawer-item.js +1 -1
- package/dist/components/bs-navigation-drawer.js +1 -1
- package/dist/components/bs-navigation-header.js +1 -1
- package/dist/components/bs-pagination.js +1 -1
- package/dist/components/bs-progress-linear.js +1 -1
- package/dist/components/bs-progress.js +1 -1
- package/dist/components/bs-radio.js +1 -1
- package/dist/components/bs-slider.js +1 -1
- package/dist/components/bs-snackbar.js +1 -1
- package/dist/components/bs-source-link.js +1 -1
- package/dist/components/bs-stepper-step.js +1 -1
- package/dist/components/bs-stepper.js +1 -1
- package/dist/components/bs-switch.js +1 -1
- package/dist/components/bs-tab.js +1 -1
- package/dist/components/bs-tabs.js +1 -1
- package/dist/components/bs-toast.js +1 -1
- package/dist/components/bs-tooltip.js +1 -1
- package/dist/components/index.js +1 -1
- package/dist/components/{p-LYvoWZt4.js → p-BA3c9Rom.js} +1 -1
- package/dist/components/{p-Dqt-Qp4W.js → p-BfEyD6Ku.js} +1 -1
- package/dist/components/p-BoeorHNv.js +1 -0
- package/dist/components/p-Buly0d5G.js +1 -0
- package/dist/components/p-CpUHnsq9.js +1 -0
- package/dist/components/{p-BxFJ74fI.js → p-EtXc94lJ.js} +1 -1
- package/dist/components/{p-mnGJPH85.js → p-JYlmcxBn.js} +1 -1
- package/dist/components/{p-BhvV55-6.js → p-R2MlkUzD.js} +1 -1
- package/dist/components/{p-Dx8gAOVC.js → p-wei0Ija2.js} +1 -1
- package/dist/esm/brandsync-wc.js +3 -3
- package/dist/esm/bs-accordion.entry.js +2 -2
- package/dist/esm/bs-ai-disclaimer.entry.js +1 -1
- package/dist/esm/bs-ai-greeting.entry.js +1 -1
- package/dist/esm/bs-ai-thinking.entry.js +1 -1
- package/dist/esm/bs-attachment-list.entry.js +2 -2
- package/dist/esm/bs-attachment.entry.js +2 -2
- package/dist/esm/bs-avatar.entry.js +1 -1
- package/dist/esm/bs-badge.entry.js +1 -1
- package/dist/esm/bs-breadcrumb-overflow.entry.js +15 -3
- package/dist/esm/bs-breadcrumb.entry.js +16 -2
- package/dist/esm/bs-breadcrumbs.entry.js +1 -1
- package/dist/esm/bs-button-skeleton.entry.js +1 -1
- package/dist/esm/bs-button.entry.js +23 -4
- package/dist/esm/bs-card.entry.js +2 -2
- package/dist/esm/bs-carousel.entry.js +1 -1
- package/dist/esm/bs-chatbot-feedback.entry.js +2 -2
- package/dist/esm/bs-chatbot-header.entry.js +1 -1
- package/dist/esm/bs-chatbot-response-action.entry.js +2 -2
- package/dist/esm/bs-chatbot-sources-drawer.entry.js +1 -1
- package/dist/esm/bs-chatbot-suggestion-button.entry.js +1 -1
- package/dist/esm/bs-checkbox-skeleton.entry.js +1 -1
- package/dist/esm/bs-checkbox.entry.js +48 -3
- package/dist/esm/bs-chip-filter.entry.js +2 -2
- package/dist/esm/bs-chip-informative.entry.js +2 -2
- package/dist/esm/bs-chip-input.entry.js +2 -2
- package/dist/esm/bs-composer-status-banner.entry.js +1 -1
- package/dist/esm/bs-composer.entry.js +1 -1
- package/dist/esm/bs-data-table.entry.js +20 -6
- package/dist/esm/bs-dialog.entry.js +2 -2
- package/dist/esm/bs-file-upload-item.entry.js +1 -1
- package/dist/esm/bs-file-upload.entry.js +1 -1
- package/dist/esm/bs-icon-button.entry.js +23 -4
- package/dist/esm/bs-inline-tab.entry.js +11 -3
- package/dist/esm/bs-input.entry.js +69 -5
- package/dist/esm/bs-logo.entry.js +1 -1
- package/dist/esm/bs-menu-item.entry.js +1 -1
- package/dist/esm/bs-menu.entry.js +25 -3
- package/dist/esm/bs-navigation-drawer-item.entry.js +2 -2
- package/dist/esm/bs-navigation-drawer.entry.js +119 -6
- package/dist/esm/bs-navigation-header.entry.js +2 -2
- package/dist/esm/bs-pagination.entry.js +1 -1
- package/dist/esm/bs-progress-linear.entry.js +1 -1
- package/dist/esm/bs-progress.entry.js +8 -3
- package/dist/esm/bs-radio.entry.js +81 -12
- package/dist/esm/bs-slider.entry.js +54 -2
- package/dist/esm/bs-snackbar.entry.js +1 -1
- package/dist/esm/bs-source-link.entry.js +2 -2
- package/dist/esm/bs-stepper-step.entry.js +2 -2
- package/dist/esm/bs-stepper.entry.js +3 -2
- package/dist/esm/bs-switch.entry.js +36 -3
- package/dist/esm/bs-tab.entry.js +11 -3
- package/dist/esm/bs-tabs.entry.js +97 -3
- package/dist/esm/bs-toast.entry.js +1 -1
- package/dist/esm/bs-tooltip.entry.js +2 -2
- package/dist/esm/{index-DuyFft7h.js → index-AgoOSYvW.js} +43 -5
- package/dist/esm/loader.js +3 -3
- package/dist/types/components/bs-a11y.cmp.test.d.ts +1 -0
- package/dist/types/components/bs-breadcrumb/bs-breadcrumb/bs-breadcrumb.d.ts +10 -0
- package/dist/types/components/bs-breadcrumb/bs-breadcrumb-overflow/bs-breadcrumb-overflow.d.ts +8 -0
- package/dist/types/components/bs-button/bs-button/bs-button.d.ts +4 -1
- package/dist/types/components/bs-button/bs-icon-button/bs-icon-button.d.ts +6 -2
- package/dist/types/components/bs-button/bs-icon-button/bs-icon-button.stories.d.ts +1 -0
- package/dist/types/components/bs-checkbox/bs-checkbox.d.ts +12 -0
- package/dist/types/components/bs-data-table/bs-data-table.d.ts +16 -2
- package/dist/types/components/bs-form-association.cmp.test.d.ts +1 -0
- package/dist/types/components/bs-input/bs-input.d.ts +12 -0
- package/dist/types/components/bs-keyboard-nav.cmp.test.d.ts +1 -0
- package/dist/types/components/bs-menu/bs-menu.d.ts +4 -0
- package/dist/types/components/bs-menu/bs-menu.stories.d.ts +1 -0
- package/dist/types/components/bs-progress/bs-progress.d.ts +5 -0
- package/dist/types/components/bs-radio/bs-radio.d.ts +23 -9
- package/dist/types/components/bs-slider/bs-slider.d.ts +9 -0
- package/dist/types/components/bs-switch/bs-switch.d.ts +10 -0
- package/dist/types/components/bs-tab/bs-inline-tab/bs-inline-tab.d.ts +8 -0
- package/dist/types/components/bs-tab/bs-tab/bs-tab.d.ts +8 -0
- package/dist/types/components/bs-tab/bs-tabs/bs-tabs.d.ts +24 -0
- package/dist/types/components/bs-tab/bs-tabs/bs-tabs.stories.d.ts +1 -0
- package/dist/types/components/forms/forms.stories.d.ts +6 -0
- package/dist/types/components/ui-shell/bs-navigation-drawer/bs-navigation-drawer/bs-navigation-drawer.d.ts +50 -1
- package/dist/types/components/ui-shell/bs-navigation-drawer/bs-navigation-drawer/bs-navigation-drawer.stories.d.ts +2 -0
- package/dist/types/components.d.ts +271 -9
- package/package.json +1 -1
- package/readme.md +14 -0
- package/dist/brandsync-wc/p-18021c05.entry.js +0 -1
- package/dist/brandsync-wc/p-1c8160c2.entry.js +0 -1
- package/dist/brandsync-wc/p-21c14465.entry.js +0 -1
- package/dist/brandsync-wc/p-27100489.entry.js +0 -1
- package/dist/brandsync-wc/p-309f920e.entry.js +0 -1
- package/dist/brandsync-wc/p-30d6a6d0.entry.js +0 -1
- package/dist/brandsync-wc/p-387ed85f.entry.js +0 -1
- package/dist/brandsync-wc/p-4b0938a5.entry.js +0 -1
- package/dist/brandsync-wc/p-5312b6a5.entry.js +0 -1
- package/dist/brandsync-wc/p-70e035ed.entry.js +0 -1
- package/dist/brandsync-wc/p-777a9dbf.entry.js +0 -1
- package/dist/brandsync-wc/p-a96856fd.entry.js +0 -1
- package/dist/brandsync-wc/p-b0634051.entry.js +0 -1
- package/dist/brandsync-wc/p-bcee3d60.entry.js +0 -1
- package/dist/brandsync-wc/p-d03eba2b.entry.js +0 -1
- package/dist/brandsync-wc/p-e61efe4d.entry.js +0 -1
- package/dist/brandsync-wc/p-f14bda01.entry.js +0 -1
- package/dist/components/p-BaxFLlKS.js +0 -1
- package/dist/components/p-DI5GgSqL.js +0 -1
- package/dist/components/p-v4T0qPVn.js +0 -1
|
@@ -70,7 +70,7 @@
|
|
|
70
70
|
.bs-dialog__close--floating {
|
|
71
71
|
position: absolute;
|
|
72
72
|
top: var(--bs-spacing-200);
|
|
73
|
-
|
|
73
|
+
inset-inline-end: var(--bs-spacing-200);
|
|
74
74
|
z-index: 1;
|
|
75
75
|
}
|
|
76
76
|
|
|
@@ -128,3 +128,7 @@
|
|
|
128
128
|
justify-content: center;
|
|
129
129
|
text-align: center;
|
|
130
130
|
}
|
|
131
|
+
|
|
132
|
+
@media (forced-colors: active) {
|
|
133
|
+
.bs-dialog__dialog { border: 1px solid CanvasText; }
|
|
134
|
+
}
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
import { render, h, describe, it, expect } from "@stencil/vitest";
|
|
2
|
+
// Cross-component coverage for native <form> participation (FormData, validation, reset) and the
|
|
3
|
+
// radio group keyboard pattern. Lives beside the components, not in one of them, since it exercises
|
|
4
|
+
// several together inside a real <form>.
|
|
5
|
+
async function renderForm(children) {
|
|
6
|
+
const { root, waitForChanges } = await render(h("form", null, children));
|
|
7
|
+
return { form: root, waitForChanges };
|
|
8
|
+
}
|
|
9
|
+
describe('form association', () => {
|
|
10
|
+
it('bs-input submits its value under name', async () => {
|
|
11
|
+
const { form, waitForChanges } = await renderForm(h("bs-input", { name: "email", value: "a@b.co" }));
|
|
12
|
+
await waitForChanges();
|
|
13
|
+
expect(new FormData(form).get('email')).toBe('a@b.co');
|
|
14
|
+
});
|
|
15
|
+
it('bs-input updates FormData as the user types, and resets with the form', async () => {
|
|
16
|
+
const { form, waitForChanges } = await renderForm(h("bs-input", { name: "q", value: "start" }));
|
|
17
|
+
const input = form.querySelector('bs-input').shadowRoot.querySelector('input');
|
|
18
|
+
input.value = 'typed';
|
|
19
|
+
input.dispatchEvent(new InputEvent('input', { bubbles: true, composed: true }));
|
|
20
|
+
await waitForChanges();
|
|
21
|
+
expect(new FormData(form).get('q')).toBe('typed');
|
|
22
|
+
form.reset();
|
|
23
|
+
await waitForChanges();
|
|
24
|
+
expect(new FormData(form).get('q')).toBe('start');
|
|
25
|
+
});
|
|
26
|
+
it('a required, empty bs-input makes the form invalid', async () => {
|
|
27
|
+
const { form, waitForChanges } = await renderForm(h("bs-input", { name: "n", required: true }));
|
|
28
|
+
await waitForChanges();
|
|
29
|
+
expect(form.checkValidity()).toBe(false);
|
|
30
|
+
});
|
|
31
|
+
it('bs-checkbox and bs-switch submit only while checked', async () => {
|
|
32
|
+
const { form, waitForChanges } = await renderForm(h("div", null, h("bs-checkbox", { name: "terms", value: "yes" }), h("bs-switch", { name: "alerts", checked: true })));
|
|
33
|
+
await waitForChanges();
|
|
34
|
+
expect(new FormData(form).get('terms')).toBeNull();
|
|
35
|
+
expect(new FormData(form).get('alerts')).toBe('on');
|
|
36
|
+
form.querySelector('bs-checkbox').shadowRoot.querySelector('input').click();
|
|
37
|
+
await waitForChanges();
|
|
38
|
+
expect(new FormData(form).get('terms')).toBe('yes');
|
|
39
|
+
form.reset();
|
|
40
|
+
await waitForChanges();
|
|
41
|
+
expect(new FormData(form).get('terms')).toBeNull();
|
|
42
|
+
});
|
|
43
|
+
it('a required, unchecked bs-checkbox makes the form invalid', async () => {
|
|
44
|
+
const { form, waitForChanges } = await renderForm(h("bs-checkbox", { name: "t", required: true }));
|
|
45
|
+
await waitForChanges();
|
|
46
|
+
expect(form.checkValidity()).toBe(false);
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
describe('bs-radio group', () => {
|
|
50
|
+
const group = () => (h("div", null, h("bs-radio", { name: "fruit", value: "a" }), h("bs-radio", { name: "fruit", value: "b" }), h("bs-radio", { name: "fruit", value: "c", disabled: true })));
|
|
51
|
+
const inputOf = (r) => r.shadowRoot.querySelector('input');
|
|
52
|
+
it('checking one unchecks the others and submits its value', async () => {
|
|
53
|
+
const { form, waitForChanges } = await renderForm(group());
|
|
54
|
+
const [a, b] = Array.from(form.querySelectorAll('bs-radio'));
|
|
55
|
+
inputOf(a).click();
|
|
56
|
+
await waitForChanges();
|
|
57
|
+
inputOf(b).click();
|
|
58
|
+
await waitForChanges();
|
|
59
|
+
expect(a.checked).toBe(false);
|
|
60
|
+
expect(b.checked).toBe(true);
|
|
61
|
+
expect(new FormData(form).get('fruit')).toBe('b');
|
|
62
|
+
});
|
|
63
|
+
it('arrow keys move selection to the next enabled radio, wrapping', async () => {
|
|
64
|
+
const { form, waitForChanges } = await renderForm(group());
|
|
65
|
+
const [a, b] = Array.from(form.querySelectorAll('bs-radio'));
|
|
66
|
+
inputOf(a).click();
|
|
67
|
+
await waitForChanges();
|
|
68
|
+
inputOf(a).dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowDown', bubbles: true, composed: true, cancelable: true }));
|
|
69
|
+
await waitForChanges();
|
|
70
|
+
expect(b.checked).toBe(true);
|
|
71
|
+
inputOf(b).dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowRight', bubbles: true, composed: true, cancelable: true }));
|
|
72
|
+
await waitForChanges();
|
|
73
|
+
expect(a.checked).toBe(true); // skipped the disabled third radio and wrapped
|
|
74
|
+
});
|
|
75
|
+
it('only the checked radio is in the tab order once the group has a selection', async () => {
|
|
76
|
+
const { form, waitForChanges } = await renderForm(group());
|
|
77
|
+
const [a, b] = Array.from(form.querySelectorAll('bs-radio'));
|
|
78
|
+
inputOf(a).click();
|
|
79
|
+
await waitForChanges();
|
|
80
|
+
expect(inputOf(a).tabIndex).toBe(0);
|
|
81
|
+
expect(inputOf(b).tabIndex).toBe(-1);
|
|
82
|
+
});
|
|
83
|
+
});
|
|
84
|
+
describe('bs-button / bs-icon-button inside a form', () => {
|
|
85
|
+
const click = (el) => el.shadowRoot.querySelector('button').click();
|
|
86
|
+
it('type="submit" submits the surrounding form (and runs validation first)', async () => {
|
|
87
|
+
let submits = 0;
|
|
88
|
+
const { root, waitForChanges } = await render(h("form", { onSubmit: (e) => { e.preventDefault(); submits++; } }, h("bs-input", { name: "n", required: true }), h("bs-button", { type: "submit" }, "Go"), h("bs-icon-button", { type: "submit", ariaLabel: "Go" }, "x")));
|
|
89
|
+
const form = root;
|
|
90
|
+
await waitForChanges();
|
|
91
|
+
click(form.querySelector('bs-button'));
|
|
92
|
+
click(form.querySelector('bs-icon-button'));
|
|
93
|
+
expect(submits).toBe(0); // required field empty -> blocked by validation
|
|
94
|
+
form.querySelector('bs-input').value = 'x';
|
|
95
|
+
await waitForChanges();
|
|
96
|
+
click(form.querySelector('bs-button'));
|
|
97
|
+
click(form.querySelector('bs-icon-button'));
|
|
98
|
+
expect(submits).toBe(2);
|
|
99
|
+
});
|
|
100
|
+
it('type="reset" resets the form; type="button" does neither', async () => {
|
|
101
|
+
let submits = 0;
|
|
102
|
+
const { root, waitForChanges } = await render(h("form", { onSubmit: (e) => { e.preventDefault(); submits++; } }, h("bs-input", { name: "q", value: "start" }), h("bs-button", { type: "reset" }, "Reset"), h("bs-button", null, "Plain")));
|
|
103
|
+
const form = root;
|
|
104
|
+
await waitForChanges();
|
|
105
|
+
form.querySelector('bs-input').value = 'changed';
|
|
106
|
+
await waitForChanges();
|
|
107
|
+
click(form.querySelectorAll('bs-button')[1]);
|
|
108
|
+
expect(submits).toBe(0);
|
|
109
|
+
expect(new FormData(form).get('q')).toBe('changed');
|
|
110
|
+
click(form.querySelectorAll('bs-button')[0]);
|
|
111
|
+
await waitForChanges();
|
|
112
|
+
expect(new FormData(form).get('q')).toBe('start');
|
|
113
|
+
});
|
|
114
|
+
});
|
|
115
|
+
// The Angular ControlValueAccessors and Vue v-model bindings (generated in stencil.config.ts) read
|
|
116
|
+
// `event.target.value` / `.checked` straight off the host inside the `bsChange` handler. That only
|
|
117
|
+
// works if the host property is already updated when `bsChange` fires -- pin that contract here.
|
|
118
|
+
describe('bsChange framework-binding contract', () => {
|
|
119
|
+
it('bs-input: host.value is already the new value inside bsChange', async () => {
|
|
120
|
+
const { root, waitForChanges } = await render(h("bs-input", null));
|
|
121
|
+
const seen = [];
|
|
122
|
+
root.addEventListener('bsChange', (e) => seen.push(e.target.value));
|
|
123
|
+
const input = root.shadowRoot.querySelector('input');
|
|
124
|
+
input.value = 'hello';
|
|
125
|
+
input.dispatchEvent(new Event('change', { bubbles: true }));
|
|
126
|
+
await waitForChanges();
|
|
127
|
+
expect(seen).toEqual(['hello']);
|
|
128
|
+
});
|
|
129
|
+
it('bs-checkbox and bs-switch: host.checked is already updated inside bsChange', async () => {
|
|
130
|
+
const { root, waitForChanges } = await render(h("div", null, h("bs-checkbox", null), h("bs-switch", null)));
|
|
131
|
+
const seen = [];
|
|
132
|
+
root.addEventListener('bsChange', (e) => seen.push(e.target.checked));
|
|
133
|
+
root.querySelector('bs-checkbox').shadowRoot.querySelector('input').click();
|
|
134
|
+
root.querySelector('bs-switch').shadowRoot.querySelector('input').click();
|
|
135
|
+
await waitForChanges();
|
|
136
|
+
expect(seen).toEqual([true, true]);
|
|
137
|
+
});
|
|
138
|
+
it('bs-slider: host.value is already updated inside bsChange', async () => {
|
|
139
|
+
const { root, waitForChanges } = await render(h("bs-slider", { value: 10 }));
|
|
140
|
+
const seen = [];
|
|
141
|
+
root.addEventListener('bsChange', (e) => seen.push(e.target.value));
|
|
142
|
+
const range = root.shadowRoot.querySelector('input[type="range"]');
|
|
143
|
+
range.value = '55';
|
|
144
|
+
range.dispatchEvent(new Event('input', { bubbles: true }));
|
|
145
|
+
range.dispatchEvent(new Event('change', { bubbles: true }));
|
|
146
|
+
await waitForChanges();
|
|
147
|
+
expect(seen.length).toBeGreaterThan(0);
|
|
148
|
+
expect(seen[seen.length - 1]).toBe(55);
|
|
149
|
+
});
|
|
150
|
+
});
|
|
151
|
+
const keysOf = (f) => {
|
|
152
|
+
const keys = [];
|
|
153
|
+
new FormData(f).forEach((_v, k) => keys.push(k));
|
|
154
|
+
return keys;
|
|
155
|
+
};
|
|
156
|
+
describe('disabled controls', () => {
|
|
157
|
+
it('a disabled control is excluded from FormData and validation, like a native disabled input', async () => {
|
|
158
|
+
const { root, waitForChanges } = await render(h("form", null, h("bs-input", { name: "i", value: "x", required: true, disabled: true }), h("bs-checkbox", { name: "c", checked: true, disabled: true }), h("bs-switch", { name: "s", checked: true, disabled: true }), h("bs-radio", { name: "r", value: "a", checked: true, disabled: true }), h("bs-slider", { name: "v", value: 20, disabled: true })));
|
|
159
|
+
const form = root;
|
|
160
|
+
await waitForChanges();
|
|
161
|
+
expect(keysOf(form)).toEqual([]);
|
|
162
|
+
expect(form.checkValidity()).toBe(true);
|
|
163
|
+
Array.from(form.querySelectorAll('bs-input, bs-checkbox, bs-switch, bs-radio, bs-slider')).forEach(el => (el.disabled = false));
|
|
164
|
+
await waitForChanges();
|
|
165
|
+
expect(keysOf(form).sort()).toEqual(['c', 'i', 'r', 's', 'v']);
|
|
166
|
+
});
|
|
167
|
+
it('a control inside <fieldset disabled> is excluded from FormData', async () => {
|
|
168
|
+
const { root, waitForChanges } = await render(h("form", null, h("fieldset", { disabled: true }, h("bs-input", { name: "fs", value: "x" }))));
|
|
169
|
+
await waitForChanges();
|
|
170
|
+
expect(keysOf(root)).toEqual([]);
|
|
171
|
+
});
|
|
172
|
+
});
|
|
@@ -84,7 +84,7 @@
|
|
|
84
84
|
|
|
85
85
|
.bs-input__required {
|
|
86
86
|
color: var(--bs-input-error-color);
|
|
87
|
-
margin-
|
|
87
|
+
margin-inline-start: 2px;
|
|
88
88
|
}
|
|
89
89
|
|
|
90
90
|
.bs-input__field {
|
|
@@ -148,7 +148,7 @@
|
|
|
148
148
|
visibility: hidden;
|
|
149
149
|
pointer-events: none;
|
|
150
150
|
position: absolute;
|
|
151
|
-
|
|
151
|
+
inset-inline-end: 0;
|
|
152
152
|
}
|
|
153
153
|
|
|
154
154
|
.bs-input__control::-webkit-textfield-decoration-container {
|
|
@@ -282,8 +282,8 @@
|
|
|
282
282
|
.bs-input__dropdown-menu {
|
|
283
283
|
position: absolute;
|
|
284
284
|
top: calc(100% + var(--bs-input-stack-gap));
|
|
285
|
-
|
|
286
|
-
|
|
285
|
+
inset-inline-start: 0;
|
|
286
|
+
inset-inline-end: 0;
|
|
287
287
|
z-index: 1;
|
|
288
288
|
}
|
|
289
289
|
|
|
@@ -450,3 +450,9 @@
|
|
|
450
450
|
.bs-input__field--pin.bs-input__field--error .bs-input__pin-cell {
|
|
451
451
|
border-color: var(--bs-input-field-border-error);
|
|
452
452
|
}
|
|
453
|
+
|
|
454
|
+
/* Windows High Contrast: keep the field boundary visible. */
|
|
455
|
+
@media (forced-colors: active) {
|
|
456
|
+
.bs-input__control { border: 1px solid FieldText; }
|
|
457
|
+
.bs-input__control:focus-visible { outline: 2px solid Highlight; outline-offset: 2px; }
|
|
458
|
+
}
|
|
@@ -49,6 +49,10 @@ import { h } from "@stencil/core";
|
|
|
49
49
|
// comments (see stencil.js's parseStyleDocs/parseCssComment), not the class-level JSDoc.
|
|
50
50
|
export class BsInput {
|
|
51
51
|
el;
|
|
52
|
+
internals;
|
|
53
|
+
initialValue = '';
|
|
54
|
+
/** The `name` the value is submitted under in a surrounding `<form>`'s `FormData`. */
|
|
55
|
+
name;
|
|
52
56
|
/** Current value. Native `input`/`change` events don't cross the Shadow DOM boundary, so this
|
|
53
57
|
* component re-dispatches them as `bsInput`/`bsChange` custom events instead. Mutable so the
|
|
54
58
|
* `number` type's stepper buttons can update it directly. */
|
|
@@ -124,9 +128,44 @@ export class BsInput {
|
|
|
124
128
|
* children, before first render -- see `bs-button`'s `componentWillLoad` for why `slotchange`
|
|
125
129
|
* alone isn't enough for a slot that starts (and stays) empty. */
|
|
126
130
|
componentWillLoad() {
|
|
131
|
+
this.initialValue = this.value;
|
|
132
|
+
this.syncFormValue();
|
|
127
133
|
this.hasIcon = this.hasSlottedContent('icon');
|
|
128
134
|
this.hasEndIcon = this.hasSlottedContent('end-icon');
|
|
129
135
|
}
|
|
136
|
+
onFormStateChange() {
|
|
137
|
+
this.syncFormValue();
|
|
138
|
+
}
|
|
139
|
+
/** Pushes the current value + validity to the surrounding form. `chip` submits one entry per
|
|
140
|
+
* chip under `name`; every other type submits `value` as a single string. */
|
|
141
|
+
syncFormValue() {
|
|
142
|
+
if (!this.internals?.setFormValue)
|
|
143
|
+
return;
|
|
144
|
+
if (this.type === 'chip' && this.name) {
|
|
145
|
+
const data = new FormData();
|
|
146
|
+
this.chips.forEach(c => data.append(this.name, c));
|
|
147
|
+
this.internals.setFormValue(data);
|
|
148
|
+
}
|
|
149
|
+
else {
|
|
150
|
+
this.internals.setFormValue(this.value ?? '');
|
|
151
|
+
}
|
|
152
|
+
const empty = this.type === 'chip' ? this.chips.length === 0 : !this.value;
|
|
153
|
+
if (this.required && empty) {
|
|
154
|
+
this.internals.setValidity({ valueMissing: true }, 'Please fill out this field.');
|
|
155
|
+
}
|
|
156
|
+
else {
|
|
157
|
+
this.internals.setValidity({});
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
/** Called by the browser when the surrounding `<form>` is reset. */
|
|
161
|
+
formResetCallback() {
|
|
162
|
+
this.value = this.initialValue;
|
|
163
|
+
}
|
|
164
|
+
/** Called when the browser restores form state (back/forward navigation, autofill). */
|
|
165
|
+
formStateRestoreCallback(state) {
|
|
166
|
+
if (typeof state === 'string')
|
|
167
|
+
this.value = state;
|
|
168
|
+
}
|
|
130
169
|
hasSlottedContent(slotName) {
|
|
131
170
|
return Array.from(this.el.childNodes).some(node => node.nodeType === Node.ELEMENT_NODE && node.getAttribute('slot') === slotName);
|
|
132
171
|
}
|
|
@@ -138,10 +177,12 @@ export class BsInput {
|
|
|
138
177
|
};
|
|
139
178
|
onInput = (ev) => {
|
|
140
179
|
const value = ev.target.value;
|
|
180
|
+
this.value = value;
|
|
141
181
|
this.bsInput.emit(value);
|
|
142
182
|
};
|
|
143
183
|
onChange = (ev) => {
|
|
144
184
|
const value = ev.target.value;
|
|
185
|
+
this.value = value;
|
|
145
186
|
this.bsChange.emit(value);
|
|
146
187
|
};
|
|
147
188
|
clampNumber(n) {
|
|
@@ -236,7 +277,8 @@ export class BsInput {
|
|
|
236
277
|
if (value && index < this.length - 1) {
|
|
237
278
|
this.pinInputs[index + 1]?.focus();
|
|
238
279
|
}
|
|
239
|
-
this.
|
|
280
|
+
this.value = this.pinInputs.map(i => i?.value ?? '').join('');
|
|
281
|
+
this.bsChange.emit(this.value);
|
|
240
282
|
};
|
|
241
283
|
onPinKeydown = (index) => (ev) => {
|
|
242
284
|
if (ev.key === 'Backspace' && !ev.target.value && index > 0) {
|
|
@@ -341,14 +383,15 @@ export class BsInput {
|
|
|
341
383
|
return (h("div", { part: "field", class: `bs-input__field bs-input__field--pin ${errorClass} ${disabledClass}` }, Array.from({ length: this.length }).map((_, i) => (h("input", { id: i === 0 ? 'control' : undefined, ref: el => (this.pinInputs[i] = el), part: "control", class: "bs-input__pin-cell", type: "text", inputMode: "numeric", maxLength: 1, value: this.value[i] ?? '', disabled: this.disabled, "aria-required": this.required ? 'true' : undefined, onInput: this.onPinInput(i), onKeyDown: this.onPinKeydown(i) })))));
|
|
342
384
|
}
|
|
343
385
|
render() {
|
|
344
|
-
return (h("div", { key: '
|
|
386
|
+
return (h("div", { key: '1149cfe8eaa6085007a8d9a963b6c909bb6cda13', class: `bs-input ${this.error ? 'bs-input--error' : ''}` }, this.label && (
|
|
345
387
|
// "control" is a fixed id, not a generated one -- safe because Shadow DOM scopes ids
|
|
346
388
|
// to this instance's own shadow root, so it can never collide with another bs-input.
|
|
347
|
-
h("label", { key: '
|
|
389
|
+
h("label", { key: 'd737018c1e1ebcde529710d8ea58c6bed76f2abf', part: "label", class: "bs-input__label", htmlFor: "control" }, this.label, this.required && (h("span", { key: '5993b19cbfcb8725550c1292c00795c8463e554c', part: "required", class: "bs-input__required", "aria-hidden": "true" }, "*")))), this.type === 'pin' ? this.renderPinField() : this.type === 'initials' ? this.renderInitialsField() : this.renderField(), this.error ? (h("span", { id: "description-or-error", part: "error", class: "bs-input__error" }, h("svg", { part: "error-icon", class: "bs-input__error-icon", viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true" }, h("circle", { cx: "8", cy: "8", r: "6.5", stroke: "currentColor", "stroke-width": "1.2" }), h("path", { d: "M8 5V8.5", stroke: "currentColor", "stroke-width": "1.2", "stroke-linecap": "round" }), h("circle", { cx: "8", cy: "11", r: "0.75", fill: "currentColor" })), this.error)) : this.description ? (h("span", { id: "description-or-error", part: "description", class: "bs-input__description" }, this.description)) : null));
|
|
348
390
|
}
|
|
349
391
|
static get is() { return "bs-input"; }
|
|
350
392
|
static get encapsulation() { return "shadow"; }
|
|
351
393
|
static get delegatesFocus() { return true; }
|
|
394
|
+
static get formAssociated() { return true; }
|
|
352
395
|
static get originalStyleUrls() {
|
|
353
396
|
return {
|
|
354
397
|
"$": ["bs-input.css"]
|
|
@@ -361,6 +404,25 @@ export class BsInput {
|
|
|
361
404
|
}
|
|
362
405
|
static get properties() {
|
|
363
406
|
return {
|
|
407
|
+
"name": {
|
|
408
|
+
"type": "string",
|
|
409
|
+
"mutable": false,
|
|
410
|
+
"complexType": {
|
|
411
|
+
"original": "string",
|
|
412
|
+
"resolved": "string",
|
|
413
|
+
"references": {}
|
|
414
|
+
},
|
|
415
|
+
"required": false,
|
|
416
|
+
"optional": true,
|
|
417
|
+
"docs": {
|
|
418
|
+
"tags": [],
|
|
419
|
+
"text": "The `name` the value is submitted under in a surrounding `<form>`'s `FormData`."
|
|
420
|
+
},
|
|
421
|
+
"getter": false,
|
|
422
|
+
"setter": false,
|
|
423
|
+
"reflect": true,
|
|
424
|
+
"attribute": "name"
|
|
425
|
+
},
|
|
364
426
|
"value": {
|
|
365
427
|
"type": "string",
|
|
366
428
|
"mutable": true,
|
|
@@ -493,7 +555,7 @@ export class BsInput {
|
|
|
493
555
|
},
|
|
494
556
|
"getter": false,
|
|
495
557
|
"setter": false,
|
|
496
|
-
"reflect":
|
|
558
|
+
"reflect": true,
|
|
497
559
|
"attribute": "disabled",
|
|
498
560
|
"defaultValue": "false"
|
|
499
561
|
},
|
|
@@ -866,6 +928,21 @@ export class BsInput {
|
|
|
866
928
|
}];
|
|
867
929
|
}
|
|
868
930
|
static get elementRef() { return "el"; }
|
|
931
|
+
static get watchers() {
|
|
932
|
+
return [{
|
|
933
|
+
"propName": "value",
|
|
934
|
+
"methodName": "onFormStateChange"
|
|
935
|
+
}, {
|
|
936
|
+
"propName": "type",
|
|
937
|
+
"methodName": "onFormStateChange"
|
|
938
|
+
}, {
|
|
939
|
+
"propName": "chips",
|
|
940
|
+
"methodName": "onFormStateChange"
|
|
941
|
+
}, {
|
|
942
|
+
"propName": "required",
|
|
943
|
+
"methodName": "onFormStateChange"
|
|
944
|
+
}];
|
|
945
|
+
}
|
|
869
946
|
static get listeners() {
|
|
870
947
|
return [{
|
|
871
948
|
"name": "keydown",
|
|
@@ -881,4 +958,5 @@ export class BsInput {
|
|
|
881
958
|
"passive": false
|
|
882
959
|
}];
|
|
883
960
|
}
|
|
961
|
+
static get attachInternalsMemberName() { return "internals"; }
|
|
884
962
|
}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { render, h, describe, it, expect } from "@stencil/vitest";
|
|
2
|
+
// Cross-component coverage for WAI-ARIA keyboard patterns (tabs, menu) and slider form submission.
|
|
3
|
+
const key = (el, k) => el.dispatchEvent(new KeyboardEvent('keydown', { key: k, bubbles: true, composed: true, cancelable: true }));
|
|
4
|
+
const btn = (el) => el.shadowRoot.querySelector('button');
|
|
5
|
+
describe('bs-tabs keyboard', () => {
|
|
6
|
+
const tabs = (orientation = 'horizontal') => (h("bs-tabs", { orientation: orientation }, h("bs-tab", { selected: true }, "One"), h("bs-tab", null, "Two"), h("bs-tab", { disabled: true }, "Three"), h("bs-tab", null, "Four")));
|
|
7
|
+
it('roving tabindex: only the selected tab is tabbable', async () => {
|
|
8
|
+
const { root, waitForChanges } = await render(tabs());
|
|
9
|
+
await waitForChanges();
|
|
10
|
+
const [a, b] = Array.from(root.querySelectorAll('bs-tab'));
|
|
11
|
+
expect(btn(a).tabIndex).toBe(0);
|
|
12
|
+
expect(btn(b).tabIndex).toBe(-1);
|
|
13
|
+
});
|
|
14
|
+
it('ArrowRight selects the next enabled tab (skipping disabled) and wraps', async () => {
|
|
15
|
+
const { root, waitForChanges } = await render(tabs());
|
|
16
|
+
const els = Array.from(root.querySelectorAll('bs-tab'));
|
|
17
|
+
key(btn(els[0]), 'ArrowRight');
|
|
18
|
+
await waitForChanges();
|
|
19
|
+
expect(els[1].selected).toBe(true);
|
|
20
|
+
key(btn(els[1]), 'ArrowRight');
|
|
21
|
+
await waitForChanges();
|
|
22
|
+
expect(els[3].selected).toBe(true);
|
|
23
|
+
key(btn(els[3]), 'ArrowRight');
|
|
24
|
+
await waitForChanges();
|
|
25
|
+
expect(els[0].selected).toBe(true);
|
|
26
|
+
expect(btn(els[0]).tabIndex).toBe(0);
|
|
27
|
+
expect(btn(els[3]).tabIndex).toBe(-1);
|
|
28
|
+
});
|
|
29
|
+
it('Home/End jump to first/last enabled tab', async () => {
|
|
30
|
+
const { root, waitForChanges } = await render(tabs());
|
|
31
|
+
const els = Array.from(root.querySelectorAll('bs-tab'));
|
|
32
|
+
key(btn(els[0]), 'End');
|
|
33
|
+
await waitForChanges();
|
|
34
|
+
expect(els[3].selected).toBe(true);
|
|
35
|
+
key(btn(els[3]), 'Home');
|
|
36
|
+
await waitForChanges();
|
|
37
|
+
expect(els[0].selected).toBe(true);
|
|
38
|
+
});
|
|
39
|
+
it('vertical orientation uses Up/Down and ignores Left/Right', async () => {
|
|
40
|
+
const { root, waitForChanges } = await render(tabs('vertical'));
|
|
41
|
+
const els = Array.from(root.querySelectorAll('bs-tab'));
|
|
42
|
+
key(btn(els[0]), 'ArrowRight');
|
|
43
|
+
await waitForChanges();
|
|
44
|
+
expect(els[0].selected).toBe(true);
|
|
45
|
+
key(btn(els[0]), 'ArrowDown');
|
|
46
|
+
await waitForChanges();
|
|
47
|
+
expect(els[1].selected).toBe(true);
|
|
48
|
+
});
|
|
49
|
+
it('with nothing selected, the first enabled tab is the tab stop', async () => {
|
|
50
|
+
const { root, waitForChanges } = await render(h("bs-tabs", null, h("bs-tab", { disabled: true }, "A"), h("bs-tab", null, "B"), h("bs-tab", null, "C")));
|
|
51
|
+
await waitForChanges();
|
|
52
|
+
const els = Array.from(root.querySelectorAll('bs-tab'));
|
|
53
|
+
expect(btn(els[1]).tabIndex).toBe(0);
|
|
54
|
+
expect(btn(els[2]).tabIndex).toBe(-1);
|
|
55
|
+
});
|
|
56
|
+
});
|
|
57
|
+
describe('bs-menu keyboard', () => {
|
|
58
|
+
const menu = () => (h("bs-menu", null, h("bs-menu-item", null, "Edit"), h("bs-menu-item", { disabled: true }, "Copy"), h("bs-menu-item", null, "Delete")));
|
|
59
|
+
it('ArrowDown/ArrowUp move focus between enabled items, wrapping', async () => {
|
|
60
|
+
const { root, waitForChanges } = await render(menu());
|
|
61
|
+
const [a, , c] = Array.from(root.querySelectorAll('bs-menu-item'));
|
|
62
|
+
btn(a).focus();
|
|
63
|
+
key(btn(a), 'ArrowDown');
|
|
64
|
+
await waitForChanges();
|
|
65
|
+
expect(c.shadowRoot.activeElement).toBe(btn(c));
|
|
66
|
+
key(btn(c), 'ArrowDown');
|
|
67
|
+
expect(a.shadowRoot.activeElement).toBe(btn(a));
|
|
68
|
+
key(btn(a), 'ArrowUp');
|
|
69
|
+
expect(c.shadowRoot.activeElement).toBe(btn(c));
|
|
70
|
+
});
|
|
71
|
+
it('Home/End jump to first/last enabled item', async () => {
|
|
72
|
+
const { root } = await render(menu());
|
|
73
|
+
const [a, , c] = Array.from(root.querySelectorAll('bs-menu-item'));
|
|
74
|
+
btn(a).focus();
|
|
75
|
+
key(btn(a), 'End');
|
|
76
|
+
expect(c.shadowRoot.activeElement).toBe(btn(c));
|
|
77
|
+
key(btn(c), 'Home');
|
|
78
|
+
expect(a.shadowRoot.activeElement).toBe(btn(a));
|
|
79
|
+
});
|
|
80
|
+
});
|
|
81
|
+
describe('bs-slider form association', () => {
|
|
82
|
+
it('submits its value under name and resets with the form', async () => {
|
|
83
|
+
const { root, waitForChanges } = await render(h("form", null, h("bs-slider", { name: "vol", value: 30 })));
|
|
84
|
+
const form = root;
|
|
85
|
+
await waitForChanges();
|
|
86
|
+
expect(new FormData(form).get('vol')).toBe('30');
|
|
87
|
+
const slider = form.querySelector('bs-slider');
|
|
88
|
+
slider.value = 70;
|
|
89
|
+
await waitForChanges();
|
|
90
|
+
expect(new FormData(form).get('vol')).toBe('70');
|
|
91
|
+
form.reset();
|
|
92
|
+
await waitForChanges();
|
|
93
|
+
expect(new FormData(form).get('vol')).toBe('30');
|
|
94
|
+
});
|
|
95
|
+
it('range type submits start then end under the same name', async () => {
|
|
96
|
+
const { root, waitForChanges } = await render(h("form", null, h("bs-slider", { name: "price", type: "range", valueStart: 10, valueEnd: 90 })));
|
|
97
|
+
await waitForChanges();
|
|
98
|
+
expect(new FormData(root).getAll('price')).toEqual(['10', '90']);
|
|
99
|
+
});
|
|
100
|
+
});
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { render, h, describe, it, expect } from "@stencil/vitest";
|
|
2
|
+
import { vi } from "vitest";
|
|
2
3
|
describe('bs-logo', () => {
|
|
3
4
|
it('renders role="img" and aria-label="BrandSync"', async () => {
|
|
4
5
|
const { root } = await render(h("bs-logo", null));
|
|
@@ -37,9 +38,9 @@ describe('bs-logo', () => {
|
|
|
37
38
|
expect(getComputedStyle(darkAsset).display).toBe('none');
|
|
38
39
|
});
|
|
39
40
|
it('shows the dark asset and hides the light one when an ambient dark theme sets --bs-logo-asset-*-display', async () => {
|
|
40
|
-
// Simulates what src/global/base.css's [data-theme="dark"] rule sets
|
|
41
|
-
//
|
|
42
|
-
//
|
|
41
|
+
// Simulates what src/global/base.css's [data-theme="dark"] rule sets, by setting the same
|
|
42
|
+
// custom properties directly on the render stage container. (The real selector is exercised
|
|
43
|
+
// in the "follows the real [data-theme="dark"] attribute" tests below.) CSS custom
|
|
43
44
|
// properties inherit through the shadow boundary regardless of where they're defined.
|
|
44
45
|
const { root } = await render(h("bs-logo", null), {
|
|
45
46
|
stageAttrs: { style: '--bs-logo-asset-light-display: none; --bs-logo-asset-dark-display: block;' },
|
|
@@ -50,6 +51,54 @@ describe('bs-logo', () => {
|
|
|
50
51
|
expect(getComputedStyle(darkAsset).display).not.toBe('none');
|
|
51
52
|
});
|
|
52
53
|
});
|
|
54
|
+
// The tests above set the --bs-logo-asset-*-display variables by hand. These exercise the real
|
|
55
|
+
// `[data-theme="dark"]` rule from src/global/base.css (loaded by vitest-setup.ts), i.e. what a
|
|
56
|
+
// consuming app actually does -- including WHERE the attribute may sit (issue: dark logo on a dark
|
|
57
|
+
// theme).
|
|
58
|
+
describe('background="auto" follows the real [data-theme="dark"] attribute', () => {
|
|
59
|
+
const shown = (root) => ({
|
|
60
|
+
light: getComputedStyle(root.shadowRoot.querySelector('.bs-logo__asset--light')).display !== 'none',
|
|
61
|
+
dark: getComputedStyle(root.shadowRoot.querySelector('.bs-logo__asset--dark')).display !== 'none',
|
|
62
|
+
});
|
|
63
|
+
it('flips to the dark asset when data-theme="dark" is on <html>', async () => {
|
|
64
|
+
document.documentElement.setAttribute('data-theme', 'dark');
|
|
65
|
+
try {
|
|
66
|
+
const { root } = await render(h("bs-logo", null));
|
|
67
|
+
expect(shown(root)).toEqual({ light: false, dark: true });
|
|
68
|
+
}
|
|
69
|
+
finally {
|
|
70
|
+
document.documentElement.removeAttribute('data-theme');
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
it('flips to the dark asset when data-theme="dark" is on <body>', async () => {
|
|
74
|
+
document.body.setAttribute('data-theme', 'dark');
|
|
75
|
+
try {
|
|
76
|
+
const { root } = await render(h("bs-logo", null));
|
|
77
|
+
expect(shown(root)).toEqual({ light: false, dark: true });
|
|
78
|
+
}
|
|
79
|
+
finally {
|
|
80
|
+
document.body.removeAttribute('data-theme');
|
|
81
|
+
}
|
|
82
|
+
});
|
|
83
|
+
it('flips to the dark asset when data-theme="dark" is on any ancestor wrapper', async () => {
|
|
84
|
+
const { root } = await render(h("div", { "data-theme": "dark" }, h("bs-logo", null)));
|
|
85
|
+
expect(shown(root.querySelector('bs-logo'))).toEqual({ light: false, dark: true });
|
|
86
|
+
});
|
|
87
|
+
it('does NOT flip for a logo outside the data-theme="dark" element', async () => {
|
|
88
|
+
const { root } = await render(h("div", null, h("div", { "data-theme": "dark" }), h("bs-logo", null)));
|
|
89
|
+
expect(shown(root.querySelector('bs-logo'))).toEqual({ light: true, dark: false });
|
|
90
|
+
});
|
|
91
|
+
it('does not follow prefers-color-scheme (only the data-theme attribute)', async () => {
|
|
92
|
+
const spy = vi.spyOn(window, 'matchMedia').mockImplementation((q) => ({ matches: q.includes('prefers-color-scheme: dark'), media: q, addEventListener: () => undefined, removeEventListener: () => undefined, addListener: () => undefined, removeListener: () => undefined, onchange: null, dispatchEvent: () => false }));
|
|
93
|
+
try {
|
|
94
|
+
const { root } = await render(h("bs-logo", null));
|
|
95
|
+
expect(shown(root)).toEqual({ light: true, dark: false });
|
|
96
|
+
}
|
|
97
|
+
finally {
|
|
98
|
+
spy.mockRestore();
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
});
|
|
53
102
|
describe('background="light"/"dark" (explicit)', () => {
|
|
54
103
|
it('pins the light asset even when an ambient dark theme is set', async () => {
|
|
55
104
|
const { root } = await render(h("bs-logo", { background: "light" }), {
|
|
@@ -21,8 +21,30 @@ import { h } from "@stencil/core";
|
|
|
21
21
|
* @prop --bs-menu-shadow - Elevation shadow of the menu box. Aliased to `--bs-shadow-sm`.
|
|
22
22
|
*/
|
|
23
23
|
export class BsMenu {
|
|
24
|
+
el;
|
|
25
|
+
/** WAI-ARIA menu pattern: Up/Down move focus between enabled items (wrapping), Home/End jump
|
|
26
|
+
* to the first/last. Items are the slotted `bs-menu-item` children. */
|
|
27
|
+
onKeyDown(ev) {
|
|
28
|
+
if (!['ArrowDown', 'ArrowUp', 'Home', 'End'].includes(ev.key))
|
|
29
|
+
return;
|
|
30
|
+
const items = Array.from(this.el.querySelectorAll('bs-menu-item')).filter(i => !i.disabled);
|
|
31
|
+
if (items.length === 0)
|
|
32
|
+
return;
|
|
33
|
+
const current = items.findIndex(i => i === ev.target || i.contains(ev.target));
|
|
34
|
+
ev.preventDefault();
|
|
35
|
+
let next;
|
|
36
|
+
if (ev.key === 'Home')
|
|
37
|
+
next = 0;
|
|
38
|
+
else if (ev.key === 'End')
|
|
39
|
+
next = items.length - 1;
|
|
40
|
+
else if (ev.key === 'ArrowDown')
|
|
41
|
+
next = current === -1 ? 0 : (current + 1) % items.length;
|
|
42
|
+
else
|
|
43
|
+
next = current === -1 ? items.length - 1 : (current - 1 + items.length) % items.length;
|
|
44
|
+
items[next].shadowRoot?.querySelector('button')?.focus();
|
|
45
|
+
}
|
|
24
46
|
render() {
|
|
25
|
-
return (h("div", { key: '
|
|
47
|
+
return (h("div", { key: '4f2995d0f53f85656de8595fb6a9909833c6369d', part: "list", class: "bs-menu", role: "menu" }, h("slot", { key: '0824f2a784eb4cfa28a2868f19c056570b56ba63' })));
|
|
26
48
|
}
|
|
27
49
|
static get is() { return "bs-menu"; }
|
|
28
50
|
static get encapsulation() { return "shadow"; }
|
|
@@ -36,4 +58,14 @@ export class BsMenu {
|
|
|
36
58
|
"$": ["bs-menu.css"]
|
|
37
59
|
};
|
|
38
60
|
}
|
|
61
|
+
static get elementRef() { return "el"; }
|
|
62
|
+
static get listeners() {
|
|
63
|
+
return [{
|
|
64
|
+
"name": "keydown",
|
|
65
|
+
"method": "onKeyDown",
|
|
66
|
+
"target": undefined,
|
|
67
|
+
"capture": false,
|
|
68
|
+
"passive": false
|
|
69
|
+
}];
|
|
70
|
+
}
|
|
39
71
|
}
|