@crdt-sync/react 0.2.1 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -93,7 +93,7 @@ function useCrdtState(url, initialState, options) {
93
93
  }, [url, initialRef, contextWasmUrl]);
94
94
  (0, import_react2.useEffect)(() => {
95
95
  if (!proxy) return;
96
- return proxy.onUpdate(() => {
96
+ return proxy.onChange(() => {
97
97
  setTick((t) => t + 1);
98
98
  });
99
99
  }, [proxy]);
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/useCrdtState.ts","../src/CrdtSyncContext.tsx"],"sourcesContent":["export { useCrdtState } from './useCrdtState';\nexport type { CrdtStatus, UseCrdtStateResult, UseCrdtStateOptions } from './useCrdtState';\nexport { CrdtSyncProvider } from './CrdtSyncContext';\nexport type { CrdtSyncContextValue, CrdtSyncProviderProps } from './CrdtSyncContext';\n","import { useState, useEffect, useContext } from 'react';\nimport { CrdtStateProxy, WebSocketManager, initWasm, WasmStateStore } from '@crdt-sync/core';\nimport { CrdtSyncContext } from './CrdtSyncContext.js';\n\nexport type CrdtStatus = 'connecting' | 'open' | 'error';\n\nexport interface UseCrdtStateResult<T> {\n state: T;\n proxy: CrdtStateProxy | null;\n status: CrdtStatus;\n}\n\nexport interface UseCrdtStateOptions {\n wasmUrl?: string;\n}\n\nexport function useCrdtState<T extends Record<string, unknown>>(\n url: string,\n initialState: T,\n options?: UseCrdtStateOptions\n): UseCrdtStateResult<T> {\n const [proxy, setProxy] = useState<CrdtStateProxy | null>(null);\n const [status, setStatus] = useState<CrdtStatus>('connecting');\n const [, setTick] = useState(0);\n\n // Note: we're ignoring initialState updates (this behaves like useState).\n const [initialRef] = useState(initialState);\n\n const { wasmUrl: contextWasmUrl } = useContext(CrdtSyncContext);\n\n useEffect(() => {\n let active = true;\n let manager: WebSocketManager | null = null;\n let currentProxy: CrdtStateProxy | null = null;\n\n async function setup() {\n try {\n await initWasm(options?.wasmUrl ?? contextWasmUrl);\n if (!active) return;\n\n // Create a unique client ID\n const clientId = 'client-' + Math.random().toString(36).substring(2, 11);\n const store = new WasmStateStore(clientId);\n\n currentProxy = new CrdtStateProxy(store);\n\n // Initialize state\n for (const [key, value] of Object.entries(initialRef)) {\n currentProxy.state[key] = value;\n }\n\n if (!active) return;\n setProxy(currentProxy);\n\n const ws = new WebSocket(url);\n\n ws.onopen = () => {\n if (active) setStatus('open');\n };\n\n ws.onerror = () => {\n if (active) setStatus('error');\n };\n\n ws.onclose = () => {\n if (active) setStatus('connecting');\n };\n\n manager = new WebSocketManager(store, currentProxy, ws as any);\n } catch (err) {\n console.error('Failed to initialize CRDT sync:', err);\n if (active) setStatus('error');\n }\n }\n\n setup();\n\n return () => {\n active = false;\n if (manager) manager.disconnect();\n };\n }, [url, initialRef, contextWasmUrl]);\n\n useEffect(() => {\n if (!proxy) return;\n\n // Subscribe to proxy updates to trigger React re-renders.\n return proxy.onUpdate(() => {\n setTick(t => t + 1);\n });\n }, [proxy]);\n\n const state = proxy ? (proxy.state as T) : initialRef;\n\n return { state, proxy, status };\n}\n","import React, { createContext } from 'react';\nimport type { ReactNode } from 'react';\n\nexport interface CrdtSyncContextValue {\n wasmUrl?: string;\n}\n\nexport const CrdtSyncContext = createContext<CrdtSyncContextValue>({});\n\nexport interface CrdtSyncProviderProps {\n wasmUrl?: string;\n children: ReactNode;\n}\n\nexport function CrdtSyncProvider({ wasmUrl, children }: CrdtSyncProviderProps): JSX.Element {\n return (\n <CrdtSyncContext.Provider value={{ wasmUrl }}>\n {children}\n </CrdtSyncContext.Provider>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,IAAAA,gBAAgD;AAChD,kBAA2E;;;ACD3E,mBAAqC;AAO9B,IAAM,sBAAkB,4BAAoC,CAAC,CAAC;AAO9D,SAAS,iBAAiB,EAAE,SAAS,SAAS,GAAuC;AACxF,SACI,6BAAAC,QAAA,cAAC,gBAAgB,UAAhB,EAAyB,OAAO,EAAE,QAAQ,KACtC,QACL;AAER;;;ADJO,SAAS,aACZ,KACA,cACA,SACqB;AACrB,QAAM,CAAC,OAAO,QAAQ,QAAI,wBAAgC,IAAI;AAC9D,QAAM,CAAC,QAAQ,SAAS,QAAI,wBAAqB,YAAY;AAC7D,QAAM,CAAC,EAAE,OAAO,QAAI,wBAAS,CAAC;AAG9B,QAAM,CAAC,UAAU,QAAI,wBAAS,YAAY;AAE1C,QAAM,EAAE,SAAS,eAAe,QAAI,0BAAW,eAAe;AAE9D,+BAAU,MAAM;AACZ,QAAI,SAAS;AACb,QAAI,UAAmC;AACvC,QAAI,eAAsC;AAE1C,mBAAe,QAAQ;AACnB,UAAI;AACA,kBAAM,sBAAS,SAAS,WAAW,cAAc;AACjD,YAAI,CAAC,OAAQ;AAGb,cAAM,WAAW,YAAY,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,UAAU,GAAG,EAAE;AACvE,cAAM,QAAQ,IAAI,2BAAe,QAAQ;AAEzC,uBAAe,IAAI,2BAAe,KAAK;AAGvC,mBAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,UAAU,GAAG;AACnD,uBAAa,MAAM,GAAG,IAAI;AAAA,QAC9B;AAEA,YAAI,CAAC,OAAQ;AACb,iBAAS,YAAY;AAErB,cAAM,KAAK,IAAI,UAAU,GAAG;AAE5B,WAAG,SAAS,MAAM;AACd,cAAI,OAAQ,WAAU,MAAM;AAAA,QAChC;AAEA,WAAG,UAAU,MAAM;AACf,cAAI,OAAQ,WAAU,OAAO;AAAA,QACjC;AAEA,WAAG,UAAU,MAAM;AACf,cAAI,OAAQ,WAAU,YAAY;AAAA,QACtC;AAEA,kBAAU,IAAI,6BAAiB,OAAO,cAAc,EAAS;AAAA,MACjE,SAAS,KAAK;AACV,gBAAQ,MAAM,mCAAmC,GAAG;AACpD,YAAI,OAAQ,WAAU,OAAO;AAAA,MACjC;AAAA,IACJ;AAEA,UAAM;AAEN,WAAO,MAAM;AACT,eAAS;AACT,UAAI,QAAS,SAAQ,WAAW;AAAA,IACpC;AAAA,EACJ,GAAG,CAAC,KAAK,YAAY,cAAc,CAAC;AAEpC,+BAAU,MAAM;AACZ,QAAI,CAAC,MAAO;AAGZ,WAAO,MAAM,SAAS,MAAM;AACxB,cAAQ,OAAK,IAAI,CAAC;AAAA,IACtB,CAAC;AAAA,EACL,GAAG,CAAC,KAAK,CAAC;AAEV,QAAM,QAAQ,QAAS,MAAM,QAAc;AAE3C,SAAO,EAAE,OAAO,OAAO,OAAO;AAClC;","names":["import_react","React"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/useCrdtState.ts","../src/CrdtSyncContext.tsx"],"sourcesContent":["export { useCrdtState } from './useCrdtState';\nexport type { CrdtStatus, UseCrdtStateResult, UseCrdtStateOptions } from './useCrdtState';\nexport { CrdtSyncProvider } from './CrdtSyncContext';\nexport type { CrdtSyncContextValue, CrdtSyncProviderProps } from './CrdtSyncContext';\n","import { useState, useEffect, useContext } from 'react';\nimport { CrdtStateProxy, WebSocketManager, initWasm, WasmStateStore } from '@crdt-sync/core';\nimport { CrdtSyncContext } from './CrdtSyncContext.js';\n\nexport type CrdtStatus = 'connecting' | 'open' | 'error';\n\nexport interface UseCrdtStateResult<T> {\n state: T;\n proxy: CrdtStateProxy | null;\n status: CrdtStatus;\n}\n\nexport interface UseCrdtStateOptions {\n wasmUrl?: string;\n}\n\nexport function useCrdtState<T extends Record<string, unknown>>(\n url: string,\n initialState: T,\n options?: UseCrdtStateOptions\n): UseCrdtStateResult<T> {\n const [proxy, setProxy] = useState<CrdtStateProxy | null>(null);\n const [status, setStatus] = useState<CrdtStatus>('connecting');\n const [, setTick] = useState(0);\n\n // Note: we're ignoring initialState updates (this behaves like useState).\n const [initialRef] = useState(initialState);\n\n const { wasmUrl: contextWasmUrl } = useContext(CrdtSyncContext);\n\n useEffect(() => {\n let active = true;\n let manager: WebSocketManager | null = null;\n let currentProxy: CrdtStateProxy | null = null;\n\n async function setup() {\n try {\n await initWasm(options?.wasmUrl ?? contextWasmUrl);\n if (!active) return;\n\n // Create a unique client ID\n const clientId = 'client-' + Math.random().toString(36).substring(2, 11);\n const store = new WasmStateStore(clientId);\n\n currentProxy = new CrdtStateProxy(store);\n\n // Initialize state\n for (const [key, value] of Object.entries(initialRef)) {\n currentProxy.state[key] = value;\n }\n\n if (!active) return;\n setProxy(currentProxy);\n\n const ws = new WebSocket(url);\n\n ws.onopen = () => {\n if (active) setStatus('open');\n };\n\n ws.onerror = () => {\n if (active) setStatus('error');\n };\n\n ws.onclose = () => {\n if (active) setStatus('connecting');\n };\n\n manager = new WebSocketManager(store, currentProxy, ws as any);\n } catch (err) {\n console.error('Failed to initialize CRDT sync:', err);\n if (active) setStatus('error');\n }\n }\n\n setup();\n\n return () => {\n active = false;\n if (manager) manager.disconnect();\n };\n }, [url, initialRef, contextWasmUrl]);\n\n useEffect(() => {\n if (!proxy) return;\n\n // Re-render on any state change: local writes and incoming remote updates.\n return proxy.onChange(() => {\n setTick(t => t + 1);\n });\n }, [proxy]);\n\n const state = proxy ? (proxy.state as T) : initialRef;\n\n return { state, proxy, status };\n}\n","import React, { createContext } from 'react';\nimport type { ReactNode } from 'react';\n\nexport interface CrdtSyncContextValue {\n wasmUrl?: string;\n}\n\nexport const CrdtSyncContext = createContext<CrdtSyncContextValue>({});\n\nexport interface CrdtSyncProviderProps {\n wasmUrl?: string;\n children: ReactNode;\n}\n\nexport function CrdtSyncProvider({ wasmUrl, children }: CrdtSyncProviderProps): JSX.Element {\n return (\n <CrdtSyncContext.Provider value={{ wasmUrl }}>\n {children}\n </CrdtSyncContext.Provider>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,IAAAA,gBAAgD;AAChD,kBAA2E;;;ACD3E,mBAAqC;AAO9B,IAAM,sBAAkB,4BAAoC,CAAC,CAAC;AAO9D,SAAS,iBAAiB,EAAE,SAAS,SAAS,GAAuC;AACxF,SACI,6BAAAC,QAAA,cAAC,gBAAgB,UAAhB,EAAyB,OAAO,EAAE,QAAQ,KACtC,QACL;AAER;;;ADJO,SAAS,aACZ,KACA,cACA,SACqB;AACrB,QAAM,CAAC,OAAO,QAAQ,QAAI,wBAAgC,IAAI;AAC9D,QAAM,CAAC,QAAQ,SAAS,QAAI,wBAAqB,YAAY;AAC7D,QAAM,CAAC,EAAE,OAAO,QAAI,wBAAS,CAAC;AAG9B,QAAM,CAAC,UAAU,QAAI,wBAAS,YAAY;AAE1C,QAAM,EAAE,SAAS,eAAe,QAAI,0BAAW,eAAe;AAE9D,+BAAU,MAAM;AACZ,QAAI,SAAS;AACb,QAAI,UAAmC;AACvC,QAAI,eAAsC;AAE1C,mBAAe,QAAQ;AACnB,UAAI;AACA,kBAAM,sBAAS,SAAS,WAAW,cAAc;AACjD,YAAI,CAAC,OAAQ;AAGb,cAAM,WAAW,YAAY,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,UAAU,GAAG,EAAE;AACvE,cAAM,QAAQ,IAAI,2BAAe,QAAQ;AAEzC,uBAAe,IAAI,2BAAe,KAAK;AAGvC,mBAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,UAAU,GAAG;AACnD,uBAAa,MAAM,GAAG,IAAI;AAAA,QAC9B;AAEA,YAAI,CAAC,OAAQ;AACb,iBAAS,YAAY;AAErB,cAAM,KAAK,IAAI,UAAU,GAAG;AAE5B,WAAG,SAAS,MAAM;AACd,cAAI,OAAQ,WAAU,MAAM;AAAA,QAChC;AAEA,WAAG,UAAU,MAAM;AACf,cAAI,OAAQ,WAAU,OAAO;AAAA,QACjC;AAEA,WAAG,UAAU,MAAM;AACf,cAAI,OAAQ,WAAU,YAAY;AAAA,QACtC;AAEA,kBAAU,IAAI,6BAAiB,OAAO,cAAc,EAAS;AAAA,MACjE,SAAS,KAAK;AACV,gBAAQ,MAAM,mCAAmC,GAAG;AACpD,YAAI,OAAQ,WAAU,OAAO;AAAA,MACjC;AAAA,IACJ;AAEA,UAAM;AAEN,WAAO,MAAM;AACT,eAAS;AACT,UAAI,QAAS,SAAQ,WAAW;AAAA,IACpC;AAAA,EACJ,GAAG,CAAC,KAAK,YAAY,cAAc,CAAC;AAEpC,+BAAU,MAAM;AACZ,QAAI,CAAC,MAAO;AAGZ,WAAO,MAAM,SAAS,MAAM;AACxB,cAAQ,OAAK,IAAI,CAAC;AAAA,IACtB,CAAC;AAAA,EACL,GAAG,CAAC,KAAK,CAAC;AAEV,QAAM,QAAQ,QAAS,MAAM,QAAc;AAE3C,SAAO,EAAE,OAAO,OAAO,OAAO;AAClC;","names":["import_react","React"]}
package/dist/index.mjs CHANGED
@@ -56,7 +56,7 @@ function useCrdtState(url, initialState, options) {
56
56
  }, [url, initialRef, contextWasmUrl]);
57
57
  useEffect(() => {
58
58
  if (!proxy) return;
59
- return proxy.onUpdate(() => {
59
+ return proxy.onChange(() => {
60
60
  setTick((t) => t + 1);
61
61
  });
62
62
  }, [proxy]);
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/useCrdtState.ts","../src/CrdtSyncContext.tsx"],"sourcesContent":["import { useState, useEffect, useContext } from 'react';\nimport { CrdtStateProxy, WebSocketManager, initWasm, WasmStateStore } from '@crdt-sync/core';\nimport { CrdtSyncContext } from './CrdtSyncContext.js';\n\nexport type CrdtStatus = 'connecting' | 'open' | 'error';\n\nexport interface UseCrdtStateResult<T> {\n state: T;\n proxy: CrdtStateProxy | null;\n status: CrdtStatus;\n}\n\nexport interface UseCrdtStateOptions {\n wasmUrl?: string;\n}\n\nexport function useCrdtState<T extends Record<string, unknown>>(\n url: string,\n initialState: T,\n options?: UseCrdtStateOptions\n): UseCrdtStateResult<T> {\n const [proxy, setProxy] = useState<CrdtStateProxy | null>(null);\n const [status, setStatus] = useState<CrdtStatus>('connecting');\n const [, setTick] = useState(0);\n\n // Note: we're ignoring initialState updates (this behaves like useState).\n const [initialRef] = useState(initialState);\n\n const { wasmUrl: contextWasmUrl } = useContext(CrdtSyncContext);\n\n useEffect(() => {\n let active = true;\n let manager: WebSocketManager | null = null;\n let currentProxy: CrdtStateProxy | null = null;\n\n async function setup() {\n try {\n await initWasm(options?.wasmUrl ?? contextWasmUrl);\n if (!active) return;\n\n // Create a unique client ID\n const clientId = 'client-' + Math.random().toString(36).substring(2, 11);\n const store = new WasmStateStore(clientId);\n\n currentProxy = new CrdtStateProxy(store);\n\n // Initialize state\n for (const [key, value] of Object.entries(initialRef)) {\n currentProxy.state[key] = value;\n }\n\n if (!active) return;\n setProxy(currentProxy);\n\n const ws = new WebSocket(url);\n\n ws.onopen = () => {\n if (active) setStatus('open');\n };\n\n ws.onerror = () => {\n if (active) setStatus('error');\n };\n\n ws.onclose = () => {\n if (active) setStatus('connecting');\n };\n\n manager = new WebSocketManager(store, currentProxy, ws as any);\n } catch (err) {\n console.error('Failed to initialize CRDT sync:', err);\n if (active) setStatus('error');\n }\n }\n\n setup();\n\n return () => {\n active = false;\n if (manager) manager.disconnect();\n };\n }, [url, initialRef, contextWasmUrl]);\n\n useEffect(() => {\n if (!proxy) return;\n\n // Subscribe to proxy updates to trigger React re-renders.\n return proxy.onUpdate(() => {\n setTick(t => t + 1);\n });\n }, [proxy]);\n\n const state = proxy ? (proxy.state as T) : initialRef;\n\n return { state, proxy, status };\n}\n","import React, { createContext } from 'react';\nimport type { ReactNode } from 'react';\n\nexport interface CrdtSyncContextValue {\n wasmUrl?: string;\n}\n\nexport const CrdtSyncContext = createContext<CrdtSyncContextValue>({});\n\nexport interface CrdtSyncProviderProps {\n wasmUrl?: string;\n children: ReactNode;\n}\n\nexport function CrdtSyncProvider({ wasmUrl, children }: CrdtSyncProviderProps): JSX.Element {\n return (\n <CrdtSyncContext.Provider value={{ wasmUrl }}>\n {children}\n </CrdtSyncContext.Provider>\n );\n}\n"],"mappings":";AAAA,SAAS,UAAU,WAAW,kBAAkB;AAChD,SAAS,gBAAgB,kBAAkB,UAAU,sBAAsB;;;ACD3E,OAAO,SAAS,qBAAqB;AAO9B,IAAM,kBAAkB,cAAoC,CAAC,CAAC;AAO9D,SAAS,iBAAiB,EAAE,SAAS,SAAS,GAAuC;AACxF,SACI,oCAAC,gBAAgB,UAAhB,EAAyB,OAAO,EAAE,QAAQ,KACtC,QACL;AAER;;;ADJO,SAAS,aACZ,KACA,cACA,SACqB;AACrB,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAgC,IAAI;AAC9D,QAAM,CAAC,QAAQ,SAAS,IAAI,SAAqB,YAAY;AAC7D,QAAM,CAAC,EAAE,OAAO,IAAI,SAAS,CAAC;AAG9B,QAAM,CAAC,UAAU,IAAI,SAAS,YAAY;AAE1C,QAAM,EAAE,SAAS,eAAe,IAAI,WAAW,eAAe;AAE9D,YAAU,MAAM;AACZ,QAAI,SAAS;AACb,QAAI,UAAmC;AACvC,QAAI,eAAsC;AAE1C,mBAAe,QAAQ;AACnB,UAAI;AACA,cAAM,SAAS,SAAS,WAAW,cAAc;AACjD,YAAI,CAAC,OAAQ;AAGb,cAAM,WAAW,YAAY,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,UAAU,GAAG,EAAE;AACvE,cAAM,QAAQ,IAAI,eAAe,QAAQ;AAEzC,uBAAe,IAAI,eAAe,KAAK;AAGvC,mBAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,UAAU,GAAG;AACnD,uBAAa,MAAM,GAAG,IAAI;AAAA,QAC9B;AAEA,YAAI,CAAC,OAAQ;AACb,iBAAS,YAAY;AAErB,cAAM,KAAK,IAAI,UAAU,GAAG;AAE5B,WAAG,SAAS,MAAM;AACd,cAAI,OAAQ,WAAU,MAAM;AAAA,QAChC;AAEA,WAAG,UAAU,MAAM;AACf,cAAI,OAAQ,WAAU,OAAO;AAAA,QACjC;AAEA,WAAG,UAAU,MAAM;AACf,cAAI,OAAQ,WAAU,YAAY;AAAA,QACtC;AAEA,kBAAU,IAAI,iBAAiB,OAAO,cAAc,EAAS;AAAA,MACjE,SAAS,KAAK;AACV,gBAAQ,MAAM,mCAAmC,GAAG;AACpD,YAAI,OAAQ,WAAU,OAAO;AAAA,MACjC;AAAA,IACJ;AAEA,UAAM;AAEN,WAAO,MAAM;AACT,eAAS;AACT,UAAI,QAAS,SAAQ,WAAW;AAAA,IACpC;AAAA,EACJ,GAAG,CAAC,KAAK,YAAY,cAAc,CAAC;AAEpC,YAAU,MAAM;AACZ,QAAI,CAAC,MAAO;AAGZ,WAAO,MAAM,SAAS,MAAM;AACxB,cAAQ,OAAK,IAAI,CAAC;AAAA,IACtB,CAAC;AAAA,EACL,GAAG,CAAC,KAAK,CAAC;AAEV,QAAM,QAAQ,QAAS,MAAM,QAAc;AAE3C,SAAO,EAAE,OAAO,OAAO,OAAO;AAClC;","names":[]}
1
+ {"version":3,"sources":["../src/useCrdtState.ts","../src/CrdtSyncContext.tsx"],"sourcesContent":["import { useState, useEffect, useContext } from 'react';\nimport { CrdtStateProxy, WebSocketManager, initWasm, WasmStateStore } from '@crdt-sync/core';\nimport { CrdtSyncContext } from './CrdtSyncContext.js';\n\nexport type CrdtStatus = 'connecting' | 'open' | 'error';\n\nexport interface UseCrdtStateResult<T> {\n state: T;\n proxy: CrdtStateProxy | null;\n status: CrdtStatus;\n}\n\nexport interface UseCrdtStateOptions {\n wasmUrl?: string;\n}\n\nexport function useCrdtState<T extends Record<string, unknown>>(\n url: string,\n initialState: T,\n options?: UseCrdtStateOptions\n): UseCrdtStateResult<T> {\n const [proxy, setProxy] = useState<CrdtStateProxy | null>(null);\n const [status, setStatus] = useState<CrdtStatus>('connecting');\n const [, setTick] = useState(0);\n\n // Note: we're ignoring initialState updates (this behaves like useState).\n const [initialRef] = useState(initialState);\n\n const { wasmUrl: contextWasmUrl } = useContext(CrdtSyncContext);\n\n useEffect(() => {\n let active = true;\n let manager: WebSocketManager | null = null;\n let currentProxy: CrdtStateProxy | null = null;\n\n async function setup() {\n try {\n await initWasm(options?.wasmUrl ?? contextWasmUrl);\n if (!active) return;\n\n // Create a unique client ID\n const clientId = 'client-' + Math.random().toString(36).substring(2, 11);\n const store = new WasmStateStore(clientId);\n\n currentProxy = new CrdtStateProxy(store);\n\n // Initialize state\n for (const [key, value] of Object.entries(initialRef)) {\n currentProxy.state[key] = value;\n }\n\n if (!active) return;\n setProxy(currentProxy);\n\n const ws = new WebSocket(url);\n\n ws.onopen = () => {\n if (active) setStatus('open');\n };\n\n ws.onerror = () => {\n if (active) setStatus('error');\n };\n\n ws.onclose = () => {\n if (active) setStatus('connecting');\n };\n\n manager = new WebSocketManager(store, currentProxy, ws as any);\n } catch (err) {\n console.error('Failed to initialize CRDT sync:', err);\n if (active) setStatus('error');\n }\n }\n\n setup();\n\n return () => {\n active = false;\n if (manager) manager.disconnect();\n };\n }, [url, initialRef, contextWasmUrl]);\n\n useEffect(() => {\n if (!proxy) return;\n\n // Re-render on any state change: local writes and incoming remote updates.\n return proxy.onChange(() => {\n setTick(t => t + 1);\n });\n }, [proxy]);\n\n const state = proxy ? (proxy.state as T) : initialRef;\n\n return { state, proxy, status };\n}\n","import React, { createContext } from 'react';\nimport type { ReactNode } from 'react';\n\nexport interface CrdtSyncContextValue {\n wasmUrl?: string;\n}\n\nexport const CrdtSyncContext = createContext<CrdtSyncContextValue>({});\n\nexport interface CrdtSyncProviderProps {\n wasmUrl?: string;\n children: ReactNode;\n}\n\nexport function CrdtSyncProvider({ wasmUrl, children }: CrdtSyncProviderProps): JSX.Element {\n return (\n <CrdtSyncContext.Provider value={{ wasmUrl }}>\n {children}\n </CrdtSyncContext.Provider>\n );\n}\n"],"mappings":";AAAA,SAAS,UAAU,WAAW,kBAAkB;AAChD,SAAS,gBAAgB,kBAAkB,UAAU,sBAAsB;;;ACD3E,OAAO,SAAS,qBAAqB;AAO9B,IAAM,kBAAkB,cAAoC,CAAC,CAAC;AAO9D,SAAS,iBAAiB,EAAE,SAAS,SAAS,GAAuC;AACxF,SACI,oCAAC,gBAAgB,UAAhB,EAAyB,OAAO,EAAE,QAAQ,KACtC,QACL;AAER;;;ADJO,SAAS,aACZ,KACA,cACA,SACqB;AACrB,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAgC,IAAI;AAC9D,QAAM,CAAC,QAAQ,SAAS,IAAI,SAAqB,YAAY;AAC7D,QAAM,CAAC,EAAE,OAAO,IAAI,SAAS,CAAC;AAG9B,QAAM,CAAC,UAAU,IAAI,SAAS,YAAY;AAE1C,QAAM,EAAE,SAAS,eAAe,IAAI,WAAW,eAAe;AAE9D,YAAU,MAAM;AACZ,QAAI,SAAS;AACb,QAAI,UAAmC;AACvC,QAAI,eAAsC;AAE1C,mBAAe,QAAQ;AACnB,UAAI;AACA,cAAM,SAAS,SAAS,WAAW,cAAc;AACjD,YAAI,CAAC,OAAQ;AAGb,cAAM,WAAW,YAAY,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,UAAU,GAAG,EAAE;AACvE,cAAM,QAAQ,IAAI,eAAe,QAAQ;AAEzC,uBAAe,IAAI,eAAe,KAAK;AAGvC,mBAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,UAAU,GAAG;AACnD,uBAAa,MAAM,GAAG,IAAI;AAAA,QAC9B;AAEA,YAAI,CAAC,OAAQ;AACb,iBAAS,YAAY;AAErB,cAAM,KAAK,IAAI,UAAU,GAAG;AAE5B,WAAG,SAAS,MAAM;AACd,cAAI,OAAQ,WAAU,MAAM;AAAA,QAChC;AAEA,WAAG,UAAU,MAAM;AACf,cAAI,OAAQ,WAAU,OAAO;AAAA,QACjC;AAEA,WAAG,UAAU,MAAM;AACf,cAAI,OAAQ,WAAU,YAAY;AAAA,QACtC;AAEA,kBAAU,IAAI,iBAAiB,OAAO,cAAc,EAAS;AAAA,MACjE,SAAS,KAAK;AACV,gBAAQ,MAAM,mCAAmC,GAAG;AACpD,YAAI,OAAQ,WAAU,OAAO;AAAA,MACjC;AAAA,IACJ;AAEA,UAAM;AAEN,WAAO,MAAM;AACT,eAAS;AACT,UAAI,QAAS,SAAQ,WAAW;AAAA,IACpC;AAAA,EACJ,GAAG,CAAC,KAAK,YAAY,cAAc,CAAC;AAEpC,YAAU,MAAM;AACZ,QAAI,CAAC,MAAO;AAGZ,WAAO,MAAM,SAAS,MAAM;AACxB,cAAQ,OAAK,IAAI,CAAC;AAAA,IACtB,CAAC;AAAA,EACL,GAAG,CAAC,KAAK,CAAC;AAEV,QAAM,QAAQ,QAAS,MAAM,QAAc;AAE3C,SAAO,EAAE,OAAO,OAAO,OAAO;AAClC;","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@crdt-sync/react",
3
- "version": "0.2.1",
3
+ "version": "0.3.0",
4
4
  "description": "React hook adapter for crdt-sync",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
@@ -24,7 +24,7 @@
24
24
  "react-dom": ">=16.8"
25
25
  },
26
26
  "dependencies": {
27
- "@crdt-sync/core": "^0.2.3"
27
+ "@crdt-sync/core": "^0.3.0"
28
28
  },
29
29
  "devDependencies": {
30
30
  "@testing-library/jest-dom": "^6.9.1",