@wordpress/block-editor 15.23.0 → 16.0.1-next.v.202607070741.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 (363) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/build/autocompleters/block.cjs +10 -2
  3. package/build/autocompleters/block.cjs.map +2 -2
  4. package/build/components/background-image-control/index.cjs +0 -2
  5. package/build/components/background-image-control/index.cjs.map +2 -2
  6. package/build/components/block-inspector/edit-contents.cjs +3 -0
  7. package/build/components/block-inspector/edit-contents.cjs.map +3 -3
  8. package/build/components/block-inspector/index.cjs +2 -3
  9. package/build/components/block-inspector/index.cjs.map +2 -2
  10. package/build/components/block-list/block-invalid-warning.cjs +8 -19
  11. package/build/components/block-list/block-invalid-warning.cjs.map +2 -2
  12. package/build/components/block-styles/use-styles-for-block.cjs +2 -1
  13. package/build/components/block-styles/use-styles-for-block.cjs.map +2 -2
  14. package/build/components/block-title/use-block-display-title.cjs +7 -2
  15. package/build/components/block-title/use-block-display-title.cjs.map +2 -2
  16. package/build/components/block-toolbar/block-toolbar-icon.cjs +10 -14
  17. package/build/components/block-toolbar/block-toolbar-icon.cjs.map +2 -2
  18. package/build/components/block-variation-transforms/index.cjs +0 -1
  19. package/build/components/block-variation-transforms/index.cjs.map +2 -2
  20. package/build/components/child-layout-control/index.cjs +0 -2
  21. package/build/components/child-layout-control/index.cjs.map +2 -2
  22. package/build/components/colors-gradients/control.cjs +5 -5
  23. package/build/components/colors-gradients/control.cjs.map +2 -2
  24. package/build/components/date-format-picker/index.cjs +0 -1
  25. package/build/components/date-format-picker/index.cjs.map +2 -2
  26. package/build/components/dimensions-tool/aspect-ratio-tool.cjs +1 -2
  27. package/build/components/dimensions-tool/aspect-ratio-tool.cjs.map +2 -2
  28. package/build/components/dimensions-tool/scale-tool.cjs +0 -1
  29. package/build/components/dimensions-tool/scale-tool.cjs.map +2 -2
  30. package/build/components/dimensions-tool/width-height-tool.cjs +2 -4
  31. package/build/components/dimensions-tool/width-height-tool.cjs.map +2 -2
  32. package/build/components/font-appearance-control/index.cjs +6 -25
  33. package/build/components/font-appearance-control/index.cjs.map +3 -3
  34. package/build/components/font-family/index.cjs +6 -15
  35. package/build/components/font-family/index.cjs.map +3 -3
  36. package/build/components/font-sizes/font-size-picker.cjs +1 -2
  37. package/build/components/font-sizes/font-size-picker.cjs.map +2 -2
  38. package/build/components/global-styles/border-panel.cjs +0 -1
  39. package/build/components/global-styles/border-panel.cjs.map +2 -2
  40. package/build/components/global-styles/dimensions-panel.cjs +0 -3
  41. package/build/components/global-styles/dimensions-panel.cjs.map +2 -2
  42. package/build/components/global-styles/typography-panel.cjs +4 -10
  43. package/build/components/global-styles/typography-panel.cjs.map +2 -2
  44. package/build/components/height-control/index.cjs +0 -2
  45. package/build/components/height-control/index.cjs.map +2 -2
  46. package/build/components/html-element-control/index.cjs +0 -1
  47. package/build/components/html-element-control/index.cjs.map +2 -2
  48. package/build/components/image-editor/index.cjs +5 -0
  49. package/build/components/image-editor/index.cjs.map +3 -3
  50. package/build/components/image-editor/zoom-dropdown.cjs +0 -1
  51. package/build/components/image-editor/zoom-dropdown.cjs.map +2 -2
  52. package/build/components/image-size-control/index.cjs +1 -3
  53. package/build/components/image-size-control/index.cjs.map +2 -2
  54. package/build/components/inner-content/index.cjs +107 -0
  55. package/build/components/inner-content/index.cjs.map +7 -0
  56. package/build/components/inserter/hooks/use-block-types-state.cjs +10 -2
  57. package/build/components/inserter/hooks/use-block-types-state.cjs.map +2 -2
  58. package/build/components/inserter/media-tab/hooks.cjs +34 -6
  59. package/build/components/inserter/media-tab/hooks.cjs.map +2 -2
  60. package/build/components/inserter/media-tab/media-list.cjs +3 -1
  61. package/build/components/inserter/media-tab/media-list.cjs.map +2 -2
  62. package/build/components/inserter/media-tab/media-panel.cjs +224 -27
  63. package/build/components/inserter/media-tab/media-panel.cjs.map +3 -3
  64. package/build/components/inserter/media-tab/media-preview.cjs +32 -17
  65. package/build/components/inserter/media-tab/media-preview.cjs.map +2 -2
  66. package/build/components/inserter/media-tab/media-tab.cjs +26 -6
  67. package/build/components/inserter/media-tab/media-tab.cjs.map +2 -2
  68. package/build/components/inserter/mobile-tab-navigation.cjs +6 -1
  69. package/build/components/inserter/mobile-tab-navigation.cjs.map +2 -2
  70. package/build/components/inserter/no-results.cjs +2 -2
  71. package/build/components/inserter/no-results.cjs.map +2 -2
  72. package/build/components/inserter/preview-panel.cjs +2 -1
  73. package/build/components/inserter/preview-panel.cjs.map +2 -2
  74. package/build/components/inserter-list-item/index.cjs +8 -2
  75. package/build/components/inserter-list-item/index.cjs.map +2 -2
  76. package/build/components/letter-spacing-control/index.cjs +0 -24
  77. package/build/components/letter-spacing-control/index.cjs.map +3 -3
  78. package/build/components/line-height-control/index.cjs +7 -22
  79. package/build/components/line-height-control/index.cjs.map +3 -3
  80. package/build/components/list-view/block-select-button.cjs +90 -84
  81. package/build/components/list-view/block-select-button.cjs.map +2 -2
  82. package/build/components/list-view/block.cjs +51 -20
  83. package/build/components/list-view/block.cjs.map +2 -2
  84. package/build/components/list-view/expander.cjs +1 -1
  85. package/build/components/list-view/expander.cjs.map +2 -2
  86. package/build/components/list-view/use-list-view-client-ids.cjs +2 -2
  87. package/build/components/list-view/use-list-view-client-ids.cjs.map +2 -2
  88. package/build/components/observe-typing/index.cjs +4 -3
  89. package/build/components/observe-typing/index.cjs.map +2 -2
  90. package/build/components/preset-input-control/custom-value-controls.cjs +1 -3
  91. package/build/components/preset-input-control/custom-value-controls.cjs.map +2 -2
  92. package/build/components/preset-input-control/index.cjs +1 -3
  93. package/build/components/preset-input-control/index.cjs.map +2 -2
  94. package/build/components/resolution-tool/index.cjs +1 -2
  95. package/build/components/resolution-tool/index.cjs.map +2 -2
  96. package/build/components/text-alignment-control/index.cjs +0 -1
  97. package/build/components/text-alignment-control/index.cjs.map +2 -2
  98. package/build/components/text-decoration-control/index.cjs +0 -1
  99. package/build/components/text-decoration-control/index.cjs.map +2 -2
  100. package/build/components/text-indent-control/index.cjs +0 -8
  101. package/build/components/text-indent-control/index.cjs.map +2 -2
  102. package/build/components/text-transform-control/index.cjs +0 -1
  103. package/build/components/text-transform-control/index.cjs.map +2 -2
  104. package/build/components/use-block-display-information/index.cjs +10 -8
  105. package/build/components/use-block-display-information/index.cjs.map +2 -2
  106. package/build/components/use-on-block-drop/index.cjs +3 -7
  107. package/build/components/use-on-block-drop/index.cjs.map +2 -2
  108. package/build/components/writing-mode-control/index.cjs +0 -1
  109. package/build/components/writing-mode-control/index.cjs.map +2 -2
  110. package/build/hooks/font-size.cjs +1 -2
  111. package/build/hooks/font-size.cjs.map +2 -2
  112. package/build/hooks/layout.cjs +5 -3
  113. package/build/hooks/layout.cjs.map +2 -2
  114. package/build/hooks/position.cjs +36 -16
  115. package/build/hooks/position.cjs.map +2 -2
  116. package/build/hooks/states.cjs +6 -9
  117. package/build/hooks/states.cjs.map +2 -2
  118. package/build/layouts/constrained.cjs +21 -21
  119. package/build/layouts/constrained.cjs.map +2 -2
  120. package/build/layouts/flex.cjs +0 -3
  121. package/build/layouts/flex.cjs.map +2 -2
  122. package/build/layouts/grid.cjs +51 -9
  123. package/build/layouts/grid.cjs.map +2 -2
  124. package/build/private-apis.cjs +4 -1
  125. package/build/private-apis.cjs.map +3 -3
  126. package/build/store/actions.cjs.map +2 -2
  127. package/build/store/private-keys.cjs +3 -0
  128. package/build/store/private-keys.cjs.map +2 -2
  129. package/build/store/private-selectors.cjs +72 -4
  130. package/build/store/private-selectors.cjs.map +2 -2
  131. package/build/store/selectors.cjs +13 -0
  132. package/build/store/selectors.cjs.map +2 -2
  133. package/build-module/autocompleters/block.mjs +10 -2
  134. package/build-module/autocompleters/block.mjs.map +2 -2
  135. package/build-module/components/background-image-control/index.mjs +0 -2
  136. package/build-module/components/background-image-control/index.mjs.map +2 -2
  137. package/build-module/components/block-inspector/edit-contents.mjs +4 -1
  138. package/build-module/components/block-inspector/edit-contents.mjs.map +2 -2
  139. package/build-module/components/block-inspector/index.mjs +2 -3
  140. package/build-module/components/block-inspector/index.mjs.map +2 -2
  141. package/build-module/components/block-list/block-invalid-warning.mjs +8 -19
  142. package/build-module/components/block-list/block-invalid-warning.mjs.map +2 -2
  143. package/build-module/components/block-styles/use-styles-for-block.mjs +2 -1
  144. package/build-module/components/block-styles/use-styles-for-block.mjs.map +2 -2
  145. package/build-module/components/block-title/use-block-display-title.mjs +7 -2
  146. package/build-module/components/block-title/use-block-display-title.mjs.map +2 -2
  147. package/build-module/components/block-toolbar/block-toolbar-icon.mjs +10 -14
  148. package/build-module/components/block-toolbar/block-toolbar-icon.mjs.map +2 -2
  149. package/build-module/components/block-variation-transforms/index.mjs +0 -1
  150. package/build-module/components/block-variation-transforms/index.mjs.map +2 -2
  151. package/build-module/components/child-layout-control/index.mjs +0 -2
  152. package/build-module/components/child-layout-control/index.mjs.map +2 -2
  153. package/build-module/components/colors-gradients/control.mjs +5 -5
  154. package/build-module/components/colors-gradients/control.mjs.map +2 -2
  155. package/build-module/components/date-format-picker/index.mjs +0 -1
  156. package/build-module/components/date-format-picker/index.mjs.map +2 -2
  157. package/build-module/components/dimensions-tool/aspect-ratio-tool.mjs +1 -2
  158. package/build-module/components/dimensions-tool/aspect-ratio-tool.mjs.map +2 -2
  159. package/build-module/components/dimensions-tool/scale-tool.mjs +0 -1
  160. package/build-module/components/dimensions-tool/scale-tool.mjs.map +2 -2
  161. package/build-module/components/dimensions-tool/width-height-tool.mjs +2 -4
  162. package/build-module/components/dimensions-tool/width-height-tool.mjs.map +2 -2
  163. package/build-module/components/font-appearance-control/index.mjs +6 -15
  164. package/build-module/components/font-appearance-control/index.mjs.map +2 -2
  165. package/build-module/components/font-family/index.mjs +6 -15
  166. package/build-module/components/font-family/index.mjs.map +2 -2
  167. package/build-module/components/font-sizes/font-size-picker.mjs +1 -2
  168. package/build-module/components/font-sizes/font-size-picker.mjs.map +2 -2
  169. package/build-module/components/global-styles/border-panel.mjs +0 -1
  170. package/build-module/components/global-styles/border-panel.mjs.map +2 -2
  171. package/build-module/components/global-styles/dimensions-panel.mjs +0 -3
  172. package/build-module/components/global-styles/dimensions-panel.mjs.map +2 -2
  173. package/build-module/components/global-styles/typography-panel.mjs +4 -10
  174. package/build-module/components/global-styles/typography-panel.mjs.map +2 -2
  175. package/build-module/components/height-control/index.mjs +0 -2
  176. package/build-module/components/height-control/index.mjs.map +2 -2
  177. package/build-module/components/html-element-control/index.mjs +0 -1
  178. package/build-module/components/html-element-control/index.mjs.map +2 -2
  179. package/build-module/components/image-editor/index.mjs +5 -0
  180. package/build-module/components/image-editor/index.mjs.map +2 -2
  181. package/build-module/components/image-editor/zoom-dropdown.mjs +0 -1
  182. package/build-module/components/image-editor/zoom-dropdown.mjs.map +2 -2
  183. package/build-module/components/image-size-control/index.mjs +1 -3
  184. package/build-module/components/image-size-control/index.mjs.map +2 -2
  185. package/build-module/components/inner-content/index.mjs +82 -0
  186. package/build-module/components/inner-content/index.mjs.map +7 -0
  187. package/build-module/components/inserter/hooks/use-block-types-state.mjs +10 -2
  188. package/build-module/components/inserter/hooks/use-block-types-state.mjs.map +2 -2
  189. package/build-module/components/inserter/media-tab/hooks.mjs +33 -6
  190. package/build-module/components/inserter/media-tab/hooks.mjs.map +2 -2
  191. package/build-module/components/inserter/media-tab/media-list.mjs +3 -1
  192. package/build-module/components/inserter/media-tab/media-list.mjs.map +2 -2
  193. package/build-module/components/inserter/media-tab/media-panel.mjs +227 -30
  194. package/build-module/components/inserter/media-tab/media-panel.mjs.map +2 -2
  195. package/build-module/components/inserter/media-tab/media-preview.mjs +33 -18
  196. package/build-module/components/inserter/media-tab/media-preview.mjs.map +2 -2
  197. package/build-module/components/inserter/media-tab/media-tab.mjs +27 -7
  198. package/build-module/components/inserter/media-tab/media-tab.mjs.map +2 -2
  199. package/build-module/components/inserter/mobile-tab-navigation.mjs +6 -1
  200. package/build-module/components/inserter/mobile-tab-navigation.mjs.map +2 -2
  201. package/build-module/components/inserter/no-results.mjs +2 -2
  202. package/build-module/components/inserter/no-results.mjs.map +2 -2
  203. package/build-module/components/inserter/preview-panel.mjs +2 -1
  204. package/build-module/components/inserter/preview-panel.mjs.map +2 -2
  205. package/build-module/components/inserter-list-item/index.mjs +8 -2
  206. package/build-module/components/inserter-list-item/index.mjs.map +2 -2
  207. package/build-module/components/letter-spacing-control/index.mjs +0 -14
  208. package/build-module/components/letter-spacing-control/index.mjs.map +2 -2
  209. package/build-module/components/line-height-control/index.mjs +7 -12
  210. package/build-module/components/line-height-control/index.mjs.map +2 -2
  211. package/build-module/components/list-view/block-select-button.mjs +90 -84
  212. package/build-module/components/list-view/block-select-button.mjs.map +2 -2
  213. package/build-module/components/list-view/block.mjs +51 -20
  214. package/build-module/components/list-view/block.mjs.map +2 -2
  215. package/build-module/components/list-view/expander.mjs +1 -1
  216. package/build-module/components/list-view/expander.mjs.map +2 -2
  217. package/build-module/components/list-view/use-list-view-client-ids.mjs +2 -2
  218. package/build-module/components/list-view/use-list-view-client-ids.mjs.map +2 -2
  219. package/build-module/components/observe-typing/index.mjs +4 -3
  220. package/build-module/components/observe-typing/index.mjs.map +2 -2
  221. package/build-module/components/preset-input-control/custom-value-controls.mjs +1 -3
  222. package/build-module/components/preset-input-control/custom-value-controls.mjs.map +2 -2
  223. package/build-module/components/preset-input-control/index.mjs +1 -3
  224. package/build-module/components/preset-input-control/index.mjs.map +2 -2
  225. package/build-module/components/resolution-tool/index.mjs +1 -2
  226. package/build-module/components/resolution-tool/index.mjs.map +2 -2
  227. package/build-module/components/text-alignment-control/index.mjs +0 -1
  228. package/build-module/components/text-alignment-control/index.mjs.map +2 -2
  229. package/build-module/components/text-decoration-control/index.mjs +0 -1
  230. package/build-module/components/text-decoration-control/index.mjs.map +2 -2
  231. package/build-module/components/text-indent-control/index.mjs +0 -8
  232. package/build-module/components/text-indent-control/index.mjs.map +2 -2
  233. package/build-module/components/text-transform-control/index.mjs +0 -1
  234. package/build-module/components/text-transform-control/index.mjs.map +2 -2
  235. package/build-module/components/use-block-display-information/index.mjs +10 -8
  236. package/build-module/components/use-block-display-information/index.mjs.map +2 -2
  237. package/build-module/components/use-on-block-drop/index.mjs +4 -7
  238. package/build-module/components/use-on-block-drop/index.mjs.map +2 -2
  239. package/build-module/components/writing-mode-control/index.mjs +0 -1
  240. package/build-module/components/writing-mode-control/index.mjs.map +2 -2
  241. package/build-module/hooks/font-size.mjs +1 -2
  242. package/build-module/hooks/font-size.mjs.map +2 -2
  243. package/build-module/hooks/layout.mjs +4 -3
  244. package/build-module/hooks/layout.mjs.map +2 -2
  245. package/build-module/hooks/position.mjs +38 -18
  246. package/build-module/hooks/position.mjs.map +2 -2
  247. package/build-module/hooks/states.mjs +6 -9
  248. package/build-module/hooks/states.mjs.map +2 -2
  249. package/build-module/layouts/constrained.mjs +21 -21
  250. package/build-module/layouts/constrained.mjs.map +2 -2
  251. package/build-module/layouts/flex.mjs +0 -3
  252. package/build-module/layouts/flex.mjs.map +2 -2
  253. package/build-module/layouts/grid.mjs +52 -9
  254. package/build-module/layouts/grid.mjs.map +2 -2
  255. package/build-module/private-apis.mjs +5 -1
  256. package/build-module/private-apis.mjs.map +2 -2
  257. package/build-module/store/actions.mjs.map +2 -2
  258. package/build-module/store/private-keys.mjs +2 -0
  259. package/build-module/store/private-keys.mjs.map +2 -2
  260. package/build-module/store/private-selectors.mjs +71 -4
  261. package/build-module/store/private-selectors.mjs.map +2 -2
  262. package/build-module/store/selectors.mjs +13 -0
  263. package/build-module/store/selectors.mjs.map +2 -2
  264. package/build-style/content-rtl.css +11 -5
  265. package/build-style/content.css +11 -5
  266. package/build-style/style-rtl.css +113 -3
  267. package/build-style/style.css +113 -3
  268. package/package.json +43 -41
  269. package/src/autocompleters/block.js +10 -3
  270. package/src/autocompleters/test/block.js +53 -0
  271. package/src/components/background-image-control/index.js +0 -2
  272. package/src/components/block-inspector/edit-contents.js +5 -1
  273. package/src/components/block-inspector/index.js +3 -2
  274. package/src/components/block-list/block-invalid-warning.js +8 -19
  275. package/src/components/block-patterns-list/stories/index.story.jsx +1 -1
  276. package/src/components/block-styles/use-styles-for-block.js +1 -0
  277. package/src/components/block-title/use-block-display-title.js +7 -2
  278. package/src/components/block-toolbar/block-toolbar-icon.js +11 -16
  279. package/src/components/block-toolbar/test/block-toolbar-icon.js +32 -9
  280. package/src/components/block-variation-transforms/index.js +0 -1
  281. package/src/components/child-layout-control/index.js +0 -2
  282. package/src/components/color-palette/test/__snapshots__/control.js.snap +11 -106
  283. package/src/components/colors-gradients/control.js +4 -4
  284. package/src/components/colors-gradients/style.scss +2 -2
  285. package/src/components/date-format-picker/index.js +0 -1
  286. package/src/components/dimensions-tool/aspect-ratio-tool.js +0 -1
  287. package/src/components/dimensions-tool/scale-tool.js +0 -1
  288. package/src/components/dimensions-tool/width-height-tool.js +0 -2
  289. package/src/components/font-appearance-control/index.js +6 -19
  290. package/src/components/font-family/README.md +0 -9
  291. package/src/components/font-family/index.js +6 -19
  292. package/src/components/font-family/stories/index.story.jsx +0 -1
  293. package/src/components/font-sizes/font-size-picker.js +0 -1
  294. package/src/components/global-styles/border-panel.js +0 -1
  295. package/src/components/global-styles/dimensions-panel.js +0 -3
  296. package/src/components/global-styles/typography-panel.js +0 -6
  297. package/src/components/height-control/index.js +0 -2
  298. package/src/components/html-element-control/index.js +0 -1
  299. package/src/components/iframe/content.scss +3 -3
  300. package/src/components/image-editor/index.js +22 -0
  301. package/src/components/image-editor/zoom-dropdown.js +0 -1
  302. package/src/components/image-size-control/index.js +0 -2
  303. package/src/components/inner-content/index.js +119 -0
  304. package/src/components/inner-content/test/index.js +81 -0
  305. package/src/components/inserter/hooks/use-block-types-state.js +10 -2
  306. package/src/components/inserter/media-tab/hooks.js +59 -9
  307. package/src/components/inserter/media-tab/media-list.js +2 -0
  308. package/src/components/inserter/media-tab/media-panel.js +256 -17
  309. package/src/components/inserter/media-tab/media-preview.js +34 -17
  310. package/src/components/inserter/media-tab/media-tab.js +20 -2
  311. package/src/components/inserter/media-tab/test/hooks.js +204 -0
  312. package/src/components/inserter/mobile-tab-navigation.js +6 -1
  313. package/src/components/inserter/no-results.js +2 -2
  314. package/src/components/inserter/preview-panel.js +1 -0
  315. package/src/components/inserter/style.scss +110 -1
  316. package/src/components/inserter-list-item/index.js +8 -2
  317. package/src/components/letter-spacing-control/README.md +0 -8
  318. package/src/components/letter-spacing-control/index.js +5 -23
  319. package/src/components/letter-spacing-control/stories/index.story.jsx +0 -12
  320. package/src/components/line-height-control/README.md +0 -8
  321. package/src/components/line-height-control/index.js +7 -16
  322. package/src/components/line-height-control/stories/index.story.jsx +0 -1
  323. package/src/components/line-height-control/test/index.js +1 -7
  324. package/src/components/link-picker/test/index.js +3 -1
  325. package/src/components/list-view/block-select-button.js +5 -1
  326. package/src/components/list-view/block.js +57 -20
  327. package/src/components/list-view/expander.js +5 -1
  328. package/src/components/list-view/style.scss +19 -0
  329. package/src/components/list-view/use-list-view-client-ids.js +2 -2
  330. package/src/components/observe-typing/index.js +9 -4
  331. package/src/components/preset-input-control/custom-value-controls.js +0 -2
  332. package/src/components/preset-input-control/index.js +0 -2
  333. package/src/components/resolution-tool/index.js +0 -1
  334. package/src/components/responsive-block-control/test/index.js +1 -5
  335. package/src/components/text-alignment-control/index.js +0 -1
  336. package/src/components/text-decoration-control/index.js +0 -1
  337. package/src/components/text-indent-control/index.js +7 -16
  338. package/src/components/text-transform-control/index.js +0 -1
  339. package/src/components/use-block-display-information/index.js +9 -13
  340. package/src/components/use-block-display-information/test/index.js +47 -9
  341. package/src/components/use-on-block-drop/index.js +4 -7
  342. package/src/components/writing-mode-control/index.js +0 -1
  343. package/src/hooks/block-hooks.scss +15 -0
  344. package/src/hooks/font-size.js +0 -1
  345. package/src/hooks/layout.js +5 -4
  346. package/src/hooks/position.js +44 -23
  347. package/src/hooks/states.js +6 -12
  348. package/src/hooks/test/cross-origin-isolation.js +0 -4
  349. package/src/hooks/test/layout.js +75 -1
  350. package/src/layouts/constrained.js +51 -28
  351. package/src/layouts/flex.js +0 -3
  352. package/src/layouts/grid.js +59 -7
  353. package/src/layouts/test/constrained.js +91 -0
  354. package/src/layouts/test/grid.js +71 -0
  355. package/src/private-apis.js +4 -0
  356. package/src/store/actions.js +1 -0
  357. package/src/store/private-keys.js +1 -0
  358. package/src/store/private-selectors.js +141 -4
  359. package/src/store/selectors.js +41 -0
  360. package/src/store/test/private-selectors.js +422 -0
  361. package/src/store/test/reducer.js +11 -11
  362. package/src/store/test/selectors.js +133 -0
  363. package/src/style.scss +1 -0
@@ -1,29 +1,200 @@
1
+ /**
2
+ * External dependencies
3
+ */
4
+ import clsx from 'clsx';
5
+
1
6
  /**
2
7
  * WordPress dependencies
3
8
  */
4
- import { Spinner, SearchControl } from '@wordpress/components';
5
- import { __ } from '@wordpress/i18n';
9
+ import { Button, Modal, Spinner, SearchControl } from '@wordpress/components';
10
+ import { __, _n, sprintf } from '@wordpress/i18n';
11
+ import { useCallback, useMemo, useState } from '@wordpress/element';
6
12
  import { useDebouncedInput } from '@wordpress/compose';
13
+ import { useDispatch } from '@wordpress/data';
14
+ import { store as noticesStore } from '@wordpress/notices';
7
15
 
8
16
  /**
9
17
  * Internal dependencies
10
18
  */
11
19
  import MediaList from './media-list';
12
- import { useMediaResults } from './hooks';
20
+ import MediaUpload from '../../media-upload';
21
+ import MediaUploadCheck from '../../media-upload/check';
22
+ import { useMediaResults, useDelayedLoading } from './hooks';
13
23
  import InserterNoResults from '../no-results';
14
24
 
15
25
  const INITIAL_MEDIA_ITEMS_PER_PAGE = 10;
16
26
 
27
+ // The attach flow is image-only, so the picker is constrained to images.
28
+ const ATTACH_ALLOWED_TYPES = [ 'image' ];
29
+
30
+ /**
31
+ * Opens the Media Library to attach images to the current post. Only rendered
32
+ * for media categories that expose an `attach` capability (i.e. the "Attached
33
+ * images" source); other sources render the panel exactly as before.
34
+ *
35
+ * The picker opens fresh each time with no pre-selected value, so it is purely
36
+ * additive: selecting images attaches them, and it does not imply that
37
+ * deselecting would detach. Detaching is a separate, explicit per-item action.
38
+ *
39
+ * @param {Object} props
40
+ * @param {Function} props.onSelect Called with the selected media items.
41
+ */
42
+ function AttachImagesButton( { onSelect } ) {
43
+ return (
44
+ <MediaUploadCheck>
45
+ <MediaUpload
46
+ multiple="add"
47
+ onSelect={ onSelect }
48
+ allowedTypes={ ATTACH_ALLOWED_TYPES }
49
+ title={ __( 'Attach images' ) }
50
+ render={ ( { open } ) => (
51
+ <Button
52
+ __next40pxDefaultSize
53
+ className="block-editor-inserter__media-panel-attach"
54
+ data-unstable-ignore-focus-outside-for-relatedtarget=".media-modal"
55
+ onClick={ ( event ) => {
56
+ event.target.focus();
57
+ open();
58
+ } }
59
+ variant="secondary"
60
+ >
61
+ { __( 'Attach images' ) }
62
+ </Button>
63
+ ) }
64
+ />
65
+ </MediaUploadCheck>
66
+ );
67
+ }
68
+
17
69
  export function MediaCategoryPanel( { rootClientId, onInsert, category } ) {
18
70
  const [ search, setSearch, debouncedSearch ] = useDebouncedInput();
19
- const { mediaList, isLoading } = useMediaResults( category, {
20
- per_page: !! debouncedSearch ? 20 : INITIAL_MEDIA_ITEMS_PER_PAGE,
21
- search: debouncedSearch,
22
- } );
71
+ const query = useMemo(
72
+ () => ( {
73
+ per_page: !! debouncedSearch ? 20 : INITIAL_MEDIA_ITEMS_PER_PAGE,
74
+ search: debouncedSearch,
75
+ } ),
76
+ [ debouncedSearch ]
77
+ );
78
+ const [ refreshKey, setRefreshKey ] = useState( 0 );
79
+ const { mediaList, isLoading } = useMediaResults(
80
+ category,
81
+ query,
82
+ refreshKey
83
+ );
84
+ const { createErrorNotice, createSuccessNotice, createWarningNotice } =
85
+ useDispatch( noticesStore );
86
+ // Dim (rather than blank) the populated grid while a refetch is in flight,
87
+ // but only once it has run long enough to be worth signalling — quick
88
+ // attach/detach refetches resolve before this and show nothing.
89
+ const showRefreshing = useDelayedLoading( isLoading );
90
+
91
+ // Invalidate the cached results and force `useMediaResults` to refetch so
92
+ // the grid reflects images that were just attached or detached.
93
+ const refresh = useCallback( () => {
94
+ category.invalidate?.( query );
95
+ setRefreshKey( ( key ) => key + 1 );
96
+ }, [ category, query ] );
97
+
98
+ const handleAttach = useCallback(
99
+ async ( selectedMedia ) => {
100
+ try {
101
+ const attachedCount = await category.attach( selectedMedia );
102
+
103
+ if ( ! attachedCount ) {
104
+ // This source only attaches images (the picker's "Upload
105
+ // files" tab otherwise accepts any file type), so a selection
106
+ // with no images attaches nothing.
107
+ createWarningNotice( __( 'No images were attached.' ), {
108
+ type: 'snackbar',
109
+ id: 'inserter-notice',
110
+ } );
111
+ return;
112
+ }
113
+
114
+ refresh();
115
+ createSuccessNotice(
116
+ category.postTypeLabel
117
+ ? sprintf(
118
+ /* translators: %1$d: Number of images attached. %2$s: Name of the post type e.g: "Page". */
119
+ _n(
120
+ '%1$d image attached to %2$s.',
121
+ '%1$d images attached to %2$s.',
122
+ attachedCount
123
+ ),
124
+ attachedCount,
125
+ category.postTypeLabel
126
+ )
127
+ : sprintf(
128
+ /* translators: %d: Number of images attached to the post. */
129
+ _n(
130
+ '%d image attached to post.',
131
+ '%d images attached to post.',
132
+ attachedCount
133
+ ),
134
+ attachedCount
135
+ ),
136
+ { type: 'snackbar', id: 'inserter-notice' }
137
+ );
138
+ } catch {
139
+ createErrorNotice( __( 'Could not attach images.' ), {
140
+ type: 'snackbar',
141
+ id: 'inserter-notice',
142
+ } );
143
+ }
144
+ },
145
+ [
146
+ category,
147
+ refresh,
148
+ createErrorNotice,
149
+ createSuccessNotice,
150
+ createWarningNotice,
151
+ ]
152
+ );
153
+
154
+ const handleDetach = useCallback(
155
+ async ( media ) => {
156
+ try {
157
+ await category.detach( media );
158
+ refresh();
159
+ createSuccessNotice(
160
+ category.postTypeLabel
161
+ ? sprintf(
162
+ /* translators: %s: Name of the post type e.g: "Page". */
163
+ __( 'Image detached from %s.' ),
164
+ category.postTypeLabel
165
+ )
166
+ : __( 'Image detached from post.' ),
167
+ { type: 'snackbar', id: 'inserter-notice' }
168
+ );
169
+ } catch {
170
+ createErrorNotice( __( 'Could not detach image.' ), {
171
+ type: 'snackbar',
172
+ id: 'inserter-notice',
173
+ } );
174
+ }
175
+ },
176
+ [ category, refresh, createErrorNotice, createSuccessNotice ]
177
+ );
178
+
179
+ // Detaching is confirmed first: the dropdown sets the pending item, which
180
+ // opens a modal, and only `confirmDetach` performs the detach.
181
+ const [ mediaPendingDetach, setMediaPendingDetach ] = useState();
182
+ const confirmDetach = useCallback( () => {
183
+ const media = mediaPendingDetach;
184
+ setMediaPendingDetach( undefined );
185
+ handleDetach( media );
186
+ }, [ handleDetach, mediaPendingDetach ] );
187
+
23
188
  const baseCssClass = 'block-editor-inserter__media-panel';
24
189
  const searchLabel = category.labels.search_items || __( 'Search' );
25
190
  return (
26
- <div className={ baseCssClass }>
191
+ <div
192
+ className={ clsx( baseCssClass, {
193
+ // The attach footer supplies the breathing room beneath the
194
+ // grid, so the list drops its own bottom padding (see styles).
195
+ 'has-attach-footer': !! category.attach,
196
+ } ) }
197
+ >
27
198
  <SearchControl
28
199
  className={ `${ baseCssClass }-search` }
29
200
  onChange={ setSearch }
@@ -31,19 +202,87 @@ export function MediaCategoryPanel( { rootClientId, onInsert, category } ) {
31
202
  label={ searchLabel }
32
203
  placeholder={ searchLabel }
33
204
  />
34
- { isLoading && (
205
+ { isLoading && ! mediaList?.length && (
35
206
  <div className={ `${ baseCssClass }-spinner` }>
36
207
  <Spinner />
37
208
  </div>
38
209
  ) }
39
- { ! isLoading && ! mediaList?.length && <InserterNoResults /> }
40
- { ! isLoading && !! mediaList?.length && (
41
- <MediaList
42
- rootClientId={ rootClientId }
43
- onClick={ onInsert }
44
- mediaList={ mediaList }
45
- category={ category }
46
- />
210
+ { ! isLoading && ! mediaList?.length && (
211
+ <InserterNoResults>
212
+ { category.emptyMessage && ! debouncedSearch
213
+ ? // For a source with a custom empty message (e.g.
214
+ // Attachments) and no active search, an empty result
215
+ // means nothing is attached yet — clearer than the
216
+ // generic "no results found".
217
+ category.emptyMessage
218
+ : __( 'No results found.' ) }
219
+ </InserterNoResults>
220
+ ) }
221
+ { !! mediaList?.length && (
222
+ // Keep the existing items visible while a refetch is in flight,
223
+ // dimming (and gently pulsing) them rather than clearing the grid,
224
+ // so it doesn't flicker or pop.
225
+ <div
226
+ className={ clsx( `${ baseCssClass }-results`, {
227
+ 'is-loading': showRefreshing,
228
+ } ) }
229
+ aria-busy={ showRefreshing }
230
+ >
231
+ <MediaList
232
+ rootClientId={ rootClientId }
233
+ onClick={ onInsert }
234
+ onDetach={
235
+ category.detach ? setMediaPendingDetach : undefined
236
+ }
237
+ mediaList={ mediaList }
238
+ category={ category }
239
+ />
240
+ </div>
241
+ ) }
242
+ { category.attach && (
243
+ // Pinned to the bottom of the panel as a fixed footer so it lines
244
+ // up with the "Open Media Library" button in the adjacent column.
245
+ <AttachImagesButton onSelect={ handleAttach } />
246
+ ) }
247
+ { mediaPendingDetach && (
248
+ // A plain `Modal` (not `ConfirmDialog`) so we can pass
249
+ // `overlayClassName` and stack it above the options dropdown that
250
+ // opened it (see the z-index entry in `_z-index.scss`).
251
+ <Modal
252
+ title={ __( 'Detach image' ) }
253
+ onRequestClose={ () => setMediaPendingDetach( undefined ) }
254
+ overlayClassName={ `${ baseCssClass }-detach-modal` }
255
+ >
256
+ <p>
257
+ { category.postTypeLabel
258
+ ? sprintf(
259
+ /* translators: %s: Name of the post type e.g: "Page". */
260
+ __(
261
+ 'Detach this image from the current %s? The image will remain in the Media Library.'
262
+ ),
263
+ category.postTypeLabel
264
+ )
265
+ : __(
266
+ 'Detach this image from the current post? The image will remain in the Media Library.'
267
+ ) }
268
+ </p>
269
+ <div className={ `${ baseCssClass }-detach-actions` }>
270
+ <Button
271
+ __next40pxDefaultSize
272
+ variant="tertiary"
273
+ onClick={ () => setMediaPendingDetach( undefined ) }
274
+ >
275
+ { __( 'Cancel' ) }
276
+ </Button>
277
+ <Button
278
+ __next40pxDefaultSize
279
+ variant="primary"
280
+ onClick={ confirmDetach }
281
+ >
282
+ { __( 'Detach' ) }
283
+ </Button>
284
+ </div>
285
+ </Modal>
47
286
  ) }
48
287
  </div>
49
288
  );
@@ -21,7 +21,7 @@ import {
21
21
  import { __, sprintf } from '@wordpress/i18n';
22
22
  import { useMemo, useCallback, useState } from '@wordpress/element';
23
23
  import { cloneBlock } from '@wordpress/blocks';
24
- import { moreVertical, external } from '@wordpress/icons';
24
+ import { moreVertical, external, linkOff } from '@wordpress/icons';
25
25
  import { useSelect, useDispatch } from '@wordpress/data';
26
26
  import { store as noticesStore } from '@wordpress/notices';
27
27
  import { isBlobURL } from '@wordpress/blob';
@@ -43,11 +43,11 @@ const MEDIA_OPTIONS_POPOVER_PROPS = {
43
43
  'block-editor-inserter__media-list__item-preview-options__popover',
44
44
  };
45
45
 
46
- function MediaPreviewOptions( { category, media } ) {
47
- if ( ! category.getReportUrl ) {
46
+ function MediaPreviewOptions( { category, media, onDetach } ) {
47
+ if ( ! category.getReportUrl && ! onDetach ) {
48
48
  return null;
49
49
  }
50
- const reportUrl = category.getReportUrl( media );
50
+ const reportUrl = category.getReportUrl?.( media );
51
51
  return (
52
52
  <DropdownMenu
53
53
  className="block-editor-inserter__media-list__item-preview-options"
@@ -57,18 +57,34 @@ function MediaPreviewOptions( { category, media } ) {
57
57
  >
58
58
  { () => (
59
59
  <MenuGroup>
60
- <MenuItem
61
- onClick={ () =>
62
- window.open( reportUrl, '_blank' ).focus()
63
- }
64
- icon={ external }
65
- >
66
- { sprintf(
67
- /* translators: %s: The media type to report e.g: "image", "video", "audio" */
68
- __( 'Report %s' ),
69
- category.mediaType
70
- ) }
71
- </MenuItem>
60
+ { reportUrl && (
61
+ <MenuItem
62
+ onClick={ () =>
63
+ window.open( reportUrl, '_blank' ).focus()
64
+ }
65
+ icon={ external }
66
+ >
67
+ { sprintf(
68
+ /* translators: %s: The media type to report e.g: "image", "video", "audio" */
69
+ __( 'Report %s' ),
70
+ category.mediaType
71
+ ) }
72
+ </MenuItem>
73
+ ) }
74
+ { onDetach && (
75
+ <MenuItem
76
+ onClick={ () => onDetach( media ) }
77
+ icon={ linkOff }
78
+ >
79
+ { category.postTypeLabel
80
+ ? sprintf(
81
+ /* translators: %s: Name of the post type e.g: "Page". */
82
+ __( 'Detach from %s' ),
83
+ category.postTypeLabel
84
+ )
85
+ : __( 'Detach from post' ) }
86
+ </MenuItem>
87
+ ) }
72
88
  </MenuGroup>
73
89
  ) }
74
90
  </DropdownMenu>
@@ -122,7 +138,7 @@ function InsertExternalImageModal( { onClose, onSubmit } ) {
122
138
  );
123
139
  }
124
140
 
125
- export function MediaPreview( { media, onClick, category } ) {
141
+ export function MediaPreview( { media, onClick, onDetach, category } ) {
126
142
  const [ showExternalUploadModal, setShowExternalUploadModal ] =
127
143
  useState( false );
128
144
  const [ isHovered, setIsHovered ] = useState( false );
@@ -294,6 +310,7 @@ export function MediaPreview( { media, onClick, category } ) {
294
310
  <MediaPreviewOptions
295
311
  category={ category }
296
312
  media={ media }
313
+ onDetach={ onDetach }
297
314
  />
298
315
  ) }
299
316
  </div>
@@ -4,7 +4,7 @@
4
4
  import { __ } from '@wordpress/i18n';
5
5
  import { useViewportMatch } from '@wordpress/compose';
6
6
  import { Button } from '@wordpress/components';
7
- import { useCallback, useMemo } from '@wordpress/element';
7
+ import { useCallback, useEffect, useMemo } from '@wordpress/element';
8
8
 
9
9
  /**
10
10
  * Internal dependencies
@@ -54,6 +54,21 @@ function MediaTab( {
54
54
  } ) ),
55
55
  [ mediaCategories ]
56
56
  );
57
+ useEffect( () => {
58
+ if ( ! selectedCategory ) {
59
+ return;
60
+ }
61
+
62
+ const latestCategory = categories.find(
63
+ ( category ) => category.name === selectedCategory.name
64
+ );
65
+
66
+ if ( latestCategory && latestCategory !== selectedCategory ) {
67
+ onSelectCategory( latestCategory );
68
+ } else if ( ! latestCategory ) {
69
+ onSelectCategory( null );
70
+ }
71
+ }, [ categories, onSelectCategory, selectedCategory ] );
57
72
 
58
73
  if ( ! categories.length ) {
59
74
  return <InserterNoResults />;
@@ -100,7 +115,10 @@ function MediaTab( {
100
115
  </div>
101
116
  ) }
102
117
  { isMobile && (
103
- <MobileTabNavigation categories={ categories }>
118
+ <MobileTabNavigation
119
+ categories={ categories }
120
+ screenClassName="block-editor-inserter__media-mobile-screen"
121
+ >
104
122
  { ( category ) => (
105
123
  <MediaCategoryPanel
106
124
  onInsert={ onInsert }
@@ -0,0 +1,204 @@
1
+ /**
2
+ * External dependencies
3
+ */
4
+ import { renderHook, act, waitFor } from '@testing-library/react';
5
+
6
+ /**
7
+ * Internal dependencies
8
+ */
9
+ import { useDelayedLoading, useMediaResults } from '../hooks';
10
+
11
+ describe( 'useDelayedLoading', () => {
12
+ beforeEach( () => {
13
+ jest.useFakeTimers();
14
+ } );
15
+ afterEach( () => {
16
+ jest.useRealTimers();
17
+ } );
18
+
19
+ it( 'does not surface loading before the delay elapses', () => {
20
+ const { result } = renderHook( () => useDelayedLoading( true, 400 ) );
21
+ expect( result.current ).toBe( false );
22
+ act( () => {
23
+ jest.advanceTimersByTime( 399 );
24
+ } );
25
+ expect( result.current ).toBe( false );
26
+ } );
27
+
28
+ it( 'surfaces loading once the delay elapses', () => {
29
+ const { result } = renderHook( () => useDelayedLoading( true, 400 ) );
30
+ act( () => {
31
+ jest.advanceTimersByTime( 400 );
32
+ } );
33
+ expect( result.current ).toBe( true );
34
+ } );
35
+
36
+ it( 'never surfaces loading for an operation that ends before the delay', () => {
37
+ const { result, rerender } = renderHook(
38
+ ( { isLoading } ) => useDelayedLoading( isLoading, 400 ),
39
+ { initialProps: { isLoading: true } }
40
+ );
41
+ act( () => {
42
+ jest.advanceTimersByTime( 200 );
43
+ } );
44
+ rerender( { isLoading: false } );
45
+ act( () => {
46
+ jest.advanceTimersByTime( 400 );
47
+ } );
48
+ expect( result.current ).toBe( false );
49
+ } );
50
+
51
+ it( 'resets once loading finishes', () => {
52
+ const { result, rerender } = renderHook(
53
+ ( { isLoading } ) => useDelayedLoading( isLoading, 400 ),
54
+ { initialProps: { isLoading: true } }
55
+ );
56
+ act( () => {
57
+ jest.advanceTimersByTime( 400 );
58
+ } );
59
+ expect( result.current ).toBe( true );
60
+ rerender( { isLoading: false } );
61
+ expect( result.current ).toBe( false );
62
+ } );
63
+ } );
64
+
65
+ describe( 'useMediaResults', () => {
66
+ const createCategory = ( name, items ) => ( {
67
+ name,
68
+ fetch: jest.fn( async () => items ),
69
+ } );
70
+
71
+ it( 'fetches and returns media for the query', async () => {
72
+ const category = createCategory( 'images', [ { id: 1 } ] );
73
+ const { result } = renderHook( () =>
74
+ useMediaResults( category, { search: '' }, 0 )
75
+ );
76
+ await waitFor( () => expect( result.current.isLoading ).toBe( false ) );
77
+ expect( category.fetch ).toHaveBeenCalledWith( { search: '' } );
78
+ expect( result.current.mediaList ).toEqual( [ { id: 1 } ] );
79
+ } );
80
+
81
+ it( 'clears the previous results when the query changes', async () => {
82
+ const category = createCategory( 'images', [ { id: 1 } ] );
83
+ const { result, rerender } = renderHook(
84
+ ( { query } ) => useMediaResults( category, query, 0 ),
85
+ { initialProps: { query: { search: 'a' } } }
86
+ );
87
+ await waitFor( () =>
88
+ expect( result.current.mediaList ).toEqual( [ { id: 1 } ] )
89
+ );
90
+
91
+ // Hold the next request open so the intermediate (cleared) state is observable.
92
+ let resolveFetch;
93
+ category.fetch.mockImplementationOnce(
94
+ () =>
95
+ new Promise( ( resolve ) => {
96
+ resolveFetch = resolve;
97
+ } )
98
+ );
99
+ rerender( { query: { search: 'b' } } );
100
+
101
+ // A query change blanks the grid while the new request is in flight.
102
+ await waitFor( () => expect( result.current.mediaList ).toEqual( [] ) );
103
+ await act( async () => {
104
+ resolveFetch( [ { id: 2 } ] );
105
+ } );
106
+ expect( result.current.mediaList ).toEqual( [ { id: 2 } ] );
107
+ } );
108
+
109
+ it( 'keeps the existing results while a refresh (refreshKey bump) refetches', async () => {
110
+ const category = createCategory( 'attached-images', [ { id: 1 } ] );
111
+ const { result, rerender } = renderHook(
112
+ ( { refreshKey } ) =>
113
+ useMediaResults( category, { search: '' }, refreshKey ),
114
+ { initialProps: { refreshKey: 0 } }
115
+ );
116
+ await waitFor( () =>
117
+ expect( result.current.mediaList ).toEqual( [ { id: 1 } ] )
118
+ );
119
+
120
+ // Hold the refetch open so we can assert the grid is not blanked.
121
+ let resolveFetch;
122
+ category.fetch.mockImplementationOnce(
123
+ () =>
124
+ new Promise( ( resolve ) => {
125
+ resolveFetch = resolve;
126
+ } )
127
+ );
128
+ rerender( { refreshKey: 1 } );
129
+
130
+ // Same query, only `refreshKey` changed: existing items stay put.
131
+ await waitFor( () => expect( result.current.isLoading ).toBe( true ) );
132
+ expect( result.current.mediaList ).toEqual( [ { id: 1 } ] );
133
+ await act( async () => {
134
+ resolveFetch( [ { id: 2 } ] );
135
+ } );
136
+ expect( result.current.mediaList ).toEqual( [ { id: 2 } ] );
137
+ } );
138
+
139
+ it( 'clears and refetches when the category source changes with the same name and query', async () => {
140
+ const firstCategory = createCategory( 'attached-images', [
141
+ { id: 1 },
142
+ ] );
143
+ const { result, rerender } = renderHook(
144
+ ( { category } ) => useMediaResults( category, { search: '' }, 0 ),
145
+ { initialProps: { category: firstCategory } }
146
+ );
147
+ await waitFor( () =>
148
+ expect( result.current.mediaList ).toEqual( [ { id: 1 } ] )
149
+ );
150
+
151
+ let resolveFetch;
152
+ const secondCategory = {
153
+ name: 'attached-images',
154
+ fetch: jest.fn(
155
+ () =>
156
+ new Promise( ( resolve ) => {
157
+ resolveFetch = resolve;
158
+ } )
159
+ ),
160
+ };
161
+ rerender( { category: secondCategory } );
162
+
163
+ await waitFor( () =>
164
+ expect( secondCategory.fetch ).toHaveBeenCalledWith( {
165
+ search: '',
166
+ } )
167
+ );
168
+ expect( result.current.mediaList ).toEqual( [] );
169
+ expect( result.current.isLoading ).toBe( true );
170
+
171
+ await act( async () => {
172
+ resolveFetch( [ { id: 2 } ] );
173
+ } );
174
+ expect( result.current.mediaList ).toEqual( [ { id: 2 } ] );
175
+ } );
176
+
177
+ it( 'does not refetch when only the category wrapper changes', async () => {
178
+ const fetch = jest.fn( async () => [ { id: 1 } ] );
179
+ const { result, rerender } = renderHook(
180
+ ( { category } ) => useMediaResults( category, { search: '' }, 0 ),
181
+ {
182
+ initialProps: {
183
+ category: {
184
+ name: 'images',
185
+ fetch,
186
+ },
187
+ },
188
+ }
189
+ );
190
+ await waitFor( () =>
191
+ expect( result.current.mediaList ).toEqual( [ { id: 1 } ] )
192
+ );
193
+
194
+ rerender( {
195
+ category: {
196
+ name: 'images',
197
+ fetch,
198
+ },
199
+ } );
200
+
201
+ expect( fetch ).toHaveBeenCalledTimes( 1 );
202
+ expect( result.current.mediaList ).toEqual( [ { id: 1 } ] );
203
+ } );
204
+ } );
@@ -41,7 +41,11 @@ function ScreenHeader( { title } ) {
41
41
  );
42
42
  }
43
43
 
44
- export default function MobileTabNavigation( { categories, children } ) {
44
+ export default function MobileTabNavigation( {
45
+ categories,
46
+ children,
47
+ screenClassName,
48
+ } ) {
45
49
  return (
46
50
  <Navigator
47
51
  initialPath="/"
@@ -71,6 +75,7 @@ export default function MobileTabNavigation( { categories, children } ) {
71
75
  { categories.map( ( category ) => (
72
76
  <Navigator.Screen
73
77
  key={ category.name }
78
+ className={ screenClassName }
74
79
  path={ `/category/${ category.name }` }
75
80
  >
76
81
  <ScreenHeader title={ __( 'Back' ) } />
@@ -3,10 +3,10 @@
3
3
  */
4
4
  import { __ } from '@wordpress/i18n';
5
5
 
6
- function InserterNoResults() {
6
+ function InserterNoResults( { children = __( 'No results found.' ) } ) {
7
7
  return (
8
8
  <div className="block-editor-inserter__no-results">
9
- <p>{ __( 'No results found.' ) }</p>
9
+ <p>{ children }</p>
10
10
  </div>
11
11
  );
12
12
  }
@@ -28,6 +28,7 @@ function InserterPreviewPanel( { item } ) {
28
28
  ...initialAttributes,
29
29
  },
30
30
  innerBlocks: example.innerBlocks,
31
+ innerContent: example.innerContent,
31
32
  } );
32
33
  }, [ name, example, initialAttributes ] );
33
34
  // Same as height of BlockPreviewPanel.