@radix-ui/react-navigation-menu 1.0.1-rc.9 → 1.1.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.
@@ -1,5 +1,5 @@
1
1
  import $yHMN2$babelruntimehelpersesmextends from "@babel/runtime/helpers/esm/extends";
2
- import {forwardRef as $yHMN2$forwardRef, useState as $yHMN2$useState, createElement as $yHMN2$createElement, useRef as $yHMN2$useRef, useEffect as $yHMN2$useEffect, useCallback as $yHMN2$useCallback, Fragment as $yHMN2$Fragment, useMemo as $yHMN2$useMemo} from "react";
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
3
  import $yHMN2$reactdom from "react-dom";
4
4
  import {createContextScope as $yHMN2$createContextScope} from "@radix-ui/react-context";
5
5
  import {composeEventHandlers as $yHMN2$composeEventHandlers} from "@radix-ui/primitive";
@@ -45,20 +45,90 @@ const [$322c88a641701f3b$var$createNavigationMenuContext, $322c88a641701f3b$expo
45
45
  const [$322c88a641701f3b$var$NavigationMenuProviderImpl, $322c88a641701f3b$var$useNavigationMenuContext] = $322c88a641701f3b$var$createNavigationMenuContext($322c88a641701f3b$var$NAVIGATION_MENU_NAME);
46
46
  const [$322c88a641701f3b$var$ViewportContentProvider, $322c88a641701f3b$var$useViewportContentContext] = $322c88a641701f3b$var$createNavigationMenuContext($322c88a641701f3b$var$NAVIGATION_MENU_NAME);
47
47
  const $322c88a641701f3b$export$5b2278cf1e8bcae2 = /*#__PURE__*/ $yHMN2$forwardRef((props, forwardedRef)=>{
48
- const { __scopeNavigationMenu: __scopeNavigationMenu , value: value , onValueChange: onValueChange , defaultValue: defaultValue , orientation: orientation = 'horizontal' , dir: dir , ...NavigationMenuProps } = props;
48
+ const { __scopeNavigationMenu: __scopeNavigationMenu , value: valueProp , onValueChange: onValueChange , defaultValue: defaultValue , delayDuration: delayDuration = 200 , skipDelayDuration: skipDelayDuration = 300 , orientation: orientation = 'horizontal' , dir: dir , ...NavigationMenuProps } = props;
49
49
  const [navigationMenu, setNavigationMenu] = $yHMN2$useState(null);
50
50
  const composedRef = $yHMN2$useComposedRefs(forwardedRef, (node)=>setNavigationMenu(node)
51
51
  );
52
52
  const direction = $yHMN2$useDirection(dir);
53
+ const openTimerRef = $yHMN2$useRef(0);
54
+ const closeTimerRef = $yHMN2$useRef(0);
55
+ const skipDelayTimerRef = $yHMN2$useRef(0);
56
+ const [isOpenDelayed, setIsOpenDelayed] = $yHMN2$useState(true);
57
+ const [value1 = '', setValue] = $yHMN2$useControllableState({
58
+ prop: valueProp,
59
+ onChange: (value)=>{
60
+ const isOpen = value !== '';
61
+ const hasSkipDelayDuration = skipDelayDuration > 0;
62
+ if (isOpen) {
63
+ window.clearTimeout(skipDelayTimerRef.current);
64
+ if (hasSkipDelayDuration) setIsOpenDelayed(false);
65
+ } else {
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
73
+ });
74
+ const startCloseTimer = $yHMN2$useCallback(()=>{
75
+ window.clearTimeout(closeTimerRef.current);
76
+ closeTimerRef.current = window.setTimeout(()=>setValue('')
77
+ , 150);
78
+ }, [
79
+ setValue
80
+ ]);
81
+ const handleOpen = $yHMN2$useCallback((itemValue)=>{
82
+ window.clearTimeout(closeTimerRef.current);
83
+ setValue(itemValue);
84
+ }, [
85
+ setValue
86
+ ]);
87
+ const handleDelayedOpen = $yHMN2$useCallback((itemValue)=>{
88
+ const isOpenItem = value1 === itemValue;
89
+ if (isOpenItem) // If the item is already open (e.g. we're transitioning from the content to the trigger)
90
+ // then we want to clear the close timer immediately.
91
+ window.clearTimeout(closeTimerRef.current);
92
+ else openTimerRef.current = window.setTimeout(()=>{
93
+ window.clearTimeout(closeTimerRef.current);
94
+ setValue(itemValue);
95
+ }, delayDuration);
96
+ }, [
97
+ value1,
98
+ setValue,
99
+ delayDuration
100
+ ]);
101
+ $yHMN2$useEffect(()=>{
102
+ return ()=>{
103
+ window.clearTimeout(openTimerRef.current);
104
+ window.clearTimeout(closeTimerRef.current);
105
+ window.clearTimeout(skipDelayTimerRef.current);
106
+ };
107
+ }, []);
53
108
  return /*#__PURE__*/ $yHMN2$createElement($322c88a641701f3b$var$NavigationMenuProvider, {
54
109
  scope: __scopeNavigationMenu,
55
110
  isRootMenu: true,
56
- value: value,
57
- onValueChange: onValueChange,
58
- defaultValue: defaultValue,
111
+ value: value1,
59
112
  dir: direction,
60
113
  orientation: orientation,
61
- rootNavigationMenu: navigationMenu
114
+ rootNavigationMenu: navigationMenu,
115
+ onTriggerEnter: (itemValue)=>{
116
+ window.clearTimeout(openTimerRef.current);
117
+ if (isOpenDelayed) handleDelayedOpen(itemValue);
118
+ else handleOpen(itemValue);
119
+ },
120
+ onTriggerLeave: ()=>{
121
+ window.clearTimeout(openTimerRef.current);
122
+ startCloseTimer();
123
+ },
124
+ onContentEnter: ()=>window.clearTimeout(closeTimerRef.current)
125
+ ,
126
+ onContentLeave: startCloseTimer,
127
+ onItemSelect: (itemValue)=>{
128
+ setValue((prevValue)=>prevValue === itemValue ? '' : itemValue
129
+ );
130
+ },
131
+ onItemDismiss: ()=>setValue('')
62
132
  }, /*#__PURE__*/ $yHMN2$createElement($yHMN2$Primitive.nav, $yHMN2$babelruntimehelpersesmextends({
63
133
  "aria-label": "Main",
64
134
  "data-orientation": orientation,
@@ -74,17 +144,25 @@ const $322c88a641701f3b$export$5b2278cf1e8bcae2 = /*#__PURE__*/ $yHMN2$forwardRe
74
144
  * NavigationMenuSub
75
145
  * -----------------------------------------------------------------------------------------------*/ const $322c88a641701f3b$var$SUB_NAME = 'NavigationMenuSub';
76
146
  const $322c88a641701f3b$export$5958edd6c4ee7c79 = /*#__PURE__*/ $yHMN2$forwardRef((props, forwardedRef)=>{
77
- const { __scopeNavigationMenu: __scopeNavigationMenu , value: value , onValueChange: onValueChange , defaultValue: defaultValue , orientation: orientation = 'horizontal' , ...subProps } = props;
147
+ const { __scopeNavigationMenu: __scopeNavigationMenu , value: valueProp , onValueChange: onValueChange , defaultValue: defaultValue , orientation: orientation = 'horizontal' , ...subProps } = props;
78
148
  const context = $322c88a641701f3b$var$useNavigationMenuContext($322c88a641701f3b$var$SUB_NAME, __scopeNavigationMenu);
149
+ const [value = '', setValue] = $yHMN2$useControllableState({
150
+ prop: valueProp,
151
+ onChange: onValueChange,
152
+ defaultProp: defaultValue
153
+ });
79
154
  return /*#__PURE__*/ $yHMN2$createElement($322c88a641701f3b$var$NavigationMenuProvider, {
80
155
  scope: __scopeNavigationMenu,
81
156
  isRootMenu: false,
82
157
  value: value,
83
- onValueChange: onValueChange,
84
- defaultValue: defaultValue,
85
158
  dir: context.dir,
86
159
  orientation: orientation,
87
- rootNavigationMenu: context.rootNavigationMenu
160
+ rootNavigationMenu: context.rootNavigationMenu,
161
+ onTriggerEnter: (itemValue)=>setValue(itemValue)
162
+ ,
163
+ onItemSelect: (itemValue)=>setValue(itemValue)
164
+ ,
165
+ onItemDismiss: ()=>setValue('')
88
166
  }, /*#__PURE__*/ $yHMN2$createElement($yHMN2$Primitive.div, $yHMN2$babelruntimehelpersesmextends({
89
167
  "data-orientation": orientation
90
168
  }, subProps, {
@@ -95,22 +173,10 @@ const $322c88a641701f3b$export$5958edd6c4ee7c79 = /*#__PURE__*/ $yHMN2$forwardRe
95
173
  displayName: $322c88a641701f3b$var$SUB_NAME
96
174
  });
97
175
  /* -----------------------------------------------------------------------------------------------*/ const $322c88a641701f3b$var$NavigationMenuProvider = (props)=>{
98
- const { scope: scope , isRootMenu: isRootMenu , rootNavigationMenu: rootNavigationMenu , value: valueProp , onValueChange: onValueChange , defaultValue: defaultValue , dir: dir , orientation: orientation , children: children } = props;
176
+ const { scope: scope , isRootMenu: isRootMenu , rootNavigationMenu: rootNavigationMenu , dir: dir , orientation: orientation , children: children , value: value , onItemSelect: onItemSelect , onItemDismiss: onItemDismiss , onTriggerEnter: onTriggerEnter , onTriggerLeave: onTriggerLeave , onContentEnter: onContentEnter , onContentLeave: onContentLeave } = props;
99
177
  const [viewport, setViewport] = $yHMN2$useState(null);
100
178
  const [viewportContent, setViewportContent] = $yHMN2$useState(new Map());
101
179
  const [indicatorTrack, setIndicatorTrack] = $yHMN2$useState(null);
102
- const closeTimerRef = $yHMN2$useRef(0);
103
- const [value = '', setValue] = $yHMN2$useControllableState({
104
- prop: valueProp,
105
- onChange: onValueChange,
106
- defaultProp: defaultValue
107
- });
108
- $yHMN2$useEffect(()=>{
109
- return ()=>window.clearTimeout(closeTimerRef.current)
110
- ;
111
- }, [
112
- closeTimerRef
113
- ]);
114
180
  return /*#__PURE__*/ $yHMN2$createElement($322c88a641701f3b$var$NavigationMenuProviderImpl, {
115
181
  scope: scope,
116
182
  isRootMenu: isRootMenu,
@@ -124,35 +190,12 @@ const $322c88a641701f3b$export$5958edd6c4ee7c79 = /*#__PURE__*/ $yHMN2$forwardRe
124
190
  onViewportChange: setViewport,
125
191
  indicatorTrack: indicatorTrack,
126
192
  onIndicatorTrackChange: setIndicatorTrack,
127
- onItemOver: $yHMN2$useCallback((itemValue)=>{
128
- if (isRootMenu) window.clearTimeout(closeTimerRef.current);
129
- setValue(itemValue);
130
- }, [
131
- setValue,
132
- isRootMenu
133
- ]),
134
- onItemLeave: $yHMN2$useCallback(()=>{
135
- if (isRootMenu) {
136
- window.clearTimeout(closeTimerRef.current);
137
- closeTimerRef.current = window.setTimeout(()=>setValue('')
138
- , 150);
139
- }
140
- }, [
141
- setValue,
142
- isRootMenu
143
- ]),
144
- onItemSelect: $yHMN2$useCallback((itemValue)=>{
145
- setValue((prevValue)=>{
146
- return isRootMenu ? prevValue === itemValue ? '' : itemValue : itemValue;
147
- });
148
- }, [
149
- setValue,
150
- isRootMenu
151
- ]),
152
- onItemDismiss: $yHMN2$useCallback(()=>setValue('')
153
- , [
154
- setValue
155
- ]),
193
+ onTriggerEnter: $yHMN2$useCallbackRef(onTriggerEnter),
194
+ onTriggerLeave: $yHMN2$useCallbackRef(onTriggerLeave),
195
+ onContentEnter: $yHMN2$useCallbackRef(onContentEnter),
196
+ onContentLeave: $yHMN2$useCallbackRef(onContentLeave),
197
+ onItemSelect: $yHMN2$useCallbackRef(onItemSelect),
198
+ onItemDismiss: $yHMN2$useCallbackRef(onItemDismiss),
156
199
  onViewportContentChange: $yHMN2$useCallback((contentValue, contentData)=>{
157
200
  setViewportContent((prevContent)=>{
158
201
  prevContent.set(contentValue, contentData);
@@ -211,6 +254,7 @@ const $322c88a641701f3b$export$ffdbb83a2de845c2 = /*#__PURE__*/ $yHMN2$forwardRe
211
254
  const triggerRef = $yHMN2$useRef(null);
212
255
  const focusProxyRef = $yHMN2$useRef(null);
213
256
  const restoreContentTabOrderRef = $yHMN2$useRef(()=>{});
257
+ const wasEscapeCloseRef = $yHMN2$useRef(false);
214
258
  const handleContentEntry = $yHMN2$useCallback((side = 'start')=>{
215
259
  if (contentRef.current) {
216
260
  restoreContentTabOrderRef.current();
@@ -230,6 +274,7 @@ const $322c88a641701f3b$export$ffdbb83a2de845c2 = /*#__PURE__*/ $yHMN2$forwardRe
230
274
  triggerRef: triggerRef,
231
275
  contentRef: contentRef,
232
276
  focusProxyRef: focusProxyRef,
277
+ wasEscapeCloseRef: wasEscapeCloseRef,
233
278
  onEntryKeyDown: handleContentEntry,
234
279
  onFocusProxyEnter: handleContentEntry,
235
280
  onRootContentClose: handleContentExit,
@@ -252,6 +297,7 @@ const $322c88a641701f3b$export$37fe8002734d8f2 = /*#__PURE__*/ $yHMN2$forwardRef
252
297
  const composedRefs = $yHMN2$useComposedRefs(ref, itemContext.triggerRef, forwardedRef);
253
298
  const triggerId = $322c88a641701f3b$var$makeTriggerId(context.baseId, itemContext.value);
254
299
  const contentId = $322c88a641701f3b$var$makeContentId(context.baseId, itemContext.value);
300
+ const hasPointerMoveOpenedRef = $yHMN2$useRef(false);
255
301
  const wasClickCloseRef = $yHMN2$useRef(false);
256
302
  const open = itemContext.value === context.value;
257
303
  return /*#__PURE__*/ $yHMN2$createElement($yHMN2$Fragment, null, /*#__PURE__*/ $yHMN2$createElement($322c88a641701f3b$var$Collection.ItemSlot, {
@@ -270,14 +316,17 @@ const $322c88a641701f3b$export$37fe8002734d8f2 = /*#__PURE__*/ $yHMN2$forwardRef
270
316
  ref: composedRefs,
271
317
  onPointerEnter: $yHMN2$composeEventHandlers(props.onPointerEnter, ()=>{
272
318
  wasClickCloseRef.current = false;
319
+ itemContext.wasEscapeCloseRef.current = false;
273
320
  }),
274
321
  onPointerMove: $yHMN2$composeEventHandlers(props.onPointerMove, $322c88a641701f3b$var$whenMouse(()=>{
275
- if (disabled || wasClickCloseRef.current) return;
276
- context.onItemOver(itemContext.value);
322
+ if (disabled || wasClickCloseRef.current || itemContext.wasEscapeCloseRef.current || hasPointerMoveOpenedRef.current) return;
323
+ context.onTriggerEnter(itemContext.value);
324
+ hasPointerMoveOpenedRef.current = true;
277
325
  })),
278
326
  onPointerLeave: $yHMN2$composeEventHandlers(props.onPointerLeave, $322c88a641701f3b$var$whenMouse(()=>{
279
327
  if (disabled) return;
280
- context.onItemLeave();
328
+ context.onTriggerLeave();
329
+ hasPointerMoveOpenedRef.current = false;
281
330
  })),
282
331
  onClick: $yHMN2$composeEventHandlers(props.onClick, ()=>{
283
332
  context.onItemSelect(itemContext.value);
@@ -430,6 +479,7 @@ const $322c88a641701f3b$export$38e00e996c2f93f7 = /*#__PURE__*/ $yHMN2$forwardRe
430
479
  value: itemContext.value,
431
480
  triggerRef: itemContext.triggerRef,
432
481
  focusProxyRef: itemContext.focusProxyRef,
482
+ wasEscapeCloseRef: itemContext.wasEscapeCloseRef,
433
483
  onContentFocusOutside: itemContext.onContentFocusOutside,
434
484
  onRootContentClose: itemContext.onRootContentClose,
435
485
  ...contentProps
@@ -440,10 +490,8 @@ const $322c88a641701f3b$export$38e00e996c2f93f7 = /*#__PURE__*/ $yHMN2$forwardRe
440
490
  "data-state": $322c88a641701f3b$var$getOpenState(open)
441
491
  }, commonProps, {
442
492
  ref: composedRefs,
443
- onPointerEnter: $yHMN2$composeEventHandlers(props.onPointerEnter, ()=>{
444
- context.onItemOver(itemContext.value);
445
- }),
446
- onPointerLeave: $yHMN2$composeEventHandlers(props.onPointerLeave, $322c88a641701f3b$var$whenMouse(context.onItemLeave)),
493
+ onPointerEnter: $yHMN2$composeEventHandlers(props.onPointerEnter, context.onContentEnter),
494
+ onPointerLeave: $yHMN2$composeEventHandlers(props.onPointerLeave, $322c88a641701f3b$var$whenMouse(context.onContentLeave)),
447
495
  style: {
448
496
  // Prevent interaction when animating out
449
497
  pointerEvents: !open && context.isRootMenu ? 'none' : undefined,
@@ -482,7 +530,7 @@ const $322c88a641701f3b$export$38e00e996c2f93f7 = /*#__PURE__*/ $yHMN2$forwardRe
482
530
  });
483
531
  /* -----------------------------------------------------------------------------------------------*/ const $322c88a641701f3b$var$ROOT_CONTENT_DISMISS = 'navigationMenu.rootContentDismiss';
484
532
  const $322c88a641701f3b$var$NavigationMenuContentImpl = /*#__PURE__*/ $yHMN2$forwardRef((props, forwardedRef)=>{
485
- const { __scopeNavigationMenu: __scopeNavigationMenu , value: value , triggerRef: triggerRef , focusProxyRef: focusProxyRef , onRootContentClose: onRootContentClose , onContentFocusOutside: onContentFocusOutside , ...contentProps } = props;
533
+ const { __scopeNavigationMenu: __scopeNavigationMenu , value: value , triggerRef: triggerRef , focusProxyRef: focusProxyRef , wasEscapeCloseRef: wasEscapeCloseRef , onRootContentClose: onRootContentClose , onContentFocusOutside: onContentFocusOutside , ...contentProps } = props;
486
534
  const context = $322c88a641701f3b$var$useNavigationMenuContext($322c88a641701f3b$var$CONTENT_NAME, __scopeNavigationMenu);
487
535
  const ref = $yHMN2$useRef(null);
488
536
  const composedRefs = $yHMN2$useComposedRefs(ref, forwardedRef);
@@ -594,6 +642,11 @@ const $322c88a641701f3b$var$NavigationMenuContentImpl = /*#__PURE__*/ $yHMN2$for
594
642
  (_focusProxyRef$curren = focusProxyRef.current) === null || _focusProxyRef$curren === void 0 || _focusProxyRef$curren.focus();
595
643
  }
596
644
  }
645
+ }),
646
+ onEscapeKeyDown: $yHMN2$composeEventHandlers(props.onEscapeKeyDown, (event)=>{
647
+ // prevent the dropdown from reopening
648
+ // after the escape key has been pressed
649
+ wasEscapeCloseRef.current = true;
597
650
  })
598
651
  })));
599
652
  });
@@ -649,10 +702,8 @@ const $322c88a641701f3b$export$ee880b97cc6d44a5 = /*#__PURE__*/ $yHMN2$forwardRe
649
702
  ['--radix-navigation-menu-viewport-height']: viewportHeight,
650
703
  ...viewportImplProps.style
651
704
  },
652
- onPointerEnter: $yHMN2$composeEventHandlers(props1.onPointerEnter, ()=>{
653
- context.onItemOver(activeContentValue);
654
- }),
655
- onPointerLeave: $yHMN2$composeEventHandlers(props1.onPointerLeave, $322c88a641701f3b$var$whenMouse(context.onItemLeave))
705
+ onPointerEnter: $yHMN2$composeEventHandlers(props1.onPointerEnter, context.onContentEnter),
706
+ onPointerLeave: $yHMN2$composeEventHandlers(props1.onPointerLeave, $322c88a641701f3b$var$whenMouse(context.onContentLeave))
656
707
  }), Array.from(viewportContentContext.items).map(([value, { ref: ref , forceMount: forceMount , ...props }])=>{
657
708
  const isActive = activeContentValue === value;
658
709
  return /*#__PURE__*/ $yHMN2$createElement($yHMN2$Presence, {