@vscode-elements/elements 1.16.0 → 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.
- package/README.md +5 -1
- package/custom-elements.json +1199 -687
- package/dist/bundled.js +888 -812
- package/dist/includes/VscElement.d.ts.map +1 -1
- package/dist/includes/VscElement.js +3 -1
- package/dist/includes/VscElement.js.map +1 -1
- package/dist/includes/vscode-select/OptionListController.d.ts +61 -0
- package/dist/includes/vscode-select/OptionListController.d.ts.map +1 -0
- package/dist/includes/vscode-select/OptionListController.js +373 -0
- package/dist/includes/vscode-select/OptionListController.js.map +1 -0
- package/dist/includes/vscode-select/helpers.d.ts +2 -2
- package/dist/includes/vscode-select/helpers.js.map +1 -1
- package/dist/includes/vscode-select/styles.d.ts.map +1 -1
- package/dist/includes/vscode-select/styles.js +19 -23
- package/dist/includes/vscode-select/styles.js.map +1 -1
- package/dist/includes/vscode-select/template-elements.d.ts +1 -0
- package/dist/includes/vscode-select/template-elements.d.ts.map +1 -1
- package/dist/includes/vscode-select/template-elements.js +14 -1
- package/dist/includes/vscode-select/template-elements.js.map +1 -1
- package/dist/includes/vscode-select/types.d.ts +11 -7
- package/dist/includes/vscode-select/types.d.ts.map +1 -1
- package/dist/includes/vscode-select/types.js.map +1 -1
- package/dist/includes/vscode-select/vscode-select-base.d.ts +25 -31
- package/dist/includes/vscode-select/vscode-select-base.d.ts.map +1 -1
- package/dist/includes/vscode-select/vscode-select-base.js +214 -324
- package/dist/includes/vscode-select/vscode-select-base.js.map +1 -1
- package/dist/vscode-button/vscode-button.styles.js +4 -4
- package/dist/vscode-button/vscode-button.styles.js.map +1 -1
- package/dist/vscode-button-group/vscode-button-group.styles.d.ts.map +1 -1
- package/dist/vscode-button-group/vscode-button-group.styles.js +2 -0
- package/dist/vscode-button-group/vscode-button-group.styles.js.map +1 -1
- package/dist/vscode-icon/vscode-icon.d.ts.map +1 -1
- package/dist/vscode-icon/vscode-icon.js +1 -0
- package/dist/vscode-icon/vscode-icon.js.map +1 -1
- package/dist/vscode-label/vscode-label.d.ts.map +1 -1
- package/dist/vscode-label/vscode-label.js +9 -7
- package/dist/vscode-label/vscode-label.js.map +1 -1
- package/dist/vscode-multi-select/vscode-multi-select.d.ts +9 -1
- package/dist/vscode-multi-select/vscode-multi-select.d.ts.map +1 -1
- package/dist/vscode-multi-select/vscode-multi-select.js +125 -65
- package/dist/vscode-multi-select/vscode-multi-select.js.map +1 -1
- package/dist/vscode-single-select/vscode-single-select.d.ts +4 -4
- package/dist/vscode-single-select/vscode-single-select.d.ts.map +1 -1
- package/dist/vscode-single-select/vscode-single-select.js +140 -74
- package/dist/vscode-single-select/vscode-single-select.js.map +1 -1
- package/package.json +5 -4
- package/vscode.css-custom-data.json +2 -2
- 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 {
|
|
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 {
|
|
16
|
-
|
|
17
|
-
|
|
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.
|
|
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.
|
|
91
|
+
this._opts.populate(opts);
|
|
75
92
|
}
|
|
76
93
|
get options() {
|
|
77
|
-
return this.
|
|
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
|
-
*
|
|
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.
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
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.
|
|
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.
|
|
219
|
+
if (!this.combobox || this._opts.filterPattern === '') {
|
|
203
220
|
return this._options;
|
|
204
221
|
}
|
|
205
|
-
return filterOptionsByPattern(this._options, this.
|
|
222
|
+
return filterOptionsByPattern(this._options, this._opts.filterPattern, this._filter);
|
|
206
223
|
}
|
|
207
|
-
|
|
208
|
-
|
|
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 =
|
|
215
|
-
const filtered = this.
|
|
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
|
-
|
|
224
|
-
|
|
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
|
-
|
|
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.
|
|
272
|
+
const nextSelectedIndex = this._opts.numOptions;
|
|
281
273
|
const op = document.createElement('vscode-option');
|
|
282
|
-
op.value = this.
|
|
283
|
-
render(this.
|
|
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.
|
|
318
|
-
this.
|
|
319
|
-
|
|
320
|
-
|
|
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.
|
|
343
|
+
this._opts.activeIndex = -1;
|
|
342
344
|
}
|
|
343
345
|
else {
|
|
344
346
|
this._isPlaceholderOptionActive = false;
|
|
345
|
-
this.
|
|
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.
|
|
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.
|
|
377
|
+
if (this._opts.activeIndex <= 0 && !(this.combobox && this.creatable)) {
|
|
456
378
|
return;
|
|
457
379
|
}
|
|
458
380
|
if (this._isPlaceholderOptionActive) {
|
|
459
|
-
const optionIndex = this.
|
|
460
|
-
this.
|
|
381
|
+
const optionIndex = this._opts.numOfVisibleOptions - 1;
|
|
382
|
+
this._opts.activeIndex = optionIndex;
|
|
461
383
|
this._isPlaceholderOptionActive = false;
|
|
462
384
|
}
|
|
463
385
|
else {
|
|
464
|
-
const
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
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.
|
|
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.
|
|
408
|
+
if (this._isPlaceholderOptionActive && this._opts.activeIndex === -1) {
|
|
488
409
|
return;
|
|
489
410
|
}
|
|
490
|
-
|
|
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.
|
|
415
|
+
this._opts.activeIndex = -1;
|
|
494
416
|
}
|
|
495
|
-
else if (
|
|
496
|
-
const
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
this._adjustOptionListScrollPos('down',
|
|
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.
|
|
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.
|
|
519
|
-
this.
|
|
520
|
-
this.
|
|
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.
|
|
524
|
-
this.
|
|
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.
|
|
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
|
|
496
|
+
active,
|
|
541
497
|
disabled: op.disabled,
|
|
542
498
|
option: true,
|
|
543
|
-
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.
|
|
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(
|
|
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
|
-
|
|
526
|
+
const foundOption = this._opts.getOptionByLabel(this._opts.filterPattern);
|
|
527
|
+
if (foundOption) {
|
|
574
528
|
return nothing;
|
|
575
529
|
}
|
|
576
|
-
if (this.creatable && this.
|
|
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.
|
|
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
|
-
|
|
551
|
+
const op = this._opts.getActiveOption();
|
|
552
|
+
if (!op) {
|
|
598
553
|
return nothing;
|
|
599
554
|
}
|
|
600
|
-
const { description } =
|
|
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
|
-
|
|
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 =
|
|
570
|
+
const classes = {
|
|
663
571
|
dropdown: true,
|
|
664
|
-
multiple: this.
|
|
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",
|
|
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
|
-
|
|
762
|
-
], VscodeSelectBase.prototype, "
|
|
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
|