@wordpress/compose 8.7.2-next.v.202609031004.0 → 8.8.2-next.v.202609171837.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/CHANGELOG.md +11 -1
  2. package/README.md +90 -90
  3. package/build/hooks/use-fixed-window-list/index.cjs.map +2 -2
  4. package/build/hooks/use-focus-outside/index.cjs +1 -0
  5. package/build/hooks/use-focus-outside/index.cjs.map +2 -2
  6. package/build/hooks/use-keyboard-shortcut/index.cjs.map +2 -2
  7. package/build/hooks/use-resize-observer/use-resize-observer.cjs +9 -0
  8. package/build/hooks/use-resize-observer/use-resize-observer.cjs.map +2 -2
  9. package/build-module/hooks/use-fixed-window-list/index.mjs.map +2 -2
  10. package/build-module/hooks/use-focus-outside/index.mjs +1 -0
  11. package/build-module/hooks/use-focus-outside/index.mjs.map +2 -2
  12. package/build-module/hooks/use-keyboard-shortcut/index.mjs.map +2 -2
  13. package/build-module/hooks/use-resize-observer/use-resize-observer.mjs +10 -1
  14. package/build-module/hooks/use-resize-observer/use-resize-observer.mjs.map +2 -2
  15. package/build-types/hooks/use-focus-outside/index.d.ts.map +1 -1
  16. package/build-types/hooks/use-resize-observer/use-resize-observer.d.ts.map +1 -1
  17. package/package.json +13 -13
  18. package/src/higher-order/pure/test/index.jsdom.test.jsx +1 -0
  19. package/src/higher-order/with-global-events/test/index.jsdom.test.jsx +18 -15
  20. package/src/higher-order/with-global-events/test/listener.jsdom.test.js +13 -4
  21. package/src/higher-order/with-instance-id/test/index.jsdom.test.jsx +1 -0
  22. package/src/higher-order/with-state/test/index.jsdom.test.jsx +1 -0
  23. package/src/hooks/use-copy-on-click/test/index.jsdom.test.tsx +18 -17
  24. package/src/hooks/use-copy-to-clipboard/test/index.jsdom.test.tsx +12 -11
  25. package/src/hooks/use-dialog/test/index.jsdom.test.tsx +14 -13
  26. package/src/hooks/use-disabled/test/index.jsdom.test.jsx +1 -0
  27. package/src/hooks/use-drop-zone/test/index.jsdom.test.jsx +1 -0
  28. package/src/hooks/use-fixed-window-list/index.ts +1 -1
  29. package/src/hooks/use-focus-outside/index.ts +3 -3
  30. package/src/hooks/use-focus-outside/test/index.jsdom.test.jsx +7 -8
  31. package/src/hooks/use-instance-id/test/index.jsdom.test.jsx +1 -0
  32. package/src/hooks/use-keyboard-shortcut/index.ts +3 -3
  33. package/src/hooks/use-media-query/test/{index.jsdom.test.jsx → index.browser.test.jsx} +23 -21
  34. package/src/hooks/use-merge-refs/test/index.jsdom.test.jsx +1 -0
  35. package/src/hooks/use-observable-value/test/index.jsdom.test.jsx +2 -1
  36. package/src/hooks/use-resize-observer/test/index.browser.test.ts +24 -0
  37. package/src/hooks/use-resize-observer/use-resize-observer.ts +13 -1
  38. package/src/hooks/use-state-with-history/test/index.jsdom.test.jsx +1 -0
  39. package/src/hooks/use-viewport-match/test/index.jsdom.test.jsx +2 -3
  40. package/src/utils/subscribe-delegated-listener/test/index.jsdom.test.js +17 -16
package/CHANGELOG.md CHANGED
@@ -2,7 +2,17 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
- ## 8.7.1-next.0 (2026-09-03)
5
+ ## 8.8.1-next.0 (2026-09-17)
6
+
7
+ ### Bug Fixes
8
+
9
+ - `useFocusOutside`: Cancel the previous pending blur check so repeated blur events from portaled content do not report focus leaving after it returns ([#81930](https://github.com/WordPress/gutenberg/pull/81930)).
10
+
11
+ ## 8.8.0 (2026-09-10)
12
+
13
+ ### Bug Fixes
14
+
15
+ - `useResizeObserver`: Disconnect the observer when the hook unmounts so queued callbacks cannot run after teardown ([#82687](https://github.com/WordPress/gutenberg/pull/82687)).
6
16
 
7
17
  ### Internal
8
18
 
package/README.md CHANGED
@@ -69,7 +69,7 @@ This is inspired by `lodash`'s `flowRight` function.
69
69
 
70
70
  _Related_
71
71
 
72
- - <https://lodash.com/docs/4#flow-right>
72
+ - <https://lodash.com/docs/4#flow-right>
73
73
 
74
74
  ### createHigherOrderComponent
75
75
 
@@ -77,12 +77,12 @@ Given a function mapping a component to an enhanced component and modifier name,
77
77
 
78
78
  _Parameters_
79
79
 
80
- - _mapComponent_ `( Inner: TInner ) => TOuter`: Function mapping component to enhanced component.
81
- - _modifierName_ `string`: Seed name from which to generated display name.
80
+ - _mapComponent_ `( Inner: TInner ) => TOuter`: Function mapping component to enhanced component.
81
+ - _modifierName_ `string`: Seed name from which to generated display name.
82
82
 
83
83
  _Returns_
84
84
 
85
- - Component class with generated display name assigned.
85
+ - Component class with generated display name assigned.
86
86
 
87
87
  ### debounce
88
88
 
@@ -96,16 +96,16 @@ If `wait` is `0` and `leading` is `false`, `func` invocation is deferred until t
96
96
 
97
97
  _Parameters_
98
98
 
99
- - _func_ `Function`: The function to debounce.
100
- - _wait_ `number`: The number of milliseconds to delay.
101
- - _options_ `Partial< DebounceOptions >`: The options object.
102
- - _options.leading_ `boolean`: Specify invoking on the leading edge of the timeout.
103
- - _options.maxWait_ `number`: The maximum time `func` is allowed to be delayed before it's invoked.
104
- - _options.trailing_ `boolean`: Specify invoking on the trailing edge of the timeout.
99
+ - _func_ `Function`: The function to debounce.
100
+ - _wait_ `number`: The number of milliseconds to delay.
101
+ - _options_ `Partial< DebounceOptions >`: The options object.
102
+ - _options.leading_ `boolean`: Specify invoking on the leading edge of the timeout.
103
+ - _options.maxWait_ `number`: The maximum time `func` is allowed to be delayed before it's invoked.
104
+ - _options.trailing_ `boolean`: Specify invoking on the trailing edge of the timeout.
105
105
 
106
106
  _Returns_
107
107
 
108
- - Returns the new debounced function.
108
+ - Returns the new debounced function.
109
109
 
110
110
  ### ifCondition
111
111
 
@@ -123,11 +123,11 @@ const ConditionalComponent = ifCondition( ( props: Props ) => props.foo.length !
123
123
 
124
124
  _Parameters_
125
125
 
126
- - _predicate_ `( props: Props ) => boolean`: Function to test condition.
126
+ - _predicate_ `( props: Props ) => boolean`: Function to test condition.
127
127
 
128
128
  _Returns_
129
129
 
130
- - Higher-order component.
130
+ - Higher-order component.
131
131
 
132
132
  ### observableMap
133
133
 
@@ -135,7 +135,7 @@ A constructor (factory) for `ObservableMap`, a map-like key/value data structure
135
135
 
136
136
  _Returns_
137
137
 
138
- - `ObservableMap< K, V >`: A new instance of the `ObservableMap` type.
138
+ - `ObservableMap< K, V >`: A new instance of the `ObservableMap` type.
139
139
 
140
140
  ### pipe
141
141
 
@@ -145,7 +145,7 @@ This is inspired by `lodash`'s `flow` function.
145
145
 
146
146
  _Related_
147
147
 
148
- - <https://lodash.com/docs/4#flow>
148
+ - <https://lodash.com/docs/4#flow>
149
149
 
150
150
  ### privateApis
151
151
 
@@ -169,15 +169,15 @@ If `wait` is `0` and `leading` is `false`, `func` invocation is deferred until t
169
169
 
170
170
  _Parameters_
171
171
 
172
- - _func_ `Function`: The function to throttle.
173
- - _wait_ `number`: The number of milliseconds to throttle invocations to.
174
- - _options_ `Partial< ThrottleOptions >`: The options object.
175
- - _options.leading_ `boolean`: Specify invoking on the leading edge of the timeout.
176
- - _options.trailing_ `boolean`: Specify invoking on the trailing edge of the timeout.
172
+ - _func_ `Function`: The function to throttle.
173
+ - _wait_ `number`: The number of milliseconds to throttle invocations to.
174
+ - _options_ `Partial< ThrottleOptions >`: The options object.
175
+ - _options.leading_ `boolean`: Specify invoking on the leading edge of the timeout.
176
+ - _options.trailing_ `boolean`: Specify invoking on the trailing edge of the timeout.
177
177
 
178
178
  _Returns_
179
179
 
180
- - Returns the new throttled function.
180
+ - Returns the new throttled function.
181
181
 
182
182
  ### useAsyncList
183
183
 
@@ -185,12 +185,12 @@ React hook returns an array which items get asynchronously appended from a sourc
185
185
 
186
186
  _Parameters_
187
187
 
188
- - _list_ `T[]`: Source array.
189
- - _config_ `AsyncListConfig`: Configuration object.
188
+ - _list_ `T[]`: Source array.
189
+ - _config_ `AsyncListConfig`: Configuration object.
190
190
 
191
191
  _Returns_
192
192
 
193
- - `T[]`: Async array.
193
+ - `T[]`: Async array.
194
194
 
195
195
  ### useConstrainedTabbing
196
196
 
@@ -214,7 +214,7 @@ const ConstrainedTabbingExample = () => {
214
214
 
215
215
  _Returns_
216
216
 
217
- - `React.RefCallback< Element >`: Element Ref.
217
+ - `React.RefCallback< Element >`: Element Ref.
218
218
 
219
219
  ### useCopyOnClick
220
220
 
@@ -224,13 +224,13 @@ Copies the text to the clipboard when the element is clicked.
224
224
 
225
225
  _Parameters_
226
226
 
227
- - _ref_ `RefObject< string | Element | NodeListOf< Element > >`: Reference with the element.
228
- - _text_ `string | ( () => string )`: The text to copy.
229
- - _timeout_ `number`: Optional timeout to reset the returned state. 4 seconds by default.
227
+ - _ref_ `RefObject< string | Element | NodeListOf< Element > >`: Reference with the element.
228
+ - _text_ `string | ( () => string )`: The text to copy.
229
+ - _timeout_ `number`: Optional timeout to reset the returned state. 4 seconds by default.
230
230
 
231
231
  _Returns_
232
232
 
233
- - `boolean`: Whether or not the text has been copied. Resets after the timeout.
233
+ - `boolean`: Whether or not the text has been copied. Resets after the timeout.
234
234
 
235
235
  ### useCopyToClipboard
236
236
 
@@ -238,12 +238,12 @@ Copies the given text to the clipboard when the element is clicked.
238
238
 
239
239
  _Parameters_
240
240
 
241
- - _text_ `string | ( () => string )`: The text to copy. Use a function if not already available and expensive to compute.
242
- - _onSuccess_ `() => void`: Called when to text is copied.
241
+ - _text_ `string | ( () => string )`: The text to copy. Use a function if not already available and expensive to compute.
242
+ - _onSuccess_ `() => void`: Called when to text is copied.
243
243
 
244
244
  _Returns_
245
245
 
246
- - `RefCallback< T >`: A ref to assign to the target element.
246
+ - `RefCallback< T >`: A ref to assign to the target element.
247
247
 
248
248
  ### useDebounce
249
249
 
@@ -251,17 +251,17 @@ Debounces a function similar to Lodash's `debounce`. A new debounced function wi
251
251
 
252
252
  _Related_
253
253
 
254
- - <https://lodash.com/docs/4#debounce>
254
+ - <https://lodash.com/docs/4#debounce>
255
255
 
256
256
  _Parameters_
257
257
 
258
- - _fn_ `TFunc`: The function to debounce.
259
- - _wait_ `number`: The number of milliseconds to delay.
260
- - _options_ `DebounceOptions`: The options object.
258
+ - _fn_ `TFunc`: The function to debounce.
259
+ - _wait_ `number`: The number of milliseconds to delay.
260
+ - _options_ `DebounceOptions`: The options object.
261
261
 
262
262
  _Returns_
263
263
 
264
- - `DebouncedFunc< TFunc >`: Debounced function.
264
+ - `DebouncedFunc< TFunc >`: Debounced function.
265
265
 
266
266
  ### useDebouncedInput
267
267
 
@@ -269,11 +269,11 @@ Helper hook for input fields that need to debounce the value before using it.
269
269
 
270
270
  _Parameters_
271
271
 
272
- - _defaultValue_ The default value to use.
272
+ - _defaultValue_ The default value to use.
273
273
 
274
274
  _Returns_
275
275
 
276
- - `[ string, ( value: string ) => void, string ]`: The input value, the setter and the debounced input value.
276
+ - `[ string, ( value: string ) => void, string ]`: The input value, the setter and the debounced input value.
277
277
 
278
278
  ### useDisabled
279
279
 
@@ -302,12 +302,12 @@ const DisabledExample = () => {
302
302
 
303
303
  _Parameters_
304
304
 
305
- - _config_ `Object`: Configuration object.
306
- - _config.isDisabled_ `boolean=`: Whether the element should be disabled.
305
+ - _config_ `Object`: Configuration object.
306
+ - _config.isDisabled_ `boolean=`: Whether the element should be disabled.
307
307
 
308
308
  _Returns_
309
309
 
310
- - `React.RefCallback<HTMLElement>`: Element Ref.
310
+ - `React.RefCallback<HTMLElement>`: Element Ref.
311
311
 
312
312
  ### useEvent
313
313
 
@@ -330,7 +330,7 @@ function Component( props ) {
330
330
 
331
331
  _Parameters_
332
332
 
333
- - _callback_ `T`: The callback function to wrap.
333
+ - _callback_ `T`: The callback function to wrap.
334
334
 
335
335
  ### useFocusableIframe
336
336
 
@@ -338,7 +338,7 @@ Dispatches a bubbling focus event when the iframe receives focus. Use `onFocus`
338
338
 
339
339
  _Returns_
340
340
 
341
- - `RefCallback< HTMLIFrameElement >`: Ref to pass to the iframe.
341
+ - `RefCallback< HTMLIFrameElement >`: Ref to pass to the iframe.
342
342
 
343
343
  ### useFocusOnMount
344
344
 
@@ -362,11 +362,11 @@ const WithFocusOnMount = () => {
362
362
 
363
363
  _Parameters_
364
364
 
365
- - _focusOnMount_ `useFocusOnMount.Mode`: Behavioral mode. Defaults to `"firstElement"` which focuses the first tabbable element within; `"firstInputElement"` focuses the first value control within; `true` focuses the element itself; `false` does nothing.
365
+ - _focusOnMount_ `useFocusOnMount.Mode`: Behavioral mode. Defaults to `"firstElement"` which focuses the first tabbable element within; `"firstInputElement"` focuses the first value control within; `true` focuses the element itself; `false` does nothing.
366
366
 
367
367
  _Returns_
368
368
 
369
- - Ref callback.
369
+ - Ref callback.
370
370
 
371
371
  ### useFocusReturn
372
372
 
@@ -390,11 +390,11 @@ const WithFocusReturn = () => {
390
390
 
391
391
  _Parameters_
392
392
 
393
- - _onFocusReturn_ `() => void`: Overrides the default return behavior.
393
+ - _onFocusReturn_ `() => void`: Overrides the default return behavior.
394
394
 
395
395
  _Returns_
396
396
 
397
- - `React.RefCallback< HTMLElement >`: Element Ref.
397
+ - `React.RefCallback< HTMLElement >`: Element Ref.
398
398
 
399
399
  ### useInstanceId
400
400
 
@@ -408,7 +408,7 @@ More accurately, useInstanceId distinguishes between three different signatures:
408
408
 
409
409
  _Parameters_
410
410
 
411
- - _object_ `object`: Object reference to create an id for.
411
+ - _object_ `object`: Object reference to create an id for.
412
412
 
413
413
  ### useIsomorphicLayoutEffect
414
414
 
@@ -420,17 +420,17 @@ Attach a keyboard shortcut handler.
420
420
 
421
421
  _Related_
422
422
 
423
- - <https://craig.is/killing/mice#api.bind> for information about the `callback` parameter.
423
+ - <https://craig.is/killing/mice#api.bind> for information about the `callback` parameter.
424
424
 
425
425
  _Parameters_
426
426
 
427
- - _shortcuts_ `string[] | string`: Keyboard Shortcuts.
428
- - _callback_ `( e: ExtendedKeyboardEvent, combo: string ) => void`: Shortcut callback.
429
- - _options_ `Partial< KeyboardShortcutConfig >`: Shortcut options.
430
- - _options.bindGlobal_ `Partial< KeyboardShortcutConfig >[ 'bindGlobal' ]`:
431
- - _options.eventName_ `Partial< KeyboardShortcutConfig >[ 'eventName' ]`:
432
- - _options.isDisabled_ `Partial< KeyboardShortcutConfig >[ 'isDisabled' ]`:
433
- - _options.target_ `Partial< KeyboardShortcutConfig >[ 'target' ]`:
427
+ - _shortcuts_ `string[] | string`: Keyboard Shortcuts.
428
+ - _callback_ `( e: ExtendedKeyboardEvent, combo: string ) => void`: Shortcut callback.
429
+ - _options_ `Partial< KeyboardShortcutConfig >`: Shortcut options.
430
+ - _options.bindGlobal_ `Partial< KeyboardShortcutConfig >[ 'bindGlobal' ]`:
431
+ - _options.eventName_ `Partial< KeyboardShortcutConfig >[ 'eventName' ]`:
432
+ - _options.isDisabled_ `Partial< KeyboardShortcutConfig >[ 'isDisabled' ]`:
433
+ - _options.target_ `Partial< KeyboardShortcutConfig >[ 'target' ]`:
434
434
 
435
435
  ### useMediaQuery
436
436
 
@@ -438,12 +438,12 @@ Runs a media query and returns its value when it changes.
438
438
 
439
439
  _Parameters_
440
440
 
441
- - _query_ `[string]`: Media Query.
442
- - _view_ `[Window | undefined]`: Window instance, else default to global window
441
+ - _query_ `[string]`: Media Query.
442
+ - _view_ `[Window | undefined]`: Window instance, else default to global window
443
443
 
444
444
  _Returns_
445
445
 
446
- - `boolean`: return value of the media query.
446
+ - `boolean`: return value of the media query.
447
447
 
448
448
  ### useMergeRefs
449
449
 
@@ -476,11 +476,11 @@ return <div ref={ mergedRefs } />;
476
476
 
477
477
  _Parameters_
478
478
 
479
- - _refs_ `Ref< T >[]`: The refs to be merged.
479
+ - _refs_ `Ref< T >[]`: The refs to be merged.
480
480
 
481
481
  _Returns_
482
482
 
483
- - `RefCallback< T >`: The merged ref callback.
483
+ - `RefCallback< T >`: The merged ref callback.
484
484
 
485
485
  ### useObservableValue
486
486
 
@@ -488,12 +488,12 @@ React hook that lets you observe an entry in an `ObservableMap`. The hook return
488
488
 
489
489
  _Parameters_
490
490
 
491
- - _map_ `ObservableMap< K, V >`: The `ObservableMap` to observe.
492
- - _name_ `K`: The map key to observe.
491
+ - _map_ `ObservableMap< K, V >`: The `ObservableMap` to observe.
492
+ - _name_ `K`: The map key to observe.
493
493
 
494
494
  _Returns_
495
495
 
496
- - `V | undefined`: The value corresponding to the map key requested.
496
+ - `V | undefined`: The value corresponding to the map key requested.
497
497
 
498
498
  ### usePrevious
499
499
 
@@ -501,11 +501,11 @@ Use something's value from the previous render. Based on <https://usehooks.com/u
501
501
 
502
502
  _Parameters_
503
503
 
504
- - _value_ `T`: The value to track.
504
+ - _value_ `T`: The value to track.
505
505
 
506
506
  _Returns_
507
507
 
508
- - `T | undefined`: The value from the previous render.
508
+ - `T | undefined`: The value from the previous render.
509
509
 
510
510
  ### useReducedMotion
511
511
 
@@ -513,7 +513,7 @@ Hook returning whether the user has a preference for reduced motion.
513
513
 
514
514
  _Returns_
515
515
 
516
- - `boolean`: Reduced motion preference value.
516
+ - `boolean`: Reduced motion preference value.
517
517
 
518
518
  ### useRefEffect
519
519
 
@@ -523,12 +523,12 @@ It's worth noting that if the dependencies array is empty, there's not strictly
523
523
 
524
524
  _Parameters_
525
525
 
526
- - _callback_ `( node: TElement ) => ( () => void ) | void`: Callback with ref as argument.
527
- - _dependencies_ `DependencyList`: Dependencies of the callback.
526
+ - _callback_ `( node: TElement ) => ( () => void ) | void`: Callback with ref as argument.
527
+ - _dependencies_ `DependencyList`: Dependencies of the callback.
528
528
 
529
529
  _Returns_
530
530
 
531
- - `RefCallback< TElement | null >`: Ref callback.
531
+ - `RefCallback< TElement | null >`: Ref callback.
532
532
 
533
533
  ### useResizeObserver
534
534
 
@@ -553,8 +553,8 @@ useLayoutEffect( () => {
553
553
 
554
554
  _Parameters_
555
555
 
556
- - _callback_ `ResizeObserverCallback`: The `ResizeObserver` callback - [MDN docs](https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserver/ResizeObserver#callback).
557
- - _options_ `ResizeObserverOptions`: Options passed to `ResizeObserver.observe` when called - [MDN docs](https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserver/observe#options). Changes will be ignored.
556
+ - _callback_ `ResizeObserverCallback`: The `ResizeObserver` callback - [MDN docs](https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserver/ResizeObserver#callback).
557
+ - _options_ `ResizeObserverOptions`: Options passed to `ResizeObserver.observe` when called - [MDN docs](https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserver/observe#options). Changes will be ignored.
558
558
 
559
559
  ### useStateWithHistory
560
560
 
@@ -562,11 +562,11 @@ useState with undo/redo history.
562
562
 
563
563
  _Parameters_
564
564
 
565
- - _initialValue_ `T`: Initial value.
565
+ - _initialValue_ `T`: Initial value.
566
566
 
567
567
  _Returns_
568
568
 
569
- - Value, setValue, hasUndo, hasRedo, undo, redo.
569
+ - Value, setValue, hasUndo, hasRedo, undo, redo.
570
570
 
571
571
  ### useThrottle
572
572
 
@@ -574,17 +574,17 @@ Throttles a function similar to Lodash's `throttle`. A new throttled function wi
574
574
 
575
575
  _Related_
576
576
 
577
- - <https://lodash.com/docs/4#throttle>
577
+ - <https://lodash.com/docs/4#throttle>
578
578
 
579
579
  _Parameters_
580
580
 
581
- - _fn_ `TFunc`: The function to throttle.
582
- - _wait_ `number`: The number of milliseconds to throttle invocations to.
583
- - _options_ `ThrottleOptions`: The options object.
581
+ - _fn_ `TFunc`: The function to throttle.
582
+ - _wait_ `number`: The number of milliseconds to throttle invocations to.
583
+ - _options_ `ThrottleOptions`: The options object.
584
584
 
585
585
  _Returns_
586
586
 
587
- - `DebouncedFunc< TFunc >`: Throttled function.
587
+ - `DebouncedFunc< TFunc >`: Throttled function.
588
588
 
589
589
  ### useViewportMatch
590
590
 
@@ -599,13 +599,13 @@ useViewportMatch( 'medium' );
599
599
 
600
600
  _Parameters_
601
601
 
602
- - _breakpoint_ `Breakpoint`: Breakpoint size name.
603
- - _operator_ `ViewportOperator`: Viewport operator.
604
- - _view_ `Window | undefined`: Window instance in which to perform viewport matching.
602
+ - _breakpoint_ `Breakpoint`: Breakpoint size name.
603
+ - _operator_ `ViewportOperator`: Viewport operator.
604
+ - _view_ `Window | undefined`: Window instance in which to perform viewport matching.
605
605
 
606
606
  _Returns_
607
607
 
608
- - `boolean`: Whether viewport matches query.
608
+ - `boolean`: Whether viewport matches query.
609
609
 
610
610
  ### useWarnOnChange
611
611
 
@@ -623,8 +623,8 @@ function MyComponent( props: Record< string, any > ) {
623
623
 
624
624
  _Parameters_
625
625
 
626
- - _object_ `Record< string, any > | any[]`: Object which changes to compare.
627
- - _prefix_ `string`: Just a prefix to show when console logging.
626
+ - _object_ `Record< string, any > | any[]`: Object which changes to compare.
627
+ - _prefix_ `string`: Just a prefix to show when console logging.
628
628
 
629
629
  ### withGlobalEvents
630
630
 
@@ -634,11 +634,11 @@ Higher-order component creator which, given an object of DOM event types and val
634
634
 
635
635
  _Parameters_
636
636
 
637
- - _eventTypesToHandlers_ `Record<keyof GlobalEventHandlersEventMap, string>`: Object with keys of DOM event type, the value a name of the function on the original component's instance which handles the event.
637
+ - _eventTypesToHandlers_ `Record<keyof GlobalEventHandlersEventMap, string>`: Object with keys of DOM event type, the value a name of the function on the original component's instance which handles the event.
638
638
 
639
639
  _Returns_
640
640
 
641
- - `any`: Higher-order component.
641
+ - `any`: Higher-order component.
642
642
 
643
643
  ### withInstanceId
644
644
 
@@ -656,11 +656,11 @@ A Higher Order Component used to provide and manage internal component state via
656
656
 
657
657
  _Parameters_
658
658
 
659
- - _initialState_ `any`: Optional initial state of the component.
659
+ - _initialState_ `any`: Optional initial state of the component.
660
660
 
661
661
  _Returns_
662
662
 
663
- - `any`: A higher order component wrapper accepting a component that takes the state props + its own props + `setState` and returning a component that only accepts the own props.
663
+ - `any`: A higher order component wrapper accepting a component that takes the state props + its own props + `setState` and returning a component that only accepts the own props.
664
664
 
665
665
  <!-- END TOKEN(Autogenerated API docs) -->
666
666
 
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/hooks/use-fixed-window-list/index.ts"],
4
- "sourcesContent": ["import { useState, useLayoutEffect, useRef } from '@wordpress/element';\nimport { getScrollContainer } from '@wordpress/dom';\nimport { PAGEUP, PAGEDOWN, HOME, END } from '@wordpress/keycodes';\nimport useEvent from '../use-event';\n\nconst DEFAULT_INIT_WINDOW_SIZE = 30;\n\ninterface FixedWindowList {\n\t/** Items visible in the viewport, as of the last rendered window */\n\tvisibleItems: number;\n\t/** Start index of the window */\n\tstart: number;\n\t/** End index of the window */\n\tend: number;\n\t/** Returns true if item is in the window */\n\titemInView: ( index: number ) => boolean;\n}\n\ninterface FixedWindowListOptions {\n\t/** Renders windowOverscan number of items before and after the calculated visible window. */\n\twindowOverscan?: number;\n\t/** When false avoids calculating the window size */\n\tuseWindowing?: boolean;\n\t/** Initial window size to use on first render before we can calculate the window size. */\n\tinitWindowSize?: number;\n\t/** Used to recalculate the window size when the expanded state of a list changes. */\n\texpandedState?: any;\n}\n\n/**\n *\n * @param elementRef Used to find the closest scroll container that contains element.\n * @param itemHeight Fixed item height in pixels\n * @param totalItems Total items in list\n * @param [options] Options object\n * @return Array with the fixed window list and setter\n */\nexport default function useFixedWindowList(\n\telementRef: React.RefObject< HTMLElement >,\n\titemHeight: number,\n\ttotalItems: number,\n\toptions?: FixedWindowListOptions\n): [\n\tFixedWindowList,\n\tReact.Dispatch< React.SetStateAction< FixedWindowList > >,\n] {\n\tconst {\n\t\twindowOverscan,\n\t\tuseWindowing = true,\n\t\tinitWindowSize = DEFAULT_INIT_WINDOW_SIZE,\n\t\texpandedState,\n\t} = options ?? {};\n\n\tconst [ fixedListWindow, setFixedListWindow ] = useState< FixedWindowList >(\n\t\t{\n\t\t\tvisibleItems: initWindowSize,\n\t\t\tstart: 0,\n\t\t\tend: initWindowSize,\n\t\t\titemInView: ( index: number ) => {\n\t\t\t\treturn index >= 0 && index <= initWindowSize;\n\t\t\t},\n\t\t}\n\t);\n\n\t// Kept out of state so that measuring the list does not, on its own, force a\n\t// re-render. Only the rendered window does that.\n\tconst visibleItemsRef = useRef( initWindowSize );\n\n\t// The measuring effect re-runs whenever the list changes, so the effect\n\t// running can't on its own tell the very first measurement from later ones.\n\tconst isFirstMeasurementRef = useRef( true );\n\n\t// Stable identity, so the listeners below never have to be re-attached, and\n\t// reads the latest props on every call.\n\tconst measureWindow = useEvent( ( initRender?: boolean ) => {\n\t\tconst scrollContainer = getScrollContainer( elementRef.current );\n\t\tif ( ! scrollContainer ) {\n\t\t\treturn;\n\t\t}\n\t\tconst visibleItems = Math.ceil(\n\t\t\tscrollContainer.clientHeight / itemHeight\n\t\t);\n\t\tvisibleItemsRef.current = visibleItems;\n\t\tconst isFirstMeasurement = isFirstMeasurementRef.current;\n\t\tisFirstMeasurementRef.current = false;\n\t\t// Aim to keep opening list view fast, afterward we can optimize for scrolling.\n\t\tconst overscan = initRender\n\t\t\t? visibleItems\n\t\t\t: windowOverscan ?? visibleItems;\n\t\tconst firstViewableIndex = Math.floor(\n\t\t\tscrollContainer.scrollTop / itemHeight\n\t\t);\n\t\tconst start = Math.max( 0, firstViewableIndex - overscan );\n\t\tconst end = Math.min(\n\t\t\ttotalItems - 1,\n\t\t\tfirstViewableIndex + visibleItems + overscan\n\t\t);\n\t\tsetFixedListWindow( ( lastWindow ) => {\n\t\t\t// Rendering the window is the expensive part, and for the items in\n\t\t\t// `lastWindow` it is already paid for. When the next window has\n\t\t\t// nothing to add, keep the current one: a window that only shrinks\n\t\t\t// drops nodes that are known to be needed again and forces another\n\t\t\t// style recalculation, with nothing new to show for it.\n\t\t\tif ( lastWindow.start <= start && lastWindow.end >= end ) {\n\t\t\t\treturn lastWindow;\n\t\t\t}\n\t\t\t// The first window is rendered before the list can be measured, so\n\t\t\t// it is sized by `initWindowSize` rather than by the viewport, and\n\t\t\t// the measured window is normally wider than it by the overscan.\n\t\t\t// Nothing has painted yet though, so there is no scrolling for the\n\t\t\t// overscan to absorb: covering the visible items is enough, and\n\t\t\t// keeping that window saves a render pass while the list opens.\n\t\t\tif (\n\t\t\t\tisFirstMeasurement &&\n\t\t\t\tlastWindow.start <= firstViewableIndex &&\n\t\t\t\tlastWindow.end >= firstViewableIndex + visibleItems\n\t\t\t) {\n\t\t\t\treturn lastWindow;\n\t\t\t}\n\t\t\treturn {\n\t\t\t\tvisibleItems,\n\t\t\t\tstart,\n\t\t\t\tend,\n\t\t\t\titemInView: ( index: number ) => {\n\t\t\t\t\treturn start <= index && index <= end;\n\t\t\t\t},\n\t\t\t};\n\t\t} );\n\t} );\n\n\tconst handleKeyDown = useEvent(\n\t\t( event: KeyboardEvent, scrollContainer: Element ) => {\n\t\t\tswitch ( event.keyCode ) {\n\t\t\t\tcase HOME: {\n\t\t\t\t\treturn scrollContainer.scrollTo( { top: 0 } );\n\t\t\t\t}\n\t\t\t\tcase END: {\n\t\t\t\t\treturn scrollContainer.scrollTo( {\n\t\t\t\t\t\ttop: totalItems * itemHeight,\n\t\t\t\t\t} );\n\t\t\t\t}\n\t\t\t\tcase PAGEUP: {\n\t\t\t\t\treturn scrollContainer.scrollTo( {\n\t\t\t\t\t\ttop:\n\t\t\t\t\t\t\tscrollContainer.scrollTop -\n\t\t\t\t\t\t\tvisibleItemsRef.current * itemHeight,\n\t\t\t\t\t} );\n\t\t\t\t}\n\t\t\t\tcase PAGEDOWN: {\n\t\t\t\t\treturn scrollContainer.scrollTo( {\n\t\t\t\t\t\ttop:\n\t\t\t\t\t\t\tscrollContainer.scrollTop +\n\t\t\t\t\t\t\tvisibleItemsRef.current * itemHeight,\n\t\t\t\t\t} );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t);\n\n\t// Measure whenever something that the window is derived from changes.\n\tuseLayoutEffect( () => {\n\t\tif ( ! useWindowing ) {\n\t\t\treturn;\n\t\t}\n\t\tmeasureWindow( true );\n\t}, [\n\t\tuseWindowing,\n\t\tmeasureWindow,\n\t\titemHeight,\n\t\ttotalItems,\n\t\twindowOverscan,\n\t\texpandedState,\n\t] );\n\n\t// Only ever attaches and detaches listeners. The deps are the things that\n\t// can change which element the scroll container is, or whether there is one\n\t// at all: a list that is too short to overflow has no scroll container to\n\t// attach to, and it grows into one by gaining items or by being expanded.\n\tuseLayoutEffect( () => {\n\t\tif ( ! useWindowing ) {\n\t\t\treturn;\n\t\t}\n\t\tconst scrollContainer = getScrollContainer( elementRef.current );\n\t\tif ( ! scrollContainer ) {\n\t\t\treturn;\n\t\t}\n\t\tconst { defaultView } = scrollContainer.ownerDocument;\n\t\t// `scroll` and `resize` already fire at about the rendering rate, so\n\t\t// there is nothing to gain from debouncing them.\n\t\tconst onMeasure = () => measureWindow();\n\t\tconst onKeyDown = ( event: KeyboardEvent ) =>\n\t\t\thandleKeyDown( event, scrollContainer );\n\n\t\tscrollContainer.addEventListener( 'scroll', onMeasure );\n\t\tdefaultView?.addEventListener( 'resize', onMeasure );\n\t\tdefaultView?.addEventListener( 'keydown', onKeyDown );\n\n\t\treturn () => {\n\t\t\tscrollContainer.removeEventListener( 'scroll', onMeasure );\n\t\t\tdefaultView?.removeEventListener( 'resize', onMeasure );\n\t\t\tdefaultView?.removeEventListener( 'keydown', onKeyDown );\n\t\t};\n\t}, [\n\t\tuseWindowing,\n\t\telementRef,\n\t\titemHeight,\n\t\ttotalItems,\n\t\texpandedState,\n\t\tmeasureWindow,\n\t\thandleKeyDown,\n\t] );\n\n\treturn [ fixedListWindow, setFixedListWindow ];\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { useState, useLayoutEffect, useRef } from '@wordpress/element';\nimport { getScrollContainer } from '@wordpress/dom';\nimport { PAGEUP, PAGEDOWN, HOME, END } from '@wordpress/keycodes';\nimport useEvent from '../use-event';\n\nconst DEFAULT_INIT_WINDOW_SIZE = 30;\n\ninterface FixedWindowList {\n\t/** Items visible in the viewport, as of the last rendered window */\n\tvisibleItems: number;\n\t/** Start index of the window */\n\tstart: number;\n\t/** End index of the window */\n\tend: number;\n\t/** Returns true if item is in the window */\n\titemInView: ( index: number ) => boolean;\n}\n\ninterface FixedWindowListOptions {\n\t/** Renders windowOverscan number of items before and after the calculated visible window. */\n\twindowOverscan?: number;\n\t/** When false avoids calculating the window size */\n\tuseWindowing?: boolean;\n\t/** Initial window size to use on first render before we can calculate the window size. */\n\tinitWindowSize?: number;\n\t/** Used to recalculate the window size when the expanded state of a list changes. */\n\texpandedState?: any;\n}\n\n/**\n *\n * @param elementRef Used to find the closest scroll container that contains element.\n * @param itemHeight Fixed item height in pixels\n * @param totalItems Total items in list\n * @param [options] Options object\n * @return Array with the fixed window list and setter\n */\nexport default function useFixedWindowList(\n\telementRef: React.RefObject< HTMLElement >,\n\titemHeight: number,\n\ttotalItems: number,\n\toptions?: FixedWindowListOptions\n): [\n\tFixedWindowList,\n\tReact.Dispatch< React.SetStateAction< FixedWindowList > >,\n] {\n\tconst {\n\t\twindowOverscan,\n\t\tuseWindowing = true,\n\t\tinitWindowSize = DEFAULT_INIT_WINDOW_SIZE,\n\t\texpandedState,\n\t} = options ?? {};\n\n\tconst [ fixedListWindow, setFixedListWindow ] = useState< FixedWindowList >(\n\t\t{\n\t\t\tvisibleItems: initWindowSize,\n\t\t\tstart: 0,\n\t\t\tend: initWindowSize,\n\t\t\titemInView: ( index: number ) => {\n\t\t\t\treturn index >= 0 && index <= initWindowSize;\n\t\t\t},\n\t\t}\n\t);\n\n\t// Kept out of state so that measuring the list does not, on its own, force a\n\t// re-render. Only the rendered window does that.\n\tconst visibleItemsRef = useRef( initWindowSize );\n\n\t// The measuring effect re-runs whenever the list changes, so the effect\n\t// running can't on its own tell the very first measurement from later ones.\n\tconst isFirstMeasurementRef = useRef( true );\n\n\t// Stable identity, so the listeners below never have to be re-attached, and\n\t// reads the latest props on every call.\n\tconst measureWindow = useEvent( ( initRender?: boolean ) => {\n\t\tconst scrollContainer = getScrollContainer( elementRef.current );\n\t\tif ( ! scrollContainer ) {\n\t\t\treturn;\n\t\t}\n\t\tconst visibleItems = Math.ceil(\n\t\t\tscrollContainer.clientHeight / itemHeight\n\t\t);\n\t\tvisibleItemsRef.current = visibleItems;\n\t\tconst isFirstMeasurement = isFirstMeasurementRef.current;\n\t\tisFirstMeasurementRef.current = false;\n\t\t// Aim to keep opening list view fast, afterward we can optimize for scrolling.\n\t\tconst overscan = initRender\n\t\t\t? visibleItems\n\t\t\t: ( windowOverscan ?? visibleItems );\n\t\tconst firstViewableIndex = Math.floor(\n\t\t\tscrollContainer.scrollTop / itemHeight\n\t\t);\n\t\tconst start = Math.max( 0, firstViewableIndex - overscan );\n\t\tconst end = Math.min(\n\t\t\ttotalItems - 1,\n\t\t\tfirstViewableIndex + visibleItems + overscan\n\t\t);\n\t\tsetFixedListWindow( ( lastWindow ) => {\n\t\t\t// Rendering the window is the expensive part, and for the items in\n\t\t\t// `lastWindow` it is already paid for. When the next window has\n\t\t\t// nothing to add, keep the current one: a window that only shrinks\n\t\t\t// drops nodes that are known to be needed again and forces another\n\t\t\t// style recalculation, with nothing new to show for it.\n\t\t\tif ( lastWindow.start <= start && lastWindow.end >= end ) {\n\t\t\t\treturn lastWindow;\n\t\t\t}\n\t\t\t// The first window is rendered before the list can be measured, so\n\t\t\t// it is sized by `initWindowSize` rather than by the viewport, and\n\t\t\t// the measured window is normally wider than it by the overscan.\n\t\t\t// Nothing has painted yet though, so there is no scrolling for the\n\t\t\t// overscan to absorb: covering the visible items is enough, and\n\t\t\t// keeping that window saves a render pass while the list opens.\n\t\t\tif (\n\t\t\t\tisFirstMeasurement &&\n\t\t\t\tlastWindow.start <= firstViewableIndex &&\n\t\t\t\tlastWindow.end >= firstViewableIndex + visibleItems\n\t\t\t) {\n\t\t\t\treturn lastWindow;\n\t\t\t}\n\t\t\treturn {\n\t\t\t\tvisibleItems,\n\t\t\t\tstart,\n\t\t\t\tend,\n\t\t\t\titemInView: ( index: number ) => {\n\t\t\t\t\treturn start <= index && index <= end;\n\t\t\t\t},\n\t\t\t};\n\t\t} );\n\t} );\n\n\tconst handleKeyDown = useEvent(\n\t\t( event: KeyboardEvent, scrollContainer: Element ) => {\n\t\t\tswitch ( event.keyCode ) {\n\t\t\t\tcase HOME: {\n\t\t\t\t\treturn scrollContainer.scrollTo( { top: 0 } );\n\t\t\t\t}\n\t\t\t\tcase END: {\n\t\t\t\t\treturn scrollContainer.scrollTo( {\n\t\t\t\t\t\ttop: totalItems * itemHeight,\n\t\t\t\t\t} );\n\t\t\t\t}\n\t\t\t\tcase PAGEUP: {\n\t\t\t\t\treturn scrollContainer.scrollTo( {\n\t\t\t\t\t\ttop:\n\t\t\t\t\t\t\tscrollContainer.scrollTop -\n\t\t\t\t\t\t\tvisibleItemsRef.current * itemHeight,\n\t\t\t\t\t} );\n\t\t\t\t}\n\t\t\t\tcase PAGEDOWN: {\n\t\t\t\t\treturn scrollContainer.scrollTo( {\n\t\t\t\t\t\ttop:\n\t\t\t\t\t\t\tscrollContainer.scrollTop +\n\t\t\t\t\t\t\tvisibleItemsRef.current * itemHeight,\n\t\t\t\t\t} );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t);\n\n\t// Measure whenever something that the window is derived from changes.\n\tuseLayoutEffect( () => {\n\t\tif ( ! useWindowing ) {\n\t\t\treturn;\n\t\t}\n\t\tmeasureWindow( true );\n\t}, [\n\t\tuseWindowing,\n\t\tmeasureWindow,\n\t\titemHeight,\n\t\ttotalItems,\n\t\twindowOverscan,\n\t\texpandedState,\n\t] );\n\n\t// Only ever attaches and detaches listeners. The deps are the things that\n\t// can change which element the scroll container is, or whether there is one\n\t// at all: a list that is too short to overflow has no scroll container to\n\t// attach to, and it grows into one by gaining items or by being expanded.\n\tuseLayoutEffect( () => {\n\t\tif ( ! useWindowing ) {\n\t\t\treturn;\n\t\t}\n\t\tconst scrollContainer = getScrollContainer( elementRef.current );\n\t\tif ( ! scrollContainer ) {\n\t\t\treturn;\n\t\t}\n\t\tconst { defaultView } = scrollContainer.ownerDocument;\n\t\t// `scroll` and `resize` already fire at about the rendering rate, so\n\t\t// there is nothing to gain from debouncing them.\n\t\tconst onMeasure = () => measureWindow();\n\t\tconst onKeyDown = ( event: KeyboardEvent ) =>\n\t\t\thandleKeyDown( event, scrollContainer );\n\n\t\tscrollContainer.addEventListener( 'scroll', onMeasure );\n\t\tdefaultView?.addEventListener( 'resize', onMeasure );\n\t\tdefaultView?.addEventListener( 'keydown', onKeyDown );\n\n\t\treturn () => {\n\t\t\tscrollContainer.removeEventListener( 'scroll', onMeasure );\n\t\t\tdefaultView?.removeEventListener( 'resize', onMeasure );\n\t\t\tdefaultView?.removeEventListener( 'keydown', onKeyDown );\n\t\t};\n\t}, [\n\t\tuseWindowing,\n\t\telementRef,\n\t\titemHeight,\n\t\ttotalItems,\n\t\texpandedState,\n\t\tmeasureWindow,\n\t\thandleKeyDown,\n\t] );\n\n\treturn [ fixedListWindow, setFixedListWindow ];\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["useEvent"]
7
7
  }
@@ -75,6 +75,7 @@ function useFocusOutside(onFocusOutside) {
75
75
  if (ignoreForRelatedTarget && event.relatedTarget?.closest(ignoreForRelatedTarget)) {
76
76
  return;
77
77
  }
78
+ clearTimeout(blurCheckTimeoutIdRef.current);
78
79
  blurCheckTimeoutIdRef.current = setTimeout(() => {
79
80
  if (!document.hasFocus()) {
80
81
  event.preventDefault();
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/hooks/use-focus-outside/index.ts"],
4
- "sourcesContent": ["import { useCallback, useEffect, useRef } from '@wordpress/element';\n\n/**\n * Input types which are classified as button types, for use in considering\n * whether element is a (focus-normalized) button.\n */\nconst INPUT_BUTTON_TYPES = [ 'button', 'submit' ];\n\n/**\n * List of HTML button elements subject to focus normalization\n *\n * @see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/button#Clicking_and_focus\n */\ntype FocusNormalizedButton =\n\t| HTMLButtonElement\n\t| HTMLLinkElement\n\t| HTMLInputElement;\n\n/**\n * Returns true if the given element is a button element subject to focus\n * normalization, or false otherwise.\n *\n * @see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/button#Clicking_and_focus\n *\n * @param eventTarget The target from a mouse or touch event.\n *\n * @return Whether the element is a button element subject to focus normalization.\n */\nfunction isFocusNormalizedButton(\n\teventTarget: EventTarget\n): eventTarget is FocusNormalizedButton {\n\tif ( ! ( eventTarget instanceof window.HTMLElement ) ) {\n\t\treturn false;\n\t}\n\tswitch ( eventTarget.nodeName ) {\n\t\tcase 'A':\n\t\tcase 'BUTTON':\n\t\t\treturn true;\n\n\t\tcase 'INPUT':\n\t\t\treturn INPUT_BUTTON_TYPES.includes(\n\t\t\t\t( eventTarget as HTMLInputElement ).type\n\t\t\t);\n\t}\n\n\treturn false;\n}\n\ntype UseFocusOutsideReturn = {\n\tonFocus: React.FocusEventHandler;\n\tonMouseDown: React.MouseEventHandler;\n\tonMouseUp: React.MouseEventHandler;\n\tonTouchStart: React.TouchEventHandler;\n\tonTouchEnd: React.TouchEventHandler;\n\tonBlur: React.FocusEventHandler;\n};\n\n/**\n * A react hook that can be used to check whether focus has moved outside the\n * element the event handlers are bound to.\n *\n * @param onFocusOutside A callback triggered when focus moves outside\n * the element the event handlers are bound to.\n *\n * @return An object containing event handlers. Bind the event handlers to a\n * wrapping element element to capture when focus moves outside that element.\n */\nexport default function useFocusOutside(\n\tonFocusOutside: ( ( event: React.FocusEvent ) => void ) | undefined\n): UseFocusOutsideReturn {\n\tconst currentOnFocusOutsideRef = useRef( onFocusOutside );\n\tuseEffect( () => {\n\t\tcurrentOnFocusOutsideRef.current = onFocusOutside;\n\t}, [ onFocusOutside ] );\n\n\tconst preventBlurCheckRef = useRef( false );\n\n\tconst blurCheckTimeoutIdRef = useRef< number >( undefined );\n\n\t/**\n\t * Cancel a blur check timeout.\n\t */\n\tconst cancelBlurCheck = useCallback( () => {\n\t\tclearTimeout( blurCheckTimeoutIdRef.current );\n\t}, [] );\n\n\t// Cancel a blur check if the callback or ref is no longer provided.\n\tuseEffect( () => {\n\t\tif ( ! onFocusOutside ) {\n\t\t\tcancelBlurCheck();\n\t\t}\n\t}, [ onFocusOutside, cancelBlurCheck ] );\n\n\t/**\n\t * Handles a mousedown or mouseup event to respectively assign and\n\t * unassign a flag for preventing blur check on button elements. Some\n\t * browsers, namely Firefox and Safari, do not emit a focus event on\n\t * button elements when clicked, while others do. The logic here\n\t * intends to normalize this as treating click on buttons as focus.\n\t *\n\t * @param event\n\t * @see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/button#Clicking_and_focus\n\t */\n\tconst normalizeButtonFocus: React.EventHandler<\n\t\tReact.MouseEvent | React.TouchEvent\n\t> = useCallback( ( event ) => {\n\t\tconst { type, target } = event;\n\t\tconst isInteractionEnd = [ 'mouseup', 'touchend' ].includes( type );\n\n\t\tif ( isInteractionEnd ) {\n\t\t\tpreventBlurCheckRef.current = false;\n\t\t} else if ( isFocusNormalizedButton( target ) ) {\n\t\t\tpreventBlurCheckRef.current = true;\n\t\t}\n\t}, [] );\n\n\t/**\n\t * A callback triggered when a blur event occurs on the element the handler\n\t * is bound to.\n\t *\n\t * Calls the `onFocusOutside` callback in an immediate timeout if focus has\n\t * move outside the bound element and is still within the document.\n\t */\n\tconst queueBlurCheck: React.FocusEventHandler = useCallback( ( event ) => {\n\t\t// React does not allow using an event reference asynchronously\n\t\t// due to recycling behavior, except when explicitly persisted.\n\t\tevent.persist();\n\n\t\t// Skip blur check if clicking button. See `normalizeButtonFocus`.\n\t\tif ( preventBlurCheckRef.current ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// The usage of this attribute should be avoided. The only use case\n\t\t// would be when we load modals that are not React components and\n\t\t// therefore don't exist in the React tree. An example is opening\n\t\t// the Media Library modal from another dialog.\n\t\t// This attribute should contain a selector of the related target\n\t\t// we want to ignore, because we still need to trigger the blur event\n\t\t// on all other cases.\n\t\tconst ignoreForRelatedTarget = event.target.getAttribute(\n\t\t\t'data-unstable-ignore-focus-outside-for-relatedtarget'\n\t\t);\n\t\tif (\n\t\t\tignoreForRelatedTarget &&\n\t\t\tevent.relatedTarget?.closest( ignoreForRelatedTarget )\n\t\t) {\n\t\t\treturn;\n\t\t}\n\n\t\tblurCheckTimeoutIdRef.current = setTimeout( () => {\n\t\t\t// If document is not focused then focus should remain\n\t\t\t// inside the wrapped component and therefore we cancel\n\t\t\t// this blur event thereby leaving focus in place.\n\t\t\t// https://developer.mozilla.org/en-US/docs/Web/API/Document/hasFocus.\n\t\t\tif ( ! document.hasFocus() ) {\n\t\t\t\tevent.preventDefault();\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif ( 'function' === typeof currentOnFocusOutsideRef.current ) {\n\t\t\t\tcurrentOnFocusOutsideRef.current( event );\n\t\t\t}\n\t\t}, 0 );\n\t}, [] );\n\n\treturn {\n\t\tonFocus: cancelBlurCheck,\n\t\tonMouseDown: normalizeButtonFocus,\n\t\tonMouseUp: normalizeButtonFocus,\n\t\tonTouchStart: normalizeButtonFocus,\n\t\tonTouchEnd: normalizeButtonFocus,\n\t\tonBlur: queueBlurCheck,\n\t};\n}\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qBAA+C;AAM/C,IAAM,qBAAqB,CAAE,UAAU,QAAS;AAsBhD,SAAS,wBACR,aACuC;AACvC,MAAK,EAAI,uBAAuB,OAAO,cAAgB;AACtD,WAAO;AAAA,EACR;AACA,UAAS,YAAY,UAAW;AAAA,IAC/B,KAAK;AAAA,IACL,KAAK;AACJ,aAAO;AAAA,IAER,KAAK;AACJ,aAAO,mBAAmB;AAAA,QACvB,YAAkC;AAAA,MACrC;AAAA,EACF;AAEA,SAAO;AACR;AAqBe,SAAR,gBACN,gBACwB;AACxB,QAAM,+BAA2B,uBAAQ,cAAe;AACxD,gCAAW,MAAM;AAChB,6BAAyB,UAAU;AAAA,EACpC,GAAG,CAAE,cAAe,CAAE;AAEtB,QAAM,0BAAsB,uBAAQ,KAAM;AAE1C,QAAM,4BAAwB,uBAAkB,MAAU;AAK1D,QAAM,sBAAkB,4BAAa,MAAM;AAC1C,iBAAc,sBAAsB,OAAQ;AAAA,EAC7C,GAAG,CAAC,CAAE;AAGN,gCAAW,MAAM;AAChB,QAAK,CAAE,gBAAiB;AACvB,sBAAgB;AAAA,IACjB;AAAA,EACD,GAAG,CAAE,gBAAgB,eAAgB,CAAE;AAYvC,QAAM,2BAEF,4BAAa,CAAE,UAAW;AAC7B,UAAM,EAAE,MAAM,OAAO,IAAI;AACzB,UAAM,mBAAmB,CAAE,WAAW,UAAW,EAAE,SAAU,IAAK;AAElE,QAAK,kBAAmB;AACvB,0BAAoB,UAAU;AAAA,IAC/B,WAAY,wBAAyB,MAAO,GAAI;AAC/C,0BAAoB,UAAU;AAAA,IAC/B;AAAA,EACD,GAAG,CAAC,CAAE;AASN,QAAM,qBAA0C,4BAAa,CAAE,UAAW;AAGzE,UAAM,QAAQ;AAGd,QAAK,oBAAoB,SAAU;AAClC;AAAA,IACD;AASA,UAAM,yBAAyB,MAAM,OAAO;AAAA,MAC3C;AAAA,IACD;AACA,QACC,0BACA,MAAM,eAAe,QAAS,sBAAuB,GACpD;AACD;AAAA,IACD;AAEA,0BAAsB,UAAU,WAAY,MAAM;AAKjD,UAAK,CAAE,SAAS,SAAS,GAAI;AAC5B,cAAM,eAAe;AACrB;AAAA,MACD;AAEA,UAAK,eAAe,OAAO,yBAAyB,SAAU;AAC7D,iCAAyB,QAAS,KAAM;AAAA,MACzC;AAAA,IACD,GAAG,CAAE;AAAA,EACN,GAAG,CAAC,CAAE;AAEN,SAAO;AAAA,IACN,SAAS;AAAA,IACT,aAAa;AAAA,IACb,WAAW;AAAA,IACX,cAAc;AAAA,IACd,YAAY;AAAA,IACZ,QAAQ;AAAA,EACT;AACD;",
4
+ "sourcesContent": ["import { useCallback, useEffect, useRef } from '@wordpress/element';\n\n/**\n * Input types which are classified as button types, for use in considering\n * whether element is a (focus-normalized) button.\n */\nconst INPUT_BUTTON_TYPES = [ 'button', 'submit' ];\n\n/**\n * List of HTML button elements subject to focus normalization\n *\n * @see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/button#Clicking_and_focus\n */\ntype FocusNormalizedButton =\n\tHTMLButtonElement | HTMLLinkElement | HTMLInputElement;\n\n/**\n * Returns true if the given element is a button element subject to focus\n * normalization, or false otherwise.\n *\n * @see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/button#Clicking_and_focus\n *\n * @param eventTarget The target from a mouse or touch event.\n *\n * @return Whether the element is a button element subject to focus normalization.\n */\nfunction isFocusNormalizedButton(\n\teventTarget: EventTarget\n): eventTarget is FocusNormalizedButton {\n\tif ( ! ( eventTarget instanceof window.HTMLElement ) ) {\n\t\treturn false;\n\t}\n\tswitch ( eventTarget.nodeName ) {\n\t\tcase 'A':\n\t\tcase 'BUTTON':\n\t\t\treturn true;\n\n\t\tcase 'INPUT':\n\t\t\treturn INPUT_BUTTON_TYPES.includes(\n\t\t\t\t( eventTarget as HTMLInputElement ).type\n\t\t\t);\n\t}\n\n\treturn false;\n}\n\ntype UseFocusOutsideReturn = {\n\tonFocus: React.FocusEventHandler;\n\tonMouseDown: React.MouseEventHandler;\n\tonMouseUp: React.MouseEventHandler;\n\tonTouchStart: React.TouchEventHandler;\n\tonTouchEnd: React.TouchEventHandler;\n\tonBlur: React.FocusEventHandler;\n};\n\n/**\n * A react hook that can be used to check whether focus has moved outside the\n * element the event handlers are bound to.\n *\n * @param onFocusOutside A callback triggered when focus moves outside\n * the element the event handlers are bound to.\n *\n * @return An object containing event handlers. Bind the event handlers to a\n * wrapping element element to capture when focus moves outside that element.\n */\nexport default function useFocusOutside(\n\tonFocusOutside: ( ( event: React.FocusEvent ) => void ) | undefined\n): UseFocusOutsideReturn {\n\tconst currentOnFocusOutsideRef = useRef( onFocusOutside );\n\tuseEffect( () => {\n\t\tcurrentOnFocusOutsideRef.current = onFocusOutside;\n\t}, [ onFocusOutside ] );\n\n\tconst preventBlurCheckRef = useRef( false );\n\n\tconst blurCheckTimeoutIdRef = useRef< number >( undefined );\n\n\t/**\n\t * Cancel a blur check timeout.\n\t */\n\tconst cancelBlurCheck = useCallback( () => {\n\t\tclearTimeout( blurCheckTimeoutIdRef.current );\n\t}, [] );\n\n\t// Cancel a blur check if the callback or ref is no longer provided.\n\tuseEffect( () => {\n\t\tif ( ! onFocusOutside ) {\n\t\t\tcancelBlurCheck();\n\t\t}\n\t}, [ onFocusOutside, cancelBlurCheck ] );\n\n\t/**\n\t * Handles a mousedown or mouseup event to respectively assign and\n\t * unassign a flag for preventing blur check on button elements. Some\n\t * browsers, namely Firefox and Safari, do not emit a focus event on\n\t * button elements when clicked, while others do. The logic here\n\t * intends to normalize this as treating click on buttons as focus.\n\t *\n\t * @param event\n\t * @see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/button#Clicking_and_focus\n\t */\n\tconst normalizeButtonFocus: React.EventHandler<\n\t\tReact.MouseEvent | React.TouchEvent\n\t> = useCallback( ( event ) => {\n\t\tconst { type, target } = event;\n\t\tconst isInteractionEnd = [ 'mouseup', 'touchend' ].includes( type );\n\n\t\tif ( isInteractionEnd ) {\n\t\t\tpreventBlurCheckRef.current = false;\n\t\t} else if ( isFocusNormalizedButton( target ) ) {\n\t\t\tpreventBlurCheckRef.current = true;\n\t\t}\n\t}, [] );\n\n\t/**\n\t * A callback triggered when a blur event occurs on the element the handler\n\t * is bound to.\n\t *\n\t * Calls the `onFocusOutside` callback in an immediate timeout if focus has\n\t * move outside the bound element and is still within the document.\n\t */\n\tconst queueBlurCheck: React.FocusEventHandler = useCallback( ( event ) => {\n\t\t// React does not allow using an event reference asynchronously\n\t\t// due to recycling behavior, except when explicitly persisted.\n\t\tevent.persist();\n\n\t\t// Skip blur check if clicking button. See `normalizeButtonFocus`.\n\t\tif ( preventBlurCheckRef.current ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// The usage of this attribute should be avoided. The only use case\n\t\t// would be when we load modals that are not React components and\n\t\t// therefore don't exist in the React tree. An example is opening\n\t\t// the Media Library modal from another dialog.\n\t\t// This attribute should contain a selector of the related target\n\t\t// we want to ignore, because we still need to trigger the blur event\n\t\t// on all other cases.\n\t\tconst ignoreForRelatedTarget = event.target.getAttribute(\n\t\t\t'data-unstable-ignore-focus-outside-for-relatedtarget'\n\t\t);\n\t\tif (\n\t\t\tignoreForRelatedTarget &&\n\t\t\tevent.relatedTarget?.closest( ignoreForRelatedTarget )\n\t\t) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Keep only the latest blur check so a subsequent focus event can cancel it.\n\t\tclearTimeout( blurCheckTimeoutIdRef.current );\n\t\tblurCheckTimeoutIdRef.current = setTimeout( () => {\n\t\t\t// If document is not focused then focus should remain\n\t\t\t// inside the wrapped component and therefore we cancel\n\t\t\t// this blur event thereby leaving focus in place.\n\t\t\t// https://developer.mozilla.org/en-US/docs/Web/API/Document/hasFocus.\n\t\t\tif ( ! document.hasFocus() ) {\n\t\t\t\tevent.preventDefault();\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif ( 'function' === typeof currentOnFocusOutsideRef.current ) {\n\t\t\t\tcurrentOnFocusOutsideRef.current( event );\n\t\t\t}\n\t\t}, 0 );\n\t}, [] );\n\n\treturn {\n\t\tonFocus: cancelBlurCheck,\n\t\tonMouseDown: normalizeButtonFocus,\n\t\tonMouseUp: normalizeButtonFocus,\n\t\tonTouchStart: normalizeButtonFocus,\n\t\tonTouchEnd: normalizeButtonFocus,\n\t\tonBlur: queueBlurCheck,\n\t};\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qBAA+C;AAM/C,IAAM,qBAAqB,CAAE,UAAU,QAAS;AAoBhD,SAAS,wBACR,aACuC;AACvC,MAAK,EAAI,uBAAuB,OAAO,cAAgB;AACtD,WAAO;AAAA,EACR;AACA,UAAS,YAAY,UAAW;AAAA,IAC/B,KAAK;AAAA,IACL,KAAK;AACJ,aAAO;AAAA,IAER,KAAK;AACJ,aAAO,mBAAmB;AAAA,QACvB,YAAkC;AAAA,MACrC;AAAA,EACF;AAEA,SAAO;AACR;AAqBe,SAAR,gBACN,gBACwB;AACxB,QAAM,+BAA2B,uBAAQ,cAAe;AACxD,gCAAW,MAAM;AAChB,6BAAyB,UAAU;AAAA,EACpC,GAAG,CAAE,cAAe,CAAE;AAEtB,QAAM,0BAAsB,uBAAQ,KAAM;AAE1C,QAAM,4BAAwB,uBAAkB,MAAU;AAK1D,QAAM,sBAAkB,4BAAa,MAAM;AAC1C,iBAAc,sBAAsB,OAAQ;AAAA,EAC7C,GAAG,CAAC,CAAE;AAGN,gCAAW,MAAM;AAChB,QAAK,CAAE,gBAAiB;AACvB,sBAAgB;AAAA,IACjB;AAAA,EACD,GAAG,CAAE,gBAAgB,eAAgB,CAAE;AAYvC,QAAM,2BAEF,4BAAa,CAAE,UAAW;AAC7B,UAAM,EAAE,MAAM,OAAO,IAAI;AACzB,UAAM,mBAAmB,CAAE,WAAW,UAAW,EAAE,SAAU,IAAK;AAElE,QAAK,kBAAmB;AACvB,0BAAoB,UAAU;AAAA,IAC/B,WAAY,wBAAyB,MAAO,GAAI;AAC/C,0BAAoB,UAAU;AAAA,IAC/B;AAAA,EACD,GAAG,CAAC,CAAE;AASN,QAAM,qBAA0C,4BAAa,CAAE,UAAW;AAGzE,UAAM,QAAQ;AAGd,QAAK,oBAAoB,SAAU;AAClC;AAAA,IACD;AASA,UAAM,yBAAyB,MAAM,OAAO;AAAA,MAC3C;AAAA,IACD;AACA,QACC,0BACA,MAAM,eAAe,QAAS,sBAAuB,GACpD;AACD;AAAA,IACD;AAGA,iBAAc,sBAAsB,OAAQ;AAC5C,0BAAsB,UAAU,WAAY,MAAM;AAKjD,UAAK,CAAE,SAAS,SAAS,GAAI;AAC5B,cAAM,eAAe;AACrB;AAAA,MACD;AAEA,UAAK,eAAe,OAAO,yBAAyB,SAAU;AAC7D,iCAAyB,QAAS,KAAM;AAAA,MACzC;AAAA,IACD,GAAG,CAAE;AAAA,EACN,GAAG,CAAC,CAAE;AAEN,SAAO;AAAA,IACN,SAAS;AAAA,IACT,aAAa;AAAA,IACb,WAAW;AAAA,IACX,cAAc;AAAA,IACd,YAAY;AAAA,IACZ,QAAQ;AAAA,EACT;AACD;",
6
6
  "names": []
7
7
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/hooks/use-keyboard-shortcut/index.ts"],
4
- "sourcesContent": ["import Mousetrap from 'mousetrap';\nimport 'mousetrap/plugins/global-bind/mousetrap-global-bind.js';\nimport type { ExtendedKeyboardEvent } from 'mousetrap';\nimport type { RefObject } from '@wordpress/element';\nimport { useEffect, useRef } from '@wordpress/element';\nimport { isAppleOS } from '@wordpress/keycodes';\n\ntype KeyboardShortcutConfig = {\n\t/**\n\t * Handle keyboard events anywhere including inside textarea/input fields.\n\t */\n\tbindGlobal: boolean;\n\t/**\n\t * Event name used to trigger the handler, defaults to keydown.\n\t */\n\teventName: string;\n\t/**\n\t * Disables the keyboard handler if the value is true.\n\t */\n\tisDisabled: boolean;\n\t/**\n\t * React reference to the DOM element used to catch the keyboard event.\n\t */\n\ttarget: RefObject< HTMLElement >;\n};\n\n/**\n * Attach a keyboard shortcut handler.\n *\n * @see https://craig.is/killing/mice#api.bind for information about the `callback` parameter.\n *\n * @param shortcuts Keyboard Shortcuts.\n * @param callback Shortcut callback.\n * @param options Shortcut options.\n * @param options.bindGlobal\n * @param options.eventName\n * @param options.isDisabled\n * @param options.target\n */\nfunction useKeyboardShortcut(\n\tshortcuts: string[] | string,\n\tcallback: ( e: ExtendedKeyboardEvent, combo: string ) => void,\n\t{\n\t\tbindGlobal = false,\n\t\teventName = 'keydown',\n\t\tisDisabled = false,\n\t\ttarget,\n\t}: Partial< KeyboardShortcutConfig > = {}\n) {\n\tconst currentCallbackRef = useRef( callback );\n\n\tuseEffect( () => {\n\t\tcurrentCallbackRef.current = callback;\n\t}, [ callback ] );\n\n\tuseEffect( () => {\n\t\tif ( isDisabled ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst mousetrap = new Mousetrap(\n\t\t\ttarget && target.current\n\t\t\t\t? target.current\n\t\t\t\t: // We were passing `document` here previously, so to successfully cast it to Element we must cast it first to `unknown`.\n\t\t\t\t // Not sure if this is a mistake but it was the behavior previous to the addition of types so we're just doing what's\n\t\t\t\t // necessary to maintain the existing behavior.\n\t\t\t\t ( document as unknown as Element )\n\t\t);\n\n\t\tconst shortcutsArray = Array.isArray( shortcuts )\n\t\t\t? shortcuts\n\t\t\t: [ shortcuts ];\n\n\t\tshortcutsArray.forEach( ( shortcut: string ) => {\n\t\t\tconst keys = shortcut.split( '+' );\n\t\t\tconst modifiers = new Set(\n\t\t\t\tkeys.filter( ( value ) => value.length > 1 )\n\t\t\t);\n\t\t\tconst hasAlt = modifiers.has( 'alt' );\n\t\t\tconst hasShift = modifiers.has( 'shift' );\n\n\t\t\tif (\n\t\t\t\tisAppleOS() &&\n\t\t\t\t( ( modifiers.size === 1 && hasAlt ) ||\n\t\t\t\t\t( modifiers.size === 2 && hasAlt && hasShift ) )\n\t\t\t) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Cannot bind ${ shortcut }. Alt and Shift+Alt modifiers are reserved for character input.`\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst bindFn = bindGlobal ? 'bindGlobal' : 'bind';\n\t\t\t// `@ts-expect-error` Mousetrap typings don’t include `bindGlobal`\n\t\t\t// It exists at runtime via the plugin\n\t\t\t// `any` is used here to allow dynamic access via `bindFn`\n\t\t\t( mousetrap as any )[ bindFn ](\n\t\t\t\tshortcut,\n\t\t\t\t( ...args: [ Mousetrap.ExtendedKeyboardEvent, string ] ) =>\n\t\t\t\t\tcurrentCallbackRef.current( ...args ),\n\t\t\t\teventName\n\t\t\t);\n\t\t} );\n\n\t\treturn () => {\n\t\t\tmousetrap.reset();\n\t\t};\n\t}, [ shortcuts, bindGlobal, eventName, target, isDisabled ] );\n}\n\nexport default useKeyboardShortcut;\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,uBAAsB;AACtB,mCAAO;AAGP,qBAAkC;AAClC,sBAA0B;AAkC1B,SAAS,oBACR,WACA,UACA;AAAA,EACC,aAAa;AAAA,EACb,YAAY;AAAA,EACZ,aAAa;AAAA,EACb;AACD,IAAuC,CAAC,GACvC;AACD,QAAM,yBAAqB,uBAAQ,QAAS;AAE5C,gCAAW,MAAM;AAChB,uBAAmB,UAAU;AAAA,EAC9B,GAAG,CAAE,QAAS,CAAE;AAEhB,gCAAW,MAAM;AAChB,QAAK,YAAa;AACjB;AAAA,IACD;AAEA,UAAM,YAAY,IAAI,iBAAAA;AAAA,MACrB,UAAU,OAAO,UACd,OAAO;AAAA;AAAA;AAAA;AAAA,QAIL;AAAA;AAAA,IACN;AAEA,UAAM,iBAAiB,MAAM,QAAS,SAAU,IAC7C,YACA,CAAE,SAAU;AAEf,mBAAe,QAAS,CAAE,aAAsB;AAC/C,YAAM,OAAO,SAAS,MAAO,GAAI;AACjC,YAAM,YAAY,IAAI;AAAA,QACrB,KAAK,OAAQ,CAAE,UAAW,MAAM,SAAS,CAAE;AAAA,MAC5C;AACA,YAAM,SAAS,UAAU,IAAK,KAAM;AACpC,YAAM,WAAW,UAAU,IAAK,OAAQ;AAExC,cACC,2BAAU,MACN,UAAU,SAAS,KAAK,UACzB,UAAU,SAAS,KAAK,UAAU,WACpC;AACD,cAAM,IAAI;AAAA,UACT,eAAgB,QAAS;AAAA,QAC1B;AAAA,MACD;AAEA,YAAM,SAAS,aAAa,eAAe;AAI3C,MAAE,UAAoB,MAAO;AAAA,QAC5B;AAAA,QACA,IAAK,SACJ,mBAAmB,QAAS,GAAG,IAAK;AAAA,QACrC;AAAA,MACD;AAAA,IACD,CAAE;AAEF,WAAO,MAAM;AACZ,gBAAU,MAAM;AAAA,IACjB;AAAA,EACD,GAAG,CAAE,WAAW,YAAY,WAAW,QAAQ,UAAW,CAAE;AAC7D;AAEA,IAAO,gCAAQ;",
4
+ "sourcesContent": ["import Mousetrap from 'mousetrap';\nimport 'mousetrap/plugins/global-bind/mousetrap-global-bind.js';\nimport type { ExtendedKeyboardEvent } from 'mousetrap';\nimport type { RefObject } from '@wordpress/element';\nimport { useEffect, useRef } from '@wordpress/element';\nimport { isAppleOS } from '@wordpress/keycodes';\n\ntype KeyboardShortcutConfig = {\n\t/**\n\t * Handle keyboard events anywhere including inside textarea/input fields.\n\t */\n\tbindGlobal: boolean;\n\t/**\n\t * Event name used to trigger the handler, defaults to keydown.\n\t */\n\teventName: string;\n\t/**\n\t * Disables the keyboard handler if the value is true.\n\t */\n\tisDisabled: boolean;\n\t/**\n\t * React reference to the DOM element used to catch the keyboard event.\n\t */\n\ttarget: RefObject< HTMLElement >;\n};\n\n/**\n * Attach a keyboard shortcut handler.\n *\n * @see https://craig.is/killing/mice#api.bind for information about the `callback` parameter.\n *\n * @param shortcuts Keyboard Shortcuts.\n * @param callback Shortcut callback.\n * @param options Shortcut options.\n * @param options.bindGlobal\n * @param options.eventName\n * @param options.isDisabled\n * @param options.target\n */\nfunction useKeyboardShortcut(\n\tshortcuts: string[] | string,\n\tcallback: ( e: ExtendedKeyboardEvent, combo: string ) => void,\n\t{\n\t\tbindGlobal = false,\n\t\teventName = 'keydown',\n\t\tisDisabled = false,\n\t\ttarget,\n\t}: Partial< KeyboardShortcutConfig > = {}\n) {\n\tconst currentCallbackRef = useRef( callback );\n\n\tuseEffect( () => {\n\t\tcurrentCallbackRef.current = callback;\n\t}, [ callback ] );\n\n\tuseEffect( () => {\n\t\tif ( isDisabled ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst mousetrap = new Mousetrap(\n\t\t\ttarget && target.current\n\t\t\t\t? target.current\n\t\t\t\t: // We were passing `document` here previously, so to successfully cast it to Element we must cast it first to `unknown`.\n\t\t\t\t\t// Not sure if this is a mistake but it was the behavior previous to the addition of types so we're just doing what's\n\t\t\t\t\t// necessary to maintain the existing behavior.\n\t\t\t\t\t( document as unknown as Element )\n\t\t);\n\n\t\tconst shortcutsArray = Array.isArray( shortcuts )\n\t\t\t? shortcuts\n\t\t\t: [ shortcuts ];\n\n\t\tshortcutsArray.forEach( ( shortcut: string ) => {\n\t\t\tconst keys = shortcut.split( '+' );\n\t\t\tconst modifiers = new Set(\n\t\t\t\tkeys.filter( ( value ) => value.length > 1 )\n\t\t\t);\n\t\t\tconst hasAlt = modifiers.has( 'alt' );\n\t\t\tconst hasShift = modifiers.has( 'shift' );\n\n\t\t\tif (\n\t\t\t\tisAppleOS() &&\n\t\t\t\t( ( modifiers.size === 1 && hasAlt ) ||\n\t\t\t\t\t( modifiers.size === 2 && hasAlt && hasShift ) )\n\t\t\t) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Cannot bind ${ shortcut }. Alt and Shift+Alt modifiers are reserved for character input.`\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst bindFn = bindGlobal ? 'bindGlobal' : 'bind';\n\t\t\t// `@ts-expect-error` Mousetrap typings don’t include `bindGlobal`\n\t\t\t// It exists at runtime via the plugin\n\t\t\t// `any` is used here to allow dynamic access via `bindFn`\n\t\t\t( mousetrap as any )[ bindFn ](\n\t\t\t\tshortcut,\n\t\t\t\t( ...args: [ Mousetrap.ExtendedKeyboardEvent, string ] ) =>\n\t\t\t\t\tcurrentCallbackRef.current( ...args ),\n\t\t\t\teventName\n\t\t\t);\n\t\t} );\n\n\t\treturn () => {\n\t\t\tmousetrap.reset();\n\t\t};\n\t}, [ shortcuts, bindGlobal, eventName, target, isDisabled ] );\n}\n\nexport default useKeyboardShortcut;\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,uBAAsB;AACtB,mCAAO;AAGP,qBAAkC;AAClC,sBAA0B;AAkC1B,SAAS,oBACR,WACA,UACA;AAAA,EACC,aAAa;AAAA,EACb,YAAY;AAAA,EACZ,aAAa;AAAA,EACb;AACD,IAAuC,CAAC,GACvC;AACD,QAAM,yBAAqB,uBAAQ,QAAS;AAE5C,gCAAW,MAAM;AAChB,uBAAmB,UAAU;AAAA,EAC9B,GAAG,CAAE,QAAS,CAAE;AAEhB,gCAAW,MAAM;AAChB,QAAK,YAAa;AACjB;AAAA,IACD;AAEA,UAAM,YAAY,IAAI,iBAAAA;AAAA,MACrB,UAAU,OAAO,UACd,OAAO;AAAA;AAAA;AAAA;AAAA,QAIN;AAAA;AAAA,IACL;AAEA,UAAM,iBAAiB,MAAM,QAAS,SAAU,IAC7C,YACA,CAAE,SAAU;AAEf,mBAAe,QAAS,CAAE,aAAsB;AAC/C,YAAM,OAAO,SAAS,MAAO,GAAI;AACjC,YAAM,YAAY,IAAI;AAAA,QACrB,KAAK,OAAQ,CAAE,UAAW,MAAM,SAAS,CAAE;AAAA,MAC5C;AACA,YAAM,SAAS,UAAU,IAAK,KAAM;AACpC,YAAM,WAAW,UAAU,IAAK,OAAQ;AAExC,cACC,2BAAU,MACN,UAAU,SAAS,KAAK,UACzB,UAAU,SAAS,KAAK,UAAU,WACpC;AACD,cAAM,IAAI;AAAA,UACT,eAAgB,QAAS;AAAA,QAC1B;AAAA,MACD;AAEA,YAAM,SAAS,aAAa,eAAe;AAI3C,MAAE,UAAoB,MAAO;AAAA,QAC5B;AAAA,QACA,IAAK,SACJ,mBAAmB,QAAS,GAAG,IAAK;AAAA,QACrC;AAAA,MACD;AAAA,IACD,CAAE;AAEF,WAAO,MAAM;AACZ,gBAAU,MAAM;AAAA,IACjB;AAAA,EACD,GAAG,CAAE,WAAW,YAAY,WAAW,QAAQ,UAAW,CAAE;AAC7D;AAEA,IAAO,gCAAQ;",
6
6
  "names": ["Mousetrap"]
7
7
  }
@@ -39,6 +39,15 @@ function useResizeObserver(callback, resizeObserverOptions = {}) {
39
39
  const callbackEvent = (0, import_use_event.default)(callback);
40
40
  const observedElementRef = (0, import_element.useRef)(null);
41
41
  const resizeObserverRef = (0, import_element.useRef)(void 0);
42
+ (0, import_element.useEffect)(() => {
43
+ if (observedElementRef.current) {
44
+ resizeObserverRef.current?.observe(
45
+ observedElementRef.current,
46
+ resizeObserverOptions
47
+ );
48
+ }
49
+ return () => resizeObserverRef.current?.disconnect();
50
+ }, []);
42
51
  return (0, import_use_event.default)((element) => {
43
52
  if (element === observedElementRef.current) {
44
53
  return;