@wordpress/block-editor 9.3.0 → 9.4.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 +2 -0
- package/build/components/block-pattern-setup/index.js +3 -9
- package/build/components/block-pattern-setup/index.js.map +1 -1
- package/build/components/block-pattern-setup/setup-toolbar.js +3 -8
- package/build/components/block-pattern-setup/setup-toolbar.js.map +1 -1
- package/build/components/block-preview/auto.js +21 -5
- package/build/components/block-preview/auto.js.map +1 -1
- package/build/components/block-settings-menu/block-edit-visually-button.js +70 -0
- package/build/components/block-settings-menu/block-edit-visually-button.js.map +1 -0
- package/build/components/block-settings-menu/block-settings-dropdown.js +1 -1
- package/build/components/block-settings-menu/block-settings-dropdown.js.map +1 -1
- package/build/components/block-settings-menu/index.js +6 -2
- package/build/components/block-settings-menu/index.js.map +1 -1
- package/build/components/block-settings-menu-controls/index.js +4 -1
- package/build/components/block-settings-menu-controls/index.js.map +1 -1
- package/build/components/block-title/use-block-display-title.js +3 -10
- package/build/components/block-title/use-block-display-title.js.map +1 -1
- package/build/components/colors-gradients/dropdown.js +2 -1
- package/build/components/colors-gradients/dropdown.js.map +1 -1
- package/build/components/duotone/components.js +145 -0
- package/build/components/duotone/components.js.map +1 -0
- package/build/components/duotone/index.js +40 -0
- package/build/components/duotone/index.js.map +1 -0
- package/build/components/duotone/utils.js +38 -0
- package/build/components/duotone/utils.js.map +1 -0
- package/build/components/duotone-control/index.js +17 -5
- package/build/components/duotone-control/index.js.map +1 -1
- package/build/components/index.js +14 -0
- package/build/components/index.js.map +1 -1
- package/build/components/inserter/index.js +3 -3
- package/build/components/inserter/index.js.map +1 -1
- package/build/components/media-placeholder/index.js +1 -0
- package/build/components/media-placeholder/index.js.map +1 -1
- package/build/components/media-placeholder/index.native.js +4 -4
- package/build/components/media-placeholder/index.native.js.map +1 -1
- package/build/components/media-replace-flow/index.js +3 -7
- package/build/components/media-replace-flow/index.js.map +1 -1
- package/build/components/publish-date-time-picker/index.js +3 -0
- package/build/components/publish-date-time-picker/index.js.map +1 -1
- package/build/components/rich-text/use-input-rules.js +4 -13
- package/build/components/rich-text/use-input-rules.js.map +1 -1
- package/build/components/rich-text/use-paste-handler.js +20 -5
- package/build/components/rich-text/use-paste-handler.js.map +1 -1
- package/build/elements/index.js +11 -3
- package/build/elements/index.js.map +1 -1
- package/build/hooks/aria-label.js +71 -0
- package/build/hooks/aria-label.js.map +1 -0
- package/build/hooks/duotone.js +33 -160
- package/build/hooks/duotone.js.map +1 -1
- package/build/hooks/index.js +3 -7
- package/build/hooks/index.js.map +1 -1
- package/build/hooks/layout.js +6 -4
- package/build/hooks/layout.js.map +1 -1
- package/build/index.js +0 -7
- package/build/index.js.map +1 -1
- package/build/layouts/flex.js +2 -2
- package/build/layouts/flex.js.map +1 -1
- package/build/store/actions.js +10 -14
- package/build/store/actions.js.map +1 -1
- package/build/store/reducer.js +18 -9
- package/build/store/reducer.js.map +1 -1
- package/build/utils/selection.js +34 -0
- package/build/utils/selection.js.map +1 -0
- package/build-module/components/block-pattern-setup/index.js +3 -9
- package/build-module/components/block-pattern-setup/index.js.map +1 -1
- package/build-module/components/block-pattern-setup/setup-toolbar.js +3 -8
- package/build-module/components/block-pattern-setup/setup-toolbar.js.map +1 -1
- package/build-module/components/block-preview/auto.js +20 -5
- package/build-module/components/block-preview/auto.js.map +1 -1
- package/build-module/components/block-settings-menu/block-edit-visually-button.js +56 -0
- package/build-module/components/block-settings-menu/block-edit-visually-button.js.map +1 -0
- package/build-module/components/block-settings-menu/block-settings-dropdown.js +2 -4
- package/build-module/components/block-settings-menu/block-settings-dropdown.js.map +1 -1
- package/build-module/components/block-settings-menu/index.js +6 -3
- package/build-module/components/block-settings-menu/index.js.map +1 -1
- package/build-module/components/block-settings-menu-controls/index.js +5 -2
- package/build-module/components/block-settings-menu-controls/index.js.map +1 -1
- package/build-module/components/block-title/use-block-display-title.js +3 -9
- package/build-module/components/block-title/use-block-display-title.js.map +1 -1
- package/build-module/components/colors-gradients/dropdown.js +2 -1
- package/build-module/components/colors-gradients/dropdown.js.map +1 -1
- package/build-module/components/duotone/components.js +130 -0
- package/build-module/components/duotone/components.js.map +1 -0
- package/build-module/components/duotone/index.js +3 -0
- package/build-module/components/duotone/index.js.map +1 -0
- package/build-module/components/duotone/utils.js +30 -0
- package/build-module/components/duotone/utils.js.map +1 -0
- package/build-module/components/duotone-control/index.js +18 -6
- package/build-module/components/duotone-control/index.js.map +1 -1
- package/build-module/components/index.js +1 -0
- package/build-module/components/index.js.map +1 -1
- package/build-module/components/inserter/index.js +3 -2
- package/build-module/components/inserter/index.js.map +1 -1
- package/build-module/components/media-placeholder/index.js +1 -0
- package/build-module/components/media-placeholder/index.js.map +1 -1
- package/build-module/components/media-placeholder/index.native.js +5 -3
- package/build-module/components/media-placeholder/index.native.js.map +1 -1
- package/build-module/components/media-replace-flow/index.js +3 -6
- package/build-module/components/media-replace-flow/index.js.map +1 -1
- package/build-module/components/publish-date-time-picker/index.js +2 -0
- package/build-module/components/publish-date-time-picker/index.js.map +1 -1
- package/build-module/components/rich-text/use-input-rules.js +3 -11
- package/build-module/components/rich-text/use-input-rules.js.map +1 -1
- package/build-module/components/rich-text/use-paste-handler.js +20 -5
- package/build-module/components/rich-text/use-paste-handler.js.map +1 -1
- package/build-module/elements/index.js +7 -1
- package/build-module/elements/index.js.map +1 -1
- package/build-module/hooks/aria-label.js +59 -0
- package/build-module/hooks/aria-label.js.map +1 -0
- package/build-module/hooks/duotone.js +22 -140
- package/build-module/hooks/duotone.js.map +1 -1
- package/build-module/hooks/index.js +1 -1
- package/build-module/hooks/index.js.map +1 -1
- package/build-module/hooks/layout.js +6 -4
- package/build-module/hooks/layout.js.map +1 -1
- package/build-module/index.js +1 -1
- package/build-module/index.js.map +1 -1
- package/build-module/layouts/flex.js +2 -2
- package/build-module/layouts/flex.js.map +1 -1
- package/build-module/store/actions.js +6 -11
- package/build-module/store/actions.js.map +1 -1
- package/build-module/store/reducer.js +19 -10
- package/build-module/store/reducer.js.map +1 -1
- package/build-module/utils/selection.js +24 -0
- package/build-module/utils/selection.js.map +1 -0
- package/build-style/style-rtl.css +5 -1
- package/build-style/style.css +5 -1
- package/package.json +28 -28
- package/src/components/block-draggable/test/helpers.native.js +3 -3
- package/src/components/block-list/style.scss +1 -1
- package/src/components/block-pattern-setup/index.js +2 -10
- package/src/components/block-pattern-setup/setup-toolbar.js +2 -9
- package/src/components/block-preview/auto.js +17 -3
- package/src/components/block-settings-menu/block-edit-visually-button.js +52 -0
- package/src/components/block-settings-menu/block-settings-dropdown.js +3 -2
- package/src/components/block-settings-menu/index.js +15 -11
- package/src/components/block-settings-menu-controls/index.js +3 -2
- package/src/components/block-title/use-block-display-title.js +9 -7
- package/src/components/colors-gradients/dropdown.js +1 -0
- package/src/components/duotone/components.js +133 -0
- package/src/components/duotone/index.js +7 -0
- package/src/components/duotone/utils.js +25 -0
- package/src/components/duotone-control/index.js +12 -7
- package/src/components/duotone-control/style.scss +5 -0
- package/src/components/index.js +1 -0
- package/src/components/inserter/index.js +3 -5
- package/src/components/link-control/test/fixtures/index.js +3 -4
- package/src/components/link-control/test/index.js +58 -69
- package/src/components/media-placeholder/index.js +1 -0
- package/src/components/media-placeholder/index.native.js +9 -5
- package/src/components/media-replace-flow/index.js +2 -8
- package/src/components/media-upload/README.md +8 -0
- package/src/components/publish-date-time-picker/index.js +2 -0
- package/src/components/responsive-block-control/README.md +3 -1
- package/src/components/responsive-block-control/test/index.js +1 -2
- package/src/components/rich-text/use-input-rules.js +6 -15
- package/src/components/rich-text/use-paste-handler.js +17 -5
- package/src/elements/index.js +8 -1
- package/src/elements/test/index.js +18 -0
- package/src/hooks/aria-label.js +67 -0
- package/src/hooks/duotone.js +18 -139
- package/src/hooks/index.js +1 -1
- package/src/hooks/layout.js +20 -9
- package/src/index.js +0 -1
- package/src/layouts/flex.js +2 -2
- package/src/store/actions.js +8 -21
- package/src/store/reducer.js +21 -9
- package/src/store/test/reducer.js +138 -10
- package/src/store/test/selectors.js +3 -6
- package/src/utils/selection.js +26 -0
- package/src/utils/test/selection.js +39 -0
package/src/hooks/duotone.js
CHANGED
|
@@ -2,14 +2,13 @@
|
|
|
2
2
|
* External dependencies
|
|
3
3
|
*/
|
|
4
4
|
import classnames from 'classnames';
|
|
5
|
-
import {
|
|
5
|
+
import { extend } from 'colord';
|
|
6
6
|
import namesPlugin from 'colord/plugins/names';
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* WordPress dependencies
|
|
10
10
|
*/
|
|
11
11
|
import { getBlockSupport, hasBlockSupport } from '@wordpress/blocks';
|
|
12
|
-
import { SVG } from '@wordpress/components';
|
|
13
12
|
import { createHigherOrderComponent, useInstanceId } from '@wordpress/compose';
|
|
14
13
|
import { addFilter } from '@wordpress/hooks';
|
|
15
14
|
import { useMemo, useContext, createPortal } from '@wordpress/element';
|
|
@@ -23,145 +22,34 @@ import {
|
|
|
23
22
|
useSetting,
|
|
24
23
|
} from '../components';
|
|
25
24
|
import BlockList from '../components/block-list';
|
|
25
|
+
import {
|
|
26
|
+
__unstableDuotoneFilter as DuotoneFilter,
|
|
27
|
+
__unstableDuotoneStylesheet as DuotoneStylesheet,
|
|
28
|
+
__unstableDuotoneUnsetStylesheet as DuotoneUnsetStylesheet,
|
|
29
|
+
} from '../components/duotone';
|
|
26
30
|
|
|
27
31
|
const EMPTY_ARRAY = [];
|
|
28
32
|
|
|
29
33
|
extend( [ namesPlugin ] );
|
|
30
34
|
|
|
31
|
-
/**
|
|
32
|
-
* Convert a list of colors to an object of R, G, and B values.
|
|
33
|
-
*
|
|
34
|
-
* @param {string[]} colors Array of RBG color strings.
|
|
35
|
-
*
|
|
36
|
-
* @return {Object} R, G, and B values.
|
|
37
|
-
*/
|
|
38
|
-
export function getValuesFromColors( colors = [] ) {
|
|
39
|
-
const values = { r: [], g: [], b: [], a: [] };
|
|
40
|
-
|
|
41
|
-
colors.forEach( ( color ) => {
|
|
42
|
-
const rgbColor = colord( color ).toRgb();
|
|
43
|
-
values.r.push( rgbColor.r / 255 );
|
|
44
|
-
values.g.push( rgbColor.g / 255 );
|
|
45
|
-
values.b.push( rgbColor.b / 255 );
|
|
46
|
-
values.a.push( rgbColor.a );
|
|
47
|
-
} );
|
|
48
|
-
|
|
49
|
-
return values;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
/**
|
|
53
|
-
* Values for the SVG `feComponentTransfer`.
|
|
54
|
-
*
|
|
55
|
-
* @typedef Values {Object}
|
|
56
|
-
* @property {number[]} r Red values.
|
|
57
|
-
* @property {number[]} g Green values.
|
|
58
|
-
* @property {number[]} b Blue values.
|
|
59
|
-
* @property {number[]} a Alpha values.
|
|
60
|
-
*/
|
|
61
|
-
|
|
62
|
-
/**
|
|
63
|
-
* Stylesheet for rendering the duotone filter.
|
|
64
|
-
*
|
|
65
|
-
* @param {Object} props Duotone props.
|
|
66
|
-
* @param {string} props.selector Selector to apply the filter to.
|
|
67
|
-
* @param {string} props.id Unique id for this duotone filter.
|
|
68
|
-
*
|
|
69
|
-
* @return {WPElement} Duotone element.
|
|
70
|
-
*/
|
|
71
|
-
function DuotoneStylesheet( { selector, id } ) {
|
|
72
|
-
const css = `
|
|
73
|
-
${ selector } {
|
|
74
|
-
filter: url( #${ id } );
|
|
75
|
-
}
|
|
76
|
-
`;
|
|
77
|
-
return <style>{ css }</style>;
|
|
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 } ) {
|
|
90
|
-
return (
|
|
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( ' ' ) }
|
|
134
|
-
/>
|
|
135
|
-
<feFuncA
|
|
136
|
-
type="table"
|
|
137
|
-
tableValues={ values.a.join( ' ' ) }
|
|
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
35
|
/**
|
|
152
36
|
* SVG and stylesheet needed for rendering the duotone filter.
|
|
153
37
|
*
|
|
154
|
-
* @param {Object} props
|
|
38
|
+
* @param {Object} props Duotone props.
|
|
155
39
|
* @param {string} props.selector Selector to apply the filter to.
|
|
156
|
-
* @param {string} props.id
|
|
157
|
-
* @param {
|
|
40
|
+
* @param {string} props.id Unique id for this duotone filter.
|
|
41
|
+
* @param {string[]|"unset"} props.colors Array of RGB color strings ordered from dark to light.
|
|
158
42
|
*
|
|
159
43
|
* @return {WPElement} Duotone element.
|
|
160
44
|
*/
|
|
161
|
-
function InlineDuotone( { selector, id,
|
|
45
|
+
function InlineDuotone( { selector, id, colors } ) {
|
|
46
|
+
if ( colors === 'unset' ) {
|
|
47
|
+
return <DuotoneUnsetStylesheet selector={ selector } />;
|
|
48
|
+
}
|
|
49
|
+
|
|
162
50
|
return (
|
|
163
51
|
<>
|
|
164
|
-
<DuotoneFilter id={ id }
|
|
52
|
+
<DuotoneFilter id={ id } colors={ colors } />
|
|
165
53
|
<DuotoneStylesheet id={ id } selector={ selector } />
|
|
166
54
|
</>
|
|
167
55
|
);
|
|
@@ -324,9 +212,9 @@ const withDuotoneStyles = createHigherOrderComponent(
|
|
|
324
212
|
props.name,
|
|
325
213
|
'color.__experimentalDuotone'
|
|
326
214
|
);
|
|
327
|
-
const
|
|
215
|
+
const colors = props?.attributes?.style?.color?.duotone;
|
|
328
216
|
|
|
329
|
-
if ( ! duotoneSupport || !
|
|
217
|
+
if ( ! duotoneSupport || ! colors ) {
|
|
330
218
|
return <BlockListBlock { ...props } />;
|
|
331
219
|
}
|
|
332
220
|
|
|
@@ -351,7 +239,7 @@ const withDuotoneStyles = createHigherOrderComponent(
|
|
|
351
239
|
<InlineDuotone
|
|
352
240
|
selector={ selectorsGroup }
|
|
353
241
|
id={ id }
|
|
354
|
-
|
|
242
|
+
colors={ colors }
|
|
355
243
|
/>,
|
|
356
244
|
element
|
|
357
245
|
) }
|
|
@@ -362,15 +250,6 @@ const withDuotoneStyles = createHigherOrderComponent(
|
|
|
362
250
|
'withDuotoneStyles'
|
|
363
251
|
);
|
|
364
252
|
|
|
365
|
-
export function PresetDuotoneFilter( { preset } ) {
|
|
366
|
-
return (
|
|
367
|
-
<DuotoneFilter
|
|
368
|
-
id={ `wp-duotone-${ preset.slug }` }
|
|
369
|
-
values={ getValuesFromColors( preset.colors ) }
|
|
370
|
-
/>
|
|
371
|
-
);
|
|
372
|
-
}
|
|
373
|
-
|
|
374
253
|
addFilter(
|
|
375
254
|
'blocks.registerBlockType',
|
|
376
255
|
'core/editor/duotone/add-attributes',
|
package/src/hooks/index.js
CHANGED
|
@@ -5,6 +5,7 @@ import './compat';
|
|
|
5
5
|
import './align';
|
|
6
6
|
import './lock';
|
|
7
7
|
import './anchor';
|
|
8
|
+
import './aria-label';
|
|
8
9
|
import './custom-class-name';
|
|
9
10
|
import './generated-class-name';
|
|
10
11
|
import './style';
|
|
@@ -20,4 +21,3 @@ export { getBorderClassesAndStyles, useBorderProps } from './use-border-props';
|
|
|
20
21
|
export { getColorClassesAndStyles, useColorProps } from './use-color-props';
|
|
21
22
|
export { getSpacingClassesAndStyles } from './use-spacing-props';
|
|
22
23
|
export { useCachedTruthy } from './use-cached-truthy';
|
|
23
|
-
export { PresetDuotoneFilter } from './duotone';
|
package/src/hooks/layout.js
CHANGED
|
@@ -130,15 +130,26 @@ function LayoutPanel( { setAttributes, attributes, name: blockName } ) {
|
|
|
130
130
|
<InspectorControls>
|
|
131
131
|
<PanelBody title={ __( 'Layout' ) }>
|
|
132
132
|
{ showInheritToggle && (
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
133
|
+
<>
|
|
134
|
+
<ToggleControl
|
|
135
|
+
label={ __( 'Inner blocks use full width' ) }
|
|
136
|
+
checked={ ! inherit }
|
|
137
|
+
onChange={ () =>
|
|
138
|
+
setAttributes( {
|
|
139
|
+
layout: { inherit: ! inherit },
|
|
140
|
+
} )
|
|
141
|
+
}
|
|
142
|
+
/>
|
|
143
|
+
<p className="block-editor-hooks__layout-controls-helptext">
|
|
144
|
+
{ !! inherit
|
|
145
|
+
? __(
|
|
146
|
+
'Nested blocks use theme content width with options for full and wide widths.'
|
|
147
|
+
)
|
|
148
|
+
: __(
|
|
149
|
+
'Nested blocks will fill the width of this container.'
|
|
150
|
+
) }
|
|
151
|
+
</p>
|
|
152
|
+
</>
|
|
142
153
|
) }
|
|
143
154
|
|
|
144
155
|
{ ! inherit && allowSwitching && (
|
package/src/index.js
CHANGED
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
*/
|
|
4
4
|
import './hooks';
|
|
5
5
|
export {
|
|
6
|
-
PresetDuotoneFilter as __unstablePresetDuotoneFilter,
|
|
7
6
|
getBorderClassesAndStyles as __experimentalGetBorderClassesAndStyles,
|
|
8
7
|
useBorderProps as __experimentalUseBorderProps,
|
|
9
8
|
getColorClassesAndStyles as __experimentalGetColorClassesAndStyles,
|
package/src/layouts/flex.js
CHANGED
|
@@ -324,7 +324,7 @@ function OrientationControl( { layout, onChange } ) {
|
|
|
324
324
|
<fieldset className="block-editor-hooks__flex-layout-orientation-controls">
|
|
325
325
|
<legend>{ __( 'Orientation' ) }</legend>
|
|
326
326
|
<Button
|
|
327
|
-
label={ '
|
|
327
|
+
label={ __( 'Horizontal' ) }
|
|
328
328
|
icon={ arrowRight }
|
|
329
329
|
isPressed={ orientation === 'horizontal' }
|
|
330
330
|
onClick={ () =>
|
|
@@ -335,7 +335,7 @@ function OrientationControl( { layout, onChange } ) {
|
|
|
335
335
|
}
|
|
336
336
|
/>
|
|
337
337
|
<Button
|
|
338
|
-
label={ '
|
|
338
|
+
label={ __( 'Vertical' ) }
|
|
339
339
|
icon={ arrowDown }
|
|
340
340
|
isPressed={ orientation === 'vertical' }
|
|
341
341
|
onClick={ () =>
|
package/src/store/actions.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* External dependencies
|
|
3
3
|
*/
|
|
4
|
-
import { castArray,
|
|
4
|
+
import { castArray, first, isObject, last, some } from 'lodash';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* WordPress dependencies
|
|
@@ -26,6 +26,10 @@ import deprecated from '@wordpress/deprecated';
|
|
|
26
26
|
* Internal dependencies
|
|
27
27
|
*/
|
|
28
28
|
import { mapRichTextSettings } from './utils';
|
|
29
|
+
import {
|
|
30
|
+
retrieveSelectedAttribute,
|
|
31
|
+
START_OF_SELECTED_AREA,
|
|
32
|
+
} from '../utils/selection';
|
|
29
33
|
|
|
30
34
|
/**
|
|
31
35
|
* Action which will insert a default block insert action if there
|
|
@@ -771,10 +775,6 @@ export const __unstableDeleteSelection =
|
|
|
771
775
|
...mapRichTextSettings( attributeDefinitionB ),
|
|
772
776
|
} );
|
|
773
777
|
|
|
774
|
-
// A robust way to retain selection position through various transforms
|
|
775
|
-
// is to insert a special character at the position and then recover it.
|
|
776
|
-
const START_OF_SELECTED_AREA = '\u0086';
|
|
777
|
-
|
|
778
778
|
valueA = remove( valueA, selectionA.offset, valueA.text.length );
|
|
779
779
|
valueB = insert( valueB, START_OF_SELECTED_AREA, 0, selectionB.offset );
|
|
780
780
|
|
|
@@ -822,12 +822,7 @@ export const __unstableDeleteSelection =
|
|
|
822
822
|
);
|
|
823
823
|
}
|
|
824
824
|
|
|
825
|
-
const newAttributeKey =
|
|
826
|
-
updatedAttributes,
|
|
827
|
-
( v ) =>
|
|
828
|
-
typeof v === 'string' &&
|
|
829
|
-
v.indexOf( START_OF_SELECTED_AREA ) !== -1
|
|
830
|
-
);
|
|
825
|
+
const newAttributeKey = retrieveSelectedAttribute( updatedAttributes );
|
|
831
826
|
|
|
832
827
|
const convertedHtml = updatedAttributes[ newAttributeKey ];
|
|
833
828
|
const convertedValue = create( {
|
|
@@ -1052,10 +1047,6 @@ export const mergeBlocks =
|
|
|
1052
1047
|
}
|
|
1053
1048
|
}
|
|
1054
1049
|
|
|
1055
|
-
// A robust way to retain selection position through various transforms
|
|
1056
|
-
// is to insert a special character at the position and then recover it.
|
|
1057
|
-
const START_OF_SELECTED_AREA = '\u0086';
|
|
1058
|
-
|
|
1059
1050
|
// Clone the blocks so we don't insert the character in a "live" block.
|
|
1060
1051
|
const cloneA = cloneBlock( blockA );
|
|
1061
1052
|
const cloneB = cloneBlock( blockB );
|
|
@@ -1098,12 +1089,8 @@ export const mergeBlocks =
|
|
|
1098
1089
|
);
|
|
1099
1090
|
|
|
1100
1091
|
if ( canRestoreTextSelection ) {
|
|
1101
|
-
const newAttributeKey =
|
|
1102
|
-
updatedAttributes
|
|
1103
|
-
( v ) =>
|
|
1104
|
-
typeof v === 'string' &&
|
|
1105
|
-
v.indexOf( START_OF_SELECTED_AREA ) !== -1
|
|
1106
|
-
);
|
|
1092
|
+
const newAttributeKey =
|
|
1093
|
+
retrieveSelectedAttribute( updatedAttributes );
|
|
1107
1094
|
const convertedHtml = updatedAttributes[ newAttributeKey ];
|
|
1108
1095
|
const convertedValue = create( {
|
|
1109
1096
|
html: convertedHtml,
|
package/src/store/reducer.js
CHANGED
|
@@ -9,7 +9,6 @@ import {
|
|
|
9
9
|
omit,
|
|
10
10
|
without,
|
|
11
11
|
mapValues,
|
|
12
|
-
keys,
|
|
13
12
|
isEqual,
|
|
14
13
|
isEmpty,
|
|
15
14
|
identity,
|
|
@@ -148,7 +147,7 @@ function getMutateSafeObject( original, working ) {
|
|
|
148
147
|
* @return {boolean} Whether the two objects have the same keys.
|
|
149
148
|
*/
|
|
150
149
|
export function hasSameKeys( a, b ) {
|
|
151
|
-
return isEqual( keys( a ), keys( b ) );
|
|
150
|
+
return isEqual( Object.keys( a ), Object.keys( b ) );
|
|
152
151
|
}
|
|
153
152
|
|
|
154
153
|
/**
|
|
@@ -399,13 +398,12 @@ const withBlockTree =
|
|
|
399
398
|
const updatedBlockUids = [];
|
|
400
399
|
if ( action.fromRootClientId ) {
|
|
401
400
|
updatedBlockUids.push( action.fromRootClientId );
|
|
401
|
+
} else {
|
|
402
|
+
updatedBlockUids.push( '' );
|
|
402
403
|
}
|
|
403
404
|
if ( action.toRootClientId ) {
|
|
404
405
|
updatedBlockUids.push( action.toRootClientId );
|
|
405
406
|
}
|
|
406
|
-
if ( ! action.fromRootClientId || ! action.fromRootClientId ) {
|
|
407
|
-
updatedBlockUids.push( '' );
|
|
408
|
-
}
|
|
409
407
|
newState.tree = updateParentInnerBlocksInTree(
|
|
410
408
|
newState,
|
|
411
409
|
newState.tree,
|
|
@@ -428,7 +426,7 @@ const withBlockTree =
|
|
|
428
426
|
break;
|
|
429
427
|
}
|
|
430
428
|
case 'SAVE_REUSABLE_BLOCK_SUCCESS': {
|
|
431
|
-
const updatedBlockUids = keys(
|
|
429
|
+
const updatedBlockUids = Object.keys(
|
|
432
430
|
omitBy( newState.attributes, ( attributes, clientId ) => {
|
|
433
431
|
return (
|
|
434
432
|
newState.byClientId[ clientId ].name !==
|
|
@@ -690,9 +688,9 @@ const withReplaceInnerBlocks = ( reducer ) => ( state, action ) => {
|
|
|
690
688
|
index: 0,
|
|
691
689
|
} );
|
|
692
690
|
|
|
693
|
-
// We need to re-attach the
|
|
694
|
-
// Otherwise, an inner block controller's blocks
|
|
695
|
-
// from its entity
|
|
691
|
+
// We need to re-attach the controlled inner blocks to the blocks tree and
|
|
692
|
+
// preserve their block order. Otherwise, an inner block controller's blocks
|
|
693
|
+
// will be deleted entirely from its entity.
|
|
696
694
|
stateAfterInsert.order = {
|
|
697
695
|
...stateAfterInsert.order,
|
|
698
696
|
...reduce(
|
|
@@ -706,6 +704,20 @@ const withReplaceInnerBlocks = ( reducer ) => ( state, action ) => {
|
|
|
706
704
|
{}
|
|
707
705
|
),
|
|
708
706
|
};
|
|
707
|
+
stateAfterInsert.tree = {
|
|
708
|
+
...stateAfterInsert.tree,
|
|
709
|
+
...reduce(
|
|
710
|
+
nestedControllers,
|
|
711
|
+
( result, value, _key ) => {
|
|
712
|
+
const key = `controlled||${ _key }`;
|
|
713
|
+
if ( state.tree[ key ] ) {
|
|
714
|
+
result[ key ] = state.tree[ key ];
|
|
715
|
+
}
|
|
716
|
+
return result;
|
|
717
|
+
},
|
|
718
|
+
{}
|
|
719
|
+
),
|
|
720
|
+
};
|
|
709
721
|
}
|
|
710
722
|
return stateAfterInsert;
|
|
711
723
|
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* External dependencies
|
|
3
3
|
*/
|
|
4
|
-
import {
|
|
4
|
+
import { omit } from 'lodash';
|
|
5
5
|
import deepFreeze from 'deep-freeze';
|
|
6
6
|
|
|
7
7
|
/**
|
|
@@ -666,7 +666,7 @@ describe( 'state', () => {
|
|
|
666
666
|
} );
|
|
667
667
|
|
|
668
668
|
expect( Object.keys( state.byClientId ) ).toHaveLength( 1 );
|
|
669
|
-
expect( values( state.byClientId )[ 0 ].clientId ).toBe(
|
|
669
|
+
expect( Object.values( state.byClientId )[ 0 ].clientId ).toBe(
|
|
670
670
|
'bananas'
|
|
671
671
|
);
|
|
672
672
|
expect( state.order ).toEqual( {
|
|
@@ -729,7 +729,9 @@ describe( 'state', () => {
|
|
|
729
729
|
} );
|
|
730
730
|
|
|
731
731
|
expect( Object.keys( state.byClientId ) ).toHaveLength( 2 );
|
|
732
|
-
expect( values( state.byClientId )[ 1 ].clientId ).toBe(
|
|
732
|
+
expect( Object.values( state.byClientId )[ 1 ].clientId ).toBe(
|
|
733
|
+
'ribs'
|
|
734
|
+
);
|
|
733
735
|
expect( state.order ).toEqual( {
|
|
734
736
|
'': [ 'chicken', 'ribs' ],
|
|
735
737
|
chicken: [],
|
|
@@ -773,10 +775,12 @@ describe( 'state', () => {
|
|
|
773
775
|
} );
|
|
774
776
|
|
|
775
777
|
expect( Object.keys( state.byClientId ) ).toHaveLength( 1 );
|
|
776
|
-
expect( values( state.byClientId )[ 0 ].name ).toBe(
|
|
778
|
+
expect( Object.values( state.byClientId )[ 0 ].name ).toBe(
|
|
777
779
|
'core/freeform'
|
|
778
780
|
);
|
|
779
|
-
expect( values( state.byClientId )[ 0 ].clientId ).toBe(
|
|
781
|
+
expect( Object.values( state.byClientId )[ 0 ].clientId ).toBe(
|
|
782
|
+
'wings'
|
|
783
|
+
);
|
|
780
784
|
expect( state.order ).toEqual( {
|
|
781
785
|
'': [ 'wings' ],
|
|
782
786
|
wings: [],
|
|
@@ -930,15 +934,15 @@ describe( 'state', () => {
|
|
|
930
934
|
} );
|
|
931
935
|
|
|
932
936
|
expect( Object.keys( replacedState.byClientId ) ).toHaveLength( 1 );
|
|
933
|
-
expect( values( originalState.byClientId )[ 0 ].name ).toBe(
|
|
937
|
+
expect( Object.values( originalState.byClientId )[ 0 ].name ).toBe(
|
|
934
938
|
'core/test-block'
|
|
935
939
|
);
|
|
936
|
-
expect( values( replacedState.byClientId )[ 0 ].name ).toBe(
|
|
940
|
+
expect( Object.values( replacedState.byClientId )[ 0 ].name ).toBe(
|
|
937
941
|
'core/freeform'
|
|
938
942
|
);
|
|
939
|
-
expect(
|
|
940
|
-
|
|
941
|
-
);
|
|
943
|
+
expect(
|
|
944
|
+
Object.values( replacedState.byClientId )[ 0 ].clientId
|
|
945
|
+
).toBe( 'chicken' );
|
|
942
946
|
expect( replacedState.order ).toEqual( {
|
|
943
947
|
'': [ 'chicken' ],
|
|
944
948
|
chicken: [],
|
|
@@ -2090,6 +2094,130 @@ describe( 'state', () => {
|
|
|
2090
2094
|
expect( state.tree.child ).toBeUndefined();
|
|
2091
2095
|
expect( state.tree.chicken.innerBlocks ).toEqual( [] );
|
|
2092
2096
|
} );
|
|
2097
|
+
it( 'should preserve the controlled blocks in state and re-attach them in other pieces of state(order, tree, etc..), when we replace inner blocks', () => {
|
|
2098
|
+
const initialState = {
|
|
2099
|
+
byClientId: {
|
|
2100
|
+
'group-id': {
|
|
2101
|
+
clientId: 'group-id',
|
|
2102
|
+
name: 'core/group',
|
|
2103
|
+
isValid: true,
|
|
2104
|
+
},
|
|
2105
|
+
'reusable-id': {
|
|
2106
|
+
clientId: 'reusable-id',
|
|
2107
|
+
name: 'core/block',
|
|
2108
|
+
isValid: true,
|
|
2109
|
+
},
|
|
2110
|
+
'paragraph-id': {
|
|
2111
|
+
clientId: 'paragraph-id',
|
|
2112
|
+
name: 'core/paragraph',
|
|
2113
|
+
isValid: true,
|
|
2114
|
+
},
|
|
2115
|
+
},
|
|
2116
|
+
order: {
|
|
2117
|
+
'': [ 'group-id' ],
|
|
2118
|
+
'group-id': [ 'reusable-id' ],
|
|
2119
|
+
'reusable-id': [ 'paragraph-id' ],
|
|
2120
|
+
'paragraph-id': [],
|
|
2121
|
+
},
|
|
2122
|
+
controlledInnerBlocks: {
|
|
2123
|
+
'reusable-id': true,
|
|
2124
|
+
},
|
|
2125
|
+
parents: {
|
|
2126
|
+
'group-id': '',
|
|
2127
|
+
'reusable-id': 'group-id',
|
|
2128
|
+
'paragraph-id': 'reusable-id',
|
|
2129
|
+
},
|
|
2130
|
+
tree: {
|
|
2131
|
+
'group-id': {
|
|
2132
|
+
clientId: 'group-id',
|
|
2133
|
+
name: 'core/group',
|
|
2134
|
+
isValid: true,
|
|
2135
|
+
innerBlocks: [
|
|
2136
|
+
{
|
|
2137
|
+
clientId: 'reusable-id',
|
|
2138
|
+
name: 'core/block',
|
|
2139
|
+
isValid: true,
|
|
2140
|
+
attributes: {
|
|
2141
|
+
ref: 687,
|
|
2142
|
+
},
|
|
2143
|
+
innerBlocks: [],
|
|
2144
|
+
},
|
|
2145
|
+
],
|
|
2146
|
+
},
|
|
2147
|
+
'reusable-id': {
|
|
2148
|
+
clientId: 'reusable-id',
|
|
2149
|
+
name: 'core/block',
|
|
2150
|
+
isValid: true,
|
|
2151
|
+
attributes: {
|
|
2152
|
+
ref: 687,
|
|
2153
|
+
},
|
|
2154
|
+
innerBlocks: [],
|
|
2155
|
+
},
|
|
2156
|
+
'': {
|
|
2157
|
+
innerBlocks: [
|
|
2158
|
+
{
|
|
2159
|
+
clientId: 'group-id',
|
|
2160
|
+
name: 'core/group',
|
|
2161
|
+
isValid: true,
|
|
2162
|
+
innerBlocks: [
|
|
2163
|
+
{
|
|
2164
|
+
clientId: 'reusable-id',
|
|
2165
|
+
name: 'core/block',
|
|
2166
|
+
isValid: true,
|
|
2167
|
+
attributes: {
|
|
2168
|
+
ref: 687,
|
|
2169
|
+
},
|
|
2170
|
+
innerBlocks: [],
|
|
2171
|
+
},
|
|
2172
|
+
],
|
|
2173
|
+
},
|
|
2174
|
+
],
|
|
2175
|
+
},
|
|
2176
|
+
'paragraph-id': {
|
|
2177
|
+
clientId: 'paragraph-id',
|
|
2178
|
+
name: 'core/paragraph',
|
|
2179
|
+
isValid: true,
|
|
2180
|
+
innerBlocks: [],
|
|
2181
|
+
},
|
|
2182
|
+
'controlled||reusable-id': {
|
|
2183
|
+
innerBlocks: [
|
|
2184
|
+
{
|
|
2185
|
+
clientId: 'paragraph-id',
|
|
2186
|
+
name: 'core/paragraph',
|
|
2187
|
+
isValid: true,
|
|
2188
|
+
innerBlocks: [],
|
|
2189
|
+
},
|
|
2190
|
+
],
|
|
2191
|
+
},
|
|
2192
|
+
},
|
|
2193
|
+
};
|
|
2194
|
+
// We will dispatch an action that replaces the inner
|
|
2195
|
+
// blocks with the same inner blocks, which contain
|
|
2196
|
+
// a controlled block (`reusable-id`).
|
|
2197
|
+
const action = {
|
|
2198
|
+
type: 'REPLACE_INNER_BLOCKS',
|
|
2199
|
+
rootClientId: 'group-id',
|
|
2200
|
+
blocks: [
|
|
2201
|
+
{
|
|
2202
|
+
clientId: 'reusable-id',
|
|
2203
|
+
name: 'core/block',
|
|
2204
|
+
isValid: true,
|
|
2205
|
+
attributes: {
|
|
2206
|
+
ref: 687,
|
|
2207
|
+
},
|
|
2208
|
+
innerBlocks: [],
|
|
2209
|
+
},
|
|
2210
|
+
],
|
|
2211
|
+
updateSelection: false,
|
|
2212
|
+
};
|
|
2213
|
+
const state = blocks( initialState, action );
|
|
2214
|
+
expect( state.order ).toEqual(
|
|
2215
|
+
expect.objectContaining( initialState.order )
|
|
2216
|
+
);
|
|
2217
|
+
expect( state.tree ).toEqual(
|
|
2218
|
+
expect.objectContaining( initialState.tree )
|
|
2219
|
+
);
|
|
2220
|
+
} );
|
|
2093
2221
|
} );
|
|
2094
2222
|
} );
|
|
2095
2223
|
} );
|
|
@@ -1,8 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* External dependencies
|
|
3
|
-
*/
|
|
4
|
-
import { filter } from 'lodash';
|
|
5
|
-
|
|
6
1
|
/**
|
|
7
2
|
* WordPress dependencies
|
|
8
3
|
*/
|
|
@@ -83,7 +78,9 @@ describe( 'selectors', () => {
|
|
|
83
78
|
let cachedSelectors;
|
|
84
79
|
|
|
85
80
|
beforeAll( () => {
|
|
86
|
-
cachedSelectors =
|
|
81
|
+
cachedSelectors = Object.entries( selectors )
|
|
82
|
+
.filter( ( [ , selector ] ) => selector.clear )
|
|
83
|
+
.map( ( [ , selector ] ) => selector );
|
|
87
84
|
} );
|
|
88
85
|
|
|
89
86
|
beforeEach( () => {
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A robust way to retain selection position through various
|
|
3
|
+
* transforms is to insert a special character at the position and
|
|
4
|
+
* then recover it.
|
|
5
|
+
*/
|
|
6
|
+
export const START_OF_SELECTED_AREA = '\u0086';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Retrieve the block attribute that contains the selection position.
|
|
10
|
+
*
|
|
11
|
+
* @param {Object} blockAttributes Block attributes.
|
|
12
|
+
* @return {string|void} The name of the block attribute that was previously selected.
|
|
13
|
+
*/
|
|
14
|
+
export function retrieveSelectedAttribute( blockAttributes ) {
|
|
15
|
+
if ( ! blockAttributes ) {
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
return Object.keys( blockAttributes ).find( ( name ) => {
|
|
20
|
+
const value = blockAttributes[ name ];
|
|
21
|
+
return (
|
|
22
|
+
typeof value === 'string' &&
|
|
23
|
+
value.indexOf( START_OF_SELECTED_AREA ) !== -1
|
|
24
|
+
);
|
|
25
|
+
} );
|
|
26
|
+
}
|