@wordpress/editor 14.33.3 → 14.33.5
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/bindings/post-data.js +47 -63
- package/build/bindings/post-data.js.map +3 -3
- package/build/bindings/post-meta.js +45 -39
- package/build/bindings/post-meta.js.map +2 -2
- package/build/components/collab-sidebar/add-comment.js +9 -5
- package/build/components/collab-sidebar/add-comment.js.map +2 -2
- package/build/components/collab-sidebar/comment-author-info.js +27 -15
- package/build/components/collab-sidebar/comment-author-info.js.map +2 -2
- package/build/components/collab-sidebar/comment-indicator-toolbar.js +9 -23
- package/build/components/collab-sidebar/comment-indicator-toolbar.js.map +3 -3
- package/build/components/collab-sidebar/comment-menu-item.js +36 -6
- package/build/components/collab-sidebar/comment-menu-item.js.map +3 -3
- package/build/components/collab-sidebar/comments.js +317 -301
- package/build/components/collab-sidebar/comments.js.map +3 -3
- package/build/components/collab-sidebar/hooks.js +5 -3
- package/build/components/collab-sidebar/hooks.js.map +2 -2
- package/build/components/collab-sidebar/index.js +35 -11
- package/build/components/collab-sidebar/index.js.map +3 -3
- package/build/components/collab-sidebar/utils.js +6 -3
- package/build/components/collab-sidebar/utils.js.map +2 -2
- package/build/components/editor/index.js +2 -2
- package/build/components/editor/index.js.map +3 -3
- package/build/components/more-menu/index.js +1 -1
- package/build/components/more-menu/index.js.map +2 -2
- package/build/components/visual-editor/index.js +20 -9
- package/build/components/visual-editor/index.js.map +2 -2
- package/build/store/private-actions.js +8 -0
- package/build/store/private-actions.js.map +2 -2
- package/build/store/private-selectors.js +5 -0
- package/build/store/private-selectors.js.map +2 -2
- package/build/store/reducer.js +10 -0
- package/build/store/reducer.js.map +2 -2
- package/build-module/bindings/post-data.js +47 -63
- package/build-module/bindings/post-data.js.map +2 -2
- package/build-module/bindings/post-meta.js +45 -39
- package/build-module/bindings/post-meta.js.map +2 -2
- package/build-module/components/collab-sidebar/add-comment.js +10 -6
- package/build-module/components/collab-sidebar/add-comment.js.map +2 -2
- package/build-module/components/collab-sidebar/comment-author-info.js +27 -15
- package/build-module/components/collab-sidebar/comment-author-info.js.map +2 -2
- package/build-module/components/collab-sidebar/comment-indicator-toolbar.js +15 -25
- package/build-module/components/collab-sidebar/comment-indicator-toolbar.js.map +2 -2
- package/build-module/components/collab-sidebar/comment-menu-item.js +40 -7
- package/build-module/components/collab-sidebar/comment-menu-item.js.map +2 -2
- package/build-module/components/collab-sidebar/comments.js +319 -302
- package/build-module/components/collab-sidebar/comments.js.map +2 -2
- package/build-module/components/collab-sidebar/hooks.js +5 -3
- package/build-module/components/collab-sidebar/hooks.js.map +2 -2
- package/build-module/components/collab-sidebar/index.js +35 -11
- package/build-module/components/collab-sidebar/index.js.map +2 -2
- package/build-module/components/collab-sidebar/utils.js +6 -3
- package/build-module/components/collab-sidebar/utils.js.map +2 -2
- package/build-module/components/editor/index.js +2 -2
- package/build-module/components/editor/index.js.map +2 -2
- package/build-module/components/more-menu/index.js +1 -1
- package/build-module/components/more-menu/index.js.map +2 -2
- package/build-module/components/visual-editor/index.js +20 -9
- package/build-module/components/visual-editor/index.js.map +2 -2
- package/build-module/store/private-actions.js +7 -0
- package/build-module/store/private-actions.js.map +2 -2
- package/build-module/store/private-selectors.js +4 -0
- package/build-module/store/private-selectors.js.map +2 -2
- package/build-module/store/reducer.js +9 -0
- package/build-module/store/reducer.js.map +2 -2
- package/build-style/style-rtl.css +6 -43
- package/build-style/style.css +6 -43
- package/build-types/bindings/post-data.d.ts +18 -8
- package/build-types/bindings/post-meta.d.ts +1 -7
- package/build-types/components/collab-sidebar/add-comment.d.ts.map +1 -1
- package/build-types/components/collab-sidebar/comment-author-info.d.ts +5 -16
- package/build-types/components/collab-sidebar/comment-author-info.d.ts.map +1 -1
- package/build-types/components/collab-sidebar/comment-indicator-toolbar.d.ts.map +1 -1
- package/build-types/components/collab-sidebar/comment-menu-item.d.ts +3 -2
- package/build-types/components/collab-sidebar/comment-menu-item.d.ts.map +1 -1
- package/build-types/components/collab-sidebar/comments.d.ts +1 -1
- package/build-types/components/collab-sidebar/comments.d.ts.map +1 -1
- 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 +2 -2
- package/build-types/components/collab-sidebar/utils.d.ts.map +1 -1
- package/build-types/components/visual-editor/index.d.ts.map +1 -1
- package/build-types/store/private-actions.d.ts +7 -0
- package/build-types/store/private-actions.d.ts.map +1 -1
- package/build-types/store/private-selectors.d.ts +7 -0
- package/build-types/store/private-selectors.d.ts.map +1 -1
- package/build-types/store/reducer.d.ts +10 -0
- package/build-types/store/reducer.d.ts.map +1 -1
- package/package.json +8 -8
- package/src/bindings/post-data.js +63 -111
- package/src/bindings/post-meta.js +55 -46
- package/src/bindings/test/post-meta.js +211 -0
- package/src/components/collab-sidebar/add-comment.js +11 -6
- package/src/components/collab-sidebar/comment-author-info.js +33 -26
- package/src/components/collab-sidebar/comment-indicator-toolbar.js +19 -29
- package/src/components/collab-sidebar/comment-menu-item.js +51 -11
- package/src/components/collab-sidebar/comments.js +47 -27
- package/src/components/collab-sidebar/hooks.js +6 -4
- package/src/components/collab-sidebar/index.js +63 -27
- package/src/components/collab-sidebar/style.scss +6 -46
- package/src/components/collab-sidebar/utils.js +15 -5
- package/src/components/editor/index.js +1 -1
- package/src/components/more-menu/index.js +1 -1
- package/src/components/visual-editor/index.js +27 -6
- package/src/store/private-actions.js +13 -0
- package/src/store/private-selectors.js +10 -0
- package/src/store/reducer.js +16 -0
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* WordPress dependencies
|
|
3
3
|
*/
|
|
4
|
-
import {
|
|
5
|
-
|
|
4
|
+
import {
|
|
5
|
+
ToolbarButton,
|
|
6
|
+
__experimentalText as Text,
|
|
7
|
+
__experimentalHStack as HStack,
|
|
8
|
+
} from '@wordpress/components';
|
|
9
|
+
import { __, sprintf } from '@wordpress/i18n';
|
|
6
10
|
import { useMemo } from '@wordpress/element';
|
|
7
11
|
import { privateApis as blockEditorPrivateApis } from '@wordpress/block-editor';
|
|
8
12
|
|
|
@@ -49,10 +53,16 @@ const CommentAvatarIndicator = ( { onClick, thread } ) => {
|
|
|
49
53
|
return null;
|
|
50
54
|
}
|
|
51
55
|
|
|
52
|
-
//
|
|
56
|
+
// If there are more than 3 participants, show 2 avatars and a "+n" number.
|
|
53
57
|
const maxAvatars = 3;
|
|
54
|
-
const
|
|
55
|
-
const
|
|
58
|
+
const isOverflow = threadParticipants.length > maxAvatars;
|
|
59
|
+
const visibleParticipants = isOverflow
|
|
60
|
+
? threadParticipants.slice( 0, maxAvatars - 1 )
|
|
61
|
+
: threadParticipants;
|
|
62
|
+
const overflowCount = Math.max(
|
|
63
|
+
0,
|
|
64
|
+
threadParticipants.length - visibleParticipants.length
|
|
65
|
+
);
|
|
56
66
|
const threadHasMoreParticipants = threadParticipants.length > 100;
|
|
57
67
|
|
|
58
68
|
// If we hit the comment limit, show "100+" instead of exact overflow count.
|
|
@@ -65,19 +75,6 @@ const CommentAvatarIndicator = ( { onClick, thread } ) => {
|
|
|
65
75
|
overflowCount
|
|
66
76
|
);
|
|
67
77
|
|
|
68
|
-
const overflowTitle =
|
|
69
|
-
threadHasMoreParticipants && overflowCount > 0
|
|
70
|
-
? __( '100+ participants' )
|
|
71
|
-
: sprintf(
|
|
72
|
-
// translators: %s: Number of participants.
|
|
73
|
-
_n(
|
|
74
|
-
'+%s more participant',
|
|
75
|
-
'+%s more participants',
|
|
76
|
-
overflowCount
|
|
77
|
-
),
|
|
78
|
-
overflowCount
|
|
79
|
-
);
|
|
80
|
-
|
|
81
78
|
return (
|
|
82
79
|
<CommentIconToolbarSlotFill.Fill>
|
|
83
80
|
<ToolbarButton
|
|
@@ -86,15 +83,14 @@ const CommentAvatarIndicator = ( { onClick, thread } ) => {
|
|
|
86
83
|
onClick={ onClick }
|
|
87
84
|
showTooltip
|
|
88
85
|
>
|
|
89
|
-
<
|
|
90
|
-
{ visibleParticipants.map( ( participant
|
|
86
|
+
<HStack spacing="1">
|
|
87
|
+
{ visibleParticipants.map( ( participant ) => (
|
|
91
88
|
<img
|
|
92
89
|
key={ participant.id }
|
|
93
90
|
src={ participant.avatar }
|
|
94
91
|
alt={ participant.name }
|
|
95
92
|
className="comment-avatar"
|
|
96
93
|
style={ {
|
|
97
|
-
zIndex: maxAvatars - index,
|
|
98
94
|
borderColor: getAvatarBorderColor(
|
|
99
95
|
participant.id
|
|
100
96
|
),
|
|
@@ -102,15 +98,9 @@ const CommentAvatarIndicator = ( { onClick, thread } ) => {
|
|
|
102
98
|
/>
|
|
103
99
|
) ) }
|
|
104
100
|
{ overflowCount > 0 && (
|
|
105
|
-
<
|
|
106
|
-
className="comment-avatar-overflow"
|
|
107
|
-
style={ { zIndex: 0 } }
|
|
108
|
-
title={ overflowTitle }
|
|
109
|
-
>
|
|
110
|
-
{ overflowText }
|
|
111
|
-
</div>
|
|
101
|
+
<Text weight={ 500 }>{ overflowText }</Text>
|
|
112
102
|
) }
|
|
113
|
-
</
|
|
103
|
+
</HStack>
|
|
114
104
|
</ToolbarButton>
|
|
115
105
|
</CommentIconToolbarSlotFill.Fill>
|
|
116
106
|
);
|
|
@@ -4,8 +4,12 @@
|
|
|
4
4
|
import { MenuItem } from '@wordpress/components';
|
|
5
5
|
import { __ } from '@wordpress/i18n';
|
|
6
6
|
import { comment as commentIcon } from '@wordpress/icons';
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
import {
|
|
8
|
+
privateApis as blockEditorPrivateApis,
|
|
9
|
+
store as blockEditorStore,
|
|
10
|
+
} from '@wordpress/block-editor';
|
|
11
|
+
import { useSelect } from '@wordpress/data';
|
|
12
|
+
import { getUnregisteredTypeHandlerName } from '@wordpress/blocks';
|
|
9
13
|
|
|
10
14
|
/**
|
|
11
15
|
* Internal dependencies
|
|
@@ -14,23 +18,59 @@ import { unlock } from '../../lock-unlock';
|
|
|
14
18
|
|
|
15
19
|
const { CommentIconSlotFill } = unlock( blockEditorPrivateApis );
|
|
16
20
|
|
|
17
|
-
const AddCommentMenuItem = ( { onClick } ) => {
|
|
21
|
+
const AddCommentMenuItem = ( { clientId, onClick, isDistractionFree } ) => {
|
|
22
|
+
const block = useSelect(
|
|
23
|
+
( select ) => {
|
|
24
|
+
return select( blockEditorStore ).getBlock( clientId );
|
|
25
|
+
},
|
|
26
|
+
[ clientId ]
|
|
27
|
+
);
|
|
28
|
+
|
|
29
|
+
if (
|
|
30
|
+
! block?.isValid ||
|
|
31
|
+
block?.name === getUnregisteredTypeHandlerName()
|
|
32
|
+
) {
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const isDisabled = isDistractionFree || block?.name === 'core/freeform';
|
|
37
|
+
|
|
38
|
+
let infoText;
|
|
39
|
+
|
|
40
|
+
if ( isDistractionFree ) {
|
|
41
|
+
infoText = __( 'Notes are disabled in distraction free mode.' );
|
|
42
|
+
} else if ( block?.name === 'core/freeform' ) {
|
|
43
|
+
infoText = __( 'Convert to blocks to add notes.' );
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return (
|
|
47
|
+
<MenuItem
|
|
48
|
+
icon={ commentIcon }
|
|
49
|
+
onClick={ onClick }
|
|
50
|
+
aria-haspopup="dialog"
|
|
51
|
+
disabled={ isDisabled }
|
|
52
|
+
info={ infoText }
|
|
53
|
+
>
|
|
54
|
+
{ __( 'Add note' ) }
|
|
55
|
+
</MenuItem>
|
|
56
|
+
);
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
const AddCommentMenuItemFill = ( { onClick, isDistractionFree } ) => {
|
|
18
60
|
return (
|
|
19
61
|
<CommentIconSlotFill.Fill>
|
|
20
|
-
{ ( { onClose } ) => (
|
|
21
|
-
<
|
|
22
|
-
|
|
62
|
+
{ ( { clientId, onClose } ) => (
|
|
63
|
+
<AddCommentMenuItem
|
|
64
|
+
clientId={ clientId }
|
|
65
|
+
isDistractionFree={ isDistractionFree }
|
|
23
66
|
onClick={ () => {
|
|
24
67
|
onClick();
|
|
25
68
|
onClose();
|
|
26
69
|
} }
|
|
27
|
-
|
|
28
|
-
>
|
|
29
|
-
{ __( 'Add note' ) }
|
|
30
|
-
</MenuItem>
|
|
70
|
+
/>
|
|
31
71
|
) }
|
|
32
72
|
</CommentIconSlotFill.Fill>
|
|
33
73
|
);
|
|
34
74
|
};
|
|
35
75
|
|
|
36
|
-
export default
|
|
76
|
+
export default AddCommentMenuItemFill;
|
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
useEffect,
|
|
13
13
|
useCallback,
|
|
14
14
|
useMemo,
|
|
15
|
+
useRef,
|
|
15
16
|
} from '@wordpress/element';
|
|
16
17
|
import {
|
|
17
18
|
__experimentalText as Text,
|
|
@@ -42,6 +43,7 @@ import CommentForm from './comment-form';
|
|
|
42
43
|
import { focusCommentThread, getCommentExcerpt } from './utils';
|
|
43
44
|
import { useFloatingThread } from './hooks';
|
|
44
45
|
import { AddComment } from './add-comment';
|
|
46
|
+
import { store as editorStore } from '../../store';
|
|
45
47
|
|
|
46
48
|
const { useBlockElement } = unlock( blockEditorPrivateApis );
|
|
47
49
|
const { Menu } = unlock( componentsPrivateApis );
|
|
@@ -63,6 +65,7 @@ export function Comments( {
|
|
|
63
65
|
const [ boardOffsets, setBoardOffsets ] = useState( {} );
|
|
64
66
|
const [ blockRefs, setBlockRefs ] = useState( {} );
|
|
65
67
|
|
|
68
|
+
const { setCanvasMinHeight } = unlock( useDispatch( editorStore ) );
|
|
66
69
|
const { blockCommentId, selectedBlockClientId, orderedBlockIds } =
|
|
67
70
|
useSelect( ( select ) => {
|
|
68
71
|
const { getBlockAttributes, getSelectedBlockClientId } =
|
|
@@ -149,8 +152,10 @@ export function Comments( {
|
|
|
149
152
|
|
|
150
153
|
// Auto-select the related comment thread when a block is selected.
|
|
151
154
|
useEffect( () => {
|
|
152
|
-
|
|
153
|
-
|
|
155
|
+
// Fallback to 'new-note-thread' when showing the comment board for a new note.
|
|
156
|
+
const fallback = showCommentBoard ? 'new-note-thread' : null;
|
|
157
|
+
setSelectedThread( blockCommentId ?? fallback );
|
|
158
|
+
}, [ blockCommentId, showCommentBoard ] );
|
|
154
159
|
|
|
155
160
|
const setBlockRef = useCallback( ( id, blockRef ) => {
|
|
156
161
|
setBlockRefs( ( prev ) => ( { ...prev, [ id ]: blockRef } ) );
|
|
@@ -166,7 +171,7 @@ export function Comments( {
|
|
|
166
171
|
const offsets = {};
|
|
167
172
|
|
|
168
173
|
if ( ! isFloating ) {
|
|
169
|
-
return offsets;
|
|
174
|
+
return { offsets, minHeight: 0 };
|
|
170
175
|
}
|
|
171
176
|
|
|
172
177
|
// Find the index of the selected thread.
|
|
@@ -184,7 +189,7 @@ export function Comments( {
|
|
|
184
189
|
! selectedThreadData ||
|
|
185
190
|
! blockRefs[ selectedThreadData.id ]
|
|
186
191
|
) {
|
|
187
|
-
return offsets;
|
|
192
|
+
return { offsets, minHeight: 0 };
|
|
188
193
|
}
|
|
189
194
|
|
|
190
195
|
let blockElement = blockRefs[ selectedThreadData.id ];
|
|
@@ -271,30 +276,41 @@ export function Comments( {
|
|
|
271
276
|
threadTop: threadTop + additionalOffset,
|
|
272
277
|
};
|
|
273
278
|
}
|
|
274
|
-
|
|
279
|
+
|
|
280
|
+
let editorMinHeight = 0;
|
|
281
|
+
// Take the calculated top of the final note plus its height as the editor min height.
|
|
282
|
+
const lastThread = threads[ threads.length - 1 ];
|
|
283
|
+
if ( blockRefs[ lastThread.id ] ) {
|
|
284
|
+
const lastBlockElement = blockRefs[ lastThread.id ];
|
|
285
|
+
const lastBlockRect = lastBlockElement?.getBoundingClientRect();
|
|
286
|
+
const lastThreadTop = lastBlockRect?.top || 0;
|
|
287
|
+
const lastThreadHeight = heights[ lastThread.id ] || 0;
|
|
288
|
+
const lastThreadOffset = offsets[ lastThread.id ] || 0;
|
|
289
|
+
editorMinHeight =
|
|
290
|
+
lastThreadTop + lastThreadHeight + lastThreadOffset + 32;
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
return { offsets, minHeight: editorMinHeight };
|
|
275
294
|
};
|
|
276
|
-
const newOffsets = calculateAllOffsets();
|
|
295
|
+
const { offsets: newOffsets, minHeight } = calculateAllOffsets();
|
|
277
296
|
if ( Object.keys( newOffsets ).length > 0 ) {
|
|
278
297
|
setBoardOffsets( newOffsets );
|
|
279
298
|
}
|
|
280
|
-
|
|
299
|
+
// Ensure the editor has enough height to scroll to all notes.
|
|
300
|
+
setCanvasMinHeight( minHeight );
|
|
301
|
+
}, [
|
|
302
|
+
heights,
|
|
303
|
+
blockRefs,
|
|
304
|
+
isFloating,
|
|
305
|
+
threads,
|
|
306
|
+
selectedThread,
|
|
307
|
+
setCanvasMinHeight,
|
|
308
|
+
] );
|
|
281
309
|
|
|
282
310
|
const hasThreads = Array.isArray( threads ) && threads.length > 0;
|
|
311
|
+
// This should no longer happen since https://github.com/WordPress/gutenberg/pull/72872.
|
|
283
312
|
if ( ! hasThreads && ! isFloating ) {
|
|
284
|
-
return
|
|
285
|
-
<>
|
|
286
|
-
<AddComment
|
|
287
|
-
onSubmit={ onAddReply }
|
|
288
|
-
showCommentBoard={ showCommentBoard }
|
|
289
|
-
setShowCommentBoard={ setShowCommentBoard }
|
|
290
|
-
commentSidebarRef={ commentSidebarRef }
|
|
291
|
-
/>
|
|
292
|
-
<Text as="p">{ __( 'No notes available.' ) }</Text>
|
|
293
|
-
<Text as="p" variant="muted">
|
|
294
|
-
{ __( 'Only logged in users can see Notes.' ) }
|
|
295
|
-
</Text>
|
|
296
|
-
</>
|
|
297
|
-
);
|
|
313
|
+
return null;
|
|
298
314
|
}
|
|
299
315
|
|
|
300
316
|
return (
|
|
@@ -431,8 +447,6 @@ function Thread( {
|
|
|
431
447
|
}
|
|
432
448
|
|
|
433
449
|
return (
|
|
434
|
-
// Disable reason: role="listitem" does in fact support aria-expanded.
|
|
435
|
-
// eslint-disable-next-line jsx-a11y/role-supports-aria-props
|
|
436
450
|
<VStack
|
|
437
451
|
className={ clsx( 'editor-collab-sidebar-panel__thread', {
|
|
438
452
|
'is-selected': isSelected,
|
|
@@ -467,7 +481,7 @@ function Thread( {
|
|
|
467
481
|
}
|
|
468
482
|
} }
|
|
469
483
|
tabIndex={ 0 }
|
|
470
|
-
role="
|
|
484
|
+
role="treeitem"
|
|
471
485
|
aria-label={ ariaLabel }
|
|
472
486
|
aria-expanded={ isSelected }
|
|
473
487
|
ref={ isFloating ? refs.setFloating : undefined }
|
|
@@ -558,7 +572,7 @@ function Thread( {
|
|
|
558
572
|
/>
|
|
559
573
|
) }
|
|
560
574
|
{ isSelected && (
|
|
561
|
-
<VStack spacing="2">
|
|
575
|
+
<VStack spacing="2" role="treeitem">
|
|
562
576
|
<HStack alignment="left" spacing="3" justify="flex-start">
|
|
563
577
|
<CommentAuthorInfo />
|
|
564
578
|
</HStack>
|
|
@@ -633,7 +647,7 @@ const CommentBoard = ( {
|
|
|
633
647
|
} ) => {
|
|
634
648
|
const [ actionState, setActionState ] = useState( false );
|
|
635
649
|
const [ showConfirmDialog, setShowConfirmDialog ] = useState( false );
|
|
636
|
-
|
|
650
|
+
const actionButtonRef = useRef( null );
|
|
637
651
|
const handleConfirmDelete = () => {
|
|
638
652
|
onDelete( thread );
|
|
639
653
|
setActionState( false );
|
|
@@ -643,6 +657,7 @@ const CommentBoard = ( {
|
|
|
643
657
|
const handleCancel = () => {
|
|
644
658
|
setActionState( false );
|
|
645
659
|
setShowConfirmDialog( false );
|
|
660
|
+
actionButtonRef.current?.focus();
|
|
646
661
|
};
|
|
647
662
|
|
|
648
663
|
// Check if this is a resolution comment by checking metadata.
|
|
@@ -687,7 +702,10 @@ const CommentBoard = ( {
|
|
|
687
702
|
: [];
|
|
688
703
|
|
|
689
704
|
return (
|
|
690
|
-
<VStack
|
|
705
|
+
<VStack
|
|
706
|
+
spacing="2"
|
|
707
|
+
role={ thread.parent !== 0 ? 'treeitem' : undefined }
|
|
708
|
+
>
|
|
691
709
|
<HStack alignment="left" spacing="3" justify="flex-start">
|
|
692
710
|
<CommentAuthorInfo
|
|
693
711
|
avatar={ thread?.author_avatar_urls?.[ 48 ] }
|
|
@@ -728,6 +746,7 @@ const CommentBoard = ( {
|
|
|
728
746
|
<Menu.TriggerButton
|
|
729
747
|
render={
|
|
730
748
|
<Button
|
|
749
|
+
ref={ actionButtonRef }
|
|
731
750
|
size="small"
|
|
732
751
|
icon={ moreVertical }
|
|
733
752
|
label={ __( 'Actions' ) }
|
|
@@ -761,6 +780,7 @@ const CommentBoard = ( {
|
|
|
761
780
|
content: value,
|
|
762
781
|
} );
|
|
763
782
|
setActionState( false );
|
|
783
|
+
actionButtonRef.current?.focus();
|
|
764
784
|
} }
|
|
765
785
|
onCancel={ () => handleCancel() }
|
|
766
786
|
thread={ thread }
|
|
@@ -70,6 +70,10 @@ export function useBlockComments( postId ) {
|
|
|
70
70
|
|
|
71
71
|
// Process comments to build the tree structure.
|
|
72
72
|
const { resultComments, unresolvedSortedThreads } = useMemo( () => {
|
|
73
|
+
if ( ! threads || threads.length === 0 ) {
|
|
74
|
+
return { resultComments: [], unresolvedSortedThreads: [] };
|
|
75
|
+
}
|
|
76
|
+
|
|
73
77
|
const blocksWithComments = clientIds.reduce( ( results, clientId ) => {
|
|
74
78
|
const commentId = getBlockAttributes( clientId )?.metadata?.noteId;
|
|
75
79
|
if ( commentId ) {
|
|
@@ -82,10 +86,8 @@ export function useBlockComments( postId ) {
|
|
|
82
86
|
const compare = {};
|
|
83
87
|
const result = [];
|
|
84
88
|
|
|
85
|
-
const allComments = threads ?? [];
|
|
86
|
-
|
|
87
89
|
// Initialize each object with an empty `reply` array and map blockClientId.
|
|
88
|
-
|
|
90
|
+
threads.forEach( ( item ) => {
|
|
89
91
|
const itemBlock = Object.keys( blocksWithComments ).find(
|
|
90
92
|
( key ) => blocksWithComments[ key ] === item.id
|
|
91
93
|
);
|
|
@@ -98,7 +100,7 @@ export function useBlockComments( postId ) {
|
|
|
98
100
|
} );
|
|
99
101
|
|
|
100
102
|
// Iterate over the data to build the tree structure.
|
|
101
|
-
|
|
103
|
+
threads.forEach( ( item ) => {
|
|
102
104
|
if ( item.parent === 0 ) {
|
|
103
105
|
// If parent is 0, it's a root item, push it to the result array.
|
|
104
106
|
result.push( compare[ item.id ] );
|
|
@@ -31,6 +31,7 @@ import {
|
|
|
31
31
|
} from './hooks';
|
|
32
32
|
import { focusCommentThread } from './utils';
|
|
33
33
|
import PostTypeSupportCheck from '../post-type-support-check';
|
|
34
|
+
import { unlock } from '../../lock-unlock';
|
|
34
35
|
|
|
35
36
|
function NotesSidebarContent( {
|
|
36
37
|
showCommentBoard,
|
|
@@ -49,7 +50,7 @@ function NotesSidebarContent( {
|
|
|
49
50
|
<VStack
|
|
50
51
|
className="editor-collab-sidebar-panel"
|
|
51
52
|
style={ styles }
|
|
52
|
-
role="
|
|
53
|
+
role="tree"
|
|
53
54
|
spacing="3"
|
|
54
55
|
justify="flex-start"
|
|
55
56
|
ref={ ( node ) => {
|
|
@@ -59,6 +60,9 @@ function NotesSidebarContent( {
|
|
|
59
60
|
commentSidebarRef.current = node;
|
|
60
61
|
}
|
|
61
62
|
} }
|
|
63
|
+
aria-label={
|
|
64
|
+
isFloating ? __( 'Unresolved notes' ) : __( 'All notes' )
|
|
65
|
+
}
|
|
62
66
|
>
|
|
63
67
|
<Comments
|
|
64
68
|
threads={ comments }
|
|
@@ -80,19 +84,30 @@ function NotesSidebar( { postId, mode } ) {
|
|
|
80
84
|
const [ showCommentBoard, setShowCommentBoard ] = useState( false );
|
|
81
85
|
const { getActiveComplementaryArea } = useSelect( interfaceStore );
|
|
82
86
|
const { enableComplementaryArea } = useDispatch( interfaceStore );
|
|
87
|
+
const { toggleBlockSpotlight } = unlock( useDispatch( blockEditorStore ) );
|
|
83
88
|
const isLargeViewport = useViewportMatch( 'medium' );
|
|
84
89
|
const commentSidebarRef = useRef( null );
|
|
85
90
|
|
|
86
91
|
const showFloatingSidebar = isLargeViewport && mode === 'post-only';
|
|
87
92
|
|
|
88
|
-
const blockCommentId = useSelect(
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
93
|
+
const { clientId, blockCommentId, isDistractionFree } = useSelect(
|
|
94
|
+
( select ) => {
|
|
95
|
+
const {
|
|
96
|
+
getBlockAttributes,
|
|
97
|
+
getSelectedBlockClientId,
|
|
98
|
+
getSettings,
|
|
99
|
+
} = select( blockEditorStore );
|
|
100
|
+
const _clientId = getSelectedBlockClientId();
|
|
101
|
+
return {
|
|
102
|
+
clientId: _clientId,
|
|
103
|
+
blockCommentId: _clientId
|
|
104
|
+
? getBlockAttributes( _clientId )?.metadata?.noteId
|
|
105
|
+
: null,
|
|
106
|
+
isDistractionFree: getSettings().isDistractionFree,
|
|
107
|
+
};
|
|
108
|
+
},
|
|
109
|
+
[]
|
|
110
|
+
);
|
|
96
111
|
|
|
97
112
|
const {
|
|
98
113
|
resultComments,
|
|
@@ -113,6 +128,8 @@ function NotesSidebar( { postId, mode } ) {
|
|
|
113
128
|
const currentThread = blockCommentId
|
|
114
129
|
? resultComments.find( ( thread ) => thread.id === blockCommentId )
|
|
115
130
|
: null;
|
|
131
|
+
const showAllNotesSidebar =
|
|
132
|
+
resultComments.length > 0 || ! showFloatingSidebar;
|
|
116
133
|
|
|
117
134
|
async function openTheSidebar() {
|
|
118
135
|
const prevArea = await getActiveComplementaryArea( 'core' );
|
|
@@ -142,6 +159,11 @@ function NotesSidebar( { postId, mode } ) {
|
|
|
142
159
|
// Focus a comment thread when there's a selected block with a comment.
|
|
143
160
|
! blockCommentId ? 'textarea' : undefined
|
|
144
161
|
);
|
|
162
|
+
toggleBlockSpotlight( clientId, true );
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
if ( isDistractionFree ) {
|
|
166
|
+
return <AddCommentMenuItem isDistractionFree />;
|
|
145
167
|
}
|
|
146
168
|
|
|
147
169
|
return (
|
|
@@ -153,22 +175,29 @@ function NotesSidebar( { postId, mode } ) {
|
|
|
153
175
|
/>
|
|
154
176
|
) }
|
|
155
177
|
<AddCommentMenuItem onClick={ openTheSidebar } />
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
178
|
+
{ showAllNotesSidebar && (
|
|
179
|
+
<PluginSidebar
|
|
180
|
+
identifier={ collabHistorySidebarName }
|
|
181
|
+
name={ collabHistorySidebarName }
|
|
182
|
+
title={ __( 'All notes' ) }
|
|
183
|
+
header={
|
|
184
|
+
<h2 className="interface-complementary-area-header__title">
|
|
185
|
+
{ __( 'All notes' ) }
|
|
186
|
+
</h2>
|
|
187
|
+
}
|
|
188
|
+
icon={ commentIcon }
|
|
189
|
+
closeLabel={ __( 'Close Notes' ) }
|
|
190
|
+
>
|
|
191
|
+
<NotesSidebarContent
|
|
192
|
+
comments={ resultComments }
|
|
193
|
+
showCommentBoard={ showCommentBoard }
|
|
194
|
+
setShowCommentBoard={ setShowCommentBoard }
|
|
195
|
+
commentSidebarRef={ commentSidebarRef }
|
|
196
|
+
reflowComments={ reflowComments }
|
|
197
|
+
commentLastUpdated={ commentLastUpdated }
|
|
198
|
+
/>
|
|
199
|
+
</PluginSidebar>
|
|
200
|
+
) }
|
|
172
201
|
{ isLargeViewport && (
|
|
173
202
|
<PluginSidebar
|
|
174
203
|
isPinnable={ false }
|
|
@@ -197,11 +226,13 @@ function NotesSidebar( { postId, mode } ) {
|
|
|
197
226
|
}
|
|
198
227
|
|
|
199
228
|
export default function NotesSidebarContainer() {
|
|
200
|
-
const { postId, mode } = useSelect( ( select ) => {
|
|
201
|
-
const { getCurrentPostId, getRenderingMode } =
|
|
229
|
+
const { postId, mode, editorMode } = useSelect( ( select ) => {
|
|
230
|
+
const { getCurrentPostId, getRenderingMode, getEditorMode } =
|
|
231
|
+
select( editorStore );
|
|
202
232
|
return {
|
|
203
233
|
postId: getCurrentPostId(),
|
|
204
234
|
mode: getRenderingMode(),
|
|
235
|
+
editorMode: getEditorMode(),
|
|
205
236
|
};
|
|
206
237
|
}, [] );
|
|
207
238
|
|
|
@@ -209,6 +240,11 @@ export default function NotesSidebarContainer() {
|
|
|
209
240
|
return null;
|
|
210
241
|
}
|
|
211
242
|
|
|
243
|
+
// Hide Notes sidebar in Code Editor mode since block-level commenting.
|
|
244
|
+
if ( editorMode === 'text' ) {
|
|
245
|
+
return null;
|
|
246
|
+
}
|
|
247
|
+
|
|
212
248
|
return (
|
|
213
249
|
<PostTypeSupportCheck supportKeys="editor.notes">
|
|
214
250
|
<NotesSidebar postId={ postId } mode={ mode } />
|
|
@@ -78,6 +78,7 @@
|
|
|
78
78
|
border-width: var(--wp-admin-border-width-focus);
|
|
79
79
|
border-style: solid;
|
|
80
80
|
padding: var(--wp-admin-border-width-focus);
|
|
81
|
+
background: $white;
|
|
81
82
|
}
|
|
82
83
|
|
|
83
84
|
.editor-collab-sidebar-panel__comment-status {
|
|
@@ -154,57 +155,16 @@
|
|
|
154
155
|
bottom: $grid-unit-10;
|
|
155
156
|
}
|
|
156
157
|
|
|
157
|
-
// Comment avatar indicators.
|
|
158
|
-
.comment-avatar-indicator {
|
|
159
|
-
position: relative;
|
|
160
|
-
padding: 4px;
|
|
161
|
-
min-width: auto;
|
|
162
|
-
background: transparent;
|
|
163
|
-
border: none;
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
.comment-avatar-stack {
|
|
167
|
-
display: flex;
|
|
168
|
-
align-items: center;
|
|
169
|
-
position: relative;
|
|
170
|
-
height: $icon-size;
|
|
171
|
-
}
|
|
172
|
-
|
|
173
158
|
.comment-avatar {
|
|
174
159
|
width: $icon-size;
|
|
175
|
-
height: $icon-size;
|
|
176
160
|
border-radius: $radius-round;
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
161
|
+
margin-left: -12px;
|
|
162
|
+
border-width: var(--wp-admin-border-width-focus);
|
|
163
|
+
border-style: solid;
|
|
164
|
+
padding: var(--wp-admin-border-width-focus);
|
|
165
|
+
background: $white;
|
|
180
166
|
|
|
181
167
|
&:first-child {
|
|
182
168
|
margin-left: 0;
|
|
183
|
-
border-color: #de6e55;
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
&:nth-child(2) {
|
|
187
|
-
border-color: #599637;
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
&:nth-child(3) {
|
|
191
|
-
border-color: #3858e9;
|
|
192
169
|
}
|
|
193
170
|
}
|
|
194
|
-
|
|
195
|
-
.comment-avatar-overflow {
|
|
196
|
-
width: fit-content;
|
|
197
|
-
height: $icon-size;
|
|
198
|
-
border-radius: 4rem;
|
|
199
|
-
padding: 0 4px;
|
|
200
|
-
background: #757575;
|
|
201
|
-
color: $white;
|
|
202
|
-
border: 2px solid $white;
|
|
203
|
-
margin-left: -6px;
|
|
204
|
-
display: flex;
|
|
205
|
-
align-items: center;
|
|
206
|
-
justify-content: center;
|
|
207
|
-
font-size: 10px;
|
|
208
|
-
font-weight: 600;
|
|
209
|
-
flex-shrink: 0;
|
|
210
|
-
}
|
|
@@ -99,23 +99,32 @@ export function getCommentExcerpt( text, excerptLength = 10 ) {
|
|
|
99
99
|
* @typedef {import('@wordpress/element').RefObject} RefObject
|
|
100
100
|
*
|
|
101
101
|
* @param {string} commentId The ID of the comment thread to focus.
|
|
102
|
-
* @param {?HTMLElement}
|
|
102
|
+
* @param {?HTMLElement} threadContainer The container element to search within.
|
|
103
103
|
* @param {string} additionalSelector The additional selector to focus on.
|
|
104
104
|
*/
|
|
105
|
-
export function focusCommentThread(
|
|
106
|
-
|
|
105
|
+
export function focusCommentThread(
|
|
106
|
+
commentId,
|
|
107
|
+
threadContainer,
|
|
108
|
+
additionalSelector
|
|
109
|
+
) {
|
|
110
|
+
if ( ! threadContainer ) {
|
|
107
111
|
return;
|
|
108
112
|
}
|
|
109
113
|
|
|
110
114
|
// A thread without a commentId is a new comment thread.
|
|
111
115
|
const threadSelector = commentId
|
|
112
|
-
? `[role=
|
|
113
|
-
: '[role=
|
|
116
|
+
? `[role=treeitem][id="comment-thread-${ commentId }"]`
|
|
117
|
+
: '[role=treeitem]:not([id])';
|
|
114
118
|
const selector = additionalSelector
|
|
115
119
|
? `${ threadSelector } ${ additionalSelector }`
|
|
116
120
|
: threadSelector;
|
|
117
121
|
|
|
118
122
|
return new Promise( ( resolve ) => {
|
|
123
|
+
// Watch the sidebar skeleton in case the sidebar disappears and re-appears.
|
|
124
|
+
const container = threadContainer.closest(
|
|
125
|
+
'.interface-interface-skeleton__sidebar'
|
|
126
|
+
);
|
|
127
|
+
|
|
119
128
|
if ( container.querySelector( selector ) ) {
|
|
120
129
|
return resolve( container.querySelector( selector ) );
|
|
121
130
|
}
|
|
@@ -129,6 +138,7 @@ export function focusCommentThread( commentId, container, additionalSelector ) {
|
|
|
129
138
|
resolve( container.querySelector( selector ) );
|
|
130
139
|
}
|
|
131
140
|
} );
|
|
141
|
+
|
|
132
142
|
observer.observe( container, {
|
|
133
143
|
childList: true,
|
|
134
144
|
subtree: true,
|
|
@@ -87,11 +87,11 @@ function Editor( {
|
|
|
87
87
|
{ extraContent }
|
|
88
88
|
</EditorInterface>
|
|
89
89
|
{ children }
|
|
90
|
-
<NotesSidebar />
|
|
91
90
|
<Sidebar
|
|
92
91
|
onActionPerformed={ onActionPerformed }
|
|
93
92
|
extraPanels={ extraSidebarPanels }
|
|
94
93
|
/>
|
|
94
|
+
<NotesSidebar />
|
|
95
95
|
</ExperimentalEditorProvider>
|
|
96
96
|
) }
|
|
97
97
|
</>
|
|
@@ -112,7 +112,7 @@ export default function MoreMenu() {
|
|
|
112
112
|
<ModeSwitcher />
|
|
113
113
|
<ActionItem.Slot
|
|
114
114
|
name="core/plugin-more-menu"
|
|
115
|
-
label={ __( '
|
|
115
|
+
label={ __( 'Panels' ) }
|
|
116
116
|
fillProps={ { onClick: onClose } }
|
|
117
117
|
/>
|
|
118
118
|
<MenuGroup label={ __( 'Tools' ) }>
|