@wordpress/notices 5.46.0 → 5.47.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,16 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
+ ## 5.47.0 (2026-05-27)
6
+
7
+ ### Enhancements
8
+
9
+ - `InlineNotices`: Wrap pinned and dismissible lists in a `notices-inline-notices-wrapper` container with spacing between lists. Add optional `className` prop for the wrapper.
10
+
11
+ ### Internal
12
+
13
+ - `InlineNotices`: Remove package-level `Notice` style overrides; `Notice` from `@wordpress/components` owns layout and chrome ([#78231](https://github.com/WordPress/gutenberg/pull/78231)).
14
+
5
15
  ## 5.46.0 (2026-05-14)
6
16
 
7
17
  ## 5.45.0 (2026-04-29)
package/README.md CHANGED
@@ -36,6 +36,7 @@ Renders notice lists for notices with type `default`:
36
36
  _Props_
37
37
 
38
38
  - `children: ReactNode` (optional): Additional content rendered in the dismissible notice list.
39
+ - `className: string` (optional): Extra class name added to the inline notices wrapper.
39
40
  - `pinnedNoticesClassName: string` (optional): Extra class name added to the pinned list.
40
41
  - `dismissibleNoticesClassName: string` (optional): Extra class name added to the dismissible list.
41
42
  - `context: string` (optional): Notice context to read and remove notices from. Defaults to `default`.
@@ -37,19 +37,13 @@ var import_clsx = __toESM(require("clsx"));
37
37
  var import_components = require("@wordpress/components");
38
38
  var import_data = require("@wordpress/data");
39
39
  var import_store = require("../../store/index.cjs");
40
-
41
- // packages/notices/src/components/inline-notices/style.scss
42
- if (typeof document !== "undefined" && process.env.NODE_ENV !== "test" && !document.head.querySelector("style[data-wp-hash='2c1d02983b']")) {
43
- const style = document.createElement("style");
44
- style.setAttribute("data-wp-hash", "2c1d02983b");
45
- style.appendChild(document.createTextNode(".components-notices__dismissible,.components-notices__pinned{color:#1e1e1e}.components-notices__dismissible .components-notice,.components-notices__pinned .components-notice{border-bottom:1px solid #0003;box-sizing:border-box;min-height:64px;padding:0 12px}.components-notices__dismissible .components-notice .components-notice__dismiss,.components-notices__pinned .components-notice .components-notice__dismiss{margin-top:12px}"));
46
- document.head.appendChild(style);
47
- }
48
-
49
- // packages/notices/src/components/inline-notices/index.tsx
50
40
  var import_jsx_runtime = require("react/jsx-runtime");
41
+ function hasRenderableChildren(children) {
42
+ return children !== null && children !== void 0 && children !== false && children !== "";
43
+ }
51
44
  function InlineNotices({
52
45
  children,
46
+ className,
53
47
  pinnedNoticesClassName,
54
48
  dismissibleNoticesClassName,
55
49
  context
@@ -65,8 +59,13 @@ function InlineNotices({
65
59
  const nonDismissibleNotices = notices.filter(
66
60
  ({ isDismissible, type }) => !isDismissible && type === "default"
67
61
  );
68
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
69
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
62
+ const hasPinnedNotices = nonDismissibleNotices.length > 0;
63
+ const hasDismissibleNotices = dismissibleNotices.length > 0 || hasRenderableChildren(children);
64
+ if (!hasPinnedNotices && !hasDismissibleNotices) {
65
+ return null;
66
+ }
67
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: (0, import_clsx.default)("notices-inline-notices-wrapper", className), children: [
68
+ hasPinnedNotices && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
70
69
  import_components.NoticeList,
71
70
  {
72
71
  notices: nonDismissibleNotices,
@@ -76,7 +75,7 @@ function InlineNotices({
76
75
  )
77
76
  }
78
77
  ),
79
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
78
+ hasDismissibleNotices && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
80
79
  import_components.NoticeList,
81
80
  {
82
81
  notices: dismissibleNotices,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../../../src/components/inline-notices/index.tsx", "../../../src/components/inline-notices/style.scss"],
4
- "sourcesContent": ["/**\n * External dependencies\n */\nimport type { ReactNode } from 'react';\nimport clsx from 'clsx';\n\n/**\n * WordPress dependencies\n */\nimport { NoticeList } from '@wordpress/components';\nimport { useDispatch, useSelect } from '@wordpress/data';\n\n/**\n * Internal dependencies\n */\nimport { store as noticesStore } from '../../store';\nimport './style.scss';\n\ntype InlineNoticesProps = {\n\tchildren?: ReactNode;\n\tpinnedNoticesClassName?: string;\n\tdismissibleNoticesClassName?: string;\n\tcontext?: string;\n};\n\nexport default function InlineNotices( {\n\tchildren,\n\tpinnedNoticesClassName,\n\tdismissibleNoticesClassName,\n\tcontext,\n}: InlineNoticesProps ) {\n\tconst notices = useSelect(\n\t\t( select ) => select( noticesStore ).getNotices( context ),\n\t\t[ context ]\n\t);\n\tconst { removeNotice } = useDispatch( noticesStore );\n\tconst dismissibleNotices = notices.filter(\n\t\t( { isDismissible, type } ) => isDismissible && type === 'default'\n\t);\n\tconst nonDismissibleNotices = notices.filter(\n\t\t( { isDismissible, type } ) => ! isDismissible && type === 'default'\n\t);\n\n\treturn (\n\t\t<>\n\t\t\t<NoticeList\n\t\t\t\tnotices={ nonDismissibleNotices }\n\t\t\t\tclassName={ clsx(\n\t\t\t\t\t'components-notices__pinned',\n\t\t\t\t\tpinnedNoticesClassName\n\t\t\t\t) }\n\t\t\t/>\n\t\t\t<NoticeList\n\t\t\t\tnotices={ dismissibleNotices }\n\t\t\t\tclassName={ clsx(\n\t\t\t\t\t'components-notices__dismissible',\n\t\t\t\t\tdismissibleNoticesClassName\n\t\t\t\t) }\n\t\t\t\tonRemove={ ( id ) => removeNotice( id, context ) }\n\t\t\t>\n\t\t\t\t{ children }\n\t\t\t</NoticeList>\n\t\t</>\n\t);\n}\n", "if (typeof document !== 'undefined' && process.env.NODE_ENV !== 'test' && !document.head.querySelector(\"style[data-wp-hash='2c1d02983b']\")) {\n\tconst style = document.createElement(\"style\");\n\tstyle.setAttribute(\"data-wp-hash\", \"2c1d02983b\");\n\tstyle.appendChild(document.createTextNode(\".components-notices__dismissible,.components-notices__pinned{color:#1e1e1e}.components-notices__dismissible .components-notice,.components-notices__pinned .components-notice{border-bottom:1px solid #0003;box-sizing:border-box;min-height:64px;padding:0 12px}.components-notices__dismissible .components-notice .components-notice__dismiss,.components-notices__pinned .components-notice .components-notice__dismiss{margin-top:12px}\"));\n\tdocument.head.appendChild(style);\n}\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAIA,kBAAiB;AAKjB,wBAA2B;AAC3B,kBAAuC;AAKvC,mBAAsC;;;ACftC,IAAI,OAAO,aAAa,eAAe,QAAQ,IAAI,aAAa,UAAU,CAAC,SAAS,KAAK,cAAc,kCAAkC,GAAG;AAC3I,QAAM,QAAQ,SAAS,cAAc,OAAO;AAC5C,QAAM,aAAa,gBAAgB,YAAY;AAC/C,QAAM,YAAY,SAAS,eAAe,8aAA8a,CAAC;AACzd,WAAS,KAAK,YAAY,KAAK;AAChC;;;ADuCE;AAnBa,SAAR,cAAgC;AAAA,EACtC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACD,GAAwB;AACvB,QAAM,cAAU;AAAA,IACf,CAAE,WAAY,OAAQ,aAAAA,KAAa,EAAE,WAAY,OAAQ;AAAA,IACzD,CAAE,OAAQ;AAAA,EACX;AACA,QAAM,EAAE,aAAa,QAAI,yBAAa,aAAAA,KAAa;AACnD,QAAM,qBAAqB,QAAQ;AAAA,IAClC,CAAE,EAAE,eAAe,KAAK,MAAO,iBAAiB,SAAS;AAAA,EAC1D;AACA,QAAM,wBAAwB,QAAQ;AAAA,IACrC,CAAE,EAAE,eAAe,KAAK,MAAO,CAAE,iBAAiB,SAAS;AAAA,EAC5D;AAEA,SACC,4EACC;AAAA;AAAA,MAAC;AAAA;AAAA,QACA,SAAU;AAAA,QACV,eAAY,YAAAC;AAAA,UACX;AAAA,UACA;AAAA,QACD;AAAA;AAAA,IACD;AAAA,IACA;AAAA,MAAC;AAAA;AAAA,QACA,SAAU;AAAA,QACV,eAAY,YAAAA;AAAA,UACX;AAAA,UACA;AAAA,QACD;AAAA,QACA,UAAW,CAAE,OAAQ,aAAc,IAAI,OAAQ;AAAA,QAE7C;AAAA;AAAA,IACH;AAAA,KACD;AAEF;",
3
+ "sources": ["../../../src/components/inline-notices/index.tsx"],
4
+ "sourcesContent": ["/**\n * External dependencies\n */\nimport type { ReactNode } from 'react';\nimport clsx from 'clsx';\n\n/**\n * WordPress dependencies\n */\nimport { NoticeList } from '@wordpress/components';\nimport { useDispatch, useSelect } from '@wordpress/data';\n\n/**\n * Internal dependencies\n */\nimport { store as noticesStore } from '../../store';\n\ntype InlineNoticesProps = {\n\tchildren?: ReactNode;\n\tclassName?: string;\n\tpinnedNoticesClassName?: string;\n\tdismissibleNoticesClassName?: string;\n\tcontext?: string;\n};\n\nfunction hasRenderableChildren( children: ReactNode ): boolean {\n\treturn (\n\t\tchildren !== null &&\n\t\tchildren !== undefined &&\n\t\tchildren !== false &&\n\t\tchildren !== ''\n\t);\n}\n\nexport default function InlineNotices( {\n\tchildren,\n\tclassName,\n\tpinnedNoticesClassName,\n\tdismissibleNoticesClassName,\n\tcontext,\n}: InlineNoticesProps ) {\n\tconst notices = useSelect(\n\t\t( select ) => select( noticesStore ).getNotices( context ),\n\t\t[ context ]\n\t);\n\tconst { removeNotice } = useDispatch( noticesStore );\n\tconst dismissibleNotices = notices.filter(\n\t\t( { isDismissible, type } ) => isDismissible && type === 'default'\n\t);\n\tconst nonDismissibleNotices = notices.filter(\n\t\t( { isDismissible, type } ) => ! isDismissible && type === 'default'\n\t);\n\n\tconst hasPinnedNotices = nonDismissibleNotices.length > 0;\n\tconst hasDismissibleNotices =\n\t\tdismissibleNotices.length > 0 || hasRenderableChildren( children );\n\n\tif ( ! hasPinnedNotices && ! hasDismissibleNotices ) {\n\t\treturn null;\n\t}\n\n\treturn (\n\t\t<div className={ clsx( 'notices-inline-notices-wrapper', className ) }>\n\t\t\t{ hasPinnedNotices && (\n\t\t\t\t<NoticeList\n\t\t\t\t\tnotices={ nonDismissibleNotices }\n\t\t\t\t\tclassName={ clsx(\n\t\t\t\t\t\t'components-notices__pinned',\n\t\t\t\t\t\tpinnedNoticesClassName\n\t\t\t\t\t) }\n\t\t\t\t/>\n\t\t\t) }\n\t\t\t{ hasDismissibleNotices && (\n\t\t\t\t<NoticeList\n\t\t\t\t\tnotices={ dismissibleNotices }\n\t\t\t\t\tclassName={ clsx(\n\t\t\t\t\t\t'components-notices__dismissible',\n\t\t\t\t\t\tdismissibleNoticesClassName\n\t\t\t\t\t) }\n\t\t\t\t\tonRemove={ ( id ) => removeNotice( id, context ) }\n\t\t\t\t>\n\t\t\t\t\t{ children }\n\t\t\t\t</NoticeList>\n\t\t\t) }\n\t\t</div>\n\t);\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAIA,kBAAiB;AAKjB,wBAA2B;AAC3B,kBAAuC;AAKvC,mBAAsC;AA+CpC;AArCF,SAAS,sBAAuB,UAA+B;AAC9D,SACC,aAAa,QACb,aAAa,UACb,aAAa,SACb,aAAa;AAEf;AAEe,SAAR,cAAgC;AAAA,EACtC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACD,GAAwB;AACvB,QAAM,cAAU;AAAA,IACf,CAAE,WAAY,OAAQ,aAAAA,KAAa,EAAE,WAAY,OAAQ;AAAA,IACzD,CAAE,OAAQ;AAAA,EACX;AACA,QAAM,EAAE,aAAa,QAAI,yBAAa,aAAAA,KAAa;AACnD,QAAM,qBAAqB,QAAQ;AAAA,IAClC,CAAE,EAAE,eAAe,KAAK,MAAO,iBAAiB,SAAS;AAAA,EAC1D;AACA,QAAM,wBAAwB,QAAQ;AAAA,IACrC,CAAE,EAAE,eAAe,KAAK,MAAO,CAAE,iBAAiB,SAAS;AAAA,EAC5D;AAEA,QAAM,mBAAmB,sBAAsB,SAAS;AACxD,QAAM,wBACL,mBAAmB,SAAS,KAAK,sBAAuB,QAAS;AAElE,MAAK,CAAE,oBAAoB,CAAE,uBAAwB;AACpD,WAAO;AAAA,EACR;AAEA,SACC,6CAAC,SAAI,eAAY,YAAAC,SAAM,kCAAkC,SAAU,GAChE;AAAA,wBACD;AAAA,MAAC;AAAA;AAAA,QACA,SAAU;AAAA,QACV,eAAY,YAAAA;AAAA,UACX;AAAA,UACA;AAAA,QACD;AAAA;AAAA,IACD;AAAA,IAEC,yBACD;AAAA,MAAC;AAAA;AAAA,QACA,SAAU;AAAA,QACV,eAAY,YAAAA;AAAA,UACX;AAAA,UACA;AAAA,QACD;AAAA,QACA,UAAW,CAAE,OAAQ,aAAc,IAAI,OAAQ;AAAA,QAE7C;AAAA;AAAA,IACH;AAAA,KAEF;AAEF;",
6
6
  "names": ["noticesStore", "clsx"]
7
7
  }
@@ -3,19 +3,13 @@ import clsx from "clsx";
3
3
  import { NoticeList } from "@wordpress/components";
4
4
  import { useDispatch, useSelect } from "@wordpress/data";
5
5
  import { store as noticesStore } from "../../store/index.mjs";
6
-
7
- // packages/notices/src/components/inline-notices/style.scss
8
- if (typeof document !== "undefined" && process.env.NODE_ENV !== "test" && !document.head.querySelector("style[data-wp-hash='2c1d02983b']")) {
9
- const style = document.createElement("style");
10
- style.setAttribute("data-wp-hash", "2c1d02983b");
11
- style.appendChild(document.createTextNode(".components-notices__dismissible,.components-notices__pinned{color:#1e1e1e}.components-notices__dismissible .components-notice,.components-notices__pinned .components-notice{border-bottom:1px solid #0003;box-sizing:border-box;min-height:64px;padding:0 12px}.components-notices__dismissible .components-notice .components-notice__dismiss,.components-notices__pinned .components-notice .components-notice__dismiss{margin-top:12px}"));
12
- document.head.appendChild(style);
6
+ import { jsx, jsxs } from "react/jsx-runtime";
7
+ function hasRenderableChildren(children) {
8
+ return children !== null && children !== void 0 && children !== false && children !== "";
13
9
  }
14
-
15
- // packages/notices/src/components/inline-notices/index.tsx
16
- import { Fragment, jsx, jsxs } from "react/jsx-runtime";
17
10
  function InlineNotices({
18
11
  children,
12
+ className,
19
13
  pinnedNoticesClassName,
20
14
  dismissibleNoticesClassName,
21
15
  context
@@ -31,8 +25,13 @@ function InlineNotices({
31
25
  const nonDismissibleNotices = notices.filter(
32
26
  ({ isDismissible, type }) => !isDismissible && type === "default"
33
27
  );
34
- return /* @__PURE__ */ jsxs(Fragment, { children: [
35
- /* @__PURE__ */ jsx(
28
+ const hasPinnedNotices = nonDismissibleNotices.length > 0;
29
+ const hasDismissibleNotices = dismissibleNotices.length > 0 || hasRenderableChildren(children);
30
+ if (!hasPinnedNotices && !hasDismissibleNotices) {
31
+ return null;
32
+ }
33
+ return /* @__PURE__ */ jsxs("div", { className: clsx("notices-inline-notices-wrapper", className), children: [
34
+ hasPinnedNotices && /* @__PURE__ */ jsx(
36
35
  NoticeList,
37
36
  {
38
37
  notices: nonDismissibleNotices,
@@ -42,7 +41,7 @@ function InlineNotices({
42
41
  )
43
42
  }
44
43
  ),
45
- /* @__PURE__ */ jsx(
44
+ hasDismissibleNotices && /* @__PURE__ */ jsx(
46
45
  NoticeList,
47
46
  {
48
47
  notices: dismissibleNotices,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../../../src/components/inline-notices/index.tsx", "../../../src/components/inline-notices/style.scss"],
4
- "sourcesContent": ["/**\n * External dependencies\n */\nimport type { ReactNode } from 'react';\nimport clsx from 'clsx';\n\n/**\n * WordPress dependencies\n */\nimport { NoticeList } from '@wordpress/components';\nimport { useDispatch, useSelect } from '@wordpress/data';\n\n/**\n * Internal dependencies\n */\nimport { store as noticesStore } from '../../store';\nimport './style.scss';\n\ntype InlineNoticesProps = {\n\tchildren?: ReactNode;\n\tpinnedNoticesClassName?: string;\n\tdismissibleNoticesClassName?: string;\n\tcontext?: string;\n};\n\nexport default function InlineNotices( {\n\tchildren,\n\tpinnedNoticesClassName,\n\tdismissibleNoticesClassName,\n\tcontext,\n}: InlineNoticesProps ) {\n\tconst notices = useSelect(\n\t\t( select ) => select( noticesStore ).getNotices( context ),\n\t\t[ context ]\n\t);\n\tconst { removeNotice } = useDispatch( noticesStore );\n\tconst dismissibleNotices = notices.filter(\n\t\t( { isDismissible, type } ) => isDismissible && type === 'default'\n\t);\n\tconst nonDismissibleNotices = notices.filter(\n\t\t( { isDismissible, type } ) => ! isDismissible && type === 'default'\n\t);\n\n\treturn (\n\t\t<>\n\t\t\t<NoticeList\n\t\t\t\tnotices={ nonDismissibleNotices }\n\t\t\t\tclassName={ clsx(\n\t\t\t\t\t'components-notices__pinned',\n\t\t\t\t\tpinnedNoticesClassName\n\t\t\t\t) }\n\t\t\t/>\n\t\t\t<NoticeList\n\t\t\t\tnotices={ dismissibleNotices }\n\t\t\t\tclassName={ clsx(\n\t\t\t\t\t'components-notices__dismissible',\n\t\t\t\t\tdismissibleNoticesClassName\n\t\t\t\t) }\n\t\t\t\tonRemove={ ( id ) => removeNotice( id, context ) }\n\t\t\t>\n\t\t\t\t{ children }\n\t\t\t</NoticeList>\n\t\t</>\n\t);\n}\n", "if (typeof document !== 'undefined' && process.env.NODE_ENV !== 'test' && !document.head.querySelector(\"style[data-wp-hash='2c1d02983b']\")) {\n\tconst style = document.createElement(\"style\");\n\tstyle.setAttribute(\"data-wp-hash\", \"2c1d02983b\");\n\tstyle.appendChild(document.createTextNode(\".components-notices__dismissible,.components-notices__pinned{color:#1e1e1e}.components-notices__dismissible .components-notice,.components-notices__pinned .components-notice{border-bottom:1px solid #0003;box-sizing:border-box;min-height:64px;padding:0 12px}.components-notices__dismissible .components-notice .components-notice__dismiss,.components-notices__pinned .components-notice .components-notice__dismiss{margin-top:12px}\"));\n\tdocument.head.appendChild(style);\n}\n"],
5
- "mappings": ";AAIA,OAAO,UAAU;AAKjB,SAAS,kBAAkB;AAC3B,SAAS,aAAa,iBAAiB;AAKvC,SAAS,SAAS,oBAAoB;;;ACftC,IAAI,OAAO,aAAa,eAAe,QAAQ,IAAI,aAAa,UAAU,CAAC,SAAS,KAAK,cAAc,kCAAkC,GAAG;AAC3I,QAAM,QAAQ,SAAS,cAAc,OAAO;AAC5C,QAAM,aAAa,gBAAgB,YAAY;AAC/C,QAAM,YAAY,SAAS,eAAe,8aAA8a,CAAC;AACzd,WAAS,KAAK,YAAY,KAAK;AAChC;;;ADuCE,mBACC,KADD;AAnBa,SAAR,cAAgC;AAAA,EACtC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACD,GAAwB;AACvB,QAAM,UAAU;AAAA,IACf,CAAE,WAAY,OAAQ,YAAa,EAAE,WAAY,OAAQ;AAAA,IACzD,CAAE,OAAQ;AAAA,EACX;AACA,QAAM,EAAE,aAAa,IAAI,YAAa,YAAa;AACnD,QAAM,qBAAqB,QAAQ;AAAA,IAClC,CAAE,EAAE,eAAe,KAAK,MAAO,iBAAiB,SAAS;AAAA,EAC1D;AACA,QAAM,wBAAwB,QAAQ;AAAA,IACrC,CAAE,EAAE,eAAe,KAAK,MAAO,CAAE,iBAAiB,SAAS;AAAA,EAC5D;AAEA,SACC,iCACC;AAAA;AAAA,MAAC;AAAA;AAAA,QACA,SAAU;AAAA,QACV,WAAY;AAAA,UACX;AAAA,UACA;AAAA,QACD;AAAA;AAAA,IACD;AAAA,IACA;AAAA,MAAC;AAAA;AAAA,QACA,SAAU;AAAA,QACV,WAAY;AAAA,UACX;AAAA,UACA;AAAA,QACD;AAAA,QACA,UAAW,CAAE,OAAQ,aAAc,IAAI,OAAQ;AAAA,QAE7C;AAAA;AAAA,IACH;AAAA,KACD;AAEF;",
3
+ "sources": ["../../../src/components/inline-notices/index.tsx"],
4
+ "sourcesContent": ["/**\n * External dependencies\n */\nimport type { ReactNode } from 'react';\nimport clsx from 'clsx';\n\n/**\n * WordPress dependencies\n */\nimport { NoticeList } from '@wordpress/components';\nimport { useDispatch, useSelect } from '@wordpress/data';\n\n/**\n * Internal dependencies\n */\nimport { store as noticesStore } from '../../store';\n\ntype InlineNoticesProps = {\n\tchildren?: ReactNode;\n\tclassName?: string;\n\tpinnedNoticesClassName?: string;\n\tdismissibleNoticesClassName?: string;\n\tcontext?: string;\n};\n\nfunction hasRenderableChildren( children: ReactNode ): boolean {\n\treturn (\n\t\tchildren !== null &&\n\t\tchildren !== undefined &&\n\t\tchildren !== false &&\n\t\tchildren !== ''\n\t);\n}\n\nexport default function InlineNotices( {\n\tchildren,\n\tclassName,\n\tpinnedNoticesClassName,\n\tdismissibleNoticesClassName,\n\tcontext,\n}: InlineNoticesProps ) {\n\tconst notices = useSelect(\n\t\t( select ) => select( noticesStore ).getNotices( context ),\n\t\t[ context ]\n\t);\n\tconst { removeNotice } = useDispatch( noticesStore );\n\tconst dismissibleNotices = notices.filter(\n\t\t( { isDismissible, type } ) => isDismissible && type === 'default'\n\t);\n\tconst nonDismissibleNotices = notices.filter(\n\t\t( { isDismissible, type } ) => ! isDismissible && type === 'default'\n\t);\n\n\tconst hasPinnedNotices = nonDismissibleNotices.length > 0;\n\tconst hasDismissibleNotices =\n\t\tdismissibleNotices.length > 0 || hasRenderableChildren( children );\n\n\tif ( ! hasPinnedNotices && ! hasDismissibleNotices ) {\n\t\treturn null;\n\t}\n\n\treturn (\n\t\t<div className={ clsx( 'notices-inline-notices-wrapper', className ) }>\n\t\t\t{ hasPinnedNotices && (\n\t\t\t\t<NoticeList\n\t\t\t\t\tnotices={ nonDismissibleNotices }\n\t\t\t\t\tclassName={ clsx(\n\t\t\t\t\t\t'components-notices__pinned',\n\t\t\t\t\t\tpinnedNoticesClassName\n\t\t\t\t\t) }\n\t\t\t\t/>\n\t\t\t) }\n\t\t\t{ hasDismissibleNotices && (\n\t\t\t\t<NoticeList\n\t\t\t\t\tnotices={ dismissibleNotices }\n\t\t\t\t\tclassName={ clsx(\n\t\t\t\t\t\t'components-notices__dismissible',\n\t\t\t\t\t\tdismissibleNoticesClassName\n\t\t\t\t\t) }\n\t\t\t\t\tonRemove={ ( id ) => removeNotice( id, context ) }\n\t\t\t\t>\n\t\t\t\t\t{ children }\n\t\t\t\t</NoticeList>\n\t\t\t) }\n\t\t</div>\n\t);\n}\n"],
5
+ "mappings": ";AAIA,OAAO,UAAU;AAKjB,SAAS,kBAAkB;AAC3B,SAAS,aAAa,iBAAiB;AAKvC,SAAS,SAAS,oBAAoB;AA+CpC,SAEE,KAFF;AArCF,SAAS,sBAAuB,UAA+B;AAC9D,SACC,aAAa,QACb,aAAa,UACb,aAAa,SACb,aAAa;AAEf;AAEe,SAAR,cAAgC;AAAA,EACtC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACD,GAAwB;AACvB,QAAM,UAAU;AAAA,IACf,CAAE,WAAY,OAAQ,YAAa,EAAE,WAAY,OAAQ;AAAA,IACzD,CAAE,OAAQ;AAAA,EACX;AACA,QAAM,EAAE,aAAa,IAAI,YAAa,YAAa;AACnD,QAAM,qBAAqB,QAAQ;AAAA,IAClC,CAAE,EAAE,eAAe,KAAK,MAAO,iBAAiB,SAAS;AAAA,EAC1D;AACA,QAAM,wBAAwB,QAAQ;AAAA,IACrC,CAAE,EAAE,eAAe,KAAK,MAAO,CAAE,iBAAiB,SAAS;AAAA,EAC5D;AAEA,QAAM,mBAAmB,sBAAsB,SAAS;AACxD,QAAM,wBACL,mBAAmB,SAAS,KAAK,sBAAuB,QAAS;AAElE,MAAK,CAAE,oBAAoB,CAAE,uBAAwB;AACpD,WAAO;AAAA,EACR;AAEA,SACC,qBAAC,SAAI,WAAY,KAAM,kCAAkC,SAAU,GAChE;AAAA,wBACD;AAAA,MAAC;AAAA;AAAA,QACA,SAAU;AAAA,QACV,WAAY;AAAA,UACX;AAAA,UACA;AAAA,QACD;AAAA;AAAA,IACD;AAAA,IAEC,yBACD;AAAA,MAAC;AAAA;AAAA,QACA,SAAU;AAAA,QACV,WAAY;AAAA,UACX;AAAA,UACA;AAAA,QACD;AAAA,QACA,UAAW,CAAE,OAAQ,aAAc,IAAI,OAAQ;AAAA,QAE7C;AAAA;AAAA,IACH;AAAA,KAEF;AAEF;",
6
6
  "names": []
7
7
  }
@@ -0,0 +1,5 @@
1
+ .notices-inline-notices-wrapper {
2
+ display: flex;
3
+ flex-direction: column;
4
+ gap: var(--wpds-dimension-gap-md, 12px);
5
+ }
@@ -0,0 +1,5 @@
1
+ .notices-inline-notices-wrapper {
2
+ display: flex;
3
+ flex-direction: column;
4
+ gap: var(--wpds-dimension-gap-md, 12px);
5
+ }
@@ -2,13 +2,13 @@
2
2
  * External dependencies
3
3
  */
4
4
  import type { ReactNode } from 'react';
5
- import './style.scss';
6
5
  type InlineNoticesProps = {
7
6
  children?: ReactNode;
7
+ className?: string;
8
8
  pinnedNoticesClassName?: string;
9
9
  dismissibleNoticesClassName?: string;
10
10
  context?: string;
11
11
  };
12
- export default function InlineNotices({ children, pinnedNoticesClassName, dismissibleNoticesClassName, context }: InlineNoticesProps): import("react").JSX.Element;
12
+ export default function InlineNotices({ children, className, pinnedNoticesClassName, dismissibleNoticesClassName, context }: InlineNoticesProps): import("react").JSX.Element | null;
13
13
  export {};
14
14
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/inline-notices/index.tsx"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAavC,OAAO,cAAc,CAAC;AAEtB,KAAK,kBAAkB,GAAG;IACzB,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,2BAA2B,CAAC,EAAE,MAAM,CAAC;IACrC,OAAO,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,MAAM,CAAC,OAAO,UAAU,aAAa,CAAE,EACtC,QAAQ,EACR,sBAAsB,EACtB,2BAA2B,EAC3B,OAAO,EACP,EAAE,kBAAkB,+BAkCpB"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/inline-notices/index.tsx"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAcvC,KAAK,kBAAkB,GAAG;IACzB,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,2BAA2B,CAAC,EAAE,MAAM,CAAC;IACrC,OAAO,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAWF,MAAM,CAAC,OAAO,UAAU,aAAa,CAAE,EACtC,QAAQ,EACR,SAAS,EACT,sBAAsB,EACtB,2BAA2B,EAC3B,OAAO,EACP,EAAE,kBAAkB,sCA8CpB"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wordpress/notices",
3
- "version": "5.46.0",
3
+ "version": "5.47.0",
4
4
  "description": "State management for notices.",
5
5
  "author": "The WordPress Contributors",
6
6
  "license": "GPL-2.0-or-later",
@@ -26,6 +26,7 @@
26
26
  "src",
27
27
  "build",
28
28
  "build-module",
29
+ "build-style",
29
30
  "build-types",
30
31
  "*.md"
31
32
  ],
@@ -37,25 +38,30 @@
37
38
  "import": "./build-module/index.mjs",
38
39
  "require": "./build/index.cjs"
39
40
  },
40
- "./package.json": "./package.json"
41
+ "./package.json": "./package.json",
42
+ "./build-style/": "./build-style/"
41
43
  },
42
44
  "react-native": "src/index",
43
45
  "wpScript": true,
44
46
  "types": "build-types",
47
+ "sideEffects": [
48
+ "build-style/**",
49
+ "src/**/*.scss"
50
+ ],
45
51
  "dependencies": {
46
- "@wordpress/a11y": "^4.46.0",
47
- "@wordpress/components": "^33.1.0",
48
- "@wordpress/data": "^10.46.0",
52
+ "@wordpress/a11y": "^4.47.0",
53
+ "@wordpress/components": "^34.0.0",
54
+ "@wordpress/data": "^10.47.0",
49
55
  "clsx": "^2.1.1"
50
56
  },
51
57
  "devDependencies": {
52
58
  "deep-freeze": "0.0.1"
53
59
  },
54
60
  "peerDependencies": {
55
- "react": "^18.0.0"
61
+ "react": "^19.2.4"
56
62
  },
57
63
  "publishConfig": {
58
64
  "access": "public"
59
65
  },
60
- "gitHead": "51264e33b95fadff9a06b68141e674ce9cde9675"
66
+ "gitHead": "d653c5fd6161571a0c2ebde28553d6e25624eacc"
61
67
  }
@@ -14,17 +14,27 @@ import { useDispatch, useSelect } from '@wordpress/data';
14
14
  * Internal dependencies
15
15
  */
16
16
  import { store as noticesStore } from '../../store';
17
- import './style.scss';
18
17
 
19
18
  type InlineNoticesProps = {
20
19
  children?: ReactNode;
20
+ className?: string;
21
21
  pinnedNoticesClassName?: string;
22
22
  dismissibleNoticesClassName?: string;
23
23
  context?: string;
24
24
  };
25
25
 
26
+ function hasRenderableChildren( children: ReactNode ): boolean {
27
+ return (
28
+ children !== null &&
29
+ children !== undefined &&
30
+ children !== false &&
31
+ children !== ''
32
+ );
33
+ }
34
+
26
35
  export default function InlineNotices( {
27
36
  children,
37
+ className,
28
38
  pinnedNoticesClassName,
29
39
  dismissibleNoticesClassName,
30
40
  context,
@@ -41,25 +51,37 @@ export default function InlineNotices( {
41
51
  ( { isDismissible, type } ) => ! isDismissible && type === 'default'
42
52
  );
43
53
 
54
+ const hasPinnedNotices = nonDismissibleNotices.length > 0;
55
+ const hasDismissibleNotices =
56
+ dismissibleNotices.length > 0 || hasRenderableChildren( children );
57
+
58
+ if ( ! hasPinnedNotices && ! hasDismissibleNotices ) {
59
+ return null;
60
+ }
61
+
44
62
  return (
45
- <>
46
- <NoticeList
47
- notices={ nonDismissibleNotices }
48
- className={ clsx(
49
- 'components-notices__pinned',
50
- pinnedNoticesClassName
51
- ) }
52
- />
53
- <NoticeList
54
- notices={ dismissibleNotices }
55
- className={ clsx(
56
- 'components-notices__dismissible',
57
- dismissibleNoticesClassName
58
- ) }
59
- onRemove={ ( id ) => removeNotice( id, context ) }
60
- >
61
- { children }
62
- </NoticeList>
63
- </>
63
+ <div className={ clsx( 'notices-inline-notices-wrapper', className ) }>
64
+ { hasPinnedNotices && (
65
+ <NoticeList
66
+ notices={ nonDismissibleNotices }
67
+ className={ clsx(
68
+ 'components-notices__pinned',
69
+ pinnedNoticesClassName
70
+ ) }
71
+ />
72
+ ) }
73
+ { hasDismissibleNotices && (
74
+ <NoticeList
75
+ notices={ dismissibleNotices }
76
+ className={ clsx(
77
+ 'components-notices__dismissible',
78
+ dismissibleNoticesClassName
79
+ ) }
80
+ onRemove={ ( id ) => removeNotice( id, context ) }
81
+ >
82
+ { children }
83
+ </NoticeList>
84
+ ) }
85
+ </div>
64
86
  );
65
87
  }
@@ -1,21 +1,5 @@
1
- @use "@wordpress/base-styles/variables" as *;
2
- @use "@wordpress/base-styles/colors" as *;
3
-
4
- .components-notices__dismissible,
5
- .components-notices__pinned {
6
- color: $gray-900;
7
-
8
- .components-notice {
9
- box-sizing: border-box;
10
- border-bottom: $border-width solid rgba(0, 0, 0, 0.2);
11
- padding: 0 $grid-unit-15;
12
-
13
- // Min-height matches the height of a single-line notice with an action button.
14
- min-height: $header-height;
15
-
16
- // Margins ensure that the dismiss button aligns to the center of the first line of text.
17
- .components-notice__dismiss {
18
- margin-top: $grid-unit-15;
19
- }
20
- }
1
+ .notices-inline-notices-wrapper {
2
+ display: flex;
3
+ flex-direction: column;
4
+ gap: var(--wpds-dimension-gap-md);
21
5
  }
@@ -0,0 +1,157 @@
1
+ /**
2
+ * External dependencies
3
+ */
4
+ import { render, screen, within } from '@testing-library/react';
5
+
6
+ /**
7
+ * WordPress dependencies
8
+ */
9
+ import { createRegistry, RegistryProvider } from '@wordpress/data';
10
+
11
+ /**
12
+ * Internal dependencies
13
+ */
14
+ import InlineNotices from '../index';
15
+ import { store as noticesStore } from '../../../store';
16
+
17
+ function getInlineNoticesWrapper( container: HTMLElement ) {
18
+ return container.firstChild as HTMLElement;
19
+ }
20
+
21
+ function renderInlineNotices( props = {} ) {
22
+ const registry = createRegistry();
23
+ registry.register( noticesStore );
24
+
25
+ const view = render(
26
+ <RegistryProvider value={ registry }>
27
+ <InlineNotices { ...props } />
28
+ </RegistryProvider>
29
+ );
30
+
31
+ return { registry, ...view };
32
+ }
33
+
34
+ describe( 'InlineNotices', () => {
35
+ it( 'should return null when there are no notices and no children', () => {
36
+ const { container } = renderInlineNotices();
37
+
38
+ expect( container ).toBeEmptyDOMElement();
39
+ } );
40
+
41
+ it( 'should return null when children is false and there are no notices', () => {
42
+ const { container } = renderInlineNotices( {
43
+ children: false,
44
+ } );
45
+
46
+ expect( container ).toBeEmptyDOMElement();
47
+ } );
48
+
49
+ it( 'should render the inline notices wrapper with a custom class name', () => {
50
+ const { container } = renderInlineNotices( {
51
+ className: 'my-inline-notices',
52
+ children: <div>Extra notice</div>,
53
+ } );
54
+
55
+ expect( getInlineNoticesWrapper( container ) ).toHaveClass(
56
+ 'notices-inline-notices-wrapper',
57
+ 'my-inline-notices'
58
+ );
59
+ } );
60
+
61
+ it( 'renders pinned notices without a close button', () => {
62
+ const registry = createRegistry();
63
+ registry.register( noticesStore );
64
+ registry
65
+ .dispatch( noticesStore )
66
+ .createNotice( 'warning', 'Pinned notice', {
67
+ isDismissible: false,
68
+ } );
69
+
70
+ const { container } = render(
71
+ <RegistryProvider value={ registry }>
72
+ <InlineNotices />
73
+ </RegistryProvider>
74
+ );
75
+
76
+ expect(
77
+ within( getInlineNoticesWrapper( container ) ).getByText(
78
+ 'Pinned notice'
79
+ )
80
+ ).toBeInTheDocument();
81
+ expect(
82
+ screen.queryByRole( 'button', { name: 'Close' } )
83
+ ).not.toBeInTheDocument();
84
+ } );
85
+
86
+ it( 'renders dismissible notices with a close button', () => {
87
+ const registry = createRegistry();
88
+ registry.register( noticesStore );
89
+ registry
90
+ .dispatch( noticesStore )
91
+ .createNotice( 'warning', 'Dismissible notice' );
92
+
93
+ render(
94
+ <RegistryProvider value={ registry }>
95
+ <InlineNotices />
96
+ </RegistryProvider>
97
+ );
98
+
99
+ expect(
100
+ screen.getByRole( 'button', { name: 'Close' } )
101
+ ).toBeInTheDocument();
102
+ } );
103
+
104
+ it( 'partitions pinned and dismissible notices into separate lists', () => {
105
+ const registry = createRegistry();
106
+ registry.register( noticesStore );
107
+ registry
108
+ .dispatch( noticesStore )
109
+ .createNotice( 'warning', 'Pinned notice', {
110
+ isDismissible: false,
111
+ } );
112
+ registry
113
+ .dispatch( noticesStore )
114
+ .createNotice( 'success', 'Dismissible notice' );
115
+
116
+ const { container } = render(
117
+ <RegistryProvider value={ registry }>
118
+ <InlineNotices
119
+ pinnedNoticesClassName="test-pinned"
120
+ dismissibleNoticesClassName="test-dismissible"
121
+ />
122
+ </RegistryProvider>
123
+ );
124
+
125
+ // eslint-disable-next-line testing-library/no-container, testing-library/no-node-access -- partition via public className props.
126
+ const pinned = container.querySelector( '.test-pinned' )!;
127
+ // eslint-disable-next-line testing-library/no-container, testing-library/no-node-access -- partition via public className props.
128
+ const dismissible = container.querySelector( '.test-dismissible' )!;
129
+
130
+ expect(
131
+ within( pinned ).getByText( 'Pinned notice' )
132
+ ).toBeInTheDocument();
133
+ expect(
134
+ within( pinned ).queryByText( 'Dismissible notice' )
135
+ ).not.toBeInTheDocument();
136
+ expect(
137
+ within( dismissible ).getByText( 'Dismissible notice' )
138
+ ).toBeInTheDocument();
139
+ expect(
140
+ within( dismissible ).queryByText( 'Pinned notice' )
141
+ ).not.toBeInTheDocument();
142
+ } );
143
+
144
+ it( 'renders children in the dismissible list', () => {
145
+ const { container } = renderInlineNotices( {
146
+ children: <div>Extra notice</div>,
147
+ dismissibleNoticesClassName: 'test-dismissible',
148
+ } );
149
+
150
+ // eslint-disable-next-line testing-library/no-container, testing-library/no-node-access -- partition via public className props.
151
+ const dismissible = container.querySelector( '.test-dismissible' )!;
152
+
153
+ expect(
154
+ within( dismissible ).getByText( 'Extra notice' )
155
+ ).toBeInTheDocument();
156
+ } );
157
+ } );
package/src/style.scss ADDED
@@ -0,0 +1 @@
1
+ @use "./components/inline-notices/style.scss" as *;