@wordpress/editor 13.24.0 → 13.25.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 (175) hide show
  1. package/CHANGELOG.md +2 -0
  2. package/build/components/document-bar/index.js +152 -0
  3. package/build/components/document-bar/index.js.map +1 -0
  4. package/build/components/editor-canvas/edit-template-blocks-notification.js +106 -0
  5. package/build/components/editor-canvas/edit-template-blocks-notification.js.map +1 -0
  6. package/build/components/editor-canvas/index.js +292 -0
  7. package/build/components/editor-canvas/index.js.map +1 -0
  8. package/build/components/index.js +24 -8
  9. package/build/components/index.js.map +1 -1
  10. package/build/components/post-publish-button/index.js +1 -0
  11. package/build/components/post-publish-button/index.js.map +1 -1
  12. package/build/components/post-publish-panel/maybe-upload-media.js +2 -4
  13. package/build/components/post-publish-panel/maybe-upload-media.js.map +1 -1
  14. package/build/components/post-saved-state/index.js +1 -0
  15. package/build/components/post-saved-state/index.js.map +1 -1
  16. package/build/components/post-schedule/panel.js +1 -1
  17. package/build/components/post-schedule/panel.js.map +1 -1
  18. package/build/components/post-template/block-theme.js +99 -0
  19. package/build/components/post-template/block-theme.js.map +1 -0
  20. package/build/components/post-template/classic-theme.js +171 -0
  21. package/build/components/post-template/classic-theme.js.map +1 -0
  22. package/build/components/post-template/create-new-template-modal.js +98 -0
  23. package/build/components/post-template/create-new-template-modal.js.map +1 -0
  24. package/build/components/post-template/create-new-template.js +55 -0
  25. package/build/components/post-template/create-new-template.js.map +1 -0
  26. package/build/components/post-template/hooks.js +88 -0
  27. package/build/components/post-template/hooks.js.map +1 -0
  28. package/build/components/post-template/panel.js +71 -0
  29. package/build/components/post-template/panel.js.map +1 -0
  30. package/build/components/post-template/reset-default-template.js +48 -0
  31. package/build/components/post-template/reset-default-template.js.map +1 -0
  32. package/build/components/post-template/swap-template-button.js +84 -0
  33. package/build/components/post-template/swap-template-button.js.map +1 -0
  34. package/build/components/post-title/index.native.js +0 -1
  35. package/build/components/post-title/index.native.js.map +1 -1
  36. package/build/components/preview-dropdown/index.js +113 -0
  37. package/build/components/preview-dropdown/index.js.map +1 -0
  38. package/build/components/provider/index.js +36 -77
  39. package/build/components/provider/index.js.map +1 -1
  40. package/build/components/provider/index.native.js +17 -8
  41. package/build/components/provider/index.native.js.map +1 -1
  42. package/build/components/provider/navigation-block-editing-mode.js +40 -0
  43. package/build/components/provider/navigation-block-editing-mode.js.map +1 -0
  44. package/build/components/provider/use-block-editor-settings.js +9 -10
  45. package/build/components/provider/use-block-editor-settings.js.map +1 -1
  46. package/build/hooks/index.js +1 -0
  47. package/build/hooks/index.js.map +1 -1
  48. package/build/hooks/pattern-partial-syncing.js +49 -0
  49. package/build/hooks/pattern-partial-syncing.js.map +1 -0
  50. package/build/private-apis.js +4 -0
  51. package/build/private-apis.js.map +1 -1
  52. package/build/store/actions.js +59 -11
  53. package/build/store/actions.js.map +1 -1
  54. package/build/store/defaults.js +2 -1
  55. package/build/store/defaults.js.map +1 -1
  56. package/build/store/index.js +3 -0
  57. package/build/store/index.js.map +1 -1
  58. package/build/store/private-actions.js +52 -0
  59. package/build/store/private-actions.js.map +1 -0
  60. package/build/store/reducer.js +32 -27
  61. package/build/store/reducer.js.map +1 -1
  62. package/build/store/reducer.native.js +0 -1
  63. package/build/store/reducer.native.js.map +1 -1
  64. package/build/store/selectors.js +31 -10
  65. package/build/store/selectors.js.map +1 -1
  66. package/build-module/components/document-bar/index.js +144 -0
  67. package/build-module/components/document-bar/index.js.map +1 -0
  68. package/build-module/components/editor-canvas/edit-template-blocks-notification.js +100 -0
  69. package/build-module/components/editor-canvas/edit-template-blocks-notification.js.map +1 -0
  70. package/build-module/components/editor-canvas/index.js +283 -0
  71. package/build-module/components/editor-canvas/index.js.map +1 -0
  72. package/build-module/components/index.js +3 -1
  73. package/build-module/components/index.js.map +1 -1
  74. package/build-module/components/post-publish-button/index.js +1 -0
  75. package/build-module/components/post-publish-button/index.js.map +1 -1
  76. package/build-module/components/post-publish-panel/maybe-upload-media.js +2 -4
  77. package/build-module/components/post-publish-panel/maybe-upload-media.js.map +1 -1
  78. package/build-module/components/post-saved-state/index.js +1 -0
  79. package/build-module/components/post-saved-state/index.js.map +1 -1
  80. package/build-module/components/post-schedule/panel.js +1 -1
  81. package/build-module/components/post-schedule/panel.js.map +1 -1
  82. package/build-module/components/post-template/block-theme.js +91 -0
  83. package/build-module/components/post-template/block-theme.js.map +1 -0
  84. package/build-module/components/post-template/classic-theme.js +162 -0
  85. package/build-module/components/post-template/classic-theme.js.map +1 -0
  86. package/build-module/components/post-template/create-new-template-modal.js +91 -0
  87. package/build-module/components/post-template/create-new-template-modal.js.map +1 -0
  88. package/build-module/components/post-template/create-new-template.js +47 -0
  89. package/build-module/components/post-template/create-new-template.js.map +1 -0
  90. package/build-module/components/post-template/hooks.js +78 -0
  91. package/build-module/components/post-template/hooks.js.map +1 -0
  92. package/build-module/components/post-template/panel.js +63 -0
  93. package/build-module/components/post-template/panel.js.map +1 -0
  94. package/build-module/components/post-template/reset-default-template.js +41 -0
  95. package/build-module/components/post-template/reset-default-template.js.map +1 -0
  96. package/build-module/components/post-template/swap-template-button.js +77 -0
  97. package/build-module/components/post-template/swap-template-button.js.map +1 -0
  98. package/build-module/components/post-title/index.native.js +0 -1
  99. package/build-module/components/post-title/index.native.js.map +1 -1
  100. package/build-module/components/preview-dropdown/index.js +105 -0
  101. package/build-module/components/preview-dropdown/index.js.map +1 -0
  102. package/build-module/components/provider/index.js +37 -78
  103. package/build-module/components/provider/index.js.map +1 -1
  104. package/build-module/components/provider/index.native.js +18 -9
  105. package/build-module/components/provider/index.native.js.map +1 -1
  106. package/build-module/components/provider/navigation-block-editing-mode.js +34 -0
  107. package/build-module/components/provider/navigation-block-editing-mode.js.map +1 -0
  108. package/build-module/components/provider/use-block-editor-settings.js +9 -10
  109. package/build-module/components/provider/use-block-editor-settings.js.map +1 -1
  110. package/build-module/hooks/index.js +1 -0
  111. package/build-module/hooks/index.js.map +1 -1
  112. package/build-module/hooks/pattern-partial-syncing.js +46 -0
  113. package/build-module/hooks/pattern-partial-syncing.js.map +1 -0
  114. package/build-module/private-apis.js +4 -0
  115. package/build-module/private-apis.js.map +1 -1
  116. package/build-module/store/actions.js +53 -9
  117. package/build-module/store/actions.js.map +1 -1
  118. package/build-module/store/defaults.js +2 -1
  119. package/build-module/store/defaults.js.map +1 -1
  120. package/build-module/store/index.js +3 -0
  121. package/build-module/store/index.js.map +1 -1
  122. package/build-module/store/private-actions.js +44 -0
  123. package/build-module/store/private-actions.js.map +1 -0
  124. package/build-module/store/reducer.js +30 -26
  125. package/build-module/store/reducer.js.map +1 -1
  126. package/build-module/store/reducer.native.js +1 -2
  127. package/build-module/store/reducer.native.js.map +1 -1
  128. package/build-module/store/selectors.js +26 -6
  129. package/build-module/store/selectors.js.map +1 -1
  130. package/build-style/style-rtl.css +182 -0
  131. package/build-style/style.css +182 -0
  132. package/package.json +32 -31
  133. package/src/components/document-bar/index.js +182 -0
  134. package/src/components/document-bar/style.scss +130 -0
  135. package/src/components/editor-canvas/edit-template-blocks-notification.js +108 -0
  136. package/src/components/editor-canvas/index.js +381 -0
  137. package/src/components/index.js +3 -1
  138. package/src/components/post-publish-button/index.js +1 -0
  139. package/src/components/post-publish-panel/maybe-upload-media.js +3 -8
  140. package/src/components/post-saved-state/index.js +1 -0
  141. package/src/components/post-saved-state/test/__snapshots__/index.js.snap +2 -2
  142. package/src/components/post-schedule/panel.js +1 -1
  143. package/src/components/post-template/block-theme.js +109 -0
  144. package/src/components/post-template/classic-theme.js +213 -0
  145. package/src/components/post-template/create-new-template-modal.js +139 -0
  146. package/src/components/post-template/create-new-template.js +50 -0
  147. package/src/components/post-template/hooks.js +95 -0
  148. package/src/components/post-template/panel.js +67 -0
  149. package/src/components/post-template/reset-default-template.js +43 -0
  150. package/src/components/post-template/style.scss +52 -0
  151. package/src/components/post-template/swap-template-button.js +83 -0
  152. package/src/components/post-title/index.native.js +0 -1
  153. package/src/components/preview-dropdown/index.js +136 -0
  154. package/src/components/preview-dropdown/style.scss +5 -0
  155. package/src/components/provider/index.js +39 -112
  156. package/src/components/provider/index.native.js +26 -12
  157. package/src/components/provider/navigation-block-editing-mode.js +37 -0
  158. package/src/components/provider/use-block-editor-settings.js +6 -9
  159. package/src/hooks/index.js +1 -0
  160. package/src/hooks/pattern-partial-syncing.js +73 -0
  161. package/src/private-apis.js +4 -0
  162. package/src/store/actions.js +51 -9
  163. package/src/store/defaults.js +1 -0
  164. package/src/store/index.js +3 -0
  165. package/src/store/private-actions.js +61 -0
  166. package/src/store/reducer.js +32 -27
  167. package/src/store/reducer.native.js +0 -2
  168. package/src/store/selectors.js +64 -42
  169. package/src/store/test/selectors.js +88 -147
  170. package/src/style.scss +3 -0
  171. package/build/components/post-template/index.js +0 -66
  172. package/build/components/post-template/index.js.map +0 -1
  173. package/build-module/components/post-template/index.js +0 -57
  174. package/build-module/components/post-template/index.js.map +0 -1
  175. package/src/components/post-template/index.js +0 -64
@@ -142,6 +142,137 @@
142
142
  color: var(--wp-admin-theme-color);
143
143
  }
144
144
 
145
+ .editor-document-bar {
146
+ display: flex;
147
+ align-items: center;
148
+ height: 32px;
149
+ justify-content: space-between;
150
+ min-width: 0;
151
+ background: #f0f0f0;
152
+ border-radius: 4px;
153
+ width: min(100%, 450px);
154
+ }
155
+ .editor-document-bar:hover {
156
+ background-color: #e0e0e0;
157
+ }
158
+ .editor-document-bar .components-button {
159
+ border-radius: 4px;
160
+ }
161
+ .editor-document-bar .components-button:hover {
162
+ color: var(--wp-block-synced-color);
163
+ background: #e0e0e0;
164
+ }
165
+ @media (min-width: 960px) {
166
+ .editor-document-bar {
167
+ width: min(100%, 450px);
168
+ }
169
+ }
170
+
171
+ .editor-document-bar__command {
172
+ flex-grow: 1;
173
+ color: var(--wp-block-synced-color);
174
+ overflow: hidden;
175
+ }
176
+
177
+ .editor-document-bar__title {
178
+ flex-grow: 1;
179
+ overflow: hidden;
180
+ color: #2f2f2f;
181
+ }
182
+ @media (min-width: 600px) {
183
+ .editor-document-bar__title {
184
+ padding-left: 32px;
185
+ }
186
+ }
187
+ .editor-document-bar__title:hover {
188
+ color: var(--wp-block-synced-color);
189
+ }
190
+ .editor-document-bar.is-global .editor-document-bar__title {
191
+ color: var(--wp-block-synced-color);
192
+ }
193
+ .editor-document-bar__title .block-editor-block-icon {
194
+ min-width: 24px;
195
+ flex-shrink: 0;
196
+ }
197
+ .editor-document-bar__title h1 {
198
+ white-space: nowrap;
199
+ overflow: hidden;
200
+ text-overflow: ellipsis;
201
+ max-width: 50%;
202
+ color: currentColor;
203
+ }
204
+ .editor-document-bar.is-animated.has-back-button .editor-document-bar__title {
205
+ animation: editor-document-bar__slide-in-left 0.3s;
206
+ }
207
+ @media (prefers-reduced-motion: reduce) {
208
+ .editor-document-bar.is-animated.has-back-button .editor-document-bar__title {
209
+ animation-duration: 1ms;
210
+ animation-delay: 0s;
211
+ }
212
+ }
213
+ .editor-document-bar.is-animated .editor-document-bar__title {
214
+ animation: editor-document-bar__slide-in-right 0.3s;
215
+ }
216
+ @media (prefers-reduced-motion: reduce) {
217
+ .editor-document-bar.is-animated .editor-document-bar__title {
218
+ animation-duration: 1ms;
219
+ animation-delay: 0s;
220
+ }
221
+ }
222
+
223
+ .editor-document-bar__shortcut {
224
+ color: #2f2f2f;
225
+ min-width: 32px;
226
+ display: none;
227
+ }
228
+ @media (min-width: 782px) {
229
+ .editor-document-bar__shortcut {
230
+ display: initial;
231
+ }
232
+ }
233
+
234
+ .editor-document-bar__back.components-button.has-icon.has-text {
235
+ min-width: 36px;
236
+ flex-shrink: 0;
237
+ color: #757575;
238
+ gap: 0;
239
+ z-index: 1;
240
+ position: absolute;
241
+ }
242
+ .editor-document-bar__back.components-button.has-icon.has-text:hover {
243
+ color: var(--wp-block-synced-color);
244
+ background-color: transparent;
245
+ }
246
+ .editor-document-bar.is-animated .editor-document-bar__back.components-button.has-icon.has-text {
247
+ animation: editor-document-bar__slide-in-left 0.3s;
248
+ }
249
+ @media (prefers-reduced-motion: reduce) {
250
+ .editor-document-bar.is-animated .editor-document-bar__back.components-button.has-icon.has-text {
251
+ animation-duration: 1ms;
252
+ animation-delay: 0s;
253
+ }
254
+ }
255
+
256
+ @keyframes editor-document-bar__slide-in-right {
257
+ from {
258
+ transform: translateX(-15%);
259
+ opacity: 0;
260
+ }
261
+ to {
262
+ transform: translateX(0);
263
+ opacity: 1;
264
+ }
265
+ }
266
+ @keyframes editor-document-bar__slide-in-left {
267
+ from {
268
+ transform: translateX(15%);
269
+ opacity: 0;
270
+ }
271
+ to {
272
+ transform: translateX(0);
273
+ opacity: 1;
274
+ }
275
+ }
145
276
  .document-outline {
146
277
  margin: 20px 0;
147
278
  }
@@ -689,6 +820,51 @@
689
820
  font-size: 12px;
690
821
  }
691
822
 
823
+ .editor-post-template__swap-template-modal {
824
+ z-index: 1000001;
825
+ }
826
+
827
+ .editor-post-template__swap-template-modal-content .block-editor-block-patterns-list {
828
+ column-count: 2;
829
+ column-gap: 24px;
830
+ padding-top: 2px;
831
+ }
832
+ @media (min-width: 782px) {
833
+ .editor-post-template__swap-template-modal-content .block-editor-block-patterns-list {
834
+ column-count: 3;
835
+ }
836
+ }
837
+ @media (min-width: 1280px) {
838
+ .editor-post-template__swap-template-modal-content .block-editor-block-patterns-list {
839
+ column-count: 4;
840
+ }
841
+ }
842
+ .editor-post-template__swap-template-modal-content .block-editor-block-patterns-list .block-editor-block-patterns-list__list-item {
843
+ break-inside: avoid-column;
844
+ }
845
+ .editor-post-template__swap-template-modal-content .block-editor-block-patterns-list .block-editor-block-patterns-list__item:not(:focus):not(:hover) .block-editor-block-preview__container {
846
+ box-shadow: 0 0 0 1px #ddd;
847
+ }
848
+
849
+ .editor-post-template__dropdown .components-popover__content {
850
+ min-width: 240px;
851
+ }
852
+ .editor-post-template__dropdown .components-button.is-pressed,
853
+ .editor-post-template__dropdown .components-button.is-pressed:hover {
854
+ background: inherit;
855
+ color: inherit;
856
+ }
857
+
858
+ @media (min-width: 782px) {
859
+ .editor-post-template__create-form {
860
+ width: 320px;
861
+ }
862
+ }
863
+
864
+ .editor-post-template__classic-theme-dropdown {
865
+ padding: 8px;
866
+ }
867
+
692
868
  .edit-post-text-editor__body textarea.editor-post-text-editor {
693
869
  border: 1px solid #949494;
694
870
  border-radius: 0;
@@ -914,6 +1090,12 @@
914
1090
  justify-content: center;
915
1091
  }
916
1092
 
1093
+ .editor-preview-dropdown__button-external {
1094
+ width: 100%;
1095
+ display: flex;
1096
+ justify-content: space-between;
1097
+ }
1098
+
917
1099
  .table-of-contents__popover.components-popover .components-popover__content {
918
1100
  min-width: 380px;
919
1101
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wordpress/editor",
3
- "version": "13.24.0",
3
+ "version": "13.25.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,35 +31,36 @@
31
31
  ],
32
32
  "dependencies": {
33
33
  "@babel/runtime": "^7.16.0",
34
- "@wordpress/a11y": "^3.47.0",
35
- "@wordpress/api-fetch": "^6.44.0",
36
- "@wordpress/blob": "^3.47.0",
37
- "@wordpress/block-editor": "^12.15.0",
38
- "@wordpress/blocks": "^12.24.0",
39
- "@wordpress/components": "^25.13.0",
40
- "@wordpress/compose": "^6.24.0",
41
- "@wordpress/core-data": "^6.24.0",
42
- "@wordpress/data": "^9.17.0",
43
- "@wordpress/date": "^4.47.0",
44
- "@wordpress/deprecated": "^3.47.0",
45
- "@wordpress/dom": "^3.47.0",
46
- "@wordpress/element": "^5.24.0",
47
- "@wordpress/hooks": "^3.47.0",
48
- "@wordpress/html-entities": "^3.47.0",
49
- "@wordpress/i18n": "^4.47.0",
50
- "@wordpress/icons": "^9.38.0",
51
- "@wordpress/keyboard-shortcuts": "^4.24.0",
52
- "@wordpress/keycodes": "^3.47.0",
53
- "@wordpress/media-utils": "^4.38.0",
54
- "@wordpress/notices": "^4.15.0",
55
- "@wordpress/patterns": "^1.8.0",
56
- "@wordpress/preferences": "^3.24.0",
57
- "@wordpress/private-apis": "^0.29.0",
58
- "@wordpress/reusable-blocks": "^4.24.0",
59
- "@wordpress/rich-text": "^6.24.0",
60
- "@wordpress/server-side-render": "^4.24.0",
61
- "@wordpress/url": "^3.48.0",
62
- "@wordpress/wordcount": "^3.47.0",
34
+ "@wordpress/a11y": "^3.48.0",
35
+ "@wordpress/api-fetch": "^6.45.0",
36
+ "@wordpress/blob": "^3.48.0",
37
+ "@wordpress/block-editor": "^12.16.0",
38
+ "@wordpress/blocks": "^12.25.0",
39
+ "@wordpress/commands": "^0.19.0",
40
+ "@wordpress/components": "^25.14.0",
41
+ "@wordpress/compose": "^6.25.0",
42
+ "@wordpress/core-data": "^6.25.0",
43
+ "@wordpress/data": "^9.18.0",
44
+ "@wordpress/date": "^4.48.0",
45
+ "@wordpress/deprecated": "^3.48.0",
46
+ "@wordpress/dom": "^3.48.0",
47
+ "@wordpress/element": "^5.25.0",
48
+ "@wordpress/hooks": "^3.48.0",
49
+ "@wordpress/html-entities": "^3.48.0",
50
+ "@wordpress/i18n": "^4.48.0",
51
+ "@wordpress/icons": "^9.39.0",
52
+ "@wordpress/keyboard-shortcuts": "^4.25.0",
53
+ "@wordpress/keycodes": "^3.48.0",
54
+ "@wordpress/media-utils": "^4.39.0",
55
+ "@wordpress/notices": "^4.16.0",
56
+ "@wordpress/patterns": "^1.9.0",
57
+ "@wordpress/preferences": "^3.25.0",
58
+ "@wordpress/private-apis": "^0.30.0",
59
+ "@wordpress/reusable-blocks": "^4.25.0",
60
+ "@wordpress/rich-text": "^6.25.0",
61
+ "@wordpress/server-side-render": "^4.25.0",
62
+ "@wordpress/url": "^3.49.0",
63
+ "@wordpress/wordcount": "^3.48.0",
63
64
  "classnames": "^2.3.1",
64
65
  "date-fns": "^2.28.0",
65
66
  "memize": "^2.1.0",
@@ -74,5 +75,5 @@
74
75
  "publishConfig": {
75
76
  "access": "public"
76
77
  },
77
- "gitHead": "d98dff8ea96f29cfea045bf964269f46f040d539"
78
+ "gitHead": "fcf61b4beff747222c2c81d09d757ca1a0abd925"
78
79
  }
@@ -0,0 +1,182 @@
1
+ /**
2
+ * External dependencies
3
+ */
4
+ import classnames from 'classnames';
5
+
6
+ /**
7
+ * WordPress dependencies
8
+ */
9
+ import { __, isRTL, sprintf } from '@wordpress/i18n';
10
+ import { useSelect, useDispatch } from '@wordpress/data';
11
+ import {
12
+ Button,
13
+ __experimentalText as Text,
14
+ __experimentalHStack as HStack,
15
+ } from '@wordpress/components';
16
+ import { BlockIcon } from '@wordpress/block-editor';
17
+ import {
18
+ chevronLeftSmall,
19
+ chevronRightSmall,
20
+ page as pageIcon,
21
+ navigation as navigationIcon,
22
+ symbol,
23
+ } from '@wordpress/icons';
24
+ import { displayShortcut } from '@wordpress/keycodes';
25
+ import { useEntityRecord } from '@wordpress/core-data';
26
+ import { store as commandsStore } from '@wordpress/commands';
27
+ import { useState, useEffect, useRef } from '@wordpress/element';
28
+
29
+ /**
30
+ * Internal dependencies
31
+ */
32
+ import { store as editorStore } from '../../store';
33
+
34
+ const typeLabels = {
35
+ // translators: 1: Pattern title.
36
+ wp_pattern: __( 'Editing pattern: %s' ),
37
+ // translators: 1: Navigation menu title.
38
+ wp_navigation: __( 'Editing navigation menu: %s' ),
39
+ // translators: 1: Template title.
40
+ wp_template: __( 'Editing template: %s' ),
41
+ // translators: 1: Template part title.
42
+ wp_template_part: __( 'Editing template part: %s' ),
43
+ };
44
+
45
+ const icons = {
46
+ wp_block: symbol,
47
+ wp_navigation: navigationIcon,
48
+ };
49
+
50
+ export default function DocumentBar() {
51
+ const { isEditingTemplate, templateId, postType, postId } = useSelect(
52
+ ( select ) => {
53
+ const {
54
+ getRenderingMode,
55
+ getCurrentTemplateId,
56
+ getCurrentPostId,
57
+ getCurrentPostType,
58
+ } = select( editorStore );
59
+ const _templateId = getCurrentTemplateId();
60
+ return {
61
+ isEditingTemplate:
62
+ !! _templateId && getRenderingMode() === 'template-only',
63
+ templateId: _templateId,
64
+ postType: getCurrentPostType(),
65
+ postId: getCurrentPostId(),
66
+ };
67
+ },
68
+ []
69
+ );
70
+ const { getEditorSettings } = useSelect( editorStore );
71
+ const { setRenderingMode } = useDispatch( editorStore );
72
+
73
+ return (
74
+ <BaseDocumentActions
75
+ postType={ isEditingTemplate ? 'wp_template' : postType }
76
+ postId={ isEditingTemplate ? templateId : postId }
77
+ onBack={
78
+ isEditingTemplate
79
+ ? () =>
80
+ setRenderingMode(
81
+ getEditorSettings().defaultRenderingMode
82
+ )
83
+ : undefined
84
+ }
85
+ />
86
+ );
87
+ }
88
+
89
+ function BaseDocumentActions( { postType, postId, onBack } ) {
90
+ const { open: openCommandCenter } = useDispatch( commandsStore );
91
+ const { editedRecord: doc, isResolving } = useEntityRecord(
92
+ 'postType',
93
+ postType,
94
+ postId
95
+ );
96
+ const { templateIcon, templateTitle } = useSelect( ( select ) => {
97
+ const { __experimentalGetTemplateInfo: getTemplateInfo } =
98
+ select( editorStore );
99
+ const templateInfo = getTemplateInfo( doc );
100
+ return {
101
+ templateIcon: templateInfo.icon,
102
+ templateTitle: templateInfo.title,
103
+ };
104
+ } );
105
+ const isNotFound = ! doc && ! isResolving;
106
+ const icon = icons[ postType ] ?? pageIcon;
107
+ const [ isAnimated, setIsAnimated ] = useState( false );
108
+ const isMounting = useRef( true );
109
+ const isTemplate = [ 'wp_template', 'wp_template_part' ].includes(
110
+ postType
111
+ );
112
+ const isGlobalEntity = [
113
+ 'wp_template',
114
+ 'wp_navigation',
115
+ 'wp_template_part',
116
+ 'wp_block',
117
+ ].includes( postType );
118
+
119
+ useEffect( () => {
120
+ if ( ! isMounting.current ) {
121
+ setIsAnimated( true );
122
+ }
123
+ isMounting.current = false;
124
+ }, [ postType, postId ] );
125
+
126
+ const title = isTemplate ? templateTitle : doc.title;
127
+
128
+ return (
129
+ <div
130
+ className={ classnames( 'editor-document-bar', {
131
+ 'has-back-button': !! onBack,
132
+ 'is-animated': isAnimated,
133
+ 'is-global': isGlobalEntity,
134
+ } ) }
135
+ >
136
+ { onBack && (
137
+ <Button
138
+ className="editor-document-bar__back"
139
+ icon={ isRTL() ? chevronRightSmall : chevronLeftSmall }
140
+ onClick={ ( event ) => {
141
+ event.stopPropagation();
142
+ onBack();
143
+ } }
144
+ size="compact"
145
+ >
146
+ { __( 'Back' ) }
147
+ </Button>
148
+ ) }
149
+ { isNotFound && <Text>{ __( 'Document not found' ) }</Text> }
150
+ { ! isNotFound && (
151
+ <Button
152
+ className="editor-document-bar__command"
153
+ onClick={ () => openCommandCenter() }
154
+ size="compact"
155
+ >
156
+ <HStack
157
+ className="editor-document-bar__title"
158
+ spacing={ 1 }
159
+ justify="center"
160
+ >
161
+ <BlockIcon icon={ isTemplate ? templateIcon : icon } />
162
+ <Text
163
+ size="body"
164
+ as="h1"
165
+ aria-label={
166
+ typeLabels[ postType ]
167
+ ? // eslint-disable-next-line @wordpress/valid-sprintf
168
+ sprintf( typeLabels[ postType ], title )
169
+ : undefined
170
+ }
171
+ >
172
+ { title }
173
+ </Text>
174
+ </HStack>
175
+ <span className="editor-document-bar__shortcut">
176
+ { displayShortcut.primary( 'k' ) }
177
+ </span>
178
+ </Button>
179
+ ) }
180
+ </div>
181
+ );
182
+ }
@@ -0,0 +1,130 @@
1
+ .editor-document-bar {
2
+ display: flex;
3
+ align-items: center;
4
+ height: $button-size-compact;
5
+ justify-content: space-between;
6
+ // Flex items will, by default, refuse to shrink below a minimum
7
+ // intrinsic width. In order to shrink this flexbox item, and
8
+ // subsequently truncate child text, we set an explicit min-width.
9
+ // See https://dev.w3.org/csswg/css-flexbox/#min-size-auto
10
+ min-width: 0;
11
+ background: $gray-100;
12
+ border-radius: $grid-unit-05;
13
+ width: min(100%, 450px);
14
+
15
+ &:hover {
16
+ background-color: $gray-200;
17
+ }
18
+
19
+ .components-button {
20
+ border-radius: $grid-unit-05;
21
+
22
+ &:hover {
23
+ color: var(--wp-block-synced-color);
24
+ background: $gray-200;
25
+ }
26
+ }
27
+
28
+ @include break-large() {
29
+ width: min(100%, 450px);
30
+ }
31
+ }
32
+
33
+ .editor-document-bar__command {
34
+ flex-grow: 1;
35
+ color: var(--wp-block-synced-color);
36
+ overflow: hidden;
37
+ }
38
+
39
+ .editor-document-bar__title {
40
+ flex-grow: 1;
41
+ overflow: hidden;
42
+ color: $gray-800;
43
+
44
+ // Offset the layout based on the width of the ⌘K label. This ensures the title is centrally aligned.
45
+ @include break-small() {
46
+ padding-left: $grid-unit-40;
47
+ }
48
+
49
+ &:hover {
50
+ color: var(--wp-block-synced-color);
51
+ }
52
+
53
+ .editor-document-bar.is-global & {
54
+ color: var(--wp-block-synced-color);
55
+ }
56
+
57
+ .block-editor-block-icon {
58
+ min-width: $grid-unit-30;
59
+ flex-shrink: 0;
60
+ }
61
+
62
+ h1 {
63
+ white-space: nowrap;
64
+ overflow: hidden;
65
+ text-overflow: ellipsis;
66
+ max-width: 50%;
67
+ color: currentColor;
68
+ }
69
+
70
+ .editor-document-bar.is-animated.has-back-button & {
71
+ animation: editor-document-bar__slide-in-left 0.3s;
72
+ @include reduce-motion("animation");
73
+ }
74
+
75
+ .editor-document-bar.is-animated & {
76
+ animation: editor-document-bar__slide-in-right 0.3s;
77
+ @include reduce-motion("animation");
78
+ }
79
+ }
80
+
81
+ .editor-document-bar__shortcut {
82
+ color: $gray-800;
83
+ min-width: $grid-unit-40;
84
+ display: none;
85
+
86
+ @include break-medium() {
87
+ display: initial;
88
+ }
89
+ }
90
+
91
+ .editor-document-bar__back.components-button.has-icon.has-text {
92
+ min-width: $button-size;
93
+ flex-shrink: 0;
94
+ color: $gray-700;
95
+ gap: 0;
96
+ z-index: 1;
97
+ position: absolute;
98
+
99
+ &:hover {
100
+ color: var(--wp-block-synced-color);
101
+ background-color: transparent;
102
+ }
103
+
104
+ .editor-document-bar.is-animated & {
105
+ animation: editor-document-bar__slide-in-left 0.3s;
106
+ @include reduce-motion("animation");
107
+ }
108
+ }
109
+
110
+ @keyframes editor-document-bar__slide-in-right {
111
+ from {
112
+ transform: translateX(-15%);
113
+ opacity: 0;
114
+ }
115
+ to {
116
+ transform: translateX(0);
117
+ opacity: 1;
118
+ }
119
+ }
120
+
121
+ @keyframes editor-document-bar__slide-in-left {
122
+ from {
123
+ transform: translateX(15%);
124
+ opacity: 0;
125
+ }
126
+ to {
127
+ transform: translateX(0);
128
+ opacity: 1;
129
+ }
130
+ }
@@ -0,0 +1,108 @@
1
+ /**
2
+ * WordPress dependencies
3
+ */
4
+ import { useSelect, useDispatch } from '@wordpress/data';
5
+ import { useEffect, useState, useRef } from '@wordpress/element';
6
+ import { store as noticesStore } from '@wordpress/notices';
7
+ import { __ } from '@wordpress/i18n';
8
+ import { __experimentalConfirmDialog as ConfirmDialog } from '@wordpress/components';
9
+
10
+ /**
11
+ * Internal dependencies
12
+ */
13
+ import { store as editorStore } from '../../store';
14
+
15
+ /**
16
+ * Component that:
17
+ *
18
+ * - Displays a 'Edit your template to edit this block' notification when the
19
+ * user is focusing on editing page content and clicks on a disabled template
20
+ * block.
21
+ * - Displays a 'Edit your template to edit this block' dialog when the user
22
+ * is focusing on editing page conetnt and double clicks on a disabled
23
+ * template block.
24
+ *
25
+ * @param {Object} props
26
+ * @param {import('react').RefObject<HTMLElement>} props.contentRef Ref to the block
27
+ * editor iframe canvas.
28
+ */
29
+ export default function EditTemplateBlocksNotification( { contentRef } ) {
30
+ const renderingMode = useSelect(
31
+ ( select ) => select( editorStore ).getRenderingMode(),
32
+ []
33
+ );
34
+ const { getNotices } = useSelect( noticesStore );
35
+
36
+ const { createInfoNotice, removeNotice } = useDispatch( noticesStore );
37
+ const { setRenderingMode } = useDispatch( editorStore );
38
+
39
+ const [ isDialogOpen, setIsDialogOpen ] = useState( false );
40
+
41
+ const lastNoticeId = useRef( 0 );
42
+
43
+ useEffect( () => {
44
+ const handleClick = async ( event ) => {
45
+ if ( renderingMode !== 'template-locked' ) {
46
+ return;
47
+ }
48
+ if ( ! event.target.classList.contains( 'is-root-container' ) ) {
49
+ return;
50
+ }
51
+ const isNoticeAlreadyShowing = getNotices().some(
52
+ ( notice ) => notice.id === lastNoticeId.current
53
+ );
54
+ if ( isNoticeAlreadyShowing ) {
55
+ return;
56
+ }
57
+ const { notice } = await createInfoNotice(
58
+ __( 'Edit your template to edit this block.' ),
59
+ {
60
+ isDismissible: true,
61
+ type: 'snackbar',
62
+ actions: [
63
+ {
64
+ label: __( 'Edit template' ),
65
+ onClick: () => setRenderingMode( 'template-only' ),
66
+ },
67
+ ],
68
+ }
69
+ );
70
+ lastNoticeId.current = notice.id;
71
+ };
72
+
73
+ const handleDblClick = ( event ) => {
74
+ if ( renderingMode !== 'template-locked' ) {
75
+ return;
76
+ }
77
+ if ( ! event.target.classList.contains( 'is-root-container' ) ) {
78
+ return;
79
+ }
80
+ if ( lastNoticeId.current ) {
81
+ removeNotice( lastNoticeId.current );
82
+ }
83
+ setIsDialogOpen( true );
84
+ };
85
+
86
+ const canvas = contentRef.current;
87
+ canvas?.addEventListener( 'click', handleClick );
88
+ canvas?.addEventListener( 'dblclick', handleDblClick );
89
+ return () => {
90
+ canvas?.removeEventListener( 'click', handleClick );
91
+ canvas?.removeEventListener( 'dblclick', handleDblClick );
92
+ };
93
+ }, [ lastNoticeId, renderingMode, contentRef.current ] );
94
+
95
+ return (
96
+ <ConfirmDialog
97
+ isOpen={ isDialogOpen }
98
+ confirmButtonText={ __( 'Edit template' ) }
99
+ onConfirm={ () => {
100
+ setIsDialogOpen( false );
101
+ setRenderingMode( 'template-only' );
102
+ } }
103
+ onCancel={ () => setIsDialogOpen( false ) }
104
+ >
105
+ { __( 'Edit your template to edit this block.' ) }
106
+ </ConfirmDialog>
107
+ );
108
+ }