realtimecursor
Version:
Real-time collaboration system with cursor tracking and approval workflow
154 lines (130 loc) • 3.84 kB
JavaScript
#!/usr/bin/env node
const fs = require('fs');
const path = require('path');
const { execSync } = require('child_process');
// Ensure dist directory exists
if (!fs.existsSync('./dist')) {
fs.mkdirSync('./dist');
}
// Copy CSS file to dist
fs.copyFileSync('./src/cursor.css', './dist/cursor.css');
// Create a simple bundle using babel
try {
console.log('Building CommonJS version...');
execSync('npx babel src/index.js --out-file dist/index.js', { stdio: 'inherit' });
console.log('Building ESM version...');
execSync('npx babel src/index.js --out-file dist/index.esm.js --no-babelrc --presets=@babel/preset-react', { stdio: 'inherit' });
// Create a simple TypeScript declaration file
const dtsContent = `import { ReactNode } from 'react';
import { EventEmitter } from 'events';
export interface RealtimeCursorOptions {
apiUrl: string;
projectId: string;
user: {
id: string;
name: string;
color?: string;
};
debug?: boolean;
autoConnect?: boolean;
}
export interface CursorPosition {
x?: number;
y?: number;
relativeX?: number;
relativeY?: number;
textPosition?: number;
}
export interface Cursor {
id: string;
position: CursorPosition;
user: {
id: string;
name: string;
color?: string;
};
timestamp: number;
}
export interface Collaborator {
id: string;
name: string;
color?: string;
socketId?: string;
}
export interface TypingStatus {
[key: string]: {
id: string;
isTyping: boolean;
user: {
id: string;
name: string;
color?: string;
};
timestamp: number;
};
}
export class RealtimeCursor extends EventEmitter {
constructor(options: RealtimeCursorOptions);
connect(): void;
disconnect(): void;
updateCursor(position: CursorPosition): void;
updateContent(content: string): void;
updateTypingStatus(isTyping: boolean): void;
getCollaborators(): Collaborator[];
getCursors(): Record<string, Cursor>;
getTypingStatus(): TypingStatus;
isConnected(): boolean;
}
export interface UseRealtimeCursorResult {
cursors: Record<string, Cursor>;
collaborators: Collaborator[];
connected: boolean;
typingStatus: TypingStatus;
connect: () => void;
disconnect: () => void;
updateCursor: (position: CursorPosition) => void;
updateContent: (content: string) => void;
updateTypingStatus: (isTyping: boolean) => void;
}
export function useRealtimeCursor(options: RealtimeCursorOptions): UseRealtimeCursorResult;
export interface CursorOverlayProps {
cursors: Record<string, Cursor>;
containerRef?: React.RefObject<HTMLElement>;
}
export const CursorOverlay: React.FC<CursorOverlayProps>;
export interface CollaboratorsListProps {
collaborators: Collaborator[];
typingStatus?: TypingStatus;
}
export const CollaboratorsList: React.FC<CollaboratorsListProps>;
export interface CollaborativeEditorProps {
apiUrl?: string;
projectId?: string;
userId?: string;
userName?: string;
userColor?: string;
initialContent?: string;
onContentChange?: (content: string) => void;
height?: string;
}
export const CollaborativeEditor: React.FC<CollaborativeEditorProps>;
declare const _default: {
RealtimeCursor: typeof RealtimeCursor;
useRealtimeCursor: typeof useRealtimeCursor;
CursorOverlay: typeof CursorOverlay;
CollaboratorsList: typeof CollaboratorsList;
CollaborativeEditor: typeof CollaborativeEditor;
};
export default _default;
`;
fs.writeFileSync('./dist/index.d.ts', dtsContent);
console.log('✅ Build completed successfully!');
console.log('📦 Files in dist:');
fs.readdirSync('./dist').forEach(file => {
const stats = fs.statSync(path.join('./dist', file));
console.log(` - ${file} (${(stats.size / 1024).toFixed(2)} KB)`);
});
} catch (error) {
console.error('❌ Build failed:', error);
process.exit(1);
}