diff --git a/.eslintrc.js b/.eslintrc.js
index 484387a285e78..caf01b7cbd71d 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -330,6 +330,7 @@ module.exports = {
'SelectControl',
'TextControl',
'ToggleGroupControl',
+ 'UnitControl',
].map( ( componentName ) => ( {
// Falsy `__next40pxDefaultSize` without a non-default `size` prop.
selector: `JSXOpeningElement[name.name="${ componentName }"]:not(:has(JSXAttribute[name.name="__next40pxDefaultSize"][value.expression.value!=false])):not(:has(JSXAttribute[name.name="size"][value.value!="default"]))`,
@@ -345,7 +346,7 @@ module.exports = {
'FormFileUpload should have the `__next40pxDefaultSize` prop to opt-in to the new default size.',
},
// Temporary rules until all existing components have the `__next40pxDefaultSize` prop.
- ...[ 'Button', 'UnitControl' ].map( ( componentName ) => ( {
+ ...[ 'Button' ].map( ( componentName ) => ( {
// Not strict. Allows pre-existing __next40pxDefaultSize={ false } usage until they are all manually updated.
selector: `JSXOpeningElement[name.name="${ componentName }"]:not(:has(JSXAttribute[name.name="__next40pxDefaultSize"])):not(:has(JSXAttribute[name.name="size"]))`,
message:
diff --git a/backport-changelog/6.7/7258.md b/backport-changelog/6.7/7258.md
new file mode 100644
index 0000000000000..6714b13b70b8d
--- /dev/null
+++ b/backport-changelog/6.7/7258.md
@@ -0,0 +1,3 @@
+https://github.com/WordPress/wordpress-develop/pull/7258
+
+* https://github.com/WordPress/gutenberg/pull/64570
\ No newline at end of file
diff --git a/lib/compat/wordpress-6.7/block-bindings.php b/lib/compat/wordpress-6.7/block-bindings.php
index 398b53b340673..9e82c1843f35a 100644
--- a/lib/compat/wordpress-6.7/block-bindings.php
+++ b/lib/compat/wordpress-6.7/block-bindings.php
@@ -38,3 +38,18 @@ function gutenberg_add_server_block_bindings_sources_to_editor_settings( $editor
}
add_filter( 'block_editor_settings_all', 'gutenberg_add_server_block_bindings_sources_to_editor_settings', 10 );
+
+/**
+ * Initialize `canUpdateBlockBindings` editor setting if it doesn't exist. By default, it is `true` only for admin users.
+ *
+ * @param array $settings The block editor settings from the `block_editor_settings_all` filter.
+ * @return array The editor settings including `canUpdateBlockBindings`.
+ */
+function gutenberg_add_can_update_block_bindings_editor_setting( $editor_settings ) {
+ if ( empty( $editor_settings['canUpdateBlockBindings'] ) ) {
+ $editor_settings['canUpdateBlockBindings'] = current_user_can( 'manage_options' );
+ }
+ return $editor_settings;
+}
+
+add_filter( 'block_editor_settings_all', 'gutenberg_add_can_update_block_bindings_editor_setting', 10 );
diff --git a/lib/experimental/editor-settings.php b/lib/experimental/editor-settings.php
index c6bd99a18bf4c..919be2e6e34a4 100644
--- a/lib/experimental/editor-settings.php
+++ b/lib/experimental/editor-settings.php
@@ -28,18 +28,15 @@ function gutenberg_enable_experiments() {
if ( gutenberg_is_experiment_enabled( 'gutenberg-full-page-client-side-navigation' ) ) {
wp_add_inline_script( 'wp-block-library', 'window.__experimentalFullPageClientSideNavigation = true', 'before' );
}
- if ( $gutenberg_experiments && array_key_exists( 'gutenberg-zoomed-out-patterns-tab', $gutenberg_experiments ) ) {
- wp_add_inline_script( 'wp-block-editor', 'window.__experimentalEnableZoomedOutPatternsTab = true', 'before' );
- }
if ( $gutenberg_experiments && array_key_exists( 'gutenberg-quick-edit-dataviews', $gutenberg_experiments ) ) {
wp_add_inline_script( 'wp-block-editor', 'window.__experimentalQuickEditDataViews = true', 'before' );
}
- if ( $gutenberg_experiments && array_key_exists( 'gutenberg-block-bindings-ui', $gutenberg_experiments ) ) {
- wp_add_inline_script( 'wp-block-editor', 'window.__experimentalBlockBindingsUI = true', 'before' );
- }
if ( $gutenberg_experiments && array_key_exists( 'gutenberg-media-processing', $gutenberg_experiments ) ) {
wp_add_inline_script( 'wp-block-editor', 'window.__experimentalMediaProcessing = true', 'before' );
}
+ if ( $gutenberg_experiments && array_key_exists( 'gutenberg-zoom-out-experiment', $gutenberg_experiments ) ) {
+ wp_add_inline_script( 'wp-block-editor', 'window.__experimentalEnableZoomOutExperiment = true', 'before' );
+ }
}
add_action( 'admin_init', 'gutenberg_enable_experiments' );
diff --git a/lib/experiments-page.php b/lib/experiments-page.php
index f76dcdca7d18c..5acd5f0f19236 100644
--- a/lib/experiments-page.php
+++ b/lib/experiments-page.php
@@ -139,18 +139,6 @@ function gutenberg_initialize_experiments_settings() {
)
);
- add_settings_field(
- 'gutenberg-zoomed-out-patterns-tab',
- __( 'Enable zoomed out view when patterns are browsed in the inserter', 'gutenberg' ),
- 'gutenberg_display_experiment_field',
- 'gutenberg-experiments',
- 'gutenberg_experiments_section',
- array(
- 'label' => __( 'Enable zoomed out view when selecting a pattern category in the main inserter.', 'gutenberg' ),
- 'id' => 'gutenberg-zoomed-out-patterns-tab',
- )
- );
-
add_settings_field(
'gutenberg-new-posts-dashboard',
__( 'Redesigned posts dashboard', 'gutenberg' ),
@@ -176,29 +164,28 @@ function gutenberg_initialize_experiments_settings() {
);
add_settings_field(
- 'gutenberg-block-bindings-ui',
- __( 'UI to create block bindings', 'gutenberg' ),
+ 'gutenberg-media-processing',
+ __( 'Client-side media processing', 'gutenberg' ),
'gutenberg_display_experiment_field',
'gutenberg-experiments',
'gutenberg_experiments_section',
array(
- 'label' => __( 'Add UI to create and update block bindings in block inspector controls.', 'gutenberg' ),
- 'id' => 'gutenberg-block-bindings-ui',
+ 'label' => __( 'Enable client-side media processing.', 'gutenberg' ),
+ 'id' => 'gutenberg-media-processing',
)
);
add_settings_field(
- 'gutenberg-media-processing',
- __( 'Client-side media processing', 'gutenberg' ),
+ 'gutenberg-zoom-out-experiment',
+ __( 'Zoom out experiments', 'gutenberg' ),
'gutenberg_display_experiment_field',
'gutenberg-experiments',
'gutenberg_experiments_section',
array(
- 'label' => __( 'Enable client-side media processing.', 'gutenberg' ),
- 'id' => 'gutenberg-media-processing',
+ 'label' => __( 'Enable zoom out experiments; shows zoom out in the device preview and other zoom out experiments.', 'gutenberg' ),
+ 'id' => 'gutenberg-zoom-out-experiment',
)
);
-
register_setting(
'gutenberg-experiments',
'gutenberg-experiments'
diff --git a/package-lock.json b/package-lock.json
index a5841a06e163e..0b5b92da05fa1 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "gutenberg",
- "version": "19.1.0",
+ "version": "19.2.0-rc.1",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "gutenberg",
- "version": "19.1.0",
+ "version": "19.2.0-rc.1",
"hasInstallScript": true,
"license": "GPL-2.0-or-later",
"dependencies": {
@@ -221,6 +221,7 @@
"postcss-local-keyframes": "^0.0.2",
"prettier": "npm:wp-prettier@3.0.3",
"progress": "2.0.3",
+ "puppeteer-core": "23.1.0",
"react": "18.3.1",
"react-dom": "18.3.1",
"react-native": "0.73.3",
@@ -22569,15 +22570,6 @@
"node": ">=4.0"
}
},
- "node_modules/cross-fetch": {
- "version": "3.1.5",
- "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.5.tgz",
- "integrity": "sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw==",
- "dev": true,
- "dependencies": {
- "node-fetch": "2.6.7"
- }
- },
"node_modules/cross-spawn": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz",
@@ -24111,10 +24103,11 @@
}
},
"node_modules/devtools-protocol": {
- "version": "0.0.981744",
- "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.981744.tgz",
- "integrity": "sha512-0cuGS8+jhR67Fy7qG3i3Pc7Aw494sb9yG9QgpG97SFVWwolgYjlhJg7n+UaHxOQT30d1TYu/EYe9k01ivLErIg==",
- "dev": true
+ "version": "0.0.1312386",
+ "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1312386.tgz",
+ "integrity": "sha512-DPnhUXvmvKT2dFA/j7B+riVLUt9Q6RKJlcppojL5CoRywJJKLDYnRlw0gTFKfgDPHP5E04UoB71SxoJlVZy8FA==",
+ "dev": true,
+ "license": "BSD-3-Clause"
},
"node_modules/diff": {
"version": "4.0.2",
@@ -42325,33 +42318,120 @@
}
},
"node_modules/puppeteer-core": {
- "version": "13.7.0",
- "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-13.7.0.tgz",
- "integrity": "sha512-rXja4vcnAzFAP1OVLq/5dWNfwBGuzcOARJ6qGV7oAZhnLmVRU8G5MsdeQEAOy332ZhkIOnn9jp15R89LKHyp2Q==",
+ "version": "23.1.0",
+ "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-23.1.0.tgz",
+ "integrity": "sha512-SvAsu+xnLN2FMXE/59bp3s3WXp8ewqUGzVV4AQtml/2xmsciZnU/bXcCW+eETHPWQ6Agg2vTI7QzWXPpEARK2g==",
"dev": true,
+ "license": "Apache-2.0",
"dependencies": {
- "cross-fetch": "3.1.5",
- "debug": "4.3.4",
- "devtools-protocol": "0.0.981744",
- "extract-zip": "2.0.1",
- "https-proxy-agent": "5.0.1",
- "pkg-dir": "4.2.0",
- "progress": "2.0.3",
- "proxy-from-env": "1.1.0",
- "rimraf": "3.0.2",
- "tar-fs": "2.1.1",
- "unbzip2-stream": "1.4.3",
- "ws": "8.5.0"
+ "@puppeteer/browsers": "2.3.1",
+ "chromium-bidi": "0.6.4",
+ "debug": "^4.3.6",
+ "devtools-protocol": "0.0.1312386",
+ "typed-query-selector": "^2.12.0",
+ "ws": "^8.18.0"
},
"engines": {
- "node": ">=10.18.1"
+ "node": ">=18"
}
},
+ "node_modules/puppeteer-core/node_modules/@puppeteer/browsers": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-2.3.1.tgz",
+ "integrity": "sha512-uK7o3hHkK+naEobMSJ+2ySYyXtQkBxIH8Gn4MK9ciePjNV+Pf+PgY/W7iPzn2MTjl3stcYB5AlcTmPYw7AXDwA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "debug": "^4.3.6",
+ "extract-zip": "^2.0.1",
+ "progress": "^2.0.3",
+ "proxy-agent": "^6.4.0",
+ "semver": "^7.6.3",
+ "tar-fs": "^3.0.6",
+ "unbzip2-stream": "^1.4.3",
+ "yargs": "^17.7.2"
+ },
+ "bin": {
+ "browsers": "lib/cjs/main-cli.js"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/puppeteer-core/node_modules/agent-base": {
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz",
+ "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "debug": "^4.3.4"
+ },
+ "engines": {
+ "node": ">= 14"
+ }
+ },
+ "node_modules/puppeteer-core/node_modules/chromium-bidi": {
+ "version": "0.6.4",
+ "resolved": "https://registry.npmjs.org/chromium-bidi/-/chromium-bidi-0.6.4.tgz",
+ "integrity": "sha512-8zoq6ogmhQQkAKZVKO2ObFTl4uOkqoX1PlKQX3hZQ5E9cbUotcAb7h4pTNVAGGv8Z36PF3CtdOriEp/Rz82JqQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "mitt": "3.0.1",
+ "urlpattern-polyfill": "10.0.0",
+ "zod": "3.23.8"
+ },
+ "peerDependencies": {
+ "devtools-protocol": "*"
+ }
+ },
+ "node_modules/puppeteer-core/node_modules/cliui": {
+ "version": "8.0.1",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
+ "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "string-width": "^4.2.0",
+ "strip-ansi": "^6.0.1",
+ "wrap-ansi": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/puppeteer-core/node_modules/debug": {
+ "version": "4.3.6",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz",
+ "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ms": "2.1.2"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/puppeteer-core/node_modules/emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/puppeteer-core/node_modules/extract-zip": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz",
"integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==",
"dev": true,
+ "license": "BSD-2-Clause",
"dependencies": {
"debug": "^4.1.1",
"get-stream": "^5.1.0",
@@ -42367,99 +42447,199 @@
"@types/yauzl": "^2.9.1"
}
},
- "node_modules/puppeteer-core/node_modules/find-up": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
- "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
+ "node_modules/puppeteer-core/node_modules/http-proxy-agent": {
+ "version": "7.0.2",
+ "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz",
+ "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "locate-path": "^5.0.0",
- "path-exists": "^4.0.0"
+ "agent-base": "^7.1.0",
+ "debug": "^4.3.4"
},
"engines": {
- "node": ">=8"
+ "node": ">= 14"
}
},
- "node_modules/puppeteer-core/node_modules/locate-path": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
- "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
+ "node_modules/puppeteer-core/node_modules/https-proxy-agent": {
+ "version": "7.0.5",
+ "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz",
+ "integrity": "sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "p-locate": "^4.1.0"
+ "agent-base": "^7.0.2",
+ "debug": "4"
},
+ "engines": {
+ "node": ">= 14"
+ }
+ },
+ "node_modules/puppeteer-core/node_modules/is-fullwidth-code-point": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+ "dev": true,
+ "license": "MIT",
"engines": {
"node": ">=8"
}
},
- "node_modules/puppeteer-core/node_modules/p-limit": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
- "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
+ "node_modules/puppeteer-core/node_modules/lru-cache": {
+ "version": "7.18.3",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz",
+ "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==",
+ "dev": true,
+ "license": "ISC",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/puppeteer-core/node_modules/mitt": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.1.tgz",
+ "integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==",
"dev": true,
+ "license": "MIT"
+ },
+ "node_modules/puppeteer-core/node_modules/ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/puppeteer-core/node_modules/proxy-agent": {
+ "version": "6.4.0",
+ "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-6.4.0.tgz",
+ "integrity": "sha512-u0piLU+nCOHMgGjRbimiXmA9kM/L9EHh3zL81xCdp7m+Y2pHIsnmbdDoEDoAz5geaonNR6q6+yOPQs6n4T6sBQ==",
+ "dev": true,
+ "license": "MIT",
"dependencies": {
- "p-try": "^2.0.0"
+ "agent-base": "^7.0.2",
+ "debug": "^4.3.4",
+ "http-proxy-agent": "^7.0.1",
+ "https-proxy-agent": "^7.0.3",
+ "lru-cache": "^7.14.1",
+ "pac-proxy-agent": "^7.0.1",
+ "proxy-from-env": "^1.1.0",
+ "socks-proxy-agent": "^8.0.2"
},
"engines": {
- "node": ">=6"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
+ "node": ">= 14"
}
},
- "node_modules/puppeteer-core/node_modules/p-locate": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
- "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
+ "node_modules/puppeteer-core/node_modules/pump": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
+ "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "p-limit": "^2.2.0"
+ "end-of-stream": "^1.1.0",
+ "once": "^1.3.1"
+ }
+ },
+ "node_modules/puppeteer-core/node_modules/semver": {
+ "version": "7.6.3",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz",
+ "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==",
+ "dev": true,
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
},
"engines": {
- "node": ">=8"
+ "node": ">=10"
}
},
- "node_modules/puppeteer-core/node_modules/p-try": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
- "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
+ "node_modules/puppeteer-core/node_modules/socks-proxy-agent": {
+ "version": "8.0.4",
+ "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.4.tgz",
+ "integrity": "sha512-GNAq/eg8Udq2x0eNiFkr9gRg5bA7PXEWagQdeRX4cPSG+X/8V38v637gim9bjFptMk1QWsCTr0ttrJEiXbNnRw==",
"dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "agent-base": "^7.1.1",
+ "debug": "^4.3.4",
+ "socks": "^2.8.3"
+ },
"engines": {
- "node": ">=6"
+ "node": ">= 14"
}
},
- "node_modules/puppeteer-core/node_modules/path-exists": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
- "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
+ "node_modules/puppeteer-core/node_modules/string-width": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
"dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
"engines": {
"node": ">=8"
}
},
- "node_modules/puppeteer-core/node_modules/pkg-dir": {
- "version": "4.2.0",
- "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz",
- "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==",
+ "node_modules/puppeteer-core/node_modules/tar-fs": {
+ "version": "3.0.6",
+ "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-3.0.6.tgz",
+ "integrity": "sha512-iokBDQQkUyeXhgPYaZxmczGPhnhXZ0CmrqI+MOb/WFGS9DW5wnfrLgtjUJBvz50vQ3qfRwJ62QVoCFu8mPVu5w==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "find-up": "^4.0.0"
+ "pump": "^3.0.0",
+ "tar-stream": "^3.1.5"
+ },
+ "optionalDependencies": {
+ "bare-fs": "^2.1.1",
+ "bare-path": "^2.1.0"
+ }
+ },
+ "node_modules/puppeteer-core/node_modules/tar-stream": {
+ "version": "3.1.7",
+ "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-3.1.7.tgz",
+ "integrity": "sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "b4a": "^1.6.4",
+ "fast-fifo": "^1.2.0",
+ "streamx": "^2.15.0"
+ }
+ },
+ "node_modules/puppeteer-core/node_modules/wrap-ansi": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
+ "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
},
"engines": {
- "node": ">=8"
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
}
},
"node_modules/puppeteer-core/node_modules/ws": {
- "version": "8.5.0",
- "resolved": "https://registry.npmjs.org/ws/-/ws-8.5.0.tgz",
- "integrity": "sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==",
+ "version": "8.18.0",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz",
+ "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">=10.0.0"
},
"peerDependencies": {
"bufferutil": "^4.0.1",
- "utf-8-validate": "^5.0.2"
+ "utf-8-validate": ">=5.0.2"
},
"peerDependenciesMeta": {
"bufferutil": {
@@ -42470,6 +42650,45 @@
}
}
},
+ "node_modules/puppeteer-core/node_modules/y18n": {
+ "version": "5.0.8",
+ "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
+ "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
+ "dev": true,
+ "license": "ISC",
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/puppeteer-core/node_modules/yargs": {
+ "version": "17.7.2",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz",
+ "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "cliui": "^8.0.1",
+ "escalade": "^3.1.1",
+ "get-caller-file": "^2.0.5",
+ "require-directory": "^2.1.1",
+ "string-width": "^4.2.3",
+ "y18n": "^5.0.5",
+ "yargs-parser": "^21.1.1"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/puppeteer-core/node_modules/yargs-parser": {
+ "version": "21.1.1",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz",
+ "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==",
+ "dev": true,
+ "license": "ISC",
+ "engines": {
+ "node": ">=12"
+ }
+ },
"node_modules/pure-rand": {
"version": "6.0.2",
"resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.0.2.tgz",
@@ -48633,6 +48852,12 @@
"node": ">= 10"
}
},
+ "node_modules/typed-query-selector": {
+ "version": "2.12.0",
+ "resolved": "https://registry.npmjs.org/typed-query-selector/-/typed-query-selector-2.12.0.tgz",
+ "integrity": "sha512-SbklCd1F0EiZOyPiW192rrHZzZ5sBijB6xM+cpmrwDqObvdtunOHHIk9fCGsoK5JVIYXoyEp4iEdE3upFH3PAg==",
+ "dev": true
+ },
"node_modules/typedarray": {
"version": "0.0.6",
"resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
@@ -49318,6 +49543,12 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/urlpattern-polyfill": {
+ "version": "10.0.0",
+ "resolved": "https://registry.npmjs.org/urlpattern-polyfill/-/urlpattern-polyfill-10.0.0.tgz",
+ "integrity": "sha512-H/A06tKD7sS1O1X2SshBVeA5FLycRpjqiBeqGKmBwBDBy28EnRjORxTNe269KSSr5un5qyWi1iL61wLxpd+ZOg==",
+ "dev": true
+ },
"node_modules/use": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz",
@@ -52052,7 +52283,7 @@
},
"packages/a11y": {
"name": "@wordpress/a11y",
- "version": "4.6.0",
+ "version": "4.7.0",
"license": "GPL-2.0-or-later",
"dependencies": {
"@babel/runtime": "^7.16.0",
@@ -52066,7 +52297,7 @@
},
"packages/annotations": {
"name": "@wordpress/annotations",
- "version": "3.6.0",
+ "version": "3.7.0",
"license": "GPL-2.0-or-later",
"dependencies": {
"@babel/runtime": "^7.16.0",
@@ -52094,7 +52325,7 @@
},
"packages/api-fetch": {
"name": "@wordpress/api-fetch",
- "version": "7.6.0",
+ "version": "7.7.0",
"license": "GPL-2.0-or-later",
"dependencies": {
"@babel/runtime": "^7.16.0",
@@ -52108,7 +52339,7 @@
},
"packages/autop": {
"name": "@wordpress/autop",
- "version": "4.6.0",
+ "version": "4.7.0",
"license": "GPL-2.0-or-later",
"dependencies": {
"@babel/runtime": "^7.16.0"
@@ -52120,7 +52351,7 @@
},
"packages/babel-plugin-import-jsx-pragma": {
"name": "@wordpress/babel-plugin-import-jsx-pragma",
- "version": "5.6.0",
+ "version": "5.7.0",
"dev": true,
"license": "GPL-2.0-or-later",
"engines": {
@@ -52133,7 +52364,7 @@
},
"packages/babel-plugin-makepot": {
"name": "@wordpress/babel-plugin-makepot",
- "version": "6.6.0",
+ "version": "6.7.0",
"dev": true,
"license": "GPL-2.0-or-later",
"dependencies": {
@@ -52151,7 +52382,7 @@
},
"packages/babel-preset-default": {
"name": "@wordpress/babel-preset-default",
- "version": "8.6.0",
+ "version": "8.7.0",
"dev": true,
"license": "GPL-2.0-or-later",
"dependencies": {
@@ -52174,7 +52405,7 @@
},
"packages/base-styles": {
"name": "@wordpress/base-styles",
- "version": "5.6.0",
+ "version": "5.7.0",
"dev": true,
"license": "GPL-2.0-or-later",
"engines": {
@@ -52184,7 +52415,7 @@
},
"packages/blob": {
"name": "@wordpress/blob",
- "version": "4.6.0",
+ "version": "4.7.0",
"license": "GPL-2.0-or-later",
"dependencies": {
"@babel/runtime": "^7.16.0"
@@ -52196,7 +52427,7 @@
},
"packages/block-directory": {
"name": "@wordpress/block-directory",
- "version": "5.6.0",
+ "version": "5.7.0",
"license": "GPL-2.0-or-later",
"dependencies": {
"@babel/runtime": "^7.16.0",
@@ -52231,7 +52462,7 @@
},
"packages/block-editor": {
"name": "@wordpress/block-editor",
- "version": "14.1.0",
+ "version": "14.2.0",
"license": "GPL-2.0-or-later",
"dependencies": {
"@babel/runtime": "^7.16.0",
@@ -52330,7 +52561,7 @@
},
"packages/block-library": {
"name": "@wordpress/block-library",
- "version": "9.6.1",
+ "version": "9.7.0",
"license": "GPL-2.0-or-later",
"dependencies": {
"@babel/runtime": "^7.16.0",
@@ -52396,7 +52627,7 @@
},
"packages/block-serialization-default-parser": {
"name": "@wordpress/block-serialization-default-parser",
- "version": "5.6.0",
+ "version": "5.7.0",
"license": "GPL-2.0-or-later",
"dependencies": {
"@babel/runtime": "^7.16.0"
@@ -52408,7 +52639,7 @@
},
"packages/block-serialization-spec-parser": {
"name": "@wordpress/block-serialization-spec-parser",
- "version": "5.6.0",
+ "version": "5.7.0",
"license": "GPL-2.0-or-later",
"dependencies": {
"pegjs": "^0.10.0",
@@ -52421,7 +52652,7 @@
},
"packages/blocks": {
"name": "@wordpress/blocks",
- "version": "13.6.0",
+ "version": "13.7.0",
"license": "GPL-2.0-or-later",
"dependencies": {
"@babel/runtime": "^7.16.0",
@@ -52475,7 +52706,7 @@
},
"packages/browserslist-config": {
"name": "@wordpress/browserslist-config",
- "version": "6.6.0",
+ "version": "6.7.0",
"dev": true,
"license": "GPL-2.0-or-later",
"engines": {
@@ -52485,7 +52716,7 @@
},
"packages/commands": {
"name": "@wordpress/commands",
- "version": "1.6.0",
+ "version": "1.7.0",
"license": "GPL-2.0-or-later",
"dependencies": {
"@babel/runtime": "^7.16.0",
@@ -52658,7 +52889,7 @@
},
"packages/components": {
"name": "@wordpress/components",
- "version": "28.6.0",
+ "version": "28.7.0",
"license": "GPL-2.0-or-later",
"dependencies": {
"@ariakit/react": "^0.4.10",
@@ -52779,7 +53010,7 @@
},
"packages/compose": {
"name": "@wordpress/compose",
- "version": "7.6.0",
+ "version": "7.7.0",
"license": "GPL-2.0-or-later",
"dependencies": {
"@babel/runtime": "^7.16.0",
@@ -52816,7 +53047,7 @@
},
"packages/core-commands": {
"name": "@wordpress/core-commands",
- "version": "1.6.0",
+ "version": "1.7.0",
"license": "GPL-2.0-or-later",
"dependencies": {
"@babel/runtime": "^7.16.0",
@@ -52844,7 +53075,7 @@
},
"packages/core-data": {
"name": "@wordpress/core-data",
- "version": "7.6.0",
+ "version": "7.7.0",
"license": "GPL-2.0-or-later",
"dependencies": {
"@babel/runtime": "^7.16.0",
@@ -52889,7 +53120,7 @@
},
"packages/create-block": {
"name": "@wordpress/create-block",
- "version": "4.49.0",
+ "version": "4.50.0",
"dev": true,
"license": "GPL-2.0-or-later",
"dependencies": {
@@ -52917,7 +53148,7 @@
},
"packages/create-block-tutorial-template": {
"name": "@wordpress/create-block-tutorial-template",
- "version": "4.6.0",
+ "version": "4.7.0",
"dev": true,
"license": "GPL-2.0-or-later",
"engines": {
@@ -52927,7 +53158,7 @@
},
"packages/customize-widgets": {
"name": "@wordpress/customize-widgets",
- "version": "5.6.1",
+ "version": "5.7.0",
"license": "GPL-2.0-or-later",
"dependencies": {
"@babel/runtime": "^7.16.0",
@@ -52965,7 +53196,7 @@
},
"packages/data": {
"name": "@wordpress/data",
- "version": "10.6.0",
+ "version": "10.7.0",
"license": "GPL-2.0-or-later",
"dependencies": {
"@babel/runtime": "^7.16.0",
@@ -52994,7 +53225,7 @@
},
"packages/data-controls": {
"name": "@wordpress/data-controls",
- "version": "4.6.0",
+ "version": "4.7.0",
"license": "GPL-2.0-or-later",
"dependencies": {
"@babel/runtime": "^7.16.0",
@@ -53012,7 +53243,7 @@
},
"packages/dataviews": {
"name": "@wordpress/dataviews",
- "version": "4.2.0",
+ "version": "4.3.0",
"license": "GPL-2.0-or-later",
"dependencies": {
"@ariakit/react": "^0.4.10",
@@ -53069,7 +53300,7 @@
},
"packages/date": {
"name": "@wordpress/date",
- "version": "5.6.0",
+ "version": "5.7.0",
"license": "GPL-2.0-or-later",
"dependencies": {
"@babel/runtime": "^7.16.0",
@@ -53084,7 +53315,7 @@
},
"packages/dependency-extraction-webpack-plugin": {
"name": "@wordpress/dependency-extraction-webpack-plugin",
- "version": "6.6.0",
+ "version": "6.7.0",
"dev": true,
"license": "GPL-2.0-or-later",
"dependencies": {
@@ -53100,7 +53331,7 @@
},
"packages/deprecated": {
"name": "@wordpress/deprecated",
- "version": "4.6.0",
+ "version": "4.7.0",
"license": "GPL-2.0-or-later",
"dependencies": {
"@babel/runtime": "^7.16.0",
@@ -53113,7 +53344,7 @@
},
"packages/docgen": {
"name": "@wordpress/docgen",
- "version": "2.6.0",
+ "version": "2.7.0",
"dev": true,
"license": "GPL-2.0-or-later",
"dependencies": {
@@ -53135,7 +53366,7 @@
},
"packages/dom": {
"name": "@wordpress/dom",
- "version": "4.6.0",
+ "version": "4.7.0",
"license": "GPL-2.0-or-later",
"dependencies": {
"@babel/runtime": "^7.16.0",
@@ -53148,7 +53379,7 @@
},
"packages/dom-ready": {
"name": "@wordpress/dom-ready",
- "version": "4.6.0",
+ "version": "4.7.0",
"license": "GPL-2.0-or-later",
"dependencies": {
"@babel/runtime": "^7.16.0"
@@ -53160,7 +53391,7 @@
},
"packages/e2e-test-utils": {
"name": "@wordpress/e2e-test-utils",
- "version": "11.6.0",
+ "version": "11.7.0",
"dev": true,
"license": "GPL-2.0-or-later",
"dependencies": {
@@ -53183,7 +53414,7 @@
},
"packages/e2e-test-utils-playwright": {
"name": "@wordpress/e2e-test-utils-playwright",
- "version": "1.6.0",
+ "version": "1.7.0",
"dev": true,
"license": "GPL-2.0-or-later",
"dependencies": {
@@ -53211,7 +53442,7 @@
},
"packages/e2e-tests": {
"name": "@wordpress/e2e-tests",
- "version": "8.6.0",
+ "version": "8.7.0",
"dev": true,
"license": "GPL-2.0-or-later",
"dependencies": {
@@ -53251,7 +53482,7 @@
},
"packages/edit-post": {
"name": "@wordpress/edit-post",
- "version": "8.6.1",
+ "version": "8.7.0",
"license": "GPL-2.0-or-later",
"dependencies": {
"@babel/runtime": "^7.16.0",
@@ -53298,7 +53529,7 @@
},
"packages/edit-site": {
"name": "@wordpress/edit-site",
- "version": "6.6.1",
+ "version": "6.7.0",
"license": "GPL-2.0-or-later",
"dependencies": {
"@babel/runtime": "^7.16.0",
@@ -53360,7 +53591,7 @@
},
"packages/edit-widgets": {
"name": "@wordpress/edit-widgets",
- "version": "6.6.1",
+ "version": "6.7.0",
"license": "GPL-2.0-or-later",
"dependencies": {
"@babel/runtime": "^7.16.0",
@@ -53403,7 +53634,7 @@
},
"packages/editor": {
"name": "@wordpress/editor",
- "version": "14.6.0",
+ "version": "14.7.0",
"license": "GPL-2.0-or-later",
"dependencies": {
"@babel/runtime": "^7.16.0",
@@ -53464,7 +53695,7 @@
},
"packages/element": {
"name": "@wordpress/element",
- "version": "6.6.0",
+ "version": "6.7.0",
"license": "GPL-2.0-or-later",
"dependencies": {
"@babel/runtime": "^7.16.0",
@@ -53483,7 +53714,7 @@
},
"packages/env": {
"name": "@wordpress/env",
- "version": "10.6.0",
+ "version": "10.7.0",
"dev": true,
"license": "GPL-2.0-or-later",
"dependencies": {
@@ -53625,7 +53856,7 @@
},
"packages/escape-html": {
"name": "@wordpress/escape-html",
- "version": "3.6.0",
+ "version": "3.7.0",
"license": "GPL-2.0-or-later",
"dependencies": {
"@babel/runtime": "^7.16.0"
@@ -53637,7 +53868,7 @@
},
"packages/eslint-plugin": {
"name": "@wordpress/eslint-plugin",
- "version": "20.3.0",
+ "version": "21.0.0",
"dev": true,
"license": "GPL-2.0-or-later",
"dependencies": {
@@ -53680,7 +53911,7 @@
},
"packages/format-library": {
"name": "@wordpress/format-library",
- "version": "5.6.0",
+ "version": "5.7.0",
"license": "GPL-2.0-or-later",
"dependencies": {
"@babel/runtime": "^7.16.0",
@@ -53708,7 +53939,7 @@
},
"packages/hooks": {
"name": "@wordpress/hooks",
- "version": "4.6.0",
+ "version": "4.7.0",
"license": "GPL-2.0-or-later",
"dependencies": {
"@babel/runtime": "^7.16.0"
@@ -53720,7 +53951,7 @@
},
"packages/html-entities": {
"name": "@wordpress/html-entities",
- "version": "4.6.0",
+ "version": "4.7.0",
"license": "GPL-2.0-or-later",
"dependencies": {
"@babel/runtime": "^7.16.0"
@@ -53732,7 +53963,7 @@
},
"packages/i18n": {
"name": "@wordpress/i18n",
- "version": "5.6.0",
+ "version": "5.7.0",
"license": "GPL-2.0-or-later",
"dependencies": {
"@babel/runtime": "^7.16.0",
@@ -53752,7 +53983,7 @@
},
"packages/icons": {
"name": "@wordpress/icons",
- "version": "10.6.0",
+ "version": "10.7.0",
"license": "GPL-2.0-or-later",
"dependencies": {
"@babel/runtime": "^7.16.0",
@@ -53766,7 +53997,7 @@
},
"packages/interactivity": {
"name": "@wordpress/interactivity",
- "version": "6.6.0",
+ "version": "6.7.0",
"license": "GPL-2.0-or-later",
"dependencies": {
"@preact/signals": "^1.2.2",
@@ -53779,7 +54010,7 @@
},
"packages/interactivity-router": {
"name": "@wordpress/interactivity-router",
- "version": "2.6.0",
+ "version": "2.7.0",
"license": "GPL-2.0-or-later",
"dependencies": {
"@wordpress/interactivity": "file:../interactivity"
@@ -53815,7 +54046,7 @@
},
"packages/interface": {
"name": "@wordpress/interface",
- "version": "6.6.0",
+ "version": "6.7.0",
"license": "GPL-2.0-or-later",
"dependencies": {
"@babel/runtime": "^7.16.0",
@@ -53844,7 +54075,7 @@
},
"packages/is-shallow-equal": {
"name": "@wordpress/is-shallow-equal",
- "version": "5.6.0",
+ "version": "5.7.0",
"license": "GPL-2.0-or-later",
"dependencies": {
"@babel/runtime": "^7.16.0"
@@ -53856,7 +54087,7 @@
},
"packages/jest-console": {
"name": "@wordpress/jest-console",
- "version": "8.6.0",
+ "version": "8.7.0",
"dev": true,
"license": "GPL-2.0-or-later",
"dependencies": {
@@ -53873,7 +54104,7 @@
},
"packages/jest-preset-default": {
"name": "@wordpress/jest-preset-default",
- "version": "12.6.0",
+ "version": "12.7.0",
"dev": true,
"license": "GPL-2.0-or-later",
"dependencies": {
@@ -53891,7 +54122,7 @@
},
"packages/jest-puppeteer-axe": {
"name": "@wordpress/jest-puppeteer-axe",
- "version": "7.6.0",
+ "version": "7.7.0",
"dev": true,
"license": "GPL-2.0-or-later",
"dependencies": {
@@ -53914,7 +54145,7 @@
},
"packages/keyboard-shortcuts": {
"name": "@wordpress/keyboard-shortcuts",
- "version": "5.6.0",
+ "version": "5.7.0",
"license": "GPL-2.0-or-later",
"dependencies": {
"@babel/runtime": "^7.16.0",
@@ -53932,7 +54163,7 @@
},
"packages/keycodes": {
"name": "@wordpress/keycodes",
- "version": "4.6.0",
+ "version": "4.7.0",
"license": "GPL-2.0-or-later",
"dependencies": {
"@babel/runtime": "^7.16.0",
@@ -53945,7 +54176,7 @@
},
"packages/lazy-import": {
"name": "@wordpress/lazy-import",
- "version": "2.6.0",
+ "version": "2.7.0",
"dev": true,
"license": "GPL-2.0-or-later",
"dependencies": {
@@ -53960,7 +54191,7 @@
},
"packages/list-reusable-blocks": {
"name": "@wordpress/list-reusable-blocks",
- "version": "5.6.0",
+ "version": "5.7.0",
"license": "GPL-2.0-or-later",
"dependencies": {
"@babel/runtime": "^7.16.0",
@@ -53983,7 +54214,7 @@
},
"packages/media-utils": {
"name": "@wordpress/media-utils",
- "version": "5.6.0",
+ "version": "5.7.0",
"license": "GPL-2.0-or-later",
"dependencies": {
"@babel/runtime": "^7.16.0",
@@ -53999,7 +54230,7 @@
},
"packages/notices": {
"name": "@wordpress/notices",
- "version": "5.6.0",
+ "version": "5.7.0",
"license": "GPL-2.0-or-later",
"dependencies": {
"@babel/runtime": "^7.16.0",
@@ -54016,7 +54247,7 @@
},
"packages/npm-package-json-lint-config": {
"name": "@wordpress/npm-package-json-lint-config",
- "version": "5.6.0",
+ "version": "5.7.0",
"dev": true,
"license": "GPL-2.0-or-later",
"engines": {
@@ -54029,7 +54260,7 @@
},
"packages/nux": {
"name": "@wordpress/nux",
- "version": "9.6.0",
+ "version": "9.7.0",
"license": "GPL-2.0-or-later",
"dependencies": {
"@babel/runtime": "^7.16.0",
@@ -54052,7 +54283,7 @@
},
"packages/patterns": {
"name": "@wordpress/patterns",
- "version": "2.6.0",
+ "version": "2.7.0",
"license": "GPL-2.0-or-later",
"dependencies": {
"@babel/runtime": "^7.16.0",
@@ -54082,7 +54313,7 @@
},
"packages/plugins": {
"name": "@wordpress/plugins",
- "version": "7.6.0",
+ "version": "7.7.0",
"license": "GPL-2.0-or-later",
"dependencies": {
"@babel/runtime": "^7.16.0",
@@ -54105,7 +54336,7 @@
},
"packages/postcss-plugins-preset": {
"name": "@wordpress/postcss-plugins-preset",
- "version": "5.6.0",
+ "version": "5.7.0",
"dev": true,
"license": "GPL-2.0-or-later",
"dependencies": {
@@ -54122,7 +54353,7 @@
},
"packages/postcss-themes": {
"name": "@wordpress/postcss-themes",
- "version": "6.6.0",
+ "version": "6.7.0",
"dev": true,
"license": "GPL-2.0-or-later",
"engines": {
@@ -54135,7 +54366,7 @@
},
"packages/preferences": {
"name": "@wordpress/preferences",
- "version": "4.6.0",
+ "version": "4.7.0",
"license": "GPL-2.0-or-later",
"dependencies": {
"@babel/runtime": "^7.16.0",
@@ -54161,7 +54392,7 @@
},
"packages/preferences-persistence": {
"name": "@wordpress/preferences-persistence",
- "version": "2.6.0",
+ "version": "2.7.0",
"license": "GPL-2.0-or-later",
"dependencies": {
"@babel/runtime": "^7.16.0",
@@ -54174,7 +54405,7 @@
},
"packages/prettier-config": {
"name": "@wordpress/prettier-config",
- "version": "4.6.0",
+ "version": "4.7.0",
"dev": true,
"license": "GPL-2.0-or-later",
"engines": {
@@ -54187,7 +54418,7 @@
},
"packages/primitives": {
"name": "@wordpress/primitives",
- "version": "4.6.0",
+ "version": "4.7.0",
"license": "GPL-2.0-or-later",
"dependencies": {
"@babel/runtime": "^7.16.0",
@@ -54204,7 +54435,7 @@
},
"packages/priority-queue": {
"name": "@wordpress/priority-queue",
- "version": "3.6.0",
+ "version": "3.7.0",
"license": "GPL-2.0-or-later",
"dependencies": {
"@babel/runtime": "^7.16.0",
@@ -54217,7 +54448,7 @@
},
"packages/private-apis": {
"name": "@wordpress/private-apis",
- "version": "1.6.0",
+ "version": "1.7.0",
"license": "GPL-2.0-or-later",
"dependencies": {
"@babel/runtime": "^7.16.0"
@@ -54229,7 +54460,7 @@
},
"packages/project-management-automation": {
"name": "@wordpress/project-management-automation",
- "version": "2.6.0",
+ "version": "2.7.0",
"dev": true,
"license": "GPL-2.0-or-later",
"dependencies": {
@@ -54259,7 +54490,7 @@
},
"packages/react-i18n": {
"name": "@wordpress/react-i18n",
- "version": "4.6.0",
+ "version": "4.7.0",
"license": "GPL-2.0-or-later",
"dependencies": {
"@babel/runtime": "^7.16.0",
@@ -54415,7 +54646,7 @@
},
"packages/readable-js-assets-webpack-plugin": {
"name": "@wordpress/readable-js-assets-webpack-plugin",
- "version": "3.6.0",
+ "version": "3.7.0",
"dev": true,
"license": "GPL-2.0-or-later",
"engines": {
@@ -54428,7 +54659,7 @@
},
"packages/redux-routine": {
"name": "@wordpress/redux-routine",
- "version": "5.6.0",
+ "version": "5.7.0",
"license": "GPL-2.0-or-later",
"dependencies": {
"@babel/runtime": "^7.16.0",
@@ -54473,7 +54704,7 @@
},
"packages/reusable-blocks": {
"name": "@wordpress/reusable-blocks",
- "version": "5.6.0",
+ "version": "5.7.0",
"license": "GPL-2.0-or-later",
"dependencies": {
"@babel/runtime": "^7.16.0",
@@ -54500,7 +54731,7 @@
},
"packages/rich-text": {
"name": "@wordpress/rich-text",
- "version": "7.6.0",
+ "version": "7.7.0",
"license": "GPL-2.0-or-later",
"dependencies": {
"@babel/runtime": "^7.16.0",
@@ -54524,7 +54755,7 @@
},
"packages/router": {
"name": "@wordpress/router",
- "version": "1.6.0",
+ "version": "1.7.0",
"license": "GPL-2.0-or-later",
"dependencies": {
"@babel/runtime": "^7.16.0",
@@ -54543,7 +54774,7 @@
},
"packages/scripts": {
"name": "@wordpress/scripts",
- "version": "28.6.0",
+ "version": "29.0.0",
"dev": true,
"license": "GPL-2.0-or-later",
"dependencies": {
@@ -54591,7 +54822,7 @@
"postcss-import": "^16.1.0",
"postcss-loader": "^6.2.1",
"prettier": "npm:wp-prettier@3.0.3",
- "puppeteer-core": "^13.2.0",
+ "puppeteer-core": "^23.1.0",
"react-refresh": "^0.14.0",
"read-pkg-up": "^7.0.1",
"resolve-bin": "^0.4.0",
@@ -54998,7 +55229,7 @@
},
"packages/server-side-render": {
"name": "@wordpress/server-side-render",
- "version": "5.6.0",
+ "version": "5.7.0",
"license": "GPL-2.0-or-later",
"dependencies": {
"@babel/runtime": "^7.16.0",
@@ -55024,7 +55255,7 @@
},
"packages/shortcode": {
"name": "@wordpress/shortcode",
- "version": "4.6.0",
+ "version": "4.7.0",
"license": "GPL-2.0-or-later",
"dependencies": {
"@babel/runtime": "^7.16.0",
@@ -55037,7 +55268,7 @@
},
"packages/style-engine": {
"name": "@wordpress/style-engine",
- "version": "2.6.0",
+ "version": "2.7.0",
"license": "GPL-2.0-or-later",
"dependencies": {
"@babel/runtime": "^7.16.0",
@@ -55050,7 +55281,7 @@
},
"packages/stylelint-config": {
"name": "@wordpress/stylelint-config",
- "version": "22.6.0",
+ "version": "22.7.0",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -55067,7 +55298,7 @@
},
"packages/sync": {
"name": "@wordpress/sync",
- "version": "1.6.0",
+ "version": "1.7.0",
"license": "GPL-2.0-or-later",
"dependencies": {
"@babel/runtime": "^7.16.0",
@@ -55088,7 +55319,7 @@
},
"packages/token-list": {
"name": "@wordpress/token-list",
- "version": "3.6.0",
+ "version": "3.7.0",
"license": "GPL-2.0-or-later",
"dependencies": {
"@babel/runtime": "^7.16.0"
@@ -55100,7 +55331,7 @@
},
"packages/undo-manager": {
"name": "@wordpress/undo-manager",
- "version": "1.6.0",
+ "version": "1.7.0",
"license": "GPL-2.0-or-later",
"dependencies": {
"@babel/runtime": "^7.16.0",
@@ -55113,7 +55344,7 @@
},
"packages/url": {
"name": "@wordpress/url",
- "version": "4.6.0",
+ "version": "4.7.0",
"license": "GPL-2.0-or-later",
"dependencies": {
"@babel/runtime": "^7.16.0",
@@ -55126,7 +55357,7 @@
},
"packages/viewport": {
"name": "@wordpress/viewport",
- "version": "6.6.0",
+ "version": "6.7.0",
"license": "GPL-2.0-or-later",
"dependencies": {
"@babel/runtime": "^7.16.0",
@@ -55144,7 +55375,7 @@
},
"packages/warning": {
"name": "@wordpress/warning",
- "version": "3.6.0",
+ "version": "3.7.0",
"license": "GPL-2.0-or-later",
"engines": {
"node": ">=18.12.0",
@@ -55153,7 +55384,7 @@
},
"packages/widgets": {
"name": "@wordpress/widgets",
- "version": "4.6.0",
+ "version": "4.7.0",
"license": "GPL-2.0-or-later",
"dependencies": {
"@babel/runtime": "^7.16.0",
@@ -55181,7 +55412,7 @@
},
"packages/wordcount": {
"name": "@wordpress/wordcount",
- "version": "4.6.0",
+ "version": "4.7.0",
"license": "GPL-2.0-or-later",
"dependencies": {
"@babel/runtime": "^7.16.0"
@@ -68770,7 +69001,7 @@
"postcss-import": "^16.1.0",
"postcss-loader": "^6.2.1",
"prettier": "npm:wp-prettier@3.0.3",
- "puppeteer-core": "^13.2.0",
+ "puppeteer-core": "^23.1.0",
"react-refresh": "^0.14.0",
"read-pkg-up": "^7.0.1",
"resolve-bin": "^0.4.0",
@@ -73319,15 +73550,6 @@
"is-windows": "^1.0.0"
}
},
- "cross-fetch": {
- "version": "3.1.5",
- "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.5.tgz",
- "integrity": "sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw==",
- "dev": true,
- "requires": {
- "node-fetch": "2.6.7"
- }
- },
"cross-spawn": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz",
@@ -74451,9 +74673,9 @@
}
},
"devtools-protocol": {
- "version": "0.0.981744",
- "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.981744.tgz",
- "integrity": "sha512-0cuGS8+jhR67Fy7qG3i3Pc7Aw494sb9yG9QgpG97SFVWwolgYjlhJg7n+UaHxOQT30d1TYu/EYe9k01ivLErIg==",
+ "version": "0.0.1312386",
+ "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1312386.tgz",
+ "integrity": "sha512-DPnhUXvmvKT2dFA/j7B+riVLUt9Q6RKJlcppojL5CoRywJJKLDYnRlw0gTFKfgDPHP5E04UoB71SxoJlVZy8FA==",
"dev": true
},
"diff": {
@@ -88284,25 +88506,81 @@
"integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg=="
},
"puppeteer-core": {
- "version": "13.7.0",
- "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-13.7.0.tgz",
- "integrity": "sha512-rXja4vcnAzFAP1OVLq/5dWNfwBGuzcOARJ6qGV7oAZhnLmVRU8G5MsdeQEAOy332ZhkIOnn9jp15R89LKHyp2Q==",
+ "version": "23.1.0",
+ "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-23.1.0.tgz",
+ "integrity": "sha512-SvAsu+xnLN2FMXE/59bp3s3WXp8ewqUGzVV4AQtml/2xmsciZnU/bXcCW+eETHPWQ6Agg2vTI7QzWXPpEARK2g==",
"dev": true,
"requires": {
- "cross-fetch": "3.1.5",
- "debug": "4.3.4",
- "devtools-protocol": "0.0.981744",
- "extract-zip": "2.0.1",
- "https-proxy-agent": "5.0.1",
- "pkg-dir": "4.2.0",
- "progress": "2.0.3",
- "proxy-from-env": "1.1.0",
- "rimraf": "3.0.2",
- "tar-fs": "2.1.1",
- "unbzip2-stream": "1.4.3",
- "ws": "8.5.0"
+ "@puppeteer/browsers": "2.3.1",
+ "chromium-bidi": "0.6.4",
+ "debug": "^4.3.6",
+ "devtools-protocol": "0.0.1312386",
+ "typed-query-selector": "^2.12.0",
+ "ws": "^8.18.0"
},
"dependencies": {
+ "@puppeteer/browsers": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-2.3.1.tgz",
+ "integrity": "sha512-uK7o3hHkK+naEobMSJ+2ySYyXtQkBxIH8Gn4MK9ciePjNV+Pf+PgY/W7iPzn2MTjl3stcYB5AlcTmPYw7AXDwA==",
+ "dev": true,
+ "requires": {
+ "debug": "^4.3.6",
+ "extract-zip": "^2.0.1",
+ "progress": "^2.0.3",
+ "proxy-agent": "^6.4.0",
+ "semver": "^7.6.3",
+ "tar-fs": "^3.0.6",
+ "unbzip2-stream": "^1.4.3",
+ "yargs": "^17.7.2"
+ }
+ },
+ "agent-base": {
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz",
+ "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==",
+ "dev": true,
+ "requires": {
+ "debug": "^4.3.4"
+ }
+ },
+ "chromium-bidi": {
+ "version": "0.6.4",
+ "resolved": "https://registry.npmjs.org/chromium-bidi/-/chromium-bidi-0.6.4.tgz",
+ "integrity": "sha512-8zoq6ogmhQQkAKZVKO2ObFTl4uOkqoX1PlKQX3hZQ5E9cbUotcAb7h4pTNVAGGv8Z36PF3CtdOriEp/Rz82JqQ==",
+ "dev": true,
+ "requires": {
+ "mitt": "3.0.1",
+ "urlpattern-polyfill": "10.0.0",
+ "zod": "3.23.8"
+ }
+ },
+ "cliui": {
+ "version": "8.0.1",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
+ "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==",
+ "dev": true,
+ "requires": {
+ "string-width": "^4.2.0",
+ "strip-ansi": "^6.0.1",
+ "wrap-ansi": "^7.0.0"
+ }
+ },
+ "debug": {
+ "version": "4.3.6",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz",
+ "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==",
+ "dev": true,
+ "requires": {
+ "ms": "2.1.2"
+ }
+ },
+ "emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+ "dev": true
+ },
"extract-zip": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz",
@@ -88315,68 +88593,169 @@
"yauzl": "^2.10.0"
}
},
- "find-up": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
- "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
+ "http-proxy-agent": {
+ "version": "7.0.2",
+ "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz",
+ "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==",
"dev": true,
"requires": {
- "locate-path": "^5.0.0",
- "path-exists": "^4.0.0"
+ "agent-base": "^7.1.0",
+ "debug": "^4.3.4"
}
},
- "locate-path": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
- "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
+ "https-proxy-agent": {
+ "version": "7.0.5",
+ "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz",
+ "integrity": "sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==",
"dev": true,
"requires": {
- "p-locate": "^4.1.0"
+ "agent-base": "^7.0.2",
+ "debug": "4"
}
},
- "p-limit": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
- "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
+ "is-fullwidth-code-point": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+ "dev": true
+ },
+ "lru-cache": {
+ "version": "7.18.3",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz",
+ "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==",
+ "dev": true
+ },
+ "mitt": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.1.tgz",
+ "integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==",
+ "dev": true
+ },
+ "ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true
+ },
+ "proxy-agent": {
+ "version": "6.4.0",
+ "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-6.4.0.tgz",
+ "integrity": "sha512-u0piLU+nCOHMgGjRbimiXmA9kM/L9EHh3zL81xCdp7m+Y2pHIsnmbdDoEDoAz5geaonNR6q6+yOPQs6n4T6sBQ==",
"dev": true,
"requires": {
- "p-try": "^2.0.0"
+ "agent-base": "^7.0.2",
+ "debug": "^4.3.4",
+ "http-proxy-agent": "^7.0.1",
+ "https-proxy-agent": "^7.0.3",
+ "lru-cache": "^7.14.1",
+ "pac-proxy-agent": "^7.0.1",
+ "proxy-from-env": "^1.1.0",
+ "socks-proxy-agent": "^8.0.2"
}
},
- "p-locate": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
- "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
+ "pump": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
+ "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==",
"dev": true,
"requires": {
- "p-limit": "^2.2.0"
+ "end-of-stream": "^1.1.0",
+ "once": "^1.3.1"
}
},
- "p-try": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
- "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
+ "semver": {
+ "version": "7.6.3",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz",
+ "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==",
"dev": true
},
- "path-exists": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
- "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
- "dev": true
+ "socks-proxy-agent": {
+ "version": "8.0.4",
+ "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.4.tgz",
+ "integrity": "sha512-GNAq/eg8Udq2x0eNiFkr9gRg5bA7PXEWagQdeRX4cPSG+X/8V38v637gim9bjFptMk1QWsCTr0ttrJEiXbNnRw==",
+ "dev": true,
+ "requires": {
+ "agent-base": "^7.1.1",
+ "debug": "^4.3.4",
+ "socks": "^2.8.3"
+ }
},
- "pkg-dir": {
- "version": "4.2.0",
- "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz",
- "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==",
+ "string-width": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
"dev": true,
"requires": {
- "find-up": "^4.0.0"
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ }
+ },
+ "tar-fs": {
+ "version": "3.0.6",
+ "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-3.0.6.tgz",
+ "integrity": "sha512-iokBDQQkUyeXhgPYaZxmczGPhnhXZ0CmrqI+MOb/WFGS9DW5wnfrLgtjUJBvz50vQ3qfRwJ62QVoCFu8mPVu5w==",
+ "dev": true,
+ "requires": {
+ "bare-fs": "^2.1.1",
+ "bare-path": "^2.1.0",
+ "pump": "^3.0.0",
+ "tar-stream": "^3.1.5"
+ }
+ },
+ "tar-stream": {
+ "version": "3.1.7",
+ "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-3.1.7.tgz",
+ "integrity": "sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ==",
+ "dev": true,
+ "requires": {
+ "b4a": "^1.6.4",
+ "fast-fifo": "^1.2.0",
+ "streamx": "^2.15.0"
+ }
+ },
+ "wrap-ansi": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
+ "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
}
},
"ws": {
- "version": "8.5.0",
- "resolved": "https://registry.npmjs.org/ws/-/ws-8.5.0.tgz",
- "integrity": "sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==",
+ "version": "8.18.0",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz",
+ "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==",
+ "dev": true
+ },
+ "y18n": {
+ "version": "5.0.8",
+ "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
+ "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
+ "dev": true
+ },
+ "yargs": {
+ "version": "17.7.2",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz",
+ "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==",
+ "dev": true,
+ "requires": {
+ "cliui": "^8.0.1",
+ "escalade": "^3.1.1",
+ "get-caller-file": "^2.0.5",
+ "require-directory": "^2.1.1",
+ "string-width": "^4.2.3",
+ "y18n": "^5.0.5",
+ "yargs-parser": "^21.1.1"
+ }
+ },
+ "yargs-parser": {
+ "version": "21.1.1",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz",
+ "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==",
"dev": true
}
}
@@ -93104,6 +93483,12 @@
"integrity": "sha512-bctQIOqx2iVbWGDGPWwIm18QScpu2XRmkC19D8rQGFsjKSgteq/o1hTZvIG/wuDq8fanpBDrLkLq+aEN/6y5XQ==",
"dev": true
},
+ "typed-query-selector": {
+ "version": "2.12.0",
+ "resolved": "https://registry.npmjs.org/typed-query-selector/-/typed-query-selector-2.12.0.tgz",
+ "integrity": "sha512-SbklCd1F0EiZOyPiW192rrHZzZ5sBijB6xM+cpmrwDqObvdtunOHHIk9fCGsoK5JVIYXoyEp4iEdE3upFH3PAg==",
+ "dev": true
+ },
"typedarray": {
"version": "0.0.6",
"resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
@@ -93631,6 +94016,12 @@
"integrity": "sha512-XdVKMF4SJ0nP/O7XIPB0JwAEuT9lDIYnNsK8yGVe43y0AWoKeJNdv3ZNWh7ksJ6KqQFjOO6ox/VEitLnaVNufw==",
"dev": true
},
+ "urlpattern-polyfill": {
+ "version": "10.0.0",
+ "resolved": "https://registry.npmjs.org/urlpattern-polyfill/-/urlpattern-polyfill-10.0.0.tgz",
+ "integrity": "sha512-H/A06tKD7sS1O1X2SshBVeA5FLycRpjqiBeqGKmBwBDBy28EnRjORxTNe269KSSr5un5qyWi1iL61wLxpd+ZOg==",
+ "dev": true
+ },
"use": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz",
diff --git a/package.json b/package.json
index c0a7853a41817..a67b376f3dbdc 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "gutenberg",
- "version": "19.1.0",
+ "version": "19.2.0-rc.1",
"private": true,
"description": "A new WordPress editor experience.",
"author": "The WordPress Contributors",
@@ -233,6 +233,7 @@
"postcss-local-keyframes": "^0.0.2",
"prettier": "npm:wp-prettier@3.0.3",
"progress": "2.0.3",
+ "puppeteer-core": "23.1.0",
"react": "18.3.1",
"react-dom": "18.3.1",
"react-native": "0.73.3",
diff --git a/packages/a11y/CHANGELOG.md b/packages/a11y/CHANGELOG.md
index 5a90a6cc98f0d..36973cce020f3 100644
--- a/packages/a11y/CHANGELOG.md
+++ b/packages/a11y/CHANGELOG.md
@@ -2,6 +2,8 @@
## Unreleased
+## 4.7.0 (2024-09-05)
+
## 4.6.0 (2024-08-21)
## 4.5.0 (2024-08-07)
diff --git a/packages/a11y/package.json b/packages/a11y/package.json
index 0e307e813c56a..88123b3c6c712 100644
--- a/packages/a11y/package.json
+++ b/packages/a11y/package.json
@@ -1,6 +1,6 @@
{
"name": "@wordpress/a11y",
- "version": "4.6.0",
+ "version": "4.7.0",
"description": "Accessibility (a11y) utilities for WordPress.",
"author": "The WordPress Contributors",
"license": "GPL-2.0-or-later",
diff --git a/packages/annotations/CHANGELOG.md b/packages/annotations/CHANGELOG.md
index b3e0dbab635b8..6211cf30688e5 100644
--- a/packages/annotations/CHANGELOG.md
+++ b/packages/annotations/CHANGELOG.md
@@ -2,6 +2,8 @@
## Unreleased
+## 3.7.0 (2024-09-05)
+
## 3.6.0 (2024-08-21)
## 3.5.0 (2024-08-07)
diff --git a/packages/annotations/package.json b/packages/annotations/package.json
index 95ceadb1d990e..c189dcc11fd09 100644
--- a/packages/annotations/package.json
+++ b/packages/annotations/package.json
@@ -1,6 +1,6 @@
{
"name": "@wordpress/annotations",
- "version": "3.6.0",
+ "version": "3.7.0",
"description": "Annotate content in the Gutenberg editor.",
"author": "The WordPress Contributors",
"license": "GPL-2.0-or-later",
diff --git a/packages/api-fetch/CHANGELOG.md b/packages/api-fetch/CHANGELOG.md
index 49319c18ab754..01b37d4e14a7d 100644
--- a/packages/api-fetch/CHANGELOG.md
+++ b/packages/api-fetch/CHANGELOG.md
@@ -2,6 +2,8 @@
## Unreleased
+## 7.7.0 (2024-09-05)
+
## 7.6.0 (2024-08-21)
## 7.5.0 (2024-08-07)
diff --git a/packages/api-fetch/package.json b/packages/api-fetch/package.json
index abbe8cce374c3..76d797f4ddfa5 100644
--- a/packages/api-fetch/package.json
+++ b/packages/api-fetch/package.json
@@ -1,6 +1,6 @@
{
"name": "@wordpress/api-fetch",
- "version": "7.6.0",
+ "version": "7.7.0",
"description": "Utility to make WordPress REST API requests.",
"author": "The WordPress Contributors",
"license": "GPL-2.0-or-later",
diff --git a/packages/autop/CHANGELOG.md b/packages/autop/CHANGELOG.md
index 353495eae8983..ed19f1ceafbc5 100644
--- a/packages/autop/CHANGELOG.md
+++ b/packages/autop/CHANGELOG.md
@@ -2,6 +2,8 @@
## Unreleased
+## 4.7.0 (2024-09-05)
+
## 4.6.0 (2024-08-21)
## 4.5.0 (2024-08-07)
diff --git a/packages/autop/package.json b/packages/autop/package.json
index 03bb56412195e..4e1cf577ebd09 100644
--- a/packages/autop/package.json
+++ b/packages/autop/package.json
@@ -1,6 +1,6 @@
{
"name": "@wordpress/autop",
- "version": "4.6.0",
+ "version": "4.7.0",
"description": "WordPress's automatic paragraph functions `autop` and `removep`.",
"author": "The WordPress Contributors",
"license": "GPL-2.0-or-later",
diff --git a/packages/babel-plugin-import-jsx-pragma/CHANGELOG.md b/packages/babel-plugin-import-jsx-pragma/CHANGELOG.md
index d96d2315e2a51..c916b788243a0 100644
--- a/packages/babel-plugin-import-jsx-pragma/CHANGELOG.md
+++ b/packages/babel-plugin-import-jsx-pragma/CHANGELOG.md
@@ -2,6 +2,8 @@
## Unreleased
+## 5.7.0 (2024-09-05)
+
## 5.6.0 (2024-08-21)
## 5.5.0 (2024-08-07)
diff --git a/packages/babel-plugin-import-jsx-pragma/package.json b/packages/babel-plugin-import-jsx-pragma/package.json
index be1dbc4235f28..1af6bdf93cb04 100644
--- a/packages/babel-plugin-import-jsx-pragma/package.json
+++ b/packages/babel-plugin-import-jsx-pragma/package.json
@@ -1,6 +1,6 @@
{
"name": "@wordpress/babel-plugin-import-jsx-pragma",
- "version": "5.6.0",
+ "version": "5.7.0",
"description": "Babel transform plugin for automatically injecting an import to be used as the pragma for the React JSX Transform plugin.",
"author": "The WordPress Contributors",
"license": "GPL-2.0-or-later",
diff --git a/packages/babel-plugin-makepot/CHANGELOG.md b/packages/babel-plugin-makepot/CHANGELOG.md
index 98da250e2ba6b..e7345f314d578 100644
--- a/packages/babel-plugin-makepot/CHANGELOG.md
+++ b/packages/babel-plugin-makepot/CHANGELOG.md
@@ -2,6 +2,8 @@
## Unreleased
+## 6.7.0 (2024-09-05)
+
## 6.6.0 (2024-08-21)
## 6.5.0 (2024-08-07)
diff --git a/packages/babel-plugin-makepot/package.json b/packages/babel-plugin-makepot/package.json
index 4d439baf28163..a7c18d891538d 100644
--- a/packages/babel-plugin-makepot/package.json
+++ b/packages/babel-plugin-makepot/package.json
@@ -1,6 +1,6 @@
{
"name": "@wordpress/babel-plugin-makepot",
- "version": "6.6.0",
+ "version": "6.7.0",
"description": "WordPress Babel internationalization (i18n) plugin.",
"author": "The WordPress Contributors",
"license": "GPL-2.0-or-later",
diff --git a/packages/babel-preset-default/CHANGELOG.md b/packages/babel-preset-default/CHANGELOG.md
index 43c9675fcb885..70a740f60cad3 100644
--- a/packages/babel-preset-default/CHANGELOG.md
+++ b/packages/babel-preset-default/CHANGELOG.md
@@ -2,6 +2,8 @@
## Unreleased
+## 8.7.0 (2024-09-05)
+
## 8.6.0 (2024-08-21)
## 8.5.0 (2024-08-07)
diff --git a/packages/babel-preset-default/package.json b/packages/babel-preset-default/package.json
index 2559b60401790..be5b3786346eb 100644
--- a/packages/babel-preset-default/package.json
+++ b/packages/babel-preset-default/package.json
@@ -1,6 +1,6 @@
{
"name": "@wordpress/babel-preset-default",
- "version": "8.6.0",
+ "version": "8.7.0",
"description": "Default Babel preset for WordPress development.",
"author": "The WordPress Contributors",
"license": "GPL-2.0-or-later",
diff --git a/packages/base-styles/CHANGELOG.md b/packages/base-styles/CHANGELOG.md
index ce98cebeae1c2..cad2f94c98da7 100644
--- a/packages/base-styles/CHANGELOG.md
+++ b/packages/base-styles/CHANGELOG.md
@@ -2,6 +2,8 @@
## Unreleased
+## 5.7.0 (2024-09-05)
+
## 5.6.0 (2024-08-21)
## 5.5.0 (2024-08-07)
diff --git a/packages/base-styles/_mixins.scss b/packages/base-styles/_mixins.scss
index 69735d75aac71..ebccbe0e5e8ae 100644
--- a/packages/base-styles/_mixins.scss
+++ b/packages/base-styles/_mixins.scss
@@ -74,7 +74,7 @@
@mixin input-style__neutral() {
box-shadow: 0 0 0 transparent;
transition: box-shadow 0.1s linear;
- border-radius: $radius-block-ui;
+ border-radius: $radius-small;
border: $border-width solid $gray-600;
@include reduce-motion("transition");
}
@@ -227,7 +227,7 @@
border: $border-width solid $gray-900;
margin-right: $grid-unit-15;
transition: none;
- border-radius: $radius-block-ui;
+ border-radius: $radius-small;
&:focus {
box-shadow: 0 0 0 ($border-width * 2) $white, 0 0 0 ($border-width * 2 + $border-width-focus-fallback) var(--wp-admin-theme-color);
@@ -363,7 +363,7 @@
&:focus {
color: var(--wp-admin-theme-color--rgb);
box-shadow: 0 0 0 var(--wp-admin-border-width-focus) var(--wp-admin-theme-color, #007cba);
- border-radius: $radius-block-ui;
+ border-radius: $radius-small;
}
}
@@ -375,7 +375,7 @@
padding: $grid-unit-15 !important;
border: $border-width solid $gray-900 !important;
box-shadow: none !important;
- border-radius: $radius-block-ui !important;
+ border-radius: $radius-small !important;
// Fonts smaller than 16px causes mobile safari to zoom.
font-size: $mobile-text-min-font-size !important;
diff --git a/packages/base-styles/package.json b/packages/base-styles/package.json
index fbe3bf149b1cd..6839a8081e04a 100644
--- a/packages/base-styles/package.json
+++ b/packages/base-styles/package.json
@@ -1,6 +1,6 @@
{
"name": "@wordpress/base-styles",
- "version": "5.6.0",
+ "version": "5.7.0",
"description": "Base SCSS utilities and variables for WordPress.",
"author": "The WordPress Contributors",
"license": "GPL-2.0-or-later",
diff --git a/packages/blob/CHANGELOG.md b/packages/blob/CHANGELOG.md
index 5c21e96d7269c..f95598025a8b6 100644
--- a/packages/blob/CHANGELOG.md
+++ b/packages/blob/CHANGELOG.md
@@ -2,6 +2,8 @@
## Unreleased
+## 4.7.0 (2024-09-05)
+
## 4.6.0 (2024-08-21)
## 4.5.0 (2024-08-07)
diff --git a/packages/blob/package.json b/packages/blob/package.json
index 58feea189bed0..3dea70c977197 100644
--- a/packages/blob/package.json
+++ b/packages/blob/package.json
@@ -1,6 +1,6 @@
{
"name": "@wordpress/blob",
- "version": "4.6.0",
+ "version": "4.7.0",
"description": "Blob utilities for WordPress.",
"author": "The WordPress Contributors",
"license": "GPL-2.0-or-later",
diff --git a/packages/block-directory/CHANGELOG.md b/packages/block-directory/CHANGELOG.md
index 4d15343f0c092..70914f293ca99 100644
--- a/packages/block-directory/CHANGELOG.md
+++ b/packages/block-directory/CHANGELOG.md
@@ -2,6 +2,8 @@
## Unreleased
+## 5.7.0 (2024-09-05)
+
## 5.6.0 (2024-08-21)
## 5.5.0 (2024-08-07)
diff --git a/packages/block-directory/package.json b/packages/block-directory/package.json
index 85222ecaa3882..39f239edfcb44 100644
--- a/packages/block-directory/package.json
+++ b/packages/block-directory/package.json
@@ -1,6 +1,6 @@
{
"name": "@wordpress/block-directory",
- "version": "5.6.0",
+ "version": "5.7.0",
"description": "Extend editor with block directory features to search, download and install blocks.",
"author": "The WordPress Contributors",
"license": "GPL-2.0-or-later",
diff --git a/packages/block-directory/src/components/downloadable-block-list-item/index.js b/packages/block-directory/src/components/downloadable-block-list-item/index.js
index 03e6e79d8928e..ac587dc2d6d0c 100644
--- a/packages/block-directory/src/components/downloadable-block-list-item/index.js
+++ b/packages/block-directory/src/components/downloadable-block-list-item/index.js
@@ -6,7 +6,7 @@ import {
Button,
Spinner,
VisuallyHidden,
- privateApis as componentsPrivateApis,
+ Composite,
} from '@wordpress/components';
import { createInterpolateElement } from '@wordpress/element';
import { decodeEntities } from '@wordpress/html-entities';
@@ -20,9 +20,6 @@ import BlockRatings from '../block-ratings';
import DownloadableBlockIcon from '../downloadable-block-icon';
import DownloadableBlockNotice from '../downloadable-block-notice';
import { store as blockDirectoryStore } from '../../store';
-import { unlock } from '../../lock-unlock';
-
-const { CompositeItemV2: CompositeItem } = unlock( componentsPrivateApis );
// Return the appropriate block item label, given the block data and status.
function getDownloadableBlockLabel(
@@ -65,7 +62,7 @@ function getDownloadableBlockLabel(
);
}
-function DownloadableBlockListItem( { composite, item, onClick } ) {
+function DownloadableBlockListItem( { item, onClick } ) {
const { author, description, icon, rating, title } = item;
// getBlockType returns a block object if this block exists, or null if not.
const isInstalled = !! getBlockType( item.name );
@@ -93,7 +90,7 @@ function DownloadableBlockListItem( { composite, item, onClick } ) {
}
return (
-
}
- store={ composite }
disabled={ isInstalling || ! isInstallable }
>
@@ -163,7 +159,7 @@ function DownloadableBlockListItem( { composite, item, onClick } ) {
>
) }
-
+
);
}
diff --git a/packages/block-directory/src/components/downloadable-blocks-list/index.js b/packages/block-directory/src/components/downloadable-blocks-list/index.js
index 09f509c4ed49c..3e44aa423bfa5 100644
--- a/packages/block-directory/src/components/downloadable-blocks-list/index.js
+++ b/packages/block-directory/src/components/downloadable-blocks-list/index.js
@@ -2,7 +2,7 @@
* WordPress dependencies
*/
import { __ } from '@wordpress/i18n';
-import { privateApis as componentsPrivateApis } from '@wordpress/components';
+import { Composite } from '@wordpress/components';
import { getBlockType } from '@wordpress/blocks';
import { useDispatch } from '@wordpress/data';
@@ -11,14 +11,10 @@ import { useDispatch } from '@wordpress/data';
*/
import DownloadableBlockListItem from '../downloadable-block-list-item';
import { store as blockDirectoryStore } from '../../store';
-import { unlock } from '../../lock-unlock';
-const { CompositeV2: Composite, useCompositeStoreV2: useCompositeStore } =
- unlock( componentsPrivateApis );
const noop = () => {};
function DownloadableBlocksList( { items, onHover = noop, onSelect } ) {
- const composite = useCompositeStore();
const { installBlockType } = useDispatch( blockDirectoryStore );
if ( ! items.length ) {
@@ -27,7 +23,6 @@ function DownloadableBlocksList( { items, onHover = noop, onSelect } ) {
return (
{
// Check if the block is registered (`getBlockType`
// will return an object). If so, insert the block.
diff --git a/packages/block-editor/CHANGELOG.md b/packages/block-editor/CHANGELOG.md
index 0b365c18ae8ad..da44ebc4149f5 100644
--- a/packages/block-editor/CHANGELOG.md
+++ b/packages/block-editor/CHANGELOG.md
@@ -2,6 +2,8 @@
## Unreleased
+## 14.2.0 (2024-09-05)
+
## 14.1.0 (2024-08-21)
## 14.0.0 (2024-08-07)
diff --git a/packages/block-editor/package.json b/packages/block-editor/package.json
index 1f4fa7588ec6c..d3064c78dbe65 100644
--- a/packages/block-editor/package.json
+++ b/packages/block-editor/package.json
@@ -1,6 +1,6 @@
{
"name": "@wordpress/block-editor",
- "version": "14.1.0",
+ "version": "14.2.0",
"description": "Generic block editor.",
"author": "The WordPress Contributors",
"license": "GPL-2.0-or-later",
diff --git a/packages/block-editor/src/components/block-breadcrumb/style.scss b/packages/block-editor/src/components/block-breadcrumb/style.scss
index 5d2e3154dc2d9..78d422d7b0997 100644
--- a/packages/block-editor/src/components/block-breadcrumb/style.scss
+++ b/packages/block-editor/src/components/block-breadcrumb/style.scss
@@ -41,7 +41,7 @@
content: "";
display: block;
position: absolute;
- border-radius: $radius-block-ui;
+ border-radius: $radius-small;
top: $border-width;
right: $border-width;
bottom: $border-width;
diff --git a/packages/block-editor/src/components/block-draggable/content.scss b/packages/block-editor/src/components/block-draggable/content.scss
index f1318daebd5a0..102230168e213 100644
--- a/packages/block-editor/src/components/block-draggable/content.scss
+++ b/packages/block-editor/src/components/block-draggable/content.scss
@@ -3,7 +3,7 @@
.block-editor-block-list__layout .is-dragging {
background-color: currentColor !important;
opacity: 0.05 !important;
- border-radius: $radius-block-ui !important;
+ border-radius: $radius-small !important;
// Disabling pointer events during the drag event is necessary,
// lest the block might affect your drag operation.
diff --git a/packages/block-editor/src/components/block-draggable/style.scss b/packages/block-editor/src/components/block-draggable/style.scss
index afbf77319f720..349afa2c3563c 100644
--- a/packages/block-editor/src/components/block-draggable/style.scss
+++ b/packages/block-editor/src/components/block-draggable/style.scss
@@ -7,7 +7,7 @@
.block-editor-block-draggable-chip {
background-color: $gray-900;
- border-radius: $radius-block-ui;
+ border-radius: $radius-small;
box-shadow: 0 6px 8px rgba($black, 0.3);
color: $white;
cursor: grabbing;
diff --git a/packages/block-editor/src/components/block-inspector/index.js b/packages/block-editor/src/components/block-inspector/index.js
index 75b5239f47d6c..1986ad8730c12 100644
--- a/packages/block-editor/src/components/block-inspector/index.js
+++ b/packages/block-editor/src/components/block-inspector/index.js
@@ -322,6 +322,7 @@ const BlockInspectorSingleBlock = ( { clientId, blockName } ) => {
/>
+
diff --git a/packages/block-editor/src/components/block-list/block.js b/packages/block-editor/src/components/block-list/block.js
index bdf33c944deb1..deda4e3b9d089 100644
--- a/packages/block-editor/src/components/block-list/block.js
+++ b/packages/block-editor/src/components/block-list/block.js
@@ -646,6 +646,8 @@ function BlockListBlockProvider( props ) {
blocksWithSameName.length &&
blocksWithSameName[ 0 ] !== clientId;
+ const editorMode = __unstableGetEditorMode();
+
return {
...previewContext,
mode: getBlockMode( clientId ),
@@ -672,6 +674,7 @@ function BlockListBlockProvider( props ) {
) && hasSelectedInnerBlock( clientId ),
blockApiVersion: blockType?.apiVersion || 1,
blockTitle: match?.title || blockType?.title,
+ editorMode,
isSubtreeDisabled:
blockEditingMode === 'disabled' &&
isBlockSubtreeDisabled( clientId ),
@@ -680,8 +683,7 @@ function BlockListBlockProvider( props ) {
! isDragging(),
initialPosition:
_isSelected &&
- ( __unstableGetEditorMode() === 'edit' ||
- __unstableGetEditorMode() === 'zoom-out' ) // Don't recalculate the initialPosition when toggling in/out of zoom-out mode
+ ( editorMode === 'edit' || editorMode === 'zoom-out' ) // Don't recalculate the initialPosition when toggling in/out of zoom-out mode
? getSelectedBlocksInitialCaretPosition()
: undefined,
isHighlighted: isBlockHighlighted( clientId ),
@@ -728,6 +730,7 @@ function BlockListBlockProvider( props ) {
themeSupportsLayout,
isTemporarilyEditingAsBlocks,
blockEditingMode,
+ editorMode,
mayDisplayControls,
mayDisplayParentControls,
index,
@@ -782,6 +785,7 @@ function BlockListBlockProvider( props ) {
hasOverlay,
initialPosition,
blockEditingMode,
+ editorMode,
isHighlighted,
isMultiSelected,
isPartiallySelected,
diff --git a/packages/block-editor/src/components/block-list/content.scss b/packages/block-editor/src/components/block-list/content.scss
index 15f0239d0f076..95bb610da9967 100644
--- a/packages/block-editor/src/components/block-list/content.scss
+++ b/packages/block-editor/src/components/block-list/content.scss
@@ -107,7 +107,7 @@ _::-webkit-full-page-media, _:future, :root .has-multi-selection .block-editor-b
right: 0;
left: 0;
top: -$default-block-margin * 0.5;
- border-radius: $radius-block-ui;
+ border-radius: $radius-small;
border-top: 4px solid $gray-400;
bottom: auto;
box-shadow: none;
@@ -215,7 +215,6 @@ _::-webkit-full-page-media, _:future, :root .has-multi-selection .block-editor-b
right: 0;
bottom: 0;
left: 0;
- border-radius: $radius-block-ui;
background-color: rgba($white, 0.4);
}
diff --git a/packages/block-editor/src/components/block-list/use-block-props/index.js b/packages/block-editor/src/components/block-list/use-block-props/index.js
index 15fb83139237c..c3a279a618b5d 100644
--- a/packages/block-editor/src/components/block-list/use-block-props/index.js
+++ b/packages/block-editor/src/components/block-list/use-block-props/index.js
@@ -26,6 +26,7 @@ import {
import { useFocusHandler } from './use-focus-handler';
import { useEventHandlers } from './use-selected-block-event-handlers';
import { useNavModeExit } from './use-nav-mode-exit';
+import { useZoomOutModeExit } from './use-zoom-out-mode-exit';
import { useBlockRefProvider } from './use-block-refs';
import { useIntersectionObserver } from './use-intersection-observer';
import { useScrollIntoView } from './use-scroll-into-view';
@@ -85,6 +86,7 @@ export function useBlockProps( props = {}, { __unstableIsHtml } = {} ) {
name,
blockApiVersion,
blockTitle,
+ editorMode,
isSelected,
isSubtreeDisabled,
hasOverlay,
@@ -115,6 +117,7 @@ export function useBlockProps( props = {}, { __unstableIsHtml } = {} ) {
useFocusHandler( clientId ),
useEventHandlers( { clientId, isSelected } ),
useNavModeExit( clientId ),
+ useZoomOutModeExit( { editorMode } ),
useIsHovered( { clientId } ),
useIntersectionObserver(),
useMovingAnimation( { triggerAnimationOnChange: index, clientId } ),
diff --git a/packages/block-editor/src/components/block-list/use-block-props/use-zoom-out-mode-exit.js b/packages/block-editor/src/components/block-list/use-block-props/use-zoom-out-mode-exit.js
new file mode 100644
index 0000000000000..bb6edd066f06f
--- /dev/null
+++ b/packages/block-editor/src/components/block-list/use-block-props/use-zoom-out-mode-exit.js
@@ -0,0 +1,44 @@
+/**
+ * WordPress dependencies
+ */
+import { useDispatch } from '@wordpress/data';
+import { useRefEffect } from '@wordpress/compose';
+
+/**
+ * Internal dependencies
+ */
+import { store as blockEditorStore } from '../../../store';
+import { unlock } from '../../../lock-unlock';
+
+/**
+ * Allows Zoom Out mode to be exited by double clicking in the selected block.
+ *
+ * @param {string} clientId Block client ID.
+ */
+export function useZoomOutModeExit( { editorMode } ) {
+ const { __unstableSetEditorMode } = unlock(
+ useDispatch( blockEditorStore )
+ );
+
+ return useRefEffect(
+ ( node ) => {
+ if ( editorMode !== 'zoom-out' ) {
+ return;
+ }
+
+ function onDoubleClick( event ) {
+ if ( ! event.defaultPrevented ) {
+ event.preventDefault();
+ __unstableSetEditorMode( 'edit' );
+ }
+ }
+
+ node.addEventListener( 'dblclick', onDoubleClick );
+
+ return () => {
+ node.removeEventListener( 'dblclick', onDoubleClick );
+ };
+ },
+ [ editorMode, __unstableSetEditorMode ]
+ );
+}
diff --git a/packages/block-editor/src/components/block-lock/style.scss b/packages/block-editor/src/components/block-lock/style.scss
index 8dc6bfb2021f0..ad59030a8f440 100644
--- a/packages/block-editor/src/components/block-lock/style.scss
+++ b/packages/block-editor/src/components/block-lock/style.scss
@@ -41,7 +41,7 @@
&:hover {
background-color: $gray-100;
- border-radius: $radius-block-ui;
+ border-radius: $radius-small;
}
}
diff --git a/packages/block-editor/src/components/block-mover/style.scss b/packages/block-editor/src/components/block-mover/style.scss
index 11bc362663a4d..c58ac9f19673f 100644
--- a/packages/block-editor/src/components/block-mover/style.scss
+++ b/packages/block-editor/src/components/block-mover/style.scss
@@ -76,7 +76,7 @@
content: "";
position: absolute;
display: block;
- border-radius: $radius-block-ui;
+ border-radius: $radius-small;
height: $grid-unit-40;
// Position the focus rectangle.
diff --git a/packages/block-editor/src/components/block-pattern-setup/index.js b/packages/block-editor/src/components/block-pattern-setup/index.js
index edd55e90dc3e2..83cceca7a20a7 100644
--- a/packages/block-editor/src/components/block-pattern-setup/index.js
+++ b/packages/block-editor/src/components/block-pattern-setup/index.js
@@ -3,10 +3,7 @@
*/
import { useDispatch } from '@wordpress/data';
import { cloneBlock } from '@wordpress/blocks';
-import {
- VisuallyHidden,
- privateApis as componentsPrivateApis,
-} from '@wordpress/components';
+import { Composite, VisuallyHidden } from '@wordpress/components';
import { useState } from '@wordpress/element';
import { useInstanceId } from '@wordpress/compose';
@@ -20,13 +17,6 @@ import BlockPreview from '../block-preview';
import SetupToolbar from './setup-toolbar';
import usePatternsSetup from './use-patterns-setup';
import { VIEWMODES } from './constants';
-import { unlock } from '../../lock-unlock';
-
-const {
- CompositeV2: Composite,
- CompositeItemV2: CompositeItem,
- useCompositeStoreV2: useCompositeStore,
-} = unlock( componentsPrivateApis );
const SetupContent = ( {
viewMode,
@@ -35,7 +25,6 @@ const SetupContent = ( {
onBlockPatternSelect,
showTitles,
} ) => {
- const compositeStore = useCompositeStore();
const containerClass = 'block-editor-block-pattern-setup__container';
if ( viewMode === VIEWMODES.carousel ) {
@@ -65,7 +54,6 @@ const SetupContent = ( {
return (
-
) }
-
+
);
}
diff --git a/packages/block-editor/src/components/block-pattern-setup/style.scss b/packages/block-editor/src/components/block-pattern-setup/style.scss
index 3474eed5be517..10582a7a2ce49 100644
--- a/packages/block-editor/src/components/block-pattern-setup/style.scss
+++ b/packages/block-editor/src/components/block-pattern-setup/style.scss
@@ -4,7 +4,7 @@
justify-content: center;
align-items: flex-start;
width: 100%;
- border-radius: $radius-block-ui;
+ border-radius: $radius-small;
&.view-mode-grid {
padding-top: $grid-unit-05;
@@ -60,7 +60,7 @@
.block-editor-block-preview__container {
min-height: 100px;
- border-radius: $radius-block-ui;
+ border-radius: $radius-medium;
border: $border-width solid $gray-300;
}
diff --git a/packages/block-editor/src/components/block-patterns-list/index.js b/packages/block-editor/src/components/block-patterns-list/index.js
index 47deb777a84aa..2609cc2db97a1 100644
--- a/packages/block-editor/src/components/block-patterns-list/index.js
+++ b/packages/block-editor/src/components/block-patterns-list/index.js
@@ -9,9 +9,9 @@ import clsx from 'clsx';
import { cloneBlock } from '@wordpress/blocks';
import { useEffect, useState, forwardRef, useMemo } from '@wordpress/element';
import {
+ Composite,
VisuallyHidden,
Tooltip,
- privateApis as componentsPrivateApis,
__experimentalHStack as HStack,
} from '@wordpress/components';
import { useInstanceId } from '@wordpress/compose';
@@ -21,16 +21,11 @@ import { Icon, symbol } from '@wordpress/icons';
/**
* Internal dependencies
*/
-import { unlock } from '../../lock-unlock';
import BlockPreview from '../block-preview';
import InserterDraggableBlocks from '../inserter-draggable-blocks';
import BlockPatternsPaging from '../block-patterns-paging';
import { INSERTER_PATTERN_TYPES } from '../inserter/block-patterns-tab/utils';
-const { CompositeV2: Composite, CompositeItemV2: CompositeItem } = unlock(
- componentsPrivateApis
-);
-
const WithToolTip = ( { showTooltip, title, children } ) => {
if ( showTooltip ) {
return { children } ;
@@ -105,7 +100,7 @@ function BlockPattern( {
}
title={ pattern.title }
>
-
) }
-
+
) }
diff --git a/packages/block-editor/src/components/block-patterns-list/style.scss b/packages/block-editor/src/components/block-patterns-list/style.scss
index 6b23c1e844dad..84e95563737c3 100644
--- a/packages/block-editor/src/components/block-patterns-list/style.scss
+++ b/packages/block-editor/src/components/block-patterns-list/style.scss
@@ -36,12 +36,12 @@
display: flex;
align-items: center;
overflow: hidden;
- border-radius: $radius-block-ui;
+ border-radius: $radius-medium;
&::after {
outline: $border-width solid rgba($black, 0.1);
outline-offset: -$border-width;
- border-radius: $radius-block-ui;
+ border-radius: $radius-medium;
}
}
diff --git a/packages/block-editor/src/components/block-switcher/pattern-transformations-menu.js b/packages/block-editor/src/components/block-switcher/pattern-transformations-menu.js
index 46fd83c92d91f..7d66e19a214a2 100644
--- a/packages/block-editor/src/components/block-switcher/pattern-transformations-menu.js
+++ b/packages/block-editor/src/components/block-switcher/pattern-transformations-menu.js
@@ -7,11 +7,11 @@ import { useInstanceId, useViewportMatch } from '@wordpress/compose';
import { chevronRight } from '@wordpress/icons';
import {
+ Composite,
MenuGroup,
MenuItem,
Popover,
VisuallyHidden,
- privateApis as componentsPrivateApis,
} from '@wordpress/components';
/**
@@ -19,13 +19,6 @@ import {
*/
import BlockPreview from '../block-preview';
import useTransformedPatterns from './use-transformed-patterns';
-import { unlock } from '../../lock-unlock';
-
-const {
- CompositeV2: Composite,
- CompositeItemV2: CompositeItem,
- useCompositeStoreV2: useCompositeStore,
-} = unlock( componentsPrivateApis );
function PatternTransformationsMenu( {
blocks,
@@ -82,10 +75,8 @@ function PreviewPatternsPopover( { patterns, onSelect } ) {
}
function BlockPatternsList( { patterns, onSelect } ) {
- const composite = useCompositeStore();
return (
-
{ pattern.title }
-
+
{ !! pattern.description && (
{ pattern.description }
diff --git a/packages/block-editor/src/components/block-switcher/style.scss b/packages/block-editor/src/components/block-switcher/style.scss
index 287afaed4055c..823a656668a62 100644
--- a/packages/block-editor/src/components/block-switcher/style.scss
+++ b/packages/block-editor/src/components/block-switcher/style.scss
@@ -99,7 +99,7 @@
width: 300px;
border: $border-width solid $gray-900;
background: $white;
- border-radius: $radius-block-ui;
+ border-radius: $radius-medium;
outline: none;
box-shadow: none;
overflow: auto;
@@ -161,7 +161,7 @@
.block-editor-block-switcher__preview-patterns-container-list__item {
height: 100%;
- border-radius: $radius-block-ui;
+ border-radius: $radius-small;
transition: all 0.05s ease-in-out;
position: relative;
border: $border-width solid transparent;
diff --git a/packages/block-editor/src/components/block-toolbar/index.js b/packages/block-editor/src/components/block-toolbar/index.js
index 13dfd6b33e56a..b14ceb5059049 100644
--- a/packages/block-editor/src/components/block-toolbar/index.js
+++ b/packages/block-editor/src/components/block-toolbar/index.js
@@ -65,6 +65,7 @@ export function PrivateBlockToolbar( {
shouldShowVisualToolbar,
showParentSelector,
isUsingBindings,
+ hasParentPattern,
} = useSelect( ( select ) => {
const {
getBlockName,
@@ -74,6 +75,7 @@ export function PrivateBlockToolbar( {
isBlockValid,
getBlockEditingMode,
getBlockAttributes,
+ getBlockParentsByBlockName,
} = select( blockEditorStore );
const selectedBlockClientIds = getSelectedBlockClientIds();
const selectedBlockClientId = selectedBlockClientIds[ 0 ];
@@ -94,6 +96,13 @@ export function PrivateBlockToolbar( {
( clientId ) =>
!! getBlockAttributes( clientId )?.metadata?.bindings
);
+
+ const _hasParentPattern = selectedBlockClientIds.every(
+ ( clientId ) =>
+ getBlockParentsByBlockName( clientId, 'core/block', true )
+ .length > 0
+ );
+
return {
blockClientId: selectedBlockClientId,
blockClientIds: selectedBlockClientIds,
@@ -113,6 +122,7 @@ export function PrivateBlockToolbar( {
selectedBlockClientIds.length === 1 &&
_isDefaultEditingMode,
isUsingBindings: _isUsingBindings,
+ hasParentPattern: _hasParentPattern,
};
}, [] );
@@ -167,7 +177,7 @@ export function PrivateBlockToolbar( {
isDefaultEditingMode && }
{ ( shouldShowVisualToolbar || isMultiToolbar ) &&
( isDefaultEditingMode ||
- isContentOnlyEditingMode ||
+ ( isContentOnlyEditingMode && ! hasParentPattern ) ||
isSynced ) && (
div,
diff --git a/packages/block-editor/src/components/default-block-appender/content.scss b/packages/block-editor/src/components/default-block-appender/content.scss
index 77725d2508ec5..51e0b4381a15d 100644
--- a/packages/block-editor/src/components/default-block-appender/content.scss
+++ b/packages/block-editor/src/components/default-block-appender/content.scss
@@ -48,7 +48,6 @@
.block-editor-inserter__toggle.components-button.has-icon {
// Basic look
background: $gray-900;
- border-radius: $radius-block-ui;
color: $white;
padding: 0;
diff --git a/packages/block-editor/src/components/global-styles/color-panel.js b/packages/block-editor/src/components/global-styles/color-panel.js
index 15f06310176c7..87c19adedbb27 100644
--- a/packages/block-editor/src/components/global-styles/color-panel.js
+++ b/packages/block-editor/src/components/global-styles/color-panel.js
@@ -33,7 +33,7 @@ import { unlock } from '../../lock-unlock';
export function useHasColorPanel( settings ) {
const hasTextPanel = useHasTextPanel( settings );
- const hasBackgroundPanel = useHasBackgroundPanel( settings );
+ const hasBackgroundPanel = useHasBackgroundColorPanel( settings );
const hasLinkPanel = useHasLinkPanel( settings );
const hasHeadingPanel = useHasHeadingPanel( settings );
const hasButtonPanel = useHasButtonPanel( settings );
@@ -97,7 +97,7 @@ export function useHasButtonPanel( settings ) {
);
}
-export function useHasBackgroundPanel( settings ) {
+export function useHasBackgroundColorPanel( settings ) {
const colors = useColorsPerOrigin( settings );
const gradients = useGradientsPerOrigin( settings );
return (
@@ -347,7 +347,7 @@ export default function ColorPanel( {
};
// BackgroundColor
- const showBackgroundPanel = useHasBackgroundPanel( settings );
+ const showBackgroundPanel = useHasBackgroundColorPanel( settings );
const backgroundColor = decodeValue( inheritedValue?.color?.background );
const userBackgroundColor = decodeValue( value?.color?.background );
const gradient = decodeValue( inheritedValue?.color?.gradient );
diff --git a/packages/block-editor/src/components/global-styles/color-panel.native.js b/packages/block-editor/src/components/global-styles/color-panel.native.js
index fcbff4e5a07d7..87002b5fa3e22 100644
--- a/packages/block-editor/src/components/global-styles/color-panel.native.js
+++ b/packages/block-editor/src/components/global-styles/color-panel.native.js
@@ -18,7 +18,7 @@ import InspectorControls from '../inspector-controls';
import {
useHasColorPanel,
useHasTextPanel,
- useHasBackgroundPanel,
+ useHasBackgroundColorPanel,
} from './color-panel.js';
import { useGlobalStyles } from './use-global-styles-context';
@@ -95,7 +95,7 @@ const ColorPanel = ( {
);
// BackgroundColor
- const showBackgroundPanel = useHasBackgroundPanel( settings );
+ const showBackgroundPanel = useHasBackgroundColorPanel( settings );
const backgroundColor = decodeValue( inheritedValue?.color?.background );
const gradient = decodeValue( inheritedValue?.color?.gradient );
const setBackgroundColor = useCallback(
diff --git a/packages/block-editor/src/components/global-styles/shadow-panel-components.js b/packages/block-editor/src/components/global-styles/shadow-panel-components.js
index e3a6c71adf8fc..1ed367e3c3ad0 100644
--- a/packages/block-editor/src/components/global-styles/shadow-panel-components.js
+++ b/packages/block-editor/src/components/global-styles/shadow-panel-components.js
@@ -10,7 +10,7 @@ import {
Button,
FlexItem,
Dropdown,
- privateApis as componentsPrivateApis,
+ Composite,
} from '@wordpress/components';
import { useMemo } from '@wordpress/element';
import { shadow as shadowIcon, Icon, check } from '@wordpress/icons';
@@ -20,11 +20,6 @@ import { shadow as shadowIcon, Icon, check } from '@wordpress/icons';
*/
import clsx from 'clsx';
-/**
- * Internal dependencies
- */
-import { unlock } from '../../lock-unlock';
-
/**
* Shared reference to an empty array for cases where it is important to avoid
* returning a new array reference on every invocation.
@@ -32,11 +27,6 @@ import { unlock } from '../../lock-unlock';
* @type {Array}
*/
const EMPTY_ARRAY = [];
-const {
- CompositeItemV2: CompositeItem,
- CompositeV2: Composite,
- useCompositeStoreV2: useCompositeStore,
-} = unlock( componentsPrivateApis );
export function ShadowPopoverContainer( { shadow, onShadowChange, settings } ) {
const shadows = useShadowPresets( settings );
@@ -66,10 +56,8 @@ export function ShadowPopoverContainer( { shadow, onShadowChange, settings } ) {
}
export function ShadowPresets( { presets, activeShadow, onSelect } ) {
- const compositeStore = useCompositeStore();
return ! presets ? null : (
{
nearestFontWeight: '400',
},
},
+ {
+ message:
+ 'should return nearest fontStyle and fontWeight for normal/400 when fontFamilyFaces contain numerical fontWeight value',
+ fontFamilyFaces: [
+ {
+ fontFamily: 'IBM Plex Mono',
+ fontStyle: 'normal',
+ fontWeight: 400,
+ src: [
+ 'file:./assets/fonts/ibm-plex-mono/IBMPlexMono-Regular.woff2',
+ ],
+ },
+ {
+ fontFamily: 'IBM Plex Mono',
+ fontStyle: 'italic',
+ fontWeight: '400',
+ src: [
+ 'file:./assets/fonts/ibm-plex-mono/IBMPlexMono-Italic.woff2',
+ ],
+ },
+ {
+ fontFamily: 'IBM Plex Mono',
+ fontStyle: 'normal',
+ fontWeight: '700',
+ src: [
+ 'file:./assets/fonts/ibm-plex-mono/IBMPlexMono-Bold.woff2',
+ ],
+ },
+ ],
+ fontStyle: 'normal',
+ fontWeight: '400',
+ expected: {
+ nearestFontStyle: 'normal',
+ nearestFontWeight: '400',
+ },
+ },
+ {
+ message:
+ 'should return nearest fontStyle and fontWeight for normal/400 when fontFamilyFaces contain undefined fontWeight value',
+ fontFamilyFaces: [
+ {
+ fontFamily: 'IBM Plex Mono',
+ fontStyle: 'normal',
+ src: [
+ 'file:./assets/fonts/ibm-plex-mono/IBMPlexMono-Regular.woff2',
+ ],
+ },
+ ],
+ fontStyle: 'normal',
+ fontWeight: '400',
+ expected: {
+ nearestFontStyle: 'normal',
+ nearestFontWeight: '700',
+ },
+ },
].forEach(
( {
message,
diff --git a/packages/block-editor/src/components/global-styles/typography-utils.js b/packages/block-editor/src/components/global-styles/typography-utils.js
index 32fbd50db2dbf..4b7c90ae4f222 100644
--- a/packages/block-editor/src/components/global-styles/typography-utils.js
+++ b/packages/block-editor/src/components/global-styles/typography-utils.js
@@ -174,6 +174,10 @@ export function findNearestFontWeight(
availableFontWeights,
newFontWeightValue
) {
+ newFontWeightValue =
+ 'number' === typeof newFontWeightValue
+ ? newFontWeightValue.toString()
+ : newFontWeightValue;
if ( ! newFontWeightValue || typeof newFontWeightValue !== 'string' ) {
return '';
}
@@ -260,7 +264,7 @@ export function findNearestStyleAndWeight(
( { value: fs } ) => fs === fontStyle
);
const hasFontWeight = fontWeights?.some(
- ( { value: fw } ) => fw === fontWeight
+ ( { value: fw } ) => fw?.toString() === fontWeight?.toString()
);
if ( ! hasFontStyle ) {
diff --git a/packages/block-editor/src/components/grid/style.scss b/packages/block-editor/src/components/grid/style.scss
index 6790d683ca7d0..3a04eb006e791 100644
--- a/packages/block-editor/src/components/grid/style.scss
+++ b/packages/block-editor/src/components/grid/style.scss
@@ -117,7 +117,7 @@
content: "";
position: absolute;
display: block;
- border-radius: $radius-block-ui;
+ border-radius: $radius-small;
height: $grid-unit-40;
// Position the focus rectangle.
diff --git a/packages/block-editor/src/components/inner-blocks/index.js b/packages/block-editor/src/components/inner-blocks/index.js
index c8db9f8cebf90..0d35b459190fe 100644
--- a/packages/block-editor/src/components/inner-blocks/index.js
+++ b/packages/block-editor/src/components/inner-blocks/index.js
@@ -203,7 +203,7 @@ export function useInnerBlocksProps( props = {}, options = {} ) {
getBlockEditingMode,
getBlockSettings,
isDragging,
- getSettings,
+ getSectionRootClientId,
} = unlock( select( blockEditorStore ) );
let _isDropZoneDisabled;
@@ -225,7 +225,7 @@ export function useInnerBlocksProps( props = {}, options = {} ) {
// In zoom out mode, we want to disable the drop zone for the sections.
// The inner blocks belonging to the section drop zone is
// already disabled by the blocks themselves being disabled.
- const { sectionRootClientId } = unlock( getSettings() );
+ const sectionRootClientId = getSectionRootClientId();
_isDropZoneDisabled = clientId !== sectionRootClientId;
}
diff --git a/packages/block-editor/src/components/inserter-list-item/style.scss b/packages/block-editor/src/components/inserter-list-item/style.scss
index f91e4365db30c..435f60ed9e2f1 100644
--- a/packages/block-editor/src/components/inserter-list-item/style.scss
+++ b/packages/block-editor/src/components/inserter-list-item/style.scss
@@ -43,7 +43,6 @@
cursor: pointer;
background: transparent;
word-break: break-word;
- border-radius: $radius-block-ui;
transition: all 0.05s ease-in-out;
@include reduce-motion("transition");
position: relative;
@@ -72,7 +71,7 @@
bottom: 0;
left: 0;
right: 0;
- border-radius: $radius-block-ui;
+ border-radius: $radius-small;
opacity: 0.04;
background: var(--wp-admin-theme-color);
// This fixes drag-and-drop in Firefox.
@@ -97,7 +96,6 @@
.block-editor-block-types-list__item-icon {
padding: 12px 20px;
- border-radius: $radius-block-ui;
color: $gray-900;
transition: all 0.05s ease-in-out;
@include reduce-motion("transition");
diff --git a/packages/block-editor/src/components/inserter-listbox/index.js b/packages/block-editor/src/components/inserter-listbox/index.js
index 6af26a1d746bf..bc833b0e4c36b 100644
--- a/packages/block-editor/src/components/inserter-listbox/index.js
+++ b/packages/block-editor/src/components/inserter-listbox/index.js
@@ -1,28 +1,19 @@
/**
* WordPress dependencies
*/
-import { privateApis as componentsPrivateApis } from '@wordpress/components';
+import { Composite } from '@wordpress/components';
/**
* Internal dependencies
*/
-import { unlock } from '../../lock-unlock';
export { default as InserterListboxGroup } from './group';
export { default as InserterListboxRow } from './row';
export { default as InserterListboxItem } from './item';
-const { CompositeV2: Composite, useCompositeStoreV2: useCompositeStore } =
- unlock( componentsPrivateApis );
-
function InserterListbox( { children } ) {
- const store = useCompositeStore( {
- focusShift: true,
- focusWrap: 'horizontal',
- } );
-
return (
- > }>
+ > }>
{ children }
);
diff --git a/packages/block-editor/src/components/inserter-listbox/item.js b/packages/block-editor/src/components/inserter-listbox/item.js
index 825c3fdfc353c..69c316bdbbcce 100644
--- a/packages/block-editor/src/components/inserter-listbox/item.js
+++ b/packages/block-editor/src/components/inserter-listbox/item.js
@@ -1,28 +1,18 @@
/**
* WordPress dependencies
*/
-import {
- Button,
- privateApis as componentsPrivateApis,
-} from '@wordpress/components';
+import { Button, Composite } from '@wordpress/components';
import { forwardRef } from '@wordpress/element';
-/**
- * Internal dependencies
- */
-import { unlock } from '../../lock-unlock';
-
-const { CompositeItemV2: CompositeItem } = unlock( componentsPrivateApis );
-
function InserterListboxItem(
{ isFirst, as: Component, children, ...props },
ref
) {
return (
- ;
+ return ;
}
export default forwardRef( InserterListboxRow );
diff --git a/packages/block-editor/src/components/inserter/media-tab/media-list.js b/packages/block-editor/src/components/inserter/media-tab/media-list.js
index bfc858bc8c4de..73f38cfc306fb 100644
--- a/packages/block-editor/src/components/inserter/media-tab/media-list.js
+++ b/packages/block-editor/src/components/inserter/media-tab/media-list.js
@@ -1,17 +1,13 @@
/**
* WordPress dependencies
*/
-import { privateApis as componentsPrivateApis } from '@wordpress/components';
+import { Composite } from '@wordpress/components';
import { __ } from '@wordpress/i18n';
/**
* Internal dependencies
*/
import { MediaPreview } from './media-preview';
-import { unlock } from '../../../lock-unlock';
-
-const { CompositeV2: Composite, useCompositeStoreV2: useCompositeStore } =
- unlock( componentsPrivateApis );
function MediaList( {
mediaList,
@@ -19,10 +15,8 @@ function MediaList( {
onClick,
label = __( 'Media List' ),
} ) {
- const compositeStore = useCompositeStore();
return (
-
) }
-
+
{ ! isInserting && (
{};
function InserterMenu(
@@ -102,12 +101,12 @@ function InserterMenu(
window.requestAnimationFrame( () => {
if (
! shouldFocusBlock &&
- ! blockTypesTabRef?.current.contains(
+ ! blockTypesTabRef.current?.contains(
ref.current.ownerDocument.activeElement
)
) {
// There has been a focus loss, so focus the first button in the block types tab
- blockTypesTabRef?.current.querySelector( 'button' ).focus();
+ blockTypesTabRef.current?.querySelector( 'button' ).focus();
}
} );
},
@@ -147,11 +146,6 @@ function InserterMenu(
const showMediaPanel = selectedTab === 'media' && !! selectedMediaCategory;
- const showZoomOut =
- showPatternPanel && !! window.__experimentalEnableZoomedOutPatternsTab;
-
- useZoomOut( showZoomOut );
-
const inserterSearch = useMemo( () => {
if ( selectedTab === 'media' ) {
return null;
diff --git a/packages/block-editor/src/components/inserter/style.scss b/packages/block-editor/src/components/inserter/style.scss
index 21f8abfa59c9e..bd3ac3f961b88 100644
--- a/packages/block-editor/src/components/inserter/style.scss
+++ b/packages/block-editor/src/components/inserter/style.scss
@@ -44,12 +44,12 @@ $block-inserter-tabs-height: 44px;
&:first-child {
border-top: $border-width solid $gray-400;
- border-radius: $radius-block-ui $radius-block-ui 0 0;
+ border-radius: $radius-medium $radius-medium 0 0;
}
&:last-child {
border-bottom: $border-width solid $gray-400;
- border-radius: 0 0 $radius-block-ui $radius-block-ui;
+ border-radius: 0 0 $radius-medium $radius-medium;
}
&.components-button {
@@ -276,7 +276,7 @@ $block-inserter-tabs-height: 44px;
bottom: 0;
left: 0;
right: 0;
- border-radius: $radius-block-ui;
+ border-radius: $radius-small;
opacity: 0.04;
background: var(--wp-admin-theme-color);
height: 100%;
@@ -359,7 +359,7 @@ $block-inserter-tabs-height: 44px;
min-height: $grid-unit-60 * 3;
color: $gray-700;
background: $gray-100;
- border-radius: $radius-block-ui;
+ border-radius: $radius-small;
}
.block-editor-inserter__tips {
@@ -577,7 +577,6 @@ $block-inserter-tabs-height: 44px;
> button {
background: $white;
- border-radius: $radius-block-ui;
display: none;
// These styles are important so as focus isn't lost
@@ -611,7 +610,6 @@ $block-inserter-tabs-height: 44px;
max-width: 100%;
outline: $border-width solid rgba($black, 0.1);
outline-offset: -$border-width;
- border-radius: $radius-block-ui;
}
.block-editor-inserter__media-list__item-preview-spinner {
diff --git a/packages/block-editor/src/components/inspector-controls-tabs/settings-tab.js b/packages/block-editor/src/components/inspector-controls-tabs/settings-tab.js
index ec34035b754a9..ea2f45114bf9c 100644
--- a/packages/block-editor/src/components/inspector-controls-tabs/settings-tab.js
+++ b/packages/block-editor/src/components/inspector-controls-tabs/settings-tab.js
@@ -9,6 +9,7 @@ const SettingsTab = ( { showAdvancedControls = false } ) => (
<>
+
{ showAdvancedControls && (
diff --git a/packages/block-editor/src/components/inspector-controls-tabs/use-inspector-controls-tabs.js b/packages/block-editor/src/components/inspector-controls-tabs/use-inspector-controls-tabs.js
index ff68be82a829f..6a80d47f02481 100644
--- a/packages/block-editor/src/components/inspector-controls-tabs/use-inspector-controls-tabs.js
+++ b/packages/block-editor/src/components/inspector-controls-tabs/use-inspector-controls-tabs.js
@@ -32,6 +32,7 @@ function getShowTabs( blockName, tabSettings = {} ) {
export default function useInspectorControlsTabs( blockName ) {
const tabs = [];
const {
+ bindings: bindingsGroup,
border: borderGroup,
color: colorGroup,
default: defaultGroup,
@@ -64,8 +65,10 @@ export default function useInspectorControlsTabs( blockName ) {
// (i.e. both list view and styles), check only the default and position
// InspectorControls slots. If we have multiple tabs, we'll need to check
// the advanced controls slot as well to ensure they are rendered.
- const advancedFills =
- useSlotFills( InspectorAdvancedControls.slotName ) || [];
+ const advancedFills = [
+ ...( useSlotFills( InspectorAdvancedControls.slotName ) || [] ),
+ ...( useSlotFills( bindingsGroup.Slot.__unstableName ) || [] ),
+ ];
const settingsFills = [
...( useSlotFills( defaultGroup.Slot.__unstableName ) || [] ),
diff --git a/packages/block-editor/src/components/inspector-controls/groups.js b/packages/block-editor/src/components/inspector-controls/groups.js
index 9ca1a72b9918a..34ec49a5e1cb4 100644
--- a/packages/block-editor/src/components/inspector-controls/groups.js
+++ b/packages/block-editor/src/components/inspector-controls/groups.js
@@ -5,6 +5,7 @@ import { createSlotFill } from '@wordpress/components';
const InspectorControlsDefault = createSlotFill( 'InspectorControls' );
const InspectorControlsAdvanced = createSlotFill( 'InspectorAdvancedControls' );
+const InspectorControlsBindings = createSlotFill( 'InspectorControlsBindings' );
const InspectorControlsBackground = createSlotFill(
'InspectorControlsBackground'
);
@@ -26,6 +27,7 @@ const groups = {
default: InspectorControlsDefault,
advanced: InspectorControlsAdvanced,
background: InspectorControlsBackground,
+ bindings: InspectorControlsBindings,
border: InspectorControlsBorder,
color: InspectorControlsColor,
dimensions: InspectorControlsDimensions,
diff --git a/packages/block-editor/src/components/link-control/style.scss b/packages/block-editor/src/components/link-control/style.scss
index 1390a285fe163..b0a5f6af2651b 100644
--- a/packages/block-editor/src/components/link-control/style.scss
+++ b/packages/block-editor/src/components/link-control/style.scss
@@ -78,7 +78,6 @@ $block-editor-link-control-number-of-actions: 1;
@include input-control;
display: block;
border: $border-width solid $gray-600;
- border-radius: $radius-block-ui;
height: $button-size-next-default-40px; // components do not properly support unstable-large yet.
margin: 0;
padding: $grid-unit-10 $button-size-next-default-40px $grid-unit-10 $grid-unit-20;
@@ -230,7 +229,7 @@ $block-editor-link-control-number-of-actions: 1;
background-color: $gray-100;
width: $grid-unit-40;
height: $grid-unit-40;
- border-radius: $radius-block-ui;
+ border-radius: $radius-small;
}
.block-editor-link-control__search-item-icon {
@@ -252,7 +251,6 @@ $block-editor-link-control-number-of-actions: 1;
}
.block-editor-link-control__search-item-title {
- border-radius: $radius-block-ui;
line-height: 1.1;
diff --git a/packages/block-editor/src/components/list-view/style.scss b/packages/block-editor/src/components/list-view/style.scss
index 406053af89317..3d25597d2af90 100644
--- a/packages/block-editor/src/components/list-view/style.scss
+++ b/packages/block-editor/src/components/list-view/style.scss
@@ -101,16 +101,16 @@
// Border radius for corners of the selected item.
&.is-first-selected td:first-child {
- border-top-left-radius: $radius-block-ui;
+ border-top-left-radius: $radius-small;
}
&.is-first-selected td:last-child {
- border-top-right-radius: $radius-block-ui;
+ border-top-right-radius: $radius-small;
}
&.is-last-selected td:first-child {
- border-bottom-left-radius: $radius-block-ui;
+ border-bottom-left-radius: $radius-small;
}
&.is-last-selected td:last-child {
- border-bottom-right-radius: $radius-block-ui;
+ border-bottom-right-radius: $radius-small;
}
&.is-branch-selected:not(.is-selected):not(.is-synced-branch) {
background: rgba(var(--wp-admin-theme-color--rgb), 0.04);
@@ -119,23 +119,23 @@
background: rgba(var(--wp-block-synced-color--rgb), 0.04);
}
&.is-branch-selected.is-first-selected td:first-child {
- border-top-left-radius: $radius-block-ui;
+ border-top-left-radius: $radius-small;
}
&.is-branch-selected.is-first-selected td:last-child {
- border-top-right-radius: $radius-block-ui;
+ border-top-right-radius: $radius-small;
}
&[data-expanded="false"] {
&.is-branch-selected.is-first-selected td:first-child {
- border-top-left-radius: $radius-block-ui;
+ border-top-left-radius: $radius-small;
}
&.is-branch-selected.is-first-selected td:last-child {
- border-top-right-radius: $radius-block-ui;
+ border-top-right-radius: $radius-small;
}
&.is-branch-selected.is-last-selected td:first-child {
- border-bottom-left-radius: $radius-block-ui;
+ border-bottom-left-radius: $radius-small;
}
&.is-branch-selected.is-last-selected td:last-child {
- border-bottom-right-radius: $radius-block-ui;
+ border-bottom-right-radius: $radius-small;
}
}
&.is-branch-selected:not(.is-selected) td {
@@ -214,7 +214,6 @@
height: $grid-unit-40;
padding: ($grid-unit-15 * 0.5) $grid-unit-05 ($grid-unit-15 * 0.5) 0;
text-align: left;
- border-radius: $radius-block-ui;
position: relative;
white-space: nowrap;
@@ -406,7 +405,7 @@
right: 0;
transform: translateY(-50%);
background: rgba($black, 0.1);
- border-radius: $radius-block-ui;
+ border-radius: $radius-x-small;
padding: 2px 6px;
max-width: 100%;
box-sizing: border-box;
@@ -429,10 +428,10 @@
background-size: cover;
width: 18px;
height: 18px;
- border-radius: $radius-block-ui;
+ border-radius: $radius-x-small;
&:not(:only-child) {
- box-shadow: 0 0 0 $radius-block-ui $white;
+ box-shadow: 0 0 0 $radius-small $white;
}
&:not(:first-child) {
@@ -442,7 +441,7 @@
&.is-selected .block-editor-list-view-block-select-button__image {
&:not(:only-child) {
- box-shadow: 0 0 0 $radius-block-ui var(--wp-admin-theme-color);
+ box-shadow: 0 0 0 $radius-small var(--wp-admin-theme-color);
}
}
}
diff --git a/packages/block-editor/src/components/media-placeholder/README.md b/packages/block-editor/src/components/media-placeholder/README.md
index 6cb00206d93d7..68fcf150c4edc 100644
--- a/packages/block-editor/src/components/media-placeholder/README.md
+++ b/packages/block-editor/src/components/media-placeholder/README.md
@@ -198,9 +198,9 @@ Callback called when urls can be configured. No media insertion from url will be
### handleUpload
-When set to false the handling of the upload is left to the calling component.
+When the value is set to `false` or returned as `false`, the handling of the upload is left to the consumer component. The function signature accepts an array containing the files to be uploaded.
-- Type: `Boolean`
+- Type: `Boolean|Function`
- Required: No
- Default: `true`
- Platform: Web
diff --git a/packages/block-editor/src/components/media-placeholder/index.js b/packages/block-editor/src/components/media-placeholder/index.js
index a5b4eb0bf19b3..bbf546a3953f3 100644
--- a/packages/block-editor/src/components/media-placeholder/index.js
+++ b/packages/block-editor/src/components/media-placeholder/index.js
@@ -172,7 +172,10 @@ export function MediaPlaceholder( {
};
const onFilesUpload = ( files ) => {
- if ( ! handleUpload ) {
+ if (
+ ! handleUpload ||
+ ( typeof handleUpload === 'function' && ! handleUpload( files ) )
+ ) {
return onSelect( files );
}
onFilesPreUpload( files );
diff --git a/packages/block-editor/src/components/responsive-block-control/README.md b/packages/block-editor/src/components/responsive-block-control/README.md
index 379e245f03ff3..16183ccd6314f 100644
--- a/packages/block-editor/src/components/responsive-block-control/README.md
+++ b/packages/block-editor/src/components/responsive-block-control/README.md
@@ -27,9 +27,6 @@ import {
InspectorControls,
__experimentalResponsiveBlockControl as ResponsiveBlockControl,
} from '@wordpress/block-editor';
-import {
- DimensionControl,
-} from '@wordpress/components';
registerBlockType( 'my-plugin/my-block', {
// ...
@@ -37,34 +34,13 @@ registerBlockType( 'my-plugin/my-block', {
edit( { attributes, setAttributes } ) {
const [ isResponsive, setIsResponsive ] = useState( false );
-
- // Used for example purposes only
- const sizeOptions = [
- {
- label: 'Small',
- value: 'small',
- },
- {
- label: 'Medium',
- value: 'medium',
- },
- {
- label: 'Large',
- value: 'large',
- },
- ];
-
const { paddingSize } = attributes;
-
// Your custom control can be anything you'd like to use.
- // You are not restricted to `DimensionControl`s, but this
- // makes life easier if dealing with standard CSS values.
- // see `packages/components/src/dimension-control/README.md`
const paddingControl = ( labelComponent, viewport ) => {
return (
-
{
// id: 'small',
// label: 'All'
// }
- return ;
+ return ;
};
```
diff --git a/packages/block-editor/src/components/rich-text/style.scss b/packages/block-editor/src/components/rich-text/style.scss
index a3bb78b2521db..ca274d378d408 100644
--- a/packages/block-editor/src/components/rich-text/style.scss
+++ b/packages/block-editor/src/components/rich-text/style.scss
@@ -12,7 +12,7 @@
}
.components-toolbar {
- border-radius: $radius-block-ui;
+ border-radius: $radius-small;
}
.components-toolbar__control,
diff --git a/packages/block-editor/src/components/spacing-sizes-control/style.scss b/packages/block-editor/src/components/spacing-sizes-control/style.scss
index cbcc8e30c5825..a387e5369d01e 100644
--- a/packages/block-editor/src/components/spacing-sizes-control/style.scss
+++ b/packages/block-editor/src/components/spacing-sizes-control/style.scss
@@ -19,6 +19,7 @@
.spacing-sizes-control__range-control,
.spacing-sizes-control__custom-value-range {
flex: 1;
+ margin-bottom: 0; // Needed for some instances of the range control, such as the Spacer block.
}
.components-range-control__mark {
diff --git a/packages/block-editor/src/components/use-block-drop-zone/index.js b/packages/block-editor/src/components/use-block-drop-zone/index.js
index 8115fe8f72a64..5af8291523370 100644
--- a/packages/block-editor/src/components/use-block-drop-zone/index.js
+++ b/packages/block-editor/src/components/use-block-drop-zone/index.js
@@ -313,8 +313,8 @@ export default function useBlockDropZone( {
getAllowedBlocks,
isDragging,
isGroupable,
- getSettings,
isZoomOutMode,
+ getSectionRootClientId,
} = unlock( useSelect( blockEditorStore ) );
const {
showInsertionPoint,
@@ -360,7 +360,7 @@ export default function useBlockDropZone( {
return;
}
- const { sectionRootClientId } = unlock( getSettings() );
+ const sectionRootClientId = getSectionRootClientId();
// In Zoom Out mode, if the target is not the section root provided by settings then
// do not allow dropping as the drop target is not within the root (that which is
@@ -492,6 +492,8 @@ export default function useBlockDropZone( {
getBlockNamesByClientId,
getDraggedBlockClientIds,
getBlockType,
+ getSectionRootClientId,
+ isZoomOutMode,
getBlocks,
getBlockListSettings,
dropZoneElement,
@@ -504,8 +506,6 @@ export default function useBlockDropZone( {
isGroupable,
getBlockVariations,
getGroupingBlockName,
- getSettings,
- isZoomOutMode,
]
),
200
diff --git a/packages/block-editor/src/components/warning/content.scss b/packages/block-editor/src/components/warning/content.scss
index 0c1185a0782e4..9380a224b2ff9 100644
--- a/packages/block-editor/src/components/warning/content.scss
+++ b/packages/block-editor/src/components/warning/content.scss
@@ -7,7 +7,7 @@
// Block UI appearance.
border: $border-width solid $gray-900;
- border-radius: $radius-block-ui;
+ border-radius: $radius-small;
background-color: $white;
.block-editor-warning__message {
diff --git a/packages/block-editor/src/hooks/block-bindings.js b/packages/block-editor/src/hooks/block-bindings.js
index 3b90ecc1a0c17..3b59de2238b96 100644
--- a/packages/block-editor/src/hooks/block-bindings.js
+++ b/packages/block-editor/src/hooks/block-bindings.js
@@ -9,11 +9,10 @@ import {
__experimentalText as Text,
__experimentalToolsPanel as ToolsPanel,
__experimentalToolsPanelItem as ToolsPanelItem,
- __experimentalTruncate as Truncate,
__experimentalVStack as VStack,
privateApis as componentsPrivateApis,
} from '@wordpress/components';
-import { useRegistry } from '@wordpress/data';
+import { useRegistry, useSelect } from '@wordpress/data';
import { useContext, Fragment } from '@wordpress/element';
import { useViewportMatch } from '@wordpress/compose';
@@ -28,6 +27,7 @@ import { unlock } from '../lock-unlock';
import InspectorControls from '../components/inspector-controls';
import BlockContext from '../components/block-context';
import { useBlockBindingsUtils } from '../utils/block-bindings';
+import { store as blockEditorStore } from '../store';
const { DropdownMenuV2 } = unlock( componentsPrivateApis );
@@ -96,17 +96,19 @@ function BlockBindingsAttribute( { attribute, binding } ) {
const { source: sourceName, args } = binding || {};
const sourceProps =
unlock( blocksPrivateApis ).getBlockBindingsSource( sourceName );
+ const isSourceInvalid = ! sourceProps;
return (
-
- { attribute }
+
+ { attribute }
{ !! binding && (
-
- { args?.key || sourceProps?.label || sourceName }
-
+ { isSourceInvalid
+ ? __( 'Invalid source' )
+ : args?.key || sourceProps?.label || sourceName }
) }
@@ -195,6 +197,13 @@ export const BlockBindingsPanel = ( { name: blockName, metadata } ) => {
}
} );
+ const { canUpdateBlockBindings } = useSelect( ( select ) => {
+ return {
+ canUpdateBlockBindings:
+ select( blockEditorStore ).getSettings().canUpdateBlockBindings,
+ };
+ }, [] );
+
if ( ! bindableAttributes || bindableAttributes.length === 0 ) {
return null;
}
@@ -230,17 +239,16 @@ export const BlockBindingsPanel = ( { name: blockName, metadata } ) => {
}
} );
- // Lock the UI when the experiment is not enabled or there are no fields to connect to.
+ // Lock the UI when the user can't update bindings or there are no fields to connect to.
const readOnly =
- ! window.__experimentalBlockBindingsUI ||
- ! Object.keys( fieldsList ).length;
+ ! canUpdateBlockBindings || ! Object.keys( fieldsList ).length;
if ( readOnly && Object.keys( filteredBindings ).length === 0 ) {
return null;
}
return (
-
+
{
@@ -262,9 +270,13 @@ export const BlockBindingsPanel = ( { name: blockName, metadata } ) => {
/>
) }
-
- { __( 'Attributes connected to various sources.' ) }
-
+
+
+ { __(
+ 'Attributes connected to custom fields or other dynamic data.'
+ ) }
+
+
);
diff --git a/packages/block-editor/src/hooks/block-bindings.scss b/packages/block-editor/src/hooks/block-bindings.scss
index 69eaa18d57dae..e8f05895922f0 100644
--- a/packages/block-editor/src/hooks/block-bindings.scss
+++ b/packages/block-editor/src/hooks/block-bindings.scss
@@ -1,6 +1,6 @@
div.block-editor-bindings__panel {
grid-template-columns: repeat(auto-fit, minmax(100%, 1fr));
- button:hover .block-editor-bindings__item-explanation {
+ button:hover .block-editor-bindings__item span {
color: inherit;
}
}
diff --git a/packages/block-editor/src/private-apis.js b/packages/block-editor/src/private-apis.js
index 788bb2bef56ef..404c94940058a 100644
--- a/packages/block-editor/src/private-apis.js
+++ b/packages/block-editor/src/private-apis.js
@@ -38,6 +38,7 @@ import {
reusableBlocksSelectKey,
globalStylesDataKey,
globalStylesLinksDataKey,
+ sectionRootClientIdKey,
} from './store/private-keys';
import { requiresWrapperOnCopy } from './components/writing-flow/utils';
import { PrivateRichText } from './components/rich-text/';
@@ -94,4 +95,5 @@ lock( privateApis, {
__unstableBlockStyleVariationOverridesWithConfig,
setBackgroundStyleDefaults,
useBlockBindingsUtils,
+ sectionRootClientIdKey,
} );
diff --git a/packages/block-editor/src/store/actions.js b/packages/block-editor/src/store/actions.js
index 319398667293e..e91f997ca6783 100644
--- a/packages/block-editor/src/store/actions.js
+++ b/packages/block-editor/src/store/actions.js
@@ -34,8 +34,6 @@ import {
__experimentalUpdateSettings,
privateRemoveBlocks,
} from './private-actions';
-import { STORE_NAME } from './constants';
-import { unlock } from '../lock-unlock';
/** @typedef {import('../components/use-on-block-drop/types').WPDropOperation} WPDropOperation */
@@ -1670,13 +1668,13 @@ export const setNavigationMode =
*/
export const __unstableSetEditorMode =
( mode ) =>
- ( { dispatch, select, registry } ) => {
+ ( { dispatch, select } ) => {
// When switching to zoom-out mode, we need to select the parent section
if ( mode === 'zoom-out' ) {
const firstSelectedClientId = select.getBlockSelectionStart();
- const { sectionRootClientId } = unlock(
- registry.select( STORE_NAME ).getSettings()
- );
+
+ const sectionRootClientId = select.getSectionRootClientId();
+
if ( firstSelectedClientId ) {
let sectionClientId;
diff --git a/packages/block-editor/src/store/private-keys.js b/packages/block-editor/src/store/private-keys.js
index 00fac5531b9c3..e24b4a6264e72 100644
--- a/packages/block-editor/src/store/private-keys.js
+++ b/packages/block-editor/src/store/private-keys.js
@@ -2,3 +2,4 @@ export const globalStylesDataKey = Symbol( 'globalStylesDataKey' );
export const globalStylesLinksDataKey = Symbol( 'globalStylesLinks' );
export const selectBlockPatternsKey = Symbol( 'selectBlockPatternsKey' );
export const reusableBlocksSelectKey = Symbol( 'reusableBlocksSelect' );
+export const sectionRootClientIdKey = Symbol( 'sectionRootClientIdKey' );
diff --git a/packages/block-editor/src/store/private-selectors.js b/packages/block-editor/src/store/private-selectors.js
index 9cc793362296c..7e323cee6581a 100644
--- a/packages/block-editor/src/store/private-selectors.js
+++ b/packages/block-editor/src/store/private-selectors.js
@@ -28,6 +28,7 @@ import { unlock } from '../lock-unlock';
import {
selectBlockPatternsKey,
reusableBlocksSelectKey,
+ sectionRootClientIdKey,
} from './private-keys';
export { getBlockSettings } from './get-block-settings';
@@ -543,3 +544,7 @@ export const getBlockStyles = createSelector(
export function isZoomOutMode( state ) {
return state.editorMode === 'zoom-out';
}
+
+export function getSectionRootClientId( state ) {
+ return state.settings?.[ sectionRootClientIdKey ];
+}
diff --git a/packages/block-editor/src/store/selectors.js b/packages/block-editor/src/store/selectors.js
index b30a719d21fd4..30fdb76bdbe78 100644
--- a/packages/block-editor/src/store/selectors.js
+++ b/packages/block-editor/src/store/selectors.js
@@ -37,6 +37,7 @@ import {
getContentLockingParent,
getTemporarilyEditingAsBlocks,
getTemporarilyEditingFocusModeToRevert,
+ getSectionRootClientId,
} from './private-selectors';
/**
@@ -2058,9 +2059,8 @@ export const getInserterItems = createRegistrySelector( ( select ) =>
if ( ! item.rootClientId ) {
let sectionRootClientId;
try {
- sectionRootClientId = unlock(
- getSettings( state )
- ).sectionRootClientId;
+ sectionRootClientId =
+ getSectionRootClientId( state );
} catch ( e ) {}
if (
sectionRootClientId &&
@@ -2838,7 +2838,7 @@ export function __unstableHasActiveBlockOverlayActive( state, clientId ) {
// In zoom-out mode, the block overlay is always active for section level blocks.
if ( editorMode === 'zoom-out' ) {
- const { sectionRootClientId } = unlock( getSettings( state ) );
+ const sectionRootClientId = getSectionRootClientId( state );
if ( sectionRootClientId ) {
const sectionClientIds = getBlockOrder(
state,
@@ -2931,7 +2931,8 @@ export const getBlockEditingMode = createRegistrySelector(
// sections.
const editorMode = __unstableGetEditorMode( state );
if ( editorMode === 'zoom-out' ) {
- const { sectionRootClientId } = unlock( getSettings( state ) );
+ const sectionRootClientId = getSectionRootClientId( state );
+
if ( clientId === '' /* ROOT_CONTAINER_CLIENT_ID */ ) {
return sectionRootClientId ? 'disabled' : 'contentOnly';
}
diff --git a/packages/block-editor/src/utils/dom.js b/packages/block-editor/src/utils/dom.js
index bfdce60b9f006..9c2e813ef742b 100644
--- a/packages/block-editor/src/utils/dom.js
+++ b/packages/block-editor/src/utils/dom.js
@@ -96,11 +96,26 @@ function isElementVisible( element ) {
return false;
}
- return element.checkVisibility( {
- opacityProperty: true,
- contentVisibilityAuto: true,
- visibilityProperty: true,
- } );
+ // Older browsers, e.g. Safari < 17.4 may not support the `checkVisibility` method.
+ if ( element.checkVisibility ) {
+ return element.checkVisibility?.( {
+ opacityProperty: true,
+ contentVisibilityAuto: true,
+ visibilityProperty: true,
+ } );
+ }
+
+ const style = viewport.getComputedStyle( element );
+
+ if (
+ style.display === 'none' ||
+ style.visibility === 'hidden' ||
+ style.opacity === '0'
+ ) {
+ return false;
+ }
+
+ return true;
}
/**
diff --git a/packages/block-editor/src/utils/get-font-styles-and-weights.js b/packages/block-editor/src/utils/get-font-styles-and-weights.js
index 88b40a5aacfeb..dcb56fc86b267 100644
--- a/packages/block-editor/src/utils/get-font-styles-and-weights.js
+++ b/packages/block-editor/src/utils/get-font-styles-and-weights.js
@@ -79,7 +79,10 @@ export function getFontStylesAndWeights( fontFamilyFaces ) {
fontFamilyFaces?.forEach( ( face ) => {
// Check for variable font by looking for a space in the font weight value. e.g. "100 900"
- if ( /\s/.test( face.fontWeight.trim() ) ) {
+ if (
+ 'string' === typeof face.fontWeight &&
+ /\s/.test( face.fontWeight.trim() )
+ ) {
isVariableFont = true;
// Find font weight start and end values.
@@ -105,11 +108,15 @@ export function getFontStylesAndWeights( fontFamilyFaces ) {
}
// Format font style and weight values.
- const fontWeight = formatFontWeight( face.fontWeight );
+ const fontWeight = formatFontWeight(
+ 'number' === typeof face.fontWeight
+ ? face.fontWeight.toString()
+ : face.fontWeight
+ );
const fontStyle = formatFontStyle( face.fontStyle );
// Create font style and font weight lists without duplicates.
- if ( fontStyle ) {
+ if ( fontStyle && Object.keys( fontStyle ).length ) {
if (
! fontStyles.some(
( style ) => style.value === fontStyle.value
@@ -118,7 +125,8 @@ export function getFontStylesAndWeights( fontFamilyFaces ) {
fontStyles.push( fontStyle );
}
}
- if ( fontWeight ) {
+
+ if ( fontWeight && Object.keys( fontWeight ).length ) {
if (
! fontWeights.some(
( weight ) => weight.value === fontWeight.value
diff --git a/packages/block-editor/src/utils/test/get-font-styles-and-weights.js b/packages/block-editor/src/utils/test/get-font-styles-and-weights.js
index ffc1a635aa1fb..7c50409bae1ac 100644
--- a/packages/block-editor/src/utils/test/get-font-styles-and-weights.js
+++ b/packages/block-editor/src/utils/test/get-font-styles-and-weights.js
@@ -343,6 +343,17 @@ describe( 'getFontStylesAndWeights', () => {
fontWeight: '400',
src: 'http://www.wordpress.org/wp-content/uploads/fonts/N0b52SlTPu5rIkWIZjVKKtYtfxYqZ4RJBFzFfYUjkSDdlqZgy7LYxnL31AHfAAy5.woff2',
},
+ {
+ fontFamily: 'Piazzolla',
+ fontStyle: 'normal',
+ fontWeight: 600,
+ src: 'http://www.wordpress.org/wp-content/uploads/fonts/N0b52SlTPu5rIkWIZjVKKtYtfxYqZ4RJBFzFfYUjkSDdlqZgy7JxwXL31AHfAAy5.woff2',
+ },
+ {
+ fontFamily: 'Piazzolla',
+ fontStyle: 'normal',
+ src: 'http://www.wordpress.org/wp-content/uploads/fonts/N0b52SlTPu5rIkWIZjVKKtYtfxYqZ4RJBFzFfYUjkSDdlqZgy7JxwXL31AHfAAy5.woff2',
+ },
{
fontFamily: 'Piazzolla',
fontStyle: 'normal',
@@ -378,6 +389,10 @@ describe( 'getFontStylesAndWeights', () => {
name: 'Regular',
value: '400',
},
+ {
+ name: 'Semi Bold',
+ value: '600',
+ },
{
name: 'Black',
value: '900',
@@ -396,6 +411,14 @@ describe( 'getFontStylesAndWeights', () => {
fontWeight: '400',
},
},
+ {
+ key: 'normal-600',
+ name: 'Semi Bold',
+ style: {
+ fontStyle: 'normal',
+ fontWeight: '600',
+ },
+ },
{
key: 'normal-900',
name: 'Black',
@@ -420,6 +443,14 @@ describe( 'getFontStylesAndWeights', () => {
fontWeight: '400',
},
},
+ {
+ key: 'italic-600',
+ name: 'Semi Bold Italic',
+ style: {
+ fontStyle: 'italic',
+ fontWeight: '600',
+ },
+ },
{
key: 'italic-900',
name: 'Black Italic',
@@ -510,4 +541,121 @@ describe( 'getFontStylesAndWeights', () => {
isVariableFont: false,
} );
} );
+
+ it( 'should return available styles and weights for a font without fontWeight', () => {
+ const fontFamilyFaces = [
+ {
+ fontFamily: 'AR One Sans',
+ fontStyle: 'normal',
+ src: 'http://www.wordpress.org/wp-content/uploads/fonts/AROneSans-VariableFont_ARRRwght.ttf',
+ },
+ ];
+ expect( getFontStylesAndWeights( fontFamilyFaces ) ).toEqual( {
+ fontStyles: [
+ {
+ name: 'Regular',
+ value: 'normal',
+ },
+ {
+ name: 'Italic',
+ value: 'italic',
+ },
+ ],
+ fontWeights: [
+ {
+ name: 'Bold',
+ value: '700',
+ },
+ ],
+ combinedStyleAndWeightOptions: [
+ {
+ key: 'normal-700',
+ name: 'Bold',
+ style: {
+ fontStyle: 'normal',
+ fontWeight: '700',
+ },
+ },
+ {
+ key: 'italic-700',
+ name: 'Bold Italic',
+ style: {
+ fontStyle: 'italic',
+ fontWeight: '700',
+ },
+ },
+ ],
+ isSystemFont: false,
+ isVariableFont: false,
+ } );
+ } );
+
+ it( 'should return available styles and weights for a font with numeric fontWeight', () => {
+ const fontFamilyFaces = [
+ {
+ fontFamily: 'AR One Sans',
+ fontStyle: 'normal',
+ fontWeight: 400,
+ src: 'http://www.wordpress.org/wp-content/uploads/fonts/AROneSans-VariableFont_ARRRwght.ttf',
+ },
+ ];
+ expect( getFontStylesAndWeights( fontFamilyFaces ) ).toEqual( {
+ fontStyles: [
+ {
+ name: 'Regular',
+ value: 'normal',
+ },
+ {
+ name: 'Italic',
+ value: 'italic',
+ },
+ ],
+ fontWeights: [
+ {
+ name: 'Regular',
+ value: '400',
+ },
+ {
+ name: 'Bold',
+ value: '700',
+ },
+ ],
+ combinedStyleAndWeightOptions: [
+ {
+ key: 'normal-400',
+ name: 'Regular',
+ style: {
+ fontStyle: 'normal',
+ fontWeight: '400',
+ },
+ },
+ {
+ key: 'normal-700',
+ name: 'Bold',
+ style: {
+ fontStyle: 'normal',
+ fontWeight: '700',
+ },
+ },
+ {
+ key: 'italic-400',
+ name: 'Regular Italic',
+ style: {
+ fontStyle: 'italic',
+ fontWeight: '400',
+ },
+ },
+ {
+ key: 'italic-700',
+ name: 'Bold Italic',
+ style: {
+ fontStyle: 'italic',
+ fontWeight: '700',
+ },
+ },
+ ],
+ isSystemFont: false,
+ isVariableFont: false,
+ } );
+ } );
} );
diff --git a/packages/block-library/CHANGELOG.md b/packages/block-library/CHANGELOG.md
index 319d2b04a3168..4ee3ebc7564b5 100644
--- a/packages/block-library/CHANGELOG.md
+++ b/packages/block-library/CHANGELOG.md
@@ -2,6 +2,8 @@
## Unreleased
+## 9.7.0 (2024-09-05)
+
## 9.6.0 (2024-08-21)
## 9.5.0 (2024-08-07)
diff --git a/packages/block-library/package.json b/packages/block-library/package.json
index 5b522f01ea778..4d0212490858c 100644
--- a/packages/block-library/package.json
+++ b/packages/block-library/package.json
@@ -1,6 +1,6 @@
{
"name": "@wordpress/block-library",
- "version": "9.6.1",
+ "version": "9.7.0",
"description": "Block library for the WordPress editor.",
"author": "The WordPress Contributors",
"license": "GPL-2.0-or-later",
diff --git a/packages/block-library/src/block/edit.js b/packages/block-library/src/block/edit.js
index 53422e1c4cb8c..5c90361e6bb43 100644
--- a/packages/block-library/src/block/edit.js
+++ b/packages/block-library/src/block/edit.js
@@ -29,6 +29,7 @@ import {
privateApis as blockEditorPrivateApis,
store as blockEditorStore,
BlockControls,
+ InnerBlocks,
} from '@wordpress/block-editor';
import { privateApis as patternsPrivateApis } from '@wordpress/patterns';
import { store as blocksStore } from '@wordpress/blocks';
@@ -193,19 +194,15 @@ function ReusableBlockEdit( {
hasPatternOverridesSource,
} = useSelect(
( select ) => {
- const {
- getBlocks,
- getSettings,
- getBlockEditingMode: _getBlockEditingMode,
- } = select( blockEditorStore );
+ const { getBlocks, getSettings, getBlockEditingMode } =
+ select( blockEditorStore );
const { getBlockBindingsSource } = unlock( select( blocksStore ) );
// For editing link to the site editor if the theme and user permissions support it.
return {
innerBlocks: getBlocks( patternClientId ),
- getBlockEditingMode: _getBlockEditingMode,
onNavigateToEntityRecord:
getSettings().onNavigateToEntityRecord,
- editingMode: _getBlockEditingMode( patternClientId ),
+ editingMode: getBlockEditingMode( patternClientId ),
hasPatternOverridesSource: !! getBlockBindingsSource(
'core/pattern-overrides'
),
@@ -247,14 +244,15 @@ function ReusableBlockEdit( {
),
} );
- // Use `blocks` variable until `innerBlocks` is populated, which has the proper clientIds.
const innerBlocksProps = useInnerBlocksProps( blockProps, {
templateLock: 'all',
layout,
- value: innerBlocks.length > 0 ? innerBlocks : blocks,
+ value: blocks,
onInput: NOOP,
onChange: NOOP,
- renderAppender: blocks?.length ? undefined : blocks.ButtonBlockAppender,
+ renderAppender: blocks?.length
+ ? undefined
+ : InnerBlocks.ButtonBlockAppender,
} );
const handleEditOriginal = () => {
@@ -292,7 +290,7 @@ function ReusableBlockEdit( {
return (
<>
- { hasResolved && (
+ { hasResolved && ! isMissing && (
%2$s';
$items_markup = wp_list_categories( $args );
$type = 'list';
+
+ if ( ! empty( $block->context['enhancedPagination'] ) ) {
+ $p = new WP_HTML_Tag_Processor( $items_markup );
+ while ( $p->next_tag( 'a' ) ) {
+ $p->set_attribute( 'data-wp-on--click', 'core/query::actions.navigate' );
+ }
+ $items_markup = $p->get_updated_html();
+ }
}
$wrapper_attributes = get_block_wrapper_attributes( array( 'class' => "wp-block-categories-{$type}" ) );
diff --git a/packages/block-library/src/comment-edit-link/block.json b/packages/block-library/src/comment-edit-link/block.json
index a49f9a23161b8..578b284715c2a 100644
--- a/packages/block-library/src/comment-edit-link/block.json
+++ b/packages/block-library/src/comment-edit-link/block.json
@@ -30,7 +30,11 @@
},
"spacing": {
"margin": true,
- "padding": true
+ "padding": true,
+ "__experimentalDefaultControls": {
+ "margin": false,
+ "padding": false
+ }
},
"typography": {
"fontSize": true,
@@ -47,6 +51,13 @@
},
"interactivity": {
"clientNavigation": true
+ },
+ "__experimentalBorder": {
+ "radius": true,
+ "color": true,
+ "width": true,
+ "style": true
}
- }
+ },
+ "style": "wp-block-comment-edit-link"
}
diff --git a/packages/block-library/src/comment-edit-link/style.scss b/packages/block-library/src/comment-edit-link/style.scss
new file mode 100644
index 0000000000000..1ae7daf55009e
--- /dev/null
+++ b/packages/block-library/src/comment-edit-link/style.scss
@@ -0,0 +1,4 @@
+.wp-block-comment-edit-link {
+ // This block has customizable padding, border-box makes that more predictable.
+ box-sizing: border-box;
+}
diff --git a/packages/block-library/src/comment-reply-link/block.json b/packages/block-library/src/comment-reply-link/block.json
index c10129412145c..68aa93c3c1526 100644
--- a/packages/block-library/src/comment-reply-link/block.json
+++ b/packages/block-library/src/comment-reply-link/block.json
@@ -25,7 +25,11 @@
},
"spacing": {
"margin": true,
- "padding": true
+ "padding": true,
+ "__experimentalDefaultControls": {
+ "margin": false,
+ "padding": false
+ }
},
"typography": {
"fontSize": true,
@@ -40,6 +44,13 @@
"fontSize": true
}
},
+ "__experimentalBorder": {
+ "radius": true,
+ "color": true,
+ "width": true,
+ "style": true
+ },
"html": false
- }
+ },
+ "style": "wp-block-comment-reply-link"
}
diff --git a/packages/block-library/src/comment-reply-link/style.scss b/packages/block-library/src/comment-reply-link/style.scss
new file mode 100644
index 0000000000000..7eca6cee1aa97
--- /dev/null
+++ b/packages/block-library/src/comment-reply-link/style.scss
@@ -0,0 +1,4 @@
+.wp-block-comment-reply-link {
+ // This block has customizable padding, border-box makes that more predictable.
+ box-sizing: border-box;
+}
diff --git a/packages/block-library/src/freeform/editor.scss b/packages/block-library/src/freeform/editor.scss
index 7329eb6e5fb06..c2256ecd7a795 100644
--- a/packages/block-library/src/freeform/editor.scss
+++ b/packages/block-library/src/freeform/editor.scss
@@ -299,7 +299,7 @@ div[data-type="core/freeform"] {
top: 0;
border: $border-width solid $gray-300;
border-bottom: none;
- border-radius: $radius-block-ui;
+ border-radius: $radius-small;
margin-bottom: $grid-unit-10;
// On mobile, toolbars go edge to edge.
diff --git a/packages/block-library/src/gallery/editor.scss b/packages/block-library/src/gallery/editor.scss
index 3184b9d3d8fb2..61121f3dd866d 100644
--- a/packages/block-library/src/gallery/editor.scss
+++ b/packages/block-library/src/gallery/editor.scss
@@ -139,7 +139,7 @@
z-index: z-index(".block-library-gallery-item__inline-menu");
transition: box-shadow 0.2s ease-out;
@include reduce-motion("transition");
- border-radius: $radius-block-ui;
+ border-radius: $radius-small;
background: $white;
border: $border-width solid $gray-900;
diff --git a/packages/block-library/src/group/editor.scss b/packages/block-library/src/group/editor.scss
index 041a2f9f884e8..11beecbab0eb6 100644
--- a/packages/block-library/src/group/editor.scss
+++ b/packages/block-library/src/group/editor.scss
@@ -43,7 +43,6 @@
pointer-events: none;
min-height: $grid-unit-60 - $border-width - $border-width;
border: $border-width dashed currentColor;
- border-radius: $radius-block-ui;
}
// Let the parent be selectable in the placeholder area.
diff --git a/packages/block-library/src/image/edit.js b/packages/block-library/src/image/edit.js
index b7c25595dcfcc..ae8461a6b1cf4 100644
--- a/packages/block-library/src/image/edit.js
+++ b/packages/block-library/src/image/edit.js
@@ -6,8 +6,8 @@ import clsx from 'clsx';
/**
* WordPress dependencies
*/
-import { isBlobURL } from '@wordpress/blob';
-import { store as blocksStore } from '@wordpress/blocks';
+import { isBlobURL, createBlobURL } from '@wordpress/blob';
+import { store as blocksStore, createBlock } from '@wordpress/blocks';
import { Placeholder } from '@wordpress/components';
import { useDispatch, useSelect } from '@wordpress/data';
import {
@@ -31,6 +31,7 @@ import { useResizeObserver } from '@wordpress/compose';
import { unlock } from '../lock-unlock';
import { useUploadMediaFromBlobURL } from '../utils/hooks';
import Image from './image';
+import { isValidFileType } from './utils';
/**
* Module constants
@@ -109,6 +110,7 @@ export function ImageEdit( {
metadata,
} = attributes;
const [ temporaryURL, setTemporaryURL ] = useState( attributes.blob );
+ const figureRef = useRef();
const [ contentResizeListener, { width: containerWidth } ] =
useResizeObserver();
@@ -123,7 +125,7 @@ export function ImageEdit( {
captionRef.current = caption;
}, [ caption ] );
- const { __unstableMarkNextChangeAsNotPersistent } =
+ const { __unstableMarkNextChangeAsNotPersistent, replaceBlock } =
useDispatch( blockEditorStore );
useEffect( () => {
@@ -138,7 +140,12 @@ export function ImageEdit( {
}
}, [ __unstableMarkNextChangeAsNotPersistent, align, setAttributes ] );
- const { getSettings } = useSelect( blockEditorStore );
+ const {
+ getSettings,
+ getBlockRootClientId,
+ getBlockName,
+ canInsertBlockType,
+ } = useSelect( blockEditorStore );
const blockEditingMode = useBlockEditingMode();
const { createErrorNotice } = useDispatch( noticesStore );
@@ -152,7 +159,52 @@ export function ImageEdit( {
} );
}
+ function onSelectImagesList( images ) {
+ const win = figureRef.current?.ownerDocument.defaultView;
+
+ if ( images.every( ( file ) => file instanceof win.File ) ) {
+ /** @type {File[]} */
+ const files = images;
+ const rootClientId = getBlockRootClientId( clientId );
+
+ if ( files.some( ( file ) => ! isValidFileType( file ) ) ) {
+ // Copied from the same notice in the gallery block.
+ createErrorNotice(
+ __(
+ 'If uploading to a gallery all files need to be image formats'
+ ),
+ { id: 'gallery-upload-invalid-file', type: 'snackbar' }
+ );
+ }
+
+ const imageBlocks = files
+ .filter( ( file ) => isValidFileType( file ) )
+ .map( ( file ) =>
+ createBlock( 'core/image', {
+ blob: createBlobURL( file ),
+ } )
+ );
+
+ if ( getBlockName( rootClientId ) === 'core/gallery' ) {
+ replaceBlock( clientId, imageBlocks );
+ } else if ( canInsertBlockType( 'core/gallery', rootClientId ) ) {
+ const galleryBlock = createBlock(
+ 'core/gallery',
+ {},
+ imageBlocks
+ );
+
+ replaceBlock( clientId, galleryBlock );
+ }
+ }
+ }
+
function onSelectImage( media ) {
+ if ( Array.isArray( media ) ) {
+ onSelectImagesList( media );
+ return;
+ }
+
if ( ! media || ! media.url ) {
setAttributes( {
url: undefined,
@@ -296,7 +348,7 @@ export function ImageEdit( {
Object.keys( borderProps.style ).length > 0 ),
} );
- const blockProps = useBlockProps( { className: classes } );
+ const blockProps = useBlockProps( { ref: figureRef, className: classes } );
// Much of this description is duplicated from MediaPlaceholder.
const { lockUrlControls = false, lockUrlControlsMessage } = useSelect(
@@ -394,6 +446,7 @@ export function ImageEdit( {
placeholder={ placeholder }
accept="image/*"
allowedTypes={ ALLOWED_MEDIA_TYPES }
+ handleUpload={ ( files ) => files.length === 1 }
value={ { id, src } }
mediaPreview={ mediaPreview }
disableMediaButtons={ temporaryURL || url }
diff --git a/packages/block-library/src/image/editor.scss b/packages/block-library/src/image/editor.scss
index db6928766c0b7..636741c7d9ddb 100644
--- a/packages/block-library/src/image/editor.scss
+++ b/packages/block-library/src/image/editor.scss
@@ -13,9 +13,6 @@
// Disable any duotone filter applied in the selected state.
filter: none !important;
- // @todo this should eventually be overridden by a custom border-radius set in the inspector.
- border-radius: $radius-block-ui;
-
> svg {
opacity: 0;
}
diff --git a/packages/block-library/src/image/utils.js b/packages/block-library/src/image/utils.js
index 1ef7973b4e57a..1541c3daac3aa 100644
--- a/packages/block-library/src/image/utils.js
+++ b/packages/block-library/src/image/utils.js
@@ -1,7 +1,7 @@
/**
* Internal dependencies
*/
-import { NEW_TAB_REL } from './constants';
+import { NEW_TAB_REL, ALLOWED_MEDIA_TYPES } from './constants';
/**
* Evaluates a CSS aspect-ratio property value as a number.
@@ -81,3 +81,15 @@ export function getImageSizeAttributes( image, size ) {
return {};
}
+
+/**
+ * Checks if the file has a valid file type.
+ *
+ * @param {File} file - The file to check.
+ * @return {boolean} - Returns true if the file has a valid file type, otherwise false.
+ */
+export function isValidFileType( file ) {
+ return ALLOWED_MEDIA_TYPES.some(
+ ( mediaType ) => file.type.indexOf( mediaType ) === 0
+ );
+}
diff --git a/packages/block-library/src/media-text/deprecated.js b/packages/block-library/src/media-text/deprecated.js
index 1cd1472f876c0..54c6f863311ff 100644
--- a/packages/block-library/src/media-text/deprecated.js
+++ b/packages/block-library/src/media-text/deprecated.js
@@ -30,7 +30,7 @@ const v1ToV5ImageFillStyles = ( url, focalPoint ) => {
: {};
};
-const v6ImageFillStyles = ( url, focalPoint ) => {
+const v6ToV7ImageFillStyles = ( url, focalPoint ) => {
return url
? {
backgroundImage: `url(${ url })`,
@@ -198,6 +198,20 @@ const v6Attributes = {
},
};
+const v7Attributes = {
+ ...v6Attributes,
+ align: {
+ type: 'string',
+ // v7 changed the default for the `align` attribute.
+ default: 'none',
+ },
+ // New attribute.
+ useFeaturedImage: {
+ type: 'boolean',
+ default: false,
+ },
+};
+
const v4ToV5Supports = {
anchor: true,
align: [ 'wide', 'full' ],
@@ -237,6 +251,148 @@ const v6Supports = {
},
};
+const v7Supports = {
+ ...v6Supports,
+ __experimentalBorder: {
+ color: true,
+ radius: true,
+ style: true,
+ width: true,
+ __experimentalDefaultControls: {
+ color: true,
+ radius: true,
+ style: true,
+ width: true,
+ },
+ },
+ color: {
+ gradients: true,
+ heading: true,
+ link: true,
+ __experimentalDefaultControls: {
+ background: true,
+ text: true,
+ },
+ },
+ interactivity: {
+ clientNavigation: true,
+ },
+};
+
+// Version with 'none' as the default alignment.
+// See: https://github.com/WordPress/gutenberg/pull/64981
+const v7 = {
+ attributes: v7Attributes,
+ supports: v7Supports,
+ usesContext: [ 'postId', 'postType' ],
+ save( { attributes } ) {
+ const {
+ isStackedOnMobile,
+ mediaAlt,
+ mediaPosition,
+ mediaType,
+ mediaUrl,
+ mediaWidth,
+ mediaId,
+ verticalAlignment,
+ imageFill,
+ focalPoint,
+ linkClass,
+ href,
+ linkTarget,
+ rel,
+ } = attributes;
+ const mediaSizeSlug =
+ attributes.mediaSizeSlug || DEFAULT_MEDIA_SIZE_SLUG;
+ const newRel = ! rel ? undefined : rel;
+
+ const imageClasses = clsx( {
+ [ `wp-image-${ mediaId }` ]: mediaId && mediaType === 'image',
+ [ `size-${ mediaSizeSlug }` ]: mediaId && mediaType === 'image',
+ } );
+
+ let image = mediaUrl ? (
+
+ ) : null;
+
+ if ( href ) {
+ image = (
+
+ { image }
+
+ );
+ }
+
+ const mediaTypeRenders = {
+ image: () => image,
+ video: () => ,
+ };
+ const className = clsx( {
+ 'has-media-on-the-right': 'right' === mediaPosition,
+ 'is-stacked-on-mobile': isStackedOnMobile,
+ [ `is-vertically-aligned-${ verticalAlignment }` ]:
+ verticalAlignment,
+ 'is-image-fill': imageFill,
+ } );
+ const backgroundStyles = imageFill
+ ? v6ToV7ImageFillStyles( mediaUrl, focalPoint )
+ : {};
+
+ let gridTemplateColumns;
+ if ( mediaWidth !== DEFAULT_MEDIA_WIDTH ) {
+ gridTemplateColumns =
+ 'right' === mediaPosition
+ ? `auto ${ mediaWidth }%`
+ : `${ mediaWidth }% auto`;
+ }
+ const style = {
+ gridTemplateColumns,
+ };
+
+ if ( 'right' === mediaPosition ) {
+ return (
+
+
+
+ { ( mediaTypeRenders[ mediaType ] || noop )() }
+
+
+ );
+ }
+ return (
+
+
+ { ( mediaTypeRenders[ mediaType ] || noop )() }
+
+
+
+ );
+ },
+};
+
// Version with wide as the default alignment.
// See: https://github.com/WordPress/gutenberg/pull/48404
const v6 = {
@@ -301,7 +457,7 @@ const v6 = {
'is-image-fill': imageFill,
} );
const backgroundStyles = imageFill
- ? v6ImageFillStyles( mediaUrl, focalPoint )
+ ? v6ToV7ImageFillStyles( mediaUrl, focalPoint )
: {};
let gridTemplateColumns;
@@ -902,4 +1058,4 @@ const v1 = {
},
};
-export default [ v6, v5, v4, v3, v2, v1 ];
+export default [ v7, v6, v5, v4, v3, v2, v1 ];
diff --git a/packages/block-library/src/media-text/edit.js b/packages/block-library/src/media-text/edit.js
index 2c020506dc889..a946a499b26f2 100644
--- a/packages/block-library/src/media-text/edit.js
+++ b/packages/block-library/src/media-text/edit.js
@@ -213,11 +213,11 @@ function MediaTextEdit( {
[ isSelected, mediaId ]
);
- const refMediaContainer = useRef();
+ const refMedia = useRef();
const imperativeFocalPointPreview = ( value ) => {
- const { style } = refMediaContainer.current.resizable;
+ const { style } = refMedia.current;
const { x, y } = value;
- style.backgroundPosition = `${ x * 100 }% ${ y * 100 }%`;
+ style.objectPosition = `${ x * 100 }% ${ y * 100 }%`;
};
const [ temporaryMediaWidth, setTemporaryMediaWidth ] = useState( null );
@@ -243,7 +243,7 @@ function MediaTextEdit( {
'is-selected': isSelected,
'is-stacked-on-mobile': isStackedOnMobile,
[ `is-vertically-aligned-${ verticalAlignment }` ]: verticalAlignment,
- 'is-image-fill': imageFill,
+ 'is-image-fill-element': imageFill,
} );
const widthString = `${ temporaryMediaWidth || mediaWidth }%`;
const gridTemplateColumns =
@@ -480,7 +480,7 @@ function MediaTextEdit( {
onSelectMedia={ onSelectMedia }
onWidthChange={ onWidthChange }
commitWidthChange={ commitWidthChange }
- ref={ refMediaContainer }
+ refMedia={ refMedia }
enableResize={ blockEditingMode === 'default' }
toggleUseFeaturedImage={ toggleUseFeaturedImage }
{ ...{
diff --git a/packages/block-library/src/media-text/editor.scss b/packages/block-library/src/media-text/editor.scss
index b417fb951e99d..639ceaed8ea99 100644
--- a/packages/block-library/src/media-text/editor.scss
+++ b/packages/block-library/src/media-text/editor.scss
@@ -27,7 +27,9 @@
}
.wp-block-media-text.is-image-fill .editor-media-container__resizer,
-.wp-block-media-text.is-image-fill .components-placeholder.has-illustration {
+.wp-block-media-text.is-image-fill .components-placeholder.has-illustration,
+.wp-block-media-text.is-image-fill-element .editor-media-container__resizer,
+.wp-block-media-text.is-image-fill-element .components-placeholder.has-illustration {
// The resizer sets an inline height but for the image fill we set it to full height.
height: 100% !important;
}
diff --git a/packages/block-library/src/media-text/image-fill.js b/packages/block-library/src/media-text/image-fill.js
new file mode 100644
index 0000000000000..c277c49b5c310
--- /dev/null
+++ b/packages/block-library/src/media-text/image-fill.js
@@ -0,0 +1,11 @@
+export function imageFillStyles( url, focalPoint ) {
+ return url
+ ? {
+ objectPosition: focalPoint
+ ? `${ Math.round( focalPoint.x * 100 ) }% ${ Math.round(
+ focalPoint.y * 100
+ ) }%`
+ : `50% 50%`,
+ }
+ : {};
+}
diff --git a/packages/block-library/src/media-text/index.php b/packages/block-library/src/media-text/index.php
index 87be164a04bb9..b65137b150ba5 100644
--- a/packages/block-library/src/media-text/index.php
+++ b/packages/block-library/src/media-text/index.php
@@ -29,15 +29,32 @@ function render_block_core_media_text( $attributes, $content ) {
return $content;
}
+ $has_media_on_right = isset( $attributes['mediaPosition'] ) && 'right' === $attributes['mediaPosition'];
+ $image_fill = isset( $attributes['imageFill'] ) && $attributes['imageFill'];
+ $focal_point = isset( $attributes['focalPoint'] ) ? round( $attributes['focalPoint']['x'] * 100 ) . '% ' . round( $attributes['focalPoint']['y'] * 100 ) . '%' : '50% 50%';
+ $unique_id = 'wp-block-media-text__media-' . wp_unique_id();
+
+ $block_tag_processor = new WP_HTML_Tag_Processor( $content );
+ $block_query = array(
+ 'tag_name' => 'div',
+ 'class_name' => 'wp-block-media-text',
+ );
+
+ while ( $block_tag_processor->next_tag( $block_query ) ) {
+ if ( $image_fill ) {
+ // The markup below does not work with the deprecated `is-image-fill` class.
+ $block_tag_processor->remove_class( 'is-image-fill' );
+ $block_tag_processor->add_class( 'is-image-fill-element' );
+ }
+ }
+
+ $content = $block_tag_processor->get_updated_html();
+
$media_tag_processor = new WP_HTML_Tag_Processor( $content );
$wrapping_figure_query = array(
'tag_name' => 'figure',
'class_name' => 'wp-block-media-text__media',
);
- $has_media_on_right = isset( $attributes['mediaPosition'] ) && 'right' === $attributes['mediaPosition'];
- $image_fill = isset( $attributes['imageFill'] ) && $attributes['imageFill'];
- $focal_point = isset( $attributes['focalPoint'] ) ? round( $attributes['focalPoint']['x'] * 100 ) . '% ' . round( $attributes['focalPoint']['y'] * 100 ) . '%' : '50% 50%';
- $unique_id = 'wp-block-media-text__media-' . wp_unique_id();
if ( $has_media_on_right ) {
// Loop through all the figure tags and set a bookmark on the last figure tag.
@@ -46,59 +63,52 @@ function render_block_core_media_text( $attributes, $content ) {
}
if ( $media_tag_processor->has_bookmark( 'last_figure' ) ) {
$media_tag_processor->seek( 'last_figure' );
- if ( $image_fill ) {
- $media_tag_processor->set_attribute( 'style', 'background-image:url(' . esc_url( $current_featured_image ) . ');background-position:' . $focal_point . ';' );
- } else {
- // Insert a unique ID to identify the figure tag.
- $media_tag_processor->set_attribute( 'id', $unique_id );
- }
+ // Insert a unique ID to identify the figure tag.
+ $media_tag_processor->set_attribute( 'id', $unique_id );
}
} else {
if ( $media_tag_processor->next_tag( $wrapping_figure_query ) ) {
- if ( $image_fill ) {
- $media_tag_processor->set_attribute( 'style', 'background-image:url(' . esc_url( $current_featured_image ) . ');background-position:' . $focal_point . ';' );
- } else {
- // Insert a unique ID to identify the figure tag.
- $media_tag_processor->set_attribute( 'id', $unique_id );
- }
+ // Insert a unique ID to identify the figure tag.
+ $media_tag_processor->set_attribute( 'id', $unique_id );
}
}
$content = $media_tag_processor->get_updated_html();
- // If the image is not set to fill, add the image tag inside the figure tag,
- // and update the image attributes in order to display the featured image.
- if ( ! $image_fill ) {
- $media_size_slug = isset( $attributes['mediaSizeSlug'] ) ? $attributes['mediaSizeSlug'] : 'full';
- $image_tag = ' ';
- $content = preg_replace(
- '/()/',
- '$1' . $image_tag,
- $content
- );
+ // Add the image tag inside the figure tag, and update the image attributes
+ // in order to display the featured image.
+ $media_size_slug = isset( $attributes['mediaSizeSlug'] ) ? $attributes['mediaSizeSlug'] : 'full';
+ $image_tag = ' ';
+ $content = preg_replace(
+ '/()/',
+ '$1' . $image_tag,
+ $content
+ );
- $image_tag_processor = new WP_HTML_Tag_Processor( $content );
+ $image_tag_processor = new WP_HTML_Tag_Processor( $content );
+ if ( $image_tag_processor->next_tag(
+ array(
+ 'tag_name' => 'figure',
+ 'id' => $unique_id,
+ )
+ ) ) {
+ // The ID is only used to ensure that the correct figure tag is selected,
+ // and can now be removed.
+ $image_tag_processor->remove_attribute( 'id' );
if ( $image_tag_processor->next_tag(
array(
- 'tag_name' => 'figure',
- 'id' => $unique_id,
+ 'tag_name' => 'img',
+ 'class_name' => 'wp-block-media-text__featured_image',
)
) ) {
- // The ID is only used to ensure that the correct figure tag is selected,
- // and can now be removed.
- $image_tag_processor->remove_attribute( 'id' );
- if ( $image_tag_processor->next_tag(
- array(
- 'tag_name' => 'img',
- 'class_name' => 'wp-block-media-text__featured_image',
- )
- ) ) {
- $image_tag_processor->set_attribute( 'src', esc_url( $current_featured_image ) );
- $image_tag_processor->set_attribute( 'class', 'wp-image-' . get_post_thumbnail_id() . ' size-' . $media_size_slug );
- $image_tag_processor->set_attribute( 'alt', trim( strip_tags( get_post_meta( get_post_thumbnail_id(), '_wp_attachment_image_alt', true ) ) ) );
-
- $content = $image_tag_processor->get_updated_html();
+ $image_tag_processor->set_attribute( 'src', esc_url( $current_featured_image ) );
+ $image_tag_processor->set_attribute( 'class', 'wp-image-' . get_post_thumbnail_id() . ' size-' . $media_size_slug );
+ $image_tag_processor->set_attribute( 'alt', trim( strip_tags( get_post_meta( get_post_thumbnail_id(), '_wp_attachment_image_alt', true ) ) ) );
+ if ( $image_fill ) {
+ $image_tag_processor->set_attribute( 'style', 'object-position:' . $focal_point . ';' );
}
+
+ $content = $image_tag_processor->get_updated_html();
}
}
diff --git a/packages/block-library/src/media-text/media-container.js b/packages/block-library/src/media-text/media-container.js
index 986ecad6cc7e6..735aaf73b88aa 100644
--- a/packages/block-library/src/media-text/media-container.js
+++ b/packages/block-library/src/media-text/media-container.js
@@ -22,25 +22,17 @@ import { isBlobURL } from '@wordpress/blob';
import { store as noticesStore } from '@wordpress/notices';
import { media as icon } from '@wordpress/icons';
+/**
+ * Internal dependencies
+ */
+import { imageFillStyles } from './image-fill';
+
/**
* Constants
*/
const ALLOWED_MEDIA_TYPES = [ 'image', 'video' ];
const noop = () => {};
-export function imageFillStyles( url, focalPoint ) {
- return url
- ? {
- backgroundImage: `url(${ url })`,
- backgroundPosition: focalPoint
- ? `${ Math.round( focalPoint.x * 100 ) }% ${ Math.round(
- focalPoint.y * 100
- ) }%`
- : `50% 50%`,
- }
- : {};
-}
-
const ResizableBoxContainer = forwardRef(
( { isSelected, isStackedOnMobile, ...props }, ref ) => {
const isMobile = useViewportMatch( 'small', '<' );
@@ -129,6 +121,7 @@ function MediaContainer( props, ref ) {
useFeaturedImage,
featuredImageURL,
featuredImageAlt,
+ refMedia,
} = props;
const isTemporaryMedia = ! mediaId && isBlobURL( mediaUrl );
@@ -151,7 +144,7 @@ function MediaContainer( props, ref ) {
left: enableResize && mediaPosition === 'right',
};
- const backgroundStyles =
+ const positionStyles =
mediaType === 'image' && imageFill
? imageFillStyles( mediaUrl || featuredImageURL, focalPoint )
: {};
@@ -159,11 +152,23 @@ function MediaContainer( props, ref ) {
const mediaTypeRenderers = {
image: () =>
useFeaturedImage && featuredImageURL ? (
-
+
) : (
- mediaUrl &&
+ mediaUrl && (
+
+ )
),
- video: () => ,
+ video: () => ,
};
return (
@@ -174,7 +179,6 @@ function MediaContainer( props, ref ) {
'editor-media-container__resizer',
{ 'is-transient': isTemporaryMedia }
) }
- style={ backgroundStyles }
size={ { width: mediaWidth + '%' } }
minWidth="10%"
maxWidth="100%"
@@ -203,6 +207,7 @@ function MediaContainer( props, ref ) {
{ ! featuredImageURL && useFeaturedImage && (
) }
diff --git a/packages/block-library/src/media-text/media-container.native.js b/packages/block-library/src/media-text/media-container.native.js
index eaee027c06185..3bf4fbf25d8f2 100644
--- a/packages/block-library/src/media-text/media-container.native.js
+++ b/packages/block-library/src/media-text/media-container.native.js
@@ -44,8 +44,6 @@ const ICON_TYPE = {
RETRY: 'retry',
};
-export { imageFillStyles } from './media-container.js';
-
class MediaContainer extends Component {
constructor() {
super( ...arguments );
diff --git a/packages/block-library/src/media-text/save.js b/packages/block-library/src/media-text/save.js
index 5bf9517adae66..3e660d94e789e 100644
--- a/packages/block-library/src/media-text/save.js
+++ b/packages/block-library/src/media-text/save.js
@@ -11,7 +11,7 @@ import { useInnerBlocksProps, useBlockProps } from '@wordpress/block-editor';
/**
* Internal dependencies
*/
-import { imageFillStyles } from './media-container';
+import { imageFillStyles } from './image-fill';
import { DEFAULT_MEDIA_SIZE_SLUG } from './constants';
const DEFAULT_MEDIA_WIDTH = 50;
@@ -42,11 +42,16 @@ export default function save( { attributes } ) {
[ `size-${ mediaSizeSlug }` ]: mediaId && mediaType === 'image',
} );
+ const positionStyles = imageFill
+ ? imageFillStyles( mediaUrl, focalPoint )
+ : {};
+
let image = mediaUrl ? (
) : null;
@@ -71,11 +76,8 @@ export default function save( { attributes } ) {
'has-media-on-the-right': 'right' === mediaPosition,
'is-stacked-on-mobile': isStackedOnMobile,
[ `is-vertically-aligned-${ verticalAlignment }` ]: verticalAlignment,
- 'is-image-fill': imageFill,
+ 'is-image-fill-element': imageFill,
} );
- const backgroundStyles = imageFill
- ? imageFillStyles( mediaUrl, focalPoint )
- : {};
let gridTemplateColumns;
if ( mediaWidth !== DEFAULT_MEDIA_WIDTH ) {
@@ -96,10 +98,7 @@ export default function save( { attributes } ) {
className: 'wp-block-media-text__content',
} ) }
/>
-
+
{ ( mediaTypeRenders[ mediaType ] || noop )() }
@@ -107,10 +106,7 @@ export default function save( { attributes } ) {
}
return (
-
+
{ ( mediaTypeRenders[ mediaType ] || noop )() }
.wp-block-media-text__media {
height: 100%;
min-height: 250px;
@@ -102,6 +103,26 @@
clip: rect(0, 0, 0, 0);
border: 0;
}
+
+/* Image fill for versions 8 and onwards */
+.wp-block-media-text.is-image-fill-element > .wp-block-media-text__media {
+ position: relative;
+ height: 100%;
+ min-height: 250px;
+}
+
+.wp-block-media-text.is-image-fill-element > .wp-block-media-text__media > a {
+ display: block;
+ height: 100%;
+}
+
+.wp-block-media-text.is-image-fill-element > .wp-block-media-text__media img {
+ position: absolute;
+ width: 100%;
+ height: 100%;
+ object-fit: cover;
+}
+
/*
* Here we here not able to use a mobile first CSS approach.
* Custom widths are set using inline styles, and on mobile,
diff --git a/packages/block-library/src/media-text/test/image-fill.js b/packages/block-library/src/media-text/test/image-fill.js
new file mode 100644
index 0000000000000..4862fcbfb0245
--- /dev/null
+++ b/packages/block-library/src/media-text/test/image-fill.js
@@ -0,0 +1,19 @@
+/**
+ * Internal dependencies
+ */
+import { imageFillStyles } from '../image-fill';
+
+describe( 'imageFillStyles()', () => {
+ it( 'should return centered object position', () => {
+ const { objectPosition } = imageFillStyles( 'image.jpg' );
+ expect( objectPosition ).toBe( '50% 50%' );
+ } );
+
+ it( 'should return custom object position', () => {
+ const { objectPosition } = imageFillStyles( 'image.jpg', {
+ x: 0.56,
+ y: 0.57,
+ } );
+ expect( objectPosition ).toBe( '56% 57%' );
+ } );
+} );
diff --git a/packages/block-library/src/media-text/test/media-container.js b/packages/block-library/src/media-text/test/media-container.js
deleted file mode 100644
index 582ec2be8d5ad..0000000000000
--- a/packages/block-library/src/media-text/test/media-container.js
+++ /dev/null
@@ -1,24 +0,0 @@
-/**
- * Internal dependencies
- */
-import { imageFillStyles } from '../media-container';
-
-describe( 'imageFillStyles()', () => {
- it( 'should return image url', () => {
- const { backgroundImage } = imageFillStyles( 'image.jpg' );
- expect( backgroundImage ).toBe( 'url(image.jpg)' );
- } );
-
- it( 'should return centered background position', () => {
- const { backgroundPosition } = imageFillStyles( 'image.jpg' );
- expect( backgroundPosition ).toBe( '50% 50%' );
- } );
-
- it( 'should return custom background position', () => {
- const { backgroundPosition } = imageFillStyles( 'image.jpg', {
- x: 0.56,
- y: 0.57,
- } );
- expect( backgroundPosition ).toBe( '56% 57%' );
- } );
-} );
diff --git a/packages/block-library/src/navigation/editor.scss b/packages/block-library/src/navigation/editor.scss
index 619b8dc6f0c7b..a8d135656e44a 100644
--- a/packages/block-library/src/navigation/editor.scss
+++ b/packages/block-library/src/navigation/editor.scss
@@ -104,7 +104,6 @@
background: $gray-900;
padding: 0;
width: $button-size-small;
- border-radius: $radius-block-ui;
margin-right: 0;
margin-left: auto;
}
@@ -326,7 +325,7 @@ $color-control-label-height: 20px;
}
.wp-block-navigation-placeholder__controls {
- border-radius: $radius-block-ui;
+ border-radius: $radius-small;
background-color: $white;
box-shadow: inset 0 0 0 $border-width $gray-900;
display: none;
diff --git a/packages/block-library/src/query-pagination/editor.scss b/packages/block-library/src/query-pagination/editor.scss
index 0b755d155091f..ed8a2cc47a30f 100644
--- a/packages/block-library/src/query-pagination/editor.scss
+++ b/packages/block-library/src/query-pagination/editor.scss
@@ -1,5 +1,3 @@
-$pagination-margin: 0.5em;
-
// Center flex items. This has an equivalent in style.scss.
.wp-block[data-align="center"] > .wp-block-query-pagination {
justify-content: center;
@@ -14,21 +12,3 @@ $pagination-margin: 0.5em;
}
}
-.wp-block-query-pagination {
- > .wp-block-query-pagination-next,
- > .wp-block-query-pagination-previous,
- > .wp-block-query-pagination-numbers {
- // Override editor auto block margins.
- margin-left: 0;
- margin-top: $pagination-margin;
-
- /*rtl:ignore*/
- margin-right: $pagination-margin;
- margin-bottom: $pagination-margin;
-
- &:last-child {
- /*rtl:ignore*/
- margin-right: 0;
- }
- }
-}
diff --git a/packages/block-library/src/query-pagination/style.scss b/packages/block-library/src/query-pagination/style.scss
index a7f2832af48c7..e949c766e5651 100644
--- a/packages/block-library/src/query-pagination/style.scss
+++ b/packages/block-library/src/query-pagination/style.scss
@@ -1,19 +1,4 @@
-$pagination-margin: 0.5em;
.wp-block-query-pagination {
- // Increased specificity to override blocks default margin.
- > .wp-block-query-pagination-next,
- > .wp-block-query-pagination-previous,
- > .wp-block-query-pagination-numbers {
- /*rtl:ignore*/
- margin-right: $pagination-margin;
- margin-bottom: $pagination-margin;
-
- &:last-child {
- /*rtl:ignore*/
- margin-right: 0;
- }
- }
-
// This moves the next link to the right side of the container,
// which is important when it's the only block displayed
// and the block has a "space-between" justification.
diff --git a/packages/block-library/src/site-logo/edit.js b/packages/block-library/src/site-logo/edit.js
index edf8bbccfeb65..1d541ba35d631 100644
--- a/packages/block-library/src/site-logo/edit.js
+++ b/packages/block-library/src/site-logo/edit.js
@@ -423,7 +423,7 @@ export default function LogoEdit( {
context: 'view',
} );
const _isRequestingMediaItem =
- _siteLogoId &&
+ !! _siteLogoId &&
! select( coreStore ).hasFinishedResolution( 'getMedia', [
_siteLogoId,
{ context: 'view' },
diff --git a/packages/block-library/src/style.scss b/packages/block-library/src/style.scss
index 7906a1231d922..a8819c2084dc2 100644
--- a/packages/block-library/src/style.scss
+++ b/packages/block-library/src/style.scss
@@ -13,6 +13,8 @@
@import "./comment-date/style.scss";
@import "./comment-content/style.scss";
@import "./comment-author-name/style.scss";
+@import "./comment-edit-link/style.scss";
+@import "./comment-reply-link/style.scss";
@import "./cover/style.scss";
@import "./details/style.scss";
@import "./embed/style.scss";
diff --git a/packages/block-serialization-default-parser/CHANGELOG.md b/packages/block-serialization-default-parser/CHANGELOG.md
index 7357d96bdcf7c..9dd0bd7030976 100644
--- a/packages/block-serialization-default-parser/CHANGELOG.md
+++ b/packages/block-serialization-default-parser/CHANGELOG.md
@@ -2,6 +2,8 @@
## Unreleased
+## 5.7.0 (2024-09-05)
+
## 5.6.0 (2024-08-21)
## 5.5.0 (2024-08-07)
diff --git a/packages/block-serialization-default-parser/package.json b/packages/block-serialization-default-parser/package.json
index cbfcbfc0e4cb6..cac606bd7bd1e 100644
--- a/packages/block-serialization-default-parser/package.json
+++ b/packages/block-serialization-default-parser/package.json
@@ -1,6 +1,6 @@
{
"name": "@wordpress/block-serialization-default-parser",
- "version": "5.6.0",
+ "version": "5.7.0",
"description": "Block serialization specification parser for WordPress posts.",
"author": "The WordPress Contributors",
"license": "GPL-2.0-or-later",
diff --git a/packages/block-serialization-spec-parser/CHANGELOG.md b/packages/block-serialization-spec-parser/CHANGELOG.md
index d4091d455937d..b8d02b5348e1b 100644
--- a/packages/block-serialization-spec-parser/CHANGELOG.md
+++ b/packages/block-serialization-spec-parser/CHANGELOG.md
@@ -2,6 +2,8 @@
## Unreleased
+## 5.7.0 (2024-09-05)
+
## 5.6.0 (2024-08-21)
## 5.5.0 (2024-08-07)
diff --git a/packages/block-serialization-spec-parser/package.json b/packages/block-serialization-spec-parser/package.json
index 0020908e33833..d48d1846e7909 100644
--- a/packages/block-serialization-spec-parser/package.json
+++ b/packages/block-serialization-spec-parser/package.json
@@ -1,6 +1,6 @@
{
"name": "@wordpress/block-serialization-spec-parser",
- "version": "5.6.0",
+ "version": "5.7.0",
"description": "Block serialization specification parser for WordPress posts.",
"author": "The WordPress Contributors",
"license": "GPL-2.0-or-later",
diff --git a/packages/blocks/CHANGELOG.md b/packages/blocks/CHANGELOG.md
index ce7417db1f35a..0755d5170d1b3 100644
--- a/packages/blocks/CHANGELOG.md
+++ b/packages/blocks/CHANGELOG.md
@@ -2,6 +2,8 @@
## Unreleased
+## 13.7.0 (2024-09-05)
+
## 13.6.0 (2024-08-21)
## 13.5.0 (2024-08-07)
diff --git a/packages/blocks/package.json b/packages/blocks/package.json
index e6c5253c7a4af..f371ecc087af4 100644
--- a/packages/blocks/package.json
+++ b/packages/blocks/package.json
@@ -1,6 +1,6 @@
{
"name": "@wordpress/blocks",
- "version": "13.6.0",
+ "version": "13.7.0",
"description": "Block API for WordPress.",
"author": "The WordPress Contributors",
"license": "GPL-2.0-or-later",
diff --git a/packages/browserslist-config/CHANGELOG.md b/packages/browserslist-config/CHANGELOG.md
index 2d0fafa7bc988..b8ee58633b7ef 100644
--- a/packages/browserslist-config/CHANGELOG.md
+++ b/packages/browserslist-config/CHANGELOG.md
@@ -2,6 +2,8 @@
## Unreleased
+## 6.7.0 (2024-09-05)
+
## 6.6.0 (2024-08-21)
## 6.5.0 (2024-08-07)
diff --git a/packages/browserslist-config/package.json b/packages/browserslist-config/package.json
index 6cf84334da5b3..c51d7318170c4 100644
--- a/packages/browserslist-config/package.json
+++ b/packages/browserslist-config/package.json
@@ -1,6 +1,6 @@
{
"name": "@wordpress/browserslist-config",
- "version": "6.6.0",
+ "version": "6.7.0",
"description": "WordPress Browserslist shared configuration.",
"author": "The WordPress Contributors",
"license": "GPL-2.0-or-later",
diff --git a/packages/commands/CHANGELOG.md b/packages/commands/CHANGELOG.md
index 86cefcc971b24..bde7767a0f61f 100644
--- a/packages/commands/CHANGELOG.md
+++ b/packages/commands/CHANGELOG.md
@@ -2,6 +2,8 @@
## Unreleased
+## 1.7.0 (2024-09-05)
+
## 1.6.0 (2024-08-21)
## 1.5.0 (2024-08-07)
diff --git a/packages/commands/package.json b/packages/commands/package.json
index 5bca7f6ad6fae..88b9b86f4b3ae 100644
--- a/packages/commands/package.json
+++ b/packages/commands/package.json
@@ -1,6 +1,6 @@
{
"name": "@wordpress/commands",
- "version": "1.6.0",
+ "version": "1.7.0",
"description": "Handles the commands menu.",
"author": "The WordPress Contributors",
"license": "GPL-2.0-or-later",
diff --git a/packages/commands/src/components/style.scss b/packages/commands/src/components/style.scss
index e69853bad9599..bcf3d17d7baa6 100644
--- a/packages/commands/src/components/style.scss
+++ b/packages/commands/src/components/style.scss
@@ -33,7 +33,7 @@
border: $border-width solid $gray-600;
border-right: 0;
justify-content: center;
- border-radius: $radius-block-ui 0 0 $radius-block-ui;
+ border-radius: $radius-small 0 0 $radius-small;
& + [cmdk-input] {
border-top-left-radius: 0;
@@ -68,7 +68,7 @@
}
[cmdk-item] {
- border-radius: $radius-block-ui;
+ border-radius: $radius-small;
cursor: pointer;
display: flex;
align-items: center;
diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md
index 3b8d45be5861b..499a3b69c06a2 100644
--- a/packages/components/CHANGELOG.md
+++ b/packages/components/CHANGELOG.md
@@ -2,11 +2,22 @@
## Unreleased
+### New Features
+
+- `Composite`: add stable version of the component ([#63569](https://github.com/WordPress/gutenberg/pull/63569)).
+
+### Internal
+
+- `Composite`: Remove from private APIs ([#63569](https://github.com/WordPress/gutenberg/pull/63569)).
+
+## 28.7.0 (2024-09-05)
+
### Deprecations
- Deprecate `replace` from the options accepted by `useNavigator().goTo()` ([#64675](https://github.com/WordPress/gutenberg/pull/64675)).
- Soft deprecate `size` prop on `AlignmentMatrixControl.Icon` ([#64827](https://github.com/WordPress/gutenberg/pull/64827)).
- `__experimentalAlignmentMatrixControl` can now be imported as a stable `AlignmentMatrixControl` ([#60913](https://github.com/WordPress/gutenberg/pull/60913)).
+- Deprecate `DimensionControl`, scheduled to be removed in WordPress 7.0 ([#64951](https://github.com/WordPress/gutenberg/pull/64951)).
### Enhancements
@@ -63,15 +74,19 @@
- `TimePicker`: use ToggleGroupControl for AM/PM toggle ([#64800](https://github.com/WordPress/gutenberg/pull/64800)).
- `ColorPalette` utils: do not normalize undefined color values ([#64969](https://github.com/WordPress/gutenberg/pull/64969)).
+- `DatePicker` restore round radius for event dot ([#65031](https://github.com/WordPress/gutenberg/pull/65031)).
### Internal
+- `DropdownMenu` v2: expose CompositeTypeaheadV2 and CompositeHoverV2 via private APIs ([#64985](https://github.com/WordPress/gutenberg/pull/64985)).
- `DropdownMenu` v2: fix flashing menu item styles when using keyboard ([#64873](https://github.com/WordPress/gutenberg/pull/64873), [#64942](https://github.com/WordPress/gutenberg/pull/64942)).
- `DropdownMenu` v2: refactor to overloaded naming convention ([#64654](https://github.com/WordPress/gutenberg/pull/64654)).
- `DropdownMenu` v2: add `GroupLabel` subcomponent ([#64854](https://github.com/WordPress/gutenberg/pull/64854)).
- `DropdownMenuV2`: update animation ([#64868](https://github.com/WordPress/gutenberg/pull/64868)).
- `Composite` V2: fix Storybook docgen ([#64682](https://github.com/WordPress/gutenberg/pull/64682)).
+- `Composite` V2: add "With Slot Fill" example ([#65051](https://github.com/WordPress/gutenberg/pull/65051)).
- `Composite` V2: accept store props on top-level component ([#64832](https://github.com/WordPress/gutenberg/pull/64832)).
+- `Composite` V2: remove `store` prop and `useCompositeStore` hook ([#64723](https://github.com/WordPress/gutenberg/pull/64723)).
## 28.6.0 (2024-08-21)
diff --git a/packages/components/package.json b/packages/components/package.json
index ba943ece33340..17209986c0f17 100644
--- a/packages/components/package.json
+++ b/packages/components/package.json
@@ -1,6 +1,6 @@
{
"name": "@wordpress/components",
- "version": "28.6.0",
+ "version": "28.7.0",
"description": "UI components for WordPress.",
"author": "The WordPress Contributors",
"license": "GPL-2.0-or-later",
diff --git a/packages/components/src/composite/README.md b/packages/components/src/composite/README.md
index 35881d815cf1b..de710bd2ab627 100644
--- a/packages/components/src/composite/README.md
+++ b/packages/components/src/composite/README.md
@@ -1,18 +1,13 @@
# `Composite`
-
-This feature is still experimental. “Experimental” means this is an early implementation subject to drastic and breaking changes.
-
-
`Composite` provides a single tab stop on the page and allows navigation through the focusable descendants with arrow keys. This abstract component is based on the [WAI-ARIA Composite Role](https://w3c.github.io/aria/#composite).
## Usage
```jsx
-import { Composite, useCompositeStore } from '@wordpress/components';
+import { Composite } from '@wordpress/components';
-const store = useCompositeStore();
-
+
Label
Item 1
@@ -21,11 +16,11 @@ const store = useCompositeStore();
```
-## Hooks
+## Components
-### `useCompositeStore`
+### `Composite`
-Creates a composite store.
+Renders a composite widget.
#### Props
@@ -131,20 +126,6 @@ This only affects the composite widget behavior. You still need to set `dir="rtl
- Required: no
- Default: `false`
-## Components
-
-### `Composite`
-
-Renders a composite widget.
-
-#### Props
-
-##### `store`: `CompositeStore`
-
-Object returned by the `useCompositeStore` hook.
-
-- Required: yes
-
##### `render`: `RenderProp & { ref?: React.Ref | undefined; }> | React.ReactElement>`
Allows the component to be rendered as a different HTML element or React component. The value can be a React element or a function that takes in the original component props and gives back a React element with the props merged.
diff --git a/packages/components/src/composite/context.ts b/packages/components/src/composite/context.tsx
similarity index 75%
rename from packages/components/src/composite/context.ts
rename to packages/components/src/composite/context.tsx
index 69a052c5bfba1..4a8b22a712b03 100644
--- a/packages/components/src/composite/context.ts
+++ b/packages/components/src/composite/context.tsx
@@ -8,7 +8,6 @@ import { createContext, useContext } from '@wordpress/element';
*/
import type { CompositeContextProps } from './types';
-export const CompositeContext =
- createContext< CompositeContextProps >( undefined );
+export const CompositeContext = createContext< CompositeContextProps >( {} );
export const useCompositeContext = () => useContext( CompositeContext );
diff --git a/packages/components/src/composite/group-label.tsx b/packages/components/src/composite/group-label.tsx
index 26d043cd0a140..17070dbb86bf8 100644
--- a/packages/components/src/composite/group-label.tsx
+++ b/packages/components/src/composite/group-label.tsx
@@ -22,7 +22,7 @@ export const CompositeGroupLabel = forwardRef<
const context = useCompositeContext();
return (
diff --git a/packages/components/src/composite/group.tsx b/packages/components/src/composite/group.tsx
index a6b1b8b3f5254..ae21ca6f11dd9 100644
--- a/packages/components/src/composite/group.tsx
+++ b/packages/components/src/composite/group.tsx
@@ -22,7 +22,7 @@ export const CompositeGroup = forwardRef<
const context = useCompositeContext();
return (
diff --git a/packages/components/src/composite/hover.tsx b/packages/components/src/composite/hover.tsx
index 76a240e076700..ca0bd9d8f6aa1 100644
--- a/packages/components/src/composite/hover.tsx
+++ b/packages/components/src/composite/hover.tsx
@@ -22,7 +22,7 @@ export const CompositeHover = forwardRef<
const context = useCompositeContext();
return (
diff --git a/packages/components/src/composite/index.tsx b/packages/components/src/composite/index.tsx
index 629010d271e81..e9e97072261fb 100644
--- a/packages/components/src/composite/index.tsx
+++ b/packages/components/src/composite/index.tsx
@@ -16,6 +16,7 @@ import * as Ariakit from '@ariakit/react';
/**
* WordPress dependencies
*/
+import { isRTL } from '@wordpress/i18n';
import { useMemo, forwardRef } from '@wordpress/element';
/**
@@ -38,10 +39,9 @@ import type { CompositeProps } from './types';
*
* @example
* ```jsx
- * import { Composite, useCompositeStore } from '@wordpress/components';
+ * import { Composite } from '@wordpress/components';
*
- * const store = useCompositeStore();
- *
+ *
* Item 1
* Item 2
*
@@ -62,21 +62,18 @@ export const Composite = Object.assign(
focusShift = false,
virtualFocus = false,
orientation = 'both',
- rtl = false,
+ rtl = isRTL(),
// Composite component props
children,
disabled = false,
- // To be removed
- store: storeProp,
-
// Rest props
...props
},
ref
) {
- const newStore = Ariakit.useCompositeStore( {
+ const store = Ariakit.useCompositeStore( {
activeId,
defaultActiveId,
setActiveId,
@@ -88,8 +85,6 @@ export const Composite = Object.assign(
rtl,
} );
- const store = storeProp || newStore;
-
const contextValue = useMemo(
() => ( {
store,
@@ -116,10 +111,9 @@ export const Composite = Object.assign(
*
* @example
* ```jsx
- * import { Composite, useCompositeStore } from '@wordpress/components';
+ * import { Composite } from '@wordpress/components';
*
- * const store = useCompositeStore();
- *
+ *
*
* Label
* Item 1
@@ -138,10 +132,9 @@ export const Composite = Object.assign(
*
* @example
* ```jsx
- * import { Composite, useCompositeStore } from '@wordpress/components';
+ * import { Composite } from '@wordpress/components';
*
- * const store = useCompositeStore();
- *
+ *
*
* Label
* Item 1
@@ -158,10 +151,9 @@ export const Composite = Object.assign(
*
* @example
* ```jsx
- * import { Composite, useCompositeStore } from '@wordpress/components';
+ * import { Composite } from '@wordpress/components';
*
- * const store = useCompositeStore();
- *
+ *
* Item 1
* Item 2
* Item 3
@@ -176,10 +168,9 @@ export const Composite = Object.assign(
*
* @example
* ```jsx
- * import { Composite, useCompositeStore } from '@wordpress/components';
+ * import { Composite } from '@wordpress/components';
*
- * const store = useCompositeStore();
- *
+ *
*
* Item 1.1
* Item 1.2
@@ -201,10 +192,9 @@ export const Composite = Object.assign(
*
* @example
* ```jsx
- * import { Composite, useCompositeStore } from '@wordpress/components';
+ * import { Composite } from '@wordpress/components';
*
- * const store = useCompositeStore();
- *
+ *
* }>
* Item 1
*
@@ -224,10 +214,9 @@ export const Composite = Object.assign(
*
* @example
* ```jsx
- * import { Composite, useCompositeStore } from '@wordpress/components';
+ * import { Composite } from '@wordpress/components';
*
- * const store = useCompositeStore();
- * }>
+ * }>
* Item 1
* Item 2
*
diff --git a/packages/components/src/composite/item.tsx b/packages/components/src/composite/item.tsx
index 8067c222c1c97..6d75b90f0baaa 100644
--- a/packages/components/src/composite/item.tsx
+++ b/packages/components/src/composite/item.tsx
@@ -22,7 +22,7 @@ export const CompositeItem = forwardRef<
const context = useCompositeContext();
return (
diff --git a/packages/components/src/composite/legacy/index.tsx b/packages/components/src/composite/legacy/index.tsx
index 41ecc6ceb3f66..cff564af1f8e7 100644
--- a/packages/components/src/composite/legacy/index.tsx
+++ b/packages/components/src/composite/legacy/index.tsx
@@ -13,6 +13,11 @@
* @see https://ariakit.org/components/composite
*/
+/**
+ * External dependencies
+ */
+import * as Ariakit from '@ariakit/react';
+
/**
* WordPress dependencies
*/
@@ -22,7 +27,6 @@ import { forwardRef } from '@wordpress/element';
* Internal dependencies
*/
import { Composite as Current } from '..';
-import { useCompositeStore } from '../store';
import { useInstanceId } from '@wordpress/compose';
type Orientation = 'horizontal' | 'vertical';
@@ -79,7 +83,7 @@ export interface LegacyStateOptions {
type Component = React.FunctionComponent< any >;
-type CompositeStore = ReturnType< typeof useCompositeStore >;
+type CompositeStore = ReturnType< typeof Ariakit.useCompositeStore >;
type CompositeStoreState = { store: CompositeStore };
export type CompositeState = CompositeStoreState &
Required< Pick< LegacyStateOptions, 'baseId' > >;
@@ -180,7 +184,7 @@ export function useCompositeState(
return {
baseId: useInstanceId( Composite, 'composite', baseId ),
- store: useCompositeStore( {
+ store: Ariakit.useCompositeStore( {
defaultActiveId,
rtl,
orientation,
diff --git a/packages/components/src/composite/legacy/stories/index.story.tsx b/packages/components/src/composite/legacy/stories/index.story.tsx
index e46d656a16810..1b8e07e9bbf56 100644
--- a/packages/components/src/composite/legacy/stories/index.story.tsx
+++ b/packages/components/src/composite/legacy/stories/index.story.tsx
@@ -15,7 +15,8 @@ import {
import { UseCompositeStatePlaceholder, transform } from './utils';
const meta: Meta< typeof UseCompositeStatePlaceholder > = {
- title: 'Components/Composite',
+ title: 'Components (Deprecated)/Composite (Unstable)',
+ id: 'components-composite-unstable',
component: UseCompositeStatePlaceholder,
subcomponents: {
Composite,
diff --git a/packages/components/src/composite/row.tsx b/packages/components/src/composite/row.tsx
index cbb9f80045de7..a082af03ad678 100644
--- a/packages/components/src/composite/row.tsx
+++ b/packages/components/src/composite/row.tsx
@@ -22,7 +22,7 @@ export const CompositeRow = forwardRef<
const context = useCompositeContext();
return (
diff --git a/packages/components/src/composite/store.ts b/packages/components/src/composite/store.ts
deleted file mode 100644
index acf24b96cb812..0000000000000
--- a/packages/components/src/composite/store.ts
+++ /dev/null
@@ -1,46 +0,0 @@
-/**
- * External dependencies
- */
-import * as Ariakit from '@ariakit/react';
-
-/**
- * Internal dependencies
- */
-import type { CompositeStoreProps } from './types';
-
-// Props are already documented in TypeScript types.
-// eslint-disable-next-line jsdoc/require-param
-/**
- * Creates a composite store.
- *
- * @example
- * ```jsx
- * import { Composite, useCompositeStore } from '@wordpress/components';
- *
- * const store = useCompositeStore();
- *
- * Item
- * Item
- * Item
- *
- * ```
- */
-export function useCompositeStore( {
- focusLoop = false,
- focusWrap = false,
- focusShift = false,
- virtualFocus = false,
- orientation = 'both',
- rtl = false,
- ...props
-}: CompositeStoreProps = {} ) {
- return Ariakit.useCompositeStore( {
- focusLoop,
- focusWrap,
- focusShift,
- virtualFocus,
- orientation,
- rtl,
- ...props,
- } );
-}
diff --git a/packages/components/src/composite/stories/index.story.tsx b/packages/components/src/composite/stories/index.story.tsx
index 80e3d85e3ce29..d6e4999407e99 100644
--- a/packages/components/src/composite/stories/index.story.tsx
+++ b/packages/components/src/composite/stories/index.story.tsx
@@ -1,26 +1,23 @@
/**
* External dependencies
*/
-import type { Meta, StoryFn } from '@storybook/react';
+import type { Meta, StoryObj } from '@storybook/react';
/**
* WordPress dependencies
*/
-import { isRTL } from '@wordpress/i18n';
+import { useContext, useMemo } from '@wordpress/element';
/**
* Internal dependencies
*/
+import { createSlotFill, Provider as SlotFillProvider } from '../../slot-fill';
import { Composite } from '..';
-import { useCompositeStore } from '../store';
-import { UseCompositeStorePlaceholder, transform } from './utils';
-const meta: Meta< typeof UseCompositeStorePlaceholder > = {
- title: 'Components/Composite (V2)',
- component: UseCompositeStorePlaceholder,
+const meta: Meta< typeof Composite > = {
+ title: 'Components/Composite',
+ component: Composite,
subcomponents: {
- // @ts-expect-error - See https://github.com/storybookjs/storybook/issues/23170
- Composite,
// @ts-expect-error - See https://github.com/storybookjs/storybook/issues/23170
'Composite.Group': Composite.Group,
// @ts-expect-error - See https://github.com/storybookjs/storybook/issues/23170
@@ -33,8 +30,12 @@ const meta: Meta< typeof UseCompositeStorePlaceholder > = {
'Composite.Hover': Composite.Hover,
// @ts-expect-error - See https://github.com/storybookjs/storybook/issues/23170
'Composite.Typeahead': Composite.Typeahead,
+ // @ts-expect-error - See https://github.com/storybookjs/storybook/issues/23170
+ 'Composite.Context': Composite.Context,
},
argTypes: {
+ children: { control: { type: null } },
+ render: { control: { type: null } },
setActiveId: { control: { type: null } },
focusLoop: {
control: 'select',
@@ -45,12 +46,10 @@ const meta: Meta< typeof UseCompositeStorePlaceholder > = {
options: [ true, false, 'horizontal', 'vertical', 'both' ],
},
},
- tags: [ 'status-private' ],
parameters: {
controls: { expanded: true },
docs: {
canvas: { sourceState: 'shown' },
- source: { transform },
},
},
decorators: [
@@ -91,116 +90,266 @@ const meta: Meta< typeof UseCompositeStorePlaceholder > = {
};
export default meta;
-export const Default: StoryFn< typeof UseCompositeStorePlaceholder > = (
- storeProps
-) => {
- const rtl = isRTL();
- const store = useCompositeStore( { rtl, ...storeProps } );
+export const Default: StoryObj< typeof Composite > = {
+ args: {
+ children: (
+ <>
+ Item one
+ Item two
+ Item three
+ >
+ ),
+ },
+};
- return (
-
- Item one
- Item two
- Item three
-
- );
+export const Groups: StoryObj< typeof Composite > = {
+ ...Default,
+ args: {
+ ...Default.args,
+ children: (
+ <>
+
+ Group one
+ Item 1.1
+ Item 1.2
+
+
+ Group two
+ Item 2.1
+ Item 2.1
+
+ >
+ ),
+ },
};
-export const Groups: StoryFn< typeof UseCompositeStorePlaceholder > = (
- storeProps
-) => {
- const rtl = isRTL();
- const store = useCompositeStore( { rtl, ...storeProps } );
+export const Grid: StoryObj< typeof Composite > = {
+ ...Default,
+ args: {
+ ...Default.args,
+ role: 'grid',
+ 'aria-label': 'Composite',
+ children: (
+ <>
+
+ Item A1
+ Item A2
+ Item A3
+
+
+ Item B1
+ Item B2
+ Item B3
+
+
+ Item C1
+ Item C2
+ Item C3
+
+ >
+ ),
+ },
+};
- return (
-
-
- Group one
- Item 1.1
- Item 1.2
-
-
- Group two
- Item 2.1
- Item 2.1
-
-
- );
+export const Hover: StoryObj< typeof Composite > = {
+ ...Default,
+ args: {
+ ...Default.args,
+ children: (
+ <>
+ }>
+ Hover item one
+
+ }>
+ Hover item two
+
+ }>
+ Hover item three
+
+ >
+ ),
+ },
+ parameters: {
+ docs: {
+ description: {
+ story: 'Elements in the composite widget will receive focus on mouse move and lose focus to the composite base element on mouse leave.',
+ },
+ },
+ },
+};
+
+export const Typeahead: StoryObj< typeof Composite > = {
+ args: {
+ ...Default.args,
+ render: ,
+ children: (
+ <>
+ Apple
+ Banana
+ Peach
+ >
+ ),
+ },
+ parameters: {
+ docs: {
+ description: {
+ story: 'When focus in on the composite widget, hitting printable character keys will move focus to the next composite item that begins with the input characters.',
+ },
+ },
+ },
};
-export const Grid: StoryFn< typeof UseCompositeStorePlaceholder > = (
- storeProps
-) => {
- const rtl = isRTL();
- const store = useCompositeStore( { rtl, ...storeProps } );
+const ExampleSlotFill = createSlotFill( 'Example' );
+
+const Slot = () => {
+ const compositeContext = useContext( Composite.Context );
+
+ // Forward the Slot's composite context to the Fill via fillProps, so that
+ // Composite components rendered inside the Fill can work as expected.
+ const fillProps = useMemo(
+ () => ( {
+ forwardedContext: [
+ [ Composite.Context.Provider, { value: compositeContext } ],
+ ],
+ } ),
+ [ compositeContext ]
+ );
return (
-
-
- Item A1
- Item A2
- Item A3
-
-
- Item B1
- Item B2
- Item B3
-
-
- Item C1
- Item C2
- Item C3
-
-
+
);
};
-export const Hover: StoryFn< typeof UseCompositeStorePlaceholder > = (
- storeProps
-) => {
- const rtl = isRTL();
- const store = useCompositeStore( { rtl, ...storeProps } );
+type ForwardedContextTuple< P = {} > = [
+ React.ComponentType< React.PropsWithChildren< P > >,
+ P,
+];
+
+const Fill = ( { children }: { children: React.ReactNode } ) => {
+ const innerMarkup = <>{ children }>;
return (
-
- }>
- Hover item one
-
- }>
- Hover item two
-
- }>
- Hover item three
-
-
+
+ { ( fillProps: { forwardedContext?: ForwardedContextTuple[] } ) => {
+ const { forwardedContext = [] } = fillProps;
+
+ // Render all context providers forwarded by the Slot via fillProps.
+ return forwardedContext.reduce(
+ ( inner: JSX.Element, [ Provider, props ] ) => (
+ { inner }
+ ),
+ innerMarkup
+ );
+ } }
+
);
};
-Hover.parameters = {
- docs: {
- description: {
- story: 'Elements in the composite widget will receive focus on mouse move and lose focus to the composite base element on mouse leave.',
- },
+
+export const WithSlotFill: StoryObj< typeof Composite > = {
+ ...Default,
+ args: {
+ ...Default.args,
+ children: (
+ <>
+ Item one (direct child)
+
+ Item four (direct child)
+ >
+ ),
},
+ decorators: [
+ ( Story ) => {
+ return (
+
+
+
+
+
+ Item two (from slot fill)
+
+
+ Item three (from slot fill)
+
+
+
+ );
+ },
+ ],
+ parameters: {
+ docs: {
+ description: {
+ story: 'When rendering Composite components across a SlotFill, the Composite.Context should be manually forwarded from the Slot to the Fill component.',
+ },
+ source: {
+ transform: ( code: string ) => {
+ return `const ExampleSlotFill = createSlotFill( 'Example' );
+
+const Slot = () => {
+ const compositeContext = useContext( Composite.Context );
+
+ // Forward the Slot's composite context to the Fill via fillProps, so that
+ // Composite components rendered inside the Fill can work as expected.
+ const fillProps = useMemo(
+ () => ( {
+ forwardedContext: [
+ [ Composite.Context.Provider, { value: compositeContext } ],
+ ],
+ } ),
+ [ compositeContext ]
+ );
+
+ return (
+
+ );
};
-export const Typeahead: StoryFn< typeof UseCompositeStorePlaceholder > = (
- storeProps
-) => {
- const rtl = isRTL();
- const store = useCompositeStore( { rtl, ...storeProps } );
+const Fill = ( { children } ) => {
+ const innerMarkup = <>{ children }>;
- return (
- }>
- Apple
- Banana
- Peach
-
- );
+ return (
+
+ { ( fillProps ) => {
+ const { forwardedContext = [] } = fillProps;
+
+ // Render all context providers forwarded by the Slot via fillProps.
+ return forwardedContext.reduce(
+ ( inner, [ Provider, props ] ) => (
+ { inner }
+ ),
+ innerMarkup
+ );
+ } }
+
+ );
};
-Typeahead.parameters = {
- docs: {
- description: {
- story: 'When focus in on the composite widget, hitting printable character keys will move focus to the next composite item that begins with the input characters.',
+
+// In a separate component:
+
+
+ ${
+ // Add one level of indentation to match the surrounding code.
+ code.replaceAll( '\n', '\n ' )
+ }
+
+
+
+ Item two (from slot fill)
+
+
+ Item three (from slot fill)
+
+
+ `;
+ },
+ },
},
},
};
diff --git a/packages/components/src/composite/stories/utils.tsx b/packages/components/src/composite/stories/utils.tsx
deleted file mode 100644
index f2f197877ff76..0000000000000
--- a/packages/components/src/composite/stories/utils.tsx
+++ /dev/null
@@ -1,76 +0,0 @@
-/**
- * External dependencies
- */
-import type { StoryContext } from '@storybook/react';
-
-/**
- * Internal dependencies
- */
-import type { CompositeStoreProps } from '../types';
-
-/**
- * Renders a widget based on the WAI-ARIA [`composite`](https://w3c.github.io/aria/#composite)
- * role, which provides a single tab stop on the page and arrow key navigation
- * through the focusable descendants.
- *
- * ```jsx
- * import { Composite, useCompositeStore } from '@wordpress/components';
- *
- * const store = useCompositeStore();
- *
- * Item 1
- * Item 2
- *
- * ```
- */
-export function UseCompositeStorePlaceholder( props: CompositeStoreProps ) {
- return (
-
- { Object.entries( props ).map( ( [ name, value ] ) => (
- <>
- { name }
- { JSON.stringify( value ) }
- >
- ) ) }
-
- );
-}
-UseCompositeStorePlaceholder.displayName = 'useCompositeStore';
-
-// The output generated by Storybook for these components is
-// messy, so we apply this transform to make it more useful
-// for anyone reading the docs.
-export function transform( code: string, context: StoryContext ) {
- const storeConfig = ` ${ JSON.stringify( context.args, null, 2 ) } `;
- const formattedStoreConfig = storeConfig.replace( ' {} ', '' );
- return [
- // Include a setup line, showing how to make use of
- // `useCompositeStore` to convert store options into
- // a composite store prop.
- `const store = useCompositeStore(${ formattedStoreConfig });`,
- '',
- 'return (',
- ' ' +
- code
- // The generated output includes a full dump of everything
- // in the store; the reader probably isn't interested in
- // what that looks like, so instead we drop all of that
- // in favor of the store generated above.
- .replaceAll( /store=\{\{[\s\S]*?\}\}/g, 'store={ store }' )
- // Now we tidy the output by removing any unnecessary
- // whitespace...
- .replaceAll( //g, ( match ) =>
- match.replaceAll( /\s+\s/g, ' ' )
- )
- // ...including around children...
- .replaceAll(
- />\s*(\w[\w ]*?)\s*<\//g,
- ( _, value ) => `>${ value }`
- )
- // ...and inside JSX definitions.
- .replaceAll( '} >', '}>' )
- // Finally we indent everything to make it more readable.
- .replaceAll( /\n/g, '\n ' ),
- ');',
- ].join( '\n' );
-}
diff --git a/packages/components/src/composite/typeahead.tsx b/packages/components/src/composite/typeahead.tsx
index d5bb7e6e2e4cc..771d58bcb6c25 100644
--- a/packages/components/src/composite/typeahead.tsx
+++ b/packages/components/src/composite/typeahead.tsx
@@ -22,7 +22,7 @@ export const CompositeTypeahead = forwardRef<
const context = useCompositeContext();
return (
diff --git a/packages/components/src/composite/types.ts b/packages/components/src/composite/types.ts
index fcde842e1cba7..ed95c7f0253b3 100644
--- a/packages/components/src/composite/types.ts
+++ b/packages/components/src/composite/types.ts
@@ -3,16 +3,18 @@
*/
import type * as Ariakit from '@ariakit/react';
-export type CompositeContextProps =
- | {
- /**
- * Object returned by the `useCompositeStore` hook.
- */
- store: Ariakit.CompositeStore;
- }
- | undefined;
+export type CompositeContextProps = {
+ /**
+ * The component store, used for advanced usage of the component.
+ *
+ * _Note: Using the store directly is not recommended. Instead, use the props
+ * exposed by the `Composite` component._
+ *
+ */
+ store?: unknown;
+};
-export type CompositeStoreProps = {
+type CompositeStoreProps = {
/**
* The current active item `id`. The active item is the element within the
* composite widget that has either DOM or virtual focus (in case
@@ -117,22 +119,18 @@ export type CompositeStoreProps = {
*/
orientation?: Ariakit.CompositeStoreProps[ 'orientation' ];
/**
- * Determines how the `store`'s `next` and `previous` functions will behave.
+ * Controls how the previous and next items are determined.
* If `rtl` is set to `true`, they will be inverted.
*
* This only affects the composite widget behavior. You still need to set
* `dir="rtl"` on HTML/CSS.
*
- * @default false
+ * @default `isRtl()`
*/
rtl?: Ariakit.CompositeStoreProps[ 'rtl' ];
};
export type CompositeProps = CompositeStoreProps & {
- /**
- * Object returned by the `useCompositeStore` hook.
- */
- store?: Ariakit.CompositeStore;
/**
* Allows the component to be rendered as a different HTML element or React
* component. The value can be a React element or a function that takes in the
diff --git a/packages/components/src/date-time/date/styles.ts b/packages/components/src/date-time/date/styles.ts
index 8f208b53fac22..bffc8ae35d2a6 100644
--- a/packages/components/src/date-time/date/styles.ts
+++ b/packages/components/src/date-time/date/styles.ts
@@ -107,6 +107,7 @@ export const DayButton = styled( Button, {
`
::before {
background: ${ props.isSelected ? COLORS.white : COLORS.theme.accent };
+ border-radius: ${ CONFIG.radiusRound };
bottom: 2px;
content: " ";
height: 4px;
diff --git a/packages/components/src/dimension-control/README.md b/packages/components/src/dimension-control/README.md
index 3cd0191a04606..78c1a60275c13 100644
--- a/packages/components/src/dimension-control/README.md
+++ b/packages/components/src/dimension-control/README.md
@@ -1,5 +1,9 @@
# DimensionControl
+
+This component is deprecated.
+
+
This feature is still experimental. “Experimental” means this is an early implementation subject to drastic and breaking changes.
diff --git a/packages/components/src/dimension-control/index.tsx b/packages/components/src/dimension-control/index.tsx
index 52662f31c3f24..25880f9b4fdb3 100644
--- a/packages/components/src/dimension-control/index.tsx
+++ b/packages/components/src/dimension-control/index.tsx
@@ -17,6 +17,7 @@ import sizesTable, { findSizeBySlug } from './sizes';
import type { DimensionControlProps, Size } from './types';
import type { SelectControlSingleSelectionProps } from '../select-control/types';
import { ContextSystemProvider } from '../context';
+import deprecated from '@wordpress/deprecated';
const CONTEXT_VALUE = {
BaseControl: {
@@ -29,7 +30,7 @@ const CONTEXT_VALUE = {
/**
* `DimensionControl` is a component designed to provide a UI to control spacing and/or dimensions.
*
- * This feature is still experimental. “Experimental” means this is an early implementation subject to drastic and breaking changes.
+ * @deprecated
*
* ```jsx
* import { __experimentalDimensionControl as DimensionControl } from '@wordpress/components';
@@ -62,6 +63,11 @@ export function DimensionControl( props: DimensionControlProps ) {
className = '',
} = props;
+ deprecated( 'wp.components.DimensionControl', {
+ since: '6.7',
+ version: '7.0',
+ } );
+
const onChangeSpacingSize: SelectControlSingleSelectionProps[ 'onChange' ] =
( val ) => {
const theSize = findSizeBySlug( sizes, val );
diff --git a/packages/components/src/dimension-control/stories/index.story.tsx b/packages/components/src/dimension-control/stories/index.story.tsx
index 3a6da44f46116..15a63fcf6ccf6 100644
--- a/packages/components/src/dimension-control/stories/index.story.tsx
+++ b/packages/components/src/dimension-control/stories/index.story.tsx
@@ -13,9 +13,15 @@ import sizes from '../sizes';
*/
import { desktop, tablet, mobile } from '@wordpress/icons';
+/**
+ * `DimensionControl` is a component designed to provide a UI to control spacing and/or dimensions.
+ *
+ * This component is deprecated.
+ */
const meta: Meta< typeof DimensionControl > = {
component: DimensionControl,
- title: 'Components (Experimental)/DimensionControl',
+ title: 'Components (Deprecated)/DimensionControl',
+ id: 'components-dimensioncontrol',
argTypes: {
onChange: { action: 'onChange' },
value: { control: { type: null } },
@@ -42,7 +48,6 @@ const Template: StoryFn< typeof DimensionControl > = ( args ) => (
);
export const Default = Template.bind( {} );
-
Default.args = {
__nextHasNoMarginBottom: true,
label: 'Please select a size',
diff --git a/packages/components/src/dimension-control/test/index.test.js b/packages/components/src/dimension-control/test/index.test.js
index 1b34d2983ad0f..14f1c509f70cf 100644
--- a/packages/components/src/dimension-control/test/index.test.js
+++ b/packages/components/src/dimension-control/test/index.test.js
@@ -31,6 +31,7 @@ describe( 'DimensionControl', () => {
const { container } = render(
);
+ expect( console ).toHaveWarned();
expect( container ).toMatchSnapshot();
} );
diff --git a/packages/components/src/index.ts b/packages/components/src/index.ts
index 3ddfbd05cd658..32195ebc444ce 100644
--- a/packages/components/src/index.ts
+++ b/packages/components/src/index.ts
@@ -66,6 +66,7 @@ export {
CompositeItem as __unstableCompositeItem,
useCompositeState as __unstableUseCompositeState,
} from './composite/legacy';
+export { Composite } from './composite';
export { ConfirmDialog as __experimentalConfirmDialog } from './confirm-dialog';
export { default as CustomSelectControl } from './custom-select-control';
export { default as Dashicon } from './dashicon';
diff --git a/packages/components/src/private-apis.ts b/packages/components/src/private-apis.ts
index fa9fece048617..b6e033ab24ab7 100644
--- a/packages/components/src/private-apis.ts
+++ b/packages/components/src/private-apis.ts
@@ -1,8 +1,6 @@
/**
* Internal dependencies
*/
-import { Composite } from './composite';
-import { useCompositeStore } from './composite/store';
import { positionToPlacement as __experimentalPopoverLegacyPositionToPlacement } from './popover/utils';
import { createPrivateSlotFill } from './slot-fill';
import { DropdownMenuV2 } from './dropdown-menu-v2';
@@ -14,11 +12,6 @@ import { lock } from './lock-unlock';
export const privateApis = {};
lock( privateApis, {
- CompositeV2: Composite,
- CompositeGroupV2: Composite.Group,
- CompositeItemV2: Composite.Item,
- CompositeRowV2: Composite.Row,
- useCompositeStoreV2: useCompositeStore,
__experimentalPopoverLegacyPositionToPlacement,
createPrivateSlotFill,
ComponentsContext,
diff --git a/packages/components/src/slot-fill/index.tsx b/packages/components/src/slot-fill/index.tsx
index b2df054973a5b..03ed33a67f13b 100644
--- a/packages/components/src/slot-fill/index.tsx
+++ b/packages/components/src/slot-fill/index.tsx
@@ -71,6 +71,7 @@ export function Provider( {
);
}
+Provider.displayName = 'SlotFillProvider';
export function createSlotFill( key: SlotKey ) {
const baseName = typeof key === 'symbol' ? key.description : key;
diff --git a/packages/compose/CHANGELOG.md b/packages/compose/CHANGELOG.md
index 951f70604f41c..2683fe8d79be7 100644
--- a/packages/compose/CHANGELOG.md
+++ b/packages/compose/CHANGELOG.md
@@ -2,6 +2,8 @@
## Unreleased
+## 7.7.0 (2024-09-05)
+
## 7.6.0 (2024-08-21)
## 7.5.0 (2024-08-07)
diff --git a/packages/compose/package.json b/packages/compose/package.json
index 92b3085e58575..4b68841d1777e 100644
--- a/packages/compose/package.json
+++ b/packages/compose/package.json
@@ -1,6 +1,6 @@
{
"name": "@wordpress/compose",
- "version": "7.6.0",
+ "version": "7.7.0",
"description": "WordPress higher-order components (HOCs).",
"author": "The WordPress Contributors",
"license": "GPL-2.0-or-later",
diff --git a/packages/core-commands/CHANGELOG.md b/packages/core-commands/CHANGELOG.md
index 16bf8c495eb03..02871d4f31e13 100644
--- a/packages/core-commands/CHANGELOG.md
+++ b/packages/core-commands/CHANGELOG.md
@@ -2,6 +2,8 @@
## Unreleased
+## 1.7.0 (2024-09-05)
+
## 1.6.0 (2024-08-21)
## 1.5.0 (2024-08-07)
diff --git a/packages/core-commands/package.json b/packages/core-commands/package.json
index 02b8b76b4f145..bae1e4c211cf0 100644
--- a/packages/core-commands/package.json
+++ b/packages/core-commands/package.json
@@ -1,6 +1,6 @@
{
"name": "@wordpress/core-commands",
- "version": "1.6.0",
+ "version": "1.7.0",
"description": "WordPress core reusable commands.",
"author": "The WordPress Contributors",
"license": "GPL-2.0-or-later",
diff --git a/packages/core-data/CHANGELOG.md b/packages/core-data/CHANGELOG.md
index caed77084733b..6286a55291a54 100644
--- a/packages/core-data/CHANGELOG.md
+++ b/packages/core-data/CHANGELOG.md
@@ -2,6 +2,8 @@
## Unreleased
+## 7.7.0 (2024-09-05)
+
## 7.6.0 (2024-08-21)
## 7.5.0 (2024-08-07)
diff --git a/packages/core-data/package.json b/packages/core-data/package.json
index e96f324708607..ddb2d2ef09177 100644
--- a/packages/core-data/package.json
+++ b/packages/core-data/package.json
@@ -1,6 +1,6 @@
{
"name": "@wordpress/core-data",
- "version": "7.6.0",
+ "version": "7.7.0",
"description": "Access to and manipulation of core WordPress entities.",
"author": "The WordPress Contributors",
"license": "GPL-2.0-or-later",
diff --git a/packages/core-data/src/resolvers.js b/packages/core-data/src/resolvers.js
index d1aaf0b447cfe..20270ef7f6cff 100644
--- a/packages/core-data/src/resolvers.js
+++ b/packages/core-data/src/resolvers.js
@@ -155,7 +155,7 @@ export const getEntityRecord =
}
);
- if ( query !== undefined ) {
+ if ( query !== undefined && query._fields ) {
query = { ...query, include: [ key ] };
// The resolution cache won't consider query as reusable based on the
diff --git a/packages/core-data/src/test/resolvers.js b/packages/core-data/src/test/resolvers.js
index 946b795726d2a..f15bee3b3c2b9 100644
--- a/packages/core-data/src/test/resolvers.js
+++ b/packages/core-data/src/test/resolvers.js
@@ -80,7 +80,6 @@ describe( 'getEntityRecord', () => {
it( 'accepts a query that overrides default api path', async () => {
const query = { context: 'view', _envelope: '1' };
- const queryObj = { include: [ 'post' ], ...query };
const select = {
hasEntityRecords: jest.fn( () => {} ),
@@ -98,13 +97,6 @@ describe( 'getEntityRecord', () => {
query
)( { dispatch, select, registry } );
- // Check resolution cache for an existing entity that fulfills the request with query.
- expect( select.hasEntityRecords ).toHaveBeenCalledWith(
- 'root',
- 'postType',
- queryObj
- );
-
// Trigger apiFetch, test that the query is present in the url.
expect( triggerFetch ).toHaveBeenCalledWith( {
path: '/wp/v2/types/post?context=view&_envelope=1',
@@ -116,7 +108,7 @@ describe( 'getEntityRecord', () => {
'root',
'postType',
POST_TYPE,
- queryObj
+ query
);
// Locks should have been acquired and released.
diff --git a/packages/create-block-interactive-template/CHANGELOG.md b/packages/create-block-interactive-template/CHANGELOG.md
index 52f97a68cbf87..c044dfff15e3a 100644
--- a/packages/create-block-interactive-template/CHANGELOG.md
+++ b/packages/create-block-interactive-template/CHANGELOG.md
@@ -2,6 +2,8 @@
## Unreleased
+## 2.7.0 (2024-09-05)
+
### Enhancements
- Set the minimum supported WordPress version to 6.6 to make it work seamlessly with the latest version of `@wordpress/scripts` package ([#64920](https://github.com/WordPress/gutenberg/pull/64920)).
diff --git a/packages/create-block-interactive-template/package.json b/packages/create-block-interactive-template/package.json
index 848cd75765215..667d3998ba820 100644
--- a/packages/create-block-interactive-template/package.json
+++ b/packages/create-block-interactive-template/package.json
@@ -1,6 +1,6 @@
{
"name": "@wordpress/create-block-interactive-template",
- "version": "2.6.0",
+ "version": "2.7.0",
"description": "Template for @wordpress/create-block to create interactive blocks with the Interactivity API.",
"author": "The WordPress Contributors",
"license": "GPL-2.0-or-later",
diff --git a/packages/create-block-tutorial-template/CHANGELOG.md b/packages/create-block-tutorial-template/CHANGELOG.md
index 50290a8e07e90..0fe0f748b8804 100644
--- a/packages/create-block-tutorial-template/CHANGELOG.md
+++ b/packages/create-block-tutorial-template/CHANGELOG.md
@@ -2,6 +2,8 @@
## Unreleased
+## 4.7.0 (2024-09-05)
+
### Enhancements
- Set the minimum supported WordPress version to 6.6 to make it work seamlessly with the latest version of `@wordpress/scripts` package ([#64920](https://github.com/WordPress/gutenberg/pull/64920)).
diff --git a/packages/create-block-tutorial-template/package.json b/packages/create-block-tutorial-template/package.json
index 0d9baf39d8db8..64a8a90bc167c 100644
--- a/packages/create-block-tutorial-template/package.json
+++ b/packages/create-block-tutorial-template/package.json
@@ -1,6 +1,6 @@
{
"name": "@wordpress/create-block-tutorial-template",
- "version": "4.6.0",
+ "version": "4.7.0",
"description": "This is a template for @wordpress/create-block that creates an example 'Copyright Date' block. This block is used in the official WordPress block development Quick Start Guide.",
"author": "The WordPress Contributors",
"license": "GPL-2.0-or-later",
diff --git a/packages/create-block/CHANGELOG.md b/packages/create-block/CHANGELOG.md
index 3f742b352614e..99e7b1fd37a33 100644
--- a/packages/create-block/CHANGELOG.md
+++ b/packages/create-block/CHANGELOG.md
@@ -2,6 +2,8 @@
## Unreleased
+## 4.50.0 (2024-09-05)
+
### Enhancements
- Unpin the `@wordpress/scripts` version and set the minimum supported WordPress version to 6.6 ([#64920](https://github.com/WordPress/gutenberg/pull/64920)).
diff --git a/packages/create-block/package.json b/packages/create-block/package.json
index 7548fca1532f0..2103a85c5894f 100644
--- a/packages/create-block/package.json
+++ b/packages/create-block/package.json
@@ -1,6 +1,6 @@
{
"name": "@wordpress/create-block",
- "version": "4.49.0",
+ "version": "4.50.0",
"description": "Generates PHP, JS and CSS code for registering a block for a WordPress plugin.",
"author": "The WordPress Contributors",
"license": "GPL-2.0-or-later",
diff --git a/packages/customize-widgets/CHANGELOG.md b/packages/customize-widgets/CHANGELOG.md
index aeec00430f47d..4e0d5a3755357 100644
--- a/packages/customize-widgets/CHANGELOG.md
+++ b/packages/customize-widgets/CHANGELOG.md
@@ -2,6 +2,8 @@
## Unreleased
+## 5.7.0 (2024-09-05)
+
## 5.6.0 (2024-08-21)
## 5.5.0 (2024-08-07)
diff --git a/packages/customize-widgets/package.json b/packages/customize-widgets/package.json
index 9c8c0a79b771a..a8b50cf9cb318 100644
--- a/packages/customize-widgets/package.json
+++ b/packages/customize-widgets/package.json
@@ -1,6 +1,6 @@
{
"name": "@wordpress/customize-widgets",
- "version": "5.6.1",
+ "version": "5.7.0",
"description": "Widgets blocks in Customizer Module for WordPress.",
"author": "The WordPress Contributors",
"license": "GPL-2.0-or-later",
diff --git a/packages/data-controls/CHANGELOG.md b/packages/data-controls/CHANGELOG.md
index ae38ef764c535..e6af7fdcb6e24 100644
--- a/packages/data-controls/CHANGELOG.md
+++ b/packages/data-controls/CHANGELOG.md
@@ -2,6 +2,8 @@
## Unreleased
+## 4.7.0 (2024-09-05)
+
## 4.6.0 (2024-08-21)
## 4.5.0 (2024-08-07)
diff --git a/packages/data-controls/package.json b/packages/data-controls/package.json
index 216f4000adff8..e97e59b74700c 100644
--- a/packages/data-controls/package.json
+++ b/packages/data-controls/package.json
@@ -1,6 +1,6 @@
{
"name": "@wordpress/data-controls",
- "version": "4.6.0",
+ "version": "4.7.0",
"description": "A set of common controls for the @wordpress/data api.",
"author": "The WordPress Contributors",
"license": "GPL-2.0-or-later",
diff --git a/packages/data/CHANGELOG.md b/packages/data/CHANGELOG.md
index 52b88a1c5d429..4ba90611c2a78 100644
--- a/packages/data/CHANGELOG.md
+++ b/packages/data/CHANGELOG.md
@@ -2,6 +2,8 @@
## Unreleased
+## 10.7.0 (2024-09-05)
+
## 10.6.0 (2024-08-21)
## 10.5.0 (2024-08-07)
diff --git a/packages/data/package.json b/packages/data/package.json
index fb27caaf37798..84ad7a7973bc4 100644
--- a/packages/data/package.json
+++ b/packages/data/package.json
@@ -1,6 +1,6 @@
{
"name": "@wordpress/data",
- "version": "10.6.0",
+ "version": "10.7.0",
"description": "Data module for WordPress.",
"author": "The WordPress Contributors",
"license": "GPL-2.0-or-later",
diff --git a/packages/dataviews/CHANGELOG.md b/packages/dataviews/CHANGELOG.md
index bf93b9e52f657..1e323714c4d5f 100644
--- a/packages/dataviews/CHANGELOG.md
+++ b/packages/dataviews/CHANGELOG.md
@@ -2,6 +2,8 @@
## Unreleased
+## 4.3.0 (2024-09-05)
+
## 4.2.0 (2024-08-21)
## New features
diff --git a/packages/dataviews/package.json b/packages/dataviews/package.json
index e02c0a624aa41..e327a217435c5 100644
--- a/packages/dataviews/package.json
+++ b/packages/dataviews/package.json
@@ -1,6 +1,6 @@
{
"name": "@wordpress/dataviews",
- "version": "4.2.0",
+ "version": "4.3.0",
"description": "DataViews is a component that provides an API to render datasets using different types of layouts (table, grid, list, etc.).",
"author": "The WordPress Contributors",
"license": "GPL-2.0-or-later",
diff --git a/packages/dataviews/src/components/dataviews-filters/search-widget.tsx b/packages/dataviews/src/components/dataviews-filters/search-widget.tsx
index 1b369222b8f28..459b68990753c 100644
--- a/packages/dataviews/src/components/dataviews-filters/search-widget.tsx
+++ b/packages/dataviews/src/components/dataviews-filters/search-widget.tsx
@@ -8,28 +8,18 @@ import removeAccents from 'remove-accents';
/**
* WordPress dependencies
*/
+import { useInstanceId } from '@wordpress/compose';
import { __, sprintf } from '@wordpress/i18n';
import { useState, useMemo, useDeferredValue } from '@wordpress/element';
-import {
- VisuallyHidden,
- Icon,
- privateApis as componentsPrivateApis,
-} from '@wordpress/components';
+import { VisuallyHidden, Icon, Composite } from '@wordpress/components';
import { search, check } from '@wordpress/icons';
import { SVG, Circle } from '@wordpress/primitives';
/**
* Internal dependencies
*/
-import { unlock } from '../../lock-unlock';
import type { Filter, NormalizedFilter, View } from '../../types';
-const {
- CompositeV2: Composite,
- CompositeItemV2: CompositeItem,
- useCompositeStoreV2: useCompositeStore,
-} = unlock( componentsPrivateApis );
-
interface SearchWidgetProps {
view: View;
filter: NormalizedFilter;
@@ -84,22 +74,37 @@ const getNewValue = (
return [ value ];
};
+function generateFilterElementCompositeItemId(
+ prefix: string,
+ filterElementValue: string
+) {
+ return `${ prefix }-${ filterElementValue }`;
+}
+
function ListBox( { view, filter, onChangeView }: SearchWidgetProps ) {
- const compositeStore = useCompositeStore( {
- virtualFocus: true,
- focusLoop: true,
- // When we have no or just one operator, we can set the first item as active.
- // We do that by passing `undefined` to `defaultActiveId`. Otherwise, we set it to `null`,
- // so the first item is not selected, since the focus is on the operators control.
- defaultActiveId: filter.operators?.length === 1 ? undefined : null,
- } );
+ const baseId = useInstanceId( ListBox, 'dataviews-filter-list-box' );
+
+ const [ activeCompositeId, setActiveCompositeId ] = useState<
+ string | null | undefined
+ >(
+ // When there are one or less operators, the first item is set as active
+ // (by setting the initial `activeId` to `undefined`).
+ // With 2 or more operators, the focus is moved on the operators control
+ // (by setting the initial `activeId` to `null`), meaning that there won't
+ // be an active item initially. Focus is then managed via the
+ // `onFocusVisible` callback.
+ filter.operators?.length === 1 ? undefined : null
+ );
const currentFilter = view.filters?.find(
( f ) => f.field === filter.field
);
const currentValue = getCurrentValue( filter, currentFilter );
return (
{
- if ( ! compositeStore.getState().activeId ) {
- compositeStore.move( compositeStore.first() );
+ // `onFocusVisible` needs the `Composite` component to be focusable,
+ // which is implicitly achieved via the `virtualFocus` prop.
+ if ( ! activeCompositeId && filter.elements.length ) {
+ setActiveCompositeId(
+ generateFilterElementCompositeItemId(
+ baseId,
+ filter.elements[ 0 ].value
+ )
+ );
}
} }
- render={ }
+ render={ }
>
{ filter.elements.map( ( element ) => (
-
{ element.label }
-
+
) ) }
);
diff --git a/packages/dataviews/src/components/dataviews-filters/style.scss b/packages/dataviews/src/components/dataviews-filters/style.scss
index f2841c16f0fec..ad834fb224e2e 100644
--- a/packages/dataviews/src/components/dataviews-filters/style.scss
+++ b/packages/dataviews/src/components/dataviews-filters/style.scss
@@ -169,7 +169,7 @@
display: flex;
align-items: center;
gap: $grid-unit-10;
- border-radius: $radius-block-ui;
+ border-radius: $radius-small;
box-sizing: border-box;
padding: $grid-unit-10 $grid-unit-15;
cursor: default;
diff --git a/packages/dataviews/src/components/dataviews-view-config/index.tsx b/packages/dataviews/src/components/dataviews-view-config/index.tsx
index 331d0d62dca00..c01c72d2ebc69 100644
--- a/packages/dataviews/src/components/dataviews-view-config/index.tsx
+++ b/packages/dataviews/src/components/dataviews-view-config/index.tsx
@@ -38,8 +38,13 @@ import {
sortIcons,
sortLabels,
} from '../../constants';
-import { VIEW_LAYOUTS, getMandatoryFields } from '../../dataviews-layouts';
-import type { NormalizedField, SupportedLayouts, View } from '../../types';
+import {
+ VIEW_LAYOUTS,
+ getNotHidableFieldIds,
+ getVisibleFieldIds,
+ getHiddenFieldIds,
+} from '../../dataviews-layouts';
+import type { SupportedLayouts, View, Field } from '../../types';
import DataViewsContext from '../dataviews-context';
import { unlock } from '../../lock-unlock';
import DensityPicker from '../../dataviews-layouts/grid/density-picker';
@@ -232,50 +237,34 @@ function ItemsPerPageControl() {
);
}
+interface FieldItemProps {
+ id: any;
+ label: string;
+ index: number;
+ isVisible: boolean;
+ isHidable: boolean;
+}
+
function FieldItem( {
+ field: { id, label, index, isVisible, isHidable },
fields,
- fieldId,
- mandatoryFields,
- viewFields,
view,
onChangeView,
}: {
- fields: NormalizedField< any >[];
- fieldId: string;
- mandatoryFields: string | any[];
- viewFields: string[];
+ field: FieldItemProps;
+ fields: Field< any >[];
view: View;
onChangeView: ( view: View ) => void;
} ) {
- let fieldLabel;
- let fieldIsHidable;
- const fieldObject = fields.find(
- ( f ) => f.id === fieldId
- ) as NormalizedField< any >;
- if ( fieldObject ) {
- fieldLabel = fieldObject.label;
- fieldIsHidable =
- fieldObject.enableHiding !== false &&
- ! mandatoryFields.includes( fieldId );
- } else if ( view.type === LAYOUT_TABLE ) {
- const combinedFieldObject = view.layout?.combinedFields?.find(
- ( f ) => f.id === fieldId
- );
- if ( combinedFieldObject ) {
- fieldLabel = combinedFieldObject.label;
- fieldIsHidable = ! mandatoryFields.includes( fieldId );
- }
- }
+ const visibleFieldIds = getVisibleFieldIds( view, fields );
- const index = view.fields?.indexOf( fieldId ) as number;
- const isVisible = viewFields.includes( fieldId );
return (
- -
+
-
- { fieldLabel }
+ { label }
{
- if ( ! view.fields || index < 1 ) {
- return;
- }
onChangeView( {
...view,
fields: [
- ...( view.fields.slice(
+ ...( visibleFieldIds.slice(
0,
index - 1
) ?? [] ),
- fieldId,
- view.fields[ index - 1 ],
- ...view.fields.slice( index + 1 ),
+ id,
+ visibleFieldIds[ index - 1 ],
+ ...visibleFieldIds.slice(
+ index + 1
+ ),
],
} );
} }
@@ -308,34 +296,26 @@ function FieldItem( {
label={ sprintf(
/* translators: %s: field label */
__( 'Move %s up' ),
- fieldLabel
+ label
) }
/>
= view.fields.length - 1
- }
+ disabled={ index >= visibleFieldIds.length - 1 }
accessibleWhenDisabled
size="compact"
onClick={ () => {
- if (
- ! view.fields ||
- index >= view.fields.length - 1
- ) {
- return;
- }
onChangeView( {
...view,
fields: [
- ...( view.fields.slice(
+ ...( visibleFieldIds.slice(
0,
index
) ?? [] ),
- view.fields[ index + 1 ],
- fieldId,
- ...view.fields.slice( index + 2 ),
+ visibleFieldIds[ index + 1 ],
+ id,
+ ...visibleFieldIds.slice(
+ index + 2
+ ),
],
} );
} }
@@ -343,31 +323,31 @@ function FieldItem( {
label={ sprintf(
/* translators: %s: field label */
__( 'Move %s down' ),
- fieldLabel
+ label
) }
/>{ ' ' }
>
) }
{
onChangeView( {
...view,
fields: isVisible
- ? viewFields.filter(
- ( id ) => id !== fieldId
+ ? visibleFieldIds.filter(
+ ( fieldId ) => fieldId !== id
)
- : [ ...viewFields, fieldId ],
+ : [ ...visibleFieldIds, id ],
} );
// Focus the visibility button to avoid focus loss.
// Our code is safe against the component being unmounted, so we don't need to worry about cleaning the timeout.
// eslint-disable-next-line @wordpress/react-no-unsafe-timeout
setTimeout( () => {
const element = document.querySelector(
- `.dataviews-field-control__field-${ fieldId } .dataviews-field-control__field-visibility-button`
+ `.dataviews-field-control__field-${ id } .dataviews-field-control__field-visibility-button`
);
if ( element instanceof HTMLElement ) {
element.focus();
@@ -380,12 +360,12 @@ function FieldItem( {
? sprintf(
/* translators: %s: field label */
__( 'Hide %s' ),
- fieldLabel
+ label
)
: sprintf(
/* translators: %s: field label */
__( 'Show %s' ),
- fieldLabel
+ label
)
}
/>
@@ -395,83 +375,77 @@ function FieldItem( {
);
}
-function FieldList( {
- fields,
- fieldIds,
- mandatoryFields,
- viewFields,
- view,
- onChangeView,
-}: Omit< Parameters< typeof FieldItem >[ 0 ], 'fieldId' > & {
- fieldIds: string[];
-} ) {
- return fieldIds.map( ( fieldId ) => (
-
- ) );
-}
-
function FieldControl() {
const { view, fields, onChangeView } = useContext( DataViewsContext );
- const mandatoryFields = useMemo(
- () => getMandatoryFields( view ),
+
+ const visibleFieldIds = useMemo(
+ () => getVisibleFieldIds( view, fields ),
+ [ view, fields ]
+ );
+ const hiddenFieldIds = useMemo(
+ () => getHiddenFieldIds( view, fields ),
+ [ view, fields ]
+ );
+ const notHidableFieldIds = useMemo(
+ () => getNotHidableFieldIds( view ),
[ view ]
);
- const viewFields = view.fields || fields.map( ( field ) => field.id );
- const visibleFields = view.fields;
- const hiddenFields = useMemo( () => {
- const nonViewFieldsList = fields
- .filter(
- ( field ) =>
- ! viewFields.includes( field.id ) &&
- ! mandatoryFields?.includes( field.id )
- )
- .map( ( field ) => field.id );
- if ( view.type !== LAYOUT_TABLE ) {
- return nonViewFieldsList;
- }
- const nonViewFieldsAndNonCombinedList = nonViewFieldsList.filter(
- ( fieldId ) => {
- return ! view.layout?.combinedFields?.some( ( combinedField ) =>
- combinedField.children.includes( fieldId )
- );
- }
- );
- const nonViewFieldsCombinedFieldsList =
- view.layout?.combinedFields
- ?.filter(
- ( combinedField ) =>
- ! viewFields.includes( combinedField.id )
- )
- .map( ( combinedField ) => combinedField.id ) || [];
- return [
- ...nonViewFieldsAndNonCombinedList,
- ...nonViewFieldsCombinedFieldsList,
- ];
- }, [ view, mandatoryFields, fields, viewFields ] );
+ const visibleFields = fields
+ .filter( ( { id } ) => visibleFieldIds.includes( id ) )
+ .map( ( { id, label, enableHiding } ) => {
+ return {
+ id,
+ label,
+ index: visibleFieldIds.indexOf( id ),
+ isVisible: true,
+ isHidable: notHidableFieldIds.includes( id )
+ ? false
+ : enableHiding,
+ };
+ } );
+ if ( view.type === LAYOUT_TABLE && view.layout?.combinedFields ) {
+ view.layout.combinedFields.forEach( ( { id, label } ) => {
+ visibleFields.push( {
+ id,
+ label,
+ index: visibleFieldIds.indexOf( id ),
+ isVisible: true,
+ isHidable: notHidableFieldIds.includes( id ),
+ } );
+ } );
+ }
+ visibleFields.sort( ( a, b ) => a.index - b.index );
+
+ const hiddenFields = fields
+ .filter( ( { id } ) => hiddenFieldIds.includes( id ) )
+ .map( ( { id, label, enableHiding }, index ) => {
+ return {
+ id,
+ label,
+ index,
+ isVisible: false,
+ isHidable: enableHiding,
+ };
+ } );
+
if ( ! visibleFields?.length && ! hiddenFields?.length ) {
return null;
}
+
return (
{ !! visibleFields?.length && (
-
+ { visibleFields.map( ( field ) => (
+
+ ) ) }
) }
{ !! hiddenFields?.length && (
@@ -481,14 +455,15 @@ function FieldControl() {
{ __( 'Hidden' ) }
-
+ { hiddenFields.map( ( field ) => (
+
+ ) ) }
>
diff --git a/packages/dataviews/src/components/dataviews/stories/fixtures.tsx b/packages/dataviews/src/components/dataviews/stories/fixtures.tsx
index 2ab02ec728e5e..ff098209b3468 100644
--- a/packages/dataviews/src/components/dataviews/stories/fixtures.tsx
+++ b/packages/dataviews/src/components/dataviews/stories/fixtures.tsx
@@ -547,7 +547,15 @@ export const themeData: Theme[] = [
export const themeFields: Field< Theme >[] = [
{ id: 'slug', label: 'Slug' },
{ id: 'name', label: 'Name' },
- { id: 'description', label: 'Description' },
+ {
+ id: 'description',
+ label: 'Description',
+ render: ( { item } ) => (
+
+ { item.description }
+
+ ),
+ },
{ id: 'requires', label: 'Requires at least' },
{ id: 'tested', label: 'Tested up to' },
{
diff --git a/packages/dataviews/src/components/dataviews/stories/index.story.tsx b/packages/dataviews/src/components/dataviews/stories/index.story.tsx
index 645c6d7ddcd92..3b3e1326115b0 100644
--- a/packages/dataviews/src/components/dataviews/stories/index.story.tsx
+++ b/packages/dataviews/src/components/dataviews/stories/index.story.tsx
@@ -17,7 +17,9 @@ import {
} from './fixtures';
import { LAYOUT_GRID, LAYOUT_LIST, LAYOUT_TABLE } from '../../../constants';
import { filterSortAndPaginate } from '../../../filter-and-sort-data-view';
-import type { View } from '../../../types';
+import type { CombinedField, View } from '../../../types';
+
+import './style.css';
const meta = {
title: 'DataViews/DataViews',
@@ -132,19 +134,39 @@ export const FieldsNoSortableNoHidable = () => {
};
export const CombinedFields = () => {
- const [ view, setView ] = useState< View >( {
- ...DEFAULT_VIEW,
- fields: [ 'theme', 'requires', 'tested' ],
- layout: {
- combinedFields: [
- {
- id: 'theme',
- label: 'Theme',
- children: [ 'name', 'description' ],
- direction: 'vertical',
+ const defaultLayoutsThemes = {
+ table: {
+ fields: [ 'theme', 'requires', 'tested' ],
+ layout: {
+ primaryField: 'name',
+ combinedFields: [
+ {
+ id: 'theme',
+ label: 'Theme',
+ children: [ 'name', 'description' ],
+ direction: 'vertical',
+ },
+ ] as CombinedField[],
+ styles: {
+ theme: {
+ maxWidth: 300,
+ },
},
- ],
+ },
},
+ grid: {
+ fields: [ 'description', 'requires', 'tested' ],
+ layout: { primaryField: 'name', columnFields: [ 'description' ] },
+ },
+ list: {
+ fields: [ 'requires', 'tested' ],
+ layout: { primaryField: 'name' },
+ },
+ };
+ const [ view, setView ] = useState< View >( {
+ ...DEFAULT_VIEW,
+ fields: defaultLayoutsThemes.table.fields,
+ layout: defaultLayoutsThemes.table.layout,
} );
const { data: shownData, paginationInfo } = useMemo( () => {
return filterSortAndPaginate( themeData, view, themeFields );
@@ -158,7 +180,7 @@ export const CombinedFields = () => {
view={ view }
fields={ themeFields }
onChangeView={ setView }
- defaultLayouts={ { table: {} } }
+ defaultLayouts={ defaultLayoutsThemes }
/>
);
};
diff --git a/packages/dataviews/src/components/dataviews/stories/style.css b/packages/dataviews/src/components/dataviews/stories/style.css
new file mode 100644
index 0000000000000..7c0c6565a6edf
--- /dev/null
+++ b/packages/dataviews/src/components/dataviews/stories/style.css
@@ -0,0 +1,4 @@
+.theme-field-description {
+ text-wrap: balance;
+ text-wrap: pretty;
+}
\ No newline at end of file
diff --git a/packages/dataviews/src/dataviews-layouts/grid/style.scss b/packages/dataviews/src/dataviews-layouts/grid/style.scss
index d154d2b614def..5fab362b0b47b 100644
--- a/packages/dataviews/src/dataviews-layouts/grid/style.scss
+++ b/packages/dataviews/src/dataviews-layouts/grid/style.scss
@@ -118,7 +118,7 @@
background: $gray-100;
padding: 0 $grid-unit-10;
min-height: $grid-unit-30;
- border-radius: $radius-block-ui;
+ border-radius: $radius-small;
display: flex;
align-items: center;
font-size: 12px;
diff --git a/packages/dataviews/src/dataviews-layouts/index.ts b/packages/dataviews/src/dataviews-layouts/index.ts
index 9c96475777c00..eece17d0f4f10 100644
--- a/packages/dataviews/src/dataviews-layouts/index.ts
+++ b/packages/dataviews/src/dataviews-layouts/index.ts
@@ -16,7 +16,7 @@ import ViewTable from './table';
import ViewGrid from './grid';
import ViewList from './list';
import { LAYOUT_GRID, LAYOUT_LIST, LAYOUT_TABLE } from '../constants';
-import type { View } from '../types';
+import type { View, Field } from '../types';
export const VIEW_LAYOUTS = [
{
@@ -39,7 +39,7 @@ export const VIEW_LAYOUTS = [
},
];
-export function getMandatoryFields( view: View ): string[] {
+export function getNotHidableFieldIds( view: View ): string[] {
if ( view.type === 'table' ) {
return [ view.layout?.primaryField ]
.concat(
@@ -64,3 +64,64 @@ export function getMandatoryFields( view: View ): string[] {
return [];
}
+
+function getCombinedFieldIds( view: View ): string[] {
+ const combinedFields: string[] = [];
+ if ( view.type === LAYOUT_TABLE && view.layout?.combinedFields ) {
+ view.layout.combinedFields.forEach( ( combination ) => {
+ combinedFields.push( ...combination.children );
+ } );
+ }
+ return combinedFields;
+}
+
+export function getVisibleFieldIds(
+ view: View,
+ fields: Field< any >[]
+): string[] {
+ const fieldsToExclude = getCombinedFieldIds( view );
+
+ if ( view.fields ) {
+ return view.fields.filter( ( id ) => ! fieldsToExclude.includes( id ) );
+ }
+
+ const visibleFields = [];
+ if ( view.type === LAYOUT_TABLE && view.layout?.combinedFields ) {
+ visibleFields.push(
+ ...view.layout.combinedFields.map( ( { id } ) => id )
+ );
+ }
+ visibleFields.push(
+ ...fields
+ .filter( ( { id } ) => ! fieldsToExclude.includes( id ) )
+ .map( ( { id } ) => id )
+ );
+
+ return visibleFields;
+}
+
+export function getHiddenFieldIds(
+ view: View,
+ fields: Field< any >[]
+): string[] {
+ const fieldsToExclude = [
+ ...getCombinedFieldIds( view ),
+ ...getVisibleFieldIds( view, fields ),
+ ];
+
+ // The media field does not need to be in the view.fields to be displayed.
+ if ( view.type === LAYOUT_GRID && view.layout?.mediaField ) {
+ fieldsToExclude.push( view.layout?.mediaField );
+ }
+
+ if ( view.type === LAYOUT_LIST && view.layout?.mediaField ) {
+ fieldsToExclude.push( view.layout?.mediaField );
+ }
+
+ return fields
+ .filter(
+ ( { id, enableHiding } ) =>
+ ! fieldsToExclude.includes( id ) && enableHiding
+ )
+ .map( ( { id } ) => id );
+}
diff --git a/packages/dataviews/src/dataviews-layouts/list/index.tsx b/packages/dataviews/src/dataviews-layouts/list/index.tsx
index d8889f25b24e9..8a3f6a297338c 100644
--- a/packages/dataviews/src/dataviews-layouts/list/index.tsx
+++ b/packages/dataviews/src/dataviews-layouts/list/index.tsx
@@ -2,17 +2,11 @@
* External dependencies
*/
import clsx from 'clsx';
-// TODO: use the @wordpress/components one once public
-// eslint-disable-next-line no-restricted-imports
-import { useStoreState } from '@ariakit/react';
-// Import CompositeStore type, which is not exported from @wordpress/components.
-// eslint-disable-next-line no-restricted-imports
-import type { CompositeStore } from '@ariakit/react';
/**
* WordPress dependencies
*/
-import { useInstanceId } from '@wordpress/compose';
+import { useInstanceId, usePrevious } from '@wordpress/compose';
import {
__experimentalHStack as HStack,
__experimentalVStack as VStack,
@@ -20,6 +14,7 @@ import {
privateApis as componentsPrivateApis,
Spinner,
VisuallyHidden,
+ Composite,
} from '@wordpress/components';
import {
useCallback,
@@ -44,39 +39,110 @@ import type { Action, NormalizedField, ViewListProps } from '../../types';
interface ListViewItemProps< Item > {
actions: Action< Item >[];
- id?: string;
+ idPrefix: string;
isSelected: boolean;
item: Item;
mediaField?: NormalizedField< Item >;
onSelect: ( item: Item ) => void;
primaryField?: NormalizedField< Item >;
- store: CompositeStore;
visibleFields: NormalizedField< Item >[];
+ onDropdownTriggerKeyDown: React.KeyboardEventHandler< HTMLButtonElement >;
}
-const {
- useCompositeStoreV2: useCompositeStore,
- CompositeV2: Composite,
- CompositeItemV2: CompositeItem,
- CompositeRowV2: CompositeRow,
- DropdownMenuV2: DropdownMenu,
-} = unlock( componentsPrivateApis );
+const { DropdownMenuV2: DropdownMenu } = unlock( componentsPrivateApis );
+
+function generateItemWrapperCompositeId( idPrefix: string ) {
+ return `${ idPrefix }-item-wrapper`;
+}
+function generatePrimaryActionCompositeId(
+ idPrefix: string,
+ primaryActionId: string
+) {
+ return `${ idPrefix }-primary-action-${ primaryActionId }`;
+}
+function generateDropdownTriggerCompositeId( idPrefix: string ) {
+ return `${ idPrefix }-dropdown`;
+}
+
+function PrimaryActionGridCell< Item >( {
+ idPrefix,
+ primaryAction,
+ item,
+}: {
+ idPrefix: string;
+ primaryAction: Action< Item >;
+ item: Item;
+} ) {
+ const registry = useRegistry();
+ const [ isModalOpen, setIsModalOpen ] = useState( false );
+
+ const compositeItemId = generatePrimaryActionCompositeId(
+ idPrefix,
+ primaryAction.id
+ );
+
+ const label =
+ typeof primaryAction.label === 'string'
+ ? primaryAction.label
+ : primaryAction.label( [ item ] );
+
+ return 'RenderModal' in primaryAction ? (
+
+
setIsModalOpen( true ) }
+ />
+ }
+ >
+ { isModalOpen && (
+
+ action={ primaryAction }
+ items={ [ item ] }
+ closeModal={ () => setIsModalOpen( false ) }
+ />
+ ) }
+
+
+ ) : (
+
+ {
+ primaryAction.callback( [ item ], { registry } );
+ } }
+ />
+ }
+ />
+
+ );
+}
function ListItem< Item >( {
actions,
- id,
+ idPrefix,
isSelected,
item,
mediaField,
onSelect,
primaryField,
- store,
visibleFields,
+ onDropdownTriggerKeyDown,
}: ListViewItemProps< Item > ) {
- const registry = useRegistry();
- const itemRef = useRef< HTMLElement >( null );
- const labelId = `${ id }-label`;
- const descriptionId = `${ id }-description`;
+ const itemRef = useRef< HTMLDivElement >( null );
+ const labelId = `${ idPrefix }-label`;
+ const descriptionId = `${ idPrefix }-description`;
const [ isHovered, setIsHovered ] = useState( false );
const handleMouseEnter = () => {
@@ -111,13 +177,6 @@ function ListItem< Item >( {
};
}, [ actions, item ] );
- const [ isModalOpen, setIsModalOpen ] = useState( false );
- const primaryActionLabel =
- primaryAction &&
- ( typeof primaryAction.label === 'string'
- ? primaryAction.label
- : primaryAction.label( [ item ] ) );
-
const renderedMediaField = mediaField?.render ? (
) : (
@@ -129,7 +188,7 @@ function ListItem< Item >( {
) : null;
return (
- }
role="row"
@@ -146,11 +205,10 @@ function ListItem< Item >( {
spacing={ 0 }
>
- }
role="button"
- id={ id }
+ id={ generateItemWrapperCompositeId( idPrefix ) }
aria-pressed={ isSelected }
aria-labelledby={ labelId }
aria-describedby={ descriptionId }
@@ -198,7 +256,7 @@ function ListItem< Item >( {
-
+
{ eligibleActions?.length > 0 && (
( {
width: 'auto',
} }
>
- { primaryAction && 'RenderModal' in primaryAction && (
-
-
- setIsModalOpen( true )
- }
- />
- }
- >
- { isModalOpen && (
-
- action={ primaryAction }
- items={ [ item ] }
- closeModal={ () =>
- setIsModalOpen( false )
- }
- />
- ) }
-
-
+ { primaryAction && (
+
) }
- { primaryAction &&
- ! ( 'RenderModal' in primaryAction ) && (
-
- {
- primaryAction.callback(
- [ item ],
- { registry }
- );
- } }
- />
- }
- />
-
- ) }
( {
label={ __( 'Actions' ) }
accessibleWhenDisabled
disabled={ ! actions.length }
- onKeyDown={ ( event: {
- key: string;
- preventDefault: () => void;
- } ) => {
- if (
- event.key ===
- 'ArrowDown'
- ) {
- // Prevent the default behaviour (open dropdown menu) and go down.
- event.preventDefault();
- store.move(
- store.down()
- );
- }
- if (
- event.key === 'ArrowUp'
- ) {
- // Prevent the default behavior (open dropdown menu) and go up.
- event.preventDefault();
- store.move(
- store.up()
- );
- }
- } }
+ onKeyDown={
+ onDropdownTriggerKeyDown
+ }
/>
}
/>
@@ -315,7 +307,7 @@ function ListItem< Item >( {
) }
-
+
);
}
@@ -331,6 +323,7 @@ export default function ViewList< Item >( props: ViewListProps< Item > ) {
view,
} = props;
const baseId = useInstanceId( ViewList, 'view-list' );
+
const selectedItem = data?.findLast( ( item ) =>
selection.includes( getItemId( item ) )
);
@@ -353,34 +346,108 @@ export default function ViewList< Item >( props: ViewListProps< Item > ) {
const onSelect = ( item: Item ) =>
onChangeSelection( [ getItemId( item ) ] );
- const getItemDomId = useCallback(
- ( item?: Item ) =>
- item ? `${ baseId }-${ getItemId( item ) }` : undefined,
+ const generateCompositeItemIdPrefix = useCallback(
+ ( item: Item ) => `${ baseId }-${ getItemId( item ) }`,
[ baseId, getItemId ]
);
- const store = useCompositeStore( {
- defaultActiveId: getItemDomId( selectedItem ),
- } ) as CompositeStore; // TODO, remove once composite APIs are public
+ const isActiveCompositeItem = useCallback(
+ ( item: Item, idToCheck: string ) => {
+ // All composite items use the same prefix in their IDs.
+ return idToCheck.startsWith(
+ generateCompositeItemIdPrefix( item )
+ );
+ },
+ [ generateCompositeItemIdPrefix ]
+ );
- // Manage focused item, when the active one is removed from the list.
- const isActiveIdInList = useStoreState(
- store,
- ( state: { items: any[]; activeId: any } ) =>
- state.items.some(
- ( item: { id: any } ) => item.id === state.activeId
- )
+ // Controlled state for the active composite item.
+ const [ activeCompositeId, setActiveCompositeId ] = useState<
+ string | null | undefined
+ >( undefined );
+
+ // Update the active composite item when the selected item changes.
+ useEffect( () => {
+ if ( selectedItem ) {
+ setActiveCompositeId(
+ generateItemWrapperCompositeId(
+ generateCompositeItemIdPrefix( selectedItem )
+ )
+ );
+ }
+ }, [ selectedItem, generateCompositeItemIdPrefix ] );
+
+ const activeItemIndex = data.findIndex( ( item ) =>
+ isActiveCompositeItem( item, activeCompositeId ?? '' )
);
+ const previousActiveItemIndex = usePrevious( activeItemIndex );
+ const isActiveIdInList = activeItemIndex !== -1;
+
+ const selectCompositeItem = useCallback(
+ (
+ targetIndex: number,
+ // Allows invokers to specify a custom function to generate the
+ // target composite item ID
+ generateCompositeId: ( idPrefix: string ) => string
+ ) => {
+ // Clamping between 0 and data.length - 1 to avoid out of bounds.
+ const clampedIndex = Math.min(
+ data.length - 1,
+ Math.max( 0, targetIndex )
+ );
+ const itemIdPrefix = generateCompositeItemIdPrefix(
+ data[ clampedIndex ]
+ );
+ const targetCompositeItemId = generateCompositeId( itemIdPrefix );
+
+ setActiveCompositeId( targetCompositeItemId );
+ document.getElementById( targetCompositeItemId )?.focus();
+ },
+ [ data, generateCompositeItemIdPrefix ]
+ );
+
+ // Select a new active composite item when the current active item
+ // is removed from the list.
useEffect( () => {
- if ( ! isActiveIdInList ) {
- // Prefer going down, except if there is no item below (last item), then go up (last item in list).
- if ( store.down() ) {
- store.move( store.down() );
- } else if ( store.up() ) {
- store.move( store.up() );
- }
+ const wasActiveIdInList =
+ previousActiveItemIndex !== undefined &&
+ previousActiveItemIndex !== -1;
+ if ( ! isActiveIdInList && wasActiveIdInList ) {
+ // By picking `previousActiveItemIndex` as the next item index, we are
+ // basically picking the item that would have been after the deleted one.
+ // If the previously active (and removed) item was the last of the list,
+ // we will select the item before it — which is the new last item.
+ selectCompositeItem(
+ previousActiveItemIndex,
+ generateItemWrapperCompositeId
+ );
}
- }, [ isActiveIdInList ] );
+ }, [ isActiveIdInList, selectCompositeItem, previousActiveItemIndex ] );
+
+ // Prevent the default behavior (open dropdown menu) and instead select the
+ // dropdown menu trigger on the previous/next row.
+ // https://github.com/ariakit/ariakit/issues/3768
+ const onDropdownTriggerKeyDown = useCallback(
+ ( event: React.KeyboardEvent< HTMLButtonElement > ) => {
+ if ( event.key === 'ArrowDown' ) {
+ // Select the dropdown menu trigger item in the next row.
+ event.preventDefault();
+ selectCompositeItem(
+ activeItemIndex + 1,
+ generateDropdownTriggerCompositeId
+ );
+ }
+ if ( event.key === 'ArrowUp' ) {
+ // Select the dropdown menu trigger item in the previous row.
+ event.preventDefault();
+ selectCompositeItem(
+ activeItemIndex - 1,
+ generateDropdownTriggerCompositeId
+ );
+ }
+ },
+ [ selectCompositeItem, activeItemIndex ]
+ );
const hasData = data?.length;
if ( ! hasData ) {
@@ -404,22 +471,23 @@ export default function ViewList< Item >( props: ViewListProps< Item > ) {
render={ }
className="dataviews-view-list"
role="grid"
- store={ store }
+ activeId={ activeCompositeId }
+ setActiveId={ setActiveCompositeId }
>
{ data.map( ( item ) => {
- const id = getItemDomId( item );
+ const id = generateCompositeItemIdPrefix( item );
return (
);
} ) }
diff --git a/packages/dataviews/src/dataviews-layouts/list/style.scss b/packages/dataviews/src/dataviews-layouts/list/style.scss
index 7344af6c3d1e8..ea3236f6d75e1 100644
--- a/packages/dataviews/src/dataviews-layouts/list/style.scss
+++ b/packages/dataviews/src/dataviews-layouts/list/style.scss
@@ -114,12 +114,12 @@ ul.dataviews-view-list {
&::before {
position: absolute;
content: "";
- top: calc(var(--wp-admin-border-width-focus) + 1px);
+ top: var(--wp-admin-border-width-focus);
right: var(--wp-admin-border-width-focus);
bottom: var(--wp-admin-border-width-focus);
left: var(--wp-admin-border-width-focus);
box-shadow: inset 0 0 0 var(--wp-admin-border-width-focus) var(--wp-admin-theme-color);
- border-radius: $radius-block-ui;
+ border-radius: $radius-small;
}
}
.dataviews-view-list__primary-field {
diff --git a/packages/dataviews/src/dataviews-layouts/table/column-header-menu.tsx b/packages/dataviews/src/dataviews-layouts/table/column-header-menu.tsx
index b019cbae36ab3..aff211fb613dc 100644
--- a/packages/dataviews/src/dataviews-layouts/table/column-header-menu.tsx
+++ b/packages/dataviews/src/dataviews-layouts/table/column-header-menu.tsx
@@ -25,7 +25,9 @@ import type {
NormalizedField,
SortDirection,
ViewTable as ViewTableType,
+ Operator,
} from '../../types';
+import { getVisibleFieldIds } from '../index';
const { DropdownMenuV2 } = unlock( componentsPrivateApis );
@@ -60,30 +62,43 @@ const _HeaderMenu = forwardRef( function HeaderMenu< Item >(
}: HeaderMenuProps< Item >,
ref: Ref< HTMLButtonElement >
) {
+ const visibleFieldIds = getVisibleFieldIds( view, fields );
+ const index = visibleFieldIds?.indexOf( fieldId ) as number;
+ const isSorted = view.sort?.field === fieldId;
+ let isHidable = false;
+ let isSortable = false;
+ let canAddFilter = false;
+ let header;
+ let operators: Operator[] = [];
+
const combinedField = view.layout?.combinedFields?.find(
( f ) => f.id === fieldId
);
- const index = view.fields?.indexOf( fieldId ) as number;
- if ( !! combinedField ) {
- return combinedField.header || combinedField.label;
- }
const field = fields.find( ( f ) => f.id === fieldId );
- if ( ! field ) {
- return null;
+
+ if ( ! combinedField ) {
+ if ( ! field ) {
+ // No combined or regular field found.
+ return null;
+ }
+
+ isHidable = field.enableHiding !== false;
+ isSortable = field.enableSorting !== false;
+ header = field.header;
+
+ operators = sanitizeOperators( field );
+ // Filter can be added:
+ // 1. If the field is not already part of a view's filters.
+ // 2. If the field meets the type and operator requirements.
+ // 3. If it's not primary. If it is, it should be already visible.
+ canAddFilter =
+ ! view.filters?.some( ( _filter ) => fieldId === _filter.field ) &&
+ !! field.elements?.length &&
+ !! operators.length &&
+ ! field.filterBy?.isPrimary;
+ } else {
+ header = combinedField.header || combinedField.label;
}
- const isHidable = field.enableHiding !== false;
- const isSortable = field.enableSorting !== false;
- const isSorted = view.sort?.field === field.id;
- const operators = sanitizeOperators( field );
- // Filter can be added:
- // 1. If the field is not already part of a view's filters.
- // 2. If the field meets the type and operator requirements.
- // 3. If it's not primary. If it is, it should be already visible.
- const canAddFilter =
- ! view.filters?.some( ( _filter ) => field.id === _filter.field ) &&
- !! field.elements?.length &&
- !! operators.length &&
- ! field.filterBy?.isPrimary;
return (
(
ref={ ref }
variant="tertiary"
>
- { field.header }
+ { header }
{ view.sort && isSorted && (
{ sortArrows[ view.sort.direction ] }
@@ -115,7 +130,7 @@ const _HeaderMenu = forwardRef( function HeaderMenu< Item >(
isSorted &&
view.sort.direction === direction;
- const value = `${ field.id }-${ direction }`;
+ const value = `${ fieldId }-${ direction }`;
return (
(
onChangeView( {
...view,
sort: {
- field: field.id,
+ field: fieldId,
direction,
},
} );
@@ -152,14 +167,14 @@ const _HeaderMenu = forwardRef( function HeaderMenu< Item >(
}
onClick={ () => {
- setOpenedFilter( field.id );
+ setOpenedFilter( fieldId );
onChangeView( {
...view,
page: 1,
filters: [
...( view.filters || [] ),
{
- field: field.id,
+ field: fieldId,
value: undefined,
operator: operators[ 0 ],
},
@@ -178,17 +193,16 @@ const _HeaderMenu = forwardRef( function HeaderMenu< Item >(
prefix={ }
disabled={ index < 1 }
onClick={ () => {
- if ( ! view.fields || index < 1 ) {
- return;
- }
onChangeView( {
...view,
fields: [
- ...( view.fields.slice( 0, index - 1 ) ??
- [] ),
- field.id,
- view.fields[ index - 1 ],
- ...view.fields.slice( index + 1 ),
+ ...( visibleFieldIds.slice(
+ 0,
+ index - 1
+ ) ?? [] ),
+ fieldId,
+ visibleFieldIds[ index - 1 ],
+ ...visibleFieldIds.slice( index + 1 ),
],
} );
} }
@@ -199,23 +213,16 @@ const _HeaderMenu = forwardRef( function HeaderMenu< Item >(
}
- disabled={
- ! view.fields || index >= view.fields.length - 1
- }
+ disabled={ index >= visibleFieldIds.length - 1 }
onClick={ () => {
- if (
- ! view.fields ||
- index >= view.fields.length - 1
- ) {
- return;
- }
onChangeView( {
...view,
fields: [
- ...( view.fields.slice( 0, index ) ?? [] ),
- view.fields[ index + 1 ],
- field.id,
- ...view.fields.slice( index + 2 ),
+ ...( visibleFieldIds.slice( 0, index ) ??
+ [] ),
+ visibleFieldIds[ index + 1 ],
+ fieldId,
+ ...visibleFieldIds.slice( index + 2 ),
],
} );
} }
@@ -224,17 +231,15 @@ const _HeaderMenu = forwardRef( function HeaderMenu< Item >(
{ __( 'Move right' ) }
- { isHidable && (
+ { isHidable && field && (
}
onClick={ () => {
- const viewFields =
- view.fields || fields.map( ( f ) => f.id );
onHide( field );
onChangeView( {
...view,
- fields: viewFields.filter(
- ( id ) => id !== field.id
+ fields: visibleFieldIds.filter(
+ ( id ) => id !== fieldId
),
} );
} }
diff --git a/packages/dataviews/src/dataviews-layouts/table/index.tsx b/packages/dataviews/src/dataviews-layouts/table/index.tsx
index b12082a55623b..4e1607b01489c 100644
--- a/packages/dataviews/src/dataviews-layouts/table/index.tsx
+++ b/packages/dataviews/src/dataviews-layouts/table/index.tsx
@@ -34,6 +34,7 @@ import type {
} from '../../types';
import type { SetSelection } from '../../private-types';
import ColumnHeaderMenu from './column-header-menu';
+import { getVisibleFieldIds } from '../index';
interface TableColumnFieldProps< Item > {
primaryField?: NormalizedField< Item >;
@@ -155,7 +156,7 @@ function TableRow< Item >( {
// `onClick` and can be used to exclude touchscreen devices from certain
// behaviours.
const isTouchDeviceRef = useRef( false );
- const columns = view.fields || fields.map( ( f ) => f.id );
+ const columns = getVisibleFieldIds( view, fields );
return (
( {
setNextHeaderMenuToFocus( fallback?.node );
};
- const columns = view.fields || fields.map( ( f ) => f.id );
+ const columns = getVisibleFieldIds( view, fields );
const hasData = !! data?.length;
const primaryField = fields.find(
diff --git a/packages/dataviews/src/normalize-fields.ts b/packages/dataviews/src/normalize-fields.ts
index 5f0baec12c4df..2d1cc0402bc20 100644
--- a/packages/dataviews/src/normalize-fields.ts
+++ b/packages/dataviews/src/normalize-fields.ts
@@ -61,6 +61,8 @@ export function normalizeFields< Item >(
sort,
isValid,
Edit,
+ enableHiding: field.enableHiding ?? true,
+ enableSorting: field.enableSorting ?? true,
};
} );
}
diff --git a/packages/dataviews/src/types.ts b/packages/dataviews/src/types.ts
index ca55442f6529a..e95a43994cd63 100644
--- a/packages/dataviews/src/types.ts
+++ b/packages/dataviews/src/types.ts
@@ -163,6 +163,8 @@ export type NormalizedField< Item > = Field< Item > & {
Edit: ComponentType< DataFormControlProps< Item > >;
sort: ( a: Item, b: Item, direction: SortDirection ) => number;
isValid: ( item: Item, context?: ValidationContext ) => boolean;
+ enableHiding: boolean;
+ enableSorting: boolean;
};
/**
diff --git a/packages/date/CHANGELOG.md b/packages/date/CHANGELOG.md
index 3940814a2f5d8..e19aa08ab6fe5 100644
--- a/packages/date/CHANGELOG.md
+++ b/packages/date/CHANGELOG.md
@@ -2,6 +2,8 @@
## Unreleased
+## 5.7.0 (2024-09-05)
+
## 5.6.0 (2024-08-21)
## 5.5.0 (2024-08-07)
diff --git a/packages/date/package.json b/packages/date/package.json
index b927d59686443..488db71cfd693 100644
--- a/packages/date/package.json
+++ b/packages/date/package.json
@@ -1,6 +1,6 @@
{
"name": "@wordpress/date",
- "version": "5.6.0",
+ "version": "5.7.0",
"description": "Date module for WordPress.",
"author": "The WordPress Contributors",
"license": "GPL-2.0-or-later",
diff --git a/packages/dependency-extraction-webpack-plugin/CHANGELOG.md b/packages/dependency-extraction-webpack-plugin/CHANGELOG.md
index ddfd7fb32710a..1da5f074301fd 100644
--- a/packages/dependency-extraction-webpack-plugin/CHANGELOG.md
+++ b/packages/dependency-extraction-webpack-plugin/CHANGELOG.md
@@ -2,6 +2,8 @@
## Unreleased
+## 6.7.0 (2024-09-05)
+
## 6.6.0 (2024-08-21)
## 6.5.0 (2024-08-07)
diff --git a/packages/dependency-extraction-webpack-plugin/package.json b/packages/dependency-extraction-webpack-plugin/package.json
index 5fd9b52f1acfd..f720a1df826e8 100644
--- a/packages/dependency-extraction-webpack-plugin/package.json
+++ b/packages/dependency-extraction-webpack-plugin/package.json
@@ -1,6 +1,6 @@
{
"name": "@wordpress/dependency-extraction-webpack-plugin",
- "version": "6.6.0",
+ "version": "6.7.0",
"description": "Extract WordPress script dependencies from webpack bundles.",
"author": "The WordPress Contributors",
"license": "GPL-2.0-or-later",
diff --git a/packages/deprecated/CHANGELOG.md b/packages/deprecated/CHANGELOG.md
index 5a19167c70965..673567a2a3e49 100644
--- a/packages/deprecated/CHANGELOG.md
+++ b/packages/deprecated/CHANGELOG.md
@@ -2,6 +2,8 @@
## Unreleased
+## 4.7.0 (2024-09-05)
+
## 4.6.0 (2024-08-21)
## 4.5.0 (2024-08-07)
diff --git a/packages/deprecated/package.json b/packages/deprecated/package.json
index 244a8a0825e29..ed2f9434539ef 100644
--- a/packages/deprecated/package.json
+++ b/packages/deprecated/package.json
@@ -1,6 +1,6 @@
{
"name": "@wordpress/deprecated",
- "version": "4.6.0",
+ "version": "4.7.0",
"description": "Deprecation utility for WordPress.",
"author": "The WordPress Contributors",
"license": "GPL-2.0-or-later",
diff --git a/packages/docgen/CHANGELOG.md b/packages/docgen/CHANGELOG.md
index db2451d218433..3aefc7cae99ae 100644
--- a/packages/docgen/CHANGELOG.md
+++ b/packages/docgen/CHANGELOG.md
@@ -2,6 +2,8 @@
## Unreleased
+## 2.7.0 (2024-09-05)
+
## 2.6.0 (2024-08-21)
## 2.5.0 (2024-08-07)
diff --git a/packages/docgen/package.json b/packages/docgen/package.json
index e5b8b294cde52..38a228d50a8e0 100644
--- a/packages/docgen/package.json
+++ b/packages/docgen/package.json
@@ -1,6 +1,6 @@
{
"name": "@wordpress/docgen",
- "version": "2.6.0",
+ "version": "2.7.0",
"description": "Autogenerate public API documentation from exports and JSDoc comments.",
"author": "The WordPress Contributors",
"license": "GPL-2.0-or-later",
diff --git a/packages/dom-ready/CHANGELOG.md b/packages/dom-ready/CHANGELOG.md
index 45cf7f02b5106..f3290182dff5c 100644
--- a/packages/dom-ready/CHANGELOG.md
+++ b/packages/dom-ready/CHANGELOG.md
@@ -2,6 +2,8 @@
## Unreleased
+## 4.7.0 (2024-09-05)
+
## 4.6.0 (2024-08-21)
## 4.5.0 (2024-08-07)
diff --git a/packages/dom-ready/package.json b/packages/dom-ready/package.json
index 5911fba9c58eb..89acde8f2b124 100644
--- a/packages/dom-ready/package.json
+++ b/packages/dom-ready/package.json
@@ -1,6 +1,6 @@
{
"name": "@wordpress/dom-ready",
- "version": "4.6.0",
+ "version": "4.7.0",
"description": "Execute callback after the DOM is loaded.",
"author": "The WordPress Contributors",
"license": "GPL-2.0-or-later",
diff --git a/packages/dom/CHANGELOG.md b/packages/dom/CHANGELOG.md
index 6444d64321a28..1857e3d51cb70 100644
--- a/packages/dom/CHANGELOG.md
+++ b/packages/dom/CHANGELOG.md
@@ -2,6 +2,8 @@
## Unreleased
+## 4.7.0 (2024-09-05)
+
## 4.6.0 (2024-08-21)
## 4.5.0 (2024-08-07)
diff --git a/packages/dom/package.json b/packages/dom/package.json
index d861e4263acce..dd05677fcb930 100644
--- a/packages/dom/package.json
+++ b/packages/dom/package.json
@@ -1,6 +1,6 @@
{
"name": "@wordpress/dom",
- "version": "4.6.0",
+ "version": "4.7.0",
"description": "DOM utilities module for WordPress.",
"author": "The WordPress Contributors",
"license": "GPL-2.0-or-later",
diff --git a/packages/e2e-test-utils-playwright/CHANGELOG.md b/packages/e2e-test-utils-playwright/CHANGELOG.md
index 2344239ebcdb2..eb3cbd95fe3ad 100644
--- a/packages/e2e-test-utils-playwright/CHANGELOG.md
+++ b/packages/e2e-test-utils-playwright/CHANGELOG.md
@@ -2,6 +2,8 @@
## Unreleased
+## 1.7.0 (2024-09-05)
+
## 1.6.0 (2024-08-21)
## 1.5.0 (2024-08-07)
diff --git a/packages/e2e-test-utils-playwright/package.json b/packages/e2e-test-utils-playwright/package.json
index 2430644c77b3b..1bb80bc4cc764 100644
--- a/packages/e2e-test-utils-playwright/package.json
+++ b/packages/e2e-test-utils-playwright/package.json
@@ -1,6 +1,6 @@
{
"name": "@wordpress/e2e-test-utils-playwright",
- "version": "1.6.0",
+ "version": "1.7.0",
"description": "End-To-End (E2E) test utils for WordPress.",
"author": "The WordPress Contributors",
"license": "GPL-2.0-or-later",
diff --git a/packages/e2e-test-utils/CHANGELOG.md b/packages/e2e-test-utils/CHANGELOG.md
index da33570821a31..b22c016a799bc 100644
--- a/packages/e2e-test-utils/CHANGELOG.md
+++ b/packages/e2e-test-utils/CHANGELOG.md
@@ -2,6 +2,8 @@
## Unreleased
+## 11.7.0 (2024-09-05)
+
## 11.6.0 (2024-08-21)
## 11.5.0 (2024-08-07)
diff --git a/packages/e2e-test-utils/package.json b/packages/e2e-test-utils/package.json
index d533cacee7a8b..02cee410f33d6 100644
--- a/packages/e2e-test-utils/package.json
+++ b/packages/e2e-test-utils/package.json
@@ -1,6 +1,6 @@
{
"name": "@wordpress/e2e-test-utils",
- "version": "11.6.0",
+ "version": "11.7.0",
"description": "End-To-End (E2E) test utils for WordPress.",
"author": "The WordPress Contributors",
"license": "GPL-2.0-or-later",
diff --git a/packages/e2e-tests/CHANGELOG.md b/packages/e2e-tests/CHANGELOG.md
index 568e58c11cdb0..a7ba03f05f466 100644
--- a/packages/e2e-tests/CHANGELOG.md
+++ b/packages/e2e-tests/CHANGELOG.md
@@ -2,6 +2,8 @@
## Unreleased
+## 8.7.0 (2024-09-05)
+
## 8.6.0 (2024-08-21)
## 8.5.0 (2024-08-07)
diff --git a/packages/e2e-tests/package.json b/packages/e2e-tests/package.json
index f6491e6d58c53..81e7fa1802c65 100644
--- a/packages/e2e-tests/package.json
+++ b/packages/e2e-tests/package.json
@@ -1,6 +1,6 @@
{
"name": "@wordpress/e2e-tests",
- "version": "8.6.0",
+ "version": "8.7.0",
"description": "End-To-End (E2E) tests for WordPress.",
"author": "The WordPress Contributors",
"license": "GPL-2.0-or-later",
diff --git a/packages/e2e-tests/plugins/block-bindings.php b/packages/e2e-tests/plugins/block-bindings.php
index b2eb9d797610d..143feb240ac2e 100644
--- a/packages/e2e-tests/plugins/block-bindings.php
+++ b/packages/e2e-tests/plugins/block-bindings.php
@@ -41,6 +41,16 @@ function gutenberg_test_block_bindings_registration() {
'default' => '#url-custom-field',
)
);
+ register_meta(
+ 'post',
+ 'empty_field',
+ array(
+ 'show_in_rest' => true,
+ 'type' => 'string',
+ 'single' => true,
+ 'default' => '',
+ )
+ );
register_meta(
'post',
'_protected_field',
diff --git a/packages/edit-post/CHANGELOG.md b/packages/edit-post/CHANGELOG.md
index c715ddebcd82a..cd4b4a36295f0 100644
--- a/packages/edit-post/CHANGELOG.md
+++ b/packages/edit-post/CHANGELOG.md
@@ -2,6 +2,8 @@
## Unreleased
+## 8.7.0 (2024-09-05)
+
## 8.6.0 (2024-08-21)
## 8.5.0 (2024-08-07)
diff --git a/packages/edit-post/package.json b/packages/edit-post/package.json
index 74152b849cf22..0d8e0b28f7c7c 100644
--- a/packages/edit-post/package.json
+++ b/packages/edit-post/package.json
@@ -1,6 +1,6 @@
{
"name": "@wordpress/edit-post",
- "version": "8.6.1",
+ "version": "8.7.0",
"description": "Edit Post module for WordPress.",
"author": "The WordPress Contributors",
"license": "GPL-2.0-or-later",
diff --git a/packages/edit-post/src/components/back-button/style.scss b/packages/edit-post/src/components/back-button/style.scss
index 8ffae89e31e05..aced752bfedfa 100644
--- a/packages/edit-post/src/components/back-button/style.scss
+++ b/packages/edit-post/src/components/back-button/style.scss
@@ -32,7 +32,7 @@
right: 9px;
bottom: 9px + $border-width; // Height of toolbar in edit-post (not edit-site) is 61px tall.
left: 9px;
- border-radius: $radius-block-ui + $border-width + $border-width;
+ border-radius: $radius-small + $border-width + $border-width;
box-shadow: inset 0 0 0 var(--wp-admin-border-width-focus) $gray-900;
}
@@ -54,7 +54,7 @@
.edit-post-fullscreen-mode-close_site-icon {
width: $button-size;
height: $button-size;
- border-radius: $radius-block-ui;
+ border-radius: $radius-small;
object-fit: cover;
// Compensate for the top-bar border.
margin-top: -($border-width);
diff --git a/packages/edit-post/src/components/layout/index.js b/packages/edit-post/src/components/layout/index.js
index 519b32691c6a4..185f97ba45a56 100644
--- a/packages/edit-post/src/components/layout/index.js
+++ b/packages/edit-post/src/components/layout/index.js
@@ -126,8 +126,8 @@ function useEditorStyles() {
? editorSettings.styles ?? []
: defaultEditorStyles;
- // Add a constant padding for the typewriter effect. When typing at the
- // bottom, there needs to be room to scroll up.
+ // Add a space for the typewriter effect. When typing in the last block,
+ // there needs to be room to scroll up.
if (
! isZoomedOutView &&
renderingMode === 'post-only' &&
diff --git a/packages/edit-post/src/components/layout/use-padding-appender.js b/packages/edit-post/src/components/layout/use-padding-appender.js
index ff342ded90817..efd46a485058c 100644
--- a/packages/edit-post/src/components/layout/use-padding-appender.js
+++ b/packages/edit-post/src/components/layout/use-padding-appender.js
@@ -18,12 +18,12 @@ export function usePaddingAppender() {
const { ownerDocument } = node;
const { defaultView } = ownerDocument;
- const paddingBottom = defaultView.parseInt(
- defaultView.getComputedStyle( node ).paddingBottom,
+ const pseudoHeight = defaultView.parseInt(
+ defaultView.getComputedStyle( node, ':after' ).height,
10
);
- if ( ! paddingBottom ) {
+ if ( ! pseudoHeight ) {
return;
}
@@ -38,25 +38,20 @@ export function usePaddingAppender() {
return;
}
- event.preventDefault();
+ event.stopPropagation();
const blockOrder = registry
.select( blockEditorStore )
.getBlockOrder( '' );
const lastBlockClientId = blockOrder[ blockOrder.length - 1 ];
- // Do nothing when only default block appender is present.
- if ( ! lastBlockClientId ) {
- return;
- }
-
const lastBlock = registry
.select( blockEditorStore )
.getBlock( lastBlockClientId );
const { selectBlock, insertDefaultBlock } =
registry.dispatch( blockEditorStore );
- if ( isUnmodifiedDefaultBlock( lastBlock ) ) {
+ if ( lastBlock && isUnmodifiedDefaultBlock( lastBlock ) ) {
selectBlock( lastBlockClientId );
} else {
insertDefaultBlock();
diff --git a/packages/edit-site/CHANGELOG.md b/packages/edit-site/CHANGELOG.md
index 2bed952f89a4e..025d2389e4b01 100644
--- a/packages/edit-site/CHANGELOG.md
+++ b/packages/edit-site/CHANGELOG.md
@@ -2,6 +2,8 @@
## Unreleased
+## 6.7.0 (2024-09-05)
+
## 6.6.0 (2024-08-21)
## 6.5.0 (2024-08-07)
diff --git a/packages/edit-site/package.json b/packages/edit-site/package.json
index 52292464a21d6..43bcf68aa68e6 100644
--- a/packages/edit-site/package.json
+++ b/packages/edit-site/package.json
@@ -1,6 +1,6 @@
{
"name": "@wordpress/edit-site",
- "version": "6.6.1",
+ "version": "6.7.0",
"description": "Edit Site Page module for WordPress.",
"author": "The WordPress Contributors",
"license": "GPL-2.0-or-later",
diff --git a/packages/edit-site/src/components/add-new-template/add-custom-template-modal-content.js b/packages/edit-site/src/components/add-new-template/add-custom-template-modal-content.js
index 0ef403379ccdb..4993f12153b9e 100644
--- a/packages/edit-site/src/components/add-new-template/add-custom-template-modal-content.js
+++ b/packages/edit-site/src/components/add-new-template/add-custom-template-modal-content.js
@@ -9,7 +9,7 @@ import {
FlexItem,
SearchControl,
TextHighlight,
- privateApis as componentsPrivateApis,
+ Composite,
__experimentalText as Text,
__experimentalVStack as VStack,
} from '@wordpress/components';
@@ -20,15 +20,8 @@ import { useDebouncedInput } from '@wordpress/compose';
/**
* Internal dependencies
*/
-import { unlock } from '../../lock-unlock';
import { mapToIHasNameAndId } from './utils';
-const {
- CompositeV2: Composite,
- CompositeItemV2: CompositeItem,
- useCompositeStoreV2: useCompositeStore,
-} = unlock( componentsPrivateApis );
-
const EMPTY_ARRAY = [];
function SuggestionListItem( {
@@ -40,7 +33,7 @@ function SuggestionListItem( {
const baseCssClass =
'edit-site-custom-template-modal__suggestions_list__list-item';
return (
-
) }
-
+
);
}
@@ -122,7 +115,6 @@ function useSearchSuggestions( entityForSuggestions, search ) {
}
function SuggestionList( { entityForSuggestions, onSelect } ) {
- const composite = useCompositeStore( { orientation: 'vertical' } );
const [ search, setSearch, debouncedSearch ] = useDebouncedInput();
const suggestions = useSearchSuggestions(
entityForSuggestions,
@@ -146,7 +138,7 @@ function SuggestionList( { entityForSuggestions, onSelect } ) {
) }
{ !! suggestions?.length && (
.components-button {
padding: $grid-unit-40;
- border-radius: $radius-block-ui;
display: flex;
flex-direction: column;
border: $border-width solid $gray-300;
diff --git a/packages/edit-site/src/components/editor-canvas-container/style.scss b/packages/edit-site/src/components/editor-canvas-container/style.scss
index fad566212e732..7df2b0ceca552 100644
--- a/packages/edit-site/src/components/editor-canvas-container/style.scss
+++ b/packages/edit-site/src/components/editor-canvas-container/style.scss
@@ -16,7 +16,7 @@
.edit-site-editor-canvas-container__section {
background: $white; // Fallback color, overridden by JavaScript.
- border-radius: $radius-block-ui;
+ border-radius: $radius-large;
bottom: 0;
left: 0;
overflow: hidden;
diff --git a/packages/edit-site/src/components/global-styles/screen-revisions/style.scss b/packages/edit-site/src/components/global-styles/screen-revisions/style.scss
index 46972f4b7c52f..5d0e7cb185137 100644
--- a/packages/edit-site/src/components/global-styles/screen-revisions/style.scss
+++ b/packages/edit-site/src/components/global-styles/screen-revisions/style.scss
@@ -43,7 +43,7 @@
}
&.is-selected {
- border-radius: $radius-block-ui;
+ border-radius: $radius-small;
// Only visible in Windows High Contrast mode.
outline: 3px solid transparent;
diff --git a/packages/edit-site/src/components/global-styles/style.scss b/packages/edit-site/src/components/global-styles/style.scss
index f85d69ad864ad..9bab48e308947 100644
--- a/packages/edit-site/src/components/global-styles/style.scss
+++ b/packages/edit-site/src/components/global-styles/style.scss
@@ -19,7 +19,7 @@
min-height: 100px;
margin-bottom: $grid-unit-20;
background: $gray-100;
- border-radius: $radius-block-ui;
+ border-radius: $radius-small;
overflow: hidden;
}
@@ -45,7 +45,7 @@
display: flex !important;
align-items: center;
justify-content: center;
- border-radius: $radius-block-ui;
+ border-radius: $radius-x-small;
}
.edit-site-global-styles-screen-typography__font-variants-count {
@@ -113,14 +113,14 @@
position: relative;
width: 100%;
border: $gray-200 $border-width solid;
- border-radius: $radius-block-ui;
+ border-radius: $radius-medium;
overflow: hidden;
}
.edit-site-global-styles__shadow-preview-panel {
height: $grid-unit-60 * 3;
border: $gray-200 $border-width solid;
- border-radius: $radius-block-ui;
+ border-radius: $radius-medium;
overflow: auto;
background-image: repeating-linear-gradient(45deg, #f5f5f5 25%, #0000 0, #0000 75%, #f5f5f5 0, #f5f5f5), repeating-linear-gradient(45deg, #f5f5f5 25%, #0000 0, #0000 75%, #f5f5f5 0, #f5f5f5);
background-position: 0 0, 8px 8px;
@@ -128,7 +128,7 @@
.edit-site-global-styles__shadow-preview-block {
border: $gray-200 $border-width solid;
- border-radius: $radius-block-ui;
+ border-radius: $radius-small;
background-color: $white;
width: 60%;
height: 60px;
diff --git a/packages/edit-site/src/components/global-styles/variations/style.scss b/packages/edit-site/src/components/global-styles/variations/style.scss
index 8d9b4238efa33..5f57c72f180b1 100644
--- a/packages/edit-site/src/components/global-styles/variations/style.scss
+++ b/packages/edit-site/src/components/global-styles/variations/style.scss
@@ -1,11 +1,10 @@
.edit-site-global-styles-variations_item {
box-sizing: border-box;
// To round the outline in Windows 10 high contrast mode.
- border-radius: $radius-block-ui;
cursor: pointer;
.edit-site-global-styles-variations_item-preview {
- border-radius: $radius-block-ui;
+ border-radius: $radius-small;
outline: $border-width solid rgba($black, 0.1);
outline-offset: -$border-width;
overflow: hidden;
diff --git a/packages/edit-site/src/components/layout/style.scss b/packages/edit-site/src/components/layout/style.scss
index 64fb1914af3dd..b2d929a7943db 100644
--- a/packages/edit-site/src/components/layout/style.scss
+++ b/packages/edit-site/src/components/layout/style.scss
@@ -120,7 +120,7 @@
overflow: hidden;
.edit-site-layout:not(.is-full-canvas) & {
- border-radius: $radius-block-ui * 4;
+ border-radius: $radius-large;
}
}
}
@@ -200,7 +200,7 @@ html.canvas-mode-edit-transition::view-transition-group(toggle) {
right: 9px;
bottom: 9px;
left: 9px;
- border-radius: $radius-block-ui + $border-width + $border-width;
+ border-radius: $radius-medium;
box-shadow: none;
}
diff --git a/packages/edit-site/src/components/page-patterns/style.scss b/packages/edit-site/src/components/page-patterns/style.scss
index a5aa1eb9ac796..c62fe34daf7d6 100644
--- a/packages/edit-site/src/components/page-patterns/style.scss
+++ b/packages/edit-site/src/components/page-patterns/style.scss
@@ -126,8 +126,8 @@
.components-form-token-field__suggestions-list:not(:empty) {
position: absolute;
border: $border-width solid var(--wp-admin-theme-color);
- border-bottom-left-radius: $radius-block-ui;
- border-bottom-right-radius: $radius-block-ui;
+ border-bottom-left-radius: $radius-small;
+ border-bottom-right-radius: $radius-small;
box-shadow: 0 0 0.5px 0.5px var(--wp-admin-theme-color);
box-sizing: border-box;
z-index: 1;
diff --git a/packages/edit-site/src/components/page-templates/style.scss b/packages/edit-site/src/components/page-templates/style.scss
index 4e21ca2c25be2..6a753921f6f40 100644
--- a/packages/edit-site/src/components/page-templates/style.scss
+++ b/packages/edit-site/src/components/page-templates/style.scss
@@ -36,7 +36,6 @@
}
.dataviews-view-table & {
- border-radius: $radius-block-ui;
position: relative;
width: 120px;
max-height: 160px;
@@ -49,7 +48,7 @@
width: 100%;
height: 100%;
box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.1);
- border-radius: $radius-block-ui;
+ border-radius: $radius-medium;
}
}
}
diff --git a/packages/edit-site/src/components/post-list/style.scss b/packages/edit-site/src/components/post-list/style.scss
index a86783c163c83..895a02b310672 100644
--- a/packages/edit-site/src/components/post-list/style.scss
+++ b/packages/edit-site/src/components/post-list/style.scss
@@ -68,7 +68,7 @@
background: $gray-100;
color: $gray-700;
padding: 0 $grid-unit-05;
- border-radius: $radius-block-ui;
+ border-radius: $radius-small;
font-size: 12px;
font-weight: 400;
flex-shrink: 0;
diff --git a/packages/edit-site/src/components/sidebar-dataviews/style.scss b/packages/edit-site/src/components/sidebar-dataviews/style.scss
index 9c5b8f48e944f..14e6bf1d03fca 100644
--- a/packages/edit-site/src/components/sidebar-dataviews/style.scss
+++ b/packages/edit-site/src/components/sidebar-dataviews/style.scss
@@ -8,7 +8,7 @@
}
.edit-site-sidebar-dataviews-dataview-item {
- border-radius: $radius-block-ui;
+ border-radius: $radius-small;
padding-right: $grid-unit-10;
.edit-site-sidebar-dataviews-dataview-item__dropdown-menu {
diff --git a/packages/edit-site/src/components/sidebar-navigation-item/style.scss b/packages/edit-site/src/components/sidebar-navigation-item/style.scss
index 908056d52af48..016027ef715a4 100644
--- a/packages/edit-site/src/components/sidebar-navigation-item/style.scss
+++ b/packages/edit-site/src/components/sidebar-navigation-item/style.scss
@@ -4,7 +4,6 @@
padding: $grid-unit-10 6px $grid-unit-10 $grid-unit-20;
border: none;
min-height: $grid-unit-50;
- border-radius: $radius-block-ui;
&:hover,
&:focus,
diff --git a/packages/edit-site/src/components/sidebar-navigation-screen/style.scss b/packages/edit-site/src/components/sidebar-navigation-screen/style.scss
index 43b789d669ba4..f0260581a8988 100644
--- a/packages/edit-site/src/components/sidebar-navigation-screen/style.scss
+++ b/packages/edit-site/src/components/sidebar-navigation-screen/style.scss
@@ -146,7 +146,6 @@
.components-input-control__input {
color: $gray-200 !important;
background: $gray-800 !important;
- border-radius: $radius-block-ui;
}
.components-input-control__backdrop {
border: 4px !important;
diff --git a/packages/edit-site/src/components/style-book/index.js b/packages/edit-site/src/components/style-book/index.js
index 7ee8eed375f9a..64503dcf7a6db 100644
--- a/packages/edit-site/src/components/style-book/index.js
+++ b/packages/edit-site/src/components/style-book/index.js
@@ -8,6 +8,7 @@ import clsx from 'clsx';
*/
import {
Disabled,
+ Composite,
privateApis as componentsPrivateApis,
} from '@wordpress/components';
import { __, sprintf } from '@wordpress/i18n';
@@ -45,12 +46,7 @@ const {
} = unlock( blockEditorPrivateApis );
const { mergeBaseAndUserConfigs } = unlock( editorPrivateApis );
-const {
- CompositeV2: Composite,
- CompositeItemV2: CompositeItem,
- useCompositeStoreV2: useCompositeStore,
- Tabs,
-} = unlock( componentsPrivateApis );
+const { Tabs } = unlock( componentsPrivateApis );
// The content area of the Style Book is rendered within an iframe so that global styles
// are applied to elements within the entire content area. To support elements that are
@@ -383,11 +379,9 @@ const StyleBookBody = ( {
const Examples = memo(
( { className, examples, category, label, isSelected, onSelect } ) => {
- const compositeStore = useCompositeStore( { orientation: 'vertical' } );
-
return (
{
return (
);
diff --git a/packages/edit-site/src/components/style-book/style.scss b/packages/edit-site/src/components/style-book/style.scss
index 3b2c6ab0867db..ab66ec288da31 100644
--- a/packages/edit-site/src/components/style-book/style.scss
+++ b/packages/edit-site/src/components/style-book/style.scss
@@ -3,13 +3,13 @@
// This is useful when the style book is used to fill a frame.
height: 100%;
&.is-button {
- border-radius: $radius-block-ui * 4;
+ border-radius: $radius-large;
}
}
.edit-site-style-book__iframe {
&.is-button {
- border-radius: $radius-block-ui * 4;
+ border-radius: $radius-large;
}
&.is-focused {
outline: calc(2 * var(--wp-admin-border-width-focus)) solid var(--wp-admin-theme-color);
diff --git a/packages/edit-site/src/components/welcome-guide/template.js b/packages/edit-site/src/components/welcome-guide/template.js
index 0e699e6b4b242..e6568a23bb3a3 100644
--- a/packages/edit-site/src/components/welcome-guide/template.js
+++ b/packages/edit-site/src/components/welcome-guide/template.js
@@ -10,29 +10,23 @@ import { store as editorStore } from '@wordpress/editor';
/**
* Internal dependencies
*/
-import { store as editSiteStore } from '../../store';
+import useEditedEntityRecord from '../use-edited-entity-record';
export default function WelcomeGuideTemplate() {
const { toggle } = useDispatch( preferencesStore );
- const isVisible = useSelect( ( select ) => {
- const isTemplateActive = !! select( preferencesStore ).get(
- 'core/edit-site',
- 'welcomeGuideTemplate'
- );
- const isEditorActive = !! select( preferencesStore ).get(
- 'core/edit-site',
- 'welcomeGuide'
- );
- const { isPage } = select( editSiteStore );
- const { getCurrentPostType } = select( editorStore );
- return (
- isTemplateActive &&
- ! isEditorActive &&
- isPage() &&
- getCurrentPostType() === 'wp_template'
- );
+ const { isLoaded, record } = useEditedEntityRecord();
+ const isPostTypeTemplate = isLoaded && record.type === 'wp_template';
+ const { isActive, hasPreviousEntity } = useSelect( ( select ) => {
+ const { getEditorSettings } = select( editorStore );
+ const { get } = select( preferencesStore );
+ return {
+ isActive: get( 'core/edit-site', 'welcomeGuideTemplate' ),
+ hasPreviousEntity:
+ !! getEditorSettings().onNavigateToPreviousEntityRecord,
+ };
}, [] );
+ const isVisible = isActive && isPostTypeTemplate && hasPreviousEntity;
if ( ! isVisible ) {
return null;
diff --git a/packages/edit-widgets/CHANGELOG.md b/packages/edit-widgets/CHANGELOG.md
index eb185d530887d..f1cbcef0667d7 100644
--- a/packages/edit-widgets/CHANGELOG.md
+++ b/packages/edit-widgets/CHANGELOG.md
@@ -2,6 +2,8 @@
## Unreleased
+## 6.7.0 (2024-09-05)
+
## 6.6.0 (2024-08-21)
## 6.5.0 (2024-08-07)
diff --git a/packages/edit-widgets/package.json b/packages/edit-widgets/package.json
index ed48d07a1d1e5..d24857f0f8a0c 100644
--- a/packages/edit-widgets/package.json
+++ b/packages/edit-widgets/package.json
@@ -1,6 +1,6 @@
{
"name": "@wordpress/edit-widgets",
- "version": "6.6.1",
+ "version": "6.7.0",
"description": "Widgets Page module for WordPress..",
"author": "The WordPress Contributors",
"license": "GPL-2.0-or-later",
diff --git a/packages/editor/CHANGELOG.md b/packages/editor/CHANGELOG.md
index 05bb9beb3b1fc..b380c2fd296d5 100644
--- a/packages/editor/CHANGELOG.md
+++ b/packages/editor/CHANGELOG.md
@@ -2,6 +2,8 @@
## Unreleased
+## 14.7.0 (2024-09-05)
+
## 14.6.0 (2024-08-21)
## 14.5.0 (2024-08-07)
diff --git a/packages/editor/package.json b/packages/editor/package.json
index 7e120895c782f..a9d486b74e79c 100644
--- a/packages/editor/package.json
+++ b/packages/editor/package.json
@@ -1,6 +1,6 @@
{
"name": "@wordpress/editor",
- "version": "14.6.0",
+ "version": "14.7.0",
"description": "Enhanced block editor for WordPress posts.",
"author": "The WordPress Contributors",
"license": "GPL-2.0-or-later",
diff --git a/packages/editor/src/bindings/post-meta.js b/packages/editor/src/bindings/post-meta.js
index 1ecd6ea50ba27..7618ba6c36023 100644
--- a/packages/editor/src/bindings/post-meta.js
+++ b/packages/editor/src/bindings/post-meta.js
@@ -22,7 +22,7 @@ export default {
for ( const [ attributeName, source ] of Object.entries( bindings ) ) {
// Use the key if the value is not set.
newValues[ attributeName ] =
- meta?.[ source.args.key ] || source.args.key;
+ meta?.[ source.args.key ] ?? source.args.key;
}
return newValues;
},
@@ -62,6 +62,12 @@ export default {
if ( fieldValue === undefined ) {
return false;
}
+ // Check that custom fields metabox is not enabled.
+ const areCustomFieldsEnabled =
+ select( editorStore ).getEditorSettings().enableCustomFields;
+ if ( areCustomFieldsEnabled ) {
+ return false;
+ }
// Check that the user has the capability to edit post meta.
const canUserEdit = select( coreDataStore ).canUser( 'update', {
diff --git a/packages/editor/src/components/document-outline/style.scss b/packages/editor/src/components/document-outline/style.scss
index efd2606b82d39..49ce0c9b2d132 100644
--- a/packages/editor/src/components/document-outline/style.scss
+++ b/packages/editor/src/components/document-outline/style.scss
@@ -51,7 +51,7 @@
padding: 2px 5px 2px 1px;
color: $gray-900;
text-align: left;
- border-radius: $radius-block-ui;
+ border-radius: $radius-small;
&:disabled {
cursor: default;
diff --git a/packages/editor/src/components/header/style.scss b/packages/editor/src/components/header/style.scss
index 99c9cc70e166e..8712121fff3ea 100644
--- a/packages/editor/src/components/header/style.scss
+++ b/packages/editor/src/components/header/style.scss
@@ -243,7 +243,7 @@
width: 100%;
@include break-medium {
- border-bottom: 1px solid #e0e0e0;
+ box-shadow: 0 $border-width 0 0 rgba($color: #000, $alpha: 0.133); // 0.133 = $gray-200 but with alpha.
position: absolute;
}
diff --git a/packages/editor/src/components/inserter-sidebar/index.js b/packages/editor/src/components/inserter-sidebar/index.js
index bf613b5c8c001..fef5e54e52f68 100644
--- a/packages/editor/src/components/inserter-sidebar/index.js
+++ b/packages/editor/src/components/inserter-sidebar/index.js
@@ -38,13 +38,14 @@ export default function InserterSidebar() {
getBlockInsertionPoint,
getBlockRootClientId,
__unstableGetEditorMode,
- getSettings,
- } = select( blockEditorStore );
+ getSectionRootClientId,
+ } = unlock( select( blockEditorStore ) );
const { get } = select( preferencesStore );
const { getActiveComplementaryArea } = select( interfaceStore );
const getBlockSectionRootClientId = () => {
if ( __unstableGetEditorMode() === 'zoom-out' ) {
- const { sectionRootClientId } = unlock( getSettings() );
+ const sectionRootClientId = getSectionRootClientId();
+
if ( sectionRootClientId ) {
return sectionRootClientId;
}
diff --git a/packages/editor/src/components/post-card-panel/style.scss b/packages/editor/src/components/post-card-panel/style.scss
index 3547b0ab10493..73b638673f3e9 100644
--- a/packages/editor/src/components/post-card-panel/style.scss
+++ b/packages/editor/src/components/post-card-panel/style.scss
@@ -46,7 +46,7 @@
background: $gray-100;
color: $gray-700;
padding: 0 $grid-unit-05;
- border-radius: $radius-block-ui;
+ border-radius: $radius-small;
font-size: 12px;
font-weight: 400;
flex-shrink: 0;
diff --git a/packages/editor/src/components/post-featured-image/style.scss b/packages/editor/src/components/post-featured-image/style.scss
index d3a4fbbcaef68..3a537471b42f2 100644
--- a/packages/editor/src/components/post-featured-image/style.scss
+++ b/packages/editor/src/components/post-featured-image/style.scss
@@ -22,7 +22,7 @@
}
.components-drop-zone__content {
- border-radius: $radius-block-ui;
+ border-radius: $radius-small;
}
// Align text and icons horizontally to avoid clipping when the featured image is not set.
@@ -65,7 +65,6 @@
}
.editor-post-featured-image__toggle {
- border-radius: $radius-block-ui;
height: 100%;
line-height: 20px;
padding: $grid-unit-10 0;
diff --git a/packages/editor/src/components/post-locked-modal/style.scss b/packages/editor/src/components/post-locked-modal/style.scss
index 03e86642493df..7f68002234466 100644
--- a/packages/editor/src/components/post-locked-modal/style.scss
+++ b/packages/editor/src/components/post-locked-modal/style.scss
@@ -3,7 +3,7 @@
}
.editor-post-locked-modal__avatar {
- border-radius: $radius-block-ui;
+ border-radius: $radius-round;
margin-top: $grid-unit-20;
min-width: initial !important;
}
diff --git a/packages/editor/src/components/post-publish-panel/style.scss b/packages/editor/src/components/post-publish-panel/style.scss
index bcd7c798c7e9f..9892cf5430f9a 100644
--- a/packages/editor/src/components/post-publish-panel/style.scss
+++ b/packages/editor/src/components/post-publish-panel/style.scss
@@ -37,7 +37,7 @@
.components-site-icon {
border: none;
- border-radius: $radius-block-ui;
+ border-radius: $radius-small;
margin-right: $grid-unit-15;
flex-shrink: 0;
diff --git a/packages/editor/src/components/post-template/block-theme.js b/packages/editor/src/components/post-template/block-theme.js
index 7fcc5ead14f5b..62de10a2c715f 100644
--- a/packages/editor/src/components/post-template/block-theme.js
+++ b/packages/editor/src/components/post-template/block-theme.js
@@ -8,6 +8,7 @@ import { __ } from '@wordpress/i18n';
import { useEntityRecord, store as coreStore } from '@wordpress/core-data';
import { check } from '@wordpress/icons';
import { store as noticesStore } from '@wordpress/notices';
+import { store as preferencesStore } from '@wordpress/preferences';
/**
* Internal dependencies
@@ -43,6 +44,8 @@ export default function BlockThemeControl( { id } ) {
};
}, [] );
+ const { get: getPreference } = useSelect( preferencesStore );
+
const { editedRecord: template, hasResolved } = useEntityRecord(
'postType',
'wp_template',
@@ -75,6 +78,17 @@ export default function BlockThemeControl( { id } ) {
},
]
: undefined;
+
+ const mayShowTemplateEditNotice = () => {
+ if ( ! getPreference( 'core/edit-site', 'welcomeGuideTemplate' ) ) {
+ createSuccessNotice(
+ __(
+ 'Editing template. Changes made here affect all posts and pages that use the template.'
+ ),
+ { type: 'snackbar', actions: notificationAction }
+ );
+ }
+ };
return (
{ __( 'Edit template' ) }
diff --git a/packages/editor/src/components/preview-dropdown/index.js b/packages/editor/src/components/preview-dropdown/index.js
index 8b51bb79bc887..5acaa351c9bb7 100644
--- a/packages/editor/src/components/preview-dropdown/index.js
+++ b/packages/editor/src/components/preview-dropdown/index.js
@@ -112,22 +112,24 @@ export default function PreviewDropdown( { forceIsAutosaveable, disabled } ) {
label: __( 'Desktop' ),
icon: desktop,
},
- {
+ ];
+ if ( window.__experimentalEnableZoomOutExperiment ) {
+ choices.push( {
value: 'ZoomOut',
label: __( 'Desktop (50%)' ),
icon: desktop,
- },
- {
- value: 'Tablet',
- label: __( 'Tablet' ),
- icon: tablet,
- },
- {
- value: 'Mobile',
- label: __( 'Mobile' ),
- icon: mobile,
- },
- ];
+ } );
+ }
+ choices.push( {
+ value: 'Tablet',
+ label: __( 'Tablet' ),
+ icon: tablet,
+ } );
+ choices.push( {
+ value: 'Mobile',
+ label: __( 'Mobile' ),
+ icon: mobile,
+ } );
const previewValue = editorMode === 'zoom-out' ? 'ZoomOut' : deviceType;
diff --git a/packages/editor/src/components/provider/use-block-editor-settings.js b/packages/editor/src/components/provider/use-block-editor-settings.js
index 6aa2763cf9db0..868ff08b3d070 100644
--- a/packages/editor/src/components/provider/use-block-editor-settings.js
+++ b/packages/editor/src/components/provider/use-block-editor-settings.js
@@ -23,7 +23,7 @@ import {
import inserterMediaCategories from '../media-categories';
import { mediaUpload } from '../../utils';
import { store as editorStore } from '../../store';
-import { lock, unlock } from '../../lock-unlock';
+import { unlock } from '../../lock-unlock';
import { useGlobalStylesContext } from '../global-styles-provider';
const EMPTY_BLOCKS_LIST = [];
@@ -47,6 +47,7 @@ const BLOCK_EDITOR_SETTINGS = [
'allowedMimeTypes',
'bodyPlaceholder',
'canLockBlocks',
+ 'canUpdateBlockBindings',
'capabilities',
'clearBlockSelection',
'codeEditingEnabled',
@@ -74,7 +75,6 @@ const BLOCK_EDITOR_SETTINGS = [
'postContentAttributes',
'postsPerPage',
'readOnly',
- 'sectionRootClientId',
'styles',
'titlePlaceholder',
'supportsLayout',
@@ -90,6 +90,7 @@ const {
globalStylesLinksDataKey,
selectBlockPatternsKey,
reusableBlocksSelectKey,
+ sectionRootClientIdKey,
} = unlock( privateApis );
/**
@@ -325,10 +326,9 @@ function useBlockEditorSettings( settings, postType, postId, renderingMode ) {
? [ [ 'core/navigation', {}, [] ] ]
: settings.template,
__experimentalSetIsInserterOpened: setIsInserterOpened,
+ [ sectionRootClientIdKey ]: sectionRootClientId,
};
- lock( blockEditorSettings, {
- sectionRootClientId,
- } );
+
return blockEditorSettings;
}, [
allowedBlockTypes,
diff --git a/packages/editor/src/components/resizable-editor/style.scss b/packages/editor/src/components/resizable-editor/style.scss
index 91ff1144c4179..364fdf39ad315 100644
--- a/packages/editor/src/components/resizable-editor/style.scss
+++ b/packages/editor/src/components/resizable-editor/style.scss
@@ -16,7 +16,7 @@
cursor: ew-resize;
outline: none;
background: none;
- border-radius: $radius-block-ui;
+ border-radius: $radius-full;
border: 0;
height: 100px;
@@ -29,7 +29,7 @@
content: "";
width: $grid-unit-05;
background-color: rgba($gray-700, 0.4);
- border-radius: $radius-block-ui;
+ border-radius: $radius-full;
}
&.is-left {
diff --git a/packages/editor/src/dataviews/actions/view-post.tsx b/packages/editor/src/dataviews/actions/view-post.tsx
index 47eb1a66d019a..187faffafb5d3 100644
--- a/packages/editor/src/dataviews/actions/view-post.tsx
+++ b/packages/editor/src/dataviews/actions/view-post.tsx
@@ -2,7 +2,7 @@
* WordPress dependencies
*/
import { external } from '@wordpress/icons';
-import { __ } from '@wordpress/i18n';
+import { _x } from '@wordpress/i18n';
import type { Action } from '@wordpress/dataviews';
/**
@@ -12,7 +12,7 @@ import type { BasePost } from '../types';
const viewPost: Action< BasePost > = {
id: 'view-post',
- label: __( 'View' ),
+ label: _x( 'View', 'verb' ),
isPrimary: true,
icon: external,
isEligible( post ) {
diff --git a/packages/editor/tsconfig.json b/packages/editor/tsconfig.json
index 8dfdf2ba7f2d5..55d79babd1dac 100644
--- a/packages/editor/tsconfig.json
+++ b/packages/editor/tsconfig.json
@@ -25,6 +25,7 @@
{ "path": "../i18n" },
{ "path": "../icons" },
{ "path": "../keycodes" },
+ { "path": "../media-utils" },
{ "path": "../notices" },
{ "path": "../plugins" },
{ "path": "../private-apis" },
diff --git a/packages/element/CHANGELOG.md b/packages/element/CHANGELOG.md
index 4c0d695bef6a3..ccfa6a6021d71 100644
--- a/packages/element/CHANGELOG.md
+++ b/packages/element/CHANGELOG.md
@@ -2,6 +2,8 @@
## Unreleased
+## 6.7.0 (2024-09-05)
+
## 6.6.0 (2024-08-21)
## 6.5.0 (2024-08-07)
diff --git a/packages/element/package.json b/packages/element/package.json
index b1ed7cef47033..d6062abe6ecf6 100644
--- a/packages/element/package.json
+++ b/packages/element/package.json
@@ -1,6 +1,6 @@
{
"name": "@wordpress/element",
- "version": "6.6.0",
+ "version": "6.7.0",
"description": "Element React module for WordPress.",
"author": "The WordPress Contributors",
"license": "GPL-2.0-or-later",
diff --git a/packages/env/CHANGELOG.md b/packages/env/CHANGELOG.md
index 836084cd437fe..b3dcf350596a0 100644
--- a/packages/env/CHANGELOG.md
+++ b/packages/env/CHANGELOG.md
@@ -2,6 +2,8 @@
## Unreleased
+## 10.7.0 (2024-09-05)
+
## 10.6.0 (2024-08-21)
## 10.5.0 (2024-08-07)
diff --git a/packages/env/package.json b/packages/env/package.json
index f7b8b2fb4a64d..7f3b15b1e1562 100644
--- a/packages/env/package.json
+++ b/packages/env/package.json
@@ -1,6 +1,6 @@
{
"name": "@wordpress/env",
- "version": "10.6.0",
+ "version": "10.7.0",
"description": "A zero-config, self contained local WordPress environment for development and testing.",
"author": "The WordPress Contributors",
"license": "GPL-2.0-or-later",
diff --git a/packages/escape-html/CHANGELOG.md b/packages/escape-html/CHANGELOG.md
index d3a505806d457..490cbdb184f5b 100644
--- a/packages/escape-html/CHANGELOG.md
+++ b/packages/escape-html/CHANGELOG.md
@@ -2,6 +2,8 @@
## Unreleased
+## 3.7.0 (2024-09-05)
+
## 3.6.0 (2024-08-21)
## 3.5.0 (2024-08-07)
diff --git a/packages/escape-html/package.json b/packages/escape-html/package.json
index 3b5572ffcfc2b..8dd1a66cf2d5e 100644
--- a/packages/escape-html/package.json
+++ b/packages/escape-html/package.json
@@ -1,6 +1,6 @@
{
"name": "@wordpress/escape-html",
- "version": "3.6.0",
+ "version": "3.7.0",
"description": "Escape HTML utils.",
"author": "The WordPress Contributors",
"license": "GPL-2.0-or-later",
diff --git a/packages/eslint-plugin/CHANGELOG.md b/packages/eslint-plugin/CHANGELOG.md
index b61a4ecb9f3bb..14d44d21acda9 100644
--- a/packages/eslint-plugin/CHANGELOG.md
+++ b/packages/eslint-plugin/CHANGELOG.md
@@ -2,6 +2,8 @@
## Unreleased
+## 21.0.0 (2024-09-05)
+
### Breaking Changes
- Add [`@wordpress/i18n-no-flanking-whitespace`](https://github.com/WordPress/gutenberg/blob/HEAD/packages/eslint-plugin/docs/rules/i18n-no-flanking-whitespace.md) to the recommended i18n ruleset ([#64710](https://github.com/WordPress/gutenberg/pull/64710).
diff --git a/packages/eslint-plugin/package.json b/packages/eslint-plugin/package.json
index 7edb4033f3251..73996275c9154 100644
--- a/packages/eslint-plugin/package.json
+++ b/packages/eslint-plugin/package.json
@@ -1,6 +1,6 @@
{
"name": "@wordpress/eslint-plugin",
- "version": "20.3.0",
+ "version": "21.0.0",
"description": "ESLint plugin for WordPress development.",
"author": "The WordPress Contributors",
"license": "GPL-2.0-or-later",
diff --git a/packages/format-library/CHANGELOG.md b/packages/format-library/CHANGELOG.md
index ff23fff3e0487..c003ac587fcdf 100644
--- a/packages/format-library/CHANGELOG.md
+++ b/packages/format-library/CHANGELOG.md
@@ -2,6 +2,8 @@
## Unreleased
+## 5.7.0 (2024-09-05)
+
## 5.6.0 (2024-08-21)
## 5.5.0 (2024-08-07)
diff --git a/packages/format-library/package.json b/packages/format-library/package.json
index 531ec71224ce7..780f513bdb037 100644
--- a/packages/format-library/package.json
+++ b/packages/format-library/package.json
@@ -1,6 +1,6 @@
{
"name": "@wordpress/format-library",
- "version": "5.6.0",
+ "version": "5.7.0",
"description": "Format library for the WordPress editor.",
"author": "The WordPress Contributors",
"license": "GPL-2.0-or-later",
diff --git a/packages/hooks/CHANGELOG.md b/packages/hooks/CHANGELOG.md
index f23ab552ca771..de9e11c38fe90 100644
--- a/packages/hooks/CHANGELOG.md
+++ b/packages/hooks/CHANGELOG.md
@@ -2,6 +2,8 @@
## Unreleased
+## 4.7.0 (2024-09-05)
+
## 4.6.0 (2024-08-21)
## 4.5.0 (2024-08-07)
diff --git a/packages/hooks/package.json b/packages/hooks/package.json
index 007404ec4a371..51074af0d239b 100644
--- a/packages/hooks/package.json
+++ b/packages/hooks/package.json
@@ -1,6 +1,6 @@
{
"name": "@wordpress/hooks",
- "version": "4.6.0",
+ "version": "4.7.0",
"description": "WordPress hooks library.",
"author": "The WordPress Contributors",
"license": "GPL-2.0-or-later",
diff --git a/packages/html-entities/CHANGELOG.md b/packages/html-entities/CHANGELOG.md
index 03e163b070bd8..6887a70b391f9 100644
--- a/packages/html-entities/CHANGELOG.md
+++ b/packages/html-entities/CHANGELOG.md
@@ -2,6 +2,8 @@
## Unreleased
+## 4.7.0 (2024-09-05)
+
## 4.6.0 (2024-08-21)
## 4.5.0 (2024-08-07)
diff --git a/packages/html-entities/package.json b/packages/html-entities/package.json
index 690bd5d676221..30e3c1728307d 100644
--- a/packages/html-entities/package.json
+++ b/packages/html-entities/package.json
@@ -1,6 +1,6 @@
{
"name": "@wordpress/html-entities",
- "version": "4.6.0",
+ "version": "4.7.0",
"description": "HTML entity utilities for WordPress.",
"author": "The WordPress Contributors",
"license": "GPL-2.0-or-later",
diff --git a/packages/i18n/CHANGELOG.md b/packages/i18n/CHANGELOG.md
index 40f11787b9779..d2bf7ad7ea7eb 100644
--- a/packages/i18n/CHANGELOG.md
+++ b/packages/i18n/CHANGELOG.md
@@ -2,6 +2,8 @@
## Unreleased
+## 5.7.0 (2024-09-05)
+
## 5.6.0 (2024-08-21)
## 5.5.0 (2024-08-07)
diff --git a/packages/i18n/package.json b/packages/i18n/package.json
index ef53c5a52900f..fb3c488c1a4de 100644
--- a/packages/i18n/package.json
+++ b/packages/i18n/package.json
@@ -1,6 +1,6 @@
{
"name": "@wordpress/i18n",
- "version": "5.6.0",
+ "version": "5.7.0",
"description": "WordPress internationalization (i18n) library.",
"author": "The WordPress Contributors",
"license": "GPL-2.0-or-later",
diff --git a/packages/icons/CHANGELOG.md b/packages/icons/CHANGELOG.md
index f5d33c3a0dea0..32bbd88181e36 100644
--- a/packages/icons/CHANGELOG.md
+++ b/packages/icons/CHANGELOG.md
@@ -2,6 +2,8 @@
## Unreleased
+## 10.7.0 (2024-09-05)
+
## 10.6.0 (2024-08-21)
## 10.5.0 (2024-08-07)
diff --git a/packages/icons/package.json b/packages/icons/package.json
index 576160fdb5273..ab23fef8eff66 100644
--- a/packages/icons/package.json
+++ b/packages/icons/package.json
@@ -1,6 +1,6 @@
{
"name": "@wordpress/icons",
- "version": "10.6.0",
+ "version": "10.7.0",
"description": "WordPress Icons package, based on dashicon.",
"author": "The WordPress Contributors",
"license": "GPL-2.0-or-later",
diff --git a/packages/icons/src/index.js b/packages/icons/src/index.js
index 9250f413a8572..11b3da927f364 100644
--- a/packages/icons/src/index.js
+++ b/packages/icons/src/index.js
@@ -255,6 +255,8 @@ export { default as tableRowBefore } from './library/table-row-before';
export { default as tableRowDelete } from './library/table-row-delete';
export { default as table } from './library/table';
export { default as tag } from './library/tag';
+export { default as thumbsDown } from './library/thumbs-down';
+export { default as thumbsUp } from './library/thumbs-up';
export { default as symbolFilled } from './library/symbol-filled';
export { default as termDescription } from './library/term-description';
export { default as footer } from './library/footer';
diff --git a/packages/icons/src/library/thumbs-down.js b/packages/icons/src/library/thumbs-down.js
new file mode 100644
index 0000000000000..94e11ee8f0638
--- /dev/null
+++ b/packages/icons/src/library/thumbs-down.js
@@ -0,0 +1,12 @@
+/**
+ * WordPress dependencies
+ */
+import { SVG, Path } from '@wordpress/primitives';
+
+const thumbsDown = (
+
+
+
+);
+
+export default thumbsDown;
diff --git a/packages/icons/src/library/thumbs-up.js b/packages/icons/src/library/thumbs-up.js
new file mode 100644
index 0000000000000..f65b6445359e2
--- /dev/null
+++ b/packages/icons/src/library/thumbs-up.js
@@ -0,0 +1,12 @@
+/**
+ * WordPress dependencies
+ */
+import { SVG, Path } from '@wordpress/primitives';
+
+const thumbsUp = (
+
+
+
+);
+
+export default thumbsUp;
diff --git a/packages/interactivity-router/CHANGELOG.md b/packages/interactivity-router/CHANGELOG.md
index 472b351682bbc..00c47f3ed074b 100644
--- a/packages/interactivity-router/CHANGELOG.md
+++ b/packages/interactivity-router/CHANGELOG.md
@@ -2,6 +2,8 @@
## Unreleased
+## 2.7.0 (2024-09-05)
+
## 2.6.0 (2024-08-21)
## 2.5.0 (2024-08-07)
diff --git a/packages/interactivity-router/package.json b/packages/interactivity-router/package.json
index 29a3f53a6109f..53b68068c528a 100644
--- a/packages/interactivity-router/package.json
+++ b/packages/interactivity-router/package.json
@@ -1,6 +1,6 @@
{
"name": "@wordpress/interactivity-router",
- "version": "2.6.0",
+ "version": "2.7.0",
"description": "Package that exposes state and actions from the `core/router` store, part of the Interactivity API.",
"author": "The WordPress Contributors",
"license": "GPL-2.0-or-later",
diff --git a/packages/interactivity/CHANGELOG.md b/packages/interactivity/CHANGELOG.md
index 1d72e85f3c34e..b410eb270358f 100644
--- a/packages/interactivity/CHANGELOG.md
+++ b/packages/interactivity/CHANGELOG.md
@@ -2,6 +2,8 @@
## Unreleased
+## 6.7.0 (2024-09-05)
+
### Enhancements
- Improve internal `deepMerge` function ([#64879](https://github.com/WordPress/gutenberg/pull/64879)).
diff --git a/packages/interactivity/package.json b/packages/interactivity/package.json
index fca8a03a7e45a..3e29d9aabeeab 100644
--- a/packages/interactivity/package.json
+++ b/packages/interactivity/package.json
@@ -1,6 +1,6 @@
{
"name": "@wordpress/interactivity",
- "version": "6.6.0",
+ "version": "6.7.0",
"description": "Package that provides a standard and simple way to handle the frontend interactivity of Gutenberg blocks.",
"author": "The WordPress Contributors",
"license": "GPL-2.0-or-later",
diff --git a/packages/interface/CHANGELOG.md b/packages/interface/CHANGELOG.md
index 60a339f019bf5..64f8c370bb6ec 100644
--- a/packages/interface/CHANGELOG.md
+++ b/packages/interface/CHANGELOG.md
@@ -2,6 +2,8 @@
## Unreleased
+## 6.7.0 (2024-09-05)
+
## 6.6.0 (2024-08-21)
## 6.5.0 (2024-08-07)
diff --git a/packages/interface/package.json b/packages/interface/package.json
index 6e017bfd34925..d15d648eaef44 100644
--- a/packages/interface/package.json
+++ b/packages/interface/package.json
@@ -1,6 +1,6 @@
{
"name": "@wordpress/interface",
- "version": "6.6.0",
+ "version": "6.7.0",
"description": "Interface module for WordPress. The package contains shared functionality across the modern JavaScript-based WordPress screens.",
"author": "The WordPress Contributors",
"license": "GPL-2.0-or-later",
diff --git a/packages/is-shallow-equal/CHANGELOG.md b/packages/is-shallow-equal/CHANGELOG.md
index 23e1a6e009848..81f2c4b164a3a 100644
--- a/packages/is-shallow-equal/CHANGELOG.md
+++ b/packages/is-shallow-equal/CHANGELOG.md
@@ -2,6 +2,8 @@
## Unreleased
+## 5.7.0 (2024-09-05)
+
## 5.6.0 (2024-08-21)
## 5.5.0 (2024-08-07)
diff --git a/packages/is-shallow-equal/package.json b/packages/is-shallow-equal/package.json
index baa1dd7b3ebea..553c3182bb566 100644
--- a/packages/is-shallow-equal/package.json
+++ b/packages/is-shallow-equal/package.json
@@ -1,6 +1,6 @@
{
"name": "@wordpress/is-shallow-equal",
- "version": "5.6.0",
+ "version": "5.7.0",
"description": "Test for shallow equality between two objects or arrays.",
"author": "The WordPress Contributors",
"license": "GPL-2.0-or-later",
diff --git a/packages/jest-console/CHANGELOG.md b/packages/jest-console/CHANGELOG.md
index ff8c00c83fc8e..7f7f80b815a85 100644
--- a/packages/jest-console/CHANGELOG.md
+++ b/packages/jest-console/CHANGELOG.md
@@ -2,6 +2,8 @@
## Unreleased
+## 8.7.0 (2024-09-05)
+
## 8.6.0 (2024-08-21)
## 8.5.0 (2024-08-07)
diff --git a/packages/jest-console/package.json b/packages/jest-console/package.json
index 4e0d804088f89..4381a0f287235 100644
--- a/packages/jest-console/package.json
+++ b/packages/jest-console/package.json
@@ -1,6 +1,6 @@
{
"name": "@wordpress/jest-console",
- "version": "8.6.0",
+ "version": "8.7.0",
"description": "Custom Jest matchers for the Console object.",
"author": "The WordPress Contributors",
"license": "GPL-2.0-or-later",
diff --git a/packages/jest-preset-default/CHANGELOG.md b/packages/jest-preset-default/CHANGELOG.md
index 04acc6e69ef60..e48d25dc1e642 100644
--- a/packages/jest-preset-default/CHANGELOG.md
+++ b/packages/jest-preset-default/CHANGELOG.md
@@ -2,6 +2,8 @@
## Unreleased
+## 12.7.0 (2024-09-05)
+
## 12.6.0 (2024-08-21)
## 12.5.0 (2024-08-07)
diff --git a/packages/jest-preset-default/package.json b/packages/jest-preset-default/package.json
index d09e89e88a63f..27638c711d4d1 100644
--- a/packages/jest-preset-default/package.json
+++ b/packages/jest-preset-default/package.json
@@ -1,6 +1,6 @@
{
"name": "@wordpress/jest-preset-default",
- "version": "12.6.0",
+ "version": "12.7.0",
"description": "Default Jest preset for WordPress development.",
"author": "The WordPress Contributors",
"license": "GPL-2.0-or-later",
diff --git a/packages/jest-puppeteer-axe/CHANGELOG.md b/packages/jest-puppeteer-axe/CHANGELOG.md
index 984fdf249f504..572b4aa137a14 100644
--- a/packages/jest-puppeteer-axe/CHANGELOG.md
+++ b/packages/jest-puppeteer-axe/CHANGELOG.md
@@ -2,6 +2,8 @@
## Unreleased
+## 7.7.0 (2024-09-05)
+
## 7.6.0 (2024-08-21)
## 7.5.0 (2024-08-07)
diff --git a/packages/jest-puppeteer-axe/package.json b/packages/jest-puppeteer-axe/package.json
index a512a018a9760..b8ccbfcd36bef 100644
--- a/packages/jest-puppeteer-axe/package.json
+++ b/packages/jest-puppeteer-axe/package.json
@@ -1,6 +1,6 @@
{
"name": "@wordpress/jest-puppeteer-axe",
- "version": "7.6.0",
+ "version": "7.7.0",
"description": "Axe API integration with Jest and Puppeteer.",
"author": "The WordPress Contributors",
"license": "GPL-2.0-or-later",
diff --git a/packages/keyboard-shortcuts/CHANGELOG.md b/packages/keyboard-shortcuts/CHANGELOG.md
index 20396b4b935ac..fe3506ea4a5f1 100644
--- a/packages/keyboard-shortcuts/CHANGELOG.md
+++ b/packages/keyboard-shortcuts/CHANGELOG.md
@@ -2,6 +2,8 @@
## Unreleased
+## 5.7.0 (2024-09-05)
+
## 5.6.0 (2024-08-21)
## 5.5.0 (2024-08-07)
diff --git a/packages/keyboard-shortcuts/package.json b/packages/keyboard-shortcuts/package.json
index 52070a0904e10..dd560424b66ff 100644
--- a/packages/keyboard-shortcuts/package.json
+++ b/packages/keyboard-shortcuts/package.json
@@ -1,6 +1,6 @@
{
"name": "@wordpress/keyboard-shortcuts",
- "version": "5.6.0",
+ "version": "5.7.0",
"description": "Handling keyboard shortcuts.",
"author": "The WordPress Contributors",
"license": "GPL-2.0-or-later",
diff --git a/packages/keycodes/CHANGELOG.md b/packages/keycodes/CHANGELOG.md
index 745412efcb990..51050728f2f5a 100644
--- a/packages/keycodes/CHANGELOG.md
+++ b/packages/keycodes/CHANGELOG.md
@@ -2,6 +2,8 @@
## Unreleased
+## 4.7.0 (2024-09-05)
+
## 4.6.0 (2024-08-21)
## 4.5.0 (2024-08-07)
diff --git a/packages/keycodes/package.json b/packages/keycodes/package.json
index 4206b93430cfa..5d8ec0545d7e3 100644
--- a/packages/keycodes/package.json
+++ b/packages/keycodes/package.json
@@ -1,6 +1,6 @@
{
"name": "@wordpress/keycodes",
- "version": "4.6.0",
+ "version": "4.7.0",
"description": "Keycodes utilities for WordPress. Used to check for keyboard events across browsers/operating systems.",
"author": "The WordPress Contributors",
"license": "GPL-2.0-or-later",
diff --git a/packages/lazy-import/CHANGELOG.md b/packages/lazy-import/CHANGELOG.md
index 944cb6207fb96..daea6da3404d3 100644
--- a/packages/lazy-import/CHANGELOG.md
+++ b/packages/lazy-import/CHANGELOG.md
@@ -2,6 +2,8 @@
## Unreleased
+## 2.7.0 (2024-09-05)
+
## 2.6.0 (2024-08-21)
## 2.5.0 (2024-08-07)
diff --git a/packages/lazy-import/package.json b/packages/lazy-import/package.json
index 54ea606faefac..62aab79635e9c 100644
--- a/packages/lazy-import/package.json
+++ b/packages/lazy-import/package.json
@@ -1,6 +1,6 @@
{
"name": "@wordpress/lazy-import",
- "version": "2.6.0",
+ "version": "2.7.0",
"description": "Lazily import a module, installing it automatically if missing.",
"author": "The WordPress Contributors",
"license": "GPL-2.0-or-later",
diff --git a/packages/list-reusable-blocks/CHANGELOG.md b/packages/list-reusable-blocks/CHANGELOG.md
index 1338124bf1a7c..9f62523fd94e1 100644
--- a/packages/list-reusable-blocks/CHANGELOG.md
+++ b/packages/list-reusable-blocks/CHANGELOG.md
@@ -2,6 +2,8 @@
## Unreleased
+## 5.7.0 (2024-09-05)
+
## 5.6.0 (2024-08-21)
## 5.5.0 (2024-08-07)
diff --git a/packages/list-reusable-blocks/package.json b/packages/list-reusable-blocks/package.json
index 8e5fb404607c6..839532327faa2 100644
--- a/packages/list-reusable-blocks/package.json
+++ b/packages/list-reusable-blocks/package.json
@@ -1,6 +1,6 @@
{
"name": "@wordpress/list-reusable-blocks",
- "version": "5.6.0",
+ "version": "5.7.0",
"description": "Adding Export/Import support to the reusable blocks listing.",
"author": "The WordPress Contributors",
"license": "GPL-2.0-or-later",
diff --git a/packages/media-utils/CHANGELOG.md b/packages/media-utils/CHANGELOG.md
index c155b906ab6dc..26282b6b2bda2 100644
--- a/packages/media-utils/CHANGELOG.md
+++ b/packages/media-utils/CHANGELOG.md
@@ -2,6 +2,12 @@
## Unreleased
+### New Features
+
+- Rewrite in TypeScript, exporting all the individual utility functions.
+
+## 5.7.0 (2024-09-05)
+
## 5.6.0 (2024-08-21)
## 5.5.0 (2024-08-07)
diff --git a/packages/media-utils/README.md b/packages/media-utils/README.md
index 6c2384061a5f6..1adc15186078a 100644
--- a/packages/media-utils/README.md
+++ b/packages/media-utils/README.md
@@ -13,6 +13,75 @@ npm install @wordpress/media-utils --save
_This package assumes that your code will run in an **ES2015+** environment. If you're using an environment that has limited or no support for such language features and APIs, you should include [the polyfill shipped in `@wordpress/babel-preset-default`](https://github.com/WordPress/gutenberg/tree/HEAD/packages/babel-preset-default#polyfill) in your code._
+## API
+
+
+
+### Attachment
+
+Undocumented declaration.
+
+### MediaUpload
+
+Undocumented declaration.
+
+### RestAttachment
+
+Undocumented declaration.
+
+### transformAttachment
+
+Transforms an attachment object from the REST API shape into the shape expected by the block editor and other consumers.
+
+_Parameters_
+
+- _attachment_ `RestAttachment`: REST API attachment object.
+
+### uploadMedia
+
+Upload a media file when the file upload button is activated or when adding a file to the editor via drag & drop.
+
+_Parameters_
+
+- _$0_ `UploadMediaArgs`: Parameters object passed to the function.
+- _$0.allowedTypes_ `UploadMediaArgs[ 'allowedTypes' ]`: Array with the types of media that can be uploaded, if unset all types are allowed.
+- _$0.additionalData_ `UploadMediaArgs[ 'additionalData' ]`: Additional data to include in the request.
+- _$0.filesList_ `UploadMediaArgs[ 'filesList' ]`: List of files.
+- _$0.maxUploadFileSize_ `UploadMediaArgs[ 'maxUploadFileSize' ]`: Maximum upload size in bytes allowed for the site.
+- _$0.onError_ `UploadMediaArgs[ 'onError' ]`: Function called when an error happens.
+- _$0.onFileChange_ `UploadMediaArgs[ 'onFileChange' ]`: Function called each time a file or a temporary representation of the file is available.
+- _$0.wpAllowedMimeTypes_ `UploadMediaArgs[ 'wpAllowedMimeTypes' ]`: List of allowed mime types and file extensions.
+- _$0.signal_ `UploadMediaArgs[ 'signal' ]`: Abort signal.
+
+### validateFileSize
+
+Verifies whether the file is within the file upload size limits for the site.
+
+_Parameters_
+
+- _file_ `File`: File object.
+- _maxUploadFileSize_ `number`: Maximum upload size in bytes allowed for the site.
+
+### validateMimeType
+
+Verifies if the caller (e.g. a block) supports this mime type.
+
+_Parameters_
+
+- _file_ `File`: File object.
+- _allowedTypes_ `string[]`: List of allowed mime types.
+
+### validateMimeTypeForUser
+
+Verifies if the user is allowed to upload this mime type.
+
+_Parameters_
+
+- _file_ `File`: File object.
+- _wpAllowedMimeTypes_ `Record< string, string > | null`: List of allowed mime types and file extensions.
+
+
+
## Usage
### uploadMedia
@@ -43,7 +112,7 @@ Beware that first onFileChange is called with temporary blob URLs and then with
### MediaUpload
Media upload component provides a UI button that allows users to open the WordPress media library. It is normally used in conjunction with the filter `editor.MediaUpload`.
-The component follows the interface specified in [https://github.com/WordPress/gutenberg/blob/HEAD/packages/block-editor/src/components/media-upload/README.md](https://github.com/WordPress/gutenberg/blob/HEAD/packages/block-editor/src/components/media-upload/README.md), and more details regarding its usage can be checked there.
+The component follows the interface specified in , and more details regarding its usage can be checked there.
## Contributing to this package
diff --git a/packages/media-utils/package.json b/packages/media-utils/package.json
index 0cbf38592a1fd..1cfe019e89d0a 100644
--- a/packages/media-utils/package.json
+++ b/packages/media-utils/package.json
@@ -1,6 +1,6 @@
{
"name": "@wordpress/media-utils",
- "version": "5.6.0",
+ "version": "5.7.0",
"description": "WordPress Media Upload Utils.",
"author": "The WordPress Contributors",
"license": "GPL-2.0-or-later",
@@ -14,7 +14,7 @@
"repository": {
"type": "git",
"url": "https://github.com/WordPress/gutenberg.git",
- "directory": "packages/url"
+ "directory": "packages/media-utils"
},
"bugs": {
"url": "https://github.com/WordPress/gutenberg/issues"
@@ -25,6 +25,7 @@
},
"main": "build/index.js",
"module": "build-module/index.js",
+ "types": "build-types",
"dependencies": {
"@babel/runtime": "^7.16.0",
"@wordpress/api-fetch": "file:../api-fetch",
diff --git a/packages/media-utils/src/index.js b/packages/media-utils/src/index.js
deleted file mode 100644
index 590a7f4c9d188..0000000000000
--- a/packages/media-utils/src/index.js
+++ /dev/null
@@ -1,2 +0,0 @@
-export * from './components';
-export * from './utils';
diff --git a/packages/media-utils/src/index.ts b/packages/media-utils/src/index.ts
new file mode 100644
index 0000000000000..c37814afe7c48
--- /dev/null
+++ b/packages/media-utils/src/index.ts
@@ -0,0 +1,9 @@
+export * from './components';
+
+export { uploadMedia } from './utils/upload-media';
+export { transformAttachment } from './utils/transform-attachment';
+export { validateFileSize } from './utils/validate-file-size';
+export { validateMimeType } from './utils/validate-mime-type';
+export { validateMimeTypeForUser } from './utils/validate-mime-type-for-user';
+
+export type { Attachment, RestAttachment } from './utils/types';
diff --git a/packages/media-utils/src/utils/flatten-form-data.ts b/packages/media-utils/src/utils/flatten-form-data.ts
new file mode 100644
index 0000000000000..594f172ef7eb2
--- /dev/null
+++ b/packages/media-utils/src/utils/flatten-form-data.ts
@@ -0,0 +1,33 @@
+/**
+ * Determines whether the passed argument appears to be a plain object.
+ *
+ * @param data The object to inspect.
+ */
+function isPlainObject( data: unknown ): data is Record< string, unknown > {
+ return (
+ data !== null &&
+ typeof data === 'object' &&
+ Object.getPrototypeOf( data ) === Object.prototype
+ );
+}
+
+/**
+ * Recursively flatten data passed to form data, to allow using multi-level objects.
+ *
+ * @param {FormData} formData Form data object.
+ * @param {string} key Key to amend to form data object
+ * @param {string|Object} data Data to be amended to form data.
+ */
+export function flattenFormData(
+ formData: FormData,
+ key: string,
+ data: string | undefined | Record< string, string >
+) {
+ if ( isPlainObject( data ) ) {
+ for ( const [ name, value ] of Object.entries( data ) ) {
+ flattenFormData( formData, `${ key }[${ name }]`, value );
+ }
+ } else if ( data !== undefined ) {
+ formData.append( key, String( data ) );
+ }
+}
diff --git a/packages/media-utils/src/utils/get-mime-types-array.ts b/packages/media-utils/src/utils/get-mime-types-array.ts
new file mode 100644
index 0000000000000..d4940d36cd6ae
--- /dev/null
+++ b/packages/media-utils/src/utils/get-mime-types-array.ts
@@ -0,0 +1,29 @@
+/**
+ * Browsers may use unexpected mime types, and they differ from browser to browser.
+ * This function computes a flexible array of mime types from the mime type structured provided by the server.
+ * Converts { jpg|jpeg|jpe: "image/jpeg" } into [ "image/jpeg", "image/jpg", "image/jpeg", "image/jpe" ]
+ *
+ * @param {?Object} wpMimeTypesObject Mime type object received from the server.
+ * Extensions are keys separated by '|' and values are mime types associated with an extension.
+ *
+ * @return An array of mime types or null
+ */
+export function getMimeTypesArray(
+ wpMimeTypesObject?: Record< string, string > | null
+) {
+ if ( ! wpMimeTypesObject ) {
+ return null;
+ }
+ return Object.entries( wpMimeTypesObject ).flatMap(
+ ( [ extensionsString, mime ] ) => {
+ const [ type ] = mime.split( '/' );
+ const extensions = extensionsString.split( '|' );
+ return [
+ mime,
+ ...extensions.map(
+ ( extension ) => `${ type }/${ extension }`
+ ),
+ ];
+ }
+ );
+}
diff --git a/packages/media-utils/src/utils/index.js b/packages/media-utils/src/utils/index.js
deleted file mode 100644
index 509b62f1e8864..0000000000000
--- a/packages/media-utils/src/utils/index.js
+++ /dev/null
@@ -1 +0,0 @@
-export { uploadMedia } from './upload-media';
diff --git a/packages/media-utils/src/utils/test/flatten-form-data.ts b/packages/media-utils/src/utils/test/flatten-form-data.ts
new file mode 100644
index 0000000000000..458dfd26c8f6e
--- /dev/null
+++ b/packages/media-utils/src/utils/test/flatten-form-data.ts
@@ -0,0 +1,49 @@
+/**
+ * Internal dependencies
+ */
+import { flattenFormData } from '../flatten-form-data';
+
+describe( 'flattenFormData', () => {
+ it( 'should flatten nested data structure', () => {
+ const data = new FormData();
+
+ class RichTextData {
+ toString() {
+ return 'i am rich text';
+ }
+ }
+
+ const additionalData = {
+ foo: null,
+ bar: 1234,
+ meta: {
+ nested: 'foo',
+ dothis: true,
+ dothat: false,
+ supermeta: {
+ nested: 'baz',
+ },
+ },
+ customClass: new RichTextData(),
+ };
+
+ for ( const [ key, value ] of Object.entries( additionalData ) ) {
+ flattenFormData(
+ data,
+ key,
+ value as Parameters< typeof flattenFormData >[ 2 ]
+ );
+ }
+
+ const actual = Object.fromEntries( data.entries() );
+ expect( actual ).toStrictEqual( {
+ bar: '1234',
+ foo: 'null',
+ 'meta[dothat]': 'false',
+ 'meta[dothis]': 'true',
+ 'meta[nested]': 'foo',
+ 'meta[supermeta][nested]': 'baz',
+ customClass: 'i am rich text',
+ } );
+ } );
+} );
diff --git a/packages/media-utils/src/utils/test/get-mime-types-array.ts b/packages/media-utils/src/utils/test/get-mime-types-array.ts
new file mode 100644
index 0000000000000..156955373bd0d
--- /dev/null
+++ b/packages/media-utils/src/utils/test/get-mime-types-array.ts
@@ -0,0 +1,47 @@
+/**
+ * Internal dependencies
+ */
+import { getMimeTypesArray } from '../get-mime-types-array';
+
+describe( 'getMimeTypesArray', () => {
+ it( 'should return null if it is "falsy" e.g: undefined or null', () => {
+ expect( getMimeTypesArray( null ) ).toEqual( null );
+ expect( getMimeTypesArray( undefined ) ).toEqual( null );
+ } );
+
+ it( 'should return an empty array if an empty object is passed', () => {
+ expect( getMimeTypesArray( {} ) ).toEqual( [] );
+ } );
+
+ it( 'should return the type plus a new mime type with type and subtype with the extension if a type is passed', () => {
+ expect( getMimeTypesArray( { ext: 'chicken' } ) ).toEqual( [
+ 'chicken',
+ 'chicken/ext',
+ ] );
+ } );
+
+ it( 'should return the mime type passed and a new mime type with type and the extension as subtype', () => {
+ expect( getMimeTypesArray( { ext: 'chicken/ribs' } ) ).toEqual( [
+ 'chicken/ribs',
+ 'chicken/ext',
+ ] );
+ } );
+
+ it( 'should return the mime type passed and an additional mime type per extension supported', () => {
+ expect( getMimeTypesArray( { 'jpg|jpeg|jpe': 'image/jpeg' } ) ).toEqual(
+ [ 'image/jpeg', 'image/jpg', 'image/jpeg', 'image/jpe' ]
+ );
+ } );
+
+ it( 'should handle multiple mime types', () => {
+ expect(
+ getMimeTypesArray( { 'ext|aaa': 'chicken/ribs', aaa: 'bbb' } )
+ ).toEqual( [
+ 'chicken/ribs',
+ 'chicken/ext',
+ 'chicken/aaa',
+ 'bbb',
+ 'bbb/aaa',
+ ] );
+ } );
+} );
diff --git a/packages/media-utils/src/utils/test/upload-error.ts b/packages/media-utils/src/utils/test/upload-error.ts
new file mode 100644
index 0000000000000..4d5f025ed8cf3
--- /dev/null
+++ b/packages/media-utils/src/utils/test/upload-error.ts
@@ -0,0 +1,24 @@
+/**
+ * Internal dependencies
+ */
+import { UploadError } from '../upload-error';
+
+describe( 'UploadError', () => {
+ it( 'holds error code and file name', () => {
+ const file = new File( [], 'example.jpg', {
+ lastModified: 1234567891,
+ type: 'image/jpeg',
+ } );
+
+ const error = new UploadError( {
+ code: 'some_error',
+ message: 'An error occurred',
+ file,
+ } );
+
+ expect( error ).toStrictEqual( expect.any( Error ) );
+ expect( error.code ).toBe( 'some_error' );
+ expect( error.message ).toBe( 'An error occurred' );
+ expect( error.file ).toBe( file );
+ } );
+} );
diff --git a/packages/media-utils/src/utils/test/upload-media.test.js b/packages/media-utils/src/utils/test/upload-media.ts
similarity index 58%
rename from packages/media-utils/src/utils/test/upload-media.test.js
rename to packages/media-utils/src/utils/test/upload-media.ts
index fa9adc9f40881..b5075255ad4c8 100644
--- a/packages/media-utils/src/utils/test/upload-media.test.js
+++ b/packages/media-utils/src/utils/test/upload-media.ts
@@ -1,19 +1,18 @@
-/**
- * WordPress dependencies
- */
-import { createBlobURL } from '@wordpress/blob';
-import apiFetch from '@wordpress/api-fetch';
-
/**
* Internal dependencies
*/
-import { uploadMedia, getMimeTypesArray } from '../upload-media';
+import { uploadMedia } from '../upload-media';
+import { UploadError } from '../upload-error';
+import { uploadToServer } from '../upload-to-server';
+
+jest.mock( '../upload-to-server', () => ( {
+ uploadToServer: jest.fn(),
+} ) );
jest.mock( '@wordpress/blob', () => ( {
createBlobURL: jest.fn(),
revokeBlobURL: jest.fn(),
} ) );
-jest.mock( '@wordpress/api-fetch', () => jest.fn() );
const xmlFile = new window.File( [ 'fake_file' ], 'test.xml', {
type: 'text/xml',
@@ -23,6 +22,10 @@ const imageFile = new window.File( [ 'fake_file' ], 'test.jpeg', {
} );
describe( 'uploadMedia', () => {
+ afterEach( () => {
+ jest.clearAllMocks();
+ } );
+
it( 'should do nothing on no files', async () => {
const onError = jest.fn();
const onFileChange = jest.fn();
@@ -33,7 +36,7 @@ describe( 'uploadMedia', () => {
} );
expect( onError ).not.toHaveBeenCalled();
- expect( onFileChange ).not.toHaveBeenCalled();
+ expect( uploadToServer ).not.toHaveBeenCalled();
} );
it( 'should error if allowedTypes contains a partial mime type and the validation fails', async () => {
@@ -47,11 +50,14 @@ describe( 'uploadMedia', () => {
} );
expect( onError ).toHaveBeenCalledWith(
- expect.objectContaining( {
+ new UploadError( {
code: 'MIME_TYPE_NOT_SUPPORTED',
+ message:
+ 'test.xml: Sorry, this file type is not supported here.',
+ file: xmlFile,
} )
);
- expect( onFileChange ).not.toHaveBeenCalled();
+ expect( uploadToServer ).not.toHaveBeenCalled();
} );
it( 'should error if allowedTypes contains a complete mime type and the validation fails', async () => {
@@ -65,17 +71,17 @@ describe( 'uploadMedia', () => {
} );
expect( onError ).toHaveBeenCalledWith(
- expect.objectContaining( {
+ new UploadError( {
code: 'MIME_TYPE_NOT_SUPPORTED',
+ message:
+ 'test.jpeg: Sorry, this file type is not supported here.',
+ file: xmlFile,
} )
);
- expect( onFileChange ).not.toHaveBeenCalled();
+ expect( uploadToServer ).not.toHaveBeenCalled();
} );
it( 'should work if allowedTypes contains a complete mime type and the validation succeeds', async () => {
- createBlobURL.mockReturnValue( 'blob:fake_blob' );
- apiFetch.mockResolvedValue( { title: { raw: 'Test' } } );
-
const onError = jest.fn();
const onFileChange = jest.fn();
await uploadMedia( {
@@ -83,10 +89,11 @@ describe( 'uploadMedia', () => {
filesList: [ imageFile ],
onError,
onFileChange,
+ wpAllowedMimeTypes: { jpeg: 'image/jpeg' },
} );
expect( onError ).not.toHaveBeenCalled();
- expect( onFileChange ).toHaveBeenCalledTimes( 2 );
+ expect( uploadToServer ).toHaveBeenCalled();
} );
it( 'should error if allowedTypes contains multiple types and the validation fails', async () => {
@@ -100,17 +107,17 @@ describe( 'uploadMedia', () => {
} );
expect( onError ).toHaveBeenCalledWith(
- expect.objectContaining( {
+ new UploadError( {
code: 'MIME_TYPE_NOT_SUPPORTED',
+ message:
+ 'test.xml: Sorry, this file type is not supported here.',
+ file: xmlFile,
} )
);
- expect( onFileChange ).not.toHaveBeenCalled();
+ expect( uploadToServer ).not.toHaveBeenCalled();
} );
it( 'should work if allowedTypes contains multiple types and the validation succeeds', async () => {
- createBlobURL.mockReturnValue( 'blob:fake_blob' );
- apiFetch.mockResolvedValue( { title: { raw: 'Test' } } );
-
const onError = jest.fn();
const onFileChange = jest.fn();
await uploadMedia( {
@@ -118,16 +125,14 @@ describe( 'uploadMedia', () => {
filesList: [ imageFile ],
onError,
onFileChange,
+ wpAllowedMimeTypes: { jpeg: 'image/jpeg', mp4: 'video/mp4' },
} );
expect( onError ).not.toHaveBeenCalled();
- expect( onFileChange ).toHaveBeenCalledTimes( 2 );
+ expect( uploadToServer ).toHaveBeenCalled();
} );
it( 'should only fail the invalid file and still allow others to succeed when uploading multiple files', async () => {
- createBlobURL.mockReturnValue( 'blob:fake_blob' );
- apiFetch.mockResolvedValue( { title: { raw: 'Test' } } );
-
const onError = jest.fn();
const onFileChange = jest.fn();
await uploadMedia( {
@@ -135,15 +140,18 @@ describe( 'uploadMedia', () => {
filesList: [ imageFile, xmlFile ],
onError,
onFileChange,
+ wpAllowedMimeTypes: { jpeg: 'image/jpeg' },
} );
expect( onError ).toHaveBeenCalledWith(
- expect.objectContaining( {
+ new UploadError( {
code: 'MIME_TYPE_NOT_SUPPORTED',
+ message:
+ 'test.xml: Sorry, you are not allowed to upload this file type.',
file: xmlFile,
} )
);
- expect( onFileChange ).toHaveBeenCalledTimes( 2 );
+ expect( uploadToServer ).toHaveBeenCalledTimes( 1 );
} );
it( 'should error if the file size is greater than the maximum', async () => {
@@ -155,19 +163,22 @@ describe( 'uploadMedia', () => {
maxUploadFileSize: 1,
onError,
onFileChange,
+ wpAllowedMimeTypes: { jpeg: 'image/jpeg' },
} );
expect( onError ).toHaveBeenCalledWith(
- expect.objectContaining( {
+ new UploadError( {
code: 'SIZE_ABOVE_LIMIT',
+ message:
+ 'test.jpeg: This file exceeds the maximum upload size for this site.',
+ file: imageFile,
} )
);
- expect( onFileChange ).not.toHaveBeenCalled();
+ expect( uploadToServer ).not.toHaveBeenCalled();
} );
it( 'should call error handler with the correct error object if file type is not allowed for user', async () => {
const onError = jest.fn();
- const onFileChange = jest.fn();
await uploadMedia( {
allowedTypes: [ 'image' ],
filesList: [ imageFile ],
@@ -176,53 +187,13 @@ describe( 'uploadMedia', () => {
} );
expect( onError ).toHaveBeenCalledWith(
- expect.objectContaining( {
+ new UploadError( {
code: 'MIME_TYPE_NOT_ALLOWED_FOR_USER',
+ message:
+ 'test.jpeg: Sorry, you are not allowed to upload this file type.',
+ file: imageFile,
} )
);
- expect( onFileChange ).not.toHaveBeenCalled();
- } );
-} );
-
-describe( 'getMimeTypesArray', () => {
- it( 'should return the parameter passed if it is "falsy" e.g: undefined or null', () => {
- expect( getMimeTypesArray( null ) ).toEqual( null );
- expect( getMimeTypesArray( undefined ) ).toEqual( undefined );
- } );
-
- it( 'should return an empty array if an empty object is passed', () => {
- expect( getMimeTypesArray( {} ) ).toEqual( [] );
- } );
-
- it( 'should return the type plus a new mime type with type and subtype with the extension if a type is passed', () => {
- expect( getMimeTypesArray( { ext: 'chicken' } ) ).toEqual( [
- 'chicken',
- 'chicken/ext',
- ] );
- } );
-
- it( 'should return the mime type passed and a new mime type with type and the extension as subtype', () => {
- expect( getMimeTypesArray( { ext: 'chicken/ribs' } ) ).toEqual( [
- 'chicken/ribs',
- 'chicken/ext',
- ] );
- } );
-
- it( 'should return the mime type passed and an additional mime type per extension supported', () => {
- expect( getMimeTypesArray( { 'jpg|jpeg|jpe': 'image/jpeg' } ) ).toEqual(
- [ 'image/jpeg', 'image/jpg', 'image/jpeg', 'image/jpe' ]
- );
- } );
-
- it( 'should handle multiple mime types', () => {
- expect(
- getMimeTypesArray( { 'ext|aaa': 'chicken/ribs', aaa: 'bbb' } )
- ).toEqual( [
- 'chicken/ribs',
- 'chicken/ext',
- 'chicken/aaa',
- 'bbb',
- 'bbb/aaa',
- ] );
+ expect( uploadToServer ).not.toHaveBeenCalled();
} );
} );
diff --git a/packages/media-utils/src/utils/test/validate-file-size.ts b/packages/media-utils/src/utils/test/validate-file-size.ts
new file mode 100644
index 0000000000000..31d6af0e7e4a5
--- /dev/null
+++ b/packages/media-utils/src/utils/test/validate-file-size.ts
@@ -0,0 +1,70 @@
+/**
+ * Internal dependencies
+ */
+import { validateFileSize } from '../validate-file-size';
+import { UploadError } from '../upload-error';
+
+const imageFile = new window.File( [ 'fake_file' ], 'test.jpeg', {
+ type: 'image/jpeg',
+} );
+
+const emptyFile = new window.File( [], 'test.jpeg', {
+ type: 'image/jpeg',
+} );
+
+describe( 'validateFileSize', () => {
+ afterEach( () => {
+ jest.clearAllMocks();
+ } );
+
+ it( 'should error if the file is empty', () => {
+ expect( () => {
+ validateFileSize( emptyFile );
+ } ).toThrow(
+ new UploadError( {
+ code: 'EMPTY_FILE',
+ message: 'test.jpeg: This file is empty.',
+ file: imageFile,
+ } )
+ );
+ } );
+
+ it( 'should error if the file is is greater than the maximum', () => {
+ expect( () => {
+ validateFileSize( imageFile, 2 );
+ } ).toThrow(
+ new UploadError( {
+ code: 'SIZE_ABOVE_LIMIT',
+ message:
+ 'test.jpeg: This file exceeds the maximum upload size for this site.',
+ file: imageFile,
+ } )
+ );
+ } );
+
+ it( 'should not error if the file is below the limit', () => {
+ expect( () => {
+ validateFileSize( imageFile, 100 );
+ } ).not.toThrow(
+ new UploadError( {
+ code: 'SIZE_ABOVE_LIMIT',
+ message:
+ 'test.jpeg: This file exceeds the maximum upload size for this site.',
+ file: imageFile,
+ } )
+ );
+ } );
+
+ it( 'should not error if there is no limit', () => {
+ expect( () => {
+ validateFileSize( imageFile );
+ } ).not.toThrow(
+ new UploadError( {
+ code: 'SIZE_ABOVE_LIMIT',
+ message:
+ 'test.jpeg: This file exceeds the maximum upload size for this site.',
+ file: imageFile,
+ } )
+ );
+ } );
+} );
diff --git a/packages/media-utils/src/utils/test/validate-mime-type-for-user.ts b/packages/media-utils/src/utils/test/validate-mime-type-for-user.ts
new file mode 100644
index 0000000000000..d256656686214
--- /dev/null
+++ b/packages/media-utils/src/utils/test/validate-mime-type-for-user.ts
@@ -0,0 +1,37 @@
+/**
+ * Internal dependencies
+ */
+import { validateMimeTypeForUser } from '../validate-mime-type-for-user';
+import { UploadError } from '../upload-error';
+
+const imageFile = new window.File( [ 'fake_file' ], 'test.jpeg', {
+ type: 'image/jpeg',
+} );
+
+describe( 'validateMimeTypeForUser', () => {
+ afterEach( () => {
+ jest.clearAllMocks();
+ } );
+
+ it( 'should not error if wpAllowedMimeTypes is null or missing', async () => {
+ expect( () => {
+ validateMimeTypeForUser( imageFile );
+ } ).not.toThrow();
+ expect( () => {
+ validateMimeTypeForUser( imageFile, null );
+ } ).not.toThrow();
+ } );
+
+ it( 'should error if file type is not allowed for user', async () => {
+ expect( () => {
+ validateMimeTypeForUser( imageFile, { aac: 'audio/aac' } );
+ } ).toThrow(
+ new UploadError( {
+ code: 'MIME_TYPE_NOT_ALLOWED_FOR_USER',
+ message:
+ 'test.jpeg: Sorry, you are not allowed to upload this file type.',
+ file: imageFile,
+ } )
+ );
+ } );
+} );
diff --git a/packages/media-utils/src/utils/test/validate-mime-type.ts b/packages/media-utils/src/utils/test/validate-mime-type.ts
new file mode 100644
index 0000000000000..a83cdcefe5f99
--- /dev/null
+++ b/packages/media-utils/src/utils/test/validate-mime-type.ts
@@ -0,0 +1,57 @@
+/**
+ * Internal dependencies
+ */
+import { validateMimeType } from '../validate-mime-type';
+import { UploadError } from '../upload-error';
+
+const xmlFile = new window.File( [ 'fake_file' ], 'test.xml', {
+ type: 'text/xml',
+} );
+const imageFile = new window.File( [ 'fake_file' ], 'test.jpeg', {
+ type: 'image/jpeg',
+} );
+
+describe( 'validateMimeType', () => {
+ afterEach( () => {
+ jest.clearAllMocks();
+ } );
+
+ it( 'should error if allowedTypes contains a partial mime type and the validation fails', async () => {
+ expect( () => {
+ validateMimeType( xmlFile, [ 'image' ] );
+ } ).toThrow(
+ new UploadError( {
+ code: 'MIME_TYPE_NOT_SUPPORTED',
+ message:
+ 'test.xml: Sorry, this file type is not supported here.',
+ file: xmlFile,
+ } )
+ );
+ } );
+
+ it( 'should error if allowedTypes contains a complete mime type and the validation fails', async () => {
+ expect( () => {
+ validateMimeType( imageFile, [ 'image/gif' ] );
+ } ).toThrow(
+ new UploadError( {
+ code: 'MIME_TYPE_NOT_SUPPORTED',
+ message:
+ 'test.jpeg: Sorry, this file type is not supported here.',
+ file: xmlFile,
+ } )
+ );
+ } );
+
+ it( 'should error if allowedTypes contains multiple types and the validation fails', async () => {
+ expect( () => {
+ validateMimeType( xmlFile, [ 'video', 'image' ] );
+ } ).toThrow(
+ new UploadError( {
+ code: 'MIME_TYPE_NOT_SUPPORTED',
+ message:
+ 'test.xml: Sorry, this file type is not supported here.',
+ file: xmlFile,
+ } )
+ );
+ } );
+} );
diff --git a/packages/media-utils/src/utils/transform-attachment.ts b/packages/media-utils/src/utils/transform-attachment.ts
new file mode 100644
index 0000000000000..a97287872f24a
--- /dev/null
+++ b/packages/media-utils/src/utils/transform-attachment.ts
@@ -0,0 +1,24 @@
+/**
+ * Internal dependencies
+ */
+import type { Attachment, RestAttachment } from './types';
+
+/**
+ * Transforms an attachment object from the REST API shape into the shape expected by the block editor and other consumers.
+ *
+ * @param attachment REST API attachment object.
+ */
+export function transformAttachment( attachment: RestAttachment ): Attachment {
+ // eslint-disable-next-line camelcase
+ const { alt_text, source_url, ...savedMediaProps } = attachment;
+ return {
+ ...savedMediaProps,
+ alt: attachment.alt_text,
+ caption: attachment.caption?.raw ?? '',
+ title: attachment.title.raw,
+ url: attachment.source_url,
+ poster:
+ attachment._embedded?.[ 'wp:featuredmedia' ]?.[ 0 ]?.source_url ||
+ undefined,
+ };
+}
diff --git a/packages/media-utils/src/utils/types.ts b/packages/media-utils/src/utils/types.ts
new file mode 100644
index 0000000000000..e05536400a760
--- /dev/null
+++ b/packages/media-utils/src/utils/types.ts
@@ -0,0 +1,207 @@
+/**
+ * A media attachment object in a REST API context.
+ *
+ * Simplified version of what's defined in the wp-types package.
+ *
+ * @see https://www.npmjs.com/package/wp-types
+ */
+interface WP_REST_API_Attachment {
+ /**
+ * Unique identifier for the attachment.
+ */
+ id: number;
+ /**
+ * The ID of the featured media for the post.
+ */
+ featured_media: number;
+ /**
+ * URL to the attachment.
+ */
+ link: string;
+ /**
+ * The date the attachment was published, in the site's timezone.
+ */
+ date: string;
+ /**
+ * The date the attachment was published, as GMT.
+ */
+ date_gmt: string;
+ /**
+ * The date the attachment was last modified, in the site's timezone.
+ */
+ modified: string;
+ /**
+ * The date the attachment was last modified, as GMT.
+ */
+ modified_gmt: string;
+ /**
+ * An alphanumeric identifier for the attachment unique to its type.
+ */
+ slug: string;
+ /**
+ * A named status for the attachment.
+ */
+ status: string;
+ /**
+ * Type of Post for the attachment.
+ */
+ type: 'attachment';
+ /**
+ * Alternative text to display when attachment is not displayed.
+ */
+ alt_text: string;
+ /**
+ * The attachment caption.
+ */
+ caption: {
+ /**
+ * Caption for the attachment, as it exists in the database. Only present when using the 'edit' context.
+ */
+ raw?: string;
+ /**
+ * HTML caption for the attachment, transformed for display.
+ */
+ rendered: string;
+ };
+ /**
+ * The attachment description.
+ */
+ description: {
+ /**
+ * Description for the attachment, as it exists in the database. Only present when using the 'edit' context.
+ */
+ raw?: string;
+ /**
+ * HTML description for the attachment, transformed for display.
+ */
+ rendered: string;
+ };
+ /**
+ * Attachment type.
+ */
+ media_type: 'image' | 'file';
+ /**
+ * The attachment MIME type.
+ */
+ mime_type: string;
+ /**
+ * Details about the media file, specific to its type.
+ */
+ media_details: {
+ [ k: string ]: unknown;
+ };
+ /**
+ * The ID for the associated post of the attachment.
+ */
+ post: number | null;
+ /**
+ * URL to the original attachment file.
+ */
+ source_url: string;
+ /**
+ * List of the missing image sizes of the attachment. Only present when using the 'edit' context.
+ */
+ missing_image_sizes?: string[];
+ /**
+ * Permalink template for the attachment. Only present when using the 'edit' context and the post type is public.
+ */
+ permalink_template?: string;
+ /**
+ * Slug automatically generated from the attachment title. Only present when using the 'edit' context and the post type is public.
+ */
+ generated_slug?: string;
+ /**
+ * An array of the class names for the post container element.
+ */
+ class_list: string[];
+ /**
+ * The title for the attachment.
+ */
+ title: {
+ /**
+ * Title for the attachment, as it exists in the database. Only present when using the 'edit' context.
+ */
+ raw?: string;
+ /**
+ * HTML title for the attachment, transformed for display.
+ */
+ rendered: string;
+ };
+ /**
+ * The ID for the author of the attachment.
+ */
+ author: number;
+ /**
+ * Whether or not comments are open on the attachment.
+ */
+ comment_status: string;
+ /**
+ * Whether or not the attachment can be pinged.
+ */
+ ping_status: string;
+ /**
+ * Meta fields.
+ */
+ meta:
+ | []
+ | {
+ [ k: string ]: unknown;
+ };
+ /**
+ * The theme file to use to display the attachment.
+ */
+ template: string;
+ _links: {
+ [ k: string ]: {
+ href: string;
+ embeddable?: boolean;
+ [ k: string ]: unknown;
+ }[];
+ };
+ /**
+ * The embedded representation of relations. Only present when the '_embed' query parameter is set.
+ */
+ _embedded?: {
+ /**
+ * The author of the post.
+ */
+ author: unknown[];
+ /**
+ * The featured image post.
+ */
+ 'wp:featuredmedia'?: WP_REST_API_Attachment[];
+ [ k: string ]: unknown;
+ };
+ [ k: string ]: unknown;
+}
+
+/**
+ * REST API attachment object with additional fields added by this project.
+ */
+export interface RestAttachment extends WP_REST_API_Attachment {}
+
+type BetterOmit< T, K extends PropertyKey > = {
+ [ P in keyof T as P extends K ? never : P ]: T[ P ];
+};
+
+/**
+ * Transformed attachment object.
+ */
+export type Attachment = BetterOmit<
+ RestAttachment,
+ 'alt_text' | 'source_url' | 'caption' | 'title'
+> & {
+ alt: WP_REST_API_Attachment[ 'alt_text' ];
+ caption: WP_REST_API_Attachment[ 'caption' ][ 'raw' ] & string;
+ title: WP_REST_API_Attachment[ 'title' ][ 'raw' ];
+ url: WP_REST_API_Attachment[ 'source_url' ];
+ poster?: WP_REST_API_Attachment[ 'source_url' ];
+};
+
+export type OnChangeHandler = ( attachments: Partial< Attachment >[] ) => void;
+export type OnSuccessHandler = ( attachments: Partial< Attachment >[] ) => void;
+export type OnErrorHandler = ( error: Error ) => void;
+
+export type CreateRestAttachment = Partial< RestAttachment >;
+
+export type AdditionalData = BetterOmit< CreateRestAttachment, 'meta' >;
diff --git a/packages/media-utils/src/utils/upload-error.ts b/packages/media-utils/src/utils/upload-error.ts
new file mode 100644
index 0000000000000..d712e9dcdb696
--- /dev/null
+++ b/packages/media-utils/src/utils/upload-error.ts
@@ -0,0 +1,26 @@
+interface UploadErrorArgs {
+ code: string;
+ message: string;
+ file: File;
+ cause?: Error;
+}
+
+/**
+ * MediaError class.
+ *
+ * Small wrapper around the `Error` class
+ * to hold an error code and a reference to a file object.
+ */
+export class UploadError extends Error {
+ code: string;
+ file: File;
+
+ constructor( { code, message, file, cause }: UploadErrorArgs ) {
+ super( message, { cause } );
+
+ Object.setPrototypeOf( this, new.target.prototype );
+
+ this.code = code;
+ this.file = file;
+ }
+}
diff --git a/packages/media-utils/src/utils/upload-media.js b/packages/media-utils/src/utils/upload-media.js
deleted file mode 100644
index e3c9b95d5c25c..0000000000000
--- a/packages/media-utils/src/utils/upload-media.js
+++ /dev/null
@@ -1,232 +0,0 @@
-/**
- * WordPress dependencies
- */
-import apiFetch from '@wordpress/api-fetch';
-import { createBlobURL, revokeBlobURL } from '@wordpress/blob';
-import { __, sprintf } from '@wordpress/i18n';
-
-const noop = () => {};
-
-/**
- * Browsers may use unexpected mime types, and they differ from browser to browser.
- * This function computes a flexible array of mime types from the mime type structured provided by the server.
- * Converts { jpg|jpeg|jpe: "image/jpeg" } into [ "image/jpeg", "image/jpg", "image/jpeg", "image/jpe" ]
- * The computation of this array instead of directly using the object,
- * solves the problem in chrome where mp3 files have audio/mp3 as mime type instead of audio/mpeg.
- * https://bugs.chromium.org/p/chromium/issues/detail?id=227004
- *
- * @param {?Object} wpMimeTypesObject Mime type object received from the server.
- * Extensions are keys separated by '|' and values are mime types associated with an extension.
- *
- * @return {?Array} An array of mime types or the parameter passed if it was "falsy".
- */
-export function getMimeTypesArray( wpMimeTypesObject ) {
- if ( ! wpMimeTypesObject ) {
- return wpMimeTypesObject;
- }
- return Object.entries( wpMimeTypesObject )
- .map( ( [ extensionsString, mime ] ) => {
- const [ type ] = mime.split( '/' );
- const extensions = extensionsString.split( '|' );
- return [
- mime,
- ...extensions.map(
- ( extension ) => `${ type }/${ extension }`
- ),
- ];
- } )
- .flat();
-}
-
-/**
- * Media Upload is used by audio, image, gallery, video, and file blocks to
- * handle uploading a media file when a file upload button is activated.
- *
- * TODO: future enhancement to add an upload indicator.
- *
- * @param {Object} $0 Parameters object passed to the function.
- * @param {?Array} $0.allowedTypes Array with the types of media that can be uploaded, if unset all types are allowed.
- * @param {?Object} $0.additionalData Additional data to include in the request.
- * @param {Array} $0.filesList List of files.
- * @param {?number} $0.maxUploadFileSize Maximum upload size in bytes allowed for the site.
- * @param {Function} $0.onError Function called when an error happens.
- * @param {Function} $0.onFileChange Function called each time a file or a temporary representation of the file is available.
- * @param {?Object} $0.wpAllowedMimeTypes List of allowed mime types and file extensions.
- */
-export async function uploadMedia( {
- allowedTypes,
- additionalData = {},
- filesList,
- maxUploadFileSize,
- onError = noop,
- onFileChange,
- wpAllowedMimeTypes = null,
-} ) {
- // Cast filesList to array.
- const files = [ ...filesList ];
-
- const filesSet = [];
- const setAndUpdateFiles = ( idx, value ) => {
- revokeBlobURL( filesSet[ idx ]?.url );
- filesSet[ idx ] = value;
- onFileChange( filesSet.filter( Boolean ) );
- };
-
- // Allowed type specified by consumer.
- const isAllowedType = ( fileType ) => {
- if ( ! allowedTypes ) {
- return true;
- }
- return allowedTypes.some( ( allowedType ) => {
- // If a complete mimetype is specified verify if it matches exactly the mime type of the file.
- if ( allowedType.includes( '/' ) ) {
- return allowedType === fileType;
- }
- // Otherwise a general mime type is used and we should verify if the file mimetype starts with it.
- return fileType.startsWith( `${ allowedType }/` );
- } );
- };
-
- // Allowed types for the current WP_User.
- const allowedMimeTypesForUser = getMimeTypesArray( wpAllowedMimeTypes );
- const isAllowedMimeTypeForUser = ( fileType ) => {
- return allowedMimeTypesForUser.includes( fileType );
- };
-
- const validFiles = [];
-
- for ( const mediaFile of files ) {
- // Verify if user is allowed to upload this mime type.
- // Defer to the server when type not detected.
- if (
- allowedMimeTypesForUser &&
- mediaFile.type &&
- ! isAllowedMimeTypeForUser( mediaFile.type )
- ) {
- onError( {
- code: 'MIME_TYPE_NOT_ALLOWED_FOR_USER',
- message: sprintf(
- // translators: %s: file name.
- __(
- '%s: Sorry, you are not allowed to upload this file type.'
- ),
- mediaFile.name
- ),
- file: mediaFile,
- } );
- continue;
- }
-
- // Check if the block supports this mime type.
- // Defer to the server when type not detected.
- if ( mediaFile.type && ! isAllowedType( mediaFile.type ) ) {
- onError( {
- code: 'MIME_TYPE_NOT_SUPPORTED',
- message: sprintf(
- // translators: %s: file name.
- __( '%s: Sorry, this file type is not supported here.' ),
- mediaFile.name
- ),
- file: mediaFile,
- } );
- continue;
- }
-
- // Verify if file is greater than the maximum file upload size allowed for the site.
- if ( maxUploadFileSize && mediaFile.size > maxUploadFileSize ) {
- onError( {
- code: 'SIZE_ABOVE_LIMIT',
- message: sprintf(
- // translators: %s: file name.
- __(
- '%s: This file exceeds the maximum upload size for this site.'
- ),
- mediaFile.name
- ),
- file: mediaFile,
- } );
- continue;
- }
-
- // Don't allow empty files to be uploaded.
- if ( mediaFile.size <= 0 ) {
- onError( {
- code: 'EMPTY_FILE',
- message: sprintf(
- // translators: %s: file name.
- __( '%s: This file is empty.' ),
- mediaFile.name
- ),
- file: mediaFile,
- } );
- continue;
- }
-
- validFiles.push( mediaFile );
-
- // Set temporary URL to create placeholder media file, this is replaced
- // with final file from media gallery when upload is `done` below.
- filesSet.push( { url: createBlobURL( mediaFile ) } );
- onFileChange( filesSet );
- }
-
- for ( let idx = 0; idx < validFiles.length; ++idx ) {
- const mediaFile = validFiles[ idx ];
- try {
- const savedMedia = await createMediaFromFile(
- mediaFile,
- additionalData
- );
- // eslint-disable-next-line camelcase
- const { alt_text, source_url, ...savedMediaProps } = savedMedia;
- const mediaObject = {
- ...savedMediaProps,
- alt: savedMedia.alt_text,
- caption: savedMedia.caption?.raw ?? '',
- title: savedMedia.title.raw,
- url: savedMedia.source_url,
- };
- setAndUpdateFiles( idx, mediaObject );
- } catch ( error ) {
- // Reset to empty on failure.
- setAndUpdateFiles( idx, null );
- let message;
- if ( error.message ) {
- message = error.message;
- } else {
- message = sprintf(
- // translators: %s: file name
- __( 'Error while uploading file %s to the media library.' ),
- mediaFile.name
- );
- }
- onError( {
- code: 'GENERAL',
- message,
- file: mediaFile,
- } );
- }
- }
-}
-
-/**
- * @param {File} file Media File to Save.
- * @param {?Object} additionalData Additional data to include in the request.
- *
- * @return {Promise} Media Object Promise.
- */
-function createMediaFromFile( file, additionalData ) {
- // Create upload payload.
- const data = new window.FormData();
- data.append( 'file', file, file.name || file.type.replace( '/', '.' ) );
- if ( additionalData ) {
- Object.entries( additionalData ).forEach( ( [ key, value ] ) =>
- data.append( key, value )
- );
- }
- return apiFetch( {
- path: '/wp/v2/media',
- body: data,
- method: 'POST',
- } );
-}
diff --git a/packages/media-utils/src/utils/upload-media.ts b/packages/media-utils/src/utils/upload-media.ts
new file mode 100644
index 0000000000000..1bc861cfb3b60
--- /dev/null
+++ b/packages/media-utils/src/utils/upload-media.ts
@@ -0,0 +1,149 @@
+/**
+ * WordPress dependencies
+ */
+import { __, sprintf } from '@wordpress/i18n';
+import { createBlobURL, revokeBlobURL } from '@wordpress/blob';
+
+/**
+ * Internal dependencies
+ */
+import type {
+ AdditionalData,
+ Attachment,
+ OnChangeHandler,
+ OnErrorHandler,
+ OnSuccessHandler,
+} from './types';
+import { uploadToServer } from './upload-to-server';
+import { validateMimeType } from './validate-mime-type';
+import { validateMimeTypeForUser } from './validate-mime-type-for-user';
+import { validateFileSize } from './validate-file-size';
+import { UploadError } from './upload-error';
+
+interface UploadMediaArgs {
+ // Additional data to include in the request.
+ additionalData?: AdditionalData;
+ // Array with the types of media that can be uploaded, if unset all types are allowed.
+ allowedTypes?: string[];
+ // List of files.
+ filesList: File[];
+ // Maximum upload size in bytes allowed for the site.
+ maxUploadFileSize?: number;
+ // Function called when an error happens.
+ onError?: OnErrorHandler;
+ // Function called each time a file or a temporary representation of the file is available.
+ onFileChange?: OnChangeHandler;
+ // Function called once a file has completely finished uploading, including thumbnails.
+ onSuccess?: OnSuccessHandler;
+ // List of allowed mime types and file extensions.
+ wpAllowedMimeTypes?: Record< string, string > | null;
+ // Abort signal.
+ signal?: AbortSignal;
+}
+
+/**
+ * Upload a media file when the file upload button is activated
+ * or when adding a file to the editor via drag & drop.
+ *
+ * @param $0 Parameters object passed to the function.
+ * @param $0.allowedTypes Array with the types of media that can be uploaded, if unset all types are allowed.
+ * @param $0.additionalData Additional data to include in the request.
+ * @param $0.filesList List of files.
+ * @param $0.maxUploadFileSize Maximum upload size in bytes allowed for the site.
+ * @param $0.onError Function called when an error happens.
+ * @param $0.onFileChange Function called each time a file or a temporary representation of the file is available.
+ * @param $0.wpAllowedMimeTypes List of allowed mime types and file extensions.
+ * @param $0.signal Abort signal.
+ */
+export function uploadMedia( {
+ wpAllowedMimeTypes,
+ allowedTypes,
+ additionalData = {},
+ filesList,
+ maxUploadFileSize,
+ onError,
+ onFileChange,
+ signal,
+}: UploadMediaArgs ) {
+ const validFiles = [];
+
+ const filesSet: Array< Partial< Attachment > | null > = [];
+ const setAndUpdateFiles = ( index: number, value: Attachment | null ) => {
+ if ( filesSet[ index ]?.url ) {
+ revokeBlobURL( filesSet[ index ].url );
+ }
+ filesSet[ index ] = value;
+ onFileChange?.(
+ filesSet.filter( ( attachment ) => attachment !== null )
+ );
+ };
+
+ for ( const mediaFile of filesList ) {
+ // Verify if user is allowed to upload this mime type.
+ // Defer to the server when type not detected.
+ try {
+ validateMimeTypeForUser( mediaFile, wpAllowedMimeTypes );
+ } catch ( error: unknown ) {
+ onError?.( error as Error );
+ continue;
+ }
+
+ // Check if the caller (e.g. a block) supports this mime type.
+ // Defer to the server when type not detected.
+ try {
+ validateMimeType( mediaFile, allowedTypes );
+ } catch ( error: unknown ) {
+ onError?.( error as Error );
+ continue;
+ }
+
+ // Verify if file is greater than the maximum file upload size allowed for the site.
+ try {
+ validateFileSize( mediaFile, maxUploadFileSize );
+ } catch ( error: unknown ) {
+ onError?.( error as Error );
+ continue;
+ }
+
+ validFiles.push( mediaFile );
+
+ // Set temporary URL to create placeholder media file, this is replaced
+ // with final file from media gallery when upload is `done` below.
+ filesSet.push( { url: createBlobURL( mediaFile ) } );
+ onFileChange?.( filesSet as Array< Partial< Attachment > > );
+ }
+
+ validFiles.map( async ( file, index ) => {
+ try {
+ const attachment = await uploadToServer(
+ file,
+ additionalData,
+ signal
+ );
+ setAndUpdateFiles( index, attachment );
+ } catch ( error ) {
+ // Reset to empty on failure.
+ setAndUpdateFiles( index, null );
+
+ let message;
+ if ( error instanceof Error ) {
+ message = error.message;
+ } else {
+ message = sprintf(
+ // translators: %s: file name
+ __( 'Error while uploading file %s to the media library.' ),
+ file.name
+ );
+ }
+
+ onError?.(
+ new UploadError( {
+ code: 'GENERAL',
+ message,
+ file,
+ cause: error instanceof Error ? error : undefined,
+ } )
+ );
+ }
+ } );
+}
diff --git a/packages/media-utils/src/utils/upload-to-server.ts b/packages/media-utils/src/utils/upload-to-server.ts
new file mode 100644
index 0000000000000..7aa4243d5ccfd
--- /dev/null
+++ b/packages/media-utils/src/utils/upload-to-server.ts
@@ -0,0 +1,38 @@
+/**
+ * WordPress dependencies
+ */
+import apiFetch from '@wordpress/api-fetch';
+
+/**
+ * Internal dependencies
+ */
+import { flattenFormData } from './flatten-form-data';
+import { transformAttachment } from './transform-attachment';
+import type { CreateRestAttachment, RestAttachment } from './types';
+
+export async function uploadToServer(
+ file: File,
+ additionalData: CreateRestAttachment = {},
+ signal?: AbortSignal
+) {
+ // Create upload payload.
+ const data = new FormData();
+ data.append( 'file', file, file.name || file.type.replace( '/', '.' ) );
+ for ( const [ key, value ] of Object.entries( additionalData ) ) {
+ flattenFormData(
+ data,
+ key,
+ value as string | Record< string, string > | undefined
+ );
+ }
+
+ return transformAttachment(
+ await apiFetch< RestAttachment >( {
+ // This allows the video block to directly get a video's poster image.
+ path: '/wp/v2/media?_embed=wp:featuredmedia',
+ body: data,
+ method: 'POST',
+ signal,
+ } )
+ );
+}
diff --git a/packages/media-utils/src/utils/validate-file-size.ts b/packages/media-utils/src/utils/validate-file-size.ts
new file mode 100644
index 0000000000000..cc34462b268dd
--- /dev/null
+++ b/packages/media-utils/src/utils/validate-file-size.ts
@@ -0,0 +1,44 @@
+/**
+ * WordPress dependencies
+ */
+import { __, sprintf } from '@wordpress/i18n';
+
+/**
+ * Internal dependencies
+ */
+import { UploadError } from './upload-error';
+
+/**
+ * Verifies whether the file is within the file upload size limits for the site.
+ *
+ * @param file File object.
+ * @param maxUploadFileSize Maximum upload size in bytes allowed for the site.
+ */
+export function validateFileSize( file: File, maxUploadFileSize?: number ) {
+ // Don't allow empty files to be uploaded.
+ if ( file.size <= 0 ) {
+ throw new UploadError( {
+ code: 'EMPTY_FILE',
+ message: sprintf(
+ // translators: %s: file name.
+ __( '%s: This file is empty.' ),
+ file.name
+ ),
+ file,
+ } );
+ }
+
+ if ( maxUploadFileSize && file.size > maxUploadFileSize ) {
+ throw new UploadError( {
+ code: 'SIZE_ABOVE_LIMIT',
+ message: sprintf(
+ // translators: %s: file name.
+ __(
+ '%s: This file exceeds the maximum upload size for this site.'
+ ),
+ file.name
+ ),
+ file,
+ } );
+ }
+}
diff --git a/packages/media-utils/src/utils/validate-mime-type-for-user.ts b/packages/media-utils/src/utils/validate-mime-type-for-user.ts
new file mode 100644
index 0000000000000..858c583561978
--- /dev/null
+++ b/packages/media-utils/src/utils/validate-mime-type-for-user.ts
@@ -0,0 +1,46 @@
+/**
+ * WordPress dependencies
+ */
+import { __, sprintf } from '@wordpress/i18n';
+
+/**
+ * Internal dependencies
+ */
+import { UploadError } from './upload-error';
+import { getMimeTypesArray } from './get-mime-types-array';
+
+/**
+ * Verifies if the user is allowed to upload this mime type.
+ *
+ * @param file File object.
+ * @param wpAllowedMimeTypes List of allowed mime types and file extensions.
+ */
+export function validateMimeTypeForUser(
+ file: File,
+ wpAllowedMimeTypes?: Record< string, string > | null
+) {
+ // Allowed types for the current WP_User.
+ const allowedMimeTypesForUser = getMimeTypesArray( wpAllowedMimeTypes );
+
+ if ( ! allowedMimeTypesForUser ) {
+ return;
+ }
+
+ const isAllowedMimeTypeForUser = allowedMimeTypesForUser.includes(
+ file.type
+ );
+
+ if ( file.type && ! isAllowedMimeTypeForUser ) {
+ throw new UploadError( {
+ code: 'MIME_TYPE_NOT_ALLOWED_FOR_USER',
+ message: sprintf(
+ // translators: %s: file name.
+ __(
+ '%s: Sorry, you are not allowed to upload this file type.'
+ ),
+ file.name
+ ),
+ file,
+ } );
+ }
+}
diff --git a/packages/media-utils/src/utils/validate-mime-type.ts b/packages/media-utils/src/utils/validate-mime-type.ts
new file mode 100644
index 0000000000000..2d99455d7b60f
--- /dev/null
+++ b/packages/media-utils/src/utils/validate-mime-type.ts
@@ -0,0 +1,43 @@
+/**
+ * WordPress dependencies
+ */
+import { __, sprintf } from '@wordpress/i18n';
+
+/**
+ * Internal dependencies
+ */
+import { UploadError } from './upload-error';
+
+/**
+ * Verifies if the caller (e.g. a block) supports this mime type.
+ *
+ * @param file File object.
+ * @param allowedTypes List of allowed mime types.
+ */
+export function validateMimeType( file: File, allowedTypes?: string[] ) {
+ if ( ! allowedTypes ) {
+ return;
+ }
+
+ // Allowed type specified by consumer.
+ const isAllowedType = allowedTypes.some( ( allowedType ) => {
+ // If a complete mimetype is specified verify if it matches exactly the mime type of the file.
+ if ( allowedType.includes( '/' ) ) {
+ return allowedType === file.type;
+ }
+ // Otherwise a general mime type is used, and we should verify if the file mimetype starts with it.
+ return file.type.startsWith( `${ allowedType }/` );
+ } );
+
+ if ( file.type && ! isAllowedType ) {
+ throw new UploadError( {
+ code: 'MIME_TYPE_NOT_SUPPORTED',
+ message: sprintf(
+ // translators: %s: file name.
+ __( '%s: Sorry, this file type is not supported here.' ),
+ file.name
+ ),
+ file,
+ } );
+ }
+}
diff --git a/packages/media-utils/tsconfig.json b/packages/media-utils/tsconfig.json
new file mode 100644
index 0000000000000..8559f1507b723
--- /dev/null
+++ b/packages/media-utils/tsconfig.json
@@ -0,0 +1,17 @@
+{
+ "$schema": "https://json.schemastore.org/tsconfig.json",
+ "extends": "../../tsconfig.base.json",
+ "compilerOptions": {
+ "rootDir": "src",
+ "declarationDir": "build-types",
+ "types": [ "gutenberg-env" ],
+ "checkJs": false
+ },
+ "include": [ "src/**/*" ],
+ "references": [
+ { "path": "../api-fetch" },
+ { "path": "../blob" },
+ { "path": "../element" },
+ { "path": "../i18n" }
+ ]
+}
diff --git a/packages/notices/CHANGELOG.md b/packages/notices/CHANGELOG.md
index 32d51970c2141..f32648df69728 100644
--- a/packages/notices/CHANGELOG.md
+++ b/packages/notices/CHANGELOG.md
@@ -2,6 +2,8 @@
## Unreleased
+## 5.7.0 (2024-09-05)
+
## 5.6.0 (2024-08-21)
## 5.5.0 (2024-08-07)
diff --git a/packages/notices/package.json b/packages/notices/package.json
index 46715eb74a891..a4e2c5ea8d98c 100644
--- a/packages/notices/package.json
+++ b/packages/notices/package.json
@@ -1,6 +1,6 @@
{
"name": "@wordpress/notices",
- "version": "5.6.0",
+ "version": "5.7.0",
"description": "State management for notices.",
"author": "The WordPress Contributors",
"license": "GPL-2.0-or-later",
diff --git a/packages/npm-package-json-lint-config/CHANGELOG.md b/packages/npm-package-json-lint-config/CHANGELOG.md
index cfb2ea682ba45..24dfd09fff55a 100644
--- a/packages/npm-package-json-lint-config/CHANGELOG.md
+++ b/packages/npm-package-json-lint-config/CHANGELOG.md
@@ -2,6 +2,8 @@
## Unreleased
+## 5.7.0 (2024-09-05)
+
## 5.6.0 (2024-08-21)
## 5.5.0 (2024-08-07)
diff --git a/packages/npm-package-json-lint-config/package.json b/packages/npm-package-json-lint-config/package.json
index 1acbcdede95ab..ad88e3fd442a1 100644
--- a/packages/npm-package-json-lint-config/package.json
+++ b/packages/npm-package-json-lint-config/package.json
@@ -1,6 +1,6 @@
{
"name": "@wordpress/npm-package-json-lint-config",
- "version": "5.6.0",
+ "version": "5.7.0",
"description": "WordPress npm-package-json-lint shareable configuration.",
"author": "The WordPress Contributors",
"license": "GPL-2.0-or-later",
diff --git a/packages/nux/CHANGELOG.md b/packages/nux/CHANGELOG.md
index 90c3e96deb80a..85feaa73dbc23 100644
--- a/packages/nux/CHANGELOG.md
+++ b/packages/nux/CHANGELOG.md
@@ -2,6 +2,8 @@
## Unreleased
+## 9.7.0 (2024-09-05)
+
## 9.6.0 (2024-08-21)
## 9.5.0 (2024-08-07)
diff --git a/packages/nux/package.json b/packages/nux/package.json
index 0997a29878bee..7a8e565d163aa 100644
--- a/packages/nux/package.json
+++ b/packages/nux/package.json
@@ -1,6 +1,6 @@
{
"name": "@wordpress/nux",
- "version": "9.6.0",
+ "version": "9.7.0",
"description": "NUX (New User eXperience) module for WordPress.",
"author": "The WordPress Contributors",
"license": "GPL-2.0-or-later",
diff --git a/packages/patterns/CHANGELOG.md b/packages/patterns/CHANGELOG.md
index 612586efb30a5..eaef3c431d668 100644
--- a/packages/patterns/CHANGELOG.md
+++ b/packages/patterns/CHANGELOG.md
@@ -2,6 +2,8 @@
## Unreleased
+## 2.7.0 (2024-09-05)
+
## 2.6.0 (2024-08-21)
## 2.5.0 (2024-08-07)
diff --git a/packages/patterns/package.json b/packages/patterns/package.json
index 5ca0cdbe5b9df..6d67aa7ef3ac9 100644
--- a/packages/patterns/package.json
+++ b/packages/patterns/package.json
@@ -1,6 +1,6 @@
{
"name": "@wordpress/patterns",
- "version": "2.6.0",
+ "version": "2.7.0",
"description": "Management of user pattern editing.",
"author": "The WordPress Contributors",
"license": "GPL-2.0-or-later",
diff --git a/packages/patterns/src/components/style.scss b/packages/patterns/src/components/style.scss
index 30fe0300503c4..1b053ab7ac251 100644
--- a/packages/patterns/src/components/style.scss
+++ b/packages/patterns/src/components/style.scss
@@ -13,8 +13,8 @@
.components-form-token-field__suggestions-list:not(:empty) {
position: absolute;
border: $border-width solid var(--wp-admin-theme-color);
- border-bottom-left-radius: $radius-block-ui;
- border-bottom-right-radius: $radius-block-ui;
+ border-bottom-left-radius: $radius-small;
+ border-bottom-right-radius: $radius-small;
box-shadow: 0 0 0.5px 0.5px var(--wp-admin-theme-color);
box-sizing: border-box;
z-index: 1;
diff --git a/packages/plugins/CHANGELOG.md b/packages/plugins/CHANGELOG.md
index 14b9e4cffa4ad..c2c010c888115 100644
--- a/packages/plugins/CHANGELOG.md
+++ b/packages/plugins/CHANGELOG.md
@@ -2,6 +2,8 @@
## Unreleased
+## 7.7.0 (2024-09-05)
+
## 7.6.0 (2024-08-21)
## 7.5.0 (2024-08-07)
diff --git a/packages/plugins/package.json b/packages/plugins/package.json
index c5bf069bfaa17..9cc58fc5096be 100644
--- a/packages/plugins/package.json
+++ b/packages/plugins/package.json
@@ -1,6 +1,6 @@
{
"name": "@wordpress/plugins",
- "version": "7.6.0",
+ "version": "7.7.0",
"description": "Plugins module for WordPress.",
"author": "The WordPress Contributors",
"license": "GPL-2.0-or-later",
diff --git a/packages/postcss-plugins-preset/CHANGELOG.md b/packages/postcss-plugins-preset/CHANGELOG.md
index 1811914b5bd88..b16c9284417a3 100644
--- a/packages/postcss-plugins-preset/CHANGELOG.md
+++ b/packages/postcss-plugins-preset/CHANGELOG.md
@@ -2,6 +2,8 @@
## Unreleased
+## 5.7.0 (2024-09-05)
+
## 5.6.0 (2024-08-21)
## 5.5.0 (2024-08-07)
diff --git a/packages/postcss-plugins-preset/package.json b/packages/postcss-plugins-preset/package.json
index 892586a194e6f..d012dde494958 100644
--- a/packages/postcss-plugins-preset/package.json
+++ b/packages/postcss-plugins-preset/package.json
@@ -1,6 +1,6 @@
{
"name": "@wordpress/postcss-plugins-preset",
- "version": "5.6.0",
+ "version": "5.7.0",
"description": "PostCSS sharable plugins preset for WordPress development.",
"author": "The WordPress Contributors",
"license": "GPL-2.0-or-later",
diff --git a/packages/postcss-themes/CHANGELOG.md b/packages/postcss-themes/CHANGELOG.md
index 11da169548988..774c2edf77e0c 100644
--- a/packages/postcss-themes/CHANGELOG.md
+++ b/packages/postcss-themes/CHANGELOG.md
@@ -2,6 +2,8 @@
## Unreleased
+## 6.7.0 (2024-09-05)
+
## 6.6.0 (2024-08-21)
## 6.5.0 (2024-08-07)
diff --git a/packages/postcss-themes/package.json b/packages/postcss-themes/package.json
index 57234c6f8d7fb..29e617382161e 100644
--- a/packages/postcss-themes/package.json
+++ b/packages/postcss-themes/package.json
@@ -1,6 +1,6 @@
{
"name": "@wordpress/postcss-themes",
- "version": "6.6.0",
+ "version": "6.7.0",
"description": "PostCSS plugin to generate theme colors.",
"author": "The WordPress Contributors",
"license": "GPL-2.0-or-later",
diff --git a/packages/preferences-persistence/CHANGELOG.md b/packages/preferences-persistence/CHANGELOG.md
index 5b280b336f051..a4a3081901bf5 100644
--- a/packages/preferences-persistence/CHANGELOG.md
+++ b/packages/preferences-persistence/CHANGELOG.md
@@ -2,6 +2,8 @@
## Unreleased
+## 2.7.0 (2024-09-05)
+
## 2.6.0 (2024-08-21)
## 2.5.0 (2024-08-07)
diff --git a/packages/preferences-persistence/package.json b/packages/preferences-persistence/package.json
index f994ca28f6301..a318979abed2a 100644
--- a/packages/preferences-persistence/package.json
+++ b/packages/preferences-persistence/package.json
@@ -1,6 +1,6 @@
{
"name": "@wordpress/preferences-persistence",
- "version": "2.6.0",
+ "version": "2.7.0",
"description": "Persistence utilities for `wordpress/preferences`.",
"author": "The WordPress Contributors",
"license": "GPL-2.0-or-later",
diff --git a/packages/preferences/CHANGELOG.md b/packages/preferences/CHANGELOG.md
index 5a71145f2396d..7d87ce9386875 100644
--- a/packages/preferences/CHANGELOG.md
+++ b/packages/preferences/CHANGELOG.md
@@ -2,6 +2,8 @@
## Unreleased
+## 4.7.0 (2024-09-05)
+
## 4.6.0 (2024-08-21)
## 4.5.0 (2024-08-07)
diff --git a/packages/preferences/package.json b/packages/preferences/package.json
index e39668e6ebe5d..5b12d274af30a 100644
--- a/packages/preferences/package.json
+++ b/packages/preferences/package.json
@@ -1,6 +1,6 @@
{
"name": "@wordpress/preferences",
- "version": "4.6.0",
+ "version": "4.7.0",
"description": "Utilities for managing WordPress preferences.",
"author": "The WordPress Contributors",
"license": "GPL-2.0-or-later",
diff --git a/packages/prettier-config/CHANGELOG.md b/packages/prettier-config/CHANGELOG.md
index 5764c3b87cdd9..e0e01d2b7f3ac 100644
--- a/packages/prettier-config/CHANGELOG.md
+++ b/packages/prettier-config/CHANGELOG.md
@@ -2,6 +2,8 @@
## Unreleased
+## 4.7.0 (2024-09-05)
+
## 4.6.0 (2024-08-21)
## 4.5.0 (2024-08-07)
diff --git a/packages/prettier-config/package.json b/packages/prettier-config/package.json
index da72819772518..f6c7797f2b6e7 100644
--- a/packages/prettier-config/package.json
+++ b/packages/prettier-config/package.json
@@ -1,6 +1,6 @@
{
"name": "@wordpress/prettier-config",
- "version": "4.6.0",
+ "version": "4.7.0",
"description": "WordPress Prettier shared configuration.",
"author": "The WordPress Contributors",
"license": "GPL-2.0-or-later",
diff --git a/packages/primitives/CHANGELOG.md b/packages/primitives/CHANGELOG.md
index b75cafd7ce35f..48db582f65e10 100644
--- a/packages/primitives/CHANGELOG.md
+++ b/packages/primitives/CHANGELOG.md
@@ -2,6 +2,8 @@
## Unreleased
+## 4.7.0 (2024-09-05)
+
## 4.6.0 (2024-08-21)
## 4.5.0 (2024-08-07)
diff --git a/packages/primitives/package.json b/packages/primitives/package.json
index d53ac401d07b6..8296c6348e9be 100644
--- a/packages/primitives/package.json
+++ b/packages/primitives/package.json
@@ -1,6 +1,6 @@
{
"name": "@wordpress/primitives",
- "version": "4.6.0",
+ "version": "4.7.0",
"description": "WordPress cross-platform primitives.",
"author": "The WordPress Contributors",
"license": "GPL-2.0-or-later",
diff --git a/packages/priority-queue/CHANGELOG.md b/packages/priority-queue/CHANGELOG.md
index 398db84f0bb44..a7f1257b8f6b4 100644
--- a/packages/priority-queue/CHANGELOG.md
+++ b/packages/priority-queue/CHANGELOG.md
@@ -2,6 +2,8 @@
## Unreleased
+## 3.7.0 (2024-09-05)
+
## 3.6.0 (2024-08-21)
## 3.5.0 (2024-08-07)
diff --git a/packages/priority-queue/package.json b/packages/priority-queue/package.json
index 012970e634468..c8d7cbe1cebb9 100644
--- a/packages/priority-queue/package.json
+++ b/packages/priority-queue/package.json
@@ -1,6 +1,6 @@
{
"name": "@wordpress/priority-queue",
- "version": "3.6.0",
+ "version": "3.7.0",
"description": "Generic browser priority queue.",
"author": "The WordPress Contributors",
"license": "GPL-2.0-or-later",
diff --git a/packages/private-apis/CHANGELOG.md b/packages/private-apis/CHANGELOG.md
index ebba5ca7d26b9..cd6449dc774ce 100644
--- a/packages/private-apis/CHANGELOG.md
+++ b/packages/private-apis/CHANGELOG.md
@@ -2,6 +2,8 @@
## Unreleased
+## 1.7.0 (2024-09-05)
+
## 1.6.0 (2024-08-21)
## 1.5.0 (2024-08-07)
diff --git a/packages/private-apis/package.json b/packages/private-apis/package.json
index 4493a6a4acc6b..3a3dd1aeab570 100644
--- a/packages/private-apis/package.json
+++ b/packages/private-apis/package.json
@@ -1,6 +1,6 @@
{
"name": "@wordpress/private-apis",
- "version": "1.6.0",
+ "version": "1.7.0",
"description": "Internal experimental APIs for WordPress core.",
"author": "The WordPress Contributors",
"license": "GPL-2.0-or-later",
diff --git a/packages/project-management-automation/CHANGELOG.md b/packages/project-management-automation/CHANGELOG.md
index d72669229fd2a..167e68512b3df 100644
--- a/packages/project-management-automation/CHANGELOG.md
+++ b/packages/project-management-automation/CHANGELOG.md
@@ -2,6 +2,8 @@
## Unreleased
+## 2.7.0 (2024-09-05)
+
## 2.6.0 (2024-08-21)
## 2.5.0 (2024-08-07)
diff --git a/packages/project-management-automation/package.json b/packages/project-management-automation/package.json
index c82b5821342fe..2e33d7c44d6cf 100644
--- a/packages/project-management-automation/package.json
+++ b/packages/project-management-automation/package.json
@@ -1,6 +1,6 @@
{
"name": "@wordpress/project-management-automation",
- "version": "2.6.0",
+ "version": "2.7.0",
"description": "GitHub Action that implements various automation to assist with managing the Gutenberg GitHub repository.",
"author": "The WordPress Contributors",
"license": "GPL-2.0-or-later",
diff --git a/packages/react-i18n/CHANGELOG.md b/packages/react-i18n/CHANGELOG.md
index 20bd01908d406..d0c0dbe7079f4 100644
--- a/packages/react-i18n/CHANGELOG.md
+++ b/packages/react-i18n/CHANGELOG.md
@@ -2,6 +2,8 @@
## Unreleased
+## 4.7.0 (2024-09-05)
+
## 4.6.0 (2024-08-21)
## 4.5.0 (2024-08-07)
diff --git a/packages/react-i18n/package.json b/packages/react-i18n/package.json
index 6067ae8cf929c..d39fc7bba4ba5 100644
--- a/packages/react-i18n/package.json
+++ b/packages/react-i18n/package.json
@@ -1,6 +1,6 @@
{
"name": "@wordpress/react-i18n",
- "version": "4.6.0",
+ "version": "4.7.0",
"description": "React bindings for @wordpress/i18n.",
"author": "The WordPress Contributors",
"license": "GPL-2.0-or-later",
diff --git a/packages/readable-js-assets-webpack-plugin/CHANGELOG.md b/packages/readable-js-assets-webpack-plugin/CHANGELOG.md
index a522759971264..8147d5c3b3475 100644
--- a/packages/readable-js-assets-webpack-plugin/CHANGELOG.md
+++ b/packages/readable-js-assets-webpack-plugin/CHANGELOG.md
@@ -2,6 +2,8 @@
## Unreleased
+## 3.7.0 (2024-09-05)
+
## 3.6.0 (2024-08-21)
## 3.5.0 (2024-08-07)
diff --git a/packages/readable-js-assets-webpack-plugin/package.json b/packages/readable-js-assets-webpack-plugin/package.json
index aefee907eb746..285bcc27ba0a6 100644
--- a/packages/readable-js-assets-webpack-plugin/package.json
+++ b/packages/readable-js-assets-webpack-plugin/package.json
@@ -1,6 +1,6 @@
{
"name": "@wordpress/readable-js-assets-webpack-plugin",
- "version": "3.6.0",
+ "version": "3.7.0",
"description": "Generate a readable JS file for each JS asset.",
"author": "The WordPress Contributors",
"license": "GPL-2.0-or-later",
diff --git a/packages/redux-routine/CHANGELOG.md b/packages/redux-routine/CHANGELOG.md
index 1241701e225e9..bd03c25219ddb 100644
--- a/packages/redux-routine/CHANGELOG.md
+++ b/packages/redux-routine/CHANGELOG.md
@@ -2,6 +2,8 @@
## Unreleased
+## 5.7.0 (2024-09-05)
+
## 5.6.0 (2024-08-21)
## 5.5.0 (2024-08-07)
diff --git a/packages/redux-routine/package.json b/packages/redux-routine/package.json
index d78fad4d28eda..1efebcb92de7f 100644
--- a/packages/redux-routine/package.json
+++ b/packages/redux-routine/package.json
@@ -1,6 +1,6 @@
{
"name": "@wordpress/redux-routine",
- "version": "5.6.0",
+ "version": "5.7.0",
"description": "Redux middleware for generator coroutines.",
"author": "The WordPress Contributors",
"license": "GPL-2.0-or-later",
diff --git a/packages/reusable-blocks/CHANGELOG.md b/packages/reusable-blocks/CHANGELOG.md
index 41a66dd019d78..33f4ef529587f 100644
--- a/packages/reusable-blocks/CHANGELOG.md
+++ b/packages/reusable-blocks/CHANGELOG.md
@@ -2,6 +2,8 @@
## Unreleased
+## 5.7.0 (2024-09-05)
+
## 5.6.0 (2024-08-21)
## 5.5.0 (2024-08-07)
diff --git a/packages/reusable-blocks/package.json b/packages/reusable-blocks/package.json
index c1e5c9a71b072..8c15057189dc9 100644
--- a/packages/reusable-blocks/package.json
+++ b/packages/reusable-blocks/package.json
@@ -1,6 +1,6 @@
{
"name": "@wordpress/reusable-blocks",
- "version": "5.6.0",
+ "version": "5.7.0",
"description": "Reusable blocks utilities.",
"author": "The WordPress Contributors",
"license": "GPL-2.0-or-later",
diff --git a/packages/rich-text/CHANGELOG.md b/packages/rich-text/CHANGELOG.md
index b3f7b7a2e4fdd..cee6ada55f7b6 100644
--- a/packages/rich-text/CHANGELOG.md
+++ b/packages/rich-text/CHANGELOG.md
@@ -2,6 +2,8 @@
## Unreleased
+## 7.7.0 (2024-09-05)
+
## 7.6.0 (2024-08-21)
## 7.5.0 (2024-08-07)
diff --git a/packages/rich-text/package.json b/packages/rich-text/package.json
index 163b7f5e7188a..a5a96c77175c1 100644
--- a/packages/rich-text/package.json
+++ b/packages/rich-text/package.json
@@ -1,6 +1,6 @@
{
"name": "@wordpress/rich-text",
- "version": "7.6.0",
+ "version": "7.7.0",
"description": "Rich text value and manipulation API.",
"author": "The WordPress Contributors",
"license": "GPL-2.0-or-later",
diff --git a/packages/router/CHANGELOG.md b/packages/router/CHANGELOG.md
index 16bf8c495eb03..02871d4f31e13 100644
--- a/packages/router/CHANGELOG.md
+++ b/packages/router/CHANGELOG.md
@@ -2,6 +2,8 @@
## Unreleased
+## 1.7.0 (2024-09-05)
+
## 1.6.0 (2024-08-21)
## 1.5.0 (2024-08-07)
diff --git a/packages/router/package.json b/packages/router/package.json
index 5bda384293cf5..bcc709bbac5d3 100644
--- a/packages/router/package.json
+++ b/packages/router/package.json
@@ -1,6 +1,6 @@
{
"name": "@wordpress/router",
- "version": "1.6.0",
+ "version": "1.7.0",
"description": "Router API for WordPress pages.",
"author": "The WordPress Contributors",
"license": "GPL-2.0-or-later",
diff --git a/packages/scripts/CHANGELOG.md b/packages/scripts/CHANGELOG.md
index cd796ba46dbfa..ea8a59d1ad2ad 100644
--- a/packages/scripts/CHANGELOG.md
+++ b/packages/scripts/CHANGELOG.md
@@ -2,6 +2,12 @@
## Unreleased
+## 29.0.0 (2024-09-05)
+
+### Breaking Changes
+
+- Fixed the issue with having 5 high severity vulnerabilities by upgrading the `puppeteer-core` package to the latest major version `^23.1.0` ([#64597](https://github.com/WordPress/gutenberg/pull/64597)).
+
### Enhancements
- Inlines CSS files imported from other CSS files before optimization in the `build` command ([#61121](https://github.com/WordPress/gutenberg/pull/61121)).
diff --git a/packages/scripts/package.json b/packages/scripts/package.json
index c4582ba65d15e..35547682ae32b 100644
--- a/packages/scripts/package.json
+++ b/packages/scripts/package.json
@@ -1,6 +1,6 @@
{
"name": "@wordpress/scripts",
- "version": "28.6.0",
+ "version": "29.0.0",
"description": "Collection of reusable scripts for WordPress development.",
"author": "The WordPress Contributors",
"license": "GPL-2.0-or-later",
@@ -76,7 +76,7 @@
"postcss-import": "^16.1.0",
"postcss-loader": "^6.2.1",
"prettier": "npm:wp-prettier@3.0.3",
- "puppeteer-core": "^13.2.0",
+ "puppeteer-core": "^23.1.0",
"react-refresh": "^0.14.0",
"read-pkg-up": "^7.0.1",
"resolve-bin": "^0.4.0",
diff --git a/packages/server-side-render/CHANGELOG.md b/packages/server-side-render/CHANGELOG.md
index 6246bff21cb48..d576f09c8e34b 100644
--- a/packages/server-side-render/CHANGELOG.md
+++ b/packages/server-side-render/CHANGELOG.md
@@ -2,6 +2,8 @@
## Unreleased
+## 5.7.0 (2024-09-05)
+
## 5.6.0 (2024-08-21)
## 5.5.0 (2024-08-07)
diff --git a/packages/server-side-render/package.json b/packages/server-side-render/package.json
index 054e8b938ce84..9ace449e3fe96 100644
--- a/packages/server-side-render/package.json
+++ b/packages/server-side-render/package.json
@@ -1,6 +1,6 @@
{
"name": "@wordpress/server-side-render",
- "version": "5.6.0",
+ "version": "5.7.0",
"description": "The component used with WordPress to server-side render a preview of dynamic blocks to display in the editor.",
"author": "The WordPress Contributors",
"license": "GPL-2.0-or-later",
diff --git a/packages/shortcode/CHANGELOG.md b/packages/shortcode/CHANGELOG.md
index eeb738b9e4912..6abdd3c52f6d7 100644
--- a/packages/shortcode/CHANGELOG.md
+++ b/packages/shortcode/CHANGELOG.md
@@ -2,6 +2,8 @@
## Unreleased
+## 4.7.0 (2024-09-05)
+
## 4.6.0 (2024-08-21)
## 4.5.0 (2024-08-07)
diff --git a/packages/shortcode/package.json b/packages/shortcode/package.json
index 42ca3458d72a5..10e368d06c995 100644
--- a/packages/shortcode/package.json
+++ b/packages/shortcode/package.json
@@ -1,6 +1,6 @@
{
"name": "@wordpress/shortcode",
- "version": "4.6.0",
+ "version": "4.7.0",
"description": "Shortcode module for WordPress.",
"author": "The WordPress Contributors",
"license": "GPL-2.0-or-later",
diff --git a/packages/style-engine/CHANGELOG.md b/packages/style-engine/CHANGELOG.md
index b8462204ea958..a5292bfdd6c19 100644
--- a/packages/style-engine/CHANGELOG.md
+++ b/packages/style-engine/CHANGELOG.md
@@ -2,6 +2,8 @@
## Unreleased
+## 2.7.0 (2024-09-05)
+
## 2.6.0 (2024-08-21)
### New Features
diff --git a/packages/style-engine/package.json b/packages/style-engine/package.json
index 91409072cb650..982ac1c1fa89d 100644
--- a/packages/style-engine/package.json
+++ b/packages/style-engine/package.json
@@ -1,6 +1,6 @@
{
"name": "@wordpress/style-engine",
- "version": "2.6.0",
+ "version": "2.7.0",
"description": "A suite of parsers and compilers for WordPress styles.",
"author": "The WordPress Contributors",
"license": "GPL-2.0-or-later",
diff --git a/packages/stylelint-config/CHANGELOG.md b/packages/stylelint-config/CHANGELOG.md
index 4df376a34b098..9cb29690af289 100644
--- a/packages/stylelint-config/CHANGELOG.md
+++ b/packages/stylelint-config/CHANGELOG.md
@@ -2,6 +2,8 @@
## Unreleased
+## 22.7.0 (2024-09-05)
+
## 22.6.0 (2024-08-21)
## 22.5.0 (2024-08-07)
diff --git a/packages/stylelint-config/package.json b/packages/stylelint-config/package.json
index aab9f8e8c3b41..19e6f19bfd2f8 100644
--- a/packages/stylelint-config/package.json
+++ b/packages/stylelint-config/package.json
@@ -1,6 +1,6 @@
{
"name": "@wordpress/stylelint-config",
- "version": "22.6.0",
+ "version": "22.7.0",
"description": "stylelint config for WordPress development.",
"author": "The WordPress Contributors",
"license": "MIT",
diff --git a/packages/sync/CHANGELOG.md b/packages/sync/CHANGELOG.md
index b38fb8b48945c..071974be2a3a8 100644
--- a/packages/sync/CHANGELOG.md
+++ b/packages/sync/CHANGELOG.md
@@ -2,6 +2,8 @@
## Unreleased
+## 1.7.0 (2024-09-05)
+
## 1.6.0 (2024-08-21)
## 1.5.0 (2024-08-07)
diff --git a/packages/sync/package.json b/packages/sync/package.json
index 703de650e3f24..ba8c433e880c3 100644
--- a/packages/sync/package.json
+++ b/packages/sync/package.json
@@ -1,6 +1,6 @@
{
"name": "@wordpress/sync",
- "version": "1.6.0",
+ "version": "1.7.0",
"description": "Sync Data.",
"author": "The WordPress Contributors",
"license": "GPL-2.0-or-later",
diff --git a/packages/token-list/CHANGELOG.md b/packages/token-list/CHANGELOG.md
index 97b674024e637..7258699a5322a 100644
--- a/packages/token-list/CHANGELOG.md
+++ b/packages/token-list/CHANGELOG.md
@@ -2,6 +2,8 @@
## Unreleased
+## 3.7.0 (2024-09-05)
+
## 3.6.0 (2024-08-21)
## 3.5.0 (2024-08-07)
diff --git a/packages/token-list/package.json b/packages/token-list/package.json
index d40820a1f73a8..1a06b76ccb111 100644
--- a/packages/token-list/package.json
+++ b/packages/token-list/package.json
@@ -1,6 +1,6 @@
{
"name": "@wordpress/token-list",
- "version": "3.6.0",
+ "version": "3.7.0",
"description": "Constructable, plain JavaScript DOMTokenList implementation, supporting non-browser runtimes.",
"author": "The WordPress Contributors",
"license": "GPL-2.0-or-later",
diff --git a/packages/undo-manager/CHANGELOG.md b/packages/undo-manager/CHANGELOG.md
index 63338342dfe54..cbe86921a489d 100644
--- a/packages/undo-manager/CHANGELOG.md
+++ b/packages/undo-manager/CHANGELOG.md
@@ -2,6 +2,8 @@
## Unreleased
+## 1.7.0 (2024-09-05)
+
## 1.6.0 (2024-08-21)
## 1.5.0 (2024-08-07)
diff --git a/packages/undo-manager/package.json b/packages/undo-manager/package.json
index 3607f6f6a990c..4574d94f46d7e 100644
--- a/packages/undo-manager/package.json
+++ b/packages/undo-manager/package.json
@@ -1,6 +1,6 @@
{
"name": "@wordpress/undo-manager",
- "version": "1.6.0",
+ "version": "1.7.0",
"description": "A small package to manage undo/redo.",
"author": "The WordPress Contributors",
"license": "GPL-2.0-or-later",
diff --git a/packages/url/CHANGELOG.md b/packages/url/CHANGELOG.md
index f9af22f9fa744..fc3082dd1bd0c 100644
--- a/packages/url/CHANGELOG.md
+++ b/packages/url/CHANGELOG.md
@@ -2,6 +2,8 @@
## Unreleased
+## 4.7.0 (2024-09-05)
+
## 4.6.0 (2024-08-21)
## 4.5.0 (2024-08-07)
diff --git a/packages/url/package.json b/packages/url/package.json
index e83c05e594e5f..c8360c81008fa 100644
--- a/packages/url/package.json
+++ b/packages/url/package.json
@@ -1,6 +1,6 @@
{
"name": "@wordpress/url",
- "version": "4.6.0",
+ "version": "4.7.0",
"description": "WordPress URL utilities.",
"author": "The WordPress Contributors",
"license": "GPL-2.0-or-later",
diff --git a/packages/viewport/CHANGELOG.md b/packages/viewport/CHANGELOG.md
index 8ce0b7b1ffb75..1bc96013d724b 100644
--- a/packages/viewport/CHANGELOG.md
+++ b/packages/viewport/CHANGELOG.md
@@ -2,6 +2,8 @@
## Unreleased
+## 6.7.0 (2024-09-05)
+
## 6.6.0 (2024-08-21)
## 6.5.0 (2024-08-07)
diff --git a/packages/viewport/package.json b/packages/viewport/package.json
index 7575c63256b63..69fe9c8695c6c 100644
--- a/packages/viewport/package.json
+++ b/packages/viewport/package.json
@@ -1,6 +1,6 @@
{
"name": "@wordpress/viewport",
- "version": "6.6.0",
+ "version": "6.7.0",
"description": "Viewport module for WordPress.",
"author": "The WordPress Contributors",
"license": "GPL-2.0-or-later",
diff --git a/packages/warning/CHANGELOG.md b/packages/warning/CHANGELOG.md
index ca17603226154..bb7df7b633062 100644
--- a/packages/warning/CHANGELOG.md
+++ b/packages/warning/CHANGELOG.md
@@ -2,6 +2,8 @@
## Unreleased
+## 3.7.0 (2024-09-05)
+
## 3.6.0 (2024-08-21)
## 3.5.0 (2024-08-07)
diff --git a/packages/warning/package.json b/packages/warning/package.json
index b18ad5ffc5167..1095d2efd7562 100644
--- a/packages/warning/package.json
+++ b/packages/warning/package.json
@@ -1,6 +1,6 @@
{
"name": "@wordpress/warning",
- "version": "3.6.0",
+ "version": "3.7.0",
"description": "Warning utility for WordPress.",
"author": "The WordPress Contributors",
"license": "GPL-2.0-or-later",
diff --git a/packages/widgets/CHANGELOG.md b/packages/widgets/CHANGELOG.md
index e95c3904f97e1..be1af83931495 100644
--- a/packages/widgets/CHANGELOG.md
+++ b/packages/widgets/CHANGELOG.md
@@ -2,6 +2,8 @@
## Unreleased
+## 4.7.0 (2024-09-05)
+
## 4.6.0 (2024-08-21)
## 4.5.0 (2024-08-07)
diff --git a/packages/widgets/package.json b/packages/widgets/package.json
index c7fbb82eb0cb1..595bad0f73365 100644
--- a/packages/widgets/package.json
+++ b/packages/widgets/package.json
@@ -1,6 +1,6 @@
{
"name": "@wordpress/widgets",
- "version": "4.6.0",
+ "version": "4.7.0",
"description": "Functionality used by the widgets block editor in the Widgets screen and the Customizer.",
"author": "The WordPress Contributors",
"license": "GPL-2.0-or-later",
diff --git a/packages/widgets/src/blocks/legacy-widget/editor.scss b/packages/widgets/src/blocks/legacy-widget/editor.scss
index 6b04ce0a407e4..8c213eec86f9f 100644
--- a/packages/widgets/src/blocks/legacy-widget/editor.scss
+++ b/packages/widgets/src/blocks/legacy-widget/editor.scss
@@ -3,7 +3,7 @@
display: flow-root;
}
background: $white;
- border-radius: $radius-block-ui;
+ border-radius: $radius-small;
border: $border-width solid $gray-900;
padding: $grid-unit-15 - $border-width;
max-height: calc(100vh - #{ $border-width } - #{ $border-width });
@@ -95,7 +95,7 @@
cursor: pointer;
&:hover::after {
- border-radius: $radius-block-ui;
+ border-radius: $radius-small;
border: $border-width solid $gray-600;
bottom: 0;
content: "";
diff --git a/packages/widgets/src/blocks/widget-group/editor.scss b/packages/widgets/src/blocks/widget-group/editor.scss
index 38798ef34c7c6..1cd179539bc1a 100644
--- a/packages/widgets/src/blocks/widget-group/editor.scss
+++ b/packages/widgets/src/blocks/widget-group/editor.scss
@@ -1,6 +1,6 @@
.wp-block-widget-group {
&.has-child-selected::after {
- border-radius: $radius-block-ui;
+ border-radius: $radius-small;
border: $border-width solid var(--wp-admin-theme-color);
bottom: 0;
content: "";
diff --git a/packages/wordcount/CHANGELOG.md b/packages/wordcount/CHANGELOG.md
index 33eb27b885ab4..0a5e3ae4d3b20 100644
--- a/packages/wordcount/CHANGELOG.md
+++ b/packages/wordcount/CHANGELOG.md
@@ -2,6 +2,8 @@
## Unreleased
+## 4.7.0 (2024-09-05)
+
## 4.6.0 (2024-08-21)
## 4.5.0 (2024-08-07)
diff --git a/packages/wordcount/package.json b/packages/wordcount/package.json
index 55cbfe3311d28..4f6fe750e3fad 100644
--- a/packages/wordcount/package.json
+++ b/packages/wordcount/package.json
@@ -1,6 +1,6 @@
{
"name": "@wordpress/wordcount",
- "version": "4.6.0",
+ "version": "4.7.0",
"description": "WordPress word count utility.",
"author": "The WordPress Contributors",
"license": "GPL-2.0-or-later",
diff --git a/phpunit/blocks/render-block-media-text-test.php b/phpunit/blocks/render-block-media-text-test.php
index 94c184408c89f..f5b67f0a8dc9b 100644
--- a/phpunit/blocks/render-block-media-text-test.php
+++ b/phpunit/blocks/render-block-media-text-test.php
@@ -81,15 +81,14 @@ public function test_render_block_core_media_text_featured_image() {
$rendered = gutenberg_render_block_core_media_text( $attributes, $content );
$this->assertStringContainsString( ' true,
'imageFill' => true,
);
$rendered = gutenberg_render_block_core_media_text( $attributes, $content );
- $this->assertStringContainsString( 'background-image:url(' . wp_get_attachment_image_url( self::$attachment_id, 'full' ) . ')', $rendered );
- $this->assertStringNotContainsString( ' assertStringContainsString( ' assertStringContainsString( ' true,
'imageFill' => true,
);
$rendered = gutenberg_render_block_core_media_text( $attributes, $content );
- $this->assertStringContainsString( 'background-image:url(' . wp_get_attachment_image_url( self::$attachment_id, 'full' ) . ')', $rendered );
- $this->assertStringNotContainsString( ' assertStringContainsString( ' assertStringContainsString( ' true,
'mediaPosition' => 'right',
'imageFill' => true,
);
$rendered = gutenberg_render_block_core_media_text( $attributes, $content );
- $this->assertStringContainsString( 'background-image:url(' . wp_get_attachment_image_url( self::$attachment_id, 'full' ) . ')', $rendered );
- $this->assertStringNotContainsString( ' assertStringContainsString( ' assertStringContainsString( ' true,
'mediaPosition' => 'right',
@@ -173,7 +170,6 @@ public function test_render_block_core_media_text_featured_image_media_on_right_
);
$rendered = gutenberg_render_block_core_media_text( $attributes, $content );
- $this->assertStringContainsString( 'background-image:url(' . wp_get_attachment_image_url( self::$attachment_id, 'full' ) . ')', $rendered );
- $this->assertStringNotContainsString( ' assertStringContainsString( ' {
).toHaveText( 'fallback value' );
} );
+ test( 'should show the prompt placeholder in field with empty value', async ( {
+ editor,
+ } ) => {
+ await editor.insertBlock( {
+ name: 'core/paragraph',
+ attributes: {
+ content: 'paragraph default content',
+ metadata: {
+ bindings: {
+ content: {
+ source: 'core/post-meta',
+ args: { key: 'empty_field' },
+ },
+ },
+ },
+ },
+ } );
+
+ const paragraphBlock = editor.canvas.getByRole( 'document', {
+ // Aria-label is changed for empty paragraphs.
+ name: 'Add empty_field',
+ } );
+
+ await expect( paragraphBlock ).toBeEmpty();
+
+ const placeholder = paragraphBlock.locator( 'span' );
+ await expect( placeholder ).toHaveAttribute(
+ 'data-rich-text-placeholder',
+ 'Add empty_field'
+ );
+ } );
+
test( 'should not show the value of a protected meta field', async ( {
editor,
} ) => {
@@ -1441,20 +1473,10 @@ test.describe( 'Block bindings', () => {
editor,
page,
} ) => {
- // Activate the block bindings UI experiment.
- await page.evaluate( () => {
- window.__experimentalBlockBindingsUI = true;
- } );
-
await editor.insertBlock( {
name: 'core/paragraph',
} );
- await page
- .getByRole( 'tabpanel', {
- name: 'Settings',
- } )
- .getByLabel( 'Attributes options' )
- .click();
+ await page.getByLabel( 'Attributes options' ).click();
const contentAttribute = page.getByRole( 'menuitemcheckbox', {
name: 'Show content',
} );
@@ -1464,11 +1486,6 @@ test.describe( 'Block bindings', () => {
editor,
page,
} ) => {
- // Activate the block bindings UI experiment.
- await page.evaluate( () => {
- window.__experimentalBlockBindingsUI = true;
- } );
-
await editor.insertBlock( {
name: 'core/paragraph',
attributes: {
@@ -1483,12 +1500,7 @@ test.describe( 'Block bindings', () => {
},
},
} );
- await page
- .getByRole( 'tabpanel', {
- name: 'Settings',
- } )
- .getByRole( 'button', { name: 'content' } )
- .click();
+ await page.getByRole( 'button', { name: 'content' } ).click();
await page
.getByRole( 'menuitemradio' )
@@ -1586,20 +1598,10 @@ test.describe( 'Block bindings', () => {
editor,
page,
} ) => {
- // Activate the block bindings UI experiment.
- await page.evaluate( () => {
- window.__experimentalBlockBindingsUI = true;
- } );
-
await editor.insertBlock( {
name: 'core/heading',
} );
- await page
- .getByRole( 'tabpanel', {
- name: 'Settings',
- } )
- .getByLabel( 'Attributes options' )
- .click();
+ await page.getByLabel( 'Attributes options' ).click();
const contentAttribute = page.getByRole( 'menuitemcheckbox', {
name: 'Show content',
} );
@@ -1786,11 +1788,6 @@ test.describe( 'Block bindings', () => {
editor,
page,
} ) => {
- // Activate the block bindings UI experiment.
- await page.evaluate( () => {
- window.__experimentalBlockBindingsUI = true;
- } );
-
await editor.insertBlock( {
name: 'core/buttons',
innerBlocks: [
@@ -2121,11 +2118,6 @@ test.describe( 'Block bindings', () => {
editor,
page,
} ) => {
- // Activate the block bindings UI experiment.
- await page.evaluate( () => {
- window.__experimentalBlockBindingsUI = true;
- } );
-
await editor.insertBlock( {
name: 'core/image',
} );
@@ -2414,11 +2406,9 @@ test.describe( 'Block bindings', () => {
},
} );
- const bindingsPanel = page
- .getByRole( 'tabpanel', {
- name: 'Settings',
- } )
- .locator( '.block-editor-bindings__panel' );
+ const bindingsPanel = page.locator(
+ '.block-editor-bindings__panel'
+ );
await expect( bindingsPanel ).toContainText( 'Server Source' );
} );
} );
diff --git a/test/integration/fixtures/blocks/core__media-text__deprecated-v5.serialized.html b/test/integration/fixtures/blocks/core__media-text__deprecated-v5.serialized.html
index 7d7a76c730b27..8c88b8b67795d 100644
--- a/test/integration/fixtures/blocks/core__media-text__deprecated-v5.serialized.html
+++ b/test/integration/fixtures/blocks/core__media-text__deprecated-v5.serialized.html
@@ -1,5 +1,5 @@
-
+
diff --git a/test/integration/fixtures/blocks/core__media-text__deprecated-v7-image-fill-no-focal-point-selected.html b/test/integration/fixtures/blocks/core__media-text__deprecated-v7-image-fill-no-focal-point-selected.html
new file mode 100644
index 0000000000000..22a2a3e18f74f
--- /dev/null
+++ b/test/integration/fixtures/blocks/core__media-text__deprecated-v7-image-fill-no-focal-point-selected.html
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
diff --git a/test/integration/fixtures/blocks/core__media-text__deprecated-v7-image-fill-no-focal-point-selected.json b/test/integration/fixtures/blocks/core__media-text__deprecated-v7-image-fill-no-focal-point-selected.json
new file mode 100644
index 0000000000000..bf195f6fa1c95
--- /dev/null
+++ b/test/integration/fixtures/blocks/core__media-text__deprecated-v7-image-fill-no-focal-point-selected.json
@@ -0,0 +1,29 @@
+[
+ {
+ "name": "core/media-text",
+ "isValid": true,
+ "attributes": {
+ "align": "wide",
+ "mediaAlt": "My alt text",
+ "mediaPosition": "left",
+ "mediaType": "image",
+ "mediaWidth": 50,
+ "isStackedOnMobile": true,
+ "mediaUrl": "data:image/jpeg;base64,/9j/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCgsOCwkJDRENDg8QEBEQCgwSExIQEw8QEBD/yQALCAABAAEBAREA/8wABgAQEAX/2gAIAQEAAD8A0s8g/9k=",
+ "imageFill": true
+ },
+ "innerBlocks": [
+ {
+ "name": "core/paragraph",
+ "isValid": true,
+ "attributes": {
+ "content": "My Content",
+ "dropCap": false,
+ "placeholder": "Content…",
+ "fontSize": "large"
+ },
+ "innerBlocks": []
+ }
+ ]
+ }
+]
diff --git a/test/integration/fixtures/blocks/core__media-text__deprecated-v7-image-fill-no-focal-point-selected.parsed.json b/test/integration/fixtures/blocks/core__media-text__deprecated-v7-image-fill-no-focal-point-selected.parsed.json
new file mode 100644
index 0000000000000..2e878c98a18a8
--- /dev/null
+++ b/test/integration/fixtures/blocks/core__media-text__deprecated-v7-image-fill-no-focal-point-selected.parsed.json
@@ -0,0 +1,29 @@
+[
+ {
+ "blockName": "core/media-text",
+ "attrs": {
+ "mediaType": "image",
+ "imageFill": true
+ },
+ "innerBlocks": [
+ {
+ "blockName": "core/paragraph",
+ "attrs": {
+ "placeholder": "Content…",
+ "fontSize": "large"
+ },
+ "innerBlocks": [],
+ "innerHTML": "\n\t\t
My Content
\n\t\t",
+ "innerContent": [
+ "\n\t\t
My Content
\n\t\t"
+ ]
+ }
+ ],
+ "innerHTML": "\n
\n\t
\n\t\t \n\t
\n\t\t\n\t
\n
\n",
+ "innerContent": [
+ "\n
\n\t
\n\t\t \n\t
\n\t\t",
+ null,
+ "\n\t
\n
\n"
+ ]
+ }
+]
diff --git a/test/integration/fixtures/blocks/core__media-text__deprecated-v7-image-fill-no-focal-point-selected.serialized.html b/test/integration/fixtures/blocks/core__media-text__deprecated-v7-image-fill-no-focal-point-selected.serialized.html
new file mode 100644
index 0000000000000..b9d5e14f90277
--- /dev/null
+++ b/test/integration/fixtures/blocks/core__media-text__deprecated-v7-image-fill-no-focal-point-selected.serialized.html
@@ -0,0 +1,5 @@
+
+
+
diff --git a/test/integration/fixtures/blocks/core__media-text__deprecated-v7-image-fill-with-focal-point-selected.html b/test/integration/fixtures/blocks/core__media-text__deprecated-v7-image-fill-with-focal-point-selected.html
new file mode 100644
index 0000000000000..47a0f0c126fa7
--- /dev/null
+++ b/test/integration/fixtures/blocks/core__media-text__deprecated-v7-image-fill-with-focal-point-selected.html
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
diff --git a/test/integration/fixtures/blocks/core__media-text__deprecated-v7-image-fill-with-focal-point-selected.json b/test/integration/fixtures/blocks/core__media-text__deprecated-v7-image-fill-with-focal-point-selected.json
new file mode 100644
index 0000000000000..986e049099541
--- /dev/null
+++ b/test/integration/fixtures/blocks/core__media-text__deprecated-v7-image-fill-with-focal-point-selected.json
@@ -0,0 +1,33 @@
+[
+ {
+ "name": "core/media-text",
+ "isValid": true,
+ "attributes": {
+ "align": "wide",
+ "mediaAlt": "My alt text",
+ "mediaPosition": "left",
+ "mediaType": "image",
+ "mediaWidth": 50,
+ "isStackedOnMobile": true,
+ "mediaUrl": "data:image/jpeg;base64,/9j/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCgsOCwkJDRENDg8QEBEQCgwSExIQEw8QEBD/yQALCAABAAEBAREA/8wABgAQEAX/2gAIAQEAAD8A0s8g/9k=",
+ "imageFill": true,
+ "focalPoint": {
+ "x": 0.84,
+ "y": 0.84
+ }
+ },
+ "innerBlocks": [
+ {
+ "name": "core/paragraph",
+ "isValid": true,
+ "attributes": {
+ "content": "My Content",
+ "dropCap": false,
+ "placeholder": "Content…",
+ "fontSize": "large"
+ },
+ "innerBlocks": []
+ }
+ ]
+ }
+]
diff --git a/test/integration/fixtures/blocks/core__media-text__deprecated-v7-image-fill-with-focal-point-selected.parsed.json b/test/integration/fixtures/blocks/core__media-text__deprecated-v7-image-fill-with-focal-point-selected.parsed.json
new file mode 100644
index 0000000000000..175fbad27927b
--- /dev/null
+++ b/test/integration/fixtures/blocks/core__media-text__deprecated-v7-image-fill-with-focal-point-selected.parsed.json
@@ -0,0 +1,33 @@
+[
+ {
+ "blockName": "core/media-text",
+ "attrs": {
+ "mediaType": "image",
+ "imageFill": true,
+ "focalPoint": {
+ "x": 0.84,
+ "y": 0.84
+ }
+ },
+ "innerBlocks": [
+ {
+ "blockName": "core/paragraph",
+ "attrs": {
+ "placeholder": "Content…",
+ "fontSize": "large"
+ },
+ "innerBlocks": [],
+ "innerHTML": "\n\t\t
My Content
\n\t\t",
+ "innerContent": [
+ "\n\t\t
My Content
\n\t\t"
+ ]
+ }
+ ],
+ "innerHTML": "\n
\n\t
\n\t\t \n\t
\n\t\t\n\t
\n
\n",
+ "innerContent": [
+ "\n
\n\t
\n\t\t \n\t
\n\t\t",
+ null,
+ "\n\t
\n
\n"
+ ]
+ }
+]
diff --git a/test/integration/fixtures/blocks/core__media-text__deprecated-v7-image-fill-with-focal-point-selected.serialized.html b/test/integration/fixtures/blocks/core__media-text__deprecated-v7-image-fill-with-focal-point-selected.serialized.html
new file mode 100644
index 0000000000000..4b001f4f27c8a
--- /dev/null
+++ b/test/integration/fixtures/blocks/core__media-text__deprecated-v7-image-fill-with-focal-point-selected.serialized.html
@@ -0,0 +1,5 @@
+
+
+
diff --git a/test/integration/fixtures/blocks/core__media-text__deprecated-v7.html b/test/integration/fixtures/blocks/core__media-text__deprecated-v7.html
new file mode 100644
index 0000000000000..92b4b4d275413
--- /dev/null
+++ b/test/integration/fixtures/blocks/core__media-text__deprecated-v7.html
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
diff --git a/test/integration/fixtures/blocks/core__media-text__deprecated-v7.json b/test/integration/fixtures/blocks/core__media-text__deprecated-v7.json
new file mode 100644
index 0000000000000..a6f0dff927874
--- /dev/null
+++ b/test/integration/fixtures/blocks/core__media-text__deprecated-v7.json
@@ -0,0 +1,30 @@
+[
+ {
+ "name": "core/media-text",
+ "isValid": true,
+ "attributes": {
+ "align": "none",
+ "mediaAlt": "My alt text",
+ "mediaPosition": "left",
+ "mediaType": "image",
+ "mediaWidth": 50,
+ "isStackedOnMobile": true,
+ "mediaUrl": "data:image/jpeg;base64,/9j/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCgsOCwkJDRENDg8QEBEQCgwSExIQEw8QEBD/yQALCAABAAEBAREA/8wABgAQEAX/2gAIAQEAAD8A0s8g/9k=",
+ "imageFill": true,
+ "useFeaturedImage": false
+ },
+ "innerBlocks": [
+ {
+ "name": "core/paragraph",
+ "isValid": true,
+ "attributes": {
+ "content": "My Content",
+ "dropCap": false,
+ "placeholder": "Content…",
+ "fontSize": "large"
+ },
+ "innerBlocks": []
+ }
+ ]
+ }
+]
diff --git a/test/integration/fixtures/blocks/core__media-text__deprecated-v7.parsed.json b/test/integration/fixtures/blocks/core__media-text__deprecated-v7.parsed.json
new file mode 100644
index 0000000000000..49b392d423138
--- /dev/null
+++ b/test/integration/fixtures/blocks/core__media-text__deprecated-v7.parsed.json
@@ -0,0 +1,29 @@
+[
+ {
+ "blockName": "core/media-text",
+ "attrs": {
+ "mediaType": "image",
+ "imageFill": true
+ },
+ "innerBlocks": [
+ {
+ "blockName": "core/paragraph",
+ "attrs": {
+ "placeholder": "Content…",
+ "fontSize": "large"
+ },
+ "innerBlocks": [],
+ "innerHTML": "\n\t\t
My Content
\n\t\t",
+ "innerContent": [
+ "\n\t\t
My Content
\n\t\t"
+ ]
+ }
+ ],
+ "innerHTML": "\n
\n\t
\n\t\t \n\t
\n\t\t\n\t
\n
\n",
+ "innerContent": [
+ "\n
\n\t
\n\t\t \n\t
\n\t\t",
+ null,
+ "\n\t
\n
\n"
+ ]
+ }
+]
diff --git a/test/integration/fixtures/blocks/core__media-text__deprecated-v7.serialized.html b/test/integration/fixtures/blocks/core__media-text__deprecated-v7.serialized.html
new file mode 100644
index 0000000000000..b44ebe1c4ee89
--- /dev/null
+++ b/test/integration/fixtures/blocks/core__media-text__deprecated-v7.serialized.html
@@ -0,0 +1,5 @@
+
+
+
diff --git a/test/integration/fixtures/blocks/core__media-text__image-fill-no-focal-point-selected.html b/test/integration/fixtures/blocks/core__media-text__image-fill-no-focal-point-selected.html
index 22a2a3e18f74f..30667e0dd24dc 100644
--- a/test/integration/fixtures/blocks/core__media-text__image-fill-no-focal-point-selected.html
+++ b/test/integration/fixtures/blocks/core__media-text__image-fill-no-focal-point-selected.html
@@ -1,9 +1,8 @@
-
-
-
+
+
+
+ alt="My alt text" style="object-position:50% 50%"/>
My Content
diff --git a/test/integration/fixtures/blocks/core__media-text__image-fill-no-focal-point-selected.json b/test/integration/fixtures/blocks/core__media-text__image-fill-no-focal-point-selected.json
index bf195f6fa1c95..bb57f08ad5cfa 100644
--- a/test/integration/fixtures/blocks/core__media-text__image-fill-no-focal-point-selected.json
+++ b/test/integration/fixtures/blocks/core__media-text__image-fill-no-focal-point-selected.json
@@ -6,11 +6,12 @@
"align": "wide",
"mediaAlt": "My alt text",
"mediaPosition": "left",
+ "mediaUrl": "data:image/jpeg;base64,/9j/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCgsOCwkJDRENDg8QEBEQCgwSExIQEw8QEBD/yQALCAABAAEBAREA/8wABgAQEAX/2gAIAQEAAD8A0s8g/9k=",
"mediaType": "image",
"mediaWidth": 50,
"isStackedOnMobile": true,
- "mediaUrl": "data:image/jpeg;base64,/9j/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCgsOCwkJDRENDg8QEBEQCgwSExIQEw8QEBD/yQALCAABAAEBAREA/8wABgAQEAX/2gAIAQEAAD8A0s8g/9k=",
- "imageFill": true
+ "imageFill": true,
+ "useFeaturedImage": false
},
"innerBlocks": [
{
diff --git a/test/integration/fixtures/blocks/core__media-text__image-fill-no-focal-point-selected.parsed.json b/test/integration/fixtures/blocks/core__media-text__image-fill-no-focal-point-selected.parsed.json
index 2e878c98a18a8..674b3724af8e8 100644
--- a/test/integration/fixtures/blocks/core__media-text__image-fill-no-focal-point-selected.parsed.json
+++ b/test/integration/fixtures/blocks/core__media-text__image-fill-no-focal-point-selected.parsed.json
@@ -2,6 +2,7 @@
{
"blockName": "core/media-text",
"attrs": {
+ "align": "wide",
"mediaType": "image",
"imageFill": true
},
@@ -19,9 +20,9 @@
]
}
],
- "innerHTML": "\n
\n\t
\n\t\t \n\t
\n\t\t\n\t
\n
\n",
+ "innerHTML": "\n
\n\t
\n\t\t \n\t
\n\t\t\n\t
\n
\n",
"innerContent": [
- "\n
\n\t
\n\t\t \n\t
\n\t\t",
+ "\n
\n\t
\n\t\t \n\t
\n\t\t",
null,
"\n\t
\n
\n"
]
diff --git a/test/integration/fixtures/blocks/core__media-text__image-fill-no-focal-point-selected.serialized.html b/test/integration/fixtures/blocks/core__media-text__image-fill-no-focal-point-selected.serialized.html
index 40382e884f618..b9d5e14f90277 100644
--- a/test/integration/fixtures/blocks/core__media-text__image-fill-no-focal-point-selected.serialized.html
+++ b/test/integration/fixtures/blocks/core__media-text__image-fill-no-focal-point-selected.serialized.html
@@ -1,5 +1,5 @@
-
+
diff --git a/test/integration/fixtures/blocks/core__media-text__image-fill-with-focal-point-selected.html b/test/integration/fixtures/blocks/core__media-text__image-fill-with-focal-point-selected.html
index 47a0f0c126fa7..60e2cc7be572d 100644
--- a/test/integration/fixtures/blocks/core__media-text__image-fill-with-focal-point-selected.html
+++ b/test/integration/fixtures/blocks/core__media-text__image-fill-with-focal-point-selected.html
@@ -1,9 +1,8 @@
-
-
-
+
+
+
+ alt="My alt text" style="object-position:84% 84%" />
My Content
diff --git a/test/integration/fixtures/blocks/core__media-text__image-fill-with-focal-point-selected.json b/test/integration/fixtures/blocks/core__media-text__image-fill-with-focal-point-selected.json
index 986e049099541..0de71c867457e 100644
--- a/test/integration/fixtures/blocks/core__media-text__image-fill-with-focal-point-selected.json
+++ b/test/integration/fixtures/blocks/core__media-text__image-fill-with-focal-point-selected.json
@@ -6,15 +6,16 @@
"align": "wide",
"mediaAlt": "My alt text",
"mediaPosition": "left",
+ "mediaUrl": "data:image/jpeg;base64,/9j/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCgsOCwkJDRENDg8QEBEQCgwSExIQEw8QEBD/yQALCAABAAEBAREA/8wABgAQEAX/2gAIAQEAAD8A0s8g/9k=",
"mediaType": "image",
"mediaWidth": 50,
"isStackedOnMobile": true,
- "mediaUrl": "data:image/jpeg;base64,/9j/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCgsOCwkJDRENDg8QEBEQCgwSExIQEw8QEBD/yQALCAABAAEBAREA/8wABgAQEAX/2gAIAQEAAD8A0s8g/9k=",
"imageFill": true,
"focalPoint": {
"x": 0.84,
"y": 0.84
- }
+ },
+ "useFeaturedImage": false
},
"innerBlocks": [
{
diff --git a/test/integration/fixtures/blocks/core__media-text__image-fill-with-focal-point-selected.parsed.json b/test/integration/fixtures/blocks/core__media-text__image-fill-with-focal-point-selected.parsed.json
index 175fbad27927b..92bd57443a1c3 100644
--- a/test/integration/fixtures/blocks/core__media-text__image-fill-with-focal-point-selected.parsed.json
+++ b/test/integration/fixtures/blocks/core__media-text__image-fill-with-focal-point-selected.parsed.json
@@ -2,6 +2,7 @@
{
"blockName": "core/media-text",
"attrs": {
+ "align": "wide",
"mediaType": "image",
"imageFill": true,
"focalPoint": {
@@ -23,9 +24,9 @@
]
}
],
- "innerHTML": "\n
\n\t
\n\t\t \n\t
\n\t\t\n\t
\n
\n",
+ "innerHTML": "\n
\n\t
\n\t\t \n\t
\n\t\t\n\t
\n
\n",
"innerContent": [
- "\n
\n\t
\n\t\t \n\t
\n\t\t",
+ "\n
\n\t
\n\t\t \n\t
\n\t\t",
null,
"\n\t
\n
\n"
]
diff --git a/test/integration/fixtures/blocks/core__media-text__image-fill-with-focal-point-selected.serialized.html b/test/integration/fixtures/blocks/core__media-text__image-fill-with-focal-point-selected.serialized.html
index 9445d0ad259b2..4b001f4f27c8a 100644
--- a/test/integration/fixtures/blocks/core__media-text__image-fill-with-focal-point-selected.serialized.html
+++ b/test/integration/fixtures/blocks/core__media-text__image-fill-with-focal-point-selected.serialized.html
@@ -1,5 +1,5 @@
-
+
diff --git a/tsconfig.json b/tsconfig.json
index cf986ddbee72b..6be31e9b61bef 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -35,6 +35,7 @@
{ "path": "packages/is-shallow-equal" },
{ "path": "packages/keycodes" },
{ "path": "packages/lazy-import" },
+ { "path": "packages/media-utils" },
{ "path": "packages/notices" },
{ "path": "packages/plugins" },
{ "path": "packages/prettier-config" },