@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,1123 @@
|
|
|
1
|
+
import { Localize } from "./utilities/localize.js";
|
|
2
|
+
import { t as __decorate } from "./decorate-DcF3lt7P.js";
|
|
3
|
+
import "./dropdown-item-i77cRuN6.js";
|
|
4
|
+
import { css, html } from "lit";
|
|
5
|
+
import { property, query } from "lit/decorators.js";
|
|
6
|
+
import hostStyles from "@mcp-b/wc-support/styles/host.styles";
|
|
7
|
+
import { SigveloElement } from "@mcp-b/wc-support/base/sigvelo-element";
|
|
8
|
+
import { animateWithClass } from "@mcp-b/wc-support/utilities/animate";
|
|
9
|
+
import { SigveloBeforeCloseEvent, SigveloBeforeOpenEvent, SigveloCloseEvent, SigveloOpenEvent } from "@mcp-b/wc-support/events/open-close";
|
|
10
|
+
import { lockScrolling, unlockScrolling } from "@mcp-b/wc-support/utilities/scroll";
|
|
11
|
+
import { LongPress, LongPressEvent } from "@mcp-b/wc-support/utilities/long-press";
|
|
12
|
+
import { autoUpdate, computePosition, flip, offset, shift, size } from "@floating-ui/dom";
|
|
13
|
+
import { createId } from "@mcp-b/wc-support/utilities/math";
|
|
14
|
+
import { SigveloSelectEvent } from "@mcp-b/wc-support/events/select";
|
|
15
|
+
import { activeElements } from "@mcp-b/wc-support/utilities/active-element";
|
|
16
|
+
//#region src/components/dropdown/dropdown.styles.ts
|
|
17
|
+
var dropdown_styles_default = css`
|
|
18
|
+
:host {
|
|
19
|
+
--show-duration: var(--sigvelo-motion-duration-interaction);
|
|
20
|
+
|
|
21
|
+
display: contents;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
#menu {
|
|
25
|
+
display: flex;
|
|
26
|
+
position: absolute;
|
|
27
|
+
top: 0;
|
|
28
|
+
left: 0;
|
|
29
|
+
flex-direction: column;
|
|
30
|
+
width: max-content;
|
|
31
|
+
margin: 0;
|
|
32
|
+
padding: 0.25em;
|
|
33
|
+
border: var(--sigvelo-border-style) var(--sigvelo-border-width)
|
|
34
|
+
var(--sigvelo-color-neutral-border-muted);
|
|
35
|
+
border-radius: var(--sigvelo-radius-md);
|
|
36
|
+
background-color: var(--sigvelo-color-surface);
|
|
37
|
+
box-shadow: var(--sigvelo-elevation-floating);
|
|
38
|
+
color: var(--sigvelo-color-neutral-text-on-subtle);
|
|
39
|
+
text-align: start;
|
|
40
|
+
user-select: none;
|
|
41
|
+
|
|
42
|
+
&.show {
|
|
43
|
+
animation: show var(--show-duration) ease;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
&.hide {
|
|
47
|
+
animation: show var(--show-duration) ease reverse;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
::slotted(h1),
|
|
51
|
+
::slotted(h2),
|
|
52
|
+
::slotted(h3),
|
|
53
|
+
::slotted(h4),
|
|
54
|
+
::slotted(h5),
|
|
55
|
+
::slotted(h6) {
|
|
56
|
+
display: block !important;
|
|
57
|
+
margin: 0.25em 0 !important;
|
|
58
|
+
padding: 0.25em 1em !important;
|
|
59
|
+
color: var(--sigvelo-color-text-muted) !important;
|
|
60
|
+
font-weight: var(--sigvelo-font-weight-semibold) !important;
|
|
61
|
+
font-size: 0.75em !important;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
::slotted(sigvelo-divider) {
|
|
65
|
+
--spacing: 0.25em;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
:host([data-placement^="top"]) #menu {
|
|
70
|
+
transform-origin: bottom;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
:host([data-placement^="bottom"]) #menu {
|
|
74
|
+
transform-origin: top;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
:host([data-placement^="left"]) #menu {
|
|
78
|
+
transform-origin: right;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
:host([data-placement^="right"]) #menu {
|
|
82
|
+
transform-origin: left;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
:host([data-placement="left-start"]) #menu {
|
|
86
|
+
transform-origin: right top;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
:host([data-placement="left-end"]) #menu {
|
|
90
|
+
transform-origin: right bottom;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
:host([data-placement="right-start"]) #menu {
|
|
94
|
+
transform-origin: left top;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
:host([data-placement="right-end"]) #menu {
|
|
98
|
+
transform-origin: left bottom;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
@keyframes show {
|
|
102
|
+
from {
|
|
103
|
+
scale: 0.9;
|
|
104
|
+
opacity: 0;
|
|
105
|
+
}
|
|
106
|
+
to {
|
|
107
|
+
scale: 1;
|
|
108
|
+
opacity: 1;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
`;
|
|
112
|
+
//#endregion
|
|
113
|
+
//#region src/components/dropdown/dropdown.ts
|
|
114
|
+
const openDropdowns = /* @__PURE__ */ new Set();
|
|
115
|
+
/**
|
|
116
|
+
* <sigvelo-dropdown>
|
|
117
|
+
*
|
|
118
|
+
* @summary Provides a menu of options that appear when the corresponding trigger is activated.
|
|
119
|
+
* @tag sigvelo-dropdown
|
|
120
|
+
* @documentation https://design-system.sigvelo.com/docs/components/dropdown
|
|
121
|
+
* @status stable
|
|
122
|
+
* @since 1.0
|
|
123
|
+
*
|
|
124
|
+
* @dependency sigvelo-dropdown-item
|
|
125
|
+
*
|
|
126
|
+
* @slot - One or more `<dropdown-item>` elements to show in the dropdown. You can also use `<sigvelo-divider>` here.
|
|
127
|
+
* @slot trigger - The dropdown's trigger. Must be a `<sigvelo-button>` or `<button>` element.
|
|
128
|
+
*
|
|
129
|
+
* @event sigvelo-before-open - Emitted when the dropdown is instructed to open but before it is shown.
|
|
130
|
+
* @event sigvelo-open - Emitted when the dropdown menu has opened and the animation has completed.
|
|
131
|
+
* @event sigvelo-before-close - Emitted when the dropdown is dismissed but before it is hidden.
|
|
132
|
+
* @event sigvelo-close - Emitted when the dropdown menu has closed and the animation has completed.
|
|
133
|
+
* @event sigvelo-select - Emitted when a dropdown item has been selected. You can inspect `event.detail.item` to see the
|
|
134
|
+
* `<sigvelo-dropdown-item>` that was selected. Calling `event.preventDefault()` will keep the dropdown open.
|
|
135
|
+
*
|
|
136
|
+
* @cssproperty [--show-duration=50ms] - The duration of the show/hide animation.
|
|
137
|
+
*
|
|
138
|
+
* @csspart menu - The dropdown menu's container.
|
|
139
|
+
*
|
|
140
|
+
* @cssstate open - Applied when the dropdown is open.
|
|
141
|
+
*
|
|
142
|
+
* @example Default
|
|
143
|
+
* Dropdown menus appear when their trigger element is clicked. They are not modal, so no overlay is shown when open. Dropdowns will close when the user selects an item, clicks outside of them, or presses [[Escape]]. Only one dropdown can be open at a time.
|
|
144
|
+
*
|
|
145
|
+
* ```html
|
|
146
|
+
* <sigvelo-dropdown>
|
|
147
|
+
* <sigvelo-button slot="trigger" with-caret>
|
|
148
|
+
* <sigvelo-icon slot="start" name="mail"></sigvelo-icon>
|
|
149
|
+
* Message
|
|
150
|
+
* </sigvelo-button>
|
|
151
|
+
*
|
|
152
|
+
* <h3>Actions</h3>
|
|
153
|
+
*
|
|
154
|
+
* <sigvelo-dropdown-item value="reply">
|
|
155
|
+
* <sigvelo-icon slot="icon" name="corner-up-left"></sigvelo-icon>
|
|
156
|
+
* Reply
|
|
157
|
+
* <sigvelo-hotkey slot="details" keys="$cmdctrl R" variant="unstyled"></sigvelo-hotkey>
|
|
158
|
+
* </sigvelo-dropdown-item>
|
|
159
|
+
*
|
|
160
|
+
* <sigvelo-dropdown-item value="forward">
|
|
161
|
+
* <sigvelo-icon slot="icon" name="corner-up-right"></sigvelo-icon>
|
|
162
|
+
* Forward
|
|
163
|
+
* <sigvelo-hotkey slot="details" keys="$cmdctrl F" variant="unstyled"></sigvelo-hotkey>
|
|
164
|
+
* </sigvelo-dropdown-item>
|
|
165
|
+
*
|
|
166
|
+
* <sigvelo-dropdown-item value="archive">
|
|
167
|
+
* <sigvelo-icon slot="icon" name="archive"></sigvelo-icon>
|
|
168
|
+
* Archive
|
|
169
|
+
* <sigvelo-hotkey slot="details" keys="$shift $cmdctrl A" variant="unstyled"></sigvelo-hotkey>
|
|
170
|
+
* </sigvelo-dropdown-item>
|
|
171
|
+
*
|
|
172
|
+
* <sigvelo-dropdown-item value="delete" color="destructive">
|
|
173
|
+
* <sigvelo-icon slot="icon" name="trash"></sigvelo-icon>
|
|
174
|
+
* Delete
|
|
175
|
+
* <span slot="details">Del</span>
|
|
176
|
+
* </sigvelo-dropdown-item>
|
|
177
|
+
*
|
|
178
|
+
* <sigvelo-divider></sigvelo-divider>
|
|
179
|
+
*
|
|
180
|
+
* <sigvelo-dropdown-item value="images" type="checkbox" checked>
|
|
181
|
+
* Show images
|
|
182
|
+
* </sigvelo-dropdown-item>
|
|
183
|
+
*
|
|
184
|
+
* <sigvelo-dropdown-item value="wrap" type="checkbox" checked>
|
|
185
|
+
* Word wrap
|
|
186
|
+
* </sigvelo-dropdown-item>
|
|
187
|
+
*
|
|
188
|
+
* <sigvelo-divider></sigvelo-divider>
|
|
189
|
+
*
|
|
190
|
+
* <sigvelo-dropdown-item>
|
|
191
|
+
* <sigvelo-icon slot="icon" name="tag"></sigvelo-icon>
|
|
192
|
+
* Labels
|
|
193
|
+
* <sigvelo-dropdown-item slot="submenu" value="add-label">
|
|
194
|
+
* <sigvelo-icon slot="icon" name="plus"></sigvelo-icon>
|
|
195
|
+
* Add label
|
|
196
|
+
* </sigvelo-dropdown-item>
|
|
197
|
+
* <sigvelo-dropdown-item slot="submenu" value="manage-labels">
|
|
198
|
+
* <sigvelo-icon slot="icon" name="edit"></sigvelo-icon>
|
|
199
|
+
* Manage labels
|
|
200
|
+
* </sigvelo-dropdown-item>
|
|
201
|
+
* </sigvelo-dropdown-item>
|
|
202
|
+
*
|
|
203
|
+
* <sigvelo-dropdown-item value="preferences">
|
|
204
|
+
* <sigvelo-icon slot="icon" name="adjustments-horizontal"></sigvelo-icon>
|
|
205
|
+
* Preferences
|
|
206
|
+
* </sigvelo-dropdown-item>
|
|
207
|
+
* </sigvelo-dropdown>
|
|
208
|
+
* ```
|
|
209
|
+
*
|
|
210
|
+
* @example Getting the selected item
|
|
211
|
+
* When an item is selected, the `sigvelo-select` event will be emitted by the dropdown. You can inspect `event.detail.item` to get a reference to the selected item. If you've provided a value for each dropdown item, it will be available in `event.detail.item.value`.
|
|
212
|
+
*
|
|
213
|
+
* ```html
|
|
214
|
+
* <sigvelo-dropdown id="dropdown__selected">
|
|
215
|
+
* <sigvelo-button slot="trigger" with-caret>View</sigvelo-button>
|
|
216
|
+
* <sigvelo-dropdown-item value="full-screen">Enter full screen</sigvelo-dropdown-item>
|
|
217
|
+
* <sigvelo-dropdown-item value="actual">Actual size</sigvelo-dropdown-item>
|
|
218
|
+
* <sigvelo-dropdown-item value="zoom-in">Zoom in</sigvelo-dropdown-item>
|
|
219
|
+
* <sigvelo-dropdown-item value="zoom-out">Zoom out</sigvelo-dropdown-item>
|
|
220
|
+
* </sigvelo-dropdown>
|
|
221
|
+
*
|
|
222
|
+
* <script>
|
|
223
|
+
* const dropdown = document.getElementById('dropdown__selected');
|
|
224
|
+
*
|
|
225
|
+
* dropdown.addEventListener('sigvelo-select', event => {
|
|
226
|
+
* console.log(event.detail.item.value);
|
|
227
|
+
* });
|
|
228
|
+
* <\/script>
|
|
229
|
+
* ```
|
|
230
|
+
*
|
|
231
|
+
* **Note:** To keep the dropdown open after selection, call `event.preventDefault()` in the `sigvelo-select` event's callback.
|
|
232
|
+
*
|
|
233
|
+
* @example Showing icons
|
|
234
|
+
* Use the `icon` slot to add icons to dropdown items. This works best with icon elements.
|
|
235
|
+
*
|
|
236
|
+
* ```html
|
|
237
|
+
* <sigvelo-dropdown>
|
|
238
|
+
* <sigvelo-button slot="trigger" with-caret>Edit</sigvelo-button>
|
|
239
|
+
*
|
|
240
|
+
* <sigvelo-dropdown-item value="cut">
|
|
241
|
+
* <sigvelo-icon slot="icon" name="scissors"></sigvelo-icon>
|
|
242
|
+
* Cut
|
|
243
|
+
* </sigvelo-dropdown-item>
|
|
244
|
+
*
|
|
245
|
+
* <sigvelo-dropdown-item value="copy">
|
|
246
|
+
* <sigvelo-icon slot="icon" name="clipboard-copy"></sigvelo-icon>
|
|
247
|
+
* Copy
|
|
248
|
+
* </sigvelo-dropdown-item>
|
|
249
|
+
*
|
|
250
|
+
* <sigvelo-dropdown-item value="paste">
|
|
251
|
+
* <sigvelo-icon slot="icon" name="clipboard-plus"></sigvelo-icon>
|
|
252
|
+
* Paste
|
|
253
|
+
* </sigvelo-dropdown-item>
|
|
254
|
+
*
|
|
255
|
+
* <sigvelo-dropdown-item value="delete">
|
|
256
|
+
* <sigvelo-icon slot="icon" name="backspace"></sigvelo-icon>
|
|
257
|
+
* Delete
|
|
258
|
+
* </sigvelo-dropdown-item>
|
|
259
|
+
* </sigvelo-dropdown>
|
|
260
|
+
* ```
|
|
261
|
+
*
|
|
262
|
+
* @example Showing labels & dividers
|
|
263
|
+
* Use any heading, e.g. `<h1>`–`<h6>` to add labels and the `<sigvelo-divider>` element for separators.
|
|
264
|
+
*
|
|
265
|
+
* ```html
|
|
266
|
+
* <sigvelo-dropdown>
|
|
267
|
+
* <sigvelo-button slot="trigger" with-caret>Device</sigvelo-button>
|
|
268
|
+
* <h3>Type</h3>
|
|
269
|
+
* <sigvelo-dropdown-item value="phone">Phone</sigvelo-dropdown-item>
|
|
270
|
+
* <sigvelo-dropdown-item value="tablet">Tablet</sigvelo-dropdown-item>
|
|
271
|
+
* <sigvelo-dropdown-item value="desktop">Desktop</sigvelo-dropdown-item>
|
|
272
|
+
* <sigvelo-divider></sigvelo-divider>
|
|
273
|
+
* <sigvelo-dropdown-item value="more">More options…</sigvelo-dropdown-item>
|
|
274
|
+
* </sigvelo-dropdown>
|
|
275
|
+
* ```
|
|
276
|
+
*
|
|
277
|
+
* @example Showing details
|
|
278
|
+
* Use the `details` slot to display details, such as keyboard shortcuts, inside dropdown items.
|
|
279
|
+
*
|
|
280
|
+
* ```html
|
|
281
|
+
* <sigvelo-dropdown>
|
|
282
|
+
* <sigvelo-button slot="trigger" with-caret>Message</sigvelo-button>
|
|
283
|
+
*
|
|
284
|
+
* <sigvelo-dropdown-item value="reply">
|
|
285
|
+
* Reply
|
|
286
|
+
* <sigvelo-hotkey slot="details" keys="$cmdctrl R" variant="unstyled"></sigvelo-hotkey>
|
|
287
|
+
* </sigvelo-dropdown-item>
|
|
288
|
+
*
|
|
289
|
+
* <sigvelo-dropdown-item value="forward">
|
|
290
|
+
* Forward
|
|
291
|
+
* <sigvelo-hotkey slot="details" keys="$cmdctrl F" variant="unstyled"></sigvelo-hotkey>
|
|
292
|
+
* </sigvelo-dropdown-item>
|
|
293
|
+
*
|
|
294
|
+
* <sigvelo-dropdown-item value="move">
|
|
295
|
+
* Move
|
|
296
|
+
* <sigvelo-hotkey slot="details" keys="$cmdctrl M" variant="unstyled"></sigvelo-hotkey>
|
|
297
|
+
* </sigvelo-dropdown-item>
|
|
298
|
+
*
|
|
299
|
+
* <sigvelo-divider></sigvelo-divider>
|
|
300
|
+
*
|
|
301
|
+
* <sigvelo-dropdown-item value="archive">
|
|
302
|
+
* Archive
|
|
303
|
+
* <sigvelo-hotkey slot="details" keys="$cmdctrl A" variant="unstyled"></sigvelo-hotkey>
|
|
304
|
+
* </sigvelo-dropdown-item>
|
|
305
|
+
*
|
|
306
|
+
* <sigvelo-dropdown-item value="delete" color="destructive">
|
|
307
|
+
* Delete
|
|
308
|
+
* <span slot="details">Delete</span>
|
|
309
|
+
* </sigvelo-dropdown-item>
|
|
310
|
+
* </sigvelo-dropdown>
|
|
311
|
+
* ```
|
|
312
|
+
*
|
|
313
|
+
* @example Checkable items
|
|
314
|
+
* You can turn a dropdown item into a checkable option by setting `type="checkbox"`. Add the `checked` attribute to make it checked initially. When clicked, the item's checked state will toggle and the dropdown will close. You can cancel the `sigvelo-select` event if you want to keep it open instead.
|
|
315
|
+
*
|
|
316
|
+
* ```html
|
|
317
|
+
* <sigvelo-dropdown id="dropdown__checkboxes">
|
|
318
|
+
* <sigvelo-button slot="trigger" with-caret>View</sigvelo-button>
|
|
319
|
+
* <sigvelo-dropdown-item type="checkbox" value="canvas" checked>Show canvas</sigvelo-dropdown-item>
|
|
320
|
+
* <sigvelo-dropdown-item type="checkbox" value="grid" checked>Show grid</sigvelo-dropdown-item>
|
|
321
|
+
* <sigvelo-dropdown-item type="checkbox" value="source">Show source</sigvelo-dropdown-item>
|
|
322
|
+
* <sigvelo-divider></sigvelo-divider>
|
|
323
|
+
* <sigvelo-dropdown-item value="preferences">Preferences…</sigvelo-dropdown-item>
|
|
324
|
+
* </sigvelo-dropdown>
|
|
325
|
+
*
|
|
326
|
+
* <script>
|
|
327
|
+
* const dropdown = document.getElementById('dropdown__checkboxes');
|
|
328
|
+
*
|
|
329
|
+
* dropdown.addEventListener('sigvelo-select', event => {
|
|
330
|
+
* if (event.detail.item.type === 'checkbox') {
|
|
331
|
+
* // Checkbox
|
|
332
|
+
* console.log(
|
|
333
|
+
* event.detail.item.value,
|
|
334
|
+
* event.detail.item.checked ? 'checked' : 'unchecked'
|
|
335
|
+
* );
|
|
336
|
+
* } else {
|
|
337
|
+
* // Not a checkbox
|
|
338
|
+
* console.log(event.detail.item.value);
|
|
339
|
+
* }
|
|
340
|
+
* });
|
|
341
|
+
* <\/script>
|
|
342
|
+
* ```
|
|
343
|
+
*
|
|
344
|
+
* **Note:** When a checkable option exists anywhere in the dropdown, all of items will receive additional padding so they align properly.
|
|
345
|
+
*
|
|
346
|
+
* @example Destructive items
|
|
347
|
+
* Add `color="destructive"` to any dropdown item to highlight that it's a dangerous action.
|
|
348
|
+
*
|
|
349
|
+
* ```html
|
|
350
|
+
* <sigvelo-dropdown>
|
|
351
|
+
* <sigvelo-button slot="trigger" with-caret>Project</sigvelo-button>
|
|
352
|
+
*
|
|
353
|
+
* <sigvelo-dropdown-item value="share">
|
|
354
|
+
* <sigvelo-icon slot="icon" name="share-2"></sigvelo-icon>
|
|
355
|
+
* Share
|
|
356
|
+
* </sigvelo-dropdown-item>
|
|
357
|
+
*
|
|
358
|
+
* <sigvelo-dropdown-item value="preferences">
|
|
359
|
+
* <sigvelo-icon slot="icon" name="adjustments-horizontal"></sigvelo-icon>
|
|
360
|
+
* Preferences
|
|
361
|
+
* </sigvelo-dropdown-item>
|
|
362
|
+
*
|
|
363
|
+
* <sigvelo-divider></sigvelo-divider>
|
|
364
|
+
*
|
|
365
|
+
* <h3>Danger zone</h3>
|
|
366
|
+
*
|
|
367
|
+
* <sigvelo-dropdown-item value="archive">
|
|
368
|
+
* <sigvelo-icon slot="icon" name="archive"></sigvelo-icon>
|
|
369
|
+
* Archive
|
|
370
|
+
* </sigvelo-dropdown-item>
|
|
371
|
+
*
|
|
372
|
+
* <sigvelo-dropdown-item value="delete" color="destructive">
|
|
373
|
+
* <sigvelo-icon slot="icon" name="trash"></sigvelo-icon>
|
|
374
|
+
* Delete
|
|
375
|
+
* </sigvelo-dropdown-item>
|
|
376
|
+
* </sigvelo-dropdown>
|
|
377
|
+
* ```
|
|
378
|
+
*
|
|
379
|
+
* @example Link items
|
|
380
|
+
* Add `href` to any dropdown item to make it behave like a link. When selected, the browser will navigate to the target URL. When creating link items, you can also use the `target`, `rel`, and `download` attributes to control how the link opens.
|
|
381
|
+
*
|
|
382
|
+
* ```html
|
|
383
|
+
* <sigvelo-dropdown>
|
|
384
|
+
* <sigvelo-button slot="trigger" with-caret>Components</sigvelo-button>
|
|
385
|
+
* <sigvelo-dropdown-item href="/docs/components/button">Button</sigvelo-dropdown-item>
|
|
386
|
+
* <sigvelo-dropdown-item href="/docs/components/checkbox">Checkbox</sigvelo-dropdown-item>
|
|
387
|
+
* <sigvelo-dropdown-item href="/docs/components/radio">Radio</sigvelo-dropdown-item>
|
|
388
|
+
* <sigvelo-dropdown-item href="/docs/components/switch">Switch</sigvelo-dropdown-item>
|
|
389
|
+
* <sigvelo-dropdown-item href="/docs/components/text-field">Text Field</sigvelo-dropdown-item>
|
|
390
|
+
* <sigvelo-dropdown-item href="/docs/components/text-area">Text Area</sigvelo-dropdown-item>
|
|
391
|
+
* <sigvelo-divider></sigvelo-divider>
|
|
392
|
+
* <sigvelo-dropdown-item href="https://example.com/" target="_blank">
|
|
393
|
+
* Visit external website
|
|
394
|
+
* <sigvelo-icon name="external-link" slot="icon"></sigvelo-icon>
|
|
395
|
+
* </sigvelo-dropdown-item>
|
|
396
|
+
* </sigvelo-dropdown>
|
|
397
|
+
* ```
|
|
398
|
+
*
|
|
399
|
+
* **Note:** Note that link items are not actual links! You won't see a URL when hovering and users of assistive devices will need to infer it's behavior from context. When a link item is selected, the component renders a hidden link and dispatches a synthetic event to open it. Modifier keys are passed from the original event, but only Chrome and Firefox appear to honor them. Safari opens the link, but ignores modifier keys.
|
|
400
|
+
*
|
|
401
|
+
* @example Submenus
|
|
402
|
+
* To create submenus, nest additional dropdown items in a dropdown item and assign `slot="submenu"` to them. You can also add dividers as needed.
|
|
403
|
+
*
|
|
404
|
+
* ```html
|
|
405
|
+
* <sigvelo-dropdown id="dropdown__submenus">
|
|
406
|
+
* <sigvelo-button slot="trigger" with-caret>Cat Type</sigvelo-button>
|
|
407
|
+
*
|
|
408
|
+
* <sigvelo-dropdown-item>
|
|
409
|
+
* Domestic
|
|
410
|
+
* <sigvelo-dropdown-item slot="submenu" value="shorthair">Shorthair</sigvelo-dropdown-item>
|
|
411
|
+
* <sigvelo-dropdown-item slot="submenu" value="longhair">Longhair</sigvelo-dropdown-item>
|
|
412
|
+
* </sigvelo-dropdown-item>
|
|
413
|
+
*
|
|
414
|
+
* <sigvelo-dropdown-item>
|
|
415
|
+
* Pedigree
|
|
416
|
+
* <sigvelo-dropdown-item slot="submenu">
|
|
417
|
+
* European
|
|
418
|
+
* <sigvelo-dropdown-item slot="submenu" value="british">British Shorthair</sigvelo-dropdown-item>
|
|
419
|
+
* <sigvelo-dropdown-item slot="submenu" value="scottish">Scottish Fold</sigvelo-dropdown-item>
|
|
420
|
+
* <sigvelo-dropdown-item slot="submenu" value="chartreux">Chartreux</sigvelo-dropdown-item>
|
|
421
|
+
* </sigvelo-dropdown-item>
|
|
422
|
+
*
|
|
423
|
+
* <sigvelo-dropdown-item slot="submenu">
|
|
424
|
+
* Asian
|
|
425
|
+
* <sigvelo-dropdown-item slot="submenu" value="siamese">Siamese</sigvelo-dropdown-item>
|
|
426
|
+
* <sigvelo-dropdown-item slot="submenu" value="bengal">Bengal</sigvelo-dropdown-item>
|
|
427
|
+
* <sigvelo-dropdown-item slot="submenu" value="burmese">Burmese</sigvelo-dropdown-item>
|
|
428
|
+
* </sigvelo-dropdown-item>
|
|
429
|
+
*
|
|
430
|
+
* <sigvelo-dropdown-item slot="submenu" value="american">American Breeds</sigvelo-dropdown-item>
|
|
431
|
+
* </sigvelo-dropdown-item>
|
|
432
|
+
*
|
|
433
|
+
* <sigvelo-divider></sigvelo-divider>
|
|
434
|
+
*
|
|
435
|
+
* <sigvelo-dropdown-item>
|
|
436
|
+
* Sizes
|
|
437
|
+
* <sigvelo-dropdown-item slot="submenu" type="checkbox" value="small">Small</sigvelo-dropdown-item>
|
|
438
|
+
* <sigvelo-dropdown-item slot="submenu" type="checkbox" checked value="medium">Medium</sigvelo-dropdown-item>
|
|
439
|
+
* <sigvelo-dropdown-item slot="submenu" type="checkbox" value="large">Large</sigvelo-dropdown-item>
|
|
440
|
+
* </sigvelo-dropdown-item>
|
|
441
|
+
* </sigvelo-dropdown>
|
|
442
|
+
*
|
|
443
|
+
* <script>
|
|
444
|
+
* const dropdown = document.getElementById('dropdown__submenus');
|
|
445
|
+
*
|
|
446
|
+
* dropdown.addEventListener('sigvelo-select', event => {
|
|
447
|
+
* console.log(event.detail.item.value);
|
|
448
|
+
* });
|
|
449
|
+
* <\/script>
|
|
450
|
+
* ```
|
|
451
|
+
*
|
|
452
|
+
* **Note:** Dropdown items that contain a submenu will not dispatch the `sigvelo-select` event when clicked. However, items inside of the submenu will, unless they also have a submenu.
|
|
453
|
+
*
|
|
454
|
+
* @example Disabling items
|
|
455
|
+
* Add the `disabled` attribute to any dropdown item to disabled it.
|
|
456
|
+
*
|
|
457
|
+
* ```html
|
|
458
|
+
* <sigvelo-dropdown>
|
|
459
|
+
* <sigvelo-button slot="trigger" with-caret>Payment method</sigvelo-button>
|
|
460
|
+
* <sigvelo-dropdown-item value="cash">Cash</sigvelo-dropdown-item>
|
|
461
|
+
* <sigvelo-dropdown-item value="check" disabled>Personal check</sigvelo-dropdown-item>
|
|
462
|
+
* <sigvelo-dropdown-item value="credit">Credit card</sigvelo-dropdown-item>
|
|
463
|
+
* <sigvelo-dropdown-item value="gift-card">Gift card</sigvelo-dropdown-item>
|
|
464
|
+
* </sigvelo-dropdown>
|
|
465
|
+
* ```
|
|
466
|
+
*
|
|
467
|
+
* @example Changing the placement
|
|
468
|
+
* You can set the preferred placement of the dropdown menu with the `placement` attribute. The menu will shift to a more optimal location if the preferred placement doesn't have enough room.
|
|
469
|
+
*
|
|
470
|
+
* ```html
|
|
471
|
+
* <sigvelo-dropdown placement="right">
|
|
472
|
+
* <sigvelo-button slot="trigger">
|
|
473
|
+
* Types of cats
|
|
474
|
+
* <sigvelo-icon slot="end" name="chevron-right"></sigvelo-icon>
|
|
475
|
+
* </sigvelo-button>
|
|
476
|
+
* <sigvelo-dropdown-item value="bengal">Bengal</sigvelo-dropdown-item>
|
|
477
|
+
* <sigvelo-dropdown-item value="calico">Calico</sigvelo-dropdown-item>
|
|
478
|
+
* <sigvelo-dropdown-item value="maine-coon">Maine coon</sigvelo-dropdown-item>
|
|
479
|
+
* <sigvelo-dropdown-item value="siamese">Siamese</sigvelo-dropdown-item>
|
|
480
|
+
* <sigvelo-dropdown-item value="tabby">Tabby</sigvelo-dropdown-item>
|
|
481
|
+
* <sigvelo-dropdown-item value="tuxedo">Tuxedo</sigvelo-dropdown-item>
|
|
482
|
+
* </sigvelo-dropdown>
|
|
483
|
+
* ```
|
|
484
|
+
*
|
|
485
|
+
* @example Context menus
|
|
486
|
+
* To turn a dropdown menu into a context menu, omit the trigger and set the `context-menu` attribute to the ID of an element in the same document. When you right-click or long press (touch only) the target element, the context menu will be shown.
|
|
487
|
+
*
|
|
488
|
+
* ```html
|
|
489
|
+
* <div id="dropdown__context" tabindex="0">
|
|
490
|
+
* Right-click or long press here to show the context menu
|
|
491
|
+
* </div>
|
|
492
|
+
*
|
|
493
|
+
* <sigvelo-dropdown context-menu="dropdown__context">
|
|
494
|
+
* <sigvelo-dropdown-item value="cut">Cut</sigvelo-dropdown-item>
|
|
495
|
+
* <sigvelo-dropdown-item value="cut">Copy</sigvelo-dropdown-item>
|
|
496
|
+
* <sigvelo-dropdown-item value="cut">Paste</sigvelo-dropdown-item>
|
|
497
|
+
* <sigvelo-divider></sigvelo-divider>
|
|
498
|
+
* <sigvelo-dropdown-item>
|
|
499
|
+
* Adjust
|
|
500
|
+
* <sigvelo-dropdown-item slot="submenu" value="brightness">Brightness</sigvelo-dropdown-item>
|
|
501
|
+
* <sigvelo-dropdown-item slot="submenu" value="contrast">Contrast</sigvelo-dropdown-item>
|
|
502
|
+
* </sigvelo-dropdown-item>
|
|
503
|
+
* <sigvelo-dropdown-item>
|
|
504
|
+
* Filters
|
|
505
|
+
* <sigvelo-dropdown-item slot="submenu">
|
|
506
|
+
* Artistic
|
|
507
|
+
* <sigvelo-dropdown-item slot="submenu" value="watercolor">Watercolor</sigvelo-dropdown-item>
|
|
508
|
+
* <sigvelo-dropdown-item slot="submenu" value="oil-paint">Oil Paint</sigvelo-dropdown-item>
|
|
509
|
+
* <sigvelo-dropdown-item slot="submenu" value="sketch">Sketch</sigvelo-dropdown-item>
|
|
510
|
+
* </sigvelo-dropdown-item>
|
|
511
|
+
* <sigvelo-dropdown-item slot="submenu">
|
|
512
|
+
* Color
|
|
513
|
+
* <sigvelo-dropdown-item slot="submenu" value="grayscale">Grayscale</sigvelo-dropdown-item>
|
|
514
|
+
* <sigvelo-dropdown-item slot="submenu" value="sepia">Sepia</sigvelo-dropdown-item>
|
|
515
|
+
* <sigvelo-dropdown-item slot="submenu" value="vibrance">Vibrance</sigvelo-dropdown-item>
|
|
516
|
+
* </sigvelo-dropdown-item>
|
|
517
|
+
* <sigvelo-dropdown-item slot="submenu" value="blur">Blur Effects</sigvelo-dropdown-item>
|
|
518
|
+
* </sigvelo-dropdown-item>
|
|
519
|
+
* <sigvelo-dropdown-item>
|
|
520
|
+
* Transform
|
|
521
|
+
* <sigvelo-dropdown-item slot="submenu" value="crop">Crop</sigvelo-dropdown-item>
|
|
522
|
+
* <sigvelo-dropdown-item slot="submenu" value="rotate">Rotate</sigvelo-dropdown-item>
|
|
523
|
+
* <sigvelo-dropdown-item slot="submenu" value="resize">Resize</sigvelo-dropdown-item>
|
|
524
|
+
* </sigvelo-dropdown-item>
|
|
525
|
+
* </sigvelo-dropdown>
|
|
526
|
+
*
|
|
527
|
+
* <style>
|
|
528
|
+
* #dropdown__context {
|
|
529
|
+
* display: flex;
|
|
530
|
+
* align-items: center;
|
|
531
|
+
* justify-content: center;
|
|
532
|
+
* text-align: center;
|
|
533
|
+
* min-height: 200px;
|
|
534
|
+
* color: var(--sigvelo-color-text-muted);
|
|
535
|
+
* background-color: var(--sigvelo-color-surface);
|
|
536
|
+
* border: dashed var(--sigvelo-border-width) var(--sigvelo-color-neutral-border-muted);
|
|
537
|
+
* border-radius: var(--sigvelo-radius-md);
|
|
538
|
+
* padding: 1rem;
|
|
539
|
+
*
|
|
540
|
+
* &:focus {
|
|
541
|
+
* outline: none;
|
|
542
|
+
* }
|
|
543
|
+
*
|
|
544
|
+
* &:focus-visible {
|
|
545
|
+
* outline: var(--sigvelo-focus-ring);
|
|
546
|
+
* outline-offset: calc(var(--sigvelo-border-width) * -1);
|
|
547
|
+
* }
|
|
548
|
+
* }
|
|
549
|
+
* </style>
|
|
550
|
+
* ```
|
|
551
|
+
*
|
|
552
|
+
* **Warning:** The context menu element must be in the DOM when the dropdown is connected, otherwise the dropdown won't be attached and a warning will be shown in the console.
|
|
553
|
+
*/
|
|
554
|
+
var SigveloDropdown = class SigveloDropdown extends SigveloElement {
|
|
555
|
+
constructor(..._args) {
|
|
556
|
+
super(..._args);
|
|
557
|
+
this.submenuCleanups = /* @__PURE__ */ new Map();
|
|
558
|
+
this.localize = new Localize(this);
|
|
559
|
+
this.userTypedQuery = "";
|
|
560
|
+
this.openSubmenuStack = [];
|
|
561
|
+
this.open = false;
|
|
562
|
+
this.contextMenu = "";
|
|
563
|
+
this.placement = "bottom-start";
|
|
564
|
+
this.distance = 0;
|
|
565
|
+
this.offset = 0;
|
|
566
|
+
this.handleDocumentFocusIn = (event) => {
|
|
567
|
+
const path = event.composedPath();
|
|
568
|
+
if (!path.includes(this) && this.contextMenuElement && !path.includes(this.contextMenuElement)) this.open = false;
|
|
569
|
+
};
|
|
570
|
+
this.handleDocumentKeyDown = (event) => {
|
|
571
|
+
const isRtl = this.localize.dir() === "rtl";
|
|
572
|
+
if (event.key === "Escape") {
|
|
573
|
+
const trigger = this.getTrigger();
|
|
574
|
+
event.preventDefault();
|
|
575
|
+
event.stopPropagation();
|
|
576
|
+
this.open = false;
|
|
577
|
+
trigger?.focus();
|
|
578
|
+
return;
|
|
579
|
+
}
|
|
580
|
+
const activeElement = [...activeElements()].find((el) => el.localName === "sigvelo-dropdown-item");
|
|
581
|
+
const isFocusedOnItem = activeElement?.localName === "sigvelo-dropdown-item";
|
|
582
|
+
const currentSubmenuItem = this.getCurrentSubmenuItem();
|
|
583
|
+
const isInSubmenu = !!currentSubmenuItem;
|
|
584
|
+
let items;
|
|
585
|
+
let activeItem;
|
|
586
|
+
let activeItemIndex;
|
|
587
|
+
if (isInSubmenu) {
|
|
588
|
+
items = this.getSubmenuItems(currentSubmenuItem);
|
|
589
|
+
activeItem = items.find((item) => item.active || item === activeElement);
|
|
590
|
+
activeItemIndex = activeItem ? items.indexOf(activeItem) : -1;
|
|
591
|
+
} else {
|
|
592
|
+
items = this.getItems();
|
|
593
|
+
activeItem = items.find((item) => item.active || item === activeElement);
|
|
594
|
+
activeItemIndex = activeItem ? items.indexOf(activeItem) : -1;
|
|
595
|
+
}
|
|
596
|
+
let itemToSelect;
|
|
597
|
+
if (event.key === "ArrowUp") {
|
|
598
|
+
event.preventDefault();
|
|
599
|
+
event.stopPropagation();
|
|
600
|
+
if (activeItemIndex > 0) itemToSelect = items[activeItemIndex - 1];
|
|
601
|
+
else itemToSelect = items[items.length - 1];
|
|
602
|
+
}
|
|
603
|
+
if (event.key === "ArrowDown") {
|
|
604
|
+
event.preventDefault();
|
|
605
|
+
event.stopPropagation();
|
|
606
|
+
if (activeItemIndex !== -1 && activeItemIndex < items.length - 1) itemToSelect = items[activeItemIndex + 1];
|
|
607
|
+
else itemToSelect = items[0];
|
|
608
|
+
}
|
|
609
|
+
if (event.key === (isRtl ? "ArrowLeft" : "ArrowRight") && isFocusedOnItem && activeItem) {
|
|
610
|
+
if (activeItem.slotsWithContent && activeItem.slotsWithContent.has("submenu")) {
|
|
611
|
+
event.preventDefault();
|
|
612
|
+
event.stopPropagation();
|
|
613
|
+
activeItem.submenuOpen = true;
|
|
614
|
+
this.addToSubmenuStack(activeItem);
|
|
615
|
+
setTimeout(() => {
|
|
616
|
+
const submenuItems = this.getSubmenuItems(activeItem);
|
|
617
|
+
if (submenuItems.length > 0) {
|
|
618
|
+
submenuItems.forEach((item, index) => item.active = index === 0);
|
|
619
|
+
submenuItems[0].focus();
|
|
620
|
+
}
|
|
621
|
+
}, 0);
|
|
622
|
+
return;
|
|
623
|
+
}
|
|
624
|
+
}
|
|
625
|
+
if (event.key === (isRtl ? "ArrowRight" : "ArrowLeft") && isInSubmenu) {
|
|
626
|
+
event.preventDefault();
|
|
627
|
+
event.stopPropagation();
|
|
628
|
+
const removedItem = this.removeFromSubmenuStack();
|
|
629
|
+
if (removedItem) {
|
|
630
|
+
removedItem.submenuOpen = false;
|
|
631
|
+
setTimeout(() => {
|
|
632
|
+
removedItem.focus();
|
|
633
|
+
removedItem.active = true;
|
|
634
|
+
(removedItem.slot === "submenu" ? this.getSubmenuItems(removedItem.parentElement) : this.getItems()).forEach((item) => {
|
|
635
|
+
if (item !== removedItem) item.active = false;
|
|
636
|
+
});
|
|
637
|
+
}, 0);
|
|
638
|
+
}
|
|
639
|
+
return;
|
|
640
|
+
}
|
|
641
|
+
if (event.key === "Home" || event.key === "End") {
|
|
642
|
+
event.preventDefault();
|
|
643
|
+
event.stopPropagation();
|
|
644
|
+
itemToSelect = event.key === "Home" ? items[0] : items[items.length - 1];
|
|
645
|
+
}
|
|
646
|
+
if (event.key === "Tab") this.hideMenu();
|
|
647
|
+
if (event.key.length === 1 && !(event.metaKey || event.ctrlKey || event.altKey) && !(event.key === " " && this.userTypedQuery === "")) {
|
|
648
|
+
clearTimeout(this.userTypedTimeout);
|
|
649
|
+
this.userTypedTimeout = setTimeout(() => {
|
|
650
|
+
this.userTypedQuery = "";
|
|
651
|
+
}, 1e3);
|
|
652
|
+
this.userTypedQuery += event.key;
|
|
653
|
+
items.some((item) => {
|
|
654
|
+
const label = (item.textContent || "").trim().toLowerCase();
|
|
655
|
+
const selectionQuery = this.userTypedQuery.trim().toLowerCase();
|
|
656
|
+
if (label.startsWith(selectionQuery)) {
|
|
657
|
+
itemToSelect = item;
|
|
658
|
+
return true;
|
|
659
|
+
}
|
|
660
|
+
return false;
|
|
661
|
+
});
|
|
662
|
+
}
|
|
663
|
+
if (itemToSelect) {
|
|
664
|
+
event.preventDefault();
|
|
665
|
+
event.stopPropagation();
|
|
666
|
+
items.forEach((item) => item.active = item === itemToSelect);
|
|
667
|
+
itemToSelect.focus();
|
|
668
|
+
return;
|
|
669
|
+
}
|
|
670
|
+
if ((event.key === "Enter" || event.key === " " && this.userTypedQuery === "") && isFocusedOnItem && activeItem) {
|
|
671
|
+
event.preventDefault();
|
|
672
|
+
event.stopPropagation();
|
|
673
|
+
if (activeItem.slotsWithContent && activeItem.slotsWithContent.has("submenu")) {
|
|
674
|
+
activeItem.submenuOpen = true;
|
|
675
|
+
this.addToSubmenuStack(activeItem);
|
|
676
|
+
setTimeout(() => {
|
|
677
|
+
const submenuItems = this.getSubmenuItems(activeItem);
|
|
678
|
+
if (submenuItems.length > 0) {
|
|
679
|
+
submenuItems.forEach((item, index) => item.active = index === 0);
|
|
680
|
+
submenuItems[0].focus();
|
|
681
|
+
}
|
|
682
|
+
}, 0);
|
|
683
|
+
} else this.makeSelection(activeItem, event);
|
|
684
|
+
}
|
|
685
|
+
};
|
|
686
|
+
this.handleDocumentPointerDown = (event) => {
|
|
687
|
+
if (!event.composedPath().some((el) => {
|
|
688
|
+
if (el instanceof HTMLElement) return el === this || el.closest("sigvelo-dropdown, [part=\"submenu\"]");
|
|
689
|
+
return false;
|
|
690
|
+
})) this.open = false;
|
|
691
|
+
};
|
|
692
|
+
this.handleContextMenu = (event) => {
|
|
693
|
+
const originalEvent = event instanceof LongPressEvent ? event.detail.originalEvent : event;
|
|
694
|
+
const clientX = originalEvent instanceof MouseEvent || originalEvent instanceof PointerEvent ? originalEvent.clientX : originalEvent.touches[0].clientX;
|
|
695
|
+
const clientY = originalEvent instanceof MouseEvent || originalEvent instanceof PointerEvent ? originalEvent.clientY : originalEvent.touches[0].clientY;
|
|
696
|
+
event.preventDefault();
|
|
697
|
+
if (this.menu.hidden) {
|
|
698
|
+
this.contextMenuVirtualElement = this.getContextMenuVirtualElement(clientX, clientY);
|
|
699
|
+
this.open = true;
|
|
700
|
+
}
|
|
701
|
+
};
|
|
702
|
+
this.handleGlobalMouseMove = (event) => {
|
|
703
|
+
const currentSubmenuItem = this.getCurrentSubmenuItem();
|
|
704
|
+
if (!currentSubmenuItem?.submenuOpen || !currentSubmenuItem.submenuElement) return;
|
|
705
|
+
const submenuRect = currentSubmenuItem.submenuElement.getBoundingClientRect();
|
|
706
|
+
const isLeftPlacement = (currentSubmenuItem.submenuElement.getAttribute("data-placement") || "").startsWith("left");
|
|
707
|
+
const constrainedY = Math.max(submenuRect.top, Math.min(event.clientY, submenuRect.bottom));
|
|
708
|
+
let submenuEdgeX;
|
|
709
|
+
let constrainedX;
|
|
710
|
+
if (isLeftPlacement) {
|
|
711
|
+
submenuEdgeX = submenuRect.right;
|
|
712
|
+
constrainedX = Math.max(event.clientX, submenuEdgeX);
|
|
713
|
+
} else {
|
|
714
|
+
submenuEdgeX = submenuRect.left;
|
|
715
|
+
constrainedX = Math.min(event.clientX, submenuEdgeX);
|
|
716
|
+
}
|
|
717
|
+
currentSubmenuItem.submenuElement.style.setProperty("--safe-triangle-cursor-x", `${constrainedX}px`);
|
|
718
|
+
currentSubmenuItem.submenuElement.style.setProperty("--safe-triangle-cursor-y", `${constrainedY}px`);
|
|
719
|
+
const isOverItem = currentSubmenuItem.matches(":hover");
|
|
720
|
+
const isOverSubmenu = currentSubmenuItem.submenuElement?.matches(":hover") || !!event.composedPath().find((el) => el instanceof HTMLElement && el.closest("[part=\"submenu\"]") === currentSubmenuItem.submenuElement);
|
|
721
|
+
if (!isOverItem && !isOverSubmenu) setTimeout(() => {
|
|
722
|
+
if (!currentSubmenuItem.matches(":hover") && !currentSubmenuItem.submenuElement?.matches(":hover")) currentSubmenuItem.submenuOpen = false;
|
|
723
|
+
}, 100);
|
|
724
|
+
};
|
|
725
|
+
}
|
|
726
|
+
static {
|
|
727
|
+
this.styles = [hostStyles, dropdown_styles_default];
|
|
728
|
+
}
|
|
729
|
+
disconnectedCallback() {
|
|
730
|
+
super.disconnectedCallback();
|
|
731
|
+
clearInterval(this.userTypedTimeout);
|
|
732
|
+
this.closeAllSubmenus();
|
|
733
|
+
this.submenuCleanups.forEach((cleanup) => cleanup());
|
|
734
|
+
this.submenuCleanups.clear();
|
|
735
|
+
document.removeEventListener("mousemove", this.handleGlobalMouseMove);
|
|
736
|
+
}
|
|
737
|
+
firstUpdated() {
|
|
738
|
+
this.syncAriaAttributes();
|
|
739
|
+
}
|
|
740
|
+
updated(changedProperties) {
|
|
741
|
+
if (changedProperties.has("open")) {
|
|
742
|
+
this.customStates.set("open", this.open);
|
|
743
|
+
if (this.open) this.showMenu();
|
|
744
|
+
else {
|
|
745
|
+
this.closeAllSubmenus();
|
|
746
|
+
this.hideMenu();
|
|
747
|
+
}
|
|
748
|
+
}
|
|
749
|
+
if (changedProperties.has("contextMenu")) {
|
|
750
|
+
const root = this.getRootNode();
|
|
751
|
+
if (this.contextMenuElement) {
|
|
752
|
+
this.contextMenuLongPress?.stop();
|
|
753
|
+
this.contextMenuElement.removeEventListener("contextmenu", this.handleContextMenu);
|
|
754
|
+
this.contextMenuElement.removeEventListener("sigvelo-long-press", this.handleContextMenu);
|
|
755
|
+
}
|
|
756
|
+
this.contextMenuElement = this.contextMenu ? root.getElementById(this.contextMenu) : null;
|
|
757
|
+
if (this.contextMenuElement) {
|
|
758
|
+
this.contextMenuLongPress = new LongPress(this.contextMenuElement, {
|
|
759
|
+
eventName: "sigvelo-long-press",
|
|
760
|
+
ignorePointerEvents: true
|
|
761
|
+
});
|
|
762
|
+
this.contextMenuLongPress.start();
|
|
763
|
+
this.contextMenuElement.addEventListener("contextmenu", this.handleContextMenu);
|
|
764
|
+
this.contextMenuElement.addEventListener("sigvelo-long-press", this.handleContextMenu);
|
|
765
|
+
} else if (this.contextMenu) console.warn(`A dropdown was assigned as a context menu to an element with an ID of "${this.contextMenu}" but the element could not be found.`, this);
|
|
766
|
+
}
|
|
767
|
+
}
|
|
768
|
+
/** Gets all <sigvelo-dropdown-item> elements slotted in the menu that aren't disabled. */
|
|
769
|
+
getItems(includeDisabled = false) {
|
|
770
|
+
const items = this.defaultSlot.assignedElements({ flatten: true }).filter((el) => el.localName === "sigvelo-dropdown-item");
|
|
771
|
+
return includeDisabled ? items : items.filter((item) => !item.disabled);
|
|
772
|
+
}
|
|
773
|
+
/** Gets all dropdown items in a specific submenu. */
|
|
774
|
+
getSubmenuItems(parentItem, includeDisabled = false) {
|
|
775
|
+
const submenuSlot = parentItem.shadowRoot?.querySelector("slot[name=\"submenu\"]") || parentItem.querySelector("slot[name=\"submenu\"]");
|
|
776
|
+
if (!submenuSlot) return [];
|
|
777
|
+
const items = submenuSlot.assignedElements({ flatten: true }).filter((el) => el.localName === "sigvelo-dropdown-item");
|
|
778
|
+
return includeDisabled ? items : items.filter((item) => !item.disabled);
|
|
779
|
+
}
|
|
780
|
+
/** Handles the submenu navigation stack */
|
|
781
|
+
addToSubmenuStack(item) {
|
|
782
|
+
const index = this.openSubmenuStack.indexOf(item);
|
|
783
|
+
if (index !== -1) this.openSubmenuStack = this.openSubmenuStack.slice(0, index + 1);
|
|
784
|
+
else this.openSubmenuStack.push(item);
|
|
785
|
+
}
|
|
786
|
+
/** Removes the last item from the submenu stack */
|
|
787
|
+
removeFromSubmenuStack() {
|
|
788
|
+
return this.openSubmenuStack.pop();
|
|
789
|
+
}
|
|
790
|
+
/** Gets the current active submenu item */
|
|
791
|
+
getCurrentSubmenuItem() {
|
|
792
|
+
return this.openSubmenuStack.length > 0 ? this.openSubmenuStack[this.openSubmenuStack.length - 1] : void 0;
|
|
793
|
+
}
|
|
794
|
+
/** Closes all submenus in the dropdown. */
|
|
795
|
+
closeAllSubmenus() {
|
|
796
|
+
this.getItems(true).forEach((item) => {
|
|
797
|
+
item.submenuOpen = false;
|
|
798
|
+
});
|
|
799
|
+
this.openSubmenuStack = [];
|
|
800
|
+
}
|
|
801
|
+
/** Closes sibling submenus at the same level as the specified item. */
|
|
802
|
+
closeSiblingSubmenus(item) {
|
|
803
|
+
const parentDropdownItem = item.closest("sigvelo-dropdown-item:not([slot=\"submenu\"])");
|
|
804
|
+
let siblingItems;
|
|
805
|
+
if (parentDropdownItem) siblingItems = this.getSubmenuItems(parentDropdownItem, true);
|
|
806
|
+
else siblingItems = this.getItems(true);
|
|
807
|
+
siblingItems.forEach((siblingItem) => {
|
|
808
|
+
if (siblingItem !== item && siblingItem.submenuOpen) siblingItem.submenuOpen = false;
|
|
809
|
+
});
|
|
810
|
+
if (!this.openSubmenuStack.includes(item)) this.openSubmenuStack.push(item);
|
|
811
|
+
}
|
|
812
|
+
/** Get the slotted trigger button, a <sigvelo-button> or <button> element */
|
|
813
|
+
getTrigger() {
|
|
814
|
+
return this.querySelector("[slot=\"trigger\"]");
|
|
815
|
+
}
|
|
816
|
+
/** Shows the dropdown menu. This should only be called from within updated(). */
|
|
817
|
+
async showMenu() {
|
|
818
|
+
const anchor = this.contextMenu ? this.contextMenuVirtualElement : this.getTrigger();
|
|
819
|
+
if (!anchor) return;
|
|
820
|
+
const openEvent = new SigveloBeforeOpenEvent();
|
|
821
|
+
this.dispatchEvent(openEvent);
|
|
822
|
+
if (openEvent.defaultPrevented) {
|
|
823
|
+
this.open = false;
|
|
824
|
+
return;
|
|
825
|
+
}
|
|
826
|
+
openDropdowns.forEach((dropdown) => dropdown.open = false);
|
|
827
|
+
this.menu.showPopover();
|
|
828
|
+
this.open = true;
|
|
829
|
+
if (this.contextMenu) lockScrolling(this);
|
|
830
|
+
openDropdowns.add(this);
|
|
831
|
+
this.syncAriaAttributes();
|
|
832
|
+
document.addEventListener("keydown", this.handleDocumentKeyDown);
|
|
833
|
+
document.addEventListener("pointerdown", this.handleDocumentPointerDown);
|
|
834
|
+
document.addEventListener("focusin", this.handleDocumentFocusIn);
|
|
835
|
+
document.addEventListener("mousemove", this.handleGlobalMouseMove);
|
|
836
|
+
this.menu.hidden = false;
|
|
837
|
+
this.cleanup = autoUpdate(anchor, this.menu, () => this.reposition());
|
|
838
|
+
await animateWithClass(this.menu, "show");
|
|
839
|
+
const items = this.getItems();
|
|
840
|
+
if (items.length > 0) {
|
|
841
|
+
items.forEach((item, index) => item.active = index === 0);
|
|
842
|
+
items[0].focus();
|
|
843
|
+
}
|
|
844
|
+
this.dispatchEvent(new SigveloOpenEvent());
|
|
845
|
+
}
|
|
846
|
+
/** Hides the dropdown menu. This should only be called from within updated(). */
|
|
847
|
+
async hideMenu() {
|
|
848
|
+
const closeEvent = new SigveloBeforeCloseEvent({ source: this });
|
|
849
|
+
this.dispatchEvent(closeEvent);
|
|
850
|
+
if (closeEvent.defaultPrevented) {
|
|
851
|
+
this.open = true;
|
|
852
|
+
return;
|
|
853
|
+
}
|
|
854
|
+
this.open = false;
|
|
855
|
+
unlockScrolling(this);
|
|
856
|
+
openDropdowns.delete(this);
|
|
857
|
+
this.syncAriaAttributes();
|
|
858
|
+
document.removeEventListener("keydown", this.handleDocumentKeyDown);
|
|
859
|
+
document.removeEventListener("pointerdown", this.handleDocumentPointerDown);
|
|
860
|
+
document.removeEventListener("focusin", this.handleDocumentFocusIn);
|
|
861
|
+
document.removeEventListener("mousemove", this.handleGlobalMouseMove);
|
|
862
|
+
if (!this.menu.hidden) {
|
|
863
|
+
await animateWithClass(this.menu, "hide");
|
|
864
|
+
this.menu.hidden = true;
|
|
865
|
+
this.menu.hidePopover();
|
|
866
|
+
this.dispatchEvent(new SigveloCloseEvent());
|
|
867
|
+
}
|
|
868
|
+
if (this.cleanup) {
|
|
869
|
+
this.cleanup();
|
|
870
|
+
this.cleanup = void 0;
|
|
871
|
+
this.removeAttribute("data-placement");
|
|
872
|
+
}
|
|
873
|
+
}
|
|
874
|
+
/** Repositions the dropdown menu */
|
|
875
|
+
reposition() {
|
|
876
|
+
const anchor = this.contextMenu ? this.contextMenuVirtualElement : this.getTrigger();
|
|
877
|
+
if (!anchor) return;
|
|
878
|
+
computePosition(anchor, this.menu, {
|
|
879
|
+
placement: this.placement,
|
|
880
|
+
middleware: [
|
|
881
|
+
offset({
|
|
882
|
+
mainAxis: this.distance,
|
|
883
|
+
crossAxis: this.offset
|
|
884
|
+
}),
|
|
885
|
+
flip(),
|
|
886
|
+
shift(),
|
|
887
|
+
size({
|
|
888
|
+
apply: ({ availableWidth, availableHeight }) => {
|
|
889
|
+
Object.assign(this.menu.style, {
|
|
890
|
+
maxWidth: `${Math.max(0, availableWidth)}px`,
|
|
891
|
+
maxHeight: `${Math.max(0, availableHeight)}px`
|
|
892
|
+
});
|
|
893
|
+
},
|
|
894
|
+
padding: 10
|
|
895
|
+
})
|
|
896
|
+
]
|
|
897
|
+
}).then(({ x, y, placement }) => {
|
|
898
|
+
this.setAttribute("data-placement", placement);
|
|
899
|
+
Object.assign(this.menu.style, {
|
|
900
|
+
left: `${x}px`,
|
|
901
|
+
top: `${y}px`
|
|
902
|
+
});
|
|
903
|
+
});
|
|
904
|
+
}
|
|
905
|
+
/** Handles clicks on the menu. */
|
|
906
|
+
handleMenuClick(event) {
|
|
907
|
+
const item = event.target.closest("sigvelo-dropdown-item");
|
|
908
|
+
if (!item || item.disabled) return;
|
|
909
|
+
if (item.slotsWithContent && item.slotsWithContent.has("submenu")) {
|
|
910
|
+
if (!item.submenuOpen) {
|
|
911
|
+
this.closeSiblingSubmenus(item);
|
|
912
|
+
this.addToSubmenuStack(item);
|
|
913
|
+
item.submenuOpen = true;
|
|
914
|
+
}
|
|
915
|
+
event.stopPropagation();
|
|
916
|
+
return;
|
|
917
|
+
}
|
|
918
|
+
this.makeSelection(item, event);
|
|
919
|
+
}
|
|
920
|
+
/** Prepares dropdown items when they get added or removed */
|
|
921
|
+
async handleMenuSlotChange() {
|
|
922
|
+
const items = this.getItems(true);
|
|
923
|
+
await Promise.all(items.map((item) => item.updateComplete));
|
|
924
|
+
const hasCheckbox = items.some((item) => item.type === "checkbox");
|
|
925
|
+
const hasSubmenu = items.some((item) => item.hasSubmenu);
|
|
926
|
+
items.forEach((item, index) => {
|
|
927
|
+
item.active = index === 0;
|
|
928
|
+
item.checkboxAdjacent = hasCheckbox;
|
|
929
|
+
item.submenuAdjacent = hasSubmenu;
|
|
930
|
+
});
|
|
931
|
+
}
|
|
932
|
+
/** Toggles the dropdown menu */
|
|
933
|
+
handleTriggerClick() {
|
|
934
|
+
this.open = !this.open;
|
|
935
|
+
}
|
|
936
|
+
/** Given an x and y coordinate, a virtual element for Floating UI is returned. */
|
|
937
|
+
getContextMenuVirtualElement(clientX, clientY) {
|
|
938
|
+
return { getBoundingClientRect: () => {
|
|
939
|
+
return {
|
|
940
|
+
x: clientX,
|
|
941
|
+
y: clientY,
|
|
942
|
+
top: clientY,
|
|
943
|
+
left: clientX,
|
|
944
|
+
bottom: clientY,
|
|
945
|
+
right: clientX,
|
|
946
|
+
width: 0,
|
|
947
|
+
height: 0
|
|
948
|
+
};
|
|
949
|
+
} };
|
|
950
|
+
}
|
|
951
|
+
/** Handles submenu opening events */
|
|
952
|
+
handleSubmenuOpening(event) {
|
|
953
|
+
const openingItem = event.detail.item;
|
|
954
|
+
this.closeSiblingSubmenus(openingItem);
|
|
955
|
+
this.addToSubmenuStack(openingItem);
|
|
956
|
+
this.setupSubmenuPosition(openingItem);
|
|
957
|
+
this.processSubmenuItems(openingItem);
|
|
958
|
+
}
|
|
959
|
+
/** Sets up submenu positioning with autoUpdate */
|
|
960
|
+
setupSubmenuPosition(item) {
|
|
961
|
+
if (!item.submenuElement) return;
|
|
962
|
+
this.cleanupSubmenuPosition(item);
|
|
963
|
+
const cleanup = autoUpdate(item, item.submenuElement, () => {
|
|
964
|
+
this.positionSubmenu(item);
|
|
965
|
+
this.updateSafeTriangleCoordinates(item);
|
|
966
|
+
});
|
|
967
|
+
this.submenuCleanups.set(item, cleanup);
|
|
968
|
+
const submenuSlot = item.submenuElement.querySelector("slot[name=\"submenu\"]");
|
|
969
|
+
if (submenuSlot) {
|
|
970
|
+
submenuSlot.removeEventListener("slotchange", SigveloDropdown.handleSubmenuSlotChange);
|
|
971
|
+
submenuSlot.addEventListener("slotchange", SigveloDropdown.handleSubmenuSlotChange);
|
|
972
|
+
SigveloDropdown.handleSubmenuSlotChange({ target: submenuSlot });
|
|
973
|
+
}
|
|
974
|
+
}
|
|
975
|
+
static handleSubmenuSlotChange(event) {
|
|
976
|
+
const slot = event.target;
|
|
977
|
+
if (!slot) return;
|
|
978
|
+
const items = slot.assignedElements().filter((el) => el.localName === "sigvelo-dropdown-item");
|
|
979
|
+
if (items.length === 0) return;
|
|
980
|
+
const hasSubmenuItems = items.some((item) => item.slotsWithContent && item.slotsWithContent.has("submenu"));
|
|
981
|
+
const hasCheckboxItems = items.some((item) => item.type === "checkbox");
|
|
982
|
+
items.forEach((item) => {
|
|
983
|
+
item.submenuAdjacent = hasSubmenuItems;
|
|
984
|
+
item.checkboxAdjacent = hasCheckboxItems;
|
|
985
|
+
});
|
|
986
|
+
}
|
|
987
|
+
processSubmenuItems(item) {
|
|
988
|
+
if (!item.submenuElement) return;
|
|
989
|
+
const submenuItems = this.getSubmenuItems(item, true);
|
|
990
|
+
const hasSubmenuItems = submenuItems.some((subItem) => subItem.slotsWithContent && subItem.slotsWithContent.has("submenu"));
|
|
991
|
+
submenuItems.forEach((subItem) => {
|
|
992
|
+
subItem.submenuAdjacent = hasSubmenuItems;
|
|
993
|
+
});
|
|
994
|
+
}
|
|
995
|
+
/** Cleans up submenu positioning */
|
|
996
|
+
cleanupSubmenuPosition(item) {
|
|
997
|
+
const cleanup = this.submenuCleanups.get(item);
|
|
998
|
+
if (cleanup) {
|
|
999
|
+
cleanup();
|
|
1000
|
+
this.submenuCleanups.delete(item);
|
|
1001
|
+
}
|
|
1002
|
+
}
|
|
1003
|
+
/** Positions a submenu relative to its parent item */
|
|
1004
|
+
positionSubmenu(item) {
|
|
1005
|
+
if (!item.submenuElement) return;
|
|
1006
|
+
const placement = this.localize.dir() === "rtl" ? "left-start" : "right-start";
|
|
1007
|
+
computePosition(item, item.submenuElement, {
|
|
1008
|
+
placement,
|
|
1009
|
+
middleware: [
|
|
1010
|
+
offset({
|
|
1011
|
+
mainAxis: 0,
|
|
1012
|
+
crossAxis: -5
|
|
1013
|
+
}),
|
|
1014
|
+
flip({ fallbackStrategy: "bestFit" }),
|
|
1015
|
+
shift({ padding: 8 })
|
|
1016
|
+
]
|
|
1017
|
+
}).then(({ x, y, placement: resolvedPlacement }) => {
|
|
1018
|
+
item.submenuElement.setAttribute("data-placement", resolvedPlacement);
|
|
1019
|
+
Object.assign(item.submenuElement.style, {
|
|
1020
|
+
left: `${x}px`,
|
|
1021
|
+
top: `${y}px`
|
|
1022
|
+
});
|
|
1023
|
+
});
|
|
1024
|
+
}
|
|
1025
|
+
/** Updates the safe triangle coordinates for a submenu */
|
|
1026
|
+
updateSafeTriangleCoordinates(item) {
|
|
1027
|
+
if (!item.submenuElement || !item.submenuOpen) return;
|
|
1028
|
+
if (document.activeElement?.matches(":focus-visible")) {
|
|
1029
|
+
item.submenuElement.style.setProperty("--safe-triangle-visible", "none");
|
|
1030
|
+
return;
|
|
1031
|
+
}
|
|
1032
|
+
item.submenuElement.style.setProperty("--safe-triangle-visible", "block");
|
|
1033
|
+
const submenuRect = item.submenuElement.getBoundingClientRect();
|
|
1034
|
+
const placement = item.submenuElement.getAttribute("data-placement") || "";
|
|
1035
|
+
const isRtl = this.localize.dir() === "rtl";
|
|
1036
|
+
const isLeftPlacement = placement.startsWith("left");
|
|
1037
|
+
const isRightPlacement = placement.startsWith("right");
|
|
1038
|
+
let submenuEdgeX;
|
|
1039
|
+
if (isLeftPlacement) submenuEdgeX = submenuRect.right;
|
|
1040
|
+
else if (isRightPlacement) submenuEdgeX = submenuRect.left;
|
|
1041
|
+
else submenuEdgeX = isRtl ? submenuRect.right : submenuRect.left;
|
|
1042
|
+
item.submenuElement.style.setProperty("--safe-triangle-submenu-start-x", `${submenuEdgeX}px`);
|
|
1043
|
+
item.submenuElement.style.setProperty("--safe-triangle-submenu-start-y", `${submenuRect.top}px`);
|
|
1044
|
+
item.submenuElement.style.setProperty("--safe-triangle-submenu-end-x", `${submenuEdgeX}px`);
|
|
1045
|
+
item.submenuElement.style.setProperty("--safe-triangle-submenu-end-y", `${submenuRect.bottom}px`);
|
|
1046
|
+
}
|
|
1047
|
+
/** Makes a selection, emits the sigvelo-select event, and closes the dropdown. */
|
|
1048
|
+
makeSelection(item, originalEvent) {
|
|
1049
|
+
const trigger = this.getTrigger();
|
|
1050
|
+
if (item.disabled) return;
|
|
1051
|
+
if (item.type === "checkbox") item.checked = !item.checked;
|
|
1052
|
+
const selectEvent = new SigveloSelectEvent({ item });
|
|
1053
|
+
this.dispatchEvent(selectEvent);
|
|
1054
|
+
if (!selectEvent.defaultPrevented) {
|
|
1055
|
+
this.open = false;
|
|
1056
|
+
trigger?.focus();
|
|
1057
|
+
}
|
|
1058
|
+
if (item.hiddenLink) {
|
|
1059
|
+
const clickEvent = new MouseEvent("click", {
|
|
1060
|
+
bubbles: true,
|
|
1061
|
+
cancelable: true,
|
|
1062
|
+
view: window,
|
|
1063
|
+
detail: originalEvent.detail,
|
|
1064
|
+
ctrlKey: originalEvent.ctrlKey,
|
|
1065
|
+
shiftKey: originalEvent.shiftKey,
|
|
1066
|
+
altKey: originalEvent.altKey,
|
|
1067
|
+
metaKey: originalEvent.metaKey
|
|
1068
|
+
});
|
|
1069
|
+
item.hiddenLink.dispatchEvent(clickEvent);
|
|
1070
|
+
}
|
|
1071
|
+
}
|
|
1072
|
+
/** Syncs aria attributes on the slotted trigger element and the menu based on the dropdown's current state */
|
|
1073
|
+
async syncAriaAttributes() {
|
|
1074
|
+
const trigger = this.getTrigger();
|
|
1075
|
+
let nativeButton;
|
|
1076
|
+
if (!trigger) return;
|
|
1077
|
+
if (trigger.localName === "sigvelo-button") {
|
|
1078
|
+
await customElements.whenDefined("sigvelo-button");
|
|
1079
|
+
await trigger.updateComplete;
|
|
1080
|
+
nativeButton = trigger.shadowRoot.querySelector("[part=\"button\"]");
|
|
1081
|
+
} else nativeButton = trigger;
|
|
1082
|
+
if (!nativeButton.hasAttribute("id")) nativeButton.setAttribute("id", createId("sigvelo-dropdown-trigger-"));
|
|
1083
|
+
nativeButton.setAttribute("aria-haspopup", "menu");
|
|
1084
|
+
nativeButton.setAttribute("aria-expanded", this.open ? "true" : "false");
|
|
1085
|
+
this.menu.setAttribute("aria-expanded", "false");
|
|
1086
|
+
}
|
|
1087
|
+
render() {
|
|
1088
|
+
return html`
|
|
1089
|
+
<slot
|
|
1090
|
+
name="trigger"
|
|
1091
|
+
@click=${this.handleTriggerClick}
|
|
1092
|
+
@slotchange=${this.syncAriaAttributes}
|
|
1093
|
+
></slot>
|
|
1094
|
+
|
|
1095
|
+
<div
|
|
1096
|
+
id="menu"
|
|
1097
|
+
part="menu"
|
|
1098
|
+
popover="manual"
|
|
1099
|
+
role="menu"
|
|
1100
|
+
tabindex="-1"
|
|
1101
|
+
aria-orientation="vertical"
|
|
1102
|
+
hidden
|
|
1103
|
+
@click=${this.handleMenuClick}
|
|
1104
|
+
@submenu-opening=${this.handleSubmenuOpening}
|
|
1105
|
+
>
|
|
1106
|
+
<slot @slotchange=${this.handleMenuSlotChange}></slot>
|
|
1107
|
+
</div>
|
|
1108
|
+
`;
|
|
1109
|
+
}
|
|
1110
|
+
};
|
|
1111
|
+
__decorate([query("slot:not([name])")], SigveloDropdown.prototype, "defaultSlot", void 0);
|
|
1112
|
+
__decorate([query("#menu")], SigveloDropdown.prototype, "menu", void 0);
|
|
1113
|
+
__decorate([property({
|
|
1114
|
+
type: Boolean,
|
|
1115
|
+
reflect: true
|
|
1116
|
+
})], SigveloDropdown.prototype, "open", void 0);
|
|
1117
|
+
__decorate([property({ attribute: "context-menu" })], SigveloDropdown.prototype, "contextMenu", void 0);
|
|
1118
|
+
__decorate([property({ reflect: true })], SigveloDropdown.prototype, "placement", void 0);
|
|
1119
|
+
__decorate([property({ type: Number })], SigveloDropdown.prototype, "distance", void 0);
|
|
1120
|
+
__decorate([property({ type: Number })], SigveloDropdown.prototype, "offset", void 0);
|
|
1121
|
+
customElements.define("sigvelo-dropdown", SigveloDropdown);
|
|
1122
|
+
//#endregion
|
|
1123
|
+
export { SigveloDropdown as t };
|