@tamagui/create-menu 2.0.0-rc.4 → 2.0.0-rc.40

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 (149) hide show
  1. package/dist/cjs/MenuPredefined.cjs +159 -157
  2. package/dist/cjs/MenuPredefined.native.js +159 -157
  3. package/dist/cjs/MenuPredefined.native.js.map +1 -1
  4. package/dist/cjs/createBaseMenu.cjs +1144 -933
  5. package/dist/cjs/createBaseMenu.native.js +1266 -1100
  6. package/dist/cjs/createBaseMenu.native.js.map +1 -1
  7. package/dist/cjs/createNativeMenu/createNativeMenu.cjs +282 -159
  8. package/dist/cjs/createNativeMenu/createNativeMenu.native.js +390 -268
  9. package/dist/cjs/createNativeMenu/createNativeMenu.native.js.map +1 -1
  10. package/dist/cjs/createNativeMenu/createNativeMenuTypes.cjs +7 -5
  11. package/dist/cjs/createNativeMenu/createNativeMenuTypes.native.js +7 -5
  12. package/dist/cjs/createNativeMenu/createNativeMenuTypes.native.js.map +1 -1
  13. package/dist/cjs/createNativeMenu/utils.cjs +85 -42
  14. package/dist/cjs/createNativeMenu/utils.native.js +83 -58
  15. package/dist/cjs/createNativeMenu/utils.native.js.map +1 -1
  16. package/dist/cjs/createNativeMenu/withNativeMenu.cjs +27 -17
  17. package/dist/cjs/createNativeMenu/withNativeMenu.native.js +22 -14
  18. package/dist/cjs/createNativeMenu/withNativeMenu.native.js.map +1 -1
  19. package/dist/cjs/index.cjs +15 -12
  20. package/dist/cjs/index.native.js +15 -12
  21. package/dist/cjs/index.native.js.map +1 -1
  22. package/dist/esm/MenuPredefined.mjs +144 -144
  23. package/dist/esm/MenuPredefined.mjs.map +1 -1
  24. package/dist/esm/MenuPredefined.native.js +144 -144
  25. package/dist/esm/MenuPredefined.native.js.map +1 -1
  26. package/dist/esm/createBaseMenu.mjs +1104 -895
  27. package/dist/esm/createBaseMenu.mjs.map +1 -1
  28. package/dist/esm/createBaseMenu.native.js +1226 -1062
  29. package/dist/esm/createBaseMenu.native.js.map +1 -1
  30. package/dist/esm/createNativeMenu/createNativeMenu.mjs +255 -134
  31. package/dist/esm/createNativeMenu/createNativeMenu.mjs.map +1 -1
  32. package/dist/esm/createNativeMenu/createNativeMenu.native.js +336 -216
  33. package/dist/esm/createNativeMenu/createNativeMenu.native.js.map +1 -1
  34. package/dist/esm/createNativeMenu/utils.mjs +58 -17
  35. package/dist/esm/createNativeMenu/utils.mjs.map +1 -1
  36. package/dist/esm/createNativeMenu/utils.native.js +57 -34
  37. package/dist/esm/createNativeMenu/utils.native.js.map +1 -1
  38. package/dist/esm/createNativeMenu/withNativeMenu.mjs +13 -5
  39. package/dist/esm/createNativeMenu/withNativeMenu.mjs.map +1 -1
  40. package/dist/esm/createNativeMenu/withNativeMenu.native.js +8 -2
  41. package/dist/esm/createNativeMenu/withNativeMenu.native.js.map +1 -1
  42. package/dist/esm/index.js +5 -6
  43. package/dist/esm/index.js.map +1 -6
  44. package/dist/esm/index.mjs +2 -1
  45. package/dist/esm/index.mjs.map +1 -1
  46. package/dist/esm/index.native.js +2 -1
  47. package/dist/esm/index.native.js.map +1 -1
  48. package/dist/jsx/MenuPredefined.mjs +144 -144
  49. package/dist/jsx/MenuPredefined.mjs.map +1 -1
  50. package/dist/jsx/MenuPredefined.native.js +159 -157
  51. package/dist/jsx/MenuPredefined.native.js.map +1 -1
  52. package/dist/jsx/createBaseMenu.mjs +1104 -895
  53. package/dist/jsx/createBaseMenu.mjs.map +1 -1
  54. package/dist/jsx/createBaseMenu.native.js +1266 -1100
  55. package/dist/jsx/createBaseMenu.native.js.map +1 -1
  56. package/dist/jsx/createNativeMenu/createNativeMenu.mjs +255 -134
  57. package/dist/jsx/createNativeMenu/createNativeMenu.mjs.map +1 -1
  58. package/dist/jsx/createNativeMenu/createNativeMenu.native.js +390 -268
  59. package/dist/jsx/createNativeMenu/createNativeMenu.native.js.map +1 -1
  60. package/dist/jsx/createNativeMenu/createNativeMenuTypes.native.js +7 -5
  61. package/dist/jsx/createNativeMenu/utils.mjs +58 -17
  62. package/dist/jsx/createNativeMenu/utils.mjs.map +1 -1
  63. package/dist/jsx/createNativeMenu/utils.native.js +83 -58
  64. package/dist/jsx/createNativeMenu/utils.native.js.map +1 -1
  65. package/dist/jsx/createNativeMenu/withNativeMenu.mjs +13 -5
  66. package/dist/jsx/createNativeMenu/withNativeMenu.mjs.map +1 -1
  67. package/dist/jsx/createNativeMenu/withNativeMenu.native.js +22 -14
  68. package/dist/jsx/createNativeMenu/withNativeMenu.native.js.map +1 -1
  69. package/dist/jsx/index.js +5 -6
  70. package/dist/jsx/index.js.map +1 -6
  71. package/dist/jsx/index.mjs +2 -1
  72. package/dist/jsx/index.mjs.map +1 -1
  73. package/dist/jsx/index.native.js +15 -12
  74. package/dist/jsx/index.native.js.map +1 -1
  75. package/package.json +25 -27
  76. package/src/MenuPredefined.tsx +1 -1
  77. package/src/createBaseMenu.tsx +359 -271
  78. package/src/createNativeMenu/createNativeMenu.tsx +383 -222
  79. package/src/createNativeMenu/createNativeMenuTypes.ts +20 -20
  80. package/src/createNativeMenu/withNativeMenu.tsx +5 -3
  81. package/src/index.tsx +3 -5
  82. package/types/createBaseMenu.d.ts +121 -35
  83. package/types/createBaseMenu.d.ts.map +1 -1
  84. package/types/createNativeMenu/createNativeMenu.d.ts +21 -21
  85. package/types/createNativeMenu/createNativeMenu.d.ts.map +1 -1
  86. package/types/createNativeMenu/createNativeMenuTypes.d.ts +20 -20
  87. package/types/createNativeMenu/createNativeMenuTypes.d.ts.map +1 -1
  88. package/types/createNativeMenu/withNativeMenu.d.ts +3 -3
  89. package/types/createNativeMenu/withNativeMenu.d.ts.map +1 -1
  90. package/types/index.d.ts +3 -2
  91. package/types/index.d.ts.map +1 -1
  92. package/dist/cjs/MenuPredefined.js +0 -168
  93. package/dist/cjs/MenuPredefined.js.map +0 -6
  94. package/dist/cjs/createBaseMenu.js +0 -832
  95. package/dist/cjs/createBaseMenu.js.map +0 -6
  96. package/dist/cjs/createNativeMenu/createNativeMenu.js +0 -177
  97. package/dist/cjs/createNativeMenu/createNativeMenu.js.map +0 -6
  98. package/dist/cjs/createNativeMenu/createNativeMenuTypes.js +0 -14
  99. package/dist/cjs/createNativeMenu/createNativeMenuTypes.js.map +0 -6
  100. package/dist/cjs/createNativeMenu/index.cjs +0 -19
  101. package/dist/cjs/createNativeMenu/index.js +0 -16
  102. package/dist/cjs/createNativeMenu/index.js.map +0 -6
  103. package/dist/cjs/createNativeMenu/index.native.js +0 -22
  104. package/dist/cjs/createNativeMenu/index.native.js.map +0 -1
  105. package/dist/cjs/createNativeMenu/utils.js +0 -66
  106. package/dist/cjs/createNativeMenu/utils.js.map +0 -6
  107. package/dist/cjs/createNativeMenu/withNativeMenu.js +0 -30
  108. package/dist/cjs/createNativeMenu/withNativeMenu.js.map +0 -6
  109. package/dist/cjs/index.js +0 -23
  110. package/dist/cjs/index.js.map +0 -6
  111. package/dist/esm/MenuPredefined.js +0 -154
  112. package/dist/esm/MenuPredefined.js.map +0 -6
  113. package/dist/esm/createBaseMenu.js +0 -838
  114. package/dist/esm/createBaseMenu.js.map +0 -6
  115. package/dist/esm/createNativeMenu/createNativeMenu.js +0 -156
  116. package/dist/esm/createNativeMenu/createNativeMenu.js.map +0 -6
  117. package/dist/esm/createNativeMenu/createNativeMenuTypes.js +0 -1
  118. package/dist/esm/createNativeMenu/createNativeMenuTypes.js.map +0 -6
  119. package/dist/esm/createNativeMenu/index.js +0 -3
  120. package/dist/esm/createNativeMenu/index.js.map +0 -6
  121. package/dist/esm/createNativeMenu/index.mjs +0 -3
  122. package/dist/esm/createNativeMenu/index.mjs.map +0 -1
  123. package/dist/esm/createNativeMenu/index.native.js +0 -3
  124. package/dist/esm/createNativeMenu/index.native.js.map +0 -1
  125. package/dist/esm/createNativeMenu/utils.js +0 -47
  126. package/dist/esm/createNativeMenu/utils.js.map +0 -6
  127. package/dist/esm/createNativeMenu/withNativeMenu.js +0 -15
  128. package/dist/esm/createNativeMenu/withNativeMenu.js.map +0 -6
  129. package/dist/jsx/MenuPredefined.js +0 -154
  130. package/dist/jsx/MenuPredefined.js.map +0 -6
  131. package/dist/jsx/createBaseMenu.js +0 -838
  132. package/dist/jsx/createBaseMenu.js.map +0 -6
  133. package/dist/jsx/createNativeMenu/createNativeMenu.js +0 -156
  134. package/dist/jsx/createNativeMenu/createNativeMenu.js.map +0 -6
  135. package/dist/jsx/createNativeMenu/createNativeMenuTypes.js +0 -1
  136. package/dist/jsx/createNativeMenu/createNativeMenuTypes.js.map +0 -6
  137. package/dist/jsx/createNativeMenu/index.js +0 -3
  138. package/dist/jsx/createNativeMenu/index.js.map +0 -6
  139. package/dist/jsx/createNativeMenu/index.mjs +0 -3
  140. package/dist/jsx/createNativeMenu/index.mjs.map +0 -1
  141. package/dist/jsx/createNativeMenu/index.native.js +0 -22
  142. package/dist/jsx/createNativeMenu/index.native.js.map +0 -1
  143. package/dist/jsx/createNativeMenu/utils.js +0 -47
  144. package/dist/jsx/createNativeMenu/utils.js.map +0 -6
  145. package/dist/jsx/createNativeMenu/withNativeMenu.js +0 -15
  146. package/dist/jsx/createNativeMenu/withNativeMenu.js.map +0 -6
  147. package/src/createNativeMenu/index.tsx +0 -7
  148. package/types/createNativeMenu/index.d.ts +0 -4
  149. package/types/createNativeMenu/index.d.ts.map +0 -1
@@ -2,81 +2,83 @@ var __create = Object.create;
2
2
  var __defProp = Object.defineProperty;
3
3
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
4
  var __getOwnPropNames = Object.getOwnPropertyNames;
5
- var __getProtoOf = Object.getPrototypeOf,
6
- __hasOwnProp = Object.prototype.hasOwnProperty;
5
+ var __getProtoOf = Object.getPrototypeOf;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
7
  var __export = (target, all) => {
8
- for (var name in all) __defProp(target, name, {
9
- get: all[name],
10
- enumerable: !0
11
- });
12
- },
13
- __copyProps = (to, from, except, desc) => {
14
- if (from && typeof from == "object" || typeof from == "function") for (let key of __getOwnPropNames(from)) !__hasOwnProp.call(to, key) && key !== except && __defProp(to, key, {
8
+ for (var name in all) __defProp(target, name, {
9
+ get: all[name],
10
+ enumerable: true
11
+ });
12
+ };
13
+ var __copyProps = (to, from, except, desc) => {
14
+ if (from && typeof from === "object" || typeof from === "function") {
15
+ for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
15
16
  get: () => from[key],
16
17
  enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
17
18
  });
18
- return to;
19
- };
19
+ }
20
+ return to;
21
+ };
20
22
  var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
- // If the importer is in node compatibility mode or this is not an ESM
22
- // file that has been converted to a CommonJS file using a Babel-
23
- // compatible transform (i.e. "__esModule" has not been set), then set
24
- // "default" to the CommonJS "module.exports" for node compatibility.
25
- isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
26
- value: mod,
27
- enumerable: !0
28
- }) : target, mod)),
29
- __toCommonJS = mod => __copyProps(__defProp({}, "__esModule", {
30
- value: !0
31
- }), mod);
23
+ // If the importer is in node compatibility mode or this is not an ESM
24
+ // file that has been converted to a CommonJS file using a Babel-
25
+ // compatible transform (i.e. "__esModule" has not been set), then set
26
+ // "default" to the CommonJS "module.exports" for node compatibility.
27
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
28
+ value: mod,
29
+ enumerable: true
30
+ }) : target, mod));
31
+ var __toCommonJS = mod => __copyProps(__defProp({}, "__esModule", {
32
+ value: true
33
+ }), mod);
32
34
  var createBaseMenu_exports = {};
33
35
  __export(createBaseMenu_exports, {
34
36
  createBaseMenu: () => createBaseMenu
35
37
  });
36
38
  module.exports = __toCommonJS(createBaseMenu_exports);
37
- var import_animate = require("@tamagui/animate"),
38
- import_animate_presence = require("@tamagui/animate-presence"),
39
- import_collection = require("@tamagui/collection"),
40
- import_dismissable = require("@tamagui/dismissable"),
41
- import_focus_guard = require("@tamagui/focus-guard"),
42
- import_focus_scope = require("@tamagui/focus-scope"),
43
- PopperPrimitive = __toESM(require("@tamagui/popper"), 1),
44
- import_portal = require("@tamagui/portal"),
45
- import_remove_scroll = require("@tamagui/remove-scroll"),
46
- import_roving_focus = require("@tamagui/roving-focus"),
47
- import_use_callback_ref = require("@tamagui/use-callback-ref"),
48
- import_use_direction = require("@tamagui/use-direction"),
49
- import_web = require("@tamagui/web"),
50
- React = __toESM(require("react"), 1),
51
- import_react = require("react"),
52
- import_MenuPredefined = require("./MenuPredefined.cjs"),
53
- import_jsx_runtime = require("react/jsx-runtime");
39
+ var import_animate = require("@tamagui/animate");
40
+ var import_animate_presence = require("@tamagui/animate-presence");
41
+ var import_collection = require("@tamagui/collection");
42
+ var import_dismissable = require("@tamagui/dismissable");
43
+ var import_focus_guard = require("@tamagui/focus-guard");
44
+ var import_focus_scope = require("@tamagui/focus-scope");
45
+ var PopperPrimitive = __toESM(require("@tamagui/popper"), 1);
46
+ var import_portal = require("@tamagui/portal");
47
+ var import_remove_scroll = require("@tamagui/remove-scroll");
48
+ var import_roving_focus = require("@tamagui/roving-focus");
49
+ var import_use_callback_ref = require("@tamagui/use-callback-ref");
50
+ var import_use_direction = require("@tamagui/use-direction");
51
+ var import_web = require("@tamagui/web");
52
+ var React = __toESM(require("react"), 1);
53
+ var import_react = require("react");
54
+ var import_MenuPredefined = require("./MenuPredefined.cjs");
55
+ var import_jsx_runtime = require("react/jsx-runtime");
54
56
  function whenMouse(handler) {
55
57
  return event => event.pointerType === "mouse" ? handler(event) : void 0;
56
58
  }
57
- const SELECTION_KEYS = ["Enter", " "],
58
- FIRST_KEYS = ["ArrowDown", "PageUp", "Home"],
59
- LAST_KEYS = ["ArrowUp", "PageDown", "End"],
60
- FIRST_LAST_KEYS = [...FIRST_KEYS, ...LAST_KEYS],
61
- SUB_OPEN_KEYS = {
62
- ltr: [...SELECTION_KEYS, "ArrowRight"],
63
- rtl: [...SELECTION_KEYS, "ArrowLeft"]
64
- },
65
- SUB_CLOSE_KEYS = {
66
- ltr: ["ArrowLeft"],
67
- rtl: ["ArrowRight"]
68
- },
69
- MENU_NAME = "Menu",
70
- [Collection, useCollection] = (0, import_collection.createCollection)(MENU_NAME),
71
- {
72
- Provider: MenuProvider,
73
- useStyledContext: useMenuContext
74
- } = (0, import_web.createStyledContext)(),
75
- {
76
- Provider: MenuRootProvider,
77
- useStyledContext: useMenuRootContext
78
- } = (0, import_web.createStyledContext)(),
79
- MENU_CONTEXT = "MenuContext";
59
+ const SELECTION_KEYS = ["Enter", " "];
60
+ const FIRST_KEYS = ["ArrowDown", "PageUp", "Home"];
61
+ const LAST_KEYS = ["ArrowUp", "PageDown", "End"];
62
+ const FIRST_LAST_KEYS = [...FIRST_KEYS, ...LAST_KEYS];
63
+ const SUB_OPEN_KEYS = {
64
+ ltr: [...SELECTION_KEYS, "ArrowRight"],
65
+ rtl: [...SELECTION_KEYS, "ArrowLeft"]
66
+ };
67
+ const SUB_CLOSE_KEYS = {
68
+ ltr: ["ArrowLeft"],
69
+ rtl: ["ArrowRight"]
70
+ };
71
+ const MENU_NAME = "Menu";
72
+ const [Collection, useCollection] = (0, import_collection.createCollection)(MENU_NAME);
73
+ const {
74
+ Provider: MenuProvider,
75
+ useStyledContext: useMenuContext
76
+ } = (0, import_web.createStyledContext)();
77
+ const {
78
+ Provider: MenuRootProvider,
79
+ useStyledContext: useMenuRootContext
80
+ } = (0, import_web.createStyledContext)();
81
+ const MENU_CONTEXT = "MenuContext";
80
82
  function createBaseMenu({
81
83
  Item: _Item = import_MenuPredefined.MenuPredefined.MenuItem,
82
84
  Title: _Title = import_MenuPredefined.MenuPredefined.Title,
@@ -89,950 +91,1151 @@ function createBaseMenu({
89
91
  Label: _Label = import_MenuPredefined.MenuPredefined.MenuLabel
90
92
  }) {
91
93
  const MenuComp = props => {
92
- const {
93
- scope = MENU_CONTEXT,
94
- open = !1,
95
- children,
96
- dir,
97
- onOpenChange,
98
- modal = !0,
99
- ...rest
100
- } = props,
101
- [content, setContent] = React.useState(null),
102
- isUsingKeyboardRef = React.useRef(!1),
103
- handleOpenChange = (0, import_use_callback_ref.useCallbackRef)(onOpenChange),
104
- direction = (0, import_use_direction.useDirection)(dir);
105
- return import_web.isWeb && React.useEffect(() => {
94
+ const direction = (0, import_use_direction.useDirection)(props.dir);
95
+ const defaultPlacement = direction === "rtl" ? "bottom-end" : "bottom-start";
96
+ const {
97
+ scope = MENU_CONTEXT,
98
+ open = false,
99
+ children,
100
+ dir,
101
+ onOpenChange,
102
+ modal = true,
103
+ allowFlip = {
104
+ padding: 10
105
+ },
106
+ stayInFrame = {
107
+ padding: 10
108
+ },
109
+ placement = defaultPlacement,
110
+ resize = true,
111
+ offset = 10,
112
+ ...rest
113
+ } = props;
114
+ const [content, setContent] = React.useState(null);
115
+ const isUsingKeyboardRef = React.useRef(false);
116
+ const handleOpenChange = (0, import_use_callback_ref.useCallbackRef)(onOpenChange);
117
+ if (import_web.isWeb) {
118
+ React.useEffect(() => {
106
119
  const handleKeyDown = () => {
107
- isUsingKeyboardRef.current = !0, document.addEventListener("pointerdown", handlePointer, {
108
- capture: !0,
109
- once: !0
110
- }), document.addEventListener("pointermove", handlePointer, {
111
- capture: !0,
112
- once: !0
113
- });
114
- },
115
- handlePointer = () => isUsingKeyboardRef.current = !1;
116
- return document.addEventListener("keydown", handleKeyDown, {
117
- capture: !0
118
- }), () => {
120
+ isUsingKeyboardRef.current = true;
121
+ document.addEventListener("pointerdown", handlePointer, {
122
+ capture: true,
123
+ once: true
124
+ });
125
+ document.addEventListener("pointermove", handlePointer, {
126
+ capture: true,
127
+ once: true
128
+ });
129
+ };
130
+ const handlePointer = () => isUsingKeyboardRef.current = false;
131
+ document.addEventListener("keydown", handleKeyDown, {
132
+ capture: true
133
+ });
134
+ return () => {
119
135
  document.removeEventListener("keydown", handleKeyDown, {
120
- capture: !0
121
- }), document.removeEventListener("pointerdown", handlePointer, {
122
- capture: !0
123
- }), document.removeEventListener("pointermove", handlePointer, {
124
- capture: !0
136
+ capture: true
137
+ });
138
+ document.removeEventListener("pointerdown", handlePointer, {
139
+ capture: true
140
+ });
141
+ document.removeEventListener("pointermove", handlePointer, {
142
+ capture: true
125
143
  });
126
144
  };
127
- }, []), /* @__PURE__ */(0, import_jsx_runtime.jsx)(PopperPrimitive.Popper, {
145
+ }, []);
146
+ }
147
+ return /* @__PURE__ */(0, import_jsx_runtime.jsx)(PopperPrimitive.Popper, {
148
+ scope,
149
+ open,
150
+ placement,
151
+ allowFlip,
152
+ stayInFrame,
153
+ resize,
154
+ offset,
155
+ ...rest,
156
+ children: /* @__PURE__ */(0, import_jsx_runtime.jsx)(MenuProvider, {
128
157
  scope,
129
- ...rest,
130
- children: /* @__PURE__ */(0, import_jsx_runtime.jsx)(MenuProvider, {
158
+ open,
159
+ onOpenChange: handleOpenChange,
160
+ content,
161
+ onContentChange: setContent,
162
+ children: /* @__PURE__ */(0, import_jsx_runtime.jsx)(MenuRootProvider, {
131
163
  scope,
132
164
  open,
133
- onOpenChange: handleOpenChange,
134
- content,
135
- onContentChange: setContent,
136
- children: /* @__PURE__ */(0, import_jsx_runtime.jsx)(MenuRootProvider, {
165
+ onClose: React.useCallback(() => handleOpenChange(false), [handleOpenChange]),
166
+ isUsingKeyboardRef,
167
+ dir: direction,
168
+ modal,
169
+ children: /* @__PURE__ */(0, import_jsx_runtime.jsx)(MenuSubProvider, {
137
170
  scope,
138
- open,
139
- onClose: React.useCallback(() => handleOpenChange(!1), [handleOpenChange]),
140
- isUsingKeyboardRef,
141
- dir: direction,
142
- modal,
143
- children: /* @__PURE__ */(0, import_jsx_runtime.jsx)(MenuSubProvider, {
144
- scope,
145
- children
146
- })
171
+ children
147
172
  })
148
173
  })
149
- });
150
- },
151
- RepropagateMenuAndMenuRootProvider = props => {
152
- const {
153
- scope = MENU_CONTEXT,
154
- menuContext,
155
- rootContext,
156
- popperContext,
157
- menuSubContext,
158
- children
159
- } = props;
160
- return /* @__PURE__ */(0, import_jsx_runtime.jsx)(PopperPrimitive.PopperProvider, {
161
- ...popperContext,
174
+ })
175
+ });
176
+ };
177
+ const RepropagateMenuAndMenuRootProvider = props => {
178
+ const {
179
+ scope = MENU_CONTEXT,
180
+ menuContext,
181
+ rootContext,
182
+ popperContext,
183
+ menuSubContext,
184
+ children
185
+ } = props;
186
+ return /* @__PURE__ */(0, import_jsx_runtime.jsx)(PopperPrimitive.PopperProvider, {
187
+ ...popperContext,
188
+ scope,
189
+ children: /* @__PURE__ */(0, import_jsx_runtime.jsx)(MenuProvider, {
162
190
  scope,
163
- children: /* @__PURE__ */(0, import_jsx_runtime.jsx)(MenuProvider, {
191
+ ...menuContext,
192
+ children: /* @__PURE__ */(0, import_jsx_runtime.jsx)(MenuRootProvider, {
164
193
  scope,
165
- ...menuContext,
166
- children: /* @__PURE__ */(0, import_jsx_runtime.jsx)(MenuRootProvider, {
194
+ ...rootContext,
195
+ children: menuSubContext ? /* @__PURE__ */(0, import_jsx_runtime.jsx)(MenuSubProvider, {
167
196
  scope,
168
- ...rootContext,
169
- children: menuSubContext ? /* @__PURE__ */(0, import_jsx_runtime.jsx)(MenuSubProvider, {
170
- scope,
171
- ...menuSubContext,
172
- children
173
- }) : children
174
- })
197
+ ...menuSubContext,
198
+ children
199
+ }) : children
175
200
  })
176
- });
177
- };
201
+ })
202
+ });
203
+ };
178
204
  MenuComp.displayName = MENU_NAME;
179
- const ANCHOR_NAME = "MenuAnchor",
180
- MenuAnchor = props => /* @__PURE__ */(0, import_jsx_runtime.jsx)(PopperPrimitive.PopperAnchor, {
205
+ const ANCHOR_NAME = "MenuAnchor";
206
+ const MenuAnchor = props => {
207
+ return /* @__PURE__ */(0, import_jsx_runtime.jsx)(PopperPrimitive.PopperAnchor, {
181
208
  scope: MENU_CONTEXT,
182
209
  ...props
183
210
  });
211
+ };
184
212
  MenuAnchor.displayName = ANCHOR_NAME;
185
- const PORTAL_NAME = "MenuPortal",
186
- {
187
- Provider: PortalProvider,
188
- useStyledContext: usePortalContext
189
- } = (0, import_web.createStyledContext)(void 0, "Portal"),
190
- MenuPortal = props => {
191
- const {
192
- scope = MENU_CONTEXT,
193
- forceMount,
194
- zIndex,
195
- children
196
- } = props,
197
- menuContext = useMenuContext(scope),
198
- rootContext = useMenuRootContext(scope),
199
- popperContext = PopperPrimitive.usePopperContext(scope),
200
- menuSubContext = useMenuSubContext(scope),
201
- themeName = (0, import_web.useThemeName)(),
202
- themedChildren = /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_web.Theme, {
203
- forceClassName: !0,
204
- name: themeName,
205
- children
206
- }),
207
- content = (0, import_portal.needsPortalRepropagation)() ? /* @__PURE__ */(0, import_jsx_runtime.jsx)(RepropagateMenuAndMenuRootProvider, {
208
- menuContext,
209
- rootContext,
210
- popperContext,
211
- menuSubContext,
212
- scope,
213
- children: themedChildren
214
- }) : themedChildren,
215
- isPresent = forceMount || rootContext.open && menuContext.open;
216
- return /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_animate.Animate, {
217
- type: "presence",
218
- present: isPresent,
219
- children: /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_portal.Portal, {
220
- children: /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_jsx_runtime.Fragment, {
221
- children: /* @__PURE__ */(0, import_jsx_runtime.jsx)(PortalProvider, {
222
- scope,
223
- forceMount,
224
- children: /* @__PURE__ */(0, import_jsx_runtime.jsxs)(import_web.View, {
225
- zIndex: zIndex || 100,
213
+ const PORTAL_NAME = "MenuPortal";
214
+ const {
215
+ Provider: PortalProvider,
216
+ useStyledContext: usePortalContext
217
+ } = (0, import_web.createStyledContext)(void 0, "Portal");
218
+ const MenuPortal = props => {
219
+ const {
220
+ scope = MENU_CONTEXT,
221
+ forceMount,
222
+ zIndex,
223
+ children
224
+ } = props;
225
+ const menuContext = useMenuContext(scope);
226
+ const rootContext = useMenuRootContext(scope);
227
+ const popperContext = PopperPrimitive.usePopperContext(scope);
228
+ const menuSubContext = useMenuSubContext(scope);
229
+ const themeName = (0, import_web.useThemeName)();
230
+ const themedChildren = /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_web.Theme, {
231
+ forceClassName: true,
232
+ name: themeName,
233
+ children
234
+ });
235
+ const content = (0, import_portal.needsPortalRepropagation)() ? /* @__PURE__ */(0, import_jsx_runtime.jsx)(RepropagateMenuAndMenuRootProvider, {
236
+ menuContext,
237
+ rootContext,
238
+ popperContext,
239
+ menuSubContext,
240
+ scope,
241
+ children: themedChildren
242
+ }) : themedChildren;
243
+ const isPresent = forceMount || rootContext.open && menuContext.open;
244
+ return /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_animate.Animate, {
245
+ type: "presence",
246
+ present: isPresent,
247
+ children: /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_portal.Portal, {
248
+ stackZIndex: true,
249
+ children: /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_jsx_runtime.Fragment, {
250
+ children: /* @__PURE__ */(0, import_jsx_runtime.jsx)(PortalProvider, {
251
+ scope,
252
+ forceMount,
253
+ children: /* @__PURE__ */(0, import_jsx_runtime.jsxs)(import_web.View, {
254
+ zIndex: zIndex || 100,
255
+ inset: 0,
256
+ position: "absolute",
257
+ children: [!!menuContext.open && !import_web.isWeb && /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_web.View, {
226
258
  inset: 0,
227
259
  position: "absolute",
228
- children: [!!menuContext.open && !import_web.isWeb && /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_web.View, {
229
- inset: 0,
230
- position: "absolute",
231
- onPress: () => menuContext.onOpenChange(!menuContext.open)
232
- }), content]
233
- })
260
+ onPress: () => menuContext.onOpenChange(!menuContext.open)
261
+ }), content]
234
262
  })
235
263
  })
236
264
  })
237
- });
238
- };
265
+ })
266
+ });
267
+ };
239
268
  MenuPortal.displayName = PORTAL_NAME;
240
- const CONTENT_NAME = "MenuContent",
241
- {
242
- Provider: MenuContentProvider,
243
- useStyledContext: useMenuContentContext
244
- } = (0, import_web.createStyledContext)(),
245
- MenuContent = React.forwardRef((props, forwardedRef) => {
246
- const scope = props.scope || MENU_CONTEXT,
247
- portalContext = usePortalContext(scope),
248
- {
249
- forceMount = portalContext.forceMount,
250
- ...contentProps
251
- } = props,
252
- rootContext = useMenuRootContext(scope);
253
- return /* @__PURE__ */(0, import_jsx_runtime.jsx)(Collection.Provider, {
269
+ const CONTENT_NAME = "MenuContent";
270
+ const {
271
+ Provider: MenuContentProvider,
272
+ useStyledContext: useMenuContentContext
273
+ } = (0, import_web.createStyledContext)();
274
+ const MenuContentFrame = (0, import_web.styled)(PopperPrimitive.PopperContentFrame, {
275
+ name: CONTENT_NAME
276
+ });
277
+ const MenuContent = MenuContentFrame.styleable((props, forwardedRef) => {
278
+ const scope = props.scope || MENU_CONTEXT;
279
+ const portalContext = usePortalContext(scope);
280
+ const {
281
+ forceMount = portalContext.forceMount,
282
+ ...contentProps
283
+ } = props;
284
+ const rootContext = useMenuRootContext(scope);
285
+ return /* @__PURE__ */(0, import_jsx_runtime.jsx)(Collection.Provider, {
286
+ scope,
287
+ children: /* @__PURE__ */(0, import_jsx_runtime.jsx)(Collection.Slot, {
254
288
  scope,
255
- children: /* @__PURE__ */(0, import_jsx_runtime.jsx)(Collection.Slot, {
256
- scope,
257
- children: rootContext.modal ? /* @__PURE__ */(0, import_jsx_runtime.jsx)(MenuRootContentModal, {
258
- ...contentProps,
259
- ref: forwardedRef
260
- }) : /* @__PURE__ */(0, import_jsx_runtime.jsx)(MenuRootContentNonModal, {
261
- ...contentProps,
262
- ref: forwardedRef
263
- })
289
+ children: rootContext.modal ? /* @__PURE__ */(0, import_jsx_runtime.jsx)(MenuRootContentModal, {
290
+ ...contentProps,
291
+ ref: forwardedRef
292
+ }) : /* @__PURE__ */(0, import_jsx_runtime.jsx)(MenuRootContentNonModal, {
293
+ ...contentProps,
294
+ ref: forwardedRef
264
295
  })
296
+ })
297
+ });
298
+ });
299
+ const MenuRootContentModal = React.forwardRef((props, forwardedRef) => {
300
+ const scope = props.scope || MENU_CONTEXT;
301
+ const context = useMenuContext(scope);
302
+ const ref = React.useRef(null);
303
+ const composedRefs = (0, import_web.useComposedRefs)(forwardedRef, ref);
304
+ return /* @__PURE__ */(0, import_jsx_runtime.jsx)(MenuContentImpl, {
305
+ ...props,
306
+ scope,
307
+ ref: composedRefs,
308
+ trapFocus: context.open,
309
+ disableOutsidePointerEvents: context.open,
310
+ disableOutsideScroll: false,
311
+ onFocusOutside: (0, import_web.composeEventHandlers)(props.onFocusOutside, event => event.preventDefault(), {
312
+ checkDefaultPrevented: false
313
+ }),
314
+ onDismiss: () => context.onOpenChange(false)
315
+ });
316
+ });
317
+ const MenuRootContentNonModal = React.forwardRef((props, forwardedRef) => {
318
+ const scope = props.scope || MENU_CONTEXT;
319
+ const context = useMenuContext(scope);
320
+ return /* @__PURE__ */(0, import_jsx_runtime.jsx)(MenuContentImpl, {
321
+ ...props,
322
+ scope,
323
+ ref: forwardedRef,
324
+ trapFocus: false,
325
+ disableOutsidePointerEvents: false,
326
+ disableOutsideScroll: false,
327
+ onDismiss: () => context.onOpenChange(false)
328
+ });
329
+ });
330
+ const MenuContentImpl = React.forwardRef((props, forwardedRef) => {
331
+ const {
332
+ scope = MENU_CONTEXT,
333
+ loop = false,
334
+ trapFocus,
335
+ onOpenAutoFocus,
336
+ onCloseAutoFocus,
337
+ disableOutsidePointerEvents,
338
+ onEntryFocus,
339
+ onEscapeKeyDown,
340
+ onPointerDownOutside,
341
+ onFocusOutside,
342
+ onInteractOutside,
343
+ onDismiss,
344
+ disableOutsideScroll,
345
+ disableDismissOnScroll = false,
346
+ unstyled = process.env.TAMAGUI_HEADLESS === "1",
347
+ ...contentProps
348
+ } = props;
349
+ const context = useMenuContext(scope);
350
+ const rootContext = useMenuRootContext(scope);
351
+ const getItems = useCollection(scope);
352
+ const [currentItemId, setCurrentItemId] = React.useState(null);
353
+ const contentRef = React.useRef(null);
354
+ const focusableContentRef = React.useRef(null);
355
+ const composedRefs = (0, import_web.useComposedRefs)(forwardedRef, contentRef, context.onContentChange);
356
+ const timerRef = React.useRef(0);
357
+ const searchRef = React.useRef("");
358
+ const pointerGraceTimerRef = React.useRef(0);
359
+ const pointerGraceIntentRef = React.useRef(null);
360
+ const pointerDirRef = React.useRef("right");
361
+ const lastPointerXRef = React.useRef(0);
362
+ const handleTypeaheadSearch = key => {
363
+ const search = searchRef.current + key;
364
+ const items = getItems().filter(item => !item.disabled);
365
+ const currentItem = document.activeElement;
366
+ const currentMatch = items.find(item => item.ref.current === currentItem)?.textValue;
367
+ const values = items.map(item => item.textValue);
368
+ const nextMatch = getNextMatch(values, search, currentMatch);
369
+ const newItem = items.find(item => item.textValue === nextMatch)?.ref.current;
370
+ (function updateSearch(value) {
371
+ searchRef.current = value;
372
+ clearTimeout(timerRef.current);
373
+ if (value !== "") timerRef.current = setTimeout(() => updateSearch(""), 1e3);
374
+ })(search);
375
+ if (newItem) {
376
+ setTimeout(() => newItem.focus());
377
+ }
378
+ };
379
+ React.useEffect(() => {
380
+ return () => clearTimeout(timerRef.current);
381
+ }, []);
382
+ React.useEffect(() => {
383
+ if (!import_web.isWeb || !context.open) return;
384
+ const frame = requestAnimationFrame(() => {
385
+ const container = contentRef.current;
386
+ const el = container?.querySelector("[data-tamagui-menu-content]");
387
+ if (el) focusableContentRef.current = el;
265
388
  });
266
- }),
267
- MenuRootContentModal = React.forwardRef((props, forwardedRef) => {
268
- const scope = props.scope || MENU_CONTEXT,
269
- context = useMenuContext(scope),
270
- ref = React.useRef(null),
271
- composedRefs = (0, import_web.useComposedRefs)(forwardedRef, ref);
272
- return /* @__PURE__ */(0, import_jsx_runtime.jsx)(MenuContentImpl, {
273
- ...props,
274
- scope,
275
- ref: composedRefs,
276
- trapFocus: context.open,
277
- disableOutsidePointerEvents: context.open,
278
- disableOutsideScroll: !1,
279
- onFocusOutside: (0, import_web.composeEventHandlers)(props.onFocusOutside, event => event.preventDefault(), {
280
- checkDefaultPrevented: !1
281
- }),
282
- onDismiss: () => context.onOpenChange(!1)
283
- });
284
- }),
285
- MenuRootContentNonModal = React.forwardRef((props, forwardedRef) => {
286
- const scope = props.scope || MENU_CONTEXT,
287
- context = useMenuContext(scope);
288
- return /* @__PURE__ */(0, import_jsx_runtime.jsx)(MenuContentImpl, {
289
- ...props,
290
- scope,
291
- ref: forwardedRef,
292
- trapFocus: !1,
293
- disableOutsidePointerEvents: !1,
294
- disableOutsideScroll: !1,
295
- onDismiss: () => context.onOpenChange(!1)
389
+ return () => cancelAnimationFrame(frame);
390
+ }, [context.open]);
391
+ React.useEffect(() => {
392
+ if (!import_web.isWeb || disableDismissOnScroll || !context.open) return;
393
+ const handleScroll = event => {
394
+ const target = event.target;
395
+ if (contentRef.current?.contains(target)) return;
396
+ onDismiss?.();
397
+ };
398
+ window.addEventListener("scroll", handleScroll, {
399
+ capture: true,
400
+ passive: true
296
401
  });
297
- }),
298
- MenuContentImpl = React.forwardRef((props, forwardedRef) => {
299
- const {
300
- scope = MENU_CONTEXT,
301
- loop = !1,
302
- trapFocus,
303
- onOpenAutoFocus,
304
- onCloseAutoFocus,
305
- disableOutsidePointerEvents,
306
- onEntryFocus,
307
- onEscapeKeyDown,
308
- onPointerDownOutside,
309
- onFocusOutside,
310
- onInteractOutside,
311
- onDismiss,
312
- disableOutsideScroll,
313
- disableDismissOnScroll = !1,
314
- unstyled = process.env.TAMAGUI_HEADLESS === "1",
315
- ...contentProps
316
- } = props,
317
- context = useMenuContext(scope),
318
- rootContext = useMenuRootContext(scope),
319
- getItems = useCollection(scope),
320
- [currentItemId, setCurrentItemId] = React.useState(null),
321
- contentRef = React.useRef(null),
322
- composedRefs = (0, import_web.useComposedRefs)(forwardedRef, contentRef, context.onContentChange),
323
- timerRef = React.useRef(0),
324
- searchRef = React.useRef(""),
325
- pointerGraceTimerRef = React.useRef(0),
326
- pointerGraceIntentRef = React.useRef(null),
327
- pointerDirRef = React.useRef("right"),
328
- lastPointerXRef = React.useRef(0),
329
- handleTypeaheadSearch = key => {
330
- const search = searchRef.current + key,
331
- items = getItems().filter(item => !item.disabled),
332
- currentItem = document.activeElement,
333
- currentMatch = items.find(item => item.ref.current === currentItem)?.textValue,
334
- values = items.map(item => item.textValue),
335
- nextMatch = getNextMatch(values, search, currentMatch),
336
- newItem = items.find(item => item.textValue === nextMatch)?.ref.current;
337
- (function updateSearch(value) {
338
- searchRef.current = value, clearTimeout(timerRef.current), value !== "" && (timerRef.current = setTimeout(() => updateSearch(""), 1e3));
339
- })(search), newItem && setTimeout(() => newItem.focus());
340
- };
341
- React.useEffect(() => () => clearTimeout(timerRef.current), []), React.useEffect(() => {
342
- if (!import_web.isWeb || disableDismissOnScroll || !context.open) return;
343
- const handleScroll = () => {
344
- onDismiss?.();
345
- };
346
- return window.addEventListener("scroll", handleScroll, {
347
- capture: !0,
348
- passive: !0
349
- }), () => {
350
- window.removeEventListener("scroll", handleScroll, {
351
- capture: !0
402
+ return () => {
403
+ window.removeEventListener("scroll", handleScroll, {
404
+ capture: true
405
+ });
406
+ };
407
+ }, [disableDismissOnScroll, context.open, onDismiss]);
408
+ if (import_web.isWeb) {
409
+ (0, import_focus_guard.useFocusGuards)();
410
+ }
411
+ const isPointerMovingToSubmenu = React.useCallback(event => {
412
+ const isMovingTowards = pointerDirRef.current === pointerGraceIntentRef.current?.side;
413
+ const inArea = isPointerInGraceArea(event, pointerGraceIntentRef.current?.area);
414
+ return isMovingTowards && inArea;
415
+ }, []);
416
+ const content = /* @__PURE__ */(0, import_jsx_runtime.jsx)(PopperPrimitive.PopperContent, {
417
+ role: "menu",
418
+ tabIndex: -1,
419
+ unstyled,
420
+ ...(!unstyled && {
421
+ backgroundColor: "$background",
422
+ borderWidth: 1,
423
+ borderColor: "$borderColor",
424
+ outlineWidth: 0,
425
+ minWidth: 180
426
+ }),
427
+ "aria-orientation": "vertical",
428
+ "data-state": getOpenState(context.open),
429
+ "data-tamagui-menu-content": "",
430
+ dir: rootContext.dir,
431
+ scope: scope || MENU_CONTEXT,
432
+ ...contentProps,
433
+ ref: composedRefs,
434
+ className: contentProps.transition ? void 0 : contentProps.className,
435
+ ...(import_web.isWeb ? {
436
+ onKeyDown: (0, import_web.composeEventHandlers)(contentProps.onKeyDown, event => {
437
+ const target = event.target;
438
+ const isKeyDownInside = target.closest("[data-tamagui-menu-content]") === event.currentTarget;
439
+ const isModifierKey = event.ctrlKey || event.altKey || event.metaKey;
440
+ const isCharacterKey = event.key.length === 1;
441
+ if (isKeyDownInside) {
442
+ if (event.key === "Tab") event.preventDefault();
443
+ if (!isModifierKey && isCharacterKey) handleTypeaheadSearch(event.key);
444
+ }
445
+ const isOnContentFrame = event.target.hasAttribute("data-tamagui-menu-content");
446
+ if (!isKeyDownInside || !isOnContentFrame) return;
447
+ if (!FIRST_LAST_KEYS.includes(event.key)) return;
448
+ event.preventDefault();
449
+ const items = getItems().filter(item => !item.disabled);
450
+ const candidateNodes = items.map(item => item.ref.current);
451
+ if (LAST_KEYS.includes(event.key)) candidateNodes.reverse();
452
+ focusFirst(candidateNodes, {
453
+ focusVisible: true
352
454
  });
353
- };
354
- }, [disableDismissOnScroll, context.open, onDismiss]), import_web.isWeb && (0, import_focus_guard.useFocusGuards)();
355
- const isPointerMovingToSubmenu = React.useCallback(event => {
356
- const isMovingTowards = pointerDirRef.current === pointerGraceIntentRef.current?.side,
357
- inArea = isPointerInGraceArea(event, pointerGraceIntentRef.current?.area);
358
- return isMovingTowards && inArea;
359
- }, []),
360
- content = /* @__PURE__ */(0, import_jsx_runtime.jsx)(PopperPrimitive.PopperContent, {
361
- role: "menu",
362
- ...(!unstyled && {
363
- padding: 4,
364
- backgroundColor: "$background",
365
- borderWidth: 1,
366
- borderColor: "$borderColor",
367
- outlineWidth: 0,
368
- minWidth: 180
455
+ }),
456
+ // TODO
457
+ // @ts-ignore
458
+ onBlur: (0, import_web.composeEventHandlers)(props.onBlur, event => {
459
+ if (!event.currentTarget?.contains(event.target)) {
460
+ clearTimeout(timerRef.current);
461
+ searchRef.current = "";
462
+ }
463
+ }),
464
+ // TODO
465
+ onPointerMove: (0, import_web.composeEventHandlers)(props.onPointerMove, event => {
466
+ if (event.pointerType !== "mouse") return;
467
+ const target = event.target;
468
+ const pointerXHasChanged = lastPointerXRef.current !== event.clientX;
469
+ if (event.currentTarget?.contains(target) && pointerXHasChanged) {
470
+ const newDir = event.clientX > lastPointerXRef.current ? "right" : "left";
471
+ pointerDirRef.current = newDir;
472
+ lastPointerXRef.current = event.clientX;
473
+ }
474
+ })
475
+ } : {})
476
+ });
477
+ return /* @__PURE__ */(0, import_jsx_runtime.jsx)(MenuContentProvider, {
478
+ scope,
479
+ searchRef,
480
+ onItemEnter: React.useCallback(event => {
481
+ if (isPointerMovingToSubmenu(event)) event.preventDefault();
482
+ }, [isPointerMovingToSubmenu]),
483
+ onItemLeave: React.useCallback(event => {
484
+ if (isPointerMovingToSubmenu(event)) return;
485
+ focusableContentRef.current?.focus();
486
+ setCurrentItemId(null);
487
+ }, [isPointerMovingToSubmenu]),
488
+ onTriggerLeave: React.useCallback(event => {
489
+ if (isPointerMovingToSubmenu(event)) event.preventDefault();
490
+ }, [isPointerMovingToSubmenu]),
491
+ pointerGraceTimerRef,
492
+ onPointerGraceIntentChange: React.useCallback(intent => {
493
+ pointerGraceIntentRef.current = intent;
494
+ }, []),
495
+ children: /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_remove_scroll.RemoveScroll, {
496
+ enabled: disableOutsideScroll,
497
+ children: /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_focus_scope.FocusScope, {
498
+ asChild: false,
499
+ trapped: trapFocus,
500
+ onMountAutoFocus: (0, import_web.composeEventHandlers)(onOpenAutoFocus, event => {
501
+ event.preventDefault();
502
+ const content2 = document.querySelector("[data-tamagui-menu-content]");
503
+ content2?.focus({
504
+ preventScroll: true
505
+ });
369
506
  }),
370
- "aria-orientation": "vertical",
371
- "data-state": getOpenState(context.open),
372
- "data-tamagui-menu-content": "",
373
- dir: rootContext.dir,
374
- scope: scope || MENU_CONTEXT,
375
- ...contentProps,
376
- ref: composedRefs,
377
- className: contentProps.transition ? void 0 : contentProps.className,
378
- ...(import_web.isWeb ? {
379
- onKeyDown: (0, import_web.composeEventHandlers)(contentProps.onKeyDown, event => {
380
- const isKeyDownInside = event.target.closest("[data-tamagui-menu-content]") === event.currentTarget,
381
- isModifierKey = event.ctrlKey || event.altKey || event.metaKey,
382
- isCharacterKey = event.key.length === 1;
383
- isKeyDownInside && (event.key === "Tab" && event.preventDefault(), !isModifierKey && isCharacterKey && handleTypeaheadSearch(event.key));
384
- const isOnContentFrame = event.target.hasAttribute("data-tamagui-menu-content");
385
- if (!isKeyDownInside || !isOnContentFrame || !FIRST_LAST_KEYS.includes(event.key)) return;
386
- event.preventDefault();
387
- const candidateNodes = getItems().filter(item => !item.disabled).map(item => item.ref.current);
388
- LAST_KEYS.includes(event.key) && candidateNodes.reverse(), focusFirst(candidateNodes, {
389
- focusVisible: !0
390
- });
391
- }),
392
- // TODO
393
- // @ts-ignore
394
- onBlur: (0, import_web.composeEventHandlers)(props.onBlur, event => {
395
- event.currentTarget?.contains(event.target) || (clearTimeout(timerRef.current), searchRef.current = "");
396
- }),
397
- // TODO
398
- onPointerMove: (0, import_web.composeEventHandlers)(props.onPointerMove, event => {
399
- if (event.pointerType !== "mouse") return;
400
- const target = event.target,
401
- pointerXHasChanged = lastPointerXRef.current !== event.clientX;
402
- if (event.currentTarget?.contains(target) && pointerXHasChanged) {
403
- const newDir = event.clientX > lastPointerXRef.current ? "right" : "left";
404
- pointerDirRef.current = newDir, lastPointerXRef.current = event.clientX;
405
- }
406
- })
407
- } : {})
408
- });
409
- return /* @__PURE__ */(0, import_jsx_runtime.jsx)(MenuContentProvider, {
410
- scope,
411
- searchRef,
412
- onItemEnter: React.useCallback(event => {
413
- isPointerMovingToSubmenu(event) && event.preventDefault();
414
- }, [isPointerMovingToSubmenu]),
415
- onItemLeave: React.useCallback(event => {
416
- isPointerMovingToSubmenu(event) || (contentRef.current?.focus(), setCurrentItemId(null));
417
- }, [isPointerMovingToSubmenu]),
418
- onTriggerLeave: React.useCallback(event => {
419
- isPointerMovingToSubmenu(event) && event.preventDefault();
420
- }, [isPointerMovingToSubmenu]),
421
- pointerGraceTimerRef,
422
- onPointerGraceIntentChange: React.useCallback(intent => {
423
- pointerGraceIntentRef.current = intent;
424
- }, []),
425
- children: /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_remove_scroll.RemoveScroll, {
426
- enabled: disableOutsideScroll,
427
- children: /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_focus_scope.FocusScope, {
428
- asChild: !1,
429
- trapped: trapFocus,
430
- onMountAutoFocus: (0, import_web.composeEventHandlers)(onOpenAutoFocus, event => {
431
- event.preventDefault(), document.querySelector("[data-tamagui-menu-content]")?.focus();
432
- }),
433
- onUnmountAutoFocus: onCloseAutoFocus,
434
- children: /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_dismissable.Dismissable, {
435
- disableOutsidePointerEvents,
436
- onEscapeKeyDown,
437
- onPointerDownOutside,
438
- onFocusOutside,
439
- onInteractOutside,
440
- onDismiss,
441
- asChild: !0,
442
- children: /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_roving_focus.RovingFocusGroup, {
443
- asChild: !0,
444
- __scopeRovingFocusGroup: scope || MENU_CONTEXT,
445
- dir: rootContext.dir,
446
- orientation: "vertical",
447
- loop,
448
- currentTabStopId: currentItemId,
449
- onCurrentTabStopIdChange: setCurrentItemId,
450
- onEntryFocus: (0, import_web.composeEventHandlers)(onEntryFocus, event => {
451
- rootContext.isUsingKeyboardRef.current || event.preventDefault();
452
- }),
453
- children: content
454
- })
507
+ onUnmountAutoFocus: onCloseAutoFocus,
508
+ children: /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_dismissable.Dismissable, {
509
+ disableOutsidePointerEvents,
510
+ onEscapeKeyDown,
511
+ onPointerDownOutside,
512
+ onFocusOutside,
513
+ onInteractOutside,
514
+ onDismiss,
515
+ asChild: true,
516
+ children: /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_roving_focus.RovingFocusGroup, {
517
+ asChild: true,
518
+ __scopeRovingFocusGroup: scope || MENU_CONTEXT,
519
+ dir: rootContext.dir,
520
+ orientation: "vertical",
521
+ loop,
522
+ currentTabStopId: currentItemId,
523
+ onCurrentTabStopIdChange: setCurrentItemId,
524
+ onEntryFocus: (0, import_web.composeEventHandlers)(onEntryFocus, event => {
525
+ if (!rootContext.isUsingKeyboardRef.current) {
526
+ event.preventDefault();
527
+ }
528
+ }),
529
+ children: content
455
530
  })
456
531
  })
457
532
  })
458
- });
533
+ })
459
534
  });
535
+ });
460
536
  MenuContent.displayName = CONTENT_NAME;
461
- const ITEM_NAME = "MenuItem",
462
- ITEM_SELECT = "menu.itemSelect",
463
- MenuItem = React.forwardRef((props, forwardedRef) => {
464
- const {
465
- disabled = !1,
466
- onSelect,
467
- children,
468
- scope = MENU_CONTEXT,
469
- // filter out native-only props that shouldn't reach the DOM
470
- // @ts-ignore
471
- destructive,
472
- // @ts-ignore
473
- hidden,
474
- // @ts-ignore
475
- androidIconName,
476
- // @ts-ignore
477
- iosIconName,
478
- ...itemProps
479
- } = props,
480
- ref = React.useRef(null),
481
- rootContext = useMenuRootContext(scope),
482
- contentContext = useMenuContentContext(scope),
483
- composedRefs = (0, import_web.useComposedRefs)(forwardedRef, ref),
484
- isPointerDownRef = React.useRef(!1),
485
- handleSelect = () => {
486
- const menuItem = ref.current;
487
- if (!disabled && menuItem) if (import_web.isWeb) {
488
- const menuItemEl = menuItem,
489
- itemSelectEvent = new CustomEvent(ITEM_SELECT, {
490
- bubbles: !0,
491
- cancelable: !0
492
- });
493
- menuItemEl.addEventListener(ITEM_SELECT, event => onSelect?.(event), {
494
- once: !0
495
- }), (0, import_dismissable.dispatchDiscreteCustomEvent)(menuItemEl, itemSelectEvent), itemSelectEvent.defaultPrevented ? isPointerDownRef.current = !1 : rootContext.onClose();
496
- } else onSelect?.({
537
+ const ITEM_NAME = "MenuItem";
538
+ const ITEM_SELECT = "menu.itemSelect";
539
+ const MenuItem = _Item.styleable((props, forwardedRef) => {
540
+ const {
541
+ disabled = false,
542
+ onSelect,
543
+ preventCloseOnSelect,
544
+ children,
545
+ scope = MENU_CONTEXT,
546
+ // filter out native-only props that shouldn't reach the DOM
547
+ // @ts-ignore
548
+ destructive,
549
+ // @ts-ignore
550
+ hidden,
551
+ // @ts-ignore
552
+ androidIconName,
553
+ // @ts-ignore
554
+ iosIconName,
555
+ ...itemProps
556
+ } = props;
557
+ const ref = React.useRef(null);
558
+ const rootContext = useMenuRootContext(scope);
559
+ const contentContext = useMenuContentContext(scope);
560
+ const composedRefs = (0, import_web.useComposedRefs)(forwardedRef, ref);
561
+ const isPointerDownRef = React.useRef(false);
562
+ const handleSelect = () => {
563
+ const menuItem = ref.current;
564
+ if (!disabled && menuItem) {
565
+ if (import_web.isWeb) {
566
+ const menuItemEl = menuItem;
567
+ const itemSelectEvent = new CustomEvent(ITEM_SELECT, {
568
+ bubbles: true,
569
+ cancelable: true
570
+ });
571
+ menuItemEl.addEventListener(ITEM_SELECT, event => onSelect?.(event), {
572
+ once: true
573
+ });
574
+ (0, import_dismissable.dispatchDiscreteCustomEvent)(menuItemEl, itemSelectEvent);
575
+ if (itemSelectEvent.defaultPrevented || preventCloseOnSelect) {
576
+ isPointerDownRef.current = false;
577
+ } else {
578
+ rootContext.onClose();
579
+ }
580
+ } else {
581
+ onSelect?.({
497
582
  target: menuItem
498
- }), isPointerDownRef.current = !1, rootContext.onClose();
499
- },
500
- content = typeof children == "string" ? /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_web.Text, {
501
- children
502
- }) : children;
503
- return /* @__PURE__ */(0, import_jsx_runtime.jsx)(MenuItemImpl, {
504
- outlineStyle: "none",
505
- ...itemProps,
506
- scope,
507
- ref: composedRefs,
508
- disabled,
509
- onPress: (0, import_web.composeEventHandlers)(props.onPress, handleSelect),
510
- onPointerDown: event => {
511
- props.onPointerDown?.(event), isPointerDownRef.current = !0;
512
- },
513
- onPointerUp: (0, import_web.composeEventHandlers)(props.onPointerUp, event => {
514
- import_web.isWeb && (isPointerDownRef.current || event.currentTarget?.click());
515
- }),
516
- ...(import_web.isWeb ? {
517
- onKeyDown: (0, import_web.composeEventHandlers)(props.onKeyDown, event => {
518
- const isTypingAhead = contentContext.searchRef.current !== "";
519
- disabled || isTypingAhead && event.key === " " || SELECTION_KEYS.includes(event.key) && (event.currentTarget?.click(), event.preventDefault());
520
- })
521
- } : {}),
522
- children: content
523
- });
524
- }),
525
- MenuItemImpl = React.forwardRef((props, forwardedRef) => {
526
- const {
527
- scope = MENU_CONTEXT,
528
- disabled = !1,
529
- textValue,
530
- unstyled = process.env.TAMAGUI_HEADLESS === "1",
531
- ...itemProps
532
- } = props,
533
- contentContext = useMenuContentContext(scope),
534
- ref = React.useRef(null),
535
- composedRefs = (0, import_web.useComposedRefs)(forwardedRef, ref),
536
- [isFocused, setIsFocused] = React.useState(!1),
537
- [textContent, setTextContent] = React.useState("");
538
- return import_web.isWeb && React.useEffect(() => {
583
+ });
584
+ isPointerDownRef.current = false;
585
+ if (!preventCloseOnSelect) {
586
+ rootContext.onClose();
587
+ }
588
+ }
589
+ }
590
+ };
591
+ const content = typeof children === "string" ? /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_web.Text, {
592
+ children
593
+ }) : children;
594
+ return /* @__PURE__ */(0, import_jsx_runtime.jsx)(MenuItemImpl, {
595
+ outlineStyle: "none",
596
+ ...itemProps,
597
+ scope,
598
+ ref: composedRefs,
599
+ disabled,
600
+ onPress: (0, import_web.composeEventHandlers)(props.onPress, handleSelect),
601
+ onPointerDown: event => {
602
+ props.onPointerDown?.(event);
603
+ isPointerDownRef.current = true;
604
+ },
605
+ onPointerUp: (0, import_web.composeEventHandlers)(props.onPointerUp, event => {
606
+ if (import_web.isWeb) {
607
+ if (!isPointerDownRef.current) event.currentTarget?.click();
608
+ }
609
+ }),
610
+ ...(import_web.isWeb ? {
611
+ onKeyDown: (0, import_web.composeEventHandlers)(props.onKeyDown, event => {
612
+ const isTypingAhead = contentContext.searchRef.current !== "";
613
+ if (disabled || isTypingAhead && event.key === " ") return;
614
+ if (SELECTION_KEYS.includes(event.key)) {
615
+ event.currentTarget?.click();
616
+ event.preventDefault();
617
+ }
618
+ })
619
+ } : {}),
620
+ children: content
621
+ });
622
+ });
623
+ const MenuItemImpl = React.forwardRef((props, forwardedRef) => {
624
+ const {
625
+ scope = MENU_CONTEXT,
626
+ disabled = false,
627
+ textValue,
628
+ unstyled = process.env.TAMAGUI_HEADLESS === "1",
629
+ ...itemProps
630
+ } = props;
631
+ const contentContext = useMenuContentContext(scope);
632
+ const ref = React.useRef(null);
633
+ const composedRefs = (0, import_web.useComposedRefs)(forwardedRef, ref);
634
+ const [isFocused, setIsFocused] = React.useState(false);
635
+ const [textContent, setTextContent] = React.useState("");
636
+ if (import_web.isWeb) {
637
+ React.useEffect(() => {
539
638
  const menuItem = ref.current;
540
- menuItem && setTextContent((menuItem.textContent ?? "").trim());
541
- }, [itemProps.children]), /* @__PURE__ */(0, import_jsx_runtime.jsx)(Collection.ItemSlot, {
542
- scope,
543
- disabled,
544
- textValue: textValue ?? textContent,
545
- children: /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_roving_focus.RovingFocusGroup.Item, {
546
- asChild: !0,
547
- __scopeRovingFocusGroup: scope,
548
- focusable: !disabled,
549
- ...(!unstyled && {
550
- flexDirection: "row",
551
- alignItems: "center"
552
- }),
639
+ if (menuItem) {
640
+ setTextContent((menuItem.textContent ?? "").trim());
641
+ }
642
+ }, [itemProps.children]);
643
+ }
644
+ return /* @__PURE__ */(0, import_jsx_runtime.jsx)(Collection.ItemSlot, {
645
+ scope,
646
+ disabled,
647
+ textValue: textValue ?? textContent,
648
+ children: /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_roving_focus.RovingFocusGroup.Item, {
649
+ asChild: true,
650
+ __scopeRovingFocusGroup: scope,
651
+ focusable: !disabled,
652
+ children: /* @__PURE__ */(0, import_jsx_runtime.jsx)(_Item, {
653
+ unstyled,
654
+ componentName: ITEM_NAME,
655
+ role: "menuitem",
656
+ "data-highlighted": isFocused ? "" : void 0,
657
+ "aria-disabled": disabled || void 0,
658
+ "data-disabled": disabled ? "" : void 0,
553
659
  ...itemProps,
554
- children: /* @__PURE__ */(0, import_jsx_runtime.jsx)(_Item, {
555
- componentName: ITEM_NAME,
556
- role: "menuitem",
557
- "data-highlighted": isFocused ? "" : void 0,
558
- "aria-disabled": disabled || void 0,
559
- "data-disabled": disabled ? "" : void 0,
560
- ...itemProps,
561
- ref: composedRefs,
562
- onPointerMove: (0, import_web.composeEventHandlers)(props.onPointerMove, event => {
563
- event.pointerType === "mouse" && (disabled ? contentContext.onItemLeave(event) : (contentContext.onItemEnter(event), event.defaultPrevented || event.currentTarget.focus({
564
- preventScroll: !0,
565
- focusVisible: !1
566
- })));
567
- }),
568
- onPointerLeave: (0, import_web.composeEventHandlers)(props.onPointerLeave, event => {
660
+ ref: composedRefs,
661
+ onPointerMove: (0, import_web.composeEventHandlers)(props.onPointerMove, event => {
662
+ if (event.pointerType !== "mouse") return;
663
+ if (disabled) {
569
664
  contentContext.onItemLeave(event);
570
- }),
571
- onFocus: (0, import_web.composeEventHandlers)(props.onFocus, () => setIsFocused(!0)),
572
- onBlur: (0, import_web.composeEventHandlers)(props.onBlur, () => setIsFocused(!1))
573
- })
665
+ } else {
666
+ contentContext.onItemEnter(event);
667
+ if (!event.defaultPrevented) {
668
+ const item = event.currentTarget;
669
+ item.focus({
670
+ preventScroll: true,
671
+ focusVisible: false
672
+ });
673
+ }
674
+ }
675
+ }),
676
+ onPointerLeave: (0, import_web.composeEventHandlers)(props.onPointerLeave, event => {
677
+ contentContext.onItemLeave(event);
678
+ }),
679
+ onFocus: (0, import_web.composeEventHandlers)(props.onFocus, () => setIsFocused(true)),
680
+ onBlur: (0, import_web.composeEventHandlers)(props.onBlur, () => setIsFocused(false))
574
681
  })
575
- });
682
+ })
576
683
  });
684
+ });
577
685
  MenuItem.displayName = ITEM_NAME;
578
- const ITEM_TITLE_NAME = "MenuItemTitle",
579
- MenuItemTitle = _Title.styleable((props, forwardedRef) => /* @__PURE__ */(0, import_jsx_runtime.jsx)(_Title, {
686
+ const ITEM_TITLE_NAME = "MenuItemTitle";
687
+ const MenuItemTitle = _Title.styleable((props, forwardedRef) => {
688
+ return /* @__PURE__ */(0, import_jsx_runtime.jsx)(_Title, {
580
689
  ...props,
581
690
  ref: forwardedRef
582
- }));
691
+ });
692
+ });
583
693
  MenuItemTitle.displayName = ITEM_TITLE_NAME;
584
- const ITEM_SUB_TITLE_NAME = "MenuItemSubTitle",
585
- MenuItemSubTitle = _SubTitle.styleable((props, forwardedRef) => /* @__PURE__ */(0, import_jsx_runtime.jsx)(_SubTitle, {
694
+ const ITEM_SUB_TITLE_NAME = "MenuItemSubTitle";
695
+ const MenuItemSubTitle = _SubTitle.styleable((props, forwardedRef) => {
696
+ return /* @__PURE__ */(0, import_jsx_runtime.jsx)(_SubTitle, {
586
697
  ...props,
587
698
  ref: forwardedRef
588
- }));
699
+ });
700
+ });
589
701
  MenuItemSubTitle.displayName = ITEM_SUB_TITLE_NAME;
590
- const ITEM_IMAGE = "MenuItemImage",
591
- MenuItemImage = React.forwardRef((props, forwardedRef) => {
592
- const {
593
- // @ts-ignore - native menu ios config
594
- ios,
595
- // @ts-ignore
596
- androidIconName,
597
- // @ts-ignore
598
- iosIconName,
599
- ...rest
600
- } = props;
601
- return /* @__PURE__ */(0, import_jsx_runtime.jsx)(_Image, {
602
- ...rest,
603
- ref: forwardedRef
604
- });
702
+ const ITEM_IMAGE = "MenuItemImage";
703
+ const MenuItemImage = React.forwardRef((props, forwardedRef) => {
704
+ const {
705
+ // @ts-ignore - native menu ios config
706
+ ios,
707
+ // @ts-ignore
708
+ androidIconName,
709
+ // @ts-ignore
710
+ iosIconName,
711
+ ...rest
712
+ } = props;
713
+ return /* @__PURE__ */(0, import_jsx_runtime.jsx)(_Image, {
714
+ ...rest,
715
+ ref: forwardedRef
605
716
  });
717
+ });
606
718
  MenuItemImage.displayName = ITEM_IMAGE;
607
- const ITEM_ICON = "MenuItemIcon",
608
- MenuItemIcon = _Icon.styleable((props, forwardedRef) => {
609
- const {
610
- // @ts-ignore
611
- ios,
612
- // @ts-ignore
613
- android,
614
- // @ts-ignore
615
- androidIconName,
616
- // @ts-ignore
617
- iosIconName,
618
- ...rest
619
- } = props;
620
- return /* @__PURE__ */(0, import_jsx_runtime.jsx)(_Icon, {
621
- ...rest,
622
- ref: forwardedRef
623
- });
719
+ const ITEM_ICON = "MenuItemIcon";
720
+ const MenuItemIcon = _Icon.styleable((props, forwardedRef) => {
721
+ const {
722
+ // @ts-ignore
723
+ ios,
724
+ // @ts-ignore
725
+ android,
726
+ // @ts-ignore
727
+ androidIconName,
728
+ // @ts-ignore
729
+ iosIconName,
730
+ ...rest
731
+ } = props;
732
+ return /* @__PURE__ */(0, import_jsx_runtime.jsx)(_Icon, {
733
+ ...rest,
734
+ ref: forwardedRef
624
735
  });
736
+ });
625
737
  MenuItemIcon.displayName = ITEM_ICON;
626
- const CHECKBOX_ITEM_NAME = "MenuCheckboxItem",
627
- MenuCheckboxItem = React.forwardRef((props, forwardedRef) => {
628
- const {
629
- checked = !1,
630
- onCheckedChange,
631
- scope = MENU_CONTEXT,
632
- // filter out native-only props
633
- // @ts-ignore - native menu value state
634
- value,
635
- // @ts-ignore - native menu value change handler
636
- onValueChange,
637
- ...checkboxItemProps
638
- } = props;
639
- return /* @__PURE__ */(0, import_jsx_runtime.jsx)(ItemIndicatorProvider, {
738
+ const CHECKBOX_ITEM_NAME = "MenuCheckboxItem";
739
+ const MenuCheckboxItem = _Item.styleable((props, forwardedRef) => {
740
+ const {
741
+ checked = false,
742
+ onCheckedChange,
743
+ scope = MENU_CONTEXT,
744
+ // filter out native-only props
745
+ // @ts-ignore - native menu value state
746
+ value,
747
+ // @ts-ignore - native menu value change handler
748
+ onValueChange,
749
+ ...checkboxItemProps
750
+ } = props;
751
+ return /* @__PURE__ */(0, import_jsx_runtime.jsx)(ItemIndicatorProvider, {
752
+ scope,
753
+ checked,
754
+ children: /* @__PURE__ */(0, import_jsx_runtime.jsx)(MenuItem, {
755
+ componentName: CHECKBOX_ITEM_NAME,
756
+ role: import_web.isWeb ? "menuitemcheckbox" : "menuitem",
757
+ "aria-checked": isIndeterminate(checked) ? "mixed" : checked,
758
+ ...checkboxItemProps,
640
759
  scope,
641
- checked,
642
- children: /* @__PURE__ */(0, import_jsx_runtime.jsx)(MenuItem, {
643
- componentName: CHECKBOX_ITEM_NAME,
644
- role: import_web.isWeb ? "menuitemcheckbox" : "menuitem",
645
- "aria-checked": isIndeterminate(checked) ? "mixed" : checked,
646
- ...checkboxItemProps,
647
- scope,
648
- ref: forwardedRef,
649
- "data-state": getCheckedState(checked),
650
- onSelect: (0, import_web.composeEventHandlers)(checkboxItemProps.onSelect, () => onCheckedChange?.(isIndeterminate(checked) ? !0 : !checked), {
651
- checkDefaultPrevented: !1
652
- })
760
+ ref: forwardedRef,
761
+ "data-state": getCheckedState(checked),
762
+ onSelect: (0, import_web.composeEventHandlers)(checkboxItemProps.onSelect, () => onCheckedChange?.(isIndeterminate(checked) ? true : !checked), {
763
+ checkDefaultPrevented: false
653
764
  })
654
- });
765
+ })
655
766
  });
767
+ });
656
768
  MenuCheckboxItem.displayName = CHECKBOX_ITEM_NAME;
657
- const RADIO_GROUP_NAME = "MenuRadioGroup",
658
- {
659
- Provider: RadioGroupProvider,
660
- useStyledContext: useRadioGroupContext
661
- } = (0, import_web.createStyledContext)(),
662
- MenuRadioGroup = _MenuGroup.styleable((props, forwardedRef) => {
663
- const {
664
- value,
665
- onValueChange,
666
- scope = MENU_CONTEXT,
667
- ...groupProps
668
- } = props,
669
- handleValueChange = (0, import_use_callback_ref.useCallbackRef)(onValueChange);
670
- return /* @__PURE__ */(0, import_jsx_runtime.jsx)(RadioGroupProvider, {
671
- scope,
672
- value,
673
- onValueChange: handleValueChange,
674
- children: /* @__PURE__ */(0, import_jsx_runtime.jsx)(_MenuGroup, {
675
- componentName: RADIO_GROUP_NAME,
676
- ...groupProps,
677
- ref: forwardedRef
678
- })
679
- });
769
+ const RADIO_GROUP_NAME = "MenuRadioGroup";
770
+ const {
771
+ Provider: RadioGroupProvider,
772
+ useStyledContext: useRadioGroupContext
773
+ } = (0, import_web.createStyledContext)();
774
+ const MenuRadioGroup = _MenuGroup.styleable((props, forwardedRef) => {
775
+ const {
776
+ value,
777
+ onValueChange,
778
+ scope = MENU_CONTEXT,
779
+ ...groupProps
780
+ } = props;
781
+ const handleValueChange = (0, import_use_callback_ref.useCallbackRef)(onValueChange);
782
+ return /* @__PURE__ */(0, import_jsx_runtime.jsx)(RadioGroupProvider, {
783
+ scope,
784
+ value,
785
+ onValueChange: handleValueChange,
786
+ children: /* @__PURE__ */(0, import_jsx_runtime.jsx)(_MenuGroup, {
787
+ componentName: RADIO_GROUP_NAME,
788
+ ...groupProps,
789
+ ref: forwardedRef
790
+ })
680
791
  });
792
+ });
681
793
  MenuRadioGroup.displayName = RADIO_GROUP_NAME;
682
- const RADIO_ITEM_NAME = "MenuRadioItem",
683
- MenuRadioItem = React.forwardRef((props, forwardedRef) => {
684
- const {
685
- value,
686
- scope = MENU_CONTEXT,
687
- ...radioItemProps
688
- } = props,
689
- context = useRadioGroupContext(scope),
690
- checked = value === context.value;
691
- return /* @__PURE__ */(0, import_jsx_runtime.jsx)(ItemIndicatorProvider, {
794
+ const RADIO_ITEM_NAME = "MenuRadioItem";
795
+ const MenuRadioItem = _Item.styleable((props, forwardedRef) => {
796
+ const {
797
+ value,
798
+ scope = MENU_CONTEXT,
799
+ ...radioItemProps
800
+ } = props;
801
+ const context = useRadioGroupContext(scope);
802
+ const checked = value === context.value;
803
+ return /* @__PURE__ */(0, import_jsx_runtime.jsx)(ItemIndicatorProvider, {
804
+ scope,
805
+ checked,
806
+ children: /* @__PURE__ */(0, import_jsx_runtime.jsx)(MenuItem, {
807
+ componentName: RADIO_ITEM_NAME,
808
+ ...radioItemProps,
692
809
  scope,
693
- checked,
694
- children: /* @__PURE__ */(0, import_jsx_runtime.jsx)(MenuItem, {
695
- componentName: RADIO_ITEM_NAME,
696
- ...radioItemProps,
697
- scope,
698
- "aria-checked": checked,
699
- ref: forwardedRef,
700
- role: import_web.isWeb ? "menuitemradio" : "menuitem",
701
- "data-state": getCheckedState(checked),
702
- onSelect: (0, import_web.composeEventHandlers)(radioItemProps.onSelect, () => context.onValueChange?.(value), {
703
- checkDefaultPrevented: !1
704
- })
810
+ "aria-checked": checked,
811
+ ref: forwardedRef,
812
+ role: import_web.isWeb ? "menuitemradio" : "menuitem",
813
+ "data-state": getCheckedState(checked),
814
+ onSelect: (0, import_web.composeEventHandlers)(radioItemProps.onSelect, () => context.onValueChange?.(value), {
815
+ checkDefaultPrevented: false
705
816
  })
706
- });
817
+ })
707
818
  });
819
+ });
708
820
  MenuRadioItem.displayName = RADIO_ITEM_NAME;
709
- const ITEM_INDICATOR_NAME = "MenuItemIndicator",
710
- {
711
- Provider: ItemIndicatorProvider,
712
- useStyledContext: useItemIndicatorContext
713
- } = (0, import_web.createStyledContext)(),
714
- MenuItemIndicator = _Indicator.styleable((props, forwardedRef) => {
715
- const {
716
- scope = MENU_CONTEXT,
717
- forceMount,
718
- ...itemIndicatorProps
719
- } = props,
720
- indicatorContext = useItemIndicatorContext(scope);
721
- return /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_animate_presence.AnimatePresence, {
722
- children: forceMount || isIndeterminate(indicatorContext.checked) || indicatorContext.checked === !0 ? /* @__PURE__ */(0, import_jsx_runtime.jsx)(_Indicator, {
723
- componentName: ITEM_INDICATOR_NAME,
724
- render: "span",
725
- ...itemIndicatorProps,
726
- ref: forwardedRef,
727
- "data-state": getCheckedState(indicatorContext.checked)
728
- }) : null
729
- });
821
+ const ITEM_INDICATOR_NAME = "MenuItemIndicator";
822
+ const {
823
+ Provider: ItemIndicatorProvider,
824
+ useStyledContext: useItemIndicatorContext
825
+ } = (0, import_web.createStyledContext)();
826
+ const MenuItemIndicator = _Indicator.styleable((props, forwardedRef) => {
827
+ const {
828
+ scope = MENU_CONTEXT,
829
+ forceMount,
830
+ ...itemIndicatorProps
831
+ } = props;
832
+ const indicatorContext = useItemIndicatorContext(scope);
833
+ return /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_animate_presence.AnimatePresence, {
834
+ children: forceMount || isIndeterminate(indicatorContext.checked) || indicatorContext.checked === true ? /* @__PURE__ */(0, import_jsx_runtime.jsx)(_Indicator, {
835
+ componentName: ITEM_INDICATOR_NAME,
836
+ render: "span",
837
+ ...itemIndicatorProps,
838
+ ref: forwardedRef,
839
+ "data-state": getCheckedState(indicatorContext.checked)
840
+ }) : null
730
841
  });
842
+ });
731
843
  MenuItemIndicator.displayName = ITEM_INDICATOR_NAME;
732
- const MenuArrow = React.forwardRef(function (props, forwardedRef) {
733
- const {
734
- scope = MENU_CONTEXT,
735
- unstyled = process.env.TAMAGUI_HEADLESS === "1",
736
- ...rest
737
- } = props;
738
- return /* @__PURE__ */(0, import_jsx_runtime.jsx)(PopperPrimitive.PopperArrow, {
739
- scope,
740
- componentName: "PopperArrow",
741
- ...(!unstyled && {
742
- backgroundColor: "$background"
743
- }),
744
- ...rest,
745
- ref: forwardedRef
746
- });
747
- }),
748
- SUB_NAME = "MenuSub",
749
- {
750
- Provider: MenuSubProvider,
751
- useStyledContext: useMenuSubContext
752
- } = (0, import_web.createStyledContext)(),
753
- MenuSub = props => {
754
- const {
755
- scope = MENU_CONTEXT,
756
- children,
757
- open = !1,
758
- onOpenChange,
759
- allowFlip = {
760
- padding: 10
761
- },
762
- stayInFrame = {
763
- padding: 10
764
- },
765
- ...rest
766
- } = props,
767
- parentMenuContext = useMenuContext(scope),
768
- [trigger, setTrigger] = React.useState(null),
769
- [content, setContent] = React.useState(null),
770
- handleOpenChange = (0, import_use_callback_ref.useCallbackRef)(onOpenChange);
771
- return React.useEffect(() => (parentMenuContext.open === !1 && handleOpenChange(!1), () => handleOpenChange(!1)), [parentMenuContext.open, handleOpenChange]), /* @__PURE__ */(0, import_jsx_runtime.jsx)(PopperPrimitive.Popper, {
772
- allowFlip,
773
- stayInFrame,
774
- ...rest,
844
+ const MenuArrow = React.forwardRef(function MenuArrow2(props, forwardedRef) {
845
+ const {
846
+ scope = MENU_CONTEXT,
847
+ unstyled = process.env.TAMAGUI_HEADLESS === "1",
848
+ ...rest
849
+ } = props;
850
+ return /* @__PURE__ */(0, import_jsx_runtime.jsx)(PopperPrimitive.PopperArrow, {
851
+ scope,
852
+ componentName: "PopperArrow",
853
+ unstyled,
854
+ ...(!unstyled && {
855
+ backgroundColor: "$background"
856
+ }),
857
+ ...rest,
858
+ ref: forwardedRef
859
+ });
860
+ });
861
+ const SUB_NAME = "MenuSub";
862
+ const {
863
+ Provider: MenuSubProvider,
864
+ useStyledContext: useMenuSubContext
865
+ } = (0, import_web.createStyledContext)();
866
+ const MenuSub = props => {
867
+ const isTouchDevice = (0, import_web.useIsTouchDevice)();
868
+ const {
869
+ scope = MENU_CONTEXT
870
+ } = props;
871
+ const rootContext = useMenuRootContext(scope);
872
+ const parentPopperContext = PopperPrimitive.usePopperContext(scope);
873
+ const parentSide = parentPopperContext.placement?.split("-")[0];
874
+ const isNestedSubmenu = parentSide === "left" || parentSide === "right";
875
+ const defaultPlacement = isTouchDevice ? "bottom" : isNestedSubmenu ? `${parentSide}-start` : rootContext.dir === "rtl" ? "left-start" : "right-start";
876
+ const {
877
+ children,
878
+ open = false,
879
+ onOpenChange,
880
+ allowFlip: allowFlipProp = {
881
+ padding: 10
882
+ },
883
+ stayInFrame = {
884
+ padding: 10
885
+ },
886
+ placement = defaultPlacement,
887
+ ...rest
888
+ } = props;
889
+ const allowFlip = React.useMemo(() => {
890
+ if (!isNestedSubmenu || typeof allowFlipProp === "boolean") return allowFlipProp;
891
+ if (allowFlipProp.fallbackPlacements) return allowFlipProp;
892
+ const side = placement.split("-")[0];
893
+ const align = placement.split("-")[1] || "start";
894
+ const otherAlign = align === "start" ? "end" : "start";
895
+ if (side === "left" || side === "right") {
896
+ const oppositeSide = side === "right" ? "left" : "right";
897
+ return {
898
+ ...(typeof allowFlipProp === "object" ? allowFlipProp : {}),
899
+ fallbackPlacements: [`${side}-${otherAlign}`, `${oppositeSide}-${align}`, `${oppositeSide}-${otherAlign}`]
900
+ };
901
+ }
902
+ return allowFlipProp;
903
+ }, [isNestedSubmenu, allowFlipProp, placement]);
904
+ const parentMenuContext = useMenuContext(scope);
905
+ const [trigger, setTrigger] = React.useState(null);
906
+ const [content, setContent] = React.useState(null);
907
+ const handleOpenChange = (0, import_use_callback_ref.useCallbackRef)(onOpenChange);
908
+ React.useEffect(() => {
909
+ if (parentMenuContext.open === false) handleOpenChange(false);
910
+ return () => handleOpenChange(false);
911
+ }, [parentMenuContext.open, handleOpenChange]);
912
+ return /* @__PURE__ */(0, import_jsx_runtime.jsx)(PopperPrimitive.Popper, {
913
+ open,
914
+ placement,
915
+ allowFlip,
916
+ stayInFrame,
917
+ ...rest,
918
+ scope,
919
+ children: /* @__PURE__ */(0, import_jsx_runtime.jsx)(MenuProvider, {
775
920
  scope,
776
- children: /* @__PURE__ */(0, import_jsx_runtime.jsx)(MenuProvider, {
921
+ open,
922
+ onOpenChange: handleOpenChange,
923
+ content,
924
+ onContentChange: setContent,
925
+ children: /* @__PURE__ */(0, import_jsx_runtime.jsx)(MenuSubProvider, {
777
926
  scope,
778
- open,
779
- onOpenChange: handleOpenChange,
780
- content,
781
- onContentChange: setContent,
782
- children: /* @__PURE__ */(0, import_jsx_runtime.jsx)(MenuSubProvider, {
783
- scope,
784
- contentId: (0, import_react.useId)(),
785
- triggerId: (0, import_react.useId)(),
786
- trigger,
787
- onTriggerChange: setTrigger,
788
- children
789
- })
927
+ contentId: (0, import_react.useId)(),
928
+ triggerId: (0, import_react.useId)(),
929
+ trigger,
930
+ onTriggerChange: setTrigger,
931
+ children
790
932
  })
791
- });
792
- };
933
+ })
934
+ });
935
+ };
793
936
  MenuSub.displayName = SUB_NAME;
794
- const SUB_TRIGGER_NAME = "MenuSubTrigger",
795
- MenuSubTrigger = React.forwardRef((props, forwardedRef) => {
796
- const scope = props.scope || MENU_CONTEXT,
797
- context = useMenuContext(scope),
798
- rootContext = useMenuRootContext(scope),
799
- subContext = useMenuSubContext(scope),
800
- contentContext = useMenuContentContext(scope),
801
- popperContext = PopperPrimitive.usePopperContext(scope),
802
- openTimerRef = React.useRef(null),
803
- {
804
- pointerGraceTimerRef,
805
- onPointerGraceIntentChange
806
- } = contentContext,
807
- placementSide = popperContext.placement?.split("-")[0],
808
- effectiveDir = placementSide === "left" ? "rtl" : placementSide === "right" ? "ltr" : rootContext.dir,
809
- clearOpenTimer = React.useCallback(() => {
810
- openTimerRef.current && window.clearTimeout(openTimerRef.current), openTimerRef.current = null;
811
- }, []);
812
- return React.useEffect(() => clearOpenTimer, [clearOpenTimer]), React.useEffect(() => {
813
- const pointerGraceTimer = pointerGraceTimerRef.current;
814
- return () => {
815
- window.clearTimeout(pointerGraceTimer), onPointerGraceIntentChange(null);
816
- };
817
- }, [pointerGraceTimerRef, onPointerGraceIntentChange]), /* @__PURE__ */(0, import_jsx_runtime.jsx)(MenuAnchor, {
818
- componentName: SUB_TRIGGER_NAME,
819
- asChild: "except-style",
820
- scope,
821
- children: /* @__PURE__ */(0, import_jsx_runtime.jsx)(MenuItemImpl, {
822
- id: subContext.triggerId,
823
- "aria-haspopup": "menu",
824
- "aria-expanded": context.open,
825
- "aria-controls": subContext.contentId,
826
- "data-state": getOpenState(context.open),
827
- outlineStyle: "none",
828
- ...props,
829
- ref: (0, import_web.composeRefs)(forwardedRef, subContext.onTriggerChange),
830
- onPress: event => {
831
- props.onPress?.(event), !(props.disabled || event.defaultPrevented) && (import_web.isWeb && event.currentTarget.focus(), context.open || context.onOpenChange(!0));
832
- },
833
- onPointerMove: (0, import_web.composeEventHandlers)(props.onPointerMove,
834
- // @ts-ignore
835
- whenMouse(event => {
836
- contentContext.onItemEnter(event), !event.defaultPrevented && !props.disabled && !context.open && !openTimerRef.current && (contentContext.onPointerGraceIntentChange(null), openTimerRef.current = window.setTimeout(() => {
837
- context.onOpenChange(!0), clearOpenTimer();
838
- }, 100));
839
- })),
840
- onPointerLeave: (0, import_web.composeEventHandlers)(props.onPointerLeave, eventIn => {
841
- const event = eventIn;
842
- clearOpenTimer();
843
- const contentRect = context.content?.getBoundingClientRect();
844
- if (contentRect) {
845
- const contentEl = context.content,
846
- side = (contentEl?.dataset?.side ? contentEl : contentEl?.querySelector("[data-side]"))?.dataset?.side || "right",
847
- rightSide = side === "right",
848
- bleed = rightSide ? -5 : 5,
849
- contentNearEdge = contentRect[rightSide ? "left" : "right"],
850
- contentFarEdge = contentRect[rightSide ? "right" : "left"],
851
- polygon = {
852
- area: [
853
- // Apply a bleed on clientX to ensure that our exit point is
854
- // consistently within polygon bounds
855
- {
856
- x: event.clientX + bleed,
857
- y: event.clientY
858
- }, {
859
- x: contentNearEdge,
860
- y: contentRect.top
861
- }, {
862
- x: contentFarEdge,
863
- y: contentRect.top
864
- }, {
865
- x: contentFarEdge,
866
- y: contentRect.bottom
867
- }, {
868
- x: contentNearEdge,
869
- y: contentRect.bottom
870
- }],
871
- side
872
- };
873
- contentContext.onPointerGraceIntentChange(polygon), window.clearTimeout(pointerGraceTimerRef.current), pointerGraceTimerRef.current = window.setTimeout(() => contentContext.onPointerGraceIntentChange(null), 300);
874
- } else if (import_web.isWeb && subContext.trigger) {
875
- const triggerRect = subContext.trigger?.getBoundingClientRect();
876
- if (triggerRect) {
877
- const placementSide2 = popperContext.placement?.split("-")[0],
878
- side = placementSide2 === "left" || placementSide2 === "right" ? placementSide2 : rootContext.dir === "rtl" ? "left" : "right",
879
- rightSide = side === "right",
880
- bleed = rightSide ? -5 : 5,
881
- nearEdge = rightSide ? triggerRect.right + 4 : triggerRect.left - 4,
882
- farEdge = rightSide ? nearEdge + 200 : nearEdge - 200,
883
- polygon = {
884
- area: [{
885
- x: event.clientX + bleed,
886
- y: event.clientY
887
- }, {
888
- x: nearEdge,
889
- y: triggerRect.top - 50
890
- }, {
891
- x: farEdge,
892
- y: triggerRect.top - 50
893
- }, {
894
- x: farEdge,
895
- y: triggerRect.bottom + 50
896
- }, {
897
- x: nearEdge,
898
- y: triggerRect.bottom + 50
899
- }],
900
- side
901
- };
902
- contentContext.onPointerGraceIntentChange(polygon), window.clearTimeout(pointerGraceTimerRef.current), pointerGraceTimerRef.current = window.setTimeout(() => contentContext.onPointerGraceIntentChange(null), 300);
937
+ const SUB_TRIGGER_NAME = "MenuSubTrigger";
938
+ const MenuSubTrigger = React.forwardRef((props, forwardedRef) => {
939
+ const scope = props.scope || MENU_CONTEXT;
940
+ const context = useMenuContext(scope);
941
+ const rootContext = useMenuRootContext(scope);
942
+ const subContext = useMenuSubContext(scope);
943
+ const contentContext = useMenuContentContext(scope);
944
+ const popperContext = PopperPrimitive.usePopperContext(scope);
945
+ const openTimerRef = React.useRef(null);
946
+ const {
947
+ pointerGraceTimerRef,
948
+ onPointerGraceIntentChange
949
+ } = contentContext;
950
+ const effectiveDir = rootContext.dir;
951
+ const clearOpenTimer = React.useCallback(() => {
952
+ if (openTimerRef.current) window.clearTimeout(openTimerRef.current);
953
+ openTimerRef.current = null;
954
+ }, []);
955
+ React.useEffect(() => clearOpenTimer, [clearOpenTimer]);
956
+ React.useEffect(() => {
957
+ const pointerGraceTimer = pointerGraceTimerRef.current;
958
+ return () => {
959
+ window.clearTimeout(pointerGraceTimer);
960
+ onPointerGraceIntentChange(null);
961
+ };
962
+ }, [pointerGraceTimerRef, onPointerGraceIntentChange]);
963
+ return /* @__PURE__ */(0, import_jsx_runtime.jsx)(MenuAnchor, {
964
+ componentName: SUB_TRIGGER_NAME,
965
+ asChild: "except-style",
966
+ scope,
967
+ children: /* @__PURE__ */(0, import_jsx_runtime.jsx)(MenuItemImpl, {
968
+ id: subContext.triggerId,
969
+ "aria-haspopup": "menu",
970
+ "aria-expanded": context.open,
971
+ "aria-controls": subContext.contentId,
972
+ "data-state": getOpenState(context.open),
973
+ outlineStyle: "none",
974
+ ...props,
975
+ ref: (0, import_web.composeRefs)(forwardedRef, subContext.onTriggerChange),
976
+ onPress: event => {
977
+ props.onPress?.(event);
978
+ if (props.disabled || event.defaultPrevented) return;
979
+ if (import_web.isWeb) {
980
+ event.currentTarget.focus();
981
+ }
982
+ if (!context.open) context.onOpenChange(true);
983
+ },
984
+ onPointerMove: (0, import_web.composeEventHandlers)(props.onPointerMove,
985
+ // @ts-ignore
986
+ whenMouse(event => {
987
+ contentContext.onItemEnter(event);
988
+ if (event.defaultPrevented) return;
989
+ if (!props.disabled && !context.open && !openTimerRef.current) {
990
+ contentContext.onPointerGraceIntentChange(null);
991
+ openTimerRef.current = window.setTimeout(() => {
992
+ context.onOpenChange(true);
993
+ clearOpenTimer();
994
+ }, 100);
995
+ }
996
+ })),
997
+ onPointerLeave: (0, import_web.composeEventHandlers)(props.onPointerLeave, eventIn => {
998
+ const event = eventIn;
999
+ clearOpenTimer();
1000
+ const contentRect = context.content?.getBoundingClientRect();
1001
+ if (contentRect) {
1002
+ const contentEl = context.content;
1003
+ const sideEl = contentEl?.dataset?.side ? contentEl : contentEl?.querySelector("[data-side]");
1004
+ const side = sideEl?.dataset?.side || "right";
1005
+ const rightSide = side === "right";
1006
+ const bleed = rightSide ? -5 : 5;
1007
+ const contentNearEdge = contentRect[rightSide ? "left" : "right"];
1008
+ const contentFarEdge = contentRect[rightSide ? "right" : "left"];
1009
+ const polygon = {
1010
+ area: [
1011
+ // Apply a bleed on clientX to ensure that our exit point is
1012
+ // consistently within polygon bounds
1013
+ {
1014
+ x: event.clientX + bleed,
1015
+ y: event.clientY
1016
+ }, {
1017
+ x: contentNearEdge,
1018
+ y: contentRect.top
1019
+ }, {
1020
+ x: contentFarEdge,
1021
+ y: contentRect.top
1022
+ }, {
1023
+ x: contentFarEdge,
1024
+ y: contentRect.bottom
1025
+ }, {
1026
+ x: contentNearEdge,
1027
+ y: contentRect.bottom
1028
+ }],
1029
+ side
1030
+ };
1031
+ contentContext.onPointerGraceIntentChange(polygon);
1032
+ window.clearTimeout(pointerGraceTimerRef.current);
1033
+ pointerGraceTimerRef.current = window.setTimeout(() => contentContext.onPointerGraceIntentChange(null), 300);
1034
+ } else if (import_web.isWeb && subContext.trigger) {
1035
+ const triggerEl = subContext.trigger;
1036
+ const triggerRect = triggerEl?.getBoundingClientRect();
1037
+ if (triggerRect) {
1038
+ const placementSide = popperContext.placement?.split("-")[0];
1039
+ const side = placementSide === "left" || placementSide === "right" ? placementSide : rootContext.dir === "rtl" ? "left" : "right";
1040
+ const rightSide = side === "right";
1041
+ const bleed = rightSide ? -5 : 5;
1042
+ const nearEdge = rightSide ? triggerRect.right + 4 : triggerRect.left - 4;
1043
+ const farEdge = rightSide ? nearEdge + 200 : nearEdge - 200;
1044
+ const polygon = {
1045
+ area: [{
1046
+ x: event.clientX + bleed,
1047
+ y: event.clientY
1048
+ }, {
1049
+ x: nearEdge,
1050
+ y: triggerRect.top - 50
1051
+ }, {
1052
+ x: farEdge,
1053
+ y: triggerRect.top - 50
1054
+ }, {
1055
+ x: farEdge,
1056
+ y: triggerRect.bottom + 50
1057
+ }, {
1058
+ x: nearEdge,
1059
+ y: triggerRect.bottom + 50
1060
+ }],
1061
+ side
1062
+ };
1063
+ contentContext.onPointerGraceIntentChange(polygon);
1064
+ window.clearTimeout(pointerGraceTimerRef.current);
1065
+ pointerGraceTimerRef.current = window.setTimeout(() => contentContext.onPointerGraceIntentChange(null), 300);
1066
+ }
1067
+ } else {
1068
+ contentContext.onTriggerLeave(event);
1069
+ if (event.defaultPrevented) return;
1070
+ contentContext.onPointerGraceIntentChange(null);
1071
+ }
1072
+ }),
1073
+ ...(import_web.isWeb ? {
1074
+ onKeyDown: (0, import_web.composeEventHandlers)(props.onKeyDown, event => {
1075
+ const isTypingAhead = contentContext.searchRef.current !== "";
1076
+ if (props.disabled || isTypingAhead && event.key === " ") return;
1077
+ const willOpen = SUB_OPEN_KEYS[effectiveDir].includes(event.key);
1078
+ if (willOpen) {
1079
+ if (context.open && context.content) {
1080
+ const contentEl = context.content;
1081
+ const firstItem = contentEl.querySelector?.('[role="menuitem"]:not([data-disabled])');
1082
+ if (firstItem) {
1083
+ firstItem.focus({
1084
+ focusVisible: true
1085
+ });
1086
+ event.preventDefault();
1087
+ return;
1088
+ }
903
1089
  }
904
- } else {
905
- if (contentContext.onTriggerLeave(event), event.defaultPrevented) return;
906
- contentContext.onPointerGraceIntentChange(null);
1090
+ const triggerEl = event.currentTarget;
1091
+ popperContext.refs?.setReference(triggerEl);
1092
+ context.onOpenChange(true);
1093
+ requestAnimationFrame(() => {
1094
+ popperContext.update?.();
1095
+ });
1096
+ context.content?.focus({
1097
+ focusVisible: true
1098
+ });
1099
+ event.preventDefault();
1100
+ }
1101
+ })
1102
+ } : null)
1103
+ })
1104
+ });
1105
+ });
1106
+ MenuSubTrigger.displayName = SUB_TRIGGER_NAME;
1107
+ const SUB_CONTENT_NAME = "MenuSubContent";
1108
+ const MenuSubContentFrame = (0, import_web.styled)(PopperPrimitive.PopperContentFrame, {
1109
+ name: SUB_CONTENT_NAME
1110
+ });
1111
+ const MenuSubContent = MenuSubContentFrame.styleable((props, forwardedRef) => {
1112
+ const scope = props.scope || MENU_CONTEXT;
1113
+ const portalContext = usePortalContext(scope);
1114
+ const {
1115
+ forceMount = portalContext.forceMount,
1116
+ ...subContentProps
1117
+ } = props;
1118
+ const context = useMenuContext(scope);
1119
+ const rootContext = useMenuRootContext(scope);
1120
+ const subContext = useMenuSubContext(scope);
1121
+ const popperContext = PopperPrimitive.usePopperContext(scope);
1122
+ const ref = React.useRef(null);
1123
+ const composedRefs = (0, import_web.useComposedRefs)(forwardedRef, ref);
1124
+ const placementSide = popperContext.placement?.split("-")[0];
1125
+ const dataSide = placementSide === "left" || placementSide === "right" ? placementSide : rootContext.dir === "rtl" ? "left" : "right";
1126
+ const effectiveDir = rootContext.dir;
1127
+ return /* @__PURE__ */(0, import_jsx_runtime.jsx)(Collection.Provider, {
1128
+ scope,
1129
+ children: /* @__PURE__ */(0, import_jsx_runtime.jsx)(Collection.Slot, {
1130
+ scope,
1131
+ children: /* @__PURE__ */(0, import_jsx_runtime.jsx)(MenuContentImpl, {
1132
+ id: subContext.contentId,
1133
+ "aria-labelledby": subContext.triggerId,
1134
+ ...subContentProps,
1135
+ ref: composedRefs,
1136
+ "data-side": dataSide,
1137
+ disableOutsidePointerEvents: false,
1138
+ disableOutsideScroll: false,
1139
+ trapFocus: false,
1140
+ onOpenAutoFocus: event => {
1141
+ if (rootContext.isUsingKeyboardRef.current) {
1142
+ const root = ref.current;
1143
+ const content = root?.querySelector?.("[data-tamagui-menu-content]");
1144
+ (content || root)?.focus({
1145
+ preventScroll: true
1146
+ });
907
1147
  }
1148
+ event.preventDefault();
1149
+ },
1150
+ onCloseAutoFocus: event => event.preventDefault(),
1151
+ onFocusOutside: (0, import_web.composeEventHandlers)(props.onFocusOutside, event => {
1152
+ if (event.target !== subContext.trigger) context.onOpenChange(false);
1153
+ }),
1154
+ onEscapeKeyDown: (0, import_web.composeEventHandlers)(props.onEscapeKeyDown, event => {
1155
+ context.onOpenChange(false);
1156
+ subContext.trigger?.focus({
1157
+ focusVisible: true
1158
+ });
1159
+ event.preventDefault();
908
1160
  }),
909
1161
  ...(import_web.isWeb ? {
910
1162
  onKeyDown: (0, import_web.composeEventHandlers)(props.onKeyDown, event => {
911
- const isTypingAhead = contentContext.searchRef.current !== "";
912
- if (props.disabled || isTypingAhead && event.key === " ") return;
913
- if (SUB_OPEN_KEYS[effectiveDir].includes(event.key)) {
914
- if (context.open && context.content) {
915
- const firstItem = context.content.querySelector?.('[role="menuitem"]:not([data-disabled])');
916
- if (firstItem) {
917
- firstItem.focus({
918
- focusVisible: !0
919
- }), event.preventDefault();
920
- return;
921
- }
922
- }
923
- const triggerEl = event.currentTarget;
924
- popperContext.refs?.setReference(triggerEl), context.onOpenChange(!0), requestAnimationFrame(() => {
925
- popperContext.update?.();
926
- }), context.content?.focus({
927
- focusVisible: !0
928
- }), event.preventDefault();
1163
+ const isKeyDownInside = event.currentTarget.contains(event.target);
1164
+ const isCloseKey = SUB_CLOSE_KEYS[effectiveDir].includes(event.key);
1165
+ if (isKeyDownInside && isCloseKey) {
1166
+ context.onOpenChange(false);
1167
+ subContext.trigger?.focus({
1168
+ focusVisible: true
1169
+ });
1170
+ event.preventDefault();
929
1171
  }
930
1172
  })
931
1173
  } : null)
932
1174
  })
933
- });
934
- });
935
- MenuSubTrigger.displayName = SUB_TRIGGER_NAME;
936
- const SUB_CONTENT_NAME = "MenuSubContent",
937
- MenuSubContent = React.forwardRef((props, forwardedRef) => {
938
- const scope = props.scope || MENU_CONTEXT,
939
- portalContext = usePortalContext(scope),
940
- {
941
- forceMount = portalContext.forceMount,
942
- ...subContentProps
943
- } = props,
944
- context = useMenuContext(scope),
945
- rootContext = useMenuRootContext(scope),
946
- subContext = useMenuSubContext(scope),
947
- popperContext = PopperPrimitive.usePopperContext(scope),
948
- ref = React.useRef(null),
949
- composedRefs = (0, import_web.useComposedRefs)(forwardedRef, ref),
950
- placementSide = popperContext.placement?.split("-")[0],
951
- dataSide = placementSide === "left" || placementSide === "right" ? placementSide : rootContext.dir === "rtl" ? "left" : "right",
952
- effectiveDir = placementSide === "left" ? "rtl" : placementSide === "right" ? "ltr" : rootContext.dir;
953
- return /* @__PURE__ */(0, import_jsx_runtime.jsx)(Collection.Provider, {
954
- scope,
955
- children: /* @__PURE__ */(0, import_jsx_runtime.jsx)(Collection.Slot, {
956
- scope,
957
- children: /* @__PURE__ */(0, import_jsx_runtime.jsx)(MenuContentImpl, {
958
- id: subContext.contentId,
959
- "aria-labelledby": subContext.triggerId,
960
- ...subContentProps,
961
- ref: composedRefs,
962
- "data-side": dataSide,
963
- disableOutsidePointerEvents: !1,
964
- disableOutsideScroll: !1,
965
- trapFocus: !1,
966
- onOpenAutoFocus: event => {
967
- rootContext.isUsingKeyboardRef.current && document.querySelector("[data-tamagui-menu-content][data-side]")?.focus(), event.preventDefault();
968
- },
969
- onCloseAutoFocus: event => event.preventDefault(),
970
- onFocusOutside: (0, import_web.composeEventHandlers)(props.onFocusOutside, event => {
971
- event.target !== subContext.trigger && context.onOpenChange(!1);
972
- }),
973
- onEscapeKeyDown: (0, import_web.composeEventHandlers)(props.onEscapeKeyDown, event => {
974
- context.onOpenChange(!1), subContext.trigger?.focus({
975
- focusVisible: !0
976
- }), event.preventDefault();
977
- }),
978
- ...(import_web.isWeb ? {
979
- onKeyDown: (0, import_web.composeEventHandlers)(props.onKeyDown, event => {
980
- const isKeyDownInside = event.currentTarget.contains(event.target),
981
- isCloseKey = SUB_CLOSE_KEYS[effectiveDir].includes(event.key);
982
- isKeyDownInside && isCloseKey && (context.onOpenChange(!1), subContext.trigger?.focus({
983
- focusVisible: !0
984
- }), event.preventDefault());
985
- })
986
- } : null)
987
- })
988
- })
989
- });
1175
+ })
990
1176
  });
1177
+ });
991
1178
  MenuSubContent.displayName = SUB_CONTENT_NAME;
992
- const Anchor = MenuAnchor,
993
- Portal = MenuPortal,
994
- Content = MenuContent,
995
- Group = _MenuGroup.styleable((props, ref) => /* @__PURE__ */(0, import_jsx_runtime.jsx)(_MenuGroup, {
1179
+ const Anchor = MenuAnchor;
1180
+ const Portal = MenuPortal;
1181
+ const Content = MenuContent;
1182
+ const Group = _MenuGroup.styleable((props, ref) => {
1183
+ return /* @__PURE__ */(0, import_jsx_runtime.jsx)(_MenuGroup, {
996
1184
  ...props,
997
1185
  ref
998
- }));
1186
+ });
1187
+ });
999
1188
  Group.displayName = "MenuGroup";
1000
- const Label = _Label.styleable((props, ref) => /* @__PURE__ */(0, import_jsx_runtime.jsx)(_Label, {
1001
- ...props,
1002
- ref
1003
- }));
1189
+ const Label = _Label.styleable((props, ref) => {
1190
+ return /* @__PURE__ */(0, import_jsx_runtime.jsx)(_Label, {
1191
+ ...props,
1192
+ ref
1193
+ });
1194
+ });
1004
1195
  Label.displayName = "MenuLabel";
1005
- const Item = MenuItem,
1006
- CheckboxItem = MenuCheckboxItem,
1007
- RadioGroup = MenuRadioGroup,
1008
- RadioItem = MenuRadioItem,
1009
- ItemIndicator = MenuItemIndicator,
1010
- Separator = _Separator.styleable((props, ref) => /* @__PURE__ */(0, import_jsx_runtime.jsx)(_Separator, {
1196
+ const Item = MenuItem;
1197
+ const CheckboxItem = MenuCheckboxItem;
1198
+ const RadioGroup = MenuRadioGroup;
1199
+ const RadioItem = MenuRadioItem;
1200
+ const ItemIndicator = MenuItemIndicator;
1201
+ const Separator = _Separator.styleable((props, ref) => {
1202
+ return /* @__PURE__ */(0, import_jsx_runtime.jsx)(_Separator, {
1011
1203
  ...props,
1012
1204
  ref
1013
- }));
1014
- return Separator.displayName = "MenuSeparator", {
1015
- Menu: (0, import_web.withStaticProperties)(MenuComp, {
1016
- Anchor,
1017
- Portal,
1018
- Content,
1019
- Group,
1020
- Label,
1021
- Item,
1022
- CheckboxItem,
1023
- RadioGroup,
1024
- RadioItem,
1025
- ItemIndicator,
1026
- Separator,
1027
- Arrow: MenuArrow,
1028
- Sub: MenuSub,
1029
- SubTrigger: MenuSubTrigger,
1030
- SubContent: MenuSubContent,
1031
- ItemTitle: MenuItemTitle,
1032
- ItemSubtitle: MenuItemSubTitle,
1033
- ItemImage: MenuItemImage,
1034
- ItemIcon: MenuItemIcon
1035
- })
1205
+ });
1206
+ });
1207
+ Separator.displayName = "MenuSeparator";
1208
+ const Arrow = MenuArrow;
1209
+ const Sub = MenuSub;
1210
+ const SubTrigger = MenuSubTrigger;
1211
+ const SubContent = MenuSubContent;
1212
+ const ItemTitle = MenuItemTitle;
1213
+ const ItemSubtitle = MenuItemSubTitle;
1214
+ const ItemImage = MenuItemImage;
1215
+ const ItemIcon = MenuItemIcon;
1216
+ const Menu = (0, import_web.withStaticProperties)(MenuComp, {
1217
+ Anchor,
1218
+ Portal,
1219
+ Content,
1220
+ Group,
1221
+ Label,
1222
+ Item,
1223
+ CheckboxItem,
1224
+ RadioGroup,
1225
+ RadioItem,
1226
+ ItemIndicator,
1227
+ Separator,
1228
+ Arrow,
1229
+ Sub,
1230
+ SubTrigger,
1231
+ SubContent,
1232
+ ItemTitle,
1233
+ ItemSubtitle,
1234
+ ItemImage,
1235
+ ItemIcon
1236
+ });
1237
+ return {
1238
+ Menu
1036
1239
  };
1037
1240
  }
1038
1241
  function getOpenState(open) {
@@ -1046,18 +1249,25 @@ function getCheckedState(checked) {
1046
1249
  }
1047
1250
  function focusFirst(candidates, options) {
1048
1251
  const PREVIOUSLY_FOCUSED_ELEMENT = document.activeElement;
1049
- for (const candidate of candidates) if (candidate === PREVIOUSLY_FOCUSED_ELEMENT || (candidate.focus({
1050
- focusVisible: options?.focusVisible
1051
- }), document.activeElement !== PREVIOUSLY_FOCUSED_ELEMENT)) return;
1252
+ for (const candidate of candidates) {
1253
+ if (candidate === PREVIOUSLY_FOCUSED_ELEMENT) return;
1254
+ candidate.focus({
1255
+ preventScroll: true,
1256
+ focusVisible: options?.focusVisible
1257
+ });
1258
+ if (document.activeElement !== PREVIOUSLY_FOCUSED_ELEMENT) return;
1259
+ }
1052
1260
  }
1053
1261
  function wrapArray(array, startIndex) {
1054
1262
  return array.map((_, index) => array[(startIndex + index) % array.length]);
1055
1263
  }
1056
1264
  function getNextMatch(values, search, currentMatch) {
1057
- const normalizedSearch = search.length > 1 && Array.from(search).every(char => char === search[0]) ? search[0] : search,
1058
- currentMatchIndex = currentMatch ? values.indexOf(currentMatch) : -1;
1265
+ const isRepeated = search.length > 1 && Array.from(search).every(char => char === search[0]);
1266
+ const normalizedSearch = isRepeated ? search[0] : search;
1267
+ const currentMatchIndex = currentMatch ? values.indexOf(currentMatch) : -1;
1059
1268
  let wrappedValues = wrapArray(values, Math.max(currentMatchIndex, 0));
1060
- normalizedSearch.length === 1 && (wrappedValues = wrappedValues.filter(v => v !== currentMatch));
1269
+ const excludeCurrentMatch = normalizedSearch.length === 1;
1270
+ if (excludeCurrentMatch) wrappedValues = wrappedValues.filter(v => v !== currentMatch);
1061
1271
  const nextMatch = wrappedValues.find(value => value.toLowerCase().startsWith(normalizedSearch.toLowerCase()));
1062
1272
  return nextMatch !== currentMatch ? nextMatch : void 0;
1063
1273
  }
@@ -1066,18 +1276,19 @@ function isPointInPolygon(point, polygon) {
1066
1276
  x,
1067
1277
  y
1068
1278
  } = point;
1069
- let inside = !1;
1279
+ let inside = false;
1070
1280
  for (let i = 0, j = polygon.length - 1; i < polygon.length; j = i++) {
1071
- const xi = polygon[i].x,
1072
- yi = polygon[i].y,
1073
- xj = polygon[j].x,
1074
- yj = polygon[j].y;
1075
- yi > y != yj > y && x < (xj - xi) * (y - yi) / (yj - yi) + xi && (inside = !inside);
1281
+ const xi = polygon[i].x;
1282
+ const yi = polygon[i].y;
1283
+ const xj = polygon[j].x;
1284
+ const yj = polygon[j].y;
1285
+ const intersect = yi > y !== yj > y && x < (xj - xi) * (y - yi) / (yj - yi) + xi;
1286
+ if (intersect) inside = !inside;
1076
1287
  }
1077
1288
  return inside;
1078
1289
  }
1079
1290
  function isPointerInGraceArea(event, area) {
1080
- if (!area) return !1;
1291
+ if (!area) return false;
1081
1292
  const cursorPos = {
1082
1293
  x: event.clientX,
1083
1294
  y: event.clientY