@wordpress/block-editor 12.10.2 → 12.10.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-styles/index.js +1 -2
- package/build/components/block-styles/index.js.map +1 -1
- package/build/components/global-styles/hooks.js +1 -1
- package/build/components/global-styles/hooks.js.map +1 -1
- package/build/components/global-styles/use-global-styles-output.js +17 -5
- package/build/components/global-styles/use-global-styles-output.js.map +1 -1
- package/build/components/global-styles/utils.js +22 -0
- package/build/components/global-styles/utils.js.map +1 -1
- package/build/components/iframe/index.js +9 -1
- package/build/components/iframe/index.js.map +1 -1
- package/build/components/inserter/block-patterns-filter.js +11 -10
- package/build/components/inserter/block-patterns-filter.js.map +1 -1
- package/build/components/inserter/block-patterns-tab.js +1 -1
- package/build/components/inserter/block-patterns-tab.js.map +1 -1
- package/build/components/inserter/media-tab/hooks.js +4 -33
- package/build/components/inserter/media-tab/hooks.js.map +1 -1
- package/build/components/link-control/search-item.js +36 -1
- package/build/components/link-control/search-item.js.map +1 -1
- package/build/components/list-view/block.js +1 -32
- package/build/components/list-view/block.js.map +1 -1
- package/build/components/list-view/branch.js +8 -1
- package/build/components/list-view/branch.js.map +1 -1
- package/build/components/list-view/index.js +8 -3
- package/build/components/list-view/index.js.map +1 -1
- package/build/components/list-view/utils.js +35 -0
- package/build/components/list-view/utils.js.map +1 -1
- package/build/components/tool-selector/index.js +2 -1
- package/build/components/tool-selector/index.js.map +1 -1
- package/build/hooks/block-rename-ui.js +5 -2
- package/build/hooks/block-rename-ui.js.map +1 -1
- package/build/store/actions.js +8 -12
- package/build/store/actions.js.map +1 -1
- package/build/store/private-selectors.js +55 -1
- package/build/store/private-selectors.js.map +1 -1
- package/build/store/reducer.js +19 -1
- package/build/store/reducer.js.map +1 -1
- package/build/utils/transform-styles/transforms/wrap.js +5 -0
- package/build/utils/transform-styles/transforms/wrap.js.map +1 -1
- package/build-module/components/block-styles/index.js +1 -2
- package/build-module/components/block-styles/index.js.map +1 -1
- package/build-module/components/global-styles/hooks.js +1 -1
- package/build-module/components/global-styles/hooks.js.map +1 -1
- package/build-module/components/global-styles/use-global-styles-output.js +17 -6
- package/build-module/components/global-styles/use-global-styles-output.js.map +1 -1
- package/build-module/components/global-styles/utils.js +21 -0
- package/build-module/components/global-styles/utils.js.map +1 -1
- package/build-module/components/iframe/index.js +9 -1
- package/build-module/components/iframe/index.js.map +1 -1
- package/build-module/components/inserter/block-patterns-filter.js +13 -12
- package/build-module/components/inserter/block-patterns-filter.js.map +1 -1
- package/build-module/components/inserter/block-patterns-tab.js +1 -1
- package/build-module/components/inserter/block-patterns-tab.js.map +1 -1
- package/build-module/components/inserter/media-tab/hooks.js +5 -34
- package/build-module/components/inserter/media-tab/hooks.js.map +1 -1
- package/build-module/components/link-control/search-item.js +37 -2
- package/build-module/components/link-control/search-item.js.map +1 -1
- package/build-module/components/list-view/block.js +3 -34
- package/build-module/components/list-view/block.js.map +1 -1
- package/build-module/components/list-view/branch.js +8 -1
- package/build-module/components/list-view/branch.js.map +1 -1
- package/build-module/components/list-view/index.js +8 -3
- package/build-module/components/list-view/index.js.map +1 -1
- package/build-module/components/list-view/utils.js +34 -0
- package/build-module/components/list-view/utils.js.map +1 -1
- package/build-module/components/tool-selector/index.js +2 -1
- package/build-module/components/tool-selector/index.js.map +1 -1
- package/build-module/hooks/block-rename-ui.js +5 -2
- package/build-module/hooks/block-rename-ui.js.map +1 -1
- package/build-module/store/actions.js +8 -12
- package/build-module/store/actions.js.map +1 -1
- package/build-module/store/private-selectors.js +52 -0
- package/build-module/store/private-selectors.js.map +1 -1
- package/build-module/store/reducer.js +18 -1
- package/build-module/store/reducer.js.map +1 -1
- package/build-module/utils/transform-styles/transforms/wrap.js +5 -0
- package/build-module/utils/transform-styles/transforms/wrap.js.map +1 -1
- package/build-style/style-rtl.css +1 -1
- package/build-style/style.css +1 -1
- package/package.json +32 -32
- package/src/components/block-styles/index.js +1 -4
- package/src/components/global-styles/hooks.js +1 -1
- package/src/components/global-styles/test/use-global-styles-output.js +39 -0
- package/src/components/global-styles/use-global-styles-output.js +26 -6
- package/src/components/global-styles/utils.js +21 -0
- package/src/components/iframe/index.js +8 -1
- package/src/components/inserter/block-patterns-filter.js +22 -10
- package/src/components/inserter/block-patterns-tab.js +0 -3
- package/src/components/inserter/media-tab/hooks.js +10 -44
- package/src/components/inserter/style.scss +1 -1
- package/src/components/link-control/search-item.js +55 -2
- package/src/components/list-view/block.js +3 -43
- package/src/components/list-view/branch.js +11 -1
- package/src/components/list-view/index.js +8 -4
- package/src/components/list-view/utils.js +37 -0
- package/src/components/tool-selector/index.js +1 -1
- package/src/hooks/block-rename-ui.js +14 -10
- package/src/store/actions.js +7 -11
- package/src/store/private-selectors.js +72 -0
- package/src/store/reducer.js +17 -0
- package/src/store/test/actions.js +10 -16
- package/src/utils/transform-styles/transforms/test/__snapshots__/wrap.js.snap +13 -6
- package/src/utils/transform-styles/transforms/test/wrap.js +9 -0
- package/src/utils/transform-styles/transforms/wrap.js +5 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wordpress/block-editor",
|
|
3
|
-
"version": "12.10.
|
|
3
|
+
"version": "12.10.4",
|
|
4
4
|
"description": "Generic block editor.",
|
|
5
5
|
"author": "The WordPress Contributors",
|
|
6
6
|
"license": "GPL-2.0-or-later",
|
|
@@ -35,36 +35,36 @@
|
|
|
35
35
|
"@emotion/react": "^11.7.1",
|
|
36
36
|
"@emotion/styled": "^11.6.0",
|
|
37
37
|
"@react-spring/web": "^9.4.5",
|
|
38
|
-
"@wordpress/a11y": "^3.42.
|
|
39
|
-
"@wordpress/api-fetch": "^6.39.
|
|
40
|
-
"@wordpress/blob": "^3.42.
|
|
41
|
-
"@wordpress/blocks": "^12.19.
|
|
42
|
-
"@wordpress/commands": "^0.13.
|
|
43
|
-
"@wordpress/components": "^25.8.
|
|
44
|
-
"@wordpress/compose": "^6.19.
|
|
45
|
-
"@wordpress/data": "^9.12.
|
|
46
|
-
"@wordpress/date": "^4.42.
|
|
47
|
-
"@wordpress/deprecated": "^3.42.
|
|
48
|
-
"@wordpress/dom": "^3.42.
|
|
49
|
-
"@wordpress/element": "^5.19.
|
|
50
|
-
"@wordpress/escape-html": "^2.42.
|
|
51
|
-
"@wordpress/hooks": "^3.42.
|
|
52
|
-
"@wordpress/html-entities": "^3.42.
|
|
53
|
-
"@wordpress/i18n": "^4.42.
|
|
54
|
-
"@wordpress/icons": "^9.33.
|
|
55
|
-
"@wordpress/is-shallow-equal": "^4.42.
|
|
56
|
-
"@wordpress/keyboard-shortcuts": "^4.19.
|
|
57
|
-
"@wordpress/keycodes": "^3.42.
|
|
58
|
-
"@wordpress/notices": "^4.10.
|
|
59
|
-
"@wordpress/preferences": "^3.19.
|
|
60
|
-
"@wordpress/private-apis": "^0.24.
|
|
61
|
-
"@wordpress/rich-text": "^6.19.
|
|
62
|
-
"@wordpress/shortcode": "^3.42.
|
|
63
|
-
"@wordpress/style-engine": "^1.25.
|
|
64
|
-
"@wordpress/token-list": "^2.42.
|
|
65
|
-
"@wordpress/url": "^3.43.
|
|
66
|
-
"@wordpress/warning": "^2.42.
|
|
67
|
-
"@wordpress/wordcount": "^3.42.
|
|
38
|
+
"@wordpress/a11y": "^3.42.4",
|
|
39
|
+
"@wordpress/api-fetch": "^6.39.4",
|
|
40
|
+
"@wordpress/blob": "^3.42.4",
|
|
41
|
+
"@wordpress/blocks": "^12.19.4",
|
|
42
|
+
"@wordpress/commands": "^0.13.4",
|
|
43
|
+
"@wordpress/components": "^25.8.4",
|
|
44
|
+
"@wordpress/compose": "^6.19.4",
|
|
45
|
+
"@wordpress/data": "^9.12.4",
|
|
46
|
+
"@wordpress/date": "^4.42.4",
|
|
47
|
+
"@wordpress/deprecated": "^3.42.4",
|
|
48
|
+
"@wordpress/dom": "^3.42.4",
|
|
49
|
+
"@wordpress/element": "^5.19.4",
|
|
50
|
+
"@wordpress/escape-html": "^2.42.4",
|
|
51
|
+
"@wordpress/hooks": "^3.42.4",
|
|
52
|
+
"@wordpress/html-entities": "^3.42.4",
|
|
53
|
+
"@wordpress/i18n": "^4.42.4",
|
|
54
|
+
"@wordpress/icons": "^9.33.4",
|
|
55
|
+
"@wordpress/is-shallow-equal": "^4.42.4",
|
|
56
|
+
"@wordpress/keyboard-shortcuts": "^4.19.4",
|
|
57
|
+
"@wordpress/keycodes": "^3.42.4",
|
|
58
|
+
"@wordpress/notices": "^4.10.4",
|
|
59
|
+
"@wordpress/preferences": "^3.19.4",
|
|
60
|
+
"@wordpress/private-apis": "^0.24.4",
|
|
61
|
+
"@wordpress/rich-text": "^6.19.4",
|
|
62
|
+
"@wordpress/shortcode": "^3.42.4",
|
|
63
|
+
"@wordpress/style-engine": "^1.25.4",
|
|
64
|
+
"@wordpress/token-list": "^2.42.4",
|
|
65
|
+
"@wordpress/url": "^3.43.4",
|
|
66
|
+
"@wordpress/warning": "^2.42.4",
|
|
67
|
+
"@wordpress/wordcount": "^3.42.4",
|
|
68
68
|
"change-case": "^4.1.2",
|
|
69
69
|
"classnames": "^2.3.1",
|
|
70
70
|
"colord": "^2.7.0",
|
|
@@ -86,5 +86,5 @@
|
|
|
86
86
|
"publishConfig": {
|
|
87
87
|
"access": "public"
|
|
88
88
|
},
|
|
89
|
-
"gitHead": "
|
|
89
|
+
"gitHead": "d1072bbcaf037a18d414da7865ebaf366a0e7062"
|
|
90
90
|
}
|
|
@@ -14,7 +14,6 @@ import {
|
|
|
14
14
|
Popover,
|
|
15
15
|
} from '@wordpress/components';
|
|
16
16
|
import deprecated from '@wordpress/deprecated';
|
|
17
|
-
import { __ } from '@wordpress/i18n';
|
|
18
17
|
|
|
19
18
|
/**
|
|
20
19
|
* Internal dependencies
|
|
@@ -65,9 +64,7 @@ function BlockStyles( { clientId, onSwitch = noop, onHoverClassName = noop } ) {
|
|
|
65
64
|
<div className="block-editor-block-styles">
|
|
66
65
|
<div className="block-editor-block-styles__variants">
|
|
67
66
|
{ stylesToRender.map( ( style ) => {
|
|
68
|
-
const buttonText = style.
|
|
69
|
-
? __( 'Default' )
|
|
70
|
-
: style.label || style.name;
|
|
67
|
+
const buttonText = style.label || style.name;
|
|
71
68
|
|
|
72
69
|
return (
|
|
73
70
|
<Button
|
|
@@ -117,7 +117,7 @@ export function useGlobalSetting( propertyPath, blockName, source = 'all' ) {
|
|
|
117
117
|
`settings${ appendedBlockPath }.${ setting }`
|
|
118
118
|
) ??
|
|
119
119
|
getValueFromObjectPath( configToUse, `settings.${ setting }` );
|
|
120
|
-
if ( value ) {
|
|
120
|
+
if ( value !== undefined ) {
|
|
121
121
|
result = setImmutably( result, setting.split( '.' ), value );
|
|
122
122
|
}
|
|
123
123
|
} );
|
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
toCustomProperties,
|
|
15
15
|
toStyles,
|
|
16
16
|
getStylesDeclarations,
|
|
17
|
+
processCSSNesting,
|
|
17
18
|
} from '../use-global-styles-output';
|
|
18
19
|
import { ROOT_BLOCK_SELECTOR } from '../utils';
|
|
19
20
|
|
|
@@ -967,4 +968,42 @@ describe( 'global styles renderer', () => {
|
|
|
967
968
|
] );
|
|
968
969
|
} );
|
|
969
970
|
} );
|
|
971
|
+
|
|
972
|
+
describe( 'processCSSNesting', () => {
|
|
973
|
+
it( 'should return processed CSS without any nested selectors', () => {
|
|
974
|
+
expect(
|
|
975
|
+
processCSSNesting( 'color: red; margin: auto;', '.foo' )
|
|
976
|
+
).toEqual( '.foo{color: red; margin: auto;}' );
|
|
977
|
+
} );
|
|
978
|
+
it( 'should return processed CSS with nested selectors', () => {
|
|
979
|
+
expect(
|
|
980
|
+
processCSSNesting(
|
|
981
|
+
'color: red; margin: auto; &.one{color: blue;} & .two{color: green;}',
|
|
982
|
+
'.foo'
|
|
983
|
+
)
|
|
984
|
+
).toEqual(
|
|
985
|
+
'.foo{color: red; margin: auto;}.foo.one{color: blue;}.foo .two{color: green;}'
|
|
986
|
+
);
|
|
987
|
+
} );
|
|
988
|
+
it( 'should return processed CSS with pseudo elements', () => {
|
|
989
|
+
expect(
|
|
990
|
+
processCSSNesting(
|
|
991
|
+
'color: red; margin: auto; &::before{color: blue;} & ::before{color: green;} &.one::before{color: yellow;} & .two::before{color: purple;}',
|
|
992
|
+
'.foo'
|
|
993
|
+
)
|
|
994
|
+
).toEqual(
|
|
995
|
+
'.foo{color: red; margin: auto;}.foo::before{color: blue;}.foo ::before{color: green;}.foo.one::before{color: yellow;}.foo .two::before{color: purple;}'
|
|
996
|
+
);
|
|
997
|
+
} );
|
|
998
|
+
it( 'should return processed CSS with multiple root selectors', () => {
|
|
999
|
+
expect(
|
|
1000
|
+
processCSSNesting(
|
|
1001
|
+
'color: red; margin: auto; &.one{color: blue;} & .two{color: green;} &::before{color: yellow;} & ::before{color: purple;} &.three::before{color: orange;} & .four::before{color: skyblue;}',
|
|
1002
|
+
'.foo, .bar'
|
|
1003
|
+
)
|
|
1004
|
+
).toEqual(
|
|
1005
|
+
'.foo, .bar{color: red; margin: auto;}.foo.one, .bar.one{color: blue;}.foo .two, .bar .two{color: green;}.foo::before, .bar::before{color: yellow;}.foo ::before, .bar ::before{color: purple;}.foo.three::before, .bar.three::before{color: orange;}.foo .four::before, .bar .four::before{color: skyblue;}'
|
|
1006
|
+
);
|
|
1007
|
+
} );
|
|
1008
|
+
} );
|
|
970
1009
|
} );
|
|
@@ -15,7 +15,12 @@ import { getCSSRules } from '@wordpress/style-engine';
|
|
|
15
15
|
/**
|
|
16
16
|
* Internal dependencies
|
|
17
17
|
*/
|
|
18
|
-
import {
|
|
18
|
+
import {
|
|
19
|
+
PRESET_METADATA,
|
|
20
|
+
ROOT_BLOCK_SELECTOR,
|
|
21
|
+
scopeSelector,
|
|
22
|
+
appendToSelector,
|
|
23
|
+
} from './utils';
|
|
19
24
|
import { getBlockCSSSelector } from './get-block-css-selector';
|
|
20
25
|
import {
|
|
21
26
|
getTypographyFontSizeValue,
|
|
@@ -1124,18 +1129,33 @@ function updateConfigWithSeparator( config ) {
|
|
|
1124
1129
|
return config;
|
|
1125
1130
|
}
|
|
1126
1131
|
|
|
1127
|
-
|
|
1132
|
+
export function processCSSNesting( css, blockSelector ) {
|
|
1128
1133
|
let processedCSS = '';
|
|
1129
1134
|
|
|
1130
1135
|
// Split CSS nested rules.
|
|
1131
1136
|
const parts = css.split( '&' );
|
|
1132
1137
|
parts.forEach( ( part ) => {
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1138
|
+
const isRootCss = ! part.includes( '{' );
|
|
1139
|
+
if ( isRootCss ) {
|
|
1140
|
+
// If the part doesn't contain braces, it applies to the root level.
|
|
1141
|
+
processedCSS += `${ blockSelector }{${ part.trim() }}`;
|
|
1142
|
+
} else {
|
|
1143
|
+
// If the part contains braces, it's a nested CSS rule.
|
|
1144
|
+
const splittedPart = part.replace( '}', '' ).split( '{' );
|
|
1145
|
+
if ( splittedPart.length !== 2 ) {
|
|
1146
|
+
return;
|
|
1147
|
+
}
|
|
1148
|
+
|
|
1149
|
+
const [ nestedSelector, cssValue ] = splittedPart;
|
|
1150
|
+
const combinedSelector = nestedSelector.startsWith( ' ' )
|
|
1151
|
+
? scopeSelector( blockSelector, nestedSelector )
|
|
1152
|
+
: appendToSelector( blockSelector, nestedSelector );
|
|
1153
|
+
|
|
1154
|
+
processedCSS += `${ combinedSelector }{${ cssValue.trim() }}`;
|
|
1155
|
+
}
|
|
1136
1156
|
} );
|
|
1137
1157
|
return processedCSS;
|
|
1138
|
-
}
|
|
1158
|
+
}
|
|
1139
1159
|
|
|
1140
1160
|
/**
|
|
1141
1161
|
* Returns the global styles output using a global styles configuration.
|
|
@@ -393,6 +393,27 @@ export function scopeSelector( scope, selector ) {
|
|
|
393
393
|
return selectorsScoped.join( ', ' );
|
|
394
394
|
}
|
|
395
395
|
|
|
396
|
+
/**
|
|
397
|
+
* Appends a sub-selector to an existing one.
|
|
398
|
+
*
|
|
399
|
+
* Given the compounded `selector` "h1, h2, h3"
|
|
400
|
+
* and the `toAppend` selector ".some-class" the result will be
|
|
401
|
+
* "h1.some-class, h2.some-class, h3.some-class".
|
|
402
|
+
*
|
|
403
|
+
* @param {string} selector Original selector.
|
|
404
|
+
* @param {string} toAppend Selector to append.
|
|
405
|
+
*
|
|
406
|
+
* @return {string} The new selector.
|
|
407
|
+
*/
|
|
408
|
+
export function appendToSelector( selector, toAppend ) {
|
|
409
|
+
if ( ! selector.includes( ',' ) ) {
|
|
410
|
+
return selector + toAppend;
|
|
411
|
+
}
|
|
412
|
+
const selectors = selector.split( ',' );
|
|
413
|
+
const newSelectors = selectors.map( ( sel ) => sel + toAppend );
|
|
414
|
+
return newSelectors.join( ',' );
|
|
415
|
+
}
|
|
416
|
+
|
|
396
417
|
/**
|
|
397
418
|
* Compares global style variations according to their styles and settings properties.
|
|
398
419
|
*
|
|
@@ -38,7 +38,14 @@ function bubbleEvent( event, Constructor, frame ) {
|
|
|
38
38
|
init[ key ] = event[ key ];
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
-
if
|
|
41
|
+
// Check if the event is a MouseEvent generated within the iframe.
|
|
42
|
+
// If so, adjust the coordinates to be relative to the position of
|
|
43
|
+
// the iframe. This ensures that components such as Draggable
|
|
44
|
+
// receive coordinates relative to the window, instead of relative
|
|
45
|
+
// to the iframe. Without this, the Draggable event handler would
|
|
46
|
+
// result in components "jumping" position as soon as the user
|
|
47
|
+
// drags over the iframe.
|
|
48
|
+
if ( event instanceof frame.contentDocument.defaultView.MouseEvent ) {
|
|
42
49
|
const rect = frame.getBoundingClientRect();
|
|
43
50
|
init.clientX += rect.left;
|
|
44
51
|
init.clientY += rect.top;
|
|
@@ -7,10 +7,11 @@ import {
|
|
|
7
7
|
DropdownMenu,
|
|
8
8
|
MenuGroup,
|
|
9
9
|
MenuItemsChoice,
|
|
10
|
+
ExternalLink,
|
|
10
11
|
} from '@wordpress/components';
|
|
11
12
|
import { __ } from '@wordpress/i18n';
|
|
12
13
|
import { Icon } from '@wordpress/icons';
|
|
13
|
-
import { useMemo } from '@wordpress/element';
|
|
14
|
+
import { useMemo, createInterpolateElement } from '@wordpress/element';
|
|
14
15
|
|
|
15
16
|
/**
|
|
16
17
|
* Internal dependencies
|
|
@@ -73,13 +74,11 @@ export function BlockPatternsSyncFilter( {
|
|
|
73
74
|
{
|
|
74
75
|
value: SYNC_TYPES.full,
|
|
75
76
|
label: __( 'Synced' ),
|
|
76
|
-
info: __( 'Updated everywhere' ),
|
|
77
77
|
disabled: shouldDisableSyncFilter,
|
|
78
78
|
},
|
|
79
79
|
{
|
|
80
80
|
value: SYNC_TYPES.unsynced,
|
|
81
|
-
label: __( '
|
|
82
|
-
info: __( 'Edit freely' ),
|
|
81
|
+
label: __( 'Not synced' ),
|
|
83
82
|
disabled: shouldDisableSyncFilter,
|
|
84
83
|
},
|
|
85
84
|
],
|
|
@@ -95,20 +94,17 @@ export function BlockPatternsSyncFilter( {
|
|
|
95
94
|
},
|
|
96
95
|
{
|
|
97
96
|
value: PATTERN_TYPES.directory,
|
|
98
|
-
label: __( 'Directory' ),
|
|
99
|
-
info: __( 'Pattern directory & core' ),
|
|
97
|
+
label: __( 'Pattern Directory' ),
|
|
100
98
|
disabled: shouldDisableNonUserSources,
|
|
101
99
|
},
|
|
102
100
|
{
|
|
103
101
|
value: PATTERN_TYPES.theme,
|
|
104
|
-
label: __( 'Theme' ),
|
|
105
|
-
info: __( 'Bundled with the theme' ),
|
|
102
|
+
label: __( 'Theme & Plugins' ),
|
|
106
103
|
disabled: shouldDisableNonUserSources,
|
|
107
104
|
},
|
|
108
105
|
{
|
|
109
106
|
value: PATTERN_TYPES.user,
|
|
110
107
|
label: __( 'User' ),
|
|
111
|
-
info: __( 'Custom created' ),
|
|
112
108
|
},
|
|
113
109
|
],
|
|
114
110
|
[ shouldDisableNonUserSources ]
|
|
@@ -149,7 +145,7 @@ export function BlockPatternsSyncFilter( {
|
|
|
149
145
|
>
|
|
150
146
|
{ () => (
|
|
151
147
|
<>
|
|
152
|
-
<MenuGroup label={ __( '
|
|
148
|
+
<MenuGroup label={ __( 'Source' ) }>
|
|
153
149
|
<MenuItemsChoice
|
|
154
150
|
choices={ patternSourceMenuOptions }
|
|
155
151
|
onSelect={ ( value ) => {
|
|
@@ -175,6 +171,22 @@ export function BlockPatternsSyncFilter( {
|
|
|
175
171
|
value={ patternSyncFilter }
|
|
176
172
|
/>
|
|
177
173
|
</MenuGroup>
|
|
174
|
+
<div className="block-editor-tool-selector__help">
|
|
175
|
+
{ createInterpolateElement(
|
|
176
|
+
__(
|
|
177
|
+
'Patterns are available from the <Link>WordPress.org Pattern Directory</Link>, bundled in the active theme, or created by users on this site. Only patterns created on this site can be synced.'
|
|
178
|
+
),
|
|
179
|
+
{
|
|
180
|
+
Link: (
|
|
181
|
+
<ExternalLink
|
|
182
|
+
href={ __(
|
|
183
|
+
'https://wordpress.org/patterns/'
|
|
184
|
+
) }
|
|
185
|
+
/>
|
|
186
|
+
),
|
|
187
|
+
}
|
|
188
|
+
) }
|
|
189
|
+
</div>
|
|
178
190
|
</>
|
|
179
191
|
) }
|
|
180
192
|
</DropdownMenu>
|
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* WordPress dependencies
|
|
3
3
|
*/
|
|
4
|
-
import { useEffect, useState, useRef
|
|
4
|
+
import { useEffect, useState, useRef } from '@wordpress/element';
|
|
5
5
|
import { useSelect } from '@wordpress/data';
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* Internal dependencies
|
|
9
9
|
*/
|
|
10
10
|
import { store as blockEditorStore } from '../../../store';
|
|
11
|
+
import { unlock } from '../../../lock-unlock';
|
|
11
12
|
|
|
12
|
-
/** @typedef {import('
|
|
13
|
-
/** @typedef {import('
|
|
13
|
+
/** @typedef {import('../../../store/actions').InserterMediaRequest} InserterMediaRequest */
|
|
14
|
+
/** @typedef {import('../../../store/actions').InserterMediaItem} InserterMediaItem */
|
|
14
15
|
|
|
15
16
|
/**
|
|
16
17
|
* Fetches media items based on the provided category.
|
|
@@ -50,48 +51,14 @@ export function useMediaResults( category, query = {} ) {
|
|
|
50
51
|
return { mediaList, isLoading };
|
|
51
52
|
}
|
|
52
53
|
|
|
53
|
-
function useInserterMediaCategories() {
|
|
54
|
-
const {
|
|
55
|
-
inserterMediaCategories,
|
|
56
|
-
allowedMimeTypes,
|
|
57
|
-
enableOpenverseMediaCategory,
|
|
58
|
-
} = useSelect( ( select ) => {
|
|
59
|
-
const settings = select( blockEditorStore ).getSettings();
|
|
60
|
-
return {
|
|
61
|
-
inserterMediaCategories: settings.inserterMediaCategories,
|
|
62
|
-
allowedMimeTypes: settings.allowedMimeTypes,
|
|
63
|
-
enableOpenverseMediaCategory: settings.enableOpenverseMediaCategory,
|
|
64
|
-
};
|
|
65
|
-
}, [] );
|
|
66
|
-
// The allowed `mime_types` can be altered by `upload_mimes` filter and restrict
|
|
67
|
-
// some of them. In this case we shouldn't add the category to the available media
|
|
68
|
-
// categories list in the inserter.
|
|
69
|
-
const allowedCategories = useMemo( () => {
|
|
70
|
-
if ( ! inserterMediaCategories || ! allowedMimeTypes ) {
|
|
71
|
-
return;
|
|
72
|
-
}
|
|
73
|
-
return inserterMediaCategories.filter( ( category ) => {
|
|
74
|
-
// Check if Openverse category is enabled.
|
|
75
|
-
if (
|
|
76
|
-
! enableOpenverseMediaCategory &&
|
|
77
|
-
category.name === 'openverse'
|
|
78
|
-
) {
|
|
79
|
-
return false;
|
|
80
|
-
}
|
|
81
|
-
return Object.values( allowedMimeTypes ).some( ( mimeType ) =>
|
|
82
|
-
mimeType.startsWith( `${ category.mediaType }/` )
|
|
83
|
-
);
|
|
84
|
-
} );
|
|
85
|
-
}, [
|
|
86
|
-
inserterMediaCategories,
|
|
87
|
-
allowedMimeTypes,
|
|
88
|
-
enableOpenverseMediaCategory,
|
|
89
|
-
] );
|
|
90
|
-
return allowedCategories;
|
|
91
|
-
}
|
|
92
|
-
|
|
93
54
|
export function useMediaCategories( rootClientId ) {
|
|
94
55
|
const [ categories, setCategories ] = useState( [] );
|
|
56
|
+
|
|
57
|
+
const inserterMediaCategories = useSelect(
|
|
58
|
+
( select ) =>
|
|
59
|
+
unlock( select( blockEditorStore ) ).getInserterMediaCategories(),
|
|
60
|
+
[]
|
|
61
|
+
);
|
|
95
62
|
const { canInsertImage, canInsertVideo, canInsertAudio } = useSelect(
|
|
96
63
|
( select ) => {
|
|
97
64
|
const { canInsertBlockType } = select( blockEditorStore );
|
|
@@ -112,7 +79,6 @@ export function useMediaCategories( rootClientId ) {
|
|
|
112
79
|
},
|
|
113
80
|
[ rootClientId ]
|
|
114
81
|
);
|
|
115
|
-
const inserterMediaCategories = useInserterMediaCategories();
|
|
116
82
|
useEffect( () => {
|
|
117
83
|
( async () => {
|
|
118
84
|
const _categories = [];
|
|
@@ -13,7 +13,8 @@ import {
|
|
|
13
13
|
file,
|
|
14
14
|
} from '@wordpress/icons';
|
|
15
15
|
import { __unstableStripHTML as stripHTML } from '@wordpress/dom';
|
|
16
|
-
import { safeDecodeURI, filterURLForDisplay } from '@wordpress/url';
|
|
16
|
+
import { safeDecodeURI, filterURLForDisplay, getPath } from '@wordpress/url';
|
|
17
|
+
import { pipe } from '@wordpress/compose';
|
|
17
18
|
|
|
18
19
|
const ICONS_MAP = {
|
|
19
20
|
post: postList,
|
|
@@ -44,6 +45,58 @@ function SearchItemIcon( { isURL, suggestion } ) {
|
|
|
44
45
|
return null;
|
|
45
46
|
}
|
|
46
47
|
|
|
48
|
+
/**
|
|
49
|
+
* Adds a leading slash to a url if it doesn't already have one.
|
|
50
|
+
* @param {string} url the url to add a leading slash to.
|
|
51
|
+
* @return {string} the url with a leading slash.
|
|
52
|
+
*/
|
|
53
|
+
function addLeadingSlash( url ) {
|
|
54
|
+
const trimmedURL = url?.trim();
|
|
55
|
+
|
|
56
|
+
if ( ! trimmedURL?.length ) return url;
|
|
57
|
+
|
|
58
|
+
return url?.replace( /^\/?/, '/' );
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function removeTrailingSlash( url ) {
|
|
62
|
+
const trimmedURL = url?.trim();
|
|
63
|
+
|
|
64
|
+
if ( ! trimmedURL?.length ) return url;
|
|
65
|
+
|
|
66
|
+
return url?.replace( /\/$/, '' );
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const partialRight =
|
|
70
|
+
( fn, ...partialArgs ) =>
|
|
71
|
+
( ...args ) =>
|
|
72
|
+
fn( ...args, ...partialArgs );
|
|
73
|
+
|
|
74
|
+
const defaultTo = ( d ) => ( v ) => {
|
|
75
|
+
return v === null || v === undefined || v !== v ? d : v;
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Prepares a URL for display in the UI.
|
|
80
|
+
* - decodes the URL.
|
|
81
|
+
* - filters it (removes protocol, www, etc.).
|
|
82
|
+
* - truncates it if necessary.
|
|
83
|
+
* - adds a leading slash.
|
|
84
|
+
* @param {string} url the url.
|
|
85
|
+
* @return {string} the processed url to display.
|
|
86
|
+
*/
|
|
87
|
+
function getURLForDisplay( url ) {
|
|
88
|
+
if ( ! url ) return url;
|
|
89
|
+
|
|
90
|
+
return pipe(
|
|
91
|
+
safeDecodeURI,
|
|
92
|
+
getPath,
|
|
93
|
+
defaultTo( '' ),
|
|
94
|
+
partialRight( filterURLForDisplay, 24 ),
|
|
95
|
+
removeTrailingSlash,
|
|
96
|
+
addLeadingSlash
|
|
97
|
+
)( url );
|
|
98
|
+
}
|
|
99
|
+
|
|
47
100
|
export const LinkControlSearchItem = ( {
|
|
48
101
|
itemProps,
|
|
49
102
|
suggestion,
|
|
@@ -54,7 +107,7 @@ export const LinkControlSearchItem = ( {
|
|
|
54
107
|
} ) => {
|
|
55
108
|
const info = isURL
|
|
56
109
|
? __( 'Press ENTER to add this link' )
|
|
57
|
-
:
|
|
110
|
+
: getURLForDisplay( suggestion.url );
|
|
58
111
|
|
|
59
112
|
return (
|
|
60
113
|
<MenuItem
|
|
@@ -13,16 +13,9 @@ import {
|
|
|
13
13
|
} from '@wordpress/components';
|
|
14
14
|
import { useInstanceId } from '@wordpress/compose';
|
|
15
15
|
import { moreVertical } from '@wordpress/icons';
|
|
16
|
-
import {
|
|
17
|
-
useState,
|
|
18
|
-
useRef,
|
|
19
|
-
useEffect,
|
|
20
|
-
useCallback,
|
|
21
|
-
memo,
|
|
22
|
-
} from '@wordpress/element';
|
|
16
|
+
import { useState, useRef, useCallback, memo } from '@wordpress/element';
|
|
23
17
|
import { useDispatch, useSelect } from '@wordpress/data';
|
|
24
18
|
import { sprintf, __ } from '@wordpress/i18n';
|
|
25
|
-
import { focus } from '@wordpress/dom';
|
|
26
19
|
import { ESCAPE } from '@wordpress/keycodes';
|
|
27
20
|
|
|
28
21
|
/**
|
|
@@ -36,7 +29,7 @@ import {
|
|
|
36
29
|
} from '../block-mover/button';
|
|
37
30
|
import ListViewBlockContents from './block-contents';
|
|
38
31
|
import { useListViewContext } from './context';
|
|
39
|
-
import { getBlockPositionDescription } from './utils';
|
|
32
|
+
import { getBlockPositionDescription, focusListItem } from './utils';
|
|
40
33
|
import { store as blockEditorStore } from '../../store';
|
|
41
34
|
import useBlockDisplayInformation from '../use-block-display-information';
|
|
42
35
|
import { useBlockLock } from '../block-lock';
|
|
@@ -120,7 +113,6 @@ function ListViewBlock( {
|
|
|
120
113
|
);
|
|
121
114
|
|
|
122
115
|
const {
|
|
123
|
-
isTreeGridMounted,
|
|
124
116
|
expand,
|
|
125
117
|
collapse,
|
|
126
118
|
BlockSettingsMenu,
|
|
@@ -142,15 +134,6 @@ function ListViewBlock( {
|
|
|
142
134
|
{ 'is-visible': isHovered || isFirstSelectedBlock }
|
|
143
135
|
);
|
|
144
136
|
|
|
145
|
-
// If ListView has experimental features related to the Persistent List View,
|
|
146
|
-
// only focus the selected list item on mount; otherwise the list would always
|
|
147
|
-
// try to steal the focus from the editor canvas.
|
|
148
|
-
useEffect( () => {
|
|
149
|
-
if ( ! isTreeGridMounted && isSelected ) {
|
|
150
|
-
cellRef.current.focus();
|
|
151
|
-
}
|
|
152
|
-
}, [] );
|
|
153
|
-
|
|
154
137
|
// If multiple blocks are selected, deselect all blocks when the user
|
|
155
138
|
// presses the escape key.
|
|
156
139
|
const onKeyDown = ( event ) => {
|
|
@@ -188,30 +171,7 @@ function ListViewBlock( {
|
|
|
188
171
|
selectBlock( undefined, focusClientId, null, null );
|
|
189
172
|
}
|
|
190
173
|
|
|
191
|
-
|
|
192
|
-
const row = treeGridElementRef.current?.querySelector(
|
|
193
|
-
`[role=row][data-block="${ focusClientId }"]`
|
|
194
|
-
);
|
|
195
|
-
if ( ! row ) return null;
|
|
196
|
-
// Focus the first focusable in the row, which is the ListViewBlockSelectButton.
|
|
197
|
-
return focus.focusable.find( row )[ 0 ];
|
|
198
|
-
};
|
|
199
|
-
|
|
200
|
-
let focusElement = getFocusElement();
|
|
201
|
-
if ( focusElement ) {
|
|
202
|
-
focusElement.focus();
|
|
203
|
-
} else {
|
|
204
|
-
// The element hasn't been painted yet. Defer focusing on the next frame.
|
|
205
|
-
// This could happen when all blocks have been deleted and the default block
|
|
206
|
-
// hasn't been added to the editor yet.
|
|
207
|
-
window.requestAnimationFrame( () => {
|
|
208
|
-
focusElement = getFocusElement();
|
|
209
|
-
// Ignore if the element still doesn't exist.
|
|
210
|
-
if ( focusElement ) {
|
|
211
|
-
focusElement.focus();
|
|
212
|
-
}
|
|
213
|
-
} );
|
|
214
|
-
}
|
|
174
|
+
focusListItem( focusClientId, treeGridElementRef );
|
|
215
175
|
},
|
|
216
176
|
[ selectBlock, treeGridElementRef ]
|
|
217
177
|
);
|
|
@@ -168,8 +168,18 @@ function ListViewBranch( props ) {
|
|
|
168
168
|
);
|
|
169
169
|
const isSelectedBranch =
|
|
170
170
|
isBranchSelected || ( isSelected && hasNestedBlocks );
|
|
171
|
+
|
|
172
|
+
// To avoid performance issues, we only render blocks that are in view,
|
|
173
|
+
// or blocks that are selected or dragged. If a block is selected,
|
|
174
|
+
// it is only counted if it is the first of the block selection.
|
|
175
|
+
// This prevents the entire tree from being rendered when a branch is
|
|
176
|
+
// selected, or a user selects all blocks, while still enabling scroll
|
|
177
|
+
// into view behavior when selecting a block or opening the list view.
|
|
171
178
|
const showBlock =
|
|
172
|
-
isDragged ||
|
|
179
|
+
isDragged ||
|
|
180
|
+
blockInView ||
|
|
181
|
+
isBranchDragged ||
|
|
182
|
+
( isSelected && clientId === selectedClientIds[ 0 ] );
|
|
173
183
|
return (
|
|
174
184
|
<AsyncModeProvider key={ clientId } value={ ! isSelected }>
|
|
175
185
|
{ showBlock && (
|
|
@@ -32,6 +32,7 @@ import useListViewDropZone from './use-list-view-drop-zone';
|
|
|
32
32
|
import useListViewExpandSelectedItem from './use-list-view-expand-selected-item';
|
|
33
33
|
import { store as blockEditorStore } from '../../store';
|
|
34
34
|
import { BlockSettingsDropdown } from '../block-settings-menu/block-settings-dropdown';
|
|
35
|
+
import { focusListItem } from './utils';
|
|
35
36
|
|
|
36
37
|
const expanded = ( state, action ) => {
|
|
37
38
|
if ( Array.isArray( action.clientIds ) ) {
|
|
@@ -132,8 +133,6 @@ function ListViewComponent(
|
|
|
132
133
|
const elementRef = useRef();
|
|
133
134
|
const treeGridRef = useMergeRefs( [ elementRef, dropZoneRef, ref ] );
|
|
134
135
|
|
|
135
|
-
const isMounted = useRef( false );
|
|
136
|
-
|
|
137
136
|
const [ insertedBlock, setInsertedBlock ] = useState( null );
|
|
138
137
|
|
|
139
138
|
const { setSelectedTreeId } = useListViewExpandSelectedItem( {
|
|
@@ -156,7 +155,13 @@ function ListViewComponent(
|
|
|
156
155
|
[ setSelectedTreeId, updateBlockSelection, onSelect, getBlock ]
|
|
157
156
|
);
|
|
158
157
|
useEffect( () => {
|
|
159
|
-
|
|
158
|
+
// If a blocks are already selected when the list view is initially
|
|
159
|
+
// mounted, shift focus to the first selected block.
|
|
160
|
+
if ( selectedClientIds?.length ) {
|
|
161
|
+
focusListItem( selectedClientIds[ 0 ], elementRef );
|
|
162
|
+
}
|
|
163
|
+
// Disable reason: Only focus on the selected item when the list view is mounted.
|
|
164
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
160
165
|
}, [] );
|
|
161
166
|
|
|
162
167
|
const expand = useCallback(
|
|
@@ -204,7 +209,6 @@ function ListViewComponent(
|
|
|
204
209
|
|
|
205
210
|
const contextValue = useMemo(
|
|
206
211
|
() => ( {
|
|
207
|
-
isTreeGridMounted: isMounted.current,
|
|
208
212
|
draggedClientIds,
|
|
209
213
|
expandedState,
|
|
210
214
|
expand,
|