@wordpress/compose 7.41.1-next.v.202603102151.0 → 7.42.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 CHANGED
@@ -2,6 +2,12 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
+ ## 7.42.0 (2026-03-18)
6
+
7
+ ### New Features
8
+
9
+ - Hooks `useMediaQuery` and `useViewportMatch` accept a new optional `view` argument of type `Window`, which enables consumers to perform media queries in a window other than the global one (e.g. an iframe) ([#76446](https://github.com/WordPress/gutenberg/pull/76446)).
10
+
5
11
  ## 7.41.0 (2026-03-04)
6
12
 
7
13
  ## 7.40.0 (2026-02-18)
package/README.md CHANGED
@@ -431,6 +431,7 @@ Runs a media query and returns its value when it changes.
431
431
  _Parameters_
432
432
 
433
433
  - _query_ `[string]`: Media Query.
434
+ - _view_ `[Window]`: Window instance, else default to global window
434
435
 
435
436
  _Returns_
436
437
 
@@ -592,6 +593,7 @@ _Parameters_
592
593
 
593
594
  - _breakpoint_ `WPBreakpoint`: Breakpoint size name.
594
595
  - _operator_ `[WPViewportOperator]`: Viewport operator.
596
+ - _view_ `[Window]`: Window instance in which to perform viewport matching.
595
597
 
596
598
  _Returns_
597
599
 
@@ -17,34 +17,37 @@ var __copyProps = (to, from, except, desc) => {
17
17
  };
18
18
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
19
 
20
- // packages/compose/src/hooks/use-media-query/index.js
20
+ // packages/compose/src/hooks/use-media-query/index.ts
21
21
  var use_media_query_exports = {};
22
22
  __export(use_media_query_exports, {
23
23
  default: () => useMediaQuery
24
24
  });
25
25
  module.exports = __toCommonJS(use_media_query_exports);
26
26
  var import_element = require("@wordpress/element");
27
- var matchMediaCache = /* @__PURE__ */ new Map();
28
- function getMediaQueryList(query) {
27
+ var perWindowCache = /* @__PURE__ */ new WeakMap();
28
+ function getMediaQueryList(view, query) {
29
29
  if (!query) {
30
30
  return null;
31
31
  }
32
+ const matchMediaCache = perWindowCache.get(view) ?? /* @__PURE__ */ new Map();
33
+ if (!perWindowCache.has(view)) {
34
+ perWindowCache.set(view, matchMediaCache);
35
+ }
32
36
  let match = matchMediaCache.get(query);
33
37
  if (match) {
34
38
  return match;
35
39
  }
36
- if (typeof window !== "undefined" && typeof window.matchMedia === "function") {
37
- match = window.matchMedia(query);
40
+ if (typeof view?.matchMedia === "function") {
41
+ match = view.matchMedia(query);
38
42
  matchMediaCache.set(query, match);
39
43
  return match;
40
44
  }
41
45
  return null;
42
46
  }
43
- function useMediaQuery(query) {
47
+ function useMediaQuery(query, view = window) {
44
48
  const source = (0, import_element.useMemo)(() => {
45
- const mediaQueryList = getMediaQueryList(query);
49
+ const mediaQueryList = getMediaQueryList(view, query);
46
50
  return {
47
- /** @type {(onStoreChange: () => void) => () => void} */
48
51
  subscribe(onStoreChange) {
49
52
  if (!mediaQueryList) {
50
53
  return () => {
@@ -62,7 +65,7 @@ function useMediaQuery(query) {
62
65
  return mediaQueryList?.matches ?? false;
63
66
  }
64
67
  };
65
- }, [query]);
68
+ }, [view, query]);
66
69
  return (0, import_element.useSyncExternalStore)(
67
70
  source.subscribe,
68
71
  source.getValue,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../../../src/hooks/use-media-query/index.js"],
4
- "sourcesContent": ["/**\n * WordPress dependencies\n */\nimport { useMemo, useSyncExternalStore } from '@wordpress/element';\n\nconst matchMediaCache = new Map();\n\n/**\n * A new MediaQueryList object for the media query\n *\n * @param {string} [query] Media Query.\n * @return {MediaQueryList|null} A new object for the media query\n */\nfunction getMediaQueryList( query ) {\n\tif ( ! query ) {\n\t\treturn null;\n\t}\n\n\tlet match = matchMediaCache.get( query );\n\n\tif ( match ) {\n\t\treturn match;\n\t}\n\n\tif (\n\t\ttypeof window !== 'undefined' &&\n\t\ttypeof window.matchMedia === 'function'\n\t) {\n\t\tmatch = window.matchMedia( query );\n\t\tmatchMediaCache.set( query, match );\n\t\treturn match;\n\t}\n\n\treturn null;\n}\n\n/**\n * Runs a media query and returns its value when it changes.\n *\n * @param {string} [query] Media Query.\n * @return {boolean} return value of the media query.\n */\nexport default function useMediaQuery( query ) {\n\tconst source = useMemo( () => {\n\t\tconst mediaQueryList = getMediaQueryList( query );\n\n\t\treturn {\n\t\t\t/** @type {(onStoreChange: () => void) => () => void} */\n\t\t\tsubscribe( onStoreChange ) {\n\t\t\t\tif ( ! mediaQueryList ) {\n\t\t\t\t\treturn () => {};\n\t\t\t\t}\n\n\t\t\t\t// Avoid a fatal error when browsers don't support `addEventListener` on MediaQueryList.\n\t\t\t\tmediaQueryList.addEventListener?.( 'change', onStoreChange );\n\t\t\t\treturn () => {\n\t\t\t\t\tmediaQueryList.removeEventListener?.(\n\t\t\t\t\t\t'change',\n\t\t\t\t\t\tonStoreChange\n\t\t\t\t\t);\n\t\t\t\t};\n\t\t\t},\n\t\t\tgetValue() {\n\t\t\t\treturn mediaQueryList?.matches ?? false;\n\t\t\t},\n\t\t};\n\t}, [ 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,qBAA8C;AAE9C,IAAM,kBAAkB,oBAAI,IAAI;AAQhC,SAAS,kBAAmB,OAAQ;AACnC,MAAK,CAAE,OAAQ;AACd,WAAO;AAAA,EACR;AAEA,MAAI,QAAQ,gBAAgB,IAAK,KAAM;AAEvC,MAAK,OAAQ;AACZ,WAAO;AAAA,EACR;AAEA,MACC,OAAO,WAAW,eAClB,OAAO,OAAO,eAAe,YAC5B;AACD,YAAQ,OAAO,WAAY,KAAM;AACjC,oBAAgB,IAAK,OAAO,KAAM;AAClC,WAAO;AAAA,EACR;AAEA,SAAO;AACR;AAQe,SAAR,cAAgC,OAAQ;AAC9C,QAAM,aAAS,wBAAS,MAAM;AAC7B,UAAM,iBAAiB,kBAAmB,KAAM;AAEhD,WAAO;AAAA;AAAA,MAEN,UAAW,eAAgB;AAC1B,YAAK,CAAE,gBAAiB;AACvB,iBAAO,MAAM;AAAA,UAAC;AAAA,QACf;AAGA,uBAAe,mBAAoB,UAAU,aAAc;AAC3D,eAAO,MAAM;AACZ,yBAAe;AAAA,YACd;AAAA,YACA;AAAA,UACD;AAAA,QACD;AAAA,MACD;AAAA,MACA,WAAW;AACV,eAAO,gBAAgB,WAAW;AAAA,MACnC;AAAA,IACD;AAAA,EACD,GAAG,CAAE,KAAM,CAAE;AAEb,aAAO;AAAA,IACN,OAAO;AAAA,IACP,OAAO;AAAA,IACP,MAAM;AAAA,EACP;AACD;",
3
+ "sources": ["../../../src/hooks/use-media-query/index.ts"],
4
+ "sourcesContent": ["/**\n * WordPress dependencies\n */\nimport { useMemo, useSyncExternalStore } from '@wordpress/element';\n\ntype MQLCache = Map< string, MediaQueryList >;\n\nconst perWindowCache = new WeakMap< Window, MQLCache >();\n\n/**\n * A new MediaQueryList object for the media query\n *\n * @param view Window.\n * @param [query] Media Query.\n */\nfunction getMediaQueryList(\n\tview: Window,\n\tquery?: string\n): MediaQueryList | null {\n\tif ( ! query ) {\n\t\treturn null;\n\t}\n\n\tconst matchMediaCache: MQLCache = perWindowCache.get( view ) ?? new Map();\n\n\tif ( ! perWindowCache.has( view ) ) {\n\t\tperWindowCache.set( view, matchMediaCache );\n\t}\n\n\tlet match = matchMediaCache.get( query );\n\n\tif ( match ) {\n\t\treturn match;\n\t}\n\n\tif ( typeof view?.matchMedia === 'function' ) {\n\t\tmatch = view.matchMedia( query );\n\t\tmatchMediaCache.set( query, match );\n\t\treturn match;\n\t}\n\n\treturn null;\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 = useMemo( () => {\n\t\tconst mediaQueryList = getMediaQueryList( view, query );\n\n\t\treturn {\n\t\t\tsubscribe( onStoreChange: any ) {\n\t\t\t\tif ( ! mediaQueryList ) {\n\t\t\t\t\treturn () => {};\n\t\t\t\t}\n\n\t\t\t\t// Avoid a fatal error when browsers don't support `addEventListener` on MediaQueryList.\n\t\t\t\tmediaQueryList.addEventListener?.( 'change', onStoreChange );\n\t\t\t\treturn () => {\n\t\t\t\t\tmediaQueryList.removeEventListener?.(\n\t\t\t\t\t\t'change',\n\t\t\t\t\t\tonStoreChange\n\t\t\t\t\t);\n\t\t\t\t};\n\t\t\t},\n\t\t\tgetValue() {\n\t\t\t\treturn mediaQueryList?.matches ?? false;\n\t\t\t},\n\t\t};\n\t}, [ 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,qBAA8C;AAI9C,IAAM,iBAAiB,oBAAI,QAA4B;AAQvD,SAAS,kBACR,MACA,OACwB;AACxB,MAAK,CAAE,OAAQ;AACd,WAAO;AAAA,EACR;AAEA,QAAM,kBAA4B,eAAe,IAAK,IAAK,KAAK,oBAAI,IAAI;AAExE,MAAK,CAAE,eAAe,IAAK,IAAK,GAAI;AACnC,mBAAe,IAAK,MAAM,eAAgB;AAAA,EAC3C;AAEA,MAAI,QAAQ,gBAAgB,IAAK,KAAM;AAEvC,MAAK,OAAQ;AACZ,WAAO;AAAA,EACR;AAEA,MAAK,OAAO,MAAM,eAAe,YAAa;AAC7C,YAAQ,KAAK,WAAY,KAAM;AAC/B,oBAAgB,IAAK,OAAO,KAAM;AAClC,WAAO;AAAA,EACR;AAEA,SAAO;AACR;AASe,SAAR,cACN,OACA,OAAe,QACL;AACV,QAAM,aAAS,wBAAS,MAAM;AAC7B,UAAM,iBAAiB,kBAAmB,MAAM,KAAM;AAEtD,WAAO;AAAA,MACN,UAAW,eAAqB;AAC/B,YAAK,CAAE,gBAAiB;AACvB,iBAAO,MAAM;AAAA,UAAC;AAAA,QACf;AAGA,uBAAe,mBAAoB,UAAU,aAAc;AAC3D,eAAO,MAAM;AACZ,yBAAe;AAAA,YACd;AAAA,YACA;AAAA,UACD;AAAA,QACD;AAAA,MACD;AAAA,MACA,WAAW;AACV,eAAO,gBAAgB,WAAW;AAAA,MACnC;AAAA,IACD;AAAA,EACD,GAAG,CAAE,MAAM,KAAM,CAAE;AAEnB,aAAO;AAAA,IACN,OAAO;AAAA,IACP,OAAO;AAAA,IACP,MAAM;AAAA,EACP;AACD;",
6
6
  "names": []
7
7
  }
@@ -58,10 +58,10 @@ var ViewportMatchWidthContext = (0, import_element.createContext)(
58
58
  null
59
59
  );
60
60
  ViewportMatchWidthContext.displayName = "ViewportMatchWidthContext";
61
- var useViewportMatch = (breakpoint, operator = ">=") => {
61
+ var useViewportMatch = (breakpoint, operator = ">=", view = window) => {
62
62
  const simulatedWidth = (0, import_element.useContext)(ViewportMatchWidthContext);
63
63
  const mediaQuery = !simulatedWidth && `(${CONDITIONS[operator]}: ${BREAKPOINTS[breakpoint]}px)`;
64
- const mediaQueryResult = (0, import_use_media_query.default)(mediaQuery || void 0);
64
+ const mediaQueryResult = (0, import_use_media_query.default)(mediaQuery || void 0, view);
65
65
  if (simulatedWidth) {
66
66
  return OPERATOR_EVALUATORS[operator](
67
67
  BREAKPOINTS[breakpoint],
@@ -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 *\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 = '>=' ) => {\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 );\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;AAiBxC,IAAM,mBAAmB,CAAE,YAAY,WAAW,SAAU;AAC3D,QAAM,qBAAiB,2BAAY,yBAA0B;AAC7D,QAAM,aACL,CAAE,kBACF,IAAK,WAAY,QAAS,CAAE,KAAM,YAAa,UAAW,CAAE;AAC7D,QAAM,uBAAmB,uBAAAA,SAAe,cAAc,MAAU;AAChE,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} [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;",
6
6
  "names": ["useMediaQuery"]
7
7
  }
@@ -1,26 +1,29 @@
1
- // packages/compose/src/hooks/use-media-query/index.js
1
+ // packages/compose/src/hooks/use-media-query/index.ts
2
2
  import { useMemo, useSyncExternalStore } from "@wordpress/element";
3
- var matchMediaCache = /* @__PURE__ */ new Map();
4
- function getMediaQueryList(query) {
3
+ var perWindowCache = /* @__PURE__ */ new WeakMap();
4
+ function getMediaQueryList(view, query) {
5
5
  if (!query) {
6
6
  return null;
7
7
  }
8
+ const matchMediaCache = perWindowCache.get(view) ?? /* @__PURE__ */ new Map();
9
+ if (!perWindowCache.has(view)) {
10
+ perWindowCache.set(view, matchMediaCache);
11
+ }
8
12
  let match = matchMediaCache.get(query);
9
13
  if (match) {
10
14
  return match;
11
15
  }
12
- if (typeof window !== "undefined" && typeof window.matchMedia === "function") {
13
- match = window.matchMedia(query);
16
+ if (typeof view?.matchMedia === "function") {
17
+ match = view.matchMedia(query);
14
18
  matchMediaCache.set(query, match);
15
19
  return match;
16
20
  }
17
21
  return null;
18
22
  }
19
- function useMediaQuery(query) {
23
+ function useMediaQuery(query, view = window) {
20
24
  const source = useMemo(() => {
21
- const mediaQueryList = getMediaQueryList(query);
25
+ const mediaQueryList = getMediaQueryList(view, query);
22
26
  return {
23
- /** @type {(onStoreChange: () => void) => () => void} */
24
27
  subscribe(onStoreChange) {
25
28
  if (!mediaQueryList) {
26
29
  return () => {
@@ -38,7 +41,7 @@ function useMediaQuery(query) {
38
41
  return mediaQueryList?.matches ?? false;
39
42
  }
40
43
  };
41
- }, [query]);
44
+ }, [view, query]);
42
45
  return useSyncExternalStore(
43
46
  source.subscribe,
44
47
  source.getValue,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../../../src/hooks/use-media-query/index.js"],
4
- "sourcesContent": ["/**\n * WordPress dependencies\n */\nimport { useMemo, useSyncExternalStore } from '@wordpress/element';\n\nconst matchMediaCache = new Map();\n\n/**\n * A new MediaQueryList object for the media query\n *\n * @param {string} [query] Media Query.\n * @return {MediaQueryList|null} A new object for the media query\n */\nfunction getMediaQueryList( query ) {\n\tif ( ! query ) {\n\t\treturn null;\n\t}\n\n\tlet match = matchMediaCache.get( query );\n\n\tif ( match ) {\n\t\treturn match;\n\t}\n\n\tif (\n\t\ttypeof window !== 'undefined' &&\n\t\ttypeof window.matchMedia === 'function'\n\t) {\n\t\tmatch = window.matchMedia( query );\n\t\tmatchMediaCache.set( query, match );\n\t\treturn match;\n\t}\n\n\treturn null;\n}\n\n/**\n * Runs a media query and returns its value when it changes.\n *\n * @param {string} [query] Media Query.\n * @return {boolean} return value of the media query.\n */\nexport default function useMediaQuery( query ) {\n\tconst source = useMemo( () => {\n\t\tconst mediaQueryList = getMediaQueryList( query );\n\n\t\treturn {\n\t\t\t/** @type {(onStoreChange: () => void) => () => void} */\n\t\t\tsubscribe( onStoreChange ) {\n\t\t\t\tif ( ! mediaQueryList ) {\n\t\t\t\t\treturn () => {};\n\t\t\t\t}\n\n\t\t\t\t// Avoid a fatal error when browsers don't support `addEventListener` on MediaQueryList.\n\t\t\t\tmediaQueryList.addEventListener?.( 'change', onStoreChange );\n\t\t\t\treturn () => {\n\t\t\t\t\tmediaQueryList.removeEventListener?.(\n\t\t\t\t\t\t'change',\n\t\t\t\t\t\tonStoreChange\n\t\t\t\t\t);\n\t\t\t\t};\n\t\t\t},\n\t\t\tgetValue() {\n\t\t\t\treturn mediaQueryList?.matches ?? false;\n\t\t\t},\n\t\t};\n\t}, [ 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,SAAS,4BAA4B;AAE9C,IAAM,kBAAkB,oBAAI,IAAI;AAQhC,SAAS,kBAAmB,OAAQ;AACnC,MAAK,CAAE,OAAQ;AACd,WAAO;AAAA,EACR;AAEA,MAAI,QAAQ,gBAAgB,IAAK,KAAM;AAEvC,MAAK,OAAQ;AACZ,WAAO;AAAA,EACR;AAEA,MACC,OAAO,WAAW,eAClB,OAAO,OAAO,eAAe,YAC5B;AACD,YAAQ,OAAO,WAAY,KAAM;AACjC,oBAAgB,IAAK,OAAO,KAAM;AAClC,WAAO;AAAA,EACR;AAEA,SAAO;AACR;AAQe,SAAR,cAAgC,OAAQ;AAC9C,QAAM,SAAS,QAAS,MAAM;AAC7B,UAAM,iBAAiB,kBAAmB,KAAM;AAEhD,WAAO;AAAA;AAAA,MAEN,UAAW,eAAgB;AAC1B,YAAK,CAAE,gBAAiB;AACvB,iBAAO,MAAM;AAAA,UAAC;AAAA,QACf;AAGA,uBAAe,mBAAoB,UAAU,aAAc;AAC3D,eAAO,MAAM;AACZ,yBAAe;AAAA,YACd;AAAA,YACA;AAAA,UACD;AAAA,QACD;AAAA,MACD;AAAA,MACA,WAAW;AACV,eAAO,gBAAgB,WAAW;AAAA,MACnC;AAAA,IACD;AAAA,EACD,GAAG,CAAE,KAAM,CAAE;AAEb,SAAO;AAAA,IACN,OAAO;AAAA,IACP,OAAO;AAAA,IACP,MAAM;AAAA,EACP;AACD;",
3
+ "sources": ["../../../src/hooks/use-media-query/index.ts"],
4
+ "sourcesContent": ["/**\n * WordPress dependencies\n */\nimport { useMemo, useSyncExternalStore } from '@wordpress/element';\n\ntype MQLCache = Map< string, MediaQueryList >;\n\nconst perWindowCache = new WeakMap< Window, MQLCache >();\n\n/**\n * A new MediaQueryList object for the media query\n *\n * @param view Window.\n * @param [query] Media Query.\n */\nfunction getMediaQueryList(\n\tview: Window,\n\tquery?: string\n): MediaQueryList | null {\n\tif ( ! query ) {\n\t\treturn null;\n\t}\n\n\tconst matchMediaCache: MQLCache = perWindowCache.get( view ) ?? new Map();\n\n\tif ( ! perWindowCache.has( view ) ) {\n\t\tperWindowCache.set( view, matchMediaCache );\n\t}\n\n\tlet match = matchMediaCache.get( query );\n\n\tif ( match ) {\n\t\treturn match;\n\t}\n\n\tif ( typeof view?.matchMedia === 'function' ) {\n\t\tmatch = view.matchMedia( query );\n\t\tmatchMediaCache.set( query, match );\n\t\treturn match;\n\t}\n\n\treturn null;\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 = useMemo( () => {\n\t\tconst mediaQueryList = getMediaQueryList( view, query );\n\n\t\treturn {\n\t\t\tsubscribe( onStoreChange: any ) {\n\t\t\t\tif ( ! mediaQueryList ) {\n\t\t\t\t\treturn () => {};\n\t\t\t\t}\n\n\t\t\t\t// Avoid a fatal error when browsers don't support `addEventListener` on MediaQueryList.\n\t\t\t\tmediaQueryList.addEventListener?.( 'change', onStoreChange );\n\t\t\t\treturn () => {\n\t\t\t\t\tmediaQueryList.removeEventListener?.(\n\t\t\t\t\t\t'change',\n\t\t\t\t\t\tonStoreChange\n\t\t\t\t\t);\n\t\t\t\t};\n\t\t\t},\n\t\t\tgetValue() {\n\t\t\t\treturn mediaQueryList?.matches ?? false;\n\t\t\t},\n\t\t};\n\t}, [ 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,SAAS,4BAA4B;AAI9C,IAAM,iBAAiB,oBAAI,QAA4B;AAQvD,SAAS,kBACR,MACA,OACwB;AACxB,MAAK,CAAE,OAAQ;AACd,WAAO;AAAA,EACR;AAEA,QAAM,kBAA4B,eAAe,IAAK,IAAK,KAAK,oBAAI,IAAI;AAExE,MAAK,CAAE,eAAe,IAAK,IAAK,GAAI;AACnC,mBAAe,IAAK,MAAM,eAAgB;AAAA,EAC3C;AAEA,MAAI,QAAQ,gBAAgB,IAAK,KAAM;AAEvC,MAAK,OAAQ;AACZ,WAAO;AAAA,EACR;AAEA,MAAK,OAAO,MAAM,eAAe,YAAa;AAC7C,YAAQ,KAAK,WAAY,KAAM;AAC/B,oBAAgB,IAAK,OAAO,KAAM;AAClC,WAAO;AAAA,EACR;AAEA,SAAO;AACR;AASe,SAAR,cACN,OACA,OAAe,QACL;AACV,QAAM,SAAS,QAAS,MAAM;AAC7B,UAAM,iBAAiB,kBAAmB,MAAM,KAAM;AAEtD,WAAO;AAAA,MACN,UAAW,eAAqB;AAC/B,YAAK,CAAE,gBAAiB;AACvB,iBAAO,MAAM;AAAA,UAAC;AAAA,QACf;AAGA,uBAAe,mBAAoB,UAAU,aAAc;AAC3D,eAAO,MAAM;AACZ,yBAAe;AAAA,YACd;AAAA,YACA;AAAA,UACD;AAAA,QACD;AAAA,MACD;AAAA,MACA,WAAW;AACV,eAAO,gBAAgB,WAAW;AAAA,MACnC;AAAA,IACD;AAAA,EACD,GAAG,CAAE,MAAM,KAAM,CAAE;AAEnB,SAAO;AAAA,IACN,OAAO;AAAA,IACP,OAAO;AAAA,IACP,MAAM;AAAA,EACP;AACD;",
6
6
  "names": []
7
7
  }
@@ -24,10 +24,10 @@ var ViewportMatchWidthContext = createContext(
24
24
  null
25
25
  );
26
26
  ViewportMatchWidthContext.displayName = "ViewportMatchWidthContext";
27
- var useViewportMatch = (breakpoint, operator = ">=") => {
27
+ var useViewportMatch = (breakpoint, operator = ">=", view = window) => {
28
28
  const simulatedWidth = useContext(ViewportMatchWidthContext);
29
29
  const mediaQuery = !simulatedWidth && `(${CONDITIONS[operator]}: ${BREAKPOINTS[breakpoint]}px)`;
30
- const mediaQueryResult = useMediaQuery(mediaQuery || void 0);
30
+ const mediaQueryResult = useMediaQuery(mediaQuery || void 0, view);
31
31
  if (simulatedWidth) {
32
32
  return OPERATOR_EVALUATORS[operator](
33
33
  BREAKPOINTS[breakpoint],
@@ -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 *\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 = '>=' ) => {\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 );\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;AAiBxC,IAAM,mBAAmB,CAAE,YAAY,WAAW,SAAU;AAC3D,QAAM,iBAAiB,WAAY,yBAA0B;AAC7D,QAAM,aACL,CAAE,kBACF,IAAK,WAAY,QAAS,CAAE,KAAM,YAAa,UAAW,CAAE;AAC7D,QAAM,mBAAmB,cAAe,cAAc,MAAU;AAChE,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} [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;",
6
6
  "names": []
7
7
  }
@@ -1,8 +1,9 @@
1
1
  /**
2
2
  * Runs a media query and returns its value when it changes.
3
3
  *
4
- * @param {string} [query] Media Query.
5
- * @return {boolean} return value of the media query.
4
+ * @param [query] Media Query.
5
+ * @param [view] Window instance, else default to global window
6
+ * @return return value of the media query.
6
7
  */
7
- export default function useMediaQuery(query?: string): boolean;
8
+ export default function useMediaQuery(query?: string, view?: Window): boolean;
8
9
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/hooks/use-media-query/index.js"],"names":[],"mappings":"AAoCA;;;;;GAKG;AACH,8CAHW,MAAM,GACL,OAAO,CAiClB"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/hooks/use-media-query/index.ts"],"names":[],"mappings":"AA4CA;;;;;;GAMG;AACH,MAAM,CAAC,OAAO,UAAU,aAAa,CACpC,KAAK,CAAC,EAAE,MAAM,EACd,IAAI,GAAE,MAAe,GACnB,OAAO,CA8BT"}
@@ -6,6 +6,7 @@ export type WPViewportOperator = ">=" | "<";
6
6
  *
7
7
  * @param {WPBreakpoint} breakpoint Breakpoint size name.
8
8
  * @param {WPViewportOperator} [operator=">="] Viewport operator.
9
+ * @param {Window} [view=window] Window instance in which to perform viewport matching.
9
10
  *
10
11
  * @example
11
12
  *
@@ -16,7 +17,7 @@ export type WPViewportOperator = ">=" | "<";
16
17
  *
17
18
  * @return {boolean} Whether viewport matches query.
18
19
  */
19
- declare function useViewportMatch(breakpoint: WPBreakpoint, operator?: WPViewportOperator): boolean;
20
+ declare function useViewportMatch(breakpoint: WPBreakpoint, operator?: WPViewportOperator, view?: Window): boolean;
20
21
  declare namespace useViewportMatch {
21
22
  let __experimentalWidthProvider: import("react").Provider<number | null>;
22
23
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/hooks/use-viewport-match/index.js"],"names":[],"mappings":";2BAWa,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,QAAQ,GAAG,OAAO,GAAG,QAAQ,GAAG,OAAO,GAAG,QAAQ;iCAsB9E,IAAI,GAAG,GAAG;AA4BvB;;;;;;;;;;;;;;GAcG;AACH,8CAZW,YAAY,aACZ,kBAAkB,GASjB,OAAO,CAelB"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/hooks/use-viewport-match/index.js"],"names":[],"mappings":";2BAWa,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,QAAQ,GAAG,OAAO,GAAG,QAAQ,GAAG,OAAO,GAAG,QAAQ;iCAsB9E,IAAI,GAAG,GAAG;AA4BvB;;;;;;;;;;;;;;;GAeG;AACH,8CAbW,YAAY,aACZ,kBAAkB,SAClB,MAAM,GASL,OAAO,CAelB"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wordpress/compose",
3
- "version": "7.41.1-next.v.202603102151.0+59e17f9ec",
3
+ "version": "7.42.0",
4
4
  "description": "WordPress higher-order components (HOCs).",
5
5
  "author": "The WordPress Contributors",
6
6
  "license": "GPL-2.0-or-later",
@@ -47,13 +47,13 @@
47
47
  "sideEffects": false,
48
48
  "dependencies": {
49
49
  "@types/mousetrap": "^1.6.8",
50
- "@wordpress/deprecated": "^4.41.1-next.v.202603102151.0+59e17f9ec",
51
- "@wordpress/dom": "^4.41.1-next.v.202603102151.0+59e17f9ec",
52
- "@wordpress/element": "^6.41.1-next.v.202603102151.0+59e17f9ec",
53
- "@wordpress/is-shallow-equal": "^5.41.1-next.v.202603102151.0+59e17f9ec",
54
- "@wordpress/keycodes": "^4.41.1-next.v.202603102151.0+59e17f9ec",
55
- "@wordpress/priority-queue": "^3.41.1-next.v.202603102151.0+59e17f9ec",
56
- "@wordpress/undo-manager": "^1.41.1-next.v.202603102151.0+59e17f9ec",
50
+ "@wordpress/deprecated": "^4.42.0",
51
+ "@wordpress/dom": "^4.42.0",
52
+ "@wordpress/element": "^6.42.0",
53
+ "@wordpress/is-shallow-equal": "^5.42.0",
54
+ "@wordpress/keycodes": "^4.42.0",
55
+ "@wordpress/priority-queue": "^3.42.0",
56
+ "@wordpress/undo-manager": "^1.42.0",
57
57
  "change-case": "^4.1.2",
58
58
  "mousetrap": "^1.6.5",
59
59
  "use-memo-one": "^1.1.1"
@@ -67,5 +67,5 @@
67
67
  "publishConfig": {
68
68
  "access": "public"
69
69
  },
70
- "gitHead": "86db21e727d89e8f0dbba9300d2f97fd22b08693"
70
+ "gitHead": "c20787b1778ae64c2db65643b1c236309d68e6ba"
71
71
  }
@@ -3,30 +3,38 @@
3
3
  */
4
4
  import { useMemo, useSyncExternalStore } from '@wordpress/element';
5
5
 
6
- const matchMediaCache = new Map();
6
+ type MQLCache = Map< string, MediaQueryList >;
7
+
8
+ const perWindowCache = new WeakMap< Window, MQLCache >();
7
9
 
8
10
  /**
9
11
  * A new MediaQueryList object for the media query
10
12
  *
11
- * @param {string} [query] Media Query.
12
- * @return {MediaQueryList|null} A new object for the media query
13
+ * @param view Window.
14
+ * @param [query] Media Query.
13
15
  */
14
- function getMediaQueryList( query ) {
16
+ function getMediaQueryList(
17
+ view: Window,
18
+ query?: string
19
+ ): MediaQueryList | null {
15
20
  if ( ! query ) {
16
21
  return null;
17
22
  }
18
23
 
24
+ const matchMediaCache: MQLCache = perWindowCache.get( view ) ?? new Map();
25
+
26
+ if ( ! perWindowCache.has( view ) ) {
27
+ perWindowCache.set( view, matchMediaCache );
28
+ }
29
+
19
30
  let match = matchMediaCache.get( query );
20
31
 
21
32
  if ( match ) {
22
33
  return match;
23
34
  }
24
35
 
25
- if (
26
- typeof window !== 'undefined' &&
27
- typeof window.matchMedia === 'function'
28
- ) {
29
- match = window.matchMedia( query );
36
+ if ( typeof view?.matchMedia === 'function' ) {
37
+ match = view.matchMedia( query );
30
38
  matchMediaCache.set( query, match );
31
39
  return match;
32
40
  }
@@ -37,16 +45,19 @@ function getMediaQueryList( query ) {
37
45
  /**
38
46
  * Runs a media query and returns its value when it changes.
39
47
  *
40
- * @param {string} [query] Media Query.
41
- * @return {boolean} return value of the media query.
48
+ * @param [query] Media Query.
49
+ * @param [view] Window instance, else default to global window
50
+ * @return return value of the media query.
42
51
  */
43
- export default function useMediaQuery( query ) {
52
+ export default function useMediaQuery(
53
+ query?: string,
54
+ view: Window = window
55
+ ): boolean {
44
56
  const source = useMemo( () => {
45
- const mediaQueryList = getMediaQueryList( query );
57
+ const mediaQueryList = getMediaQueryList( view, query );
46
58
 
47
59
  return {
48
- /** @type {(onStoreChange: () => void) => () => void} */
49
- subscribe( onStoreChange ) {
60
+ subscribe( onStoreChange: any ) {
50
61
  if ( ! mediaQueryList ) {
51
62
  return () => {};
52
63
  }
@@ -64,7 +75,7 @@ export default function useMediaQuery( query ) {
64
75
  return mediaQueryList?.matches ?? false;
65
76
  },
66
77
  };
67
- }, [ query ] );
78
+ }, [ view, query ] );
68
79
 
69
80
  return useSyncExternalStore(
70
81
  source.subscribe,
@@ -64,6 +64,7 @@ ViewportMatchWidthContext.displayName = 'ViewportMatchWidthContext';
64
64
  *
65
65
  * @param {WPBreakpoint} breakpoint Breakpoint size name.
66
66
  * @param {WPViewportOperator} [operator=">="] Viewport operator.
67
+ * @param {Window} [view=window] Window instance in which to perform viewport matching.
67
68
  *
68
69
  * @example
69
70
  *
@@ -74,12 +75,12 @@ ViewportMatchWidthContext.displayName = 'ViewportMatchWidthContext';
74
75
  *
75
76
  * @return {boolean} Whether viewport matches query.
76
77
  */
77
- const useViewportMatch = ( breakpoint, operator = '>=' ) => {
78
+ const useViewportMatch = ( breakpoint, operator = '>=', view = window ) => {
78
79
  const simulatedWidth = useContext( ViewportMatchWidthContext );
79
80
  const mediaQuery =
80
81
  ! simulatedWidth &&
81
82
  `(${ CONDITIONS[ operator ] }: ${ BREAKPOINTS[ breakpoint ] }px)`;
82
- const mediaQueryResult = useMediaQuery( mediaQuery || undefined );
83
+ const mediaQueryResult = useMediaQuery( mediaQuery || undefined, view );
83
84
  if ( simulatedWidth ) {
84
85
  return OPERATOR_EVALUATORS[ operator ](
85
86
  BREAKPOINTS[ breakpoint ],
@@ -44,15 +44,18 @@ describe( 'useViewportMatch', () => {
44
44
  expect( useMediaQueryMock ).toHaveBeenCalledTimes( 3 );
45
45
  expect( useMediaQueryMock ).toHaveBeenNthCalledWith(
46
46
  1,
47
- '(max-width: 1280px)'
47
+ '(max-width: 1280px)',
48
+ window
48
49
  );
49
50
  expect( useMediaQueryMock ).toHaveBeenNthCalledWith(
50
51
  2,
51
- '(min-width: 782px)'
52
+ '(min-width: 782px)',
53
+ window
52
54
  );
53
55
  expect( useMediaQueryMock ).toHaveBeenNthCalledWith(
54
56
  3,
55
- '(min-width: 600px)'
57
+ '(min-width: 600px)',
58
+ window
56
59
  );
57
60
  } );
58
61
 
@@ -76,15 +79,18 @@ describe( 'useViewportMatch', () => {
76
79
  expect( useMediaQueryMock ).toHaveBeenCalledTimes( 3 );
77
80
  expect( useMediaQueryMock ).toHaveBeenNthCalledWith(
78
81
  1,
79
- '(min-width: 1440px)'
82
+ '(min-width: 1440px)',
83
+ window
80
84
  );
81
85
  expect( useMediaQueryMock ).toHaveBeenNthCalledWith(
82
86
  2,
83
- '(max-width: 960px)'
87
+ '(max-width: 960px)',
88
+ window
84
89
  );
85
90
  expect( useMediaQueryMock ).toHaveBeenNthCalledWith(
86
91
  3,
87
- '(max-width: 480px)'
92
+ '(max-width: 480px)',
93
+ window
88
94
  );
89
95
  } );
90
96
 
@@ -121,9 +127,25 @@ describe( 'useViewportMatch', () => {
121
127
 
122
128
  expect( useMediaQueryMock ).toHaveBeenCalledTimes( 4 );
123
129
  // `useMediaQuery` is expected to receive `undefined` when simulating width.
124
- expect( useMediaQueryMock ).toHaveBeenNthCalledWith( 1, undefined );
125
- expect( useMediaQueryMock ).toHaveBeenNthCalledWith( 2, undefined );
126
- expect( useMediaQueryMock ).toHaveBeenNthCalledWith( 3, undefined );
127
- expect( useMediaQueryMock ).toHaveBeenNthCalledWith( 4, undefined );
130
+ expect( useMediaQueryMock ).toHaveBeenNthCalledWith(
131
+ 1,
132
+ undefined,
133
+ window
134
+ );
135
+ expect( useMediaQueryMock ).toHaveBeenNthCalledWith(
136
+ 2,
137
+ undefined,
138
+ window
139
+ );
140
+ expect( useMediaQueryMock ).toHaveBeenNthCalledWith(
141
+ 3,
142
+ undefined,
143
+ window
144
+ );
145
+ expect( useMediaQueryMock ).toHaveBeenNthCalledWith(
146
+ 4,
147
+ undefined,
148
+ window
149
+ );
128
150
  } );
129
151
  } );