UNPKG

realtimecursor

Version:

Real-time collaboration system with cursor tracking and approval workflow

172 lines 5.83 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.RealtimeCursor = void 0; const socket_io_client_1 = require("socket.io-client"); class RealtimeCursor { constructor(options) { this.socket = null; this.collaborators = []; this.cursors = {}; this.typingUsers = new Set(); this.options = Object.assign(Object.assign({}, options), { socketUrl: options.socketUrl || options.apiUrl }); } /** * Connect to the real-time cursor service */ connect() { if (this.socket) { this.disconnect(); } // Connect to socket server this.socket = (0, socket_io_client_1.io)(this.options.socketUrl, { auth: { token: this.options.token } }); // Join project room this.socket.emit('join-project', { projectId: this.options.projectId, user: { id: this.options.user.id, name: this.options.user.name, color: this.options.user.color || this.getRandomColor() } }); // Set up event listeners this.setupEventListeners(); } /** * Disconnect from the real-time cursor service */ disconnect() { if (this.socket) { this.socket.disconnect(); this.socket = null; this.collaborators = []; this.cursors = {}; this.typingUsers.clear(); } } /** * Update cursor position */ updateCursor(position) { if (!this.socket) throw new Error('Socket not connected'); this.socket.emit('cursor-move', position); } /** * Update cursor position in text */ updateCursorPosition(textPosition) { if (!this.socket) throw new Error('Socket not connected'); this.socket.emit('cursor-position', { textPosition }); } /** * Update content */ updateContent(content, cursorPosition) { if (!this.socket) throw new Error('Socket not connected'); this.socket.emit('content-change', { content, cursorPosition }); } /** * Set typing indicator */ setTyping(isTyping) { if (!this.socket) throw new Error('Socket not connected'); this.socket.emit('user-typing', { isTyping }); } /** * Register event handlers */ setupEventListeners() { if (!this.socket) return; this.socket.on('room-users', (users) => { var _a; this.collaborators = users; (_a = this.onCollaboratorsChange) === null || _a === void 0 ? void 0 : _a.call(this, users); }); this.socket.on('user-joined', ({ user }) => { var _a, _b; this.collaborators.push(user); (_a = this.onCollaboratorsChange) === null || _a === void 0 ? void 0 : _a.call(this, this.collaborators); (_b = this.onUserJoined) === null || _b === void 0 ? void 0 : _b.call(this, user); }); this.socket.on('user-left', ({ socketId }) => { var _a, _b; this.collaborators = this.collaborators.filter(u => u.socketId !== socketId); delete this.cursors[socketId]; this.typingUsers.delete(socketId); (_a = this.onCollaboratorsChange) === null || _a === void 0 ? void 0 : _a.call(this, this.collaborators); (_b = this.onUserLeft) === null || _b === void 0 ? void 0 : _b.call(this, { socketId }); }); this.socket.on('content-update', (data) => { var _a; (_a = this.onContentUpdate) === null || _a === void 0 ? void 0 : _a.call(this, data); }); this.socket.on('cursor-update', (data) => { var _a; const { socketId, user, x, y, textPosition } = data; this.cursors[socketId] = { x, y, user, textPosition }; (_a = this.onCursorUpdate) === null || _a === void 0 ? void 0 : _a.call(this, data); }); this.socket.on('user-typing', ({ socketId, isTyping }) => { var _a; if (isTyping) { this.typingUsers.add(socketId); } else { this.typingUsers.delete(socketId); } (_a = this.onTypingStatusChange) === null || _a === void 0 ? void 0 : _a.call(this, Array.from(this.typingUsers)); }); this.socket.on('cursor-position', (data) => { var _a; const { socketId, textPosition, user } = data; if (this.cursors[socketId]) { this.cursors[socketId].textPosition = textPosition; this.cursors[socketId].user = user; } else { this.cursors[socketId] = { textPosition, user }; } (_a = this.onCursorPositionUpdate) === null || _a === void 0 ? void 0 : _a.call(this, data); }); } /** * Get random color for cursor */ getRandomColor() { const colors = [ '#3b82f6', '#ef4444', '#10b981', '#f59e0b', '#8b5cf6', '#06b6d4', '#f97316', '#84cc16', '#ec4899', '#6366f1', '#14b8a6', '#f43f5e' ]; return colors[Math.floor(Math.random() * colors.length)]; } /** * Get current collaborators */ getCollaborators() { return this.collaborators; } /** * Get current cursors */ getCursors() { return this.cursors; } /** * Get typing users */ getTypingUsers() { return Array.from(this.typingUsers); } } exports.RealtimeCursor = RealtimeCursor; exports.default = RealtimeCursor; //# sourceMappingURL=realtimecursor.js.map