@wordpress/compose 8.3.0 → 8.4.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.
- package/CHANGELOG.md +10 -0
- package/build/hooks/use-merge-refs/index.cjs +16 -22
- package/build/hooks/use-merge-refs/index.cjs.map +2 -2
- package/build-module/hooks/use-merge-refs/index.mjs +16 -22
- package/build-module/hooks/use-merge-refs/index.mjs.map +2 -2
- package/build-types/higher-order/with-global-events/listener.d.ts +2 -0
- package/build-types/higher-order/with-global-events/listener.d.ts.map +1 -1
- package/build-types/hooks/use-disabled/index.d.ts +1 -1
- package/build-types/hooks/use-disabled/index.d.ts.map +1 -1
- package/build-types/hooks/use-dragging/index.d.ts +1 -1
- package/build-types/hooks/use-dragging/index.d.ts.map +1 -1
- package/build-types/hooks/use-drop-zone/index.d.ts +1 -1
- package/build-types/hooks/use-drop-zone/index.d.ts.map +1 -1
- package/build-types/hooks/use-focus-on-mount/index.d.ts.map +1 -1
- package/build-types/hooks/use-keyboard-shortcut/index.d.ts +1 -1
- package/build-types/hooks/use-keyboard-shortcut/index.d.ts.map +1 -1
- package/build-types/hooks/use-merge-refs/index.d.ts.map +1 -1
- package/build-types/utils/subscribe-delegated-listener/index.d.ts +0 -25
- package/build-types/utils/subscribe-delegated-listener/index.d.ts.map +1 -1
- package/package.json +12 -12
- package/src/hooks/use-merge-refs/index.ts +29 -33
- package/src/hooks/use-merge-refs/test/index.js +70 -2
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,16 @@
|
|
|
2
2
|
|
|
3
3
|
## Unreleased
|
|
4
4
|
|
|
5
|
+
## 8.4.0 (2026-07-14)
|
|
6
|
+
|
|
7
|
+
### Enhancements
|
|
8
|
+
|
|
9
|
+
- Widen React peer dependency ranges to `^18 || ^19` to support both React 18 and React 19 environments ([#80024](https://github.com/WordPress/gutenberg/pull/80024)).
|
|
10
|
+
|
|
11
|
+
### Bug Fixes
|
|
12
|
+
|
|
13
|
+
- `useMergeRefs`: Apply ref changes when the element attached outside a render of the calling component (e.g. a merged ref passed to a child that mounts the element in its own commit); previously the first ref change after such an attachment was skipped, leaving stale callbacks on the element ([#80133](https://github.com/WordPress/gutenberg/pull/80133)).
|
|
14
|
+
|
|
5
15
|
## 8.3.0 (2026-07-01)
|
|
6
16
|
|
|
7
17
|
## 8.2.0 (2026-06-24)
|
|
@@ -44,40 +44,34 @@ function detachRef(ref, index, cleanups) {
|
|
|
44
44
|
}
|
|
45
45
|
function useMergeRefs(refs) {
|
|
46
46
|
const elementRef = (0, import_element.useRef)(null);
|
|
47
|
-
const
|
|
48
|
-
const didElementChangeRef = (0, import_element.useRef)(false);
|
|
49
|
-
const previousRefsRef = (0, import_element.useRef)([]);
|
|
47
|
+
const attachedRefsRef = (0, import_element.useRef)([]);
|
|
50
48
|
const currentRefsRef = (0, import_element.useRef)(refs);
|
|
51
49
|
const cleanupsRef = (0, import_element.useRef)([]);
|
|
52
50
|
currentRefsRef.current = refs;
|
|
53
51
|
(0, import_element.useLayoutEffect)(() => {
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
if (ref !== previousRef) {
|
|
58
|
-
detachRef(previousRef, index, cleanupsRef.current);
|
|
59
|
-
cleanupsRef.current[index] = assignRef(
|
|
60
|
-
ref,
|
|
61
|
-
elementRef.current
|
|
62
|
-
);
|
|
63
|
-
}
|
|
64
|
-
});
|
|
52
|
+
const element = elementRef.current;
|
|
53
|
+
if (element === null) {
|
|
54
|
+
return;
|
|
65
55
|
}
|
|
66
|
-
|
|
56
|
+
refs.forEach((ref, index) => {
|
|
57
|
+
const attachedRef = attachedRefsRef.current[index];
|
|
58
|
+
if (ref !== attachedRef) {
|
|
59
|
+
detachRef(attachedRef, index, cleanupsRef.current);
|
|
60
|
+
cleanupsRef.current[index] = assignRef(ref, element);
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
attachedRefsRef.current = refs;
|
|
67
64
|
}, refs);
|
|
68
|
-
(0, import_element.useLayoutEffect)(() => {
|
|
69
|
-
didElementChangeRef.current = false;
|
|
70
|
-
});
|
|
71
65
|
return (0, import_element.useCallback)((value) => {
|
|
72
66
|
elementRef.current = value;
|
|
73
|
-
didElementChangeRef.current = true;
|
|
74
|
-
isAttachedRef.current = value !== null;
|
|
75
67
|
if (value === null) {
|
|
76
|
-
|
|
68
|
+
attachedRefsRef.current.forEach((ref, index) => {
|
|
77
69
|
detachRef(ref, index, cleanupsRef.current);
|
|
78
70
|
});
|
|
71
|
+
attachedRefsRef.current = [];
|
|
79
72
|
} else {
|
|
80
|
-
|
|
73
|
+
attachedRefsRef.current = currentRefsRef.current;
|
|
74
|
+
attachedRefsRef.current.forEach((ref, index) => {
|
|
81
75
|
cleanupsRef.current[index] = assignRef(ref, value);
|
|
82
76
|
});
|
|
83
77
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/hooks/use-merge-refs/index.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * WordPress dependencies\n */\nimport { useRef, useCallback, useLayoutEffect } from '@wordpress/element';\nimport type { MutableRefObject, Ref, RefCallback } from 'react';\n\n// Returns a cleanup function if the ref callback returned one (React 19 ref\n// callback cleanup pattern), otherwise `undefined`. Object refs never have a\n// cleanup and only set `.current`.\nfunction assignRef< T >( ref: Ref< T >, value: T ): ( () => void ) | undefined {\n\tif ( typeof ref === 'function' ) {\n\t\tconst returned = ref( value );\n\t\treturn typeof returned === 'function' ? returned : undefined;\n\t} else if ( ref && ref.hasOwnProperty( 'current' ) ) {\n\t\t( ref as MutableRefObject< T > ).current = value;\n\t}\n\treturn undefined;\n}\n\n// Tear down a ref at the given index: prefer the stored cleanup; otherwise\n// fall back to calling the ref with `null`.\nfunction detachRef< T >(\n\tref: Ref< T >,\n\tindex: number,\n\tcleanups: Array< ( () => void ) | undefined >\n): void {\n\tconst cleanup = cleanups[ index ];\n\tif ( cleanup ) {\n\t\tcleanups[ index ] = undefined;\n\t\tcleanup();\n\t} else {\n\t\tassignRef( ref, null );\n\t}\n}\n\n/**\n * Merges refs into one ref callback.\n *\n * It also ensures that the merged ref callbacks are only called when they\n * change (as a result of a `useCallback` dependency update) OR when the ref\n * value changes, just as React does when passing a single ref callback to the\n * component.\n *\n * As expected, if you pass a new function on every render, the ref callback\n * will be called after every render.\n *\n * If you don't wish a ref callback to be called after every render, wrap it\n * with `useCallback( callback, dependencies )`. When a dependency changes, the\n * old ref callback will be called with `null` and the new ref callback will be\n * called with the same value.\n *\n * Inner ref callbacks may return a cleanup function (React 19's ref callback\n * cleanup pattern). When a ref callback returns a function, that function is\n * invoked at teardown (node change, dependency change, or unmount) **instead\n * of** the callback being called with `null`. Callbacks that do not return a\n * cleanup continue to receive `null` on teardown as before.\n *\n * It's also possible to _disable_ a ref (and its behaviour) by simply not\n * passing the ref.\n *\n * ```jsx\n * const ref = useCallback( ( node ) => {\n * node.addEventListener( ... );\n * return () => {\n * node.removeEventListener( ... );\n * };\n * }, [ ...dependencies ] );\n * const otherRef = useRef();\n * const mergedRefs = useMergeRefs( [\n * enabled && ref,\n * otherRef,\n * ] );\n * return <div ref={ mergedRefs } />;\n * ```\n *\n * @param refs The refs to be merged.\n * @return The merged ref callback.\n */\nexport default function useMergeRefs< T >(\n\trefs: Ref< T >[]\n): RefCallback< T > {\n\tconst elementRef = useRef< T | null >( null );\n\
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAGA,qBAAqD;AAMrD,SAAS,UAAgB,KAAe,OAAuC;AAC9E,MAAK,OAAO,QAAQ,YAAa;AAChC,UAAM,WAAW,IAAK,KAAM;AAC5B,WAAO,OAAO,aAAa,aAAa,WAAW;AAAA,EACpD,WAAY,OAAO,IAAI,eAAgB,SAAU,GAAI;AACpD,IAAE,IAA+B,UAAU;AAAA,EAC5C;AACA,SAAO;AACR;AAIA,SAAS,UACR,KACA,OACA,UACO;AACP,QAAM,UAAU,SAAU,KAAM;AAChC,MAAK,SAAU;AACd,aAAU,KAAM,IAAI;AACpB,YAAQ;AAAA,EACT,OAAO;AACN,cAAW,KAAK,IAAK;AAAA,EACtB;AACD;AA6Ce,SAAR,aACN,MACmB;AACnB,QAAM,iBAAa,uBAAoB,IAAK;
|
|
4
|
+
"sourcesContent": ["/**\n * WordPress dependencies\n */\nimport { useRef, useCallback, useLayoutEffect } from '@wordpress/element';\nimport type { MutableRefObject, Ref, RefCallback } from 'react';\n\n// Returns a cleanup function if the ref callback returned one (React 19 ref\n// callback cleanup pattern), otherwise `undefined`. Object refs never have a\n// cleanup and only set `.current`.\nfunction assignRef< T >( ref: Ref< T >, value: T ): ( () => void ) | undefined {\n\tif ( typeof ref === 'function' ) {\n\t\tconst returned = ref( value );\n\t\treturn typeof returned === 'function' ? returned : undefined;\n\t} else if ( ref && ref.hasOwnProperty( 'current' ) ) {\n\t\t( ref as MutableRefObject< T > ).current = value;\n\t}\n\treturn undefined;\n}\n\n// Tear down a ref at the given index: prefer the stored cleanup; otherwise\n// fall back to calling the ref with `null`.\nfunction detachRef< T >(\n\tref: Ref< T >,\n\tindex: number,\n\tcleanups: Array< ( () => void ) | undefined >\n): void {\n\tconst cleanup = cleanups[ index ];\n\tif ( cleanup ) {\n\t\tcleanups[ index ] = undefined;\n\t\tcleanup();\n\t} else {\n\t\tassignRef( ref, null );\n\t}\n}\n\n/**\n * Merges refs into one ref callback.\n *\n * It also ensures that the merged ref callbacks are only called when they\n * change (as a result of a `useCallback` dependency update) OR when the ref\n * value changes, just as React does when passing a single ref callback to the\n * component.\n *\n * As expected, if you pass a new function on every render, the ref callback\n * will be called after every render.\n *\n * If you don't wish a ref callback to be called after every render, wrap it\n * with `useCallback( callback, dependencies )`. When a dependency changes, the\n * old ref callback will be called with `null` and the new ref callback will be\n * called with the same value.\n *\n * Inner ref callbacks may return a cleanup function (React 19's ref callback\n * cleanup pattern). When a ref callback returns a function, that function is\n * invoked at teardown (node change, dependency change, or unmount) **instead\n * of** the callback being called with `null`. Callbacks that do not return a\n * cleanup continue to receive `null` on teardown as before.\n *\n * It's also possible to _disable_ a ref (and its behaviour) by simply not\n * passing the ref.\n *\n * ```jsx\n * const ref = useCallback( ( node ) => {\n * node.addEventListener( ... );\n * return () => {\n * node.removeEventListener( ... );\n * };\n * }, [ ...dependencies ] );\n * const otherRef = useRef();\n * const mergedRefs = useMergeRefs( [\n * enabled && ref,\n * otherRef,\n * ] );\n * return <div ref={ mergedRefs } />;\n * ```\n *\n * @param refs The refs to be merged.\n * @return The merged ref callback.\n */\nexport default function useMergeRefs< T >(\n\trefs: Ref< T >[]\n): RefCallback< T > {\n\tconst elementRef = useRef< T | null >( null );\n\t// The refs that are attached to the element: set when the element\n\t// attaches, and kept in sync when a changed ref is swapped on render.\n\tconst attachedRefsRef = useRef< Ref< T >[] >( [] );\n\tconst currentRefsRef = useRef( refs );\n\t// Position-indexed cleanups returned by inner ref callbacks. A slot is\n\t// `undefined` when the ref at that position did not return a cleanup (or\n\t// is an object ref / disabled).\n\tconst cleanupsRef = useRef< Array< ( () => void ) | undefined > >( [] );\n\n\t// Update on render before the ref callback is called, so the ref callback\n\t// always has access to the current refs.\n\tcurrentRefsRef.current = refs;\n\n\t// If any of the refs change, call the attached ref with `null` and the\n\t// new ref with the node. Comparing against the refs that are attached to\n\t// the element, rather than the previous render's refs, also covers an\n\t// element that attaches outside a render of this component (a merged ref\n\t// passed to a child that mounts the element in its own commit): the\n\t// change is still detected on the next render. When the element attached\n\t// during this commit, the ref callback has already been called with the\n\t// current refs, which compare equal here.\n\tuseLayoutEffect( () => {\n\t\tconst element = elementRef.current;\n\n\t\tif ( element === null ) {\n\t\t\treturn;\n\t\t}\n\n\t\trefs.forEach( ( ref, index ) => {\n\t\t\tconst attachedRef = attachedRefsRef.current[ index ];\n\t\t\tif ( ref !== attachedRef ) {\n\t\t\t\tdetachRef( attachedRef, index, cleanupsRef.current );\n\t\t\t\tcleanupsRef.current[ index ] = assignRef( ref, element );\n\t\t\t}\n\t\t} );\n\n\t\tattachedRefsRef.current = refs;\n\t}, refs );\n\n\t// There should be no dependencies so that `callback` is only called when\n\t// the node changes.\n\treturn useCallback( ( value: T | null ) => {\n\t\t// Update the element so it can be used when calling ref callbacks on a\n\t\t// dependency change.\n\t\telementRef.current = value;\n\n\t\t// When an element changes, the current ref callback should be called\n\t\t// with the new element and the attached one with `null`.\n\t\tif ( value === null ) {\n\t\t\tattachedRefsRef.current.forEach( ( ref, index ) => {\n\t\t\t\tdetachRef( ref, index, cleanupsRef.current );\n\t\t\t} );\n\t\t\tattachedRefsRef.current = [];\n\t\t} else {\n\t\t\tattachedRefsRef.current = currentRefsRef.current;\n\t\t\tattachedRefsRef.current.forEach( ( ref, index ) => {\n\t\t\t\tcleanupsRef.current[ index ] = assignRef( ref, value );\n\t\t\t} );\n\t\t}\n\t}, [] );\n}\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAGA,qBAAqD;AAMrD,SAAS,UAAgB,KAAe,OAAuC;AAC9E,MAAK,OAAO,QAAQ,YAAa;AAChC,UAAM,WAAW,IAAK,KAAM;AAC5B,WAAO,OAAO,aAAa,aAAa,WAAW;AAAA,EACpD,WAAY,OAAO,IAAI,eAAgB,SAAU,GAAI;AACpD,IAAE,IAA+B,UAAU;AAAA,EAC5C;AACA,SAAO;AACR;AAIA,SAAS,UACR,KACA,OACA,UACO;AACP,QAAM,UAAU,SAAU,KAAM;AAChC,MAAK,SAAU;AACd,aAAU,KAAM,IAAI;AACpB,YAAQ;AAAA,EACT,OAAO;AACN,cAAW,KAAK,IAAK;AAAA,EACtB;AACD;AA6Ce,SAAR,aACN,MACmB;AACnB,QAAM,iBAAa,uBAAoB,IAAK;AAG5C,QAAM,sBAAkB,uBAAsB,CAAC,CAAE;AACjD,QAAM,qBAAiB,uBAAQ,IAAK;AAIpC,QAAM,kBAAc,uBAA+C,CAAC,CAAE;AAItE,iBAAe,UAAU;AAUzB,sCAAiB,MAAM;AACtB,UAAM,UAAU,WAAW;AAE3B,QAAK,YAAY,MAAO;AACvB;AAAA,IACD;AAEA,SAAK,QAAS,CAAE,KAAK,UAAW;AAC/B,YAAM,cAAc,gBAAgB,QAAS,KAAM;AACnD,UAAK,QAAQ,aAAc;AAC1B,kBAAW,aAAa,OAAO,YAAY,OAAQ;AACnD,oBAAY,QAAS,KAAM,IAAI,UAAW,KAAK,OAAQ;AAAA,MACxD;AAAA,IACD,CAAE;AAEF,oBAAgB,UAAU;AAAA,EAC3B,GAAG,IAAK;AAIR,aAAO,4BAAa,CAAE,UAAqB;AAG1C,eAAW,UAAU;AAIrB,QAAK,UAAU,MAAO;AACrB,sBAAgB,QAAQ,QAAS,CAAE,KAAK,UAAW;AAClD,kBAAW,KAAK,OAAO,YAAY,OAAQ;AAAA,MAC5C,CAAE;AACF,sBAAgB,UAAU,CAAC;AAAA,IAC5B,OAAO;AACN,sBAAgB,UAAU,eAAe;AACzC,sBAAgB,QAAQ,QAAS,CAAE,KAAK,UAAW;AAClD,oBAAY,QAAS,KAAM,IAAI,UAAW,KAAK,KAAM;AAAA,MACtD,CAAE;AAAA,IACH;AAAA,EACD,GAAG,CAAC,CAAE;AACP;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -20,40 +20,34 @@ function detachRef(ref, index, cleanups) {
|
|
|
20
20
|
}
|
|
21
21
|
function useMergeRefs(refs) {
|
|
22
22
|
const elementRef = useRef(null);
|
|
23
|
-
const
|
|
24
|
-
const didElementChangeRef = useRef(false);
|
|
25
|
-
const previousRefsRef = useRef([]);
|
|
23
|
+
const attachedRefsRef = useRef([]);
|
|
26
24
|
const currentRefsRef = useRef(refs);
|
|
27
25
|
const cleanupsRef = useRef([]);
|
|
28
26
|
currentRefsRef.current = refs;
|
|
29
27
|
useLayoutEffect(() => {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
if (ref !== previousRef) {
|
|
34
|
-
detachRef(previousRef, index, cleanupsRef.current);
|
|
35
|
-
cleanupsRef.current[index] = assignRef(
|
|
36
|
-
ref,
|
|
37
|
-
elementRef.current
|
|
38
|
-
);
|
|
39
|
-
}
|
|
40
|
-
});
|
|
28
|
+
const element = elementRef.current;
|
|
29
|
+
if (element === null) {
|
|
30
|
+
return;
|
|
41
31
|
}
|
|
42
|
-
|
|
32
|
+
refs.forEach((ref, index) => {
|
|
33
|
+
const attachedRef = attachedRefsRef.current[index];
|
|
34
|
+
if (ref !== attachedRef) {
|
|
35
|
+
detachRef(attachedRef, index, cleanupsRef.current);
|
|
36
|
+
cleanupsRef.current[index] = assignRef(ref, element);
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
attachedRefsRef.current = refs;
|
|
43
40
|
}, refs);
|
|
44
|
-
useLayoutEffect(() => {
|
|
45
|
-
didElementChangeRef.current = false;
|
|
46
|
-
});
|
|
47
41
|
return useCallback((value) => {
|
|
48
42
|
elementRef.current = value;
|
|
49
|
-
didElementChangeRef.current = true;
|
|
50
|
-
isAttachedRef.current = value !== null;
|
|
51
43
|
if (value === null) {
|
|
52
|
-
|
|
44
|
+
attachedRefsRef.current.forEach((ref, index) => {
|
|
53
45
|
detachRef(ref, index, cleanupsRef.current);
|
|
54
46
|
});
|
|
47
|
+
attachedRefsRef.current = [];
|
|
55
48
|
} else {
|
|
56
|
-
|
|
49
|
+
attachedRefsRef.current = currentRefsRef.current;
|
|
50
|
+
attachedRefsRef.current.forEach((ref, index) => {
|
|
57
51
|
cleanupsRef.current[index] = assignRef(ref, value);
|
|
58
52
|
});
|
|
59
53
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/hooks/use-merge-refs/index.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * WordPress dependencies\n */\nimport { useRef, useCallback, useLayoutEffect } from '@wordpress/element';\nimport type { MutableRefObject, Ref, RefCallback } from 'react';\n\n// Returns a cleanup function if the ref callback returned one (React 19 ref\n// callback cleanup pattern), otherwise `undefined`. Object refs never have a\n// cleanup and only set `.current`.\nfunction assignRef< T >( ref: Ref< T >, value: T ): ( () => void ) | undefined {\n\tif ( typeof ref === 'function' ) {\n\t\tconst returned = ref( value );\n\t\treturn typeof returned === 'function' ? returned : undefined;\n\t} else if ( ref && ref.hasOwnProperty( 'current' ) ) {\n\t\t( ref as MutableRefObject< T > ).current = value;\n\t}\n\treturn undefined;\n}\n\n// Tear down a ref at the given index: prefer the stored cleanup; otherwise\n// fall back to calling the ref with `null`.\nfunction detachRef< T >(\n\tref: Ref< T >,\n\tindex: number,\n\tcleanups: Array< ( () => void ) | undefined >\n): void {\n\tconst cleanup = cleanups[ index ];\n\tif ( cleanup ) {\n\t\tcleanups[ index ] = undefined;\n\t\tcleanup();\n\t} else {\n\t\tassignRef( ref, null );\n\t}\n}\n\n/**\n * Merges refs into one ref callback.\n *\n * It also ensures that the merged ref callbacks are only called when they\n * change (as a result of a `useCallback` dependency update) OR when the ref\n * value changes, just as React does when passing a single ref callback to the\n * component.\n *\n * As expected, if you pass a new function on every render, the ref callback\n * will be called after every render.\n *\n * If you don't wish a ref callback to be called after every render, wrap it\n * with `useCallback( callback, dependencies )`. When a dependency changes, the\n * old ref callback will be called with `null` and the new ref callback will be\n * called with the same value.\n *\n * Inner ref callbacks may return a cleanup function (React 19's ref callback\n * cleanup pattern). When a ref callback returns a function, that function is\n * invoked at teardown (node change, dependency change, or unmount) **instead\n * of** the callback being called with `null`. Callbacks that do not return a\n * cleanup continue to receive `null` on teardown as before.\n *\n * It's also possible to _disable_ a ref (and its behaviour) by simply not\n * passing the ref.\n *\n * ```jsx\n * const ref = useCallback( ( node ) => {\n * node.addEventListener( ... );\n * return () => {\n * node.removeEventListener( ... );\n * };\n * }, [ ...dependencies ] );\n * const otherRef = useRef();\n * const mergedRefs = useMergeRefs( [\n * enabled && ref,\n * otherRef,\n * ] );\n * return <div ref={ mergedRefs } />;\n * ```\n *\n * @param refs The refs to be merged.\n * @return The merged ref callback.\n */\nexport default function useMergeRefs< T >(\n\trefs: Ref< T >[]\n): RefCallback< T > {\n\tconst elementRef = useRef< T | null >( null );\n\
|
|
5
|
-
"mappings": ";AAGA,SAAS,QAAQ,aAAa,uBAAuB;AAMrD,SAAS,UAAgB,KAAe,OAAuC;AAC9E,MAAK,OAAO,QAAQ,YAAa;AAChC,UAAM,WAAW,IAAK,KAAM;AAC5B,WAAO,OAAO,aAAa,aAAa,WAAW;AAAA,EACpD,WAAY,OAAO,IAAI,eAAgB,SAAU,GAAI;AACpD,IAAE,IAA+B,UAAU;AAAA,EAC5C;AACA,SAAO;AACR;AAIA,SAAS,UACR,KACA,OACA,UACO;AACP,QAAM,UAAU,SAAU,KAAM;AAChC,MAAK,SAAU;AACd,aAAU,KAAM,IAAI;AACpB,YAAQ;AAAA,EACT,OAAO;AACN,cAAW,KAAK,IAAK;AAAA,EACtB;AACD;AA6Ce,SAAR,aACN,MACmB;AACnB,QAAM,aAAa,OAAoB,IAAK;
|
|
4
|
+
"sourcesContent": ["/**\n * WordPress dependencies\n */\nimport { useRef, useCallback, useLayoutEffect } from '@wordpress/element';\nimport type { MutableRefObject, Ref, RefCallback } from 'react';\n\n// Returns a cleanup function if the ref callback returned one (React 19 ref\n// callback cleanup pattern), otherwise `undefined`. Object refs never have a\n// cleanup and only set `.current`.\nfunction assignRef< T >( ref: Ref< T >, value: T ): ( () => void ) | undefined {\n\tif ( typeof ref === 'function' ) {\n\t\tconst returned = ref( value );\n\t\treturn typeof returned === 'function' ? returned : undefined;\n\t} else if ( ref && ref.hasOwnProperty( 'current' ) ) {\n\t\t( ref as MutableRefObject< T > ).current = value;\n\t}\n\treturn undefined;\n}\n\n// Tear down a ref at the given index: prefer the stored cleanup; otherwise\n// fall back to calling the ref with `null`.\nfunction detachRef< T >(\n\tref: Ref< T >,\n\tindex: number,\n\tcleanups: Array< ( () => void ) | undefined >\n): void {\n\tconst cleanup = cleanups[ index ];\n\tif ( cleanup ) {\n\t\tcleanups[ index ] = undefined;\n\t\tcleanup();\n\t} else {\n\t\tassignRef( ref, null );\n\t}\n}\n\n/**\n * Merges refs into one ref callback.\n *\n * It also ensures that the merged ref callbacks are only called when they\n * change (as a result of a `useCallback` dependency update) OR when the ref\n * value changes, just as React does when passing a single ref callback to the\n * component.\n *\n * As expected, if you pass a new function on every render, the ref callback\n * will be called after every render.\n *\n * If you don't wish a ref callback to be called after every render, wrap it\n * with `useCallback( callback, dependencies )`. When a dependency changes, the\n * old ref callback will be called with `null` and the new ref callback will be\n * called with the same value.\n *\n * Inner ref callbacks may return a cleanup function (React 19's ref callback\n * cleanup pattern). When a ref callback returns a function, that function is\n * invoked at teardown (node change, dependency change, or unmount) **instead\n * of** the callback being called with `null`. Callbacks that do not return a\n * cleanup continue to receive `null` on teardown as before.\n *\n * It's also possible to _disable_ a ref (and its behaviour) by simply not\n * passing the ref.\n *\n * ```jsx\n * const ref = useCallback( ( node ) => {\n * node.addEventListener( ... );\n * return () => {\n * node.removeEventListener( ... );\n * };\n * }, [ ...dependencies ] );\n * const otherRef = useRef();\n * const mergedRefs = useMergeRefs( [\n * enabled && ref,\n * otherRef,\n * ] );\n * return <div ref={ mergedRefs } />;\n * ```\n *\n * @param refs The refs to be merged.\n * @return The merged ref callback.\n */\nexport default function useMergeRefs< T >(\n\trefs: Ref< T >[]\n): RefCallback< T > {\n\tconst elementRef = useRef< T | null >( null );\n\t// The refs that are attached to the element: set when the element\n\t// attaches, and kept in sync when a changed ref is swapped on render.\n\tconst attachedRefsRef = useRef< Ref< T >[] >( [] );\n\tconst currentRefsRef = useRef( refs );\n\t// Position-indexed cleanups returned by inner ref callbacks. A slot is\n\t// `undefined` when the ref at that position did not return a cleanup (or\n\t// is an object ref / disabled).\n\tconst cleanupsRef = useRef< Array< ( () => void ) | undefined > >( [] );\n\n\t// Update on render before the ref callback is called, so the ref callback\n\t// always has access to the current refs.\n\tcurrentRefsRef.current = refs;\n\n\t// If any of the refs change, call the attached ref with `null` and the\n\t// new ref with the node. Comparing against the refs that are attached to\n\t// the element, rather than the previous render's refs, also covers an\n\t// element that attaches outside a render of this component (a merged ref\n\t// passed to a child that mounts the element in its own commit): the\n\t// change is still detected on the next render. When the element attached\n\t// during this commit, the ref callback has already been called with the\n\t// current refs, which compare equal here.\n\tuseLayoutEffect( () => {\n\t\tconst element = elementRef.current;\n\n\t\tif ( element === null ) {\n\t\t\treturn;\n\t\t}\n\n\t\trefs.forEach( ( ref, index ) => {\n\t\t\tconst attachedRef = attachedRefsRef.current[ index ];\n\t\t\tif ( ref !== attachedRef ) {\n\t\t\t\tdetachRef( attachedRef, index, cleanupsRef.current );\n\t\t\t\tcleanupsRef.current[ index ] = assignRef( ref, element );\n\t\t\t}\n\t\t} );\n\n\t\tattachedRefsRef.current = refs;\n\t}, refs );\n\n\t// There should be no dependencies so that `callback` is only called when\n\t// the node changes.\n\treturn useCallback( ( value: T | null ) => {\n\t\t// Update the element so it can be used when calling ref callbacks on a\n\t\t// dependency change.\n\t\telementRef.current = value;\n\n\t\t// When an element changes, the current ref callback should be called\n\t\t// with the new element and the attached one with `null`.\n\t\tif ( value === null ) {\n\t\t\tattachedRefsRef.current.forEach( ( ref, index ) => {\n\t\t\t\tdetachRef( ref, index, cleanupsRef.current );\n\t\t\t} );\n\t\t\tattachedRefsRef.current = [];\n\t\t} else {\n\t\t\tattachedRefsRef.current = currentRefsRef.current;\n\t\t\tattachedRefsRef.current.forEach( ( ref, index ) => {\n\t\t\t\tcleanupsRef.current[ index ] = assignRef( ref, value );\n\t\t\t} );\n\t\t}\n\t}, [] );\n}\n"],
|
|
5
|
+
"mappings": ";AAGA,SAAS,QAAQ,aAAa,uBAAuB;AAMrD,SAAS,UAAgB,KAAe,OAAuC;AAC9E,MAAK,OAAO,QAAQ,YAAa;AAChC,UAAM,WAAW,IAAK,KAAM;AAC5B,WAAO,OAAO,aAAa,aAAa,WAAW;AAAA,EACpD,WAAY,OAAO,IAAI,eAAgB,SAAU,GAAI;AACpD,IAAE,IAA+B,UAAU;AAAA,EAC5C;AACA,SAAO;AACR;AAIA,SAAS,UACR,KACA,OACA,UACO;AACP,QAAM,UAAU,SAAU,KAAM;AAChC,MAAK,SAAU;AACd,aAAU,KAAM,IAAI;AACpB,YAAQ;AAAA,EACT,OAAO;AACN,cAAW,KAAK,IAAK;AAAA,EACtB;AACD;AA6Ce,SAAR,aACN,MACmB;AACnB,QAAM,aAAa,OAAoB,IAAK;AAG5C,QAAM,kBAAkB,OAAsB,CAAC,CAAE;AACjD,QAAM,iBAAiB,OAAQ,IAAK;AAIpC,QAAM,cAAc,OAA+C,CAAC,CAAE;AAItE,iBAAe,UAAU;AAUzB,kBAAiB,MAAM;AACtB,UAAM,UAAU,WAAW;AAE3B,QAAK,YAAY,MAAO;AACvB;AAAA,IACD;AAEA,SAAK,QAAS,CAAE,KAAK,UAAW;AAC/B,YAAM,cAAc,gBAAgB,QAAS,KAAM;AACnD,UAAK,QAAQ,aAAc;AAC1B,kBAAW,aAAa,OAAO,YAAY,OAAQ;AACnD,oBAAY,QAAS,KAAM,IAAI,UAAW,KAAK,OAAQ;AAAA,MACxD;AAAA,IACD,CAAE;AAEF,oBAAgB,UAAU;AAAA,EAC3B,GAAG,IAAK;AAIR,SAAO,YAAa,CAAE,UAAqB;AAG1C,eAAW,UAAU;AAIrB,QAAK,UAAU,MAAO;AACrB,sBAAgB,QAAQ,QAAS,CAAE,KAAK,UAAW;AAClD,kBAAW,KAAK,OAAO,YAAY,OAAQ;AAAA,MAC5C,CAAE;AACF,sBAAgB,UAAU,CAAC;AAAA,IAC5B,OAAO;AACN,sBAAgB,UAAU,eAAe;AACzC,sBAAgB,QAAQ,QAAS,CAAE,KAAK,UAAW;AAClD,oBAAY,QAAS,KAAM,IAAI,UAAW,KAAK,KAAM;AAAA,MACtD,CAAE;AAAA,IACH;AAAA,EACD,GAAG,CAAC,CAAE;AACP;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -4,6 +4,8 @@
|
|
|
4
4
|
* removing the handler when no instances are listening for the event.
|
|
5
5
|
*/
|
|
6
6
|
declare class Listener {
|
|
7
|
+
/** @type {any} */
|
|
8
|
+
listeners: any;
|
|
7
9
|
constructor();
|
|
8
10
|
add(/** @type {any} */ eventType: any, /** @type {any} */ instance: any): void;
|
|
9
11
|
remove(/** @type {any} */ eventType: any, /** @type {any} */ instance: any): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"listener.d.ts","sourceRoot":"","sources":["../../../src/higher-order/with-global-events/listener.js"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,cAAM,QAAQ;IACb,cAKC;IAED,GAAG,CAAE,kBAAkB,CAAC,SAAS,EAAjB,GAAiB,EAAE,kBAAkB,CAAC,QAAQ,EAAhB,GAAgB,QAQ7D;IAED,MAAM,CAAE,kBAAkB,CAAC,SAAS,EAAjB,GAAiB,EAAE,kBAAkB,CAAC,QAAQ,EAAhB,GAAgB,QAchE;IAED,WAAW,CAAE,kBAAkB,CAAC,KAAK,EAAb,GAAa,QAMpC;CACD;eAEc,QAAQ"}
|
|
1
|
+
{"version":3,"file":"listener.d.ts","sourceRoot":"","sources":["../../../src/higher-order/with-global-events/listener.js"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,cAAM,QAAQ;IAEZ,kBAAkB;IACb,SAAS,EADH,GAAG;IADf,cAKC;IAED,GAAG,CAAE,kBAAkB,CAAC,SAAS,EAAjB,GAAiB,EAAE,kBAAkB,CAAC,QAAQ,EAAhB,GAAgB,QAQ7D;IAED,MAAM,CAAE,kBAAkB,CAAC,SAAS,EAAjB,GAAiB,EAAE,kBAAkB,CAAC,QAAQ,EAAhB,GAAgB,QAchE;IAED,WAAW,CAAE,kBAAkB,CAAC,KAAK,EAAb,GAAa,QAMpC;CACD;eAEc,QAAQ"}
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
* };
|
|
25
25
|
* ```
|
|
26
26
|
*/
|
|
27
|
-
export default function useDisabled({ isDisabled: isDisabledProp }?: {
|
|
27
|
+
export default function useDisabled({ isDisabled: isDisabledProp, }?: {
|
|
28
28
|
isDisabled?: boolean;
|
|
29
29
|
}): import("react").RefCallback<Node | null>;
|
|
30
30
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/hooks/use-disabled/index.ts"],"names":[],"mappings":"AAMA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,MAAM,CAAC,OAAO,UAAU,WAAW,CAAE,EACpC,UAAU,EAAE,cAAsB,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/hooks/use-disabled/index.ts"],"names":[],"mappings":"AAMA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,MAAM,CAAC,OAAO,UAAU,WAAW,CAAE,EACpC,UAAU,EAAE,cAAsB,GAClC,GAAE;IACF,UAAU,CAAC,EAAE,OAAO,CAAC;CAChB,4CAmDL"}
|
|
@@ -8,5 +8,5 @@ import type { DraggingProps, DraggingReturn } from './types';
|
|
|
8
8
|
* @param props.onDragEnd
|
|
9
9
|
* @return Drag state and handlers
|
|
10
10
|
*/
|
|
11
|
-
export default function useDragging({ onDragStart, onDragMove, onDragEnd }: DraggingProps): DraggingReturn;
|
|
11
|
+
export default function useDragging({ onDragStart, onDragMove, onDragEnd, }: DraggingProps): DraggingReturn;
|
|
12
12
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/hooks/use-dragging/index.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAE7D;;;;;;;;GAQG;AACH,MAAM,CAAC,OAAO,UAAU,WAAW,CAAE,EACpC,WAAW,EACX,UAAU,EACV,SAAS,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/hooks/use-dragging/index.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAE7D;;;;;;;;GAQG;AACH,MAAM,CAAC,OAAO,UAAU,WAAW,CAAE,EACpC,WAAW,EACX,UAAU,EACV,SAAS,GACT,EAAE,aAAa,GAAI,cAAc,CAqDjC"}
|
|
@@ -5,5 +5,5 @@ import type { UseDropZoneProps } from './types';
|
|
|
5
5
|
* @param {UseDropZoneProps} props Hook options
|
|
6
6
|
* @return Ref callback to be passed to the drop zone element.
|
|
7
7
|
*/
|
|
8
|
-
export default function useDropZone({ dropZoneElement, isDisabled, onDrop: _onDrop, onDragStart: _onDragStart, onDragEnter: _onDragEnter, onDragLeave: _onDragLeave, onDragEnd: _onDragEnd, onDragOver: _onDragOver }: UseDropZoneProps): React.RefCallback<HTMLElement>;
|
|
8
|
+
export default function useDropZone({ dropZoneElement, isDisabled, onDrop: _onDrop, onDragStart: _onDragStart, onDragEnter: _onDragEnter, onDragLeave: _onDragLeave, onDragEnd: _onDragEnd, onDragOver: _onDragOver, }: UseDropZoneProps): React.RefCallback<HTMLElement>;
|
|
9
9
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/hooks/use-drop-zone/index.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAEhD;;;;;GAKG;AACH,MAAM,CAAC,OAAO,UAAU,WAAW,CAAE,EACpC,eAAe,EACf,UAAU,EACV,MAAM,EAAE,OAAO,EACf,WAAW,EAAE,YAAY,EACzB,WAAW,EAAE,YAAY,EACzB,WAAW,EAAE,YAAY,EACzB,SAAS,EAAE,UAAU,EACrB,UAAU,EAAE,WAAW,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/hooks/use-drop-zone/index.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAEhD;;;;;GAKG;AACH,MAAM,CAAC,OAAO,UAAU,WAAW,CAAE,EACpC,eAAe,EACf,UAAU,EACV,MAAM,EAAE,OAAO,EACf,WAAW,EAAE,YAAY,EACzB,WAAW,EAAE,YAAY,EACzB,WAAW,EAAE,YAAY,EACzB,SAAS,EAAE,UAAU,EACrB,UAAU,EAAE,WAAW,GACvB,EAAE,gBAAgB,GAAI,KAAK,CAAC,WAAW,CAAE,WAAW,CAAE,CAmLtD"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/hooks/use-focus-on-mount/index.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,eAAe,CAC9B,YAAY,GAAE,eAAe,CAAC,IAAqB,mDA+DnD;AAED,yBAAiB,eAAe,CAAC
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/hooks/use-focus-on-mount/index.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,eAAe,CAC9B,YAAY,GAAE,eAAe,CAAC,IAAqB,mDA+DnD;AAED,yBAAiB,eAAe,CAAC;IAChC,KAAY,IAAI,GAAG,OAAO,GAAG,cAAc,GAAG,mBAAmB,CAAC;CAClE"}
|
|
@@ -35,6 +35,6 @@ type KeyboardShortcutConfig = {
|
|
|
35
35
|
* @param options.isDisabled
|
|
36
36
|
* @param options.target
|
|
37
37
|
*/
|
|
38
|
-
declare function useKeyboardShortcut(shortcuts: string[] | string, callback: (e: ExtendedKeyboardEvent, combo: string) => void, { bindGlobal, eventName, isDisabled, target }?: Partial<KeyboardShortcutConfig>): void;
|
|
38
|
+
declare function useKeyboardShortcut(shortcuts: string[] | string, callback: (e: ExtendedKeyboardEvent, combo: string) => void, { bindGlobal, eventName, isDisabled, target, }?: Partial<KeyboardShortcutConfig>): void;
|
|
39
39
|
export default useKeyboardShortcut;
|
|
40
40
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/hooks/use-keyboard-shortcut/index.ts"],"names":[],"mappings":"AAIA,OAAO,wDAAwD,CAAC;AAChE,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,WAAW,CAAC;AAEvD;;GAEG;AACH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAIpD,KAAK,sBAAsB,GAAG;IAC7B;;OAEG;IACH,UAAU,EAAE,OAAO,CAAC;IACpB;;OAEG;IACH,SAAS,EAAE,MAAM,CAAC;IAClB;;OAEG;IACH,UAAU,EAAE,OAAO,CAAC;IACpB;;OAEG;IACH,MAAM,EAAE,SAAS,CAAE,WAAW,CAAE,CAAC;CACjC,CAAC;AAEF;;;;;;;;;;;;GAYG;AACH,iBAAS,mBAAmB,CAC3B,SAAS,EAAE,MAAM,EAAE,GAAG,MAAM,EAC5B,QAAQ,EAAE,CAAE,CAAC,EAAE,qBAAqB,EAAE,KAAK,EAAE,MAAM,KAAM,IAAI,EAC7D,EACC,UAAkB,EAClB,SAAqB,EACrB,UAAkB,EAClB,MAAM,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/hooks/use-keyboard-shortcut/index.ts"],"names":[],"mappings":"AAIA,OAAO,wDAAwD,CAAC;AAChE,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,WAAW,CAAC;AAEvD;;GAEG;AACH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAIpD,KAAK,sBAAsB,GAAG;IAC7B;;OAEG;IACH,UAAU,EAAE,OAAO,CAAC;IACpB;;OAEG;IACH,SAAS,EAAE,MAAM,CAAC;IAClB;;OAEG;IACH,UAAU,EAAE,OAAO,CAAC;IACpB;;OAEG;IACH,MAAM,EAAE,SAAS,CAAE,WAAW,CAAE,CAAC;CACjC,CAAC;AAEF;;;;;;;;;;;;GAYG;AACH,iBAAS,mBAAmB,CAC3B,SAAS,EAAE,MAAM,EAAE,GAAG,MAAM,EAC5B,QAAQ,EAAE,CAAE,CAAC,EAAE,qBAAqB,EAAE,KAAK,EAAE,MAAM,KAAM,IAAI,EAC7D,EACC,UAAkB,EAClB,SAAqB,EACrB,UAAkB,EAClB,MAAM,GACN,GAAE,OAAO,CAAE,sBAAsB,CAAO,QA4DzC;eAEc,mBAAmB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/hooks/use-merge-refs/index.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAoB,GAAG,EAAE,WAAW,EAAE,MAAM,OAAO,CAAC;AA+BhE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AACH,MAAM,CAAC,OAAO,UAAU,YAAY,CAAE,CAAC,EACtC,IAAI,EAAE,GAAG,CAAE,CAAC,CAAE,EAAE,GACd,WAAW,CAAE,CAAC,CAAE,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/hooks/use-merge-refs/index.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAoB,GAAG,EAAE,WAAW,EAAE,MAAM,OAAO,CAAC;AA+BhE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AACH,MAAM,CAAC,OAAO,UAAU,YAAY,CAAE,CAAC,EACtC,IAAI,EAAE,GAAG,CAAE,CAAC,CAAE,EAAE,GACd,WAAW,CAAE,CAAC,CAAE,CA8DlB"}
|
|
@@ -1,27 +1,2 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Adds a callback to a shared `addEventListener`. Only one underlying
|
|
3
|
-
* native listener is attached per (root, event type, phase); subscribers
|
|
4
|
-
* join an in-JS registry that dispatches events along the DOM ancestry
|
|
5
|
-
* of `event.target`.
|
|
6
|
-
*
|
|
7
|
-
* The model mirrors React's synthetic event system: a single root
|
|
8
|
-
* listener handles every event of a given type, and callbacks bound to
|
|
9
|
-
* an `Element` only fire when that element is on the target's path.
|
|
10
|
-
* Callbacks bound to a `Document` always fire (document is the root of
|
|
11
|
-
* every event in that document); callbacks bound to a `Window` always
|
|
12
|
-
* fire as a flat fan-out, since `window` isn't on the DOM tree.
|
|
13
|
-
*
|
|
14
|
-
* @param target `Element`, `Document`, or `Window` to bind the
|
|
15
|
-
* callback to. For `Element`, the callback only fires
|
|
16
|
-
* when the event happens on the element or a
|
|
17
|
-
* descendant.
|
|
18
|
-
* @param eventType DOM event name.
|
|
19
|
-
* @param callback Listener to be invoked with the event.
|
|
20
|
-
* @param capture Use the capture phase. Required when ancestor
|
|
21
|
-
* listeners gate on `event.defaultPrevented`, since a
|
|
22
|
-
* bubble-phase root listener fires after them. Defaults
|
|
23
|
-
* to `false`.
|
|
24
|
-
* @return Unsubscribe function.
|
|
25
|
-
*/
|
|
26
1
|
export default function subscribeDelegatedListener(target: EventTarget, eventType: string, callback: EventListener, capture?: boolean): () => void;
|
|
27
2
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/utils/subscribe-delegated-listener/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/utils/subscribe-delegated-listener/index.ts"],"names":[],"mappings":"AAoCA,MAAM,CAAC,OAAO,UAAU,0BAA0B,CACjD,MAAM,EAAE,WAAW,EACnB,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,aAAa,EACvB,OAAO,GAAE,OAAe,GACtB,MAAM,IAAI,CAsFZ"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wordpress/compose",
|
|
3
|
-
"version": "8.
|
|
3
|
+
"version": "8.4.0",
|
|
4
4
|
"description": "WordPress higher-order components (HOCs).",
|
|
5
5
|
"author": "The WordPress Contributors",
|
|
6
6
|
"license": "GPL-2.0-or-later",
|
|
@@ -46,14 +46,14 @@
|
|
|
46
46
|
"sideEffects": false,
|
|
47
47
|
"dependencies": {
|
|
48
48
|
"@types/mousetrap": "^1.6.8",
|
|
49
|
-
"@wordpress/deprecated": "^4.
|
|
50
|
-
"@wordpress/dom": "^4.
|
|
51
|
-
"@wordpress/element": "^8.
|
|
52
|
-
"@wordpress/is-shallow-equal": "^5.
|
|
53
|
-
"@wordpress/keycodes": "^4.
|
|
54
|
-
"@wordpress/priority-queue": "^3.
|
|
55
|
-
"@wordpress/private-apis": "^1.
|
|
56
|
-
"@wordpress/undo-manager": "^1.
|
|
49
|
+
"@wordpress/deprecated": "^4.51.0",
|
|
50
|
+
"@wordpress/dom": "^4.51.0",
|
|
51
|
+
"@wordpress/element": "^8.3.0",
|
|
52
|
+
"@wordpress/is-shallow-equal": "^5.51.0",
|
|
53
|
+
"@wordpress/keycodes": "^4.51.0",
|
|
54
|
+
"@wordpress/priority-queue": "^3.51.0",
|
|
55
|
+
"@wordpress/private-apis": "^1.51.0",
|
|
56
|
+
"@wordpress/undo-manager": "^1.51.0",
|
|
57
57
|
"change-case": "^4.1.2",
|
|
58
58
|
"mousetrap": "^1.6.5",
|
|
59
59
|
"use-memo-one": "^1.1.1"
|
|
@@ -66,8 +66,8 @@
|
|
|
66
66
|
"react-dom": "^18.3.1"
|
|
67
67
|
},
|
|
68
68
|
"peerDependencies": {
|
|
69
|
-
"@types/react": "^18
|
|
70
|
-
"react": "^18
|
|
69
|
+
"@types/react": "^18 || ^19",
|
|
70
|
+
"react": "^18 || ^19"
|
|
71
71
|
},
|
|
72
72
|
"peerDependenciesMeta": {
|
|
73
73
|
"@types/react": {
|
|
@@ -77,5 +77,5 @@
|
|
|
77
77
|
"publishConfig": {
|
|
78
78
|
"access": "public"
|
|
79
79
|
},
|
|
80
|
-
"gitHead": "
|
|
80
|
+
"gitHead": "e9a74f9c14095a34398ecd4d1f7a908e55051205"
|
|
81
81
|
}
|
|
@@ -80,9 +80,9 @@ export default function useMergeRefs< T >(
|
|
|
80
80
|
refs: Ref< T >[]
|
|
81
81
|
): RefCallback< T > {
|
|
82
82
|
const elementRef = useRef< T | null >( null );
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
const
|
|
83
|
+
// The refs that are attached to the element: set when the element
|
|
84
|
+
// attaches, and kept in sync when a changed ref is swapped on render.
|
|
85
|
+
const attachedRefsRef = useRef< Ref< T >[] >( [] );
|
|
86
86
|
const currentRefsRef = useRef( refs );
|
|
87
87
|
// Position-indexed cleanups returned by inner ref callbacks. A slot is
|
|
88
88
|
// `undefined` when the ref at that position did not return a cleanup (or
|
|
@@ -93,34 +93,31 @@ export default function useMergeRefs< T >(
|
|
|
93
93
|
// always has access to the current refs.
|
|
94
94
|
currentRefsRef.current = refs;
|
|
95
95
|
|
|
96
|
-
// If any of the refs change, call the
|
|
97
|
-
// ref with the node
|
|
98
|
-
//
|
|
96
|
+
// If any of the refs change, call the attached ref with `null` and the
|
|
97
|
+
// new ref with the node. Comparing against the refs that are attached to
|
|
98
|
+
// the element, rather than the previous render's refs, also covers an
|
|
99
|
+
// element that attaches outside a render of this component (a merged ref
|
|
100
|
+
// passed to a child that mounts the element in its own commit): the
|
|
101
|
+
// change is still detected on the next render. When the element attached
|
|
102
|
+
// during this commit, the ref callback has already been called with the
|
|
103
|
+
// current refs, which compare equal here.
|
|
99
104
|
useLayoutEffect( () => {
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
refs.forEach( ( ref, index ) => {
|
|
105
|
-
const previousRef = previousRefsRef.current[ index ];
|
|
106
|
-
if ( ref !== previousRef ) {
|
|
107
|
-
detachRef( previousRef, index, cleanupsRef.current );
|
|
108
|
-
cleanupsRef.current[ index ] = assignRef(
|
|
109
|
-
ref,
|
|
110
|
-
elementRef.current as T
|
|
111
|
-
);
|
|
112
|
-
}
|
|
113
|
-
} );
|
|
105
|
+
const element = elementRef.current;
|
|
106
|
+
|
|
107
|
+
if ( element === null ) {
|
|
108
|
+
return;
|
|
114
109
|
}
|
|
115
110
|
|
|
116
|
-
|
|
117
|
-
|
|
111
|
+
refs.forEach( ( ref, index ) => {
|
|
112
|
+
const attachedRef = attachedRefsRef.current[ index ];
|
|
113
|
+
if ( ref !== attachedRef ) {
|
|
114
|
+
detachRef( attachedRef, index, cleanupsRef.current );
|
|
115
|
+
cleanupsRef.current[ index ] = assignRef( ref, element );
|
|
116
|
+
}
|
|
117
|
+
} );
|
|
118
118
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
useLayoutEffect( () => {
|
|
122
|
-
didElementChangeRef.current = false;
|
|
123
|
-
} );
|
|
119
|
+
attachedRefsRef.current = refs;
|
|
120
|
+
}, refs );
|
|
124
121
|
|
|
125
122
|
// There should be no dependencies so that `callback` is only called when
|
|
126
123
|
// the node changes.
|
|
@@ -129,17 +126,16 @@ export default function useMergeRefs< T >(
|
|
|
129
126
|
// dependency change.
|
|
130
127
|
elementRef.current = value;
|
|
131
128
|
|
|
132
|
-
didElementChangeRef.current = true;
|
|
133
|
-
isAttachedRef.current = value !== null;
|
|
134
|
-
|
|
135
129
|
// When an element changes, the current ref callback should be called
|
|
136
|
-
// with the new element and the
|
|
130
|
+
// with the new element and the attached one with `null`.
|
|
137
131
|
if ( value === null ) {
|
|
138
|
-
|
|
132
|
+
attachedRefsRef.current.forEach( ( ref, index ) => {
|
|
139
133
|
detachRef( ref, index, cleanupsRef.current );
|
|
140
134
|
} );
|
|
135
|
+
attachedRefsRef.current = [];
|
|
141
136
|
} else {
|
|
142
|
-
|
|
137
|
+
attachedRefsRef.current = currentRefsRef.current;
|
|
138
|
+
attachedRefsRef.current.forEach( ( ref, index ) => {
|
|
143
139
|
cleanupsRef.current[ index ] = assignRef( ref, value );
|
|
144
140
|
} );
|
|
145
141
|
}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* External dependencies
|
|
3
3
|
*/
|
|
4
|
-
import { render, screen } from '@testing-library/react';
|
|
4
|
+
import { render, screen, fireEvent } from '@testing-library/react';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* WordPress dependencies
|
|
8
8
|
*/
|
|
9
|
-
import { useCallback } from '@wordpress/element';
|
|
9
|
+
import { useCallback, useState } from '@wordpress/element';
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
12
|
* Internal dependencies
|
|
@@ -344,6 +344,74 @@ describe( 'useMergeRefs', () => {
|
|
|
344
344
|
[ [], [] ],
|
|
345
345
|
] );
|
|
346
346
|
} );
|
|
347
|
+
|
|
348
|
+
it( 'should work for dependency change after attachment outside a render of the owner', () => {
|
|
349
|
+
// The merged ref is created by a parent, but the element is mounted
|
|
350
|
+
// by a child in a commit of its own (e.g. the editor iframe portals
|
|
351
|
+
// the canvas body once the iframe document is available). The parent
|
|
352
|
+
// does not render in that commit, so the hook must still detect and
|
|
353
|
+
// apply a later ref change on the parent's next render.
|
|
354
|
+
function Child( { mergedRefs } ) {
|
|
355
|
+
const [ attached, setAttached ] = useState( false );
|
|
356
|
+
return (
|
|
357
|
+
<>
|
|
358
|
+
<button onClick={ () => setAttached( true ) } />
|
|
359
|
+
{ attached && <ul ref={ mergedRefs } /> }
|
|
360
|
+
</>
|
|
361
|
+
);
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
function Parent( { count } ) {
|
|
365
|
+
function refCallback1( value ) {
|
|
366
|
+
refCallback1.history.push( value );
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
refCallback1.history = [];
|
|
370
|
+
|
|
371
|
+
function refCallback2( value ) {
|
|
372
|
+
refCallback2.history.push( value );
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
refCallback2.history = [];
|
|
376
|
+
|
|
377
|
+
renderCallback( [ refCallback1.history, refCallback2.history ] );
|
|
378
|
+
|
|
379
|
+
const ref1 = useCallback( refCallback1, [] );
|
|
380
|
+
const ref2 = useCallback( refCallback2, [ count ] );
|
|
381
|
+
return <Child mergedRefs={ useMergeRefs( [ ref1, ref2 ] ) } />;
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
const { rerender, unmount } = render( <Parent count={ 1 } /> );
|
|
385
|
+
|
|
386
|
+
// Mount the element in a child-only commit: the parent does not
|
|
387
|
+
// render.
|
|
388
|
+
fireEvent.click( screen.getByRole( 'button' ) );
|
|
389
|
+
|
|
390
|
+
const originalElement = screen.getByRole( 'list' );
|
|
391
|
+
|
|
392
|
+
expect( renderCallback.history ).toEqual( [
|
|
393
|
+
[ [ originalElement ], [ originalElement ] ],
|
|
394
|
+
] );
|
|
395
|
+
|
|
396
|
+
rerender( <Parent count={ 2 } /> );
|
|
397
|
+
|
|
398
|
+
// The dependency change must still swap the second ref: the initial
|
|
399
|
+
// function called with null, the new function with the attached node.
|
|
400
|
+
expect( renderCallback.history ).toEqual( [
|
|
401
|
+
[ [ originalElement ], [ originalElement, null ] ],
|
|
402
|
+
[ [], [ originalElement ] ],
|
|
403
|
+
] );
|
|
404
|
+
|
|
405
|
+
unmount();
|
|
406
|
+
|
|
407
|
+
expect( renderCallback.history ).toEqual( [
|
|
408
|
+
[
|
|
409
|
+
[ originalElement, null ],
|
|
410
|
+
[ originalElement, null ],
|
|
411
|
+
],
|
|
412
|
+
[ [], [ originalElement, null ] ],
|
|
413
|
+
] );
|
|
414
|
+
} );
|
|
347
415
|
} );
|
|
348
416
|
|
|
349
417
|
describe( 'useMergeRefs with cleanup-returning ref callbacks', () => {
|