@brandsync/wc 1.8.0 → 1.10.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 +4493 -3458
- package/dist/brandsync-wc/brandsync-wc.esm.js +1 -1
- package/dist/brandsync-wc/{p-c4de155c.entry.js → p-0132a2d1.entry.js} +1 -1
- package/dist/brandsync-wc/{p-051d3064.entry.js → p-041776c0.entry.js} +1 -1
- package/dist/brandsync-wc/{p-a09e157f.entry.js → p-08c99a60.entry.js} +1 -1
- package/dist/brandsync-wc/{p-70f64b25.entry.js → p-18c3c22c.entry.js} +1 -1
- package/dist/brandsync-wc/p-1c3a43c7.entry.js +1 -0
- package/dist/brandsync-wc/{p-fddc7bd1.entry.js → p-1c427ffb.entry.js} +1 -1
- package/dist/brandsync-wc/p-2181378f.entry.js +1 -0
- package/dist/brandsync-wc/{p-29027559.entry.js → p-2e958566.entry.js} +1 -1
- package/dist/brandsync-wc/{p-235ae012.entry.js → p-301b2455.entry.js} +1 -1
- package/dist/brandsync-wc/{p-8ee0153b.entry.js → p-32cd69f1.entry.js} +1 -1
- package/dist/brandsync-wc/p-4f2c4929.entry.js +1 -0
- package/dist/brandsync-wc/{p-a0d5a620.entry.js → p-50a251a4.entry.js} +1 -1
- package/dist/brandsync-wc/{p-0e39b9cc.entry.js → p-5f3cd501.entry.js} +1 -1
- package/dist/brandsync-wc/p-701ebf4a.entry.js +1 -0
- package/dist/brandsync-wc/p-763876f5.entry.js +1 -0
- package/dist/brandsync-wc/{p-f7d47c17.entry.js → p-76e1c295.entry.js} +1 -1
- package/dist/brandsync-wc/p-790db8b3.entry.js +1 -0
- package/dist/brandsync-wc/{p-4e5dcaff.entry.js → p-796a1860.entry.js} +1 -1
- package/dist/brandsync-wc/p-806a5347.entry.js +1 -0
- package/dist/brandsync-wc/{p-6331de9c.entry.js → p-8eba7f90.entry.js} +1 -1
- package/dist/brandsync-wc/p-96ed9386.entry.js +1 -0
- package/dist/brandsync-wc/{p-cfcf3f0a.entry.js → p-9e88f19c.entry.js} +1 -1
- package/dist/brandsync-wc/p-9f6fe37d.entry.js +1 -0
- package/dist/brandsync-wc/{p-de7c946d.entry.js → p-a71d2811.entry.js} +1 -1
- package/dist/brandsync-wc/{p-33e44094.entry.js → p-a8e2a829.entry.js} +1 -1
- package/dist/brandsync-wc/p-addfa0a0.entry.js +1 -0
- package/dist/brandsync-wc/{p-4574a707.entry.js → p-af2bf957.entry.js} +1 -1
- package/dist/brandsync-wc/{p-6bf2f116.entry.js → p-b2074a32.entry.js} +1 -1
- package/dist/brandsync-wc/{p-03b08508.entry.js → p-c3f72584.entry.js} +1 -1
- package/dist/brandsync-wc/{p-7c94e6ae.entry.js → p-c99b6a66.entry.js} +1 -1
- package/dist/brandsync-wc/{p-2891d40b.entry.js → p-c9a72416.entry.js} +1 -1
- package/dist/brandsync-wc/{p-9f65f998.entry.js → p-d3f44cb7.entry.js} +1 -1
- package/dist/brandsync-wc/p-d42b1c2b.entry.js +1 -0
- package/dist/brandsync-wc/{p-3ec74d35.entry.js → p-daab6b22.entry.js} +1 -1
- package/dist/brandsync-wc/{p-ee7da23d.entry.js → p-dbcbe682.entry.js} +1 -1
- package/dist/brandsync-wc/{p-3176d1d3.entry.js → p-e8a5b8eb.entry.js} +1 -1
- package/dist/brandsync-wc/{p-062cfa34.entry.js → p-ea4e20ef.entry.js} +1 -1
- package/dist/brandsync-wc/p-f370b8fa.entry.js +1 -0
- package/dist/brandsync-wc/{p-05c7de28.entry.js → p-f89de457.entry.js} +1 -1
- package/dist/brandsync-wc/{p-114d2fd8.entry.js → p-fd254972.entry.js} +1 -1
- package/dist/cjs/brandsync-wc.cjs.js +1 -1
- 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 +1 -1
- package/dist/cjs/bs-breadcrumb-overflow.cjs.entry.js +13 -1
- package/dist/cjs/bs-breadcrumb.cjs.entry.js +15 -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-chatbot-feedback.cjs.entry.js +1 -1
- package/dist/cjs/bs-chatbot-header.cjs.entry.js +1 -1
- package/dist/cjs/bs-chatbot-response-action.cjs.entry.js +1 -1
- 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-data-table.cjs.entry.js +18 -4
- package/dist/cjs/bs-datepicker.cjs.entry.js +410 -0
- 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 +2 -2
- package/dist/cjs/bs-inline-tab.cjs.entry.js +5 -1
- package/dist/cjs/{bs-input.cjs.entry.js → bs-input_2.cjs.entry.js} +37 -4
- package/dist/cjs/bs-menu.cjs.entry.js +1 -1
- package/dist/cjs/bs-navigation-drawer-item.cjs.entry.js +1 -1
- package/dist/cjs/bs-navigation-drawer.cjs.entry.js +118 -5
- 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 +2 -2
- package/dist/cjs/bs-progress.cjs.entry.js +2 -2
- package/dist/cjs/bs-radio.cjs.entry.js +1 -1
- package/dist/cjs/bs-slider.cjs.entry.js +1 -1
- 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 +1 -1
- package/dist/cjs/bs-stepper.cjs.entry.js +1 -1
- package/dist/cjs/bs-switch.cjs.entry.js +1 -1
- package/dist/cjs/bs-tab.cjs.entry.js +5 -1
- package/dist/cjs/bs-tabs.cjs.entry.js +47 -2
- package/dist/cjs/bs-timepicker.cjs.entry.js +209 -0
- package/dist/cjs/bs-toast.cjs.entry.js +1 -1
- package/dist/cjs/bs-tooltip.cjs.entry.js +1 -1
- package/dist/cjs/loader.cjs.js +1 -1
- package/dist/collection/collection-manifest.json +2 -0
- package/dist/collection/components/bs-a11y.cmp.test.js +4 -0
- package/dist/collection/components/bs-ai-disclaimer/bs-ai-disclaimer.js +1 -1
- package/dist/collection/components/bs-ai-greeting/bs-ai-greeting.js +1 -1
- package/dist/collection/components/bs-ai-thinking/bs-ai-thinking.js +1 -1
- package/dist/collection/components/bs-attachment-list/bs-attachment-list.js +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.js +30 -1
- package/dist/collection/components/bs-breadcrumb/bs-breadcrumbs/bs-breadcrumbs.js +1 -1
- 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 +3 -2
- package/dist/collection/components/bs-button/bs-icon-button/bs-icon-button.stories.js +10 -0
- package/dist/collection/components/bs-button-skeleton/bs-button-skeleton.js +1 -1
- package/dist/collection/components/bs-chatbot-feedback/bs-chatbot-feedback.js +1 -1
- package/dist/collection/components/bs-chatbot-header/bs-chatbot-header.js +1 -1
- package/dist/collection/components/bs-chatbot-response-action/bs-chatbot-response-action.js +1 -1
- package/dist/collection/components/bs-chatbot-sources-drawer/bs-chatbot-sources-drawer.js +1 -1
- package/dist/collection/components/bs-chatbot-suggestion-button/bs-chatbot-suggestion-button.js +1 -1
- package/dist/collection/components/bs-checkbox/bs-checkbox-skeleton/bs-checkbox-skeleton.js +1 -1
- 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.js +19 -5
- package/dist/collection/components/bs-data-table/bs-data-table.stories.js +8 -1
- package/dist/collection/components/bs-datepicker/bs-datepicker.cmp.test.js +182 -0
- package/dist/collection/components/bs-datepicker/bs-datepicker.css +315 -0
- package/dist/collection/components/bs-datepicker/bs-datepicker.js +782 -0
- package/dist/collection/components/bs-datepicker/bs-datepicker.stories.js +63 -0
- package/dist/collection/components/bs-file-upload/bs-file-upload.js +1 -1
- package/dist/collection/components/bs-file-upload-item/bs-file-upload-item.js +1 -1
- package/dist/collection/components/bs-input/bs-input.js +7 -4
- package/dist/collection/components/bs-logo/bs-logo.cmp.test.js +52 -3
- package/dist/collection/components/bs-menu/bs-menu.js +1 -1
- package/dist/collection/components/bs-menu/bs-menu.stories.js +54 -0
- package/dist/collection/components/bs-menu-item/bs-menu-item.js +1 -1
- package/dist/collection/components/bs-pagination/bs-pagination.js +1 -1
- package/dist/collection/components/bs-progress/bs-progress.js +2 -2
- package/dist/collection/components/bs-progress-linear/bs-progress-linear.js +2 -2
- package/dist/collection/components/bs-radio/bs-radio.js +1 -1
- package/dist/collection/components/bs-slider/bs-slider.js +1 -1
- package/dist/collection/components/bs-snackbar/bs-snackbar.js +1 -1
- package/dist/collection/components/bs-source-link/bs-source-link.js +2 -2
- package/dist/collection/components/bs-stepper/bs-stepper/bs-stepper.js +1 -1
- package/dist/collection/components/bs-stepper/bs-stepper-step/bs-stepper-step.js +1 -1
- package/dist/collection/components/bs-switch/bs-switch.js +1 -1
- 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.js +24 -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 +83 -2
- package/dist/collection/components/bs-tab/bs-tabs/bs-tabs.stories.js +24 -0
- package/dist/collection/components/bs-timepicker/bs-timepicker.cmp.test.js +141 -0
- package/dist/collection/components/bs-timepicker/bs-timepicker.css +200 -0
- package/dist/collection/components/bs-timepicker/bs-timepicker.js +509 -0
- package/dist/collection/components/bs-timepicker/bs-timepicker.stories.js +44 -0
- package/dist/collection/components/bs-toast/bs-toast.js +1 -1
- package/dist/collection/components/bs-tooltip/bs-tooltip.js +1 -1
- 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/collection/components/ui-shell/bs-navigation-header/bs-navigation-header/bs-navigation-header.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-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-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-data-table.js +1 -1
- package/dist/components/bs-datepicker.d.ts +11 -0
- package/dist/components/bs-datepicker.js +1 -0
- 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-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-timepicker.d.ts +11 -0
- package/dist/components/bs-timepicker.js +1 -0
- package/dist/components/bs-toast.js +1 -1
- package/dist/components/bs-tooltip.js +1 -1
- package/dist/components/{p-BA3c9Rom.js → p-B7Icv1ho.js} +1 -1
- package/dist/components/{p-wei0Ija2.js → p-BTvme8CE.js} +1 -1
- package/dist/components/p-BYR_ZC8v.js +1 -0
- package/dist/components/p-Ba860ej1.js +1 -0
- package/dist/components/p-CPvqZNO8.js +1 -0
- package/dist/components/{p-EtXc94lJ.js → p-DkIVyFOP.js} +1 -1
- package/dist/components/{p-BfEyD6Ku.js → p-ZK8p5zax.js} +1 -1
- package/dist/components/p-jDO25SfF.js +1 -0
- package/dist/esm/brandsync-wc.js +1 -1
- 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 +1 -1
- package/dist/esm/bs-breadcrumb-overflow.entry.js +14 -2
- 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-chatbot-feedback.entry.js +1 -1
- package/dist/esm/bs-chatbot-header.entry.js +1 -1
- package/dist/esm/bs-chatbot-response-action.entry.js +1 -1
- 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-data-table.entry.js +18 -4
- package/dist/esm/bs-datepicker.entry.js +408 -0
- 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 +2 -2
- package/dist/esm/bs-inline-tab.entry.js +5 -1
- package/dist/esm/{bs-input.entry.js → bs-input_2.entry.js} +37 -5
- package/dist/esm/bs-menu.entry.js +1 -1
- package/dist/esm/bs-navigation-drawer-item.entry.js +1 -1
- 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 +2 -2
- package/dist/esm/bs-progress.entry.js +2 -2
- package/dist/esm/bs-radio.entry.js +1 -1
- package/dist/esm/bs-slider.entry.js +1 -1
- 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 +1 -1
- package/dist/esm/bs-stepper.entry.js +1 -1
- package/dist/esm/bs-switch.entry.js +1 -1
- package/dist/esm/bs-tab.entry.js +5 -1
- package/dist/esm/bs-tabs.entry.js +48 -3
- package/dist/esm/bs-timepicker.entry.js +207 -0
- package/dist/esm/bs-toast.entry.js +1 -1
- package/dist/esm/bs-tooltip.entry.js +1 -1
- package/dist/esm/loader.js +1 -1
- 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-icon-button/bs-icon-button.d.ts +2 -1
- package/dist/types/components/bs-button/bs-icon-button/bs-icon-button.stories.d.ts +1 -0
- package/dist/types/components/bs-data-table/bs-data-table.d.ts +16 -2
- package/dist/types/components/bs-datepicker/bs-datepicker.cmp.test.d.ts +1 -0
- package/dist/types/components/bs-datepicker/bs-datepicker.d.ts +136 -0
- package/dist/types/components/bs-datepicker/bs-datepicker.stories.d.ts +20 -0
- package/dist/types/components/bs-menu/bs-menu.stories.d.ts +1 -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 +17 -0
- package/dist/types/components/bs-tab/bs-tabs/bs-tabs.stories.d.ts +1 -0
- package/dist/types/components/bs-timepicker/bs-timepicker.cmp.test.d.ts +1 -0
- package/dist/types/components/bs-timepicker/bs-timepicker.d.ts +101 -0
- package/dist/types/components/bs-timepicker/bs-timepicker.stories.d.ts +14 -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 +645 -2
- package/package.json +1 -1
- package/dist/brandsync-wc/p-002d258d.entry.js +0 -1
- package/dist/brandsync-wc/p-153da845.entry.js +0 -1
- package/dist/brandsync-wc/p-2e7a1082.entry.js +0 -1
- package/dist/brandsync-wc/p-612cf79c.entry.js +0 -1
- package/dist/brandsync-wc/p-652d4068.entry.js +0 -1
- package/dist/brandsync-wc/p-7b00dd36.entry.js +0 -1
- package/dist/brandsync-wc/p-ae978c9a.entry.js +0 -1
- package/dist/brandsync-wc/p-bc69a96c.entry.js +0 -1
- package/dist/brandsync-wc/p-bf53ad52.entry.js +0 -1
- package/dist/brandsync-wc/p-c10d2529.entry.js +0 -1
- package/dist/brandsync-wc/p-c7f4c114.entry.js +0 -1
- package/dist/cjs/bs-menu-item.cjs.entry.js +0 -34
- package/dist/components/p-BkHYJIyj.js +0 -1
- package/dist/components/p-Buly0d5G.js +0 -1
- package/dist/esm/bs-menu-item.entry.js +0 -32
|
@@ -54,7 +54,7 @@ export class BsBreadcrumbs {
|
|
|
54
54
|
});
|
|
55
55
|
}
|
|
56
56
|
render() {
|
|
57
|
-
return (h("nav", { key: '
|
|
57
|
+
return (h("nav", { key: '2772673d54ceab8866fada7a3a460938fd03d00c', "aria-label": this.label }, h("ol", { key: 'd9021230f43d8c307ea89ba5ce665bacff66cadf', part: "list", class: "bs-breadcrumbs__list" }, h("slot", { key: 'eccde40d6fc8c47caf1813daccb906b748117840', onSlotchange: this.onSlotChange }))));
|
|
58
58
|
}
|
|
59
59
|
static get is() { return "bs-breadcrumbs"; }
|
|
60
60
|
static get encapsulation() { return "shadow"; }
|
|
@@ -80,4 +80,24 @@ describe('bs-icon-button', () => {
|
|
|
80
80
|
expect(iconWrapper.querySelector('slot')).not.toBeNull();
|
|
81
81
|
expect(root.querySelector('svg.my-icon')).not.toBeNull();
|
|
82
82
|
});
|
|
83
|
+
describe('icon-font glyphs', () => {
|
|
84
|
+
// Issue: a slotted icon-font glyph (<i class="ph-bold ...">) ignored the size prop, because
|
|
85
|
+
// glyphs are sized by font-size and only width/height were being set.
|
|
86
|
+
for (const [size, px] of [
|
|
87
|
+
['xs', 8],
|
|
88
|
+
['sm', 16],
|
|
89
|
+
['md', 20],
|
|
90
|
+
['lg', 24],
|
|
91
|
+
]) {
|
|
92
|
+
it(`size="${size}" sizes a slotted glyph to ${px}px via font-size`, async () => {
|
|
93
|
+
const { root } = await render(h("bs-icon-button", { size: size, ariaLabel: "Bell" }, h("i", { class: "glyph" }, "A")));
|
|
94
|
+
const glyph = root.querySelector('i.glyph');
|
|
95
|
+
expect(getComputedStyle(glyph).fontSize).toBe(`${px}px`);
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
it('does not override a font-size the consumer sets on the glyph themselves', async () => {
|
|
99
|
+
const { root } = await render(h("bs-icon-button", { size: "md", ariaLabel: "Bell" }, h("i", { class: "glyph", style: { fontSize: '30px' } }, "A")));
|
|
100
|
+
expect(getComputedStyle(root.querySelector('i.glyph')).fontSize).toBe('30px');
|
|
101
|
+
});
|
|
102
|
+
});
|
|
83
103
|
});
|
|
@@ -2,14 +2,14 @@
|
|
|
2
2
|
* @prop --bs-icon-button-radius: Corner radius, size="sm"/"md"/"lg". Aliased to --bs-border-radius-100.
|
|
3
3
|
* @prop --bs-icon-button-radius-xs: Corner radius, size="xs" -- a smaller radius than --bs-icon-button-radius, since --bs-border-radius-100 (8px) on a 16px box would look nearly circular. Aliased to --bs-border-radius-50.
|
|
4
4
|
* @prop --bs-icon-button-size-xs: Container width/height at size="xs". 16px.
|
|
5
|
-
* @prop --bs-icon-button-icon-size-xs: Slotted icon width/height at size="xs". 8px.
|
|
5
|
+
* @prop --bs-icon-button-icon-size-xs: Slotted icon width/height (and font-size, for icon-font glyphs) at size="xs". 8px.
|
|
6
6
|
* @prop --bs-icon-button-padding-xs: Padding on all sides, size="xs" only -- distinct from --bs-icon-button-padding, since 16px/8px icon math (4px) differs from the sm/md/lg constant (12px). Aliased to --bs-spacing-50.
|
|
7
7
|
* @prop --bs-icon-button-size-sm: Container width/height at size="sm". 40px.
|
|
8
8
|
* @prop --bs-icon-button-size-md: Container width/height at size="md". 44px.
|
|
9
9
|
* @prop --bs-icon-button-size-lg: Container width/height at size="lg". 48px.
|
|
10
|
-
* @prop --bs-icon-button-icon-size-sm: Slotted icon width/height at size="sm". 16px.
|
|
11
|
-
* @prop --bs-icon-button-icon-size-md: Slotted icon width/height at size="md". 20px.
|
|
12
|
-
* @prop --bs-icon-button-icon-size-lg: Slotted icon width/height at size="lg". 24px.
|
|
10
|
+
* @prop --bs-icon-button-icon-size-sm: Slotted icon width/height (and font-size, for icon-font glyphs) at size="sm". 16px.
|
|
11
|
+
* @prop --bs-icon-button-icon-size-md: Slotted icon width/height (and font-size, for icon-font glyphs) at size="md". 20px.
|
|
12
|
+
* @prop --bs-icon-button-icon-size-lg: Slotted icon width/height (and font-size, for icon-font glyphs) at size="lg". 24px.
|
|
13
13
|
* @prop --bs-icon-button-padding: Padding on all sides, all sizes (constant -- centers the icon
|
|
14
14
|
* inside the container at every size). Aliased to --bs-spacing-150.
|
|
15
15
|
* @prop --bs-icon-button-primary-default: Background, variant="primary", default. Aliased to --bs-color-primary-default.
|
|
@@ -161,6 +161,9 @@
|
|
|
161
161
|
.bs-icon-button--xs .bs-icon-button__icon {
|
|
162
162
|
width: var(--bs-icon-button-icon-size-xs);
|
|
163
163
|
height: var(--bs-icon-button-icon-size-xs);
|
|
164
|
+
/* Icon-font glyphs (e.g. <i class="ph-bold ph-bell">) are sized by font-size, not width/height,
|
|
165
|
+
so they follow the same token as SVG icons do. */
|
|
166
|
+
font-size: var(--bs-icon-button-icon-size-xs);
|
|
164
167
|
}
|
|
165
168
|
|
|
166
169
|
.bs-icon-button--sm {
|
|
@@ -170,6 +173,9 @@
|
|
|
170
173
|
.bs-icon-button--sm .bs-icon-button__icon {
|
|
171
174
|
width: var(--bs-icon-button-icon-size-sm);
|
|
172
175
|
height: var(--bs-icon-button-icon-size-sm);
|
|
176
|
+
/* Icon-font glyphs (e.g. <i class="ph-bold ph-bell">) are sized by font-size, not width/height,
|
|
177
|
+
so they follow the same token as SVG icons do. */
|
|
178
|
+
font-size: var(--bs-icon-button-icon-size-sm);
|
|
173
179
|
}
|
|
174
180
|
|
|
175
181
|
.bs-icon-button--md {
|
|
@@ -179,6 +185,9 @@
|
|
|
179
185
|
.bs-icon-button--md .bs-icon-button__icon {
|
|
180
186
|
width: var(--bs-icon-button-icon-size-md);
|
|
181
187
|
height: var(--bs-icon-button-icon-size-md);
|
|
188
|
+
/* Icon-font glyphs (e.g. <i class="ph-bold ph-bell">) are sized by font-size, not width/height,
|
|
189
|
+
so they follow the same token as SVG icons do. */
|
|
190
|
+
font-size: var(--bs-icon-button-icon-size-md);
|
|
182
191
|
}
|
|
183
192
|
|
|
184
193
|
.bs-icon-button--lg {
|
|
@@ -188,6 +197,9 @@
|
|
|
188
197
|
.bs-icon-button--lg .bs-icon-button__icon {
|
|
189
198
|
width: var(--bs-icon-button-icon-size-lg);
|
|
190
199
|
height: var(--bs-icon-button-icon-size-lg);
|
|
200
|
+
/* Icon-font glyphs (e.g. <i class="ph-bold ph-bell">) are sized by font-size, not width/height,
|
|
201
|
+
so they follow the same token as SVG icons do. */
|
|
202
|
+
font-size: var(--bs-icon-button-icon-size-lg);
|
|
191
203
|
}
|
|
192
204
|
|
|
193
205
|
.bs-icon-button__icon {
|
|
@@ -195,12 +207,17 @@
|
|
|
195
207
|
align-items: center;
|
|
196
208
|
justify-content: center;
|
|
197
209
|
color: inherit;
|
|
210
|
+
line-height: 1;
|
|
198
211
|
}
|
|
199
212
|
|
|
200
213
|
.bs-icon-button__icon ::slotted(*) {
|
|
201
214
|
display: block;
|
|
202
215
|
width: 100%;
|
|
203
216
|
height: 100%;
|
|
217
|
+
/* Make a slotted icon font glyph take the wrapper's font-size (above) rather than whatever the
|
|
218
|
+
page's inherited size happens to be. */
|
|
219
|
+
font-size: inherit;
|
|
220
|
+
line-height: 1;
|
|
204
221
|
}
|
|
205
222
|
|
|
206
223
|
.bs-icon-button--primary {
|
|
@@ -20,7 +20,8 @@ import { h } from "@stencil/core";
|
|
|
20
20
|
* just conditionally, unlike `bs-button`) -- there's no visible label text to fall back on for an
|
|
21
21
|
* accessible name.
|
|
22
22
|
*
|
|
23
|
-
* @slot - Default slot: the icon content. Exactly one icon, no label
|
|
23
|
+
* @slot - Default slot: the icon content. Exactly one icon, no label -- an inline SVG, or an icon-font
|
|
24
|
+
* glyph (sized by `font-size`, which this component sets from the `size` prop).
|
|
24
25
|
* @part icon - The icon wrapper element.
|
|
25
26
|
*/
|
|
26
27
|
// Note: this component's CSS Custom Properties (--bs-icon-button-*) are documented via @prop
|
|
@@ -61,7 +62,7 @@ export class BsIconButton {
|
|
|
61
62
|
form.reset();
|
|
62
63
|
};
|
|
63
64
|
render() {
|
|
64
|
-
return (h("button", { key: '
|
|
65
|
+
return (h("button", { key: '433827a167fc7ce5183358c3e8469d68dd67788a', class: `bs-icon-button bs-icon-button--${this.variant} bs-icon-button--${this.size}`, type: this.type, disabled: this.disabled, "aria-label": this.ariaLabel, onClick: this.onClick }, h("span", { key: 'e7d50a6755e7e4de39db799abef38c118d888b98', part: "icon", class: "bs-icon-button__icon" }, h("slot", { key: 'a737620ca5d0baf69abc1964a160492c32359d09' }))));
|
|
65
66
|
}
|
|
66
67
|
static get is() { return "bs-icon-button"; }
|
|
67
68
|
static get encapsulation() { return "shadow"; }
|
|
@@ -42,6 +42,16 @@ export const Sizes = {
|
|
|
42
42
|
</div>
|
|
43
43
|
`,
|
|
44
44
|
};
|
|
45
|
+
// An icon-font glyph in the slot (here a plain text glyph, so the story needs no icon-font
|
|
46
|
+
// dependency) scales with `size` exactly like the SVG above -- no manual font-size needed.
|
|
47
|
+
export const IconFontGlyph = {
|
|
48
|
+
name: 'Icon-font glyph',
|
|
49
|
+
render: args => html `
|
|
50
|
+
<div style="display:flex; gap:12px; align-items:center;">
|
|
51
|
+
${['xs', 'sm', 'md', 'lg'].map(size => html `<bs-icon-button size=${size} aria-label=${args.ariaLabel}><i style="font-style: normal;">★</i></bs-icon-button>`)}
|
|
52
|
+
</div>
|
|
53
|
+
`,
|
|
54
|
+
};
|
|
45
55
|
export const Disabled = {
|
|
46
56
|
args: { disabled: true },
|
|
47
57
|
};
|
|
@@ -25,7 +25,7 @@ export class BsButtonSkeleton {
|
|
|
25
25
|
/** Sizing scale, matching the `bs-button` size it stands in for. */
|
|
26
26
|
size = 'md';
|
|
27
27
|
render() {
|
|
28
|
-
return h("span", { key: '
|
|
28
|
+
return h("span", { key: 'e272ddf5faf4cf9875b3d70d22ae4a406d1fdf02', part: "container", class: `bs-button-skeleton bs-button-skeleton--${this.size}`, role: "status", "aria-label": "Loading" });
|
|
29
29
|
}
|
|
30
30
|
static get is() { return "bs-button-skeleton"; }
|
|
31
31
|
static get encapsulation() { return "shadow"; }
|
|
@@ -123,7 +123,7 @@ export class BsChatbotFeedback {
|
|
|
123
123
|
}
|
|
124
124
|
render() {
|
|
125
125
|
const stars = [1, 2, 3, 4, 5];
|
|
126
|
-
return (h("div", { key: '
|
|
126
|
+
return (h("div", { key: 'aabc3b63a41eb5324d572f20a0af29ccea5d9507', class: "bs-chatbot-feedback", role: "region", "aria-label": this.computedHeading() }, h("button", { key: '2b01df39b773ba1ab55b654b688b8e514af87c29', type: "button", part: "close", class: "bs-chatbot-feedback__close", "aria-label": "Close", onClick: this.onCloseClick }, h(CloseIcon, { key: 'bcffb7d5c49c3de2fd62296c0a815a9ebab92bef' })), h("div", { key: '2d2f9c08f0b345dacda9d6514e6b2c665967358c', class: "bs-chatbot-feedback__top" }, h("div", { key: 'd06bf92615cb05d6b3142c7b375297b78a8ebb1c', class: "bs-chatbot-feedback__text" }, h("p", { key: '0c362bce3ad81312816565fff5440593daf55790', part: "heading", class: "bs-chatbot-feedback__heading" }, this.computedHeading()), h("p", { key: '0fe0980b52c758fcbed0176c5791e1ac088cc5ae', part: "subtitle", class: "bs-chatbot-feedback__subtitle" }, this.computedSubtitle())), h("div", { key: '556b835d8cc4543f524fdb01791c3af7aacd8669', class: "bs-chatbot-feedback__stars", role: "radiogroup", "aria-label": "Rating" }, stars.map(value => (h("button", { type: "button", part: "star", class: "bs-chatbot-feedback__star", role: "radio", "aria-checked": (this.rating >= value).toString(), "aria-label": `${value} star${value > 1 ? 's' : ''}`, disabled: this.submitted, onClick: () => this.onStarClick(value) }, h(StarIcon, { filled: this.rating >= value }))))), !this.submitted && (h("div", { key: 'f99093e2962ffedc27999e3a517c48904dea468b', class: "bs-chatbot-feedback__field" }, h("label", { key: 'c9bb2ebb44265fc2700e4a862e5ccb6076eaa25e', part: "label", class: "bs-chatbot-feedback__label", htmlFor: "bs-chatbot-feedback-comment" }, "Tell us what you think"), h("textarea", { key: '847b1022f1d7e1507e5e82186e03735eccafd80e', part: "textarea", id: "bs-chatbot-feedback-comment", class: "bs-chatbot-feedback__textarea", placeholder: "e.g.The response was helpful ....", value: this.comment, onInput: this.onCommentInput }))), this.submitted && this.comment && (h("p", { key: '7817ecda3a3778cd8b3fb05565ca4ed4101da612', part: "comment", class: "bs-chatbot-feedback__comment" }, this.comment))), h("div", { key: 'e0415b534c83f0fd8026c70aa01db12e68f0bab4', class: "bs-chatbot-feedback__actions" }, !this.submitted && (h("button", { key: 'f2969b4501a1e0af5adb302d5c80e813cd1aec26', type: "button", part: "submit", class: "bs-chatbot-feedback__submit", disabled: this.rating === 0, onClick: this.onSubmitClick }, h(SendIcon, { key: 'd3ca363da5f1e278a4d1653137cacfe42ac7daf7' }), "Submit feedback")), h("button", { key: '0b40842d7d9bf740847d0b851a10c9459db4a9c1', type: "button", part: "new-chat", class: `bs-chatbot-feedback__new-chat ${this.submitted ? 'bs-chatbot-feedback__new-chat--primary' : 'bs-chatbot-feedback__new-chat--outlined'}`, onClick: this.onNewChatClick }, h(EditIcon, { key: '6fe3c4955794d0d6167d307afe5156923ae871f2' }), "Start new chat"))));
|
|
127
127
|
}
|
|
128
128
|
static get is() { return "bs-chatbot-feedback"; }
|
|
129
129
|
static get encapsulation() { return "shadow"; }
|
|
@@ -74,7 +74,7 @@ export class BsChatbotHeader {
|
|
|
74
74
|
this.bsClose.emit();
|
|
75
75
|
};
|
|
76
76
|
render() {
|
|
77
|
-
return (h("div", { key: '
|
|
77
|
+
return (h("div", { key: '05419c0e9659074c99586190cd78a8de7a5eafcc', class: "bs-chatbot-header", role: "banner", "aria-label": this.heading }, h("div", { key: 'db67056399c3cd0054f24b8b6622221ec9a0817a', part: "logo", class: "bs-chatbot-header__logo", role: "img", "aria-label": this.heading, innerHTML: GENIE_LOGO_SVG }), h("div", { key: 'c8d98740445bd9d53c096b16058e721c9aea098c', class: "bs-chatbot-header__actions" }, h("span", { key: 'fbe6e910956684325e7ea9945f6ec16dbaf89b47', class: "bs-chatbot-header__tooltip-wrapper" }, h("button", { key: '30d9914ab21468151821e45b6243196e8e69f5b0', type: "button", part: "new-chat", class: "bs-chatbot-header__button", "aria-label": "New chat", onClick: this.onNewChatClick }, h("slot", { key: '1d85439aa66bc42d0a479c90fa581f9ef4fd4245', name: "new-chat-icon" }, h(NewChatIcon, { key: 'adada1b7014df77327f48279fcab1468c9ebcb5e' }))), h("bs-tooltip", { key: '5854895579df420a25b8ad367aa31acf7a5afc05', class: "bs-chatbot-header__tooltip", placement: "top", "aria-hidden": "true" }, "New chat")), h("span", { key: 'd2ce725b9b07208ae540601afc99845adceaf110', class: "bs-chatbot-header__tooltip-wrapper" }, h("button", { key: 'a2dd3406bc6b557dd0323bffd843e21a9c4cbed6', type: "button", part: "history", class: "bs-chatbot-header__button", "aria-label": "History", onClick: this.onHistoryClick }, h("slot", { key: '2acf5d76225c710ed8da26d7b28a15b9906f6938', name: "history-icon" }, h(HistoryIcon, { key: 'a5452154bd46c7b0cfdfc77b584aed0078e9d808' }))), h("bs-tooltip", { key: 'da3ca7cdeb6182fb45e969e6cfb8232ec8410a17', class: "bs-chatbot-header__tooltip", placement: "top", "aria-hidden": "true" }, "History")), h("span", { key: 'c69f4bba7e92f341f57c77909dfa4f5365f0ec3a', class: "bs-chatbot-header__tooltip-wrapper" }, h("button", { key: 'cd42ff4dd756295b93948fb2c9a9b5b957c4e335', type: "button", part: "expand", class: "bs-chatbot-header__button", "aria-label": this.expanded ? 'Collapse' : 'Expand', "aria-pressed": this.expanded ? 'true' : 'false', onClick: this.onExpandClick }, h("slot", { key: '8c13063be20983c2c504042d3811c5dc4820f399', name: "expand-icon" }, h(ExpandIcon, { key: 'd508f7f4ff1a3b9e5622aab3775c786d85472b3e' }))), h("bs-tooltip", { key: 'e575d46939327fb304c3fdd6e78b169271b39848', class: "bs-chatbot-header__tooltip", placement: "top", "aria-hidden": "true" }, this.expanded ? 'Collapse' : 'Expand')), h("span", { key: '9b4bab65e49526f20b2760f3bc8d98fcefad30c7', class: "bs-chatbot-header__tooltip-wrapper" }, h("button", { key: '519b509a320894329ba716f604d185dd4d2746b0', type: "button", part: "close", class: "bs-chatbot-header__button", "aria-label": "Close", onClick: this.onCloseClick }, h("slot", { key: '4205d1d665053faf07ba13d929f5120f05806a89', name: "close-icon" }, h(CloseIcon, { key: '76bf4ab39f7e5fbdcdbb62d0baabb381192fbae7' }))), h("bs-tooltip", { key: 'cbebd979aef708c05e75bf835cd353834bcf83cb', class: "bs-chatbot-header__tooltip", placement: "top", "aria-hidden": "true" }, "Close")))));
|
|
78
78
|
}
|
|
79
79
|
static get is() { return "bs-chatbot-header"; }
|
|
80
80
|
static get encapsulation() { return "shadow"; }
|
|
@@ -105,7 +105,7 @@ export class BsChatbotResponseAction {
|
|
|
105
105
|
};
|
|
106
106
|
render() {
|
|
107
107
|
const hasSources = !!this.sourcesCount && this.sourcesCount > 0;
|
|
108
|
-
return (h("div", { key: '
|
|
108
|
+
return (h("div", { key: '580d2b0a324ade66bf1ae17b03634bf6d746b2c0', class: "bs-chatbot-response-action" }, h("button", { key: 'a623ca741c690bf3746974d7bac37efa43e5e754', type: "button", part: "like", class: "bs-chatbot-response-action__button", "aria-label": "Like", onClick: this.onLikeClick }, h("slot", { key: '22fd030c4828821509e5e5be53fd790d4bb98aa4', name: "like-icon" }, h(ThumbsUpIcon, { key: '2a1f8e1ad10f1d3c5f76de648b9a423c463677e1' }))), h("button", { key: 'f980f7d1f3df9aefa3a125563fe555132497e390', type: "button", part: "dislike", class: "bs-chatbot-response-action__button", "aria-label": "Dislike", onClick: this.onDislikeClick }, h("slot", { key: 'ceb6da0a1809e8fc2f889c3ad53cc2a480fecef5', name: "dislike-icon" }, h(ThumbsDownIcon, { key: '6b45b16449372ddc167e976791fbd0b5d7c7b897' }))), h("button", { key: 'e46e67457ee5f0f011e1f71de30c05a2ebcccd87', type: "button", part: "copy", class: "bs-chatbot-response-action__button", "aria-label": "Copy", onClick: this.onCopyClick }, h("slot", { key: 'f6173acf30c68012a2c99edc84b28955bc275d6a', name: "copy-icon" }, h(CopyIcon, { key: 'f1ca6efa24d6b65a270244a37978a0c791c2e897' }))), h("button", { key: '40a809efd3bf8d9fa1fc1975082e9d8a5dbfd55a', type: "button", part: "regenerate", class: "bs-chatbot-response-action__button", "aria-label": "Regenerate", onClick: this.onRegenerateClick }, h("slot", { key: 'b85d02a27fe9ba9f10e008255139a2f6221530c8', name: "regenerate-icon" }, h(RegenerateIcon, { key: '38eb20d38c90462d7b337f5f9b5e1320a8d0382b' }))), h("div", { key: '94d8abdc602ca68fc86b29c3440b5458916a9d5c', class: "bs-chatbot-response-action__menu-wrapper" }, h("button", { key: '9684224b6e5d246011d9b07dd6a7b7e09dc38c01', type: "button", part: "menu", class: "bs-chatbot-response-action__button", "aria-label": "More options", "aria-haspopup": "menu", "aria-expanded": this.menuOpen ? 'true' : 'false', onClick: this.onMenuClick }, h("slot", { key: '2bff489b2b6df0cb072b57335e73b6b17be19b0b', name: "menu-icon" }, h(MenuIcon, { key: 'f65fd8348f6b426a0230e5248d0ecc0707169d59' }))), this.menuOpen && (h("div", { key: '8ed1d83ed4e2fcc69a638dbe8579d4e77b8a70ff', class: "bs-chatbot-response-action__menu-popup" }, h("slot", { key: '7d61fb81284b9351a7beb876052024b4a8b58094', name: "menu" })))), hasSources && (h("button", { key: '8c858a645dbdaefafb27b0b799fbb64892aaae40', type: "button", part: "sources", class: "bs-chatbot-response-action__sources", onClick: this.onSourcesClick }, h("slot", { key: '3a9d96c3adae31db76a29d06f0a2467cd479055a', name: "sources-icon" }, h(SourcesIcon, { key: '12503e29497a08a5aaf1448d02791e735f274d09' })), h("span", { key: 'cb5a49e1892a5f5f1cfb92095514ea3b1da59c5f', class: "bs-chatbot-response-action__sources-label" }, this.sourcesCount, " ", this.sourcesCount === 1 ? 'source' : 'sources')))));
|
|
109
109
|
}
|
|
110
110
|
static get is() { return "bs-chatbot-response-action"; }
|
|
111
111
|
static get encapsulation() { return "shadow"; }
|
|
@@ -57,7 +57,7 @@ export class BsChatbotSourcesDrawer {
|
|
|
57
57
|
};
|
|
58
58
|
render() {
|
|
59
59
|
const displayCount = this.count ?? this.slottedCount;
|
|
60
|
-
return (h("div", { key: '
|
|
60
|
+
return (h("div", { key: 'cc40e8f428b35477177886763cabe96a2414a2b6', class: "bs-chatbot-sources-drawer", role: "region", "aria-label": this.heading }, h("div", { key: '13c34662ec82fcf7537564d12be6a7c4681631c4', class: "bs-chatbot-sources-drawer__header" }, h("div", { key: '8d82c247489192a70dd23cf7e35f08d59048e05a', class: "bs-chatbot-sources-drawer__title-group" }, h("h2", { key: 'b4eb825451c43a835b050edaf5ad559234a75124', part: "heading", class: "bs-chatbot-sources-drawer__heading" }, this.heading), displayCount > 0 && (h("span", { key: 'b6503e6525dd9a3464ad7cbab2225009392ce4cc', part: "count", class: "bs-chatbot-sources-drawer__count" }, displayCount))), h("button", { key: '26059a165b9e8a45b1902bb82e89c2fd693dfc85', type: "button", part: "collapse", class: "bs-chatbot-sources-drawer__collapse", "aria-label": "Collapse sources", onClick: this.onCollapseClick }, h("slot", { key: '720e1f4baff8d3764163934134966fd25aea0097', name: "collapse-icon" }, h(CaretRightIcon, { key: '779d738da467eb380801263bcffc1935ae5e9875' })))), h("div", { key: '29279a88a3f3b76c7418522af48b4bd9e652e453', part: "list", class: "bs-chatbot-sources-drawer__list" }, h("slot", { key: '85d006ab484a4427e363647b290d7a8e9229c7c6', onSlotchange: this.onSlotchange }))));
|
|
61
61
|
}
|
|
62
62
|
static get is() { return "bs-chatbot-sources-drawer"; }
|
|
63
63
|
static get encapsulation() { return "shadow"; }
|
package/dist/collection/components/bs-chatbot-suggestion-button/bs-chatbot-suggestion-button.js
CHANGED
|
@@ -45,7 +45,7 @@ export class BsChatbotSuggestionButton {
|
|
|
45
45
|
this.bsSelect.emit();
|
|
46
46
|
};
|
|
47
47
|
render() {
|
|
48
|
-
return (h("button", { key: '
|
|
48
|
+
return (h("button", { key: '3eed6a4eb359433fe682984f4628bdc46045f910', type: "button", part: "button", class: "bs-chatbot-suggestion-button", disabled: this.disabled, onClick: this.onClick }, h("slot", { key: '2e5bdcd63ed01ca0235bd6f74fa40a0e9e835863' })));
|
|
49
49
|
}
|
|
50
50
|
static get is() { return "bs-chatbot-suggestion-button"; }
|
|
51
51
|
static get encapsulation() { return "shadow"; }
|
|
@@ -33,7 +33,7 @@ export class BsCheckboxSkeleton {
|
|
|
33
33
|
* (unusual) default `bs-checkbox` itself uses. */
|
|
34
34
|
size = 'lg';
|
|
35
35
|
render() {
|
|
36
|
-
return (h("span", { key: '
|
|
36
|
+
return (h("span", { key: '062c3abd38665132c305089335d3eb993c910061', part: "container", class: "bs-checkbox-skeleton", role: "status", "aria-label": "Loading" }, h("span", { key: 'bc682511b4e316e13460186388e13aa09b77b139', part: "box", class: `bs-checkbox-skeleton__box bs-checkbox-skeleton__box--${this.size}` }), h("span", { key: '20dc4a2ebff2e678a990cb244359bec2f515d742', part: "label", class: "bs-checkbox-skeleton__label" })));
|
|
37
37
|
}
|
|
38
38
|
static get is() { return "bs-checkbox-skeleton"; }
|
|
39
39
|
static get encapsulation() { return "shadow"; }
|
|
@@ -99,6 +99,25 @@ describe('bs-data-table', () => {
|
|
|
99
99
|
expect(cell.querySelector('img')).toBeNull();
|
|
100
100
|
expect(cell.textContent).toBe('<img src=x onerror="window.__xss = true">');
|
|
101
101
|
});
|
|
102
|
+
it('renders rich cell content: a link and a web component become real elements', async () => {
|
|
103
|
+
const { root, waitForChanges } = await render(h("bs-data-table", { columns: columns, rows: rows, cellRenderer: (row) => `<a href="/users/${row.id}">Open</a><bs-badge variant="success">Active</bs-badge>` }));
|
|
104
|
+
await waitForChanges();
|
|
105
|
+
const cell = root.shadowRoot.querySelector('tbody td');
|
|
106
|
+
expect(cell.querySelector('a')).toEqualAttribute('href', '/users/1');
|
|
107
|
+
const badge = cell.querySelector('bs-badge');
|
|
108
|
+
expect(badge).not.toBeNull();
|
|
109
|
+
expect(badge.shadowRoot).not.toBeNull(); // upgraded: it is a live component, not inert text
|
|
110
|
+
});
|
|
111
|
+
it('applies cellRenderer to every cell, and does NOT escape what it returns (the caller must)', async () => {
|
|
112
|
+
const unsafeRows = [{ id: 1, name: '<img src=x onerror="window.__xss2 = true">', status: 'Active' }];
|
|
113
|
+
const unsafe = await render(h("bs-data-table", { columns: columns, rows: unsafeRows, cellRenderer: (row, col) => String(row[col.key]) }));
|
|
114
|
+
expect(unsafe.root.shadowRoot.querySelector('tbody td').querySelector('img')).not.toBeNull();
|
|
115
|
+
const esc = (v) => String(v).replace(/[&<>"']/g, c => ({ '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' })[c]);
|
|
116
|
+
const safe = await render(h("bs-data-table", { columns: columns, rows: unsafeRows, cellRenderer: (row, col) => esc(row[col.key]) }));
|
|
117
|
+
const cell = safe.root.shadowRoot.querySelector('tbody td');
|
|
118
|
+
expect(cell.querySelector('img')).toBeNull();
|
|
119
|
+
expect(cell.textContent).toBe('<img src=x onerror="window.__xss2 = true">');
|
|
120
|
+
});
|
|
102
121
|
it('still allows cellRenderer to render trusted custom HTML when explicitly supplied', async () => {
|
|
103
122
|
const { root } = await render(h("bs-data-table", { columns: columns, rows: rows, cellRenderer: () => '<button type="button">Edit</button>' }));
|
|
104
123
|
const cell = root.shadowRoot.querySelector('tbody td');
|
|
@@ -29,8 +29,22 @@ export class BsDataTable {
|
|
|
29
29
|
sortColumn;
|
|
30
30
|
sortDirection = 'asc';
|
|
31
31
|
selectable = false;
|
|
32
|
-
/** Optional custom cell renderer,
|
|
33
|
-
*
|
|
32
|
+
/** Optional custom cell renderer, for rich cells such as a status badge, a link or an actions
|
|
33
|
+
* column. It returns an **HTML string** that is inserted into the cell as real markup
|
|
34
|
+
* (`innerHTML`), so links, buttons, `<img>` and other web components (e.g. `<bs-badge>`) all render.
|
|
35
|
+
*
|
|
36
|
+
* **When set it renders every cell, not just the special ones** -- return the plain value for
|
|
37
|
+
* ordinary columns too. And **the returned string is not escaped or sanitized** (same trust
|
|
38
|
+
* model as React's `dangerouslySetInnerHTML`): escape any untrusted row data you put in it, plain
|
|
39
|
+
* columns included, or it will be interpreted as HTML. Without a `cellRenderer`, values are
|
|
40
|
+
* rendered as escaped text.
|
|
41
|
+
*
|
|
42
|
+
* The markup is static HTML -- attach behavior yourself, e.g. one `click` listener on the table
|
|
43
|
+
* that reads `event.composedPath()[0]` (events from inside the shadow root are retargeted to the
|
|
44
|
+
* table itself).
|
|
45
|
+
*
|
|
46
|
+
* Function props are JS-property-only, same as array props -- there is no attribute equivalent.
|
|
47
|
+
* Falls back to the raw cell value (as escaped text) when unset. */
|
|
34
48
|
cellRenderer;
|
|
35
49
|
bsSort;
|
|
36
50
|
bsRowSelect;
|
|
@@ -71,11 +85,11 @@ export class BsDataTable {
|
|
|
71
85
|
}
|
|
72
86
|
}
|
|
73
87
|
render() {
|
|
74
|
-
return (h("table", { key: '
|
|
88
|
+
return (h("table", { key: '7ea79a70148513512cdba2f8cb8d5a5c7ae09706', part: "table", class: "bs-data-table" }, h("thead", { key: 'e9cf73cbba196e9caf4b03a837866a5370c13e19', part: "head" }, h("tr", { key: 'a33fbd57f1925e34c6e7ce292b6945d2ee5c6113' }, this.selectable && (h("th", { key: '876948b66e54ae68d6aa6148c962781223fa0441', class: "bs-data-table__select-col" }, this.rows.length > 0 && (h("input", { key: 'cf8f26258bcee486190e3ac4b3d5ce4715784d5f', type: "checkbox", "aria-label": "Select all rows", checked: this.selectedIds.size > 0 && this.selectedIds.size === this.rows.length, indeterminate: this.selectedIds.size > 0 && this.selectedIds.size < this.rows.length, onChange: this.onSelectAllChange })))), this.columns.map(column => {
|
|
75
89
|
const isSorted = this.sortColumn === column.key;
|
|
76
90
|
const ariaSort = column.sortable ? (isSorted ? (this.sortDirection === 'asc' ? 'ascending' : 'descending') : 'none') : undefined;
|
|
77
91
|
return (h("th", { part: "header-cell", class: "bs-data-table__header-cell", "aria-sort": ariaSort }, column.sortable ? (h("button", { type: "button", class: "bs-data-table__sort-button", onClick: () => this.onHeaderClick(column) }, column.label, isSorted && h("span", { class: "bs-data-table__sort-indicator" }, this.sortDirection === 'asc' ? ' ▲' : ' ▼'))) : (column.label)));
|
|
78
|
-
}))), h("tbody", { key: '
|
|
92
|
+
}))), h("tbody", { key: '3a0c2ce6fea27797b855ee2b3c724d0e99471d28', part: "body" }, this.rows.map(row => (h("tr", { part: "row", class: "bs-data-table__row" }, this.selectable && (h("td", { class: "bs-data-table__select-col" }, h("input", { type: "checkbox", checked: this.selectedIds.has(row.id), onChange: ev => this.onRowCheckboxChange(row, ev) }))), this.columns.map(column => this.cellRenderer ? (
|
|
79
93
|
// cellRenderer is a developer-supplied, trusted function (JS-property-only, never
|
|
80
94
|
// derived from untrusted input) -- its HTML output is intentionally not escaped,
|
|
81
95
|
// same trust model as React's dangerouslySetInnerHTML.
|
|
@@ -228,7 +242,7 @@ export class BsDataTable {
|
|
|
228
242
|
"optional": true,
|
|
229
243
|
"docs": {
|
|
230
244
|
"tags": [],
|
|
231
|
-
"text": "Optional custom cell renderer, e.g. for
|
|
245
|
+
"text": "Optional custom cell renderer, for rich cells such as a status badge, a link or an actions\ncolumn. It returns an **HTML string** that is inserted into the cell as real markup\n(`innerHTML`), so links, buttons, `<img>` and other web components (e.g. `<bs-badge>`) all render.\n\n**When set it renders every cell, not just the special ones** -- return the plain value for\nordinary columns too. And **the returned string is not escaped or sanitized** (same trust\nmodel as React's `dangerouslySetInnerHTML`): escape any untrusted row data you put in it, plain\ncolumns included, or it will be interpreted as HTML. Without a `cellRenderer`, values are\nrendered as escaped text.\n\nThe markup is static HTML -- attach behavior yourself, e.g. one `click` listener on the table\nthat reads `event.composedPath()[0]` (events from inside the shadow root are retargeted to the\ntable itself).\n\nFunction props are JS-property-only, same as array props -- there is no attribute equivalent.\nFalls back to the raw cell value (as escaped text) when unset."
|
|
232
246
|
},
|
|
233
247
|
"getter": false,
|
|
234
248
|
"setter": false
|
|
@@ -44,11 +44,18 @@ export const WithCustomCellRenderer = {
|
|
|
44
44
|
const table = document.createElement('bs-data-table');
|
|
45
45
|
table.columns = [...columns, { key: 'actions', label: 'Actions' }];
|
|
46
46
|
table.rows = rows;
|
|
47
|
+
// cellRenderer renders EVERY cell and its output is not escaped, so plain columns are escaped
|
|
48
|
+
// here too -- copying `String(row[column.key])` unescaped would make untrusted row data HTML.
|
|
49
|
+
const escapeHtml = (value) => String(value ?? '').replace(/[&<>"']/g, c => ({ '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' })[c]);
|
|
47
50
|
table.cellRenderer = (row, column) => {
|
|
48
51
|
if (column.key === 'actions') {
|
|
49
52
|
return `<button type="button">Edit</button>`;
|
|
50
53
|
}
|
|
51
|
-
|
|
54
|
+
if (column.key === 'status') {
|
|
55
|
+
// Rich content: a web component in the cell.
|
|
56
|
+
return `<bs-badge variant="${row.status === 'Active' ? 'success' : 'neutral'}">${escapeHtml(row.status)}</bs-badge>`;
|
|
57
|
+
}
|
|
58
|
+
return escapeHtml(row[column.key]);
|
|
52
59
|
};
|
|
53
60
|
return table;
|
|
54
61
|
},
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
import { render, h, describe, it, expect } from "@stencil/vitest";
|
|
2
|
+
const days = (root) => Array.from(root.shadowRoot.querySelectorAll('[part~="day"]'));
|
|
3
|
+
const day = (root, iso) => root.shadowRoot.querySelector(`[data-date="${iso}"]`);
|
|
4
|
+
describe('bs-datepicker', () => {
|
|
5
|
+
it('renders a 6-row grid starting on Sunday, matching the Figma (September 2026)', async () => {
|
|
6
|
+
const { root } = await render(h("bs-datepicker", { value: "2026-09-16" }));
|
|
7
|
+
const cells = days(root);
|
|
8
|
+
expect(cells.length).toBe(42);
|
|
9
|
+
// Sept 1 2026 is a Tuesday, so the grid leads with Sunday 30 August.
|
|
10
|
+
expect(cells[0].dataset.date).toBe('2026-08-30');
|
|
11
|
+
expect(cells[41].dataset.date).toBe('2026-10-10');
|
|
12
|
+
const weekdays = Array.from(root.shadowRoot.querySelectorAll('[part="weekday"]')).map(e => e.textContent);
|
|
13
|
+
expect(weekdays).toEqual(['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']);
|
|
14
|
+
});
|
|
15
|
+
it('can start the week on Monday', async () => {
|
|
16
|
+
const { root } = await render(h("bs-datepicker", { value: "2026-09-16", firstDayOfWeek: 1 }));
|
|
17
|
+
expect(days(root)[0].dataset.date).toBe('2026-08-31');
|
|
18
|
+
expect(root.shadowRoot.querySelector('[part="weekday"]').textContent).toBe('Mon');
|
|
19
|
+
});
|
|
20
|
+
it('shows the selected date in the title and marks it selected', async () => {
|
|
21
|
+
const { root } = await render(h("bs-datepicker", { value: "2026-09-16" }));
|
|
22
|
+
expect(root.shadowRoot.querySelector('[part="title"]').textContent).toBe('16 September 2026');
|
|
23
|
+
expect(day(root, '2026-09-16').getAttribute('part')).toContain('selected');
|
|
24
|
+
});
|
|
25
|
+
it('marks days from adjacent months as outside', async () => {
|
|
26
|
+
const { root } = await render(h("bs-datepicker", { value: "2026-09-16" }));
|
|
27
|
+
expect(day(root, '2026-08-31').getAttribute('part')).toContain('outside');
|
|
28
|
+
expect(day(root, '2026-09-01').getAttribute('part')).not.toContain('outside');
|
|
29
|
+
});
|
|
30
|
+
it('selects a day on click, updates value and emits bsChange', async () => {
|
|
31
|
+
const { root, waitForChanges } = await render(h("bs-datepicker", { value: "2026-09-16" }));
|
|
32
|
+
const events = [];
|
|
33
|
+
root.addEventListener('bsChange', (e) => events.push(e.detail));
|
|
34
|
+
day(root, '2026-09-20').click();
|
|
35
|
+
await waitForChanges();
|
|
36
|
+
expect(root.value).toBe('2026-09-20');
|
|
37
|
+
expect(events).toEqual([{ value: '2026-09-20' }]);
|
|
38
|
+
});
|
|
39
|
+
it('does not emit when value is set programmatically, and jumps to that month', async () => {
|
|
40
|
+
const { root, waitForChanges } = await render(h("bs-datepicker", { value: "2026-09-16" }));
|
|
41
|
+
let fired = 0;
|
|
42
|
+
root.addEventListener('bsChange', () => fired++);
|
|
43
|
+
root.value = '2027-01-05';
|
|
44
|
+
await waitForChanges();
|
|
45
|
+
expect(fired).toBe(0);
|
|
46
|
+
expect(day(root, '2027-01-05').getAttribute('part')).toContain('selected');
|
|
47
|
+
});
|
|
48
|
+
it('navigates months with the prev/next buttons', async () => {
|
|
49
|
+
const { root, waitForChanges } = await render(h("bs-datepicker", { value: "2026-09-16" }));
|
|
50
|
+
root.shadowRoot.querySelector('[part="next"]').click();
|
|
51
|
+
await waitForChanges();
|
|
52
|
+
expect(day(root, '2026-10-15')).not.toBeNull();
|
|
53
|
+
expect(day(root, '2026-10-15').getAttribute('part')).not.toContain('outside');
|
|
54
|
+
root.shadowRoot.querySelector('[part="prev"]').click();
|
|
55
|
+
root.shadowRoot.querySelector('[part="prev"]').click();
|
|
56
|
+
await waitForChanges();
|
|
57
|
+
expect(day(root, '2026-08-15').getAttribute('part')).not.toContain('outside');
|
|
58
|
+
});
|
|
59
|
+
it('disables days outside min/max and ignores clicks on them', async () => {
|
|
60
|
+
const { root, waitForChanges } = await render(h("bs-datepicker", { value: "2026-09-16", min: "2026-09-10", max: "2026-09-20" }));
|
|
61
|
+
expect(day(root, '2026-09-09')).toHaveAttribute('disabled');
|
|
62
|
+
expect(day(root, '2026-09-21')).toHaveAttribute('disabled');
|
|
63
|
+
expect(day(root, '2026-09-10')).not.toHaveAttribute('disabled');
|
|
64
|
+
day(root, '2026-09-09').click();
|
|
65
|
+
await waitForChanges();
|
|
66
|
+
expect(root.value).toBe('2026-09-16');
|
|
67
|
+
});
|
|
68
|
+
it('keeps a single tab stop (roving tabindex) and moves focus with the arrow keys', async () => {
|
|
69
|
+
const { root, waitForChanges } = await render(h("bs-datepicker", { value: "2026-09-16" }));
|
|
70
|
+
expect(days(root).filter(d => d.tabIndex === 0).map(d => d.dataset.date)).toEqual(['2026-09-16']);
|
|
71
|
+
day(root, '2026-09-16').dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowDown', bubbles: true }));
|
|
72
|
+
await waitForChanges();
|
|
73
|
+
expect(days(root).filter(d => d.tabIndex === 0).map(d => d.dataset.date)).toEqual(['2026-09-23']);
|
|
74
|
+
});
|
|
75
|
+
it('PageDown moves a month and clamps the day (Jan 31 -> Feb 28)', async () => {
|
|
76
|
+
const { root, waitForChanges } = await render(h("bs-datepicker", { value: "2027-01-31" }));
|
|
77
|
+
day(root, '2027-01-31').dispatchEvent(new KeyboardEvent('keydown', { key: 'PageDown', bubbles: true }));
|
|
78
|
+
await waitForChanges();
|
|
79
|
+
expect(days(root).filter(d => d.tabIndex === 0).map(d => d.dataset.date)).toEqual(['2027-02-28']);
|
|
80
|
+
});
|
|
81
|
+
describe('month/year dropdowns', () => {
|
|
82
|
+
const triggers = (root) => root.shadowRoot.querySelectorAll('bs-input');
|
|
83
|
+
const items = (root) => Array.from(root.shadowRoot.querySelectorAll('[part="menu"] bs-menu-item'));
|
|
84
|
+
it('renders a dropdown trigger per field showing the current month and year', async () => {
|
|
85
|
+
const { root } = await render(h("bs-datepicker", { value: "2026-09-16" }));
|
|
86
|
+
const t = triggers(root);
|
|
87
|
+
expect(t.length).toBe(2);
|
|
88
|
+
expect(t[0].type).toBe('dropdown');
|
|
89
|
+
expect(t[0].value).toBe('September');
|
|
90
|
+
expect(t[1].value).toBe('2026');
|
|
91
|
+
expect(root.shadowRoot.querySelector('[part="menu"]')).toBeNull();
|
|
92
|
+
});
|
|
93
|
+
it('opens a list of all 12 months with a checkmark on the current one', async () => {
|
|
94
|
+
const { root, waitForChanges } = await render(h("bs-datepicker", { value: "2026-09-16" }));
|
|
95
|
+
triggers(root)[0].dispatchEvent(new CustomEvent('bsOpen', { detail: true }));
|
|
96
|
+
await waitForChanges();
|
|
97
|
+
const list = items(root);
|
|
98
|
+
expect(list.length).toBe(12);
|
|
99
|
+
const checked = list.filter(i => i.querySelector('svg'));
|
|
100
|
+
expect(checked.length).toBe(1);
|
|
101
|
+
expect(checked[0].textContent).toBe('September');
|
|
102
|
+
});
|
|
103
|
+
it('picking a month changes the displayed month and closes the list', async () => {
|
|
104
|
+
const { root, waitForChanges } = await render(h("bs-datepicker", { value: "2026-09-16" }));
|
|
105
|
+
triggers(root)[0].dispatchEvent(new CustomEvent('bsOpen', { detail: true }));
|
|
106
|
+
await waitForChanges();
|
|
107
|
+
items(root)[5].dispatchEvent(new CustomEvent('bsSelect'));
|
|
108
|
+
await waitForChanges();
|
|
109
|
+
expect(root.shadowRoot.querySelector('[part="menu"]')).toBeNull();
|
|
110
|
+
expect(triggers(root)[0].value).toBe('June');
|
|
111
|
+
expect(day(root, '2026-06-15').getAttribute('part')).not.toContain('outside');
|
|
112
|
+
// Browsing doesn't change the selection.
|
|
113
|
+
expect(root.value).toBe('2026-09-16');
|
|
114
|
+
});
|
|
115
|
+
it('picking a year changes the displayed year', async () => {
|
|
116
|
+
const { root, waitForChanges } = await render(h("bs-datepicker", { value: "2026-09-16" }));
|
|
117
|
+
triggers(root)[1].dispatchEvent(new CustomEvent('bsOpen', { detail: true }));
|
|
118
|
+
await waitForChanges();
|
|
119
|
+
const target = items(root).find(i => i.textContent === '2028');
|
|
120
|
+
target.dispatchEvent(new CustomEvent('bsSelect'));
|
|
121
|
+
await waitForChanges();
|
|
122
|
+
expect(triggers(root)[1].value).toBe('2028');
|
|
123
|
+
expect(day(root, '2028-09-15')).not.toBeNull();
|
|
124
|
+
});
|
|
125
|
+
it('limits the year list to min/max', async () => {
|
|
126
|
+
const { root, waitForChanges } = await render(h("bs-datepicker", { value: "2026-09-16", min: "2025-01-01", max: "2027-12-31" }));
|
|
127
|
+
triggers(root)[1].dispatchEvent(new CustomEvent('bsOpen', { detail: true }));
|
|
128
|
+
await waitForChanges();
|
|
129
|
+
expect(items(root).map(i => i.textContent)).toEqual(['2025', '2026', '2027']);
|
|
130
|
+
});
|
|
131
|
+
it('closes on Escape', async () => {
|
|
132
|
+
const { root, waitForChanges } = await render(h("bs-datepicker", { value: "2026-09-16" }));
|
|
133
|
+
triggers(root)[0].dispatchEvent(new CustomEvent('bsOpen', { detail: true }));
|
|
134
|
+
await waitForChanges();
|
|
135
|
+
root.shadowRoot.querySelector('.bs-datepicker__dropdown').dispatchEvent(new KeyboardEvent('keydown', { key: 'Escape', bubbles: true }));
|
|
136
|
+
await waitForChanges();
|
|
137
|
+
expect(root.shadowRoot.querySelector('[part="menu"]')).toBeNull();
|
|
138
|
+
});
|
|
139
|
+
});
|
|
140
|
+
describe('range', () => {
|
|
141
|
+
it('renders start/end fields instead of dropdowns, and highlights the days between', async () => {
|
|
142
|
+
const { root } = await render(h("bs-datepicker", { range: true, start: "2026-09-11", end: "2026-09-16" }));
|
|
143
|
+
const fields = root.shadowRoot.querySelectorAll('bs-input');
|
|
144
|
+
expect(fields.length).toBe(2);
|
|
145
|
+
expect(fields[0].label).toBe('Start date');
|
|
146
|
+
expect(fields[0].value).toBe('11 Sept 2026');
|
|
147
|
+
const inRange = Array.from(root.shadowRoot.querySelectorAll('[part~="in-range"]')).map(e => e.dataset.date);
|
|
148
|
+
expect(inRange).toEqual(['2026-09-12', '2026-09-13', '2026-09-14', '2026-09-15']);
|
|
149
|
+
expect(day(root, '2026-09-11').getAttribute('part')).toContain('selected');
|
|
150
|
+
expect(day(root, '2026-09-16').getAttribute('part')).toContain('selected');
|
|
151
|
+
});
|
|
152
|
+
it('two clicks pick a range: first emits an open range, second completes it', async () => {
|
|
153
|
+
const { root, waitForChanges } = await render(h("bs-datepicker", { range: true, start: "2026-09-01", end: "2026-09-02" }));
|
|
154
|
+
const events = [];
|
|
155
|
+
root.addEventListener('bsChange', (e) => events.push(e.detail));
|
|
156
|
+
day(root, '2026-09-10').click();
|
|
157
|
+
await waitForChanges();
|
|
158
|
+
day(root, '2026-09-15').click();
|
|
159
|
+
await waitForChanges();
|
|
160
|
+
expect(events).toEqual([
|
|
161
|
+
{ start: '2026-09-10', end: '' },
|
|
162
|
+
{ start: '2026-09-10', end: '2026-09-15' },
|
|
163
|
+
]);
|
|
164
|
+
expect(root.start).toBe('2026-09-10');
|
|
165
|
+
expect(root.end).toBe('2026-09-15');
|
|
166
|
+
});
|
|
167
|
+
it('a click before the start restarts the range instead of reversing it', async () => {
|
|
168
|
+
const { root, waitForChanges } = await render(h("bs-datepicker", { range: true, start: "2026-09-11" }));
|
|
169
|
+
day(root, '2026-09-05').click();
|
|
170
|
+
await waitForChanges();
|
|
171
|
+
expect(root.start).toBe('2026-09-05');
|
|
172
|
+
expect(root.end).toBe('');
|
|
173
|
+
});
|
|
174
|
+
it('a click after a completed range starts a new one', async () => {
|
|
175
|
+
const { root, waitForChanges } = await render(h("bs-datepicker", { range: true, start: "2026-09-11", end: "2026-09-16" }));
|
|
176
|
+
day(root, '2026-09-20').click();
|
|
177
|
+
await waitForChanges();
|
|
178
|
+
expect(root.start).toBe('2026-09-20');
|
|
179
|
+
expect(root.end).toBe('');
|
|
180
|
+
});
|
|
181
|
+
});
|
|
182
|
+
});
|