@@ -118,18 +118,20 @@ const NavigationMenu = React.forwardRef<NavigationMenuElement, NavigationMenuPro
118
118
const closeTimerRef = React . useRef ( 0 ) ;
119
119
const skipDelayTimerRef = React . useRef ( 0 ) ;
120
120
const [ isOpenDelayed , setIsOpenDelayed ] = React . useState ( true ) ;
121
+ const documentWindow = useDocument ( ) ?. defaultView ;
121
122
const [ value = '' , setValue ] = useControllableState ( {
122
123
prop : valueProp ,
123
124
onChange : ( value ) => {
124
125
const isOpen = value !== '' ;
125
126
const hasSkipDelayDuration = skipDelayDuration > 0 ;
126
127
127
128
if ( isOpen ) {
128
- window . clearTimeout ( skipDelayTimerRef . current ) ;
129
+ documentWindow ? .clearTimeout ( skipDelayTimerRef . current ) ;
129
130
if ( hasSkipDelayDuration ) setIsOpenDelayed ( false ) ;
130
131
} else {
131
- window . clearTimeout ( skipDelayTimerRef . current ) ;
132
- skipDelayTimerRef . current = window . setTimeout (
132
+ documentWindow ?. clearTimeout ( skipDelayTimerRef . current ) ;
133
+ if ( ! documentWindow ) return ;
134
+ skipDelayTimerRef . current = documentWindow . setTimeout (
133
135
( ) => setIsOpenDelayed ( true ) ,
134
136
skipDelayDuration
135
137
) ;
@@ -141,16 +143,17 @@ const NavigationMenu = React.forwardRef<NavigationMenuElement, NavigationMenuPro
141
143
} ) ;
142
144
143
145
const startCloseTimer = React . useCallback ( ( ) => {
144
- window . clearTimeout ( closeTimerRef . current ) ;
145
- closeTimerRef . current = window . setTimeout ( ( ) => setValue ( '' ) , 150 ) ;
146
- } , [ setValue ] ) ;
146
+ if ( ! documentWindow ) return ;
147
+ documentWindow . clearTimeout ( closeTimerRef . current ) ;
148
+ closeTimerRef . current = documentWindow . setTimeout ( ( ) => setValue ( '' ) , 150 ) ;
149
+ } , [ setValue , documentWindow ] ) ;
147
150
148
151
const handleOpen = React . useCallback (
149
152
( itemValue : string ) => {
150
- window . clearTimeout ( closeTimerRef . current ) ;
153
+ documentWindow ? .clearTimeout ( closeTimerRef . current ) ;
151
154
setValue ( itemValue ) ;
152
155
} ,
153
- [ setValue ]
156
+ [ setValue , documentWindow ]
154
157
) ;
155
158
156
159
const handleDelayedOpen = React . useCallback (
@@ -159,24 +162,24 @@ const NavigationMenu = React.forwardRef<NavigationMenuElement, NavigationMenuPro
159
162
if ( isOpenItem ) {
160
163
// If the item is already open (e.g. we're transitioning from the content to the trigger)
161
164
// then we want to clear the close timer immediately.
162
- window . clearTimeout ( closeTimerRef . current ) ;
163
- } else {
164
- openTimerRef . current = window . setTimeout ( ( ) => {
165
- window . clearTimeout ( closeTimerRef . current ) ;
165
+ documentWindow ? .clearTimeout ( closeTimerRef . current ) ;
166
+ } else if ( documentWindow ) {
167
+ openTimerRef . current = documentWindow . setTimeout ( ( ) => {
168
+ documentWindow . clearTimeout ( closeTimerRef . current ) ;
166
169
setValue ( itemValue ) ;
167
170
} , delayDuration ) ;
168
171
}
169
172
} ,
170
- [ value , setValue , delayDuration ]
173
+ [ value , setValue , delayDuration , documentWindow ]
171
174
) ;
172
175
173
176
React . useEffect ( ( ) => {
174
177
return ( ) => {
175
- window . clearTimeout ( openTimerRef . current ) ;
176
- window . clearTimeout ( closeTimerRef . current ) ;
177
- window . clearTimeout ( skipDelayTimerRef . current ) ;
178
+ documentWindow ? .clearTimeout ( openTimerRef . current ) ;
179
+ documentWindow ? .clearTimeout ( closeTimerRef . current ) ;
180
+ documentWindow ? .clearTimeout ( skipDelayTimerRef . current ) ;
178
181
} ;
179
- } , [ ] ) ;
182
+ } , [ documentWindow ] ) ;
180
183
181
184
return (
182
185
< NavigationMenuProvider
@@ -187,15 +190,15 @@ const NavigationMenu = React.forwardRef<NavigationMenuElement, NavigationMenuPro
187
190
orientation = { orientation }
188
191
rootNavigationMenu = { navigationMenu }
189
192
onTriggerEnter = { ( itemValue ) => {
190
- window . clearTimeout ( openTimerRef . current ) ;
193
+ documentWindow ? .clearTimeout ( openTimerRef . current ) ;
191
194
if ( isOpenDelayed ) handleDelayedOpen ( itemValue ) ;
192
195
else handleOpen ( itemValue ) ;
193
196
} }
194
197
onTriggerLeave = { ( ) => {
195
- window . clearTimeout ( openTimerRef . current ) ;
198
+ documentWindow ? .clearTimeout ( openTimerRef . current ) ;
196
199
startCloseTimer ( ) ;
197
200
} }
198
- onContentEnter = { ( ) => window . clearTimeout ( closeTimerRef . current ) }
201
+ onContentEnter = { ( ) => documentWindow ? .clearTimeout ( closeTimerRef . current ) }
199
202
onContentLeave = { startCloseTimer }
200
203
onItemSelect = { ( itemValue ) => {
201
204
setValue ( ( prevValue ) => ( prevValue === itemValue ? '' : itemValue ) ) ;
@@ -1220,10 +1223,11 @@ function removeFromTabOrder(candidates: HTMLElement[]) {
1220
1223
}
1221
1224
1222
1225
function useResizeObserver ( element : HTMLElement | null , onResize : ( ) => void ) {
1226
+ const documentWindow = useDocument ( ) ?. defaultView ;
1223
1227
const handleResize = useCallbackRef ( onResize ) ;
1224
1228
useLayoutEffect ( ( ) => {
1225
1229
let rAF = 0 ;
1226
- if ( element ) {
1230
+ if ( element && documentWindow ) {
1227
1231
/**
1228
1232
* Resize Observer will throw an often benign error that says `ResizeObserver loop
1229
1233
* completed with undelivered notifications`. This means that ResizeObserver was not
@@ -1233,15 +1237,15 @@ function useResizeObserver(element: HTMLElement | null, onResize: () => void) {
1233
1237
*/
1234
1238
const resizeObserver = new ResizeObserver ( ( ) => {
1235
1239
cancelAnimationFrame ( rAF ) ;
1236
- rAF = window . requestAnimationFrame ( handleResize ) ;
1240
+ rAF = documentWindow . requestAnimationFrame ( handleResize ) ;
1237
1241
} ) ;
1238
1242
resizeObserver . observe ( element ) ;
1239
1243
return ( ) => {
1240
- window . cancelAnimationFrame ( rAF ) ;
1244
+ documentWindow . cancelAnimationFrame ( rAF ) ;
1241
1245
resizeObserver . unobserve ( element ) ;
1242
1246
} ;
1243
1247
}
1244
- } , [ element , handleResize ] ) ;
1248
+ } , [ element , handleResize , documentWindow ] ) ;
1245
1249
}
1246
1250
1247
1251
function getOpenState ( open : boolean ) {
0 commit comments