@wordpress/editor 14.33.3-next.36001005c.0 → 14.33.4
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 +49 -72
- package/build/bindings/post-data.js.map +3 -3
- package/build/bindings/post-meta.js +46 -47
- package/build/bindings/post-meta.js.map +2 -2
- package/build/bindings/term-data.js +6 -16
- package/build/bindings/term-data.js.map +2 -2
- package/build/components/block-settings-menu/content-only-settings-menu.js +186 -0
- package/build/components/block-settings-menu/content-only-settings-menu.js.map +7 -0
- package/build/components/collab-sidebar/add-comment.js +34 -7
- package/build/components/collab-sidebar/add-comment.js.map +3 -3
- 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 +15 -45
- package/build/components/collab-sidebar/comment-indicator-toolbar.js.map +3 -3
- package/build/components/collab-sidebar/comments.js +137 -35
- package/build/components/collab-sidebar/comments.js.map +3 -3
- package/build/components/collab-sidebar/hooks.js +8 -7
- package/build/components/collab-sidebar/hooks.js.map +2 -2
- package/build/components/collab-sidebar/index.js +56 -60
- package/build/components/collab-sidebar/index.js.map +3 -3
- package/build/components/editor/index.js +2 -0
- package/build/components/editor/index.js.map +3 -3
- package/build/components/header/index.js +0 -3
- package/build/components/header/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/post-template/hooks.js +7 -38
- package/build/components/post-template/hooks.js.map +2 -2
- package/build/components/provider/index.js +3 -1
- package/build/components/provider/index.js.map +3 -3
- package/build/components/visual-editor/index.js +20 -9
- package/build/components/visual-editor/index.js.map +2 -2
- package/build/store/actions.js +1 -1
- package/build/store/actions.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 +49 -72
- package/build-module/bindings/post-data.js.map +2 -2
- package/build-module/bindings/post-meta.js +46 -47
- package/build-module/bindings/post-meta.js.map +2 -2
- package/build-module/bindings/term-data.js +6 -16
- package/build-module/bindings/term-data.js.map +2 -2
- package/build-module/components/block-settings-menu/content-only-settings-menu.js +161 -0
- package/build-module/components/block-settings-menu/content-only-settings-menu.js.map +7 -0
- package/build-module/components/collab-sidebar/add-comment.js +36 -9
- 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 +21 -37
- package/build-module/components/collab-sidebar/comment-indicator-toolbar.js.map +2 -2
- package/build-module/components/collab-sidebar/comments.js +147 -38
- package/build-module/components/collab-sidebar/comments.js.map +2 -2
- package/build-module/components/collab-sidebar/hooks.js +8 -7
- package/build-module/components/collab-sidebar/hooks.js.map +2 -2
- package/build-module/components/collab-sidebar/index.js +56 -60
- package/build-module/components/collab-sidebar/index.js.map +2 -2
- package/build-module/components/editor/index.js +2 -0
- package/build-module/components/editor/index.js.map +2 -2
- package/build-module/components/header/index.js +0 -3
- package/build-module/components/header/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/post-template/hooks.js +7 -38
- package/build-module/components/post-template/hooks.js.map +2 -2
- package/build-module/components/provider/index.js +3 -1
- package/build-module/components/provider/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/actions.js +1 -1
- package/build-module/store/actions.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 +18 -66
- package/build-style/style.css +18 -66
- package/build-types/bindings/post-data.d.ts +20 -20
- package/build-types/bindings/post-meta.d.ts +1 -14
- package/build-types/bindings/term-data.d.ts +6 -16
- package/build-types/components/block-settings-menu/content-only-settings-menu.d.ts +2 -0
- package/build-types/components/block-settings-menu/content-only-settings-menu.d.ts.map +1 -0
- package/build-types/components/collab-sidebar/add-comment.d.ts +6 -1
- 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 +1 -2
- package/build-types/components/collab-sidebar/comment-indicator-toolbar.d.ts.map +1 -1
- package/build-types/components/collab-sidebar/comments.d.ts +12 -26
- package/build-types/components/collab-sidebar/comments.d.ts.map +1 -1
- package/build-types/components/collab-sidebar/hooks.d.ts +0 -1
- package/build-types/components/collab-sidebar/hooks.d.ts.map +1 -1
- package/build-types/components/collab-sidebar/index.d.ts +1 -4
- package/build-types/components/collab-sidebar/index.d.ts.map +1 -1
- package/build-types/components/editor/index.d.ts.map +1 -1
- package/build-types/components/header/index.d.ts.map +1 -1
- package/build-types/components/post-template/hooks.d.ts +1 -1
- package/build-types/components/post-template/hooks.d.ts.map +1 -1
- package/build-types/components/provider/index.d.ts.map +1 -1
- package/build-types/components/visual-editor/index.d.ts.map +1 -1
- package/build-types/store/actions.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 +38 -38
- package/src/bindings/post-data.js +65 -124
- package/src/bindings/post-meta.js +56 -58
- package/src/bindings/term-data.js +6 -21
- package/src/bindings/test/post-meta.js +211 -0
- package/src/components/block-settings-menu/content-only-settings-menu.js +185 -0
- package/src/components/block-settings-menu/content-only-settings-menu.native.js +4 -0
- package/src/components/block-settings-menu/style.scss +6 -0
- package/src/components/collab-sidebar/add-comment.js +41 -8
- package/src/components/collab-sidebar/comment-author-info.js +33 -26
- package/src/components/collab-sidebar/comment-indicator-toolbar.js +25 -51
- package/src/components/collab-sidebar/comments.js +147 -43
- package/src/components/collab-sidebar/hooks.js +9 -8
- package/src/components/collab-sidebar/index.js +58 -48
- package/src/components/collab-sidebar/style.scss +8 -69
- package/src/components/editor/index.js +2 -0
- package/src/components/editor-help/style.scss +1 -1
- package/src/components/header/index.js +0 -7
- package/src/components/more-menu/index.js +1 -1
- package/src/components/post-last-revision/style.scss +1 -1
- package/src/components/post-panel-row/style.scss +0 -1
- package/src/components/post-publish-panel/style.scss +1 -1
- package/src/components/post-publish-panel/test/__snapshots__/index.js.snap +2 -2
- package/src/components/post-template/hooks.js +10 -51
- package/src/components/provider/index.js +3 -4
- package/src/components/visual-editor/index.js +27 -6
- package/src/store/actions.js +4 -1
- package/src/store/private-actions.js +13 -0
- package/src/store/private-selectors.js +10 -0
- package/src/store/reducer.js +16 -0
- package/src/style.scss +1 -0
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -1,16 +1,15 @@
|
|
|
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
|
|
|
9
|
-
/**
|
|
10
|
-
* External dependencies
|
|
11
|
-
*/
|
|
12
|
-
import clsx from 'clsx';
|
|
13
|
-
|
|
14
13
|
/**
|
|
15
14
|
* Internal dependencies
|
|
16
15
|
*/
|
|
@@ -19,7 +18,7 @@ import { getAvatarBorderColor } from './utils';
|
|
|
19
18
|
|
|
20
19
|
const { CommentIconToolbarSlotFill } = unlock( blockEditorPrivateApis );
|
|
21
20
|
|
|
22
|
-
const CommentAvatarIndicator = ( { onClick, thread
|
|
21
|
+
const CommentAvatarIndicator = ( { onClick, thread } ) => {
|
|
23
22
|
const threadParticipants = useMemo( () => {
|
|
24
23
|
if ( ! thread ) {
|
|
25
24
|
return [];
|
|
@@ -34,15 +33,13 @@ const CommentAvatarIndicator = ( { onClick, thread, hasMoreComments } ) => {
|
|
|
34
33
|
allComments.forEach( ( comment ) => {
|
|
35
34
|
// Track thread participants (original commenter + repliers).
|
|
36
35
|
if ( comment.author_name && comment.author_avatar_urls ) {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
participantsMap.set( authorKey, {
|
|
36
|
+
if ( ! participantsMap.has( comment.author ) ) {
|
|
37
|
+
participantsMap.set( comment.author, {
|
|
40
38
|
name: comment.author_name,
|
|
41
39
|
avatar:
|
|
42
40
|
comment.author_avatar_urls?.[ '48' ] ||
|
|
43
41
|
comment.author_avatar_urls?.[ '96' ],
|
|
44
42
|
id: comment.author,
|
|
45
|
-
isOriginalCommenter: comment.id === thread.id,
|
|
46
43
|
date: comment.date,
|
|
47
44
|
} );
|
|
48
45
|
}
|
|
@@ -52,22 +49,21 @@ const CommentAvatarIndicator = ( { onClick, thread, hasMoreComments } ) => {
|
|
|
52
49
|
return Array.from( participantsMap.values() );
|
|
53
50
|
}, [ thread ] );
|
|
54
51
|
|
|
55
|
-
const hasUnresolved = thread?.status !== 'approved';
|
|
56
|
-
|
|
57
|
-
// Check if this specific thread has more participants due to pagination.
|
|
58
|
-
// If we have pagination AND this thread + its replies equals or exceeds the API limit,
|
|
59
|
-
// then this thread likely has more participants that weren't loaded.
|
|
60
|
-
const threadHasMoreParticipants =
|
|
61
|
-
hasMoreComments && thread?.reply && 1 + thread.reply.length >= 100;
|
|
62
|
-
|
|
63
52
|
if ( ! threadParticipants.length ) {
|
|
64
53
|
return null;
|
|
65
54
|
}
|
|
66
55
|
|
|
67
|
-
//
|
|
56
|
+
// If there are more than 3 participants, show 2 avatars and a "+n" number.
|
|
68
57
|
const maxAvatars = 3;
|
|
69
|
-
const
|
|
70
|
-
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
|
+
);
|
|
66
|
+
const threadHasMoreParticipants = threadParticipants.length > 100;
|
|
71
67
|
|
|
72
68
|
// If we hit the comment limit, show "100+" instead of exact overflow count.
|
|
73
69
|
const overflowText =
|
|
@@ -79,38 +75,22 @@ const CommentAvatarIndicator = ( { onClick, thread, hasMoreComments } ) => {
|
|
|
79
75
|
overflowCount
|
|
80
76
|
);
|
|
81
77
|
|
|
82
|
-
const overflowTitle =
|
|
83
|
-
threadHasMoreParticipants && overflowCount > 0
|
|
84
|
-
? __( '100+ participants' )
|
|
85
|
-
: sprintf(
|
|
86
|
-
// translators: %s: Number of participants.
|
|
87
|
-
_n(
|
|
88
|
-
'+%s more participant',
|
|
89
|
-
'+%s more participants',
|
|
90
|
-
overflowCount
|
|
91
|
-
),
|
|
92
|
-
overflowCount
|
|
93
|
-
);
|
|
94
|
-
|
|
95
78
|
return (
|
|
96
79
|
<CommentIconToolbarSlotFill.Fill>
|
|
97
80
|
<ToolbarButton
|
|
98
|
-
className=
|
|
99
|
-
'has-unresolved': hasUnresolved,
|
|
100
|
-
} ) }
|
|
81
|
+
className="comment-avatar-indicator"
|
|
101
82
|
label={ __( 'View notes' ) }
|
|
102
83
|
onClick={ onClick }
|
|
103
84
|
showTooltip
|
|
104
85
|
>
|
|
105
|
-
<
|
|
106
|
-
{ visibleParticipants.map( ( participant
|
|
86
|
+
<HStack spacing="1">
|
|
87
|
+
{ visibleParticipants.map( ( participant ) => (
|
|
107
88
|
<img
|
|
108
|
-
key={ participant.
|
|
89
|
+
key={ participant.id }
|
|
109
90
|
src={ participant.avatar }
|
|
110
91
|
alt={ participant.name }
|
|
111
92
|
className="comment-avatar"
|
|
112
93
|
style={ {
|
|
113
|
-
zIndex: maxAvatars - index,
|
|
114
94
|
borderColor: getAvatarBorderColor(
|
|
115
95
|
participant.id
|
|
116
96
|
),
|
|
@@ -118,15 +98,9 @@ const CommentAvatarIndicator = ( { onClick, thread, hasMoreComments } ) => {
|
|
|
118
98
|
/>
|
|
119
99
|
) ) }
|
|
120
100
|
{ overflowCount > 0 && (
|
|
121
|
-
<
|
|
122
|
-
className="comment-avatar-overflow"
|
|
123
|
-
style={ { zIndex: 0 } }
|
|
124
|
-
title={ overflowTitle }
|
|
125
|
-
>
|
|
126
|
-
{ overflowText }
|
|
127
|
-
</div>
|
|
101
|
+
<Text weight={ 500 }>{ overflowText }</Text>
|
|
128
102
|
) }
|
|
129
|
-
</
|
|
103
|
+
</HStack>
|
|
130
104
|
</ToolbarButton>
|
|
131
105
|
</CommentIconToolbarSlotFill.Fill>
|
|
132
106
|
);
|
|
@@ -6,7 +6,14 @@ import clsx from 'clsx';
|
|
|
6
6
|
/**
|
|
7
7
|
* WordPress dependencies
|
|
8
8
|
*/
|
|
9
|
-
import {
|
|
9
|
+
import {
|
|
10
|
+
useState,
|
|
11
|
+
RawHTML,
|
|
12
|
+
useEffect,
|
|
13
|
+
useCallback,
|
|
14
|
+
useMemo,
|
|
15
|
+
useRef,
|
|
16
|
+
} from '@wordpress/element';
|
|
10
17
|
import {
|
|
11
18
|
__experimentalText as Text,
|
|
12
19
|
__experimentalHStack as HStack,
|
|
@@ -33,32 +40,20 @@ import {
|
|
|
33
40
|
import { unlock } from '../../lock-unlock';
|
|
34
41
|
import CommentAuthorInfo from './comment-author-info';
|
|
35
42
|
import CommentForm from './comment-form';
|
|
36
|
-
import {
|
|
43
|
+
import { focusCommentThread, getCommentExcerpt } from './utils';
|
|
37
44
|
import { useFloatingThread } from './hooks';
|
|
45
|
+
import { AddComment } from './add-comment';
|
|
46
|
+
import { store as editorStore } from '../../store';
|
|
38
47
|
|
|
39
48
|
const { useBlockElement } = unlock( blockEditorPrivateApis );
|
|
40
49
|
const { Menu } = unlock( componentsPrivateApis );
|
|
41
50
|
|
|
42
|
-
/**
|
|
43
|
-
* Renders the Comments component.
|
|
44
|
-
*
|
|
45
|
-
* @param {Object} props - The component props.
|
|
46
|
-
* @param {Array} props.threads - The array of comment threads.
|
|
47
|
-
* @param {Function} props.onEditComment - The function to handle comment editing.
|
|
48
|
-
* @param {Function} props.onAddReply - The function to add a reply to a comment.
|
|
49
|
-
* @param {Function} props.onCommentDelete - The function to delete a comment.
|
|
50
|
-
* @param {Function} props.setShowCommentBoard - The function to set the comment board visibility.
|
|
51
|
-
* @param {Ref} props.commentSidebarRef - The ref to the comment sidebar.
|
|
52
|
-
* @param {Function} props.reflowComments - The function to call indicating a comment is updated.
|
|
53
|
-
* @param {boolean} props.isFloating - Whether the comment thread is floating.
|
|
54
|
-
* @param {number} props.commentLastUpdated - Timestamp of the last comment update.
|
|
55
|
-
* @return {React.ReactNode} The rendered Comments component.
|
|
56
|
-
*/
|
|
57
51
|
export function Comments( {
|
|
58
|
-
threads,
|
|
52
|
+
threads: noteThreads,
|
|
59
53
|
onEditComment,
|
|
60
54
|
onAddReply,
|
|
61
55
|
onCommentDelete,
|
|
56
|
+
showCommentBoard,
|
|
62
57
|
setShowCommentBoard,
|
|
63
58
|
commentSidebarRef,
|
|
64
59
|
reflowComments,
|
|
@@ -70,20 +65,63 @@ export function Comments( {
|
|
|
70
65
|
const [ boardOffsets, setBoardOffsets ] = useState( {} );
|
|
71
66
|
const [ blockRefs, setBlockRefs ] = useState( {} );
|
|
72
67
|
|
|
73
|
-
const {
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
:
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
68
|
+
const { setCanvasMinHeight } = unlock( useDispatch( editorStore ) );
|
|
69
|
+
const { blockCommentId, selectedBlockClientId, orderedBlockIds } =
|
|
70
|
+
useSelect( ( select ) => {
|
|
71
|
+
const { getBlockAttributes, getSelectedBlockClientId } =
|
|
72
|
+
select( blockEditorStore );
|
|
73
|
+
const clientId = getSelectedBlockClientId();
|
|
74
|
+
return {
|
|
75
|
+
blockCommentId: clientId
|
|
76
|
+
? getBlockAttributes( clientId )?.metadata?.noteId
|
|
77
|
+
: null,
|
|
78
|
+
selectedBlockClientId: clientId,
|
|
79
|
+
orderedBlockIds: select( blockEditorStore ).getBlockOrder(),
|
|
80
|
+
};
|
|
81
|
+
}, [] );
|
|
84
82
|
|
|
85
83
|
const relatedBlockElement = useBlockElement( selectedBlockClientId );
|
|
86
84
|
|
|
85
|
+
const threads = useMemo( () => {
|
|
86
|
+
const t = [ ...noteThreads ];
|
|
87
|
+
const orderedThreads = [];
|
|
88
|
+
// In floating mode, when the note board is shown, and as long
|
|
89
|
+
// as the selected block doesn't have an existing note attached -
|
|
90
|
+
// add a "new note" entry to the threads. This special thread type
|
|
91
|
+
// gets sorted and floated like regular threads, but shows an AddComment
|
|
92
|
+
// component instead of a regular comment thread.
|
|
93
|
+
if ( isFloating && showCommentBoard && undefined === blockCommentId ) {
|
|
94
|
+
// Insert the new note entry at the correct location for its blockId.
|
|
95
|
+
const newNoteThread = {
|
|
96
|
+
id: 'new-note-thread',
|
|
97
|
+
blockClientId: selectedBlockClientId,
|
|
98
|
+
content: { rendered: '' },
|
|
99
|
+
};
|
|
100
|
+
// Insert the new comment block at the right order within the threads.
|
|
101
|
+
orderedBlockIds.forEach( ( blockId ) => {
|
|
102
|
+
if ( blockId === selectedBlockClientId ) {
|
|
103
|
+
orderedThreads.push( newNoteThread );
|
|
104
|
+
} else {
|
|
105
|
+
const threadForBlock = t.find(
|
|
106
|
+
( thread ) => thread.blockClientId === blockId
|
|
107
|
+
);
|
|
108
|
+
if ( threadForBlock ) {
|
|
109
|
+
orderedThreads.push( threadForBlock );
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
} );
|
|
113
|
+
return orderedThreads;
|
|
114
|
+
}
|
|
115
|
+
return t;
|
|
116
|
+
}, [
|
|
117
|
+
noteThreads,
|
|
118
|
+
isFloating,
|
|
119
|
+
showCommentBoard,
|
|
120
|
+
blockCommentId,
|
|
121
|
+
selectedBlockClientId,
|
|
122
|
+
orderedBlockIds,
|
|
123
|
+
] );
|
|
124
|
+
|
|
87
125
|
const handleDelete = async ( comment ) => {
|
|
88
126
|
const currentIndex = threads.findIndex( ( t ) => t.id === comment.id );
|
|
89
127
|
const nextThread = threads[ currentIndex + 1 ];
|
|
@@ -114,8 +152,10 @@ export function Comments( {
|
|
|
114
152
|
|
|
115
153
|
// Auto-select the related comment thread when a block is selected.
|
|
116
154
|
useEffect( () => {
|
|
117
|
-
|
|
118
|
-
|
|
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 ] );
|
|
119
159
|
|
|
120
160
|
const setBlockRef = useCallback( ( id, blockRef ) => {
|
|
121
161
|
setBlockRefs( ( prev ) => ( { ...prev, [ id ]: blockRef } ) );
|
|
@@ -131,7 +171,7 @@ export function Comments( {
|
|
|
131
171
|
const offsets = {};
|
|
132
172
|
|
|
133
173
|
if ( ! isFloating ) {
|
|
134
|
-
return offsets;
|
|
174
|
+
return { offsets, minHeight: 0 };
|
|
135
175
|
}
|
|
136
176
|
|
|
137
177
|
// Find the index of the selected thread.
|
|
@@ -149,7 +189,7 @@ export function Comments( {
|
|
|
149
189
|
! selectedThreadData ||
|
|
150
190
|
! blockRefs[ selectedThreadData.id ]
|
|
151
191
|
) {
|
|
152
|
-
return offsets;
|
|
192
|
+
return { offsets, minHeight: 0 };
|
|
153
193
|
}
|
|
154
194
|
|
|
155
195
|
let blockElement = blockRefs[ selectedThreadData.id ];
|
|
@@ -236,28 +276,67 @@ export function Comments( {
|
|
|
236
276
|
threadTop: threadTop + additionalOffset,
|
|
237
277
|
};
|
|
238
278
|
}
|
|
239
|
-
|
|
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 };
|
|
240
294
|
};
|
|
241
|
-
const newOffsets = calculateAllOffsets();
|
|
295
|
+
const { offsets: newOffsets, minHeight } = calculateAllOffsets();
|
|
242
296
|
if ( Object.keys( newOffsets ).length > 0 ) {
|
|
243
297
|
setBoardOffsets( newOffsets );
|
|
244
298
|
}
|
|
245
|
-
|
|
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
|
+
] );
|
|
246
309
|
|
|
247
310
|
const hasThreads = Array.isArray( threads ) && threads.length > 0;
|
|
248
311
|
if ( ! hasThreads && ! isFloating ) {
|
|
249
312
|
return (
|
|
250
|
-
|
|
313
|
+
<>
|
|
314
|
+
<AddComment
|
|
315
|
+
onSubmit={ onAddReply }
|
|
316
|
+
showCommentBoard={ showCommentBoard }
|
|
317
|
+
setShowCommentBoard={ setShowCommentBoard }
|
|
318
|
+
commentSidebarRef={ commentSidebarRef }
|
|
319
|
+
/>
|
|
251
320
|
<Text as="p">{ __( 'No notes available.' ) }</Text>
|
|
252
321
|
<Text as="p" variant="muted">
|
|
253
322
|
{ __( 'Only logged in users can see Notes.' ) }
|
|
254
323
|
</Text>
|
|
255
|
-
|
|
324
|
+
</>
|
|
256
325
|
);
|
|
257
326
|
}
|
|
258
327
|
|
|
259
328
|
return (
|
|
260
|
-
|
|
329
|
+
<>
|
|
330
|
+
{ ! isFloating &&
|
|
331
|
+
showCommentBoard &&
|
|
332
|
+
undefined === blockCommentId && (
|
|
333
|
+
<AddComment
|
|
334
|
+
onSubmit={ onAddReply }
|
|
335
|
+
showCommentBoard={ showCommentBoard }
|
|
336
|
+
setShowCommentBoard={ setShowCommentBoard }
|
|
337
|
+
commentSidebarRef={ commentSidebarRef }
|
|
338
|
+
/>
|
|
339
|
+
) }
|
|
261
340
|
{ threads.map( ( thread ) => (
|
|
262
341
|
<Thread
|
|
263
342
|
key={ thread.id }
|
|
@@ -276,9 +355,10 @@ export function Comments( {
|
|
|
276
355
|
setBlockRef={ setBlockRef }
|
|
277
356
|
selectedThread={ selectedThread }
|
|
278
357
|
commentLastUpdated={ commentLastUpdated }
|
|
358
|
+
showCommentBoard={ showCommentBoard }
|
|
279
359
|
/>
|
|
280
360
|
) ) }
|
|
281
|
-
|
|
361
|
+
</>
|
|
282
362
|
);
|
|
283
363
|
}
|
|
284
364
|
|
|
@@ -298,6 +378,7 @@ function Thread( {
|
|
|
298
378
|
setSelectedThread,
|
|
299
379
|
selectedThread,
|
|
300
380
|
commentLastUpdated,
|
|
381
|
+
showCommentBoard,
|
|
301
382
|
} ) {
|
|
302
383
|
const { toggleBlockHighlight, selectBlock, toggleBlockSpotlight } = unlock(
|
|
303
384
|
useDispatch( blockEditorStore )
|
|
@@ -347,7 +428,7 @@ function Thread( {
|
|
|
347
428
|
const restReplies = allReplies.length > 0 ? allReplies.slice( 0, -1 ) : [];
|
|
348
429
|
|
|
349
430
|
const commentExcerpt = getCommentExcerpt(
|
|
350
|
-
stripHTML( thread.content
|
|
431
|
+
stripHTML( thread.content?.rendered ),
|
|
351
432
|
10
|
|
352
433
|
);
|
|
353
434
|
const ariaLabel = !! thread.blockClientId
|
|
@@ -362,6 +443,21 @@ function Thread( {
|
|
|
362
443
|
commentExcerpt
|
|
363
444
|
);
|
|
364
445
|
|
|
446
|
+
if ( 'new-note-thread' === thread.id && showCommentBoard && isFloating ) {
|
|
447
|
+
return (
|
|
448
|
+
<AddComment
|
|
449
|
+
onSubmit={ onAddReply }
|
|
450
|
+
showCommentBoard={ showCommentBoard }
|
|
451
|
+
setShowCommentBoard={ setShowCommentBoard }
|
|
452
|
+
commentSidebarRef={ commentSidebarRef }
|
|
453
|
+
reflowComments={ reflowComments }
|
|
454
|
+
isFloating={ isFloating }
|
|
455
|
+
y={ y }
|
|
456
|
+
refs={ refs }
|
|
457
|
+
/>
|
|
458
|
+
);
|
|
459
|
+
}
|
|
460
|
+
|
|
365
461
|
return (
|
|
366
462
|
// Disable reason: role="listitem" does in fact support aria-expanded.
|
|
367
463
|
// eslint-disable-next-line jsx-a11y/role-supports-aria-props
|
|
@@ -378,6 +474,9 @@ function Thread( {
|
|
|
378
474
|
onFocus={ onMouseEnter }
|
|
379
475
|
onBlur={ onMouseLeave }
|
|
380
476
|
onKeyDown={ ( event ) => {
|
|
477
|
+
if ( event.defaultPrevented ) {
|
|
478
|
+
return;
|
|
479
|
+
}
|
|
381
480
|
// Expand or Collapse thread.
|
|
382
481
|
if (
|
|
383
482
|
event.key === 'Enter' &&
|
|
@@ -562,7 +661,7 @@ const CommentBoard = ( {
|
|
|
562
661
|
} ) => {
|
|
563
662
|
const [ actionState, setActionState ] = useState( false );
|
|
564
663
|
const [ showConfirmDialog, setShowConfirmDialog ] = useState( false );
|
|
565
|
-
|
|
664
|
+
const actionButtonRef = useRef( null );
|
|
566
665
|
const handleConfirmDelete = () => {
|
|
567
666
|
onDelete( thread );
|
|
568
667
|
setActionState( false );
|
|
@@ -572,6 +671,7 @@ const CommentBoard = ( {
|
|
|
572
671
|
const handleCancel = () => {
|
|
573
672
|
setActionState( false );
|
|
574
673
|
setShowConfirmDialog( false );
|
|
674
|
+
actionButtonRef.current?.focus();
|
|
575
675
|
};
|
|
576
676
|
|
|
577
677
|
// Check if this is a resolution comment by checking metadata.
|
|
@@ -657,6 +757,7 @@ const CommentBoard = ( {
|
|
|
657
757
|
<Menu.TriggerButton
|
|
658
758
|
render={
|
|
659
759
|
<Button
|
|
760
|
+
ref={ actionButtonRef }
|
|
660
761
|
size="small"
|
|
661
762
|
icon={ moreVertical }
|
|
662
763
|
label={ __( 'Actions' ) }
|
|
@@ -690,6 +791,7 @@ const CommentBoard = ( {
|
|
|
690
791
|
content: value,
|
|
691
792
|
} );
|
|
692
793
|
setActionState( false );
|
|
794
|
+
actionButtonRef.current?.focus();
|
|
693
795
|
} }
|
|
694
796
|
onCancel={ () => handleCancel() }
|
|
695
797
|
thread={ thread }
|
|
@@ -745,7 +847,9 @@ const CommentBoard = ( {
|
|
|
745
847
|
onCancel={ handleCancel }
|
|
746
848
|
confirmButtonText={ __( 'Delete' ) }
|
|
747
849
|
>
|
|
748
|
-
{ __(
|
|
850
|
+
{ __(
|
|
851
|
+
"Are you sure you want to delete this note? This will also delete all of this note's replies."
|
|
852
|
+
) }
|
|
749
853
|
</ConfirmDialog>
|
|
750
854
|
) }
|
|
751
855
|
</VStack>
|
|
@@ -50,10 +50,10 @@ export function useBlockComments( postId ) {
|
|
|
50
50
|
post: postId,
|
|
51
51
|
type: 'note',
|
|
52
52
|
status: 'all',
|
|
53
|
-
per_page:
|
|
53
|
+
per_page: -1,
|
|
54
54
|
};
|
|
55
55
|
|
|
56
|
-
const { records: threads
|
|
56
|
+
const { records: threads } = useEntityRecords(
|
|
57
57
|
'root',
|
|
58
58
|
'comment',
|
|
59
59
|
queryArgs,
|
|
@@ -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 ] );
|
|
@@ -160,7 +162,6 @@ export function useBlockComments( postId ) {
|
|
|
160
162
|
return {
|
|
161
163
|
resultComments,
|
|
162
164
|
unresolvedSortedThreads,
|
|
163
|
-
totalPages,
|
|
164
165
|
reflowComments,
|
|
165
166
|
commentLastUpdated,
|
|
166
167
|
};
|
|
@@ -399,7 +400,7 @@ export function useFloatingThread( {
|
|
|
399
400
|
if ( blockRef.current ) {
|
|
400
401
|
refs.setReference( blockRef.current );
|
|
401
402
|
}
|
|
402
|
-
}, [ blockRef, refs ] );
|
|
403
|
+
}, [ blockRef, refs, commentLastUpdated ] );
|
|
403
404
|
|
|
404
405
|
// Track thread heights.
|
|
405
406
|
useEffect( () => {
|