@wordpress/editor 14.48.1 → 14.49.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 (460) hide show
  1. package/CHANGELOG.md +2 -0
  2. package/README.md +5 -13
  3. package/build/bindings/pattern-overrides.cjs +1 -1
  4. package/build/bindings/pattern-overrides.cjs.map +2 -2
  5. package/build/components/autosave-monitor/index.cjs +40 -83
  6. package/build/components/autosave-monitor/index.cjs.map +3 -3
  7. package/build/components/collab-sidebar/note-byline.cjs +1 -1
  8. package/build/components/collab-sidebar/note-byline.cjs.map +2 -2
  9. package/build/components/collab-sidebar/note.cjs +49 -17
  10. package/build/components/collab-sidebar/note.cjs.map +3 -3
  11. package/build/components/collab-sidebar/notes.cjs.map +1 -1
  12. package/build/components/collab-sidebar/utils.cjs +1 -1
  13. package/build/components/collab-sidebar/utils.cjs.map +2 -2
  14. package/build/components/collaborators-overlay/avatar-iframe-styles.cjs.map +1 -1
  15. package/build/components/collaborators-overlay/collaborator-styles.cjs.map +1 -1
  16. package/build/components/collaborators-overlay/compute-selection.cjs.map +1 -1
  17. package/build/components/collaborators-overlay/overlay-iframe-styles.cjs +1 -1
  18. package/build/components/collaborators-overlay/overlay-iframe-styles.cjs.map +1 -1
  19. package/build/components/collaborators-overlay/use-block-highlighting.cjs.map +1 -1
  20. package/build/components/collaborators-presence/avatar/component.cjs.map +2 -2
  21. package/build/components/collaborators-presence/avatar/use-image-loading-status.cjs.map +1 -1
  22. package/build/components/document-bar/index.cjs +7 -5
  23. package/build/components/document-bar/index.cjs.map +2 -2
  24. package/build/components/global-keyboard-shortcuts/index.cjs +3 -2
  25. package/build/components/global-keyboard-shortcuts/index.cjs.map +2 -2
  26. package/build/components/global-styles-sidebar/welcome-guide.cjs +3 -3
  27. package/build/components/global-styles-sidebar/welcome-guide.cjs.map +1 -1
  28. package/build/components/local-autosave-monitor/index.cjs +14 -15
  29. package/build/components/local-autosave-monitor/index.cjs.map +2 -2
  30. package/build/components/page-attributes/parent.cjs +1 -1
  31. package/build/components/page-attributes/parent.cjs.map +2 -2
  32. package/build/components/post-card-panel/index.cjs +1 -1
  33. package/build/components/post-card-panel/index.cjs.map +2 -2
  34. package/build/components/post-excerpt/panel.cjs +1 -1
  35. package/build/components/post-excerpt/panel.cjs.map +2 -2
  36. package/build/components/post-locked-modal/index.cjs +3 -3
  37. package/build/components/post-locked-modal/index.cjs.map +1 -1
  38. package/build/components/post-preview-button/index.cjs +2 -2
  39. package/build/components/post-preview-button/index.cjs.map +2 -2
  40. package/build/components/post-publish-button/index.cjs +4 -3
  41. package/build/components/post-publish-button/index.cjs.map +2 -2
  42. package/build/components/post-publish-button/label.cjs +2 -2
  43. package/build/components/post-publish-button/label.cjs.map +2 -2
  44. package/build/components/post-publish-panel/index.cjs.map +1 -1
  45. package/build/components/post-publish-panel/postpublish.cjs +1 -2
  46. package/build/components/post-publish-panel/postpublish.cjs.map +2 -2
  47. package/build/components/post-revisions-preview/block-diff.cjs.map +1 -1
  48. package/build/components/post-revisions-preview/diff-markers.cjs.map +2 -2
  49. package/build/components/post-revisions-preview/revisions-slider.cjs +1 -1
  50. package/build/components/post-revisions-preview/revisions-slider.cjs.map +2 -2
  51. package/build/components/post-revisions-timeline/index.cjs +173 -0
  52. package/build/components/post-revisions-timeline/index.cjs.map +7 -0
  53. package/build/components/post-saved-state/index.cjs +17 -26
  54. package/build/components/post-saved-state/index.cjs.map +2 -2
  55. package/build/components/post-schedule/label.cjs +5 -5
  56. package/build/components/post-schedule/label.cjs.map +1 -1
  57. package/build/components/post-status/index.cjs +0 -1
  58. package/build/components/post-status/index.cjs.map +2 -2
  59. package/build/components/post-taxonomies/flat-term-selector.cjs +2 -1
  60. package/build/components/post-taxonomies/flat-term-selector.cjs.map +3 -3
  61. package/build/components/post-taxonomies/hierarchical-term-selector.cjs +1 -2
  62. package/build/components/post-taxonomies/hierarchical-term-selector.cjs.map +2 -2
  63. package/build/components/post-template/create-new-template-modal.cjs +0 -1
  64. package/build/components/post-template/create-new-template-modal.cjs.map +2 -2
  65. package/build/components/post-text-editor/index.cjs +51 -0
  66. package/build/components/post-text-editor/index.cjs.map +2 -2
  67. package/build/components/post-text-editor/utils.cjs +150 -0
  68. package/build/components/post-text-editor/utils.cjs.map +7 -0
  69. package/build/components/post-url/index.cjs +1 -1
  70. package/build/components/post-url/index.cjs.map +2 -2
  71. package/build/components/post-view-link/index.cjs +1 -1
  72. package/build/components/post-view-link/index.cjs.map +2 -2
  73. package/build/components/post-visibility/index.cjs +0 -1
  74. package/build/components/post-visibility/index.cjs.map +2 -2
  75. package/build/components/provider/disable-non-page-content-blocks.cjs +23 -3
  76. package/build/components/provider/disable-non-page-content-blocks.cjs.map +2 -2
  77. package/build/components/provider/index.cjs +1 -1
  78. package/build/components/provider/index.cjs.map +2 -2
  79. package/build/components/provider/navigation-block-editing-mode.cjs +9 -2
  80. package/build/components/provider/navigation-block-editing-mode.cjs.map +2 -2
  81. package/build/components/provider/use-block-editor-settings.cjs +2 -1
  82. package/build/components/provider/use-block-editor-settings.cjs.map +2 -2
  83. package/build/components/resizable-editor/resize-handle.cjs.map +2 -2
  84. package/build/components/revision-diff-panel/index.cjs +7 -2
  85. package/build/components/revision-diff-panel/index.cjs.map +2 -2
  86. package/build/components/revision-fields-diff/index.cjs +6 -2
  87. package/build/components/revision-fields-diff/index.cjs.map +2 -2
  88. package/build/components/sidebar/dataform-post-summary.cjs +189 -29
  89. package/build/components/sidebar/dataform-post-summary.cjs.map +3 -3
  90. package/build/components/sidebar/index.cjs +1 -11
  91. package/build/components/sidebar/index.cjs.map +3 -3
  92. package/build/components/sidebar/post-revision-summary.cjs +11 -17
  93. package/build/components/sidebar/post-revision-summary.cjs.map +3 -3
  94. package/build/components/sidebar/post-summary.cjs +8 -6
  95. package/build/components/sidebar/post-summary.cjs.map +3 -3
  96. package/build/components/style-book/examples.cjs +1 -1
  97. package/build/components/style-book/examples.cjs.map +1 -1
  98. package/build/components/style-book/index.cjs +1 -1
  99. package/build/components/style-book/index.cjs.map +2 -2
  100. package/build/components/sync-connection-error-modal/index.cjs +3 -3
  101. package/build/components/sync-connection-error-modal/index.cjs.map +1 -1
  102. package/build/components/template-actions-panel/block-theme-content.cjs.map +2 -2
  103. package/build/components/template-actions-panel/index.cjs +0 -9
  104. package/build/components/template-actions-panel/index.cjs.map +3 -3
  105. package/build/components/template-validation-notice/index.cjs +1 -1
  106. package/build/components/template-validation-notice/index.cjs.map +1 -1
  107. package/build/components/upload-progress-snackbar/index.cjs +3 -3
  108. package/build/components/upload-progress-snackbar/index.cjs.map +2 -2
  109. package/build/components/upload-progress-snackbar/tracker.cjs.map +1 -1
  110. package/build/components/visual-editor/edit-template-blocks-notification.cjs +1 -1
  111. package/build/components/visual-editor/edit-template-blocks-notification.cjs.map +1 -1
  112. package/build/{components/revision-author-panel → dataviews/fields/revisions}/index.cjs +18 -26
  113. package/build/dataviews/fields/revisions/index.cjs.map +7 -0
  114. package/build/dataviews/fields/revisions/revisions-view.cjs +74 -0
  115. package/build/dataviews/fields/revisions/revisions-view.cjs.map +7 -0
  116. package/build/dataviews/store/private-actions.cjs +17 -5
  117. package/build/dataviews/store/private-actions.cjs.map +3 -3
  118. package/build/hooks/push-changes-to-global-styles/index.cjs +1 -1
  119. package/build/hooks/push-changes-to-global-styles/index.cjs.map +1 -1
  120. package/build/store/actions.cjs +1 -1
  121. package/build/store/actions.cjs.map +2 -2
  122. package/build/store/private-actions.cjs +2 -2
  123. package/build/store/private-actions.cjs.map +2 -2
  124. package/build/store/private-selectors.cjs +6 -1
  125. package/build/store/private-selectors.cjs.map +2 -2
  126. package/build/utils/media-upload/index.cjs.map +1 -1
  127. package/build/utils/set-nested-value.cjs.map +1 -1
  128. package/build-module/bindings/pattern-overrides.mjs +1 -1
  129. package/build-module/bindings/pattern-overrides.mjs.map +2 -2
  130. package/build-module/components/autosave-monitor/index.mjs +42 -81
  131. package/build-module/components/autosave-monitor/index.mjs.map +2 -2
  132. package/build-module/components/collab-sidebar/note-byline.mjs +1 -1
  133. package/build-module/components/collab-sidebar/note-byline.mjs.map +2 -2
  134. package/build-module/components/collab-sidebar/note.mjs +50 -18
  135. package/build-module/components/collab-sidebar/note.mjs.map +2 -2
  136. package/build-module/components/collab-sidebar/notes.mjs.map +1 -1
  137. package/build-module/components/collab-sidebar/utils.mjs +1 -1
  138. package/build-module/components/collab-sidebar/utils.mjs.map +2 -2
  139. package/build-module/components/collaborators-overlay/avatar-iframe-styles.mjs.map +1 -1
  140. package/build-module/components/collaborators-overlay/collaborator-styles.mjs.map +1 -1
  141. package/build-module/components/collaborators-overlay/compute-selection.mjs.map +1 -1
  142. package/build-module/components/collaborators-overlay/overlay-iframe-styles.mjs +1 -1
  143. package/build-module/components/collaborators-overlay/overlay-iframe-styles.mjs.map +1 -1
  144. package/build-module/components/collaborators-overlay/use-block-highlighting.mjs.map +1 -1
  145. package/build-module/components/collaborators-presence/avatar/component.mjs.map +2 -2
  146. package/build-module/components/collaborators-presence/avatar/use-image-loading-status.mjs.map +1 -1
  147. package/build-module/components/document-bar/index.mjs +7 -5
  148. package/build-module/components/document-bar/index.mjs.map +2 -2
  149. package/build-module/components/global-keyboard-shortcuts/index.mjs +3 -2
  150. package/build-module/components/global-keyboard-shortcuts/index.mjs.map +2 -2
  151. package/build-module/components/global-styles-sidebar/welcome-guide.mjs +3 -3
  152. package/build-module/components/global-styles-sidebar/welcome-guide.mjs.map +1 -1
  153. package/build-module/components/local-autosave-monitor/index.mjs +15 -16
  154. package/build-module/components/local-autosave-monitor/index.mjs.map +2 -2
  155. package/build-module/components/page-attributes/parent.mjs +1 -1
  156. package/build-module/components/page-attributes/parent.mjs.map +2 -2
  157. package/build-module/components/post-card-panel/index.mjs +1 -1
  158. package/build-module/components/post-card-panel/index.mjs.map +2 -2
  159. package/build-module/components/post-excerpt/panel.mjs +1 -1
  160. package/build-module/components/post-excerpt/panel.mjs.map +2 -2
  161. package/build-module/components/post-locked-modal/index.mjs +3 -3
  162. package/build-module/components/post-locked-modal/index.mjs.map +1 -1
  163. package/build-module/components/post-preview-button/index.mjs +2 -2
  164. package/build-module/components/post-preview-button/index.mjs.map +2 -2
  165. package/build-module/components/post-publish-button/index.mjs +4 -3
  166. package/build-module/components/post-publish-button/index.mjs.map +2 -2
  167. package/build-module/components/post-publish-button/label.mjs +2 -2
  168. package/build-module/components/post-publish-button/label.mjs.map +2 -2
  169. package/build-module/components/post-publish-panel/index.mjs.map +1 -1
  170. package/build-module/components/post-publish-panel/postpublish.mjs +1 -2
  171. package/build-module/components/post-publish-panel/postpublish.mjs.map +2 -2
  172. package/build-module/components/post-revisions-preview/block-diff.mjs.map +1 -1
  173. package/build-module/components/post-revisions-preview/diff-markers.mjs.map +2 -2
  174. package/build-module/components/post-revisions-preview/revisions-slider.mjs +1 -1
  175. package/build-module/components/post-revisions-preview/revisions-slider.mjs.map +2 -2
  176. package/build-module/components/post-revisions-timeline/index.mjs +152 -0
  177. package/build-module/components/post-revisions-timeline/index.mjs.map +7 -0
  178. package/build-module/components/post-saved-state/index.mjs +17 -26
  179. package/build-module/components/post-saved-state/index.mjs.map +2 -2
  180. package/build-module/components/post-schedule/label.mjs +5 -5
  181. package/build-module/components/post-schedule/label.mjs.map +1 -1
  182. package/build-module/components/post-status/index.mjs +0 -1
  183. package/build-module/components/post-status/index.mjs.map +2 -2
  184. package/build-module/components/post-taxonomies/flat-term-selector.mjs +3 -6
  185. package/build-module/components/post-taxonomies/flat-term-selector.mjs.map +2 -2
  186. package/build-module/components/post-taxonomies/hierarchical-term-selector.mjs +1 -2
  187. package/build-module/components/post-taxonomies/hierarchical-term-selector.mjs.map +2 -2
  188. package/build-module/components/post-template/create-new-template-modal.mjs +0 -1
  189. package/build-module/components/post-template/create-new-template-modal.mjs.map +2 -2
  190. package/build-module/components/post-text-editor/index.mjs +51 -0
  191. package/build-module/components/post-text-editor/index.mjs.map +2 -2
  192. package/build-module/components/post-text-editor/utils.mjs +123 -0
  193. package/build-module/components/post-text-editor/utils.mjs.map +7 -0
  194. package/build-module/components/post-url/index.mjs +1 -1
  195. package/build-module/components/post-url/index.mjs.map +2 -2
  196. package/build-module/components/post-view-link/index.mjs +1 -1
  197. package/build-module/components/post-view-link/index.mjs.map +2 -2
  198. package/build-module/components/post-visibility/index.mjs +0 -1
  199. package/build-module/components/post-visibility/index.mjs.map +2 -2
  200. package/build-module/components/provider/disable-non-page-content-blocks.mjs +23 -3
  201. package/build-module/components/provider/disable-non-page-content-blocks.mjs.map +2 -2
  202. package/build-module/components/provider/index.mjs +1 -1
  203. package/build-module/components/provider/index.mjs.map +2 -2
  204. package/build-module/components/provider/navigation-block-editing-mode.mjs +10 -3
  205. package/build-module/components/provider/navigation-block-editing-mode.mjs.map +2 -2
  206. package/build-module/components/provider/use-block-editor-settings.mjs +2 -1
  207. package/build-module/components/provider/use-block-editor-settings.mjs.map +2 -2
  208. package/build-module/components/resizable-editor/resize-handle.mjs.map +2 -2
  209. package/build-module/components/revision-diff-panel/index.mjs +7 -2
  210. package/build-module/components/revision-diff-panel/index.mjs.map +2 -2
  211. package/build-module/components/revision-fields-diff/index.mjs +6 -2
  212. package/build-module/components/revision-fields-diff/index.mjs.map +2 -2
  213. package/build-module/components/sidebar/dataform-post-summary.mjs +190 -30
  214. package/build-module/components/sidebar/dataform-post-summary.mjs.map +2 -2
  215. package/build-module/components/sidebar/index.mjs +1 -11
  216. package/build-module/components/sidebar/index.mjs.map +2 -2
  217. package/build-module/components/sidebar/post-revision-summary.mjs +11 -17
  218. package/build-module/components/sidebar/post-revision-summary.mjs.map +2 -2
  219. package/build-module/components/sidebar/post-summary.mjs +8 -6
  220. package/build-module/components/sidebar/post-summary.mjs.map +2 -2
  221. package/build-module/components/style-book/examples.mjs +1 -1
  222. package/build-module/components/style-book/examples.mjs.map +1 -1
  223. package/build-module/components/style-book/index.mjs +1 -1
  224. package/build-module/components/style-book/index.mjs.map +2 -2
  225. package/build-module/components/sync-connection-error-modal/index.mjs +3 -3
  226. package/build-module/components/sync-connection-error-modal/index.mjs.map +1 -1
  227. package/build-module/components/template-actions-panel/block-theme-content.mjs.map +2 -2
  228. package/build-module/components/template-actions-panel/index.mjs +0 -9
  229. package/build-module/components/template-actions-panel/index.mjs.map +2 -2
  230. package/build-module/components/template-validation-notice/index.mjs +1 -1
  231. package/build-module/components/template-validation-notice/index.mjs.map +1 -1
  232. package/build-module/components/upload-progress-snackbar/index.mjs +3 -3
  233. package/build-module/components/upload-progress-snackbar/index.mjs.map +2 -2
  234. package/build-module/components/upload-progress-snackbar/tracker.mjs.map +1 -1
  235. package/build-module/components/visual-editor/edit-template-blocks-notification.mjs +1 -1
  236. package/build-module/components/visual-editor/edit-template-blocks-notification.mjs.map +1 -1
  237. package/build-module/dataviews/fields/revisions/index.mjs +20 -0
  238. package/build-module/dataviews/fields/revisions/index.mjs.map +7 -0
  239. package/build-module/dataviews/fields/revisions/revisions-view.mjs +53 -0
  240. package/build-module/dataviews/fields/revisions/revisions-view.mjs.map +7 -0
  241. package/build-module/dataviews/store/private-actions.mjs +28 -8
  242. package/build-module/dataviews/store/private-actions.mjs.map +2 -2
  243. package/build-module/hooks/push-changes-to-global-styles/index.mjs +1 -1
  244. package/build-module/hooks/push-changes-to-global-styles/index.mjs.map +1 -1
  245. package/build-module/store/actions.mjs +1 -1
  246. package/build-module/store/actions.mjs.map +2 -2
  247. package/build-module/store/private-actions.mjs +2 -2
  248. package/build-module/store/private-actions.mjs.map +2 -2
  249. package/build-module/store/private-selectors.mjs +7 -1
  250. package/build-module/store/private-selectors.mjs.map +2 -2
  251. package/build-module/utils/media-upload/index.mjs.map +1 -1
  252. package/build-module/utils/set-nested-value.mjs.map +1 -1
  253. package/build-style/style-rtl.css +298 -238
  254. package/build-style/style.css +298 -238
  255. package/build-types/components/autosave-monitor/index.d.ts +11 -29
  256. package/build-types/components/autosave-monitor/index.d.ts.map +1 -1
  257. package/build-types/components/collab-sidebar/note-byline.d.ts +0 -3
  258. package/build-types/components/collab-sidebar/note-byline.d.ts.map +1 -1
  259. package/build-types/components/collab-sidebar/note.d.ts.map +1 -1
  260. package/build-types/components/collaborators-presence/avatar/component.d.ts.map +1 -1
  261. package/build-types/components/document-bar/index.d.ts +2 -2
  262. package/build-types/components/document-bar/index.d.ts.map +1 -1
  263. package/build-types/components/global-keyboard-shortcuts/index.d.ts.map +1 -1
  264. package/build-types/components/local-autosave-monitor/index.d.ts.map +1 -1
  265. package/build-types/components/post-publish-button/index.d.ts.map +1 -1
  266. package/build-types/components/post-publish-panel/postpublish.d.ts.map +1 -1
  267. package/build-types/components/post-revisions-preview/diff-markers.d.ts.map +1 -1
  268. package/build-types/components/post-revisions-timeline/index.d.ts +2 -0
  269. package/build-types/components/post-revisions-timeline/index.d.ts.map +1 -0
  270. package/build-types/components/post-saved-state/index.d.ts.map +1 -1
  271. package/build-types/components/post-status/index.d.ts.map +1 -1
  272. package/build-types/components/post-taxonomies/flat-term-selector.d.ts.map +1 -1
  273. package/build-types/components/post-taxonomies/hierarchical-term-selector.d.ts.map +1 -1
  274. package/build-types/components/post-template/create-new-template-modal.d.ts.map +1 -1
  275. package/build-types/components/post-text-editor/index.d.ts +1 -1
  276. package/build-types/components/post-text-editor/index.d.ts.map +1 -1
  277. package/build-types/components/post-visibility/index.d.ts.map +1 -1
  278. package/build-types/components/provider/disable-non-page-content-blocks.d.ts.map +1 -1
  279. package/build-types/components/provider/index.d.ts.map +1 -1
  280. package/build-types/components/provider/navigation-block-editing-mode.d.ts.map +1 -1
  281. package/build-types/components/provider/use-block-editor-settings.d.ts.map +1 -1
  282. package/build-types/components/resizable-editor/resize-handle.d.ts.map +1 -1
  283. package/build-types/components/revision-diff-panel/index.d.ts +3 -1
  284. package/build-types/components/revision-diff-panel/index.d.ts.map +1 -1
  285. package/build-types/components/revision-fields-diff/index.d.ts.map +1 -1
  286. package/build-types/components/sidebar/dataform-post-summary.d.ts.map +1 -1
  287. package/build-types/components/sidebar/index.d.ts.map +1 -1
  288. package/build-types/components/sidebar/post-revision-summary.d.ts.map +1 -1
  289. package/build-types/components/sidebar/post-summary.d.ts.map +1 -1
  290. package/build-types/components/template-actions-panel/block-theme-content.d.ts.map +1 -1
  291. package/build-types/components/template-actions-panel/index.d.ts.map +1 -1
  292. package/build-types/dataviews/fields/revisions/index.d.ts +8 -0
  293. package/build-types/dataviews/fields/revisions/index.d.ts.map +1 -0
  294. package/build-types/dataviews/fields/revisions/revisions-view.d.ts +2 -0
  295. package/build-types/dataviews/fields/revisions/revisions-view.d.ts.map +1 -0
  296. package/build-types/dataviews/store/private-actions.d.ts.map +1 -1
  297. package/build-types/store/private-selectors.d.ts +1 -1
  298. package/build-types/store/private-selectors.d.ts.map +1 -1
  299. package/build-types/store/selectors.d.ts +1 -1
  300. package/build-types/store/selectors.d.ts.map +1 -1
  301. package/build-types/utils/get-template-part-icon.d.ts.map +1 -1
  302. package/package.json +53 -47
  303. package/src/bindings/pattern-overrides.js +1 -1
  304. package/src/bindings/test/pattern-overrides.js +65 -0
  305. package/src/components/autosave-monitor/index.js +69 -104
  306. package/src/components/autosave-monitor/test/index.js +137 -122
  307. package/src/components/collab-sidebar/note-byline.js +0 -1
  308. package/src/components/collab-sidebar/note.js +64 -29
  309. package/src/components/collab-sidebar/style.scss +20 -0
  310. package/src/components/collaborators-presence/avatar/component.tsx +0 -1
  311. package/src/components/collaborators-presence/avatar/test/index.tsx +0 -1
  312. package/src/components/document-bar/index.js +8 -3
  313. package/src/components/document-bar/style.scss +4 -2
  314. package/src/components/global-keyboard-shortcuts/index.js +2 -1
  315. package/src/components/local-autosave-monitor/index.js +23 -21
  316. package/src/components/plugin-post-publish-panel/test/__snapshots__/index.js.snap +1 -0
  317. package/src/components/post-card-panel/index.js +1 -1
  318. package/src/components/post-publish-button/index.js +6 -3
  319. package/src/components/post-publish-button/test/index.js +13 -0
  320. package/src/components/post-publish-panel/postpublish.js +0 -1
  321. package/src/components/post-publish-panel/test/__snapshots__/index.js.snap +7 -2
  322. package/src/components/post-revisions-preview/diff-markers.js +0 -1
  323. package/src/components/post-revisions-timeline/index.js +186 -0
  324. package/src/components/post-revisions-timeline/style.scss +43 -0
  325. package/src/components/post-saved-state/index.js +23 -26
  326. package/src/components/post-saved-state/test/__snapshots__/index.js.snap +1 -0
  327. package/src/components/post-saved-state/test/index.js +18 -0
  328. package/src/components/post-status/index.js +0 -1
  329. package/src/components/post-taxonomies/flat-term-selector.js +4 -7
  330. package/src/components/post-taxonomies/hierarchical-term-selector.js +0 -1
  331. package/src/components/post-template/create-new-template-modal.js +0 -1
  332. package/src/components/post-text-editor/index.js +65 -0
  333. package/src/components/post-text-editor/test/utils.js +210 -0
  334. package/src/components/post-text-editor/utils.js +204 -0
  335. package/src/components/post-type-support-check/test/index.js +11 -0
  336. package/src/components/post-url/index.js +1 -1
  337. package/src/components/post-view-link/index.js +1 -1
  338. package/src/components/post-view-link/test/index.js +71 -0
  339. package/src/components/post-visibility/index.js +0 -1
  340. package/src/components/provider/disable-non-page-content-blocks.js +23 -6
  341. package/src/components/provider/index.js +2 -1
  342. package/src/components/provider/navigation-block-editing-mode.js +10 -4
  343. package/src/components/provider/use-block-editor-settings.js +3 -1
  344. package/src/components/resizable-editor/resize-handle.js +0 -1
  345. package/src/components/revision-diff-panel/index.js +8 -2
  346. package/src/components/revision-fields-diff/index.js +12 -1
  347. package/src/components/sidebar/dataform-post-summary.js +291 -36
  348. package/src/components/sidebar/index.js +2 -12
  349. package/src/components/sidebar/post-revision-summary.js +8 -15
  350. package/src/components/sidebar/post-summary.js +12 -10
  351. package/src/components/style-book/index.js +1 -1
  352. package/src/components/template-actions-panel/block-theme-content.js +0 -1
  353. package/src/components/template-actions-panel/index.js +0 -15
  354. package/src/dataviews/fields/revisions/index.tsx +28 -0
  355. package/src/dataviews/fields/revisions/revisions-view.tsx +59 -0
  356. package/src/dataviews/store/private-actions.ts +35 -7
  357. package/src/store/private-actions.js +2 -2
  358. package/src/store/private-selectors.js +11 -1
  359. package/src/store/test/actions.js +2 -2
  360. package/src/store/test/private-selectors.js +69 -0
  361. package/src/style.scss +1 -1
  362. package/build/components/post-revisions-panel/index.cjs +0 -173
  363. package/build/components/post-revisions-panel/index.cjs.map +0 -7
  364. package/build/components/revision-author-panel/index.cjs.map +0 -7
  365. package/build/components/revision-created-panel/index.cjs +0 -47
  366. package/build/components/revision-created-panel/index.cjs.map +0 -7
  367. package/build-module/components/post-revisions-panel/index.mjs +0 -148
  368. package/build-module/components/post-revisions-panel/index.mjs.map +0 -7
  369. package/build-module/components/revision-author-panel/index.mjs +0 -28
  370. package/build-module/components/revision-author-panel/index.mjs.map +0 -7
  371. package/build-module/components/revision-created-panel/index.mjs +0 -26
  372. package/build-module/components/revision-created-panel/index.mjs.map +0 -7
  373. package/build-types/components/collab-sidebar/add-comment.d.ts +0 -6
  374. package/build-types/components/collab-sidebar/add-comment.d.ts.map +0 -1
  375. package/build-types/components/collab-sidebar/comment-author-info.d.ts +0 -8
  376. package/build-types/components/collab-sidebar/comment-author-info.d.ts.map +0 -1
  377. package/build-types/components/collab-sidebar/comment-form.d.ts +0 -9
  378. package/build-types/components/collab-sidebar/comment-form.d.ts.map +0 -1
  379. package/build-types/components/collab-sidebar/comment-indicator-toolbar.d.ts +0 -6
  380. package/build-types/components/collab-sidebar/comment-indicator-toolbar.d.ts.map +0 -1
  381. package/build-types/components/collab-sidebar/comment-menu-item.d.ts +0 -6
  382. package/build-types/components/collab-sidebar/comment-menu-item.d.ts.map +0 -1
  383. package/build-types/components/collab-sidebar/comments.d.ts +0 -10
  384. package/build-types/components/collab-sidebar/comments.d.ts.map +0 -1
  385. package/build-types/components/global-styles-provider/index.d.ts +0 -16
  386. package/build-types/components/global-styles-provider/index.d.ts.map +0 -1
  387. package/build-types/components/media/index.d.ts +0 -3
  388. package/build-types/components/media/index.d.ts.map +0 -1
  389. package/build-types/components/media/metadata-panel.d.ts +0 -12
  390. package/build-types/components/media/metadata-panel.d.ts.map +0 -1
  391. package/build-types/components/media/preview.d.ts +0 -9
  392. package/build-types/components/media/preview.d.ts.map +0 -1
  393. package/build-types/components/post-revisions-panel/index.d.ts +0 -2
  394. package/build-types/components/post-revisions-panel/index.d.ts.map +0 -1
  395. package/build-types/components/revision-author-panel/index.d.ts +0 -2
  396. package/build-types/components/revision-author-panel/index.d.ts.map +0 -1
  397. package/build-types/components/revision-created-panel/index.d.ts +0 -2
  398. package/build-types/components/revision-created-panel/index.d.ts.map +0 -1
  399. package/src/components/editor-help/images/add-dark.png +0 -0
  400. package/src/components/editor-help/images/add-dark@2x.png +0 -0
  401. package/src/components/editor-help/images/add-dark@3x.png +0 -0
  402. package/src/components/editor-help/images/add-light.png +0 -0
  403. package/src/components/editor-help/images/add-light@2x.png +0 -0
  404. package/src/components/editor-help/images/add-light@3x.png +0 -0
  405. package/src/components/editor-help/images/block-layout-collage.png +0 -0
  406. package/src/components/editor-help/images/block-layout-collage@2x.png +0 -0
  407. package/src/components/editor-help/images/block-layout-collage@3x.png +0 -0
  408. package/src/components/editor-help/images/build-layouts-dark.png +0 -0
  409. package/src/components/editor-help/images/build-layouts-dark@2x.png +0 -0
  410. package/src/components/editor-help/images/build-layouts-dark@3x.png +0 -0
  411. package/src/components/editor-help/images/build-layouts-light.png +0 -0
  412. package/src/components/editor-help/images/build-layouts-light@2x.png +0 -0
  413. package/src/components/editor-help/images/build-layouts-light@3x.png +0 -0
  414. package/src/components/editor-help/images/drag-and-drop-dark.png +0 -0
  415. package/src/components/editor-help/images/drag-and-drop-dark@2x.png +0 -0
  416. package/src/components/editor-help/images/drag-and-drop-dark@3x.png +0 -0
  417. package/src/components/editor-help/images/drag-and-drop-light.png +0 -0
  418. package/src/components/editor-help/images/drag-and-drop-light@2x.png +0 -0
  419. package/src/components/editor-help/images/drag-and-drop-light@3x.png +0 -0
  420. package/src/components/editor-help/images/edit-media-dark.png +0 -0
  421. package/src/components/editor-help/images/edit-media-dark@2x.png +0 -0
  422. package/src/components/editor-help/images/edit-media-dark@3x.png +0 -0
  423. package/src/components/editor-help/images/edit-media-light.png +0 -0
  424. package/src/components/editor-help/images/edit-media-light@2x.png +0 -0
  425. package/src/components/editor-help/images/edit-media-light@3x.png +0 -0
  426. package/src/components/editor-help/images/embed-media-dark.png +0 -0
  427. package/src/components/editor-help/images/embed-media-dark@2x.png +0 -0
  428. package/src/components/editor-help/images/embed-media-dark@3x.png +0 -0
  429. package/src/components/editor-help/images/embed-media-light.png +0 -0
  430. package/src/components/editor-help/images/embed-media-light@2x.png +0 -0
  431. package/src/components/editor-help/images/embed-media-light@3x.png +0 -0
  432. package/src/components/editor-help/images/move-dark.png +0 -0
  433. package/src/components/editor-help/images/move-dark@2x.png +0 -0
  434. package/src/components/editor-help/images/move-dark@3x.png +0 -0
  435. package/src/components/editor-help/images/move-light.png +0 -0
  436. package/src/components/editor-help/images/move-light@2x.png +0 -0
  437. package/src/components/editor-help/images/move-light@3x.png +0 -0
  438. package/src/components/editor-help/images/options-dark.png +0 -0
  439. package/src/components/editor-help/images/options-dark@2x.png +0 -0
  440. package/src/components/editor-help/images/options-dark@3x.png +0 -0
  441. package/src/components/editor-help/images/options-light.png +0 -0
  442. package/src/components/editor-help/images/options-light@2x.png +0 -0
  443. package/src/components/editor-help/images/options-light@3x.png +0 -0
  444. package/src/components/editor-help/images/rich-text-dark.png +0 -0
  445. package/src/components/editor-help/images/rich-text-dark@2x.png +0 -0
  446. package/src/components/editor-help/images/rich-text-dark@3x.png +0 -0
  447. package/src/components/editor-help/images/rich-text-light.png +0 -0
  448. package/src/components/editor-help/images/rich-text-light@2x.png +0 -0
  449. package/src/components/editor-help/images/rich-text-light@3x.png +0 -0
  450. package/src/components/editor-help/images/settings-dark.png +0 -0
  451. package/src/components/editor-help/images/settings-dark@2x.png +0 -0
  452. package/src/components/editor-help/images/settings-dark@3x.png +0 -0
  453. package/src/components/editor-help/images/settings-light.png +0 -0
  454. package/src/components/editor-help/images/settings-light@2x.png +0 -0
  455. package/src/components/editor-help/images/settings-light@3x.png +0 -0
  456. package/src/components/editor-help/style.scss +0 -123
  457. package/src/components/post-revisions-panel/index.js +0 -161
  458. package/src/components/post-revisions-panel/style.scss +0 -16
  459. package/src/components/revision-author-panel/index.js +0 -36
  460. package/src/components/revision-created-panel/index.js +0 -36
@@ -71,6 +71,24 @@ describe( 'PostSavedState', () => {
71
71
  expect( screen.getByRole( 'button' ) ).toMatchSnapshot();
72
72
  } );
73
73
 
74
+ it( 'returns a disabled button while a non-post entity is being saved', () => {
75
+ useSelect.mockImplementation( () => ( {
76
+ isDirty: true,
77
+ isNew: false,
78
+ isSaveable: true,
79
+ isSaving: false,
80
+ isSavingNonPostEntityChanges: true,
81
+ postStatus: 'draft',
82
+ } ) );
83
+
84
+ render( <PostSavedState /> );
85
+
86
+ expect( screen.getByRole( 'button' ) ).toHaveAttribute(
87
+ 'aria-disabled',
88
+ 'true'
89
+ );
90
+ } );
91
+
74
92
  it( 'should return Saved text if not new and not dirty', () => {
75
93
  useSelect.mockImplementation( () => ( {
76
94
  isDirty: false,
@@ -246,7 +246,6 @@ export default function PostStatus() {
246
246
  ) }
247
247
  type="text"
248
248
  id={ passwordInputId }
249
- __next40pxDefaultSize
250
249
  maxLength={ 255 }
251
250
  />
252
251
  </div>
@@ -3,11 +3,8 @@
3
3
  */
4
4
  import { __, _x, sprintf } from '@wordpress/i18n';
5
5
  import { useEffect, useMemo, useState } from '@wordpress/element';
6
- import {
7
- FormTokenField,
8
- withFilters,
9
- __experimentalVStack as VStack,
10
- } from '@wordpress/components';
6
+ import { FormTokenField, withFilters } from '@wordpress/components';
7
+ import { Stack } from '@wordpress/ui';
11
8
  import { useSelect, useDispatch } from '@wordpress/data';
12
9
  import { store as coreStore } from '@wordpress/core-data';
13
10
  import { useDebounce } from '@wordpress/compose';
@@ -280,7 +277,7 @@ export function FlatTermSelector( { slug } ) {
280
277
  );
281
278
 
282
279
  return (
283
- <VStack spacing={ 4 }>
280
+ <Stack direction="column" gap="lg">
284
281
  <FormTokenField
285
282
  __next40pxDefaultSize
286
283
  value={ values }
@@ -296,7 +293,7 @@ export function FlatTermSelector( { slug } ) {
296
293
  } }
297
294
  />
298
295
  <MostUsedTerms taxonomy={ taxonomy } onSelect={ appendTerm } />
299
- </VStack>
296
+ </Stack>
300
297
  );
301
298
  }
302
299
 
@@ -462,7 +462,6 @@ export function HierarchicalTermSelector( { slug } ) {
462
462
  <form onSubmit={ onAddTerm }>
463
463
  <Flex direction="column" gap="4">
464
464
  <TextControl
465
- __next40pxDefaultSize
466
465
  className="editor-post-taxonomies__hierarchical-terms-input"
467
466
  label={ newTermLabel }
468
467
  value={ formName }
@@ -121,7 +121,6 @@ export default function CreateNewTemplateModal( { onClose } ) {
121
121
  <form onSubmit={ submit }>
122
122
  <VStack spacing="3">
123
123
  <TextControl
124
- __next40pxDefaultSize
125
124
  label={ __( 'Name' ) }
126
125
  value={ title }
127
126
  onChange={ setTitle }
@@ -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.js';
5
+ import { diffLines } from 'diff/lib/diff/line.js';
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
  };