@zag-js/combobox 0.82.2 → 1.0.1

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