diff --git a/block-hydration-experiments.php b/block-hydration-experiments.php index b06a5ef5..d18d9f60 100644 --- a/block-hydration-experiments.php +++ b/block-hydration-experiments.php @@ -1,4 +1,5 @@ block_type; - if ( ! block_has_support( $block_type, [ 'view' ] ) ) { + if (!block_has_support($block_type, ['view'])) { return $block_content; } diff --git a/package.json b/package.json index 3cc32895..b81db0e5 100644 --- a/package.json +++ b/package.json @@ -35,7 +35,7 @@ "@wordpress/blocks": "^11.7.0", "@wordpress/element": "^4.3.0", "@wordpress/env": "^4.4.0", - "@wordpress/scripts": "^22.3.0", + "@wordpress/scripts": "^24.0.0", "babel-jest": "^28.1.0", "jest": "^28.1.0", "prettier": "^2.7.1" diff --git a/src/blocks/dynamic-interactive-child/block.json b/src/blocks/dynamic-interactive-child/block.json new file mode 100644 index 00000000..cb118afc --- /dev/null +++ b/src/blocks/dynamic-interactive-child/block.json @@ -0,0 +1,38 @@ +{ + "$schema": "https://schemas.wp.org/trunk/block.json", + "apiVersion": 2, + "name": "bhe/dynamic-interactive-child", + "version": "0.1.0", + "title": "BHE - Dynamic Interactive Child", + "category": "text", + "icon": "flag", + "description": "", + "usesContext": [ + "bhe/dynamic-interactive-title", + "bhe/dynamic-non-interactive-title" + ], + "attributes": { + "state": { + "type": "string", + "public": true, + "source": "text", + "selector": ".dynamic-child-block-state" + } + }, + "supports": { + "color": { + "text": true + }, + "typography": { + "fontSize": true + }, + "html": true, + "view": true + }, + "textdomain": "bhe", + "editorScript": "file:./index.js", + "editorStyle": "file:./style.css", + "style": "file:./style-index.css", + "viewScript": "file:./register-view.js", + "render": "file:./render.php" +} \ No newline at end of file diff --git a/src/blocks/dynamic-interactive-child/edit.js b/src/blocks/dynamic-interactive-child/edit.js new file mode 100644 index 00000000..f9667b92 --- /dev/null +++ b/src/blocks/dynamic-interactive-child/edit.js @@ -0,0 +1,16 @@ +import { useBlockProps } from '@wordpress/block-editor'; + +const Edit = ({ context }) => ( +
+

+ Block Context from interactive parent:{' '} + {context['bhe/dynamic-interactive-title']} +

+

+ Block Context from non-interactive parent - + "bhe/non-interactive-title": {context['bhe/dynamic-non-interactive-title']} +

+
+); + +export default Edit; \ No newline at end of file diff --git a/src/blocks/dynamic-interactive-child/index.js b/src/blocks/dynamic-interactive-child/index.js new file mode 100644 index 00000000..066c34b9 --- /dev/null +++ b/src/blocks/dynamic-interactive-child/index.js @@ -0,0 +1,11 @@ +/** + * WordPress dependencies + */ +import { registerBlockType } from '@wordpress/blocks'; +import Edit from './edit'; +import './style.scss'; + +// Register the block +registerBlockType('bhe/dynamic-interactive-child', { + edit: Edit, +}); \ No newline at end of file diff --git a/src/blocks/dynamic-interactive-child/register-view.js b/src/blocks/dynamic-interactive-child/register-view.js new file mode 100644 index 00000000..d5caae41 --- /dev/null +++ b/src/blocks/dynamic-interactive-child/register-view.js @@ -0,0 +1,8 @@ +import CounterContext from '../../context/counter'; +import ThemeContext from '../../context/theme'; +import registerBlockView from '../../gutenberg-packages/register-block-view'; +import View from './view'; + +registerBlockView('bhe/dynamic-interactive-child', View, { + usesContext: [ThemeContext, CounterContext], +}); diff --git a/src/blocks/dynamic-interactive-child/render.php b/src/blocks/dynamic-interactive-child/render.php new file mode 100644 index 00000000..ee5790e0 --- /dev/null +++ b/src/blocks/dynamic-interactive-child/render.php @@ -0,0 +1,23 @@ +post_date; +$state = [ + "date" => $date +]; +?> + +
> +

+ Block Context from interactive parent - "bhe/interactive-title": context['bhe/dynamic-interactive-title'] ?> +

+

+ Block Context from non-interactive parent - "bhe/non-interactive-title": context['bhe/dynamic-non-interactive-title'] ?> +

+

React Context - "counter":

+

React Context - "theme":

+

Post Date:

+ +
\ No newline at end of file diff --git a/src/blocks/dynamic-interactive-child/style.scss b/src/blocks/dynamic-interactive-child/style.scss new file mode 100644 index 00000000..977b0e38 --- /dev/null +++ b/src/blocks/dynamic-interactive-child/style.scss @@ -0,0 +1,23 @@ +.wp-block-bhe-dynamic-interactive-child { + padding: 15px 10px 15px 50px; + border: 1px solid rgb(117, 76, 5); + position: relative; +} + +.wp-block-bhe-dynamic-interactive-child::before { + position: absolute; + top: 0; + right: 0; + border: 1px solid rgb(117, 76, 5); + background-color: rgb(117, 76, 5); + color: white; + margin: -1px; + padding: 0px 5px; + font-size: 9px; + content: 'BHE - Dynamic Interactive Child'; +} + +wp-block, +wp-inner-blocks { + display: contents; +} \ No newline at end of file diff --git a/src/blocks/dynamic-interactive-child/view.js b/src/blocks/dynamic-interactive-child/view.js new file mode 100644 index 00000000..73c76def --- /dev/null +++ b/src/blocks/dynamic-interactive-child/view.js @@ -0,0 +1,28 @@ +import CounterContext from '../../context/counter'; +import ThemeContext from '../../context/theme'; +import { useContext } from '../../gutenberg-packages/wordpress-element'; + +const View = ({ blockProps, attributes, context }) => { + const theme = useContext(ThemeContext); + const counter = useContext(CounterContext); + const { date } = JSON.parse(attributes.state); + + return ( +
+

+ Block Context from interactive parent - "bhe/interactive-title":{' '} + {context['bhe/dynamic-interactive-title']} +

+

+ Block Context from non-interactive parent - + "bhe/non-interactive-title":{' '} + {context['bhe/dynamic-non-interactive-title']} +

+

React Context - "counter": {counter}

+

React Context - "theme": {theme}

+

Post Date: {date}

+
+ ); +}; + +export default View; diff --git a/src/blocks/dynamic-interactive-parent/block.json b/src/blocks/dynamic-interactive-parent/block.json new file mode 100644 index 00000000..3bb66d09 --- /dev/null +++ b/src/blocks/dynamic-interactive-parent/block.json @@ -0,0 +1,57 @@ +{ + "$schema": "https://schemas.wp.org/trunk/block.json", + "apiVersion": 2, + "name": "bhe/dynamic-interactive-parent", + "version": "0.1.0", + "title": "BHE - Dynamic Interactive Parent", + "category": "text", + "icon": "flag", + "description": "", + "usesContext": [ + "postId", + "postType", + "queryId" + ], + "attributes": { + "counter": { + "type": "number", + "default": 0, + "public": true + }, + "blockTitle": { + "type": "string", + "public": true + }, + "state": { + "type": "string", + "public": true, + "source": "text", + "selector": ".dynamic-parent-block-state" + }, + "secret": { + "type": "string", + "default": "fa4e3d47e4e0a38c5c57533391855013" + } + }, + "supports": { + "color": { + "text": true + }, + "typography": { + "fontSize": true, + "__experimentalFontWeight": true, + "__experimentalLetterSpacing": true + }, + "html": true, + "view": true + }, + "providesContext": { + "bhe/dynamic-interactive-title": "blockTitle" + }, + "textdomain": "bhe", + "editorScript": "file:./index.js", + "editorStyle": "file:./style.css", + "style": "file:./style-index.css", + "viewScript": "file:./register-view.js", + "render": "file:./render.php" +} \ No newline at end of file diff --git a/src/blocks/dynamic-interactive-parent/edit.js b/src/blocks/dynamic-interactive-parent/edit.js new file mode 100644 index 00000000..1991c702 --- /dev/null +++ b/src/blocks/dynamic-interactive-parent/edit.js @@ -0,0 +1,47 @@ +// This import is needed to ensure that the `wp.blockEditor` global is available +// by the time this component gets loaded. The `Title` component consumes the +// global but cannot import it because it shouldn't be loaded on the frontend of +// the site. +import '@wordpress/block-editor'; +import { InnerBlocks, useBlockProps } from '@wordpress/block-editor'; +import { useEntityProp } from '@wordpress/core-data'; + +import Button from './shared/button'; +import Title from './shared/title'; + +const Edit = ({ attributes, setAttributes, context }) => { + const { counter, blockTitle, secret } = attributes; + const { postType, postId, queryId } = context; + + const [rawTitle = '', setTitle, fullTitle] = useEntityProp( + 'postType', + postType, + 'title', + postId + ); + + return ( +
+

Post Title: {fullTitle?.rendered}

+ setAttributes({ blockTitle: val })} + placeholder="This will be passed through context to child blocks" + className="dynamic-interactive-parent-block-title" + > + {blockTitle} + + + +
+ This is a secret attribute that should not be serialized:{' '} + {secret} +
+ +
+ ) +}; + +export default Edit; \ No newline at end of file diff --git a/src/blocks/dynamic-interactive-parent/index.js b/src/blocks/dynamic-interactive-parent/index.js new file mode 100644 index 00000000..9abd860d --- /dev/null +++ b/src/blocks/dynamic-interactive-parent/index.js @@ -0,0 +1,21 @@ +/** + * WordPress dependencies + */ +import { registerBlockType } from '@wordpress/blocks'; +import Edit from './edit'; +import { RichText, InnerBlocks } from '@wordpress/block-editor'; +import './style.scss'; + +// Register the block +registerBlockType('bhe/dynamic-interactive-parent', { + edit: Edit, + // If I don't add this, the InnerBlocks don't seem to work in dynamic blocks. + save: ({ attributes }) => { + return ( + <> + + + + ) + } +}); \ No newline at end of file diff --git a/src/blocks/dynamic-interactive-parent/register-view.js b/src/blocks/dynamic-interactive-parent/register-view.js new file mode 100644 index 00000000..10f90d4c --- /dev/null +++ b/src/blocks/dynamic-interactive-parent/register-view.js @@ -0,0 +1,8 @@ +import CounterContext from '../../context/counter'; +import ThemeContext from '../../context/theme'; +import registerBlockView from '../../gutenberg-packages/register-block-view'; +import View from './view'; + +registerBlockView('bhe/dynamic-interactive-parent', View, { + providesContext: [ThemeContext, CounterContext], +}); diff --git a/src/blocks/dynamic-interactive-parent/render.php b/src/blocks/dynamic-interactive-parent/render.php new file mode 100644 index 00000000..46c2ca2f --- /dev/null +++ b/src/blocks/dynamic-interactive-parent/render.php @@ -0,0 +1,25 @@ +inner_blocks as $inner_block) { + $inner_blocks_html .= $inner_block->render(); +} +$state = [ + "title" => $post->post_title +]; +?> + +
> +

Post Title: post_title ?>

+

Block Title:

+ + + + + + + +
\ No newline at end of file diff --git a/src/blocks/dynamic-interactive-parent/shared/button.js b/src/blocks/dynamic-interactive-parent/shared/button.js new file mode 100644 index 00000000..2384a54a --- /dev/null +++ b/src/blocks/dynamic-interactive-parent/shared/button.js @@ -0,0 +1,5 @@ +const Button = ({ handler, children }) => { + return ; +}; + +export default Button; diff --git a/src/blocks/dynamic-interactive-parent/shared/title.js b/src/blocks/dynamic-interactive-parent/shared/title.js new file mode 100644 index 00000000..8fdd696b --- /dev/null +++ b/src/blocks/dynamic-interactive-parent/shared/title.js @@ -0,0 +1,9 @@ +import { RichText } from '../../../gutenberg-packages/wordpress-blockeditor'; + +const Title = ({ children, ...props }) => ( + + {children} + +); + +export default Title; diff --git a/src/blocks/dynamic-interactive-parent/style.scss b/src/blocks/dynamic-interactive-parent/style.scss new file mode 100644 index 00000000..519dddca --- /dev/null +++ b/src/blocks/dynamic-interactive-parent/style.scss @@ -0,0 +1,23 @@ +.wp-block-bhe-dynamic-interactive-parent { + padding: 15px 10px 15px 50px; + border: 1px solid rgb(1, 89, 20); + position: relative; +} + +.wp-block-bhe-dynamic-interactive-parent::before { + position: absolute; + top: 0; + right: 0; + background-color: rgb(1, 89, 20); + border: 1px solid rgb(1, 89, 20); + color: white; + margin: -1px; + padding: 0px 5px; + font-size: 10px; + content: 'BHE - Dynamic Interactive Parent'; +} + +wp-block, +wp-inner-blocks { + display: contents; +} \ No newline at end of file diff --git a/src/blocks/dynamic-interactive-parent/view.js b/src/blocks/dynamic-interactive-parent/view.js new file mode 100644 index 00000000..c798424f --- /dev/null +++ b/src/blocks/dynamic-interactive-parent/view.js @@ -0,0 +1,44 @@ +import Counter from '../../context/counter'; +import Theme from '../../context/theme'; +import { useState } from '../../gutenberg-packages/wordpress-element'; +import Button from './shared/button'; +import Title from './shared/title'; + +const View = ({ + blockProps: { + className, + style: { fontWeight, ...style }, + }, + attributes: { counter: initialCounter, blockTitle, state }, + children, +}) => { + const [show, setShow] = useState(true); + const [bold, setBold] = useState(false); + const [counter, setCounter] = useState(initialCounter); + const { title } = JSON.parse(state); + + return ( + + +
+

Post Title: {title}

+ Block Title: {blockTitle} + + + + {show && children} +
+
+
+ ); +}; + +export default View; diff --git a/src/blocks/dynamic-non-interactive-parent/block.json b/src/blocks/dynamic-non-interactive-parent/block.json new file mode 100644 index 00000000..ecd0e21b --- /dev/null +++ b/src/blocks/dynamic-non-interactive-parent/block.json @@ -0,0 +1,32 @@ +{ + "apiVersion": 2, + "title": "BHE - Dynamic Non Interactive Parent", + "name": "bhe/dynamic-non-interactive-parent", + "category": "text", + "icon": "flag", + "usesContext": [ + "postId", + "postType", + "queryId" + ], + "attributes": { + "blockTitle": { + "type": "string", + "public": true + } + }, + "providesContext": { + "bhe/dynamic-non-interactive-title": "blockTitle" + }, + "supports": { + "color": { + "text": true + }, + "html": true, + "view": true + }, + "textdomain": "bhe", + "editorScript": "file:./index.js", + "style": "file:./style-index.css", + "render": "file:./render.php" +} \ No newline at end of file diff --git a/src/blocks/dynamic-non-interactive-parent/edit.js b/src/blocks/dynamic-non-interactive-parent/edit.js new file mode 100644 index 00000000..8a19f1b9 --- /dev/null +++ b/src/blocks/dynamic-non-interactive-parent/edit.js @@ -0,0 +1,38 @@ +// This import is needed to ensure that the `wp.blockEditor` global is available +// by the time this component gets loaded. The `Title` component consumes the +// global but cannot import it because it shouldn't be loaded on the frontend of +// the site. +import '@wordpress/block-editor'; +import { InnerBlocks, useBlockProps } from '@wordpress/block-editor'; +import { useEntityProp } from '@wordpress/core-data'; +import { RichText } from '../../gutenberg-packages/wordpress-blockeditor'; + +const Edit = ({ attributes, setAttributes, context }) => { + const blockProps = useBlockProps(); + const { postType, postId, queryId } = context; + + const [rawTitle = '', setTitle, fullTitle] = useEntityProp( + 'postType', + postType, + 'title', + postId + ); + + return ( +
+

Post Title: {fullTitle?.rendered}

+ setAttributes({ blockTitle: val })} + placeholder="This will be passed through context to child blocks" + value={attributes.blockTitle} + > + {attributes.blockTitle} + + +
+ ) +}; + +export default Edit; \ No newline at end of file diff --git a/src/blocks/dynamic-non-interactive-parent/index.js b/src/blocks/dynamic-non-interactive-parent/index.js new file mode 100644 index 00000000..c23307a3 --- /dev/null +++ b/src/blocks/dynamic-non-interactive-parent/index.js @@ -0,0 +1,21 @@ +/** + * WordPress dependencies + */ +import { registerBlockType } from '@wordpress/blocks'; +import Edit from './edit'; +import { RichText, InnerBlocks } from '@wordpress/block-editor'; +import './style.scss'; + +// Register the block +registerBlockType('bhe/dynamic-non-interactive-parent', { + edit: Edit, + // If I don't add this, the InnerBlocks don't seem to work in dynamic blocks. + save: ({ attributes }) => { + return ( + <> + + + + ) + } +}); \ No newline at end of file diff --git a/src/blocks/dynamic-non-interactive-parent/render.php b/src/blocks/dynamic-non-interactive-parent/render.php new file mode 100644 index 00000000..a6133b3a --- /dev/null +++ b/src/blocks/dynamic-non-interactive-parent/render.php @@ -0,0 +1,15 @@ +inner_blocks as $inner_block) { + $inner_blocks_html .= $inner_block->render(); +} +?> + +
> +

Post Title: post_title ?>

+

Block Title :

+
+ +
+
\ No newline at end of file diff --git a/src/blocks/dynamic-non-interactive-parent/style.scss b/src/blocks/dynamic-non-interactive-parent/style.scss new file mode 100644 index 00000000..a5731ff4 --- /dev/null +++ b/src/blocks/dynamic-non-interactive-parent/style.scss @@ -0,0 +1,23 @@ +.wp-block-bhe-dynamic-non-interactive-parent { + border: 1px solid rgb(0, 86, 129); + position: relative; + padding: 25px 10px; +} + +.wp-block-bhe-dynamic-non-interactive-parent::before { + content: 'BHE - Dynamic Non Interactive Parent'; + position: absolute; + top: 0; + right: 0; + border: 1px solid rgb(0, 86, 129); + background-color: rgb(0, 86, 129); + color: white; + margin: -1px; + padding: 0px 5px; + font-size: 10px; +} + +wp-block, +wp-inner-blocks { + display: contents; +} \ No newline at end of file