@wordpress/block-editor 8.0.11 → 8.0.12-next.33ec3857e2.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 (278) hide show
  1. package/README.md +4 -0
  2. package/build/components/block-caption/index.native.js +14 -3
  3. package/build/components/block-caption/index.native.js.map +1 -1
  4. package/build/components/block-inspector/index.js +12 -23
  5. package/build/components/block-inspector/index.js.map +1 -1
  6. package/build/components/block-list-appender/index.js +3 -11
  7. package/build/components/block-list-appender/index.js.map +1 -1
  8. package/build/components/block-preview/auto.js +10 -2
  9. package/build/components/block-preview/auto.js.map +1 -1
  10. package/build/components/block-preview/index.js +51 -0
  11. package/build/components/block-preview/index.js.map +1 -1
  12. package/build/components/block-settings/container.native.js +2 -1
  13. package/build/components/block-settings/container.native.js.map +1 -1
  14. package/build/components/block-styles/index.js +110 -134
  15. package/build/components/block-styles/index.js.map +1 -1
  16. package/build/components/block-styles/menu-items.js +63 -0
  17. package/build/components/block-styles/menu-items.js.map +1 -0
  18. package/build/components/block-styles/preview-panel.js +45 -0
  19. package/build/components/block-styles/preview-panel.js.map +1 -0
  20. package/build/components/block-styles/use-styles-for-block.js +119 -0
  21. package/build/components/block-styles/use-styles-for-block.js.map +1 -0
  22. package/build/components/block-styles/utils.js +39 -0
  23. package/build/components/block-styles/utils.js.map +1 -1
  24. package/build/components/block-switcher/block-styles-menu.js +3 -23
  25. package/build/components/block-switcher/block-styles-menu.js.map +1 -1
  26. package/build/components/block-tools/back-compat.js +2 -1
  27. package/build/components/block-tools/back-compat.js.map +1 -1
  28. package/build/components/block-tools/insertion-point.js +11 -1
  29. package/build/components/block-tools/insertion-point.js.map +1 -1
  30. package/build/components/button-block-appender/index.js +2 -1
  31. package/build/components/button-block-appender/index.js.map +1 -1
  32. package/build/components/colors-gradients/panel-color-gradient-settings.js +51 -10
  33. package/build/components/colors-gradients/panel-color-gradient-settings.js.map +1 -1
  34. package/build/components/default-block-appender/index.js +16 -19
  35. package/build/components/default-block-appender/index.js.map +1 -1
  36. package/build/components/default-style-picker/index.js +18 -3
  37. package/build/components/default-style-picker/index.js.map +1 -1
  38. package/build/components/iframe/index.js +3 -4
  39. package/build/components/iframe/index.js.map +1 -1
  40. package/build/components/index.js +17 -10
  41. package/build/components/index.js.map +1 -1
  42. package/build/components/inner-blocks/default-block-appender.js +2 -4
  43. package/build/components/inner-blocks/default-block-appender.js.map +1 -1
  44. package/build/components/inserter/index.native.js +1 -1
  45. package/build/components/inserter/index.native.js.map +1 -1
  46. package/build/components/inserter/tabs.native.js +7 -4
  47. package/build/components/inserter/tabs.native.js.map +1 -1
  48. package/build/components/inspector-controls/block-support-slot-container.js +2 -1
  49. package/build/components/inspector-controls/block-support-slot-container.js.map +1 -1
  50. package/build/components/inspector-controls/fill.native.js +3 -5
  51. package/build/components/inspector-controls/fill.native.js.map +1 -1
  52. package/build/components/inspector-controls/groups.js +2 -0
  53. package/build/components/inspector-controls/groups.js.map +1 -1
  54. package/build/components/inspector-controls/slot.js +1 -3
  55. package/build/components/inspector-controls/slot.js.map +1 -1
  56. package/build/components/letter-spacing-control/index.js +6 -6
  57. package/build/components/letter-spacing-control/index.js.map +1 -1
  58. package/build/components/list-view/block-select-button.js +23 -3
  59. package/build/components/list-view/block-select-button.js.map +1 -1
  60. package/build/components/media-placeholder/index.js +2 -0
  61. package/build/components/media-placeholder/index.js.map +1 -1
  62. package/build/components/media-replace-flow/index.js +2 -0
  63. package/build/components/media-replace-flow/index.js.map +1 -1
  64. package/build/components/rich-text/file-paste-handler.js +1 -1
  65. package/build/components/rich-text/file-paste-handler.js.map +1 -1
  66. package/build/components/rich-text/prevent-event-discovery.js +33 -0
  67. package/build/components/rich-text/prevent-event-discovery.js.map +1 -0
  68. package/build/components/rich-text/use-input-rules.js +3 -1
  69. package/build/components/rich-text/use-input-rules.js.map +1 -1
  70. package/build/components/selection-scroll-into-view/index.js +2 -1
  71. package/build/components/selection-scroll-into-view/index.js.map +1 -1
  72. package/build/components/use-display-block-controls/index.native.js +45 -0
  73. package/build/components/use-display-block-controls/index.native.js.map +1 -0
  74. package/build/components/use-on-block-drop/index.js +7 -3
  75. package/build/components/use-on-block-drop/index.js.map +1 -1
  76. package/build/components/writing-flow/use-multi-selection.js +3 -1
  77. package/build/components/writing-flow/use-multi-selection.js.map +1 -1
  78. package/build/hooks/border-color.js +63 -5
  79. package/build/hooks/border-color.js.map +1 -1
  80. package/build/hooks/border-radius.js +47 -0
  81. package/build/hooks/border-radius.js.map +1 -1
  82. package/build/hooks/border-style.js +41 -0
  83. package/build/hooks/border-style.js.map +1 -1
  84. package/build/hooks/border-width.js +70 -31
  85. package/build/hooks/border-width.js.map +1 -1
  86. package/build/hooks/border.js +81 -11
  87. package/build/hooks/border.js.map +1 -1
  88. package/build/hooks/letter-spacing.js +1 -1
  89. package/build/hooks/letter-spacing.js.map +1 -1
  90. package/build/hooks/typography.js +1 -1
  91. package/build/hooks/typography.js.map +1 -1
  92. package/build/store/actions.js +1 -2
  93. package/build/store/actions.js.map +1 -1
  94. package/build/store/defaults.js +5 -1
  95. package/build/store/defaults.js.map +1 -1
  96. package/build/store/selectors.js +25 -7
  97. package/build/store/selectors.js.map +1 -1
  98. package/build/utils/get-paste-event-data.js +1 -1
  99. package/build/utils/get-paste-event-data.js.map +1 -1
  100. package/build/utils/parse-css-unit-to-px.js +1 -1
  101. package/build/utils/parse-css-unit-to-px.js.map +1 -1
  102. package/build-module/components/block-caption/index.native.js +13 -3
  103. package/build-module/components/block-caption/index.native.js.map +1 -1
  104. package/build-module/components/block-inspector/index.js +12 -23
  105. package/build-module/components/block-inspector/index.js.map +1 -1
  106. package/build-module/components/block-list-appender/index.js +3 -10
  107. package/build-module/components/block-list-appender/index.js.map +1 -1
  108. package/build-module/components/block-preview/auto.js +10 -2
  109. package/build-module/components/block-preview/auto.js.map +1 -1
  110. package/build-module/components/block-preview/index.js +46 -0
  111. package/build-module/components/block-preview/index.js.map +1 -1
  112. package/build-module/components/block-settings/container.native.js +2 -1
  113. package/build-module/components/block-settings/container.native.js.map +1 -1
  114. package/build-module/components/block-styles/index.js +112 -133
  115. package/build-module/components/block-styles/index.js.map +1 -1
  116. package/build-module/components/block-styles/menu-items.js +50 -0
  117. package/build-module/components/block-styles/menu-items.js.map +1 -0
  118. package/build-module/components/block-styles/preview-panel.js +35 -0
  119. package/build-module/components/block-styles/preview-panel.js.map +1 -0
  120. package/build-module/components/block-styles/use-styles-for-block.js +107 -0
  121. package/build-module/components/block-styles/use-styles-for-block.js.map +1 -0
  122. package/build-module/components/block-styles/utils.js +34 -0
  123. package/build-module/components/block-styles/utils.js.map +1 -1
  124. package/build-module/components/block-switcher/block-styles-menu.js +3 -21
  125. package/build-module/components/block-switcher/block-styles-menu.js.map +1 -1
  126. package/build-module/components/block-tools/back-compat.js +2 -1
  127. package/build-module/components/block-tools/back-compat.js.map +1 -1
  128. package/build-module/components/block-tools/insertion-point.js +11 -1
  129. package/build-module/components/block-tools/insertion-point.js.map +1 -1
  130. package/build-module/components/button-block-appender/index.js +2 -1
  131. package/build-module/components/button-block-appender/index.js.map +1 -1
  132. package/build-module/components/colors-gradients/panel-color-gradient-settings.js +54 -13
  133. package/build-module/components/colors-gradients/panel-color-gradient-settings.js.map +1 -1
  134. package/build-module/components/default-block-appender/index.js +15 -18
  135. package/build-module/components/default-block-appender/index.js.map +1 -1
  136. package/build-module/components/default-style-picker/index.js +17 -3
  137. package/build-module/components/default-style-picker/index.js.map +1 -1
  138. package/build-module/components/iframe/index.js +3 -4
  139. package/build-module/components/iframe/index.js.map +1 -1
  140. package/build-module/components/index.js +2 -2
  141. package/build-module/components/index.js.map +1 -1
  142. package/build-module/components/inner-blocks/default-block-appender.js +2 -4
  143. package/build-module/components/inner-blocks/default-block-appender.js.map +1 -1
  144. package/build-module/components/inserter/index.native.js +2 -2
  145. package/build-module/components/inserter/index.native.js.map +1 -1
  146. package/build-module/components/inserter/tabs.native.js +7 -4
  147. package/build-module/components/inserter/tabs.native.js.map +1 -1
  148. package/build-module/components/inspector-controls/block-support-slot-container.js +2 -1
  149. package/build-module/components/inspector-controls/block-support-slot-container.js.map +1 -1
  150. package/build-module/components/inspector-controls/fill.native.js +3 -5
  151. package/build-module/components/inspector-controls/fill.native.js.map +1 -1
  152. package/build-module/components/inspector-controls/groups.js +2 -0
  153. package/build-module/components/inspector-controls/groups.js.map +1 -1
  154. package/build-module/components/inspector-controls/slot.js +1 -3
  155. package/build-module/components/inspector-controls/slot.js.map +1 -1
  156. package/build-module/components/letter-spacing-control/index.js +6 -6
  157. package/build-module/components/letter-spacing-control/index.js.map +1 -1
  158. package/build-module/components/list-view/block-select-button.js +22 -3
  159. package/build-module/components/list-view/block-select-button.js.map +1 -1
  160. package/build-module/components/media-placeholder/index.js +2 -0
  161. package/build-module/components/media-placeholder/index.js.map +1 -1
  162. package/build-module/components/media-replace-flow/index.js +2 -0
  163. package/build-module/components/media-replace-flow/index.js.map +1 -1
  164. package/build-module/components/rich-text/file-paste-handler.js +1 -1
  165. package/build-module/components/rich-text/file-paste-handler.js.map +1 -1
  166. package/build-module/components/rich-text/prevent-event-discovery.js +25 -0
  167. package/build-module/components/rich-text/prevent-event-discovery.js.map +1 -0
  168. package/build-module/components/rich-text/use-input-rules.js +2 -1
  169. package/build-module/components/rich-text/use-input-rules.js.map +1 -1
  170. package/build-module/components/selection-scroll-into-view/index.js +2 -1
  171. package/build-module/components/selection-scroll-into-view/index.js.map +1 -1
  172. package/build-module/components/use-display-block-controls/index.native.js +34 -0
  173. package/build-module/components/use-display-block-controls/index.native.js.map +1 -0
  174. package/build-module/components/use-on-block-drop/index.js +7 -3
  175. package/build-module/components/use-on-block-drop/index.js.map +1 -1
  176. package/build-module/components/writing-flow/use-multi-selection.js +3 -4
  177. package/build-module/components/writing-flow/use-multi-selection.js.map +1 -1
  178. package/build-module/hooks/border-color.js +61 -7
  179. package/build-module/hooks/border-color.js.map +1 -1
  180. package/build-module/hooks/border-radius.js +42 -0
  181. package/build-module/hooks/border-radius.js.map +1 -1
  182. package/build-module/hooks/border-style.js +36 -0
  183. package/build-module/hooks/border-style.js.map +1 -1
  184. package/build-module/hooks/border-width.js +66 -32
  185. package/build-module/hooks/border-width.js.map +1 -1
  186. package/build-module/hooks/border.js +80 -12
  187. package/build-module/hooks/border.js.map +1 -1
  188. package/build-module/hooks/letter-spacing.js +1 -1
  189. package/build-module/hooks/letter-spacing.js.map +1 -1
  190. package/build-module/hooks/typography.js +1 -1
  191. package/build-module/hooks/typography.js.map +1 -1
  192. package/build-module/store/actions.js +1 -2
  193. package/build-module/store/actions.js.map +1 -1
  194. package/build-module/store/defaults.js +5 -1
  195. package/build-module/store/defaults.js.map +1 -1
  196. package/build-module/store/selectors.js +24 -7
  197. package/build-module/store/selectors.js.map +1 -1
  198. package/build-module/utils/get-paste-event-data.js +1 -1
  199. package/build-module/utils/get-paste-event-data.js.map +1 -1
  200. package/build-module/utils/parse-css-unit-to-px.js +1 -1
  201. package/build-module/utils/parse-css-unit-to-px.js.map +1 -1
  202. package/build-style/style-rtl.css +226 -180
  203. package/build-style/style.css +226 -180
  204. package/package.json +27 -27
  205. package/src/components/block-caption/index.native.js +22 -4
  206. package/src/components/block-inspector/index.js +14 -17
  207. package/src/components/block-list-appender/index.js +5 -21
  208. package/src/components/block-preview/auto.js +7 -2
  209. package/src/components/block-preview/index.js +60 -0
  210. package/src/components/block-preview/style.scss +23 -0
  211. package/src/components/block-preview/test/index.js +114 -0
  212. package/src/components/block-settings/container.native.js +1 -0
  213. package/src/components/block-styles/index.js +125 -145
  214. package/src/components/block-styles/menu-items.js +49 -0
  215. package/src/components/block-styles/preview-panel.js +36 -0
  216. package/src/components/block-styles/style.scss +59 -51
  217. package/src/components/block-styles/test/{index.js → utils.js} +60 -1
  218. package/src/components/block-styles/use-styles-for-block.js +99 -0
  219. package/src/components/block-styles/utils.js +39 -0
  220. package/src/components/block-switcher/block-styles-menu.js +3 -38
  221. package/src/components/block-tools/back-compat.js +1 -0
  222. package/src/components/block-tools/insertion-point.js +10 -1
  223. package/src/components/border-style-control/style.scss +0 -1
  224. package/src/components/button-block-appender/index.js +1 -0
  225. package/src/components/colors-gradients/panel-color-gradient-settings.js +75 -19
  226. package/src/components/colors-gradients/style.scss +42 -5
  227. package/src/components/default-block-appender/index.js +17 -24
  228. package/src/components/default-block-appender/style.scss +4 -0
  229. package/src/components/default-block-appender/test/__snapshots__/index.js.snap +12 -24
  230. package/src/components/default-block-appender/test/index.js +4 -14
  231. package/src/components/default-style-picker/index.js +18 -6
  232. package/src/components/iframe/index.js +6 -3
  233. package/src/components/index.js +5 -2
  234. package/src/components/inner-blocks/README.md +2 -0
  235. package/src/components/inner-blocks/default-block-appender.js +2 -7
  236. package/src/components/inserter/index.native.js +2 -2
  237. package/src/components/inserter/tabs.native.js +5 -4
  238. package/src/components/inspector-controls/block-support-slot-container.js +3 -1
  239. package/src/components/inspector-controls/fill.native.js +4 -3
  240. package/src/components/inspector-controls/groups.js +2 -0
  241. package/src/components/inspector-controls/slot.js +2 -7
  242. package/src/components/letter-spacing-control/index.js +6 -6
  243. package/src/components/link-control/README.md +1 -1
  244. package/src/components/link-control/test/index.js +2 -0
  245. package/src/components/list-view/block-select-button.js +20 -1
  246. package/src/components/media-placeholder/index.js +2 -0
  247. package/src/components/media-replace-flow/index.js +2 -0
  248. package/src/components/rich-text/file-paste-handler.js +3 -1
  249. package/src/components/rich-text/prevent-event-discovery.js +23 -0
  250. package/src/components/rich-text/use-input-rules.js +2 -1
  251. package/src/components/selection-scroll-into-view/index.js +1 -0
  252. package/src/components/url-input/README.md +5 -0
  253. package/src/components/use-display-block-controls/index.native.js +38 -0
  254. package/src/components/use-on-block-drop/index.js +7 -3
  255. package/src/components/writing-flow/test/use-multi-selection.js +36 -0
  256. package/src/components/writing-flow/use-multi-selection.js +12 -9
  257. package/src/hooks/border-color.js +55 -3
  258. package/src/hooks/border-radius.js +32 -0
  259. package/src/hooks/border-style.js +26 -0
  260. package/src/hooks/border-width.js +56 -32
  261. package/src/hooks/border.js +115 -20
  262. package/src/hooks/border.scss +3 -17
  263. package/src/hooks/dimensions.scss +5 -0
  264. package/src/hooks/letter-spacing.js +1 -1
  265. package/src/hooks/typography.js +1 -1
  266. package/src/store/actions.js +1 -2
  267. package/src/store/defaults.js +2 -0
  268. package/src/store/selectors.js +37 -7
  269. package/src/style.scss +4 -3
  270. package/src/utils/get-paste-event-data.js +1 -1
  271. package/src/utils/parse-css-unit-to-px.js +1 -1
  272. package/src/utils/test/parse-css-unit-to-px.js +1 -0
  273. package/tsconfig.tsbuildinfo +1 -1
  274. package/build/components/use-canvas-click-redirect/index.js +0 -66
  275. package/build/components/use-canvas-click-redirect/index.js.map +0 -1
  276. package/build-module/components/use-canvas-click-redirect/index.js +0 -54
  277. package/build-module/components/use-canvas-click-redirect/index.js.map +0 -1
  278. package/src/components/use-canvas-click-redirect/index.js +0 -57
@@ -1,7 +1,6 @@
1
1
  /**
2
2
  * External dependencies
3
3
  */
4
- import { last } from 'lodash';
5
4
  import classnames from 'classnames';
6
5
 
7
6
  /**
@@ -18,7 +17,6 @@ import ButtonBlockAppender from '../button-block-appender';
18
17
  import { store as blockEditorStore } from '../../store';
19
18
 
20
19
  function BlockListAppender( {
21
- blockClientIds,
22
20
  rootClientId,
23
21
  canInsertDefaultBlock,
24
22
  isLocked,
@@ -36,30 +34,18 @@ function BlockListAppender( {
36
34
  // Prefer custom render prop if provided.
37
35
  appender = <CustomAppender />;
38
36
  } else {
39
- const isDocumentAppender = ! rootClientId;
40
- const isParentSelected = selectedBlockClientId === rootClientId;
41
- const isAnotherDefaultAppenderAlreadyDisplayed =
42
- selectedBlockClientId &&
43
- ! blockClientIds.includes( selectedBlockClientId );
37
+ const isParentSelected =
38
+ selectedBlockClientId === rootClientId ||
39
+ ( ! rootClientId && ! selectedBlockClientId );
44
40
 
45
- if (
46
- ! isDocumentAppender &&
47
- ! isParentSelected &&
48
- ( ! selectedBlockClientId ||
49
- isAnotherDefaultAppenderAlreadyDisplayed )
50
- ) {
41
+ if ( ! isParentSelected ) {
51
42
  return null;
52
43
  }
53
44
 
54
45
  if ( canInsertDefaultBlock ) {
55
46
  // Render the default block appender when renderAppender has not been
56
47
  // provided and the context supports use of the default appender.
57
- appender = (
58
- <DefaultBlockAppender
59
- rootClientId={ rootClientId }
60
- lastBlockClientId={ last( blockClientIds ) }
61
- />
62
- );
48
+ appender = <DefaultBlockAppender rootClientId={ rootClientId } />;
63
49
  } else {
64
50
  // Fallback in the case no renderAppender has been provided and the
65
51
  // default block can't be inserted.
@@ -103,7 +89,6 @@ function BlockListAppender( {
103
89
 
104
90
  export default withSelect( ( select, { rootClientId } ) => {
105
91
  const {
106
- getBlockOrder,
107
92
  canInsertBlockType,
108
93
  getTemplateLock,
109
94
  getSelectedBlockClientId,
@@ -111,7 +96,6 @@ export default withSelect( ( select, { rootClientId } ) => {
111
96
 
112
97
  return {
113
98
  isLocked: !! getTemplateLock( rootClientId ),
114
- blockClientIds: getBlockOrder( rootClientId ),
115
99
  canInsertDefaultBlock: canInsertBlockType(
116
100
  getDefaultBlockName(),
117
101
  rootClientId
@@ -25,8 +25,12 @@ function AutoBlockPreview( { viewportWidth, __experimentalPadding } ) {
25
25
  contentResizeListener,
26
26
  { height: contentHeight },
27
27
  ] = useResizeObserver();
28
- const styles = useSelect( ( select ) => {
29
- return select( store ).getSettings().styles;
28
+ const { styles, assets } = useSelect( ( select ) => {
29
+ const settings = select( store ).getSettings();
30
+ return {
31
+ styles: settings.styles,
32
+ assets: settings.__unstableResolvedAssets,
33
+ };
30
34
  }, [] );
31
35
 
32
36
  // Initialize on render instead of module top level, to avoid circular dependency issues.
@@ -46,6 +50,7 @@ function AutoBlockPreview( { viewportWidth, __experimentalPadding } ) {
46
50
  >
47
51
  <Iframe
48
52
  head={ <EditorStyles styles={ styles } /> }
53
+ assets={ assets }
49
54
  contentRef={ useRefEffect( ( bodyElement ) => {
50
55
  const {
51
56
  ownerDocument: { documentElement },
@@ -2,10 +2,15 @@
2
2
  * External dependencies
3
3
  */
4
4
  import { castArray } from 'lodash';
5
+ import classnames from 'classnames';
5
6
 
6
7
  /**
7
8
  * WordPress dependencies
8
9
  */
10
+ import {
11
+ __experimentalUseDisabled as useDisabled,
12
+ useMergeRefs,
13
+ } from '@wordpress/compose';
9
14
  import { useSelect } from '@wordpress/data';
10
15
  import { memo, useMemo } from '@wordpress/element';
11
16
 
@@ -16,6 +21,7 @@ import BlockEditorProvider from '../provider';
16
21
  import LiveBlockPreview from './live';
17
22
  import AutoHeightBlockPreview from './auto';
18
23
  import { store as blockEditorStore } from '../../store';
24
+ import { BlockListItems } from '../block-list';
19
25
 
20
26
  export function BlockPreview( {
21
27
  blocks,
@@ -63,3 +69,57 @@ export function BlockPreview( {
63
69
  * @return {WPComponent} The component to be rendered.
64
70
  */
65
71
  export default memo( BlockPreview );
72
+
73
+ /**
74
+ * This hook is used to lightly mark an element as a block preview wrapper
75
+ * element. Call this hook and pass the returned props to the element to mark as
76
+ * a block preview wrapper, automatically rendering inner blocks as children. If
77
+ * you define a ref for the element, it is important to pass the ref to this
78
+ * hook, which the hook in turn will pass to the component through the props it
79
+ * returns. Optionally, you can also pass any other props through this hook, and
80
+ * they will be merged and returned.
81
+ *
82
+ * @param {Object} options Preview options.
83
+ * @param {WPBlock[]} options.blocks Block objects.
84
+ * @param {Object} options.props Optional. Props to pass to the element. Must contain
85
+ * the ref if one is defined.
86
+ * @param {Object} options.__experimentalLayout Layout settings to be used in the preview.
87
+ *
88
+ */
89
+ export function useBlockPreview( {
90
+ blocks,
91
+ props = {},
92
+ __experimentalLayout,
93
+ } ) {
94
+ const originalSettings = useSelect(
95
+ ( select ) => select( blockEditorStore ).getSettings(),
96
+ []
97
+ );
98
+ const disabledRef = useDisabled();
99
+ const ref = useMergeRefs( [ props.ref, disabledRef ] );
100
+ const settings = useMemo(
101
+ () => ( { ...originalSettings, __experimentalBlockPatterns: [] } ),
102
+ [ originalSettings ]
103
+ );
104
+ const renderedBlocks = useMemo( () => castArray( blocks ), [ blocks ] );
105
+
106
+ const children = (
107
+ <BlockEditorProvider value={ renderedBlocks } settings={ settings }>
108
+ <BlockListItems
109
+ renderAppender={ false }
110
+ __experimentalLayout={ __experimentalLayout }
111
+ />
112
+ </BlockEditorProvider>
113
+ );
114
+
115
+ return {
116
+ ...props,
117
+ ref,
118
+ className: classnames(
119
+ props.className,
120
+ 'block-editor-block-preview__live-content',
121
+ 'components-disabled'
122
+ ),
123
+ children: blocks?.length ? children : null,
124
+ };
125
+ }
@@ -41,3 +41,26 @@
41
41
  .block-editor-block-preview__content-iframe .block-list-appender {
42
42
  display: none;
43
43
  }
44
+
45
+ .block-editor-block-preview__live-content {
46
+ * {
47
+ pointer-events: none;
48
+ }
49
+
50
+ // Hide the block appender, as the block is not editable in this context.
51
+ .block-list-appender {
52
+ display: none;
53
+ }
54
+
55
+ // Revert button disable styles to ensure that button styles render as they will on the
56
+ // front end of the site. For example, this ensures that Social Links icons display correctly.
57
+ .components-button:disabled {
58
+ opacity: initial;
59
+ }
60
+
61
+ // Hide placeholders.
62
+ .components-placeholder,
63
+ .block-editor-block-list__block[data-empty="true"] {
64
+ display: none;
65
+ }
66
+ }
@@ -0,0 +1,114 @@
1
+ /**
2
+ * External dependencies
3
+ */
4
+ import { render, screen, waitFor } from '@testing-library/react';
5
+
6
+ /**
7
+ * WordPress dependencies
8
+ */
9
+ import {
10
+ registerBlockType,
11
+ unregisterBlockType,
12
+ createBlock,
13
+ } from '@wordpress/blocks';
14
+
15
+ /**
16
+ * Internal dependencies
17
+ */
18
+ import { useBlockPreview } from '../';
19
+
20
+ jest.mock( '@wordpress/dom', () => {
21
+ const focus = jest.requireActual( '../../../../../dom/src' ).focus;
22
+
23
+ return {
24
+ focus: {
25
+ ...focus,
26
+ focusable: {
27
+ ...focus.focusable,
28
+ find( context ) {
29
+ // In JSDOM, all elements have zero'd widths and height.
30
+ // This is a metric for focusable's `isVisible`, so find
31
+ // and apply an arbitrary non-zero width.
32
+ Array.from( context.querySelectorAll( '*' ) ).forEach(
33
+ ( element ) => {
34
+ Object.defineProperties( element, {
35
+ offsetWidth: {
36
+ get: () => 1,
37
+ configurable: true,
38
+ },
39
+ } );
40
+ }
41
+ );
42
+
43
+ return focus.focusable.find( ...arguments );
44
+ },
45
+ },
46
+ },
47
+ };
48
+ } );
49
+
50
+ describe( 'useBlockPreview', () => {
51
+ beforeAll( () => {
52
+ registerBlockType( 'core/test-block', {
53
+ save: () => (
54
+ <div>
55
+ Test block save view
56
+ <button>Button</button>
57
+ </div>
58
+ ),
59
+ edit: () => (
60
+ <div>
61
+ Test block edit view
62
+ <button>Button</button>
63
+ </div>
64
+ ),
65
+ category: 'text',
66
+ title: 'test block',
67
+ } );
68
+ } );
69
+
70
+ afterAll( () => {
71
+ unregisterBlockType( 'core/test-block' );
72
+ } );
73
+
74
+ function BlockPreviewComponent( { blocks, className } ) {
75
+ const blockPreviewProps = useBlockPreview( {
76
+ blocks,
77
+ props: { className },
78
+ } );
79
+ return <div { ...blockPreviewProps } />;
80
+ }
81
+
82
+ it( 'will render a block preview with minimal nesting', async () => {
83
+ const blocks = [];
84
+ blocks.push( createBlock( 'core/test-block' ) );
85
+
86
+ const { container } = render(
87
+ <BlockPreviewComponent
88
+ className="test-container-classname"
89
+ blocks={ blocks }
90
+ />
91
+ );
92
+
93
+ // Test block and block contents are rendered.
94
+ const previewedBlock = screen.getByLabelText( 'Block: test block' );
95
+ const previewedBlockContents = screen.getByText(
96
+ 'Test block edit view'
97
+ );
98
+ expect( previewedBlockContents ).toBeInTheDocument();
99
+
100
+ // Test elements within block contents are disabled.
101
+ await waitFor( () => {
102
+ const button = screen.getByText( 'Button' );
103
+ expect( button.hasAttribute( 'disabled' ) ).toBe( true );
104
+ } );
105
+
106
+ // Ensure the block preview class names are merged with the component's class name.
107
+ expect( container.firstChild.className ).toBe(
108
+ 'test-container-classname block-editor-block-preview__live-content components-disabled'
109
+ );
110
+
111
+ // Ensure there is no nesting between the parent component and rendered blocks.
112
+ expect( container.firstChild.firstChild ).toBe( previewedBlock );
113
+ } );
114
+ } );
@@ -43,6 +43,7 @@ function BottomSheetSettings( {
43
43
  hideHeader
44
44
  contentStyle={ styles.content }
45
45
  hasNavigation
46
+ testID="block-settings-modal"
46
47
  { ...props }
47
48
  >
48
49
  <BottomSheet.NavigationContainer animate main>
@@ -1,182 +1,162 @@
1
1
  /**
2
2
  * External dependencies
3
3
  */
4
- import { find, noop } from 'lodash';
4
+ import { noop, debounce } from 'lodash';
5
5
  import classnames from 'classnames';
6
6
 
7
7
  /**
8
8
  * WordPress dependencies
9
9
  */
10
- import { useMemo } from '@wordpress/element';
11
- import { useSelect, useDispatch } from '@wordpress/data';
10
+ import { useState, useLayoutEffect } from '@wordpress/element';
11
+ import { useViewportMatch } from '@wordpress/compose';
12
12
  import { ENTER, SPACE } from '@wordpress/keycodes';
13
- import { _x } from '@wordpress/i18n';
14
13
  import {
15
- getBlockType,
16
- cloneBlock,
17
- getBlockFromExample,
18
- store as blocksStore,
19
- } from '@wordpress/blocks';
14
+ Button,
15
+ __experimentalText as Text,
16
+ Slot,
17
+ Fill,
18
+ } from '@wordpress/components';
20
19
 
21
20
  /**
22
21
  * Internal dependencies
23
22
  */
24
- import { getActiveStyle, replaceActiveStyle } from './utils';
25
- import BlockPreview from '../block-preview';
26
- import { store as blockEditorStore } from '../../store';
23
+ import BlockStylesPreviewPanel from './preview-panel';
24
+ import useStylesForBlocks from './use-styles-for-block';
27
25
 
28
- const EMPTY_OBJECT = {};
29
-
30
- function useGenericPreviewBlock( block, type ) {
31
- return useMemo( () => {
32
- const example = type?.example;
33
- const blockName = type?.name;
34
-
35
- if ( example && blockName ) {
36
- return getBlockFromExample( blockName, {
37
- attributes: example.attributes,
38
- innerBlocks: example.innerBlocks,
39
- } );
40
- }
26
+ function BlockStylesPreviewPanelSlot( { scope } ) {
27
+ return <Slot name={ `BlockStylesPreviewPanel/${ scope }` } />;
28
+ }
41
29
 
42
- if ( block ) {
43
- return cloneBlock( block );
44
- }
45
- }, [ type?.example ? block?.name : block, type ] );
30
+ function BlockStylesPreviewPanelFill( { children, scope, ...props } ) {
31
+ return (
32
+ <Fill name={ `BlockStylesPreviewPanel/${ scope }` }>
33
+ <div { ...props }>{ children }</div>
34
+ </Fill>
35
+ );
46
36
  }
47
37
 
38
+ // Top position (in px) of the Block Styles container
39
+ // relative to the editor pane.
40
+ // The value is the equivalent of the container's right position.
41
+ const DEFAULT_POSITION_TOP = 16;
42
+
43
+ // Block Styles component for the Settings Sidebar.
48
44
  function BlockStyles( {
49
45
  clientId,
50
46
  onSwitch = noop,
51
47
  onHoverClassName = noop,
52
- itemRole,
48
+ scope,
53
49
  } ) {
54
- const selector = ( select ) => {
55
- const { getBlock } = select( blockEditorStore );
56
- const block = getBlock( clientId );
57
-
58
- if ( ! block ) {
59
- return EMPTY_OBJECT;
60
- }
61
-
62
- const blockType = getBlockType( block.name );
63
- const { getBlockStyles } = select( blocksStore );
64
- return {
65
- block,
66
- type: blockType,
67
- styles: getBlockStyles( block.name ),
68
- className: block.attributes.className || '',
69
- };
70
- };
71
-
72
- const { styles, block, type, className } = useSelect( selector, [
50
+ const {
51
+ onSelect,
52
+ stylesToRender,
53
+ activeStyle,
54
+ genericPreviewBlock,
55
+ className: previewClassName,
56
+ } = useStylesForBlocks( {
73
57
  clientId,
74
- ] );
75
-
76
- const { updateBlockAttributes } = useDispatch( blockEditorStore );
77
- const genericPreviewBlock = useGenericPreviewBlock( block, type );
78
-
79
- if ( ! styles || styles.length === 0 ) {
58
+ onSwitch,
59
+ } );
60
+ const [ hoveredStyle, setHoveredStyle ] = useState( null );
61
+ const [ containerScrollTop, setContainerScrollTop ] = useState( 0 );
62
+ const isMobileViewport = useViewportMatch( 'medium', '<' );
63
+
64
+ useLayoutEffect( () => {
65
+ const scrollContainer = document.querySelector(
66
+ '.interface-interface-skeleton__content'
67
+ );
68
+ const scrollTop = scrollContainer?.scrollTop || 0;
69
+ setContainerScrollTop( scrollTop + DEFAULT_POSITION_TOP );
70
+ }, [ hoveredStyle ] );
71
+
72
+ if ( ! stylesToRender || stylesToRender.length === 0 ) {
80
73
  return null;
81
74
  }
82
75
 
83
- const renderedStyles = find( styles, 'isDefault' )
84
- ? styles
85
- : [
86
- {
87
- name: 'default',
88
- label: _x( 'Default', 'block style' ),
89
- isDefault: true,
90
- },
91
- ...styles,
92
- ];
76
+ const debouncedSetHoveredStyle = debounce( setHoveredStyle, 250 );
93
77
 
94
- const activeStyle = getActiveStyle( renderedStyles, className );
95
- return (
96
- <div className="block-editor-block-styles">
97
- { renderedStyles.map( ( style ) => {
98
- const styleClassName = replaceActiveStyle(
99
- className,
100
- activeStyle,
101
- style
102
- );
103
- return (
104
- <BlockStyleItem
105
- genericPreviewBlock={ genericPreviewBlock }
106
- viewportWidth={ type.example?.viewportWidth ?? 500 }
107
- className={ className }
108
- isActive={ activeStyle === style }
109
- key={ style.name }
110
- onSelect={ () => {
111
- updateBlockAttributes( clientId, {
112
- className: styleClassName,
113
- } );
114
- onHoverClassName( null );
115
- onSwitch();
116
- } }
117
- onBlur={ () => onHoverClassName( null ) }
118
- onHover={ () => onHoverClassName( styleClassName ) }
119
- style={ style }
120
- styleClassName={ styleClassName }
121
- itemRole={ itemRole }
122
- />
123
- );
124
- } ) }
125
- </div>
126
- );
127
- }
78
+ const onSelectStylePreview = ( style ) => {
79
+ onSelect( style );
80
+ onHoverClassName( null );
81
+ setHoveredStyle( null );
82
+ debouncedSetHoveredStyle.cancel();
83
+ };
128
84
 
129
- function BlockStyleItem( {
130
- genericPreviewBlock,
131
- viewportWidth,
132
- style,
133
- isActive,
134
- onBlur,
135
- onHover,
136
- onSelect,
137
- styleClassName,
138
- itemRole,
139
- } ) {
140
- const previewBlocks = useMemo( () => {
141
- return {
142
- ...genericPreviewBlock,
143
- attributes: {
144
- ...genericPreviewBlock.attributes,
145
- className: styleClassName,
146
- },
147
- };
148
- }, [ genericPreviewBlock, styleClassName ] );
85
+ const styleItemHandler = ( item ) => {
86
+ if ( hoveredStyle === item ) {
87
+ debouncedSetHoveredStyle.cancel();
88
+ return;
89
+ }
90
+ debouncedSetHoveredStyle( item );
91
+ onHoverClassName( item?.name ?? null );
92
+ };
149
93
 
150
94
  return (
151
- <div
152
- key={ style.name }
153
- className={ classnames( 'block-editor-block-styles__item', {
154
- 'is-active': isActive,
155
- } ) }
156
- onClick={ () => onSelect() }
157
- onKeyDown={ ( event ) => {
158
- if ( ENTER === event.keyCode || SPACE === event.keyCode ) {
159
- event.preventDefault();
160
- onSelect();
161
- }
162
- } }
163
- onMouseEnter={ onHover }
164
- onMouseLeave={ onBlur }
165
- role={ itemRole || 'button' }
166
- tabIndex="0"
167
- aria-label={ style.label || style.name }
168
- >
169
- <div className="block-editor-block-styles__item-preview">
170
- <BlockPreview
171
- viewportWidth={ viewportWidth }
172
- blocks={ previewBlocks }
173
- />
174
- </div>
175
- <div className="block-editor-block-styles__item-label">
176
- { style.label || style.name }
95
+ <div className="block-editor-block-styles">
96
+ <div className="block-editor-block-styles__variants">
97
+ { stylesToRender.map( ( style ) => {
98
+ const buttonText = style.label || style.name;
99
+
100
+ return (
101
+ <Button
102
+ className={ classnames(
103
+ 'block-editor-block-styles__item',
104
+ {
105
+ 'is-active':
106
+ activeStyle.name === style.name,
107
+ }
108
+ ) }
109
+ key={ style.name }
110
+ variant="secondary"
111
+ label={ buttonText }
112
+ onMouseEnter={ () => styleItemHandler( style ) }
113
+ onFocus={ () => styleItemHandler( style ) }
114
+ onMouseLeave={ () => styleItemHandler( null ) }
115
+ onBlur={ () => styleItemHandler( null ) }
116
+ onKeyDown={ ( event ) => {
117
+ if (
118
+ ENTER === event.keyCode ||
119
+ SPACE === event.keyCode
120
+ ) {
121
+ event.preventDefault();
122
+ onSelectStylePreview( style );
123
+ }
124
+ } }
125
+ onClick={ () => onSelectStylePreview( style ) }
126
+ role="button"
127
+ tabIndex="0"
128
+ >
129
+ <Text
130
+ as="span"
131
+ limit={ 12 }
132
+ ellipsizeMode="tail"
133
+ className="block-editor-block-styles__item-text"
134
+ truncate
135
+ >
136
+ { buttonText }
137
+ </Text>
138
+ </Button>
139
+ );
140
+ } ) }
177
141
  </div>
142
+ { hoveredStyle && ! isMobileViewport && (
143
+ <BlockStylesPreviewPanelFill
144
+ scope={ scope }
145
+ className="block-editor-block-styles__preview-panel"
146
+ style={ { top: containerScrollTop } }
147
+ onMouseLeave={ () => styleItemHandler( null ) }
148
+ >
149
+ <BlockStylesPreviewPanel
150
+ activeStyle={ activeStyle }
151
+ className={ previewClassName }
152
+ genericPreviewBlock={ genericPreviewBlock }
153
+ style={ hoveredStyle }
154
+ />
155
+ </BlockStylesPreviewPanelFill>
156
+ ) }
178
157
  </div>
179
158
  );
180
159
  }
181
160
 
161
+ BlockStyles.Slot = BlockStylesPreviewPanelSlot;
182
162
  export default BlockStyles;
@@ -0,0 +1,49 @@
1
+ /**
2
+ * External dependencies
3
+ */
4
+ import { noop } from 'lodash';
5
+
6
+ /**
7
+ * WordPress dependencies
8
+ */
9
+ import { MenuItem, __experimentalText as Text } from '@wordpress/components';
10
+ import { check } from '@wordpress/icons';
11
+
12
+ /**
13
+ * Internal dependencies
14
+ */
15
+ import useStylesForBlocks from './use-styles-for-block';
16
+
17
+ export default function BlockStylesMenuItems( { clientId, onSwitch = noop } ) {
18
+ const { onSelect, stylesToRender, activeStyle } = useStylesForBlocks( {
19
+ clientId,
20
+ onSwitch,
21
+ } );
22
+
23
+ if ( ! stylesToRender || stylesToRender.length === 0 ) {
24
+ return null;
25
+ }
26
+ return (
27
+ <>
28
+ { stylesToRender.map( ( style ) => {
29
+ const menuItemText = style.label || style.name;
30
+ return (
31
+ <MenuItem
32
+ key={ style.name }
33
+ icon={ activeStyle.name === style.name ? check : null }
34
+ onClick={ () => onSelect( style ) }
35
+ >
36
+ <Text
37
+ as="span"
38
+ limit={ 18 }
39
+ ellipsizeMode="tail"
40
+ truncate
41
+ >
42
+ { menuItemText }
43
+ </Text>
44
+ </MenuItem>
45
+ );
46
+ } ) }
47
+ </>
48
+ );
49
+ }