@destyler/combobox 0.0.7-beta.7 → 0.1.0

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