@wordpress/block-editor 12.14.0 → 12.15.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 (240) hide show
  1. package/CHANGELOG.md +2 -0
  2. package/README.md +1 -1
  3. package/build/components/block-list/block.native.js +2 -0
  4. package/build/components/block-list/block.native.js.map +1 -1
  5. package/build/components/block-parent-selector/index.js +1 -1
  6. package/build/components/block-parent-selector/index.js.map +1 -1
  7. package/build/components/block-pattern-setup/index.js +25 -16
  8. package/build/components/block-pattern-setup/index.js.map +1 -1
  9. package/build/components/block-pattern-setup/setup-toolbar.js +4 -2
  10. package/build/components/block-pattern-setup/setup-toolbar.js.map +1 -1
  11. package/build/components/block-patterns-list/index.js +36 -19
  12. package/build/components/block-patterns-list/index.js.map +1 -1
  13. package/build/components/block-rename/index.js +28 -0
  14. package/build/components/block-rename/index.js.map +1 -0
  15. package/build/components/block-rename/is-empty-string.js +10 -0
  16. package/build/components/block-rename/is-empty-string.js.map +1 -0
  17. package/build/components/block-rename/modal.js +87 -0
  18. package/build/components/block-rename/modal.js.map +1 -0
  19. package/build/components/block-rename/rename-control.js +74 -0
  20. package/build/components/block-rename/rename-control.js.map +1 -0
  21. package/build/components/block-rename/use-block-rename.js +17 -0
  22. package/build/components/block-rename/use-block-rename.js.map +1 -0
  23. package/build/components/block-settings-menu/block-settings-dropdown.js +33 -20
  24. package/build/components/block-settings-menu/block-settings-dropdown.js.map +1 -1
  25. package/build/components/block-settings-menu-controls/index.js +7 -0
  26. package/build/components/block-settings-menu-controls/index.js.map +1 -1
  27. package/build/components/block-toolbar/block-toolbar-menu.native.js +1 -1
  28. package/build/components/block-toolbar/block-toolbar-menu.native.js.map +1 -1
  29. package/build/components/block-types-list/index.js +6 -2
  30. package/build/components/block-types-list/index.js.map +1 -1
  31. package/build/components/date-format-picker/index.js +8 -1
  32. package/build/components/date-format-picker/index.js.map +1 -1
  33. package/build/components/global-styles/advanced-panel.js +1 -1
  34. package/build/components/global-styles/advanced-panel.js.map +1 -1
  35. package/build/components/image-size-control/index.js +0 -5
  36. package/build/components/image-size-control/index.js.map +1 -1
  37. package/build/components/inner-blocks/index.js +3 -1
  38. package/build/components/inner-blocks/index.js.map +1 -1
  39. package/build/components/inner-blocks/warning-max-depth-exceeded.native.js +29 -31
  40. package/build/components/inner-blocks/warning-max-depth-exceeded.native.js.map +1 -1
  41. package/build/components/inserter/block-patterns-explorer/pattern-list.js +1 -1
  42. package/build/components/inserter/block-patterns-explorer/pattern-list.js.map +1 -1
  43. package/build/components/inserter/block-patterns-tab/pattern-category-previews.js +1 -1
  44. package/build/components/inserter/block-patterns-tab/pattern-category-previews.js.map +1 -1
  45. package/build/components/inserter/block-patterns-tab/use-pattern-categories.js +1 -1
  46. package/build/components/inserter/block-patterns-tab/use-pattern-categories.js.map +1 -1
  47. package/build/components/inserter/block-patterns-tab/utils.js +3 -4
  48. package/build/components/inserter/block-patterns-tab/utils.js.map +1 -1
  49. package/build/components/inserter/hooks/use-patterns-state.js +2 -1
  50. package/build/components/inserter/hooks/use-patterns-state.js.map +1 -1
  51. package/build/components/inserter-listbox/index.js +11 -6
  52. package/build/components/inserter-listbox/index.js.map +1 -1
  53. package/build/components/inserter-listbox/item.js +24 -23
  54. package/build/components/inserter-listbox/item.js.map +1 -1
  55. package/build/components/inserter-listbox/row.js +5 -5
  56. package/build/components/inserter-listbox/row.js.map +1 -1
  57. package/build/components/list-view/use-list-view-expand-selected-item.js +2 -3
  58. package/build/components/list-view/use-list-view-expand-selected-item.js.map +1 -1
  59. package/build/components/preview-options/index.js +4 -2
  60. package/build/components/preview-options/index.js.map +1 -1
  61. package/build/components/rich-text/index.native.js +1 -1
  62. package/build/components/rich-text/index.native.js.map +1 -1
  63. package/build/components/rich-text/native/index.native.js +34 -3
  64. package/build/components/rich-text/native/index.native.js.map +1 -1
  65. package/build/components/rich-text/use-input-rules.js +30 -1
  66. package/build/components/rich-text/use-input-rules.js.map +1 -1
  67. package/build/components/spacing-sizes-control/input-controls/spacing-input-control.js +1 -1
  68. package/build/components/spacing-sizes-control/input-controls/spacing-input-control.js.map +1 -1
  69. package/build/components/use-block-drop-zone/index.js +4 -1
  70. package/build/components/use-block-drop-zone/index.js.map +1 -1
  71. package/build/components/use-moving-animation/index.js +2 -1
  72. package/build/components/use-moving-animation/index.js.map +1 -1
  73. package/build/components/use-settings/index.js +2 -2
  74. package/build/components/use-settings/index.js.map +1 -1
  75. package/build/hooks/block-renaming.js +42 -0
  76. package/build/hooks/block-renaming.js.map +1 -1
  77. package/build/hooks/custom-fields.js +53 -48
  78. package/build/hooks/custom-fields.js.map +1 -1
  79. package/build/hooks/index.js +0 -1
  80. package/build/hooks/index.js.map +1 -1
  81. package/build/hooks/layout.js +13 -7
  82. package/build/hooks/layout.js.map +1 -1
  83. package/build/layouts/constrained.js +4 -3
  84. package/build/layouts/constrained.js.map +1 -1
  85. package/build/store/selectors.js +2 -0
  86. package/build/store/selectors.js.map +1 -1
  87. package/build/utils/transform-styles/index.js +26 -6
  88. package/build/utils/transform-styles/index.js.map +1 -1
  89. package/build-module/components/block-list/block.native.js +2 -0
  90. package/build-module/components/block-list/block.native.js.map +1 -1
  91. package/build-module/components/block-parent-selector/index.js +1 -1
  92. package/build-module/components/block-parent-selector/index.js.map +1 -1
  93. package/build-module/components/block-pattern-setup/index.js +24 -15
  94. package/build-module/components/block-pattern-setup/index.js.map +1 -1
  95. package/build-module/components/block-pattern-setup/setup-toolbar.js +4 -2
  96. package/build-module/components/block-pattern-setup/setup-toolbar.js.map +1 -1
  97. package/build-module/components/block-patterns-list/index.js +36 -19
  98. package/build-module/components/block-patterns-list/index.js.map +1 -1
  99. package/build-module/components/block-rename/index.js +4 -0
  100. package/build-module/components/block-rename/index.js.map +1 -0
  101. package/build-module/components/block-rename/is-empty-string.js +4 -0
  102. package/build-module/components/block-rename/is-empty-string.js.map +1 -0
  103. package/build-module/components/block-rename/modal.js +79 -0
  104. package/build-module/components/block-rename/modal.js.map +1 -0
  105. package/build-module/components/block-rename/rename-control.js +66 -0
  106. package/build-module/components/block-rename/rename-control.js.map +1 -0
  107. package/build-module/components/block-rename/use-block-rename.js +10 -0
  108. package/build-module/components/block-rename/use-block-rename.js.map +1 -0
  109. package/build-module/components/block-settings-menu/block-settings-dropdown.js +34 -21
  110. package/build-module/components/block-settings-menu/block-settings-dropdown.js.map +1 -1
  111. package/build-module/components/block-settings-menu-controls/index.js +7 -0
  112. package/build-module/components/block-settings-menu-controls/index.js.map +1 -1
  113. package/build-module/components/block-toolbar/block-toolbar-menu.native.js +1 -1
  114. package/build-module/components/block-toolbar/block-toolbar-menu.native.js.map +1 -1
  115. package/build-module/components/block-types-list/index.js +6 -2
  116. package/build-module/components/block-types-list/index.js.map +1 -1
  117. package/build-module/components/date-format-picker/index.js +8 -1
  118. package/build-module/components/date-format-picker/index.js.map +1 -1
  119. package/build-module/components/global-styles/advanced-panel.js +1 -1
  120. package/build-module/components/global-styles/advanced-panel.js.map +1 -1
  121. package/build-module/components/image-size-control/index.js +0 -5
  122. package/build-module/components/image-size-control/index.js.map +1 -1
  123. package/build-module/components/inner-blocks/index.js +3 -1
  124. package/build-module/components/inner-blocks/index.js.map +1 -1
  125. package/build-module/components/inner-blocks/warning-max-depth-exceeded.native.js +30 -32
  126. package/build-module/components/inner-blocks/warning-max-depth-exceeded.native.js.map +1 -1
  127. package/build-module/components/inserter/block-patterns-explorer/pattern-list.js +2 -2
  128. package/build-module/components/inserter/block-patterns-explorer/pattern-list.js.map +1 -1
  129. package/build-module/components/inserter/block-patterns-tab/pattern-category-previews.js +4 -4
  130. package/build-module/components/inserter/block-patterns-tab/pattern-category-previews.js.map +1 -1
  131. package/build-module/components/inserter/block-patterns-tab/use-pattern-categories.js +2 -2
  132. package/build-module/components/inserter/block-patterns-tab/use-pattern-categories.js.map +1 -1
  133. package/build-module/components/inserter/block-patterns-tab/utils.js +3 -4
  134. package/build-module/components/inserter/block-patterns-tab/utils.js.map +1 -1
  135. package/build-module/components/inserter/hooks/use-patterns-state.js +2 -1
  136. package/build-module/components/inserter/hooks/use-patterns-state.js.map +1 -1
  137. package/build-module/components/inserter-listbox/index.js +13 -8
  138. package/build-module/components/inserter-listbox/index.js.map +1 -1
  139. package/build-module/components/inserter-listbox/item.js +25 -23
  140. package/build-module/components/inserter-listbox/item.js.map +1 -1
  141. package/build-module/components/inserter-listbox/row.js +6 -5
  142. package/build-module/components/inserter-listbox/row.js.map +1 -1
  143. package/build-module/components/list-view/use-list-view-expand-selected-item.js +2 -3
  144. package/build-module/components/list-view/use-list-view-expand-selected-item.js.map +1 -1
  145. package/build-module/components/preview-options/index.js +4 -2
  146. package/build-module/components/preview-options/index.js.map +1 -1
  147. package/build-module/components/rich-text/index.native.js +1 -1
  148. package/build-module/components/rich-text/index.native.js.map +1 -1
  149. package/build-module/components/rich-text/native/index.native.js +34 -3
  150. package/build-module/components/rich-text/native/index.native.js.map +1 -1
  151. package/build-module/components/rich-text/use-input-rules.js +31 -2
  152. package/build-module/components/rich-text/use-input-rules.js.map +1 -1
  153. package/build-module/components/spacing-sizes-control/input-controls/spacing-input-control.js +1 -1
  154. package/build-module/components/spacing-sizes-control/input-controls/spacing-input-control.js.map +1 -1
  155. package/build-module/components/use-block-drop-zone/index.js +4 -1
  156. package/build-module/components/use-block-drop-zone/index.js.map +1 -1
  157. package/build-module/components/use-moving-animation/index.js +2 -1
  158. package/build-module/components/use-moving-animation/index.js.map +1 -1
  159. package/build-module/components/use-settings/index.js +2 -2
  160. package/build-module/components/use-settings/index.js.map +1 -1
  161. package/build-module/hooks/block-renaming.js +40 -0
  162. package/build-module/hooks/block-renaming.js.map +1 -1
  163. package/build-module/hooks/custom-fields.js +53 -48
  164. package/build-module/hooks/custom-fields.js.map +1 -1
  165. package/build-module/hooks/index.js +0 -1
  166. package/build-module/hooks/index.js.map +1 -1
  167. package/build-module/hooks/layout.js +13 -7
  168. package/build-module/hooks/layout.js.map +1 -1
  169. package/build-module/layouts/constrained.js +4 -3
  170. package/build-module/layouts/constrained.js.map +1 -1
  171. package/build-module/store/selectors.js +2 -0
  172. package/build-module/store/selectors.js.map +1 -1
  173. package/build-module/utils/transform-styles/index.js +24 -7
  174. package/build-module/utils/transform-styles/index.js.map +1 -1
  175. package/build-style/content-rtl.css +6 -6
  176. package/build-style/content.css +6 -6
  177. package/build-style/style-rtl.css +10 -5
  178. package/build-style/style.css +10 -5
  179. package/package.json +31 -31
  180. package/src/components/block-list/block.native.js +2 -0
  181. package/src/components/block-parent-selector/index.js +1 -1
  182. package/src/components/block-pattern-setup/index.js +38 -22
  183. package/src/components/block-pattern-setup/setup-toolbar.js +2 -0
  184. package/src/components/block-pattern-setup/style.scss +4 -1
  185. package/src/components/block-patterns-list/README.md +4 -4
  186. package/src/components/block-patterns-list/index.js +60 -34
  187. package/src/components/block-patterns-list/style.scss +7 -0
  188. package/src/components/block-rename/index.js +3 -0
  189. package/src/components/block-rename/is-empty-string.js +3 -0
  190. package/src/components/block-rename/modal.js +115 -0
  191. package/src/components/block-rename/rename-control.js +80 -0
  192. package/src/components/block-rename/use-block-rename.js +10 -0
  193. package/src/components/block-settings-menu/block-settings-dropdown.js +38 -34
  194. package/src/components/block-settings-menu-controls/index.js +9 -0
  195. package/src/components/block-toolbar/block-toolbar-menu.native.js +1 -4
  196. package/src/components/block-types-list/index.js +5 -4
  197. package/src/components/button-block-appender/content.scss +2 -2
  198. package/src/components/date-format-picker/index.js +7 -0
  199. package/src/components/editable-text/README.md +0 -36
  200. package/src/components/global-styles/advanced-panel.js +1 -1
  201. package/src/components/image-size-control/index.js +0 -6
  202. package/src/components/inner-blocks/index.js +6 -2
  203. package/src/components/inner-blocks/warning-max-depth-exceeded.native.js +57 -33
  204. package/src/components/inserter/block-patterns-explorer/pattern-list.js +5 -1
  205. package/src/components/inserter/block-patterns-tab/pattern-category-previews.js +7 -3
  206. package/src/components/inserter/block-patterns-tab/use-pattern-categories.js +6 -1
  207. package/src/components/inserter/block-patterns-tab/utils.js +6 -4
  208. package/src/components/inserter/hooks/use-patterns-state.js +3 -1
  209. package/src/components/inserter-listbox/index.js +11 -7
  210. package/src/components/inserter-listbox/item.js +11 -12
  211. package/src/components/inserter-listbox/row.js +6 -12
  212. package/src/components/list-view/use-list-view-expand-selected-item.js +7 -8
  213. package/src/components/plain-text/README.md +0 -28
  214. package/src/components/preview-options/index.js +2 -0
  215. package/src/components/rich-text/README.md +0 -58
  216. package/src/components/rich-text/index.native.js +1 -1
  217. package/src/components/rich-text/native/index.native.js +45 -2
  218. package/src/components/rich-text/use-input-rules.js +30 -2
  219. package/src/components/spacing-sizes-control/input-controls/spacing-input-control.js +1 -1
  220. package/src/components/url-input/README.md +1 -74
  221. package/src/components/use-block-drop-zone/index.js +4 -1
  222. package/src/components/use-moving-animation/index.js +1 -1
  223. package/src/components/use-settings/index.js +2 -2
  224. package/src/components/use-settings/test/index.js +1 -1
  225. package/src/hooks/block-renaming.js +47 -0
  226. package/src/hooks/custom-fields.js +68 -65
  227. package/src/hooks/index.js +0 -1
  228. package/src/hooks/layout.js +12 -8
  229. package/src/hooks/test/__snapshots__/align.native.js.snap +5 -5
  230. package/src/layouts/constrained.js +57 -50
  231. package/src/store/selectors.js +2 -0
  232. package/src/style.scss +1 -1
  233. package/src/utils/test/transform-styles.js +49 -0
  234. package/src/utils/transform-styles/index.js +39 -13
  235. package/build/hooks/block-rename-ui.js +0 -167
  236. package/build/hooks/block-rename-ui.js.map +0 -1
  237. package/build-module/hooks/block-rename-ui.js +0 -159
  238. package/build-module/hooks/block-rename-ui.js.map +0 -1
  239. package/src/hooks/block-rename-ui.js +0 -228
  240. /package/src/{hooks/block-rename-ui.scss → components/block-rename/style.scss} +0 -0
@@ -6,13 +6,11 @@ import classnames from 'classnames';
6
6
  /**
7
7
  * WordPress dependencies
8
8
  */
9
- import { useState, forwardRef } from '@wordpress/element';
9
+ import { useEffect, useState, forwardRef } from '@wordpress/element';
10
10
  import {
11
11
  VisuallyHidden,
12
- __unstableComposite as Composite,
13
- __unstableUseCompositeState as useCompositeState,
14
- __unstableCompositeItem as CompositeItem,
15
12
  Tooltip,
13
+ privateApis as componentsPrivateApis,
16
14
  __experimentalHStack as HStack,
17
15
  } from '@wordpress/components';
18
16
  import { useInstanceId } from '@wordpress/compose';
@@ -22,9 +20,17 @@ import { Icon, symbol } from '@wordpress/icons';
22
20
  /**
23
21
  * Internal dependencies
24
22
  */
23
+ import { unlock } from '../../lock-unlock';
25
24
  import BlockPreview from '../block-preview';
26
25
  import InserterDraggableBlocks from '../inserter-draggable-blocks';
27
26
  import BlockPatternsPaging from '../block-patterns-paging';
27
+ import { PATTERN_TYPES } from '../inserter/block-patterns-tab/utils';
28
+
29
+ const {
30
+ CompositeV2: Composite,
31
+ CompositeItemV2: CompositeItem,
32
+ useCompositeStoreV2: useCompositeStore,
33
+ } = unlock( componentsPrivateApis );
28
34
 
29
35
  const WithToolTip = ( { showTooltip, title, children } ) => {
30
36
  if ( showTooltip ) {
@@ -34,11 +40,11 @@ const WithToolTip = ( { showTooltip, title, children } ) => {
34
40
  };
35
41
 
36
42
  function BlockPattern( {
43
+ id,
37
44
  isDraggable,
38
45
  pattern,
39
46
  onClick,
40
47
  onHover,
41
- composite,
42
48
  showTooltip,
43
49
  } ) {
44
50
  const [ isDragging, setIsDragging ] = useState( false );
@@ -71,20 +77,33 @@ function BlockPattern( {
71
77
  } }
72
78
  >
73
79
  <WithToolTip
74
- showTooltip={ showTooltip && ! pattern.id }
80
+ showTooltip={
81
+ showTooltip && ! pattern.type !== PATTERN_TYPES.user
82
+ }
75
83
  title={ pattern.title }
76
84
  >
77
85
  <CompositeItem
78
- role="option"
79
- as="div"
80
- { ...composite }
81
- className={ classnames(
82
- 'block-editor-block-patterns-list__item',
83
- {
84
- 'block-editor-block-patterns-list__list-item-synced':
85
- pattern.id && ! pattern.syncStatus,
86
- }
87
- ) }
86
+ render={
87
+ <div
88
+ role="option"
89
+ aria-label={ pattern.title }
90
+ aria-describedby={
91
+ pattern.description
92
+ ? descriptionId
93
+ : undefined
94
+ }
95
+ className={ classnames(
96
+ 'block-editor-block-patterns-list__item',
97
+ {
98
+ 'block-editor-block-patterns-list__list-item-synced':
99
+ pattern.type ===
100
+ PATTERN_TYPES.user &&
101
+ ! pattern.syncStatus,
102
+ }
103
+ ) }
104
+ />
105
+ }
106
+ id={ id }
88
107
  onClick={ () => {
89
108
  onClick( pattern, blocks );
90
109
  onHover?.( null );
@@ -96,10 +115,6 @@ function BlockPattern( {
96
115
  onHover?.( pattern );
97
116
  } }
98
117
  onMouseLeave={ () => onHover?.( null ) }
99
- aria-label={ pattern.title }
100
- aria-describedby={
101
- pattern.description ? descriptionId : undefined
102
- }
103
118
  >
104
119
  <BlockPreview
105
120
  blocks={ blocks }
@@ -107,15 +122,17 @@ function BlockPattern( {
107
122
  />
108
123
 
109
124
  <HStack className="block-editor-patterns__pattern-details">
110
- { pattern.id && ! pattern.syncStatus && (
111
- <div className="block-editor-patterns__pattern-icon-wrapper">
112
- <Icon
113
- className="block-editor-patterns__pattern-icon"
114
- icon={ symbol }
115
- />
116
- </div>
117
- ) }
118
- { ( ! showTooltip || pattern.id ) && (
125
+ { pattern.type === PATTERN_TYPES.user &&
126
+ ! pattern.syncStatus && (
127
+ <div className="block-editor-patterns__pattern-icon-wrapper">
128
+ <Icon
129
+ className="block-editor-patterns__pattern-icon"
130
+ icon={ symbol }
131
+ />
132
+ </div>
133
+ ) }
134
+ { ( ! showTooltip ||
135
+ pattern.type === PATTERN_TYPES.user ) && (
119
136
  <div className="block-editor-block-patterns-list__item-title">
120
137
  { pattern.title }
121
138
  </div>
@@ -141,7 +158,7 @@ function BlockPatternPlaceholder() {
141
158
  );
142
159
  }
143
160
 
144
- function BlockPatternList(
161
+ function BlockPatternsList(
145
162
  {
146
163
  isDraggable,
147
164
  blockPatterns,
@@ -155,10 +172,19 @@ function BlockPatternList(
155
172
  },
156
173
  ref
157
174
  ) {
158
- const composite = useCompositeState( { orientation } );
175
+ const compositeStore = useCompositeStore( { orientation } );
176
+ const { setActiveId } = compositeStore;
177
+
178
+ useEffect( () => {
179
+ // We reset the active composite item whenever the
180
+ // available patterns change, to make sure that
181
+ // focus is put back to the start.
182
+ setActiveId( undefined );
183
+ }, [ setActiveId, shownPatterns, blockPatterns ] );
184
+
159
185
  return (
160
186
  <Composite
161
- { ...composite }
187
+ store={ compositeStore }
162
188
  role="listbox"
163
189
  className="block-editor-block-patterns-list"
164
190
  aria-label={ label }
@@ -169,11 +195,11 @@ function BlockPatternList(
169
195
  return isShown ? (
170
196
  <BlockPattern
171
197
  key={ pattern.name }
198
+ id={ pattern.name }
172
199
  pattern={ pattern }
173
200
  onClick={ onClickPattern }
174
201
  onHover={ onHover }
175
202
  isDraggable={ isDraggable }
176
- composite={ composite }
177
203
  showTooltip={ showTitlesAsTooltip }
178
204
  />
179
205
  ) : (
@@ -185,4 +211,4 @@ function BlockPatternList(
185
211
  );
186
212
  }
187
213
 
188
- export default forwardRef( BlockPatternList );
214
+ export default forwardRef( BlockPatternsList );
@@ -18,6 +18,13 @@
18
18
 
19
19
  .block-editor-block-patterns-list__item {
20
20
  height: 100%;
21
+ // This is derived from the top padding set on
22
+ // `.block-editor-block-patterns-explorer__list`
23
+ scroll-margin-top: $grid-unit-30;
24
+ // This is derived from the bottom padding set on
25
+ // `.block-editor-block-patterns-explorer__list` and
26
+ // the bottom margin set on `...__list-item` above
27
+ scroll-margin-bottom: ($grid-unit-40 + $grid-unit-30);
21
28
 
22
29
  .block-editor-block-preview__container {
23
30
  display: flex;
@@ -0,0 +1,3 @@
1
+ export { default as BlockRenameControl } from './rename-control';
2
+ export { default as BlockRenameModal } from './modal';
3
+ export { default as useBlockRename } from './use-block-rename';
@@ -0,0 +1,3 @@
1
+ export default function isEmptyString( testString ) {
2
+ return testString?.trim()?.length === 0;
3
+ }
@@ -0,0 +1,115 @@
1
+ /**
2
+ * WordPress dependencies
3
+ */
4
+ import {
5
+ __experimentalHStack as HStack,
6
+ __experimentalVStack as VStack,
7
+ Button,
8
+ TextControl,
9
+ Modal,
10
+ } from '@wordpress/components';
11
+ import { useInstanceId } from '@wordpress/compose';
12
+ import { __, sprintf } from '@wordpress/i18n';
13
+ import { useState } from '@wordpress/element';
14
+ import { speak } from '@wordpress/a11y';
15
+
16
+ /**
17
+ * Internal dependencies
18
+ */
19
+ import isEmptyString from './is-empty-string';
20
+
21
+ export default function BlockRenameModal( {
22
+ blockName,
23
+ originalBlockName,
24
+ onClose,
25
+ onSave,
26
+ } ) {
27
+ const [ editedBlockName, setEditedBlockName ] = useState( blockName );
28
+
29
+ const nameHasChanged = editedBlockName !== blockName;
30
+ const nameIsOriginal = editedBlockName === originalBlockName;
31
+ const nameIsEmpty = isEmptyString( editedBlockName );
32
+
33
+ const isNameValid = nameHasChanged || nameIsOriginal;
34
+
35
+ const autoSelectInputText = ( event ) => event.target.select();
36
+
37
+ const dialogDescription = useInstanceId(
38
+ BlockRenameModal,
39
+ `block-editor-rename-modal__description`
40
+ );
41
+
42
+ const handleSubmit = () => {
43
+ const message =
44
+ nameIsOriginal || nameIsEmpty
45
+ ? sprintf(
46
+ /* translators: %s: new name/label for the block */
47
+ __( 'Block name reset to: "%s".' ),
48
+ editedBlockName
49
+ )
50
+ : sprintf(
51
+ /* translators: %s: new name/label for the block */
52
+ __( 'Block name changed to: "%s".' ),
53
+ editedBlockName
54
+ );
55
+
56
+ // Must be assertive to immediately announce change.
57
+ speak( message, 'assertive' );
58
+ onSave( editedBlockName );
59
+
60
+ // Immediate close avoids ability to hit save multiple times.
61
+ onClose();
62
+ };
63
+
64
+ return (
65
+ <Modal
66
+ title={ __( 'Rename' ) }
67
+ onRequestClose={ onClose }
68
+ overlayClassName="block-editor-block-rename-modal"
69
+ aria={ {
70
+ describedby: dialogDescription,
71
+ } }
72
+ focusOnMount="firstContentElement"
73
+ >
74
+ <p id={ dialogDescription }>
75
+ { __( 'Enter a custom name for this block.' ) }
76
+ </p>
77
+ <form
78
+ onSubmit={ ( e ) => {
79
+ e.preventDefault();
80
+
81
+ if ( ! isNameValid ) {
82
+ return;
83
+ }
84
+
85
+ handleSubmit();
86
+ } }
87
+ >
88
+ <VStack spacing="3">
89
+ <TextControl
90
+ __nextHasNoMarginBottom
91
+ value={ editedBlockName }
92
+ label={ __( 'Block name' ) }
93
+ hideLabelFromVision={ true }
94
+ placeholder={ originalBlockName }
95
+ onChange={ setEditedBlockName }
96
+ onFocus={ autoSelectInputText }
97
+ />
98
+ <HStack justify="right">
99
+ <Button variant="tertiary" onClick={ onClose }>
100
+ { __( 'Cancel' ) }
101
+ </Button>
102
+
103
+ <Button
104
+ aria-disabled={ ! isNameValid }
105
+ variant="primary"
106
+ type="submit"
107
+ >
108
+ { __( 'Save' ) }
109
+ </Button>
110
+ </HStack>
111
+ </VStack>
112
+ </form>
113
+ </Modal>
114
+ );
115
+ }
@@ -0,0 +1,80 @@
1
+ /**
2
+ * WordPress dependencies
3
+ */
4
+ import { MenuItem } from '@wordpress/components';
5
+ import { useSelect, useDispatch } from '@wordpress/data';
6
+ import { __ } from '@wordpress/i18n';
7
+ import { useState } from '@wordpress/element';
8
+
9
+ /**
10
+ * Internal dependencies
11
+ */
12
+ import { store as blockEditorStore } from '../../store';
13
+ import { useBlockDisplayInformation } from '..';
14
+ import isEmptyString from './is-empty-string';
15
+ import BlockRenameModal from './modal';
16
+
17
+ export default function BlockRenameControl( { clientId } ) {
18
+ const [ renamingBlock, setRenamingBlock ] = useState( false );
19
+
20
+ const { metadata } = useSelect(
21
+ ( select ) => {
22
+ const { getBlockAttributes } = select( blockEditorStore );
23
+
24
+ const _metadata = getBlockAttributes( clientId )?.metadata;
25
+ return {
26
+ metadata: _metadata,
27
+ };
28
+ },
29
+ [ clientId ]
30
+ );
31
+
32
+ const { updateBlockAttributes } = useDispatch( blockEditorStore );
33
+
34
+ const customName = metadata?.name;
35
+
36
+ function onChange( newName ) {
37
+ updateBlockAttributes( [ clientId ], {
38
+ metadata: {
39
+ ...( metadata && metadata ),
40
+ name: newName,
41
+ },
42
+ } );
43
+ }
44
+
45
+ const blockInformation = useBlockDisplayInformation( clientId );
46
+
47
+ return (
48
+ <>
49
+ <MenuItem
50
+ onClick={ () => {
51
+ setRenamingBlock( true );
52
+ } }
53
+ aria-expanded={ renamingBlock }
54
+ aria-haspopup="dialog"
55
+ >
56
+ { __( 'Rename' ) }
57
+ </MenuItem>
58
+ { renamingBlock && (
59
+ <BlockRenameModal
60
+ blockName={ customName || '' }
61
+ originalBlockName={ blockInformation?.title }
62
+ onClose={ () => setRenamingBlock( false ) }
63
+ onSave={ ( newName ) => {
64
+ // If the new value is the block's original name (e.g. `Group`)
65
+ // or it is an empty string then assume the intent is to reset
66
+ // the value. Therefore reset the metadata.
67
+ if (
68
+ newName === blockInformation?.title ||
69
+ isEmptyString( newName )
70
+ ) {
71
+ newName = undefined;
72
+ }
73
+
74
+ onChange( newName );
75
+ } }
76
+ />
77
+ ) }
78
+ </>
79
+ );
80
+ }
@@ -0,0 +1,10 @@
1
+ /**
2
+ * WordPress dependencies
3
+ */
4
+ import { getBlockSupport } from '@wordpress/blocks';
5
+
6
+ export default function useBlockRename( name ) {
7
+ return {
8
+ canRename: getBlockSupport( name, 'renaming', true ),
9
+ };
10
+ }
@@ -20,7 +20,7 @@ import {
20
20
  store as keyboardShortcutsStore,
21
21
  __unstableUseShortcutEventMatch,
22
22
  } from '@wordpress/keyboard-shortcuts';
23
- import { pipe, useCopyToClipboard } from '@wordpress/compose';
23
+ import { pipe, useCopyToClipboard, useViewportMatch } from '@wordpress/compose';
24
24
 
25
25
  /**
26
26
  * Internal dependencies
@@ -47,6 +47,38 @@ function CopyMenuItem( { blocks, onCopy, label } ) {
47
47
  return <MenuItem ref={ ref }>{ copyMenuItemLabel }</MenuItem>;
48
48
  }
49
49
 
50
+ function ParentSelectorMenuItem( { parentClientId, parentBlockType } ) {
51
+ const isSmallViewport = useViewportMatch( 'medium', '<' );
52
+ const { selectBlock } = useDispatch( blockEditorStore );
53
+
54
+ // Allows highlighting the parent block outline when focusing or hovering
55
+ // the parent block selector within the child.
56
+ const menuItemRef = useRef();
57
+ const gesturesProps = useShowHoveredOrFocusedGestures( {
58
+ ref: menuItemRef,
59
+ highlightParent: true,
60
+ } );
61
+
62
+ if ( ! isSmallViewport ) {
63
+ return null;
64
+ }
65
+
66
+ return (
67
+ <MenuItem
68
+ { ...gesturesProps }
69
+ ref={ menuItemRef }
70
+ icon={ <BlockIcon icon={ parentBlockType.icon } /> }
71
+ onClick={ () => selectBlock( parentClientId ) }
72
+ >
73
+ { sprintf(
74
+ /* translators: %s: Name of the block's parent. */
75
+ __( 'Select parent block (%s)' ),
76
+ parentBlockType.title
77
+ ) }
78
+ </MenuItem>
79
+ );
80
+ }
81
+
50
82
  export function BlockSettingsDropdown( {
51
83
  block,
52
84
  clientIds,
@@ -132,8 +164,6 @@ export function BlockSettingsDropdown( {
132
164
  };
133
165
  }, [] );
134
166
  const isMatch = __unstableUseShortcutEventMatch();
135
-
136
- const { selectBlock } = useDispatch( blockEditorStore );
137
167
  const hasSelectedBlocks = selectedBlockClientIds.length > 0;
138
168
 
139
169
  const updateSelectionAfterDuplicate = useCallback(
@@ -175,14 +205,6 @@ export function BlockSettingsDropdown( {
175
205
  const removeBlockLabel =
176
206
  count === 1 ? __( 'Delete' ) : __( 'Delete blocks' );
177
207
 
178
- // Allows highlighting the parent block outline when focusing or hovering
179
- // the parent block selector within the child.
180
- const selectParentButtonRef = useRef();
181
- const showParentOutlineGestures = useShowHoveredOrFocusedGestures( {
182
- ref: selectParentButtonRef,
183
- highlightParent: true,
184
- } );
185
-
186
208
  // This can occur when the selected block (the parent)
187
209
  // displays child blocks within a List View.
188
210
  const parentBlockIsSelected =
@@ -297,30 +319,12 @@ export function BlockSettingsDropdown( {
297
319
  />
298
320
  { ! parentBlockIsSelected &&
299
321
  !! firstParentClientId && (
300
- <MenuItem
301
- { ...showParentOutlineGestures }
302
- ref={ selectParentButtonRef }
303
- icon={
304
- <BlockIcon
305
- icon={
306
- parentBlockType.icon
307
- }
308
- />
309
- }
310
- onClick={ () =>
311
- selectBlock(
312
- firstParentClientId
313
- )
322
+ <ParentSelectorMenuItem
323
+ parentClientId={
324
+ firstParentClientId
314
325
  }
315
- >
316
- { sprintf(
317
- /* translators: %s: Name of the block's parent. */
318
- __(
319
- 'Select parent block (%s)'
320
- ),
321
- parentBlockType.title
322
- ) }
323
- </MenuItem>
326
+ parentBlockType={ parentBlockType }
327
+ />
324
328
  ) }
325
329
  { count === 1 && (
326
330
  <BlockHTMLConvertButton
@@ -22,6 +22,8 @@ import { BlockLockMenuItem, useBlockLock } from '../block-lock';
22
22
  import { store as blockEditorStore } from '../../store';
23
23
  import BlockModeToggle from '../block-settings-menu/block-mode-toggle';
24
24
 
25
+ import { BlockRenameControl, useBlockRename } from '../block-rename';
26
+
25
27
  const { Fill, Slot } = createSlotFill( 'BlockSettingsMenuControls' );
26
28
 
27
29
  const BlockSettingsMenuControlsSlot = ( {
@@ -44,7 +46,9 @@ const BlockSettingsMenuControlsSlot = ( {
44
46
  );
45
47
 
46
48
  const { canLock } = useBlockLock( selectedClientIds[ 0 ] );
49
+ const { canRename } = useBlockRename( selectedBlocks[ 0 ] );
47
50
  const showLockButton = selectedClientIds.length === 1 && canLock;
51
+ const showRenameButton = selectedClientIds.length === 1 && canRename;
48
52
 
49
53
  // Check if current selection of blocks is Groupable or Ungroupable
50
54
  // and pass this props down to ConvertToGroupButton.
@@ -84,6 +88,11 @@ const BlockSettingsMenuControlsSlot = ( {
84
88
  clientId={ selectedClientIds[ 0 ] }
85
89
  />
86
90
  ) }
91
+ { showRenameButton && (
92
+ <BlockRenameControl
93
+ clientId={ selectedClientIds[ 0 ] }
94
+ />
95
+ ) }
87
96
  { fills }
88
97
  { fillProps?.canMove && ! fillProps?.onlyBlock && (
89
98
  <MenuItem
@@ -212,10 +212,7 @@ const BlockActionsMenu = ( {
212
212
  },
213
213
  convertToRegularBlocks: {
214
214
  id: 'convertToRegularBlocksOption',
215
- label:
216
- innerBlockCount > 1
217
- ? __( 'Detach patterns' )
218
- : __( 'Detach pattern' ),
215
+ label: __( 'Detach' ),
219
216
  value: 'convertToRegularBlocksOption',
220
217
  onSelect: () => {
221
218
  /* translators: %s: name of the synced block */
@@ -2,6 +2,7 @@
2
2
  * WordPress dependencies
3
3
  */
4
4
  import { getBlockMenuDefaultClassName } from '@wordpress/blocks';
5
+ import { useInstanceId } from '@wordpress/compose';
5
6
 
6
7
  /**
7
8
  * Internal dependencies
@@ -25,11 +26,10 @@ function BlockTypesList( {
25
26
  label,
26
27
  isDraggable = true,
27
28
  } ) {
29
+ const className = 'block-editor-block-types-list';
30
+ const listId = useInstanceId( BlockTypesList, className );
28
31
  return (
29
- <InserterListboxGroup
30
- className="block-editor-block-types-list"
31
- aria-label={ label }
32
- >
32
+ <InserterListboxGroup className={ className } aria-label={ label }>
33
33
  { chunk( items, 3 ).map( ( row, i ) => (
34
34
  <InserterListboxRow key={ i }>
35
35
  { row.map( ( item, j ) => (
@@ -43,6 +43,7 @@ function BlockTypesList( {
43
43
  onHover={ onHover }
44
44
  isDraggable={ isDraggable && ! item.isDisabled }
45
45
  isFirst={ i === 0 && j === 0 }
46
+ rowId={ `${ listId }-${ i }` }
46
47
  />
47
48
  ) ) }
48
49
  </InserterListboxRow>
@@ -39,8 +39,8 @@
39
39
  .is-layout-constrained.block-editor-block-list__block:not(.is-selected) > &,
40
40
  .is-layout-flow.block-editor-block-list__block:not(.is-selected) > &,
41
41
  // Legacy groups have an inner container so need to be targeted separately
42
- .is-layout-constrained.block-editor-block-list__block:not(.is-selected) > .wp-block-group__inner-container > &,
43
- .is-layout-flow.block-editor-block-list__block:not(.is-selected) > .wp-block-group__inner-container > & {
42
+ .block-editor-block-list__block:not(.is-selected) > .is-layout-constrained.wp-block-group__inner-container > &,
43
+ .block-editor-block-list__block:not(.is-selected) > .is-layout-flow.wp-block-group__inner-container > & {
44
44
  pointer-events: none;
45
45
 
46
46
  &::after {
@@ -78,12 +78,19 @@ function NonDefaultControls( { format, onChange } ) {
78
78
  // formats.
79
79
  const suggestedFormats = [
80
80
  ...new Set( [
81
+ /* translators: See https://www.php.net/manual/datetime.format.php */
81
82
  'Y-m-d',
83
+ /* translators: See https://www.php.net/manual/datetime.format.php */
82
84
  _x( 'n/j/Y', 'short date format' ),
85
+ /* translators: See https://www.php.net/manual/datetime.format.php */
83
86
  _x( 'n/j/Y g:i A', 'short date format with time' ),
87
+ /* translators: See https://www.php.net/manual/datetime.format.php */
84
88
  _x( 'M j, Y', 'medium date format' ),
89
+ /* translators: See https://www.php.net/manual/datetime.format.php */
85
90
  _x( 'M j, Y g:i A', 'medium date format with time' ),
91
+ /* translators: See https://www.php.net/manual/datetime.format.php */
86
92
  _x( 'F j, Y', 'long date format' ),
93
+ /* translators: See https://www.php.net/manual/datetime.format.php */
87
94
  _x( 'M j', 'short date format without the year' ),
88
95
  ] ),
89
96
  ];
@@ -47,40 +47,6 @@ _Optional._ Called when the block can be removed. `forward` is true when the sel
47
47
 
48
48
  ## Example
49
49
 
50
- {% codetabs %}
51
- {% ES5 %}
52
-
53
- ```js
54
- wp.blocks.registerBlockType( /* ... */, {
55
- // ...
56
-
57
- attributes: {
58
- content: {
59
- source: 'html',
60
- selector: 'div',
61
- },
62
- },
63
-
64
- edit: function( props ) {
65
- return React.createElement( wp.editor.EditableText, {
66
- className: props.className,
67
- value: props.attributes.content,
68
- onChange: function( content ) {
69
- props.setAttributes( { content: content } );
70
- }
71
- } );
72
- },
73
-
74
- save: function( props ) {
75
- return React.createElement( wp.editor.EditableText.Content, {
76
- value: props.attributes.content
77
- } );
78
- }
79
- } );
80
- ```
81
-
82
- {% ESNext %}
83
-
84
50
  ```js
85
51
  const { registerBlockType } = wp.blocks;
86
52
  const { EditableText } = wp.editor;
@@ -110,5 +76,3 @@ registerBlockType( /* ... */, {
110
76
  }
111
77
  } );
112
78
  ```
113
-
114
- {% end %}
@@ -30,7 +30,7 @@ export default function AdvancedPanel( {
30
30
  } );
31
31
  if ( cssError ) {
32
32
  const [ transformed ] = transformStyles(
33
- [ { css: value } ],
33
+ [ { css: newValue } ],
34
34
  '.editor-styles-wrapper'
35
35
  );
36
36
  if ( transformed ) {