@wordpress/editor 14.40.2-next.v.202602241322.0 → 14.40.2

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 (464) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/build/components/collab-sidebar/index.cjs +7 -4
  3. package/build/components/collab-sidebar/index.cjs.map +2 -2
  4. package/build/components/collab-sidebar/utils.cjs +13 -15
  5. package/build/components/collab-sidebar/utils.cjs.map +2 -2
  6. package/build/components/collaborators-overlay/avatar-iframe-styles.cjs +141 -0
  7. package/build/components/collaborators-overlay/avatar-iframe-styles.cjs.map +7 -0
  8. package/build/components/collaborators-overlay/collaborator-styles.cjs +38 -2
  9. package/build/components/collaborators-overlay/collaborator-styles.cjs.map +2 -2
  10. package/build/components/collaborators-overlay/compute-selection.cjs +185 -0
  11. package/build/components/collaborators-overlay/compute-selection.cjs.map +7 -0
  12. package/build/components/collaborators-overlay/cursor-dom-utils.cjs +243 -0
  13. package/build/components/collaborators-overlay/cursor-dom-utils.cjs.map +7 -0
  14. package/build/components/collaborators-overlay/cursor-registry.cjs +86 -0
  15. package/build/components/collaborators-overlay/cursor-registry.cjs.map +7 -0
  16. package/build/components/collaborators-overlay/index.cjs +7 -2
  17. package/build/components/collaborators-overlay/index.cjs.map +2 -2
  18. package/build/components/collaborators-overlay/overlay-iframe-styles.cjs +148 -0
  19. package/build/components/collaborators-overlay/overlay-iframe-styles.cjs.map +7 -0
  20. package/build/components/collaborators-overlay/overlay.cjs +146 -236
  21. package/build/components/collaborators-overlay/overlay.cjs.map +3 -3
  22. package/build/components/collaborators-overlay/timing-utils.cjs +46 -0
  23. package/build/components/collaborators-overlay/timing-utils.cjs.map +7 -0
  24. package/build/components/collaborators-overlay/use-block-highlighting.cjs +91 -42
  25. package/build/components/collaborators-overlay/use-block-highlighting.cjs.map +2 -2
  26. package/build/components/collaborators-overlay/use-debounced-recompute.cjs +49 -0
  27. package/build/components/collaborators-overlay/use-debounced-recompute.cjs.map +7 -0
  28. package/build/components/collaborators-overlay/use-render-cursors.cjs +82 -172
  29. package/build/components/collaborators-overlay/use-render-cursors.cjs.map +3 -3
  30. package/build/components/collaborators-presence/avatar/component.cjs +121 -0
  31. package/build/components/collaborators-presence/avatar/component.cjs.map +7 -0
  32. package/build/components/collaborators-presence/avatar/index.cjs +37 -0
  33. package/build/components/collaborators-presence/avatar/index.cjs.map +7 -0
  34. package/build/components/collaborators-presence/avatar/types.cjs +19 -0
  35. package/build/components/collaborators-presence/avatar/types.cjs.map +7 -0
  36. package/build/components/collaborators-presence/avatar/use-image-loading-status.cjs +44 -0
  37. package/build/components/collaborators-presence/avatar/use-image-loading-status.cjs.map +7 -0
  38. package/build/components/collaborators-presence/avatar-group/component.cjs +78 -0
  39. package/build/components/collaborators-presence/avatar-group/component.cjs.map +7 -0
  40. package/build/components/collaborators-presence/avatar-group/index.cjs +37 -0
  41. package/build/components/collaborators-presence/avatar-group/index.cjs.map +7 -0
  42. package/build/components/collaborators-presence/avatar-group/types.cjs +19 -0
  43. package/build/components/collaborators-presence/avatar-group/types.cjs.map +7 -0
  44. package/build/components/collaborators-presence/index.cjs +66 -19
  45. package/build/components/collaborators-presence/index.cjs.map +3 -3
  46. package/build/components/collaborators-presence/list.cjs +60 -38
  47. package/build/components/collaborators-presence/list.cjs.map +3 -3
  48. package/build/components/collaborators-presence/use-collaborator-notifications.cjs +149 -0
  49. package/build/components/collaborators-presence/use-collaborator-notifications.cjs.map +7 -0
  50. package/build/components/editor-interface/index.cjs +11 -6
  51. package/build/components/editor-interface/index.cjs.map +2 -2
  52. package/build/components/inserter-sidebar/index.cjs +2 -1
  53. package/build/components/inserter-sidebar/index.cjs.map +2 -2
  54. package/build/components/post-last-revision/index.cjs +27 -6
  55. package/build/components/post-last-revision/index.cjs.map +2 -2
  56. package/build/components/post-locked-modal/index.cjs +49 -17
  57. package/build/components/post-locked-modal/index.cjs.map +3 -3
  58. package/build/components/post-revisions-preview/block-diff.cjs +130 -34
  59. package/build/components/post-revisions-preview/block-diff.cjs.map +2 -2
  60. package/build/components/post-revisions-preview/diff-markers.cjs +6 -5
  61. package/build/components/post-revisions-preview/diff-markers.cjs.map +2 -2
  62. package/build/components/post-revisions-preview/revisions-canvas.cjs +16 -60
  63. package/build/components/post-revisions-preview/revisions-canvas.cjs.map +3 -3
  64. package/build/components/post-revisions-preview/revisions-header.cjs +33 -26
  65. package/build/components/post-revisions-preview/revisions-header.cjs.map +3 -3
  66. package/build/components/post-revisions-preview/revisions-slider.cjs +104 -39
  67. package/build/components/post-revisions-preview/revisions-slider.cjs.map +3 -3
  68. package/build/components/preferences-modal/index.cjs +36 -4
  69. package/build/components/preferences-modal/index.cjs.map +2 -2
  70. package/build/components/provider/disable-non-page-content-blocks.cjs +31 -28
  71. package/build/components/provider/disable-non-page-content-blocks.cjs.map +3 -3
  72. package/build/components/provider/index.cjs +17 -5
  73. package/build/components/provider/index.cjs.map +2 -2
  74. package/build/components/provider/use-block-editor-settings.cjs +20 -4
  75. package/build/components/provider/use-block-editor-settings.cjs.map +3 -3
  76. package/build/components/provider/{use-post-content-blocks.cjs → use-post-content-block-types.cjs} +8 -19
  77. package/build/components/provider/use-post-content-block-types.cjs.map +7 -0
  78. package/build/components/provider/use-revision-blocks.cjs +106 -0
  79. package/build/components/provider/use-revision-blocks.cjs.map +7 -0
  80. package/build/components/revision-block-diff/index.cjs +61 -0
  81. package/build/components/revision-block-diff/index.cjs.map +7 -0
  82. package/build/components/revision-diff-panel/index.cjs +68 -0
  83. package/build/components/revision-diff-panel/index.cjs.map +7 -0
  84. package/build/components/revision-fields-diff/index.cjs +96 -0
  85. package/build/components/revision-fields-diff/index.cjs.map +7 -0
  86. package/build/components/sidebar/header.cjs +1 -1
  87. package/build/components/sidebar/header.cjs.map +2 -2
  88. package/build/components/sidebar/index.cjs +7 -1
  89. package/build/components/sidebar/index.cjs.map +3 -3
  90. package/build/components/style-book/index.cjs +4 -3
  91. package/build/components/style-book/index.cjs.map +2 -2
  92. package/build/components/sync-connection-error-modal/index.cjs +187 -0
  93. package/build/components/sync-connection-error-modal/index.cjs.map +7 -0
  94. package/build/components/sync-connection-error-modal/use-retry-countdown.cjs +84 -0
  95. package/build/components/sync-connection-error-modal/use-retry-countdown.cjs.map +7 -0
  96. package/build/components/template-content-panel/index.cjs +35 -31
  97. package/build/components/template-content-panel/index.cjs.map +3 -3
  98. package/build/components/template-part-menu-items/convert-to-regular.cjs +54 -11
  99. package/build/components/template-part-menu-items/convert-to-regular.cjs.map +3 -3
  100. package/build/components/visual-editor/index.cjs +6 -15
  101. package/build/components/visual-editor/index.cjs.map +2 -2
  102. package/build/store/private-actions.cjs +46 -2
  103. package/build/store/private-actions.cjs.map +2 -2
  104. package/build/store/private-selectors.cjs +156 -21
  105. package/build/store/private-selectors.cjs.map +2 -2
  106. package/build/store/reducer.cjs +27 -0
  107. package/build/store/reducer.cjs.map +2 -2
  108. package/build/store/selectors.cjs +0 -14
  109. package/build/store/selectors.cjs.map +2 -2
  110. package/build/utils/media-finalize/index.cjs +43 -0
  111. package/build/utils/media-finalize/index.cjs.map +7 -0
  112. package/build/utils/media-upload/on-success.cjs +46 -0
  113. package/build/utils/media-upload/on-success.cjs.map +7 -0
  114. package/build/utils/sync-error-messages.cjs +32 -15
  115. package/build/utils/sync-error-messages.cjs.map +3 -3
  116. package/build-module/components/collab-sidebar/index.mjs +7 -4
  117. package/build-module/components/collab-sidebar/index.mjs.map +2 -2
  118. package/build-module/components/collab-sidebar/utils.mjs +13 -15
  119. package/build-module/components/collab-sidebar/utils.mjs.map +2 -2
  120. package/build-module/components/collaborators-overlay/avatar-iframe-styles.mjs +128 -0
  121. package/build-module/components/collaborators-overlay/avatar-iframe-styles.mjs.map +7 -0
  122. package/build-module/components/collaborators-overlay/collaborator-styles.mjs +25 -1
  123. package/build-module/components/collaborators-overlay/collaborator-styles.mjs.map +2 -2
  124. package/build-module/components/collaborators-overlay/compute-selection.mjs +166 -0
  125. package/build-module/components/collaborators-overlay/compute-selection.mjs.map +7 -0
  126. package/build-module/components/collaborators-overlay/cursor-dom-utils.mjs +213 -0
  127. package/build-module/components/collaborators-overlay/cursor-dom-utils.mjs.map +7 -0
  128. package/build-module/components/collaborators-overlay/cursor-registry.mjs +61 -0
  129. package/build-module/components/collaborators-overlay/cursor-registry.mjs.map +7 -0
  130. package/build-module/components/collaborators-overlay/index.mjs +7 -2
  131. package/build-module/components/collaborators-overlay/index.mjs.map +2 -2
  132. package/build-module/components/collaborators-overlay/overlay-iframe-styles.mjs +130 -0
  133. package/build-module/components/collaborators-overlay/overlay-iframe-styles.mjs.map +7 -0
  134. package/build-module/components/collaborators-overlay/overlay.mjs +137 -237
  135. package/build-module/components/collaborators-overlay/overlay.mjs.map +2 -2
  136. package/build-module/components/collaborators-overlay/timing-utils.mjs +21 -0
  137. package/build-module/components/collaborators-overlay/timing-utils.mjs.map +7 -0
  138. package/build-module/components/collaborators-overlay/use-block-highlighting.mjs +93 -45
  139. package/build-module/components/collaborators-overlay/use-block-highlighting.mjs.map +2 -2
  140. package/build-module/components/collaborators-overlay/use-debounced-recompute.mjs +24 -0
  141. package/build-module/components/collaborators-overlay/use-debounced-recompute.mjs.map +7 -0
  142. package/build-module/components/collaborators-overlay/use-render-cursors.mjs +83 -176
  143. package/build-module/components/collaborators-overlay/use-render-cursors.mjs.map +2 -2
  144. package/build-module/components/collaborators-presence/avatar/component.mjs +90 -0
  145. package/build-module/components/collaborators-presence/avatar/component.mjs.map +7 -0
  146. package/build-module/components/collaborators-presence/avatar/index.mjs +6 -0
  147. package/build-module/components/collaborators-presence/avatar/index.mjs.map +7 -0
  148. package/build-module/components/collaborators-presence/avatar/types.mjs +1 -0
  149. package/build-module/components/collaborators-presence/avatar/types.mjs.map +7 -0
  150. package/build-module/components/collaborators-presence/avatar/use-image-loading-status.mjs +19 -0
  151. package/build-module/components/collaborators-presence/avatar/use-image-loading-status.mjs.map +7 -0
  152. package/build-module/components/collaborators-presence/avatar-group/component.mjs +47 -0
  153. package/build-module/components/collaborators-presence/avatar-group/component.mjs.map +7 -0
  154. package/build-module/components/collaborators-presence/avatar-group/index.mjs +6 -0
  155. package/build-module/components/collaborators-presence/avatar-group/index.mjs.map +7 -0
  156. package/build-module/components/collaborators-presence/avatar-group/types.mjs +1 -0
  157. package/build-module/components/collaborators-presence/avatar-group/types.mjs.map +7 -0
  158. package/build-module/components/collaborators-presence/index.mjs +57 -23
  159. package/build-module/components/collaborators-presence/index.mjs.map +2 -2
  160. package/build-module/components/collaborators-presence/list.mjs +52 -44
  161. package/build-module/components/collaborators-presence/list.mjs.map +2 -2
  162. package/build-module/components/collaborators-presence/use-collaborator-notifications.mjs +126 -0
  163. package/build-module/components/collaborators-presence/use-collaborator-notifications.mjs.map +7 -0
  164. package/build-module/components/editor-interface/index.mjs +12 -7
  165. package/build-module/components/editor-interface/index.mjs.map +2 -2
  166. package/build-module/components/inserter-sidebar/index.mjs +2 -1
  167. package/build-module/components/inserter-sidebar/index.mjs.map +2 -2
  168. package/build-module/components/post-last-revision/index.mjs +27 -6
  169. package/build-module/components/post-last-revision/index.mjs.map +2 -2
  170. package/build-module/components/post-locked-modal/index.mjs +49 -17
  171. package/build-module/components/post-locked-modal/index.mjs.map +2 -2
  172. package/build-module/components/post-revisions-preview/block-diff.mjs +130 -34
  173. package/build-module/components/post-revisions-preview/block-diff.mjs.map +2 -2
  174. package/build-module/components/post-revisions-preview/diff-markers.mjs +6 -5
  175. package/build-module/components/post-revisions-preview/diff-markers.mjs.map +2 -2
  176. package/build-module/components/post-revisions-preview/revisions-canvas.mjs +18 -65
  177. package/build-module/components/post-revisions-preview/revisions-canvas.mjs.map +2 -2
  178. package/build-module/components/post-revisions-preview/revisions-header.mjs +36 -33
  179. package/build-module/components/post-revisions-preview/revisions-header.mjs.map +2 -2
  180. package/build-module/components/post-revisions-preview/revisions-slider.mjs +112 -42
  181. package/build-module/components/post-revisions-preview/revisions-slider.mjs.map +2 -2
  182. package/build-module/components/preferences-modal/index.mjs +36 -4
  183. package/build-module/components/preferences-modal/index.mjs.map +2 -2
  184. package/build-module/components/provider/disable-non-page-content-blocks.mjs +31 -28
  185. package/build-module/components/provider/disable-non-page-content-blocks.mjs.map +2 -2
  186. package/build-module/components/provider/index.mjs +17 -5
  187. package/build-module/components/provider/index.mjs.map +2 -2
  188. package/build-module/components/provider/use-block-editor-settings.mjs +20 -4
  189. package/build-module/components/provider/use-block-editor-settings.mjs.map +2 -2
  190. package/build-module/components/provider/use-post-content-block-types.mjs +23 -0
  191. package/build-module/components/provider/use-post-content-block-types.mjs.map +7 -0
  192. package/build-module/components/provider/use-revision-blocks.mjs +81 -0
  193. package/build-module/components/provider/use-revision-blocks.mjs.map +7 -0
  194. package/build-module/components/revision-block-diff/index.mjs +30 -0
  195. package/build-module/components/revision-block-diff/index.mjs.map +7 -0
  196. package/build-module/components/revision-diff-panel/index.mjs +37 -0
  197. package/build-module/components/revision-diff-panel/index.mjs.map +7 -0
  198. package/build-module/components/revision-fields-diff/index.mjs +65 -0
  199. package/build-module/components/revision-fields-diff/index.mjs.map +7 -0
  200. package/build-module/components/sidebar/header.mjs +1 -1
  201. package/build-module/components/sidebar/header.mjs.map +2 -2
  202. package/build-module/components/sidebar/index.mjs +7 -1
  203. package/build-module/components/sidebar/index.mjs.map +2 -2
  204. package/build-module/components/style-book/index.mjs +4 -3
  205. package/build-module/components/style-book/index.mjs.map +2 -2
  206. package/build-module/components/sync-connection-error-modal/index.mjs +170 -0
  207. package/build-module/components/sync-connection-error-modal/index.mjs.map +7 -0
  208. package/build-module/components/sync-connection-error-modal/use-retry-countdown.mjs +59 -0
  209. package/build-module/components/sync-connection-error-modal/use-retry-countdown.mjs.map +7 -0
  210. package/build-module/components/template-content-panel/index.mjs +25 -31
  211. package/build-module/components/template-content-panel/index.mjs.map +2 -2
  212. package/build-module/components/template-part-menu-items/convert-to-regular.mjs +60 -14
  213. package/build-module/components/template-part-menu-items/convert-to-regular.mjs.map +2 -2
  214. package/build-module/components/visual-editor/index.mjs +6 -15
  215. package/build-module/components/visual-editor/index.mjs.map +2 -2
  216. package/build-module/store/private-actions.mjs +44 -2
  217. package/build-module/store/private-actions.mjs.map +2 -2
  218. package/build-module/store/private-selectors.mjs +155 -21
  219. package/build-module/store/private-selectors.mjs.map +2 -2
  220. package/build-module/store/reducer.mjs +25 -0
  221. package/build-module/store/reducer.mjs.map +2 -2
  222. package/build-module/store/selectors.mjs +0 -13
  223. package/build-module/store/selectors.mjs.map +2 -2
  224. package/build-module/utils/media-finalize/index.mjs +12 -0
  225. package/build-module/utils/media-finalize/index.mjs.map +7 -0
  226. package/build-module/utils/media-upload/on-success.mjs +25 -0
  227. package/build-module/utils/media-upload/on-success.mjs.map +7 -0
  228. package/build-module/utils/sync-error-messages.mjs +27 -15
  229. package/build-module/utils/sync-error-messages.mjs.map +3 -3
  230. package/build-style/style-rtl.css +388 -132
  231. package/build-style/style.css +388 -132
  232. package/build-types/components/autocompleters/link.d.ts +8 -0
  233. package/build-types/components/autocompleters/link.d.ts.map +1 -0
  234. package/build-types/components/collab-sidebar/add-note-menu-item.d.ts +5 -0
  235. package/build-types/components/collab-sidebar/add-note-menu-item.d.ts.map +1 -0
  236. package/build-types/components/collab-sidebar/add-note.d.ts +6 -0
  237. package/build-types/components/collab-sidebar/add-note.d.ts.map +1 -0
  238. package/build-types/components/collab-sidebar/board-store.d.ts +9 -0
  239. package/build-types/components/collab-sidebar/board-store.d.ts.map +1 -0
  240. package/build-types/components/collab-sidebar/floating-container.d.ts +8 -0
  241. package/build-types/components/collab-sidebar/floating-container.d.ts.map +1 -0
  242. package/build-types/components/collab-sidebar/index.d.ts.map +1 -1
  243. package/build-types/components/collab-sidebar/note-byline.d.ts +10 -0
  244. package/build-types/components/collab-sidebar/note-byline.d.ts.map +1 -0
  245. package/build-types/components/collab-sidebar/note-card.d.ts +8 -0
  246. package/build-types/components/collab-sidebar/note-card.d.ts.map +1 -0
  247. package/build-types/components/collab-sidebar/note-form.d.ts +7 -0
  248. package/build-types/components/collab-sidebar/note-form.d.ts.map +1 -0
  249. package/build-types/components/collab-sidebar/note-indicator-toolbar.d.ts +5 -0
  250. package/build-types/components/collab-sidebar/note-indicator-toolbar.d.ts.map +1 -0
  251. package/build-types/components/collab-sidebar/note-thread.d.ts +11 -0
  252. package/build-types/components/collab-sidebar/note-thread.d.ts.map +1 -0
  253. package/build-types/components/collab-sidebar/note.d.ts +9 -0
  254. package/build-types/components/collab-sidebar/note.d.ts.map +1 -0
  255. package/build-types/components/collab-sidebar/notes.d.ts +7 -0
  256. package/build-types/components/collab-sidebar/notes.d.ts.map +1 -0
  257. package/build-types/components/collab-sidebar/utils.d.ts.map +1 -1
  258. package/build-types/components/collaborators-overlay/avatar-iframe-styles.d.ts +11 -0
  259. package/build-types/components/collaborators-overlay/avatar-iframe-styles.d.ts.map +1 -0
  260. package/build-types/components/collaborators-overlay/collaborator-styles.d.ts +17 -2
  261. package/build-types/components/collaborators-overlay/collaborator-styles.d.ts.map +1 -1
  262. package/build-types/components/collaborators-overlay/compute-selection.d.ts +24 -0
  263. package/build-types/components/collaborators-overlay/compute-selection.d.ts.map +1 -0
  264. package/build-types/components/collaborators-overlay/cursor-dom-utils.d.ts +72 -0
  265. package/build-types/components/collaborators-overlay/cursor-dom-utils.d.ts.map +1 -0
  266. package/build-types/components/collaborators-overlay/cursor-registry.d.ts +36 -0
  267. package/build-types/components/collaborators-overlay/cursor-registry.d.ts.map +1 -0
  268. package/build-types/components/collaborators-overlay/index.d.ts +7 -4
  269. package/build-types/components/collaborators-overlay/index.d.ts.map +1 -1
  270. package/build-types/components/collaborators-overlay/overlay-iframe-styles.d.ts +6 -0
  271. package/build-types/components/collaborators-overlay/overlay-iframe-styles.d.ts.map +1 -0
  272. package/build-types/components/collaborators-overlay/overlay.d.ts +4 -1
  273. package/build-types/components/collaborators-overlay/overlay.d.ts.map +1 -1
  274. package/build-types/components/collaborators-overlay/timing-utils.d.ts +11 -0
  275. package/build-types/components/collaborators-overlay/timing-utils.d.ts.map +1 -0
  276. package/build-types/components/collaborators-overlay/use-block-highlighting.d.ts +21 -5
  277. package/build-types/components/collaborators-overlay/use-block-highlighting.d.ts.map +1 -1
  278. package/build-types/components/collaborators-overlay/use-debounced-recompute.d.ts +10 -0
  279. package/build-types/components/collaborators-overlay/use-debounced-recompute.d.ts.map +1 -0
  280. package/build-types/components/collaborators-overlay/use-render-cursors.d.ts +6 -1
  281. package/build-types/components/collaborators-overlay/use-render-cursors.d.ts.map +1 -1
  282. package/build-types/components/collaborators-presence/avatar/component.d.ts +7 -0
  283. package/build-types/components/collaborators-presence/avatar/component.d.ts.map +1 -0
  284. package/build-types/components/collaborators-presence/avatar/index.d.ts +3 -0
  285. package/build-types/components/collaborators-presence/avatar/index.d.ts.map +1 -0
  286. package/build-types/components/collaborators-presence/avatar/types.d.ts +66 -0
  287. package/build-types/components/collaborators-presence/avatar/types.d.ts.map +1 -0
  288. package/build-types/components/collaborators-presence/avatar/use-image-loading-status.d.ts +17 -0
  289. package/build-types/components/collaborators-presence/avatar/use-image-loading-status.d.ts.map +1 -0
  290. package/build-types/components/collaborators-presence/avatar-group/component.d.ts +7 -0
  291. package/build-types/components/collaborators-presence/avatar-group/component.d.ts.map +1 -0
  292. package/build-types/components/collaborators-presence/avatar-group/index.d.ts +3 -0
  293. package/build-types/components/collaborators-presence/avatar-group/index.d.ts.map +1 -0
  294. package/build-types/components/collaborators-presence/avatar-group/types.d.ts +14 -0
  295. package/build-types/components/collaborators-presence/avatar-group/types.d.ts.map +1 -0
  296. package/build-types/components/collaborators-presence/index.d.ts.map +1 -1
  297. package/build-types/components/collaborators-presence/list.d.ts +6 -2
  298. package/build-types/components/collaborators-presence/list.d.ts.map +1 -1
  299. package/build-types/components/collaborators-presence/use-collaborator-notifications.d.ts +9 -0
  300. package/build-types/components/collaborators-presence/use-collaborator-notifications.d.ts.map +1 -0
  301. package/build-types/components/editor-interface/index.d.ts.map +1 -1
  302. package/build-types/components/inserter-sidebar/index.d.ts.map +1 -1
  303. package/build-types/components/media/media-editor-modal.d.ts +15 -0
  304. package/build-types/components/media/media-editor-modal.d.ts.map +1 -0
  305. package/build-types/components/post-last-revision/index.d.ts.map +1 -1
  306. package/build-types/components/post-locked-modal/index.d.ts.map +1 -1
  307. package/build-types/components/post-revisions-panel/index.d.ts +2 -0
  308. package/build-types/components/post-revisions-panel/index.d.ts.map +1 -0
  309. package/build-types/components/post-revisions-preview/block-diff.d.ts.map +1 -1
  310. package/build-types/components/post-revisions-preview/diff-markers.d.ts.map +1 -1
  311. package/build-types/components/post-revisions-preview/revisions-canvas.d.ts +2 -5
  312. package/build-types/components/post-revisions-preview/revisions-canvas.d.ts.map +1 -1
  313. package/build-types/components/post-revisions-preview/revisions-header.d.ts.map +1 -1
  314. package/build-types/components/post-revisions-preview/revisions-slider.d.ts +1 -1
  315. package/build-types/components/post-revisions-preview/revisions-slider.d.ts.map +1 -1
  316. package/build-types/components/post-text-editor/utils.d.ts +29 -0
  317. package/build-types/components/post-text-editor/utils.d.ts.map +1 -0
  318. package/build-types/components/provider/disable-non-page-content-blocks.d.ts.map +1 -1
  319. package/build-types/components/provider/index.d.ts.map +1 -1
  320. package/build-types/components/provider/use-block-editor-settings.d.ts.map +1 -1
  321. package/build-types/components/provider/use-network-reconnect.d.ts +8 -0
  322. package/build-types/components/provider/use-network-reconnect.d.ts.map +1 -0
  323. package/build-types/components/provider/use-post-content-block-types.d.ts +9 -0
  324. package/build-types/components/provider/use-post-content-block-types.d.ts.map +1 -0
  325. package/build-types/components/provider/use-revision-blocks.d.ts +10 -0
  326. package/build-types/components/provider/use-revision-blocks.d.ts.map +1 -0
  327. package/build-types/components/revision-block-diff/index.d.ts +6 -0
  328. package/build-types/components/revision-block-diff/index.d.ts.map +1 -0
  329. package/build-types/components/revision-diff-panel/index.d.ts +14 -0
  330. package/build-types/components/revision-diff-panel/index.d.ts.map +1 -0
  331. package/build-types/components/revision-fields-diff/index.d.ts +6 -0
  332. package/build-types/components/revision-fields-diff/index.d.ts.map +1 -0
  333. package/build-types/components/sidebar/dataform-post-summary.d.ts +4 -0
  334. package/build-types/components/sidebar/dataform-post-summary.d.ts.map +1 -0
  335. package/build-types/components/sidebar/index.d.ts.map +1 -1
  336. package/build-types/components/sidebar/post-revision-summary.d.ts +2 -0
  337. package/build-types/components/sidebar/post-revision-summary.d.ts.map +1 -0
  338. package/build-types/components/style-book/index.d.ts +2 -1
  339. package/build-types/components/style-book/index.d.ts.map +1 -1
  340. package/build-types/components/sync-connection-error-modal/index.d.ts +8 -0
  341. package/build-types/components/sync-connection-error-modal/index.d.ts.map +1 -0
  342. package/build-types/components/sync-connection-error-modal/use-retry-countdown.d.ts +11 -0
  343. package/build-types/components/sync-connection-error-modal/use-retry-countdown.d.ts.map +1 -0
  344. package/build-types/components/template-actions-panel/block-theme-content.d.ts +2 -0
  345. package/build-types/components/template-actions-panel/block-theme-content.d.ts.map +1 -0
  346. package/build-types/components/template-actions-panel/classic-theme-content.d.ts +2 -0
  347. package/build-types/components/template-actions-panel/classic-theme-content.d.ts.map +1 -0
  348. package/build-types/components/template-actions-panel/index.d.ts +2 -0
  349. package/build-types/components/template-actions-panel/index.d.ts.map +1 -0
  350. package/build-types/components/template-content-panel/index.d.ts.map +1 -1
  351. package/build-types/components/template-part-menu-items/convert-to-regular.d.ts.map +1 -1
  352. package/build-types/components/upload-progress-snackbar/index.d.ts +19 -0
  353. package/build-types/components/upload-progress-snackbar/index.d.ts.map +1 -0
  354. package/build-types/components/upload-progress-snackbar/stories/index.story.d.ts +28 -0
  355. package/build-types/components/upload-progress-snackbar/stories/index.story.d.ts.map +1 -0
  356. package/build-types/components/upload-progress-snackbar/tracker.d.ts +41 -0
  357. package/build-types/components/upload-progress-snackbar/tracker.d.ts.map +1 -0
  358. package/build-types/components/visual-editor/index.d.ts.map +1 -1
  359. package/build-types/store/private-actions.d.ts +12 -0
  360. package/build-types/store/private-actions.d.ts.map +1 -1
  361. package/build-types/store/private-selectors.d.ts +45 -0
  362. package/build-types/store/private-selectors.d.ts.map +1 -1
  363. package/build-types/store/reducer.d.ts +21 -0
  364. package/build-types/store/reducer.d.ts.map +1 -1
  365. package/build-types/store/selectors.d.ts +0 -10
  366. package/build-types/store/selectors.d.ts.map +1 -1
  367. package/build-types/utils/media-delete/index.d.ts +2 -0
  368. package/build-types/utils/media-delete/index.d.ts.map +1 -0
  369. package/build-types/utils/media-finalize/index.d.ts +2 -0
  370. package/build-types/utils/media-finalize/index.d.ts.map +1 -0
  371. package/build-types/utils/media-upload/on-success.d.ts +9 -0
  372. package/build-types/utils/media-upload/on-success.d.ts.map +1 -0
  373. package/build-types/utils/sync-error-messages.d.ts +17 -3
  374. package/build-types/utils/sync-error-messages.d.ts.map +1 -1
  375. package/package.json +45 -44
  376. package/src/components/collab-sidebar/index.js +7 -4
  377. package/src/components/collab-sidebar/utils.js +9 -10
  378. package/src/components/collaborators-overlay/avatar-iframe-styles.ts +134 -0
  379. package/src/components/collaborators-overlay/collaborator-styles.ts +43 -2
  380. package/src/components/collaborators-overlay/compute-selection.ts +315 -0
  381. package/src/components/collaborators-overlay/cursor-dom-utils.ts +382 -0
  382. package/src/components/collaborators-overlay/cursor-registry.ts +96 -0
  383. package/src/components/collaborators-overlay/index.tsx +12 -4
  384. package/src/components/collaborators-overlay/overlay-iframe-styles.ts +131 -0
  385. package/src/components/collaborators-overlay/overlay.tsx +145 -229
  386. package/src/components/collaborators-overlay/timing-utils.ts +30 -0
  387. package/src/components/collaborators-overlay/use-block-highlighting.ts +152 -64
  388. package/src/components/collaborators-overlay/use-debounced-recompute.ts +32 -0
  389. package/src/components/collaborators-overlay/use-render-cursors.ts +120 -282
  390. package/src/components/collaborators-presence/avatar/component.tsx +123 -0
  391. package/src/components/collaborators-presence/avatar/index.ts +2 -0
  392. package/src/components/collaborators-presence/avatar/styles.scss +184 -0
  393. package/src/components/collaborators-presence/avatar/test/index.tsx +389 -0
  394. package/src/components/collaborators-presence/avatar/types.ts +66 -0
  395. package/src/components/collaborators-presence/avatar/use-image-loading-status.ts +36 -0
  396. package/src/components/collaborators-presence/avatar-group/component.tsx +55 -0
  397. package/src/components/collaborators-presence/avatar-group/index.ts +2 -0
  398. package/src/components/collaborators-presence/avatar-group/styles.scss +33 -0
  399. package/src/components/collaborators-presence/avatar-group/test/index.tsx +139 -0
  400. package/src/components/collaborators-presence/avatar-group/types.ts +13 -0
  401. package/src/components/collaborators-presence/index.tsx +43 -12
  402. package/src/components/collaborators-presence/list.tsx +68 -40
  403. package/src/components/collaborators-presence/styles/collaborators-list.scss +26 -19
  404. package/src/components/collaborators-presence/styles/collaborators-presence.scss +6 -2
  405. package/src/components/collaborators-presence/test/use-collaborator-notifications.ts +397 -0
  406. package/src/components/collaborators-presence/use-collaborator-notifications.ts +203 -0
  407. package/src/components/document-bar/style.scss +1 -1
  408. package/src/components/editor-interface/index.js +13 -6
  409. package/src/components/inserter-sidebar/index.js +4 -1
  410. package/src/components/post-last-revision/index.js +35 -6
  411. package/src/components/post-last-revision/style.scss +0 -3
  412. package/src/components/post-locked-modal/index.js +69 -25
  413. package/src/components/post-panel-row/style.scss +1 -0
  414. package/src/components/post-revisions-preview/block-diff.js +224 -61
  415. package/src/components/post-revisions-preview/diff-markers.js +15 -12
  416. package/src/components/post-revisions-preview/revisions-canvas.js +23 -86
  417. package/src/components/post-revisions-preview/revisions-header.js +35 -37
  418. package/src/components/post-revisions-preview/revisions-slider.js +138 -62
  419. package/src/components/post-revisions-preview/style.scss +3 -3
  420. package/src/components/post-revisions-preview/test/block-diff.js +202 -35
  421. package/src/components/preferences-modal/index.js +37 -7
  422. package/src/components/provider/disable-non-page-content-blocks.js +42 -40
  423. package/src/components/provider/index.js +20 -2
  424. package/src/components/provider/use-block-editor-settings.js +21 -1
  425. package/src/components/provider/use-post-content-block-types.js +30 -0
  426. package/src/components/provider/use-revision-blocks.js +105 -0
  427. package/src/components/revision-block-diff/index.js +39 -0
  428. package/src/components/revision-diff-panel/index.js +59 -0
  429. package/src/components/revision-diff-panel/style.scss +13 -0
  430. package/src/components/revision-fields-diff/index.js +91 -0
  431. package/src/components/sidebar/header.js +1 -1
  432. package/src/components/sidebar/index.js +4 -0
  433. package/src/components/style-book/index.js +4 -2
  434. package/src/components/sync-connection-error-modal/index.tsx +253 -0
  435. package/src/components/sync-connection-error-modal/style.scss +14 -0
  436. package/src/components/sync-connection-error-modal/use-retry-countdown.ts +93 -0
  437. package/src/components/template-content-panel/index.js +30 -38
  438. package/src/components/template-part-menu-items/convert-to-regular.js +74 -12
  439. package/src/components/visual-editor/index.js +6 -23
  440. package/src/store/private-actions.js +70 -1
  441. package/src/store/private-selectors.js +216 -28
  442. package/src/store/reducer.js +41 -0
  443. package/src/store/selectors.js +0 -19
  444. package/src/style.scss +4 -1
  445. package/src/utils/media-finalize/index.js +11 -0
  446. package/src/utils/media-finalize/test/index.js +34 -0
  447. package/src/utils/media-upload/on-success.js +34 -0
  448. package/src/utils/sync-error-messages.ts +72 -0
  449. package/src/utils/test/sync-error-messages.js +34 -0
  450. package/build/components/provider/use-post-content-blocks.cjs.map +0 -7
  451. package/build/components/sync-connection-modal/index.cjs +0 -130
  452. package/build/components/sync-connection-modal/index.cjs.map +0 -7
  453. package/build-module/components/provider/use-post-content-blocks.mjs +0 -34
  454. package/build-module/components/provider/use-post-content-blocks.mjs.map +0 -7
  455. package/build-module/components/sync-connection-modal/index.mjs +0 -114
  456. package/build-module/components/sync-connection-modal/index.mjs.map +0 -7
  457. package/build-types/components/provider/use-post-content-blocks.d.ts +0 -2
  458. package/build-types/components/provider/use-post-content-blocks.d.ts.map +0 -1
  459. package/build-types/components/sync-connection-modal/index.d.ts +0 -8
  460. package/build-types/components/sync-connection-modal/index.d.ts.map +0 -1
  461. package/src/components/provider/use-post-content-blocks.js +0 -42
  462. package/src/components/sync-connection-modal/index.js +0 -140
  463. package/src/components/sync-connection-modal/style.scss +0 -11
  464. package/src/utils/sync-error-messages.js +0 -53
@@ -0,0 +1,382 @@
1
+ export interface SelectionRect {
2
+ x: number;
3
+ y: number;
4
+ width: number;
5
+ height: number;
6
+ }
7
+
8
+ export interface CursorCoords {
9
+ x: number;
10
+ y: number;
11
+ height: number;
12
+ }
13
+
14
+ const MAX_NODE_OFFSET_COUNT = 500;
15
+
16
+ /**
17
+ * Given a selection, returns the coordinates of the cursor in the block.
18
+ *
19
+ * @param absolutePositionIndex - The absolute position index
20
+ * @param blockElement - The block element (or null if deleted)
21
+ * @param editorDocument - The editor document
22
+ * @param overlayRect - Pre-computed bounding rect of the overlay element
23
+ * @return The position of the cursor
24
+ */
25
+ export const getCursorPosition = (
26
+ absolutePositionIndex: number | null,
27
+ blockElement: HTMLElement | null,
28
+ editorDocument: Document,
29
+ overlayRect: DOMRect
30
+ ): CursorCoords | null => {
31
+ if ( absolutePositionIndex === null || ! blockElement ) {
32
+ return null;
33
+ }
34
+
35
+ return (
36
+ getOffsetPositionInBlock(
37
+ blockElement,
38
+ absolutePositionIndex,
39
+ editorDocument,
40
+ overlayRect
41
+ ) ?? null
42
+ );
43
+ };
44
+
45
+ /**
46
+ * Given a block element and a character offset, returns the coordinates for drawing a visual cursor in the block.
47
+ *
48
+ * @param blockElement - The block element
49
+ * @param charOffset - The character offset
50
+ * @param editorDocument - The editor document
51
+ * @param overlayRect - Pre-computed bounding rect of the overlay element
52
+ * @return The position of the cursor
53
+ */
54
+ const getOffsetPositionInBlock = (
55
+ blockElement: HTMLElement,
56
+ charOffset: number,
57
+ editorDocument: Document,
58
+ overlayRect: DOMRect
59
+ ) => {
60
+ const { node, offset } = findInnerBlockOffset(
61
+ blockElement,
62
+ charOffset,
63
+ editorDocument
64
+ );
65
+
66
+ const cursorRange = editorDocument.createRange();
67
+
68
+ try {
69
+ cursorRange.setStart( node, offset );
70
+ } catch ( error ) {
71
+ return null;
72
+ }
73
+
74
+ // Ensure the range only represents single point in the DOM.
75
+ cursorRange.collapse( true );
76
+
77
+ const cursorRect = cursorRange.getBoundingClientRect();
78
+ const blockRect = blockElement.getBoundingClientRect();
79
+
80
+ let cursorX = 0;
81
+ let cursorY = 0;
82
+
83
+ if (
84
+ cursorRect.x === 0 &&
85
+ cursorRect.y === 0 &&
86
+ cursorRect.width === 0 &&
87
+ cursorRect.height === 0
88
+ ) {
89
+ // This can happen for empty blocks.
90
+ cursorX = blockRect.left - overlayRect.left;
91
+ cursorY = blockRect.top - overlayRect.top;
92
+ } else {
93
+ cursorX = cursorRect.left - overlayRect.left;
94
+ cursorY = cursorRect.top - overlayRect.top;
95
+ }
96
+
97
+ let cursorHeight = cursorRect.height;
98
+ if ( cursorHeight === 0 ) {
99
+ const view = editorDocument.defaultView ?? window;
100
+ cursorHeight =
101
+ parseInt( view.getComputedStyle( blockElement ).lineHeight, 10 ) ||
102
+ blockRect.height;
103
+ }
104
+
105
+ return {
106
+ x: cursorX,
107
+ y: cursorY,
108
+ height: cursorHeight,
109
+ };
110
+ };
111
+
112
+ /**
113
+ * Computes selection highlight rectangles for a text range within a single block.
114
+ *
115
+ * @param blockElement - The block element
116
+ * @param startOffset - Start character offset within the block
117
+ * @param endOffset - End character offset within the block
118
+ * @param editorDocument - The editor document
119
+ * @param overlayRect - Pre-computed bounding rect of the overlay element
120
+ * @return Array of selection rectangles relative to the overlay, or null on failure
121
+ */
122
+ export const getSelectionRects = (
123
+ blockElement: HTMLElement,
124
+ startOffset: number,
125
+ endOffset: number,
126
+ editorDocument: Document,
127
+ overlayRect: DOMRect
128
+ ): SelectionRect[] | null => {
129
+ // Normalize direction.
130
+ let normalizedStart = startOffset;
131
+ let normalizedEnd = endOffset;
132
+ if ( normalizedStart > normalizedEnd ) {
133
+ [ normalizedStart, normalizedEnd ] = [ normalizedEnd, normalizedStart ];
134
+ }
135
+
136
+ const startPos = findInnerBlockOffset(
137
+ blockElement,
138
+ normalizedStart,
139
+ editorDocument
140
+ );
141
+ const endPos = findInnerBlockOffset(
142
+ blockElement,
143
+ normalizedEnd,
144
+ editorDocument
145
+ );
146
+
147
+ const range = editorDocument.createRange();
148
+ try {
149
+ range.setStart( startPos.node, startPos.offset );
150
+ range.setEnd( endPos.node, endPos.offset );
151
+ } catch {
152
+ return null;
153
+ }
154
+
155
+ const clientRects = range.getClientRects();
156
+ const rects: SelectionRect[] = [];
157
+
158
+ for ( const rect of clientRects ) {
159
+ if ( rect.width === 0 && rect.height === 0 ) {
160
+ continue;
161
+ }
162
+ const x = rect.left - overlayRect.left;
163
+ const y = rect.top - overlayRect.top;
164
+
165
+ // Range.getClientRects() can return duplicate rects at inline
166
+ // formatting boundaries (e.g. <em>, <strong>). Skip exact matches.
167
+ const isDuplicate = rects.some(
168
+ ( r ) =>
169
+ r.x === x &&
170
+ r.y === y &&
171
+ r.width === rect.width &&
172
+ r.height === rect.height
173
+ );
174
+ if ( isDuplicate ) {
175
+ continue;
176
+ }
177
+
178
+ rects.push( {
179
+ x,
180
+ y,
181
+ width: rect.width,
182
+ height: rect.height,
183
+ } );
184
+ }
185
+
186
+ return rects.length > 0 ? rects : null;
187
+ };
188
+
189
+ /**
190
+ * Computes selection highlight rectangles for the full content of a block.
191
+ * Used for intermediate blocks in a multi-block selection.
192
+ *
193
+ * @param blockElement - The block element
194
+ * @param editorDocument - The editor document
195
+ * @param overlayRect - Pre-computed bounding rect of the overlay element
196
+ * @return Array of selection rectangles relative to the overlay
197
+ */
198
+ export const getFullBlockSelectionRects = (
199
+ blockElement: HTMLElement,
200
+ editorDocument: Document,
201
+ overlayRect: DOMRect
202
+ ): SelectionRect[] => {
203
+ const range = editorDocument.createRange();
204
+ range.selectNodeContents( blockElement );
205
+ const clientRects = range.getClientRects();
206
+ const rects: SelectionRect[] = [];
207
+
208
+ for ( const rect of clientRects ) {
209
+ if ( rect.width === 0 && rect.height === 0 ) {
210
+ continue;
211
+ }
212
+ rects.push( {
213
+ x: rect.left - overlayRect.left,
214
+ y: rect.top - overlayRect.top,
215
+ width: rect.width,
216
+ height: rect.height,
217
+ } );
218
+ }
219
+
220
+ // Fallback: if getClientRects returned nothing, use the block's bounding rect.
221
+ if ( rects.length === 0 ) {
222
+ const blockRect = blockElement.getBoundingClientRect();
223
+ if ( blockRect.width > 0 && blockRect.height > 0 ) {
224
+ rects.push( {
225
+ x: blockRect.left - overlayRect.left,
226
+ y: blockRect.top - overlayRect.top,
227
+ width: blockRect.width,
228
+ height: blockRect.height,
229
+ } );
230
+ }
231
+ }
232
+
233
+ return rects;
234
+ };
235
+
236
+ /**
237
+ * Finds all block elements between two blocks in DOM order (exclusive of start and end).
238
+ *
239
+ * @param startBlockId - The clientId of the start block
240
+ * @param endBlockId - The clientId of the end block
241
+ * @param editorDocument - The editor document
242
+ * @return Array of intermediate block HTMLElements in document order
243
+ */
244
+ export const getBlocksBetween = (
245
+ startBlockId: string,
246
+ endBlockId: string,
247
+ editorDocument: Document
248
+ ): HTMLElement[] => {
249
+ const allBlocks =
250
+ editorDocument.querySelectorAll< HTMLElement >( '[data-block]' );
251
+
252
+ let startIndex = -1;
253
+ let endIndex = -1;
254
+
255
+ for ( let i = 0; i < allBlocks.length; i++ ) {
256
+ const blockId = allBlocks[ i ].getAttribute( 'data-block' );
257
+ if ( blockId === startBlockId ) {
258
+ startIndex = i;
259
+ }
260
+ if ( blockId === endBlockId ) {
261
+ endIndex = i;
262
+ }
263
+ }
264
+
265
+ if ( startIndex === -1 || endIndex === -1 ) {
266
+ return [];
267
+ }
268
+
269
+ // Normalize order.
270
+ if ( startIndex > endIndex ) {
271
+ [ startIndex, endIndex ] = [ endIndex, startIndex ];
272
+ }
273
+
274
+ const result: HTMLElement[] = [];
275
+ for ( let i = startIndex + 1; i < endIndex; i++ ) {
276
+ result.push( allBlocks[ i ] );
277
+ }
278
+ return result;
279
+ };
280
+
281
+ /**
282
+ * Given a block element and a character offset, returns an exact inner node and offset for use in a range.
283
+ *
284
+ * @param blockElement - The block element
285
+ * @param offset - The character offset
286
+ * @param editorDocument - The editor document
287
+ * @return The node and offset of the character at the offset
288
+ */
289
+ export const findInnerBlockOffset = (
290
+ blockElement: HTMLElement,
291
+ offset: number,
292
+ editorDocument: Document
293
+ ) => {
294
+ const treeWalker = editorDocument.createTreeWalker(
295
+ blockElement,
296
+ NodeFilter.SHOW_TEXT | NodeFilter.SHOW_ELEMENT // eslint-disable-line no-bitwise
297
+ );
298
+
299
+ let currentOffset = 0;
300
+ let lastTextNode: Node | null = null;
301
+
302
+ let node: Node | null = null;
303
+ let nodeCount = 1;
304
+
305
+ while ( ( node = treeWalker.nextNode() ) ) {
306
+ nodeCount++;
307
+
308
+ if ( nodeCount > MAX_NODE_OFFSET_COUNT ) {
309
+ // If we've walked too many nodes, return the last text node or the beginning of the block.
310
+ if ( lastTextNode ) {
311
+ return { node: lastTextNode, offset: 0 };
312
+ }
313
+ return { node: blockElement, offset: 0 };
314
+ }
315
+
316
+ const nodeLength = node.nodeValue?.length ?? 0;
317
+
318
+ if ( node.nodeType === Node.ELEMENT_NODE ) {
319
+ if ( node.nodeName === 'BR' ) {
320
+ // Treat <br> as a single "\n" character.
321
+
322
+ if ( currentOffset + 1 >= offset ) {
323
+ // If the <br> occurs right on the target offset, return the next text node.
324
+ const nodeAfterBr = treeWalker.nextNode();
325
+
326
+ if ( nodeAfterBr?.nodeType === Node.TEXT_NODE ) {
327
+ return { node: nodeAfterBr, offset: 0 };
328
+ } else if ( lastTextNode ) {
329
+ // If there's no text node after the <br>, return the end offset of the last text node.
330
+ return {
331
+ node: lastTextNode,
332
+ offset: lastTextNode.nodeValue?.length ?? 0,
333
+ };
334
+ }
335
+ // Just in case, if there's no last text node, return the beginning of the block.
336
+ return { node: blockElement, offset: 0 };
337
+ }
338
+
339
+ // The <br> is before the target offset. Count it as a single character.
340
+ currentOffset += 1;
341
+ continue;
342
+ } else {
343
+ // Skip other element types.
344
+ continue;
345
+ }
346
+ }
347
+
348
+ if ( nodeLength === 0 ) {
349
+ // Skip empty nodes.
350
+ continue;
351
+ }
352
+
353
+ if ( currentOffset + nodeLength >= offset ) {
354
+ // This node exceeds the target offset. Return the node and the position of the offset within it.
355
+ return { node, offset: offset - currentOffset };
356
+ }
357
+
358
+ currentOffset += nodeLength;
359
+
360
+ if ( node.nodeType === Node.TEXT_NODE ) {
361
+ lastTextNode = node;
362
+ }
363
+ }
364
+
365
+ if ( lastTextNode && lastTextNode.nodeValue?.length ) {
366
+ // We didn't reach the target offset. Return the last text node's last character.
367
+ return { node: lastTextNode, offset: lastTextNode.nodeValue.length };
368
+ }
369
+
370
+ // We didn't find any text nodes. Return the beginning of the block.
371
+ return { node: blockElement, offset: 0 };
372
+ };
373
+
374
+ /**
375
+ * Check if node `a` precedes node `b` in document order.
376
+ *
377
+ * @param a - First node.
378
+ * @param b - Second node.
379
+ * @return True if `a` comes before `b`.
380
+ */
381
+ export const isNodeBefore = ( a: Node, b: Node ): boolean =>
382
+ a.compareDocumentPosition( b ) === Node.DOCUMENT_POSITION_FOLLOWING;
@@ -0,0 +1,96 @@
1
+ interface ScrollToCursorOptions {
2
+ behavior?: ScrollBehavior;
3
+ block?: ScrollLogicalPosition;
4
+ inline?: ScrollLogicalPosition;
5
+ highlightDuration?: number;
6
+ }
7
+
8
+ /**
9
+ * Cursor Registry
10
+ * ===
11
+ * This registry stores references to cursor elements so that we can access them
12
+ * in different parts of the component tree. This would more ideally be solved
13
+ * with React context or state in the awareness store, but:
14
+ *
15
+ * 1. EditorPresence and BlockCanvasCover slot/fill break context propagation. We
16
+ * don't currently have a way to provide context to both the slot and fill.
17
+ * 2. Storing pointers to the cursor elements in the awareness store might be a
18
+ * better solution, but would require broader refactoring.
19
+ *
20
+ * For now, we create a single instance of this registry and pass it down to the
21
+ * components that need it. It's important that we create a single instance and
22
+ * not a new instance per component or render; use useState with a lazy
23
+ * initializer to accomplish this.
24
+ */
25
+
26
+ function highlightCursor( element: HTMLElement, duration: number ): void {
27
+ element.classList.add( 'collaborators-overlay-cursor-highlighted' );
28
+
29
+ setTimeout( () => {
30
+ element.classList.remove( 'collaborators-overlay-cursor-highlighted' );
31
+ }, duration );
32
+ }
33
+
34
+ export function createCursorRegistry() {
35
+ const cursorMap = new Map< number, HTMLElement >();
36
+
37
+ return {
38
+ /**
39
+ * Register a cursor element when it's created.
40
+ *
41
+ * @param clientId - The clientId of the cursor to register.
42
+ * @param element - The cursor element to register.
43
+ */
44
+ registerCursor( clientId: number, element: HTMLElement ): void {
45
+ cursorMap.set( clientId, element );
46
+ },
47
+
48
+ /**
49
+ * Unregister a cursor element when it's removed.
50
+ *
51
+ * @param clientId - The clientId of the cursor to unregister.
52
+ */
53
+ unregisterCursor( clientId: number ): void {
54
+ cursorMap.delete( clientId );
55
+ },
56
+
57
+ /**
58
+ * Scroll to a cursor by clientId.
59
+ *
60
+ * @param clientId - The clientId of the cursor to scroll to.
61
+ * @param options - The options for the scroll.
62
+ * @return true if cursor was found and scrolled to, false otherwise.
63
+ */
64
+ scrollToCursor(
65
+ clientId: number,
66
+ options?: ScrollToCursorOptions
67
+ ): boolean {
68
+ const cursorElement = cursorMap.get( clientId );
69
+
70
+ if ( ! cursorElement ) {
71
+ return false;
72
+ }
73
+
74
+ cursorElement.scrollIntoView( {
75
+ behavior: options?.behavior ?? 'smooth',
76
+ block: options?.block ?? 'center',
77
+ inline: options?.inline ?? 'nearest',
78
+ } );
79
+
80
+ if ( options?.highlightDuration ) {
81
+ highlightCursor( cursorElement, options.highlightDuration );
82
+ }
83
+
84
+ return true;
85
+ },
86
+
87
+ /**
88
+ * Clear the registry.
89
+ */
90
+ removeAll(): void {
91
+ cursorMap.clear();
92
+ },
93
+ };
94
+ }
95
+
96
+ export type CursorRegistry = ReturnType< typeof createCursorRegistry >;
@@ -9,22 +9,29 @@ import { privateApis } from '@wordpress/block-editor';
9
9
  */
10
10
  import { unlock } from '../../lock-unlock';
11
11
  import { Overlay } from './overlay';
12
+ import { type CursorRegistry } from './cursor-registry';
12
13
 
13
14
  const { BlockCanvasCover } = unlock( privateApis );
14
15
 
15
16
  interface Props {
16
17
  postId: number | null;
17
18
  postType: string | null;
19
+ cursorRegistry?: CursorRegistry;
18
20
  }
19
21
 
20
22
  /**
21
23
  * Collaborators Overlay component
22
- * @param props - The props for the CollaboratorsOverlay component
23
- * @param props.postId - The ID of the post
24
- * @param props.postType - The type of the post
24
+ * @param props - The props for the CollaboratorsOverlay component
25
+ * @param props.postId - The ID of the post
26
+ * @param props.postType - The type of the post
27
+ * @param props.cursorRegistry - The shared cursor registry
25
28
  * @return The CollaboratorsOverlay component
26
29
  */
27
- export function CollaboratorsOverlay( { postId, postType }: Props ) {
30
+ export function CollaboratorsOverlay( {
31
+ postId,
32
+ postType,
33
+ cursorRegistry,
34
+ }: Props ) {
28
35
  return (
29
36
  <BlockCanvasCover.Fill>
30
37
  { ( {
@@ -36,6 +43,7 @@ export function CollaboratorsOverlay( { postId, postType }: Props ) {
36
43
  blockEditorDocument={ containerRef.current?.ownerDocument }
37
44
  postId={ postId }
38
45
  postType={ postType }
46
+ cursorRegistry={ cursorRegistry }
39
47
  />
40
48
  ) }
41
49
  </BlockCanvasCover.Fill>
@@ -0,0 +1,131 @@
1
+ /**
2
+ * CSS for the collaborators overlay — cursor indicators, block highlights,
3
+ * and positioning of Avatar labels inside the editor canvas iframe.
4
+ */
5
+
6
+ import {
7
+ BORDER_WIDTH,
8
+ BORDER_WIDTH_FOCUS_FALLBACK,
9
+ ELEVATION_X_SMALL,
10
+ GRID_UNIT_05,
11
+ GRID_UNIT_10,
12
+ WHITE,
13
+ } from './collaborator-styles';
14
+
15
+ export const OVERLAY_IFRAME_STYLES = `
16
+ .block-canvas-cover {
17
+ position: absolute;
18
+ top: 0;
19
+ left: 0;
20
+ width: 100%;
21
+ height: 100%;
22
+ pointer-events: none;
23
+ z-index: 20000;
24
+ }
25
+ .block-canvas-cover .collaborators-overlay-full {
26
+ position: absolute;
27
+ top: 0;
28
+ left: 0;
29
+ width: 100%;
30
+ height: 100%;
31
+ }
32
+ .block-canvas-cover .collaborators-overlay-fixed {
33
+ position: fixed;
34
+ width: 100%;
35
+ height: 100%;
36
+ }
37
+ .collaborators-overlay-user {
38
+ position: absolute;
39
+ }
40
+ /* Cursor lines render below avatar labels across all users. The parent
41
+ .collaborators-overlay-user has no z-index so it does not create a
42
+ stacking context — children participate in the shared overlay context. */
43
+ .collaborators-overlay-user-cursor {
44
+ position: absolute;
45
+ z-index: 0;
46
+ width: ${ BORDER_WIDTH_FOCUS_FALLBACK };
47
+ border-radius: ${ BORDER_WIDTH };
48
+ outline: ${ BORDER_WIDTH } solid ${ WHITE };
49
+ box-shadow: ${ ELEVATION_X_SMALL };
50
+ animation: collaborators-overlay-cursor-blink 1s infinite;
51
+ }
52
+ .collaborators-overlay-selection-rect {
53
+ position: absolute;
54
+ opacity: 0.15;
55
+ pointer-events: none;
56
+ border-radius: 2px;
57
+ }
58
+
59
+ /* Overlay-specific positioning applied to the Avatar cursor label. */
60
+ .collaborators-overlay-user-label.editor-avatar {
61
+ position: absolute;
62
+ z-index: 1;
63
+ transform: translate(-11px, -100%);
64
+ margin-top: -${ GRID_UNIT_05 };
65
+ pointer-events: auto;
66
+ overflow: visible;
67
+ width: max-content;
68
+ }
69
+ /* Avatar positioned above a highlighted block as a label. */
70
+ .collaborators-overlay-block-label.editor-avatar {
71
+ position: absolute;
72
+ z-index: 1;
73
+ transform: translateY(calc(-100% - ${ GRID_UNIT_10 }));
74
+ pointer-events: auto;
75
+ overflow: visible;
76
+ width: max-content;
77
+ }
78
+
79
+ @keyframes collaborators-overlay-cursor-blink {
80
+ 0%, 45% { opacity: 1; }
81
+ 55%, 95% { opacity: 0; }
82
+ 100% { opacity: 1; }
83
+ }
84
+ .collaborators-overlay-cursor-highlighted .collaborators-overlay-user-cursor {
85
+ animation: collaborators-overlay-cursor-highlight 0.6s ease-in-out 3;
86
+ }
87
+ .collaborators-overlay-cursor-highlighted .collaborators-overlay-user-label {
88
+ animation: collaborators-overlay-label-highlight 0.6s ease-in-out 3;
89
+ }
90
+ @keyframes collaborators-overlay-cursor-highlight {
91
+ 0%, 100% {
92
+ transform: scale(1);
93
+ filter: drop-shadow(0 0 0 transparent);
94
+ }
95
+ 50% {
96
+ transform: scale(1.2);
97
+ filter: drop-shadow(0 0 8px currentColor);
98
+ }
99
+ }
100
+ @keyframes collaborators-overlay-label-highlight {
101
+ 0%, 100% {
102
+ transform: translate(-11px, -100%) scale(1);
103
+ filter: drop-shadow(0 0 0 transparent);
104
+ }
105
+ 50% {
106
+ transform: translate(-11px, -100%) scale(1.1);
107
+ filter: drop-shadow(0 0 6px currentColor);
108
+ }
109
+ }
110
+ .block-editor-block-list__block.is-collaborator-selected:not(:focus)::after {
111
+ content: "";
112
+ position: absolute;
113
+ pointer-events: none;
114
+ top: 0;
115
+ right: 0;
116
+ bottom: 0;
117
+ left: 0;
118
+ outline-color: var(--collaborator-outline-color);
119
+ outline-style: solid;
120
+ outline-width: calc(var(--wp-admin-border-width-focus) / var(--wp-block-editor-iframe-zoom-out-scale, 1));
121
+ outline-offset: calc(-1 * var(--wp-admin-border-width-focus) / var(--wp-block-editor-iframe-zoom-out-scale, 1));
122
+ box-shadow: inset 0 0 0 calc((var(--wp-admin-border-width-focus) / var(--wp-block-editor-iframe-zoom-out-scale, 1)) + 0.5px) rgba(${ WHITE }, 0.7);
123
+ z-index: 1;
124
+ }
125
+ @media (prefers-reduced-motion: reduce) {
126
+ .collaborators-overlay-user-label,
127
+ .collaborators-overlay-user-cursor {
128
+ animation: none;
129
+ }
130
+ }
131
+ `;