@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.
Files changed (87) hide show
  1. package/CHANGELOG.md +2 -0
  2. package/build/bindings/index.js +3 -1
  3. package/build/bindings/index.js.map +1 -1
  4. package/build/components/document-bar/index.js +2 -2
  5. package/build/components/document-bar/index.js.map +1 -1
  6. package/build/components/document-outline/index.js +1 -1
  7. package/build/components/document-outline/index.js.map +1 -1
  8. package/build/components/entities-saved-states/hooks/use-is-dirty.js +10 -16
  9. package/build/components/entities-saved-states/hooks/use-is-dirty.js.map +1 -1
  10. package/build/components/entities-saved-states/index.js +17 -3
  11. package/build/components/entities-saved-states/index.js.map +1 -1
  12. package/build/components/error-boundary/index.native.js +133 -0
  13. package/build/components/error-boundary/index.native.js.map +1 -0
  14. package/build/components/index.js +9 -8
  15. package/build/components/index.js.map +1 -1
  16. package/build/components/index.native.js +9 -1
  17. package/build/components/index.native.js.map +1 -1
  18. package/build/components/plugin-document-setting-panel/index.js +123 -0
  19. package/build/components/plugin-document-setting-panel/index.js.map +1 -0
  20. package/build/components/post-featured-image/index.js +3 -8
  21. package/build/components/post-featured-image/index.js.map +1 -1
  22. package/build/components/post-featured-image/panel.js +7 -3
  23. package/build/components/post-featured-image/panel.js.map +1 -1
  24. package/build/components/post-sync-status/index.js +0 -72
  25. package/build/components/post-sync-status/index.js.map +1 -1
  26. package/build/components/post-taxonomies/flat-term-selector.js +7 -3
  27. package/build/components/post-taxonomies/flat-term-selector.js.map +1 -1
  28. package/build/components/provider/index.js +1 -1
  29. package/build/components/provider/index.js.map +1 -1
  30. package/build/components/provider/use-hide-blocks-from-inserter.js +4 -3
  31. package/build/components/provider/use-hide-blocks-from-inserter.js.map +1 -1
  32. package/build/private-apis.js +0 -2
  33. package/build/private-apis.js.map +1 -1
  34. package/build-module/bindings/index.js +3 -1
  35. package/build-module/bindings/index.js.map +1 -1
  36. package/build-module/components/document-bar/index.js +2 -2
  37. package/build-module/components/document-bar/index.js.map +1 -1
  38. package/build-module/components/document-outline/index.js +1 -1
  39. package/build-module/components/document-outline/index.js.map +1 -1
  40. package/build-module/components/entities-saved-states/hooks/use-is-dirty.js +10 -16
  41. package/build-module/components/entities-saved-states/hooks/use-is-dirty.js.map +1 -1
  42. package/build-module/components/entities-saved-states/index.js +18 -4
  43. package/build-module/components/entities-saved-states/index.js.map +1 -1
  44. package/build-module/components/error-boundary/index.native.js +125 -0
  45. package/build-module/components/error-boundary/index.native.js.map +1 -0
  46. package/build-module/components/index.js +2 -1
  47. package/build-module/components/index.js.map +1 -1
  48. package/build-module/components/index.native.js +1 -0
  49. package/build-module/components/index.native.js.map +1 -1
  50. package/build-module/components/plugin-document-setting-panel/index.js +115 -0
  51. package/build-module/components/plugin-document-setting-panel/index.js.map +1 -0
  52. package/build-module/components/post-featured-image/index.js +4 -9
  53. package/build-module/components/post-featured-image/index.js.map +1 -1
  54. package/build-module/components/post-featured-image/panel.js +6 -2
  55. package/build-module/components/post-featured-image/panel.js.map +1 -1
  56. package/build-module/components/post-sync-status/index.js +2 -73
  57. package/build-module/components/post-sync-status/index.js.map +1 -1
  58. package/build-module/components/post-taxonomies/flat-term-selector.js +7 -3
  59. package/build-module/components/post-taxonomies/flat-term-selector.js.map +1 -1
  60. package/build-module/components/provider/index.js +1 -1
  61. package/build-module/components/provider/index.js.map +1 -1
  62. package/build-module/components/provider/use-hide-blocks-from-inserter.js +4 -3
  63. package/build-module/components/provider/use-hide-blocks-from-inserter.js.map +1 -1
  64. package/build-module/private-apis.js +0 -2
  65. package/build-module/private-apis.js.map +1 -1
  66. package/build-style/style-rtl.css +8 -8
  67. package/build-style/style.css +8 -8
  68. package/package.json +34 -32
  69. package/src/bindings/index.js +4 -1
  70. package/src/components/document-bar/index.js +3 -2
  71. package/src/components/document-outline/index.js +2 -1
  72. package/src/components/entities-saved-states/hooks/use-is-dirty.js +18 -22
  73. package/src/components/entities-saved-states/index.js +33 -8
  74. package/src/components/entities-saved-states/test/use-is-dirty.js +3 -0
  75. package/src/components/error-boundary/index.native.js +192 -0
  76. package/src/components/error-boundary/style.native.scss +116 -0
  77. package/src/components/index.js +2 -4
  78. package/src/components/index.native.js +1 -0
  79. package/src/components/plugin-document-setting-panel/index.js +121 -0
  80. package/src/components/post-featured-image/index.js +6 -15
  81. package/src/components/post-featured-image/panel.js +9 -3
  82. package/src/components/post-featured-image/style.scss +8 -13
  83. package/src/components/post-sync-status/index.js +1 -94
  84. package/src/components/post-taxonomies/flat-term-selector.js +13 -8
  85. package/src/components/provider/index.js +1 -1
  86. package/src/components/provider/use-hide-blocks-from-inserter.js +5 -3
  87. package/src/private-apis.js +0 -2
@@ -0,0 +1,121 @@
1
+ /**
2
+ * WordPress dependencies
3
+ */
4
+ import { createSlotFill, PanelBody } from '@wordpress/components';
5
+ import { usePluginContext } from '@wordpress/plugins';
6
+ import { useDispatch, useSelect } from '@wordpress/data';
7
+ import warning from '@wordpress/warning';
8
+
9
+ /**
10
+ * Internal dependencies
11
+ */
12
+ import EnablePluginDocumentSettingPanelOption from '../preferences-modal/enable-plugin-document-setting-panel';
13
+ import { store as editorStore } from '../../store';
14
+
15
+ const { Fill, Slot } = createSlotFill( 'PluginDocumentSettingPanel' );
16
+
17
+ /**
18
+ * Renders items below the Status & Availability panel in the Document Sidebar.
19
+ *
20
+ * @param {Object} props Component properties.
21
+ * @param {string} props.name Required. A machine-friendly name for the panel.
22
+ * @param {string} [props.className] An optional class name added to the row.
23
+ * @param {string} [props.title] The title of the panel
24
+ * @param {WPBlockTypeIconRender} [props.icon=inherits from the plugin] The [Dashicon](https://developer.wordpress.org/resource/dashicons/) icon slug string, or an SVG WP element, to be rendered when the sidebar is pinned to toolbar.
25
+ * @param {Element} props.children Children to be rendered
26
+ *
27
+ * @example
28
+ * ```js
29
+ * // Using ES5 syntax
30
+ * var el = React.createElement;
31
+ * var __ = wp.i18n.__;
32
+ * var registerPlugin = wp.plugins.registerPlugin;
33
+ * var PluginDocumentSettingPanel = wp.editor.PluginDocumentSettingPanel;
34
+ *
35
+ * function MyDocumentSettingPlugin() {
36
+ * return el(
37
+ * PluginDocumentSettingPanel,
38
+ * {
39
+ * className: 'my-document-setting-plugin',
40
+ * title: 'My Panel',
41
+ * name: 'my-panel',
42
+ * },
43
+ * __( 'My Document Setting Panel' )
44
+ * );
45
+ * }
46
+ *
47
+ * registerPlugin( 'my-document-setting-plugin', {
48
+ * render: MyDocumentSettingPlugin
49
+ * } );
50
+ * ```
51
+ *
52
+ * @example
53
+ * ```jsx
54
+ * // Using ESNext syntax
55
+ * import { registerPlugin } from '@wordpress/plugins';
56
+ * import { PluginDocumentSettingPanel } from '@wordpress/editor';
57
+ *
58
+ * const MyDocumentSettingTest = () => (
59
+ * <PluginDocumentSettingPanel className="my-document-setting-plugin" title="My Panel" name="my-panel">
60
+ * <p>My Document Setting Panel</p>
61
+ * </PluginDocumentSettingPanel>
62
+ * );
63
+ *
64
+ * registerPlugin( 'document-setting-test', { render: MyDocumentSettingTest } );
65
+ * ```
66
+ *
67
+ * @return {Component} The component to be rendered.
68
+ */
69
+ const PluginDocumentSettingPanel = ( {
70
+ name,
71
+ className,
72
+ title,
73
+ icon,
74
+ children,
75
+ } ) => {
76
+ const { name: pluginName } = usePluginContext();
77
+ const panelName = `${ pluginName }/${ name }`;
78
+ const { opened, isEnabled } = useSelect(
79
+ ( select ) => {
80
+ const { isEditorPanelOpened, isEditorPanelEnabled } =
81
+ select( editorStore );
82
+
83
+ return {
84
+ opened: isEditorPanelOpened( panelName ),
85
+ isEnabled: isEditorPanelEnabled( panelName ),
86
+ };
87
+ },
88
+ [ panelName ]
89
+ );
90
+ const { toggleEditorPanelOpened } = useDispatch( editorStore );
91
+
92
+ if ( undefined === name ) {
93
+ warning( 'PluginDocumentSettingPanel requires a name property.' );
94
+ }
95
+
96
+ return (
97
+ <>
98
+ <EnablePluginDocumentSettingPanelOption
99
+ label={ title }
100
+ panelName={ panelName }
101
+ />
102
+ <Fill>
103
+ { isEnabled && (
104
+ <PanelBody
105
+ className={ className }
106
+ title={ title }
107
+ icon={ icon }
108
+ opened={ opened }
109
+ onToggle={ () => toggleEditorPanelOpened( panelName ) }
110
+ >
111
+ { children }
112
+ </PanelBody>
113
+ ) }
114
+ </Fill>
115
+ </>
116
+ );
117
+ };
118
+
119
+ PluginDocumentSettingPanel.Slot = Slot;
120
+
121
+ export default PluginDocumentSettingPanel;
@@ -7,7 +7,6 @@ import {
7
7
  DropZone,
8
8
  Button,
9
9
  Spinner,
10
- ResponsiveWrapper,
11
10
  withNotices,
12
11
  withFilters,
13
12
  __experimentalHStack as HStack,
@@ -99,10 +98,7 @@ function PostFeaturedImage( {
99
98
  const toggleRef = useRef();
100
99
  const [ isLoading, setIsLoading ] = useState( false );
101
100
  const { getSettings } = useSelect( blockEditorStore );
102
- const { mediaWidth, mediaHeight, mediaSourceUrl } = getMediaDetails(
103
- media,
104
- currentPostId
105
- );
101
+ const { mediaSourceUrl } = getMediaDetails( media, currentPostId );
106
102
 
107
103
  function onDropFiles( filesList ) {
108
104
  getSettings().mediaUpload( {
@@ -183,16 +179,11 @@ function PostFeaturedImage( {
183
179
  }
184
180
  >
185
181
  { !! featuredImageId && media && (
186
- <ResponsiveWrapper
187
- naturalWidth={ mediaWidth }
188
- naturalHeight={ mediaHeight }
189
- isInline
190
- >
191
- <img
192
- src={ mediaSourceUrl }
193
- alt=""
194
- />
195
- </ResponsiveWrapper>
182
+ <img
183
+ className="editor-post-featured-image__preview-image"
184
+ src={ mediaSourceUrl }
185
+ alt=""
186
+ />
196
187
  ) }
197
188
  { isLoading && <Spinner /> }
198
189
  { ! featuredImageId &&
@@ -15,7 +15,7 @@ import PostFeaturedImageCheck from './check';
15
15
 
16
16
  const PANEL_NAME = 'featured-image';
17
17
 
18
- function FeaturedImage() {
18
+ export default function PostFeaturedImagePanel( { withPanelBody = true } ) {
19
19
  const { postType, isEnabled, isOpened } = useSelect( ( select ) => {
20
20
  const {
21
21
  getEditedPostAttribute,
@@ -37,6 +37,14 @@ function FeaturedImage() {
37
37
  return null;
38
38
  }
39
39
 
40
+ if ( ! withPanelBody ) {
41
+ return (
42
+ <PostFeaturedImageCheck>
43
+ <PostFeaturedImage />
44
+ </PostFeaturedImageCheck>
45
+ );
46
+ }
47
+
40
48
  return (
41
49
  <PostFeaturedImageCheck>
42
50
  <PanelBody
@@ -51,5 +59,3 @@ function FeaturedImage() {
51
59
  </PostFeaturedImageCheck>
52
60
  );
53
61
  }
54
-
55
- export default FeaturedImage;
@@ -1,7 +1,6 @@
1
1
  .editor-post-featured-image {
2
2
  padding: 0;
3
3
 
4
-
5
4
  .components-spinner {
6
5
  position: absolute;
7
6
  top: 50%;
@@ -9,17 +8,11 @@
9
8
  margin-top: -9px;
10
9
  margin-left: -9px;
11
10
  }
12
-
13
- // This keeps images at their intrinsic size (eg. a 50px
14
- // image will never be wider than 50px).
15
- .components-responsive-wrapper__content {
16
- max-width: 100%;
17
- width: auto;
18
- }
19
11
  }
20
12
 
21
13
  .editor-post-featured-image__container {
22
14
  position: relative;
15
+ aspect-ratio: 2/1;
23
16
 
24
17
  &:hover,
25
18
  &:focus,
@@ -38,26 +31,28 @@
38
31
  @include reduce-motion("transition");
39
32
  box-shadow: 0 0 0 0 var(--wp-admin-theme-color);
40
33
  overflow: hidden; // Ensure the focus style properly encapsulates the image.
34
+ outline: $border-width solid rgba(0, 0, 0, 0.1);
35
+ outline-offset: -#{$border-width};
41
36
 
42
- // Apply a max-height.
43
37
  display: flex;
44
38
  justify-content: center;
45
- max-height: 150px;
46
39
  }
47
40
 
48
41
  .editor-post-featured-image__preview {
49
42
  height: auto;
50
43
 
51
- .components-responsive-wrapper {
44
+ .editor-post-featured-image__preview-image {
45
+ object-fit: cover;
52
46
  width: 100%;
53
- background: $gray-100;
47
+ object-position: 50% 50%;
48
+ aspect-ratio: 2/1;
54
49
  }
55
50
  }
56
51
 
57
52
  .editor-post-featured-image__toggle {
58
53
  border-radius: $radius-block-ui;
59
54
  background-color: $gray-100;
60
- min-height: 90px;
55
+ height: 100%;
61
56
  line-height: 20px;
62
57
  padding: $grid-unit-10 0;
63
58
  text-align: center;
@@ -1,26 +1,14 @@
1
1
  /**
2
2
  * WordPress dependencies
3
3
  */
4
- import { useSelect, useDispatch } from '@wordpress/data';
4
+ import { useSelect } from '@wordpress/data';
5
5
  import { __, _x } from '@wordpress/i18n';
6
- import {
7
- Modal,
8
- Button,
9
- __experimentalHStack as HStack,
10
- __experimentalVStack as VStack,
11
- ToggleControl,
12
- } from '@wordpress/components';
13
- import { useEffect, useState } from '@wordpress/element';
14
- import { privateApis as blockEditorPrivateApis } from '@wordpress/block-editor';
15
6
 
16
7
  /**
17
8
  * Internal dependencies
18
9
  */
19
10
  import PostPanelRow from '../post-panel-row';
20
11
  import { store as editorStore } from '../../store';
21
- import { unlock } from '../../lock-unlock';
22
-
23
- const { ReusableBlocksRenameHint } = unlock( blockEditorPrivateApis );
24
12
 
25
13
  export default function PostSyncStatus() {
26
14
  const { syncStatus, postType } = useSelect( ( select ) => {
@@ -59,84 +47,3 @@ export default function PostSyncStatus() {
59
47
  </PostPanelRow>
60
48
  );
61
49
  }
62
-
63
- export function PostSyncStatusModal() {
64
- const { editPost } = useDispatch( editorStore );
65
- const [ isModalOpen, setIsModalOpen ] = useState( false );
66
- const [ syncType, setSyncType ] = useState( undefined );
67
-
68
- const { postType, isNewPost } = useSelect( ( select ) => {
69
- const { getEditedPostAttribute, isCleanNewPost } =
70
- select( editorStore );
71
- return {
72
- postType: getEditedPostAttribute( 'type' ),
73
- isNewPost: isCleanNewPost(),
74
- };
75
- }, [] );
76
-
77
- useEffect( () => {
78
- if ( isNewPost && postType === 'wp_block' ) {
79
- setIsModalOpen( true );
80
- }
81
- // We only want the modal to open when the page is first loaded.
82
- // eslint-disable-next-line react-hooks/exhaustive-deps
83
- }, [] );
84
-
85
- const setSyncStatus = () => {
86
- editPost( {
87
- meta: {
88
- wp_pattern_sync_status: syncType,
89
- },
90
- } );
91
- };
92
-
93
- if ( postType !== 'wp_block' || ! isNewPost ) {
94
- return null;
95
- }
96
-
97
- return (
98
- <>
99
- { isModalOpen && (
100
- <Modal
101
- title={ __( 'Set pattern sync status' ) }
102
- onRequestClose={ () => {
103
- setIsModalOpen( false );
104
- } }
105
- overlayClassName="reusable-blocks-menu-items__convert-modal"
106
- >
107
- <form
108
- onSubmit={ ( event ) => {
109
- event.preventDefault();
110
- setIsModalOpen( false );
111
- setSyncStatus();
112
- } }
113
- >
114
- <VStack spacing="5">
115
- <ReusableBlocksRenameHint />
116
- <ToggleControl
117
- label={ _x(
118
- 'Synced',
119
- 'Option that makes an individual pattern synchronized'
120
- ) }
121
- help={ __(
122
- 'Sync this pattern across multiple locations.'
123
- ) }
124
- checked={ ! syncType }
125
- onChange={ () => {
126
- setSyncType(
127
- ! syncType ? 'unsynced' : undefined
128
- );
129
- } }
130
- />
131
- <HStack justify="right">
132
- <Button variant="primary" type="submit">
133
- { __( 'Create' ) }
134
- </Button>
135
- </HStack>
136
- </VStack>
137
- </form>
138
- </Modal>
139
- ) }
140
- </>
141
- );
142
- }
@@ -40,10 +40,13 @@ const isSameTermName = ( termA, termB ) =>
40
40
  unescapeString( termB ).toLowerCase();
41
41
 
42
42
  const termNamesToIds = ( names, terms ) => {
43
- return names.map(
44
- ( termName ) =>
45
- terms.find( ( term ) => isSameTermName( term.name, termName ) ).id
46
- );
43
+ return names
44
+ .map(
45
+ ( termName ) =>
46
+ terms.find( ( term ) => isSameTermName( term.name, termName ) )
47
+ ?.id
48
+ )
49
+ .filter( ( id ) => id !== undefined );
47
50
  };
48
51
 
49
52
  export function FlatTermSelector( { slug } ) {
@@ -193,9 +196,8 @@ export function FlatTermSelector( { slug } ) {
193
196
  setValues( uniqueTerms );
194
197
 
195
198
  if ( newTermNames.length === 0 ) {
196
- return onUpdateTerms(
197
- termNamesToIds( uniqueTerms, availableTerms )
198
- );
199
+ onUpdateTerms( termNamesToIds( uniqueTerms, availableTerms ) );
200
+ return;
199
201
  }
200
202
 
201
203
  if ( ! hasCreateAction ) {
@@ -209,7 +211,7 @@ export function FlatTermSelector( { slug } ) {
209
211
  )
210
212
  .then( ( newTerms ) => {
211
213
  const newAvailableTerms = availableTerms.concat( newTerms );
212
- return onUpdateTerms(
214
+ onUpdateTerms(
213
215
  termNamesToIds( uniqueTerms, newAvailableTerms )
214
216
  );
215
217
  } )
@@ -217,6 +219,9 @@ export function FlatTermSelector( { slug } ) {
217
219
  createErrorNotice( error.message, {
218
220
  type: 'snackbar',
219
221
  } );
222
+ // In case of a failure, try assigning available terms.
223
+ // This will invalidate the optimistic update.
224
+ onUpdateTerms( termNamesToIds( uniqueTerms, availableTerms ) );
220
225
  } );
221
226
  }
222
227
 
@@ -232,7 +232,7 @@ export const ExperimentalEditorProvider = withRegistryProvider(
232
232
  setRenderingMode( settings.defaultRenderingMode ?? 'post-only' );
233
233
  }, [ settings.defaultRenderingMode, setRenderingMode ] );
234
234
 
235
- useHideBlocksFromInserter( post.type );
235
+ useHideBlocksFromInserter( post.type, mode );
236
236
 
237
237
  // Register the editor commands.
238
238
  useCommands();
@@ -18,8 +18,9 @@ const POST_TYPES_ALLOWING_POST_CONTENT_TEMPLATE_PART = [
18
18
  * the template part and post content blocks need to be hidden.
19
19
  *
20
20
  * @param {string} postType Post Type
21
+ * @param {string} mode Rendering mode
21
22
  */
22
- export function useHideBlocksFromInserter( postType ) {
23
+ export function useHideBlocksFromInserter( postType, mode ) {
23
24
  useEffect( () => {
24
25
  /*
25
26
  * Prevent adding template part in the editor.
@@ -32,7 +33,8 @@ export function useHideBlocksFromInserter( postType ) {
32
33
  ! POST_TYPES_ALLOWING_POST_CONTENT_TEMPLATE_PART.includes(
33
34
  postType
34
35
  ) &&
35
- blockType.name === 'core/template-part'
36
+ blockType.name === 'core/template-part' &&
37
+ mode === 'post-only'
36
38
  ) {
37
39
  return false;
38
40
  }
@@ -77,5 +79,5 @@ export function useHideBlocksFromInserter( postType ) {
77
79
  'removePostContentFromInserter'
78
80
  );
79
81
  };
80
- }, [ postType ] );
82
+ }, [ postType, mode ] );
81
83
  }
@@ -4,7 +4,6 @@
4
4
  import EditorCanvas from './components/editor-canvas';
5
5
  import { ExperimentalEditorProvider } from './components/provider';
6
6
  import { lock } from './lock-unlock';
7
- import EnablePluginDocumentSettingPanelOption from './components/preferences-modal/enable-plugin-document-setting-panel';
8
7
  import { EntitiesSavedStatesExtensible } from './components/entities-saved-states';
9
8
  import useBlockEditorSettings from './components/provider/use-block-editor-settings';
10
9
  import DocumentTools from './components/document-tools';
@@ -22,7 +21,6 @@ lock( privateApis, {
22
21
  DocumentTools,
23
22
  EditorCanvas,
24
23
  ExperimentalEditorProvider,
25
- EnablePluginDocumentSettingPanelOption,
26
24
  EntitiesSavedStatesExtensible,
27
25
  InserterSidebar,
28
26
  ListViewSidebar,