import { ReactElement } from 'react'; import * as Y from 'yjs'; import { Awareness } from 'y-protocols/awareness'; /** * Collab types — wire-protocol shapes for the workbook CRDT layer (v2). * * See `FEATURE.md` in this directory for the full integration plan. * * V1 of the workbook surface uses snapshot-per-save persistence and is * intentionally NOT collaborative beyond hot-swap on remote snapshot. * V2 layers Yjs CRDT updates over Supabase Broadcast on top of that store — * the snapshot table stays the canonical state, Broadcast handles the * ephemeral causal log between active editors. * * Nothing in this file imports `yjs` so that consumers (e.g. snapshot * tooling) can pull the types without dragging the CRDT lib into the bundle. * The `Y.Doc` / `Awareness` references in JSDoc point at the types provided * by `yjs` and `y-protocols/awareness` once those deps land. */ /** Per-peer presence payload. ~80 bytes JSON. */ type AwarenessState = { /** Stable user id (matches auth.uid). */ uid: string; /** Display name as shown next to the cursor. */ name: string; /** Cursor color (hex, e.g. "#3b82f6"). Derived deterministically from uid. */ color: string; /** Univer sheet the cursor is currently focused on. */ sheetId: string | null; /** Cursor row index, 0-based. */ row: number | null; /** Cursor column index, 0-based. */ col: number | null; /** Last-update ms timestamp. Used to age out stale cursors. */ ts: number; }; /** * openCollabSession — one co-editing room: a Y.Doc, its Awareness, the * Supabase-Broadcast provider on the app's ONE RealtimeManager, and the saver * election (election.ts, frozen as the editors ran it). "Exactly one peer per * session saves" is `isSaver()`. */ interface CollabSession { doc: Y.Doc; awareness: Awareness; /** Exactly one peer per session saves. */ isSaver(): boolean; onSaverChange(cb: (isSaver: boolean) => void): () => void; destroy(): void; } /** * `@ai-matrx/realtime/collab/react` — what a collab surface draws. * - RemoteCursorsLayer: one caret box per remote peer, positioned by the host editor's `mapPosition`. * - RemotePeerChips: the "who is here" strip (moved from matrx-frontend `lib/collab/RemoteCursorsLayer`). * Inline styles only: the package ships no stylesheet. */ declare function RemoteCursorsLayer(props: { session: CollabSession; /** Editor position payload (`awareness.cursor`) to a rect in this layer's coordinate space; null hides it. */ mapPosition: (p: unknown) => DOMRect | null; }): ReactElement; declare function RemotePeerChips({ states, selfUid }: { states: Map; selfUid: string; }): ReactElement | null; export { RemoteCursorsLayer, RemotePeerChips };