@destyler/combobox 0.0.6 → 0.0.7-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -1,50 +1,1475 @@
1
1
  'use strict';
2
2
 
3
- const index = require('./component.cjs');
4
- require('vue');
5
- require('@destyler/primitive');
6
- require('@destyler/composition');
7
- require('@destyler/popper');
8
- require('@destyler/popper/component');
9
- require('@destyler/shared');
10
- require('@destyler/visually-hidden/component');
11
- require('@destyler/collection/composition');
12
- require('@destyler/collection');
13
- require('@destyler/dismissable-layer');
14
- require('@destyler/dismissable-layer/component');
15
- require('@destyler/directives');
16
- require('@destyler/presence');
17
- require('@destyler/teleport');
3
+ const anatomy$1 = require('@zag-js/anatomy');
4
+ const collection$1 = require('@zag-js/collection');
5
+ const core = require('@zag-js/core');
6
+ const domEvent = require('@zag-js/dom-event');
7
+ const domQuery = require('@zag-js/dom-query');
8
+ const popper = require('@zag-js/popper');
9
+ const ariaHidden = require('@zag-js/aria-hidden');
10
+ const dismissable = require('@zag-js/dismissable');
11
+ const utils = require('@zag-js/utils');
18
12
 
13
+ const anatomy = anatomy$1.createAnatomy("combobox").parts(
14
+ "root",
15
+ "clearTrigger",
16
+ "content",
17
+ "control",
18
+ "input",
19
+ "item",
20
+ "itemGroup",
21
+ "itemGroupLabel",
22
+ "itemIndicator",
23
+ "itemText",
24
+ "label",
25
+ "list",
26
+ "positioner",
27
+ "trigger"
28
+ );
29
+ const parts = anatomy.build();
19
30
 
31
+ function collection(options) {
32
+ return core.ref(new collection$1.ListCollection(options));
33
+ }
34
+ collection.empty = () => {
35
+ return core.ref(new collection$1.ListCollection({ items: [] }));
36
+ };
20
37
 
21
- exports.ComboboxAnchor = index.ComboboxAnchor;
22
- exports.ComboboxArrow = index.ComboboxArrow;
23
- exports.ComboboxCancel = index.ComboboxCancel;
24
- exports.ComboboxContent = index.ComboboxContent;
25
- exports.ComboboxEmpty = index.ComboboxEmpty;
26
- exports.ComboboxGroup = index.ComboboxGroup;
27
- exports.ComboboxInput = index.ComboboxInput;
28
- exports.ComboboxItem = index.ComboboxItem;
29
- exports.ComboboxItemIndicator = index.ComboboxItemIndicator;
30
- exports.ComboboxLabel = index.ComboboxLabel;
31
- exports.ComboboxPortal = index.ComboboxPortal;
32
- exports.ComboboxRoot = index.ComboboxRoot;
33
- exports.ComboboxSeparator = index.ComboboxSeparator;
34
- exports.ComboboxTrigger = index.ComboboxTrigger;
35
- exports.ComboboxViewport = index.ComboboxViewport;
36
- exports.comboboxAnchorProps = index.comboboxAnchorProps;
37
- exports.comboboxArrowProps = index.comboboxArrowProps;
38
- exports.comboboxCancelProps = index.comboboxCancelProps;
39
- exports.comboboxContentProps = index.comboboxContentProps;
40
- exports.comboboxEmptyProps = index.comboboxEmptyProps;
41
- exports.comboboxGroupProps = index.comboboxGroupProps;
42
- exports.comboboxInputProps = index.comboboxInputProps;
43
- exports.comboboxItemIndicatorProps = index.comboboxItemIndicatorProps;
44
- exports.comboboxItemProps = index.comboboxItemProps;
45
- exports.comboboxLabelProps = index.comboboxLabelProps;
46
- exports.comboboxPortalProps = index.comboboxPortalProps;
47
- exports.comboboxRootProps = index.comboboxRootProps;
48
- exports.comboboxSeparatorProps = index.comboboxSeparatorProps;
49
- exports.comboboxTriggerProps = index.comboboxTriggerProps;
50
- exports.comboboxViewportProps = index.comboboxViewportProps;
38
+ const dom = domQuery.createScope({
39
+ getRootId: (ctx) => ctx.ids?.root ?? `combobox:${ctx.id}`,
40
+ getLabelId: (ctx) => ctx.ids?.label ?? `combobox:${ctx.id}:label`,
41
+ getControlId: (ctx) => ctx.ids?.control ?? `combobox:${ctx.id}:control`,
42
+ getInputId: (ctx) => ctx.ids?.input ?? `combobox:${ctx.id}:input`,
43
+ getContentId: (ctx) => ctx.ids?.content ?? `combobox:${ctx.id}:content`,
44
+ getPositionerId: (ctx) => ctx.ids?.positioner ?? `combobox:${ctx.id}:popper`,
45
+ getTriggerId: (ctx) => ctx.ids?.trigger ?? `combobox:${ctx.id}:toggle-btn`,
46
+ getClearTriggerId: (ctx) => ctx.ids?.clearTrigger ?? `combobox:${ctx.id}:clear-btn`,
47
+ getItemGroupId: (ctx, id) => ctx.ids?.itemGroup?.(id) ?? `combobox:${ctx.id}:optgroup:${id}`,
48
+ getItemGroupLabelId: (ctx, id) => ctx.ids?.itemGroupLabel?.(id) ?? `combobox:${ctx.id}:optgroup-label:${id}`,
49
+ getItemId: (ctx, id) => ctx.ids?.item?.(id) ?? `combobox:${ctx.id}:option:${id}`,
50
+ getContentEl: (ctx) => dom.getById(ctx, dom.getContentId(ctx)),
51
+ getInputEl: (ctx) => dom.getById(ctx, dom.getInputId(ctx)),
52
+ getPositionerEl: (ctx) => dom.getById(ctx, dom.getPositionerId(ctx)),
53
+ getControlEl: (ctx) => dom.getById(ctx, dom.getControlId(ctx)),
54
+ getTriggerEl: (ctx) => dom.getById(ctx, dom.getTriggerId(ctx)),
55
+ getClearTriggerEl: (ctx) => dom.getById(ctx, dom.getClearTriggerId(ctx)),
56
+ getHighlightedItemEl: (ctx) => {
57
+ const value = ctx.highlightedValue;
58
+ if (value == null)
59
+ return;
60
+ const selector = `[role=option][data-value="${CSS.escape(value)}"`;
61
+ return domQuery.query(dom.getContentEl(ctx), selector);
62
+ },
63
+ focusInputEl: (ctx) => {
64
+ const inputEl = dom.getInputEl(ctx);
65
+ if (dom.isActiveElement(ctx, inputEl))
66
+ return;
67
+ inputEl?.focus({ preventScroll: true });
68
+ },
69
+ focusTriggerEl: (ctx) => {
70
+ const triggerEl = dom.getTriggerEl(ctx);
71
+ if (dom.isActiveElement(ctx, triggerEl))
72
+ return;
73
+ triggerEl?.focus({ preventScroll: true });
74
+ }
75
+ });
76
+
77
+ function connect(state, send, normalize) {
78
+ const translations = state.context.translations;
79
+ const collection = state.context.collection;
80
+ const disabled = state.context.disabled;
81
+ const interactive = state.context.isInteractive;
82
+ const invalid = state.context.invalid;
83
+ const readOnly = state.context.readOnly;
84
+ const open = state.hasTag("open");
85
+ const focused = state.hasTag("focused");
86
+ const composite = state.context.composite;
87
+ const highlightedValue = state.context.highlightedValue;
88
+ const popperStyles = popper.getPlacementStyles({
89
+ ...state.context.positioning,
90
+ placement: state.context.currentPlacement
91
+ });
92
+ function getItemState(props) {
93
+ const disabled2 = collection.getItemDisabled(props.item);
94
+ const value = collection.getItemValue(props.item);
95
+ return {
96
+ value,
97
+ disabled: Boolean(disabled2 || disabled2),
98
+ highlighted: highlightedValue === value,
99
+ selected: state.context.value.includes(value)
100
+ };
101
+ }
102
+ return {
103
+ focused,
104
+ open,
105
+ inputValue: state.context.inputValue,
106
+ highlightedValue,
107
+ highlightedItem: state.context.highlightedItem,
108
+ value: state.context.value,
109
+ valueAsString: state.context.valueAsString,
110
+ hasSelectedItems: state.context.hasSelectedItems,
111
+ selectedItems: state.context.selectedItems,
112
+ collection: state.context.collection,
113
+ multiple: !!state.context.multiple,
114
+ disabled: !!disabled,
115
+ syncSelectedItems() {
116
+ send({ type: "SELECTED_ITEMS.SYNC" });
117
+ },
118
+ reposition(options = {}) {
119
+ send({ type: "POSITIONING.SET", options });
120
+ },
121
+ setCollection(collection2) {
122
+ send({ type: "COLLECTION.SET", value: collection2 });
123
+ },
124
+ setHighlightValue(value) {
125
+ send({ type: "HIGHLIGHTED_VALUE.SET", value });
126
+ },
127
+ selectValue(value) {
128
+ send({ type: "ITEM.SELECT", value });
129
+ },
130
+ setValue(value) {
131
+ send({ type: "VALUE.SET", value });
132
+ },
133
+ setInputValue(value) {
134
+ send({ type: "INPUT_VALUE.SET", value });
135
+ },
136
+ clearValue(value) {
137
+ if (value != null) {
138
+ send({ type: "ITEM.CLEAR", value });
139
+ } else {
140
+ send("VALUE.CLEAR");
141
+ }
142
+ },
143
+ focus() {
144
+ dom.getInputEl(state.context)?.focus();
145
+ },
146
+ setOpen(nextOpen) {
147
+ if (nextOpen === open)
148
+ return;
149
+ send(nextOpen ? "OPEN" : "CLOSE");
150
+ },
151
+ getRootProps() {
152
+ return normalize.element({
153
+ ...parts.root.attrs,
154
+ "dir": state.context.dir,
155
+ "id": dom.getRootId(state.context),
156
+ "data-invalid": domQuery.dataAttr(invalid),
157
+ "data-readonly": domQuery.dataAttr(readOnly)
158
+ });
159
+ },
160
+ getLabelProps() {
161
+ return normalize.label({
162
+ ...parts.label.attrs,
163
+ "dir": state.context.dir,
164
+ "htmlFor": dom.getInputId(state.context),
165
+ "id": dom.getLabelId(state.context),
166
+ "data-readonly": domQuery.dataAttr(readOnly),
167
+ "data-disabled": domQuery.dataAttr(disabled),
168
+ "data-invalid": domQuery.dataAttr(invalid),
169
+ "data-focus": domQuery.dataAttr(focused),
170
+ onClick(event) {
171
+ if (composite)
172
+ return;
173
+ event.preventDefault();
174
+ dom.getTriggerEl(state.context)?.focus({ preventScroll: true });
175
+ }
176
+ });
177
+ },
178
+ getControlProps() {
179
+ return normalize.element({
180
+ ...parts.control.attrs,
181
+ "dir": state.context.dir,
182
+ "id": dom.getControlId(state.context),
183
+ "data-state": open ? "open" : "closed",
184
+ "data-focus": domQuery.dataAttr(focused),
185
+ "data-disabled": domQuery.dataAttr(disabled),
186
+ "data-invalid": domQuery.dataAttr(invalid)
187
+ });
188
+ },
189
+ getPositionerProps() {
190
+ return normalize.element({
191
+ ...parts.positioner.attrs,
192
+ dir: state.context.dir,
193
+ id: dom.getPositionerId(state.context),
194
+ style: popperStyles.floating
195
+ });
196
+ },
197
+ getInputProps() {
198
+ return normalize.input({
199
+ ...parts.input.attrs,
200
+ "dir": state.context.dir,
201
+ "aria-invalid": domQuery.ariaAttr(invalid),
202
+ "data-invalid": domQuery.dataAttr(invalid),
203
+ "name": state.context.name,
204
+ "form": state.context.form,
205
+ "disabled": disabled,
206
+ "autoFocus": state.context.autoFocus,
207
+ "required": state.context.required,
208
+ "autoComplete": "off",
209
+ "autoCorrect": "off",
210
+ "autoCapitalize": "none",
211
+ "spellCheck": "false",
212
+ "readOnly": readOnly,
213
+ "placeholder": state.context.placeholder,
214
+ "id": dom.getInputId(state.context),
215
+ "type": "text",
216
+ "role": "combobox",
217
+ "defaultValue": state.context.inputValue,
218
+ "aria-autocomplete": state.context.autoComplete ? "both" : "list",
219
+ "aria-controls": dom.getContentId(state.context),
220
+ "aria-expanded": open,
221
+ "data-state": open ? "open" : "closed",
222
+ "aria-activedescendant": highlightedValue ? dom.getItemId(state.context, highlightedValue) : void 0,
223
+ onClick(event) {
224
+ if (event.defaultPrevented)
225
+ return;
226
+ if (!state.context.openOnClick)
227
+ return;
228
+ if (!interactive)
229
+ return;
230
+ send("INPUT.CLICK");
231
+ },
232
+ onFocus() {
233
+ if (disabled)
234
+ return;
235
+ send("INPUT.FOCUS");
236
+ },
237
+ onBlur() {
238
+ if (disabled)
239
+ return;
240
+ send("INPUT.BLUR");
241
+ },
242
+ onChange(event) {
243
+ send({ type: "INPUT.CHANGE", value: event.currentTarget.value });
244
+ },
245
+ onKeyDown(event) {
246
+ if (event.defaultPrevented)
247
+ return;
248
+ if (!interactive)
249
+ return;
250
+ if (event.ctrlKey || event.shiftKey || domQuery.isComposingEvent(event))
251
+ return;
252
+ const openOnKeyPress = state.context.openOnKeyPress;
253
+ const isModifierKey = event.ctrlKey || event.metaKey || event.shiftKey;
254
+ const keypress = true;
255
+ const keymap = {
256
+ ArrowDown(event2) {
257
+ if (!openOnKeyPress && !open)
258
+ return;
259
+ send({ type: event2.altKey ? "OPEN" : "INPUT.ARROW_DOWN", keypress });
260
+ event2.preventDefault();
261
+ },
262
+ ArrowUp() {
263
+ if (!openOnKeyPress && !open)
264
+ return;
265
+ send({ type: event.altKey ? "CLOSE" : "INPUT.ARROW_UP", keypress });
266
+ event.preventDefault();
267
+ },
268
+ Home(event2) {
269
+ if (isModifierKey)
270
+ return;
271
+ send({ type: "INPUT.HOME", keypress });
272
+ if (open) {
273
+ event2.preventDefault();
274
+ }
275
+ },
276
+ End(event2) {
277
+ if (isModifierKey)
278
+ return;
279
+ send({ type: "INPUT.END", keypress });
280
+ if (open) {
281
+ event2.preventDefault();
282
+ }
283
+ },
284
+ Enter(event2) {
285
+ send({ type: "INPUT.ENTER", keypress });
286
+ if (open) {
287
+ event2.preventDefault();
288
+ }
289
+ const itemEl = dom.getHighlightedItemEl(state.context);
290
+ domEvent.clickIfLink(itemEl);
291
+ },
292
+ Escape() {
293
+ send({ type: "INPUT.ESCAPE", keypress });
294
+ event.preventDefault();
295
+ }
296
+ };
297
+ const key = domEvent.getEventKey(event, state.context);
298
+ const exec = keymap[key];
299
+ exec?.(event);
300
+ }
301
+ });
302
+ },
303
+ getTriggerProps(props = {}) {
304
+ return normalize.button({
305
+ ...parts.trigger.attrs,
306
+ "dir": state.context.dir,
307
+ "id": dom.getTriggerId(state.context),
308
+ "aria-haspopup": composite ? "listbox" : "dialog",
309
+ "type": "button",
310
+ "tabIndex": props.focusable ? void 0 : -1,
311
+ "aria-label": translations.triggerLabel,
312
+ "aria-expanded": open,
313
+ "data-state": open ? "open" : "closed",
314
+ "aria-controls": open ? dom.getContentId(state.context) : void 0,
315
+ disabled,
316
+ "data-invalid": domQuery.dataAttr(invalid),
317
+ "data-focusable": domQuery.dataAttr(props.focusable),
318
+ "data-readonly": domQuery.dataAttr(readOnly),
319
+ "data-disabled": domQuery.dataAttr(disabled),
320
+ onFocus() {
321
+ if (!props.focusable)
322
+ return;
323
+ send({ type: "INPUT.FOCUS", src: "trigger" });
324
+ },
325
+ onClick(event) {
326
+ if (event.defaultPrevented)
327
+ return;
328
+ if (!interactive)
329
+ return;
330
+ if (!domEvent.isLeftClick(event))
331
+ return;
332
+ send("TRIGGER.CLICK");
333
+ },
334
+ onPointerDown(event) {
335
+ if (!interactive)
336
+ return;
337
+ if (event.pointerType === "touch")
338
+ return;
339
+ event.preventDefault();
340
+ queueMicrotask(() => {
341
+ dom.getInputEl(state.context)?.focus({ preventScroll: true });
342
+ });
343
+ },
344
+ onKeyDown(event) {
345
+ if (event.defaultPrevented)
346
+ return;
347
+ if (composite)
348
+ return;
349
+ const keyMap = {
350
+ ArrowDown() {
351
+ send({ type: "INPUT.ARROW_DOWN", src: "trigger" });
352
+ },
353
+ ArrowUp() {
354
+ send({ type: "INPUT.ARROW_UP", src: "trigger" });
355
+ }
356
+ };
357
+ const key = domEvent.getEventKey(event, state.context);
358
+ const exec = keyMap[key];
359
+ if (exec) {
360
+ exec(event);
361
+ event.preventDefault();
362
+ }
363
+ }
364
+ });
365
+ },
366
+ getContentProps() {
367
+ return normalize.element({
368
+ ...parts.content.attrs,
369
+ "dir": state.context.dir,
370
+ "id": dom.getContentId(state.context),
371
+ "role": !composite ? "dialog" : "listbox",
372
+ "tabIndex": -1,
373
+ "hidden": !open,
374
+ "data-state": open ? "open" : "closed",
375
+ "data-placement": state.context.currentPlacement,
376
+ "aria-labelledby": dom.getLabelId(state.context),
377
+ "aria-multiselectable": state.context.multiple && composite ? true : void 0,
378
+ onPointerDown(event) {
379
+ event.preventDefault();
380
+ }
381
+ });
382
+ },
383
+ getListProps() {
384
+ return normalize.element({
385
+ ...parts.list.attrs,
386
+ "role": !composite ? "listbox" : void 0,
387
+ "aria-labelledby": dom.getLabelId(state.context),
388
+ "aria-multiselectable": state.context.multiple && !composite ? true : void 0
389
+ });
390
+ },
391
+ getClearTriggerProps() {
392
+ return normalize.button({
393
+ ...parts.clearTrigger.attrs,
394
+ "dir": state.context.dir,
395
+ "id": dom.getClearTriggerId(state.context),
396
+ "type": "button",
397
+ "tabIndex": -1,
398
+ "disabled": disabled,
399
+ "data-invalid": domQuery.dataAttr(invalid),
400
+ "aria-label": translations.clearTriggerLabel,
401
+ "aria-controls": dom.getInputId(state.context),
402
+ "hidden": !state.context.value.length,
403
+ onPointerDown(event) {
404
+ event.preventDefault();
405
+ },
406
+ onClick(event) {
407
+ if (event.defaultPrevented)
408
+ return;
409
+ if (!interactive)
410
+ return;
411
+ send({ type: "VALUE.CLEAR", src: "clear-trigger" });
412
+ }
413
+ });
414
+ },
415
+ getItemState,
416
+ getItemProps(props) {
417
+ const itemState = getItemState(props);
418
+ const value = itemState.value;
419
+ return normalize.element({
420
+ ...parts.item.attrs,
421
+ "dir": state.context.dir,
422
+ "id": dom.getItemId(state.context, value),
423
+ "role": "option",
424
+ "tabIndex": -1,
425
+ "data-highlighted": domQuery.dataAttr(itemState.highlighted),
426
+ "data-state": itemState.selected ? "checked" : "unchecked",
427
+ "aria-selected": domQuery.ariaAttr(itemState.highlighted),
428
+ "aria-disabled": domQuery.ariaAttr(itemState.disabled),
429
+ "data-disabled": domQuery.dataAttr(itemState.disabled),
430
+ "data-value": itemState.value,
431
+ onPointerMove() {
432
+ if (itemState.disabled)
433
+ return;
434
+ if (itemState.highlighted)
435
+ return;
436
+ send({ type: "ITEM.POINTER_MOVE", value });
437
+ },
438
+ onPointerLeave() {
439
+ if (props.persistFocus)
440
+ return;
441
+ if (itemState.disabled)
442
+ return;
443
+ const mouseMoved = state.previousEvent.type.includes("POINTER");
444
+ if (!mouseMoved)
445
+ return;
446
+ send({ type: "ITEM.POINTER_LEAVE", value });
447
+ },
448
+ onClick(event) {
449
+ if (domQuery.isDownloadingEvent(event))
450
+ return;
451
+ if (domQuery.isOpeningInNewTab(event))
452
+ return;
453
+ if (domEvent.isContextMenuEvent(event))
454
+ return;
455
+ if (itemState.disabled)
456
+ return;
457
+ send({ type: "ITEM.CLICK", src: "click", value });
458
+ }
459
+ });
460
+ },
461
+ getItemTextProps(props) {
462
+ const itemState = getItemState(props);
463
+ return normalize.element({
464
+ ...parts.itemText.attrs,
465
+ "dir": state.context.dir,
466
+ "data-state": itemState.selected ? "checked" : "unchecked",
467
+ "data-disabled": domQuery.dataAttr(itemState.disabled),
468
+ "data-highlighted": domQuery.dataAttr(itemState.highlighted)
469
+ });
470
+ },
471
+ getItemIndicatorProps(props) {
472
+ const itemState = getItemState(props);
473
+ return normalize.element({
474
+ "aria-hidden": true,
475
+ ...parts.itemIndicator.attrs,
476
+ "dir": state.context.dir,
477
+ "data-state": itemState.selected ? "checked" : "unchecked",
478
+ "hidden": !itemState.selected
479
+ });
480
+ },
481
+ getItemGroupProps(props) {
482
+ const { id } = props;
483
+ return normalize.element({
484
+ ...parts.itemGroup.attrs,
485
+ "dir": state.context.dir,
486
+ "id": dom.getItemGroupId(state.context, id),
487
+ "aria-labelledby": dom.getItemGroupLabelId(state.context, id)
488
+ });
489
+ },
490
+ getItemGroupLabelProps(props) {
491
+ const { htmlFor } = props;
492
+ return normalize.element({
493
+ ...parts.itemGroupLabel.attrs,
494
+ dir: state.context.dir,
495
+ id: dom.getItemGroupLabelId(state.context, htmlFor),
496
+ role: "group"
497
+ });
498
+ }
499
+ };
500
+ }
501
+
502
+ const { and, not } = core.guards;
503
+ function getInputValue(ctx) {
504
+ return utils.match(ctx.selectionBehavior, {
505
+ preserve: ctx.inputValue,
506
+ replace: ctx.valueAsString,
507
+ clear: ""
508
+ });
509
+ }
510
+ const sync = {
511
+ valueChange: (ctx) => {
512
+ const prevSelectedItems = ctx.selectedItems;
513
+ ctx.selectedItems = ctx.value.map((v) => {
514
+ const foundItem = prevSelectedItems.find((item) => ctx.collection.getItemValue(item) === v);
515
+ if (foundItem)
516
+ return foundItem;
517
+ return ctx.collection.find(v);
518
+ });
519
+ ctx.valueAsString = ctx.collection.stringifyItems(ctx.selectedItems);
520
+ },
521
+ highlightChange: (ctx) => {
522
+ ctx.highlightedItem = ctx.collection.find(ctx.highlightedValue);
523
+ }
524
+ };
525
+ const invoke = {
526
+ valueChange: (ctx) => {
527
+ sync.valueChange(ctx);
528
+ ctx.onValueChange?.({
529
+ value: Array.from(ctx.value),
530
+ items: Array.from(ctx.selectedItems)
531
+ });
532
+ },
533
+ highlightChange: (ctx) => {
534
+ sync.highlightChange(ctx);
535
+ ctx.onHighlightChange?.({
536
+ highlightedValue: ctx.highlightedValue,
537
+ highlightedItem: ctx.highlightedItem
538
+ });
539
+ },
540
+ inputChange: (ctx) => {
541
+ ctx.onInputValueChange?.({ inputValue: ctx.inputValue });
542
+ }
543
+ };
544
+ const set = {
545
+ value: (ctx, value, force = false) => {
546
+ if (utils.isEqual(ctx.value, value))
547
+ return;
548
+ if (value == null && !force)
549
+ return;
550
+ if (value == null && force) {
551
+ ctx.value = [];
552
+ invoke.valueChange(ctx);
553
+ return;
554
+ }
555
+ if (utils.isArray(value)) {
556
+ ctx.value = value;
557
+ } else if (value != null) {
558
+ ctx.value = ctx.multiple ? utils.addOrRemove(ctx.value, value) : [value];
559
+ }
560
+ invoke.valueChange(ctx);
561
+ },
562
+ highlightedValue: (ctx, value, force = false) => {
563
+ if (utils.isEqual(ctx.highlightedValue, value))
564
+ return;
565
+ if (!value && !force)
566
+ return;
567
+ ctx.highlightedValue = value || null;
568
+ invoke.highlightChange(ctx);
569
+ },
570
+ inputValue: (ctx, value) => {
571
+ if (utils.isEqual(ctx.inputValue, value))
572
+ return;
573
+ ctx.inputValue = value;
574
+ invoke.inputChange(ctx);
575
+ }
576
+ };
577
+ function machine(userContext) {
578
+ const ctx = utils.compact(userContext);
579
+ return core.createMachine(
580
+ {
581
+ id: "combobox",
582
+ initial: ctx.open ? "suggesting" : "idle",
583
+ context: {
584
+ loopFocus: true,
585
+ openOnClick: false,
586
+ value: [],
587
+ highlightedValue: null,
588
+ inputValue: "",
589
+ allowCustomValue: false,
590
+ closeOnSelect: !ctx.multiple,
591
+ inputBehavior: "none",
592
+ selectionBehavior: "replace",
593
+ openOnKeyPress: true,
594
+ openOnChange: true,
595
+ composite: true,
596
+ readOnly: false,
597
+ disabled: false,
598
+ ...ctx,
599
+ highlightedItem: null,
600
+ selectedItems: [],
601
+ valueAsString: "",
602
+ collection: ctx.collection ?? collection.empty(),
603
+ positioning: {
604
+ placement: "bottom",
605
+ sameWidth: true,
606
+ ...ctx.positioning
607
+ },
608
+ translations: {
609
+ triggerLabel: "Toggle suggestions",
610
+ clearTriggerLabel: "Clear value",
611
+ ...ctx.translations
612
+ }
613
+ },
614
+ created: ["syncInitialValues", "syncSelectionBehavior"],
615
+ computed: {
616
+ isInputValueEmpty: (ctx2) => ctx2.inputValue.length === 0,
617
+ isInteractive: (ctx2) => !(ctx2.readOnly || ctx2.disabled),
618
+ autoComplete: (ctx2) => ctx2.inputBehavior === "autocomplete",
619
+ autoHighlight: (ctx2) => ctx2.inputBehavior === "autohighlight",
620
+ hasSelectedItems: (ctx2) => ctx2.value.length > 0
621
+ },
622
+ watch: {
623
+ value: ["syncSelectedItems"],
624
+ inputValue: ["syncInputValue"],
625
+ highlightedValue: ["syncHighlightedItem", "autofillInputValue"],
626
+ multiple: ["syncSelectionBehavior"],
627
+ open: ["toggleVisibility"]
628
+ },
629
+ on: {
630
+ "SELECTED_ITEMS.SYNC": {
631
+ actions: ["syncSelectedItems"]
632
+ },
633
+ "HIGHLIGHTED_VALUE.SET": {
634
+ actions: ["setHighlightedItem"]
635
+ },
636
+ "ITEM.SELECT": {
637
+ actions: ["selectItem"]
638
+ },
639
+ "ITEM.CLEAR": {
640
+ actions: ["clearItem"]
641
+ },
642
+ "VALUE.SET": {
643
+ actions: ["setSelectedItems"]
644
+ },
645
+ "INPUT_VALUE.SET": {
646
+ actions: "setInputValue"
647
+ },
648
+ "COLLECTION.SET": {
649
+ actions: ["setCollection"]
650
+ },
651
+ "POSITIONING.SET": {
652
+ actions: ["reposition"]
653
+ }
654
+ },
655
+ states: {
656
+ idle: {
657
+ tags: ["idle", "closed"],
658
+ entry: ["scrollContentToTop", "clearHighlightedItem"],
659
+ on: {
660
+ "CONTROLLED.OPEN": {
661
+ target: "interacting"
662
+ },
663
+ "TRIGGER.CLICK": [
664
+ {
665
+ guard: "isOpenControlled",
666
+ actions: ["setInitialFocus", "highlightFirstSelectedItem", "invokeOnOpen"]
667
+ },
668
+ {
669
+ target: "interacting",
670
+ actions: ["setInitialFocus", "highlightFirstSelectedItem", "invokeOnOpen"]
671
+ }
672
+ ],
673
+ "INPUT.CLICK": [
674
+ {
675
+ guard: "isOpenControlled",
676
+ actions: ["highlightFirstSelectedItem", "invokeOnOpen"]
677
+ },
678
+ {
679
+ target: "interacting",
680
+ actions: ["highlightFirstSelectedItem", "invokeOnOpen"]
681
+ }
682
+ ],
683
+ "INPUT.FOCUS": {
684
+ target: "focused"
685
+ },
686
+ "OPEN": [
687
+ {
688
+ guard: "isOpenControlled",
689
+ actions: ["invokeOnOpen"]
690
+ },
691
+ {
692
+ target: "interacting",
693
+ actions: ["invokeOnOpen"]
694
+ }
695
+ ],
696
+ "VALUE.CLEAR": {
697
+ target: "focused",
698
+ actions: ["clearInputValue", "clearSelectedItems", "setInitialFocus"]
699
+ }
700
+ }
701
+ },
702
+ focused: {
703
+ tags: ["focused", "closed"],
704
+ entry: ["scrollContentToTop", "clearHighlightedItem"],
705
+ on: {
706
+ "CONTROLLED.OPEN": [
707
+ {
708
+ guard: "isChangeEvent",
709
+ target: "suggesting"
710
+ },
711
+ {
712
+ target: "interacting"
713
+ }
714
+ ],
715
+ "INPUT.CHANGE": [
716
+ {
717
+ guard: and("isOpenControlled", "openOnChange"),
718
+ actions: ["setInputValue", "invokeOnOpen", "highlightFirstItemIfNeeded"]
719
+ },
720
+ {
721
+ guard: "openOnChange",
722
+ target: "suggesting",
723
+ actions: ["setInputValue", "invokeOnOpen", "highlightFirstItemIfNeeded"]
724
+ },
725
+ {
726
+ actions: "setInputValue"
727
+ }
728
+ ],
729
+ "LAYER.INTERACT_OUTSIDE": {
730
+ target: "idle"
731
+ },
732
+ "INPUT.ESCAPE": {
733
+ guard: and("isCustomValue", not("allowCustomValue")),
734
+ actions: "revertInputValue"
735
+ },
736
+ "INPUT.BLUR": {
737
+ target: "idle"
738
+ },
739
+ "INPUT.CLICK": [
740
+ {
741
+ guard: "isOpenControlled",
742
+ actions: ["highlightFirstSelectedItem", "invokeOnOpen"]
743
+ },
744
+ {
745
+ target: "interacting",
746
+ actions: ["highlightFirstSelectedItem", "invokeOnOpen"]
747
+ }
748
+ ],
749
+ "TRIGGER.CLICK": [
750
+ {
751
+ guard: "isOpenControlled",
752
+ actions: ["setInitialFocus", "highlightFirstSelectedItem", "invokeOnOpen"]
753
+ },
754
+ {
755
+ target: "interacting",
756
+ actions: ["setInitialFocus", "highlightFirstSelectedItem", "invokeOnOpen"]
757
+ }
758
+ ],
759
+ "INPUT.ARROW_DOWN": [
760
+ // == group 1 ==
761
+ {
762
+ guard: and("isOpenControlled", "autoComplete"),
763
+ actions: ["invokeOnOpen"]
764
+ },
765
+ {
766
+ guard: "autoComplete",
767
+ target: "interacting",
768
+ actions: ["invokeOnOpen"]
769
+ },
770
+ // == group 2 ==
771
+ {
772
+ guard: "isOpenControlled",
773
+ actions: ["highlightFirstOrSelectedItem", "invokeOnOpen"]
774
+ },
775
+ {
776
+ target: "interacting",
777
+ actions: ["highlightFirstOrSelectedItem", "invokeOnOpen"]
778
+ }
779
+ ],
780
+ "INPUT.ARROW_UP": [
781
+ // == group 1 ==
782
+ {
783
+ guard: "autoComplete",
784
+ target: "interacting",
785
+ actions: "invokeOnOpen"
786
+ },
787
+ {
788
+ guard: "autoComplete",
789
+ target: "interacting",
790
+ actions: "invokeOnOpen"
791
+ },
792
+ // == group 2 ==
793
+ {
794
+ target: "interacting",
795
+ actions: ["highlightLastOrSelectedItem", "invokeOnOpen"]
796
+ },
797
+ {
798
+ target: "interacting",
799
+ actions: ["highlightLastOrSelectedItem", "invokeOnOpen"]
800
+ }
801
+ ],
802
+ "OPEN": [
803
+ {
804
+ guard: "isOpenControlled",
805
+ actions: ["invokeOnOpen"]
806
+ },
807
+ {
808
+ target: "interacting",
809
+ actions: ["invokeOnOpen"]
810
+ }
811
+ ],
812
+ "VALUE.CLEAR": {
813
+ actions: ["clearInputValue", "clearSelectedItems"]
814
+ }
815
+ }
816
+ },
817
+ interacting: {
818
+ tags: ["open", "focused"],
819
+ entry: ["setInitialFocus"],
820
+ activities: ["scrollToHighlightedItem", "trackDismissableLayer", "computePlacement", "hideOtherElements"],
821
+ on: {
822
+ "CONTROLLED.CLOSE": [
823
+ {
824
+ guard: "restoreFocus",
825
+ target: "focused",
826
+ actions: ["setFinalFocus"]
827
+ },
828
+ {
829
+ target: "idle"
830
+ }
831
+ ],
832
+ "INPUT.HOME": {
833
+ actions: ["highlightFirstItem"]
834
+ },
835
+ "INPUT.END": {
836
+ actions: ["highlightLastItem"]
837
+ },
838
+ "INPUT.ARROW_DOWN": [
839
+ {
840
+ guard: and("autoComplete", "isLastItemHighlighted"),
841
+ actions: ["clearHighlightedItem", "scrollContentToTop"]
842
+ },
843
+ {
844
+ actions: ["highlightNextItem"]
845
+ }
846
+ ],
847
+ "INPUT.ARROW_UP": [
848
+ {
849
+ guard: and("autoComplete", "isFirstItemHighlighted"),
850
+ actions: "clearHighlightedItem"
851
+ },
852
+ {
853
+ actions: "highlightPrevItem"
854
+ }
855
+ ],
856
+ "INPUT.ENTER": [
857
+ // == group 1 ==
858
+ {
859
+ guard: and("isOpenControlled", "isCustomValue", not("hasHighlightedItem"), not("allowCustomValue")),
860
+ actions: ["revertInputValue", "invokeOnClose"]
861
+ },
862
+ {
863
+ guard: and("isCustomValue", not("hasHighlightedItem"), not("allowCustomValue")),
864
+ target: "focused",
865
+ actions: ["revertInputValue", "invokeOnClose"]
866
+ },
867
+ // == group 2 ==
868
+ {
869
+ guard: and("isOpenControlled", "closeOnSelect"),
870
+ actions: ["selectHighlightedItem", "invokeOnClose"]
871
+ },
872
+ {
873
+ guard: "closeOnSelect",
874
+ target: "focused",
875
+ actions: ["selectHighlightedItem", "invokeOnClose", "setFinalFocus"]
876
+ },
877
+ {
878
+ actions: ["selectHighlightedItem"]
879
+ }
880
+ ],
881
+ "INPUT.CHANGE": [
882
+ {
883
+ guard: "autoComplete",
884
+ target: "suggesting",
885
+ actions: ["setInputValue", "invokeOnOpen"]
886
+ },
887
+ {
888
+ target: "suggesting",
889
+ actions: ["clearHighlightedItem", "setInputValue", "invokeOnOpen"]
890
+ }
891
+ ],
892
+ "ITEM.POINTER_MOVE": {
893
+ actions: ["setHighlightedItem"]
894
+ },
895
+ "ITEM.POINTER_LEAVE": {
896
+ actions: ["clearHighlightedItem"]
897
+ },
898
+ "ITEM.CLICK": [
899
+ {
900
+ guard: and("isOpenControlled", "closeOnSelect"),
901
+ actions: ["selectItem", "invokeOnClose"]
902
+ },
903
+ {
904
+ guard: "closeOnSelect",
905
+ target: "focused",
906
+ actions: ["selectItem", "invokeOnClose", "setFinalFocus"]
907
+ },
908
+ {
909
+ actions: ["selectItem"]
910
+ }
911
+ ],
912
+ "LAYER.ESCAPE": [
913
+ {
914
+ guard: and("isOpenControlled", "autoComplete"),
915
+ actions: ["syncInputValue", "invokeOnClose"]
916
+ },
917
+ {
918
+ guard: "autoComplete",
919
+ target: "focused",
920
+ actions: ["syncInputValue", "invokeOnClose"]
921
+ },
922
+ {
923
+ guard: "isOpenControlled",
924
+ actions: "invokeOnClose"
925
+ },
926
+ {
927
+ target: "focused",
928
+ actions: ["invokeOnClose", "setFinalFocus"]
929
+ }
930
+ ],
931
+ "TRIGGER.CLICK": [
932
+ {
933
+ guard: "isOpenControlled",
934
+ actions: "invokeOnClose"
935
+ },
936
+ {
937
+ target: "focused",
938
+ actions: "invokeOnClose"
939
+ }
940
+ ],
941
+ "LAYER.INTERACT_OUTSIDE": [
942
+ // == group 1 ==
943
+ {
944
+ guard: and("isOpenControlled", "isCustomValue", not("allowCustomValue")),
945
+ actions: ["revertInputValue", "invokeOnClose"]
946
+ },
947
+ {
948
+ guard: and("isCustomValue", not("allowCustomValue")),
949
+ target: "idle",
950
+ actions: ["revertInputValue", "invokeOnClose"]
951
+ },
952
+ // == group 2 ==
953
+ {
954
+ guard: "isOpenControlled",
955
+ actions: "invokeOnClose"
956
+ },
957
+ {
958
+ target: "idle",
959
+ actions: "invokeOnClose"
960
+ }
961
+ ],
962
+ "CLOSE": [
963
+ {
964
+ guard: "isOpenControlled",
965
+ actions: ["invokeOnClose"]
966
+ },
967
+ {
968
+ target: "focused",
969
+ actions: ["invokeOnClose", "setFinalFocus"]
970
+ }
971
+ ],
972
+ "VALUE.CLEAR": [
973
+ {
974
+ guard: "isOpenControlled",
975
+ actions: ["clearInputValue", "clearSelectedItems", "invokeOnClose"]
976
+ },
977
+ {
978
+ target: "focused",
979
+ actions: ["clearInputValue", "clearSelectedItems", "invokeOnClose", "setFinalFocus"]
980
+ }
981
+ ]
982
+ }
983
+ },
984
+ suggesting: {
985
+ tags: ["open", "focused"],
986
+ activities: [
987
+ "trackDismissableLayer",
988
+ "scrollToHighlightedItem",
989
+ "computePlacement",
990
+ "trackChildNodes",
991
+ "hideOtherElements"
992
+ ],
993
+ entry: ["setInitialFocus"],
994
+ on: {
995
+ "CONTROLLED.CLOSE": [
996
+ {
997
+ guard: "restoreFocus",
998
+ target: "focused",
999
+ actions: ["setFinalFocus"]
1000
+ },
1001
+ {
1002
+ target: "idle"
1003
+ }
1004
+ ],
1005
+ "CHILDREN_CHANGE": {
1006
+ actions: ["highlightFirstItem"]
1007
+ },
1008
+ "INPUT.ARROW_DOWN": {
1009
+ target: "interacting",
1010
+ actions: ["highlightNextItem"]
1011
+ },
1012
+ "INPUT.ARROW_UP": {
1013
+ target: "interacting",
1014
+ actions: ["highlightPrevItem"]
1015
+ },
1016
+ "INPUT.HOME": {
1017
+ target: "interacting",
1018
+ actions: ["highlightFirstItem"]
1019
+ },
1020
+ "INPUT.END": {
1021
+ target: "interacting",
1022
+ actions: ["highlightLastItem"]
1023
+ },
1024
+ "INPUT.ENTER": [
1025
+ // == group 1 ==
1026
+ {
1027
+ guard: and("isOpenControlled", "isCustomValue", not("hasHighlightedItem"), not("allowCustomValue")),
1028
+ actions: ["revertInputValue", "invokeOnClose"]
1029
+ },
1030
+ {
1031
+ guard: and("isCustomValue", not("hasHighlightedItem"), not("allowCustomValue")),
1032
+ target: "focused",
1033
+ actions: ["revertInputValue", "invokeOnClose"]
1034
+ },
1035
+ // == group 2 ==
1036
+ {
1037
+ guard: and("isOpenControlled", "closeOnSelect"),
1038
+ actions: ["selectHighlightedItem", "invokeOnClose"]
1039
+ },
1040
+ {
1041
+ guard: "closeOnSelect",
1042
+ target: "focused",
1043
+ actions: ["selectHighlightedItem", "invokeOnClose", "setFinalFocus"]
1044
+ },
1045
+ {
1046
+ actions: ["selectHighlightedItem"]
1047
+ }
1048
+ ],
1049
+ "INPUT.CHANGE": [
1050
+ {
1051
+ guard: "autoHighlight",
1052
+ actions: ["setInputValue"]
1053
+ },
1054
+ {
1055
+ actions: ["setInputValue"]
1056
+ }
1057
+ ],
1058
+ "LAYER.ESCAPE": [
1059
+ {
1060
+ guard: "isOpenControlled",
1061
+ actions: ["invokeOnClose"]
1062
+ },
1063
+ {
1064
+ target: "focused",
1065
+ actions: ["invokeOnClose"]
1066
+ }
1067
+ ],
1068
+ "ITEM.POINTER_MOVE": {
1069
+ target: "interacting",
1070
+ actions: ["setHighlightedItem"]
1071
+ },
1072
+ "ITEM.POINTER_LEAVE": {
1073
+ actions: ["clearHighlightedItem"]
1074
+ },
1075
+ "LAYER.INTERACT_OUTSIDE": [
1076
+ // == group 1 ==
1077
+ {
1078
+ guard: and("isOpenControlled", "isCustomValue", not("allowCustomValue")),
1079
+ actions: ["revertInputValue", "invokeOnClose"]
1080
+ },
1081
+ {
1082
+ guard: and("isCustomValue", not("allowCustomValue")),
1083
+ target: "idle",
1084
+ actions: ["revertInputValue", "invokeOnClose"]
1085
+ },
1086
+ // == group 2 ==
1087
+ {
1088
+ guard: "isOpenControlled",
1089
+ actions: ["invokeOnClose"]
1090
+ },
1091
+ {
1092
+ target: "idle",
1093
+ actions: ["invokeOnClose"]
1094
+ }
1095
+ ],
1096
+ "TRIGGER.CLICK": [
1097
+ {
1098
+ guard: "isOpenControlled",
1099
+ actions: ["invokeOnClose"]
1100
+ },
1101
+ {
1102
+ target: "focused",
1103
+ actions: ["invokeOnClose"]
1104
+ }
1105
+ ],
1106
+ "ITEM.CLICK": [
1107
+ {
1108
+ guard: and("isOpenControlled", "closeOnSelect"),
1109
+ actions: ["selectItem", "invokeOnClose"]
1110
+ },
1111
+ {
1112
+ guard: "closeOnSelect",
1113
+ target: "focused",
1114
+ actions: ["selectItem", "invokeOnClose", "setFinalFocus"]
1115
+ },
1116
+ {
1117
+ actions: ["selectItem"]
1118
+ }
1119
+ ],
1120
+ "CLOSE": [
1121
+ {
1122
+ guard: "isOpenControlled",
1123
+ actions: ["invokeOnClose"]
1124
+ },
1125
+ {
1126
+ target: "focused",
1127
+ actions: ["invokeOnClose", "setFinalFocus"]
1128
+ }
1129
+ ],
1130
+ "VALUE.CLEAR": [
1131
+ {
1132
+ guard: "isOpenControlled",
1133
+ actions: ["clearInputValue", "clearSelectedItems", "invokeOnClose"]
1134
+ },
1135
+ {
1136
+ target: "focused",
1137
+ actions: ["clearInputValue", "clearSelectedItems", "invokeOnClose", "setFinalFocus"]
1138
+ }
1139
+ ]
1140
+ }
1141
+ }
1142
+ }
1143
+ },
1144
+ {
1145
+ guards: {
1146
+ isInputValueEmpty: (ctx2) => ctx2.isInputValueEmpty,
1147
+ autoComplete: (ctx2) => ctx2.autoComplete && !ctx2.multiple,
1148
+ autoHighlight: (ctx2) => ctx2.autoHighlight,
1149
+ isFirstItemHighlighted: (ctx2) => ctx2.collection.firstValue === ctx2.highlightedValue,
1150
+ isLastItemHighlighted: (ctx2) => ctx2.collection.lastValue === ctx2.highlightedValue,
1151
+ isCustomValue: (ctx2) => ctx2.inputValue !== ctx2.valueAsString,
1152
+ allowCustomValue: (ctx2) => !!ctx2.allowCustomValue,
1153
+ hasHighlightedItem: (ctx2) => ctx2.highlightedValue != null,
1154
+ closeOnSelect: (ctx2) => !!ctx2.closeOnSelect,
1155
+ isOpenControlled: (ctx2) => !!ctx2["open.controlled"],
1156
+ openOnChange: (ctx2, evt) => {
1157
+ if (utils.isBoolean(ctx2.openOnChange))
1158
+ return ctx2.openOnChange;
1159
+ return !!ctx2.openOnChange?.({ inputValue: evt.value });
1160
+ },
1161
+ restoreFocus: (_ctx, evt) => evt.restoreFocus == null ? true : !!evt.restoreFocus,
1162
+ isChangeEvent: (_ctx, evt) => evt.previousEvent?.type === "INPUT.CHANGE"
1163
+ },
1164
+ activities: {
1165
+ trackDismissableLayer(ctx2, _evt, { send }) {
1166
+ if (ctx2.disableLayer)
1167
+ return;
1168
+ const contentEl = () => dom.getContentEl(ctx2);
1169
+ return dismissable.trackDismissableElement(contentEl, {
1170
+ defer: true,
1171
+ exclude: () => [dom.getInputEl(ctx2), dom.getTriggerEl(ctx2), dom.getClearTriggerEl(ctx2)],
1172
+ onFocusOutside: ctx2.onFocusOutside,
1173
+ onPointerDownOutside: ctx2.onPointerDownOutside,
1174
+ onInteractOutside: ctx2.onInteractOutside,
1175
+ onEscapeKeyDown(event) {
1176
+ event.preventDefault();
1177
+ event.stopPropagation();
1178
+ send("LAYER.ESCAPE");
1179
+ },
1180
+ onDismiss() {
1181
+ send({ type: "LAYER.INTERACT_OUTSIDE", restoreFocus: false });
1182
+ }
1183
+ });
1184
+ },
1185
+ hideOtherElements(ctx2) {
1186
+ return ariaHidden.ariaHidden([
1187
+ dom.getInputEl(ctx2),
1188
+ dom.getContentEl(ctx2),
1189
+ dom.getTriggerEl(ctx2),
1190
+ dom.getClearTriggerEl(ctx2)
1191
+ ]);
1192
+ },
1193
+ computePlacement(ctx2) {
1194
+ const controlEl = () => dom.getControlEl(ctx2);
1195
+ const positionerEl = () => dom.getPositionerEl(ctx2);
1196
+ ctx2.currentPlacement = ctx2.positioning.placement;
1197
+ return popper.getPlacement(controlEl, positionerEl, {
1198
+ ...ctx2.positioning,
1199
+ defer: true,
1200
+ onComplete(data) {
1201
+ ctx2.currentPlacement = data.placement;
1202
+ }
1203
+ });
1204
+ },
1205
+ // in event the options are fetched (async), we still want to auto-highlight the first option
1206
+ trackChildNodes(ctx2, _evt, { send }) {
1207
+ if (!ctx2.autoHighlight)
1208
+ return;
1209
+ const exec = () => send("CHILDREN_CHANGE");
1210
+ const contentEl = () => dom.getContentEl(ctx2);
1211
+ return domQuery.observeChildren(contentEl, {
1212
+ callback: exec,
1213
+ defer: true
1214
+ });
1215
+ },
1216
+ scrollToHighlightedItem(ctx2, _evt, { getState }) {
1217
+ const inputEl = dom.getInputEl(ctx2);
1218
+ const cleanups = [];
1219
+ const exec = (immediate) => {
1220
+ const state = getState();
1221
+ const pointer = state.event.type.includes("POINTER");
1222
+ if (pointer || !ctx2.highlightedValue)
1223
+ return;
1224
+ const itemEl = dom.getHighlightedItemEl(ctx2);
1225
+ const contentEl = dom.getContentEl(ctx2);
1226
+ if (ctx2.scrollToIndexFn) {
1227
+ const highlightedIndex = ctx2.collection.indexOf(ctx2.highlightedValue);
1228
+ ctx2.scrollToIndexFn({ index: highlightedIndex, immediate });
1229
+ return;
1230
+ }
1231
+ const rafCleanup2 = domQuery.raf(() => {
1232
+ domQuery.scrollIntoView(itemEl, { rootEl: contentEl, block: "nearest" });
1233
+ });
1234
+ cleanups.push(rafCleanup2);
1235
+ };
1236
+ const rafCleanup = domQuery.raf(() => exec(true));
1237
+ cleanups.push(rafCleanup);
1238
+ const observerCleanup = domQuery.observeAttributes(inputEl, {
1239
+ attributes: ["aria-activedescendant"],
1240
+ callback: () => exec(false)
1241
+ });
1242
+ cleanups.push(observerCleanup);
1243
+ return () => {
1244
+ cleanups.forEach((cleanup) => cleanup());
1245
+ };
1246
+ }
1247
+ },
1248
+ actions: {
1249
+ reposition(ctx2, evt) {
1250
+ const controlEl = () => dom.getControlEl(ctx2);
1251
+ const positionerEl = () => dom.getPositionerEl(ctx2);
1252
+ popper.getPlacement(controlEl, positionerEl, {
1253
+ ...ctx2.positioning,
1254
+ ...evt.options,
1255
+ defer: true,
1256
+ listeners: false,
1257
+ onComplete(data) {
1258
+ ctx2.currentPlacement = data.placement;
1259
+ }
1260
+ });
1261
+ },
1262
+ setHighlightedItem(ctx2, evt) {
1263
+ if (evt.value == null)
1264
+ return;
1265
+ set.highlightedValue(ctx2, evt.value);
1266
+ },
1267
+ clearHighlightedItem(ctx2) {
1268
+ set.highlightedValue(ctx2, null, true);
1269
+ },
1270
+ selectHighlightedItem(ctx2) {
1271
+ set.value(ctx2, ctx2.highlightedValue);
1272
+ set.inputValue(ctx2, getInputValue(ctx2));
1273
+ },
1274
+ selectItem(ctx2, evt) {
1275
+ if (evt.value == null)
1276
+ return;
1277
+ set.value(ctx2, evt.value);
1278
+ set.inputValue(ctx2, getInputValue(ctx2));
1279
+ },
1280
+ clearItem(ctx2, evt) {
1281
+ if (evt.value == null)
1282
+ return;
1283
+ const value = ctx2.value.filter((v) => v !== evt.value);
1284
+ set.value(ctx2, value);
1285
+ set.inputValue(ctx2, getInputValue(ctx2));
1286
+ },
1287
+ setInitialFocus(ctx2) {
1288
+ domQuery.raf(() => {
1289
+ dom.focusInputEl(ctx2);
1290
+ });
1291
+ },
1292
+ setFinalFocus(ctx2) {
1293
+ domQuery.raf(() => {
1294
+ const triggerEl = dom.getTriggerEl(ctx2);
1295
+ if (triggerEl?.dataset.focusable == null) {
1296
+ dom.focusInputEl(ctx2);
1297
+ } else {
1298
+ dom.focusTriggerEl(ctx2);
1299
+ }
1300
+ });
1301
+ },
1302
+ syncInputValue(ctx2) {
1303
+ const inputEl = dom.getInputEl(ctx2);
1304
+ if (!inputEl)
1305
+ return;
1306
+ inputEl.value = ctx2.inputValue;
1307
+ queueMicrotask(() => {
1308
+ const { selectionStart, selectionEnd } = inputEl;
1309
+ if (Math.abs((selectionEnd ?? 0) - (selectionStart ?? 0)) !== 0)
1310
+ return;
1311
+ if (selectionStart !== 0)
1312
+ return;
1313
+ inputEl.setSelectionRange(inputEl.value.length, inputEl.value.length);
1314
+ });
1315
+ },
1316
+ setInputValue(ctx2, evt) {
1317
+ set.inputValue(ctx2, evt.value);
1318
+ },
1319
+ clearInputValue(ctx2) {
1320
+ set.inputValue(ctx2, "");
1321
+ },
1322
+ revertInputValue(ctx2) {
1323
+ const inputValue = utils.match(ctx2.selectionBehavior, {
1324
+ replace: ctx2.hasSelectedItems ? ctx2.valueAsString : "",
1325
+ preserve: ctx2.inputValue,
1326
+ clear: ""
1327
+ });
1328
+ set.inputValue(ctx2, inputValue);
1329
+ },
1330
+ syncInitialValues(ctx2) {
1331
+ const selectedItems = ctx2.collection.findMany(ctx2.value);
1332
+ const valueAsString = ctx2.collection.stringifyMany(ctx2.value);
1333
+ ctx2.highlightedItem = ctx2.collection.find(ctx2.highlightedValue);
1334
+ ctx2.selectedItems = selectedItems;
1335
+ ctx2.valueAsString = valueAsString;
1336
+ if (ctx2.inputValue.trim() || ctx2.multiple)
1337
+ return;
1338
+ ctx2.inputValue = utils.match(ctx2.selectionBehavior, {
1339
+ preserve: ctx2.inputValue || valueAsString,
1340
+ replace: valueAsString,
1341
+ clear: ""
1342
+ });
1343
+ },
1344
+ syncSelectionBehavior(ctx2) {
1345
+ if (ctx2.multiple) {
1346
+ ctx2.selectionBehavior = "clear";
1347
+ }
1348
+ },
1349
+ setSelectedItems(ctx2, evt) {
1350
+ if (!utils.isArray(evt.value))
1351
+ return;
1352
+ set.value(ctx2, evt.value);
1353
+ set.inputValue(ctx2, getInputValue(ctx2));
1354
+ },
1355
+ clearSelectedItems(ctx2) {
1356
+ set.value(ctx2, []);
1357
+ set.inputValue(ctx2, getInputValue(ctx2));
1358
+ },
1359
+ scrollContentToTop(ctx2) {
1360
+ if (ctx2.scrollToIndexFn) {
1361
+ ctx2.scrollToIndexFn({ index: 0, immediate: true });
1362
+ } else {
1363
+ const contentEl = dom.getContentEl(ctx2);
1364
+ if (!contentEl)
1365
+ return;
1366
+ contentEl.scrollTop = 0;
1367
+ }
1368
+ },
1369
+ invokeOnOpen(ctx2) {
1370
+ ctx2.onOpenChange?.({ open: true });
1371
+ },
1372
+ invokeOnClose(ctx2) {
1373
+ ctx2.onOpenChange?.({ open: false });
1374
+ },
1375
+ highlightFirstItem(ctx2) {
1376
+ domQuery.raf(() => {
1377
+ const value = ctx2.collection.firstValue;
1378
+ set.highlightedValue(ctx2, value, true);
1379
+ });
1380
+ },
1381
+ highlightFirstItemIfNeeded(ctx2) {
1382
+ if (!ctx2.autoHighlight)
1383
+ return;
1384
+ domQuery.raf(() => {
1385
+ const value = ctx2.collection.firstValue;
1386
+ set.highlightedValue(ctx2, value);
1387
+ });
1388
+ },
1389
+ highlightLastItem(ctx2) {
1390
+ domQuery.raf(() => {
1391
+ const value = ctx2.collection.lastValue;
1392
+ set.highlightedValue(ctx2, value);
1393
+ });
1394
+ },
1395
+ highlightNextItem(ctx2) {
1396
+ let value = null;
1397
+ if (ctx2.highlightedValue) {
1398
+ value = ctx2.collection.getNextValue(ctx2.highlightedValue);
1399
+ if (!value && ctx2.loopFocus)
1400
+ value = ctx2.collection.firstValue;
1401
+ } else {
1402
+ value = ctx2.collection.firstValue;
1403
+ }
1404
+ set.highlightedValue(ctx2, value);
1405
+ },
1406
+ highlightPrevItem(ctx2) {
1407
+ let value = null;
1408
+ if (ctx2.highlightedValue) {
1409
+ value = ctx2.collection.getPreviousValue(ctx2.highlightedValue);
1410
+ if (!value && ctx2.loopFocus)
1411
+ value = ctx2.collection.lastValue;
1412
+ } else {
1413
+ value = ctx2.collection.lastValue;
1414
+ }
1415
+ set.highlightedValue(ctx2, value);
1416
+ },
1417
+ highlightFirstSelectedItem(ctx2) {
1418
+ domQuery.raf(() => {
1419
+ const [value] = ctx2.collection.sort(ctx2.value);
1420
+ set.highlightedValue(ctx2, value);
1421
+ });
1422
+ },
1423
+ highlightFirstOrSelectedItem(ctx2) {
1424
+ domQuery.raf(() => {
1425
+ let value = null;
1426
+ if (ctx2.hasSelectedItems) {
1427
+ value = ctx2.collection.sort(ctx2.value)[0];
1428
+ } else {
1429
+ value = ctx2.collection.firstValue;
1430
+ }
1431
+ set.highlightedValue(ctx2, value);
1432
+ });
1433
+ },
1434
+ highlightLastOrSelectedItem(ctx2) {
1435
+ domQuery.raf(() => {
1436
+ let value = null;
1437
+ if (ctx2.hasSelectedItems) {
1438
+ value = ctx2.collection.sort(ctx2.value)[0];
1439
+ } else {
1440
+ value = ctx2.collection.lastValue;
1441
+ }
1442
+ set.highlightedValue(ctx2, value);
1443
+ });
1444
+ },
1445
+ autofillInputValue(ctx2, evt) {
1446
+ const inputEl = dom.getInputEl(ctx2);
1447
+ if (!ctx2.autoComplete || !inputEl || !evt.keypress)
1448
+ return;
1449
+ const valueText = ctx2.collection.stringify(ctx2.highlightedValue);
1450
+ domQuery.raf(() => {
1451
+ inputEl.value = valueText || ctx2.inputValue;
1452
+ });
1453
+ },
1454
+ setCollection(ctx2, evt) {
1455
+ ctx2.collection = evt.value;
1456
+ },
1457
+ syncSelectedItems(ctx2) {
1458
+ sync.valueChange(ctx2);
1459
+ set.inputValue(ctx2, getInputValue(ctx2));
1460
+ },
1461
+ syncHighlightedItem(ctx2) {
1462
+ sync.highlightChange(ctx2);
1463
+ },
1464
+ toggleVisibility(ctx2, evt, { send }) {
1465
+ send({ type: ctx2.open ? "CONTROLLED.OPEN" : "CONTROLLED.CLOSE", previousEvent: evt });
1466
+ }
1467
+ }
1468
+ }
1469
+ );
1470
+ }
1471
+
1472
+ exports.anatomy = anatomy;
1473
+ exports.collection = collection;
1474
+ exports.connect = connect;
1475
+ exports.machine = machine;