@wordpress/block-editor 8.5.0 → 8.5.3
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-alignment-control/ui.js +1 -1
- package/build/components/block-alignment-control/ui.js.map +1 -1
- package/build/components/block-content-overlay/index.js +13 -4
- package/build/components/block-content-overlay/index.js.map +1 -1
- package/build/components/block-lock/index.js +8 -0
- package/build/components/block-lock/index.js.map +1 -1
- package/build/components/block-lock/menu-item.js +5 -20
- package/build/components/block-lock/menu-item.js.map +1 -1
- package/build/components/block-lock/modal.js +33 -12
- package/build/components/block-lock/modal.js.map +1 -1
- package/build/components/block-lock/toolbar.js +7 -20
- package/build/components/block-lock/toolbar.js.map +1 -1
- package/build/components/block-lock/use-block-lock.js +50 -0
- package/build/components/block-lock/use-block-lock.js.map +1 -0
- package/build/components/block-pattern-setup/index.js +37 -22
- package/build/components/block-pattern-setup/index.js.map +1 -1
- package/build/components/block-pattern-setup/setup-toolbar.js +1 -1
- package/build/components/block-pattern-setup/setup-toolbar.js.map +1 -1
- package/build/components/block-preview/auto.js +6 -3
- package/build/components/block-preview/auto.js.map +1 -1
- package/build/components/block-preview/index.js +4 -2
- package/build/components/block-preview/index.js.map +1 -1
- package/build/components/block-switcher/index.js +7 -2
- package/build/components/block-switcher/index.js.map +1 -1
- package/build/components/copy-handler/index.js +44 -9
- package/build/components/copy-handler/index.js.map +1 -1
- package/build/components/link-control/index.js +6 -7
- package/build/components/link-control/index.js.map +1 -1
- package/build/components/list-view/block-select-button.js +4 -10
- package/build/components/list-view/block-select-button.js.map +1 -1
- package/build/components/list-view/block.js +13 -2
- package/build/components/list-view/block.js.map +1 -1
- package/build/components/writing-flow/use-selection-observer.js +7 -1
- package/build/components/writing-flow/use-selection-observer.js.map +1 -1
- package/build/hooks/duotone.js +66 -16
- package/build/hooks/duotone.js.map +1 -1
- package/build/hooks/index.js +7 -1
- package/build/hooks/index.js.map +1 -1
- package/build/index.js +7 -0
- package/build/index.js.map +1 -1
- package/build/store/actions.js +22 -29
- package/build/store/actions.js.map +1 -1
- package/build/store/selectors.js +122 -3
- package/build/store/selectors.js.map +1 -1
- package/build/store/utils.js +27 -0
- package/build/store/utils.js.map +1 -0
- package/build-module/components/block-alignment-control/ui.js +2 -2
- package/build-module/components/block-alignment-control/ui.js.map +1 -1
- package/build-module/components/block-content-overlay/index.js +13 -4
- package/build-module/components/block-content-overlay/index.js.map +1 -1
- package/build-module/components/block-lock/index.js +1 -0
- package/build-module/components/block-lock/index.js.map +1 -1
- package/build-module/components/block-lock/menu-item.js +4 -18
- package/build-module/components/block-lock/menu-item.js.map +1 -1
- package/build-module/components/block-lock/modal.js +31 -12
- package/build-module/components/block-lock/modal.js.map +1 -1
- package/build-module/components/block-lock/toolbar.js +6 -18
- package/build-module/components/block-lock/toolbar.js.map +1 -1
- package/build-module/components/block-lock/use-block-lock.js +41 -0
- package/build-module/components/block-lock/use-block-lock.js.map +1 -0
- package/build-module/components/block-pattern-setup/index.js +39 -24
- package/build-module/components/block-pattern-setup/index.js.map +1 -1
- package/build-module/components/block-pattern-setup/setup-toolbar.js +1 -1
- package/build-module/components/block-pattern-setup/setup-toolbar.js.map +1 -1
- package/build-module/components/block-preview/auto.js +6 -3
- package/build-module/components/block-preview/auto.js.map +1 -1
- package/build-module/components/block-preview/index.js +4 -2
- package/build-module/components/block-preview/index.js.map +1 -1
- package/build-module/components/block-switcher/index.js +7 -2
- package/build-module/components/block-switcher/index.js.map +1 -1
- package/build-module/components/copy-handler/index.js +44 -9
- package/build-module/components/copy-handler/index.js.map +1 -1
- package/build-module/components/link-control/index.js +6 -7
- package/build-module/components/link-control/index.js.map +1 -1
- package/build-module/components/list-view/block-select-button.js +4 -9
- package/build-module/components/list-view/block-select-button.js.map +1 -1
- package/build-module/components/list-view/block.js +13 -2
- package/build-module/components/list-view/block.js.map +1 -1
- package/build-module/components/writing-flow/use-selection-observer.js +7 -1
- package/build-module/components/writing-flow/use-selection-observer.js.map +1 -1
- package/build-module/hooks/duotone.js +63 -16
- package/build-module/hooks/duotone.js.map +1 -1
- package/build-module/hooks/index.js +1 -0
- package/build-module/hooks/index.js.map +1 -1
- package/build-module/index.js +1 -1
- package/build-module/index.js.map +1 -1
- package/build-module/store/actions.js +5 -14
- package/build-module/store/actions.js.map +1 -1
- package/build-module/store/selectors.js +112 -2
- package/build-module/store/selectors.js.map +1 -1
- package/build-module/store/utils.js +20 -0
- package/build-module/store/utils.js.map +1 -0
- package/build-style/style-rtl.css +35 -28
- package/build-style/style.css +35 -28
- package/package.json +28 -28
- package/src/components/block-alignment-control/ui.js +2 -2
- package/src/components/block-content-overlay/index.js +19 -2
- package/src/components/block-content-overlay/style.scss +0 -1
- package/src/components/block-lock/index.js +1 -0
- package/src/components/block-lock/menu-item.js +3 -23
- package/src/components/block-lock/modal.js +37 -13
- package/src/components/block-lock/style.scss +1 -2
- package/src/components/block-lock/toolbar.js +4 -21
- package/src/components/block-lock/use-block-lock.js +45 -0
- package/src/components/block-pattern-setup/index.js +84 -59
- package/src/components/block-pattern-setup/setup-toolbar.js +3 -1
- package/src/components/block-pattern-setup/style.scss +32 -26
- package/src/components/block-preview/auto.js +10 -1
- package/src/components/block-preview/index.js +2 -0
- package/src/components/block-switcher/index.js +13 -1
- package/src/components/block-switcher/style.scss +7 -3
- package/src/components/block-switcher/test/__snapshots__/index.js.snap +15 -13
- package/src/components/copy-handler/index.js +52 -10
- package/src/components/link-control/index.js +5 -5
- package/src/components/list-view/block-select-button.js +2 -10
- package/src/components/list-view/block.js +16 -7
- package/src/components/writing-flow/use-selection-observer.js +7 -0
- package/src/hooks/duotone.js +98 -62
- package/src/hooks/index.js +1 -0
- package/src/index.js +1 -0
- package/src/store/actions.js +5 -13
- package/src/store/selectors.js +148 -2
- package/src/store/utils.js +19 -0
|
@@ -8,7 +8,6 @@ import classnames from 'classnames';
|
|
|
8
8
|
*/
|
|
9
9
|
import { Button } from '@wordpress/components';
|
|
10
10
|
import { forwardRef } from '@wordpress/element';
|
|
11
|
-
import { useSelect } from '@wordpress/data';
|
|
12
11
|
import { Icon, lock } from '@wordpress/icons';
|
|
13
12
|
import { SPACE, ENTER } from '@wordpress/keycodes';
|
|
14
13
|
|
|
@@ -19,7 +18,7 @@ import BlockIcon from '../block-icon';
|
|
|
19
18
|
import useBlockDisplayInformation from '../use-block-display-information';
|
|
20
19
|
import BlockTitle from '../block-title';
|
|
21
20
|
import ListViewExpander from './expander';
|
|
22
|
-
import {
|
|
21
|
+
import { useBlockLock } from '../block-lock';
|
|
23
22
|
|
|
24
23
|
function ListViewBlockSelectButton(
|
|
25
24
|
{
|
|
@@ -36,14 +35,7 @@ function ListViewBlockSelectButton(
|
|
|
36
35
|
ref
|
|
37
36
|
) {
|
|
38
37
|
const blockInformation = useBlockDisplayInformation( clientId );
|
|
39
|
-
const isLocked =
|
|
40
|
-
( select ) => {
|
|
41
|
-
const { canMoveBlock, canRemoveBlock } = select( blockEditorStore );
|
|
42
|
-
|
|
43
|
-
return ! canMoveBlock( clientId ) || ! canRemoveBlock( clientId );
|
|
44
|
-
},
|
|
45
|
-
[ clientId ]
|
|
46
|
-
);
|
|
38
|
+
const { isLocked } = useBlockLock( clientId );
|
|
47
39
|
|
|
48
40
|
// The `href` attribute triggers the browser's native HTML drag operations.
|
|
49
41
|
// When the link is dragged, the element's outerHTML is set in DataTransfer object as text/html.
|
|
@@ -36,6 +36,7 @@ import { useListViewContext } from './context';
|
|
|
36
36
|
import { getBlockPositionDescription } from './utils';
|
|
37
37
|
import { store as blockEditorStore } from '../../store';
|
|
38
38
|
import useBlockDisplayInformation from '../use-block-display-information';
|
|
39
|
+
import { useBlockLock } from '../block-lock';
|
|
39
40
|
|
|
40
41
|
function ListViewBlock( {
|
|
41
42
|
block,
|
|
@@ -65,6 +66,7 @@ function ListViewBlock( {
|
|
|
65
66
|
const { toggleBlockHighlight } = useDispatch( blockEditorStore );
|
|
66
67
|
|
|
67
68
|
const blockInformation = useBlockDisplayInformation( clientId );
|
|
69
|
+
const { isLocked } = useBlockLock( clientId );
|
|
68
70
|
const instanceId = useInstanceId( ListViewBlock );
|
|
69
71
|
const descriptionId = `list-view-block-select-button__${ instanceId }`;
|
|
70
72
|
const blockPositionDescription = getBlockPositionDescription(
|
|
@@ -73,13 +75,20 @@ function ListViewBlock( {
|
|
|
73
75
|
level
|
|
74
76
|
);
|
|
75
77
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
78
|
+
let blockAriaLabel = __( 'Link' );
|
|
79
|
+
if ( blockInformation ) {
|
|
80
|
+
blockAriaLabel = isLocked
|
|
81
|
+
? sprintf(
|
|
82
|
+
// translators: %s: The title of the block. This string indicates a link to select the locked block.
|
|
83
|
+
__( '%s link (locked)' ),
|
|
84
|
+
blockInformation.title
|
|
85
|
+
)
|
|
86
|
+
: sprintf(
|
|
87
|
+
// translators: %s: The title of the block. This string indicates a link to select the block.
|
|
88
|
+
__( '%s link' ),
|
|
89
|
+
blockInformation.title
|
|
90
|
+
);
|
|
91
|
+
}
|
|
83
92
|
|
|
84
93
|
const settingsAriaLabel = blockInformation
|
|
85
94
|
? sprintf(
|
|
@@ -98,6 +98,13 @@ export default function useSelectionObserver() {
|
|
|
98
98
|
const endClientId = getBlockClientId(
|
|
99
99
|
extractSelectionEndNode( selection )
|
|
100
100
|
);
|
|
101
|
+
|
|
102
|
+
// If the selection did not involve a block, return early.
|
|
103
|
+
if ( clientId === undefined && endClientId === undefined ) {
|
|
104
|
+
setContentEditableWrapper( node, false );
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
|
|
101
108
|
const isSingularSelection = clientId === endClientId;
|
|
102
109
|
|
|
103
110
|
if ( isSingularSelection ) {
|
package/src/hooks/duotone.js
CHANGED
|
@@ -60,82 +60,109 @@ export function getValuesFromColors( colors = [] ) {
|
|
|
60
60
|
*/
|
|
61
61
|
|
|
62
62
|
/**
|
|
63
|
-
*
|
|
63
|
+
* Stylesheet for rendering the duotone filter.
|
|
64
64
|
*
|
|
65
65
|
* @param {Object} props Duotone props.
|
|
66
66
|
* @param {string} props.selector Selector to apply the filter to.
|
|
67
67
|
* @param {string} props.id Unique id for this duotone filter.
|
|
68
|
-
* @param {Values} props.values R, G, B, and A values to filter with.
|
|
69
68
|
*
|
|
70
69
|
* @return {WPElement} Duotone element.
|
|
71
70
|
*/
|
|
72
|
-
function
|
|
73
|
-
const
|
|
71
|
+
function DuotoneStylesheet( { selector, id } ) {
|
|
72
|
+
const css = `
|
|
74
73
|
${ selector } {
|
|
75
74
|
filter: url( #${ id } );
|
|
76
75
|
}
|
|
77
76
|
`;
|
|
77
|
+
return <style>{ css }</style>;
|
|
78
|
+
}
|
|
78
79
|
|
|
80
|
+
/**
|
|
81
|
+
* SVG for rendering the duotone filter.
|
|
82
|
+
*
|
|
83
|
+
* @param {Object} props Duotone props.
|
|
84
|
+
* @param {string} props.id Unique id for this duotone filter.
|
|
85
|
+
* @param {Values} props.values R, G, B, and A values to filter with.
|
|
86
|
+
*
|
|
87
|
+
* @return {WPElement} Duotone element.
|
|
88
|
+
*/
|
|
89
|
+
function DuotoneFilter( { id, values } ) {
|
|
79
90
|
return (
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
>
|
|
95
|
-
<
|
|
96
|
-
<
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
91
|
+
<SVG
|
|
92
|
+
xmlnsXlink="http://www.w3.org/1999/xlink"
|
|
93
|
+
viewBox="0 0 0 0"
|
|
94
|
+
width="0"
|
|
95
|
+
height="0"
|
|
96
|
+
focusable="false"
|
|
97
|
+
role="none"
|
|
98
|
+
style={ {
|
|
99
|
+
visibility: 'hidden',
|
|
100
|
+
position: 'absolute',
|
|
101
|
+
left: '-9999px',
|
|
102
|
+
overflow: 'hidden',
|
|
103
|
+
} }
|
|
104
|
+
>
|
|
105
|
+
<defs>
|
|
106
|
+
<filter id={ id }>
|
|
107
|
+
<feColorMatrix
|
|
108
|
+
// Use sRGB instead of linearRGB so transparency looks correct.
|
|
109
|
+
colorInterpolationFilters="sRGB"
|
|
110
|
+
type="matrix"
|
|
111
|
+
// Use perceptual brightness to convert to grayscale.
|
|
112
|
+
values="
|
|
113
|
+
.299 .587 .114 0 0
|
|
114
|
+
.299 .587 .114 0 0
|
|
115
|
+
.299 .587 .114 0 0
|
|
116
|
+
.299 .587 .114 0 0
|
|
117
|
+
"
|
|
118
|
+
/>
|
|
119
|
+
<feComponentTransfer
|
|
120
|
+
// Use sRGB instead of linearRGB to be consistent with how CSS gradients work.
|
|
121
|
+
colorInterpolationFilters="sRGB"
|
|
122
|
+
>
|
|
123
|
+
<feFuncR
|
|
124
|
+
type="table"
|
|
125
|
+
tableValues={ values.r.join( ' ' ) }
|
|
126
|
+
/>
|
|
127
|
+
<feFuncG
|
|
128
|
+
type="table"
|
|
129
|
+
tableValues={ values.g.join( ' ' ) }
|
|
130
|
+
/>
|
|
131
|
+
<feFuncB
|
|
132
|
+
type="table"
|
|
133
|
+
tableValues={ values.b.join( ' ' ) }
|
|
108
134
|
/>
|
|
109
|
-
<
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
>
|
|
113
|
-
<feFuncR
|
|
114
|
-
type="table"
|
|
115
|
-
tableValues={ values.r.join( ' ' ) }
|
|
116
|
-
/>
|
|
117
|
-
<feFuncG
|
|
118
|
-
type="table"
|
|
119
|
-
tableValues={ values.g.join( ' ' ) }
|
|
120
|
-
/>
|
|
121
|
-
<feFuncB
|
|
122
|
-
type="table"
|
|
123
|
-
tableValues={ values.b.join( ' ' ) }
|
|
124
|
-
/>
|
|
125
|
-
<feFuncA
|
|
126
|
-
type="table"
|
|
127
|
-
tableValues={ values.a.join( ' ' ) }
|
|
128
|
-
/>
|
|
129
|
-
</feComponentTransfer>
|
|
130
|
-
<feComposite
|
|
131
|
-
// Re-mask the image with the original transparency since the feColorMatrix above loses that information.
|
|
132
|
-
in2="SourceGraphic"
|
|
133
|
-
operator="in"
|
|
135
|
+
<feFuncA
|
|
136
|
+
type="table"
|
|
137
|
+
tableValues={ values.a.join( ' ' ) }
|
|
134
138
|
/>
|
|
135
|
-
</
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
+
</feComponentTransfer>
|
|
140
|
+
<feComposite
|
|
141
|
+
// Re-mask the image with the original transparency since the feColorMatrix above loses that information.
|
|
142
|
+
in2="SourceGraphic"
|
|
143
|
+
operator="in"
|
|
144
|
+
/>
|
|
145
|
+
</filter>
|
|
146
|
+
</defs>
|
|
147
|
+
</SVG>
|
|
148
|
+
);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* SVG and stylesheet needed for rendering the duotone filter.
|
|
153
|
+
*
|
|
154
|
+
* @param {Object} props Duotone props.
|
|
155
|
+
* @param {string} props.selector Selector to apply the filter to.
|
|
156
|
+
* @param {string} props.id Unique id for this duotone filter.
|
|
157
|
+
* @param {Values} props.values R, G, B, and A values to filter with.
|
|
158
|
+
*
|
|
159
|
+
* @return {WPElement} Duotone element.
|
|
160
|
+
*/
|
|
161
|
+
function InlineDuotone( { selector, id, values } ) {
|
|
162
|
+
return (
|
|
163
|
+
<>
|
|
164
|
+
<DuotoneFilter id={ id } values={ values } />
|
|
165
|
+
<DuotoneStylesheet id={ id } selector={ selector } />
|
|
139
166
|
</>
|
|
140
167
|
);
|
|
141
168
|
}
|
|
@@ -321,7 +348,7 @@ const withDuotoneStyles = createHigherOrderComponent(
|
|
|
321
348
|
<>
|
|
322
349
|
{ element &&
|
|
323
350
|
createPortal(
|
|
324
|
-
<
|
|
351
|
+
<InlineDuotone
|
|
325
352
|
selector={ selectorsGroup }
|
|
326
353
|
id={ id }
|
|
327
354
|
values={ getValuesFromColors( values ) }
|
|
@@ -335,6 +362,15 @@ const withDuotoneStyles = createHigherOrderComponent(
|
|
|
335
362
|
'withDuotoneStyles'
|
|
336
363
|
);
|
|
337
364
|
|
|
365
|
+
export function PresetDuotoneFilter( { preset } ) {
|
|
366
|
+
return (
|
|
367
|
+
<DuotoneFilter
|
|
368
|
+
id={ `wp-duotone-${ preset.slug }` }
|
|
369
|
+
values={ getValuesFromColors( preset.colors ) }
|
|
370
|
+
/>
|
|
371
|
+
);
|
|
372
|
+
}
|
|
373
|
+
|
|
338
374
|
addFilter(
|
|
339
375
|
'blocks.registerBlockType',
|
|
340
376
|
'core/editor/duotone/add-attributes',
|
package/src/hooks/index.js
CHANGED
|
@@ -19,3 +19,4 @@ export { getBorderClassesAndStyles, useBorderProps } from './use-border-props';
|
|
|
19
19
|
export { getColorClassesAndStyles, useColorProps } from './use-color-props';
|
|
20
20
|
export { getSpacingClassesAndStyles } from './use-spacing-props';
|
|
21
21
|
export { useCachedTruthy } from './use-cached-truthy';
|
|
22
|
+
export { PresetDuotoneFilter } from './duotone';
|
package/src/index.js
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
import './hooks';
|
|
5
5
|
export {
|
|
6
|
+
PresetDuotoneFilter as __unstablePresetDuotoneFilter,
|
|
6
7
|
getBorderClassesAndStyles as __experimentalGetBorderClassesAndStyles,
|
|
7
8
|
useBorderProps as __experimentalUseBorderProps,
|
|
8
9
|
getColorClassesAndStyles as __experimentalGetColorClassesAndStyles,
|
package/src/store/actions.js
CHANGED
|
@@ -22,6 +22,11 @@ import { __, _n, sprintf } from '@wordpress/i18n';
|
|
|
22
22
|
import { create, insert, remove, toHTMLString } from '@wordpress/rich-text';
|
|
23
23
|
import deprecated from '@wordpress/deprecated';
|
|
24
24
|
|
|
25
|
+
/**
|
|
26
|
+
* Internal dependencies
|
|
27
|
+
*/
|
|
28
|
+
import { mapRichTextSettings } from './utils';
|
|
29
|
+
|
|
25
30
|
/**
|
|
26
31
|
* Action which will insert a default block insert action if there
|
|
27
32
|
* are no other blocks at the root of the editor. This action should be used
|
|
@@ -667,19 +672,6 @@ export const synchronizeTemplate = () => ( { select, dispatch } ) => {
|
|
|
667
672
|
dispatch.resetBlocks( updatedBlockList );
|
|
668
673
|
};
|
|
669
674
|
|
|
670
|
-
function mapRichTextSettings( attributeDefinition ) {
|
|
671
|
-
const {
|
|
672
|
-
multiline: multilineTag,
|
|
673
|
-
__unstableMultilineWrapperTags: multilineWrapperTags,
|
|
674
|
-
__unstablePreserveWhiteSpace: preserveWhiteSpace,
|
|
675
|
-
} = attributeDefinition;
|
|
676
|
-
return {
|
|
677
|
-
multilineTag,
|
|
678
|
-
multilineWrapperTags,
|
|
679
|
-
preserveWhiteSpace,
|
|
680
|
-
};
|
|
681
|
-
}
|
|
682
|
-
|
|
683
675
|
/**
|
|
684
676
|
* Delete the current selection.
|
|
685
677
|
*
|
package/src/store/selectors.js
CHANGED
|
@@ -33,6 +33,12 @@ import { Platform } from '@wordpress/element';
|
|
|
33
33
|
import { applyFilters } from '@wordpress/hooks';
|
|
34
34
|
import { symbol } from '@wordpress/icons';
|
|
35
35
|
import { __ } from '@wordpress/i18n';
|
|
36
|
+
import { create, remove, toHTMLString } from '@wordpress/rich-text';
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Internal dependencies
|
|
40
|
+
*/
|
|
41
|
+
import { mapRichTextSettings } from './utils';
|
|
36
42
|
|
|
37
43
|
/**
|
|
38
44
|
* A block selection object.
|
|
@@ -926,6 +932,25 @@ export function __unstableIsFullySelected( state ) {
|
|
|
926
932
|
);
|
|
927
933
|
}
|
|
928
934
|
|
|
935
|
+
/**
|
|
936
|
+
* Returns true if the selection is collapsed.
|
|
937
|
+
*
|
|
938
|
+
* @param {Object} state Editor state.
|
|
939
|
+
*
|
|
940
|
+
* @return {boolean} Whether the selection is collapsed.
|
|
941
|
+
*/
|
|
942
|
+
export function __unstableIsSelectionCollapsed( state ) {
|
|
943
|
+
const selectionAnchor = getSelectionStart( state );
|
|
944
|
+
const selectionFocus = getSelectionEnd( state );
|
|
945
|
+
return (
|
|
946
|
+
!! selectionAnchor &&
|
|
947
|
+
!! selectionFocus &&
|
|
948
|
+
selectionAnchor.clientId === selectionFocus.clientId &&
|
|
949
|
+
selectionAnchor.attributeKey === selectionFocus.attributeKey &&
|
|
950
|
+
selectionAnchor.offset === selectionFocus.offset
|
|
951
|
+
);
|
|
952
|
+
}
|
|
953
|
+
|
|
929
954
|
/**
|
|
930
955
|
* Check whether the selection is mergeable.
|
|
931
956
|
*
|
|
@@ -1004,6 +1029,107 @@ export function __unstableIsSelectionMergeable( state, isForward ) {
|
|
|
1004
1029
|
return blocksToMerge && blocksToMerge.length;
|
|
1005
1030
|
}
|
|
1006
1031
|
|
|
1032
|
+
/**
|
|
1033
|
+
* Get partial selected blocks with their content updated
|
|
1034
|
+
* based on the selection.
|
|
1035
|
+
*
|
|
1036
|
+
* @param {Object} state Editor state.
|
|
1037
|
+
*
|
|
1038
|
+
* @return {Object[]} Updated partial selected blocks.
|
|
1039
|
+
*/
|
|
1040
|
+
export const __unstableGetSelectedBlocksWithPartialSelection = ( state ) => {
|
|
1041
|
+
const selectionAnchor = getSelectionStart( state );
|
|
1042
|
+
const selectionFocus = getSelectionEnd( state );
|
|
1043
|
+
|
|
1044
|
+
if ( selectionAnchor.clientId === selectionFocus.clientId ) {
|
|
1045
|
+
return EMPTY_ARRAY;
|
|
1046
|
+
}
|
|
1047
|
+
|
|
1048
|
+
// Can't split if the selection is not set.
|
|
1049
|
+
if (
|
|
1050
|
+
! selectionAnchor.attributeKey ||
|
|
1051
|
+
! selectionFocus.attributeKey ||
|
|
1052
|
+
typeof selectionAnchor.offset === 'undefined' ||
|
|
1053
|
+
typeof selectionFocus.offset === 'undefined'
|
|
1054
|
+
) {
|
|
1055
|
+
return EMPTY_ARRAY;
|
|
1056
|
+
}
|
|
1057
|
+
|
|
1058
|
+
const anchorRootClientId = getBlockRootClientId(
|
|
1059
|
+
state,
|
|
1060
|
+
selectionAnchor.clientId
|
|
1061
|
+
);
|
|
1062
|
+
const focusRootClientId = getBlockRootClientId(
|
|
1063
|
+
state,
|
|
1064
|
+
selectionFocus.clientId
|
|
1065
|
+
);
|
|
1066
|
+
|
|
1067
|
+
// It's not splittable if the selection doesn't start and end in the same
|
|
1068
|
+
// block list. Maybe in the future it should be allowed.
|
|
1069
|
+
if ( anchorRootClientId !== focusRootClientId ) {
|
|
1070
|
+
return EMPTY_ARRAY;
|
|
1071
|
+
}
|
|
1072
|
+
|
|
1073
|
+
const blockOrder = getBlockOrder( state, anchorRootClientId );
|
|
1074
|
+
const anchorIndex = blockOrder.indexOf( selectionAnchor.clientId );
|
|
1075
|
+
const focusIndex = blockOrder.indexOf( selectionFocus.clientId );
|
|
1076
|
+
|
|
1077
|
+
// Reassign selection start and end based on order.
|
|
1078
|
+
const [ selectionStart, selectionEnd ] =
|
|
1079
|
+
anchorIndex > focusIndex
|
|
1080
|
+
? [ selectionFocus, selectionAnchor ]
|
|
1081
|
+
: [ selectionAnchor, selectionFocus ];
|
|
1082
|
+
|
|
1083
|
+
const blockA = getBlock( state, selectionStart.clientId );
|
|
1084
|
+
const blockAType = getBlockType( blockA.name );
|
|
1085
|
+
|
|
1086
|
+
const blockB = getBlock( state, selectionEnd.clientId );
|
|
1087
|
+
const blockBType = getBlockType( blockB.name );
|
|
1088
|
+
|
|
1089
|
+
const htmlA = blockA.attributes[ selectionStart.attributeKey ];
|
|
1090
|
+
const htmlB = blockB.attributes[ selectionEnd.attributeKey ];
|
|
1091
|
+
|
|
1092
|
+
const attributeDefinitionA =
|
|
1093
|
+
blockAType.attributes[ selectionStart.attributeKey ];
|
|
1094
|
+
const attributeDefinitionB =
|
|
1095
|
+
blockBType.attributes[ selectionEnd.attributeKey ];
|
|
1096
|
+
|
|
1097
|
+
let valueA = create( {
|
|
1098
|
+
html: htmlA,
|
|
1099
|
+
...mapRichTextSettings( attributeDefinitionA ),
|
|
1100
|
+
} );
|
|
1101
|
+
let valueB = create( {
|
|
1102
|
+
html: htmlB,
|
|
1103
|
+
...mapRichTextSettings( attributeDefinitionB ),
|
|
1104
|
+
} );
|
|
1105
|
+
|
|
1106
|
+
valueA = remove( valueA, 0, selectionStart.offset );
|
|
1107
|
+
valueB = remove( valueB, selectionEnd.offset, valueB.text.length );
|
|
1108
|
+
|
|
1109
|
+
return [
|
|
1110
|
+
{
|
|
1111
|
+
...blockA,
|
|
1112
|
+
attributes: {
|
|
1113
|
+
...blockA.attributes,
|
|
1114
|
+
[ selectionStart.attributeKey ]: toHTMLString( {
|
|
1115
|
+
value: valueA,
|
|
1116
|
+
...mapRichTextSettings( attributeDefinitionA ),
|
|
1117
|
+
} ),
|
|
1118
|
+
},
|
|
1119
|
+
},
|
|
1120
|
+
{
|
|
1121
|
+
...blockB,
|
|
1122
|
+
attributes: {
|
|
1123
|
+
...blockB.attributes,
|
|
1124
|
+
[ selectionEnd.attributeKey ]: toHTMLString( {
|
|
1125
|
+
value: valueB,
|
|
1126
|
+
...mapRichTextSettings( attributeDefinitionB ),
|
|
1127
|
+
} ),
|
|
1128
|
+
},
|
|
1129
|
+
},
|
|
1130
|
+
];
|
|
1131
|
+
};
|
|
1132
|
+
|
|
1007
1133
|
/**
|
|
1008
1134
|
* Returns an array containing all block client IDs in the editor in the order
|
|
1009
1135
|
* they appear. Optionally accepts a root client ID of the block list for which
|
|
@@ -1504,7 +1630,7 @@ export function canRemoveBlock( state, clientId, rootClientId = null ) {
|
|
|
1504
1630
|
|
|
1505
1631
|
const { lock } = attributes;
|
|
1506
1632
|
const parentIsLocked = !! getTemplateLock( state, rootClientId );
|
|
1507
|
-
// If we don't have a lock on the blockType level, we
|
|
1633
|
+
// If we don't have a lock on the blockType level, we defer to the parent templateLock.
|
|
1508
1634
|
if ( lock === undefined || lock?.remove === undefined ) {
|
|
1509
1635
|
return ! parentIsLocked;
|
|
1510
1636
|
}
|
|
@@ -1545,7 +1671,7 @@ export function canMoveBlock( state, clientId, rootClientId = null ) {
|
|
|
1545
1671
|
|
|
1546
1672
|
const { lock } = attributes;
|
|
1547
1673
|
const parentIsLocked = getTemplateLock( state, rootClientId ) === 'all';
|
|
1548
|
-
// If we don't have a lock on the blockType level, we
|
|
1674
|
+
// If we don't have a lock on the blockType level, we defer to the parent templateLock.
|
|
1549
1675
|
if ( lock === undefined || lock?.move === undefined ) {
|
|
1550
1676
|
return ! parentIsLocked;
|
|
1551
1677
|
}
|
|
@@ -1569,6 +1695,26 @@ export function canMoveBlocks( state, clientIds, rootClientId = null ) {
|
|
|
1569
1695
|
);
|
|
1570
1696
|
}
|
|
1571
1697
|
|
|
1698
|
+
/**
|
|
1699
|
+
* Determines if the given block is allowed to be edited.
|
|
1700
|
+
*
|
|
1701
|
+
* @param {Object} state Editor state.
|
|
1702
|
+
* @param {string} clientId The block client Id.
|
|
1703
|
+
*
|
|
1704
|
+
* @return {boolean} Whether the given block is allowed to be edited.
|
|
1705
|
+
*/
|
|
1706
|
+
export function canEditBlock( state, clientId ) {
|
|
1707
|
+
const attributes = getBlockAttributes( state, clientId );
|
|
1708
|
+
if ( attributes === null ) {
|
|
1709
|
+
return true;
|
|
1710
|
+
}
|
|
1711
|
+
|
|
1712
|
+
const { lock } = attributes;
|
|
1713
|
+
|
|
1714
|
+
// When the edit is true, we cannot edit the block.
|
|
1715
|
+
return ! lock?.edit;
|
|
1716
|
+
}
|
|
1717
|
+
|
|
1572
1718
|
/**
|
|
1573
1719
|
* Determines if the given block type can be locked/unlocked by a user.
|
|
1574
1720
|
*
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Helper function that maps attribute definition properties to the
|
|
3
|
+
* ones used by RichText utils like `create, toHTMLString, etc..`.
|
|
4
|
+
*
|
|
5
|
+
* @param {Object} attributeDefinition A block's attribute definition object.
|
|
6
|
+
* @return {Object} The mapped object.
|
|
7
|
+
*/
|
|
8
|
+
export function mapRichTextSettings( attributeDefinition ) {
|
|
9
|
+
const {
|
|
10
|
+
multiline: multilineTag,
|
|
11
|
+
__unstableMultilineWrapperTags: multilineWrapperTags,
|
|
12
|
+
__unstablePreserveWhiteSpace: preserveWhiteSpace,
|
|
13
|
+
} = attributeDefinition;
|
|
14
|
+
return {
|
|
15
|
+
multilineTag,
|
|
16
|
+
multilineWrapperTags,
|
|
17
|
+
preserveWhiteSpace,
|
|
18
|
+
};
|
|
19
|
+
}
|