@wordpress/block-editor 15.12.0 → 15.12.2-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/CHANGELOG.md +6 -0
- package/build/components/block-allowed-blocks/modal.cjs +1 -1
- package/build/components/block-allowed-blocks/modal.cjs.map +2 -2
- package/build/components/block-inspector/index.cjs +9 -9
- package/build/components/block-inspector/index.cjs.map +3 -3
- package/build/components/block-removal-warning-modal/index.cjs +30 -5
- package/build/components/block-removal-warning-modal/index.cjs.map +3 -3
- package/build/components/block-visibility/use-block-visibility.cjs +14 -29
- package/build/components/block-visibility/use-block-visibility.cjs.map +2 -2
- package/build/components/global-styles/hooks.cjs +7 -0
- package/build/components/global-styles/hooks.cjs.map +2 -2
- package/build/components/global-styles/typography-panel.cjs +71 -3
- package/build/components/global-styles/typography-panel.cjs.map +3 -3
- package/build/components/grid/grid-visualizer.cjs +49 -13
- package/build/components/grid/grid-visualizer.cjs.map +2 -2
- package/build/components/iframe/index.cjs +3 -1
- package/build/components/iframe/index.cjs.map +2 -2
- package/build/components/iframe/use-scale-canvas.cjs +1 -0
- package/build/components/iframe/use-scale-canvas.cjs.map +2 -2
- package/build/components/inspector-controls/last-item.cjs +41 -0
- package/build/components/inspector-controls/last-item.cjs.map +7 -0
- package/build/components/inspector-controls-tabs/styles-tab.cjs +3 -3
- package/build/components/inspector-controls-tabs/styles-tab.cjs.map +2 -2
- package/build/components/link-control/index.cjs +73 -2
- package/build/components/link-control/index.cjs.map +3 -3
- package/build/components/link-control/is-url-like.cjs +15 -3
- package/build/components/link-control/is-url-like.cjs.map +2 -2
- package/build/components/link-control/search-input.cjs +4 -1
- package/build/components/link-control/search-input.cjs.map +2 -2
- package/build/components/link-control/use-search-handler.cjs +1 -1
- package/build/components/link-control/use-search-handler.cjs.map +2 -2
- package/build/components/provider/use-block-sync.cjs +60 -8
- package/build/components/provider/use-block-sync.cjs.map +2 -2
- package/build/components/text-indent-control/index.cjs +121 -0
- package/build/components/text-indent-control/index.cjs.map +7 -0
- package/build/components/url-input/index.cjs +22 -2
- package/build/components/url-input/index.cjs.map +3 -3
- package/build/components/url-popover/image-url-input-ui.cjs +1 -1
- package/build/components/url-popover/image-url-input-ui.cjs.map +2 -2
- package/build/components/writing-flow/use-arrow-nav.cjs +0 -3
- package/build/components/writing-flow/use-arrow-nav.cjs.map +2 -2
- package/build/hooks/anchor.cjs +1 -1
- package/build/hooks/anchor.cjs.map +1 -1
- package/build/hooks/aria-label.cjs +2 -1
- package/build/hooks/aria-label.cjs.map +2 -2
- package/build/hooks/grid-visualizer.cjs +59 -6
- package/build/hooks/grid-visualizer.cjs.map +3 -3
- package/build/hooks/layout-child.cjs +47 -6
- package/build/hooks/layout-child.cjs.map +3 -3
- package/build/hooks/typography.cjs +2 -0
- package/build/hooks/typography.cjs.map +2 -2
- package/build/hooks/utils.cjs +4 -0
- package/build/hooks/utils.cjs.map +2 -2
- package/build/private-apis.cjs +2 -0
- package/build/private-apis.cjs.map +3 -3
- package/build/store/actions.cjs +2 -2
- package/build/store/actions.cjs.map +2 -2
- package/build-module/components/block-allowed-blocks/modal.mjs +2 -2
- package/build-module/components/block-allowed-blocks/modal.mjs.map +2 -2
- package/build-module/components/block-inspector/index.mjs +10 -9
- package/build-module/components/block-inspector/index.mjs.map +2 -2
- package/build-module/components/block-removal-warning-modal/index.mjs +34 -7
- package/build-module/components/block-removal-warning-modal/index.mjs.map +2 -2
- package/build-module/components/block-visibility/use-block-visibility.mjs +14 -29
- package/build-module/components/block-visibility/use-block-visibility.mjs.map +2 -2
- package/build-module/components/global-styles/hooks.mjs +7 -0
- package/build-module/components/global-styles/hooks.mjs.map +2 -2
- package/build-module/components/global-styles/typography-panel.mjs +73 -4
- package/build-module/components/global-styles/typography-panel.mjs.map +2 -2
- package/build-module/components/grid/grid-visualizer.mjs +50 -14
- package/build-module/components/grid/grid-visualizer.mjs.map +2 -2
- package/build-module/components/iframe/index.mjs +9 -2
- package/build-module/components/iframe/index.mjs.map +2 -2
- package/build-module/components/iframe/use-scale-canvas.mjs +1 -0
- package/build-module/components/iframe/use-scale-canvas.mjs.map +2 -2
- package/build-module/components/inspector-controls/last-item.mjs +23 -0
- package/build-module/components/inspector-controls/last-item.mjs.map +7 -0
- package/build-module/components/inspector-controls-tabs/styles-tab.mjs +3 -3
- package/build-module/components/inspector-controls-tabs/styles-tab.mjs.map +2 -2
- package/build-module/components/link-control/index.mjs +74 -3
- package/build-module/components/link-control/index.mjs.map +2 -2
- package/build-module/components/link-control/is-url-like.mjs +10 -3
- package/build-module/components/link-control/is-url-like.mjs.map +2 -2
- package/build-module/components/link-control/search-input.mjs +4 -1
- package/build-module/components/link-control/search-input.mjs.map +2 -2
- package/build-module/components/link-control/use-search-handler.mjs +2 -2
- package/build-module/components/link-control/use-search-handler.mjs.map +2 -2
- package/build-module/components/provider/use-block-sync.mjs +60 -8
- package/build-module/components/provider/use-block-sync.mjs.map +2 -2
- package/build-module/components/text-indent-control/index.mjs +110 -0
- package/build-module/components/text-indent-control/index.mjs.map +7 -0
- package/build-module/components/url-input/index.mjs +24 -4
- package/build-module/components/url-input/index.mjs.map +2 -2
- package/build-module/components/url-popover/image-url-input-ui.mjs +2 -2
- package/build-module/components/url-popover/image-url-input-ui.mjs.map +2 -2
- package/build-module/components/writing-flow/use-arrow-nav.mjs +0 -3
- package/build-module/components/writing-flow/use-arrow-nav.mjs.map +2 -2
- package/build-module/hooks/anchor.mjs +1 -1
- package/build-module/hooks/anchor.mjs.map +1 -1
- package/build-module/hooks/aria-label.mjs +2 -1
- package/build-module/hooks/aria-label.mjs.map +2 -2
- package/build-module/hooks/grid-visualizer.mjs +37 -6
- package/build-module/hooks/grid-visualizer.mjs.map +2 -2
- package/build-module/hooks/layout-child.mjs +37 -6
- package/build-module/hooks/layout-child.mjs.map +2 -2
- package/build-module/hooks/typography.mjs +2 -0
- package/build-module/hooks/typography.mjs.map +2 -2
- package/build-module/hooks/utils.mjs +4 -0
- package/build-module/hooks/utils.mjs.map +2 -2
- package/build-module/private-apis.mjs +2 -0
- package/build-module/private-apis.mjs.map +2 -2
- package/build-module/store/actions.mjs +2 -2
- package/build-module/store/actions.mjs.map +2 -2
- package/package.json +39 -39
- package/src/components/block-allowed-blocks/modal.js +2 -2
- package/src/components/block-inspector/index.js +19 -17
- package/src/components/block-removal-warning-modal/index.js +55 -19
- package/src/components/block-switcher/block-transformations-menu.native.js +1 -0
- package/src/components/block-toolbar/test/__snapshots__/block-toolbar-menu.native.js.snap +4 -6
- package/src/components/block-toolbar/test/block-toolbar-menu.native.js +2 -2
- package/src/components/block-visibility/use-block-visibility.js +17 -32
- package/src/components/global-styles/hooks.js +10 -0
- package/src/components/global-styles/typography-panel.js +78 -1
- package/src/components/grid/grid-visualizer.js +58 -12
- package/src/components/iframe/index.js +12 -2
- package/src/components/iframe/use-scale-canvas.js +1 -0
- package/src/components/inserter/menu.native.js +1 -0
- package/src/components/inspector-controls/last-item.js +29 -0
- package/src/components/inspector-controls-tabs/styles-tab.js +3 -3
- package/src/components/link-control/index.js +160 -3
- package/src/components/link-control/is-url-like.js +43 -8
- package/src/components/link-control/search-input.js +7 -0
- package/src/components/link-control/test/index.js +260 -0
- package/src/components/link-control/test/is-url-like.js +49 -1
- package/src/components/link-control/use-search-handler.js +2 -2
- package/src/components/provider/test/use-block-sync.js +105 -0
- package/src/components/provider/use-block-sync.js +118 -9
- package/src/components/text-indent-control/index.js +138 -0
- package/src/components/url-input/index.js +21 -2
- package/src/components/url-popover/image-url-input-ui.js +2 -2
- package/src/components/writing-flow/use-arrow-nav.js +0 -4
- package/src/hooks/anchor.js +1 -1
- package/src/hooks/aria-label.js +9 -1
- package/src/hooks/grid-visualizer.js +63 -24
- package/src/hooks/layout-child.js +45 -3
- package/src/hooks/typography.js +2 -0
- package/src/hooks/utils.js +4 -0
- package/src/private-apis.js +2 -0
- package/src/store/actions.js +8 -6
|
@@ -5,6 +5,7 @@ import { __ } from '@wordpress/i18n';
|
|
|
5
5
|
import {
|
|
6
6
|
getBlockType,
|
|
7
7
|
getUnregisteredTypeHandlerName,
|
|
8
|
+
hasBlockSupport,
|
|
8
9
|
store as blocksStore,
|
|
9
10
|
} from '@wordpress/blocks';
|
|
10
11
|
import { __unstableMotion as motion } from '@wordpress/components';
|
|
@@ -24,6 +25,7 @@ import BlockStyles from '../block-styles';
|
|
|
24
25
|
import { default as InspectorControls } from '../inspector-controls';
|
|
25
26
|
import { default as InspectorControlsTabs } from '../inspector-controls-tabs';
|
|
26
27
|
import useInspectorControlsTabs from '../inspector-controls-tabs/use-inspector-controls-tabs';
|
|
28
|
+
import InspectorControlsLastItem from '../inspector-controls/last-item';
|
|
27
29
|
import AdvancedControls from '../inspector-controls-tabs/advanced-controls-panel';
|
|
28
30
|
import PositionControls from '../inspector-controls-tabs/position-controls-panel';
|
|
29
31
|
import useBlockInspectorAnimationSettings from './useBlockInspectorAnimationSettings';
|
|
@@ -145,30 +147,29 @@ function BlockInspector() {
|
|
|
145
147
|
renderedBlockClientId
|
|
146
148
|
);
|
|
147
149
|
|
|
148
|
-
//
|
|
149
|
-
//
|
|
150
|
-
|
|
151
|
-
// This prevents a poor UX where all Nav block sub-items are shown
|
|
152
|
-
// when the parent block is in contentOnly mode.
|
|
153
|
-
// Build a Set of all navigation block descendants for efficient lookup
|
|
154
|
-
const navigationDescendants = new Set();
|
|
150
|
+
// Exclude items from the content tab that are already present in the
|
|
151
|
+
// List View tab.
|
|
152
|
+
const listViewDescendants = new Set();
|
|
155
153
|
descendants.forEach( ( clientId ) => {
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
154
|
+
const blockName = getBlockName( clientId );
|
|
155
|
+
// Navigation block doesn't have List View block support, but
|
|
156
|
+
// it does have a custom implementation that is shown within
|
|
157
|
+
// patterns, so it's included in this condition.
|
|
158
|
+
if (
|
|
159
|
+
blockName === 'core/navigation' ||
|
|
160
|
+
hasBlockSupport( blockName, 'listView' )
|
|
161
|
+
) {
|
|
162
|
+
const listViewChildren =
|
|
163
|
+
getClientIdsOfDescendants( clientId );
|
|
164
|
+
listViewChildren.forEach( ( childId ) =>
|
|
165
|
+
listViewDescendants.add( childId )
|
|
160
166
|
);
|
|
161
167
|
}
|
|
162
168
|
} );
|
|
163
169
|
|
|
164
170
|
return descendants.filter( ( current ) => {
|
|
165
|
-
// Exclude navigation block children
|
|
166
|
-
if ( navigationDescendants.has( current ) ) {
|
|
167
|
-
return false;
|
|
168
|
-
}
|
|
169
|
-
|
|
170
171
|
return (
|
|
171
|
-
|
|
172
|
+
! listViewDescendants.has( current ) &&
|
|
172
173
|
getBlockEditingMode( current ) === 'contentOnly'
|
|
173
174
|
);
|
|
174
175
|
} );
|
|
@@ -369,6 +370,7 @@ const BlockInspectorSingleBlock = ( {
|
|
|
369
370
|
) }
|
|
370
371
|
</>
|
|
371
372
|
) }
|
|
373
|
+
<InspectorControlsLastItem.Slot />
|
|
372
374
|
<SkipToSelectedBlock key="back" />
|
|
373
375
|
</div>
|
|
374
376
|
);
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* WordPress dependencies
|
|
3
3
|
*/
|
|
4
|
-
import { useEffect } from '@wordpress/element';
|
|
4
|
+
import { useEffect, useState } from '@wordpress/element';
|
|
5
5
|
import { useDispatch, useSelect } from '@wordpress/data';
|
|
6
6
|
import {
|
|
7
7
|
Modal,
|
|
8
8
|
Button,
|
|
9
|
+
CheckboxControl,
|
|
9
10
|
__experimentalHStack as HStack,
|
|
11
|
+
__experimentalVStack as VStack,
|
|
10
12
|
} from '@wordpress/components';
|
|
11
13
|
import { __ } from '@wordpress/i18n';
|
|
12
14
|
|
|
@@ -17,6 +19,7 @@ import { store as blockEditorStore } from '../../store';
|
|
|
17
19
|
import { unlock } from '../../lock-unlock';
|
|
18
20
|
|
|
19
21
|
export function BlockRemovalWarningModal( { rules } ) {
|
|
22
|
+
const [ confirmed, setConfirmed ] = useState( false );
|
|
20
23
|
const { clientIds, selectPrevious, message } = useSelect( ( select ) =>
|
|
21
24
|
unlock( select( blockEditorStore ) ).getRemovalPromptData()
|
|
22
25
|
);
|
|
@@ -36,10 +39,20 @@ export function BlockRemovalWarningModal( { rules } ) {
|
|
|
36
39
|
};
|
|
37
40
|
}, [ rules, setBlockRemovalRules ] );
|
|
38
41
|
|
|
42
|
+
// Reset confirmed state when modal opens with new content.
|
|
43
|
+
useEffect( () => {
|
|
44
|
+
setConfirmed( false );
|
|
45
|
+
}, [ clientIds ] );
|
|
46
|
+
|
|
39
47
|
if ( ! message ) {
|
|
40
48
|
return;
|
|
41
49
|
}
|
|
42
50
|
|
|
51
|
+
const isStructured = typeof message === 'object' && message !== null;
|
|
52
|
+
const description = isStructured ? message.description : message;
|
|
53
|
+
const requireConfirmation = isStructured && message.requireConfirmation;
|
|
54
|
+
const isRemoveDisabled = requireConfirmation && ! confirmed;
|
|
55
|
+
|
|
43
56
|
const onConfirmRemoval = () => {
|
|
44
57
|
privateRemoveBlocks( clientIds, selectPrevious, /* force */ true );
|
|
45
58
|
clearBlockRemovalPrompt();
|
|
@@ -47,27 +60,50 @@ export function BlockRemovalWarningModal( { rules } ) {
|
|
|
47
60
|
|
|
48
61
|
return (
|
|
49
62
|
<Modal
|
|
50
|
-
title={ __( '
|
|
63
|
+
title={ __( 'Confirm deletion' ) }
|
|
51
64
|
onRequestClose={ clearBlockRemovalPrompt }
|
|
52
65
|
size="medium"
|
|
53
66
|
>
|
|
54
|
-
<
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
>
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
67
|
+
<VStack spacing={ 4 }>
|
|
68
|
+
<div>
|
|
69
|
+
<p>{ description }</p>
|
|
70
|
+
{ isStructured &&
|
|
71
|
+
( message.warning || message.subtext ) && (
|
|
72
|
+
<p>
|
|
73
|
+
{ message.warning && (
|
|
74
|
+
<strong>{ message.warning }</strong>
|
|
75
|
+
) }
|
|
76
|
+
{ message.warning && message.subtext && ' ' }
|
|
77
|
+
{ message.subtext }
|
|
78
|
+
</p>
|
|
79
|
+
) }
|
|
80
|
+
</div>
|
|
81
|
+
{ requireConfirmation && (
|
|
82
|
+
<CheckboxControl
|
|
83
|
+
label={ __( 'I understand the consequences' ) }
|
|
84
|
+
checked={ confirmed }
|
|
85
|
+
onChange={ setConfirmed }
|
|
86
|
+
/>
|
|
87
|
+
) }
|
|
88
|
+
<HStack justify="right">
|
|
89
|
+
<Button
|
|
90
|
+
variant="tertiary"
|
|
91
|
+
onClick={ clearBlockRemovalPrompt }
|
|
92
|
+
__next40pxDefaultSize
|
|
93
|
+
>
|
|
94
|
+
{ __( 'Cancel' ) }
|
|
95
|
+
</Button>
|
|
96
|
+
<Button
|
|
97
|
+
variant="primary"
|
|
98
|
+
onClick={ onConfirmRemoval }
|
|
99
|
+
disabled={ isRemoveDisabled }
|
|
100
|
+
accessibleWhenDisabled
|
|
101
|
+
__next40pxDefaultSize
|
|
102
|
+
>
|
|
103
|
+
{ __( 'Delete' ) }
|
|
104
|
+
</Button>
|
|
105
|
+
</HStack>
|
|
106
|
+
</VStack>
|
|
71
107
|
</Modal>
|
|
72
108
|
);
|
|
73
109
|
}
|
|
@@ -33,6 +33,7 @@ const BlockTransformationsMenu = ( {
|
|
|
33
33
|
const blocksThatSplitWhenTransformed = {
|
|
34
34
|
'core/list': [ 'core/paragraph', 'core/heading' ],
|
|
35
35
|
'core/quote': [ 'core/paragraph' ],
|
|
36
|
+
'core/pullquote': [ 'core/paragraph' ],
|
|
36
37
|
};
|
|
37
38
|
|
|
38
39
|
return possibleTransformations.map( ( item ) => {
|
|
@@ -68,12 +68,10 @@ exports[`Block Actions Menu block options duplicates a block 1`] = `
|
|
|
68
68
|
<!-- /wp:heading -->"
|
|
69
69
|
`;
|
|
70
70
|
|
|
71
|
-
exports[`Block Actions Menu block options transforms a Paragraph block into a
|
|
72
|
-
"<!-- wp:
|
|
73
|
-
<
|
|
74
|
-
|
|
75
|
-
<!-- /wp:paragraph --></blockquote>
|
|
76
|
-
<!-- /wp:quote -->
|
|
71
|
+
exports[`Block Actions Menu block options transforms a Paragraph block into a Pullquote block 1`] = `
|
|
72
|
+
"<!-- wp:pullquote -->
|
|
73
|
+
<figure class="wp-block-pullquote"><blockquote><p>Hello!</p></blockquote></figure>
|
|
74
|
+
<!-- /wp:pullquote -->
|
|
77
75
|
|
|
78
76
|
<!-- wp:spacer -->
|
|
79
77
|
<div style="height:100px" aria-hidden="true" class="wp-block-spacer"></div>
|
|
@@ -357,7 +357,7 @@ describe( 'Block Actions Menu', () => {
|
|
|
357
357
|
expect( getEditorHtml() ).toMatchSnapshot();
|
|
358
358
|
} );
|
|
359
359
|
|
|
360
|
-
it( 'transforms a Paragraph block into a
|
|
360
|
+
it( 'transforms a Paragraph block into a Pullquote block', async () => {
|
|
361
361
|
const screen = await initializeEditor();
|
|
362
362
|
const { getByLabelText, getByRole } = screen;
|
|
363
363
|
|
|
@@ -397,7 +397,7 @@ describe( 'Block Actions Menu', () => {
|
|
|
397
397
|
expect( headerTitle ).toBeVisible();
|
|
398
398
|
|
|
399
399
|
// Tap on the Transform block button
|
|
400
|
-
fireEvent.press( getByLabelText( /
|
|
400
|
+
fireEvent.press( getByLabelText( /Pullquote/ ) );
|
|
401
401
|
|
|
402
402
|
expect( getEditorHtml() ).toMatchSnapshot();
|
|
403
403
|
} );
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
* WordPress dependencies
|
|
3
3
|
*/
|
|
4
4
|
import { useViewportMatch } from '@wordpress/compose';
|
|
5
|
-
import { useMemo } from '@wordpress/element';
|
|
6
5
|
|
|
7
6
|
/**
|
|
8
7
|
* Internal dependencies
|
|
@@ -15,7 +14,7 @@ import { BLOCK_VISIBILITY_VIEWPORTS } from './constants';
|
|
|
15
14
|
* @param {Object} options Parameters to avoid extra store subscriptions.
|
|
16
15
|
* @param {Object|boolean} options.blockVisibility Block visibility metadata.
|
|
17
16
|
* @param {string} options.deviceType Current device type ('desktop', 'tablet', 'mobile').
|
|
18
|
-
* @return {Object} Object with `isBlockCurrentlyHidden` and `currentViewport`
|
|
17
|
+
* @return {Object} Object with `isBlockCurrentlyHidden` (boolean) and `currentViewport` (string) properties.
|
|
19
18
|
*/
|
|
20
19
|
export default function useBlockVisibility( options = {} ) {
|
|
21
20
|
const {
|
|
@@ -31,37 +30,23 @@ export default function useBlockVisibility( options = {} ) {
|
|
|
31
30
|
* 1. Device type override (Mobile/Tablet) - uses device type to determine viewport
|
|
32
31
|
* 2. Actual window size (Desktop mode) - uses viewport detection
|
|
33
32
|
*/
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
}
|
|
47
|
-
return BLOCK_VISIBILITY_VIEWPORTS.desktop.key;
|
|
48
|
-
}, [ deviceType, isLargerThanMobile, isLargerThanTablet ] );
|
|
33
|
+
let currentViewport;
|
|
34
|
+
if ( deviceType === BLOCK_VISIBILITY_VIEWPORTS.mobile.key ) {
|
|
35
|
+
currentViewport = BLOCK_VISIBILITY_VIEWPORTS.mobile.key;
|
|
36
|
+
} else if ( deviceType === BLOCK_VISIBILITY_VIEWPORTS.tablet.key ) {
|
|
37
|
+
currentViewport = BLOCK_VISIBILITY_VIEWPORTS.tablet.key;
|
|
38
|
+
} else if ( ! isLargerThanMobile ) {
|
|
39
|
+
currentViewport = BLOCK_VISIBILITY_VIEWPORTS.mobile.key;
|
|
40
|
+
} else if ( isLargerThanMobile && ! isLargerThanTablet ) {
|
|
41
|
+
currentViewport = BLOCK_VISIBILITY_VIEWPORTS.tablet.key;
|
|
42
|
+
} else {
|
|
43
|
+
currentViewport = BLOCK_VISIBILITY_VIEWPORTS.desktop.key;
|
|
44
|
+
}
|
|
49
45
|
|
|
50
46
|
// Determine if block is currently hidden.
|
|
51
|
-
const isBlockCurrentlyHidden =
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
}
|
|
47
|
+
const isBlockCurrentlyHidden =
|
|
48
|
+
blockVisibility === false ||
|
|
49
|
+
blockVisibility?.viewport?.[ currentViewport ] === false;
|
|
55
50
|
|
|
56
|
-
|
|
57
|
-
return true;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
return false;
|
|
61
|
-
}, [ blockVisibility, currentViewport ] );
|
|
62
|
-
|
|
63
|
-
return {
|
|
64
|
-
isBlockCurrentlyHidden,
|
|
65
|
-
currentViewport,
|
|
66
|
-
};
|
|
51
|
+
return { isBlockCurrentlyHidden, currentViewport };
|
|
67
52
|
}
|
|
@@ -100,6 +100,7 @@ export function useSettingsForBlockElement(
|
|
|
100
100
|
'textAlign',
|
|
101
101
|
'textTransform',
|
|
102
102
|
'textDecoration',
|
|
103
|
+
'textIndent',
|
|
103
104
|
'writingMode',
|
|
104
105
|
].forEach( ( key ) => {
|
|
105
106
|
if ( ! supportedStyles.includes( key ) ) {
|
|
@@ -110,6 +111,15 @@ export function useSettingsForBlockElement(
|
|
|
110
111
|
}
|
|
111
112
|
} );
|
|
112
113
|
|
|
114
|
+
// Text indent needs explicit handling since it may not be in parent settings.
|
|
115
|
+
if ( supportedStyles.includes( 'textIndent' ) ) {
|
|
116
|
+
updatedSettings.typography = {
|
|
117
|
+
...updatedSettings.typography,
|
|
118
|
+
textIndent:
|
|
119
|
+
updatedSettings.typography?.textIndent ?? 'subsequent',
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
|
|
113
123
|
// The column-count style is named text column to reduce confusion with
|
|
114
124
|
// the columns block and manage expectations from the support.
|
|
115
125
|
// See: https://github.com/WordPress/gutenberg/pull/33587
|
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
__experimentalToolsPanel as ToolsPanel,
|
|
8
8
|
__experimentalToolsPanelItem as ToolsPanelItem,
|
|
9
9
|
Notice,
|
|
10
|
+
ToggleControl,
|
|
10
11
|
} from '@wordpress/components';
|
|
11
12
|
import { __ } from '@wordpress/i18n';
|
|
12
13
|
import { useCallback, useMemo } from '@wordpress/element';
|
|
@@ -22,6 +23,7 @@ import LetterSpacingControl from '../letter-spacing-control';
|
|
|
22
23
|
import TextAlignmentControl from '../text-alignment-control';
|
|
23
24
|
import TextTransformControl from '../text-transform-control';
|
|
24
25
|
import TextDecorationControl from '../text-decoration-control';
|
|
26
|
+
import TextIndentControl from '../text-indent-control';
|
|
25
27
|
import WritingModeControl from '../writing-mode-control';
|
|
26
28
|
import { useToolsPanelDropdownMenuProps } from './utils';
|
|
27
29
|
import { setImmutably } from '../../utils/object';
|
|
@@ -42,6 +44,7 @@ export function useHasTypographyPanel( settings ) {
|
|
|
42
44
|
const hasTextAlign = useHasTextAlignmentControl( settings );
|
|
43
45
|
const hasTextTransform = useHasTextTransformControl( settings );
|
|
44
46
|
const hasTextDecoration = useHasTextDecorationControl( settings );
|
|
47
|
+
const hasTextIndent = useHasTextIndentControl( settings );
|
|
45
48
|
const hasWritingMode = useHasWritingModeControl( settings );
|
|
46
49
|
const hasTextColumns = useHasTextColumnsControl( settings );
|
|
47
50
|
const hasFontSize = useHasFontSizeControl( settings );
|
|
@@ -55,6 +58,7 @@ export function useHasTypographyPanel( settings ) {
|
|
|
55
58
|
hasTextTransform ||
|
|
56
59
|
hasFontSize ||
|
|
57
60
|
hasTextDecoration ||
|
|
61
|
+
hasTextIndent ||
|
|
58
62
|
hasWritingMode ||
|
|
59
63
|
hasTextColumns
|
|
60
64
|
);
|
|
@@ -118,6 +122,10 @@ function useHasTextColumnsControl( settings ) {
|
|
|
118
122
|
return settings?.typography?.textColumns;
|
|
119
123
|
}
|
|
120
124
|
|
|
125
|
+
function useHasTextIndentControl( settings ) {
|
|
126
|
+
return settings?.typography?.textIndent;
|
|
127
|
+
}
|
|
128
|
+
|
|
121
129
|
/**
|
|
122
130
|
* Concatenate all the font sizes into a single list for the font size picker.
|
|
123
131
|
*
|
|
@@ -169,6 +177,7 @@ const DEFAULT_CONTROLS = {
|
|
|
169
177
|
textAlign: true,
|
|
170
178
|
textTransform: true,
|
|
171
179
|
textDecoration: true,
|
|
180
|
+
textIndent: true,
|
|
172
181
|
writingMode: true,
|
|
173
182
|
textColumns: true,
|
|
174
183
|
};
|
|
@@ -181,6 +190,7 @@ export default function TypographyPanel( {
|
|
|
181
190
|
settings,
|
|
182
191
|
panelId,
|
|
183
192
|
defaultControls = DEFAULT_CONTROLS,
|
|
193
|
+
isGlobalStyles = false,
|
|
184
194
|
} ) {
|
|
185
195
|
const decodeValue = ( rawValue ) =>
|
|
186
196
|
getValueFromVariable( { settings }, '', rawValue );
|
|
@@ -358,6 +368,48 @@ export default function TypographyPanel( {
|
|
|
358
368
|
const hasLetterSpacing = () => !! value?.typography?.letterSpacing;
|
|
359
369
|
const resetLetterSpacing = () => setLetterSpacing( undefined );
|
|
360
370
|
|
|
371
|
+
// Text Indent
|
|
372
|
+
const hasTextIndentControl = useHasTextIndentControl( settings );
|
|
373
|
+
const textIndent = decodeValue( inheritedValue?.typography?.textIndent );
|
|
374
|
+
|
|
375
|
+
// Get the setting value - can be 'subsequent' (default), 'all', or false.
|
|
376
|
+
// The setting determines which CSS selector is used for the text-indent style.
|
|
377
|
+
const textIndentSetting = settings?.typography?.textIndent ?? 'subsequent';
|
|
378
|
+
const isTextIndentAll = textIndentSetting === 'all';
|
|
379
|
+
|
|
380
|
+
const setTextIndentValue = ( newValue ) => {
|
|
381
|
+
onChange(
|
|
382
|
+
setImmutably(
|
|
383
|
+
value,
|
|
384
|
+
[ 'typography', 'textIndent' ],
|
|
385
|
+
newValue || undefined
|
|
386
|
+
)
|
|
387
|
+
);
|
|
388
|
+
};
|
|
389
|
+
|
|
390
|
+
const onToggleTextIndentAll = ( newValue ) => {
|
|
391
|
+
// Toggle between 'all' and 'subsequent' for the setting.
|
|
392
|
+
// Include the settings change so it can be handled atomically by the parent.
|
|
393
|
+
onChange( {
|
|
394
|
+
...value,
|
|
395
|
+
settings: {
|
|
396
|
+
typography: {
|
|
397
|
+
textIndent: newValue ? 'all' : 'subsequent',
|
|
398
|
+
},
|
|
399
|
+
},
|
|
400
|
+
} );
|
|
401
|
+
};
|
|
402
|
+
|
|
403
|
+
const hasTextIndent = () => !! value?.typography?.textIndent;
|
|
404
|
+
const resetTextIndent = () => {
|
|
405
|
+
onChange(
|
|
406
|
+
setImmutably( value, [ 'typography', 'textIndent' ], undefined )
|
|
407
|
+
);
|
|
408
|
+
};
|
|
409
|
+
const textIndentHelp = isTextIndentAll
|
|
410
|
+
? __( 'Indents the first line of all paragraphs.' )
|
|
411
|
+
: __( 'Indents the first line of each paragraph after the first one.' );
|
|
412
|
+
|
|
361
413
|
// Text Columns
|
|
362
414
|
const hasTextColumnsControl = useHasTextColumnsControl( settings );
|
|
363
415
|
const textColumns = decodeValue( inheritedValue?.typography?.textColumns );
|
|
@@ -490,7 +542,6 @@ export default function TypographyPanel( {
|
|
|
490
542
|
) }
|
|
491
543
|
{ hasAppearanceControl && (
|
|
492
544
|
<ToolsPanelItem
|
|
493
|
-
className="single-column"
|
|
494
545
|
label={ appearanceControlLabel }
|
|
495
546
|
hasValue={ hasFontAppearance }
|
|
496
547
|
onDeselect={ resetFontAppearance }
|
|
@@ -544,6 +595,32 @@ export default function TypographyPanel( {
|
|
|
544
595
|
/>
|
|
545
596
|
</ToolsPanelItem>
|
|
546
597
|
) }
|
|
598
|
+
{ hasTextIndentControl && (
|
|
599
|
+
<ToolsPanelItem
|
|
600
|
+
label={ __( 'Line indent' ) }
|
|
601
|
+
hasValue={ hasTextIndent }
|
|
602
|
+
onDeselect={ resetTextIndent }
|
|
603
|
+
isShownByDefault={ defaultControls.textIndent }
|
|
604
|
+
panelId={ panelId }
|
|
605
|
+
>
|
|
606
|
+
<TextIndentControl
|
|
607
|
+
value={ textIndent }
|
|
608
|
+
onChange={ setTextIndentValue }
|
|
609
|
+
size="__unstable-large"
|
|
610
|
+
__unstableInputWidth="auto"
|
|
611
|
+
withSlider
|
|
612
|
+
hasBottomMargin={ isGlobalStyles }
|
|
613
|
+
/>
|
|
614
|
+
{ isGlobalStyles && (
|
|
615
|
+
<ToggleControl
|
|
616
|
+
label={ __( 'Indent all paragraphs' ) }
|
|
617
|
+
checked={ isTextIndentAll }
|
|
618
|
+
onChange={ onToggleTextIndentAll }
|
|
619
|
+
help={ textIndentHelp }
|
|
620
|
+
/>
|
|
621
|
+
) }
|
|
622
|
+
</ToolsPanelItem>
|
|
623
|
+
) }
|
|
547
624
|
{ hasTextColumnsControl && (
|
|
548
625
|
<ToolsPanelItem
|
|
549
626
|
className="single-column"
|
|
@@ -15,13 +15,18 @@ import { __experimentalUseDropZone as useDropZone } from '@wordpress/compose';
|
|
|
15
15
|
*/
|
|
16
16
|
import { useBlockElement } from '../block-list/use-block-props/use-block-refs';
|
|
17
17
|
import BlockPopoverCover from '../block-popover/cover';
|
|
18
|
-
import { range, GridRect, getGridInfo } from './utils';
|
|
18
|
+
import { range, GridRect, getGridInfo, getGridItemRect } from './utils';
|
|
19
19
|
import { store as blockEditorStore } from '../../store';
|
|
20
20
|
import { useGetNumberOfBlocksBeforeCell } from './use-get-number-of-blocks-before-cell';
|
|
21
21
|
import ButtonBlockAppender from '../button-block-appender';
|
|
22
22
|
import { unlock } from '../../lock-unlock';
|
|
23
23
|
|
|
24
|
-
export function GridVisualizer( {
|
|
24
|
+
export function GridVisualizer( {
|
|
25
|
+
clientId,
|
|
26
|
+
contentRef,
|
|
27
|
+
parentLayout,
|
|
28
|
+
childGridClientId,
|
|
29
|
+
} ) {
|
|
25
30
|
const isDistractionFree = useSelect(
|
|
26
31
|
( select ) =>
|
|
27
32
|
select( blockEditorStore ).getSettings().isDistractionFree,
|
|
@@ -42,17 +47,31 @@ export function GridVisualizer( { clientId, contentRef, parentLayout } ) {
|
|
|
42
47
|
gridElement={ gridElement }
|
|
43
48
|
isManualGrid={ isManualGrid }
|
|
44
49
|
ref={ contentRef }
|
|
50
|
+
childGridClientId={ childGridClientId }
|
|
45
51
|
/>
|
|
46
52
|
);
|
|
47
53
|
}
|
|
48
54
|
|
|
49
55
|
const GridVisualizerGrid = forwardRef(
|
|
50
|
-
( { gridClientId, gridElement, isManualGrid }, ref ) => {
|
|
56
|
+
( { gridClientId, gridElement, isManualGrid, childGridClientId }, ref ) => {
|
|
51
57
|
const [ gridInfo, setGridInfo ] = useState( () =>
|
|
52
58
|
getGridInfo( gridElement )
|
|
53
59
|
);
|
|
54
60
|
const [ isDroppingAllowed, setIsDroppingAllowed ] = useState( false );
|
|
55
61
|
|
|
62
|
+
// Get the element for the child grid block so we can
|
|
63
|
+
// compute its position and hide overlapping visualizer cells.
|
|
64
|
+
const childGridElement = useBlockElement( childGridClientId );
|
|
65
|
+
|
|
66
|
+
// Compute the child grid block's rect from its position in the grid.
|
|
67
|
+
// This works for both manual and non-manual grids.
|
|
68
|
+
const childGridRect = useMemo( () => {
|
|
69
|
+
if ( ! childGridElement ) {
|
|
70
|
+
return null;
|
|
71
|
+
}
|
|
72
|
+
return getGridItemRect( childGridElement );
|
|
73
|
+
}, [ childGridElement ] );
|
|
74
|
+
|
|
56
75
|
useEffect( () => {
|
|
57
76
|
const resizeCallback = () =>
|
|
58
77
|
setGridInfo( getGridInfo( gridElement ) );
|
|
@@ -101,14 +120,13 @@ const GridVisualizerGrid = forwardRef(
|
|
|
101
120
|
<ManualGridVisualizer
|
|
102
121
|
gridClientId={ gridClientId }
|
|
103
122
|
gridInfo={ gridInfo }
|
|
123
|
+
childGridRect={ childGridRect }
|
|
104
124
|
/>
|
|
105
125
|
) : (
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
/>
|
|
111
|
-
) )
|
|
126
|
+
<AutoGridVisualizer
|
|
127
|
+
gridInfo={ gridInfo }
|
|
128
|
+
childGridRect={ childGridRect }
|
|
129
|
+
/>
|
|
112
130
|
) }
|
|
113
131
|
</div>
|
|
114
132
|
</BlockPopoverCover>
|
|
@@ -116,7 +134,27 @@ const GridVisualizerGrid = forwardRef(
|
|
|
116
134
|
}
|
|
117
135
|
);
|
|
118
136
|
|
|
119
|
-
function
|
|
137
|
+
function AutoGridVisualizer( { gridInfo, childGridRect } ) {
|
|
138
|
+
return range( 1, gridInfo.numRows ).map( ( row ) =>
|
|
139
|
+
range( 1, gridInfo.numColumns ).map( ( column ) => {
|
|
140
|
+
// Don't render visualizer cells for a selected child block
|
|
141
|
+
// that is itself a grid, so that only the child's grid
|
|
142
|
+
// visualizer is visible.
|
|
143
|
+
let color = gridInfo.currentColor;
|
|
144
|
+
if ( childGridRect?.contains( column, row ) ) {
|
|
145
|
+
color = 'transparent';
|
|
146
|
+
}
|
|
147
|
+
return (
|
|
148
|
+
<GridVisualizerCell
|
|
149
|
+
key={ `${ row }-${ column }` }
|
|
150
|
+
color={ color }
|
|
151
|
+
/>
|
|
152
|
+
);
|
|
153
|
+
} )
|
|
154
|
+
);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
function ManualGridVisualizer( { gridClientId, gridInfo, childGridRect } ) {
|
|
120
158
|
const [ highlightedRect, setHighlightedRect ] = useState( null );
|
|
121
159
|
|
|
122
160
|
const gridItemStyles = useSelect(
|
|
@@ -155,6 +193,14 @@ function ManualGridVisualizer( { gridClientId, gridInfo } ) {
|
|
|
155
193
|
|
|
156
194
|
return range( 1, gridInfo.numRows ).map( ( row ) =>
|
|
157
195
|
range( 1, gridInfo.numColumns ).map( ( column ) => {
|
|
196
|
+
// Don't render visualizer cells for a selected child block
|
|
197
|
+
// that is itself a grid, so that only the child's grid
|
|
198
|
+
// visualizer is visible.
|
|
199
|
+
const isChildGridCell = childGridRect?.contains( column, row );
|
|
200
|
+
let color = gridInfo.currentColor;
|
|
201
|
+
if ( isChildGridCell ) {
|
|
202
|
+
color = 'transparent';
|
|
203
|
+
}
|
|
158
204
|
const isCellOccupied = occupiedRects.some( ( rect ) =>
|
|
159
205
|
rect.contains( column, row )
|
|
160
206
|
);
|
|
@@ -163,10 +209,10 @@ function ManualGridVisualizer( { gridClientId, gridInfo } ) {
|
|
|
163
209
|
return (
|
|
164
210
|
<GridVisualizerCell
|
|
165
211
|
key={ `${ row }-${ column }` }
|
|
166
|
-
color={
|
|
212
|
+
color={ color }
|
|
167
213
|
className={ isHighlighted && 'is-highlighted' }
|
|
168
214
|
>
|
|
169
|
-
{ isCellOccupied ? (
|
|
215
|
+
{ isCellOccupied && ! isChildGridCell ? (
|
|
170
216
|
<GridVisualizerDropZone
|
|
171
217
|
column={ column }
|
|
172
218
|
row={ row }
|
|
@@ -14,7 +14,12 @@ import {
|
|
|
14
14
|
useEffect,
|
|
15
15
|
} from '@wordpress/element';
|
|
16
16
|
import { __ } from '@wordpress/i18n';
|
|
17
|
-
import {
|
|
17
|
+
import {
|
|
18
|
+
useMergeRefs,
|
|
19
|
+
useRefEffect,
|
|
20
|
+
useDisabled,
|
|
21
|
+
useViewportMatch,
|
|
22
|
+
} from '@wordpress/compose';
|
|
18
23
|
import { __experimentalStyleProvider as StyleProvider } from '@wordpress/components';
|
|
19
24
|
import { useSelect } from '@wordpress/data';
|
|
20
25
|
|
|
@@ -26,6 +31,8 @@ import { getCompatibilityStyles } from './get-compatibility-styles';
|
|
|
26
31
|
import { useScaleCanvas } from './use-scale-canvas';
|
|
27
32
|
import { store as blockEditorStore } from '../../store';
|
|
28
33
|
|
|
34
|
+
const ViewportWidthProvider = useViewportMatch.__experimentalWidthProvider;
|
|
35
|
+
|
|
29
36
|
function bubbleEvent( event, Constructor, frame ) {
|
|
30
37
|
const init = {};
|
|
31
38
|
|
|
@@ -227,6 +234,7 @@ function Iframe( {
|
|
|
227
234
|
const {
|
|
228
235
|
contentResizeListener,
|
|
229
236
|
containerResizeListener,
|
|
237
|
+
containerWidth,
|
|
230
238
|
isZoomedOut,
|
|
231
239
|
scaleContainerWidth,
|
|
232
240
|
} = useScaleCanvas( {
|
|
@@ -347,7 +355,9 @@ function Iframe( {
|
|
|
347
355
|
>
|
|
348
356
|
{ contentResizeListener }
|
|
349
357
|
<StyleProvider document={ iframeDocument }>
|
|
350
|
-
{
|
|
358
|
+
<ViewportWidthProvider value={ containerWidth }>
|
|
359
|
+
{ children }
|
|
360
|
+
</ViewportWidthProvider>
|
|
351
361
|
</StyleProvider>
|
|
352
362
|
</body>,
|
|
353
363
|
iframeDocument.documentElement
|