From a194105533f76b8de124a8327778a6de38a4a5b6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Andr=C3=A9?= <583546+oandregal@users.noreply.github.com>
Date: Tue, 8 Mar 2022 11:24:23 +0100
Subject: [PATCH 1/6] Add settings attribute via hook
---
docs/reference-guides/core-blocks.md | 2 +-
packages/block-editor/src/hooks/index.js | 1 +
packages/block-editor/src/hooks/settings.js | 32 +++++++++++++
.../block-editor/src/hooks/test/settings.js | 48 +++++++++++++++++++
4 files changed, 82 insertions(+), 1 deletion(-)
create mode 100644 packages/block-editor/src/hooks/settings.js
create mode 100644 packages/block-editor/src/hooks/test/settings.js
diff --git a/docs/reference-guides/core-blocks.md b/docs/reference-guides/core-blocks.md
index 08367cb90f925..796d68c18b6d4 100644
--- a/docs/reference-guides/core-blocks.md
+++ b/docs/reference-guides/core-blocks.md
@@ -275,7 +275,7 @@ Gather blocks in a layout container. ([Source](https://github.com/WordPress/gute
- **Name:** core/group
- **Category:** design
-- **Supports:** align (full, wide), anchor, color (background, gradients, link, text), spacing (blockGap, margin, padding), typography (fontSize, lineHeight), ~~html~~
+- **Supports:** align (full, wide), anchor, color (background, gradients, link, text), settings, spacing (blockGap, margin, padding), typography (fontSize, lineHeight), ~~html~~
- **Attributes:** tagName, templateLock
## Heading
diff --git a/packages/block-editor/src/hooks/index.js b/packages/block-editor/src/hooks/index.js
index b76c06ce9bf42..36c3181092a17 100644
--- a/packages/block-editor/src/hooks/index.js
+++ b/packages/block-editor/src/hooks/index.js
@@ -8,6 +8,7 @@ import './anchor';
import './custom-class-name';
import './generated-class-name';
import './style';
+import './settings';
import './color';
import './duotone';
import './font-size';
diff --git a/packages/block-editor/src/hooks/settings.js b/packages/block-editor/src/hooks/settings.js
new file mode 100644
index 0000000000000..8e8f5bd9b2919
--- /dev/null
+++ b/packages/block-editor/src/hooks/settings.js
@@ -0,0 +1,32 @@
+/**
+ * WordPress dependencies
+ */
+import { addFilter } from '@wordpress/hooks';
+import { hasBlockSupport } from '@wordpress/blocks';
+
+const hasSettingsSupport = ( blockType ) =>
+ hasBlockSupport( blockType, 'settings', true );
+
+function addAttribute( settings ) {
+ if ( ! hasSettingsSupport( settings ) ) {
+ return settings;
+ }
+
+ // Allow blocks to specify their own attribute definition with default values if needed.
+ if ( ! settings?.attributes?.settings ) {
+ settings.attributes = {
+ ...settings.attributes,
+ settings: {
+ type: 'object',
+ },
+ };
+ }
+
+ return settings;
+}
+
+addFilter(
+ 'blocks.registerBlockType',
+ 'core/settings/addAttribute',
+ addAttribute
+);
diff --git a/packages/block-editor/src/hooks/test/settings.js b/packages/block-editor/src/hooks/test/settings.js
new file mode 100644
index 0000000000000..7e3e096d2b728
--- /dev/null
+++ b/packages/block-editor/src/hooks/test/settings.js
@@ -0,0 +1,48 @@
+/**
+ * WordPress dependencies
+ */
+import { applyFilters } from '@wordpress/hooks';
+
+/**
+ * Internal dependencies
+ */
+import '../settings';
+
+describe( 'with settings', () => {
+ const blockSettings = {
+ save: () =>
,
+ category: 'text',
+ title: 'block title',
+ };
+
+ describe( 'addAttribute', () => {
+ const addAttribute = applyFilters.bind(
+ null,
+ 'blocks.registerBlockType'
+ );
+
+ it( 'does not have settings att if settings block support is not enabled', () => {
+ const settings = addAttribute( {
+ ...blockSettings,
+ supports: {
+ settings: false,
+ },
+ } );
+
+ expect( settings.attributes ).toBe( undefined );
+ } );
+
+ it( 'has settings att if settings block supports is enabled', () => {
+ const settings = addAttribute( {
+ ...blockSettings,
+ supports: {
+ settings: true,
+ },
+ } );
+
+ expect( settings.attributes ).toStrictEqual( {
+ settings: { type: 'object' },
+ } );
+ } );
+ } );
+} );
From 6f758391f8e595d2c8fbedbba038445ee8a3ce8b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Andr=C3=A9?= <583546+oandregal@users.noreply.github.com>
Date: Tue, 8 Mar 2022 12:35:14 +0100
Subject: [PATCH 2/6] useSetting: take the setting from the block instance
---
.../src/components/use-setting/index.js | 17 +++++++++++++++--
1 file changed, 15 insertions(+), 2 deletions(-)
diff --git a/packages/block-editor/src/components/use-setting/index.js b/packages/block-editor/src/components/use-setting/index.js
index d96546dae73f4..db6f1e79507af 100644
--- a/packages/block-editor/src/components/use-setting/index.js
+++ b/packages/block-editor/src/components/use-setting/index.js
@@ -102,7 +102,7 @@ const removeCustomPrefixes = ( path ) => {
* ```
*/
export default function useSetting( path ) {
- const { name: blockName } = useBlockEditContext();
+ const { name: blockName, clientId } = useBlockEditContext();
const setting = useSelect(
( select ) => {
@@ -115,13 +115,26 @@ export default function useSetting( path ) {
}
const settings = select( blockEditorStore ).getSettings();
+ // 0 - Use settings for this block instance, if there's any.
+ // Also, look up in the block hierarchy.
+ // todo: only check if the block type has support for settings to minimize the queries we make
+ // todo: how do we provide i18n for the presets defined by block instances? In PHP, they already do i18n.
+ // todo: the presets defined in a block instance are "custom" ones;
+ // remove the need for users to provide the custom key.
+ const blockAtts = select( blockEditorStore ).getBlockAttributes(
+ clientId
+ );
+
// 1 - Use __experimental features, if available.
// We cascade to the all value if the block one is not available.
const normalizedPath = removeCustomPrefixes( path );
const defaultsPath = `__experimentalFeatures.${ normalizedPath }`;
const blockPath = `__experimentalFeatures.blocks.${ blockName }.${ normalizedPath }`;
+ const blockInstancePath = `settings.${ normalizedPath }`;
const experimentalFeaturesResult =
- get( settings, blockPath ) ?? get( settings, defaultsPath );
+ get( blockAtts, blockInstancePath ) ??
+ get( settings, blockPath ) ??
+ get( settings, defaultsPath );
if ( experimentalFeaturesResult !== undefined ) {
if ( PATHS_WITH_MERGE[ normalizedPath ] ) {
From 05f266c8cc225ba9f0db62a3146d847934b1e8a4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Andr=C3=A9?= <583546+oandregal@users.noreply.github.com>
Date: Tue, 8 Mar 2022 12:35:32 +0100
Subject: [PATCH 3/6] Test: enable settings for the group block
---
packages/block-library/src/group/block.json | 1 +
1 file changed, 1 insertion(+)
diff --git a/packages/block-library/src/group/block.json b/packages/block-library/src/group/block.json
index 2e3a99f78ae3c..e34579df4d590 100644
--- a/packages/block-library/src/group/block.json
+++ b/packages/block-library/src/group/block.json
@@ -18,6 +18,7 @@
}
},
"supports": {
+ "settings": true,
"align": [ "wide", "full" ],
"anchor": true,
"html": false,
From 322e113476b107d13a8b1801830d0bd836a5e50f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Andr=C3=A9?= <583546+oandregal@users.noreply.github.com>
Date: Mon, 25 Apr 2022 11:00:10 +0200
Subject: [PATCH 4/6] Update packages/block-editor/src/hooks/settings.js
Co-authored-by: Miguel Fonseca
---
packages/block-editor/src/hooks/settings.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/packages/block-editor/src/hooks/settings.js b/packages/block-editor/src/hooks/settings.js
index 8e8f5bd9b2919..e1f393be2d335 100644
--- a/packages/block-editor/src/hooks/settings.js
+++ b/packages/block-editor/src/hooks/settings.js
@@ -5,7 +5,7 @@ import { addFilter } from '@wordpress/hooks';
import { hasBlockSupport } from '@wordpress/blocks';
const hasSettingsSupport = ( blockType ) =>
- hasBlockSupport( blockType, 'settings', true );
+ hasBlockSupport( blockType, 'settings', false );
function addAttribute( settings ) {
if ( ! hasSettingsSupport( settings ) ) {
From f52967dbb063f36a6c0d55d36c01a4acbe727059 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Andr=C3=A9?= <583546+oandregal@users.noreply.github.com>
Date: Mon, 25 Apr 2022 12:40:04 +0200
Subject: [PATCH 5/6] Add support for hierarchical block instance look up
---
packages/block-editor/README.md | 6 +-
.../src/components/use-setting/index.js | 87 +++++++++++--------
2 files changed, 57 insertions(+), 36 deletions(-)
diff --git a/packages/block-editor/README.md b/packages/block-editor/README.md
index bb4dc1725bc3f..1ac284320078a 100644
--- a/packages/block-editor/README.md
+++ b/packages/block-editor/README.md
@@ -762,8 +762,10 @@ _Parameters_
### useSetting
-Hook that retrieves the editor setting.
-It works with nested objects using by finding the value at path.
+Hook that retrieves the given setting for the block instance in use.
+
+It looks up the settings first in the block instance hierarchy.
+If none is found, it'll look it up in the block editor store.
_Usage_
diff --git a/packages/block-editor/src/components/use-setting/index.js b/packages/block-editor/src/components/use-setting/index.js
index db6f1e79507af..bc8a496c9536d 100644
--- a/packages/block-editor/src/components/use-setting/index.js
+++ b/packages/block-editor/src/components/use-setting/index.js
@@ -7,7 +7,10 @@ import { get } from 'lodash';
* WordPress dependencies
*/
import { useSelect } from '@wordpress/data';
-import { __EXPERIMENTAL_PATHS_WITH_MERGE as PATHS_WITH_MERGE } from '@wordpress/blocks';
+import {
+ __EXPERIMENTAL_PATHS_WITH_MERGE as PATHS_WITH_MERGE,
+ hasBlockSupport,
+} from '@wordpress/blocks';
/**
* Internal dependencies
@@ -91,8 +94,10 @@ const removeCustomPrefixes = ( path ) => {
};
/**
- * Hook that retrieves the editor setting.
- * It works with nested objects using by finding the value at path.
+ * Hook that retrieves the given setting for the block instance in use.
+ *
+ * It looks up the settings first in the block instance hierarchy.
+ * If none is found, it'll look it up in the block editor store.
*
* @param {string} path The path to the setting.
* @return {any} Returns the value defined for the setting.
@@ -113,41 +118,55 @@ export default function useSetting( path ) {
);
return undefined;
}
- const settings = select( blockEditorStore ).getSettings();
- // 0 - Use settings for this block instance, if there's any.
- // Also, look up in the block hierarchy.
- // todo: only check if the block type has support for settings to minimize the queries we make
- // todo: how do we provide i18n for the presets defined by block instances? In PHP, they already do i18n.
- // todo: the presets defined in a block instance are "custom" ones;
- // remove the need for users to provide the custom key.
- const blockAtts = select( blockEditorStore ).getBlockAttributes(
- clientId
- );
-
- // 1 - Use __experimental features, if available.
- // We cascade to the all value if the block one is not available.
+ let result;
const normalizedPath = removeCustomPrefixes( path );
- const defaultsPath = `__experimentalFeatures.${ normalizedPath }`;
- const blockPath = `__experimentalFeatures.blocks.${ blockName }.${ normalizedPath }`;
- const blockInstancePath = `settings.${ normalizedPath }`;
- const experimentalFeaturesResult =
- get( blockAtts, blockInstancePath ) ??
- get( settings, blockPath ) ??
- get( settings, defaultsPath );
-
- if ( experimentalFeaturesResult !== undefined ) {
+
+ // 1. Take settings from the block instance or its ancestors.
+ const candidates = [
+ ...select( blockEditorStore ).getBlockParents( clientId ),
+ clientId, // The current block is added last, so it overwrites any ancestor.
+ ];
+ candidates.forEach( ( candidateClientId ) => {
+ const candidateBlockName = select(
+ blockEditorStore
+ ).getBlockName( candidateClientId );
+ if (
+ hasBlockSupport( candidateBlockName, 'settings', false )
+ ) {
+ const candidateAtts = select(
+ blockEditorStore
+ ).getBlockAttributes( candidateClientId );
+ const candidateResult =
+ get(
+ candidateAtts,
+ `settings.blocks.${ blockName }.${ normalizedPath }`
+ ) ??
+ get( candidateAtts, `settings.${ normalizedPath }` );
+ if ( candidateResult !== undefined ) {
+ result = candidateResult;
+ }
+ }
+ } );
+
+ // 2. Fall back to the settings from the block editor store (__experimentalFeatures).
+ const settings = select( blockEditorStore ).getSettings();
+ if ( result === undefined ) {
+ const defaultsPath = `__experimentalFeatures.${ normalizedPath }`;
+ const blockPath = `__experimentalFeatures.blocks.${ blockName }.${ normalizedPath }`;
+ result =
+ get( settings, blockPath ) ?? get( settings, defaultsPath );
+ }
+
+ // Return if the setting was found in either the block instance or the store.
+ if ( result !== undefined ) {
if ( PATHS_WITH_MERGE[ normalizedPath ] ) {
- return (
- experimentalFeaturesResult.custom ??
- experimentalFeaturesResult.theme ??
- experimentalFeaturesResult.default
- );
+ return result.custom ?? result.theme ?? result.default;
}
- return experimentalFeaturesResult;
+ return result;
}
- // 2 - Use deprecated settings, otherwise.
+ // 3. Otherwise, use deprecated settings.
const deprecatedSettingsValue = deprecatedFlags[ normalizedPath ]
? deprecatedFlags[ normalizedPath ]( settings )
: undefined;
@@ -155,13 +174,13 @@ export default function useSetting( path ) {
return deprecatedSettingsValue;
}
- // 3 - Fall back for typography.dropCap:
+ // 4. Fallback for typography.dropCap:
// This is only necessary to support typography.dropCap.
// when __experimentalFeatures are not present (core without plugin).
// To remove when __experimentalFeatures are ported to core.
return normalizedPath === 'typography.dropCap' ? true : undefined;
},
- [ blockName, path ]
+ [ blockName, clientId, path ]
);
return setting;
From c1a2762546312a45d3886056b361fc3f1a0aa7f7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Andr=C3=A9?= <583546+oandregal@users.noreply.github.com>
Date: Fri, 29 Apr 2022 11:05:41 +0200
Subject: [PATCH 6/6] Rename settings support to __experimentalSettings
---
docs/reference-guides/core-blocks.md | 2 +-
packages/block-editor/src/components/use-setting/index.js | 6 +++++-
packages/block-editor/src/hooks/settings.js | 2 +-
packages/block-editor/src/hooks/test/settings.js | 4 ++--
packages/block-library/src/group/block.json | 2 +-
5 files changed, 10 insertions(+), 6 deletions(-)
diff --git a/docs/reference-guides/core-blocks.md b/docs/reference-guides/core-blocks.md
index 796d68c18b6d4..08367cb90f925 100644
--- a/docs/reference-guides/core-blocks.md
+++ b/docs/reference-guides/core-blocks.md
@@ -275,7 +275,7 @@ Gather blocks in a layout container. ([Source](https://github.com/WordPress/gute
- **Name:** core/group
- **Category:** design
-- **Supports:** align (full, wide), anchor, color (background, gradients, link, text), settings, spacing (blockGap, margin, padding), typography (fontSize, lineHeight), ~~html~~
+- **Supports:** align (full, wide), anchor, color (background, gradients, link, text), spacing (blockGap, margin, padding), typography (fontSize, lineHeight), ~~html~~
- **Attributes:** tagName, templateLock
## Heading
diff --git a/packages/block-editor/src/components/use-setting/index.js b/packages/block-editor/src/components/use-setting/index.js
index bc8a496c9536d..a1aba3e3faf65 100644
--- a/packages/block-editor/src/components/use-setting/index.js
+++ b/packages/block-editor/src/components/use-setting/index.js
@@ -132,7 +132,11 @@ export default function useSetting( path ) {
blockEditorStore
).getBlockName( candidateClientId );
if (
- hasBlockSupport( candidateBlockName, 'settings', false )
+ hasBlockSupport(
+ candidateBlockName,
+ '__experimentalSettings',
+ false
+ )
) {
const candidateAtts = select(
blockEditorStore
diff --git a/packages/block-editor/src/hooks/settings.js b/packages/block-editor/src/hooks/settings.js
index e1f393be2d335..a778c1605cbc4 100644
--- a/packages/block-editor/src/hooks/settings.js
+++ b/packages/block-editor/src/hooks/settings.js
@@ -5,7 +5,7 @@ import { addFilter } from '@wordpress/hooks';
import { hasBlockSupport } from '@wordpress/blocks';
const hasSettingsSupport = ( blockType ) =>
- hasBlockSupport( blockType, 'settings', false );
+ hasBlockSupport( blockType, '__experimentalSettings', false );
function addAttribute( settings ) {
if ( ! hasSettingsSupport( settings ) ) {
diff --git a/packages/block-editor/src/hooks/test/settings.js b/packages/block-editor/src/hooks/test/settings.js
index 7e3e096d2b728..681c635b98271 100644
--- a/packages/block-editor/src/hooks/test/settings.js
+++ b/packages/block-editor/src/hooks/test/settings.js
@@ -25,7 +25,7 @@ describe( 'with settings', () => {
const settings = addAttribute( {
...blockSettings,
supports: {
- settings: false,
+ __experimentalSettings: false,
},
} );
@@ -36,7 +36,7 @@ describe( 'with settings', () => {
const settings = addAttribute( {
...blockSettings,
supports: {
- settings: true,
+ __experimentalSettings: true,
},
} );
diff --git a/packages/block-library/src/group/block.json b/packages/block-library/src/group/block.json
index e34579df4d590..3e89f14dc938b 100644
--- a/packages/block-library/src/group/block.json
+++ b/packages/block-library/src/group/block.json
@@ -18,7 +18,7 @@
}
},
"supports": {
- "settings": true,
+ "__experimentalSettings": true,
"align": [ "wide", "full" ],
"anchor": true,
"html": false,