@wordpress/block-editor 10.0.0 → 10.0.1
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/autocomplete/index.js +2 -2
- package/build/components/autocomplete/index.js.map +1 -1
- package/build/components/block-inspector/index.js +1 -1
- package/build/components/block-inspector/index.js.map +1 -1
- package/build/components/block-list/block-list-compact.native.js +2 -1
- package/build/components/block-list/block-list-compact.native.js.map +1 -1
- package/build/components/block-list/block.js +1 -1
- package/build/components/block-list/block.js.map +1 -1
- package/build/components/block-lock/use-block-lock.js +1 -1
- package/build/components/block-lock/use-block-lock.js.map +1 -1
- package/build/components/block-popover/inbetween.js +37 -49
- package/build/components/block-popover/inbetween.js.map +1 -1
- package/build/components/block-popover/index.js +28 -5
- package/build/components/block-popover/index.js.map +1 -1
- package/build/components/border-radius-control/linked-button.js +5 -6
- package/build/components/border-radius-control/linked-button.js.map +1 -1
- package/build/components/convert-to-group-buttons/toolbar.js +8 -3
- package/build/components/convert-to-group-buttons/toolbar.js.map +1 -1
- package/build/components/inner-blocks/index.js +7 -1
- package/build/components/inner-blocks/index.js.map +1 -1
- package/build/components/inner-blocks/use-inner-block-template-sync.js +27 -16
- package/build/components/inner-blocks/use-inner-block-template-sync.js.map +1 -1
- package/build/components/inner-blocks/use-nested-settings-update.js +28 -4
- package/build/components/inner-blocks/use-nested-settings-update.js.map +1 -1
- package/build/components/list-view/branch.js +1 -1
- package/build/components/list-view/branch.js.map +1 -1
- package/build/components/list-view/drop-indicator.js +30 -28
- package/build/components/list-view/drop-indicator.js.map +1 -1
- package/build/components/rich-text/format-toolbar-container.js +9 -9
- package/build/components/rich-text/format-toolbar-container.js.map +1 -1
- package/build/components/rich-text/index.js +4 -2
- package/build/components/rich-text/index.js.map +1 -1
- package/build/components/spacing-sizes-control/linked-button.js +2 -3
- package/build/components/spacing-sizes-control/linked-button.js.map +1 -1
- package/build/components/spacing-sizes-control/utils.js +1 -4
- package/build/components/spacing-sizes-control/utils.js.map +1 -1
- package/build/components/text-decoration-control/index.js +19 -15
- package/build/components/text-decoration-control/index.js.map +1 -1
- package/build/components/text-transform-control/index.js +25 -17
- package/build/components/text-transform-control/index.js.map +1 -1
- package/build/components/url-popover/image-url-input-ui.js +6 -4
- package/build/components/url-popover/image-url-input-ui.js.map +1 -1
- package/build/components/use-block-drop-zone/index.js +1 -1
- package/build/components/use-block-drop-zone/index.js.map +1 -1
- package/build/hooks/content-lock-ui.js +3 -3
- package/build/hooks/content-lock-ui.js.map +1 -1
- package/build/hooks/typography.js +10 -11
- package/build/hooks/typography.js.map +1 -1
- package/build/layouts/constrained.js +1 -1
- package/build/layouts/constrained.js.map +1 -1
- package/build/store/reducer.js +4 -1
- package/build/store/reducer.js.map +1 -1
- package/build/store/selectors.js +2 -2
- package/build/store/selectors.js.map +1 -1
- package/build-module/components/autocomplete/index.js +2 -2
- package/build-module/components/autocomplete/index.js.map +1 -1
- package/build-module/components/block-inspector/index.js +1 -1
- package/build-module/components/block-inspector/index.js.map +1 -1
- package/build-module/components/block-list/block-list-compact.native.js +2 -1
- package/build-module/components/block-list/block-list-compact.native.js.map +1 -1
- package/build-module/components/block-list/block.js +1 -1
- package/build-module/components/block-list/block.js.map +1 -1
- package/build-module/components/block-lock/use-block-lock.js +1 -1
- package/build-module/components/block-lock/use-block-lock.js.map +1 -1
- package/build-module/components/block-popover/inbetween.js +38 -50
- package/build-module/components/block-popover/inbetween.js.map +1 -1
- package/build-module/components/block-popover/index.js +28 -5
- package/build-module/components/block-popover/index.js.map +1 -1
- package/build-module/components/border-radius-control/linked-button.js +5 -6
- package/build-module/components/border-radius-control/linked-button.js.map +1 -1
- package/build-module/components/convert-to-group-buttons/toolbar.js +8 -3
- package/build-module/components/convert-to-group-buttons/toolbar.js.map +1 -1
- package/build-module/components/inner-blocks/index.js +7 -1
- package/build-module/components/inner-blocks/index.js.map +1 -1
- package/build-module/components/inner-blocks/use-inner-block-template-sync.js +27 -16
- package/build-module/components/inner-blocks/use-inner-block-template-sync.js.map +1 -1
- package/build-module/components/inner-blocks/use-nested-settings-update.js +28 -4
- package/build-module/components/inner-blocks/use-nested-settings-update.js.map +1 -1
- package/build-module/components/list-view/branch.js +1 -1
- package/build-module/components/list-view/branch.js.map +1 -1
- package/build-module/components/list-view/drop-indicator.js +30 -28
- package/build-module/components/list-view/drop-indicator.js.map +1 -1
- package/build-module/components/rich-text/format-toolbar-container.js +10 -10
- package/build-module/components/rich-text/format-toolbar-container.js.map +1 -1
- package/build-module/components/rich-text/index.js +4 -2
- package/build-module/components/rich-text/index.js.map +1 -1
- package/build-module/components/spacing-sizes-control/linked-button.js +2 -3
- package/build-module/components/spacing-sizes-control/linked-button.js.map +1 -1
- package/build-module/components/spacing-sizes-control/utils.js +1 -4
- package/build-module/components/spacing-sizes-control/utils.js.map +1 -1
- package/build-module/components/text-decoration-control/index.js +21 -16
- package/build-module/components/text-decoration-control/index.js.map +1 -1
- package/build-module/components/text-transform-control/index.js +28 -20
- package/build-module/components/text-transform-control/index.js.map +1 -1
- package/build-module/components/url-popover/image-url-input-ui.js +6 -4
- package/build-module/components/url-popover/image-url-input-ui.js.map +1 -1
- package/build-module/components/use-block-drop-zone/index.js +1 -1
- package/build-module/components/use-block-drop-zone/index.js.map +1 -1
- package/build-module/hooks/content-lock-ui.js +3 -3
- package/build-module/hooks/content-lock-ui.js.map +1 -1
- package/build-module/hooks/typography.js +10 -11
- package/build-module/hooks/typography.js.map +1 -1
- package/build-module/layouts/constrained.js +1 -1
- package/build-module/layouts/constrained.js.map +1 -1
- package/build-module/store/reducer.js +4 -1
- package/build-module/store/reducer.js.map +1 -1
- package/build-module/store/selectors.js +2 -2
- package/build-module/store/selectors.js.map +1 -1
- package/build-style/style-rtl.css +49 -3
- package/build-style/style.css +49 -3
- package/package.json +11 -11
- package/src/components/autocomplete/index.js +2 -5
- package/src/components/block-inspector/index.js +1 -1
- package/src/components/block-list/block-list-compact.native.js +1 -1
- package/src/components/block-list/block.js +1 -1
- package/src/components/block-list/style.scss +22 -3
- package/src/components/block-lock/use-block-lock.js +1 -1
- package/src/components/block-popover/inbetween.js +50 -52
- package/src/components/block-popover/index.js +44 -6
- package/src/components/border-radius-control/linked-button.js +12 -11
- package/src/components/convert-to-group-buttons/toolbar.js +6 -2
- package/src/components/inner-blocks/README.md +2 -2
- package/src/components/inner-blocks/index.js +7 -0
- package/src/components/inner-blocks/use-inner-block-template-sync.js +39 -28
- package/src/components/inner-blocks/use-nested-settings-update.js +30 -3
- package/src/components/list-view/branch.js +1 -1
- package/src/components/list-view/drop-indicator.js +33 -32
- package/src/components/rich-text/format-toolbar-container.js +18 -10
- package/src/components/rich-text/index.js +2 -2
- package/src/components/spacing-sizes-control/linked-button.js +2 -3
- package/src/components/spacing-sizes-control/style.scss +4 -1
- package/src/components/spacing-sizes-control/utils.js +1 -8
- package/src/components/text-decoration-control/index.js +31 -23
- package/src/components/text-decoration-control/style.scss +18 -0
- package/src/components/text-transform-control/index.js +42 -26
- package/src/components/text-transform-control/style.scss +18 -0
- package/src/components/url-popover/image-url-input-ui.js +5 -3
- package/src/components/use-block-drop-zone/index.js +1 -1
- package/src/hooks/content-lock-ui.js +3 -3
- package/src/hooks/typography.js +13 -14
- package/src/layouts/constrained.js +1 -1
- package/src/store/reducer.js +3 -0
- package/src/store/selectors.js +2 -2
- package/src/store/test/selectors.js +4 -4
- package/src/style.scss +2 -0
|
@@ -19,7 +19,7 @@ import { store as blockEditorStore } from '../../store';
|
|
|
19
19
|
* This hook makes sure that a block's inner blocks stay in sync with the given
|
|
20
20
|
* block "template". The template is a block hierarchy to which inner blocks must
|
|
21
21
|
* conform. If the blocks get "out of sync" with the template and the template
|
|
22
|
-
* is meant to be locked (e.g. templateLock = "all" or templateLock = "
|
|
22
|
+
* is meant to be locked (e.g. templateLock = "all" or templateLock = "contentOnly"),
|
|
23
23
|
* then we replace the inner blocks with the correct value after synchronizing it with the template.
|
|
24
24
|
*
|
|
25
25
|
* @param {string} clientId The block client ID.
|
|
@@ -47,42 +47,53 @@ export default function useInnerBlockTemplateSync(
|
|
|
47
47
|
( select ) => select( blockEditorStore ).getBlocks( clientId ),
|
|
48
48
|
[ clientId ]
|
|
49
49
|
);
|
|
50
|
+
const { getBlocks } = useSelect( blockEditorStore );
|
|
50
51
|
|
|
51
52
|
// Maintain a reference to the previous value so we can do a deep equality check.
|
|
52
53
|
const existingTemplate = useRef( null );
|
|
53
54
|
useLayoutEffect( () => {
|
|
54
|
-
//
|
|
55
|
-
//
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
55
|
+
// There's an implicit dependency between useInnerBlockTemplateSync and useNestedSettingsUpdate
|
|
56
|
+
// The former needs to happen after the latter and since the latter is using microtasks to batch updates (performance optimization),
|
|
57
|
+
// we need to schedule this one in a microtask as well.
|
|
58
|
+
// Exemple: If you remove queueMicrotask here, ctrl + click to insert quote block won't close the inserter.
|
|
59
|
+
window.queueMicrotask( () => {
|
|
60
|
+
// Only synchronize innerBlocks with template if innerBlocks are empty
|
|
61
|
+
// or a locking "all" or "contentOnly" exists directly on the block.
|
|
62
|
+
const currentInnerBlocks = getBlocks( clientId );
|
|
63
|
+
const shouldApplyTemplate =
|
|
64
|
+
currentInnerBlocks.length === 0 ||
|
|
65
|
+
templateLock === 'all' ||
|
|
66
|
+
templateLock === 'contentOnly';
|
|
67
|
+
|
|
61
68
|
const hasTemplateChanged = ! isEqual(
|
|
62
69
|
template,
|
|
63
70
|
existingTemplate.current
|
|
64
71
|
);
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
72
|
+
|
|
73
|
+
if ( ! shouldApplyTemplate || ! hasTemplateChanged ) {
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
existingTemplate.current = template;
|
|
78
|
+
const nextBlocks = synchronizeBlocksWithTemplate(
|
|
79
|
+
currentInnerBlocks,
|
|
80
|
+
template
|
|
81
|
+
);
|
|
82
|
+
|
|
83
|
+
if ( ! isEqual( nextBlocks, currentInnerBlocks ) ) {
|
|
84
|
+
replaceInnerBlocks(
|
|
85
|
+
clientId,
|
|
86
|
+
nextBlocks,
|
|
87
|
+
currentInnerBlocks.length === 0 &&
|
|
88
|
+
templateInsertUpdatesSelection &&
|
|
89
|
+
nextBlocks.length !== 0,
|
|
90
|
+
// This ensures the "initialPosition" doesn't change when applying the template
|
|
91
|
+
// If we're supposed to focus the block, we'll focus the first inner block
|
|
92
|
+
// otherwise, we won't apply any auto-focus.
|
|
93
|
+
// This ensures for instance that the focus stays in the inserter when inserting the "buttons" block.
|
|
94
|
+
getSelectedBlocksInitialCaretPosition()
|
|
70
95
|
);
|
|
71
|
-
if ( ! isEqual( nextBlocks, innerBlocks ) ) {
|
|
72
|
-
replaceInnerBlocks(
|
|
73
|
-
clientId,
|
|
74
|
-
nextBlocks,
|
|
75
|
-
innerBlocks.length === 0 &&
|
|
76
|
-
templateInsertUpdatesSelection &&
|
|
77
|
-
nextBlocks.length !== 0,
|
|
78
|
-
// This ensures the "initialPosition" doesn't change when applying the template
|
|
79
|
-
// If we're supposed to focus the block, we'll focus the first inner block
|
|
80
|
-
// otherwise, we won't apply any auto-focus.
|
|
81
|
-
// This ensures for instance that the focus stays in the inserter when inserting the "buttons" block.
|
|
82
|
-
getSelectedBlocksInitialCaretPosition()
|
|
83
|
-
);
|
|
84
|
-
}
|
|
85
96
|
}
|
|
86
|
-
}
|
|
97
|
+
} );
|
|
87
98
|
}, [ innerBlocks, template, templateLock, clientId ] );
|
|
88
99
|
}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* WordPress dependencies
|
|
3
3
|
*/
|
|
4
4
|
import { useLayoutEffect, useMemo } from '@wordpress/element';
|
|
5
|
-
import { useSelect, useDispatch } from '@wordpress/data';
|
|
5
|
+
import { useSelect, useDispatch, useRegistry } from '@wordpress/data';
|
|
6
6
|
import isShallowEqual from '@wordpress/is-shallow-equal';
|
|
7
7
|
|
|
8
8
|
/**
|
|
@@ -13,6 +13,8 @@ import { getLayoutType } from '../../layouts';
|
|
|
13
13
|
|
|
14
14
|
/** @typedef {import('../../selectors').WPDirectInsertBlock } WPDirectInsertBlock */
|
|
15
15
|
|
|
16
|
+
const pendingSettingsUpdates = new WeakMap();
|
|
17
|
+
|
|
16
18
|
/**
|
|
17
19
|
* This hook is a side effect which updates the block-editor store when changes
|
|
18
20
|
* happen to inner block settings. The given props are transformed into a
|
|
@@ -46,6 +48,7 @@ export default function useNestedSettingsUpdate(
|
|
|
46
48
|
layout
|
|
47
49
|
) {
|
|
48
50
|
const { updateBlockListSettings } = useDispatch( blockEditorStore );
|
|
51
|
+
const registry = useRegistry();
|
|
49
52
|
|
|
50
53
|
const { blockListSettings, parentLock } = useSelect(
|
|
51
54
|
( select ) => {
|
|
@@ -69,7 +72,7 @@ export default function useNestedSettingsUpdate(
|
|
|
69
72
|
const newSettings = {
|
|
70
73
|
allowedBlocks: _allowedBlocks,
|
|
71
74
|
templateLock:
|
|
72
|
-
templateLock === undefined || parentLock === '
|
|
75
|
+
templateLock === undefined || parentLock === 'contentOnly'
|
|
73
76
|
? parentLock
|
|
74
77
|
: templateLock,
|
|
75
78
|
};
|
|
@@ -98,7 +101,30 @@ export default function useNestedSettingsUpdate(
|
|
|
98
101
|
}
|
|
99
102
|
|
|
100
103
|
if ( ! isShallowEqual( blockListSettings, newSettings ) ) {
|
|
101
|
-
|
|
104
|
+
// Batch updates to block list settings to avoid triggering cascading renders
|
|
105
|
+
// for each container block included in a tree and optimize initial render.
|
|
106
|
+
// To avoid triggering updateBlockListSettings for each container block
|
|
107
|
+
// causing X re-renderings for X container blocks,
|
|
108
|
+
// we batch all the updatedBlockListSettings in a single "data" batch
|
|
109
|
+
// which results in a single re-render.
|
|
110
|
+
if ( ! pendingSettingsUpdates.get( registry ) ) {
|
|
111
|
+
pendingSettingsUpdates.set( registry, [] );
|
|
112
|
+
}
|
|
113
|
+
pendingSettingsUpdates
|
|
114
|
+
.get( registry )
|
|
115
|
+
.push( [ clientId, newSettings ] );
|
|
116
|
+
window.queueMicrotask( () => {
|
|
117
|
+
if ( pendingSettingsUpdates.get( registry )?.length ) {
|
|
118
|
+
registry.batch( () => {
|
|
119
|
+
pendingSettingsUpdates
|
|
120
|
+
.get( registry )
|
|
121
|
+
.forEach( ( args ) => {
|
|
122
|
+
updateBlockListSettings( ...args );
|
|
123
|
+
} );
|
|
124
|
+
pendingSettingsUpdates.set( registry, [] );
|
|
125
|
+
} );
|
|
126
|
+
}
|
|
127
|
+
} );
|
|
102
128
|
}
|
|
103
129
|
}, [
|
|
104
130
|
clientId,
|
|
@@ -112,5 +138,6 @@ export default function useNestedSettingsUpdate(
|
|
|
112
138
|
orientation,
|
|
113
139
|
updateBlockListSettings,
|
|
114
140
|
layout,
|
|
141
|
+
registry,
|
|
115
142
|
] );
|
|
116
143
|
}
|
|
@@ -68,40 +68,41 @@ export default function ListViewDropIndicator( {
|
|
|
68
68
|
};
|
|
69
69
|
}, [ getDropIndicatorIndent, targetElement ] );
|
|
70
70
|
|
|
71
|
-
const
|
|
72
|
-
|
|
73
|
-
|
|
71
|
+
const popoverAnchor = useMemo( () => {
|
|
72
|
+
const isValidDropPosition =
|
|
73
|
+
dropPosition === 'top' ||
|
|
74
|
+
dropPosition === 'bottom' ||
|
|
75
|
+
dropPosition === 'inside';
|
|
76
|
+
if ( ! targetElement || ! isValidDropPosition ) {
|
|
77
|
+
return undefined;
|
|
74
78
|
}
|
|
75
79
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
80
|
+
return {
|
|
81
|
+
ownerDocument: targetElement.ownerDocument,
|
|
82
|
+
getBoundingClientRect() {
|
|
83
|
+
const rect = targetElement.getBoundingClientRect();
|
|
84
|
+
const indent = getDropIndicatorIndent();
|
|
85
|
+
|
|
86
|
+
const left = rect.left + indent;
|
|
87
|
+
const right = rect.right;
|
|
88
|
+
let top = 0;
|
|
89
|
+
let bottom = 0;
|
|
90
|
+
|
|
91
|
+
if ( dropPosition === 'top' ) {
|
|
92
|
+
top = rect.top;
|
|
93
|
+
bottom = rect.top;
|
|
94
|
+
} else {
|
|
95
|
+
// `dropPosition` is either `bottom` or `inside`
|
|
96
|
+
top = rect.bottom;
|
|
97
|
+
bottom = rect.bottom;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
const width = right - left;
|
|
101
|
+
const height = bottom - top;
|
|
102
|
+
|
|
103
|
+
return new window.DOMRect( left, top, width, height );
|
|
104
|
+
},
|
|
86
105
|
};
|
|
87
|
-
|
|
88
|
-
if ( dropPosition === 'top' ) {
|
|
89
|
-
return {
|
|
90
|
-
...anchorRect,
|
|
91
|
-
top: rect.top,
|
|
92
|
-
bottom: rect.top,
|
|
93
|
-
};
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
if ( dropPosition === 'bottom' || dropPosition === 'inside' ) {
|
|
97
|
-
return {
|
|
98
|
-
...anchorRect,
|
|
99
|
-
top: rect.bottom,
|
|
100
|
-
bottom: rect.bottom,
|
|
101
|
-
};
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
return {};
|
|
105
106
|
}, [ targetElement, dropPosition, getDropIndicatorIndent ] );
|
|
106
107
|
|
|
107
108
|
if ( ! targetElement ) {
|
|
@@ -111,7 +112,7 @@ export default function ListViewDropIndicator( {
|
|
|
111
112
|
return (
|
|
112
113
|
<Popover
|
|
113
114
|
animate={ false }
|
|
114
|
-
|
|
115
|
+
anchor={ popoverAnchor }
|
|
115
116
|
focusOnMount={ false }
|
|
116
117
|
className="block-editor-list-view-drop-indicator"
|
|
117
118
|
>
|
|
@@ -6,7 +6,7 @@ import { useSelect } from '@wordpress/data';
|
|
|
6
6
|
import {
|
|
7
7
|
isCollapsed,
|
|
8
8
|
getActiveFormats,
|
|
9
|
-
|
|
9
|
+
useAnchor,
|
|
10
10
|
store as richTextStore,
|
|
11
11
|
} from '@wordpress/rich-text';
|
|
12
12
|
|
|
@@ -17,28 +17,32 @@ import BlockControls from '../block-controls';
|
|
|
17
17
|
import FormatToolbar from './format-toolbar';
|
|
18
18
|
import { store as blockEditorStore } from '../../store';
|
|
19
19
|
|
|
20
|
-
function InlineSelectionToolbar( {
|
|
20
|
+
function InlineSelectionToolbar( {
|
|
21
|
+
value,
|
|
22
|
+
editableContentElement,
|
|
23
|
+
activeFormats,
|
|
24
|
+
} ) {
|
|
21
25
|
const lastFormat = activeFormats[ activeFormats.length - 1 ];
|
|
22
26
|
const lastFormatType = lastFormat?.type;
|
|
23
27
|
const settings = useSelect(
|
|
24
28
|
( select ) => select( richTextStore ).getFormatType( lastFormatType ),
|
|
25
29
|
[ lastFormatType ]
|
|
26
30
|
);
|
|
27
|
-
const
|
|
28
|
-
|
|
31
|
+
const popoverAnchor = useAnchor( {
|
|
32
|
+
editableContentElement,
|
|
29
33
|
value,
|
|
30
34
|
settings,
|
|
31
35
|
} );
|
|
32
36
|
|
|
33
|
-
return <InlineToolbar
|
|
37
|
+
return <InlineToolbar popoverAnchor={ popoverAnchor } />;
|
|
34
38
|
}
|
|
35
39
|
|
|
36
|
-
function InlineToolbar( {
|
|
40
|
+
function InlineToolbar( { popoverAnchor } ) {
|
|
37
41
|
return (
|
|
38
42
|
<Popover
|
|
39
43
|
position="top center"
|
|
40
44
|
focusOnMount={ false }
|
|
41
|
-
|
|
45
|
+
anchor={ popoverAnchor }
|
|
42
46
|
className="block-editor-rich-text__inline-format-toolbar"
|
|
43
47
|
__unstableSlotName="block-toolbar"
|
|
44
48
|
>
|
|
@@ -51,14 +55,18 @@ function InlineToolbar( { anchorRef } ) {
|
|
|
51
55
|
);
|
|
52
56
|
}
|
|
53
57
|
|
|
54
|
-
const FormatToolbarContainer = ( {
|
|
58
|
+
const FormatToolbarContainer = ( {
|
|
59
|
+
inline,
|
|
60
|
+
editableContentElement,
|
|
61
|
+
value,
|
|
62
|
+
} ) => {
|
|
55
63
|
const hasInlineToolbar = useSelect(
|
|
56
64
|
( select ) => select( blockEditorStore ).getSettings().hasInlineToolbar,
|
|
57
65
|
[]
|
|
58
66
|
);
|
|
59
67
|
|
|
60
68
|
if ( inline ) {
|
|
61
|
-
return <InlineToolbar
|
|
69
|
+
return <InlineToolbar popoverAnchor={ editableContentElement } />;
|
|
62
70
|
}
|
|
63
71
|
|
|
64
72
|
if ( hasInlineToolbar ) {
|
|
@@ -70,7 +78,7 @@ const FormatToolbarContainer = ( { inline, anchorRef, value } ) => {
|
|
|
70
78
|
|
|
71
79
|
return (
|
|
72
80
|
<InlineSelectionToolbar
|
|
73
|
-
|
|
81
|
+
editableContentElement={ editableContentElement }
|
|
74
82
|
value={ value }
|
|
75
83
|
activeFormats={ activeFormats }
|
|
76
84
|
/>
|
|
@@ -328,7 +328,7 @@ function RichTextWrapper(
|
|
|
328
328
|
}
|
|
329
329
|
|
|
330
330
|
function onFocus() {
|
|
331
|
-
anchorRef.current
|
|
331
|
+
anchorRef.current?.focus();
|
|
332
332
|
}
|
|
333
333
|
|
|
334
334
|
const TagName = tagName;
|
|
@@ -354,7 +354,7 @@ function RichTextWrapper(
|
|
|
354
354
|
{ isSelected && hasFormats && (
|
|
355
355
|
<FormatToolbarContainer
|
|
356
356
|
inline={ inlineToolbar }
|
|
357
|
-
|
|
357
|
+
editableContentElement={ anchorRef.current }
|
|
358
358
|
value={ value }
|
|
359
359
|
/>
|
|
360
360
|
) }
|
|
@@ -6,16 +6,15 @@ import { __ } from '@wordpress/i18n';
|
|
|
6
6
|
import { Button, Tooltip } from '@wordpress/components';
|
|
7
7
|
|
|
8
8
|
export default function LinkedButton( { isLinked, onClick } ) {
|
|
9
|
-
const label = isLinked ? __( 'Unlink
|
|
9
|
+
const label = isLinked ? __( 'Unlink sides' ) : __( 'Link sides' );
|
|
10
10
|
|
|
11
11
|
return (
|
|
12
12
|
<Tooltip text={ label }>
|
|
13
13
|
<span className="component-spacing-sizes-control__linked-button">
|
|
14
14
|
<Button
|
|
15
|
-
variant={ isLinked ? 'primary' : 'secondary' }
|
|
16
15
|
isSmall
|
|
17
16
|
icon={ isLinked ? link : linkOff }
|
|
18
|
-
iconSize={
|
|
17
|
+
iconSize={ 24 }
|
|
19
18
|
aria-label={ label }
|
|
20
19
|
onClick={ onClick }
|
|
21
20
|
/>
|
|
@@ -46,10 +46,13 @@
|
|
|
46
46
|
grid-column: 2 / 2;
|
|
47
47
|
grid-row: 1 / 1;
|
|
48
48
|
justify-self: end;
|
|
49
|
-
margin-right: $grid-unit-05;
|
|
50
49
|
padding: 0;
|
|
51
50
|
}
|
|
52
51
|
|
|
52
|
+
.component-spacing-sizes-control__linked-button ~ .components-spacing-sizes-control__custom-toggle-all {
|
|
53
|
+
margin-right: $grid-unit-05;
|
|
54
|
+
}
|
|
55
|
+
|
|
53
56
|
.components-spacing-sizes-control__custom-toggle-single {
|
|
54
57
|
grid-column: 3 / 3;
|
|
55
58
|
justify-self: end;
|
|
@@ -211,12 +211,5 @@ export function isValuesDefined( values ) {
|
|
|
211
211
|
if ( values === undefined || values === null ) {
|
|
212
212
|
return false;
|
|
213
213
|
}
|
|
214
|
-
return ! isEmpty(
|
|
215
|
-
Object.values( values ).filter(
|
|
216
|
-
// Switching units when input is empty causes values only
|
|
217
|
-
// containing units. This gives false positive on mixed values
|
|
218
|
-
// unless filtered.
|
|
219
|
-
( value ) => !! value && /\d/.test( value )
|
|
220
|
-
)
|
|
221
|
-
);
|
|
214
|
+
return ! isEmpty( Object.values( values ).filter( ( value ) => !! value ) );
|
|
222
215
|
}
|
|
@@ -6,14 +6,16 @@ import classnames from 'classnames';
|
|
|
6
6
|
/**
|
|
7
7
|
* WordPress dependencies
|
|
8
8
|
*/
|
|
9
|
-
import {
|
|
10
|
-
|
|
11
|
-
__experimentalToggleGroupControlOptionIcon as ToggleGroupControlOptionIcon,
|
|
12
|
-
} from '@wordpress/components';
|
|
13
|
-
import { formatStrikethrough, formatUnderline } from '@wordpress/icons';
|
|
9
|
+
import { BaseControl, Button } from '@wordpress/components';
|
|
10
|
+
import { reset, formatStrikethrough, formatUnderline } from '@wordpress/icons';
|
|
14
11
|
import { __ } from '@wordpress/i18n';
|
|
15
12
|
|
|
16
13
|
const TEXT_DECORATIONS = [
|
|
14
|
+
{
|
|
15
|
+
name: __( 'None' ),
|
|
16
|
+
value: 'none',
|
|
17
|
+
icon: reset,
|
|
18
|
+
},
|
|
17
19
|
{
|
|
18
20
|
name: __( 'Underline' ),
|
|
19
21
|
value: 'underline',
|
|
@@ -40,30 +42,36 @@ export default function TextDecorationControl( {
|
|
|
40
42
|
value,
|
|
41
43
|
onChange,
|
|
42
44
|
className,
|
|
43
|
-
...props
|
|
44
45
|
} ) {
|
|
45
46
|
return (
|
|
46
|
-
<
|
|
47
|
-
{ ...props }
|
|
47
|
+
<fieldset
|
|
48
48
|
className={ classnames(
|
|
49
49
|
'block-editor-text-decoration-control',
|
|
50
50
|
className
|
|
51
51
|
) }
|
|
52
|
-
__experimentalIsBorderless
|
|
53
|
-
label={ __( 'Decoration' ) }
|
|
54
|
-
value={ value }
|
|
55
|
-
onChange={ onChange }
|
|
56
52
|
>
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
53
|
+
<BaseControl.VisualLabel as="legend">
|
|
54
|
+
{ __( 'Decoration' ) }
|
|
55
|
+
</BaseControl.VisualLabel>
|
|
56
|
+
<div className="block-editor-text-decoration-control__buttons">
|
|
57
|
+
{ TEXT_DECORATIONS.map( ( textDecoration ) => {
|
|
58
|
+
return (
|
|
59
|
+
<Button
|
|
60
|
+
key={ textDecoration.value }
|
|
61
|
+
icon={ textDecoration.icon }
|
|
62
|
+
label={ textDecoration.name }
|
|
63
|
+
isPressed={ textDecoration.value === value }
|
|
64
|
+
onClick={ () => {
|
|
65
|
+
onChange(
|
|
66
|
+
textDecoration.value === value
|
|
67
|
+
? undefined
|
|
68
|
+
: textDecoration.value
|
|
69
|
+
);
|
|
70
|
+
} }
|
|
71
|
+
/>
|
|
72
|
+
);
|
|
73
|
+
} ) }
|
|
74
|
+
</div>
|
|
75
|
+
</fieldset>
|
|
68
76
|
);
|
|
69
77
|
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
.block-editor-text-decoration-control {
|
|
2
|
+
border: 0;
|
|
3
|
+
margin: 0;
|
|
4
|
+
padding: 0;
|
|
5
|
+
|
|
6
|
+
.block-editor-text-decoration-control__buttons {
|
|
7
|
+
// 4px of padding makes the row 40px high, same as an input.
|
|
8
|
+
padding: $grid-unit-05 0;
|
|
9
|
+
display: flex;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
.components-button.has-icon {
|
|
13
|
+
height: $grid-unit-40;
|
|
14
|
+
margin-right: $grid-unit-05;
|
|
15
|
+
min-width: $grid-unit-40;
|
|
16
|
+
padding: 0;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
@@ -1,21 +1,26 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* External dependencies
|
|
3
3
|
*/
|
|
4
|
+
import classnames from 'classnames';
|
|
5
|
+
|
|
4
6
|
/**
|
|
5
7
|
* WordPress dependencies
|
|
6
8
|
*/
|
|
7
|
-
import {
|
|
8
|
-
__experimentalToggleGroupControl as ToggleGroupControl,
|
|
9
|
-
__experimentalToggleGroupControlOptionIcon as ToggleGroupControlOptionIcon,
|
|
10
|
-
} from '@wordpress/components';
|
|
9
|
+
import { BaseControl, Button } from '@wordpress/components';
|
|
11
10
|
import { __ } from '@wordpress/i18n';
|
|
12
11
|
import {
|
|
12
|
+
reset,
|
|
13
13
|
formatCapitalize,
|
|
14
14
|
formatLowercase,
|
|
15
15
|
formatUppercase,
|
|
16
16
|
} from '@wordpress/icons';
|
|
17
17
|
|
|
18
18
|
const TEXT_TRANSFORMS = [
|
|
19
|
+
{
|
|
20
|
+
name: __( 'None' ),
|
|
21
|
+
value: 'none',
|
|
22
|
+
icon: reset,
|
|
23
|
+
},
|
|
19
24
|
{
|
|
20
25
|
name: __( 'Uppercase' ),
|
|
21
26
|
value: 'uppercase',
|
|
@@ -36,32 +41,43 @@ const TEXT_TRANSFORMS = [
|
|
|
36
41
|
/**
|
|
37
42
|
* Control to facilitate text transform selections.
|
|
38
43
|
*
|
|
39
|
-
* @param {Object} props
|
|
40
|
-
* @param {string} props.
|
|
41
|
-
* @param {
|
|
44
|
+
* @param {Object} props Component props.
|
|
45
|
+
* @param {string} props.className Class name to add to the control.
|
|
46
|
+
* @param {string} props.value Currently selected text transform.
|
|
47
|
+
* @param {Function} props.onChange Handles change in text transform selection.
|
|
42
48
|
*
|
|
43
49
|
* @return {WPElement} Text transform control.
|
|
44
50
|
*/
|
|
45
|
-
export default function TextTransformControl( { value, onChange
|
|
51
|
+
export default function TextTransformControl( { className, value, onChange } ) {
|
|
46
52
|
return (
|
|
47
|
-
<
|
|
48
|
-
{
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
value={ value }
|
|
53
|
-
onChange={ onChange }
|
|
53
|
+
<fieldset
|
|
54
|
+
className={ classnames(
|
|
55
|
+
'block-editor-text-transform-control',
|
|
56
|
+
className
|
|
57
|
+
) }
|
|
54
58
|
>
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
59
|
+
<BaseControl.VisualLabel as="legend">
|
|
60
|
+
{ __( 'Letter case' ) }
|
|
61
|
+
</BaseControl.VisualLabel>
|
|
62
|
+
<div className="block-editor-text-transform-control__buttons">
|
|
63
|
+
{ TEXT_TRANSFORMS.map( ( textTransform ) => {
|
|
64
|
+
return (
|
|
65
|
+
<Button
|
|
66
|
+
key={ textTransform.value }
|
|
67
|
+
icon={ textTransform.icon }
|
|
68
|
+
label={ textTransform.name }
|
|
69
|
+
isPressed={ textTransform.value === value }
|
|
70
|
+
onClick={ () => {
|
|
71
|
+
onChange(
|
|
72
|
+
textTransform.value === value
|
|
73
|
+
? undefined
|
|
74
|
+
: textTransform.value
|
|
75
|
+
);
|
|
76
|
+
} }
|
|
77
|
+
/>
|
|
78
|
+
);
|
|
79
|
+
} ) }
|
|
80
|
+
</div>
|
|
81
|
+
</fieldset>
|
|
66
82
|
);
|
|
67
83
|
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
.block-editor-text-transform-control {
|
|
2
|
+
border: 0;
|
|
3
|
+
margin: 0;
|
|
4
|
+
padding: 0;
|
|
5
|
+
|
|
6
|
+
.block-editor-text-transform-control__buttons {
|
|
7
|
+
// 4px of padding makes the row 40px high, same as an input.
|
|
8
|
+
padding: $grid-unit-05 0;
|
|
9
|
+
display: flex;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
.components-button.has-icon {
|
|
13
|
+
height: $grid-unit-40;
|
|
14
|
+
margin-right: $grid-unit-05;
|
|
15
|
+
min-width: $grid-unit-40;
|
|
16
|
+
padding: 0;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
@@ -51,7 +51,9 @@ const ImageURLInputUI = ( {
|
|
|
51
51
|
rel,
|
|
52
52
|
} ) => {
|
|
53
53
|
const [ isOpen, setIsOpen ] = useState( false );
|
|
54
|
-
|
|
54
|
+
// Use internal state instead of a ref to make sure that the component
|
|
55
|
+
// re-renders when the popover's anchor updates.
|
|
56
|
+
const [ popoverAnchor, setPopoverAnchor ] = useState( null );
|
|
55
57
|
const openLinkUI = useCallback( () => {
|
|
56
58
|
setIsOpen( true );
|
|
57
59
|
} );
|
|
@@ -246,11 +248,11 @@ const ImageURLInputUI = ( {
|
|
|
246
248
|
label={ url ? __( 'Edit link' ) : __( 'Insert link' ) }
|
|
247
249
|
aria-expanded={ isOpen }
|
|
248
250
|
onClick={ openLinkUI }
|
|
249
|
-
ref={
|
|
251
|
+
ref={ setPopoverAnchor }
|
|
250
252
|
/>
|
|
251
253
|
{ isOpen && (
|
|
252
254
|
<URLPopover
|
|
253
|
-
|
|
255
|
+
anchor={ popoverAnchor }
|
|
254
256
|
onFocusOutside={ onFocusOutside() }
|
|
255
257
|
onClose={ closeLinkUI }
|
|
256
258
|
renderSettings={ () => advancedOptions }
|
|
@@ -101,7 +101,7 @@ export default function useBlockDropZone( {
|
|
|
101
101
|
} = select( blockEditorStore );
|
|
102
102
|
const templateLock = getTemplateLock( targetRootClientId );
|
|
103
103
|
return (
|
|
104
|
-
[ 'all', '
|
|
104
|
+
[ 'all', 'contentOnly' ].some(
|
|
105
105
|
( lock ) => lock === templateLock
|
|
106
106
|
) ||
|
|
107
107
|
__unstableHasActiveBlockOverlayActive( targetRootClientId ) ||
|
|
@@ -72,7 +72,7 @@ export const withBlockControls = createHigherOrderComponent(
|
|
|
72
72
|
__unstableSetTemporarilyEditingAsBlocks,
|
|
73
73
|
} = useDispatch( blockEditorStore );
|
|
74
74
|
const isContentLocked =
|
|
75
|
-
! isLockedByParent && templateLock === '
|
|
75
|
+
! isLockedByParent && templateLock === 'contentOnly';
|
|
76
76
|
const {
|
|
77
77
|
__unstableMarkNextChangeAsNotPersistent,
|
|
78
78
|
updateBlockAttributes,
|
|
@@ -81,11 +81,11 @@ export const withBlockControls = createHigherOrderComponent(
|
|
|
81
81
|
const stopEditingAsBlock = useCallback( () => {
|
|
82
82
|
__unstableMarkNextChangeAsNotPersistent();
|
|
83
83
|
updateBlockAttributes( props.clientId, {
|
|
84
|
-
templateLock: '
|
|
84
|
+
templateLock: 'contentOnly',
|
|
85
85
|
} );
|
|
86
86
|
updateBlockListSettings( props.clientId, {
|
|
87
87
|
...getBlockListSettings( props.clientId ),
|
|
88
|
-
templateLock: '
|
|
88
|
+
templateLock: 'contentOnly',
|
|
89
89
|
} );
|
|
90
90
|
updateSettings( { focusMode: focusModeToRevert.current } );
|
|
91
91
|
__unstableSetTemporarilyEditingAsBlocks();
|