{
  "version": 3,
  "sources": ["../../../src/components/collaborators-overlay/use-render-cursors.ts"],
  "sourcesContent": ["import { privateApis as coreDataPrivateApis } from '@wordpress/core-data';\nimport type {\n\tCoreDataPrivateApis,\n\tResolvedSelection,\n\tSelectionEndpoint,\n\tPostEditorAwarenessState as ActiveCollaborator,\n} from '@wordpress/core-data';\nimport { useSelect } from '@wordpress/data';\nimport { useEffect, useState } from '@wordpress/element';\nimport { store as preferencesStore } from '@wordpress/preferences';\nimport { unlock } from '../../lock-unlock';\nimport { getAvatarUrl } from './get-avatar-url';\nimport { getAvatarBorderColor } from '../collab-sidebar/utils';\nimport { computeSelectionVisual } from './compute-selection';\nimport {\n\tuseDebouncedRecompute,\n\tuseRequestAnimationFrameRecompute,\n} from './use-debounced-recompute';\nimport { blockContainerOf } from './cursor-dom-utils';\nimport type { SelectionRect } from './cursor-dom-utils';\nimport { getCollaboratorDisplayName } from '../../utils/get-collaborator-display-name';\n\nconst { useActiveCollaborators, useResolvedSelection } =\n\tunlock( coreDataPrivateApis );\nconst { SelectionType } = unlock( coreDataPrivateApis ) as Pick<\n\tCoreDataPrivateApis,\n\t'SelectionType'\n>;\n\nexport type { SelectionRect };\n\nexport interface CursorData {\n\tuserName: string;\n\tclientId: number;\n\tcolor: string;\n\tavatarUrl?: string;\n\t// x/y/height absent for multi-block selections — avatar comes from\n\t// use-block-highlighting; only selectionRects are rendered here.\n\tx?: number;\n\ty?: number;\n\theight?: number;\n\tisMe?: boolean;\n\tselectionRects?: SelectionRect[];\n}\n\n/**\n * Custom hook that computes cursor positions for each remote user in the editor.\n *\n * @param overlayElement      - The overlay element\n * @param blockEditorDocument - The block editor document\n * @param postId              - The ID of the post\n * @param postType            - The type of the post\n * @param delayMs             - Milliseconds to wait before recomputing cursor positions.\n * @return An array of cursor data for rendering, and a function to trigger a delayed recompute.\n */\nexport function useRenderCursors(\n\toverlayElement: HTMLElement | null,\n\tblockEditorDocument: Document | null,\n\tpostId: number | null,\n\tpostType: string | null,\n\tdelayMs: number\n): {\n\tcursors: CursorData[];\n\trerenderCursorsAfterDelay: () => () => void;\n\trerenderCursorsOnResize: () => void;\n} {\n\tconst sortedUsers = useActiveCollaborators(\n\t\tpostId ?? null,\n\t\tpostType ?? null\n\t);\n\tconst resolveSelection = useResolvedSelection(\n\t\tpostId ?? null,\n\t\tpostType ?? null\n\t);\n\n\tconst showOwnCursor = useSelect(\n\t\t( select ) =>\n\t\t\tselect( preferencesStore ).get( 'core', 'showCollaborationCursor' ),\n\t\t[]\n\t);\n\n\tconst [ cursorPositions, setCursorPositions ] = useState< CursorData[] >(\n\t\t[]\n\t);\n\n\t// Bump this counter to force the effect to re-run (e.g. after a layout shift).\n\tconst [ recomputeToken, rerenderCursorsAfterDelay ] =\n\t\tuseDebouncedRecompute( delayMs );\n\t// Separate token for resize events: fires on the next animation frame so\n\t// getBoundingClientRect() reflects the post-resize layout immediately.\n\tconst [ resizeToken, rerenderCursorsOnResize ] =\n\t\tuseRequestAnimationFrameRecompute();\n\n\t// All DOM position computations live inside useEffect.\n\tuseEffect( () => {\n\t\tif ( ! overlayElement || ! blockEditorDocument ) {\n\t\t\tsetCursorPositions( [] );\n\t\t\treturn;\n\t\t}\n\n\t\t// Pre-compute the overlay rect once, same for every user.\n\t\tconst overlayRect = overlayElement.getBoundingClientRect();\n\t\tconst overlayContext = {\n\t\t\teditorDocument: blockEditorDocument,\n\t\t\toverlayRect,\n\t\t};\n\n\t\tconst results: CursorData[] = [];\n\n\t\tconst hasOtherCollaborators = sortedUsers.some(\n\t\t\t( u: ActiveCollaborator ) => ! u.isMe\n\t\t);\n\n\t\tsortedUsers.forEach( ( user: ActiveCollaborator ) => {\n\t\t\tif ( user.isMe && ( ! showOwnCursor || ! hasOtherCollaborators ) ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst selection = user.editorState?.selection ?? {\n\t\t\t\ttype: SelectionType.None,\n\t\t\t};\n\n\t\t\tlet start: ResolvedSelection = {\n\t\t\t\trichTextOffset: null,\n\t\t\t\tlocalClientId: null,\n\t\t\t\tattributeKey: null,\n\t\t\t};\n\t\t\tlet end: ResolvedSelection | undefined;\n\n\t\t\tif ( selection.type === SelectionType.Cursor ) {\n\t\t\t\ttry {\n\t\t\t\t\tstart = resolveSelection( selection );\n\t\t\t\t} catch {\n\t\t\t\t\t// Selection may reference a stale Yjs position.\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t} else if ( selection.type === SelectionType.SelectionInOneBlock ) {\n\t\t\t\ttry {\n\t\t\t\t\tstart = resolveSelection( {\n\t\t\t\t\t\ttype: SelectionType.Cursor,\n\t\t\t\t\t\tcursorPosition: selection.cursorStartPosition,\n\t\t\t\t\t} );\n\t\t\t\t\tend = resolveSelection( {\n\t\t\t\t\t\ttype: SelectionType.Cursor,\n\t\t\t\t\t\tcursorPosition: selection.cursorEndPosition,\n\t\t\t\t\t} );\n\t\t\t\t} catch {\n\t\t\t\t\t// Selection may reference a stale Yjs position.\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t} else if (\n\t\t\t\tselection.type === SelectionType.SelectionInMultipleBlocks\n\t\t\t) {\n\t\t\t\t// Each endpoint is either a CursorEndpoint (character offset\n\t\t\t\t// inside a RichText field) or a WholeBlockEndpoint (block selected\n\t\t\t\t// as a unit, no character offset). Resolve independently so each\n\t\t\t\t// end uses the right Yjs anchor regardless of block type.\n\t\t\t\tconst resolveEndpoint = (\n\t\t\t\t\tendpoint: SelectionEndpoint\n\t\t\t\t): ResolvedSelection => resolveSelection( endpoint );\n\t\t\t\ttry {\n\t\t\t\t\tstart = resolveEndpoint( selection.startEndpoint );\n\t\t\t\t\tend = resolveEndpoint( selection.endEndpoint );\n\t\t\t\t} catch {\n\t\t\t\t\t// Selection may reference a stale Yjs position.\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\t// Promote inner-block endpoints (e.g. list-items → list) to\n\t\t\t\t// their direct [data-block] parent before passing to\n\t\t\t\t// computeSelectionVisual, so that function receives\n\t\t\t\t// container-level IDs and needs no promotion logic of its own.\n\t\t\t\tconst promote = ( r: ResolvedSelection ): ResolvedSelection => {\n\t\t\t\t\tif ( ! r.localClientId ) {\n\t\t\t\t\t\treturn r;\n\t\t\t\t\t}\n\t\t\t\t\tconst el = blockEditorDocument.querySelector< HTMLElement >(\n\t\t\t\t\t\t`[data-block=\"${ r.localClientId }\"]`\n\t\t\t\t\t);\n\t\t\t\t\tif ( ! el ) {\n\t\t\t\t\t\treturn r;\n\t\t\t\t\t}\n\t\t\t\t\tconst container = blockContainerOf( el );\n\t\t\t\t\tconst containerId = container.getAttribute( 'data-block' );\n\t\t\t\t\tif ( ! containerId || containerId === r.localClientId ) {\n\t\t\t\t\t\treturn r;\n\t\t\t\t\t}\n\t\t\t\t\treturn {\n\t\t\t\t\t\t...r,\n\t\t\t\t\t\tlocalClientId: containerId,\n\t\t\t\t\t\trichTextOffset: null,\n\t\t\t\t\t\tattributeKey: null,\n\t\t\t\t\t};\n\t\t\t\t};\n\t\t\t\tstart = promote( start );\n\t\t\t\tif ( end ) {\n\t\t\t\t\tend = promote( end );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst userName = getCollaboratorDisplayName(\n\t\t\t\tuser.collaboratorInfo\n\t\t\t);\n\t\t\tconst clientId = user.clientId;\n\t\t\tconst color = user.isMe\n\t\t\t\t? 'var(--wp-admin-theme-color)'\n\t\t\t\t: getAvatarBorderColor(\n\t\t\t\t\t\tuser.collaboratorInfo.id ?? user.clientId\n\t\t\t\t  );\n\t\t\tconst avatarUrl = getAvatarUrl( user.collaboratorInfo.avatar_urls );\n\n\t\t\tconst selectionVisual = computeSelectionVisual(\n\t\t\t\tselection,\n\t\t\t\tstart,\n\t\t\t\tend,\n\t\t\t\toverlayContext\n\t\t\t);\n\n\t\t\tconst hasCoords = Boolean( selectionVisual.coords );\n\t\t\tconst hasRects =\n\t\t\t\t( selectionVisual.selectionRects?.length ?? 0 ) > 0;\n\t\t\tif ( hasCoords || hasRects ) {\n\t\t\t\tconst cursorData: CursorData = {\n\t\t\t\t\tuserName,\n\t\t\t\t\tclientId,\n\t\t\t\t\tcolor,\n\t\t\t\t\tavatarUrl,\n\t\t\t\t\tisMe: user.isMe,\n\t\t\t\t\t...( selectionVisual.coords ?? {} ),\n\t\t\t\t};\n\t\t\t\tif ( selectionVisual.selectionRects ) {\n\t\t\t\t\tcursorData.selectionRects = selectionVisual.selectionRects;\n\t\t\t\t}\n\t\t\t\tresults.push( cursorData );\n\t\t\t}\n\t\t} );\n\n\t\tsetCursorPositions( results );\n\t}, [\n\t\tblockEditorDocument,\n\t\tresolveSelection,\n\t\toverlayElement,\n\t\tsortedUsers,\n\t\tshowOwnCursor,\n\t\trecomputeToken,\n\t\tresizeToken,\n\t] );\n\n\treturn {\n\t\tcursors: cursorPositions,\n\t\trerenderCursorsAfterDelay,\n\t\trerenderCursorsOnResize,\n\t};\n}\n"],
  "mappings": "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",
  "names": ["coreDataPrivateApis", "preferencesStore"]
}
