@vscode-elements/elements 1.16.1 → 1.16.2-pre.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.
Files changed (47) hide show
  1. package/custom-elements.json +1199 -687
  2. package/dist/bundled.js +885 -809
  3. package/dist/includes/VscElement.d.ts.map +1 -1
  4. package/dist/includes/VscElement.js +3 -1
  5. package/dist/includes/VscElement.js.map +1 -1
  6. package/dist/includes/vscode-select/OptionListController.d.ts +61 -0
  7. package/dist/includes/vscode-select/OptionListController.d.ts.map +1 -0
  8. package/dist/includes/vscode-select/OptionListController.js +373 -0
  9. package/dist/includes/vscode-select/OptionListController.js.map +1 -0
  10. package/dist/includes/vscode-select/helpers.d.ts +2 -2
  11. package/dist/includes/vscode-select/helpers.js.map +1 -1
  12. package/dist/includes/vscode-select/styles.d.ts.map +1 -1
  13. package/dist/includes/vscode-select/styles.js +19 -23
  14. package/dist/includes/vscode-select/styles.js.map +1 -1
  15. package/dist/includes/vscode-select/template-elements.d.ts +1 -0
  16. package/dist/includes/vscode-select/template-elements.d.ts.map +1 -1
  17. package/dist/includes/vscode-select/template-elements.js +14 -1
  18. package/dist/includes/vscode-select/template-elements.js.map +1 -1
  19. package/dist/includes/vscode-select/types.d.ts +11 -7
  20. package/dist/includes/vscode-select/types.d.ts.map +1 -1
  21. package/dist/includes/vscode-select/types.js.map +1 -1
  22. package/dist/includes/vscode-select/vscode-select-base.d.ts +25 -31
  23. package/dist/includes/vscode-select/vscode-select-base.d.ts.map +1 -1
  24. package/dist/includes/vscode-select/vscode-select-base.js +214 -324
  25. package/dist/includes/vscode-select/vscode-select-base.js.map +1 -1
  26. package/dist/vscode-button/vscode-button.styles.js +1 -1
  27. package/dist/vscode-button/vscode-button.styles.js.map +1 -1
  28. package/dist/vscode-button-group/vscode-button-group.styles.d.ts.map +1 -1
  29. package/dist/vscode-button-group/vscode-button-group.styles.js +2 -0
  30. package/dist/vscode-button-group/vscode-button-group.styles.js.map +1 -1
  31. package/dist/vscode-icon/vscode-icon.d.ts.map +1 -1
  32. package/dist/vscode-icon/vscode-icon.js +1 -0
  33. package/dist/vscode-icon/vscode-icon.js.map +1 -1
  34. package/dist/vscode-label/vscode-label.d.ts.map +1 -1
  35. package/dist/vscode-label/vscode-label.js +9 -7
  36. package/dist/vscode-label/vscode-label.js.map +1 -1
  37. package/dist/vscode-multi-select/vscode-multi-select.d.ts +9 -1
  38. package/dist/vscode-multi-select/vscode-multi-select.d.ts.map +1 -1
  39. package/dist/vscode-multi-select/vscode-multi-select.js +125 -65
  40. package/dist/vscode-multi-select/vscode-multi-select.js.map +1 -1
  41. package/dist/vscode-single-select/vscode-single-select.d.ts +4 -4
  42. package/dist/vscode-single-select/vscode-single-select.d.ts.map +1 -1
  43. package/dist/vscode-single-select/vscode-single-select.js +140 -74
  44. package/dist/vscode-single-select/vscode-single-select.js.map +1 -1
  45. package/package.json +5 -4
  46. package/vscode.css-custom-data.json +2 -2
  47. package/vscode.html-custom-data.json +19 -9
@@ -5,20 +5,32 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
5
5
  return c > 3 && r && Object.defineProperty(target, key, r), r;
6
6
  };
7
7
  import { html, render, nothing } from 'lit';
8
- import { property, query, queryAssignedElements, state } from 'lit/decorators.js';
8
+ import { eventOptions, property, queryAssignedElements, state, } from 'lit/decorators.js';
9
9
  import { classMap } from 'lit/directives/class-map.js';
10
+ import { ifDefined } from 'lit/directives/if-defined.js';
10
11
  import { repeat } from 'lit/directives/repeat.js';
12
+ import { when } from 'lit/directives/when.js';
11
13
  import '../../vscode-button/index.js';
12
14
  import '../../vscode-option/index.js';
13
- import { filterOptionsByPattern, findNextSelectableOptionIndex, findPrevSelectableOptionIndex, highlightRanges, } from './helpers.js';
14
15
  import { VscElement } from '../VscElement.js';
15
- import { chevronDownIcon } from './template-elements.js';
16
- const VISIBLE_OPTS = 10;
17
- const OPT_HEIGHT = 22;
16
+ import { filterOptionsByPattern, highlightRanges } from './helpers.js';
17
+ import { OptionListController } from './OptionListController.js';
18
+ import { checkIcon } from './template-elements.js';
19
+ export const VISIBLE_OPTS = 10;
20
+ export const OPT_HEIGHT = 22;
18
21
  /**
19
22
  * @cssprop --dropdown-z-index - workaround for dropdown z-index issues
20
23
  */
21
24
  export class VscodeSelectBase extends VscElement {
25
+ /**
26
+ * Options can be filtered by typing into a text input field.
27
+ */
28
+ set combobox(enabled) {
29
+ this._opts.comboboxMode = enabled;
30
+ }
31
+ get combobox() {
32
+ return this._opts.comboboxMode;
33
+ }
22
34
  /**
23
35
  * The element cannot be used and is not focusable.
24
36
  */
@@ -55,26 +67,31 @@ export class VscodeSelectBase extends VscElement {
55
67
  'startsWith',
56
68
  'startsWithPerTerm',
57
69
  ];
70
+ let fm;
58
71
  if (validValues.includes(val)) {
59
- this._filter = val;
72
+ // this._filter = val as FilterMethod;
73
+ fm = val;
60
74
  }
61
75
  else {
62
- this._filter = 'fuzzy';
76
+ // this._filter = 'fuzzy';
77
+ // eslint-disable-next-line no-console
63
78
  console.warn(`[VSCode Webview Elements] Invalid filter: "${val}", fallback to default. Valid values are: "contains", "fuzzy", "startsWith", "startsWithPerm".`, this);
79
+ fm = 'fuzzy';
64
80
  }
81
+ this._opts.filterMethod = fm;
65
82
  }
66
83
  get filter() {
67
- return this._filter;
84
+ return this._opts.filterMethod;
68
85
  }
69
86
  /**
70
87
  * @attr [options=[]]
71
88
  * @type {Option[]}
72
89
  */
73
90
  set options(opts) {
74
- this._options = opts.map((op, index) => ({ ...op, index }));
91
+ this._opts.populate(opts);
75
92
  }
76
93
  get options() {
77
- return this._options.map(({ label, value, description, selected, disabled }) => ({
94
+ return this._opts.options.map(({ label, value, description, selected, disabled }) => ({
78
95
  label,
79
96
  value,
80
97
  description,
@@ -84,13 +101,12 @@ export class VscodeSelectBase extends VscElement {
84
101
  }
85
102
  constructor() {
86
103
  super();
87
- /** @internal */
88
- this.ariaExpanded = 'false';
89
104
  this.creatable = false;
90
105
  /**
91
- * Options can be filtered by typing into a text input field.
106
+ * Accessible label for screen readers. When a `<vscode-label>` is connected
107
+ * to the component, it will be filled automatically.
92
108
  */
93
- this.combobox = false;
109
+ this.label = '';
94
110
  /**
95
111
  * Sets the invalid state manually.
96
112
  */
@@ -107,29 +123,17 @@ export class VscodeSelectBase extends VscElement {
107
123
  * Position of the options list when visible.
108
124
  */
109
125
  this.position = 'below';
110
- /** @internal */
111
- this.tabIndex = 0;
126
+ this._opts = new OptionListController(this);
112
127
  this._firstUpdateCompleted = false;
113
- this._activeIndex = -1;
114
128
  this._currentDescription = '';
115
129
  this._filter = 'fuzzy';
116
- this._filterPattern = '';
117
- this._selectedIndex = -1;
118
130
  this._selectedIndexes = [];
119
131
  this._options = [];
120
132
  this._value = '';
121
133
  this._values = [];
122
- this._listScrollTop = 0;
123
134
  this._isPlaceholderOptionActive = false;
124
135
  this._isBeingFiltered = false;
125
- /** @internal */
126
- this._multiple = false;
127
- /**
128
- * @internal
129
- * Quick-searchable map for searching a value in the options list.
130
- * Keys are the options values, values are the option indexes.
131
- */
132
- this._valueOptionIndexMap = {};
136
+ this._optionListScrollPos = 0;
133
137
  this._isHoverForbidden = false;
134
138
  this._disabled = false;
135
139
  this._originalTabIndex = undefined;
@@ -137,8 +141,7 @@ export class VscodeSelectBase extends VscElement {
137
141
  const path = event.composedPath();
138
142
  const found = path.findIndex((et) => et === this);
139
143
  if (found === -1) {
140
- this._toggleDropdown(false);
141
- window.removeEventListener('click', this._onClickOutside);
144
+ this.open = false;
142
145
  }
143
146
  };
144
147
  this._onMouseMove = () => {
@@ -157,7 +160,7 @@ export class VscodeSelectBase extends VscElement {
157
160
  this._onSpaceKeyDown();
158
161
  }
159
162
  if (event.key === 'Escape') {
160
- this._toggleDropdown(false);
163
+ this._onEscapeKeyDown();
161
164
  }
162
165
  if (event.key === 'ArrowUp') {
163
166
  this._onArrowUpKeyDown();
@@ -183,6 +186,7 @@ export class VscodeSelectBase extends VscElement {
183
186
  this.addEventListener('keydown', this._onComponentKeyDown);
184
187
  this.addEventListener('focus', this._onComponentFocus);
185
188
  this.addEventListener('blur', this._onComponentBlur);
189
+ this._setAutoFocus();
186
190
  }
187
191
  disconnectedCallback() {
188
192
  super.disconnectedCallback();
@@ -198,32 +202,59 @@ export class VscodeSelectBase extends VscElement {
198
202
  this._manageRequired();
199
203
  }
200
204
  }
205
+ update(changedProperties) {
206
+ super.update(changedProperties);
207
+ if (changedProperties.has('open')) {
208
+ if (this.open) {
209
+ this._opts.activateDefault();
210
+ this._scrollActiveElementToTop();
211
+ window.addEventListener('click', this._onClickOutside);
212
+ }
213
+ else {
214
+ window.removeEventListener('click', this._onClickOutside);
215
+ }
216
+ }
217
+ }
201
218
  get _filteredOptions() {
202
- if (!this.combobox || this._filterPattern === '') {
219
+ if (!this.combobox || this._opts.filterPattern === '') {
203
220
  return this._options;
204
221
  }
205
- return filterOptionsByPattern(this._options, this._filterPattern, this._filter);
222
+ return filterOptionsByPattern(this._options, this._opts.filterPattern, this._filter);
206
223
  }
207
- get _currentOptions() {
208
- return this.combobox ? this._filteredOptions : this._options;
224
+ _setAutoFocus() {
225
+ if (this.hasAttribute('autofocus')) {
226
+ if (this.tabIndex < 0) {
227
+ this.tabIndex = 0;
228
+ }
229
+ if (this.combobox) {
230
+ this.updateComplete.then(() => {
231
+ this.shadowRoot
232
+ ?.querySelector('.combobox-input')
233
+ .focus();
234
+ });
235
+ }
236
+ else {
237
+ this.updateComplete.then(() => {
238
+ this.shadowRoot
239
+ ?.querySelector('.select-face')
240
+ .focus();
241
+ });
242
+ }
243
+ }
209
244
  }
210
245
  get _isSuggestedOptionVisible() {
211
246
  if (!(this.combobox && this.creatable)) {
212
247
  return false;
213
248
  }
214
- const filterPatternExistsAsOption = typeof this._valueOptionIndexMap[this._filterPattern] !== 'undefined';
215
- const filtered = this._filterPattern.length > 0;
249
+ const filterPatternExistsAsOption = this._opts.getOptionByValue(this._opts.filterPattern) !== null;
250
+ const filtered = this._opts.filterPattern.length > 0;
216
251
  return !filterPatternExistsAsOption && filtered;
217
252
  }
218
253
  _manageRequired() { }
219
254
  _setStateFromSlottedElements() {
220
- const options = [];
221
- let nextIndex = 0;
222
255
  const optionElements = this._assignedOptions ?? [];
223
- const selectedIndexes = [];
224
- const values = [];
225
- this._valueOptionIndexMap = {};
226
- optionElements.forEach((el, i) => {
256
+ this._opts.clear();
257
+ optionElements.forEach((el) => {
227
258
  const { innerText, description, disabled } = el;
228
259
  const value = typeof el.value === 'string' ? el.value : innerText.trim();
229
260
  const selected = el.selected ?? false;
@@ -232,93 +263,61 @@ export class VscodeSelectBase extends VscElement {
232
263
  value,
233
264
  description,
234
265
  selected,
235
- index: nextIndex,
236
266
  disabled,
237
267
  };
238
- nextIndex = options.push(op);
239
- if (selected && !this._multiple) {
240
- this._activeIndex = i;
241
- }
242
- if (selected) {
243
- selectedIndexes.push(options.length - 1);
244
- values.push(value);
245
- }
246
- this._valueOptionIndexMap[op.value] = op.index;
268
+ this._opts.add(op);
247
269
  });
248
- this._options = options;
249
- if (selectedIndexes.length > 0) {
250
- this._selectedIndex = selectedIndexes[0];
251
- this._selectedIndexes = selectedIndexes;
252
- this._value = values[0];
253
- this._values = values;
254
- }
255
- if (!this._multiple && !this.combobox && selectedIndexes.length === 0) {
256
- this._selectedIndex = this._options.length > 0 ? 0 : -1;
257
- }
258
- }
259
- async _toggleDropdown(visible) {
260
- this.open = visible;
261
- this.ariaExpanded = String(visible);
262
- if (visible && !this._multiple) {
263
- this._activeIndex = this._selectedIndex;
264
- }
265
- if (visible && !this._multiple && !this.combobox) {
266
- this._activeIndex = this._selectedIndex;
267
- if (this._activeIndex > VISIBLE_OPTS - 1) {
268
- await this.updateComplete;
269
- this._listElement.scrollTop = Math.floor(this._activeIndex * OPT_HEIGHT);
270
- }
271
- }
272
- if (visible) {
273
- window.addEventListener('click', this._onClickOutside);
274
- }
275
- else {
276
- window.removeEventListener('click', this._onClickOutside);
277
- }
278
270
  }
279
271
  _createSuggestedOption() {
280
- const nextSelectedIndex = this._options.length;
272
+ const nextSelectedIndex = this._opts.numOptions;
281
273
  const op = document.createElement('vscode-option');
282
- op.value = this._filterPattern;
283
- render(this._filterPattern, op);
274
+ op.value = this._opts.filterPattern;
275
+ render(this._opts.filterPattern, op);
284
276
  this.appendChild(op);
285
277
  return nextSelectedIndex;
286
278
  }
287
279
  _dispatchChangeEvent() {
288
- if (!this._multiple) {
289
- /** @deprecated */
290
- this.dispatchEvent(new CustomEvent('vsc-change', {
291
- detail: {
292
- selectedIndex: this._selectedIndex,
293
- value: this._value,
294
- },
295
- }));
296
- }
297
- else {
298
- /** @deprecated */
299
- this.dispatchEvent(new CustomEvent('vsc-change', {
300
- detail: {
301
- selectedIndexes: this._selectedIndexes,
302
- value: this._values,
303
- },
304
- }));
305
- }
306
280
  this.dispatchEvent(new Event('change'));
307
281
  this.dispatchEvent(new Event('input'));
308
282
  }
309
283
  async _createAndSelectSuggestedOption() { }
310
- _onFaceClick() {
311
- this._toggleDropdown(!this.open);
312
- if (this._multiple) {
313
- this._activeIndex = 0;
314
- }
315
- }
316
284
  _toggleComboboxDropdown() {
317
- this._filterPattern = '';
318
- this._toggleDropdown(!this.open);
319
- if (this._multiple) {
320
- this._activeIndex = -1;
285
+ this._opts.filterPattern = '';
286
+ this.open = !this.open;
287
+ }
288
+ _scrollActiveElementToTop() {
289
+ this._optionListScrollPos = Math.floor(this._opts.relativeActiveIndex * OPT_HEIGHT);
290
+ }
291
+ async _adjustOptionListScrollPos(direction, optionIndex) {
292
+ let numOpts = this._opts.numOfVisibleOptions;
293
+ const suggestedOptionVisible = this._isSuggestedOptionVisible;
294
+ if (suggestedOptionVisible) {
295
+ numOpts += 1;
296
+ }
297
+ if (numOpts <= VISIBLE_OPTS) {
298
+ return;
321
299
  }
300
+ this._isHoverForbidden = true;
301
+ window.addEventListener('mousemove', this._onMouseMove);
302
+ const ulScrollTop = this._optionListScrollPos;
303
+ const liPosY = optionIndex * OPT_HEIGHT;
304
+ const fullyVisible = liPosY >= ulScrollTop &&
305
+ liPosY <= ulScrollTop + VISIBLE_OPTS * OPT_HEIGHT - OPT_HEIGHT;
306
+ if (direction === 'down') {
307
+ if (!fullyVisible) {
308
+ this._optionListScrollPos =
309
+ optionIndex * OPT_HEIGHT - (VISIBLE_OPTS - 1) * OPT_HEIGHT;
310
+ }
311
+ }
312
+ if (direction === 'up') {
313
+ if (!fullyVisible) {
314
+ this._optionListScrollPos = Math.floor(this._opts.relativeActiveIndex * OPT_HEIGHT);
315
+ }
316
+ }
317
+ }
318
+ //#region event handlers
319
+ _onFaceClick() {
320
+ this.open = !this.open;
322
321
  }
323
322
  _onComboboxButtonClick() {
324
323
  this._toggleComboboxDropdown();
@@ -328,6 +327,9 @@ export class VscodeSelectBase extends VscElement {
328
327
  this._toggleComboboxDropdown();
329
328
  }
330
329
  }
330
+ _onOptionListScroll(ev) {
331
+ this._optionListScrollPos = ev.target.scrollTop;
332
+ }
331
333
  _onOptionMouseOver(ev) {
332
334
  if (this._isHoverForbidden) {
333
335
  return;
@@ -338,11 +340,11 @@ export class VscodeSelectBase extends VscElement {
338
340
  }
339
341
  if (el.matches('.placeholder')) {
340
342
  this._isPlaceholderOptionActive = true;
341
- this._activeIndex = -1;
343
+ this._opts.activeIndex = -1;
342
344
  }
343
345
  else {
344
346
  this._isPlaceholderOptionActive = false;
345
- this._activeIndex = Number(this.combobox ? el.dataset.filteredIndex : el.dataset.index);
347
+ this._opts.activeIndex = +el.dataset.index;
346
348
  }
347
349
  }
348
350
  _onPlaceholderOptionMouseOut() {
@@ -363,143 +365,70 @@ export class VscodeSelectBase extends VscElement {
363
365
  if (clickedOnAcceptButton) {
364
366
  return;
365
367
  }
366
- const list = this.combobox ? this._filteredOptions : this._options;
367
- const showDropdownNext = !this.open;
368
- this._toggleDropdown(showDropdownNext);
369
- if (!this._multiple &&
370
- !showDropdownNext &&
371
- this._selectedIndex !== this._activeIndex) {
372
- this._selectedIndex =
373
- this._activeIndex > -1 ? list[this._activeIndex].index : -1;
374
- this._value =
375
- this._selectedIndex > -1
376
- ? this._options[this._selectedIndex].value
377
- : '';
378
- this._dispatchChangeEvent();
379
- }
380
- if (this.combobox) {
381
- if (this._isPlaceholderOptionActive) {
382
- this._createAndSelectSuggestedOption();
383
- }
384
- else {
385
- if (!this._multiple && !showDropdownNext) {
386
- this._selectedIndex =
387
- this._activeIndex > -1
388
- ? this._filteredOptions[this._activeIndex].index
389
- : -1;
390
- }
391
- if (!this._multiple && showDropdownNext) {
392
- this.updateComplete.then(() => {
393
- this._scrollActiveElementToTop();
394
- });
395
- }
396
- }
397
- }
398
- if (this._multiple && showDropdownNext) {
399
- this._activeIndex = 0;
400
- }
401
368
  }
402
369
  _onSpaceKeyDown() {
403
370
  if (!this.open) {
404
- this._toggleDropdown(true);
371
+ this.open = true;
405
372
  return;
406
373
  }
407
- if (this.open && this._multiple && this._activeIndex > -1) {
408
- const opts = this.combobox ? this._filteredOptions : this._options;
409
- const selectedOption = opts[this._activeIndex];
410
- const nextSelectedIndexes = [];
411
- this._options[selectedOption.index].selected = !selectedOption.selected;
412
- opts.forEach(({ index }) => {
413
- const { selected } = this._options[index];
414
- if (selected) {
415
- nextSelectedIndexes.push(index);
416
- }
417
- });
418
- this._selectedIndexes = nextSelectedIndexes;
419
- }
420
- }
421
- _scrollActiveElementToTop() {
422
- this._listElement.scrollTop = Math.floor(this._activeIndex * OPT_HEIGHT);
423
- }
424
- async _adjustOptionListScrollPos(direction, optionIndex) {
425
- let numOpts = this.combobox
426
- ? this._filteredOptions.length
427
- : this._options.length;
428
- const suggestedOptionVisible = this._isSuggestedOptionVisible;
429
- if (suggestedOptionVisible) {
430
- numOpts += 1;
431
- }
432
- if (numOpts <= VISIBLE_OPTS) {
433
- return;
434
- }
435
- this._isHoverForbidden = true;
436
- window.addEventListener('mousemove', this._onMouseMove);
437
- const ulScrollTop = this._listElement.scrollTop;
438
- const liPosY = optionIndex * OPT_HEIGHT;
439
- const fullyVisible = liPosY >= ulScrollTop &&
440
- liPosY <= ulScrollTop + VISIBLE_OPTS * OPT_HEIGHT - OPT_HEIGHT;
441
- if (direction === 'down') {
442
- if (!fullyVisible) {
443
- this._listElement.scrollTop =
444
- optionIndex * OPT_HEIGHT - (VISIBLE_OPTS - 1) * OPT_HEIGHT;
445
- }
446
- }
447
- if (direction === 'up') {
448
- if (!fullyVisible) {
449
- this._listElement.scrollTop = Math.floor(this._activeIndex * OPT_HEIGHT);
450
- }
451
- }
452
374
  }
453
375
  _onArrowUpKeyDown() {
454
376
  if (this.open) {
455
- if (this._activeIndex <= 0 && !(this.combobox && this.creatable)) {
377
+ if (this._opts.activeIndex <= 0 && !(this.combobox && this.creatable)) {
456
378
  return;
457
379
  }
458
380
  if (this._isPlaceholderOptionActive) {
459
- const optionIndex = this._currentOptions.length - 1;
460
- this._activeIndex = optionIndex;
381
+ const optionIndex = this._opts.numOfVisibleOptions - 1;
382
+ this._opts.activeIndex = optionIndex;
461
383
  this._isPlaceholderOptionActive = false;
462
384
  }
463
385
  else {
464
- const currentOptions = this.combobox
465
- ? this._filteredOptions
466
- : this._options;
467
- const prevSelectable = findPrevSelectableOptionIndex(currentOptions, this._activeIndex);
468
- if (prevSelectable > -1) {
469
- this._activeIndex = prevSelectable;
470
- this._adjustOptionListScrollPos('up', prevSelectable);
386
+ const prevOp = this._opts.prev();
387
+ if (prevOp !== null) {
388
+ this._opts.activeIndex = prevOp?.index ?? -1;
389
+ const prevSelectableIndex = prevOp?.filteredIndex ?? -1;
390
+ if (prevSelectableIndex > -1) {
391
+ this._adjustOptionListScrollPos('up', prevSelectableIndex);
392
+ }
471
393
  }
472
394
  }
473
395
  }
396
+ else {
397
+ this.open = true;
398
+ this._opts.activateDefault();
399
+ }
474
400
  }
475
401
  _onArrowDownKeyDown() {
476
- let numOpts = this.combobox
477
- ? this._filteredOptions.length
478
- : this._options.length;
479
- const currentOptions = this.combobox
480
- ? this._filteredOptions
481
- : this._options;
402
+ let numOpts = this._opts.numOfVisibleOptions;
482
403
  const suggestedOptionVisible = this._isSuggestedOptionVisible;
483
404
  if (suggestedOptionVisible) {
484
405
  numOpts += 1;
485
406
  }
486
407
  if (this.open) {
487
- if (this._isPlaceholderOptionActive && this._activeIndex === -1) {
408
+ if (this._isPlaceholderOptionActive && this._opts.activeIndex === -1) {
488
409
  return;
489
410
  }
490
- if (suggestedOptionVisible && this._activeIndex === numOpts - 2) {
411
+ const nextOp = this._opts.next();
412
+ if (suggestedOptionVisible && nextOp === null) {
491
413
  this._isPlaceholderOptionActive = true;
492
414
  this._adjustOptionListScrollPos('down', numOpts - 1);
493
- this._activeIndex = -1;
415
+ this._opts.activeIndex = -1;
494
416
  }
495
- else if (this._activeIndex < numOpts - 1) {
496
- const nextSelectable = findNextSelectableOptionIndex(currentOptions, this._activeIndex);
497
- if (nextSelectable > -1) {
498
- this._activeIndex = nextSelectable;
499
- this._adjustOptionListScrollPos('down', nextSelectable);
417
+ else if (nextOp !== null) {
418
+ const nextSelectableIndex = nextOp?.filteredIndex ?? -1;
419
+ this._opts.activeIndex = nextOp?.index ?? -1;
420
+ if (nextSelectableIndex > -1) {
421
+ this._adjustOptionListScrollPos('down', nextSelectableIndex);
500
422
  }
501
423
  }
502
424
  }
425
+ else {
426
+ this.open = true;
427
+ this._opts.activateDefault();
428
+ }
429
+ }
430
+ _onEscapeKeyDown() {
431
+ this.open = false;
503
432
  }
504
433
  _onSlotChange() {
505
434
  this._setStateFromSlottedElements();
@@ -508,61 +437,85 @@ export class VscodeSelectBase extends VscElement {
508
437
  _onComboboxInputFocus(ev) {
509
438
  ev.target.select();
510
439
  this._isBeingFiltered = false;
511
- this._filterPattern = '';
440
+ this._opts.filterPattern = '';
512
441
  }
513
442
  _onComboboxInputBlur() {
514
443
  this._isBeingFiltered = false;
515
444
  }
516
445
  _onComboboxInputInput(ev) {
517
446
  this._isBeingFiltered = true;
518
- this._filterPattern = ev.target.value;
519
- this._activeIndex = -1;
520
- this._toggleDropdown(true);
447
+ this._opts.filterPattern = ev.target.value;
448
+ this._opts.activeIndex = -1;
449
+ this.open = true;
521
450
  }
522
451
  _onComboboxInputClick() {
523
- this._isBeingFiltered = this._filterPattern !== '';
524
- this._toggleDropdown(true);
452
+ this._isBeingFiltered = this._opts.filterPattern !== '';
453
+ this.open = true;
454
+ }
455
+ _onComboboxInputSpaceKeyDown(ev) {
456
+ if (ev.key === ' ') {
457
+ ev.stopPropagation();
458
+ }
525
459
  }
526
460
  _onOptionClick(_ev) {
527
461
  this._isBeingFiltered = false;
528
462
  return;
529
463
  }
464
+ //#endregion
465
+ //#region render functions
466
+ _renderCheckbox(checked, label) {
467
+ const checkboxClasses = {
468
+ 'checkbox-icon': true,
469
+ checked,
470
+ };
471
+ return html `<span class=${classMap(checkboxClasses)}>${checkIcon}</span
472
+ ><span class="option-label">${label}</span>`;
473
+ }
530
474
  _renderOptions() {
531
- const list = this.combobox ? this._filteredOptions : this._options;
475
+ const list = this._opts.options;
532
476
  return html `
533
477
  <ul
478
+ aria-label=${ifDefined(this.label ?? undefined)}
479
+ aria-multiselectable=${ifDefined(this._opts.multiSelect ? 'true' : undefined)}
534
480
  class="options"
481
+ id="select-listbox"
482
+ role="listbox"
483
+ tabindex="-1"
535
484
  @click=${this._onOptionClick}
536
485
  @mouseover=${this._onOptionMouseOver}
486
+ @scroll=${this._onOptionListScroll}
487
+ .scrollTop=${this._optionListScrollPos}
537
488
  >
538
489
  ${repeat(list, (op) => op.index, (op, index) => {
490
+ if (!op.visible) {
491
+ return nothing;
492
+ }
493
+ const active = op.index === this._opts.activeIndex && !op.disabled;
494
+ const selected = this._opts.getIsIndexSelected(op.index);
539
495
  const optionClasses = {
540
- active: index === this._activeIndex && !op.disabled,
496
+ active,
541
497
  disabled: op.disabled,
542
498
  option: true,
543
- selected: op.selected,
544
- };
545
- const checkboxClasses = {
546
- 'checkbox-icon': true,
547
- checked: op.selected,
499
+ selected,
548
500
  };
549
501
  const labelText = (op.ranges?.length ?? 0 > 0)
550
502
  ? highlightRanges(op.label, op.ranges ?? [])
551
503
  : op.label;
552
504
  return html `
553
505
  <li
506
+ aria-selected=${selected ? 'true' : 'false'}
554
507
  class=${classMap(optionClasses)}
555
508
  data-index=${op.index}
556
509
  data-filtered-index=${index}
510
+ id=${`op-${op.index}`}
511
+ role="option"
512
+ tabindex="-1"
557
513
  >
558
- ${this._multiple
559
- ? html `<span class=${classMap(checkboxClasses)}></span
560
- ><span class="option-label">${labelText}</span>`
561
- : labelText}
514
+ ${when(this._opts.multiSelect, () => this._renderCheckbox(selected, labelText), () => labelText)}
562
515
  </li>
563
516
  `;
564
517
  })}
565
- ${this._renderPlaceholderOption(list.length < 1)}
518
+ ${this._renderPlaceholderOption(this._opts.numOfVisibleOptions < 1)}
566
519
  </ul>
567
520
  `;
568
521
  }
@@ -570,10 +523,11 @@ export class VscodeSelectBase extends VscElement {
570
523
  if (!this.combobox) {
571
524
  return nothing;
572
525
  }
573
- if (this._valueOptionIndexMap[this._filterPattern]) {
526
+ const foundOption = this._opts.getOptionByLabel(this._opts.filterPattern);
527
+ if (foundOption) {
574
528
  return nothing;
575
529
  }
576
- if (this.creatable && this._filterPattern.length > 0) {
530
+ if (this.creatable && this._opts.filterPattern.length > 0) {
577
531
  return html `<li
578
532
  class=${classMap({
579
533
  option: true,
@@ -582,7 +536,7 @@ export class VscodeSelectBase extends VscElement {
582
536
  })}
583
537
  @mouseout=${this._onPlaceholderOptionMouseOut}
584
538
  >
585
- Add "${this._filterPattern}"
539
+ Add "${this._opts.filterPattern}"
586
540
  </li>`;
587
541
  }
588
542
  else {
@@ -594,10 +548,11 @@ export class VscodeSelectBase extends VscElement {
594
548
  }
595
549
  }
596
550
  _renderDescription() {
597
- if (!this._options[this._activeIndex]) {
551
+ const op = this._opts.getActiveOption();
552
+ if (!op) {
598
553
  return nothing;
599
554
  }
600
- const { description } = this._options[this._activeIndex];
555
+ const { description } = op;
601
556
  return description
602
557
  ? html `<div class="description">${description}</div>`
603
558
  : nothing;
@@ -605,89 +560,36 @@ export class VscodeSelectBase extends VscElement {
605
560
  _renderSelectFace() {
606
561
  return html `${nothing}`;
607
562
  }
608
- _renderMultiSelectLabel() {
609
- switch (this._selectedIndexes.length) {
610
- case 0:
611
- return html `<span class="select-face-badge no-item"
612
- >No items selected</span
613
- >`;
614
- case 1:
615
- return html `<span class="select-face-badge">1 item selected</span>`;
616
- default:
617
- return html `<span class="select-face-badge"
618
- >${this._selectedIndexes.length} items selected</span
619
- >`;
620
- }
621
- }
622
563
  _renderComboboxFace() {
623
- let inputVal = '';
624
- if (this._isBeingFiltered) {
625
- inputVal = this._filterPattern;
626
- }
627
- else {
628
- inputVal =
629
- this._selectedIndex > -1
630
- ? (this._options[this._selectedIndex]?.label ?? '')
631
- : '';
632
- }
633
- return html `
634
- <div class="combobox-face face">
635
- ${this._multiple ? this._renderMultiSelectLabel() : nothing}
636
- <input
637
- class="combobox-input"
638
- spellcheck="false"
639
- type="text"
640
- autocomplete="off"
641
- .value=${inputVal}
642
- @focus=${this._onComboboxInputFocus}
643
- @blur=${this._onComboboxInputBlur}
644
- @input=${this._onComboboxInputInput}
645
- @click=${this._onComboboxInputClick}
646
- >
647
- <button
648
- class="combobox-button"
649
- type="button"
650
- @click=${this._onComboboxButtonClick}
651
- @keydown=${this._onComboboxButtonKeyDown}
652
- >
653
- ${chevronDownIcon}
654
- </button>
655
- </div>
656
- `;
564
+ return html `${nothing}`;
657
565
  }
658
566
  _renderDropdownControls() {
659
567
  return html `${nothing}`;
660
568
  }
661
569
  _renderDropdown() {
662
- const classes = classMap({
570
+ const classes = {
663
571
  dropdown: true,
664
- multiple: this._multiple,
665
- });
572
+ multiple: this._opts.multiSelect,
573
+ open: this.open,
574
+ };
666
575
  return html `
667
- <div class=${classes}>
576
+ <div class=${classMap(classes)}>
668
577
  ${this.position === 'above' ? this._renderDescription() : nothing}
669
578
  ${this._renderOptions()} ${this._renderDropdownControls()}
670
579
  ${this.position === 'below' ? this._renderDescription() : nothing}
671
580
  </div>
672
581
  `;
673
582
  }
674
- render() {
675
- return html `
676
- <slot class="main-slot" @slotchange=${this._onSlotChange}></slot>
677
- ${this.combobox ? this._renderComboboxFace() : this._renderSelectFace()}
678
- ${this.open ? this._renderDropdown() : nothing}
679
- `;
680
- }
681
583
  }
682
- __decorate([
683
- property({ type: String, reflect: true, attribute: 'aria-expanded' })
684
- ], VscodeSelectBase.prototype, "ariaExpanded", void 0);
685
584
  __decorate([
686
585
  property({ type: Boolean, reflect: true })
687
586
  ], VscodeSelectBase.prototype, "creatable", void 0);
688
587
  __decorate([
689
588
  property({ type: Boolean, reflect: true })
690
- ], VscodeSelectBase.prototype, "combobox", void 0);
589
+ ], VscodeSelectBase.prototype, "combobox", null);
590
+ __decorate([
591
+ property({ reflect: true })
592
+ ], VscodeSelectBase.prototype, "label", void 0);
691
593
  __decorate([
692
594
  property({ type: Boolean, reflect: true })
693
595
  ], VscodeSelectBase.prototype, "disabled", null);
@@ -709,18 +611,12 @@ __decorate([
709
611
  __decorate([
710
612
  property({ reflect: true })
711
613
  ], VscodeSelectBase.prototype, "position", void 0);
712
- __decorate([
713
- property({ type: Number, attribute: true, reflect: true })
714
- ], VscodeSelectBase.prototype, "tabIndex", void 0);
715
614
  __decorate([
716
615
  queryAssignedElements({
717
616
  flatten: true,
718
617
  selector: 'vscode-option',
719
618
  })
720
619
  ], VscodeSelectBase.prototype, "_assignedOptions", void 0);
721
- __decorate([
722
- state()
723
- ], VscodeSelectBase.prototype, "_activeIndex", void 0);
724
620
  __decorate([
725
621
  state()
726
622
  ], VscodeSelectBase.prototype, "_currentDescription", void 0);
@@ -730,12 +626,6 @@ __decorate([
730
626
  __decorate([
731
627
  state()
732
628
  ], VscodeSelectBase.prototype, "_filteredOptions", null);
733
- __decorate([
734
- state()
735
- ], VscodeSelectBase.prototype, "_filterPattern", void 0);
736
- __decorate([
737
- state()
738
- ], VscodeSelectBase.prototype, "_selectedIndex", void 0);
739
629
  __decorate([
740
630
  state()
741
631
  ], VscodeSelectBase.prototype, "_selectedIndexes", void 0);
@@ -748,9 +638,6 @@ __decorate([
748
638
  __decorate([
749
639
  state()
750
640
  ], VscodeSelectBase.prototype, "_values", void 0);
751
- __decorate([
752
- state()
753
- ], VscodeSelectBase.prototype, "_listScrollTop", void 0);
754
641
  __decorate([
755
642
  state()
756
643
  ], VscodeSelectBase.prototype, "_isPlaceholderOptionActive", void 0);
@@ -758,6 +645,9 @@ __decorate([
758
645
  state()
759
646
  ], VscodeSelectBase.prototype, "_isBeingFiltered", void 0);
760
647
  __decorate([
761
- query('.options')
762
- ], VscodeSelectBase.prototype, "_listElement", void 0);
648
+ state()
649
+ ], VscodeSelectBase.prototype, "_optionListScrollPos", void 0);
650
+ __decorate([
651
+ eventOptions({ passive: true })
652
+ ], VscodeSelectBase.prototype, "_onOptionListScroll", null);
763
653
  //# sourceMappingURL=vscode-select-base.js.map