@wordpress/block-library 9.31.1-next.f56bd8138.0 → 9.32.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +2 -0
- package/build/accordion/edit.js +62 -12
- package/build/accordion/edit.js.map +1 -1
- package/build/accordion/index.js +15 -8
- package/build/accordion/index.js.map +1 -1
- package/build/accordion/view.js +15 -15
- package/build/accordion/view.js.map +1 -1
- package/build/accordion-heading/edit.js +68 -0
- package/build/accordion-heading/edit.js.map +1 -0
- package/build/accordion-heading/icon.js.map +1 -0
- package/build/{accordion-header → accordion-heading}/index.js +9 -17
- package/build/accordion-heading/index.js.map +1 -0
- package/build/{accordion-content → accordion-heading}/init.js.map +1 -1
- package/build/{accordion-header → accordion-heading}/save.js +7 -20
- package/build/accordion-heading/save.js.map +1 -0
- package/build/{accordion-content → accordion-item}/edit.js +8 -2
- package/build/accordion-item/edit.js.map +1 -0
- package/build/accordion-item/icon.js.map +1 -0
- package/build/{accordion-content → accordion-item}/index.js +6 -5
- package/build/accordion-item/index.js.map +1 -0
- package/build/accordion-item/init.js.map +1 -0
- package/build/{accordion-content → accordion-item}/save.js +5 -7
- package/build/accordion-item/save.js.map +1 -0
- package/build/accordion-panel/edit.js +2 -1
- package/build/accordion-panel/edit.js.map +1 -1
- package/build/accordion-panel/index.js +5 -3
- package/build/accordion-panel/index.js.map +1 -1
- package/build/accordion-panel/save.js +3 -1
- package/build/accordion-panel/save.js.map +1 -1
- package/build/block/index.js +1 -0
- package/build/block/index.js.map +1 -1
- package/build/group/variations.js +3 -4
- package/build/group/variations.js.map +1 -1
- package/build/index.js +24 -4
- package/build/index.js.map +1 -1
- package/build/navigation/edit/leaf-more-menu.js +6 -1
- package/build/navigation/edit/leaf-more-menu.js.map +1 -1
- package/build/navigation-link/edit.js +3 -140
- package/build/navigation-link/edit.js.map +1 -1
- package/build/navigation-link/shared/controls.js +171 -0
- package/build/navigation-link/shared/controls.js.map +1 -0
- package/build/navigation-link/shared/index.js +13 -0
- package/build/navigation-link/shared/index.js.map +1 -0
- package/build/navigation-submenu/edit.js +7 -114
- package/build/navigation-submenu/edit.js.map +1 -1
- package/build/pattern/index.js +1 -0
- package/build/pattern/index.js.map +1 -1
- package/build/post-date/edit.js +16 -3
- package/build/post-date/edit.js.map +1 -1
- package/build/post-time-to-read/edit.js +27 -15
- package/build/post-time-to-read/edit.js.map +1 -1
- package/build/post-time-to-read/index.js +7 -1
- package/build/post-time-to-read/index.js.map +1 -1
- package/build/post-time-to-read/variations.js +41 -0
- package/build/post-time-to-read/variations.js.map +1 -0
- package/build/query-title/edit.js +1 -1
- package/build/query-title/edit.js.map +1 -1
- package/build/table-of-contents/index.js +1 -0
- package/build/table-of-contents/index.js.map +1 -1
- package/build/template-part/index.js +1 -0
- package/build/template-part/index.js.map +1 -1
- package/build/utils/get-transformed-metadata.js +7 -0
- package/build/utils/get-transformed-metadata.js.map +1 -1
- package/build-module/accordion/edit.js +66 -16
- package/build-module/accordion/edit.js.map +1 -1
- package/build-module/accordion/index.js +15 -8
- package/build-module/accordion/index.js.map +1 -1
- package/build-module/accordion/view.js +15 -15
- package/build-module/accordion/view.js.map +1 -1
- package/build-module/accordion-heading/edit.js +61 -0
- package/build-module/accordion-heading/edit.js.map +1 -0
- package/build-module/accordion-heading/icon.js.map +1 -0
- package/build-module/{accordion-header → accordion-heading}/index.js +9 -17
- package/build-module/accordion-heading/index.js.map +1 -0
- package/build-module/{accordion-content → accordion-heading}/init.js.map +1 -1
- package/build-module/{accordion-header → accordion-heading}/save.js +7 -18
- package/build-module/accordion-heading/save.js.map +1 -0
- package/build-module/{accordion-content → accordion-item}/edit.js +8 -2
- package/build-module/accordion-item/edit.js.map +1 -0
- package/build-module/accordion-item/icon.js.map +1 -0
- package/build-module/{accordion-content → accordion-item}/index.js +6 -5
- package/build-module/accordion-item/index.js.map +1 -0
- package/build-module/accordion-item/init.js.map +1 -0
- package/build-module/{accordion-content → accordion-item}/save.js +5 -7
- package/build-module/accordion-item/save.js.map +1 -0
- package/build-module/accordion-panel/edit.js +2 -1
- package/build-module/accordion-panel/edit.js.map +1 -1
- package/build-module/accordion-panel/index.js +5 -3
- package/build-module/accordion-panel/index.js.map +1 -1
- package/build-module/accordion-panel/save.js +3 -1
- package/build-module/accordion-panel/save.js.map +1 -1
- package/build-module/block/index.js +1 -0
- package/build-module/block/index.js.map +1 -1
- package/build-module/group/variations.js +3 -4
- package/build-module/group/variations.js.map +1 -1
- package/build-module/index.js +25 -5
- package/build-module/index.js.map +1 -1
- package/build-module/navigation/edit/leaf-more-menu.js +6 -1
- package/build-module/navigation/edit/leaf-more-menu.js.map +1 -1
- package/build-module/navigation-link/edit.js +4 -141
- package/build-module/navigation-link/edit.js.map +1 -1
- package/build-module/navigation-link/shared/controls.js +165 -0
- package/build-module/navigation-link/shared/controls.js.map +1 -0
- package/build-module/navigation-link/shared/index.js +9 -0
- package/build-module/navigation-link/shared/index.js.map +1 -0
- package/build-module/navigation-submenu/edit.js +7 -114
- package/build-module/navigation-submenu/edit.js.map +1 -1
- package/build-module/pattern/index.js +1 -0
- package/build-module/pattern/index.js.map +1 -1
- package/build-module/post-date/edit.js +17 -4
- package/build-module/post-date/edit.js.map +1 -1
- package/build-module/post-time-to-read/edit.js +27 -15
- package/build-module/post-time-to-read/edit.js.map +1 -1
- package/build-module/post-time-to-read/index.js +7 -1
- package/build-module/post-time-to-read/index.js.map +1 -1
- package/build-module/post-time-to-read/variations.js +33 -0
- package/build-module/post-time-to-read/variations.js.map +1 -0
- package/build-module/query-title/edit.js +1 -1
- package/build-module/query-title/edit.js.map +1 -1
- package/build-module/table-of-contents/index.js +1 -0
- package/build-module/table-of-contents/index.js.map +1 -1
- package/build-module/template-part/index.js +1 -0
- package/build-module/template-part/index.js.map +1 -1
- package/build-module/utils/get-transformed-metadata.js +7 -0
- package/build-module/utils/get-transformed-metadata.js.map +1 -1
- package/build-style/{accordion → accordion-heading}/style-rtl.css +9 -54
- package/build-style/{accordion → accordion-heading}/style.css +9 -54
- package/build-style/accordion-item/style-rtl.css +155 -0
- package/build-style/accordion-item/style.css +155 -0
- package/build-style/accordion-panel/style-rtl.css +140 -0
- package/build-style/accordion-panel/style.css +140 -0
- package/build-style/style-rtl.css +23 -42
- package/build-style/style.css +23 -42
- package/package.json +35 -35
- package/src/accordion/block.json +11 -4
- package/src/accordion/edit.js +70 -13
- package/src/accordion/index.js +4 -4
- package/src/accordion/index.php +1 -1
- package/src/accordion/view.js +15 -15
- package/src/{accordion-header → accordion-heading}/block.json +10 -17
- package/src/accordion-heading/edit.js +70 -0
- package/src/{accordion-header → accordion-heading}/save.js +8 -18
- package/src/accordion-heading/style.scss +43 -0
- package/src/{accordion-content → accordion-item}/block.json +6 -5
- package/src/{accordion-content → accordion-item}/edit.js +12 -2
- package/src/{accordion-content → accordion-item}/index.php +11 -11
- package/src/{accordion-content → accordion-item}/save.js +4 -10
- package/src/accordion-item/style.scss +21 -0
- package/src/accordion-panel/block.json +5 -3
- package/src/accordion-panel/edit.js +1 -0
- package/src/accordion-panel/save.js +3 -1
- package/src/accordion-panel/style.scss +8 -0
- package/src/block/block.json +1 -0
- package/src/comments/index.php +2 -2
- package/src/group/variations.js +3 -14
- package/src/index.js +23 -4
- package/src/navigation/edit/leaf-more-menu.js +9 -1
- package/src/navigation/index.php +2 -2
- package/src/navigation-link/edit.js +3 -142
- package/src/navigation-link/shared/README.md +47 -0
- package/src/navigation-link/shared/controls.js +167 -0
- package/src/navigation-link/shared/index.js +8 -0
- package/src/navigation-link/shared/test/controls.js +210 -0
- package/src/navigation-submenu/edit.js +8 -129
- package/src/pattern/block.json +1 -0
- package/src/post-date/edit.js +16 -16
- package/src/post-time-to-read/block.json +5 -1
- package/src/post-time-to-read/edit.js +87 -59
- package/src/post-time-to-read/index.js +2 -0
- package/src/post-time-to-read/index.php +48 -23
- package/src/post-time-to-read/variations.js +39 -0
- package/src/query-title/edit.js +2 -1
- package/src/query-title/index.php +3 -1
- package/src/social-link/index.php +2 -2
- package/src/style.scss +3 -1
- package/src/table-of-contents/block.json +1 -0
- package/src/table-of-contents/index.php +44 -0
- package/src/template-part/block.json +1 -0
- package/src/utils/get-transformed-metadata.js +8 -0
- package/build/accordion-content/edit.js.map +0 -1
- package/build/accordion-content/icon.js.map +0 -1
- package/build/accordion-content/index.js.map +0 -1
- package/build/accordion-content/save.js.map +0 -1
- package/build/accordion-header/edit.js +0 -94
- package/build/accordion-header/edit.js.map +0 -1
- package/build/accordion-header/icon.js.map +0 -1
- package/build/accordion-header/index.js.map +0 -1
- package/build/accordion-header/init.js.map +0 -1
- package/build/accordion-header/save.js.map +0 -1
- package/build-module/accordion-content/edit.js.map +0 -1
- package/build-module/accordion-content/icon.js.map +0 -1
- package/build-module/accordion-content/index.js.map +0 -1
- package/build-module/accordion-content/save.js.map +0 -1
- package/build-module/accordion-header/edit.js +0 -85
- package/build-module/accordion-header/edit.js.map +0 -1
- package/build-module/accordion-header/icon.js.map +0 -1
- package/build-module/accordion-header/index.js.map +0 -1
- package/build-module/accordion-header/init.js.map +0 -1
- package/build-module/accordion-header/save.js.map +0 -1
- package/src/accordion/style.scss +0 -90
- package/src/accordion-header/edit.js +0 -94
- /package/build/{accordion-header → accordion-heading}/icon.js +0 -0
- /package/build/{accordion-content → accordion-heading}/init.js +0 -0
- /package/build/{accordion-content → accordion-item}/icon.js +0 -0
- /package/build/{accordion-header → accordion-item}/init.js +0 -0
- /package/build-module/{accordion-header → accordion-heading}/icon.js +0 -0
- /package/build-module/{accordion-content → accordion-heading}/init.js +0 -0
- /package/build-module/{accordion-content → accordion-item}/icon.js +0 -0
- /package/build-module/{accordion-header → accordion-item}/init.js +0 -0
- /package/src/{accordion-header → accordion-heading}/icon.js +0 -0
- /package/src/{accordion-content → accordion-heading}/index.js +0 -0
- /package/src/{accordion-content → accordion-heading}/init.js +0 -0
- /package/src/{accordion-content → accordion-item}/icon.js +0 -0
- /package/src/{accordion-header → accordion-item}/index.js +0 -0
- /package/src/{accordion-header → accordion-item}/init.js +0 -0
|
@@ -4,7 +4,9 @@
|
|
|
4
4
|
import { useBlockProps, useInnerBlocksProps } from '@wordpress/block-editor';
|
|
5
5
|
|
|
6
6
|
export default function save() {
|
|
7
|
-
const blockProps = useBlockProps.save(
|
|
7
|
+
const blockProps = useBlockProps.save( {
|
|
8
|
+
role: 'region',
|
|
9
|
+
} );
|
|
8
10
|
const innerBlocksProps = useInnerBlocksProps.save( blockProps );
|
|
9
11
|
return <div { ...innerBlocksProps } />;
|
|
10
12
|
}
|
package/src/block/block.json
CHANGED
package/src/comments/index.php
CHANGED
|
@@ -28,11 +28,11 @@
|
|
|
28
28
|
function render_block_core_comments( $attributes, $content, $block ) {
|
|
29
29
|
global $post;
|
|
30
30
|
|
|
31
|
-
|
|
32
|
-
if ( ! isset( $post_id ) ) {
|
|
31
|
+
if ( ! isset( $block->context['postId'] ) ) {
|
|
33
32
|
return '';
|
|
34
33
|
}
|
|
35
34
|
|
|
35
|
+
$post_id = $block->context['postId'];
|
|
36
36
|
// Return early if there are no comments and comments are closed.
|
|
37
37
|
if ( ! comments_open( $post_id ) && (int) get_comments_number( $post_id ) === 0 ) {
|
|
38
38
|
return '';
|
package/src/group/variations.js
CHANGED
|
@@ -53,11 +53,6 @@ const variations = [
|
|
|
53
53
|
attributes: { layout: { type: 'constrained' } },
|
|
54
54
|
isDefault: true,
|
|
55
55
|
scope: [ 'block', 'inserter', 'transform' ],
|
|
56
|
-
isActive: ( blockAttributes ) =>
|
|
57
|
-
! blockAttributes.layout ||
|
|
58
|
-
! blockAttributes.layout?.type ||
|
|
59
|
-
blockAttributes.layout?.type === 'default' ||
|
|
60
|
-
blockAttributes.layout?.type === 'constrained',
|
|
61
56
|
icon: group,
|
|
62
57
|
},
|
|
63
58
|
{
|
|
@@ -66,10 +61,7 @@ const variations = [
|
|
|
66
61
|
description: __( 'Arrange blocks horizontally.' ),
|
|
67
62
|
attributes: { layout: { type: 'flex', flexWrap: 'nowrap' } },
|
|
68
63
|
scope: [ 'block', 'inserter', 'transform' ],
|
|
69
|
-
isActive:
|
|
70
|
-
blockAttributes.layout?.type === 'flex' &&
|
|
71
|
-
( ! blockAttributes.layout?.orientation ||
|
|
72
|
-
blockAttributes.layout?.orientation === 'horizontal' ),
|
|
64
|
+
isActive: [ 'layout.type' ],
|
|
73
65
|
icon: row,
|
|
74
66
|
example,
|
|
75
67
|
},
|
|
@@ -79,9 +71,7 @@ const variations = [
|
|
|
79
71
|
description: __( 'Arrange blocks vertically.' ),
|
|
80
72
|
attributes: { layout: { type: 'flex', orientation: 'vertical' } },
|
|
81
73
|
scope: [ 'block', 'inserter', 'transform' ],
|
|
82
|
-
isActive:
|
|
83
|
-
blockAttributes.layout?.type === 'flex' &&
|
|
84
|
-
blockAttributes.layout?.orientation === 'vertical',
|
|
74
|
+
isActive: [ 'layout.type', 'layout.orientation' ],
|
|
85
75
|
icon: stack,
|
|
86
76
|
example,
|
|
87
77
|
},
|
|
@@ -91,8 +81,7 @@ const variations = [
|
|
|
91
81
|
description: __( 'Arrange blocks in a grid.' ),
|
|
92
82
|
attributes: { layout: { type: 'grid' } },
|
|
93
83
|
scope: [ 'block', 'inserter', 'transform' ],
|
|
94
|
-
isActive:
|
|
95
|
-
blockAttributes.layout?.type === 'grid',
|
|
84
|
+
isActive: [ 'layout.type' ],
|
|
96
85
|
icon: grid,
|
|
97
86
|
example,
|
|
98
87
|
},
|
package/src/index.js
CHANGED
|
@@ -6,7 +6,10 @@ import {
|
|
|
6
6
|
setFreeformContentHandlerName,
|
|
7
7
|
setUnregisteredTypeHandlerName,
|
|
8
8
|
setGroupingBlockName,
|
|
9
|
+
registerBlockType,
|
|
9
10
|
} from '@wordpress/blocks';
|
|
11
|
+
import { createElement } from '@wordpress/element';
|
|
12
|
+
import ServerSideRender from '@wordpress/server-side-render';
|
|
10
13
|
|
|
11
14
|
/**
|
|
12
15
|
* Internal dependencies
|
|
@@ -21,8 +24,8 @@ import {
|
|
|
21
24
|
//
|
|
22
25
|
// See https://github.com/WordPress/gutenberg/pull/40655 for more context.
|
|
23
26
|
import * as accordion from './accordion';
|
|
24
|
-
import * as
|
|
25
|
-
import * as
|
|
27
|
+
import * as accordionItem from './accordion-item';
|
|
28
|
+
import * as accordionHeading from './accordion-heading';
|
|
26
29
|
import * as accordionPanel from './accordion-panel';
|
|
27
30
|
import * as archives from './archives';
|
|
28
31
|
import * as avatar from './avatar';
|
|
@@ -243,8 +246,8 @@ const getAllBlocks = () => {
|
|
|
243
246
|
|
|
244
247
|
if ( window?.__experimentalEnableBlockExperiments ) {
|
|
245
248
|
blocks.push( accordion );
|
|
246
|
-
blocks.push(
|
|
247
|
-
blocks.push(
|
|
249
|
+
blocks.push( accordionItem );
|
|
250
|
+
blocks.push( accordionHeading );
|
|
248
251
|
blocks.push( accordionPanel );
|
|
249
252
|
blocks.push( termsQuery );
|
|
250
253
|
blocks.push( termTemplate );
|
|
@@ -309,6 +312,22 @@ export const registerCoreBlocks = (
|
|
|
309
312
|
) => {
|
|
310
313
|
blocks.forEach( ( { init } ) => init() );
|
|
311
314
|
|
|
315
|
+
// Auto-register PHP-only blocks with ServerSideRender
|
|
316
|
+
if ( window.__unstableAutoRegisterBlocks ) {
|
|
317
|
+
window.__unstableAutoRegisterBlocks.forEach( ( blockName ) => {
|
|
318
|
+
registerBlockType( blockName, {
|
|
319
|
+
title: blockName,
|
|
320
|
+
edit: ( { attributes } ) => {
|
|
321
|
+
return createElement( ServerSideRender, {
|
|
322
|
+
block: blockName,
|
|
323
|
+
attributes,
|
|
324
|
+
} );
|
|
325
|
+
},
|
|
326
|
+
save: () => null,
|
|
327
|
+
} );
|
|
328
|
+
} );
|
|
329
|
+
}
|
|
330
|
+
|
|
312
331
|
setDefaultBlockName( paragraph.name );
|
|
313
332
|
if (
|
|
314
333
|
window.wp &&
|
|
@@ -13,6 +13,11 @@ import { useDispatch, useSelect } from '@wordpress/data';
|
|
|
13
13
|
import { __, sprintf } from '@wordpress/i18n';
|
|
14
14
|
import { BlockTitle, store as blockEditorStore } from '@wordpress/block-editor';
|
|
15
15
|
|
|
16
|
+
/**
|
|
17
|
+
* Internal dependencies
|
|
18
|
+
*/
|
|
19
|
+
import { DEFAULT_BLOCK } from '../constants';
|
|
20
|
+
|
|
16
21
|
const POPOVER_PROPS = {
|
|
17
22
|
className: 'block-editor-block-settings-menu__popover',
|
|
18
23
|
placement: 'bottom-start',
|
|
@@ -43,7 +48,10 @@ function AddSubmenuItem( {
|
|
|
43
48
|
disabled={ isDisabled }
|
|
44
49
|
onClick={ () => {
|
|
45
50
|
const updateSelectionOnInsert = false;
|
|
46
|
-
const newLink = createBlock(
|
|
51
|
+
const newLink = createBlock(
|
|
52
|
+
DEFAULT_BLOCK.name,
|
|
53
|
+
DEFAULT_BLOCK.attributes
|
|
54
|
+
);
|
|
47
55
|
|
|
48
56
|
if ( block.name === 'core/navigation-submenu' ) {
|
|
49
57
|
insertBlock(
|
package/src/navigation/index.php
CHANGED
|
@@ -478,10 +478,10 @@ class WP_Navigation_Block_Renderer {
|
|
|
478
478
|
);
|
|
479
479
|
|
|
480
480
|
$should_display_icon_label = isset( $attributes['hasIcon'] ) && true === $attributes['hasIcon'];
|
|
481
|
-
$toggle_button_icon = '<svg width="24" height="24" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><
|
|
481
|
+
$toggle_button_icon = '<svg width="24" height="24" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M4 7.5h16v1.5H4z"></path><path d="M4 15h16v1.5H4z"></path></svg>';
|
|
482
482
|
if ( isset( $attributes['icon'] ) ) {
|
|
483
483
|
if ( 'menu' === $attributes['icon'] ) {
|
|
484
|
-
$toggle_button_icon = '<svg width="24" height="24" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M5 5v1.
|
|
484
|
+
$toggle_button_icon = '<svg width="24" height="24" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M5 5v1.5h14V5H5z"></path><path d="M5 12.8h14v-1.5H5v1.5z"></path><path d="M5 19h14v-1.5H5V19z"></path></svg>';
|
|
485
485
|
}
|
|
486
486
|
}
|
|
487
487
|
$toggle_button_content = $should_display_icon_label ? $toggle_button_icon : __( 'Menu' );
|
|
@@ -8,15 +8,7 @@ import clsx from 'clsx';
|
|
|
8
8
|
*/
|
|
9
9
|
import { createBlock } from '@wordpress/blocks';
|
|
10
10
|
import { useSelect, useDispatch } from '@wordpress/data';
|
|
11
|
-
import {
|
|
12
|
-
__experimentalToolsPanel as ToolsPanel,
|
|
13
|
-
__experimentalToolsPanelItem as ToolsPanelItem,
|
|
14
|
-
CheckboxControl,
|
|
15
|
-
TextControl,
|
|
16
|
-
TextareaControl,
|
|
17
|
-
ToolbarButton,
|
|
18
|
-
ToolbarGroup,
|
|
19
|
-
} from '@wordpress/components';
|
|
11
|
+
import { ToolbarButton, ToolbarGroup } from '@wordpress/components';
|
|
20
12
|
import { displayShortcut, isKeyboardEvent } from '@wordpress/keycodes';
|
|
21
13
|
import { __ } from '@wordpress/i18n';
|
|
22
14
|
import {
|
|
@@ -29,9 +21,8 @@ import {
|
|
|
29
21
|
useInnerBlocksProps,
|
|
30
22
|
useBlockEditingMode,
|
|
31
23
|
} from '@wordpress/block-editor';
|
|
32
|
-
import { isURL, prependHTTP
|
|
24
|
+
import { isURL, prependHTTP } from '@wordpress/url';
|
|
33
25
|
import { useState, useEffect, useRef } from '@wordpress/element';
|
|
34
|
-
import { __unstableStripHTML as stripHTML } from '@wordpress/dom';
|
|
35
26
|
import { decodeEntities } from '@wordpress/html-entities';
|
|
36
27
|
import { link as linkIcon, addSubmenu } from '@wordpress/icons';
|
|
37
28
|
import { store as coreStore } from '@wordpress/core-data';
|
|
@@ -43,7 +34,7 @@ import { useMergeRefs, usePrevious } from '@wordpress/compose';
|
|
|
43
34
|
import { LinkUI } from './link-ui';
|
|
44
35
|
import { updateAttributes } from './update-attributes';
|
|
45
36
|
import { getColors } from '../navigation/edit/utils';
|
|
46
|
-
import {
|
|
37
|
+
import { Controls } from './shared';
|
|
47
38
|
|
|
48
39
|
const DEFAULT_BLOCK = { name: 'core/navigation-link' };
|
|
49
40
|
const NESTING_BLOCK_NAMES = [
|
|
@@ -175,136 +166,6 @@ function getMissingText( type ) {
|
|
|
175
166
|
* packages/block-library/src/navigation-submenu/edit.js
|
|
176
167
|
* Consider reusing this components for both blocks.
|
|
177
168
|
*/
|
|
178
|
-
function Controls( { attributes, setAttributes, setIsEditingControl } ) {
|
|
179
|
-
const { label, url, description, rel, opensInNewTab } = attributes;
|
|
180
|
-
const lastURLRef = useRef( url );
|
|
181
|
-
const dropdownMenuProps = useToolsPanelDropdownMenuProps();
|
|
182
|
-
return (
|
|
183
|
-
<ToolsPanel
|
|
184
|
-
label={ __( 'Settings' ) }
|
|
185
|
-
resetAll={ () => {
|
|
186
|
-
setAttributes( {
|
|
187
|
-
label: '',
|
|
188
|
-
url: '',
|
|
189
|
-
description: '',
|
|
190
|
-
rel: '',
|
|
191
|
-
opensInNewTab: false,
|
|
192
|
-
} );
|
|
193
|
-
} }
|
|
194
|
-
dropdownMenuProps={ dropdownMenuProps }
|
|
195
|
-
>
|
|
196
|
-
<ToolsPanelItem
|
|
197
|
-
hasValue={ () => !! label }
|
|
198
|
-
label={ __( 'Text' ) }
|
|
199
|
-
onDeselect={ () => setAttributes( { label: '' } ) }
|
|
200
|
-
isShownByDefault
|
|
201
|
-
>
|
|
202
|
-
<TextControl
|
|
203
|
-
__nextHasNoMarginBottom
|
|
204
|
-
__next40pxDefaultSize
|
|
205
|
-
label={ __( 'Text' ) }
|
|
206
|
-
value={ label ? stripHTML( label ) : '' }
|
|
207
|
-
onChange={ ( labelValue ) => {
|
|
208
|
-
setAttributes( { label: labelValue } );
|
|
209
|
-
} }
|
|
210
|
-
autoComplete="off"
|
|
211
|
-
onFocus={ () => setIsEditingControl( true ) }
|
|
212
|
-
onBlur={ () => setIsEditingControl( false ) }
|
|
213
|
-
/>
|
|
214
|
-
</ToolsPanelItem>
|
|
215
|
-
|
|
216
|
-
<ToolsPanelItem
|
|
217
|
-
hasValue={ () => !! url }
|
|
218
|
-
label={ __( 'Link' ) }
|
|
219
|
-
onDeselect={ () => setAttributes( { url: '' } ) }
|
|
220
|
-
isShownByDefault
|
|
221
|
-
>
|
|
222
|
-
<TextControl
|
|
223
|
-
__nextHasNoMarginBottom
|
|
224
|
-
__next40pxDefaultSize
|
|
225
|
-
label={ __( 'Link' ) }
|
|
226
|
-
value={ url ? safeDecodeURI( url ) : '' }
|
|
227
|
-
onChange={ ( urlValue ) => {
|
|
228
|
-
setAttributes( {
|
|
229
|
-
url: encodeURI( safeDecodeURI( urlValue ) ),
|
|
230
|
-
} );
|
|
231
|
-
} }
|
|
232
|
-
autoComplete="off"
|
|
233
|
-
type="url"
|
|
234
|
-
onFocus={ () => {
|
|
235
|
-
lastURLRef.current = url;
|
|
236
|
-
setIsEditingControl( true );
|
|
237
|
-
} }
|
|
238
|
-
onBlur={ () => {
|
|
239
|
-
// Defer the updateAttributes call to ensure entity connection isn't severed by accident.
|
|
240
|
-
updateAttributes(
|
|
241
|
-
{ url: ! url ? lastURLRef.current : url },
|
|
242
|
-
setAttributes,
|
|
243
|
-
{ ...attributes, url: lastURLRef.current }
|
|
244
|
-
);
|
|
245
|
-
setIsEditingControl( false );
|
|
246
|
-
} }
|
|
247
|
-
/>
|
|
248
|
-
</ToolsPanelItem>
|
|
249
|
-
|
|
250
|
-
<ToolsPanelItem
|
|
251
|
-
hasValue={ () => !! opensInNewTab }
|
|
252
|
-
label={ __( 'Open in new tab' ) }
|
|
253
|
-
onDeselect={ () => setAttributes( { opensInNewTab: false } ) }
|
|
254
|
-
isShownByDefault
|
|
255
|
-
>
|
|
256
|
-
<CheckboxControl
|
|
257
|
-
__nextHasNoMarginBottom
|
|
258
|
-
label={ __( 'Open in new tab' ) }
|
|
259
|
-
checked={ opensInNewTab }
|
|
260
|
-
onChange={ ( value ) =>
|
|
261
|
-
setAttributes( { opensInNewTab: value } )
|
|
262
|
-
}
|
|
263
|
-
/>
|
|
264
|
-
</ToolsPanelItem>
|
|
265
|
-
|
|
266
|
-
<ToolsPanelItem
|
|
267
|
-
hasValue={ () => !! description }
|
|
268
|
-
label={ __( 'Description' ) }
|
|
269
|
-
onDeselect={ () => setAttributes( { description: '' } ) }
|
|
270
|
-
isShownByDefault
|
|
271
|
-
>
|
|
272
|
-
<TextareaControl
|
|
273
|
-
__nextHasNoMarginBottom
|
|
274
|
-
label={ __( 'Description' ) }
|
|
275
|
-
value={ description || '' }
|
|
276
|
-
onChange={ ( descriptionValue ) => {
|
|
277
|
-
setAttributes( { description: descriptionValue } );
|
|
278
|
-
} }
|
|
279
|
-
help={ __(
|
|
280
|
-
'The description will be displayed in the menu if the current theme supports it.'
|
|
281
|
-
) }
|
|
282
|
-
/>
|
|
283
|
-
</ToolsPanelItem>
|
|
284
|
-
|
|
285
|
-
<ToolsPanelItem
|
|
286
|
-
hasValue={ () => !! rel }
|
|
287
|
-
label={ __( 'Rel attribute' ) }
|
|
288
|
-
onDeselect={ () => setAttributes( { rel: '' } ) }
|
|
289
|
-
isShownByDefault
|
|
290
|
-
>
|
|
291
|
-
<TextControl
|
|
292
|
-
__nextHasNoMarginBottom
|
|
293
|
-
__next40pxDefaultSize
|
|
294
|
-
label={ __( 'Rel attribute' ) }
|
|
295
|
-
value={ rel || '' }
|
|
296
|
-
onChange={ ( relValue ) => {
|
|
297
|
-
setAttributes( { rel: relValue } );
|
|
298
|
-
} }
|
|
299
|
-
autoComplete="off"
|
|
300
|
-
help={ __(
|
|
301
|
-
'The relationship of the linked URL as space-separated link types.'
|
|
302
|
-
) }
|
|
303
|
-
/>
|
|
304
|
-
</ToolsPanelItem>
|
|
305
|
-
</ToolsPanel>
|
|
306
|
-
);
|
|
307
|
-
}
|
|
308
169
|
|
|
309
170
|
export default function NavigationLinkEdit( {
|
|
310
171
|
attributes,
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# Navigation Blocks Shared Components
|
|
2
|
+
|
|
3
|
+
This directory contains shared components and utilities used by both the Navigation Link and Navigation Submenu blocks to reduce code duplication and ensure consistent behavior.
|
|
4
|
+
|
|
5
|
+
## Purpose
|
|
6
|
+
|
|
7
|
+
The Navigation Link and Navigation Submenu blocks share significant functionality, particularly in their inspector controls (ToolsPanel). This shared directory was created to:
|
|
8
|
+
|
|
9
|
+
- **Reduce code duplication** - Eliminate identical code between the two blocks
|
|
10
|
+
- **Ensure consistency** - Both blocks now use the same components, preventing behavioral differences
|
|
11
|
+
- **Reduce maintenance burden** - Changes to shared functionality only need to be made in one place
|
|
12
|
+
- **Minimize bugs** - Less duplicated code means fewer places for bugs to hide
|
|
13
|
+
- **Improve testability** - Shared components can be tested once and reused
|
|
14
|
+
|
|
15
|
+
## Current Shared Components
|
|
16
|
+
|
|
17
|
+
- **`Controls`** - Inspector controls component providing the ToolsPanel interface for both blocks
|
|
18
|
+
|
|
19
|
+
## Future Direction
|
|
20
|
+
|
|
21
|
+
While this shared directory provides immediate benefits for reducing duplication, the long-term vision is to refactor towards a **unified Navigation Item block** that can behave differently based on context (link vs submenu). This would:
|
|
22
|
+
|
|
23
|
+
- Eliminate the need for separate Navigation Link and Navigation Submenu blocks
|
|
24
|
+
- Provide a single, more maintainable codebase
|
|
25
|
+
- Allow for more flexible navigation item types
|
|
26
|
+
- Simplify the user experience
|
|
27
|
+
|
|
28
|
+
However, this refactoring is beyond the current scope and would require significant architectural changes. For now, this shared directory provides a practical solution that:
|
|
29
|
+
|
|
30
|
+
- Maintains backward compatibility
|
|
31
|
+
- Reduces immediate technical debt
|
|
32
|
+
- Prepares the foundation for future unification
|
|
33
|
+
- Supports the integration of new features like Dynamic URL functionality
|
|
34
|
+
|
|
35
|
+
## Testing
|
|
36
|
+
|
|
37
|
+
All shared components include comprehensive tests in the `test/` directory. The tests use pure mocking strategies to ensure isolated, reliable testing of component behavior.
|
|
38
|
+
|
|
39
|
+
## Contributing
|
|
40
|
+
|
|
41
|
+
When adding new shared functionality:
|
|
42
|
+
|
|
43
|
+
1. Place shared components in this directory
|
|
44
|
+
2. Export them from `index.js`
|
|
45
|
+
3. Add comprehensive tests
|
|
46
|
+
4. Update both Navigation Link and Navigation Submenu blocks to use the shared component
|
|
47
|
+
5. Remove any duplicated code from the individual blocks
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WordPress dependencies
|
|
3
|
+
*/
|
|
4
|
+
import {
|
|
5
|
+
__experimentalToolsPanel as ToolsPanel,
|
|
6
|
+
__experimentalToolsPanelItem as ToolsPanelItem,
|
|
7
|
+
CheckboxControl,
|
|
8
|
+
TextControl,
|
|
9
|
+
TextareaControl,
|
|
10
|
+
} from '@wordpress/components';
|
|
11
|
+
import { __ } from '@wordpress/i18n';
|
|
12
|
+
import { useRef } from '@wordpress/element';
|
|
13
|
+
import { safeDecodeURI } from '@wordpress/url';
|
|
14
|
+
import { __unstableStripHTML as stripHTML } from '@wordpress/dom';
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Internal dependencies
|
|
18
|
+
*/
|
|
19
|
+
import { useToolsPanelDropdownMenuProps } from '../../utils/hooks';
|
|
20
|
+
import { updateAttributes } from '../update-attributes';
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Shared Controls component for Navigation Link and Navigation Submenu blocks.
|
|
24
|
+
*
|
|
25
|
+
* This component provides the inspector controls (ToolsPanel) that are identical
|
|
26
|
+
* between both navigation blocks.
|
|
27
|
+
*
|
|
28
|
+
* @param {Object} props - Component props
|
|
29
|
+
* @param {Object} props.attributes - Block attributes
|
|
30
|
+
* @param {Function} props.setAttributes - Function to update block attributes
|
|
31
|
+
* @param {Function} props.setIsEditingControl - Function to set editing state (optional)
|
|
32
|
+
*/
|
|
33
|
+
export function Controls( {
|
|
34
|
+
attributes,
|
|
35
|
+
setAttributes,
|
|
36
|
+
setIsEditingControl = () => {},
|
|
37
|
+
} ) {
|
|
38
|
+
const { label, url, description, rel, opensInNewTab } = attributes;
|
|
39
|
+
const lastURLRef = useRef( url );
|
|
40
|
+
const dropdownMenuProps = useToolsPanelDropdownMenuProps();
|
|
41
|
+
|
|
42
|
+
return (
|
|
43
|
+
<ToolsPanel
|
|
44
|
+
label={ __( 'Settings' ) }
|
|
45
|
+
resetAll={ () => {
|
|
46
|
+
setAttributes( {
|
|
47
|
+
label: '',
|
|
48
|
+
url: '',
|
|
49
|
+
description: '',
|
|
50
|
+
rel: '',
|
|
51
|
+
opensInNewTab: false,
|
|
52
|
+
} );
|
|
53
|
+
} }
|
|
54
|
+
dropdownMenuProps={ dropdownMenuProps }
|
|
55
|
+
>
|
|
56
|
+
<ToolsPanelItem
|
|
57
|
+
hasValue={ () => !! label }
|
|
58
|
+
label={ __( 'Text' ) }
|
|
59
|
+
onDeselect={ () => setAttributes( { label: '' } ) }
|
|
60
|
+
isShownByDefault
|
|
61
|
+
>
|
|
62
|
+
<TextControl
|
|
63
|
+
__nextHasNoMarginBottom
|
|
64
|
+
__next40pxDefaultSize
|
|
65
|
+
label={ __( 'Text' ) }
|
|
66
|
+
value={ label ? stripHTML( label ) : '' }
|
|
67
|
+
onChange={ ( labelValue ) => {
|
|
68
|
+
setAttributes( { label: labelValue } );
|
|
69
|
+
} }
|
|
70
|
+
autoComplete="off"
|
|
71
|
+
onFocus={ () => setIsEditingControl( true ) }
|
|
72
|
+
onBlur={ () => setIsEditingControl( false ) }
|
|
73
|
+
/>
|
|
74
|
+
</ToolsPanelItem>
|
|
75
|
+
|
|
76
|
+
<ToolsPanelItem
|
|
77
|
+
hasValue={ () => !! url }
|
|
78
|
+
label={ __( 'Link' ) }
|
|
79
|
+
onDeselect={ () => setAttributes( { url: '' } ) }
|
|
80
|
+
isShownByDefault
|
|
81
|
+
>
|
|
82
|
+
<TextControl
|
|
83
|
+
__nextHasNoMarginBottom
|
|
84
|
+
__next40pxDefaultSize
|
|
85
|
+
label={ __( 'Link' ) }
|
|
86
|
+
value={ url ? safeDecodeURI( url ) : '' }
|
|
87
|
+
onChange={ ( urlValue ) => {
|
|
88
|
+
setAttributes( {
|
|
89
|
+
url: encodeURI( safeDecodeURI( urlValue ) ),
|
|
90
|
+
} );
|
|
91
|
+
} }
|
|
92
|
+
autoComplete="off"
|
|
93
|
+
type="url"
|
|
94
|
+
onFocus={ () => {
|
|
95
|
+
lastURLRef.current = url;
|
|
96
|
+
setIsEditingControl( true );
|
|
97
|
+
} }
|
|
98
|
+
onBlur={ () => {
|
|
99
|
+
// Defer the updateAttributes call to ensure entity connection isn't severed by accident.
|
|
100
|
+
updateAttributes(
|
|
101
|
+
{ url: ! url ? lastURLRef.current : url },
|
|
102
|
+
setAttributes,
|
|
103
|
+
{ ...attributes, url: lastURLRef.current }
|
|
104
|
+
);
|
|
105
|
+
setIsEditingControl( false );
|
|
106
|
+
} }
|
|
107
|
+
/>
|
|
108
|
+
</ToolsPanelItem>
|
|
109
|
+
|
|
110
|
+
<ToolsPanelItem
|
|
111
|
+
hasValue={ () => !! opensInNewTab }
|
|
112
|
+
label={ __( 'Open in new tab' ) }
|
|
113
|
+
onDeselect={ () => setAttributes( { opensInNewTab: false } ) }
|
|
114
|
+
isShownByDefault
|
|
115
|
+
>
|
|
116
|
+
<CheckboxControl
|
|
117
|
+
__nextHasNoMarginBottom
|
|
118
|
+
label={ __( 'Open in new tab' ) }
|
|
119
|
+
checked={ opensInNewTab }
|
|
120
|
+
onChange={ ( value ) =>
|
|
121
|
+
setAttributes( { opensInNewTab: value } )
|
|
122
|
+
}
|
|
123
|
+
/>
|
|
124
|
+
</ToolsPanelItem>
|
|
125
|
+
|
|
126
|
+
<ToolsPanelItem
|
|
127
|
+
hasValue={ () => !! description }
|
|
128
|
+
label={ __( 'Description' ) }
|
|
129
|
+
onDeselect={ () => setAttributes( { description: '' } ) }
|
|
130
|
+
isShownByDefault
|
|
131
|
+
>
|
|
132
|
+
<TextareaControl
|
|
133
|
+
__nextHasNoMarginBottom
|
|
134
|
+
label={ __( 'Description' ) }
|
|
135
|
+
value={ description || '' }
|
|
136
|
+
onChange={ ( descriptionValue ) => {
|
|
137
|
+
setAttributes( { description: descriptionValue } );
|
|
138
|
+
} }
|
|
139
|
+
help={ __(
|
|
140
|
+
'The description will be displayed in the menu if the current theme supports it.'
|
|
141
|
+
) }
|
|
142
|
+
/>
|
|
143
|
+
</ToolsPanelItem>
|
|
144
|
+
|
|
145
|
+
<ToolsPanelItem
|
|
146
|
+
hasValue={ () => !! rel }
|
|
147
|
+
label={ __( 'Rel attribute' ) }
|
|
148
|
+
onDeselect={ () => setAttributes( { rel: '' } ) }
|
|
149
|
+
isShownByDefault
|
|
150
|
+
>
|
|
151
|
+
<TextControl
|
|
152
|
+
__nextHasNoMarginBottom
|
|
153
|
+
__next40pxDefaultSize
|
|
154
|
+
label={ __( 'Rel attribute' ) }
|
|
155
|
+
value={ rel || '' }
|
|
156
|
+
onChange={ ( relValue ) => {
|
|
157
|
+
setAttributes( { rel: relValue } );
|
|
158
|
+
} }
|
|
159
|
+
autoComplete="off"
|
|
160
|
+
help={ __(
|
|
161
|
+
'The relationship of the linked URL as space-separated link types.'
|
|
162
|
+
) }
|
|
163
|
+
/>
|
|
164
|
+
</ToolsPanelItem>
|
|
165
|
+
</ToolsPanel>
|
|
166
|
+
);
|
|
167
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared components for Navigation Link and Navigation Submenu blocks.
|
|
3
|
+
*
|
|
4
|
+
* This module provides common functionality that can be used by both blocks
|
|
5
|
+
* to reduce code duplication and ensure consistent behavior.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
export { Controls } from './controls';
|