@brandsync/wc 1.7.0 → 1.8.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 +201 -13
- package/dist/brandsync-wc/brandsync-wc.esm.js +1 -1
- package/dist/brandsync-wc/{p-387ed85f.entry.js → p-002d258d.entry.js} +1 -1
- package/dist/brandsync-wc/{p-819a3dae.entry.js → p-03b08508.entry.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-538cc08e.entry.js → p-114d2fd8.entry.js} +1 -1
- package/dist/brandsync-wc/{p-70e035ed.entry.js → p-153da845.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-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-2891d40b.entry.js +1 -0
- package/dist/brandsync-wc/p-29027559.entry.js +1 -0
- package/dist/brandsync-wc/p-2e7a1082.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-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-612cf79c.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-d03eba2b.entry.js → p-652d4068.entry.js} +1 -1
- package/dist/brandsync-wc/{p-9c1be2a0.entry.js → p-6bf2f116.entry.js} +1 -1
- 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-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-30d6a6d0.entry.js → p-bc69a96c.entry.js} +1 -1
- package/dist/brandsync-wc/{p-80cf96ff.entry.js → p-be2c1740.entry.js} +1 -1
- package/dist/brandsync-wc/p-bf53ad52.entry.js +1 -0
- package/dist/brandsync-wc/p-c10d2529.entry.js +1 -0
- package/dist/brandsync-wc/{p-8b57f606.entry.js → p-c4de155c.entry.js} +1 -1
- package/dist/brandsync-wc/p-c7f4c114.entry.js +1 -0
- 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-d25b7b74.entry.js → p-ee7da23d.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-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 +2 -2
- package/dist/cjs/bs-breadcrumb.cjs.entry.js +1 -1
- 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 +2 -2
- 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 +22 -3
- package/dist/cjs/bs-inline-tab.cjs.entry.js +7 -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 +2 -2
- package/dist/cjs/bs-navigation-header.cjs.entry.js +1 -1
- 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 +7 -3
- package/dist/cjs/bs-tabs.cjs.entry.js +51 -2
- 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-overflow/bs-breadcrumb-overflow.css +1 -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.js +16 -3
- 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.css +1 -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-menu/bs-menu.css +4 -0
- package/dist/collection/components/bs-menu/bs-menu.js +33 -1
- 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 +24 -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 +24 -1
- package/dist/collection/components/bs-tab/bs-tabs/bs-tabs.js +57 -1
- 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.js +1 -1
- package/dist/collection/components/ui-shell/bs-navigation-drawer/bs-navigation-drawer-item/bs-navigation-drawer-item.js +1 -1
- 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-BkHYJIyj.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 +2 -2
- package/dist/esm/bs-breadcrumb.entry.js +1 -1
- 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 +2 -2
- 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 +22 -3
- package/dist/esm/bs-inline-tab.entry.js +7 -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 +2 -2
- package/dist/esm/bs-navigation-header.entry.js +1 -1
- 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 +7 -3
- package/dist/esm/bs-tabs.entry.js +51 -2
- 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-button/bs-button/bs-button.d.ts +4 -1
- package/dist/types/components/bs-button/bs-icon-button/bs-icon-button.d.ts +4 -1
- package/dist/types/components/bs-checkbox/bs-checkbox.d.ts +12 -0
- 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-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 +4 -0
- package/dist/types/components/bs-tab/bs-tab/bs-tab.d.ts +4 -0
- package/dist/types/components/bs-tab/bs-tabs/bs-tabs.d.ts +7 -0
- package/dist/types/components/forms/forms.stories.d.ts +6 -0
- package/dist/types/components.d.ts +141 -7
- 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-4b0938a5.entry.js +0 -1
- package/dist/brandsync-wc/p-5312b6a5.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-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
|
@@ -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
|
+
});
|
|
@@ -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
|
}
|
|
@@ -45,6 +45,11 @@ export class BsProgress {
|
|
|
45
45
|
* `indeterminate` never shows a label regardless of this prop, since there's no percentage to
|
|
46
46
|
* show. Defaults to `true`. */
|
|
47
47
|
showLabel = true;
|
|
48
|
+
/** Accessible name for the progress bar (e.g. "Uploading report"). Required for assistive tech --
|
|
49
|
+
* a `role="progressbar"` with no name is an axe-core `aria-progressbar-name` violation. Setting
|
|
50
|
+
* `aria-label` on the host doesn't reach the inner element across the shadow boundary, so this
|
|
51
|
+
* prop binds it directly -- same pattern as `bs-button`'s `ariaLabel`. */
|
|
52
|
+
ariaLabel = null;
|
|
48
53
|
get clampedValue() {
|
|
49
54
|
return Math.min(100, Math.max(0, this.value));
|
|
50
55
|
}
|
|
@@ -64,7 +69,7 @@ export class BsProgress {
|
|
|
64
69
|
const isDeterminate = this.type === 'determinate';
|
|
65
70
|
const value = this.clampedValue;
|
|
66
71
|
const dashOffset = circumference * (1 - value / 100);
|
|
67
|
-
return (h("div", { key: '
|
|
72
|
+
return (h("div", { key: 'add8dfafdbee4eaa9712c6e2ba6ddff6f8f6c47f', part: "container", class: "bs-progress" }, h("div", { key: 'fd89c73aa247fc3770187a45dc4681857e257d4e', class: "bs-progress__box", style: { width: `${diameter}px`, height: `${diameter}px` }, role: "progressbar", "aria-label": this.ariaLabel, "aria-valuemin": isDeterminate ? '0' : undefined, "aria-valuemax": isDeterminate ? '100' : undefined, "aria-valuenow": isDeterminate ? String(value) : undefined, "aria-busy": isDeterminate ? undefined : 'true' }, isDeterminate ? (h("svg", { class: "bs-progress__ring", width: diameter, height: diameter, viewBox: `0 0 ${diameter} ${diameter}` }, h("circle", { part: "track", class: "bs-progress__track", cx: diameter / 2, cy: diameter / 2, r: radius, "stroke-width": this.strokeWidth, fill: "none" }), h("circle", { part: "arc", class: "bs-progress__arc", cx: diameter / 2, cy: diameter / 2, r: radius, "stroke-width": this.strokeWidth, fill: "none", "stroke-linecap": "round", "stroke-dasharray": circumference, "stroke-dashoffset": dashOffset }))) : (
|
|
68
73
|
// Figma's indeterminate ring is a fading "comet tail" (transparent -> solid color),
|
|
69
74
|
// not a flat-colored partial arc -- SVG has no angular/conic gradient primitive, so a
|
|
70
75
|
// CSS conic-gradient (color varying by angle) + a radial-gradient mask (carving the
|
|
@@ -73,7 +78,7 @@ export class BsProgress {
|
|
|
73
78
|
h("div", { part: "arc", class: "bs-progress__spinner", style: {
|
|
74
79
|
'--bs-progress-spinner-stroke-width': `${this.strokeWidth}px`,
|
|
75
80
|
'--bs-progress-spinner-sweep': `${INDETERMINATE_SWEEP_DEGREES}deg`,
|
|
76
|
-
} }))), isDeterminate && this.showLabel && (h("span", { key: '
|
|
81
|
+
} }))), isDeterminate && this.showLabel && (h("span", { key: '9c86dc195204f28c06e05bf09f823241bf9f3a86', part: "label", class: `bs-progress__label bs-progress__label--${this.size}` }, value, "%"))));
|
|
77
82
|
}
|
|
78
83
|
static get is() { return "bs-progress"; }
|
|
79
84
|
static get encapsulation() { return "shadow"; }
|
|
@@ -206,6 +211,26 @@ export class BsProgress {
|
|
|
206
211
|
"reflect": false,
|
|
207
212
|
"attribute": "show-label",
|
|
208
213
|
"defaultValue": "true"
|
|
214
|
+
},
|
|
215
|
+
"ariaLabel": {
|
|
216
|
+
"type": "string",
|
|
217
|
+
"mutable": false,
|
|
218
|
+
"complexType": {
|
|
219
|
+
"original": "string | null",
|
|
220
|
+
"resolved": "string",
|
|
221
|
+
"references": {}
|
|
222
|
+
},
|
|
223
|
+
"required": false,
|
|
224
|
+
"optional": false,
|
|
225
|
+
"docs": {
|
|
226
|
+
"tags": [],
|
|
227
|
+
"text": "Accessible name for the progress bar (e.g. \"Uploading report\"). Required for assistive tech --\na `role=\"progressbar\"` with no name is an axe-core `aria-progressbar-name` violation. Setting\n`aria-label` on the host doesn't reach the inner element across the shadow boundary, so this\nprop binds it directly -- same pattern as `bs-button`'s `ariaLabel`."
|
|
228
|
+
},
|
|
229
|
+
"getter": false,
|
|
230
|
+
"setter": false,
|
|
231
|
+
"reflect": false,
|
|
232
|
+
"attribute": "aria-label",
|
|
233
|
+
"defaultValue": "null"
|
|
209
234
|
}
|
|
210
235
|
};
|
|
211
236
|
}
|
|
@@ -30,14 +30,9 @@ describe('bs-radio', () => {
|
|
|
30
30
|
expect(input).toEqualAttribute('name', 'fruit');
|
|
31
31
|
expect(input).toEqualAttribute('value', 'apple');
|
|
32
32
|
});
|
|
33
|
-
//
|
|
34
|
-
//
|
|
35
|
-
|
|
36
|
-
// native radio group, so clicking one does not natively uncheck another. This is a real, tested
|
|
37
|
-
// limitation of composing native <input type="radio"> inside separate shadow roots, not a bug in
|
|
38
|
-
// this component -- see bs-radio.mdx's Accessibility section for the documented gap. Within a
|
|
39
|
-
// single instance's own shadow root the native input still behaves like a normal radio input.
|
|
40
|
-
it('same-name bs-radio instances do NOT natively uncheck each other, since each lives in its own shadow root', async () => {
|
|
33
|
+
// Native same-name grouping can't cross each <bs-radio>'s own shadow root, so the component
|
|
34
|
+
// implements mutual exclusion itself (see bs-radio.tsx's `name` prop doc).
|
|
35
|
+
it('same-name bs-radio instances uncheck each other', async () => {
|
|
41
36
|
const { root, waitForChanges } = await render(h("div", null, h("bs-radio", { name: "fruit", value: "apple" }), h("bs-radio", { name: "fruit", value: "banana" })));
|
|
42
37
|
const [first, second] = Array.from(root.querySelectorAll('bs-radio'));
|
|
43
38
|
const firstInput = first.shadowRoot.querySelector('input');
|
|
@@ -48,8 +43,7 @@ describe('bs-radio', () => {
|
|
|
48
43
|
secondInput.click();
|
|
49
44
|
await waitForChanges();
|
|
50
45
|
expect(secondInput.checked).toBe(true);
|
|
51
|
-
|
|
52
|
-
expect(firstInput.checked).toBe(true);
|
|
46
|
+
expect(firstInput.checked).toBe(false);
|
|
53
47
|
});
|
|
54
48
|
describe('disabled', () => {
|
|
55
49
|
it('sets the disabled attribute on the native input', async () => {
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
.bs-radio__input {
|
|
35
35
|
position: absolute;
|
|
36
36
|
top: 0;
|
|
37
|
-
|
|
37
|
+
inset-inline-start: 0;
|
|
38
38
|
width: 100%;
|
|
39
39
|
height: 100%;
|
|
40
40
|
margin: 0;
|
|
@@ -162,3 +162,9 @@
|
|
|
162
162
|
.bs-radio--disabled .bs-radio__label {
|
|
163
163
|
color: var(--bs-radio-label-disabled);
|
|
164
164
|
}
|
|
165
|
+
|
|
166
|
+
/* Windows High Contrast: ring and dot in system colors. */
|
|
167
|
+
@media (forced-colors: active) {
|
|
168
|
+
.bs-radio__circle { border: 2px solid ButtonText; forced-color-adjust: none; background: Canvas; }
|
|
169
|
+
.bs-radio__dot { background: Highlight; }
|
|
170
|
+
}
|
|
@@ -22,13 +22,10 @@ import { h } from "@stencil/core";
|
|
|
22
22
|
export class BsRadio {
|
|
23
23
|
el;
|
|
24
24
|
/** The native radio input's `name` attribute. Passed straight through to the native input inside.
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
* bs-radio.mdx's Accessibility section for this known gap; consumers building a group currently
|
|
30
|
-
* need to manage mutual exclusivity themselves (e.g. via `bsChange`) until a `bs-radio-group`
|
|
31
|
-
* wrapper exists. */
|
|
25
|
+
* Also the group key: `bs-radio` elements sharing a `name` within the same root (document or
|
|
26
|
+
* shadow root) behave as one radio group -- checking one unchecks the others, arrow keys move
|
|
27
|
+
* between them, and only one is in the tab order. Native grouping can't cross each radio's own
|
|
28
|
+
* shadow root, so this component implements it itself. */
|
|
32
29
|
name;
|
|
33
30
|
/** The native radio input's `value` attribute -- read from `event.target.value`, or used when
|
|
34
31
|
* wiring the group up to a form. */
|
|
@@ -40,9 +37,65 @@ export class BsRadio {
|
|
|
40
37
|
disabled = false;
|
|
41
38
|
/** Emitted with this radio's own `value` when it becomes checked via user interaction. Since
|
|
42
39
|
* native same-`name` grouping doesn't cross shadow-root boundaries (see the `name` prop's doc),
|
|
43
|
-
* a consumer wiring up a group of `bs-radio`s
|
|
44
|
-
* response to this event -- there's no automatic un-checking to rely on here. */
|
|
40
|
+
* a consumer wiring up a group of `bs-radio`s does not need to un-check the others itself. */
|
|
45
41
|
bsChange;
|
|
42
|
+
internals;
|
|
43
|
+
initialChecked = false;
|
|
44
|
+
/** Whether any radio in this group is checked -- drives roving tabindex (an unchecked radio is
|
|
45
|
+
* only tabbable while nothing in its group is checked). */
|
|
46
|
+
groupHasChecked = false;
|
|
47
|
+
/** Other `bs-radio`s sharing this one's `name` within the same root, in DOM order (including
|
|
48
|
+
* this one). */
|
|
49
|
+
groupMembers() {
|
|
50
|
+
if (!this.name)
|
|
51
|
+
return [this.el];
|
|
52
|
+
const root = this.el.getRootNode();
|
|
53
|
+
return Array.from(root.querySelectorAll('bs-radio')).filter(r => r.name === this.name);
|
|
54
|
+
}
|
|
55
|
+
onCheckedChange() {
|
|
56
|
+
this.internals?.setFormValue?.(this.checked ? this.value ?? 'on' : null);
|
|
57
|
+
if (this.checked) {
|
|
58
|
+
this.groupMembers().forEach(r => {
|
|
59
|
+
if (r !== this.el && r.checked)
|
|
60
|
+
r.checked = false;
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
this.refreshGroupState();
|
|
64
|
+
}
|
|
65
|
+
onAnyRadioChange() {
|
|
66
|
+
this.refreshGroupState();
|
|
67
|
+
}
|
|
68
|
+
refreshGroupState() {
|
|
69
|
+
this.groupHasChecked = this.groupMembers().some(r => r.checked);
|
|
70
|
+
}
|
|
71
|
+
componentWillLoad() {
|
|
72
|
+
this.initialChecked = this.checked;
|
|
73
|
+
this.internals?.setFormValue?.(this.checked ? this.value ?? 'on' : null);
|
|
74
|
+
}
|
|
75
|
+
componentDidLoad() {
|
|
76
|
+
this.refreshGroupState();
|
|
77
|
+
}
|
|
78
|
+
/** Called by the browser when the surrounding `<form>` is reset. */
|
|
79
|
+
formResetCallback() {
|
|
80
|
+
this.checked = this.initialChecked;
|
|
81
|
+
}
|
|
82
|
+
/** WAI-ARIA radio group pattern: arrows move selection (and focus) to the previous/next enabled
|
|
83
|
+
* radio in the group, wrapping at the ends. */
|
|
84
|
+
onKeyDown = (ev) => {
|
|
85
|
+
const forward = ev.key === 'ArrowRight' || ev.key === 'ArrowDown';
|
|
86
|
+
const backward = ev.key === 'ArrowLeft' || ev.key === 'ArrowUp';
|
|
87
|
+
if (!forward && !backward)
|
|
88
|
+
return;
|
|
89
|
+
const members = this.groupMembers().filter(r => !r.disabled);
|
|
90
|
+
if (members.length < 2)
|
|
91
|
+
return;
|
|
92
|
+
ev.preventDefault();
|
|
93
|
+
const idx = members.indexOf(this.el);
|
|
94
|
+
const next = members[(idx + (forward ? 1 : -1) + members.length) % members.length];
|
|
95
|
+
const input = next.shadowRoot?.querySelector('input');
|
|
96
|
+
input?.click();
|
|
97
|
+
input?.focus();
|
|
98
|
+
};
|
|
46
99
|
onChange = (ev) => {
|
|
47
100
|
const checked = ev.target.checked;
|
|
48
101
|
this.checked = checked;
|
|
@@ -51,11 +104,12 @@ export class BsRadio {
|
|
|
51
104
|
}
|
|
52
105
|
};
|
|
53
106
|
render() {
|
|
54
|
-
return (h("label", { key: '
|
|
107
|
+
return (h("label", { key: '84bfc39d5714d15c45936c8150b9bd7473b79574', class: `bs-radio ${this.disabled ? 'bs-radio--disabled' : ''}` }, h("input", { key: '0a118d5e59f4d33b0411f7be0fba08a706cda298', class: "bs-radio__input", type: "radio", name: this.name, value: this.value, checked: this.checked, disabled: this.disabled, tabIndex: this.checked || !this.groupHasChecked ? 0 : -1, onKeyDown: this.onKeyDown, onChange: this.onChange }), h("span", { key: '889dadd67126819c3d39a5823d48be58a9c71f9f', class: "bs-radio__hit-area" }, h("span", { key: '5bbed4d44bcf4d810693b5912a90855d680540d0', class: "bs-radio__state-layer" }, h("span", { key: '509389527b876127ca456900e3bb4aa21c735f72', part: "circle", class: `bs-radio__circle ${this.checked ? 'bs-radio__circle--selected' : ''}` }, this.checked && h("span", { key: '9a7e335f9646eb72fb06fb0ca9436e763c3ad278', part: "dot", class: "bs-radio__dot" })))), h("span", { key: '2017790d3d99355b4eb93e3659c809df58c61065', part: "label", class: "bs-radio__label" }, h("slot", { key: '199450bb26f7966cdd64b04c78e3015300d793c9' }))));
|
|
55
108
|
}
|
|
56
109
|
static get is() { return "bs-radio"; }
|
|
57
110
|
static get encapsulation() { return "shadow"; }
|
|
58
111
|
static get delegatesFocus() { return true; }
|
|
112
|
+
static get formAssociated() { return true; }
|
|
59
113
|
static get originalStyleUrls() {
|
|
60
114
|
return {
|
|
61
115
|
"$": ["bs-radio.css"]
|
|
@@ -80,11 +134,11 @@ export class BsRadio {
|
|
|
80
134
|
"optional": false,
|
|
81
135
|
"docs": {
|
|
82
136
|
"tags": [],
|
|
83
|
-
"text": "The native radio input's `name` attribute. Passed straight through to the native input inside.\
|
|
137
|
+
"text": "The native radio input's `name` attribute. Passed straight through to the native input inside.\nAlso the group key: `bs-radio` elements sharing a `name` within the same root (document or\nshadow root) behave as one radio group -- checking one unchecks the others, arrow keys move\nbetween them, and only one is in the tab order. Native grouping can't cross each radio's own\nshadow root, so this component implements it itself."
|
|
84
138
|
},
|
|
85
139
|
"getter": false,
|
|
86
140
|
"setter": false,
|
|
87
|
-
"reflect":
|
|
141
|
+
"reflect": true,
|
|
88
142
|
"attribute": "name"
|
|
89
143
|
},
|
|
90
144
|
"value": {
|
|
@@ -142,12 +196,17 @@ export class BsRadio {
|
|
|
142
196
|
},
|
|
143
197
|
"getter": false,
|
|
144
198
|
"setter": false,
|
|
145
|
-
"reflect":
|
|
199
|
+
"reflect": true,
|
|
146
200
|
"attribute": "disabled",
|
|
147
201
|
"defaultValue": "false"
|
|
148
202
|
}
|
|
149
203
|
};
|
|
150
204
|
}
|
|
205
|
+
static get states() {
|
|
206
|
+
return {
|
|
207
|
+
"groupHasChecked": {}
|
|
208
|
+
};
|
|
209
|
+
}
|
|
151
210
|
static get events() {
|
|
152
211
|
return [{
|
|
153
212
|
"method": "bsChange",
|
|
@@ -157,7 +216,7 @@ export class BsRadio {
|
|
|
157
216
|
"composed": true,
|
|
158
217
|
"docs": {
|
|
159
218
|
"tags": [],
|
|
160
|
-
"text": "Emitted with this radio's own `value` when it becomes checked via user interaction. Since\nnative same-`name` grouping doesn't cross shadow-root boundaries (see the `name` prop's doc),\na consumer wiring up a group of `bs-radio`s
|
|
219
|
+
"text": "Emitted with this radio's own `value` when it becomes checked via user interaction. Since\nnative same-`name` grouping doesn't cross shadow-root boundaries (see the `name` prop's doc),\na consumer wiring up a group of `bs-radio`s does not need to un-check the others itself."
|
|
161
220
|
},
|
|
162
221
|
"complexType": {
|
|
163
222
|
"original": "string",
|
|
@@ -167,4 +226,23 @@ export class BsRadio {
|
|
|
167
226
|
}];
|
|
168
227
|
}
|
|
169
228
|
static get elementRef() { return "el"; }
|
|
229
|
+
static get watchers() {
|
|
230
|
+
return [{
|
|
231
|
+
"propName": "checked",
|
|
232
|
+
"methodName": "onCheckedChange"
|
|
233
|
+
}, {
|
|
234
|
+
"propName": "value",
|
|
235
|
+
"methodName": "onCheckedChange"
|
|
236
|
+
}];
|
|
237
|
+
}
|
|
238
|
+
static get listeners() {
|
|
239
|
+
return [{
|
|
240
|
+
"name": "bsChange",
|
|
241
|
+
"method": "onAnyRadioChange",
|
|
242
|
+
"target": "document",
|
|
243
|
+
"capture": false,
|
|
244
|
+
"passive": false
|
|
245
|
+
}];
|
|
246
|
+
}
|
|
247
|
+
static get attachInternalsMemberName() { return "internals"; }
|
|
170
248
|
}
|
|
@@ -35,19 +35,10 @@ export const DisabledChecked = {
|
|
|
35
35
|
name: 'Disabled + checked',
|
|
36
36
|
args: { disabled: true, checked: true },
|
|
37
37
|
};
|
|
38
|
-
// Native same-name radio grouping doesn't extend across separate <bs-radio> instances (each has
|
|
39
|
-
// its own shadow root -- see bs-radio.mdx's Accessibility section), so this story manages mutual
|
|
40
|
-
// exclusivity itself by listening for bsChange and unchecking the siblings.
|
|
41
|
-
const onGroupChange = (ev) => {
|
|
42
|
-
const group = ev.target.closest('[data-radio-group]');
|
|
43
|
-
group?.querySelectorAll('bs-radio').forEach(radio => {
|
|
44
|
-
radio.checked = radio === ev.target;
|
|
45
|
-
});
|
|
46
|
-
};
|
|
47
38
|
export const Group = {
|
|
48
39
|
name: 'Radio group',
|
|
49
40
|
render: () => html `
|
|
50
|
-
<div
|
|
41
|
+
<div role="radiogroup" aria-label="Options" style="display: flex; flex-direction: column; gap: 8px;">
|
|
51
42
|
<bs-radio name="group-story" value="option-1" checked>Option 1</bs-radio>
|
|
52
43
|
<bs-radio name="group-story" value="option-2">Option 2</bs-radio>
|
|
53
44
|
<bs-radio name="group-story" value="option-3">Option 3</bs-radio>
|