@wordpress/editor 14.44.0 → 14.44.1-next.v.202604201441.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/components/collab-sidebar/add-comment.cjs +6 -22
- package/build/components/collab-sidebar/add-comment.cjs.map +3 -3
- package/build/components/collab-sidebar/board-store.cjs +103 -0
- package/build/components/collab-sidebar/board-store.cjs.map +7 -0
- package/build/components/collab-sidebar/comment-form.cjs +2 -10
- package/build/components/collab-sidebar/comment-form.cjs.map +2 -2
- package/build/components/collab-sidebar/comments.cjs +29 -149
- package/build/components/collab-sidebar/comments.cjs.map +3 -3
- package/build/components/collab-sidebar/floating-container.cjs +62 -0
- package/build/components/collab-sidebar/floating-container.cjs.map +7 -0
- package/build/components/collab-sidebar/hooks.cjs +49 -41
- package/build/components/collab-sidebar/hooks.cjs.map +2 -2
- package/build/components/collab-sidebar/index.cjs +2 -13
- package/build/components/collab-sidebar/index.cjs.map +2 -2
- package/build/components/collab-sidebar/utils.cjs +72 -4
- package/build/components/collab-sidebar/utils.cjs.map +2 -2
- package/build/components/collaborators-presence/avatar/component.cjs.map +1 -1
- package/build/components/collaborators-presence/index.cjs +3 -3
- package/build/components/collaborators-presence/index.cjs.map +2 -2
- package/build/components/collaborators-presence/list.cjs +3 -3
- package/build/components/collaborators-presence/list.cjs.map +2 -2
- package/build/components/media-categories/index.cjs +1 -1
- package/build/components/media-categories/index.cjs.map +1 -1
- package/build/components/more-menu/index.cjs +1 -1
- package/build/components/more-menu/index.cjs.map +1 -1
- package/build/components/post-publish-panel/maybe-upload-media.cjs +1 -1
- package/build/components/post-publish-panel/maybe-upload-media.cjs.map +1 -1
- package/build/components/style-book/constants.cjs +1 -1
- package/build/components/style-book/constants.cjs.map +1 -1
- package/build/components/style-book/index.cjs +1 -1
- package/build/components/style-book/index.cjs.map +1 -1
- package/build-module/components/collab-sidebar/add-comment.mjs +8 -27
- package/build-module/components/collab-sidebar/add-comment.mjs.map +2 -2
- package/build-module/components/collab-sidebar/board-store.mjs +78 -0
- package/build-module/components/collab-sidebar/board-store.mjs.map +7 -0
- package/build-module/components/collab-sidebar/comment-form.mjs +4 -12
- package/build-module/components/collab-sidebar/comment-form.mjs.map +2 -2
- package/build-module/components/collab-sidebar/comments.mjs +30 -151
- package/build-module/components/collab-sidebar/comments.mjs.map +2 -2
- package/build-module/components/collab-sidebar/floating-container.mjs +27 -0
- package/build-module/components/collab-sidebar/floating-container.mjs.map +7 -0
- package/build-module/components/collab-sidebar/hooks.mjs +51 -44
- package/build-module/components/collab-sidebar/hooks.mjs.map +2 -2
- package/build-module/components/collab-sidebar/index.mjs +2 -13
- package/build-module/components/collab-sidebar/index.mjs.map +2 -2
- package/build-module/components/collab-sidebar/utils.mjs +71 -3
- package/build-module/components/collab-sidebar/utils.mjs.map +2 -2
- package/build-module/components/collaborators-presence/avatar/component.mjs.map +1 -1
- package/build-module/components/collaborators-presence/index.mjs +3 -3
- package/build-module/components/collaborators-presence/index.mjs.map +2 -2
- package/build-module/components/collaborators-presence/list.mjs +3 -3
- package/build-module/components/collaborators-presence/list.mjs.map +2 -2
- package/build-module/components/media-categories/index.mjs +1 -1
- package/build-module/components/media-categories/index.mjs.map +1 -1
- package/build-module/components/more-menu/index.mjs +1 -1
- package/build-module/components/more-menu/index.mjs.map +1 -1
- package/build-module/components/post-publish-panel/maybe-upload-media.mjs +1 -1
- package/build-module/components/post-publish-panel/maybe-upload-media.mjs.map +1 -1
- package/build-module/components/style-book/constants.mjs +1 -1
- package/build-module/components/style-book/constants.mjs.map +1 -1
- package/build-module/components/style-book/index.mjs +1 -1
- package/build-module/components/style-book/index.mjs.map +1 -1
- package/build-style/style-rtl.css +12 -30
- package/build-style/style.css +12 -30
- package/build-types/components/collab-sidebar/add-comment.d.ts +2 -6
- package/build-types/components/collab-sidebar/add-comment.d.ts.map +1 -1
- package/build-types/components/collab-sidebar/board-store.d.ts +8 -0
- package/build-types/components/collab-sidebar/board-store.d.ts.map +1 -0
- package/build-types/components/collab-sidebar/comment-form.d.ts +1 -3
- package/build-types/components/collab-sidebar/comment-form.d.ts.map +1 -1
- package/build-types/components/collab-sidebar/comments.d.ts +1 -3
- package/build-types/components/collab-sidebar/comments.d.ts.map +1 -1
- 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/hooks.d.ts +13 -9
- package/build-types/components/collab-sidebar/hooks.d.ts.map +1 -1
- package/build-types/components/collab-sidebar/index.d.ts.map +1 -1
- package/build-types/components/collab-sidebar/utils.d.ts +27 -4
- package/build-types/components/collab-sidebar/utils.d.ts.map +1 -1
- package/build-types/components/style-book/constants.d.ts +1 -1
- package/build-types/components/style-book/constants.d.ts.map +1 -1
- package/package.json +45 -45
- package/src/components/collab-sidebar/add-comment.js +9 -31
- package/src/components/collab-sidebar/board-store.js +83 -0
- package/src/components/collab-sidebar/comment-form.js +5 -14
- package/src/components/collab-sidebar/comments.js +29 -202
- package/src/components/collab-sidebar/floating-container.js +29 -0
- package/src/components/collab-sidebar/hooks.js +60 -48
- package/src/components/collab-sidebar/index.js +3 -14
- package/src/components/collab-sidebar/test/utils.js +153 -0
- package/src/components/collab-sidebar/utils.js +112 -4
- package/src/components/collaborators-presence/avatar/component.tsx +1 -1
- package/src/components/collaborators-presence/styles/collaborators-list.scss +1 -1
- package/src/components/collaborators-presence/styles/collaborators-presence.scss +1 -1
- package/src/components/document-outline/style.scss +1 -1
- package/src/components/media-categories/index.js +1 -1
- package/src/components/more-menu/index.js +1 -1
- package/src/components/post-publish-panel/maybe-upload-media.js +1 -1
- package/src/components/post-publish-panel/test/__snapshots__/index.js.snap +2 -2
- package/src/components/post-revisions-preview/style.scss +1 -1
- package/src/components/style-book/constants.ts +1 -1
- package/src/components/style-book/index.js +1 -1
- package/src/components/template-actions-panel/style.scss +1 -1
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
export function createBoardStore() {
|
|
2
|
+
const listeners = new Set();
|
|
3
|
+
const blockRefs = new Map();
|
|
4
|
+
const floatingRefs = new Map();
|
|
5
|
+
const idByElement = new WeakMap();
|
|
6
|
+
const heights = {};
|
|
7
|
+
let snapshot = {};
|
|
8
|
+
|
|
9
|
+
function emit() {
|
|
10
|
+
snapshot = { ...heights };
|
|
11
|
+
for ( const listener of listeners ) {
|
|
12
|
+
listener();
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const observer = new window.ResizeObserver( ( entries ) => {
|
|
17
|
+
let changed = false;
|
|
18
|
+
for ( const entry of entries ) {
|
|
19
|
+
const id = idByElement.get( entry.target );
|
|
20
|
+
const newHeight = entry.borderBoxSize[ 0 ].blockSize;
|
|
21
|
+
if ( heights[ id ] !== newHeight ) {
|
|
22
|
+
heights[ id ] = newHeight;
|
|
23
|
+
changed = true;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
if ( changed ) {
|
|
27
|
+
emit();
|
|
28
|
+
}
|
|
29
|
+
} );
|
|
30
|
+
|
|
31
|
+
return {
|
|
32
|
+
subscribe( listener ) {
|
|
33
|
+
listeners.add( listener );
|
|
34
|
+
return () => {
|
|
35
|
+
listeners.delete( listener );
|
|
36
|
+
if ( listeners.size === 0 ) {
|
|
37
|
+
observer.disconnect();
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
},
|
|
41
|
+
|
|
42
|
+
getSnapshot() {
|
|
43
|
+
return snapshot;
|
|
44
|
+
},
|
|
45
|
+
|
|
46
|
+
registerThread( id, blockEl, floatingEl ) {
|
|
47
|
+
blockRefs.set( id, blockEl );
|
|
48
|
+
|
|
49
|
+
const prev = floatingRefs.get( id );
|
|
50
|
+
if ( prev && prev !== floatingEl ) {
|
|
51
|
+
observer.unobserve( prev );
|
|
52
|
+
idByElement.delete( prev );
|
|
53
|
+
}
|
|
54
|
+
if ( floatingEl ) {
|
|
55
|
+
floatingRefs.set( id, floatingEl );
|
|
56
|
+
idByElement.set( floatingEl, id );
|
|
57
|
+
observer.observe( floatingEl );
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
emit();
|
|
61
|
+
},
|
|
62
|
+
|
|
63
|
+
unregisterThread( id ) {
|
|
64
|
+
blockRefs.delete( id );
|
|
65
|
+
const prev = floatingRefs.get( id );
|
|
66
|
+
if ( prev ) {
|
|
67
|
+
observer.unobserve( prev );
|
|
68
|
+
idByElement.delete( prev );
|
|
69
|
+
floatingRefs.delete( id );
|
|
70
|
+
}
|
|
71
|
+
delete heights[ id ];
|
|
72
|
+
},
|
|
73
|
+
|
|
74
|
+
getBlockRects() {
|
|
75
|
+
// Batch all rect reads before any writes to avoid layout thrashing.
|
|
76
|
+
return Object.fromEntries(
|
|
77
|
+
Array.from( blockRefs ).flatMap( ( [ id, el ] ) =>
|
|
78
|
+
el ? [ [ id, el.getBoundingClientRect() ] ] : []
|
|
79
|
+
)
|
|
80
|
+
);
|
|
81
|
+
},
|
|
82
|
+
};
|
|
83
|
+
}
|
|
@@ -15,13 +15,13 @@ import {
|
|
|
15
15
|
VisuallyHidden,
|
|
16
16
|
} from '@wordpress/components';
|
|
17
17
|
import { __ } from '@wordpress/i18n';
|
|
18
|
-
import { useInstanceId
|
|
18
|
+
import { useInstanceId } from '@wordpress/compose';
|
|
19
19
|
import { isKeyboardEvent } from '@wordpress/keycodes';
|
|
20
20
|
|
|
21
21
|
/**
|
|
22
22
|
* Internal dependencies
|
|
23
23
|
*/
|
|
24
|
-
import { sanitizeCommentString
|
|
24
|
+
import { sanitizeCommentString } from './utils';
|
|
25
25
|
|
|
26
26
|
function CommentForm( {
|
|
27
27
|
onSubmit,
|
|
@@ -29,19 +29,11 @@ function CommentForm( {
|
|
|
29
29
|
thread,
|
|
30
30
|
submitButtonText,
|
|
31
31
|
labelText,
|
|
32
|
-
reflowComments = noop,
|
|
33
32
|
} ) {
|
|
34
33
|
const [ inputComment, setInputComment ] = useState(
|
|
35
34
|
thread?.content?.raw ?? ''
|
|
36
35
|
);
|
|
37
36
|
|
|
38
|
-
// Regularly trigger a reflow as the user types since the textarea may grow or shrink.
|
|
39
|
-
const debouncedCommentUpdated = useDebounce( reflowComments, 100 );
|
|
40
|
-
|
|
41
|
-
const updateComment = ( value ) => {
|
|
42
|
-
setInputComment( value );
|
|
43
|
-
};
|
|
44
|
-
|
|
45
37
|
const inputId = useInstanceId( CommentForm, 'comment-input' );
|
|
46
38
|
const isDisabled =
|
|
47
39
|
inputComment === thread?.content?.raw ||
|
|
@@ -64,10 +56,9 @@ function CommentForm( {
|
|
|
64
56
|
<TextareaAutosize
|
|
65
57
|
id={ inputId }
|
|
66
58
|
value={ inputComment ?? '' }
|
|
67
|
-
onChange={ ( comment ) =>
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
} }
|
|
59
|
+
onChange={ ( comment ) =>
|
|
60
|
+
setInputComment( comment.target.value )
|
|
61
|
+
}
|
|
71
62
|
rows={ 1 }
|
|
72
63
|
maxRows={ 20 }
|
|
73
64
|
onKeyDown={ ( event ) => {
|
|
@@ -10,7 +10,6 @@ import {
|
|
|
10
10
|
useState,
|
|
11
11
|
RawHTML,
|
|
12
12
|
useEffect,
|
|
13
|
-
useCallback,
|
|
14
13
|
useMemo,
|
|
15
14
|
useRef,
|
|
16
15
|
} from '@wordpress/element';
|
|
@@ -41,7 +40,8 @@ import { unlock } from '../../lock-unlock';
|
|
|
41
40
|
import CommentAuthorInfo from './comment-author-info';
|
|
42
41
|
import CommentForm from './comment-form';
|
|
43
42
|
import { focusCommentThread, getCommentExcerpt } from './utils';
|
|
44
|
-
import { useFloatingThread } from './hooks';
|
|
43
|
+
import { useFloatingBoard, useFloatingThread } from './hooks';
|
|
44
|
+
import { FloatingContainer } from './floating-container';
|
|
45
45
|
import { AddComment } from './add-comment';
|
|
46
46
|
import { store as editorStore } from '../../store';
|
|
47
47
|
|
|
@@ -54,17 +54,9 @@ export function Comments( {
|
|
|
54
54
|
onAddReply,
|
|
55
55
|
onCommentDelete,
|
|
56
56
|
commentSidebarRef,
|
|
57
|
-
reflowComments,
|
|
58
57
|
isFloating = false,
|
|
59
|
-
commentLastUpdated,
|
|
60
58
|
} ) {
|
|
61
|
-
const
|
|
62
|
-
const [ boardOffsets, setBoardOffsets ] = useState( {} );
|
|
63
|
-
const [ blockRefs, setBlockRefs ] = useState( {} );
|
|
64
|
-
|
|
65
|
-
const { setCanvasMinHeight, selectNote } = unlock(
|
|
66
|
-
useDispatch( editorStore )
|
|
67
|
-
);
|
|
59
|
+
const { selectNote } = unlock( useDispatch( editorStore ) );
|
|
68
60
|
const { selectBlock, toggleBlockSpotlight } = unlock(
|
|
69
61
|
useDispatch( blockEditorStore )
|
|
70
62
|
);
|
|
@@ -182,151 +174,13 @@ export function Comments( {
|
|
|
182
174
|
}
|
|
183
175
|
}, [ noteFocused, selectedNote, selectNote, commentSidebarRef ] );
|
|
184
176
|
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
*/
|
|
191
|
-
const calculateAllOffsets = () => {
|
|
192
|
-
const offsets = {};
|
|
193
|
-
|
|
194
|
-
if ( ! isFloating ) {
|
|
195
|
-
return { offsets, minHeight: 0 };
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
// Find the index of the selected thread.
|
|
199
|
-
const selectedThreadIndex = threads.findIndex(
|
|
200
|
-
( t ) => t.id === selectedNote
|
|
201
|
-
);
|
|
202
|
-
|
|
203
|
-
const breakIndex =
|
|
204
|
-
selectedThreadIndex === -1 ? 0 : selectedThreadIndex;
|
|
205
|
-
|
|
206
|
-
// If there is a selected thread, push threads above up and threads below down.
|
|
207
|
-
const selectedThreadData = threads[ breakIndex ];
|
|
208
|
-
|
|
209
|
-
if (
|
|
210
|
-
! selectedThreadData ||
|
|
211
|
-
! blockRefs[ selectedThreadData.id ]
|
|
212
|
-
) {
|
|
213
|
-
return { offsets, minHeight: 0 };
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
let blockElement = blockRefs[ selectedThreadData.id ];
|
|
217
|
-
let blockRect = blockElement?.getBoundingClientRect();
|
|
218
|
-
const selectedThreadTop = blockRect?.top || 0;
|
|
219
|
-
const selectedThreadHeight = heights[ selectedThreadData.id ] || 0;
|
|
220
|
-
|
|
221
|
-
offsets[ selectedThreadData.id ] = -16;
|
|
222
|
-
|
|
223
|
-
let previousThreadData = {
|
|
224
|
-
threadTop: selectedThreadTop - 16,
|
|
225
|
-
threadHeight: selectedThreadHeight,
|
|
226
|
-
};
|
|
227
|
-
|
|
228
|
-
// Process threads after the selected thread, offsetting any overlapping
|
|
229
|
-
// threads downward.
|
|
230
|
-
for ( let i = breakIndex + 1; i < threads.length; i++ ) {
|
|
231
|
-
const thread = threads[ i ];
|
|
232
|
-
if ( ! blockRefs[ thread.id ] ) {
|
|
233
|
-
continue;
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
blockElement = blockRefs[ thread.id ];
|
|
237
|
-
blockRect = blockElement?.getBoundingClientRect();
|
|
238
|
-
const threadTop = blockRect?.top || 0;
|
|
239
|
-
const threadHeight = heights[ thread.id ] || 0;
|
|
240
|
-
|
|
241
|
-
let additionalOffset = -16;
|
|
242
|
-
|
|
243
|
-
// Check if the thread overlaps with the previous one.
|
|
244
|
-
const previousBottom =
|
|
245
|
-
previousThreadData.threadTop +
|
|
246
|
-
previousThreadData.threadHeight;
|
|
247
|
-
if ( threadTop < previousBottom + 16 ) {
|
|
248
|
-
// Shift down by the difference plus a margin to avoid overlap.
|
|
249
|
-
additionalOffset = previousBottom - threadTop + 20;
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
offsets[ thread.id ] = additionalOffset;
|
|
253
|
-
|
|
254
|
-
// Update for next iteration.
|
|
255
|
-
previousThreadData = {
|
|
256
|
-
threadTop: threadTop + additionalOffset,
|
|
257
|
-
threadHeight,
|
|
258
|
-
};
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
// Process threads before the selected thread, offsetting any overlapping
|
|
262
|
-
// threads upward.
|
|
263
|
-
let nextThreadData = {
|
|
264
|
-
threadTop: selectedThreadTop - 16,
|
|
265
|
-
};
|
|
266
|
-
|
|
267
|
-
for ( let i = selectedThreadIndex - 1; i >= 0; i-- ) {
|
|
268
|
-
const thread = threads[ i ];
|
|
269
|
-
if ( ! blockRefs[ thread.id ] ) {
|
|
270
|
-
continue;
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
blockElement = blockRefs[ thread.id ];
|
|
274
|
-
blockRect = blockElement?.getBoundingClientRect();
|
|
275
|
-
const threadTop = blockRect?.top || 0;
|
|
276
|
-
const threadHeight = heights[ thread.id ] || 0;
|
|
277
|
-
|
|
278
|
-
let additionalOffset = -16;
|
|
279
|
-
|
|
280
|
-
// Calculate the bottom position of this thread with default offset.
|
|
281
|
-
const threadBottom = threadTop + threadHeight;
|
|
282
|
-
|
|
283
|
-
// Check if this thread's bottom would overlap with the next thread's top.
|
|
284
|
-
if ( threadBottom > nextThreadData.threadTop ) {
|
|
285
|
-
// Shift up by the difference plus a margin to avoid overlap.
|
|
286
|
-
additionalOffset =
|
|
287
|
-
nextThreadData.threadTop -
|
|
288
|
-
threadTop -
|
|
289
|
-
threadHeight -
|
|
290
|
-
20;
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
offsets[ thread.id ] = additionalOffset;
|
|
294
|
-
|
|
295
|
-
// Update for next iteration (going upward).
|
|
296
|
-
nextThreadData = {
|
|
297
|
-
threadTop: threadTop + additionalOffset,
|
|
298
|
-
};
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
let editorMinHeight = 0;
|
|
302
|
-
// Take the calculated top of the final note plus its height as the editor min height.
|
|
303
|
-
const lastThread = threads[ threads.length - 1 ];
|
|
304
|
-
if ( blockRefs[ lastThread.id ] ) {
|
|
305
|
-
const lastBlockElement = blockRefs[ lastThread.id ];
|
|
306
|
-
const lastBlockRect = lastBlockElement?.getBoundingClientRect();
|
|
307
|
-
const lastThreadTop = lastBlockRect?.top || 0;
|
|
308
|
-
const lastThreadHeight = heights[ lastThread.id ] || 0;
|
|
309
|
-
const lastThreadOffset = offsets[ lastThread.id ] || 0;
|
|
310
|
-
editorMinHeight =
|
|
311
|
-
lastThreadTop + lastThreadHeight + lastThreadOffset + 32;
|
|
312
|
-
}
|
|
313
|
-
|
|
314
|
-
return { offsets, minHeight: editorMinHeight };
|
|
315
|
-
};
|
|
316
|
-
const { offsets: newOffsets, minHeight } = calculateAllOffsets();
|
|
317
|
-
if ( Object.keys( newOffsets ).length > 0 ) {
|
|
318
|
-
setBoardOffsets( newOffsets );
|
|
177
|
+
const { boardOffsets, registerThread, unregisterThread } = useFloatingBoard(
|
|
178
|
+
{
|
|
179
|
+
threads,
|
|
180
|
+
selectedNoteId: selectedNote,
|
|
181
|
+
isFloating,
|
|
319
182
|
}
|
|
320
|
-
|
|
321
|
-
setCanvasMinHeight( minHeight );
|
|
322
|
-
}, [
|
|
323
|
-
heights,
|
|
324
|
-
blockRefs,
|
|
325
|
-
isFloating,
|
|
326
|
-
threads,
|
|
327
|
-
selectedNote,
|
|
328
|
-
setCanvasMinHeight,
|
|
329
|
-
] );
|
|
183
|
+
);
|
|
330
184
|
|
|
331
185
|
const handleThreadNavigation = ( event, thread, isSelected ) => {
|
|
332
186
|
if ( event.defaultPrevented ) {
|
|
@@ -393,10 +247,6 @@ export function Comments( {
|
|
|
393
247
|
}
|
|
394
248
|
};
|
|
395
249
|
|
|
396
|
-
const setBlockRef = useCallback( ( id, blockRef ) => {
|
|
397
|
-
setBlockRefs( ( prev ) => ( { ...prev, [ id ]: blockRef } ) );
|
|
398
|
-
}, [] );
|
|
399
|
-
|
|
400
250
|
const hasThreads = Array.isArray( threads ) && threads.length > 0;
|
|
401
251
|
// A special case for `template-locked` mode - https://github.com/WordPress/gutenberg/pull/72646.
|
|
402
252
|
if ( ! hasThreads && ! isFloating ) {
|
|
@@ -425,12 +275,16 @@ export function Comments( {
|
|
|
425
275
|
onEditComment={ onEditComment }
|
|
426
276
|
isSelected={ selectedNote === thread.id }
|
|
427
277
|
commentSidebarRef={ commentSidebarRef }
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
278
|
+
floating={
|
|
279
|
+
isFloating
|
|
280
|
+
? {
|
|
281
|
+
calculatedOffset:
|
|
282
|
+
boardOffsets[ thread.id ] ?? 0,
|
|
283
|
+
registerThread,
|
|
284
|
+
unregisterThread,
|
|
285
|
+
}
|
|
286
|
+
: undefined
|
|
287
|
+
}
|
|
434
288
|
onKeyDown={ ( event ) =>
|
|
435
289
|
handleThreadNavigation(
|
|
436
290
|
event,
|
|
@@ -451,22 +305,14 @@ function Thread( {
|
|
|
451
305
|
onCommentDelete,
|
|
452
306
|
isSelected,
|
|
453
307
|
commentSidebarRef,
|
|
454
|
-
|
|
455
|
-
isFloating,
|
|
456
|
-
calculatedOffset,
|
|
457
|
-
setHeights,
|
|
458
|
-
setBlockRef,
|
|
459
|
-
commentLastUpdated,
|
|
308
|
+
floating,
|
|
460
309
|
onKeyDown,
|
|
461
310
|
} ) {
|
|
311
|
+
const isFloating = !! floating;
|
|
462
312
|
const { toggleBlockHighlight, selectBlock, toggleBlockSpotlight } = unlock(
|
|
463
313
|
useDispatch( blockEditorStore )
|
|
464
314
|
);
|
|
465
315
|
const { selectNote } = unlock( useDispatch( editorStore ) );
|
|
466
|
-
const selectedNote = useSelect(
|
|
467
|
-
( select ) => unlock( select( editorStore ) ).getSelectedNote(),
|
|
468
|
-
[]
|
|
469
|
-
);
|
|
470
316
|
const relatedBlockElement = useBlockElement( thread.blockClientId );
|
|
471
317
|
const debouncedToggleBlockHighlight = useDebounce(
|
|
472
318
|
toggleBlockHighlight,
|
|
@@ -474,11 +320,9 @@ function Thread( {
|
|
|
474
320
|
);
|
|
475
321
|
const { y, refs } = useFloatingThread( {
|
|
476
322
|
thread,
|
|
477
|
-
calculatedOffset,
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
selectedThread: selectedNote,
|
|
481
|
-
commentLastUpdated,
|
|
323
|
+
calculatedOffset: floating?.calculatedOffset ?? 0,
|
|
324
|
+
registerThread: floating?.registerThread,
|
|
325
|
+
unregisterThread: floating?.unregisterThread,
|
|
482
326
|
} );
|
|
483
327
|
const isKeyboardTabbingRef = useRef( false );
|
|
484
328
|
|
|
@@ -570,19 +414,16 @@ function Thread( {
|
|
|
570
414
|
<AddComment
|
|
571
415
|
onSubmit={ onAddReply }
|
|
572
416
|
commentSidebarRef={ commentSidebarRef }
|
|
573
|
-
|
|
574
|
-
isFloating={ isFloating }
|
|
575
|
-
y={ y }
|
|
576
|
-
refs={ refs }
|
|
417
|
+
floating={ { y, refs } }
|
|
577
418
|
/>
|
|
578
419
|
);
|
|
579
420
|
}
|
|
580
421
|
|
|
581
422
|
return (
|
|
582
|
-
<
|
|
423
|
+
<FloatingContainer
|
|
424
|
+
floating={ isFloating ? { y, refs } : undefined }
|
|
583
425
|
className={ clsx( 'editor-collab-sidebar-panel__thread', {
|
|
584
426
|
'is-selected': isSelected,
|
|
585
|
-
'is-floating': isFloating,
|
|
586
427
|
} ) }
|
|
587
428
|
id={ `comment-thread-${ thread.id }` }
|
|
588
429
|
spacing="3"
|
|
@@ -607,8 +448,6 @@ function Thread( {
|
|
|
607
448
|
role="treeitem"
|
|
608
449
|
aria-label={ ariaLabel }
|
|
609
450
|
aria-expanded={ isSelected }
|
|
610
|
-
ref={ isFloating ? refs.setFloating : undefined }
|
|
611
|
-
style={ isFloating ? { top: y } : undefined }
|
|
612
451
|
>
|
|
613
452
|
<Button
|
|
614
453
|
className="editor-collab-sidebar-panel__skip-to-comment"
|
|
@@ -647,7 +486,6 @@ function Thread( {
|
|
|
647
486
|
}
|
|
648
487
|
} }
|
|
649
488
|
onDelete={ onCommentDelete }
|
|
650
|
-
reflowComments={ reflowComments }
|
|
651
489
|
/>
|
|
652
490
|
{ isSelected &&
|
|
653
491
|
allReplies.map( ( reply ) => (
|
|
@@ -658,7 +496,6 @@ function Thread( {
|
|
|
658
496
|
isExpanded={ isSelected }
|
|
659
497
|
onEdit={ onEditComment }
|
|
660
498
|
onDelete={ onCommentDelete }
|
|
661
|
-
reflowComments={ reflowComments }
|
|
662
499
|
/>
|
|
663
500
|
) ) }
|
|
664
501
|
{ ! isSelected && restReplies.length > 0 && (
|
|
@@ -694,7 +531,6 @@ function Thread( {
|
|
|
694
531
|
isExpanded={ isSelected }
|
|
695
532
|
onEdit={ onEditComment }
|
|
696
533
|
onDelete={ onCommentDelete }
|
|
697
|
-
reflowComments={ reflowComments }
|
|
698
534
|
/>
|
|
699
535
|
) }
|
|
700
536
|
{ isSelected && (
|
|
@@ -741,7 +577,6 @@ function Thread( {
|
|
|
741
577
|
thread.id,
|
|
742
578
|
thread.author_name
|
|
743
579
|
) }
|
|
744
|
-
reflowComments={ reflowComments }
|
|
745
580
|
/>
|
|
746
581
|
</VStack>
|
|
747
582
|
</VStack>
|
|
@@ -759,18 +594,11 @@ function Thread( {
|
|
|
759
594
|
{ __( 'Back to block' ) }
|
|
760
595
|
</Button>
|
|
761
596
|
) }
|
|
762
|
-
</
|
|
597
|
+
</FloatingContainer>
|
|
763
598
|
);
|
|
764
599
|
}
|
|
765
600
|
|
|
766
|
-
const CommentBoard = ( {
|
|
767
|
-
thread,
|
|
768
|
-
parent,
|
|
769
|
-
isExpanded,
|
|
770
|
-
onEdit,
|
|
771
|
-
onDelete,
|
|
772
|
-
reflowComments,
|
|
773
|
-
} ) => {
|
|
601
|
+
const CommentBoard = ( { thread, parent, isExpanded, onEdit, onDelete } ) => {
|
|
774
602
|
const [ actionState, setActionState ] = useState( false );
|
|
775
603
|
const [ showConfirmDialog, setShowConfirmDialog ] = useState( false );
|
|
776
604
|
const actionButtonRef = useRef( null );
|
|
@@ -930,7 +758,6 @@ const CommentBoard = ( {
|
|
|
930
758
|
thread.id,
|
|
931
759
|
thread.author_name
|
|
932
760
|
) }
|
|
933
|
-
reflowComments={ reflowComments }
|
|
934
761
|
/>
|
|
935
762
|
) : (
|
|
936
763
|
<RawHTML
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* External dependencies
|
|
3
|
+
*/
|
|
4
|
+
import clsx from 'clsx';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* WordPress dependencies
|
|
8
|
+
*/
|
|
9
|
+
import { __experimentalVStack as VStack } from '@wordpress/components';
|
|
10
|
+
|
|
11
|
+
export function FloatingContainer( {
|
|
12
|
+
floating,
|
|
13
|
+
className,
|
|
14
|
+
style,
|
|
15
|
+
children,
|
|
16
|
+
...props
|
|
17
|
+
} ) {
|
|
18
|
+
const isFloating = !! floating;
|
|
19
|
+
return (
|
|
20
|
+
<VStack
|
|
21
|
+
className={ clsx( className, { 'is-floating': isFloating } ) }
|
|
22
|
+
ref={ isFloating ? floating.refs.setFloating : undefined }
|
|
23
|
+
style={ isFloating ? { top: floating.y, ...style } : style }
|
|
24
|
+
{ ...props }
|
|
25
|
+
>
|
|
26
|
+
{ children }
|
|
27
|
+
</VStack>
|
|
28
|
+
);
|
|
29
|
+
}
|
|
@@ -12,10 +12,10 @@ import {
|
|
|
12
12
|
*/
|
|
13
13
|
import { __ } from '@wordpress/i18n';
|
|
14
14
|
import {
|
|
15
|
+
useState,
|
|
15
16
|
useEffect,
|
|
16
17
|
useMemo,
|
|
17
|
-
|
|
18
|
-
useReducer,
|
|
18
|
+
useSyncExternalStore,
|
|
19
19
|
} from '@wordpress/element';
|
|
20
20
|
import { useEntityRecords, store as coreStore } from '@wordpress/core-data';
|
|
21
21
|
import { useDispatch, useRegistry, useSelect } from '@wordpress/data';
|
|
@@ -33,16 +33,12 @@ import { store as interfaceStore } from '@wordpress/interface';
|
|
|
33
33
|
import { store as editorStore } from '../../store';
|
|
34
34
|
import { FLOATING_NOTES_SIDEBAR } from './constants';
|
|
35
35
|
import { unlock } from '../../lock-unlock';
|
|
36
|
-
import {
|
|
36
|
+
import { createBoardStore } from './board-store';
|
|
37
|
+
import { calculateAllOffsets } from './utils';
|
|
37
38
|
|
|
38
39
|
const { useBlockElement, cleanEmptyObject } = unlock( blockEditorPrivateApis );
|
|
39
40
|
|
|
40
41
|
export function useBlockComments( postId ) {
|
|
41
|
-
const [ commentLastUpdated, reflowComments ] = useReducer(
|
|
42
|
-
() => Date.now(),
|
|
43
|
-
0
|
|
44
|
-
);
|
|
45
|
-
|
|
46
42
|
const queryArgs = {
|
|
47
43
|
post: postId,
|
|
48
44
|
type: 'note',
|
|
@@ -165,12 +161,10 @@ export function useBlockComments( postId ) {
|
|
|
165
161
|
return {
|
|
166
162
|
resultComments,
|
|
167
163
|
unresolvedSortedThreads,
|
|
168
|
-
reflowComments,
|
|
169
|
-
commentLastUpdated,
|
|
170
164
|
};
|
|
171
165
|
}
|
|
172
166
|
|
|
173
|
-
export function useBlockCommentsActions(
|
|
167
|
+
export function useBlockCommentsActions() {
|
|
174
168
|
const { createNotice } = useDispatch( noticesStore );
|
|
175
169
|
const { saveEntityRecord, deleteEntityRecord } = useDispatch( coreStore );
|
|
176
170
|
const { getCurrentPostId } = useSelect( editorStore );
|
|
@@ -224,10 +218,8 @@ export function useBlockCommentsActions( reflowComments = noop ) {
|
|
|
224
218
|
isDismissible: true,
|
|
225
219
|
}
|
|
226
220
|
);
|
|
227
|
-
setTimeout( reflowComments, 300 );
|
|
228
221
|
return savedRecord;
|
|
229
222
|
} catch ( error ) {
|
|
230
|
-
reflowComments();
|
|
231
223
|
onError( error );
|
|
232
224
|
}
|
|
233
225
|
};
|
|
@@ -292,9 +284,7 @@ export function useBlockCommentsActions( reflowComments = noop ) {
|
|
|
292
284
|
isDismissible: true,
|
|
293
285
|
}
|
|
294
286
|
);
|
|
295
|
-
reflowComments();
|
|
296
287
|
} catch ( error ) {
|
|
297
|
-
reflowComments();
|
|
298
288
|
onError( error );
|
|
299
289
|
}
|
|
300
290
|
};
|
|
@@ -326,9 +316,7 @@ export function useBlockCommentsActions( reflowComments = noop ) {
|
|
|
326
316
|
type: 'snackbar',
|
|
327
317
|
isDismissible: true,
|
|
328
318
|
} );
|
|
329
|
-
reflowComments();
|
|
330
319
|
} catch ( error ) {
|
|
331
|
-
reflowComments();
|
|
332
320
|
onError( error );
|
|
333
321
|
}
|
|
334
322
|
};
|
|
@@ -366,26 +354,55 @@ export function useEnableFloatingSidebar( enabled = false ) {
|
|
|
366
354
|
}, [ enabled, registry ] );
|
|
367
355
|
}
|
|
368
356
|
|
|
357
|
+
export function useFloatingBoard( { threads, selectedNoteId, isFloating } ) {
|
|
358
|
+
const [ boardOffsets, setBoardOffsets ] = useState( {} );
|
|
359
|
+
const [ store ] = useState( createBoardStore );
|
|
360
|
+
const { setCanvasMinHeight } = unlock( useDispatch( editorStore ) );
|
|
361
|
+
|
|
362
|
+
const heights = useSyncExternalStore( store.subscribe, store.getSnapshot );
|
|
363
|
+
|
|
364
|
+
// Recalc is deferred to a rAF; the cleanup cancels the pending frame
|
|
365
|
+
// when deps change, so back-to-back updates collapse into one paint.
|
|
366
|
+
useEffect( () => {
|
|
367
|
+
if ( ! isFloating ) {
|
|
368
|
+
return;
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
const rafId = window.requestAnimationFrame( () => {
|
|
372
|
+
const { offsets, minHeight } = calculateAllOffsets( {
|
|
373
|
+
threads,
|
|
374
|
+
selectedNoteId,
|
|
375
|
+
blockRects: store.getBlockRects(),
|
|
376
|
+
heights,
|
|
377
|
+
} );
|
|
378
|
+
setBoardOffsets( offsets );
|
|
379
|
+
setCanvasMinHeight( minHeight );
|
|
380
|
+
} );
|
|
381
|
+
|
|
382
|
+
return () => window.cancelAnimationFrame( rafId );
|
|
383
|
+
}, [
|
|
384
|
+
heights,
|
|
385
|
+
isFloating,
|
|
386
|
+
selectedNoteId,
|
|
387
|
+
setCanvasMinHeight,
|
|
388
|
+
store,
|
|
389
|
+
threads,
|
|
390
|
+
] );
|
|
391
|
+
|
|
392
|
+
return {
|
|
393
|
+
boardOffsets,
|
|
394
|
+
registerThread: store.registerThread,
|
|
395
|
+
unregisterThread: store.unregisterThread,
|
|
396
|
+
};
|
|
397
|
+
}
|
|
398
|
+
|
|
369
399
|
export function useFloatingThread( {
|
|
370
400
|
thread,
|
|
371
401
|
calculatedOffset,
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
setBlockRef,
|
|
375
|
-
commentLastUpdated,
|
|
402
|
+
registerThread,
|
|
403
|
+
unregisterThread,
|
|
376
404
|
} ) {
|
|
377
405
|
const blockElement = useBlockElement( thread.blockClientId );
|
|
378
|
-
const updateHeight = useCallback(
|
|
379
|
-
( id, newHeight ) => {
|
|
380
|
-
setHeights( ( prev ) => {
|
|
381
|
-
if ( prev[ id ] !== newHeight ) {
|
|
382
|
-
return { ...prev, [ id ]: newHeight };
|
|
383
|
-
}
|
|
384
|
-
return prev;
|
|
385
|
-
} );
|
|
386
|
-
},
|
|
387
|
-
[ setHeights ]
|
|
388
|
-
);
|
|
389
406
|
|
|
390
407
|
// Use floating-ui to track the block element's position with the calculated offset.
|
|
391
408
|
const { y, refs } = useFloating( {
|
|
@@ -398,32 +415,27 @@ export function useFloatingThread( {
|
|
|
398
415
|
whileElementsMounted: autoUpdate,
|
|
399
416
|
} );
|
|
400
417
|
|
|
401
|
-
//
|
|
418
|
+
// Set the floating-ui reference element.
|
|
402
419
|
useEffect( () => {
|
|
403
420
|
if ( blockElement ) {
|
|
404
421
|
refs.setReference( blockElement );
|
|
405
422
|
}
|
|
406
|
-
}, [ blockElement, refs
|
|
407
|
-
|
|
408
|
-
// Track thread heights.
|
|
409
|
-
useEffect( () => {
|
|
410
|
-
if ( refs.floating?.current ) {
|
|
411
|
-
setBlockRef( thread.id, blockElement );
|
|
412
|
-
}
|
|
413
|
-
}, [ blockElement, thread.id, refs.floating, setBlockRef ] );
|
|
423
|
+
}, [ blockElement, refs ] );
|
|
414
424
|
|
|
415
|
-
//
|
|
425
|
+
// Register block + floating elements with the board.
|
|
426
|
+
// The board's ResizeObserver tracks height changes automatically.
|
|
416
427
|
useEffect( () => {
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
428
|
+
const floatingEl = refs.floating?.current;
|
|
429
|
+
if ( floatingEl && registerThread ) {
|
|
430
|
+
registerThread( thread.id, blockElement, floatingEl );
|
|
420
431
|
}
|
|
432
|
+
return () => unregisterThread?.( thread.id );
|
|
421
433
|
}, [
|
|
434
|
+
blockElement,
|
|
422
435
|
thread.id,
|
|
423
|
-
updateHeight,
|
|
424
436
|
refs.floating,
|
|
425
|
-
|
|
426
|
-
|
|
437
|
+
registerThread,
|
|
438
|
+
unregisterThread,
|
|
427
439
|
] );
|
|
428
440
|
|
|
429
441
|
return {
|