@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
@@ -1,13 +1,15 @@
1
1
  // packages/editor/src/components/collaborators-overlay/use-block-highlighting.ts
2
2
  import {
3
- privateApis as coreDataPrivateApis,
4
- SelectionType
3
+ privateApis as coreDataPrivateApis
5
4
  } from "@wordpress/core-data";
6
- import { useEffect, useRef } from "@wordpress/element";
5
+ import { useEffect, useRef, useState } from "@wordpress/element";
7
6
  import { unlock } from "../../lock-unlock.mjs";
8
7
  import { getAvatarBorderColor } from "../collab-sidebar/utils.mjs";
8
+ import { getAvatarUrl } from "./get-avatar-url.mjs";
9
+ import { useDebouncedRecompute } from "./use-debounced-recompute.mjs";
9
10
  var { useActiveCollaborators, useResolvedSelection } = unlock(coreDataPrivateApis);
10
- function useBlockHighlighting(blockEditorDocument, postId, postType) {
11
+ var { SelectionType } = unlock(coreDataPrivateApis);
12
+ function useBlockHighlighting(overlayElement, blockEditorDocument, postId, postType, delayMs) {
11
13
  const highlightedBlockIds = useRef(/* @__PURE__ */ new Set());
12
14
  const userStates = useActiveCollaborators(
13
15
  postId ?? null,
@@ -17,12 +19,55 @@ function useBlockHighlighting(blockEditorDocument, postId, postType) {
17
19
  postId ?? null,
18
20
  postType ?? null
19
21
  );
22
+ const [highlights, setHighlights] = useState(
23
+ []
24
+ );
25
+ const [recomputeToken, rerenderHighlightsAfterDelay] = useDebouncedRecompute(delayMs);
20
26
  useEffect(() => {
21
- if (blockEditorDocument === null) {
27
+ if (!blockEditorDocument) {
28
+ setHighlights([]);
22
29
  return;
23
30
  }
24
- const unhighlightBlocks = (blockIds) => {
25
- blockIds.forEach((blockId) => {
31
+ const currentHighlightedIds = highlightedBlockIds.current;
32
+ const seen = /* @__PURE__ */ new Set();
33
+ const blocksToHighlight = userStates.filter((userState) => {
34
+ const isWholeBlockSelected = userState.editorState?.selection?.type === SelectionType.WholeBlock;
35
+ return !userState.isMe && isWholeBlockSelected;
36
+ }).map((userState) => {
37
+ let localClientId;
38
+ try {
39
+ ({ localClientId } = resolveSelection(
40
+ userState.editorState?.selection
41
+ ));
42
+ } catch {
43
+ return null;
44
+ }
45
+ if (!localClientId) {
46
+ return null;
47
+ }
48
+ return {
49
+ blockId: localClientId,
50
+ color: userState.isMe ? "var(--wp-admin-theme-color)" : getAvatarBorderColor(userState.collaboratorInfo.id),
51
+ userName: userState.collaboratorInfo.name,
52
+ avatarUrl: getAvatarUrl(
53
+ userState.collaboratorInfo.avatar_urls
54
+ )
55
+ };
56
+ }).filter((block) => {
57
+ if (!block) {
58
+ return false;
59
+ }
60
+ if (seen.has(block.blockId)) {
61
+ return false;
62
+ }
63
+ seen.add(block.blockId);
64
+ return true;
65
+ });
66
+ const selectedBlockIds = new Set(
67
+ blocksToHighlight.map((block) => block.blockId)
68
+ );
69
+ for (const blockId of currentHighlightedIds) {
70
+ if (!selectedBlockIds.has(blockId)) {
26
71
  const blockElement = getBlockElementById(
27
72
  blockEditorDocument,
28
73
  blockId
@@ -33,37 +78,13 @@ function useBlockHighlighting(blockEditorDocument, postId, postType) {
33
78
  "--collaborator-outline-color"
34
79
  );
35
80
  }
36
- highlightedBlockIds.current.delete(blockId);
37
- });
38
- };
39
- const blocksToHighlight = userStates.map((userState) => {
40
- const isWholeBlockSelected = userState.editorState?.selection?.type === SelectionType.WholeBlock;
41
- const shouldDrawUser = !userState.isMe;
42
- if (isWholeBlockSelected && shouldDrawUser) {
43
- const { localClientId } = resolveSelection(
44
- userState.editorState?.selection
45
- );
46
- if (!localClientId) {
47
- return null;
48
- }
49
- return {
50
- blockId: localClientId,
51
- color: getAvatarBorderColor(
52
- userState.collaboratorInfo.id
53
- )
54
- };
81
+ currentHighlightedIds.delete(blockId);
55
82
  }
56
- return null;
57
- }).filter((block) => block !== null);
58
- const selectedBlockIds = blocksToHighlight.map(
59
- (block) => block.blockId
60
- );
61
- const blocksIdsToUnhighlight = Array.from(
62
- highlightedBlockIds.current
63
- ).filter((blockId) => !selectedBlockIds.includes(blockId));
64
- unhighlightBlocks(blocksIdsToUnhighlight);
65
- blocksToHighlight.forEach((blockColorPair) => {
66
- const { color, blockId } = blockColorPair;
83
+ }
84
+ const results = [];
85
+ const overlayRect = overlayElement?.getBoundingClientRect() ?? null;
86
+ blocksToHighlight.forEach((block) => {
87
+ const { color, blockId, userName, avatarUrl } = block;
67
88
  const blockElement = getBlockElementById(
68
89
  blockEditorDocument,
69
90
  blockId
@@ -71,16 +92,43 @@ function useBlockHighlighting(blockEditorDocument, postId, postType) {
71
92
  if (!blockElement) {
72
93
  return;
73
94
  }
74
- if (blockElement) {
75
- blockElement.classList.add("is-collaborator-selected");
76
- blockElement.style.setProperty(
77
- "--collaborator-outline-color",
78
- color
79
- );
80
- highlightedBlockIds.current.add(blockId);
95
+ blockElement.classList.add("is-collaborator-selected");
96
+ blockElement.style.setProperty(
97
+ "--collaborator-outline-color",
98
+ color
99
+ );
100
+ currentHighlightedIds.add(blockId);
101
+ if (overlayRect) {
102
+ const blockRect = blockElement.getBoundingClientRect();
103
+ results.push({
104
+ blockId,
105
+ userName,
106
+ avatarUrl,
107
+ color,
108
+ x: blockRect.left - overlayRect.left,
109
+ y: blockRect.top - overlayRect.top
110
+ });
81
111
  }
82
112
  });
83
- }, [userStates, blockEditorDocument, resolveSelection]);
113
+ setHighlights(results);
114
+ return () => {
115
+ for (const blockId of currentHighlightedIds) {
116
+ const el = getBlockElementById(blockEditorDocument, blockId);
117
+ if (el) {
118
+ el.classList.remove("is-collaborator-selected");
119
+ el.style.removeProperty("--collaborator-outline-color");
120
+ }
121
+ }
122
+ currentHighlightedIds.clear();
123
+ };
124
+ }, [
125
+ userStates,
126
+ blockEditorDocument,
127
+ overlayElement,
128
+ recomputeToken,
129
+ resolveSelection
130
+ ]);
131
+ return { highlights, rerenderHighlightsAfterDelay };
84
132
  }
85
133
  var getBlockElementById = (blockEditorDocument, blockId) => {
86
134
  return blockEditorDocument.querySelector(`[data-block="${blockId}"]`);
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/components/collaborators-overlay/use-block-highlighting.ts"],
4
- "sourcesContent": ["/**\n * WordPress dependencies\n */\nimport {\n\tprivateApis as coreDataPrivateApis,\n\tSelectionType,\n} from '@wordpress/core-data';\nimport { useEffect, useRef } from '@wordpress/element';\n\n/**\n * Internal dependencies\n */\nimport { unlock } from '../../lock-unlock';\nimport { getAvatarBorderColor } from '../collab-sidebar/utils';\n\nconst { useActiveCollaborators, useResolvedSelection } =\n\tunlock( coreDataPrivateApis );\n\n/**\n * Custom hook for highlighting selected blocks in the editor\n * @param blockEditorDocument - Ref to the block editor document, used to directly style block elements.\n * @param postId - The ID of the post\n * @param postType - The type of the post\n */\nexport function useBlockHighlighting(\n\tblockEditorDocument: Document | null,\n\tpostId: number | null,\n\tpostType: string | null\n) {\n\tconst highlightedBlockIds = useRef< Set< string > >( new Set() );\n\tconst userStates = useActiveCollaborators(\n\t\tpostId ?? null,\n\t\tpostType ?? null\n\t);\n\tconst resolveSelection = useResolvedSelection(\n\t\tpostId ?? null,\n\t\tpostType ?? null\n\t);\n\n\t// Draw block highlights\n\tuseEffect( () => {\n\t\t// Don't do anything if editor is not rendered yet.\n\t\tif ( blockEditorDocument === null ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst unhighlightBlocks = ( blockIds: string[] ) => {\n\t\t\tblockIds.forEach( ( blockId ) => {\n\t\t\t\tconst blockElement = getBlockElementById(\n\t\t\t\t\tblockEditorDocument,\n\t\t\t\t\tblockId\n\t\t\t\t);\n\n\t\t\t\tif ( blockElement ) {\n\t\t\t\t\tblockElement.classList.remove( 'is-collaborator-selected' );\n\t\t\t\t\tblockElement.style.removeProperty(\n\t\t\t\t\t\t'--collaborator-outline-color'\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\thighlightedBlockIds.current.delete( blockId );\n\t\t\t} );\n\t\t};\n\n\t\tconst blocksToHighlight = userStates\n\t\t\t.map( ( userState: any ) => {\n\t\t\t\tconst isWholeBlockSelected =\n\t\t\t\t\tuserState.editorState?.selection?.type ===\n\t\t\t\t\tSelectionType.WholeBlock;\n\t\t\t\tconst shouldDrawUser = ! userState.isMe;\n\n\t\t\t\tif ( isWholeBlockSelected && shouldDrawUser ) {\n\t\t\t\t\tconst { localClientId } = resolveSelection(\n\t\t\t\t\t\tuserState.editorState?.selection\n\t\t\t\t\t);\n\n\t\t\t\t\tif ( ! localClientId ) {\n\t\t\t\t\t\treturn null;\n\t\t\t\t\t}\n\n\t\t\t\t\treturn {\n\t\t\t\t\t\tblockId: localClientId,\n\t\t\t\t\t\tcolor: getAvatarBorderColor(\n\t\t\t\t\t\t\tuserState.collaboratorInfo.id\n\t\t\t\t\t\t),\n\t\t\t\t\t};\n\t\t\t\t}\n\n\t\t\t\treturn null;\n\t\t\t} )\n\t\t\t.filter( ( block: any ) => block !== null );\n\n\t\t// Unhighlight blocks that are no longer highlighted.\n\t\tconst selectedBlockIds = blocksToHighlight.map(\n\t\t\t( block: any ) => block.blockId\n\t\t);\n\t\tconst blocksIdsToUnhighlight = Array.from(\n\t\t\thighlightedBlockIds.current\n\t\t).filter( ( blockId ) => ! selectedBlockIds.includes( blockId ) );\n\n\t\tunhighlightBlocks( blocksIdsToUnhighlight );\n\n\t\t// Highlight blocks that are currently highlighted.\n\t\tblocksToHighlight.forEach( ( blockColorPair: any ) => {\n\t\t\tconst { color, blockId } = blockColorPair;\n\t\t\tconst blockElement = getBlockElementById(\n\t\t\t\tblockEditorDocument,\n\t\t\t\tblockId\n\t\t\t);\n\n\t\t\tif ( ! blockElement ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif ( blockElement ) {\n\t\t\t\tblockElement.classList.add( 'is-collaborator-selected' );\n\t\t\t\tblockElement.style.setProperty(\n\t\t\t\t\t'--collaborator-outline-color',\n\t\t\t\t\tcolor\n\t\t\t\t);\n\t\t\t\thighlightedBlockIds.current.add( blockId );\n\t\t\t}\n\t\t} );\n\t}, [ userStates, blockEditorDocument, resolveSelection ] );\n}\n\nconst getBlockElementById = (\n\tblockEditorDocument: Document,\n\tblockId: string\n): HTMLElement | null => {\n\treturn blockEditorDocument.querySelector( `[data-block=\"${ blockId }\"]` );\n};\n"],
5
- "mappings": ";AAGA;AAAA,EACC,eAAe;AAAA,EACf;AAAA,OACM;AACP,SAAS,WAAW,cAAc;AAKlC,SAAS,cAAc;AACvB,SAAS,4BAA4B;AAErC,IAAM,EAAE,wBAAwB,qBAAqB,IACpD,OAAQ,mBAAoB;AAQtB,SAAS,qBACf,qBACA,QACA,UACC;AACD,QAAM,sBAAsB,OAAyB,oBAAI,IAAI,CAAE;AAC/D,QAAM,aAAa;AAAA,IAClB,UAAU;AAAA,IACV,YAAY;AAAA,EACb;AACA,QAAM,mBAAmB;AAAA,IACxB,UAAU;AAAA,IACV,YAAY;AAAA,EACb;AAGA,YAAW,MAAM;AAEhB,QAAK,wBAAwB,MAAO;AACnC;AAAA,IACD;AAEA,UAAM,oBAAoB,CAAE,aAAwB;AACnD,eAAS,QAAS,CAAE,YAAa;AAChC,cAAM,eAAe;AAAA,UACpB;AAAA,UACA;AAAA,QACD;AAEA,YAAK,cAAe;AACnB,uBAAa,UAAU,OAAQ,0BAA2B;AAC1D,uBAAa,MAAM;AAAA,YAClB;AAAA,UACD;AAAA,QACD;AAEA,4BAAoB,QAAQ,OAAQ,OAAQ;AAAA,MAC7C,CAAE;AAAA,IACH;AAEA,UAAM,oBAAoB,WACxB,IAAK,CAAE,cAAoB;AAC3B,YAAM,uBACL,UAAU,aAAa,WAAW,SAClC,cAAc;AACf,YAAM,iBAAiB,CAAE,UAAU;AAEnC,UAAK,wBAAwB,gBAAiB;AAC7C,cAAM,EAAE,cAAc,IAAI;AAAA,UACzB,UAAU,aAAa;AAAA,QACxB;AAEA,YAAK,CAAE,eAAgB;AACtB,iBAAO;AAAA,QACR;AAEA,eAAO;AAAA,UACN,SAAS;AAAA,UACT,OAAO;AAAA,YACN,UAAU,iBAAiB;AAAA,UAC5B;AAAA,QACD;AAAA,MACD;AAEA,aAAO;AAAA,IACR,CAAE,EACD,OAAQ,CAAE,UAAgB,UAAU,IAAK;AAG3C,UAAM,mBAAmB,kBAAkB;AAAA,MAC1C,CAAE,UAAgB,MAAM;AAAA,IACzB;AACA,UAAM,yBAAyB,MAAM;AAAA,MACpC,oBAAoB;AAAA,IACrB,EAAE,OAAQ,CAAE,YAAa,CAAE,iBAAiB,SAAU,OAAQ,CAAE;AAEhE,sBAAmB,sBAAuB;AAG1C,sBAAkB,QAAS,CAAE,mBAAyB;AACrD,YAAM,EAAE,OAAO,QAAQ,IAAI;AAC3B,YAAM,eAAe;AAAA,QACpB;AAAA,QACA;AAAA,MACD;AAEA,UAAK,CAAE,cAAe;AACrB;AAAA,MACD;AAEA,UAAK,cAAe;AACnB,qBAAa,UAAU,IAAK,0BAA2B;AACvD,qBAAa,MAAM;AAAA,UAClB;AAAA,UACA;AAAA,QACD;AACA,4BAAoB,QAAQ,IAAK,OAAQ;AAAA,MAC1C;AAAA,IACD,CAAE;AAAA,EACH,GAAG,CAAE,YAAY,qBAAqB,gBAAiB,CAAE;AAC1D;AAEA,IAAM,sBAAsB,CAC3B,qBACA,YACwB;AACxB,SAAO,oBAAoB,cAAe,gBAAiB,OAAQ,IAAK;AACzE;",
4
+ "sourcesContent": ["/**\n * WordPress dependencies\n */\nimport {\n\tprivateApis as coreDataPrivateApis,\n\ttype CoreDataPrivateApis,\n\ttype PostEditorAwarenessState as ActiveCollaborator,\n} from '@wordpress/core-data';\nimport { useEffect, useRef, useState } from '@wordpress/element';\n\n/**\n * Internal dependencies\n */\nimport { unlock } from '../../lock-unlock';\nimport { getAvatarBorderColor } from '../collab-sidebar/utils';\nimport { getAvatarUrl } from './get-avatar-url';\nimport { useDebouncedRecompute } from './use-debounced-recompute';\n\nconst { useActiveCollaborators, useResolvedSelection } =\n\tunlock( coreDataPrivateApis );\nconst { SelectionType } = unlock( coreDataPrivateApis ) as Pick<\n\tCoreDataPrivateApis,\n\t'SelectionType'\n>;\n\nexport interface BlockHighlightData {\n\tblockId: string;\n\tuserName: string;\n\tavatarUrl?: string;\n\tcolor: string;\n\tx: number;\n\ty: number;\n}\n\n/**\n * Custom hook for highlighting selected blocks in the editor and computing\n * their positions for rendering avatar labels in the overlay.\n *\n * @param overlayElement - The overlay element used as position reference.\n * @param blockEditorDocument - Ref to the block editor document.\n * @param postId - The ID of the post.\n * @param postType - The type of the post.\n * @param delayMs - Milliseconds to wait before recomputing highlight positions.\n * @return Highlight data for rendering and a delayed recompute function.\n */\nexport function useBlockHighlighting(\n\toverlayElement: HTMLElement | null,\n\tblockEditorDocument: Document | null,\n\tpostId: number | null,\n\tpostType: string | null,\n\tdelayMs: number\n): {\n\thighlights: BlockHighlightData[];\n\trerenderHighlightsAfterDelay: () => () => void;\n} {\n\tconst highlightedBlockIds = useRef< Set< string > >( new Set() );\n\tconst userStates: ActiveCollaborator[] = useActiveCollaborators(\n\t\tpostId ?? null,\n\t\tpostType ?? null\n\t);\n\tconst resolveSelection = useResolvedSelection(\n\t\tpostId ?? null,\n\t\tpostType ?? null\n\t);\n\n\tconst [ highlights, setHighlights ] = useState< BlockHighlightData[] >(\n\t\t[]\n\t);\n\n\t// Bump this counter to force the effect to re-run (e.g. after a layout shift).\n\tconst [ recomputeToken, rerenderHighlightsAfterDelay ] =\n\t\tuseDebouncedRecompute( delayMs );\n\n\t// All DOM mutations and position computations live inside useEffect.\n\tuseEffect( () => {\n\t\tif ( ! blockEditorDocument ) {\n\t\t\tsetHighlights( [] );\n\t\t\treturn;\n\t\t}\n\n\t\t// Capture the ref value so the cleanup closure sees the same Set\n\t\t// even if a later render replaces it.\n\t\tconst currentHighlightedIds = highlightedBlockIds.current;\n\n\t\t// Deduplicate by blockId \u2014 when multiple collaborators select the\n\t\t// same block, only the first one gets the highlight and avatar label.\n\t\tconst seen = new Set< string >();\n\t\tconst blocksToHighlight = userStates\n\t\t\t.filter( ( userState: ActiveCollaborator ) => {\n\t\t\t\tconst isWholeBlockSelected =\n\t\t\t\t\tuserState.editorState?.selection?.type ===\n\t\t\t\t\tSelectionType.WholeBlock;\n\n\t\t\t\treturn ! userState.isMe && isWholeBlockSelected;\n\t\t\t} )\n\t\t\t.map( ( userState ) => {\n\t\t\t\tlet localClientId;\n\t\t\t\ttry {\n\t\t\t\t\t( { localClientId } = resolveSelection(\n\t\t\t\t\t\tuserState.editorState?.selection\n\t\t\t\t\t) );\n\t\t\t\t} catch {\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\n\t\t\t\tif ( ! localClientId ) {\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\n\t\t\t\treturn {\n\t\t\t\t\tblockId: localClientId,\n\t\t\t\t\tcolor: userState.isMe\n\t\t\t\t\t\t? 'var(--wp-admin-theme-color)'\n\t\t\t\t\t\t: getAvatarBorderColor( userState.collaboratorInfo.id ),\n\t\t\t\t\tuserName: userState.collaboratorInfo.name,\n\t\t\t\t\tavatarUrl: getAvatarUrl(\n\t\t\t\t\t\tuserState.collaboratorInfo.avatar_urls\n\t\t\t\t\t),\n\t\t\t\t};\n\t\t\t} )\n\t\t\t.filter( ( block ): block is NonNullable< typeof block > => {\n\t\t\t\tif ( ! block ) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\tif ( seen.has( block.blockId ) ) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\tseen.add( block.blockId );\n\t\t\t\treturn true;\n\t\t\t} );\n\n\t\t// Unhighlight blocks that are no longer selected.\n\t\tconst selectedBlockIds = new Set(\n\t\t\tblocksToHighlight.map( ( block ) => block.blockId )\n\t\t);\n\n\t\tfor ( const blockId of currentHighlightedIds ) {\n\t\t\tif ( ! selectedBlockIds.has( blockId ) ) {\n\t\t\t\tconst blockElement = getBlockElementById(\n\t\t\t\t\tblockEditorDocument,\n\t\t\t\t\tblockId\n\t\t\t\t);\n\n\t\t\t\tif ( blockElement ) {\n\t\t\t\t\tblockElement.classList.remove( 'is-collaborator-selected' );\n\t\t\t\t\tblockElement.style.removeProperty(\n\t\t\t\t\t\t'--collaborator-outline-color'\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\tcurrentHighlightedIds.delete( blockId );\n\t\t\t}\n\t\t}\n\n\t\t// Highlight blocks and compute positions for avatar labels.\n\t\tconst results: BlockHighlightData[] = [];\n\t\tconst overlayRect = overlayElement?.getBoundingClientRect() ?? null;\n\n\t\tblocksToHighlight.forEach( ( block ) => {\n\t\t\tconst { color, blockId, userName, avatarUrl } = block;\n\t\t\tconst blockElement = getBlockElementById(\n\t\t\t\tblockEditorDocument,\n\t\t\t\tblockId\n\t\t\t);\n\n\t\t\tif ( ! blockElement ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tblockElement.classList.add( 'is-collaborator-selected' );\n\t\t\tblockElement.style.setProperty(\n\t\t\t\t'--collaborator-outline-color',\n\t\t\t\tcolor\n\t\t\t);\n\t\t\tcurrentHighlightedIds.add( blockId );\n\n\t\t\tif ( overlayRect ) {\n\t\t\t\tconst blockRect = blockElement.getBoundingClientRect();\n\n\t\t\t\tresults.push( {\n\t\t\t\t\tblockId,\n\t\t\t\t\tuserName,\n\t\t\t\t\tavatarUrl,\n\t\t\t\t\tcolor,\n\t\t\t\t\tx: blockRect.left - overlayRect.left,\n\t\t\t\t\ty: blockRect.top - overlayRect.top,\n\t\t\t\t} );\n\t\t\t}\n\t\t} );\n\n\t\tsetHighlights( results );\n\n\t\t// Clean up all highlights on unmount.\n\t\treturn () => {\n\t\t\tfor ( const blockId of currentHighlightedIds ) {\n\t\t\t\tconst el = getBlockElementById( blockEditorDocument, blockId );\n\t\t\t\tif ( el ) {\n\t\t\t\t\tel.classList.remove( 'is-collaborator-selected' );\n\t\t\t\t\tel.style.removeProperty( '--collaborator-outline-color' );\n\t\t\t\t}\n\t\t\t}\n\t\t\tcurrentHighlightedIds.clear();\n\t\t};\n\t}, [\n\t\tuserStates,\n\t\tblockEditorDocument,\n\t\toverlayElement,\n\t\trecomputeToken,\n\t\tresolveSelection,\n\t] );\n\n\treturn { highlights, rerenderHighlightsAfterDelay };\n}\n\nconst getBlockElementById = (\n\tblockEditorDocument: Document,\n\tblockId: string\n): HTMLElement | null => {\n\treturn blockEditorDocument.querySelector( `[data-block=\"${ blockId }\"]` );\n};\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -0,0 +1,24 @@
1
+ // packages/editor/src/components/collaborators-overlay/use-debounced-recompute.ts
2
+ import { useCallback, useRef, useState } from "@wordpress/element";
3
+ function useDebouncedRecompute(delayMs) {
4
+ const [recomputeToken, setRecomputeToken] = useState(0);
5
+ const timeoutRef = useRef(null);
6
+ const rerenderAfterDelay = useCallback(() => {
7
+ if (timeoutRef.current) {
8
+ clearTimeout(timeoutRef.current);
9
+ }
10
+ timeoutRef.current = setTimeout(() => {
11
+ setRecomputeToken((t) => t + 1);
12
+ }, delayMs);
13
+ return () => {
14
+ if (timeoutRef.current) {
15
+ clearTimeout(timeoutRef.current);
16
+ }
17
+ };
18
+ }, [delayMs]);
19
+ return [recomputeToken, rerenderAfterDelay];
20
+ }
21
+ export {
22
+ useDebouncedRecompute
23
+ };
24
+ //# sourceMappingURL=use-debounced-recompute.mjs.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/components/collaborators-overlay/use-debounced-recompute.ts"],
4
+ "sourcesContent": ["import { useCallback, useRef, useState } from '@wordpress/element';\n\n/**\n * Returns a recompute token and a debounced callback that bumps it.\n * Rapid successive calls cancel the previous pending timeout so only one\n * recompute fires, `delayMs` after the last call.\n *\n * @param delayMs - Milliseconds to wait before bumping the recompute token.\n * @return A tuple of [recomputeToken, rerenderAfterDelay].\n */\nexport function useDebouncedRecompute(\n\tdelayMs: number\n): [ number, () => () => void ] {\n\tconst [ recomputeToken, setRecomputeToken ] = useState( 0 );\n\tconst timeoutRef = useRef< ReturnType< typeof setTimeout > | null >( null );\n\n\tconst rerenderAfterDelay = useCallback( () => {\n\t\tif ( timeoutRef.current ) {\n\t\t\tclearTimeout( timeoutRef.current );\n\t\t}\n\t\ttimeoutRef.current = setTimeout( () => {\n\t\t\tsetRecomputeToken( ( t ) => t + 1 );\n\t\t}, delayMs );\n\t\treturn () => {\n\t\t\tif ( timeoutRef.current ) {\n\t\t\t\tclearTimeout( timeoutRef.current );\n\t\t\t}\n\t\t};\n\t}, [ delayMs ] );\n\n\treturn [ recomputeToken, rerenderAfterDelay ];\n}\n"],
5
+ "mappings": ";AAAA,SAAS,aAAa,QAAQ,gBAAgB;AAUvC,SAAS,sBACf,SAC+B;AAC/B,QAAM,CAAE,gBAAgB,iBAAkB,IAAI,SAAU,CAAE;AAC1D,QAAM,aAAa,OAAkD,IAAK;AAE1E,QAAM,qBAAqB,YAAa,MAAM;AAC7C,QAAK,WAAW,SAAU;AACzB,mBAAc,WAAW,OAAQ;AAAA,IAClC;AACA,eAAW,UAAU,WAAY,MAAM;AACtC,wBAAmB,CAAE,MAAO,IAAI,CAAE;AAAA,IACnC,GAAG,OAAQ;AACX,WAAO,MAAM;AACZ,UAAK,WAAW,SAAU;AACzB,qBAAc,WAAW,OAAQ;AAAA,MAClC;AAAA,IACD;AAAA,EACD,GAAG,CAAE,OAAQ,CAAE;AAEf,SAAO,CAAE,gBAAgB,kBAAmB;AAC7C;",
6
+ "names": []
7
+ }
@@ -1,14 +1,16 @@
1
1
  // packages/editor/src/components/collaborators-overlay/use-render-cursors.ts
2
- import {
3
- privateApis as coreDataPrivateApis,
4
- SelectionType
5
- } from "@wordpress/core-data";
6
- import { useEffect, useMemo, useState } from "@wordpress/element";
2
+ import { privateApis as coreDataPrivateApis } from "@wordpress/core-data";
3
+ import { useSelect } from "@wordpress/data";
4
+ import { useEffect, useState } from "@wordpress/element";
5
+ import { store as preferencesStore } from "@wordpress/preferences";
7
6
  import { unlock } from "../../lock-unlock.mjs";
8
7
  import { getAvatarUrl } from "./get-avatar-url.mjs";
9
8
  import { getAvatarBorderColor } from "../collab-sidebar/utils.mjs";
9
+ import { computeSelectionVisual } from "./compute-selection.mjs";
10
+ import { useDebouncedRecompute } from "./use-debounced-recompute.mjs";
10
11
  var { useActiveCollaborators, useResolvedSelection } = unlock(coreDataPrivateApis);
11
- function useRenderCursors(overlayElement, blockEditorDocument, postId, postType) {
12
+ var { SelectionType } = unlock(coreDataPrivateApis);
13
+ function useRenderCursors(overlayElement, blockEditorDocument, postId, postType, delayMs) {
12
14
  const sortedUsers = useActiveCollaborators(
13
15
  postId ?? null,
14
16
  postType ?? null
@@ -17,191 +19,96 @@ function useRenderCursors(overlayElement, blockEditorDocument, postId, postType)
17
19
  postId ?? null,
18
20
  postType ?? null
19
21
  );
22
+ const showOwnCursor = useSelect(
23
+ (select) => select(preferencesStore).get("core", "showCollaborationCursor"),
24
+ []
25
+ );
20
26
  const [cursorPositions, setCursorPositions] = useState(
21
27
  []
22
28
  );
23
- const computeCursors = useMemo(
24
- () => () => {
25
- if (!overlayElement || !blockEditorDocument) {
26
- setCursorPositions([]);
29
+ const [recomputeToken, rerenderCursorsAfterDelay] = useDebouncedRecompute(delayMs);
30
+ useEffect(() => {
31
+ if (!overlayElement || !blockEditorDocument) {
32
+ setCursorPositions([]);
33
+ return;
34
+ }
35
+ const overlayRect = overlayElement.getBoundingClientRect();
36
+ const overlayContext = {
37
+ editorDocument: blockEditorDocument,
38
+ overlayRect
39
+ };
40
+ const results = [];
41
+ const hasOtherCollaborators = sortedUsers.some(
42
+ (u) => !u.isMe
43
+ );
44
+ sortedUsers.forEach((user) => {
45
+ if (user.isMe && (!showOwnCursor || !hasOtherCollaborators)) {
27
46
  return;
28
47
  }
29
- const results = [];
30
- sortedUsers.forEach((user) => {
31
- if (user.isMe) {
48
+ const selection = user.editorState?.selection ?? {
49
+ type: SelectionType.None
50
+ };
51
+ let start = {
52
+ richTextOffset: null,
53
+ localClientId: null
54
+ };
55
+ let end;
56
+ if (selection.type === SelectionType.Cursor) {
57
+ try {
58
+ start = resolveSelection(selection);
59
+ } catch {
32
60
  return;
33
61
  }
34
- const selection = user.editorState?.selection ?? {
35
- type: SelectionType.None
36
- };
37
- const userName = user.collaboratorInfo.name;
38
- const clientId = user.clientId;
39
- const color = getAvatarBorderColor(user.collaboratorInfo.id);
40
- const avatarUrl = getAvatarUrl(
41
- user.collaboratorInfo.avatar_urls
42
- );
43
- let coords = null;
44
- if (selection.type === SelectionType.None) {
45
- } else if (selection.type === SelectionType.WholeBlock) {
46
- } else if (selection.type === SelectionType.Cursor) {
47
- const { textIndex, localClientId } = resolveSelection(selection);
48
- if (localClientId) {
49
- coords = getCursorPosition(
50
- textIndex,
51
- localClientId,
52
- blockEditorDocument,
53
- overlayElement
54
- );
55
- }
56
- } else if (selection.type === SelectionType.SelectionInOneBlock || selection.type === SelectionType.SelectionInMultipleBlocks) {
57
- const { textIndex, localClientId } = resolveSelection({
62
+ } else if (selection.type === SelectionType.SelectionInOneBlock || selection.type === SelectionType.SelectionInMultipleBlocks) {
63
+ try {
64
+ start = resolveSelection({
58
65
  type: SelectionType.Cursor,
59
66
  cursorPosition: selection.cursorStartPosition
60
67
  });
61
- if (localClientId) {
62
- coords = getCursorPosition(
63
- textIndex,
64
- localClientId,
65
- blockEditorDocument,
66
- overlayElement
67
- );
68
- }
69
- }
70
- if (coords) {
71
- results.push({
72
- userName,
73
- clientId,
74
- color,
75
- avatarUrl,
76
- ...coords
68
+ end = resolveSelection({
69
+ type: SelectionType.Cursor,
70
+ cursorPosition: selection.cursorEndPosition
77
71
  });
72
+ } catch {
73
+ return;
78
74
  }
79
- });
80
- setCursorPositions(results);
81
- },
82
- [blockEditorDocument, resolveSelection, overlayElement, sortedUsers]
83
- );
84
- useEffect(computeCursors, [computeCursors]);
85
- const rerenderCursorsAfterDelay = useMemo(
86
- () => () => {
87
- const timeout = setTimeout(computeCursors, 500);
88
- return () => clearTimeout(timeout);
89
- },
90
- [computeCursors]
91
- );
92
- return { cursors: cursorPositions, rerenderCursorsAfterDelay };
93
- }
94
- var getCursorPosition = (absolutePositionIndex, blockId, editorDocument, overlay) => {
95
- if (absolutePositionIndex === null) {
96
- return null;
97
- }
98
- const blockElement = editorDocument.querySelector(
99
- `[data-block="${blockId}"]`
100
- );
101
- if (!blockElement) {
102
- return null;
103
- }
104
- return getOffsetPositionInBlock(
105
- blockElement,
106
- absolutePositionIndex,
107
- editorDocument,
108
- overlay
109
- ) ?? null;
110
- };
111
- var getOffsetPositionInBlock = (blockElement, charOffset, editorDocument, overlay) => {
112
- const { node, offset } = findInnerBlockOffset(
113
- blockElement,
114
- charOffset,
115
- editorDocument
116
- );
117
- const cursorRange = editorDocument.createRange();
118
- try {
119
- cursorRange.setStart(node, offset);
120
- } catch (error) {
121
- return null;
122
- }
123
- cursorRange.collapse(true);
124
- const cursorRect = cursorRange.getBoundingClientRect();
125
- const overlayRect = overlay.getBoundingClientRect();
126
- const blockRect = blockElement.getBoundingClientRect();
127
- let cursorX = 0;
128
- let cursorY = 0;
129
- if (cursorRect.x === 0 && cursorRect.y === 0 && cursorRect.width === 0 && cursorRect.height === 0) {
130
- cursorX = blockRect.left - overlayRect.left;
131
- cursorY = blockRect.top - overlayRect.top;
132
- } else {
133
- cursorX = cursorRect.left - overlayRect.left;
134
- cursorY = cursorRect.top - overlayRect.top;
135
- }
136
- let cursorHeight = cursorRect.height;
137
- if (cursorHeight === 0) {
138
- cursorHeight = parseInt(
139
- window.getComputedStyle(blockElement).lineHeight,
140
- 10
141
- ) || blockRect.height;
142
- }
143
- return {
144
- x: cursorX,
145
- y: cursorY,
146
- height: cursorHeight
147
- };
148
- };
149
- var MAX_NODE_OFFSET_COUNT = 1e3;
150
- var findInnerBlockOffset = (blockElement, offset, editorDocument) => {
151
- const treeWalker = editorDocument.createTreeWalker(
152
- blockElement,
153
- NodeFilter.SHOW_TEXT | NodeFilter.SHOW_ELEMENT
154
- // eslint-disable-line no-bitwise
155
- );
156
- let currentOffset = 0;
157
- let lastTextNode = null;
158
- let node = null;
159
- let nodeCount = 1;
160
- while (node = treeWalker.nextNode()) {
161
- nodeCount++;
162
- if (nodeCount > MAX_NODE_OFFSET_COUNT) {
163
- if (lastTextNode) {
164
- return { node: lastTextNode, offset: 0 };
165
75
  }
166
- return { node: blockElement, offset: 0 };
167
- }
168
- const nodeLength = node.nodeValue?.length ?? 0;
169
- if (node.nodeType === Node.ELEMENT_NODE) {
170
- if (node.nodeName === "BR") {
171
- if (currentOffset + 1 >= offset) {
172
- const nodeAfterBr = treeWalker.nextNode();
173
- if (nodeAfterBr?.nodeType === Node.TEXT_NODE) {
174
- return { node: nodeAfterBr, offset: 0 };
175
- } else if (lastTextNode) {
176
- return {
177
- node: lastTextNode,
178
- offset: lastTextNode.nodeValue?.length ?? 0
179
- };
180
- }
181
- return { node: blockElement, offset: 0 };
76
+ const userName = user.collaboratorInfo.name;
77
+ const clientId = user.clientId;
78
+ const color = user.isMe ? "var(--wp-admin-theme-color)" : getAvatarBorderColor(user.collaboratorInfo.id);
79
+ const avatarUrl = getAvatarUrl(user.collaboratorInfo.avatar_urls);
80
+ const selectionVisual = computeSelectionVisual(
81
+ selection,
82
+ start,
83
+ end,
84
+ overlayContext
85
+ );
86
+ if (selectionVisual.coords) {
87
+ const cursorData = {
88
+ userName,
89
+ clientId,
90
+ color,
91
+ avatarUrl,
92
+ isMe: user.isMe,
93
+ ...selectionVisual.coords
94
+ };
95
+ if (selectionVisual.selectionRects) {
96
+ cursorData.selectionRects = selectionVisual.selectionRects;
182
97
  }
183
- currentOffset += 1;
184
- continue;
185
- } else {
186
- continue;
98
+ results.push(cursorData);
187
99
  }
188
- }
189
- if (nodeLength === 0) {
190
- continue;
191
- }
192
- if (currentOffset + nodeLength >= offset) {
193
- return { node, offset: offset - currentOffset };
194
- }
195
- currentOffset += nodeLength;
196
- if (node.nodeType === Node.TEXT_NODE) {
197
- lastTextNode = node;
198
- }
199
- }
200
- if (lastTextNode && lastTextNode.nodeValue?.length) {
201
- return { node: lastTextNode, offset: lastTextNode.nodeValue.length };
202
- }
203
- return { node: blockElement, offset: 0 };
204
- };
100
+ });
101
+ setCursorPositions(results);
102
+ }, [
103
+ blockEditorDocument,
104
+ resolveSelection,
105
+ overlayElement,
106
+ sortedUsers,
107
+ showOwnCursor,
108
+ recomputeToken
109
+ ]);
110
+ return { cursors: cursorPositions, rerenderCursorsAfterDelay };
111
+ }
205
112
  export {
206
113
  useRenderCursors
207
114
  };
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/components/collaborators-overlay/use-render-cursors.ts"],
4
- "sourcesContent": ["import {\n\tprivateApis as coreDataPrivateApis,\n\tSelectionType,\n} from '@wordpress/core-data';\nimport { useEffect, useMemo, useState } from '@wordpress/element';\n\nimport { unlock } from '../../lock-unlock';\nimport { getAvatarUrl } from './get-avatar-url';\nimport { getAvatarBorderColor } from '../collab-sidebar/utils';\n\nconst { useActiveCollaborators, useResolvedSelection } =\n\tunlock( coreDataPrivateApis );\n\nexport interface CursorData {\n\tuserName: string;\n\tclientId: number;\n\tcolor: string;\n\tavatarUrl?: string;\n\tx: number;\n\ty: number;\n\theight: number;\n}\n\n/**\n * Custom hook that computes cursor positions for each remote user in the editor.\n *\n * @param overlayElement - The overlay element\n * @param blockEditorDocument - The block editor document\n * @param postId - The ID of the post\n * @param postType - The type of the post\n * @return An array of cursor data for rendering, and a function to trigger a delayed recompute.\n */\nexport function useRenderCursors(\n\toverlayElement: HTMLElement | null,\n\tblockEditorDocument: Document | null,\n\tpostId: number | null,\n\tpostType: string | null\n): { cursors: CursorData[]; rerenderCursorsAfterDelay: () => () => void } {\n\tconst sortedUsers = useActiveCollaborators(\n\t\tpostId ?? null,\n\t\tpostType ?? null\n\t);\n\tconst resolveSelection = useResolvedSelection(\n\t\tpostId ?? null,\n\t\tpostType ?? null\n\t);\n\n\tconst [ cursorPositions, setCursorPositions ] = useState< CursorData[] >(\n\t\t[]\n\t);\n\n\tconst computeCursors = useMemo(\n\t\t() => () => {\n\t\t\tif ( ! overlayElement || ! blockEditorDocument ) {\n\t\t\t\tsetCursorPositions( [] );\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst results: CursorData[] = [];\n\n\t\t\tsortedUsers.forEach( ( user: any ) => {\n\t\t\t\tif ( user.isMe ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst selection = user.editorState?.selection ?? {\n\t\t\t\t\ttype: SelectionType.None,\n\t\t\t\t};\n\t\t\t\tconst userName = user.collaboratorInfo.name;\n\t\t\t\tconst clientId = user.clientId;\n\t\t\t\tconst color = getAvatarBorderColor( user.collaboratorInfo.id );\n\t\t\t\tconst avatarUrl = getAvatarUrl(\n\t\t\t\t\tuser.collaboratorInfo.avatar_urls\n\t\t\t\t);\n\n\t\t\t\tlet coords: {\n\t\t\t\t\tx: number;\n\t\t\t\t\ty: number;\n\t\t\t\t\theight: number;\n\t\t\t\t} | null = null;\n\n\t\t\t\tif ( selection.type === SelectionType.None ) {\n\t\t\t\t\t// Nothing selected.\n\t\t\t\t} else if ( selection.type === SelectionType.WholeBlock ) {\n\t\t\t\t\t// Don't draw a cursor for a whole block selection.\n\t\t\t\t} else if ( selection.type === SelectionType.Cursor ) {\n\t\t\t\t\tconst { textIndex, localClientId } =\n\t\t\t\t\t\tresolveSelection( selection );\n\t\t\t\t\tif ( localClientId ) {\n\t\t\t\t\t\tcoords = getCursorPosition(\n\t\t\t\t\t\t\ttextIndex,\n\t\t\t\t\t\t\tlocalClientId,\n\t\t\t\t\t\t\tblockEditorDocument,\n\t\t\t\t\t\t\toverlayElement\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t} else if (\n\t\t\t\t\tselection.type === SelectionType.SelectionInOneBlock ||\n\t\t\t\t\tselection.type === SelectionType.SelectionInMultipleBlocks\n\t\t\t\t) {\n\t\t\t\t\tconst { textIndex, localClientId } = resolveSelection( {\n\t\t\t\t\t\ttype: SelectionType.Cursor,\n\t\t\t\t\t\tcursorPosition: selection.cursorStartPosition,\n\t\t\t\t\t} );\n\t\t\t\t\tif ( localClientId ) {\n\t\t\t\t\t\tcoords = getCursorPosition(\n\t\t\t\t\t\t\ttextIndex,\n\t\t\t\t\t\t\tlocalClientId,\n\t\t\t\t\t\t\tblockEditorDocument,\n\t\t\t\t\t\t\toverlayElement\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( coords ) {\n\t\t\t\t\tresults.push( {\n\t\t\t\t\t\tuserName,\n\t\t\t\t\t\tclientId,\n\t\t\t\t\t\tcolor,\n\t\t\t\t\t\tavatarUrl,\n\t\t\t\t\t\t...coords,\n\t\t\t\t\t} );\n\t\t\t\t}\n\t\t\t} );\n\n\t\t\tsetCursorPositions( results );\n\t\t},\n\t\t[ blockEditorDocument, resolveSelection, overlayElement, sortedUsers ]\n\t);\n\n\tuseEffect( computeCursors, [ computeCursors ] );\n\n\tconst rerenderCursorsAfterDelay = useMemo(\n\t\t() => () => {\n\t\t\tconst timeout = setTimeout( computeCursors, 500 );\n\t\t\treturn () => clearTimeout( timeout );\n\t\t},\n\t\t[ computeCursors ]\n\t);\n\n\treturn { cursors: cursorPositions, rerenderCursorsAfterDelay };\n}\n\n/**\n * Given a selection, returns the coordinates of the cursor in the block.\n *\n * @param absolutePositionIndex - The absolute position index\n * @param blockId - The block ID\n * @param editorDocument - The editor document\n * @param overlay - The overlay element\n * @return The position of the cursor\n */\nconst getCursorPosition = (\n\tabsolutePositionIndex: number | null,\n\tblockId: string,\n\teditorDocument: Document,\n\toverlay: HTMLElement\n): { x: number; y: number; height: number } | null => {\n\tif ( absolutePositionIndex === null ) {\n\t\t// An absolute position index can be null if a cursor was set in a block that\n\t\t// has since been deleted.\n\t\t// Return null so we don't try to draw it.\n\t\treturn null;\n\t}\n\n\tconst blockElement = editorDocument.querySelector(\n\t\t`[data-block=\"${ blockId }\"]`\n\t) as HTMLElement;\n\n\tif ( ! blockElement ) {\n\t\treturn null;\n\t}\n\n\treturn (\n\t\tgetOffsetPositionInBlock(\n\t\t\tblockElement,\n\t\t\tabsolutePositionIndex,\n\t\t\teditorDocument,\n\t\t\toverlay\n\t\t) ?? null\n\t);\n};\n\n/**\n * Given a block element and a character offset, returns the coordinates for drawing a visual cursor in the block.\n *\n * @param blockElement - The block element\n * @param charOffset - The character offset\n * @param editorDocument - The editor document\n * @param overlay - The overlay element\n * @return The position of the cursor\n */\nconst getOffsetPositionInBlock = (\n\tblockElement: HTMLElement,\n\tcharOffset: number,\n\teditorDocument: Document,\n\toverlay: HTMLElement\n) => {\n\tconst { node, offset } = findInnerBlockOffset(\n\t\tblockElement,\n\t\tcharOffset,\n\t\teditorDocument\n\t);\n\n\tconst cursorRange = editorDocument.createRange();\n\n\ttry {\n\t\tcursorRange.setStart( node, offset );\n\t} catch ( error ) {\n\t\treturn null;\n\t}\n\n\t// Ensure the range only represents single point in the DOM.\n\tcursorRange.collapse( true );\n\n\tconst cursorRect = cursorRange.getBoundingClientRect();\n\tconst overlayRect = overlay.getBoundingClientRect();\n\tconst blockRect = blockElement.getBoundingClientRect();\n\n\tlet cursorX = 0;\n\tlet cursorY = 0;\n\n\tif (\n\t\tcursorRect.x === 0 &&\n\t\tcursorRect.y === 0 &&\n\t\tcursorRect.width === 0 &&\n\t\tcursorRect.height === 0\n\t) {\n\t\t// This can happen for empty blocks.\n\t\tcursorX = blockRect.left - overlayRect.left;\n\t\tcursorY = blockRect.top - overlayRect.top;\n\t} else {\n\t\tcursorX = cursorRect.left - overlayRect.left;\n\t\tcursorY = cursorRect.top - overlayRect.top;\n\t}\n\n\tlet cursorHeight = cursorRect.height;\n\tif ( cursorHeight === 0 ) {\n\t\tcursorHeight =\n\t\t\tparseInt(\n\t\t\t\twindow.getComputedStyle( blockElement ).lineHeight,\n\t\t\t\t10\n\t\t\t) || blockRect.height;\n\t}\n\n\treturn {\n\t\tx: cursorX,\n\t\ty: cursorY,\n\t\theight: cursorHeight,\n\t};\n};\n\nconst MAX_NODE_OFFSET_COUNT = 1000;\n\n/**\n * Given a block element and a character offset, returns an exact inner node and offset for use in a range.\n *\n * @param blockElement - The block element\n * @param offset - The character offset\n * @param editorDocument - The editor document\n * @return The node and offset of the character at the offset\n */\nconst findInnerBlockOffset = (\n\tblockElement: HTMLElement,\n\toffset: number,\n\teditorDocument: Document\n) => {\n\tconst treeWalker = editorDocument.createTreeWalker(\n\t\tblockElement,\n\t\tNodeFilter.SHOW_TEXT | NodeFilter.SHOW_ELEMENT // eslint-disable-line no-bitwise\n\t);\n\n\tlet currentOffset = 0;\n\tlet lastTextNode: Node | null = null;\n\n\tlet node: Node | null = null;\n\tlet nodeCount = 1;\n\n\twhile ( ( node = treeWalker.nextNode() ) ) {\n\t\tnodeCount++;\n\n\t\tif ( nodeCount > MAX_NODE_OFFSET_COUNT ) {\n\t\t\t// If we've walked too many nodes, return the last text node or the beginning of the block.\n\t\t\tif ( lastTextNode ) {\n\t\t\t\treturn { node: lastTextNode, offset: 0 };\n\t\t\t}\n\t\t\treturn { node: blockElement, offset: 0 };\n\t\t}\n\n\t\tconst nodeLength = node.nodeValue?.length ?? 0;\n\n\t\tif ( node.nodeType === Node.ELEMENT_NODE ) {\n\t\t\tif ( node.nodeName === 'BR' ) {\n\t\t\t\t// Treat <br> as a single \"\\n\" character.\n\n\t\t\t\tif ( currentOffset + 1 >= offset ) {\n\t\t\t\t\t// If the <br> occurs right on the target offset, return the next text node.\n\t\t\t\t\tconst nodeAfterBr = treeWalker.nextNode();\n\n\t\t\t\t\tif ( nodeAfterBr?.nodeType === Node.TEXT_NODE ) {\n\t\t\t\t\t\treturn { node: nodeAfterBr, offset: 0 };\n\t\t\t\t\t} else if ( lastTextNode ) {\n\t\t\t\t\t\t// If there's no text node after the <br>, return the end offset of the last text node.\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\tnode: lastTextNode,\n\t\t\t\t\t\t\toffset: lastTextNode.nodeValue?.length ?? 0,\n\t\t\t\t\t\t};\n\t\t\t\t\t}\n\t\t\t\t\t// Just in case, if there's no last text node, return the beginning of the block.\n\t\t\t\t\treturn { node: blockElement, offset: 0 };\n\t\t\t\t}\n\n\t\t\t\t// The <br> is before the target offset. Count it as a single character.\n\t\t\t\tcurrentOffset += 1;\n\t\t\t\tcontinue;\n\t\t\t} else {\n\t\t\t\t// Skip other element types.\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t}\n\n\t\tif ( nodeLength === 0 ) {\n\t\t\t// Skip empty nodes.\n\t\t\tcontinue;\n\t\t}\n\n\t\tif ( currentOffset + nodeLength >= offset ) {\n\t\t\t// This node exceeds the target offset. Return the node and the position of the offset within it.\n\t\t\treturn { node, offset: offset - currentOffset };\n\t\t}\n\n\t\tcurrentOffset += nodeLength;\n\n\t\tif ( node.nodeType === Node.TEXT_NODE ) {\n\t\t\tlastTextNode = node;\n\t\t}\n\t}\n\n\tif ( lastTextNode && lastTextNode.nodeValue?.length ) {\n\t\t// We didn't reach the target offset. Return the last text node's last character.\n\t\treturn { node: lastTextNode, offset: lastTextNode.nodeValue.length };\n\t}\n\n\t// We didn't find any text nodes. Return the beginning of the block.\n\treturn { node: blockElement, offset: 0 };\n};\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { privateApis as coreDataPrivateApis } from '@wordpress/core-data';\nimport type {\n\tCoreDataPrivateApis,\n\tResolvedSelection,\n\tPostEditorAwarenessState as ActiveCollaborator,\n} from '@wordpress/core-data';\nimport { useSelect } from '@wordpress/data';\nimport { useEffect, useState } from '@wordpress/element';\nimport { store as preferencesStore } from '@wordpress/preferences';\n\nimport { unlock } from '../../lock-unlock';\nimport { getAvatarUrl } from './get-avatar-url';\nimport { getAvatarBorderColor } from '../collab-sidebar/utils';\nimport { computeSelectionVisual } from './compute-selection';\nimport { useDebouncedRecompute } from './use-debounced-recompute';\nimport type { SelectionRect } from './cursor-dom-utils';\n\nconst { useActiveCollaborators, useResolvedSelection } =\n\tunlock( coreDataPrivateApis );\nconst { SelectionType } = unlock( coreDataPrivateApis ) as Pick<\n\tCoreDataPrivateApis,\n\t'SelectionType'\n>;\n\nexport type { SelectionRect };\n\nexport interface CursorData {\n\tuserName: string;\n\tclientId: number;\n\tcolor: string;\n\tavatarUrl?: string;\n\tx: number;\n\ty: number;\n\theight: number;\n\tisMe?: boolean;\n\tselectionRects?: SelectionRect[];\n}\n\n/**\n * Custom hook that computes cursor positions for each remote user in the editor.\n *\n * @param overlayElement - The overlay element\n * @param blockEditorDocument - The block editor document\n * @param postId - The ID of the post\n * @param postType - The type of the post\n * @param delayMs - Milliseconds to wait before recomputing cursor positions.\n * @return An array of cursor data for rendering, and a function to trigger a delayed recompute.\n */\nexport function useRenderCursors(\n\toverlayElement: HTMLElement | null,\n\tblockEditorDocument: Document | null,\n\tpostId: number | null,\n\tpostType: string | null,\n\tdelayMs: number\n): { cursors: CursorData[]; rerenderCursorsAfterDelay: () => () => void } {\n\tconst sortedUsers = useActiveCollaborators(\n\t\tpostId ?? null,\n\t\tpostType ?? null\n\t);\n\tconst resolveSelection = useResolvedSelection(\n\t\tpostId ?? null,\n\t\tpostType ?? null\n\t);\n\n\tconst showOwnCursor = useSelect(\n\t\t( select ) =>\n\t\t\tselect( preferencesStore ).get( 'core', 'showCollaborationCursor' ),\n\t\t[]\n\t);\n\n\tconst [ cursorPositions, setCursorPositions ] = useState< CursorData[] >(\n\t\t[]\n\t);\n\n\t// Bump this counter to force the effect to re-run (e.g. after a layout shift).\n\tconst [ recomputeToken, rerenderCursorsAfterDelay ] =\n\t\tuseDebouncedRecompute( delayMs );\n\n\t// All DOM position computations live inside useEffect.\n\tuseEffect( () => {\n\t\tif ( ! overlayElement || ! blockEditorDocument ) {\n\t\t\tsetCursorPositions( [] );\n\t\t\treturn;\n\t\t}\n\n\t\t// Pre-compute the overlay rect once, same for every user.\n\t\tconst overlayRect = overlayElement.getBoundingClientRect();\n\t\tconst overlayContext = {\n\t\t\teditorDocument: blockEditorDocument,\n\t\t\toverlayRect,\n\t\t};\n\n\t\tconst results: CursorData[] = [];\n\n\t\tconst hasOtherCollaborators = sortedUsers.some(\n\t\t\t( u: ActiveCollaborator ) => ! u.isMe\n\t\t);\n\n\t\tsortedUsers.forEach( ( user: ActiveCollaborator ) => {\n\t\t\tif ( user.isMe && ( ! showOwnCursor || ! hasOtherCollaborators ) ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst selection = user.editorState?.selection ?? {\n\t\t\t\ttype: SelectionType.None,\n\t\t\t};\n\n\t\t\tlet start: ResolvedSelection = {\n\t\t\t\trichTextOffset: null,\n\t\t\t\tlocalClientId: null,\n\t\t\t};\n\t\t\tlet end: ResolvedSelection | undefined;\n\n\t\t\tif ( selection.type === SelectionType.Cursor ) {\n\t\t\t\ttry {\n\t\t\t\t\tstart = resolveSelection( selection );\n\t\t\t\t} catch {\n\t\t\t\t\t// Selection may reference a stale Yjs position.\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t} else if (\n\t\t\t\tselection.type === SelectionType.SelectionInOneBlock ||\n\t\t\t\tselection.type === SelectionType.SelectionInMultipleBlocks\n\t\t\t) {\n\t\t\t\ttry {\n\t\t\t\t\tstart = resolveSelection( {\n\t\t\t\t\t\ttype: SelectionType.Cursor,\n\t\t\t\t\t\tcursorPosition: selection.cursorStartPosition,\n\t\t\t\t\t} );\n\n\t\t\t\t\tend = resolveSelection( {\n\t\t\t\t\t\ttype: SelectionType.Cursor,\n\t\t\t\t\t\tcursorPosition: selection.cursorEndPosition,\n\t\t\t\t\t} );\n\t\t\t\t} catch {\n\t\t\t\t\t// Selection may reference a stale Yjs position.\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst userName = user.collaboratorInfo.name;\n\t\t\tconst clientId = user.clientId;\n\t\t\tconst color = user.isMe\n\t\t\t\t? 'var(--wp-admin-theme-color)'\n\t\t\t\t: getAvatarBorderColor( user.collaboratorInfo.id );\n\t\t\tconst avatarUrl = getAvatarUrl( user.collaboratorInfo.avatar_urls );\n\n\t\t\tconst selectionVisual = computeSelectionVisual(\n\t\t\t\tselection,\n\t\t\t\tstart,\n\t\t\t\tend,\n\t\t\t\toverlayContext\n\t\t\t);\n\n\t\t\tif ( selectionVisual.coords ) {\n\t\t\t\tconst cursorData: CursorData = {\n\t\t\t\t\tuserName,\n\t\t\t\t\tclientId,\n\t\t\t\t\tcolor,\n\t\t\t\t\tavatarUrl,\n\t\t\t\t\tisMe: user.isMe,\n\t\t\t\t\t...selectionVisual.coords,\n\t\t\t\t};\n\n\t\t\t\tif ( selectionVisual.selectionRects ) {\n\t\t\t\t\tcursorData.selectionRects = selectionVisual.selectionRects;\n\t\t\t\t}\n\n\t\t\t\tresults.push( cursorData );\n\t\t\t}\n\t\t} );\n\n\t\tsetCursorPositions( results );\n\t}, [\n\t\tblockEditorDocument,\n\t\tresolveSelection,\n\t\toverlayElement,\n\t\tsortedUsers,\n\t\tshowOwnCursor,\n\t\trecomputeToken,\n\t] );\n\n\treturn { cursors: cursorPositions, rerenderCursorsAfterDelay };\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }