@pine-ds/core 4.2.0 → 4.4.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/components/closest.js +1 -1
- package/components/floating-ui.dom.js +1 -1
- package/components/i18n-format.js +1 -1
- package/components/index.d.ts +2 -0
- package/components/index.js +1 -1
- package/components/index2.js +1 -1
- package/components/mock-pds-modal.js +1 -1
- package/components/pds-button2.js +1 -1
- package/components/pds-checkbox2.js +1 -1
- package/components/pds-chip2.js +1 -1
- package/components/pds-combobox.js +2 -2
- package/components/pds-container.js +1 -1
- package/components/pds-copytext.js +1 -1
- package/components/pds-datepicker.d.ts +11 -0
- package/components/pds-datepicker.js +1 -0
- package/components/pds-divider.js +1 -1
- package/components/pds-drawer-content.js +1 -1
- package/components/pds-drawer-footer.js +1 -1
- package/components/pds-drawer-header.js +1 -1
- package/components/pds-drawer.js +1 -1
- package/components/pds-dropdown-menu-item.js +1 -1
- package/components/pds-dropdown-menu-separator.js +1 -1
- package/components/pds-dropdown-menu.js +1 -1
- package/components/pds-filter.js +1 -1
- package/components/pds-filters.js +1 -1
- package/components/pds-icon2.js +1 -1
- package/components/pds-image.js +1 -1
- package/components/pds-input.js +1 -1
- package/components/pds-input2.js +1 -0
- package/components/pds-link2.js +1 -1
- package/components/pds-loader2.js +1 -1
- package/components/pds-modal-content.js +1 -1
- package/components/pds-modal-footer.js +1 -1
- package/components/pds-modal-header.js +1 -1
- package/components/pds-modal2.js +1 -1
- package/components/pds-multiselect.js +1 -1
- package/components/pds-popover.js +1 -1
- package/components/pds-progress.js +1 -1
- package/components/pds-property.js +1 -1
- package/components/pds-radio-group.js +1 -1
- package/components/pds-radio.js +1 -1
- package/components/pds-row.js +1 -1
- package/components/pds-select.js +1 -1
- package/components/pds-sortable-item.js +1 -1
- package/components/pds-sortable.js +2 -2
- package/components/pds-switch.js +1 -1
- package/components/pds-table-body.js +1 -1
- package/components/pds-table-cell2.js +1 -1
- package/components/pds-table-head-cell2.js +1 -1
- package/components/pds-table-head.js +1 -1
- package/components/pds-table-row.js +1 -1
- package/components/pds-tabpanel.js +1 -1
- package/components/pds-tabs.js +1 -1
- package/components/pds-text2.js +1 -1
- package/components/pds-textarea.js +1 -1
- package/components/pds-toast.js +1 -1
- package/components/pds-tooltip.js +1 -1
- package/components/utils.js +1 -1
- package/dist/cjs/closest-D0qyYtJ3.js +20 -0
- package/dist/cjs/{floating-ui.dom-BZk7Blsu.js → floating-ui.dom-Dc8Anyel.js} +79 -0
- package/dist/cjs/{i18n-format-CrpIhahc.js → i18n-format-BD0PmYzT.js} +1 -0
- package/dist/cjs/{index-CuQil7H0.js → index-Bl5KnQay.js} +4 -1
- package/dist/cjs/{index-Bu3NXpbK.js → index-D-QQKB0y.js} +9 -1
- package/dist/cjs/loader.cjs.js +2 -2
- package/dist/cjs/mock-pds-modal.cjs.entry.js +3 -3
- package/dist/cjs/pds-accordion.cjs.entry.js +2 -2
- package/dist/cjs/pds-alert.cjs.entry.js +1 -1
- package/dist/cjs/pds-avatar.cjs.entry.js +2 -2
- package/dist/cjs/pds-box.cjs.entry.js +2 -2
- package/dist/cjs/pds-button.cjs.entry.js +54 -5
- package/dist/cjs/pds-checkbox.cjs.entry.js +14 -6
- package/dist/cjs/pds-chip.cjs.entry.js +34 -9
- package/dist/cjs/pds-combobox.cjs.entry.js +1225 -117
- package/dist/cjs/pds-container.cjs.entry.js +2 -2
- package/dist/cjs/pds-copytext.cjs.entry.js +5 -5
- package/dist/cjs/pds-datepicker.cjs.entry.js +1962 -0
- package/dist/cjs/pds-divider.cjs.entry.js +2 -2
- package/dist/cjs/pds-drawer-content.cjs.entry.js +2 -2
- package/dist/cjs/pds-drawer-footer.cjs.entry.js +2 -2
- package/dist/cjs/pds-drawer-header.cjs.entry.js +2 -2
- package/dist/cjs/pds-drawer.cjs.entry.js +11 -4
- package/dist/cjs/pds-dropdown-menu-item.cjs.entry.js +2 -2
- package/dist/cjs/pds-dropdown-menu-separator.cjs.entry.js +2 -2
- package/dist/cjs/pds-dropdown-menu.cjs.entry.js +11 -4
- package/dist/cjs/pds-filter.cjs.entry.js +3 -3
- package/dist/cjs/pds-filters.cjs.entry.js +2 -2
- package/dist/cjs/pds-icon.cjs.entry.js +2 -2
- package/dist/cjs/pds-image.cjs.entry.js +3 -3
- package/dist/cjs/pds-input.cjs.entry.js +8 -5
- package/dist/cjs/pds-link.cjs.entry.js +5 -5
- package/dist/cjs/pds-loader.cjs.entry.js +2 -2
- package/dist/cjs/pds-modal-content.cjs.entry.js +3 -3
- package/dist/cjs/pds-modal-footer.cjs.entry.js +2 -2
- package/dist/cjs/pds-modal-header.cjs.entry.js +2 -2
- package/dist/cjs/pds-modal.cjs.entry.js +42 -8
- package/dist/cjs/pds-multiselect.cjs.entry.js +264 -51
- package/dist/cjs/pds-popover.cjs.entry.js +30 -12
- package/dist/cjs/pds-progress.cjs.entry.js +4 -2
- package/dist/cjs/pds-property.cjs.entry.js +2 -2
- package/dist/cjs/pds-radio-group.cjs.entry.js +5 -5
- package/dist/cjs/pds-radio.cjs.entry.js +6 -6
- package/dist/cjs/pds-row.cjs.entry.js +2 -2
- package/dist/cjs/pds-select.cjs.entry.js +3 -3
- package/dist/cjs/pds-sortable-item.cjs.entry.js +3 -3
- package/dist/cjs/pds-sortable.cjs.entry.js +2 -2
- package/dist/cjs/pds-switch.cjs.entry.js +14 -6
- package/dist/cjs/pds-tab.cjs.entry.js +1 -1
- package/dist/cjs/pds-table-body.cjs.entry.js +2 -2
- package/dist/cjs/pds-table-cell.cjs.entry.js +5 -5
- package/dist/cjs/pds-table-head-cell.cjs.entry.js +4 -4
- package/dist/cjs/pds-table-head.cjs.entry.js +3 -3
- package/dist/cjs/pds-table-row.cjs.entry.js +3 -3
- package/dist/cjs/pds-table.cjs.entry.js +1 -1
- package/dist/cjs/pds-tabpanel.cjs.entry.js +2 -2
- package/dist/cjs/pds-tabs.cjs.entry.js +2 -2
- package/dist/cjs/pds-text.cjs.entry.js +5 -5
- package/dist/cjs/pds-textarea.cjs.entry.js +14 -9
- package/dist/cjs/pds-toast.cjs.entry.js +4 -4
- package/dist/cjs/pds-tooltip.cjs.entry.js +4 -4
- package/dist/cjs/pine-core.cjs.js +2 -2
- package/dist/cjs/{truncation-tooltip-Bps7_rUy.js → truncation-tooltip-CYgQfBLt.js} +1 -1
- package/dist/cjs/{utils-7jx8T2mW.js → utils-BhRmyxT8.js} +51 -6
- package/dist/collection/collection-manifest.json +1 -0
- package/dist/collection/components/pds-button/pds-button.css +1 -2
- package/dist/collection/components/pds-button/pds-button.js +53 -2
- package/dist/collection/components/pds-checkbox/pds-checkbox.css +13 -4
- package/dist/collection/components/pds-checkbox/pds-checkbox.js +19 -3
- package/dist/collection/components/pds-chip/pds-chip.css +60 -6
- package/dist/collection/components/pds-chip/pds-chip.js +69 -4
- package/dist/collection/components/pds-chip/pds-chip.tokens.css +16 -0
- package/dist/collection/components/pds-chip/stories/pds-chip.stories.js +39 -1
- package/dist/collection/components/pds-combobox/grouped-options-panel.js +262 -0
- package/dist/collection/components/pds-combobox/pds-combobox.css +243 -15
- package/dist/collection/components/pds-combobox/pds-combobox.js +1129 -115
- package/dist/collection/components/pds-combobox/stories/pds-combobox.stories.js +240 -0
- package/dist/collection/components/pds-container/pds-container.js +1 -1
- package/dist/collection/components/pds-copytext/pds-copytext.js +1 -1
- package/dist/collection/components/pds-datepicker/calendar-portal.js +136 -0
- package/dist/collection/components/pds-datepicker/date-utils.js +132 -0
- package/dist/collection/components/pds-datepicker/datepicker-interface.js +1 -0
- package/dist/collection/components/pds-datepicker/pds-datepicker.css +545 -0
- package/dist/collection/components/pds-datepicker/pds-datepicker.js +2406 -0
- package/dist/collection/components/pds-datepicker/presets.js +96 -0
- package/dist/collection/components/pds-datepicker/stories/pds-datepicker.stories.js +195 -0
- package/dist/collection/components/pds-datepicker/value.js +238 -0
- package/dist/collection/components/pds-divider/pds-divider.js +1 -1
- package/dist/collection/components/pds-drawer/pds-drawer-content/pds-drawer-content.js +1 -1
- package/dist/collection/components/pds-drawer/pds-drawer-footer/pds-drawer-footer.js +1 -1
- package/dist/collection/components/pds-drawer/pds-drawer-header/pds-drawer-header.js +1 -1
- package/dist/collection/components/pds-drawer/pds-drawer.css +4 -0
- package/dist/collection/components/pds-drawer/pds-drawer.js +9 -2
- package/dist/collection/components/pds-dropdown-menu/pds-dropdown-menu-item/pds-dropdown-menu-item.js +1 -1
- package/dist/collection/components/pds-dropdown-menu/pds-dropdown-menu-separator/pds-dropdown-menu-separator.js +1 -1
- package/dist/collection/components/pds-dropdown-menu/pds-dropdown-menu.js +9 -2
- package/dist/collection/components/pds-filters/pds-filter/pds-filter.js +1 -1
- package/dist/collection/components/pds-filters/pds-filters.js +1 -1
- package/dist/collection/components/pds-image/pds-image.js +2 -2
- package/dist/collection/components/pds-input/pds-input.js +6 -3
- package/dist/collection/components/pds-link/pds-link.js +2 -2
- package/dist/collection/components/pds-loader/pds-loader.js +1 -1
- package/dist/collection/components/pds-modal/pds-modal-content/pds-modal-content.js +2 -2
- package/dist/collection/components/pds-modal/pds-modal-footer/pds-modal-footer.js +1 -1
- package/dist/collection/components/pds-modal/pds-modal-header/pds-modal-header.js +1 -1
- package/dist/collection/components/pds-modal/pds-modal.css +20 -0
- package/dist/collection/components/pds-modal/pds-modal.js +55 -10
- package/dist/collection/components/pds-modal/stories/pds-modal.stories.js +14 -0
- package/dist/collection/components/pds-modal/test/mock-pds-modal.js +1 -1
- package/dist/collection/components/pds-multiselect/pds-multiselect.css +19 -1
- package/dist/collection/components/pds-multiselect/pds-multiselect.js +390 -47
- package/dist/collection/components/pds-multiselect/stories/pds-multiselect.stories.js +136 -1
- package/dist/collection/components/pds-popover/pds-popover.js +29 -11
- package/dist/collection/components/pds-progress/pds-progress.js +3 -1
- package/dist/collection/components/pds-property/pds-property.js +1 -1
- package/dist/collection/components/pds-radio/pds-radio.css +1 -2
- package/dist/collection/components/pds-radio/pds-radio.js +3 -3
- package/dist/collection/components/pds-radio-group/pds-radio-group.js +3 -3
- package/dist/collection/components/pds-row/pds-row.js +1 -1
- package/dist/collection/components/pds-select/pds-select.js +1 -1
- package/dist/collection/components/pds-sortable/pds-sortable-item/pds-sortable-item.js +1 -1
- package/dist/collection/components/pds-sortable/pds-sortable.js +1 -1
- package/dist/collection/components/pds-switch/pds-switch.css +3 -0
- package/dist/collection/components/pds-switch/pds-switch.js +20 -4
- package/dist/collection/components/pds-table/pds-table-body/pds-table-body.js +1 -1
- package/dist/collection/components/pds-table/pds-table-cell/pds-table-cell.js +2 -2
- package/dist/collection/components/pds-table/pds-table-head/pds-table-head.js +1 -1
- package/dist/collection/components/pds-table/pds-table-head-cell/pds-table-head-cell.js +2 -2
- package/dist/collection/components/pds-table/pds-table-row/pds-table-row.js +1 -1
- package/dist/collection/components/pds-tabs/pds-tabpanel/pds-tabpanel.js +1 -1
- package/dist/collection/components/pds-tabs/pds-tabs.js +1 -1
- package/dist/collection/components/pds-text/pds-text.js +1 -1
- package/dist/collection/components/pds-textarea/pds-textarea.js +11 -6
- package/dist/collection/components/pds-toast/pds-toast.js +3 -3
- package/dist/collection/components/pds-tooltip/pds-tooltip.js +2 -2
- package/dist/collection/utils/closest.js +8 -0
- package/dist/collection/utils/utils.js +49 -6
- package/dist/docs.json +2055 -84
- package/dist/esm/closest-DHPzKMVS.js +17 -0
- package/dist/esm/{floating-ui.dom-DDtwbwIl.js → floating-ui.dom-BPqJgIq6.js} +79 -1
- package/dist/esm/{i18n-format-BKsJZTyn.js → i18n-format-BJgZHCWe.js} +1 -1
- package/dist/esm/{index-CTLu1TM4.js → index-CB8Yh0Nt.js} +4 -1
- package/dist/esm/{index-DdPaBxPo.js → index-DxI-61GK.js} +6 -2
- package/dist/esm/loader.js +3 -3
- package/dist/esm/mock-pds-modal.entry.js +3 -3
- package/dist/esm/pds-accordion.entry.js +2 -2
- package/dist/esm/pds-alert.entry.js +1 -1
- package/dist/esm/pds-avatar.entry.js +2 -2
- package/dist/esm/pds-box.entry.js +2 -2
- package/dist/esm/pds-button.entry.js +54 -5
- package/dist/esm/pds-checkbox.entry.js +14 -6
- package/dist/esm/pds-chip.entry.js +34 -9
- package/dist/esm/pds-combobox.entry.js +1225 -117
- package/dist/esm/pds-container.entry.js +2 -2
- package/dist/esm/pds-copytext.entry.js +5 -5
- package/dist/esm/pds-datepicker.entry.js +1960 -0
- package/dist/esm/pds-divider.entry.js +2 -2
- package/dist/esm/pds-drawer-content.entry.js +2 -2
- package/dist/esm/pds-drawer-footer.entry.js +2 -2
- package/dist/esm/pds-drawer-header.entry.js +2 -2
- package/dist/esm/pds-drawer.entry.js +11 -4
- package/dist/esm/pds-dropdown-menu-item.entry.js +2 -2
- package/dist/esm/pds-dropdown-menu-separator.entry.js +2 -2
- package/dist/esm/pds-dropdown-menu.entry.js +11 -4
- package/dist/esm/pds-filter.entry.js +3 -3
- package/dist/esm/pds-filters.entry.js +2 -2
- package/dist/esm/pds-icon.entry.js +2 -2
- package/dist/esm/pds-image.entry.js +3 -3
- package/dist/esm/pds-input.entry.js +8 -5
- package/dist/esm/pds-link.entry.js +5 -5
- package/dist/esm/pds-loader.entry.js +2 -2
- package/dist/esm/pds-modal-content.entry.js +3 -3
- package/dist/esm/pds-modal-footer.entry.js +2 -2
- package/dist/esm/pds-modal-header.entry.js +2 -2
- package/dist/esm/pds-modal.entry.js +42 -8
- package/dist/esm/pds-multiselect.entry.js +264 -51
- package/dist/esm/pds-popover.entry.js +30 -12
- package/dist/esm/pds-progress.entry.js +4 -2
- package/dist/esm/pds-property.entry.js +2 -2
- package/dist/esm/pds-radio-group.entry.js +5 -5
- package/dist/esm/pds-radio.entry.js +6 -6
- package/dist/esm/pds-row.entry.js +2 -2
- package/dist/esm/pds-select.entry.js +3 -3
- package/dist/esm/pds-sortable-item.entry.js +3 -3
- package/dist/esm/pds-sortable.entry.js +2 -2
- package/dist/esm/pds-switch.entry.js +14 -6
- package/dist/esm/pds-tab.entry.js +1 -1
- package/dist/esm/pds-table-body.entry.js +2 -2
- package/dist/esm/pds-table-cell.entry.js +5 -5
- package/dist/esm/pds-table-head-cell.entry.js +4 -4
- package/dist/esm/pds-table-head.entry.js +3 -3
- package/dist/esm/pds-table-row.entry.js +3 -3
- package/dist/esm/pds-table.entry.js +1 -1
- package/dist/esm/pds-tabpanel.entry.js +2 -2
- package/dist/esm/pds-tabs.entry.js +2 -2
- package/dist/esm/pds-text.entry.js +5 -5
- package/dist/esm/pds-textarea.entry.js +14 -9
- package/dist/esm/pds-toast.entry.js +4 -4
- package/dist/esm/pds-tooltip.entry.js +4 -4
- package/dist/esm/pine-core.js +3 -3
- package/dist/esm/{truncation-tooltip-CdtEBn_5.js → truncation-tooltip-_902ENWC.js} +1 -1
- package/dist/esm/{utils-tJa4KYNO.js → utils-OYK5-nwe.js} +50 -7
- package/dist/esm-es5/closest-DHPzKMVS.js +1 -0
- package/dist/esm-es5/floating-ui.dom-BPqJgIq6.js +1 -0
- package/dist/esm-es5/{i18n-format-BKsJZTyn.js → i18n-format-BJgZHCWe.js} +1 -1
- package/dist/esm-es5/index-CB8Yh0Nt.js +2 -0
- package/dist/esm-es5/index-DxI-61GK.js +1 -0
- package/dist/esm-es5/loader.js +1 -1
- package/dist/esm-es5/mock-pds-modal.entry.js +1 -1
- package/dist/esm-es5/pds-accordion.entry.js +1 -1
- package/dist/esm-es5/pds-alert.entry.js +1 -1
- package/dist/esm-es5/pds-avatar.entry.js +1 -1
- package/dist/esm-es5/pds-box.entry.js +1 -1
- package/dist/esm-es5/pds-button.entry.js +1 -1
- package/dist/esm-es5/pds-checkbox.entry.js +1 -1
- package/dist/esm-es5/pds-chip.entry.js +1 -1
- package/dist/esm-es5/pds-combobox.entry.js +2 -2
- package/dist/esm-es5/pds-container.entry.js +1 -1
- package/dist/esm-es5/pds-copytext.entry.js +1 -1
- package/dist/esm-es5/pds-datepicker.entry.js +1 -0
- package/dist/esm-es5/pds-divider.entry.js +1 -1
- package/dist/esm-es5/pds-drawer-content.entry.js +1 -1
- package/dist/esm-es5/pds-drawer-footer.entry.js +1 -1
- package/dist/esm-es5/pds-drawer-header.entry.js +1 -1
- package/dist/esm-es5/pds-drawer.entry.js +1 -1
- package/dist/esm-es5/pds-dropdown-menu-item.entry.js +1 -1
- package/dist/esm-es5/pds-dropdown-menu-separator.entry.js +1 -1
- package/dist/esm-es5/pds-dropdown-menu.entry.js +1 -1
- package/dist/esm-es5/pds-filter.entry.js +1 -1
- package/dist/esm-es5/pds-filters.entry.js +1 -1
- package/dist/esm-es5/pds-icon.entry.js +1 -1
- package/dist/esm-es5/pds-image.entry.js +1 -1
- package/dist/esm-es5/pds-input.entry.js +1 -1
- package/dist/esm-es5/pds-link.entry.js +1 -1
- package/dist/esm-es5/pds-loader.entry.js +1 -1
- package/dist/esm-es5/pds-modal-content.entry.js +1 -1
- package/dist/esm-es5/pds-modal-footer.entry.js +1 -1
- package/dist/esm-es5/pds-modal-header.entry.js +1 -1
- package/dist/esm-es5/pds-modal.entry.js +1 -1
- package/dist/esm-es5/pds-multiselect.entry.js +1 -1
- package/dist/esm-es5/pds-popover.entry.js +1 -1
- package/dist/esm-es5/pds-progress.entry.js +1 -1
- package/dist/esm-es5/pds-property.entry.js +1 -1
- package/dist/esm-es5/pds-radio-group.entry.js +1 -1
- package/dist/esm-es5/pds-radio.entry.js +1 -1
- package/dist/esm-es5/pds-row.entry.js +1 -1
- package/dist/esm-es5/pds-select.entry.js +1 -1
- package/dist/esm-es5/pds-sortable-item.entry.js +1 -1
- package/dist/esm-es5/pds-sortable.entry.js +2 -2
- package/dist/esm-es5/pds-switch.entry.js +1 -1
- package/dist/esm-es5/pds-tab.entry.js +1 -1
- package/dist/esm-es5/pds-table-body.entry.js +1 -1
- package/dist/esm-es5/pds-table-cell.entry.js +1 -1
- package/dist/esm-es5/pds-table-head-cell.entry.js +1 -1
- package/dist/esm-es5/pds-table-head.entry.js +1 -1
- package/dist/esm-es5/pds-table-row.entry.js +1 -1
- package/dist/esm-es5/pds-table.entry.js +1 -1
- package/dist/esm-es5/pds-tabpanel.entry.js +1 -1
- package/dist/esm-es5/pds-tabs.entry.js +1 -1
- package/dist/esm-es5/pds-text.entry.js +1 -1
- package/dist/esm-es5/pds-textarea.entry.js +1 -1
- package/dist/esm-es5/pds-toast.entry.js +1 -1
- package/dist/esm-es5/pds-tooltip.entry.js +1 -1
- package/dist/esm-es5/pine-core.js +1 -1
- package/dist/esm-es5/{truncation-tooltip-CdtEBn_5.js → truncation-tooltip-_902ENWC.js} +1 -1
- package/dist/esm-es5/utils-OYK5-nwe.js +1 -0
- package/dist/pine-core/p-0414092a.system.entry.js +1 -0
- package/dist/pine-core/p-04807201.entry.js +1 -0
- package/dist/pine-core/{p-56b34569.system.entry.js → p-07f0d168.system.entry.js} +1 -1
- package/dist/pine-core/p-08f5d19c.entry.js +1 -0
- package/dist/pine-core/{p-15d3a4bc.system.entry.js → p-0aaf8faa.system.entry.js} +1 -1
- package/dist/pine-core/p-0bad5955.entry.js +1 -0
- package/dist/pine-core/{p-4d388957.system.entry.js → p-0c3bf377.system.entry.js} +1 -1
- package/dist/pine-core/p-0ce79cd0.entry.js +1 -0
- package/dist/pine-core/{p-3464b456.system.entry.js → p-1057b8c3.system.entry.js} +1 -1
- package/dist/pine-core/{p-bf3afa16.system.entry.js → p-108c910a.system.entry.js} +1 -1
- package/dist/pine-core/{p-53a4852e.system.entry.js → p-166f61a6.system.entry.js} +1 -1
- package/dist/pine-core/{p-31e1722e.entry.js → p-16c8f5e3.entry.js} +1 -1
- package/dist/pine-core/p-16e258d1.entry.js +1 -0
- package/dist/pine-core/{p-591fbff5.entry.js → p-1be33c95.entry.js} +1 -1
- package/dist/pine-core/p-1e3a31da.entry.js +1 -0
- package/dist/pine-core/p-1f228db9.entry.js +1 -0
- package/dist/pine-core/p-257c6ef9.entry.js +1 -0
- package/dist/pine-core/p-26415245.system.entry.js +1 -0
- package/dist/pine-core/p-26e1e5bb.entry.js +1 -0
- package/dist/pine-core/p-27c06bf8.entry.js +2 -0
- package/dist/pine-core/p-31aee437.entry.js +1 -0
- package/dist/pine-core/p-330a76f6.system.entry.js +1 -0
- package/dist/pine-core/{p-3c4236a8.system.entry.js → p-33c63be6.system.entry.js} +1 -1
- package/dist/pine-core/{p-d46adf7d.entry.js → p-344609f9.entry.js} +2 -2
- package/dist/pine-core/{p-049681fc.entry.js → p-3a1711c1.entry.js} +1 -1
- package/dist/pine-core/p-3a9c58bd.system.entry.js +1 -0
- package/dist/pine-core/{p-e3a7d2db.entry.js → p-3ebd543f.entry.js} +1 -1
- package/dist/pine-core/p-3fbcb0c8.system.entry.js +1 -0
- package/dist/pine-core/{p-b923a70b.entry.js → p-427b4aeb.entry.js} +1 -1
- package/dist/pine-core/{p-5772f260.system.entry.js → p-42bd87ea.system.entry.js} +1 -1
- package/dist/pine-core/{p-1e2a9b5d.system.entry.js → p-43c691bf.system.entry.js} +1 -1
- package/dist/pine-core/p-4566d659.system.entry.js +1 -0
- package/dist/pine-core/p-4b8cf04a.system.entry.js +1 -0
- package/dist/pine-core/p-4d6f471c.entry.js +1 -0
- package/dist/pine-core/{p-3e0c6384.entry.js → p-4e7580c4.entry.js} +1 -1
- package/dist/pine-core/{p-0ab735aa.system.entry.js → p-4f4a2d2a.system.entry.js} +1 -1
- package/dist/pine-core/{p-7e2b934d.entry.js → p-5211aba7.entry.js} +1 -1
- package/dist/pine-core/{p-376f8286.entry.js → p-524b7d3f.entry.js} +1 -1
- package/dist/pine-core/{p-3f12afb1.entry.js → p-5613c64c.entry.js} +1 -1
- package/dist/pine-core/p-5bb24cb4.entry.js +1 -0
- package/dist/pine-core/{p-d7865297.entry.js → p-5bb80b3c.entry.js} +1 -1
- package/dist/pine-core/{p-e3cd4627.system.entry.js → p-5c6e0a26.system.entry.js} +1 -1
- package/dist/pine-core/{p-51dff5af.system.entry.js → p-5db57551.system.entry.js} +1 -1
- package/dist/pine-core/{p-f94667b5.entry.js → p-5eb00ba5.entry.js} +1 -1
- package/dist/pine-core/p-61756414.system.entry.js +1 -0
- package/dist/pine-core/{p-e5bbe8cc.entry.js → p-682e9e8f.entry.js} +1 -1
- package/dist/pine-core/p-6965db1d.entry.js +1 -0
- package/dist/pine-core/{p-5aea1082.entry.js → p-6b180ee2.entry.js} +1 -1
- package/dist/pine-core/{p-d21739eb.entry.js → p-6c53962f.entry.js} +1 -1
- package/dist/pine-core/p-6da6520b.system.entry.js +3 -0
- package/dist/pine-core/p-6e3bf862.system.entry.js +1 -0
- package/dist/pine-core/{p-053b0898.system.entry.js → p-71c9f866.system.entry.js} +1 -1
- package/dist/pine-core/{p-78fd593d.system.entry.js → p-7265b94c.system.entry.js} +1 -1
- package/dist/pine-core/{p-9187c26c.system.entry.js → p-74229b5e.system.entry.js} +1 -1
- package/dist/pine-core/p-7512c2d4.system.entry.js +1 -0
- package/dist/pine-core/p-76db406d.system.entry.js +1 -0
- package/dist/pine-core/{p-e1653d75.system.entry.js → p-79aa5f43.system.entry.js} +1 -1
- package/dist/pine-core/p-7bbcda0f.system.entry.js +1 -0
- package/dist/pine-core/p-7c8946e6.entry.js +1 -0
- package/dist/pine-core/p-7c98c90a.system.entry.js +1 -0
- package/dist/pine-core/p-81292c03.system.entry.js +1 -0
- package/dist/pine-core/p-81300046.system.entry.js +1 -0
- package/dist/pine-core/{p-a11a9c40.system.entry.js → p-8252cd84.system.entry.js} +1 -1
- package/dist/pine-core/{p-d0d2a886.system.entry.js → p-84ba0e6a.system.entry.js} +1 -1
- package/dist/pine-core/{p-c1f8a187.entry.js → p-86fc0bfa.entry.js} +1 -1
- package/dist/pine-core/p-90692bb6.entry.js +1 -0
- package/dist/pine-core/{p-2eb8d697.system.entry.js → p-90ea812c.system.entry.js} +1 -1
- package/dist/pine-core/p-948826db.entry.js +1 -0
- package/dist/pine-core/{p-714bfdbd.entry.js → p-9b66642d.entry.js} +1 -1
- package/dist/pine-core/p-BJgZHCWe.js +1 -0
- package/dist/pine-core/p-BPqJgIq6.js +1 -0
- package/dist/pine-core/p-BSRFZB4I.system.js +1 -0
- package/dist/pine-core/p-BZsj6eAn.system.js +1 -0
- package/dist/pine-core/p-CB8Yh0Nt.js +2 -0
- package/dist/pine-core/{p-B2qvvB3q.system.js → p-CBu9UrXr.system.js} +1 -1
- package/dist/pine-core/p-COtCa1Md.system.js +1 -0
- package/dist/pine-core/p-CTQZ2fkv.system.js +1 -0
- package/dist/pine-core/{p-B2nn1gSd.js → p-CnM3cCof.js} +1 -1
- package/dist/pine-core/p-CnO10OxH.system.js +1 -0
- package/dist/pine-core/p-D-akEPIU.system.js +2 -0
- package/dist/pine-core/p-DHPzKMVS.js +1 -0
- package/dist/pine-core/p-Dx8tEj0U.system.js +1 -0
- package/dist/pine-core/p-DxI-61GK.js +1 -0
- package/dist/pine-core/p-OYK5-nwe.js +1 -0
- package/dist/pine-core/p-a10af84b.system.entry.js +1 -0
- package/dist/pine-core/p-a21b530a.system.entry.js +1 -0
- package/dist/pine-core/p-a85535a4.system.entry.js +1 -0
- package/dist/pine-core/p-abc0fe2f.system.entry.js +1 -0
- package/dist/pine-core/p-ac6a5bf0.entry.js +1 -0
- package/dist/pine-core/{p-f7a5062f.entry.js → p-b0526f98.entry.js} +1 -1
- package/dist/pine-core/p-b130b716.entry.js +1 -0
- package/dist/pine-core/{p-09413b07.entry.js → p-b195d345.entry.js} +1 -1
- package/dist/pine-core/{p-e3600c53.entry.js → p-b4923acf.entry.js} +1 -1
- package/dist/pine-core/{p-e410b0d8.system.entry.js → p-b4e440e3.system.entry.js} +1 -1
- package/dist/pine-core/p-b8693a87.entry.js +1 -0
- package/dist/pine-core/{p-e95225cf.entry.js → p-b8ada1eb.entry.js} +1 -1
- package/dist/pine-core/{p-1614c000.system.entry.js → p-bb85bbb5.system.entry.js} +1 -1
- package/dist/pine-core/{p-fec298bb.system.entry.js → p-bbc539bc.system.entry.js} +2 -2
- package/dist/pine-core/{p-f21aea90.system.entry.js → p-bf833976.system.entry.js} +1 -1
- package/dist/pine-core/{p-c5ce6dea.entry.js → p-c23097af.entry.js} +1 -1
- package/dist/pine-core/p-c2dd84bd.system.entry.js +1 -0
- package/dist/pine-core/{p-869ed1c0.system.entry.js → p-c4520b04.system.entry.js} +1 -1
- package/dist/pine-core/{p-3605a5f5.entry.js → p-c4f68dfc.entry.js} +1 -1
- package/dist/pine-core/{p-d9ffb2d9.system.entry.js → p-c6fa6744.system.entry.js} +1 -1
- package/dist/pine-core/p-c7dba815.entry.js +1 -0
- package/dist/pine-core/p-cb6f55ff.entry.js +1 -0
- package/dist/pine-core/p-cfb8fa7c.system.entry.js +1 -0
- package/dist/pine-core/{p-86bc2a0c.entry.js → p-d0d7d1d4.entry.js} +1 -1
- package/dist/pine-core/{p-b109de2e.entry.js → p-d1112c8a.entry.js} +1 -1
- package/dist/pine-core/p-d4e91ad9.system.entry.js +1 -0
- package/dist/pine-core/{p-7b1e3e91.entry.js → p-da018dcb.entry.js} +1 -1
- package/dist/pine-core/{p-c09dab1a.system.entry.js → p-dc27abe6.system.entry.js} +1 -1
- package/dist/pine-core/{p-3eca0b00.entry.js → p-dc343b6d.entry.js} +1 -1
- package/dist/pine-core/p-dde753e7.system.entry.js +1 -0
- package/dist/pine-core/{p-f35596cd.entry.js → p-dea3a582.entry.js} +1 -1
- package/dist/pine-core/p-df29fd41.entry.js +1 -0
- package/dist/pine-core/{p-1f307e59.system.entry.js → p-e4e2eae2.system.entry.js} +1 -1
- package/dist/pine-core/{p-51b8490d.entry.js → p-e8668178.entry.js} +1 -1
- package/dist/pine-core/{p-5dd393cd.system.entry.js → p-eb28d21d.system.entry.js} +1 -1
- package/dist/pine-core/p-eb71a82d.system.entry.js +1 -0
- package/dist/pine-core/{p-8eef80d5.entry.js → p-ed63873c.entry.js} +1 -1
- package/dist/pine-core/{p-12182cab.entry.js → p-f4f6dc36.entry.js} +1 -1
- package/dist/pine-core/{p-be819bff.system.entry.js → p-f67a0ca8.system.entry.js} +1 -1
- package/dist/pine-core/p-fc455968.entry.js +1 -0
- package/dist/pine-core/{p-92ef1608.system.entry.js → p-fe3e2ebd.system.entry.js} +1 -1
- package/dist/pine-core/pine-core.css +1 -1
- package/dist/pine-core/pine-core.esm.js +1 -1
- package/dist/pine-core/pine-core.js +1 -1
- package/dist/types/components/pds-button/pds-button.d.ts +10 -0
- package/dist/types/components/pds-checkbox/pds-checkbox.d.ts +5 -0
- package/dist/types/components/pds-chip/pds-chip.d.ts +12 -0
- package/dist/types/components/pds-combobox/combobox-interface.d.ts +17 -0
- package/dist/types/components/pds-combobox/grouped-options-panel.d.ts +105 -0
- package/dist/types/components/pds-combobox/pds-combobox.d.ts +235 -3
- package/dist/types/components/pds-datepicker/calendar-portal.d.ts +43 -0
- package/dist/types/components/pds-datepicker/date-utils.d.ts +48 -0
- package/dist/types/components/pds-datepicker/datepicker-interface.d.ts +30 -0
- package/dist/types/components/pds-datepicker/pds-datepicker.d.ts +489 -0
- package/dist/types/components/pds-datepicker/presets.d.ts +23 -0
- package/dist/types/components/pds-datepicker/value.d.ts +47 -0
- package/dist/types/components/pds-dropdown-menu/pds-dropdown-menu.d.ts +1 -0
- package/dist/types/components/pds-modal/pds-modal.d.ts +9 -2
- package/dist/types/components/pds-multiselect/multiselect-interface.d.ts +19 -0
- package/dist/types/components/pds-multiselect/pds-multiselect.d.ts +56 -1
- package/dist/types/components/pds-popover/pds-popover.d.ts +1 -0
- package/dist/types/components/pds-switch/pds-switch.d.ts +5 -0
- package/dist/types/components.d.ts +702 -11
- package/dist/types/utils/closest.d.ts +2 -0
- package/dist/types/utils/types.d.ts +2 -1
- package/dist/types/utils/utils.d.ts +25 -2
- package/dist/vscode.html-data.json +497 -7
- package/hydrate/index.js +4059 -377
- package/hydrate/index.mjs +4059 -377
- package/package.json +2 -2
- package/dist/cjs/closest-BZXvuB_Y.js +0 -11
- package/dist/esm/closest-DnUJodVd.js +0 -9
- package/dist/esm-es5/closest-DnUJodVd.js +0 -1
- package/dist/esm-es5/floating-ui.dom-DDtwbwIl.js +0 -1
- package/dist/esm-es5/index-CTLu1TM4.js +0 -2
- package/dist/esm-es5/index-DdPaBxPo.js +0 -1
- package/dist/esm-es5/utils-tJa4KYNO.js +0 -1
- package/dist/pine-core/p--Llh7wKm.system.js +0 -1
- package/dist/pine-core/p-02a47ebb.entry.js +0 -1
- package/dist/pine-core/p-12ec8186.system.entry.js +0 -1
- package/dist/pine-core/p-17dc3f87.entry.js +0 -1
- package/dist/pine-core/p-18a59cdd.system.entry.js +0 -1
- package/dist/pine-core/p-2016c878.entry.js +0 -1
- package/dist/pine-core/p-222ff58e.system.entry.js +0 -1
- package/dist/pine-core/p-324a7ae4.system.entry.js +0 -1
- package/dist/pine-core/p-32f10aa9.entry.js +0 -1
- package/dist/pine-core/p-33c0f3c9.system.entry.js +0 -1
- package/dist/pine-core/p-34e38037.system.entry.js +0 -1
- package/dist/pine-core/p-3873f55b.entry.js +0 -1
- package/dist/pine-core/p-3aec9079.entry.js +0 -1
- package/dist/pine-core/p-3c229a00.system.entry.js +0 -1
- package/dist/pine-core/p-43338f77.system.entry.js +0 -1
- package/dist/pine-core/p-4661259e.system.entry.js +0 -1
- package/dist/pine-core/p-585ad368.system.entry.js +0 -1
- package/dist/pine-core/p-5d585aa8.entry.js +0 -1
- package/dist/pine-core/p-613a64f1.entry.js +0 -1
- package/dist/pine-core/p-630f33d6.system.entry.js +0 -1
- package/dist/pine-core/p-63686e2a.system.entry.js +0 -1
- package/dist/pine-core/p-6f7a7d55.entry.js +0 -1
- package/dist/pine-core/p-6fd863e5.system.entry.js +0 -1
- package/dist/pine-core/p-76286a68.system.entry.js +0 -1
- package/dist/pine-core/p-7691a875.system.entry.js +0 -3
- package/dist/pine-core/p-7e44106e.entry.js +0 -1
- package/dist/pine-core/p-84ade640.entry.js +0 -1
- package/dist/pine-core/p-8be301b6.entry.js +0 -1
- package/dist/pine-core/p-8cc270f0.system.entry.js +0 -1
- package/dist/pine-core/p-8cea0d7a.system.entry.js +0 -1
- package/dist/pine-core/p-957dbb0c.entry.js +0 -1
- package/dist/pine-core/p-BG6uGRQj.system.js +0 -1
- package/dist/pine-core/p-BKsJZTyn.js +0 -1
- package/dist/pine-core/p-BrLs99ML.system.js +0 -1
- package/dist/pine-core/p-CTLu1TM4.js +0 -2
- package/dist/pine-core/p-Cr7-rJtJ.system.js +0 -1
- package/dist/pine-core/p-DAIsVNlL.system.js +0 -2
- package/dist/pine-core/p-DDtwbwIl.js +0 -1
- package/dist/pine-core/p-DdPaBxPo.js +0 -1
- package/dist/pine-core/p-DnUJodVd.js +0 -1
- package/dist/pine-core/p-Dr-FzkdE.system.js +0 -1
- package/dist/pine-core/p-a4a58477.entry.js +0 -1
- package/dist/pine-core/p-a98bf89f.system.entry.js +0 -1
- package/dist/pine-core/p-ac0098fd.entry.js +0 -1
- package/dist/pine-core/p-b32e3174.system.entry.js +0 -1
- package/dist/pine-core/p-be4a6cc2.entry.js +0 -1
- package/dist/pine-core/p-c0b3f2c1.system.entry.js +0 -1
- package/dist/pine-core/p-c8bffb08.system.entry.js +0 -1
- package/dist/pine-core/p-cf24ed1e.system.entry.js +0 -1
- package/dist/pine-core/p-d12ef40d.entry.js +0 -1
- package/dist/pine-core/p-d280741f.entry.js +0 -1
- package/dist/pine-core/p-d415bb01.entry.js +0 -2
- package/dist/pine-core/p-d43db3ba.entry.js +0 -1
- package/dist/pine-core/p-db5703f2.entry.js +0 -1
- package/dist/pine-core/p-dd6d9807.system.entry.js +0 -1
- package/dist/pine-core/p-e0da17aa.system.entry.js +0 -1
- package/dist/pine-core/p-ed297f3e.entry.js +0 -1
- package/dist/pine-core/p-fbf5f315.entry.js +0 -1
- package/dist/pine-core/p-kYMYDfJY.system.js +0 -1
- package/dist/pine-core/p-tJa4KYNO.js +0 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { r as registerInstance, c as createEvent, h, H as Host, a as getElement } from './index-
|
|
1
|
+
import { r as registerInstance, c as createEvent, h, H as Host, a as getElement } from './index-CB8Yh0Nt.js';
|
|
2
2
|
import { i as isSpecTest, m as messageId, a as assignDescription } from './form-BuRbS7Hp.js';
|
|
3
|
-
import {
|
|
4
|
-
import { d as debounceEvent } from './utils-
|
|
3
|
+
import { a as autoUpdate, c as computePosition, o as offset, f as flip, s as shift, b as size, h as hide } from './floating-ui.dom-BPqJgIq6.js';
|
|
4
|
+
import { c as cancelDebouncedEvent, d as debounceEvent, f as flushDebouncedEvent } from './utils-OYK5-nwe.js';
|
|
5
5
|
|
|
6
6
|
/*! @license DOMPurify 3.3.3 | (c) Cure53 and other contributors | Released under the Apache license 2.0 and Mozilla Public License 2.0 | github.com/cure53/DOMPurify/blob/3.3.3/LICENSE */
|
|
7
7
|
|
|
@@ -1389,7 +1389,269 @@ function createDOMPurify() {
|
|
|
1389
1389
|
}
|
|
1390
1390
|
var purify = createDOMPurify();
|
|
1391
1391
|
|
|
1392
|
-
const pdsComboboxCss = () => `:host{display:block}:host([aria-disabled=true]) .pds-combobox__input-icon{color:var(--pine-color-text-disabled);pointer-events:none}.pds-combobox{position:relative}.pds-combobox__label{color:var(--pine-color-text-label);display:block;font:var(--pine-typography-body-medium);letter-spacing:var(--pine-letter-spacing);-webkit-margin-after:var(--pine-dimension-2xs);margin-block-end:var(--pine-dimension-2xs)}.pds-combobox__input-wrapper{-ms-flex-align:center;align-items:center;display:-ms-flexbox;display:flex;position:relative;width:100%}.pds-combobox__input{background:var(--pine-color-background-container);border:var(--pine-border);border-radius:var(--pine-dimension-125);-webkit-box-sizing:border-box;box-sizing:border-box;color:var(--pine-color-text-strong);-ms-flex:1;flex:1;font:var(--pine-typography-body-medium);padding:var(--pine-dimension-xs) var(--pine-dimension-450) var(--pine-dimension-xs) var(--pine-dimension-150);-webkit-transition:border-color var(--pine-motion-duration-base) ease;transition:border-color var(--pine-motion-duration-base) ease;width:100%}.pds-combobox__input:hover:not(:disabled){border-color:var(--pine-color-border-hover)}.pds-combobox__input:disabled{background:var(--pine-color-background-container-disabled);border-color:var(--pine-color-border-disabled);color:var(--pine-color-text-disabled);cursor:not-allowed}.pds-combobox__input:disabled::-webkit-input-placeholder{color:var(--pine-color-text-placeholder-disabled)}.pds-combobox__input:disabled::-moz-placeholder{color:var(--pine-color-text-placeholder-disabled)}.pds-combobox__input:disabled:-ms-input-placeholder{color:var(--pine-color-text-placeholder-disabled)}.pds-combobox__input:disabled::-ms-input-placeholder{color:var(--pine-color-text-placeholder-disabled)}.pds-combobox__input:disabled::placeholder{color:var(--pine-color-text-placeholder-disabled)}.pds-combobox__input:focus-visible{border-color:var(--pine-color-border-active);outline:var(--pine-outline-focus);outline-offset:var(--pine-border-width)}.pds-combobox__input::-webkit-input-placeholder{color:var(--pine-color-text-placeholder)}.pds-combobox__input::-moz-placeholder{color:var(--pine-color-text-placeholder)}.pds-combobox__input:-ms-input-placeholder{color:var(--pine-color-text-placeholder)}.pds-combobox__input::-ms-input-placeholder{color:var(--pine-color-text-placeholder)}.pds-combobox__input::placeholder{color:var(--pine-color-text-placeholder)}.pds-combobox__input.pds-combobox__input--invalid{background:var(--pine-color-red-050);border-color:var(--pine-color-border-danger)}:host-context([data-theme=dark]) .pds-combobox__input.pds-combobox__input--invalid{background:var(--pine-color-red-950)}.pds-combobox__input.pds-combobox__input--invalid:hover:not(:disabled){border-color:var(--pine-color-border-danger)}.pds-combobox__input.pds-combobox__input--invalid:focus-visible{outline-color:var(--pine-color-focus-ring-danger)}.pds-combobox__input-icon{color:var(--pine-color-text-secondary);inset-inline-end:var(--pine-dimension-150);pointer-events:none;position:absolute;z-index:calc(var(--pine-z-index-raised) - 1)}.pds-combobox__helper{color:var(--pine-color-text-message);font:var(--pine-typography-body-sm-medium);-webkit-margin-before:var(--pine-dimension-2xs);margin-block-start:var(--pine-dimension-2xs)}.pds-combobox__error{-ms-flex-align:start;align-items:flex-start;color:var(--pine-color-text-message-danger);display:-ms-flexbox;display:flex;font:var(--pine-typography-body-sm-medium);gap:var(--pine-dimension-2xs);-webkit-margin-before:var(--pine-dimension-2xs);margin-block-start:var(--pine-dimension-2xs)}.pds-combobox__error pds-icon{-ms-flex-negative:0;flex-shrink:0;-webkit-margin-before:var(--pine-dimension-025);margin-block-start:var(--pine-dimension-025)}.pds-combobox__listbox{background:var(--pine-color-background-overlay);border:0;border-radius:var(--pine-dimension-125);-webkit-box-shadow:var(--pine-box-shadow);box-shadow:var(--pine-box-shadow);list-style:none;margin:0;min-width:220px;overflow-y:auto;padding:var(--pine-dimension-xs);position:absolute;z-index:var(--pine-z-index-raised)}.pds-combobox__option{-ms-flex-align:center;align-items:center;background:transparent;border-radius:var(--pine-dimension-125);color:var(--pine-color-text-secondary);cursor:pointer;display:-ms-flexbox;display:flex;font:var(--pine-typography-body-medium);-ms-flex-pack:justify;justify-content:space-between;padding:var(--pine-dimension-xs) var(--pine-dimension-sm);position:relative;-webkit-transition:background 0.15s;transition:background 0.15s}.pds-combobox__option[aria-selected=true]{background:var(--pine-color-background-muted)}.pds-combobox__option:focus-visible{outline:0}.pds-combobox__option.pds-combobox__option--layout .pds-combobox__option-layout-wrapper{-ms-flex-align:center;align-items:center;display:-ms-flexbox;display:flex;width:100%}.pds-combobox__option.pds-combobox__option--chip .pds-combobox__option-chip{-ms-flex-align:center;align-items:center;display:-ms-flexbox;display:flex;width:100%}.pds-combobox__option:last-child{-webkit-margin-after:0;margin-block-end:0}.pds-combobox__option--highlighted,.pds-combobox__option[selected],.pds-combobox__option--selected{background:var(--pine-color-background-muted)}.pds-combobox__option-check{color:currentColor;font-size:var(--pine-dimension-150);-webkit-margin-start:var(--pine-dimension-150);margin-inline-start:var(--pine-dimension-150)}.pds-combobox__group-label{color:var(--pine-color-text-tertiary);cursor:default;font:var(--pine-typography-heading-caption);-webkit-margin-after:var(--pine-dimension-2xs);margin-block-end:var(--pine-dimension-2xs);-webkit-margin-before:var(--pine-dimension-150);margin-block-start:var(--pine-dimension-150);padding:var(--pine-dimension-2xs) var(--pine-dimension-sm);text-transform:uppercase}.pds-combobox__group-label:first-child{-webkit-margin-before:0;margin-block-start:0}.pds-combobox__loading{-ms-flex-align:center;align-items:center;display:-ms-flexbox;display:flex;-ms-flex-pack:center;justify-content:center;padding:var(--pine-dimension-150)}.pds-combobox__empty{color:var(--pine-color-text-tertiary);padding:var(--pine-dimension-150) var(--pine-dimension-sm);text-align:center}.pds-combobox__load-more{-ms-flex-align:center;align-items:center;display:-ms-flexbox;display:flex;-ms-flex-pack:center;justify-content:center;padding:var(--pine-dimension-150)}.pds-combobox__button-trigger{-ms-flex-align:center;align-items:center;background:var(--color-background-default, var(--pine-color-secondary));border:var(--pine-border);border-radius:var(--pine-border-radius-full);color:var(--color-text-default, var(--pine-color-text-inverse-emphasis));cursor:pointer;display:-ms-flexbox;display:flex;font:var(--pine-typography-body-medium);-ms-flex-pack:justify;justify-content:space-between;min-height:var(--pine-dimension-450);outline:none;padding:0 var(--pine-dimension-sm);-webkit-transition:border-color 0.15s, background 0.15s, -webkit-box-shadow 0.15s;transition:border-color 0.15s, background 0.15s, -webkit-box-shadow 0.15s;transition:border-color 0.15s, box-shadow 0.15s, background 0.15s;transition:border-color 0.15s, box-shadow 0.15s, background 0.15s, -webkit-box-shadow 0.15s;width:-webkit-fit-content;width:-moz-fit-content;width:fit-content}.pds-combobox__button-trigger .pds-combobox__button-trigger-layout-wrapper{-ms-flex-align:center;align-items:center;display:-ms-flexbox;display:flex;-ms-flex:1;flex:1}.pds-combobox__button-trigger .trigger-content{-ms-flex-align:center;align-items:center;display:-ms-flexbox;display:flex;width:100%}.pds-combobox__button-trigger:focus-visible{border-color:var(--color-border-focus, var(--pine-color-border));-webkit-box-shadow:0 0 0 2px var(--color-outline, var(--pine-color-focus-ring));box-shadow:0 0 0 2px var(--color-outline, var(--pine-color-focus-ring))}.pds-combobox__button-trigger:hover{background:var(--color-background-hover, var(--pine-color-secondary-hover));border-color:var(--color-border-hover, var(--pine-color-border-hover))}.pds-combobox__button-trigger[aria-disabled=true],.pds-combobox__button-trigger:disabled{background:var(--color-background-disabled, var(--pine-color-secondary-disabled));border-color:var(--color-border-disabled, var(--pine-color-border-disabled));color:var(--color-text-disabled, var(--pine-color-text-secondary-disabled));cursor:not-allowed;opacity:0.6}.pds-combobox__button-trigger-label{color:inherit;-ms-flex:1 1 auto;flex:1 1 auto;text-align:start}.pds-combobox__button-trigger--input-shape{border-radius:var(--pine-dimension-125);min-height:var(--pine-dimension-500)}.pds-combobox__button-trigger-chevron{color:currentColor;-webkit-margin-start:var(--pine-dimension-150);margin-inline-start:var(--pine-dimension-150)}.pds-combobox__button-trigger--primary{--color-background-default:var(--pine-color-primary);--color-background-hover:var(--pine-color-primary-hover);--color-background-disabled:var(--pine-color-primary-disabled);--color-border-default:var(--pine-color-primary);--color-border-hover:var(--pine-color-primary-hover);--color-border-disabled:var(--pine-color-primary-disabled);--color-border-focus:var(--pine-color-primary);--color-text-default:var(--pine-color-text-primary);--color-text-disabled:var(--pine-color-text-primary-disabled);--color-outline:var(--pine-color-focus-ring)}.pds-combobox__button-trigger--accent{--color-background-default:var(--pine-color-accent);--color-background-hover:var(--pine-color-accent-hover);--color-background-disabled:var(--pine-color-accent-disabled);--color-border-default:var(--pine-color-accent);--color-border-hover:var(--pine-color-accent-hover);--color-border-disabled:var(--pine-color-accent-disabled);--color-border-focus:var(--pine-color-accent);--color-text-default:var(--pine-color-white);--color-text-disabled:var(--pine-color-text-accent-disabled);--color-outline:var(--pine-color-focus-ring)}.pds-combobox__button-trigger--secondary{--color-background-default:var(--pine-color-secondary);--color-background-hover:var(--pine-color-secondary-hover);--color-background-disabled:var(--pine-color-secondary-disabled);--color-border-default:var(--pine-color-border);--color-border-hover:var(--pine-color-border-hover);--color-border-disabled:var(--pine-color-border-disabled);--color-border-focus:var(--pine-color-border);--color-text-default:var(--pine-color-text-secondary);--color-text-disabled:var(--pine-color-text-secondary-disabled);--color-outline:var(--pine-color-focus-ring)}.pds-combobox__button-trigger--destructive{--color-background-default:var(--pine-color-danger);--color-background-hover:var(--pine-color-danger-hover);--color-background-disabled:var(--pine-color-danger-disabled);--color-border-default:var(--pine-color-danger);--color-border-hover:var(--pine-color-danger-hover);--color-border-disabled:var(--pine-color-danger-disabled);--color-border-focus:var(--pine-color-danger);--color-text-default:var(--pine-color-white);--color-text-disabled:var(--pine-color-text-danger-disabled);--color-outline:var(--pine-color-focus-ring-danger)}.visually-hidden{border:0;clip:rect(0 0 0 0);-webkit-clip-path:polygon(0 0, 0 0, 0 0);clip-path:polygon(0 0, 0 0, 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;white-space:nowrap;width:1px}[data-layout]{border-radius:var(--pine-dimension-125);padding-block:var(--pine-dimension-xs)}.pds-combobox__chip-trigger{-ms-flex-align:center;align-items:center;border-radius:var(--pine-dimension-sm);cursor:pointer;display:-ms-inline-flexbox;display:inline-flex;font:var(--pine-typography-body-medium);-ms-flex-pack:justify;justify-content:space-between;outline:none;padding-block:var(--pine-dimension-025);padding-inline:var(--pine-dimension-150);-webkit-transition:all 0.15s ease;transition:all 0.15s ease;width:-webkit-fit-content;width:-moz-fit-content;width:fit-content}.pds-combobox__chip-trigger .pds-combobox__chip-trigger-layout-wrapper{-ms-flex-align:center;align-items:center;display:-ms-flexbox;display:flex;-ms-flex:1;flex:1}.pds-combobox__chip-trigger .trigger-content{-ms-flex-align:center;align-items:center;display:-ms-flexbox;display:flex;width:100%}.pds-combobox__chip-trigger:focus-visible{outline:var(--pine-outline-focus);outline-offset:var(--pine-border-width)}.pds-combobox__chip-trigger[aria-disabled=true]{cursor:not-allowed;opacity:0.6}.pds-combobox__chip-trigger-label{color:inherit;-ms-flex:1 1 auto;flex:1 1 auto;text-align:start}.pds-combobox__chip-trigger-chevron{color:currentColor;-webkit-margin-start:var(--pine-dimension-150);margin-inline-start:var(--pine-dimension-150)}.pds-combobox__chip-trigger-icon{-webkit-margin-end:var(--pine-dimension-2xs);margin-inline-end:var(--pine-dimension-2xs)}.pds-combobox__chip-trigger--neutral,.pds-combobox__chip-trigger--accent,.pds-combobox__chip-trigger--success,.pds-combobox__chip-trigger--warning,.pds-combobox__chip-trigger--danger,.pds-combobox__chip-trigger--info{background:var(--chip-bg);border:var(--pine-border-width) solid var(--chip-border);color:var(--chip-text)}.pds-combobox__chip-trigger--neutral:hover:not([aria-disabled=true]),.pds-combobox__chip-trigger--accent:hover:not([aria-disabled=true]),.pds-combobox__chip-trigger--success:hover:not([aria-disabled=true]),.pds-combobox__chip-trigger--warning:hover:not([aria-disabled=true]),.pds-combobox__chip-trigger--danger:hover:not([aria-disabled=true]),.pds-combobox__chip-trigger--info:hover:not([aria-disabled=true]){background:var(--chip-bg-hover)}.pds-combobox__chip-trigger--neutral:focus-visible,.pds-combobox__chip-trigger--accent:focus-visible,.pds-combobox__chip-trigger--success:focus-visible,.pds-combobox__chip-trigger--warning:focus-visible,.pds-combobox__chip-trigger--danger:focus-visible,.pds-combobox__chip-trigger--info:focus-visible{border-color:var(--chip-border)}.pds-combobox__chip-trigger--neutral{--chip-bg:var(--pine-chip-color-neutral);--chip-bg-hover:var(--pine-chip-color-neutral-hover);--chip-border:var(--pine-chip-color-neutral-hover);--chip-text:var(--pine-color-text-neutral)}.pds-combobox__chip-trigger--accent{--chip-bg:var(--pine-chip-color-accent);--chip-bg-hover:var(--pine-chip-color-accent-hover);--chip-border:var(--pine-chip-color-accent-hover);--chip-text:var(--pine-color-text-accent)}.pds-combobox__chip-trigger--success{--chip-bg:var(--pine-chip-color-success);--chip-bg-hover:var(--pine-chip-color-success-hover);--chip-border:var(--pine-chip-color-success-hover);--chip-text:var(--pine-color-text-success)}.pds-combobox__chip-trigger--warning{--chip-bg:var(--pine-chip-color-warning);--chip-bg-hover:var(--pine-chip-color-warning-hover);--chip-border:var(--pine-chip-color-warning-hover);--chip-text:var(--pine-color-text-warning)}.pds-combobox__chip-trigger--danger{--chip-bg:var(--pine-chip-color-danger);--chip-bg-hover:var(--pine-chip-color-danger-hover);--chip-border:var(--pine-chip-color-danger-hover);--chip-text:var(--pine-color-text-danger)}.pds-combobox__chip-trigger--info{--chip-bg:var(--pine-chip-color-info);--chip-bg-hover:var(--pine-chip-color-info-hover);--chip-border:var(--pine-chip-color-info-hover);--chip-text:var(--pine-color-text-info)}.pds-combobox__chip-trigger--brand{background:-webkit-gradient(linear, left top, right top, from(#FF3E14), to(#6B62F2));background:linear-gradient(90deg, #FF3E14 0%, #6B62F2 100%);border:0;color:var(--pine-color-text-neutral);padding:1px;position:relative}.pds-combobox__chip-trigger--brand .pds-combobox__chip-trigger-label{background:rgba(255, 255, 255, 0.9);border-radius:calc(var(--pine-dimension-sm) - 1px);color:var(--pine-color-text-neutral);font-weight:var(--pine-font-weight-medium);padding:var(--pine-dimension-025) var(--pine-dimension-150);position:relative;z-index:1}.pds-combobox__chip-trigger--brand .pds-combobox__chip-trigger-chevron{position:relative;z-index:1}.pds-combobox__chip-trigger--brand:hover:not([aria-disabled=true]) .pds-combobox__chip-trigger-label{background:rgba(255, 255, 255, 0.8)}.pds-combobox__chip-trigger--dropdown:not(.pds-combobox__chip-trigger--brand){padding:var(--pine-dimension-none)}.pds-combobox__chip-trigger--dropdown:not(.pds-combobox__chip-trigger--brand) .pds-combobox__chip-trigger-label{padding:var(--pine-dimension-025) var(--pine-dimension-150)}.pds-combobox__chip-trigger--large .pds-combobox__chip-trigger-label{font-family:var(--pine-font-family-heading);font-size:var(--pine-font-size-heading-6);font-weight:var(--pine-font-weight-medium);letter-spacing:var(--pine-letter-spacing-heading-6)}.pds-combobox__chip-trigger--dot .pds-combobox__chip-trigger-label::before{border:var(--pine-border-width) solid transparent;border-radius:var(--pine-border-radius-full);content:"";display:inline-block;height:var(--pine-dimension-2xs);-webkit-margin-end:var(--pine-dimension-2xs);margin-inline-end:var(--pine-dimension-2xs);width:var(--pine-dimension-2xs)}`;
|
|
1392
|
+
/** The optgroup an option sits in, or null for an ungrouped option. */
|
|
1393
|
+
function parentOptgroupOf(option) {
|
|
1394
|
+
const parent = option === null || option === void 0 ? void 0 : option.parentElement;
|
|
1395
|
+
return parent !== null && parent !== undefined && parent.tagName === 'OPTGROUP' ? parent : null;
|
|
1396
|
+
}
|
|
1397
|
+
/** A Pine icon name: letters, digits and hyphens, such as `hashtag`. Never a URL or file path. */
|
|
1398
|
+
const PINE_ICON_NAME = /^[a-z0-9-]+$/i;
|
|
1399
|
+
/**
|
|
1400
|
+
* An optgroup's `data-icon` when it's a Pine icon name, or null. One definition of a usable group
|
|
1401
|
+
* icon for every mode, checked here rather than trusting `pds-icon` to reject anything else; it is
|
|
1402
|
+
* only ever passed to `pds-icon` as `name`.
|
|
1403
|
+
*/
|
|
1404
|
+
function groupIconOf(optgroup) {
|
|
1405
|
+
const icon = optgroup.getAttribute('data-icon');
|
|
1406
|
+
return icon !== null && PINE_ICON_NAME.test(icon) ? icon : null;
|
|
1407
|
+
}
|
|
1408
|
+
/** An option is disabled by its own `disabled` or its optgroup's, as in a native select. */
|
|
1409
|
+
function isOptionDisabled(option) {
|
|
1410
|
+
var _a;
|
|
1411
|
+
if (option === null || option === undefined)
|
|
1412
|
+
return false;
|
|
1413
|
+
return option.hasAttribute('disabled') || ((_a = parentOptgroupOf(option)) === null || _a === void 0 ? void 0 : _a.hasAttribute('disabled')) === true;
|
|
1414
|
+
}
|
|
1415
|
+
/** A group with no option left to choose. It still opens, so its options can be seen. */
|
|
1416
|
+
function isGroupDisabled(group) {
|
|
1417
|
+
return group.options.every(({ option }) => isOptionDisabled(option));
|
|
1418
|
+
}
|
|
1419
|
+
/**
|
|
1420
|
+
* Groups the combobox's filtered items for the panel: each optgroup becomes one entry holding its
|
|
1421
|
+
* options, and ungrouped options stay where they are. Indexes count options in list order, the
|
|
1422
|
+
* same as the inline listbox, so `data-option-index` means the same thing in every mode.
|
|
1423
|
+
*/
|
|
1424
|
+
function buildPanelEntries(items) {
|
|
1425
|
+
const entries = [];
|
|
1426
|
+
const groups = new Map();
|
|
1427
|
+
let index = 0;
|
|
1428
|
+
items.forEach(item => {
|
|
1429
|
+
if (item.tagName !== 'OPTION')
|
|
1430
|
+
return;
|
|
1431
|
+
const option = item;
|
|
1432
|
+
const optgroup = parentOptgroupOf(option);
|
|
1433
|
+
if (optgroup !== null) {
|
|
1434
|
+
let group = groups.get(optgroup);
|
|
1435
|
+
if (!group) {
|
|
1436
|
+
group = { optgroup, label: optgroup.label, icon: groupIconOf(optgroup), options: [] };
|
|
1437
|
+
groups.set(optgroup, group);
|
|
1438
|
+
entries.push({ kind: 'group', group });
|
|
1439
|
+
}
|
|
1440
|
+
group.options.push({ option, index: index++ });
|
|
1441
|
+
}
|
|
1442
|
+
else {
|
|
1443
|
+
entries.push({ kind: 'option', option, index: index++ });
|
|
1444
|
+
}
|
|
1445
|
+
});
|
|
1446
|
+
return entries;
|
|
1447
|
+
}
|
|
1448
|
+
/** The label of the optgroup an option sits in, or null for an ungrouped option. */
|
|
1449
|
+
function groupLabelOf(option) {
|
|
1450
|
+
var _a, _b;
|
|
1451
|
+
return (_b = (_a = parentOptgroupOf(option)) === null || _a === void 0 ? void 0 : _a.label) !== null && _b !== void 0 ? _b : null;
|
|
1452
|
+
}
|
|
1453
|
+
/**
|
|
1454
|
+
* The items Up and Down move through from `current`, one tree level at a time: the panel's rows
|
|
1455
|
+
* (groups and ungrouped options), or the open group's options. Drilled into a group, its row
|
|
1456
|
+
* (drawn as the row back) comes first, above its options, as a tree draws a parent above its children.
|
|
1457
|
+
* Disabled options and groups stay in it, as the APG listbox and tree patterns advise, so they're
|
|
1458
|
+
* announced as unavailable rather than hidden from the keyboard.
|
|
1459
|
+
*/
|
|
1460
|
+
function panelColumn(entries, openGroup, current, drilledIn) {
|
|
1461
|
+
const open = openGroup === null ? undefined : findGroup(entries, openGroup);
|
|
1462
|
+
if (open !== undefined) {
|
|
1463
|
+
const options = open.options.map(({ index }) => index);
|
|
1464
|
+
if (drilledIn)
|
|
1465
|
+
return [open.optgroup, ...options];
|
|
1466
|
+
if (typeof current === 'number' && options.includes(current))
|
|
1467
|
+
return options;
|
|
1468
|
+
}
|
|
1469
|
+
return entries.map(entry => (entry.kind === 'group' ? entry.group.optgroup : entry.index));
|
|
1470
|
+
}
|
|
1471
|
+
/** The panel's group for an optgroup, if it's showing. */
|
|
1472
|
+
function findGroup(entries, optgroup) {
|
|
1473
|
+
for (const entry of entries) {
|
|
1474
|
+
if (entry.kind === 'group' && entry.group.optgroup === optgroup)
|
|
1475
|
+
return entry.group;
|
|
1476
|
+
}
|
|
1477
|
+
return undefined;
|
|
1478
|
+
}
|
|
1479
|
+
/** Moving from one group row to another waits this long, so a diagonal trip into the flyout doesn't switch groups. */
|
|
1480
|
+
const SWITCH_DELAY_MS = 120;
|
|
1481
|
+
/** Leaving a group (into the gap beside its flyout, say) waits this long before closing it. */
|
|
1482
|
+
const CLOSE_DELAY_MS = 200;
|
|
1483
|
+
/** Space between the panel's edge and the flyout: --pine-dimension-050 (4px), per the Figma frames. */
|
|
1484
|
+
const FLYOUT_GAP_PX = 4;
|
|
1485
|
+
/** How close the flyout may come to the viewport edge: --pine-dimension-100 (8px). */
|
|
1486
|
+
const VIEWPORT_PADDING_PX = 8;
|
|
1487
|
+
/** A flyout never shrinks below roughly three rows, even when little space is left. */
|
|
1488
|
+
const MIN_FLYOUT_HEIGHT_PX = 120;
|
|
1489
|
+
/**
|
|
1490
|
+
* Opens and closes a group's flyout with hover intent, and keeps the open flyout positioned beside
|
|
1491
|
+
* its group row. The flyout renders inside the row, so moving the pointer into it never leaves
|
|
1492
|
+
* the row; the delays cover the gap between panel and flyout and diagonal moves across rows.
|
|
1493
|
+
*/
|
|
1494
|
+
/**
|
|
1495
|
+
* Scrolls `el` into view inside `container` only. A flyout option needs this: the flyout is `fixed`
|
|
1496
|
+
* beside the panel but sits inside it in the DOM, so `scrollIntoView` would also scroll the panel
|
|
1497
|
+
* and the page, moving the flyout's row out from under it.
|
|
1498
|
+
*/
|
|
1499
|
+
function scrollIntoViewWithin(container, el) {
|
|
1500
|
+
const bounds = container.getBoundingClientRect();
|
|
1501
|
+
const rect = el.getBoundingClientRect();
|
|
1502
|
+
if (rect.top < bounds.top) {
|
|
1503
|
+
container.scrollTop -= bounds.top - rect.top;
|
|
1504
|
+
}
|
|
1505
|
+
else if (rect.bottom > bounds.bottom) {
|
|
1506
|
+
container.scrollTop += rect.bottom - bounds.bottom;
|
|
1507
|
+
}
|
|
1508
|
+
}
|
|
1509
|
+
class FlyoutController {
|
|
1510
|
+
constructor(getOpenGroup, setOpenGroup) {
|
|
1511
|
+
this.getOpenGroup = getOpenGroup;
|
|
1512
|
+
this.setOpenGroup = setOpenGroup;
|
|
1513
|
+
}
|
|
1514
|
+
/** Pointer entered a group row (or its flyout, which sits inside it). */
|
|
1515
|
+
enter(label) {
|
|
1516
|
+
this.clearClose();
|
|
1517
|
+
const open = this.getOpenGroup();
|
|
1518
|
+
if (open === label) {
|
|
1519
|
+
this.clearSwitch();
|
|
1520
|
+
return;
|
|
1521
|
+
}
|
|
1522
|
+
if (open === null) {
|
|
1523
|
+
this.setOpenGroup(label);
|
|
1524
|
+
return;
|
|
1525
|
+
}
|
|
1526
|
+
this.clearSwitch();
|
|
1527
|
+
this.switchTimer = setTimeout(() => {
|
|
1528
|
+
this.switchTimer = undefined;
|
|
1529
|
+
this.setOpenGroup(label);
|
|
1530
|
+
}, SWITCH_DELAY_MS);
|
|
1531
|
+
}
|
|
1532
|
+
/** Pointer left a group row and its flyout. */
|
|
1533
|
+
leave(label) {
|
|
1534
|
+
this.clearSwitch();
|
|
1535
|
+
if (this.getOpenGroup() !== label)
|
|
1536
|
+
return;
|
|
1537
|
+
this.clearClose();
|
|
1538
|
+
this.closeTimer = setTimeout(() => {
|
|
1539
|
+
this.closeTimer = undefined;
|
|
1540
|
+
if (this.getOpenGroup() === label)
|
|
1541
|
+
this.setOpenGroup(null);
|
|
1542
|
+
}, CLOSE_DELAY_MS);
|
|
1543
|
+
}
|
|
1544
|
+
/**
|
|
1545
|
+
* A click or tap on a group row opens it. It never closes it: on desktop the hover that preceded
|
|
1546
|
+
* the click has already opened it, and touch browsers fire an emulated mouseenter and then click
|
|
1547
|
+
* in the same tap. Closing happens on leaving the row or closing the panel.
|
|
1548
|
+
*/
|
|
1549
|
+
open(label) {
|
|
1550
|
+
this.clearTimers();
|
|
1551
|
+
this.setOpenGroup(label);
|
|
1552
|
+
}
|
|
1553
|
+
/**
|
|
1554
|
+
* Keeps `flyout` beside `row`: horizontally against the panel's edge, vertically so its first
|
|
1555
|
+
* option lines up with the row. `fixed` positioning so the panel's scrolling can't clip it,
|
|
1556
|
+
* including when the panel is portaled into a dialog.
|
|
1557
|
+
*/
|
|
1558
|
+
position(row, panel, flyout) {
|
|
1559
|
+
if (this.positionedFlyout === flyout && this.stopAutoUpdate)
|
|
1560
|
+
return;
|
|
1561
|
+
this.stopPositioning();
|
|
1562
|
+
this.positionedFlyout = flyout;
|
|
1563
|
+
const reference = {
|
|
1564
|
+
getBoundingClientRect: () => {
|
|
1565
|
+
const panelRect = panel.getBoundingClientRect();
|
|
1566
|
+
const rowRect = row.getBoundingClientRect();
|
|
1567
|
+
return {
|
|
1568
|
+
x: panelRect.x,
|
|
1569
|
+
y: rowRect.y,
|
|
1570
|
+
left: panelRect.left,
|
|
1571
|
+
right: panelRect.right,
|
|
1572
|
+
top: rowRect.top,
|
|
1573
|
+
bottom: rowRect.bottom,
|
|
1574
|
+
width: panelRect.width,
|
|
1575
|
+
height: rowRect.height,
|
|
1576
|
+
};
|
|
1577
|
+
},
|
|
1578
|
+
contextElement: row,
|
|
1579
|
+
};
|
|
1580
|
+
// The flyout's own top padding, so its first option, not its edge, lines up with the row.
|
|
1581
|
+
const flyoutPaddingTop = parseFloat(getComputedStyle(flyout).paddingTop) || 0;
|
|
1582
|
+
const update = () => computePosition(reference, flyout, {
|
|
1583
|
+
placement: 'right-start',
|
|
1584
|
+
strategy: 'fixed',
|
|
1585
|
+
middleware: [
|
|
1586
|
+
offset({ mainAxis: FLYOUT_GAP_PX, crossAxis: -flyoutPaddingTop }),
|
|
1587
|
+
flip({ fallbackPlacements: ['left-start'] }),
|
|
1588
|
+
shift({ padding: VIEWPORT_PADDING_PX }),
|
|
1589
|
+
// A long group scrolls inside the flyout instead of running off the viewport.
|
|
1590
|
+
size({
|
|
1591
|
+
padding: VIEWPORT_PADDING_PX,
|
|
1592
|
+
apply({ availableHeight }) {
|
|
1593
|
+
flyout.style.maxHeight = `${Math.max(availableHeight, MIN_FLYOUT_HEIGHT_PX)}px`;
|
|
1594
|
+
},
|
|
1595
|
+
}),
|
|
1596
|
+
// Hidden with its row when the panel scrolls the row out of view.
|
|
1597
|
+
hide({ strategy: 'referenceHidden' }),
|
|
1598
|
+
],
|
|
1599
|
+
}).then(({ x, y, middlewareData }) => {
|
|
1600
|
+
var _a;
|
|
1601
|
+
// It starts hidden (see the stylesheet) so it never flashes in the row before it's placed.
|
|
1602
|
+
Object.assign(flyout.style, {
|
|
1603
|
+
position: 'fixed',
|
|
1604
|
+
left: `${x}px`,
|
|
1605
|
+
top: `${y}px`,
|
|
1606
|
+
visibility: ((_a = middlewareData.hide) === null || _a === void 0 ? void 0 : _a.referenceHidden) === true ? 'hidden' : 'visible',
|
|
1607
|
+
});
|
|
1608
|
+
const reveal = this.pendingReveal;
|
|
1609
|
+
this.pendingReveal = undefined;
|
|
1610
|
+
if (reveal !== undefined && flyout.contains(reveal))
|
|
1611
|
+
scrollIntoViewWithin(flyout, reveal);
|
|
1612
|
+
});
|
|
1613
|
+
this.stopAutoUpdate = autoUpdate(reference, flyout, () => {
|
|
1614
|
+
void update();
|
|
1615
|
+
});
|
|
1616
|
+
}
|
|
1617
|
+
/**
|
|
1618
|
+
* Scrolls `option` into view inside its flyout. Before the flyout's first placement its height
|
|
1619
|
+
* isn't capped yet, so the option looks visible; it's revealed again once the placement lands.
|
|
1620
|
+
*/
|
|
1621
|
+
reveal(flyout, option) {
|
|
1622
|
+
scrollIntoViewWithin(flyout, option);
|
|
1623
|
+
if (flyout.style.maxHeight === '')
|
|
1624
|
+
this.pendingReveal = option;
|
|
1625
|
+
}
|
|
1626
|
+
stopPositioning() {
|
|
1627
|
+
var _a;
|
|
1628
|
+
(_a = this.stopAutoUpdate) === null || _a === void 0 ? void 0 : _a.call(this);
|
|
1629
|
+
this.stopAutoUpdate = undefined;
|
|
1630
|
+
this.positionedFlyout = undefined;
|
|
1631
|
+
this.pendingReveal = undefined;
|
|
1632
|
+
}
|
|
1633
|
+
/** The panel closed or the component left the page. */
|
|
1634
|
+
reset() {
|
|
1635
|
+
this.clearTimers();
|
|
1636
|
+
this.stopPositioning();
|
|
1637
|
+
}
|
|
1638
|
+
clearTimers() {
|
|
1639
|
+
this.clearSwitch();
|
|
1640
|
+
this.clearClose();
|
|
1641
|
+
}
|
|
1642
|
+
clearSwitch() {
|
|
1643
|
+
if (this.switchTimer !== undefined)
|
|
1644
|
+
clearTimeout(this.switchTimer);
|
|
1645
|
+
this.switchTimer = undefined;
|
|
1646
|
+
}
|
|
1647
|
+
clearClose() {
|
|
1648
|
+
if (this.closeTimer !== undefined)
|
|
1649
|
+
clearTimeout(this.closeTimer);
|
|
1650
|
+
this.closeTimer = undefined;
|
|
1651
|
+
}
|
|
1652
|
+
}
|
|
1653
|
+
|
|
1654
|
+
const pdsComboboxCss = () => `:host{display:block}:host([aria-disabled=true]) .pds-combobox__input-icon{color:var(--pine-color-text-disabled);pointer-events:none}.pds-combobox{position:relative}.pds-combobox__label{color:var(--pine-color-text-label);display:block;font:var(--pine-typography-body-medium);letter-spacing:var(--pine-letter-spacing);-webkit-margin-after:var(--pine-dimension-2xs);margin-block-end:var(--pine-dimension-2xs)}.pds-combobox__input-wrapper{-ms-flex-align:center;align-items:center;display:-ms-flexbox;display:flex;position:relative;width:100%}.pds-combobox__input{background:var(--pine-color-background-container);border:var(--pine-border);border-radius:var(--pine-dimension-125);-webkit-box-sizing:border-box;box-sizing:border-box;color:var(--pine-color-text-strong);-ms-flex:1;flex:1;font:var(--pine-typography-body-medium);padding:var(--pine-dimension-xs) var(--pine-dimension-450) var(--pine-dimension-xs) var(--pine-dimension-150);-webkit-transition:border-color var(--pine-motion-duration-base) ease;transition:border-color var(--pine-motion-duration-base) ease;width:100%}.pds-combobox__input:hover:not(:disabled){border-color:var(--pine-color-border-hover)}.pds-combobox__input:disabled{background:var(--pine-color-background-container-disabled);border-color:var(--pine-color-border-disabled);color:var(--pine-color-text-disabled);cursor:not-allowed}.pds-combobox__input:disabled::-webkit-input-placeholder{color:var(--pine-color-text-placeholder-disabled)}.pds-combobox__input:disabled::-moz-placeholder{color:var(--pine-color-text-placeholder-disabled)}.pds-combobox__input:disabled:-ms-input-placeholder{color:var(--pine-color-text-placeholder-disabled)}.pds-combobox__input:disabled::-ms-input-placeholder{color:var(--pine-color-text-placeholder-disabled)}.pds-combobox__input:disabled::placeholder{color:var(--pine-color-text-placeholder-disabled)}.pds-combobox__input:focus-visible{border-color:var(--pine-color-border-active);outline:var(--pine-outline-focus);outline-offset:var(--pine-border-width)}.pds-combobox__input::-webkit-input-placeholder{color:var(--pine-color-text-placeholder)}.pds-combobox__input::-moz-placeholder{color:var(--pine-color-text-placeholder)}.pds-combobox__input:-ms-input-placeholder{color:var(--pine-color-text-placeholder)}.pds-combobox__input::-ms-input-placeholder{color:var(--pine-color-text-placeholder)}.pds-combobox__input::placeholder{color:var(--pine-color-text-placeholder)}.pds-combobox__input.pds-combobox__input--invalid{background:var(--pine-color-red-050);border-color:var(--pine-color-border-danger)}:host-context([data-theme=dark]) .pds-combobox__input.pds-combobox__input--invalid{background:var(--pine-color-red-950)}.pds-combobox__input.pds-combobox__input--invalid:hover:not(:disabled){border-color:var(--pine-color-border-danger)}.pds-combobox__input.pds-combobox__input--invalid:focus-visible{outline-color:var(--pine-color-focus-ring-danger)}.pds-combobox__input-icon{color:var(--pine-color-text-secondary);inset-inline-end:var(--pine-dimension-150);pointer-events:none;position:absolute;z-index:calc(var(--pine-z-index-raised) - 1)}.pds-combobox__helper{color:var(--pine-color-text-message);font:var(--pine-typography-body-sm-medium);-webkit-margin-before:var(--pine-dimension-2xs);margin-block-start:var(--pine-dimension-2xs)}.pds-combobox__error{-ms-flex-align:start;align-items:flex-start;color:var(--pine-color-text-message-danger);display:-ms-flexbox;display:flex;font:var(--pine-typography-body-sm-medium);gap:var(--pine-dimension-2xs);-webkit-margin-before:var(--pine-dimension-2xs);margin-block-start:var(--pine-dimension-2xs)}.pds-combobox__error pds-icon{-ms-flex-negative:0;flex-shrink:0;-webkit-margin-before:var(--pine-dimension-025);margin-block-start:var(--pine-dimension-025)}.pds-combobox__listbox{background:var(--pine-color-background-overlay);border:0;border-radius:var(--pine-dimension-125);-webkit-box-shadow:var(--pine-box-shadow);box-shadow:var(--pine-box-shadow);list-style:none;margin:0;min-width:220px;overflow-y:auto;padding:var(--pine-dimension-xs);position:absolute;z-index:var(--pine-z-index-raised)}.pds-combobox__option{-ms-flex-align:center;align-items:center;background:transparent;border-radius:var(--pine-dimension-125);color:var(--pine-color-text-secondary);cursor:pointer;display:-ms-flexbox;display:flex;font:var(--pine-typography-body-medium);-ms-flex-pack:justify;justify-content:space-between;padding:var(--pine-dimension-xs) var(--pine-dimension-sm);position:relative;-webkit-transition:background 0.15s;transition:background 0.15s}.pds-combobox__option[aria-selected=true]{background:var(--pine-color-background-muted)}.pds-combobox__option:focus-visible{outline:0}.pds-combobox__option.pds-combobox__option--layout .pds-combobox__option-layout-wrapper{-ms-flex-align:center;align-items:center;display:-ms-flexbox;display:flex;width:100%}.pds-combobox__option.pds-combobox__option--chip .pds-combobox__option-chip{-ms-flex-align:center;align-items:center;display:-ms-flexbox;display:flex;width:100%}.pds-combobox__option:last-child{-webkit-margin-after:0;margin-block-end:0}.pds-combobox__option--highlighted,.pds-combobox__option[selected],.pds-combobox__option--selected{background:var(--pine-color-background-muted)}.pds-combobox__option--disabled,.pds-combobox__group-row--disabled>.pds-combobox__group-row-trigger,.pds-combobox__group-back--disabled>.pds-combobox__group-back-trigger,.pds-combobox__group--disabled>.pds-combobox__group-label{color:var(--pine-color-text-disabled)}.pds-combobox__option--disabled{cursor:not-allowed}.pds-combobox__option--disabled .pds-combobox__option-chip,.pds-combobox__option--disabled .pds-combobox__option-layout-wrapper{opacity:0.5}.pds-combobox__option-check{color:currentColor;font-size:var(--pine-dimension-150);-webkit-margin-start:var(--pine-dimension-150);margin-inline-start:var(--pine-dimension-150)}.pds-combobox__group-label{color:var(--pine-color-text-tertiary);cursor:default;font:var(--pine-typography-heading-caption);-webkit-margin-after:var(--pine-dimension-2xs);margin-block-end:var(--pine-dimension-2xs);-webkit-margin-before:var(--pine-dimension-150);margin-block-start:var(--pine-dimension-150);padding:var(--pine-dimension-2xs) var(--pine-dimension-sm);text-transform:uppercase}.pds-combobox__group-label:first-child{-webkit-margin-before:0;margin-block-start:0}.pds-combobox__group{list-style:none;-webkit-margin-before:var(--pine-dimension-150);margin-block-start:var(--pine-dimension-150)}.pds-combobox__group:first-child{-webkit-margin-before:0;margin-block-start:0}.pds-combobox__group-list{list-style:none;margin:0;padding:0}.pds-combobox__listbox--grouped .pds-combobox__group-list{display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;gap:var(--pine-dimension-2xs)}.pds-combobox__group-label--with-icon{-ms-flex-align:center;align-items:center;display:-ms-flexbox;display:flex;gap:var(--pine-dimension-xs)}.pds-combobox__group-icon{-ms-flex-negative:0;flex-shrink:0}.pds-combobox__group-row{list-style:none;position:relative}.pds-combobox__group-row-trigger{-ms-flex-align:center;align-items:center;border-radius:var(--pine-dimension-125);color:var(--pine-color-text-secondary);cursor:pointer;display:-ms-flexbox;display:flex;font:var(--pine-typography-body-medium);gap:var(--pine-dimension-xs);-ms-flex-pack:justify;justify-content:space-between;padding:var(--pine-dimension-xs) var(--pine-dimension-sm);-webkit-transition:background 0.15s;transition:background 0.15s}.pds-combobox__group-row--open>.pds-combobox__group-row-trigger,.pds-combobox__group-row--has-selection>.pds-combobox__group-row-trigger,.pds-combobox__group-row--highlighted>.pds-combobox__group-row-trigger,.pds-combobox__group-back--highlighted>.pds-combobox__group-row-trigger,.pds-combobox__group-row-trigger:hover{background:var(--pine-color-background-muted)}.pds-combobox__listbox--drill-in,.pds-combobox__listbox--drill-out{overflow-x:hidden}.pds-combobox__listbox--drill-in>.pds-combobox__group-back{-webkit-animation:pds-combobox-drill-from-end var(--pine-motion-duration-base) var(--pine-motion-easing-out);animation:pds-combobox-drill-from-end var(--pine-motion-duration-base) var(--pine-motion-easing-out)}.pds-combobox__listbox--drill-out>li{-webkit-animation:pds-combobox-drill-from-start var(--pine-motion-duration-base) var(--pine-motion-easing-out);animation:pds-combobox-drill-from-start var(--pine-motion-duration-base) var(--pine-motion-easing-out)}@-webkit-keyframes pds-combobox-drill-from-end{from{opacity:0;-webkit-transform:translateX(var(--pine-dimension-sm));transform:translateX(var(--pine-dimension-sm))}}@keyframes pds-combobox-drill-from-end{from{opacity:0;-webkit-transform:translateX(var(--pine-dimension-sm));transform:translateX(var(--pine-dimension-sm))}}@-webkit-keyframes pds-combobox-drill-from-start{from{opacity:0;-webkit-transform:translateX(calc(var(--pine-dimension-sm) * -1));transform:translateX(calc(var(--pine-dimension-sm) * -1))}}@keyframes pds-combobox-drill-from-start{from{opacity:0;-webkit-transform:translateX(calc(var(--pine-dimension-sm) * -1));transform:translateX(calc(var(--pine-dimension-sm) * -1))}}.pds-combobox__group-row--keyboard>.pds-combobox__group-row-trigger,.pds-combobox__group-back--keyboard>.pds-combobox__group-row-trigger{outline:var(--pine-outline-focus);outline-offset:calc(var(--pine-border-width) * -2)}.pds-combobox__group-row-label{-ms-flex-align:center;align-items:center;display:-ms-flexbox;display:flex;gap:var(--pine-dimension-xs);min-width:0}.pds-combobox__group-row-caret{-ms-flex-negative:0;flex-shrink:0}.pds-combobox__listbox--grouped,.pds-combobox__flyout{display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;gap:var(--pine-dimension-2xs);padding:var(--pine-dimension-2xs)}.pds-combobox__flyout{background:var(--pine-color-background-overlay);border-radius:var(--pine-dimension-125);-webkit-box-shadow:var(--pine-box-shadow);box-shadow:var(--pine-box-shadow);list-style:none;margin:0;overflow-y:auto;position:fixed;visibility:hidden;width:-webkit-max-content;width:-moz-max-content;width:max-content;z-index:1}.pds-combobox__listbox--with-search{display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;overflow:hidden;padding:0}.pds-combobox__listbox-options{-ms-flex:1;flex:1;list-style:none;margin:0;min-height:0;overflow-y:auto;padding:var(--pine-dimension-xs)}.pds-combobox__listbox-options.pds-combobox__listbox--grouped{padding:var(--pine-dimension-2xs)}.pds-combobox__panel-search{-ms-flex-align:center;align-items:center;-webkit-border-after:var(--pine-border);border-block-end:var(--pine-border);border-block-end-color:var(--pine-color-border-subtle);display:-ms-flexbox;display:flex;-ms-flex-negative:0;flex-shrink:0;gap:var(--pine-dimension-xs);padding:var(--pine-dimension-xs) var(--pine-dimension-sm)}.pds-combobox__panel-search pds-icon{color:var(--pine-color-text-muted);-ms-flex-negative:0;flex-shrink:0}.pds-combobox__panel-search:focus-within{border-block-end-color:var(--pine-color-border-active)}.pds-combobox__panel-search-input{background:transparent;border:0;color:var(--pine-color-text-strong);-ms-flex:1;flex:1;font:var(--pine-typography-body);letter-spacing:var(--pine-letter-spacing);min-width:0;outline:none}.pds-combobox__panel-search-input::-webkit-input-placeholder{color:var(--pine-color-text-placeholder)}.pds-combobox__panel-search-input::-moz-placeholder{color:var(--pine-color-text-placeholder)}.pds-combobox__panel-search-input:-ms-input-placeholder{color:var(--pine-color-text-placeholder)}.pds-combobox__panel-search-input::-ms-input-placeholder{color:var(--pine-color-text-placeholder)}.pds-combobox__panel-search-input::placeholder{color:var(--pine-color-text-placeholder)}.pds-combobox__group-back{display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;gap:var(--pine-dimension-2xs);list-style:none}.pds-combobox__group-back-trigger{-ms-flex-pack:start;justify-content:flex-start}.pds-combobox__listbox-options--drilled-in.pds-combobox__listbox--grouped{-webkit-padding-before:0;padding-block-start:0}.pds-combobox__listbox-options--drilled-in:focus{outline:none}.pds-combobox__listbox-options--drilled-in:focus .pds-combobox__group-back-trigger{border-block-end-color:var(--pine-color-border-active)}:where(.pds-combobox__listbox-options--drilled-in) .pds-combobox__group-back-trigger{background-color:var(--pine-color-background-overlay);-webkit-border-after:var(--pine-border);border-block-end:var(--pine-border);border-block-end-color:var(--pine-color-border-subtle);border-radius:0;inset-block-start:0;margin-inline:calc(var(--pine-dimension-2xs) * -1);position:-webkit-sticky;position:sticky;z-index:1}.pds-combobox__drill-in-options{display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;gap:var(--pine-dimension-2xs);list-style:none;margin:0;padding:0}.visually-hidden{border:0;clip:rect(0 0 0 0);-webkit-clip-path:polygon(0 0, 0 0, 0 0);clip-path:polygon(0 0, 0 0, 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;white-space:nowrap;width:1px}.pds-combobox__loading{-ms-flex-align:center;align-items:center;display:-ms-flexbox;display:flex;-ms-flex-pack:center;justify-content:center;padding:var(--pine-dimension-150)}.pds-combobox__empty{color:var(--pine-color-text-tertiary);padding:var(--pine-dimension-150) var(--pine-dimension-sm);text-align:center}.pds-combobox__load-more{-ms-flex-align:center;align-items:center;display:-ms-flexbox;display:flex;-ms-flex-pack:center;justify-content:center;padding:var(--pine-dimension-150)}.pds-combobox__button-trigger{-ms-flex-align:center;align-items:center;background:var(--color-background-default, var(--pine-color-secondary));border:var(--pine-border);border-radius:var(--pine-border-radius-full);color:var(--color-text-default, var(--pine-color-text-inverse-emphasis));cursor:pointer;display:-ms-flexbox;display:flex;font:var(--pine-typography-body-medium);-ms-flex-pack:justify;justify-content:space-between;min-height:var(--pine-dimension-450);outline:none;padding:0 var(--pine-dimension-sm);-webkit-transition:border-color 0.15s, background 0.15s, -webkit-box-shadow 0.15s;transition:border-color 0.15s, background 0.15s, -webkit-box-shadow 0.15s;transition:border-color 0.15s, box-shadow 0.15s, background 0.15s;transition:border-color 0.15s, box-shadow 0.15s, background 0.15s, -webkit-box-shadow 0.15s;width:-webkit-fit-content;width:-moz-fit-content;width:fit-content}.pds-combobox__button-trigger .pds-combobox__button-trigger-layout-wrapper{-ms-flex-align:center;align-items:center;display:-ms-flexbox;display:flex;-ms-flex:1;flex:1}.pds-combobox__button-trigger .trigger-content{-ms-flex-align:center;align-items:center;display:-ms-flexbox;display:flex;width:100%}.pds-combobox__button-trigger:focus-visible{border-color:var(--color-border-focus, var(--pine-color-border));-webkit-box-shadow:0 0 0 2px var(--color-outline, var(--pine-color-focus-ring));box-shadow:0 0 0 2px var(--color-outline, var(--pine-color-focus-ring))}.pds-combobox__button-trigger:hover{background:var(--color-background-hover, var(--pine-color-secondary-hover));border-color:var(--color-border-hover, var(--pine-color-border-hover))}.pds-combobox__button-trigger[aria-disabled=true],.pds-combobox__button-trigger:disabled{background:var(--color-background-disabled, var(--pine-color-secondary-disabled));border-color:var(--color-border-disabled, var(--pine-color-border-disabled));color:var(--color-text-disabled, var(--pine-color-text-secondary-disabled));cursor:not-allowed;opacity:0.6}.pds-combobox__button-trigger-label{color:inherit;-ms-flex:1 1 auto;flex:1 1 auto;text-align:start}.pds-combobox__button-trigger--input-shape{border-radius:var(--pine-dimension-125);min-height:var(--pine-dimension-500)}.pds-combobox__button-trigger-chevron{color:currentColor;-webkit-margin-start:var(--pine-dimension-150);margin-inline-start:var(--pine-dimension-150)}.pds-combobox__button-trigger--primary{--color-background-default:var(--pine-color-primary);--color-background-hover:var(--pine-color-primary-hover);--color-background-disabled:var(--pine-color-primary-disabled);--color-border-default:var(--pine-color-primary);--color-border-hover:var(--pine-color-primary-hover);--color-border-disabled:var(--pine-color-primary-disabled);--color-border-focus:var(--pine-color-primary);--color-text-default:var(--pine-color-text-primary);--color-text-disabled:var(--pine-color-text-primary-disabled);--color-outline:var(--pine-color-focus-ring)}.pds-combobox__button-trigger--accent{--color-background-default:var(--pine-color-accent);--color-background-hover:var(--pine-color-accent-hover);--color-background-disabled:var(--pine-color-accent-disabled);--color-border-default:var(--pine-color-accent);--color-border-hover:var(--pine-color-accent-hover);--color-border-disabled:var(--pine-color-accent-disabled);--color-border-focus:var(--pine-color-accent);--color-text-default:var(--pine-color-text-primary);--color-text-disabled:var(--pine-color-text-accent-disabled);--color-outline:var(--pine-color-focus-ring)}.pds-combobox__button-trigger--secondary{--color-background-default:var(--pine-color-secondary);--color-background-hover:var(--pine-color-secondary-hover);--color-background-disabled:var(--pine-color-secondary-disabled);--color-border-default:var(--pine-color-border);--color-border-hover:var(--pine-color-border-hover);--color-border-disabled:var(--pine-color-border-disabled);--color-border-focus:var(--pine-color-border);--color-text-default:var(--pine-color-text-secondary);--color-text-disabled:var(--pine-color-text-secondary-disabled);--color-outline:var(--pine-color-focus-ring)}.pds-combobox__button-trigger--destructive{--color-background-default:var(--pine-color-danger);--color-background-hover:var(--pine-color-danger-hover);--color-background-disabled:var(--pine-color-danger-disabled);--color-border-default:var(--pine-color-danger);--color-border-hover:var(--pine-color-danger-hover);--color-border-disabled:var(--pine-color-danger-disabled);--color-border-focus:var(--pine-color-danger);--color-text-default:var(--pine-color-white);--color-text-disabled:var(--pine-color-text-danger-disabled);--color-outline:var(--pine-color-focus-ring-danger)}[data-layout]{border-radius:var(--pine-dimension-125);padding-block:var(--pine-dimension-xs)}.pds-combobox__chip-trigger{-ms-flex-align:center;align-items:center;border-radius:var(--pine-dimension-sm);cursor:pointer;display:-ms-inline-flexbox;display:inline-flex;font:var(--pine-typography-body-medium);-ms-flex-pack:justify;justify-content:space-between;outline:none;padding-block:var(--pine-dimension-025);padding-inline:var(--pine-dimension-150);-webkit-transition:all 0.15s ease;transition:all 0.15s ease;width:-webkit-fit-content;width:-moz-fit-content;width:fit-content}.pds-combobox__chip-trigger .pds-combobox__chip-trigger-layout-wrapper{-ms-flex-align:center;align-items:center;display:-ms-flexbox;display:flex;-ms-flex:1;flex:1}.pds-combobox__chip-trigger .trigger-content{-ms-flex-align:center;align-items:center;display:-ms-flexbox;display:flex;width:100%}.pds-combobox__chip-trigger:focus-visible{outline:var(--pine-outline-focus);outline-offset:var(--pine-border-width)}.pds-combobox__chip-trigger[aria-disabled=true]{cursor:not-allowed;opacity:0.6}.pds-combobox__chip-trigger-label{color:inherit;-ms-flex:1 1 auto;flex:1 1 auto;text-align:start}.pds-combobox__chip-trigger-chevron{color:currentColor;-webkit-margin-start:var(--pine-dimension-150);margin-inline-start:var(--pine-dimension-150)}.pds-combobox__chip-trigger-icon{-webkit-margin-end:var(--pine-dimension-2xs);margin-inline-end:var(--pine-dimension-2xs)}.pds-combobox__chip-trigger--neutral,.pds-combobox__chip-trigger--accent,.pds-combobox__chip-trigger--success,.pds-combobox__chip-trigger--warning,.pds-combobox__chip-trigger--danger,.pds-combobox__chip-trigger--info{background:var(--chip-bg);border:var(--pine-border-width) solid var(--chip-border);color:var(--chip-text)}.pds-combobox__chip-trigger--neutral:hover:not([aria-disabled=true]),.pds-combobox__chip-trigger--accent:hover:not([aria-disabled=true]),.pds-combobox__chip-trigger--success:hover:not([aria-disabled=true]),.pds-combobox__chip-trigger--warning:hover:not([aria-disabled=true]),.pds-combobox__chip-trigger--danger:hover:not([aria-disabled=true]),.pds-combobox__chip-trigger--info:hover:not([aria-disabled=true]){background:var(--chip-bg-hover)}.pds-combobox__chip-trigger--neutral:focus-visible,.pds-combobox__chip-trigger--accent:focus-visible,.pds-combobox__chip-trigger--success:focus-visible,.pds-combobox__chip-trigger--warning:focus-visible,.pds-combobox__chip-trigger--danger:focus-visible,.pds-combobox__chip-trigger--info:focus-visible{border-color:var(--chip-border)}.pds-combobox__chip-trigger--neutral{--chip-bg:var(--pine-chip-color-neutral);--chip-bg-hover:var(--pine-chip-color-neutral-hover);--chip-border:var(--pine-chip-color-neutral-hover);--chip-text:var(--pine-color-text-neutral)}.pds-combobox__chip-trigger--accent{--chip-bg:var(--pine-chip-color-accent);--chip-bg-hover:var(--pine-chip-color-accent-hover);--chip-border:var(--pine-chip-color-accent-hover);--chip-text:var(--pine-color-text-accent)}.pds-combobox__chip-trigger--success{--chip-bg:var(--pine-chip-color-success);--chip-bg-hover:var(--pine-chip-color-success-hover);--chip-border:var(--pine-chip-color-success-hover);--chip-text:var(--pine-color-text-success)}.pds-combobox__chip-trigger--warning{--chip-bg:var(--pine-chip-color-warning);--chip-bg-hover:var(--pine-chip-color-warning-hover);--chip-border:var(--pine-chip-color-warning-hover);--chip-text:var(--pine-color-text-warning)}.pds-combobox__chip-trigger--danger{--chip-bg:var(--pine-chip-color-danger);--chip-bg-hover:var(--pine-chip-color-danger-hover);--chip-border:var(--pine-chip-color-danger-hover);--chip-text:var(--pine-color-text-danger)}.pds-combobox__chip-trigger--info{--chip-bg:var(--pine-chip-color-info);--chip-bg-hover:var(--pine-chip-color-info-hover);--chip-border:var(--pine-chip-color-info-hover);--chip-text:var(--pine-color-text-info)}.pds-combobox__chip-trigger--brand{background:-webkit-gradient(linear, left top, right top, from(#FF3E14), to(#6B62F2));background:linear-gradient(90deg, #FF3E14 0%, #6B62F2 100%);border:0;color:var(--pine-color-text-neutral);padding:1px;position:relative}.pds-combobox__chip-trigger--brand .pds-combobox__chip-trigger-label{background:rgba(255, 255, 255, 0.9);border-radius:calc(var(--pine-dimension-sm) - 1px);color:var(--pine-color-text-neutral);font-weight:var(--pine-font-weight-medium);padding:var(--pine-dimension-025) var(--pine-dimension-150);position:relative;z-index:1}.pds-combobox__chip-trigger--brand .pds-combobox__chip-trigger-chevron{position:relative;z-index:1}.pds-combobox__chip-trigger--brand:hover:not([aria-disabled=true]) .pds-combobox__chip-trigger-label{background:rgba(255, 255, 255, 0.8)}.pds-combobox__chip-trigger--dropdown:not(.pds-combobox__chip-trigger--brand){padding:var(--pine-dimension-none)}.pds-combobox__chip-trigger--dropdown:not(.pds-combobox__chip-trigger--brand) .pds-combobox__chip-trigger-label{padding:var(--pine-dimension-025) var(--pine-dimension-150)}.pds-combobox__chip-trigger--large .pds-combobox__chip-trigger-label{font-family:var(--pine-font-family-heading);font-size:var(--pine-font-size-heading-6);font-weight:var(--pine-font-weight-medium);letter-spacing:var(--pine-letter-spacing-heading-6)}.pds-combobox__chip-trigger--dot .pds-combobox__chip-trigger-label::before{border:var(--pine-border-width) solid transparent;border-radius:var(--pine-border-radius-full);content:"";display:inline-block;height:var(--pine-dimension-2xs);-webkit-margin-end:var(--pine-dimension-2xs);margin-inline-end:var(--pine-dimension-2xs);width:var(--pine-dimension-2xs)}`;
|
|
1393
1655
|
|
|
1394
1656
|
const PdsCombobox = class {
|
|
1395
1657
|
constructor(hostRef) {
|
|
@@ -1436,6 +1698,35 @@ const PdsCombobox = class {
|
|
|
1436
1698
|
* @default 'host'
|
|
1437
1699
|
*/
|
|
1438
1700
|
this.dropdownMount = 'host';
|
|
1701
|
+
/**
|
|
1702
|
+
* Accessible prefix for the row that returns to the group list when `group-display` is
|
|
1703
|
+
* `drill-in`, read before the open group's label. Pass a translated string to localize it; defaults to English.
|
|
1704
|
+
* @defaultValue 'Back'
|
|
1705
|
+
*/
|
|
1706
|
+
this.drillInBackLabel = 'Back';
|
|
1707
|
+
/**
|
|
1708
|
+
* Maximum width of a group's flyout when `group-display` is `flyout`. Any valid CSS width value.
|
|
1709
|
+
* @default '380px'
|
|
1710
|
+
*/
|
|
1711
|
+
this.flyoutMaxWidth = '380px';
|
|
1712
|
+
/**
|
|
1713
|
+
* Minimum width of a group's flyout when `group-display` is `flyout`. Any valid CSS width value.
|
|
1714
|
+
* The flyout is as wide as its options, between this and `flyout-max-width`.
|
|
1715
|
+
* @default '280px'
|
|
1716
|
+
*/
|
|
1717
|
+
this.flyoutMinWidth = '280px';
|
|
1718
|
+
/**
|
|
1719
|
+
* How option groups (`<optgroup>`, or the `group` field of `options`) are shown in the dropdown.
|
|
1720
|
+
* `inline` lists each group's label above its options. `flyout` lists the groups, and opens a
|
|
1721
|
+
* group's options in a panel beside it on hover or click; while searching, the matching options
|
|
1722
|
+
* are listed under their group labels, and search also matches group labels. `flyout` groups
|
|
1723
|
+
* by `<optgroup>` (or `group`) only: options under a `<pds-text>` heading are listed ungrouped.
|
|
1724
|
+
* `drill-in` lists the groups too, but a click replaces the list with that group's options and a
|
|
1725
|
+
* row back to the groups; use it where nothing can open beside the dropdown, such as a side
|
|
1726
|
+
* panel. `flyout` falls back to `drill-in` when there is no room for a flyout on either side.
|
|
1727
|
+
* @default 'inline'
|
|
1728
|
+
*/
|
|
1729
|
+
this.groupDisplay = 'inline';
|
|
1439
1730
|
/**
|
|
1440
1731
|
* Visually hides the label text for instances where only the combobox should be displayed.
|
|
1441
1732
|
* The visible `<label>` is omitted (same pattern as `pds-select`) so label spacing does not reserve layout;
|
|
@@ -1449,6 +1740,23 @@ const PdsCombobox = class {
|
|
|
1449
1740
|
* @default 'filter'
|
|
1450
1741
|
*/
|
|
1451
1742
|
this.mode = 'filter';
|
|
1743
|
+
/**
|
|
1744
|
+
* Shows a search field at the top of the dropdown for the `button` and `chip` triggers, which
|
|
1745
|
+
* can't be typed into. Search filters the options the same way typing in the `input` trigger
|
|
1746
|
+
* does; in a grouped display it also matches group labels.
|
|
1747
|
+
* @default false
|
|
1748
|
+
*/
|
|
1749
|
+
this.panelSearch = false;
|
|
1750
|
+
/**
|
|
1751
|
+
* Accessible label for the search input inside the dropdown panel (`panel-search`). Pass a translated string to localize it; defaults to English.
|
|
1752
|
+
* @defaultValue 'Search options'
|
|
1753
|
+
*/
|
|
1754
|
+
this.searchOptionsLabel = 'Search options';
|
|
1755
|
+
/**
|
|
1756
|
+
* Placeholder text for the search input inside the dropdown panel (`panel-search`). Pass a translated string to localize it; defaults to English.
|
|
1757
|
+
* @defaultValue 'Find...'
|
|
1758
|
+
*/
|
|
1759
|
+
this.searchPlaceholder = 'Find...';
|
|
1452
1760
|
/**
|
|
1453
1761
|
* Determines the combobox trigger: 'input' (editable input), 'button' (button-like, non-editable), or 'chip' (chip-like, non-editable).
|
|
1454
1762
|
* @default 'input'
|
|
@@ -1521,6 +1829,30 @@ const PdsCombobox = class {
|
|
|
1521
1829
|
* Internal state for dropdown open/close
|
|
1522
1830
|
*/
|
|
1523
1831
|
this.isOpen = false;
|
|
1832
|
+
/**
|
|
1833
|
+
* The optgroup whose flyout is open, when `groupDisplay` is `flyout`.
|
|
1834
|
+
*/
|
|
1835
|
+
this.openGroup = null;
|
|
1836
|
+
/**
|
|
1837
|
+
* Which way drill-in just moved, so the list slides that way: `in` to a group, `out` back to the
|
|
1838
|
+
* groups. Cleared once the slide ends, so later renders don't animate.
|
|
1839
|
+
*/
|
|
1840
|
+
this.drillDirection = null;
|
|
1841
|
+
/**
|
|
1842
|
+
* The group row highlighted in the grouped panel. It counts only while no option is
|
|
1843
|
+
* highlighted (`highlightedIndex` is -1); see `highlightedGroupRow`.
|
|
1844
|
+
*/
|
|
1845
|
+
this.highlightedGroup = null;
|
|
1846
|
+
/** The keys, not the pointer, moved the highlight last; the focus ring shows only then. */
|
|
1847
|
+
this.keyboardNavigating = false;
|
|
1848
|
+
/**
|
|
1849
|
+
* What's typed in the dropdown's own search field (`panelSearch`).
|
|
1850
|
+
*/
|
|
1851
|
+
this.panelQuery = '';
|
|
1852
|
+
/**
|
|
1853
|
+
* `groupDisplay` is `flyout` but there's no room beside the dropdown, so groups drill in instead.
|
|
1854
|
+
*/
|
|
1855
|
+
this.flyoutFallback = false;
|
|
1524
1856
|
/**
|
|
1525
1857
|
* Internal state for the currently selected option
|
|
1526
1858
|
*/
|
|
@@ -1550,12 +1882,39 @@ const PdsCombobox = class {
|
|
|
1550
1882
|
this.portalEl = null;
|
|
1551
1883
|
this.bodyPortalAutoUpdateActive = false;
|
|
1552
1884
|
this.isUpdatingFromSelection = false;
|
|
1885
|
+
this.flyout = new FlyoutController(() => this.openGroup, group => {
|
|
1886
|
+
this.openGroup = group;
|
|
1887
|
+
});
|
|
1888
|
+
/** The groups in the flyout panel's last render, so a row's index finds its optgroup. */
|
|
1889
|
+
this.renderedGroups = [];
|
|
1890
|
+
/** Room for a flyout was checked for this open. */
|
|
1891
|
+
this.flyoutRoomChecked = false;
|
|
1892
|
+
/** The highlighted option sits in a flyout that hasn't rendered yet; focus it after the next render. */
|
|
1893
|
+
this.pendingOptionFocus = false;
|
|
1894
|
+
/** Group rows' DOM ids, stable across renders so `aria-activedescendant` can point at a row. */
|
|
1895
|
+
this.groupIds = new WeakMap();
|
|
1896
|
+
this.groupIdCount = 0;
|
|
1553
1897
|
/**
|
|
1554
1898
|
* In filter mode, after choosing an option the input still shows the label and would
|
|
1555
1899
|
* otherwise filter the list to matching substrings only. While this flag is true,
|
|
1556
1900
|
* the list shows every option until the user types (then normal filtering applies).
|
|
1557
1901
|
*/
|
|
1558
1902
|
this.expandFilterListWhileOpen = false;
|
|
1903
|
+
this.onDrillAnimationEnd = (event) => {
|
|
1904
|
+
var _a;
|
|
1905
|
+
// Only the slide's own end: slotted consumer content can animate inside the list too.
|
|
1906
|
+
if ((_a = event.animationName) === null || _a === void 0 ? void 0 : _a.startsWith('pds-combobox-drill'))
|
|
1907
|
+
this.drillDirection = null;
|
|
1908
|
+
};
|
|
1909
|
+
/** `<label for>` only works on the input trigger; for a div trigger a click on the label focuses it. */
|
|
1910
|
+
this.onLabelClick = () => {
|
|
1911
|
+
var _a;
|
|
1912
|
+
if (this.trigger !== 'input' && !this.disabled) {
|
|
1913
|
+
(_a = this.triggerEl) === null || _a === void 0 ? void 0 : _a.focus();
|
|
1914
|
+
}
|
|
1915
|
+
};
|
|
1916
|
+
/** The query behind the options loaded from `async-url`. */
|
|
1917
|
+
this.lastFetchedQuery = '';
|
|
1559
1918
|
this.handleInput = (e) => {
|
|
1560
1919
|
const target = e.target;
|
|
1561
1920
|
this.clearExpandFilterList();
|
|
@@ -1592,6 +1951,7 @@ const PdsCombobox = class {
|
|
|
1592
1951
|
this.handleKeyDown = (e) => {
|
|
1593
1952
|
if (!this.isOpen && (e.key === 'ArrowDown' || e.key === 'ArrowUp' || (e.altKey && e.key === 'ArrowDown'))) {
|
|
1594
1953
|
e.preventDefault();
|
|
1954
|
+
this.keyboardNavigating = true;
|
|
1595
1955
|
this.isOpen = true;
|
|
1596
1956
|
this.prepareExpandFilterListOnOpen();
|
|
1597
1957
|
this.filterOptions();
|
|
@@ -1613,75 +1973,53 @@ const PdsCombobox = class {
|
|
|
1613
1973
|
if (!this.isOpen) {
|
|
1614
1974
|
return;
|
|
1615
1975
|
}
|
|
1976
|
+
if (this.handleGroupedPanelKey(e))
|
|
1977
|
+
return;
|
|
1978
|
+
// The input trigger's text keeps Space, Home and End while the grouped panel shows.
|
|
1979
|
+
if (this.showsGroupedPanel && this.trigger === 'input' && (e.key === ' ' || e.key === 'Home' || e.key === 'End'))
|
|
1980
|
+
return;
|
|
1616
1981
|
// Get only the option elements (skip group labels) for navigation
|
|
1617
1982
|
const selectableOptions = this.filteredItems.filter(item => item.tagName === 'OPTION');
|
|
1618
1983
|
switch (e.key) {
|
|
1619
1984
|
case 'ArrowDown':
|
|
1620
1985
|
e.preventDefault();
|
|
1621
|
-
// If no option is highlighted
|
|
1622
|
-
|
|
1623
|
-
this.highlightedIndex = 0;
|
|
1624
|
-
}
|
|
1625
|
-
else {
|
|
1626
|
-
this.highlightedIndex = Math.min(this.highlightedIndex + 1, selectableOptions.length - 1);
|
|
1627
|
-
}
|
|
1628
|
-
this.updateOptionFocus();
|
|
1986
|
+
// If no option is highlighted, start at the first
|
|
1987
|
+
this.highlightOptionAt(selectableOptions, this.highlightedIndex < 0 ? 0 : this.highlightedIndex + 1);
|
|
1629
1988
|
break;
|
|
1630
1989
|
case 'ArrowUp':
|
|
1631
1990
|
e.preventDefault();
|
|
1632
|
-
// If no option is highlighted
|
|
1633
|
-
|
|
1634
|
-
this.highlightedIndex = selectableOptions.length - 1;
|
|
1635
|
-
}
|
|
1636
|
-
else {
|
|
1637
|
-
this.highlightedIndex = Math.max(this.highlightedIndex - 1, 0);
|
|
1638
|
-
}
|
|
1639
|
-
this.updateOptionFocus();
|
|
1991
|
+
// If no option is highlighted, start at the last
|
|
1992
|
+
this.highlightOptionAt(selectableOptions, this.highlightedIndex < 0 ? selectableOptions.length - 1 : this.highlightedIndex - 1);
|
|
1640
1993
|
break;
|
|
1641
1994
|
case 'Home':
|
|
1642
1995
|
e.preventDefault();
|
|
1643
|
-
|
|
1644
|
-
this.highlightedIndex = 0;
|
|
1645
|
-
this.updateOptionFocus();
|
|
1646
|
-
}
|
|
1996
|
+
this.highlightOptionAt(selectableOptions, 0);
|
|
1647
1997
|
break;
|
|
1648
1998
|
case 'End':
|
|
1649
1999
|
e.preventDefault();
|
|
1650
|
-
|
|
1651
|
-
this.highlightedIndex = selectableOptions.length - 1;
|
|
1652
|
-
this.updateOptionFocus();
|
|
1653
|
-
}
|
|
2000
|
+
this.highlightOptionAt(selectableOptions, selectableOptions.length - 1);
|
|
1654
2001
|
break;
|
|
1655
2002
|
case 'PageDown':
|
|
1656
2003
|
e.preventDefault();
|
|
1657
|
-
|
|
1658
|
-
const nextIndex = Math.min(this.highlightedIndex + 10, selectableOptions.length - 1);
|
|
1659
|
-
this.highlightedIndex = nextIndex;
|
|
1660
|
-
this.updateOptionFocus();
|
|
1661
|
-
}
|
|
2004
|
+
this.highlightOptionAt(selectableOptions, this.highlightedIndex + 10);
|
|
1662
2005
|
break;
|
|
1663
2006
|
case 'PageUp':
|
|
1664
2007
|
e.preventDefault();
|
|
1665
|
-
|
|
1666
|
-
const prevIndex = Math.max(this.highlightedIndex - 10, 0);
|
|
1667
|
-
this.highlightedIndex = prevIndex;
|
|
1668
|
-
this.updateOptionFocus();
|
|
1669
|
-
}
|
|
2008
|
+
this.highlightOptionAt(selectableOptions, this.highlightedIndex - 10);
|
|
1670
2009
|
break;
|
|
1671
2010
|
case 'Enter':
|
|
2011
|
+
case ' ': {
|
|
1672
2012
|
e.preventDefault();
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
e.preventDefault();
|
|
1680
|
-
if (this.highlightedIndex >= 0 && this.highlightedIndex < selectableOptions.length) {
|
|
1681
|
-
this.handleOptionClick(selectableOptions[this.highlightedIndex]);
|
|
2013
|
+
// An option in a flyout the pointer has since closed isn't on screen; don't choose it.
|
|
2014
|
+
if (this.showsGroupedPanel && this.activeDescendantId === undefined)
|
|
2015
|
+
break;
|
|
2016
|
+
const option = selectableOptions[this.highlightedIndex];
|
|
2017
|
+
if (option !== undefined && !isOptionDisabled(option)) {
|
|
2018
|
+
this.handleOptionClick(option);
|
|
1682
2019
|
this.restoreFocusToTrigger();
|
|
1683
2020
|
}
|
|
1684
2021
|
break;
|
|
2022
|
+
}
|
|
1685
2023
|
case 'Escape':
|
|
1686
2024
|
e.preventDefault();
|
|
1687
2025
|
this.isOpen = false;
|
|
@@ -1706,12 +2044,53 @@ const PdsCombobox = class {
|
|
|
1706
2044
|
const idx = Number(event.currentTarget.getAttribute('data-option-index'));
|
|
1707
2045
|
const selectableOptions = this.filteredItems.filter(item => item.tagName === 'OPTION');
|
|
1708
2046
|
const option = selectableOptions[idx];
|
|
2047
|
+
if (isOptionDisabled(option))
|
|
2048
|
+
return;
|
|
1709
2049
|
this.handleOptionClick(option);
|
|
2050
|
+
// The search field closes with the panel; send focus back to the trigger instead of losing it.
|
|
2051
|
+
// (Enter and Space already restore focus in the key handler.)
|
|
2052
|
+
if (this.usesPanelSearch)
|
|
2053
|
+
this.restoreFocusToTrigger();
|
|
1710
2054
|
};
|
|
1711
2055
|
// Event handler for mouse enter on option
|
|
1712
2056
|
this.onOptionMouseEnter = (event) => {
|
|
1713
2057
|
const idx = Number(event.currentTarget.getAttribute('data-option-index'));
|
|
1714
2058
|
this.highlightedIndex = idx;
|
|
2059
|
+
this.keyboardNavigating = false;
|
|
2060
|
+
};
|
|
2061
|
+
this.onGroupRowMouseEnter = (event) => {
|
|
2062
|
+
const group = this.groupFromEvent(event);
|
|
2063
|
+
if (group !== null)
|
|
2064
|
+
this.flyout.enter(group);
|
|
2065
|
+
};
|
|
2066
|
+
this.onGroupRowMouseLeave = (event) => {
|
|
2067
|
+
const group = this.groupFromEvent(event);
|
|
2068
|
+
if (group !== null)
|
|
2069
|
+
this.flyout.leave(group);
|
|
2070
|
+
};
|
|
2071
|
+
// The pointer highlights a group's row as it does an option, so the keys carry on from there.
|
|
2072
|
+
this.onGroupRowTriggerMouseEnter = (event) => {
|
|
2073
|
+
const group = this.groupFromEvent(event);
|
|
2074
|
+
if (group !== null)
|
|
2075
|
+
this.highlightGroupRowByPointer(group);
|
|
2076
|
+
};
|
|
2077
|
+
this.onGroupBackMouseEnter = () => {
|
|
2078
|
+
if (this.openGroup !== null)
|
|
2079
|
+
this.highlightGroupRowByPointer(this.openGroup);
|
|
2080
|
+
};
|
|
2081
|
+
this.onGroupRowClick = (event) => {
|
|
2082
|
+
var _a;
|
|
2083
|
+
const group = this.groupFromEvent(event);
|
|
2084
|
+
if (group === null)
|
|
2085
|
+
return;
|
|
2086
|
+
this.flyout.open(group);
|
|
2087
|
+
// Highlight the group's first option, so the arrow keys carry on from the group just opened
|
|
2088
|
+
// rather than from wherever the highlight was before.
|
|
2089
|
+
const first = (_a = this.renderedGroups.find(entry => entry.optgroup === group)) === null || _a === void 0 ? void 0 : _a.options[0];
|
|
2090
|
+
if (first !== undefined) {
|
|
2091
|
+
this.highlightedIndex = first.index;
|
|
2092
|
+
this.updateAriaActiveDescendant();
|
|
2093
|
+
}
|
|
1715
2094
|
};
|
|
1716
2095
|
// Prevent blur on mousedown
|
|
1717
2096
|
this.onOptionMouseDown = (event) => {
|
|
@@ -1728,10 +2107,7 @@ const PdsCombobox = class {
|
|
|
1728
2107
|
if (this.isOpen) {
|
|
1729
2108
|
this.prepareExpandFilterListOnOpen();
|
|
1730
2109
|
this.filterOptions();
|
|
1731
|
-
|
|
1732
|
-
if (this.asyncUrl && this.internalOptions.length === 0) {
|
|
1733
|
-
this.debouncedFetchAsyncOptions(this.displayText, 1);
|
|
1734
|
-
}
|
|
2110
|
+
this.fetchAsyncOptionsOnOpen();
|
|
1735
2111
|
// Set highlighted index and prepare for keyboard navigation
|
|
1736
2112
|
this.setInitialHighlightedIndex();
|
|
1737
2113
|
// For button trigger, prepare for arrow-key navigation mode
|
|
@@ -1746,12 +2122,17 @@ const PdsCombobox = class {
|
|
|
1746
2122
|
};
|
|
1747
2123
|
// Handler for button trigger keyboard events
|
|
1748
2124
|
this.onButtonTriggerKeyDown = (e) => {
|
|
2125
|
+
// Escape closes an open group before the dropdown. Other keys reach the tree through handleKeyDown.
|
|
2126
|
+
if (this.isOpen && e.key === 'Escape' && this.handleGroupedPanelKey(e))
|
|
2127
|
+
return;
|
|
1749
2128
|
if ((e.key === 'Enter' || e.key === ' ' || e.key === 'ArrowDown' || e.key === 'ArrowUp') && !this.isOpen) {
|
|
1750
2129
|
e.preventDefault();
|
|
1751
2130
|
e.stopPropagation(); // Prevent the event from bubbling and triggering click
|
|
2131
|
+
this.keyboardNavigating = true;
|
|
1752
2132
|
this.isOpen = true;
|
|
1753
2133
|
this.prepareExpandFilterListOnOpen();
|
|
1754
2134
|
this.filterOptions();
|
|
2135
|
+
this.fetchAsyncOptionsOnOpen();
|
|
1755
2136
|
// Set highlighted index immediately
|
|
1756
2137
|
this.setInitialHighlightedIndex();
|
|
1757
2138
|
setTimeout(() => {
|
|
@@ -1784,11 +2165,13 @@ const PdsCombobox = class {
|
|
|
1784
2165
|
};
|
|
1785
2166
|
// Close dropdown when focus leaves the combobox
|
|
1786
2167
|
this.onComboboxFocusOut = (event) => {
|
|
1787
|
-
var _a, _b;
|
|
2168
|
+
var _a, _b, _c;
|
|
1788
2169
|
const relatedTarget = event.relatedTarget;
|
|
1789
2170
|
const isRelatedTargetInListbox = relatedTarget &&
|
|
1790
2171
|
(((_a = this.listboxEl) === null || _a === void 0 ? void 0 : _a.contains(relatedTarget)) || ((_b = this.portalEl) === null || _b === void 0 ? void 0 : _b.contains(relatedTarget)));
|
|
1791
|
-
|
|
2172
|
+
// `contains` doesn't cross into the shadow root, where the trigger lives; with panel search,
|
|
2173
|
+
// focus leaves the search field for the trigger whenever it's clicked to close.
|
|
2174
|
+
const isRelatedTargetInCombobox = relatedTarget !== null && (this.el.contains(relatedTarget) || !!((_c = this.el.shadowRoot) === null || _c === void 0 ? void 0 : _c.contains(relatedTarget)));
|
|
1792
2175
|
// Don't close if focus is moving to an option in the listbox or staying within the combobox
|
|
1793
2176
|
if (!isRelatedTargetInCombobox && !isRelatedTargetInListbox) {
|
|
1794
2177
|
this.isOpen = false;
|
|
@@ -1811,11 +2194,58 @@ const PdsCombobox = class {
|
|
|
1811
2194
|
// Load more when near bottom (within 50px)
|
|
1812
2195
|
if (scrollBottom < 50) {
|
|
1813
2196
|
this.pdsComboboxLoadOptions.emit({
|
|
1814
|
-
query: this.
|
|
2197
|
+
query: this.activeQuery,
|
|
1815
2198
|
page: this.currentPage + 1,
|
|
1816
2199
|
});
|
|
1817
|
-
this.debouncedFetchAsyncOptions(this.
|
|
2200
|
+
this.debouncedFetchAsyncOptions(this.activeQuery, this.currentPage + 1);
|
|
2201
|
+
}
|
|
2202
|
+
};
|
|
2203
|
+
// A press on the panel's padding, captions or status rows keeps focus in the search field;
|
|
2204
|
+
// otherwise it would blur the field, closing a portaled panel or stranding the keys.
|
|
2205
|
+
this.onPanelMouseDown = (event) => {
|
|
2206
|
+
if (event.target !== this.panelSearchEl)
|
|
2207
|
+
event.preventDefault();
|
|
2208
|
+
};
|
|
2209
|
+
this.onPanelSearchInput = (event) => {
|
|
2210
|
+
this.setPanelQuery(event.target.value);
|
|
2211
|
+
};
|
|
2212
|
+
// Space, Home and End edit the search text rather than moving through the options.
|
|
2213
|
+
this.onPanelSearchKeyDown = (event) => {
|
|
2214
|
+
if (event.key === ' ' || event.key === 'Home' || event.key === 'End')
|
|
2215
|
+
return;
|
|
2216
|
+
if (this.handlePanelTab(event))
|
|
2217
|
+
return;
|
|
2218
|
+
this.handleKeyDown(event);
|
|
2219
|
+
};
|
|
2220
|
+
/**
|
|
2221
|
+
* Keys in the list while a drilled-in group hides the search field. Backspace, like ArrowLeft,
|
|
2222
|
+
* steps back to the groups; a character starts a search of the whole list. Characters typed
|
|
2223
|
+
* before the search field renders and takes focus still land on the list, so they add to the
|
|
2224
|
+
* query rather than starting it again.
|
|
2225
|
+
*/
|
|
2226
|
+
this.onPanelTreeKeyDown = (event) => {
|
|
2227
|
+
if (this.handlePanelTab(event))
|
|
2228
|
+
return;
|
|
2229
|
+
if (event.key === 'Backspace') {
|
|
2230
|
+
event.preventDefault();
|
|
2231
|
+
if (!this.leaveDrilledInGroup() && this.panelQuery !== '')
|
|
2232
|
+
this.setPanelQuery(this.panelQuery.slice(0, -1));
|
|
2233
|
+
return;
|
|
1818
2234
|
}
|
|
2235
|
+
// AltGr (Ctrl+Alt on Windows) and Option on macOS type characters too; Meta and Ctrl alone are
|
|
2236
|
+
// shortcuts.
|
|
2237
|
+
if (event.key.length === 1 && event.key !== ' ' && !event.metaKey && (!event.ctrlKey || event.altKey)) {
|
|
2238
|
+
event.preventDefault();
|
|
2239
|
+
this.flyout.reset();
|
|
2240
|
+
// The query first, so leaving the group reads as search results, not a slide back.
|
|
2241
|
+
this.setPanelQuery(this.panelQuery + event.key);
|
|
2242
|
+
this.openGroup = null;
|
|
2243
|
+
return;
|
|
2244
|
+
}
|
|
2245
|
+
this.handleKeyDown(event);
|
|
2246
|
+
};
|
|
2247
|
+
this.onGroupBackClick = () => {
|
|
2248
|
+
this.leaveDrilledInGroup();
|
|
1819
2249
|
};
|
|
1820
2250
|
}
|
|
1821
2251
|
connectedCallback() {
|
|
@@ -1852,15 +2282,106 @@ const PdsCombobox = class {
|
|
|
1852
2282
|
this.deferredPortalTeardownId = undefined;
|
|
1853
2283
|
}
|
|
1854
2284
|
(_a = this.observer) === null || _a === void 0 ? void 0 : _a.disconnect();
|
|
2285
|
+
cancelDebouncedEvent(this.pdsComboboxSearch);
|
|
1855
2286
|
this.clearAsyncFetchState();
|
|
1856
2287
|
this.removeBodyPortal();
|
|
2288
|
+
this.flyout.reset();
|
|
1857
2289
|
}
|
|
1858
2290
|
componentDidRender() {
|
|
2291
|
+
var _a;
|
|
1859
2292
|
if (this.usesBodyPortal && this.isOpen) {
|
|
1860
2293
|
this.syncBodyPortal();
|
|
1861
2294
|
}
|
|
2295
|
+
const row = (_a = this.listboxEl) === null || _a === void 0 ? void 0 : _a.querySelector('.pds-combobox__group-row--open');
|
|
2296
|
+
const flyoutEl = row === null || row === void 0 ? void 0 : row.querySelector('.pds-combobox__flyout');
|
|
2297
|
+
if (this.isOpen && this.listboxEl && row && flyoutEl) {
|
|
2298
|
+
this.flyout.position(row, this.listboxEl, flyoutEl);
|
|
2299
|
+
}
|
|
2300
|
+
else {
|
|
2301
|
+
this.flyout.stopPositioning();
|
|
2302
|
+
}
|
|
2303
|
+
// The row back is sticky over the group's options; scrolling an option into view stops below
|
|
2304
|
+
// it. Set before any scroll below, and when it first applies, scroll the highlighted option
|
|
2305
|
+
// again: the list keeps its offset on drilling in, and an earlier scroll had no padding.
|
|
2306
|
+
if (this.panelTreeEl) {
|
|
2307
|
+
const header = this.hidesPanelSearch ? this.panelTreeEl.querySelector('.pds-combobox__group-back-trigger') : null;
|
|
2308
|
+
const padding = header ? `${header.offsetHeight}px` : '';
|
|
2309
|
+
if (this.panelTreeEl.style.scrollPaddingBlockStart !== padding) {
|
|
2310
|
+
this.panelTreeEl.style.scrollPaddingBlockStart = padding;
|
|
2311
|
+
if (padding !== '' && this.highlightedIndex >= 0)
|
|
2312
|
+
this.pendingOptionFocus = true;
|
|
2313
|
+
}
|
|
2314
|
+
}
|
|
2315
|
+
if (this.pendingOptionFocus) {
|
|
2316
|
+
this.pendingOptionFocus = false;
|
|
2317
|
+
this.updateOptionFocus();
|
|
2318
|
+
}
|
|
2319
|
+
// Panel search keeps focus in the search field, or in the list while a group hides the field.
|
|
2320
|
+
const panelFocusEl = this.hidesPanelSearch ? this.panelTreeEl : this.panelSearchEl;
|
|
2321
|
+
if (this.isOpen && this.usesPanelSearch && panelFocusEl && panelFocusEl !== this.panelFocusEl) {
|
|
2322
|
+
this.focusPanel(panelFocusEl);
|
|
2323
|
+
}
|
|
2324
|
+
}
|
|
2325
|
+
focusPanel(el) {
|
|
2326
|
+
var _a, _b;
|
|
2327
|
+
this.panelFocusEl = el;
|
|
2328
|
+
// Before the dropdown is positioned it sits in the page's flow; don't scroll to it.
|
|
2329
|
+
el.focus({ preventScroll: true });
|
|
2330
|
+
// A search started by typing in the list carries its first character; type on after it.
|
|
2331
|
+
if (el === this.panelSearchEl && this.panelQuery !== '') {
|
|
2332
|
+
(_b = (_a = this.panelSearchEl).setSelectionRange) === null || _b === void 0 ? void 0 : _b.call(_a, this.panelQuery.length, this.panelQuery.length);
|
|
2333
|
+
}
|
|
2334
|
+
this.updateAriaActiveDescendant();
|
|
2335
|
+
}
|
|
2336
|
+
/** Switching display mode leaves no flyout or hover timer from the last one. */
|
|
2337
|
+
groupDisplayChanged() {
|
|
2338
|
+
this.flyout.reset();
|
|
2339
|
+
this.openGroup = null;
|
|
2340
|
+
// The reset isn't a drill-out, so it doesn't slide either.
|
|
2341
|
+
this.drillDirection = null;
|
|
2342
|
+
}
|
|
2343
|
+
openGroupChanged(next, previous) {
|
|
2344
|
+
this.handPanelFocusToList();
|
|
2345
|
+
// Only moves between the drill-in panel's views slide; search results don't.
|
|
2346
|
+
if (!this.isOpen || this.effectiveGroupDisplay !== 'drill-in' || !this.showsGroupedPanel)
|
|
2347
|
+
return;
|
|
2348
|
+
if (next !== null && previous === null)
|
|
2349
|
+
this.drillDirection = 'in';
|
|
2350
|
+
else if (next === null && previous !== null)
|
|
2351
|
+
this.drillDirection = 'out';
|
|
2352
|
+
}
|
|
2353
|
+
/** A flyout with no room beside the dropdown drills in, which can hide the focused search field too. */
|
|
2354
|
+
flyoutFallbackChanged() {
|
|
2355
|
+
this.handPanelFocusToList();
|
|
2356
|
+
}
|
|
2357
|
+
/**
|
|
2358
|
+
* Drilling into a group hides the search field, so focus moves to the list before the field
|
|
2359
|
+
* unmounts: focus lost with it would leave the combobox and close the dropdown.
|
|
2360
|
+
*/
|
|
2361
|
+
handPanelFocusToList() {
|
|
2362
|
+
if (this.isOpen && this.hidesPanelSearch && this.panelTreeEl)
|
|
2363
|
+
this.focusPanel(this.panelTreeEl);
|
|
1862
2364
|
}
|
|
1863
2365
|
isOpenChanged(isOpen) {
|
|
2366
|
+
if (!isOpen) {
|
|
2367
|
+
this.drillDirection = null;
|
|
2368
|
+
this.openGroup = null;
|
|
2369
|
+
this.highlightedGroup = null;
|
|
2370
|
+
this.keyboardNavigating = false;
|
|
2371
|
+
this.flyout.reset();
|
|
2372
|
+
if (this.panelQuery !== '') {
|
|
2373
|
+
// The field reopens empty, so tell consumers who filter `options` from this event.
|
|
2374
|
+
this.panelQuery = '';
|
|
2375
|
+
this.pdsComboboxSearch.emit({ query: '' });
|
|
2376
|
+
}
|
|
2377
|
+
// And with `async-url`, start loading the unsearched list now, so it's ready by the reopen.
|
|
2378
|
+
if (this.usesPanelSearch && this.asyncUrl && this.lastFetchedQuery !== '') {
|
|
2379
|
+
this.debouncedFetchAsyncOptions('', 1);
|
|
2380
|
+
}
|
|
2381
|
+
this.panelFocusEl = undefined;
|
|
2382
|
+
this.flyoutRoomChecked = false;
|
|
2383
|
+
this.flyoutFallback = false;
|
|
2384
|
+
}
|
|
1864
2385
|
if (isOpen && this.deferredPortalTeardownId !== undefined) {
|
|
1865
2386
|
clearTimeout(this.deferredPortalTeardownId);
|
|
1866
2387
|
this.deferredPortalTeardownId = undefined;
|
|
@@ -1893,17 +2414,52 @@ const PdsCombobox = class {
|
|
|
1893
2414
|
get usesBodyPortal() {
|
|
1894
2415
|
return this.dropdownMount === 'body';
|
|
1895
2416
|
}
|
|
2417
|
+
get labelId() {
|
|
2418
|
+
return `${this.componentId}-label`;
|
|
2419
|
+
}
|
|
2420
|
+
/** One check for "the `<label>` is rendered", so the label and the reference to it can't disagree. */
|
|
2421
|
+
get hasVisibleLabel() {
|
|
2422
|
+
return Boolean(this.label) && !this.hideLabel;
|
|
2423
|
+
}
|
|
2424
|
+
/**
|
|
2425
|
+
* The button and chip triggers are `div`s, which `<label for>` can't name, so they point at the
|
|
2426
|
+
* visible label instead. With `hide-label` there is no visible label and `aria-label` names them.
|
|
2427
|
+
* With panel search the trigger is a button, which has no value, so its own text (the selection
|
|
2428
|
+
* or placeholder) joins the label in its name.
|
|
2429
|
+
*/
|
|
2430
|
+
get triggerLabelledBy() {
|
|
2431
|
+
if (!this.hasVisibleLabel)
|
|
2432
|
+
return undefined;
|
|
2433
|
+
return this.usesPanelSearch ? `${this.labelId} ${this.componentId}` : this.labelId;
|
|
2434
|
+
}
|
|
2435
|
+
/** The div triggers' `aria-label` when the label is hidden; with panel search it names the selection too. */
|
|
2436
|
+
get triggerAriaLabel() {
|
|
2437
|
+
if (!this.hideLabel)
|
|
2438
|
+
return undefined;
|
|
2439
|
+
const shown = this.selectedLabel || this.placeholder;
|
|
2440
|
+
return this.usesPanelSearch && shown ? `${this.label}, ${shown}` : this.label;
|
|
2441
|
+
}
|
|
1896
2442
|
get listboxId() {
|
|
1897
2443
|
return `${this.componentId}-listbox`;
|
|
1898
2444
|
}
|
|
1899
2445
|
optionDomId(optionIndex) {
|
|
1900
2446
|
return `${this.componentId}-option-${optionIndex}`;
|
|
1901
2447
|
}
|
|
2448
|
+
groupDomId(optgroup) {
|
|
2449
|
+
let id = this.groupIds.get(optgroup);
|
|
2450
|
+
if (id === undefined) {
|
|
2451
|
+
id = `${this.componentId}-group-${this.groupIdCount++}`;
|
|
2452
|
+
this.groupIds.set(optgroup, id);
|
|
2453
|
+
}
|
|
2454
|
+
return id;
|
|
2455
|
+
}
|
|
1902
2456
|
setupDebounce() {
|
|
1903
2457
|
const { pdsComboboxSearch, debounce, originalSearchEmitter } = this;
|
|
1904
2458
|
this.pdsComboboxSearch = debounce === undefined
|
|
1905
2459
|
? originalSearchEmitter !== null && originalSearchEmitter !== void 0 ? originalSearchEmitter : pdsComboboxSearch
|
|
1906
2460
|
: debounceEvent(pdsComboboxSearch, debounce);
|
|
2461
|
+
// After the swap, so an emit made while flushing goes to the new emitter, not the old one.
|
|
2462
|
+
flushDebouncedEvent(pdsComboboxSearch);
|
|
1907
2463
|
}
|
|
1908
2464
|
optionsChanged() {
|
|
1909
2465
|
if (this.options) {
|
|
@@ -2050,6 +2606,8 @@ const PdsCombobox = class {
|
|
|
2050
2606
|
});
|
|
2051
2607
|
if (page === 1) {
|
|
2052
2608
|
this.internalOptions = formattedResults;
|
|
2609
|
+
// Only once its results have loaded: a failed or aborted fetch leaves the last query's.
|
|
2610
|
+
this.lastFetchedQuery = query;
|
|
2053
2611
|
}
|
|
2054
2612
|
else {
|
|
2055
2613
|
this.internalOptions = [...this.internalOptions, ...formattedResults];
|
|
@@ -2074,26 +2632,76 @@ const PdsCombobox = class {
|
|
|
2074
2632
|
}
|
|
2075
2633
|
}
|
|
2076
2634
|
updateOptionsFromAsync() {
|
|
2635
|
+
var _a;
|
|
2077
2636
|
if (!this.asyncUrl && !this.options)
|
|
2078
2637
|
return;
|
|
2079
2638
|
// Clear existing slot-based options when using async
|
|
2080
2639
|
this.optionEls = [];
|
|
2081
2640
|
this.allItems = [];
|
|
2082
|
-
// Create option elements from async data
|
|
2641
|
+
// Create option elements from async data. Grouped options are nested in an optgroup, as
|
|
2642
|
+
// slotted markup would be, so grouping, filtering and labels work the same either way. Each
|
|
2643
|
+
// group is listed where it first appears with all of its options, even when the data
|
|
2644
|
+
// interleaves groups, so an option never renders under another group's label. Ungrouped
|
|
2645
|
+
// options come first, so none reads as part of the group above it.
|
|
2083
2646
|
const asyncOptions = this.options || this.internalOptions;
|
|
2647
|
+
const groups = new Map();
|
|
2648
|
+
const ungrouped = [];
|
|
2649
|
+
const groupEntries = [];
|
|
2084
2650
|
asyncOptions.forEach(opt => {
|
|
2085
2651
|
const optionEl = document.createElement('option');
|
|
2086
2652
|
optionEl.value = String(opt.id);
|
|
2087
2653
|
optionEl.textContent = opt.text;
|
|
2088
|
-
|
|
2089
|
-
|
|
2654
|
+
if (opt.disabled === true)
|
|
2655
|
+
optionEl.setAttribute('disabled', '');
|
|
2656
|
+
// Only strings group an option or name an icon; anything else from JS is ignored, not coerced.
|
|
2657
|
+
if (typeof opt.group !== 'string' || opt.group === '') {
|
|
2658
|
+
ungrouped.push(optionEl);
|
|
2659
|
+
return;
|
|
2660
|
+
}
|
|
2661
|
+
let optgroup = groups.get(opt.group);
|
|
2662
|
+
if (!optgroup) {
|
|
2663
|
+
optgroup = document.createElement('optgroup');
|
|
2664
|
+
optgroup.label = opt.group;
|
|
2665
|
+
groups.set(opt.group, optgroup);
|
|
2666
|
+
groupEntries.push(optgroup);
|
|
2667
|
+
}
|
|
2668
|
+
if (!optgroup.hasAttribute('data-icon') && typeof opt.groupIcon === 'string' && opt.groupIcon !== '') {
|
|
2669
|
+
optgroup.setAttribute('data-icon', opt.groupIcon);
|
|
2670
|
+
}
|
|
2671
|
+
optgroup.appendChild(optionEl);
|
|
2672
|
+
});
|
|
2673
|
+
[...ungrouped, ...groupEntries].forEach(entry => {
|
|
2674
|
+
if (entry.tagName === 'OPTGROUP') {
|
|
2675
|
+
this.allItems.push(entry);
|
|
2676
|
+
Array.from(entry.children).forEach(child => {
|
|
2677
|
+
this.optionEls.push(child);
|
|
2678
|
+
this.allItems.push(child);
|
|
2679
|
+
});
|
|
2680
|
+
}
|
|
2681
|
+
else {
|
|
2682
|
+
this.optionEls.push(entry);
|
|
2683
|
+
this.allItems.push(entry);
|
|
2684
|
+
}
|
|
2090
2685
|
});
|
|
2091
|
-
//
|
|
2092
|
-
//
|
|
2093
|
-
|
|
2686
|
+
// A rebuild replaces every optgroup. Follow the open group to its new element by label, so the
|
|
2687
|
+
// flyout stays open across reloads and pagination, or close it if the group is gone. The hover
|
|
2688
|
+
// timers still hold the old element, so they're cleared either way. filterOptions, below,
|
|
2689
|
+
// resets the highlight.
|
|
2690
|
+
if (this.openGroup !== null && !groupEntries.includes(this.openGroup)) {
|
|
2691
|
+
this.flyout.reset();
|
|
2692
|
+
this.openGroup = (_a = groups.get(this.openGroup.label)) !== null && _a !== void 0 ? _a : null;
|
|
2693
|
+
}
|
|
2694
|
+
// Re-apply the selection to the rebuilt options: when `value` is set before async options have
|
|
2695
|
+
// loaded, and after any rebuild, which detaches the previously selected option element.
|
|
2696
|
+
if (this.value && (!this.selectedOption || !this.optionEls.includes(this.selectedOption))) {
|
|
2094
2697
|
const matchingOption = this.optionEls.find(opt => opt.value === this.value);
|
|
2095
2698
|
if (matchingOption) {
|
|
2699
|
+
// Relinking a selection keeps the same value, so it keeps any text being typed too, which
|
|
2700
|
+
// the selectedOption watcher would otherwise reset to the label.
|
|
2701
|
+
const typed = this.selectedOption ? this.displayText : undefined;
|
|
2096
2702
|
this.setSelectedOption(matchingOption);
|
|
2703
|
+
if (typed !== undefined)
|
|
2704
|
+
this.displayText = typed;
|
|
2097
2705
|
}
|
|
2098
2706
|
}
|
|
2099
2707
|
this.filterOptions();
|
|
@@ -2144,11 +2752,12 @@ const PdsCombobox = class {
|
|
|
2144
2752
|
}
|
|
2145
2753
|
}
|
|
2146
2754
|
// For chip triggers, ensure we always have a selected option
|
|
2147
|
-
|
|
2148
|
-
|
|
2755
|
+
const firstEnabled = this.optionEls.find(opt => !isOptionDisabled(opt));
|
|
2756
|
+
if (initialSelected === null && this.trigger === 'chip' && firstEnabled !== undefined) {
|
|
2757
|
+
initialSelected = firstEnabled;
|
|
2149
2758
|
this.value = initialSelected.value;
|
|
2150
2759
|
this.displayText = this.getOptionLabel(initialSelected);
|
|
2151
|
-
console.warn('PDS Combobox: Chip triggers should always have a selected option. Automatically selected the first option.');
|
|
2760
|
+
console.warn('PDS Combobox: Chip triggers should always have a selected option. Automatically selected the first enabled option.');
|
|
2152
2761
|
}
|
|
2153
2762
|
// Update selection if we found a different selected option or if we don't have one
|
|
2154
2763
|
if (initialSelected && initialSelected !== this.selectedOption) {
|
|
@@ -2236,16 +2845,26 @@ const PdsCombobox = class {
|
|
|
2236
2845
|
}
|
|
2237
2846
|
}
|
|
2238
2847
|
filterOptions() {
|
|
2848
|
+
// A new list replaces the rows a slide was animating, so its end event may never come.
|
|
2849
|
+
this.drillDirection = null;
|
|
2239
2850
|
// Ensure allItems includes optionEls if not already populated (for edge cases)
|
|
2240
2851
|
if (this.allItems.length === 0 && this.optionEls.length > 0) {
|
|
2241
2852
|
this.allItems = [...this.optionEls];
|
|
2242
2853
|
}
|
|
2243
|
-
|
|
2854
|
+
const searchesPanel = this.usesPanelSearch;
|
|
2855
|
+
if ((this.mode === 'select-only' && !searchesPanel) || this.expandFilterListWhileOpen || (searchesPanel && this.panelQuery === '')) {
|
|
2244
2856
|
this.filteredItems = [...this.allItems];
|
|
2245
2857
|
}
|
|
2246
2858
|
else {
|
|
2247
|
-
const val = this.displayText.toLowerCase();
|
|
2859
|
+
const val = (searchesPanel ? this.panelQuery : this.displayText).toLowerCase();
|
|
2248
2860
|
const filteredOptions = this.optionEls.filter(option => {
|
|
2861
|
+
// Outside inline mode a group's label is part of what search matches, so "tag" finds
|
|
2862
|
+
// every option in the Tag group.
|
|
2863
|
+
if (this.groupDisplay !== 'inline') {
|
|
2864
|
+
const groupLabel = groupLabelOf(option);
|
|
2865
|
+
if (groupLabel !== null && groupLabel.toLowerCase().includes(val))
|
|
2866
|
+
return true;
|
|
2867
|
+
}
|
|
2249
2868
|
// For layout options, search both text content and data-search-text attribute
|
|
2250
2869
|
if (this.isOptionLayout(option)) {
|
|
2251
2870
|
const searchText = option.getAttribute('data-search-text') || option.textContent || '';
|
|
@@ -2280,6 +2899,7 @@ const PdsCombobox = class {
|
|
|
2280
2899
|
});
|
|
2281
2900
|
}
|
|
2282
2901
|
this.highlightedIndex = -1;
|
|
2902
|
+
this.highlightedGroup = null;
|
|
2283
2903
|
}
|
|
2284
2904
|
clearExpandFilterList() {
|
|
2285
2905
|
this.expandFilterListWhileOpen = false;
|
|
@@ -2309,7 +2929,8 @@ const PdsCombobox = class {
|
|
|
2309
2929
|
this.listboxEl.style.width = this.dropdownWidth;
|
|
2310
2930
|
if (this.maxHeight) {
|
|
2311
2931
|
this.listboxEl.style.maxHeight = this.maxHeight;
|
|
2312
|
-
|
|
2932
|
+
// With panel search, the options list scrolls under a fixed search field.
|
|
2933
|
+
this.listboxEl.style.overflowY = this.usesPanelSearch ? 'hidden' : 'auto';
|
|
2313
2934
|
}
|
|
2314
2935
|
return computePosition(this.triggerEl, this.listboxEl, {
|
|
2315
2936
|
placement: this.dropdownPlacement,
|
|
@@ -2325,8 +2946,30 @@ const PdsCombobox = class {
|
|
|
2325
2946
|
position: strategy,
|
|
2326
2947
|
zIndex,
|
|
2327
2948
|
});
|
|
2949
|
+
this.checkFlyoutRoom();
|
|
2328
2950
|
});
|
|
2329
2951
|
}
|
|
2952
|
+
/**
|
|
2953
|
+
* Once per open, after the dropdown is placed: with no room for a flyout on either side of it,
|
|
2954
|
+
* `flyout` drills in instead. `flyout-min-width` is resolved through CSS, so any length works.
|
|
2955
|
+
*/
|
|
2956
|
+
checkFlyoutRoom() {
|
|
2957
|
+
if (!this.isOpen || this.groupDisplay !== 'flyout' || this.flyoutRoomChecked || !this.listboxEl)
|
|
2958
|
+
return;
|
|
2959
|
+
this.flyoutRoomChecked = true;
|
|
2960
|
+
const probe = document.createElement('div');
|
|
2961
|
+
// Fixed, like the flyout, so a percentage resolves against the viewport as the flyout's does.
|
|
2962
|
+
probe.style.cssText = 'position:fixed;visibility:hidden;width:0;';
|
|
2963
|
+
probe.style.minWidth = this.flyoutMinWidth;
|
|
2964
|
+
this.listboxEl.appendChild(probe);
|
|
2965
|
+
const needed = parseFloat(getComputedStyle(probe).minWidth);
|
|
2966
|
+
probe.remove();
|
|
2967
|
+
const rect = this.listboxEl.getBoundingClientRect();
|
|
2968
|
+
const room = Math.max(window.innerWidth - rect.right, rect.left);
|
|
2969
|
+
const fallback = Number.isFinite(needed) && needed > 0 && rect.width > 0 && room < needed;
|
|
2970
|
+
if (fallback !== this.flyoutFallback)
|
|
2971
|
+
this.flyoutFallback = fallback;
|
|
2972
|
+
}
|
|
2330
2973
|
openDropdownPositioning() {
|
|
2331
2974
|
if (!this.triggerEl || !this.listboxEl) {
|
|
2332
2975
|
return;
|
|
@@ -2429,6 +3072,130 @@ const PdsCombobox = class {
|
|
|
2429
3072
|
this.listboxEl = undefined;
|
|
2430
3073
|
}
|
|
2431
3074
|
}
|
|
3075
|
+
/**
|
|
3076
|
+
* The tree keys in the grouped panel. Up, Down, Home, End, PageUp and PageDown move within one
|
|
3077
|
+
* level; Right, Enter or Space opens a group at its first option; Left, or Escape, closes the
|
|
3078
|
+
* open group back to its row. Returns false for keys the listbox handling covers, such as
|
|
3079
|
+
* Enter on an option.
|
|
3080
|
+
*/
|
|
3081
|
+
handleGroupedPanelKey(e) {
|
|
3082
|
+
if (!this.showsGroupedPanel)
|
|
3083
|
+
return false;
|
|
3084
|
+
this.keyboardNavigating = true;
|
|
3085
|
+
// In the input trigger, Left and Right still move the caret through typed text, and Space,
|
|
3086
|
+
// Home and End edit it, as they do in the panel's search field.
|
|
3087
|
+
if (this.trigger === 'input') {
|
|
3088
|
+
if ((e.key === 'ArrowLeft' || e.key === 'ArrowRight') && this.displayText !== '')
|
|
3089
|
+
return false;
|
|
3090
|
+
if (e.key === ' ' || e.key === 'Home' || e.key === 'End')
|
|
3091
|
+
return false;
|
|
3092
|
+
}
|
|
3093
|
+
const entries = buildPanelEntries(this.filteredItems);
|
|
3094
|
+
const drilledIn = this.effectiveGroupDisplay === 'drill-in' && this.openGroup !== null;
|
|
3095
|
+
const current = this.currentPanelItem();
|
|
3096
|
+
const column = panelColumn(entries, this.openGroup, current, drilledIn);
|
|
3097
|
+
if (column.length === 0)
|
|
3098
|
+
return false;
|
|
3099
|
+
const position = current === null ? -1 : column.indexOf(current);
|
|
3100
|
+
const moveTo = (to) => {
|
|
3101
|
+
e.preventDefault();
|
|
3102
|
+
this.highlightPanelItem(column[Math.max(0, Math.min(column.length - 1, to))]);
|
|
3103
|
+
return true;
|
|
3104
|
+
};
|
|
3105
|
+
switch (e.key) {
|
|
3106
|
+
case 'ArrowDown':
|
|
3107
|
+
return moveTo(position < 0 ? 0 : position + 1);
|
|
3108
|
+
case 'ArrowUp':
|
|
3109
|
+
return moveTo(position < 0 ? column.length - 1 : position - 1);
|
|
3110
|
+
case 'Home':
|
|
3111
|
+
return moveTo(0);
|
|
3112
|
+
case 'End':
|
|
3113
|
+
return moveTo(column.length - 1);
|
|
3114
|
+
case 'PageDown':
|
|
3115
|
+
return moveTo(position < 0 ? 0 : position + 10);
|
|
3116
|
+
case 'PageUp':
|
|
3117
|
+
return moveTo(position < 0 ? column.length - 1 : position - 10);
|
|
3118
|
+
case 'ArrowRight':
|
|
3119
|
+
case 'Enter':
|
|
3120
|
+
case ' ': {
|
|
3121
|
+
if (current === null || typeof current === 'number')
|
|
3122
|
+
return false;
|
|
3123
|
+
e.preventDefault();
|
|
3124
|
+
if (!drilledIn || current !== this.openGroup) {
|
|
3125
|
+
this.expandGroup(entries, current);
|
|
3126
|
+
}
|
|
3127
|
+
else if (e.key === 'ArrowRight') {
|
|
3128
|
+
// On the row back of a drilled-in group: down into its options.
|
|
3129
|
+
if (column.length > 1)
|
|
3130
|
+
this.highlightPanelItem(column[1]);
|
|
3131
|
+
}
|
|
3132
|
+
else {
|
|
3133
|
+
this.leaveDrilledInGroup();
|
|
3134
|
+
}
|
|
3135
|
+
return true;
|
|
3136
|
+
}
|
|
3137
|
+
case 'ArrowLeft':
|
|
3138
|
+
case 'Escape': {
|
|
3139
|
+
// Escape with no group open closes the panel, through the listbox handling.
|
|
3140
|
+
if (this.openGroup === null)
|
|
3141
|
+
return false;
|
|
3142
|
+
e.preventDefault();
|
|
3143
|
+
this.collapseToGroup(this.openGroup);
|
|
3144
|
+
return true;
|
|
3145
|
+
}
|
|
3146
|
+
}
|
|
3147
|
+
return false;
|
|
3148
|
+
}
|
|
3149
|
+
/**
|
|
3150
|
+
* Where the keyboard is in the grouped panel. An option highlighted in a group that has since
|
|
3151
|
+
* closed (the pointer left its flyout) counts as its group's row, so the keys carry on from
|
|
3152
|
+
* what's showing rather than from an option that isn't.
|
|
3153
|
+
*/
|
|
3154
|
+
currentPanelItem() {
|
|
3155
|
+
if (this.highlightedIndex < 0)
|
|
3156
|
+
return this.highlightedGroup;
|
|
3157
|
+
const selectable = this.filteredItems.filter(item => item.tagName === 'OPTION');
|
|
3158
|
+
const group = parentOptgroupOf(selectable[this.highlightedIndex]);
|
|
3159
|
+
return group !== null && group !== this.openGroup ? group : this.highlightedIndex;
|
|
3160
|
+
}
|
|
3161
|
+
/**
|
|
3162
|
+
* Highlights the option at `index`, kept within the list. Disabled options can be highlighted,
|
|
3163
|
+
* so assistive tech announces them as unavailable, but not chosen.
|
|
3164
|
+
*/
|
|
3165
|
+
highlightOptionAt(options, index) {
|
|
3166
|
+
if (options.length === 0)
|
|
3167
|
+
return;
|
|
3168
|
+
this.highlightedIndex = Math.max(0, Math.min(options.length - 1, index));
|
|
3169
|
+
this.updateOptionFocus();
|
|
3170
|
+
}
|
|
3171
|
+
/** Highlights a group row or an option, opening or closing flyouts to match. */
|
|
3172
|
+
highlightPanelItem(item) {
|
|
3173
|
+
if (typeof item === 'number') {
|
|
3174
|
+
this.highlightedIndex = item;
|
|
3175
|
+
}
|
|
3176
|
+
else {
|
|
3177
|
+
this.highlightedIndex = -1;
|
|
3178
|
+
this.highlightedGroup = item;
|
|
3179
|
+
}
|
|
3180
|
+
this.updateOptionFocus();
|
|
3181
|
+
}
|
|
3182
|
+
expandGroup(entries, optgroup) {
|
|
3183
|
+
var _a;
|
|
3184
|
+
this.flyout.open(optgroup);
|
|
3185
|
+
const first = (_a = findGroup(entries, optgroup)) === null || _a === void 0 ? void 0 : _a.options[0];
|
|
3186
|
+
if (first !== undefined)
|
|
3187
|
+
this.highlightPanelItem(first.index);
|
|
3188
|
+
// Its options render after this change; scroll to the first one then.
|
|
3189
|
+
this.pendingOptionFocus = true;
|
|
3190
|
+
}
|
|
3191
|
+
/** Closes the open group and highlights its row, as a tree's Left does from a child. */
|
|
3192
|
+
collapseToGroup(optgroup) {
|
|
3193
|
+
this.flyout.reset();
|
|
3194
|
+
this.openGroup = null;
|
|
3195
|
+
this.highlightPanelItem(optgroup);
|
|
3196
|
+
// The row renders after this change (in drill-in it replaces the row back); scroll to it then.
|
|
3197
|
+
this.pendingOptionFocus = true;
|
|
3198
|
+
}
|
|
2432
3199
|
/**
|
|
2433
3200
|
* Sets focus on the native input element.
|
|
2434
3201
|
*/
|
|
@@ -2442,8 +3209,9 @@ const PdsCombobox = class {
|
|
|
2442
3209
|
}
|
|
2443
3210
|
}
|
|
2444
3211
|
/**
|
|
2445
|
-
* Sets the initial highlighted index when dropdown opens.
|
|
2446
|
-
*
|
|
3212
|
+
* Sets the initial highlighted index when dropdown opens. Highlights the selected option unless
|
|
3213
|
+
* it's disabled. Otherwise highlights the first enabled option, or, in the grouped panel, the
|
|
3214
|
+
* first row with something to choose, or nothing when every option is disabled.
|
|
2447
3215
|
*/
|
|
2448
3216
|
setInitialHighlightedIndex() {
|
|
2449
3217
|
const selectableOptions = this.filteredItems.filter(item => item.tagName === 'OPTION');
|
|
@@ -2451,16 +3219,33 @@ const PdsCombobox = class {
|
|
|
2451
3219
|
this.highlightedIndex = -1;
|
|
2452
3220
|
return;
|
|
2453
3221
|
}
|
|
2454
|
-
// If there's a selected option, find its index in the filtered options
|
|
2455
|
-
|
|
3222
|
+
// If there's a selected option, find its index in the filtered options. A disabled one can be
|
|
3223
|
+
// the value, as in a native select, but it isn't highlighted.
|
|
3224
|
+
if (this.selectedOption && !isOptionDisabled(this.selectedOption)) {
|
|
2456
3225
|
const selectedIndex = selectableOptions.findIndex(option => option === this.selectedOption);
|
|
2457
3226
|
if (selectedIndex >= 0) {
|
|
2458
3227
|
this.highlightedIndex = selectedIndex;
|
|
3228
|
+
// In the grouped panel, open on the selection's group, however the dropdown was opened, and
|
|
3229
|
+
// scroll the selection into view once its group has rendered.
|
|
3230
|
+
if (this.showsGroupedPanel) {
|
|
3231
|
+
this.openGroup = parentOptgroupOf(this.selectedOption);
|
|
3232
|
+
// Opening on the selection isn't drilling in, so it doesn't slide.
|
|
3233
|
+
this.drillDirection = null;
|
|
3234
|
+
this.pendingOptionFocus = true;
|
|
3235
|
+
}
|
|
2459
3236
|
return;
|
|
2460
3237
|
}
|
|
2461
3238
|
}
|
|
2462
|
-
//
|
|
2463
|
-
|
|
3239
|
+
// In the grouped panel, the first row with something to choose: a group stays closed until
|
|
3240
|
+
// it's opened.
|
|
3241
|
+
if (this.showsGroupedPanel) {
|
|
3242
|
+
const first = buildPanelEntries(this.filteredItems).find(entry => entry.kind === 'group' ? !isGroupDisabled(entry.group) : !isOptionDisabled(entry.option));
|
|
3243
|
+
this.highlightedIndex = (first === null || first === void 0 ? void 0 : first.kind) === 'option' ? first.index : -1;
|
|
3244
|
+
this.highlightedGroup = (first === null || first === void 0 ? void 0 : first.kind) === 'group' ? first.group.optgroup : null;
|
|
3245
|
+
return;
|
|
3246
|
+
}
|
|
3247
|
+
// No selected option or selected option not in filtered results, highlight the first enabled option
|
|
3248
|
+
this.highlightedIndex = selectableOptions.findIndex(option => !isOptionDisabled(option));
|
|
2464
3249
|
}
|
|
2465
3250
|
/**
|
|
2466
3251
|
* Focus management helper - moves focus to the first option when dropdown opens
|
|
@@ -2496,19 +3281,9 @@ const PdsCombobox = class {
|
|
|
2496
3281
|
const selectableOptions = this.filteredItems.filter(item => item.tagName === 'OPTION');
|
|
2497
3282
|
if (selectableOptions.length > 0) {
|
|
2498
3283
|
this.setInitialHighlightedIndex();
|
|
2499
|
-
|
|
2500
|
-
|
|
2501
|
-
|
|
2502
|
-
if (highlightedOption) {
|
|
2503
|
-
optionElements.forEach(option => {
|
|
2504
|
-
option.setAttribute('tabindex', '-1');
|
|
2505
|
-
});
|
|
2506
|
-
highlightedOption.setAttribute('tabindex', '0');
|
|
2507
|
-
highlightedOption.focus();
|
|
2508
|
-
highlightedOption.scrollIntoView({ block: 'nearest', behavior: 'smooth' });
|
|
2509
|
-
}
|
|
2510
|
-
}
|
|
2511
|
-
this.updateAriaActiveDescendant();
|
|
3284
|
+
// By index, through the same path as arrowing: it opens the option's flyout group first
|
|
3285
|
+
// when it isn't rendered, and highlights it once it is.
|
|
3286
|
+
this.updateOptionFocus();
|
|
2512
3287
|
}
|
|
2513
3288
|
}
|
|
2514
3289
|
/**
|
|
@@ -2516,14 +3291,58 @@ const PdsCombobox = class {
|
|
|
2516
3291
|
* Note: We don't actually focus the option to prevent focusout events that close the dropdown
|
|
2517
3292
|
*/
|
|
2518
3293
|
updateOptionFocus() {
|
|
2519
|
-
|
|
3294
|
+
var _a;
|
|
3295
|
+
if (this.listboxEl === undefined || this.listboxEl === null)
|
|
3296
|
+
return;
|
|
3297
|
+
// A row highlighted outright; an option highlighted in a closed group opens it below instead.
|
|
3298
|
+
const groupRow = this.showsGroupedPanel && this.highlightedIndex < 0 ? this.highlightedGroup : null;
|
|
3299
|
+
if (groupRow !== null) {
|
|
3300
|
+
// Arrowing onto another row closes a flyout that hover left open.
|
|
3301
|
+
if (this.effectiveGroupDisplay === 'flyout' && this.openGroup !== null && this.openGroup !== groupRow) {
|
|
3302
|
+
this.flyout.reset();
|
|
3303
|
+
this.openGroup = null;
|
|
3304
|
+
}
|
|
3305
|
+
// Matched by id, not a selector: componentId is consumer text and may not be selector-safe.
|
|
3306
|
+
const id = this.groupDomId(groupRow);
|
|
3307
|
+
(_a = Array.from(this.listboxEl.querySelectorAll('[role="treeitem"]'))
|
|
3308
|
+
.find(row => row.id === id)) === null || _a === void 0 ? void 0 : _a.scrollIntoView({ block: 'nearest' });
|
|
3309
|
+
this.updateAriaActiveDescendant();
|
|
2520
3310
|
return;
|
|
3311
|
+
}
|
|
3312
|
+
if (this.highlightedIndex < 0)
|
|
3313
|
+
return;
|
|
3314
|
+
// In the flyout panel only the open group's options are rendered: open the highlighted
|
|
3315
|
+
// option's group, and finish once it has rendered. Through the controller, so a hover timer
|
|
3316
|
+
// left running by the pointer can't close or switch the group the keys just moved into.
|
|
3317
|
+
if (this.showsGroupedPanel) {
|
|
3318
|
+
const selectable = this.filteredItems.filter(item => item.tagName === 'OPTION');
|
|
3319
|
+
const group = parentOptgroupOf(selectable[this.highlightedIndex]);
|
|
3320
|
+
const changed = group !== this.openGroup;
|
|
3321
|
+
if (group !== null) {
|
|
3322
|
+
this.flyout.open(group);
|
|
3323
|
+
}
|
|
3324
|
+
else {
|
|
3325
|
+
this.flyout.reset();
|
|
3326
|
+
this.openGroup = null;
|
|
3327
|
+
}
|
|
3328
|
+
if (changed) {
|
|
3329
|
+
this.pendingOptionFocus = true;
|
|
3330
|
+
return;
|
|
3331
|
+
}
|
|
3332
|
+
}
|
|
2521
3333
|
const optionElements = this.listboxEl.querySelectorAll('[role="option"]');
|
|
2522
|
-
|
|
3334
|
+
// By index, not position: the flyout panel renders only some options.
|
|
3335
|
+
const currentOption = this.listboxEl.querySelector(`[data-option-index="${this.highlightedIndex}"]`);
|
|
2523
3336
|
if (currentOption) {
|
|
2524
3337
|
// Check if any option currently has focus OR if we're in arrow-key navigation mode
|
|
2525
3338
|
const hasOptionFocus = Array.from(optionElements).some(el => el === document.activeElement);
|
|
2526
|
-
|
|
3339
|
+
// The panel's search field keeps focus and points at the option with aria-activedescendant,
|
|
3340
|
+
// and so does the trigger over the grouped panel, whose group rows can't take focus and
|
|
3341
|
+
// whose options are hidden while a flyout is placed.
|
|
3342
|
+
const shouldFocusOption = !this.usesBodyPortal &&
|
|
3343
|
+
!this.usesPanelSearch &&
|
|
3344
|
+
!this.showsGroupedPanel &&
|
|
3345
|
+
(hasOptionFocus || this.isArrowKeyNavigationMode);
|
|
2527
3346
|
if (shouldFocusOption) {
|
|
2528
3347
|
optionElements.forEach(option => {
|
|
2529
3348
|
option.setAttribute('tabindex', '-1');
|
|
@@ -2531,21 +3350,64 @@ const PdsCombobox = class {
|
|
|
2531
3350
|
currentOption.setAttribute('tabindex', '0');
|
|
2532
3351
|
currentOption.focus();
|
|
2533
3352
|
}
|
|
2534
|
-
// Always scroll the option into view
|
|
2535
|
-
currentOption.
|
|
3353
|
+
// Always scroll the option into view; in a flyout, by scrolling the flyout alone.
|
|
3354
|
+
const flyout = currentOption.closest('.pds-combobox__flyout');
|
|
3355
|
+
if (flyout) {
|
|
3356
|
+
this.flyout.reveal(flyout, currentOption);
|
|
3357
|
+
}
|
|
3358
|
+
else {
|
|
3359
|
+
currentOption.scrollIntoView({ block: 'nearest', behavior: 'smooth' });
|
|
3360
|
+
}
|
|
2536
3361
|
}
|
|
2537
3362
|
// Always update aria-activedescendant on the trigger element
|
|
2538
3363
|
this.updateAriaActiveDescendant();
|
|
2539
3364
|
}
|
|
3365
|
+
/** The highlighted group row in the grouped panel, or null while an option is highlighted. */
|
|
3366
|
+
get highlightedGroupRow() {
|
|
3367
|
+
if (!this.showsGroupedPanel)
|
|
3368
|
+
return null;
|
|
3369
|
+
if (this.highlightedIndex < 0)
|
|
3370
|
+
return this.highlightedGroup;
|
|
3371
|
+
// An option left highlighted in a flyout that has since closed shows as its group's row.
|
|
3372
|
+
const current = this.currentPanelItem();
|
|
3373
|
+
return typeof current === 'number' ? null : current;
|
|
3374
|
+
}
|
|
2540
3375
|
/**
|
|
2541
|
-
*
|
|
3376
|
+
* The id of the highlighted option or group row, only while it's rendered. In the flyout panel
|
|
3377
|
+
* an option in a closed group isn't in the DOM, and drilled into a group the other groups' rows
|
|
3378
|
+
* aren't; `aria-activedescendant` must not point at a missing element.
|
|
2542
3379
|
*/
|
|
3380
|
+
get activeDescendantId() {
|
|
3381
|
+
if (!this.isOpen)
|
|
3382
|
+
return undefined;
|
|
3383
|
+
const groupRow = this.highlightedGroupRow;
|
|
3384
|
+
if (groupRow !== null) {
|
|
3385
|
+
const drilledIntoAnother = this.effectiveGroupDisplay === 'drill-in' && this.openGroup !== null && this.openGroup !== groupRow;
|
|
3386
|
+
return drilledIntoAnother ? undefined : this.groupDomId(groupRow);
|
|
3387
|
+
}
|
|
3388
|
+
if (this.highlightedIndex < 0)
|
|
3389
|
+
return undefined;
|
|
3390
|
+
if (this.showsGroupedPanel) {
|
|
3391
|
+
const selectable = this.filteredItems.filter(item => item.tagName === 'OPTION');
|
|
3392
|
+
const group = parentOptgroupOf(selectable[this.highlightedIndex]);
|
|
3393
|
+
if (group !== null && group !== this.openGroup)
|
|
3394
|
+
return undefined;
|
|
3395
|
+
}
|
|
3396
|
+
return this.optionDomId(this.highlightedIndex);
|
|
3397
|
+
}
|
|
3398
|
+
/** Points the focused element's aria-activedescendant at the highlighted option, or clears it. */
|
|
2543
3399
|
updateAriaActiveDescendant() {
|
|
2544
|
-
|
|
2545
|
-
|
|
3400
|
+
// With panel search, the element with focus owns it, not the trigger: the search field, or
|
|
3401
|
+
// the list while a drilled-in group hides the field.
|
|
3402
|
+
const target = this.usesPanelSearch ? (this.hidesPanelSearch ? this.panelTreeEl : this.panelSearchEl) : this.triggerEl;
|
|
3403
|
+
if (!target)
|
|
3404
|
+
return;
|
|
3405
|
+
const id = this.activeDescendantId;
|
|
3406
|
+
if (id !== undefined) {
|
|
3407
|
+
target.setAttribute('aria-activedescendant', id);
|
|
2546
3408
|
}
|
|
2547
|
-
else
|
|
2548
|
-
|
|
3409
|
+
else {
|
|
3410
|
+
target.removeAttribute('aria-activedescendant');
|
|
2549
3411
|
}
|
|
2550
3412
|
}
|
|
2551
3413
|
/**
|
|
@@ -2581,6 +3443,17 @@ const PdsCombobox = class {
|
|
|
2581
3443
|
this.pdsComboboxChange.emit({ value: '' });
|
|
2582
3444
|
}
|
|
2583
3445
|
}
|
|
3446
|
+
// Group rows in the flyout panel carry their group's index, as options carry theirs.
|
|
3447
|
+
groupFromEvent(event) {
|
|
3448
|
+
var _a, _b;
|
|
3449
|
+
const index = Number(event.currentTarget.getAttribute('data-group-index'));
|
|
3450
|
+
return (_b = (_a = this.renderedGroups[index]) === null || _a === void 0 ? void 0 : _a.optgroup) !== null && _b !== void 0 ? _b : null;
|
|
3451
|
+
}
|
|
3452
|
+
highlightGroupRowByPointer(group) {
|
|
3453
|
+
this.highlightedIndex = -1;
|
|
3454
|
+
this.highlightedGroup = group;
|
|
3455
|
+
this.keyboardNavigating = false;
|
|
3456
|
+
}
|
|
2584
3457
|
// Get the label of the selected option
|
|
2585
3458
|
get selectedLabel() {
|
|
2586
3459
|
return this.displayText || '';
|
|
@@ -2693,7 +3566,24 @@ const PdsCombobox = class {
|
|
|
2693
3566
|
// Fallback: Use component props
|
|
2694
3567
|
return this.chipDot;
|
|
2695
3568
|
}
|
|
3569
|
+
/**
|
|
3570
|
+
* With `async-url`, fetches when the button trigger opens: the first page if nothing has loaded.
|
|
3571
|
+
* The panel's search field opens empty, so results left from the last search are refetched for
|
|
3572
|
+
* an empty query.
|
|
3573
|
+
*/
|
|
3574
|
+
fetchAsyncOptionsOnOpen() {
|
|
3575
|
+
if (!this.asyncUrl)
|
|
3576
|
+
return;
|
|
3577
|
+
if (this.usesPanelSearch && (this.internalOptions.length === 0 || this.lastFetchedQuery !== '')) {
|
|
3578
|
+
this.debouncedFetchAsyncOptions('', 1);
|
|
3579
|
+
}
|
|
3580
|
+
else if (this.internalOptions.length === 0) {
|
|
3581
|
+
this.debouncedFetchAsyncOptions(this.displayText, 1);
|
|
3582
|
+
}
|
|
3583
|
+
}
|
|
2696
3584
|
handleOptionClick(option) {
|
|
3585
|
+
if (isOptionDisabled(option))
|
|
3586
|
+
return;
|
|
2697
3587
|
// Update reactive state - single source of truth
|
|
2698
3588
|
// The @Watch('selectedOption') will handle displayText, value, and form internals
|
|
2699
3589
|
this.setSelectedOption(option);
|
|
@@ -2707,33 +3597,242 @@ const PdsCombobox = class {
|
|
|
2707
3597
|
}
|
|
2708
3598
|
const hasSlottedEmpty = !this.usesBodyPortal && !!this.el.querySelector('[slot="empty"]');
|
|
2709
3599
|
const hasSlottedLoading = !this.usesBodyPortal && !!this.el.querySelector('[slot="loading"]');
|
|
2710
|
-
let optionIndex = 0;
|
|
2711
3600
|
const selectableOptions = this.filteredItems.filter(item => item.tagName === 'OPTION');
|
|
2712
|
-
|
|
3601
|
+
const withSearch = this.usesPanelSearch;
|
|
3602
|
+
// While a drilled-in group hides the search field, the list takes focus in its place.
|
|
3603
|
+
const listTakesFocus = this.hidesPanelSearch;
|
|
3604
|
+
const list = (h("ul", { key: "panel-list", class: {
|
|
3605
|
+
'pds-combobox__listbox': !withSearch,
|
|
3606
|
+
'pds-combobox__listbox-options': withSearch,
|
|
3607
|
+
'pds-combobox__listbox-options--drilled-in': listTakesFocus,
|
|
3608
|
+
'pds-combobox__listbox--grouped': this.groupDisplay !== 'inline',
|
|
3609
|
+
'pds-combobox__listbox--drill-in': this.drillDirection === 'in',
|
|
3610
|
+
'pds-combobox__listbox--drill-out': this.drillDirection === 'out',
|
|
3611
|
+
}, onAnimationEnd: this.onDrillAnimationEnd, role: this.showsGroupedPanel ? 'tree' : 'listbox', id: this.listboxId, "aria-label": this.label || 'Options', "aria-multiselectable": "false",
|
|
3612
|
+
// Focusable but out of the tab order with panel search, so it can take focus when a
|
|
3613
|
+
// drilled-in group hides the field. Dropping it while focused would blur the list and close.
|
|
3614
|
+
tabIndex: withSearch ? -1 : undefined, "aria-activedescendant": listTakesFocus ? this.activeDescendantId : undefined, onKeyDown: withSearch ? this.onPanelTreeKeyDown : undefined, ref: el => {
|
|
3615
|
+
if (withSearch)
|
|
3616
|
+
this.panelTreeEl = el;
|
|
3617
|
+
else
|
|
3618
|
+
this.listboxEl = el;
|
|
3619
|
+
}, onScroll: this.handleScroll }, this.loading && (h("li", { class: "pds-combobox__loading", role: "presentation" }, hasSlottedLoading ? (h("slot", { name: "loading" })) : (h("pds-loader", { size: "small" })))), !this.loading && this.filteredItems.length === 0 && (h("li", { class: "pds-combobox__empty", role: "presentation" }, hasSlottedEmpty ? (h("slot", { name: "empty" })) : (h("span", null, "No options found")))), this.showsGroupedPanel ? this.renderGroupedPanel() : this.renderListboxItems(selectableOptions.length), this.hasMore && !this.loading && (h("li", { class: "pds-combobox__load-more", role: "presentation" }, h("pds-loader", { size: "small" })))));
|
|
3620
|
+
if (!withSearch)
|
|
3621
|
+
return list;
|
|
3622
|
+
// The search field sits above the list; the wrapper is what's positioned and portaled.
|
|
3623
|
+
return (h("div", { class: "pds-combobox__listbox pds-combobox__listbox--with-search", ref: el => (this.listboxEl = el), onMouseDown: this.onPanelMouseDown,
|
|
3624
|
+
// Portaled, the panel sits outside .pds-combobox, so its focusout wouldn't reach that handler.
|
|
3625
|
+
onFocusout: this.usesBodyPortal ? this.onComboboxFocusOut : undefined }, !listTakesFocus && this.renderPanelSearch(), list));
|
|
3626
|
+
}
|
|
3627
|
+
/**
|
|
3628
|
+
* The listbox's items. Each optgroup's options sit in a `group` named for it, as in
|
|
3629
|
+
* `pds-multiselect`, so assistive tech announces the group on entering it; a `pds-text` label
|
|
3630
|
+
* stays a caption above the options that follow it.
|
|
3631
|
+
*/
|
|
3632
|
+
renderListboxItems(setSize) {
|
|
3633
|
+
const rendered = [];
|
|
3634
|
+
let optionIndex = 0;
|
|
3635
|
+
let group = null;
|
|
3636
|
+
const closeGroup = () => {
|
|
3637
|
+
if (group === null)
|
|
3638
|
+
return;
|
|
3639
|
+
const { optgroup, key, options, members } = group;
|
|
3640
|
+
const groupIcon = groupIconOf(optgroup);
|
|
3641
|
+
// As in the grouped displays: disabled when there's nothing left in it to choose.
|
|
3642
|
+
const disabled = members.length > 0 && members.every(member => isOptionDisabled(member));
|
|
3643
|
+
rendered.push(h("li", { key: key, class: { 'pds-combobox__group': true, 'pds-combobox__group--disabled': disabled }, role: "group", "aria-label": optgroup.label, "aria-disabled": disabled ? 'true' : undefined }, h("div", { class: { 'pds-combobox__group-label': true, 'pds-combobox__group-label--with-icon': groupIcon !== null }, "aria-hidden": "true" }, groupIcon !== null && (
|
|
3644
|
+
// `name`, not `icon`: `icon` also loads URLs and data: SVGs, unsanitized.
|
|
3645
|
+
h("pds-icon", { name: groupIcon, size: "small", "aria-hidden": "true", class: "pds-combobox__group-icon" })), optgroup.label), h("ul", { class: "pds-combobox__group-list", role: "presentation" }, options)));
|
|
3646
|
+
group = null;
|
|
3647
|
+
};
|
|
3648
|
+
this.filteredItems.forEach((item, itemIdx) => {
|
|
2713
3649
|
if (item.tagName === 'OPTGROUP') {
|
|
2714
|
-
|
|
2715
|
-
|
|
3650
|
+
closeGroup();
|
|
3651
|
+
group = { optgroup: item, key: `optgroup-${itemIdx}`, options: [], members: [] };
|
|
2716
3652
|
}
|
|
2717
3653
|
else if (item.tagName === 'PDS-TEXT') {
|
|
2718
|
-
|
|
2719
|
-
|
|
3654
|
+
closeGroup();
|
|
3655
|
+
rendered.push(h("li", { key: `pds-text-${itemIdx}`, class: "pds-combobox__group-label", role: "presentation" }, item.textContent));
|
|
2720
3656
|
}
|
|
2721
3657
|
else if (item.tagName === 'OPTION') {
|
|
2722
3658
|
const option = item;
|
|
2723
|
-
|
|
2724
|
-
|
|
2725
|
-
const
|
|
2726
|
-
|
|
2727
|
-
|
|
2728
|
-
|
|
2729
|
-
|
|
2730
|
-
|
|
2731
|
-
|
|
2732
|
-
|
|
2733
|
-
|
|
3659
|
+
if (group !== null && parentOptgroupOf(option) !== group.optgroup)
|
|
3660
|
+
closeGroup();
|
|
3661
|
+
const rendering = this.renderOption(option, optionIndex, { posinset: optionIndex + 1, setsize: setSize });
|
|
3662
|
+
optionIndex++;
|
|
3663
|
+
if (group !== null) {
|
|
3664
|
+
group.options.push(rendering);
|
|
3665
|
+
group.members.push(option);
|
|
3666
|
+
}
|
|
3667
|
+
else {
|
|
3668
|
+
rendered.push(rendering);
|
|
3669
|
+
}
|
|
2734
3670
|
}
|
|
2735
|
-
|
|
2736
|
-
|
|
3671
|
+
});
|
|
3672
|
+
closeGroup();
|
|
3673
|
+
return rendered;
|
|
3674
|
+
}
|
|
3675
|
+
/** `panelSearch` applies to the triggers that can't be typed into. */
|
|
3676
|
+
get usesPanelSearch() {
|
|
3677
|
+
return this.panelSearch && this.trigger !== 'input';
|
|
3678
|
+
}
|
|
3679
|
+
/** `groupDisplay`, with `flyout` drilling in when there's no room beside the dropdown. */
|
|
3680
|
+
get effectiveGroupDisplay() {
|
|
3681
|
+
return this.groupDisplay === 'flyout' && this.flyoutFallback ? 'drill-in' : this.groupDisplay;
|
|
3682
|
+
}
|
|
3683
|
+
/**
|
|
3684
|
+
* The popup's role, for the triggers' `aria-haspopup`: a `tree` while the grouped panel shows
|
|
3685
|
+
* groups, and a `listbox` of options otherwise, search results included.
|
|
3686
|
+
*/
|
|
3687
|
+
get popupRole() {
|
|
3688
|
+
return this.showsGroupedPanel ? 'tree' : 'listbox';
|
|
3689
|
+
}
|
|
3690
|
+
/**
|
|
3691
|
+
* The input trigger's `aria-haspopup`. While closed it names what opening shows: the full list,
|
|
3692
|
+
* so the grouped panel in a grouped display, even though the input still holds the selection's
|
|
3693
|
+
* label.
|
|
3694
|
+
*/
|
|
3695
|
+
get inputPopupRole() {
|
|
3696
|
+
if (this.isOpen)
|
|
3697
|
+
return this.popupRole;
|
|
3698
|
+
return this.effectiveGroupDisplay === 'inline' ? 'listbox' : 'tree';
|
|
3699
|
+
}
|
|
3700
|
+
/**
|
|
3701
|
+
* The button and chip triggers' `aria-haspopup`. With panel search the trigger opens the panel,
|
|
3702
|
+
* which starts as a tree in a grouped display, so typing in the panel doesn't change it.
|
|
3703
|
+
*/
|
|
3704
|
+
get triggerPopupRole() {
|
|
3705
|
+
if (!this.usesPanelSearch)
|
|
3706
|
+
return this.popupRole;
|
|
3707
|
+
return this.groupDisplay === 'inline' ? 'listbox' : 'tree';
|
|
3708
|
+
}
|
|
3709
|
+
/**
|
|
3710
|
+
* Drilled into a group with panel search: the group's row back takes the search field's place,
|
|
3711
|
+
* since one group's options don't need searching. Typing searches the whole list again.
|
|
3712
|
+
*/
|
|
3713
|
+
get hidesPanelSearch() {
|
|
3714
|
+
return this.usesPanelSearch && this.showsGroupedPanel && this.effectiveGroupDisplay === 'drill-in' && this.openGroup !== null;
|
|
3715
|
+
}
|
|
3716
|
+
/** The grouped panel is showing groups rather than search results. */
|
|
3717
|
+
get showsGroupedPanel() {
|
|
3718
|
+
if (this.effectiveGroupDisplay === 'inline')
|
|
3719
|
+
return false;
|
|
3720
|
+
const searching = this.usesPanelSearch
|
|
3721
|
+
? this.panelQuery !== ''
|
|
3722
|
+
: this.mode === 'filter' && !this.expandFilterListWhileOpen && this.displayText !== '';
|
|
3723
|
+
return !searching;
|
|
3724
|
+
}
|
|
3725
|
+
setPanelQuery(query) {
|
|
3726
|
+
this.panelQuery = query;
|
|
3727
|
+
this.clearExpandFilterList();
|
|
3728
|
+
this.filterOptions();
|
|
3729
|
+
this.pdsComboboxSearch.emit({ query: this.panelQuery });
|
|
3730
|
+
if (this.asyncUrl !== undefined && this.asyncUrl !== '') {
|
|
3731
|
+
this.debouncedFetchAsyncOptions(this.panelQuery, 1);
|
|
3732
|
+
}
|
|
3733
|
+
// The list changes size, so place the dropdown again, as typing in the input trigger does.
|
|
3734
|
+
setTimeout(() => this.openDropdownPositioning(), 0);
|
|
3735
|
+
}
|
|
3736
|
+
/** What's being searched: the panel's field, or the input trigger's text. */
|
|
3737
|
+
get activeQuery() {
|
|
3738
|
+
return this.usesPanelSearch ? this.panelQuery : this.displayText;
|
|
3739
|
+
}
|
|
3740
|
+
// Tab closes the dropdown and lands on the trigger, as Escape does: the focused field or list is
|
|
3741
|
+
// about to unmount, so the browser can't tab on from it. The next Tab continues from the trigger.
|
|
3742
|
+
handlePanelTab(event) {
|
|
3743
|
+
if (event.key !== 'Tab')
|
|
3744
|
+
return false;
|
|
3745
|
+
event.preventDefault();
|
|
3746
|
+
this.handleKeyDown(event);
|
|
3747
|
+
this.restoreFocusToTrigger();
|
|
3748
|
+
return true;
|
|
3749
|
+
}
|
|
3750
|
+
/** Returns from a drilled-in group to the group list; false when not drilled in. */
|
|
3751
|
+
leaveDrilledInGroup() {
|
|
3752
|
+
if (!this.showsGroupedPanel || this.effectiveGroupDisplay !== 'drill-in' || this.openGroup === null)
|
|
3753
|
+
return false;
|
|
3754
|
+
this.collapseToGroup(this.openGroup);
|
|
3755
|
+
return true;
|
|
3756
|
+
}
|
|
3757
|
+
renderPanelSearch() {
|
|
3758
|
+
return (h("div", { key: "panel-search", class: "pds-combobox__panel-search" }, h("pds-icon", { name: "search", size: "small", "aria-hidden": "true" }), h("input", { ref: el => (this.panelSearchEl = el), type: "text", class: "pds-combobox__panel-search-input", placeholder: this.searchPlaceholder, value: this.panelQuery, role: "combobox", "aria-label": this.searchOptionsLabel, "aria-haspopup": this.popupRole, "aria-controls": this.listboxId, "aria-autocomplete": "list", "aria-expanded": "true", "aria-activedescendant": this.activeDescendantId, autocomplete: "off", onInput: this.onPanelSearchInput, onKeyDown: this.onPanelSearchKeyDown })));
|
|
3759
|
+
}
|
|
3760
|
+
/**
|
|
3761
|
+
* An option, as a listbox `option` or, given a tree `level`, a `treeitem`. `posinset` and
|
|
3762
|
+
* `setsize` place it among its siblings.
|
|
3763
|
+
*/
|
|
3764
|
+
renderOption(option, index, { posinset, setsize, level }) {
|
|
3765
|
+
const isSelected = this.isOptionSelected(option);
|
|
3766
|
+
const isHighlighted = this.highlightedIndex === index;
|
|
3767
|
+
const isLayout = this.isOptionLayout(option);
|
|
3768
|
+
const isChip = this.isOptionChip(option);
|
|
3769
|
+
const isDisabled = isOptionDisabled(option);
|
|
3770
|
+
const tree = level !== undefined;
|
|
3771
|
+
return (h("li", { key: option.value, id: this.optionDomId(index), role: tree ? 'treeitem' : 'option', "aria-selected": isSelected ? 'true' : tree ? undefined : 'false', "aria-disabled": isDisabled ? 'true' : undefined, "aria-level": level, "aria-setsize": setsize, "aria-posinset": posinset, "aria-label": isLayout || isChip ? option.getAttribute('aria-label') || this.getOptionLabel(option) : undefined, tabindex: this.usesBodyPortal || this.usesPanelSearch || tree ? '-1' : isHighlighted ? '0' : '-1', class: {
|
|
3772
|
+
'pds-combobox__option': true,
|
|
3773
|
+
'pds-combobox__option--highlighted': isHighlighted,
|
|
3774
|
+
'pds-combobox__option--layout': isLayout,
|
|
3775
|
+
'pds-combobox__option--chip': isChip,
|
|
3776
|
+
'pds-combobox__option--disabled': isDisabled,
|
|
3777
|
+
}, "data-option-index": index, onMouseDown: this.onOptionMouseDown, onClick: this.onOptionClick, onMouseEnter: this.onOptionMouseEnter, onKeyDown: this.onOptionKeyDown }, isLayout ? (h("pds-box", { class: "pds-combobox__option-layout-wrapper", innerHTML: this.getOptionLayoutContent(option) })) : isChip ? (this.renderOptionChip(option)) : (this.getOptionLabel(option)), isSelected && h("pds-icon", { icon: "check", size: "regular", class: "pds-combobox__option-check" })));
|
|
3778
|
+
}
|
|
3779
|
+
/**
|
|
3780
|
+
* `flyout`: one row per group, its options in a flyout beside it. `drill-in`: the same rows, and
|
|
3781
|
+
* an opened group replaces them with its row, drawn as a row back, above its options. Either way
|
|
3782
|
+
* it's a tree: the rows and ungrouped options are level 1, a group's options level 2.
|
|
3783
|
+
*/
|
|
3784
|
+
renderGroupedPanel() {
|
|
3785
|
+
const entries = buildPanelEntries(this.filteredItems);
|
|
3786
|
+
const setsize = entries.length;
|
|
3787
|
+
if (this.effectiveGroupDisplay === 'drill-in' && this.openGroup !== null) {
|
|
3788
|
+
const position = entries.findIndex(entry => entry.kind === 'group' && entry.group.optgroup === this.openGroup);
|
|
3789
|
+
const open = entries[position];
|
|
3790
|
+
if ((open === null || open === void 0 ? void 0 : open.kind) === 'group')
|
|
3791
|
+
return this.renderGroupBackRow(open.group, { posinset: position + 1, setsize });
|
|
3792
|
+
}
|
|
3793
|
+
this.renderedGroups = [];
|
|
3794
|
+
return entries.map((entry, position) => {
|
|
3795
|
+
const placement = { posinset: position + 1, setsize };
|
|
3796
|
+
if (entry.kind === 'option')
|
|
3797
|
+
return this.renderOption(entry.option, entry.index, Object.assign(Object.assign({}, placement), { level: 1 }));
|
|
3798
|
+
this.renderedGroups.push(entry.group);
|
|
3799
|
+
return this.renderGroupRow(entry.group, this.renderedGroups.length - 1, placement);
|
|
3800
|
+
});
|
|
3801
|
+
}
|
|
3802
|
+
/** A group's options, as its children in the tree. */
|
|
3803
|
+
renderGroupOptions(group) {
|
|
3804
|
+
return group.options.map(({ option, index }, position) => this.renderOption(option, index, { posinset: position + 1, setsize: group.options.length, level: 2 }));
|
|
3805
|
+
}
|
|
3806
|
+
/**
|
|
3807
|
+
* Drilled into a group: its treeitem, expanded. Its row reads as a way back ("Back: Tag") and
|
|
3808
|
+
* leads its options.
|
|
3809
|
+
*/
|
|
3810
|
+
renderGroupBackRow(group, { posinset, setsize }) {
|
|
3811
|
+
const id = this.groupDomId(group.optgroup);
|
|
3812
|
+
const disabled = isGroupDisabled(group);
|
|
3813
|
+
return (h("li", { key: "group-back", id: id, class: {
|
|
3814
|
+
'pds-combobox__group-back': true,
|
|
3815
|
+
'pds-combobox__group-back--disabled': disabled,
|
|
3816
|
+
'pds-combobox__group-back--highlighted': this.highlightedGroupRow === group.optgroup,
|
|
3817
|
+
'pds-combobox__group-back--keyboard': this.keyboardNavigating && this.highlightedGroupRow === group.optgroup,
|
|
3818
|
+
}, role: "treeitem", "aria-expanded": "true", "aria-disabled": disabled ? 'true' : undefined, "aria-level": 1, "aria-posinset": posinset, "aria-setsize": setsize, "aria-labelledby": `${id}-label` }, h("div", { class: "pds-combobox__group-row-trigger pds-combobox__group-back-trigger", onMouseDown: this.onOptionMouseDown, onMouseEnter: this.onGroupBackMouseEnter, onClick: this.onGroupBackClick }, h("span", { class: "pds-combobox__group-row-label", id: `${id}-label` }, h("pds-icon", { name: "caret-left", size: "regular", "aria-hidden": "true", class: "pds-combobox__group-row-caret" }), h("span", { class: "visually-hidden" }, this.drillInBackLabel, ": "), group.label)), h("ul", { class: "pds-combobox__drill-in-options", role: "group", "aria-label": group.label }, this.renderGroupOptions(group))));
|
|
3819
|
+
}
|
|
3820
|
+
renderGroupRow(group, groupIndex, { posinset, setsize }) {
|
|
3821
|
+
const flyout = this.effectiveGroupDisplay === 'flyout';
|
|
3822
|
+
const isOpen = flyout && this.openGroup === group.optgroup;
|
|
3823
|
+
const hasSelection = group.options.some(({ option }) => this.isOptionSelected(option));
|
|
3824
|
+
const disabled = isGroupDisabled(group);
|
|
3825
|
+
const id = this.groupDomId(group.optgroup);
|
|
3826
|
+
return (h("li", { key: `group-${groupIndex}`, id: id, class: {
|
|
3827
|
+
'pds-combobox__group-row': true,
|
|
3828
|
+
'pds-combobox__group-row--open': isOpen,
|
|
3829
|
+
'pds-combobox__group-row--has-selection': hasSelection,
|
|
3830
|
+
'pds-combobox__group-row--highlighted': this.highlightedGroupRow === group.optgroup,
|
|
3831
|
+
'pds-combobox__group-row--keyboard': this.keyboardNavigating && this.highlightedGroupRow === group.optgroup,
|
|
3832
|
+
'pds-combobox__group-row--disabled': disabled,
|
|
3833
|
+
}, role: "treeitem", "aria-expanded": isOpen ? 'true' : 'false', "aria-disabled": disabled ? 'true' : undefined, "aria-level": 1, "aria-posinset": posinset, "aria-setsize": setsize, "aria-labelledby": `${id}-label`, "data-group-index": groupIndex, onMouseEnter: flyout ? this.onGroupRowMouseEnter : undefined, onMouseLeave: flyout ? this.onGroupRowMouseLeave : undefined }, h("div", { class: "pds-combobox__group-row-trigger", "data-group-index": groupIndex, onMouseDown: this.onOptionMouseDown, onMouseEnter: this.onGroupRowTriggerMouseEnter, onClick: this.onGroupRowClick }, h("span", { class: "pds-combobox__group-row-label", id: `${id}-label` }, group.icon !== null && (
|
|
3834
|
+
// `name`, not `icon`: `icon` also loads URLs and data: SVGs, unsanitized.
|
|
3835
|
+
h("pds-icon", { name: group.icon, size: "regular", "aria-hidden": "true", class: "pds-combobox__group-icon" })), group.label), h("pds-icon", { name: "caret-right", size: "regular", "aria-hidden": "true", class: "pds-combobox__group-row-caret" })), isOpen && (h("ul", { class: "pds-combobox__flyout", role: "group", "aria-label": group.label, style: { minWidth: this.flyoutMinWidth, maxWidth: this.flyoutMaxWidth } }, this.renderGroupOptions(group)))));
|
|
2737
3836
|
}
|
|
2738
3837
|
// Helper method to render the caret icon
|
|
2739
3838
|
renderCaretIcon() {
|
|
@@ -2870,17 +3969,26 @@ const PdsCombobox = class {
|
|
|
2870
3969
|
]
|
|
2871
3970
|
.filter(Boolean)
|
|
2872
3971
|
.join(' ');
|
|
2873
|
-
return (h(Host, { key: '
|
|
3972
|
+
return (h(Host, { key: 'd709320411c4d1706133376ea716756c3e1c1471', "aria-disabled": this.disabled ? 'true' : null }, h("div", { key: '455a02fa764524c95fe0bbfd024eba7134b3ac34', class: "pds-combobox", tabIndex: -1, onFocusout: this.onComboboxFocusOut, part: "combobox" }, this.hasVisibleLabel && (h("label", { key: '0d243157491934d823156841e97bfd369e12c2d5', htmlFor: this.trigger === 'input' ? this.componentId : undefined, id: this.labelId, class: "pds-combobox__label", onClick: this.onLabelClick }, this.label)), this.trigger === 'input' ? (h("div", { class: "pds-combobox__input-wrapper", style: { width: this.triggerWidth } }, h("input", { ref: el => {
|
|
2874
3973
|
this.inputEl = el;
|
|
2875
3974
|
this.triggerEl = el;
|
|
2876
3975
|
}, class: {
|
|
2877
3976
|
'pds-combobox__input': true,
|
|
2878
3977
|
'pds-combobox__input--invalid': this.isInvalid(),
|
|
2879
|
-
}, type: "text", role: "combobox", "aria-autocomplete": "list", "aria-controls": this.listboxId, "aria-describedby": assignDescription(this.componentId, this.isInvalid(), this.helperMessage, this.errorMessage), "aria-invalid": this.isInvalid() ? 'true' : undefined, "aria-activedescendant": this.
|
|
3978
|
+
}, type: "text", role: "combobox", "aria-autocomplete": "list", "aria-haspopup": this.inputPopupRole === 'tree' ? 'tree' : undefined, "aria-controls": this.listboxId, "aria-describedby": assignDescription(this.componentId, this.isInvalid(), this.helperMessage, this.errorMessage), "aria-invalid": this.isInvalid() ? 'true' : undefined, "aria-activedescendant": this.usesPanelSearch ? undefined : this.activeDescendantId, "aria-expanded": this.isOpen ? 'true' : 'false', "aria-disabled": this.disabled ? 'true' : 'false', "aria-label": this.hideLabel ? this.label : undefined, id: this.componentId, value: this.displayText, placeholder: this.placeholder, disabled: this.disabled, onInput: this.handleInput, onClick: this.handleInputClick, onKeyDown: this.handleKeyDown, autocomplete: "off", part: "input" }), h("pds-icon", { icon: "enlarge", "aria-hidden": "true", class: "pds-combobox__input-icon" }))) : this.trigger === 'chip' ? (h("div", { class: this.getChipTriggerClass(), style: { width: this.triggerWidth }, role: this.usesPanelSearch ? 'button' : 'combobox', "aria-haspopup": this.triggerPopupRole, "aria-controls": this.listboxId, "aria-describedby": assignDescription(this.componentId, this.isInvalid(), this.helperMessage, this.errorMessage), "aria-invalid": this.isInvalid() ? 'true' : undefined, "aria-activedescendant": this.usesPanelSearch ? undefined : this.activeDescendantId, "aria-expanded": this.isOpen ? 'true' : 'false', "aria-disabled": this.disabled ? 'true' : 'false', "aria-label": this.triggerAriaLabel, "aria-labelledby": this.triggerLabelledBy, id: this.componentId, tabIndex: this.disabled ? -1 : 0, onClick: this.onButtonTriggerClick, "data-layout": this.customTriggerContent, onKeyDown: this.onButtonTriggerKeyDown, onKeyUp: this.onButtonTriggerKeyUp, ref: el => (this.triggerEl = el), part: "chip-trigger" }, this.renderChipTriggerContent())) : (h("div", { class: triggerClass, style: { width: this.triggerWidth }, role: this.usesPanelSearch ? 'button' : 'combobox', "aria-haspopup": this.triggerPopupRole, "aria-controls": this.listboxId, "aria-describedby": assignDescription(this.componentId, this.isInvalid(), this.helperMessage, this.errorMessage), "aria-invalid": this.isInvalid() ? 'true' : undefined, "aria-activedescendant": this.usesPanelSearch ? undefined : this.activeDescendantId, "aria-expanded": this.isOpen ? 'true' : 'false', "aria-disabled": this.disabled ? 'true' : 'false', "aria-label": this.triggerAriaLabel, "aria-labelledby": this.triggerLabelledBy, id: this.componentId, tabIndex: this.disabled ? -1 : 0, onClick: this.onButtonTriggerClick, "data-layout": this.customTriggerContent, onKeyDown: this.onButtonTriggerKeyDown, onKeyUp: this.onButtonTriggerKeyUp, ref: el => (this.triggerEl = el), part: "button-trigger" }, this.renderButtonTriggerContent())), this.renderMessages(), h("div", { key: 'fd1eb34561f56df05e2f44c7acecde0e56b5e714', style: { display: 'none' } }, h("slot", { key: '68e11626a00175d0926c54086ae815be157e6bf0', onSlotchange: () => this.updateOptions() })), this.renderDropdown(), this.groupDisplay !== 'inline' && (h("span", { key: '6f3c60c3400d411abbed08ddc6e596db097bb097', class: "visually-hidden", role: "status", "aria-live": "polite" }, this.isOpen && this.effectiveGroupDisplay === 'drill-in' && this.openGroup !== null ? this.openGroup.label : '')))));
|
|
2880
3979
|
}
|
|
2881
3980
|
static get formAssociated() { return true; }
|
|
2882
3981
|
get el() { return getElement(this); }
|
|
2883
3982
|
static get watchers() { return {
|
|
3983
|
+
"groupDisplay": [{
|
|
3984
|
+
"groupDisplayChanged": 0
|
|
3985
|
+
}],
|
|
3986
|
+
"openGroup": [{
|
|
3987
|
+
"openGroupChanged": 0
|
|
3988
|
+
}],
|
|
3989
|
+
"flyoutFallback": [{
|
|
3990
|
+
"flyoutFallbackChanged": 0
|
|
3991
|
+
}],
|
|
2884
3992
|
"isOpen": [{
|
|
2885
3993
|
"isOpenChanged": 0
|
|
2886
3994
|
}],
|