@wordpress/editor 13.31.0 → 13.32.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 (157) hide show
  1. package/CHANGELOG.md +2 -0
  2. package/README.md +857 -0
  3. package/build/components/block-settings-menu/plugin-block-settings-menu-item.js +107 -0
  4. package/build/components/block-settings-menu/plugin-block-settings-menu-item.js.map +1 -0
  5. package/build/components/commands/index.js +1 -1
  6. package/build/components/commands/index.js.map +1 -1
  7. package/build/components/deprecated.js +158 -0
  8. package/build/components/deprecated.js.map +1 -1
  9. package/build/components/document-bar/index.js +5 -8
  10. package/build/components/document-bar/index.js.map +1 -1
  11. package/build/components/editor-canvas/edit-template-blocks-notification.js +2 -39
  12. package/build/components/editor-canvas/edit-template-blocks-notification.js.map +1 -1
  13. package/build/components/editor-canvas/index.js +3 -0
  14. package/build/components/editor-canvas/index.js.map +1 -1
  15. package/build/components/entities-saved-states/index.js +11 -85
  16. package/build/components/entities-saved-states/index.js.map +1 -1
  17. package/build/components/index.js +24 -0
  18. package/build/components/index.js.map +1 -1
  19. package/build/components/inserter-sidebar/index.js +5 -1
  20. package/build/components/inserter-sidebar/index.js.map +1 -1
  21. package/build/components/list-view-sidebar/index.js +2 -1
  22. package/build/components/list-view-sidebar/index.js.map +1 -1
  23. package/build/components/pattern-overrides-panel/index.js +30 -0
  24. package/build/components/pattern-overrides-panel/index.js.map +1 -0
  25. package/build/components/plugin-post-publish-panel/index.js +68 -0
  26. package/build/components/plugin-post-publish-panel/index.js.map +1 -0
  27. package/build/components/plugin-pre-publish-panel/index.js +71 -0
  28. package/build/components/plugin-pre-publish-panel/index.js.map +1 -0
  29. package/build/components/post-actions/actions.js +455 -0
  30. package/build/components/post-actions/actions.js.map +1 -0
  31. package/build/components/post-card-panel/index.js +93 -0
  32. package/build/components/post-card-panel/index.js.map +1 -0
  33. package/build/components/post-title/index.native.js +1 -1
  34. package/build/components/post-title/index.native.js.map +1 -1
  35. package/build/components/provider/disable-non-page-content-blocks.js +36 -20
  36. package/build/components/provider/disable-non-page-content-blocks.js.map +1 -1
  37. package/build/components/provider/use-block-editor-settings.js +8 -9
  38. package/build/components/provider/use-block-editor-settings.js.map +1 -1
  39. package/build/components/template-areas/index.js +70 -0
  40. package/build/components/template-areas/index.js.map +1 -0
  41. package/build/hooks/use-select-nearest-editable-block.js +87 -0
  42. package/build/hooks/use-select-nearest-editable-block.js.map +1 -0
  43. package/build/private-apis.js +6 -0
  44. package/build/private-apis.js.map +1 -1
  45. package/build/store/actions.js +46 -6
  46. package/build/store/actions.js.map +1 -1
  47. package/build/store/constants.js +3 -1
  48. package/build/store/constants.js.map +1 -1
  49. package/build/store/private-actions.js +80 -1
  50. package/build/store/private-actions.js.map +1 -1
  51. package/build/store/private-selectors.js +56 -3
  52. package/build/store/private-selectors.js.map +1 -1
  53. package/build/store/reducer.js +14 -1
  54. package/build/store/reducer.js.map +1 -1
  55. package/build/store/selectors.js +21 -11
  56. package/build/store/selectors.js.map +1 -1
  57. package/build/store/utils/get-filtered-template-parts.js +71 -0
  58. package/build/store/utils/get-filtered-template-parts.js.map +1 -0
  59. package/build-module/components/block-settings-menu/plugin-block-settings-menu-item.js +100 -0
  60. package/build-module/components/block-settings-menu/plugin-block-settings-menu-item.js.map +1 -0
  61. package/build-module/components/commands/index.js +1 -1
  62. package/build-module/components/commands/index.js.map +1 -1
  63. package/build-module/components/deprecated.js +159 -0
  64. package/build-module/components/deprecated.js.map +1 -1
  65. package/build-module/components/document-bar/index.js +6 -9
  66. package/build-module/components/document-bar/index.js.map +1 -1
  67. package/build-module/components/editor-canvas/edit-template-blocks-notification.js +4 -41
  68. package/build-module/components/editor-canvas/edit-template-blocks-notification.js.map +1 -1
  69. package/build-module/components/editor-canvas/index.js +3 -0
  70. package/build-module/components/editor-canvas/index.js.map +1 -1
  71. package/build-module/components/entities-saved-states/index.js +11 -85
  72. package/build-module/components/entities-saved-states/index.js.map +1 -1
  73. package/build-module/components/index.js +3 -0
  74. package/build-module/components/index.js.map +1 -1
  75. package/build-module/components/inserter-sidebar/index.js +5 -1
  76. package/build-module/components/inserter-sidebar/index.js.map +1 -1
  77. package/build-module/components/list-view-sidebar/index.js +2 -1
  78. package/build-module/components/list-view-sidebar/index.js.map +1 -1
  79. package/build-module/components/pattern-overrides-panel/index.js +23 -0
  80. package/build-module/components/pattern-overrides-panel/index.js.map +1 -0
  81. package/build-module/components/plugin-post-publish-panel/index.js +61 -0
  82. package/build-module/components/plugin-post-publish-panel/index.js.map +1 -0
  83. package/build-module/components/plugin-pre-publish-panel/index.js +64 -0
  84. package/build-module/components/plugin-pre-publish-panel/index.js.map +1 -0
  85. package/build-module/components/post-actions/actions.js +444 -0
  86. package/build-module/components/post-actions/actions.js.map +1 -0
  87. package/build-module/components/post-card-panel/index.js +85 -0
  88. package/build-module/components/post-card-panel/index.js.map +1 -0
  89. package/build-module/components/post-title/index.native.js +1 -1
  90. package/build-module/components/post-title/index.native.js.map +1 -1
  91. package/build-module/components/provider/disable-non-page-content-blocks.js +36 -20
  92. package/build-module/components/provider/disable-non-page-content-blocks.js.map +1 -1
  93. package/build-module/components/provider/use-block-editor-settings.js +9 -10
  94. package/build-module/components/provider/use-block-editor-settings.js.map +1 -1
  95. package/build-module/components/template-areas/index.js +63 -0
  96. package/build-module/components/template-areas/index.js.map +1 -0
  97. package/build-module/hooks/use-select-nearest-editable-block.js +80 -0
  98. package/build-module/hooks/use-select-nearest-editable-block.js.map +1 -0
  99. package/build-module/private-apis.js +6 -0
  100. package/build-module/private-apis.js.map +1 -1
  101. package/build-module/store/actions.js +37 -3
  102. package/build-module/store/actions.js.map +1 -1
  103. package/build-module/store/constants.js +2 -0
  104. package/build-module/store/constants.js.map +1 -1
  105. package/build-module/store/private-actions.js +78 -0
  106. package/build-module/store/private-actions.js.map +1 -1
  107. package/build-module/store/private-selectors.js +54 -3
  108. package/build-module/store/private-selectors.js.map +1 -1
  109. package/build-module/store/reducer.js +13 -1
  110. package/build-module/store/reducer.js.map +1 -1
  111. package/build-module/store/selectors.js +19 -10
  112. package/build-module/store/selectors.js.map +1 -1
  113. package/build-module/store/utils/get-filtered-template-parts.js +64 -0
  114. package/build-module/store/utils/get-filtered-template-parts.js.map +1 -0
  115. package/build-style/style-rtl.css +70 -27
  116. package/build-style/style.css +70 -27
  117. package/package.json +35 -35
  118. package/src/components/block-settings-menu/plugin-block-settings-menu-item.js +108 -0
  119. package/src/components/commands/index.js +1 -1
  120. package/src/components/deprecated.js +157 -0
  121. package/src/components/document-bar/index.js +9 -15
  122. package/src/components/document-bar/style.scss +9 -12
  123. package/src/components/document-tools/style.scss +4 -11
  124. package/src/components/editor-canvas/edit-template-blocks-notification.js +6 -56
  125. package/src/components/editor-canvas/index.js +4 -0
  126. package/src/components/entities-saved-states/index.js +12 -113
  127. package/src/components/index.js +3 -0
  128. package/src/components/inserter-sidebar/index.js +7 -1
  129. package/src/components/list-view-sidebar/index.js +1 -0
  130. package/src/components/list-view-sidebar/style.scss +1 -1
  131. package/src/components/pattern-overrides-panel/index.js +26 -0
  132. package/src/components/plugin-post-publish-panel/index.js +64 -0
  133. package/src/components/plugin-post-publish-panel/test/__snapshots__/index.js.snap +39 -0
  134. package/src/components/plugin-post-publish-panel/test/index.js +33 -0
  135. package/src/components/plugin-pre-publish-panel/index.js +67 -0
  136. package/src/components/plugin-pre-publish-panel/test/index.js +33 -0
  137. package/src/components/post-actions/actions.js +582 -0
  138. package/src/components/post-card-panel/index.js +108 -0
  139. package/src/components/post-card-panel/style.scss +32 -0
  140. package/src/components/post-featured-image/style.scss +3 -2
  141. package/src/components/post-title/index.native.js +1 -1
  142. package/src/components/provider/disable-non-page-content-blocks.js +40 -20
  143. package/src/components/provider/test/disable-non-page-content-blocks.js +35 -14
  144. package/src/components/provider/use-block-editor-settings.js +11 -11
  145. package/src/components/template-areas/index.js +85 -0
  146. package/src/components/template-areas/style.scss +23 -0
  147. package/src/hooks/use-select-nearest-editable-block.js +95 -0
  148. package/src/private-apis.js +6 -0
  149. package/src/store/actions.js +37 -3
  150. package/src/store/constants.js +2 -0
  151. package/src/store/private-actions.js +111 -0
  152. package/src/store/private-selectors.js +105 -17
  153. package/src/store/reducer.js +13 -0
  154. package/src/store/selectors.js +50 -40
  155. package/src/store/utils/get-filtered-template-parts.js +69 -0
  156. package/src/store/utils/test/get-filtered-template-parts.js +189 -0
  157. package/src/style.scss +2 -0
@@ -3,32 +3,24 @@
3
3
  */
4
4
  import { Button, Flex, FlexItem } from '@wordpress/components';
5
5
  import { __, _n, sprintf } from '@wordpress/i18n';
6
- import { useSelect, useDispatch } from '@wordpress/data';
7
6
  import {
8
7
  useCallback,
9
8
  useRef,
10
9
  createInterpolateElement,
11
10
  } from '@wordpress/element';
12
- import { store as coreStore } from '@wordpress/core-data';
13
- import { store as blockEditorStore } from '@wordpress/block-editor';
14
11
  import {
15
12
  __experimentalUseDialog as useDialog,
16
13
  useInstanceId,
17
14
  } from '@wordpress/compose';
18
- import { store as noticesStore } from '@wordpress/notices';
15
+ import { useDispatch } from '@wordpress/data';
19
16
 
20
17
  /**
21
18
  * Internal dependencies
22
19
  */
23
20
  import EntityTypeList from './entity-type-list';
24
21
  import { useIsDirty } from './hooks/use-is-dirty';
25
-
26
- const PUBLISH_ON_SAVE_ENTITIES = [
27
- {
28
- kind: 'postType',
29
- name: 'wp_navigation',
30
- },
31
- ];
22
+ import { store as editorStore } from '../../store';
23
+ import { unlock } from '../../lock-unlock';
32
24
 
33
25
  function identity( values ) {
34
26
  return values;
@@ -55,25 +47,13 @@ export function EntitiesSavedStatesExtensible( {
55
47
  saveEnabled: saveEnabledProp = undefined,
56
48
  saveLabel = __( 'Save' ),
57
49
  renderDialog = undefined,
58
-
59
50
  dirtyEntityRecords,
60
51
  isDirty,
61
52
  setUnselectedEntities,
62
53
  unselectedEntities,
63
54
  } ) {
64
55
  const saveButtonRef = useRef();
65
- const {
66
- editEntityRecord,
67
- saveEditedEntityRecord,
68
- __experimentalSaveSpecifiedEntityEdits: saveSpecifiedEntityEdits,
69
- } = useDispatch( coreStore );
70
-
71
- const { __unstableMarkLastChangeAsPersistent } =
72
- useDispatch( blockEditorStore );
73
-
74
- const { createSuccessNotice, createErrorNotice, removeNotice } =
75
- useDispatch( noticesStore );
76
-
56
+ const { saveDirtyEntities } = unlock( useDispatch( editorStore ) );
77
57
  // To group entities by type.
78
58
  const partitionedSavables = dirtyEntityRecords.reduce( ( acc, record ) => {
79
59
  const { name } = record;
@@ -99,94 +79,6 @@ export function EntitiesSavedStatesExtensible( {
99
79
  ].filter( Array.isArray );
100
80
 
101
81
  const saveEnabled = saveEnabledProp ?? isDirty;
102
-
103
- const { homeUrl } = useSelect( ( select ) => {
104
- const {
105
- getUnstableBase, // Site index.
106
- } = select( coreStore );
107
- return {
108
- homeUrl: getUnstableBase()?.home,
109
- };
110
- }, [] );
111
-
112
- const saveCheckedEntities = () => {
113
- const saveNoticeId = 'site-editor-save-success';
114
- removeNotice( saveNoticeId );
115
- const entitiesToSave = dirtyEntityRecords.filter(
116
- ( { kind, name, key, property } ) => {
117
- return ! unselectedEntities.some(
118
- ( elt ) =>
119
- elt.kind === kind &&
120
- elt.name === name &&
121
- elt.key === key &&
122
- elt.property === property
123
- );
124
- }
125
- );
126
-
127
- close( entitiesToSave );
128
-
129
- const siteItemsToSave = [];
130
- const pendingSavedRecords = [];
131
- entitiesToSave.forEach( ( { kind, name, key, property } ) => {
132
- if ( 'root' === kind && 'site' === name ) {
133
- siteItemsToSave.push( property );
134
- } else {
135
- if (
136
- PUBLISH_ON_SAVE_ENTITIES.some(
137
- ( typeToPublish ) =>
138
- typeToPublish.kind === kind &&
139
- typeToPublish.name === name
140
- )
141
- ) {
142
- editEntityRecord( kind, name, key, { status: 'publish' } );
143
- }
144
-
145
- pendingSavedRecords.push(
146
- saveEditedEntityRecord( kind, name, key )
147
- );
148
- }
149
- } );
150
- if ( siteItemsToSave.length ) {
151
- pendingSavedRecords.push(
152
- saveSpecifiedEntityEdits(
153
- 'root',
154
- 'site',
155
- undefined,
156
- siteItemsToSave
157
- )
158
- );
159
- }
160
-
161
- __unstableMarkLastChangeAsPersistent();
162
-
163
- Promise.all( pendingSavedRecords )
164
- .then( ( values ) => {
165
- return onSave( values );
166
- } )
167
- .then( ( values ) => {
168
- if (
169
- values.some( ( value ) => typeof value === 'undefined' )
170
- ) {
171
- createErrorNotice( __( 'Saving failed.' ) );
172
- } else {
173
- createSuccessNotice( __( 'Site updated.' ), {
174
- type: 'snackbar',
175
- id: saveNoticeId,
176
- actions: [
177
- {
178
- label: __( 'View site' ),
179
- url: homeUrl,
180
- },
181
- ],
182
- } );
183
- }
184
- } )
185
- .catch( ( error ) =>
186
- createErrorNotice( `${ __( 'Saving failed.' ) } ${ error }` )
187
- );
188
- };
189
-
190
82
  // Explicitly define this with no argument passed. Using `close` on
191
83
  // its own will use the event object in place of the expected saved entities.
192
84
  const dismissPanel = useCallback( () => close(), [ close ] );
@@ -217,7 +109,14 @@ export function EntitiesSavedStatesExtensible( {
217
109
  variant="primary"
218
110
  disabled={ ! saveEnabled }
219
111
  __experimentalIsFocusable
220
- onClick={ saveCheckedEntities }
112
+ onClick={ () =>
113
+ saveDirtyEntities( {
114
+ onSave,
115
+ dirtyEntityRecords,
116
+ entitiesToSkip: unselectedEntities,
117
+ close,
118
+ } )
119
+ }
221
120
  className="editor-entities-saved-states__save-button"
222
121
  >
223
122
  { saveLabel }
@@ -27,6 +27,9 @@ 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
29
  export { default as PluginDocumentSettingPanel } from './plugin-document-setting-panel';
30
+ export { default as PluginBlockSettingsMenuItem } from './block-settings-menu/plugin-block-settings-menu-item';
31
+ export { default as PluginPostPublishPanel } from './plugin-post-publish-panel';
32
+ export { default as PluginPrePublishPanel } from './plugin-pre-publish-panel';
30
33
  export { default as PostTemplatePanel } from './post-template/panel';
31
34
  export { default as PostAuthor } from './post-author';
32
35
  export { default as PostAuthorCheck } from './post-author/check';
@@ -19,7 +19,10 @@ import { store as preferencesStore } from '@wordpress/preferences';
19
19
  import { unlock } from '../../lock-unlock';
20
20
  import { store as editorStore } from '../../store';
21
21
 
22
- export default function InserterSidebar() {
22
+ export default function InserterSidebar( {
23
+ closeGeneralSidebar,
24
+ isRightSidebarOpen,
25
+ } ) {
23
26
  const { insertionPoint, showMostUsedBlocks } = useSelect( ( select ) => {
24
27
  const { getInsertionPoint } = unlock( select( editorStore ) );
25
28
  const { get } = select( preferencesStore );
@@ -65,6 +68,9 @@ export default function InserterSidebar() {
65
68
  insertionPoint.insertionIndex
66
69
  }
67
70
  __experimentalFilterValue={ insertionPoint.filterValue }
71
+ __experimentalOnPatternCategorySelection={
72
+ isRightSidebarOpen ? closeGeneralSidebar : undefined
73
+ }
68
74
  ref={ libraryRef }
69
75
  />
70
76
  </div>
@@ -135,6 +135,7 @@ export default function ListViewSidebar() {
135
135
  icon={ closeSmall }
136
136
  label={ __( 'Close' ) }
137
137
  onClick={ closeListView }
138
+ size="small"
138
139
  />
139
140
  <Tabs.TabList
140
141
  className="editor-list-view-sidebar__tabs-tablist"
@@ -16,7 +16,7 @@
16
16
  background: $white;
17
17
  order: 1;
18
18
  align-self: center;
19
- margin-right: $grid-unit-10;
19
+ margin-right: $grid-unit-15;
20
20
  }
21
21
  }
22
22
 
@@ -0,0 +1,26 @@
1
+ /**
2
+ * WordPress dependencies
3
+ */
4
+ import { useSelect } from '@wordpress/data';
5
+ import { privateApis as patternsPrivateApis } from '@wordpress/patterns';
6
+
7
+ /**
8
+ * Internal dependencies
9
+ */
10
+ import { store as editorStore } from '../../store';
11
+ import { unlock } from '../../lock-unlock';
12
+
13
+ const { OverridesPanel } = unlock( patternsPrivateApis );
14
+
15
+ export default function PatternOverridesPanel() {
16
+ const supportsPatternOverridesPanel = useSelect(
17
+ ( select ) => select( editorStore ).getCurrentPostType() === 'wp_block',
18
+ []
19
+ );
20
+
21
+ if ( ! supportsPatternOverridesPanel ) {
22
+ return null;
23
+ }
24
+
25
+ return <OverridesPanel />;
26
+ }
@@ -0,0 +1,64 @@
1
+ /**
2
+ * WordPress dependencies
3
+ */
4
+ import { usePluginContext } from '@wordpress/plugins';
5
+ import { createSlotFill, PanelBody } from '@wordpress/components';
6
+
7
+ const { Fill, Slot } = createSlotFill( 'PluginPostPublishPanel' );
8
+
9
+ /**
10
+ * Renders provided content to the post-publish panel in the publish flow
11
+ * (side panel that opens after a user publishes the post).
12
+ *
13
+ * @param {Object} props Component properties.
14
+ * @param {string} [props.className] An optional class name added to the panel.
15
+ * @param {string} [props.title] Title displayed at the top of the panel.
16
+ * @param {boolean} [props.initialOpen=false] Whether to have the panel initially opened. When no title is provided it is always opened.
17
+ * @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.
18
+ * @param {Element} props.children Children to be rendered
19
+ *
20
+ * @example
21
+ * ```jsx
22
+ * // Using ESNext syntax
23
+ * import { __ } from '@wordpress/i18n';
24
+ * import { PluginPostPublishPanel } from '@wordpress/edit-post';
25
+ *
26
+ * const MyPluginPostPublishPanel = () => (
27
+ * <PluginPostPublishPanel
28
+ * className="my-plugin-post-publish-panel"
29
+ * title={ __( 'My panel title' ) }
30
+ * initialOpen={ true }
31
+ * >
32
+ * { __( 'My panel content' ) }
33
+ * </PluginPostPublishPanel>
34
+ * );
35
+ * ```
36
+ *
37
+ * @return {Component} The component to be rendered.
38
+ */
39
+ const PluginPostPublishPanel = ( {
40
+ children,
41
+ className,
42
+ title,
43
+ initialOpen = false,
44
+ icon,
45
+ } ) => {
46
+ const { icon: pluginIcon } = usePluginContext();
47
+
48
+ return (
49
+ <Fill>
50
+ <PanelBody
51
+ className={ className }
52
+ initialOpen={ initialOpen || ! title }
53
+ title={ title }
54
+ icon={ icon ?? pluginIcon }
55
+ >
56
+ { children }
57
+ </PanelBody>
58
+ </Fill>
59
+ );
60
+ };
61
+
62
+ PluginPostPublishPanel.Slot = Slot;
63
+
64
+ export default PluginPostPublishPanel;
@@ -0,0 +1,39 @@
1
+ // Jest Snapshot v1, https://goo.gl/fbAQLP
2
+
3
+ exports[`PluginPostPublishPanel renders fill properly 1`] = `
4
+ <div>
5
+ <div
6
+ class="components-panel__body my-plugin-post-publish-panel is-opened"
7
+ >
8
+ <h2
9
+ class="components-panel__body-title"
10
+ >
11
+ <button
12
+ aria-expanded="true"
13
+ class="components-button components-panel__body-toggle"
14
+ type="button"
15
+ >
16
+ <span
17
+ aria-hidden="true"
18
+ >
19
+ <svg
20
+ aria-hidden="true"
21
+ class="components-panel__arrow"
22
+ focusable="false"
23
+ height="24"
24
+ viewBox="0 0 24 24"
25
+ width="24"
26
+ xmlns="http://www.w3.org/2000/svg"
27
+ >
28
+ <path
29
+ d="M6.5 12.4L12 8l5.5 4.4-.9 1.2L12 10l-4.5 3.6-1-1.2z"
30
+ />
31
+ </svg>
32
+ </span>
33
+ My panel title
34
+ </button>
35
+ </h2>
36
+ My panel content
37
+ </div>
38
+ </div>
39
+ `;
@@ -0,0 +1,33 @@
1
+ /**
2
+ * External dependencies
3
+ */
4
+ import { render } from '@testing-library/react';
5
+
6
+ /**
7
+ * WordPress dependencies
8
+ */
9
+ import { SlotFillProvider } from '@wordpress/components';
10
+
11
+ /**
12
+ * Internal dependencies
13
+ */
14
+ import PluginPostPublishPanel from '../';
15
+
16
+ describe( 'PluginPostPublishPanel', () => {
17
+ test( 'renders fill properly', () => {
18
+ const { container } = render(
19
+ <SlotFillProvider>
20
+ <PluginPostPublishPanel
21
+ className="my-plugin-post-publish-panel"
22
+ title="My panel title"
23
+ initialOpen
24
+ >
25
+ My panel content
26
+ </PluginPostPublishPanel>
27
+ <PluginPostPublishPanel.Slot />
28
+ </SlotFillProvider>
29
+ );
30
+
31
+ expect( container ).toMatchSnapshot();
32
+ } );
33
+ } );
@@ -0,0 +1,67 @@
1
+ /**
2
+ * WordPress dependencies
3
+ */
4
+ import { createSlotFill, PanelBody } from '@wordpress/components';
5
+ import { usePluginContext } from '@wordpress/plugins';
6
+
7
+ const { Fill, Slot } = createSlotFill( 'PluginPrePublishPanel' );
8
+
9
+ /**
10
+ * Renders provided content to the pre-publish side panel in the publish flow
11
+ * (side panel that opens when a user first pushes "Publish" from the main editor).
12
+ *
13
+ * @param {Object} props Component props.
14
+ * @param {string} [props.className] An optional class name added to the panel.
15
+ * @param {string} [props.title] Title displayed at the top of the panel.
16
+ * @param {boolean} [props.initialOpen=false] Whether to have the panel initially opened.
17
+ * When no title is provided it is always opened.
18
+ * @param {WPBlockTypeIconRender} [props.icon=inherits from the plugin] The [Dashicon](https://developer.wordpress.org/resource/dashicons/)
19
+ * icon slug string, or an SVG WP element, to be rendered when
20
+ * the sidebar is pinned to toolbar.
21
+ * @param {Element} props.children Children to be rendered
22
+ *
23
+ * @example
24
+ * ```jsx
25
+ * // Using ESNext syntax
26
+ * import { __ } from '@wordpress/i18n';
27
+ * import { PluginPrePublishPanel } from '@wordpress/edit-post';
28
+ *
29
+ * const MyPluginPrePublishPanel = () => (
30
+ * <PluginPrePublishPanel
31
+ * className="my-plugin-pre-publish-panel"
32
+ * title={ __( 'My panel title' ) }
33
+ * initialOpen={ true }
34
+ * >
35
+ * { __( 'My panel content' ) }
36
+ * </PluginPrePublishPanel>
37
+ * );
38
+ * ```
39
+ *
40
+ * @return {Component} The component to be rendered.
41
+ */
42
+ const PluginPrePublishPanel = ( {
43
+ children,
44
+ className,
45
+ title,
46
+ initialOpen = false,
47
+ icon,
48
+ } ) => {
49
+ const { icon: pluginIcon } = usePluginContext();
50
+
51
+ return (
52
+ <Fill>
53
+ <PanelBody
54
+ className={ className }
55
+ initialOpen={ initialOpen || ! title }
56
+ title={ title }
57
+ icon={ icon ?? pluginIcon }
58
+ >
59
+ { children }
60
+ </PanelBody>
61
+ </Fill>
62
+ );
63
+ };
64
+
65
+ PluginPrePublishPanel.Slot = Slot;
66
+
67
+ export default PluginPrePublishPanel;
@@ -0,0 +1,33 @@
1
+ /**
2
+ * External dependencies
3
+ */
4
+ import { render, screen } from '@testing-library/react';
5
+
6
+ /**
7
+ * WordPress dependencies
8
+ */
9
+ import { SlotFillProvider } from '@wordpress/components';
10
+
11
+ /**
12
+ * Internal dependencies
13
+ */
14
+ import PluginPrePublishPanel from '../';
15
+
16
+ describe( 'PluginPrePublishPanel', () => {
17
+ test( 'renders fill properly', () => {
18
+ render(
19
+ <SlotFillProvider>
20
+ <PluginPrePublishPanel
21
+ className="my-plugin-pre-publish-panel"
22
+ title="My panel title"
23
+ initialOpen
24
+ >
25
+ My panel content
26
+ </PluginPrePublishPanel>
27
+ <PluginPrePublishPanel.Slot />
28
+ </SlotFillProvider>
29
+ );
30
+
31
+ expect( screen.getByText( 'My panel title' ) ).toBeVisible();
32
+ } );
33
+ } );