@wordpress/block-editor 12.19.2 → 12.19.4
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-edit/context.js +2 -1
- package/build/components/block-edit/context.js.map +1 -1
- package/build/components/block-edit/index.js +8 -3
- package/build/components/block-edit/index.js.map +1 -1
- package/build/components/block-inspector/index.js +5 -4
- package/build/components/block-inspector/index.js.map +1 -1
- package/build/components/block-preview/index.js +4 -0
- package/build/components/block-preview/index.js.map +1 -1
- package/build/components/block-tools/insertion-point.js +4 -1
- package/build/components/block-tools/insertion-point.js.map +1 -1
- package/build/components/global-styles/advanced-panel.js +5 -10
- package/build/components/global-styles/advanced-panel.js.map +1 -1
- package/build/components/global-styles/border-panel.js +21 -8
- package/build/components/global-styles/border-panel.js.map +1 -1
- package/build/components/global-styles/index.js +6 -0
- package/build/components/global-styles/index.js.map +1 -1
- package/build/components/global-styles/shadow-panel-components.js +80 -23
- package/build/components/global-styles/shadow-panel-components.js.map +1 -1
- package/build/components/inserter/media-tab/media-preview.js +1 -1
- package/build/components/inserter/media-tab/media-preview.js.map +1 -1
- package/build/components/inspector-controls-tabs/styles-tab.js +1 -1
- package/build/components/inspector-controls-tabs/styles-tab.js.map +1 -1
- package/build/components/link-control/link-preview.js +4 -1
- package/build/components/link-control/link-preview.js.map +1 -1
- package/build/components/rich-text/index.js +52 -28
- package/build/components/rich-text/index.js.map +1 -1
- package/build/components/rich-text/use-enter.js +3 -0
- package/build/components/rich-text/use-enter.js.map +1 -1
- package/build/components/rich-text/use-paste-handler.js +25 -26
- package/build/components/rich-text/use-paste-handler.js.map +1 -1
- package/build/hooks/background.js +4 -2
- package/build/hooks/background.js.map +1 -1
- package/build/hooks/block-hooks.js +8 -6
- package/build/hooks/block-hooks.js.map +1 -1
- package/build/hooks/border.js +6 -4
- package/build/hooks/border.js.map +1 -1
- package/build/hooks/use-bindings-attributes.js +2 -4
- package/build/hooks/use-bindings-attributes.js.map +1 -1
- package/build/private-apis.js +5 -1
- package/build/private-apis.js.map +1 -1
- package/build/store/index.js +0 -2
- package/build/store/index.js.map +1 -1
- package/build/store/private-actions.js +0 -10
- package/build/store/private-actions.js.map +1 -1
- package/build/store/private-keys.js +8 -0
- package/build/store/private-keys.js.map +1 -0
- package/build/store/private-selectors.js +6 -17
- package/build/store/private-selectors.js.map +1 -1
- package/build/store/reducer.js +1 -24
- package/build/store/reducer.js.map +1 -1
- package/build/store/selectors.js +7 -12
- package/build/store/selectors.js.map +1 -1
- package/build/store/utils.js +7 -2
- package/build/store/utils.js.map +1 -1
- package/build-module/components/block-edit/context.js +1 -0
- package/build-module/components/block-edit/context.js.map +1 -1
- package/build-module/components/block-edit/index.js +9 -4
- package/build-module/components/block-edit/index.js.map +1 -1
- package/build-module/components/block-inspector/index.js +6 -5
- package/build-module/components/block-inspector/index.js.map +1 -1
- package/build-module/components/block-preview/index.js +4 -0
- package/build-module/components/block-preview/index.js.map +1 -1
- package/build-module/components/block-tools/insertion-point.js +4 -1
- package/build-module/components/block-tools/insertion-point.js.map +1 -1
- package/build-module/components/global-styles/advanced-panel.js +6 -11
- package/build-module/components/global-styles/advanced-panel.js.map +1 -1
- package/build-module/components/global-styles/border-panel.js +22 -10
- package/build-module/components/global-styles/border-panel.js.map +1 -1
- package/build-module/components/global-styles/index.js +1 -1
- package/build-module/components/global-styles/index.js.map +1 -1
- package/build-module/components/global-styles/shadow-panel-components.js +82 -24
- package/build-module/components/global-styles/shadow-panel-components.js.map +1 -1
- package/build-module/components/inserter/media-tab/media-preview.js +1 -1
- package/build-module/components/inserter/media-tab/media-preview.js.map +1 -1
- package/build-module/components/inspector-controls-tabs/styles-tab.js +2 -2
- package/build-module/components/inspector-controls-tabs/styles-tab.js.map +1 -1
- package/build-module/components/link-control/link-preview.js +5 -2
- package/build-module/components/link-control/link-preview.js.map +1 -1
- package/build-module/components/rich-text/index.js +52 -29
- package/build-module/components/rich-text/index.js.map +1 -1
- package/build-module/components/rich-text/use-enter.js +3 -0
- package/build-module/components/rich-text/use-enter.js.map +1 -1
- package/build-module/components/rich-text/use-paste-handler.js +25 -26
- package/build-module/components/rich-text/use-paste-handler.js.map +1 -1
- package/build-module/hooks/background.js +4 -2
- package/build-module/hooks/background.js.map +1 -1
- package/build-module/hooks/block-hooks.js +8 -6
- package/build-module/hooks/block-hooks.js.map +1 -1
- package/build-module/hooks/border.js +7 -5
- package/build-module/hooks/border.js.map +1 -1
- package/build-module/hooks/use-bindings-attributes.js +3 -5
- package/build-module/hooks/use-bindings-attributes.js.map +1 -1
- package/build-module/private-apis.js +5 -1
- package/build-module/private-apis.js.map +1 -1
- package/build-module/store/index.js +0 -2
- package/build-module/store/index.js.map +1 -1
- package/build-module/store/private-actions.js +0 -9
- package/build-module/store/private-actions.js.map +1 -1
- package/build-module/store/private-keys.js +2 -0
- package/build-module/store/private-keys.js.map +1 -0
- package/build-module/store/private-selectors.js +5 -12
- package/build-module/store/private-selectors.js.map +1 -1
- package/build-module/store/reducer.js +1 -24
- package/build-module/store/reducer.js.map +1 -1
- package/build-module/store/selectors.js +8 -13
- package/build-module/store/selectors.js.map +1 -1
- package/build-module/store/utils.js +6 -2
- package/build-module/store/utils.js.map +1 -1
- package/build-style/style-rtl.css +47 -24
- package/build-style/style.css +47 -24
- package/package.json +7 -7
- package/src/components/block-edit/context.js +1 -0
- package/src/components/block-edit/index.js +5 -1
- package/src/components/block-inspector/index.js +7 -5
- package/src/components/block-preview/index.js +6 -1
- package/src/components/block-toolbar/style.scss +11 -6
- package/src/components/block-tools/insertion-point.js +6 -1
- package/src/components/global-styles/advanced-panel.js +6 -12
- package/src/components/global-styles/border-panel.js +33 -22
- package/src/components/global-styles/index.js +5 -1
- package/src/components/global-styles/shadow-panel-components.js +92 -23
- package/src/components/global-styles/style.scss +33 -20
- package/src/components/inserter/media-tab/media-preview.js +6 -1
- package/src/components/inspector-controls-tabs/styles-tab.js +2 -2
- package/src/components/link-control/link-preview.js +9 -2
- package/src/components/link-control/style.scss +9 -0
- package/src/components/rich-text/index.js +74 -44
- package/src/components/rich-text/use-enter.js +4 -0
- package/src/components/rich-text/use-paste-handler.js +26 -25
- package/src/components/url-popover/style.scss +1 -0
- package/src/hooks/background.js +5 -2
- package/src/hooks/block-hooks.js +10 -5
- package/src/hooks/block-hooks.scss +6 -0
- package/src/hooks/border.js +16 -4
- package/src/hooks/use-bindings-attributes.js +5 -7
- package/src/private-apis.js +4 -0
- package/src/store/index.js +0 -2
- package/src/store/private-actions.js +0 -10
- package/src/store/private-keys.js +1 -0
- package/src/store/private-selectors.js +4 -15
- package/src/store/reducer.js +0 -25
- package/src/store/selectors.js +7 -15
- package/src/store/utils.js +7 -2
- package/build/store/resolvers.js +0 -27
- package/build/store/resolvers.js.map +0 -1
- package/build-module/store/resolvers.js +0 -20
- package/build-module/store/resolvers.js.map +0 -1
- package/src/store/resolvers.js +0 -17
|
@@ -5,28 +5,36 @@ import { __ } from '@wordpress/i18n';
|
|
|
5
5
|
import {
|
|
6
6
|
__experimentalVStack as VStack,
|
|
7
7
|
__experimentalHeading as Heading,
|
|
8
|
-
__experimentalGrid as Grid,
|
|
9
8
|
__experimentalHStack as HStack,
|
|
10
9
|
__experimentalDropdownContentWrapper as DropdownContentWrapper,
|
|
11
10
|
Button,
|
|
12
11
|
FlexItem,
|
|
13
12
|
Dropdown,
|
|
13
|
+
privateApis as componentsPrivateApis,
|
|
14
14
|
} from '@wordpress/components';
|
|
15
|
+
import { useMemo } from '@wordpress/element';
|
|
15
16
|
import { shadow as shadowIcon, Icon, check } from '@wordpress/icons';
|
|
17
|
+
|
|
16
18
|
/**
|
|
17
19
|
* External dependencies
|
|
18
20
|
*/
|
|
19
21
|
import classNames from 'classnames';
|
|
20
22
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
23
|
+
/**
|
|
24
|
+
* Internal dependencies
|
|
25
|
+
*/
|
|
26
|
+
import { unlock } from '../../lock-unlock';
|
|
25
27
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
28
|
+
/**
|
|
29
|
+
* Shared reference to an empty array for cases where it is important to avoid
|
|
30
|
+
* returning a new array reference on every invocation.
|
|
31
|
+
*
|
|
32
|
+
* @type {Array}
|
|
33
|
+
*/
|
|
34
|
+
const EMPTY_ARRAY = [];
|
|
35
|
+
|
|
36
|
+
export function ShadowPopoverContainer( { shadow, onShadowChange, settings } ) {
|
|
37
|
+
const shadows = useShadowPresets( settings );
|
|
30
38
|
|
|
31
39
|
return (
|
|
32
40
|
<div className="block-editor-global-styles__shadow-popover-container">
|
|
@@ -37,42 +45,76 @@ export function ShadowPopoverContainer( { shadow, onShadowChange, settings } ) {
|
|
|
37
45
|
activeShadow={ shadow }
|
|
38
46
|
onSelect={ onShadowChange }
|
|
39
47
|
/>
|
|
48
|
+
<div className="block-editor-global-styles__clear-shadow">
|
|
49
|
+
<Button
|
|
50
|
+
variant="tertiary"
|
|
51
|
+
onClick={ () => onShadowChange( undefined ) }
|
|
52
|
+
>
|
|
53
|
+
{ __( 'Clear' ) }
|
|
54
|
+
</Button>
|
|
55
|
+
</div>
|
|
40
56
|
</VStack>
|
|
41
57
|
</div>
|
|
42
58
|
);
|
|
43
59
|
}
|
|
44
60
|
|
|
45
61
|
export function ShadowPresets( { presets, activeShadow, onSelect } ) {
|
|
62
|
+
const { CompositeV2: Composite, useCompositeStoreV2: useCompositeStore } =
|
|
63
|
+
unlock( componentsPrivateApis );
|
|
64
|
+
const compositeStore = useCompositeStore();
|
|
46
65
|
return ! presets ? null : (
|
|
47
|
-
<
|
|
66
|
+
<Composite
|
|
67
|
+
store={ compositeStore }
|
|
68
|
+
role="listbox"
|
|
69
|
+
className="block-editor-global-styles__shadow__list"
|
|
70
|
+
aria-label={ __( 'Drop shadows' ) }
|
|
71
|
+
>
|
|
48
72
|
{ presets.map( ( { name, slug, shadow } ) => (
|
|
49
73
|
<ShadowIndicator
|
|
50
74
|
key={ slug }
|
|
51
75
|
label={ name }
|
|
52
76
|
isActive={ shadow === activeShadow }
|
|
77
|
+
type={ slug === 'unset' ? 'unset' : 'preset' }
|
|
53
78
|
onSelect={ () =>
|
|
54
79
|
onSelect( shadow === activeShadow ? undefined : shadow )
|
|
55
80
|
}
|
|
56
81
|
shadow={ shadow }
|
|
57
82
|
/>
|
|
58
83
|
) ) }
|
|
59
|
-
</
|
|
84
|
+
</Composite>
|
|
60
85
|
);
|
|
61
86
|
}
|
|
62
87
|
|
|
63
|
-
export function ShadowIndicator( { label, isActive, onSelect, shadow } ) {
|
|
88
|
+
export function ShadowIndicator( { type, label, isActive, onSelect, shadow } ) {
|
|
89
|
+
const { CompositeItemV2: CompositeItem } = unlock( componentsPrivateApis );
|
|
64
90
|
return (
|
|
65
|
-
<
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
91
|
+
<CompositeItem
|
|
92
|
+
role="option"
|
|
93
|
+
aria-label={ label }
|
|
94
|
+
aria-selected={ isActive }
|
|
95
|
+
className={ classNames(
|
|
96
|
+
'block-editor-global-styles__shadow__item',
|
|
97
|
+
{
|
|
98
|
+
'is-active': isActive,
|
|
99
|
+
}
|
|
100
|
+
) }
|
|
101
|
+
render={
|
|
102
|
+
<Button
|
|
103
|
+
className={ classNames(
|
|
104
|
+
'block-editor-global-styles__shadow-indicator',
|
|
105
|
+
{
|
|
106
|
+
unset: type === 'unset',
|
|
107
|
+
}
|
|
108
|
+
) }
|
|
109
|
+
onClick={ onSelect }
|
|
110
|
+
label={ label }
|
|
111
|
+
style={ { boxShadow: shadow } }
|
|
112
|
+
showTooltip
|
|
113
|
+
>
|
|
114
|
+
{ isActive && <Icon icon={ check } /> }
|
|
115
|
+
</Button>
|
|
116
|
+
}
|
|
117
|
+
/>
|
|
76
118
|
);
|
|
77
119
|
}
|
|
78
120
|
|
|
@@ -123,3 +165,30 @@ function renderShadowToggle() {
|
|
|
123
165
|
);
|
|
124
166
|
};
|
|
125
167
|
}
|
|
168
|
+
|
|
169
|
+
export function useShadowPresets( settings ) {
|
|
170
|
+
return useMemo( () => {
|
|
171
|
+
if ( ! settings?.shadow ) {
|
|
172
|
+
return EMPTY_ARRAY;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
const defaultPresetsEnabled = settings?.shadow?.defaultPresets;
|
|
176
|
+
const { default: defaultShadows, theme: themeShadows } =
|
|
177
|
+
settings?.shadow?.presets ?? {};
|
|
178
|
+
const unsetShadow = {
|
|
179
|
+
name: __( 'Unset' ),
|
|
180
|
+
slug: 'unset',
|
|
181
|
+
shadow: 'none',
|
|
182
|
+
};
|
|
183
|
+
|
|
184
|
+
const shadowPresets = [
|
|
185
|
+
...( ( defaultPresetsEnabled && defaultShadows ) || EMPTY_ARRAY ),
|
|
186
|
+
...( themeShadows || EMPTY_ARRAY ),
|
|
187
|
+
];
|
|
188
|
+
if ( shadowPresets.length ) {
|
|
189
|
+
shadowPresets.unshift( unsetShadow );
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
return shadowPresets;
|
|
193
|
+
}, [ settings ] );
|
|
194
|
+
}
|
|
@@ -2,10 +2,24 @@
|
|
|
2
2
|
fill: currentColor;
|
|
3
3
|
}
|
|
4
4
|
|
|
5
|
+
// @todo: Ideally, popover, swatch size, and gap values should be CSS variables
|
|
6
|
+
// to apply precise grid layouts.
|
|
7
|
+
// https://github.com/WordPress/gutenberg/blob/954ecae571abbddc113d3a4bd8e1a72230180554/packages/block-editor/src/components/duotone-control/style.scss#L3-L9
|
|
5
8
|
.block-editor-global-styles__shadow-popover-container {
|
|
6
9
|
width: 230px;
|
|
7
10
|
}
|
|
8
11
|
|
|
12
|
+
.block-editor-global-styles__shadow__list {
|
|
13
|
+
display: flex;
|
|
14
|
+
gap: 12px;
|
|
15
|
+
flex-wrap: wrap;
|
|
16
|
+
padding-bottom: $grid-unit-10;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
.block-editor-global-styles__clear-shadow {
|
|
20
|
+
text-align: right;
|
|
21
|
+
}
|
|
22
|
+
|
|
9
23
|
.block-editor-global-styles-filters-panel__dropdown,
|
|
10
24
|
.block-editor-global-styles__shadow-dropdown {
|
|
11
25
|
display: block;
|
|
@@ -21,14 +35,6 @@
|
|
|
21
35
|
}
|
|
22
36
|
}
|
|
23
37
|
|
|
24
|
-
// wrapper to clip the shadow beyond 6px
|
|
25
|
-
.block-editor-global-styles__shadow-indicator-wrapper {
|
|
26
|
-
padding: $grid-unit-15 * 0.5;
|
|
27
|
-
display: flex;
|
|
28
|
-
align-items: center;
|
|
29
|
-
justify-content: center;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
38
|
// These styles are similar to the color palette.
|
|
33
39
|
.block-editor-global-styles__shadow-indicator {
|
|
34
40
|
color: $gray-800;
|
|
@@ -37,8 +43,25 @@
|
|
|
37
43
|
cursor: pointer;
|
|
38
44
|
padding: 0;
|
|
39
45
|
|
|
40
|
-
height: $button-size-small;
|
|
41
|
-
width: $button-size-small;
|
|
46
|
+
height: $button-size-small + 2 * $border-width;
|
|
47
|
+
width: $button-size-small + 2 * $border-width;
|
|
48
|
+
box-sizing: border-box;
|
|
49
|
+
|
|
50
|
+
transform: scale(1);
|
|
51
|
+
transition: transform 0.1s ease;
|
|
52
|
+
will-change: transform;
|
|
53
|
+
|
|
54
|
+
&:focus {
|
|
55
|
+
border: #{ $border-width * 2 } solid $gray-700;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
&:hover {
|
|
59
|
+
transform: scale(1.2);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
&.unset {
|
|
63
|
+
background: linear-gradient(-45deg, transparent 48%, $gray-300 48%, $gray-300 52%, transparent 52%);
|
|
64
|
+
}
|
|
42
65
|
}
|
|
43
66
|
|
|
44
67
|
.block-editor-global-styles-advanced-panel__custom-css-input textarea {
|
|
@@ -47,13 +70,3 @@
|
|
|
47
70
|
/*rtl:ignore*/
|
|
48
71
|
direction: ltr;
|
|
49
72
|
}
|
|
50
|
-
|
|
51
|
-
.block-editor-global-styles-advanced-panel__custom-css-validation-wrapper {
|
|
52
|
-
position: absolute;
|
|
53
|
-
bottom: $grid-unit-20;
|
|
54
|
-
right: $grid-unit * 3;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
.block-editor-global-styles-advanced-panel__custom-css-validation-icon {
|
|
58
|
-
fill: $alert-red;
|
|
59
|
-
}
|
|
@@ -195,7 +195,12 @@ export function MediaPreview( { media, onClick, category } ) {
|
|
|
195
195
|
createSuccessNotice,
|
|
196
196
|
]
|
|
197
197
|
);
|
|
198
|
-
|
|
198
|
+
|
|
199
|
+
const title =
|
|
200
|
+
typeof media.title === 'string'
|
|
201
|
+
? media.title
|
|
202
|
+
: media.title?.rendered || __( 'no title' );
|
|
203
|
+
|
|
199
204
|
let truncatedTitle;
|
|
200
205
|
if ( title.length > MAXIMUM_TITLE_LENGTH ) {
|
|
201
206
|
const omission = '...';
|
|
@@ -11,10 +11,10 @@ import { __ } from '@wordpress/i18n';
|
|
|
11
11
|
import BlockStyles from '../block-styles';
|
|
12
12
|
import DefaultStylePicker from '../default-style-picker';
|
|
13
13
|
import InspectorControls from '../inspector-controls';
|
|
14
|
-
import {
|
|
14
|
+
import { useBorderPanelLabel } from '../../hooks/border';
|
|
15
15
|
|
|
16
16
|
const StylesTab = ( { blockName, clientId, hasBlockStyles } ) => {
|
|
17
|
-
const borderPanelLabel =
|
|
17
|
+
const borderPanelLabel = useBorderPanelLabel( { blockName } );
|
|
18
18
|
|
|
19
19
|
return (
|
|
20
20
|
<>
|
|
@@ -16,8 +16,9 @@ import { useCopyToClipboard } from '@wordpress/compose';
|
|
|
16
16
|
import { filterURLForDisplay, safeDecodeURI } from '@wordpress/url';
|
|
17
17
|
import { Icon, globe, info, linkOff, edit, copySmall } from '@wordpress/icons';
|
|
18
18
|
import { __unstableStripHTML as stripHTML } from '@wordpress/dom';
|
|
19
|
-
import { useDispatch } from '@wordpress/data';
|
|
19
|
+
import { useDispatch, useSelect } from '@wordpress/data';
|
|
20
20
|
import { store as noticesStore } from '@wordpress/notices';
|
|
21
|
+
import { store as preferencesStore } from '@wordpress/preferences';
|
|
21
22
|
|
|
22
23
|
/**
|
|
23
24
|
* Internal dependencies
|
|
@@ -33,6 +34,12 @@ export default function LinkPreview( {
|
|
|
33
34
|
hasUnlinkControl = false,
|
|
34
35
|
onRemove,
|
|
35
36
|
} ) {
|
|
37
|
+
const showIconLabels = useSelect(
|
|
38
|
+
( select ) =>
|
|
39
|
+
select( preferencesStore ).get( 'core', 'showIconLabels' ),
|
|
40
|
+
[]
|
|
41
|
+
);
|
|
42
|
+
|
|
36
43
|
// Avoid fetching if rich previews are not desired.
|
|
37
44
|
const showRichPreviews = hasRichPreviews ? value?.url : null;
|
|
38
45
|
|
|
@@ -139,7 +146,7 @@ export default function LinkPreview( {
|
|
|
139
146
|
label={ sprintf(
|
|
140
147
|
// Translators: %s is a placeholder for the link URL and an optional colon, (if a Link URL is present).
|
|
141
148
|
__( 'Copy link%s' ), // Ends up looking like "Copy link: https://example.com".
|
|
142
|
-
isEmptyURL ? '' : ': ' + value.url
|
|
149
|
+
isEmptyURL || showIconLabels ? '' : ': ' + value.url
|
|
143
150
|
) }
|
|
144
151
|
ref={ ref }
|
|
145
152
|
disabled={ isEmptyURL }
|
|
@@ -34,6 +34,15 @@ $block-editor-link-control-number-of-actions: 1;
|
|
|
34
34
|
content: attr(aria-label);
|
|
35
35
|
}
|
|
36
36
|
}
|
|
37
|
+
|
|
38
|
+
.block-editor-link-control__search-item-top {
|
|
39
|
+
gap: $grid-unit-10;
|
|
40
|
+
|
|
41
|
+
.components-button.has-icon {
|
|
42
|
+
min-width: inherit;
|
|
43
|
+
width: min-content;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
37
46
|
}
|
|
38
47
|
}
|
|
39
48
|
|
|
@@ -19,13 +19,14 @@ import {
|
|
|
19
19
|
removeFormat,
|
|
20
20
|
} from '@wordpress/rich-text';
|
|
21
21
|
import { Popover } from '@wordpress/components';
|
|
22
|
-
import { getBlockType } from '@wordpress/blocks';
|
|
22
|
+
import { getBlockType, store as blocksStore } from '@wordpress/blocks';
|
|
23
23
|
|
|
24
24
|
/**
|
|
25
25
|
* Internal dependencies
|
|
26
26
|
*/
|
|
27
27
|
import { useBlockEditorAutocompleteProps } from '../autocomplete';
|
|
28
28
|
import { useBlockEditContext } from '../block-edit';
|
|
29
|
+
import { blockBindingsKey } from '../block-edit/context';
|
|
29
30
|
import FormatToolbarContainer from './format-toolbar-container';
|
|
30
31
|
import { store as blockEditorStore } from '../../store';
|
|
31
32
|
import { useUndoAutomaticChange } from './use-undo-automatic-change';
|
|
@@ -109,6 +110,7 @@ export function RichTextWrapper(
|
|
|
109
110
|
__unstableDisableFormats: disableFormats,
|
|
110
111
|
disableLineBreaks,
|
|
111
112
|
__unstableAllowPrefixTransformations,
|
|
113
|
+
disableEditing,
|
|
112
114
|
...props
|
|
113
115
|
},
|
|
114
116
|
forwardedRef
|
|
@@ -116,11 +118,9 @@ export function RichTextWrapper(
|
|
|
116
118
|
props = removeNativeProps( props );
|
|
117
119
|
|
|
118
120
|
const anchorRef = useRef();
|
|
119
|
-
const
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
name: blockName,
|
|
123
|
-
} = useBlockEditContext();
|
|
121
|
+
const context = useBlockEditContext();
|
|
122
|
+
const { clientId, isSelected: isBlockSelected, name: blockName } = context;
|
|
123
|
+
const blockBindings = context[ blockBindingsKey ];
|
|
124
124
|
const selector = ( select ) => {
|
|
125
125
|
// Avoid subscribing to the block editor store if the block is not
|
|
126
126
|
// selected.
|
|
@@ -128,12 +128,10 @@ export function RichTextWrapper(
|
|
|
128
128
|
return { isSelected: false };
|
|
129
129
|
}
|
|
130
130
|
|
|
131
|
-
const { getSelectionStart, getSelectionEnd
|
|
131
|
+
const { getSelectionStart, getSelectionEnd } =
|
|
132
132
|
select( blockEditorStore );
|
|
133
133
|
const selectionStart = getSelectionStart();
|
|
134
134
|
const selectionEnd = getSelectionEnd();
|
|
135
|
-
const blockBindings =
|
|
136
|
-
getBlockAttributes( clientId )?.metadata?.bindings;
|
|
137
135
|
|
|
138
136
|
let isSelected;
|
|
139
137
|
|
|
@@ -146,43 +144,60 @@ export function RichTextWrapper(
|
|
|
146
144
|
isSelected = selectionStart.clientId === clientId;
|
|
147
145
|
}
|
|
148
146
|
|
|
149
|
-
// Disable Rich Text editing if block bindings specify that.
|
|
150
|
-
let shouldDisableEditing = false;
|
|
151
|
-
if ( blockBindings && blockName in BLOCK_BINDINGS_ALLOWED_BLOCKS ) {
|
|
152
|
-
const blockTypeAttributes = getBlockType( blockName ).attributes;
|
|
153
|
-
const { getBlockBindingsSource } = unlock(
|
|
154
|
-
select( blockEditorStore )
|
|
155
|
-
);
|
|
156
|
-
for ( const [ attribute, args ] of Object.entries(
|
|
157
|
-
blockBindings
|
|
158
|
-
) ) {
|
|
159
|
-
// If any of the attributes with source "rich-text" is part of the bindings,
|
|
160
|
-
// has a source with `lockAttributesEditing`, disable it.
|
|
161
|
-
if (
|
|
162
|
-
blockTypeAttributes?.[ attribute ]?.source ===
|
|
163
|
-
'rich-text' &&
|
|
164
|
-
getBlockBindingsSource( args.source )?.lockAttributesEditing
|
|
165
|
-
) {
|
|
166
|
-
shouldDisableEditing = true;
|
|
167
|
-
break;
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
|
|
172
147
|
return {
|
|
173
148
|
selectionStart: isSelected ? selectionStart.offset : undefined,
|
|
174
149
|
selectionEnd: isSelected ? selectionEnd.offset : undefined,
|
|
175
150
|
isSelected,
|
|
176
|
-
shouldDisableEditing,
|
|
177
151
|
};
|
|
178
152
|
};
|
|
179
|
-
const { selectionStart, selectionEnd, isSelected
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
153
|
+
const { selectionStart, selectionEnd, isSelected } = useSelect( selector, [
|
|
154
|
+
clientId,
|
|
155
|
+
identifier,
|
|
156
|
+
originalIsSelected,
|
|
157
|
+
isBlockSelected,
|
|
158
|
+
] );
|
|
159
|
+
|
|
160
|
+
const disableBoundBlocks = useSelect(
|
|
161
|
+
( select ) => {
|
|
162
|
+
// Disable Rich Text editing if block bindings specify that.
|
|
163
|
+
let _disableBoundBlocks = false;
|
|
164
|
+
if ( blockBindings && blockName in BLOCK_BINDINGS_ALLOWED_BLOCKS ) {
|
|
165
|
+
const blockTypeAttributes =
|
|
166
|
+
getBlockType( blockName ).attributes;
|
|
167
|
+
const { getBlockBindingsSource } = unlock(
|
|
168
|
+
select( blocksStore )
|
|
169
|
+
);
|
|
170
|
+
for ( const [ attribute, args ] of Object.entries(
|
|
171
|
+
blockBindings
|
|
172
|
+
) ) {
|
|
173
|
+
if (
|
|
174
|
+
blockTypeAttributes?.[ attribute ]?.source !==
|
|
175
|
+
'rich-text'
|
|
176
|
+
) {
|
|
177
|
+
break;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
// If the source is not defined, or if its value of `lockAttributesEditing` is `true`, disable it.
|
|
181
|
+
const blockBindingsSource = getBlockBindingsSource(
|
|
182
|
+
args.source
|
|
183
|
+
);
|
|
184
|
+
if (
|
|
185
|
+
! blockBindingsSource ||
|
|
186
|
+
blockBindingsSource.lockAttributesEditing
|
|
187
|
+
) {
|
|
188
|
+
_disableBoundBlocks = true;
|
|
189
|
+
break;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
return _disableBoundBlocks;
|
|
195
|
+
},
|
|
196
|
+
[ blockBindings, blockName ]
|
|
197
|
+
);
|
|
198
|
+
|
|
199
|
+
const shouldDisableEditing = disableEditing || disableBoundBlocks;
|
|
200
|
+
|
|
186
201
|
const { getSelectionStart, getSelectionEnd, getBlockRootClientId } =
|
|
187
202
|
useSelect( blockEditorStore );
|
|
188
203
|
const { selectionChange } = useDispatch( blockEditorStore );
|
|
@@ -435,19 +450,34 @@ export function RichTextWrapper(
|
|
|
435
450
|
);
|
|
436
451
|
}
|
|
437
452
|
|
|
438
|
-
|
|
453
|
+
// This is the private API for the RichText component.
|
|
454
|
+
// It allows access to all props, not just the public ones.
|
|
455
|
+
export const PrivateRichText = withDeprecations(
|
|
439
456
|
forwardRef( RichTextWrapper )
|
|
440
457
|
);
|
|
441
458
|
|
|
442
|
-
|
|
443
|
-
|
|
459
|
+
PrivateRichText.Content = Content;
|
|
460
|
+
PrivateRichText.isEmpty = ( value ) => {
|
|
444
461
|
return ! value || value.length === 0;
|
|
445
462
|
};
|
|
446
463
|
|
|
464
|
+
// This is the public API for the RichText component.
|
|
465
|
+
// We wrap the PrivateRichText component to hide some props from the public API.
|
|
447
466
|
/**
|
|
448
467
|
* @see https://github.com/WordPress/gutenberg/blob/HEAD/packages/block-editor/src/components/rich-text/README.md
|
|
449
468
|
*/
|
|
450
|
-
|
|
469
|
+
const PublicForwardedRichTextContainer = forwardRef( ( props, ref ) => {
|
|
470
|
+
return (
|
|
471
|
+
<PrivateRichText ref={ ref } { ...props } disableEditing={ false } />
|
|
472
|
+
);
|
|
473
|
+
} );
|
|
474
|
+
|
|
475
|
+
PublicForwardedRichTextContainer.Content = Content;
|
|
476
|
+
PublicForwardedRichTextContainer.isEmpty = ( value ) => {
|
|
477
|
+
return ! value || value.length === 0;
|
|
478
|
+
};
|
|
479
|
+
|
|
480
|
+
export default PublicForwardedRichTextContainer;
|
|
451
481
|
export { RichTextShortcut } from './shortcut';
|
|
452
482
|
export { RichTextToolbarButton } from './toolbar-button';
|
|
453
483
|
export { __unstableRichTextInputEvent } from './input-event';
|
|
@@ -21,6 +21,10 @@ export function useEnter( props ) {
|
|
|
21
21
|
propsRef.current = props;
|
|
22
22
|
return useRefEffect( ( element ) => {
|
|
23
23
|
function onKeyDown( event ) {
|
|
24
|
+
if ( event.target.contentEditable !== 'true' ) {
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
|
|
24
28
|
if ( event.defaultPrevented ) {
|
|
25
29
|
return;
|
|
26
30
|
}
|
|
@@ -58,13 +58,35 @@ export function usePasteHandler( props ) {
|
|
|
58
58
|
const isInternal =
|
|
59
59
|
event.clipboardData.getData( 'rich-text' ) === 'true';
|
|
60
60
|
|
|
61
|
+
function pasteInline( content ) {
|
|
62
|
+
const transformed = formatTypes.reduce(
|
|
63
|
+
( accumulator, { __unstablePasteRule } ) => {
|
|
64
|
+
// Only allow one transform.
|
|
65
|
+
if ( __unstablePasteRule && accumulator === value ) {
|
|
66
|
+
accumulator = __unstablePasteRule( value, {
|
|
67
|
+
html,
|
|
68
|
+
plainText,
|
|
69
|
+
} );
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
return accumulator;
|
|
73
|
+
},
|
|
74
|
+
value
|
|
75
|
+
);
|
|
76
|
+
if ( transformed !== value ) {
|
|
77
|
+
onChange( transformed );
|
|
78
|
+
} else {
|
|
79
|
+
const valueToInsert = create( { html: content } );
|
|
80
|
+
addActiveFormats( valueToInsert, value.activeFormats );
|
|
81
|
+
onChange( insert( value, valueToInsert ) );
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
61
85
|
// If the data comes from a rich text instance, we can directly use it
|
|
62
86
|
// without filtering the data. The filters are only meant for externally
|
|
63
87
|
// pasted content and remove inline styles.
|
|
64
88
|
if ( isInternal ) {
|
|
65
|
-
|
|
66
|
-
addActiveFormats( pastedValue, value.activeFormats );
|
|
67
|
-
onChange( insert( value, pastedValue ) );
|
|
89
|
+
pasteInline( html );
|
|
68
90
|
return;
|
|
69
91
|
}
|
|
70
92
|
|
|
@@ -135,28 +157,7 @@ export function usePasteHandler( props ) {
|
|
|
135
157
|
} );
|
|
136
158
|
|
|
137
159
|
if ( typeof content === 'string' ) {
|
|
138
|
-
|
|
139
|
-
( accumlator, { __unstablePasteRule } ) => {
|
|
140
|
-
// Only allow one transform.
|
|
141
|
-
if ( __unstablePasteRule && accumlator === value ) {
|
|
142
|
-
accumlator = __unstablePasteRule( value, {
|
|
143
|
-
html,
|
|
144
|
-
plainText,
|
|
145
|
-
} );
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
return accumlator;
|
|
149
|
-
},
|
|
150
|
-
value
|
|
151
|
-
);
|
|
152
|
-
|
|
153
|
-
if ( transformed !== value ) {
|
|
154
|
-
onChange( transformed );
|
|
155
|
-
} else {
|
|
156
|
-
const valueToInsert = create( { html: content } );
|
|
157
|
-
addActiveFormats( valueToInsert, value.activeFormats );
|
|
158
|
-
onChange( insert( value, valueToInsert ) );
|
|
159
|
-
}
|
|
160
|
+
pasteInline( content );
|
|
160
161
|
} else if ( content.length > 0 ) {
|
|
161
162
|
if ( onReplace && isEmpty( value ) ) {
|
|
162
163
|
onReplace( content, content.length - 1, -1 );
|
|
@@ -58,6 +58,7 @@
|
|
|
58
58
|
text-overflow: ellipsis;
|
|
59
59
|
white-space: nowrap;
|
|
60
60
|
margin-right: $grid-unit-10;
|
|
61
|
+
min-width: 150px;
|
|
61
62
|
// Avoids the popover from growing too wide when the URL is long.
|
|
62
63
|
// See https://github.com/WordPress/gutenberg/issues/58599
|
|
63
64
|
max-width: $modal-min-width;
|
package/src/hooks/background.js
CHANGED
|
@@ -374,11 +374,14 @@ function backgroundSizeHelpText( value ) {
|
|
|
374
374
|
}
|
|
375
375
|
|
|
376
376
|
export const coordsToBackgroundPosition = ( value ) => {
|
|
377
|
-
if ( ! value || isNaN( value.x )
|
|
377
|
+
if ( ! value || ( isNaN( value.x ) && isNaN( value.y ) ) ) {
|
|
378
378
|
return undefined;
|
|
379
379
|
}
|
|
380
380
|
|
|
381
|
-
|
|
381
|
+
const x = isNaN( value.x ) ? 0.5 : value.x;
|
|
382
|
+
const y = isNaN( value.y ) ? 0.5 : value.y;
|
|
383
|
+
|
|
384
|
+
return `${ x * 100 }% ${ y * 100 }%`;
|
|
382
385
|
};
|
|
383
386
|
|
|
384
387
|
export const backgroundPositionToCoords = ( value ) => {
|
package/src/hooks/block-hooks.js
CHANGED
|
@@ -35,12 +35,12 @@ function BlockHooksControlPure( { name, clientId } ) {
|
|
|
35
35
|
|
|
36
36
|
const { blockIndex, rootClientId, innerBlocksLength } = useSelect(
|
|
37
37
|
( select ) => {
|
|
38
|
-
const {
|
|
38
|
+
const { getBlocks, getBlockIndex, getBlockRootClientId } =
|
|
39
39
|
select( blockEditorStore );
|
|
40
40
|
|
|
41
41
|
return {
|
|
42
42
|
blockIndex: getBlockIndex( clientId ),
|
|
43
|
-
innerBlocksLength:
|
|
43
|
+
innerBlocksLength: getBlocks( clientId )?.length,
|
|
44
44
|
rootClientId: getBlockRootClientId( clientId ),
|
|
45
45
|
};
|
|
46
46
|
},
|
|
@@ -49,7 +49,7 @@ function BlockHooksControlPure( { name, clientId } ) {
|
|
|
49
49
|
|
|
50
50
|
const hookedBlockClientIds = useSelect(
|
|
51
51
|
( select ) => {
|
|
52
|
-
const {
|
|
52
|
+
const { getBlocks, getGlobalBlockCount } =
|
|
53
53
|
select( blockEditorStore );
|
|
54
54
|
|
|
55
55
|
const _hookedBlockClientIds = hookedBlocksForCurrentBlock.reduce(
|
|
@@ -69,7 +69,7 @@ function BlockHooksControlPure( { name, clientId } ) {
|
|
|
69
69
|
// Any of the current block's siblings (with the right block type) qualifies
|
|
70
70
|
// as a hooked block (inserted `before` or `after` the current one), as the block
|
|
71
71
|
// might've been automatically inserted and then moved around a bit by the user.
|
|
72
|
-
candidates =
|
|
72
|
+
candidates = getBlocks( rootClientId );
|
|
73
73
|
break;
|
|
74
74
|
|
|
75
75
|
case 'first_child':
|
|
@@ -77,7 +77,7 @@ function BlockHooksControlPure( { name, clientId } ) {
|
|
|
77
77
|
// Any of the current block's child blocks (with the right block type) qualifies
|
|
78
78
|
// as a hooked first or last child block, as the block might've been automatically
|
|
79
79
|
// inserted and then moved around a bit by the user.
|
|
80
|
-
candidates =
|
|
80
|
+
candidates = getBlocks( clientId );
|
|
81
81
|
break;
|
|
82
82
|
}
|
|
83
83
|
|
|
@@ -161,6 +161,11 @@ function BlockHooksControlPure( { name, clientId } ) {
|
|
|
161
161
|
title={ __( 'Plugins' ) }
|
|
162
162
|
initialOpen={ true }
|
|
163
163
|
>
|
|
164
|
+
<p className="block-editor-hooks__block-hooks-helptext">
|
|
165
|
+
{ __(
|
|
166
|
+
'Manage the inclusion of blocks added automatically by plugins.'
|
|
167
|
+
) }
|
|
168
|
+
</p>
|
|
164
169
|
{ Object.keys( groupedHookedBlocks ).map( ( vendor ) => {
|
|
165
170
|
return (
|
|
166
171
|
<Fragment key={ vendor }>
|