UNPKG

@wordpress/block-library

Version:
8 lines (7 loc) 13.8 kB
{ "version": 3, "sources": ["../../src/comment-template/edit.js"], "sourcesContent": ["/**\n * WordPress dependencies\n */\nimport { useState, memo } from '@wordpress/element';\nimport { useSelect } from '@wordpress/data';\nimport { __ } from '@wordpress/i18n';\nimport {\n\tBlockContextProvider,\n\tuseBlockProps,\n\tuseInnerBlocksProps,\n\tstore as blockEditorStore,\n\t__experimentalUseBlockPreview as useBlockPreview,\n} from '@wordpress/block-editor';\nimport { Spinner } from '@wordpress/components';\nimport { store as coreStore } from '@wordpress/core-data';\n\n/**\n * Internal dependencies\n */\nimport { useCommentQueryArgs, useCommentTree } from './hooks';\n\nconst TEMPLATE = [\n\t[ 'core/avatar' ],\n\t[ 'core/comment-author-name' ],\n\t[ 'core/comment-date' ],\n\t[ 'core/comment-content' ],\n\t[ 'core/comment-reply-link' ],\n\t[ 'core/comment-edit-link' ],\n];\n\n/**\n * Function that returns a comment structure that will be rendered with default placehoders.\n *\n * Each comment has a `commentId` property that is always a negative number in\n * case of the placeholders. This is to ensure that the comment does not\n * conflict with the actual (real) comments.\n *\n * @param {Object} settings Discussion Settings.\n * @param {number} [settings.perPage] - Comments per page setting or block attribute.\n * @param {boolean} [settings.pageComments] - Enable break comments into pages setting.\n * @param {boolean} [settings.threadComments] - Enable threaded (nested) comments setting.\n * @param {number} [settings.threadCommentsDepth] - Level deep of threaded comments.\n *\n * @typedef {{id: null, children: EmptyComment[]}} EmptyComment\n * @return {EmptyComment[]} \t\tInner blocks of the Comment Template\n */\nconst getCommentsPlaceholder = ( {\n\tperPage,\n\tpageComments,\n\tthreadComments,\n\tthreadCommentsDepth,\n} ) => {\n\t// Limit commentsDepth to 3\n\tconst commentsDepth = ! threadComments\n\t\t? 1\n\t\t: Math.min( threadCommentsDepth, 3 );\n\n\tconst buildChildrenComment = ( commentsLevel ) => {\n\t\t// Render children comments until commentsDepth is reached\n\t\tif ( commentsLevel < commentsDepth ) {\n\t\t\tconst nextLevel = commentsLevel + 1;\n\n\t\t\treturn [\n\t\t\t\t{\n\t\t\t\t\tcommentId: -( commentsLevel + 3 ),\n\t\t\t\t\tchildren: buildChildrenComment( nextLevel ),\n\t\t\t\t},\n\t\t\t];\n\t\t}\n\t\treturn [];\n\t};\n\n\t// Add the first comment and its children\n\tconst placeholderComments = [\n\t\t{ commentId: -1, children: buildChildrenComment( 1 ) },\n\t];\n\n\t// Add a second comment unless the break comments setting is active and set to less than 2, and there is one nested comment max\n\tif ( ( ! pageComments || perPage >= 2 ) && commentsDepth < 3 ) {\n\t\tplaceholderComments.push( {\n\t\t\tcommentId: -2,\n\t\t\tchildren: [],\n\t\t} );\n\t}\n\n\t// Add a third comment unless the break comments setting is active and set to less than 3, and there aren't nested comments\n\tif ( ( ! pageComments || perPage >= 3 ) && commentsDepth < 2 ) {\n\t\tplaceholderComments.push( {\n\t\t\tcommentId: -3,\n\t\t\tchildren: [],\n\t\t} );\n\t}\n\n\t// In case that the value is set but larger than 3 we truncate it to 3.\n\treturn placeholderComments;\n};\n\n/**\n * Component which renders the inner blocks of the Comment Template.\n *\n * @param {Object} props Component props.\n * @param {Array} [props.comment] - A comment object.\n * @param {Array} [props.activeCommentId] - The ID of the comment that is currently active.\n * @param {Array} [props.setActiveCommentId] - The setter for activeCommentId.\n * @param {Array} [props.firstCommentId] - ID of the first comment in the array.\n * @param {Array} [props.blocks] - Array of blocks returned from\n * getBlocks() in parent .\n * @return {Element} \t\tInner blocks of the Comment Template\n */\nfunction CommentTemplateInnerBlocks( {\n\tcomment,\n\tactiveCommentId,\n\tsetActiveCommentId,\n\tfirstCommentId,\n\tblocks,\n} ) {\n\tconst { children, ...innerBlocksProps } = useInnerBlocksProps(\n\t\t{},\n\t\t{ template: TEMPLATE }\n\t);\n\n\treturn (\n\t\t<li { ...innerBlocksProps }>\n\t\t\t{ comment.commentId === ( activeCommentId || firstCommentId )\n\t\t\t\t? children\n\t\t\t\t: null }\n\n\t\t\t{ /* To avoid flicker when switching active block contexts, a preview\n\t\t\t is ALWAYS rendered and the preview for the active block is hidden.\n\t\t\t This ensures that when switching the active block, the component is not\n\t\t\t mounted again but rather it only toggles the `isHidden` prop.\n\t\t\t The same strategy is used for preventing the flicker in the Post Template\n\t\t\t block. */ }\n\t\t\t<MemoizedCommentTemplatePreview\n\t\t\t\tblocks={ blocks }\n\t\t\t\tcommentId={ comment.commentId }\n\t\t\t\tsetActiveCommentId={ setActiveCommentId }\n\t\t\t\tisHidden={\n\t\t\t\t\tcomment.commentId === ( activeCommentId || firstCommentId )\n\t\t\t\t}\n\t\t\t/>\n\n\t\t\t{ comment?.children?.length > 0 ? (\n\t\t\t\t<CommentsList\n\t\t\t\t\tcomments={ comment.children }\n\t\t\t\t\tactiveCommentId={ activeCommentId }\n\t\t\t\t\tsetActiveCommentId={ setActiveCommentId }\n\t\t\t\t\tblocks={ blocks }\n\t\t\t\t\tfirstCommentId={ firstCommentId }\n\t\t\t\t/>\n\t\t\t) : null }\n\t\t</li>\n\t);\n}\n\nconst CommentTemplatePreview = ( {\n\tblocks,\n\tcommentId,\n\tsetActiveCommentId,\n\tisHidden,\n} ) => {\n\tconst blockPreviewProps = useBlockPreview( {\n\t\tblocks,\n\t} );\n\n\tconst handleOnClick = () => {\n\t\tsetActiveCommentId( commentId );\n\t};\n\n\t// We have to hide the preview block if the `comment` props points to\n\t// the currently active block!\n\n\t// Or, to put it differently, every preview block is visible unless it is the\n\t// currently active block - in this case we render its inner blocks.\n\tconst style = {\n\t\tdisplay: isHidden ? 'none' : undefined,\n\t};\n\n\treturn (\n\t\t<div\n\t\t\t{ ...blockPreviewProps }\n\t\t\ttabIndex={ 0 }\n\t\t\trole=\"button\"\n\t\t\tstyle={ style }\n\t\t\tonClick={ handleOnClick }\n\t\t\tonKeyPress={ handleOnClick }\n\t\t/>\n\t);\n};\n\nconst MemoizedCommentTemplatePreview = memo( CommentTemplatePreview );\n\n/**\n * Component that renders a list of (nested) comments. It is called recursively.\n *\n * @param {Object} props Component props.\n * @param {Array} [props.comments] - Array of comment objects.\n * @param {Array} [props.blockProps] - Props from parent's `useBlockProps()`.\n * @param {Array} [props.activeCommentId] - The ID of the comment that is currently active.\n * @param {Array} [props.setActiveCommentId] - The setter for activeCommentId.\n * @param {Array} [props.blocks] - Array of blocks returned from getBlocks() in parent.\n * @param {Object} [props.firstCommentId] - The ID of the first comment in the array of\n * comment objects.\n * @return {Element} \t\tList of comments.\n */\nconst CommentsList = ( {\n\tcomments,\n\tblockProps,\n\tactiveCommentId,\n\tsetActiveCommentId,\n\tblocks,\n\tfirstCommentId,\n} ) => (\n\t<ol { ...blockProps }>\n\t\t{ comments &&\n\t\t\tcomments.map( ( { commentId, ...comment }, index ) => (\n\t\t\t\t<BlockContextProvider\n\t\t\t\t\tkey={ comment.commentId || index }\n\t\t\t\t\tvalue={ {\n\t\t\t\t\t\t// If the commentId is negative it means that this comment is a\n\t\t\t\t\t\t// \"placeholder\" and that the block is most likely being used in the\n\t\t\t\t\t\t// site editor. In this case, we have to set the commentId to `null`\n\t\t\t\t\t\t// because otherwise the (non-existent) comment with a negative ID\n\t\t\t\t\t\t// would be requested from the REST API.\n\t\t\t\t\t\tcommentId: commentId < 0 ? null : commentId,\n\t\t\t\t\t} }\n\t\t\t\t>\n\t\t\t\t\t<CommentTemplateInnerBlocks\n\t\t\t\t\t\tcomment={ { commentId, ...comment } }\n\t\t\t\t\t\tactiveCommentId={ activeCommentId }\n\t\t\t\t\t\tsetActiveCommentId={ setActiveCommentId }\n\t\t\t\t\t\tblocks={ blocks }\n\t\t\t\t\t\tfirstCommentId={ firstCommentId }\n\t\t\t\t\t/>\n\t\t\t\t</BlockContextProvider>\n\t\t\t) ) }\n\t</ol>\n);\n\nexport default function CommentTemplateEdit( {\n\tclientId,\n\tcontext: { postId },\n} ) {\n\tconst blockProps = useBlockProps();\n\n\tconst [ activeCommentId, setActiveCommentId ] = useState();\n\tconst {\n\t\tcommentOrder,\n\t\tthreadCommentsDepth,\n\t\tthreadComments,\n\t\tcommentsPerPage,\n\t\tpageComments,\n\t} = useSelect( ( select ) => {\n\t\tconst { getSettings } = select( blockEditorStore );\n\t\treturn getSettings().__experimentalDiscussionSettings ?? {};\n\t}, [] );\n\n\tconst commentQuery = useCommentQueryArgs( {\n\t\tpostId,\n\t} );\n\n\tconst { topLevelComments, blocks } = useSelect(\n\t\t( select ) => {\n\t\t\tconst { getEntityRecords } = select( coreStore );\n\t\t\tconst { getBlocks } = select( blockEditorStore );\n\t\t\treturn {\n\t\t\t\t// Request only top-level comments. Replies are embedded.\n\t\t\t\ttopLevelComments: commentQuery\n\t\t\t\t\t? getEntityRecords( 'root', 'comment', commentQuery )\n\t\t\t\t\t: null,\n\t\t\t\tblocks: getBlocks( clientId ),\n\t\t\t};\n\t\t},\n\t\t[ clientId, commentQuery ]\n\t);\n\n\t// Generate a tree structure of comment IDs.\n\tlet commentTree = useCommentTree(\n\t\t// Reverse the order of top comments if needed.\n\t\tcommentOrder === 'desc' && topLevelComments\n\t\t\t? [ ...topLevelComments ].reverse()\n\t\t\t: topLevelComments\n\t);\n\n\tif ( ! topLevelComments ) {\n\t\treturn (\n\t\t\t<p { ...blockProps }>\n\t\t\t\t<Spinner />\n\t\t\t</p>\n\t\t);\n\t}\n\n\tif ( ! postId ) {\n\t\tcommentTree = getCommentsPlaceholder( {\n\t\t\tperPage: commentsPerPage,\n\t\t\tpageComments,\n\t\t\tthreadComments,\n\t\t\tthreadCommentsDepth,\n\t\t} );\n\t}\n\n\tif ( ! commentTree.length ) {\n\t\treturn <p { ...blockProps }>{ __( 'No results found.' ) }</p>;\n\t}\n\n\treturn (\n\t\t<CommentsList\n\t\t\tcomments={ commentTree }\n\t\t\tblockProps={ blockProps }\n\t\t\tblocks={ blocks }\n\t\t\tactiveCommentId={ activeCommentId }\n\t\t\tsetActiveCommentId={ setActiveCommentId }\n\t\t\tfirstCommentId={ commentTree[ 0 ]?.commentId }\n\t\t/>\n\t);\n}\n"], "mappings": "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", "names": ["useBlockPreview", "blockEditorStore", "coreStore"] }