@fluid-topics/ftds-combobox 2.0.37

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 (33) hide show
  1. package/build/BaseComboboxSuggestionProvider.d.ts +2 -0
  2. package/build/BaseComboboxSuggestionProvider.js +22 -0
  3. package/build/FtdsBaseComboboxMessages.d.ts +10 -0
  4. package/build/FtdsBaseComboboxMessages.js +9 -0
  5. package/build/FtdsComboboxMultiValueMessages.d.ts +10 -0
  6. package/build/FtdsComboboxMultiValueMessages.js +11 -0
  7. package/build/define.d.ts +1 -0
  8. package/build/define.js +3 -0
  9. package/build/definitions.d.ts +7 -0
  10. package/build/definitions.js +6 -0
  11. package/build/ftds-base-combobox.d.ts +71 -0
  12. package/build/ftds-base-combobox.js +540 -0
  13. package/build/ftds-base-combobox.properties.d.ts +39 -0
  14. package/build/ftds-base-combobox.properties.js +14 -0
  15. package/build/ftds-base-combobox.styles.d.ts +1 -0
  16. package/build/ftds-base-combobox.styles.js +111 -0
  17. package/build/ftds-combobox-multi-value.d.ts +30 -0
  18. package/build/ftds-combobox-multi-value.js +218 -0
  19. package/build/ftds-combobox-multi-value.properties.d.ts +14 -0
  20. package/build/ftds-combobox-multi-value.properties.js +5 -0
  21. package/build/ftds-combobox-multi-value.styles.d.ts +1 -0
  22. package/build/ftds-combobox-multi-value.styles.js +58 -0
  23. package/build/ftds-combobox.d.ts +21 -0
  24. package/build/ftds-combobox.js +96 -0
  25. package/build/ftds-combobox.light.js +3486 -0
  26. package/build/ftds-combobox.min.js +3607 -0
  27. package/build/ftds-combobox.properties.d.ts +8 -0
  28. package/build/ftds-combobox.properties.js +5 -0
  29. package/build/ftds-combobox.styles.d.ts +1 -0
  30. package/build/ftds-combobox.styles.js +36 -0
  31. package/build/index.d.ts +11 -0
  32. package/build/index.js +11 -0
  33. package/package.json +36 -0
@@ -0,0 +1,540 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ import { html, nothing, } from "lit";
8
+ import { property, query, state, } from "lit/decorators.js";
9
+ import { ifDefined } from "lit/directives/if-defined.js";
10
+ import { repeat } from "lit/directives/repeat.js";
11
+ import { classMap } from "lit/directives/class-map.js";
12
+ import { when } from "lit/directives/when.js";
13
+ import { Debouncer, FtdsBase, ignoreComposingEvents, numberProperty, processValidationRules, Status, toFtInput, } from "@fluid-topics/ft-wc-utils";
14
+ import { FtIcons, FtIconVariants, } from "@fluid-topics/ft-icon";
15
+ import { isActionableListboxItem, isSelectableListboxItem, ListboxItemType, } from "./ftds-base-combobox.properties";
16
+ import { withI18n } from "@fluid-topics/ft-i18n";
17
+ import { baseComboboxContext, defaultBaseComboboxMessages, } from "./FtdsBaseComboboxMessages";
18
+ import { FtdsTypography, FtdsTypographyVariants, } from "@fluid-topics/ft-typography";
19
+ import { FtdsBaseInput } from "@fluid-topics/ft-base-input";
20
+ import { FtdsNotice } from "@fluid-topics/ft-notice";
21
+ // TS2562: base class expressions cannot reference class type parameters, so we
22
+ // fix V=any here and restore the generic via `declare value: T` below.
23
+ const FtdsBaseComboboxBase = withI18n(toFtInput(FtdsBase));
24
+ export class FtdsBaseCombobox extends FtdsBaseComboboxBase {
25
+ constructor() {
26
+ super();
27
+ this.suggestionsProvider = () => [];
28
+ this.filterSuggestions = false;
29
+ this.canOfferNewValue = false;
30
+ this.required = false;
31
+ this.maxDisplayedSuggestions = 100;
32
+ this.newValueValidationRules = [];
33
+ this.isOpen = false;
34
+ this.inputValue = "";
35
+ this.activeIndex = -1;
36
+ this.providedSuggestions = [];
37
+ this.ariaLiveMessage = "";
38
+ this.ariaDescribedBy = "";
39
+ this.listboxItems = [];
40
+ this.listboxId = `ftds-combobox-listbox-${Math.random().toString(36).slice(2)}`;
41
+ // Close the menu when a click is triggered outside the listbox (inspired by W3C examples)
42
+ this.onBackgroundPointerUp = (event) => {
43
+ // Use composedPath to handle Shadow DOM correctly
44
+ const path = event.composedPath();
45
+ const clickedInside = path.includes(this);
46
+ if (!clickedInside) {
47
+ this.closeMenu();
48
+ }
49
+ };
50
+ this.addI18nContext(baseComboboxContext, defaultBaseComboboxMessages);
51
+ }
52
+ willUpdate(props) {
53
+ super.willUpdate(props);
54
+ if (props.has("debouncerTimeout")) {
55
+ this.debounceTimer = this.debouncerTimeout && this.debouncerTimeout > 0
56
+ ? new Debouncer(this.debouncerTimeout)
57
+ : undefined;
58
+ }
59
+ if (props.has("value") && props.get("value") !== undefined) {
60
+ this.onInput();
61
+ }
62
+ }
63
+ connectedCallback() {
64
+ super.connectedCallback();
65
+ document.body.addEventListener("pointerup", this.onBackgroundPointerUp);
66
+ }
67
+ disconnectedCallback() {
68
+ super.disconnectedCallback();
69
+ document.body.removeEventListener("pointerup", this.onBackgroundPointerUp);
70
+ }
71
+ get shouldRaiseLabel() {
72
+ return this.focused || this.inputValue != "";
73
+ }
74
+ get filteredSuggestions() {
75
+ const base = this.filterSuggestions
76
+ ? this.providedSuggestions
77
+ .filter((s) => s.label.toLowerCase().includes(this.inputValue.toLowerCase()))
78
+ : this.providedSuggestions;
79
+ return [...base];
80
+ }
81
+ get filteredSuggestionsWithLimit() {
82
+ return this.filteredSuggestions.slice(0, this.maxDisplayedSuggestions);
83
+ }
84
+ get appendIcon() {
85
+ return this.isOpen ? FtIcons.THIN_ARROW_UP : FtIcons.THIN_ARROW;
86
+ }
87
+ get activeItemId() {
88
+ if (!this.isOpen || this.activeIndex < 0 || this.activeIndex >= this.listboxItems.length) {
89
+ return undefined;
90
+ }
91
+ return this.suggestionId(this.activeIndex);
92
+ }
93
+ renderField() {
94
+ return html `
95
+ <ftds-base-input
96
+ .status=${this.status}
97
+ .size=${this.size}
98
+ .errorMessages=${this.errorMessages}
99
+ .warningMessages=${this.warningMessages}
100
+ .helperText=${this.helperText}
101
+ .label=${ifDefined(this.label)}
102
+ ?hideLabel=${this.hideLabel}
103
+ ?raiseLabel=${this.shouldRaiseLabel}
104
+ ?disabled=${this.disabled}
105
+ .appendIcon=${this.appendIcon}
106
+ .appendIconVariant=${FtIconVariants.fluid_topics}
107
+ .appendIconLabel=${this.isOpen ? baseComboboxContext.messages.closeMenu() : baseComboboxContext.messages.openMenu()}
108
+ @click=${() => this.onInputClick()}
109
+ >
110
+ <input
111
+ role="combobox"
112
+ name="${ifDefined(this.name)}"
113
+ aria-autocomplete="list"
114
+ aria-haspopup="listbox"
115
+ aria-expanded="${this.isOpen}"
116
+ aria-controls="${this.listboxId}"
117
+ aria-activedescendant="${ifDefined(this.activeItemId)}"
118
+ aria-label="${ifDefined(this.label)}"
119
+ aria-invalid="${this.status === Status.error}"
120
+ aria-disabled="${this.disabled}"
121
+ aria-required="${this.required}"
122
+ aria-describedby="${this.listboxId + "-described-by"}"
123
+ .value=${this.inputValue}
124
+ ?disabled=${this.disabled}
125
+ @input=${(e) => this.onType(e)}
126
+ @focus=${() => this.onFocus()}
127
+ @blur=${() => this.onBlur()}
128
+ @keydown=${(e) => this.onKeyDown(e)}
129
+ />
130
+ </ftds-base-input>
131
+ <div class="sr-only" id="${this.listboxId + "-described-by"}">${this.ariaDescribedBy}</div>
132
+ <div class="sr-only" role="status">${this.ariaLiveMessage}</div>
133
+ `;
134
+ }
135
+ renderListboxContainer(isMultiSelectable) {
136
+ const hidden = !this.isOpen;
137
+ const listboxClasses = {
138
+ "listbox": true,
139
+ ...this.getDesignSystemBaseClasses(),
140
+ };
141
+ return html `
142
+ <ul
143
+ class="${classMap(listboxClasses)}"
144
+ id="${this.listboxId}"
145
+ role="listbox"
146
+ aria-multiselectable="${isMultiSelectable}"
147
+ ?hidden=${hidden}
148
+ >
149
+ ${repeat(this.listboxItems, (s) => { var _a; return `${s.type === ListboxItemType.suggestion ? s.value : (_a = s.type) !== null && _a !== void 0 ? _a : ""}`; }, (s, i) => this.renderListboxItem(s, i))}
150
+ </ul>
151
+ `;
152
+ }
153
+ renderListboxItem(listboxItem, index) {
154
+ if (listboxItem.type === ListboxItemType.noResult) {
155
+ return this.renderNoResult(index);
156
+ }
157
+ if (listboxItem.type === ListboxItemType.maxSuggestions) {
158
+ return this.renderMaxSuggestionsItem(index);
159
+ }
160
+ if (listboxItem.type === ListboxItemType.newValue && isSelectableListboxItem(listboxItem)) {
161
+ return this.renderNewValueSuggestion(listboxItem, index);
162
+ }
163
+ if (isSelectableListboxItem(listboxItem)) {
164
+ return this.renderSuggestion(listboxItem, index);
165
+ }
166
+ return nothing;
167
+ }
168
+ renderSuggestion(suggestion, index) {
169
+ const isActive = this.activeIndex === index;
170
+ const isSelected = this.isSuggestionSelected(suggestion.value);
171
+ return html `
172
+ <li
173
+ id="${this.suggestionId(index)}"
174
+ class="listbox-option"
175
+ role="option"
176
+ aria-selected="${isSelected}"
177
+ data-active="${isActive}"
178
+ @mousedown=${(e) => e.preventDefault()}
179
+ @click=${() => this.onItemSelected(index)}
180
+ >
181
+ <div class="listbox-option--label">
182
+ ${this.renderSuggestionItem(suggestion, isSelected)}
183
+ </div>
184
+ </li>`;
185
+ }
186
+ renderNewValueSuggestion(suggestion, index) {
187
+ const isActive = this.activeIndex === index;
188
+ const isSelected = this.isSuggestionSelected(suggestion.value);
189
+ const validationErrors = processValidationRules(this.inputValue, this.newValueValidationRules);
190
+ const isValidationErrors = validationErrors.length > 0;
191
+ const classes = classMap({
192
+ "listbox-option": true,
193
+ "listbox-option--new-value": true,
194
+ "listbox-option--new-value--error": isValidationErrors,
195
+ });
196
+ return html `
197
+ <li
198
+ id="${this.suggestionId(index)}"
199
+ class="${classes}"
200
+ role="option"
201
+ aria-selected="${isSelected}"
202
+ data-active="${isActive}"
203
+ @mousedown=${(e) => e.preventDefault()}
204
+ @click=${() => this.onItemSelected(index)}
205
+ >
206
+ ${this.renderNewValueTag()}
207
+ ${when(isValidationErrors, () => this.renderNewValueValidationErrors(validationErrors), () => this.renderNewValueLabel(suggestion, isSelected))}
208
+ </li>`;
209
+ }
210
+ renderNewValueTag() {
211
+ return html `
212
+ <ftds-typography
213
+ variant="${FtdsTypographyVariants.caption2medium}"
214
+ class="listbox-option--helper"
215
+ >
216
+ ${baseComboboxContext.messages.newValueLabel()}
217
+ </ftds-typography>`;
218
+ }
219
+ renderNewValueLabel(suggestion, isSelected) {
220
+ return html `
221
+ <div class="listbox-option--label">
222
+ ${this.renderSuggestionItem(suggestion, isSelected)}
223
+ </div>`;
224
+ }
225
+ renderNewValueValidationErrors(validationErrors) {
226
+ return html `${validationErrors.map((error) => html `
227
+ <ftds-notice
228
+ family="error"
229
+ dense>
230
+ ${error}
231
+ </ftds-notice>
232
+ `)}`;
233
+ }
234
+ renderMaxSuggestionsItem(index) {
235
+ const id = this.suggestionId(index);
236
+ return html `
237
+ <li id="${id}"
238
+ class="listbox-option--message--max"
239
+ role="option"
240
+ aria-hidden="true"
241
+ >
242
+ <ftds-typography variant="${FtdsTypographyVariants.body2medium}">
243
+ ${baseComboboxContext.messages.maxSuggestionsLabel(this.maxDisplayedSuggestions)}
244
+ </ftds-typography>
245
+ <ftds-typography variant="${FtdsTypographyVariants.body2medium}">
246
+ ${baseComboboxContext.messages.refineYourSearchLabel()}
247
+ </ftds-typography>
248
+ </li>
249
+ `;
250
+ }
251
+ renderNoResult(index) {
252
+ const id = this.suggestionId(index);
253
+ return html `
254
+ <li id="${id}"
255
+ class="listbox-option--message--no-option"
256
+ role="option"
257
+ aria-hidden="true"
258
+ >
259
+ <ftds-typography variant="${FtdsTypographyVariants.body2medium}">
260
+ ${baseComboboxContext.messages.noResultLabel()}
261
+ </ftds-typography>
262
+ </li>
263
+ `;
264
+ }
265
+ async computeListboxItems() {
266
+ await this.computeSuggestions();
267
+ this.listboxItems = await this.getListboxItems();
268
+ void this.setAriaDescribeBy();
269
+ }
270
+ async getListboxItems() {
271
+ const filteredListboxItems = this.filteredSuggestions;
272
+ const listboxItemsWithLimit = this.filteredSuggestionsWithLimit;
273
+ const exactMatch = this.filteredSuggestions.some((s) => s.label.toLowerCase() === this.inputValue.toLowerCase());
274
+ const shouldShowNewValue = this.canOfferNewValue && this.inputValue !== "" && !exactMatch;
275
+ const shouldShowNoResults = !this.canOfferNewValue && this.filteredSuggestions.length === 0 && this.inputValue !== "";
276
+ if (shouldShowNewValue) {
277
+ listboxItemsWithLimit.push({ label: this.inputValue, value: this.inputValue, type: ListboxItemType.newValue });
278
+ }
279
+ else if (shouldShowNoResults) {
280
+ listboxItemsWithLimit.push({ type: ListboxItemType.noResult });
281
+ }
282
+ const shouldShowMaxSuggestionsReached = filteredListboxItems.length > this.maxDisplayedSuggestions;
283
+ if (shouldShowMaxSuggestionsReached) {
284
+ listboxItemsWithLimit.push({ type: ListboxItemType.maxSuggestions });
285
+ }
286
+ return listboxItemsWithLimit;
287
+ }
288
+ async setAriaDescribeBy() {
289
+ this.ariaLiveMessage = "";
290
+ await this.updateComplete;
291
+ if (this.filteredSuggestions.length === 0) {
292
+ this.ariaLiveMessage = baseComboboxContext.messages.noResultLabel();
293
+ }
294
+ if (this.maxDisplayedSuggestions < this.filteredSuggestions.length) {
295
+ this.ariaLiveMessage = baseComboboxContext.messages.maxSuggestionsAriaLabel(this.maxDisplayedSuggestions);
296
+ }
297
+ }
298
+ async computeSuggestions() {
299
+ var _a;
300
+ if (this.debouncerTimeout && this.debouncerTimeout > 0) {
301
+ (_a = this.debounceTimer) !== null && _a !== void 0 ? _a : (this.debounceTimer = new Debouncer(this.debouncerTimeout));
302
+ await this.debounceTimer.run(() => this.runSuggestionsProvider());
303
+ }
304
+ else {
305
+ return this.runSuggestionsProvider();
306
+ }
307
+ }
308
+ async runSuggestionsProvider() {
309
+ const suggestions = await this.suggestionsProvider(this.inputValue);
310
+ this.providedSuggestions = suggestions.map((s) => ({ ...s, type: ListboxItemType.suggestion }));
311
+ }
312
+ suggestionId(index) {
313
+ return `${this.listboxId}-option-${index}`;
314
+ }
315
+ async onType(e) {
316
+ if (this.disabled) {
317
+ return;
318
+ }
319
+ this.inputValue = e.target.value;
320
+ if (!this.isOpen) {
321
+ await this.openMenu();
322
+ }
323
+ else {
324
+ await this.computeListboxItems();
325
+ }
326
+ this.activeIndex = -1;
327
+ }
328
+ async onInputClick() {
329
+ if (this.disabled) {
330
+ return;
331
+ }
332
+ if (!this.isOpen) {
333
+ await this.openMenu();
334
+ }
335
+ else {
336
+ this.closeMenu();
337
+ }
338
+ }
339
+ onBlur() {
340
+ if (this.disabled) {
341
+ return;
342
+ }
343
+ if (this.isOpen) {
344
+ this.closeMenu();
345
+ }
346
+ this.handleBlurStrategy();
347
+ super.onBlur();
348
+ }
349
+ async openMenu() {
350
+ if (this.disabled || this.isOpen) {
351
+ return;
352
+ }
353
+ await this.computeListboxItems();
354
+ this.isOpen = true;
355
+ }
356
+ closeMenu() {
357
+ if (!this.isOpen) {
358
+ return;
359
+ }
360
+ this.isOpen = false;
361
+ this.activeIndex = -1;
362
+ }
363
+ onItemSelected(index) {
364
+ if (this.disabled) {
365
+ return;
366
+ }
367
+ const suggestion = this.listboxItems[index];
368
+ if (!suggestion) {
369
+ return;
370
+ }
371
+ if (isActionableListboxItem(suggestion)) {
372
+ this.commitSelection(suggestion);
373
+ }
374
+ }
375
+ async onKeyDown(e) {
376
+ var _a, _b;
377
+ if (this.disabled) {
378
+ return;
379
+ }
380
+ switch (e.key) {
381
+ case "ArrowDown":
382
+ e.preventDefault();
383
+ if (e.altKey) {
384
+ if (!this.isOpen) {
385
+ await this.openMenu();
386
+ }
387
+ return;
388
+ }
389
+ if (!this.isOpen) {
390
+ await this.openMenu();
391
+ const indices = this.getSelectableIndexes();
392
+ this.activeIndex = (_a = indices[0]) !== null && _a !== void 0 ? _a : -1;
393
+ }
394
+ else {
395
+ this.moveActiveIndex(1);
396
+ }
397
+ return;
398
+ case "ArrowUp":
399
+ e.preventDefault();
400
+ if (!this.isOpen) {
401
+ await this.openMenu();
402
+ const indices = this.getSelectableIndexes();
403
+ this.activeIndex = (_b = indices[indices.length - 1]) !== null && _b !== void 0 ? _b : -1;
404
+ }
405
+ else {
406
+ this.moveActiveIndex(-1);
407
+ }
408
+ return;
409
+ case "ArrowRight":
410
+ case "ArrowLeft":
411
+ case "Home":
412
+ case "End":
413
+ this.activeIndex = -1;
414
+ return;
415
+ case "Enter":
416
+ if (!this.isOpen) {
417
+ return;
418
+ }
419
+ e.preventDefault();
420
+ if (this.activeIndex >= 0) {
421
+ this.onItemSelected(this.activeIndex);
422
+ }
423
+ else {
424
+ this.closeMenu();
425
+ }
426
+ return;
427
+ case "Escape":
428
+ e.preventDefault();
429
+ if (this.isOpen) {
430
+ this.closeMenu();
431
+ }
432
+ else {
433
+ this.inputValue = "";
434
+ }
435
+ return;
436
+ case "Tab":
437
+ if (this.isOpen) {
438
+ this.closeMenu();
439
+ }
440
+ return;
441
+ }
442
+ }
443
+ getSelectableIndexes() {
444
+ return this.listboxItems.reduce((indexes, item, currentIndex) => isActionableListboxItem(item) ? [...indexes, currentIndex] : indexes, []);
445
+ }
446
+ moveActiveIndex(direction) {
447
+ const selectableIndices = this.getSelectableIndexes();
448
+ if (selectableIndices.length === 0) {
449
+ this.activeIndex = -1;
450
+ return;
451
+ }
452
+ const currentPos = selectableIndices.indexOf(this.activeIndex);
453
+ const nextPos = currentPos === -1
454
+ ? (direction === 1 ? 0 : selectableIndices.length - 1)
455
+ : (currentPos + direction + selectableIndices.length) % selectableIndices.length;
456
+ this.activeIndex = selectableIndices[nextPos];
457
+ this.scrollSuggestionIntoView(this.activeIndex);
458
+ }
459
+ scrollSuggestionIntoView(suggestionIndex) {
460
+ requestAnimationFrame(() => {
461
+ const elementToScrollTo = this.getElementToScrollTo(suggestionIndex);
462
+ if (elementToScrollTo && elementToScrollTo instanceof HTMLElement && this.listbox) {
463
+ const needToScrollDown = this.listbox.scrollTop + this.listbox.offsetHeight < elementToScrollTo.offsetTop + elementToScrollTo.offsetHeight;
464
+ const needToScrollUp = this.listbox.scrollTop > elementToScrollTo.offsetTop + 2;
465
+ if (needToScrollDown) {
466
+ this.listbox.scrollTop = elementToScrollTo.offsetTop + elementToScrollTo.offsetHeight - this.listbox.offsetHeight;
467
+ }
468
+ else if (needToScrollUp) {
469
+ this.listbox.scrollTop = elementToScrollTo.offsetTop;
470
+ }
471
+ }
472
+ });
473
+ }
474
+ // When reaching the last suggestion we want to scroll down more to put the max suggestions message into view
475
+ getElementToScrollTo(suggestionIndex) {
476
+ var _a, _b, _c, _d, _e;
477
+ const isLastSuggestion = ((_c = (_b = (_a = this.listbox) === null || _a === void 0 ? void 0 : _a.querySelectorAll(".listbox-option")) === null || _b === void 0 ? void 0 : _b.length) !== null && _c !== void 0 ? _c : 0) - 1 === suggestionIndex;
478
+ const maxSuggestionElement = (_d = this.listbox) === null || _d === void 0 ? void 0 : _d.querySelector(".listbox-option--message--max");
479
+ if (isLastSuggestion && maxSuggestionElement) {
480
+ return maxSuggestionElement;
481
+ }
482
+ return (_e = this.listbox) === null || _e === void 0 ? void 0 : _e.children.item(suggestionIndex);
483
+ }
484
+ }
485
+ FtdsBaseCombobox.baseComboboxElementDefinitions = {
486
+ "ftds-base-input": FtdsBaseInput,
487
+ "ftds-typography": FtdsTypography,
488
+ "ftds-notice": FtdsNotice,
489
+ };
490
+ __decorate([
491
+ property({ attribute: false })
492
+ ], FtdsBaseCombobox.prototype, "suggestionsProvider", void 0);
493
+ __decorate([
494
+ numberProperty()
495
+ ], FtdsBaseCombobox.prototype, "debouncerTimeout", void 0);
496
+ __decorate([
497
+ property({ type: Boolean })
498
+ ], FtdsBaseCombobox.prototype, "filterSuggestions", void 0);
499
+ __decorate([
500
+ property({ type: Boolean })
501
+ ], FtdsBaseCombobox.prototype, "canOfferNewValue", void 0);
502
+ __decorate([
503
+ property({ type: Boolean })
504
+ ], FtdsBaseCombobox.prototype, "required", void 0);
505
+ __decorate([
506
+ numberProperty()
507
+ ], FtdsBaseCombobox.prototype, "maxDisplayedSuggestions", void 0);
508
+ __decorate([
509
+ property()
510
+ ], FtdsBaseCombobox.prototype, "newValueValidationRules", void 0);
511
+ __decorate([
512
+ state()
513
+ ], FtdsBaseCombobox.prototype, "isOpen", void 0);
514
+ __decorate([
515
+ state()
516
+ ], FtdsBaseCombobox.prototype, "inputValue", void 0);
517
+ __decorate([
518
+ state()
519
+ ], FtdsBaseCombobox.prototype, "activeIndex", void 0);
520
+ __decorate([
521
+ state()
522
+ ], FtdsBaseCombobox.prototype, "providedSuggestions", void 0);
523
+ __decorate([
524
+ state()
525
+ ], FtdsBaseCombobox.prototype, "ariaLiveMessage", void 0);
526
+ __decorate([
527
+ state()
528
+ ], FtdsBaseCombobox.prototype, "ariaDescribedBy", void 0);
529
+ __decorate([
530
+ state()
531
+ ], FtdsBaseCombobox.prototype, "listboxItems", void 0);
532
+ __decorate([
533
+ query("input")
534
+ ], FtdsBaseCombobox.prototype, "input", void 0);
535
+ __decorate([
536
+ query(".listbox")
537
+ ], FtdsBaseCombobox.prototype, "listbox", void 0);
538
+ __decorate([
539
+ ignoreComposingEvents()
540
+ ], FtdsBaseCombobox.prototype, "onKeyDown", null);
@@ -0,0 +1,39 @@
1
+ import { FtdsBaseInterface } from "@fluid-topics/ft-wc-utils/build/FtdsBase";
2
+ import { FtInputInterface, ValidationRule } from "@fluid-topics/ft-wc-utils";
3
+ export interface ComboboxSuggestion {
4
+ label: string;
5
+ value: string;
6
+ }
7
+ export declare enum ListboxItemType {
8
+ suggestion = 0,
9
+ noResult = 1,
10
+ newValue = 2,
11
+ maxSuggestions = 3,
12
+ all = 4
13
+ }
14
+ export interface SuggestionListboxItem {
15
+ label: string;
16
+ value: string;
17
+ type: ListboxItemType.suggestion | ListboxItemType.newValue;
18
+ }
19
+ export interface SelectAllListboxItem {
20
+ type: ListboxItemType.all;
21
+ }
22
+ export interface NonSelectableListboxItem {
23
+ type: ListboxItemType.noResult | ListboxItemType.maxSuggestions;
24
+ }
25
+ export type ActionableListboxItem = SuggestionListboxItem | SelectAllListboxItem;
26
+ export type ListboxItem = ActionableListboxItem | NonSelectableListboxItem;
27
+ export declare function isActionableListboxItem(item: ListboxItem): item is ActionableListboxItem;
28
+ export declare function isSelectableListboxItem(item: ListboxItem): item is SuggestionListboxItem;
29
+ export type SuggestionsProvider = (filter: string) => ComboboxSuggestion[] | Promise<ComboboxSuggestion[]>;
30
+ export interface FtdsBaseComboboxProperties extends FtdsBaseInterface, FtInputInterface<any> {
31
+ required: boolean;
32
+ placeholder?: string;
33
+ suggestionsProvider: SuggestionsProvider;
34
+ debouncerTimeout?: number;
35
+ filterSuggestions: boolean;
36
+ canOfferNewValue: boolean;
37
+ maxDisplayedSuggestions: number;
38
+ newValueValidationRules: Array<ValidationRule<string>>;
39
+ }
@@ -0,0 +1,14 @@
1
+ export var ListboxItemType;
2
+ (function (ListboxItemType) {
3
+ ListboxItemType[ListboxItemType["suggestion"] = 0] = "suggestion";
4
+ ListboxItemType[ListboxItemType["noResult"] = 1] = "noResult";
5
+ ListboxItemType[ListboxItemType["newValue"] = 2] = "newValue";
6
+ ListboxItemType[ListboxItemType["maxSuggestions"] = 3] = "maxSuggestions";
7
+ ListboxItemType[ListboxItemType["all"] = 4] = "all";
8
+ })(ListboxItemType || (ListboxItemType = {}));
9
+ export function isActionableListboxItem(item) {
10
+ return item.type === ListboxItemType.suggestion || item.type === ListboxItemType.newValue || item.type === ListboxItemType.all;
11
+ }
12
+ export function isSelectableListboxItem(item) {
13
+ return item.type === ListboxItemType.suggestion || item.type === ListboxItemType.newValue;
14
+ }
@@ -0,0 +1 @@
1
+ export declare const baseComboboxStyles: import("lit").CSSResult;