@wordpress/editor
Version:
Enhanced block editor for WordPress posts.
168 lines (167 loc) • 5.4 kB
JavaScript
// 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