@wordpress/block-editor 15.9.0 → 15.9.1-next.6deb34194.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/README.md +12 -0
- package/build/components/block-alignment-matrix-control/index.js +1 -8
- package/build/components/block-alignment-matrix-control/index.js.map +2 -2
- package/build/components/block-bindings/attribute-control.js +172 -0
- package/build/components/block-bindings/attribute-control.js.map +7 -0
- package/build/components/block-bindings/index.js +47 -0
- package/build/components/block-bindings/index.js.map +7 -0
- package/build/components/block-bindings/source-fields-list.js +135 -0
- package/build/components/block-bindings/source-fields-list.js.map +7 -0
- package/build/components/block-bindings/use-block-bindings-utils.js +66 -0
- package/build/components/block-bindings/use-block-bindings-utils.js.map +7 -0
- package/build/components/block-edit/edit.js +1 -3
- package/build/components/block-edit/edit.js.map +2 -2
- package/build/components/block-styles/preview-panel.js +3 -5
- package/build/components/block-styles/preview-panel.js.map +2 -2
- package/build/components/block-styles/use-styles-for-block.js +2 -2
- package/build/components/block-styles/use-styles-for-block.js.map +2 -2
- package/build/components/block-toolbar/index.js +1 -8
- package/build/components/block-toolbar/index.js.map +3 -3
- package/build/components/content-only-controls/index.js +2 -25
- package/build/components/content-only-controls/index.js.map +2 -2
- package/build/components/content-only-controls/link/index.js +3 -3
- package/build/components/content-only-controls/link/index.js.map +2 -2
- package/build/components/content-only-controls/media/index.js +3 -3
- package/build/components/content-only-controls/media/index.js.map +2 -2
- package/build/components/content-only-controls/rich-text/index.js +3 -2
- package/build/components/content-only-controls/rich-text/index.js.map +2 -2
- package/build/components/dimensions-tool/width-height-tool.js +4 -16
- package/build/components/dimensions-tool/width-height-tool.js.map +3 -3
- package/build/components/image-editor/cropper.js +3 -34
- package/build/components/image-editor/cropper.js.map +3 -3
- package/build/components/image-editor/index.js +9 -3
- package/build/components/image-editor/index.js.map +2 -2
- package/build/components/image-editor/use-transform-image.js +62 -32
- package/build/components/image-editor/use-transform-image.js.map +2 -2
- package/build/components/image-editor/zoom-dropdown.js +2 -2
- package/build/components/image-editor/zoom-dropdown.js.map +2 -2
- package/build/components/index.js +10 -3
- package/build/components/index.js.map +2 -2
- package/build/components/inserter-draggable-blocks/index.js +8 -4
- package/build/components/inserter-draggable-blocks/index.js.map +2 -2
- package/build/components/inspector-controls-tabs/content-tab.js +3 -2
- package/build/components/inspector-controls-tabs/content-tab.js.map +2 -2
- package/build/components/tool-selector/index.js +46 -0
- package/build/components/tool-selector/index.js.map +7 -0
- package/build/hooks/block-bindings.js +22 -260
- package/build/hooks/block-bindings.js.map +3 -3
- package/build/layouts/grid.js +23 -28
- package/build/layouts/grid.js.map +2 -2
- package/build/utils/block-bindings.js +2 -44
- package/build/utils/block-bindings.js.map +3 -3
- package/build/utils/index.js +2 -5
- package/build/utils/index.js.map +2 -2
- package/build-module/components/block-alignment-matrix-control/index.js +1 -8
- package/build-module/components/block-alignment-matrix-control/index.js.map +2 -2
- package/build-module/components/block-bindings/attribute-control.js +150 -0
- package/build-module/components/block-bindings/attribute-control.js.map +7 -0
- package/build-module/components/block-bindings/index.js +10 -0
- package/build-module/components/block-bindings/index.js.map +7 -0
- package/build-module/components/block-bindings/source-fields-list.js +104 -0
- package/build-module/components/block-bindings/source-fields-list.js.map +7 -0
- package/build-module/components/block-bindings/use-block-bindings-utils.js +45 -0
- package/build-module/components/block-bindings/use-block-bindings-utils.js.map +7 -0
- package/build-module/components/block-edit/edit.js +1 -3
- package/build-module/components/block-edit/edit.js.map +2 -2
- package/build-module/components/block-styles/preview-panel.js +3 -5
- package/build-module/components/block-styles/preview-panel.js.map +2 -2
- package/build-module/components/block-styles/use-styles-for-block.js +2 -2
- package/build-module/components/block-styles/use-styles-for-block.js.map +2 -2
- package/build-module/components/block-toolbar/index.js +1 -8
- package/build-module/components/block-toolbar/index.js.map +2 -2
- package/build-module/components/content-only-controls/index.js +2 -25
- package/build-module/components/content-only-controls/index.js.map +2 -2
- package/build-module/components/content-only-controls/link/index.js +3 -3
- package/build-module/components/content-only-controls/link/index.js.map +2 -2
- package/build-module/components/content-only-controls/media/index.js +3 -3
- package/build-module/components/content-only-controls/media/index.js.map +2 -2
- package/build-module/components/content-only-controls/rich-text/index.js +3 -2
- package/build-module/components/content-only-controls/rich-text/index.js.map +2 -2
- package/build-module/components/dimensions-tool/width-height-tool.js +4 -6
- package/build-module/components/dimensions-tool/width-height-tool.js.map +2 -2
- package/build-module/components/image-editor/cropper.js +3 -34
- package/build-module/components/image-editor/cropper.js.map +2 -2
- package/build-module/components/image-editor/index.js +9 -3
- package/build-module/components/image-editor/index.js.map +2 -2
- package/build-module/components/image-editor/use-transform-image.js +63 -33
- package/build-module/components/image-editor/use-transform-image.js.map +2 -2
- package/build-module/components/image-editor/zoom-dropdown.js +2 -2
- package/build-module/components/image-editor/zoom-dropdown.js.map +2 -2
- package/build-module/components/index.js +74 -66
- package/build-module/components/index.js.map +2 -2
- package/build-module/components/inserter-draggable-blocks/index.js +8 -4
- package/build-module/components/inserter-draggable-blocks/index.js.map +2 -2
- package/build-module/components/inspector-controls-tabs/content-tab.js +3 -2
- package/build-module/components/inspector-controls-tabs/content-tab.js.map +2 -2
- package/build-module/components/tool-selector/index.js +15 -0
- package/build-module/components/tool-selector/index.js.map +7 -0
- package/build-module/hooks/block-bindings.js +27 -270
- package/build-module/hooks/block-bindings.js.map +2 -2
- package/build-module/layouts/grid.js +23 -28
- package/build-module/layouts/grid.js.map +2 -2
- package/build-module/utils/block-bindings.js +1 -42
- package/build-module/utils/block-bindings.js.map +2 -2
- package/build-module/utils/index.js +1 -3
- package/build-module/utils/index.js.map +2 -2
- package/build-style/style-rtl.css +6 -6
- package/build-style/style.css +6 -6
- package/package.json +39 -40
- package/src/components/block-alignment-matrix-control/index.js +1 -5
- package/src/components/block-bindings/attribute-control.js +174 -0
- package/src/components/block-bindings/index.js +6 -0
- package/src/components/block-bindings/source-fields-list.js +130 -0
- package/src/components/block-bindings/use-block-bindings-utils.js +156 -0
- package/src/components/block-edit/edit.js +1 -3
- package/src/components/block-styles/preview-panel.js +3 -5
- package/src/components/block-styles/use-styles-for-block.js +2 -2
- package/src/components/block-toolbar/index.js +1 -6
- package/src/components/block-toolbar/style.scss +6 -6
- package/src/components/content-only-controls/index.js +2 -27
- package/src/components/content-only-controls/link/index.js +3 -3
- package/src/components/content-only-controls/media/index.js +3 -3
- package/src/components/content-only-controls/rich-text/index.js +3 -2
- package/src/components/dimensions-tool/width-height-tool.js +6 -13
- package/src/components/image-editor/cropper.js +3 -32
- package/src/components/image-editor/index.js +34 -29
- package/src/components/image-editor/use-transform-image.js +80 -34
- package/src/components/image-editor/zoom-dropdown.js +2 -2
- package/src/components/index.js +9 -1
- package/src/components/inserter/style.scss +1 -1
- package/src/components/inserter-draggable-blocks/index.js +19 -8
- package/src/components/inspector-controls-tabs/content-tab.js +6 -2
- package/src/components/tool-selector/index.js +19 -0
- package/src/hooks/block-bindings.js +27 -347
- package/src/layouts/grid.js +40 -72
- package/src/layouts/test/grid.js +14 -0
- package/src/utils/block-bindings.js +0 -157
- package/src/utils/index.js +0 -1
- package/tsconfig.json +1 -0
- package/build/components/block-toolbar/block-name-context.js +0 -30
- package/build/components/block-toolbar/block-name-context.js.map +0 -7
- package/build-module/components/block-toolbar/block-name-context.js +0 -9
- package/build-module/components/block-toolbar/block-name-context.js.map +0 -7
- package/src/components/block-toolbar/block-name-context.js +0 -9
- /package/src/{utils → components/block-bindings}/test/use-block-bindings-utils.js +0 -0
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* External dependencies
|
|
3
|
+
*/
|
|
4
|
+
import fastDeepEqual from 'fast-deep-equal/es6';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* WordPress dependencies
|
|
8
|
+
*/
|
|
9
|
+
import { __ } from '@wordpress/i18n';
|
|
10
|
+
import {
|
|
11
|
+
getBlockBindingsSource,
|
|
12
|
+
store as blocksStore,
|
|
13
|
+
} from '@wordpress/blocks';
|
|
14
|
+
import {
|
|
15
|
+
__experimentalItem as Item,
|
|
16
|
+
__experimentalText as Text,
|
|
17
|
+
__experimentalToolsPanelItem as ToolsPanelItem,
|
|
18
|
+
__experimentalVStack as VStack,
|
|
19
|
+
privateApis as componentsPrivateApis,
|
|
20
|
+
} from '@wordpress/components';
|
|
21
|
+
import { useSelect } from '@wordpress/data';
|
|
22
|
+
import { useContext } from '@wordpress/element';
|
|
23
|
+
import { useViewportMatch } from '@wordpress/compose';
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Internal dependencies
|
|
27
|
+
*/
|
|
28
|
+
import BlockContext from '../block-context';
|
|
29
|
+
import BlockBindingsSourceFieldsList from './source-fields-list';
|
|
30
|
+
import useBlockBindingsUtils from './use-block-bindings-utils';
|
|
31
|
+
import { unlock } from '../../lock-unlock';
|
|
32
|
+
import { store as blockEditorStore } from '../../store';
|
|
33
|
+
|
|
34
|
+
const { Menu } = unlock( componentsPrivateApis );
|
|
35
|
+
|
|
36
|
+
export default function BlockBindingsAttributeControl( {
|
|
37
|
+
attribute,
|
|
38
|
+
binding,
|
|
39
|
+
blockName,
|
|
40
|
+
} ) {
|
|
41
|
+
const { updateBlockBindings } = useBlockBindingsUtils();
|
|
42
|
+
const isMobile = useViewportMatch( 'medium', '<' );
|
|
43
|
+
|
|
44
|
+
const blockContext = useContext( BlockContext );
|
|
45
|
+
const compatibleFields = useSelect(
|
|
46
|
+
( select ) => {
|
|
47
|
+
const {
|
|
48
|
+
getAllBlockBindingsSources,
|
|
49
|
+
getBlockBindingsSourceFieldsList,
|
|
50
|
+
getBlockType,
|
|
51
|
+
} = unlock( select( blocksStore ) );
|
|
52
|
+
|
|
53
|
+
const _attributeType =
|
|
54
|
+
getBlockType( blockName ).attributes?.[ attribute ]?.type;
|
|
55
|
+
const attributeType =
|
|
56
|
+
_attributeType === 'rich-text' ? 'string' : _attributeType;
|
|
57
|
+
|
|
58
|
+
const sourceFields = {};
|
|
59
|
+
Object.entries( getAllBlockBindingsSources() ).forEach(
|
|
60
|
+
( [ sourceName, source ] ) => {
|
|
61
|
+
const fieldsList = getBlockBindingsSourceFieldsList(
|
|
62
|
+
source,
|
|
63
|
+
blockContext
|
|
64
|
+
);
|
|
65
|
+
if ( ! fieldsList?.length ) {
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
const compatibleFieldsList = fieldsList.filter(
|
|
69
|
+
( field ) => field.type === attributeType
|
|
70
|
+
);
|
|
71
|
+
if ( compatibleFieldsList.length ) {
|
|
72
|
+
sourceFields[ sourceName ] = compatibleFieldsList;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
);
|
|
76
|
+
return sourceFields;
|
|
77
|
+
},
|
|
78
|
+
[ attribute, blockName, blockContext ]
|
|
79
|
+
);
|
|
80
|
+
|
|
81
|
+
const { canUpdateBlockBindings } = useSelect( ( select ) => ( {
|
|
82
|
+
canUpdateBlockBindings:
|
|
83
|
+
select( blockEditorStore ).getSettings().canUpdateBlockBindings,
|
|
84
|
+
} ) );
|
|
85
|
+
|
|
86
|
+
const hasCompatibleFields = Object.keys( compatibleFields ).length > 0;
|
|
87
|
+
|
|
88
|
+
// Lock the UI when the user can't update bindings or there are no fields to connect to.
|
|
89
|
+
const isAttributeReadOnly =
|
|
90
|
+
! canUpdateBlockBindings || ! hasCompatibleFields;
|
|
91
|
+
|
|
92
|
+
const { source: boundSourceName, args } = binding || {};
|
|
93
|
+
const source = getBlockBindingsSource( boundSourceName );
|
|
94
|
+
|
|
95
|
+
let displayText;
|
|
96
|
+
let isValid = true;
|
|
97
|
+
|
|
98
|
+
if ( binding === undefined ) {
|
|
99
|
+
if ( ! hasCompatibleFields ) {
|
|
100
|
+
displayText = __( 'No sources available' );
|
|
101
|
+
} else {
|
|
102
|
+
displayText = __( 'Not connected' );
|
|
103
|
+
}
|
|
104
|
+
isValid = true;
|
|
105
|
+
} else if ( ! source ) {
|
|
106
|
+
// If there's a binding but the source is not found, it's invalid.
|
|
107
|
+
isValid = false;
|
|
108
|
+
displayText = __( 'Source not registered' );
|
|
109
|
+
} else {
|
|
110
|
+
displayText =
|
|
111
|
+
compatibleFields?.[ boundSourceName ]?.find( ( field ) =>
|
|
112
|
+
fastDeepEqual( field.args, args )
|
|
113
|
+
)?.label ||
|
|
114
|
+
source?.label ||
|
|
115
|
+
boundSourceName;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
return (
|
|
119
|
+
<ToolsPanelItem
|
|
120
|
+
hasValue={ () => !! binding }
|
|
121
|
+
label={ attribute }
|
|
122
|
+
onDeselect={
|
|
123
|
+
!! hasCompatibleFields &&
|
|
124
|
+
( () => {
|
|
125
|
+
updateBlockBindings( {
|
|
126
|
+
[ attribute ]: undefined,
|
|
127
|
+
} );
|
|
128
|
+
} )
|
|
129
|
+
}
|
|
130
|
+
>
|
|
131
|
+
<Menu placement={ isMobile ? 'bottom-start' : 'left-start' }>
|
|
132
|
+
<Menu.TriggerButton
|
|
133
|
+
render={ <Item /> }
|
|
134
|
+
disabled={ ! hasCompatibleFields }
|
|
135
|
+
>
|
|
136
|
+
<VStack
|
|
137
|
+
className="block-editor-bindings__item"
|
|
138
|
+
spacing={ 0 }
|
|
139
|
+
>
|
|
140
|
+
<Text truncate>{ attribute }</Text>
|
|
141
|
+
<Text
|
|
142
|
+
truncate
|
|
143
|
+
variant={ isValid ? 'muted' : undefined }
|
|
144
|
+
isDestructive={ ! isValid }
|
|
145
|
+
>
|
|
146
|
+
{ displayText }
|
|
147
|
+
</Text>
|
|
148
|
+
</VStack>
|
|
149
|
+
</Menu.TriggerButton>
|
|
150
|
+
{ ! isAttributeReadOnly && (
|
|
151
|
+
<Menu.Popover gutter={ isMobile ? 8 : 36 }>
|
|
152
|
+
<Menu
|
|
153
|
+
placement={
|
|
154
|
+
isMobile ? 'bottom-start' : 'left-start'
|
|
155
|
+
}
|
|
156
|
+
>
|
|
157
|
+
{ Object.entries( compatibleFields ).map(
|
|
158
|
+
( [ sourceKey, fields ] ) => (
|
|
159
|
+
<BlockBindingsSourceFieldsList
|
|
160
|
+
key={ sourceKey }
|
|
161
|
+
args={ binding?.args }
|
|
162
|
+
attribute={ attribute }
|
|
163
|
+
sourceKey={ sourceKey }
|
|
164
|
+
fields={ fields }
|
|
165
|
+
/>
|
|
166
|
+
)
|
|
167
|
+
) }
|
|
168
|
+
</Menu>
|
|
169
|
+
</Menu.Popover>
|
|
170
|
+
) }
|
|
171
|
+
</Menu>
|
|
172
|
+
</ToolsPanelItem>
|
|
173
|
+
);
|
|
174
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Internal dependencies
|
|
3
|
+
*/
|
|
4
|
+
export { default as BlockBindingsAttributeControl } from './attribute-control';
|
|
5
|
+
export { default as BlockBindingsSourceFieldsList } from './source-fields-list';
|
|
6
|
+
export { default as useBlockBindingsUtils } from './use-block-bindings-utils';
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* External dependencies
|
|
3
|
+
*/
|
|
4
|
+
import fastDeepEqual from 'fast-deep-equal/es6';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* WordPress dependencies
|
|
8
|
+
*/
|
|
9
|
+
import { getBlockBindingsSource } from '@wordpress/blocks';
|
|
10
|
+
import { privateApis as componentsPrivateApis } from '@wordpress/components';
|
|
11
|
+
import { useSelect } from '@wordpress/data';
|
|
12
|
+
import { useContext, useMemo } from '@wordpress/element';
|
|
13
|
+
import { useViewportMatch } from '@wordpress/compose';
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Internal dependencies
|
|
17
|
+
*/
|
|
18
|
+
import useBlockBindingsUtils from './use-block-bindings-utils';
|
|
19
|
+
import { unlock } from '../../lock-unlock';
|
|
20
|
+
import BlockContext from '../block-context';
|
|
21
|
+
|
|
22
|
+
const { Menu } = unlock( componentsPrivateApis );
|
|
23
|
+
|
|
24
|
+
function BlockBindingsSourceFieldsListItem( {
|
|
25
|
+
args,
|
|
26
|
+
attribute,
|
|
27
|
+
field,
|
|
28
|
+
source,
|
|
29
|
+
sourceKey,
|
|
30
|
+
} ) {
|
|
31
|
+
const itemBindings = useMemo(
|
|
32
|
+
() => ( {
|
|
33
|
+
source: sourceKey,
|
|
34
|
+
args: field.args || {
|
|
35
|
+
key: field.key,
|
|
36
|
+
},
|
|
37
|
+
} ),
|
|
38
|
+
[ field.args, field.key, sourceKey ]
|
|
39
|
+
);
|
|
40
|
+
|
|
41
|
+
const blockContext = useContext( BlockContext );
|
|
42
|
+
const values = useSelect(
|
|
43
|
+
( select ) =>
|
|
44
|
+
source.getValues( {
|
|
45
|
+
select,
|
|
46
|
+
context: blockContext,
|
|
47
|
+
bindings: {
|
|
48
|
+
[ attribute ]: itemBindings,
|
|
49
|
+
},
|
|
50
|
+
} ),
|
|
51
|
+
[ attribute, blockContext, itemBindings, source ]
|
|
52
|
+
);
|
|
53
|
+
const { updateBlockBindings } = useBlockBindingsUtils();
|
|
54
|
+
|
|
55
|
+
return (
|
|
56
|
+
<Menu.CheckboxItem
|
|
57
|
+
onChange={ () => {
|
|
58
|
+
const isCurrentlySelected =
|
|
59
|
+
fastDeepEqual( args, field.args ) ??
|
|
60
|
+
// Deprecate key dependency in 7.0.
|
|
61
|
+
field.key === args?.key;
|
|
62
|
+
|
|
63
|
+
if ( isCurrentlySelected ) {
|
|
64
|
+
// Unset if the same field is selected again.
|
|
65
|
+
updateBlockBindings( {
|
|
66
|
+
[ attribute ]: undefined,
|
|
67
|
+
} );
|
|
68
|
+
} else {
|
|
69
|
+
updateBlockBindings( {
|
|
70
|
+
[ attribute ]: itemBindings,
|
|
71
|
+
} );
|
|
72
|
+
}
|
|
73
|
+
} }
|
|
74
|
+
name={ attribute + '-binding' }
|
|
75
|
+
value={ values[ attribute ] }
|
|
76
|
+
checked={
|
|
77
|
+
fastDeepEqual( args, field.args ) ??
|
|
78
|
+
// Deprecate key dependency in 7.0.
|
|
79
|
+
field.key === args?.key
|
|
80
|
+
}
|
|
81
|
+
>
|
|
82
|
+
<Menu.ItemLabel>{ field.label }</Menu.ItemLabel>
|
|
83
|
+
<Menu.ItemHelpText>{ values[ attribute ] }</Menu.ItemHelpText>
|
|
84
|
+
</Menu.CheckboxItem>
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export default function BlockBindingsSourceFieldsList( {
|
|
89
|
+
args,
|
|
90
|
+
attribute,
|
|
91
|
+
sourceKey,
|
|
92
|
+
fields,
|
|
93
|
+
} ) {
|
|
94
|
+
const isMobile = useViewportMatch( 'medium', '<' );
|
|
95
|
+
|
|
96
|
+
// Only render source if it has compatible fields.
|
|
97
|
+
if ( ! fields || fields.length === 0 ) {
|
|
98
|
+
return null;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
const source = getBlockBindingsSource( sourceKey );
|
|
102
|
+
|
|
103
|
+
return (
|
|
104
|
+
<Menu
|
|
105
|
+
key={ sourceKey }
|
|
106
|
+
placement={ isMobile ? 'bottom-start' : 'left-start' }
|
|
107
|
+
>
|
|
108
|
+
<Menu.SubmenuTriggerItem>
|
|
109
|
+
<Menu.ItemLabel>{ source.label }</Menu.ItemLabel>
|
|
110
|
+
</Menu.SubmenuTriggerItem>
|
|
111
|
+
<Menu.Popover gutter={ 8 }>
|
|
112
|
+
<Menu.Group>
|
|
113
|
+
{ fields.map( ( field ) => (
|
|
114
|
+
<BlockBindingsSourceFieldsListItem
|
|
115
|
+
key={
|
|
116
|
+
sourceKey + JSON.stringify( field.args ) ||
|
|
117
|
+
field.key
|
|
118
|
+
}
|
|
119
|
+
args={ args }
|
|
120
|
+
attribute={ attribute }
|
|
121
|
+
field={ field }
|
|
122
|
+
source={ source }
|
|
123
|
+
sourceKey={ sourceKey }
|
|
124
|
+
/>
|
|
125
|
+
) ) }
|
|
126
|
+
</Menu.Group>
|
|
127
|
+
</Menu.Popover>
|
|
128
|
+
</Menu>
|
|
129
|
+
);
|
|
130
|
+
}
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WordPress dependencies
|
|
3
|
+
*/
|
|
4
|
+
import { useDispatch, useRegistry } from '@wordpress/data';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Internal dependencies
|
|
8
|
+
*/
|
|
9
|
+
import { store as blockEditorStore } from '../../store';
|
|
10
|
+
import { useBlockEditContext } from '../block-edit';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Checks if the given object is empty.
|
|
14
|
+
*
|
|
15
|
+
* @param {?Object} object The object to check.
|
|
16
|
+
*
|
|
17
|
+
* @return {boolean} Whether the object is empty.
|
|
18
|
+
*/
|
|
19
|
+
function isObjectEmpty( object ) {
|
|
20
|
+
return ! object || Object.keys( object ).length === 0;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Contains utils to update the block `bindings` metadata.
|
|
25
|
+
*
|
|
26
|
+
* @typedef {Object} WPBlockBindingsUtils
|
|
27
|
+
*
|
|
28
|
+
* @property {Function} updateBlockBindings Updates the value of the bindings connected to block attributes.
|
|
29
|
+
* @property {Function} removeAllBlockBindings Removes the bindings property of the `metadata` attribute.
|
|
30
|
+
*/
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Retrieves the existing utils needed to update the block `bindings` metadata.
|
|
34
|
+
* They can be used to create, modify, or remove connections from the existing block attributes.
|
|
35
|
+
*
|
|
36
|
+
* It contains the following utils:
|
|
37
|
+
* - `updateBlockBindings`: Updates the value of the bindings connected to block attributes. It can be used to remove a specific binding by setting the value to `undefined`.
|
|
38
|
+
* - `removeAllBlockBindings`: Removes the bindings property of the `metadata` attribute.
|
|
39
|
+
*
|
|
40
|
+
* @since 6.7.0 Introduced in WordPress core.
|
|
41
|
+
*
|
|
42
|
+
* @param {?string} clientId Optional block client ID. If not set, it will use the current block client ID from the context.
|
|
43
|
+
*
|
|
44
|
+
* @return {?WPBlockBindingsUtils} Object containing the block bindings utils.
|
|
45
|
+
*
|
|
46
|
+
* @example
|
|
47
|
+
* ```js
|
|
48
|
+
* import { useBlockBindingsUtils } from '@wordpress/block-editor'
|
|
49
|
+
* const { updateBlockBindings, removeAllBlockBindings } = useBlockBindingsUtils();
|
|
50
|
+
*
|
|
51
|
+
* // Update url and alt attributes.
|
|
52
|
+
* updateBlockBindings( {
|
|
53
|
+
* url: {
|
|
54
|
+
* source: 'core/post-meta',
|
|
55
|
+
* args: {
|
|
56
|
+
* key: 'url_custom_field',
|
|
57
|
+
* },
|
|
58
|
+
* },
|
|
59
|
+
* alt: {
|
|
60
|
+
* source: 'core/post-meta',
|
|
61
|
+
* args: {
|
|
62
|
+
* key: 'text_custom_field',
|
|
63
|
+
* },
|
|
64
|
+
* },
|
|
65
|
+
* } );
|
|
66
|
+
*
|
|
67
|
+
* // Remove binding from url attribute.
|
|
68
|
+
* updateBlockBindings( { url: undefined } );
|
|
69
|
+
*
|
|
70
|
+
* // Remove bindings from all attributes.
|
|
71
|
+
* removeAllBlockBindings();
|
|
72
|
+
* ```
|
|
73
|
+
*/
|
|
74
|
+
export default function useBlockBindingsUtils( clientId ) {
|
|
75
|
+
const { clientId: contextClientId } = useBlockEditContext();
|
|
76
|
+
const blockClientId = clientId || contextClientId;
|
|
77
|
+
const { updateBlockAttributes } = useDispatch( blockEditorStore );
|
|
78
|
+
const { getBlockAttributes } = useRegistry().select( blockEditorStore );
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Updates the value of the bindings connected to block attributes.
|
|
82
|
+
* It removes the binding when the new value is `undefined`.
|
|
83
|
+
*
|
|
84
|
+
* @param {Object} bindings Bindings including the attributes to update and the new object.
|
|
85
|
+
* @param {string} bindings.source The source name to connect to.
|
|
86
|
+
* @param {Object} [bindings.args] Object containing the arguments needed by the source.
|
|
87
|
+
*
|
|
88
|
+
* @example
|
|
89
|
+
* ```js
|
|
90
|
+
* import { useBlockBindingsUtils } from '@wordpress/block-editor'
|
|
91
|
+
*
|
|
92
|
+
* const { updateBlockBindings } = useBlockBindingsUtils();
|
|
93
|
+
* updateBlockBindings( {
|
|
94
|
+
* url: {
|
|
95
|
+
* source: 'core/post-meta',
|
|
96
|
+
* args: {
|
|
97
|
+
* key: 'url_custom_field',
|
|
98
|
+
* },
|
|
99
|
+
* },
|
|
100
|
+
* alt: {
|
|
101
|
+
* source: 'core/post-meta',
|
|
102
|
+
* args: {
|
|
103
|
+
* key: 'text_custom_field',
|
|
104
|
+
* },
|
|
105
|
+
* }
|
|
106
|
+
* } );
|
|
107
|
+
* ```
|
|
108
|
+
*/
|
|
109
|
+
const updateBlockBindings = ( bindings ) => {
|
|
110
|
+
const { metadata: { bindings: currentBindings, ...metadata } = {} } =
|
|
111
|
+
getBlockAttributes( blockClientId );
|
|
112
|
+
const newBindings = { ...currentBindings };
|
|
113
|
+
|
|
114
|
+
Object.entries( bindings ).forEach( ( [ attribute, binding ] ) => {
|
|
115
|
+
if ( ! binding && newBindings[ attribute ] ) {
|
|
116
|
+
delete newBindings[ attribute ];
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
newBindings[ attribute ] = binding;
|
|
120
|
+
} );
|
|
121
|
+
|
|
122
|
+
const newMetadata = {
|
|
123
|
+
...metadata,
|
|
124
|
+
bindings: newBindings,
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
if ( isObjectEmpty( newMetadata.bindings ) ) {
|
|
128
|
+
delete newMetadata.bindings;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
updateBlockAttributes( blockClientId, {
|
|
132
|
+
metadata: isObjectEmpty( newMetadata ) ? undefined : newMetadata,
|
|
133
|
+
} );
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Removes the bindings property of the `metadata` attribute.
|
|
138
|
+
*
|
|
139
|
+
* @example
|
|
140
|
+
* ```js
|
|
141
|
+
* import { useBlockBindingsUtils } from '@wordpress/block-editor'
|
|
142
|
+
*
|
|
143
|
+
* const { removeAllBlockBindings } = useBlockBindingsUtils();
|
|
144
|
+
* removeAllBlockBindings();
|
|
145
|
+
* ```
|
|
146
|
+
*/
|
|
147
|
+
const removeAllBlockBindings = () => {
|
|
148
|
+
const { metadata: { bindings, ...metadata } = {} } =
|
|
149
|
+
getBlockAttributes( blockClientId );
|
|
150
|
+
updateBlockAttributes( blockClientId, {
|
|
151
|
+
metadata: isObjectEmpty( metadata ) ? undefined : metadata,
|
|
152
|
+
} );
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
return { updateBlockBindings, removeAllBlockBindings };
|
|
156
|
+
}
|
|
@@ -100,10 +100,10 @@ const EditWithGeneratedProps = ( props ) => {
|
|
|
100
100
|
),
|
|
101
101
|
};
|
|
102
102
|
}, [
|
|
103
|
-
name,
|
|
104
103
|
blockType?.usesContext,
|
|
105
104
|
blockContext,
|
|
106
105
|
attributes?.metadata?.bindings,
|
|
106
|
+
bindableAttributes,
|
|
107
107
|
registeredSources,
|
|
108
108
|
] );
|
|
109
109
|
|
|
@@ -180,7 +180,6 @@ const EditWithGeneratedProps = ( props ) => {
|
|
|
180
180
|
blockBindings,
|
|
181
181
|
clientId,
|
|
182
182
|
context,
|
|
183
|
-
name,
|
|
184
183
|
registeredSources,
|
|
185
184
|
]
|
|
186
185
|
);
|
|
@@ -262,7 +261,6 @@ const EditWithGeneratedProps = ( props ) => {
|
|
|
262
261
|
hasPatternOverrides,
|
|
263
262
|
setAttributes,
|
|
264
263
|
registeredSources,
|
|
265
|
-
name,
|
|
266
264
|
registry,
|
|
267
265
|
]
|
|
268
266
|
);
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* WordPress dependencies
|
|
3
3
|
*/
|
|
4
|
-
import { getBlockType } from '@wordpress/blocks';
|
|
5
4
|
import { useMemo } from '@wordpress/element';
|
|
6
5
|
|
|
7
6
|
/**
|
|
@@ -16,11 +15,10 @@ export default function BlockStylesPreviewPanel( {
|
|
|
16
15
|
className,
|
|
17
16
|
activeStyle,
|
|
18
17
|
} ) {
|
|
19
|
-
const example = getBlockType( genericPreviewBlock.name )?.example;
|
|
20
18
|
const styleClassName = replaceActiveStyle( className, activeStyle, style );
|
|
21
19
|
const previewBlocks = useMemo( () => {
|
|
22
20
|
return {
|
|
23
|
-
|
|
21
|
+
name: genericPreviewBlock.name,
|
|
24
22
|
title: style.label || style.name,
|
|
25
23
|
description: style.description,
|
|
26
24
|
initialAttributes: {
|
|
@@ -29,9 +27,9 @@ export default function BlockStylesPreviewPanel( {
|
|
|
29
27
|
styleClassName +
|
|
30
28
|
' block-editor-block-styles__block-preview-container',
|
|
31
29
|
},
|
|
32
|
-
example,
|
|
30
|
+
example: genericPreviewBlock,
|
|
33
31
|
};
|
|
34
|
-
}, [ genericPreviewBlock, styleClassName ] );
|
|
32
|
+
}, [ genericPreviewBlock, style, styleClassName ] );
|
|
35
33
|
|
|
36
34
|
return <InserterPreviewPanel item={ previewBlocks } />;
|
|
37
35
|
}
|
|
@@ -37,7 +37,7 @@ function useGenericPreviewBlock( block, type ) {
|
|
|
37
37
|
if ( block ) {
|
|
38
38
|
return cloneBlock( block );
|
|
39
39
|
}
|
|
40
|
-
}, [ type?.example
|
|
40
|
+
}, [ block, type?.example, type?.name ] );
|
|
41
41
|
}
|
|
42
42
|
|
|
43
43
|
/**
|
|
@@ -63,7 +63,7 @@ export default function useStylesForBlocks( { clientId, onSwitch } ) {
|
|
|
63
63
|
const { getBlockStyles } = select( blocksStore );
|
|
64
64
|
|
|
65
65
|
return {
|
|
66
|
-
block,
|
|
66
|
+
block: ! blockType?.example ? block : null,
|
|
67
67
|
blockType,
|
|
68
68
|
styles: getBlockStyles( block.name ),
|
|
69
69
|
className: block.attributes.className || '',
|
|
@@ -32,7 +32,6 @@ import { BlockGroupToolbar } from '../convert-to-group-buttons';
|
|
|
32
32
|
import BlockEditVisuallyButton from '../block-edit-visually-button';
|
|
33
33
|
import { useShowHoveredOrFocusedGestures } from './utils';
|
|
34
34
|
import { store as blockEditorStore } from '../../store';
|
|
35
|
-
import __unstableBlockNameContext from './block-name-context';
|
|
36
35
|
import NavigableToolbar from '../navigable-toolbar';
|
|
37
36
|
import { useHasBlockToolbar } from './use-has-block-toolbar';
|
|
38
37
|
import ChangeDesign from './change-design';
|
|
@@ -265,11 +264,7 @@ export function PrivateBlockToolbar( {
|
|
|
265
264
|
group="other"
|
|
266
265
|
className="block-editor-block-toolbar__slot"
|
|
267
266
|
/>
|
|
268
|
-
<
|
|
269
|
-
value={ blockType?.name }
|
|
270
|
-
>
|
|
271
|
-
<__unstableBlockToolbarLastItem.Slot />
|
|
272
|
-
</__unstableBlockNameContext.Provider>
|
|
267
|
+
<__unstableBlockToolbarLastItem.Slot />
|
|
273
268
|
</>
|
|
274
269
|
) }
|
|
275
270
|
<BlockEditVisuallyButton clientIds={ blockClientIds } />
|
|
@@ -193,6 +193,12 @@
|
|
|
193
193
|
font-size: $helptext-font-size;
|
|
194
194
|
}
|
|
195
195
|
}
|
|
196
|
+
|
|
197
|
+
.block-editor-block-icon {
|
|
198
|
+
width: 0 !important;
|
|
199
|
+
height: 0 !important;
|
|
200
|
+
min-width: 0 !important;
|
|
201
|
+
}
|
|
196
202
|
}
|
|
197
203
|
|
|
198
204
|
// Padding overrides.
|
|
@@ -201,12 +207,6 @@
|
|
|
201
207
|
padding-right: 6px;
|
|
202
208
|
}
|
|
203
209
|
|
|
204
|
-
.block-editor-block-icon {
|
|
205
|
-
width: 0 !important;
|
|
206
|
-
height: 0 !important;
|
|
207
|
-
min-width: 0 !important;
|
|
208
|
-
}
|
|
209
|
-
|
|
210
210
|
// Parent selector overrides
|
|
211
211
|
.block-editor-block-parent-selector .block-editor-block-parent-selector__button {
|
|
212
212
|
border-top-right-radius: 0;
|
|
@@ -295,19 +295,13 @@ function BlockFields( { clientId } ) {
|
|
|
295
295
|
field.Edit = createConfiguredControl( {
|
|
296
296
|
control: fieldDef.type,
|
|
297
297
|
clientId,
|
|
298
|
-
updateBlockAttributes,
|
|
299
298
|
fieldDef,
|
|
300
299
|
} );
|
|
301
300
|
}
|
|
302
301
|
|
|
303
302
|
return field;
|
|
304
303
|
} );
|
|
305
|
-
}, [
|
|
306
|
-
blockTypeFields,
|
|
307
|
-
blockType?.attributes,
|
|
308
|
-
clientId,
|
|
309
|
-
updateBlockAttributes,
|
|
310
|
-
] );
|
|
304
|
+
}, [ blockTypeFields, blockType?.attributes, clientId ] );
|
|
311
305
|
|
|
312
306
|
const handleToggleField = ( fieldId ) => {
|
|
313
307
|
setForm( ( prev ) => {
|
|
@@ -351,26 +345,7 @@ function BlockFields( { clientId } ) {
|
|
|
351
345
|
fields={ dataFormFields }
|
|
352
346
|
form={ form }
|
|
353
347
|
onChange={ ( changes ) => {
|
|
354
|
-
|
|
355
|
-
const mappedChanges = {};
|
|
356
|
-
Object.entries( changes ).forEach(
|
|
357
|
-
( [ fieldId, fieldValue ] ) => {
|
|
358
|
-
const field = dataFormFields.find(
|
|
359
|
-
( f ) => f.id === fieldId
|
|
360
|
-
);
|
|
361
|
-
if ( field && field.setValue ) {
|
|
362
|
-
const updates = field.setValue( {
|
|
363
|
-
item: attributes,
|
|
364
|
-
value: fieldValue,
|
|
365
|
-
} );
|
|
366
|
-
Object.assign( mappedChanges, updates );
|
|
367
|
-
} else {
|
|
368
|
-
// For fields without setValue, use the value directly
|
|
369
|
-
mappedChanges[ fieldId ] = fieldValue;
|
|
370
|
-
}
|
|
371
|
-
}
|
|
372
|
-
);
|
|
373
|
-
updateBlockAttributes( clientId, mappedChanges );
|
|
348
|
+
updateBlockAttributes( clientId, changes );
|
|
374
349
|
} }
|
|
375
350
|
/>
|
|
376
351
|
</div>
|
|
@@ -67,15 +67,15 @@ export function getUpdatedLinkAttributes( {
|
|
|
67
67
|
};
|
|
68
68
|
}
|
|
69
69
|
|
|
70
|
-
export default function Link( { data, field, config = {} } ) {
|
|
70
|
+
export default function Link( { data, field, onChange, config = {} } ) {
|
|
71
71
|
const [ isLinkControlOpen, setIsLinkControlOpen ] = useState( false );
|
|
72
72
|
const { popoverProps } = useInspectorPopoverPlacement( {
|
|
73
73
|
isControl: true,
|
|
74
74
|
} );
|
|
75
|
-
const {
|
|
75
|
+
const { fieldDef } = config;
|
|
76
76
|
const updateAttributes = ( newValue ) => {
|
|
77
77
|
const mappedChanges = field.setValue( { item: data, value: newValue } );
|
|
78
|
-
|
|
78
|
+
onChange( mappedChanges );
|
|
79
79
|
};
|
|
80
80
|
|
|
81
81
|
const value = field.getValue( { item: data } );
|
|
@@ -83,19 +83,19 @@ function MediaThumbnail( { data, field, attachment } ) {
|
|
|
83
83
|
return <Icon icon={ mediaIcon } size={ 24 } />;
|
|
84
84
|
}
|
|
85
85
|
|
|
86
|
-
export default function Media( { data, field, config = {} } ) {
|
|
86
|
+
export default function Media( { data, field, onChange, config = {} } ) {
|
|
87
87
|
const { popoverProps } = useInspectorPopoverPlacement( {
|
|
88
88
|
isControl: true,
|
|
89
89
|
} );
|
|
90
90
|
const value = field.getValue( { item: data } );
|
|
91
91
|
const { allowedTypes = [], multiple = false } = field.config || {};
|
|
92
|
-
const {
|
|
92
|
+
const { fieldDef } = config;
|
|
93
93
|
const updateAttributes = ( newFieldValue ) => {
|
|
94
94
|
const mappedChanges = field.setValue( {
|
|
95
95
|
item: data,
|
|
96
96
|
value: newFieldValue,
|
|
97
97
|
} );
|
|
98
|
-
|
|
98
|
+
onChange( mappedChanges );
|
|
99
99
|
};
|
|
100
100
|
|
|
101
101
|
// Check if featured image is supported by checking if it's in the mapping
|