@emuanalytics/flow-rdf-ui 4.1.3 → 4.1.4
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/dist/components/autocomplete/autocomplete.component.mjs +621 -0
- package/dist/components/autocomplete/autocomplete.mjs +5 -0
- package/dist/components/autocomplete/autocomplete.styles.mjs +233 -0
- package/dist/custom-elements.json +1199 -536
- package/dist/index.d.mts +193 -7
- package/dist/index.d.ts +193 -7
- package/dist/index.mjs +1 -0
- package/dist/package.json.mjs +1 -1
- package/dist/utilities/register-components.mjs +2 -0
- package/dist/vscode.html-custom-data.json +156 -57
- package/package.json +3 -3
|
@@ -0,0 +1,621 @@
|
|
|
1
|
+
import { html, nothing } from 'lit';
|
|
2
|
+
import { FlowRdfFormControl } from '../../internal/flow-ui-rdf-element.mjs';
|
|
3
|
+
import { property, state, query } from 'lit/decorators.js';
|
|
4
|
+
import { FormControlController } from '../../internal/form.mjs';
|
|
5
|
+
import { debounce } from '@emuanalytics/flow-rdf-core/utils';
|
|
6
|
+
import { watch } from '../../internal/watch.mjs';
|
|
7
|
+
import { boolean } from '../../internal/boolean.mjs';
|
|
8
|
+
import { classMap } from 'lit-html/directives/class-map.js';
|
|
9
|
+
import { HasSlotController } from '../../internal/slot.mjs';
|
|
10
|
+
import { LocalizeController as LocalizeController$1 } from '../../internal/localize.mjs';
|
|
11
|
+
import { ifDefined } from 'lit-html/directives/if-defined.js';
|
|
12
|
+
import FlowUiIcon from '../icon/icon.component.mjs';
|
|
13
|
+
import FlowUiPopup from '../popup/popup.component.mjs';
|
|
14
|
+
import styles from './autocomplete.styles.mjs';
|
|
15
|
+
import { getAnimation, setDefaultAnimation } from '../../utilities/animation-registry.mjs';
|
|
16
|
+
import { stopAnimations, animateTo } from '../../internal/animate.mjs';
|
|
17
|
+
|
|
18
|
+
var __defProp = Object.defineProperty;
|
|
19
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
20
|
+
var __decorateClass = (decorators, target, key, kind) => {
|
|
21
|
+
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
|
|
22
|
+
for (var i = decorators.length - 1, decorator; i >= 0; i--)
|
|
23
|
+
if (decorator = decorators[i])
|
|
24
|
+
result = (kind ? decorator(target, key, result) : decorator(result)) || result;
|
|
25
|
+
if (kind && result)
|
|
26
|
+
__defProp(target, key, result);
|
|
27
|
+
return result;
|
|
28
|
+
};
|
|
29
|
+
class FlowUiAutocomplete extends FlowRdfFormControl {
|
|
30
|
+
constructor() {
|
|
31
|
+
super(...arguments);
|
|
32
|
+
this.hasSlotController = new HasSlotController(this, "help-text", "label");
|
|
33
|
+
this.localize = new LocalizeController$1(this);
|
|
34
|
+
/** @internal Last time when the mousedown event was fired */
|
|
35
|
+
this.mouseDownAt = 0;
|
|
36
|
+
this.pendingChangeEvent = false;
|
|
37
|
+
this.pendingInputEvent = false;
|
|
38
|
+
this.hasOptions = false;
|
|
39
|
+
this.formControlController = new FormControlController(this, {
|
|
40
|
+
assumeInteractionOn: ["flow-ui-blur", "flow-ui-input"]
|
|
41
|
+
});
|
|
42
|
+
this.size = "medium";
|
|
43
|
+
this.filled = false;
|
|
44
|
+
this.pill = false;
|
|
45
|
+
this.label = "";
|
|
46
|
+
this.helpText = "";
|
|
47
|
+
this.placeholder = "";
|
|
48
|
+
this.disabled = false;
|
|
49
|
+
this.required = false;
|
|
50
|
+
this.inline = false;
|
|
51
|
+
this.divider = false;
|
|
52
|
+
this.hoist = false;
|
|
53
|
+
this.placement = "bottom";
|
|
54
|
+
this.value = "";
|
|
55
|
+
this.displayWith = (value) => value;
|
|
56
|
+
this.debounceDelay = 0;
|
|
57
|
+
this.clearable = false;
|
|
58
|
+
this.inputText = "";
|
|
59
|
+
this.open = false;
|
|
60
|
+
this.selectedOption = null;
|
|
61
|
+
this.currentOption = null;
|
|
62
|
+
this.hasFocus = false;
|
|
63
|
+
/** @internal Handle mouse and keyboard events in the document, outside the control. */
|
|
64
|
+
this.handleDocumentEvent = (event) => {
|
|
65
|
+
const path = event.composedPath();
|
|
66
|
+
if (this && !path.includes(this) && this.hasFocus) {
|
|
67
|
+
this.blur();
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
connectedCallback() {
|
|
72
|
+
super.connectedCallback();
|
|
73
|
+
this.disabled = boolean(this.disabled, true);
|
|
74
|
+
this.filled = boolean(this.filled, true);
|
|
75
|
+
this.pill = boolean(this.pill, true);
|
|
76
|
+
this.required = boolean(this.required, true);
|
|
77
|
+
this.inline = boolean(this.inline, true);
|
|
78
|
+
this.divider = boolean(this.divider, true);
|
|
79
|
+
this.clearable = boolean(this.clearable, true);
|
|
80
|
+
}
|
|
81
|
+
/** Gets the associated form, if one exists. */
|
|
82
|
+
getForm() {
|
|
83
|
+
return this.formControlController.getForm();
|
|
84
|
+
}
|
|
85
|
+
/** Gets the validity state object.*/
|
|
86
|
+
get validity() {
|
|
87
|
+
return this.input.validity;
|
|
88
|
+
}
|
|
89
|
+
/** Gets the validation message. */
|
|
90
|
+
get validationMessage() {
|
|
91
|
+
return this.input.validationMessage;
|
|
92
|
+
}
|
|
93
|
+
/** Checks for validity but does not show a validation message. Returns `true` when valid and `false` when invalid. */
|
|
94
|
+
checkValidity() {
|
|
95
|
+
return this.input.checkValidity();
|
|
96
|
+
}
|
|
97
|
+
/** Checks for validity and shows the browser's validation message if the control is invalid. */
|
|
98
|
+
reportValidity() {
|
|
99
|
+
return this.input.reportValidity();
|
|
100
|
+
}
|
|
101
|
+
/** Sets a custom validation message. Pass an empty string to restore validity. */
|
|
102
|
+
setCustomValidity(_) {
|
|
103
|
+
this.formControlController.updateValidity();
|
|
104
|
+
}
|
|
105
|
+
/** @internal Gets an array of all <flow-ui-option> elements */
|
|
106
|
+
getAllOptions() {
|
|
107
|
+
return [...this.querySelectorAll("flow-ui-option")];
|
|
108
|
+
}
|
|
109
|
+
/** @internal Gets the first <flow-ui-option> element */
|
|
110
|
+
getFirstOption() {
|
|
111
|
+
return this.querySelector("flow-ui-option");
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* @internal
|
|
115
|
+
* Un-highlights currently highlighted option
|
|
116
|
+
* and highlights the given option
|
|
117
|
+
*/
|
|
118
|
+
setCurrentOption(option) {
|
|
119
|
+
if (this.currentOption) {
|
|
120
|
+
this.currentOption.current = false;
|
|
121
|
+
}
|
|
122
|
+
option.current = true;
|
|
123
|
+
option.focus();
|
|
124
|
+
this.currentOption = option;
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* @internal
|
|
128
|
+
* Unselects currently selected option
|
|
129
|
+
* and selects the given option
|
|
130
|
+
*/
|
|
131
|
+
setSelectedOption(option) {
|
|
132
|
+
if (this.selectedOption) {
|
|
133
|
+
this.selectedOption.selected = false;
|
|
134
|
+
}
|
|
135
|
+
if (!option) {
|
|
136
|
+
this.selectedOption = null;
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
option.selected = true;
|
|
140
|
+
this.selectedOption = option;
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* @internal
|
|
144
|
+
* Sets the value of the control.
|
|
145
|
+
* Should trigger {@link handleValueChange} when value is set.
|
|
146
|
+
* By default, it will emit a `flow-ui-change` event.
|
|
147
|
+
*
|
|
148
|
+
* @param value - The value to set.
|
|
149
|
+
* @param emitChangeEvent - A change event will be emitted if true.
|
|
150
|
+
*/
|
|
151
|
+
setValue(value, options) {
|
|
152
|
+
this.pendingChangeEvent = options?.emitChangeEvent ?? false;
|
|
153
|
+
this.pendingInputEvent = options?.emitInputEvent ?? false;
|
|
154
|
+
this.value = value;
|
|
155
|
+
}
|
|
156
|
+
updateDebounceDelay() {
|
|
157
|
+
this.debouncedInput = debounce(
|
|
158
|
+
(inputText) => {
|
|
159
|
+
this.inputText = inputText;
|
|
160
|
+
this.emit("flow-ui-input");
|
|
161
|
+
this.toggleListbox();
|
|
162
|
+
},
|
|
163
|
+
this.debounceDelay,
|
|
164
|
+
{ leading: false, trailing: true, context: this }
|
|
165
|
+
);
|
|
166
|
+
}
|
|
167
|
+
/** @internal Handle the `flow-ui-input` event from the input box. */
|
|
168
|
+
handleInput(event) {
|
|
169
|
+
event.stopPropagation();
|
|
170
|
+
this.debouncedInput(this.input.value);
|
|
171
|
+
}
|
|
172
|
+
/** @internal Handle the `flow-ui-change` event from the input box */
|
|
173
|
+
handleInputChange(event) {
|
|
174
|
+
event.stopPropagation();
|
|
175
|
+
}
|
|
176
|
+
/** @internal Handle `flow-ui-focus` event from the input box. */
|
|
177
|
+
handleInputFocus(event) {
|
|
178
|
+
event.stopPropagation();
|
|
179
|
+
this.focus();
|
|
180
|
+
}
|
|
181
|
+
/** @internal Handle `flow-ui-focus` event from the input box. */
|
|
182
|
+
handleInputBlur(event) {
|
|
183
|
+
event.stopPropagation();
|
|
184
|
+
}
|
|
185
|
+
handleClearClick(event) {
|
|
186
|
+
event.stopPropagation();
|
|
187
|
+
event.preventDefault();
|
|
188
|
+
}
|
|
189
|
+
/** @internal Handle the `mousedown` event from the clear button */
|
|
190
|
+
handleClearMouseDown(event) {
|
|
191
|
+
event.stopPropagation();
|
|
192
|
+
event.preventDefault();
|
|
193
|
+
this.setValue("", { emitInputEvent: true });
|
|
194
|
+
this.input.focus({ preventScroll: true });
|
|
195
|
+
}
|
|
196
|
+
/** @internal Handle option selection when an option is clicked on */
|
|
197
|
+
async handleListboxClick(event) {
|
|
198
|
+
if (Date.now() - this.mouseDownAt < 200) {
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
const target = event.target;
|
|
202
|
+
const option = target.closest("flow-ui-option");
|
|
203
|
+
if (option && !option.disabled) {
|
|
204
|
+
this.setValue(option.value, { emitChangeEvent: true });
|
|
205
|
+
this.input.focus();
|
|
206
|
+
this.hide();
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
/** @internal */
|
|
210
|
+
handleKeyDown(event) {
|
|
211
|
+
if (event.key === "Escape" && this.open) {
|
|
212
|
+
event.preventDefault();
|
|
213
|
+
event.stopPropagation();
|
|
214
|
+
this.hide();
|
|
215
|
+
this.input.focus({ preventScroll: true });
|
|
216
|
+
}
|
|
217
|
+
if (["ArrowUp", "ArrowDown"].includes(event.key) && this.open) {
|
|
218
|
+
const allOptions = this.getAllOptions();
|
|
219
|
+
const currentIndex = this.currentOption ? allOptions.indexOf(this.currentOption) : 0;
|
|
220
|
+
let newIndex = Math.max(0, currentIndex);
|
|
221
|
+
event.preventDefault();
|
|
222
|
+
if (!this.open) {
|
|
223
|
+
this.show();
|
|
224
|
+
if (this.currentOption) {
|
|
225
|
+
return;
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
switch (event.key) {
|
|
229
|
+
case "ArrowDown": {
|
|
230
|
+
newIndex = currentIndex + 1;
|
|
231
|
+
if (newIndex >= allOptions.length) {
|
|
232
|
+
newIndex = 0;
|
|
233
|
+
}
|
|
234
|
+
break;
|
|
235
|
+
}
|
|
236
|
+
case "ArrowUp": {
|
|
237
|
+
newIndex = currentIndex - 1;
|
|
238
|
+
if (newIndex < 0) {
|
|
239
|
+
newIndex = allOptions.length - 1;
|
|
240
|
+
}
|
|
241
|
+
break;
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
this.setCurrentOption(allOptions[newIndex]);
|
|
245
|
+
}
|
|
246
|
+
if (event.key === "Enter" && this.open) {
|
|
247
|
+
event.preventDefault();
|
|
248
|
+
event.stopPropagation();
|
|
249
|
+
if (this.currentOption) {
|
|
250
|
+
this.setSelectedOption(this.currentOption);
|
|
251
|
+
this.setValue(this.currentOption.value, { emitChangeEvent: true });
|
|
252
|
+
}
|
|
253
|
+
this.hide();
|
|
254
|
+
this.input.focus({ preventScroll: true });
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
/** @internal Add event listeners to the document when the dropdown is opened. */
|
|
258
|
+
addListenersForDropdown() {
|
|
259
|
+
document.addEventListener("mousedown", this.handleDocumentEvent);
|
|
260
|
+
document.addEventListener("focusin", this.handleDocumentEvent);
|
|
261
|
+
document.addEventListener("keydown", this.handleDocumentEvent);
|
|
262
|
+
}
|
|
263
|
+
/** @internal Remove event listeners from the document when the dropdown is closed. */
|
|
264
|
+
removeListenersForDropdown() {
|
|
265
|
+
document.removeEventListener("mousedown", this.handleDocumentEvent);
|
|
266
|
+
document.removeEventListener("focusin", this.handleDocumentEvent);
|
|
267
|
+
document.addEventListener("keydown", this.handleDocumentEvent);
|
|
268
|
+
}
|
|
269
|
+
/** @internal Handles changes in the default slot */
|
|
270
|
+
handleDefaultSlotChange() {
|
|
271
|
+
const options = this.getAllOptions();
|
|
272
|
+
this.hasOptions = options.length > 0;
|
|
273
|
+
this.toggleListbox();
|
|
274
|
+
const firstOption = this.getFirstOption();
|
|
275
|
+
if (firstOption) {
|
|
276
|
+
this.setCurrentOption(firstOption);
|
|
277
|
+
}
|
|
278
|
+
this.setSelectedOption(null);
|
|
279
|
+
for (const option of options) {
|
|
280
|
+
if (option.value === this.value) {
|
|
281
|
+
this.setSelectedOption(option);
|
|
282
|
+
this.setCurrentOption(option);
|
|
283
|
+
break;
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
/** @internal Toggles listbox based on focus and options in the default slot. */
|
|
288
|
+
toggleListbox() {
|
|
289
|
+
if (this.hasFocus && this.hasOptions) {
|
|
290
|
+
this.show();
|
|
291
|
+
} else {
|
|
292
|
+
this.hide();
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
/**
|
|
296
|
+
* @internal
|
|
297
|
+
* Syncs the {@link displayValue} by applying {@link displayWith} based on the current {@link value}.
|
|
298
|
+
*/
|
|
299
|
+
async syncDisplayValue() {
|
|
300
|
+
await this.updateComplete.then(async () => {
|
|
301
|
+
this.inputText = await Promise.resolve(this.displayWith(this.value)) ?? "";
|
|
302
|
+
});
|
|
303
|
+
}
|
|
304
|
+
async handleValueChange(oldValue, value) {
|
|
305
|
+
if (value !== oldValue) {
|
|
306
|
+
await this.syncDisplayValue();
|
|
307
|
+
const options = this.getAllOptions();
|
|
308
|
+
this.setSelectedOption(null);
|
|
309
|
+
for (const option of options) {
|
|
310
|
+
if (option.value === this.value) {
|
|
311
|
+
this.setSelectedOption(option);
|
|
312
|
+
this.setCurrentOption(option);
|
|
313
|
+
break;
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
this.updateComplete.then(() => {
|
|
317
|
+
this.pendingChangeEvent && this.emit("flow-ui-change");
|
|
318
|
+
this.pendingInputEvent && this.emit("flow-ui-input");
|
|
319
|
+
this.pendingChangeEvent = false;
|
|
320
|
+
this.pendingInputEvent = false;
|
|
321
|
+
});
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
/** Focuses on the control */
|
|
325
|
+
focus() {
|
|
326
|
+
if (!this.hasFocus) {
|
|
327
|
+
this.hasFocus = true;
|
|
328
|
+
this.input.focus({ preventScroll: true });
|
|
329
|
+
this.emit("flow-ui-focus");
|
|
330
|
+
this.toggleListbox();
|
|
331
|
+
this.addListenersForDropdown();
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
/** Blurs from the control. */
|
|
335
|
+
blur() {
|
|
336
|
+
if (this.hasFocus) {
|
|
337
|
+
this.input.focus({ preventScroll: true });
|
|
338
|
+
this.hasFocus = false;
|
|
339
|
+
this.toggleListbox();
|
|
340
|
+
this.removeListenersForDropdown();
|
|
341
|
+
this.emit("flow-ui-blur");
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
/** Shows the listbox. */
|
|
345
|
+
async show() {
|
|
346
|
+
if (!this.open) {
|
|
347
|
+
this.emit("flow-ui-show");
|
|
348
|
+
await stopAnimations(this);
|
|
349
|
+
this.open = true;
|
|
350
|
+
const { keyframes, options } = getAnimation(this, "autocomplete.show", { dir: this.localize.dir() });
|
|
351
|
+
await animateTo(this.popup.popup, keyframes, options);
|
|
352
|
+
this.emit("flow-ui-after-show");
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
/** Hides the listbox. */
|
|
356
|
+
async hide() {
|
|
357
|
+
if (this.open) {
|
|
358
|
+
this.emit("flow-ui-hide");
|
|
359
|
+
await stopAnimations(this);
|
|
360
|
+
const { keyframes, options } = getAnimation(this, "autocomplete.hide", { dir: this.localize.dir() });
|
|
361
|
+
await animateTo(this.popup.popup, keyframes, options);
|
|
362
|
+
this.open = false;
|
|
363
|
+
this.emit("flow-ui-after-hide");
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
/** Gets the current value of the text input */
|
|
367
|
+
getInputText() {
|
|
368
|
+
return this.inputText;
|
|
369
|
+
}
|
|
370
|
+
/** @internal */
|
|
371
|
+
render() {
|
|
372
|
+
const hasLabelSlot = this.hasSlotController.test("label");
|
|
373
|
+
const hasHelpTextSlot = this.hasSlotController.test("help-text");
|
|
374
|
+
const hasLabel = !!this.label || !!hasLabelSlot;
|
|
375
|
+
const hasHelpText = !!this.helpText || !!hasHelpTextSlot;
|
|
376
|
+
const hasClearIcon = this.clearable && this.value.length > 0;
|
|
377
|
+
const isPlaceholderVisible = this.placeholder && this.inputText.length === 0;
|
|
378
|
+
const horizontalPlacement = this.inline ? "end" : "start";
|
|
379
|
+
const placement = `${this.placement}-${horizontalPlacement}`;
|
|
380
|
+
const strategy = this.inline || this.hoist ? "fixed" : "absolute";
|
|
381
|
+
const sync = this.inline ? void 0 : "width";
|
|
382
|
+
return html`
|
|
383
|
+
<div
|
|
384
|
+
part="form-control"
|
|
385
|
+
class=${classMap({
|
|
386
|
+
"form-control": true,
|
|
387
|
+
"form-control--small": this.size === "small",
|
|
388
|
+
"form-control--medium": this.size === "medium",
|
|
389
|
+
"form-control--large": this.size === "large",
|
|
390
|
+
"form-control--inline": this.inline,
|
|
391
|
+
"form-control--disabled": this.disabled,
|
|
392
|
+
"form-control--focused": this.hasFocus,
|
|
393
|
+
"form-control--has-label": hasLabel,
|
|
394
|
+
"form-control--has-help-text": hasHelpText,
|
|
395
|
+
"form-control--has-divider": this.divider,
|
|
396
|
+
"form-control--filled": this.filled,
|
|
397
|
+
"form-control--pill": this.pill
|
|
398
|
+
})}
|
|
399
|
+
>
|
|
400
|
+
<label
|
|
401
|
+
id="label"
|
|
402
|
+
part="label"
|
|
403
|
+
class="form-control__label"
|
|
404
|
+
aria-hidden=${hasLabel ? "false" : "true"}
|
|
405
|
+
>
|
|
406
|
+
<slot name="label">${this.label}</slot>
|
|
407
|
+
</label>
|
|
408
|
+
|
|
409
|
+
<div
|
|
410
|
+
part="help-text"
|
|
411
|
+
id="help-text"
|
|
412
|
+
class="form-control__help-text"
|
|
413
|
+
aria-hidden=${hasHelpText ? "false" : "true"}
|
|
414
|
+
>
|
|
415
|
+
<slot name="help-text">${this.helpText}</slot>
|
|
416
|
+
</div>
|
|
417
|
+
|
|
418
|
+
<div
|
|
419
|
+
part="control"
|
|
420
|
+
class="form-control__input"
|
|
421
|
+
>
|
|
422
|
+
<flow-ui-popup
|
|
423
|
+
class=${classMap({
|
|
424
|
+
autocomplete: true,
|
|
425
|
+
"autocomplete--standard": true,
|
|
426
|
+
"autocomplete--pill": this.pill,
|
|
427
|
+
"autocomplete--open": this.open,
|
|
428
|
+
"autocomplete--disabled": this.disabled,
|
|
429
|
+
"autocomplete--inline": this.inline,
|
|
430
|
+
"autocomplete--focused": this.hasFocus,
|
|
431
|
+
"autocomplete--placeholder-visible": isPlaceholderVisible,
|
|
432
|
+
"autocomplete--top": this.placement === "top",
|
|
433
|
+
"autocomplete--bottom": this.placement === "bottom",
|
|
434
|
+
"autocomplete--small": this.size === "small",
|
|
435
|
+
"autocomplete--medium": this.size === "medium",
|
|
436
|
+
"autocomplete--large": this.size === "large"
|
|
437
|
+
})}
|
|
438
|
+
?active=${this.open}
|
|
439
|
+
placement=${ifDefined(placement)}
|
|
440
|
+
strategy=${ifDefined(strategy)}
|
|
441
|
+
sync=${ifDefined(sync)}
|
|
442
|
+
flip
|
|
443
|
+
shift
|
|
444
|
+
auto-size="vertical"
|
|
445
|
+
auto-size-padding="10"
|
|
446
|
+
@keydown=${this.handleKeyDown}
|
|
447
|
+
>
|
|
448
|
+
<div
|
|
449
|
+
part="combobox"
|
|
450
|
+
class="autocomplete__combobox"
|
|
451
|
+
slot="anchor"
|
|
452
|
+
@keydown=${this.handleDocumentEvent}
|
|
453
|
+
@mousedown=${this.handleDocumentEvent}
|
|
454
|
+
>
|
|
455
|
+
<slot part="prefix" name="prefix" class="autocomplete__prefix"></slot>
|
|
456
|
+
|
|
457
|
+
<div class="autocomplete__input-wrapper">
|
|
458
|
+
<input
|
|
459
|
+
part="display-input"
|
|
460
|
+
class="autocomplete__input"
|
|
461
|
+
type="text"
|
|
462
|
+
autocomplete="off"
|
|
463
|
+
spellcheck="false"
|
|
464
|
+
autocapitalize="off"
|
|
465
|
+
aria-controls="listbox"
|
|
466
|
+
aria-expanded=${this.open ? "true" : "false"}
|
|
467
|
+
aria-haspopup="listbox"
|
|
468
|
+
aria-labelledby="label"
|
|
469
|
+
aria-disabled=${this.disabled ? "true" : "false"}
|
|
470
|
+
aria-describedby="help-text"
|
|
471
|
+
role="combobox"
|
|
472
|
+
tabindex="0"
|
|
473
|
+
placeholder=${this.placeholder}
|
|
474
|
+
.value=${this.inputText}
|
|
475
|
+
?disabled=${this.disabled}
|
|
476
|
+
@focus=${this.handleInputFocus}
|
|
477
|
+
@blur=${this.handleInputBlur}
|
|
478
|
+
@input=${this.handleInput}
|
|
479
|
+
@change=${this.handleInputChange}
|
|
480
|
+
/>
|
|
481
|
+
<span class="autocomplete__input-sizer">${this.inputText || this.placeholder}</span>
|
|
482
|
+
</div>
|
|
483
|
+
|
|
484
|
+
${hasClearIcon ? html`
|
|
485
|
+
<button
|
|
486
|
+
part="clear-button"
|
|
487
|
+
class="autocomplete__clear"
|
|
488
|
+
type="button"
|
|
489
|
+
aria-label=${this.localize.term("clearEntry")}
|
|
490
|
+
@mousedown=${this.handleClearMouseDown}
|
|
491
|
+
@click=${this.handleClearClick}
|
|
492
|
+
tabindex="-1"
|
|
493
|
+
>
|
|
494
|
+
<slot name="clear-icon">
|
|
495
|
+
<flow-ui-icon name="x-circle-fill" library="system"></flow-ui-icon>
|
|
496
|
+
</slot>
|
|
497
|
+
</button>
|
|
498
|
+
` : nothing}
|
|
499
|
+
|
|
500
|
+
<slot part="suffix" name="suffix" class="autocomplete__suffix"></slot>
|
|
501
|
+
</div>
|
|
502
|
+
|
|
503
|
+
<div
|
|
504
|
+
id="listbox"
|
|
505
|
+
role="listbox"
|
|
506
|
+
part="listbox"
|
|
507
|
+
class="autocomplete__listbox"
|
|
508
|
+
aria-expanded=${this.open ? "true" : "false"}
|
|
509
|
+
aria-multiselectable="false"
|
|
510
|
+
@mouseup=${this.handleListboxClick}
|
|
511
|
+
@slotchange=${this.handleDefaultSlotChange}
|
|
512
|
+
>
|
|
513
|
+
<slot></slot>
|
|
514
|
+
</div>
|
|
515
|
+
</flow-ui-popup>
|
|
516
|
+
</div>
|
|
517
|
+
|
|
518
|
+
${this.divider ? this.renderDivider() : nothing}
|
|
519
|
+
</div>
|
|
520
|
+
`;
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
FlowUiAutocomplete.styles = styles;
|
|
524
|
+
FlowUiAutocomplete.dependencies = {
|
|
525
|
+
"flow-ui-popup": FlowUiPopup,
|
|
526
|
+
"flow-ui-icon": FlowUiIcon
|
|
527
|
+
};
|
|
528
|
+
__decorateClass([
|
|
529
|
+
property({ reflect: true })
|
|
530
|
+
], FlowUiAutocomplete.prototype, "size", 2);
|
|
531
|
+
__decorateClass([
|
|
532
|
+
property({ type: Boolean, reflect: true })
|
|
533
|
+
], FlowUiAutocomplete.prototype, "filled", 2);
|
|
534
|
+
__decorateClass([
|
|
535
|
+
property({ type: Boolean, reflect: true })
|
|
536
|
+
], FlowUiAutocomplete.prototype, "pill", 2);
|
|
537
|
+
__decorateClass([
|
|
538
|
+
property()
|
|
539
|
+
], FlowUiAutocomplete.prototype, "label", 2);
|
|
540
|
+
__decorateClass([
|
|
541
|
+
property({ attribute: "help-text" })
|
|
542
|
+
], FlowUiAutocomplete.prototype, "helpText", 2);
|
|
543
|
+
__decorateClass([
|
|
544
|
+
property()
|
|
545
|
+
], FlowUiAutocomplete.prototype, "placeholder", 2);
|
|
546
|
+
__decorateClass([
|
|
547
|
+
property({ type: Boolean, reflect: true })
|
|
548
|
+
], FlowUiAutocomplete.prototype, "disabled", 2);
|
|
549
|
+
__decorateClass([
|
|
550
|
+
property()
|
|
551
|
+
], FlowUiAutocomplete.prototype, "form", 2);
|
|
552
|
+
__decorateClass([
|
|
553
|
+
property({ type: Boolean, reflect: true })
|
|
554
|
+
], FlowUiAutocomplete.prototype, "required", 2);
|
|
555
|
+
__decorateClass([
|
|
556
|
+
property({ type: Boolean, reflect: true })
|
|
557
|
+
], FlowUiAutocomplete.prototype, "inline", 2);
|
|
558
|
+
__decorateClass([
|
|
559
|
+
property({ type: Boolean, reflect: true })
|
|
560
|
+
], FlowUiAutocomplete.prototype, "divider", 2);
|
|
561
|
+
__decorateClass([
|
|
562
|
+
property({ type: Boolean })
|
|
563
|
+
], FlowUiAutocomplete.prototype, "hoist", 2);
|
|
564
|
+
__decorateClass([
|
|
565
|
+
property({ reflect: true })
|
|
566
|
+
], FlowUiAutocomplete.prototype, "placement", 2);
|
|
567
|
+
__decorateClass([
|
|
568
|
+
property()
|
|
569
|
+
], FlowUiAutocomplete.prototype, "value", 2);
|
|
570
|
+
__decorateClass([
|
|
571
|
+
property()
|
|
572
|
+
], FlowUiAutocomplete.prototype, "displayWith", 2);
|
|
573
|
+
__decorateClass([
|
|
574
|
+
property({ reflect: true, attribute: "debounce-delay", type: Number })
|
|
575
|
+
], FlowUiAutocomplete.prototype, "debounceDelay", 2);
|
|
576
|
+
__decorateClass([
|
|
577
|
+
property({ type: Boolean, reflect: true })
|
|
578
|
+
], FlowUiAutocomplete.prototype, "clearable", 2);
|
|
579
|
+
__decorateClass([
|
|
580
|
+
state()
|
|
581
|
+
], FlowUiAutocomplete.prototype, "inputText", 2);
|
|
582
|
+
__decorateClass([
|
|
583
|
+
state()
|
|
584
|
+
], FlowUiAutocomplete.prototype, "open", 2);
|
|
585
|
+
__decorateClass([
|
|
586
|
+
state()
|
|
587
|
+
], FlowUiAutocomplete.prototype, "selectedOption", 2);
|
|
588
|
+
__decorateClass([
|
|
589
|
+
state()
|
|
590
|
+
], FlowUiAutocomplete.prototype, "currentOption", 2);
|
|
591
|
+
__decorateClass([
|
|
592
|
+
state()
|
|
593
|
+
], FlowUiAutocomplete.prototype, "hasFocus", 2);
|
|
594
|
+
__decorateClass([
|
|
595
|
+
query(".autocomplete__input")
|
|
596
|
+
], FlowUiAutocomplete.prototype, "input", 2);
|
|
597
|
+
__decorateClass([
|
|
598
|
+
query(".autocomplete")
|
|
599
|
+
], FlowUiAutocomplete.prototype, "popup", 2);
|
|
600
|
+
__decorateClass([
|
|
601
|
+
watch("debounceDelay")
|
|
602
|
+
], FlowUiAutocomplete.prototype, "updateDebounceDelay", 1);
|
|
603
|
+
__decorateClass([
|
|
604
|
+
watch("value")
|
|
605
|
+
], FlowUiAutocomplete.prototype, "handleValueChange", 1);
|
|
606
|
+
setDefaultAnimation("autocomplete.show", {
|
|
607
|
+
keyframes: [
|
|
608
|
+
{ opacity: 0, scale: 0.9 },
|
|
609
|
+
{ opacity: 1, scale: 1 }
|
|
610
|
+
],
|
|
611
|
+
options: { duration: 100, easing: "ease" }
|
|
612
|
+
});
|
|
613
|
+
setDefaultAnimation("autocomplete.hide", {
|
|
614
|
+
keyframes: [
|
|
615
|
+
{ opacity: 1, scale: 1 },
|
|
616
|
+
{ opacity: 0, scale: 0.9 }
|
|
617
|
+
],
|
|
618
|
+
options: { duration: 100, easing: "ease" }
|
|
619
|
+
});
|
|
620
|
+
|
|
621
|
+
export { FlowUiAutocomplete as default };
|