@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.
- package/CHANGELOG.md +6 -0
- package/build/components/collab-sidebar/index.cjs +7 -4
- package/build/components/collab-sidebar/index.cjs.map +2 -2
- package/build/components/collab-sidebar/utils.cjs +13 -15
- package/build/components/collab-sidebar/utils.cjs.map +2 -2
- package/build/components/collaborators-overlay/avatar-iframe-styles.cjs +141 -0
- package/build/components/collaborators-overlay/avatar-iframe-styles.cjs.map +7 -0
- package/build/components/collaborators-overlay/collaborator-styles.cjs +38 -2
- package/build/components/collaborators-overlay/collaborator-styles.cjs.map +2 -2
- package/build/components/collaborators-overlay/compute-selection.cjs +185 -0
- package/build/components/collaborators-overlay/compute-selection.cjs.map +7 -0
- package/build/components/collaborators-overlay/cursor-dom-utils.cjs +243 -0
- package/build/components/collaborators-overlay/cursor-dom-utils.cjs.map +7 -0
- package/build/components/collaborators-overlay/cursor-registry.cjs +86 -0
- package/build/components/collaborators-overlay/cursor-registry.cjs.map +7 -0
- package/build/components/collaborators-overlay/index.cjs +7 -2
- package/build/components/collaborators-overlay/index.cjs.map +2 -2
- package/build/components/collaborators-overlay/overlay-iframe-styles.cjs +148 -0
- package/build/components/collaborators-overlay/overlay-iframe-styles.cjs.map +7 -0
- package/build/components/collaborators-overlay/overlay.cjs +146 -236
- package/build/components/collaborators-overlay/overlay.cjs.map +3 -3
- package/build/components/collaborators-overlay/timing-utils.cjs +46 -0
- package/build/components/collaborators-overlay/timing-utils.cjs.map +7 -0
- package/build/components/collaborators-overlay/use-block-highlighting.cjs +91 -42
- package/build/components/collaborators-overlay/use-block-highlighting.cjs.map +2 -2
- package/build/components/collaborators-overlay/use-debounced-recompute.cjs +49 -0
- package/build/components/collaborators-overlay/use-debounced-recompute.cjs.map +7 -0
- package/build/components/collaborators-overlay/use-render-cursors.cjs +82 -172
- package/build/components/collaborators-overlay/use-render-cursors.cjs.map +3 -3
- package/build/components/collaborators-presence/avatar/component.cjs +121 -0
- package/build/components/collaborators-presence/avatar/component.cjs.map +7 -0
- package/build/components/collaborators-presence/avatar/index.cjs +37 -0
- package/build/components/collaborators-presence/avatar/index.cjs.map +7 -0
- package/build/components/collaborators-presence/avatar/types.cjs +19 -0
- package/build/components/collaborators-presence/avatar/types.cjs.map +7 -0
- package/build/components/collaborators-presence/avatar/use-image-loading-status.cjs +44 -0
- package/build/components/collaborators-presence/avatar/use-image-loading-status.cjs.map +7 -0
- package/build/components/collaborators-presence/avatar-group/component.cjs +78 -0
- package/build/components/collaborators-presence/avatar-group/component.cjs.map +7 -0
- package/build/components/collaborators-presence/avatar-group/index.cjs +37 -0
- package/build/components/collaborators-presence/avatar-group/index.cjs.map +7 -0
- package/build/components/collaborators-presence/avatar-group/types.cjs +19 -0
- package/build/components/collaborators-presence/avatar-group/types.cjs.map +7 -0
- package/build/components/collaborators-presence/index.cjs +66 -19
- package/build/components/collaborators-presence/index.cjs.map +3 -3
- package/build/components/collaborators-presence/list.cjs +60 -38
- package/build/components/collaborators-presence/list.cjs.map +3 -3
- package/build/components/collaborators-presence/use-collaborator-notifications.cjs +149 -0
- package/build/components/collaborators-presence/use-collaborator-notifications.cjs.map +7 -0
- package/build/components/editor-interface/index.cjs +11 -6
- package/build/components/editor-interface/index.cjs.map +2 -2
- package/build/components/inserter-sidebar/index.cjs +2 -1
- package/build/components/inserter-sidebar/index.cjs.map +2 -2
- package/build/components/post-last-revision/index.cjs +27 -6
- package/build/components/post-last-revision/index.cjs.map +2 -2
- package/build/components/post-locked-modal/index.cjs +49 -17
- package/build/components/post-locked-modal/index.cjs.map +3 -3
- package/build/components/post-revisions-preview/block-diff.cjs +130 -34
- package/build/components/post-revisions-preview/block-diff.cjs.map +2 -2
- package/build/components/post-revisions-preview/diff-markers.cjs +6 -5
- package/build/components/post-revisions-preview/diff-markers.cjs.map +2 -2
- package/build/components/post-revisions-preview/revisions-canvas.cjs +16 -60
- package/build/components/post-revisions-preview/revisions-canvas.cjs.map +3 -3
- package/build/components/post-revisions-preview/revisions-header.cjs +33 -26
- package/build/components/post-revisions-preview/revisions-header.cjs.map +3 -3
- package/build/components/post-revisions-preview/revisions-slider.cjs +104 -39
- package/build/components/post-revisions-preview/revisions-slider.cjs.map +3 -3
- package/build/components/preferences-modal/index.cjs +36 -4
- package/build/components/preferences-modal/index.cjs.map +2 -2
- package/build/components/provider/disable-non-page-content-blocks.cjs +31 -28
- package/build/components/provider/disable-non-page-content-blocks.cjs.map +3 -3
- package/build/components/provider/index.cjs +17 -5
- package/build/components/provider/index.cjs.map +2 -2
- package/build/components/provider/use-block-editor-settings.cjs +20 -4
- package/build/components/provider/use-block-editor-settings.cjs.map +3 -3
- package/build/components/provider/{use-post-content-blocks.cjs → use-post-content-block-types.cjs} +8 -19
- package/build/components/provider/use-post-content-block-types.cjs.map +7 -0
- package/build/components/provider/use-revision-blocks.cjs +106 -0
- package/build/components/provider/use-revision-blocks.cjs.map +7 -0
- package/build/components/revision-block-diff/index.cjs +61 -0
- package/build/components/revision-block-diff/index.cjs.map +7 -0
- package/build/components/revision-diff-panel/index.cjs +68 -0
- package/build/components/revision-diff-panel/index.cjs.map +7 -0
- package/build/components/revision-fields-diff/index.cjs +96 -0
- package/build/components/revision-fields-diff/index.cjs.map +7 -0
- package/build/components/sidebar/header.cjs +1 -1
- package/build/components/sidebar/header.cjs.map +2 -2
- package/build/components/sidebar/index.cjs +7 -1
- package/build/components/sidebar/index.cjs.map +3 -3
- package/build/components/style-book/index.cjs +4 -3
- package/build/components/style-book/index.cjs.map +2 -2
- package/build/components/sync-connection-error-modal/index.cjs +187 -0
- package/build/components/sync-connection-error-modal/index.cjs.map +7 -0
- package/build/components/sync-connection-error-modal/use-retry-countdown.cjs +84 -0
- package/build/components/sync-connection-error-modal/use-retry-countdown.cjs.map +7 -0
- package/build/components/template-content-panel/index.cjs +35 -31
- package/build/components/template-content-panel/index.cjs.map +3 -3
- package/build/components/template-part-menu-items/convert-to-regular.cjs +54 -11
- package/build/components/template-part-menu-items/convert-to-regular.cjs.map +3 -3
- package/build/components/visual-editor/index.cjs +6 -15
- package/build/components/visual-editor/index.cjs.map +2 -2
- package/build/store/private-actions.cjs +46 -2
- package/build/store/private-actions.cjs.map +2 -2
- package/build/store/private-selectors.cjs +156 -21
- package/build/store/private-selectors.cjs.map +2 -2
- package/build/store/reducer.cjs +27 -0
- package/build/store/reducer.cjs.map +2 -2
- package/build/store/selectors.cjs +0 -14
- package/build/store/selectors.cjs.map +2 -2
- package/build/utils/media-finalize/index.cjs +43 -0
- package/build/utils/media-finalize/index.cjs.map +7 -0
- package/build/utils/media-upload/on-success.cjs +46 -0
- package/build/utils/media-upload/on-success.cjs.map +7 -0
- package/build/utils/sync-error-messages.cjs +32 -15
- package/build/utils/sync-error-messages.cjs.map +3 -3
- package/build-module/components/collab-sidebar/index.mjs +7 -4
- package/build-module/components/collab-sidebar/index.mjs.map +2 -2
- package/build-module/components/collab-sidebar/utils.mjs +13 -15
- package/build-module/components/collab-sidebar/utils.mjs.map +2 -2
- package/build-module/components/collaborators-overlay/avatar-iframe-styles.mjs +128 -0
- package/build-module/components/collaborators-overlay/avatar-iframe-styles.mjs.map +7 -0
- package/build-module/components/collaborators-overlay/collaborator-styles.mjs +25 -1
- package/build-module/components/collaborators-overlay/collaborator-styles.mjs.map +2 -2
- package/build-module/components/collaborators-overlay/compute-selection.mjs +166 -0
- package/build-module/components/collaborators-overlay/compute-selection.mjs.map +7 -0
- package/build-module/components/collaborators-overlay/cursor-dom-utils.mjs +213 -0
- package/build-module/components/collaborators-overlay/cursor-dom-utils.mjs.map +7 -0
- package/build-module/components/collaborators-overlay/cursor-registry.mjs +61 -0
- package/build-module/components/collaborators-overlay/cursor-registry.mjs.map +7 -0
- package/build-module/components/collaborators-overlay/index.mjs +7 -2
- package/build-module/components/collaborators-overlay/index.mjs.map +2 -2
- package/build-module/components/collaborators-overlay/overlay-iframe-styles.mjs +130 -0
- package/build-module/components/collaborators-overlay/overlay-iframe-styles.mjs.map +7 -0
- package/build-module/components/collaborators-overlay/overlay.mjs +137 -237
- package/build-module/components/collaborators-overlay/overlay.mjs.map +2 -2
- package/build-module/components/collaborators-overlay/timing-utils.mjs +21 -0
- package/build-module/components/collaborators-overlay/timing-utils.mjs.map +7 -0
- package/build-module/components/collaborators-overlay/use-block-highlighting.mjs +93 -45
- package/build-module/components/collaborators-overlay/use-block-highlighting.mjs.map +2 -2
- package/build-module/components/collaborators-overlay/use-debounced-recompute.mjs +24 -0
- package/build-module/components/collaborators-overlay/use-debounced-recompute.mjs.map +7 -0
- package/build-module/components/collaborators-overlay/use-render-cursors.mjs +83 -176
- package/build-module/components/collaborators-overlay/use-render-cursors.mjs.map +2 -2
- package/build-module/components/collaborators-presence/avatar/component.mjs +90 -0
- package/build-module/components/collaborators-presence/avatar/component.mjs.map +7 -0
- package/build-module/components/collaborators-presence/avatar/index.mjs +6 -0
- package/build-module/components/collaborators-presence/avatar/index.mjs.map +7 -0
- package/build-module/components/collaborators-presence/avatar/types.mjs +1 -0
- package/build-module/components/collaborators-presence/avatar/types.mjs.map +7 -0
- package/build-module/components/collaborators-presence/avatar/use-image-loading-status.mjs +19 -0
- package/build-module/components/collaborators-presence/avatar/use-image-loading-status.mjs.map +7 -0
- package/build-module/components/collaborators-presence/avatar-group/component.mjs +47 -0
- package/build-module/components/collaborators-presence/avatar-group/component.mjs.map +7 -0
- package/build-module/components/collaborators-presence/avatar-group/index.mjs +6 -0
- package/build-module/components/collaborators-presence/avatar-group/index.mjs.map +7 -0
- package/build-module/components/collaborators-presence/avatar-group/types.mjs +1 -0
- package/build-module/components/collaborators-presence/avatar-group/types.mjs.map +7 -0
- package/build-module/components/collaborators-presence/index.mjs +57 -23
- package/build-module/components/collaborators-presence/index.mjs.map +2 -2
- package/build-module/components/collaborators-presence/list.mjs +52 -44
- package/build-module/components/collaborators-presence/list.mjs.map +2 -2
- package/build-module/components/collaborators-presence/use-collaborator-notifications.mjs +126 -0
- package/build-module/components/collaborators-presence/use-collaborator-notifications.mjs.map +7 -0
- package/build-module/components/editor-interface/index.mjs +12 -7
- package/build-module/components/editor-interface/index.mjs.map +2 -2
- package/build-module/components/inserter-sidebar/index.mjs +2 -1
- package/build-module/components/inserter-sidebar/index.mjs.map +2 -2
- package/build-module/components/post-last-revision/index.mjs +27 -6
- package/build-module/components/post-last-revision/index.mjs.map +2 -2
- package/build-module/components/post-locked-modal/index.mjs +49 -17
- package/build-module/components/post-locked-modal/index.mjs.map +2 -2
- package/build-module/components/post-revisions-preview/block-diff.mjs +130 -34
- package/build-module/components/post-revisions-preview/block-diff.mjs.map +2 -2
- package/build-module/components/post-revisions-preview/diff-markers.mjs +6 -5
- package/build-module/components/post-revisions-preview/diff-markers.mjs.map +2 -2
- package/build-module/components/post-revisions-preview/revisions-canvas.mjs +18 -65
- package/build-module/components/post-revisions-preview/revisions-canvas.mjs.map +2 -2
- package/build-module/components/post-revisions-preview/revisions-header.mjs +36 -33
- package/build-module/components/post-revisions-preview/revisions-header.mjs.map +2 -2
- package/build-module/components/post-revisions-preview/revisions-slider.mjs +112 -42
- package/build-module/components/post-revisions-preview/revisions-slider.mjs.map +2 -2
- package/build-module/components/preferences-modal/index.mjs +36 -4
- package/build-module/components/preferences-modal/index.mjs.map +2 -2
- package/build-module/components/provider/disable-non-page-content-blocks.mjs +31 -28
- package/build-module/components/provider/disable-non-page-content-blocks.mjs.map +2 -2
- package/build-module/components/provider/index.mjs +17 -5
- package/build-module/components/provider/index.mjs.map +2 -2
- package/build-module/components/provider/use-block-editor-settings.mjs +20 -4
- package/build-module/components/provider/use-block-editor-settings.mjs.map +2 -2
- package/build-module/components/provider/use-post-content-block-types.mjs +23 -0
- package/build-module/components/provider/use-post-content-block-types.mjs.map +7 -0
- package/build-module/components/provider/use-revision-blocks.mjs +81 -0
- package/build-module/components/provider/use-revision-blocks.mjs.map +7 -0
- package/build-module/components/revision-block-diff/index.mjs +30 -0
- package/build-module/components/revision-block-diff/index.mjs.map +7 -0
- package/build-module/components/revision-diff-panel/index.mjs +37 -0
- package/build-module/components/revision-diff-panel/index.mjs.map +7 -0
- package/build-module/components/revision-fields-diff/index.mjs +65 -0
- package/build-module/components/revision-fields-diff/index.mjs.map +7 -0
- package/build-module/components/sidebar/header.mjs +1 -1
- package/build-module/components/sidebar/header.mjs.map +2 -2
- package/build-module/components/sidebar/index.mjs +7 -1
- package/build-module/components/sidebar/index.mjs.map +2 -2
- package/build-module/components/style-book/index.mjs +4 -3
- package/build-module/components/style-book/index.mjs.map +2 -2
- package/build-module/components/sync-connection-error-modal/index.mjs +170 -0
- package/build-module/components/sync-connection-error-modal/index.mjs.map +7 -0
- package/build-module/components/sync-connection-error-modal/use-retry-countdown.mjs +59 -0
- package/build-module/components/sync-connection-error-modal/use-retry-countdown.mjs.map +7 -0
- package/build-module/components/template-content-panel/index.mjs +25 -31
- package/build-module/components/template-content-panel/index.mjs.map +2 -2
- package/build-module/components/template-part-menu-items/convert-to-regular.mjs +60 -14
- package/build-module/components/template-part-menu-items/convert-to-regular.mjs.map +2 -2
- package/build-module/components/visual-editor/index.mjs +6 -15
- package/build-module/components/visual-editor/index.mjs.map +2 -2
- package/build-module/store/private-actions.mjs +44 -2
- package/build-module/store/private-actions.mjs.map +2 -2
- package/build-module/store/private-selectors.mjs +155 -21
- package/build-module/store/private-selectors.mjs.map +2 -2
- package/build-module/store/reducer.mjs +25 -0
- package/build-module/store/reducer.mjs.map +2 -2
- package/build-module/store/selectors.mjs +0 -13
- package/build-module/store/selectors.mjs.map +2 -2
- package/build-module/utils/media-finalize/index.mjs +12 -0
- package/build-module/utils/media-finalize/index.mjs.map +7 -0
- package/build-module/utils/media-upload/on-success.mjs +25 -0
- package/build-module/utils/media-upload/on-success.mjs.map +7 -0
- package/build-module/utils/sync-error-messages.mjs +27 -15
- package/build-module/utils/sync-error-messages.mjs.map +3 -3
- package/build-style/style-rtl.css +388 -132
- package/build-style/style.css +388 -132
- package/build-types/components/autocompleters/link.d.ts +8 -0
- package/build-types/components/autocompleters/link.d.ts.map +1 -0
- package/build-types/components/collab-sidebar/add-note-menu-item.d.ts +5 -0
- package/build-types/components/collab-sidebar/add-note-menu-item.d.ts.map +1 -0
- package/build-types/components/collab-sidebar/add-note.d.ts +6 -0
- package/build-types/components/collab-sidebar/add-note.d.ts.map +1 -0
- package/build-types/components/collab-sidebar/board-store.d.ts +9 -0
- package/build-types/components/collab-sidebar/board-store.d.ts.map +1 -0
- package/build-types/components/collab-sidebar/floating-container.d.ts +8 -0
- package/build-types/components/collab-sidebar/floating-container.d.ts.map +1 -0
- package/build-types/components/collab-sidebar/index.d.ts.map +1 -1
- package/build-types/components/collab-sidebar/note-byline.d.ts +10 -0
- package/build-types/components/collab-sidebar/note-byline.d.ts.map +1 -0
- package/build-types/components/collab-sidebar/note-card.d.ts +8 -0
- package/build-types/components/collab-sidebar/note-card.d.ts.map +1 -0
- package/build-types/components/collab-sidebar/note-form.d.ts +7 -0
- package/build-types/components/collab-sidebar/note-form.d.ts.map +1 -0
- package/build-types/components/collab-sidebar/note-indicator-toolbar.d.ts +5 -0
- package/build-types/components/collab-sidebar/note-indicator-toolbar.d.ts.map +1 -0
- package/build-types/components/collab-sidebar/note-thread.d.ts +11 -0
- package/build-types/components/collab-sidebar/note-thread.d.ts.map +1 -0
- package/build-types/components/collab-sidebar/note.d.ts +9 -0
- package/build-types/components/collab-sidebar/note.d.ts.map +1 -0
- package/build-types/components/collab-sidebar/notes.d.ts +7 -0
- package/build-types/components/collab-sidebar/notes.d.ts.map +1 -0
- package/build-types/components/collab-sidebar/utils.d.ts.map +1 -1
- package/build-types/components/collaborators-overlay/avatar-iframe-styles.d.ts +11 -0
- package/build-types/components/collaborators-overlay/avatar-iframe-styles.d.ts.map +1 -0
- package/build-types/components/collaborators-overlay/collaborator-styles.d.ts +17 -2
- package/build-types/components/collaborators-overlay/collaborator-styles.d.ts.map +1 -1
- package/build-types/components/collaborators-overlay/compute-selection.d.ts +24 -0
- package/build-types/components/collaborators-overlay/compute-selection.d.ts.map +1 -0
- package/build-types/components/collaborators-overlay/cursor-dom-utils.d.ts +72 -0
- package/build-types/components/collaborators-overlay/cursor-dom-utils.d.ts.map +1 -0
- package/build-types/components/collaborators-overlay/cursor-registry.d.ts +36 -0
- package/build-types/components/collaborators-overlay/cursor-registry.d.ts.map +1 -0
- package/build-types/components/collaborators-overlay/index.d.ts +7 -4
- package/build-types/components/collaborators-overlay/index.d.ts.map +1 -1
- package/build-types/components/collaborators-overlay/overlay-iframe-styles.d.ts +6 -0
- package/build-types/components/collaborators-overlay/overlay-iframe-styles.d.ts.map +1 -0
- package/build-types/components/collaborators-overlay/overlay.d.ts +4 -1
- package/build-types/components/collaborators-overlay/overlay.d.ts.map +1 -1
- package/build-types/components/collaborators-overlay/timing-utils.d.ts +11 -0
- package/build-types/components/collaborators-overlay/timing-utils.d.ts.map +1 -0
- package/build-types/components/collaborators-overlay/use-block-highlighting.d.ts +21 -5
- package/build-types/components/collaborators-overlay/use-block-highlighting.d.ts.map +1 -1
- package/build-types/components/collaborators-overlay/use-debounced-recompute.d.ts +10 -0
- package/build-types/components/collaborators-overlay/use-debounced-recompute.d.ts.map +1 -0
- package/build-types/components/collaborators-overlay/use-render-cursors.d.ts +6 -1
- package/build-types/components/collaborators-overlay/use-render-cursors.d.ts.map +1 -1
- package/build-types/components/collaborators-presence/avatar/component.d.ts +7 -0
- package/build-types/components/collaborators-presence/avatar/component.d.ts.map +1 -0
- package/build-types/components/collaborators-presence/avatar/index.d.ts +3 -0
- package/build-types/components/collaborators-presence/avatar/index.d.ts.map +1 -0
- package/build-types/components/collaborators-presence/avatar/types.d.ts +66 -0
- package/build-types/components/collaborators-presence/avatar/types.d.ts.map +1 -0
- package/build-types/components/collaborators-presence/avatar/use-image-loading-status.d.ts +17 -0
- package/build-types/components/collaborators-presence/avatar/use-image-loading-status.d.ts.map +1 -0
- package/build-types/components/collaborators-presence/avatar-group/component.d.ts +7 -0
- package/build-types/components/collaborators-presence/avatar-group/component.d.ts.map +1 -0
- package/build-types/components/collaborators-presence/avatar-group/index.d.ts +3 -0
- package/build-types/components/collaborators-presence/avatar-group/index.d.ts.map +1 -0
- package/build-types/components/collaborators-presence/avatar-group/types.d.ts +14 -0
- package/build-types/components/collaborators-presence/avatar-group/types.d.ts.map +1 -0
- package/build-types/components/collaborators-presence/index.d.ts.map +1 -1
- package/build-types/components/collaborators-presence/list.d.ts +6 -2
- package/build-types/components/collaborators-presence/list.d.ts.map +1 -1
- package/build-types/components/collaborators-presence/use-collaborator-notifications.d.ts +9 -0
- package/build-types/components/collaborators-presence/use-collaborator-notifications.d.ts.map +1 -0
- package/build-types/components/editor-interface/index.d.ts.map +1 -1
- package/build-types/components/inserter-sidebar/index.d.ts.map +1 -1
- package/build-types/components/media/media-editor-modal.d.ts +15 -0
- package/build-types/components/media/media-editor-modal.d.ts.map +1 -0
- package/build-types/components/post-last-revision/index.d.ts.map +1 -1
- package/build-types/components/post-locked-modal/index.d.ts.map +1 -1
- package/build-types/components/post-revisions-panel/index.d.ts +2 -0
- package/build-types/components/post-revisions-panel/index.d.ts.map +1 -0
- package/build-types/components/post-revisions-preview/block-diff.d.ts.map +1 -1
- package/build-types/components/post-revisions-preview/diff-markers.d.ts.map +1 -1
- package/build-types/components/post-revisions-preview/revisions-canvas.d.ts +2 -5
- package/build-types/components/post-revisions-preview/revisions-canvas.d.ts.map +1 -1
- package/build-types/components/post-revisions-preview/revisions-header.d.ts.map +1 -1
- package/build-types/components/post-revisions-preview/revisions-slider.d.ts +1 -1
- package/build-types/components/post-revisions-preview/revisions-slider.d.ts.map +1 -1
- package/build-types/components/post-text-editor/utils.d.ts +29 -0
- package/build-types/components/post-text-editor/utils.d.ts.map +1 -0
- package/build-types/components/provider/disable-non-page-content-blocks.d.ts.map +1 -1
- package/build-types/components/provider/index.d.ts.map +1 -1
- package/build-types/components/provider/use-block-editor-settings.d.ts.map +1 -1
- package/build-types/components/provider/use-network-reconnect.d.ts +8 -0
- package/build-types/components/provider/use-network-reconnect.d.ts.map +1 -0
- package/build-types/components/provider/use-post-content-block-types.d.ts +9 -0
- package/build-types/components/provider/use-post-content-block-types.d.ts.map +1 -0
- package/build-types/components/provider/use-revision-blocks.d.ts +10 -0
- package/build-types/components/provider/use-revision-blocks.d.ts.map +1 -0
- package/build-types/components/revision-block-diff/index.d.ts +6 -0
- package/build-types/components/revision-block-diff/index.d.ts.map +1 -0
- package/build-types/components/revision-diff-panel/index.d.ts +14 -0
- package/build-types/components/revision-diff-panel/index.d.ts.map +1 -0
- package/build-types/components/revision-fields-diff/index.d.ts +6 -0
- package/build-types/components/revision-fields-diff/index.d.ts.map +1 -0
- package/build-types/components/sidebar/dataform-post-summary.d.ts +4 -0
- package/build-types/components/sidebar/dataform-post-summary.d.ts.map +1 -0
- package/build-types/components/sidebar/index.d.ts.map +1 -1
- package/build-types/components/sidebar/post-revision-summary.d.ts +2 -0
- package/build-types/components/sidebar/post-revision-summary.d.ts.map +1 -0
- package/build-types/components/style-book/index.d.ts +2 -1
- package/build-types/components/style-book/index.d.ts.map +1 -1
- package/build-types/components/sync-connection-error-modal/index.d.ts +8 -0
- package/build-types/components/sync-connection-error-modal/index.d.ts.map +1 -0
- package/build-types/components/sync-connection-error-modal/use-retry-countdown.d.ts +11 -0
- package/build-types/components/sync-connection-error-modal/use-retry-countdown.d.ts.map +1 -0
- package/build-types/components/template-actions-panel/block-theme-content.d.ts +2 -0
- package/build-types/components/template-actions-panel/block-theme-content.d.ts.map +1 -0
- package/build-types/components/template-actions-panel/classic-theme-content.d.ts +2 -0
- package/build-types/components/template-actions-panel/classic-theme-content.d.ts.map +1 -0
- package/build-types/components/template-actions-panel/index.d.ts +2 -0
- package/build-types/components/template-actions-panel/index.d.ts.map +1 -0
- package/build-types/components/template-content-panel/index.d.ts.map +1 -1
- package/build-types/components/template-part-menu-items/convert-to-regular.d.ts.map +1 -1
- package/build-types/components/upload-progress-snackbar/index.d.ts +19 -0
- package/build-types/components/upload-progress-snackbar/index.d.ts.map +1 -0
- package/build-types/components/upload-progress-snackbar/stories/index.story.d.ts +28 -0
- package/build-types/components/upload-progress-snackbar/stories/index.story.d.ts.map +1 -0
- package/build-types/components/upload-progress-snackbar/tracker.d.ts +41 -0
- package/build-types/components/upload-progress-snackbar/tracker.d.ts.map +1 -0
- package/build-types/components/visual-editor/index.d.ts.map +1 -1
- package/build-types/store/private-actions.d.ts +12 -0
- package/build-types/store/private-actions.d.ts.map +1 -1
- package/build-types/store/private-selectors.d.ts +45 -0
- package/build-types/store/private-selectors.d.ts.map +1 -1
- package/build-types/store/reducer.d.ts +21 -0
- package/build-types/store/reducer.d.ts.map +1 -1
- package/build-types/store/selectors.d.ts +0 -10
- package/build-types/store/selectors.d.ts.map +1 -1
- package/build-types/utils/media-delete/index.d.ts +2 -0
- package/build-types/utils/media-delete/index.d.ts.map +1 -0
- package/build-types/utils/media-finalize/index.d.ts +2 -0
- package/build-types/utils/media-finalize/index.d.ts.map +1 -0
- package/build-types/utils/media-upload/on-success.d.ts +9 -0
- package/build-types/utils/media-upload/on-success.d.ts.map +1 -0
- package/build-types/utils/sync-error-messages.d.ts +17 -3
- package/build-types/utils/sync-error-messages.d.ts.map +1 -1
- package/package.json +45 -44
- package/src/components/collab-sidebar/index.js +7 -4
- package/src/components/collab-sidebar/utils.js +9 -10
- package/src/components/collaborators-overlay/avatar-iframe-styles.ts +134 -0
- package/src/components/collaborators-overlay/collaborator-styles.ts +43 -2
- package/src/components/collaborators-overlay/compute-selection.ts +315 -0
- package/src/components/collaborators-overlay/cursor-dom-utils.ts +382 -0
- package/src/components/collaborators-overlay/cursor-registry.ts +96 -0
- package/src/components/collaborators-overlay/index.tsx +12 -4
- package/src/components/collaborators-overlay/overlay-iframe-styles.ts +131 -0
- package/src/components/collaborators-overlay/overlay.tsx +145 -229
- package/src/components/collaborators-overlay/timing-utils.ts +30 -0
- package/src/components/collaborators-overlay/use-block-highlighting.ts +152 -64
- package/src/components/collaborators-overlay/use-debounced-recompute.ts +32 -0
- package/src/components/collaborators-overlay/use-render-cursors.ts +120 -282
- package/src/components/collaborators-presence/avatar/component.tsx +123 -0
- package/src/components/collaborators-presence/avatar/index.ts +2 -0
- package/src/components/collaborators-presence/avatar/styles.scss +184 -0
- package/src/components/collaborators-presence/avatar/test/index.tsx +389 -0
- package/src/components/collaborators-presence/avatar/types.ts +66 -0
- package/src/components/collaborators-presence/avatar/use-image-loading-status.ts +36 -0
- package/src/components/collaborators-presence/avatar-group/component.tsx +55 -0
- package/src/components/collaborators-presence/avatar-group/index.ts +2 -0
- package/src/components/collaborators-presence/avatar-group/styles.scss +33 -0
- package/src/components/collaborators-presence/avatar-group/test/index.tsx +139 -0
- package/src/components/collaborators-presence/avatar-group/types.ts +13 -0
- package/src/components/collaborators-presence/index.tsx +43 -12
- package/src/components/collaborators-presence/list.tsx +68 -40
- package/src/components/collaborators-presence/styles/collaborators-list.scss +26 -19
- package/src/components/collaborators-presence/styles/collaborators-presence.scss +6 -2
- package/src/components/collaborators-presence/test/use-collaborator-notifications.ts +397 -0
- package/src/components/collaborators-presence/use-collaborator-notifications.ts +203 -0
- package/src/components/document-bar/style.scss +1 -1
- package/src/components/editor-interface/index.js +13 -6
- package/src/components/inserter-sidebar/index.js +4 -1
- package/src/components/post-last-revision/index.js +35 -6
- package/src/components/post-last-revision/style.scss +0 -3
- package/src/components/post-locked-modal/index.js +69 -25
- package/src/components/post-panel-row/style.scss +1 -0
- package/src/components/post-revisions-preview/block-diff.js +224 -61
- package/src/components/post-revisions-preview/diff-markers.js +15 -12
- package/src/components/post-revisions-preview/revisions-canvas.js +23 -86
- package/src/components/post-revisions-preview/revisions-header.js +35 -37
- package/src/components/post-revisions-preview/revisions-slider.js +138 -62
- package/src/components/post-revisions-preview/style.scss +3 -3
- package/src/components/post-revisions-preview/test/block-diff.js +202 -35
- package/src/components/preferences-modal/index.js +37 -7
- package/src/components/provider/disable-non-page-content-blocks.js +42 -40
- package/src/components/provider/index.js +20 -2
- package/src/components/provider/use-block-editor-settings.js +21 -1
- package/src/components/provider/use-post-content-block-types.js +30 -0
- package/src/components/provider/use-revision-blocks.js +105 -0
- package/src/components/revision-block-diff/index.js +39 -0
- package/src/components/revision-diff-panel/index.js +59 -0
- package/src/components/revision-diff-panel/style.scss +13 -0
- package/src/components/revision-fields-diff/index.js +91 -0
- package/src/components/sidebar/header.js +1 -1
- package/src/components/sidebar/index.js +4 -0
- package/src/components/style-book/index.js +4 -2
- package/src/components/sync-connection-error-modal/index.tsx +253 -0
- package/src/components/sync-connection-error-modal/style.scss +14 -0
- package/src/components/sync-connection-error-modal/use-retry-countdown.ts +93 -0
- package/src/components/template-content-panel/index.js +30 -38
- package/src/components/template-part-menu-items/convert-to-regular.js +74 -12
- package/src/components/visual-editor/index.js +6 -23
- package/src/store/private-actions.js +70 -1
- package/src/store/private-selectors.js +216 -28
- package/src/store/reducer.js +41 -0
- package/src/store/selectors.js +0 -19
- package/src/style.scss +4 -1
- package/src/utils/media-finalize/index.js +11 -0
- package/src/utils/media-finalize/test/index.js +34 -0
- package/src/utils/media-upload/on-success.js +34 -0
- package/src/utils/sync-error-messages.ts +72 -0
- package/src/utils/test/sync-error-messages.js +34 -0
- package/build/components/provider/use-post-content-blocks.cjs.map +0 -7
- package/build/components/sync-connection-modal/index.cjs +0 -130
- package/build/components/sync-connection-modal/index.cjs.map +0 -7
- package/build-module/components/provider/use-post-content-blocks.mjs +0 -34
- package/build-module/components/provider/use-post-content-blocks.mjs.map +0 -7
- package/build-module/components/sync-connection-modal/index.mjs +0 -114
- package/build-module/components/sync-connection-modal/index.mjs.map +0 -7
- package/build-types/components/provider/use-post-content-blocks.d.ts +0 -2
- package/build-types/components/provider/use-post-content-blocks.d.ts.map +0 -1
- package/build-types/components/sync-connection-modal/index.d.ts +0 -8
- package/build-types/components/sync-connection-modal/index.d.ts.map +0 -1
- package/src/components/provider/use-post-content-blocks.js +0 -42
- package/src/components/sync-connection-modal/index.js +0 -140
- package/src/components/sync-connection-modal/style.scss +0 -11
- package/src/utils/sync-error-messages.js +0 -53
|
@@ -0,0 +1,397 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* External dependencies
|
|
3
|
+
*/
|
|
4
|
+
import { renderHook } from '@testing-library/react';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* WordPress dependencies
|
|
8
|
+
*/
|
|
9
|
+
import { useDispatch, useSelect } from '@wordpress/data';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Internal dependencies
|
|
13
|
+
*/
|
|
14
|
+
import { useCollaboratorNotifications } from '../use-collaborator-notifications';
|
|
15
|
+
|
|
16
|
+
// --- Mocks ---
|
|
17
|
+
|
|
18
|
+
const mockCreateNotice = jest.fn();
|
|
19
|
+
let mockOnJoinCallback: Function | null = null;
|
|
20
|
+
let mockOnLeaveCallback: Function | null = null;
|
|
21
|
+
let mockOnPostSaveCallback: Function | null = null;
|
|
22
|
+
let lastJoinPostId: unknown;
|
|
23
|
+
let lastLeavePostId: unknown;
|
|
24
|
+
let lastSavePostId: unknown;
|
|
25
|
+
let mockEditorState = {
|
|
26
|
+
postStatus: 'draft',
|
|
27
|
+
isCollaborationEnabled: true,
|
|
28
|
+
showCollaborationNotifications: true,
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
jest.mock( '@wordpress/data', () => ( {
|
|
32
|
+
useSelect: jest.fn(),
|
|
33
|
+
useDispatch: jest.fn(),
|
|
34
|
+
} ) );
|
|
35
|
+
|
|
36
|
+
jest.mock( '@wordpress/notices', () => ( {
|
|
37
|
+
store: 'core/notices',
|
|
38
|
+
} ) );
|
|
39
|
+
|
|
40
|
+
jest.mock( '@wordpress/preferences', () => ( {
|
|
41
|
+
store: 'core/preferences',
|
|
42
|
+
} ) );
|
|
43
|
+
|
|
44
|
+
// Mock the editor store to prevent deep import chain (blocks, rich-text, etc.)
|
|
45
|
+
jest.mock( '../../../store', () => ( {
|
|
46
|
+
store: 'core/editor',
|
|
47
|
+
} ) );
|
|
48
|
+
|
|
49
|
+
// Mock the private APIs and unlock mechanism
|
|
50
|
+
jest.mock( '@wordpress/core-data', () => ( {
|
|
51
|
+
privateApis: {},
|
|
52
|
+
} ) );
|
|
53
|
+
|
|
54
|
+
jest.mock( '../../../lock-unlock', () => ( {
|
|
55
|
+
unlock: jest.fn( ( value: unknown ) => ( {
|
|
56
|
+
...( value as object ),
|
|
57
|
+
useOnCollaboratorJoin: jest.fn(
|
|
58
|
+
( postId: unknown, _postType: unknown, callback: Function ) => {
|
|
59
|
+
lastJoinPostId = postId;
|
|
60
|
+
mockOnJoinCallback = callback;
|
|
61
|
+
}
|
|
62
|
+
),
|
|
63
|
+
useOnCollaboratorLeave: jest.fn(
|
|
64
|
+
( postId: unknown, _postType: unknown, callback: Function ) => {
|
|
65
|
+
lastLeavePostId = postId;
|
|
66
|
+
mockOnLeaveCallback = callback;
|
|
67
|
+
}
|
|
68
|
+
),
|
|
69
|
+
useOnPostSave: jest.fn(
|
|
70
|
+
( postId: unknown, _postType: unknown, callback: Function ) => {
|
|
71
|
+
lastSavePostId = postId;
|
|
72
|
+
mockOnPostSaveCallback = callback;
|
|
73
|
+
}
|
|
74
|
+
),
|
|
75
|
+
} ) ),
|
|
76
|
+
} ) );
|
|
77
|
+
|
|
78
|
+
// --- Helpers ---
|
|
79
|
+
|
|
80
|
+
const BASE_ENTERED_AT = 1704067200000;
|
|
81
|
+
|
|
82
|
+
function makeCollaborator( overrides: Record< string, unknown > = {} ) {
|
|
83
|
+
return {
|
|
84
|
+
clientId: 1,
|
|
85
|
+
isMe: false,
|
|
86
|
+
isConnected: true,
|
|
87
|
+
collaboratorInfo: {
|
|
88
|
+
id: 100,
|
|
89
|
+
name: 'Alice',
|
|
90
|
+
slug: 'alice',
|
|
91
|
+
avatar_urls: {},
|
|
92
|
+
browserType: 'Chrome',
|
|
93
|
+
enteredAt: BASE_ENTERED_AT + 1000,
|
|
94
|
+
},
|
|
95
|
+
...overrides,
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
function makeMe( overrides: Record< string, unknown > = {} ) {
|
|
100
|
+
return makeCollaborator( {
|
|
101
|
+
clientId: 999,
|
|
102
|
+
isMe: true,
|
|
103
|
+
collaboratorInfo: {
|
|
104
|
+
id: 1,
|
|
105
|
+
name: 'Me',
|
|
106
|
+
slug: 'me',
|
|
107
|
+
avatar_urls: {},
|
|
108
|
+
browserType: 'Chrome',
|
|
109
|
+
enteredAt: BASE_ENTERED_AT + 5000, // joined later than Alice
|
|
110
|
+
},
|
|
111
|
+
...overrides,
|
|
112
|
+
} );
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// --- Setup ---
|
|
116
|
+
|
|
117
|
+
function buildMockSelect() {
|
|
118
|
+
return ( storeKey: string ) => {
|
|
119
|
+
if ( storeKey === 'core/preferences' ) {
|
|
120
|
+
return {
|
|
121
|
+
get: ( scope: string, name: string ) => {
|
|
122
|
+
if (
|
|
123
|
+
scope === 'core' &&
|
|
124
|
+
name === 'showCollaborationNotifications'
|
|
125
|
+
) {
|
|
126
|
+
return mockEditorState.showCollaborationNotifications;
|
|
127
|
+
}
|
|
128
|
+
return undefined;
|
|
129
|
+
},
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
return {
|
|
133
|
+
getCurrentPostAttribute: ( attr: string ) =>
|
|
134
|
+
attr === 'status' ? mockEditorState.postStatus : undefined,
|
|
135
|
+
isCollaborationEnabledForCurrentPost: () =>
|
|
136
|
+
mockEditorState.isCollaborationEnabled,
|
|
137
|
+
};
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
beforeEach( () => {
|
|
142
|
+
mockOnJoinCallback = null;
|
|
143
|
+
mockOnLeaveCallback = null;
|
|
144
|
+
mockOnPostSaveCallback = null;
|
|
145
|
+
lastJoinPostId = undefined;
|
|
146
|
+
lastLeavePostId = undefined;
|
|
147
|
+
lastSavePostId = undefined;
|
|
148
|
+
mockEditorState = {
|
|
149
|
+
postStatus: 'draft',
|
|
150
|
+
isCollaborationEnabled: true,
|
|
151
|
+
showCollaborationNotifications: true,
|
|
152
|
+
};
|
|
153
|
+
mockCreateNotice.mockClear();
|
|
154
|
+
( useSelect as jest.Mock ).mockImplementation( ( selector: Function ) =>
|
|
155
|
+
selector( buildMockSelect() )
|
|
156
|
+
);
|
|
157
|
+
( useDispatch as jest.Mock ).mockReturnValue( {
|
|
158
|
+
createNotice: mockCreateNotice,
|
|
159
|
+
} );
|
|
160
|
+
} );
|
|
161
|
+
|
|
162
|
+
// --- Tests ---
|
|
163
|
+
|
|
164
|
+
describe( 'useCollaboratorNotifications', () => {
|
|
165
|
+
describe( 'collaborator join notifications', () => {
|
|
166
|
+
it( 'fires join notification for a collaborator who joined after current user', () => {
|
|
167
|
+
const me = makeMe(); // enteredAt: BASE_ENTERED_AT + 5000
|
|
168
|
+
const bobJoinedAfter = makeCollaborator( {
|
|
169
|
+
clientId: 2,
|
|
170
|
+
collaboratorInfo: {
|
|
171
|
+
id: 200,
|
|
172
|
+
name: 'Bob',
|
|
173
|
+
slug: 'bob',
|
|
174
|
+
avatar_urls: {},
|
|
175
|
+
browserType: 'Firefox',
|
|
176
|
+
enteredAt: BASE_ENTERED_AT + 10000, // joined after me
|
|
177
|
+
},
|
|
178
|
+
} );
|
|
179
|
+
|
|
180
|
+
renderHook( () => useCollaboratorNotifications( 123, 'post' ) );
|
|
181
|
+
|
|
182
|
+
// Simulate the core-data hook firing the join callback
|
|
183
|
+
mockOnJoinCallback?.( bobJoinedAfter, me );
|
|
184
|
+
|
|
185
|
+
expect( mockCreateNotice ).toHaveBeenCalledWith(
|
|
186
|
+
'info',
|
|
187
|
+
'Bob has joined the post.',
|
|
188
|
+
expect.objectContaining( {
|
|
189
|
+
id: 'collab-user-entered-200',
|
|
190
|
+
} )
|
|
191
|
+
);
|
|
192
|
+
} );
|
|
193
|
+
|
|
194
|
+
it( 'skips join notification for collaborators who joined before current user', () => {
|
|
195
|
+
const me = makeMe(); // enteredAt: BASE_ENTERED_AT + 5000
|
|
196
|
+
const aliceJoinedFirst = makeCollaborator( {
|
|
197
|
+
collaboratorInfo: {
|
|
198
|
+
id: 100,
|
|
199
|
+
name: 'Alice',
|
|
200
|
+
slug: 'alice',
|
|
201
|
+
avatar_urls: {},
|
|
202
|
+
browserType: 'Chrome',
|
|
203
|
+
enteredAt: BASE_ENTERED_AT + 1000, // joined earlier than me
|
|
204
|
+
},
|
|
205
|
+
} );
|
|
206
|
+
|
|
207
|
+
renderHook( () => useCollaboratorNotifications( 123, 'post' ) );
|
|
208
|
+
|
|
209
|
+
// Simulate the core-data hook firing the join callback
|
|
210
|
+
mockOnJoinCallback?.( aliceJoinedFirst, me );
|
|
211
|
+
|
|
212
|
+
expect( mockCreateNotice ).not.toHaveBeenCalled();
|
|
213
|
+
} );
|
|
214
|
+
} );
|
|
215
|
+
|
|
216
|
+
describe( 'collaborator leave notifications', () => {
|
|
217
|
+
it( 'fires a leave notification when a collaborator leaves', () => {
|
|
218
|
+
const alice = makeCollaborator();
|
|
219
|
+
renderHook( () => useCollaboratorNotifications( 123, 'post' ) );
|
|
220
|
+
|
|
221
|
+
// Simulate the core-data hook firing the leave callback
|
|
222
|
+
mockOnLeaveCallback?.( alice );
|
|
223
|
+
|
|
224
|
+
expect( mockCreateNotice ).toHaveBeenCalledWith(
|
|
225
|
+
'info',
|
|
226
|
+
'Alice has left the post.',
|
|
227
|
+
expect.objectContaining( {
|
|
228
|
+
type: 'snackbar',
|
|
229
|
+
isDismissible: false,
|
|
230
|
+
id: 'collab-user-exited-100',
|
|
231
|
+
} )
|
|
232
|
+
);
|
|
233
|
+
} );
|
|
234
|
+
} );
|
|
235
|
+
|
|
236
|
+
describe( 'post updated notifications', () => {
|
|
237
|
+
it( 'fires a post updated notification when a collaborator saves (draft)', () => {
|
|
238
|
+
const alice = makeCollaborator();
|
|
239
|
+
renderHook( () => useCollaboratorNotifications( 123, 'post' ) );
|
|
240
|
+
|
|
241
|
+
// Simulate the core-data hook firing the save callback
|
|
242
|
+
mockOnPostSaveCallback?.(
|
|
243
|
+
{
|
|
244
|
+
savedAt: Date.now(),
|
|
245
|
+
savedByClientId: alice.clientId,
|
|
246
|
+
postStatus: undefined,
|
|
247
|
+
},
|
|
248
|
+
alice,
|
|
249
|
+
null
|
|
250
|
+
);
|
|
251
|
+
|
|
252
|
+
expect( mockCreateNotice ).toHaveBeenCalledWith(
|
|
253
|
+
'info',
|
|
254
|
+
'Draft saved by Alice.',
|
|
255
|
+
expect.objectContaining( {
|
|
256
|
+
type: 'snackbar',
|
|
257
|
+
isDismissible: false,
|
|
258
|
+
id: 'collab-post-updated-100',
|
|
259
|
+
} )
|
|
260
|
+
);
|
|
261
|
+
} );
|
|
262
|
+
|
|
263
|
+
it( 'fires a post updated notification with "Post updated" for published status', () => {
|
|
264
|
+
mockEditorState = {
|
|
265
|
+
...mockEditorState,
|
|
266
|
+
postStatus: 'publish',
|
|
267
|
+
};
|
|
268
|
+
const alice = makeCollaborator();
|
|
269
|
+
renderHook( () => useCollaboratorNotifications( 123, 'post' ) );
|
|
270
|
+
|
|
271
|
+
mockOnPostSaveCallback?.(
|
|
272
|
+
{
|
|
273
|
+
savedAt: Date.now(),
|
|
274
|
+
savedByClientId: alice.clientId,
|
|
275
|
+
postStatus: 'publish',
|
|
276
|
+
},
|
|
277
|
+
alice,
|
|
278
|
+
null
|
|
279
|
+
);
|
|
280
|
+
|
|
281
|
+
expect( mockCreateNotice ).toHaveBeenCalledWith(
|
|
282
|
+
'info',
|
|
283
|
+
'Post updated by Alice.',
|
|
284
|
+
expect.objectContaining( {
|
|
285
|
+
id: 'collab-post-updated-100',
|
|
286
|
+
} )
|
|
287
|
+
);
|
|
288
|
+
} );
|
|
289
|
+
|
|
290
|
+
it( 'fires a "Post published" notification on first publish (no previous save)', () => {
|
|
291
|
+
mockEditorState = {
|
|
292
|
+
...mockEditorState,
|
|
293
|
+
postStatus: 'draft',
|
|
294
|
+
};
|
|
295
|
+
const alice = makeCollaborator();
|
|
296
|
+
renderHook( () => useCollaboratorNotifications( 123, 'post' ) );
|
|
297
|
+
|
|
298
|
+
mockOnPostSaveCallback?.(
|
|
299
|
+
{
|
|
300
|
+
savedAt: Date.now(),
|
|
301
|
+
savedByClientId: alice.clientId,
|
|
302
|
+
postStatus: 'publish',
|
|
303
|
+
},
|
|
304
|
+
alice,
|
|
305
|
+
null
|
|
306
|
+
);
|
|
307
|
+
|
|
308
|
+
expect( mockCreateNotice ).toHaveBeenCalledWith(
|
|
309
|
+
'info',
|
|
310
|
+
'Post published by Alice.',
|
|
311
|
+
expect.objectContaining( {
|
|
312
|
+
id: 'collab-post-updated-100',
|
|
313
|
+
} )
|
|
314
|
+
);
|
|
315
|
+
} );
|
|
316
|
+
|
|
317
|
+
it( 'fires a "Post published" notification using prevEvent status for transition detection', () => {
|
|
318
|
+
// Redux postStatus may already be 'publish' by the time the
|
|
319
|
+
// callback fires. The prevEvent carries the accurate prior status.
|
|
320
|
+
mockEditorState = {
|
|
321
|
+
...mockEditorState,
|
|
322
|
+
postStatus: 'publish',
|
|
323
|
+
};
|
|
324
|
+
const alice = makeCollaborator();
|
|
325
|
+
renderHook( () => useCollaboratorNotifications( 123, 'post' ) );
|
|
326
|
+
|
|
327
|
+
mockOnPostSaveCallback?.(
|
|
328
|
+
{
|
|
329
|
+
savedAt: Date.now() + 2000,
|
|
330
|
+
savedByClientId: alice.clientId,
|
|
331
|
+
postStatus: 'publish',
|
|
332
|
+
},
|
|
333
|
+
alice,
|
|
334
|
+
{
|
|
335
|
+
savedAt: Date.now() + 1000,
|
|
336
|
+
savedByClientId: alice.clientId,
|
|
337
|
+
postStatus: 'draft',
|
|
338
|
+
}
|
|
339
|
+
);
|
|
340
|
+
|
|
341
|
+
expect( mockCreateNotice ).toHaveBeenCalledWith(
|
|
342
|
+
'info',
|
|
343
|
+
'Post published by Alice.',
|
|
344
|
+
expect.objectContaining( {
|
|
345
|
+
id: 'collab-post-updated-100',
|
|
346
|
+
} )
|
|
347
|
+
);
|
|
348
|
+
} );
|
|
349
|
+
|
|
350
|
+
it( 'does not fire a notification when postStatus is undefined', () => {
|
|
351
|
+
mockEditorState = {
|
|
352
|
+
...mockEditorState,
|
|
353
|
+
postStatus: undefined as any,
|
|
354
|
+
};
|
|
355
|
+
const alice = makeCollaborator();
|
|
356
|
+
renderHook( () => useCollaboratorNotifications( 123, 'post' ) );
|
|
357
|
+
|
|
358
|
+
mockOnPostSaveCallback?.(
|
|
359
|
+
{
|
|
360
|
+
savedAt: Date.now(),
|
|
361
|
+
savedByClientId: alice.clientId,
|
|
362
|
+
postStatus: undefined,
|
|
363
|
+
},
|
|
364
|
+
alice,
|
|
365
|
+
null
|
|
366
|
+
);
|
|
367
|
+
|
|
368
|
+
expect( mockCreateNotice ).not.toHaveBeenCalled();
|
|
369
|
+
} );
|
|
370
|
+
} );
|
|
371
|
+
|
|
372
|
+
describe( 'when notifications are disabled', () => {
|
|
373
|
+
it( 'passes null postId to hooks when showCollaborationNotifications preference is false', () => {
|
|
374
|
+
mockEditorState = {
|
|
375
|
+
...mockEditorState,
|
|
376
|
+
showCollaborationNotifications: false,
|
|
377
|
+
};
|
|
378
|
+
renderHook( () => useCollaboratorNotifications( 123, 'post' ) );
|
|
379
|
+
|
|
380
|
+
expect( lastJoinPostId ).toBeNull();
|
|
381
|
+
expect( lastLeavePostId ).toBeNull();
|
|
382
|
+
expect( lastSavePostId ).toBeNull();
|
|
383
|
+
} );
|
|
384
|
+
|
|
385
|
+
it( 'passes null postId to hooks when collaboration is disabled', () => {
|
|
386
|
+
mockEditorState = {
|
|
387
|
+
...mockEditorState,
|
|
388
|
+
isCollaborationEnabled: false,
|
|
389
|
+
};
|
|
390
|
+
renderHook( () => useCollaboratorNotifications( 123, 'post' ) );
|
|
391
|
+
|
|
392
|
+
expect( lastJoinPostId ).toBeNull();
|
|
393
|
+
expect( lastLeavePostId ).toBeNull();
|
|
394
|
+
expect( lastSavePostId ).toBeNull();
|
|
395
|
+
} );
|
|
396
|
+
} );
|
|
397
|
+
} );
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WordPress dependencies
|
|
3
|
+
*/
|
|
4
|
+
import { useDispatch, useSelect } from '@wordpress/data';
|
|
5
|
+
import { useCallback } from '@wordpress/element';
|
|
6
|
+
import { __, sprintf } from '@wordpress/i18n';
|
|
7
|
+
import { store as noticesStore } from '@wordpress/notices';
|
|
8
|
+
import {
|
|
9
|
+
privateApis,
|
|
10
|
+
type PostEditorAwarenessState,
|
|
11
|
+
type PostSaveEvent,
|
|
12
|
+
} from '@wordpress/core-data';
|
|
13
|
+
import { store as preferencesStore } from '@wordpress/preferences';
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Internal dependencies
|
|
17
|
+
*/
|
|
18
|
+
import { unlock } from '../../lock-unlock';
|
|
19
|
+
import { store as editorStore } from '../../store';
|
|
20
|
+
|
|
21
|
+
const { useOnCollaboratorJoin, useOnCollaboratorLeave, useOnPostSave } =
|
|
22
|
+
unlock( privateApis );
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Notice IDs for each notification type. Using stable IDs prevents duplicate
|
|
26
|
+
* notices if the same event is processed more than once.
|
|
27
|
+
*/
|
|
28
|
+
const NOTIFICATION_TYPE = {
|
|
29
|
+
COLLAB_POST_UPDATED: 'collab-post-updated',
|
|
30
|
+
COLLAB_USER_ENTERED: 'collab-user-entered',
|
|
31
|
+
COLLAB_USER_EXITED: 'collab-user-exited',
|
|
32
|
+
} as const;
|
|
33
|
+
|
|
34
|
+
const PUBLISHED_STATUSES = [ 'publish', 'private', 'future' ];
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Returns the snackbar message for a post updated notification.
|
|
38
|
+
*
|
|
39
|
+
* @param name Display name of the collaborator who saved.
|
|
40
|
+
* @param status WordPress post status at the time of save.
|
|
41
|
+
* @param isFirstPublish Whether this save transitioned the post to published.
|
|
42
|
+
*/
|
|
43
|
+
function getPostUpdatedMessage(
|
|
44
|
+
name: string,
|
|
45
|
+
status: string,
|
|
46
|
+
isFirstPublish: boolean
|
|
47
|
+
): string {
|
|
48
|
+
if ( isFirstPublish ) {
|
|
49
|
+
/* translators: %s: collaborator display name */
|
|
50
|
+
return sprintf( __( 'Post published by %s.' ), name );
|
|
51
|
+
}
|
|
52
|
+
if ( PUBLISHED_STATUSES.includes( status ) ) {
|
|
53
|
+
/* translators: %s: collaborator display name */
|
|
54
|
+
return sprintf( __( 'Post updated by %s.' ), name );
|
|
55
|
+
}
|
|
56
|
+
/* translators: %s: collaborator display name */
|
|
57
|
+
return sprintf( __( 'Draft saved by %s.' ), name );
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Hook that watches for collaborator join/leave events and remote save events,
|
|
62
|
+
* dispatching snackbar notices accordingly.
|
|
63
|
+
*
|
|
64
|
+
* @param postId The ID of the post being edited.
|
|
65
|
+
* @param postType The post type of the post being edited.
|
|
66
|
+
*/
|
|
67
|
+
export function useCollaboratorNotifications(
|
|
68
|
+
postId: number | null,
|
|
69
|
+
postType: string | null
|
|
70
|
+
): void {
|
|
71
|
+
const { postStatus, isCollaborationEnabled, showNotifications } = useSelect(
|
|
72
|
+
( select ) => {
|
|
73
|
+
const {
|
|
74
|
+
getCurrentPostAttribute,
|
|
75
|
+
isCollaborationEnabledForCurrentPost,
|
|
76
|
+
} = unlock( select( editorStore ) );
|
|
77
|
+
return {
|
|
78
|
+
postStatus: getCurrentPostAttribute( 'status' ) as
|
|
79
|
+
| string
|
|
80
|
+
| undefined,
|
|
81
|
+
isCollaborationEnabled: isCollaborationEnabledForCurrentPost(),
|
|
82
|
+
showNotifications:
|
|
83
|
+
select( preferencesStore ).get(
|
|
84
|
+
'core',
|
|
85
|
+
'showCollaborationNotifications'
|
|
86
|
+
) ?? true,
|
|
87
|
+
};
|
|
88
|
+
},
|
|
89
|
+
[]
|
|
90
|
+
);
|
|
91
|
+
|
|
92
|
+
const { createNotice } = useDispatch( noticesStore );
|
|
93
|
+
|
|
94
|
+
// Pass null when collaboration is disabled or notifications are
|
|
95
|
+
// turned off to prevent the hooks from subscribing to awareness state.
|
|
96
|
+
const shouldSubscribe = isCollaborationEnabled && showNotifications;
|
|
97
|
+
const effectivePostId = shouldSubscribe ? postId : null;
|
|
98
|
+
const effectivePostType = shouldSubscribe ? postType : null;
|
|
99
|
+
|
|
100
|
+
useOnCollaboratorJoin(
|
|
101
|
+
effectivePostId,
|
|
102
|
+
effectivePostType,
|
|
103
|
+
useCallback(
|
|
104
|
+
(
|
|
105
|
+
collaborator: PostEditorAwarenessState,
|
|
106
|
+
me?: PostEditorAwarenessState
|
|
107
|
+
) => {
|
|
108
|
+
/*
|
|
109
|
+
* Skip collaborators who were present before the current user
|
|
110
|
+
* joined. Their enteredAt is earlier than ours, meaning we're
|
|
111
|
+
* the newcomer.
|
|
112
|
+
*/
|
|
113
|
+
if (
|
|
114
|
+
me &&
|
|
115
|
+
collaborator.collaboratorInfo.enteredAt <
|
|
116
|
+
me.collaboratorInfo.enteredAt
|
|
117
|
+
) {
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
void createNotice(
|
|
122
|
+
'info',
|
|
123
|
+
sprintf(
|
|
124
|
+
/* translators: %s: collaborator display name */
|
|
125
|
+
__( '%s has joined the post.' ),
|
|
126
|
+
collaborator.collaboratorInfo.name
|
|
127
|
+
),
|
|
128
|
+
{
|
|
129
|
+
id: `${ NOTIFICATION_TYPE.COLLAB_USER_ENTERED }-${ collaborator.collaboratorInfo.id }`,
|
|
130
|
+
type: 'snackbar',
|
|
131
|
+
isDismissible: false,
|
|
132
|
+
}
|
|
133
|
+
);
|
|
134
|
+
},
|
|
135
|
+
[ createNotice ]
|
|
136
|
+
)
|
|
137
|
+
);
|
|
138
|
+
|
|
139
|
+
useOnCollaboratorLeave(
|
|
140
|
+
effectivePostId,
|
|
141
|
+
effectivePostType,
|
|
142
|
+
useCallback(
|
|
143
|
+
( collaborator: PostEditorAwarenessState ) => {
|
|
144
|
+
void createNotice(
|
|
145
|
+
'info',
|
|
146
|
+
sprintf(
|
|
147
|
+
/* translators: %s: collaborator display name */
|
|
148
|
+
__( '%s has left the post.' ),
|
|
149
|
+
collaborator.collaboratorInfo.name
|
|
150
|
+
),
|
|
151
|
+
{
|
|
152
|
+
id: `${ NOTIFICATION_TYPE.COLLAB_USER_EXITED }-${ collaborator.collaboratorInfo.id }`,
|
|
153
|
+
type: 'snackbar',
|
|
154
|
+
isDismissible: false,
|
|
155
|
+
}
|
|
156
|
+
);
|
|
157
|
+
},
|
|
158
|
+
[ createNotice ]
|
|
159
|
+
)
|
|
160
|
+
);
|
|
161
|
+
|
|
162
|
+
useOnPostSave(
|
|
163
|
+
effectivePostId,
|
|
164
|
+
effectivePostType,
|
|
165
|
+
useCallback(
|
|
166
|
+
(
|
|
167
|
+
saveEvent: PostSaveEvent,
|
|
168
|
+
saver: PostEditorAwarenessState,
|
|
169
|
+
prevEvent: PostSaveEvent | null
|
|
170
|
+
) => {
|
|
171
|
+
if ( ! postStatus ) {
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// Prefer the remote status from Y.Doc (accurate at save time)
|
|
176
|
+
// over the local Redux value, which may not have synced yet.
|
|
177
|
+
const effectiveStatus =
|
|
178
|
+
saveEvent.postStatus ?? postStatus ?? 'draft';
|
|
179
|
+
|
|
180
|
+
// Use the previous save event's status when available for
|
|
181
|
+
// accurate first-publish detection across rapid saves.
|
|
182
|
+
const prevStatus = prevEvent?.postStatus ?? postStatus;
|
|
183
|
+
const isFirstPublish =
|
|
184
|
+
! (
|
|
185
|
+
prevStatus && PUBLISHED_STATUSES.includes( prevStatus )
|
|
186
|
+
) && PUBLISHED_STATUSES.includes( effectiveStatus );
|
|
187
|
+
|
|
188
|
+
const message = getPostUpdatedMessage(
|
|
189
|
+
saver.collaboratorInfo.name,
|
|
190
|
+
effectiveStatus,
|
|
191
|
+
isFirstPublish
|
|
192
|
+
);
|
|
193
|
+
|
|
194
|
+
void createNotice( 'info', message, {
|
|
195
|
+
id: `${ NOTIFICATION_TYPE.COLLAB_POST_UPDATED }-${ saver.collaboratorInfo.id }`,
|
|
196
|
+
type: 'snackbar',
|
|
197
|
+
isDismissible: false,
|
|
198
|
+
} );
|
|
199
|
+
},
|
|
200
|
+
[ createNotice, postStatus ]
|
|
201
|
+
)
|
|
202
|
+
);
|
|
203
|
+
}
|
|
@@ -7,7 +7,7 @@ import clsx from 'clsx';
|
|
|
7
7
|
* WordPress dependencies
|
|
8
8
|
*/
|
|
9
9
|
import { InterfaceSkeleton, ComplementaryArea } from '@wordpress/interface';
|
|
10
|
-
import { useSelect } from '@wordpress/data';
|
|
10
|
+
import { useSelect, useDispatch } from '@wordpress/data';
|
|
11
11
|
import { __ } from '@wordpress/i18n';
|
|
12
12
|
import { store as preferencesStore } from '@wordpress/preferences';
|
|
13
13
|
import { BlockBreadcrumb, BlockToolbar } from '@wordpress/block-editor';
|
|
@@ -27,6 +27,7 @@ import InserterSidebar from '../inserter-sidebar';
|
|
|
27
27
|
import ListViewSidebar from '../list-view-sidebar';
|
|
28
28
|
import { RevisionsHeader, RevisionsCanvas } from '../post-revisions-preview';
|
|
29
29
|
import { CollaboratorsOverlay } from '../collaborators-overlay';
|
|
30
|
+
import { useCollaboratorNotifications } from '../collaborators-presence/use-collaborator-notifications';
|
|
30
31
|
import SavePublishPanels from '../save-publish-panels';
|
|
31
32
|
import TextEditor from '../text-editor';
|
|
32
33
|
import VisualEditor from '../visual-editor';
|
|
@@ -81,6 +82,7 @@ export default function EditorInterface( {
|
|
|
81
82
|
stylesPath,
|
|
82
83
|
showStylebook,
|
|
83
84
|
isRevisionsMode,
|
|
85
|
+
showDiff,
|
|
84
86
|
} = useSelect( ( select ) => {
|
|
85
87
|
const { get } = select( preferencesStore );
|
|
86
88
|
const {
|
|
@@ -93,6 +95,7 @@ export default function EditorInterface( {
|
|
|
93
95
|
getStylesPath,
|
|
94
96
|
getShowStylebook,
|
|
95
97
|
isRevisionsMode: _isRevisionsMode,
|
|
98
|
+
isShowingRevisionDiff,
|
|
96
99
|
} = unlock( select( editorStore ) );
|
|
97
100
|
const editorSettings = getEditorSettings();
|
|
98
101
|
|
|
@@ -120,8 +123,15 @@ export default function EditorInterface( {
|
|
|
120
123
|
getCurrentPostType() === 'attachment' &&
|
|
121
124
|
window?.__experimentalMediaEditor,
|
|
122
125
|
isRevisionsMode: _isRevisionsMode(),
|
|
126
|
+
showDiff: isShowingRevisionDiff(),
|
|
123
127
|
};
|
|
124
128
|
}, [] );
|
|
129
|
+
const { setShowRevisionDiff } = unlock( useDispatch( editorStore ) );
|
|
130
|
+
|
|
131
|
+
// Runs unconditionally so join/leave/save notifications are dispatched
|
|
132
|
+
// regardless of viewport width or whether the header centre area is visible.
|
|
133
|
+
useCollaboratorNotifications( postId, postType );
|
|
134
|
+
|
|
125
135
|
const isLargeViewport = useViewportMatch( 'medium' );
|
|
126
136
|
const secondarySidebarLabel = isListViewOpened
|
|
127
137
|
? __( 'Document Overview' )
|
|
@@ -147,9 +157,6 @@ export default function EditorInterface( {
|
|
|
147
157
|
[ entitiesSavedStatesCallback ]
|
|
148
158
|
);
|
|
149
159
|
|
|
150
|
-
// Local state for diff toggle in revisions mode.
|
|
151
|
-
const [ showDiff, setShowDiff ] = useState( true );
|
|
152
|
-
|
|
153
160
|
// When in revisions mode, render the revisions interface.
|
|
154
161
|
if ( isRevisionsMode ) {
|
|
155
162
|
return (
|
|
@@ -159,10 +166,10 @@ export default function EditorInterface( {
|
|
|
159
166
|
header={
|
|
160
167
|
<RevisionsHeader
|
|
161
168
|
showDiff={ showDiff }
|
|
162
|
-
onToggleDiff={ () =>
|
|
169
|
+
onToggleDiff={ () => setShowRevisionDiff( ! showDiff ) }
|
|
163
170
|
/>
|
|
164
171
|
}
|
|
165
|
-
content={ <RevisionsCanvas
|
|
172
|
+
content={ <RevisionsCanvas /> }
|
|
166
173
|
sidebar={ <ComplementaryArea.Slot scope="core" /> }
|
|
167
174
|
/>
|
|
168
175
|
);
|
|
@@ -85,7 +85,10 @@ export default function InserterSidebar() {
|
|
|
85
85
|
showMostUsedBlocks={ showMostUsedBlocks }
|
|
86
86
|
showInserterHelpPanel
|
|
87
87
|
shouldFocusBlock={ isMobileViewport }
|
|
88
|
-
rootClientId={
|
|
88
|
+
rootClientId={
|
|
89
|
+
blockSectionRootClientId ?? inserter.rootClientId
|
|
90
|
+
}
|
|
91
|
+
__experimentalInsertionIndex={ inserter.insertionIndex }
|
|
89
92
|
onSelect={ inserter.onSelect }
|
|
90
93
|
__experimentalInitialTab={ inserter.tab }
|
|
91
94
|
__experimentalInitialCategory={ inserter.category }
|