UNPKG

@wordpress/editor

Version:
168 lines (167 loc) 5.4 kB
// packages/editor/src/components/collaborators-overlay/use-render-cursors.ts import { privateApis as coreDataPrivateApis } from "@wordpress/core-data"; import { useSelect } from "@wordpress/data"; import { useEffect, useState } from "@wordpress/element"; import { store as preferencesStore } from "@wordpress/preferences"; import { unlock } from "../../lock-unlock.mjs"; import { getAvatarUrl } from "./get-avatar-url.mjs"; import { getAvatarBorderColor } from "../collab-sidebar/utils.mjs"; import { computeSelectionVisual } from "./compute-selection.mjs"; import { useDebouncedRecompute, useRequestAnimationFrameRecompute } from "./use-debounced-recompute.mjs"; import { blockContainerOf } from "./cursor-dom-utils.mjs"; import { getCollaboratorDisplayName } from "../../utils/get-collaborator-display-name.mjs"; var { useActiveCollaborators, useResolvedSelection } = unlock(coreDataPrivateApis); var { SelectionType } = unlock(coreDataPrivateApis); function useRenderCursors(overlayElement, blockEditorDocument, postId, postType, delayMs) { const sortedUsers = useActiveCollaborators( postId ?? null, postType ?? null ); const resolveSelection = useResolvedSelection( postId ?? null, postType ?? null ); const showOwnCursor = useSelect( (select) => select(preferencesStore).get("core", "showCollaborationCursor"), [] ); const [cursorPositions, setCursorPositions] = useState( [] ); const [recomputeToken, rerenderCursorsAfterDelay] = useDebouncedRecompute(delayMs); const [resizeToken, rerenderCursorsOnResize] = useRequestAnimationFrameRecompute(); useEffect(() => { if (!overlayElement || !blockEditorDocument) { setCursorPositions([]); return; } const overlayRect = overlayElement.getBoundingClientRect(); const overlayContext = { editorDocument: blockEditorDocument, overlayRect }; const results = []; const hasOtherCollaborators = sortedUsers.some( (u) => !u.isMe ); sortedUsers.forEach((user) => { if (user.isMe && (!showOwnCursor || !hasOtherCollaborators)) { return; } const selection = user.editorState?.selection ?? { type: SelectionType.None }; let start = { richTextOffset: null, localClientId: null, attributeKey: null }; let end; if (selection.type === SelectionType.Cursor) { try { start = resolveSelection(selection); } catch { return; } } else if (selection.type === SelectionType.SelectionInOneBlock) { try { start = resolveSelection({ type: SelectionType.Cursor, cursorPosition: selection.cursorStartPosition }); end = resolveSelection({ type: SelectionType.Cursor, cursorPosition: selection.cursorEndPosition }); } catch { return; } } else if (selection.type === SelectionType.SelectionInMultipleBlocks) { const resolveEndpoint = (endpoint) => resolveSelection(endpoint); try { start = resolveEndpoint(selection.startEndpoint); end = resolveEndpoint(selection.endEndpoint); } catch { return; } const promote = (r) => { if (!r.localClientId) { return r; } const el = blockEditorDocument.querySelector( `[data-block="${r.localClientId}"]` ); if (!el) { return r; } const container = blockContainerOf(el); const containerId = container.getAttribute("data-block"); if (!containerId || containerId === r.localClientId) { return r; } return { ...r, localClientId: containerId, richTextOffset: null, attributeKey: null }; }; start = promote(start); if (end) { end = promote(end); } } const userName = getCollaboratorDisplayName( user.collaboratorInfo ); const clientId = user.clientId; const color = user.isMe ? "var(--wp-admin-theme-color)" : getAvatarBorderColor( user.collaboratorInfo.id ?? user.clientId ); const avatarUrl = getAvatarUrl(user.collaboratorInfo.avatar_urls); const selectionVisual = computeSelectionVisual( selection, start, end, overlayContext ); const hasCoords = Boolean(selectionVisual.coords); const hasRects = (selectionVisual.selectionRects?.length ?? 0) > 0; if (hasCoords || hasRects) { const cursorData = { userName, clientId, color, avatarUrl, isMe: user.isMe, ...selectionVisual.coords ?? {} }; if (selectionVisual.selectionRects) { cursorData.selectionRects = selectionVisual.selectionRects; } results.push(cursorData); } }); setCursorPositions(results); }, [ blockEditorDocument, resolveSelection, overlayElement, sortedUsers, showOwnCursor, recomputeToken, resizeToken ]); return { cursors: cursorPositions, rerenderCursorsAfterDelay, rerenderCursorsOnResize }; } export { useRenderCursors }; //# sourceMappingURL=use-render-cursors.mjs.map