diff --git a/packages/e2e-tests/plugins/interactive-blocks/directive-on-document/block.json b/packages/e2e-tests/plugins/interactive-blocks/directive-on-document/block.json new file mode 100644 index 0000000000000..296a9b2f04190 --- /dev/null +++ b/packages/e2e-tests/plugins/interactive-blocks/directive-on-document/block.json @@ -0,0 +1,15 @@ +{ + "$schema": "https://schemas.wp.org/trunk/block.json", + "apiVersion": 2, + "name": "test/directive-on-document", + "title": "E2E Interactivity tests - directive on document", + "category": "text", + "icon": "heart", + "description": "", + "supports": { + "interactivity": true + }, + "textdomain": "e2e-interactivity", + "viewScript": "directive-on-document-view", + "render": "file:./render.php" +} diff --git a/packages/e2e-tests/plugins/interactive-blocks/directive-on-document/render.php b/packages/e2e-tests/plugins/interactive-blocks/directive-on-document/render.php new file mode 100644 index 0000000000000..d04cb79ea5852 --- /dev/null +++ b/packages/e2e-tests/plugins/interactive-blocks/directive-on-document/render.php @@ -0,0 +1,18 @@ + + +
+ +
+
+

0

+
+
+
diff --git a/packages/e2e-tests/plugins/interactive-blocks/directive-on-document/view.js b/packages/e2e-tests/plugins/interactive-blocks/directive-on-document/view.js new file mode 100644 index 0000000000000..b3cb891e4d6cb --- /dev/null +++ b/packages/e2e-tests/plugins/interactive-blocks/directive-on-document/view.js @@ -0,0 +1,34 @@ +/** + * WordPress dependencies + */ +import { store, directive, getContext } from '@wordpress/interactivity'; + +// Mock `data-wp-show` directive to test when things are removed from the +// DOM. Replace with `data-wp-show` when it's ready. +directive( + 'show-mock', + ( { directives: { 'show-mock': showMock }, element, evaluate } ) => { + const entry = showMock.find( ( { suffix } ) => suffix === 'default' ); + if ( ! evaluate( entry ) ) { + return null; + } + return element; + } +); + +const { state } = store( 'directive-on-document', { + state: { + counter: 0, + }, + callbacks: { + keydownHandler: ( ) => { + state.counter += 1; + }, + }, + actions: { + visibilityHandler: () => { + const context = getContext(); + context.isVisible = ! context.isVisible; + }, + } +} ); diff --git a/packages/e2e-tests/plugins/interactive-blocks/directive-on-window/block.json b/packages/e2e-tests/plugins/interactive-blocks/directive-on-window/block.json new file mode 100644 index 0000000000000..9d55395b087a6 --- /dev/null +++ b/packages/e2e-tests/plugins/interactive-blocks/directive-on-window/block.json @@ -0,0 +1,15 @@ +{ + "$schema": "https://schemas.wp.org/trunk/block.json", + "apiVersion": 2, + "name": "test/directive-on-window", + "title": "E2E Interactivity tests - directive on window", + "category": "text", + "icon": "heart", + "description": "", + "supports": { + "interactivity": true + }, + "textdomain": "e2e-interactivity", + "viewScript": "directive-on-window-view", + "render": "file:./render.php" +} diff --git a/packages/e2e-tests/plugins/interactive-blocks/directive-on-window/render.php b/packages/e2e-tests/plugins/interactive-blocks/directive-on-window/render.php new file mode 100644 index 0000000000000..e9c8792354e2a --- /dev/null +++ b/packages/e2e-tests/plugins/interactive-blocks/directive-on-window/render.php @@ -0,0 +1,18 @@ + + +
+ +
+
+

0

+
+
+
diff --git a/packages/e2e-tests/plugins/interactive-blocks/directive-on-window/view.js b/packages/e2e-tests/plugins/interactive-blocks/directive-on-window/view.js new file mode 100644 index 0000000000000..11d01b7a216d1 --- /dev/null +++ b/packages/e2e-tests/plugins/interactive-blocks/directive-on-window/view.js @@ -0,0 +1,34 @@ +/** + * WordPress dependencies + */ +import { store, directive, getContext } from '@wordpress/interactivity'; + +// Mock `data-wp-show` directive to test when things are removed from the +// DOM. Replace with `data-wp-show` when it's ready. +directive( + 'show-mock', + ( { directives: { 'show-mock': showMock }, element, evaluate } ) => { + const entry = showMock.find( ( { suffix } ) => suffix === 'default' ); + if ( ! evaluate( entry ) ) { + return null; + } + return element; + } +); + +const { state } = store( 'directive-on-window', { + state: { + counter: 0, + }, + callbacks: { + resizeHandler: ( ) => { + state.counter += 1; + }, + }, + actions: { + visibilityHandler: () => { + const context = getContext(); + context.isVisible = ! context.isVisible; + }, + } +} ); diff --git a/packages/interactivity/CHANGELOG.md b/packages/interactivity/CHANGELOG.md index 8514ecc6716f8..8a09c2d856416 100644 --- a/packages/interactivity/CHANGELOG.md +++ b/packages/interactivity/CHANGELOG.md @@ -9,6 +9,7 @@ ### New Features - Add the `data-wp-run` directive along with the `useInit` and `useWatch` hooks. ([57805](https://github.com/WordPress/gutenberg/pull/57805)) +- Add `wp-data-on-window` and `wp-data-on-document` directives. ([57931](https://github.com/WordPress/gutenberg/pull/57931)) ### Enhancements diff --git a/packages/interactivity/docs/2-api-reference.md b/packages/interactivity/docs/2-api-reference.md index 7980c31b984f8..922662c10a8e2 100644 --- a/packages/interactivity/docs/2-api-reference.md +++ b/packages/interactivity/docs/2-api-reference.md @@ -20,6 +20,8 @@ DOM elements are connected to data stored in the state and context through direc - [`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-on-window`](#wp-on-window) ![](https://img.shields.io/badge/EVENT_HANDLERS-afd2e3.svg) + - [`wp-on-document`](#wp-on-document) ![](https://img.shields.io/badge/EVENT_HANDLERS-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-run`](#wp-run) ![](https://img.shields.io/badge/SIDE_EFFECTS-afd2e3.svg) @@ -55,7 +57,7 @@ _Example of directives used in the HTML markup_ > Toggle - +

This element is now visible!

@@ -68,13 +70,13 @@ Directives can also be injected dynamically using the [HTML Tag Processor](https With directives, we can directly manage behavior related to things such as side effects, state, event handlers, attributes or content. -#### `wp-interactive` +#### `wp-interactive` The `wp-interactive` directive "activates" the interactivity for the DOM element and its children through the Interactivity API (directives and store). It includes a namespace to reference a specific store. ```html -
@@ -88,13 +90,13 @@ The `wp-interactive` directive "activates" the interactivity for the DOM element > **Note** > 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` +#### `wp-context` It provides a **local** state available to a specific HTML node and its children. The `wp-context` directive accepts a stringified JSON as a value. -_Example of `wp-context` directive_ +_Example of `wp-context` directive_ ```php //render.php @@ -139,13 +141,13 @@ Different contexts can be defined at different levels, and deeper levels will me
``` -#### `wp-bind` +#### `wp-bind` 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_ +_Example of `wp-bind` directive_ ```html
  • @@ -183,10 +185,10 @@ store( "myPlugin", { The `wp-bind` directive is executed: -- When the element is created. +- 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: +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 returned value in the callback function is used to change the value of the associated attribute. @@ -198,24 +200,24 @@ The `wp-bind` will do different things over the DOM element is applied, dependin - If the value is a string, the attribute is added with its value assigned: `
    `. -#### `wp-class` +#### `wp-class` It adds or removes a class to an HTML element, depending on a boolean value. > This directive follows the syntax `data-wp-class--classname`. -_Example of `wp-class` directive_ +_Example of `wp-class` directive_ ```html
    -
  • Option 1
  • -
  • This directive follows the syntax `data-wp-style--css-property`. -_Example of `wp-style` directive_ +_Example of `wp-style` directive_ ```html
    @@ -296,7 +298,7 @@ The value received by the directive is used to add or remove the style attribute - 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` +#### `wp-text` It sets the inner text of an HTML element. @@ -333,13 +335,13 @@ The `wp-text` directive is executed: The returned value is used to change the inner content of the element: `
    value
    `. -#### `wp-on` +#### `wp-on` -It runs code on dispatched DOM events like `click` or `keyup`. +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_ +_Example of `wp-on` directive_ ```php