UNPKG

realtimecursor

Version:

Real-time collaboration system with cursor tracking and approval workflow

347 lines (284 loc) 9.38 kB
# RealtimeCursor Enhanced SDK A user-friendly SDK for real-time cursor tracking and collaboration features. ## Features - 🖱️ Real-time cursor tracking - 👥 Collaborator presence - 📝 Content synchronization - ⌨️ Typing indicators - 🔄 Automatic reconnection - 🎨 Customizable cursors and colors - ⚛️ Ready-to-use React components - 🌐 Vanilla JavaScript support ## Installation ```bash npm install realtimecursor-enhanced # or yarn add realtimecursor-enhanced ``` ## Quick Start ### Option 1: Ready-to-use Collaborative Editor The fastest way to add real-time collaboration to your app: ```jsx import React from 'react'; import { CollaborativeEditor } from 'realtimecursor-enhanced'; import 'realtimecursor-enhanced/dist/cursor.css'; function MyEditor() { return ( <CollaborativeEditor apiUrl="http://localhost:3001" projectId="my-project" userId="user-123" userName="John Doe" initialContent="Start collaborating!" onContentChange={(content) => console.log('Content changed:', content)} height="400px" /> ); } ``` ### Option 2: Using the React Hook For more control over the UI: ```jsx import React, { useState, useRef, useEffect } from 'react'; import { useRealtimeCursor, CursorOverlay, CollaboratorsList } from 'realtimecursor-enhanced'; import 'realtimecursor-enhanced/dist/cursor.css'; function CustomEditor() { const [content, setContent] = useState(''); const editorRef = useRef(null); const { cursors, collaborators, connected, typingStatus, connect, disconnect, updateCursor, updateContent, updateTypingStatus } = useRealtimeCursor({ apiUrl: 'http://localhost:3001', projectId: 'my-project', 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 and typing status 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 className="connection-status"> {connected ? 'Connected' : 'Disconnected'} </div> <div className="editor-container" ref={editorRef} onMouseMove={handleMouseMove}> <textarea value={content} onChange={handleContentChange} placeholder="Start typing..." /> <CursorOverlay cursors={cursors} /> </div> <div className="collaborators-panel"> <h3>Active Collaborators ({collaborators.length})</h3> <CollaboratorsList collaborators={collaborators} typingStatus={typingStatus} /> </div> </div> ); } ``` ### Option 3: Vanilla JavaScript ```javascript import { RealtimeCursor } from 'realtimecursor-enhanced'; import 'realtimecursor-enhanced/dist/cursor.css'; // Initialize the cursor client const cursorClient = new RealtimeCursor({ apiUrl: 'http://localhost:3001', projectId: 'my-project', user: { id: 'user-123', name: 'John Doe', color: '#3b82f6' }, debug: true // Enable debug logging }); // Connect to the real-time service cursorClient.connect(); // Set up event handlers cursorClient.on('connected', () => { console.log('Connected to real-time service'); document.getElementById('status').textContent = 'Connected'; }); cursorClient.on('disconnected', () => { console.log('Disconnected from real-time service'); document.getElementById('status').textContent = 'Disconnected'; }); cursorClient.on('cursors-changed', (cursors) => { console.log('Cursors updated:', cursors); renderCursors(cursors); }); cursorClient.on('collaborators-changed', (collaborators) => { console.log('Collaborators updated:', collaborators); renderCollaborators(collaborators); }); cursorClient.on('typing-status-changed', (typingStatus) => { console.log('Typing status updated:', typingStatus); updateTypingIndicators(typingStatus); }); cursorClient.on('content-updated', (data) => { console.log('Content updated:', data); document.getElementById('editor').value = data.content; }); // Update cursor position on mouse move document.getElementById('editor-container').addEventListener('mousemove', (e) => { const rect = e.currentTarget.getBoundingClientRect(); cursorClient.updateCursor({ x: e.clientX, y: e.clientY, relativeX: e.clientX - rect.left, relativeY: e.clientY - rect.top }); }); // Update content and typing status when changed let typingTimeout; document.getElementById('editor').addEventListener('input', (e) => { cursorClient.updateContent(e.target.value); cursorClient.updateTypingStatus(true); // Reset typing status after 2 seconds clearTimeout(typingTimeout); typingTimeout = setTimeout(() => { cursorClient.updateTypingStatus(false); }, 2000); }); // Disconnect when the page is closed window.addEventListener('beforeunload', () => { cursorClient.disconnect(); }); // Helper functions for rendering (implement these based on your UI) function renderCursors(cursors) { /* ... */ } function renderCollaborators(collaborators) { /* ... */ } function updateTypingIndicators(typingStatus) { /* ... */ } ``` ## API Reference ### RealtimeCursor Class ```javascript const cursorClient = new RealtimeCursor(options); ``` #### Options - `apiUrl` (string): URL of the RealtimeCursor API server - `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 - `autoConnect` (boolean, optional): Automatically connect on initialization #### Methods - `connect()`: Connect to the real-time service - `disconnect()`: Disconnect from the real-time service - `updateCursor(position)`: Update cursor position - `position` (object): Cursor position - `x` (number, optional): Absolute X position - `y` (number, optional): Absolute Y position - `relativeX` (number, optional): Relative X position within container - `relativeY` (number, optional): Relative Y position within container - `textPosition` (number, optional): Position in text (for text editors) - `updateContent(content)`: Update content - `content` (string): New content - `updateTypingStatus(isTyping)`: Update typing status - `isTyping` (boolean): Whether the user is typing - `getCollaborators()`: Get all collaborators - `getCursors()`: Get all cursors - `getTypingStatus()`: Get typing status - `isConnected()`: Get connection status #### Events - `connected`: Emitted when connected to the service - `disconnected`: Emitted when disconnected from the service - `connection-error`: Emitted when a connection error occurs - `reconnect-attempt`: Emitted when attempting to reconnect - `reconnect-failed`: Emitted when reconnection fails - `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 ```javascript const { cursors, collaborators, connected, typingStatus, connect, disconnect, updateCursor, updateContent, updateTypingStatus } = useRealtimeCursor(options); ``` #### Returns - `cursors` (object): Map of cursor objects by user ID - `collaborators` (array): List of active collaborators - `connected` (boolean): Connection status - `typingStatus` (object): Map of typing status by user ID - `connect()`: Function to connect to the service - `disconnect()`: Function to disconnect from the service - `updateCursor(position)`: Function to update cursor position - `updateContent(content)`: Function to update content - `updateTypingStatus(isTyping)`: Function to update typing status ### React Components #### CursorOverlay ```jsx <CursorOverlay cursors={cursors} /> ``` #### CollaboratorsList ```jsx <CollaboratorsList collaborators={collaborators} typingStatus={typingStatus} /> ``` #### CollaborativeEditor ```jsx <CollaborativeEditor apiUrl="http://localhost:3001" projectId="my-project" userId="user-123" userName="John Doe" userColor="#3b82f6" initialContent="Start collaborating!" onContentChange={(content) => console.log('Content changed:', content)} height="400px" /> ``` ## Backend Server This SDK requires a backend server for real-time communication. The server is included in the package and can be started with: ```bash cd api npm install npm start ``` ## License MIT