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