UNPKG

realtimecursor

Version:

Real-time collaboration system with cursor tracking and approval workflow

253 lines (210 loc) 6.16 kB
# RealtimeCursor A lightweight library for real-time cursor tracking and collaboration in web applications. ## Features - 🖱️ Real-time cursor tracking - 👥 Collaborator presence - 📝 Content synchronization - ⌨️ Typing indicators - 🔄 Automatic reconnection - 🎨 Customizable cursors and colors ## Installation ```bash npm install realtimecursor # or yarn add realtimecursor ``` ## Usage ### Basic Usage ```javascript import { RealtimeCursor } from 'realtimecursor'; // Initialize the cursor client const cursor = new RealtimeCursor({ projectId: 'your-project-id', user: { id: 'user-123', name: 'John Doe', color: '#3b82f6' } }); // Connect to the real-time service cursor.connect(); // Set up event handlers cursor.on('connect', () => { console.log('Connected to real-time service'); }); cursor.on('collaborators-changed', (collaborators) => { console.log('Active collaborators:', collaborators); }); cursor.on('cursors-changed', (cursors) => { console.log('Cursor positions:', cursors); }); // Update cursor position document.addEventListener('mousemove', (e) => { const editorElement = document.getElementById('editor'); const rect = editorElement.getBoundingClientRect(); cursor.updateCursor({ x: e.clientX, y: e.clientY, relativeX: e.clientX - rect.left, relativeY: e.clientY - rect.top }); }); // Update content document.getElementById('editor').addEventListener('input', (e) => { cursor.updateContent(e.target.value); cursor.updateTypingStatus(true); // Reset typing status after 2 seconds setTimeout(() => { cursor.updateTypingStatus(false); }, 2000); }); // Disconnect when done window.addEventListener('beforeunload', () => { cursor.disconnect(); }); ``` ### React Hook ```jsx import React, { useState, useRef, useEffect } from 'react'; import { useRealtimeCursor } from 'realtimecursor'; function CollaborativeEditor() { const [content, setContent] = useState(''); const editorRef = useRef(null); const { cursors, collaborators, connected, typingStatus, connect, disconnect, updateCursor, updateContent, updateTypingStatus } = useRealtimeCursor({ projectId: 'your-project-id', user: { id: 'user-123', name: 'John Doe', color: '#3b82f6' } }); // Connect on mount useEffect(() => { connect(); return () => disconnect(); }, [connect, disconnect]); // Update cursor position on mouse move const handleMouseMove = (e) => { if (!editorRef.current) return; const rect = editorRef.current.getBoundingClientRect(); updateCursor({ x: e.clientX, y: e.clientY, relativeX: e.clientX - rect.left, relativeY: e.clientY - rect.top }); }; // Update content when changed const handleContentChange = (e) => { const newContent = e.target.value; setContent(newContent); updateContent(newContent); updateTypingStatus(true); // Reset typing status after 2 seconds setTimeout(() => updateTypingStatus(false), 2000); }; return ( <div> <div>Connection status: {connected ? 'Connected' : 'Disconnected'}</div> <div>Active collaborators: {collaborators.length}</div> <div ref={editorRef} onMouseMove={handleMouseMove} style={{ position: 'relative' }} > <textarea value={content} onChange={handleContentChange} placeholder="Start typing..." /> {/* Render cursors */} {Object.values(cursors).map(cursor => ( <div key={cursor.id} style={{ position: 'absolute', left: cursor.position.x || cursor.position.relativeX || 0, top: cursor.position.y || cursor.position.relativeY || 0, pointerEvents: 'none' }} > <div style={{ backgroundColor: cursor.user.color || '#3b82f6', padding: '2px 6px', borderRadius: '4px', color: 'white', fontSize: '12px' }} > {cursor.user.name} {typingStatus[cursor.id]?.isTyping && ' (typing...)'} </div> </div> ))} </div> </div> ); } ``` ## API Reference ### RealtimeCursor ```typescript const cursor = new RealtimeCursor(options); ``` #### Options - `apiUrl` (string): URL of the RealtimeCursor API server (defaults to hosted service) - `projectId` (string): Unique identifier for the project - `user` (object): User information - `id` (string): Unique identifier for the user - `name` (string): Display name for the user - `color` (string, optional): Color for the user's cursor (hex code) - `debug` (boolean, optional): Enable debug logging #### Methods - `connect()`: Connect to the real-time service - `disconnect()`: Disconnect from the real-time service - `updateCursor(position)`: Update cursor position - `updateContent(content)`: Update content - `updateTypingStatus(isTyping)`: Update typing status - `on(event, callback)`: Add event listener - `off(event, callback)`: Remove event listener - `getCollaborators()`: Get all collaborators - `getCursors()`: Get all cursors - `getTypingStatus()`: Get typing status - `isConnected()`: Get connection status #### Events - `connect`: Emitted when connected to the service - `disconnect`: Emitted when disconnected from the service - `cursors-changed`: Emitted when cursors are updated - `collaborators-changed`: Emitted when collaborators list changes - `typing-status-changed`: Emitted when typing status changes - `content-updated`: Emitted when content is updated by another user - `user-joined`: Emitted when a user joins - `user-left`: Emitted when a user leaves - `error`: Emitted when an error occurs ### useRealtimeCursor Hook ```typescript const { cursors, collaborators, connected, typingStatus, connect, disconnect, updateCursor, updateContent, updateTypingStatus } = useRealtimeCursor(options); ``` ## License MIT