@pine-ds/core 3.25.0 → 3.25.1

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.
@@ -46,6 +46,8 @@ export class PdsCombobox {
46
46
  this.hideLabel = false;
47
47
  /**
48
48
  * Determines the combobox mode: 'filter' (filter options as you type) or 'select-only' (show all options).
49
+ * In filter mode, reopening the menu while the input still shows the label of the selected option temporarily lists
50
+ * all options until you type (so you can switch to a different choice without clearing the field first).
49
51
  * @default 'filter'
50
52
  */
51
53
  this.mode = 'filter';
@@ -148,8 +150,15 @@ export class PdsCombobox {
148
150
  this.optionEls = [];
149
151
  this.allItems = [];
150
152
  this.isUpdatingFromSelection = false;
153
+ /**
154
+ * In filter mode, after choosing an option the input still shows the label and would
155
+ * otherwise filter the list to matching substrings only. While this flag is true,
156
+ * the list shows every option until the user types (then normal filtering applies).
157
+ */
158
+ this.expandFilterListWhileOpen = false;
151
159
  this.handleInput = (e) => {
152
160
  const target = e.target;
161
+ this.clearExpandFilterList();
153
162
  this.displayText = target.value;
154
163
  this.isOpen = true;
155
164
  this.filterOptions();
@@ -165,19 +174,26 @@ export class PdsCombobox {
165
174
  // Open dropdown when input is clicked (but not when tabbed into)
166
175
  if (!this.isOpen) {
167
176
  this.isOpen = true;
177
+ this.prepareExpandFilterListOnOpen();
168
178
  this.filterOptions();
169
179
  // Trigger initial fetch if async and no options loaded yet
170
180
  if (this.asyncUrl && this.internalOptions.length === 0) {
171
181
  this.debouncedFetchAsyncOptions(this.displayText, 1);
172
182
  }
173
183
  this.setInitialHighlightedIndex();
174
- setTimeout(() => this.openDropdownPositioning(), 0);
184
+ setTimeout(() => {
185
+ this.openDropdownPositioning();
186
+ if (this.trigger === 'input' && this.expandFilterListWhileOpen && this.inputEl) {
187
+ this.inputEl.select();
188
+ }
189
+ }, 0);
175
190
  }
176
191
  };
177
192
  this.handleKeyDown = (e) => {
178
193
  if (!this.isOpen && (e.key === 'ArrowDown' || e.key === 'ArrowUp' || (e.altKey && e.key === 'ArrowDown'))) {
179
194
  e.preventDefault();
180
195
  this.isOpen = true;
196
+ this.prepareExpandFilterListOnOpen();
181
197
  this.filterOptions();
182
198
  // Set highlighted index immediately for testing
183
199
  this.setInitialHighlightedIndex();
@@ -270,6 +286,7 @@ export class PdsCombobox {
270
286
  e.preventDefault();
271
287
  this.isOpen = false;
272
288
  this.highlightedIndex = -1;
289
+ this.clearExpandFilterList();
273
290
  this.isArrowKeyNavigationMode = false; // Reset arrow-key navigation mode
274
291
  this.restoreFocusToTrigger();
275
292
  break;
@@ -277,6 +294,7 @@ export class PdsCombobox {
277
294
  // Allow normal tab behavior to close dropdown and move focus
278
295
  this.isOpen = false;
279
296
  this.highlightedIndex = -1;
297
+ this.clearExpandFilterList();
280
298
  this.isArrowKeyNavigationMode = false; // Reset arrow-key navigation mode
281
299
  break;
282
300
  }
@@ -308,6 +326,7 @@ export class PdsCombobox {
308
326
  this.onButtonTriggerClick = () => {
309
327
  this.isOpen = !this.isOpen;
310
328
  if (this.isOpen) {
329
+ this.prepareExpandFilterListOnOpen();
311
330
  this.filterOptions();
312
331
  // Trigger initial fetch if async and no options loaded yet
313
332
  if (this.asyncUrl && this.internalOptions.length === 0) {
@@ -321,6 +340,7 @@ export class PdsCombobox {
321
340
  }
322
341
  else {
323
342
  // Reset navigation mode when closing
343
+ this.clearExpandFilterList();
324
344
  this.isArrowKeyNavigationMode = false;
325
345
  }
326
346
  };
@@ -330,6 +350,7 @@ export class PdsCombobox {
330
350
  e.preventDefault();
331
351
  e.stopPropagation(); // Prevent the event from bubbling and triggering click
332
352
  this.isOpen = true;
353
+ this.prepareExpandFilterListOnOpen();
333
354
  this.filterOptions();
334
355
  // Set highlighted index immediately
335
356
  this.setInitialHighlightedIndex();
@@ -344,6 +365,7 @@ export class PdsCombobox {
344
365
  if (this.isOpen) {
345
366
  this.isOpen = false;
346
367
  this.highlightedIndex = -1;
368
+ this.clearExpandFilterList();
347
369
  this.updateAriaActiveDescendant(); // Clear aria-activedescendant
348
370
  this.restoreFocusToTrigger();
349
371
  }
@@ -371,6 +393,7 @@ export class PdsCombobox {
371
393
  if (!isRelatedTargetInCombobox && !isRelatedTargetInListbox) {
372
394
  this.isOpen = false;
373
395
  this.highlightedIndex = -1;
396
+ this.clearExpandFilterList();
374
397
  this.isArrowKeyNavigationMode = false; // Reset arrow-key navigation mode
375
398
  this.updateAriaActiveDescendant(); // Clear aria-activedescendant
376
399
  // If there's a selected option but the display text doesn't match, restore the selected option's display text
@@ -768,7 +791,7 @@ export class PdsCombobox {
768
791
  if (this.allItems.length === 0 && this.optionEls.length > 0) {
769
792
  this.allItems = [...this.optionEls];
770
793
  }
771
- if (this.mode === 'select-only') {
794
+ if (this.mode === 'select-only' || this.expandFilterListWhileOpen) {
772
795
  this.filteredItems = [...this.allItems];
773
796
  }
774
797
  else {
@@ -809,6 +832,23 @@ export class PdsCombobox {
809
832
  }
810
833
  this.highlightedIndex = -1;
811
834
  }
835
+ clearExpandFilterList() {
836
+ this.expandFilterListWhileOpen = false;
837
+ }
838
+ /**
839
+ * When reopening the dropdown in filter mode with the input still showing the
840
+ * committed selection label, show the full option list until the user edits the query.
841
+ */
842
+ prepareExpandFilterListOnOpen() {
843
+ if (this.mode === 'filter' &&
844
+ this.selectedOption &&
845
+ this.displayText === this.getOptionLabel(this.selectedOption)) {
846
+ this.expandFilterListWhileOpen = true;
847
+ }
848
+ else {
849
+ this.expandFilterListWhileOpen = false;
850
+ }
851
+ }
812
852
  openDropdownPositioning() {
813
853
  if (this.triggerEl && this.listboxEl) {
814
854
  // Apply width and max-height BEFORE positioning calculations
@@ -1086,6 +1126,7 @@ export class PdsCombobox {
1086
1126
  // The @Watch('selectedOption') will handle displayText, value, and form internals
1087
1127
  this.setSelectedOption(option);
1088
1128
  this.isOpen = false;
1129
+ this.clearExpandFilterList();
1089
1130
  this.pdsComboboxChange.emit({ value: option.value });
1090
1131
  }
1091
1132
  renderDropdown() {
@@ -1244,10 +1285,10 @@ export class PdsCombobox {
1244
1285
  ]
1245
1286
  .filter(Boolean)
1246
1287
  .join(' ');
1247
- return (h(Host, { key: '6a8f372c89a896d2d7e67661e84053c4c95b93c9' }, h("div", { key: '7b4747885bfa9aaa6e698bf13b6cdf9d4e77b3b1', class: "pds-combobox", tabIndex: -1, onFocusout: this.onComboboxFocusOut, part: "combobox" }, this.label && !this.hideLabel && (h("label", { key: '46acd60080458de682516becc6144b38675a3f2d', htmlFor: this.componentId, class: "pds-combobox__label" }, this.label)), this.trigger === 'input' ? (h("div", { class: "pds-combobox__input-wrapper", style: { width: this.triggerWidth } }, h("input", { ref: el => {
1288
+ return (h(Host, { key: '28c9653028e7fd67ccd8361a84108fbe11b1303f' }, h("div", { key: 'd9a3d6c4d3ca1c6135501e702be8beeffcafdf0d', class: "pds-combobox", tabIndex: -1, onFocusout: this.onComboboxFocusOut, part: "combobox" }, this.label && !this.hideLabel && (h("label", { key: '8832180ca4ee60506d464115aff2503d3aeb6c52', htmlFor: this.componentId, class: "pds-combobox__label" }, this.label)), this.trigger === 'input' ? (h("div", { class: "pds-combobox__input-wrapper", style: { width: this.triggerWidth } }, h("input", { ref: el => {
1248
1289
  this.inputEl = el;
1249
1290
  this.triggerEl = el;
1250
- }, class: "pds-combobox__input", type: "text", role: "combobox", "aria-autocomplete": "list", "aria-controls": "pds-combobox-listbox", "aria-activedescendant": this.isOpen && this.highlightedIndex >= 0 ? `pds-combobox-option-${this.highlightedIndex}` : undefined, "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: "combobox", "aria-haspopup": "listbox", "aria-controls": "pds-combobox-listbox", "aria-activedescendant": this.isOpen && this.highlightedIndex >= 0 ? `pds-combobox-option-${this.highlightedIndex}` : undefined, "aria-expanded": this.isOpen ? 'true' : 'false', "aria-disabled": this.disabled ? 'true' : 'false', "aria-label": this.hideLabel ? this.label : undefined, 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: "combobox", "aria-haspopup": "listbox", "aria-controls": "pds-combobox-listbox", "aria-activedescendant": this.isOpen && this.highlightedIndex >= 0 ? `pds-combobox-option-${this.highlightedIndex}` : undefined, "aria-expanded": this.isOpen ? 'true' : 'false', "aria-disabled": this.disabled ? 'true' : 'false', "aria-label": this.hideLabel ? this.label : undefined, 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())), h("div", { key: '4e4bd7cb7139416f3f59b1c9736a1fad85c09c24', style: { display: 'none' } }, h("slot", { key: '79e4c181d161a56acba68e1f7ca932369e938e10', onSlotchange: () => this.updateOptions() })), this.renderDropdown())));
1291
+ }, class: "pds-combobox__input", type: "text", role: "combobox", "aria-autocomplete": "list", "aria-controls": "pds-combobox-listbox", "aria-activedescendant": this.isOpen && this.highlightedIndex >= 0 ? `pds-combobox-option-${this.highlightedIndex}` : undefined, "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: "combobox", "aria-haspopup": "listbox", "aria-controls": "pds-combobox-listbox", "aria-activedescendant": this.isOpen && this.highlightedIndex >= 0 ? `pds-combobox-option-${this.highlightedIndex}` : undefined, "aria-expanded": this.isOpen ? 'true' : 'false', "aria-disabled": this.disabled ? 'true' : 'false', "aria-label": this.hideLabel ? this.label : undefined, 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: "combobox", "aria-haspopup": "listbox", "aria-controls": "pds-combobox-listbox", "aria-activedescendant": this.isOpen && this.highlightedIndex >= 0 ? `pds-combobox-option-${this.highlightedIndex}` : undefined, "aria-expanded": this.isOpen ? 'true' : 'false', "aria-disabled": this.disabled ? 'true' : 'false', "aria-label": this.hideLabel ? this.label : undefined, 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())), h("div", { key: '3f2ac580f226fc9a0bf72539804d0b514a93f5b8', style: { display: 'none' } }, h("slot", { key: '075205fb4fed8d0e4aec43531593444c1ab8e1cd', onSlotchange: () => this.updateOptions() })), this.renderDropdown())));
1251
1292
  }
1252
1293
  static get is() { return "pds-combobox"; }
1253
1294
  static get encapsulation() { return "shadow"; }
@@ -1487,7 +1528,7 @@ export class PdsCombobox {
1487
1528
  "name": "default",
1488
1529
  "text": "'filter'"
1489
1530
  }],
1490
- "text": "Determines the combobox mode: 'filter' (filter options as you type) or 'select-only' (show all options)."
1531
+ "text": "Determines the combobox mode: 'filter' (filter options as you type) or 'select-only' (show all options).\nIn filter mode, reopening the menu while the input still shows the label of the selected option temporarily lists\nall options until you type (so you can switch to a different choice without clearing the field first)."
1491
1532
  },
1492
1533
  "getter": false,
1493
1534
  "setter": false,