@zag-js/combobox 1.34.0 → 1.35.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.js CHANGED
@@ -1,1590 +1,42 @@
1
- 'use strict';
2
-
3
- var anatomy$1 = require('@zag-js/anatomy');
4
- var collection$1 = require('@zag-js/collection');
5
- var domQuery = require('@zag-js/dom-query');
6
- var popper = require('@zag-js/popper');
7
- var utils = require('@zag-js/utils');
8
- var core = require('@zag-js/core');
9
- var dismissable = require('@zag-js/dismissable');
10
- var focusVisible = require('@zag-js/focus-visible');
11
- var types = require('@zag-js/types');
12
-
13
- // src/combobox.anatomy.ts
14
- var anatomy = anatomy$1.createAnatomy("combobox").parts(
15
- "root",
16
- "clearTrigger",
17
- "content",
18
- "control",
19
- "input",
20
- "item",
21
- "itemGroup",
22
- "itemGroupLabel",
23
- "itemIndicator",
24
- "itemText",
25
- "label",
26
- "list",
27
- "positioner",
28
- "trigger"
29
- );
30
- var parts = anatomy.build();
31
- var collection = (options) => {
32
- return new collection$1.ListCollection(options);
33
- };
34
- collection.empty = () => {
35
- return new collection$1.ListCollection({ items: [] });
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
36
9
  };
37
- var getRootId = (ctx) => ctx.ids?.root ?? `combobox:${ctx.id}`;
38
- var getLabelId = (ctx) => ctx.ids?.label ?? `combobox:${ctx.id}:label`;
39
- var getControlId = (ctx) => ctx.ids?.control ?? `combobox:${ctx.id}:control`;
40
- var getInputId = (ctx) => ctx.ids?.input ?? `combobox:${ctx.id}:input`;
41
- var getContentId = (ctx) => ctx.ids?.content ?? `combobox:${ctx.id}:content`;
42
- var getPositionerId = (ctx) => ctx.ids?.positioner ?? `combobox:${ctx.id}:popper`;
43
- var getTriggerId = (ctx) => ctx.ids?.trigger ?? `combobox:${ctx.id}:toggle-btn`;
44
- var getClearTriggerId = (ctx) => ctx.ids?.clearTrigger ?? `combobox:${ctx.id}:clear-btn`;
45
- var getItemGroupId = (ctx, id) => ctx.ids?.itemGroup?.(id) ?? `combobox:${ctx.id}:optgroup:${id}`;
46
- var getItemGroupLabelId = (ctx, id) => ctx.ids?.itemGroupLabel?.(id) ?? `combobox:${ctx.id}:optgroup-label:${id}`;
47
- var getItemId = (ctx, id) => ctx.ids?.item?.(id) ?? `combobox:${ctx.id}:option:${id}`;
48
- var getContentEl = (ctx) => ctx.getById(getContentId(ctx));
49
- var getInputEl = (ctx) => ctx.getById(getInputId(ctx));
50
- var getPositionerEl = (ctx) => ctx.getById(getPositionerId(ctx));
51
- var getControlEl = (ctx) => ctx.getById(getControlId(ctx));
52
- var getTriggerEl = (ctx) => ctx.getById(getTriggerId(ctx));
53
- var getClearTriggerEl = (ctx) => ctx.getById(getClearTriggerId(ctx));
54
- var getItemEl = (ctx, value) => {
55
- if (value == null) return null;
56
- const selector = `[role=option][data-value="${CSS.escape(value)}"]`;
57
- return domQuery.query(getContentEl(ctx), selector);
58
- };
59
- var focusInputEl = (ctx) => {
60
- const inputEl = getInputEl(ctx);
61
- if (!ctx.isActiveElement(inputEl)) {
62
- inputEl?.focus({ preventScroll: true });
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
63
15
  }
64
- domQuery.setCaretToEnd(inputEl);
65
- };
66
- var focusTriggerEl = (ctx) => {
67
- const triggerEl = getTriggerEl(ctx);
68
- if (ctx.isActiveElement(triggerEl)) return;
69
- triggerEl?.focus({ preventScroll: true });
16
+ return to;
70
17
  };
18
+ var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default"));
19
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
71
20
 
72
- // src/combobox.connect.ts
73
- function connect(service, normalize) {
74
- const { context, prop, state, send, scope, computed, event } = service;
75
- const translations = prop("translations");
76
- const collection2 = prop("collection");
77
- const disabled = !!prop("disabled");
78
- const interactive = computed("isInteractive");
79
- const invalid = !!prop("invalid");
80
- const required = !!prop("required");
81
- const readOnly = !!prop("readOnly");
82
- const open = state.hasTag("open");
83
- const focused = state.hasTag("focused");
84
- const composite = prop("composite");
85
- const highlightedValue = context.get("highlightedValue");
86
- const popperStyles = popper.getPlacementStyles({
87
- ...prop("positioning"),
88
- placement: context.get("currentPlacement")
89
- });
90
- function getItemState(props2) {
91
- const itemDisabled = collection2.getItemDisabled(props2.item);
92
- const value = collection2.getItemValue(props2.item);
93
- utils.ensure(value, () => `[zag-js] No value found for item ${JSON.stringify(props2.item)}`);
94
- return {
95
- value,
96
- disabled: Boolean(disabled || itemDisabled),
97
- highlighted: highlightedValue === value,
98
- selected: context.get("value").includes(value)
99
- };
100
- }
101
- return {
102
- focused,
103
- open,
104
- inputValue: context.get("inputValue"),
105
- highlightedValue,
106
- highlightedItem: context.get("highlightedItem"),
107
- value: context.get("value"),
108
- valueAsString: computed("valueAsString"),
109
- hasSelectedItems: computed("hasSelectedItems"),
110
- selectedItems: context.get("selectedItems"),
111
- collection: prop("collection"),
112
- multiple: !!prop("multiple"),
113
- disabled: !!disabled,
114
- syncSelectedItems() {
115
- send({ type: "SELECTED_ITEMS.SYNC" });
116
- },
117
- reposition(options = {}) {
118
- send({ type: "POSITIONING.SET", options });
119
- },
120
- setHighlightValue(value) {
121
- send({ type: "HIGHLIGHTED_VALUE.SET", value });
122
- },
123
- clearHighlightValue() {
124
- send({ type: "HIGHLIGHTED_VALUE.CLEAR" });
125
- },
126
- selectValue(value) {
127
- send({ type: "ITEM.SELECT", value });
128
- },
129
- setValue(value) {
130
- send({ type: "VALUE.SET", value });
131
- },
132
- setInputValue(value, reason = "script") {
133
- send({ type: "INPUT_VALUE.SET", value, src: reason });
134
- },
135
- clearValue(value) {
136
- if (value != null) {
137
- send({ type: "ITEM.CLEAR", value });
138
- } else {
139
- send({ type: "VALUE.CLEAR" });
140
- }
141
- },
142
- focus() {
143
- getInputEl(scope)?.focus();
144
- },
145
- setOpen(nextOpen, reason = "script") {
146
- const open2 = state.hasTag("open");
147
- if (open2 === nextOpen) return;
148
- send({ type: nextOpen ? "OPEN" : "CLOSE", src: reason });
149
- },
150
- getRootProps() {
151
- return normalize.element({
152
- ...parts.root.attrs,
153
- dir: prop("dir"),
154
- id: getRootId(scope),
155
- "data-invalid": domQuery.dataAttr(invalid),
156
- "data-readonly": domQuery.dataAttr(readOnly)
157
- });
158
- },
159
- getLabelProps() {
160
- return normalize.label({
161
- ...parts.label.attrs,
162
- dir: prop("dir"),
163
- htmlFor: getInputId(scope),
164
- id: getLabelId(scope),
165
- "data-readonly": domQuery.dataAttr(readOnly),
166
- "data-disabled": domQuery.dataAttr(disabled),
167
- "data-invalid": domQuery.dataAttr(invalid),
168
- "data-required": domQuery.dataAttr(required),
169
- "data-focus": domQuery.dataAttr(focused),
170
- onClick(event2) {
171
- if (composite) return;
172
- event2.preventDefault();
173
- getTriggerEl(scope)?.focus({ preventScroll: true });
174
- }
175
- });
176
- },
177
- getControlProps() {
178
- return normalize.element({
179
- ...parts.control.attrs,
180
- dir: prop("dir"),
181
- id: getControlId(scope),
182
- "data-state": open ? "open" : "closed",
183
- "data-focus": domQuery.dataAttr(focused),
184
- "data-disabled": domQuery.dataAttr(disabled),
185
- "data-invalid": domQuery.dataAttr(invalid)
186
- });
187
- },
188
- getPositionerProps() {
189
- return normalize.element({
190
- ...parts.positioner.attrs,
191
- dir: prop("dir"),
192
- id: getPositionerId(scope),
193
- style: popperStyles.floating
194
- });
195
- },
196
- getInputProps() {
197
- return normalize.input({
198
- ...parts.input.attrs,
199
- dir: prop("dir"),
200
- "aria-invalid": domQuery.ariaAttr(invalid),
201
- "data-invalid": domQuery.dataAttr(invalid),
202
- "data-autofocus": domQuery.dataAttr(prop("autoFocus")),
203
- name: prop("name"),
204
- form: prop("form"),
205
- disabled,
206
- required: prop("required"),
207
- autoComplete: "off",
208
- autoCorrect: "off",
209
- autoCapitalize: "none",
210
- spellCheck: "false",
211
- readOnly,
212
- placeholder: prop("placeholder"),
213
- id: getInputId(scope),
214
- type: "text",
215
- role: "combobox",
216
- defaultValue: context.get("inputValue"),
217
- "aria-autocomplete": computed("autoComplete") ? "both" : "list",
218
- "aria-controls": getContentId(scope),
219
- "aria-expanded": open,
220
- "data-state": open ? "open" : "closed",
221
- "aria-activedescendant": highlightedValue ? getItemId(scope, highlightedValue) : void 0,
222
- onClick(event2) {
223
- if (event2.defaultPrevented) return;
224
- if (!prop("openOnClick")) return;
225
- if (!interactive) return;
226
- send({ type: "INPUT.CLICK", src: "input-click" });
227
- },
228
- onFocus() {
229
- if (disabled) return;
230
- send({ type: "INPUT.FOCUS" });
231
- },
232
- onBlur() {
233
- if (disabled) return;
234
- send({ type: "INPUT.BLUR" });
235
- },
236
- onChange(event2) {
237
- send({ type: "INPUT.CHANGE", value: event2.currentTarget.value, src: "input-change" });
238
- },
239
- onKeyDown(event2) {
240
- if (event2.defaultPrevented) return;
241
- if (!interactive) return;
242
- if (event2.ctrlKey || event2.shiftKey || domQuery.isComposingEvent(event2)) return;
243
- const openOnKeyPress = prop("openOnKeyPress");
244
- const isModifierKey = event2.ctrlKey || event2.metaKey || event2.shiftKey;
245
- const keypress = true;
246
- const keymap = {
247
- ArrowDown(event3) {
248
- if (!openOnKeyPress && !open) return;
249
- send({ type: event3.altKey ? "OPEN" : "INPUT.ARROW_DOWN", keypress, src: "arrow-key" });
250
- event3.preventDefault();
251
- },
252
- ArrowUp() {
253
- if (!openOnKeyPress && !open) return;
254
- send({ type: event2.altKey ? "CLOSE" : "INPUT.ARROW_UP", keypress, src: "arrow-key" });
255
- event2.preventDefault();
256
- },
257
- Home(event3) {
258
- if (isModifierKey) return;
259
- send({ type: "INPUT.HOME", keypress });
260
- if (open) {
261
- event3.preventDefault();
262
- }
263
- },
264
- End(event3) {
265
- if (isModifierKey) return;
266
- send({ type: "INPUT.END", keypress });
267
- if (open) {
268
- event3.preventDefault();
269
- }
270
- },
271
- Enter(event3) {
272
- send({ type: "INPUT.ENTER", keypress, src: "item-select" });
273
- const submittable = computed("isCustomValue") && prop("allowCustomValue");
274
- const hasHighlight = highlightedValue != null;
275
- const alwaysSubmit = prop("alwaysSubmitOnEnter");
276
- if (open && !submittable && !alwaysSubmit && hasHighlight) {
277
- event3.preventDefault();
278
- }
279
- if (highlightedValue == null) return;
280
- const itemEl = getItemEl(scope, highlightedValue);
281
- if (domQuery.isAnchorElement(itemEl)) {
282
- prop("navigate")?.({ value: highlightedValue, node: itemEl, href: itemEl.href });
283
- }
284
- },
285
- Escape() {
286
- send({ type: "INPUT.ESCAPE", keypress, src: "escape-key" });
287
- event2.preventDefault();
288
- }
289
- };
290
- const key = domQuery.getEventKey(event2, { dir: prop("dir") });
291
- const exec = keymap[key];
292
- exec?.(event2);
293
- }
294
- });
295
- },
296
- getTriggerProps(props2 = {}) {
297
- return normalize.button({
298
- ...parts.trigger.attrs,
299
- dir: prop("dir"),
300
- id: getTriggerId(scope),
301
- "aria-haspopup": composite ? "listbox" : "dialog",
302
- type: "button",
303
- tabIndex: props2.focusable ? void 0 : -1,
304
- "aria-label": translations.triggerLabel,
305
- "aria-expanded": open,
306
- "data-state": open ? "open" : "closed",
307
- "aria-controls": open ? getContentId(scope) : void 0,
308
- disabled,
309
- "data-invalid": domQuery.dataAttr(invalid),
310
- "data-focusable": domQuery.dataAttr(props2.focusable),
311
- "data-readonly": domQuery.dataAttr(readOnly),
312
- "data-disabled": domQuery.dataAttr(disabled),
313
- onFocus() {
314
- if (!props2.focusable) return;
315
- send({ type: "INPUT.FOCUS", src: "trigger" });
316
- },
317
- onClick(event2) {
318
- if (event2.defaultPrevented) return;
319
- if (!interactive) return;
320
- if (!domQuery.isLeftClick(event2)) return;
321
- send({ type: "TRIGGER.CLICK", src: "trigger-click" });
322
- },
323
- onPointerDown(event2) {
324
- if (!interactive) return;
325
- if (event2.pointerType === "touch") return;
326
- if (!domQuery.isLeftClick(event2)) return;
327
- event2.preventDefault();
328
- queueMicrotask(() => {
329
- focusInputEl(scope);
330
- });
331
- },
332
- onKeyDown(event2) {
333
- if (event2.defaultPrevented) return;
334
- if (composite) return;
335
- const keyMap = {
336
- ArrowDown() {
337
- send({ type: "INPUT.ARROW_DOWN", src: "arrow-key" });
338
- },
339
- ArrowUp() {
340
- send({ type: "INPUT.ARROW_UP", src: "arrow-key" });
341
- }
342
- };
343
- const key = domQuery.getEventKey(event2, { dir: prop("dir") });
344
- const exec = keyMap[key];
345
- if (exec) {
346
- exec(event2);
347
- event2.preventDefault();
348
- }
349
- }
350
- });
351
- },
352
- getContentProps() {
353
- return normalize.element({
354
- ...parts.content.attrs,
355
- dir: prop("dir"),
356
- id: getContentId(scope),
357
- role: !composite ? "dialog" : "listbox",
358
- tabIndex: -1,
359
- hidden: !open,
360
- "data-state": open ? "open" : "closed",
361
- "data-placement": context.get("currentPlacement"),
362
- "aria-labelledby": getLabelId(scope),
363
- "aria-multiselectable": prop("multiple") && composite ? true : void 0,
364
- "data-empty": domQuery.dataAttr(collection2.size === 0),
365
- onPointerDown(event2) {
366
- if (!domQuery.isLeftClick(event2)) return;
367
- event2.preventDefault();
368
- }
369
- });
370
- },
371
- getListProps() {
372
- return normalize.element({
373
- ...parts.list.attrs,
374
- role: !composite ? "listbox" : void 0,
375
- "data-empty": domQuery.dataAttr(collection2.size === 0),
376
- "aria-labelledby": getLabelId(scope),
377
- "aria-multiselectable": prop("multiple") && !composite ? true : void 0
378
- });
379
- },
380
- getClearTriggerProps() {
381
- return normalize.button({
382
- ...parts.clearTrigger.attrs,
383
- dir: prop("dir"),
384
- id: getClearTriggerId(scope),
385
- type: "button",
386
- tabIndex: -1,
387
- disabled,
388
- "data-invalid": domQuery.dataAttr(invalid),
389
- "aria-label": translations.clearTriggerLabel,
390
- "aria-controls": getInputId(scope),
391
- hidden: !context.get("value").length,
392
- onPointerDown(event2) {
393
- if (!domQuery.isLeftClick(event2)) return;
394
- event2.preventDefault();
395
- },
396
- onClick(event2) {
397
- if (event2.defaultPrevented) return;
398
- if (!interactive) return;
399
- send({ type: "VALUE.CLEAR", src: "clear-trigger" });
400
- }
401
- });
402
- },
403
- getItemState,
404
- getItemProps(props2) {
405
- const itemState = getItemState(props2);
406
- const value = itemState.value;
407
- return normalize.element({
408
- ...parts.item.attrs,
409
- dir: prop("dir"),
410
- id: getItemId(scope, value),
411
- role: "option",
412
- tabIndex: -1,
413
- "data-highlighted": domQuery.dataAttr(itemState.highlighted),
414
- "data-state": itemState.selected ? "checked" : "unchecked",
415
- "aria-selected": domQuery.ariaAttr(itemState.selected),
416
- "aria-disabled": domQuery.ariaAttr(itemState.disabled),
417
- "data-disabled": domQuery.dataAttr(itemState.disabled),
418
- "data-value": itemState.value,
419
- onPointerMove() {
420
- if (itemState.disabled) return;
421
- if (itemState.highlighted) return;
422
- send({ type: "ITEM.POINTER_MOVE", value });
423
- },
424
- onPointerLeave() {
425
- if (props2.persistFocus) return;
426
- if (itemState.disabled) return;
427
- const prev = event.previous();
428
- const mouseMoved = prev?.type.includes("POINTER");
429
- if (!mouseMoved) return;
430
- send({ type: "ITEM.POINTER_LEAVE", value });
431
- },
432
- onClick(event2) {
433
- if (domQuery.isDownloadingEvent(event2)) return;
434
- if (domQuery.isOpeningInNewTab(event2)) return;
435
- if (domQuery.isContextMenuEvent(event2)) return;
436
- if (itemState.disabled) return;
437
- send({ type: "ITEM.CLICK", src: "item-select", value });
438
- }
439
- });
440
- },
441
- getItemTextProps(props2) {
442
- const itemState = getItemState(props2);
443
- return normalize.element({
444
- ...parts.itemText.attrs,
445
- dir: prop("dir"),
446
- "data-state": itemState.selected ? "checked" : "unchecked",
447
- "data-disabled": domQuery.dataAttr(itemState.disabled),
448
- "data-highlighted": domQuery.dataAttr(itemState.highlighted)
449
- });
450
- },
451
- getItemIndicatorProps(props2) {
452
- const itemState = getItemState(props2);
453
- return normalize.element({
454
- "aria-hidden": true,
455
- ...parts.itemIndicator.attrs,
456
- dir: prop("dir"),
457
- "data-state": itemState.selected ? "checked" : "unchecked",
458
- hidden: !itemState.selected
459
- });
460
- },
461
- getItemGroupProps(props2) {
462
- const { id } = props2;
463
- return normalize.element({
464
- ...parts.itemGroup.attrs,
465
- dir: prop("dir"),
466
- id: getItemGroupId(scope, id),
467
- "aria-labelledby": getItemGroupLabelId(scope, id),
468
- "data-empty": domQuery.dataAttr(collection2.size === 0),
469
- role: "group"
470
- });
471
- },
472
- getItemGroupLabelProps(props2) {
473
- const { htmlFor } = props2;
474
- return normalize.element({
475
- ...parts.itemGroupLabel.attrs,
476
- dir: prop("dir"),
477
- id: getItemGroupLabelId(scope, htmlFor),
478
- role: "presentation"
479
- });
480
- }
481
- };
482
- }
483
- var { guards, createMachine, choose } = core.setup();
484
- var { and, not } = guards;
485
- var machine = createMachine({
486
- props({ props: props2 }) {
487
- return {
488
- loopFocus: true,
489
- openOnClick: false,
490
- defaultValue: [],
491
- defaultInputValue: "",
492
- closeOnSelect: !props2.multiple,
493
- allowCustomValue: false,
494
- alwaysSubmitOnEnter: false,
495
- inputBehavior: "none",
496
- selectionBehavior: props2.multiple ? "clear" : "replace",
497
- openOnKeyPress: true,
498
- openOnChange: true,
499
- composite: true,
500
- navigate({ node }) {
501
- domQuery.clickIfLink(node);
502
- },
503
- collection: collection.empty(),
504
- ...props2,
505
- positioning: {
506
- placement: "bottom",
507
- sameWidth: true,
508
- ...props2.positioning
509
- },
510
- translations: {
511
- triggerLabel: "Toggle suggestions",
512
- clearTriggerLabel: "Clear value",
513
- ...props2.translations
514
- }
515
- };
516
- },
517
- initialState({ prop }) {
518
- const open = prop("open") || prop("defaultOpen");
519
- return open ? "suggesting" : "idle";
520
- },
521
- context({ prop, bindable, getContext, getEvent }) {
522
- return {
523
- currentPlacement: bindable(() => ({
524
- defaultValue: void 0
525
- })),
526
- value: bindable(() => ({
527
- defaultValue: prop("defaultValue"),
528
- value: prop("value"),
529
- isEqual: utils.isEqual,
530
- hash(value) {
531
- return value.join(",");
532
- },
533
- onChange(value) {
534
- const context = getContext();
535
- const prevSelectedItems = context.get("selectedItems");
536
- const collection2 = prop("collection");
537
- const effectiveValue = prop("value") || value;
538
- const nextItems = effectiveValue.map((v) => {
539
- const item = prevSelectedItems.find((item2) => collection2.getItemValue(item2) === v);
540
- return item || collection2.find(v);
541
- });
542
- context.set("selectedItems", nextItems);
543
- prop("onValueChange")?.({ value, items: nextItems });
544
- }
545
- })),
546
- highlightedValue: bindable(() => ({
547
- defaultValue: prop("defaultHighlightedValue") || null,
548
- value: prop("highlightedValue"),
549
- onChange(value) {
550
- const item = prop("collection").find(value);
551
- prop("onHighlightChange")?.({ highlightedValue: value, highlightedItem: item });
552
- }
553
- })),
554
- inputValue: bindable(() => {
555
- let inputValue = prop("inputValue") || prop("defaultInputValue");
556
- const value = prop("value") || prop("defaultValue");
557
- if (!inputValue.trim() && !prop("multiple")) {
558
- const valueAsString = prop("collection").stringifyMany(value);
559
- inputValue = utils.match(prop("selectionBehavior"), {
560
- preserve: inputValue || valueAsString,
561
- replace: valueAsString,
562
- clear: ""
563
- });
564
- }
565
- return {
566
- defaultValue: inputValue,
567
- value: prop("inputValue"),
568
- onChange(value2) {
569
- const event = getEvent();
570
- const reason = (event.previousEvent || event).src;
571
- prop("onInputValueChange")?.({ inputValue: value2, reason });
572
- }
573
- };
574
- }),
575
- highlightedItem: bindable(() => {
576
- const highlightedValue = prop("highlightedValue");
577
- const highlightedItem = prop("collection").find(highlightedValue);
578
- return { defaultValue: highlightedItem };
579
- }),
580
- selectedItems: bindable(() => {
581
- const value = prop("value") || prop("defaultValue") || [];
582
- const selectedItems = prop("collection").findMany(value);
583
- return { defaultValue: selectedItems };
584
- })
585
- };
586
- },
587
- computed: {
588
- isInputValueEmpty: ({ context }) => context.get("inputValue").length === 0,
589
- isInteractive: ({ prop }) => !(prop("readOnly") || prop("disabled")),
590
- autoComplete: ({ prop }) => prop("inputBehavior") === "autocomplete",
591
- autoHighlight: ({ prop }) => prop("inputBehavior") === "autohighlight",
592
- hasSelectedItems: ({ context }) => context.get("value").length > 0,
593
- valueAsString: ({ context, prop }) => prop("collection").stringifyItems(context.get("selectedItems")),
594
- isCustomValue: ({ context, computed }) => context.get("inputValue") !== computed("valueAsString")
595
- },
596
- watch({ context, prop, track, action, send }) {
597
- track([() => context.hash("value")], () => {
598
- action(["syncSelectedItems"]);
599
- });
600
- track([() => context.get("inputValue")], () => {
601
- action(["syncInputValue"]);
602
- });
603
- track([() => context.get("highlightedValue")], () => {
604
- action(["syncHighlightedItem", "autofillInputValue"]);
605
- });
606
- track([() => prop("open")], () => {
607
- action(["toggleVisibility"]);
608
- });
609
- track([() => prop("collection").toString()], () => {
610
- send({ type: "CHILDREN_CHANGE" });
611
- });
612
- },
613
- on: {
614
- "SELECTED_ITEMS.SYNC": {
615
- actions: ["syncSelectedItems"]
616
- },
617
- "HIGHLIGHTED_VALUE.SET": {
618
- actions: ["setHighlightedValue"]
619
- },
620
- "HIGHLIGHTED_VALUE.CLEAR": {
621
- actions: ["clearHighlightedValue"]
622
- },
623
- "ITEM.SELECT": {
624
- actions: ["selectItem"]
625
- },
626
- "ITEM.CLEAR": {
627
- actions: ["clearItem"]
628
- },
629
- "VALUE.SET": {
630
- actions: ["setValue"]
631
- },
632
- "INPUT_VALUE.SET": {
633
- actions: ["setInputValue"]
634
- },
635
- "POSITIONING.SET": {
636
- actions: ["reposition"]
637
- }
638
- },
639
- entry: choose([
640
- {
641
- guard: "autoFocus",
642
- actions: ["setInitialFocus"]
643
- }
644
- ]),
645
- states: {
646
- idle: {
647
- tags: ["idle", "closed"],
648
- entry: ["scrollContentToTop", "clearHighlightedValue"],
649
- on: {
650
- "CONTROLLED.OPEN": {
651
- target: "interacting"
652
- },
653
- "TRIGGER.CLICK": [
654
- {
655
- guard: "isOpenControlled",
656
- actions: ["setInitialFocus", "highlightFirstSelectedItem", "invokeOnOpen"]
657
- },
658
- {
659
- target: "interacting",
660
- actions: ["setInitialFocus", "highlightFirstSelectedItem", "invokeOnOpen"]
661
- }
662
- ],
663
- "INPUT.CLICK": [
664
- {
665
- guard: "isOpenControlled",
666
- actions: ["highlightFirstSelectedItem", "invokeOnOpen"]
667
- },
668
- {
669
- target: "interacting",
670
- actions: ["highlightFirstSelectedItem", "invokeOnOpen"]
671
- }
672
- ],
673
- "INPUT.FOCUS": {
674
- target: "focused"
675
- },
676
- OPEN: [
677
- {
678
- guard: "isOpenControlled",
679
- actions: ["invokeOnOpen"]
680
- },
681
- {
682
- target: "interacting",
683
- actions: ["invokeOnOpen"]
684
- }
685
- ],
686
- "VALUE.CLEAR": {
687
- target: "focused",
688
- actions: ["clearInputValue", "clearSelectedItems", "setInitialFocus"]
689
- }
690
- }
691
- },
692
- focused: {
693
- tags: ["focused", "closed"],
694
- entry: ["scrollContentToTop", "clearHighlightedValue"],
695
- on: {
696
- "CONTROLLED.OPEN": [
697
- {
698
- guard: "isChangeEvent",
699
- target: "suggesting"
700
- },
701
- {
702
- target: "interacting"
703
- }
704
- ],
705
- "INPUT.CHANGE": [
706
- {
707
- guard: and("isOpenControlled", "openOnChange"),
708
- actions: ["setInputValue", "invokeOnOpen", "highlightFirstItemIfNeeded"]
709
- },
710
- {
711
- guard: "openOnChange",
712
- target: "suggesting",
713
- actions: ["setInputValue", "invokeOnOpen", "highlightFirstItemIfNeeded"]
714
- },
715
- {
716
- actions: ["setInputValue"]
717
- }
718
- ],
719
- "LAYER.INTERACT_OUTSIDE": {
720
- target: "idle"
721
- },
722
- "INPUT.ESCAPE": {
723
- guard: and("isCustomValue", not("allowCustomValue")),
724
- actions: ["revertInputValue"]
725
- },
726
- "INPUT.BLUR": {
727
- target: "idle"
728
- },
729
- "INPUT.CLICK": [
730
- {
731
- guard: "isOpenControlled",
732
- actions: ["highlightFirstSelectedItem", "invokeOnOpen"]
733
- },
734
- {
735
- target: "interacting",
736
- actions: ["highlightFirstSelectedItem", "invokeOnOpen"]
737
- }
738
- ],
739
- "TRIGGER.CLICK": [
740
- {
741
- guard: "isOpenControlled",
742
- actions: ["setInitialFocus", "highlightFirstSelectedItem", "invokeOnOpen"]
743
- },
744
- {
745
- target: "interacting",
746
- actions: ["setInitialFocus", "highlightFirstSelectedItem", "invokeOnOpen"]
747
- }
748
- ],
749
- "INPUT.ARROW_DOWN": [
750
- // == group 1 ==
751
- {
752
- guard: and("isOpenControlled", "autoComplete"),
753
- actions: ["invokeOnOpen"]
754
- },
755
- {
756
- guard: "autoComplete",
757
- target: "interacting",
758
- actions: ["invokeOnOpen"]
759
- },
760
- // == group 2 ==
761
- {
762
- guard: "isOpenControlled",
763
- actions: ["highlightFirstOrSelectedItem", "invokeOnOpen"]
764
- },
765
- {
766
- target: "interacting",
767
- actions: ["highlightFirstOrSelectedItem", "invokeOnOpen"]
768
- }
769
- ],
770
- "INPUT.ARROW_UP": [
771
- // == group 1 ==
772
- {
773
- guard: and("isOpenControlled", "autoComplete"),
774
- actions: ["invokeOnOpen"]
775
- },
776
- {
777
- guard: "autoComplete",
778
- target: "interacting",
779
- actions: ["invokeOnOpen"]
780
- },
781
- // == group 2 ==
782
- {
783
- guard: "isOpenControlled",
784
- actions: ["highlightLastOrSelectedItem", "invokeOnOpen"]
785
- },
786
- {
787
- target: "interacting",
788
- actions: ["highlightLastOrSelectedItem", "invokeOnOpen"]
789
- }
790
- ],
791
- OPEN: [
792
- {
793
- guard: "isOpenControlled",
794
- actions: ["invokeOnOpen"]
795
- },
796
- {
797
- target: "interacting",
798
- actions: ["invokeOnOpen"]
799
- }
800
- ],
801
- "VALUE.CLEAR": {
802
- actions: ["clearInputValue", "clearSelectedItems"]
803
- }
804
- }
805
- },
806
- interacting: {
807
- tags: ["open", "focused"],
808
- entry: ["setInitialFocus"],
809
- effects: ["trackFocusVisible", "scrollToHighlightedItem", "trackDismissableLayer", "trackPlacement"],
810
- on: {
811
- "CONTROLLED.CLOSE": [
812
- {
813
- guard: "restoreFocus",
814
- target: "focused",
815
- actions: ["setFinalFocus"]
816
- },
817
- {
818
- target: "idle"
819
- }
820
- ],
821
- CHILDREN_CHANGE: [
822
- {
823
- guard: "isHighlightedItemRemoved",
824
- actions: ["clearHighlightedValue"]
825
- },
826
- {
827
- actions: ["scrollToHighlightedItem"]
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: ["clearHighlightedValue", "scrollContentToTop"]
840
- },
841
- {
842
- actions: ["highlightNextItem"]
843
- }
844
- ],
845
- "INPUT.ARROW_UP": [
846
- {
847
- guard: and("autoComplete", "isFirstItemHighlighted"),
848
- actions: ["clearHighlightedValue"]
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"]
884
- },
885
- {
886
- target: "suggesting",
887
- actions: ["clearHighlightedValue", "setInputValue"]
888
- }
889
- ],
890
- "ITEM.POINTER_MOVE": {
891
- actions: ["setHighlightedValue"]
892
- },
893
- "ITEM.POINTER_LEAVE": {
894
- actions: ["clearHighlightedValue"]
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
- effects: ["trackFocusVisible", "trackDismissableLayer", "scrollToHighlightedItem", "trackPlacement"],
985
- entry: ["setInitialFocus"],
986
- on: {
987
- "CONTROLLED.CLOSE": [
988
- {
989
- guard: "restoreFocus",
990
- target: "focused",
991
- actions: ["setFinalFocus"]
992
- },
993
- {
994
- target: "idle"
995
- }
996
- ],
997
- CHILDREN_CHANGE: [
998
- {
999
- guard: and("isHighlightedItemRemoved", "hasCollectionItems", "autoHighlight"),
1000
- actions: ["clearHighlightedValue", "highlightFirstItem"]
1001
- },
1002
- {
1003
- guard: "isHighlightedItemRemoved",
1004
- actions: ["clearHighlightedValue"]
1005
- },
1006
- {
1007
- guard: "autoHighlight",
1008
- actions: ["highlightFirstItem"]
1009
- }
1010
- ],
1011
- "INPUT.ARROW_DOWN": {
1012
- target: "interacting",
1013
- actions: ["highlightNextItem"]
1014
- },
1015
- "INPUT.ARROW_UP": {
1016
- target: "interacting",
1017
- actions: ["highlightPrevItem"]
1018
- },
1019
- "INPUT.HOME": {
1020
- target: "interacting",
1021
- actions: ["highlightFirstItem"]
1022
- },
1023
- "INPUT.END": {
1024
- target: "interacting",
1025
- actions: ["highlightLastItem"]
1026
- },
1027
- "INPUT.ENTER": [
1028
- // == group 1 ==
1029
- {
1030
- guard: and("isOpenControlled", "isCustomValue", not("hasHighlightedItem"), not("allowCustomValue")),
1031
- actions: ["revertInputValue", "invokeOnClose"]
1032
- },
1033
- {
1034
- guard: and("isCustomValue", not("hasHighlightedItem"), not("allowCustomValue")),
1035
- target: "focused",
1036
- actions: ["revertInputValue", "invokeOnClose"]
1037
- },
1038
- // == group 2 ==
1039
- {
1040
- guard: and("isOpenControlled", "closeOnSelect"),
1041
- actions: ["selectHighlightedItem", "invokeOnClose"]
1042
- },
1043
- {
1044
- guard: "closeOnSelect",
1045
- target: "focused",
1046
- actions: ["selectHighlightedItem", "invokeOnClose", "setFinalFocus"]
1047
- },
1048
- {
1049
- actions: ["selectHighlightedItem"]
1050
- }
1051
- ],
1052
- "INPUT.CHANGE": {
1053
- actions: ["setInputValue"]
1054
- },
1055
- "LAYER.ESCAPE": [
1056
- {
1057
- guard: "isOpenControlled",
1058
- actions: ["invokeOnClose"]
1059
- },
1060
- {
1061
- target: "focused",
1062
- actions: ["invokeOnClose"]
1063
- }
1064
- ],
1065
- "ITEM.POINTER_MOVE": {
1066
- target: "interacting",
1067
- actions: ["setHighlightedValue"]
1068
- },
1069
- "ITEM.POINTER_LEAVE": {
1070
- actions: ["clearHighlightedValue"]
1071
- },
1072
- "LAYER.INTERACT_OUTSIDE": [
1073
- // == group 1 ==
1074
- {
1075
- guard: and("isOpenControlled", "isCustomValue", not("allowCustomValue")),
1076
- actions: ["revertInputValue", "invokeOnClose"]
1077
- },
1078
- {
1079
- guard: and("isCustomValue", not("allowCustomValue")),
1080
- target: "idle",
1081
- actions: ["revertInputValue", "invokeOnClose"]
1082
- },
1083
- // == group 2 ==
1084
- {
1085
- guard: "isOpenControlled",
1086
- actions: ["invokeOnClose"]
1087
- },
1088
- {
1089
- target: "idle",
1090
- actions: ["invokeOnClose"]
1091
- }
1092
- ],
1093
- "TRIGGER.CLICK": [
1094
- {
1095
- guard: "isOpenControlled",
1096
- actions: ["invokeOnClose"]
1097
- },
1098
- {
1099
- target: "focused",
1100
- actions: ["invokeOnClose"]
1101
- }
1102
- ],
1103
- "ITEM.CLICK": [
1104
- {
1105
- guard: and("isOpenControlled", "closeOnSelect"),
1106
- actions: ["selectItem", "invokeOnClose"]
1107
- },
1108
- {
1109
- guard: "closeOnSelect",
1110
- target: "focused",
1111
- actions: ["selectItem", "invokeOnClose", "setFinalFocus"]
1112
- },
1113
- {
1114
- actions: ["selectItem"]
1115
- }
1116
- ],
1117
- CLOSE: [
1118
- {
1119
- guard: "isOpenControlled",
1120
- actions: ["invokeOnClose"]
1121
- },
1122
- {
1123
- target: "focused",
1124
- actions: ["invokeOnClose", "setFinalFocus"]
1125
- }
1126
- ],
1127
- "VALUE.CLEAR": [
1128
- {
1129
- guard: "isOpenControlled",
1130
- actions: ["clearInputValue", "clearSelectedItems", "invokeOnClose"]
1131
- },
1132
- {
1133
- target: "focused",
1134
- actions: ["clearInputValue", "clearSelectedItems", "invokeOnClose", "setFinalFocus"]
1135
- }
1136
- ]
1137
- }
1138
- }
1139
- },
1140
- implementations: {
1141
- guards: {
1142
- isInputValueEmpty: ({ computed }) => computed("isInputValueEmpty"),
1143
- autoComplete: ({ computed, prop }) => computed("autoComplete") && !prop("multiple"),
1144
- autoHighlight: ({ computed }) => computed("autoHighlight"),
1145
- isFirstItemHighlighted: ({ prop, context }) => prop("collection").firstValue === context.get("highlightedValue"),
1146
- isLastItemHighlighted: ({ prop, context }) => prop("collection").lastValue === context.get("highlightedValue"),
1147
- isCustomValue: ({ computed }) => computed("isCustomValue"),
1148
- allowCustomValue: ({ prop }) => !!prop("allowCustomValue"),
1149
- hasHighlightedItem: ({ context }) => context.get("highlightedValue") != null,
1150
- closeOnSelect: ({ prop }) => !!prop("closeOnSelect"),
1151
- isOpenControlled: ({ prop }) => prop("open") != null,
1152
- openOnChange: ({ prop, context }) => {
1153
- const openOnChange = prop("openOnChange");
1154
- if (utils.isBoolean(openOnChange)) return openOnChange;
1155
- return !!openOnChange?.({ inputValue: context.get("inputValue") });
1156
- },
1157
- restoreFocus: ({ event }) => {
1158
- const restoreFocus = event.restoreFocus ?? event.previousEvent?.restoreFocus;
1159
- return restoreFocus == null ? true : !!restoreFocus;
1160
- },
1161
- isChangeEvent: ({ event }) => event.previousEvent?.type === "INPUT.CHANGE",
1162
- autoFocus: ({ prop }) => !!prop("autoFocus"),
1163
- isHighlightedItemRemoved: ({ prop, context }) => !prop("collection").has(context.get("highlightedValue")),
1164
- hasCollectionItems: ({ prop }) => prop("collection").size > 0
1165
- },
1166
- effects: {
1167
- trackFocusVisible({ scope }) {
1168
- return focusVisible.trackFocusVisible({ root: scope.getRootNode?.() });
1169
- },
1170
- trackDismissableLayer({ send, prop, scope }) {
1171
- if (prop("disableLayer")) return;
1172
- const contentEl = () => getContentEl(scope);
1173
- return dismissable.trackDismissableElement(contentEl, {
1174
- type: "listbox",
1175
- defer: true,
1176
- exclude: () => [getInputEl(scope), getTriggerEl(scope), getClearTriggerEl(scope)],
1177
- onFocusOutside: prop("onFocusOutside"),
1178
- onPointerDownOutside: prop("onPointerDownOutside"),
1179
- onInteractOutside: prop("onInteractOutside"),
1180
- onEscapeKeyDown(event) {
1181
- event.preventDefault();
1182
- event.stopPropagation();
1183
- send({ type: "LAYER.ESCAPE", src: "escape-key" });
1184
- },
1185
- onDismiss() {
1186
- send({ type: "LAYER.INTERACT_OUTSIDE", src: "interact-outside", restoreFocus: false });
1187
- }
1188
- });
1189
- },
1190
- trackPlacement({ context, prop, scope }) {
1191
- const anchorEl = () => getControlEl(scope) || getTriggerEl(scope);
1192
- const positionerEl = () => getPositionerEl(scope);
1193
- context.set("currentPlacement", prop("positioning").placement);
1194
- return popper.getPlacement(anchorEl, positionerEl, {
1195
- ...prop("positioning"),
1196
- defer: true,
1197
- onComplete(data) {
1198
- context.set("currentPlacement", data.placement);
1199
- }
1200
- });
1201
- },
1202
- scrollToHighlightedItem({ context, prop, scope }) {
1203
- const inputEl = getInputEl(scope);
1204
- let cleanups = [];
1205
- const exec = (immediate) => {
1206
- const modality = focusVisible.getInteractionModality();
1207
- if (modality === "pointer") return;
1208
- const highlightedValue = context.get("highlightedValue");
1209
- if (!highlightedValue) return;
1210
- const contentEl = getContentEl(scope);
1211
- const scrollToIndexFn = prop("scrollToIndexFn");
1212
- if (scrollToIndexFn) {
1213
- const highlightedIndex = prop("collection").indexOf(highlightedValue);
1214
- scrollToIndexFn({
1215
- index: highlightedIndex,
1216
- immediate,
1217
- getElement: () => getItemEl(scope, highlightedValue)
1218
- });
1219
- return;
1220
- }
1221
- const itemEl = getItemEl(scope, highlightedValue);
1222
- const raf_cleanup = domQuery.raf(() => {
1223
- domQuery.scrollIntoView(itemEl, { rootEl: contentEl, block: "nearest" });
1224
- });
1225
- cleanups.push(raf_cleanup);
1226
- };
1227
- const rafCleanup = domQuery.raf(() => {
1228
- focusVisible.setInteractionModality("virtual");
1229
- exec(true);
1230
- });
1231
- cleanups.push(rafCleanup);
1232
- const observerCleanup = domQuery.observeAttributes(inputEl, {
1233
- attributes: ["aria-activedescendant"],
1234
- callback: () => exec(false)
1235
- });
1236
- cleanups.push(observerCleanup);
1237
- return () => {
1238
- cleanups.forEach((cleanup) => cleanup());
1239
- };
1240
- }
1241
- },
1242
- actions: {
1243
- reposition({ context, prop, scope, event }) {
1244
- const controlEl = () => getControlEl(scope);
1245
- const positionerEl = () => getPositionerEl(scope);
1246
- popper.getPlacement(controlEl, positionerEl, {
1247
- ...prop("positioning"),
1248
- ...event.options,
1249
- defer: true,
1250
- listeners: false,
1251
- onComplete(data) {
1252
- context.set("currentPlacement", data.placement);
1253
- }
1254
- });
1255
- },
1256
- setHighlightedValue({ context, event }) {
1257
- if (event.value == null) return;
1258
- context.set("highlightedValue", event.value);
1259
- },
1260
- clearHighlightedValue({ context }) {
1261
- context.set("highlightedValue", null);
1262
- },
1263
- selectHighlightedItem(params) {
1264
- const { context, prop } = params;
1265
- const collection2 = prop("collection");
1266
- const highlightedValue = context.get("highlightedValue");
1267
- if (!highlightedValue || !collection2.has(highlightedValue)) return;
1268
- const nextValue = prop("multiple") ? utils.addOrRemove(context.get("value"), highlightedValue) : [highlightedValue];
1269
- prop("onSelect")?.({ value: nextValue, itemValue: highlightedValue });
1270
- context.set("value", nextValue);
1271
- const inputValue = utils.match(prop("selectionBehavior"), {
1272
- preserve: context.get("inputValue"),
1273
- replace: collection2.stringifyMany(nextValue),
1274
- clear: ""
1275
- });
1276
- context.set("inputValue", inputValue);
1277
- },
1278
- scrollToHighlightedItem({ context, prop, scope }) {
1279
- domQuery.nextTick(() => {
1280
- const highlightedValue = context.get("highlightedValue");
1281
- if (highlightedValue == null) return;
1282
- const itemEl = getItemEl(scope, highlightedValue);
1283
- const contentEl = getContentEl(scope);
1284
- const scrollToIndexFn = prop("scrollToIndexFn");
1285
- if (scrollToIndexFn) {
1286
- const highlightedIndex = prop("collection").indexOf(highlightedValue);
1287
- scrollToIndexFn({
1288
- index: highlightedIndex,
1289
- immediate: true,
1290
- getElement: () => getItemEl(scope, highlightedValue)
1291
- });
1292
- return;
1293
- }
1294
- domQuery.scrollIntoView(itemEl, { rootEl: contentEl, block: "nearest" });
1295
- });
1296
- },
1297
- selectItem(params) {
1298
- const { context, event, flush, prop } = params;
1299
- if (event.value == null) return;
1300
- flush(() => {
1301
- const nextValue = prop("multiple") ? utils.addOrRemove(context.get("value"), event.value) : [event.value];
1302
- prop("onSelect")?.({ value: nextValue, itemValue: event.value });
1303
- context.set("value", nextValue);
1304
- const inputValue = utils.match(prop("selectionBehavior"), {
1305
- preserve: context.get("inputValue"),
1306
- replace: prop("collection").stringifyMany(nextValue),
1307
- clear: ""
1308
- });
1309
- context.set("inputValue", inputValue);
1310
- });
1311
- },
1312
- clearItem(params) {
1313
- const { context, event, flush, prop } = params;
1314
- if (event.value == null) return;
1315
- flush(() => {
1316
- const nextValue = utils.remove(context.get("value"), event.value);
1317
- context.set("value", nextValue);
1318
- const inputValue = utils.match(prop("selectionBehavior"), {
1319
- preserve: context.get("inputValue"),
1320
- replace: prop("collection").stringifyMany(nextValue),
1321
- clear: ""
1322
- });
1323
- context.set("inputValue", inputValue);
1324
- });
1325
- },
1326
- setInitialFocus({ scope }) {
1327
- domQuery.raf(() => {
1328
- focusInputEl(scope);
1329
- });
1330
- },
1331
- setFinalFocus({ scope }) {
1332
- domQuery.raf(() => {
1333
- const triggerEl = getTriggerEl(scope);
1334
- if (triggerEl?.dataset.focusable == null) {
1335
- focusInputEl(scope);
1336
- } else {
1337
- focusTriggerEl(scope);
1338
- }
1339
- });
1340
- },
1341
- syncInputValue({ context, scope, event }) {
1342
- const inputEl = getInputEl(scope);
1343
- if (!inputEl) return;
1344
- inputEl.value = context.get("inputValue");
1345
- queueMicrotask(() => {
1346
- if (event.current().type === "INPUT.CHANGE") return;
1347
- domQuery.setCaretToEnd(inputEl);
1348
- });
1349
- },
1350
- setInputValue({ context, event }) {
1351
- context.set("inputValue", event.value);
1352
- },
1353
- clearInputValue({ context }) {
1354
- context.set("inputValue", "");
1355
- },
1356
- revertInputValue({ context, prop, computed }) {
1357
- const selectionBehavior = prop("selectionBehavior");
1358
- const inputValue = utils.match(selectionBehavior, {
1359
- replace: computed("hasSelectedItems") ? computed("valueAsString") : "",
1360
- preserve: context.get("inputValue"),
1361
- clear: ""
1362
- });
1363
- context.set("inputValue", inputValue);
1364
- },
1365
- setValue(params) {
1366
- const { context, flush, event, prop } = params;
1367
- flush(() => {
1368
- context.set("value", event.value);
1369
- const inputValue = utils.match(prop("selectionBehavior"), {
1370
- preserve: context.get("inputValue"),
1371
- replace: prop("collection").stringifyMany(event.value),
1372
- clear: ""
1373
- });
1374
- context.set("inputValue", inputValue);
1375
- });
1376
- },
1377
- clearSelectedItems(params) {
1378
- const { context, flush, prop } = params;
1379
- flush(() => {
1380
- context.set("value", []);
1381
- const inputValue = utils.match(prop("selectionBehavior"), {
1382
- preserve: context.get("inputValue"),
1383
- replace: prop("collection").stringifyMany([]),
1384
- clear: ""
1385
- });
1386
- context.set("inputValue", inputValue);
1387
- });
1388
- },
1389
- scrollContentToTop({ prop, scope }) {
1390
- const scrollToIndexFn = prop("scrollToIndexFn");
1391
- if (scrollToIndexFn) {
1392
- const firstValue = prop("collection").firstValue;
1393
- scrollToIndexFn({
1394
- index: 0,
1395
- immediate: true,
1396
- getElement: () => getItemEl(scope, firstValue)
1397
- });
1398
- } else {
1399
- const contentEl = getContentEl(scope);
1400
- if (!contentEl) return;
1401
- contentEl.scrollTop = 0;
1402
- }
1403
- },
1404
- invokeOnOpen({ prop, event, context }) {
1405
- const reason = getOpenChangeReason(event);
1406
- prop("onOpenChange")?.({ open: true, reason, value: context.get("value") });
1407
- },
1408
- invokeOnClose({ prop, event, context }) {
1409
- const reason = getOpenChangeReason(event);
1410
- prop("onOpenChange")?.({ open: false, reason, value: context.get("value") });
1411
- },
1412
- highlightFirstItem({ context, prop, scope }) {
1413
- const exec = getContentEl(scope) ? queueMicrotask : domQuery.raf;
1414
- exec(() => {
1415
- const value = prop("collection").firstValue;
1416
- if (value) context.set("highlightedValue", value);
1417
- });
1418
- },
1419
- highlightFirstItemIfNeeded({ computed, action }) {
1420
- if (!computed("autoHighlight")) return;
1421
- action(["highlightFirstItem"]);
1422
- },
1423
- highlightLastItem({ context, prop, scope }) {
1424
- const exec = getContentEl(scope) ? queueMicrotask : domQuery.raf;
1425
- exec(() => {
1426
- const value = prop("collection").lastValue;
1427
- if (value) context.set("highlightedValue", value);
1428
- });
1429
- },
1430
- highlightNextItem({ context, prop }) {
1431
- let value = null;
1432
- const highlightedValue = context.get("highlightedValue");
1433
- const collection2 = prop("collection");
1434
- if (highlightedValue) {
1435
- value = collection2.getNextValue(highlightedValue);
1436
- if (!value && prop("loopFocus")) value = collection2.firstValue;
1437
- } else {
1438
- value = collection2.firstValue;
1439
- }
1440
- if (value) context.set("highlightedValue", value);
1441
- },
1442
- highlightPrevItem({ context, prop }) {
1443
- let value = null;
1444
- const highlightedValue = context.get("highlightedValue");
1445
- const collection2 = prop("collection");
1446
- if (highlightedValue) {
1447
- value = collection2.getPreviousValue(highlightedValue);
1448
- if (!value && prop("loopFocus")) value = collection2.lastValue;
1449
- } else {
1450
- value = collection2.lastValue;
1451
- }
1452
- if (value) context.set("highlightedValue", value);
1453
- },
1454
- highlightFirstSelectedItem({ context, prop }) {
1455
- domQuery.raf(() => {
1456
- const [value] = prop("collection").sort(context.get("value"));
1457
- if (value) context.set("highlightedValue", value);
1458
- });
1459
- },
1460
- highlightFirstOrSelectedItem({ context, prop, computed }) {
1461
- domQuery.raf(() => {
1462
- let value = null;
1463
- if (computed("hasSelectedItems")) {
1464
- value = prop("collection").sort(context.get("value"))[0];
1465
- } else {
1466
- value = prop("collection").firstValue;
1467
- }
1468
- if (value) context.set("highlightedValue", value);
1469
- });
1470
- },
1471
- highlightLastOrSelectedItem({ context, prop, computed }) {
1472
- domQuery.raf(() => {
1473
- const collection2 = prop("collection");
1474
- let value = null;
1475
- if (computed("hasSelectedItems")) {
1476
- value = collection2.sort(context.get("value"))[0];
1477
- } else {
1478
- value = collection2.lastValue;
1479
- }
1480
- if (value) context.set("highlightedValue", value);
1481
- });
1482
- },
1483
- autofillInputValue({ context, computed, prop, event, scope }) {
1484
- const inputEl = getInputEl(scope);
1485
- const collection2 = prop("collection");
1486
- if (!computed("autoComplete") || !inputEl || !event.keypress) return;
1487
- const valueText = collection2.stringify(context.get("highlightedValue"));
1488
- domQuery.raf(() => {
1489
- inputEl.value = valueText || context.get("inputValue");
1490
- });
1491
- },
1492
- syncSelectedItems(params) {
1493
- queueMicrotask(() => {
1494
- const { context, prop } = params;
1495
- const collection2 = prop("collection");
1496
- const value = context.get("value");
1497
- const selectedItems = value.map((v) => {
1498
- const item = context.get("selectedItems").find((item2) => collection2.getItemValue(item2) === v);
1499
- return item || collection2.find(v);
1500
- });
1501
- context.set("selectedItems", selectedItems);
1502
- const inputValue = utils.match(prop("selectionBehavior"), {
1503
- preserve: context.get("inputValue"),
1504
- replace: collection2.stringifyMany(value),
1505
- clear: ""
1506
- });
1507
- context.set("inputValue", inputValue);
1508
- });
1509
- },
1510
- syncHighlightedItem({ context, prop }) {
1511
- const item = prop("collection").find(context.get("highlightedValue"));
1512
- context.set("highlightedItem", item);
1513
- },
1514
- toggleVisibility({ event, send, prop }) {
1515
- send({ type: prop("open") ? "CONTROLLED.OPEN" : "CONTROLLED.CLOSE", previousEvent: event });
1516
- }
1517
- }
1518
- }
21
+ // src/index.ts
22
+ var index_exports = {};
23
+ __export(index_exports, {
24
+ anatomy: () => import_combobox.anatomy,
25
+ collection: () => import_combobox2.collection,
26
+ connect: () => import_combobox3.connect,
27
+ machine: () => import_combobox4.machine
28
+ });
29
+ module.exports = __toCommonJS(index_exports);
30
+ var import_combobox = require("./combobox.anatomy.cjs");
31
+ var import_combobox2 = require("./combobox.collection.cjs");
32
+ var import_combobox3 = require("./combobox.connect.cjs");
33
+ var import_combobox4 = require("./combobox.machine.cjs");
34
+ __reExport(index_exports, require("./combobox.props.cjs"), module.exports);
35
+ // Annotate the CommonJS export names for ESM import in node:
36
+ 0 && (module.exports = {
37
+ anatomy,
38
+ collection,
39
+ connect,
40
+ machine,
41
+ ...require("./combobox.props.cjs")
1519
42
  });
1520
- function getOpenChangeReason(event) {
1521
- return (event.previousEvent || event).src;
1522
- }
1523
- var props = types.createProps()([
1524
- "allowCustomValue",
1525
- "autoFocus",
1526
- "closeOnSelect",
1527
- "collection",
1528
- "composite",
1529
- "defaultHighlightedValue",
1530
- "defaultInputValue",
1531
- "defaultOpen",
1532
- "defaultValue",
1533
- "dir",
1534
- "disabled",
1535
- "disableLayer",
1536
- "form",
1537
- "getRootNode",
1538
- "highlightedValue",
1539
- "id",
1540
- "ids",
1541
- "inputBehavior",
1542
- "inputValue",
1543
- "invalid",
1544
- "loopFocus",
1545
- "multiple",
1546
- "name",
1547
- "navigate",
1548
- "onFocusOutside",
1549
- "onHighlightChange",
1550
- "onInputValueChange",
1551
- "onInteractOutside",
1552
- "onOpenChange",
1553
- "onOpenChange",
1554
- "onPointerDownOutside",
1555
- "onSelect",
1556
- "onValueChange",
1557
- "open",
1558
- "openOnChange",
1559
- "openOnClick",
1560
- "openOnKeyPress",
1561
- "placeholder",
1562
- "positioning",
1563
- "readOnly",
1564
- "required",
1565
- "scrollToIndexFn",
1566
- "selectionBehavior",
1567
- "translations",
1568
- "value",
1569
- "alwaysSubmitOnEnter"
1570
- ]);
1571
- var splitProps = utils.createSplitProps(props);
1572
- var itemGroupLabelProps = types.createProps()(["htmlFor"]);
1573
- var splitItemGroupLabelProps = utils.createSplitProps(itemGroupLabelProps);
1574
- var itemGroupProps = types.createProps()(["id"]);
1575
- var splitItemGroupProps = utils.createSplitProps(itemGroupProps);
1576
- var itemProps = types.createProps()(["item", "persistFocus"]);
1577
- var splitItemProps = utils.createSplitProps(itemProps);
1578
-
1579
- exports.anatomy = anatomy;
1580
- exports.collection = collection;
1581
- exports.connect = connect;
1582
- exports.itemGroupLabelProps = itemGroupLabelProps;
1583
- exports.itemGroupProps = itemGroupProps;
1584
- exports.itemProps = itemProps;
1585
- exports.machine = machine;
1586
- exports.props = props;
1587
- exports.splitItemGroupLabelProps = splitItemGroupLabelProps;
1588
- exports.splitItemGroupProps = splitItemGroupProps;
1589
- exports.splitItemProps = splitItemProps;
1590
- exports.splitProps = splitProps;