@wordpress/editor 14.40.2-next.v.202602271551.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 (481) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/build/components/collab-sidebar/add-comment.cjs +0 -3
  3. package/build/components/collab-sidebar/add-comment.cjs.map +2 -2
  4. package/build/components/collab-sidebar/comments.cjs +0 -3
  5. package/build/components/collab-sidebar/comments.cjs.map +2 -2
  6. package/build/components/collab-sidebar/index.cjs +7 -4
  7. package/build/components/collab-sidebar/index.cjs.map +2 -2
  8. package/build/components/collab-sidebar/utils.cjs +13 -15
  9. package/build/components/collab-sidebar/utils.cjs.map +2 -2
  10. package/build/components/collaborators-overlay/avatar-iframe-styles.cjs +141 -0
  11. package/build/components/collaborators-overlay/avatar-iframe-styles.cjs.map +7 -0
  12. package/build/components/collaborators-overlay/collaborator-styles.cjs +38 -2
  13. package/build/components/collaborators-overlay/collaborator-styles.cjs.map +2 -2
  14. package/build/components/collaborators-overlay/compute-selection.cjs +185 -0
  15. package/build/components/collaborators-overlay/compute-selection.cjs.map +7 -0
  16. package/build/components/collaborators-overlay/cursor-dom-utils.cjs +243 -0
  17. package/build/components/collaborators-overlay/cursor-dom-utils.cjs.map +7 -0
  18. package/build/components/collaborators-overlay/cursor-registry.cjs +86 -0
  19. package/build/components/collaborators-overlay/cursor-registry.cjs.map +7 -0
  20. package/build/components/collaborators-overlay/index.cjs +7 -2
  21. package/build/components/collaborators-overlay/index.cjs.map +2 -2
  22. package/build/components/collaborators-overlay/overlay-iframe-styles.cjs +148 -0
  23. package/build/components/collaborators-overlay/overlay-iframe-styles.cjs.map +7 -0
  24. package/build/components/collaborators-overlay/overlay.cjs +141 -229
  25. package/build/components/collaborators-overlay/overlay.cjs.map +3 -3
  26. package/build/components/collaborators-overlay/timing-utils.cjs +46 -0
  27. package/build/components/collaborators-overlay/timing-utils.cjs.map +7 -0
  28. package/build/components/collaborators-overlay/use-block-highlighting.cjs +91 -42
  29. package/build/components/collaborators-overlay/use-block-highlighting.cjs.map +2 -2
  30. package/build/components/collaborators-overlay/use-debounced-recompute.cjs +49 -0
  31. package/build/components/collaborators-overlay/use-debounced-recompute.cjs.map +7 -0
  32. package/build/components/collaborators-overlay/use-render-cursors.cjs +82 -172
  33. package/build/components/collaborators-overlay/use-render-cursors.cjs.map +3 -3
  34. package/build/components/collaborators-presence/avatar/component.cjs +121 -0
  35. package/build/components/collaborators-presence/avatar/component.cjs.map +7 -0
  36. package/build/components/collaborators-presence/avatar/index.cjs +37 -0
  37. package/build/components/collaborators-presence/avatar/index.cjs.map +7 -0
  38. package/build/components/collaborators-presence/avatar/types.cjs +19 -0
  39. package/build/components/collaborators-presence/avatar/types.cjs.map +7 -0
  40. package/build/components/collaborators-presence/avatar/use-image-loading-status.cjs +44 -0
  41. package/build/components/collaborators-presence/avatar/use-image-loading-status.cjs.map +7 -0
  42. package/build/components/collaborators-presence/avatar-group/component.cjs +78 -0
  43. package/build/components/collaborators-presence/avatar-group/component.cjs.map +7 -0
  44. package/build/components/collaborators-presence/avatar-group/index.cjs +37 -0
  45. package/build/components/collaborators-presence/avatar-group/index.cjs.map +7 -0
  46. package/build/components/collaborators-presence/avatar-group/types.cjs +19 -0
  47. package/build/components/collaborators-presence/avatar-group/types.cjs.map +7 -0
  48. package/build/components/collaborators-presence/index.cjs +66 -19
  49. package/build/components/collaborators-presence/index.cjs.map +3 -3
  50. package/build/components/collaborators-presence/list.cjs +60 -38
  51. package/build/components/collaborators-presence/list.cjs.map +3 -3
  52. package/build/components/collaborators-presence/use-collaborator-notifications.cjs +149 -0
  53. package/build/components/collaborators-presence/use-collaborator-notifications.cjs.map +7 -0
  54. package/build/components/editor-interface/index.cjs +11 -6
  55. package/build/components/editor-interface/index.cjs.map +2 -2
  56. package/build/components/inserter-sidebar/index.cjs +2 -1
  57. package/build/components/inserter-sidebar/index.cjs.map +2 -2
  58. package/build/components/more-menu/copy-content-menu-item.cjs +19 -2
  59. package/build/components/more-menu/copy-content-menu-item.cjs.map +3 -3
  60. package/build/components/post-last-revision/index.cjs +27 -6
  61. package/build/components/post-last-revision/index.cjs.map +2 -2
  62. package/build/components/post-locked-modal/index.cjs +49 -17
  63. package/build/components/post-locked-modal/index.cjs.map +3 -3
  64. package/build/components/post-revisions-preview/block-diff.cjs +130 -34
  65. package/build/components/post-revisions-preview/block-diff.cjs.map +2 -2
  66. package/build/components/post-revisions-preview/diff-markers.cjs +6 -5
  67. package/build/components/post-revisions-preview/diff-markers.cjs.map +2 -2
  68. package/build/components/post-revisions-preview/revisions-canvas.cjs +16 -60
  69. package/build/components/post-revisions-preview/revisions-canvas.cjs.map +3 -3
  70. package/build/components/post-revisions-preview/revisions-slider.cjs +102 -39
  71. package/build/components/post-revisions-preview/revisions-slider.cjs.map +3 -3
  72. package/build/components/post-text-editor/index.cjs +20 -5
  73. package/build/components/post-text-editor/index.cjs.map +3 -3
  74. package/build/components/preferences-modal/index.cjs +36 -4
  75. package/build/components/preferences-modal/index.cjs.map +2 -2
  76. package/build/components/provider/disable-non-page-content-blocks.cjs +31 -28
  77. package/build/components/provider/disable-non-page-content-blocks.cjs.map +3 -3
  78. package/build/components/provider/index.cjs +17 -5
  79. package/build/components/provider/index.cjs.map +2 -2
  80. package/build/components/provider/use-block-editor-settings.cjs +20 -4
  81. package/build/components/provider/use-block-editor-settings.cjs.map +3 -3
  82. package/build/components/provider/{use-post-content-blocks.cjs → use-post-content-block-types.cjs} +8 -19
  83. package/build/components/provider/use-post-content-block-types.cjs.map +7 -0
  84. package/build/components/provider/use-revision-blocks.cjs +106 -0
  85. package/build/components/provider/use-revision-blocks.cjs.map +7 -0
  86. package/build/components/revision-block-diff/index.cjs +61 -0
  87. package/build/components/revision-block-diff/index.cjs.map +7 -0
  88. package/build/components/revision-diff-panel/index.cjs +68 -0
  89. package/build/components/revision-diff-panel/index.cjs.map +7 -0
  90. package/build/components/revision-fields-diff/index.cjs +96 -0
  91. package/build/components/revision-fields-diff/index.cjs.map +7 -0
  92. package/build/components/sidebar/header.cjs +1 -1
  93. package/build/components/sidebar/header.cjs.map +2 -2
  94. package/build/components/sidebar/index.cjs +7 -1
  95. package/build/components/sidebar/index.cjs.map +3 -3
  96. package/build/components/style-book/index.cjs +4 -3
  97. package/build/components/style-book/index.cjs.map +2 -2
  98. package/build/components/sync-connection-error-modal/index.cjs +187 -0
  99. package/build/components/sync-connection-error-modal/index.cjs.map +7 -0
  100. package/build/components/sync-connection-error-modal/use-retry-countdown.cjs +84 -0
  101. package/build/components/sync-connection-error-modal/use-retry-countdown.cjs.map +7 -0
  102. package/build/components/template-content-panel/index.cjs +35 -31
  103. package/build/components/template-content-panel/index.cjs.map +3 -3
  104. package/build/components/template-part-menu-items/convert-to-regular.cjs +54 -11
  105. package/build/components/template-part-menu-items/convert-to-regular.cjs.map +3 -3
  106. package/build/components/visual-editor/index.cjs +6 -15
  107. package/build/components/visual-editor/index.cjs.map +2 -2
  108. package/build/store/private-actions.cjs +46 -2
  109. package/build/store/private-actions.cjs.map +2 -2
  110. package/build/store/private-selectors.cjs +154 -29
  111. package/build/store/private-selectors.cjs.map +2 -2
  112. package/build/store/reducer.cjs +27 -0
  113. package/build/store/reducer.cjs.map +2 -2
  114. package/build/store/selectors.cjs +0 -14
  115. package/build/store/selectors.cjs.map +2 -2
  116. package/build/utils/media-finalize/index.cjs +43 -0
  117. package/build/utils/media-finalize/index.cjs.map +7 -0
  118. package/build/utils/media-upload/on-success.cjs +46 -0
  119. package/build/utils/media-upload/on-success.cjs.map +7 -0
  120. package/build/utils/sync-error-messages.cjs +32 -15
  121. package/build/utils/sync-error-messages.cjs.map +3 -3
  122. package/build-module/components/collab-sidebar/add-comment.mjs +0 -3
  123. package/build-module/components/collab-sidebar/add-comment.mjs.map +2 -2
  124. package/build-module/components/collab-sidebar/comments.mjs +0 -3
  125. package/build-module/components/collab-sidebar/comments.mjs.map +2 -2
  126. package/build-module/components/collab-sidebar/index.mjs +7 -4
  127. package/build-module/components/collab-sidebar/index.mjs.map +2 -2
  128. package/build-module/components/collab-sidebar/utils.mjs +13 -15
  129. package/build-module/components/collab-sidebar/utils.mjs.map +2 -2
  130. package/build-module/components/collaborators-overlay/avatar-iframe-styles.mjs +128 -0
  131. package/build-module/components/collaborators-overlay/avatar-iframe-styles.mjs.map +7 -0
  132. package/build-module/components/collaborators-overlay/collaborator-styles.mjs +25 -1
  133. package/build-module/components/collaborators-overlay/collaborator-styles.mjs.map +2 -2
  134. package/build-module/components/collaborators-overlay/compute-selection.mjs +166 -0
  135. package/build-module/components/collaborators-overlay/compute-selection.mjs.map +7 -0
  136. package/build-module/components/collaborators-overlay/cursor-dom-utils.mjs +213 -0
  137. package/build-module/components/collaborators-overlay/cursor-dom-utils.mjs.map +7 -0
  138. package/build-module/components/collaborators-overlay/cursor-registry.mjs +61 -0
  139. package/build-module/components/collaborators-overlay/cursor-registry.mjs.map +7 -0
  140. package/build-module/components/collaborators-overlay/index.mjs +7 -2
  141. package/build-module/components/collaborators-overlay/index.mjs.map +2 -2
  142. package/build-module/components/collaborators-overlay/overlay-iframe-styles.mjs +130 -0
  143. package/build-module/components/collaborators-overlay/overlay-iframe-styles.mjs.map +7 -0
  144. package/build-module/components/collaborators-overlay/overlay.mjs +132 -230
  145. package/build-module/components/collaborators-overlay/overlay.mjs.map +2 -2
  146. package/build-module/components/collaborators-overlay/timing-utils.mjs +21 -0
  147. package/build-module/components/collaborators-overlay/timing-utils.mjs.map +7 -0
  148. package/build-module/components/collaborators-overlay/use-block-highlighting.mjs +93 -45
  149. package/build-module/components/collaborators-overlay/use-block-highlighting.mjs.map +2 -2
  150. package/build-module/components/collaborators-overlay/use-debounced-recompute.mjs +24 -0
  151. package/build-module/components/collaborators-overlay/use-debounced-recompute.mjs.map +7 -0
  152. package/build-module/components/collaborators-overlay/use-render-cursors.mjs +83 -176
  153. package/build-module/components/collaborators-overlay/use-render-cursors.mjs.map +2 -2
  154. package/build-module/components/collaborators-presence/avatar/component.mjs +90 -0
  155. package/build-module/components/collaborators-presence/avatar/component.mjs.map +7 -0
  156. package/build-module/components/collaborators-presence/avatar/index.mjs +6 -0
  157. package/build-module/components/collaborators-presence/avatar/index.mjs.map +7 -0
  158. package/build-module/components/collaborators-presence/avatar/types.mjs +1 -0
  159. package/build-module/components/collaborators-presence/avatar/types.mjs.map +7 -0
  160. package/build-module/components/collaborators-presence/avatar/use-image-loading-status.mjs +19 -0
  161. package/build-module/components/collaborators-presence/avatar/use-image-loading-status.mjs.map +7 -0
  162. package/build-module/components/collaborators-presence/avatar-group/component.mjs +47 -0
  163. package/build-module/components/collaborators-presence/avatar-group/component.mjs.map +7 -0
  164. package/build-module/components/collaborators-presence/avatar-group/index.mjs +6 -0
  165. package/build-module/components/collaborators-presence/avatar-group/index.mjs.map +7 -0
  166. package/build-module/components/collaborators-presence/avatar-group/types.mjs +1 -0
  167. package/build-module/components/collaborators-presence/avatar-group/types.mjs.map +7 -0
  168. package/build-module/components/collaborators-presence/index.mjs +57 -23
  169. package/build-module/components/collaborators-presence/index.mjs.map +2 -2
  170. package/build-module/components/collaborators-presence/list.mjs +52 -44
  171. package/build-module/components/collaborators-presence/list.mjs.map +2 -2
  172. package/build-module/components/collaborators-presence/use-collaborator-notifications.mjs +126 -0
  173. package/build-module/components/collaborators-presence/use-collaborator-notifications.mjs.map +7 -0
  174. package/build-module/components/editor-interface/index.mjs +12 -7
  175. package/build-module/components/editor-interface/index.mjs.map +2 -2
  176. package/build-module/components/inserter-sidebar/index.mjs +2 -1
  177. package/build-module/components/inserter-sidebar/index.mjs.map +2 -2
  178. package/build-module/components/more-menu/copy-content-menu-item.mjs +19 -2
  179. package/build-module/components/more-menu/copy-content-menu-item.mjs.map +2 -2
  180. package/build-module/components/post-last-revision/index.mjs +27 -6
  181. package/build-module/components/post-last-revision/index.mjs.map +2 -2
  182. package/build-module/components/post-locked-modal/index.mjs +49 -17
  183. package/build-module/components/post-locked-modal/index.mjs.map +2 -2
  184. package/build-module/components/post-revisions-preview/block-diff.mjs +130 -34
  185. package/build-module/components/post-revisions-preview/block-diff.mjs.map +2 -2
  186. package/build-module/components/post-revisions-preview/diff-markers.mjs +6 -5
  187. package/build-module/components/post-revisions-preview/diff-markers.mjs.map +2 -2
  188. package/build-module/components/post-revisions-preview/revisions-canvas.mjs +18 -65
  189. package/build-module/components/post-revisions-preview/revisions-canvas.mjs.map +2 -2
  190. package/build-module/components/post-revisions-preview/revisions-slider.mjs +110 -42
  191. package/build-module/components/post-revisions-preview/revisions-slider.mjs.map +2 -2
  192. package/build-module/components/post-text-editor/index.mjs +20 -5
  193. package/build-module/components/post-text-editor/index.mjs.map +2 -2
  194. package/build-module/components/preferences-modal/index.mjs +36 -4
  195. package/build-module/components/preferences-modal/index.mjs.map +2 -2
  196. package/build-module/components/provider/disable-non-page-content-blocks.mjs +31 -28
  197. package/build-module/components/provider/disable-non-page-content-blocks.mjs.map +2 -2
  198. package/build-module/components/provider/index.mjs +17 -5
  199. package/build-module/components/provider/index.mjs.map +2 -2
  200. package/build-module/components/provider/use-block-editor-settings.mjs +20 -4
  201. package/build-module/components/provider/use-block-editor-settings.mjs.map +2 -2
  202. package/build-module/components/provider/use-post-content-block-types.mjs +23 -0
  203. package/build-module/components/provider/use-post-content-block-types.mjs.map +7 -0
  204. package/build-module/components/provider/use-revision-blocks.mjs +81 -0
  205. package/build-module/components/provider/use-revision-blocks.mjs.map +7 -0
  206. package/build-module/components/revision-block-diff/index.mjs +30 -0
  207. package/build-module/components/revision-block-diff/index.mjs.map +7 -0
  208. package/build-module/components/revision-diff-panel/index.mjs +37 -0
  209. package/build-module/components/revision-diff-panel/index.mjs.map +7 -0
  210. package/build-module/components/revision-fields-diff/index.mjs +65 -0
  211. package/build-module/components/revision-fields-diff/index.mjs.map +7 -0
  212. package/build-module/components/sidebar/header.mjs +1 -1
  213. package/build-module/components/sidebar/header.mjs.map +2 -2
  214. package/build-module/components/sidebar/index.mjs +7 -1
  215. package/build-module/components/sidebar/index.mjs.map +2 -2
  216. package/build-module/components/style-book/index.mjs +4 -3
  217. package/build-module/components/style-book/index.mjs.map +2 -2
  218. package/build-module/components/sync-connection-error-modal/index.mjs +170 -0
  219. package/build-module/components/sync-connection-error-modal/index.mjs.map +7 -0
  220. package/build-module/components/sync-connection-error-modal/use-retry-countdown.mjs +59 -0
  221. package/build-module/components/sync-connection-error-modal/use-retry-countdown.mjs.map +7 -0
  222. package/build-module/components/template-content-panel/index.mjs +25 -31
  223. package/build-module/components/template-content-panel/index.mjs.map +2 -2
  224. package/build-module/components/template-part-menu-items/convert-to-regular.mjs +60 -14
  225. package/build-module/components/template-part-menu-items/convert-to-regular.mjs.map +2 -2
  226. package/build-module/components/visual-editor/index.mjs +6 -15
  227. package/build-module/components/visual-editor/index.mjs.map +2 -2
  228. package/build-module/store/private-actions.mjs +44 -2
  229. package/build-module/store/private-actions.mjs.map +2 -2
  230. package/build-module/store/private-selectors.mjs +153 -29
  231. package/build-module/store/private-selectors.mjs.map +2 -2
  232. package/build-module/store/reducer.mjs +25 -0
  233. package/build-module/store/reducer.mjs.map +2 -2
  234. package/build-module/store/selectors.mjs +0 -13
  235. package/build-module/store/selectors.mjs.map +2 -2
  236. package/build-module/utils/media-finalize/index.mjs +12 -0
  237. package/build-module/utils/media-finalize/index.mjs.map +7 -0
  238. package/build-module/utils/media-upload/on-success.mjs +25 -0
  239. package/build-module/utils/media-upload/on-success.mjs.map +7 -0
  240. package/build-module/utils/sync-error-messages.mjs +27 -15
  241. package/build-module/utils/sync-error-messages.mjs.map +3 -3
  242. package/build-style/style-rtl.css +296 -121
  243. package/build-style/style.css +296 -121
  244. package/build-types/components/autocompleters/link.d.ts +8 -0
  245. package/build-types/components/autocompleters/link.d.ts.map +1 -0
  246. package/build-types/components/collab-sidebar/add-comment.d.ts.map +1 -1
  247. package/build-types/components/collab-sidebar/add-note-menu-item.d.ts +5 -0
  248. package/build-types/components/collab-sidebar/add-note-menu-item.d.ts.map +1 -0
  249. package/build-types/components/collab-sidebar/add-note.d.ts +6 -0
  250. package/build-types/components/collab-sidebar/add-note.d.ts.map +1 -0
  251. package/build-types/components/collab-sidebar/board-store.d.ts +9 -0
  252. package/build-types/components/collab-sidebar/board-store.d.ts.map +1 -0
  253. package/build-types/components/collab-sidebar/floating-container.d.ts +8 -0
  254. package/build-types/components/collab-sidebar/floating-container.d.ts.map +1 -0
  255. package/build-types/components/collab-sidebar/index.d.ts.map +1 -1
  256. package/build-types/components/collab-sidebar/note-byline.d.ts +10 -0
  257. package/build-types/components/collab-sidebar/note-byline.d.ts.map +1 -0
  258. package/build-types/components/collab-sidebar/note-card.d.ts +8 -0
  259. package/build-types/components/collab-sidebar/note-card.d.ts.map +1 -0
  260. package/build-types/components/collab-sidebar/note-form.d.ts +7 -0
  261. package/build-types/components/collab-sidebar/note-form.d.ts.map +1 -0
  262. package/build-types/components/collab-sidebar/note-indicator-toolbar.d.ts +5 -0
  263. package/build-types/components/collab-sidebar/note-indicator-toolbar.d.ts.map +1 -0
  264. package/build-types/components/collab-sidebar/note-thread.d.ts +11 -0
  265. package/build-types/components/collab-sidebar/note-thread.d.ts.map +1 -0
  266. package/build-types/components/collab-sidebar/note.d.ts +9 -0
  267. package/build-types/components/collab-sidebar/note.d.ts.map +1 -0
  268. package/build-types/components/collab-sidebar/notes.d.ts +7 -0
  269. package/build-types/components/collab-sidebar/notes.d.ts.map +1 -0
  270. package/build-types/components/collab-sidebar/utils.d.ts.map +1 -1
  271. package/build-types/components/collaborators-overlay/avatar-iframe-styles.d.ts +11 -0
  272. package/build-types/components/collaborators-overlay/avatar-iframe-styles.d.ts.map +1 -0
  273. package/build-types/components/collaborators-overlay/collaborator-styles.d.ts +17 -2
  274. package/build-types/components/collaborators-overlay/collaborator-styles.d.ts.map +1 -1
  275. package/build-types/components/collaborators-overlay/compute-selection.d.ts +24 -0
  276. package/build-types/components/collaborators-overlay/compute-selection.d.ts.map +1 -0
  277. package/build-types/components/collaborators-overlay/cursor-dom-utils.d.ts +72 -0
  278. package/build-types/components/collaborators-overlay/cursor-dom-utils.d.ts.map +1 -0
  279. package/build-types/components/collaborators-overlay/cursor-registry.d.ts +36 -0
  280. package/build-types/components/collaborators-overlay/cursor-registry.d.ts.map +1 -0
  281. package/build-types/components/collaborators-overlay/index.d.ts +7 -4
  282. package/build-types/components/collaborators-overlay/index.d.ts.map +1 -1
  283. package/build-types/components/collaborators-overlay/overlay-iframe-styles.d.ts +6 -0
  284. package/build-types/components/collaborators-overlay/overlay-iframe-styles.d.ts.map +1 -0
  285. package/build-types/components/collaborators-overlay/overlay.d.ts +4 -1
  286. package/build-types/components/collaborators-overlay/overlay.d.ts.map +1 -1
  287. package/build-types/components/collaborators-overlay/timing-utils.d.ts +11 -0
  288. package/build-types/components/collaborators-overlay/timing-utils.d.ts.map +1 -0
  289. package/build-types/components/collaborators-overlay/use-block-highlighting.d.ts +21 -5
  290. package/build-types/components/collaborators-overlay/use-block-highlighting.d.ts.map +1 -1
  291. package/build-types/components/collaborators-overlay/use-debounced-recompute.d.ts +10 -0
  292. package/build-types/components/collaborators-overlay/use-debounced-recompute.d.ts.map +1 -0
  293. package/build-types/components/collaborators-overlay/use-render-cursors.d.ts +6 -1
  294. package/build-types/components/collaborators-overlay/use-render-cursors.d.ts.map +1 -1
  295. package/build-types/components/collaborators-presence/avatar/component.d.ts +7 -0
  296. package/build-types/components/collaborators-presence/avatar/component.d.ts.map +1 -0
  297. package/build-types/components/collaborators-presence/avatar/index.d.ts +3 -0
  298. package/build-types/components/collaborators-presence/avatar/index.d.ts.map +1 -0
  299. package/build-types/components/collaborators-presence/avatar/types.d.ts +66 -0
  300. package/build-types/components/collaborators-presence/avatar/types.d.ts.map +1 -0
  301. package/build-types/components/collaborators-presence/avatar/use-image-loading-status.d.ts +17 -0
  302. package/build-types/components/collaborators-presence/avatar/use-image-loading-status.d.ts.map +1 -0
  303. package/build-types/components/collaborators-presence/avatar-group/component.d.ts +7 -0
  304. package/build-types/components/collaborators-presence/avatar-group/component.d.ts.map +1 -0
  305. package/build-types/components/collaborators-presence/avatar-group/index.d.ts +3 -0
  306. package/build-types/components/collaborators-presence/avatar-group/index.d.ts.map +1 -0
  307. package/build-types/components/collaborators-presence/avatar-group/types.d.ts +14 -0
  308. package/build-types/components/collaborators-presence/avatar-group/types.d.ts.map +1 -0
  309. package/build-types/components/collaborators-presence/index.d.ts.map +1 -1
  310. package/build-types/components/collaborators-presence/list.d.ts +6 -2
  311. package/build-types/components/collaborators-presence/list.d.ts.map +1 -1
  312. package/build-types/components/collaborators-presence/use-collaborator-notifications.d.ts +9 -0
  313. package/build-types/components/collaborators-presence/use-collaborator-notifications.d.ts.map +1 -0
  314. package/build-types/components/editor-interface/index.d.ts.map +1 -1
  315. package/build-types/components/inserter-sidebar/index.d.ts.map +1 -1
  316. package/build-types/components/media/media-editor-modal.d.ts +15 -0
  317. package/build-types/components/media/media-editor-modal.d.ts.map +1 -0
  318. package/build-types/components/more-menu/copy-content-menu-item.d.ts.map +1 -1
  319. package/build-types/components/post-last-revision/index.d.ts.map +1 -1
  320. package/build-types/components/post-locked-modal/index.d.ts.map +1 -1
  321. package/build-types/components/post-revisions-panel/index.d.ts +2 -0
  322. package/build-types/components/post-revisions-panel/index.d.ts.map +1 -0
  323. package/build-types/components/post-revisions-preview/block-diff.d.ts.map +1 -1
  324. package/build-types/components/post-revisions-preview/diff-markers.d.ts.map +1 -1
  325. package/build-types/components/post-revisions-preview/revisions-canvas.d.ts +2 -5
  326. package/build-types/components/post-revisions-preview/revisions-canvas.d.ts.map +1 -1
  327. package/build-types/components/post-revisions-preview/revisions-slider.d.ts +1 -1
  328. package/build-types/components/post-revisions-preview/revisions-slider.d.ts.map +1 -1
  329. package/build-types/components/post-text-editor/index.d.ts.map +1 -1
  330. package/build-types/components/post-text-editor/utils.d.ts +29 -0
  331. package/build-types/components/post-text-editor/utils.d.ts.map +1 -0
  332. package/build-types/components/provider/disable-non-page-content-blocks.d.ts.map +1 -1
  333. package/build-types/components/provider/index.d.ts.map +1 -1
  334. package/build-types/components/provider/use-block-editor-settings.d.ts.map +1 -1
  335. package/build-types/components/provider/use-network-reconnect.d.ts +8 -0
  336. package/build-types/components/provider/use-network-reconnect.d.ts.map +1 -0
  337. package/build-types/components/provider/use-post-content-block-types.d.ts +9 -0
  338. package/build-types/components/provider/use-post-content-block-types.d.ts.map +1 -0
  339. package/build-types/components/provider/use-revision-blocks.d.ts +10 -0
  340. package/build-types/components/provider/use-revision-blocks.d.ts.map +1 -0
  341. package/build-types/components/revision-block-diff/index.d.ts +6 -0
  342. package/build-types/components/revision-block-diff/index.d.ts.map +1 -0
  343. package/build-types/components/revision-diff-panel/index.d.ts +14 -0
  344. package/build-types/components/revision-diff-panel/index.d.ts.map +1 -0
  345. package/build-types/components/revision-fields-diff/index.d.ts +6 -0
  346. package/build-types/components/revision-fields-diff/index.d.ts.map +1 -0
  347. package/build-types/components/sidebar/dataform-post-summary.d.ts +4 -0
  348. package/build-types/components/sidebar/dataform-post-summary.d.ts.map +1 -0
  349. package/build-types/components/sidebar/index.d.ts.map +1 -1
  350. package/build-types/components/sidebar/post-revision-summary.d.ts +2 -0
  351. package/build-types/components/sidebar/post-revision-summary.d.ts.map +1 -0
  352. package/build-types/components/style-book/index.d.ts +2 -1
  353. package/build-types/components/style-book/index.d.ts.map +1 -1
  354. package/build-types/components/sync-connection-error-modal/index.d.ts +8 -0
  355. package/build-types/components/sync-connection-error-modal/index.d.ts.map +1 -0
  356. package/build-types/components/sync-connection-error-modal/use-retry-countdown.d.ts +11 -0
  357. package/build-types/components/sync-connection-error-modal/use-retry-countdown.d.ts.map +1 -0
  358. package/build-types/components/template-actions-panel/block-theme-content.d.ts +2 -0
  359. package/build-types/components/template-actions-panel/block-theme-content.d.ts.map +1 -0
  360. package/build-types/components/template-actions-panel/classic-theme-content.d.ts +2 -0
  361. package/build-types/components/template-actions-panel/classic-theme-content.d.ts.map +1 -0
  362. package/build-types/components/template-actions-panel/index.d.ts +2 -0
  363. package/build-types/components/template-actions-panel/index.d.ts.map +1 -0
  364. package/build-types/components/template-content-panel/index.d.ts.map +1 -1
  365. package/build-types/components/template-part-menu-items/convert-to-regular.d.ts.map +1 -1
  366. package/build-types/components/upload-progress-snackbar/index.d.ts +19 -0
  367. package/build-types/components/upload-progress-snackbar/index.d.ts.map +1 -0
  368. package/build-types/components/upload-progress-snackbar/stories/index.story.d.ts +28 -0
  369. package/build-types/components/upload-progress-snackbar/stories/index.story.d.ts.map +1 -0
  370. package/build-types/components/upload-progress-snackbar/tracker.d.ts +41 -0
  371. package/build-types/components/upload-progress-snackbar/tracker.d.ts.map +1 -0
  372. package/build-types/components/visual-editor/index.d.ts.map +1 -1
  373. package/build-types/store/private-actions.d.ts +12 -0
  374. package/build-types/store/private-actions.d.ts.map +1 -1
  375. package/build-types/store/private-selectors.d.ts +45 -0
  376. package/build-types/store/private-selectors.d.ts.map +1 -1
  377. package/build-types/store/reducer.d.ts +21 -0
  378. package/build-types/store/reducer.d.ts.map +1 -1
  379. package/build-types/store/selectors.d.ts +0 -10
  380. package/build-types/store/selectors.d.ts.map +1 -1
  381. package/build-types/utils/media-delete/index.d.ts +2 -0
  382. package/build-types/utils/media-delete/index.d.ts.map +1 -0
  383. package/build-types/utils/media-finalize/index.d.ts +2 -0
  384. package/build-types/utils/media-finalize/index.d.ts.map +1 -0
  385. package/build-types/utils/media-upload/on-success.d.ts +9 -0
  386. package/build-types/utils/media-upload/on-success.d.ts.map +1 -0
  387. package/build-types/utils/sync-error-messages.d.ts +17 -3
  388. package/build-types/utils/sync-error-messages.d.ts.map +1 -1
  389. package/package.json +45 -44
  390. package/src/components/collab-sidebar/add-comment.js +0 -4
  391. package/src/components/collab-sidebar/comments.js +0 -5
  392. package/src/components/collab-sidebar/index.js +7 -4
  393. package/src/components/collab-sidebar/utils.js +9 -10
  394. package/src/components/collaborators-overlay/avatar-iframe-styles.ts +134 -0
  395. package/src/components/collaborators-overlay/collaborator-styles.ts +43 -2
  396. package/src/components/collaborators-overlay/compute-selection.ts +315 -0
  397. package/src/components/collaborators-overlay/cursor-dom-utils.ts +382 -0
  398. package/src/components/collaborators-overlay/cursor-registry.ts +96 -0
  399. package/src/components/collaborators-overlay/index.tsx +12 -4
  400. package/src/components/collaborators-overlay/overlay-iframe-styles.ts +131 -0
  401. package/src/components/collaborators-overlay/overlay.tsx +145 -223
  402. package/src/components/collaborators-overlay/timing-utils.ts +30 -0
  403. package/src/components/collaborators-overlay/use-block-highlighting.ts +152 -64
  404. package/src/components/collaborators-overlay/use-debounced-recompute.ts +32 -0
  405. package/src/components/collaborators-overlay/use-render-cursors.ts +120 -282
  406. package/src/components/collaborators-presence/avatar/component.tsx +123 -0
  407. package/src/components/collaborators-presence/avatar/index.ts +2 -0
  408. package/src/components/collaborators-presence/avatar/styles.scss +184 -0
  409. package/src/components/collaborators-presence/avatar/test/index.tsx +389 -0
  410. package/src/components/collaborators-presence/avatar/types.ts +66 -0
  411. package/src/components/collaborators-presence/avatar/use-image-loading-status.ts +36 -0
  412. package/src/components/collaborators-presence/avatar-group/component.tsx +55 -0
  413. package/src/components/collaborators-presence/avatar-group/index.ts +2 -0
  414. package/src/components/collaborators-presence/avatar-group/styles.scss +33 -0
  415. package/src/components/collaborators-presence/avatar-group/test/index.tsx +139 -0
  416. package/src/components/collaborators-presence/avatar-group/types.ts +13 -0
  417. package/src/components/collaborators-presence/index.tsx +43 -12
  418. package/src/components/collaborators-presence/list.tsx +68 -40
  419. package/src/components/collaborators-presence/styles/collaborators-list.scss +26 -19
  420. package/src/components/collaborators-presence/styles/collaborators-presence.scss +6 -2
  421. package/src/components/collaborators-presence/test/use-collaborator-notifications.ts +397 -0
  422. package/src/components/collaborators-presence/use-collaborator-notifications.ts +203 -0
  423. package/src/components/document-bar/style.scss +1 -1
  424. package/src/components/editor-interface/index.js +13 -6
  425. package/src/components/inserter-sidebar/index.js +4 -1
  426. package/src/components/more-menu/copy-content-menu-item.js +20 -2
  427. package/src/components/post-last-revision/index.js +35 -6
  428. package/src/components/post-last-revision/style.scss +0 -3
  429. package/src/components/post-locked-modal/index.js +69 -25
  430. package/src/components/post-panel-row/style.scss +1 -0
  431. package/src/components/post-revisions-preview/block-diff.js +224 -61
  432. package/src/components/post-revisions-preview/diff-markers.js +15 -12
  433. package/src/components/post-revisions-preview/revisions-canvas.js +23 -86
  434. package/src/components/post-revisions-preview/revisions-slider.js +136 -63
  435. package/src/components/post-revisions-preview/style.scss +3 -3
  436. package/src/components/post-revisions-preview/test/block-diff.js +202 -35
  437. package/src/components/post-text-editor/index.js +25 -6
  438. package/src/components/preferences-modal/index.js +37 -7
  439. package/src/components/provider/disable-non-page-content-blocks.js +42 -40
  440. package/src/components/provider/index.js +20 -2
  441. package/src/components/provider/use-block-editor-settings.js +21 -1
  442. package/src/components/provider/use-post-content-block-types.js +30 -0
  443. package/src/components/provider/use-revision-blocks.js +105 -0
  444. package/src/components/revision-block-diff/index.js +39 -0
  445. package/src/components/revision-diff-panel/index.js +59 -0
  446. package/src/components/revision-diff-panel/style.scss +13 -0
  447. package/src/components/revision-fields-diff/index.js +91 -0
  448. package/src/components/sidebar/header.js +1 -1
  449. package/src/components/sidebar/index.js +4 -0
  450. package/src/components/style-book/index.js +4 -2
  451. package/src/components/sync-connection-error-modal/index.tsx +253 -0
  452. package/src/components/sync-connection-error-modal/style.scss +14 -0
  453. package/src/components/sync-connection-error-modal/use-retry-countdown.ts +93 -0
  454. package/src/components/template-content-panel/index.js +30 -38
  455. package/src/components/template-part-menu-items/convert-to-regular.js +74 -12
  456. package/src/components/visual-editor/index.js +6 -23
  457. package/src/store/private-actions.js +70 -1
  458. package/src/store/private-selectors.js +215 -37
  459. package/src/store/reducer.js +41 -0
  460. package/src/store/selectors.js +0 -19
  461. package/src/style.scss +4 -1
  462. package/src/utils/media-finalize/index.js +11 -0
  463. package/src/utils/media-finalize/test/index.js +34 -0
  464. package/src/utils/media-upload/on-success.js +34 -0
  465. package/src/utils/sync-error-messages.ts +72 -0
  466. package/src/utils/test/sync-error-messages.js +34 -0
  467. package/build/components/provider/use-post-content-blocks.cjs.map +0 -7
  468. package/build/components/sync-connection-modal/index.cjs +0 -130
  469. package/build/components/sync-connection-modal/index.cjs.map +0 -7
  470. package/build-module/components/provider/use-post-content-blocks.mjs +0 -34
  471. package/build-module/components/provider/use-post-content-blocks.mjs.map +0 -7
  472. package/build-module/components/sync-connection-modal/index.mjs +0 -114
  473. package/build-module/components/sync-connection-modal/index.mjs.map +0 -7
  474. package/build-types/components/provider/use-post-content-blocks.d.ts +0 -2
  475. package/build-types/components/provider/use-post-content-blocks.d.ts.map +0 -1
  476. package/build-types/components/sync-connection-modal/index.d.ts +0 -8
  477. package/build-types/components/sync-connection-modal/index.d.ts.map +0 -1
  478. package/src/components/provider/use-post-content-blocks.js +0 -42
  479. package/src/components/sync-connection-modal/index.js +0 -140
  480. package/src/components/sync-connection-modal/style.scss +0 -11
  481. package/src/utils/sync-error-messages.js +0 -53
@@ -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
+ `;
@@ -1,208 +1,29 @@
1
- import { privateApis as componentsPrivateApis } from '@wordpress/components';
2
1
  import { useResizeObserver, useMergeRefs } from '@wordpress/compose';
3
- import { useEffect, useState } from '@wordpress/element';
2
+ import { useCallback, useEffect, useRef, useState } from '@wordpress/element';
3
+ import { __ } from '@wordpress/i18n';
4
4
 
5
- import { unlock } from '../../lock-unlock';
5
+ import Avatar from '../collaborators-presence/avatar';
6
+ import { AVATAR_IFRAME_STYLES } from './avatar-iframe-styles';
7
+ import { OVERLAY_IFRAME_STYLES } from './overlay-iframe-styles';
8
+ import { setDelayedInterval } from './timing-utils';
6
9
  import { useBlockHighlighting } from './use-block-highlighting';
7
10
  import { useRenderCursors } from './use-render-cursors';
8
- import { ELEVATION_X_SMALL } from './collaborator-styles';
11
+ import { type CursorRegistry } from './cursor-registry';
9
12
 
10
- const { Avatar } = unlock( componentsPrivateApis );
13
+ // Milliseconds to wait after a change before recomputing cursor positions.
14
+ const RERENDER_DELAY_MS = 500;
11
15
 
12
- // wp-components styles are excluded from the editor canvas iframe, so the
13
- // Avatar component's SCSS is not available there. We inject compiled versions
14
- // of the relevant rules alongside the overlay-specific positioning styles.
15
- const COLLABORATORS_OVERLAY_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
- .collaborators-overlay-user-cursor {
41
- position: absolute;
42
- width: 2px;
43
- border-radius: 1px;
44
- outline: 1px solid #fff;
45
- box-shadow: ${ ELEVATION_X_SMALL };
46
- animation: collaborators-overlay-cursor-blink 1s infinite;
47
- }
48
-
49
- /* ── Avatar component (compiled from packages/components/src/avatar/styles.scss) ── */
50
- .components-avatar {
51
- display: inline-flex;
52
- align-items: center;
53
- border-radius: 9999px;
54
- overflow: clip;
55
- flex-shrink: 0;
56
- background-color: var(--wp-components-color-accent, var(--wp-admin-theme-color, #3858e9));
57
- box-shadow: 0 0 0 var(--wp-admin-border-width-focus, 2px) #fff, ${ ELEVATION_X_SMALL };
58
- }
59
- .components-avatar__image {
60
- box-sizing: border-box;
61
- position: relative;
62
- width: 32px;
63
- height: 32px;
64
- border-radius: 9999px;
65
- border: 0;
66
- background-color: var(--wp-components-color-accent, var(--wp-admin-theme-color, #3858e9));
67
- overflow: clip;
68
- flex-shrink: 0;
69
- font-size: 0;
70
- color: #fff;
71
- }
72
- .is-small > .components-avatar__image {
73
- width: 24px;
74
- height: 24px;
75
- }
76
- .has-src > .components-avatar__image {
77
- background-image: var(--components-avatar-url);
78
- background-size: cover;
79
- background-position: center;
80
- }
81
- .has-avatar-border-color > .components-avatar__image {
82
- border: var(--wp-admin-border-width-focus, 2px) solid var(--components-avatar-outline-color);
83
- box-shadow: inset 0 0 0 var(--wp-admin-border-width-focus, 2px) #fff;
84
- background-clip: padding-box;
85
- }
86
- .components-avatar:not(.has-src) > .components-avatar__image {
87
- display: flex;
88
- align-items: center;
89
- justify-content: center;
90
- font-size: 11px;
91
- font-weight: 499;
92
- border: 0;
93
- box-shadow: none;
94
- background-clip: border-box;
95
- }
96
- .components-avatar:not(.has-src).has-avatar-border-color > .components-avatar__image {
97
- background-color: var(--components-avatar-outline-color);
98
- }
99
- .components-avatar__name {
100
- font-size: 13px;
101
- line-height: 20px;
102
- color: #fff;
103
- min-width: 0;
104
- padding-bottom: 2px;
105
- overflow: hidden;
106
- opacity: 0;
107
- white-space: nowrap;
108
- transition: opacity 0.15s cubic-bezier(0.15, 0, 0.15, 1);
109
- }
110
- .components-avatar.has-badge {
111
- display: inline-grid;
112
- grid-template-columns: min-content 0fr;
113
- column-gap: 0;
114
- padding-inline-end: 0;
115
- transition:
116
- grid-template-columns 0.3s cubic-bezier(0.15, 0, 0.15, 1),
117
- column-gap 0.3s cubic-bezier(0.15, 0, 0.15, 1),
118
- padding-inline-end 0.3s cubic-bezier(0.15, 0, 0.15, 1);
119
- }
120
- .components-avatar.has-badge:hover {
121
- grid-template-columns: min-content 1fr;
122
- column-gap: 4px;
123
- padding-inline-end: 8px;
124
- transition-timing-function: cubic-bezier(0.85, 0, 0.85, 1);
125
- }
126
- .components-avatar.has-badge:hover .components-avatar__name {
127
- opacity: 1;
128
- transition-timing-function: cubic-bezier(0.85, 0, 0.85, 1);
129
- }
130
- .components-avatar.has-badge.has-avatar-border-color {
131
- background-color: var(--components-avatar-outline-color);
132
- }
133
- /* ── end Avatar ── */
134
-
135
- /* Overlay-specific positioning applied to the Avatar cursor label. */
136
- .collaborators-overlay-user-label.components-avatar {
137
- position: absolute;
138
- transform: translate(-11px, -100%);
139
- margin-top: -4px;
140
- pointer-events: auto;
141
- overflow: visible;
142
- width: max-content;
143
- }
144
-
145
- @keyframes collaborators-overlay-cursor-blink {
146
- 0%, 45% { opacity: 1; }
147
- 55%, 95% { opacity: 0; }
148
- 100% { opacity: 1; }
149
- }
150
- .collaborators-overlay-cursor-highlighted .collaborators-overlay-user-cursor {
151
- animation: collaborators-overlay-cursor-highlight 0.6s ease-in-out 3;
152
- }
153
- .collaborators-overlay-cursor-highlighted .collaborators-overlay-user-label {
154
- animation: collaborators-overlay-label-highlight 0.6s ease-in-out 3;
155
- }
156
- @keyframes collaborators-overlay-cursor-highlight {
157
- 0%, 100% {
158
- transform: scale(1);
159
- filter: drop-shadow(0 0 0 transparent);
160
- }
161
- 50% {
162
- transform: scale(1.2);
163
- filter: drop-shadow(0 0 8px currentColor);
164
- }
165
- }
166
- @keyframes collaborators-overlay-label-highlight {
167
- 0%, 100% {
168
- transform: translate(-11px, -100%) scale(1);
169
- filter: drop-shadow(0 0 0 transparent);
170
- }
171
- 50% {
172
- transform: translate(-11px, -100%) scale(1.1);
173
- filter: drop-shadow(0 0 6px currentColor);
174
- }
175
- }
176
- .block-editor-block-list__block.is-collaborator-selected:not(:focus)::after {
177
- content: "";
178
- position: absolute;
179
- pointer-events: none;
180
- top: 0;
181
- right: 0;
182
- bottom: 0;
183
- left: 0;
184
- outline-color: var(--collaborator-outline-color);
185
- outline-style: solid;
186
- outline-width: calc(var(--wp-admin-border-width-focus) / var(--wp-block-editor-iframe-zoom-out-scale, 1));
187
- outline-offset: calc(-1 * var(--wp-admin-border-width-focus) / var(--wp-block-editor-iframe-zoom-out-scale, 1));
188
- box-shadow: inset 0 0 0 calc(var(--wp-admin-border-width-focus, 2px) + 1px) #fff, 0 0 0 1px #fff, ${ ELEVATION_X_SMALL };
189
- z-index: 1;
190
- }
191
- @media (prefers-reduced-motion: reduce) {
192
- .components-avatar.has-badge,
193
- .components-avatar__name,
194
- .collaborators-overlay-user-label,
195
- .collaborators-overlay-user-cursor {
196
- transition: none;
197
- animation: none;
198
- }
199
- }
200
- `;
16
+ // Periodically recompute cursor positions to account for DOM layout
17
+ // changes that don't trigger awareness state updates (e.g. a collaborator
18
+ // applying formatting shifts text but the cursor's logical position is
19
+ // unchanged). Only active when remote cursors are visible.
20
+ const CURSOR_REDRAW_INTERVAL_MS = 10_000;
201
21
 
202
22
  interface OverlayProps {
203
23
  blockEditorDocument?: Document;
204
24
  postId: number | null;
205
25
  postType: string | null;
26
+ cursorRegistry?: CursorRegistry;
206
27
  }
207
28
 
208
29
  /**
@@ -212,12 +33,14 @@ interface OverlayProps {
212
33
  * @param props.blockEditorDocument - The block editor document.
213
34
  * @param props.postId - The ID of the post.
214
35
  * @param props.postType - The type of the post.
36
+ * @param props.cursorRegistry - The shared cursor registry.
215
37
  * @return The Overlay component.
216
38
  */
217
39
  export function Overlay( {
218
40
  blockEditorDocument,
219
41
  postId,
220
42
  postType,
43
+ cursorRegistry,
221
44
  }: OverlayProps ) {
222
45
  // Use state for the overlay element so that the hook re-runs once the ref is attached.
223
46
  const [ overlayElement, setOverlayElement ] =
@@ -227,13 +50,46 @@ export function Overlay( {
227
50
  overlayElement,
228
51
  blockEditorDocument ?? null,
229
52
  postId ?? null,
230
- postType ?? null
53
+ postType ?? null,
54
+ RERENDER_DELAY_MS
55
+ );
56
+
57
+ const { highlights, rerenderHighlightsAfterDelay } = useBlockHighlighting(
58
+ overlayElement,
59
+ blockEditorDocument ?? null,
60
+ postId ?? null,
61
+ postType ?? null,
62
+ RERENDER_DELAY_MS
231
63
  );
232
64
 
233
65
  // Detect layout changes on overlay (e.g. turning on "Show Template") and window
234
- // resizes, and re-render the cursors.
235
- const resizeObserverRef = useResizeObserver( rerenderCursorsAfterDelay );
236
- useEffect( rerenderCursorsAfterDelay, [ rerenderCursorsAfterDelay ] );
66
+ // resizes, and re-render the cursors and block highlights.
67
+ const onResize = useCallback( () => {
68
+ rerenderCursorsAfterDelay();
69
+ rerenderHighlightsAfterDelay();
70
+ }, [ rerenderCursorsAfterDelay, rerenderHighlightsAfterDelay ] );
71
+ const resizeObserverRef = useResizeObserver( onResize );
72
+
73
+ // Trigger the initial position computation on mount.
74
+ useEffect( () => {
75
+ const cleanupCursors = rerenderCursorsAfterDelay();
76
+ const cleanupHighlights = rerenderHighlightsAfterDelay();
77
+ return () => {
78
+ cleanupCursors();
79
+ cleanupHighlights();
80
+ };
81
+ }, [ rerenderCursorsAfterDelay, rerenderHighlightsAfterDelay ] );
82
+
83
+ useEffect( () => {
84
+ if ( cursors.length === 0 ) {
85
+ return;
86
+ }
87
+
88
+ return setDelayedInterval(
89
+ rerenderCursorsAfterDelay,
90
+ CURSOR_REDRAW_INTERVAL_MS
91
+ );
92
+ }, [ cursors.length, rerenderCursorsAfterDelay ] );
237
93
 
238
94
  // Merge the refs to use the same element for both overlay and resize observation
239
95
  const mergedRef = useMergeRefs< HTMLDivElement | null >( [
@@ -241,43 +97,109 @@ export function Overlay( {
241
97
  resizeObserverRef,
242
98
  ] );
243
99
 
244
- useBlockHighlighting(
245
- blockEditorDocument ?? null,
246
- postId ?? null,
247
- postType ?? null
100
+ // Track cursor element refs for registry registration.
101
+ const cursorRefsMap = useRef< Map< number, HTMLElement > >( new Map() );
102
+
103
+ // Keep the registry in sync whenever the rendered cursors change.
104
+ useEffect( () => {
105
+ if ( ! cursorRegistry ) {
106
+ return;
107
+ }
108
+ const refs = cursorRefsMap.current;
109
+ const currentIds = new Set( cursors.map( ( c ) => c.clientId ) );
110
+
111
+ // Unregister cursors that are no longer rendered.
112
+ for ( const id of refs.keys() ) {
113
+ if ( ! currentIds.has( id ) ) {
114
+ cursorRegistry.unregisterCursor( id );
115
+ refs.delete( id );
116
+ }
117
+ }
118
+
119
+ // Register or update cursors that are currently rendered.
120
+ for ( const [ id, el ] of refs.entries() ) {
121
+ cursorRegistry.registerCursor( id, el );
122
+ }
123
+
124
+ return () => cursorRegistry.removeAll();
125
+ }, [ cursors, cursorRegistry ] );
126
+
127
+ // Callback ref factory to capture each cursor's DOM element.
128
+ const setCursorRef = useCallback(
129
+ ( clientId: number ) => ( el: HTMLDivElement | null ) => {
130
+ if ( el ) {
131
+ cursorRefsMap.current.set( clientId, el );
132
+ } else {
133
+ cursorRefsMap.current.delete( clientId );
134
+ }
135
+ },
136
+ []
248
137
  );
249
138
 
250
139
  // This is a full overlay that covers the entire iframe document. Good for
251
140
  // scrollable elements like cursor indicators.
252
141
  return (
253
142
  <div className="collaborators-overlay-full" ref={ mergedRef }>
254
- <style>{ COLLABORATORS_OVERLAY_STYLES }</style>
143
+ <style>{ AVATAR_IFRAME_STYLES + OVERLAY_IFRAME_STYLES }</style>
255
144
  { cursors.map( ( cursor ) => (
256
- <div
257
- key={ cursor.clientId }
258
- className="collaborators-overlay-user"
259
- style={ {
260
- left: `${ cursor.x }px`,
261
- top: `${ cursor.y }px`,
262
- } }
263
- >
145
+ <div key={ cursor.clientId }>
146
+ { cursor.selectionRects?.map( ( rect, index ) => (
147
+ <div
148
+ key={ `${ cursor.clientId }-sel-${ index }` }
149
+ className="collaborators-overlay-selection-rect"
150
+ style={ {
151
+ left: `${ rect.x }px`,
152
+ top: `${ rect.y }px`,
153
+ width: `${ rect.width }px`,
154
+ height: `${ rect.height }px`,
155
+ backgroundColor: cursor.color,
156
+ } }
157
+ />
158
+ ) ) }
264
159
  <div
265
- className="collaborators-overlay-user-cursor"
160
+ ref={ setCursorRef( cursor.clientId ) }
161
+ className="collaborators-overlay-user"
266
162
  style={ {
267
- backgroundColor: cursor.color,
268
- height: `${ cursor.height }px`,
163
+ left: `${ cursor.x }px`,
164
+ top: `${ cursor.y }px`,
269
165
  } }
270
- />
271
- <Avatar
272
- className="collaborators-overlay-user-label"
273
- badge
274
- size="small"
275
- src={ cursor.avatarUrl }
276
- name={ cursor.userName }
277
- borderColor={ cursor.color }
278
- />
166
+ >
167
+ { ! cursor.isMe && (
168
+ <div
169
+ className="collaborators-overlay-user-cursor"
170
+ style={ {
171
+ backgroundColor: cursor.color,
172
+ height: `${ cursor.height }px`,
173
+ } }
174
+ />
175
+ ) }
176
+ <Avatar
177
+ className="collaborators-overlay-user-label"
178
+ variant="badge"
179
+ size="small"
180
+ src={ cursor.avatarUrl }
181
+ name={ cursor.userName }
182
+ label={ cursor.isMe ? __( 'You' ) : undefined }
183
+ borderColor={ cursor.color }
184
+ />
185
+ </div>
279
186
  </div>
280
187
  ) ) }
188
+ { highlights.map( ( highlight ) => (
189
+ <Avatar
190
+ key={ highlight.blockId }
191
+ className="collaborators-overlay-block-label"
192
+ variant="badge"
193
+ size="small"
194
+ src={ highlight.avatarUrl }
195
+ name={ highlight.userName }
196
+ borderColor={ highlight.color }
197
+ style={ {
198
+ left: `${ highlight.x }px`,
199
+ top: `${ highlight.y }px`,
200
+ } }
201
+ />
202
+ ) ) }
281
203
  </div>
282
204
  );
283
205
  }