Skip to content

Collaborative Presence

HTMLRevoGridElement (Extended from @revolist/revogrid)

Section titled “HTMLRevoGridElement (Extended from @revolist/revogrid)”
interface HTMLRevoGridElement {
collaborativePresence?: CollaborativePresenceConfig;
'collaborative-presence'?: CollaborativePresenceConfig
}

AdditionalData (Extended from @revolist/revogrid)

Section titled “AdditionalData (Extended from @revolist/revogrid)”
interface AdditionalData {
collaborativePresence?: CollaborativePresenceConfig
}

Renders remote collaborator focus and range presence without mutating local grid focus, selection, data, or history.

  • Config integration additionalData.collaborativePresence: Reads remote collaborator presence from grid.collaborativePresence or additionalData.collaborativePresence.
  • Event integration afterrender: Refreshes visible remote focus and range markers after grid render updates.
class CollaborativePresencePlugin {
destroy();
}

export type CollaborativePresenceActivity = 'viewing' | 'editing' | 'idle';

interface CollaborativePresenceCellRef {
x: number;
y: number;
colType?: DimensionCols;
rowType?: DimensionRows
}

CollaborativePresenceRangeRef (Extended from index.ts)

Section titled “CollaborativePresenceRangeRef (Extended from index.ts)”
interface CollaborativePresenceRangeRef {
colType?: DimensionCols;
rowType?: DimensionRows
}

interface CollaborativePresenceUser {
id: string;
name: string;
initials?: string;
color?: string;
activity?: CollaborativePresenceActivity;
focus?: CollaborativePresenceCellRef | null;
range?: CollaborativePresenceRangeRef | null;
lastActiveAt?: number | string | Date
}

interface CollaborativePresenceRowPatch {
rowIndex: number;
data: Record<string, unknown>;
rowType?: DimensionRows
}

interface CollaborativePresenceConfig {
enabled?: boolean;
showLabels?: boolean;
staleAfterMs?: number;
users?: CollaborativePresenceUser[];
remoteEdits?: CollaborativePresenceRowPatch[]
}

interface ResolvedCollaborativePresenceConfig {
enabled: boolean;
showLabels: boolean;
staleAfterMs?: number;
users: CollaborativePresenceUser[];
remoteEdits: CollaborativePresenceRowPatch[]
}

interface CollaborativePresenceRect {
left: number;
top: number;
width: number;
height: number
}

interface CollaborativePresenceMarker {
kind: 'focus' | 'range';
user: CollaborativePresenceUser;
rect: CollaborativePresenceRect;
colType: DimensionCols;
rowType: DimensionRows
}

export function normalizeCollaborativePresenceCell(
cell: CollaborativePresenceCellRef,
): Required<CollaborativePresenceCellRef>;

export function normalizeCollaborativePresenceRange(
range: CollaborativePresenceRangeRef,
): Required<CollaborativePresenceRangeRef>;

export function resolveCollaborativePresenceConfig(
config?: CollaborativePresenceConfig,
): ResolvedCollaborativePresenceConfig;

export function getVisibleCollaborativePresenceUsers(
config: ResolvedCollaborativePresenceConfig,
now = Date.now(),
): CollaborativePresenceUser[];

export function resolveCollaborativePresenceMarkers(
_grid: HTMLElement,
users: CollaborativePresenceUser[],
providers?: PluginProviders,
): CollaborativePresenceMarker[];

Applies row patches directly into the RevoGrid data store without triggering a full source reset or plugin re-initialization.

rowIndex is treated as a source (physical) index — the position in the original data array — so patches always target the correct row regardless of the current sort or reorder state.

Per rowType:

  1. Mutate source[rowIndex] directly for each patch
  2. store.set(‘source’, […]) once — triggers a single targeted reactive update

Mirrors the low-level write pattern in spreadsheet.simulation.ts.

export function applyCollaborativePresenceRowPatches(
providers: PluginProviders,
patches: CollaborativePresenceRowPatch[],
): void;

Manages per-viewport slot overlay elements and draws presence markers into them. Each viewport type combination (colType × rowType) gets its own slot div so markers clip and scroll correctly within their viewport.

class CollaborativePresenceLayer {
render(markers: CollaborativePresenceMarker[], showLabels: boolean): void;
destroy(): void;
}

export function resolveCollaborativePresenceCellRect(
providers: PluginProviders | undefined,
cell: PresenceCell,
): CollaborativePresenceRect | undefined;

export function resolveCollaborativePresenceRangeRect(
providers: PluginProviders | undefined,
range: PresenceRange,
): CollaborativePresenceRect | undefined;