{"_id":"@barocss/collaboration-yjs","_rev":"3-b363bbe5ba6ae3ed469408a6a39ce953","name":"@barocss/collaboration-yjs","dist-tags":{"latest":"0.1.2"},"versions":{"0.1.0":{"name":"@barocss/collaboration-yjs","version":"0.1.0","keywords":["collaboration","yjs","crdt","realtime","editor"],"author":{"name":"Barocss Team"},"license":"MIT","_id":"@barocss/collaboration-yjs@0.1.0","maintainers":[{"name":"easylogic","email":"cyberuls@gmail.com"}],"dist":{"shasum":"88d3f38590f225081f975fa6bdc08e5613d1f1b5","tarball":"https://registry.npmjs.org/@barocss/collaboration-yjs/-/collaboration-yjs-0.1.0.tgz","fileCount":5,"integrity":"sha512-Js5K/pD2Ar+TooeYR71NvLkCNLSvZYxFSFr++1D9yS2w3miX5gphcQJWAoTsTn6yqA8wgTJBiNBSDJWyB1vEUw==","signatures":[{"sig":"MEUCIE9WXkoezYj34IRhzvdzunvkfvCRnfITyUEq3VYe6aRFAiEAoFuhDvJP9oEdb12xCQDb2VCxCxv8i2U3ee0h7BKFL3g=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":17884},"main":"./dist/index.js","type":"module","_from":"file:barocss-collaboration-yjs-0.1.0.tgz","types":"./dist/index.d.ts","module":"./dist/index.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"scripts":{"dev":"vite build --watch","test":"vitest","build":"vite build","clean":"rm -rf dist","test:run":"vitest run","type-check":"tsc --noEmit"},"_npmUser":{"name":"easylogic","email":"cyberuls@gmail.com"},"_resolved":"/tmp/191cbe96c338fe066be0466b61230da5/barocss-collaboration-yjs-0.1.0.tgz","_integrity":"sha512-Js5K/pD2Ar+TooeYR71NvLkCNLSvZYxFSFr++1D9yS2w3miX5gphcQJWAoTsTn6yqA8wgTJBiNBSDJWyB1vEUw==","_npmVersion":"10.8.2","description":"Yjs adapter for Barocss Editor collaborative editing","directories":{},"_nodeVersion":"20.20.0","dependencies":{"@barocss/datastore":"0.1.0","@barocss/collaboration":"0.1.0"},"publishConfig":{"files":["dist"]},"_hasShrinkwrap":false,"devDependencies":{"vite":"^5.4.21","vitest":"^3.2.4","typescript":"^5.9.3","vite-plugin-dts":"^4.5.4"},"peerDependencies":{"yjs":"^13.6.0"},"_npmOperationalInternal":{"tmp":"tmp/collaboration-yjs_0.1.0_1770043574413_0.9708790238263463","host":"s3://npm-registry-packages-npm-production"}},"0.1.1":{"name":"@barocss/collaboration-yjs","version":"0.1.1","keywords":["collaboration","yjs","crdt","realtime","editor"],"author":{"name":"Barocss Team"},"license":"MIT","_id":"@barocss/collaboration-yjs@0.1.1","maintainers":[{"name":"easylogic","email":"cyberuls@gmail.com"}],"dist":{"shasum":"e9c592488f43b5a0651ff7ff6021ab43ea2dc914","tarball":"https://registry.npmjs.org/@barocss/collaboration-yjs/-/collaboration-yjs-0.1.1.tgz","fileCount":5,"integrity":"sha512-YpcVOuI9/xx6D3Q75AH0nU7QC451lfT0bJl2VYHWZSTXIaEPpgsDa6YmpxpSKnG0rjtqnVajVu2wW0gt4B3xfw==","signatures":[{"sig":"MEYCIQDj0IqKgY+4Pe2+mh+Y+ZuXLT4Rz6VIjEvsDtqrObNkOgIhAN090S6D/8JLssr6fxSytjA8+kS8FwuCGs9UCFDk1+z5","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":17884},"main":"./dist/index.js","type":"module","_from":"file:barocss-collaboration-yjs-0.1.1.tgz","types":"./dist/index.d.ts","module":"./dist/index.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"scripts":{"dev":"vite build --watch","test":"vitest","build":"vite build","clean":"rm -rf dist","test:run":"vitest run","type-check":"tsc --noEmit"},"_npmUser":{"name":"easylogic","email":"cyberuls@gmail.com"},"_resolved":"/tmp/1da440f81723323d16b2f825c3402e1c/barocss-collaboration-yjs-0.1.1.tgz","_integrity":"sha512-YpcVOuI9/xx6D3Q75AH0nU7QC451lfT0bJl2VYHWZSTXIaEPpgsDa6YmpxpSKnG0rjtqnVajVu2wW0gt4B3xfw==","_npmVersion":"10.8.2","description":"Yjs adapter for Barocss Editor collaborative editing","directories":{},"_nodeVersion":"20.20.0","dependencies":{"@barocss/datastore":"0.1.1","@barocss/collaboration":"0.1.1"},"publishConfig":{"files":["dist"]},"_hasShrinkwrap":false,"devDependencies":{"vite":"^5.4.21","vitest":"^3.2.4","typescript":"^5.9.3","vite-plugin-dts":"^4.5.4"},"peerDependencies":{"yjs":"^13.6.0"},"_npmOperationalInternal":{"tmp":"tmp/collaboration-yjs_0.1.1_1771600455303_0.5917378653064342","host":"s3://npm-registry-packages-npm-production"}},"0.1.2":{"name":"@barocss/collaboration-yjs","version":"0.1.2","description":"Yjs adapter for Barocss Editor collaborative editing","type":"module","main":"./dist/index.js","module":"./dist/index.js","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","default":"./dist/index.js"}},"dependencies":{"@barocss/collaboration":"0.1.2","@barocss/datastore":"0.1.2"},"peerDependencies":{"yjs":"^13.6.0"},"devDependencies":{"typescript":"^5.9.3","vite":"^5.4.21","vite-plugin-dts":"^4.5.4","vitest":"^3.2.4"},"publishConfig":{"files":["dist"]},"keywords":["collaboration","yjs","crdt","realtime","editor"],"author":{"name":"Barocss Team"},"license":"MIT","scripts":{"build":"vite build","dev":"vite build --watch","type-check":"tsc --noEmit","clean":"rm -rf dist","test":"vitest","test:run":"vitest run"},"_id":"@barocss/collaboration-yjs@0.1.2","_integrity":"sha512-uvlQywEceLCtCHxtRq+dQmheGoDRvJp0taKlayuA14vwTA5+HzQx6eJlwhkmVINKulz0z0CR/cKCcxs8vDEkwA==","_resolved":"/tmp/a30ba7777263b9f15d5757c09170ac36/barocss-collaboration-yjs-0.1.2.tgz","_from":"file:barocss-collaboration-yjs-0.1.2.tgz","_nodeVersion":"20.20.0","_npmVersion":"10.8.2","dist":{"integrity":"sha512-uvlQywEceLCtCHxtRq+dQmheGoDRvJp0taKlayuA14vwTA5+HzQx6eJlwhkmVINKulz0z0CR/cKCcxs8vDEkwA==","shasum":"660b17ca2b1824d466536ad1d5482fe2f65b4153","tarball":"https://registry.npmjs.org/@barocss/collaboration-yjs/-/collaboration-yjs-0.1.2.tgz","fileCount":5,"unpackedSize":20855,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIAL3Hw1KUQe2pB/wDxjNHMhn4pJe3o7evBCLnhoT4W4mAiB869OPft8IiIM5unFoIjBkMIbhyBuQnn1AtJSMp1iVHA=="}]},"_npmUser":{"name":"easylogic","email":"cyberuls@gmail.com"},"directories":{},"maintainers":[{"name":"easylogic","email":"cyberuls@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/collaboration-yjs_0.1.2_1771692409536_0.24213609001699155"},"_hasShrinkwrap":false}},"time":{"created":"2026-02-02T14:46:14.301Z","modified":"2026-02-21T16:46:49.817Z","0.1.0":"2026-02-02T14:46:14.557Z","0.1.1":"2026-02-20T15:14:15.455Z","0.1.2":"2026-02-21T16:46:49.672Z"},"author":{"name":"Barocss Team"},"license":"MIT","keywords":["collaboration","yjs","crdt","realtime","editor"],"description":"Yjs adapter for Barocss Editor collaborative editing","maintainers":[{"name":"easylogic","email":"cyberuls@gmail.com"}],"readme":"# @barocss/collaboration-yjs\n\nYjs adapter for Barocss Editor collaborative editing. Integrates Barocss DataStore with Yjs CRDT for real-time collaborative editing.\n\n## Architecture\n\n```mermaid\ngraph TB\n    subgraph \"Barocss Editor\"\n        A[\"DataStore<br/>emitOperation/onOperation\"]\n        B[\"AtomicOperation<br/>create|update|delete|move\"]\n    end\n    \n    subgraph \"YjsAdapter\"\n        C[\"BaseAdapter<br/>Common Logic\"]\n        D[\"YjsAdapter<br/>Y.Doc Integration\"]\n    end\n    \n    subgraph \"Yjs\"\n        E[\"Y.Doc<br/>CRDT Document\"]\n        F[\"Y.Map<br/>barocss-document\"]\n        G[\"WebSocketProvider<br/>y-websocket\"]\n    end\n    \n    A --> B\n    B --> C\n    C --> D\n    D --> E\n    E --> F\n    F --> G\n    \n    G --> H[\"Yjs Server<br/>y-websocket\"]\n    H --> I[\"Other Clients\"]\n    \n    style A fill:#e1f5ff\n    style D fill:#fff4e1\n    style E fill:#e8f5e9\n    style F fill:#f3e5f5\n    style G fill:#fce4ec\n```\n\n## Installation\n\n```bash\npnpm add @barocss/collaboration-yjs yjs\n```\n\nFor WebSocket support, also install:\n\n```bash\npnpm add y-websocket\n```\n\n## Quick Start\n\n```typescript\nimport { DataStore } from '@barocss/datastore';\nimport { YjsAdapter } from '@barocss/collaboration-yjs';\nimport * as Y from 'yjs';\nimport { WebsocketProvider } from 'y-websocket';\n\n// Create Yjs document\nconst ydoc = new Y.Doc();\nconst ymap = ydoc.getMap('barocss-document');\n\n// Connect to WebSocket provider\nconst provider = new WebsocketProvider('ws://localhost:1234', 'my-room', ydoc);\n\n// Create adapter\nconst adapter = new YjsAdapter({\n  ydoc,\n  ymap,\n  config: {\n    clientId: 'user-1',\n    user: {\n      id: 'user-1',\n      name: 'John Doe',\n      color: '#ff0000'\n    },\n    debug: true\n  }\n});\n\n// Connect to DataStore\nconst dataStore = new DataStore();\nawait adapter.connect(dataStore);\n\n// Disconnect when done\nawait adapter.disconnect();\n```\n\n## Usage\n\n### Basic Setup\n\n```typescript\nimport { DataStore } from '@barocss/datastore';\nimport { YjsAdapter } from '@barocss/collaboration-yjs';\nimport * as Y from 'yjs';\nimport { WebsocketProvider } from 'y-websocket';\n\n// 1. Create Yjs document\nconst ydoc = new Y.Doc();\n\n// 2. Create or get Y.Map for storing document data\n// You can use a custom map name or default to 'barocss-document'\nconst ymap = ydoc.getMap('barocss-document');\n\n// 3. Set up WebSocket provider (or other sync mechanism)\nconst provider = new WebsocketProvider(\n  'ws://localhost:1234',  // WebSocket server URL\n  'my-room',               // Room/document ID\n  ydoc                     // Y.Doc instance\n);\n\n// 4. Create adapter\nconst adapter = new YjsAdapter({\n  ydoc,\n  ymap,  // Optional: defaults to ydoc.getMap('barocss-document')\n  config: {\n    clientId: 'user-1',\n    debug: true\n  }\n});\n\n// 5. Connect to DataStore\nconst dataStore = new DataStore();\nawait adapter.connect(dataStore);\n```\n\n### Using with y-websocket Server\n\n```typescript\nimport { WebsocketProvider } from 'y-websocket';\n\n// Connect to y-websocket server\nconst provider = new WebsocketProvider(\n  'ws://localhost:1234',\n  'document-id',\n  ydoc\n);\n\nprovider.on('status', (event: { status: string }) => {\n  console.log('Connection status:', event.status);\n});\n\nprovider.on('sync', (isSynced: boolean) => {\n  console.log('Document synced:', isSynced);\n});\n```\n\n### Using with Custom Provider\n\n```typescript\nimport { YjsAdapter } from '@barocss/collaboration-yjs';\nimport * as Y from 'yjs';\n\n// Create Yjs document\nconst ydoc = new Y.Doc();\nconst ymap = ydoc.getMap('barocss-document');\n\n// Set up custom sync mechanism\nclass CustomProvider {\n  constructor(ydoc: Y.Doc) {\n    // Implement your sync logic\n    this.syncWithServer(ydoc);\n  }\n\n  syncWithServer(ydoc: Y.Doc) {\n    // Your custom sync implementation\n  }\n}\n\nconst provider = new CustomProvider(ydoc);\n\n// Create adapter\nconst adapter = new YjsAdapter({\n  ydoc,\n  ymap,\n  config: { clientId: 'user-1' }\n});\n```\n\n## API Reference\n\n### YjsAdapterOptions\n\n```typescript\ninterface YjsAdapterOptions {\n  /**\n   * Y.Doc instance\n   * Required: The Yjs document that will store the collaborative state\n   */\n  ydoc: Y.Doc;\n\n  /**\n   * Y.Map instance\n   * Optional: The Y.Map where document data is stored\n   * Defaults to ydoc.getMap('barocss-document')\n   */\n  ymap?: Y.Map<any>;\n\n  /**\n   * Adapter configuration\n   * See AdapterConfig in @barocss/collaboration\n   */\n  config?: AdapterConfig;\n}\n```\n\n### YjsAdapter Methods\n\n```typescript\nclass YjsAdapter extends BaseAdapter {\n  /**\n   * Connect adapter to DataStore\n   * Sets up Yjs observers and loads initial state\n   */\n  connect(dataStore: DataStore): Promise<void>;\n\n  /**\n   * Disconnect adapter from DataStore\n   * Removes Yjs observers and cleans up\n   */\n  disconnect(): Promise<void>;\n\n  /**\n   * Check if adapter is connected\n   */\n  isConnected(): boolean;\n}\n```\n\n## Advanced Usage\n\n### Custom Y.Map Structure\n\nYou can use a custom Y.Map structure:\n\n```typescript\nconst ydoc = new Y.Doc();\nconst root = ydoc.getMap('root');\nconst operations = root.getMap('operations');\nconst document = root.getMap('document');\n\n// Use operations map for adapter\nconst adapter = new YjsAdapter({\n  ydoc,\n  ymap: operations,\n  config: { clientId: 'user-1' }\n});\n```\n\n### Operation Transformation\n\nTransform operations before storing in Yjs:\n\n```typescript\nconst adapter = new YjsAdapter({\n  ydoc,\n  ymap,\n  config: {\n    clientId: 'user-1',\n    transformOperation: (op) => {\n      // Add Yjs-specific metadata\n      return {\n        ...op,\n        yjsClientId: ydoc.clientID,\n        yjsClock: ydoc.getStateVector()\n      };\n    }\n  }\n});\n```\n\n### Handling Yjs Events\n\n```typescript\n// Listen to Yjs document updates\nydoc.on('update', (update: Uint8Array, origin: any) => {\n  console.log('Yjs document updated:', update);\n});\n\n// Listen to Y.Map changes\nymap.observe((event: Y.YMapEvent<any>) => {\n  console.log('Y.Map changed:', event);\n});\n```\n\n### Presence/Awareness\n\nYjs provides awareness for cursor positions and user presence:\n\n```typescript\nimport * as awarenessProtocol from 'y-protocols/awareness';\n\nconst awareness = new awarenessProtocol.Awareness(ydoc);\n\n// Set local user state\nawareness.setLocalStateField('user', {\n  name: 'John Doe',\n  color: '#ff0000',\n  cursor: { x: 100, y: 200 }\n});\n\n// Listen to other users' presence\nawareness.on('change', (changes: any) => {\n  console.log('Awareness changed:', changes);\n});\n```\n\n## Configuration Options\n\n### AdapterConfig\n\n```typescript\ninterface AdapterConfig {\n  /**\n   * Unique client identifier\n   * Used for operation attribution\n   */\n  clientId?: string;\n\n  /**\n   * User information for presence\n   */\n  user?: {\n    id: string;\n    name?: string;\n    color?: string;\n    avatar?: string;\n  };\n\n  /**\n   * Enable debug logging\n   * Logs all operations to console\n   */\n  debug?: boolean;\n\n  /**\n   * Transform operations before sending\n   */\n  transformOperation?: (op: AtomicOperation) => AtomicOperation;\n}\n```\n\n## Troubleshooting\n\n### Operations Not Syncing\n\n1. **Check WebSocket connection**: Ensure provider is connected\n   ```typescript\n   provider.on('status', (event) => {\n     console.log('Status:', event.status); // Should be 'connected'\n   });\n   ```\n\n2. **Verify Y.Map structure**: Ensure operations are being stored correctly\n   ```typescript\n   ymap.forEach((value, key) => {\n     console.log('Y.Map entry:', key, value);\n   });\n   ```\n\n3. **Check adapter connection**: Verify adapter is connected\n   ```typescript\n   console.log('Adapter connected:', adapter.isConnected());\n   ```\n\n### Circular Updates\n\nIf operations are being sent repeatedly, ensure remote operations are properly detected:\n\n```typescript\n// The adapter automatically handles this, but if you see issues:\n// Check that Yjs update origin is not the adapter itself\n```\n\n### State Not Loading\n\nEnsure initial state is properly loaded:\n\n```typescript\n// Check if root node exists in Yjs\nconst rootData = ymap.get('root');\nconsole.log('Root data:', rootData);\n\n// Manually trigger state load\nawait adapter.getDocumentState();\n```\n\n## Best Practices\n\n1. **Use WebSocket Provider**: For production, use `y-websocket` or similar for reliable sync\n2. **Handle Connection Errors**: Implement reconnection logic for WebSocket providers\n3. **Monitor Sync Status**: Use provider events to track sync state\n4. **Use Awareness**: Leverage Yjs awareness for cursor positions and user presence\n5. **Clean Up**: Always disconnect adapter when component unmounts\n\n## Example: Full Integration\n\n```typescript\nimport { Editor } from '@barocss/editor-core';\nimport { DataStore } from '@barocss/datastore';\nimport { YjsAdapter } from '@barocss/collaboration-yjs';\nimport * as Y from 'yjs';\nimport { WebsocketProvider } from 'y-websocket';\n\nclass CollaborativeEditor {\n  private ydoc: Y.Doc;\n  private provider: WebsocketProvider;\n  private adapter: YjsAdapter;\n  private dataStore: DataStore;\n  private editor: Editor;\n\n  constructor(roomId: string, userId: string) {\n    // Initialize Yjs\n    this.ydoc = new Y.Doc();\n    this.provider = new WebsocketProvider('ws://localhost:1234', roomId, this.ydoc);\n\n    // Initialize DataStore\n    this.dataStore = new DataStore();\n\n    // Create adapter\n    this.adapter = new YjsAdapter({\n      ydoc: this.ydoc,\n      config: {\n        clientId: userId,\n        user: {\n          id: userId,\n          name: `User ${userId}`\n        },\n        debug: true\n      }\n    });\n\n    // Initialize editor\n    this.editor = new Editor({\n      dataStore: this.dataStore\n    });\n  }\n\n  async connect() {\n    await this.adapter.connect(this.dataStore);\n    \n    // Set up provider event handlers\n    this.provider.on('status', (event) => {\n      console.log('Connection status:', event.status);\n    });\n\n    this.provider.on('sync', (isSynced) => {\n      if (isSynced) {\n        console.log('Document synced with server');\n      }\n    });\n  }\n\n  async disconnect() {\n    await this.adapter.disconnect();\n    this.provider.destroy();\n    this.ydoc.destroy();\n  }\n}\n```\n\n## License\n\nMIT\n","readmeFilename":"README.md"}