From 99f34d63a9c07de5cb2557d955ad6d510b1da91d Mon Sep 17 00:00:00 2001 From: Luis Herranz Date: Mon, 4 Dec 2023 19:02:14 +0100 Subject: [PATCH 1/9] New store() API docs --- .../interactivity/docs/2-api-reference.md | 430 +++++++++--------- 1 file changed, 224 insertions(+), 206 deletions(-) diff --git a/packages/interactivity/docs/2-api-reference.md b/packages/interactivity/docs/2-api-reference.md index 828de4379c0269..dbc5c89b767d77 100644 --- a/packages/interactivity/docs/2-api-reference.md +++ b/packages/interactivity/docs/2-api-reference.md @@ -2,10 +2,10 @@ To add interactivity to blocks using the Interactivity API, developers can use: -- **Directives** - added to the markup to add specific behavior to the DOM elements of block. -- **Store** - that contains the logic and data (state, actions, or effects among others) needed for the behaviour. +- **Directives** - added to the markup to add specific behavior to the DOM elements of the block. +- **Store** - that contains the logic and data (state, actions, or side effects, among others) needed for the behavior. -DOM elements are connected to data stored in the state & context through directives. If data in the state or context change, directives will react to those changes updating the DOM accordingly (see [diagram](https://excalidraw.com/#json=rEg5d71O_jy3NrgYJUIVd,yjOUmMvxzNf6alqFjElvIw)). +DOM elements are connected to data stored in the state and context through directives. If data in the state or context change directives will react to those changes, updating the DOM accordingly (see [diagram](https://excalidraw.com/#json=rEg5d71O_jy3NrgYJUIVd,yjOUmMvxzNf6alqFjElvIw)). ![State & Directives](assets/state-directives.png) @@ -20,7 +20,7 @@ DOM elements are connected to data stored in the state & context through directi - [`wp-style`](#wp-style) ![](https://img.shields.io/badge/ATTRIBUTES-afd2e3.svg) - [`wp-text`](#wp-text) ![](https://img.shields.io/badge/CONTENT-afd2e3.svg) - [`wp-on`](#wp-on) ![](https://img.shields.io/badge/EVENT_HANDLERS-afd2e3.svg) - - [`wp-effect`](#wp-effect) ![](https://img.shields.io/badge/SIDE_EFFECTS-afd2e3.svg) + - [`wp-watch`](#wp-watch) ![](https://img.shields.io/badge/SIDE_EFFECTS-afd2e3.svg) - [`wp-init`](#wp-init) ![](https://img.shields.io/badge/SIDE_EFFECTS-afd2e3.svg) - [`wp-key`](#wp-key) ![](https://img.shields.io/badge/TEMPLATING-afd2e3.svg) - [Values of directives are references to store properties](#values-of-directives-are-references-to-store-properties) @@ -28,18 +28,14 @@ DOM elements are connected to data stored in the state & context through directi - [Elements of the store](#elements-of-the-store) - [State](#state) - [Actions](#actions) - - [Effects](#effects) - - [Selectors](#selectors) - - [Arguments passed to callbacks](#arguments-passed-to-callbacks) + - [Side Effects](#side-effects) - [Setting the store](#setting-the-store) - [On the client side](#on-the-client-side) - [On the server side](#on-the-server-side) - - ## The directives -Directives are custom attributes that are added to the markup of your block to add behaviour to its DOM elements. This can be done in the `render.php` file (for dynamic blocks) or the `save.js` file (for static blocks). +Directives are custom attributes that are added to the markup of your block to add behavior to its DOM elements. This can be done in the `render.php` file (for dynamic blocks) or the `save.js` file (for static blocks). Interactivity API directives use the `data-` prefix. @@ -47,40 +43,38 @@ _Example of directives used in the HTML markup_ ```html
-

+

This element is now visible!

``` -> **Note** -> The use of Namespaces to define the context, state or any other elements of the store is highly recommended to avoid possible collision with other elements with the same name. In the following examples we have not used namespaces for the sake of simplicity. - Directives can also be injected dynamically using the [HTML Tag Processor](https://make.wordpress.org/core/2023/03/07/introducing-the-html-api-in-wordpress-6-2). ### List of Directives -With directives we can manage directly in the DOM behavior related to things such as side effects, state, event handlers, attributes or content. +With directives, we can directly manage behavior related to things such as side effects, state, event handlers, attributes or content. #### `wp-interactive` -The `wp-interactive` directive "activates" the interactivity for the DOM element and its children through the Interactivity API (directives and store). +The `wp-interactive` directive "activates" the interactivity for the DOM element and its children through the Interactivity API (directives and store). It includes the a namespace to reference a specific store. ```html - +

I'm interactive now, >and I can use directives!

@@ -91,19 +85,19 @@ The `wp-interactive` directive "activates" the interactivity for the DOM element ``` > **Note** -> The use of `wp-interactive` is a requirement for the Interactivity API "engine" to work. In the following examples the `wp-interactive` has not been added for the sake of simplicity. - +> The use of `data-wp-interactive` is a requirement for the Interactivity API "engine" to work. In the following examples the `data-wp-interactive` has not been added for the sake of simplicity. Also, the `data-wp-interactive` directive will be injected automatically in the future. #### `wp-context` -It provides **local** state available to a specific HTML node and its children. +It provides a **local** state available to a specific HTML node and its children. -The `wp-context` directive accepts a stringified JSON as value. +The `wp-context` directive accepts a stringified JSON as a value. _Example of `wp-context` directive_ + ```php //render.php -
+
@@ -114,10 +108,11 @@ _Example of `wp-context` directive_ See store used with the directive above ```js -store( { +store( "myPlugin", { actions: { - logId: ( { context } ) => { - console.log( context.post.id ); + logId: () => { + const { post } = getContext(); + console.log( post.id ); }, }, } ); @@ -126,7 +121,7 @@ store( {
-Different contexts can be defined at different levels and deeper levels will merge their own context with any parent one: +Different contexts can be defined at different levels, and deeper levels will merge their own context with any parent one: ```html
@@ -150,6 +145,7 @@ It allows setting HTML attributes on elements based on a boolean or string value > This directive follows the syntax `data-wp-bind--attribute`. _Example of `wp-bind` directive_ + ```html
  • ``` +
    See store used with the directive above ```js -store( { - actions: { - toggleMenu: ( { context } ) => { +store( "myPlugin", { + actions: { + toggleMenu: () => { + const context = getContext(); context.isMenuOpen = !context.isMenuOpen; }, - }, + }, } ); ``` @@ -183,15 +181,17 @@ store( {
    The `wp-bind` directive is executed: - - when the element is created. - - each time there's a change on any of the properties of the `state` or `context` involved on getting the final value of the directive (inside the callback or the expression passed as reference). + +- When the element is created. +- Each time there's a change on any of the properties of the `state` or `context` involved in getting the final value of the directive (inside the callback or the expression passed as reference). When `wp-bind` directive references a callback to get its final value: + - The `wp-bind` directive will be executed each time there's a change on any of the properties of the `state` or `context` used inside this callback. -- The callback receives the attribute name: `attribute`. - The returned value in the callback function is used to change the value of the associated attribute. -The `wp-bind` will do different things over the DOM element is applied depending on its value: +The `wp-bind` will do different things over the DOM element is applied, depending on its value: + - If the value is `true`, the attribute is added: `
    `. - If the value is `false`, the attribute is removed: `
    `. - If the value is a string, the attribute is added with its value assigned: `
    This directive follows the syntax `data-wp-class--classname`. _Example of `wp-class` directive_ + ```php
  • See store used with the directive above ```js -store( { +store( "myPlugin", { actions: { - toggleSelection: ( { context } ) => { + toggleSelection: () => { + const context = getContext(); context.isSelected = !context.isSelected } } @@ -240,14 +242,14 @@ store( {
    The `wp-class` directive is executed: - - when the element is created. - - each time there's a change on any of the properties of the `state` or `context` involved on getting the final value of the directive (inside the callback or the expression passed as reference). + +- When the element is created. +- Each time there's a change on any of the properties of the `state` or `context` involved in getting the final value of the directive (inside the callback or the expression passed as reference). When `wp-class` directive references a callback to get its final boolean value, the callback receives the class name: `className`. The boolean value received by the directive is used to toggle (add when `true` or remove when `false`) the associated class name from the `class` attribute. - #### `wp-style` It adds or removes inline style to an HTML element, depending on its value. @@ -255,6 +257,7 @@ It adds or removes inline style to an HTML element, depending on its value. > This directive follows the syntax `data-wp-style--css-property`. _Example of `wp-style` directive_ + ```html
    @@ -267,9 +270,10 @@ _Example of `wp-style` directive_ See store used with the directive above ```js -store( { +store( "myPlugin", { actions: { - toggleContextColor: ( { context } ) => { + toggleContextColor: () => { + const context = getContext(); context.color = context.color === 'red' ? 'blue' : 'red'; }, }, @@ -280,14 +284,16 @@ store( {
    The `wp-style` directive is executed: - - when the element is created. - - each time there's a change on any of the properties of the `state` or `context` involved on getting the final value of the directive (inside the callback or the expression passed as reference). + +- When the element is created. +- Each time there's a change on any of the properties of the `state` or `context` involved in getting the final value of the directive (inside the callback or the expression passed as reference). When `wp-style` directive references a callback to get its final value, the callback receives the class style property: `css-property`. The value received by the directive is used to add or remove the style attribute with the associated CSS property: : - - If the value is `false`, the style attribute is removed: `
    `. - - If the value is a string, the attribute is added with its value assigned: `
    `. + +- If the value is `false`, the style attribute is removed: `
    `. +- If the value is a string, the attribute is added with its value assigned: `
    `. #### `wp-text` @@ -306,9 +312,10 @@ It sets the inner text of an HTML element. See store used with the directive above ```js -store( { +store( "myPlugin", { actions: { - toggleContextText: ( { context } ) => { + toggleContextText: () => { + const context = getContext(); context.text = context.text === 'Text 1' ? 'Text 2' : 'Text 1'; }, }, @@ -319,8 +326,9 @@ store( {
    The `wp-text` directive is executed: - - when the element is created. - - each time there's a change on any of the properties of the `state` or `context` involved on getting the final value of the directive (inside the callback or the expression passed as reference). + +- When the element is created. +- Each time there's a change on any of the properties of the `state` or `context` involved in getting the final value of the directive (inside the callback or the expression passed as reference). The returned value is used to change the inner content of the element: `
    value
    `. @@ -331,6 +339,7 @@ It runs code on dispatched DOM events like `click` or `keyup`. > The syntax of this directive is `data-wp-on--[event]` (like `data-wp-on--click` or `data-wp-on--keyup`). _Example of `wp-on` directive_ + ```php @@ -378,17 +389,22 @@ _Example of `wp-effect` directive_ See store used with the directive above ```js -store( { +store( "myPlugin", { actions: { - increaseCounter: ({ context }) => { + increaseCounter: () => { + const context = getContext(); context.counter++; }, - decreaseCounter: ({ context }) => { + decreaseCounter: () => { + const context = getContext(); context.counter--; }, } - effects: { - logCounter: ({ context }) => console.log("Counter is " + context.counter + " at " + new Date() ), + callbacks: { + logCounter: () => { + const { counter } = getContext(); + console.log("Counter is " + counter + " at " + new Date() ); + }, }, } ); ``` @@ -396,17 +412,19 @@ store( {

  • -The `wp-effect` directive is executed: - - when the element is created. - - each time that any of the properties of the `state` or `context` used inside the callback changes. +The `wp-watch` directive is executed: + +- When the element is created. +- Each time that any of the properties of the `state` or `context` used inside the callback changes. + +The `wp-watch` directive can return a function. If it does, the returned function is used as cleanup logic, i.e., it will run just before the callback runs again, and it will run again when the element is removed from the DOM. -The `wp-effect` directive can return a function. If it does, the returned function is used as cleanup logic, i.e., it will run just before the callback runs again, and it will run again when the element is removed from the DOM. +As a reference, some use cases for this directive may be: -As a reference, some use cases for this directive may be: -- logging. -- changing the title of the page. -- setting the focus on an element with `.focus()`. -- changing the state or context when certain conditions are met. +- Logging. +- Changing the title of the page. +- Setting the focus on an element with `.focus()`. +- Changing the state or context when certain conditions are met. #### `wp-init` @@ -415,17 +433,19 @@ It runs a callback **only when the node is created**. You can attach several `wp-init` to the same DOM element by using the syntax `data-wp-init--[unique-id]`. _The unique id doesn't need to be unique globally, it just needs to be different than the other unique ids of the `wp-init` directives of that DOM element._ _Example of `data-wp-init` directive_ + ```html -
    +

    Hi!

    ``` _Example of several `wp-init` directives on the same DOM element_ + ```html
    @@ -435,11 +455,13 @@ _Example of several `wp-init` directives on the same DOM element_ See store used with the directive above ```js -store( { - effects: { +store( "myPlugin", { + callbacks: { logTimeInit: () => console.log( `Init at ` + new Date() ), - focusFirstElement: ( { ref } ) => + focusFirstElement: () => { + const { ref } = getElement(); ref.querySelector( 'input:first-child' ).focus(), + }, }, } ); ``` @@ -447,15 +469,13 @@ store( {
    - The `wp-init` can return a function. If it does, the returned function will run when the element is removed from the DOM. #### `wp-key` +The `wp-key` directive assigns a unique key to an element to help the Interactivity API identify it when iterating through arrays of elements. This becomes important if your array elements can move (e.g., due to sorting), get inserted, or get deleted. A well-chosen key value helps the Interactivity API infer what exactly has changed in the array, allowing it to make the correct updates to the DOM. -The `wp-key` directive assigns a unique key to an element to help the Interactivity API identify it when iterating through arrays of elements. This becomes important if your array elements can move (e.g. due to sorting), get inserted, or get deleted. A well-chosen key value helps the Interactivity API infer what exactly has changed in the array, allowing it to make the correct updates to the DOM. - -The key should be a string that uniquely identifies the element among its siblings. Typically it is used on repeated elements like list items. For example: +The key should be a string that uniquely identifies the element among its siblings. Typically, it is used on repeated elements like list items. For example: ```html