@wordpress/block-editor 10.4.0 → 11.0.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 (638) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/README.md +0 -1
  3. package/build/autocompleters/block.js +2 -6
  4. package/build/autocompleters/block.js.map +1 -1
  5. package/build/autocompleters/link.js +2 -0
  6. package/build/autocompleters/link.js.map +1 -1
  7. package/build/components/block-card/index.js +51 -3
  8. package/build/components/block-card/index.js.map +1 -1
  9. package/build/components/block-draggable/index.native.js +46 -39
  10. package/build/components/block-draggable/index.native.js.map +1 -1
  11. package/build/components/block-edit/edit.js +4 -3
  12. package/build/components/block-edit/edit.js.map +1 -1
  13. package/build/components/block-edit/edit.native.js +4 -7
  14. package/build/components/block-edit/edit.native.js.map +1 -1
  15. package/build/components/block-inspector/index.js +35 -33
  16. package/build/components/block-inspector/index.js.map +1 -1
  17. package/build/components/block-list/block-list-context.native.js +5 -8
  18. package/build/components/block-list/block-list-context.native.js.map +1 -1
  19. package/build/components/block-list/block.js +55 -24
  20. package/build/components/block-list/block.js.map +1 -1
  21. package/build/components/block-list/block.native.js +61 -28
  22. package/build/components/block-list/block.native.js.map +1 -1
  23. package/build/components/block-lock/menu-item.js +1 -1
  24. package/build/components/block-lock/menu-item.js.map +1 -1
  25. package/build/components/block-lock/modal.js +16 -9
  26. package/build/components/block-lock/modal.js.map +1 -1
  27. package/build/components/block-mobile-toolbar/block-actions-menu.native.js +12 -4
  28. package/build/components/block-mobile-toolbar/block-actions-menu.native.js.map +1 -1
  29. package/build/components/block-pattern-setup/index.js +3 -2
  30. package/build/components/block-pattern-setup/index.js.map +1 -1
  31. package/build/components/block-patterns-list/index.js +33 -11
  32. package/build/components/block-patterns-list/index.js.map +1 -1
  33. package/build/components/block-preview/auto.js +9 -3
  34. package/build/components/block-preview/auto.js.map +1 -1
  35. package/build/components/block-preview/index.js +5 -9
  36. package/build/components/block-preview/index.js.map +1 -1
  37. package/build/components/block-settings-menu/block-settings-dropdown.js +5 -2
  38. package/build/components/block-settings-menu/block-settings-dropdown.js.map +1 -1
  39. package/build/components/block-styles/utils.js +3 -3
  40. package/build/components/block-styles/utils.js.map +1 -1
  41. package/build/components/block-switcher/index.js +19 -4
  42. package/build/components/block-switcher/index.js.map +1 -1
  43. package/build/components/block-toolbar/index.js +5 -1
  44. package/build/components/block-toolbar/index.js.map +1 -1
  45. package/build/components/block-tools/insertion-point.js +8 -49
  46. package/build/components/block-tools/insertion-point.js.map +1 -1
  47. package/build/components/block-tools/selected-block-popover.js +27 -4
  48. package/build/components/block-tools/selected-block-popover.js.map +1 -1
  49. package/build/components/block-variation-picker/index.js +1 -2
  50. package/build/components/block-variation-picker/index.js.map +1 -1
  51. package/build/components/colors/with-colors.js +4 -3
  52. package/build/components/colors/with-colors.js.map +1 -1
  53. package/build/components/font-sizes/fluid-utils.js +24 -40
  54. package/build/components/font-sizes/fluid-utils.js.map +1 -1
  55. package/build/components/font-sizes/with-font-sizes.js +7 -5
  56. package/build/components/font-sizes/with-font-sizes.js.map +1 -1
  57. package/build/components/height-control/index.js +115 -0
  58. package/build/components/height-control/index.js.map +1 -0
  59. package/build/components/iframe/index.js +11 -8
  60. package/build/components/iframe/index.js.map +1 -1
  61. package/build/components/image-editor/use-save-image.js +2 -0
  62. package/build/components/image-editor/use-save-image.js.map +1 -1
  63. package/build/components/image-editor/zoom-dropdown.js +1 -0
  64. package/build/components/image-editor/zoom-dropdown.js.map +1 -1
  65. package/build/components/index.js +18 -0
  66. package/build/components/index.js.map +1 -1
  67. package/build/components/inner-blocks/index.js +25 -9
  68. package/build/components/inner-blocks/index.js.map +1 -1
  69. package/build/components/inner-blocks/use-inner-block-template-sync.js +25 -10
  70. package/build/components/inner-blocks/use-inner-block-template-sync.js.map +1 -1
  71. package/build/components/inserter/block-patterns-explorer/sidebar.js +1 -0
  72. package/build/components/inserter/block-patterns-explorer/sidebar.js.map +1 -1
  73. package/build/components/inserter/block-patterns-tab.js +25 -46
  74. package/build/components/inserter/block-patterns-tab.js.map +1 -1
  75. package/build/components/inserter/block-types-tab.js +3 -1
  76. package/build/components/inserter/block-types-tab.js.map +1 -1
  77. package/build/components/inserter/hooks/use-debounced-input.js +27 -0
  78. package/build/components/inserter/hooks/use-debounced-input.js.map +1 -0
  79. package/build/components/inserter/index.js +8 -3
  80. package/build/components/inserter/index.js.map +1 -1
  81. package/build/components/inserter/index.native.js +3 -4
  82. package/build/components/inserter/index.native.js.map +1 -1
  83. package/build/components/inserter/media-tab/hooks.js +103 -0
  84. package/build/components/inserter/media-tab/hooks.js.map +1 -0
  85. package/build/components/inserter/media-tab/index.js +32 -0
  86. package/build/components/inserter/media-tab/index.js.map +1 -0
  87. package/build/components/inserter/media-tab/media-list.js +100 -0
  88. package/build/components/inserter/media-tab/media-list.js.map +1 -0
  89. package/build/components/inserter/media-tab/media-panel.js +96 -0
  90. package/build/components/inserter/media-tab/media-panel.js.map +1 -0
  91. package/build/components/inserter/media-tab/media-tab.js +120 -0
  92. package/build/components/inserter/media-tab/media-tab.js.map +1 -0
  93. package/build/components/inserter/media-tab/utils.js +54 -0
  94. package/build/components/inserter/media-tab/utils.js.map +1 -0
  95. package/build/components/inserter/menu.js +35 -12
  96. package/build/components/inserter/menu.js.map +1 -1
  97. package/build/components/inserter/mobile-tab-navigation.js +70 -0
  98. package/build/components/inserter/mobile-tab-navigation.js.map +1 -0
  99. package/build/components/inserter/quick-inserter.js +1 -0
  100. package/build/components/inserter/quick-inserter.js.map +1 -1
  101. package/build/components/inserter/reusable-blocks-tab.js +4 -1
  102. package/build/components/inserter/reusable-blocks-tab.js.map +1 -1
  103. package/build/components/inserter/search-results.js +3 -1
  104. package/build/components/inserter/search-results.js.map +1 -1
  105. package/build/components/inserter/tabs.js +16 -2
  106. package/build/components/inserter/tabs.js.map +1 -1
  107. package/build/components/inserter-list-item/index.js +4 -1
  108. package/build/components/inserter-list-item/index.js.map +1 -1
  109. package/build/components/inspector-controls/groups.js +2 -0
  110. package/build/components/inspector-controls/groups.js.map +1 -1
  111. package/build/components/inspector-controls-tabs/advanced-controls-panel.js +46 -0
  112. package/build/components/inspector-controls-tabs/advanced-controls-panel.js.map +1 -0
  113. package/build/components/inspector-controls-tabs/index.js +71 -0
  114. package/build/components/inspector-controls-tabs/index.js.map +1 -0
  115. package/build/components/inspector-controls-tabs/settings-tab.js +28 -0
  116. package/build/components/inspector-controls-tabs/settings-tab.js.map +1 -0
  117. package/build/components/inspector-controls-tabs/styles-tab.js +61 -0
  118. package/build/components/inspector-controls-tabs/styles-tab.js.map +1 -0
  119. package/build/components/inspector-controls-tabs/use-inspector-controls-tabs.js +97 -0
  120. package/build/components/inspector-controls-tabs/use-inspector-controls-tabs.js.map +1 -0
  121. package/build/components/inspector-controls-tabs/use-is-list-view-tab-disabled.js +18 -0
  122. package/build/components/inspector-controls-tabs/use-is-list-view-tab-disabled.js.map +1 -0
  123. package/build/components/inspector-controls-tabs/utils.js +37 -0
  124. package/build/components/inspector-controls-tabs/utils.js.map +1 -0
  125. package/build/components/link-control/index.js +19 -34
  126. package/build/components/link-control/index.js.map +1 -1
  127. package/build/components/link-control/search-input.js +1 -2
  128. package/build/components/link-control/search-input.js.map +1 -1
  129. package/build/components/link-control/use-internal-input-value.js +26 -0
  130. package/build/components/link-control/use-internal-input-value.js.map +1 -0
  131. package/build/components/list-view/block.js +10 -5
  132. package/build/components/list-view/block.js.map +1 -1
  133. package/build/components/list-view/branch.js +22 -15
  134. package/build/components/list-view/branch.js.map +1 -1
  135. package/build/components/media-upload/index.native.js +2 -3
  136. package/build/components/media-upload/index.native.js.map +1 -1
  137. package/build/components/off-canvas-editor/appender.js +104 -0
  138. package/build/components/off-canvas-editor/appender.js.map +1 -0
  139. package/build/components/off-canvas-editor/block-contents.js +100 -0
  140. package/build/components/off-canvas-editor/block-contents.js.map +1 -0
  141. package/build/components/off-canvas-editor/block-edit-button.js +50 -0
  142. package/build/components/off-canvas-editor/block-edit-button.js.map +1 -0
  143. package/build/components/off-canvas-editor/block-select-button.js +119 -0
  144. package/build/components/off-canvas-editor/block-select-button.js.map +1 -0
  145. package/build/components/off-canvas-editor/block.js +324 -0
  146. package/build/components/off-canvas-editor/block.js.map +1 -0
  147. package/build/components/off-canvas-editor/branch.js +179 -0
  148. package/build/components/off-canvas-editor/branch.js.map +1 -0
  149. package/build/components/off-canvas-editor/context.js +19 -0
  150. package/build/components/off-canvas-editor/context.js.map +1 -0
  151. package/build/components/off-canvas-editor/drop-indicator.js +118 -0
  152. package/build/components/off-canvas-editor/drop-indicator.js.map +1 -0
  153. package/build/components/off-canvas-editor/expander.js +41 -0
  154. package/build/components/off-canvas-editor/expander.js.map +1 -0
  155. package/build/components/off-canvas-editor/index.js +213 -0
  156. package/build/components/off-canvas-editor/index.js.map +1 -0
  157. package/build/components/off-canvas-editor/leaf.js +60 -0
  158. package/build/components/off-canvas-editor/leaf.js.map +1 -0
  159. package/build/components/off-canvas-editor/link-ui.js +185 -0
  160. package/build/components/off-canvas-editor/link-ui.js.map +1 -0
  161. package/build/components/off-canvas-editor/update-attributes.js +108 -0
  162. package/build/components/off-canvas-editor/update-attributes.js.map +1 -0
  163. package/build/components/off-canvas-editor/use-block-selection.js +139 -0
  164. package/build/components/off-canvas-editor/use-block-selection.js.map +1 -0
  165. package/build/components/off-canvas-editor/use-list-view-client-ids.js +33 -0
  166. package/build/components/off-canvas-editor/use-list-view-client-ids.js.map +1 -0
  167. package/build/components/off-canvas-editor/use-list-view-drop-zone.js +235 -0
  168. package/build/components/off-canvas-editor/use-list-view-drop-zone.js.map +1 -0
  169. package/build/components/off-canvas-editor/use-list-view-expand-selected-item.js +60 -0
  170. package/build/components/off-canvas-editor/use-list-view-expand-selected-item.js.map +1 -0
  171. package/build/components/off-canvas-editor/utils.js +60 -0
  172. package/build/components/off-canvas-editor/utils.js.map +1 -0
  173. package/build/components/rich-text/format-toolbar/index.js +8 -4
  174. package/build/components/rich-text/format-toolbar/index.js.map +1 -1
  175. package/build/components/rich-text/index.js +3 -3
  176. package/build/components/rich-text/index.js.map +1 -1
  177. package/build/components/rich-text/index.native.js +0 -2
  178. package/build/components/rich-text/index.native.js.map +1 -1
  179. package/build/components/rich-text/use-insert-replacement-text.js +43 -0
  180. package/build/components/rich-text/use-insert-replacement-text.js.map +1 -0
  181. package/build/components/rich-text/use-undo-automatic-change.js +9 -1
  182. package/build/components/rich-text/use-undo-automatic-change.js.map +1 -1
  183. package/build/components/rich-text/utils.js +1 -19
  184. package/build/components/rich-text/utils.js.map +1 -1
  185. package/build/components/spacing-sizes-control/spacing-input-control.js +12 -3
  186. package/build/components/spacing-sizes-control/spacing-input-control.js.map +1 -1
  187. package/build/components/ungroup-button/index.native.js +4 -2
  188. package/build/components/ungroup-button/index.native.js.map +1 -1
  189. package/build/components/url-input/index.js +46 -43
  190. package/build/components/url-input/index.js.map +1 -1
  191. package/build/components/url-popover/index.js +31 -2
  192. package/build/components/url-popover/index.js.map +1 -1
  193. package/build/components/use-block-display-information/index.js +8 -4
  194. package/build/components/use-block-display-information/index.js.map +1 -1
  195. package/build/components/use-setting/index.js +10 -2
  196. package/build/components/use-setting/index.js.map +1 -1
  197. package/build/hooks/child-layout.js +209 -0
  198. package/build/hooks/child-layout.js.map +1 -0
  199. package/build/hooks/color-panel.js +17 -1
  200. package/build/hooks/color-panel.js.map +1 -1
  201. package/build/hooks/color.js +1 -1
  202. package/build/hooks/color.js.map +1 -1
  203. package/build/hooks/content-lock-ui.js +14 -7
  204. package/build/hooks/content-lock-ui.js.map +1 -1
  205. package/build/hooks/dimensions.js +65 -16
  206. package/build/hooks/dimensions.js.map +1 -1
  207. package/build/hooks/layout.js +59 -3
  208. package/build/hooks/layout.js.map +1 -1
  209. package/build/hooks/margin.js +4 -2
  210. package/build/hooks/margin.js.map +1 -1
  211. package/build/hooks/min-height.js +139 -0
  212. package/build/hooks/min-height.js.map +1 -0
  213. package/build/hooks/padding.js +4 -2
  214. package/build/hooks/padding.js.map +1 -1
  215. package/build/hooks/style.js +3 -2
  216. package/build/hooks/style.js.map +1 -1
  217. package/build/layouts/flex.js +22 -21
  218. package/build/layouts/flex.js.map +1 -1
  219. package/build/store/actions.js +26 -0
  220. package/build/store/actions.js.map +1 -1
  221. package/build/store/reducer.js +420 -265
  222. package/build/store/reducer.js.map +1 -1
  223. package/build/store/selectors.js +73 -49
  224. package/build/store/selectors.js.map +1 -1
  225. package/build/utils/sorting.js +63 -0
  226. package/build/utils/sorting.js.map +1 -0
  227. package/build-module/autocompleters/block.js +2 -6
  228. package/build-module/autocompleters/block.js.map +1 -1
  229. package/build-module/autocompleters/link.js +2 -0
  230. package/build-module/autocompleters/link.js.map +1 -1
  231. package/build-module/components/block-card/index.js +45 -3
  232. package/build-module/components/block-card/index.js.map +1 -1
  233. package/build-module/components/block-draggable/index.native.js +40 -31
  234. package/build-module/components/block-draggable/index.native.js.map +1 -1
  235. package/build-module/components/block-edit/edit.js +4 -2
  236. package/build-module/components/block-edit/edit.js.map +1 -1
  237. package/build-module/components/block-edit/edit.native.js +4 -6
  238. package/build-module/components/block-edit/edit.native.js.map +1 -1
  239. package/build-module/components/block-inspector/index.js +32 -30
  240. package/build-module/components/block-inspector/index.js.map +1 -1
  241. package/build-module/components/block-list/block-list-context.native.js +5 -8
  242. package/build-module/components/block-list/block-list-context.native.js.map +1 -1
  243. package/build-module/components/block-list/block.js +55 -25
  244. package/build-module/components/block-list/block.js.map +1 -1
  245. package/build-module/components/block-list/block.native.js +61 -28
  246. package/build-module/components/block-list/block.native.js.map +1 -1
  247. package/build-module/components/block-lock/menu-item.js +2 -2
  248. package/build-module/components/block-lock/menu-item.js.map +1 -1
  249. package/build-module/components/block-lock/modal.js +17 -10
  250. package/build-module/components/block-lock/modal.js.map +1 -1
  251. package/build-module/components/block-mobile-toolbar/block-actions-menu.native.js +13 -6
  252. package/build-module/components/block-mobile-toolbar/block-actions-menu.native.js.map +1 -1
  253. package/build-module/components/block-pattern-setup/index.js +3 -2
  254. package/build-module/components/block-pattern-setup/index.js.map +1 -1
  255. package/build-module/components/block-patterns-list/index.js +35 -13
  256. package/build-module/components/block-patterns-list/index.js.map +1 -1
  257. package/build-module/components/block-preview/auto.js +9 -3
  258. package/build-module/components/block-preview/auto.js.map +1 -1
  259. package/build-module/components/block-preview/index.js +5 -8
  260. package/build-module/components/block-preview/index.js.map +1 -1
  261. package/build-module/components/block-settings-menu/block-settings-dropdown.js +5 -2
  262. package/build-module/components/block-settings-menu/block-settings-dropdown.js.map +1 -1
  263. package/build-module/components/block-styles/utils.js +3 -3
  264. package/build-module/components/block-styles/utils.js.map +1 -1
  265. package/build-module/components/block-switcher/index.js +19 -4
  266. package/build-module/components/block-switcher/index.js.map +1 -1
  267. package/build-module/components/block-toolbar/index.js +6 -2
  268. package/build-module/components/block-toolbar/index.js.map +1 -1
  269. package/build-module/components/block-tools/insertion-point.js +8 -49
  270. package/build-module/components/block-tools/insertion-point.js.map +1 -1
  271. package/build-module/components/block-tools/selected-block-popover.js +27 -5
  272. package/build-module/components/block-tools/selected-block-popover.js.map +1 -1
  273. package/build-module/components/block-variation-picker/index.js +1 -2
  274. package/build-module/components/block-variation-picker/index.js.map +1 -1
  275. package/build-module/components/colors/with-colors.js +5 -4
  276. package/build-module/components/colors/with-colors.js.map +1 -1
  277. package/build-module/components/font-sizes/fluid-utils.js +24 -40
  278. package/build-module/components/font-sizes/fluid-utils.js.map +1 -1
  279. package/build-module/components/font-sizes/with-font-sizes.js +8 -6
  280. package/build-module/components/font-sizes/with-font-sizes.js.map +1 -1
  281. package/build-module/components/height-control/index.js +103 -0
  282. package/build-module/components/height-control/index.js.map +1 -0
  283. package/build-module/components/iframe/index.js +11 -8
  284. package/build-module/components/iframe/index.js.map +1 -1
  285. package/build-module/components/image-editor/use-save-image.js +2 -0
  286. package/build-module/components/image-editor/use-save-image.js.map +1 -1
  287. package/build-module/components/image-editor/zoom-dropdown.js +1 -0
  288. package/build-module/components/image-editor/zoom-dropdown.js.map +1 -1
  289. package/build-module/components/index.js +2 -0
  290. package/build-module/components/index.js.map +1 -1
  291. package/build-module/components/inner-blocks/index.js +27 -11
  292. package/build-module/components/inner-blocks/index.js.map +1 -1
  293. package/build-module/components/inner-blocks/use-inner-block-template-sync.js +23 -10
  294. package/build-module/components/inner-blocks/use-inner-block-template-sync.js.map +1 -1
  295. package/build-module/components/inserter/block-patterns-explorer/sidebar.js +1 -0
  296. package/build-module/components/inserter/block-patterns-explorer/sidebar.js.map +1 -1
  297. package/build-module/components/inserter/block-patterns-tab.js +27 -49
  298. package/build-module/components/inserter/block-patterns-tab.js.map +1 -1
  299. package/build-module/components/inserter/block-types-tab.js +3 -2
  300. package/build-module/components/inserter/block-types-tab.js.map +1 -1
  301. package/build-module/components/inserter/hooks/use-debounced-input.js +18 -0
  302. package/build-module/components/inserter/hooks/use-debounced-input.js.map +1 -0
  303. package/build-module/components/inserter/index.js +8 -3
  304. package/build-module/components/inserter/index.js.map +1 -1
  305. package/build-module/components/inserter/index.native.js +3 -5
  306. package/build-module/components/inserter/index.native.js.map +1 -1
  307. package/build-module/components/inserter/media-tab/hooks.js +89 -0
  308. package/build-module/components/inserter/media-tab/hooks.js.map +1 -0
  309. package/build-module/components/inserter/media-tab/index.js +4 -0
  310. package/build-module/components/inserter/media-tab/index.js.map +1 -0
  311. package/build-module/components/inserter/media-tab/media-list.js +86 -0
  312. package/build-module/components/inserter/media-tab/media-list.js.map +1 -0
  313. package/build-module/components/inserter/media-tab/media-panel.js +77 -0
  314. package/build-module/components/inserter/media-tab/media-panel.js.map +1 -0
  315. package/build-module/components/inserter/media-tab/media-tab.js +100 -0
  316. package/build-module/components/inserter/media-tab/media-tab.js.map +1 -0
  317. package/build-module/components/inserter/media-tab/utils.js +45 -0
  318. package/build-module/components/inserter/media-tab/utils.js.map +1 -0
  319. package/build-module/components/inserter/menu.js +33 -12
  320. package/build-module/components/inserter/menu.js.map +1 -1
  321. package/build-module/components/inserter/mobile-tab-navigation.js +61 -0
  322. package/build-module/components/inserter/mobile-tab-navigation.js.map +1 -0
  323. package/build-module/components/inserter/quick-inserter.js +1 -0
  324. package/build-module/components/inserter/quick-inserter.js.map +1 -1
  325. package/build-module/components/inserter/reusable-blocks-tab.js +3 -1
  326. package/build-module/components/inserter/reusable-blocks-tab.js.map +1 -1
  327. package/build-module/components/inserter/search-results.js +3 -2
  328. package/build-module/components/inserter/search-results.js.map +1 -1
  329. package/build-module/components/inserter/tabs.js +15 -2
  330. package/build-module/components/inserter/tabs.js.map +1 -1
  331. package/build-module/components/inserter-list-item/index.js +5 -2
  332. package/build-module/components/inserter-list-item/index.js.map +1 -1
  333. package/build-module/components/inspector-controls/groups.js +2 -0
  334. package/build-module/components/inspector-controls/groups.js.map +1 -1
  335. package/build-module/components/inspector-controls-tabs/advanced-controls-panel.js +32 -0
  336. package/build-module/components/inspector-controls-tabs/advanced-controls-panel.js.map +1 -0
  337. package/build-module/components/inspector-controls-tabs/index.js +56 -0
  338. package/build-module/components/inspector-controls-tabs/index.js.map +1 -0
  339. package/build-module/components/inspector-controls-tabs/settings-tab.js +17 -0
  340. package/build-module/components/inspector-controls-tabs/settings-tab.js.map +1 -0
  341. package/build-module/components/inspector-controls-tabs/styles-tab.js +46 -0
  342. package/build-module/components/inspector-controls-tabs/styles-tab.js.map +1 -0
  343. package/build-module/components/inspector-controls-tabs/use-inspector-controls-tabs.js +81 -0
  344. package/build-module/components/inspector-controls-tabs/use-inspector-controls-tabs.js.map +1 -0
  345. package/build-module/components/inspector-controls-tabs/use-is-list-view-tab-disabled.js +8 -0
  346. package/build-module/components/inspector-controls-tabs/use-is-list-view-tab-disabled.js.map +1 -0
  347. package/build-module/components/inspector-controls-tabs/utils.js +26 -0
  348. package/build-module/components/inspector-controls-tabs/utils.js.map +1 -0
  349. package/build-module/components/link-control/index.js +18 -34
  350. package/build-module/components/link-control/index.js.map +1 -1
  351. package/build-module/components/link-control/search-input.js +1 -2
  352. package/build-module/components/link-control/search-input.js.map +1 -1
  353. package/build-module/components/link-control/use-internal-input-value.js +18 -0
  354. package/build-module/components/link-control/use-internal-input-value.js.map +1 -0
  355. package/build-module/components/list-view/block.js +10 -5
  356. package/build-module/components/list-view/block.js.map +1 -1
  357. package/build-module/components/list-view/branch.js +21 -14
  358. package/build-module/components/list-view/branch.js.map +1 -1
  359. package/build-module/components/media-upload/index.native.js +2 -4
  360. package/build-module/components/media-upload/index.native.js.map +1 -1
  361. package/build-module/components/off-canvas-editor/appender.js +89 -0
  362. package/build-module/components/off-canvas-editor/appender.js.map +1 -0
  363. package/build-module/components/off-canvas-editor/block-contents.js +85 -0
  364. package/build-module/components/off-canvas-editor/block-contents.js.map +1 -0
  365. package/build-module/components/off-canvas-editor/block-edit-button.js +35 -0
  366. package/build-module/components/off-canvas-editor/block-edit-button.js.map +1 -0
  367. package/build-module/components/off-canvas-editor/block-select-button.js +101 -0
  368. package/build-module/components/off-canvas-editor/block-select-button.js.map +1 -0
  369. package/build-module/components/off-canvas-editor/block.js +298 -0
  370. package/build-module/components/off-canvas-editor/block.js.map +1 -0
  371. package/build-module/components/off-canvas-editor/branch.js +164 -0
  372. package/build-module/components/off-canvas-editor/branch.js.map +1 -0
  373. package/build-module/components/off-canvas-editor/context.js +7 -0
  374. package/build-module/components/off-canvas-editor/context.js.map +1 -0
  375. package/build-module/components/off-canvas-editor/drop-indicator.js +111 -0
  376. package/build-module/components/off-canvas-editor/drop-indicator.js.map +1 -0
  377. package/build-module/components/off-canvas-editor/expander.js +32 -0
  378. package/build-module/components/off-canvas-editor/expander.js.map +1 -0
  379. package/build-module/components/off-canvas-editor/index.js +189 -0
  380. package/build-module/components/off-canvas-editor/index.js.map +1 -0
  381. package/build-module/components/off-canvas-editor/leaf.js +45 -0
  382. package/build-module/components/off-canvas-editor/leaf.js.map +1 -0
  383. package/build-module/components/off-canvas-editor/link-ui.js +165 -0
  384. package/build-module/components/off-canvas-editor/link-ui.js.map +1 -0
  385. package/build-module/components/off-canvas-editor/update-attributes.js +97 -0
  386. package/build-module/components/off-canvas-editor/update-attributes.js.map +1 -0
  387. package/build-module/components/off-canvas-editor/use-block-selection.js +124 -0
  388. package/build-module/components/off-canvas-editor/use-block-selection.js.map +1 -0
  389. package/build-module/components/off-canvas-editor/use-list-view-client-ids.js +24 -0
  390. package/build-module/components/off-canvas-editor/use-list-view-client-ids.js.map +1 -0
  391. package/build-module/components/off-canvas-editor/use-list-view-drop-zone.js +220 -0
  392. package/build-module/components/off-canvas-editor/use-list-view-drop-zone.js.map +1 -0
  393. package/build-module/components/off-canvas-editor/use-list-view-expand-selected-item.js +50 -0
  394. package/build-module/components/off-canvas-editor/use-list-view-expand-selected-item.js.map +1 -0
  395. package/build-module/components/off-canvas-editor/utils.js +44 -0
  396. package/build-module/components/off-canvas-editor/utils.js.map +1 -0
  397. package/build-module/components/rich-text/format-toolbar/index.js +6 -2
  398. package/build-module/components/rich-text/format-toolbar/index.js.map +1 -1
  399. package/build-module/components/rich-text/index.js +2 -3
  400. package/build-module/components/rich-text/index.js.map +1 -1
  401. package/build-module/components/rich-text/index.native.js +0 -2
  402. package/build-module/components/rich-text/index.native.js.map +1 -1
  403. package/build-module/components/rich-text/use-insert-replacement-text.js +33 -0
  404. package/build-module/components/rich-text/use-insert-replacement-text.js.map +1 -0
  405. package/build-module/components/rich-text/use-undo-automatic-change.js +9 -1
  406. package/build-module/components/rich-text/use-undo-automatic-change.js.map +1 -1
  407. package/build-module/components/rich-text/utils.js +1 -16
  408. package/build-module/components/rich-text/utils.js.map +1 -1
  409. package/build-module/components/spacing-sizes-control/spacing-input-control.js +12 -3
  410. package/build-module/components/spacing-sizes-control/spacing-input-control.js.map +1 -1
  411. package/build-module/components/ungroup-button/index.native.js +3 -2
  412. package/build-module/components/ungroup-button/index.native.js.map +1 -1
  413. package/build-module/components/url-input/index.js +46 -43
  414. package/build-module/components/url-input/index.js.map +1 -1
  415. package/build-module/components/url-popover/index.js +30 -3
  416. package/build-module/components/url-popover/index.js.map +1 -1
  417. package/build-module/components/use-block-display-information/index.js +9 -5
  418. package/build-module/components/use-block-display-information/index.js.map +1 -1
  419. package/build-module/components/use-setting/index.js +9 -2
  420. package/build-module/components/use-setting/index.js.map +1 -1
  421. package/build-module/hooks/child-layout.js +189 -0
  422. package/build-module/hooks/child-layout.js.map +1 -0
  423. package/build-module/hooks/color-panel.js +17 -1
  424. package/build-module/hooks/color-panel.js.map +1 -1
  425. package/build-module/hooks/color.js +1 -1
  426. package/build-module/hooks/color.js.map +1 -1
  427. package/build-module/hooks/content-lock-ui.js +16 -9
  428. package/build-module/hooks/content-lock-ui.js.map +1 -1
  429. package/build-module/hooks/dimensions.js +60 -16
  430. package/build-module/hooks/dimensions.js.map +1 -1
  431. package/build-module/hooks/layout.js +57 -2
  432. package/build-module/hooks/layout.js.map +1 -1
  433. package/build-module/hooks/margin.js +4 -2
  434. package/build-module/hooks/margin.js.map +1 -1
  435. package/build-module/hooks/min-height.js +116 -0
  436. package/build-module/hooks/min-height.js.map +1 -0
  437. package/build-module/hooks/padding.js +4 -2
  438. package/build-module/hooks/padding.js.map +1 -1
  439. package/build-module/hooks/style.js +4 -3
  440. package/build-module/hooks/style.js.map +1 -1
  441. package/build-module/layouts/flex.js +23 -22
  442. package/build-module/layouts/flex.js.map +1 -1
  443. package/build-module/store/actions.js +22 -0
  444. package/build-module/store/actions.js.map +1 -1
  445. package/build-module/store/reducer.js +415 -265
  446. package/build-module/store/reducer.js.map +1 -1
  447. package/build-module/store/selectors.js +66 -48
  448. package/build-module/store/selectors.js.map +1 -1
  449. package/build-module/utils/sorting.js +56 -0
  450. package/build-module/utils/sorting.js.map +1 -0
  451. package/build-style/content-rtl.css +701 -0
  452. package/build-style/content.css +701 -0
  453. package/build-style/default-editor-styles-rtl.css +14 -0
  454. package/build-style/default-editor-styles.css +14 -0
  455. package/build-style/style-rtl.css +305 -668
  456. package/build-style/style.css +305 -668
  457. package/package.json +32 -30
  458. package/src/autocompleters/block.js +2 -6
  459. package/src/autocompleters/link.js +2 -0
  460. package/src/components/alignment-control/README.md +1 -1
  461. package/src/components/alignment-control/test/index.js +4 -1
  462. package/src/components/block-alignment-control/test/index.js +4 -1
  463. package/src/components/block-alignment-control/test/index.native.js +4 -4
  464. package/src/components/block-card/index.js +46 -2
  465. package/src/components/block-card/style.scss +4 -0
  466. package/src/components/block-content-overlay/{style.scss → content.scss} +7 -1
  467. package/src/components/block-draggable/content.scss +20 -0
  468. package/src/components/block-draggable/index.native.js +54 -40
  469. package/src/components/block-draggable/style.scss +0 -21
  470. package/src/components/block-draggable/test/helpers.native.js +7 -9
  471. package/src/components/block-draggable/test/index.native.js +35 -45
  472. package/src/components/block-edit/edit.js +5 -2
  473. package/src/components/block-edit/edit.native.js +5 -6
  474. package/src/components/block-inspector/index.js +96 -81
  475. package/src/components/block-inspector/style.scss +9 -1
  476. package/src/components/block-list/block-list-context.native.js +5 -8
  477. package/src/components/block-list/block.js +74 -23
  478. package/src/components/block-list/block.native.js +78 -23
  479. package/src/components/block-list/{style.scss → content.scss} +11 -20
  480. package/src/components/block-list-appender/{style.scss → content.scss} +0 -0
  481. package/src/components/block-lock/menu-item.js +5 -2
  482. package/src/components/block-lock/modal.js +19 -36
  483. package/src/components/block-lock/style.scss +8 -17
  484. package/src/components/block-mobile-toolbar/block-actions-menu.native.js +24 -6
  485. package/src/components/block-mover/style.scss +0 -1
  486. package/src/components/block-mover/test/__snapshots__/index.native.js.snap +0 -2
  487. package/src/components/block-pattern-setup/index.js +2 -1
  488. package/src/components/block-patterns-list/index.js +47 -24
  489. package/src/components/block-popover/style.scss +1 -1
  490. package/src/components/block-preview/README.md +15 -10
  491. package/src/components/block-preview/auto.js +7 -1
  492. package/src/components/block-preview/content.scss +4 -0
  493. package/src/components/block-preview/index.js +7 -12
  494. package/src/components/block-preview/style.scss +0 -7
  495. package/src/components/block-preview/test/index.js +18 -35
  496. package/src/components/block-selection-clearer/test/index.js +12 -12
  497. package/src/components/block-settings-menu/block-settings-dropdown.js +32 -20
  498. package/src/components/block-styles/utils.js +3 -3
  499. package/src/components/block-switcher/index.js +19 -4
  500. package/src/components/block-switcher/test/index.js +4 -0
  501. package/src/components/block-toolbar/index.js +12 -5
  502. package/src/components/block-toolbar/style.scss +10 -0
  503. package/src/components/block-tools/insertion-point.js +3 -47
  504. package/src/components/block-tools/selected-block-popover.js +80 -34
  505. package/src/components/block-tools/style.scss +27 -5
  506. package/src/components/block-variation-picker/index.js +1 -4
  507. package/src/components/block-vertical-alignment-control/test/index.js +4 -1
  508. package/src/components/colors/with-colors.js +13 -23
  509. package/src/components/default-block-appender/{style.scss → content.scss} +1 -0
  510. package/src/components/font-sizes/fluid-utils.js +37 -64
  511. package/src/components/font-sizes/test/fluid-utils.js +5 -5
  512. package/src/components/font-sizes/with-font-sizes.js +14 -11
  513. package/src/components/height-control/index.js +123 -0
  514. package/src/components/height-control/stories/index.js +21 -0
  515. package/src/components/height-control/style.scss +5 -0
  516. package/src/components/iframe/index.js +25 -18
  517. package/src/components/image-editor/use-save-image.js +2 -0
  518. package/src/components/image-editor/zoom-dropdown.js +1 -0
  519. package/src/components/index.js +2 -0
  520. package/src/components/inner-blocks/{style.scss → content.scss} +0 -0
  521. package/src/components/inner-blocks/index.js +30 -10
  522. package/src/components/inner-blocks/use-inner-block-template-sync.js +28 -10
  523. package/src/components/inserter/block-patterns-explorer/sidebar.js +1 -0
  524. package/src/components/inserter/block-patterns-tab.js +28 -71
  525. package/src/components/inserter/block-types-tab.js +3 -2
  526. package/src/components/inserter/hooks/use-debounced-input.js +17 -0
  527. package/src/components/inserter/index.js +10 -2
  528. package/src/components/inserter/index.native.js +1 -1
  529. package/src/components/inserter/media-tab/hooks.js +88 -0
  530. package/src/components/inserter/media-tab/index.js +3 -0
  531. package/src/components/inserter/media-tab/media-list.js +93 -0
  532. package/src/components/inserter/media-tab/media-panel.js +83 -0
  533. package/src/components/inserter/media-tab/media-tab.js +135 -0
  534. package/src/components/inserter/media-tab/utils.js +37 -0
  535. package/src/components/inserter/menu.js +55 -13
  536. package/src/components/inserter/mobile-tab-navigation.js +85 -0
  537. package/src/components/inserter/quick-inserter.js +1 -0
  538. package/src/components/inserter/reusable-blocks-tab.js +4 -2
  539. package/src/components/inserter/search-results.js +3 -2
  540. package/src/components/inserter/stories/index.js +1 -1
  541. package/src/components/inserter/stories/{fixtures.js → utils/fixtures.js} +0 -0
  542. package/src/components/inserter/style.scss +184 -18
  543. package/src/components/inserter/tabs.js +12 -1
  544. package/src/components/inserter/test/reusable-blocks-tab.js +14 -57
  545. package/src/components/inserter-list-item/index.js +11 -1
  546. package/src/components/inserter-list-item/style.scss +26 -0
  547. package/src/components/inspector-controls/groups.js +2 -0
  548. package/src/components/inspector-controls-tabs/advanced-controls-panel.js +37 -0
  549. package/src/components/inspector-controls-tabs/index.js +62 -0
  550. package/src/components/inspector-controls-tabs/settings-tab.js +18 -0
  551. package/src/components/inspector-controls-tabs/styles-tab.js +51 -0
  552. package/src/components/inspector-controls-tabs/use-inspector-controls-tabs.js +89 -0
  553. package/src/components/inspector-controls-tabs/use-is-list-view-tab-disabled.js +9 -0
  554. package/src/components/inspector-controls-tabs/utils.js +28 -0
  555. package/src/components/line-height-control/test/index.js +5 -5
  556. package/src/components/link-control/README.md +1 -1
  557. package/src/components/link-control/index.js +24 -39
  558. package/src/components/link-control/search-input.js +1 -2
  559. package/src/components/link-control/test/index.js +400 -582
  560. package/src/components/link-control/use-internal-input-value.js +22 -0
  561. package/src/components/list-view/block.js +7 -3
  562. package/src/components/list-view/branch.js +21 -14
  563. package/src/components/list-view/style.scss +20 -9
  564. package/src/components/media-placeholder/{style.scss → content.scss} +0 -0
  565. package/src/components/media-replace-flow/test/index.js +37 -9
  566. package/src/components/media-upload/test/index.native.js +2 -0
  567. package/src/components/off-canvas-editor/README.md +5 -0
  568. package/src/components/off-canvas-editor/appender.js +93 -0
  569. package/src/components/off-canvas-editor/block-contents.js +89 -0
  570. package/src/components/off-canvas-editor/block-edit-button.js +27 -0
  571. package/src/components/off-canvas-editor/block-select-button.js +113 -0
  572. package/src/components/off-canvas-editor/block.js +401 -0
  573. package/src/components/off-canvas-editor/branch.js +208 -0
  574. package/src/components/off-canvas-editor/context.js +8 -0
  575. package/src/components/off-canvas-editor/drop-indicator.js +126 -0
  576. package/src/components/off-canvas-editor/expander.js +26 -0
  577. package/src/components/off-canvas-editor/index.js +242 -0
  578. package/src/components/off-canvas-editor/leaf.js +52 -0
  579. package/src/components/off-canvas-editor/link-ui.js +166 -0
  580. package/src/components/off-canvas-editor/style.scss +26 -0
  581. package/src/components/off-canvas-editor/test/utils.js +50 -0
  582. package/src/components/off-canvas-editor/update-attributes.js +99 -0
  583. package/src/components/off-canvas-editor/use-block-selection.js +169 -0
  584. package/src/components/off-canvas-editor/use-list-view-client-ids.js +29 -0
  585. package/src/components/off-canvas-editor/use-list-view-drop-zone.js +260 -0
  586. package/src/components/off-canvas-editor/use-list-view-expand-selected-item.js +58 -0
  587. package/src/components/off-canvas-editor/utils.js +58 -0
  588. package/src/components/plain-text/{style.scss → content.scss} +0 -0
  589. package/src/components/recursion-provider/test/index.js +27 -29
  590. package/src/components/responsive-block-control/test/index.js +69 -92
  591. package/src/components/rich-text/content.scss +42 -0
  592. package/src/components/rich-text/format-toolbar/index.js +6 -4
  593. package/src/components/rich-text/index.js +2 -2
  594. package/src/components/rich-text/index.native.js +0 -2
  595. package/src/components/rich-text/style.scss +0 -43
  596. package/src/components/rich-text/use-insert-replacement-text.js +31 -0
  597. package/src/components/rich-text/use-undo-automatic-change.js +7 -1
  598. package/src/components/rich-text/utils.js +2 -21
  599. package/src/components/spacing-sizes-control/spacing-input-control.js +9 -0
  600. package/src/components/ungroup-button/index.native.js +6 -2
  601. package/src/components/url-input/index.js +57 -73
  602. package/src/components/url-popover/README.md +12 -3
  603. package/src/components/url-popover/index.js +33 -3
  604. package/src/components/url-popover/test/__snapshots__/index.js.snap +8 -6
  605. package/src/components/url-popover/test/index.js +21 -9
  606. package/src/components/use-block-display-information/index.js +14 -5
  607. package/src/components/use-setting/index.js +20 -2
  608. package/src/components/use-setting/test/index.js +99 -0
  609. package/src/content.scss +10 -0
  610. package/src/hooks/child-layout.js +190 -0
  611. package/src/hooks/color-panel.js +13 -1
  612. package/src/hooks/color.js +2 -0
  613. package/src/hooks/content-lock-ui.js +47 -35
  614. package/src/hooks/dimensions.js +119 -21
  615. package/src/hooks/layout.js +62 -3
  616. package/src/hooks/margin.js +4 -3
  617. package/src/hooks/min-height.js +104 -0
  618. package/src/hooks/padding.js +4 -3
  619. package/src/hooks/style.js +10 -2
  620. package/src/hooks/test/style.js +4 -0
  621. package/src/hooks/test/use-typography-props.js +1 -1
  622. package/src/layouts/flex.js +43 -38
  623. package/src/store/actions.js +22 -0
  624. package/src/store/reducer.js +480 -434
  625. package/src/store/selectors.js +70 -64
  626. package/src/store/test/actions.js +18 -0
  627. package/src/store/test/performance.js +71 -0
  628. package/src/store/test/reducer.js +662 -490
  629. package/src/store/test/selectors.js +1839 -1306
  630. package/src/style.scss +4 -7
  631. package/src/utils/sorting.js +54 -0
  632. package/src/utils/test/sorting.js +49 -0
  633. package/tsconfig.tsbuildinfo +1 -1
  634. package/build/components/block-preview/live.js +0 -30
  635. package/build/components/block-preview/live.js.map +0 -1
  636. package/build-module/components/block-preview/live.js +0 -20
  637. package/build-module/components/block-preview/live.js.map +0 -1
  638. package/src/components/block-preview/live.js +0 -19
@@ -1,7 +1,8 @@
1
1
  /**
2
2
  * External dependencies
3
3
  */
4
- import { reduce, omit, mapValues, isEqual, isEmpty } from 'lodash';
4
+ import fastDeepEqual from 'fast-deep-equal/es6';
5
+ import { omit, isEmpty } from 'lodash';
5
6
 
6
7
  /**
7
8
  * WordPress dependencies
@@ -28,16 +29,18 @@ const identity = ( x ) => x;
28
29
  * @return {Object} Block order map object.
29
30
  */
30
31
  function mapBlockOrder( blocks, rootClientId = '' ) {
31
- const result = { [ rootClientId ]: [] };
32
-
32
+ const result = new Map();
33
+ const current = [];
34
+ result.set( rootClientId, current );
33
35
  blocks.forEach( ( block ) => {
34
36
  const { clientId, innerBlocks } = block;
35
-
36
- result[ rootClientId ].push( clientId );
37
-
38
- Object.assign( result, mapBlockOrder( innerBlocks, clientId ) );
37
+ current.push( clientId );
38
+ mapBlockOrder( innerBlocks, clientId ).forEach(
39
+ ( order, subClientId ) => {
40
+ result.set( subClientId, order );
41
+ }
42
+ );
39
43
  } );
40
-
41
44
  return result;
42
45
  }
43
46
 
@@ -51,15 +54,18 @@ function mapBlockOrder( blocks, rootClientId = '' ) {
51
54
  * @return {Object} Block order map object.
52
55
  */
53
56
  function mapBlockParents( blocks, rootClientId = '' ) {
54
- return blocks.reduce(
55
- ( result, block ) =>
56
- Object.assign(
57
- result,
58
- { [ block.clientId ]: rootClientId },
59
- mapBlockParents( block.innerBlocks, block.clientId )
60
- ),
61
- {}
62
- );
57
+ const result = [];
58
+ const stack = [ [ rootClientId, blocks ] ];
59
+ while ( stack.length ) {
60
+ const [ parent, currentBlocks ] = stack.shift();
61
+ currentBlocks.forEach( ( { innerBlocks, ...block } ) => {
62
+ result.push( [ block.clientId, parent ] );
63
+ if ( innerBlocks?.length ) {
64
+ stack.push( [ block.clientId, innerBlocks ] );
65
+ }
66
+ } );
67
+ }
68
+ return result;
63
69
  }
64
70
 
65
71
  /**
@@ -70,16 +76,28 @@ function mapBlockParents( blocks, rootClientId = '' ) {
70
76
  * @param {Array} blocks Blocks to flatten.
71
77
  * @param {Function} transform Transforming function to be applied to each block.
72
78
  *
73
- * @return {Object} Flattened object.
79
+ * @return {Array} Flattened object.
74
80
  */
75
81
  function flattenBlocks( blocks, transform = identity ) {
76
- const result = {};
82
+ const result = [];
77
83
 
78
84
  const stack = [ ...blocks ];
79
85
  while ( stack.length ) {
80
86
  const { innerBlocks, ...block } = stack.shift();
81
87
  stack.push( ...innerBlocks );
82
- result[ block.clientId ] = transform( block );
88
+ result.push( [ block.clientId, transform( block ) ] );
89
+ }
90
+
91
+ return result;
92
+ }
93
+
94
+ function getFlattenedClientIds( blocks ) {
95
+ const result = {};
96
+ const stack = [ ...blocks ];
97
+ while ( stack.length ) {
98
+ const { innerBlocks, ...block } = stack.shift();
99
+ stack.push( ...innerBlocks );
100
+ result[ block.clientId ] = true;
83
101
  }
84
102
 
85
103
  return result;
@@ -92,7 +110,7 @@ function flattenBlocks( blocks, transform = identity ) {
92
110
  *
93
111
  * @param {Array} blocks Blocks to flatten.
94
112
  *
95
- * @return {Object} Flattened block attributes object.
113
+ * @return {Array} Flattened block attributes object.
96
114
  */
97
115
  function getFlattenedBlocksWithoutAttributes( blocks ) {
98
116
  return flattenBlocks( blocks, ( block ) => omit( block, 'attributes' ) );
@@ -105,29 +123,12 @@ function getFlattenedBlocksWithoutAttributes( blocks ) {
105
123
  *
106
124
  * @param {Array} blocks Blocks to flatten.
107
125
  *
108
- * @return {Object} Flattened block attributes object.
126
+ * @return {Array} Flattened block attributes object.
109
127
  */
110
128
  function getFlattenedBlockAttributes( blocks ) {
111
129
  return flattenBlocks( blocks, ( block ) => block.attributes );
112
130
  }
113
131
 
114
- /**
115
- * Returns an object against which it is safe to perform mutating operations,
116
- * given the original object and its current working copy.
117
- *
118
- * @param {Object} original Original object.
119
- * @param {Object} working Working object.
120
- *
121
- * @return {Object} Mutation-safe object.
122
- */
123
- function getMutateSafeObject( original, working ) {
124
- if ( original === working ) {
125
- return { ...original };
126
- }
127
-
128
- return working;
129
- }
130
-
131
132
  /**
132
133
  * Returns true if the two object arguments have the same keys, or false
133
134
  * otherwise.
@@ -138,7 +139,7 @@ function getMutateSafeObject( original, working ) {
138
139
  * @return {boolean} Whether the two objects have the same keys.
139
140
  */
140
141
  export function hasSameKeys( a, b ) {
141
- return isEqual( Object.keys( a ), Object.keys( b ) );
142
+ return fastDeepEqual( Object.keys( a ), Object.keys( b ) );
142
143
  }
143
144
 
144
145
  /**
@@ -156,13 +157,13 @@ export function isUpdatingSameBlockAttribute( action, lastAction ) {
156
157
  action.type === 'UPDATE_BLOCK_ATTRIBUTES' &&
157
158
  lastAction !== undefined &&
158
159
  lastAction.type === 'UPDATE_BLOCK_ATTRIBUTES' &&
159
- isEqual( action.clientIds, lastAction.clientIds ) &&
160
+ fastDeepEqual( action.clientIds, lastAction.clientIds ) &&
160
161
  hasSameKeys( action.attributes, lastAction.attributes )
161
162
  );
162
163
  }
163
164
 
164
- function buildBlockTree( state, blocks ) {
165
- const result = {};
165
+ function updateBlockTreeForBlocks( state, blocks ) {
166
+ const treeToUpdate = state.tree;
166
167
  const stack = [ ...blocks ];
167
168
  const flattenedBlocks = [ ...blocks ];
168
169
  while ( stack.length ) {
@@ -172,33 +173,34 @@ function buildBlockTree( state, blocks ) {
172
173
  }
173
174
  // Create objects before mutating them, that way it's always defined.
174
175
  for ( const block of flattenedBlocks ) {
175
- result[ block.clientId ] = {};
176
+ treeToUpdate.set( block.clientId, {} );
176
177
  }
177
178
  for ( const block of flattenedBlocks ) {
178
- result[ block.clientId ] = Object.assign( result[ block.clientId ], {
179
- ...state.byClientId[ block.clientId ],
180
- attributes: state.attributes[ block.clientId ],
181
- innerBlocks: block.innerBlocks.map(
182
- ( subBlock ) => result[ subBlock.clientId ]
183
- ),
184
- } );
179
+ treeToUpdate.set(
180
+ block.clientId,
181
+ Object.assign( treeToUpdate.get( block.clientId ), {
182
+ ...state.byClientId.get( block.clientId ),
183
+ attributes: state.attributes.get( block.clientId ),
184
+ innerBlocks: block.innerBlocks.map( ( subBlock ) =>
185
+ treeToUpdate.get( subBlock.clientId )
186
+ ),
187
+ } )
188
+ );
185
189
  }
186
-
187
- return result;
188
190
  }
189
191
 
190
192
  function updateParentInnerBlocksInTree(
191
193
  state,
192
- tree,
193
194
  updatedClientIds,
194
195
  updateChildrenOfUpdatedClientIds = false
195
196
  ) {
197
+ const treeToUpdate = state.tree;
196
198
  const uncontrolledParents = new Set( [] );
197
199
  const controlledParents = new Set();
198
200
  for ( const clientId of updatedClientIds ) {
199
201
  let current = updateChildrenOfUpdatedClientIds
200
202
  ? clientId
201
- : state.parents[ clientId ];
203
+ : state.parents.get( clientId );
202
204
  do {
203
205
  if ( state.controlledInnerBlocks[ current ] ) {
204
206
  // Should stop on controlled blocks.
@@ -208,7 +210,7 @@ function updateParentInnerBlocksInTree(
208
210
  } else {
209
211
  // Else continue traversing up through parents.
210
212
  uncontrolledParents.add( current );
211
- current = state.parents[ current ];
213
+ current = state.parents.get( current );
212
214
  }
213
215
  } while ( current !== undefined );
214
216
  }
@@ -216,27 +218,23 @@ function updateParentInnerBlocksInTree(
216
218
  // To make sure the order of assignments doesn't matter,
217
219
  // we first create empty objects and mutates the inner blocks later.
218
220
  for ( const clientId of uncontrolledParents ) {
219
- tree[ clientId ] = {
220
- ...tree[ clientId ],
221
- };
221
+ treeToUpdate.set( clientId, { ...treeToUpdate.get( clientId ) } );
222
222
  }
223
223
  for ( const clientId of uncontrolledParents ) {
224
- tree[ clientId ].innerBlocks = ( state.order[ clientId ] || [] ).map(
225
- ( subClientId ) => tree[ subClientId ]
226
- );
224
+ treeToUpdate.get( clientId ).innerBlocks = (
225
+ state.order.get( clientId ) || []
226
+ ).map( ( subClientId ) => treeToUpdate.get( subClientId ) );
227
227
  }
228
228
 
229
229
  // Controlled parent blocks, need a dedicated key for their inner blocks
230
230
  // to be used when doing getBlocks( controlledBlockClientId ).
231
231
  for ( const clientId of controlledParents ) {
232
- tree[ 'controlled||' + clientId ] = {
233
- innerBlocks: ( state.order[ clientId ] || [] ).map(
234
- ( subClientId ) => tree[ subClientId ]
232
+ treeToUpdate.set( 'controlled||' + clientId, {
233
+ innerBlocks: ( state.order.get( clientId ) || [] ).map(
234
+ ( subClientId ) => treeToUpdate.get( subClientId )
235
235
  ),
236
- };
236
+ } );
237
237
  }
238
-
239
- return tree;
240
238
  }
241
239
 
242
240
  /**
@@ -257,82 +255,70 @@ const withBlockTree =
257
255
  return state;
258
256
  }
259
257
 
260
- newState.tree = state.tree ? state.tree : {};
258
+ newState.tree = state.tree ? state.tree : new Map();
261
259
  switch ( action.type ) {
262
260
  case 'RECEIVE_BLOCKS':
263
261
  case 'INSERT_BLOCKS': {
264
- const subTree = buildBlockTree( newState, action.blocks );
265
- newState.tree = updateParentInnerBlocksInTree(
262
+ newState.tree = new Map( newState.tree );
263
+ updateBlockTreeForBlocks( newState, action.blocks );
264
+ updateParentInnerBlocksInTree(
266
265
  newState,
267
- {
268
- ...newState.tree,
269
- ...subTree,
270
- },
271
266
  action.rootClientId ? [ action.rootClientId ] : [ '' ],
272
267
  true
273
268
  );
274
269
  break;
275
270
  }
276
271
  case 'UPDATE_BLOCK':
277
- newState.tree = updateParentInnerBlocksInTree(
272
+ newState.tree = new Map( newState.tree );
273
+ newState.tree.set( action.clientId, {
274
+ ...newState.tree.get( action.clientId ),
275
+ ...newState.byClientId.get( action.clientId ),
276
+ attributes: newState.attributes.get( action.clientId ),
277
+ } );
278
+ updateParentInnerBlocksInTree(
278
279
  newState,
279
- {
280
- ...newState.tree,
281
- [ action.clientId ]: {
282
- ...newState.tree[ action.clientId ],
283
- ...newState.byClientId[ action.clientId ],
284
- attributes: newState.attributes[ action.clientId ],
285
- },
286
- },
287
280
  [ action.clientId ],
288
281
  false
289
282
  );
290
283
  break;
291
284
  case 'UPDATE_BLOCK_ATTRIBUTES': {
292
- const newSubTree = action.clientIds.reduce(
293
- ( result, clientId ) => {
294
- result[ clientId ] = {
295
- ...newState.tree[ clientId ],
296
- attributes: newState.attributes[ clientId ],
297
- };
298
- return result;
299
- },
300
- {}
301
- );
302
- newState.tree = updateParentInnerBlocksInTree(
285
+ newState.tree = new Map( newState.tree );
286
+ action.clientIds.forEach( ( clientId ) => {
287
+ newState.tree.set( clientId, {
288
+ ...newState.tree.get( clientId ),
289
+ attributes: newState.attributes.get( clientId ),
290
+ } );
291
+ } );
292
+ updateParentInnerBlocksInTree(
303
293
  newState,
304
- {
305
- ...newState.tree,
306
- ...newSubTree,
307
- },
308
294
  action.clientIds,
309
295
  false
310
296
  );
311
297
  break;
312
298
  }
313
299
  case 'REPLACE_BLOCKS_AUGMENTED_WITH_CHILDREN': {
314
- const subTree = buildBlockTree( newState, action.blocks );
315
- newState.tree = updateParentInnerBlocksInTree(
316
- newState,
317
- {
318
- ...omit(
319
- newState.tree,
320
- action.replacedClientIds.concat(
321
- // Controlled inner blocks are only removed
322
- // if the block doesn't move to another position
323
- // otherwise their content will be lost.
324
- action.replacedClientIds
325
- .filter(
326
- ( clientId ) => ! subTree[ clientId ]
327
- )
328
- .map(
329
- ( clientId ) =>
330
- 'controlled||' + clientId
331
- )
300
+ const inserterClientIds = getFlattenedClientIds(
301
+ action.blocks
302
+ );
303
+ newState.tree = new Map( newState.tree );
304
+ action.replacedClientIds
305
+ .concat(
306
+ // Controlled inner blocks are only removed
307
+ // if the block doesn't move to another position
308
+ // otherwise their content will be lost.
309
+ action.replacedClientIds
310
+ .filter(
311
+ ( clientId ) => ! inserterClientIds[ clientId ]
332
312
  )
333
- ),
334
- ...subTree,
335
- },
313
+ .map( ( clientId ) => 'controlled||' + clientId )
314
+ )
315
+ .forEach( ( key ) => {
316
+ newState.tree.delete( key );
317
+ } );
318
+
319
+ updateBlockTreeForBlocks( newState, action.blocks );
320
+ updateParentInnerBlocksInTree(
321
+ newState,
336
322
  action.blocks.map( ( b ) => b.clientId ),
337
323
  false
338
324
  );
@@ -341,18 +327,19 @@ const withBlockTree =
341
327
  const parentsOfRemovedBlocks = [];
342
328
  for ( const clientId of action.clientIds ) {
343
329
  if (
344
- state.parents[ clientId ] !== undefined &&
345
- ( state.parents[ clientId ] === '' ||
346
- newState.byClientId[ state.parents[ clientId ] ] )
330
+ state.parents.get( clientId ) !== undefined &&
331
+ ( state.parents.get( clientId ) === '' ||
332
+ newState.byClientId.get(
333
+ state.parents.get( clientId )
334
+ ) )
347
335
  ) {
348
336
  parentsOfRemovedBlocks.push(
349
- state.parents[ clientId ]
337
+ state.parents.get( clientId )
350
338
  );
351
339
  }
352
340
  }
353
- newState.tree = updateParentInnerBlocksInTree(
341
+ updateParentInnerBlocksInTree(
354
342
  newState,
355
- newState.tree,
356
343
  parentsOfRemovedBlocks,
357
344
  true
358
345
  );
@@ -362,25 +349,29 @@ const withBlockTree =
362
349
  const parentsOfRemovedBlocks = [];
363
350
  for ( const clientId of action.clientIds ) {
364
351
  if (
365
- state.parents[ clientId ] !== undefined &&
366
- ( state.parents[ clientId ] === '' ||
367
- newState.byClientId[ state.parents[ clientId ] ] )
352
+ state.parents.get( clientId ) !== undefined &&
353
+ ( state.parents.get( clientId ) === '' ||
354
+ newState.byClientId.get(
355
+ state.parents.get( clientId )
356
+ ) )
368
357
  ) {
369
358
  parentsOfRemovedBlocks.push(
370
- state.parents[ clientId ]
359
+ state.parents.get( clientId )
371
360
  );
372
361
  }
373
362
  }
374
- newState.tree = updateParentInnerBlocksInTree(
375
- newState,
376
- omit(
377
- newState.tree,
378
- action.removedClientIds.concat(
379
- action.removedClientIds.map(
380
- ( clientId ) => 'controlled||' + clientId
381
- )
363
+ newState.tree = new Map( newState.tree );
364
+ action.removedClientIds
365
+ .concat(
366
+ action.removedClientIds.map(
367
+ ( clientId ) => 'controlled||' + clientId
382
368
  )
383
- ),
369
+ )
370
+ .forEach( ( key ) => {
371
+ newState.tree.delete( key );
372
+ } );
373
+ updateParentInnerBlocksInTree(
374
+ newState,
384
375
  parentsOfRemovedBlocks,
385
376
  true
386
377
  );
@@ -395,9 +386,9 @@ const withBlockTree =
395
386
  if ( action.toRootClientId ) {
396
387
  updatedBlockUids.push( action.toRootClientId );
397
388
  }
398
- newState.tree = updateParentInnerBlocksInTree(
389
+ newState.tree = new Map( newState.tree );
390
+ updateParentInnerBlocksInTree(
399
391
  newState,
400
- newState.tree,
401
392
  updatedBlockUids,
402
393
  true
403
394
  );
@@ -408,39 +399,35 @@ const withBlockTree =
408
399
  const updatedBlockUids = [
409
400
  action.rootClientId ? action.rootClientId : '',
410
401
  ];
411
- newState.tree = updateParentInnerBlocksInTree(
402
+ newState.tree = new Map( newState.tree );
403
+ updateParentInnerBlocksInTree(
412
404
  newState,
413
- newState.tree,
414
405
  updatedBlockUids,
415
406
  true
416
407
  );
417
408
  break;
418
409
  }
419
410
  case 'SAVE_REUSABLE_BLOCK_SUCCESS': {
420
- const updatedBlockUids = Object.entries( newState.attributes )
421
- .filter( ( [ clientId, attributes ] ) => {
422
- return (
423
- newState.byClientId[ clientId ].name ===
424
- 'core/block' &&
425
- attributes.ref === action.updatedId
426
- );
427
- } )
428
- .map( ( [ clientId ] ) => clientId );
429
-
430
- newState.tree = updateParentInnerBlocksInTree(
411
+ const updatedBlockUids = [];
412
+ newState.attributes.forEach( ( attributes, clientId ) => {
413
+ if (
414
+ newState.byClientId.get( clientId ).name ===
415
+ 'core/block' &&
416
+ attributes.ref === action.updatedId
417
+ ) {
418
+ updatedBlockUids.push( clientId );
419
+ }
420
+ } );
421
+ newState.tree = new Map( newState.tree );
422
+ updatedBlockUids.forEach( ( clientId ) => {
423
+ newState.tree.set( clientId, {
424
+ ...newState.byClientId.get( clientId ),
425
+ attributes: newState.attributes.get( clientId ),
426
+ innerBlocks: newState.tree.get( clientId ).innerBlocks,
427
+ } );
428
+ } );
429
+ updateParentInnerBlocksInTree(
431
430
  newState,
432
- {
433
- ...newState.tree,
434
- ...updatedBlockUids.reduce( ( result, clientId ) => {
435
- result[ clientId ] = {
436
- ...newState.byClientId[ clientId ],
437
- attributes: newState.attributes[ clientId ],
438
- innerBlocks:
439
- newState.tree[ clientId ].innerBlocks,
440
- };
441
- return result;
442
- }, {} ),
443
- },
444
431
  updatedBlockUids,
445
432
  false
446
433
  );
@@ -549,7 +536,7 @@ const withInnerBlocksRemoveCascade = ( reducer ) => ( state, action ) => {
549
536
  let result = clientIds;
550
537
  for ( let i = 0; i < result.length; i++ ) {
551
538
  if (
552
- ! state.order[ result[ i ] ] ||
539
+ ! state.order.get( result[ i ] ) ||
553
540
  ( action.keepControlledInnerBlocks &&
554
541
  action.keepControlledInnerBlocks[ result[ i ] ] )
555
542
  ) {
@@ -560,7 +547,7 @@ const withInnerBlocksRemoveCascade = ( reducer ) => ( state, action ) => {
560
547
  result = [ ...result ];
561
548
  }
562
549
 
563
- result.push( ...state.order[ result[ i ] ] );
550
+ result.push( ...state.order.get( result[ i ] ) );
564
551
  }
565
552
  return result;
566
553
  };
@@ -601,23 +588,22 @@ const withBlockReset = ( reducer ) => ( state, action ) => {
601
588
  if ( action.type === 'RESET_BLOCKS' ) {
602
589
  const newState = {
603
590
  ...state,
604
- byClientId: getFlattenedBlocksWithoutAttributes( action.blocks ),
605
- attributes: getFlattenedBlockAttributes( action.blocks ),
591
+ byClientId: new Map(
592
+ getFlattenedBlocksWithoutAttributes( action.blocks )
593
+ ),
594
+ attributes: new Map( getFlattenedBlockAttributes( action.blocks ) ),
606
595
  order: mapBlockOrder( action.blocks ),
607
- parents: mapBlockParents( action.blocks ),
596
+ parents: new Map( mapBlockParents( action.blocks ) ),
608
597
  controlledInnerBlocks: {},
609
598
  };
610
599
 
611
- const subTree = buildBlockTree( newState, action.blocks );
612
- newState.tree = {
613
- ...subTree,
614
- // Root.
615
- '': {
616
- innerBlocks: action.blocks.map(
617
- ( subBlock ) => subTree[ subBlock.clientId ]
618
- ),
619
- },
620
- };
600
+ newState.tree = new Map( state?.tree );
601
+ updateBlockTreeForBlocks( newState, action.blocks );
602
+ newState.tree.set( '', {
603
+ innerBlocks: action.blocks.map( ( subBlock ) =>
604
+ newState.tree.get( subBlock.clientId )
605
+ ),
606
+ } );
621
607
 
622
608
  return newState;
623
609
  }
@@ -663,11 +649,11 @@ const withReplaceInnerBlocks = ( reducer ) => ( state, action ) => {
663
649
  // marked block in the block state so that they can be reattached to the
664
650
  // marked block when we re-insert everything a few lines below.
665
651
  let stateAfterBlocksRemoval = state;
666
- if ( state.order[ action.rootClientId ] ) {
652
+ if ( state.order.get( action.rootClientId ) ) {
667
653
  stateAfterBlocksRemoval = reducer( stateAfterBlocksRemoval, {
668
654
  type: 'REMOVE_BLOCKS',
669
655
  keepControlledInnerBlocks: nestedControllers,
670
- clientIds: state.order[ action.rootClientId ],
656
+ clientIds: state.order.get( action.rootClientId ),
671
657
  } );
672
658
  }
673
659
  let stateAfterInsert = stateAfterBlocksRemoval;
@@ -681,33 +667,20 @@ const withReplaceInnerBlocks = ( reducer ) => ( state, action ) => {
681
667
  // We need to re-attach the controlled inner blocks to the blocks tree and
682
668
  // preserve their block order. Otherwise, an inner block controller's blocks
683
669
  // will be deleted entirely from its entity.
684
- stateAfterInsert.order = {
685
- ...stateAfterInsert.order,
686
- ...reduce(
687
- nestedControllers,
688
- ( result, value, key ) => {
689
- if ( state.order[ key ] ) {
690
- result[ key ] = state.order[ key ];
691
- }
692
- return result;
693
- },
694
- {}
695
- ),
696
- };
697
- stateAfterInsert.tree = {
698
- ...stateAfterInsert.tree,
699
- ...reduce(
700
- nestedControllers,
701
- ( result, value, _key ) => {
702
- const key = `controlled||${ _key }`;
703
- if ( state.tree[ key ] ) {
704
- result[ key ] = state.tree[ key ];
705
- }
706
- return result;
707
- },
708
- {}
709
- ),
710
- };
670
+ const stateAfterInsertOrder = new Map( stateAfterInsert.order );
671
+ Object.keys( nestedControllers ).forEach( ( key ) => {
672
+ if ( state.order.get( key ) ) {
673
+ stateAfterInsertOrder.set( key, state.order.get( key ) );
674
+ }
675
+ } );
676
+ stateAfterInsert.order = stateAfterInsertOrder;
677
+ stateAfterInsert.tree = new Map( stateAfterInsert.tree );
678
+ Object.keys( nestedControllers ).forEach( ( _key ) => {
679
+ const key = `controlled||${ _key }`;
680
+ if ( state.tree.has( key ) ) {
681
+ stateAfterInsert.tree.set( key, state.tree.get( key ) );
682
+ }
683
+ } );
711
684
  }
712
685
  return stateAfterInsert;
713
686
  };
@@ -732,21 +705,16 @@ const withSaveReusableBlock = ( reducer ) => ( state, action ) => {
732
705
  }
733
706
 
734
707
  state = { ...state };
735
-
736
- state.attributes = mapValues(
737
- state.attributes,
738
- ( attributes, clientId ) => {
739
- const { name } = state.byClientId[ clientId ];
740
- if ( name === 'core/block' && attributes.ref === id ) {
741
- return {
742
- ...attributes,
743
- ref: updatedId,
744
- };
745
- }
746
-
747
- return attributes;
708
+ state.attributes = new Map( state.attributes );
709
+ state.attributes.forEach( ( attributes, clientId ) => {
710
+ const { name } = state.byClientId.get( clientId );
711
+ if ( name === 'core/block' && attributes.ref === id ) {
712
+ state.attributes.set( clientId, {
713
+ ...attributes,
714
+ ref: updatedId,
715
+ } );
748
716
  }
749
- );
717
+ } );
750
718
  }
751
719
 
752
720
  return reducer( state, action );
@@ -792,18 +760,24 @@ export const blocks = pipe(
792
760
  withIgnoredBlockChange,
793
761
  withResetControlledBlocks
794
762
  )( {
795
- byClientId( state = {}, action ) {
763
+ // The state is using a Map instead of a plain object for performance reasons.
764
+ // You can run the "./test/performance.js" unit test to check the impact
765
+ // code changes can have on this reducer.
766
+ byClientId( state = new Map(), action ) {
796
767
  switch ( action.type ) {
797
768
  case 'RECEIVE_BLOCKS':
798
- case 'INSERT_BLOCKS':
799
- return {
800
- ...state,
801
- ...getFlattenedBlocksWithoutAttributes( action.blocks ),
802
- };
803
-
804
- case 'UPDATE_BLOCK':
769
+ case 'INSERT_BLOCKS': {
770
+ const newState = new Map( state );
771
+ getFlattenedBlocksWithoutAttributes( action.blocks ).forEach(
772
+ ( [ key, value ] ) => {
773
+ newState.set( key, value );
774
+ }
775
+ );
776
+ return newState;
777
+ }
778
+ case 'UPDATE_BLOCK': {
805
779
  // Ignore updates if block isn't known.
806
- if ( ! state[ action.clientId ] ) {
780
+ if ( ! state.has( action.clientId ) ) {
807
781
  return state;
808
782
  }
809
783
 
@@ -813,144 +787,184 @@ export const blocks = pipe(
813
787
  return state;
814
788
  }
815
789
 
816
- return {
817
- ...state,
818
- [ action.clientId ]: {
819
- ...state[ action.clientId ],
820
- ...changes,
821
- },
822
- };
790
+ const newState = new Map( state );
791
+ newState.set( action.clientId, {
792
+ ...state.get( action.clientId ),
793
+ ...changes,
794
+ } );
795
+ return newState;
796
+ }
823
797
 
824
- case 'REPLACE_BLOCKS_AUGMENTED_WITH_CHILDREN':
798
+ case 'REPLACE_BLOCKS_AUGMENTED_WITH_CHILDREN': {
825
799
  if ( ! action.blocks ) {
826
800
  return state;
827
801
  }
828
802
 
829
- return {
830
- ...omit( state, action.replacedClientIds ),
831
- ...getFlattenedBlocksWithoutAttributes( action.blocks ),
832
- };
803
+ const newState = new Map( state );
804
+ action.replacedClientIds.forEach( ( clientId ) => {
805
+ newState.delete( clientId );
806
+ } );
833
807
 
834
- case 'REMOVE_BLOCKS_AUGMENTED_WITH_CHILDREN':
835
- return omit( state, action.removedClientIds );
808
+ getFlattenedBlocksWithoutAttributes( action.blocks ).forEach(
809
+ ( [ key, value ] ) => {
810
+ newState.set( key, value );
811
+ }
812
+ );
813
+ return newState;
814
+ }
815
+
816
+ case 'REMOVE_BLOCKS_AUGMENTED_WITH_CHILDREN': {
817
+ const newState = new Map( state );
818
+ action.removedClientIds.forEach( ( clientId ) => {
819
+ newState.delete( clientId );
820
+ } );
821
+ return newState;
822
+ }
836
823
  }
837
824
 
838
825
  return state;
839
826
  },
840
827
 
841
- attributes( state = {}, action ) {
828
+ // The state is using a Map instead of a plain object for performance reasons.
829
+ // You can run the "./test/performance.js" unit test to check the impact
830
+ // code changes can have on this reducer.
831
+ attributes( state = new Map(), action ) {
842
832
  switch ( action.type ) {
843
833
  case 'RECEIVE_BLOCKS':
844
- case 'INSERT_BLOCKS':
845
- return {
846
- ...state,
847
- ...getFlattenedBlockAttributes( action.blocks ),
848
- };
834
+ case 'INSERT_BLOCKS': {
835
+ const newState = new Map( state );
836
+ getFlattenedBlockAttributes( action.blocks ).forEach(
837
+ ( [ key, value ] ) => {
838
+ newState.set( key, value );
839
+ }
840
+ );
841
+ return newState;
842
+ }
849
843
 
850
- case 'UPDATE_BLOCK':
844
+ case 'UPDATE_BLOCK': {
851
845
  // Ignore updates if block isn't known or there are no attribute changes.
852
846
  if (
853
- ! state[ action.clientId ] ||
847
+ ! state.get( action.clientId ) ||
854
848
  ! action.updates.attributes
855
849
  ) {
856
850
  return state;
857
851
  }
858
852
 
859
- return {
860
- ...state,
861
- [ action.clientId ]: {
862
- ...state[ action.clientId ],
863
- ...action.updates.attributes,
864
- },
865
- };
853
+ const newState = new Map( state );
854
+ newState.set( action.clientId, {
855
+ ...state.get( action.clientId ),
856
+ ...action.updates.attributes,
857
+ } );
858
+ return newState;
859
+ }
866
860
 
867
861
  case 'UPDATE_BLOCK_ATTRIBUTES': {
868
862
  // Avoid a state change if none of the block IDs are known.
869
- if ( action.clientIds.every( ( id ) => ! state[ id ] ) ) {
863
+ if ( action.clientIds.every( ( id ) => ! state.get( id ) ) ) {
870
864
  return state;
871
865
  }
872
866
 
873
- const next = action.clientIds.reduce(
874
- ( accumulator, id ) => ( {
875
- ...accumulator,
876
- [ id ]: reduce(
877
- action.uniqueByBlock
878
- ? action.attributes[ id ]
879
- : action.attributes,
880
- ( result, value, key ) => {
881
- // Consider as updates only changed values.
882
- if ( value !== result[ key ] ) {
883
- result = getMutateSafeObject(
884
- state[ id ],
885
- result
886
- );
887
- result[ key ] = value;
888
- }
889
-
890
- return result;
891
- },
892
- state[ id ]
893
- ),
894
- } ),
895
- {}
896
- );
897
-
898
- if (
899
- action.clientIds.every(
900
- ( id ) => next[ id ] === state[ id ]
901
- )
902
- ) {
903
- return state;
867
+ let hasChange = false;
868
+ const newState = new Map( state );
869
+ for ( const clientId of action.clientIds ) {
870
+ const updatedAttributeEntries = Object.entries(
871
+ action.uniqueByBlock
872
+ ? action.attributes[ clientId ]
873
+ : action.attributes ?? {}
874
+ );
875
+ if ( updatedAttributeEntries.length === 0 ) {
876
+ continue;
877
+ }
878
+ let hasUpdatedAttributes = false;
879
+ const existingAttributes = state.get( clientId );
880
+ const newAttributes = {};
881
+ updatedAttributeEntries.forEach( ( [ key, value ] ) => {
882
+ if ( existingAttributes[ key ] !== value ) {
883
+ hasUpdatedAttributes = true;
884
+ newAttributes[ key ] = value;
885
+ }
886
+ } );
887
+ hasChange = hasChange || hasUpdatedAttributes;
888
+ if ( hasUpdatedAttributes ) {
889
+ newState.set( clientId, {
890
+ ...existingAttributes,
891
+ ...newAttributes,
892
+ } );
893
+ }
904
894
  }
905
895
 
906
- return { ...state, ...next };
896
+ return hasChange ? newState : state;
907
897
  }
908
898
 
909
- case 'REPLACE_BLOCKS_AUGMENTED_WITH_CHILDREN':
899
+ case 'REPLACE_BLOCKS_AUGMENTED_WITH_CHILDREN': {
910
900
  if ( ! action.blocks ) {
911
901
  return state;
912
902
  }
913
903
 
914
- return {
915
- ...omit( state, action.replacedClientIds ),
916
- ...getFlattenedBlockAttributes( action.blocks ),
917
- };
904
+ const newState = new Map( state );
905
+ action.replacedClientIds.forEach( ( clientId ) => {
906
+ newState.delete( clientId );
907
+ } );
908
+ getFlattenedBlockAttributes( action.blocks ).forEach(
909
+ ( [ key, value ] ) => {
910
+ newState.set( key, value );
911
+ }
912
+ );
913
+ return newState;
914
+ }
918
915
 
919
- case 'REMOVE_BLOCKS_AUGMENTED_WITH_CHILDREN':
920
- return omit( state, action.removedClientIds );
916
+ case 'REMOVE_BLOCKS_AUGMENTED_WITH_CHILDREN': {
917
+ const newState = new Map( state );
918
+ action.removedClientIds.forEach( ( clientId ) => {
919
+ newState.delete( clientId );
920
+ } );
921
+ return newState;
922
+ }
921
923
  }
922
924
 
923
925
  return state;
924
926
  },
925
927
 
926
- order( state = {}, action ) {
928
+ // The state is using a Map instead of a plain object for performance reasons.
929
+ // You can run the "./test/performance.js" unit test to check the impact
930
+ // code changes can have on this reducer.
931
+ order( state = new Map(), action ) {
927
932
  switch ( action.type ) {
928
933
  case 'RECEIVE_BLOCKS': {
929
934
  const blockOrder = mapBlockOrder( action.blocks );
930
- return {
931
- ...state,
932
- ...omit( blockOrder, '' ),
933
- '': ( state?.[ '' ] || [] ).concat( blockOrder[ '' ] ),
934
- };
935
+ const newState = new Map( state );
936
+ blockOrder.forEach( ( order, clientId ) => {
937
+ if ( clientId !== '' ) {
938
+ newState.set( clientId, order );
939
+ }
940
+ } );
941
+ newState.set(
942
+ '',
943
+ ( state.get( '' ) ?? [] ).concat( blockOrder[ '' ] )
944
+ );
945
+ return newState;
935
946
  }
936
947
  case 'INSERT_BLOCKS': {
937
948
  const { rootClientId = '' } = action;
938
- const subState = state[ rootClientId ] || [];
949
+ const subState = state.get( rootClientId ) || [];
939
950
  const mappedBlocks = mapBlockOrder(
940
951
  action.blocks,
941
952
  rootClientId
942
953
  );
943
954
  const { index = subState.length } = action;
944
-
945
- return {
946
- ...state,
947
- ...mappedBlocks,
948
- [ rootClientId ]: insertAt(
955
+ const newState = new Map( state );
956
+ mappedBlocks.forEach( ( order, clientId ) => {
957
+ newState.set( clientId, order );
958
+ } );
959
+ newState.set(
960
+ rootClientId,
961
+ insertAt(
949
962
  subState,
950
- mappedBlocks[ rootClientId ],
963
+ mappedBlocks.get( rootClientId ),
951
964
  index
952
- ),
953
- };
965
+ )
966
+ );
967
+ return newState;
954
968
  }
955
969
 
956
970
  case 'MOVE_BLOCKS_TO_POSITION': {
@@ -959,65 +973,68 @@ export const blocks = pipe(
959
973
  toRootClientId = '',
960
974
  clientIds,
961
975
  } = action;
962
- const { index = state[ toRootClientId ].length } = action;
976
+ const { index = state.get( toRootClientId ).length } = action;
963
977
 
964
978
  // Moving inside the same parent block.
965
979
  if ( fromRootClientId === toRootClientId ) {
966
- const subState = state[ toRootClientId ];
980
+ const subState = state.get( toRootClientId );
967
981
  const fromIndex = subState.indexOf( clientIds[ 0 ] );
968
- return {
969
- ...state,
970
- [ toRootClientId ]: moveTo(
971
- state[ toRootClientId ],
982
+ const newState = new Map( state );
983
+ newState.set(
984
+ toRootClientId,
985
+ moveTo(
986
+ state.get( toRootClientId ),
972
987
  fromIndex,
973
988
  index,
974
989
  clientIds.length
975
- ),
976
- };
990
+ )
991
+ );
992
+ return newState;
977
993
  }
978
994
 
979
995
  // Moving from a parent block to another.
980
- return {
981
- ...state,
982
- [ fromRootClientId ]:
983
- state[ fromRootClientId ]?.filter(
984
- ( id ) => ! clientIds.includes( id )
985
- ) ?? [],
986
- [ toRootClientId ]: insertAt(
987
- state[ toRootClientId ],
988
- clientIds,
989
- index
990
- ),
991
- };
996
+ const newState = new Map( state );
997
+ newState.set(
998
+ fromRootClientId,
999
+ state
1000
+ .get( fromRootClientId )
1001
+ ?.filter( ( id ) => ! clientIds.includes( id ) ) ?? []
1002
+ );
1003
+ newState.set(
1004
+ toRootClientId,
1005
+ insertAt( state.get( toRootClientId ), clientIds, index )
1006
+ );
1007
+ return newState;
992
1008
  }
993
1009
 
994
1010
  case 'MOVE_BLOCKS_UP': {
995
1011
  const { clientIds, rootClientId = '' } = action;
996
1012
  const firstClientId = clientIds[ 0 ];
997
- const subState = state[ rootClientId ];
1013
+ const subState = state.get( rootClientId );
998
1014
 
999
1015
  if ( ! subState.length || firstClientId === subState[ 0 ] ) {
1000
1016
  return state;
1001
1017
  }
1002
1018
 
1003
1019
  const firstIndex = subState.indexOf( firstClientId );
1004
-
1005
- return {
1006
- ...state,
1007
- [ rootClientId ]: moveTo(
1020
+ const newState = new Map( state );
1021
+ newState.set(
1022
+ rootClientId,
1023
+ moveTo(
1008
1024
  subState,
1009
1025
  firstIndex,
1010
1026
  firstIndex - 1,
1011
1027
  clientIds.length
1012
- ),
1013
- };
1028
+ )
1029
+ );
1030
+ return newState;
1014
1031
  }
1015
1032
 
1016
1033
  case 'MOVE_BLOCKS_DOWN': {
1017
1034
  const { clientIds, rootClientId = '' } = action;
1018
1035
  const firstClientId = clientIds[ 0 ];
1019
1036
  const lastClientId = clientIds[ clientIds.length - 1 ];
1020
- const subState = state[ rootClientId ];
1037
+ const subState = state.get( rootClientId );
1021
1038
 
1022
1039
  if (
1023
1040
  ! subState.length ||
@@ -1027,16 +1044,17 @@ export const blocks = pipe(
1027
1044
  }
1028
1045
 
1029
1046
  const firstIndex = subState.indexOf( firstClientId );
1030
-
1031
- return {
1032
- ...state,
1033
- [ rootClientId ]: moveTo(
1047
+ const newState = new Map( state );
1048
+ newState.set(
1049
+ rootClientId,
1050
+ moveTo(
1034
1051
  subState,
1035
1052
  firstIndex,
1036
1053
  firstIndex + 1,
1037
1054
  clientIds.length
1038
- ),
1039
- };
1055
+ )
1056
+ );
1057
+ return newState;
1040
1058
  }
1041
1059
 
1042
1060
  case 'REPLACE_BLOCKS_AUGMENTED_WITH_CHILDREN': {
@@ -1046,56 +1064,52 @@ export const blocks = pipe(
1046
1064
  }
1047
1065
 
1048
1066
  const mappedBlocks = mapBlockOrder( action.blocks );
1067
+ const newState = new Map( state );
1068
+ action.replacedClientIds.forEach( ( clientId ) => {
1069
+ newState.delete( clientId );
1070
+ } );
1071
+ mappedBlocks.forEach( ( order, clientId ) => {
1072
+ if ( clientId !== '' ) {
1073
+ newState.set( clientId, order );
1074
+ }
1075
+ } );
1076
+ newState.forEach( ( order, clientId ) => {
1077
+ const newSubOrder = Object.values( order ).reduce(
1078
+ ( result, subClientId ) => {
1079
+ if ( subClientId === clientIds[ 0 ] ) {
1080
+ return [ ...result, ...mappedBlocks.get( '' ) ];
1081
+ }
1082
+
1083
+ if ( clientIds.indexOf( subClientId ) === -1 ) {
1084
+ result.push( subClientId );
1085
+ }
1049
1086
 
1050
- return pipe( [
1051
- ( nextState ) =>
1052
- omit( nextState, action.replacedClientIds ),
1053
- ( nextState ) => ( {
1054
- ...nextState,
1055
- ...omit( mappedBlocks, '' ),
1056
- } ),
1057
- ( nextState ) =>
1058
- mapValues( nextState, ( subState ) =>
1059
- reduce(
1060
- subState,
1061
- ( result, clientId ) => {
1062
- if ( clientId === clientIds[ 0 ] ) {
1063
- return [
1064
- ...result,
1065
- ...mappedBlocks[ '' ],
1066
- ];
1067
- }
1068
-
1069
- if (
1070
- clientIds.indexOf( clientId ) === -1
1071
- ) {
1072
- result.push( clientId );
1073
- }
1074
-
1075
- return result;
1076
- },
1077
- []
1078
- )
1079
- ),
1080
- ] )( state );
1087
+ return result;
1088
+ },
1089
+ []
1090
+ );
1091
+ newState.set( clientId, newSubOrder );
1092
+ } );
1093
+ return newState;
1081
1094
  }
1082
1095
 
1083
- case 'REMOVE_BLOCKS_AUGMENTED_WITH_CHILDREN':
1084
- return pipe( [
1085
- // Remove inner block ordering for removed blocks.
1086
- ( nextState ) => omit( nextState, action.removedClientIds ),
1087
-
1088
- // Remove deleted blocks from other blocks' orderings.
1089
- ( nextState ) =>
1090
- mapValues(
1091
- nextState,
1092
- ( subState ) =>
1093
- subState?.filter(
1094
- ( id ) =>
1095
- ! action.removedClientIds.includes( id )
1096
- ) ?? []
1097
- ),
1098
- ] )( state );
1096
+ case 'REMOVE_BLOCKS_AUGMENTED_WITH_CHILDREN': {
1097
+ const newState = new Map( state );
1098
+ // Remove inner block ordering for removed blocks.
1099
+ action.removedClientIds.forEach( ( clientId ) => {
1100
+ newState.delete( clientId );
1101
+ } );
1102
+ newState.forEach( ( order, clientId ) => {
1103
+ const newSubOrder =
1104
+ order?.filter(
1105
+ ( id ) => ! action.removedClientIds.includes( id )
1106
+ ) ?? [];
1107
+ if ( newSubOrder.length !== order.length ) {
1108
+ newState.set( clientId, newSubOrder );
1109
+ }
1110
+ } );
1111
+ return newState;
1112
+ }
1099
1113
  }
1100
1114
 
1101
1115
  return state;
@@ -1103,44 +1117,55 @@ export const blocks = pipe(
1103
1117
 
1104
1118
  // While technically redundant data as the inverse of `order`, it serves as
1105
1119
  // an optimization for the selectors which derive the ancestry of a block.
1106
- parents( state = {}, action ) {
1120
+ parents( state = new Map(), action ) {
1107
1121
  switch ( action.type ) {
1108
- case 'RECEIVE_BLOCKS':
1109
- return {
1110
- ...state,
1111
- ...mapBlockParents( action.blocks ),
1112
- };
1113
-
1114
- case 'INSERT_BLOCKS':
1115
- return {
1116
- ...state,
1117
- ...mapBlockParents(
1118
- action.blocks,
1119
- action.rootClientId || ''
1120
- ),
1121
- };
1122
-
1122
+ case 'RECEIVE_BLOCKS': {
1123
+ const newState = new Map( state );
1124
+ mapBlockParents( action.blocks ).forEach(
1125
+ ( [ key, value ] ) => {
1126
+ newState.set( key, value );
1127
+ }
1128
+ );
1129
+ return newState;
1130
+ }
1131
+ case 'INSERT_BLOCKS': {
1132
+ const newState = new Map( state );
1133
+ mapBlockParents(
1134
+ action.blocks,
1135
+ action.rootClientId || ''
1136
+ ).forEach( ( [ key, value ] ) => {
1137
+ newState.set( key, value );
1138
+ } );
1139
+ return newState;
1140
+ }
1123
1141
  case 'MOVE_BLOCKS_TO_POSITION': {
1124
- return {
1125
- ...state,
1126
- ...action.clientIds.reduce( ( accumulator, id ) => {
1127
- accumulator[ id ] = action.toRootClientId || '';
1128
- return accumulator;
1129
- }, {} ),
1130
- };
1142
+ const newState = new Map( state );
1143
+ action.clientIds.forEach( ( id ) => {
1144
+ newState.set( id, action.toRootClientId || '' );
1145
+ } );
1146
+ return newState;
1131
1147
  }
1132
1148
 
1133
- case 'REPLACE_BLOCKS_AUGMENTED_WITH_CHILDREN':
1134
- return {
1135
- ...omit( state, action.replacedClientIds ),
1136
- ...mapBlockParents(
1137
- action.blocks,
1138
- state[ action.clientIds[ 0 ] ]
1139
- ),
1140
- };
1141
-
1142
- case 'REMOVE_BLOCKS_AUGMENTED_WITH_CHILDREN':
1143
- return omit( state, action.removedClientIds );
1149
+ case 'REPLACE_BLOCKS_AUGMENTED_WITH_CHILDREN': {
1150
+ const newState = new Map( state );
1151
+ action.replacedClientIds.forEach( ( clientId ) => {
1152
+ newState.delete( clientId );
1153
+ } );
1154
+ mapBlockParents(
1155
+ action.blocks,
1156
+ state.get( action.clientIds[ 0 ] )
1157
+ ).forEach( ( [ key, value ] ) => {
1158
+ newState.set( key, value );
1159
+ } );
1160
+ return newState;
1161
+ }
1162
+ case 'REMOVE_BLOCKS_AUGMENTED_WITH_CHILDREN': {
1163
+ const newState = new Map( state );
1164
+ action.removedClientIds.forEach( ( clientId ) => {
1165
+ newState.delete( clientId );
1166
+ } );
1167
+ return newState;
1168
+ }
1144
1169
  }
1145
1170
 
1146
1171
  return state;
@@ -1160,6 +1185,26 @@ export const blocks = pipe(
1160
1185
  },
1161
1186
  } );
1162
1187
 
1188
+ /**
1189
+ * Reducer returning visibility status of block interface.
1190
+ *
1191
+ * @param {boolean} state Current state.
1192
+ * @param {Object} action Dispatched action.
1193
+ *
1194
+ * @return {boolean} Updated state.
1195
+ */
1196
+ export function isBlockInterfaceHidden( state = false, action ) {
1197
+ switch ( action.type ) {
1198
+ case 'HIDE_BLOCK_INTERFACE':
1199
+ return true;
1200
+
1201
+ case 'SHOW_BLOCK_INTERFACE':
1202
+ return false;
1203
+ }
1204
+
1205
+ return state;
1206
+ }
1207
+
1163
1208
  /**
1164
1209
  * Reducer returning typing state.
1165
1210
  *
@@ -1483,7 +1528,7 @@ export function insertionPoint( state = null, action ) {
1483
1528
  };
1484
1529
 
1485
1530
  // Bail out updates if the states are the same.
1486
- return isEqual( state, nextState ) ? state : nextState;
1531
+ return fastDeepEqual( state, nextState ) ? state : nextState;
1487
1532
  }
1488
1533
 
1489
1534
  case 'HIDE_INSERTION_POINT':
@@ -1608,7 +1653,7 @@ export const blockListSettings = ( state = {}, action ) => {
1608
1653
  return state;
1609
1654
  }
1610
1655
 
1611
- if ( isEqual( state[ clientId ], action.settings ) ) {
1656
+ if ( fastDeepEqual( state[ clientId ], action.settings ) ) {
1612
1657
  return state;
1613
1658
  }
1614
1659
 
@@ -1809,6 +1854,7 @@ export function temporarilyEditingAsBlocks( state = '', action ) {
1809
1854
  export default combineReducers( {
1810
1855
  blocks,
1811
1856
  isTyping,
1857
+ isBlockInterfaceHidden,
1812
1858
  draggedBlocks,
1813
1859
  selection,
1814
1860
  isMultiSelecting,