realtimecursor
Version:
Real-time collaboration system with cursor tracking and approval workflow
125 lines (110 loc) • 3.58 kB
JSX
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;