@wordpress/block-editor 10.5.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 (488) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/build/autocompleters/block.js +2 -6
  3. package/build/autocompleters/block.js.map +1 -1
  4. package/build/autocompleters/link.js +2 -0
  5. package/build/autocompleters/link.js.map +1 -1
  6. package/build/components/block-card/index.js +51 -3
  7. package/build/components/block-card/index.js.map +1 -1
  8. package/build/components/block-draggable/index.native.js +46 -39
  9. package/build/components/block-draggable/index.native.js.map +1 -1
  10. package/build/components/block-edit/edit.js +4 -3
  11. package/build/components/block-edit/edit.js.map +1 -1
  12. package/build/components/block-edit/edit.native.js +4 -7
  13. package/build/components/block-edit/edit.native.js.map +1 -1
  14. package/build/components/block-inspector/index.js +35 -33
  15. package/build/components/block-inspector/index.js.map +1 -1
  16. package/build/components/block-list/block-list-context.native.js +5 -8
  17. package/build/components/block-list/block-list-context.native.js.map +1 -1
  18. package/build/components/block-list/block.js +55 -24
  19. package/build/components/block-list/block.js.map +1 -1
  20. package/build/components/block-list/block.native.js +61 -28
  21. package/build/components/block-list/block.native.js.map +1 -1
  22. package/build/components/block-mobile-toolbar/block-actions-menu.native.js +12 -4
  23. package/build/components/block-mobile-toolbar/block-actions-menu.native.js.map +1 -1
  24. package/build/components/block-pattern-setup/index.js +3 -2
  25. package/build/components/block-pattern-setup/index.js.map +1 -1
  26. package/build/components/block-patterns-list/index.js +33 -11
  27. package/build/components/block-patterns-list/index.js.map +1 -1
  28. package/build/components/block-preview/auto.js +9 -3
  29. package/build/components/block-preview/auto.js.map +1 -1
  30. package/build/components/block-preview/index.js +5 -9
  31. package/build/components/block-preview/index.js.map +1 -1
  32. package/build/components/block-settings-menu/block-settings-dropdown.js +5 -2
  33. package/build/components/block-settings-menu/block-settings-dropdown.js.map +1 -1
  34. package/build/components/block-toolbar/index.js +5 -1
  35. package/build/components/block-toolbar/index.js.map +1 -1
  36. package/build/components/block-tools/insertion-point.js +8 -49
  37. package/build/components/block-tools/insertion-point.js.map +1 -1
  38. package/build/components/block-variation-picker/index.js +1 -2
  39. package/build/components/block-variation-picker/index.js.map +1 -1
  40. package/build/components/height-control/index.js +115 -0
  41. package/build/components/height-control/index.js.map +1 -0
  42. package/build/components/iframe/index.js +11 -8
  43. package/build/components/iframe/index.js.map +1 -1
  44. package/build/components/image-editor/use-save-image.js +2 -0
  45. package/build/components/image-editor/use-save-image.js.map +1 -1
  46. package/build/components/image-editor/zoom-dropdown.js +1 -0
  47. package/build/components/image-editor/zoom-dropdown.js.map +1 -1
  48. package/build/components/index.js +9 -0
  49. package/build/components/index.js.map +1 -1
  50. package/build/components/inner-blocks/index.js +20 -6
  51. package/build/components/inner-blocks/index.js.map +1 -1
  52. package/build/components/inner-blocks/use-inner-block-template-sync.js +25 -10
  53. package/build/components/inner-blocks/use-inner-block-template-sync.js.map +1 -1
  54. package/build/components/inserter/block-patterns-explorer/sidebar.js +1 -0
  55. package/build/components/inserter/block-patterns-explorer/sidebar.js.map +1 -1
  56. package/build/components/inserter/block-patterns-tab.js +25 -46
  57. package/build/components/inserter/block-patterns-tab.js.map +1 -1
  58. package/build/components/inserter/block-types-tab.js +3 -1
  59. package/build/components/inserter/block-types-tab.js.map +1 -1
  60. package/build/components/inserter/hooks/use-debounced-input.js +27 -0
  61. package/build/components/inserter/hooks/use-debounced-input.js.map +1 -0
  62. package/build/components/inserter/index.js +8 -3
  63. package/build/components/inserter/index.js.map +1 -1
  64. package/build/components/inserter/index.native.js +3 -4
  65. package/build/components/inserter/index.native.js.map +1 -1
  66. package/build/components/inserter/media-tab/hooks.js +103 -0
  67. package/build/components/inserter/media-tab/hooks.js.map +1 -0
  68. package/build/components/inserter/media-tab/index.js +32 -0
  69. package/build/components/inserter/media-tab/index.js.map +1 -0
  70. package/build/components/inserter/media-tab/media-list.js +100 -0
  71. package/build/components/inserter/media-tab/media-list.js.map +1 -0
  72. package/build/components/inserter/media-tab/media-panel.js +96 -0
  73. package/build/components/inserter/media-tab/media-panel.js.map +1 -0
  74. package/build/components/inserter/media-tab/media-tab.js +120 -0
  75. package/build/components/inserter/media-tab/media-tab.js.map +1 -0
  76. package/build/components/inserter/media-tab/utils.js +54 -0
  77. package/build/components/inserter/media-tab/utils.js.map +1 -0
  78. package/build/components/inserter/menu.js +35 -12
  79. package/build/components/inserter/menu.js.map +1 -1
  80. package/build/components/inserter/mobile-tab-navigation.js +70 -0
  81. package/build/components/inserter/mobile-tab-navigation.js.map +1 -0
  82. package/build/components/inserter/quick-inserter.js +1 -0
  83. package/build/components/inserter/quick-inserter.js.map +1 -1
  84. package/build/components/inserter/search-results.js +3 -1
  85. package/build/components/inserter/search-results.js.map +1 -1
  86. package/build/components/inserter/tabs.js +16 -2
  87. package/build/components/inserter/tabs.js.map +1 -1
  88. package/build/components/inserter-list-item/index.js +4 -1
  89. package/build/components/inserter-list-item/index.js.map +1 -1
  90. package/build/components/inspector-controls/groups.js +2 -0
  91. package/build/components/inspector-controls/groups.js.map +1 -1
  92. package/build/components/inspector-controls-tabs/advanced-controls-panel.js +46 -0
  93. package/build/components/inspector-controls-tabs/advanced-controls-panel.js.map +1 -0
  94. package/build/components/inspector-controls-tabs/index.js +71 -0
  95. package/build/components/inspector-controls-tabs/index.js.map +1 -0
  96. package/build/components/inspector-controls-tabs/settings-tab.js +28 -0
  97. package/build/components/inspector-controls-tabs/settings-tab.js.map +1 -0
  98. package/build/components/inspector-controls-tabs/styles-tab.js +61 -0
  99. package/build/components/inspector-controls-tabs/styles-tab.js.map +1 -0
  100. package/build/components/inspector-controls-tabs/use-inspector-controls-tabs.js +97 -0
  101. package/build/components/inspector-controls-tabs/use-inspector-controls-tabs.js.map +1 -0
  102. package/build/components/inspector-controls-tabs/use-is-list-view-tab-disabled.js +18 -0
  103. package/build/components/inspector-controls-tabs/use-is-list-view-tab-disabled.js.map +1 -0
  104. package/build/components/inspector-controls-tabs/utils.js +37 -0
  105. package/build/components/inspector-controls-tabs/utils.js.map +1 -0
  106. package/build/components/link-control/index.js +1 -0
  107. package/build/components/link-control/index.js.map +1 -1
  108. package/build/components/link-control/search-input.js +0 -1
  109. package/build/components/link-control/search-input.js.map +1 -1
  110. package/build/components/link-control/use-internal-input-value.js +3 -3
  111. package/build/components/link-control/use-internal-input-value.js.map +1 -1
  112. package/build/components/list-view/block.js +5 -2
  113. package/build/components/list-view/block.js.map +1 -1
  114. package/build/components/list-view/branch.js +13 -12
  115. package/build/components/list-view/branch.js.map +1 -1
  116. package/build/components/media-upload/index.native.js +2 -3
  117. package/build/components/media-upload/index.native.js.map +1 -1
  118. package/build/components/off-canvas-editor/appender.js +104 -0
  119. package/build/components/off-canvas-editor/appender.js.map +1 -0
  120. package/build/components/off-canvas-editor/block-edit-button.js +50 -0
  121. package/build/components/off-canvas-editor/block-edit-button.js.map +1 -0
  122. package/build/components/off-canvas-editor/block.js +36 -4
  123. package/build/components/off-canvas-editor/block.js.map +1 -1
  124. package/build/components/off-canvas-editor/branch.js +3 -5
  125. package/build/components/off-canvas-editor/branch.js.map +1 -1
  126. package/build/components/off-canvas-editor/index.js +20 -11
  127. package/build/components/off-canvas-editor/index.js.map +1 -1
  128. package/build/components/off-canvas-editor/leaf.js +1 -1
  129. package/build/components/off-canvas-editor/leaf.js.map +1 -1
  130. package/build/components/off-canvas-editor/link-ui.js +185 -0
  131. package/build/components/off-canvas-editor/link-ui.js.map +1 -0
  132. package/build/components/off-canvas-editor/update-attributes.js +108 -0
  133. package/build/components/off-canvas-editor/update-attributes.js.map +1 -0
  134. package/build/components/rich-text/format-toolbar/index.js +8 -4
  135. package/build/components/rich-text/format-toolbar/index.js.map +1 -1
  136. package/build/components/rich-text/index.js +3 -3
  137. package/build/components/rich-text/index.js.map +1 -1
  138. package/build/components/rich-text/index.native.js +0 -2
  139. package/build/components/rich-text/index.native.js.map +1 -1
  140. package/build/components/rich-text/use-insert-replacement-text.js +43 -0
  141. package/build/components/rich-text/use-insert-replacement-text.js.map +1 -0
  142. package/build/components/rich-text/use-undo-automatic-change.js +9 -1
  143. package/build/components/rich-text/use-undo-automatic-change.js.map +1 -1
  144. package/build/components/rich-text/utils.js +1 -19
  145. package/build/components/rich-text/utils.js.map +1 -1
  146. package/build/components/spacing-sizes-control/spacing-input-control.js +12 -3
  147. package/build/components/spacing-sizes-control/spacing-input-control.js.map +1 -1
  148. package/build/components/ungroup-button/index.native.js +4 -2
  149. package/build/components/ungroup-button/index.native.js.map +1 -1
  150. package/build/components/url-input/index.js +46 -43
  151. package/build/components/url-input/index.js.map +1 -1
  152. package/build/components/use-block-display-information/index.js +8 -4
  153. package/build/components/use-block-display-information/index.js.map +1 -1
  154. package/build/components/use-setting/index.js +9 -1
  155. package/build/components/use-setting/index.js.map +1 -1
  156. package/build/hooks/child-layout.js +209 -0
  157. package/build/hooks/child-layout.js.map +1 -0
  158. package/build/hooks/content-lock-ui.js +1 -1
  159. package/build/hooks/content-lock-ui.js.map +1 -1
  160. package/build/hooks/dimensions.js +25 -7
  161. package/build/hooks/dimensions.js.map +1 -1
  162. package/build/hooks/layout.js +57 -1
  163. package/build/hooks/layout.js.map +1 -1
  164. package/build/hooks/min-height.js +4 -10
  165. package/build/hooks/min-height.js.map +1 -1
  166. package/build/store/reducer.js +393 -270
  167. package/build/store/reducer.js.map +1 -1
  168. package/build/store/selectors.js +57 -47
  169. package/build/store/selectors.js.map +1 -1
  170. package/build/utils/sorting.js +63 -0
  171. package/build/utils/sorting.js.map +1 -0
  172. package/build-module/autocompleters/block.js +2 -6
  173. package/build-module/autocompleters/block.js.map +1 -1
  174. package/build-module/autocompleters/link.js +2 -0
  175. package/build-module/autocompleters/link.js.map +1 -1
  176. package/build-module/components/block-card/index.js +45 -3
  177. package/build-module/components/block-card/index.js.map +1 -1
  178. package/build-module/components/block-draggable/index.native.js +40 -31
  179. package/build-module/components/block-draggable/index.native.js.map +1 -1
  180. package/build-module/components/block-edit/edit.js +4 -2
  181. package/build-module/components/block-edit/edit.js.map +1 -1
  182. package/build-module/components/block-edit/edit.native.js +4 -6
  183. package/build-module/components/block-edit/edit.native.js.map +1 -1
  184. package/build-module/components/block-inspector/index.js +32 -30
  185. package/build-module/components/block-inspector/index.js.map +1 -1
  186. package/build-module/components/block-list/block-list-context.native.js +5 -8
  187. package/build-module/components/block-list/block-list-context.native.js.map +1 -1
  188. package/build-module/components/block-list/block.js +55 -25
  189. package/build-module/components/block-list/block.js.map +1 -1
  190. package/build-module/components/block-list/block.native.js +61 -28
  191. package/build-module/components/block-list/block.native.js.map +1 -1
  192. package/build-module/components/block-mobile-toolbar/block-actions-menu.native.js +13 -6
  193. package/build-module/components/block-mobile-toolbar/block-actions-menu.native.js.map +1 -1
  194. package/build-module/components/block-pattern-setup/index.js +3 -2
  195. package/build-module/components/block-pattern-setup/index.js.map +1 -1
  196. package/build-module/components/block-patterns-list/index.js +35 -13
  197. package/build-module/components/block-patterns-list/index.js.map +1 -1
  198. package/build-module/components/block-preview/auto.js +9 -3
  199. package/build-module/components/block-preview/auto.js.map +1 -1
  200. package/build-module/components/block-preview/index.js +5 -8
  201. package/build-module/components/block-preview/index.js.map +1 -1
  202. package/build-module/components/block-settings-menu/block-settings-dropdown.js +5 -2
  203. package/build-module/components/block-settings-menu/block-settings-dropdown.js.map +1 -1
  204. package/build-module/components/block-toolbar/index.js +6 -2
  205. package/build-module/components/block-toolbar/index.js.map +1 -1
  206. package/build-module/components/block-tools/insertion-point.js +8 -49
  207. package/build-module/components/block-tools/insertion-point.js.map +1 -1
  208. package/build-module/components/block-variation-picker/index.js +1 -2
  209. package/build-module/components/block-variation-picker/index.js.map +1 -1
  210. package/build-module/components/height-control/index.js +103 -0
  211. package/build-module/components/height-control/index.js.map +1 -0
  212. package/build-module/components/iframe/index.js +11 -8
  213. package/build-module/components/iframe/index.js.map +1 -1
  214. package/build-module/components/image-editor/use-save-image.js +2 -0
  215. package/build-module/components/image-editor/use-save-image.js.map +1 -1
  216. package/build-module/components/image-editor/zoom-dropdown.js +1 -0
  217. package/build-module/components/image-editor/zoom-dropdown.js.map +1 -1
  218. package/build-module/components/index.js +1 -0
  219. package/build-module/components/index.js.map +1 -1
  220. package/build-module/components/inner-blocks/index.js +22 -8
  221. package/build-module/components/inner-blocks/index.js.map +1 -1
  222. package/build-module/components/inner-blocks/use-inner-block-template-sync.js +23 -10
  223. package/build-module/components/inner-blocks/use-inner-block-template-sync.js.map +1 -1
  224. package/build-module/components/inserter/block-patterns-explorer/sidebar.js +1 -0
  225. package/build-module/components/inserter/block-patterns-explorer/sidebar.js.map +1 -1
  226. package/build-module/components/inserter/block-patterns-tab.js +27 -49
  227. package/build-module/components/inserter/block-patterns-tab.js.map +1 -1
  228. package/build-module/components/inserter/block-types-tab.js +3 -2
  229. package/build-module/components/inserter/block-types-tab.js.map +1 -1
  230. package/build-module/components/inserter/hooks/use-debounced-input.js +18 -0
  231. package/build-module/components/inserter/hooks/use-debounced-input.js.map +1 -0
  232. package/build-module/components/inserter/index.js +8 -3
  233. package/build-module/components/inserter/index.js.map +1 -1
  234. package/build-module/components/inserter/index.native.js +3 -5
  235. package/build-module/components/inserter/index.native.js.map +1 -1
  236. package/build-module/components/inserter/media-tab/hooks.js +89 -0
  237. package/build-module/components/inserter/media-tab/hooks.js.map +1 -0
  238. package/build-module/components/inserter/media-tab/index.js +4 -0
  239. package/build-module/components/inserter/media-tab/index.js.map +1 -0
  240. package/build-module/components/inserter/media-tab/media-list.js +86 -0
  241. package/build-module/components/inserter/media-tab/media-list.js.map +1 -0
  242. package/build-module/components/inserter/media-tab/media-panel.js +77 -0
  243. package/build-module/components/inserter/media-tab/media-panel.js.map +1 -0
  244. package/build-module/components/inserter/media-tab/media-tab.js +100 -0
  245. package/build-module/components/inserter/media-tab/media-tab.js.map +1 -0
  246. package/build-module/components/inserter/media-tab/utils.js +45 -0
  247. package/build-module/components/inserter/media-tab/utils.js.map +1 -0
  248. package/build-module/components/inserter/menu.js +33 -12
  249. package/build-module/components/inserter/menu.js.map +1 -1
  250. package/build-module/components/inserter/mobile-tab-navigation.js +61 -0
  251. package/build-module/components/inserter/mobile-tab-navigation.js.map +1 -0
  252. package/build-module/components/inserter/quick-inserter.js +1 -0
  253. package/build-module/components/inserter/quick-inserter.js.map +1 -1
  254. package/build-module/components/inserter/search-results.js +3 -2
  255. package/build-module/components/inserter/search-results.js.map +1 -1
  256. package/build-module/components/inserter/tabs.js +15 -2
  257. package/build-module/components/inserter/tabs.js.map +1 -1
  258. package/build-module/components/inserter-list-item/index.js +5 -2
  259. package/build-module/components/inserter-list-item/index.js.map +1 -1
  260. package/build-module/components/inspector-controls/groups.js +2 -0
  261. package/build-module/components/inspector-controls/groups.js.map +1 -1
  262. package/build-module/components/inspector-controls-tabs/advanced-controls-panel.js +32 -0
  263. package/build-module/components/inspector-controls-tabs/advanced-controls-panel.js.map +1 -0
  264. package/build-module/components/inspector-controls-tabs/index.js +56 -0
  265. package/build-module/components/inspector-controls-tabs/index.js.map +1 -0
  266. package/build-module/components/inspector-controls-tabs/settings-tab.js +17 -0
  267. package/build-module/components/inspector-controls-tabs/settings-tab.js.map +1 -0
  268. package/build-module/components/inspector-controls-tabs/styles-tab.js +46 -0
  269. package/build-module/components/inspector-controls-tabs/styles-tab.js.map +1 -0
  270. package/build-module/components/inspector-controls-tabs/use-inspector-controls-tabs.js +81 -0
  271. package/build-module/components/inspector-controls-tabs/use-inspector-controls-tabs.js.map +1 -0
  272. package/build-module/components/inspector-controls-tabs/use-is-list-view-tab-disabled.js +8 -0
  273. package/build-module/components/inspector-controls-tabs/use-is-list-view-tab-disabled.js.map +1 -0
  274. package/build-module/components/inspector-controls-tabs/utils.js +26 -0
  275. package/build-module/components/inspector-controls-tabs/utils.js.map +1 -0
  276. package/build-module/components/link-control/index.js +1 -0
  277. package/build-module/components/link-control/index.js.map +1 -1
  278. package/build-module/components/link-control/search-input.js +0 -1
  279. package/build-module/components/link-control/search-input.js.map +1 -1
  280. package/build-module/components/link-control/use-internal-input-value.js +3 -3
  281. package/build-module/components/link-control/use-internal-input-value.js.map +1 -1
  282. package/build-module/components/list-view/block.js +5 -2
  283. package/build-module/components/list-view/block.js.map +1 -1
  284. package/build-module/components/list-view/branch.js +12 -11
  285. package/build-module/components/list-view/branch.js.map +1 -1
  286. package/build-module/components/media-upload/index.native.js +2 -4
  287. package/build-module/components/media-upload/index.native.js.map +1 -1
  288. package/build-module/components/off-canvas-editor/appender.js +89 -0
  289. package/build-module/components/off-canvas-editor/appender.js.map +1 -0
  290. package/build-module/components/off-canvas-editor/block-edit-button.js +35 -0
  291. package/build-module/components/off-canvas-editor/block-edit-button.js.map +1 -0
  292. package/build-module/components/off-canvas-editor/block.js +36 -6
  293. package/build-module/components/off-canvas-editor/block.js.map +1 -1
  294. package/build-module/components/off-canvas-editor/branch.js +3 -4
  295. package/build-module/components/off-canvas-editor/branch.js.map +1 -1
  296. package/build-module/components/off-canvas-editor/index.js +20 -12
  297. package/build-module/components/off-canvas-editor/index.js.map +1 -1
  298. package/build-module/components/off-canvas-editor/leaf.js +1 -1
  299. package/build-module/components/off-canvas-editor/leaf.js.map +1 -1
  300. package/build-module/components/off-canvas-editor/link-ui.js +165 -0
  301. package/build-module/components/off-canvas-editor/link-ui.js.map +1 -0
  302. package/build-module/components/off-canvas-editor/update-attributes.js +97 -0
  303. package/build-module/components/off-canvas-editor/update-attributes.js.map +1 -0
  304. package/build-module/components/rich-text/format-toolbar/index.js +6 -2
  305. package/build-module/components/rich-text/format-toolbar/index.js.map +1 -1
  306. package/build-module/components/rich-text/index.js +2 -3
  307. package/build-module/components/rich-text/index.js.map +1 -1
  308. package/build-module/components/rich-text/index.native.js +0 -2
  309. package/build-module/components/rich-text/index.native.js.map +1 -1
  310. package/build-module/components/rich-text/use-insert-replacement-text.js +33 -0
  311. package/build-module/components/rich-text/use-insert-replacement-text.js.map +1 -0
  312. package/build-module/components/rich-text/use-undo-automatic-change.js +9 -1
  313. package/build-module/components/rich-text/use-undo-automatic-change.js.map +1 -1
  314. package/build-module/components/rich-text/utils.js +1 -16
  315. package/build-module/components/rich-text/utils.js.map +1 -1
  316. package/build-module/components/spacing-sizes-control/spacing-input-control.js +12 -3
  317. package/build-module/components/spacing-sizes-control/spacing-input-control.js.map +1 -1
  318. package/build-module/components/ungroup-button/index.native.js +3 -2
  319. package/build-module/components/ungroup-button/index.native.js.map +1 -1
  320. package/build-module/components/url-input/index.js +46 -43
  321. package/build-module/components/url-input/index.js.map +1 -1
  322. package/build-module/components/use-block-display-information/index.js +9 -5
  323. package/build-module/components/use-block-display-information/index.js.map +1 -1
  324. package/build-module/components/use-setting/index.js +8 -1
  325. package/build-module/components/use-setting/index.js.map +1 -1
  326. package/build-module/hooks/child-layout.js +189 -0
  327. package/build-module/hooks/child-layout.js.map +1 -0
  328. package/build-module/hooks/content-lock-ui.js +1 -1
  329. package/build-module/hooks/content-lock-ui.js.map +1 -1
  330. package/build-module/hooks/dimensions.js +25 -8
  331. package/build-module/hooks/dimensions.js.map +1 -1
  332. package/build-module/hooks/layout.js +55 -0
  333. package/build-module/hooks/layout.js.map +1 -1
  334. package/build-module/hooks/min-height.js +3 -9
  335. package/build-module/hooks/min-height.js.map +1 -1
  336. package/build-module/store/reducer.js +391 -271
  337. package/build-module/store/reducer.js.map +1 -1
  338. package/build-module/store/selectors.js +54 -47
  339. package/build-module/store/selectors.js.map +1 -1
  340. package/build-module/utils/sorting.js +56 -0
  341. package/build-module/utils/sorting.js.map +1 -0
  342. package/build-style/content-rtl.css +701 -0
  343. package/build-style/content.css +701 -0
  344. package/build-style/default-editor-styles-rtl.css +14 -0
  345. package/build-style/default-editor-styles.css +14 -0
  346. package/build-style/style-rtl.css +286 -662
  347. package/build-style/style.css +286 -662
  348. package/package.json +32 -30
  349. package/src/autocompleters/block.js +2 -6
  350. package/src/autocompleters/link.js +2 -0
  351. package/src/components/alignment-control/test/index.js +4 -1
  352. package/src/components/block-alignment-control/test/index.js +4 -1
  353. package/src/components/block-card/index.js +46 -2
  354. package/src/components/block-card/style.scss +4 -0
  355. package/src/components/block-content-overlay/{style.scss → content.scss} +7 -1
  356. package/src/components/block-draggable/content.scss +20 -0
  357. package/src/components/block-draggable/index.native.js +54 -40
  358. package/src/components/block-draggable/style.scss +0 -21
  359. package/src/components/block-draggable/test/helpers.native.js +7 -9
  360. package/src/components/block-draggable/test/index.native.js +35 -45
  361. package/src/components/block-edit/edit.js +5 -2
  362. package/src/components/block-edit/edit.native.js +5 -6
  363. package/src/components/block-inspector/index.js +96 -81
  364. package/src/components/block-inspector/style.scss +9 -1
  365. package/src/components/block-list/block-list-context.native.js +5 -8
  366. package/src/components/block-list/block.js +74 -23
  367. package/src/components/block-list/block.native.js +78 -23
  368. package/src/components/block-list/{style.scss → content.scss} +1 -15
  369. package/src/components/block-list-appender/{style.scss → content.scss} +0 -0
  370. package/src/components/block-mobile-toolbar/block-actions-menu.native.js +24 -6
  371. package/src/components/block-mover/test/__snapshots__/index.native.js.snap +0 -2
  372. package/src/components/block-pattern-setup/index.js +2 -1
  373. package/src/components/block-patterns-list/index.js +47 -24
  374. package/src/components/block-preview/README.md +15 -10
  375. package/src/components/block-preview/auto.js +7 -1
  376. package/src/components/block-preview/content.scss +4 -0
  377. package/src/components/block-preview/index.js +7 -12
  378. package/src/components/block-preview/style.scss +0 -7
  379. package/src/components/block-preview/test/index.js +18 -35
  380. package/src/components/block-selection-clearer/test/index.js +12 -12
  381. package/src/components/block-settings-menu/block-settings-dropdown.js +32 -20
  382. package/src/components/block-switcher/test/index.js +4 -0
  383. package/src/components/block-toolbar/index.js +12 -5
  384. package/src/components/block-toolbar/style.scss +10 -0
  385. package/src/components/block-tools/insertion-point.js +3 -47
  386. package/src/components/block-tools/style.scss +12 -5
  387. package/src/components/block-variation-picker/index.js +1 -4
  388. package/src/components/block-vertical-alignment-control/test/index.js +4 -1
  389. package/src/components/default-block-appender/{style.scss → content.scss} +0 -0
  390. package/src/components/height-control/index.js +123 -0
  391. package/src/components/height-control/stories/index.js +21 -0
  392. package/src/components/height-control/style.scss +5 -0
  393. package/src/components/iframe/index.js +25 -18
  394. package/src/components/image-editor/use-save-image.js +2 -0
  395. package/src/components/image-editor/zoom-dropdown.js +1 -0
  396. package/src/components/index.js +1 -0
  397. package/src/components/inner-blocks/{style.scss → content.scss} +0 -0
  398. package/src/components/inner-blocks/index.js +23 -6
  399. package/src/components/inner-blocks/use-inner-block-template-sync.js +28 -10
  400. package/src/components/inserter/block-patterns-explorer/sidebar.js +1 -0
  401. package/src/components/inserter/block-patterns-tab.js +28 -71
  402. package/src/components/inserter/block-types-tab.js +3 -2
  403. package/src/components/inserter/hooks/use-debounced-input.js +17 -0
  404. package/src/components/inserter/index.js +10 -2
  405. package/src/components/inserter/index.native.js +1 -1
  406. package/src/components/inserter/media-tab/hooks.js +88 -0
  407. package/src/components/inserter/media-tab/index.js +3 -0
  408. package/src/components/inserter/media-tab/media-list.js +93 -0
  409. package/src/components/inserter/media-tab/media-panel.js +83 -0
  410. package/src/components/inserter/media-tab/media-tab.js +135 -0
  411. package/src/components/inserter/media-tab/utils.js +37 -0
  412. package/src/components/inserter/menu.js +55 -13
  413. package/src/components/inserter/mobile-tab-navigation.js +85 -0
  414. package/src/components/inserter/quick-inserter.js +1 -0
  415. package/src/components/inserter/search-results.js +3 -2
  416. package/src/components/inserter/stories/index.js +1 -1
  417. package/src/components/inserter/stories/{fixtures.js → utils/fixtures.js} +0 -0
  418. package/src/components/inserter/style.scss +176 -11
  419. package/src/components/inserter/tabs.js +12 -1
  420. package/src/components/inserter-list-item/index.js +11 -1
  421. package/src/components/inserter-list-item/style.scss +26 -0
  422. package/src/components/inspector-controls/groups.js +2 -0
  423. package/src/components/inspector-controls-tabs/advanced-controls-panel.js +37 -0
  424. package/src/components/inspector-controls-tabs/index.js +62 -0
  425. package/src/components/inspector-controls-tabs/settings-tab.js +18 -0
  426. package/src/components/inspector-controls-tabs/styles-tab.js +51 -0
  427. package/src/components/inspector-controls-tabs/use-inspector-controls-tabs.js +89 -0
  428. package/src/components/inspector-controls-tabs/use-is-list-view-tab-disabled.js +9 -0
  429. package/src/components/inspector-controls-tabs/utils.js +28 -0
  430. package/src/components/line-height-control/test/index.js +5 -5
  431. package/src/components/link-control/README.md +1 -1
  432. package/src/components/link-control/index.js +1 -0
  433. package/src/components/link-control/search-input.js +0 -1
  434. package/src/components/link-control/test/index.js +188 -401
  435. package/src/components/link-control/use-internal-input-value.js +3 -3
  436. package/src/components/list-view/block.js +3 -0
  437. package/src/components/list-view/branch.js +10 -8
  438. package/src/components/list-view/style.scss +20 -9
  439. package/src/components/media-placeholder/{style.scss → content.scss} +0 -0
  440. package/src/components/media-replace-flow/test/index.js +37 -9
  441. package/src/components/media-upload/test/index.native.js +2 -0
  442. package/src/components/off-canvas-editor/appender.js +93 -0
  443. package/src/components/off-canvas-editor/block-edit-button.js +27 -0
  444. package/src/components/off-canvas-editor/block.js +88 -22
  445. package/src/components/off-canvas-editor/branch.js +3 -5
  446. package/src/components/off-canvas-editor/index.js +59 -33
  447. package/src/components/off-canvas-editor/leaf.js +5 -1
  448. package/src/components/off-canvas-editor/link-ui.js +166 -0
  449. package/src/components/off-canvas-editor/style.scss +17 -388
  450. package/src/components/off-canvas-editor/update-attributes.js +99 -0
  451. package/src/components/plain-text/{style.scss → content.scss} +0 -0
  452. package/src/components/recursion-provider/test/index.js +27 -29
  453. package/src/components/rich-text/content.scss +42 -0
  454. package/src/components/rich-text/format-toolbar/index.js +6 -4
  455. package/src/components/rich-text/index.js +2 -2
  456. package/src/components/rich-text/index.native.js +0 -2
  457. package/src/components/rich-text/style.scss +0 -43
  458. package/src/components/rich-text/use-insert-replacement-text.js +31 -0
  459. package/src/components/rich-text/use-undo-automatic-change.js +7 -1
  460. package/src/components/rich-text/utils.js +2 -21
  461. package/src/components/spacing-sizes-control/spacing-input-control.js +9 -0
  462. package/src/components/ungroup-button/index.native.js +6 -2
  463. package/src/components/url-input/index.js +57 -73
  464. package/src/components/url-popover/test/__snapshots__/index.js.snap +8 -6
  465. package/src/components/url-popover/test/index.js +21 -9
  466. package/src/components/use-block-display-information/index.js +14 -5
  467. package/src/components/use-setting/index.js +13 -1
  468. package/src/components/use-setting/test/index.js +99 -0
  469. package/src/content.scss +10 -0
  470. package/src/hooks/child-layout.js +190 -0
  471. package/src/hooks/content-lock-ui.js +1 -1
  472. package/src/hooks/dimensions.js +45 -7
  473. package/src/hooks/layout.js +60 -0
  474. package/src/hooks/min-height.js +2 -19
  475. package/src/store/reducer.js +459 -423
  476. package/src/store/selectors.js +56 -57
  477. package/src/store/test/performance.js +71 -0
  478. package/src/store/test/reducer.js +623 -491
  479. package/src/store/test/selectors.js +1820 -1306
  480. package/src/style.scss +4 -7
  481. package/src/utils/sorting.js +54 -0
  482. package/src/utils/test/sorting.js +49 -0
  483. package/tsconfig.tsbuildinfo +1 -1
  484. package/build/components/block-preview/live.js +0 -30
  485. package/build/components/block-preview/live.js.map +0 -1
  486. package/build-module/components/block-preview/live.js +0 -20
  487. package/build-module/components/block-preview/live.js.map +0 -1
  488. package/src/components/block-preview/live.js +0 -19
@@ -1,7 +1,8 @@
1
1
  /**
2
2
  * External dependencies
3
3
  */
4
- import { 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,25 +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
- ...Object.keys( nestedControllers ).reduce( ( result, key ) => {
687
- if ( state.order[ key ] ) {
688
- result[ key ] = state.order[ key ];
689
- }
690
- return result;
691
- }, {} ),
692
- };
693
- stateAfterInsert.tree = {
694
- ...stateAfterInsert.tree,
695
- ...Object.keys( nestedControllers ).reduce( ( result, _key ) => {
696
- const key = `controlled||${ _key }`;
697
- if ( state.tree[ key ] ) {
698
- result[ key ] = state.tree[ key ];
699
- }
700
- return result;
701
- }, {} ),
702
- };
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
+ } );
703
684
  }
704
685
  return stateAfterInsert;
705
686
  };
@@ -724,21 +705,16 @@ const withSaveReusableBlock = ( reducer ) => ( state, action ) => {
724
705
  }
725
706
 
726
707
  state = { ...state };
727
-
728
- state.attributes = mapValues(
729
- state.attributes,
730
- ( attributes, clientId ) => {
731
- const { name } = state.byClientId[ clientId ];
732
- if ( name === 'core/block' && attributes.ref === id ) {
733
- return {
734
- ...attributes,
735
- ref: updatedId,
736
- };
737
- }
738
-
739
- 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
+ } );
740
716
  }
741
- );
717
+ } );
742
718
  }
743
719
 
744
720
  return reducer( state, action );
@@ -784,18 +760,24 @@ export const blocks = pipe(
784
760
  withIgnoredBlockChange,
785
761
  withResetControlledBlocks
786
762
  )( {
787
- 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 ) {
788
767
  switch ( action.type ) {
789
768
  case 'RECEIVE_BLOCKS':
790
- case 'INSERT_BLOCKS':
791
- return {
792
- ...state,
793
- ...getFlattenedBlocksWithoutAttributes( action.blocks ),
794
- };
795
-
796
- 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': {
797
779
  // Ignore updates if block isn't known.
798
- if ( ! state[ action.clientId ] ) {
780
+ if ( ! state.has( action.clientId ) ) {
799
781
  return state;
800
782
  }
801
783
 
@@ -805,142 +787,184 @@ export const blocks = pipe(
805
787
  return state;
806
788
  }
807
789
 
808
- return {
809
- ...state,
810
- [ action.clientId ]: {
811
- ...state[ action.clientId ],
812
- ...changes,
813
- },
814
- };
790
+ const newState = new Map( state );
791
+ newState.set( action.clientId, {
792
+ ...state.get( action.clientId ),
793
+ ...changes,
794
+ } );
795
+ return newState;
796
+ }
815
797
 
816
- case 'REPLACE_BLOCKS_AUGMENTED_WITH_CHILDREN':
798
+ case 'REPLACE_BLOCKS_AUGMENTED_WITH_CHILDREN': {
817
799
  if ( ! action.blocks ) {
818
800
  return state;
819
801
  }
820
802
 
821
- return {
822
- ...omit( state, action.replacedClientIds ),
823
- ...getFlattenedBlocksWithoutAttributes( action.blocks ),
824
- };
803
+ const newState = new Map( state );
804
+ action.replacedClientIds.forEach( ( clientId ) => {
805
+ newState.delete( clientId );
806
+ } );
825
807
 
826
- case 'REMOVE_BLOCKS_AUGMENTED_WITH_CHILDREN':
827
- 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
+ }
828
823
  }
829
824
 
830
825
  return state;
831
826
  },
832
827
 
833
- 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 ) {
834
832
  switch ( action.type ) {
835
833
  case 'RECEIVE_BLOCKS':
836
- case 'INSERT_BLOCKS':
837
- return {
838
- ...state,
839
- ...getFlattenedBlockAttributes( action.blocks ),
840
- };
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
+ }
841
843
 
842
- case 'UPDATE_BLOCK':
844
+ case 'UPDATE_BLOCK': {
843
845
  // Ignore updates if block isn't known or there are no attribute changes.
844
846
  if (
845
- ! state[ action.clientId ] ||
847
+ ! state.get( action.clientId ) ||
846
848
  ! action.updates.attributes
847
849
  ) {
848
850
  return state;
849
851
  }
850
852
 
851
- return {
852
- ...state,
853
- [ action.clientId ]: {
854
- ...state[ action.clientId ],
855
- ...action.updates.attributes,
856
- },
857
- };
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
+ }
858
860
 
859
861
  case 'UPDATE_BLOCK_ATTRIBUTES': {
860
862
  // Avoid a state change if none of the block IDs are known.
861
- if ( action.clientIds.every( ( id ) => ! state[ id ] ) ) {
863
+ if ( action.clientIds.every( ( id ) => ! state.get( id ) ) ) {
862
864
  return state;
863
865
  }
864
866
 
865
- const next = action.clientIds.reduce(
866
- ( accumulator, id ) => ( {
867
- ...accumulator,
868
- [ id ]: Object.entries(
869
- action.uniqueByBlock
870
- ? action.attributes[ id ]
871
- : action.attributes ?? {}
872
- ).reduce( ( result, [ key, value ] ) => {
873
- // Consider as updates only changed values.
874
- if ( value !== result[ key ] ) {
875
- result = getMutateSafeObject(
876
- state[ id ],
877
- result
878
- );
879
- result[ key ] = value;
880
- }
881
-
882
- return result;
883
- }, state[ id ] ),
884
- } ),
885
- {}
886
- );
887
-
888
- if (
889
- action.clientIds.every(
890
- ( id ) => next[ id ] === state[ id ]
891
- )
892
- ) {
893
- 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
+ }
894
894
  }
895
895
 
896
- return { ...state, ...next };
896
+ return hasChange ? newState : state;
897
897
  }
898
898
 
899
- case 'REPLACE_BLOCKS_AUGMENTED_WITH_CHILDREN':
899
+ case 'REPLACE_BLOCKS_AUGMENTED_WITH_CHILDREN': {
900
900
  if ( ! action.blocks ) {
901
901
  return state;
902
902
  }
903
903
 
904
- return {
905
- ...omit( state, action.replacedClientIds ),
906
- ...getFlattenedBlockAttributes( action.blocks ),
907
- };
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
+ }
908
915
 
909
- case 'REMOVE_BLOCKS_AUGMENTED_WITH_CHILDREN':
910
- 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
+ }
911
923
  }
912
924
 
913
925
  return state;
914
926
  },
915
927
 
916
- 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 ) {
917
932
  switch ( action.type ) {
918
933
  case 'RECEIVE_BLOCKS': {
919
934
  const blockOrder = mapBlockOrder( action.blocks );
920
- return {
921
- ...state,
922
- ...omit( blockOrder, '' ),
923
- '': ( state?.[ '' ] || [] ).concat( blockOrder[ '' ] ),
924
- };
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;
925
946
  }
926
947
  case 'INSERT_BLOCKS': {
927
948
  const { rootClientId = '' } = action;
928
- const subState = state[ rootClientId ] || [];
949
+ const subState = state.get( rootClientId ) || [];
929
950
  const mappedBlocks = mapBlockOrder(
930
951
  action.blocks,
931
952
  rootClientId
932
953
  );
933
954
  const { index = subState.length } = action;
934
-
935
- return {
936
- ...state,
937
- ...mappedBlocks,
938
- [ 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(
939
962
  subState,
940
- mappedBlocks[ rootClientId ],
963
+ mappedBlocks.get( rootClientId ),
941
964
  index
942
- ),
943
- };
965
+ )
966
+ );
967
+ return newState;
944
968
  }
945
969
 
946
970
  case 'MOVE_BLOCKS_TO_POSITION': {
@@ -949,65 +973,68 @@ export const blocks = pipe(
949
973
  toRootClientId = '',
950
974
  clientIds,
951
975
  } = action;
952
- const { index = state[ toRootClientId ].length } = action;
976
+ const { index = state.get( toRootClientId ).length } = action;
953
977
 
954
978
  // Moving inside the same parent block.
955
979
  if ( fromRootClientId === toRootClientId ) {
956
- const subState = state[ toRootClientId ];
980
+ const subState = state.get( toRootClientId );
957
981
  const fromIndex = subState.indexOf( clientIds[ 0 ] );
958
- return {
959
- ...state,
960
- [ toRootClientId ]: moveTo(
961
- state[ toRootClientId ],
982
+ const newState = new Map( state );
983
+ newState.set(
984
+ toRootClientId,
985
+ moveTo(
986
+ state.get( toRootClientId ),
962
987
  fromIndex,
963
988
  index,
964
989
  clientIds.length
965
- ),
966
- };
990
+ )
991
+ );
992
+ return newState;
967
993
  }
968
994
 
969
995
  // Moving from a parent block to another.
970
- return {
971
- ...state,
972
- [ fromRootClientId ]:
973
- state[ fromRootClientId ]?.filter(
974
- ( id ) => ! clientIds.includes( id )
975
- ) ?? [],
976
- [ toRootClientId ]: insertAt(
977
- state[ toRootClientId ],
978
- clientIds,
979
- index
980
- ),
981
- };
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;
982
1008
  }
983
1009
 
984
1010
  case 'MOVE_BLOCKS_UP': {
985
1011
  const { clientIds, rootClientId = '' } = action;
986
1012
  const firstClientId = clientIds[ 0 ];
987
- const subState = state[ rootClientId ];
1013
+ const subState = state.get( rootClientId );
988
1014
 
989
1015
  if ( ! subState.length || firstClientId === subState[ 0 ] ) {
990
1016
  return state;
991
1017
  }
992
1018
 
993
1019
  const firstIndex = subState.indexOf( firstClientId );
994
-
995
- return {
996
- ...state,
997
- [ rootClientId ]: moveTo(
1020
+ const newState = new Map( state );
1021
+ newState.set(
1022
+ rootClientId,
1023
+ moveTo(
998
1024
  subState,
999
1025
  firstIndex,
1000
1026
  firstIndex - 1,
1001
1027
  clientIds.length
1002
- ),
1003
- };
1028
+ )
1029
+ );
1030
+ return newState;
1004
1031
  }
1005
1032
 
1006
1033
  case 'MOVE_BLOCKS_DOWN': {
1007
1034
  const { clientIds, rootClientId = '' } = action;
1008
1035
  const firstClientId = clientIds[ 0 ];
1009
1036
  const lastClientId = clientIds[ clientIds.length - 1 ];
1010
- const subState = state[ rootClientId ];
1037
+ const subState = state.get( rootClientId );
1011
1038
 
1012
1039
  if (
1013
1040
  ! subState.length ||
@@ -1017,16 +1044,17 @@ export const blocks = pipe(
1017
1044
  }
1018
1045
 
1019
1046
  const firstIndex = subState.indexOf( firstClientId );
1020
-
1021
- return {
1022
- ...state,
1023
- [ rootClientId ]: moveTo(
1047
+ const newState = new Map( state );
1048
+ newState.set(
1049
+ rootClientId,
1050
+ moveTo(
1024
1051
  subState,
1025
1052
  firstIndex,
1026
1053
  firstIndex + 1,
1027
1054
  clientIds.length
1028
- ),
1029
- };
1055
+ )
1056
+ );
1057
+ return newState;
1030
1058
  }
1031
1059
 
1032
1060
  case 'REPLACE_BLOCKS_AUGMENTED_WITH_CHILDREN': {
@@ -1036,55 +1064,52 @@ export const blocks = pipe(
1036
1064
  }
1037
1065
 
1038
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
+ }
1039
1082
 
1040
- return pipe( [
1041
- ( nextState ) =>
1042
- omit( nextState, action.replacedClientIds ),
1043
- ( nextState ) => ( {
1044
- ...nextState,
1045
- ...omit( mappedBlocks, '' ),
1046
- } ),
1047
- ( nextState ) =>
1048
- mapValues( nextState, ( subState ) =>
1049
- Object.values( subState ).reduce(
1050
- ( result, clientId ) => {
1051
- if ( clientId === clientIds[ 0 ] ) {
1052
- return [
1053
- ...result,
1054
- ...mappedBlocks[ '' ],
1055
- ];
1056
- }
1057
-
1058
- if (
1059
- clientIds.indexOf( clientId ) === -1
1060
- ) {
1061
- result.push( clientId );
1062
- }
1063
-
1064
- return result;
1065
- },
1066
- []
1067
- )
1068
- ),
1069
- ] )( state );
1083
+ if ( clientIds.indexOf( subClientId ) === -1 ) {
1084
+ result.push( subClientId );
1085
+ }
1086
+
1087
+ return result;
1088
+ },
1089
+ []
1090
+ );
1091
+ newState.set( clientId, newSubOrder );
1092
+ } );
1093
+ return newState;
1070
1094
  }
1071
1095
 
1072
- case 'REMOVE_BLOCKS_AUGMENTED_WITH_CHILDREN':
1073
- return pipe( [
1074
- // Remove inner block ordering for removed blocks.
1075
- ( nextState ) => omit( nextState, action.removedClientIds ),
1076
-
1077
- // Remove deleted blocks from other blocks' orderings.
1078
- ( nextState ) =>
1079
- mapValues(
1080
- nextState,
1081
- ( subState ) =>
1082
- subState?.filter(
1083
- ( id ) =>
1084
- ! action.removedClientIds.includes( id )
1085
- ) ?? []
1086
- ),
1087
- ] )( 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
+ }
1088
1113
  }
1089
1114
 
1090
1115
  return state;
@@ -1092,44 +1117,55 @@ export const blocks = pipe(
1092
1117
 
1093
1118
  // While technically redundant data as the inverse of `order`, it serves as
1094
1119
  // an optimization for the selectors which derive the ancestry of a block.
1095
- parents( state = {}, action ) {
1120
+ parents( state = new Map(), action ) {
1096
1121
  switch ( action.type ) {
1097
- case 'RECEIVE_BLOCKS':
1098
- return {
1099
- ...state,
1100
- ...mapBlockParents( action.blocks ),
1101
- };
1102
-
1103
- case 'INSERT_BLOCKS':
1104
- return {
1105
- ...state,
1106
- ...mapBlockParents(
1107
- action.blocks,
1108
- action.rootClientId || ''
1109
- ),
1110
- };
1111
-
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
+ }
1112
1141
  case 'MOVE_BLOCKS_TO_POSITION': {
1113
- return {
1114
- ...state,
1115
- ...action.clientIds.reduce( ( accumulator, id ) => {
1116
- accumulator[ id ] = action.toRootClientId || '';
1117
- return accumulator;
1118
- }, {} ),
1119
- };
1142
+ const newState = new Map( state );
1143
+ action.clientIds.forEach( ( id ) => {
1144
+ newState.set( id, action.toRootClientId || '' );
1145
+ } );
1146
+ return newState;
1120
1147
  }
1121
1148
 
1122
- case 'REPLACE_BLOCKS_AUGMENTED_WITH_CHILDREN':
1123
- return {
1124
- ...omit( state, action.replacedClientIds ),
1125
- ...mapBlockParents(
1126
- action.blocks,
1127
- state[ action.clientIds[ 0 ] ]
1128
- ),
1129
- };
1130
-
1131
- case 'REMOVE_BLOCKS_AUGMENTED_WITH_CHILDREN':
1132
- 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
+ }
1133
1169
  }
1134
1170
 
1135
1171
  return state;
@@ -1492,7 +1528,7 @@ export function insertionPoint( state = null, action ) {
1492
1528
  };
1493
1529
 
1494
1530
  // Bail out updates if the states are the same.
1495
- return isEqual( state, nextState ) ? state : nextState;
1531
+ return fastDeepEqual( state, nextState ) ? state : nextState;
1496
1532
  }
1497
1533
 
1498
1534
  case 'HIDE_INSERTION_POINT':
@@ -1617,7 +1653,7 @@ export const blockListSettings = ( state = {}, action ) => {
1617
1653
  return state;
1618
1654
  }
1619
1655
 
1620
- if ( isEqual( state[ clientId ], action.settings ) ) {
1656
+ if ( fastDeepEqual( state[ clientId ], action.settings ) ) {
1621
1657
  return state;
1622
1658
  }
1623
1659