realtimecursor
Version:
Real-time collaboration system with cursor tracking and approval workflow
380 lines (299 loc) • 9.79 kB
Markdown
# 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).