@ariakit/react-core 0.3.10 → 0.3.11

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.
Files changed (103) hide show
  1. package/CHANGELOG.md +50 -0
  2. package/cjs/__chunks/{TTMCZ7ZN.cjs → 3RUODFRU.cjs} +15 -0
  3. package/cjs/__chunks/{UBME4GBY.cjs → 63WKH5OP.cjs} +2 -2
  4. package/cjs/__chunks/{SANV4XBF.cjs → 7EEAHTIW.cjs} +2 -2
  5. package/cjs/__chunks/{3KZQJDTV.cjs → APFV5PTX.cjs} +2 -2
  6. package/cjs/__chunks/{DHSZ2ZFJ.cjs → BKU5STIE.cjs} +2 -2
  7. package/cjs/__chunks/{PHZJAGWK.cjs → IAYTETYN.cjs} +2 -2
  8. package/cjs/__chunks/{CZOBQEIO.cjs → RM2WCNSU.cjs} +16 -22
  9. package/cjs/__chunks/{GF6NWLKX.cjs → WWU35JDJ.cjs} +6 -2
  10. package/cjs/__chunks/{UUTXBBHD.cjs → XAYQLYTN.cjs} +2 -2
  11. package/cjs/checkbox/checkbox-check.d.cts +6 -3
  12. package/cjs/checkbox/checkbox-check.d.ts +6 -3
  13. package/cjs/combobox/combobox-disclosure.cjs +3 -4
  14. package/cjs/combobox/combobox-item.cjs +2 -2
  15. package/cjs/combobox/combobox-item.d.cts +13 -1
  16. package/cjs/combobox/combobox-item.d.ts +13 -1
  17. package/cjs/combobox/combobox-popover.cjs +34 -5
  18. package/cjs/combobox/combobox-popover.d.cts +1 -1
  19. package/cjs/combobox/combobox-popover.d.ts +1 -1
  20. package/cjs/combobox/combobox.cjs +18 -6
  21. package/cjs/combobox/combobox.d.cts +26 -1
  22. package/cjs/combobox/combobox.d.ts +26 -1
  23. package/cjs/composite/composite-hover.d.cts +10 -1
  24. package/cjs/composite/composite-hover.d.ts +10 -1
  25. package/cjs/composite/composite-item.cjs +2 -2
  26. package/cjs/composite/composite-overflow-disclosure.cjs +2 -2
  27. package/cjs/composite/composite.cjs +2 -2
  28. package/cjs/form/form-radio.cjs +3 -3
  29. package/cjs/menu/menu-bar.cjs +3 -3
  30. package/cjs/menu/menu-item-check.d.cts +14 -0
  31. package/cjs/menu/menu-item-check.d.ts +14 -0
  32. package/cjs/menu/menu-item-checkbox.cjs +3 -3
  33. package/cjs/menu/menu-item-radio.cjs +5 -5
  34. package/cjs/menu/menu-item.cjs +3 -3
  35. package/cjs/menu/menu-item.d.cts +8 -1
  36. package/cjs/menu/menu-item.d.ts +8 -1
  37. package/cjs/menu/menu-list.cjs +3 -3
  38. package/cjs/menu/menu-store.d.cts +2 -0
  39. package/cjs/menu/menu-store.d.ts +2 -0
  40. package/cjs/menu/menu.cjs +3 -3
  41. package/cjs/menubar/menubar.cjs +3 -3
  42. package/cjs/popover/popover.d.cts +2 -0
  43. package/cjs/popover/popover.d.ts +2 -0
  44. package/cjs/radio/radio-group.cjs +2 -2
  45. package/cjs/radio/radio.cjs +3 -3
  46. package/cjs/select/select-item.cjs +2 -2
  47. package/cjs/select/select-list.cjs +3 -3
  48. package/cjs/select/select-popover.cjs +3 -3
  49. package/cjs/tab/tab-list.cjs +2 -2
  50. package/cjs/tab/tab-provider.cjs +2 -2
  51. package/cjs/tab/tab-store.cjs +2 -2
  52. package/cjs/tab/tab.cjs +2 -2
  53. package/cjs/toolbar/toolbar-container.cjs +3 -3
  54. package/cjs/toolbar/toolbar-input.cjs +3 -3
  55. package/cjs/toolbar/toolbar-item.cjs +3 -3
  56. package/cjs/toolbar/toolbar.cjs +2 -2
  57. package/esm/__chunks/{FHDXHZLB.js → 57KNUQTI.js} +16 -22
  58. package/esm/__chunks/{UV2O3GRQ.js → 7D63S66W.js} +1 -1
  59. package/esm/__chunks/{TZJDOU75.js → 7R5VX7DV.js} +1 -1
  60. package/esm/__chunks/{GJYUMUMT.js → 7SHHFY4P.js} +1 -1
  61. package/esm/__chunks/{QEPSYGAQ.js → CVFC2LN3.js} +1 -1
  62. package/esm/__chunks/{DHHIMTTV.js → DENCHBDS.js} +1 -1
  63. package/esm/__chunks/{K5VQ2XTM.js → LZUSNDXA.js} +6 -2
  64. package/esm/__chunks/{P6VCQ6Q3.js → R2WNOXYG.js} +15 -0
  65. package/esm/__chunks/{UJUY6GAA.js → W2TTCKOE.js} +1 -1
  66. package/esm/checkbox/checkbox-check.d.ts +6 -3
  67. package/esm/combobox/combobox-disclosure.js +3 -4
  68. package/esm/combobox/combobox-item.d.ts +13 -1
  69. package/esm/combobox/combobox-item.js +1 -1
  70. package/esm/combobox/combobox-popover.d.ts +1 -1
  71. package/esm/combobox/combobox-popover.js +35 -6
  72. package/esm/combobox/combobox.d.ts +26 -1
  73. package/esm/combobox/combobox.js +17 -5
  74. package/esm/composite/composite-hover.d.ts +10 -1
  75. package/esm/composite/composite-item.js +1 -1
  76. package/esm/composite/composite-overflow-disclosure.js +1 -1
  77. package/esm/composite/composite.js +1 -1
  78. package/esm/form/form-radio.js +2 -2
  79. package/esm/menu/menu-bar.js +2 -2
  80. package/esm/menu/menu-item-check.d.ts +14 -0
  81. package/esm/menu/menu-item-checkbox.js +2 -2
  82. package/esm/menu/menu-item-radio.js +3 -3
  83. package/esm/menu/menu-item.d.ts +8 -1
  84. package/esm/menu/menu-item.js +2 -2
  85. package/esm/menu/menu-list.js +2 -2
  86. package/esm/menu/menu-store.d.ts +2 -0
  87. package/esm/menu/menu.js +2 -2
  88. package/esm/menubar/menubar.js +2 -2
  89. package/esm/popover/popover.d.ts +2 -0
  90. package/esm/radio/radio-group.js +1 -1
  91. package/esm/radio/radio.js +2 -2
  92. package/esm/select/select-item.js +1 -1
  93. package/esm/select/select-list.js +2 -2
  94. package/esm/select/select-popover.js +2 -2
  95. package/esm/tab/tab-list.js +1 -1
  96. package/esm/tab/tab-provider.js +1 -1
  97. package/esm/tab/tab-store.js +1 -1
  98. package/esm/tab/tab.js +1 -1
  99. package/esm/toolbar/toolbar-container.js +2 -2
  100. package/esm/toolbar/toolbar-input.js +2 -2
  101. package/esm/toolbar/toolbar-item.js +2 -2
  102. package/esm/toolbar/toolbar.js +1 -1
  103. package/package.json +2 -2
@@ -1,7 +1,7 @@
1
1
  "use strict";Object.defineProperty(exports, "__esModule", {value: true});"use client";
2
2
 
3
3
 
4
- var _GF6NWLKXcjs = require('../__chunks/GF6NWLKX.cjs');
4
+ var _WWU35JDJcjs = require('../__chunks/WWU35JDJ.cjs');
5
5
 
6
6
 
7
7
  var _I65V32V2cjs = require('../__chunks/I65V32V2.cjs');
@@ -18,7 +18,7 @@ require('../__chunks/AV6KTKLE.cjs');
18
18
  // src/tab/tab-provider.tsx
19
19
  var _jsxruntime = require('react/jsx-runtime');
20
20
  function TabProvider(props = {}) {
21
- const store = _GF6NWLKXcjs.useTabStore.call(void 0, props);
21
+ const store = _WWU35JDJcjs.useTabStore.call(void 0, props);
22
22
  return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _I65V32V2cjs.TabContextProvider, { value: store, children: props.children });
23
23
  }
24
24
 
@@ -2,7 +2,7 @@
2
2
 
3
3
 
4
4
 
5
- var _GF6NWLKXcjs = require('../__chunks/GF6NWLKX.cjs');
5
+ var _WWU35JDJcjs = require('../__chunks/WWU35JDJ.cjs');
6
6
  require('../__chunks/N6CR2VNN.cjs');
7
7
  require('../__chunks/DKOWT2IJ.cjs');
8
8
  require('../__chunks/B233QVZE.cjs');
@@ -12,4 +12,4 @@ require('../__chunks/AV6KTKLE.cjs');
12
12
 
13
13
 
14
14
 
15
- exports.useTabStore = _GF6NWLKXcjs.useTabStore; exports.useTabStoreProps = _GF6NWLKXcjs.useTabStoreProps;
15
+ exports.useTabStore = _WWU35JDJcjs.useTabStore; exports.useTabStoreProps = _WWU35JDJcjs.useTabStoreProps;
package/cjs/tab/tab.cjs CHANGED
@@ -1,7 +1,7 @@
1
1
  "use strict";Object.defineProperty(exports, "__esModule", {value: true});"use client";
2
2
 
3
3
 
4
- var _TTMCZ7ZNcjs = require('../__chunks/TTMCZ7ZN.cjs');
4
+ var _3RUODFRUcjs = require('../__chunks/3RUODFRU.cjs');
5
5
  require('../__chunks/DAJUUBUI.cjs');
6
6
  require('../__chunks/R5A2WTWB.cjs');
7
7
 
@@ -84,7 +84,7 @@ var useTab = _RNZNGEL4cjs.createHook.call(void 0,
84
84
  }, props), {
85
85
  onClick
86
86
  });
87
- props = _TTMCZ7ZNcjs.useCompositeItem.call(void 0, _AV6KTKLEcjs.__spreadProps.call(void 0, _AV6KTKLEcjs.__spreadValues.call(void 0, {
87
+ props = _3RUODFRUcjs.useCompositeItem.call(void 0, _AV6KTKLEcjs.__spreadProps.call(void 0, _AV6KTKLEcjs.__spreadValues.call(void 0, {
88
88
  store
89
89
  }, props), {
90
90
  accessibleWhenDisabled,
@@ -4,8 +4,8 @@
4
4
  var _VQJ44BSYcjs = require('../__chunks/VQJ44BSY.cjs');
5
5
 
6
6
 
7
- var _SANV4XBFcjs = require('../__chunks/SANV4XBF.cjs');
8
- require('../__chunks/TTMCZ7ZN.cjs');
7
+ var _7EEAHTIWcjs = require('../__chunks/7EEAHTIW.cjs');
8
+ require('../__chunks/3RUODFRU.cjs');
9
9
  require('../__chunks/DAJUUBUI.cjs');
10
10
  require('../__chunks/R5A2WTWB.cjs');
11
11
  require('../__chunks/RV3PHHWM.cjs');
@@ -36,7 +36,7 @@ var useToolbarContainer = _RNZNGEL4cjs.createHook.call(void 0,
36
36
  const context = _LYIGAIJFcjs.useToolbarContext.call(void 0, );
37
37
  store = store || context;
38
38
  props = _VQJ44BSYcjs.useCompositeContainer.call(void 0, _AV6KTKLEcjs.__spreadValues.call(void 0, { store }, props));
39
- props = _SANV4XBFcjs.useToolbarItem.call(void 0, _AV6KTKLEcjs.__spreadValues.call(void 0, { store }, props));
39
+ props = _7EEAHTIWcjs.useToolbarItem.call(void 0, _AV6KTKLEcjs.__spreadValues.call(void 0, { store }, props));
40
40
  return props;
41
41
  }
42
42
  );
@@ -4,8 +4,8 @@
4
4
  var _FM5S6RADcjs = require('../__chunks/FM5S6RAD.cjs');
5
5
 
6
6
 
7
- var _SANV4XBFcjs = require('../__chunks/SANV4XBF.cjs');
8
- require('../__chunks/TTMCZ7ZN.cjs');
7
+ var _7EEAHTIWcjs = require('../__chunks/7EEAHTIW.cjs');
8
+ require('../__chunks/3RUODFRU.cjs');
9
9
  require('../__chunks/DAJUUBUI.cjs');
10
10
  require('../__chunks/R5A2WTWB.cjs');
11
11
  require('../__chunks/RV3PHHWM.cjs');
@@ -36,7 +36,7 @@ var useToolbarInput = _RNZNGEL4cjs.createHook.call(void 0,
36
36
  const context = _LYIGAIJFcjs.useToolbarContext.call(void 0, );
37
37
  store = store || context;
38
38
  props = _FM5S6RADcjs.useCompositeInput.call(void 0, _AV6KTKLEcjs.__spreadValues.call(void 0, { store }, props));
39
- props = _SANV4XBFcjs.useToolbarItem.call(void 0, _AV6KTKLEcjs.__spreadValues.call(void 0, { store }, props));
39
+ props = _7EEAHTIWcjs.useToolbarItem.call(void 0, _AV6KTKLEcjs.__spreadValues.call(void 0, { store }, props));
40
40
  return props;
41
41
  }
42
42
  );
@@ -2,8 +2,8 @@
2
2
 
3
3
 
4
4
 
5
- var _SANV4XBFcjs = require('../__chunks/SANV4XBF.cjs');
6
- require('../__chunks/TTMCZ7ZN.cjs');
5
+ var _7EEAHTIWcjs = require('../__chunks/7EEAHTIW.cjs');
6
+ require('../__chunks/3RUODFRU.cjs');
7
7
  require('../__chunks/DAJUUBUI.cjs');
8
8
  require('../__chunks/R5A2WTWB.cjs');
9
9
  require('../__chunks/RV3PHHWM.cjs');
@@ -20,4 +20,4 @@ require('../__chunks/AV6KTKLE.cjs');
20
20
 
21
21
 
22
22
 
23
- exports.ToolbarItem = _SANV4XBFcjs.ToolbarItem; exports.useToolbarItem = _SANV4XBFcjs.useToolbarItem;
23
+ exports.ToolbarItem = _7EEAHTIWcjs.ToolbarItem; exports.useToolbarItem = _7EEAHTIWcjs.useToolbarItem;
@@ -1,7 +1,7 @@
1
1
  "use strict";Object.defineProperty(exports, "__esModule", {value: true});"use client";
2
2
 
3
3
 
4
- var _CZOBQEIOcjs = require('../__chunks/CZOBQEIO.cjs');
4
+ var _RM2WCNSUcjs = require('../__chunks/RM2WCNSU.cjs');
5
5
  require('../__chunks/RV3PHHWM.cjs');
6
6
 
7
7
 
@@ -69,7 +69,7 @@ var useToolbar = _RNZNGEL4cjs.createHook.call(void 0,
69
69
  role: "toolbar",
70
70
  "aria-orientation": orientation
71
71
  }, props);
72
- props = _CZOBQEIOcjs.useComposite.call(void 0, _AV6KTKLEcjs.__spreadValues.call(void 0, { store }, props));
72
+ props = _RM2WCNSUcjs.useComposite.call(void 0, _AV6KTKLEcjs.__spreadValues.call(void 0, { store }, props));
73
73
  return props;
74
74
  }
75
75
  );
@@ -48,43 +48,32 @@ function isGrid(items) {
48
48
  return items.some((item) => !!item.rowId);
49
49
  }
50
50
  function isPrintableKey(event) {
51
+ const target = event.target;
52
+ if (target && !isTextField(target))
53
+ return false;
51
54
  return event.key.length === 1 && !event.ctrlKey && !event.metaKey;
52
55
  }
53
56
  function isModifierKey(event) {
54
57
  return event.key === "Shift" || event.key === "Control" || event.key === "Alt" || event.key === "Meta";
55
58
  }
56
- function canProxyKeyboardEvent(event, state) {
57
- if (!isSelfTarget(event))
58
- return false;
59
- if (isModifierKey(event))
60
- return false;
61
- const target = event.target;
62
- if (!target)
63
- return true;
64
- if (isTextField(target)) {
65
- if (isPrintableKey(event))
66
- return false;
67
- const grid = isGrid(state.renderedItems);
68
- const focusingInputOnly = state.activeId === null;
69
- const allowHorizontalNavigationOnItems = grid && !focusingInputOnly;
70
- const isHomeOrEnd = event.key === "Home" || event.key === "End";
71
- if (!allowHorizontalNavigationOnItems && isHomeOrEnd)
72
- return false;
73
- }
74
- return !event.isPropagationStopped();
75
- }
76
59
  function useKeyboardEventProxy(store, onKeyboardEvent, previousElementRef) {
77
60
  return useEvent((event) => {
78
61
  var _a;
79
62
  onKeyboardEvent == null ? void 0 : onKeyboardEvent(event);
80
63
  if (event.defaultPrevented)
81
64
  return;
65
+ if (event.isPropagationStopped())
66
+ return;
67
+ if (!isSelfTarget(event))
68
+ return;
69
+ if (isModifierKey(event))
70
+ return;
71
+ if (isPrintableKey(event))
72
+ return;
82
73
  const state = store.getState();
83
74
  const activeElement = (_a = getEnabledItem(store, state.activeId)) == null ? void 0 : _a.element;
84
75
  if (!activeElement)
85
76
  return;
86
- if (!canProxyKeyboardEvent(event, state))
87
- return;
88
77
  const _b = event, { view } = _b, eventInit = __objRest(_b, ["view"]);
89
78
  const previousElement = previousElementRef == null ? void 0 : previousElementRef.current;
90
79
  if (activeElement !== previousElement) {
@@ -269,6 +258,8 @@ var useComposite = createHook(
269
258
  }
270
259
  } else if (activeElement) {
271
260
  fireBlurEvent(activeElement, event);
261
+ } else if (previousElement) {
262
+ fireBlurEvent(previousElement, event);
272
263
  }
273
264
  event.stopPropagation();
274
265
  } else {
@@ -296,6 +287,9 @@ var useComposite = createHook(
296
287
  const isVertical = orientation !== "horizontal";
297
288
  const isHorizontal = orientation !== "vertical";
298
289
  const grid = isGrid(renderedItems);
290
+ const isHorizontalKey = event.key === "ArrowLeft" || event.key === "ArrowRight" || event.key === "Home" || event.key === "End";
291
+ if (isHorizontalKey && isTextField(event.currentTarget))
292
+ return;
299
293
  const up = () => {
300
294
  if (grid) {
301
295
  const item = items && findFirstEnabledItemInTheLastRow(items);
@@ -8,7 +8,7 @@ import {
8
8
  } from "./5HVNGX6D.js";
9
9
  import {
10
10
  useComposite
11
- } from "./FHDXHZLB.js";
11
+ } from "./57KNUQTI.js";
12
12
  import {
13
13
  isHidden
14
14
  } from "./KOKHD3Z3.js";
@@ -8,7 +8,7 @@ import {
8
8
  } from "./FWQLUQ4T.js";
9
9
  import {
10
10
  useComposite
11
- } from "./FHDXHZLB.js";
11
+ } from "./57KNUQTI.js";
12
12
  import {
13
13
  createComponent,
14
14
  createElement,
@@ -4,7 +4,7 @@ import {
4
4
  } from "./XEV62JUQ.js";
5
5
  import {
6
6
  useCompositeItem
7
- } from "./P6VCQ6Q3.js";
7
+ } from "./R2WNOXYG.js";
8
8
  import {
9
9
  createElement,
10
10
  createHook,
@@ -10,7 +10,7 @@ import {
10
10
  } from "./G6ONQ5EH.js";
11
11
  import {
12
12
  useCompositeItem
13
- } from "./P6VCQ6Q3.js";
13
+ } from "./R2WNOXYG.js";
14
14
  import {
15
15
  createElement,
16
16
  createHook,
@@ -8,7 +8,7 @@ import {
8
8
  } from "./HBGJOTTX.js";
9
9
  import {
10
10
  useComposite
11
- } from "./FHDXHZLB.js";
11
+ } from "./57KNUQTI.js";
12
12
  import {
13
13
  isHidden
14
14
  } from "./KOKHD3Z3.js";
@@ -6,6 +6,9 @@ import {
6
6
  useStore,
7
7
  useStoreProps
8
8
  } from "./4OZYHFMH.js";
9
+ import {
10
+ useUpdateEffect
11
+ } from "./6O5OEQGF.js";
9
12
  import {
10
13
  __spreadProps,
11
14
  __spreadValues
@@ -18,8 +21,9 @@ function useTabStoreProps(store, update, props) {
18
21
  store = useCompositeStoreProps(store, update, props);
19
22
  useStoreProps(store, props, "selectedId", "setSelectedId");
20
23
  useStoreProps(store, props, "selectOnMove");
21
- const [panels] = useStore(() => store.panels, {});
22
- return useMemo(() => __spreadProps(__spreadValues({}, store), { panels }), []);
24
+ const [panels, updatePanels] = useStore(() => store.panels, {});
25
+ useUpdateEffect(updatePanels, [store, updatePanels]);
26
+ return useMemo(() => __spreadProps(__spreadValues({}, store), { panels }), [store, panels]);
23
27
  }
24
28
  function useTabStore(props = {}) {
25
29
  const [store, update] = useStore(Core.createTabStore, props);
@@ -259,18 +259,33 @@ var useCompositeItem = createHook(
259
259
  const isGrid = !!(item == null ? void 0 : item.rowId);
260
260
  const isVertical = state.orientation !== "horizontal";
261
261
  const isHorizontal = state.orientation !== "vertical";
262
+ const canHomeEnd = () => {
263
+ if (isGrid)
264
+ return true;
265
+ if (isHorizontal)
266
+ return true;
267
+ if (!state.baseElement)
268
+ return true;
269
+ if (!isTextField(state.baseElement))
270
+ return true;
271
+ return false;
272
+ };
262
273
  const keyMap = {
263
274
  ArrowUp: (isGrid || isVertical) && store.up,
264
275
  ArrowRight: (isGrid || isHorizontal) && store.next,
265
276
  ArrowDown: (isGrid || isVertical) && store.down,
266
277
  ArrowLeft: (isGrid || isHorizontal) && store.previous,
267
278
  Home: () => {
279
+ if (!canHomeEnd())
280
+ return;
268
281
  if (!isGrid || event.ctrlKey) {
269
282
  return store == null ? void 0 : store.first();
270
283
  }
271
284
  return store == null ? void 0 : store.previous(-1);
272
285
  },
273
286
  End: () => {
287
+ if (!canHomeEnd())
288
+ return;
274
289
  if (!isGrid || event.ctrlKey) {
275
290
  return store == null ? void 0 : store.last();
276
291
  }
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
  import {
3
3
  useCompositeItem
4
- } from "./P6VCQ6Q3.js";
4
+ } from "./R2WNOXYG.js";
5
5
  import {
6
6
  useToolbarContext
7
7
  } from "./SOK7T35T.js";
@@ -28,9 +28,12 @@ export interface CheckboxCheckOptions<T extends As = "span"> extends Options<T>
28
28
  */
29
29
  store?: CheckboxStore;
30
30
  /**
31
- * Whether the check mark should be shown. This value is automatically
32
- * inferred from the `store` prop or the parent `Checkbox` component. Manually
33
- * setting this prop will override the inferred value.
31
+ * Determines if the check mark should be displayed. This value is
32
+ * automatically derived from the
33
+ * [`store`](https://ariakit.org/reference/checkbox-check#store) prop or the
34
+ * parent [`Checkbox`](https://ariakit.org/reference/checkbox) component.
35
+ *
36
+ * Manually setting this prop will supersede the derived value.
34
37
  */
35
38
  checked?: boolean;
36
39
  }
@@ -75,13 +75,12 @@ var useComboboxDisclosure = createHook(
75
75
  const { baseElement } = store.getState();
76
76
  store.setDisclosureElement(baseElement);
77
77
  });
78
- const label = store.useState(
79
- (state) => state.open ? "Hide popup" : "Show popup"
80
- );
78
+ const open = store.useState("open");
81
79
  props = __spreadProps(__spreadValues({
82
80
  children,
83
81
  tabIndex: -1,
84
- "aria-label": label
82
+ "aria-label": open ? "Hide popup" : "Show popup",
83
+ "aria-expanded": open
85
84
  }, props), {
86
85
  onMouseDown,
87
86
  onClick
@@ -56,6 +56,11 @@ export interface ComboboxItemOptions<T extends As = "div"> extends CompositeItem
56
56
  * [`setValueOnClick`](https://ariakit.org/reference/combobox-item#setvalueonclick)
57
57
  * is set to `true`, this will be the value of the combobox input when the
58
58
  * user clicks on this item.
59
+ * - If
60
+ * [`selectValueOnClick`](https://ariakit.org/reference/combobox-item#selectvalueonclick)
61
+ * is set to `true`, this will be the value of the
62
+ * [`selectedValue`](https://ariakit.org/reference/combobox-provider#selectedvalue)
63
+ * state.
59
64
  * - If the
60
65
  * [`autoComplete`](https://ariakit.org/reference/combobox#autocomplete)
61
66
  * prop on the [`Combobox`](https://ariakit.org/reference/combobox)
@@ -88,7 +93,12 @@ export interface ComboboxItemOptions<T extends As = "div"> extends CompositeItem
88
93
  * [`selectedValue`](https://ariakit.org/reference/combobox-provider#selectedvalue)
89
94
  * state using this item's
90
95
  * [`value`](https://ariakit.org/reference/combobox-item#value) when the item
91
- * is clicked.
96
+ * is clicked. If a callback is provided, it will only be invoked if the item
97
+ * has a value.
98
+ *
99
+ * Live examples:
100
+ * - [Submenu with
101
+ * Combobox](https://ariakit.org/examples/menu-nested-combobox)
92
102
  * @default true
93
103
  */
94
104
  selectValueOnClick?: BooleanOrCallback<MouseEvent<HTMLElement>>;
@@ -102,6 +112,8 @@ export interface ComboboxItemOptions<T extends As = "div"> extends CompositeItem
102
112
  *
103
113
  * Live examples:
104
114
  * - [Menu with Combobox](https://ariakit.org/examples/menu-combobox)
115
+ * - [Submenu with
116
+ * Combobox](https://ariakit.org/examples/menu-nested-combobox)
105
117
  */
106
118
  setValueOnClick?: BooleanOrCallback<MouseEvent<HTMLElement>>;
107
119
  /**
@@ -9,7 +9,7 @@ import {
9
9
  } from "../__chunks/W76OTZCC.js";
10
10
  import {
11
11
  useCompositeItem
12
- } from "../__chunks/P6VCQ6Q3.js";
12
+ } from "../__chunks/R2WNOXYG.js";
13
13
  import "../__chunks/NWCBQ4CV.js";
14
14
  import "../__chunks/UH3I23HL.js";
15
15
  import "../__chunks/6QXBPV75.js";
@@ -35,6 +35,6 @@ export declare const useComboboxPopover: import("../utils/types.js").Hook<Combob
35
35
  * ```
36
36
  */
37
37
  export declare const ComboboxPopover: import("../utils/types.js").Component<ComboboxPopoverOptions<"div">>;
38
- export interface ComboboxPopoverOptions<T extends As = "div"> extends ComboboxListOptions<T>, Omit<PopoverOptions<T>, "store" | "modal"> {
38
+ export interface ComboboxPopoverOptions<T extends As = "div"> extends ComboboxListOptions<T>, Omit<PopoverOptions<T>, "store"> {
39
39
  }
40
40
  export type ComboboxPopoverProps<T extends As = "div"> = Props<ComboboxPopoverOptions<T>>;
@@ -58,13 +58,13 @@ import {
58
58
  } from "../__chunks/4R3V3JGP.js";
59
59
 
60
60
  // src/combobox/combobox-popover.tsx
61
- import { matches } from "@ariakit/core/utils/dom";
61
+ import { getDocument, matches } from "@ariakit/core/utils/dom";
62
62
  import { invariant } from "@ariakit/core/utils/misc";
63
63
  function isController(target, ...ids) {
64
64
  if (!target)
65
65
  return false;
66
66
  if ("id" in target) {
67
- const selector = ids.filter(Boolean).map((id) => `[aria-controls="${id}"]`).join(", ");
67
+ const selector = ids.filter(Boolean).map((id) => `[aria-controls~="${id}"]`).join(", ");
68
68
  if (!selector)
69
69
  return false;
70
70
  return matches(target, selector);
@@ -75,11 +75,13 @@ var useComboboxPopover = createHook(
75
75
  (_a) => {
76
76
  var _b = _a, {
77
77
  store,
78
+ modal,
78
79
  tabIndex,
79
80
  alwaysVisible,
80
81
  hideOnInteractOutside = true
81
82
  } = _b, props = __objRest(_b, [
82
83
  "store",
84
+ "modal",
83
85
  "tabIndex",
84
86
  "alwaysVisible",
85
87
  "hideOnInteractOutside"
@@ -94,20 +96,47 @@ var useComboboxPopover = createHook(
94
96
  props = useComboboxList(__spreadValues({ store, alwaysVisible }, props));
95
97
  props = usePopover(__spreadProps(__spreadValues({
96
98
  store,
99
+ modal,
97
100
  alwaysVisible,
101
+ backdrop: false,
98
102
  autoFocusOnShow: false,
99
103
  autoFocusOnHide: false,
100
104
  finalFocus: baseElement,
101
105
  preserveTabOrderAnchor: null
102
106
  }, props), {
103
- // Combobox popovers can't be modal because the focus may be (and is by
104
- // default) outside of it on the combobox input element.
105
- modal: false,
107
+ // When the combobox popover is modal, we make sure to include the
108
+ // combobox input and all the combobox controls (cancel, disclosure) in
109
+ // the list of persistent elements so they make part of the modal context,
110
+ // allowing users to tab through them.
111
+ getPersistentElements() {
112
+ var _a2;
113
+ const elements = ((_a2 = props.getPersistentElements) == null ? void 0 : _a2.call(props)) || [];
114
+ if (!modal)
115
+ return elements;
116
+ if (!store)
117
+ return elements;
118
+ const { contentElement, baseElement: baseElement2 } = store.getState();
119
+ if (!baseElement2)
120
+ return elements;
121
+ const doc = getDocument(baseElement2);
122
+ const selectors = [];
123
+ if (contentElement == null ? void 0 : contentElement.id) {
124
+ selectors.push(`[aria-controls~="${contentElement.id}"]`);
125
+ }
126
+ if (baseElement2 == null ? void 0 : baseElement2.id) {
127
+ selectors.push(`[aria-controls~="${baseElement2.id}"]`);
128
+ }
129
+ if (!selectors.length)
130
+ return [...elements, baseElement2];
131
+ const selector = selectors.join(",");
132
+ const controlElements = doc.querySelectorAll(selector);
133
+ return [...elements, ...controlElements];
134
+ },
106
135
  // Make sure we don't hide the popover when the user interacts with the
107
136
  // combobox cancel or the combobox disclosure buttons. They will have the
108
137
  // aria-controls attribute pointing to either the combobox input or the
109
138
  // combobox popover elements.
110
- hideOnInteractOutside: (event) => {
139
+ hideOnInteractOutside(event) {
111
140
  var _a2, _b2;
112
141
  const state = store == null ? void 0 : store.getState();
113
142
  const contentId = (_a2 = state == null ? void 0 : state.contentElement) == null ? void 0 : _a2.id;
@@ -3,7 +3,7 @@ import type { BooleanOrCallback, StringWithValue } from "@ariakit/core/utils/typ
3
3
  import type { CompositeOptions } from "../composite/composite.js";
4
4
  import type { PopoverAnchorOptions } from "../popover/popover-anchor.js";
5
5
  import type { As, Props } from "../utils/types.js";
6
- import type { ComboboxStore } from "./combobox-store.js";
6
+ import type { ComboboxStore, ComboboxStoreState } from "./combobox-store.js";
7
7
  /**
8
8
  * Returns props to create a `Combobox` component.
9
9
  * @see https://ariakit.org/components/combobox
@@ -70,6 +70,31 @@ export interface ComboboxOptions<T extends As = "input"> extends CompositeOption
70
70
  * @default false
71
71
  */
72
72
  autoSelect?: boolean;
73
+ /**
74
+ * Function that takes the currently rendered items and returns the id of the
75
+ * item to be auto selected when the
76
+ * [`autoSelect`](https://ariakit.org/reference/combobox#autoselect) prop is
77
+ * `true`.
78
+ *
79
+ * By default, the first enabled item is auto selected. This function is handy
80
+ * if you prefer a different item to be auto selected.
81
+ * @example
82
+ * ```jsx
83
+ * <Combobox
84
+ * autoSelect
85
+ * getAutoSelectId={(items) => {
86
+ * // Auto select the first enabled item with a value
87
+ * const item = items.find((item) => {
88
+ * if (item.disabled) return false;
89
+ * if (!item.value) return false;
90
+ * return true;
91
+ * });
92
+ * return item?.id;
93
+ * }}
94
+ * />
95
+ * ```
96
+ */
97
+ getAutoSelectId?: (renderedItems: ComboboxStoreState["renderedItems"]) => string | null | undefined;
73
98
  /**
74
99
  * Whether the items will be filtered based on
75
100
  * [`value`](https://ariakit.org/reference/combobox-provider#value) and
@@ -7,7 +7,7 @@ import {
7
7
  } from "../__chunks/W76OTZCC.js";
8
8
  import {
9
9
  useComposite
10
- } from "../__chunks/FHDXHZLB.js";
10
+ } from "../__chunks/57KNUQTI.js";
11
11
  import "../__chunks/6QXBPV75.js";
12
12
  import "../__chunks/IB7YUKH5.js";
13
13
  import "../__chunks/4UUKJZ4V.js";
@@ -82,6 +82,7 @@ var useCombobox = createHook(
82
82
  store,
83
83
  focusable = true,
84
84
  autoSelect: autoSelectProp = false,
85
+ getAutoSelectId,
85
86
  showOnChange = true,
86
87
  setValueOnChange = true,
87
88
  showOnMouseDown = true,
@@ -93,6 +94,7 @@ var useCombobox = createHook(
93
94
  "store",
94
95
  "focusable",
95
96
  "autoSelect",
97
+ "getAutoSelectId",
96
98
  "showOnChange",
97
99
  "setValueOnChange",
98
100
  "showOnMouseDown",
@@ -189,6 +191,8 @@ var useCombobox = createHook(
189
191
  storeValue
190
192
  ]);
191
193
  const scrollingElementRef = useRef(null);
194
+ const getAutoSelectIdProp = useEvent(getAutoSelectId);
195
+ const autoSelectIdRef = useRef(null);
192
196
  useEffect(() => {
193
197
  if (!open)
194
198
  return;
@@ -204,10 +208,12 @@ var useCombobox = createHook(
204
208
  const onScroll = () => {
205
209
  if (!store)
206
210
  return;
211
+ if (!canAutoSelectRef.current)
212
+ return;
207
213
  const { activeId } = store.getState();
208
214
  if (activeId === null)
209
215
  return;
210
- if (activeId === store.first())
216
+ if (activeId === autoSelectIdRef.current)
211
217
  return;
212
218
  canAutoSelectRef.current = false;
213
219
  };
@@ -233,7 +239,7 @@ var useCombobox = createHook(
233
239
  }, [open]);
234
240
  const resetValueOnSelect = store.useState("resetValueOnSelect");
235
241
  useUpdateEffect(() => {
236
- var _a2, _b2;
242
+ var _a2;
237
243
  if (!store)
238
244
  return;
239
245
  if (!autoSelect && !resetValueOnSelect)
@@ -249,9 +255,12 @@ var useCombobox = createHook(
249
255
  return () => observer.disconnect();
250
256
  }
251
257
  if (autoSelect) {
252
- store.move((_a2 = store.first()) != null ? _a2 : null);
258
+ const userAutoSelectId = getAutoSelectIdProp(items);
259
+ const autoSelectId = userAutoSelectId !== void 0 ? userAutoSelectId : store.first();
260
+ autoSelectIdRef.current = autoSelectId;
261
+ store.move(autoSelectId != null ? autoSelectId : null);
253
262
  } else {
254
- const element = (_b2 = store.item(activeId)) == null ? void 0 : _b2.element;
263
+ const element = (_a2 = store.item(activeId)) == null ? void 0 : _a2.element;
255
264
  if (element && "scrollIntoView" in element) {
256
265
  element.scrollIntoView({ block: "nearest", inline: "nearest" });
257
266
  }
@@ -263,6 +272,7 @@ var useCombobox = createHook(
263
272
  storeValue,
264
273
  autoSelect,
265
274
  resetValueOnSelect,
275
+ getAutoSelectIdProp,
266
276
  items
267
277
  ]);
268
278
  useEffect(() => {
@@ -395,6 +405,7 @@ var useCombobox = createHook(
395
405
  });
396
406
  const id = useId(props.id);
397
407
  const ariaAutoComplete = isAriaAutoCompleteValue(autoComplete) ? autoComplete : void 0;
408
+ const isActiveItem = store.useState((state) => state.activeId === null);
398
409
  props = __spreadProps(__spreadValues({
399
410
  id,
400
411
  role: "combobox",
@@ -402,6 +413,7 @@ var useCombobox = createHook(
402
413
  "aria-haspopup": getPopupRole(contentElement, "listbox"),
403
414
  "aria-expanded": open,
404
415
  "aria-controls": contentElement == null ? void 0 : contentElement.id,
416
+ "data-active-item": isActiveItem || void 0,
405
417
  value
406
418
  }, props), {
407
419
  ref: useMergeRefs(ref, props.ref),
@@ -43,7 +43,12 @@ export interface CompositeHoverOptions<T extends As = "div"> extends Options<T>
43
43
  */
44
44
  store?: CompositeStore;
45
45
  /**
46
- * Determines if the composite item should be focused on hover.
46
+ * Determines if the composite item should be _focused_ when hovered over.
47
+ *
48
+ * Note that the actual DOM focus will stay on the composite element. This
49
+ * item will get the
50
+ * [`data-active-item`](https://ariakit.org/guide/styling#data-active-item)
51
+ * attribute so it can be styled as if it's focused.
47
52
  *
48
53
  * Live examples:
49
54
  * - [Multi-selectable
@@ -53,6 +58,8 @@ export interface CompositeHoverOptions<T extends As = "div"> extends Options<T>
53
58
  * - [Textarea with inline
54
59
  * Combobox](https://ariakit.org/examples/combobox-textarea)
55
60
  * - [Navigation Menubar](https://ariakit.org/examples/menubar-navigation)
61
+ * - [Submenu with
62
+ * Combobox](https://ariakit.org/examples/menu-nested-combobox)
56
63
  * @default true
57
64
  */
58
65
  focusOnHover?: BooleanOrCallback<ReactMouseEvent<HTMLElement>>;
@@ -66,6 +73,8 @@ export interface CompositeHoverOptions<T extends As = "div"> extends Options<T>
66
73
  * - [Navigation Menubar](https://ariakit.org/examples/menubar-navigation)
67
74
  * - [Combobox with integrated
68
75
  * filter](https://ariakit.org/examples/combobox-filtering-integrated)
76
+ * - [Submenu with
77
+ * Combobox](https://ariakit.org/examples/menu-nested-combobox)
69
78
  */
70
79
  blurOnHoverEnd?: BooleanOrCallback<ReactMouseEvent<HTMLElement>>;
71
80
  }