@pine-ds/core 4.3.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-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-CaLa1zy9.js → index-Bl5KnQay.js} +4 -1
- package/dist/cjs/{index-DYvijwA6.js → index-D-QQKB0y.js} +8 -0
- 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 +53 -4
- package/dist/cjs/pds-checkbox.cjs.entry.js +14 -6
- package/dist/cjs/pds-chip.cjs.entry.js +6 -6
- 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 +1 -1
- 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 +12 -6
- 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 +3 -3
- 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 +5 -5
- 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-KWALOgy9.js → utils-BhRmyxT8.js} +35 -4
- package/dist/collection/collection-manifest.json +1 -0
- package/dist/collection/components/pds-button/pds-button.js +53 -2
- package/dist/collection/components/pds-checkbox/pds-checkbox.css +7 -0
- package/dist/collection/components/pds-checkbox/pds-checkbox.js +19 -3
- package/dist/collection/components/pds-chip/pds-chip.js +1 -1
- package/dist/collection/components/pds-combobox/grouped-options-panel.js +262 -0
- package/dist/collection/components/pds-combobox/pds-combobox.css +242 -13
- package/dist/collection/components/pds-combobox/pds-combobox.js +1128 -114
- 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 +16 -0
- package/dist/collection/components/pds-modal/pds-modal.js +10 -4
- 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 +1 -1
- package/dist/collection/components/pds-property/pds-property.js +1 -1
- 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 +33 -4
- package/dist/docs.json +1933 -59
- 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-DcT8--Dn.js → index-CB8Yh0Nt.js} +4 -1
- package/dist/esm/{index-BU1hN5Vy.js → index-DxI-61GK.js} +5 -1
- 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 +53 -4
- package/dist/esm/pds-checkbox.entry.js +14 -6
- package/dist/esm/pds-chip.entry.js +6 -6
- 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 +1 -1
- 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 +12 -6
- 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 +3 -3
- 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 +5 -5
- 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-u_0lxWnH.js → utils-OYK5-nwe.js} +34 -5
- 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-cfcb89d1.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-d70aa0c7.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-99f300ef.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-f682f08a.system.entry.js → p-1057b8c3.system.entry.js} +1 -1
- package/dist/pine-core/{p-089606b8.system.entry.js → p-108c910a.system.entry.js} +1 -1
- package/dist/pine-core/{p-ea986474.system.entry.js → p-166f61a6.system.entry.js} +1 -1
- package/dist/pine-core/{p-95defb53.entry.js → p-16c8f5e3.entry.js} +1 -1
- package/dist/pine-core/p-16e258d1.entry.js +1 -0
- package/dist/pine-core/{p-a8f1a48d.entry.js → p-1be33c95.entry.js} +1 -1
- package/dist/pine-core/{p-70fb83d4.entry.js → p-1e3a31da.entry.js} +1 -1
- package/dist/pine-core/{p-12941e0d.entry.js → p-1f228db9.entry.js} +1 -1
- 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-4ebdb90b.system.entry.js → p-33c63be6.system.entry.js} +1 -1
- package/dist/pine-core/{p-c5b6b545.entry.js → p-344609f9.entry.js} +2 -2
- package/dist/pine-core/{p-2dbc90ba.entry.js → p-3a1711c1.entry.js} +1 -1
- package/dist/pine-core/p-3a9c58bd.system.entry.js +1 -0
- package/dist/pine-core/{p-32fc82c2.entry.js → p-3ebd543f.entry.js} +1 -1
- package/dist/pine-core/p-3fbcb0c8.system.entry.js +1 -0
- package/dist/pine-core/{p-e08e4ca7.entry.js → p-427b4aeb.entry.js} +1 -1
- package/dist/pine-core/{p-f5cf98be.system.entry.js → p-42bd87ea.system.entry.js} +1 -1
- package/dist/pine-core/{p-8d1e7b3c.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-b9a857fc.system.entry.js → p-4b8cf04a.system.entry.js} +1 -1
- package/dist/pine-core/p-4d6f471c.entry.js +1 -0
- package/dist/pine-core/{p-ec04d4c3.entry.js → p-4e7580c4.entry.js} +1 -1
- package/dist/pine-core/{p-fbb72e66.system.entry.js → p-4f4a2d2a.system.entry.js} +1 -1
- package/dist/pine-core/{p-b8a5597d.entry.js → p-5211aba7.entry.js} +1 -1
- package/dist/pine-core/{p-7e4729e0.entry.js → p-524b7d3f.entry.js} +1 -1
- package/dist/pine-core/{p-c08b1697.entry.js → p-5613c64c.entry.js} +1 -1
- package/dist/pine-core/{p-5a8345e2.entry.js → p-5bb24cb4.entry.js} +1 -1
- package/dist/pine-core/{p-73c3a73f.entry.js → p-5bb80b3c.entry.js} +1 -1
- package/dist/pine-core/{p-e039ebb6.system.entry.js → p-5c6e0a26.system.entry.js} +1 -1
- package/dist/pine-core/{p-b53d9620.system.entry.js → p-5db57551.system.entry.js} +1 -1
- package/dist/pine-core/{p-6b260a97.entry.js → p-5eb00ba5.entry.js} +1 -1
- package/dist/pine-core/p-61756414.system.entry.js +1 -0
- package/dist/pine-core/{p-08196d6c.entry.js → p-682e9e8f.entry.js} +1 -1
- package/dist/pine-core/p-6965db1d.entry.js +1 -0
- package/dist/pine-core/{p-317337e4.entry.js → p-6b180ee2.entry.js} +1 -1
- package/dist/pine-core/{p-d33d65f6.entry.js → p-6c53962f.entry.js} +1 -1
- package/dist/pine-core/p-6da6520b.system.entry.js +3 -0
- package/dist/pine-core/{p-bd9b2931.system.entry.js → p-6e3bf862.system.entry.js} +1 -1
- package/dist/pine-core/{p-9d77f2f8.system.entry.js → p-71c9f866.system.entry.js} +1 -1
- package/dist/pine-core/{p-a616385b.system.entry.js → p-7265b94c.system.entry.js} +1 -1
- package/dist/pine-core/{p-55532d56.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-3b555f06.system.entry.js → p-79aa5f43.system.entry.js} +1 -1
- package/dist/pine-core/{p-77082557.system.entry.js → p-7bbcda0f.system.entry.js} +1 -1
- 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-93c52e2b.system.entry.js → p-8252cd84.system.entry.js} +1 -1
- package/dist/pine-core/p-84ba0e6a.system.entry.js +1 -0
- package/dist/pine-core/{p-45d55983.entry.js → p-86fc0bfa.entry.js} +1 -1
- package/dist/pine-core/p-90692bb6.entry.js +1 -0
- package/dist/pine-core/{p-67fc26e5.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-35edd8b0.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-b0becff3.system.entry.js → p-a85535a4.system.entry.js} +1 -1
- 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-5f5339ab.entry.js → p-b0526f98.entry.js} +1 -1
- package/dist/pine-core/p-b130b716.entry.js +1 -0
- package/dist/pine-core/{p-4cbb691f.entry.js → p-b195d345.entry.js} +1 -1
- package/dist/pine-core/{p-5c5bd609.entry.js → p-b4923acf.entry.js} +1 -1
- package/dist/pine-core/{p-15a0fa0a.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-bf025e38.entry.js → p-b8ada1eb.entry.js} +1 -1
- package/dist/pine-core/{p-a6a269da.system.entry.js → p-bb85bbb5.system.entry.js} +1 -1
- package/dist/pine-core/{p-fa8d3155.system.entry.js → p-bbc539bc.system.entry.js} +2 -2
- package/dist/pine-core/{p-f26dcbc2.system.entry.js → p-bf833976.system.entry.js} +1 -1
- package/dist/pine-core/{p-e055c543.entry.js → p-c23097af.entry.js} +1 -1
- package/dist/pine-core/p-c2dd84bd.system.entry.js +1 -0
- package/dist/pine-core/{p-441682f4.system.entry.js → p-c4520b04.system.entry.js} +1 -1
- package/dist/pine-core/{p-f1365550.entry.js → p-c4f68dfc.entry.js} +1 -1
- package/dist/pine-core/{p-fa2a786d.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-2bb101c2.entry.js → p-d0d7d1d4.entry.js} +1 -1
- package/dist/pine-core/{p-4f5aacd9.entry.js → p-d1112c8a.entry.js} +1 -1
- package/dist/pine-core/{p-5f3d0c86.system.entry.js → p-d4e91ad9.system.entry.js} +1 -1
- package/dist/pine-core/{p-44222439.entry.js → p-da018dcb.entry.js} +1 -1
- package/dist/pine-core/{p-57784f2f.system.entry.js → p-dc27abe6.system.entry.js} +1 -1
- package/dist/pine-core/{p-f9f7101e.entry.js → p-dc343b6d.entry.js} +1 -1
- package/dist/pine-core/{p-fb774f89.system.entry.js → p-dde753e7.system.entry.js} +1 -1
- package/dist/pine-core/{p-558ac401.entry.js → p-dea3a582.entry.js} +1 -1
- package/dist/pine-core/p-df29fd41.entry.js +1 -0
- package/dist/pine-core/{p-c6426e16.system.entry.js → p-e4e2eae2.system.entry.js} +1 -1
- package/dist/pine-core/{p-1abae35f.entry.js → p-e8668178.entry.js} +1 -1
- package/dist/pine-core/{p-20753e42.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-13bb89ff.entry.js → p-ed63873c.entry.js} +1 -1
- package/dist/pine-core/{p-5d2f95bd.entry.js → p-f4f6dc36.entry.js} +1 -1
- package/dist/pine-core/{p-6b3d8c2b.system.entry.js → p-f67a0ca8.system.entry.js} +1 -1
- package/dist/pine-core/{p-003df3b3.entry.js → p-fc455968.entry.js} +1 -1
- package/dist/pine-core/{p-02452806.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-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-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 +677 -4
- package/dist/types/utils/closest.d.ts +2 -0
- package/dist/types/utils/utils.d.ts +9 -1
- package/dist/vscode.html-data.json +467 -3
- package/hydrate/index.js +3973 -362
- package/hydrate/index.mjs +3973 -362
- 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-BU1hN5Vy.js +0 -1
- package/dist/esm-es5/index-DcT8--Dn.js +0 -2
- package/dist/esm-es5/utils-u_0lxWnH.js +0 -1
- package/dist/pine-core/p-026ee6de.entry.js +0 -1
- package/dist/pine-core/p-03f3fc92.system.entry.js +0 -1
- package/dist/pine-core/p-06375326.system.entry.js +0 -1
- package/dist/pine-core/p-1df5e088.entry.js +0 -1
- package/dist/pine-core/p-24214ab9.system.entry.js +0 -1
- package/dist/pine-core/p-250011ba.entry.js +0 -1
- package/dist/pine-core/p-2b420257.entry.js +0 -1
- package/dist/pine-core/p-375eb7f4.entry.js +0 -1
- package/dist/pine-core/p-3b796898.entry.js +0 -1
- package/dist/pine-core/p-3c5489ce.entry.js +0 -1
- package/dist/pine-core/p-3e868906.system.entry.js +0 -1
- package/dist/pine-core/p-464f23e6.entry.js +0 -1
- package/dist/pine-core/p-49c6112a.entry.js +0 -1
- package/dist/pine-core/p-4bd57896.system.entry.js +0 -1
- package/dist/pine-core/p-6a6a767b.system.entry.js +0 -1
- package/dist/pine-core/p-6dabeebc.system.entry.js +0 -3
- package/dist/pine-core/p-70891202.entry.js +0 -1
- package/dist/pine-core/p-73fa955a.system.entry.js +0 -1
- package/dist/pine-core/p-755e0b3c.system.entry.js +0 -1
- package/dist/pine-core/p-8b051229.entry.js +0 -1
- package/dist/pine-core/p-8d8a8550.system.entry.js +0 -1
- package/dist/pine-core/p-93486f2e.entry.js +0 -1
- package/dist/pine-core/p-93ae562d.entry.js +0 -1
- package/dist/pine-core/p-95b8bece.system.entry.js +0 -1
- package/dist/pine-core/p-9d902000.system.entry.js +0 -1
- package/dist/pine-core/p-9ef355b7.entry.js +0 -1
- package/dist/pine-core/p-BI7Ml0VF.system.js +0 -1
- package/dist/pine-core/p-BKsJZTyn.js +0 -1
- package/dist/pine-core/p-BU1hN5Vy.js +0 -1
- package/dist/pine-core/p-BrLs99ML.system.js +0 -1
- package/dist/pine-core/p-CJ8t3EBJ.system.js +0 -2
- package/dist/pine-core/p-Cr7-rJtJ.system.js +0 -1
- package/dist/pine-core/p-DDtwbwIl.js +0 -1
- package/dist/pine-core/p-D_I-k33A.system.js +0 -1
- package/dist/pine-core/p-DcT8--Dn.js +0 -2
- package/dist/pine-core/p-DnUJodVd.js +0 -1
- package/dist/pine-core/p-a009ab10.system.entry.js +0 -1
- package/dist/pine-core/p-a8cd2ab5.entry.js +0 -1
- package/dist/pine-core/p-b45b8f8b.system.entry.js +0 -1
- package/dist/pine-core/p-b85bb61d.system.entry.js +0 -1
- package/dist/pine-core/p-bdded57a.system.entry.js +0 -1
- package/dist/pine-core/p-c1a65082.entry.js +0 -1
- package/dist/pine-core/p-c1d1befb.system.entry.js +0 -1
- package/dist/pine-core/p-ctdGub9B.system.js +0 -1
- package/dist/pine-core/p-d9c1ee36.system.entry.js +0 -1
- package/dist/pine-core/p-df285ece.system.entry.js +0 -1
- package/dist/pine-core/p-ee114aef.entry.js +0 -1
- package/dist/pine-core/p-ee997fbf.entry.js +0 -2
- package/dist/pine-core/p-f89197c9.entry.js +0 -1
- package/dist/pine-core/p-kYMYDfJY.system.js +0 -1
- package/dist/pine-core/p-u_0lxWnH.js +0 -1
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { h, Host } from "@stencil/core";
|
|
2
2
|
import { assignDescription, isSpecTest, messageId } from "../../utils/form";
|
|
3
3
|
import { autoUpdate, computePosition, flip, offset, shift } from "@floating-ui/dom";
|
|
4
|
-
import { debounceEvent } from "../../utils/utils";
|
|
4
|
+
import { cancelDebouncedEvent, debounceEvent, flushDebouncedEvent } from "../../utils/utils";
|
|
5
5
|
import DOMPurify from "dompurify";
|
|
6
|
+
import { FlyoutController, buildPanelEntries, findGroup, groupIconOf, groupLabelOf, isGroupDisabled, isOptionDisabled, panelColumn, parentOptgroupOf, } from "./grouped-options-panel";
|
|
6
7
|
/**
|
|
7
8
|
* @slot option - Option elements for the combobox dropdown
|
|
8
9
|
* @slot trigger-content - Custom content for the button trigger when customTriggerContent is true
|
|
@@ -50,6 +51,35 @@ export class PdsCombobox {
|
|
|
50
51
|
* @default 'host'
|
|
51
52
|
*/
|
|
52
53
|
this.dropdownMount = 'host';
|
|
54
|
+
/**
|
|
55
|
+
* Accessible prefix for the row that returns to the group list when `group-display` is
|
|
56
|
+
* `drill-in`, read before the open group's label. Pass a translated string to localize it; defaults to English.
|
|
57
|
+
* @defaultValue 'Back'
|
|
58
|
+
*/
|
|
59
|
+
this.drillInBackLabel = 'Back';
|
|
60
|
+
/**
|
|
61
|
+
* Maximum width of a group's flyout when `group-display` is `flyout`. Any valid CSS width value.
|
|
62
|
+
* @default '380px'
|
|
63
|
+
*/
|
|
64
|
+
this.flyoutMaxWidth = '380px';
|
|
65
|
+
/**
|
|
66
|
+
* Minimum width of a group's flyout when `group-display` is `flyout`. Any valid CSS width value.
|
|
67
|
+
* The flyout is as wide as its options, between this and `flyout-max-width`.
|
|
68
|
+
* @default '280px'
|
|
69
|
+
*/
|
|
70
|
+
this.flyoutMinWidth = '280px';
|
|
71
|
+
/**
|
|
72
|
+
* How option groups (`<optgroup>`, or the `group` field of `options`) are shown in the dropdown.
|
|
73
|
+
* `inline` lists each group's label above its options. `flyout` lists the groups, and opens a
|
|
74
|
+
* group's options in a panel beside it on hover or click; while searching, the matching options
|
|
75
|
+
* are listed under their group labels, and search also matches group labels. `flyout` groups
|
|
76
|
+
* by `<optgroup>` (or `group`) only: options under a `<pds-text>` heading are listed ungrouped.
|
|
77
|
+
* `drill-in` lists the groups too, but a click replaces the list with that group's options and a
|
|
78
|
+
* row back to the groups; use it where nothing can open beside the dropdown, such as a side
|
|
79
|
+
* panel. `flyout` falls back to `drill-in` when there is no room for a flyout on either side.
|
|
80
|
+
* @default 'inline'
|
|
81
|
+
*/
|
|
82
|
+
this.groupDisplay = 'inline';
|
|
53
83
|
/**
|
|
54
84
|
* Visually hides the label text for instances where only the combobox should be displayed.
|
|
55
85
|
* The visible `<label>` is omitted (same pattern as `pds-select`) so label spacing does not reserve layout;
|
|
@@ -63,6 +93,23 @@ export class PdsCombobox {
|
|
|
63
93
|
* @default 'filter'
|
|
64
94
|
*/
|
|
65
95
|
this.mode = 'filter';
|
|
96
|
+
/**
|
|
97
|
+
* Shows a search field at the top of the dropdown for the `button` and `chip` triggers, which
|
|
98
|
+
* can't be typed into. Search filters the options the same way typing in the `input` trigger
|
|
99
|
+
* does; in a grouped display it also matches group labels.
|
|
100
|
+
* @default false
|
|
101
|
+
*/
|
|
102
|
+
this.panelSearch = false;
|
|
103
|
+
/**
|
|
104
|
+
* Accessible label for the search input inside the dropdown panel (`panel-search`). Pass a translated string to localize it; defaults to English.
|
|
105
|
+
* @defaultValue 'Search options'
|
|
106
|
+
*/
|
|
107
|
+
this.searchOptionsLabel = 'Search options';
|
|
108
|
+
/**
|
|
109
|
+
* Placeholder text for the search input inside the dropdown panel (`panel-search`). Pass a translated string to localize it; defaults to English.
|
|
110
|
+
* @defaultValue 'Find...'
|
|
111
|
+
*/
|
|
112
|
+
this.searchPlaceholder = 'Find...';
|
|
66
113
|
/**
|
|
67
114
|
* Determines the combobox trigger: 'input' (editable input), 'button' (button-like, non-editable), or 'chip' (chip-like, non-editable).
|
|
68
115
|
* @default 'input'
|
|
@@ -135,6 +182,30 @@ export class PdsCombobox {
|
|
|
135
182
|
* Internal state for dropdown open/close
|
|
136
183
|
*/
|
|
137
184
|
this.isOpen = false;
|
|
185
|
+
/**
|
|
186
|
+
* The optgroup whose flyout is open, when `groupDisplay` is `flyout`.
|
|
187
|
+
*/
|
|
188
|
+
this.openGroup = null;
|
|
189
|
+
/**
|
|
190
|
+
* Which way drill-in just moved, so the list slides that way: `in` to a group, `out` back to the
|
|
191
|
+
* groups. Cleared once the slide ends, so later renders don't animate.
|
|
192
|
+
*/
|
|
193
|
+
this.drillDirection = null;
|
|
194
|
+
/**
|
|
195
|
+
* The group row highlighted in the grouped panel. It counts only while no option is
|
|
196
|
+
* highlighted (`highlightedIndex` is -1); see `highlightedGroupRow`.
|
|
197
|
+
*/
|
|
198
|
+
this.highlightedGroup = null;
|
|
199
|
+
/** The keys, not the pointer, moved the highlight last; the focus ring shows only then. */
|
|
200
|
+
this.keyboardNavigating = false;
|
|
201
|
+
/**
|
|
202
|
+
* What's typed in the dropdown's own search field (`panelSearch`).
|
|
203
|
+
*/
|
|
204
|
+
this.panelQuery = '';
|
|
205
|
+
/**
|
|
206
|
+
* `groupDisplay` is `flyout` but there's no room beside the dropdown, so groups drill in instead.
|
|
207
|
+
*/
|
|
208
|
+
this.flyoutFallback = false;
|
|
138
209
|
/**
|
|
139
210
|
* Internal state for the currently selected option
|
|
140
211
|
*/
|
|
@@ -164,12 +235,39 @@ export class PdsCombobox {
|
|
|
164
235
|
this.portalEl = null;
|
|
165
236
|
this.bodyPortalAutoUpdateActive = false;
|
|
166
237
|
this.isUpdatingFromSelection = false;
|
|
238
|
+
this.flyout = new FlyoutController(() => this.openGroup, group => {
|
|
239
|
+
this.openGroup = group;
|
|
240
|
+
});
|
|
241
|
+
/** The groups in the flyout panel's last render, so a row's index finds its optgroup. */
|
|
242
|
+
this.renderedGroups = [];
|
|
243
|
+
/** Room for a flyout was checked for this open. */
|
|
244
|
+
this.flyoutRoomChecked = false;
|
|
245
|
+
/** The highlighted option sits in a flyout that hasn't rendered yet; focus it after the next render. */
|
|
246
|
+
this.pendingOptionFocus = false;
|
|
247
|
+
/** Group rows' DOM ids, stable across renders so `aria-activedescendant` can point at a row. */
|
|
248
|
+
this.groupIds = new WeakMap();
|
|
249
|
+
this.groupIdCount = 0;
|
|
167
250
|
/**
|
|
168
251
|
* In filter mode, after choosing an option the input still shows the label and would
|
|
169
252
|
* otherwise filter the list to matching substrings only. While this flag is true,
|
|
170
253
|
* the list shows every option until the user types (then normal filtering applies).
|
|
171
254
|
*/
|
|
172
255
|
this.expandFilterListWhileOpen = false;
|
|
256
|
+
this.onDrillAnimationEnd = (event) => {
|
|
257
|
+
var _a;
|
|
258
|
+
// Only the slide's own end: slotted consumer content can animate inside the list too.
|
|
259
|
+
if ((_a = event.animationName) === null || _a === void 0 ? void 0 : _a.startsWith('pds-combobox-drill'))
|
|
260
|
+
this.drillDirection = null;
|
|
261
|
+
};
|
|
262
|
+
/** `<label for>` only works on the input trigger; for a div trigger a click on the label focuses it. */
|
|
263
|
+
this.onLabelClick = () => {
|
|
264
|
+
var _a;
|
|
265
|
+
if (this.trigger !== 'input' && !this.disabled) {
|
|
266
|
+
(_a = this.triggerEl) === null || _a === void 0 ? void 0 : _a.focus();
|
|
267
|
+
}
|
|
268
|
+
};
|
|
269
|
+
/** The query behind the options loaded from `async-url`. */
|
|
270
|
+
this.lastFetchedQuery = '';
|
|
173
271
|
this.handleInput = (e) => {
|
|
174
272
|
const target = e.target;
|
|
175
273
|
this.clearExpandFilterList();
|
|
@@ -206,6 +304,7 @@ export class PdsCombobox {
|
|
|
206
304
|
this.handleKeyDown = (e) => {
|
|
207
305
|
if (!this.isOpen && (e.key === 'ArrowDown' || e.key === 'ArrowUp' || (e.altKey && e.key === 'ArrowDown'))) {
|
|
208
306
|
e.preventDefault();
|
|
307
|
+
this.keyboardNavigating = true;
|
|
209
308
|
this.isOpen = true;
|
|
210
309
|
this.prepareExpandFilterListOnOpen();
|
|
211
310
|
this.filterOptions();
|
|
@@ -227,75 +326,53 @@ export class PdsCombobox {
|
|
|
227
326
|
if (!this.isOpen) {
|
|
228
327
|
return;
|
|
229
328
|
}
|
|
329
|
+
if (this.handleGroupedPanelKey(e))
|
|
330
|
+
return;
|
|
331
|
+
// The input trigger's text keeps Space, Home and End while the grouped panel shows.
|
|
332
|
+
if (this.showsGroupedPanel && this.trigger === 'input' && (e.key === ' ' || e.key === 'Home' || e.key === 'End'))
|
|
333
|
+
return;
|
|
230
334
|
// Get only the option elements (skip group labels) for navigation
|
|
231
335
|
const selectableOptions = this.filteredItems.filter(item => item.tagName === 'OPTION');
|
|
232
336
|
switch (e.key) {
|
|
233
337
|
case 'ArrowDown':
|
|
234
338
|
e.preventDefault();
|
|
235
|
-
// If no option is highlighted
|
|
236
|
-
|
|
237
|
-
this.highlightedIndex = 0;
|
|
238
|
-
}
|
|
239
|
-
else {
|
|
240
|
-
this.highlightedIndex = Math.min(this.highlightedIndex + 1, selectableOptions.length - 1);
|
|
241
|
-
}
|
|
242
|
-
this.updateOptionFocus();
|
|
339
|
+
// If no option is highlighted, start at the first
|
|
340
|
+
this.highlightOptionAt(selectableOptions, this.highlightedIndex < 0 ? 0 : this.highlightedIndex + 1);
|
|
243
341
|
break;
|
|
244
342
|
case 'ArrowUp':
|
|
245
343
|
e.preventDefault();
|
|
246
|
-
// If no option is highlighted
|
|
247
|
-
|
|
248
|
-
this.highlightedIndex = selectableOptions.length - 1;
|
|
249
|
-
}
|
|
250
|
-
else {
|
|
251
|
-
this.highlightedIndex = Math.max(this.highlightedIndex - 1, 0);
|
|
252
|
-
}
|
|
253
|
-
this.updateOptionFocus();
|
|
344
|
+
// If no option is highlighted, start at the last
|
|
345
|
+
this.highlightOptionAt(selectableOptions, this.highlightedIndex < 0 ? selectableOptions.length - 1 : this.highlightedIndex - 1);
|
|
254
346
|
break;
|
|
255
347
|
case 'Home':
|
|
256
348
|
e.preventDefault();
|
|
257
|
-
|
|
258
|
-
this.highlightedIndex = 0;
|
|
259
|
-
this.updateOptionFocus();
|
|
260
|
-
}
|
|
349
|
+
this.highlightOptionAt(selectableOptions, 0);
|
|
261
350
|
break;
|
|
262
351
|
case 'End':
|
|
263
352
|
e.preventDefault();
|
|
264
|
-
|
|
265
|
-
this.highlightedIndex = selectableOptions.length - 1;
|
|
266
|
-
this.updateOptionFocus();
|
|
267
|
-
}
|
|
353
|
+
this.highlightOptionAt(selectableOptions, selectableOptions.length - 1);
|
|
268
354
|
break;
|
|
269
355
|
case 'PageDown':
|
|
270
356
|
e.preventDefault();
|
|
271
|
-
|
|
272
|
-
const nextIndex = Math.min(this.highlightedIndex + 10, selectableOptions.length - 1);
|
|
273
|
-
this.highlightedIndex = nextIndex;
|
|
274
|
-
this.updateOptionFocus();
|
|
275
|
-
}
|
|
357
|
+
this.highlightOptionAt(selectableOptions, this.highlightedIndex + 10);
|
|
276
358
|
break;
|
|
277
359
|
case 'PageUp':
|
|
278
360
|
e.preventDefault();
|
|
279
|
-
|
|
280
|
-
const prevIndex = Math.max(this.highlightedIndex - 10, 0);
|
|
281
|
-
this.highlightedIndex = prevIndex;
|
|
282
|
-
this.updateOptionFocus();
|
|
283
|
-
}
|
|
361
|
+
this.highlightOptionAt(selectableOptions, this.highlightedIndex - 10);
|
|
284
362
|
break;
|
|
285
363
|
case 'Enter':
|
|
364
|
+
case ' ': {
|
|
286
365
|
e.preventDefault();
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
e.preventDefault();
|
|
294
|
-
if (this.highlightedIndex >= 0 && this.highlightedIndex < selectableOptions.length) {
|
|
295
|
-
this.handleOptionClick(selectableOptions[this.highlightedIndex]);
|
|
366
|
+
// An option in a flyout the pointer has since closed isn't on screen; don't choose it.
|
|
367
|
+
if (this.showsGroupedPanel && this.activeDescendantId === undefined)
|
|
368
|
+
break;
|
|
369
|
+
const option = selectableOptions[this.highlightedIndex];
|
|
370
|
+
if (option !== undefined && !isOptionDisabled(option)) {
|
|
371
|
+
this.handleOptionClick(option);
|
|
296
372
|
this.restoreFocusToTrigger();
|
|
297
373
|
}
|
|
298
374
|
break;
|
|
375
|
+
}
|
|
299
376
|
case 'Escape':
|
|
300
377
|
e.preventDefault();
|
|
301
378
|
this.isOpen = false;
|
|
@@ -320,12 +397,53 @@ export class PdsCombobox {
|
|
|
320
397
|
const idx = Number(event.currentTarget.getAttribute('data-option-index'));
|
|
321
398
|
const selectableOptions = this.filteredItems.filter(item => item.tagName === 'OPTION');
|
|
322
399
|
const option = selectableOptions[idx];
|
|
400
|
+
if (isOptionDisabled(option))
|
|
401
|
+
return;
|
|
323
402
|
this.handleOptionClick(option);
|
|
403
|
+
// The search field closes with the panel; send focus back to the trigger instead of losing it.
|
|
404
|
+
// (Enter and Space already restore focus in the key handler.)
|
|
405
|
+
if (this.usesPanelSearch)
|
|
406
|
+
this.restoreFocusToTrigger();
|
|
324
407
|
};
|
|
325
408
|
// Event handler for mouse enter on option
|
|
326
409
|
this.onOptionMouseEnter = (event) => {
|
|
327
410
|
const idx = Number(event.currentTarget.getAttribute('data-option-index'));
|
|
328
411
|
this.highlightedIndex = idx;
|
|
412
|
+
this.keyboardNavigating = false;
|
|
413
|
+
};
|
|
414
|
+
this.onGroupRowMouseEnter = (event) => {
|
|
415
|
+
const group = this.groupFromEvent(event);
|
|
416
|
+
if (group !== null)
|
|
417
|
+
this.flyout.enter(group);
|
|
418
|
+
};
|
|
419
|
+
this.onGroupRowMouseLeave = (event) => {
|
|
420
|
+
const group = this.groupFromEvent(event);
|
|
421
|
+
if (group !== null)
|
|
422
|
+
this.flyout.leave(group);
|
|
423
|
+
};
|
|
424
|
+
// The pointer highlights a group's row as it does an option, so the keys carry on from there.
|
|
425
|
+
this.onGroupRowTriggerMouseEnter = (event) => {
|
|
426
|
+
const group = this.groupFromEvent(event);
|
|
427
|
+
if (group !== null)
|
|
428
|
+
this.highlightGroupRowByPointer(group);
|
|
429
|
+
};
|
|
430
|
+
this.onGroupBackMouseEnter = () => {
|
|
431
|
+
if (this.openGroup !== null)
|
|
432
|
+
this.highlightGroupRowByPointer(this.openGroup);
|
|
433
|
+
};
|
|
434
|
+
this.onGroupRowClick = (event) => {
|
|
435
|
+
var _a;
|
|
436
|
+
const group = this.groupFromEvent(event);
|
|
437
|
+
if (group === null)
|
|
438
|
+
return;
|
|
439
|
+
this.flyout.open(group);
|
|
440
|
+
// Highlight the group's first option, so the arrow keys carry on from the group just opened
|
|
441
|
+
// rather than from wherever the highlight was before.
|
|
442
|
+
const first = (_a = this.renderedGroups.find(entry => entry.optgroup === group)) === null || _a === void 0 ? void 0 : _a.options[0];
|
|
443
|
+
if (first !== undefined) {
|
|
444
|
+
this.highlightedIndex = first.index;
|
|
445
|
+
this.updateAriaActiveDescendant();
|
|
446
|
+
}
|
|
329
447
|
};
|
|
330
448
|
// Prevent blur on mousedown
|
|
331
449
|
this.onOptionMouseDown = (event) => {
|
|
@@ -342,10 +460,7 @@ export class PdsCombobox {
|
|
|
342
460
|
if (this.isOpen) {
|
|
343
461
|
this.prepareExpandFilterListOnOpen();
|
|
344
462
|
this.filterOptions();
|
|
345
|
-
|
|
346
|
-
if (this.asyncUrl && this.internalOptions.length === 0) {
|
|
347
|
-
this.debouncedFetchAsyncOptions(this.displayText, 1);
|
|
348
|
-
}
|
|
463
|
+
this.fetchAsyncOptionsOnOpen();
|
|
349
464
|
// Set highlighted index and prepare for keyboard navigation
|
|
350
465
|
this.setInitialHighlightedIndex();
|
|
351
466
|
// For button trigger, prepare for arrow-key navigation mode
|
|
@@ -360,12 +475,17 @@ export class PdsCombobox {
|
|
|
360
475
|
};
|
|
361
476
|
// Handler for button trigger keyboard events
|
|
362
477
|
this.onButtonTriggerKeyDown = (e) => {
|
|
478
|
+
// Escape closes an open group before the dropdown. Other keys reach the tree through handleKeyDown.
|
|
479
|
+
if (this.isOpen && e.key === 'Escape' && this.handleGroupedPanelKey(e))
|
|
480
|
+
return;
|
|
363
481
|
if ((e.key === 'Enter' || e.key === ' ' || e.key === 'ArrowDown' || e.key === 'ArrowUp') && !this.isOpen) {
|
|
364
482
|
e.preventDefault();
|
|
365
483
|
e.stopPropagation(); // Prevent the event from bubbling and triggering click
|
|
484
|
+
this.keyboardNavigating = true;
|
|
366
485
|
this.isOpen = true;
|
|
367
486
|
this.prepareExpandFilterListOnOpen();
|
|
368
487
|
this.filterOptions();
|
|
488
|
+
this.fetchAsyncOptionsOnOpen();
|
|
369
489
|
// Set highlighted index immediately
|
|
370
490
|
this.setInitialHighlightedIndex();
|
|
371
491
|
setTimeout(() => {
|
|
@@ -398,11 +518,13 @@ export class PdsCombobox {
|
|
|
398
518
|
};
|
|
399
519
|
// Close dropdown when focus leaves the combobox
|
|
400
520
|
this.onComboboxFocusOut = (event) => {
|
|
401
|
-
var _a, _b;
|
|
521
|
+
var _a, _b, _c;
|
|
402
522
|
const relatedTarget = event.relatedTarget;
|
|
403
523
|
const isRelatedTargetInListbox = relatedTarget &&
|
|
404
524
|
(((_a = this.listboxEl) === null || _a === void 0 ? void 0 : _a.contains(relatedTarget)) || ((_b = this.portalEl) === null || _b === void 0 ? void 0 : _b.contains(relatedTarget)));
|
|
405
|
-
|
|
525
|
+
// `contains` doesn't cross into the shadow root, where the trigger lives; with panel search,
|
|
526
|
+
// focus leaves the search field for the trigger whenever it's clicked to close.
|
|
527
|
+
const isRelatedTargetInCombobox = relatedTarget !== null && (this.el.contains(relatedTarget) || !!((_c = this.el.shadowRoot) === null || _c === void 0 ? void 0 : _c.contains(relatedTarget)));
|
|
406
528
|
// Don't close if focus is moving to an option in the listbox or staying within the combobox
|
|
407
529
|
if (!isRelatedTargetInCombobox && !isRelatedTargetInListbox) {
|
|
408
530
|
this.isOpen = false;
|
|
@@ -425,11 +547,58 @@ export class PdsCombobox {
|
|
|
425
547
|
// Load more when near bottom (within 50px)
|
|
426
548
|
if (scrollBottom < 50) {
|
|
427
549
|
this.pdsComboboxLoadOptions.emit({
|
|
428
|
-
query: this.
|
|
550
|
+
query: this.activeQuery,
|
|
429
551
|
page: this.currentPage + 1,
|
|
430
552
|
});
|
|
431
|
-
this.debouncedFetchAsyncOptions(this.
|
|
553
|
+
this.debouncedFetchAsyncOptions(this.activeQuery, this.currentPage + 1);
|
|
554
|
+
}
|
|
555
|
+
};
|
|
556
|
+
// A press on the panel's padding, captions or status rows keeps focus in the search field;
|
|
557
|
+
// otherwise it would blur the field, closing a portaled panel or stranding the keys.
|
|
558
|
+
this.onPanelMouseDown = (event) => {
|
|
559
|
+
if (event.target !== this.panelSearchEl)
|
|
560
|
+
event.preventDefault();
|
|
561
|
+
};
|
|
562
|
+
this.onPanelSearchInput = (event) => {
|
|
563
|
+
this.setPanelQuery(event.target.value);
|
|
564
|
+
};
|
|
565
|
+
// Space, Home and End edit the search text rather than moving through the options.
|
|
566
|
+
this.onPanelSearchKeyDown = (event) => {
|
|
567
|
+
if (event.key === ' ' || event.key === 'Home' || event.key === 'End')
|
|
568
|
+
return;
|
|
569
|
+
if (this.handlePanelTab(event))
|
|
570
|
+
return;
|
|
571
|
+
this.handleKeyDown(event);
|
|
572
|
+
};
|
|
573
|
+
/**
|
|
574
|
+
* Keys in the list while a drilled-in group hides the search field. Backspace, like ArrowLeft,
|
|
575
|
+
* steps back to the groups; a character starts a search of the whole list. Characters typed
|
|
576
|
+
* before the search field renders and takes focus still land on the list, so they add to the
|
|
577
|
+
* query rather than starting it again.
|
|
578
|
+
*/
|
|
579
|
+
this.onPanelTreeKeyDown = (event) => {
|
|
580
|
+
if (this.handlePanelTab(event))
|
|
581
|
+
return;
|
|
582
|
+
if (event.key === 'Backspace') {
|
|
583
|
+
event.preventDefault();
|
|
584
|
+
if (!this.leaveDrilledInGroup() && this.panelQuery !== '')
|
|
585
|
+
this.setPanelQuery(this.panelQuery.slice(0, -1));
|
|
586
|
+
return;
|
|
587
|
+
}
|
|
588
|
+
// AltGr (Ctrl+Alt on Windows) and Option on macOS type characters too; Meta and Ctrl alone are
|
|
589
|
+
// shortcuts.
|
|
590
|
+
if (event.key.length === 1 && event.key !== ' ' && !event.metaKey && (!event.ctrlKey || event.altKey)) {
|
|
591
|
+
event.preventDefault();
|
|
592
|
+
this.flyout.reset();
|
|
593
|
+
// The query first, so leaving the group reads as search results, not a slide back.
|
|
594
|
+
this.setPanelQuery(this.panelQuery + event.key);
|
|
595
|
+
this.openGroup = null;
|
|
596
|
+
return;
|
|
432
597
|
}
|
|
598
|
+
this.handleKeyDown(event);
|
|
599
|
+
};
|
|
600
|
+
this.onGroupBackClick = () => {
|
|
601
|
+
this.leaveDrilledInGroup();
|
|
433
602
|
};
|
|
434
603
|
}
|
|
435
604
|
connectedCallback() {
|
|
@@ -466,15 +635,106 @@ export class PdsCombobox {
|
|
|
466
635
|
this.deferredPortalTeardownId = undefined;
|
|
467
636
|
}
|
|
468
637
|
(_a = this.observer) === null || _a === void 0 ? void 0 : _a.disconnect();
|
|
638
|
+
cancelDebouncedEvent(this.pdsComboboxSearch);
|
|
469
639
|
this.clearAsyncFetchState();
|
|
470
640
|
this.removeBodyPortal();
|
|
641
|
+
this.flyout.reset();
|
|
471
642
|
}
|
|
472
643
|
componentDidRender() {
|
|
644
|
+
var _a;
|
|
473
645
|
if (this.usesBodyPortal && this.isOpen) {
|
|
474
646
|
this.syncBodyPortal();
|
|
475
647
|
}
|
|
648
|
+
const row = (_a = this.listboxEl) === null || _a === void 0 ? void 0 : _a.querySelector('.pds-combobox__group-row--open');
|
|
649
|
+
const flyoutEl = row === null || row === void 0 ? void 0 : row.querySelector('.pds-combobox__flyout');
|
|
650
|
+
if (this.isOpen && this.listboxEl && row && flyoutEl) {
|
|
651
|
+
this.flyout.position(row, this.listboxEl, flyoutEl);
|
|
652
|
+
}
|
|
653
|
+
else {
|
|
654
|
+
this.flyout.stopPositioning();
|
|
655
|
+
}
|
|
656
|
+
// The row back is sticky over the group's options; scrolling an option into view stops below
|
|
657
|
+
// it. Set before any scroll below, and when it first applies, scroll the highlighted option
|
|
658
|
+
// again: the list keeps its offset on drilling in, and an earlier scroll had no padding.
|
|
659
|
+
if (this.panelTreeEl) {
|
|
660
|
+
const header = this.hidesPanelSearch ? this.panelTreeEl.querySelector('.pds-combobox__group-back-trigger') : null;
|
|
661
|
+
const padding = header ? `${header.offsetHeight}px` : '';
|
|
662
|
+
if (this.panelTreeEl.style.scrollPaddingBlockStart !== padding) {
|
|
663
|
+
this.panelTreeEl.style.scrollPaddingBlockStart = padding;
|
|
664
|
+
if (padding !== '' && this.highlightedIndex >= 0)
|
|
665
|
+
this.pendingOptionFocus = true;
|
|
666
|
+
}
|
|
667
|
+
}
|
|
668
|
+
if (this.pendingOptionFocus) {
|
|
669
|
+
this.pendingOptionFocus = false;
|
|
670
|
+
this.updateOptionFocus();
|
|
671
|
+
}
|
|
672
|
+
// Panel search keeps focus in the search field, or in the list while a group hides the field.
|
|
673
|
+
const panelFocusEl = this.hidesPanelSearch ? this.panelTreeEl : this.panelSearchEl;
|
|
674
|
+
if (this.isOpen && this.usesPanelSearch && panelFocusEl && panelFocusEl !== this.panelFocusEl) {
|
|
675
|
+
this.focusPanel(panelFocusEl);
|
|
676
|
+
}
|
|
677
|
+
}
|
|
678
|
+
focusPanel(el) {
|
|
679
|
+
var _a, _b;
|
|
680
|
+
this.panelFocusEl = el;
|
|
681
|
+
// Before the dropdown is positioned it sits in the page's flow; don't scroll to it.
|
|
682
|
+
el.focus({ preventScroll: true });
|
|
683
|
+
// A search started by typing in the list carries its first character; type on after it.
|
|
684
|
+
if (el === this.panelSearchEl && this.panelQuery !== '') {
|
|
685
|
+
(_b = (_a = this.panelSearchEl).setSelectionRange) === null || _b === void 0 ? void 0 : _b.call(_a, this.panelQuery.length, this.panelQuery.length);
|
|
686
|
+
}
|
|
687
|
+
this.updateAriaActiveDescendant();
|
|
688
|
+
}
|
|
689
|
+
/** Switching display mode leaves no flyout or hover timer from the last one. */
|
|
690
|
+
groupDisplayChanged() {
|
|
691
|
+
this.flyout.reset();
|
|
692
|
+
this.openGroup = null;
|
|
693
|
+
// The reset isn't a drill-out, so it doesn't slide either.
|
|
694
|
+
this.drillDirection = null;
|
|
695
|
+
}
|
|
696
|
+
openGroupChanged(next, previous) {
|
|
697
|
+
this.handPanelFocusToList();
|
|
698
|
+
// Only moves between the drill-in panel's views slide; search results don't.
|
|
699
|
+
if (!this.isOpen || this.effectiveGroupDisplay !== 'drill-in' || !this.showsGroupedPanel)
|
|
700
|
+
return;
|
|
701
|
+
if (next !== null && previous === null)
|
|
702
|
+
this.drillDirection = 'in';
|
|
703
|
+
else if (next === null && previous !== null)
|
|
704
|
+
this.drillDirection = 'out';
|
|
705
|
+
}
|
|
706
|
+
/** A flyout with no room beside the dropdown drills in, which can hide the focused search field too. */
|
|
707
|
+
flyoutFallbackChanged() {
|
|
708
|
+
this.handPanelFocusToList();
|
|
709
|
+
}
|
|
710
|
+
/**
|
|
711
|
+
* Drilling into a group hides the search field, so focus moves to the list before the field
|
|
712
|
+
* unmounts: focus lost with it would leave the combobox and close the dropdown.
|
|
713
|
+
*/
|
|
714
|
+
handPanelFocusToList() {
|
|
715
|
+
if (this.isOpen && this.hidesPanelSearch && this.panelTreeEl)
|
|
716
|
+
this.focusPanel(this.panelTreeEl);
|
|
476
717
|
}
|
|
477
718
|
isOpenChanged(isOpen) {
|
|
719
|
+
if (!isOpen) {
|
|
720
|
+
this.drillDirection = null;
|
|
721
|
+
this.openGroup = null;
|
|
722
|
+
this.highlightedGroup = null;
|
|
723
|
+
this.keyboardNavigating = false;
|
|
724
|
+
this.flyout.reset();
|
|
725
|
+
if (this.panelQuery !== '') {
|
|
726
|
+
// The field reopens empty, so tell consumers who filter `options` from this event.
|
|
727
|
+
this.panelQuery = '';
|
|
728
|
+
this.pdsComboboxSearch.emit({ query: '' });
|
|
729
|
+
}
|
|
730
|
+
// And with `async-url`, start loading the unsearched list now, so it's ready by the reopen.
|
|
731
|
+
if (this.usesPanelSearch && this.asyncUrl && this.lastFetchedQuery !== '') {
|
|
732
|
+
this.debouncedFetchAsyncOptions('', 1);
|
|
733
|
+
}
|
|
734
|
+
this.panelFocusEl = undefined;
|
|
735
|
+
this.flyoutRoomChecked = false;
|
|
736
|
+
this.flyoutFallback = false;
|
|
737
|
+
}
|
|
478
738
|
if (isOpen && this.deferredPortalTeardownId !== undefined) {
|
|
479
739
|
clearTimeout(this.deferredPortalTeardownId);
|
|
480
740
|
this.deferredPortalTeardownId = undefined;
|
|
@@ -507,17 +767,52 @@ export class PdsCombobox {
|
|
|
507
767
|
get usesBodyPortal() {
|
|
508
768
|
return this.dropdownMount === 'body';
|
|
509
769
|
}
|
|
770
|
+
get labelId() {
|
|
771
|
+
return `${this.componentId}-label`;
|
|
772
|
+
}
|
|
773
|
+
/** One check for "the `<label>` is rendered", so the label and the reference to it can't disagree. */
|
|
774
|
+
get hasVisibleLabel() {
|
|
775
|
+
return Boolean(this.label) && !this.hideLabel;
|
|
776
|
+
}
|
|
777
|
+
/**
|
|
778
|
+
* The button and chip triggers are `div`s, which `<label for>` can't name, so they point at the
|
|
779
|
+
* visible label instead. With `hide-label` there is no visible label and `aria-label` names them.
|
|
780
|
+
* With panel search the trigger is a button, which has no value, so its own text (the selection
|
|
781
|
+
* or placeholder) joins the label in its name.
|
|
782
|
+
*/
|
|
783
|
+
get triggerLabelledBy() {
|
|
784
|
+
if (!this.hasVisibleLabel)
|
|
785
|
+
return undefined;
|
|
786
|
+
return this.usesPanelSearch ? `${this.labelId} ${this.componentId}` : this.labelId;
|
|
787
|
+
}
|
|
788
|
+
/** The div triggers' `aria-label` when the label is hidden; with panel search it names the selection too. */
|
|
789
|
+
get triggerAriaLabel() {
|
|
790
|
+
if (!this.hideLabel)
|
|
791
|
+
return undefined;
|
|
792
|
+
const shown = this.selectedLabel || this.placeholder;
|
|
793
|
+
return this.usesPanelSearch && shown ? `${this.label}, ${shown}` : this.label;
|
|
794
|
+
}
|
|
510
795
|
get listboxId() {
|
|
511
796
|
return `${this.componentId}-listbox`;
|
|
512
797
|
}
|
|
513
798
|
optionDomId(optionIndex) {
|
|
514
799
|
return `${this.componentId}-option-${optionIndex}`;
|
|
515
800
|
}
|
|
801
|
+
groupDomId(optgroup) {
|
|
802
|
+
let id = this.groupIds.get(optgroup);
|
|
803
|
+
if (id === undefined) {
|
|
804
|
+
id = `${this.componentId}-group-${this.groupIdCount++}`;
|
|
805
|
+
this.groupIds.set(optgroup, id);
|
|
806
|
+
}
|
|
807
|
+
return id;
|
|
808
|
+
}
|
|
516
809
|
setupDebounce() {
|
|
517
810
|
const { pdsComboboxSearch, debounce, originalSearchEmitter } = this;
|
|
518
811
|
this.pdsComboboxSearch = debounce === undefined
|
|
519
812
|
? originalSearchEmitter !== null && originalSearchEmitter !== void 0 ? originalSearchEmitter : pdsComboboxSearch
|
|
520
813
|
: debounceEvent(pdsComboboxSearch, debounce);
|
|
814
|
+
// After the swap, so an emit made while flushing goes to the new emitter, not the old one.
|
|
815
|
+
flushDebouncedEvent(pdsComboboxSearch);
|
|
521
816
|
}
|
|
522
817
|
optionsChanged() {
|
|
523
818
|
if (this.options) {
|
|
@@ -664,6 +959,8 @@ export class PdsCombobox {
|
|
|
664
959
|
});
|
|
665
960
|
if (page === 1) {
|
|
666
961
|
this.internalOptions = formattedResults;
|
|
962
|
+
// Only once its results have loaded: a failed or aborted fetch leaves the last query's.
|
|
963
|
+
this.lastFetchedQuery = query;
|
|
667
964
|
}
|
|
668
965
|
else {
|
|
669
966
|
this.internalOptions = [...this.internalOptions, ...formattedResults];
|
|
@@ -688,26 +985,76 @@ export class PdsCombobox {
|
|
|
688
985
|
}
|
|
689
986
|
}
|
|
690
987
|
updateOptionsFromAsync() {
|
|
988
|
+
var _a;
|
|
691
989
|
if (!this.asyncUrl && !this.options)
|
|
692
990
|
return;
|
|
693
991
|
// Clear existing slot-based options when using async
|
|
694
992
|
this.optionEls = [];
|
|
695
993
|
this.allItems = [];
|
|
696
|
-
// Create option elements from async data
|
|
994
|
+
// Create option elements from async data. Grouped options are nested in an optgroup, as
|
|
995
|
+
// slotted markup would be, so grouping, filtering and labels work the same either way. Each
|
|
996
|
+
// group is listed where it first appears with all of its options, even when the data
|
|
997
|
+
// interleaves groups, so an option never renders under another group's label. Ungrouped
|
|
998
|
+
// options come first, so none reads as part of the group above it.
|
|
697
999
|
const asyncOptions = this.options || this.internalOptions;
|
|
1000
|
+
const groups = new Map();
|
|
1001
|
+
const ungrouped = [];
|
|
1002
|
+
const groupEntries = [];
|
|
698
1003
|
asyncOptions.forEach(opt => {
|
|
699
1004
|
const optionEl = document.createElement('option');
|
|
700
1005
|
optionEl.value = String(opt.id);
|
|
701
1006
|
optionEl.textContent = opt.text;
|
|
702
|
-
|
|
703
|
-
|
|
1007
|
+
if (opt.disabled === true)
|
|
1008
|
+
optionEl.setAttribute('disabled', '');
|
|
1009
|
+
// Only strings group an option or name an icon; anything else from JS is ignored, not coerced.
|
|
1010
|
+
if (typeof opt.group !== 'string' || opt.group === '') {
|
|
1011
|
+
ungrouped.push(optionEl);
|
|
1012
|
+
return;
|
|
1013
|
+
}
|
|
1014
|
+
let optgroup = groups.get(opt.group);
|
|
1015
|
+
if (!optgroup) {
|
|
1016
|
+
optgroup = document.createElement('optgroup');
|
|
1017
|
+
optgroup.label = opt.group;
|
|
1018
|
+
groups.set(opt.group, optgroup);
|
|
1019
|
+
groupEntries.push(optgroup);
|
|
1020
|
+
}
|
|
1021
|
+
if (!optgroup.hasAttribute('data-icon') && typeof opt.groupIcon === 'string' && opt.groupIcon !== '') {
|
|
1022
|
+
optgroup.setAttribute('data-icon', opt.groupIcon);
|
|
1023
|
+
}
|
|
1024
|
+
optgroup.appendChild(optionEl);
|
|
704
1025
|
});
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
1026
|
+
[...ungrouped, ...groupEntries].forEach(entry => {
|
|
1027
|
+
if (entry.tagName === 'OPTGROUP') {
|
|
1028
|
+
this.allItems.push(entry);
|
|
1029
|
+
Array.from(entry.children).forEach(child => {
|
|
1030
|
+
this.optionEls.push(child);
|
|
1031
|
+
this.allItems.push(child);
|
|
1032
|
+
});
|
|
1033
|
+
}
|
|
1034
|
+
else {
|
|
1035
|
+
this.optionEls.push(entry);
|
|
1036
|
+
this.allItems.push(entry);
|
|
1037
|
+
}
|
|
1038
|
+
});
|
|
1039
|
+
// A rebuild replaces every optgroup. Follow the open group to its new element by label, so the
|
|
1040
|
+
// flyout stays open across reloads and pagination, or close it if the group is gone. The hover
|
|
1041
|
+
// timers still hold the old element, so they're cleared either way. filterOptions, below,
|
|
1042
|
+
// resets the highlight.
|
|
1043
|
+
if (this.openGroup !== null && !groupEntries.includes(this.openGroup)) {
|
|
1044
|
+
this.flyout.reset();
|
|
1045
|
+
this.openGroup = (_a = groups.get(this.openGroup.label)) !== null && _a !== void 0 ? _a : null;
|
|
1046
|
+
}
|
|
1047
|
+
// Re-apply the selection to the rebuilt options: when `value` is set before async options have
|
|
1048
|
+
// loaded, and after any rebuild, which detaches the previously selected option element.
|
|
1049
|
+
if (this.value && (!this.selectedOption || !this.optionEls.includes(this.selectedOption))) {
|
|
708
1050
|
const matchingOption = this.optionEls.find(opt => opt.value === this.value);
|
|
709
1051
|
if (matchingOption) {
|
|
1052
|
+
// Relinking a selection keeps the same value, so it keeps any text being typed too, which
|
|
1053
|
+
// the selectedOption watcher would otherwise reset to the label.
|
|
1054
|
+
const typed = this.selectedOption ? this.displayText : undefined;
|
|
710
1055
|
this.setSelectedOption(matchingOption);
|
|
1056
|
+
if (typed !== undefined)
|
|
1057
|
+
this.displayText = typed;
|
|
711
1058
|
}
|
|
712
1059
|
}
|
|
713
1060
|
this.filterOptions();
|
|
@@ -758,11 +1105,12 @@ export class PdsCombobox {
|
|
|
758
1105
|
}
|
|
759
1106
|
}
|
|
760
1107
|
// For chip triggers, ensure we always have a selected option
|
|
761
|
-
|
|
762
|
-
|
|
1108
|
+
const firstEnabled = this.optionEls.find(opt => !isOptionDisabled(opt));
|
|
1109
|
+
if (initialSelected === null && this.trigger === 'chip' && firstEnabled !== undefined) {
|
|
1110
|
+
initialSelected = firstEnabled;
|
|
763
1111
|
this.value = initialSelected.value;
|
|
764
1112
|
this.displayText = this.getOptionLabel(initialSelected);
|
|
765
|
-
console.warn('PDS Combobox: Chip triggers should always have a selected option. Automatically selected the first option.');
|
|
1113
|
+
console.warn('PDS Combobox: Chip triggers should always have a selected option. Automatically selected the first enabled option.');
|
|
766
1114
|
}
|
|
767
1115
|
// Update selection if we found a different selected option or if we don't have one
|
|
768
1116
|
if (initialSelected && initialSelected !== this.selectedOption) {
|
|
@@ -850,16 +1198,26 @@ export class PdsCombobox {
|
|
|
850
1198
|
}
|
|
851
1199
|
}
|
|
852
1200
|
filterOptions() {
|
|
1201
|
+
// A new list replaces the rows a slide was animating, so its end event may never come.
|
|
1202
|
+
this.drillDirection = null;
|
|
853
1203
|
// Ensure allItems includes optionEls if not already populated (for edge cases)
|
|
854
1204
|
if (this.allItems.length === 0 && this.optionEls.length > 0) {
|
|
855
1205
|
this.allItems = [...this.optionEls];
|
|
856
1206
|
}
|
|
857
|
-
|
|
1207
|
+
const searchesPanel = this.usesPanelSearch;
|
|
1208
|
+
if ((this.mode === 'select-only' && !searchesPanel) || this.expandFilterListWhileOpen || (searchesPanel && this.panelQuery === '')) {
|
|
858
1209
|
this.filteredItems = [...this.allItems];
|
|
859
1210
|
}
|
|
860
1211
|
else {
|
|
861
|
-
const val = this.displayText.toLowerCase();
|
|
1212
|
+
const val = (searchesPanel ? this.panelQuery : this.displayText).toLowerCase();
|
|
862
1213
|
const filteredOptions = this.optionEls.filter(option => {
|
|
1214
|
+
// Outside inline mode a group's label is part of what search matches, so "tag" finds
|
|
1215
|
+
// every option in the Tag group.
|
|
1216
|
+
if (this.groupDisplay !== 'inline') {
|
|
1217
|
+
const groupLabel = groupLabelOf(option);
|
|
1218
|
+
if (groupLabel !== null && groupLabel.toLowerCase().includes(val))
|
|
1219
|
+
return true;
|
|
1220
|
+
}
|
|
863
1221
|
// For layout options, search both text content and data-search-text attribute
|
|
864
1222
|
if (this.isOptionLayout(option)) {
|
|
865
1223
|
const searchText = option.getAttribute('data-search-text') || option.textContent || '';
|
|
@@ -894,6 +1252,7 @@ export class PdsCombobox {
|
|
|
894
1252
|
});
|
|
895
1253
|
}
|
|
896
1254
|
this.highlightedIndex = -1;
|
|
1255
|
+
this.highlightedGroup = null;
|
|
897
1256
|
}
|
|
898
1257
|
clearExpandFilterList() {
|
|
899
1258
|
this.expandFilterListWhileOpen = false;
|
|
@@ -923,7 +1282,8 @@ export class PdsCombobox {
|
|
|
923
1282
|
this.listboxEl.style.width = this.dropdownWidth;
|
|
924
1283
|
if (this.maxHeight) {
|
|
925
1284
|
this.listboxEl.style.maxHeight = this.maxHeight;
|
|
926
|
-
|
|
1285
|
+
// With panel search, the options list scrolls under a fixed search field.
|
|
1286
|
+
this.listboxEl.style.overflowY = this.usesPanelSearch ? 'hidden' : 'auto';
|
|
927
1287
|
}
|
|
928
1288
|
this.listboxEl.offsetHeight;
|
|
929
1289
|
return computePosition(this.triggerEl, this.listboxEl, {
|
|
@@ -940,8 +1300,30 @@ export class PdsCombobox {
|
|
|
940
1300
|
position: strategy,
|
|
941
1301
|
zIndex,
|
|
942
1302
|
});
|
|
1303
|
+
this.checkFlyoutRoom();
|
|
943
1304
|
});
|
|
944
1305
|
}
|
|
1306
|
+
/**
|
|
1307
|
+
* Once per open, after the dropdown is placed: with no room for a flyout on either side of it,
|
|
1308
|
+
* `flyout` drills in instead. `flyout-min-width` is resolved through CSS, so any length works.
|
|
1309
|
+
*/
|
|
1310
|
+
checkFlyoutRoom() {
|
|
1311
|
+
if (!this.isOpen || this.groupDisplay !== 'flyout' || this.flyoutRoomChecked || !this.listboxEl)
|
|
1312
|
+
return;
|
|
1313
|
+
this.flyoutRoomChecked = true;
|
|
1314
|
+
const probe = document.createElement('div');
|
|
1315
|
+
// Fixed, like the flyout, so a percentage resolves against the viewport as the flyout's does.
|
|
1316
|
+
probe.style.cssText = 'position:fixed;visibility:hidden;width:0;';
|
|
1317
|
+
probe.style.minWidth = this.flyoutMinWidth;
|
|
1318
|
+
this.listboxEl.appendChild(probe);
|
|
1319
|
+
const needed = parseFloat(getComputedStyle(probe).minWidth);
|
|
1320
|
+
probe.remove();
|
|
1321
|
+
const rect = this.listboxEl.getBoundingClientRect();
|
|
1322
|
+
const room = Math.max(window.innerWidth - rect.right, rect.left);
|
|
1323
|
+
const fallback = Number.isFinite(needed) && needed > 0 && rect.width > 0 && room < needed;
|
|
1324
|
+
if (fallback !== this.flyoutFallback)
|
|
1325
|
+
this.flyoutFallback = fallback;
|
|
1326
|
+
}
|
|
945
1327
|
openDropdownPositioning() {
|
|
946
1328
|
if (!this.triggerEl || !this.listboxEl) {
|
|
947
1329
|
return;
|
|
@@ -1044,6 +1426,130 @@ export class PdsCombobox {
|
|
|
1044
1426
|
this.listboxEl = undefined;
|
|
1045
1427
|
}
|
|
1046
1428
|
}
|
|
1429
|
+
/**
|
|
1430
|
+
* The tree keys in the grouped panel. Up, Down, Home, End, PageUp and PageDown move within one
|
|
1431
|
+
* level; Right, Enter or Space opens a group at its first option; Left, or Escape, closes the
|
|
1432
|
+
* open group back to its row. Returns false for keys the listbox handling covers, such as
|
|
1433
|
+
* Enter on an option.
|
|
1434
|
+
*/
|
|
1435
|
+
handleGroupedPanelKey(e) {
|
|
1436
|
+
if (!this.showsGroupedPanel)
|
|
1437
|
+
return false;
|
|
1438
|
+
this.keyboardNavigating = true;
|
|
1439
|
+
// In the input trigger, Left and Right still move the caret through typed text, and Space,
|
|
1440
|
+
// Home and End edit it, as they do in the panel's search field.
|
|
1441
|
+
if (this.trigger === 'input') {
|
|
1442
|
+
if ((e.key === 'ArrowLeft' || e.key === 'ArrowRight') && this.displayText !== '')
|
|
1443
|
+
return false;
|
|
1444
|
+
if (e.key === ' ' || e.key === 'Home' || e.key === 'End')
|
|
1445
|
+
return false;
|
|
1446
|
+
}
|
|
1447
|
+
const entries = buildPanelEntries(this.filteredItems);
|
|
1448
|
+
const drilledIn = this.effectiveGroupDisplay === 'drill-in' && this.openGroup !== null;
|
|
1449
|
+
const current = this.currentPanelItem();
|
|
1450
|
+
const column = panelColumn(entries, this.openGroup, current, drilledIn);
|
|
1451
|
+
if (column.length === 0)
|
|
1452
|
+
return false;
|
|
1453
|
+
const position = current === null ? -1 : column.indexOf(current);
|
|
1454
|
+
const moveTo = (to) => {
|
|
1455
|
+
e.preventDefault();
|
|
1456
|
+
this.highlightPanelItem(column[Math.max(0, Math.min(column.length - 1, to))]);
|
|
1457
|
+
return true;
|
|
1458
|
+
};
|
|
1459
|
+
switch (e.key) {
|
|
1460
|
+
case 'ArrowDown':
|
|
1461
|
+
return moveTo(position < 0 ? 0 : position + 1);
|
|
1462
|
+
case 'ArrowUp':
|
|
1463
|
+
return moveTo(position < 0 ? column.length - 1 : position - 1);
|
|
1464
|
+
case 'Home':
|
|
1465
|
+
return moveTo(0);
|
|
1466
|
+
case 'End':
|
|
1467
|
+
return moveTo(column.length - 1);
|
|
1468
|
+
case 'PageDown':
|
|
1469
|
+
return moveTo(position < 0 ? 0 : position + 10);
|
|
1470
|
+
case 'PageUp':
|
|
1471
|
+
return moveTo(position < 0 ? column.length - 1 : position - 10);
|
|
1472
|
+
case 'ArrowRight':
|
|
1473
|
+
case 'Enter':
|
|
1474
|
+
case ' ': {
|
|
1475
|
+
if (current === null || typeof current === 'number')
|
|
1476
|
+
return false;
|
|
1477
|
+
e.preventDefault();
|
|
1478
|
+
if (!drilledIn || current !== this.openGroup) {
|
|
1479
|
+
this.expandGroup(entries, current);
|
|
1480
|
+
}
|
|
1481
|
+
else if (e.key === 'ArrowRight') {
|
|
1482
|
+
// On the row back of a drilled-in group: down into its options.
|
|
1483
|
+
if (column.length > 1)
|
|
1484
|
+
this.highlightPanelItem(column[1]);
|
|
1485
|
+
}
|
|
1486
|
+
else {
|
|
1487
|
+
this.leaveDrilledInGroup();
|
|
1488
|
+
}
|
|
1489
|
+
return true;
|
|
1490
|
+
}
|
|
1491
|
+
case 'ArrowLeft':
|
|
1492
|
+
case 'Escape': {
|
|
1493
|
+
// Escape with no group open closes the panel, through the listbox handling.
|
|
1494
|
+
if (this.openGroup === null)
|
|
1495
|
+
return false;
|
|
1496
|
+
e.preventDefault();
|
|
1497
|
+
this.collapseToGroup(this.openGroup);
|
|
1498
|
+
return true;
|
|
1499
|
+
}
|
|
1500
|
+
}
|
|
1501
|
+
return false;
|
|
1502
|
+
}
|
|
1503
|
+
/**
|
|
1504
|
+
* Where the keyboard is in the grouped panel. An option highlighted in a group that has since
|
|
1505
|
+
* closed (the pointer left its flyout) counts as its group's row, so the keys carry on from
|
|
1506
|
+
* what's showing rather than from an option that isn't.
|
|
1507
|
+
*/
|
|
1508
|
+
currentPanelItem() {
|
|
1509
|
+
if (this.highlightedIndex < 0)
|
|
1510
|
+
return this.highlightedGroup;
|
|
1511
|
+
const selectable = this.filteredItems.filter(item => item.tagName === 'OPTION');
|
|
1512
|
+
const group = parentOptgroupOf(selectable[this.highlightedIndex]);
|
|
1513
|
+
return group !== null && group !== this.openGroup ? group : this.highlightedIndex;
|
|
1514
|
+
}
|
|
1515
|
+
/**
|
|
1516
|
+
* Highlights the option at `index`, kept within the list. Disabled options can be highlighted,
|
|
1517
|
+
* so assistive tech announces them as unavailable, but not chosen.
|
|
1518
|
+
*/
|
|
1519
|
+
highlightOptionAt(options, index) {
|
|
1520
|
+
if (options.length === 0)
|
|
1521
|
+
return;
|
|
1522
|
+
this.highlightedIndex = Math.max(0, Math.min(options.length - 1, index));
|
|
1523
|
+
this.updateOptionFocus();
|
|
1524
|
+
}
|
|
1525
|
+
/** Highlights a group row or an option, opening or closing flyouts to match. */
|
|
1526
|
+
highlightPanelItem(item) {
|
|
1527
|
+
if (typeof item === 'number') {
|
|
1528
|
+
this.highlightedIndex = item;
|
|
1529
|
+
}
|
|
1530
|
+
else {
|
|
1531
|
+
this.highlightedIndex = -1;
|
|
1532
|
+
this.highlightedGroup = item;
|
|
1533
|
+
}
|
|
1534
|
+
this.updateOptionFocus();
|
|
1535
|
+
}
|
|
1536
|
+
expandGroup(entries, optgroup) {
|
|
1537
|
+
var _a;
|
|
1538
|
+
this.flyout.open(optgroup);
|
|
1539
|
+
const first = (_a = findGroup(entries, optgroup)) === null || _a === void 0 ? void 0 : _a.options[0];
|
|
1540
|
+
if (first !== undefined)
|
|
1541
|
+
this.highlightPanelItem(first.index);
|
|
1542
|
+
// Its options render after this change; scroll to the first one then.
|
|
1543
|
+
this.pendingOptionFocus = true;
|
|
1544
|
+
}
|
|
1545
|
+
/** Closes the open group and highlights its row, as a tree's Left does from a child. */
|
|
1546
|
+
collapseToGroup(optgroup) {
|
|
1547
|
+
this.flyout.reset();
|
|
1548
|
+
this.openGroup = null;
|
|
1549
|
+
this.highlightPanelItem(optgroup);
|
|
1550
|
+
// The row renders after this change (in drill-in it replaces the row back); scroll to it then.
|
|
1551
|
+
this.pendingOptionFocus = true;
|
|
1552
|
+
}
|
|
1047
1553
|
/**
|
|
1048
1554
|
* Sets focus on the native input element.
|
|
1049
1555
|
*/
|
|
@@ -1057,8 +1563,9 @@ export class PdsCombobox {
|
|
|
1057
1563
|
}
|
|
1058
1564
|
}
|
|
1059
1565
|
/**
|
|
1060
|
-
* Sets the initial highlighted index when dropdown opens.
|
|
1061
|
-
*
|
|
1566
|
+
* Sets the initial highlighted index when dropdown opens. Highlights the selected option unless
|
|
1567
|
+
* it's disabled. Otherwise highlights the first enabled option, or, in the grouped panel, the
|
|
1568
|
+
* first row with something to choose, or nothing when every option is disabled.
|
|
1062
1569
|
*/
|
|
1063
1570
|
setInitialHighlightedIndex() {
|
|
1064
1571
|
const selectableOptions = this.filteredItems.filter(item => item.tagName === 'OPTION');
|
|
@@ -1066,16 +1573,33 @@ export class PdsCombobox {
|
|
|
1066
1573
|
this.highlightedIndex = -1;
|
|
1067
1574
|
return;
|
|
1068
1575
|
}
|
|
1069
|
-
// If there's a selected option, find its index in the filtered options
|
|
1070
|
-
|
|
1576
|
+
// If there's a selected option, find its index in the filtered options. A disabled one can be
|
|
1577
|
+
// the value, as in a native select, but it isn't highlighted.
|
|
1578
|
+
if (this.selectedOption && !isOptionDisabled(this.selectedOption)) {
|
|
1071
1579
|
const selectedIndex = selectableOptions.findIndex(option => option === this.selectedOption);
|
|
1072
1580
|
if (selectedIndex >= 0) {
|
|
1073
1581
|
this.highlightedIndex = selectedIndex;
|
|
1582
|
+
// In the grouped panel, open on the selection's group, however the dropdown was opened, and
|
|
1583
|
+
// scroll the selection into view once its group has rendered.
|
|
1584
|
+
if (this.showsGroupedPanel) {
|
|
1585
|
+
this.openGroup = parentOptgroupOf(this.selectedOption);
|
|
1586
|
+
// Opening on the selection isn't drilling in, so it doesn't slide.
|
|
1587
|
+
this.drillDirection = null;
|
|
1588
|
+
this.pendingOptionFocus = true;
|
|
1589
|
+
}
|
|
1074
1590
|
return;
|
|
1075
1591
|
}
|
|
1076
1592
|
}
|
|
1077
|
-
//
|
|
1078
|
-
|
|
1593
|
+
// In the grouped panel, the first row with something to choose: a group stays closed until
|
|
1594
|
+
// it's opened.
|
|
1595
|
+
if (this.showsGroupedPanel) {
|
|
1596
|
+
const first = buildPanelEntries(this.filteredItems).find(entry => entry.kind === 'group' ? !isGroupDisabled(entry.group) : !isOptionDisabled(entry.option));
|
|
1597
|
+
this.highlightedIndex = (first === null || first === void 0 ? void 0 : first.kind) === 'option' ? first.index : -1;
|
|
1598
|
+
this.highlightedGroup = (first === null || first === void 0 ? void 0 : first.kind) === 'group' ? first.group.optgroup : null;
|
|
1599
|
+
return;
|
|
1600
|
+
}
|
|
1601
|
+
// No selected option or selected option not in filtered results, highlight the first enabled option
|
|
1602
|
+
this.highlightedIndex = selectableOptions.findIndex(option => !isOptionDisabled(option));
|
|
1079
1603
|
}
|
|
1080
1604
|
/**
|
|
1081
1605
|
* Focus management helper - moves focus to the first option when dropdown opens
|
|
@@ -1111,19 +1635,9 @@ export class PdsCombobox {
|
|
|
1111
1635
|
const selectableOptions = this.filteredItems.filter(item => item.tagName === 'OPTION');
|
|
1112
1636
|
if (selectableOptions.length > 0) {
|
|
1113
1637
|
this.setInitialHighlightedIndex();
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
if (highlightedOption) {
|
|
1118
|
-
optionElements.forEach(option => {
|
|
1119
|
-
option.setAttribute('tabindex', '-1');
|
|
1120
|
-
});
|
|
1121
|
-
highlightedOption.setAttribute('tabindex', '0');
|
|
1122
|
-
highlightedOption.focus();
|
|
1123
|
-
highlightedOption.scrollIntoView({ block: 'nearest', behavior: 'smooth' });
|
|
1124
|
-
}
|
|
1125
|
-
}
|
|
1126
|
-
this.updateAriaActiveDescendant();
|
|
1638
|
+
// By index, through the same path as arrowing: it opens the option's flyout group first
|
|
1639
|
+
// when it isn't rendered, and highlights it once it is.
|
|
1640
|
+
this.updateOptionFocus();
|
|
1127
1641
|
}
|
|
1128
1642
|
}
|
|
1129
1643
|
/**
|
|
@@ -1131,14 +1645,58 @@ export class PdsCombobox {
|
|
|
1131
1645
|
* Note: We don't actually focus the option to prevent focusout events that close the dropdown
|
|
1132
1646
|
*/
|
|
1133
1647
|
updateOptionFocus() {
|
|
1134
|
-
|
|
1648
|
+
var _a;
|
|
1649
|
+
if (this.listboxEl === undefined || this.listboxEl === null)
|
|
1135
1650
|
return;
|
|
1651
|
+
// A row highlighted outright; an option highlighted in a closed group opens it below instead.
|
|
1652
|
+
const groupRow = this.showsGroupedPanel && this.highlightedIndex < 0 ? this.highlightedGroup : null;
|
|
1653
|
+
if (groupRow !== null) {
|
|
1654
|
+
// Arrowing onto another row closes a flyout that hover left open.
|
|
1655
|
+
if (this.effectiveGroupDisplay === 'flyout' && this.openGroup !== null && this.openGroup !== groupRow) {
|
|
1656
|
+
this.flyout.reset();
|
|
1657
|
+
this.openGroup = null;
|
|
1658
|
+
}
|
|
1659
|
+
// Matched by id, not a selector: componentId is consumer text and may not be selector-safe.
|
|
1660
|
+
const id = this.groupDomId(groupRow);
|
|
1661
|
+
(_a = Array.from(this.listboxEl.querySelectorAll('[role="treeitem"]'))
|
|
1662
|
+
.find(row => row.id === id)) === null || _a === void 0 ? void 0 : _a.scrollIntoView({ block: 'nearest' });
|
|
1663
|
+
this.updateAriaActiveDescendant();
|
|
1664
|
+
return;
|
|
1665
|
+
}
|
|
1666
|
+
if (this.highlightedIndex < 0)
|
|
1667
|
+
return;
|
|
1668
|
+
// In the flyout panel only the open group's options are rendered: open the highlighted
|
|
1669
|
+
// option's group, and finish once it has rendered. Through the controller, so a hover timer
|
|
1670
|
+
// left running by the pointer can't close or switch the group the keys just moved into.
|
|
1671
|
+
if (this.showsGroupedPanel) {
|
|
1672
|
+
const selectable = this.filteredItems.filter(item => item.tagName === 'OPTION');
|
|
1673
|
+
const group = parentOptgroupOf(selectable[this.highlightedIndex]);
|
|
1674
|
+
const changed = group !== this.openGroup;
|
|
1675
|
+
if (group !== null) {
|
|
1676
|
+
this.flyout.open(group);
|
|
1677
|
+
}
|
|
1678
|
+
else {
|
|
1679
|
+
this.flyout.reset();
|
|
1680
|
+
this.openGroup = null;
|
|
1681
|
+
}
|
|
1682
|
+
if (changed) {
|
|
1683
|
+
this.pendingOptionFocus = true;
|
|
1684
|
+
return;
|
|
1685
|
+
}
|
|
1686
|
+
}
|
|
1136
1687
|
const optionElements = this.listboxEl.querySelectorAll('[role="option"]');
|
|
1137
|
-
|
|
1688
|
+
// By index, not position: the flyout panel renders only some options.
|
|
1689
|
+
const currentOption = this.listboxEl.querySelector(`[data-option-index="${this.highlightedIndex}"]`);
|
|
1138
1690
|
if (currentOption) {
|
|
1139
1691
|
// Check if any option currently has focus OR if we're in arrow-key navigation mode
|
|
1140
1692
|
const hasOptionFocus = Array.from(optionElements).some(el => el === document.activeElement);
|
|
1141
|
-
|
|
1693
|
+
// The panel's search field keeps focus and points at the option with aria-activedescendant,
|
|
1694
|
+
// and so does the trigger over the grouped panel, whose group rows can't take focus and
|
|
1695
|
+
// whose options are hidden while a flyout is placed.
|
|
1696
|
+
const shouldFocusOption = !this.usesBodyPortal &&
|
|
1697
|
+
!this.usesPanelSearch &&
|
|
1698
|
+
!this.showsGroupedPanel &&
|
|
1699
|
+
(hasOptionFocus || this.isArrowKeyNavigationMode);
|
|
1142
1700
|
if (shouldFocusOption) {
|
|
1143
1701
|
optionElements.forEach(option => {
|
|
1144
1702
|
option.setAttribute('tabindex', '-1');
|
|
@@ -1146,21 +1704,64 @@ export class PdsCombobox {
|
|
|
1146
1704
|
currentOption.setAttribute('tabindex', '0');
|
|
1147
1705
|
currentOption.focus();
|
|
1148
1706
|
}
|
|
1149
|
-
// Always scroll the option into view
|
|
1150
|
-
currentOption.
|
|
1707
|
+
// Always scroll the option into view; in a flyout, by scrolling the flyout alone.
|
|
1708
|
+
const flyout = currentOption.closest('.pds-combobox__flyout');
|
|
1709
|
+
if (flyout) {
|
|
1710
|
+
this.flyout.reveal(flyout, currentOption);
|
|
1711
|
+
}
|
|
1712
|
+
else {
|
|
1713
|
+
currentOption.scrollIntoView({ block: 'nearest', behavior: 'smooth' });
|
|
1714
|
+
}
|
|
1151
1715
|
}
|
|
1152
1716
|
// Always update aria-activedescendant on the trigger element
|
|
1153
1717
|
this.updateAriaActiveDescendant();
|
|
1154
1718
|
}
|
|
1719
|
+
/** The highlighted group row in the grouped panel, or null while an option is highlighted. */
|
|
1720
|
+
get highlightedGroupRow() {
|
|
1721
|
+
if (!this.showsGroupedPanel)
|
|
1722
|
+
return null;
|
|
1723
|
+
if (this.highlightedIndex < 0)
|
|
1724
|
+
return this.highlightedGroup;
|
|
1725
|
+
// An option left highlighted in a flyout that has since closed shows as its group's row.
|
|
1726
|
+
const current = this.currentPanelItem();
|
|
1727
|
+
return typeof current === 'number' ? null : current;
|
|
1728
|
+
}
|
|
1155
1729
|
/**
|
|
1156
|
-
*
|
|
1730
|
+
* The id of the highlighted option or group row, only while it's rendered. In the flyout panel
|
|
1731
|
+
* an option in a closed group isn't in the DOM, and drilled into a group the other groups' rows
|
|
1732
|
+
* aren't; `aria-activedescendant` must not point at a missing element.
|
|
1157
1733
|
*/
|
|
1734
|
+
get activeDescendantId() {
|
|
1735
|
+
if (!this.isOpen)
|
|
1736
|
+
return undefined;
|
|
1737
|
+
const groupRow = this.highlightedGroupRow;
|
|
1738
|
+
if (groupRow !== null) {
|
|
1739
|
+
const drilledIntoAnother = this.effectiveGroupDisplay === 'drill-in' && this.openGroup !== null && this.openGroup !== groupRow;
|
|
1740
|
+
return drilledIntoAnother ? undefined : this.groupDomId(groupRow);
|
|
1741
|
+
}
|
|
1742
|
+
if (this.highlightedIndex < 0)
|
|
1743
|
+
return undefined;
|
|
1744
|
+
if (this.showsGroupedPanel) {
|
|
1745
|
+
const selectable = this.filteredItems.filter(item => item.tagName === 'OPTION');
|
|
1746
|
+
const group = parentOptgroupOf(selectable[this.highlightedIndex]);
|
|
1747
|
+
if (group !== null && group !== this.openGroup)
|
|
1748
|
+
return undefined;
|
|
1749
|
+
}
|
|
1750
|
+
return this.optionDomId(this.highlightedIndex);
|
|
1751
|
+
}
|
|
1752
|
+
/** Points the focused element's aria-activedescendant at the highlighted option, or clears it. */
|
|
1158
1753
|
updateAriaActiveDescendant() {
|
|
1159
|
-
|
|
1160
|
-
|
|
1754
|
+
// With panel search, the element with focus owns it, not the trigger: the search field, or
|
|
1755
|
+
// the list while a drilled-in group hides the field.
|
|
1756
|
+
const target = this.usesPanelSearch ? (this.hidesPanelSearch ? this.panelTreeEl : this.panelSearchEl) : this.triggerEl;
|
|
1757
|
+
if (!target)
|
|
1758
|
+
return;
|
|
1759
|
+
const id = this.activeDescendantId;
|
|
1760
|
+
if (id !== undefined) {
|
|
1761
|
+
target.setAttribute('aria-activedescendant', id);
|
|
1161
1762
|
}
|
|
1162
|
-
else
|
|
1163
|
-
|
|
1763
|
+
else {
|
|
1764
|
+
target.removeAttribute('aria-activedescendant');
|
|
1164
1765
|
}
|
|
1165
1766
|
}
|
|
1166
1767
|
/**
|
|
@@ -1196,6 +1797,17 @@ export class PdsCombobox {
|
|
|
1196
1797
|
this.pdsComboboxChange.emit({ value: '' });
|
|
1197
1798
|
}
|
|
1198
1799
|
}
|
|
1800
|
+
// Group rows in the flyout panel carry their group's index, as options carry theirs.
|
|
1801
|
+
groupFromEvent(event) {
|
|
1802
|
+
var _a, _b;
|
|
1803
|
+
const index = Number(event.currentTarget.getAttribute('data-group-index'));
|
|
1804
|
+
return (_b = (_a = this.renderedGroups[index]) === null || _a === void 0 ? void 0 : _a.optgroup) !== null && _b !== void 0 ? _b : null;
|
|
1805
|
+
}
|
|
1806
|
+
highlightGroupRowByPointer(group) {
|
|
1807
|
+
this.highlightedIndex = -1;
|
|
1808
|
+
this.highlightedGroup = group;
|
|
1809
|
+
this.keyboardNavigating = false;
|
|
1810
|
+
}
|
|
1199
1811
|
// Get the label of the selected option
|
|
1200
1812
|
get selectedLabel() {
|
|
1201
1813
|
return this.displayText || '';
|
|
@@ -1308,7 +1920,24 @@ export class PdsCombobox {
|
|
|
1308
1920
|
// Fallback: Use component props
|
|
1309
1921
|
return this.chipDot;
|
|
1310
1922
|
}
|
|
1923
|
+
/**
|
|
1924
|
+
* With `async-url`, fetches when the button trigger opens: the first page if nothing has loaded.
|
|
1925
|
+
* The panel's search field opens empty, so results left from the last search are refetched for
|
|
1926
|
+
* an empty query.
|
|
1927
|
+
*/
|
|
1928
|
+
fetchAsyncOptionsOnOpen() {
|
|
1929
|
+
if (!this.asyncUrl)
|
|
1930
|
+
return;
|
|
1931
|
+
if (this.usesPanelSearch && (this.internalOptions.length === 0 || this.lastFetchedQuery !== '')) {
|
|
1932
|
+
this.debouncedFetchAsyncOptions('', 1);
|
|
1933
|
+
}
|
|
1934
|
+
else if (this.internalOptions.length === 0) {
|
|
1935
|
+
this.debouncedFetchAsyncOptions(this.displayText, 1);
|
|
1936
|
+
}
|
|
1937
|
+
}
|
|
1311
1938
|
handleOptionClick(option) {
|
|
1939
|
+
if (isOptionDisabled(option))
|
|
1940
|
+
return;
|
|
1312
1941
|
// Update reactive state - single source of truth
|
|
1313
1942
|
// The @Watch('selectedOption') will handle displayText, value, and form internals
|
|
1314
1943
|
this.setSelectedOption(option);
|
|
@@ -1322,33 +1951,242 @@ export class PdsCombobox {
|
|
|
1322
1951
|
}
|
|
1323
1952
|
const hasSlottedEmpty = !this.usesBodyPortal && !!this.el.querySelector('[slot="empty"]');
|
|
1324
1953
|
const hasSlottedLoading = !this.usesBodyPortal && !!this.el.querySelector('[slot="loading"]');
|
|
1325
|
-
let optionIndex = 0;
|
|
1326
1954
|
const selectableOptions = this.filteredItems.filter(item => item.tagName === 'OPTION');
|
|
1327
|
-
|
|
1955
|
+
const withSearch = this.usesPanelSearch;
|
|
1956
|
+
// While a drilled-in group hides the search field, the list takes focus in its place.
|
|
1957
|
+
const listTakesFocus = this.hidesPanelSearch;
|
|
1958
|
+
const list = (h("ul", { key: "panel-list", class: {
|
|
1959
|
+
'pds-combobox__listbox': !withSearch,
|
|
1960
|
+
'pds-combobox__listbox-options': withSearch,
|
|
1961
|
+
'pds-combobox__listbox-options--drilled-in': listTakesFocus,
|
|
1962
|
+
'pds-combobox__listbox--grouped': this.groupDisplay !== 'inline',
|
|
1963
|
+
'pds-combobox__listbox--drill-in': this.drillDirection === 'in',
|
|
1964
|
+
'pds-combobox__listbox--drill-out': this.drillDirection === 'out',
|
|
1965
|
+
}, onAnimationEnd: this.onDrillAnimationEnd, role: this.showsGroupedPanel ? 'tree' : 'listbox', id: this.listboxId, "aria-label": this.label || 'Options', "aria-multiselectable": "false",
|
|
1966
|
+
// Focusable but out of the tab order with panel search, so it can take focus when a
|
|
1967
|
+
// drilled-in group hides the field. Dropping it while focused would blur the list and close.
|
|
1968
|
+
tabIndex: withSearch ? -1 : undefined, "aria-activedescendant": listTakesFocus ? this.activeDescendantId : undefined, onKeyDown: withSearch ? this.onPanelTreeKeyDown : undefined, ref: el => {
|
|
1969
|
+
if (withSearch)
|
|
1970
|
+
this.panelTreeEl = el;
|
|
1971
|
+
else
|
|
1972
|
+
this.listboxEl = el;
|
|
1973
|
+
}, 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" })))));
|
|
1974
|
+
if (!withSearch)
|
|
1975
|
+
return list;
|
|
1976
|
+
// The search field sits above the list; the wrapper is what's positioned and portaled.
|
|
1977
|
+
return (h("div", { class: "pds-combobox__listbox pds-combobox__listbox--with-search", ref: el => (this.listboxEl = el), onMouseDown: this.onPanelMouseDown,
|
|
1978
|
+
// Portaled, the panel sits outside .pds-combobox, so its focusout wouldn't reach that handler.
|
|
1979
|
+
onFocusout: this.usesBodyPortal ? this.onComboboxFocusOut : undefined }, !listTakesFocus && this.renderPanelSearch(), list));
|
|
1980
|
+
}
|
|
1981
|
+
/**
|
|
1982
|
+
* The listbox's items. Each optgroup's options sit in a `group` named for it, as in
|
|
1983
|
+
* `pds-multiselect`, so assistive tech announces the group on entering it; a `pds-text` label
|
|
1984
|
+
* stays a caption above the options that follow it.
|
|
1985
|
+
*/
|
|
1986
|
+
renderListboxItems(setSize) {
|
|
1987
|
+
const rendered = [];
|
|
1988
|
+
let optionIndex = 0;
|
|
1989
|
+
let group = null;
|
|
1990
|
+
const closeGroup = () => {
|
|
1991
|
+
if (group === null)
|
|
1992
|
+
return;
|
|
1993
|
+
const { optgroup, key, options, members } = group;
|
|
1994
|
+
const groupIcon = groupIconOf(optgroup);
|
|
1995
|
+
// As in the grouped displays: disabled when there's nothing left in it to choose.
|
|
1996
|
+
const disabled = members.length > 0 && members.every(member => isOptionDisabled(member));
|
|
1997
|
+
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 && (
|
|
1998
|
+
// `name`, not `icon`: `icon` also loads URLs and data: SVGs, unsanitized.
|
|
1999
|
+
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)));
|
|
2000
|
+
group = null;
|
|
2001
|
+
};
|
|
2002
|
+
this.filteredItems.forEach((item, itemIdx) => {
|
|
1328
2003
|
if (item.tagName === 'OPTGROUP') {
|
|
1329
|
-
|
|
1330
|
-
|
|
2004
|
+
closeGroup();
|
|
2005
|
+
group = { optgroup: item, key: `optgroup-${itemIdx}`, options: [], members: [] };
|
|
1331
2006
|
}
|
|
1332
2007
|
else if (item.tagName === 'PDS-TEXT') {
|
|
1333
|
-
|
|
1334
|
-
|
|
2008
|
+
closeGroup();
|
|
2009
|
+
rendered.push(h("li", { key: `pds-text-${itemIdx}`, class: "pds-combobox__group-label", role: "presentation" }, item.textContent));
|
|
1335
2010
|
}
|
|
1336
2011
|
else if (item.tagName === 'OPTION') {
|
|
1337
2012
|
const option = item;
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
const
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
2013
|
+
if (group !== null && parentOptgroupOf(option) !== group.optgroup)
|
|
2014
|
+
closeGroup();
|
|
2015
|
+
const rendering = this.renderOption(option, optionIndex, { posinset: optionIndex + 1, setsize: setSize });
|
|
2016
|
+
optionIndex++;
|
|
2017
|
+
if (group !== null) {
|
|
2018
|
+
group.options.push(rendering);
|
|
2019
|
+
group.members.push(option);
|
|
2020
|
+
}
|
|
2021
|
+
else {
|
|
2022
|
+
rendered.push(rendering);
|
|
2023
|
+
}
|
|
1349
2024
|
}
|
|
1350
|
-
|
|
1351
|
-
|
|
2025
|
+
});
|
|
2026
|
+
closeGroup();
|
|
2027
|
+
return rendered;
|
|
2028
|
+
}
|
|
2029
|
+
/** `panelSearch` applies to the triggers that can't be typed into. */
|
|
2030
|
+
get usesPanelSearch() {
|
|
2031
|
+
return this.panelSearch && this.trigger !== 'input';
|
|
2032
|
+
}
|
|
2033
|
+
/** `groupDisplay`, with `flyout` drilling in when there's no room beside the dropdown. */
|
|
2034
|
+
get effectiveGroupDisplay() {
|
|
2035
|
+
return this.groupDisplay === 'flyout' && this.flyoutFallback ? 'drill-in' : this.groupDisplay;
|
|
2036
|
+
}
|
|
2037
|
+
/**
|
|
2038
|
+
* The popup's role, for the triggers' `aria-haspopup`: a `tree` while the grouped panel shows
|
|
2039
|
+
* groups, and a `listbox` of options otherwise, search results included.
|
|
2040
|
+
*/
|
|
2041
|
+
get popupRole() {
|
|
2042
|
+
return this.showsGroupedPanel ? 'tree' : 'listbox';
|
|
2043
|
+
}
|
|
2044
|
+
/**
|
|
2045
|
+
* The input trigger's `aria-haspopup`. While closed it names what opening shows: the full list,
|
|
2046
|
+
* so the grouped panel in a grouped display, even though the input still holds the selection's
|
|
2047
|
+
* label.
|
|
2048
|
+
*/
|
|
2049
|
+
get inputPopupRole() {
|
|
2050
|
+
if (this.isOpen)
|
|
2051
|
+
return this.popupRole;
|
|
2052
|
+
return this.effectiveGroupDisplay === 'inline' ? 'listbox' : 'tree';
|
|
2053
|
+
}
|
|
2054
|
+
/**
|
|
2055
|
+
* The button and chip triggers' `aria-haspopup`. With panel search the trigger opens the panel,
|
|
2056
|
+
* which starts as a tree in a grouped display, so typing in the panel doesn't change it.
|
|
2057
|
+
*/
|
|
2058
|
+
get triggerPopupRole() {
|
|
2059
|
+
if (!this.usesPanelSearch)
|
|
2060
|
+
return this.popupRole;
|
|
2061
|
+
return this.groupDisplay === 'inline' ? 'listbox' : 'tree';
|
|
2062
|
+
}
|
|
2063
|
+
/**
|
|
2064
|
+
* Drilled into a group with panel search: the group's row back takes the search field's place,
|
|
2065
|
+
* since one group's options don't need searching. Typing searches the whole list again.
|
|
2066
|
+
*/
|
|
2067
|
+
get hidesPanelSearch() {
|
|
2068
|
+
return this.usesPanelSearch && this.showsGroupedPanel && this.effectiveGroupDisplay === 'drill-in' && this.openGroup !== null;
|
|
2069
|
+
}
|
|
2070
|
+
/** The grouped panel is showing groups rather than search results. */
|
|
2071
|
+
get showsGroupedPanel() {
|
|
2072
|
+
if (this.effectiveGroupDisplay === 'inline')
|
|
2073
|
+
return false;
|
|
2074
|
+
const searching = this.usesPanelSearch
|
|
2075
|
+
? this.panelQuery !== ''
|
|
2076
|
+
: this.mode === 'filter' && !this.expandFilterListWhileOpen && this.displayText !== '';
|
|
2077
|
+
return !searching;
|
|
2078
|
+
}
|
|
2079
|
+
setPanelQuery(query) {
|
|
2080
|
+
this.panelQuery = query;
|
|
2081
|
+
this.clearExpandFilterList();
|
|
2082
|
+
this.filterOptions();
|
|
2083
|
+
this.pdsComboboxSearch.emit({ query: this.panelQuery });
|
|
2084
|
+
if (this.asyncUrl !== undefined && this.asyncUrl !== '') {
|
|
2085
|
+
this.debouncedFetchAsyncOptions(this.panelQuery, 1);
|
|
2086
|
+
}
|
|
2087
|
+
// The list changes size, so place the dropdown again, as typing in the input trigger does.
|
|
2088
|
+
setTimeout(() => this.openDropdownPositioning(), 0);
|
|
2089
|
+
}
|
|
2090
|
+
/** What's being searched: the panel's field, or the input trigger's text. */
|
|
2091
|
+
get activeQuery() {
|
|
2092
|
+
return this.usesPanelSearch ? this.panelQuery : this.displayText;
|
|
2093
|
+
}
|
|
2094
|
+
// Tab closes the dropdown and lands on the trigger, as Escape does: the focused field or list is
|
|
2095
|
+
// about to unmount, so the browser can't tab on from it. The next Tab continues from the trigger.
|
|
2096
|
+
handlePanelTab(event) {
|
|
2097
|
+
if (event.key !== 'Tab')
|
|
2098
|
+
return false;
|
|
2099
|
+
event.preventDefault();
|
|
2100
|
+
this.handleKeyDown(event);
|
|
2101
|
+
this.restoreFocusToTrigger();
|
|
2102
|
+
return true;
|
|
2103
|
+
}
|
|
2104
|
+
/** Returns from a drilled-in group to the group list; false when not drilled in. */
|
|
2105
|
+
leaveDrilledInGroup() {
|
|
2106
|
+
if (!this.showsGroupedPanel || this.effectiveGroupDisplay !== 'drill-in' || this.openGroup === null)
|
|
2107
|
+
return false;
|
|
2108
|
+
this.collapseToGroup(this.openGroup);
|
|
2109
|
+
return true;
|
|
2110
|
+
}
|
|
2111
|
+
renderPanelSearch() {
|
|
2112
|
+
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 })));
|
|
2113
|
+
}
|
|
2114
|
+
/**
|
|
2115
|
+
* An option, as a listbox `option` or, given a tree `level`, a `treeitem`. `posinset` and
|
|
2116
|
+
* `setsize` place it among its siblings.
|
|
2117
|
+
*/
|
|
2118
|
+
renderOption(option, index, { posinset, setsize, level }) {
|
|
2119
|
+
const isSelected = this.isOptionSelected(option);
|
|
2120
|
+
const isHighlighted = this.highlightedIndex === index;
|
|
2121
|
+
const isLayout = this.isOptionLayout(option);
|
|
2122
|
+
const isChip = this.isOptionChip(option);
|
|
2123
|
+
const isDisabled = isOptionDisabled(option);
|
|
2124
|
+
const tree = level !== undefined;
|
|
2125
|
+
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: {
|
|
2126
|
+
'pds-combobox__option': true,
|
|
2127
|
+
'pds-combobox__option--highlighted': isHighlighted,
|
|
2128
|
+
'pds-combobox__option--layout': isLayout,
|
|
2129
|
+
'pds-combobox__option--chip': isChip,
|
|
2130
|
+
'pds-combobox__option--disabled': isDisabled,
|
|
2131
|
+
}, "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" })));
|
|
2132
|
+
}
|
|
2133
|
+
/**
|
|
2134
|
+
* `flyout`: one row per group, its options in a flyout beside it. `drill-in`: the same rows, and
|
|
2135
|
+
* an opened group replaces them with its row, drawn as a row back, above its options. Either way
|
|
2136
|
+
* it's a tree: the rows and ungrouped options are level 1, a group's options level 2.
|
|
2137
|
+
*/
|
|
2138
|
+
renderGroupedPanel() {
|
|
2139
|
+
const entries = buildPanelEntries(this.filteredItems);
|
|
2140
|
+
const setsize = entries.length;
|
|
2141
|
+
if (this.effectiveGroupDisplay === 'drill-in' && this.openGroup !== null) {
|
|
2142
|
+
const position = entries.findIndex(entry => entry.kind === 'group' && entry.group.optgroup === this.openGroup);
|
|
2143
|
+
const open = entries[position];
|
|
2144
|
+
if ((open === null || open === void 0 ? void 0 : open.kind) === 'group')
|
|
2145
|
+
return this.renderGroupBackRow(open.group, { posinset: position + 1, setsize });
|
|
2146
|
+
}
|
|
2147
|
+
this.renderedGroups = [];
|
|
2148
|
+
return entries.map((entry, position) => {
|
|
2149
|
+
const placement = { posinset: position + 1, setsize };
|
|
2150
|
+
if (entry.kind === 'option')
|
|
2151
|
+
return this.renderOption(entry.option, entry.index, Object.assign(Object.assign({}, placement), { level: 1 }));
|
|
2152
|
+
this.renderedGroups.push(entry.group);
|
|
2153
|
+
return this.renderGroupRow(entry.group, this.renderedGroups.length - 1, placement);
|
|
2154
|
+
});
|
|
2155
|
+
}
|
|
2156
|
+
/** A group's options, as its children in the tree. */
|
|
2157
|
+
renderGroupOptions(group) {
|
|
2158
|
+
return group.options.map(({ option, index }, position) => this.renderOption(option, index, { posinset: position + 1, setsize: group.options.length, level: 2 }));
|
|
2159
|
+
}
|
|
2160
|
+
/**
|
|
2161
|
+
* Drilled into a group: its treeitem, expanded. Its row reads as a way back ("Back: Tag") and
|
|
2162
|
+
* leads its options.
|
|
2163
|
+
*/
|
|
2164
|
+
renderGroupBackRow(group, { posinset, setsize }) {
|
|
2165
|
+
const id = this.groupDomId(group.optgroup);
|
|
2166
|
+
const disabled = isGroupDisabled(group);
|
|
2167
|
+
return (h("li", { key: "group-back", id: id, class: {
|
|
2168
|
+
'pds-combobox__group-back': true,
|
|
2169
|
+
'pds-combobox__group-back--disabled': disabled,
|
|
2170
|
+
'pds-combobox__group-back--highlighted': this.highlightedGroupRow === group.optgroup,
|
|
2171
|
+
'pds-combobox__group-back--keyboard': this.keyboardNavigating && this.highlightedGroupRow === group.optgroup,
|
|
2172
|
+
}, 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))));
|
|
2173
|
+
}
|
|
2174
|
+
renderGroupRow(group, groupIndex, { posinset, setsize }) {
|
|
2175
|
+
const flyout = this.effectiveGroupDisplay === 'flyout';
|
|
2176
|
+
const isOpen = flyout && this.openGroup === group.optgroup;
|
|
2177
|
+
const hasSelection = group.options.some(({ option }) => this.isOptionSelected(option));
|
|
2178
|
+
const disabled = isGroupDisabled(group);
|
|
2179
|
+
const id = this.groupDomId(group.optgroup);
|
|
2180
|
+
return (h("li", { key: `group-${groupIndex}`, id: id, class: {
|
|
2181
|
+
'pds-combobox__group-row': true,
|
|
2182
|
+
'pds-combobox__group-row--open': isOpen,
|
|
2183
|
+
'pds-combobox__group-row--has-selection': hasSelection,
|
|
2184
|
+
'pds-combobox__group-row--highlighted': this.highlightedGroupRow === group.optgroup,
|
|
2185
|
+
'pds-combobox__group-row--keyboard': this.keyboardNavigating && this.highlightedGroupRow === group.optgroup,
|
|
2186
|
+
'pds-combobox__group-row--disabled': disabled,
|
|
2187
|
+
}, 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 && (
|
|
2188
|
+
// `name`, not `icon`: `icon` also loads URLs and data: SVGs, unsanitized.
|
|
2189
|
+
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)))));
|
|
1352
2190
|
}
|
|
1353
2191
|
// Helper method to render the caret icon
|
|
1354
2192
|
renderCaretIcon() {
|
|
@@ -1485,13 +2323,13 @@ export class PdsCombobox {
|
|
|
1485
2323
|
]
|
|
1486
2324
|
.filter(Boolean)
|
|
1487
2325
|
.join(' ');
|
|
1488
|
-
return (h(Host, { key: '
|
|
2326
|
+
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 => {
|
|
1489
2327
|
this.inputEl = el;
|
|
1490
2328
|
this.triggerEl = el;
|
|
1491
2329
|
}, class: {
|
|
1492
2330
|
'pds-combobox__input': true,
|
|
1493
2331
|
'pds-combobox__input--invalid': this.isInvalid(),
|
|
1494
|
-
}, 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.
|
|
2332
|
+
}, 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 : '')))));
|
|
1495
2333
|
}
|
|
1496
2334
|
static get is() { return "pds-combobox"; }
|
|
1497
2335
|
static get encapsulation() { return "shadow"; }
|
|
@@ -1700,6 +2538,98 @@ export class PdsCombobox {
|
|
|
1700
2538
|
"attribute": "dropdown-mount",
|
|
1701
2539
|
"defaultValue": "'host'"
|
|
1702
2540
|
},
|
|
2541
|
+
"drillInBackLabel": {
|
|
2542
|
+
"type": "string",
|
|
2543
|
+
"mutable": false,
|
|
2544
|
+
"complexType": {
|
|
2545
|
+
"original": "string",
|
|
2546
|
+
"resolved": "string",
|
|
2547
|
+
"references": {}
|
|
2548
|
+
},
|
|
2549
|
+
"required": false,
|
|
2550
|
+
"optional": false,
|
|
2551
|
+
"docs": {
|
|
2552
|
+
"tags": [{
|
|
2553
|
+
"name": "defaultValue",
|
|
2554
|
+
"text": "'Back'"
|
|
2555
|
+
}],
|
|
2556
|
+
"text": "Accessible prefix for the row that returns to the group list when `group-display` is\n`drill-in`, read before the open group's label. Pass a translated string to localize it; defaults to English."
|
|
2557
|
+
},
|
|
2558
|
+
"getter": false,
|
|
2559
|
+
"setter": false,
|
|
2560
|
+
"reflect": false,
|
|
2561
|
+
"attribute": "drill-in-back-label",
|
|
2562
|
+
"defaultValue": "'Back'"
|
|
2563
|
+
},
|
|
2564
|
+
"flyoutMaxWidth": {
|
|
2565
|
+
"type": "string",
|
|
2566
|
+
"mutable": false,
|
|
2567
|
+
"complexType": {
|
|
2568
|
+
"original": "string",
|
|
2569
|
+
"resolved": "string",
|
|
2570
|
+
"references": {}
|
|
2571
|
+
},
|
|
2572
|
+
"required": false,
|
|
2573
|
+
"optional": false,
|
|
2574
|
+
"docs": {
|
|
2575
|
+
"tags": [{
|
|
2576
|
+
"name": "default",
|
|
2577
|
+
"text": "'380px'"
|
|
2578
|
+
}],
|
|
2579
|
+
"text": "Maximum width of a group's flyout when `group-display` is `flyout`. Any valid CSS width value."
|
|
2580
|
+
},
|
|
2581
|
+
"getter": false,
|
|
2582
|
+
"setter": false,
|
|
2583
|
+
"reflect": false,
|
|
2584
|
+
"attribute": "flyout-max-width",
|
|
2585
|
+
"defaultValue": "'380px'"
|
|
2586
|
+
},
|
|
2587
|
+
"flyoutMinWidth": {
|
|
2588
|
+
"type": "string",
|
|
2589
|
+
"mutable": false,
|
|
2590
|
+
"complexType": {
|
|
2591
|
+
"original": "string",
|
|
2592
|
+
"resolved": "string",
|
|
2593
|
+
"references": {}
|
|
2594
|
+
},
|
|
2595
|
+
"required": false,
|
|
2596
|
+
"optional": false,
|
|
2597
|
+
"docs": {
|
|
2598
|
+
"tags": [{
|
|
2599
|
+
"name": "default",
|
|
2600
|
+
"text": "'280px'"
|
|
2601
|
+
}],
|
|
2602
|
+
"text": "Minimum width of a group's flyout when `group-display` is `flyout`. Any valid CSS width value.\nThe flyout is as wide as its options, between this and `flyout-max-width`."
|
|
2603
|
+
},
|
|
2604
|
+
"getter": false,
|
|
2605
|
+
"setter": false,
|
|
2606
|
+
"reflect": false,
|
|
2607
|
+
"attribute": "flyout-min-width",
|
|
2608
|
+
"defaultValue": "'280px'"
|
|
2609
|
+
},
|
|
2610
|
+
"groupDisplay": {
|
|
2611
|
+
"type": "string",
|
|
2612
|
+
"mutable": false,
|
|
2613
|
+
"complexType": {
|
|
2614
|
+
"original": "'inline' | 'flyout' | 'drill-in'",
|
|
2615
|
+
"resolved": "\"drill-in\" | \"flyout\" | \"inline\"",
|
|
2616
|
+
"references": {}
|
|
2617
|
+
},
|
|
2618
|
+
"required": false,
|
|
2619
|
+
"optional": false,
|
|
2620
|
+
"docs": {
|
|
2621
|
+
"tags": [{
|
|
2622
|
+
"name": "default",
|
|
2623
|
+
"text": "'inline'"
|
|
2624
|
+
}],
|
|
2625
|
+
"text": "How option groups (`<optgroup>`, or the `group` field of `options`) are shown in the dropdown.\n`inline` lists each group's label above its options. `flyout` lists the groups, and opens a\ngroup's options in a panel beside it on hover or click; while searching, the matching options\nare listed under their group labels, and search also matches group labels. `flyout` groups\nby `<optgroup>` (or `group`) only: options under a `<pds-text>` heading are listed ungrouped.\n`drill-in` lists the groups too, but a click replaces the list with that group's options and a\nrow back to the groups; use it where nothing can open beside the dropdown, such as a side\npanel. `flyout` falls back to `drill-in` when there is no room for a flyout on either side."
|
|
2626
|
+
},
|
|
2627
|
+
"getter": false,
|
|
2628
|
+
"setter": false,
|
|
2629
|
+
"reflect": false,
|
|
2630
|
+
"attribute": "group-display",
|
|
2631
|
+
"defaultValue": "'inline'"
|
|
2632
|
+
},
|
|
1703
2633
|
"helperMessage": {
|
|
1704
2634
|
"type": "string",
|
|
1705
2635
|
"mutable": false,
|
|
@@ -1819,6 +2749,29 @@ export class PdsCombobox {
|
|
|
1819
2749
|
"attribute": "mode",
|
|
1820
2750
|
"defaultValue": "'filter'"
|
|
1821
2751
|
},
|
|
2752
|
+
"panelSearch": {
|
|
2753
|
+
"type": "boolean",
|
|
2754
|
+
"mutable": false,
|
|
2755
|
+
"complexType": {
|
|
2756
|
+
"original": "boolean",
|
|
2757
|
+
"resolved": "boolean",
|
|
2758
|
+
"references": {}
|
|
2759
|
+
},
|
|
2760
|
+
"required": false,
|
|
2761
|
+
"optional": false,
|
|
2762
|
+
"docs": {
|
|
2763
|
+
"tags": [{
|
|
2764
|
+
"name": "default",
|
|
2765
|
+
"text": "false"
|
|
2766
|
+
}],
|
|
2767
|
+
"text": "Shows a search field at the top of the dropdown for the `button` and `chip` triggers, which\ncan't be typed into. Search filters the options the same way typing in the `input` trigger\ndoes; in a grouped display it also matches group labels."
|
|
2768
|
+
},
|
|
2769
|
+
"getter": false,
|
|
2770
|
+
"setter": false,
|
|
2771
|
+
"reflect": false,
|
|
2772
|
+
"attribute": "panel-search",
|
|
2773
|
+
"defaultValue": "false"
|
|
2774
|
+
},
|
|
1822
2775
|
"placeholder": {
|
|
1823
2776
|
"type": "string",
|
|
1824
2777
|
"mutable": false,
|
|
@@ -1838,6 +2791,52 @@ export class PdsCombobox {
|
|
|
1838
2791
|
"reflect": false,
|
|
1839
2792
|
"attribute": "placeholder"
|
|
1840
2793
|
},
|
|
2794
|
+
"searchOptionsLabel": {
|
|
2795
|
+
"type": "string",
|
|
2796
|
+
"mutable": false,
|
|
2797
|
+
"complexType": {
|
|
2798
|
+
"original": "string",
|
|
2799
|
+
"resolved": "string",
|
|
2800
|
+
"references": {}
|
|
2801
|
+
},
|
|
2802
|
+
"required": false,
|
|
2803
|
+
"optional": false,
|
|
2804
|
+
"docs": {
|
|
2805
|
+
"tags": [{
|
|
2806
|
+
"name": "defaultValue",
|
|
2807
|
+
"text": "'Search options'"
|
|
2808
|
+
}],
|
|
2809
|
+
"text": "Accessible label for the search input inside the dropdown panel (`panel-search`). Pass a translated string to localize it; defaults to English."
|
|
2810
|
+
},
|
|
2811
|
+
"getter": false,
|
|
2812
|
+
"setter": false,
|
|
2813
|
+
"reflect": false,
|
|
2814
|
+
"attribute": "search-options-label",
|
|
2815
|
+
"defaultValue": "'Search options'"
|
|
2816
|
+
},
|
|
2817
|
+
"searchPlaceholder": {
|
|
2818
|
+
"type": "string",
|
|
2819
|
+
"mutable": false,
|
|
2820
|
+
"complexType": {
|
|
2821
|
+
"original": "string",
|
|
2822
|
+
"resolved": "string",
|
|
2823
|
+
"references": {}
|
|
2824
|
+
},
|
|
2825
|
+
"required": false,
|
|
2826
|
+
"optional": false,
|
|
2827
|
+
"docs": {
|
|
2828
|
+
"tags": [{
|
|
2829
|
+
"name": "defaultValue",
|
|
2830
|
+
"text": "'Find...'"
|
|
2831
|
+
}],
|
|
2832
|
+
"text": "Placeholder text for the search input inside the dropdown panel (`panel-search`). Pass a translated string to localize it; defaults to English."
|
|
2833
|
+
},
|
|
2834
|
+
"getter": false,
|
|
2835
|
+
"setter": false,
|
|
2836
|
+
"reflect": false,
|
|
2837
|
+
"attribute": "search-placeholder",
|
|
2838
|
+
"defaultValue": "'Find...'"
|
|
2839
|
+
},
|
|
1841
2840
|
"trigger": {
|
|
1842
2841
|
"type": "string",
|
|
1843
2842
|
"mutable": false,
|
|
@@ -2200,6 +3199,12 @@ export class PdsCombobox {
|
|
|
2200
3199
|
"filteredItems": {},
|
|
2201
3200
|
"highlightedIndex": {},
|
|
2202
3201
|
"isOpen": {},
|
|
3202
|
+
"openGroup": {},
|
|
3203
|
+
"drillDirection": {},
|
|
3204
|
+
"highlightedGroup": {},
|
|
3205
|
+
"keyboardNavigating": {},
|
|
3206
|
+
"panelQuery": {},
|
|
3207
|
+
"flyoutFallback": {},
|
|
2203
3208
|
"selectedOption": {},
|
|
2204
3209
|
"selectedOptionLayoutContent": {},
|
|
2205
3210
|
"selectedOptionChipProps": {},
|
|
@@ -2328,6 +3333,15 @@ export class PdsCombobox {
|
|
|
2328
3333
|
static get elementRef() { return "el"; }
|
|
2329
3334
|
static get watchers() {
|
|
2330
3335
|
return [{
|
|
3336
|
+
"propName": "groupDisplay",
|
|
3337
|
+
"methodName": "groupDisplayChanged"
|
|
3338
|
+
}, {
|
|
3339
|
+
"propName": "openGroup",
|
|
3340
|
+
"methodName": "openGroupChanged"
|
|
3341
|
+
}, {
|
|
3342
|
+
"propName": "flyoutFallback",
|
|
3343
|
+
"methodName": "flyoutFallbackChanged"
|
|
3344
|
+
}, {
|
|
2331
3345
|
"propName": "isOpen",
|
|
2332
3346
|
"methodName": "isOpenChanged"
|
|
2333
3347
|
}, {
|