Skip to content

Commit

Permalink
Merge branch 'trunk' into custom-gradient-picker-margin
Browse files Browse the repository at this point in the history
  • Loading branch information
mirka committed Feb 6, 2024
2 parents 381db02 + 6d97038 commit 2db4c3e
Show file tree
Hide file tree
Showing 52 changed files with 1,939 additions and 994 deletions.
48 changes: 23 additions & 25 deletions docs/getting-started/fundamentals/block-in-the-editor.md
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
# The block in the Editor

The Block Editor is a React Single Page Application (SPA) and every block in the editor is displayed through a React component defined in the `edit` property of the settings object used to [register the block on the client](https://developer.wordpress.org/block-editor/getting-started/fundamentals/registration-of-a-block/#registration-of-the-block-with-javascript-client-side).
The Block Editor is a React Single Page Application (SPA). Every block in the Editor is displayed through a React component defined in the `edit` property of the settings object used to [register the block](https://developer.wordpress.org/block-editor/getting-started/fundamentals/registration-of-a-block/#registration-of-the-block-with-javascript-client-side) on the client.

The `props` object received by the block's `Edit` React component includes:

- [`attributes`](https://developer.wordpress.org/block-editor/reference-guides/block-api/block-edit-save/#attributes) - attributes object
- [`setAttributes`](https://developer.wordpress.org/block-editor/reference-guides/block-api/block-edit-save/#setattributes) - method to update the attributes object
- [`isSelected`](https://developer.wordpress.org/block-editor/reference-guides/block-api/block-edit-save/#isselected) - boolean that communicates whether the block is currently selected
- **[`attributes`](https://developer.wordpress.org/block-editor/reference-guides/block-api/block-edit-save/#attributes):** An object of all the block's attributes.
- **[`setAttributes`](https://developer.wordpress.org/block-editor/reference-guides/block-api/block-edit-save/#setattributes):** A method to update the attributes object.
- **[`isSelected`](https://developer.wordpress.org/block-editor/reference-guides/block-api/block-edit-save/#isselected):** A boolean value that communicates whether the block is currently selected

WordPress provides many built-in standard components that can be used to define the interface of the block in the editor. These built-in components are available via packages such as [`@wordpress/components`](https://developer.wordpress.org/block-editor/reference-guides/packages/packages-components/) and [`@wordpress/block-editor`](https://developer.wordpress.org/block-editor/reference-guides/packages/packages-block-editor/).
WordPress provides many built-in standard components that can be used to define the block interface in the Editor. These built-in components are available via packages such as [`@wordpress/components`](https://developer.wordpress.org/block-editor/reference-guides/packages/packages-components/) and [`@wordpress/block-editor`](https://developer.wordpress.org/block-editor/reference-guides/packages/packages-block-editor/).

<div class="callout">
The WordPress Gutenberg project uses <a href="https://wordpress.github.io/gutenberg/?path=/docs/docs-introduction--page">Storybook</a> to document the user interface components that are available in WordPress packages.
The WordPress Gutenberg project uses <a href="https://wordpress.github.io/gutenberg/?path=/docs/docs-introduction--page">Storybook</a> to document the user interface components that are available in WordPress packages.
</div>

Custom settings controls for the block in the Block Toolbar or the Settings Sidebar can also be defined through this `Edit` React component via built-in components such as:
Expand All @@ -28,34 +28,35 @@ The package [`@wordpress/components`](https://developer.wordpress.org/block-edit
- [`ToggleControl`](https://wordpress.github.io/gutenberg/?path=/docs/components-togglecontrol--docs)
- [`ExternalLink`](https://wordpress.github.io/gutenberg/?path=/docs/components-externallink--docs)

The package [`@wordpress/block-editor`](https://developer.wordpress.org/block-editor/reference-guides/packages/packages-block-editor/) includes a library of components and hooks for the Block Editor, including those to define custom settings controls for the block in the Editor. Some of the components most commonly used from this package are:
The package [`@wordpress/block-editor`](https://developer.wordpress.org/block-editor/reference-guides/packages/packages-block-editor/) includes a library of components and hooks for the Block Editor, including those to define custom settings controls for the block. Some of the components most commonly used from this package are:

- [`RichText`](https://github.com/WordPress/gutenberg/blob/HEAD/packages/block-editor/src/components/rich-text/README.md)
- [`BlockControls`](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-editor/src/components/block-controls)
- [`InspectorControls`](https://github.com/WordPress/gutenberg/blob/HEAD/packages/block-editor/src/components/inspector-controls/README.md)
- [`InnerBlocks`](https://github.com/WordPress/gutenberg/blob/HEAD/packages/block-editor/src/components/inner-blocks/README.md)
- `PanelColorSettings` or `ColorPalette`

<div class="callout callout-tip">
The package <a href="https://developer.wordpress.org/block-editor/reference-guides/packages/packages-block-editor/"><code>@wordpress/block-editor</code></a> also provide the tools to create and use standalone block editors.
<div class="callout callout-info">
The package <a href="https://developer.wordpress.org/block-editor/reference-guides/packages/packages-block-editor/"><code>@wordpress/block-editor</code></a> also provides the tools to create and use standalone block editors.
</div>

A good workflow when using a component for the Block Editor is:

- Import the component from a WordPress package
- Add the corresponding code for the component to your project in JSX format
- Most built-in components will be used to set [block attributes](https://developer.wordpress.org/block-editor/getting-started/fundamentals/block-json/#using-attributes-to-store-block-data), so define any necessary attributes in `block.json` and create event handlers to update those attributes with `setAttributes` in your component
- If needed, adapt the code to be serialized and stored in the database
- Import the component from a WordPress package.
- Add the corresponding code for the component to your project in JSX format.
- Most built-in components will be used to set [block attributes](https://developer.wordpress.org/block-editor/getting-started/fundamentals/block-json/#using-attributes-to-store-block-data), so define any necessary attributes in `block.json` and create event handlers to update those attributes with `setAttributes` in your component.
- Adapt the code to be serialized and stored in the database if needed.

## Block Controls: Block Toolbar and Settings Sidebar

To simplify block customization and ensure a consistent experience for users, there are a number of built-in UI patterns to help generate the editor preview.
To simplify block customization and ensure a consistent user experience, there are several built-in UI patterns to help generate the Editor preview of a block.

The image below details the Block Toolbar and the Settings Sidebar of a selected Paragraph block.

![Diagram showing the Block Toolbar and the Settings Sidebar when a Paragraph block is selected](https://developer.wordpress.org/files/2023/12/block-toolbar-settings-sidebar.png)

### Block Toolbar

When the user selects a block, a number of control buttons may be shown in a toolbar above the selected block. Some of these block-level controls may be included automatically but you can also customize the toolbar to include controls specific to your block type. If the return value of your block type's `edit` function includes a `BlockControls` element, those controls will be shown in the selected block's toolbar.
When the user selects a block, a number of control buttons may be shown in a toolbar above the selected block. Some of these block-level controls may be included automatically, but you can also customize the toolbar to include controls specific to your block type. If the return value of your block type's `Edit` function includes a `BlockControls` element, those controls will be shown in the selected block's toolbar.

```jsx
export default function Edit( { className, attributes: attr, setAttributes } ) {
Expand Down Expand Up @@ -95,18 +96,15 @@ export default function Edit( { className, attributes: attr, setAttributes } ) {

_See the [full block example](https://github.com/WordPress/block-development-examples/tree/trunk/plugins/block-toolbar-ab967f) of the [code above](https://github.com/WordPress/block-development-examples/blob/trunk/plugins/block-toolbar-ab967f/src/edit.js)._


Note that `BlockControls` is only visible when the block is currently selected and in visual editing mode. `BlockControls` are not shown when editing a block in HTML editing mode.

### Settings Sidebar

The Settings Sidebar is used to display less-often-used settings or settings that require more screen space. The Settings Sidebar should be used for **block-level settings only**.
The Settings Sidebar is used to display less-often-used settings or those that require more screen space. The Settings Sidebar should be used for **block-level settings only** and is shown when a block is selected.

If you have settings that affects only selected content inside a block (example: the "bold" setting for selected text inside a paragraph): **do not place it inside the Settings Sidebar**. The Settings Sidebar is displayed even when editing a block in HTML mode, so it should only contain block-level settings.
If a setting only affects selected content inside a block, such as "bolding" text, **do not place the setting inside the Settings Sidebar**. Use a toolbar instead. The Settings Sidebar is displayed even when editing a block in HTML mode, so it should only contain block-level settings.

The Block Tab is shown in place of the Document Tab when a block is selected.

Similar to rendering a toolbar, if you include an `InspectorControls` element in the return value of your block type's `edit` function, those controls will be shown in the Settings Sidebar region.
Similar to rendering a toolbar, if you include an `InspectorControls` component in the `return` value of your block type's `Edit` function, those controls will be shown in the Settings Sidebar region.

```jsx
export default function Edit( { attributes, setAttributes } ) {
Expand Down Expand Up @@ -154,16 +152,16 @@ export default function Edit( { attributes, setAttributes } ) {
```
_See the [full block example](https://github.com/WordPress/block-development-examples/tree/trunk/plugins/settings-sidebar-82c525) of the [code above](https://github.com/WordPress/block-development-examples/blob/trunk/plugins/settings-sidebar-82c525/src/edit.js)._

Block controls rendered in both the toolbar and sidebar will also be used when multiple blocks of the same type are selected.
Block controls rendered in both the toolbar and sidebar will also be available when multiple blocks of the same type are selected.

<div class="callout callout-note">
For common customization settings including color, border, spacing customization and more, you can rely on <a href="https://developer.wordpress.org/block-editor/getting-started/fundamentals/block-json/#enable-ui-settings-panels-for-the-block-with-supports">block supports</a> to provide the same functionality in a more efficient way.
For common customization settings, including color, border, spacing, and more, you can rely on <a href="https://developer.wordpress.org/block-editor/getting-started/fundamentals/block-json/#enable-ui-settings-panels-for-the-block-with-supports">block supports</a> instead of a custom solution. Block supports provide a consistent UI with the same functionality as other Core blocks.
</div>

## Additional resources

- [Storybook for WordPress components](https://wordpress.github.io/gutenberg/?path=/docs/docs-introduction--page)
- [@wordpress/block-editor](https://developer.wordpress.org/block-editor/reference-guides/packages/packages-block-editor/)
- [@wordpress/components](https://developer.wordpress.org/block-editor/reference-guides/packages/packages-components/)
- [`Inspector Controls`](https://github.com/WordPress/gutenberg/blob/HEAD/packages/block-editor/src/components/inspector-controls/README.md)
- [`InspectorControls`](https://github.com/WordPress/gutenberg/blob/HEAD/packages/block-editor/src/components/inspector-controls/README.md)
- [`BlockControls`](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-editor/src/components/block-controls)
24 changes: 20 additions & 4 deletions lib/compat/wordpress-6.5/block-bindings/block-bindings.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,10 @@
*
* @since 6.5.0
*
* @param string $source_name The name of the source.
* @param array $source_properties {
* @param string $source_name The name of the source. It must be a string containing a namespace prefix, i.e.
* `my-plugin/my-custom-source`. It must only contain lowercase alphanumeric
* characters, the forward slash `/` and dashes.
* @param array $source_properties {
* The array of arguments that are used to register a source.
*
* @type string $label The label of the source.
Expand All @@ -39,7 +41,7 @@
* @return array|false Source when the registration was successful, or `false` on failure.
*/
if ( ! function_exists( 'register_block_bindings_source' ) ) {
function register_block_bindings_source( $source_name, array $source_properties ) {
function register_block_bindings_source( string $source_name, array $source_properties ) {
return WP_Block_Bindings_Registry::get_instance()->register( $source_name, $source_properties );
}
}
Expand All @@ -53,7 +55,7 @@ function register_block_bindings_source( $source_name, array $source_properties
* @return array|false The unregistred block bindings source on success and `false` otherwise.
*/
if ( ! function_exists( 'unregister_block_bindings_source' ) ) {
function unregister_block_bindings_source( $source_name ) {
function unregister_block_bindings_source( string $source_name ) {
return WP_Block_Bindings_Registry::get_instance()->unregister( $source_name );
}
}
Expand All @@ -70,3 +72,17 @@ function get_all_registered_block_bindings_sources() {
return WP_Block_Bindings_Registry::get_instance()->get_all_registered();
}
}

/**
* Retrieves a registered block bindings source.
*
* @since 6.5.0
*
* @param string $source_name The name of the source.
* @return array|null The registered block bindings source, or `null` if it is not registered.
*/
if ( ! function_exists( 'get_block_bindings_source' ) ) {
function get_block_bindings_source( string $source_name ) {
return WP_Block_Bindings_Registry::get_instance()->get_registered( $source_name );
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,9 @@ final class WP_Block_Bindings_Registry {
*
* @since 6.5.0
*
* @param string $source_name The name of the source.
* @param string $source_name The name of the source. It must be a string containing a namespace prefix, i.e.
* `my-plugin/my-custom-source`. It must only contain lowercase alphanumeric
* characters, the forward slash `/` and dashes.
* @param array $source_properties {
* The array of arguments that are used to register a source.
*
Expand All @@ -57,13 +59,13 @@ final class WP_Block_Bindings_Registry {
* used to look up the override value,
* i.e. {"key": "foo"}.
* - @param WP_Block $block_instance The block instance.
* - @param string $attribute_name The name of an attribute .
* - @param string $attribute_name The name of the target attribute .
* The callback has a mixed return type; it may return a string to override
* the block's original value, null, false to remove an attribute, etc.
* }
* @return array|false Source when the registration was successful, or `false` on failure.
*/
public function register( $source_name, array $source_properties ) {
public function register( string $source_name, array $source_properties ) {
if ( ! is_string( $source_name ) ) {
_doing_it_wrong(
__METHOD__,
Expand Down Expand Up @@ -120,7 +122,7 @@ public function register( $source_name, array $source_properties ) {
* @param string $source_name Block bindings source name including namespace.
* @return array|false The unregistred block bindings source on success and `false` otherwise.
*/
public function unregister( $source_name ) {
public function unregister( string $source_name ) {
if ( ! $this->is_registered( $source_name ) ) {
_doing_it_wrong(
__METHOD__,
Expand Down Expand Up @@ -156,7 +158,7 @@ public function get_all_registered() {
* @param string $source_name The name of the source.
* @return array|null The registered block bindings source, or `null` if it is not registered.
*/
public function get_registered( $source_name ) {
public function get_registered( string $source_name ) {
if ( ! $this->is_registered( $source_name ) ) {
return null;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,30 @@
<?php
/**
* Add the metadata source to the block bindings API.
* Pattern Overrides source for the Block Bindings.
*
* @package gutenberg
*/

/**
* Gets value for the Pattern Overrides source.
*
* @param array $source_args Array containing source arguments used to look up the override value.
* Example: array( "key" => "foo" ).
* @param WP_Block $block_instance The block instance.
* @param string $attribute_name The name of the target attribute.
* @return mixed The value computed for the source.
*/
function gutenberg_block_bindings_pattern_overrides_callback( $source_attrs, $block_instance, $attribute_name ) {
if ( ! _wp_array_get( $block_instance->attributes, array( 'metadata', 'id' ), false ) ) {
if ( empty( $block_instance->attributes['metadata']['id'] ) ) {
return null;
}
$block_id = $block_instance->attributes['metadata']['id'];
return _wp_array_get( $block_instance->context, array( 'pattern/overrides', $block_id, 'values', $attribute_name ), null );
}

/**
* Registers Pattern Overrides source in the Block Bindings registry.
*/
function gutenberg_register_block_bindings_pattern_overrides_source() {
// Override the "core/pattern-overrides" source from core.
if ( array_key_exists( 'core/pattern-overrides', get_all_registered_block_bindings_sources() ) ) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,17 @@
<?php
/**
* Add the post_meta source to the block bindings API.
* Post Meta source for the block bindings.
*
* @package gutenberg
*/

/**
* Gets value for Post Meta source.
*
* @param array $source_args Array containing source arguments used to look up the override value.
* Example: array( "key" => "foo" ).
* @return mixed The value computed for the source.
*/
function gutenberg_block_bindings_post_meta_callback( $source_attrs ) {
if ( ! isset( $source_attrs['key'] ) ) {
return null;
Expand All @@ -17,16 +25,18 @@ function gutenberg_block_bindings_post_meta_callback( $source_attrs ) {
$post_id = get_the_ID();
}

// If a post isn't public, we need to prevent
// unauthorized users from accessing the post meta.
// If a post isn't public, we need to prevent unauthorized users from accessing the post meta.
$post = get_post( $post_id );
if ( ( $post && 'publish' !== $post->post_status && ! current_user_can( 'read_post', $post_id ) ) || post_password_required( $post_id ) ) {
if ( ( ! is_post_publicly_viewable( $post ) && ! current_user_can( 'read_post', $post_id ) ) || post_password_required( $post ) ) {
return null;
}

return get_post_meta( $post_id, $source_attrs['key'], true );
}

/**
* Registers Post Meta source in the block bindings registry.
*/
function gutenberg_register_block_bindings_post_meta_source() {
// Override the "core/post-meta" source from core.
if ( array_key_exists( 'core/post-meta', get_all_registered_block_bindings_sources() ) ) {
Expand Down
Loading

0 comments on commit 2db4c3e

Please sign in to comment.