UNPKG

realtimecursor

Version:

Real-time collaboration system with cursor tracking and approval workflow

380 lines (299 loc) 9.79 kB
# RealtimeCursor SDK Documentation Welcome to the RealtimeCursor SDK documentation. This guide will help you integrate real-time cursor tracking and collaborative editing into your application. ## Table of Contents - [Installation](#installation) - [Quick Start](#quick-start) - [API Reference](#api-reference) - [React Integration](#react-integration) - [Vanilla JavaScript Integration](#vanilla-javascript-integration) - [Advanced Usage](#advanced-usage) - [Troubleshooting](#troubleshooting) ## Installation ### npm ```bash npm install realtimecursor-sdk ``` ### CDN ```html <script src="https://cdn.realtimecursor.com/realtimecursor.min.js"></script> <link rel="stylesheet" href="https://cdn.realtimecursor.com/realtimecursor.min.css"> ``` ## Quick Start ### 1. Get an API Key Sign up at [realtimecursor.com](https://realtimecursor.com) to get an API key. ### 2. Initialize the SDK ```javascript // Initialize the cursor client const cursorClient = new RealtimeCursor({ apiUrl: 'https://api.realtimecursor.com', apiKey: 'your-api-key', projectId: 'your-project-id', user: { id: 'user-123', name: 'John Doe', color: '#3b82f6' // Optional } }); // Connect to the real-time service cursorClient.connect(); ``` ### 3. Track Cursor Movement ```javascript // Update cursor position on mouse move document.addEventListener('mousemove', (e) => { cursorClient.updateCursor({ x: e.clientX, y: e.clientY }); }); ``` ### 4. Track Content Changes ```javascript // Update content on change editor.addEventListener('input', (e) => { cursorClient.updateContent(e.target.value); }); ``` ### 5. Handle Events ```javascript // Handle cursor updates from other users cursorClient.onCursorUpdate = (data) => { const { socketId, user, x, y } = data; // Update cursor UI }; // Handle content updates from other users cursorClient.onContentUpdate = (data) => { const { content, user } = data; // Update editor content }; // Handle user presence cursorClient.onCollaboratorsChange = (collaborators) => { // Update collaborators list }; // Handle typing indicators cursorClient.onTypingStatusChange = (typingUserIds) => { // Update typing indicators }; ``` ## API Reference ### RealtimeCursor #### Constructor ```javascript const cursorClient = new RealtimeCursor(options); ``` **Options:** - `apiUrl` (string): The URL of the RealtimeCursor API server - `apiKey` (string): Your API key - `projectId` (string): The ID of the project - `user` (object): Information about the current user - `id` (string): The user's ID - `name` (string): The user's name - `color` (string, optional): The user's color (hex code) #### Methods - `connect()`: Connect to the real-time service - `disconnect()`: Disconnect from the real-time service - `updateCursor(position)`: Update the cursor position - `position` (object): - `x` (number): The x-coordinate of the cursor - `y` (number): The y-coordinate of the cursor - `textPosition` (number, optional): The position in the text - `updateContent(content, cursorPosition)`: Update the content - `content` (string): The new content - `cursorPosition` (number, optional): The position of the cursor in the text - `setTyping(isTyping)`: Set the typing status - `isTyping` (boolean): Whether the user is typing #### Events - `onCursorUpdate`: Called when a cursor is updated - `onContentUpdate`: Called when content is updated - `onCollaboratorsChange`: Called when the list of collaborators changes - `onTypingStatusChange`: Called when a user's typing status changes - `onUserJoined`: Called when a user joins - `onUserLeft`: Called when a user leaves ## React Integration ### Using the useRealtimeCursor Hook ```jsx import React, { useState, useRef } from 'react'; import { useRealtimeCursor, CursorOverlay } from 'realtimecursor-sdk'; import 'realtimecursor-sdk/dist/cursor.css'; function CollaborativeEditor() { const [content, setContent] = useState(''); const editorRef = useRef(null); const { cursors, updateCursor, updateContent, collaborators } = useRealtimeCursor({ apiUrl: 'https://api.realtimecursor.com', apiKey: 'your-api-key', projectId: 'your-project-id', user: { id: 'user-123', name: 'John Doe' } }); const handleMouseMove = (e) => { if (!editorRef.current) return; updateCursor({ x: e.clientX, y: e.clientY, textPosition: editorRef.current.selectionStart }); }; const handleChange = (e) => { const newContent = e.target.value; setContent(newContent); updateContent(newContent, e.target.selectionStart); }; return ( <div className="editor-container"> <div className="collaborators"> {collaborators.map(user => ( <div key={user.id} className="collaborator"> {user.name} </div> ))} </div> <textarea ref={editorRef} value={content} onChange={handleChange} onMouseMove={handleMouseMove} className="editor" /> <CursorOverlay cursors={cursors} content={content} editorRef={editorRef} /> </div> ); } ``` ## Vanilla JavaScript Integration ```javascript import { RealtimeCursor } from 'realtimecursor-sdk'; import 'realtimecursor-sdk/dist/cursor.css'; // Initialize the cursor client const cursorClient = new RealtimeCursor({ apiUrl: 'https://api.realtimecursor.com', apiKey: 'your-api-key', projectId: 'your-project-id', user: { id: 'user-123', name: 'John Doe' } }); // Connect to the real-time service cursorClient.connect(); // Set up event handlers cursorClient.onCursorUpdate = ({ socketId, user, x, y }) => { // Render cursor for this user renderCursor(socketId, user, x, y); }; cursorClient.onContentUpdate = ({ content }) => { // Update editor content document.getElementById('editor').value = content; }; // Update cursor position on mouse move document.getElementById('editor').addEventListener('mousemove', (e) => { cursorClient.updateCursor({ x: e.clientX, y: e.clientY }); }); // Update content on change document.getElementById('editor').addEventListener('input', (e) => { cursorClient.updateContent(e.target.value); }); // Helper function to render cursors function renderCursor(socketId, user, x, y) { let cursorElement = document.getElementById(`cursor-${socketId}`); if (!cursorElement) { cursorElement = document.createElement('div'); cursorElement.id = `cursor-${socketId}`; cursorElement.className = 'realtimecursor-cursor'; cursorElement.innerHTML = ` <div class="realtimecursor-pointer" style="background-color: ${user.color};"></div> <div class="realtimecursor-name" style="background-color: ${user.color};">${user.name}</div> `; document.body.appendChild(cursorElement); } cursorElement.style.position = 'fixed'; cursorElement.style.left = `${x}px`; cursorElement.style.top = `${y}px`; cursorElement.style.transform = 'translate(-50%, -50%)'; cursorElement.style.zIndex = '9999'; cursorElement.style.pointerEvents = 'none'; } ``` ## Advanced Usage ### Custom Cursor Rendering ```javascript cursorClient.onCursorUpdate = ({ socketId, user, x, y }) => { // Custom cursor rendering let cursorElement = document.getElementById(`cursor-${socketId}`); if (!cursorElement) { cursorElement = document.createElement('div'); cursorElement.id = `cursor-${socketId}`; cursorElement.className = 'custom-cursor'; // Create avatar const avatar = document.createElement('div'); avatar.className = 'custom-cursor-avatar'; avatar.style.backgroundColor = user.color || '#3b82f6'; avatar.textContent = user.name.charAt(0); // Create name tag const nameTag = document.createElement('div'); nameTag.className = 'custom-cursor-name'; nameTag.textContent = user.name; cursorElement.appendChild(avatar); cursorElement.appendChild(nameTag); document.body.appendChild(cursorElement); } cursorElement.style.left = `${x}px`; cursorElement.style.top = `${y}px`; }; ``` ### Typing Indicators ```javascript // Set typing status let typingTimeout; editor.addEventListener('keydown', () => { cursorClient.setTyping(true); clearTimeout(typingTimeout); typingTimeout = setTimeout(() => { cursorClient.setTyping(false); }, 1000); }); // Handle typing status changes cursorClient.onTypingStatusChange = (typingUserIds) => { document.querySelectorAll('.collaborator').forEach(el => { const socketId = el.dataset.socketId; const typingIndicator = el.querySelector('.typing-indicator'); if (typingUserIds.includes(socketId)) { typingIndicator.style.display = 'inline'; } else { typingIndicator.style.display = 'none'; } }); }; ``` ## Troubleshooting ### Connection Issues If you're having trouble connecting to the RealtimeCursor service: 1. Check that your API key is valid 2. Ensure your project ID is correct 3. Check that the API URL is correct 4. Verify that your user object has the required fields ### Cursor Not Showing If cursors are not showing: 1. Make sure you've included the CSS file 2. Check that the cursor update events are being triggered 3. Verify that the cursor elements are being created in the DOM ### Content Not Syncing If content is not syncing: 1. Check that the content update events are being triggered 2. Verify that the content is being sent to the server 3. Check that the content update handler is updating the editor ## Support If you need help, please contact us at support@realtimecursor.com or visit our [support page](https://realtimecursor.com/support).