@wordpress/editor 14.48.1 → 14.48.2-next.v.202606191442.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 (401) hide show
  1. package/build/bindings/pattern-overrides.cjs +1 -1
  2. package/build/bindings/pattern-overrides.cjs.map +2 -2
  3. package/build/components/collab-sidebar/note-byline.cjs +1 -1
  4. package/build/components/collab-sidebar/note-byline.cjs.map +2 -2
  5. package/build/components/collab-sidebar/note.cjs +49 -17
  6. package/build/components/collab-sidebar/note.cjs.map +3 -3
  7. package/build/components/collab-sidebar/notes.cjs.map +1 -1
  8. package/build/components/collab-sidebar/utils.cjs +1 -1
  9. package/build/components/collab-sidebar/utils.cjs.map +2 -2
  10. package/build/components/collaborators-overlay/avatar-iframe-styles.cjs.map +1 -1
  11. package/build/components/collaborators-overlay/collaborator-styles.cjs.map +1 -1
  12. package/build/components/collaborators-overlay/compute-selection.cjs.map +1 -1
  13. package/build/components/collaborators-overlay/overlay-iframe-styles.cjs +1 -1
  14. package/build/components/collaborators-overlay/overlay-iframe-styles.cjs.map +1 -1
  15. package/build/components/collaborators-overlay/use-block-highlighting.cjs.map +1 -1
  16. package/build/components/collaborators-presence/avatar/component.cjs.map +2 -2
  17. package/build/components/collaborators-presence/avatar/use-image-loading-status.cjs.map +1 -1
  18. package/build/components/document-bar/index.cjs +7 -5
  19. package/build/components/document-bar/index.cjs.map +2 -2
  20. package/build/components/global-keyboard-shortcuts/index.cjs +3 -2
  21. package/build/components/global-keyboard-shortcuts/index.cjs.map +2 -2
  22. package/build/components/global-styles-sidebar/welcome-guide.cjs +3 -3
  23. package/build/components/global-styles-sidebar/welcome-guide.cjs.map +1 -1
  24. package/build/components/local-autosave-monitor/index.cjs +14 -15
  25. package/build/components/local-autosave-monitor/index.cjs.map +2 -2
  26. package/build/components/page-attributes/parent.cjs +1 -1
  27. package/build/components/page-attributes/parent.cjs.map +2 -2
  28. package/build/components/post-card-panel/index.cjs +1 -1
  29. package/build/components/post-card-panel/index.cjs.map +2 -2
  30. package/build/components/post-excerpt/panel.cjs +1 -1
  31. package/build/components/post-excerpt/panel.cjs.map +2 -2
  32. package/build/components/post-locked-modal/index.cjs +3 -3
  33. package/build/components/post-locked-modal/index.cjs.map +1 -1
  34. package/build/components/post-preview-button/index.cjs +2 -2
  35. package/build/components/post-preview-button/index.cjs.map +2 -2
  36. package/build/components/post-publish-button/index.cjs +4 -3
  37. package/build/components/post-publish-button/index.cjs.map +2 -2
  38. package/build/components/post-publish-button/label.cjs +2 -2
  39. package/build/components/post-publish-button/label.cjs.map +2 -2
  40. package/build/components/post-publish-panel/index.cjs.map +1 -1
  41. package/build/components/post-publish-panel/postpublish.cjs +1 -1
  42. package/build/components/post-publish-panel/postpublish.cjs.map +2 -2
  43. package/build/components/post-revisions-preview/block-diff.cjs.map +1 -1
  44. package/build/components/post-revisions-preview/diff-markers.cjs.map +2 -2
  45. package/build/components/post-revisions-preview/revisions-slider.cjs +1 -1
  46. package/build/components/post-revisions-preview/revisions-slider.cjs.map +2 -2
  47. package/build/components/post-revisions-timeline/index.cjs +173 -0
  48. package/build/components/post-revisions-timeline/index.cjs.map +7 -0
  49. package/build/components/post-saved-state/index.cjs +17 -26
  50. package/build/components/post-saved-state/index.cjs.map +2 -2
  51. package/build/components/post-schedule/label.cjs +5 -5
  52. package/build/components/post-schedule/label.cjs.map +1 -1
  53. package/build/components/post-taxonomies/flat-term-selector.cjs +2 -1
  54. package/build/components/post-taxonomies/flat-term-selector.cjs.map +3 -3
  55. package/build/components/post-taxonomies/hierarchical-term-selector.cjs +1 -1
  56. package/build/components/post-taxonomies/hierarchical-term-selector.cjs.map +2 -2
  57. package/build/components/post-text-editor/index.cjs +51 -0
  58. package/build/components/post-text-editor/index.cjs.map +2 -2
  59. package/build/components/post-text-editor/utils.cjs +150 -0
  60. package/build/components/post-text-editor/utils.cjs.map +7 -0
  61. package/build/components/post-url/index.cjs +1 -1
  62. package/build/components/post-url/index.cjs.map +2 -2
  63. package/build/components/post-view-link/index.cjs +1 -1
  64. package/build/components/post-view-link/index.cjs.map +2 -2
  65. package/build/components/provider/disable-non-page-content-blocks.cjs.map +1 -1
  66. package/build/components/provider/index.cjs +1 -1
  67. package/build/components/provider/index.cjs.map +2 -2
  68. package/build/components/resizable-editor/resize-handle.cjs.map +2 -2
  69. package/build/components/revision-diff-panel/index.cjs +7 -2
  70. package/build/components/revision-diff-panel/index.cjs.map +2 -2
  71. package/build/components/revision-fields-diff/index.cjs +6 -2
  72. package/build/components/revision-fields-diff/index.cjs.map +2 -2
  73. package/build/components/sidebar/dataform-post-summary.cjs +125 -20
  74. package/build/components/sidebar/dataform-post-summary.cjs.map +3 -3
  75. package/build/components/sidebar/index.cjs +1 -11
  76. package/build/components/sidebar/index.cjs.map +3 -3
  77. package/build/components/sidebar/post-revision-summary.cjs +11 -17
  78. package/build/components/sidebar/post-revision-summary.cjs.map +3 -3
  79. package/build/components/sidebar/post-summary.cjs +1 -1
  80. package/build/components/sidebar/post-summary.cjs.map +2 -2
  81. package/build/components/style-book/examples.cjs +1 -1
  82. package/build/components/style-book/examples.cjs.map +1 -1
  83. package/build/components/style-book/index.cjs +1 -1
  84. package/build/components/style-book/index.cjs.map +2 -2
  85. package/build/components/sync-connection-error-modal/index.cjs +3 -3
  86. package/build/components/sync-connection-error-modal/index.cjs.map +1 -1
  87. package/build/components/template-actions-panel/block-theme-content.cjs.map +2 -2
  88. package/build/components/template-actions-panel/index.cjs +0 -9
  89. package/build/components/template-actions-panel/index.cjs.map +3 -3
  90. package/build/components/template-validation-notice/index.cjs +1 -1
  91. package/build/components/template-validation-notice/index.cjs.map +1 -1
  92. package/build/components/upload-progress-snackbar/index.cjs +3 -3
  93. package/build/components/upload-progress-snackbar/index.cjs.map +2 -2
  94. package/build/components/upload-progress-snackbar/tracker.cjs.map +1 -1
  95. package/build/components/visual-editor/edit-template-blocks-notification.cjs +1 -1
  96. package/build/components/visual-editor/edit-template-blocks-notification.cjs.map +1 -1
  97. package/build/{components/revision-author-panel → dataviews/fields/revisions}/index.cjs +18 -26
  98. package/build/dataviews/fields/revisions/index.cjs.map +7 -0
  99. package/build/dataviews/fields/revisions/revisions-view.cjs +74 -0
  100. package/build/dataviews/fields/revisions/revisions-view.cjs.map +7 -0
  101. package/build/dataviews/store/private-actions.cjs +14 -4
  102. package/build/dataviews/store/private-actions.cjs.map +3 -3
  103. package/build/hooks/push-changes-to-global-styles/index.cjs +1 -1
  104. package/build/hooks/push-changes-to-global-styles/index.cjs.map +1 -1
  105. package/build/store/actions.cjs +1 -1
  106. package/build/store/actions.cjs.map +2 -2
  107. package/build/store/private-selectors.cjs +6 -1
  108. package/build/store/private-selectors.cjs.map +2 -2
  109. package/build/utils/media-upload/index.cjs.map +1 -1
  110. package/build/utils/set-nested-value.cjs.map +1 -1
  111. package/build-module/bindings/pattern-overrides.mjs +1 -1
  112. package/build-module/bindings/pattern-overrides.mjs.map +2 -2
  113. package/build-module/components/collab-sidebar/note-byline.mjs +1 -1
  114. package/build-module/components/collab-sidebar/note-byline.mjs.map +2 -2
  115. package/build-module/components/collab-sidebar/note.mjs +50 -18
  116. package/build-module/components/collab-sidebar/note.mjs.map +2 -2
  117. package/build-module/components/collab-sidebar/notes.mjs.map +1 -1
  118. package/build-module/components/collab-sidebar/utils.mjs +1 -1
  119. package/build-module/components/collab-sidebar/utils.mjs.map +2 -2
  120. package/build-module/components/collaborators-overlay/avatar-iframe-styles.mjs.map +1 -1
  121. package/build-module/components/collaborators-overlay/collaborator-styles.mjs.map +1 -1
  122. package/build-module/components/collaborators-overlay/compute-selection.mjs.map +1 -1
  123. package/build-module/components/collaborators-overlay/overlay-iframe-styles.mjs +1 -1
  124. package/build-module/components/collaborators-overlay/overlay-iframe-styles.mjs.map +1 -1
  125. package/build-module/components/collaborators-overlay/use-block-highlighting.mjs.map +1 -1
  126. package/build-module/components/collaborators-presence/avatar/component.mjs.map +2 -2
  127. package/build-module/components/collaborators-presence/avatar/use-image-loading-status.mjs.map +1 -1
  128. package/build-module/components/document-bar/index.mjs +7 -5
  129. package/build-module/components/document-bar/index.mjs.map +2 -2
  130. package/build-module/components/global-keyboard-shortcuts/index.mjs +3 -2
  131. package/build-module/components/global-keyboard-shortcuts/index.mjs.map +2 -2
  132. package/build-module/components/global-styles-sidebar/welcome-guide.mjs +3 -3
  133. package/build-module/components/global-styles-sidebar/welcome-guide.mjs.map +1 -1
  134. package/build-module/components/local-autosave-monitor/index.mjs +15 -16
  135. package/build-module/components/local-autosave-monitor/index.mjs.map +2 -2
  136. package/build-module/components/page-attributes/parent.mjs +1 -1
  137. package/build-module/components/page-attributes/parent.mjs.map +2 -2
  138. package/build-module/components/post-card-panel/index.mjs +1 -1
  139. package/build-module/components/post-card-panel/index.mjs.map +2 -2
  140. package/build-module/components/post-excerpt/panel.mjs +1 -1
  141. package/build-module/components/post-excerpt/panel.mjs.map +2 -2
  142. package/build-module/components/post-locked-modal/index.mjs +3 -3
  143. package/build-module/components/post-locked-modal/index.mjs.map +1 -1
  144. package/build-module/components/post-preview-button/index.mjs +2 -2
  145. package/build-module/components/post-preview-button/index.mjs.map +2 -2
  146. package/build-module/components/post-publish-button/index.mjs +4 -3
  147. package/build-module/components/post-publish-button/index.mjs.map +2 -2
  148. package/build-module/components/post-publish-button/label.mjs +2 -2
  149. package/build-module/components/post-publish-button/label.mjs.map +2 -2
  150. package/build-module/components/post-publish-panel/index.mjs.map +1 -1
  151. package/build-module/components/post-publish-panel/postpublish.mjs +1 -1
  152. package/build-module/components/post-publish-panel/postpublish.mjs.map +2 -2
  153. package/build-module/components/post-revisions-preview/block-diff.mjs.map +1 -1
  154. package/build-module/components/post-revisions-preview/diff-markers.mjs.map +2 -2
  155. package/build-module/components/post-revisions-preview/revisions-slider.mjs +1 -1
  156. package/build-module/components/post-revisions-preview/revisions-slider.mjs.map +2 -2
  157. package/build-module/components/post-revisions-timeline/index.mjs +152 -0
  158. package/build-module/components/post-revisions-timeline/index.mjs.map +7 -0
  159. package/build-module/components/post-saved-state/index.mjs +17 -26
  160. package/build-module/components/post-saved-state/index.mjs.map +2 -2
  161. package/build-module/components/post-schedule/label.mjs +5 -5
  162. package/build-module/components/post-schedule/label.mjs.map +1 -1
  163. package/build-module/components/post-taxonomies/flat-term-selector.mjs +3 -6
  164. package/build-module/components/post-taxonomies/flat-term-selector.mjs.map +2 -2
  165. package/build-module/components/post-taxonomies/hierarchical-term-selector.mjs +1 -1
  166. package/build-module/components/post-taxonomies/hierarchical-term-selector.mjs.map +2 -2
  167. package/build-module/components/post-text-editor/index.mjs +51 -0
  168. package/build-module/components/post-text-editor/index.mjs.map +2 -2
  169. package/build-module/components/post-text-editor/utils.mjs +123 -0
  170. package/build-module/components/post-text-editor/utils.mjs.map +7 -0
  171. package/build-module/components/post-url/index.mjs +1 -1
  172. package/build-module/components/post-url/index.mjs.map +2 -2
  173. package/build-module/components/post-view-link/index.mjs +1 -1
  174. package/build-module/components/post-view-link/index.mjs.map +2 -2
  175. package/build-module/components/provider/disable-non-page-content-blocks.mjs.map +1 -1
  176. package/build-module/components/provider/index.mjs +1 -1
  177. package/build-module/components/provider/index.mjs.map +2 -2
  178. package/build-module/components/resizable-editor/resize-handle.mjs.map +2 -2
  179. package/build-module/components/revision-diff-panel/index.mjs +7 -2
  180. package/build-module/components/revision-diff-panel/index.mjs.map +2 -2
  181. package/build-module/components/revision-fields-diff/index.mjs +6 -2
  182. package/build-module/components/revision-fields-diff/index.mjs.map +2 -2
  183. package/build-module/components/sidebar/dataform-post-summary.mjs +125 -20
  184. package/build-module/components/sidebar/dataform-post-summary.mjs.map +2 -2
  185. package/build-module/components/sidebar/index.mjs +1 -11
  186. package/build-module/components/sidebar/index.mjs.map +2 -2
  187. package/build-module/components/sidebar/post-revision-summary.mjs +11 -17
  188. package/build-module/components/sidebar/post-revision-summary.mjs.map +2 -2
  189. package/build-module/components/sidebar/post-summary.mjs +1 -1
  190. package/build-module/components/sidebar/post-summary.mjs.map +2 -2
  191. package/build-module/components/style-book/examples.mjs +1 -1
  192. package/build-module/components/style-book/examples.mjs.map +1 -1
  193. package/build-module/components/style-book/index.mjs +1 -1
  194. package/build-module/components/style-book/index.mjs.map +2 -2
  195. package/build-module/components/sync-connection-error-modal/index.mjs +3 -3
  196. package/build-module/components/sync-connection-error-modal/index.mjs.map +1 -1
  197. package/build-module/components/template-actions-panel/block-theme-content.mjs.map +2 -2
  198. package/build-module/components/template-actions-panel/index.mjs +0 -9
  199. package/build-module/components/template-actions-panel/index.mjs.map +2 -2
  200. package/build-module/components/template-validation-notice/index.mjs +1 -1
  201. package/build-module/components/template-validation-notice/index.mjs.map +1 -1
  202. package/build-module/components/upload-progress-snackbar/index.mjs +3 -3
  203. package/build-module/components/upload-progress-snackbar/index.mjs.map +2 -2
  204. package/build-module/components/upload-progress-snackbar/tracker.mjs.map +1 -1
  205. package/build-module/components/visual-editor/edit-template-blocks-notification.mjs +1 -1
  206. package/build-module/components/visual-editor/edit-template-blocks-notification.mjs.map +1 -1
  207. package/build-module/dataviews/fields/revisions/index.mjs +20 -0
  208. package/build-module/dataviews/fields/revisions/index.mjs.map +7 -0
  209. package/build-module/dataviews/fields/revisions/revisions-view.mjs +53 -0
  210. package/build-module/dataviews/fields/revisions/revisions-view.mjs.map +7 -0
  211. package/build-module/dataviews/store/private-actions.mjs +23 -7
  212. package/build-module/dataviews/store/private-actions.mjs.map +2 -2
  213. package/build-module/hooks/push-changes-to-global-styles/index.mjs +1 -1
  214. package/build-module/hooks/push-changes-to-global-styles/index.mjs.map +1 -1
  215. package/build-module/store/actions.mjs +1 -1
  216. package/build-module/store/actions.mjs.map +2 -2
  217. package/build-module/store/private-selectors.mjs +7 -1
  218. package/build-module/store/private-selectors.mjs.map +2 -2
  219. package/build-module/utils/media-upload/index.mjs.map +1 -1
  220. package/build-module/utils/set-nested-value.mjs.map +1 -1
  221. package/build-style/style-rtl.css +270 -206
  222. package/build-style/style.css +270 -206
  223. package/build-types/components/collab-sidebar/note-byline.d.ts +0 -3
  224. package/build-types/components/collab-sidebar/note-byline.d.ts.map +1 -1
  225. package/build-types/components/collab-sidebar/note.d.ts.map +1 -1
  226. package/build-types/components/collaborators-presence/avatar/component.d.ts.map +1 -1
  227. package/build-types/components/document-bar/index.d.ts +2 -2
  228. package/build-types/components/document-bar/index.d.ts.map +1 -1
  229. package/build-types/components/global-keyboard-shortcuts/index.d.ts.map +1 -1
  230. package/build-types/components/local-autosave-monitor/index.d.ts.map +1 -1
  231. package/build-types/components/post-publish-button/index.d.ts.map +1 -1
  232. package/build-types/components/post-revisions-preview/diff-markers.d.ts.map +1 -1
  233. package/build-types/components/post-revisions-timeline/index.d.ts +2 -0
  234. package/build-types/components/post-revisions-timeline/index.d.ts.map +1 -0
  235. package/build-types/components/post-saved-state/index.d.ts.map +1 -1
  236. package/build-types/components/post-taxonomies/flat-term-selector.d.ts.map +1 -1
  237. package/build-types/components/post-text-editor/index.d.ts +1 -1
  238. package/build-types/components/post-text-editor/index.d.ts.map +1 -1
  239. package/build-types/components/provider/index.d.ts.map +1 -1
  240. package/build-types/components/resizable-editor/resize-handle.d.ts.map +1 -1
  241. package/build-types/components/revision-diff-panel/index.d.ts +3 -1
  242. package/build-types/components/revision-diff-panel/index.d.ts.map +1 -1
  243. package/build-types/components/revision-fields-diff/index.d.ts.map +1 -1
  244. package/build-types/components/sidebar/dataform-post-summary.d.ts.map +1 -1
  245. package/build-types/components/sidebar/index.d.ts.map +1 -1
  246. package/build-types/components/sidebar/post-revision-summary.d.ts.map +1 -1
  247. package/build-types/components/template-actions-panel/block-theme-content.d.ts.map +1 -1
  248. package/build-types/components/template-actions-panel/index.d.ts.map +1 -1
  249. package/build-types/dataviews/fields/revisions/index.d.ts +8 -0
  250. package/build-types/dataviews/fields/revisions/index.d.ts.map +1 -0
  251. package/build-types/dataviews/fields/revisions/revisions-view.d.ts +2 -0
  252. package/build-types/dataviews/fields/revisions/revisions-view.d.ts.map +1 -0
  253. package/build-types/dataviews/store/private-actions.d.ts.map +1 -1
  254. package/build-types/store/private-selectors.d.ts +1 -1
  255. package/build-types/store/private-selectors.d.ts.map +1 -1
  256. package/build-types/store/selectors.d.ts +1 -1
  257. package/build-types/store/selectors.d.ts.map +1 -1
  258. package/package.json +53 -47
  259. package/src/bindings/pattern-overrides.js +1 -1
  260. package/src/bindings/test/pattern-overrides.js +65 -0
  261. package/src/components/collab-sidebar/note-byline.js +0 -1
  262. package/src/components/collab-sidebar/note.js +64 -29
  263. package/src/components/collab-sidebar/style.scss +20 -0
  264. package/src/components/collaborators-presence/avatar/component.tsx +0 -1
  265. package/src/components/collaborators-presence/avatar/test/index.tsx +0 -1
  266. package/src/components/document-bar/index.js +8 -3
  267. package/src/components/document-bar/style.scss +4 -2
  268. package/src/components/global-keyboard-shortcuts/index.js +2 -1
  269. package/src/components/local-autosave-monitor/index.js +23 -21
  270. package/src/components/post-card-panel/index.js +1 -1
  271. package/src/components/post-publish-button/index.js +6 -3
  272. package/src/components/post-publish-button/test/index.js +13 -0
  273. package/src/components/post-revisions-preview/diff-markers.js +0 -1
  274. package/src/components/post-revisions-timeline/index.js +186 -0
  275. package/src/components/post-revisions-timeline/style.scss +43 -0
  276. package/src/components/post-saved-state/index.js +23 -26
  277. package/src/components/post-saved-state/test/index.js +18 -0
  278. package/src/components/post-taxonomies/flat-term-selector.js +4 -7
  279. package/src/components/post-text-editor/index.js +65 -0
  280. package/src/components/post-text-editor/test/utils.js +210 -0
  281. package/src/components/post-text-editor/utils.js +204 -0
  282. package/src/components/post-type-support-check/test/index.js +11 -0
  283. package/src/components/post-url/index.js +1 -1
  284. package/src/components/post-view-link/index.js +1 -1
  285. package/src/components/post-view-link/test/index.js +71 -0
  286. package/src/components/provider/index.js +2 -1
  287. package/src/components/resizable-editor/resize-handle.js +0 -1
  288. package/src/components/revision-diff-panel/index.js +8 -2
  289. package/src/components/revision-fields-diff/index.js +12 -1
  290. package/src/components/sidebar/dataform-post-summary.js +196 -25
  291. package/src/components/sidebar/index.js +2 -12
  292. package/src/components/sidebar/post-revision-summary.js +8 -15
  293. package/src/components/sidebar/post-summary.js +1 -1
  294. package/src/components/style-book/index.js +1 -1
  295. package/src/components/template-actions-panel/block-theme-content.js +0 -1
  296. package/src/components/template-actions-panel/index.js +0 -15
  297. package/src/dataviews/fields/revisions/index.tsx +28 -0
  298. package/src/dataviews/fields/revisions/revisions-view.tsx +59 -0
  299. package/src/dataviews/store/private-actions.ts +27 -6
  300. package/src/store/private-selectors.js +11 -1
  301. package/src/store/test/private-selectors.js +69 -0
  302. package/src/style.scss +1 -1
  303. package/build/components/post-revisions-panel/index.cjs +0 -173
  304. package/build/components/post-revisions-panel/index.cjs.map +0 -7
  305. package/build/components/revision-author-panel/index.cjs.map +0 -7
  306. package/build/components/revision-created-panel/index.cjs +0 -47
  307. package/build/components/revision-created-panel/index.cjs.map +0 -7
  308. package/build-module/components/post-revisions-panel/index.mjs +0 -148
  309. package/build-module/components/post-revisions-panel/index.mjs.map +0 -7
  310. package/build-module/components/revision-author-panel/index.mjs +0 -28
  311. package/build-module/components/revision-author-panel/index.mjs.map +0 -7
  312. package/build-module/components/revision-created-panel/index.mjs +0 -26
  313. package/build-module/components/revision-created-panel/index.mjs.map +0 -7
  314. package/build-types/components/collab-sidebar/add-comment.d.ts +0 -6
  315. package/build-types/components/collab-sidebar/add-comment.d.ts.map +0 -1
  316. package/build-types/components/collab-sidebar/comment-author-info.d.ts +0 -8
  317. package/build-types/components/collab-sidebar/comment-author-info.d.ts.map +0 -1
  318. package/build-types/components/collab-sidebar/comment-form.d.ts +0 -9
  319. package/build-types/components/collab-sidebar/comment-form.d.ts.map +0 -1
  320. package/build-types/components/collab-sidebar/comment-indicator-toolbar.d.ts +0 -6
  321. package/build-types/components/collab-sidebar/comment-indicator-toolbar.d.ts.map +0 -1
  322. package/build-types/components/collab-sidebar/comment-menu-item.d.ts +0 -6
  323. package/build-types/components/collab-sidebar/comment-menu-item.d.ts.map +0 -1
  324. package/build-types/components/collab-sidebar/comments.d.ts +0 -10
  325. package/build-types/components/collab-sidebar/comments.d.ts.map +0 -1
  326. package/build-types/components/global-styles-provider/index.d.ts +0 -16
  327. package/build-types/components/global-styles-provider/index.d.ts.map +0 -1
  328. package/build-types/components/media/index.d.ts +0 -3
  329. package/build-types/components/media/index.d.ts.map +0 -1
  330. package/build-types/components/media/metadata-panel.d.ts +0 -12
  331. package/build-types/components/media/metadata-panel.d.ts.map +0 -1
  332. package/build-types/components/media/preview.d.ts +0 -9
  333. package/build-types/components/media/preview.d.ts.map +0 -1
  334. package/build-types/components/post-revisions-panel/index.d.ts +0 -2
  335. package/build-types/components/post-revisions-panel/index.d.ts.map +0 -1
  336. package/build-types/components/revision-author-panel/index.d.ts +0 -2
  337. package/build-types/components/revision-author-panel/index.d.ts.map +0 -1
  338. package/build-types/components/revision-created-panel/index.d.ts +0 -2
  339. package/build-types/components/revision-created-panel/index.d.ts.map +0 -1
  340. package/src/components/editor-help/images/add-dark.png +0 -0
  341. package/src/components/editor-help/images/add-dark@2x.png +0 -0
  342. package/src/components/editor-help/images/add-dark@3x.png +0 -0
  343. package/src/components/editor-help/images/add-light.png +0 -0
  344. package/src/components/editor-help/images/add-light@2x.png +0 -0
  345. package/src/components/editor-help/images/add-light@3x.png +0 -0
  346. package/src/components/editor-help/images/block-layout-collage.png +0 -0
  347. package/src/components/editor-help/images/block-layout-collage@2x.png +0 -0
  348. package/src/components/editor-help/images/block-layout-collage@3x.png +0 -0
  349. package/src/components/editor-help/images/build-layouts-dark.png +0 -0
  350. package/src/components/editor-help/images/build-layouts-dark@2x.png +0 -0
  351. package/src/components/editor-help/images/build-layouts-dark@3x.png +0 -0
  352. package/src/components/editor-help/images/build-layouts-light.png +0 -0
  353. package/src/components/editor-help/images/build-layouts-light@2x.png +0 -0
  354. package/src/components/editor-help/images/build-layouts-light@3x.png +0 -0
  355. package/src/components/editor-help/images/drag-and-drop-dark.png +0 -0
  356. package/src/components/editor-help/images/drag-and-drop-dark@2x.png +0 -0
  357. package/src/components/editor-help/images/drag-and-drop-dark@3x.png +0 -0
  358. package/src/components/editor-help/images/drag-and-drop-light.png +0 -0
  359. package/src/components/editor-help/images/drag-and-drop-light@2x.png +0 -0
  360. package/src/components/editor-help/images/drag-and-drop-light@3x.png +0 -0
  361. package/src/components/editor-help/images/edit-media-dark.png +0 -0
  362. package/src/components/editor-help/images/edit-media-dark@2x.png +0 -0
  363. package/src/components/editor-help/images/edit-media-dark@3x.png +0 -0
  364. package/src/components/editor-help/images/edit-media-light.png +0 -0
  365. package/src/components/editor-help/images/edit-media-light@2x.png +0 -0
  366. package/src/components/editor-help/images/edit-media-light@3x.png +0 -0
  367. package/src/components/editor-help/images/embed-media-dark.png +0 -0
  368. package/src/components/editor-help/images/embed-media-dark@2x.png +0 -0
  369. package/src/components/editor-help/images/embed-media-dark@3x.png +0 -0
  370. package/src/components/editor-help/images/embed-media-light.png +0 -0
  371. package/src/components/editor-help/images/embed-media-light@2x.png +0 -0
  372. package/src/components/editor-help/images/embed-media-light@3x.png +0 -0
  373. package/src/components/editor-help/images/move-dark.png +0 -0
  374. package/src/components/editor-help/images/move-dark@2x.png +0 -0
  375. package/src/components/editor-help/images/move-dark@3x.png +0 -0
  376. package/src/components/editor-help/images/move-light.png +0 -0
  377. package/src/components/editor-help/images/move-light@2x.png +0 -0
  378. package/src/components/editor-help/images/move-light@3x.png +0 -0
  379. package/src/components/editor-help/images/options-dark.png +0 -0
  380. package/src/components/editor-help/images/options-dark@2x.png +0 -0
  381. package/src/components/editor-help/images/options-dark@3x.png +0 -0
  382. package/src/components/editor-help/images/options-light.png +0 -0
  383. package/src/components/editor-help/images/options-light@2x.png +0 -0
  384. package/src/components/editor-help/images/options-light@3x.png +0 -0
  385. package/src/components/editor-help/images/rich-text-dark.png +0 -0
  386. package/src/components/editor-help/images/rich-text-dark@2x.png +0 -0
  387. package/src/components/editor-help/images/rich-text-dark@3x.png +0 -0
  388. package/src/components/editor-help/images/rich-text-light.png +0 -0
  389. package/src/components/editor-help/images/rich-text-light@2x.png +0 -0
  390. package/src/components/editor-help/images/rich-text-light@3x.png +0 -0
  391. package/src/components/editor-help/images/settings-dark.png +0 -0
  392. package/src/components/editor-help/images/settings-dark@2x.png +0 -0
  393. package/src/components/editor-help/images/settings-dark@3x.png +0 -0
  394. package/src/components/editor-help/images/settings-light.png +0 -0
  395. package/src/components/editor-help/images/settings-light@2x.png +0 -0
  396. package/src/components/editor-help/images/settings-light@3x.png +0 -0
  397. package/src/components/editor-help/style.scss +0 -123
  398. package/src/components/post-revisions-panel/index.js +0 -161
  399. package/src/components/post-revisions-panel/style.scss +0 -16
  400. package/src/components/revision-author-panel/index.js +0 -36
  401. package/src/components/revision-created-panel/index.js +0 -36
@@ -6,6 +6,7 @@ import Textarea from 'react-autosize-textarea';
6
6
  /**
7
7
  * WordPress dependencies
8
8
  */
9
+ import { useLayoutEffect, useRef } from '@wordpress/element';
9
10
  import { __ } from '@wordpress/i18n';
10
11
  import { store as coreStore } from '@wordpress/core-data';
11
12
  import { useDispatch, useSelect } from '@wordpress/data';
@@ -16,6 +17,7 @@ import { VisuallyHidden } from '@wordpress/ui';
16
17
  * Internal dependencies
17
18
  */
18
19
  import { store as editorStore } from '../../store';
20
+ import { adjustPosition, getDiff } from './utils';
19
21
 
20
22
  /**
21
23
  * Displays the Post Text Editor along with content in Visual and Text mode.
@@ -24,6 +26,9 @@ import { store as editorStore } from '../../store';
24
26
  */
25
27
  export default function PostTextEditor() {
26
28
  const instanceId = useInstanceId( PostTextEditor );
29
+ const textareaRef = useRef();
30
+ const previousValueRef = useRef();
31
+ const selectionRef = useRef();
27
32
  const { value, type, id } = useSelect( ( select ) => {
28
33
  const { getCurrentPostType, getCurrentPostId, getEditedPostContent } =
29
34
  select( editorStore );
@@ -35,6 +40,58 @@ export default function PostTextEditor() {
35
40
  }, [] );
36
41
  const { editEntityRecord } = useDispatch( coreStore );
37
42
 
43
+ useLayoutEffect( () => {
44
+ const textarea = textareaRef.current;
45
+ const previousValue = previousValueRef.current;
46
+ previousValueRef.current = value;
47
+
48
+ if (
49
+ ! textarea ||
50
+ previousValue === undefined ||
51
+ previousValue === value ||
52
+ ! selectionRef.current
53
+ ) {
54
+ return;
55
+ }
56
+
57
+ const { selectionStart, selectionEnd, selectionDirection } =
58
+ selectionRef.current;
59
+ const changes = getDiff( previousValue, value );
60
+ const adjustedSelectionStart = adjustPosition(
61
+ selectionStart,
62
+ changes,
63
+ previousValue,
64
+ value
65
+ );
66
+ const adjustedSelectionEnd = adjustPosition(
67
+ selectionEnd,
68
+ changes,
69
+ previousValue,
70
+ value
71
+ );
72
+
73
+ textarea.setSelectionRange(
74
+ adjustedSelectionStart,
75
+ adjustedSelectionEnd,
76
+ selectionDirection
77
+ );
78
+ selectionRef.current = {
79
+ selectionStart: adjustedSelectionStart,
80
+ selectionEnd: adjustedSelectionEnd,
81
+ selectionDirection,
82
+ };
83
+ }, [ value ] );
84
+
85
+ const updateSelection = ( event ) => {
86
+ const { selectionStart, selectionEnd, selectionDirection } =
87
+ event.target;
88
+ selectionRef.current = {
89
+ selectionStart,
90
+ selectionEnd,
91
+ selectionDirection,
92
+ };
93
+ };
94
+
38
95
  return (
39
96
  <>
40
97
  <VisuallyHidden
@@ -46,14 +103,22 @@ export default function PostTextEditor() {
46
103
  <Textarea
47
104
  autoComplete="off"
48
105
  dir="auto"
106
+ ref={ textareaRef }
49
107
  value={ value }
50
108
  onChange={ ( event ) => {
109
+ updateSelection( event );
110
+ previousValueRef.current = event.target.value;
51
111
  editEntityRecord( 'postType', type, id, {
52
112
  content: event.target.value,
53
113
  blocks: undefined,
54
114
  selection: undefined,
55
115
  } );
56
116
  } }
117
+ onFocus={ updateSelection }
118
+ // A click or arrow-key caret move does not fire `select` (only
119
+ // range selections do), so track those moves via mouseup/keyup.
120
+ onMouseUp={ updateSelection }
121
+ onKeyUp={ updateSelection }
57
122
  className="editor-post-text-editor"
58
123
  id={ `post-content-${ instanceId }` }
59
124
  placeholder={ __( 'Start writing with text or HTML' ) }
@@ -0,0 +1,210 @@
1
+ /**
2
+ * Internal dependencies
3
+ */
4
+ import { getAdjustedCursorPosition } from '../utils';
5
+
6
+ describe( 'PostTextEditor', () => {
7
+ describe( 'getAdjustedCursorPosition', () => {
8
+ it( 'keeps the cursor in place when text is inserted after it', () => {
9
+ expect(
10
+ getAdjustedCursorPosition( 3, 'foo bar', 'foo bar baz' )
11
+ ).toBe( 3 );
12
+ } );
13
+
14
+ it( 'moves the cursor when text is inserted before it', () => {
15
+ expect( getAdjustedCursorPosition( 4, 'abcd', 'abXYcd' ) ).toBe(
16
+ 6
17
+ );
18
+ } );
19
+
20
+ it( 'moves the cursor when text is deleted before it', () => {
21
+ expect( getAdjustedCursorPosition( 6, 'abcdef', 'abef' ) ).toBe(
22
+ 4
23
+ );
24
+ } );
25
+
26
+ it( 'moves the cursor to the end of a replacement around it', () => {
27
+ expect( getAdjustedCursorPosition( 3, 'abcdef', 'abXYef' ) ).toBe(
28
+ 4
29
+ );
30
+ } );
31
+
32
+ it( 'handles multiple separated changes in one update', () => {
33
+ expect(
34
+ getAdjustedCursorPosition( 7, 'abcdefghij', 'abXXcdefYYghij' )
35
+ ).toBe( 11 );
36
+ } );
37
+
38
+ it( 'keeps the cursor in place when large text is inserted after it', () => {
39
+ const oldValue = `cursor\n${ 'a\n'.repeat( 6000 ) }`;
40
+ const newValue = `${ oldValue }remote\n`;
41
+
42
+ expect(
43
+ getAdjustedCursorPosition( 'cursor'.length, oldValue, newValue )
44
+ ).toBe( 'cursor'.length );
45
+ } );
46
+
47
+ it( 'moves the cursor when large text is inserted before it', () => {
48
+ const oldValue = `cursor\n${ 'a\n'.repeat( 6000 ) }`;
49
+ const newValue = `remote\n${ oldValue }`;
50
+
51
+ expect(
52
+ getAdjustedCursorPosition( 'cursor'.length, oldValue, newValue )
53
+ ).toBe( 'remote\n'.length + 'cursor'.length );
54
+ } );
55
+
56
+ it( 'moves the cursor when large text is deleted before it', () => {
57
+ const deletedPrefix = 'remote\n';
58
+ const newValue = `cursor\n${ 'a\n'.repeat( 6000 ) }`;
59
+ const oldValue = `${ deletedPrefix }${ newValue }`;
60
+ const position = deletedPrefix.length + 'cursor'.length;
61
+
62
+ expect(
63
+ getAdjustedCursorPosition( position, oldValue, newValue )
64
+ ).toBe( 'cursor'.length );
65
+ } );
66
+
67
+ it( 'moves the cursor when large single-line HTML is inserted before it', () => {
68
+ const opening = '<!-- wp:paragraph -->\n<p>';
69
+ const closing = '</p>\n<!-- /wp:paragraph -->';
70
+ const content = 'a'.repeat( 120000 );
71
+ const insertedText = 'remote';
72
+ const tailText = 'tail';
73
+ const oldValue = `${ opening }${ content }${ closing }`;
74
+ const newValue = `${ opening }${ insertedText }${ content.slice(
75
+ 0,
76
+ 100000
77
+ ) }${ tailText }${ content.slice( 100000 ) }${ closing }`;
78
+ const position = opening.length + 60000;
79
+
80
+ expect(
81
+ getAdjustedCursorPosition( position, oldValue, newValue )
82
+ ).toBe( position + insertedText.length );
83
+ } );
84
+
85
+ it( 'moves the cursor when large single-line HTML is deleted before it', () => {
86
+ const opening = '<!-- wp:paragraph -->\n<p>';
87
+ const closing = '</p>\n<!-- /wp:paragraph -->';
88
+ const deletedText = 'remote'.repeat( 1000 );
89
+ const deletedTailText = 'tail';
90
+ const content = 'a'.repeat( 120000 );
91
+ const newValue = `${ opening }${ content }${ closing }`;
92
+ const oldValue = `${ opening }${ deletedText }${ content.slice(
93
+ 0,
94
+ 100000
95
+ ) }${ deletedTailText }${ content.slice( 100000 ) }${ closing }`;
96
+ const position = opening.length + deletedText.length + 60000;
97
+
98
+ expect(
99
+ getAdjustedCursorPosition( position, oldValue, newValue )
100
+ ).toBe( position - deletedText.length );
101
+ } );
102
+
103
+ it( 'keeps the cursor in an unchanged same-line prefix before a large replacement', () => {
104
+ const prefix = `${ 'a'.repeat( 300 ) }\n${ 'b'.repeat( 199 ) }`;
105
+ const suffix = 'tail';
106
+ const oldValue = `${ prefix }old${ 'x'.repeat(
107
+ 11000
108
+ ) }${ suffix }`;
109
+ const newValue = `${ prefix }new${ 'y'.repeat(
110
+ 11000
111
+ ) }${ suffix }`;
112
+ const position = 450;
113
+
114
+ expect(
115
+ getAdjustedCursorPosition( position, oldValue, newValue )
116
+ ).toBe( position );
117
+ } );
118
+
119
+ it( 'moves the cursor when large same-line text is inserted before it and replaced after it', () => {
120
+ const opening = '<!-- wp:paragraph -->\n<p>';
121
+ const closing = '</p>\n<!-- /wp:paragraph -->';
122
+ const content = 'a'.repeat( 120000 );
123
+ const insertedText = 'remote';
124
+ const oldValue = `${ opening }${ content }${ closing }`;
125
+ const newValue = `${ opening }${ content.slice(
126
+ 0,
127
+ 50000
128
+ ) }${ insertedText }${ content.slice(
129
+ 50000,
130
+ 100000
131
+ ) }b${ content.slice( 100001 ) }${ closing }`;
132
+ const position = opening.length + 60000;
133
+
134
+ expect(
135
+ getAdjustedCursorPosition( position, oldValue, newValue )
136
+ ).toBe( position + insertedText.length );
137
+ } );
138
+
139
+ it( 'moves the cursor when large same-line text is deleted before it and inserted after it', () => {
140
+ const opening = '<!-- wp:paragraph -->\n<p>';
141
+ const closing = '</p>\n<!-- /wp:paragraph -->';
142
+ const content = 'a'.repeat( 120000 );
143
+ const deletedText = 'remote'.repeat( 1000 );
144
+ const insertedTailText = 'tail';
145
+ const commonTextBeforeCursor = 500;
146
+ const oldValue = `${ opening }${ content.slice(
147
+ 0,
148
+ 50000
149
+ ) }${ deletedText }${ content.slice( 50000 ) }${ closing }`;
150
+ const newValue = `${ opening }${ content.slice(
151
+ 0,
152
+ 100000
153
+ ) }${ insertedTailText }${ content.slice( 100000 ) }${ closing }`;
154
+ const position =
155
+ opening.length +
156
+ 50000 +
157
+ deletedText.length +
158
+ commonTextBeforeCursor;
159
+
160
+ expect(
161
+ getAdjustedCursorPosition( position, oldValue, newValue )
162
+ ).toBe( position - deletedText.length );
163
+ } );
164
+
165
+ it( 'maps the cursor through a pure insertion in a large single line', () => {
166
+ // "HEAD"/"TAIL" wrap the unchanged content, so the new value contains
167
+ // the old changed window and it routes through the line-diff fallback.
168
+ const opening = '<!-- wp:paragraph -->\n<p>';
169
+ const closing = '</p>\n<!-- /wp:paragraph -->';
170
+ const content = 'a'.repeat( 120000 );
171
+ const oldValue = `${ opening }${ content }${ closing }`;
172
+ const newValue = `${ opening }HEAD${ content }TAIL${ closing }`;
173
+ const position = opening.length + 60000;
174
+
175
+ expect(
176
+ getAdjustedCursorPosition( position, oldValue, newValue )
177
+ ).toBe( position + 'HEAD'.length );
178
+ } );
179
+
180
+ it( 'maps the cursor through a pure deletion in a large single line', () => {
181
+ const opening = '<!-- wp:paragraph -->\n<p>';
182
+ const closing = '</p>\n<!-- /wp:paragraph -->';
183
+ const content = 'a'.repeat( 120000 );
184
+ const oldValue = `${ opening }HEAD${ content }TAIL${ closing }`;
185
+ const newValue = `${ opening }${ content }${ closing }`;
186
+ const position = opening.length + 'HEAD'.length + 60000;
187
+
188
+ expect(
189
+ getAdjustedCursorPosition( position, oldValue, newValue )
190
+ ).toBe( position - 'HEAD'.length );
191
+ } );
192
+
193
+ it( 'handles a large fully-divergent replacement without blocking', () => {
194
+ // Neither side contains the other and the changed window exceeds the
195
+ // diffChars threshold, so this routes to the line-diff fallback. A
196
+ // character diff here would be O(n^2) and freeze the main thread for
197
+ // seconds; completing within the test timeout guards that path.
198
+ const oldValue = 'a'.repeat( 8000 );
199
+ const newValue = 'b'.repeat( 8000 );
200
+ const result = getAdjustedCursorPosition(
201
+ 4000,
202
+ oldValue,
203
+ newValue
204
+ );
205
+
206
+ expect( result ).toBeGreaterThanOrEqual( 0 );
207
+ expect( result ).toBeLessThanOrEqual( newValue.length );
208
+ } );
209
+ } );
210
+ } );
@@ -0,0 +1,204 @@
1
+ /**
2
+ * External dependencies
3
+ */
4
+ import { diffChars } from 'diff/lib/diff/character';
5
+ import { diffLines } from 'diff/lib/diff/line';
6
+
7
+ // Character diffing (Myers) is cheap when the edit distance is small but
8
+ // degrades toward O(n^2) as the two strings diverge: a full replacement of
9
+ // ~10k differing chars blocks the main thread for seconds. Cap the input handed
10
+ // to diffChars so the worst case stays small (~100ms); larger windows fall back
11
+ // to a line diff, with the cursor remapped by getCursorOffsetFromCommonText...
12
+ const STRING_TOO_LARGE_THRESHOLD = 1000;
13
+
14
+ /**
15
+ * Diffs two strings into a list of `{ value, added?, removed? }` change parts.
16
+ *
17
+ * @param {string} oldValue The previous string.
18
+ * @param {string} newValue The next string.
19
+ * @return {Array<Object>} The diff change parts.
20
+ */
21
+ export function getDiff( oldValue, newValue ) {
22
+ const maxStringLength = Math.max( oldValue.length, newValue.length );
23
+
24
+ if ( maxStringLength <= STRING_TOO_LARGE_THRESHOLD ) {
25
+ return diffChars( oldValue, newValue );
26
+ }
27
+
28
+ let start = 0;
29
+ const minStringLength = Math.min( oldValue.length, newValue.length );
30
+
31
+ while (
32
+ start < minStringLength &&
33
+ oldValue[ start ] === newValue[ start ]
34
+ ) {
35
+ start++;
36
+ }
37
+
38
+ let oldEnd = oldValue.length;
39
+ let newEnd = newValue.length;
40
+
41
+ while (
42
+ oldEnd > start &&
43
+ newEnd > start &&
44
+ oldValue[ oldEnd - 1 ] === newValue[ newEnd - 1 ]
45
+ ) {
46
+ oldEnd--;
47
+ newEnd--;
48
+ }
49
+
50
+ const oldChangedValue = oldValue.slice( start, oldEnd );
51
+ const newChangedValue = newValue.slice( start, newEnd );
52
+ const maxChangedStringLength = Math.max(
53
+ oldChangedValue.length,
54
+ newChangedValue.length
55
+ );
56
+ let changes;
57
+
58
+ if ( maxChangedStringLength <= STRING_TOO_LARGE_THRESHOLD ) {
59
+ changes = diffChars( oldChangedValue, newChangedValue );
60
+ } else {
61
+ changes = diffLines( oldChangedValue, newChangedValue );
62
+ }
63
+
64
+ if ( start > 0 ) {
65
+ changes.unshift( { value: oldValue.slice( 0, start ) } );
66
+ }
67
+
68
+ if ( oldEnd < oldValue.length ) {
69
+ changes.push( { value: oldValue.slice( oldEnd ) } );
70
+ }
71
+
72
+ return changes;
73
+ }
74
+
75
+ function clampCursorPosition( position, value ) {
76
+ return Math.max( 0, Math.min( value.length, position ) );
77
+ }
78
+
79
+ // A coarse (line-level) diff reports a whole changed region as one replacement,
80
+ // which would otherwise snap the cursor to the region's end. Recover a precise
81
+ // position by finding the longest run of text ending at the cursor that is
82
+ // preserved in the replacement, then placing the cursor just past where that
83
+ // run starts in the new text. This uses indexOf (near-linear in V8) rather than
84
+ // a character diff, so it stays cheap even across a large single-line region.
85
+ function getCursorOffsetFromCommonTextBeforeCursor(
86
+ oldValue,
87
+ newValue,
88
+ position
89
+ ) {
90
+ const oldValueBeforeCursor = oldValue.slice( 0, position );
91
+ let low = 1;
92
+ let high = oldValueBeforeCursor.length;
93
+ let cursorOffset;
94
+
95
+ while ( low <= high ) {
96
+ const length = Math.floor( ( low + high ) / 2 );
97
+ const index = newValue.indexOf(
98
+ oldValueBeforeCursor.slice( oldValueBeforeCursor.length - length )
99
+ );
100
+
101
+ if ( index === -1 ) {
102
+ high = length - 1;
103
+ } else {
104
+ cursorOffset = index + length;
105
+ low = length + 1;
106
+ }
107
+ }
108
+
109
+ return cursorOffset;
110
+ }
111
+
112
+ /**
113
+ * Maps a cursor position from the old string to the new string given a diff.
114
+ *
115
+ * @param {number} position The cursor position in the old string.
116
+ * @param {Array<Object>} changes The diff returned by `getDiff`.
117
+ * @param {string} oldValue The previous string.
118
+ * @param {string} newValue The next string.
119
+ * @return {number} The adjusted cursor position in the new string.
120
+ */
121
+ export function adjustPosition( position, changes, oldValue, newValue ) {
122
+ let oldIndex = 0;
123
+ let newIndex = 0;
124
+ let adjustedPosition = position;
125
+
126
+ for ( let i = 0; i < changes.length; i++ ) {
127
+ const change = changes[ i ];
128
+ if ( ! change.added && ! change.removed ) {
129
+ oldIndex += change.value.length;
130
+ newIndex += change.value.length;
131
+ continue;
132
+ }
133
+
134
+ const oldStart = oldIndex;
135
+ const newStart = newIndex;
136
+ let oldLength = 0;
137
+ let newLength = 0;
138
+
139
+ while (
140
+ i < changes.length &&
141
+ ( changes[ i ].added || changes[ i ].removed )
142
+ ) {
143
+ if ( changes[ i ].removed ) {
144
+ oldLength += changes[ i ].value.length;
145
+ } else {
146
+ newLength += changes[ i ].value.length;
147
+ }
148
+ i++;
149
+ }
150
+ i--;
151
+
152
+ const oldEnd = oldStart + oldLength;
153
+ const newEnd = newStart + newLength;
154
+
155
+ if ( position < oldStart ) {
156
+ // The cursor is before this change, so nothing here can move it.
157
+ break;
158
+ }
159
+
160
+ if ( oldLength === 0 ) {
161
+ // Pure insertion at or before the cursor: shift it right by the
162
+ // inserted length.
163
+ adjustedPosition += newLength;
164
+ } else if ( position <= oldEnd ) {
165
+ // The cursor falls inside a replaced region; recover its precise
166
+ // spot from the text preserved around it.
167
+ const cursorOffset = getCursorOffsetFromCommonTextBeforeCursor(
168
+ oldValue.slice( oldStart, oldEnd ),
169
+ newValue.slice( newStart, newEnd ),
170
+ position - oldStart
171
+ );
172
+
173
+ adjustedPosition =
174
+ cursorOffset === undefined ? newEnd : newStart + cursorOffset;
175
+ break;
176
+ } else {
177
+ // The cursor is after this change: shift it by the net length delta.
178
+ adjustedPosition += newLength - oldLength;
179
+ }
180
+
181
+ oldIndex += oldLength;
182
+ newIndex += newLength;
183
+ }
184
+
185
+ return clampCursorPosition( adjustedPosition, newValue );
186
+ }
187
+
188
+ /**
189
+ * Diffs `oldValue` against `newValue` and maps a cursor `position` from the old
190
+ * string to the new one.
191
+ *
192
+ * @param {number} position The cursor position in the old string.
193
+ * @param {string} oldValue The previous string.
194
+ * @param {string} newValue The next string.
195
+ * @return {number} The adjusted cursor position in the new string.
196
+ */
197
+ export function getAdjustedCursorPosition( position, oldValue, newValue ) {
198
+ return adjustPosition(
199
+ position,
200
+ getDiff( oldValue, newValue ),
201
+ oldValue,
202
+ newValue
203
+ );
204
+ }
@@ -54,6 +54,17 @@ describe( 'PostTypeSupportCheck', () => {
54
54
  expect( container ).not.toHaveTextContent( 'Supported' );
55
55
  } );
56
56
 
57
+ it( 'does not crash when the post type has no `supports` object', () => {
58
+ setupUseSelectMock( {} );
59
+ const { container } = render(
60
+ <PostTypeSupportCheck supportKeys="title">
61
+ Supported
62
+ </PostTypeSupportCheck>
63
+ );
64
+
65
+ expect( container ).not.toHaveTextContent( 'Supported' );
66
+ } );
67
+
57
68
  it( 'renders its children when post type is known and supports', () => {
58
69
  setupUseSelectMock( {
59
70
  supports: {
@@ -58,7 +58,7 @@ export default function PostURL( { onClose } ) {
58
58
  postSlug: safeDecodeURIComponent(
59
59
  select( editorStore ).getEditedPostSlug()
60
60
  ),
61
- viewPostLabel: postType?.labels.view_item,
61
+ viewPostLabel: postType?.labels?.view_item,
62
62
  postLink: post.link,
63
63
  permalinkPrefix: permalinkParts?.prefix,
64
64
  permalinkSuffix: permalinkParts?.suffix,
@@ -24,7 +24,7 @@ export default function PostViewLink() {
24
24
  return {
25
25
  permalink: select( editorStore ).getPermalink(),
26
26
  isPublished: select( editorStore ).isCurrentPostPublished(),
27
- label: postType?.labels.view_item,
27
+ label: postType?.labels?.view_item,
28
28
  hasLoaded: !! postType,
29
29
  showIconLabels: get( 'core', 'showIconLabels' ),
30
30
  };
@@ -0,0 +1,71 @@
1
+ /**
2
+ * External dependencies
3
+ */
4
+ import { render, screen } from '@testing-library/react';
5
+
6
+ /**
7
+ * WordPress dependencies
8
+ */
9
+ import { useSelect } from '@wordpress/data';
10
+
11
+ /**
12
+ * Internal dependencies
13
+ */
14
+ import PostViewLink from '../';
15
+
16
+ jest.mock( '@wordpress/data/src/components/use-select', () => jest.fn() );
17
+
18
+ const DEFAULTS = {
19
+ postType: { labels: { view_item: 'View Post' } },
20
+ permalink: 'https://example.com/sample/',
21
+ isPublished: true,
22
+ showIconLabels: false,
23
+ };
24
+
25
+ function setupUseSelectMock( overrides = {} ) {
26
+ // Use object spread (not destructure defaults) so an explicit `undefined`
27
+ // override actually overrides the default value.
28
+ const data = { ...DEFAULTS, ...overrides };
29
+ useSelect.mockImplementation( ( cb ) =>
30
+ cb( () => ( {
31
+ getCurrentPostType: () => 'post',
32
+ getPostType: () => data.postType,
33
+ getPermalink: () => data.permalink,
34
+ isCurrentPostPublished: () => data.isPublished,
35
+ get: () => data.showIconLabels,
36
+ } ) )
37
+ );
38
+ }
39
+
40
+ describe( 'PostViewLink', () => {
41
+ it( 'renders the post type-specific view label when available', () => {
42
+ setupUseSelectMock();
43
+ render( <PostViewLink /> );
44
+ expect( screen.getByLabelText( 'View Post' ) ).toBeInTheDocument();
45
+ } );
46
+
47
+ it( 'falls back to "View post" without crashing when the post type has no labels', () => {
48
+ // See https://github.com/WordPress/gutenberg/issues/62918.
49
+ setupUseSelectMock( { postType: {} } );
50
+ render( <PostViewLink /> );
51
+ expect( screen.getByLabelText( 'View post' ) ).toBeInTheDocument();
52
+ } );
53
+
54
+ it( 'renders nothing if the post is not published', () => {
55
+ setupUseSelectMock( { isPublished: false } );
56
+ const { container } = render( <PostViewLink /> );
57
+ expect( container ).toBeEmptyDOMElement();
58
+ } );
59
+
60
+ it( 'renders nothing if no permalink is available', () => {
61
+ setupUseSelectMock( { permalink: undefined } );
62
+ const { container } = render( <PostViewLink /> );
63
+ expect( container ).toBeEmptyDOMElement();
64
+ } );
65
+
66
+ it( 'renders nothing while the post type has not loaded', () => {
67
+ setupUseSelectMock( { postType: undefined } );
68
+ const { container } = render( <PostViewLink /> );
69
+ expect( container ).toBeEmptyDOMElement();
70
+ } );
71
+ } );
@@ -380,7 +380,8 @@ export const ExperimentalEditorProvider = withRegistryProvider(
380
380
  }, [ post.type, post.id, setEditedPost, removeNotice ] );
381
381
 
382
382
  // Synchronize the editor settings as they change.
383
- useEffect( () => {
383
+ // Do it as a layout effect so that rendered UI with outdated settings is not painted.
384
+ useLayoutEffect( () => {
384
385
  updateEditorSettings( settings );
385
386
  }, [ settings, updateEditorSettings ] );
386
387
 
@@ -4,7 +4,6 @@
4
4
  import { __ } from '@wordpress/i18n';
5
5
  import { LEFT, RIGHT } from '@wordpress/keycodes';
6
6
  import { __unstableMotion as motion } from '@wordpress/components';
7
- // eslint-disable-next-line @wordpress/use-recommended-components -- `Tooltip` is not yet on the recommended `@wordpress/ui` allow-list; landing as a migration step ahead of the wider rollout.
8
7
  import { Tooltip, VisuallyHidden } from '@wordpress/ui';
9
8
 
10
9
  const DELTA_DISTANCE = 20; // The distance to resize per keydown in pixels.
@@ -15,8 +15,14 @@ import PostPanelRow from '../post-panel-row';
15
15
  * @param {string} props.title Panel title.
16
16
  * @param {Object} props.entries Map of key → diffWords parts arrays.
17
17
  * @param {boolean} props.initialOpen Whether the panel starts open.
18
+ * @param {string} [props.className] Optional class for the content wrapper.
18
19
  */
19
- export default function RevisionDiffPanel( { title, entries, initialOpen } ) {
20
+ export default function RevisionDiffPanel( {
21
+ title,
22
+ entries,
23
+ initialOpen,
24
+ className,
25
+ } ) {
20
26
  if ( ! entries ) {
21
27
  return null;
22
28
  }
@@ -53,7 +59,7 @@ export default function RevisionDiffPanel( { title, entries, initialOpen } ) {
53
59
 
54
60
  return (
55
61
  <PanelBody title={ title } initialOpen={ initialOpen }>
56
- { fields }
62
+ <div className={ className }>{ fields }</div>
57
63
  </PanelBody>
58
64
  );
59
65
  }