@wordpress/block-editor 15.10.1-next.79a2f3cdd.0 → 15.10.1-next.v.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-bindings/attribute-control.cjs +1 -1
- package/build/components/block-bindings/attribute-control.cjs.map +1 -1
- package/build/components/block-bindings/source-fields-list.cjs +1 -1
- package/build/components/block-bindings/source-fields-list.cjs.map +1 -1
- package/build/components/block-edit/context.cjs +5 -5
- package/build/components/block-edit/context.cjs.map +1 -1
- package/build/components/block-list/block.cjs +24 -12
- package/build/components/block-list/block.cjs.map +3 -3
- package/build/components/block-list/use-block-props/index.cjs +8 -2
- package/build/components/block-list/use-block-props/index.cjs.map +2 -2
- package/build/components/block-tools/index.cjs +82 -70
- package/build/components/block-tools/index.cjs.map +2 -2
- package/build/components/block-visibility/block-visibility-info.cjs +0 -59
- package/build/components/block-visibility/block-visibility-info.cjs.map +3 -3
- package/build/components/block-visibility/constants.cjs +54 -0
- package/build/components/block-visibility/constants.cjs.map +7 -0
- package/build/components/block-visibility/index.cjs +15 -4
- package/build/components/block-visibility/index.cjs.map +3 -3
- package/build/components/block-visibility/modal.cjs +397 -0
- package/build/components/block-visibility/modal.cjs.map +7 -0
- package/build/components/block-visibility/toolbar.cjs +1 -1
- package/build/components/block-visibility/toolbar.cjs.map +2 -2
- package/build/components/block-visibility/use-block-visibility.cjs +65 -0
- package/build/components/block-visibility/use-block-visibility.cjs.map +7 -0
- package/build/components/block-visibility/utils.cjs +81 -0
- package/build/components/block-visibility/utils.cjs.map +7 -0
- package/build/components/block-visibility/viewport-menu-item.cjs +61 -0
- package/build/components/block-visibility/viewport-menu-item.cjs.map +7 -0
- package/build/components/block-visibility/viewport-toolbar.cjs +89 -0
- package/build/components/block-visibility/viewport-toolbar.cjs.map +7 -0
- package/build/components/collab/block-comment-icon-slot.cjs +1 -1
- package/build/components/collab/block-comment-icon-slot.cjs.map +1 -1
- package/build/components/collab/block-comment-icon-toolbar-slot.cjs +1 -1
- package/build/components/collab/block-comment-icon-toolbar-slot.cjs.map +1 -1
- package/build/components/inner-blocks/use-inner-block-template-sync.cjs +1 -1
- package/build/components/inner-blocks/use-inner-block-template-sync.cjs.map +1 -1
- package/build/components/inserter/menu.cjs +6 -2
- package/build/components/inserter/menu.cjs.map +2 -2
- package/build/components/inspector-controls/groups.cjs +1 -1
- package/build/components/inspector-controls/groups.cjs.map +1 -1
- package/build/components/inspector-controls-tabs/content-tab.cjs +1 -1
- package/build/components/inspector-controls-tabs/content-tab.cjs.map +2 -2
- package/build/components/list-view/block-select-button.cjs +2 -2
- package/build/components/list-view/block-select-button.cjs.map +2 -2
- package/build/components/list-view/block.cjs +39 -22
- package/build/components/list-view/block.cjs.map +2 -2
- package/build/components/list-view/index.cjs +11 -6
- package/build/components/list-view/index.cjs.map +2 -2
- package/build/components/list-view/utils.cjs +24 -17
- package/build/components/list-view/utils.cjs.map +2 -2
- package/build/components/rich-text/event-listeners/input-rules.cjs +13 -1
- package/build/components/rich-text/event-listeners/input-rules.cjs.map +2 -2
- package/build/components/rich-text/format-edit.cjs +1 -1
- package/build/components/rich-text/format-edit.cjs.map +1 -1
- package/build/components/rich-text/index.cjs +2 -2
- package/build/components/rich-text/index.cjs.map +2 -2
- package/build/components/url-input/index.cjs +2 -0
- package/build/components/url-input/index.cjs.map +2 -2
- package/build/components/use-block-commands/index.cjs +1 -1
- package/build/components/use-block-commands/index.cjs.map +2 -2
- package/build/components/writing-flow/utils.cjs +1 -1
- package/build/components/writing-flow/utils.cjs.map +1 -1
- package/build/hooks/block-fields/index.cjs +76 -167
- package/build/hooks/block-fields/index.cjs.map +2 -2
- package/build/hooks/block-fields/link/index.cjs +13 -23
- package/build/hooks/block-fields/link/index.cjs.map +2 -2
- package/build/hooks/block-fields/media/index.cjs +32 -58
- package/build/hooks/block-fields/media/index.cjs.map +2 -2
- package/build/hooks/block-fields/rich-text/index.cjs +1 -5
- package/build/hooks/block-fields/rich-text/index.cjs.map +2 -2
- package/build/hooks/cross-origin-isolation.cjs +102 -0
- package/build/hooks/cross-origin-isolation.cjs.map +7 -0
- package/build/hooks/fit-text.cjs +1 -1
- package/build/hooks/fit-text.cjs.map +1 -1
- package/build/hooks/index.cjs +1 -0
- package/build/hooks/index.cjs.map +2 -2
- package/build/layouts/flex.cjs +6 -2
- package/build/layouts/flex.cjs.map +2 -2
- package/build/store/private-keys.cjs +10 -10
- package/build/store/private-keys.cjs.map +1 -1
- package/build/store/private-selectors.cjs +33 -1
- package/build/store/private-selectors.cjs.map +3 -3
- package/build/store/reducer.cjs +1 -1
- package/build/store/reducer.cjs.map +1 -1
- package/build/store/selectors.cjs +7 -8
- package/build/store/selectors.cjs.map +2 -2
- package/build/store/utils.cjs +1 -1
- package/build/store/utils.cjs.map +1 -1
- package/build-module/components/block-bindings/attribute-control.mjs +1 -1
- package/build-module/components/block-bindings/attribute-control.mjs.map +1 -1
- package/build-module/components/block-bindings/source-fields-list.mjs +1 -1
- package/build-module/components/block-bindings/source-fields-list.mjs.map +1 -1
- package/build-module/components/block-edit/context.mjs +5 -5
- package/build-module/components/block-edit/context.mjs.map +1 -1
- package/build-module/components/block-list/block.mjs +24 -12
- package/build-module/components/block-list/block.mjs.map +3 -3
- package/build-module/components/block-list/use-block-props/index.mjs +8 -2
- package/build-module/components/block-list/use-block-props/index.mjs.map +2 -2
- package/build-module/components/block-tools/index.mjs +85 -73
- package/build-module/components/block-tools/index.mjs.map +2 -2
- package/build-module/components/block-visibility/block-visibility-info.mjs +0 -59
- package/build-module/components/block-visibility/block-visibility-info.mjs.map +3 -3
- package/build-module/components/block-visibility/constants.mjs +28 -0
- package/build-module/components/block-visibility/constants.mjs.map +7 -0
- package/build-module/components/block-visibility/index.mjs +13 -4
- package/build-module/components/block-visibility/index.mjs.map +2 -2
- package/build-module/components/block-visibility/modal.mjs +384 -0
- package/build-module/components/block-visibility/modal.mjs.map +7 -0
- package/build-module/components/block-visibility/toolbar.mjs +1 -1
- package/build-module/components/block-visibility/toolbar.mjs.map +2 -2
- package/build-module/components/block-visibility/use-block-visibility.mjs +44 -0
- package/build-module/components/block-visibility/use-block-visibility.mjs.map +7 -0
- package/build-module/components/block-visibility/utils.mjs +55 -0
- package/build-module/components/block-visibility/utils.mjs.map +7 -0
- package/build-module/components/block-visibility/viewport-menu-item.mjs +40 -0
- package/build-module/components/block-visibility/viewport-menu-item.mjs.map +7 -0
- package/build-module/components/block-visibility/viewport-toolbar.mjs +68 -0
- package/build-module/components/block-visibility/viewport-toolbar.mjs.map +7 -0
- package/build-module/components/collab/block-comment-icon-slot.mjs +1 -1
- package/build-module/components/collab/block-comment-icon-slot.mjs.map +1 -1
- package/build-module/components/collab/block-comment-icon-toolbar-slot.mjs +1 -1
- package/build-module/components/collab/block-comment-icon-toolbar-slot.mjs.map +1 -1
- package/build-module/components/inner-blocks/use-inner-block-template-sync.mjs +1 -1
- package/build-module/components/inner-blocks/use-inner-block-template-sync.mjs.map +1 -1
- package/build-module/components/inserter/menu.mjs +6 -2
- package/build-module/components/inserter/menu.mjs.map +2 -2
- package/build-module/components/inspector-controls/groups.mjs +1 -1
- package/build-module/components/inspector-controls/groups.mjs.map +1 -1
- package/build-module/components/inspector-controls-tabs/content-tab.mjs +1 -1
- package/build-module/components/inspector-controls-tabs/content-tab.mjs.map +2 -2
- package/build-module/components/list-view/block-select-button.mjs +2 -2
- package/build-module/components/list-view/block-select-button.mjs.map +2 -2
- package/build-module/components/list-view/block.mjs +39 -22
- package/build-module/components/list-view/block.mjs.map +2 -2
- package/build-module/components/list-view/index.mjs +11 -7
- package/build-module/components/list-view/index.mjs.map +2 -2
- package/build-module/components/list-view/utils.mjs +24 -17
- package/build-module/components/list-view/utils.mjs.map +2 -2
- package/build-module/components/rich-text/event-listeners/input-rules.mjs +13 -1
- package/build-module/components/rich-text/event-listeners/input-rules.mjs.map +2 -2
- package/build-module/components/rich-text/format-edit.mjs +1 -1
- package/build-module/components/rich-text/format-edit.mjs.map +1 -1
- package/build-module/components/rich-text/index.mjs +2 -2
- package/build-module/components/rich-text/index.mjs.map +2 -2
- package/build-module/components/url-input/index.mjs +2 -0
- package/build-module/components/url-input/index.mjs.map +2 -2
- package/build-module/components/use-block-commands/index.mjs +1 -1
- package/build-module/components/use-block-commands/index.mjs.map +2 -2
- package/build-module/components/writing-flow/utils.mjs +1 -1
- package/build-module/components/writing-flow/utils.mjs.map +1 -1
- package/build-module/hooks/block-fields/index.mjs +76 -167
- package/build-module/hooks/block-fields/index.mjs.map +2 -2
- package/build-module/hooks/block-fields/link/index.mjs +13 -23
- package/build-module/hooks/block-fields/link/index.mjs.map +2 -2
- package/build-module/hooks/block-fields/media/index.mjs +32 -58
- package/build-module/hooks/block-fields/media/index.mjs.map +2 -2
- package/build-module/hooks/block-fields/rich-text/index.mjs +1 -5
- package/build-module/hooks/block-fields/rich-text/index.mjs.map +2 -2
- package/build-module/hooks/cross-origin-isolation.mjs +100 -0
- package/build-module/hooks/cross-origin-isolation.mjs.map +7 -0
- package/build-module/hooks/fit-text.mjs +1 -1
- package/build-module/hooks/fit-text.mjs.map +1 -1
- package/build-module/hooks/index.mjs +1 -0
- package/build-module/hooks/index.mjs.map +2 -2
- package/build-module/layouts/flex.mjs +6 -2
- package/build-module/layouts/flex.mjs.map +2 -2
- package/build-module/store/private-keys.mjs +10 -10
- package/build-module/store/private-keys.mjs.map +1 -1
- package/build-module/store/private-selectors.mjs +34 -1
- package/build-module/store/private-selectors.mjs.map +2 -2
- package/build-module/store/reducer.mjs +1 -1
- package/build-module/store/reducer.mjs.map +1 -1
- package/build-module/store/selectors.mjs +7 -8
- package/build-module/store/selectors.mjs.map +2 -2
- package/build-module/store/utils.mjs +1 -1
- package/build-module/store/utils.mjs.map +1 -1
- package/build-style/content-rtl.css +4 -1
- package/build-style/content.css +4 -1
- package/build-style/style-rtl.css +54 -1
- package/build-style/style.css +54 -1
- package/package.json +39 -39
- package/src/components/block-bindings/attribute-control.js +1 -1
- package/src/components/block-bindings/source-fields-list.js +1 -1
- package/src/components/block-list/block.js +23 -9
- package/src/components/block-list/content.scss +4 -1
- package/src/components/block-list/use-block-props/index.js +10 -2
- package/src/components/block-toolbar/style.scss +0 -1
- package/src/components/block-tools/index.js +45 -33
- package/src/components/block-tools/style.scss +10 -0
- package/src/components/block-visibility/block-visibility-info.js +0 -1
- package/src/components/block-visibility/constants.js +33 -0
- package/src/components/block-visibility/index.js +21 -2
- package/src/components/block-visibility/modal.js +358 -0
- package/src/components/block-visibility/style.scss +58 -0
- package/src/components/block-visibility/test/use-block-visibility.js +316 -0
- package/src/components/block-visibility/test/utils.js +266 -0
- package/src/components/block-visibility/toolbar.js +1 -1
- package/src/components/block-visibility/use-block-visibility.js +70 -0
- package/src/components/block-visibility/utils.js +95 -0
- package/src/components/block-visibility/viewport-menu-item.js +42 -0
- package/src/components/block-visibility/viewport-toolbar.js +88 -0
- package/src/components/inner-blocks/use-inner-block-template-sync.js +1 -1
- package/src/components/inserter/menu.js +6 -2
- package/src/components/inspector-controls-tabs/content-tab.js +0 -1
- package/src/components/list-view/block-select-button.js +2 -2
- package/src/components/list-view/block.js +47 -25
- package/src/components/list-view/index.js +15 -11
- package/src/components/list-view/utils.js +31 -23
- package/src/components/rich-text/event-listeners/input-rules.js +17 -0
- package/src/components/rich-text/index.js +1 -1
- package/src/components/url-input/index.js +2 -0
- package/src/components/use-block-commands/index.js +4 -3
- package/src/hooks/block-fields/index.js +104 -225
- package/src/hooks/block-fields/link/index.js +13 -39
- package/src/hooks/block-fields/media/index.js +31 -90
- package/src/hooks/block-fields/rich-text/index.js +1 -5
- package/src/hooks/block-fields/styles.scss +2 -0
- package/src/hooks/cross-origin-isolation.js +143 -0
- package/src/hooks/fit-text.js +1 -1
- package/src/hooks/index.js +1 -0
- package/src/layouts/flex.js +8 -3
- package/src/layouts/test/flex.js +53 -0
- package/src/store/private-selectors.js +64 -1
- package/src/store/reducer.js +1 -1
- package/src/store/selectors.js +7 -9
- package/src/store/test/private-selectors.js +80 -0
- package/src/style.scss +1 -0
- package/src/components/block-visibility/styles.scss +0 -10
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
import { createHigherOrderComponent } from '@wordpress/compose';
|
|
11
11
|
import { DataForm } from '@wordpress/dataviews';
|
|
12
12
|
import { useContext, useState, useMemo } from '@wordpress/element';
|
|
13
|
+
import { __ } from '@wordpress/i18n';
|
|
13
14
|
|
|
14
15
|
/**
|
|
15
16
|
* Internal dependencies
|
|
@@ -38,138 +39,41 @@ const CONTROLS = {
|
|
|
38
39
|
* Creates a configured control component that wraps a custom control
|
|
39
40
|
* and passes configuration as props.
|
|
40
41
|
*
|
|
41
|
-
* @param {
|
|
42
|
-
* @param {string}
|
|
42
|
+
* @param {Component} ControlComponent The React component for the control.
|
|
43
|
+
* @param {string} type The type of control.
|
|
44
|
+
* @param {Object} config The control configuration passed as a prop.
|
|
45
|
+
*
|
|
43
46
|
* @return {Function} A wrapped control component
|
|
44
47
|
*/
|
|
45
|
-
function createConfiguredControl( config ) {
|
|
46
|
-
const { control, ...controlConfig } = config;
|
|
47
|
-
const ControlComponent = CONTROLS[ control ];
|
|
48
|
-
|
|
48
|
+
function createConfiguredControl( ControlComponent, type, config ) {
|
|
49
49
|
if ( ! ControlComponent ) {
|
|
50
|
-
throw new Error( `Control type "${
|
|
50
|
+
throw new Error( `Control type "${ type }" not found` );
|
|
51
51
|
}
|
|
52
52
|
|
|
53
53
|
return function ConfiguredControl( props ) {
|
|
54
|
-
return <ControlComponent { ...props } config={
|
|
55
|
-
};
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
/**
|
|
59
|
-
* Normalize a media value to a canonical structure.
|
|
60
|
-
* Only includes properties that are present in the field's mapping (if provided).
|
|
61
|
-
*
|
|
62
|
-
* @param {Object} value - The mapped value from the block attributes (with canonical keys)
|
|
63
|
-
* @param {Object} fieldDef - Optional field definition containing the mapping
|
|
64
|
-
* @return {Object} Normalized media value with canonical properties
|
|
65
|
-
*/
|
|
66
|
-
function normalizeMediaValue( value, fieldDef ) {
|
|
67
|
-
const defaults = {
|
|
68
|
-
id: null,
|
|
69
|
-
url: '',
|
|
70
|
-
caption: '',
|
|
71
|
-
alt: '',
|
|
72
|
-
type: 'image',
|
|
73
|
-
poster: '',
|
|
74
|
-
featuredImage: false,
|
|
75
|
-
link: '',
|
|
54
|
+
return <ControlComponent { ...props } config={ config } />;
|
|
76
55
|
};
|
|
77
|
-
|
|
78
|
-
const result = {};
|
|
79
|
-
|
|
80
|
-
// If there's a mapping, only include properties that are in it
|
|
81
|
-
if ( fieldDef?.mapping ) {
|
|
82
|
-
Object.keys( fieldDef.mapping ).forEach( ( key ) => {
|
|
83
|
-
result[ key ] = value?.[ key ] ?? defaults[ key ] ?? '';
|
|
84
|
-
} );
|
|
85
|
-
return result;
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
// Without mapping, include all default properties
|
|
89
|
-
Object.keys( defaults ).forEach( ( key ) => {
|
|
90
|
-
result[ key ] = value?.[ key ] ?? defaults[ key ];
|
|
91
|
-
} );
|
|
92
|
-
return result;
|
|
93
56
|
}
|
|
94
57
|
|
|
95
58
|
/**
|
|
96
|
-
*
|
|
97
|
-
*
|
|
98
|
-
*
|
|
99
|
-
* @param {Object}
|
|
100
|
-
* @param {Object}
|
|
101
|
-
* @
|
|
59
|
+
* Component that renders a DataForm for a single block's attributes
|
|
60
|
+
* @param {Object} props
|
|
61
|
+
* @param {string} props.clientId The clientId of the block.
|
|
62
|
+
* @param {Object} props.blockType The blockType definition.
|
|
63
|
+
* @param {Object} props.attributes The block's attribute values.
|
|
64
|
+
* @param {Function} props.setAttributes Action to set the block's attributes.
|
|
65
|
+
* @param {boolean} props.isCollapsed Whether the DataForm is rendered as 'collapsed' with only the first field
|
|
66
|
+
* displayed by default. When collapsed a dropdown is displayed to allow
|
|
67
|
+
* displaying additional fields. The block's title is displayed as the title.
|
|
68
|
+
* The collapsed mode is often used when multiple BlockForms are shown together.
|
|
102
69
|
*/
|
|
103
|
-
function
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
if ( key in value ) {
|
|
111
|
-
result[ key ] = value[ key ];
|
|
112
|
-
}
|
|
113
|
-
} );
|
|
114
|
-
return result;
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
/**
|
|
118
|
-
* Normalize a link value to a canonical structure.
|
|
119
|
-
* Only includes properties that are present in the field's mapping (if provided).
|
|
120
|
-
*
|
|
121
|
-
* @param {Object} value - The mapped value from the block attributes (with canonical keys)
|
|
122
|
-
* @param {Object} fieldDef - Optional field definition containing the mapping
|
|
123
|
-
* @return {Object} Normalized link value with canonical properties
|
|
124
|
-
*/
|
|
125
|
-
function normalizeLinkValue( value, fieldDef ) {
|
|
126
|
-
const defaults = {
|
|
127
|
-
url: '',
|
|
128
|
-
rel: '',
|
|
129
|
-
linkTarget: '',
|
|
130
|
-
destination: '',
|
|
131
|
-
};
|
|
132
|
-
|
|
133
|
-
const result = {};
|
|
134
|
-
|
|
135
|
-
// If there's a mapping, only include properties that are in it
|
|
136
|
-
if ( fieldDef?.mapping ) {
|
|
137
|
-
Object.keys( fieldDef.mapping ).forEach( ( key ) => {
|
|
138
|
-
result[ key ] = value?.[ key ] ?? defaults[ key ] ?? '';
|
|
139
|
-
} );
|
|
140
|
-
return result;
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
// Without mapping, include all default properties
|
|
144
|
-
Object.keys( defaults ).forEach( ( key ) => {
|
|
145
|
-
result[ key ] = value?.[ key ] ?? defaults[ key ];
|
|
146
|
-
} );
|
|
147
|
-
return result;
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
/**
|
|
151
|
-
* Denormalize a link value from canonical structure back to mapped keys.
|
|
152
|
-
* Only includes properties that are present in the field's mapping.
|
|
153
|
-
*
|
|
154
|
-
* @param {Object} value - The normalized link value
|
|
155
|
-
* @param {Object} fieldDef - The field definition containing the mapping
|
|
156
|
-
* @return {Object} Value with only mapped properties
|
|
157
|
-
*/
|
|
158
|
-
function denormalizeLinkValue( value, fieldDef ) {
|
|
159
|
-
if ( ! fieldDef.mapping ) {
|
|
160
|
-
return value;
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
const result = {};
|
|
164
|
-
Object.entries( fieldDef.mapping ).forEach( ( [ key ] ) => {
|
|
165
|
-
if ( key in value ) {
|
|
166
|
-
result[ key ] = value[ key ];
|
|
167
|
-
}
|
|
168
|
-
} );
|
|
169
|
-
return result;
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
function BlockFields( { clientId, blockType, attributes, setAttributes } ) {
|
|
70
|
+
function BlockFields( {
|
|
71
|
+
clientId,
|
|
72
|
+
blockType,
|
|
73
|
+
attributes,
|
|
74
|
+
setAttributes,
|
|
75
|
+
isCollapsed = false,
|
|
76
|
+
} ) {
|
|
173
77
|
const blockTitle = useBlockDisplayTitle( {
|
|
174
78
|
clientId,
|
|
175
79
|
context: 'list-view',
|
|
@@ -178,9 +82,19 @@ function BlockFields( { clientId, blockType, attributes, setAttributes } ) {
|
|
|
178
82
|
|
|
179
83
|
const blockTypeFields = blockType?.[ fieldsKey ];
|
|
180
84
|
|
|
181
|
-
const
|
|
182
|
-
|
|
183
|
-
|
|
85
|
+
const computedForm = useMemo( () => {
|
|
86
|
+
if ( ! isCollapsed ) {
|
|
87
|
+
return blockType?.[ formKey ];
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// For a collapsed form only show the first field by default.
|
|
91
|
+
return {
|
|
92
|
+
...blockType?.[ formKey ],
|
|
93
|
+
fields: [ blockType?.[ formKey ]?.fields?.[ 0 ] ],
|
|
94
|
+
};
|
|
95
|
+
}, [ blockType, isCollapsed ] );
|
|
96
|
+
|
|
97
|
+
const [ form, setForm ] = useState( computedForm );
|
|
184
98
|
|
|
185
99
|
// Build DataForm fields with proper structure
|
|
186
100
|
const dataFormFields = useMemo( () => {
|
|
@@ -189,100 +103,63 @@ function BlockFields( { clientId, blockType, attributes, setAttributes } ) {
|
|
|
189
103
|
}
|
|
190
104
|
|
|
191
105
|
return blockTypeFields.map( ( fieldDef ) => {
|
|
192
|
-
const ControlComponent = CONTROLS[ fieldDef.type ];
|
|
193
|
-
|
|
194
|
-
const defaultValues = {};
|
|
195
|
-
if ( fieldDef.mapping && blockType?.attributes ) {
|
|
196
|
-
Object.entries( fieldDef.mapping ).forEach(
|
|
197
|
-
( [ key, attrKey ] ) => {
|
|
198
|
-
defaultValues[ key ] =
|
|
199
|
-
blockType.attributes[ attrKey ]?.defaultValue ??
|
|
200
|
-
undefined;
|
|
201
|
-
}
|
|
202
|
-
);
|
|
203
|
-
}
|
|
204
|
-
|
|
205
106
|
const field = {
|
|
206
107
|
id: fieldDef.id,
|
|
207
108
|
label: fieldDef.label,
|
|
208
109
|
type: fieldDef.type, // Use the field's type; DataForm will use built-in or custom Edit
|
|
209
|
-
|
|
210
|
-
hideLabelFromVision: fieldDef.id === 'content',
|
|
211
|
-
// getValue and setValue handle the mapping to block attributes
|
|
212
|
-
getValue: ( { item } ) => {
|
|
213
|
-
if ( fieldDef.mapping ) {
|
|
214
|
-
// Extract mapped properties from the block attributes
|
|
215
|
-
const mappedValue = {};
|
|
216
|
-
Object.entries( fieldDef.mapping ).forEach(
|
|
217
|
-
( [ key, attrKey ] ) => {
|
|
218
|
-
mappedValue[ key ] = item[ attrKey ];
|
|
219
|
-
}
|
|
220
|
-
);
|
|
110
|
+
};
|
|
221
111
|
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
112
|
+
// If the field defines a `mapping`, then custom `getValue` and `setValue`
|
|
113
|
+
// implementations are provided.
|
|
114
|
+
// These functions map from the inconsistent attribute keys found on blocks
|
|
115
|
+
// to consistent keys that the field can use internally (and back again).
|
|
116
|
+
// When `mapping` isn't provided, we can use the field API's default
|
|
117
|
+
// implementation of these functions.
|
|
118
|
+
if ( fieldDef.mapping ) {
|
|
119
|
+
field.getValue = ( { item } ) => {
|
|
120
|
+
// Extract mapped properties from the block attributes
|
|
121
|
+
const mappedValue = {};
|
|
122
|
+
Object.entries( fieldDef.mapping ).forEach(
|
|
123
|
+
( [ key, attrKey ] ) => {
|
|
124
|
+
mappedValue[ key ] = item[ attrKey ];
|
|
228
125
|
}
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
if ( fieldDef.mapping ) {
|
|
238
|
-
// Denormalize from canonical structure back to mapped keys
|
|
239
|
-
let denormalizedValue = value;
|
|
240
|
-
if ( fieldDef.type === 'media' ) {
|
|
241
|
-
denormalizedValue = denormalizeMediaValue(
|
|
242
|
-
value,
|
|
243
|
-
fieldDef
|
|
244
|
-
);
|
|
245
|
-
} else if ( fieldDef.type === 'link' ) {
|
|
246
|
-
denormalizedValue = denormalizeLinkValue(
|
|
247
|
-
value,
|
|
248
|
-
fieldDef
|
|
249
|
-
);
|
|
126
|
+
);
|
|
127
|
+
return mappedValue;
|
|
128
|
+
};
|
|
129
|
+
field.setValue = ( { value } ) => {
|
|
130
|
+
const attributeUpdates = {};
|
|
131
|
+
Object.entries( fieldDef.mapping ).forEach(
|
|
132
|
+
( [ key, attrKey ] ) => {
|
|
133
|
+
attributeUpdates[ attrKey ] = value[ key ];
|
|
250
134
|
}
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
( [ key, attrKey ] ) => {
|
|
256
|
-
// If key is explicitly in value, use it (even if undefined to allow clearing)
|
|
257
|
-
// Otherwise, preserve the old value
|
|
258
|
-
if ( key in denormalizedValue ) {
|
|
259
|
-
updates[ attrKey ] =
|
|
260
|
-
denormalizedValue[ key ];
|
|
261
|
-
} else {
|
|
262
|
-
updates[ attrKey ] = item[ attrKey ];
|
|
263
|
-
}
|
|
264
|
-
}
|
|
265
|
-
);
|
|
266
|
-
return updates;
|
|
267
|
-
}
|
|
268
|
-
// For simple id-based fields, use the id as the attribute key
|
|
269
|
-
return { [ fieldDef.id ]: value };
|
|
270
|
-
},
|
|
271
|
-
};
|
|
135
|
+
);
|
|
136
|
+
return attributeUpdates;
|
|
137
|
+
};
|
|
138
|
+
}
|
|
272
139
|
|
|
273
140
|
// Only add custom Edit component if one exists for this type
|
|
141
|
+
const ControlComponent = CONTROLS[ fieldDef.type ];
|
|
274
142
|
if ( ControlComponent ) {
|
|
275
143
|
// Use EditConfig pattern: Edit is an object with control type and config props
|
|
276
|
-
field.Edit = createConfiguredControl(
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
144
|
+
field.Edit = createConfiguredControl(
|
|
145
|
+
ControlComponent,
|
|
146
|
+
fieldDef.type,
|
|
147
|
+
{
|
|
148
|
+
clientId,
|
|
149
|
+
fieldDef,
|
|
150
|
+
}
|
|
151
|
+
);
|
|
281
152
|
}
|
|
282
153
|
|
|
283
154
|
return field;
|
|
284
155
|
} );
|
|
285
|
-
}, [ blockTypeFields,
|
|
156
|
+
}, [ blockTypeFields, clientId ] );
|
|
157
|
+
|
|
158
|
+
if ( ! blockTypeFields?.length ) {
|
|
159
|
+
// TODO - we might still want to show a placeholder for blocks with no fields.
|
|
160
|
+
// for example, a way to select the block.
|
|
161
|
+
return null;
|
|
162
|
+
}
|
|
286
163
|
|
|
287
164
|
const handleToggleField = ( fieldId ) => {
|
|
288
165
|
setForm( ( prev ) => {
|
|
@@ -300,31 +177,33 @@ function BlockFields( { clientId, blockType, attributes, setAttributes } ) {
|
|
|
300
177
|
} );
|
|
301
178
|
};
|
|
302
179
|
|
|
303
|
-
if ( ! blockTypeFields?.length ) {
|
|
304
|
-
// TODO - we might still want to show a placeholder for blocks with no fields.
|
|
305
|
-
// for example, a way to select the block.
|
|
306
|
-
return null;
|
|
307
|
-
}
|
|
308
|
-
|
|
309
180
|
return (
|
|
310
181
|
<div className="block-editor-block-fields__container">
|
|
311
182
|
<div className="block-editor-block-fields__header">
|
|
312
183
|
<HStack spacing={ 1 }>
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
184
|
+
{ isCollapsed && (
|
|
185
|
+
<>
|
|
186
|
+
<BlockIcon
|
|
187
|
+
className="block-editor-block-fields__header-icon"
|
|
188
|
+
icon={ blockInformation?.icon }
|
|
189
|
+
/>
|
|
190
|
+
<h2 className="block-editor-block-fields__header-title">
|
|
191
|
+
<Truncate numberOfLines={ 1 }>
|
|
192
|
+
{ blockTitle }
|
|
193
|
+
</Truncate>
|
|
194
|
+
</h2>
|
|
195
|
+
<FieldsDropdownMenu
|
|
196
|
+
fields={ dataFormFields }
|
|
197
|
+
visibleFields={ form.fields }
|
|
198
|
+
onToggleField={ handleToggleField }
|
|
199
|
+
/>
|
|
200
|
+
</>
|
|
201
|
+
) }
|
|
202
|
+
{ ! isCollapsed && (
|
|
203
|
+
<h2 className="block-editor-block-fields__header-title">
|
|
204
|
+
{ __( 'Content' ) }
|
|
205
|
+
</h2>
|
|
206
|
+
) }
|
|
328
207
|
</HStack>
|
|
329
208
|
</div>
|
|
330
209
|
<DataForm
|
|
@@ -348,7 +227,6 @@ const withBlockFields = createHigherOrderComponent(
|
|
|
348
227
|
} = useContext( PrivateBlockContext );
|
|
349
228
|
|
|
350
229
|
const shouldShowBlockFields =
|
|
351
|
-
window?.__experimentalContentOnlyPatternInsertion &&
|
|
352
230
|
window?.__experimentalContentOnlyInspectorFields;
|
|
353
231
|
const blockTypeFields = blockType?.[ fieldsKey ];
|
|
354
232
|
|
|
@@ -371,6 +249,7 @@ const withBlockFields = createHigherOrderComponent(
|
|
|
371
249
|
<BlockFields
|
|
372
250
|
{ ...props }
|
|
373
251
|
blockType={ blockType }
|
|
252
|
+
isCollapsed
|
|
374
253
|
/>
|
|
375
254
|
</PrivateInspectorControlsFill>
|
|
376
255
|
)
|
|
@@ -73,11 +73,6 @@ export default function Link( { data, field, onChange, config = {} } ) {
|
|
|
73
73
|
isControl: true,
|
|
74
74
|
} );
|
|
75
75
|
const { fieldDef } = config;
|
|
76
|
-
const updateAttributes = ( newValue ) => {
|
|
77
|
-
const mappedChanges = field.setValue( { item: data, value: newValue } );
|
|
78
|
-
onChange( mappedChanges );
|
|
79
|
-
};
|
|
80
|
-
|
|
81
76
|
const value = field.getValue( { item: data } );
|
|
82
77
|
const url = value?.url;
|
|
83
78
|
const rel = value?.rel || '';
|
|
@@ -145,30 +140,12 @@ export default function Link( { data, field, onChange, config = {} } ) {
|
|
|
145
140
|
...newValues,
|
|
146
141
|
} );
|
|
147
142
|
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
if ( key === 'href' || key === 'url' ) {
|
|
155
|
-
updateValue[ key ] =
|
|
156
|
-
updatedAttrs.url;
|
|
157
|
-
} else if ( key === 'rel' ) {
|
|
158
|
-
updateValue[ key ] =
|
|
159
|
-
updatedAttrs.rel;
|
|
160
|
-
} else if (
|
|
161
|
-
key === 'target' ||
|
|
162
|
-
key === 'linkTarget'
|
|
163
|
-
) {
|
|
164
|
-
updateValue[ key ] =
|
|
165
|
-
updatedAttrs.linkTarget;
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
);
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
updateAttributes( updateValue );
|
|
143
|
+
onChange(
|
|
144
|
+
field.setValue( {
|
|
145
|
+
item: data,
|
|
146
|
+
value: updatedAttrs,
|
|
147
|
+
} )
|
|
148
|
+
);
|
|
172
149
|
} }
|
|
173
150
|
onRemove={ () => {
|
|
174
151
|
// Remove all link-related properties based on what's in the mapping
|
|
@@ -177,20 +154,17 @@ export default function Link( { data, field, onChange, config = {} } ) {
|
|
|
177
154
|
if ( fieldDef?.mapping ) {
|
|
178
155
|
Object.keys( fieldDef.mapping ).forEach(
|
|
179
156
|
( key ) => {
|
|
180
|
-
|
|
181
|
-
key === 'href' ||
|
|
182
|
-
key === 'url' ||
|
|
183
|
-
key === 'rel' ||
|
|
184
|
-
key === 'target' ||
|
|
185
|
-
key === 'linkTarget'
|
|
186
|
-
) {
|
|
187
|
-
removeValue[ key ] = undefined;
|
|
188
|
-
}
|
|
157
|
+
removeValue[ key ] = undefined;
|
|
189
158
|
}
|
|
190
159
|
);
|
|
191
160
|
}
|
|
192
161
|
|
|
193
|
-
|
|
162
|
+
onChange(
|
|
163
|
+
field.setValue( {
|
|
164
|
+
item: data,
|
|
165
|
+
value: removeValue,
|
|
166
|
+
} )
|
|
167
|
+
);
|
|
194
168
|
} }
|
|
195
169
|
/>
|
|
196
170
|
</Popover>
|
|
@@ -24,9 +24,9 @@ import { useInspectorPopoverPlacement } from '../use-inspector-popover-placement
|
|
|
24
24
|
import { getMediaSelectKey } from '../../../store/private-keys';
|
|
25
25
|
import { store as blockEditorStore } from '../../../store';
|
|
26
26
|
|
|
27
|
-
function MediaThumbnail( { data, field, attachment } ) {
|
|
28
|
-
const
|
|
29
|
-
const { allowedTypes = [], multiple = false } =
|
|
27
|
+
function MediaThumbnail( { data, field, attachment, config } ) {
|
|
28
|
+
const { fieldDef } = config;
|
|
29
|
+
const { allowedTypes = [], multiple = false } = fieldDef.args || {};
|
|
30
30
|
|
|
31
31
|
if ( multiple ) {
|
|
32
32
|
return 'todo multiple';
|
|
@@ -53,7 +53,7 @@ function MediaThumbnail( { data, field, attachment } ) {
|
|
|
53
53
|
const value = field.getValue( { item: data } );
|
|
54
54
|
const url = value?.url;
|
|
55
55
|
|
|
56
|
-
if ( url ) {
|
|
56
|
+
if ( allowedTypes[ 0 ] === 'image' && url ) {
|
|
57
57
|
return (
|
|
58
58
|
<div className="block-editor-content-only-controls__media-thumbnail">
|
|
59
59
|
<img alt="" width={ 24 } height={ 24 } src={ url } />
|
|
@@ -85,15 +85,8 @@ export default function Media( { data, field, onChange, config = {} } ) {
|
|
|
85
85
|
isControl: true,
|
|
86
86
|
} );
|
|
87
87
|
const value = field.getValue( { item: data } );
|
|
88
|
-
const { allowedTypes = [], multiple = false } = field.config || {};
|
|
89
88
|
const { fieldDef } = config;
|
|
90
|
-
const
|
|
91
|
-
const mappedChanges = field.setValue( {
|
|
92
|
-
item: data,
|
|
93
|
-
value: newFieldValue,
|
|
94
|
-
} );
|
|
95
|
-
onChange( mappedChanges );
|
|
96
|
-
};
|
|
89
|
+
const { allowedTypes = [], multiple = false } = fieldDef.args || {};
|
|
97
90
|
|
|
98
91
|
// Check if featured image is supported by checking if it's in the mapping
|
|
99
92
|
const hasFeaturedImageSupport =
|
|
@@ -152,102 +145,49 @@ export default function Media( { data, field, onChange, config = {} } ) {
|
|
|
152
145
|
|
|
153
146
|
if ( fieldDef?.mapping ) {
|
|
154
147
|
Object.keys( fieldDef.mapping ).forEach( ( key ) => {
|
|
155
|
-
|
|
156
|
-
key === 'id' ||
|
|
157
|
-
key === 'src' ||
|
|
158
|
-
key === 'url'
|
|
159
|
-
) {
|
|
160
|
-
resetValue[ key ] = undefined;
|
|
161
|
-
} else if ( key === 'caption' || key === 'alt' ) {
|
|
162
|
-
resetValue[ key ] = '';
|
|
163
|
-
}
|
|
148
|
+
resetValue[ key ] = undefined;
|
|
164
149
|
} );
|
|
165
150
|
}
|
|
166
151
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
updateAttributes( { ...value, ...resetValue } );
|
|
152
|
+
onChange(
|
|
153
|
+
field.setValue( {
|
|
154
|
+
item: data,
|
|
155
|
+
value: resetValue,
|
|
156
|
+
} )
|
|
157
|
+
);
|
|
174
158
|
} }
|
|
175
159
|
{ ...( hasFeaturedImageSupport && {
|
|
176
160
|
useFeaturedImage: !! value?.featuredImage,
|
|
177
161
|
onToggleFeaturedImage: () => {
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
162
|
+
onChange(
|
|
163
|
+
field.setValue( {
|
|
164
|
+
item: data,
|
|
165
|
+
value: {
|
|
166
|
+
featuredImage: ! value?.featuredImage,
|
|
167
|
+
},
|
|
168
|
+
} )
|
|
169
|
+
);
|
|
182
170
|
},
|
|
183
171
|
} ) }
|
|
184
172
|
onSelect={ ( selectedMedia ) => {
|
|
185
173
|
if ( selectedMedia.id && selectedMedia.url ) {
|
|
186
|
-
// Determine mediaType from MIME type, not from object type
|
|
187
|
-
let mediaType = 'image'; // default
|
|
188
|
-
if ( selectedMedia.mime_type ) {
|
|
189
|
-
if (
|
|
190
|
-
selectedMedia.mime_type.startsWith( 'video/' )
|
|
191
|
-
) {
|
|
192
|
-
mediaType = 'video';
|
|
193
|
-
} else if (
|
|
194
|
-
selectedMedia.mime_type.startsWith( 'audio/' )
|
|
195
|
-
) {
|
|
196
|
-
mediaType = 'audio';
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
|
|
200
174
|
// Build new value dynamically based on what's in the mapping
|
|
201
|
-
const newValue = {
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
Object.keys( fieldDef.mapping ).forEach(
|
|
206
|
-
( key ) => {
|
|
207
|
-
if ( key === 'id' ) {
|
|
208
|
-
newValue[ key ] = selectedMedia.id;
|
|
209
|
-
} else if (
|
|
210
|
-
key === 'src' ||
|
|
211
|
-
key === 'url'
|
|
212
|
-
) {
|
|
213
|
-
newValue[ key ] = selectedMedia.url;
|
|
214
|
-
} else if ( key === 'type' ) {
|
|
215
|
-
newValue[ key ] = mediaType;
|
|
216
|
-
} else if (
|
|
217
|
-
key === 'link' &&
|
|
218
|
-
selectedMedia.link
|
|
219
|
-
) {
|
|
220
|
-
newValue[ key ] = selectedMedia.link;
|
|
221
|
-
} else if (
|
|
222
|
-
key === 'caption' &&
|
|
223
|
-
! value?.caption &&
|
|
224
|
-
selectedMedia.caption
|
|
225
|
-
) {
|
|
226
|
-
newValue[ key ] = selectedMedia.caption;
|
|
227
|
-
} else if (
|
|
228
|
-
key === 'alt' &&
|
|
229
|
-
! value?.alt &&
|
|
230
|
-
selectedMedia.alt
|
|
231
|
-
) {
|
|
232
|
-
newValue[ key ] = selectedMedia.alt;
|
|
233
|
-
} else if (
|
|
234
|
-
key === 'poster' &&
|
|
235
|
-
selectedMedia.poster
|
|
236
|
-
) {
|
|
237
|
-
newValue[ key ] = selectedMedia.poster;
|
|
238
|
-
}
|
|
239
|
-
}
|
|
240
|
-
);
|
|
241
|
-
}
|
|
175
|
+
const newValue = {
|
|
176
|
+
...selectedMedia,
|
|
177
|
+
mediaType: selectedMedia.media_type,
|
|
178
|
+
};
|
|
242
179
|
|
|
243
180
|
// Turn off featured image when manually selecting media
|
|
244
181
|
if ( hasFeaturedImageSupport ) {
|
|
245
182
|
newValue.featuredImage = false;
|
|
246
183
|
}
|
|
247
184
|
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
185
|
+
onChange(
|
|
186
|
+
field.setValue( {
|
|
187
|
+
item: data,
|
|
188
|
+
value: newValue,
|
|
189
|
+
} )
|
|
190
|
+
);
|
|
251
191
|
}
|
|
252
192
|
} }
|
|
253
193
|
renderToggle={ ( buttonProps ) => (
|
|
@@ -268,6 +208,7 @@ export default function Media( { data, field, onChange, config = {} } ) {
|
|
|
268
208
|
attachment={ attachment }
|
|
269
209
|
field={ field }
|
|
270
210
|
data={ data }
|
|
211
|
+
config={ config }
|
|
271
212
|
/>
|
|
272
213
|
<span className="block-editor-content-only-controls__media-title">
|
|
273
214
|
{
|
|
@@ -33,10 +33,6 @@ export default function RichTextControl( {
|
|
|
33
33
|
const attrValue = field.getValue( { item: data } );
|
|
34
34
|
const fieldConfig = field.config || {};
|
|
35
35
|
const { clientId } = config;
|
|
36
|
-
const updateAttributes = ( html ) => {
|
|
37
|
-
const mappedChanges = field.setValue( { item: data, value: html } );
|
|
38
|
-
onChange( mappedChanges );
|
|
39
|
-
};
|
|
40
36
|
const [ selection, setSelection ] = useState( {
|
|
41
37
|
start: undefined,
|
|
42
38
|
end: undefined,
|
|
@@ -107,7 +103,7 @@ export default function RichTextControl( {
|
|
|
107
103
|
} = useRichText( {
|
|
108
104
|
value: attrValue,
|
|
109
105
|
onChange( html, { __unstableFormats, __unstableText } ) {
|
|
110
|
-
|
|
106
|
+
onChange( field.setValue( { item: data, value: html } ) );
|
|
111
107
|
Object.values( changeHandlers ).forEach( ( changeHandler ) => {
|
|
112
108
|
changeHandler( __unstableFormats, __unstableText );
|
|
113
109
|
} );
|