Components
Cursor Overlay
Cursor Overlay
Overlay a cursor indicator for collaborative editing or real-time interaction.
Installation
npx @udecode/plate-ui@latest add cursor-overlay
Examples
Cursor Overlay
Try to drag over text: you will see a black cursor on the drop target: color and other styles are customizable!
'use client';
import React, { useRef } from 'react';
import { cn } from '@udecode/cn';
import { CommentsProvider } from '@udecode/plate-comments';
import { Plate } from '@udecode/plate-common';
import { ELEMENT_PARAGRAPH } from '@udecode/plate-paragraph';
import { DndProvider } from 'react-dnd';
import { HTML5Backend } from 'react-dnd-html5-backend';
import { commentsUsers, myUserId } from '@/lib/plate/comments';
import { MENTIONABLES } from '@/lib/plate/mentionables';
import { plugins } from '@/lib/plate/plate-plugins';
import { CommentsPopover } from '@/components/plate-ui/comments-popover';
import { CursorOverlay } from '@/components/plate-ui/cursor-overlay';
import { Editor } from '@/components/plate-ui/editor';
import { FixedToolbar } from '@/components/plate-ui/fixed-toolbar';
import { FixedToolbarButtons } from '@/components/plate-ui/fixed-toolbar-buttons';
import { FloatingToolbar } from '@/components/plate-ui/floating-toolbar';
import { FloatingToolbarButtons } from '@/components/plate-ui/floating-toolbar-buttons';
import { MentionCombobox } from '@/components/plate-ui/mention-combobox';
export default function PlateEditor() {
const containerRef = useRef(null);
const initialValue = [
{
id: '1',
type: ELEMENT_PARAGRAPH,
children: [{ text: 'Hello, World!' }],
},
];
return (
<DndProvider backend={HTML5Backend}>
<CommentsProvider users={commentsUsers} myUserId={myUserId}>
<Plate plugins={plugins} initialValue={initialValue}>
<div
ref={containerRef}
className={cn(
// Block selection
'[&_.slate-start-area-left]:!w-[64px] [&_.slate-start-area-right]:!w-[64px] [&_.slate-start-area-top]:!h-4'
)}
>
<FixedToolbar>
<FixedToolbarButtons />
</FixedToolbar>
<Editor
className="px-[96px] py-16"
autoFocus
focusRing={false}
variant="ghost"
size="md"
/>
<FloatingToolbar>
<FloatingToolbarButtons />
</FloatingToolbar>
<MentionCombobox items={MENTIONABLES} />
<CommentsPopover />
<CursorOverlay containerRef={containerRef} />
</div>
</Plate>
</CommentsProvider>
</DndProvider>
);
}
API
CursorOverlay
useCursorOverlayPositions
Types
export type SelectionRect = {
width: number;
height: number;
top: number;
left: number;
};
export type CaretPosition = {
height: number;
top: number;
left: number;
};
export type CursorState<TCursorData extends UnknownObject = UnknownObject> = {
key?: any;
selection: Range | null;
data?: TCursorData;
};
export interface CursorOverlayState<TCursorData extends Record<string, unknown>>
extends CursorState<TCursorData> {
caretPosition: CaretPosition | null;
selectionRects: SelectionRect[];
}
export type CursorData = {
style?: CSSProperties;
selectionStyle?: CSSProperties;
};