@wordpress/block-editor 15.8.1-next.16d95556a.0 → 15.8.1-next.dc3f6d3c1.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/build/components/block-inspector/edit-contents.js +19 -23
- package/build/components/block-inspector/edit-contents.js.map +3 -3
- package/build/components/block-inspector/index.js +7 -1
- package/build/components/block-inspector/index.js.map +2 -2
- package/build/components/block-list/block.js +4 -0
- package/build/components/block-list/block.js.map +2 -2
- package/build/components/block-list/use-block-props/index.js +3 -1
- package/build/components/block-list/use-block-props/index.js.map +2 -2
- package/build/components/block-list/use-block-props/use-is-hovered.js +16 -10
- package/build/components/block-list/use-block-props/use-is-hovered.js.map +2 -2
- package/build/components/block-settings-menu-controls/edit-section-menu-item.js +64 -0
- package/build/components/block-settings-menu-controls/edit-section-menu-item.js.map +7 -0
- package/build/components/block-settings-menu-controls/index.js +8 -0
- package/build/components/block-settings-menu-controls/index.js.map +2 -2
- package/build/components/block-toolbar/block-toolbar-icon.js +9 -9
- package/build/components/block-toolbar/block-toolbar-icon.js.map +2 -2
- package/build/components/block-variation-transforms/index.js +32 -5
- package/build/components/block-variation-transforms/index.js.map +2 -2
- package/build/components/border-radius-control/single-input-control.js +1 -0
- package/build/components/border-radius-control/single-input-control.js.map +2 -2
- package/build/components/content-only-controls/index.js +263 -0
- package/build/components/content-only-controls/index.js.map +7 -0
- package/build/components/content-only-controls/link/index.js +204 -0
- package/build/components/content-only-controls/link/index.js.map +7 -0
- package/build/components/content-only-controls/media/index.js +264 -0
- package/build/components/content-only-controls/media/index.js.map +7 -0
- package/build/components/content-only-controls/plain-text/index.js +68 -0
- package/build/components/content-only-controls/plain-text/index.js.map +7 -0
- package/build/components/content-only-controls/rich-text/index.js +197 -0
- package/build/components/content-only-controls/rich-text/index.js.map +7 -0
- package/build/components/content-only-controls/use-inspector-popover-placement.js +41 -0
- package/build/components/content-only-controls/use-inspector-popover-placement.js.map +7 -0
- package/build/components/inserter/media-tab/media-tab.js +1 -33
- package/build/components/inserter/media-tab/media-tab.js.map +3 -3
- package/build/components/inspector-controls-tabs/content-tab.js +6 -2
- package/build/components/inspector-controls-tabs/content-tab.js.map +3 -3
- package/build/components/inspector-controls-tabs/index.js +7 -1
- package/build/components/inspector-controls-tabs/index.js.map +2 -2
- package/build/components/list-view/block-select-button.js +11 -4
- package/build/components/list-view/block-select-button.js.map +2 -2
- package/build/components/media-placeholder/index.js +1 -31
- package/build/components/media-placeholder/index.js.map +3 -3
- package/build/components/media-replace-flow/index.js +4 -30
- package/build/components/media-replace-flow/index.js.map +3 -3
- package/build/components/use-block-display-information/index.js +21 -1
- package/build/components/use-block-display-information/index.js.map +3 -3
- package/build/hooks/block-bindings.js +52 -61
- package/build/hooks/block-bindings.js.map +3 -3
- package/build/hooks/use-content-only-section-edit.js +67 -0
- package/build/hooks/use-content-only-section-edit.js.map +7 -0
- package/build/layouts/constrained.js +2 -2
- package/build/layouts/constrained.js.map +2 -2
- package/build/private-apis.js +2 -3
- package/build/private-apis.js.map +3 -3
- package/build/store/private-keys.js +3 -0
- package/build/store/private-keys.js.map +2 -2
- package/build/store/private-selectors.js +1 -2
- package/build/store/private-selectors.js.map +2 -2
- package/build/store/reducer.js +1 -2
- package/build/store/reducer.js.map +2 -2
- package/build/utils/fit-text-utils.js +9 -1
- package/build/utils/fit-text-utils.js.map +2 -2
- package/build-module/components/block-inspector/edit-contents.js +9 -23
- package/build-module/components/block-inspector/edit-contents.js.map +2 -2
- package/build-module/components/block-inspector/index.js +7 -1
- package/build-module/components/block-inspector/index.js.map +2 -2
- package/build-module/components/block-list/block.js +4 -0
- package/build-module/components/block-list/block.js.map +2 -2
- package/build-module/components/block-list/use-block-props/index.js +3 -1
- package/build-module/components/block-list/use-block-props/index.js.map +2 -2
- package/build-module/components/block-list/use-block-props/use-is-hovered.js +16 -10
- package/build-module/components/block-list/use-block-props/use-is-hovered.js.map +2 -2
- package/build-module/components/block-settings-menu-controls/edit-section-menu-item.js +29 -0
- package/build-module/components/block-settings-menu-controls/edit-section-menu-item.js.map +7 -0
- package/build-module/components/block-settings-menu-controls/index.js +8 -0
- package/build-module/components/block-settings-menu-controls/index.js.map +2 -2
- package/build-module/components/block-toolbar/block-toolbar-icon.js +10 -10
- package/build-module/components/block-toolbar/block-toolbar-icon.js.map +2 -2
- package/build-module/components/block-variation-transforms/index.js +32 -5
- package/build-module/components/block-variation-transforms/index.js.map +2 -2
- package/build-module/components/border-radius-control/single-input-control.js +1 -0
- package/build-module/components/border-radius-control/single-input-control.js.map +2 -2
- package/build-module/components/content-only-controls/index.js +237 -0
- package/build-module/components/content-only-controls/index.js.map +7 -0
- package/build-module/components/content-only-controls/link/index.js +172 -0
- package/build-module/components/content-only-controls/link/index.js.map +7 -0
- package/build-module/components/content-only-controls/media/index.js +243 -0
- package/build-module/components/content-only-controls/media/index.js.map +7 -0
- package/build-module/components/content-only-controls/plain-text/index.js +50 -0
- package/build-module/components/content-only-controls/plain-text/index.js.map +7 -0
- package/build-module/components/content-only-controls/rich-text/index.js +174 -0
- package/build-module/components/content-only-controls/rich-text/index.js.map +7 -0
- package/build-module/components/content-only-controls/use-inspector-popover-placement.js +16 -0
- package/build-module/components/content-only-controls/use-inspector-popover-placement.js.map +7 -0
- package/build-module/components/inserter/media-tab/media-tab.js +2 -34
- package/build-module/components/inserter/media-tab/media-tab.js.map +2 -2
- package/build-module/components/inspector-controls-tabs/content-tab.js +7 -3
- package/build-module/components/inspector-controls-tabs/content-tab.js.map +2 -2
- package/build-module/components/inspector-controls-tabs/index.js +7 -1
- package/build-module/components/inspector-controls-tabs/index.js.map +2 -2
- package/build-module/components/list-view/block-select-button.js +18 -5
- package/build-module/components/list-view/block-select-button.js.map +2 -2
- package/build-module/components/media-placeholder/index.js +1 -31
- package/build-module/components/media-placeholder/index.js.map +2 -2
- package/build-module/components/media-replace-flow/index.js +4 -30
- package/build-module/components/media-replace-flow/index.js.map +2 -2
- package/build-module/components/use-block-display-information/index.js +21 -1
- package/build-module/components/use-block-display-information/index.js.map +3 -3
- package/build-module/hooks/block-bindings.js +57 -62
- package/build-module/hooks/block-bindings.js.map +2 -2
- package/build-module/hooks/use-content-only-section-edit.js +46 -0
- package/build-module/hooks/use-content-only-section-edit.js.map +7 -0
- package/build-module/layouts/constrained.js +2 -2
- package/build-module/layouts/constrained.js.map +2 -2
- package/build-module/private-apis.js +3 -3
- package/build-module/private-apis.js.map +2 -2
- package/build-module/store/private-keys.js +2 -0
- package/build-module/store/private-keys.js.map +2 -2
- package/build-module/store/private-selectors.js +1 -2
- package/build-module/store/private-selectors.js.map +2 -2
- package/build-module/store/reducer.js +1 -2
- package/build-module/store/reducer.js.map +2 -2
- package/build-module/utils/fit-text-utils.js +9 -1
- package/build-module/utils/fit-text-utils.js.map +2 -2
- package/build-style/style-rtl.css +132 -0
- package/build-style/style.css +132 -0
- package/package.json +37 -37
- package/src/components/block-inspector/edit-contents.js +10 -29
- package/src/components/block-inspector/index.js +4 -2
- package/src/components/block-list/block.js +6 -0
- package/src/components/block-list/use-block-props/index.js +3 -1
- package/src/components/block-list/use-block-props/use-is-hovered.js +24 -12
- package/src/components/block-settings-menu-controls/edit-section-menu-item.js +39 -0
- package/src/components/block-settings-menu-controls/index.js +7 -0
- package/src/components/block-toolbar/block-toolbar-icon.js +14 -10
- package/src/components/block-variation-transforms/index.js +96 -35
- package/src/components/border-radius-control/single-input-control.js +1 -0
- package/src/components/content-only-controls/index.js +296 -0
- package/src/components/content-only-controls/link/index.js +195 -0
- package/src/components/content-only-controls/link/styles.scss +23 -0
- package/src/components/content-only-controls/media/index.js +285 -0
- package/src/components/content-only-controls/media/styles.scss +47 -0
- package/src/components/content-only-controls/plain-text/index.js +49 -0
- package/src/components/content-only-controls/rich-text/index.js +193 -0
- package/src/components/content-only-controls/rich-text/styles.scss +24 -0
- package/src/components/content-only-controls/styles.scss +35 -0
- package/src/components/content-only-controls/use-inspector-popover-placement.js +19 -0
- package/src/components/inserter/media-tab/media-tab.js +2 -44
- package/src/components/inspector-controls-tabs/content-tab.js +12 -4
- package/src/components/inspector-controls-tabs/index.js +4 -1
- package/src/components/list-view/block-select-button.js +37 -24
- package/src/components/media-placeholder/index.js +1 -41
- package/src/components/media-replace-flow/index.js +3 -39
- package/src/components/use-block-display-information/index.js +30 -2
- package/src/hooks/block-bindings.js +71 -82
- package/src/hooks/use-content-only-section-edit.js +63 -0
- package/src/layouts/constrained.js +8 -2
- package/src/private-apis.js +2 -2
- package/src/store/private-keys.js +1 -0
- package/src/store/private-selectors.js +1 -2
- package/src/store/reducer.js +0 -3
- package/src/store/test/reducer.js +7 -17
- package/src/style.scss +1 -0
- package/src/utils/fit-text-utils.js +19 -1
- package/build/components/media-upload-modal/index.js +0 -29
- package/build/components/media-upload-modal/index.js.map +0 -7
- package/build-module/components/media-upload-modal/index.js +0 -8
- package/build-module/components/media-upload-modal/index.js.map +0 -7
- package/src/components/media-upload-modal/index.js +0 -18
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
import { ToolbarButton } from '@wordpress/components';
|
|
5
5
|
import { __ } from '@wordpress/i18n';
|
|
6
6
|
import { useSelect } from '@wordpress/data';
|
|
7
|
-
import { copy } from '@wordpress/icons';
|
|
7
|
+
import { copy, symbol } from '@wordpress/icons';
|
|
8
8
|
import { getBlockType, store as blocksStore } from '@wordpress/blocks';
|
|
9
9
|
import { store as preferencesStore } from '@wordpress/preferences';
|
|
10
10
|
|
|
@@ -24,7 +24,6 @@ function getBlockIconVariant( { select, clientIds } ) {
|
|
|
24
24
|
getBlockName,
|
|
25
25
|
getBlockAttributes,
|
|
26
26
|
getBlockParentsByBlockName,
|
|
27
|
-
isSectionBlock,
|
|
28
27
|
canRemoveBlocks,
|
|
29
28
|
getTemplateLock,
|
|
30
29
|
getBlockEditingMode,
|
|
@@ -40,8 +39,8 @@ function getBlockIconVariant( { select, clientIds } ) {
|
|
|
40
39
|
const blockName = isSingleBlock && getBlockName( clientIds[ 0 ] );
|
|
41
40
|
const hasBlockStyles =
|
|
42
41
|
isSingleBlock && !! getBlockStyles( blockName )?.length;
|
|
43
|
-
const
|
|
44
|
-
|
|
42
|
+
const hasPatternNameInSelection = clientIds.some(
|
|
43
|
+
( id ) => !! getBlockAttributes( id )?.metadata?.patternName
|
|
45
44
|
);
|
|
46
45
|
const hasPatternOverrides = clientIds.every( ( clientId ) =>
|
|
47
46
|
hasPatternOverridesDefaultBinding(
|
|
@@ -59,7 +58,7 @@ function getBlockIconVariant( { select, clientIds } ) {
|
|
|
59
58
|
getBlockEditingMode( clientIds[ 0 ] ) === 'default';
|
|
60
59
|
const _hideTransformsForSections =
|
|
61
60
|
window?.__experimentalContentOnlyPatternInsertion &&
|
|
62
|
-
|
|
61
|
+
hasPatternNameInSelection;
|
|
63
62
|
const _showBlockSwitcher =
|
|
64
63
|
! _hideTransformsForSections &&
|
|
65
64
|
isDefaultEditingMode &&
|
|
@@ -81,19 +80,24 @@ function getBlockIcon( { select, clientIds } ) {
|
|
|
81
80
|
const { getBlockName, getBlockAttributes } = unlock(
|
|
82
81
|
select( blockEditorStore )
|
|
83
82
|
);
|
|
84
|
-
const { getActiveBlockVariation } = select( blocksStore );
|
|
85
83
|
|
|
86
84
|
const _isSingleBlock = clientIds.length === 1;
|
|
87
85
|
const firstClientId = clientIds[ 0 ];
|
|
86
|
+
const blockAttributes = getBlockAttributes( firstClientId );
|
|
87
|
+
if (
|
|
88
|
+
_isSingleBlock &&
|
|
89
|
+
blockAttributes?.metadata?.patternName &&
|
|
90
|
+
window?.__experimentalContentOnlyPatternInsertion
|
|
91
|
+
) {
|
|
92
|
+
return symbol;
|
|
93
|
+
}
|
|
88
94
|
|
|
89
95
|
const blockName = getBlockName( firstClientId );
|
|
90
96
|
const blockType = getBlockType( blockName );
|
|
91
97
|
|
|
92
98
|
if ( _isSingleBlock ) {
|
|
93
|
-
const
|
|
94
|
-
|
|
95
|
-
getBlockAttributes( firstClientId )
|
|
96
|
-
);
|
|
99
|
+
const { getActiveBlockVariation } = select( blocksStore );
|
|
100
|
+
const match = getActiveBlockVariation( blockName, blockAttributes );
|
|
97
101
|
return match?.icon || blockType?.icon;
|
|
98
102
|
}
|
|
99
103
|
|
|
@@ -147,41 +147,102 @@ function VariationsToggleGroupControl( {
|
|
|
147
147
|
|
|
148
148
|
function __experimentalBlockVariationTransforms( { blockClientId } ) {
|
|
149
149
|
const { updateBlockAttributes } = useDispatch( blockEditorStore );
|
|
150
|
-
const {
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
150
|
+
const {
|
|
151
|
+
activeBlockVariation,
|
|
152
|
+
unfilteredVariations,
|
|
153
|
+
blockName,
|
|
154
|
+
isContentOnly,
|
|
155
|
+
isSection,
|
|
156
|
+
} = useSelect(
|
|
157
|
+
( select ) => {
|
|
158
|
+
const { getActiveBlockVariation, getBlockVariations } =
|
|
159
|
+
select( blocksStore );
|
|
160
|
+
|
|
161
|
+
const {
|
|
162
|
+
getBlockName,
|
|
163
|
+
getBlockAttributes,
|
|
164
|
+
getBlockEditingMode,
|
|
165
|
+
isSectionBlock,
|
|
166
|
+
} = unlock( select( blockEditorStore ) );
|
|
167
|
+
|
|
168
|
+
const name = blockClientId && getBlockName( blockClientId );
|
|
169
|
+
|
|
170
|
+
const { hasContentRoleAttribute } = unlock( select( blocksStore ) );
|
|
171
|
+
const isContentBlock = hasContentRoleAttribute( name );
|
|
172
|
+
|
|
173
|
+
return {
|
|
174
|
+
activeBlockVariation: getActiveBlockVariation(
|
|
175
|
+
name,
|
|
176
|
+
getBlockAttributes( blockClientId ),
|
|
177
|
+
'transform'
|
|
178
|
+
),
|
|
179
|
+
unfilteredVariations:
|
|
180
|
+
name && getBlockVariations( name, 'transform' ),
|
|
181
|
+
blockName: name,
|
|
182
|
+
isContentOnly:
|
|
183
|
+
getBlockEditingMode( blockClientId ) === 'contentOnly' &&
|
|
184
|
+
! isContentBlock,
|
|
185
|
+
isSection: isSectionBlock( blockClientId ),
|
|
186
|
+
};
|
|
187
|
+
},
|
|
188
|
+
[ blockClientId ]
|
|
189
|
+
);
|
|
190
|
+
|
|
191
|
+
/*
|
|
192
|
+
* Hack for WordPress 6.9
|
|
193
|
+
*
|
|
194
|
+
* The Stretchy blocks shipped in 6.9 were ultimately
|
|
195
|
+
* implemented as block variations of the base types Paragraph
|
|
196
|
+
* and Heading. See #73056 for discussion and trade-offs.
|
|
197
|
+
*
|
|
198
|
+
* The main drawback of this choice is that the Variations API
|
|
199
|
+
* doesn't offer enough control over how prominent and how tied
|
|
200
|
+
* to the base type a variation should be.
|
|
201
|
+
*
|
|
202
|
+
* In order to ship these new "blocks" with an acceptable UX,
|
|
203
|
+
* we need two hacks until the Variations API is improved:
|
|
204
|
+
*
|
|
205
|
+
* - Don't show the variations switcher in the block inspector
|
|
206
|
+
* for Paragraph, Heading, Stretchy Paragraph and Stretchy
|
|
207
|
+
* Heading (implemented below). Transformations are still
|
|
208
|
+
* available in the block switcher.
|
|
209
|
+
*
|
|
210
|
+
* - Move the stretchy variations to the end of the core blocks
|
|
211
|
+
* list in the block inserter (implemented in
|
|
212
|
+
* getInserterItems in #73056).
|
|
213
|
+
*/
|
|
214
|
+
const variations = useMemo( () => {
|
|
215
|
+
if ( blockName === 'core/paragraph' ) {
|
|
216
|
+
// Always hide options when active variation is stretchy, but
|
|
217
|
+
// ensure that there are no third-party variations before doing the
|
|
218
|
+
// same elsewhere.
|
|
219
|
+
if (
|
|
220
|
+
activeBlockVariation?.name === 'stretchy-paragraph' ||
|
|
221
|
+
unfilteredVariations.every( ( v ) =>
|
|
222
|
+
[ 'paragraph', 'stretchy-paragraph' ].includes( v.name )
|
|
223
|
+
)
|
|
224
|
+
) {
|
|
225
|
+
return [];
|
|
226
|
+
}
|
|
227
|
+
// If there are other variations, only hide the stretchy one.
|
|
228
|
+
return unfilteredVariations.filter(
|
|
229
|
+
( v ) => v.name !== 'stretchy-paragraph'
|
|
230
|
+
);
|
|
231
|
+
} else if ( blockName === 'core/heading' ) {
|
|
232
|
+
if (
|
|
233
|
+
activeBlockVariation?.name === 'stretchy-heading' ||
|
|
234
|
+
unfilteredVariations.every( ( v ) =>
|
|
235
|
+
[ 'heading', 'stretchy-heading' ].includes( v.name )
|
|
236
|
+
)
|
|
237
|
+
) {
|
|
238
|
+
return [];
|
|
239
|
+
}
|
|
240
|
+
return unfilteredVariations.filter(
|
|
241
|
+
( v ) => v.name !== 'stretchy-heading'
|
|
242
|
+
);
|
|
243
|
+
}
|
|
244
|
+
return unfilteredVariations;
|
|
245
|
+
}, [ activeBlockVariation?.name, blockName, unfilteredVariations ] );
|
|
185
246
|
|
|
186
247
|
const selectedValue = activeBlockVariation?.name;
|
|
187
248
|
|
|
@@ -74,6 +74,7 @@ export default function SingleInputControl( {
|
|
|
74
74
|
const onChangeUnit = ( next ) => {
|
|
75
75
|
const newUnits = { ...selectedUnits };
|
|
76
76
|
if ( corner === 'all' ) {
|
|
77
|
+
newUnits.flat = next;
|
|
77
78
|
newUnits.topLeft = next;
|
|
78
79
|
newUnits.topRight = next;
|
|
79
80
|
newUnits.bottomLeft = next;
|
|
@@ -0,0 +1,296 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WordPress dependencies
|
|
3
|
+
*/
|
|
4
|
+
import { store as blocksStore } from '@wordpress/blocks';
|
|
5
|
+
import {
|
|
6
|
+
__experimentalToolsPanel as ToolsPanel,
|
|
7
|
+
__experimentalHStack as HStack,
|
|
8
|
+
Icon,
|
|
9
|
+
Navigator,
|
|
10
|
+
} from '@wordpress/components';
|
|
11
|
+
import { useDispatch, useSelect } from '@wordpress/data';
|
|
12
|
+
import { __ } from '@wordpress/i18n';
|
|
13
|
+
import { arrowLeft, arrowRight } from '@wordpress/icons';
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Internal dependencies
|
|
17
|
+
*/
|
|
18
|
+
import { unlock } from '../../lock-unlock';
|
|
19
|
+
import { store as blockEditorStore } from '../../store';
|
|
20
|
+
import BlockIcon from '../block-icon';
|
|
21
|
+
import useBlockDisplayTitle from '../block-title/use-block-display-title';
|
|
22
|
+
import useBlockDisplayInformation from '../use-block-display-information';
|
|
23
|
+
import { useInspectorPopoverPlacement } from './use-inspector-popover-placement';
|
|
24
|
+
|
|
25
|
+
// controls
|
|
26
|
+
import PlainText from './plain-text';
|
|
27
|
+
import RichText from './rich-text';
|
|
28
|
+
import Media from './media';
|
|
29
|
+
import Link from './link';
|
|
30
|
+
|
|
31
|
+
const controls = {
|
|
32
|
+
PlainText,
|
|
33
|
+
RichText,
|
|
34
|
+
Media,
|
|
35
|
+
Link,
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
function BlockAttributeToolsPanelItem( {
|
|
39
|
+
clientId,
|
|
40
|
+
control,
|
|
41
|
+
blockType,
|
|
42
|
+
attributeValues,
|
|
43
|
+
} ) {
|
|
44
|
+
const { updateBlockAttributes } = useDispatch( blockEditorStore );
|
|
45
|
+
const ControlComponent = controls[ control.type ];
|
|
46
|
+
|
|
47
|
+
if ( ! ControlComponent ) {
|
|
48
|
+
return null;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return (
|
|
52
|
+
<ControlComponent
|
|
53
|
+
clientId={ clientId }
|
|
54
|
+
control={ control }
|
|
55
|
+
blockType={ blockType }
|
|
56
|
+
attributeValues={ attributeValues }
|
|
57
|
+
updateAttributes={ ( attributes ) =>
|
|
58
|
+
updateBlockAttributes( clientId, attributes )
|
|
59
|
+
}
|
|
60
|
+
/>
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function BlockFields( { clientId } ) {
|
|
65
|
+
const { attributes, blockType } = useSelect(
|
|
66
|
+
( select ) => {
|
|
67
|
+
const { getBlockAttributes, getBlockName } =
|
|
68
|
+
select( blockEditorStore );
|
|
69
|
+
const { getBlockType } = select( blocksStore );
|
|
70
|
+
const blockName = getBlockName( clientId );
|
|
71
|
+
return {
|
|
72
|
+
attributes: getBlockAttributes( clientId ),
|
|
73
|
+
blockType: getBlockType( blockName ),
|
|
74
|
+
};
|
|
75
|
+
},
|
|
76
|
+
[ clientId ]
|
|
77
|
+
);
|
|
78
|
+
|
|
79
|
+
const blockTitle = useBlockDisplayTitle( {
|
|
80
|
+
clientId,
|
|
81
|
+
context: 'list-view',
|
|
82
|
+
} );
|
|
83
|
+
const blockInformation = useBlockDisplayInformation( clientId );
|
|
84
|
+
const popoverPlacementProps = useInspectorPopoverPlacement();
|
|
85
|
+
|
|
86
|
+
if ( ! blockType?.fields?.length ) {
|
|
87
|
+
// TODO - we might still want to show a placeholder for blocks with no fields.
|
|
88
|
+
// for example, a way to select the block.
|
|
89
|
+
return null;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
return (
|
|
93
|
+
<ToolsPanel
|
|
94
|
+
label={
|
|
95
|
+
<HStack spacing={ 1 }>
|
|
96
|
+
<BlockIcon icon={ blockInformation?.icon } />
|
|
97
|
+
<div>{ blockTitle }</div>
|
|
98
|
+
</HStack>
|
|
99
|
+
}
|
|
100
|
+
panelId={ clientId }
|
|
101
|
+
dropdownMenuProps={ popoverPlacementProps }
|
|
102
|
+
>
|
|
103
|
+
{ blockType?.fields?.map( ( field, index ) => (
|
|
104
|
+
<BlockAttributeToolsPanelItem
|
|
105
|
+
key={ `${ clientId }/${ index }` }
|
|
106
|
+
clientId={ clientId }
|
|
107
|
+
control={ field }
|
|
108
|
+
blockType={ blockType }
|
|
109
|
+
attributeValues={ attributes }
|
|
110
|
+
/>
|
|
111
|
+
) ) }
|
|
112
|
+
</ToolsPanel>
|
|
113
|
+
);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
function DrillDownButton( { clientId } ) {
|
|
117
|
+
const blockTitle = useBlockDisplayTitle( {
|
|
118
|
+
clientId,
|
|
119
|
+
context: 'list-view',
|
|
120
|
+
} );
|
|
121
|
+
const blockInformation = useBlockDisplayInformation( clientId );
|
|
122
|
+
return (
|
|
123
|
+
<div className="block-editor-content-only-controls__button-panel">
|
|
124
|
+
<Navigator.Button
|
|
125
|
+
path={ `/${ clientId }` }
|
|
126
|
+
className="block-editor-content-only-controls__drill-down-button"
|
|
127
|
+
>
|
|
128
|
+
<HStack expanded justify="space-between">
|
|
129
|
+
<HStack justify="flex-start" spacing={ 1 }>
|
|
130
|
+
<BlockIcon icon={ blockInformation?.icon } />
|
|
131
|
+
<div>{ blockTitle }</div>
|
|
132
|
+
</HStack>
|
|
133
|
+
<Icon icon={ arrowRight } />
|
|
134
|
+
</HStack>
|
|
135
|
+
</Navigator.Button>
|
|
136
|
+
</div>
|
|
137
|
+
);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
function ContentOnlyControlsScreen( {
|
|
141
|
+
rootClientId,
|
|
142
|
+
contentClientIds,
|
|
143
|
+
parentClientIds,
|
|
144
|
+
isNested,
|
|
145
|
+
} ) {
|
|
146
|
+
const isRootContentBlock = useSelect(
|
|
147
|
+
( select ) => {
|
|
148
|
+
const { getBlockName } = select( blockEditorStore );
|
|
149
|
+
const blockName = getBlockName( rootClientId );
|
|
150
|
+
const { hasContentRoleAttribute } = unlock( select( blocksStore ) );
|
|
151
|
+
return hasContentRoleAttribute( blockName );
|
|
152
|
+
},
|
|
153
|
+
[ rootClientId ]
|
|
154
|
+
);
|
|
155
|
+
|
|
156
|
+
if ( ! isRootContentBlock && ! contentClientIds.length ) {
|
|
157
|
+
return null;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
return (
|
|
161
|
+
<>
|
|
162
|
+
{ isNested && (
|
|
163
|
+
<div className="block-editor-content-only-controls__button-panel">
|
|
164
|
+
<Navigator.BackButton className="block-editor-content-only-controls__back-button">
|
|
165
|
+
<HStack expanded spacing={ 1 } justify="flex-start">
|
|
166
|
+
<Icon icon={ arrowLeft } />
|
|
167
|
+
<div>{ __( 'Back' ) }</div>
|
|
168
|
+
</HStack>
|
|
169
|
+
</Navigator.BackButton>
|
|
170
|
+
</div>
|
|
171
|
+
) }
|
|
172
|
+
{ isRootContentBlock && <BlockFields clientId={ rootClientId } /> }
|
|
173
|
+
{ contentClientIds.map( ( clientId ) => {
|
|
174
|
+
if ( parentClientIds?.[ clientId ] ) {
|
|
175
|
+
return (
|
|
176
|
+
<DrillDownButton
|
|
177
|
+
key={ clientId }
|
|
178
|
+
clientId={ clientId }
|
|
179
|
+
/>
|
|
180
|
+
);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
return <BlockFields key={ clientId } clientId={ clientId } />;
|
|
184
|
+
} ) }
|
|
185
|
+
</>
|
|
186
|
+
);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
export default function ContentOnlyControls( { rootClientId } ) {
|
|
190
|
+
const { updatedRootClientId, nestedContentClientIds, contentClientIds } =
|
|
191
|
+
useSelect(
|
|
192
|
+
( select ) => {
|
|
193
|
+
const { getClientIdsOfDescendants, getBlockEditingMode } =
|
|
194
|
+
select( blockEditorStore );
|
|
195
|
+
|
|
196
|
+
// _nestedContentClientIds is for content blocks within 'drilldowns'.
|
|
197
|
+
// It's an object where the key is the parent clientId, and the element is
|
|
198
|
+
// an array of child clientIds whose controls are shown within the drilldown.
|
|
199
|
+
const _nestedContentClientIds = {};
|
|
200
|
+
|
|
201
|
+
// _contentClientIds is the list of contentClientIds for blocks being
|
|
202
|
+
// shown at the root level. Includes parent blocks that might have a drilldown,
|
|
203
|
+
// but not the children of those blocks.
|
|
204
|
+
const _contentClientIds = [];
|
|
205
|
+
|
|
206
|
+
// An array of all nested client ids. Used for ensuring blocks within drilldowns
|
|
207
|
+
// don't appear at the root level.
|
|
208
|
+
let allNestedClientIds = [];
|
|
209
|
+
|
|
210
|
+
// A flattened list of all content clientIds to arrange into the
|
|
211
|
+
// groups above.
|
|
212
|
+
const allContentClientIds = getClientIdsOfDescendants(
|
|
213
|
+
rootClientId
|
|
214
|
+
).filter(
|
|
215
|
+
( clientId ) =>
|
|
216
|
+
getBlockEditingMode( clientId ) === 'contentOnly'
|
|
217
|
+
);
|
|
218
|
+
|
|
219
|
+
for ( const clientId of allContentClientIds ) {
|
|
220
|
+
const childClientIds = getClientIdsOfDescendants(
|
|
221
|
+
clientId
|
|
222
|
+
).filter(
|
|
223
|
+
( childClientId ) =>
|
|
224
|
+
getBlockEditingMode( childClientId ) ===
|
|
225
|
+
'contentOnly'
|
|
226
|
+
);
|
|
227
|
+
|
|
228
|
+
// If there's more than one child block, use a drilldown.
|
|
229
|
+
if (
|
|
230
|
+
childClientIds.length > 1 &&
|
|
231
|
+
! allNestedClientIds.includes( clientId )
|
|
232
|
+
) {
|
|
233
|
+
_nestedContentClientIds[ clientId ] = childClientIds;
|
|
234
|
+
allNestedClientIds = [
|
|
235
|
+
allNestedClientIds,
|
|
236
|
+
...childClientIds,
|
|
237
|
+
];
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
if ( ! allNestedClientIds.includes( clientId ) ) {
|
|
241
|
+
_contentClientIds.push( clientId );
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
// Avoid showing only one drilldown block at the root.
|
|
246
|
+
if (
|
|
247
|
+
_contentClientIds.length === 1 &&
|
|
248
|
+
Object.keys( _nestedContentClientIds ).length === 1
|
|
249
|
+
) {
|
|
250
|
+
const onlyParentClientId = Object.keys(
|
|
251
|
+
_nestedContentClientIds
|
|
252
|
+
)[ 0 ];
|
|
253
|
+
return {
|
|
254
|
+
updatedRootClientId: onlyParentClientId,
|
|
255
|
+
contentClientIds:
|
|
256
|
+
_nestedContentClientIds[ onlyParentClientId ],
|
|
257
|
+
nestedContentClientIds: {},
|
|
258
|
+
};
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
return {
|
|
262
|
+
nestedContentClientIds: _nestedContentClientIds,
|
|
263
|
+
contentClientIds: _contentClientIds,
|
|
264
|
+
};
|
|
265
|
+
},
|
|
266
|
+
[ rootClientId ]
|
|
267
|
+
);
|
|
268
|
+
|
|
269
|
+
return (
|
|
270
|
+
<Navigator initialPath="/">
|
|
271
|
+
<Navigator.Screen
|
|
272
|
+
path="/"
|
|
273
|
+
className="block-editor-content-only-controls__screen"
|
|
274
|
+
>
|
|
275
|
+
<ContentOnlyControlsScreen
|
|
276
|
+
rootClientId={ updatedRootClientId ?? rootClientId }
|
|
277
|
+
contentClientIds={ contentClientIds }
|
|
278
|
+
parentClientIds={ nestedContentClientIds }
|
|
279
|
+
/>
|
|
280
|
+
</Navigator.Screen>
|
|
281
|
+
{ Object.keys( nestedContentClientIds ).map( ( clientId ) => (
|
|
282
|
+
<Navigator.Screen
|
|
283
|
+
key={ clientId }
|
|
284
|
+
path={ `/${ clientId }` }
|
|
285
|
+
className="block-editor-content-only-controls__screen"
|
|
286
|
+
>
|
|
287
|
+
<ContentOnlyControlsScreen
|
|
288
|
+
isNested
|
|
289
|
+
rootClientId={ clientId }
|
|
290
|
+
contentClientIds={ nestedContentClientIds[ clientId ] }
|
|
291
|
+
/>
|
|
292
|
+
</Navigator.Screen>
|
|
293
|
+
) ) }
|
|
294
|
+
</Navigator>
|
|
295
|
+
);
|
|
296
|
+
}
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WordPress dependencies
|
|
3
|
+
*/
|
|
4
|
+
import {
|
|
5
|
+
Button,
|
|
6
|
+
Icon,
|
|
7
|
+
__experimentalToolsPanelItem as ToolsPanelItem,
|
|
8
|
+
__experimentalGrid as Grid,
|
|
9
|
+
Popover,
|
|
10
|
+
} from '@wordpress/components';
|
|
11
|
+
import { useMemo, useState } from '@wordpress/element';
|
|
12
|
+
import { __ } from '@wordpress/i18n';
|
|
13
|
+
import { link } from '@wordpress/icons';
|
|
14
|
+
import { prependHTTP } from '@wordpress/url';
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Internal dependencies
|
|
18
|
+
*/
|
|
19
|
+
import LinkControl from '../../link-control';
|
|
20
|
+
import { useInspectorPopoverPlacement } from '../use-inspector-popover-placement';
|
|
21
|
+
|
|
22
|
+
export const NEW_TAB_REL = 'noreferrer noopener';
|
|
23
|
+
export const NEW_TAB_TARGET = '_blank';
|
|
24
|
+
export const NOFOLLOW_REL = 'nofollow';
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Updates the link attributes.
|
|
28
|
+
*
|
|
29
|
+
* @param {Object} attributes The current block attributes.
|
|
30
|
+
* @param {string} attributes.rel The current link rel attribute.
|
|
31
|
+
* @param {string} attributes.url The current link url.
|
|
32
|
+
* @param {boolean} attributes.opensInNewTab Whether the link should open in a new window.
|
|
33
|
+
* @param {boolean} attributes.nofollow Whether the link should be marked as nofollow.
|
|
34
|
+
*/
|
|
35
|
+
export function getUpdatedLinkAttributes( {
|
|
36
|
+
rel = '',
|
|
37
|
+
url = '',
|
|
38
|
+
opensInNewTab,
|
|
39
|
+
nofollow,
|
|
40
|
+
} ) {
|
|
41
|
+
let newLinkTarget;
|
|
42
|
+
// Since `rel` is editable attribute, we need to check for existing values and proceed accordingly.
|
|
43
|
+
let updatedRel = rel;
|
|
44
|
+
|
|
45
|
+
if ( opensInNewTab ) {
|
|
46
|
+
newLinkTarget = NEW_TAB_TARGET;
|
|
47
|
+
updatedRel = updatedRel?.includes( NEW_TAB_REL )
|
|
48
|
+
? updatedRel
|
|
49
|
+
: updatedRel + ` ${ NEW_TAB_REL }`;
|
|
50
|
+
} else {
|
|
51
|
+
const relRegex = new RegExp( `\\b${ NEW_TAB_REL }\\s*`, 'g' );
|
|
52
|
+
updatedRel = updatedRel?.replace( relRegex, '' ).trim();
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
if ( nofollow ) {
|
|
56
|
+
updatedRel = updatedRel?.includes( NOFOLLOW_REL )
|
|
57
|
+
? updatedRel
|
|
58
|
+
: ( updatedRel + ` ${ NOFOLLOW_REL }` ).trim();
|
|
59
|
+
} else {
|
|
60
|
+
const relRegex = new RegExp( `\\b${ NOFOLLOW_REL }\\s*`, 'g' );
|
|
61
|
+
updatedRel = updatedRel?.replace( relRegex, '' ).trim();
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
return {
|
|
65
|
+
url: prependHTTP( url ),
|
|
66
|
+
linkTarget: newLinkTarget,
|
|
67
|
+
rel: updatedRel || undefined,
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export default function Link( {
|
|
72
|
+
clientId,
|
|
73
|
+
control,
|
|
74
|
+
blockType,
|
|
75
|
+
attributeValues,
|
|
76
|
+
updateAttributes,
|
|
77
|
+
} ) {
|
|
78
|
+
const [ isLinkControlOpen, setIsLinkControlOpen ] = useState( false );
|
|
79
|
+
const { popoverProps } = useInspectorPopoverPlacement( {
|
|
80
|
+
isControl: true,
|
|
81
|
+
} );
|
|
82
|
+
const hrefKey = control.mapping.href;
|
|
83
|
+
const relKey = control.mapping.rel;
|
|
84
|
+
const targetKey = control.mapping.target;
|
|
85
|
+
const destinationKey = control.mapping.destination;
|
|
86
|
+
|
|
87
|
+
const href = attributeValues[ hrefKey ];
|
|
88
|
+
const rel = attributeValues[ relKey ];
|
|
89
|
+
const target = attributeValues[ targetKey ];
|
|
90
|
+
const destination = attributeValues[ destinationKey ];
|
|
91
|
+
|
|
92
|
+
const hrefDefaultValue =
|
|
93
|
+
blockType.attributes[ href ]?.defaultValue ?? undefined;
|
|
94
|
+
const relDefaultValue =
|
|
95
|
+
blockType.attributes[ rel ]?.defaultValue ?? undefined;
|
|
96
|
+
const targetDefaultValue =
|
|
97
|
+
blockType.attributes[ target ]?.defaultValue ?? undefined;
|
|
98
|
+
const destinationDefaultValue =
|
|
99
|
+
blockType.attributes[ destination ]?.defaultValue ?? undefined;
|
|
100
|
+
|
|
101
|
+
const opensInNewTab = target === NEW_TAB_TARGET;
|
|
102
|
+
const nofollow = rel === NOFOLLOW_REL;
|
|
103
|
+
|
|
104
|
+
// Memoize link value to avoid overriding the LinkControl's internal state.
|
|
105
|
+
// This is a temporary fix. See https://github.com/WordPress/gutenberg/issues/51256.
|
|
106
|
+
const linkValue = useMemo(
|
|
107
|
+
() => ( { url: href, opensInNewTab, nofollow } ),
|
|
108
|
+
[ href, opensInNewTab, nofollow ]
|
|
109
|
+
);
|
|
110
|
+
|
|
111
|
+
return (
|
|
112
|
+
<ToolsPanelItem
|
|
113
|
+
panelId={ clientId }
|
|
114
|
+
label={ control.label }
|
|
115
|
+
hasValue={ () => !! href }
|
|
116
|
+
onDeselect={ () => {
|
|
117
|
+
updateAttributes( {
|
|
118
|
+
[ hrefKey ]: hrefDefaultValue,
|
|
119
|
+
[ relKey ]: relDefaultValue,
|
|
120
|
+
[ targetKey ]: targetDefaultValue,
|
|
121
|
+
[ destinationKey ]: destinationDefaultValue,
|
|
122
|
+
} );
|
|
123
|
+
} }
|
|
124
|
+
isShownByDefault={ control.shownByDefault }
|
|
125
|
+
>
|
|
126
|
+
<Button
|
|
127
|
+
__next40pxDefaultSize
|
|
128
|
+
className="block-editor-content-only-controls__link"
|
|
129
|
+
onClick={ () => {
|
|
130
|
+
setIsLinkControlOpen( true );
|
|
131
|
+
} }
|
|
132
|
+
>
|
|
133
|
+
<Grid
|
|
134
|
+
rowGap={ 0 }
|
|
135
|
+
columnGap={ 8 }
|
|
136
|
+
templateColumns="24px 1fr"
|
|
137
|
+
className="block-editor-content-only-controls__link-row"
|
|
138
|
+
>
|
|
139
|
+
{ href && (
|
|
140
|
+
<>
|
|
141
|
+
<Icon icon={ link } size={ 24 } />
|
|
142
|
+
<span className="block-editor-content-only-controls__link-title">
|
|
143
|
+
{ href }
|
|
144
|
+
</span>
|
|
145
|
+
</>
|
|
146
|
+
) }
|
|
147
|
+
{ ! href && (
|
|
148
|
+
<>
|
|
149
|
+
<Icon
|
|
150
|
+
icon={ link }
|
|
151
|
+
size={ 24 }
|
|
152
|
+
style={ { opacity: 0.3 } }
|
|
153
|
+
/>
|
|
154
|
+
<span className="block-editor-content-only-controls__link-title">
|
|
155
|
+
{ __( 'Link' ) }
|
|
156
|
+
</span>
|
|
157
|
+
</>
|
|
158
|
+
) }
|
|
159
|
+
</Grid>
|
|
160
|
+
</Button>
|
|
161
|
+
{ isLinkControlOpen && (
|
|
162
|
+
<Popover
|
|
163
|
+
onClose={ () => {
|
|
164
|
+
setIsLinkControlOpen( false );
|
|
165
|
+
} }
|
|
166
|
+
{ ...( popoverProps ?? {} ) }
|
|
167
|
+
>
|
|
168
|
+
<LinkControl
|
|
169
|
+
value={ linkValue }
|
|
170
|
+
onChange={ ( newValues ) => {
|
|
171
|
+
const updatedAttrs = getUpdatedLinkAttributes( {
|
|
172
|
+
rel,
|
|
173
|
+
...newValues,
|
|
174
|
+
} );
|
|
175
|
+
|
|
176
|
+
updateAttributes( {
|
|
177
|
+
[ hrefKey ]: updatedAttrs.url,
|
|
178
|
+
[ relKey ]: updatedAttrs.rel,
|
|
179
|
+
[ targetKey ]: updatedAttrs.linkTarget,
|
|
180
|
+
} );
|
|
181
|
+
} }
|
|
182
|
+
onRemove={ () => {
|
|
183
|
+
updateAttributes( {
|
|
184
|
+
[ hrefKey ]: hrefDefaultValue,
|
|
185
|
+
[ relKey ]: relDefaultValue,
|
|
186
|
+
[ targetKey ]: targetDefaultValue,
|
|
187
|
+
[ destinationKey ]: destinationDefaultValue,
|
|
188
|
+
} );
|
|
189
|
+
} }
|
|
190
|
+
/>
|
|
191
|
+
</Popover>
|
|
192
|
+
) }
|
|
193
|
+
</ToolsPanelItem>
|
|
194
|
+
);
|
|
195
|
+
}
|