@radix-ui/react-navigation-menu 1.1.5-rc.9 → 1.2.0-rc.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +60 -48
- package/dist/index.d.ts +60 -48
- package/dist/index.js +733 -824
- package/dist/index.js.map +7 -1
- package/dist/index.mjs +732 -809
- package/dist/index.mjs.map +7 -1
- package/package.json +15 -16
- package/dist/index.d.ts.map +0 -1
package/dist/index.mjs
CHANGED
|
@@ -1,879 +1,802 @@
|
|
|
1
|
-
|
|
2
|
-
import
|
|
3
|
-
import
|
|
4
|
-
import {createContextScope
|
|
5
|
-
import {composeEventHandlers
|
|
6
|
-
import {
|
|
7
|
-
import {useControllableState
|
|
8
|
-
import {
|
|
9
|
-
import {useDirection
|
|
10
|
-
import {Presence
|
|
11
|
-
import {useId
|
|
12
|
-
import {createCollection
|
|
13
|
-
import {DismissableLayer
|
|
14
|
-
import {usePrevious
|
|
15
|
-
import {useLayoutEffect
|
|
16
|
-
import {useCallbackRef
|
|
17
|
-
import
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
const [
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
const
|
|
46
|
-
const
|
|
47
|
-
const
|
|
48
|
-
const
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
window.clearTimeout(skipDelayTimerRef.current);
|
|
67
|
-
skipDelayTimerRef.current = window.setTimeout(()=>setIsOpenDelayed(true)
|
|
68
|
-
, skipDelayDuration);
|
|
69
|
-
}
|
|
70
|
-
onValueChange === null || onValueChange === void 0 || onValueChange(value);
|
|
71
|
-
},
|
|
72
|
-
defaultProp: defaultValue
|
|
1
|
+
// packages/react/navigation-menu/src/NavigationMenu.tsx
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
import ReactDOM from "react-dom";
|
|
4
|
+
import { createContextScope } from "@radix-ui/react-context";
|
|
5
|
+
import { composeEventHandlers } from "@radix-ui/primitive";
|
|
6
|
+
import { Primitive, dispatchDiscreteCustomEvent } from "@radix-ui/react-primitive";
|
|
7
|
+
import { useControllableState } from "@radix-ui/react-use-controllable-state";
|
|
8
|
+
import { composeRefs, useComposedRefs } from "@radix-ui/react-compose-refs";
|
|
9
|
+
import { useDirection } from "@radix-ui/react-direction";
|
|
10
|
+
import { Presence } from "@radix-ui/react-presence";
|
|
11
|
+
import { useId } from "@radix-ui/react-id";
|
|
12
|
+
import { createCollection } from "@radix-ui/react-collection";
|
|
13
|
+
import { DismissableLayer } from "@radix-ui/react-dismissable-layer";
|
|
14
|
+
import { usePrevious } from "@radix-ui/react-use-previous";
|
|
15
|
+
import { useLayoutEffect } from "@radix-ui/react-use-layout-effect";
|
|
16
|
+
import { useCallbackRef } from "@radix-ui/react-use-callback-ref";
|
|
17
|
+
import * as VisuallyHiddenPrimitive from "@radix-ui/react-visually-hidden";
|
|
18
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
19
|
+
var NAVIGATION_MENU_NAME = "NavigationMenu";
|
|
20
|
+
var [Collection, useCollection, createCollectionScope] = createCollection(NAVIGATION_MENU_NAME);
|
|
21
|
+
var [FocusGroupCollection, useFocusGroupCollection, createFocusGroupCollectionScope] = createCollection(NAVIGATION_MENU_NAME);
|
|
22
|
+
var [createNavigationMenuContext, createNavigationMenuScope] = createContextScope(
|
|
23
|
+
NAVIGATION_MENU_NAME,
|
|
24
|
+
[createCollectionScope, createFocusGroupCollectionScope]
|
|
25
|
+
);
|
|
26
|
+
var [NavigationMenuProviderImpl, useNavigationMenuContext] = createNavigationMenuContext(NAVIGATION_MENU_NAME);
|
|
27
|
+
var [ViewportContentProvider, useViewportContentContext] = createNavigationMenuContext(NAVIGATION_MENU_NAME);
|
|
28
|
+
var NavigationMenu = React.forwardRef(
|
|
29
|
+
(props, forwardedRef) => {
|
|
30
|
+
const {
|
|
31
|
+
__scopeNavigationMenu,
|
|
32
|
+
value: valueProp,
|
|
33
|
+
onValueChange,
|
|
34
|
+
defaultValue,
|
|
35
|
+
delayDuration = 200,
|
|
36
|
+
skipDelayDuration = 300,
|
|
37
|
+
orientation = "horizontal",
|
|
38
|
+
dir,
|
|
39
|
+
...NavigationMenuProps
|
|
40
|
+
} = props;
|
|
41
|
+
const [navigationMenu, setNavigationMenu] = React.useState(null);
|
|
42
|
+
const composedRef = useComposedRefs(forwardedRef, (node) => setNavigationMenu(node));
|
|
43
|
+
const direction = useDirection(dir);
|
|
44
|
+
const openTimerRef = React.useRef(0);
|
|
45
|
+
const closeTimerRef = React.useRef(0);
|
|
46
|
+
const skipDelayTimerRef = React.useRef(0);
|
|
47
|
+
const [isOpenDelayed, setIsOpenDelayed] = React.useState(true);
|
|
48
|
+
const [value = "", setValue] = useControllableState({
|
|
49
|
+
prop: valueProp,
|
|
50
|
+
onChange: (value2) => {
|
|
51
|
+
const isOpen = value2 !== "";
|
|
52
|
+
const hasSkipDelayDuration = skipDelayDuration > 0;
|
|
53
|
+
if (isOpen) {
|
|
54
|
+
window.clearTimeout(skipDelayTimerRef.current);
|
|
55
|
+
if (hasSkipDelayDuration) setIsOpenDelayed(false);
|
|
56
|
+
} else {
|
|
57
|
+
window.clearTimeout(skipDelayTimerRef.current);
|
|
58
|
+
skipDelayTimerRef.current = window.setTimeout(
|
|
59
|
+
() => setIsOpenDelayed(true),
|
|
60
|
+
skipDelayDuration
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
onValueChange?.(value2);
|
|
64
|
+
},
|
|
65
|
+
defaultProp: defaultValue
|
|
73
66
|
});
|
|
74
|
-
const startCloseTimer =
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
]);
|
|
81
|
-
const handleOpen = $yHMN2$useCallback((itemValue)=>{
|
|
67
|
+
const startCloseTimer = React.useCallback(() => {
|
|
68
|
+
window.clearTimeout(closeTimerRef.current);
|
|
69
|
+
closeTimerRef.current = window.setTimeout(() => setValue(""), 150);
|
|
70
|
+
}, [setValue]);
|
|
71
|
+
const handleOpen = React.useCallback(
|
|
72
|
+
(itemValue) => {
|
|
82
73
|
window.clearTimeout(closeTimerRef.current);
|
|
83
74
|
setValue(itemValue);
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
const handleDelayedOpen =
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
else
|
|
75
|
+
},
|
|
76
|
+
[setValue]
|
|
77
|
+
);
|
|
78
|
+
const handleDelayedOpen = React.useCallback(
|
|
79
|
+
(itemValue) => {
|
|
80
|
+
const isOpenItem = value === itemValue;
|
|
81
|
+
if (isOpenItem) {
|
|
82
|
+
window.clearTimeout(closeTimerRef.current);
|
|
83
|
+
} else {
|
|
84
|
+
openTimerRef.current = window.setTimeout(() => {
|
|
93
85
|
window.clearTimeout(closeTimerRef.current);
|
|
94
86
|
setValue(itemValue);
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
};
|
|
87
|
+
}, delayDuration);
|
|
88
|
+
}
|
|
89
|
+
},
|
|
90
|
+
[value, setValue, delayDuration]
|
|
91
|
+
);
|
|
92
|
+
React.useEffect(() => {
|
|
93
|
+
return () => {
|
|
94
|
+
window.clearTimeout(openTimerRef.current);
|
|
95
|
+
window.clearTimeout(closeTimerRef.current);
|
|
96
|
+
window.clearTimeout(skipDelayTimerRef.current);
|
|
97
|
+
};
|
|
107
98
|
}, []);
|
|
108
|
-
return
|
|
99
|
+
return /* @__PURE__ */ jsx(
|
|
100
|
+
NavigationMenuProvider,
|
|
101
|
+
{
|
|
109
102
|
scope: __scopeNavigationMenu,
|
|
110
103
|
isRootMenu: true,
|
|
111
|
-
value
|
|
104
|
+
value,
|
|
112
105
|
dir: direction,
|
|
113
|
-
orientation
|
|
106
|
+
orientation,
|
|
114
107
|
rootNavigationMenu: navigationMenu,
|
|
115
|
-
onTriggerEnter: (itemValue)=>{
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
108
|
+
onTriggerEnter: (itemValue) => {
|
|
109
|
+
window.clearTimeout(openTimerRef.current);
|
|
110
|
+
if (isOpenDelayed) handleDelayedOpen(itemValue);
|
|
111
|
+
else handleOpen(itemValue);
|
|
119
112
|
},
|
|
120
|
-
onTriggerLeave: ()=>{
|
|
121
|
-
|
|
122
|
-
|
|
113
|
+
onTriggerLeave: () => {
|
|
114
|
+
window.clearTimeout(openTimerRef.current);
|
|
115
|
+
startCloseTimer();
|
|
123
116
|
},
|
|
124
|
-
onContentEnter: ()=>window.clearTimeout(closeTimerRef.current)
|
|
125
|
-
,
|
|
117
|
+
onContentEnter: () => window.clearTimeout(closeTimerRef.current),
|
|
126
118
|
onContentLeave: startCloseTimer,
|
|
127
|
-
onItemSelect: (itemValue)=>{
|
|
128
|
-
|
|
129
|
-
);
|
|
119
|
+
onItemSelect: (itemValue) => {
|
|
120
|
+
setValue((prevValue) => prevValue === itemValue ? "" : itemValue);
|
|
130
121
|
},
|
|
131
|
-
onItemDismiss: ()=>setValue(
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
122
|
+
onItemDismiss: () => setValue(""),
|
|
123
|
+
children: /* @__PURE__ */ jsx(
|
|
124
|
+
Primitive.nav,
|
|
125
|
+
{
|
|
126
|
+
"aria-label": "Main",
|
|
127
|
+
"data-orientation": orientation,
|
|
128
|
+
dir: direction,
|
|
129
|
+
...NavigationMenuProps,
|
|
130
|
+
ref: composedRef
|
|
131
|
+
}
|
|
132
|
+
)
|
|
133
|
+
}
|
|
134
|
+
);
|
|
135
|
+
}
|
|
136
|
+
);
|
|
137
|
+
NavigationMenu.displayName = NAVIGATION_MENU_NAME;
|
|
138
|
+
var SUB_NAME = "NavigationMenuSub";
|
|
139
|
+
var NavigationMenuSub = React.forwardRef(
|
|
140
|
+
(props, forwardedRef) => {
|
|
141
|
+
const {
|
|
142
|
+
__scopeNavigationMenu,
|
|
143
|
+
value: valueProp,
|
|
144
|
+
onValueChange,
|
|
145
|
+
defaultValue,
|
|
146
|
+
orientation = "horizontal",
|
|
147
|
+
...subProps
|
|
148
|
+
} = props;
|
|
149
|
+
const context = useNavigationMenuContext(SUB_NAME, __scopeNavigationMenu);
|
|
150
|
+
const [value = "", setValue] = useControllableState({
|
|
151
|
+
prop: valueProp,
|
|
152
|
+
onChange: onValueChange,
|
|
153
|
+
defaultProp: defaultValue
|
|
153
154
|
});
|
|
154
|
-
return
|
|
155
|
+
return /* @__PURE__ */ jsx(
|
|
156
|
+
NavigationMenuProvider,
|
|
157
|
+
{
|
|
155
158
|
scope: __scopeNavigationMenu,
|
|
156
159
|
isRootMenu: false,
|
|
157
|
-
value
|
|
160
|
+
value,
|
|
158
161
|
dir: context.dir,
|
|
159
|
-
orientation
|
|
162
|
+
orientation,
|
|
160
163
|
rootNavigationMenu: context.rootNavigationMenu,
|
|
161
|
-
onTriggerEnter: (itemValue)=>setValue(itemValue)
|
|
162
|
-
,
|
|
163
|
-
|
|
164
|
-
,
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
164
|
+
onTriggerEnter: (itemValue) => setValue(itemValue),
|
|
165
|
+
onItemSelect: (itemValue) => setValue(itemValue),
|
|
166
|
+
onItemDismiss: () => setValue(""),
|
|
167
|
+
children: /* @__PURE__ */ jsx(Primitive.div, { "data-orientation": orientation, ...subProps, ref: forwardedRef })
|
|
168
|
+
}
|
|
169
|
+
);
|
|
170
|
+
}
|
|
171
|
+
);
|
|
172
|
+
NavigationMenuSub.displayName = SUB_NAME;
|
|
173
|
+
var NavigationMenuProvider = (props) => {
|
|
174
|
+
const {
|
|
175
|
+
scope,
|
|
176
|
+
isRootMenu,
|
|
177
|
+
rootNavigationMenu,
|
|
178
|
+
dir,
|
|
179
|
+
orientation,
|
|
180
|
+
children,
|
|
181
|
+
value,
|
|
182
|
+
onItemSelect,
|
|
183
|
+
onItemDismiss,
|
|
184
|
+
onTriggerEnter,
|
|
185
|
+
onTriggerLeave,
|
|
186
|
+
onContentEnter,
|
|
187
|
+
onContentLeave
|
|
188
|
+
} = props;
|
|
189
|
+
const [viewport, setViewport] = React.useState(null);
|
|
190
|
+
const [viewportContent, setViewportContent] = React.useState(/* @__PURE__ */ new Map());
|
|
191
|
+
const [indicatorTrack, setIndicatorTrack] = React.useState(null);
|
|
192
|
+
return /* @__PURE__ */ jsx(
|
|
193
|
+
NavigationMenuProviderImpl,
|
|
194
|
+
{
|
|
195
|
+
scope,
|
|
196
|
+
isRootMenu,
|
|
197
|
+
rootNavigationMenu,
|
|
198
|
+
value,
|
|
199
|
+
previousValue: usePrevious(value),
|
|
200
|
+
baseId: useId(),
|
|
201
|
+
dir,
|
|
202
|
+
orientation,
|
|
203
|
+
viewport,
|
|
204
|
+
onViewportChange: setViewport,
|
|
205
|
+
indicatorTrack,
|
|
206
|
+
onIndicatorTrackChange: setIndicatorTrack,
|
|
207
|
+
onTriggerEnter: useCallbackRef(onTriggerEnter),
|
|
208
|
+
onTriggerLeave: useCallbackRef(onTriggerLeave),
|
|
209
|
+
onContentEnter: useCallbackRef(onContentEnter),
|
|
210
|
+
onContentLeave: useCallbackRef(onContentLeave),
|
|
211
|
+
onItemSelect: useCallbackRef(onItemSelect),
|
|
212
|
+
onItemDismiss: useCallbackRef(onItemDismiss),
|
|
213
|
+
onViewportContentChange: React.useCallback((contentValue, contentData) => {
|
|
214
|
+
setViewportContent((prevContent) => {
|
|
215
|
+
prevContent.set(contentValue, contentData);
|
|
216
|
+
return new Map(prevContent);
|
|
217
|
+
});
|
|
218
|
+
}, []),
|
|
219
|
+
onViewportContentRemove: React.useCallback((contentValue) => {
|
|
220
|
+
setViewportContent((prevContent) => {
|
|
221
|
+
if (!prevContent.has(contentValue)) return prevContent;
|
|
222
|
+
prevContent.delete(contentValue);
|
|
223
|
+
return new Map(prevContent);
|
|
224
|
+
});
|
|
225
|
+
}, []),
|
|
226
|
+
children: /* @__PURE__ */ jsx(Collection.Provider, { scope, children: /* @__PURE__ */ jsx(ViewportContentProvider, { scope, items: viewportContent, children }) })
|
|
227
|
+
}
|
|
228
|
+
);
|
|
218
229
|
};
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
const
|
|
223
|
-
const
|
|
224
|
-
const
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
});
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
const $322c88a641701f3b$export$ffdbb83a2de845c2 = /*#__PURE__*/ $yHMN2$forwardRef((props, forwardedRef)=>{
|
|
249
|
-
const { __scopeNavigationMenu: __scopeNavigationMenu , value: valueProp , ...itemProps } = props;
|
|
250
|
-
const autoValue = $yHMN2$useId(); // We need to provide an initial deterministic value as `useId` will return
|
|
251
|
-
// empty string on the first render and we don't want to match our internal "closed" value.
|
|
252
|
-
const value = valueProp || autoValue || 'LEGACY_REACT_AUTO_VALUE';
|
|
253
|
-
const contentRef = $yHMN2$useRef(null);
|
|
254
|
-
const triggerRef = $yHMN2$useRef(null);
|
|
255
|
-
const focusProxyRef = $yHMN2$useRef(null);
|
|
256
|
-
const restoreContentTabOrderRef = $yHMN2$useRef(()=>{});
|
|
257
|
-
const wasEscapeCloseRef = $yHMN2$useRef(false);
|
|
258
|
-
const handleContentEntry = $yHMN2$useCallback((side = 'start')=>{
|
|
259
|
-
if (contentRef.current) {
|
|
260
|
-
restoreContentTabOrderRef.current();
|
|
261
|
-
const candidates = $322c88a641701f3b$var$getTabbableCandidates(contentRef.current);
|
|
262
|
-
if (candidates.length) $322c88a641701f3b$var$focusFirst(side === 'start' ? candidates : candidates.reverse());
|
|
263
|
-
}
|
|
230
|
+
var LIST_NAME = "NavigationMenuList";
|
|
231
|
+
var NavigationMenuList = React.forwardRef(
|
|
232
|
+
(props, forwardedRef) => {
|
|
233
|
+
const { __scopeNavigationMenu, ...listProps } = props;
|
|
234
|
+
const context = useNavigationMenuContext(LIST_NAME, __scopeNavigationMenu);
|
|
235
|
+
const list = /* @__PURE__ */ jsx(Primitive.ul, { "data-orientation": context.orientation, ...listProps, ref: forwardedRef });
|
|
236
|
+
return /* @__PURE__ */ jsx(Primitive.div, { style: { position: "relative" }, ref: context.onIndicatorTrackChange, children: /* @__PURE__ */ jsx(Collection.Slot, { scope: __scopeNavigationMenu, children: context.isRootMenu ? /* @__PURE__ */ jsx(FocusGroup, { asChild: true, children: list }) : list }) });
|
|
237
|
+
}
|
|
238
|
+
);
|
|
239
|
+
NavigationMenuList.displayName = LIST_NAME;
|
|
240
|
+
var ITEM_NAME = "NavigationMenuItem";
|
|
241
|
+
var [NavigationMenuItemContextProvider, useNavigationMenuItemContext] = createNavigationMenuContext(ITEM_NAME);
|
|
242
|
+
var NavigationMenuItem = React.forwardRef(
|
|
243
|
+
(props, forwardedRef) => {
|
|
244
|
+
const { __scopeNavigationMenu, value: valueProp, ...itemProps } = props;
|
|
245
|
+
const autoValue = useId();
|
|
246
|
+
const value = valueProp || autoValue || "LEGACY_REACT_AUTO_VALUE";
|
|
247
|
+
const contentRef = React.useRef(null);
|
|
248
|
+
const triggerRef = React.useRef(null);
|
|
249
|
+
const focusProxyRef = React.useRef(null);
|
|
250
|
+
const restoreContentTabOrderRef = React.useRef(() => {
|
|
251
|
+
});
|
|
252
|
+
const wasEscapeCloseRef = React.useRef(false);
|
|
253
|
+
const handleContentEntry = React.useCallback((side = "start") => {
|
|
254
|
+
if (contentRef.current) {
|
|
255
|
+
restoreContentTabOrderRef.current();
|
|
256
|
+
const candidates = getTabbableCandidates(contentRef.current);
|
|
257
|
+
if (candidates.length) focusFirst(side === "start" ? candidates : candidates.reverse());
|
|
258
|
+
}
|
|
264
259
|
}, []);
|
|
265
|
-
const handleContentExit =
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
260
|
+
const handleContentExit = React.useCallback(() => {
|
|
261
|
+
if (contentRef.current) {
|
|
262
|
+
const candidates = getTabbableCandidates(contentRef.current);
|
|
263
|
+
if (candidates.length) restoreContentTabOrderRef.current = removeFromTabOrder(candidates);
|
|
264
|
+
}
|
|
270
265
|
}, []);
|
|
271
|
-
return
|
|
266
|
+
return /* @__PURE__ */ jsx(
|
|
267
|
+
NavigationMenuItemContextProvider,
|
|
268
|
+
{
|
|
272
269
|
scope: __scopeNavigationMenu,
|
|
273
|
-
value
|
|
274
|
-
triggerRef
|
|
275
|
-
contentRef
|
|
276
|
-
focusProxyRef
|
|
277
|
-
wasEscapeCloseRef
|
|
270
|
+
value,
|
|
271
|
+
triggerRef,
|
|
272
|
+
contentRef,
|
|
273
|
+
focusProxyRef,
|
|
274
|
+
wasEscapeCloseRef,
|
|
278
275
|
onEntryKeyDown: handleContentEntry,
|
|
279
276
|
onFocusProxyEnter: handleContentEntry,
|
|
280
277
|
onRootContentClose: handleContentExit,
|
|
281
|
-
onContentFocusOutside: handleContentExit
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
const
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
scope: __scopeNavigationMenu,
|
|
305
|
-
value: itemContext.value
|
|
306
|
-
}, /*#__PURE__*/ $yHMN2$createElement($322c88a641701f3b$var$FocusGroupItem, {
|
|
307
|
-
asChild: true
|
|
308
|
-
}, /*#__PURE__*/ $yHMN2$createElement($yHMN2$Primitive.button, $yHMN2$babelruntimehelpersesmextends({
|
|
278
|
+
onContentFocusOutside: handleContentExit,
|
|
279
|
+
children: /* @__PURE__ */ jsx(Primitive.li, { ...itemProps, ref: forwardedRef })
|
|
280
|
+
}
|
|
281
|
+
);
|
|
282
|
+
}
|
|
283
|
+
);
|
|
284
|
+
NavigationMenuItem.displayName = ITEM_NAME;
|
|
285
|
+
var TRIGGER_NAME = "NavigationMenuTrigger";
|
|
286
|
+
var NavigationMenuTrigger = React.forwardRef((props, forwardedRef) => {
|
|
287
|
+
const { __scopeNavigationMenu, disabled, ...triggerProps } = props;
|
|
288
|
+
const context = useNavigationMenuContext(TRIGGER_NAME, props.__scopeNavigationMenu);
|
|
289
|
+
const itemContext = useNavigationMenuItemContext(TRIGGER_NAME, props.__scopeNavigationMenu);
|
|
290
|
+
const ref = React.useRef(null);
|
|
291
|
+
const composedRefs = useComposedRefs(ref, itemContext.triggerRef, forwardedRef);
|
|
292
|
+
const triggerId = makeTriggerId(context.baseId, itemContext.value);
|
|
293
|
+
const contentId = makeContentId(context.baseId, itemContext.value);
|
|
294
|
+
const hasPointerMoveOpenedRef = React.useRef(false);
|
|
295
|
+
const wasClickCloseRef = React.useRef(false);
|
|
296
|
+
const open = itemContext.value === context.value;
|
|
297
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
298
|
+
/* @__PURE__ */ jsx(Collection.ItemSlot, { scope: __scopeNavigationMenu, value: itemContext.value, children: /* @__PURE__ */ jsx(FocusGroupItem, { asChild: true, children: /* @__PURE__ */ jsx(
|
|
299
|
+
Primitive.button,
|
|
300
|
+
{
|
|
309
301
|
id: triggerId,
|
|
310
|
-
disabled
|
|
311
|
-
"data-disabled": disabled ?
|
|
312
|
-
"data-state":
|
|
302
|
+
disabled,
|
|
303
|
+
"data-disabled": disabled ? "" : void 0,
|
|
304
|
+
"data-state": getOpenState(open),
|
|
313
305
|
"aria-expanded": open,
|
|
314
|
-
"aria-controls": contentId
|
|
315
|
-
|
|
306
|
+
"aria-controls": contentId,
|
|
307
|
+
...triggerProps,
|
|
316
308
|
ref: composedRefs,
|
|
317
|
-
onPointerEnter:
|
|
318
|
-
|
|
319
|
-
|
|
309
|
+
onPointerEnter: composeEventHandlers(props.onPointerEnter, () => {
|
|
310
|
+
wasClickCloseRef.current = false;
|
|
311
|
+
itemContext.wasEscapeCloseRef.current = false;
|
|
320
312
|
}),
|
|
321
|
-
onPointerMove:
|
|
322
|
-
|
|
313
|
+
onPointerMove: composeEventHandlers(
|
|
314
|
+
props.onPointerMove,
|
|
315
|
+
whenMouse(() => {
|
|
316
|
+
if (disabled || wasClickCloseRef.current || itemContext.wasEscapeCloseRef.current || hasPointerMoveOpenedRef.current)
|
|
317
|
+
return;
|
|
323
318
|
context.onTriggerEnter(itemContext.value);
|
|
324
319
|
hasPointerMoveOpenedRef.current = true;
|
|
325
|
-
|
|
326
|
-
|
|
320
|
+
})
|
|
321
|
+
),
|
|
322
|
+
onPointerLeave: composeEventHandlers(
|
|
323
|
+
props.onPointerLeave,
|
|
324
|
+
whenMouse(() => {
|
|
327
325
|
if (disabled) return;
|
|
328
326
|
context.onTriggerLeave();
|
|
329
327
|
hasPointerMoveOpenedRef.current = false;
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
328
|
+
})
|
|
329
|
+
),
|
|
330
|
+
onClick: composeEventHandlers(props.onClick, () => {
|
|
331
|
+
context.onItemSelect(itemContext.value);
|
|
332
|
+
wasClickCloseRef.current = open;
|
|
334
333
|
}),
|
|
335
|
-
onKeyDown:
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
itemContext.onEntryKeyDown(); // Prevent FocusGroupItem from handling the event
|
|
343
|
-
event.preventDefault();
|
|
344
|
-
}
|
|
334
|
+
onKeyDown: composeEventHandlers(props.onKeyDown, (event) => {
|
|
335
|
+
const verticalEntryKey = context.dir === "rtl" ? "ArrowLeft" : "ArrowRight";
|
|
336
|
+
const entryKey = { horizontal: "ArrowDown", vertical: verticalEntryKey }[context.orientation];
|
|
337
|
+
if (open && event.key === entryKey) {
|
|
338
|
+
itemContext.onEntryKeyDown();
|
|
339
|
+
event.preventDefault();
|
|
340
|
+
}
|
|
345
341
|
})
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
342
|
+
}
|
|
343
|
+
) }) }),
|
|
344
|
+
open && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
345
|
+
/* @__PURE__ */ jsx(
|
|
346
|
+
VisuallyHiddenPrimitive.Root,
|
|
347
|
+
{
|
|
348
|
+
"aria-hidden": true,
|
|
349
|
+
tabIndex: 0,
|
|
350
|
+
ref: itemContext.focusProxyRef,
|
|
351
|
+
onFocus: (event) => {
|
|
351
352
|
const content = itemContext.contentRef.current;
|
|
352
353
|
const prevFocusedElement = event.relatedTarget;
|
|
353
354
|
const wasTriggerFocused = prevFocusedElement === ref.current;
|
|
354
|
-
const wasFocusFromContent = content
|
|
355
|
-
if (wasTriggerFocused || !wasFocusFromContent)
|
|
355
|
+
const wasFocusFromContent = content?.contains(prevFocusedElement);
|
|
356
|
+
if (wasTriggerFocused || !wasFocusFromContent) {
|
|
357
|
+
itemContext.onFocusProxyEnter(wasTriggerFocused ? "start" : "end");
|
|
358
|
+
}
|
|
359
|
+
}
|
|
356
360
|
}
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
})
|
|
360
|
-
});
|
|
361
|
-
/*#__PURE__*/ Object.assign($322c88a641701f3b$export$37fe8002734d8f2, {
|
|
362
|
-
displayName: $322c88a641701f3b$var$TRIGGER_NAME
|
|
361
|
+
),
|
|
362
|
+
context.viewport && /* @__PURE__ */ jsx("span", { "aria-owns": contentId })
|
|
363
|
+
] })
|
|
364
|
+
] });
|
|
363
365
|
});
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
const { __scopeNavigationMenu
|
|
370
|
-
return
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
"data-active": active ?
|
|
374
|
-
"aria-current": active ?
|
|
375
|
-
|
|
366
|
+
NavigationMenuTrigger.displayName = TRIGGER_NAME;
|
|
367
|
+
var LINK_NAME = "NavigationMenuLink";
|
|
368
|
+
var LINK_SELECT = "navigationMenu.linkSelect";
|
|
369
|
+
var NavigationMenuLink = React.forwardRef(
|
|
370
|
+
(props, forwardedRef) => {
|
|
371
|
+
const { __scopeNavigationMenu, active, onSelect, ...linkProps } = props;
|
|
372
|
+
return /* @__PURE__ */ jsx(FocusGroupItem, { asChild: true, children: /* @__PURE__ */ jsx(
|
|
373
|
+
Primitive.a,
|
|
374
|
+
{
|
|
375
|
+
"data-active": active ? "" : void 0,
|
|
376
|
+
"aria-current": active ? "page" : void 0,
|
|
377
|
+
...linkProps,
|
|
376
378
|
ref: forwardedRef,
|
|
377
|
-
onClick:
|
|
378
|
-
|
|
379
|
-
|
|
379
|
+
onClick: composeEventHandlers(
|
|
380
|
+
props.onClick,
|
|
381
|
+
(event) => {
|
|
382
|
+
const target = event.target;
|
|
383
|
+
const linkSelectEvent = new CustomEvent(LINK_SELECT, {
|
|
384
|
+
bubbles: true,
|
|
385
|
+
cancelable: true
|
|
386
|
+
});
|
|
387
|
+
target.addEventListener(LINK_SELECT, (event2) => onSelect?.(event2), { once: true });
|
|
388
|
+
dispatchDiscreteCustomEvent(target, linkSelectEvent);
|
|
389
|
+
if (!linkSelectEvent.defaultPrevented && !event.metaKey) {
|
|
390
|
+
const rootContentDismissEvent = new CustomEvent(ROOT_CONTENT_DISMISS, {
|
|
380
391
|
bubbles: true,
|
|
381
392
|
cancelable: true
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
, {
|
|
385
|
-
once: true
|
|
386
|
-
});
|
|
387
|
-
$yHMN2$dispatchDiscreteCustomEvent(target, linkSelectEvent);
|
|
388
|
-
if (!linkSelectEvent.defaultPrevented && !event1.metaKey) {
|
|
389
|
-
const rootContentDismissEvent = new CustomEvent($322c88a641701f3b$var$ROOT_CONTENT_DISMISS, {
|
|
390
|
-
bubbles: true,
|
|
391
|
-
cancelable: true
|
|
392
|
-
});
|
|
393
|
-
$yHMN2$dispatchDiscreteCustomEvent(target, rootContentDismissEvent);
|
|
393
|
+
});
|
|
394
|
+
dispatchDiscreteCustomEvent(target, rootContentDismissEvent);
|
|
394
395
|
}
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
});
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
const
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
}, /*#__PURE__*/ $yHMN2$createElement($322c88a641701f3b$var$NavigationMenuIndicatorImpl, $yHMN2$babelruntimehelpersesmextends({}, indicatorProps, {
|
|
413
|
-
ref: forwardedRef
|
|
414
|
-
}))), context.indicatorTrack) : null;
|
|
396
|
+
},
|
|
397
|
+
{ checkForDefaultPrevented: false }
|
|
398
|
+
)
|
|
399
|
+
}
|
|
400
|
+
) });
|
|
401
|
+
}
|
|
402
|
+
);
|
|
403
|
+
NavigationMenuLink.displayName = LINK_NAME;
|
|
404
|
+
var INDICATOR_NAME = "NavigationMenuIndicator";
|
|
405
|
+
var NavigationMenuIndicator = React.forwardRef((props, forwardedRef) => {
|
|
406
|
+
const { forceMount, ...indicatorProps } = props;
|
|
407
|
+
const context = useNavigationMenuContext(INDICATOR_NAME, props.__scopeNavigationMenu);
|
|
408
|
+
const isVisible = Boolean(context.value);
|
|
409
|
+
return context.indicatorTrack ? ReactDOM.createPortal(
|
|
410
|
+
/* @__PURE__ */ jsx(Presence, { present: forceMount || isVisible, children: /* @__PURE__ */ jsx(NavigationMenuIndicatorImpl, { ...indicatorProps, ref: forwardedRef }) }),
|
|
411
|
+
context.indicatorTrack
|
|
412
|
+
) : null;
|
|
415
413
|
});
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
}
|
|
419
|
-
const
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
"
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
...indicatorProps.style
|
|
466
|
-
}
|
|
467
|
-
})) : null;
|
|
414
|
+
NavigationMenuIndicator.displayName = INDICATOR_NAME;
|
|
415
|
+
var NavigationMenuIndicatorImpl = React.forwardRef((props, forwardedRef) => {
|
|
416
|
+
const { __scopeNavigationMenu, ...indicatorProps } = props;
|
|
417
|
+
const context = useNavigationMenuContext(INDICATOR_NAME, __scopeNavigationMenu);
|
|
418
|
+
const getItems = useCollection(__scopeNavigationMenu);
|
|
419
|
+
const [activeTrigger, setActiveTrigger] = React.useState(
|
|
420
|
+
null
|
|
421
|
+
);
|
|
422
|
+
const [position, setPosition] = React.useState(null);
|
|
423
|
+
const isHorizontal = context.orientation === "horizontal";
|
|
424
|
+
const isVisible = Boolean(context.value);
|
|
425
|
+
React.useEffect(() => {
|
|
426
|
+
const items = getItems();
|
|
427
|
+
const triggerNode = items.find((item) => item.value === context.value)?.ref.current;
|
|
428
|
+
if (triggerNode) setActiveTrigger(triggerNode);
|
|
429
|
+
}, [getItems, context.value]);
|
|
430
|
+
const handlePositionChange = () => {
|
|
431
|
+
if (activeTrigger) {
|
|
432
|
+
setPosition({
|
|
433
|
+
size: isHorizontal ? activeTrigger.offsetWidth : activeTrigger.offsetHeight,
|
|
434
|
+
offset: isHorizontal ? activeTrigger.offsetLeft : activeTrigger.offsetTop
|
|
435
|
+
});
|
|
436
|
+
}
|
|
437
|
+
};
|
|
438
|
+
useResizeObserver(activeTrigger, handlePositionChange);
|
|
439
|
+
useResizeObserver(context.indicatorTrack, handlePositionChange);
|
|
440
|
+
return position ? /* @__PURE__ */ jsx(
|
|
441
|
+
Primitive.div,
|
|
442
|
+
{
|
|
443
|
+
"aria-hidden": true,
|
|
444
|
+
"data-state": isVisible ? "visible" : "hidden",
|
|
445
|
+
"data-orientation": context.orientation,
|
|
446
|
+
...indicatorProps,
|
|
447
|
+
ref: forwardedRef,
|
|
448
|
+
style: {
|
|
449
|
+
position: "absolute",
|
|
450
|
+
...isHorizontal ? {
|
|
451
|
+
left: 0,
|
|
452
|
+
width: position.size + "px",
|
|
453
|
+
transform: `translateX(${position.offset}px)`
|
|
454
|
+
} : {
|
|
455
|
+
top: 0,
|
|
456
|
+
height: position.size + "px",
|
|
457
|
+
transform: `translateY(${position.offset}px)`
|
|
458
|
+
},
|
|
459
|
+
...indicatorProps.style
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
) : null;
|
|
468
463
|
});
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
const
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
ref: composedRefs
|
|
504
|
-
}));
|
|
464
|
+
var CONTENT_NAME = "NavigationMenuContent";
|
|
465
|
+
var NavigationMenuContent = React.forwardRef((props, forwardedRef) => {
|
|
466
|
+
const { forceMount, ...contentProps } = props;
|
|
467
|
+
const context = useNavigationMenuContext(CONTENT_NAME, props.__scopeNavigationMenu);
|
|
468
|
+
const itemContext = useNavigationMenuItemContext(CONTENT_NAME, props.__scopeNavigationMenu);
|
|
469
|
+
const composedRefs = useComposedRefs(itemContext.contentRef, forwardedRef);
|
|
470
|
+
const open = itemContext.value === context.value;
|
|
471
|
+
const commonProps = {
|
|
472
|
+
value: itemContext.value,
|
|
473
|
+
triggerRef: itemContext.triggerRef,
|
|
474
|
+
focusProxyRef: itemContext.focusProxyRef,
|
|
475
|
+
wasEscapeCloseRef: itemContext.wasEscapeCloseRef,
|
|
476
|
+
onContentFocusOutside: itemContext.onContentFocusOutside,
|
|
477
|
+
onRootContentClose: itemContext.onRootContentClose,
|
|
478
|
+
...contentProps
|
|
479
|
+
};
|
|
480
|
+
return !context.viewport ? /* @__PURE__ */ jsx(Presence, { present: forceMount || open, children: /* @__PURE__ */ jsx(
|
|
481
|
+
NavigationMenuContentImpl,
|
|
482
|
+
{
|
|
483
|
+
"data-state": getOpenState(open),
|
|
484
|
+
...commonProps,
|
|
485
|
+
ref: composedRefs,
|
|
486
|
+
onPointerEnter: composeEventHandlers(props.onPointerEnter, context.onContentEnter),
|
|
487
|
+
onPointerLeave: composeEventHandlers(
|
|
488
|
+
props.onPointerLeave,
|
|
489
|
+
whenMouse(context.onContentLeave)
|
|
490
|
+
),
|
|
491
|
+
style: {
|
|
492
|
+
// Prevent interaction when animating out
|
|
493
|
+
pointerEvents: !open && context.isRootMenu ? "none" : void 0,
|
|
494
|
+
...commonProps.style
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
) }) : /* @__PURE__ */ jsx(ViewportContentMounter, { forceMount, ...commonProps, ref: composedRefs });
|
|
505
498
|
});
|
|
506
|
-
|
|
507
|
-
|
|
499
|
+
NavigationMenuContent.displayName = CONTENT_NAME;
|
|
500
|
+
var ViewportContentMounter = React.forwardRef((props, forwardedRef) => {
|
|
501
|
+
const context = useNavigationMenuContext(CONTENT_NAME, props.__scopeNavigationMenu);
|
|
502
|
+
const { onViewportContentChange, onViewportContentRemove } = context;
|
|
503
|
+
useLayoutEffect(() => {
|
|
504
|
+
onViewportContentChange(props.value, {
|
|
505
|
+
ref: forwardedRef,
|
|
506
|
+
...props
|
|
507
|
+
});
|
|
508
|
+
}, [props, forwardedRef, onViewportContentChange]);
|
|
509
|
+
useLayoutEffect(() => {
|
|
510
|
+
return () => onViewportContentRemove(props.value);
|
|
511
|
+
}, [props.value, onViewportContentRemove]);
|
|
512
|
+
return null;
|
|
508
513
|
});
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
514
|
+
var ROOT_CONTENT_DISMISS = "navigationMenu.rootContentDismiss";
|
|
515
|
+
var NavigationMenuContentImpl = React.forwardRef((props, forwardedRef) => {
|
|
516
|
+
const {
|
|
517
|
+
__scopeNavigationMenu,
|
|
518
|
+
value,
|
|
519
|
+
triggerRef,
|
|
520
|
+
focusProxyRef,
|
|
521
|
+
wasEscapeCloseRef,
|
|
522
|
+
onRootContentClose,
|
|
523
|
+
onContentFocusOutside,
|
|
524
|
+
...contentProps
|
|
525
|
+
} = props;
|
|
526
|
+
const context = useNavigationMenuContext(CONTENT_NAME, __scopeNavigationMenu);
|
|
527
|
+
const ref = React.useRef(null);
|
|
528
|
+
const composedRefs = useComposedRefs(ref, forwardedRef);
|
|
529
|
+
const triggerId = makeTriggerId(context.baseId, value);
|
|
530
|
+
const contentId = makeContentId(context.baseId, value);
|
|
531
|
+
const getItems = useCollection(__scopeNavigationMenu);
|
|
532
|
+
const prevMotionAttributeRef = React.useRef(null);
|
|
533
|
+
const { onItemDismiss } = context;
|
|
534
|
+
React.useEffect(() => {
|
|
535
|
+
const content = ref.current;
|
|
536
|
+
if (context.isRootMenu && content) {
|
|
537
|
+
const handleClose = () => {
|
|
538
|
+
onItemDismiss();
|
|
539
|
+
onRootContentClose();
|
|
540
|
+
if (content.contains(document.activeElement)) triggerRef.current?.focus();
|
|
541
|
+
};
|
|
542
|
+
content.addEventListener(ROOT_CONTENT_DISMISS, handleClose);
|
|
543
|
+
return () => content.removeEventListener(ROOT_CONTENT_DISMISS, handleClose);
|
|
544
|
+
}
|
|
545
|
+
}, [context.isRootMenu, props.value, triggerRef, onItemDismiss, onRootContentClose]);
|
|
546
|
+
const motionAttribute = React.useMemo(() => {
|
|
547
|
+
const items = getItems();
|
|
548
|
+
const values = items.map((item) => item.value);
|
|
549
|
+
if (context.dir === "rtl") values.reverse();
|
|
550
|
+
const index = values.indexOf(context.value);
|
|
551
|
+
const prevIndex = values.indexOf(context.previousValue);
|
|
552
|
+
const isSelected = value === context.value;
|
|
553
|
+
const wasSelected = prevIndex === values.indexOf(value);
|
|
554
|
+
if (!isSelected && !wasSelected) return prevMotionAttributeRef.current;
|
|
555
|
+
const attribute = (() => {
|
|
556
|
+
if (index !== prevIndex) {
|
|
557
|
+
if (isSelected && prevIndex !== -1) return index > prevIndex ? "from-end" : "from-start";
|
|
558
|
+
if (wasSelected && index !== -1) return index > prevIndex ? "to-start" : "to-end";
|
|
559
|
+
}
|
|
560
|
+
return null;
|
|
561
|
+
})();
|
|
562
|
+
prevMotionAttributeRef.current = attribute;
|
|
563
|
+
return attribute;
|
|
564
|
+
}, [context.previousValue, context.value, context.dir, getItems, value]);
|
|
565
|
+
return /* @__PURE__ */ jsx(FocusGroup, { asChild: true, children: /* @__PURE__ */ jsx(
|
|
566
|
+
DismissableLayer,
|
|
567
|
+
{
|
|
568
|
+
id: contentId,
|
|
569
|
+
"aria-labelledby": triggerId,
|
|
570
|
+
"data-motion": motionAttribute,
|
|
571
|
+
"data-orientation": context.orientation,
|
|
572
|
+
...contentProps,
|
|
573
|
+
ref: composedRefs,
|
|
574
|
+
disableOutsidePointerEvents: false,
|
|
575
|
+
onDismiss: () => {
|
|
576
|
+
const rootContentDismissEvent = new Event(ROOT_CONTENT_DISMISS, {
|
|
577
|
+
bubbles: true,
|
|
578
|
+
cancelable: true
|
|
516
579
|
});
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
const
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
if (context.isRootMenu && content) {
|
|
545
|
-
const handleClose = ()=>{
|
|
546
|
-
var _triggerRef$current;
|
|
547
|
-
onItemDismiss();
|
|
548
|
-
onRootContentClose();
|
|
549
|
-
if (content.contains(document.activeElement)) (_triggerRef$current = triggerRef.current) === null || _triggerRef$current === void 0 || _triggerRef$current.focus();
|
|
550
|
-
};
|
|
551
|
-
content.addEventListener($322c88a641701f3b$var$ROOT_CONTENT_DISMISS, handleClose);
|
|
552
|
-
return ()=>content.removeEventListener($322c88a641701f3b$var$ROOT_CONTENT_DISMISS, handleClose)
|
|
553
|
-
;
|
|
580
|
+
ref.current?.dispatchEvent(rootContentDismissEvent);
|
|
581
|
+
},
|
|
582
|
+
onFocusOutside: composeEventHandlers(props.onFocusOutside, (event) => {
|
|
583
|
+
onContentFocusOutside();
|
|
584
|
+
const target = event.target;
|
|
585
|
+
if (context.rootNavigationMenu?.contains(target)) event.preventDefault();
|
|
586
|
+
}),
|
|
587
|
+
onPointerDownOutside: composeEventHandlers(props.onPointerDownOutside, (event) => {
|
|
588
|
+
const target = event.target;
|
|
589
|
+
const isTrigger = getItems().some((item) => item.ref.current?.contains(target));
|
|
590
|
+
const isRootViewport = context.isRootMenu && context.viewport?.contains(target);
|
|
591
|
+
if (isTrigger || isRootViewport || !context.isRootMenu) event.preventDefault();
|
|
592
|
+
}),
|
|
593
|
+
onKeyDown: composeEventHandlers(props.onKeyDown, (event) => {
|
|
594
|
+
const isMetaKey = event.altKey || event.ctrlKey || event.metaKey;
|
|
595
|
+
const isTabKey = event.key === "Tab" && !isMetaKey;
|
|
596
|
+
if (isTabKey) {
|
|
597
|
+
const candidates = getTabbableCandidates(event.currentTarget);
|
|
598
|
+
const focusedElement = document.activeElement;
|
|
599
|
+
const index = candidates.findIndex((candidate) => candidate === focusedElement);
|
|
600
|
+
const isMovingBackwards = event.shiftKey;
|
|
601
|
+
const nextCandidates = isMovingBackwards ? candidates.slice(0, index).reverse() : candidates.slice(index + 1, candidates.length);
|
|
602
|
+
if (focusFirst(nextCandidates)) {
|
|
603
|
+
event.preventDefault();
|
|
604
|
+
} else {
|
|
605
|
+
focusProxyRef.current?.focus();
|
|
606
|
+
}
|
|
554
607
|
}
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
]);
|
|
562
|
-
const motionAttribute = $yHMN2$useMemo(()=>{
|
|
563
|
-
const items = getItems();
|
|
564
|
-
const values = items.map((item)=>item.value
|
|
565
|
-
);
|
|
566
|
-
if (context.dir === 'rtl') values.reverse();
|
|
567
|
-
const index = values.indexOf(context.value);
|
|
568
|
-
const prevIndex = values.indexOf(context.previousValue);
|
|
569
|
-
const isSelected = value === context.value;
|
|
570
|
-
const wasSelected = prevIndex === values.indexOf(value); // We only want to update selected and the last selected content
|
|
571
|
-
// this avoids animations being interrupted outside of that range
|
|
572
|
-
if (!isSelected && !wasSelected) return prevMotionAttributeRef.current;
|
|
573
|
-
const attribute = (()=>{
|
|
574
|
-
// Don't provide a direction on the initial open
|
|
575
|
-
if (index !== prevIndex) {
|
|
576
|
-
// If we're moving to this item from another
|
|
577
|
-
if (isSelected && prevIndex !== -1) return index > prevIndex ? 'from-end' : 'from-start'; // If we're leaving this item for another
|
|
578
|
-
if (wasSelected && index !== -1) return index > prevIndex ? 'to-start' : 'to-end';
|
|
579
|
-
} // Otherwise we're entering from closed or leaving the list
|
|
580
|
-
// entirely and should not animate in any direction
|
|
581
|
-
return null;
|
|
582
|
-
})();
|
|
583
|
-
prevMotionAttributeRef.current = attribute;
|
|
584
|
-
return attribute;
|
|
585
|
-
}, [
|
|
586
|
-
context.previousValue,
|
|
587
|
-
context.value,
|
|
588
|
-
context.dir,
|
|
589
|
-
getItems,
|
|
590
|
-
value
|
|
591
|
-
]);
|
|
592
|
-
return /*#__PURE__*/ $yHMN2$createElement($322c88a641701f3b$var$FocusGroup, {
|
|
593
|
-
asChild: true
|
|
594
|
-
}, /*#__PURE__*/ $yHMN2$createElement($yHMN2$DismissableLayer, $yHMN2$babelruntimehelpersesmextends({
|
|
595
|
-
id: contentId,
|
|
596
|
-
"aria-labelledby": triggerId,
|
|
597
|
-
"data-motion": motionAttribute,
|
|
598
|
-
"data-orientation": context.orientation
|
|
599
|
-
}, contentProps, {
|
|
600
|
-
ref: composedRefs,
|
|
601
|
-
disableOutsidePointerEvents: false,
|
|
602
|
-
onDismiss: ()=>{
|
|
603
|
-
var _ref$current;
|
|
604
|
-
const rootContentDismissEvent = new Event($322c88a641701f3b$var$ROOT_CONTENT_DISMISS, {
|
|
605
|
-
bubbles: true,
|
|
606
|
-
cancelable: true
|
|
607
|
-
});
|
|
608
|
-
(_ref$current = ref.current) === null || _ref$current === void 0 || _ref$current.dispatchEvent(rootContentDismissEvent);
|
|
609
|
-
},
|
|
610
|
-
onFocusOutside: $yHMN2$composeEventHandlers(props.onFocusOutside, (event)=>{
|
|
611
|
-
var _context$rootNavigati;
|
|
612
|
-
onContentFocusOutside();
|
|
613
|
-
const target = event.target; // Only dismiss content when focus moves outside of the menu
|
|
614
|
-
if ((_context$rootNavigati = context.rootNavigationMenu) !== null && _context$rootNavigati !== void 0 && _context$rootNavigati.contains(target)) event.preventDefault();
|
|
615
|
-
}),
|
|
616
|
-
onPointerDownOutside: $yHMN2$composeEventHandlers(props.onPointerDownOutside, (event)=>{
|
|
617
|
-
var _context$viewport;
|
|
618
|
-
const target = event.target;
|
|
619
|
-
const isTrigger = getItems().some((item)=>{
|
|
620
|
-
var _item$ref$current;
|
|
621
|
-
return (_item$ref$current = item.ref.current) === null || _item$ref$current === void 0 ? void 0 : _item$ref$current.contains(target);
|
|
622
|
-
});
|
|
623
|
-
const isRootViewport = context.isRootMenu && ((_context$viewport = context.viewport) === null || _context$viewport === void 0 ? void 0 : _context$viewport.contains(target));
|
|
624
|
-
if (isTrigger || isRootViewport || !context.isRootMenu) event.preventDefault();
|
|
625
|
-
}),
|
|
626
|
-
onKeyDown: $yHMN2$composeEventHandlers(props.onKeyDown, (event)=>{
|
|
627
|
-
const isMetaKey = event.altKey || event.ctrlKey || event.metaKey;
|
|
628
|
-
const isTabKey = event.key === 'Tab' && !isMetaKey;
|
|
629
|
-
if (isTabKey) {
|
|
630
|
-
const candidates = $322c88a641701f3b$var$getTabbableCandidates(event.currentTarget);
|
|
631
|
-
const focusedElement = document.activeElement;
|
|
632
|
-
const index = candidates.findIndex((candidate)=>candidate === focusedElement
|
|
633
|
-
);
|
|
634
|
-
const isMovingBackwards = event.shiftKey;
|
|
635
|
-
const nextCandidates = isMovingBackwards ? candidates.slice(0, index).reverse() : candidates.slice(index + 1, candidates.length);
|
|
636
|
-
if ($322c88a641701f3b$var$focusFirst(nextCandidates)) // prevent browser tab keydown because we've handled focus
|
|
637
|
-
event.preventDefault();
|
|
638
|
-
else {
|
|
639
|
-
var _focusProxyRef$curren;
|
|
640
|
-
// If we can't focus that means we're at the edges
|
|
641
|
-
// so focus the proxy and let browser handle
|
|
642
|
-
// tab/shift+tab keypress on the proxy instead
|
|
643
|
-
(_focusProxyRef$curren = focusProxyRef.current) === null || _focusProxyRef$curren === void 0 || _focusProxyRef$curren.focus();
|
|
644
|
-
}
|
|
645
|
-
}
|
|
646
|
-
}),
|
|
647
|
-
onEscapeKeyDown: $yHMN2$composeEventHandlers(props.onEscapeKeyDown, (event)=>{
|
|
648
|
-
// prevent the dropdown from reopening
|
|
649
|
-
// after the escape key has been pressed
|
|
650
|
-
wasEscapeCloseRef.current = true;
|
|
651
|
-
})
|
|
652
|
-
})));
|
|
653
|
-
});
|
|
654
|
-
/* -------------------------------------------------------------------------------------------------
|
|
655
|
-
* NavigationMenuViewport
|
|
656
|
-
* -----------------------------------------------------------------------------------------------*/ const $322c88a641701f3b$var$VIEWPORT_NAME = 'NavigationMenuViewport';
|
|
657
|
-
const $322c88a641701f3b$export$ee880b97cc6d44a5 = /*#__PURE__*/ $yHMN2$forwardRef((props, forwardedRef)=>{
|
|
658
|
-
const { forceMount: forceMount , ...viewportProps } = props;
|
|
659
|
-
const context = $322c88a641701f3b$var$useNavigationMenuContext($322c88a641701f3b$var$VIEWPORT_NAME, props.__scopeNavigationMenu);
|
|
660
|
-
const open = Boolean(context.value);
|
|
661
|
-
return /*#__PURE__*/ $yHMN2$createElement($yHMN2$Presence, {
|
|
662
|
-
present: forceMount || open
|
|
663
|
-
}, /*#__PURE__*/ $yHMN2$createElement($322c88a641701f3b$var$NavigationMenuViewportImpl, $yHMN2$babelruntimehelpersesmextends({}, viewportProps, {
|
|
664
|
-
ref: forwardedRef
|
|
665
|
-
})));
|
|
608
|
+
}),
|
|
609
|
+
onEscapeKeyDown: composeEventHandlers(props.onEscapeKeyDown, (event) => {
|
|
610
|
+
wasEscapeCloseRef.current = true;
|
|
611
|
+
})
|
|
612
|
+
}
|
|
613
|
+
) });
|
|
666
614
|
});
|
|
667
|
-
|
|
668
|
-
|
|
615
|
+
var VIEWPORT_NAME = "NavigationMenuViewport";
|
|
616
|
+
var NavigationMenuViewport = React.forwardRef((props, forwardedRef) => {
|
|
617
|
+
const { forceMount, ...viewportProps } = props;
|
|
618
|
+
const context = useNavigationMenuContext(VIEWPORT_NAME, props.__scopeNavigationMenu);
|
|
619
|
+
const open = Boolean(context.value);
|
|
620
|
+
return /* @__PURE__ */ jsx(Presence, { present: forceMount || open, children: /* @__PURE__ */ jsx(NavigationMenuViewportImpl, { ...viewportProps, ref: forwardedRef }) });
|
|
669
621
|
});
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
onPointerEnter: $yHMN2$composeEventHandlers(props1.onPointerEnter, context.onContentEnter),
|
|
707
|
-
onPointerLeave: $yHMN2$composeEventHandlers(props1.onPointerLeave, $322c88a641701f3b$var$whenMouse(context.onContentLeave))
|
|
708
|
-
}), Array.from(viewportContentContext.items).map(([value, { ref: ref , forceMount: forceMount , ...props }])=>{
|
|
622
|
+
NavigationMenuViewport.displayName = VIEWPORT_NAME;
|
|
623
|
+
var NavigationMenuViewportImpl = React.forwardRef((props, forwardedRef) => {
|
|
624
|
+
const { __scopeNavigationMenu, children, ...viewportImplProps } = props;
|
|
625
|
+
const context = useNavigationMenuContext(VIEWPORT_NAME, __scopeNavigationMenu);
|
|
626
|
+
const composedRefs = useComposedRefs(forwardedRef, context.onViewportChange);
|
|
627
|
+
const viewportContentContext = useViewportContentContext(
|
|
628
|
+
CONTENT_NAME,
|
|
629
|
+
props.__scopeNavigationMenu
|
|
630
|
+
);
|
|
631
|
+
const [size, setSize] = React.useState(null);
|
|
632
|
+
const [content, setContent] = React.useState(null);
|
|
633
|
+
const viewportWidth = size ? size?.width + "px" : void 0;
|
|
634
|
+
const viewportHeight = size ? size?.height + "px" : void 0;
|
|
635
|
+
const open = Boolean(context.value);
|
|
636
|
+
const activeContentValue = open ? context.value : context.previousValue;
|
|
637
|
+
const handleSizeChange = () => {
|
|
638
|
+
if (content) setSize({ width: content.offsetWidth, height: content.offsetHeight });
|
|
639
|
+
};
|
|
640
|
+
useResizeObserver(content, handleSizeChange);
|
|
641
|
+
return /* @__PURE__ */ jsx(
|
|
642
|
+
Primitive.div,
|
|
643
|
+
{
|
|
644
|
+
"data-state": getOpenState(open),
|
|
645
|
+
"data-orientation": context.orientation,
|
|
646
|
+
...viewportImplProps,
|
|
647
|
+
ref: composedRefs,
|
|
648
|
+
style: {
|
|
649
|
+
// Prevent interaction when animating out
|
|
650
|
+
pointerEvents: !open && context.isRootMenu ? "none" : void 0,
|
|
651
|
+
["--radix-navigation-menu-viewport-width"]: viewportWidth,
|
|
652
|
+
["--radix-navigation-menu-viewport-height"]: viewportHeight,
|
|
653
|
+
...viewportImplProps.style
|
|
654
|
+
},
|
|
655
|
+
onPointerEnter: composeEventHandlers(props.onPointerEnter, context.onContentEnter),
|
|
656
|
+
onPointerLeave: composeEventHandlers(props.onPointerLeave, whenMouse(context.onContentLeave)),
|
|
657
|
+
children: Array.from(viewportContentContext.items).map(([value, { ref, forceMount, ...props2 }]) => {
|
|
709
658
|
const isActive = activeContentValue === value;
|
|
710
|
-
return
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
ref:
|
|
715
|
-
|
|
716
|
-
// as we need to smoothly transition between them.
|
|
717
|
-
if (isActive && node) setContent(node);
|
|
659
|
+
return /* @__PURE__ */ jsx(Presence, { present: forceMount || isActive, children: /* @__PURE__ */ jsx(
|
|
660
|
+
NavigationMenuContentImpl,
|
|
661
|
+
{
|
|
662
|
+
...props2,
|
|
663
|
+
ref: composeRefs(ref, (node) => {
|
|
664
|
+
if (isActive && node) setContent(node);
|
|
718
665
|
})
|
|
719
|
-
|
|
720
|
-
|
|
666
|
+
}
|
|
667
|
+
) }, value);
|
|
668
|
+
})
|
|
669
|
+
}
|
|
670
|
+
);
|
|
721
671
|
});
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
const
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
}
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
];
|
|
742
|
-
const $322c88a641701f3b$var$FOCUS_GROUP_ITEM_NAME = 'FocusGroupItem';
|
|
743
|
-
const $322c88a641701f3b$var$FocusGroupItem = /*#__PURE__*/ $yHMN2$forwardRef((props, forwardedRef)=>{
|
|
744
|
-
const { __scopeNavigationMenu: __scopeNavigationMenu , ...groupProps } = props;
|
|
745
|
-
const getItems = $322c88a641701f3b$var$useFocusGroupCollection(__scopeNavigationMenu);
|
|
746
|
-
const context = $322c88a641701f3b$var$useNavigationMenuContext($322c88a641701f3b$var$FOCUS_GROUP_ITEM_NAME, __scopeNavigationMenu);
|
|
747
|
-
return /*#__PURE__*/ $yHMN2$createElement($322c88a641701f3b$var$FocusGroupCollection.ItemSlot, {
|
|
748
|
-
scope: __scopeNavigationMenu
|
|
749
|
-
}, /*#__PURE__*/ $yHMN2$createElement($yHMN2$Primitive.button, $yHMN2$babelruntimehelpersesmextends({}, groupProps, {
|
|
672
|
+
var FOCUS_GROUP_NAME = "FocusGroup";
|
|
673
|
+
var FocusGroup = React.forwardRef(
|
|
674
|
+
(props, forwardedRef) => {
|
|
675
|
+
const { __scopeNavigationMenu, ...groupProps } = props;
|
|
676
|
+
const context = useNavigationMenuContext(FOCUS_GROUP_NAME, __scopeNavigationMenu);
|
|
677
|
+
return /* @__PURE__ */ jsx(FocusGroupCollection.Provider, { scope: __scopeNavigationMenu, children: /* @__PURE__ */ jsx(FocusGroupCollection.Slot, { scope: __scopeNavigationMenu, children: /* @__PURE__ */ jsx(Primitive.div, { dir: context.dir, ...groupProps, ref: forwardedRef }) }) });
|
|
678
|
+
}
|
|
679
|
+
);
|
|
680
|
+
var ARROW_KEYS = ["ArrowRight", "ArrowLeft", "ArrowUp", "ArrowDown"];
|
|
681
|
+
var FOCUS_GROUP_ITEM_NAME = "FocusGroupItem";
|
|
682
|
+
var FocusGroupItem = React.forwardRef(
|
|
683
|
+
(props, forwardedRef) => {
|
|
684
|
+
const { __scopeNavigationMenu, ...groupProps } = props;
|
|
685
|
+
const getItems = useFocusGroupCollection(__scopeNavigationMenu);
|
|
686
|
+
const context = useNavigationMenuContext(FOCUS_GROUP_ITEM_NAME, __scopeNavigationMenu);
|
|
687
|
+
return /* @__PURE__ */ jsx(FocusGroupCollection.ItemSlot, { scope: __scopeNavigationMenu, children: /* @__PURE__ */ jsx(
|
|
688
|
+
Primitive.button,
|
|
689
|
+
{
|
|
690
|
+
...groupProps,
|
|
750
691
|
ref: forwardedRef,
|
|
751
|
-
onKeyDown:
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
]
|
|
757
|
-
if (
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
const prevKeys = [
|
|
762
|
-
prevItemKey,
|
|
763
|
-
'ArrowUp',
|
|
764
|
-
'End'
|
|
765
|
-
];
|
|
766
|
-
if (prevKeys.includes(event.key)) candidateNodes.reverse();
|
|
767
|
-
if ($322c88a641701f3b$var$ARROW_KEYS.includes(event.key)) {
|
|
768
|
-
const currentIndex = candidateNodes.indexOf(event.currentTarget);
|
|
769
|
-
candidateNodes = candidateNodes.slice(currentIndex + 1);
|
|
770
|
-
}
|
|
771
|
-
/**
|
|
772
|
-
* Imperative focus during keydown is risky so we prevent React's batching updates
|
|
773
|
-
* to avoid potential bugs. See: https://github.com/facebook/react/issues/20332
|
|
774
|
-
*/ setTimeout(()=>$322c88a641701f3b$var$focusFirst(candidateNodes)
|
|
775
|
-
); // Prevent page scroll while navigating
|
|
776
|
-
event.preventDefault();
|
|
692
|
+
onKeyDown: composeEventHandlers(props.onKeyDown, (event) => {
|
|
693
|
+
const isFocusNavigationKey = ["Home", "End", ...ARROW_KEYS].includes(event.key);
|
|
694
|
+
if (isFocusNavigationKey) {
|
|
695
|
+
let candidateNodes = getItems().map((item) => item.ref.current);
|
|
696
|
+
const prevItemKey = context.dir === "rtl" ? "ArrowRight" : "ArrowLeft";
|
|
697
|
+
const prevKeys = [prevItemKey, "ArrowUp", "End"];
|
|
698
|
+
if (prevKeys.includes(event.key)) candidateNodes.reverse();
|
|
699
|
+
if (ARROW_KEYS.includes(event.key)) {
|
|
700
|
+
const currentIndex = candidateNodes.indexOf(event.currentTarget);
|
|
701
|
+
candidateNodes = candidateNodes.slice(currentIndex + 1);
|
|
777
702
|
}
|
|
703
|
+
setTimeout(() => focusFirst(candidateNodes));
|
|
704
|
+
event.preventDefault();
|
|
705
|
+
}
|
|
778
706
|
})
|
|
779
|
-
|
|
780
|
-
});
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
const isHiddenInput = node.tagName === 'INPUT' && node.type === 'hidden';
|
|
795
|
-
if (node.disabled || node.hidden || isHiddenInput) return NodeFilter.FILTER_SKIP; // `.tabIndex` is not the same as the `tabindex` attribute. It works on the
|
|
796
|
-
// runtime's understanding of tabbability, so this automatically accounts
|
|
797
|
-
// for any kind of element that could be tabbed to.
|
|
798
|
-
return node.tabIndex >= 0 ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_SKIP;
|
|
799
|
-
}
|
|
800
|
-
});
|
|
801
|
-
while(walker.nextNode())nodes.push(walker.currentNode); // we do not take into account the order of nodes with positive `tabIndex` as it
|
|
802
|
-
// hinders accessibility to have tab order different from visual order.
|
|
803
|
-
return nodes;
|
|
707
|
+
}
|
|
708
|
+
) });
|
|
709
|
+
}
|
|
710
|
+
);
|
|
711
|
+
function getTabbableCandidates(container) {
|
|
712
|
+
const nodes = [];
|
|
713
|
+
const walker = document.createTreeWalker(container, NodeFilter.SHOW_ELEMENT, {
|
|
714
|
+
acceptNode: (node) => {
|
|
715
|
+
const isHiddenInput = node.tagName === "INPUT" && node.type === "hidden";
|
|
716
|
+
if (node.disabled || node.hidden || isHiddenInput) return NodeFilter.FILTER_SKIP;
|
|
717
|
+
return node.tabIndex >= 0 ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_SKIP;
|
|
718
|
+
}
|
|
719
|
+
});
|
|
720
|
+
while (walker.nextNode()) nodes.push(walker.currentNode);
|
|
721
|
+
return nodes;
|
|
804
722
|
}
|
|
805
|
-
function
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
});
|
|
723
|
+
function focusFirst(candidates) {
|
|
724
|
+
const previouslyFocusedElement = document.activeElement;
|
|
725
|
+
return candidates.some((candidate) => {
|
|
726
|
+
if (candidate === previouslyFocusedElement) return true;
|
|
727
|
+
candidate.focus();
|
|
728
|
+
return document.activeElement !== previouslyFocusedElement;
|
|
729
|
+
});
|
|
813
730
|
}
|
|
814
|
-
function
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
731
|
+
function removeFromTabOrder(candidates) {
|
|
732
|
+
candidates.forEach((candidate) => {
|
|
733
|
+
candidate.dataset.tabindex = candidate.getAttribute("tabindex") || "";
|
|
734
|
+
candidate.setAttribute("tabindex", "-1");
|
|
735
|
+
});
|
|
736
|
+
return () => {
|
|
737
|
+
candidates.forEach((candidate) => {
|
|
738
|
+
const prevTabIndex = candidate.dataset.tabindex;
|
|
739
|
+
candidate.setAttribute("tabindex", prevTabIndex);
|
|
818
740
|
});
|
|
819
|
-
|
|
820
|
-
candidates.forEach((candidate)=>{
|
|
821
|
-
const prevTabIndex = candidate.dataset.tabindex;
|
|
822
|
-
candidate.setAttribute('tabindex', prevTabIndex);
|
|
823
|
-
});
|
|
824
|
-
};
|
|
741
|
+
};
|
|
825
742
|
}
|
|
826
|
-
function
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
return ()=>{
|
|
843
|
-
window.cancelAnimationFrame(rAF);
|
|
844
|
-
resizeObserver.unobserve(element);
|
|
845
|
-
};
|
|
846
|
-
}
|
|
847
|
-
}, [
|
|
848
|
-
element,
|
|
849
|
-
handleResize
|
|
850
|
-
]);
|
|
743
|
+
function useResizeObserver(element, onResize) {
|
|
744
|
+
const handleResize = useCallbackRef(onResize);
|
|
745
|
+
useLayoutEffect(() => {
|
|
746
|
+
let rAF = 0;
|
|
747
|
+
if (element) {
|
|
748
|
+
const resizeObserver = new ResizeObserver(() => {
|
|
749
|
+
cancelAnimationFrame(rAF);
|
|
750
|
+
rAF = window.requestAnimationFrame(handleResize);
|
|
751
|
+
});
|
|
752
|
+
resizeObserver.observe(element);
|
|
753
|
+
return () => {
|
|
754
|
+
window.cancelAnimationFrame(rAF);
|
|
755
|
+
resizeObserver.unobserve(element);
|
|
756
|
+
};
|
|
757
|
+
}
|
|
758
|
+
}, [element, handleResize]);
|
|
851
759
|
}
|
|
852
|
-
function
|
|
853
|
-
|
|
760
|
+
function getOpenState(open) {
|
|
761
|
+
return open ? "open" : "closed";
|
|
854
762
|
}
|
|
855
|
-
function
|
|
856
|
-
|
|
763
|
+
function makeTriggerId(baseId, value) {
|
|
764
|
+
return `${baseId}-trigger-${value}`;
|
|
857
765
|
}
|
|
858
|
-
function
|
|
859
|
-
|
|
766
|
+
function makeContentId(baseId, value) {
|
|
767
|
+
return `${baseId}-content-${value}`;
|
|
860
768
|
}
|
|
861
|
-
function
|
|
862
|
-
|
|
863
|
-
;
|
|
769
|
+
function whenMouse(handler) {
|
|
770
|
+
return (event) => event.pointerType === "mouse" ? handler(event) : void 0;
|
|
864
771
|
}
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
772
|
+
var Root2 = NavigationMenu;
|
|
773
|
+
var Sub = NavigationMenuSub;
|
|
774
|
+
var List = NavigationMenuList;
|
|
775
|
+
var Item = NavigationMenuItem;
|
|
776
|
+
var Trigger = NavigationMenuTrigger;
|
|
777
|
+
var Link = NavigationMenuLink;
|
|
778
|
+
var Indicator = NavigationMenuIndicator;
|
|
779
|
+
var Content = NavigationMenuContent;
|
|
780
|
+
var Viewport = NavigationMenuViewport;
|
|
781
|
+
export {
|
|
782
|
+
Content,
|
|
783
|
+
Indicator,
|
|
784
|
+
Item,
|
|
785
|
+
Link,
|
|
786
|
+
List,
|
|
787
|
+
NavigationMenu,
|
|
788
|
+
NavigationMenuContent,
|
|
789
|
+
NavigationMenuIndicator,
|
|
790
|
+
NavigationMenuItem,
|
|
791
|
+
NavigationMenuLink,
|
|
792
|
+
NavigationMenuList,
|
|
793
|
+
NavigationMenuSub,
|
|
794
|
+
NavigationMenuTrigger,
|
|
795
|
+
NavigationMenuViewport,
|
|
796
|
+
Root2 as Root,
|
|
797
|
+
Sub,
|
|
798
|
+
Trigger,
|
|
799
|
+
Viewport,
|
|
800
|
+
createNavigationMenuScope
|
|
801
|
+
};
|
|
879
802
|
//# sourceMappingURL=index.mjs.map
|