UNPKG

realtimecursor

Version:

Real-time collaboration system with cursor tracking and approval workflow

125 lines (110 loc) 3.58 kB
import React, { useState, useRef, useEffect } from 'react'; import { useRealtimeCursor, CursorOverlay } from 'realtimecursor-sdk-fixed'; import 'realtimecursor-sdk-fixed/dist/cursor.css'; import './App.css'; function App() { const [content, setContent] = useState('Welcome to RealtimeCursor React Example!\n\nTry opening this in multiple windows to see real-time collaboration.'); const editorRef = useRef(null); // Generate random user const userId = `user_${Math.random().toString(36).substring(2, 10)}`; const userName = `User ${Math.floor(Math.random() * 1000)}`; const colors = ['#3b82f6', '#ef4444', '#10b981', '#f59e0b', '#8b5cf6']; const userColor = colors[Math.floor(Math.random() * colors.length)]; // Initialize RealtimeCursor const { cursors, updateCursor, updateContent, collaborators, setTyping, connect, disconnect } = useRealtimeCursor({ apiUrl: 'http://localhost:3001', projectId: 'react-example', user: { id: userId, name: userName, color: userColor } }); // Connect on mount useEffect(() => { connect(); return () => disconnect(); }, [connect, disconnect]); // Handle mouse movement const handleMouseMove = (e) => { if (!editorRef.current) return; updateCursor({ x: e.clientX, y: e.clientY }); }; // Handle content changes const handleChange = (e) => { const newContent = e.target.value; setContent(newContent); updateContent(newContent); }; // Handle typing indicator let typingTimeoutRef = useRef(null); const handleKeyDown = () => { setTyping(true); clearTimeout(typingTimeoutRef.current); typingTimeoutRef.current = setTimeout(() => { setTyping(false); }, 1000); }; return ( <div className="app"> <header> <h1>RealtimeCursor React Example</h1> <p>Open this page in multiple browser windows to see real-time collaboration in action.</p> </header> <main> <div className="collaborators"> <h3>Current Users:</h3> <div className="collaborator-list"> <div className="collaborator"> <div className="avatar" style={{ backgroundColor: userColor }}> {userName.charAt(0)} </div> <span>{userName} (You)</span> </div> {collaborators.map(user => ( user.id !== userId && ( <div key={user.id} className="collaborator"> <div className="avatar" style={{ backgroundColor: user.color }}> {user.name.charAt(0)} </div> <span>{user.name}</span> {user.isTyping && <span className="typing-indicator">typing...</span>} </div> ) ))} </div> </div> <div className="editor-container"> <textarea ref={editorRef} value={content} onChange={handleChange} onMouseMove={handleMouseMove} onKeyDown={handleKeyDown} className="editor" /> <CursorOverlay cursors={cursors} /> </div> </main> <footer> <p> <a href="https://github.com/sourabhpunase/realtimecursor" target="_blank" rel="noopener noreferrer"> RealtimeCursor </a> - A free and open-source real-time collaboration SDK </p> </footer> </div> ); } export default App;