UNPKG

realtimecursor

Version:

Real-time collaboration system with cursor tracking and approval workflow

140 lines (124 loc) 4.28 kB
import React, { useState, useRef, useEffect } from 'react'; import { useRealtimeCursor, CursorOverlay, CollaboratorsList } from 'realtimecursor-sdk-fixed'; import 'realtimecursor-sdk-fixed/dist/cursor.css'; function App() { const [content, setContent] = useState('# Welcome to RealtimeCursor Demo\n\nThis is a collaborative editor using the fixed RealtimeCursor SDK.\n\nTry opening this page in multiple browser windows to see real-time collaboration in action!\n\n1. Your cursor position will be shared with others\n2. Content changes will be synchronized\n3. You\'ll see who else is editing this document'); const [userId, setUserId] = useState(`user-${Math.floor(Math.random() * 10000)}`); const [userName, setUserName] = useState(`User ${Math.floor(Math.random() * 10000)}`); const [userColor, setUserColor] = useState(getRandomColor()); const editorRef = useRef(null); const { cursors, collaborators, connected, connect, disconnect, updateCursor, updateContent } = useRealtimeCursor({ apiUrl: 'http://localhost:3001', projectId: 'demo-project', user: { id: userId, name: userName, color: userColor } }); // Connect on mount useEffect(() => { connect(); return () => disconnect(); }, [connect, disconnect, userId, userName, userColor]); // 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); }; // Update user info const handleUserUpdate = (e) => { e.preventDefault(); // Disconnect and reconnect with new user info disconnect(); setTimeout(() => connect(), 100); }; // Generate random color function getRandomColor() { const colors = [ '#3b82f6', // blue '#ef4444', // red '#10b981', // green '#f59e0b', // yellow '#8b5cf6', // purple '#ec4899', // pink '#06b6d4', // cyan '#f97316', // orange ]; return colors[Math.floor(Math.random() * colors.length)]; } return ( <div className="app"> <div className="header"> <h1>RealtimeCursor Demo</h1> <p>Fixed version (v1.1.0) with improved stability and performance</p> </div> <div className="user-info"> <h2>Your Information</h2> <form className="user-form" onSubmit={handleUserUpdate}> <input type="text" value={userName} onChange={(e) => setUserName(e.target.value)} placeholder="Your name" /> <input type="color" value={userColor} onChange={(e) => setUserColor(e.target.value)} title="Choose your cursor color" /> <button type="submit">Update</button> </form> <div className="connection-status"> <div className={`status-indicator ${connected ? 'connected' : 'disconnected'}`}></div> <div className="status-text"> {connected ? 'Connected' : 'Disconnected'} </div> </div> </div> <div className="editor-container" ref={editorRef} onMouseMove={handleMouseMove}> <textarea className="editor" value={content} onChange={handleContentChange} placeholder="Start typing..." /> <CursorOverlay cursors={cursors} /> </div> <div className="collaborators-panel"> <h2>Active Collaborators ({collaborators.length})</h2> <CollaboratorsList collaborators={collaborators} /> </div> <div className="footer"> <p> RealtimeCursor SDK - Fixed Version (v1.1.0) | <a href="https://github.com/yourusername/realtimecursor" target="_blank" rel="noopener noreferrer"> GitHub </a> </p> </div> </div> ); } export default App;