@zag-js/combobox 1.33.0 → 1.34.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.d.mts CHANGED
@@ -3,9 +3,9 @@ export { FocusOutsideEvent, InteractOutsideEvent, PointerDownOutsideEvent } from
3
3
  import * as _zag_js_anatomy from '@zag-js/anatomy';
4
4
  import { CollectionOptions, ListCollection, CollectionItem } from '@zag-js/collection';
5
5
  export { CollectionItem, CollectionOptions } from '@zag-js/collection';
6
- import { RequiredBy, DirectionProperty, CommonProperties, PropTypes, NormalizeProps } from '@zag-js/types';
6
+ import { PropTypes, RequiredBy, DirectionProperty, CommonProperties, NormalizeProps } from '@zag-js/types';
7
7
  import * as _zag_js_core from '@zag-js/core';
8
- import { Service, EventObject, Machine } from '@zag-js/core';
8
+ import { Machine, EventObject, Service } from '@zag-js/core';
9
9
  import { PositioningOptions, Placement } from '@zag-js/popper';
10
10
  export { Placement, PositioningOptions } from '@zag-js/popper';
11
11
 
package/dist/index.d.ts CHANGED
@@ -3,9 +3,9 @@ export { FocusOutsideEvent, InteractOutsideEvent, PointerDownOutsideEvent } from
3
3
  import * as _zag_js_anatomy from '@zag-js/anatomy';
4
4
  import { CollectionOptions, ListCollection, CollectionItem } from '@zag-js/collection';
5
5
  export { CollectionItem, CollectionOptions } from '@zag-js/collection';
6
- import { RequiredBy, DirectionProperty, CommonProperties, PropTypes, NormalizeProps } from '@zag-js/types';
6
+ import { PropTypes, RequiredBy, DirectionProperty, CommonProperties, NormalizeProps } from '@zag-js/types';
7
7
  import * as _zag_js_core from '@zag-js/core';
8
- import { Service, EventObject, Machine } from '@zag-js/core';
8
+ import { Machine, EventObject, Service } from '@zag-js/core';
9
9
  import { PositioningOptions, Placement } from '@zag-js/popper';
10
10
  export { Placement, PositioningOptions } from '@zag-js/popper';
11
11
 
package/dist/index.js CHANGED
@@ -7,6 +7,7 @@ var popper = require('@zag-js/popper');
7
7
  var utils = require('@zag-js/utils');
8
8
  var core = require('@zag-js/core');
9
9
  var dismissable = require('@zag-js/dismissable');
10
+ var focusVisible = require('@zag-js/focus-visible');
10
11
  var types = require('@zag-js/types');
11
12
 
12
13
  // src/combobox.anatomy.ts
@@ -57,8 +58,10 @@ var getItemEl = (ctx, value) => {
57
58
  };
58
59
  var focusInputEl = (ctx) => {
59
60
  const inputEl = getInputEl(ctx);
60
- if (ctx.isActiveElement(inputEl)) return;
61
- inputEl?.focus({ preventScroll: true });
61
+ if (!ctx.isActiveElement(inputEl)) {
62
+ inputEl?.focus({ preventScroll: true });
63
+ }
64
+ domQuery.setCaretToEnd(inputEl);
62
65
  };
63
66
  var focusTriggerEl = (ctx) => {
64
67
  const triggerEl = getTriggerEl(ctx);
@@ -85,12 +88,12 @@ function connect(service, normalize) {
85
88
  placement: context.get("currentPlacement")
86
89
  });
87
90
  function getItemState(props2) {
88
- const disabled2 = collection2.getItemDisabled(props2.item);
91
+ const itemDisabled = collection2.getItemDisabled(props2.item);
89
92
  const value = collection2.getItemValue(props2.item);
90
93
  utils.ensure(value, () => `[zag-js] No value found for item ${JSON.stringify(props2.item)}`);
91
94
  return {
92
95
  value,
93
- disabled: Boolean(disabled2 || disabled2),
96
+ disabled: Boolean(disabled || itemDisabled),
94
97
  highlighted: highlightedValue === value,
95
98
  selected: context.get("value").includes(value)
96
99
  };
@@ -323,7 +326,7 @@ function connect(service, normalize) {
323
326
  if (!domQuery.isLeftClick(event2)) return;
324
327
  event2.preventDefault();
325
328
  queueMicrotask(() => {
326
- getInputEl(scope)?.focus({ preventScroll: true });
329
+ focusInputEl(scope);
327
330
  });
328
331
  },
329
332
  onKeyDown(event2) {
@@ -409,7 +412,7 @@ function connect(service, normalize) {
409
412
  tabIndex: -1,
410
413
  "data-highlighted": domQuery.dataAttr(itemState.highlighted),
411
414
  "data-state": itemState.selected ? "checked" : "unchecked",
412
- "aria-selected": domQuery.ariaAttr(itemState.highlighted),
415
+ "aria-selected": domQuery.ariaAttr(itemState.selected),
413
416
  "aria-disabled": domQuery.ariaAttr(itemState.disabled),
414
417
  "data-disabled": domQuery.dataAttr(itemState.disabled),
415
418
  "data-value": itemState.value,
@@ -531,7 +534,8 @@ var machine = createMachine({
531
534
  const context = getContext();
532
535
  const prevSelectedItems = context.get("selectedItems");
533
536
  const collection2 = prop("collection");
534
- const nextItems = value.map((v) => {
537
+ const effectiveValue = prop("value") || value;
538
+ const nextItems = effectiveValue.map((v) => {
535
539
  const item = prevSelectedItems.find((item2) => collection2.getItemValue(item2) === v);
536
540
  return item || collection2.find(v);
537
541
  });
@@ -766,8 +770,7 @@ var machine = createMachine({
766
770
  "INPUT.ARROW_UP": [
767
771
  // == group 1 ==
768
772
  {
769
- guard: "autoComplete",
770
- target: "interacting",
773
+ guard: and("isOpenControlled", "autoComplete"),
771
774
  actions: ["invokeOnOpen"]
772
775
  },
773
776
  {
@@ -777,7 +780,7 @@ var machine = createMachine({
777
780
  },
778
781
  // == group 2 ==
779
782
  {
780
- target: "interacting",
783
+ guard: "isOpenControlled",
781
784
  actions: ["highlightLastOrSelectedItem", "invokeOnOpen"]
782
785
  },
783
786
  {
@@ -803,7 +806,7 @@ var machine = createMachine({
803
806
  interacting: {
804
807
  tags: ["open", "focused"],
805
808
  entry: ["setInitialFocus"],
806
- effects: ["scrollToHighlightedItem", "trackDismissableLayer", "trackPlacement"],
809
+ effects: ["trackFocusVisible", "scrollToHighlightedItem", "trackDismissableLayer", "trackPlacement"],
807
810
  on: {
808
811
  "CONTROLLED.CLOSE": [
809
812
  {
@@ -978,7 +981,7 @@ var machine = createMachine({
978
981
  },
979
982
  suggesting: {
980
983
  tags: ["open", "focused"],
981
- effects: ["trackDismissableLayer", "scrollToHighlightedItem", "trackPlacement"],
984
+ effects: ["trackFocusVisible", "trackDismissableLayer", "scrollToHighlightedItem", "trackPlacement"],
982
985
  entry: ["setInitialFocus"],
983
986
  on: {
984
987
  "CONTROLLED.CLOSE": [
@@ -1161,6 +1164,9 @@ var machine = createMachine({
1161
1164
  hasCollectionItems: ({ prop }) => prop("collection").size > 0
1162
1165
  },
1163
1166
  effects: {
1167
+ trackFocusVisible({ scope }) {
1168
+ return focusVisible.trackFocusVisible({ root: scope.getRootNode?.() });
1169
+ },
1164
1170
  trackDismissableLayer({ send, prop, scope }) {
1165
1171
  if (prop("disableLayer")) return;
1166
1172
  const contentEl = () => getContentEl(scope);
@@ -1193,13 +1199,14 @@ var machine = createMachine({
1193
1199
  }
1194
1200
  });
1195
1201
  },
1196
- scrollToHighlightedItem({ context, prop, scope, event }) {
1202
+ scrollToHighlightedItem({ context, prop, scope }) {
1197
1203
  const inputEl = getInputEl(scope);
1198
1204
  let cleanups = [];
1199
1205
  const exec = (immediate) => {
1200
- const pointer = event.current().type.includes("POINTER");
1206
+ const modality = focusVisible.getInteractionModality();
1207
+ if (modality === "pointer") return;
1201
1208
  const highlightedValue = context.get("highlightedValue");
1202
- if (pointer || !highlightedValue) return;
1209
+ if (!highlightedValue) return;
1203
1210
  const contentEl = getContentEl(scope);
1204
1211
  const scrollToIndexFn = prop("scrollToIndexFn");
1205
1212
  if (scrollToIndexFn) {
@@ -1217,7 +1224,10 @@ var machine = createMachine({
1217
1224
  });
1218
1225
  cleanups.push(raf_cleanup);
1219
1226
  };
1220
- const rafCleanup = domQuery.raf(() => exec(true));
1227
+ const rafCleanup = domQuery.raf(() => {
1228
+ focusVisible.setInteractionModality("virtual");
1229
+ exec(true);
1230
+ });
1221
1231
  cleanups.push(rafCleanup);
1222
1232
  const observerCleanup = domQuery.observeAttributes(inputEl, {
1223
1233
  attributes: ["aria-activedescendant"],
package/dist/index.mjs CHANGED
@@ -1,10 +1,11 @@
1
1
  import { createAnatomy } from '@zag-js/anatomy';
2
2
  import { ListCollection } from '@zag-js/collection';
3
- import { raf, setCaretToEnd, nextTick, scrollIntoView, observeAttributes, clickIfLink, query, dataAttr, ariaAttr, isDownloadingEvent, isOpeningInNewTab, isContextMenuEvent, isLeftClick, getEventKey, isComposingEvent, isAnchorElement } from '@zag-js/dom-query';
3
+ import { raf, setCaretToEnd, nextTick, scrollIntoView, observeAttributes, clickIfLink, query, dataAttr, isDownloadingEvent, isOpeningInNewTab, isContextMenuEvent, ariaAttr, isLeftClick, getEventKey, isComposingEvent, isAnchorElement } from '@zag-js/dom-query';
4
4
  import { getPlacement, getPlacementStyles } from '@zag-js/popper';
5
5
  import { match, remove, addOrRemove, isBoolean, isEqual, createSplitProps, ensure } from '@zag-js/utils';
6
6
  import { setup } from '@zag-js/core';
7
7
  import { trackDismissableElement } from '@zag-js/dismissable';
8
+ import { setInteractionModality, trackFocusVisible, getInteractionModality } from '@zag-js/focus-visible';
8
9
  import { createProps } from '@zag-js/types';
9
10
 
10
11
  // src/combobox.anatomy.ts
@@ -55,8 +56,10 @@ var getItemEl = (ctx, value) => {
55
56
  };
56
57
  var focusInputEl = (ctx) => {
57
58
  const inputEl = getInputEl(ctx);
58
- if (ctx.isActiveElement(inputEl)) return;
59
- inputEl?.focus({ preventScroll: true });
59
+ if (!ctx.isActiveElement(inputEl)) {
60
+ inputEl?.focus({ preventScroll: true });
61
+ }
62
+ setCaretToEnd(inputEl);
60
63
  };
61
64
  var focusTriggerEl = (ctx) => {
62
65
  const triggerEl = getTriggerEl(ctx);
@@ -83,12 +86,12 @@ function connect(service, normalize) {
83
86
  placement: context.get("currentPlacement")
84
87
  });
85
88
  function getItemState(props2) {
86
- const disabled2 = collection2.getItemDisabled(props2.item);
89
+ const itemDisabled = collection2.getItemDisabled(props2.item);
87
90
  const value = collection2.getItemValue(props2.item);
88
91
  ensure(value, () => `[zag-js] No value found for item ${JSON.stringify(props2.item)}`);
89
92
  return {
90
93
  value,
91
- disabled: Boolean(disabled2 || disabled2),
94
+ disabled: Boolean(disabled || itemDisabled),
92
95
  highlighted: highlightedValue === value,
93
96
  selected: context.get("value").includes(value)
94
97
  };
@@ -321,7 +324,7 @@ function connect(service, normalize) {
321
324
  if (!isLeftClick(event2)) return;
322
325
  event2.preventDefault();
323
326
  queueMicrotask(() => {
324
- getInputEl(scope)?.focus({ preventScroll: true });
327
+ focusInputEl(scope);
325
328
  });
326
329
  },
327
330
  onKeyDown(event2) {
@@ -407,7 +410,7 @@ function connect(service, normalize) {
407
410
  tabIndex: -1,
408
411
  "data-highlighted": dataAttr(itemState.highlighted),
409
412
  "data-state": itemState.selected ? "checked" : "unchecked",
410
- "aria-selected": ariaAttr(itemState.highlighted),
413
+ "aria-selected": ariaAttr(itemState.selected),
411
414
  "aria-disabled": ariaAttr(itemState.disabled),
412
415
  "data-disabled": dataAttr(itemState.disabled),
413
416
  "data-value": itemState.value,
@@ -529,7 +532,8 @@ var machine = createMachine({
529
532
  const context = getContext();
530
533
  const prevSelectedItems = context.get("selectedItems");
531
534
  const collection2 = prop("collection");
532
- const nextItems = value.map((v) => {
535
+ const effectiveValue = prop("value") || value;
536
+ const nextItems = effectiveValue.map((v) => {
533
537
  const item = prevSelectedItems.find((item2) => collection2.getItemValue(item2) === v);
534
538
  return item || collection2.find(v);
535
539
  });
@@ -764,8 +768,7 @@ var machine = createMachine({
764
768
  "INPUT.ARROW_UP": [
765
769
  // == group 1 ==
766
770
  {
767
- guard: "autoComplete",
768
- target: "interacting",
771
+ guard: and("isOpenControlled", "autoComplete"),
769
772
  actions: ["invokeOnOpen"]
770
773
  },
771
774
  {
@@ -775,7 +778,7 @@ var machine = createMachine({
775
778
  },
776
779
  // == group 2 ==
777
780
  {
778
- target: "interacting",
781
+ guard: "isOpenControlled",
779
782
  actions: ["highlightLastOrSelectedItem", "invokeOnOpen"]
780
783
  },
781
784
  {
@@ -801,7 +804,7 @@ var machine = createMachine({
801
804
  interacting: {
802
805
  tags: ["open", "focused"],
803
806
  entry: ["setInitialFocus"],
804
- effects: ["scrollToHighlightedItem", "trackDismissableLayer", "trackPlacement"],
807
+ effects: ["trackFocusVisible", "scrollToHighlightedItem", "trackDismissableLayer", "trackPlacement"],
805
808
  on: {
806
809
  "CONTROLLED.CLOSE": [
807
810
  {
@@ -976,7 +979,7 @@ var machine = createMachine({
976
979
  },
977
980
  suggesting: {
978
981
  tags: ["open", "focused"],
979
- effects: ["trackDismissableLayer", "scrollToHighlightedItem", "trackPlacement"],
982
+ effects: ["trackFocusVisible", "trackDismissableLayer", "scrollToHighlightedItem", "trackPlacement"],
980
983
  entry: ["setInitialFocus"],
981
984
  on: {
982
985
  "CONTROLLED.CLOSE": [
@@ -1159,6 +1162,9 @@ var machine = createMachine({
1159
1162
  hasCollectionItems: ({ prop }) => prop("collection").size > 0
1160
1163
  },
1161
1164
  effects: {
1165
+ trackFocusVisible({ scope }) {
1166
+ return trackFocusVisible({ root: scope.getRootNode?.() });
1167
+ },
1162
1168
  trackDismissableLayer({ send, prop, scope }) {
1163
1169
  if (prop("disableLayer")) return;
1164
1170
  const contentEl = () => getContentEl(scope);
@@ -1191,13 +1197,14 @@ var machine = createMachine({
1191
1197
  }
1192
1198
  });
1193
1199
  },
1194
- scrollToHighlightedItem({ context, prop, scope, event }) {
1200
+ scrollToHighlightedItem({ context, prop, scope }) {
1195
1201
  const inputEl = getInputEl(scope);
1196
1202
  let cleanups = [];
1197
1203
  const exec = (immediate) => {
1198
- const pointer = event.current().type.includes("POINTER");
1204
+ const modality = getInteractionModality();
1205
+ if (modality === "pointer") return;
1199
1206
  const highlightedValue = context.get("highlightedValue");
1200
- if (pointer || !highlightedValue) return;
1207
+ if (!highlightedValue) return;
1201
1208
  const contentEl = getContentEl(scope);
1202
1209
  const scrollToIndexFn = prop("scrollToIndexFn");
1203
1210
  if (scrollToIndexFn) {
@@ -1215,7 +1222,10 @@ var machine = createMachine({
1215
1222
  });
1216
1223
  cleanups.push(raf_cleanup);
1217
1224
  };
1218
- const rafCleanup = raf(() => exec(true));
1225
+ const rafCleanup = raf(() => {
1226
+ setInteractionModality("virtual");
1227
+ exec(true);
1228
+ });
1219
1229
  cleanups.push(rafCleanup);
1220
1230
  const observerCleanup = observeAttributes(inputEl, {
1221
1231
  attributes: ["aria-activedescendant"],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zag-js/combobox",
3
- "version": "1.33.0",
3
+ "version": "1.34.0",
4
4
  "description": "Core logic for the combobox widget implemented as a state machine",
5
5
  "keywords": [
6
6
  "js",
@@ -26,15 +26,16 @@
26
26
  "url": "https://github.com/chakra-ui/zag/issues"
27
27
  },
28
28
  "dependencies": {
29
- "@zag-js/anatomy": "1.33.0",
30
- "@zag-js/collection": "1.33.0",
31
- "@zag-js/core": "1.33.0",
32
- "@zag-js/aria-hidden": "1.33.0",
33
- "@zag-js/dismissable": "1.33.0",
34
- "@zag-js/utils": "1.33.0",
35
- "@zag-js/dom-query": "1.33.0",
36
- "@zag-js/popper": "1.33.0",
37
- "@zag-js/types": "1.33.0"
29
+ "@zag-js/anatomy": "1.34.0",
30
+ "@zag-js/aria-hidden": "1.34.0",
31
+ "@zag-js/collection": "1.34.0",
32
+ "@zag-js/core": "1.34.0",
33
+ "@zag-js/dismissable": "1.34.0",
34
+ "@zag-js/focus-visible": "1.34.0",
35
+ "@zag-js/dom-query": "1.34.0",
36
+ "@zag-js/popper": "1.34.0",
37
+ "@zag-js/types": "1.34.0",
38
+ "@zag-js/utils": "1.34.0"
38
39
  },
39
40
  "devDependencies": {
40
41
  "clean-package": "2.2.0"