@wordpress/compose 8.1.0 → 8.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/CHANGELOG.md +20 -1
  2. package/README.md +5 -5
  3. package/build/higher-order/pure/index.cjs +15 -0
  4. package/build/higher-order/pure/index.cjs.map +3 -3
  5. package/build/hooks/use-media-query/index.cjs +2 -2
  6. package/build/hooks/use-media-query/index.cjs.map +2 -2
  7. package/build/hooks/use-merge-refs/index.cjs +28 -8
  8. package/build/hooks/use-merge-refs/index.cjs.map +2 -2
  9. package/build/hooks/use-viewport-match/index.cjs +1 -1
  10. package/build/hooks/use-viewport-match/index.cjs.map +2 -2
  11. package/build-module/higher-order/pure/index.mjs +5 -0
  12. package/build-module/higher-order/pure/index.mjs.map +2 -2
  13. package/build-module/hooks/use-media-query/index.mjs +2 -2
  14. package/build-module/hooks/use-media-query/index.mjs.map +2 -2
  15. package/build-module/hooks/use-merge-refs/index.mjs +28 -8
  16. package/build-module/hooks/use-merge-refs/index.mjs.map +2 -2
  17. package/build-module/hooks/use-viewport-match/index.mjs +1 -1
  18. package/build-module/hooks/use-viewport-match/index.mjs.map +2 -2
  19. package/build-types/higher-order/pure/index.d.ts.map +1 -1
  20. package/build-types/hooks/use-media-query/index.d.ts +1 -1
  21. package/build-types/hooks/use-media-query/index.d.ts.map +1 -1
  22. package/build-types/hooks/use-merge-refs/index.d.ts +7 -5
  23. package/build-types/hooks/use-merge-refs/index.d.ts.map +1 -1
  24. package/build-types/hooks/use-viewport-match/index.d.ts +1 -1
  25. package/build-types/hooks/use-viewport-match/index.d.ts.map +1 -1
  26. package/package.json +16 -12
  27. package/src/higher-order/pure/index.tsx +6 -0
  28. package/src/higher-order/pure/test/index.js +14 -81
  29. package/src/hooks/use-drop-zone/README.md +1 -1
  30. package/src/hooks/use-media-query/index.ts +10 -3
  31. package/src/hooks/use-media-query/test/ssr.js +47 -0
  32. package/src/hooks/use-merge-refs/index.ts +49 -18
  33. package/src/hooks/use-merge-refs/test/index.js +288 -0
  34. package/src/hooks/use-viewport-match/index.js +8 -2
  35. package/src/higher-order/with-network-connectivity/README.md +0 -20
  36. package/src/higher-order/with-network-connectivity/index.native.js +0 -19
  37. package/src/higher-order/with-preferred-color-scheme/index.native.js +0 -40
  38. package/src/hooks/use-constrained-tabbing/index.native.js +0 -14
  39. package/src/hooks/use-focus-outside/index.native.js +0 -170
  40. package/src/hooks/use-keyboard-shortcut/index.native.js +0 -2
  41. package/src/hooks/use-network-connectivity/index.native.js +0 -59
  42. package/src/hooks/use-network-connectivity/test/index.native.js +0 -87
  43. package/src/hooks/use-preferred-color-scheme/index.android.js +0 -30
  44. package/src/hooks/use-preferred-color-scheme/index.ios.js +0 -13
  45. package/src/hooks/use-preferred-color-scheme-style/index.native.js +0 -33
  46. package/src/hooks/use-resize-observer/index.native.js +0 -1
  47. package/src/hooks/use-resize-observer/legacy/index.native.js +0 -59
  48. package/src/hooks/use-resize-observer/legacy/test/index.native.js +0 -46
  49. package/src/index.native.js +0 -44
package/CHANGELOG.md CHANGED
@@ -2,7 +2,17 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
- ## 8.1.0 (2026-06-04)
5
+ ## 8.1.1 (2026-06-16)
6
+
7
+ ## 8.1.0 (2026-06-10)
8
+
9
+ ### Code Quality
10
+
11
+ - Add missing `@types/react` dependency. [#78882](https://github.com/WordPress/gutenberg/pull/78882).
12
+
13
+ ### Documentation
14
+
15
+ - Fix documentation typos ([#78686](https://github.com/WordPress/gutenberg/pull/78686)).
6
16
 
7
17
  ## 8.0.0 (2026-05-27)
8
18
 
@@ -10,10 +20,19 @@
10
20
 
11
21
  - `useDialog`: The returned `props` object now exposes an `onKeyDown` handler. Consumers that spread it onto a wrapper which also receives an `onKeyDown` from elsewhere should pass that handler via the new `onKeyDown` option (which merges it with close-on-Escape) or merge the two themselves ([#78433](https://github.com/WordPress/gutenberg/pull/78433)).
12
22
 
23
+ ### Enhancements
24
+
25
+ - `useMergeRefs`: Support cleanup functions returned by inner ref callbacks (React 19 ref callback cleanup pattern). Inner refs that return a cleanup have it invoked at teardown instead of being called with `null`.
26
+
13
27
  ### Bug Fixes
14
28
 
15
29
  - `useCopyToClipboard`: Call the `onSuccess` callback even when the trigger node unmounts before the copy resolves ([#78387](https://github.com/WordPress/gutenberg/pull/78387)).
16
30
  - `useDialog`: Handle Escape via React `onKeyDown` so portaled descendants can stop propagation to prevent the dialog from closing ([#78433](https://github.com/WordPress/gutenberg/pull/78433)).
31
+ - `useMediaQuery`, `useViewportMatch`: Resolve the `view` default lazily so the hooks no longer throw `ReferenceError: window is not defined` during server-side rendering. Regression from [#76446](https://github.com/WordPress/gutenberg/pull/76446).
32
+
33
+ ### Deprecations
34
+
35
+ - The `pure` HoC now logs a runtime deprecation warning. Use `memo` or `PureComponent` from `@wordpress/element` instead.
17
36
 
18
37
  ## 7.46.0 (2026-05-14)
19
38
 
package/README.md CHANGED
@@ -435,7 +435,7 @@ Runs a media query and returns its value when it changes.
435
435
  _Parameters_
436
436
 
437
437
  - _query_ `[string]`: Media Query.
438
- - _view_ `[Window]`: Window instance, else default to global window
438
+ - _view_ `[Window | undefined]`: Window instance, else default to global window
439
439
 
440
440
  _Returns_
441
441
 
@@ -451,19 +451,19 @@ As expected, if you pass a new function on every render, the ref callback will b
451
451
 
452
452
  If you don't wish a ref callback to be called after every render, wrap it with `useCallback( callback, dependencies )`. When a dependency changes, the old ref callback will be called with `null` and the new ref callback will be called with the same value.
453
453
 
454
- To make ref callbacks easier to use, you can also pass the result of `useRefEffect`, which makes cleanup easier by allowing you to return a cleanup function instead of handling `null`.
454
+ Inner ref callbacks may return a cleanup function (React 19's ref callback cleanup pattern). When a ref callback returns a function, that function is invoked at teardown (node change, dependency change, or unmount) **instead of** the callback being called with `null`. Callbacks that do not return a cleanup continue to receive `null` on teardown as before.
455
455
 
456
456
  It's also possible to _disable_ a ref (and its behaviour) by simply not passing the ref.
457
457
 
458
458
  ```jsx
459
- const ref = useRefEffect( ( node ) => {
459
+ const ref = useCallback( ( node ) => {
460
460
  node.addEventListener( ... );
461
461
  return () => {
462
462
  node.removeEventListener( ... );
463
463
  };
464
464
  }, [ ...dependencies ] );
465
465
  const otherRef = useRef();
466
- const mergedRefs useMergeRefs( [
466
+ const mergedRefs = useMergeRefs( [
467
467
  enabled && ref,
468
468
  otherRef,
469
469
  ] );
@@ -597,7 +597,7 @@ _Parameters_
597
597
 
598
598
  - _breakpoint_ `WPBreakpoint`: Breakpoint size name.
599
599
  - _operator_ `[WPViewportOperator]`: Viewport operator.
600
- - _view_ `[Window]`: Window instance in which to perform viewport matching.
600
+ - _view_ `[Window|undefined]`: Window instance in which to perform viewport matching.
601
601
 
602
602
  _Returns_
603
603
 
@@ -1,7 +1,9 @@
1
1
  "use strict";
2
+ var __create = Object.create;
2
3
  var __defProp = Object.defineProperty;
3
4
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
5
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
5
7
  var __hasOwnProp = Object.prototype.hasOwnProperty;
6
8
  var __export = (target, all) => {
7
9
  for (var name in all)
@@ -15,6 +17,14 @@ var __copyProps = (to, from, except, desc) => {
15
17
  }
16
18
  return to;
17
19
  };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
18
28
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
29
 
20
30
  // packages/compose/src/higher-order/pure/index.tsx
@@ -25,9 +35,14 @@ __export(pure_exports, {
25
35
  module.exports = __toCommonJS(pure_exports);
26
36
  var import_is_shallow_equal = require("@wordpress/is-shallow-equal");
27
37
  var import_element = require("@wordpress/element");
38
+ var import_deprecated = __toESM(require("@wordpress/deprecated"));
28
39
  var import_create_higher_order_component = require("../../utils/create-higher-order-component/index.cjs");
29
40
  var import_jsx_runtime = require("react/jsx-runtime");
30
41
  var pure = (0, import_create_higher_order_component.createHigherOrderComponent)(function(WrappedComponent) {
42
+ (0, import_deprecated.default)("wp.compose.pure", {
43
+ since: "7.1",
44
+ alternative: "Use `memo` or `PureComponent` instead"
45
+ });
31
46
  if (WrappedComponent.prototype instanceof import_element.Component) {
32
47
  return class extends WrappedComponent {
33
48
  shouldComponentUpdate(nextProps, nextState) {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/higher-order/pure/index.tsx"],
4
- "sourcesContent": ["/**\n * External dependencies\n */\nimport type { ComponentType, ComponentClass } from 'react';\n\n/**\n * WordPress dependencies\n */\nimport { isShallowEqual } from '@wordpress/is-shallow-equal';\nimport { Component } from '@wordpress/element';\n\n/**\n * Internal dependencies\n */\nimport { createHigherOrderComponent } from '../../utils/create-higher-order-component';\n\n/**\n * Given a component returns the enhanced component augmented with a component\n * only re-rendering when its props/state change\n *\n * @deprecated Use `memo` or `PureComponent` instead.\n */\nconst pure = createHigherOrderComponent( function < Props extends {} >(\n\tWrappedComponent: ComponentType< Props >\n): ComponentType< Props > {\n\tif ( WrappedComponent.prototype instanceof Component ) {\n\t\treturn class extends ( WrappedComponent as ComponentClass< Props > ) {\n\t\t\tshouldComponentUpdate( nextProps: Props, nextState: any ) {\n\t\t\t\treturn (\n\t\t\t\t\t! isShallowEqual( nextProps, this.props ) ||\n\t\t\t\t\t! isShallowEqual( nextState, this.state )\n\t\t\t\t);\n\t\t\t}\n\t\t};\n\t}\n\n\treturn class extends Component< Props > {\n\t\tshouldComponentUpdate( nextProps: Props ) {\n\t\t\treturn ! isShallowEqual( nextProps, this.props );\n\t\t}\n\n\t\trender() {\n\t\t\treturn <WrappedComponent { ...this.props } />;\n\t\t}\n\t};\n}, 'pure' );\n\nexport default pure;\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAQA,8BAA+B;AAC/B,qBAA0B;AAK1B,2CAA2C;AA4BjC;AApBV,IAAM,WAAO,iEAA4B,SACxC,kBACyB;AACzB,MAAK,iBAAiB,qBAAqB,0BAAY;AACtD,WAAO,cAAgB,iBAA8C;AAAA,MACpE,sBAAuB,WAAkB,WAAiB;AACzD,eACC,KAAE,wCAAgB,WAAW,KAAK,KAAM,KACxC,KAAE,wCAAgB,WAAW,KAAK,KAAM;AAAA,MAE1C;AAAA,IACD;AAAA,EACD;AAEA,SAAO,cAAc,yBAAmB;AAAA,IACvC,sBAAuB,WAAmB;AACzC,aAAO,KAAE,wCAAgB,WAAW,KAAK,KAAM;AAAA,IAChD;AAAA,IAEA,SAAS;AACR,aAAO,4CAAC,oBAAmB,GAAG,KAAK,OAAQ;AAAA,IAC5C;AAAA,EACD;AACD,GAAG,MAAO;AAEV,IAAO,eAAQ;",
6
- "names": []
4
+ "sourcesContent": ["/**\n * External dependencies\n */\nimport type { ComponentType, ComponentClass } from 'react';\n\n/**\n * WordPress dependencies\n */\nimport { isShallowEqual } from '@wordpress/is-shallow-equal';\nimport { Component } from '@wordpress/element';\nimport deprecated from '@wordpress/deprecated';\n\n/**\n * Internal dependencies\n */\nimport { createHigherOrderComponent } from '../../utils/create-higher-order-component';\n\n/**\n * Given a component returns the enhanced component augmented with a component\n * only re-rendering when its props/state change\n *\n * @deprecated Use `memo` or `PureComponent` instead.\n */\nconst pure = createHigherOrderComponent( function < Props extends {} >(\n\tWrappedComponent: ComponentType< Props >\n): ComponentType< Props > {\n\tdeprecated( 'wp.compose.pure', {\n\t\tsince: '7.1',\n\t\talternative: 'Use `memo` or `PureComponent` instead',\n\t} );\n\n\tif ( WrappedComponent.prototype instanceof Component ) {\n\t\treturn class extends ( WrappedComponent as ComponentClass< Props > ) {\n\t\t\tshouldComponentUpdate( nextProps: Props, nextState: any ) {\n\t\t\t\treturn (\n\t\t\t\t\t! isShallowEqual( nextProps, this.props ) ||\n\t\t\t\t\t! isShallowEqual( nextState, this.state )\n\t\t\t\t);\n\t\t\t}\n\t\t};\n\t}\n\n\treturn class extends Component< Props > {\n\t\tshouldComponentUpdate( nextProps: Props ) {\n\t\t\treturn ! isShallowEqual( nextProps, this.props );\n\t\t}\n\n\t\trender() {\n\t\t\treturn <WrappedComponent { ...this.props } />;\n\t\t}\n\t};\n}, 'pure' );\n\nexport default pure;\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAQA,8BAA+B;AAC/B,qBAA0B;AAC1B,wBAAuB;AAKvB,2CAA2C;AAiCjC;AAzBV,IAAM,WAAO,iEAA4B,SACxC,kBACyB;AACzB,wBAAAA,SAAY,mBAAmB;AAAA,IAC9B,OAAO;AAAA,IACP,aAAa;AAAA,EACd,CAAE;AAEF,MAAK,iBAAiB,qBAAqB,0BAAY;AACtD,WAAO,cAAgB,iBAA8C;AAAA,MACpE,sBAAuB,WAAkB,WAAiB;AACzD,eACC,KAAE,wCAAgB,WAAW,KAAK,KAAM,KACxC,KAAE,wCAAgB,WAAW,KAAK,KAAM;AAAA,MAE1C;AAAA,IACD;AAAA,EACD;AAEA,SAAO,cAAc,yBAAmB;AAAA,IACvC,sBAAuB,WAAmB;AACzC,aAAO,KAAE,wCAAgB,WAAW,KAAK,KAAM;AAAA,IAChD;AAAA,IAEA,SAAS;AACR,aAAO,4CAAC,oBAAmB,GAAG,KAAK,OAAQ;AAAA,IAC5C;AAAA,EACD;AACD,GAAG,MAAO;AAEV,IAAO,eAAQ;",
6
+ "names": ["deprecated"]
7
7
  }
@@ -31,7 +31,7 @@ var EMPTY_SUBSCRIBER = {
31
31
  getValue: () => false
32
32
  };
33
33
  function getMQLSubscriber(view, query) {
34
- if (!query || typeof view?.matchMedia !== "function") {
34
+ if (!view || !query || typeof view.matchMedia !== "function") {
35
35
  return EMPTY_SUBSCRIBER;
36
36
  }
37
37
  let queryCache = perWindowCache.get(view);
@@ -70,7 +70,7 @@ function getMQLSubscriber(view, query) {
70
70
  queryCache.set(query, subscriber);
71
71
  return subscriber;
72
72
  }
73
- function useMediaQuery(query, view = window) {
73
+ function useMediaQuery(query, view = typeof window !== "undefined" ? window : void 0) {
74
74
  const source = getMQLSubscriber(view, query);
75
75
  return (0, import_element.useSyncExternalStore)(
76
76
  source.subscribe,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/hooks/use-media-query/index.ts"],
4
- "sourcesContent": ["/**\n * WordPress dependencies\n */\nimport { useSyncExternalStore } from '@wordpress/element';\n\ntype MQLSubscriber = {\n\tsubscribe: ( onStoreChange: () => void ) => () => void;\n\tgetValue: () => boolean;\n};\n\n// One subscriber per (window, query). The underlying MediaQueryList lives\n// inside the subscriber's closure; a single `change` listener fans out to\n// every React consumer via an in-JS `Set` to avoid the per-consumer\n// `addEventListener` cost (~85 ms during a large-post editor mount).\nconst perWindowCache = new WeakMap< Window, Map< string, MQLSubscriber > >();\n\nconst EMPTY_SUBSCRIBER: MQLSubscriber = {\n\tsubscribe: () => () => {},\n\tgetValue: () => false,\n};\n\nfunction getMQLSubscriber( view: Window, query?: string ): MQLSubscriber {\n\tif ( ! query || typeof view?.matchMedia !== 'function' ) {\n\t\treturn EMPTY_SUBSCRIBER;\n\t}\n\n\tlet queryCache = perWindowCache.get( view );\n\tif ( ! queryCache ) {\n\t\tqueryCache = new Map();\n\t\tperWindowCache.set( view, queryCache );\n\t}\n\n\tconst cached = queryCache.get( query );\n\tif ( cached ) {\n\t\treturn cached;\n\t}\n\n\tconst mediaQueryList = view.matchMedia( query );\n\tconst listeners = new Set< () => void >();\n\tconst notify = () => {\n\t\tfor ( const listener of listeners ) {\n\t\t\tlistener();\n\t\t}\n\t};\n\n\tconst subscriber: MQLSubscriber = {\n\t\tsubscribe( onStoreChange ) {\n\t\t\tif ( listeners.size === 0 ) {\n\t\t\t\t// Avoid a fatal error when browsers don't support `addEventListener` on MediaQueryList.\n\t\t\t\tmediaQueryList.addEventListener?.( 'change', notify );\n\t\t\t}\n\t\t\tlisteners.add( onStoreChange );\n\t\t\treturn () => {\n\t\t\t\tlisteners.delete( onStoreChange );\n\t\t\t\tif ( listeners.size === 0 ) {\n\t\t\t\t\tmediaQueryList.removeEventListener?.( 'change', notify );\n\t\t\t\t}\n\t\t\t};\n\t\t},\n\t\tgetValue() {\n\t\t\treturn mediaQueryList.matches;\n\t\t},\n\t};\n\n\tqueryCache.set( query, subscriber );\n\treturn subscriber;\n}\n\n/**\n * Runs a media query and returns its value when it changes.\n *\n * @param [query] Media Query.\n * @param [view] Window instance, else default to global window\n * @return return value of the media query.\n */\nexport default function useMediaQuery(\n\tquery?: string,\n\tview: Window = window\n): boolean {\n\tconst source = getMQLSubscriber( view, query );\n\n\treturn useSyncExternalStore(\n\t\tsource.subscribe,\n\t\tsource.getValue,\n\t\t() => false\n\t);\n}\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAGA,qBAAqC;AAWrC,IAAM,iBAAiB,oBAAI,QAAgD;AAE3E,IAAM,mBAAkC;AAAA,EACvC,WAAW,MAAM,MAAM;AAAA,EAAC;AAAA,EACxB,UAAU,MAAM;AACjB;AAEA,SAAS,iBAAkB,MAAc,OAAgC;AACxE,MAAK,CAAE,SAAS,OAAO,MAAM,eAAe,YAAa;AACxD,WAAO;AAAA,EACR;AAEA,MAAI,aAAa,eAAe,IAAK,IAAK;AAC1C,MAAK,CAAE,YAAa;AACnB,iBAAa,oBAAI,IAAI;AACrB,mBAAe,IAAK,MAAM,UAAW;AAAA,EACtC;AAEA,QAAM,SAAS,WAAW,IAAK,KAAM;AACrC,MAAK,QAAS;AACb,WAAO;AAAA,EACR;AAEA,QAAM,iBAAiB,KAAK,WAAY,KAAM;AAC9C,QAAM,YAAY,oBAAI,IAAkB;AACxC,QAAM,SAAS,MAAM;AACpB,eAAY,YAAY,WAAY;AACnC,eAAS;AAAA,IACV;AAAA,EACD;AAEA,QAAM,aAA4B;AAAA,IACjC,UAAW,eAAgB;AAC1B,UAAK,UAAU,SAAS,GAAI;AAE3B,uBAAe,mBAAoB,UAAU,MAAO;AAAA,MACrD;AACA,gBAAU,IAAK,aAAc;AAC7B,aAAO,MAAM;AACZ,kBAAU,OAAQ,aAAc;AAChC,YAAK,UAAU,SAAS,GAAI;AAC3B,yBAAe,sBAAuB,UAAU,MAAO;AAAA,QACxD;AAAA,MACD;AAAA,IACD;AAAA,IACA,WAAW;AACV,aAAO,eAAe;AAAA,IACvB;AAAA,EACD;AAEA,aAAW,IAAK,OAAO,UAAW;AAClC,SAAO;AACR;AASe,SAAR,cACN,OACA,OAAe,QACL;AACV,QAAM,SAAS,iBAAkB,MAAM,KAAM;AAE7C,aAAO;AAAA,IACN,OAAO;AAAA,IACP,OAAO;AAAA,IACP,MAAM;AAAA,EACP;AACD;",
4
+ "sourcesContent": ["/**\n * WordPress dependencies\n */\nimport { useSyncExternalStore } from '@wordpress/element';\n\ntype MQLSubscriber = {\n\tsubscribe: ( onStoreChange: () => void ) => () => void;\n\tgetValue: () => boolean;\n};\n\n// One subscriber per (window, query). The underlying MediaQueryList lives\n// inside the subscriber's closure; a single `change` listener fans out to\n// every React consumer via an in-JS `Set` to avoid the per-consumer\n// `addEventListener` cost (~85 ms during a large-post editor mount).\nconst perWindowCache = new WeakMap< Window, Map< string, MQLSubscriber > >();\n\nconst EMPTY_SUBSCRIBER: MQLSubscriber = {\n\tsubscribe: () => () => {},\n\tgetValue: () => false,\n};\n\nfunction getMQLSubscriber(\n\tview: Window | undefined,\n\tquery?: string\n): MQLSubscriber {\n\tif ( ! view || ! query || typeof view.matchMedia !== 'function' ) {\n\t\treturn EMPTY_SUBSCRIBER;\n\t}\n\n\tlet queryCache = perWindowCache.get( view );\n\tif ( ! queryCache ) {\n\t\tqueryCache = new Map();\n\t\tperWindowCache.set( view, queryCache );\n\t}\n\n\tconst cached = queryCache.get( query );\n\tif ( cached ) {\n\t\treturn cached;\n\t}\n\n\tconst mediaQueryList = view.matchMedia( query );\n\tconst listeners = new Set< () => void >();\n\tconst notify = () => {\n\t\tfor ( const listener of listeners ) {\n\t\t\tlistener();\n\t\t}\n\t};\n\n\tconst subscriber: MQLSubscriber = {\n\t\tsubscribe( onStoreChange ) {\n\t\t\tif ( listeners.size === 0 ) {\n\t\t\t\t// Avoid a fatal error when browsers don't support `addEventListener` on MediaQueryList.\n\t\t\t\tmediaQueryList.addEventListener?.( 'change', notify );\n\t\t\t}\n\t\t\tlisteners.add( onStoreChange );\n\t\t\treturn () => {\n\t\t\t\tlisteners.delete( onStoreChange );\n\t\t\t\tif ( listeners.size === 0 ) {\n\t\t\t\t\tmediaQueryList.removeEventListener?.( 'change', notify );\n\t\t\t\t}\n\t\t\t};\n\t\t},\n\t\tgetValue() {\n\t\t\treturn mediaQueryList.matches;\n\t\t},\n\t};\n\n\tqueryCache.set( query, subscriber );\n\treturn subscriber;\n}\n\n/**\n * Runs a media query and returns its value when it changes.\n *\n * @param [query] Media Query.\n * @param [view] Window instance, else default to global window\n * @return return value of the media query.\n */\nexport default function useMediaQuery(\n\tquery?: string,\n\t// Resolve the default lazily so SSR (where `window` is undeclared) does not\n\t// throw a ReferenceError when this default expression is evaluated.\n\tview: Window | undefined = typeof window !== 'undefined'\n\t\t? window\n\t\t: undefined\n): boolean {\n\tconst source = getMQLSubscriber( view, query );\n\n\treturn useSyncExternalStore(\n\t\tsource.subscribe,\n\t\tsource.getValue,\n\t\t() => false\n\t);\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAGA,qBAAqC;AAWrC,IAAM,iBAAiB,oBAAI,QAAgD;AAE3E,IAAM,mBAAkC;AAAA,EACvC,WAAW,MAAM,MAAM;AAAA,EAAC;AAAA,EACxB,UAAU,MAAM;AACjB;AAEA,SAAS,iBACR,MACA,OACgB;AAChB,MAAK,CAAE,QAAQ,CAAE,SAAS,OAAO,KAAK,eAAe,YAAa;AACjE,WAAO;AAAA,EACR;AAEA,MAAI,aAAa,eAAe,IAAK,IAAK;AAC1C,MAAK,CAAE,YAAa;AACnB,iBAAa,oBAAI,IAAI;AACrB,mBAAe,IAAK,MAAM,UAAW;AAAA,EACtC;AAEA,QAAM,SAAS,WAAW,IAAK,KAAM;AACrC,MAAK,QAAS;AACb,WAAO;AAAA,EACR;AAEA,QAAM,iBAAiB,KAAK,WAAY,KAAM;AAC9C,QAAM,YAAY,oBAAI,IAAkB;AACxC,QAAM,SAAS,MAAM;AACpB,eAAY,YAAY,WAAY;AACnC,eAAS;AAAA,IACV;AAAA,EACD;AAEA,QAAM,aAA4B;AAAA,IACjC,UAAW,eAAgB;AAC1B,UAAK,UAAU,SAAS,GAAI;AAE3B,uBAAe,mBAAoB,UAAU,MAAO;AAAA,MACrD;AACA,gBAAU,IAAK,aAAc;AAC7B,aAAO,MAAM;AACZ,kBAAU,OAAQ,aAAc;AAChC,YAAK,UAAU,SAAS,GAAI;AAC3B,yBAAe,sBAAuB,UAAU,MAAO;AAAA,QACxD;AAAA,MACD;AAAA,IACD;AAAA,IACA,WAAW;AACV,aAAO,eAAe;AAAA,IACvB;AAAA,EACD;AAEA,aAAW,IAAK,OAAO,UAAW;AAClC,SAAO;AACR;AASe,SAAR,cACN,OAGA,OAA2B,OAAO,WAAW,cAC1C,SACA,QACO;AACV,QAAM,SAAS,iBAAkB,MAAM,KAAM;AAE7C,aAAO;AAAA,IACN,OAAO;AAAA,IACP,OAAO;AAAA,IACP,MAAM;AAAA,EACP;AACD;",
6
6
  "names": []
7
7
  }
@@ -26,25 +26,40 @@ module.exports = __toCommonJS(use_merge_refs_exports);
26
26
  var import_element = require("@wordpress/element");
27
27
  function assignRef(ref, value) {
28
28
  if (typeof ref === "function") {
29
- ref(value);
29
+ const returned = ref(value);
30
+ return typeof returned === "function" ? returned : void 0;
30
31
  } else if (ref && ref.hasOwnProperty("current")) {
31
32
  ref.current = value;
32
33
  }
34
+ return void 0;
35
+ }
36
+ function detachRef(ref, index, cleanups) {
37
+ const cleanup = cleanups[index];
38
+ if (cleanup) {
39
+ cleanups[index] = void 0;
40
+ cleanup();
41
+ } else {
42
+ assignRef(ref, null);
43
+ }
33
44
  }
34
45
  function useMergeRefs(refs) {
35
- const element = (0, import_element.useRef)(null);
46
+ const elementRef = (0, import_element.useRef)(null);
36
47
  const isAttachedRef = (0, import_element.useRef)(false);
37
48
  const didElementChangeRef = (0, import_element.useRef)(false);
38
49
  const previousRefsRef = (0, import_element.useRef)([]);
39
50
  const currentRefsRef = (0, import_element.useRef)(refs);
51
+ const cleanupsRef = (0, import_element.useRef)([]);
40
52
  currentRefsRef.current = refs;
41
53
  (0, import_element.useLayoutEffect)(() => {
42
54
  if (didElementChangeRef.current === false && isAttachedRef.current === true) {
43
55
  refs.forEach((ref, index) => {
44
56
  const previousRef = previousRefsRef.current[index];
45
57
  if (ref !== previousRef) {
46
- assignRef(previousRef, null);
47
- assignRef(ref, element.current);
58
+ detachRef(previousRef, index, cleanupsRef.current);
59
+ cleanupsRef.current[index] = assignRef(
60
+ ref,
61
+ elementRef.current
62
+ );
48
63
  }
49
64
  });
50
65
  }
@@ -54,12 +69,17 @@ function useMergeRefs(refs) {
54
69
  didElementChangeRef.current = false;
55
70
  });
56
71
  return (0, import_element.useCallback)((value) => {
57
- assignRef(element, value);
72
+ elementRef.current = value;
58
73
  didElementChangeRef.current = true;
59
74
  isAttachedRef.current = value !== null;
60
- const refsToAssign = value ? currentRefsRef.current : previousRefsRef.current;
61
- for (const ref of refsToAssign) {
62
- assignRef(ref, value);
75
+ if (value === null) {
76
+ previousRefsRef.current.forEach((ref, index) => {
77
+ detachRef(ref, index, cleanupsRef.current);
78
+ });
79
+ } else {
80
+ currentRefsRef.current.forEach((ref, index) => {
81
+ cleanupsRef.current[index] = assignRef(ref, value);
82
+ });
63
83
  }
64
84
  }, []);
65
85
  }
@@ -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\nfunction assignRef< T >( ref: Ref< T >, value: T ) {\n\tif ( typeof ref === 'function' ) {\n\t\tref( value );\n\t} else if ( ref && ref.hasOwnProperty( 'current' ) ) {\n\t\t( ref as MutableRefObject< T > ).current = value;\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 * To make ref callbacks easier to use, you can also pass the result of\n * `useRefEffect`, which makes cleanup easier by allowing you to return a\n * cleanup function instead of handling `null`.\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 = useRefEffect( ( 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 element = useRef( null );\n\tconst isAttachedRef = useRef( false );\n\tconst didElementChangeRef = useRef( false );\n\tconst previousRefsRef = useRef< Ref< T >[] >( [] );\n\tconst currentRefsRef = useRef( refs );\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 previous ref with `null` and the new\n\t// ref with the node, except when the element changes in the same cycle, in\n\t// which case the ref callbacks will already have been called.\n\tuseLayoutEffect( () => {\n\t\tif (\n\t\t\tdidElementChangeRef.current === false &&\n\t\t\tisAttachedRef.current === true\n\t\t) {\n\t\t\trefs.forEach( ( ref, index ) => {\n\t\t\t\tconst previousRef = previousRefsRef.current[ index ];\n\t\t\t\tif ( ref !== previousRef ) {\n\t\t\t\t\tassignRef( previousRef, null );\n\t\t\t\t\tassignRef( ref, element.current );\n\t\t\t\t}\n\t\t\t} );\n\t\t}\n\n\t\tpreviousRefsRef.current = refs;\n\t}, refs );\n\n\t// No dependencies, must be reset after every render so ref callbacks are\n\t// correctly called after a ref change.\n\tuseLayoutEffect( () => {\n\t\tdidElementChangeRef.current = false;\n\t} );\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\tassignRef( element, value );\n\n\t\tdidElementChangeRef.current = true;\n\t\tisAttachedRef.current = value !== null;\n\n\t\t// When an element changes, the current ref callback should be called\n\t\t// with the new element and the previous one with `null`.\n\t\tconst refsToAssign = value\n\t\t\t? currentRefsRef.current\n\t\t\t: previousRefsRef.current;\n\n\t\t// Update the latest refs.\n\t\tfor ( const ref of refsToAssign ) {\n\t\t\tassignRef( ref, value );\n\t\t}\n\t}, [] );\n}\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAGA,qBAAqD;AAGrD,SAAS,UAAgB,KAAe,OAAW;AAClD,MAAK,OAAO,QAAQ,YAAa;AAChC,QAAK,KAAM;AAAA,EACZ,WAAY,OAAO,IAAI,eAAgB,SAAU,GAAI;AACpD,IAAE,IAA+B,UAAU;AAAA,EAC5C;AACD;AA2Ce,SAAR,aACN,MACmB;AACnB,QAAM,cAAU,uBAAQ,IAAK;AAC7B,QAAM,oBAAgB,uBAAQ,KAAM;AACpC,QAAM,0BAAsB,uBAAQ,KAAM;AAC1C,QAAM,sBAAkB,uBAAsB,CAAC,CAAE;AACjD,QAAM,qBAAiB,uBAAQ,IAAK;AAIpC,iBAAe,UAAU;AAKzB,sCAAiB,MAAM;AACtB,QACC,oBAAoB,YAAY,SAChC,cAAc,YAAY,MACzB;AACD,WAAK,QAAS,CAAE,KAAK,UAAW;AAC/B,cAAM,cAAc,gBAAgB,QAAS,KAAM;AACnD,YAAK,QAAQ,aAAc;AAC1B,oBAAW,aAAa,IAAK;AAC7B,oBAAW,KAAK,QAAQ,OAAQ;AAAA,QACjC;AAAA,MACD,CAAE;AAAA,IACH;AAEA,oBAAgB,UAAU;AAAA,EAC3B,GAAG,IAAK;AAIR,sCAAiB,MAAM;AACtB,wBAAoB,UAAU;AAAA,EAC/B,CAAE;AAIF,aAAO,4BAAa,CAAE,UAAqB;AAG1C,cAAW,SAAS,KAAM;AAE1B,wBAAoB,UAAU;AAC9B,kBAAc,UAAU,UAAU;AAIlC,UAAM,eAAe,QAClB,eAAe,UACf,gBAAgB;AAGnB,eAAY,OAAO,cAAe;AACjC,gBAAW,KAAK,KAAM;AAAA,IACvB;AAAA,EACD,GAAG,CAAC,CAAE;AACP;",
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\tconst isAttachedRef = useRef( false );\n\tconst didElementChangeRef = useRef( false );\n\tconst previousRefsRef = 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 previous ref with `null` and the new\n\t// ref with the node, except when the element changes in the same cycle, in\n\t// which case the ref callbacks will already have been called.\n\tuseLayoutEffect( () => {\n\t\tif (\n\t\t\tdidElementChangeRef.current === false &&\n\t\t\tisAttachedRef.current === true\n\t\t) {\n\t\t\trefs.forEach( ( ref, index ) => {\n\t\t\t\tconst previousRef = previousRefsRef.current[ index ];\n\t\t\t\tif ( ref !== previousRef ) {\n\t\t\t\t\tdetachRef( previousRef, index, cleanupsRef.current );\n\t\t\t\t\tcleanupsRef.current[ index ] = assignRef(\n\t\t\t\t\t\tref,\n\t\t\t\t\t\telementRef.current as T\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t} );\n\t\t}\n\n\t\tpreviousRefsRef.current = refs;\n\t}, refs );\n\n\t// No dependencies, must be reset after every render so ref callbacks are\n\t// correctly called after a ref change.\n\tuseLayoutEffect( () => {\n\t\tdidElementChangeRef.current = false;\n\t} );\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\tdidElementChangeRef.current = true;\n\t\tisAttachedRef.current = value !== null;\n\n\t\t// When an element changes, the current ref callback should be called\n\t\t// with the new element and the previous one with `null`.\n\t\tif ( value === null ) {\n\t\t\tpreviousRefsRef.current.forEach( ( ref, index ) => {\n\t\t\t\tdetachRef( ref, index, cleanupsRef.current );\n\t\t\t} );\n\t\t} else {\n\t\t\tcurrentRefsRef.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;AAC5C,QAAM,oBAAgB,uBAAQ,KAAM;AACpC,QAAM,0BAAsB,uBAAQ,KAAM;AAC1C,QAAM,sBAAkB,uBAAsB,CAAC,CAAE;AACjD,QAAM,qBAAiB,uBAAQ,IAAK;AAIpC,QAAM,kBAAc,uBAA+C,CAAC,CAAE;AAItE,iBAAe,UAAU;AAKzB,sCAAiB,MAAM;AACtB,QACC,oBAAoB,YAAY,SAChC,cAAc,YAAY,MACzB;AACD,WAAK,QAAS,CAAE,KAAK,UAAW;AAC/B,cAAM,cAAc,gBAAgB,QAAS,KAAM;AACnD,YAAK,QAAQ,aAAc;AAC1B,oBAAW,aAAa,OAAO,YAAY,OAAQ;AACnD,sBAAY,QAAS,KAAM,IAAI;AAAA,YAC9B;AAAA,YACA,WAAW;AAAA,UACZ;AAAA,QACD;AAAA,MACD,CAAE;AAAA,IACH;AAEA,oBAAgB,UAAU;AAAA,EAC3B,GAAG,IAAK;AAIR,sCAAiB,MAAM;AACtB,wBAAoB,UAAU;AAAA,EAC/B,CAAE;AAIF,aAAO,4BAAa,CAAE,UAAqB;AAG1C,eAAW,UAAU;AAErB,wBAAoB,UAAU;AAC9B,kBAAc,UAAU,UAAU;AAIlC,QAAK,UAAU,MAAO;AACrB,sBAAgB,QAAQ,QAAS,CAAE,KAAK,UAAW;AAClD,kBAAW,KAAK,OAAO,YAAY,OAAQ;AAAA,MAC5C,CAAE;AAAA,IACH,OAAO;AACN,qBAAe,QAAQ,QAAS,CAAE,KAAK,UAAW;AACjD,oBAAY,QAAS,KAAM,IAAI,UAAW,KAAK,KAAM;AAAA,MACtD,CAAE;AAAA,IACH;AAAA,EACD,GAAG,CAAC,CAAE;AACP;",
6
6
  "names": []
7
7
  }
@@ -58,7 +58,7 @@ var ViewportMatchWidthContext = (0, import_element.createContext)(
58
58
  null
59
59
  );
60
60
  ViewportMatchWidthContext.displayName = "ViewportMatchWidthContext";
61
- var useViewportMatch = (breakpoint, operator = ">=", view = window) => {
61
+ var useViewportMatch = (breakpoint, operator = ">=", view = typeof window !== "undefined" ? window : void 0) => {
62
62
  const simulatedWidth = (0, import_element.useContext)(ViewportMatchWidthContext);
63
63
  const mediaQuery = !simulatedWidth && `(${CONDITIONS[operator]}: ${BREAKPOINTS[breakpoint]}px)`;
64
64
  const mediaQueryResult = (0, import_use_media_query.default)(mediaQuery || void 0, view);
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/hooks/use-viewport-match/index.js"],
4
- "sourcesContent": ["/**\n * WordPress dependencies\n */\nimport { createContext, useContext } from '@wordpress/element';\n\n/**\n * Internal dependencies\n */\nimport useMediaQuery from '../use-media-query';\n\n/**\n * @typedef {\"xhuge\" | \"huge\" | \"wide\" | \"xlarge\" | \"large\" | \"medium\" | \"small\" | \"mobile\"} WPBreakpoint\n */\n\n/**\n * Hash of breakpoint names with pixel width at which it becomes effective.\n *\n * @see _breakpoints.scss\n *\n * @type {Record<WPBreakpoint, number>}\n */\nconst BREAKPOINTS = {\n\txhuge: 1920,\n\thuge: 1440,\n\twide: 1280,\n\txlarge: 1080,\n\tlarge: 960,\n\tmedium: 782,\n\tsmall: 600,\n\tmobile: 480,\n};\n\n/**\n * @typedef {\">=\" | \"<\"} WPViewportOperator\n */\n\n/**\n * Object mapping media query operators to the condition to be used.\n *\n * @type {Record<WPViewportOperator, string>}\n */\nconst CONDITIONS = {\n\t'>=': 'min-width',\n\t'<': 'max-width',\n};\n\n/**\n * Object mapping media query operators to a function that given a breakpointValue and a width evaluates if the operator matches the values.\n *\n * @type {Record<WPViewportOperator, (breakpointValue: number, width: number) => boolean>}\n */\nconst OPERATOR_EVALUATORS = {\n\t'>=': ( breakpointValue, width ) => width >= breakpointValue,\n\t'<': ( breakpointValue, width ) => width < breakpointValue,\n};\n\nconst ViewportMatchWidthContext = createContext(\n\t/** @type {null | number} */ ( null )\n);\nViewportMatchWidthContext.displayName = 'ViewportMatchWidthContext';\n\n/**\n * Returns true if the viewport matches the given query, or false otherwise.\n *\n * @param {WPBreakpoint} breakpoint Breakpoint size name.\n * @param {WPViewportOperator} [operator=\">=\"] Viewport operator.\n * @param {Window} [view=window] Window instance in which to perform viewport matching.\n *\n * @example\n *\n * ```js\n * useViewportMatch( 'huge', '<' );\n * useViewportMatch( 'medium' );\n * ```\n *\n * @return {boolean} Whether viewport matches query.\n */\nconst useViewportMatch = ( breakpoint, operator = '>=', view = window ) => {\n\tconst simulatedWidth = useContext( ViewportMatchWidthContext );\n\tconst mediaQuery =\n\t\t! simulatedWidth &&\n\t\t`(${ CONDITIONS[ operator ] }: ${ BREAKPOINTS[ breakpoint ] }px)`;\n\tconst mediaQueryResult = useMediaQuery( mediaQuery || undefined, view );\n\tif ( simulatedWidth ) {\n\t\treturn OPERATOR_EVALUATORS[ operator ](\n\t\t\tBREAKPOINTS[ breakpoint ],\n\t\t\tsimulatedWidth\n\t\t);\n\t}\n\treturn mediaQueryResult;\n};\n\nuseViewportMatch.__experimentalWidthProvider =\n\tViewportMatchWidthContext.Provider;\n\nexport default useViewportMatch;\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAGA,qBAA0C;AAK1C,6BAA0B;AAa1B,IAAM,cAAc;AAAA,EACnB,OAAO;AAAA,EACP,MAAM;AAAA,EACN,MAAM;AAAA,EACN,QAAQ;AAAA,EACR,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,OAAO;AAAA,EACP,QAAQ;AACT;AAWA,IAAM,aAAa;AAAA,EAClB,MAAM;AAAA,EACN,KAAK;AACN;AAOA,IAAM,sBAAsB;AAAA,EAC3B,MAAM,CAAE,iBAAiB,UAAW,SAAS;AAAA,EAC7C,KAAK,CAAE,iBAAiB,UAAW,QAAQ;AAC5C;AAEA,IAAM,gCAA4B;AAAA;AAAA,EACF;AAChC;AACA,0BAA0B,cAAc;AAkBxC,IAAM,mBAAmB,CAAE,YAAY,WAAW,MAAM,OAAO,WAAY;AAC1E,QAAM,qBAAiB,2BAAY,yBAA0B;AAC7D,QAAM,aACL,CAAE,kBACF,IAAK,WAAY,QAAS,CAAE,KAAM,YAAa,UAAW,CAAE;AAC7D,QAAM,uBAAmB,uBAAAA,SAAe,cAAc,QAAW,IAAK;AACtE,MAAK,gBAAiB;AACrB,WAAO,oBAAqB,QAAS;AAAA,MACpC,YAAa,UAAW;AAAA,MACxB;AAAA,IACD;AAAA,EACD;AACA,SAAO;AACR;AAEA,iBAAiB,8BAChB,0BAA0B;AAE3B,IAAO,6BAAQ;",
4
+ "sourcesContent": ["/**\n * WordPress dependencies\n */\nimport { createContext, useContext } from '@wordpress/element';\n\n/**\n * Internal dependencies\n */\nimport useMediaQuery from '../use-media-query';\n\n/**\n * @typedef {\"xhuge\" | \"huge\" | \"wide\" | \"xlarge\" | \"large\" | \"medium\" | \"small\" | \"mobile\"} WPBreakpoint\n */\n\n/**\n * Hash of breakpoint names with pixel width at which it becomes effective.\n *\n * @see _breakpoints.scss\n *\n * @type {Record<WPBreakpoint, number>}\n */\nconst BREAKPOINTS = {\n\txhuge: 1920,\n\thuge: 1440,\n\twide: 1280,\n\txlarge: 1080,\n\tlarge: 960,\n\tmedium: 782,\n\tsmall: 600,\n\tmobile: 480,\n};\n\n/**\n * @typedef {\">=\" | \"<\"} WPViewportOperator\n */\n\n/**\n * Object mapping media query operators to the condition to be used.\n *\n * @type {Record<WPViewportOperator, string>}\n */\nconst CONDITIONS = {\n\t'>=': 'min-width',\n\t'<': 'max-width',\n};\n\n/**\n * Object mapping media query operators to a function that given a breakpointValue and a width evaluates if the operator matches the values.\n *\n * @type {Record<WPViewportOperator, (breakpointValue: number, width: number) => boolean>}\n */\nconst OPERATOR_EVALUATORS = {\n\t'>=': ( breakpointValue, width ) => width >= breakpointValue,\n\t'<': ( breakpointValue, width ) => width < breakpointValue,\n};\n\nconst ViewportMatchWidthContext = createContext(\n\t/** @type {null | number} */ ( null )\n);\nViewportMatchWidthContext.displayName = 'ViewportMatchWidthContext';\n\n/**\n * Returns true if the viewport matches the given query, or false otherwise.\n *\n * @param {WPBreakpoint} breakpoint Breakpoint size name.\n * @param {WPViewportOperator} [operator=\">=\"] Viewport operator.\n * @param {Window|undefined} [view=window] Window instance in which to perform viewport matching.\n *\n * @example\n *\n * ```js\n * useViewportMatch( 'huge', '<' );\n * useViewportMatch( 'medium' );\n * ```\n *\n * @return {boolean} Whether viewport matches query.\n */\nconst useViewportMatch = (\n\tbreakpoint,\n\toperator = '>=',\n\t// Resolve the default lazily so SSR (where `window` is undeclared) does not\n\t// throw a ReferenceError when this default expression is evaluated.\n\tview = typeof window !== 'undefined' ? window : undefined\n) => {\n\tconst simulatedWidth = useContext( ViewportMatchWidthContext );\n\tconst mediaQuery =\n\t\t! simulatedWidth &&\n\t\t`(${ CONDITIONS[ operator ] }: ${ BREAKPOINTS[ breakpoint ] }px)`;\n\tconst mediaQueryResult = useMediaQuery( mediaQuery || undefined, view );\n\tif ( simulatedWidth ) {\n\t\treturn OPERATOR_EVALUATORS[ operator ](\n\t\t\tBREAKPOINTS[ breakpoint ],\n\t\t\tsimulatedWidth\n\t\t);\n\t}\n\treturn mediaQueryResult;\n};\n\nuseViewportMatch.__experimentalWidthProvider =\n\tViewportMatchWidthContext.Provider;\n\nexport default useViewportMatch;\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAGA,qBAA0C;AAK1C,6BAA0B;AAa1B,IAAM,cAAc;AAAA,EACnB,OAAO;AAAA,EACP,MAAM;AAAA,EACN,MAAM;AAAA,EACN,QAAQ;AAAA,EACR,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,OAAO;AAAA,EACP,QAAQ;AACT;AAWA,IAAM,aAAa;AAAA,EAClB,MAAM;AAAA,EACN,KAAK;AACN;AAOA,IAAM,sBAAsB;AAAA,EAC3B,MAAM,CAAE,iBAAiB,UAAW,SAAS;AAAA,EAC7C,KAAK,CAAE,iBAAiB,UAAW,QAAQ;AAC5C;AAEA,IAAM,gCAA4B;AAAA;AAAA,EACF;AAChC;AACA,0BAA0B,cAAc;AAkBxC,IAAM,mBAAmB,CACxB,YACA,WAAW,MAGX,OAAO,OAAO,WAAW,cAAc,SAAS,WAC5C;AACJ,QAAM,qBAAiB,2BAAY,yBAA0B;AAC7D,QAAM,aACL,CAAE,kBACF,IAAK,WAAY,QAAS,CAAE,KAAM,YAAa,UAAW,CAAE;AAC7D,QAAM,uBAAmB,uBAAAA,SAAe,cAAc,QAAW,IAAK;AACtE,MAAK,gBAAiB;AACrB,WAAO,oBAAqB,QAAS;AAAA,MACpC,YAAa,UAAW;AAAA,MACxB;AAAA,IACD;AAAA,EACD;AACA,SAAO;AACR;AAEA,iBAAiB,8BAChB,0BAA0B;AAE3B,IAAO,6BAAQ;",
6
6
  "names": ["useMediaQuery"]
7
7
  }
@@ -1,9 +1,14 @@
1
1
  // packages/compose/src/higher-order/pure/index.tsx
2
2
  import { isShallowEqual } from "@wordpress/is-shallow-equal";
3
3
  import { Component } from "@wordpress/element";
4
+ import deprecated from "@wordpress/deprecated";
4
5
  import { createHigherOrderComponent } from "../../utils/create-higher-order-component/index.mjs";
5
6
  import { jsx } from "react/jsx-runtime";
6
7
  var pure = createHigherOrderComponent(function(WrappedComponent) {
8
+ deprecated("wp.compose.pure", {
9
+ since: "7.1",
10
+ alternative: "Use `memo` or `PureComponent` instead"
11
+ });
7
12
  if (WrappedComponent.prototype instanceof Component) {
8
13
  return class extends WrappedComponent {
9
14
  shouldComponentUpdate(nextProps, nextState) {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/higher-order/pure/index.tsx"],
4
- "sourcesContent": ["/**\n * External dependencies\n */\nimport type { ComponentType, ComponentClass } from 'react';\n\n/**\n * WordPress dependencies\n */\nimport { isShallowEqual } from '@wordpress/is-shallow-equal';\nimport { Component } from '@wordpress/element';\n\n/**\n * Internal dependencies\n */\nimport { createHigherOrderComponent } from '../../utils/create-higher-order-component';\n\n/**\n * Given a component returns the enhanced component augmented with a component\n * only re-rendering when its props/state change\n *\n * @deprecated Use `memo` or `PureComponent` instead.\n */\nconst pure = createHigherOrderComponent( function < Props extends {} >(\n\tWrappedComponent: ComponentType< Props >\n): ComponentType< Props > {\n\tif ( WrappedComponent.prototype instanceof Component ) {\n\t\treturn class extends ( WrappedComponent as ComponentClass< Props > ) {\n\t\t\tshouldComponentUpdate( nextProps: Props, nextState: any ) {\n\t\t\t\treturn (\n\t\t\t\t\t! isShallowEqual( nextProps, this.props ) ||\n\t\t\t\t\t! isShallowEqual( nextState, this.state )\n\t\t\t\t);\n\t\t\t}\n\t\t};\n\t}\n\n\treturn class extends Component< Props > {\n\t\tshouldComponentUpdate( nextProps: Props ) {\n\t\t\treturn ! isShallowEqual( nextProps, this.props );\n\t\t}\n\n\t\trender() {\n\t\t\treturn <WrappedComponent { ...this.props } />;\n\t\t}\n\t};\n}, 'pure' );\n\nexport default pure;\n"],
5
- "mappings": ";AAQA,SAAS,sBAAsB;AAC/B,SAAS,iBAAiB;AAK1B,SAAS,kCAAkC;AA4BjC;AApBV,IAAM,OAAO,2BAA4B,SACxC,kBACyB;AACzB,MAAK,iBAAiB,qBAAqB,WAAY;AACtD,WAAO,cAAgB,iBAA8C;AAAA,MACpE,sBAAuB,WAAkB,WAAiB;AACzD,eACC,CAAE,eAAgB,WAAW,KAAK,KAAM,KACxC,CAAE,eAAgB,WAAW,KAAK,KAAM;AAAA,MAE1C;AAAA,IACD;AAAA,EACD;AAEA,SAAO,cAAc,UAAmB;AAAA,IACvC,sBAAuB,WAAmB;AACzC,aAAO,CAAE,eAAgB,WAAW,KAAK,KAAM;AAAA,IAChD;AAAA,IAEA,SAAS;AACR,aAAO,oBAAC,oBAAmB,GAAG,KAAK,OAAQ;AAAA,IAC5C;AAAA,EACD;AACD,GAAG,MAAO;AAEV,IAAO,eAAQ;",
4
+ "sourcesContent": ["/**\n * External dependencies\n */\nimport type { ComponentType, ComponentClass } from 'react';\n\n/**\n * WordPress dependencies\n */\nimport { isShallowEqual } from '@wordpress/is-shallow-equal';\nimport { Component } from '@wordpress/element';\nimport deprecated from '@wordpress/deprecated';\n\n/**\n * Internal dependencies\n */\nimport { createHigherOrderComponent } from '../../utils/create-higher-order-component';\n\n/**\n * Given a component returns the enhanced component augmented with a component\n * only re-rendering when its props/state change\n *\n * @deprecated Use `memo` or `PureComponent` instead.\n */\nconst pure = createHigherOrderComponent( function < Props extends {} >(\n\tWrappedComponent: ComponentType< Props >\n): ComponentType< Props > {\n\tdeprecated( 'wp.compose.pure', {\n\t\tsince: '7.1',\n\t\talternative: 'Use `memo` or `PureComponent` instead',\n\t} );\n\n\tif ( WrappedComponent.prototype instanceof Component ) {\n\t\treturn class extends ( WrappedComponent as ComponentClass< Props > ) {\n\t\t\tshouldComponentUpdate( nextProps: Props, nextState: any ) {\n\t\t\t\treturn (\n\t\t\t\t\t! isShallowEqual( nextProps, this.props ) ||\n\t\t\t\t\t! isShallowEqual( nextState, this.state )\n\t\t\t\t);\n\t\t\t}\n\t\t};\n\t}\n\n\treturn class extends Component< Props > {\n\t\tshouldComponentUpdate( nextProps: Props ) {\n\t\t\treturn ! isShallowEqual( nextProps, this.props );\n\t\t}\n\n\t\trender() {\n\t\t\treturn <WrappedComponent { ...this.props } />;\n\t\t}\n\t};\n}, 'pure' );\n\nexport default pure;\n"],
5
+ "mappings": ";AAQA,SAAS,sBAAsB;AAC/B,SAAS,iBAAiB;AAC1B,OAAO,gBAAgB;AAKvB,SAAS,kCAAkC;AAiCjC;AAzBV,IAAM,OAAO,2BAA4B,SACxC,kBACyB;AACzB,aAAY,mBAAmB;AAAA,IAC9B,OAAO;AAAA,IACP,aAAa;AAAA,EACd,CAAE;AAEF,MAAK,iBAAiB,qBAAqB,WAAY;AACtD,WAAO,cAAgB,iBAA8C;AAAA,MACpE,sBAAuB,WAAkB,WAAiB;AACzD,eACC,CAAE,eAAgB,WAAW,KAAK,KAAM,KACxC,CAAE,eAAgB,WAAW,KAAK,KAAM;AAAA,MAE1C;AAAA,IACD;AAAA,EACD;AAEA,SAAO,cAAc,UAAmB;AAAA,IACvC,sBAAuB,WAAmB;AACzC,aAAO,CAAE,eAAgB,WAAW,KAAK,KAAM;AAAA,IAChD;AAAA,IAEA,SAAS;AACR,aAAO,oBAAC,oBAAmB,GAAG,KAAK,OAAQ;AAAA,IAC5C;AAAA,EACD;AACD,GAAG,MAAO;AAEV,IAAO,eAAQ;",
6
6
  "names": []
7
7
  }
@@ -7,7 +7,7 @@ var EMPTY_SUBSCRIBER = {
7
7
  getValue: () => false
8
8
  };
9
9
  function getMQLSubscriber(view, query) {
10
- if (!query || typeof view?.matchMedia !== "function") {
10
+ if (!view || !query || typeof view.matchMedia !== "function") {
11
11
  return EMPTY_SUBSCRIBER;
12
12
  }
13
13
  let queryCache = perWindowCache.get(view);
@@ -46,7 +46,7 @@ function getMQLSubscriber(view, query) {
46
46
  queryCache.set(query, subscriber);
47
47
  return subscriber;
48
48
  }
49
- function useMediaQuery(query, view = window) {
49
+ function useMediaQuery(query, view = typeof window !== "undefined" ? window : void 0) {
50
50
  const source = getMQLSubscriber(view, query);
51
51
  return useSyncExternalStore(
52
52
  source.subscribe,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/hooks/use-media-query/index.ts"],
4
- "sourcesContent": ["/**\n * WordPress dependencies\n */\nimport { useSyncExternalStore } from '@wordpress/element';\n\ntype MQLSubscriber = {\n\tsubscribe: ( onStoreChange: () => void ) => () => void;\n\tgetValue: () => boolean;\n};\n\n// One subscriber per (window, query). The underlying MediaQueryList lives\n// inside the subscriber's closure; a single `change` listener fans out to\n// every React consumer via an in-JS `Set` to avoid the per-consumer\n// `addEventListener` cost (~85 ms during a large-post editor mount).\nconst perWindowCache = new WeakMap< Window, Map< string, MQLSubscriber > >();\n\nconst EMPTY_SUBSCRIBER: MQLSubscriber = {\n\tsubscribe: () => () => {},\n\tgetValue: () => false,\n};\n\nfunction getMQLSubscriber( view: Window, query?: string ): MQLSubscriber {\n\tif ( ! query || typeof view?.matchMedia !== 'function' ) {\n\t\treturn EMPTY_SUBSCRIBER;\n\t}\n\n\tlet queryCache = perWindowCache.get( view );\n\tif ( ! queryCache ) {\n\t\tqueryCache = new Map();\n\t\tperWindowCache.set( view, queryCache );\n\t}\n\n\tconst cached = queryCache.get( query );\n\tif ( cached ) {\n\t\treturn cached;\n\t}\n\n\tconst mediaQueryList = view.matchMedia( query );\n\tconst listeners = new Set< () => void >();\n\tconst notify = () => {\n\t\tfor ( const listener of listeners ) {\n\t\t\tlistener();\n\t\t}\n\t};\n\n\tconst subscriber: MQLSubscriber = {\n\t\tsubscribe( onStoreChange ) {\n\t\t\tif ( listeners.size === 0 ) {\n\t\t\t\t// Avoid a fatal error when browsers don't support `addEventListener` on MediaQueryList.\n\t\t\t\tmediaQueryList.addEventListener?.( 'change', notify );\n\t\t\t}\n\t\t\tlisteners.add( onStoreChange );\n\t\t\treturn () => {\n\t\t\t\tlisteners.delete( onStoreChange );\n\t\t\t\tif ( listeners.size === 0 ) {\n\t\t\t\t\tmediaQueryList.removeEventListener?.( 'change', notify );\n\t\t\t\t}\n\t\t\t};\n\t\t},\n\t\tgetValue() {\n\t\t\treturn mediaQueryList.matches;\n\t\t},\n\t};\n\n\tqueryCache.set( query, subscriber );\n\treturn subscriber;\n}\n\n/**\n * Runs a media query and returns its value when it changes.\n *\n * @param [query] Media Query.\n * @param [view] Window instance, else default to global window\n * @return return value of the media query.\n */\nexport default function useMediaQuery(\n\tquery?: string,\n\tview: Window = window\n): boolean {\n\tconst source = getMQLSubscriber( view, query );\n\n\treturn useSyncExternalStore(\n\t\tsource.subscribe,\n\t\tsource.getValue,\n\t\t() => false\n\t);\n}\n"],
5
- "mappings": ";AAGA,SAAS,4BAA4B;AAWrC,IAAM,iBAAiB,oBAAI,QAAgD;AAE3E,IAAM,mBAAkC;AAAA,EACvC,WAAW,MAAM,MAAM;AAAA,EAAC;AAAA,EACxB,UAAU,MAAM;AACjB;AAEA,SAAS,iBAAkB,MAAc,OAAgC;AACxE,MAAK,CAAE,SAAS,OAAO,MAAM,eAAe,YAAa;AACxD,WAAO;AAAA,EACR;AAEA,MAAI,aAAa,eAAe,IAAK,IAAK;AAC1C,MAAK,CAAE,YAAa;AACnB,iBAAa,oBAAI,IAAI;AACrB,mBAAe,IAAK,MAAM,UAAW;AAAA,EACtC;AAEA,QAAM,SAAS,WAAW,IAAK,KAAM;AACrC,MAAK,QAAS;AACb,WAAO;AAAA,EACR;AAEA,QAAM,iBAAiB,KAAK,WAAY,KAAM;AAC9C,QAAM,YAAY,oBAAI,IAAkB;AACxC,QAAM,SAAS,MAAM;AACpB,eAAY,YAAY,WAAY;AACnC,eAAS;AAAA,IACV;AAAA,EACD;AAEA,QAAM,aAA4B;AAAA,IACjC,UAAW,eAAgB;AAC1B,UAAK,UAAU,SAAS,GAAI;AAE3B,uBAAe,mBAAoB,UAAU,MAAO;AAAA,MACrD;AACA,gBAAU,IAAK,aAAc;AAC7B,aAAO,MAAM;AACZ,kBAAU,OAAQ,aAAc;AAChC,YAAK,UAAU,SAAS,GAAI;AAC3B,yBAAe,sBAAuB,UAAU,MAAO;AAAA,QACxD;AAAA,MACD;AAAA,IACD;AAAA,IACA,WAAW;AACV,aAAO,eAAe;AAAA,IACvB;AAAA,EACD;AAEA,aAAW,IAAK,OAAO,UAAW;AAClC,SAAO;AACR;AASe,SAAR,cACN,OACA,OAAe,QACL;AACV,QAAM,SAAS,iBAAkB,MAAM,KAAM;AAE7C,SAAO;AAAA,IACN,OAAO;AAAA,IACP,OAAO;AAAA,IACP,MAAM;AAAA,EACP;AACD;",
4
+ "sourcesContent": ["/**\n * WordPress dependencies\n */\nimport { useSyncExternalStore } from '@wordpress/element';\n\ntype MQLSubscriber = {\n\tsubscribe: ( onStoreChange: () => void ) => () => void;\n\tgetValue: () => boolean;\n};\n\n// One subscriber per (window, query). The underlying MediaQueryList lives\n// inside the subscriber's closure; a single `change` listener fans out to\n// every React consumer via an in-JS `Set` to avoid the per-consumer\n// `addEventListener` cost (~85 ms during a large-post editor mount).\nconst perWindowCache = new WeakMap< Window, Map< string, MQLSubscriber > >();\n\nconst EMPTY_SUBSCRIBER: MQLSubscriber = {\n\tsubscribe: () => () => {},\n\tgetValue: () => false,\n};\n\nfunction getMQLSubscriber(\n\tview: Window | undefined,\n\tquery?: string\n): MQLSubscriber {\n\tif ( ! view || ! query || typeof view.matchMedia !== 'function' ) {\n\t\treturn EMPTY_SUBSCRIBER;\n\t}\n\n\tlet queryCache = perWindowCache.get( view );\n\tif ( ! queryCache ) {\n\t\tqueryCache = new Map();\n\t\tperWindowCache.set( view, queryCache );\n\t}\n\n\tconst cached = queryCache.get( query );\n\tif ( cached ) {\n\t\treturn cached;\n\t}\n\n\tconst mediaQueryList = view.matchMedia( query );\n\tconst listeners = new Set< () => void >();\n\tconst notify = () => {\n\t\tfor ( const listener of listeners ) {\n\t\t\tlistener();\n\t\t}\n\t};\n\n\tconst subscriber: MQLSubscriber = {\n\t\tsubscribe( onStoreChange ) {\n\t\t\tif ( listeners.size === 0 ) {\n\t\t\t\t// Avoid a fatal error when browsers don't support `addEventListener` on MediaQueryList.\n\t\t\t\tmediaQueryList.addEventListener?.( 'change', notify );\n\t\t\t}\n\t\t\tlisteners.add( onStoreChange );\n\t\t\treturn () => {\n\t\t\t\tlisteners.delete( onStoreChange );\n\t\t\t\tif ( listeners.size === 0 ) {\n\t\t\t\t\tmediaQueryList.removeEventListener?.( 'change', notify );\n\t\t\t\t}\n\t\t\t};\n\t\t},\n\t\tgetValue() {\n\t\t\treturn mediaQueryList.matches;\n\t\t},\n\t};\n\n\tqueryCache.set( query, subscriber );\n\treturn subscriber;\n}\n\n/**\n * Runs a media query and returns its value when it changes.\n *\n * @param [query] Media Query.\n * @param [view] Window instance, else default to global window\n * @return return value of the media query.\n */\nexport default function useMediaQuery(\n\tquery?: string,\n\t// Resolve the default lazily so SSR (where `window` is undeclared) does not\n\t// throw a ReferenceError when this default expression is evaluated.\n\tview: Window | undefined = typeof window !== 'undefined'\n\t\t? window\n\t\t: undefined\n): boolean {\n\tconst source = getMQLSubscriber( view, query );\n\n\treturn useSyncExternalStore(\n\t\tsource.subscribe,\n\t\tsource.getValue,\n\t\t() => false\n\t);\n}\n"],
5
+ "mappings": ";AAGA,SAAS,4BAA4B;AAWrC,IAAM,iBAAiB,oBAAI,QAAgD;AAE3E,IAAM,mBAAkC;AAAA,EACvC,WAAW,MAAM,MAAM;AAAA,EAAC;AAAA,EACxB,UAAU,MAAM;AACjB;AAEA,SAAS,iBACR,MACA,OACgB;AAChB,MAAK,CAAE,QAAQ,CAAE,SAAS,OAAO,KAAK,eAAe,YAAa;AACjE,WAAO;AAAA,EACR;AAEA,MAAI,aAAa,eAAe,IAAK,IAAK;AAC1C,MAAK,CAAE,YAAa;AACnB,iBAAa,oBAAI,IAAI;AACrB,mBAAe,IAAK,MAAM,UAAW;AAAA,EACtC;AAEA,QAAM,SAAS,WAAW,IAAK,KAAM;AACrC,MAAK,QAAS;AACb,WAAO;AAAA,EACR;AAEA,QAAM,iBAAiB,KAAK,WAAY,KAAM;AAC9C,QAAM,YAAY,oBAAI,IAAkB;AACxC,QAAM,SAAS,MAAM;AACpB,eAAY,YAAY,WAAY;AACnC,eAAS;AAAA,IACV;AAAA,EACD;AAEA,QAAM,aAA4B;AAAA,IACjC,UAAW,eAAgB;AAC1B,UAAK,UAAU,SAAS,GAAI;AAE3B,uBAAe,mBAAoB,UAAU,MAAO;AAAA,MACrD;AACA,gBAAU,IAAK,aAAc;AAC7B,aAAO,MAAM;AACZ,kBAAU,OAAQ,aAAc;AAChC,YAAK,UAAU,SAAS,GAAI;AAC3B,yBAAe,sBAAuB,UAAU,MAAO;AAAA,QACxD;AAAA,MACD;AAAA,IACD;AAAA,IACA,WAAW;AACV,aAAO,eAAe;AAAA,IACvB;AAAA,EACD;AAEA,aAAW,IAAK,OAAO,UAAW;AAClC,SAAO;AACR;AASe,SAAR,cACN,OAGA,OAA2B,OAAO,WAAW,cAC1C,SACA,QACO;AACV,QAAM,SAAS,iBAAkB,MAAM,KAAM;AAE7C,SAAO;AAAA,IACN,OAAO;AAAA,IACP,OAAO;AAAA,IACP,MAAM;AAAA,EACP;AACD;",
6
6
  "names": []
7
7
  }
@@ -2,25 +2,40 @@
2
2
  import { useRef, useCallback, useLayoutEffect } from "@wordpress/element";
3
3
  function assignRef(ref, value) {
4
4
  if (typeof ref === "function") {
5
- ref(value);
5
+ const returned = ref(value);
6
+ return typeof returned === "function" ? returned : void 0;
6
7
  } else if (ref && ref.hasOwnProperty("current")) {
7
8
  ref.current = value;
8
9
  }
10
+ return void 0;
11
+ }
12
+ function detachRef(ref, index, cleanups) {
13
+ const cleanup = cleanups[index];
14
+ if (cleanup) {
15
+ cleanups[index] = void 0;
16
+ cleanup();
17
+ } else {
18
+ assignRef(ref, null);
19
+ }
9
20
  }
10
21
  function useMergeRefs(refs) {
11
- const element = useRef(null);
22
+ const elementRef = useRef(null);
12
23
  const isAttachedRef = useRef(false);
13
24
  const didElementChangeRef = useRef(false);
14
25
  const previousRefsRef = useRef([]);
15
26
  const currentRefsRef = useRef(refs);
27
+ const cleanupsRef = useRef([]);
16
28
  currentRefsRef.current = refs;
17
29
  useLayoutEffect(() => {
18
30
  if (didElementChangeRef.current === false && isAttachedRef.current === true) {
19
31
  refs.forEach((ref, index) => {
20
32
  const previousRef = previousRefsRef.current[index];
21
33
  if (ref !== previousRef) {
22
- assignRef(previousRef, null);
23
- assignRef(ref, element.current);
34
+ detachRef(previousRef, index, cleanupsRef.current);
35
+ cleanupsRef.current[index] = assignRef(
36
+ ref,
37
+ elementRef.current
38
+ );
24
39
  }
25
40
  });
26
41
  }
@@ -30,12 +45,17 @@ function useMergeRefs(refs) {
30
45
  didElementChangeRef.current = false;
31
46
  });
32
47
  return useCallback((value) => {
33
- assignRef(element, value);
48
+ elementRef.current = value;
34
49
  didElementChangeRef.current = true;
35
50
  isAttachedRef.current = value !== null;
36
- const refsToAssign = value ? currentRefsRef.current : previousRefsRef.current;
37
- for (const ref of refsToAssign) {
38
- assignRef(ref, value);
51
+ if (value === null) {
52
+ previousRefsRef.current.forEach((ref, index) => {
53
+ detachRef(ref, index, cleanupsRef.current);
54
+ });
55
+ } else {
56
+ currentRefsRef.current.forEach((ref, index) => {
57
+ cleanupsRef.current[index] = assignRef(ref, value);
58
+ });
39
59
  }
40
60
  }, []);
41
61
  }
@@ -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\nfunction assignRef< T >( ref: Ref< T >, value: T ) {\n\tif ( typeof ref === 'function' ) {\n\t\tref( value );\n\t} else if ( ref && ref.hasOwnProperty( 'current' ) ) {\n\t\t( ref as MutableRefObject< T > ).current = value;\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 * To make ref callbacks easier to use, you can also pass the result of\n * `useRefEffect`, which makes cleanup easier by allowing you to return a\n * cleanup function instead of handling `null`.\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 = useRefEffect( ( 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 element = useRef( null );\n\tconst isAttachedRef = useRef( false );\n\tconst didElementChangeRef = useRef( false );\n\tconst previousRefsRef = useRef< Ref< T >[] >( [] );\n\tconst currentRefsRef = useRef( refs );\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 previous ref with `null` and the new\n\t// ref with the node, except when the element changes in the same cycle, in\n\t// which case the ref callbacks will already have been called.\n\tuseLayoutEffect( () => {\n\t\tif (\n\t\t\tdidElementChangeRef.current === false &&\n\t\t\tisAttachedRef.current === true\n\t\t) {\n\t\t\trefs.forEach( ( ref, index ) => {\n\t\t\t\tconst previousRef = previousRefsRef.current[ index ];\n\t\t\t\tif ( ref !== previousRef ) {\n\t\t\t\t\tassignRef( previousRef, null );\n\t\t\t\t\tassignRef( ref, element.current );\n\t\t\t\t}\n\t\t\t} );\n\t\t}\n\n\t\tpreviousRefsRef.current = refs;\n\t}, refs );\n\n\t// No dependencies, must be reset after every render so ref callbacks are\n\t// correctly called after a ref change.\n\tuseLayoutEffect( () => {\n\t\tdidElementChangeRef.current = false;\n\t} );\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\tassignRef( element, value );\n\n\t\tdidElementChangeRef.current = true;\n\t\tisAttachedRef.current = value !== null;\n\n\t\t// When an element changes, the current ref callback should be called\n\t\t// with the new element and the previous one with `null`.\n\t\tconst refsToAssign = value\n\t\t\t? currentRefsRef.current\n\t\t\t: previousRefsRef.current;\n\n\t\t// Update the latest refs.\n\t\tfor ( const ref of refsToAssign ) {\n\t\t\tassignRef( ref, value );\n\t\t}\n\t}, [] );\n}\n"],
5
- "mappings": ";AAGA,SAAS,QAAQ,aAAa,uBAAuB;AAGrD,SAAS,UAAgB,KAAe,OAAW;AAClD,MAAK,OAAO,QAAQ,YAAa;AAChC,QAAK,KAAM;AAAA,EACZ,WAAY,OAAO,IAAI,eAAgB,SAAU,GAAI;AACpD,IAAE,IAA+B,UAAU;AAAA,EAC5C;AACD;AA2Ce,SAAR,aACN,MACmB;AACnB,QAAM,UAAU,OAAQ,IAAK;AAC7B,QAAM,gBAAgB,OAAQ,KAAM;AACpC,QAAM,sBAAsB,OAAQ,KAAM;AAC1C,QAAM,kBAAkB,OAAsB,CAAC,CAAE;AACjD,QAAM,iBAAiB,OAAQ,IAAK;AAIpC,iBAAe,UAAU;AAKzB,kBAAiB,MAAM;AACtB,QACC,oBAAoB,YAAY,SAChC,cAAc,YAAY,MACzB;AACD,WAAK,QAAS,CAAE,KAAK,UAAW;AAC/B,cAAM,cAAc,gBAAgB,QAAS,KAAM;AACnD,YAAK,QAAQ,aAAc;AAC1B,oBAAW,aAAa,IAAK;AAC7B,oBAAW,KAAK,QAAQ,OAAQ;AAAA,QACjC;AAAA,MACD,CAAE;AAAA,IACH;AAEA,oBAAgB,UAAU;AAAA,EAC3B,GAAG,IAAK;AAIR,kBAAiB,MAAM;AACtB,wBAAoB,UAAU;AAAA,EAC/B,CAAE;AAIF,SAAO,YAAa,CAAE,UAAqB;AAG1C,cAAW,SAAS,KAAM;AAE1B,wBAAoB,UAAU;AAC9B,kBAAc,UAAU,UAAU;AAIlC,UAAM,eAAe,QAClB,eAAe,UACf,gBAAgB;AAGnB,eAAY,OAAO,cAAe;AACjC,gBAAW,KAAK,KAAM;AAAA,IACvB;AAAA,EACD,GAAG,CAAC,CAAE;AACP;",
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\tconst isAttachedRef = useRef( false );\n\tconst didElementChangeRef = useRef( false );\n\tconst previousRefsRef = 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 previous ref with `null` and the new\n\t// ref with the node, except when the element changes in the same cycle, in\n\t// which case the ref callbacks will already have been called.\n\tuseLayoutEffect( () => {\n\t\tif (\n\t\t\tdidElementChangeRef.current === false &&\n\t\t\tisAttachedRef.current === true\n\t\t) {\n\t\t\trefs.forEach( ( ref, index ) => {\n\t\t\t\tconst previousRef = previousRefsRef.current[ index ];\n\t\t\t\tif ( ref !== previousRef ) {\n\t\t\t\t\tdetachRef( previousRef, index, cleanupsRef.current );\n\t\t\t\t\tcleanupsRef.current[ index ] = assignRef(\n\t\t\t\t\t\tref,\n\t\t\t\t\t\telementRef.current as T\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t} );\n\t\t}\n\n\t\tpreviousRefsRef.current = refs;\n\t}, refs );\n\n\t// No dependencies, must be reset after every render so ref callbacks are\n\t// correctly called after a ref change.\n\tuseLayoutEffect( () => {\n\t\tdidElementChangeRef.current = false;\n\t} );\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\tdidElementChangeRef.current = true;\n\t\tisAttachedRef.current = value !== null;\n\n\t\t// When an element changes, the current ref callback should be called\n\t\t// with the new element and the previous one with `null`.\n\t\tif ( value === null ) {\n\t\t\tpreviousRefsRef.current.forEach( ( ref, index ) => {\n\t\t\t\tdetachRef( ref, index, cleanupsRef.current );\n\t\t\t} );\n\t\t} else {\n\t\t\tcurrentRefsRef.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;AAC5C,QAAM,gBAAgB,OAAQ,KAAM;AACpC,QAAM,sBAAsB,OAAQ,KAAM;AAC1C,QAAM,kBAAkB,OAAsB,CAAC,CAAE;AACjD,QAAM,iBAAiB,OAAQ,IAAK;AAIpC,QAAM,cAAc,OAA+C,CAAC,CAAE;AAItE,iBAAe,UAAU;AAKzB,kBAAiB,MAAM;AACtB,QACC,oBAAoB,YAAY,SAChC,cAAc,YAAY,MACzB;AACD,WAAK,QAAS,CAAE,KAAK,UAAW;AAC/B,cAAM,cAAc,gBAAgB,QAAS,KAAM;AACnD,YAAK,QAAQ,aAAc;AAC1B,oBAAW,aAAa,OAAO,YAAY,OAAQ;AACnD,sBAAY,QAAS,KAAM,IAAI;AAAA,YAC9B;AAAA,YACA,WAAW;AAAA,UACZ;AAAA,QACD;AAAA,MACD,CAAE;AAAA,IACH;AAEA,oBAAgB,UAAU;AAAA,EAC3B,GAAG,IAAK;AAIR,kBAAiB,MAAM;AACtB,wBAAoB,UAAU;AAAA,EAC/B,CAAE;AAIF,SAAO,YAAa,CAAE,UAAqB;AAG1C,eAAW,UAAU;AAErB,wBAAoB,UAAU;AAC9B,kBAAc,UAAU,UAAU;AAIlC,QAAK,UAAU,MAAO;AACrB,sBAAgB,QAAQ,QAAS,CAAE,KAAK,UAAW;AAClD,kBAAW,KAAK,OAAO,YAAY,OAAQ;AAAA,MAC5C,CAAE;AAAA,IACH,OAAO;AACN,qBAAe,QAAQ,QAAS,CAAE,KAAK,UAAW;AACjD,oBAAY,QAAS,KAAM,IAAI,UAAW,KAAK,KAAM;AAAA,MACtD,CAAE;AAAA,IACH;AAAA,EACD,GAAG,CAAC,CAAE;AACP;",
6
6
  "names": []
7
7
  }
@@ -24,7 +24,7 @@ var ViewportMatchWidthContext = createContext(
24
24
  null
25
25
  );
26
26
  ViewportMatchWidthContext.displayName = "ViewportMatchWidthContext";
27
- var useViewportMatch = (breakpoint, operator = ">=", view = window) => {
27
+ var useViewportMatch = (breakpoint, operator = ">=", view = typeof window !== "undefined" ? window : void 0) => {
28
28
  const simulatedWidth = useContext(ViewportMatchWidthContext);
29
29
  const mediaQuery = !simulatedWidth && `(${CONDITIONS[operator]}: ${BREAKPOINTS[breakpoint]}px)`;
30
30
  const mediaQueryResult = useMediaQuery(mediaQuery || void 0, view);
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/hooks/use-viewport-match/index.js"],
4
- "sourcesContent": ["/**\n * WordPress dependencies\n */\nimport { createContext, useContext } from '@wordpress/element';\n\n/**\n * Internal dependencies\n */\nimport useMediaQuery from '../use-media-query';\n\n/**\n * @typedef {\"xhuge\" | \"huge\" | \"wide\" | \"xlarge\" | \"large\" | \"medium\" | \"small\" | \"mobile\"} WPBreakpoint\n */\n\n/**\n * Hash of breakpoint names with pixel width at which it becomes effective.\n *\n * @see _breakpoints.scss\n *\n * @type {Record<WPBreakpoint, number>}\n */\nconst BREAKPOINTS = {\n\txhuge: 1920,\n\thuge: 1440,\n\twide: 1280,\n\txlarge: 1080,\n\tlarge: 960,\n\tmedium: 782,\n\tsmall: 600,\n\tmobile: 480,\n};\n\n/**\n * @typedef {\">=\" | \"<\"} WPViewportOperator\n */\n\n/**\n * Object mapping media query operators to the condition to be used.\n *\n * @type {Record<WPViewportOperator, string>}\n */\nconst CONDITIONS = {\n\t'>=': 'min-width',\n\t'<': 'max-width',\n};\n\n/**\n * Object mapping media query operators to a function that given a breakpointValue and a width evaluates if the operator matches the values.\n *\n * @type {Record<WPViewportOperator, (breakpointValue: number, width: number) => boolean>}\n */\nconst OPERATOR_EVALUATORS = {\n\t'>=': ( breakpointValue, width ) => width >= breakpointValue,\n\t'<': ( breakpointValue, width ) => width < breakpointValue,\n};\n\nconst ViewportMatchWidthContext = createContext(\n\t/** @type {null | number} */ ( null )\n);\nViewportMatchWidthContext.displayName = 'ViewportMatchWidthContext';\n\n/**\n * Returns true if the viewport matches the given query, or false otherwise.\n *\n * @param {WPBreakpoint} breakpoint Breakpoint size name.\n * @param {WPViewportOperator} [operator=\">=\"] Viewport operator.\n * @param {Window} [view=window] Window instance in which to perform viewport matching.\n *\n * @example\n *\n * ```js\n * useViewportMatch( 'huge', '<' );\n * useViewportMatch( 'medium' );\n * ```\n *\n * @return {boolean} Whether viewport matches query.\n */\nconst useViewportMatch = ( breakpoint, operator = '>=', view = window ) => {\n\tconst simulatedWidth = useContext( ViewportMatchWidthContext );\n\tconst mediaQuery =\n\t\t! simulatedWidth &&\n\t\t`(${ CONDITIONS[ operator ] }: ${ BREAKPOINTS[ breakpoint ] }px)`;\n\tconst mediaQueryResult = useMediaQuery( mediaQuery || undefined, view );\n\tif ( simulatedWidth ) {\n\t\treturn OPERATOR_EVALUATORS[ operator ](\n\t\t\tBREAKPOINTS[ breakpoint ],\n\t\t\tsimulatedWidth\n\t\t);\n\t}\n\treturn mediaQueryResult;\n};\n\nuseViewportMatch.__experimentalWidthProvider =\n\tViewportMatchWidthContext.Provider;\n\nexport default useViewportMatch;\n"],
5
- "mappings": ";AAGA,SAAS,eAAe,kBAAkB;AAK1C,OAAO,mBAAmB;AAa1B,IAAM,cAAc;AAAA,EACnB,OAAO;AAAA,EACP,MAAM;AAAA,EACN,MAAM;AAAA,EACN,QAAQ;AAAA,EACR,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,OAAO;AAAA,EACP,QAAQ;AACT;AAWA,IAAM,aAAa;AAAA,EAClB,MAAM;AAAA,EACN,KAAK;AACN;AAOA,IAAM,sBAAsB;AAAA,EAC3B,MAAM,CAAE,iBAAiB,UAAW,SAAS;AAAA,EAC7C,KAAK,CAAE,iBAAiB,UAAW,QAAQ;AAC5C;AAEA,IAAM,4BAA4B;AAAA;AAAA,EACF;AAChC;AACA,0BAA0B,cAAc;AAkBxC,IAAM,mBAAmB,CAAE,YAAY,WAAW,MAAM,OAAO,WAAY;AAC1E,QAAM,iBAAiB,WAAY,yBAA0B;AAC7D,QAAM,aACL,CAAE,kBACF,IAAK,WAAY,QAAS,CAAE,KAAM,YAAa,UAAW,CAAE;AAC7D,QAAM,mBAAmB,cAAe,cAAc,QAAW,IAAK;AACtE,MAAK,gBAAiB;AACrB,WAAO,oBAAqB,QAAS;AAAA,MACpC,YAAa,UAAW;AAAA,MACxB;AAAA,IACD;AAAA,EACD;AACA,SAAO;AACR;AAEA,iBAAiB,8BAChB,0BAA0B;AAE3B,IAAO,6BAAQ;",
4
+ "sourcesContent": ["/**\n * WordPress dependencies\n */\nimport { createContext, useContext } from '@wordpress/element';\n\n/**\n * Internal dependencies\n */\nimport useMediaQuery from '../use-media-query';\n\n/**\n * @typedef {\"xhuge\" | \"huge\" | \"wide\" | \"xlarge\" | \"large\" | \"medium\" | \"small\" | \"mobile\"} WPBreakpoint\n */\n\n/**\n * Hash of breakpoint names with pixel width at which it becomes effective.\n *\n * @see _breakpoints.scss\n *\n * @type {Record<WPBreakpoint, number>}\n */\nconst BREAKPOINTS = {\n\txhuge: 1920,\n\thuge: 1440,\n\twide: 1280,\n\txlarge: 1080,\n\tlarge: 960,\n\tmedium: 782,\n\tsmall: 600,\n\tmobile: 480,\n};\n\n/**\n * @typedef {\">=\" | \"<\"} WPViewportOperator\n */\n\n/**\n * Object mapping media query operators to the condition to be used.\n *\n * @type {Record<WPViewportOperator, string>}\n */\nconst CONDITIONS = {\n\t'>=': 'min-width',\n\t'<': 'max-width',\n};\n\n/**\n * Object mapping media query operators to a function that given a breakpointValue and a width evaluates if the operator matches the values.\n *\n * @type {Record<WPViewportOperator, (breakpointValue: number, width: number) => boolean>}\n */\nconst OPERATOR_EVALUATORS = {\n\t'>=': ( breakpointValue, width ) => width >= breakpointValue,\n\t'<': ( breakpointValue, width ) => width < breakpointValue,\n};\n\nconst ViewportMatchWidthContext = createContext(\n\t/** @type {null | number} */ ( null )\n);\nViewportMatchWidthContext.displayName = 'ViewportMatchWidthContext';\n\n/**\n * Returns true if the viewport matches the given query, or false otherwise.\n *\n * @param {WPBreakpoint} breakpoint Breakpoint size name.\n * @param {WPViewportOperator} [operator=\">=\"] Viewport operator.\n * @param {Window|undefined} [view=window] Window instance in which to perform viewport matching.\n *\n * @example\n *\n * ```js\n * useViewportMatch( 'huge', '<' );\n * useViewportMatch( 'medium' );\n * ```\n *\n * @return {boolean} Whether viewport matches query.\n */\nconst useViewportMatch = (\n\tbreakpoint,\n\toperator = '>=',\n\t// Resolve the default lazily so SSR (where `window` is undeclared) does not\n\t// throw a ReferenceError when this default expression is evaluated.\n\tview = typeof window !== 'undefined' ? window : undefined\n) => {\n\tconst simulatedWidth = useContext( ViewportMatchWidthContext );\n\tconst mediaQuery =\n\t\t! simulatedWidth &&\n\t\t`(${ CONDITIONS[ operator ] }: ${ BREAKPOINTS[ breakpoint ] }px)`;\n\tconst mediaQueryResult = useMediaQuery( mediaQuery || undefined, view );\n\tif ( simulatedWidth ) {\n\t\treturn OPERATOR_EVALUATORS[ operator ](\n\t\t\tBREAKPOINTS[ breakpoint ],\n\t\t\tsimulatedWidth\n\t\t);\n\t}\n\treturn mediaQueryResult;\n};\n\nuseViewportMatch.__experimentalWidthProvider =\n\tViewportMatchWidthContext.Provider;\n\nexport default useViewportMatch;\n"],
5
+ "mappings": ";AAGA,SAAS,eAAe,kBAAkB;AAK1C,OAAO,mBAAmB;AAa1B,IAAM,cAAc;AAAA,EACnB,OAAO;AAAA,EACP,MAAM;AAAA,EACN,MAAM;AAAA,EACN,QAAQ;AAAA,EACR,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,OAAO;AAAA,EACP,QAAQ;AACT;AAWA,IAAM,aAAa;AAAA,EAClB,MAAM;AAAA,EACN,KAAK;AACN;AAOA,IAAM,sBAAsB;AAAA,EAC3B,MAAM,CAAE,iBAAiB,UAAW,SAAS;AAAA,EAC7C,KAAK,CAAE,iBAAiB,UAAW,QAAQ;AAC5C;AAEA,IAAM,4BAA4B;AAAA;AAAA,EACF;AAChC;AACA,0BAA0B,cAAc;AAkBxC,IAAM,mBAAmB,CACxB,YACA,WAAW,MAGX,OAAO,OAAO,WAAW,cAAc,SAAS,WAC5C;AACJ,QAAM,iBAAiB,WAAY,yBAA0B;AAC7D,QAAM,aACL,CAAE,kBACF,IAAK,WAAY,QAAS,CAAE,KAAM,YAAa,UAAW,CAAE;AAC7D,QAAM,mBAAmB,cAAe,cAAc,QAAW,IAAK;AACtE,MAAK,gBAAiB;AACrB,WAAO,oBAAqB,QAAS;AAAA,MACpC,YAAa,UAAW;AAAA,MACxB;AAAA,IACD;AAAA,EACD;AACA,SAAO;AACR;AAEA,iBAAiB,8BAChB,0BAA0B;AAE3B,IAAO,6BAAQ;",
6
6
  "names": []
7
7
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/higher-order/pure/index.tsx"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,KAAK,EAAE,aAAa,EAAkB,MAAM,OAAO,CAAC;AAa3D;;;;;GAKG;AACH,QAAA,MAAM,IAAI,GAA0C,KAAK,SAAS,EAAE,sDAuBzD,CAAC;eAEG,IAAI"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/higher-order/pure/index.tsx"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,KAAK,EAAE,aAAa,EAAkB,MAAM,OAAO,CAAC;AAc3D;;;;;GAKG;AACH,QAAA,MAAM,IAAI,GAA0C,KAAK,SAAS,EAAE,sDA4BzD,CAAC;eAEG,IAAI"}
@@ -5,5 +5,5 @@
5
5
  * @param [view] Window instance, else default to global window
6
6
  * @return return value of the media query.
7
7
  */
8
- export default function useMediaQuery(query?: string, view?: Window): boolean;
8
+ export default function useMediaQuery(query?: string, view?: Window | undefined): boolean;
9
9
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/hooks/use-media-query/index.ts"],"names":[],"mappings":"AAoEA;;;;;;GAMG;AACH,MAAM,CAAC,OAAO,UAAU,aAAa,CACpC,KAAK,CAAC,EAAE,MAAM,EACd,IAAI,GAAE,MAAe,GACnB,OAAO,CAQT"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/hooks/use-media-query/index.ts"],"names":[],"mappings":"AAuEA;;;;;;GAMG;AACH,MAAM,CAAC,OAAO,UAAU,aAAa,CACpC,KAAK,CAAC,EAAE,MAAM,EAGd,IAAI,GAAE,MAAM,GAAG,SAEH,GACV,OAAO,CAQT"}
@@ -15,22 +15,24 @@ import type { Ref, RefCallback } from 'react';
15
15
  * old ref callback will be called with `null` and the new ref callback will be
16
16
  * called with the same value.
17
17
  *
18
- * To make ref callbacks easier to use, you can also pass the result of
19
- * `useRefEffect`, which makes cleanup easier by allowing you to return a
20
- * cleanup function instead of handling `null`.
18
+ * Inner ref callbacks may return a cleanup function (React 19's ref callback
19
+ * cleanup pattern). When a ref callback returns a function, that function is
20
+ * invoked at teardown (node change, dependency change, or unmount) **instead
21
+ * of** the callback being called with `null`. Callbacks that do not return a
22
+ * cleanup continue to receive `null` on teardown as before.
21
23
  *
22
24
  * It's also possible to _disable_ a ref (and its behaviour) by simply not
23
25
  * passing the ref.
24
26
  *
25
27
  * ```jsx
26
- * const ref = useRefEffect( ( node ) => {
28
+ * const ref = useCallback( ( node ) => {
27
29
  * node.addEventListener( ... );
28
30
  * return () => {
29
31
  * node.removeEventListener( ... );
30
32
  * };
31
33
  * }, [ ...dependencies ] );
32
34
  * const otherRef = useRef();
33
- * const mergedRefs useMergeRefs( [
35
+ * const mergedRefs = useMergeRefs( [
34
36
  * enabled && ref,
35
37
  * otherRef,
36
38
  * ] );