@mcp-b/web-components 0.2.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/LICENSE +21 -0
- package/README.md +49 -0
- package/dist/accordion-B1Q3kuP_.d.ts +373 -0
- package/dist/accordion-item-DvPfhpm8.js +307 -0
- package/dist/accordion-item-bPRIahNn.d.ts +63 -0
- package/dist/accordion-zDr-Br4V.js +483 -0
- package/dist/action-bar-CYsjmhwP.d.ts +29 -0
- package/dist/action-bar-CjN_UcnP.js +56 -0
- package/dist/alert-dialog-4CnO3Nb5.d.ts +60 -0
- package/dist/alert-dialog-D25Oi_TS.js +126 -0
- package/dist/avatar-Bje_KpZo.d.ts +141 -0
- package/dist/avatar-CRP0kW3x.js +224 -0
- package/dist/badge-Ct95U4UO.js +301 -0
- package/dist/badge-D1DNQrWn.d.ts +106 -0
- package/dist/breadcrumb-BxZ-nQE5.d.ts +365 -0
- package/dist/breadcrumb-item-BC454oQe.d.ts +59 -0
- package/dist/breadcrumb-item-P5pdq_gE.js +151 -0
- package/dist/breadcrumb-uURhiqWJ.js +384 -0
- package/dist/button-5k_aL_gD.js +802 -0
- package/dist/button-BQofnUt4.d.ts +354 -0
- package/dist/button-group-BydvJTQy.js +197 -0
- package/dist/button-group-COodHeuB.d.ts +155 -0
- package/dist/callout-B8zTf8Go.js +188 -0
- package/dist/callout-DFwPao36.d.ts +103 -0
- package/dist/card-BYDzdMAU.d.ts +177 -0
- package/dist/card-DIg1-X2G.js +332 -0
- package/dist/carousel-Bktu7wrD.js +843 -0
- package/dist/carousel-DQITCtEY.d.ts +423 -0
- package/dist/carousel-item-B5-X31Ha.js +79 -0
- package/dist/carousel-item-BB3jL2tk.d.ts +34 -0
- package/dist/cdn/loader.js +530 -0
- package/dist/checkbox-D6r7PVPj.js +641 -0
- package/dist/checkbox-DoFcDEKB.d.ts +354 -0
- package/dist/checkbox-group-CLvNAO_F.js +201 -0
- package/dist/checkbox-group-Cnh8rAn4.d.ts +152 -0
- package/dist/color-input-Bky89xg_.d.ts +470 -0
- package/dist/color-input-DPIxi9wR.js +894 -0
- package/dist/color-picker-adwOmtRl.js +1240 -0
- package/dist/color-picker-wQw8bPsq.d.ts +360 -0
- package/dist/combobox-B6al50UG.js +1693 -0
- package/dist/combobox-item-D2H1CMxC.d.ts +714 -0
- package/dist/combobox-item-yM6tDrGG.js +225 -0
- package/dist/comparison-B1-nMwmp.d.ts +134 -0
- package/dist/comparison-CyqKrCN-.js +435 -0
- package/dist/components/accordion/accordion.d.ts +2 -0
- package/dist/components/accordion/accordion.js +2 -0
- package/dist/components/accordion-item/accordion-item.d.ts +2 -0
- package/dist/components/accordion-item/accordion-item.js +2 -0
- package/dist/components/action-bar/action-bar.d.ts +2 -0
- package/dist/components/action-bar/action-bar.js +2 -0
- package/dist/components/alert-dialog/alert-dialog.d.ts +2 -0
- package/dist/components/alert-dialog/alert-dialog.js +2 -0
- package/dist/components/avatar/avatar.d.ts +2 -0
- package/dist/components/avatar/avatar.js +2 -0
- package/dist/components/badge/badge.d.ts +2 -0
- package/dist/components/badge/badge.js +2 -0
- package/dist/components/breadcrumb/breadcrumb.d.ts +2 -0
- package/dist/components/breadcrumb/breadcrumb.js +2 -0
- package/dist/components/breadcrumb-item/breadcrumb-item.d.ts +2 -0
- package/dist/components/breadcrumb-item/breadcrumb-item.js +2 -0
- package/dist/components/button/button.d.ts +2 -0
- package/dist/components/button/button.js +2 -0
- package/dist/components/button-group/button-group.d.ts +2 -0
- package/dist/components/button-group/button-group.js +2 -0
- package/dist/components/callout/callout.d.ts +2 -0
- package/dist/components/callout/callout.js +2 -0
- package/dist/components/card/card.d.ts +2 -0
- package/dist/components/card/card.js +2 -0
- package/dist/components/carousel/carousel.d.ts +2 -0
- package/dist/components/carousel/carousel.js +2 -0
- package/dist/components/carousel-item/carousel-item.d.ts +2 -0
- package/dist/components/carousel-item/carousel-item.js +2 -0
- package/dist/components/checkbox/checkbox.d.ts +2 -0
- package/dist/components/checkbox/checkbox.js +2 -0
- package/dist/components/checkbox-group/checkbox-group.d.ts +2 -0
- package/dist/components/checkbox-group/checkbox-group.js +2 -0
- package/dist/components/color-input/color-input.d.ts +2 -0
- package/dist/components/color-input/color-input.js +2 -0
- package/dist/components/color-picker/color-picker.d.ts +2 -0
- package/dist/components/color-picker/color-picker.js +2 -0
- package/dist/components/combobox/combobox.d.ts +2 -0
- package/dist/components/combobox/combobox.js +2 -0
- package/dist/components/combobox-item/combobox-item.d.ts +2 -0
- package/dist/components/combobox-item/combobox-item.js +2 -0
- package/dist/components/comparison/comparison.d.ts +2 -0
- package/dist/components/comparison/comparison.js +2 -0
- package/dist/components/copy/copy.d.ts +2 -0
- package/dist/components/copy/copy.js +291 -0
- package/dist/components/data-table/data-table.d.ts +2 -0
- package/dist/components/data-table/data-table.js +2 -0
- package/dist/components/date/date.d.ts +2 -0
- package/dist/components/date/date.js +2 -0
- package/dist/components/dialog/dialog.d.ts +2 -0
- package/dist/components/dialog/dialog.js +2 -0
- package/dist/components/divider/divider.d.ts +2 -0
- package/dist/components/divider/divider.js +2 -0
- package/dist/components/dropdown/dropdown.d.ts +2 -0
- package/dist/components/dropdown/dropdown.js +2 -0
- package/dist/components/dropdown-item/dropdown-item.d.ts +2 -0
- package/dist/components/dropdown-item/dropdown-item.js +2 -0
- package/dist/components/empty-result/empty-result.d.ts +2 -0
- package/dist/components/empty-result/empty-result.js +2 -0
- package/dist/components/empty-state/empty-state.d.ts +2 -0
- package/dist/components/empty-state/empty-state.js +2 -0
- package/dist/components/expander/expander.d.ts +2 -0
- package/dist/components/expander/expander.js +2 -0
- package/dist/components/field/field.d.ts +2 -0
- package/dist/components/field/field.js +2 -0
- package/dist/components/file-input/file-input.d.ts +2 -0
- package/dist/components/file-input/file-input.js +2 -0
- package/dist/components/filter-bar/filter-bar.d.ts +2 -0
- package/dist/components/filter-bar/filter-bar.js +2 -0
- package/dist/components/form-section/form-section.d.ts +2 -0
- package/dist/components/form-section/form-section.js +2 -0
- package/dist/components/icon/icon.d.ts +2 -0
- package/dist/components/icon/icon.js +2 -0
- package/dist/components/include/include.d.ts +2 -0
- package/dist/components/include/include.js +2 -0
- package/dist/components/index.d.ts +85 -0
- package/dist/components/index.js +86 -0
- package/dist/components/infinite-scroller/infinite-scroller.d.ts +2 -0
- package/dist/components/infinite-scroller/infinite-scroller.js +2 -0
- package/dist/components/intersection-observer/intersection-observer.d.ts +2 -0
- package/dist/components/intersection-observer/intersection-observer.js +2 -0
- package/dist/components/listbox/listbox.d.ts +2 -0
- package/dist/components/listbox/listbox.js +2 -0
- package/dist/components/listbox-item/listbox-item.d.ts +2 -0
- package/dist/components/listbox-item/listbox-item.js +2 -0
- package/dist/components/lorem-ipsum/lorem-ipsum.d.ts +2 -0
- package/dist/components/lorem-ipsum/lorem-ipsum.js +2 -0
- package/dist/components/meter/meter.d.ts +2 -0
- package/dist/components/meter/meter.js +2 -0
- package/dist/components/metric/metric.d.ts +2 -0
- package/dist/components/metric/metric.js +2 -0
- package/dist/components/metric-grid/metric-grid.d.ts +2 -0
- package/dist/components/metric-grid/metric-grid.js +2 -0
- package/dist/components/mutation-observer/mutation-observer.d.ts +2 -0
- package/dist/components/mutation-observer/mutation-observer.js +2 -0
- package/dist/components/navicon/navicon.d.ts +2 -0
- package/dist/components/navicon/navicon.js +2 -0
- package/dist/components/number/number.d.ts +2 -0
- package/dist/components/number/number.js +2 -0
- package/dist/components/number-field/number-field.d.ts +2 -0
- package/dist/components/number-field/number-field.js +2 -0
- package/dist/components/pagination/pagination.d.ts +2 -0
- package/dist/components/pagination/pagination.js +2 -0
- package/dist/components/popover/popover.d.ts +2 -0
- package/dist/components/popover/popover.js +2 -0
- package/dist/components/preview-card/preview-card.d.ts +2 -0
- package/dist/components/preview-card/preview-card.js +2 -0
- package/dist/components/progress/progress.d.ts +2 -0
- package/dist/components/progress/progress.js +2 -0
- package/dist/components/radio/radio.d.ts +2 -0
- package/dist/components/radio/radio.js +2 -0
- package/dist/components/radio-item/radio-item.d.ts +2 -0
- package/dist/components/radio-item/radio-item.js +2 -0
- package/dist/components/random-content/random-content.d.ts +2 -0
- package/dist/components/random-content/random-content.js +2 -0
- package/dist/components/rating/rating.d.ts +2 -0
- package/dist/components/rating/rating.js +2 -0
- package/dist/components/resize-observer/resize-observer.d.ts +2 -0
- package/dist/components/resize-observer/resize-observer.js +2 -0
- package/dist/components/scroll-area/scroll-area.d.ts +2 -0
- package/dist/components/scroll-area/scroll-area.js +2 -0
- package/dist/components/scroller/scroller.d.ts +2 -0
- package/dist/components/scroller/scroller.js +2 -0
- package/dist/components/search-list/search-list.d.ts +2 -0
- package/dist/components/search-list/search-list.js +2 -0
- package/dist/components/select/select.d.ts +2 -0
- package/dist/components/select/select.js +2 -0
- package/dist/components/selection-summary/selection-summary.d.ts +2 -0
- package/dist/components/selection-summary/selection-summary.js +2 -0
- package/dist/components/share/share.d.ts +2 -0
- package/dist/components/share/share.js +2 -0
- package/dist/components/slide-activator/slide-activator.d.ts +2 -0
- package/dist/components/slide-activator/slide-activator.js +2 -0
- package/dist/components/slider/slider.d.ts +2 -0
- package/dist/components/slider/slider.js +2 -0
- package/dist/components/sparkline/sparkline.d.ts +2 -0
- package/dist/components/sparkline/sparkline.js +2 -0
- package/dist/components/spinner/spinner.d.ts +2 -0
- package/dist/components/spinner/spinner.js +2 -0
- package/dist/components/splitter/splitter.d.ts +2 -0
- package/dist/components/splitter/splitter.js +2 -0
- package/dist/components/switch/switch.d.ts +2 -0
- package/dist/components/switch/switch.js +2 -0
- package/dist/components/tab/tab.d.ts +2 -0
- package/dist/components/tab/tab.js +2 -0
- package/dist/components/tab-list/tab-list.d.ts +2 -0
- package/dist/components/tab-list/tab-list.js +2 -0
- package/dist/components/tab-panel/tab-panel.d.ts +2 -0
- package/dist/components/tab-panel/tab-panel.js +2 -0
- package/dist/components/text-area/text-area.d.ts +2 -0
- package/dist/components/text-area/text-area.js +2 -0
- package/dist/components/text-field/text-field.d.ts +2 -0
- package/dist/components/text-field/text-field.js +2 -0
- package/dist/components/text-mask/text-mask.d.ts +2 -0
- package/dist/components/text-mask/text-mask.js +2 -0
- package/dist/components/timed-content/timed-content.d.ts +2 -0
- package/dist/components/timed-content/timed-content.js +2 -0
- package/dist/components/toast/toast.d.ts +2 -0
- package/dist/components/toast/toast.js +2 -0
- package/dist/components/toast-item/toast-item.d.ts +2 -0
- package/dist/components/toast-item/toast-item.js +2 -0
- package/dist/components/toggle-icon/toggle-icon.d.ts +2 -0
- package/dist/components/toggle-icon/toggle-icon.js +2 -0
- package/dist/components/toggle-tag/toggle-tag.d.ts +2 -0
- package/dist/components/toggle-tag/toggle-tag.js +2 -0
- package/dist/components/toolbar/toolbar.d.ts +2 -0
- package/dist/components/toolbar/toolbar.js +2 -0
- package/dist/components/tooltip/tooltip.d.ts +2 -0
- package/dist/components/tooltip/tooltip.js +2 -0
- package/dist/components/transition-group/transition-group.d.ts +2 -0
- package/dist/components/transition-group/transition-group.js +2 -0
- package/dist/components/zoomable-frame/zoomable-frame.d.ts +2 -0
- package/dist/components/zoomable-frame/zoomable-frame.js +2 -0
- package/dist/copy-CvC9vaGw.d.ts +206 -0
- package/dist/copy.styles-DWGvGNTP.js +100 -0
- package/dist/data-table-CITa8DSn.js +247 -0
- package/dist/data-table-DL5RhE0d.d.ts +89 -0
- package/dist/date-CJPmOdi9.js +146 -0
- package/dist/date-DtaTBM71.d.ts +142 -0
- package/dist/decorate-DcF3lt7P.js +9 -0
- package/dist/dialog-Cx46HMaZ.js +983 -0
- package/dist/dialog-N-v0woIy.d.ts +414 -0
- package/dist/divider-9vNsfHW8.js +169 -0
- package/dist/divider-DWuAxcXv.d.ts +79 -0
- package/dist/docs/custom-elements.json +29301 -0
- package/dist/dropdown-BXSKpVX9.js +1123 -0
- package/dist/dropdown-Bo00Vlr5.d.ts +537 -0
- package/dist/dropdown-item-_lIs-Tfd.d.ts +111 -0
- package/dist/dropdown-item-i77cRuN6.js +504 -0
- package/dist/empty-result-B2ln1yFL.js +65 -0
- package/dist/empty-result-B54x_Ab2.d.ts +31 -0
- package/dist/empty-state-BLWjtKUo.js +186 -0
- package/dist/empty-state-SGKjpwp3.d.ts +117 -0
- package/dist/expander-BUev0BmM.d.ts +174 -0
- package/dist/expander-Bwvxj6Oa.js +342 -0
- package/dist/field-BEyS909F.js +163 -0
- package/dist/field-ITx0jVw-.d.ts +69 -0
- package/dist/file-input-BEumLJjg.js +841 -0
- package/dist/file-input-D2D6YC0B.d.ts +378 -0
- package/dist/filter-bar-Bj2QzEn9.d.ts +35 -0
- package/dist/filter-bar-Dcs67aXo.js +66 -0
- package/dist/form-section-BchPetkj.js +83 -0
- package/dist/form-section-xFBTBULQ.d.ts +34 -0
- package/dist/icon-BPVkNsY4.js +165 -0
- package/dist/icon-Ci9CPZJV.d.ts +72 -0
- package/dist/icon-library-D_if7p2h.d.ts +2 -0
- package/dist/include-CQHVVtNs.d.ts +103 -0
- package/dist/include-qNUh_6kT.js +155 -0
- package/dist/index.d.ts +89 -0
- package/dist/index.js +92 -0
- package/dist/infinite-scroller-BmmtnWNt.js +285 -0
- package/dist/infinite-scroller-CuUEAlB9.d.ts +174 -0
- package/dist/intersection-observer-B6TciOAQ.js +503 -0
- package/dist/intersection-observer-B7nmP7Zz.d.ts +418 -0
- package/dist/listbox-C3XXRWGX.js +1257 -0
- package/dist/listbox-DD4ujIJe.d.ts +682 -0
- package/dist/listbox-item-CwD9s3VY.js +135 -0
- package/dist/listbox-item-DQEJWp4Z.d.ts +53 -0
- package/dist/localize-322EtXNX.d.ts +66 -0
- package/dist/lorem-ipsum-B2x3V-v8.js +198 -0
- package/dist/lorem-ipsum-CR82CSuJ.d.ts +130 -0
- package/dist/meter-BC7uaJWf.d.ts +73 -0
- package/dist/meter-BIDyjwFp.js +155 -0
- package/dist/metric-CjlLq_VA.d.ts +36 -0
- package/dist/metric-DbuOcDp_.js +86 -0
- package/dist/metric-grid-C2Pb0Zl3.js +37 -0
- package/dist/metric-grid-C5Xbb1_0.d.ts +27 -0
- package/dist/mutation-observer-BmrZ-GER.d.ts +326 -0
- package/dist/mutation-observer-DS8EBuOp.js +388 -0
- package/dist/navicon-Dic5Qjzb.d.ts +159 -0
- package/dist/navicon-_yMHY27-.js +486 -0
- package/dist/number-BNtNXNF3.js +162 -0
- package/dist/number-BwbnErlB.d.ts +143 -0
- package/dist/number-field-BQHB7UYo.js +726 -0
- package/dist/number-field-odk4lKXM.d.ts +422 -0
- package/dist/pagination-6z2qcf3U.d.ts +322 -0
- package/dist/pagination-DuKPuzdb.js +679 -0
- package/dist/popover-D0sxTU6o.d.ts +259 -0
- package/dist/popover-DJBrJ0za.js +556 -0
- package/dist/preview-card-C7H1FPfd.js +287 -0
- package/dist/preview-card-DitOCZTD.d.ts +86 -0
- package/dist/progress-Db0_axHQ.d.ts +181 -0
- package/dist/progress-DzVk260j.js +494 -0
- package/dist/radio-BtDG9xJM.js +658 -0
- package/dist/radio-CieMa4zU.d.ts +460 -0
- package/dist/radio-item-DIrUStAX.js +264 -0
- package/dist/radio-item-Xq2U3cMu.d.ts +69 -0
- package/dist/random-content-BhSeJFKz.d.ts +380 -0
- package/dist/random-content-BwiirXdG.js +450 -0
- package/dist/rating-4xNsWumY.d.ts +369 -0
- package/dist/rating-C1BcJDIO.js +722 -0
- package/dist/resize-observer-BseSbVWP.d.ts +187 -0
- package/dist/resize-observer-DcrLhddo.js +236 -0
- package/dist/scroll-area-COc1857S.js +127 -0
- package/dist/scroll-area-CVYDf5qY.d.ts +61 -0
- package/dist/scroller-LYgBVyfY.js +590 -0
- package/dist/scroller-bB2rGs7b.d.ts +374 -0
- package/dist/search-list-Clmrg8EV.js +884 -0
- package/dist/search-list-n0GYO7rh.d.ts +777 -0
- package/dist/select-CkZK2jJn.d.ts +506 -0
- package/dist/select-DLIaRnA4.js +690 -0
- package/dist/selection-summary-BVnNJ8Lw.js +48 -0
- package/dist/selection-summary-DmFkGyZI.d.ts +34 -0
- package/dist/share-DPlqP2dc.d.ts +162 -0
- package/dist/share-bsgXZCl7.js +250 -0
- package/dist/sigvelo.d.ts +5 -0
- package/dist/sigvelo.js +5 -0
- package/dist/sigvelo.loader.d.ts +3 -0
- package/dist/sigvelo.loader.js +102 -0
- package/dist/slide-activator-D7bBz69E.d.ts +429 -0
- package/dist/slide-activator-DlxQt9R9.js +798 -0
- package/dist/slider-B0FVsV1o.d.ts +921 -0
- package/dist/slider-B90Il7x3.js +1744 -0
- package/dist/sparkline-CcpTaJ_Z.js +358 -0
- package/dist/sparkline-DlCIt81-.d.ts +235 -0
- package/dist/spinner-C04Dmc0H.js +188 -0
- package/dist/spinner-CZ19x_dC.d.ts +99 -0
- package/dist/splitter-DBDJAzsp.d.ts +325 -0
- package/dist/splitter-MnD4In9H.js +638 -0
- package/dist/switch-CPaEKbog.js +581 -0
- package/dist/switch-Cief9M59.d.ts +248 -0
- package/dist/tab-BcqYGsuW.d.ts +44 -0
- package/dist/tab-C-FtuNmh.js +102 -0
- package/dist/tab-list-B_Ye_Oj9.js +691 -0
- package/dist/tab-list-DDvS8qHr.d.ts +450 -0
- package/dist/tab-panel-BaBl6eep.js +60 -0
- package/dist/tab-panel-BzSJlSfd.d.ts +38 -0
- package/dist/text-area-B_mjCE9W.d.ts +327 -0
- package/dist/text-area-Czixaz-_.js +556 -0
- package/dist/text-field-BClWMp6q.d.ts +424 -0
- package/dist/text-field-inpJfp0A.js +687 -0
- package/dist/text-mask-CNKVKSFp.d.ts +336 -0
- package/dist/text-mask-DDEurj90.js +370 -0
- package/dist/themes/sigvelo.css +10 -0
- package/dist/themes/utilities.css +9 -0
- package/dist/timed-content-D2mGFamc.d.ts +181 -0
- package/dist/timed-content-pvEP4l5V.js +226 -0
- package/dist/toast-BnZaIg6Z.js +636 -0
- package/dist/toast-cEBVK9NQ.d.ts +487 -0
- package/dist/toast-item-BPpJT6vD.d.ts +159 -0
- package/dist/toast-item-IS8IFUEg.js +372 -0
- package/dist/toggle-icon-4oLDeEt4.js +752 -0
- package/dist/toggle-icon-DlwMMWZL.d.ts +359 -0
- package/dist/toggle-tag-1sfTFJtg.js +434 -0
- package/dist/toggle-tag-IVvMGT4R.d.ts +245 -0
- package/dist/toolbar-CABq0ZL1.d.ts +122 -0
- package/dist/toolbar-CEZ0-F-X.js +196 -0
- package/dist/tooltip-DbyoPFNe.js +521 -0
- package/dist/tooltip-ahFthek8.d.ts +192 -0
- package/dist/transition-group-3hnAnwSd.js +801 -0
- package/dist/transition-group-DD_CjSNC.d.ts +608 -0
- package/dist/translations/en.d.ts +6 -0
- package/dist/translations/en.js +75 -0
- package/dist/translations/es.d.ts +6 -0
- package/dist/translations/es.js +75 -0
- package/dist/types/custom-element-jsx.d.ts +13723 -0
- package/dist/utilities/icon-library.d.ts +3 -0
- package/dist/utilities/icon-library.js +93 -0
- package/dist/utilities/localize.d.ts +2 -0
- package/dist/utilities/localize.js +6 -0
- package/dist/zoomable-frame-Cldvj5sE.js +398 -0
- package/dist/zoomable-frame-r6S6587z.d.ts +162 -0
- package/package.json +83 -0
|
@@ -0,0 +1,1257 @@
|
|
|
1
|
+
import { Localize } from "./utilities/localize.js";
|
|
2
|
+
import { t as __decorate } from "./decorate-DcF3lt7P.js";
|
|
3
|
+
import "./listbox-item-CwD9s3VY.js";
|
|
4
|
+
import { css, html } from "lit";
|
|
5
|
+
import { property, query, state } from "lit/decorators.js";
|
|
6
|
+
import hostStyles from "@mcp-b/wc-support/styles/host.styles";
|
|
7
|
+
import { SigveloFormControlElement } from "@mcp-b/wc-support/base/sigvelo-element";
|
|
8
|
+
import { classMap } from "lit/directives/class-map.js";
|
|
9
|
+
import { SigveloBlurEvent, SigveloChangeEvent, SigveloFocusEvent, SigveloInputEvent } from "@mcp-b/wc-support/events/form";
|
|
10
|
+
import formControlStyles from "@mcp-b/wc-support/styles/form-control.styles";
|
|
11
|
+
//#region src/components/listbox/listbox.styles.ts
|
|
12
|
+
var listbox_styles_default = css`
|
|
13
|
+
#listbox {
|
|
14
|
+
display: flex;
|
|
15
|
+
flex-direction: column;
|
|
16
|
+
height: 12.125em;
|
|
17
|
+
padding: 0.25em 0;
|
|
18
|
+
padding: 0.25em;
|
|
19
|
+
overflow: auto;
|
|
20
|
+
border: var(--sigvelo-border-style) var(--sigvelo-border-width)
|
|
21
|
+
var(--sigvelo-color-neutral-border-muted);
|
|
22
|
+
border-radius: var(--sigvelo-radius-md);
|
|
23
|
+
background-color: var(--sigvelo-color-surface);
|
|
24
|
+
scrollbar-color: var(--sigvelo-color-neutral-bg) transparent;
|
|
25
|
+
scrollbar-width: thin;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/* Focus state for the listbox */
|
|
29
|
+
:host(:state(focused)) #listbox {
|
|
30
|
+
outline: var(--sigvelo-border-style) calc(var(--sigvelo-border-width) + 1px)
|
|
31
|
+
var(--sigvelo-color-focus);
|
|
32
|
+
outline-offset: calc(-1 * var(--sigvelo-border-width));
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
:host(:state(disabled)),
|
|
36
|
+
:host(:state(disabled)) ::slotted(sigvelo-listbox-item) {
|
|
37
|
+
cursor: not-allowed;
|
|
38
|
+
opacity: 0.5;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
.readonly ::slotted(sigvelo-listbox-item) {
|
|
42
|
+
cursor: default;
|
|
43
|
+
}
|
|
44
|
+
`;
|
|
45
|
+
//#endregion
|
|
46
|
+
//#region src/components/listbox/listbox.ts
|
|
47
|
+
const nativeFileInput = document.createElement("input");
|
|
48
|
+
nativeFileInput.name = "sigvelo-faux-input";
|
|
49
|
+
nativeFileInput.type = "text";
|
|
50
|
+
nativeFileInput.required = true;
|
|
51
|
+
const VALIDATION_MESSAGE = nativeFileInput.validationMessage;
|
|
52
|
+
/**
|
|
53
|
+
* <sigvelo-listbox>
|
|
54
|
+
*
|
|
55
|
+
* @summary Displays a list of options, allowing users to select one or more items from the available choices.
|
|
56
|
+
* @tag sigvelo-listbox
|
|
57
|
+
* @documentation https://design-system.sigvelo.com/docs/components/listbox
|
|
58
|
+
* @status stable
|
|
59
|
+
* @since 1.0
|
|
60
|
+
*
|
|
61
|
+
* @dependency listbox-item
|
|
62
|
+
*
|
|
63
|
+
* @slot - Listbox items to show in the listbox.
|
|
64
|
+
* @slot label - The listbox's label. For plain-text labels, you can use the `label` attribute instead.
|
|
65
|
+
* @slot description - The listbox's description. For plain-text descriptions, you can use the `description` attribute
|
|
66
|
+
* instead.
|
|
67
|
+
*
|
|
68
|
+
* @event sigvelo-blur - Emitted when the list box loses focus. This event does not bubble.
|
|
69
|
+
* @event sigvelo-change - Emitted when the user commits changes to the list box's selection. In single select mode, it
|
|
70
|
+
* occurs when a change is made and the listbox loses focus. In multiselect mode, it occurs whenever an option is
|
|
71
|
+
* toggled even while the listbox has focus.
|
|
72
|
+
* @event sigvelo-focus - Emitted when the list box receives focus. This event does not bubble.
|
|
73
|
+
* @event sigvelo-input - Emitted when the list box's selection changes from user input.
|
|
74
|
+
*
|
|
75
|
+
* @csspart label - The element that contains the text field's label.
|
|
76
|
+
* @csspart description - The element that contains the text field's description.
|
|
77
|
+
* @csspart listbox - The internal listbox container that holds listbox items.
|
|
78
|
+
*
|
|
79
|
+
* @cssstate disabled - Applied when the text field is disabled.
|
|
80
|
+
* @cssstate blank - Applied when the text field has a blank value.
|
|
81
|
+
* @cssstate focused - Applied when the text field has focus.
|
|
82
|
+
* @cssstate user-valid - Applied when the text field is valid and the user has sufficiently interacted with it.
|
|
83
|
+
* @cssstate user-invalid - Applied when the text field is invalid and the user has sufficiently interacted with it.
|
|
84
|
+
*
|
|
85
|
+
* @example Default
|
|
86
|
+
* Listboxes follow the ARIA APG listbox pattern for accessibility. The listbox is labeled for assistive devices and listbox items are announced as options. To function more like native listboxes, the alternate selection model is used for keyboard interaction.
|
|
87
|
+
*
|
|
88
|
+
* ```html
|
|
89
|
+
* <sigvelo-listbox label="Our kittens" description="Select your new friends." multiple>
|
|
90
|
+
* <sigvelo-listbox-item value="1">Bella</sigvelo-listbox-item>
|
|
91
|
+
* <sigvelo-listbox-item value="2">Luna</sigvelo-listbox-item>
|
|
92
|
+
* <sigvelo-listbox-item value="3">Meowy McGee</sigvelo-listbox-item>
|
|
93
|
+
* <sigvelo-listbox-item value="4">Milo</sigvelo-listbox-item>
|
|
94
|
+
* <sigvelo-listbox-item value="5">Mittens</sigvelo-listbox-item>
|
|
95
|
+
* <sigvelo-listbox-item value="6">Oliver</sigvelo-listbox-item>
|
|
96
|
+
* <sigvelo-listbox-item value="7">Pepper</sigvelo-listbox-item>
|
|
97
|
+
* <sigvelo-listbox-item value="8">Shadow</sigvelo-listbox-item>
|
|
98
|
+
* <sigvelo-listbox-item value="9">Simba</sigvelo-listbox-item>
|
|
99
|
+
* <sigvelo-listbox-item value="10">Whiskers</sigvelo-listbox-item>
|
|
100
|
+
* </sigvelo-listbox>
|
|
101
|
+
* ```
|
|
102
|
+
*
|
|
103
|
+
* @example Labels and descriptions
|
|
104
|
+
* You can use the `label` and `description` attributes to provide plain text labels and descriptions for the listbox. If you want to provide HTML, use the `label` and `description` slots instead.
|
|
105
|
+
*
|
|
106
|
+
* ```html
|
|
107
|
+
* <sigvelo-listbox>
|
|
108
|
+
* <span slot="label">Feline <strong>Friends</strong></span>
|
|
109
|
+
* <span slot="description">
|
|
110
|
+
* For adoption information, <a href="https://example.com/" target="_blank">visit our cat sanctuary</a>.
|
|
111
|
+
* </span>
|
|
112
|
+
* <sigvelo-listbox-item value="1">Whiskers (3 years old)</sigvelo-listbox-item>
|
|
113
|
+
* <sigvelo-listbox-item value="2">Mittens (2 years old)</sigvelo-listbox-item>
|
|
114
|
+
* <sigvelo-listbox-item value="3">Shadow (5 years old)</sigvelo-listbox-item>
|
|
115
|
+
* </sigvelo-listbox>
|
|
116
|
+
* ```
|
|
117
|
+
*
|
|
118
|
+
* @example Providing options
|
|
119
|
+
* Create listbox options by adding `<sigvelo-listbox-item>` elements inside the listbox. Each item should have a `value` attribute that will be submitted with the form.
|
|
120
|
+
*
|
|
121
|
+
* ```html
|
|
122
|
+
* <sigvelo-listbox label="Favorite Cat Toys">
|
|
123
|
+
* <sigvelo-listbox-item value="feather">Feather Wand</sigvelo-listbox-item>
|
|
124
|
+
* <sigvelo-listbox-item value="laser">Laser Pointer</sigvelo-listbox-item>
|
|
125
|
+
* <sigvelo-listbox-item value="catnip">Catnip Mouse</sigvelo-listbox-item>
|
|
126
|
+
* <sigvelo-listbox-item value="tunnel">Crinkle Tunnel</sigvelo-listbox-item>
|
|
127
|
+
* <sigvelo-listbox-item value="box">Cardboard Box</sigvelo-listbox-item>
|
|
128
|
+
* </sigvelo-listbox>
|
|
129
|
+
* ```
|
|
130
|
+
*
|
|
131
|
+
* Listbox items can have structured content, too.
|
|
132
|
+
*
|
|
133
|
+
* ```html
|
|
134
|
+
* <sigvelo-listbox label="Favorite Cat Toys" id="listbox__options">
|
|
135
|
+
* <sigvelo-listbox-item value="feather">
|
|
136
|
+
* <h4>Feather Wand</h4>
|
|
137
|
+
* <small aria-hidden="true">Interactive toy that mimics bird movements</small>
|
|
138
|
+
* </sigvelo-listbox-item>
|
|
139
|
+
* <sigvelo-listbox-item value="laser">
|
|
140
|
+
* <h4>Laser Pointer</h4>
|
|
141
|
+
* <small aria-hidden="true">Creates a moving red dot for cats to chase</small>
|
|
142
|
+
* </sigvelo-listbox-item>
|
|
143
|
+
* <sigvelo-listbox-item value="catnip">
|
|
144
|
+
* <h4>Catnip Mouse</h4>
|
|
145
|
+
* <small aria-hidden="true">Soft toy filled with enticing catnip</small>
|
|
146
|
+
* </sigvelo-listbox-item>
|
|
147
|
+
* <sigvelo-listbox-item value="tunnel">
|
|
148
|
+
* <h4>Crinkle Tunnel</h4>
|
|
149
|
+
* <small aria-hidden="true">Collapsible tunnel with crinkly material cats love</small>
|
|
150
|
+
* </sigvelo-listbox-item>
|
|
151
|
+
* <sigvelo-listbox-item value="box">
|
|
152
|
+
* <h4>Cardboard Box</h4>
|
|
153
|
+
* <small aria-hidden="true">Simple but beloved hiding spot for feline friends</small>
|
|
154
|
+
* </sigvelo-listbox-item>
|
|
155
|
+
* </sigvelo-listbox>
|
|
156
|
+
*
|
|
157
|
+
* <style>
|
|
158
|
+
* #listbox__options {
|
|
159
|
+
* &::part(listbox) {
|
|
160
|
+
* height: auto;
|
|
161
|
+
* }
|
|
162
|
+
*
|
|
163
|
+
* h4 {
|
|
164
|
+
* font-size: 1.125rem;
|
|
165
|
+
* font-weight: var(--sigvelo-font-weight-semibold);
|
|
166
|
+
* line-height: 1.4;
|
|
167
|
+
* margin-block: 0;
|
|
168
|
+
* }
|
|
169
|
+
*
|
|
170
|
+
* sigvelo-listbox-item:state(selected) small {
|
|
171
|
+
* color: var(--sigvelo-color-primary-text-on-subtle);
|
|
172
|
+
* }
|
|
173
|
+
* }
|
|
174
|
+
* </style>
|
|
175
|
+
* ```
|
|
176
|
+
*
|
|
177
|
+
* **Warning:** Avoid placing interactive elements such as buttons and links inside the listbox item, as this will hinder accessibility and can lead to unexpected behaviors.
|
|
178
|
+
*
|
|
179
|
+
* @example Providing an initial value
|
|
180
|
+
* Add the `selected` attribute to the listbox item you want to select initially. When using `multiple`, you can apply `selected` to more than one option.
|
|
181
|
+
*
|
|
182
|
+
* ```html
|
|
183
|
+
* <sigvelo-listbox label="Favorite Nap Location">
|
|
184
|
+
* <sigvelo-listbox-item value="windowsill">Sunny Windowsill</sigvelo-listbox-item>
|
|
185
|
+
* <sigvelo-listbox-item value="lap" selected>Human's Lap</sigvelo-listbox-item>
|
|
186
|
+
* <sigvelo-listbox-item value="bed">Middle of the Bed</sigvelo-listbox-item>
|
|
187
|
+
* <sigvelo-listbox-item value="keyboard">Computer Keyboard</sigvelo-listbox-item>
|
|
188
|
+
* </sigvelo-listbox>
|
|
189
|
+
* ```
|
|
190
|
+
*
|
|
191
|
+
* @example Getting and setting the selection
|
|
192
|
+
* Listboxes provide several properties for interacting with their selection state programmatically. Use the `value` property for getting/setting a single value. Use the `selectedValues` property for multiple values. If you need to get or set a list of selected `<sigvelo-listbox-item>` elements, use the `selectedItems` property.
|
|
193
|
+
*
|
|
194
|
+
* #### Getting the selection
|
|
195
|
+
*
|
|
196
|
+
* Use `value` to get a single value. To get all selected values, use `selectedValues`. If you need to get an array of DOM elements, use `selectedItems`.
|
|
197
|
+
*
|
|
198
|
+
* ```js
|
|
199
|
+
* // Get the first selected value
|
|
200
|
+
* const value = listbox.value;
|
|
201
|
+
*
|
|
202
|
+
* // Get an array of all selected values
|
|
203
|
+
* const values = listbox.selectedValues;
|
|
204
|
+
*
|
|
205
|
+
* // Get an array of all selected listbox item elements
|
|
206
|
+
* const items = listbox.selectedItems;
|
|
207
|
+
* ```
|
|
208
|
+
*
|
|
209
|
+
* #### Setting the selection
|
|
210
|
+
*
|
|
211
|
+
* Use `value` to set a single value. To set multiple values, use `selectedValues`. If you need to get or set the selection via DOM elements, use `selectedItems`.
|
|
212
|
+
*
|
|
213
|
+
* ```js
|
|
214
|
+
* // Set a single value
|
|
215
|
+
* listbox.value = 'a';
|
|
216
|
+
*
|
|
217
|
+
* // Set multiple values
|
|
218
|
+
* listbox.selectedValues = ['a', 'b', 'c'];
|
|
219
|
+
*
|
|
220
|
+
* // Set using DOM elements
|
|
221
|
+
* const itemA = document.querySelector('sigvelo-listbox-item#a');
|
|
222
|
+
* const itemB = document.querySelector('sigvelo-listbox-item#b');
|
|
223
|
+
* const itemC = document.querySelector('sigvelo-listbox-item#c');
|
|
224
|
+
*
|
|
225
|
+
* listbox.selectedItems = [itemA, itemB, itemC];
|
|
226
|
+
* ```
|
|
227
|
+
*
|
|
228
|
+
* #### Convenience methods
|
|
229
|
+
*
|
|
230
|
+
* Use `selectAll()` and `deselectAll()` as a quick way to select all or no items.
|
|
231
|
+
*
|
|
232
|
+
* ```js
|
|
233
|
+
* // Select all items
|
|
234
|
+
* listbox.selectAll();
|
|
235
|
+
*
|
|
236
|
+
* // Deselect all items
|
|
237
|
+
* listbox.deselectAll();
|
|
238
|
+
* ```
|
|
239
|
+
*
|
|
240
|
+
* @example Disabling items
|
|
241
|
+
* Add the `disabled` attribute to individual listbox items to make them non-selectable.
|
|
242
|
+
*
|
|
243
|
+
* ```html
|
|
244
|
+
* <sigvelo-listbox label="Feeding Schedule">
|
|
245
|
+
* <sigvelo-listbox-item value="morning">Morning (7am)</sigvelo-listbox-item>
|
|
246
|
+
* <sigvelo-listbox-item value="noon">Noon (12pm)</sigvelo-listbox-item>
|
|
247
|
+
* <sigvelo-listbox-item value="night" disabled>Night (10pm) - Currently unavailable</sigvelo-listbox-item>
|
|
248
|
+
* </sigvelo-listbox>
|
|
249
|
+
* ```
|
|
250
|
+
*
|
|
251
|
+
* @example Multiple selection
|
|
252
|
+
* Use the `multiple` attribute to enable multi-selection mode. Users can select multiple items using <sigvelo-hotkey keys="$command" platform="mac"></sigvelo-hotkey> or <sigvelo-hotkey keys="$control" platform="windows"></sigvelo-hotkey> + click, <sigvelo-hotkey keys="$shift"></sigvelo-hotkey> + click for ranges, or <sigvelo-hotkey keys="$cmdctrl A"></sigvelo-hotkey> to select all. For coarse pointers, such as touch, tapping an item will toggle the selection.
|
|
253
|
+
*
|
|
254
|
+
* ```html
|
|
255
|
+
* <sigvelo-listbox label="Kitty Behavior" description="Select your cat's typical antics." multiple>
|
|
256
|
+
* <sigvelo-listbox-item value="1">Midnight Zoomies</sigvelo-listbox-item>
|
|
257
|
+
* <sigvelo-listbox-item value="2" selected>Knocking Things Off Tables</sigvelo-listbox-item>
|
|
258
|
+
* <sigvelo-listbox-item value="3" selected>Ignoring Expensive Toys</sigvelo-listbox-item>
|
|
259
|
+
* <sigvelo-listbox-item value="4">Sitting on Open Books</sigvelo-listbox-item>
|
|
260
|
+
* <sigvelo-listbox-item value="5">Watching Birds Through Windows</sigvelo-listbox-item>
|
|
261
|
+
* <sigvelo-listbox-item value="6">Following You to the Bathroom</sigvelo-listbox-item>
|
|
262
|
+
* <sigvelo-listbox-item value="7" selected>Demanding Pets Then Biting</sigvelo-listbox-item>
|
|
263
|
+
* <sigvelo-listbox-item value="8">Sleeping in Weird Positions</sigvelo-listbox-item>
|
|
264
|
+
* <sigvelo-listbox-item value="9">Hiding in Paper Bags</sigvelo-listbox-item>
|
|
265
|
+
* <sigvelo-listbox-item value="10">Sudden Grooming Sessions</sigvelo-listbox-item>
|
|
266
|
+
* </sigvelo-listbox>
|
|
267
|
+
* ```
|
|
268
|
+
*
|
|
269
|
+
* @example Changing the size
|
|
270
|
+
* Use the `size` attribute to change the listbox's size.
|
|
271
|
+
*
|
|
272
|
+
* ```html
|
|
273
|
+
* <sigvelo-select label="Select a size" style="max-width: 18rem; margin-block-end: 2rem;">
|
|
274
|
+
* <option value="xs">Extra small</option>
|
|
275
|
+
* <option value="sm">Small</option>
|
|
276
|
+
* <option value="md">Medium</option>
|
|
277
|
+
* <option value="lg">Large</option>
|
|
278
|
+
* <option value="xl">Extra large</option>
|
|
279
|
+
* </sigvelo-select>
|
|
280
|
+
*
|
|
281
|
+
* <sigvelo-listbox
|
|
282
|
+
* size="xs"
|
|
283
|
+
* label="Cat Accessories"
|
|
284
|
+
* description="Size changes dynamically based on selection above"
|
|
285
|
+
* id="listbox__size"
|
|
286
|
+
* multiple
|
|
287
|
+
* >
|
|
288
|
+
* <sigvelo-listbox-item value="cat-tree">Cat Tree</sigvelo-listbox-item>
|
|
289
|
+
* <sigvelo-listbox-item value="food-bowl">Food Bowl</sigvelo-listbox-item>
|
|
290
|
+
* <sigvelo-listbox-item value="scratching-post">Scratching Post</sigvelo-listbox-item>
|
|
291
|
+
* <sigvelo-listbox-item value="toy-mouse">Toy Mouse</sigvelo-listbox-item>
|
|
292
|
+
* </sigvelo-listbox>
|
|
293
|
+
*
|
|
294
|
+
* <script>
|
|
295
|
+
* const listbox = document.getElementById('listbox__size');
|
|
296
|
+
* const select = listbox.previousElementSibling;
|
|
297
|
+
*
|
|
298
|
+
* select.addEventListener('sigvelo-change', () => {
|
|
299
|
+
* listbox.size = select.value;
|
|
300
|
+
* });
|
|
301
|
+
* <\/script>
|
|
302
|
+
* ```
|
|
303
|
+
*
|
|
304
|
+
* @example Disabling
|
|
305
|
+
* Add the `disabled` attribute to disable the entire listbox.
|
|
306
|
+
*
|
|
307
|
+
* ```html
|
|
308
|
+
* <sigvelo-listbox label="Treat Options" description="Treats temporarily unavailable." disabled>
|
|
309
|
+
* <sigvelo-listbox-item value="1">Tuna Treats</sigvelo-listbox-item>
|
|
310
|
+
* <sigvelo-listbox-item value="2" selected>Chicken Bites</sigvelo-listbox-item>
|
|
311
|
+
* <sigvelo-listbox-item value="3">Salmon Flakes</sigvelo-listbox-item>
|
|
312
|
+
* <sigvelo-listbox-item value="4">Cheese Nibbles</sigvelo-listbox-item>
|
|
313
|
+
* <sigvelo-listbox-item value="5">Catnip Crisps</sigvelo-listbox-item>
|
|
314
|
+
* </sigvelo-listbox>
|
|
315
|
+
* ```
|
|
316
|
+
*
|
|
317
|
+
* @example Showing labels on the side
|
|
318
|
+
* With the `sigvelo-side-label` utility, you can show labels on the side instead of on top of the listbox. You can control the width of the label by setting the `--label-width` custom property.
|
|
319
|
+
*
|
|
320
|
+
* ```html
|
|
321
|
+
* <sigvelo-listbox
|
|
322
|
+
* class="sigvelo-side-label"
|
|
323
|
+
* style="--label-width: 10ch;"
|
|
324
|
+
* name="fur"
|
|
325
|
+
* label="Fur Type"
|
|
326
|
+
* description="What's your cat's coat like?"
|
|
327
|
+
* >
|
|
328
|
+
* <sigvelo-listbox-item value="short">Short-haired</sigvelo-listbox-item>
|
|
329
|
+
* <sigvelo-listbox-item value="long">Long-haired</sigvelo-listbox-item>
|
|
330
|
+
* <sigvelo-listbox-item value="curly">Curly-coated</sigvelo-listbox-item>
|
|
331
|
+
* </sigvelo-listbox>
|
|
332
|
+
* <br>
|
|
333
|
+
* <sigvelo-listbox
|
|
334
|
+
* class="sigvelo-side-label"
|
|
335
|
+
* style="--label-width: 10ch;"
|
|
336
|
+
* name="eye"
|
|
337
|
+
* label="Eye Color"
|
|
338
|
+
* description="What color are your cat's eyes?"
|
|
339
|
+
* >
|
|
340
|
+
* <sigvelo-listbox-item value="green">Green</sigvelo-listbox-item>
|
|
341
|
+
* <sigvelo-listbox-item value="blue">Blue</sigvelo-listbox-item>
|
|
342
|
+
* <sigvelo-listbox-item value="amber">Amber</sigvelo-listbox-item>
|
|
343
|
+
* </sigvelo-listbox>
|
|
344
|
+
* ```
|
|
345
|
+
*
|
|
346
|
+
* @example Validation
|
|
347
|
+
* The `required` attribute can be used to enable validation using the Constraint Validation API.
|
|
348
|
+
*
|
|
349
|
+
* ```html
|
|
350
|
+
* <form action="about:blank" method="get" target="_blank">
|
|
351
|
+
* <sigvelo-listbox name="meow" label="Meow Volume" required>
|
|
352
|
+
* <sigvelo-listbox-item value="1">Barely Audible</sigvelo-listbox-item>
|
|
353
|
+
* <sigvelo-listbox-item value="2">Conversational</sigvelo-listbox-item>
|
|
354
|
+
* <sigvelo-listbox-item value="3">Wake the Neighbors</sigvelo-listbox-item>
|
|
355
|
+
* </sigvelo-listbox>
|
|
356
|
+
* <br>
|
|
357
|
+
* <sigvelo-button type="submit" color="primary">Submit</sigvelo-button>
|
|
358
|
+
* <sigvelo-button type="reset">Reset</sigvelo-button>
|
|
359
|
+
* </form>
|
|
360
|
+
* ```
|
|
361
|
+
*
|
|
362
|
+
* @example Using custom validation
|
|
363
|
+
* Use the `setCustomValidity()` method to make the listbox invalid and show a custom error message on submit. This will override all other validation parameters. To clear the error, call the method with an empty string.
|
|
364
|
+
*
|
|
365
|
+
* ```html
|
|
366
|
+
* <form action="about:blank" method="get" target="_blank" id="listbox__custom-validation">
|
|
367
|
+
* <sigvelo-listbox
|
|
368
|
+
* name="purr"
|
|
369
|
+
* label="Purr Intensity"
|
|
370
|
+
* description="This field will be invalid until custom validation is removed"
|
|
371
|
+
* >
|
|
372
|
+
* <sigvelo-listbox-item value="1">Gentle Rumble</sigvelo-listbox-item>
|
|
373
|
+
* <sigvelo-listbox-item value="2">Medium Motor</sigvelo-listbox-item>
|
|
374
|
+
* <sigvelo-listbox-item value="3">Thunderous Vibration</sigvelo-listbox-item>
|
|
375
|
+
* </sigvelo-listbox>
|
|
376
|
+
* <br>
|
|
377
|
+
* <sigvelo-button type="submit" color="primary">Submit</sigvelo-button>
|
|
378
|
+
* </form>
|
|
379
|
+
*
|
|
380
|
+
* <script type="module">
|
|
381
|
+
* import { allDefined } from '/dist/sigvelo.js';
|
|
382
|
+
*
|
|
383
|
+
* await allDefined();
|
|
384
|
+
*
|
|
385
|
+
* const form = document.getElementById('listbox__custom-validation');
|
|
386
|
+
* const listbox = form.querySelector('sigvelo-listbox');
|
|
387
|
+
*
|
|
388
|
+
* listbox.setCustomValidity('Not so fast, bubba!');
|
|
389
|
+
* <\/script>
|
|
390
|
+
* ```
|
|
391
|
+
*
|
|
392
|
+
* @example Styling validation
|
|
393
|
+
* You can style valid and invalid listboxes using the `:valid` and `:invalid` pseudo classes.
|
|
394
|
+
*
|
|
395
|
+
* ```html
|
|
396
|
+
* <form action="about:blank" method="get" target="_blank" class="listbox__validation-pseudo">
|
|
397
|
+
* <sigvelo-listbox
|
|
398
|
+
* name="claws"
|
|
399
|
+
* label="Claw Trimming"
|
|
400
|
+
* description="This field is required for grooming appointments"
|
|
401
|
+
* required
|
|
402
|
+
* >
|
|
403
|
+
* <sigvelo-listbox-item value="1">Front Paws Only</sigvelo-listbox-item>
|
|
404
|
+
* <sigvelo-listbox-item value="2">All Paws</sigvelo-listbox-item>
|
|
405
|
+
* <sigvelo-listbox-item value="3">No Trimming Needed</sigvelo-listbox-item>
|
|
406
|
+
* </sigvelo-listbox>
|
|
407
|
+
* <br>
|
|
408
|
+
* <sigvelo-button type="submit" color="primary">Submit</sigvelo-button>
|
|
409
|
+
* <sigvelo-button type="reset">Reset</sigvelo-button>
|
|
410
|
+
* </form>
|
|
411
|
+
*
|
|
412
|
+
* <style>
|
|
413
|
+
* .listbox__validation-pseudo {
|
|
414
|
+
* sigvelo-listbox:valid {
|
|
415
|
+
* outline: solid 2px var(--sigvelo-color-success-border);
|
|
416
|
+
* outline-offset: .5rem;
|
|
417
|
+
* }
|
|
418
|
+
*
|
|
419
|
+
* sigvelo-listbox:invalid {
|
|
420
|
+
* outline: solid 2px var(--sigvelo-color-danger-border);
|
|
421
|
+
* outline-offset: .5rem;
|
|
422
|
+
* }
|
|
423
|
+
* }
|
|
424
|
+
* </style>
|
|
425
|
+
* ```
|
|
426
|
+
*
|
|
427
|
+
* However, these selectors will match even before the user has had a chance to interact with the form. More often than not, you'll want to use the `user-valid` and `user-invalid` custom states instead. This way, validation styles are only shown _after_ the user interacts with the form control or when the form is submitted.
|
|
428
|
+
*
|
|
429
|
+
* ```html
|
|
430
|
+
* <form action="about:blank" method="get" target="_blank" class="listbox__validation-custom">
|
|
431
|
+
* <sigvelo-listbox
|
|
432
|
+
* name="diet"
|
|
433
|
+
* label="Dietary Needs"
|
|
434
|
+
* description="Please select your cat's dietary preference"
|
|
435
|
+
* required
|
|
436
|
+
* >
|
|
437
|
+
* <sigvelo-listbox-item value="1">Grain-Free Formula</sigvelo-listbox-item>
|
|
438
|
+
* <sigvelo-listbox-item value="2">Senior Cat Diet</sigvelo-listbox-item>
|
|
439
|
+
* <sigvelo-listbox-item value="3">Hairball Control</sigvelo-listbox-item>
|
|
440
|
+
* </sigvelo-listbox>
|
|
441
|
+
* <br>
|
|
442
|
+
* <sigvelo-button type="submit" color="primary">Submit</sigvelo-button>
|
|
443
|
+
* <sigvelo-button type="reset">Reset</sigvelo-button>
|
|
444
|
+
* </form>
|
|
445
|
+
*
|
|
446
|
+
* <style>
|
|
447
|
+
* .listbox__validation-custom {
|
|
448
|
+
* sigvelo-listbox:state(user-valid) {
|
|
449
|
+
* outline: solid 2px var(--sigvelo-color-success-border);
|
|
450
|
+
* outline-offset: .5rem;
|
|
451
|
+
* }
|
|
452
|
+
*
|
|
453
|
+
* sigvelo-listbox:state(user-invalid) {
|
|
454
|
+
* outline: solid 2px var(--sigvelo-color-danger-border);
|
|
455
|
+
* outline-offset: .5rem;
|
|
456
|
+
* }
|
|
457
|
+
* }
|
|
458
|
+
* </style>
|
|
459
|
+
* ```
|
|
460
|
+
*
|
|
461
|
+
* @example Styling listboxes
|
|
462
|
+
* Listboxes are styled like form controls for consistency, but feel free to customize them to your liking. Here's an example you might see in an email client.
|
|
463
|
+
*
|
|
464
|
+
* ```html
|
|
465
|
+
* <sigvelo-listbox
|
|
466
|
+
* label="Select a message to view"
|
|
467
|
+
* class="sigvelo-vh-label"
|
|
468
|
+
* id="listbox__styling"
|
|
469
|
+
* >
|
|
470
|
+
* <sigvelo-listbox-item value="1000">
|
|
471
|
+
* <sigvelo-avatar image="https://images.unsplash.com/photo-1735820474275-dd0ff4f28d71?q=80&w=256&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"></sigvelo-avatar>
|
|
472
|
+
* <h4 class="name">Sir Fluffington III</h4>
|
|
473
|
+
* <time class="time" datetime="2025-03-20T14:45">2:45 PM</time>
|
|
474
|
+
* <div class="summary" aria-hidden="true">Just knocked your favorite vase off the shelf. Not sorry.</div>
|
|
475
|
+
* <sigvelo-icon class="attachment" name="paperclip" label="1 attachment"></sigvelo-icon>
|
|
476
|
+
* </sigvelo-listbox-item>
|
|
477
|
+
*
|
|
478
|
+
* <sigvelo-listbox-item value="1001">
|
|
479
|
+
* <sigvelo-avatar image="https://images.unsplash.com/photo-1529778873920-4da4926a72c2?q=80&w=256&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"></sigvelo-avatar>
|
|
480
|
+
* <h4 class="name">Captain Whiskers</h4>
|
|
481
|
+
* <time class="time" datetime="2025-03-20T13:37">1:37 PM</time>
|
|
482
|
+
* <div class="summary" aria-hidden="true">Require immediate attention. Food bowl is half empty. This is an emergency.</div>
|
|
483
|
+
* <sigvelo-icon class="attachment" name="flag" family="filled" label="Urgent!"></sigvelo-icon>
|
|
484
|
+
* </sigvelo-listbox-item>
|
|
485
|
+
*
|
|
486
|
+
* <sigvelo-listbox-item value="1002">
|
|
487
|
+
* <sigvelo-avatar image="https://images.unsplash.com/photo-1569591159212-b02ea8a9f239?q=80&w=256&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"></sigvelo-avatar>
|
|
488
|
+
* <h4 class="name">Lady Purrlington</h4>
|
|
489
|
+
* <time class="time" datetime="2025-03-20T11:15">11:15 AM</time>
|
|
490
|
+
* <div class="summary" aria-hidden="true">Your lap is required for napping purposes at 3 PM sharp. Clear your schedule.</div>
|
|
491
|
+
* </sigvelo-listbox-item>
|
|
492
|
+
*
|
|
493
|
+
* <sigvelo-listbox-item value="1003">
|
|
494
|
+
* <sigvelo-avatar image="https://images.unsplash.com/photo-1672487209629-4d52e0c043d0?q=80&w=256&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"></sigvelo-avatar>
|
|
495
|
+
* <h4 class="name">Meowy McGee</h4>
|
|
496
|
+
* <time class="time" datetime="2025-03-20T10:22">10:22 AM</time>
|
|
497
|
+
* <div class="summary" aria-hidden="true">Spotted a bird outside. Making weird chattering noises. Send help.</div>
|
|
498
|
+
* <sigvelo-icon class="attachment" name="paperclip" label="1 attachment"></sigvelo-icon>
|
|
499
|
+
* </sigvelo-listbox-item>
|
|
500
|
+
*
|
|
501
|
+
* <sigvelo-listbox-item value="1004">
|
|
502
|
+
* <sigvelo-avatar image="https://images.unsplash.com/photo-1579014868745-23e405c5605d?q=80&w=400&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"></sigvelo-avatar>
|
|
503
|
+
* <h4 class="name">Chairman Meow</h4>
|
|
504
|
+
* <time class="time" datetime="2025-03-20T09:30">9:30 AM</time>
|
|
505
|
+
* <div class="summary" aria-hidden="true">Have claimed the new cardboard box. All other cats shall bow to my superiority.</div>
|
|
506
|
+
* </sigvelo-listbox-item>
|
|
507
|
+
* </sigvelo-listbox>
|
|
508
|
+
*
|
|
509
|
+
* <style>
|
|
510
|
+
* #listbox__styling {
|
|
511
|
+
* max-width: 600px;
|
|
512
|
+
* font-family: system-ui, -apple-system, BlinkMacSystemFont, sans-serif;
|
|
513
|
+
*
|
|
514
|
+
* &::part(listbox) {
|
|
515
|
+
* height: auto;
|
|
516
|
+
* padding: 0;
|
|
517
|
+
* }
|
|
518
|
+
*
|
|
519
|
+
* sigvelo-listbox-item {
|
|
520
|
+
* display: grid;
|
|
521
|
+
* grid-template-areas:
|
|
522
|
+
* "avatar name time"
|
|
523
|
+
* "avatar summary attachment";
|
|
524
|
+
* grid-template-columns: auto 1fr auto;
|
|
525
|
+
* grid-gap: 4px .75em;
|
|
526
|
+
* padding: .75em;
|
|
527
|
+
* border-bottom-color: var(--sigvelo-color-neutral-border-subtle);
|
|
528
|
+
* border-radius: 0;
|
|
529
|
+
* align-items: center;
|
|
530
|
+
* }
|
|
531
|
+
*
|
|
532
|
+
* sigvelo-listbox-item:has(+ sigvelo-listbox-item:state(selected)),
|
|
533
|
+
* sigvelo-listbox-item:state(selected) {
|
|
534
|
+
* border-bottom-color: var(--sigvelo-color-neutral-border-muted);
|
|
535
|
+
* }
|
|
536
|
+
*
|
|
537
|
+
* &:state(focused) {
|
|
538
|
+
* sigvelo-listbox-item:has(+ sigvelo-listbox-item:state(selected)),
|
|
539
|
+
* sigvelo-listbox-item:state(selected) {
|
|
540
|
+
* border-bottom-color: var(--sigvelo-color-primary-border-muted);
|
|
541
|
+
* }
|
|
542
|
+
* }
|
|
543
|
+
*
|
|
544
|
+
* sigvelo-avatar {
|
|
545
|
+
* grid-area: avatar;
|
|
546
|
+
* margin-right: 0.25rem;
|
|
547
|
+
* }
|
|
548
|
+
*
|
|
549
|
+
* .name {
|
|
550
|
+
* grid-area: name;
|
|
551
|
+
* margin: 0;
|
|
552
|
+
* font-size: 0.9375rem;
|
|
553
|
+
* font-weight: var(--sigvelo-font-weight-semibold);
|
|
554
|
+
* }
|
|
555
|
+
*
|
|
556
|
+
* .time {
|
|
557
|
+
* grid-area: time;
|
|
558
|
+
* font-size: 0.875em;
|
|
559
|
+
* color: var(--sigvelo-color-text-muted);
|
|
560
|
+
* justify-self: end;
|
|
561
|
+
* font-style: normal;
|
|
562
|
+
* }
|
|
563
|
+
*
|
|
564
|
+
* .summary {
|
|
565
|
+
* grid-area: summary;
|
|
566
|
+
* color: var(--sigvelo-color-text-muted);
|
|
567
|
+
* font-size: 0.875rem;
|
|
568
|
+
* white-space: nowrap;
|
|
569
|
+
* overflow: hidden;
|
|
570
|
+
* text-overflow: ellipsis;
|
|
571
|
+
* margin: 0;
|
|
572
|
+
* }
|
|
573
|
+
*
|
|
574
|
+
* .attachment {
|
|
575
|
+
* grid-area: attachment;
|
|
576
|
+
* color: var(--sigvelo-color-text-muted);
|
|
577
|
+
* justify-self: end;
|
|
578
|
+
* font-size: 0.875rem;
|
|
579
|
+
*
|
|
580
|
+
* &[name="flag"] {
|
|
581
|
+
* color: crimson;
|
|
582
|
+
* }
|
|
583
|
+
* }
|
|
584
|
+
*
|
|
585
|
+
* sigvelo-listbox-item:state(selected) {
|
|
586
|
+
* .name,
|
|
587
|
+
* .time,
|
|
588
|
+
* .summary,
|
|
589
|
+
* .attachment {
|
|
590
|
+
* color: var(--sigvelo-color-primary-text-on-subtle);
|
|
591
|
+
* }
|
|
592
|
+
* }
|
|
593
|
+
* }
|
|
594
|
+
* </style>
|
|
595
|
+
* ```
|
|
596
|
+
*
|
|
597
|
+
* **Note:** Note the use of `aria-hidden` on summaries, which reduces verbosity when used with screen readers.
|
|
598
|
+
*/
|
|
599
|
+
var SigveloListbox = class extends SigveloFormControlElement {
|
|
600
|
+
constructor(..._args) {
|
|
601
|
+
super(..._args);
|
|
602
|
+
this.localize = new Localize(this);
|
|
603
|
+
this.firstSelectedValue = "";
|
|
604
|
+
this.hadUserInteraction = false;
|
|
605
|
+
this.isInvalid = false;
|
|
606
|
+
this.lastSelectedIndex = -1;
|
|
607
|
+
this.previousValue = "";
|
|
608
|
+
this.typeaheadBuffer = "";
|
|
609
|
+
this.typeaheadTimeout = null;
|
|
610
|
+
this.wasChanged = false;
|
|
611
|
+
this.wasSubmitted = false;
|
|
612
|
+
this.multiple = false;
|
|
613
|
+
this.disabled = false;
|
|
614
|
+
this.readonly = false;
|
|
615
|
+
this.size = "md";
|
|
616
|
+
this.required = false;
|
|
617
|
+
}
|
|
618
|
+
static {
|
|
619
|
+
this.formAssociated = true;
|
|
620
|
+
}
|
|
621
|
+
static {
|
|
622
|
+
this.observeSlots = true;
|
|
623
|
+
}
|
|
624
|
+
static {
|
|
625
|
+
this.styles = [
|
|
626
|
+
hostStyles,
|
|
627
|
+
formControlStyles,
|
|
628
|
+
listbox_styles_default
|
|
629
|
+
];
|
|
630
|
+
}
|
|
631
|
+
/** The listbox's value. For multiple selection, this will be the value of the first selected item. */
|
|
632
|
+
get value() {
|
|
633
|
+
return this.firstSelectedValue;
|
|
634
|
+
}
|
|
635
|
+
set value(newValue) {
|
|
636
|
+
const oldValue = this.firstSelectedValue;
|
|
637
|
+
if (newValue !== oldValue) {
|
|
638
|
+
this.firstSelectedValue = newValue;
|
|
639
|
+
this.updateItemSelectionFromValue(newValue);
|
|
640
|
+
this.requestUpdate("value", oldValue);
|
|
641
|
+
}
|
|
642
|
+
}
|
|
643
|
+
/**
|
|
644
|
+
* Gets or sets the currently selected values as an array. This property provides a consistent way to access or modify
|
|
645
|
+
* the selection state regardless of whether the listbox is in single or multiple selection mode.
|
|
646
|
+
*
|
|
647
|
+
* In single selection mode, it returns an array with either zero or one value. In multiple selection mode, it returns
|
|
648
|
+
* an array of all selected values.
|
|
649
|
+
*
|
|
650
|
+
* When setting this property in single mode, the first value in the array (if any) becomes the selected value. In
|
|
651
|
+
* multiple mode, all values in the array become selected.
|
|
652
|
+
*/
|
|
653
|
+
get selectedValues() {
|
|
654
|
+
return this.getSelectedValues();
|
|
655
|
+
}
|
|
656
|
+
set selectedValues(values) {
|
|
657
|
+
this.setSelectedValues(values);
|
|
658
|
+
}
|
|
659
|
+
/** Gets or sets an array of selected listbox items. */
|
|
660
|
+
get selectedItems() {
|
|
661
|
+
return this.getItems(true).filter((item) => item.selected);
|
|
662
|
+
}
|
|
663
|
+
set selectedItems(items) {
|
|
664
|
+
if (!Array.isArray(items)) {
|
|
665
|
+
this.deselectAll();
|
|
666
|
+
return;
|
|
667
|
+
}
|
|
668
|
+
const values = items.map((item) => item?.value).filter(Boolean);
|
|
669
|
+
this.selectedValues = values;
|
|
670
|
+
}
|
|
671
|
+
get focusableAnchor() {
|
|
672
|
+
return this.listbox;
|
|
673
|
+
}
|
|
674
|
+
connectedCallback() {
|
|
675
|
+
super.connectedCallback();
|
|
676
|
+
this.addEventListener("invalid", this.handleHostInvalid);
|
|
677
|
+
this.addEventListener("keydown", this.handleKeyDown);
|
|
678
|
+
}
|
|
679
|
+
disconnectedCallback() {
|
|
680
|
+
super.disconnectedCallback();
|
|
681
|
+
this.removeEventListener("invalid", this.handleHostInvalid);
|
|
682
|
+
this.removeEventListener("keydown", this.handleKeyDown);
|
|
683
|
+
this.clearTypeaheadTimeout();
|
|
684
|
+
}
|
|
685
|
+
firstUpdated(changedProperties) {
|
|
686
|
+
super.firstUpdated(changedProperties);
|
|
687
|
+
this.initializeValueFromSelectedItems();
|
|
688
|
+
this.initializeItems();
|
|
689
|
+
}
|
|
690
|
+
updated(changedProperties) {
|
|
691
|
+
this.updateValidity();
|
|
692
|
+
if (changedProperties.has("value")) {
|
|
693
|
+
this.customStates.set("blank", this.firstSelectedValue === "");
|
|
694
|
+
this.updateFormValue();
|
|
695
|
+
this.updateSelectedItems();
|
|
696
|
+
this.resetRovingTabIndex();
|
|
697
|
+
}
|
|
698
|
+
if (changedProperties.has("disabled")) {
|
|
699
|
+
this.customStates.set("disabled", this.disabled);
|
|
700
|
+
this.updateListboxAttributesOnItems();
|
|
701
|
+
}
|
|
702
|
+
const hadUserInteraction = this.hadUserInteraction || this.wasSubmitted;
|
|
703
|
+
this.customStates.set("user-invalid", hadUserInteraction && this.isInvalid);
|
|
704
|
+
this.customStates.set("user-valid", hadUserInteraction && !this.isInvalid);
|
|
705
|
+
}
|
|
706
|
+
formDisabledCallback(isDisabled) {
|
|
707
|
+
this.disabled = isDisabled;
|
|
708
|
+
}
|
|
709
|
+
formResetCallback() {
|
|
710
|
+
this.isInvalid = false;
|
|
711
|
+
this.wasChanged = false;
|
|
712
|
+
this.hadUserInteraction = false;
|
|
713
|
+
this.wasSubmitted = false;
|
|
714
|
+
this.firstSelectedValue = this.getAttribute("value") ?? "";
|
|
715
|
+
const initiallySelectedItems = this.getItems(true).filter((item) => item.hasAttribute("selected"));
|
|
716
|
+
this.getItems(true).forEach((item) => {
|
|
717
|
+
item.selected = initiallySelectedItems.includes(item);
|
|
718
|
+
});
|
|
719
|
+
if (initiallySelectedItems.length > 0) this.firstSelectedValue = initiallySelectedItems[0].value;
|
|
720
|
+
this.updateFormValue();
|
|
721
|
+
this.updateSelectedItems();
|
|
722
|
+
}
|
|
723
|
+
clearTypeaheadTimeout() {
|
|
724
|
+
if (this.typeaheadTimeout) {
|
|
725
|
+
window.clearTimeout(this.typeaheadTimeout);
|
|
726
|
+
this.typeaheadTimeout = null;
|
|
727
|
+
}
|
|
728
|
+
}
|
|
729
|
+
getItems(includeDisabled = false) {
|
|
730
|
+
const selector = includeDisabled ? "sigvelo-listbox-item" : "sigvelo-listbox-item:not(:state(disabled))";
|
|
731
|
+
return [...this.querySelectorAll(selector)];
|
|
732
|
+
}
|
|
733
|
+
getSelectedItems() {
|
|
734
|
+
return this.getItems().filter((item) => item.selected);
|
|
735
|
+
}
|
|
736
|
+
initializeValueFromSelectedItems() {
|
|
737
|
+
const initiallySelectedItems = this.getItems(true).filter((item) => item.hasAttribute("selected") || item.selected);
|
|
738
|
+
if (initiallySelectedItems.length > 0) if (!this.multiple && initiallySelectedItems.length > 1) {
|
|
739
|
+
const firstItem = initiallySelectedItems[0];
|
|
740
|
+
initiallySelectedItems.slice(1).forEach((item) => {
|
|
741
|
+
item.selected = false;
|
|
742
|
+
});
|
|
743
|
+
this.firstSelectedValue = firstItem.value;
|
|
744
|
+
} else this.firstSelectedValue = initiallySelectedItems[0].value;
|
|
745
|
+
this.updateFormValue();
|
|
746
|
+
}
|
|
747
|
+
initializeItems() {
|
|
748
|
+
const items = this.getItems();
|
|
749
|
+
if (items.length > 0) {
|
|
750
|
+
const selectedItems = this.getSelectedItems();
|
|
751
|
+
const initialItem = selectedItems.length > 0 ? selectedItems[0] : items[0];
|
|
752
|
+
this.setActiveItem(initialItem);
|
|
753
|
+
this.resetRovingTabIndex();
|
|
754
|
+
}
|
|
755
|
+
}
|
|
756
|
+
updateItemSelectionFromValue(newValue) {
|
|
757
|
+
this.getItems(true).forEach((item) => {
|
|
758
|
+
item.selected = item.value === newValue;
|
|
759
|
+
});
|
|
760
|
+
}
|
|
761
|
+
updateFormValue() {
|
|
762
|
+
const selectedItems = this.selectedItems;
|
|
763
|
+
if (this.multiple && selectedItems.length > 0) {
|
|
764
|
+
const formData = new FormData();
|
|
765
|
+
selectedItems.forEach((item) => {
|
|
766
|
+
formData.append(this.name || "", item.value);
|
|
767
|
+
});
|
|
768
|
+
this.internals.setFormValue(formData);
|
|
769
|
+
} else this.internals.setFormValue(this.firstSelectedValue);
|
|
770
|
+
}
|
|
771
|
+
updateSelectedItems() {
|
|
772
|
+
if (!this.multiple) this.getItems(true).forEach((item) => {
|
|
773
|
+
item.selected = item.value === this.firstSelectedValue;
|
|
774
|
+
});
|
|
775
|
+
}
|
|
776
|
+
/**
|
|
777
|
+
* Updates the current value to align with selected items. We track user interaction to allow us to dispatch events
|
|
778
|
+
* when human changes are made and suppress them for programmatic changes.
|
|
779
|
+
*/
|
|
780
|
+
updateValueFromSelectedItems(isUserInteraction = false) {
|
|
781
|
+
const selectedItems = this.selectedItems;
|
|
782
|
+
this.previousValue = this.firstSelectedValue;
|
|
783
|
+
this.firstSelectedValue = selectedItems.length > 0 ? selectedItems[0].value : "";
|
|
784
|
+
if (isUserInteraction) {
|
|
785
|
+
this.hadUserInteraction = true;
|
|
786
|
+
if (this.multiple) {
|
|
787
|
+
this.dispatchEvent(new SigveloInputEvent());
|
|
788
|
+
this.dispatchEvent(new Event("input", {
|
|
789
|
+
bubbles: true,
|
|
790
|
+
composed: true
|
|
791
|
+
}));
|
|
792
|
+
this.dispatchEvent(new SigveloChangeEvent());
|
|
793
|
+
this.dispatchEvent(new Event("change", {
|
|
794
|
+
bubbles: true,
|
|
795
|
+
composed: true
|
|
796
|
+
}));
|
|
797
|
+
} else if (this.previousValue !== this.firstSelectedValue) {
|
|
798
|
+
this.dispatchEvent(new SigveloInputEvent());
|
|
799
|
+
this.dispatchEvent(new Event("input", {
|
|
800
|
+
bubbles: true,
|
|
801
|
+
composed: true
|
|
802
|
+
}));
|
|
803
|
+
this.wasChanged = true;
|
|
804
|
+
}
|
|
805
|
+
}
|
|
806
|
+
this.updateFormValue();
|
|
807
|
+
}
|
|
808
|
+
handleFocus() {
|
|
809
|
+
this.customStates.set("focused", true);
|
|
810
|
+
this.dispatchEvent(new SigveloFocusEvent());
|
|
811
|
+
if (this.getSelectedItems().length === 0) {
|
|
812
|
+
const items = this.getItems();
|
|
813
|
+
if (items.length > 0) {
|
|
814
|
+
const firstItem = items[0];
|
|
815
|
+
this.setActiveItem(firstItem);
|
|
816
|
+
this.updateValueFromSelectedItems();
|
|
817
|
+
}
|
|
818
|
+
}
|
|
819
|
+
this.updateListboxAttributesOnItems();
|
|
820
|
+
}
|
|
821
|
+
handleBlur() {
|
|
822
|
+
this.customStates.set("focused", false);
|
|
823
|
+
this.dispatchEvent(new SigveloBlurEvent());
|
|
824
|
+
if (!this.multiple && this.wasChanged && this.previousValue !== this.firstSelectedValue) {
|
|
825
|
+
this.dispatchEvent(new SigveloChangeEvent());
|
|
826
|
+
this.dispatchEvent(new Event("change", {
|
|
827
|
+
bubbles: true,
|
|
828
|
+
composed: true
|
|
829
|
+
}));
|
|
830
|
+
}
|
|
831
|
+
this.wasChanged = false;
|
|
832
|
+
this.updateListboxAttributesOnItems();
|
|
833
|
+
}
|
|
834
|
+
handleHostInvalid() {
|
|
835
|
+
this.wasSubmitted = true;
|
|
836
|
+
}
|
|
837
|
+
handleLabelClick() {
|
|
838
|
+
if (!this.disabled) this.focus();
|
|
839
|
+
}
|
|
840
|
+
handleListboxPointerDown(event) {
|
|
841
|
+
event.preventDefault();
|
|
842
|
+
}
|
|
843
|
+
handleItemClick(event) {
|
|
844
|
+
if (this.disabled) return;
|
|
845
|
+
const item = event.target.closest("sigvelo-listbox-item");
|
|
846
|
+
if (item?.disabled) return;
|
|
847
|
+
if (!item) {
|
|
848
|
+
this.deselectAll();
|
|
849
|
+
this.updateValueFromSelectedItems(true);
|
|
850
|
+
return;
|
|
851
|
+
}
|
|
852
|
+
const clickedIndex = this.getItems().indexOf(item);
|
|
853
|
+
if (clickedIndex === -1) return;
|
|
854
|
+
if (this.lastSelectedIndex === -1) this.lastSelectedIndex = clickedIndex;
|
|
855
|
+
if (!this.readonly) this.handleItemSelection(item, clickedIndex, event);
|
|
856
|
+
this.setActiveItem(item);
|
|
857
|
+
this.listbox.focus();
|
|
858
|
+
event.preventDefault();
|
|
859
|
+
}
|
|
860
|
+
handleItemSelection(item, itemIndex, event) {
|
|
861
|
+
const mouseEvent = event;
|
|
862
|
+
const modifiers = {
|
|
863
|
+
ctrl: mouseEvent.ctrlKey,
|
|
864
|
+
meta: mouseEvent.metaKey,
|
|
865
|
+
shift: mouseEvent.shiftKey
|
|
866
|
+
};
|
|
867
|
+
let selectionChanged = false;
|
|
868
|
+
const isCoarsePointer = event instanceof PointerEvent && (event.pointerType === "touch" || window.matchMedia("(pointer: coarse)").matches);
|
|
869
|
+
if (this.multiple && (modifiers.ctrl || modifiers.meta)) {
|
|
870
|
+
item.selected = !item.selected;
|
|
871
|
+
this.lastSelectedIndex = itemIndex;
|
|
872
|
+
selectionChanged = true;
|
|
873
|
+
} else if (this.multiple && modifiers.shift) {
|
|
874
|
+
const items = this.getItems();
|
|
875
|
+
const start = Math.min(this.lastSelectedIndex !== -1 ? this.lastSelectedIndex : 0, itemIndex);
|
|
876
|
+
const end = Math.max(this.lastSelectedIndex !== -1 ? this.lastSelectedIndex : 0, itemIndex);
|
|
877
|
+
selectionChanged = items.some((listItem, i) => {
|
|
878
|
+
return i >= start && i <= end && !listItem.selected;
|
|
879
|
+
});
|
|
880
|
+
if (selectionChanged) items.forEach((listItem, i) => {
|
|
881
|
+
if (i >= start && i <= end) listItem.selected = true;
|
|
882
|
+
});
|
|
883
|
+
} else if (this.multiple && isCoarsePointer) {
|
|
884
|
+
item.selected = !item.selected;
|
|
885
|
+
this.lastSelectedIndex = itemIndex;
|
|
886
|
+
selectionChanged = true;
|
|
887
|
+
} else if (this.multiple) {
|
|
888
|
+
const items = this.getItems();
|
|
889
|
+
selectionChanged = items.some((listItem, i) => {
|
|
890
|
+
return i === itemIndex && !listItem.selected || i !== itemIndex && listItem.selected;
|
|
891
|
+
});
|
|
892
|
+
if (selectionChanged) items.forEach((listItem, i) => {
|
|
893
|
+
listItem.selected = i === itemIndex;
|
|
894
|
+
});
|
|
895
|
+
this.lastSelectedIndex = itemIndex;
|
|
896
|
+
} else if (!item.selected) {
|
|
897
|
+
this.selectSingleItem(item);
|
|
898
|
+
selectionChanged = true;
|
|
899
|
+
}
|
|
900
|
+
requestAnimationFrame(() => {
|
|
901
|
+
if (selectionChanged) this.updateValueFromSelectedItems(true);
|
|
902
|
+
this.resetRovingTabIndex();
|
|
903
|
+
});
|
|
904
|
+
}
|
|
905
|
+
handleKeyDown(event) {
|
|
906
|
+
if (event.key.length === 1 && !event.metaKey && !event.ctrlKey) {
|
|
907
|
+
if (!this.readonly) this.handleTypeahead(event);
|
|
908
|
+
return;
|
|
909
|
+
}
|
|
910
|
+
const items = this.getItems();
|
|
911
|
+
if (items.length === 0) return;
|
|
912
|
+
if (this.getSelectedItems().length === 0) {
|
|
913
|
+
if (event.key === "ArrowDown" || event.key === "ArrowRight") {
|
|
914
|
+
event.preventDefault();
|
|
915
|
+
this.navigateToItem(0, items, event);
|
|
916
|
+
return;
|
|
917
|
+
} else if (event.key === "ArrowUp" || event.key === "ArrowLeft") {
|
|
918
|
+
event.preventDefault();
|
|
919
|
+
this.navigateToItem(items.length - 1, items, event);
|
|
920
|
+
return;
|
|
921
|
+
}
|
|
922
|
+
}
|
|
923
|
+
let activeItem = this.querySelector("sigvelo-listbox-item[active]");
|
|
924
|
+
let activeIndex = activeItem ? items.indexOf(activeItem) : -1;
|
|
925
|
+
if (activeIndex === -1) {
|
|
926
|
+
activeItem = this.getSelectedItems()[0] || items[0];
|
|
927
|
+
activeIndex = items.indexOf(activeItem);
|
|
928
|
+
this.setActiveItem(activeItem);
|
|
929
|
+
event.preventDefault();
|
|
930
|
+
return;
|
|
931
|
+
}
|
|
932
|
+
switch (event.key) {
|
|
933
|
+
case "ArrowDown":
|
|
934
|
+
case "ArrowRight":
|
|
935
|
+
event.preventDefault();
|
|
936
|
+
this.navigateToItem(activeIndex + 1, items, event);
|
|
937
|
+
break;
|
|
938
|
+
case "ArrowUp":
|
|
939
|
+
case "ArrowLeft":
|
|
940
|
+
event.preventDefault();
|
|
941
|
+
this.navigateToItem(activeIndex - 1, items, event);
|
|
942
|
+
break;
|
|
943
|
+
case "Home":
|
|
944
|
+
event.preventDefault();
|
|
945
|
+
if (!this.readonly && this.multiple && event.ctrlKey && event.shiftKey) {
|
|
946
|
+
const currentIndex = items.indexOf(activeItem);
|
|
947
|
+
for (let i = 0; i <= currentIndex; i++) items[i].selected = true;
|
|
948
|
+
this.updateValueFromSelectedItems(true);
|
|
949
|
+
this.navigateToItem(0, items, {
|
|
950
|
+
shiftKey: false,
|
|
951
|
+
ctrlKey: true,
|
|
952
|
+
metaKey: event.metaKey
|
|
953
|
+
});
|
|
954
|
+
} else this.navigateToItem(0, items, event);
|
|
955
|
+
break;
|
|
956
|
+
case "End":
|
|
957
|
+
event.preventDefault();
|
|
958
|
+
if (!this.readonly && this.multiple && event.ctrlKey && event.shiftKey) {
|
|
959
|
+
const currentIndex = items.indexOf(activeItem);
|
|
960
|
+
for (let i = currentIndex; i < items.length; i++) items[i].selected = true;
|
|
961
|
+
this.updateValueFromSelectedItems(true);
|
|
962
|
+
this.navigateToItem(items.length - 1, items, {
|
|
963
|
+
shiftKey: false,
|
|
964
|
+
ctrlKey: true,
|
|
965
|
+
metaKey: event.metaKey
|
|
966
|
+
});
|
|
967
|
+
} else this.navigateToItem(items.length - 1, items, event);
|
|
968
|
+
break;
|
|
969
|
+
case " ":
|
|
970
|
+
case "Enter":
|
|
971
|
+
event.preventDefault();
|
|
972
|
+
if (!this.readonly) if (this.multiple && event.shiftKey && !event.ctrlKey && !event.metaKey) {
|
|
973
|
+
const start = Math.min(this.lastSelectedIndex !== -1 ? this.lastSelectedIndex : 0, activeIndex);
|
|
974
|
+
const end = Math.max(this.lastSelectedIndex !== -1 ? this.lastSelectedIndex : 0, activeIndex);
|
|
975
|
+
items.forEach((item, i) => {
|
|
976
|
+
if (i >= start && i <= end) item.selected = true;
|
|
977
|
+
});
|
|
978
|
+
this.updateValueFromSelectedItems(true);
|
|
979
|
+
} else this.selectWithKeyboard(activeItem, activeIndex, event);
|
|
980
|
+
break;
|
|
981
|
+
case "a":
|
|
982
|
+
if (!this.readonly && (event.ctrlKey || event.metaKey) && this.multiple) {
|
|
983
|
+
event.preventDefault();
|
|
984
|
+
this.selectAll();
|
|
985
|
+
}
|
|
986
|
+
break;
|
|
987
|
+
}
|
|
988
|
+
this.listbox.focus();
|
|
989
|
+
}
|
|
990
|
+
/**
|
|
991
|
+
* Moves the active item, applying the selection semantics implied by the
|
|
992
|
+
* modifier keys.
|
|
993
|
+
*
|
|
994
|
+
* Takes only the modifier flags rather than the `KeyboardEvent`, because two
|
|
995
|
+
* call sites synthesise a modifier combination that did not happen (Ctrl is
|
|
996
|
+
* forced on for Ctrl+Shift+Home/End). Spreading a real event to fake that
|
|
997
|
+
* produced a plain object with none of the event prototype's accessors.
|
|
998
|
+
*/
|
|
999
|
+
navigateToItem(index, items, event) {
|
|
1000
|
+
index = Math.max(0, Math.min(index, items.length - 1));
|
|
1001
|
+
const newActiveItem = items[index];
|
|
1002
|
+
this.setActiveItem(newActiveItem);
|
|
1003
|
+
if (this.multiple && !this.readonly) {
|
|
1004
|
+
if (event.shiftKey && !event.ctrlKey && !event.metaKey) {
|
|
1005
|
+
newActiveItem.selected = !newActiveItem.selected;
|
|
1006
|
+
this.lastSelectedIndex = index;
|
|
1007
|
+
this.updateValueFromSelectedItems(true);
|
|
1008
|
+
this.resetRovingTabIndex();
|
|
1009
|
+
} else if (!event.shiftKey && !event.ctrlKey && !event.metaKey) {
|
|
1010
|
+
this.selectSingleItem(newActiveItem);
|
|
1011
|
+
this.updateValueFromSelectedItems(true);
|
|
1012
|
+
this.resetRovingTabIndex();
|
|
1013
|
+
}
|
|
1014
|
+
} else if (!this.readonly) {
|
|
1015
|
+
this.selectSingleItem(newActiveItem);
|
|
1016
|
+
this.updateValueFromSelectedItems(true);
|
|
1017
|
+
this.resetRovingTabIndex();
|
|
1018
|
+
}
|
|
1019
|
+
}
|
|
1020
|
+
updateListboxAttributesOnItems() {
|
|
1021
|
+
const isFocused = this.customStates.has("focused");
|
|
1022
|
+
this.getItems(true).forEach((item) => {
|
|
1023
|
+
item.customStates.set("controller-disabled", this.disabled);
|
|
1024
|
+
item.customStates.set("controller-readonly", this.readonly);
|
|
1025
|
+
item.customStates.set("controller-focused", isFocused);
|
|
1026
|
+
});
|
|
1027
|
+
}
|
|
1028
|
+
selectWithKeyboard(activeItem, activeIndex, event) {
|
|
1029
|
+
if (!activeItem) return;
|
|
1030
|
+
const modifiers = {
|
|
1031
|
+
ctrl: event.ctrlKey || event.metaKey,
|
|
1032
|
+
shift: event.shiftKey
|
|
1033
|
+
};
|
|
1034
|
+
if (this.multiple && modifiers.ctrl) {
|
|
1035
|
+
activeItem.selected = !activeItem.selected;
|
|
1036
|
+
this.lastSelectedIndex = activeIndex;
|
|
1037
|
+
} else if (this.multiple && modifiers.shift) {
|
|
1038
|
+
const items = this.getItems();
|
|
1039
|
+
const start = Math.min(this.lastSelectedIndex !== -1 ? this.lastSelectedIndex : 0, activeIndex);
|
|
1040
|
+
const end = Math.max(this.lastSelectedIndex !== -1 ? this.lastSelectedIndex : 0, activeIndex);
|
|
1041
|
+
items.forEach((item, i) => {
|
|
1042
|
+
if (i >= start && i <= end) item.selected = true;
|
|
1043
|
+
});
|
|
1044
|
+
} else this.selectSingleItem(activeItem);
|
|
1045
|
+
this.updateValueFromSelectedItems(true);
|
|
1046
|
+
this.resetRovingTabIndex();
|
|
1047
|
+
}
|
|
1048
|
+
handleSlotChange() {
|
|
1049
|
+
this.updateListboxAttributesOnItems();
|
|
1050
|
+
this.updateSelectedItems();
|
|
1051
|
+
this.resetRovingTabIndex();
|
|
1052
|
+
}
|
|
1053
|
+
selectSingleItem(item) {
|
|
1054
|
+
this.getItems().forEach((listItem) => {
|
|
1055
|
+
listItem.selected = listItem === item;
|
|
1056
|
+
});
|
|
1057
|
+
this.lastSelectedIndex = this.getItems().indexOf(item);
|
|
1058
|
+
}
|
|
1059
|
+
handleTypeahead(event) {
|
|
1060
|
+
if (event.ctrlKey || event.metaKey || event.altKey || event.key.length !== 1) return;
|
|
1061
|
+
this.clearTypeaheadTimeout();
|
|
1062
|
+
this.typeaheadBuffer += event.key.toLowerCase();
|
|
1063
|
+
this.typeaheadTimeout = window.setTimeout(() => {
|
|
1064
|
+
this.typeaheadBuffer = "";
|
|
1065
|
+
this.typeaheadTimeout = null;
|
|
1066
|
+
}, 1e3);
|
|
1067
|
+
const match = this.findTypeaheadMatch();
|
|
1068
|
+
if (match) {
|
|
1069
|
+
this.selectSingleItem(match);
|
|
1070
|
+
this.setActiveItem(match);
|
|
1071
|
+
this.updateValueFromSelectedItems(true);
|
|
1072
|
+
}
|
|
1073
|
+
}
|
|
1074
|
+
findTypeaheadMatch() {
|
|
1075
|
+
const items = this.getItems();
|
|
1076
|
+
const matchText = (idx) => (items[idx].textContent || "").trim().toLowerCase().startsWith(this.typeaheadBuffer);
|
|
1077
|
+
for (let i = 0; i < items.length; i++) if (matchText(i)) return items[i];
|
|
1078
|
+
return null;
|
|
1079
|
+
}
|
|
1080
|
+
setActiveItem(item) {
|
|
1081
|
+
this.getItems(true).forEach((i) => {
|
|
1082
|
+
const isActive = i === item;
|
|
1083
|
+
i.toggleAttribute("active", isActive);
|
|
1084
|
+
i.setAttribute("aria-current", isActive ? "true" : "false");
|
|
1085
|
+
});
|
|
1086
|
+
if (item) requestAnimationFrame(() => this.scrollItemIntoView(item));
|
|
1087
|
+
}
|
|
1088
|
+
scrollItemIntoView(item) {
|
|
1089
|
+
const listbox = this.listbox;
|
|
1090
|
+
const r1 = listbox.getBoundingClientRect();
|
|
1091
|
+
const r2 = item.getBoundingClientRect();
|
|
1092
|
+
const isRTL = this.localize.dir() === "rtl";
|
|
1093
|
+
if (r2.bottom > r1.bottom) listbox.scrollTop += r2.bottom - r1.bottom;
|
|
1094
|
+
else if (r2.top < r1.top) listbox.scrollTop -= r1.top - r2.top;
|
|
1095
|
+
if (isRTL) {
|
|
1096
|
+
if (r1.right < r2.right) listbox.scrollLeft -= r2.right - r1.right;
|
|
1097
|
+
else if (r1.left > r2.left) listbox.scrollLeft += r1.left - r2.left;
|
|
1098
|
+
} else if (r1.left > r2.left) listbox.scrollLeft += r2.left - r1.left;
|
|
1099
|
+
else if (r1.right < r2.right) listbox.scrollLeft -= r1.right - r2.right;
|
|
1100
|
+
}
|
|
1101
|
+
async updateValidity() {
|
|
1102
|
+
await this.updateComplete;
|
|
1103
|
+
const isValueMissing = this.required && this.firstSelectedValue === "";
|
|
1104
|
+
const hasCustomValidity = this.getCustomValidity().length > 0;
|
|
1105
|
+
this.isInvalid = isValueMissing || hasCustomValidity;
|
|
1106
|
+
this.internals.setValidity({
|
|
1107
|
+
badInput: false,
|
|
1108
|
+
customError: hasCustomValidity,
|
|
1109
|
+
patternMismatch: false,
|
|
1110
|
+
rangeOverflow: false,
|
|
1111
|
+
rangeUnderflow: false,
|
|
1112
|
+
stepMismatch: false,
|
|
1113
|
+
tooLong: false,
|
|
1114
|
+
tooShort: false,
|
|
1115
|
+
typeMismatch: false,
|
|
1116
|
+
valueMissing: isValueMissing
|
|
1117
|
+
}, isValueMissing ? VALIDATION_MESSAGE : this.getCustomValidity(), this.focusableAnchor);
|
|
1118
|
+
}
|
|
1119
|
+
/**
|
|
1120
|
+
* @internal Manage tab order and focus tracking for keyboard navigation
|
|
1121
|
+
*/
|
|
1122
|
+
resetRovingTabIndex() {
|
|
1123
|
+
const items = this.getItems();
|
|
1124
|
+
const selectedItem = this.getSelectedItems()[0];
|
|
1125
|
+
const targetIndex = selectedItem ? items.indexOf(selectedItem) : 0;
|
|
1126
|
+
items.forEach((item, index) => {
|
|
1127
|
+
item.tabIndex = -1;
|
|
1128
|
+
item.setAttribute("aria-current", index === targetIndex ? "true" : "false");
|
|
1129
|
+
});
|
|
1130
|
+
}
|
|
1131
|
+
/** Returns an array of all selected values. */
|
|
1132
|
+
getSelectedValues() {
|
|
1133
|
+
return this.selectedItems.map((item) => item.value);
|
|
1134
|
+
}
|
|
1135
|
+
/**
|
|
1136
|
+
* Sets the selected items by value(s) without triggering events.
|
|
1137
|
+
* Works for both single and multiple selection modes.
|
|
1138
|
+
* @param {string|string[]} values - Value(s) to select
|
|
1139
|
+
*/
|
|
1140
|
+
setSelectedValues(values) {
|
|
1141
|
+
const items = this.getItems(true);
|
|
1142
|
+
const valueArray = Array.isArray(values) ? values : [values];
|
|
1143
|
+
if (this.multiple) items.forEach((item) => {
|
|
1144
|
+
item.selected = valueArray.includes(item.value);
|
|
1145
|
+
});
|
|
1146
|
+
else {
|
|
1147
|
+
const firstValue = valueArray[0];
|
|
1148
|
+
items.forEach((item) => {
|
|
1149
|
+
item.selected = item.value === firstValue;
|
|
1150
|
+
});
|
|
1151
|
+
}
|
|
1152
|
+
this.updateValueFromSelectedItems(false);
|
|
1153
|
+
}
|
|
1154
|
+
/** Convenience method for selecting all items. */
|
|
1155
|
+
selectAll() {
|
|
1156
|
+
if (!this.multiple) return;
|
|
1157
|
+
this.getItems().forEach((item) => item.selected = true);
|
|
1158
|
+
this.updateValueFromSelectedItems();
|
|
1159
|
+
}
|
|
1160
|
+
/** Convenience method for deselecting all items. */
|
|
1161
|
+
deselectAll() {
|
|
1162
|
+
this.getItems().forEach((item) => item.selected = false);
|
|
1163
|
+
this.updateValueFromSelectedItems();
|
|
1164
|
+
}
|
|
1165
|
+
/** Sets focus to the listbox. */
|
|
1166
|
+
focus() {
|
|
1167
|
+
this.listbox.focus();
|
|
1168
|
+
}
|
|
1169
|
+
/** Removes focus from the listbox. */
|
|
1170
|
+
blur() {
|
|
1171
|
+
this.listbox.blur();
|
|
1172
|
+
}
|
|
1173
|
+
render() {
|
|
1174
|
+
const hasLabel = this.label || this.slotsWithContent.has("label");
|
|
1175
|
+
const hasDescription = this.description || this.slotsWithContent.has("description");
|
|
1176
|
+
return html`
|
|
1177
|
+
<label
|
|
1178
|
+
id="label"
|
|
1179
|
+
part="label"
|
|
1180
|
+
for="listbox"
|
|
1181
|
+
class=${classMap({ vh: !hasLabel })}
|
|
1182
|
+
@click=${this.handleLabelClick}
|
|
1183
|
+
>
|
|
1184
|
+
<slot name="label">${this.label}</slot>
|
|
1185
|
+
</label>
|
|
1186
|
+
|
|
1187
|
+
<div id="description" part="description" class=${classMap({ vh: !hasDescription })}>
|
|
1188
|
+
<slot name="description">${this.description}</slot>
|
|
1189
|
+
</div>
|
|
1190
|
+
|
|
1191
|
+
<div
|
|
1192
|
+
id="listbox"
|
|
1193
|
+
part="listbox"
|
|
1194
|
+
class=${classMap({
|
|
1195
|
+
xs: this.size === "xs",
|
|
1196
|
+
sm: this.size === "sm",
|
|
1197
|
+
md: this.size === "md",
|
|
1198
|
+
lg: this.size === "lg",
|
|
1199
|
+
xl: this.size === "xl",
|
|
1200
|
+
disabled: this.disabled,
|
|
1201
|
+
readonly: this.readonly,
|
|
1202
|
+
multiple: this.multiple
|
|
1203
|
+
})}
|
|
1204
|
+
role="listbox"
|
|
1205
|
+
aria-multiselectable=${this.multiple ? "true" : "false"}
|
|
1206
|
+
aria-disabled=${this.disabled ? "true" : "false"}
|
|
1207
|
+
aria-readonly=${this.readonly ? "true" : "false"}
|
|
1208
|
+
aria-required=${this.required ? "true" : "false"}
|
|
1209
|
+
aria-labelledby="label"
|
|
1210
|
+
aria-describedby="description"
|
|
1211
|
+
tabindex=${this.disabled ? "-1" : "0"}
|
|
1212
|
+
@blur=${this.handleBlur}
|
|
1213
|
+
@focus=${this.handleFocus}
|
|
1214
|
+
@pointerdown=${this.handleListboxPointerDown}
|
|
1215
|
+
@click=${this.handleItemClick}
|
|
1216
|
+
>
|
|
1217
|
+
<slot @slotchange=${this.handleSlotChange}></slot>
|
|
1218
|
+
</div>
|
|
1219
|
+
`;
|
|
1220
|
+
}
|
|
1221
|
+
};
|
|
1222
|
+
__decorate([query("#listbox")], SigveloListbox.prototype, "listbox", void 0);
|
|
1223
|
+
__decorate([state()], SigveloListbox.prototype, "hadUserInteraction", void 0);
|
|
1224
|
+
__decorate([state()], SigveloListbox.prototype, "isInvalid", void 0);
|
|
1225
|
+
__decorate([state()], SigveloListbox.prototype, "lastSelectedIndex", void 0);
|
|
1226
|
+
__decorate([state()], SigveloListbox.prototype, "previousValue", void 0);
|
|
1227
|
+
__decorate([state()], SigveloListbox.prototype, "typeaheadBuffer", void 0);
|
|
1228
|
+
__decorate([state()], SigveloListbox.prototype, "typeaheadTimeout", void 0);
|
|
1229
|
+
__decorate([state()], SigveloListbox.prototype, "wasChanged", void 0);
|
|
1230
|
+
__decorate([state()], SigveloListbox.prototype, "wasSubmitted", void 0);
|
|
1231
|
+
__decorate([property()], SigveloListbox.prototype, "label", void 0);
|
|
1232
|
+
__decorate([property()], SigveloListbox.prototype, "description", void 0);
|
|
1233
|
+
__decorate([property({ reflect: true })], SigveloListbox.prototype, "name", void 0);
|
|
1234
|
+
__decorate([property({
|
|
1235
|
+
type: Boolean,
|
|
1236
|
+
reflect: true
|
|
1237
|
+
})], SigveloListbox.prototype, "multiple", void 0);
|
|
1238
|
+
__decorate([property({
|
|
1239
|
+
type: Boolean,
|
|
1240
|
+
reflect: true
|
|
1241
|
+
})], SigveloListbox.prototype, "disabled", void 0);
|
|
1242
|
+
__decorate([property({
|
|
1243
|
+
type: Boolean,
|
|
1244
|
+
reflect: true
|
|
1245
|
+
})], SigveloListbox.prototype, "readonly", void 0);
|
|
1246
|
+
__decorate([property({ reflect: true })], SigveloListbox.prototype, "size", void 0);
|
|
1247
|
+
__decorate([property()], SigveloListbox.prototype, "form", void 0);
|
|
1248
|
+
__decorate([property({
|
|
1249
|
+
type: Boolean,
|
|
1250
|
+
reflect: true
|
|
1251
|
+
})], SigveloListbox.prototype, "required", void 0);
|
|
1252
|
+
__decorate([property()], SigveloListbox.prototype, "value", null);
|
|
1253
|
+
__decorate([property({ type: Array })], SigveloListbox.prototype, "selectedValues", null);
|
|
1254
|
+
SigveloListbox.disableWarning?.("change-in-update");
|
|
1255
|
+
customElements.define("sigvelo-listbox", SigveloListbox);
|
|
1256
|
+
//#endregion
|
|
1257
|
+
export { SigveloListbox as t };
|