@wordpress/editor 13.30.0 → 13.31.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/bindings/index.js +3 -1
- package/build/bindings/index.js.map +1 -1
- package/build/components/document-bar/index.js +2 -2
- package/build/components/document-bar/index.js.map +1 -1
- package/build/components/document-outline/index.js +1 -1
- package/build/components/document-outline/index.js.map +1 -1
- package/build/components/entities-saved-states/hooks/use-is-dirty.js +10 -16
- package/build/components/entities-saved-states/hooks/use-is-dirty.js.map +1 -1
- package/build/components/entities-saved-states/index.js +17 -3
- package/build/components/entities-saved-states/index.js.map +1 -1
- package/build/components/error-boundary/index.native.js +133 -0
- package/build/components/error-boundary/index.native.js.map +1 -0
- package/build/components/index.js +9 -8
- package/build/components/index.js.map +1 -1
- package/build/components/index.native.js +9 -1
- package/build/components/index.native.js.map +1 -1
- package/build/components/plugin-document-setting-panel/index.js +123 -0
- package/build/components/plugin-document-setting-panel/index.js.map +1 -0
- package/build/components/post-featured-image/index.js +3 -8
- package/build/components/post-featured-image/index.js.map +1 -1
- package/build/components/post-featured-image/panel.js +7 -3
- package/build/components/post-featured-image/panel.js.map +1 -1
- package/build/components/post-sync-status/index.js +0 -72
- package/build/components/post-sync-status/index.js.map +1 -1
- package/build/components/post-taxonomies/flat-term-selector.js +7 -3
- package/build/components/post-taxonomies/flat-term-selector.js.map +1 -1
- package/build/components/provider/index.js +1 -1
- package/build/components/provider/index.js.map +1 -1
- package/build/components/provider/use-hide-blocks-from-inserter.js +4 -3
- package/build/components/provider/use-hide-blocks-from-inserter.js.map +1 -1
- package/build/private-apis.js +0 -2
- package/build/private-apis.js.map +1 -1
- package/build-module/bindings/index.js +3 -1
- package/build-module/bindings/index.js.map +1 -1
- package/build-module/components/document-bar/index.js +2 -2
- package/build-module/components/document-bar/index.js.map +1 -1
- package/build-module/components/document-outline/index.js +1 -1
- package/build-module/components/document-outline/index.js.map +1 -1
- package/build-module/components/entities-saved-states/hooks/use-is-dirty.js +10 -16
- package/build-module/components/entities-saved-states/hooks/use-is-dirty.js.map +1 -1
- package/build-module/components/entities-saved-states/index.js +18 -4
- package/build-module/components/entities-saved-states/index.js.map +1 -1
- package/build-module/components/error-boundary/index.native.js +125 -0
- package/build-module/components/error-boundary/index.native.js.map +1 -0
- package/build-module/components/index.js +2 -1
- package/build-module/components/index.js.map +1 -1
- package/build-module/components/index.native.js +1 -0
- package/build-module/components/index.native.js.map +1 -1
- package/build-module/components/plugin-document-setting-panel/index.js +115 -0
- package/build-module/components/plugin-document-setting-panel/index.js.map +1 -0
- package/build-module/components/post-featured-image/index.js +4 -9
- package/build-module/components/post-featured-image/index.js.map +1 -1
- package/build-module/components/post-featured-image/panel.js +6 -2
- package/build-module/components/post-featured-image/panel.js.map +1 -1
- package/build-module/components/post-sync-status/index.js +2 -73
- package/build-module/components/post-sync-status/index.js.map +1 -1
- package/build-module/components/post-taxonomies/flat-term-selector.js +7 -3
- package/build-module/components/post-taxonomies/flat-term-selector.js.map +1 -1
- package/build-module/components/provider/index.js +1 -1
- package/build-module/components/provider/index.js.map +1 -1
- package/build-module/components/provider/use-hide-blocks-from-inserter.js +4 -3
- package/build-module/components/provider/use-hide-blocks-from-inserter.js.map +1 -1
- package/build-module/private-apis.js +0 -2
- package/build-module/private-apis.js.map +1 -1
- package/build-style/style-rtl.css +8 -8
- package/build-style/style.css +8 -8
- package/package.json +34 -32
- package/src/bindings/index.js +4 -1
- package/src/components/document-bar/index.js +3 -2
- package/src/components/document-outline/index.js +2 -1
- package/src/components/entities-saved-states/hooks/use-is-dirty.js +18 -22
- package/src/components/entities-saved-states/index.js +33 -8
- package/src/components/entities-saved-states/test/use-is-dirty.js +3 -0
- package/src/components/error-boundary/index.native.js +192 -0
- package/src/components/error-boundary/style.native.scss +116 -0
- package/src/components/index.js +2 -4
- package/src/components/index.native.js +1 -0
- package/src/components/plugin-document-setting-panel/index.js +121 -0
- package/src/components/post-featured-image/index.js +6 -15
- package/src/components/post-featured-image/panel.js +9 -3
- package/src/components/post-featured-image/style.scss +8 -13
- package/src/components/post-sync-status/index.js +1 -94
- package/src/components/post-taxonomies/flat-term-selector.js +13 -8
- package/src/components/provider/index.js +1 -1
- package/src/components/provider/use-hide-blocks-from-inserter.js +5 -3
- package/src/private-apis.js +0 -2
package/build-style/style.css
CHANGED
|
@@ -697,13 +697,10 @@
|
|
|
697
697
|
margin-top: -9px;
|
|
698
698
|
margin-left: -9px;
|
|
699
699
|
}
|
|
700
|
-
.editor-post-featured-image .components-responsive-wrapper__content {
|
|
701
|
-
max-width: 100%;
|
|
702
|
-
width: auto;
|
|
703
|
-
}
|
|
704
700
|
|
|
705
701
|
.editor-post-featured-image__container {
|
|
706
702
|
position: relative;
|
|
703
|
+
aspect-ratio: 2/1;
|
|
707
704
|
}
|
|
708
705
|
.editor-post-featured-image__container:hover .editor-post-featured-image__actions, .editor-post-featured-image__container:focus .editor-post-featured-image__actions, .editor-post-featured-image__container:focus-within .editor-post-featured-image__actions {
|
|
709
706
|
opacity: 1;
|
|
@@ -716,9 +713,10 @@
|
|
|
716
713
|
transition: all 0.1s ease-out;
|
|
717
714
|
box-shadow: 0 0 0 0 var(--wp-admin-theme-color);
|
|
718
715
|
overflow: hidden;
|
|
716
|
+
outline: 1px solid rgba(0, 0, 0, 0.1);
|
|
717
|
+
outline-offset: -1px;
|
|
719
718
|
display: flex;
|
|
720
719
|
justify-content: center;
|
|
721
|
-
max-height: 150px;
|
|
722
720
|
}
|
|
723
721
|
@media (prefers-reduced-motion: reduce) {
|
|
724
722
|
.editor-post-featured-image__toggle,
|
|
@@ -731,15 +729,17 @@
|
|
|
731
729
|
.editor-post-featured-image__preview {
|
|
732
730
|
height: auto;
|
|
733
731
|
}
|
|
734
|
-
.editor-post-featured-image__preview .
|
|
732
|
+
.editor-post-featured-image__preview .editor-post-featured-image__preview-image {
|
|
733
|
+
object-fit: cover;
|
|
735
734
|
width: 100%;
|
|
736
|
-
|
|
735
|
+
object-position: 50% 50%;
|
|
736
|
+
aspect-ratio: 2/1;
|
|
737
737
|
}
|
|
738
738
|
|
|
739
739
|
.editor-post-featured-image__toggle {
|
|
740
740
|
border-radius: 2px;
|
|
741
741
|
background-color: #f0f0f0;
|
|
742
|
-
|
|
742
|
+
height: 100%;
|
|
743
743
|
line-height: 20px;
|
|
744
744
|
padding: 8px 0;
|
|
745
745
|
text-align: center;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wordpress/editor",
|
|
3
|
-
"version": "13.
|
|
3
|
+
"version": "13.31.0",
|
|
4
4
|
"description": "Enhanced block editor for WordPress posts.",
|
|
5
5
|
"author": "The WordPress Contributors",
|
|
6
6
|
"license": "GPL-2.0-or-later",
|
|
@@ -31,36 +31,38 @@
|
|
|
31
31
|
],
|
|
32
32
|
"dependencies": {
|
|
33
33
|
"@babel/runtime": "^7.16.0",
|
|
34
|
-
"@wordpress/a11y": "^3.
|
|
35
|
-
"@wordpress/api-fetch": "^6.
|
|
36
|
-
"@wordpress/blob": "^3.
|
|
37
|
-
"@wordpress/block-editor": "^12.
|
|
38
|
-
"@wordpress/blocks": "^12.
|
|
39
|
-
"@wordpress/commands": "^0.
|
|
40
|
-
"@wordpress/components": "^27.
|
|
41
|
-
"@wordpress/compose": "^6.
|
|
42
|
-
"@wordpress/core-data": "^6.
|
|
43
|
-
"@wordpress/data": "^9.
|
|
44
|
-
"@wordpress/date": "^4.
|
|
45
|
-
"@wordpress/deprecated": "^3.
|
|
46
|
-
"@wordpress/dom": "^3.
|
|
47
|
-
"@wordpress/element": "^5.
|
|
48
|
-
"@wordpress/hooks": "^3.
|
|
49
|
-
"@wordpress/html-entities": "^3.
|
|
50
|
-
"@wordpress/i18n": "^4.
|
|
51
|
-
"@wordpress/icons": "^9.
|
|
52
|
-
"@wordpress/keyboard-shortcuts": "^4.
|
|
53
|
-
"@wordpress/keycodes": "^3.
|
|
54
|
-
"@wordpress/media-utils": "^4.
|
|
55
|
-
"@wordpress/notices": "^4.
|
|
56
|
-
"@wordpress/patterns": "^1.
|
|
57
|
-
"@wordpress/
|
|
58
|
-
"@wordpress/
|
|
59
|
-
"@wordpress/
|
|
60
|
-
"@wordpress/
|
|
61
|
-
"@wordpress/
|
|
62
|
-
"@wordpress/
|
|
63
|
-
"@wordpress/
|
|
34
|
+
"@wordpress/a11y": "^3.54.0",
|
|
35
|
+
"@wordpress/api-fetch": "^6.51.0",
|
|
36
|
+
"@wordpress/blob": "^3.54.0",
|
|
37
|
+
"@wordpress/block-editor": "^12.22.0",
|
|
38
|
+
"@wordpress/blocks": "^12.31.0",
|
|
39
|
+
"@wordpress/commands": "^0.25.0",
|
|
40
|
+
"@wordpress/components": "^27.2.0",
|
|
41
|
+
"@wordpress/compose": "^6.31.0",
|
|
42
|
+
"@wordpress/core-data": "^6.31.0",
|
|
43
|
+
"@wordpress/data": "^9.24.0",
|
|
44
|
+
"@wordpress/date": "^4.54.0",
|
|
45
|
+
"@wordpress/deprecated": "^3.54.0",
|
|
46
|
+
"@wordpress/dom": "^3.54.0",
|
|
47
|
+
"@wordpress/element": "^5.31.0",
|
|
48
|
+
"@wordpress/hooks": "^3.54.0",
|
|
49
|
+
"@wordpress/html-entities": "^3.54.0",
|
|
50
|
+
"@wordpress/i18n": "^4.54.0",
|
|
51
|
+
"@wordpress/icons": "^9.45.0",
|
|
52
|
+
"@wordpress/keyboard-shortcuts": "^4.31.0",
|
|
53
|
+
"@wordpress/keycodes": "^3.54.0",
|
|
54
|
+
"@wordpress/media-utils": "^4.45.0",
|
|
55
|
+
"@wordpress/notices": "^4.22.0",
|
|
56
|
+
"@wordpress/patterns": "^1.15.0",
|
|
57
|
+
"@wordpress/plugins": "^6.22.0",
|
|
58
|
+
"@wordpress/preferences": "^3.31.0",
|
|
59
|
+
"@wordpress/private-apis": "^0.36.0",
|
|
60
|
+
"@wordpress/reusable-blocks": "^4.31.0",
|
|
61
|
+
"@wordpress/rich-text": "^6.31.0",
|
|
62
|
+
"@wordpress/server-side-render": "^4.31.0",
|
|
63
|
+
"@wordpress/url": "^3.55.0",
|
|
64
|
+
"@wordpress/warning": "^2.54.0",
|
|
65
|
+
"@wordpress/wordcount": "^3.54.0",
|
|
64
66
|
"classnames": "^2.3.1",
|
|
65
67
|
"date-fns": "^2.28.0",
|
|
66
68
|
"memize": "^2.1.0",
|
|
@@ -75,5 +77,5 @@
|
|
|
75
77
|
"publishConfig": {
|
|
76
78
|
"access": "public"
|
|
77
79
|
},
|
|
78
|
-
"gitHead": "
|
|
80
|
+
"gitHead": "ffc07735d0abfb3f69e91d48f25b7fe8d1ef92d2"
|
|
79
81
|
}
|
package/src/bindings/index.js
CHANGED
|
@@ -11,5 +11,8 @@ import patternOverrides from './pattern-overrides';
|
|
|
11
11
|
import postMeta from './post-meta';
|
|
12
12
|
|
|
13
13
|
const { registerBlockBindingsSource } = unlock( dispatch( blocksStore ) );
|
|
14
|
-
registerBlockBindingsSource( patternOverrides );
|
|
15
14
|
registerBlockBindingsSource( postMeta );
|
|
15
|
+
|
|
16
|
+
if ( process.env.IS_GUTENBERG_PLUGIN ) {
|
|
17
|
+
registerBlockBindingsSource( patternOverrides );
|
|
18
|
+
}
|
|
@@ -74,7 +74,8 @@ export default function DocumentBar() {
|
|
|
74
74
|
getEditorSettings,
|
|
75
75
|
__experimentalGetTemplateInfo: getTemplateInfo,
|
|
76
76
|
} = select( editorStore );
|
|
77
|
-
const { getEditedEntityRecord,
|
|
77
|
+
const { getEditedEntityRecord, isResolving: isResolvingSelector } =
|
|
78
|
+
select( coreStore );
|
|
78
79
|
const _postType = getCurrentPostType();
|
|
79
80
|
const _postId = getCurrentPostId();
|
|
80
81
|
const _document = getEditedEntityRecord(
|
|
@@ -86,7 +87,7 @@ export default function DocumentBar() {
|
|
|
86
87
|
return {
|
|
87
88
|
postType: _postType,
|
|
88
89
|
document: _document,
|
|
89
|
-
isResolving:
|
|
90
|
+
isResolving: isResolvingSelector(
|
|
90
91
|
'getEditedEntityRecord',
|
|
91
92
|
'postType',
|
|
92
93
|
_postType,
|
|
@@ -95,7 +95,8 @@ const computeOutlineHeadings = ( blocks = [] ) => {
|
|
|
95
95
|
};
|
|
96
96
|
|
|
97
97
|
const isEmptyHeading = ( heading ) =>
|
|
98
|
-
! heading.attributes.content ||
|
|
98
|
+
! heading.attributes.content ||
|
|
99
|
+
heading.attributes.content.trim().length === 0;
|
|
99
100
|
|
|
100
101
|
export default function DocumentOutline( {
|
|
101
102
|
onSelect,
|
|
@@ -4,29 +4,24 @@
|
|
|
4
4
|
import { useSelect } from '@wordpress/data';
|
|
5
5
|
import { store as coreStore } from '@wordpress/core-data';
|
|
6
6
|
import { useMemo, useState } from '@wordpress/element';
|
|
7
|
-
import { __ } from '@wordpress/i18n';
|
|
8
|
-
|
|
9
|
-
const TRANSLATED_SITE_PROPERTIES = {
|
|
10
|
-
title: __( 'Title' ),
|
|
11
|
-
description: __( 'Tagline' ),
|
|
12
|
-
site_logo: __( 'Logo' ),
|
|
13
|
-
site_icon: __( 'Icon' ),
|
|
14
|
-
show_on_front: __( 'Show on front' ),
|
|
15
|
-
page_on_front: __( 'Page on front' ),
|
|
16
|
-
posts_per_page: __( 'Maximum posts per page' ),
|
|
17
|
-
default_comment_status: __( 'Allow comments on new posts' ),
|
|
18
|
-
};
|
|
19
7
|
|
|
20
8
|
export const useIsDirty = () => {
|
|
21
|
-
const { editedEntities, siteEdits } = useSelect(
|
|
22
|
-
|
|
23
|
-
|
|
9
|
+
const { editedEntities, siteEdits, siteEntityConfig } = useSelect(
|
|
10
|
+
( select ) => {
|
|
11
|
+
const {
|
|
12
|
+
__experimentalGetDirtyEntityRecords,
|
|
13
|
+
getEntityRecordEdits,
|
|
14
|
+
getEntityConfig,
|
|
15
|
+
} = select( coreStore );
|
|
24
16
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
17
|
+
return {
|
|
18
|
+
editedEntities: __experimentalGetDirtyEntityRecords(),
|
|
19
|
+
siteEdits: getEntityRecordEdits( 'root', 'site' ),
|
|
20
|
+
siteEntityConfig: getEntityConfig( 'root', 'site' ),
|
|
21
|
+
};
|
|
22
|
+
},
|
|
23
|
+
[]
|
|
24
|
+
);
|
|
30
25
|
|
|
31
26
|
const dirtyEntityRecords = useMemo( () => {
|
|
32
27
|
// Remove site object and decouple into its edited pieces.
|
|
@@ -34,18 +29,19 @@ export const useIsDirty = () => {
|
|
|
34
29
|
( record ) => ! ( record.kind === 'root' && record.name === 'site' )
|
|
35
30
|
);
|
|
36
31
|
|
|
32
|
+
const siteEntityLabels = siteEntityConfig?.meta?.labels ?? {};
|
|
37
33
|
const editedSiteEntities = [];
|
|
38
34
|
for ( const property in siteEdits ) {
|
|
39
35
|
editedSiteEntities.push( {
|
|
40
36
|
kind: 'root',
|
|
41
37
|
name: 'site',
|
|
42
|
-
title:
|
|
38
|
+
title: siteEntityLabels[ property ] || property,
|
|
43
39
|
property,
|
|
44
40
|
} );
|
|
45
41
|
}
|
|
46
42
|
|
|
47
43
|
return [ ...editedEntitiesWithoutSite, ...editedSiteEntities ];
|
|
48
|
-
}, [ editedEntities, siteEdits ] );
|
|
44
|
+
}, [ editedEntities, siteEdits, siteEntityConfig ] );
|
|
49
45
|
|
|
50
46
|
// Unchecked entities to be ignored by save function.
|
|
51
47
|
const [ unselectedEntities, _setUnselectedEntities ] = useState( [] );
|
|
@@ -11,7 +11,10 @@ import {
|
|
|
11
11
|
} from '@wordpress/element';
|
|
12
12
|
import { store as coreStore } from '@wordpress/core-data';
|
|
13
13
|
import { store as blockEditorStore } from '@wordpress/block-editor';
|
|
14
|
-
import {
|
|
14
|
+
import {
|
|
15
|
+
__experimentalUseDialog as useDialog,
|
|
16
|
+
useInstanceId,
|
|
17
|
+
} from '@wordpress/compose';
|
|
15
18
|
import { store as noticesStore } from '@wordpress/notices';
|
|
16
19
|
|
|
17
20
|
/**
|
|
@@ -31,10 +34,17 @@ function identity( values ) {
|
|
|
31
34
|
return values;
|
|
32
35
|
}
|
|
33
36
|
|
|
34
|
-
export default function EntitiesSavedStates( {
|
|
37
|
+
export default function EntitiesSavedStates( {
|
|
38
|
+
close,
|
|
39
|
+
renderDialog = undefined,
|
|
40
|
+
} ) {
|
|
35
41
|
const isDirtyProps = useIsDirty();
|
|
36
42
|
return (
|
|
37
|
-
<EntitiesSavedStatesExtensible
|
|
43
|
+
<EntitiesSavedStatesExtensible
|
|
44
|
+
close={ close }
|
|
45
|
+
renderDialog={ renderDialog }
|
|
46
|
+
{ ...isDirtyProps }
|
|
47
|
+
/>
|
|
38
48
|
);
|
|
39
49
|
}
|
|
40
50
|
|
|
@@ -44,6 +54,7 @@ export function EntitiesSavedStatesExtensible( {
|
|
|
44
54
|
onSave = identity,
|
|
45
55
|
saveEnabled: saveEnabledProp = undefined,
|
|
46
56
|
saveLabel = __( 'Save' ),
|
|
57
|
+
renderDialog = undefined,
|
|
47
58
|
|
|
48
59
|
dirtyEntityRecords,
|
|
49
60
|
isDirty,
|
|
@@ -183,12 +194,20 @@ export function EntitiesSavedStatesExtensible( {
|
|
|
183
194
|
const [ saveDialogRef, saveDialogProps ] = useDialog( {
|
|
184
195
|
onClose: () => dismissPanel(),
|
|
185
196
|
} );
|
|
197
|
+
const dialogLabel = useInstanceId( EntitiesSavedStatesExtensible, 'label' );
|
|
198
|
+
const dialogDescription = useInstanceId(
|
|
199
|
+
EntitiesSavedStatesExtensible,
|
|
200
|
+
'description'
|
|
201
|
+
);
|
|
186
202
|
|
|
187
203
|
return (
|
|
188
204
|
<div
|
|
189
205
|
ref={ saveDialogRef }
|
|
190
206
|
{ ...saveDialogProps }
|
|
191
207
|
className="entities-saved-states__panel"
|
|
208
|
+
role={ renderDialog ? 'dialog' : undefined }
|
|
209
|
+
aria-labelledby={ renderDialog ? dialogLabel : undefined }
|
|
210
|
+
aria-describedby={ renderDialog ? dialogDescription : undefined }
|
|
192
211
|
>
|
|
193
212
|
<Flex className="entities-saved-states__panel-header" gap={ 2 }>
|
|
194
213
|
<FlexItem
|
|
@@ -197,6 +216,7 @@ export function EntitiesSavedStatesExtensible( {
|
|
|
197
216
|
ref={ saveButtonRef }
|
|
198
217
|
variant="primary"
|
|
199
218
|
disabled={ ! saveEnabled }
|
|
219
|
+
__experimentalIsFocusable
|
|
200
220
|
onClick={ saveCheckedEntities }
|
|
201
221
|
className="editor-entities-saved-states__save-button"
|
|
202
222
|
>
|
|
@@ -213,11 +233,16 @@ export function EntitiesSavedStatesExtensible( {
|
|
|
213
233
|
</Flex>
|
|
214
234
|
|
|
215
235
|
<div className="entities-saved-states__text-prompt">
|
|
216
|
-
<
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
236
|
+
<div
|
|
237
|
+
className="entities-saved-states__text-prompt--header-wrapper"
|
|
238
|
+
id={ renderDialog ? dialogLabel : undefined }
|
|
239
|
+
>
|
|
240
|
+
<strong className="entities-saved-states__text-prompt--header">
|
|
241
|
+
{ __( 'Are you ready to save?' ) }
|
|
242
|
+
</strong>
|
|
243
|
+
{ additionalPrompt }
|
|
244
|
+
</div>
|
|
245
|
+
<p id={ renderDialog ? dialogDescription : undefined }>
|
|
221
246
|
{ isDirty
|
|
222
247
|
? createInterpolateElement(
|
|
223
248
|
sprintf(
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* External dependencies
|
|
3
|
+
*/
|
|
4
|
+
import { ScrollView, Text, TouchableOpacity, View } from 'react-native';
|
|
5
|
+
import Clipboard from '@react-native-clipboard/clipboard';
|
|
6
|
+
import { SafeAreaView } from 'react-native-safe-area-context';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* WordPress dependencies
|
|
10
|
+
*/
|
|
11
|
+
import { Component } from '@wordpress/element';
|
|
12
|
+
import { __ } from '@wordpress/i18n';
|
|
13
|
+
import { select } from '@wordpress/data';
|
|
14
|
+
import { logException } from '@wordpress/react-native-bridge';
|
|
15
|
+
import {
|
|
16
|
+
usePreferredColorSchemeStyle,
|
|
17
|
+
withPreferredColorScheme,
|
|
18
|
+
} from '@wordpress/compose';
|
|
19
|
+
import { warning } from '@wordpress/icons';
|
|
20
|
+
import { Icon } from '@wordpress/components';
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Internal dependencies
|
|
24
|
+
*/
|
|
25
|
+
import { store as editorStore } from '../../store';
|
|
26
|
+
import styles from './style.scss';
|
|
27
|
+
|
|
28
|
+
function getContent() {
|
|
29
|
+
try {
|
|
30
|
+
// While `select` in a component is generally discouraged, it is
|
|
31
|
+
// used here because it (a) reduces the chance of data loss in the
|
|
32
|
+
// case of additional errors by performing a direct retrieval and
|
|
33
|
+
// (b) avoids the performance cost associated with unnecessary
|
|
34
|
+
// content serialization throughout the lifetime of a non-erroring
|
|
35
|
+
// application.
|
|
36
|
+
return select( editorStore ).getEditedPostContent();
|
|
37
|
+
} catch ( error ) {}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function CopyButton( {
|
|
41
|
+
text,
|
|
42
|
+
label,
|
|
43
|
+
accessibilityLabel,
|
|
44
|
+
accessibilityHint,
|
|
45
|
+
secondary = false,
|
|
46
|
+
} ) {
|
|
47
|
+
const containerStyle = usePreferredColorSchemeStyle(
|
|
48
|
+
styles[ 'copy-button__container' ],
|
|
49
|
+
styles[ 'copy-button__container--dark' ]
|
|
50
|
+
);
|
|
51
|
+
|
|
52
|
+
const containerSecondaryStyle = usePreferredColorSchemeStyle(
|
|
53
|
+
styles[ 'copy-button__container--secondary' ],
|
|
54
|
+
styles[ 'copy-button__container--secondary-dark' ]
|
|
55
|
+
);
|
|
56
|
+
|
|
57
|
+
const textStyle = usePreferredColorSchemeStyle(
|
|
58
|
+
styles[ 'copy-button__text' ],
|
|
59
|
+
styles[ 'copy-button__text--dark' ]
|
|
60
|
+
);
|
|
61
|
+
|
|
62
|
+
const textSecondaryStyle = usePreferredColorSchemeStyle(
|
|
63
|
+
styles[ 'copy-button__text--secondary' ],
|
|
64
|
+
styles[ 'copy-button__text--secondary-dark' ]
|
|
65
|
+
);
|
|
66
|
+
|
|
67
|
+
return (
|
|
68
|
+
<TouchableOpacity
|
|
69
|
+
activeOpacity={ 0.5 }
|
|
70
|
+
accessibilityLabel={ accessibilityLabel }
|
|
71
|
+
style={ [ containerStyle, secondary && containerSecondaryStyle ] }
|
|
72
|
+
accessibilityRole={ 'button' }
|
|
73
|
+
accessibilityHint={ accessibilityHint }
|
|
74
|
+
onPress={ () => {
|
|
75
|
+
Clipboard.setString(
|
|
76
|
+
typeof text === 'function' ? text() : text || ''
|
|
77
|
+
);
|
|
78
|
+
} }
|
|
79
|
+
>
|
|
80
|
+
<Text style={ [ textStyle, secondary && textSecondaryStyle ] }>
|
|
81
|
+
{ label }
|
|
82
|
+
</Text>
|
|
83
|
+
</TouchableOpacity>
|
|
84
|
+
);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
class ErrorBoundary extends Component {
|
|
88
|
+
constructor() {
|
|
89
|
+
super( ...arguments );
|
|
90
|
+
|
|
91
|
+
this.state = {
|
|
92
|
+
error: null,
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
componentDidCatch( error ) {
|
|
97
|
+
logException( error, {
|
|
98
|
+
context: {
|
|
99
|
+
component_stack: error.componentStack,
|
|
100
|
+
},
|
|
101
|
+
isHandled: true,
|
|
102
|
+
handledBy: 'Editor-level Error Boundary',
|
|
103
|
+
} );
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
static getDerivedStateFromError( error ) {
|
|
107
|
+
return { error };
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
render() {
|
|
111
|
+
const { error } = this.state;
|
|
112
|
+
if ( ! error ) {
|
|
113
|
+
return this.props.children;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
const { getStylesFromColorScheme } = this.props;
|
|
117
|
+
|
|
118
|
+
const iconContainerStyle = getStylesFromColorScheme(
|
|
119
|
+
styles[ 'error-boundary__icon-container' ],
|
|
120
|
+
styles[ 'error-boundary__icon-container--dark' ]
|
|
121
|
+
);
|
|
122
|
+
|
|
123
|
+
const titleStyle = getStylesFromColorScheme(
|
|
124
|
+
styles[ 'error-boundary__title' ],
|
|
125
|
+
styles[ 'error-boundary__title--dark' ]
|
|
126
|
+
);
|
|
127
|
+
|
|
128
|
+
const messageStyle = getStylesFromColorScheme(
|
|
129
|
+
styles[ 'error-boundary__message' ],
|
|
130
|
+
styles[ 'error-boundary__message--dark' ]
|
|
131
|
+
);
|
|
132
|
+
|
|
133
|
+
return (
|
|
134
|
+
<SafeAreaView>
|
|
135
|
+
<ScrollView
|
|
136
|
+
style={ styles[ 'error-boundary__scroll' ] }
|
|
137
|
+
contentContainerStyle={
|
|
138
|
+
styles[ 'error-boundary__scroll-container' ]
|
|
139
|
+
}
|
|
140
|
+
>
|
|
141
|
+
<View style={ styles[ 'error-boundary__container' ] }>
|
|
142
|
+
<View style={ iconContainerStyle }>
|
|
143
|
+
<Icon
|
|
144
|
+
icon={ warning }
|
|
145
|
+
{ ...styles[ 'error-boundary__icon' ] }
|
|
146
|
+
/>
|
|
147
|
+
</View>
|
|
148
|
+
<Text style={ titleStyle }>
|
|
149
|
+
{ __(
|
|
150
|
+
'The editor has encountered an unexpected error'
|
|
151
|
+
) }
|
|
152
|
+
</Text>
|
|
153
|
+
<Text style={ messageStyle }>
|
|
154
|
+
{ __(
|
|
155
|
+
'You can copy your post text in case your content is impacted. Copy error details to debug and share with support.'
|
|
156
|
+
) }
|
|
157
|
+
</Text>
|
|
158
|
+
<View
|
|
159
|
+
style={
|
|
160
|
+
styles[ 'error-boundary__actions-container' ]
|
|
161
|
+
}
|
|
162
|
+
>
|
|
163
|
+
<CopyButton
|
|
164
|
+
label={ __( 'Copy post text' ) }
|
|
165
|
+
accessibilityLabel={ __(
|
|
166
|
+
'Button to copy post text'
|
|
167
|
+
) }
|
|
168
|
+
accessibilityHint={ __(
|
|
169
|
+
'Tap here to copy post text'
|
|
170
|
+
) }
|
|
171
|
+
text={ getContent }
|
|
172
|
+
/>
|
|
173
|
+
<CopyButton
|
|
174
|
+
label={ __( 'Copy error details' ) }
|
|
175
|
+
accessibilityLabel={ __(
|
|
176
|
+
'Button to copy error details'
|
|
177
|
+
) }
|
|
178
|
+
accessibilityHint={ __(
|
|
179
|
+
'Tap here to copy error details'
|
|
180
|
+
) }
|
|
181
|
+
text={ error.stack }
|
|
182
|
+
secondary
|
|
183
|
+
/>
|
|
184
|
+
</View>
|
|
185
|
+
</View>
|
|
186
|
+
</ScrollView>
|
|
187
|
+
</SafeAreaView>
|
|
188
|
+
);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
export default withPreferredColorScheme( ErrorBoundary );
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
.error-boundary__scroll {
|
|
2
|
+
height: 100%;
|
|
3
|
+
width: 100%;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
.error-boundary__scroll-container {
|
|
7
|
+
flex-grow: 1;
|
|
8
|
+
max-height: 580px;
|
|
9
|
+
align-items: center;
|
|
10
|
+
justify-content: center;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
.error-boundary__container {
|
|
15
|
+
width: 100%;
|
|
16
|
+
max-width: 600px;
|
|
17
|
+
justify-content: center;
|
|
18
|
+
align-items: center;
|
|
19
|
+
padding: 0 24px;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
.error-boundary__icon-container {
|
|
23
|
+
$size: 40px;
|
|
24
|
+
|
|
25
|
+
width: $size;
|
|
26
|
+
height: $size;
|
|
27
|
+
align-items: center;
|
|
28
|
+
justify-content: center;
|
|
29
|
+
margin-bottom: 8px;
|
|
30
|
+
background-color: rgba(60, 60, 67, 0.3);
|
|
31
|
+
border-radius: $size/2;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
.error-boundary__icon-container--dark {
|
|
35
|
+
background-color: rgba(235, 235, 245, 0.3);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
.error-boundary__icon {
|
|
39
|
+
width: 24px;
|
|
40
|
+
height: 24px;
|
|
41
|
+
fill: $white;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
.error-boundary__title {
|
|
45
|
+
font-size: 20px;
|
|
46
|
+
font-weight: 600;
|
|
47
|
+
line-height: 25px;
|
|
48
|
+
color: $black;
|
|
49
|
+
text-align: center;
|
|
50
|
+
margin-bottom: 8px;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
.error-boundary__title--dark {
|
|
54
|
+
color: $white;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
.error-boundary__message {
|
|
58
|
+
font-size: 16px;
|
|
59
|
+
font-weight: 400;
|
|
60
|
+
line-height: 21px;
|
|
61
|
+
color: rgba(60, 60, 67, 0.6);
|
|
62
|
+
text-align: center;
|
|
63
|
+
margin-bottom: 16px;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
.error-boundary__message--dark {
|
|
67
|
+
color: rgba(235, 235, 245, 0.6);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
.error-boundary__actions-container {
|
|
71
|
+
width: 100%;
|
|
72
|
+
max-width: 400px;
|
|
73
|
+
justify-content: center;
|
|
74
|
+
gap: 12px;
|
|
75
|
+
padding-top: 16px;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
.copy-button__container {
|
|
79
|
+
border-radius: 5px;
|
|
80
|
+
padding: $grid-unit $grid-unit-20;
|
|
81
|
+
background-color: $light-primary;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
.copy-button__container--dark {
|
|
85
|
+
background-color: $white;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
.copy-button__container--secondary {
|
|
89
|
+
border: 1px #c6c6c8;
|
|
90
|
+
background-color: $white;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
.copy-button__container--secondary-dark {
|
|
94
|
+
border-color: rgba(255, 255, 255, 0.3);
|
|
95
|
+
background-color: $black;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
.copy-button__text {
|
|
99
|
+
font-size: 17px;
|
|
100
|
+
font-weight: 400;
|
|
101
|
+
line-height: 22px;
|
|
102
|
+
text-align: center;
|
|
103
|
+
color: $white;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
.copy-button__text--dark {
|
|
107
|
+
color: $background-dark-secondary;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
.copy-button__text--secondary {
|
|
111
|
+
color: $black;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
.copy-button__text--secondary-dark {
|
|
115
|
+
color: $white;
|
|
116
|
+
}
|
package/src/components/index.js
CHANGED
|
@@ -26,6 +26,7 @@ export { default as PageAttributesOrder } from './page-attributes/order';
|
|
|
26
26
|
export { default as PageAttributesPanel } from './page-attributes/panel';
|
|
27
27
|
export { default as PageAttributesParent } from './page-attributes/parent';
|
|
28
28
|
export { default as PageTemplate } from './post-template/classic-theme';
|
|
29
|
+
export { default as PluginDocumentSettingPanel } from './plugin-document-setting-panel';
|
|
29
30
|
export { default as PostTemplatePanel } from './post-template/panel';
|
|
30
31
|
export { default as PostAuthor } from './post-author';
|
|
31
32
|
export { default as PostAuthorCheck } from './post-author/check';
|
|
@@ -64,10 +65,7 @@ export { default as PostSlugCheck } from './post-slug/check';
|
|
|
64
65
|
export { default as PostSticky } from './post-sticky';
|
|
65
66
|
export { default as PostStickyCheck } from './post-sticky/check';
|
|
66
67
|
export { default as PostSwitchToDraftButton } from './post-switch-to-draft-button';
|
|
67
|
-
export {
|
|
68
|
-
default as PostSyncStatus,
|
|
69
|
-
PostSyncStatusModal,
|
|
70
|
-
} from './post-sync-status';
|
|
68
|
+
export { default as PostSyncStatus } from './post-sync-status';
|
|
71
69
|
export { default as PostTaxonomies } from './post-taxonomies';
|
|
72
70
|
export { FlatTermSelector as PostTaxonomiesFlatTermSelector } from './post-taxonomies/flat-term-selector';
|
|
73
71
|
export { HierarchicalTermSelector as PostTaxonomiesHierarchicalTermSelector } from './post-taxonomies/hierarchical-term-selector';
|
|
@@ -10,5 +10,6 @@ export { default as EditorProvider } from './provider';
|
|
|
10
10
|
// Other Components.
|
|
11
11
|
export { default as EditorHelpTopics } from './editor-help';
|
|
12
12
|
export { default as OfflineStatus } from './offline-status';
|
|
13
|
+
export { default as ErrorBoundary } from './error-boundary';
|
|
13
14
|
|
|
14
15
|
export * from './deprecated';
|