@akashjs/runtime 0.1.1 → 0.1.3
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/README.md +21 -0
- package/dist/animate.cjs +2 -0
- package/dist/animate.cjs.map +1 -0
- package/dist/animate.js +2 -0
- package/dist/animate.js.map +1 -0
- package/dist/chunk-24I477TY.js +32 -0
- package/dist/chunk-24I477TY.js.map +1 -0
- package/dist/chunk-2PUQBTK5.cjs +5 -0
- package/dist/chunk-2PUQBTK5.cjs.map +1 -0
- package/dist/chunk-2X7GUBTG.cjs +2 -0
- package/dist/chunk-2X7GUBTG.cjs.map +1 -0
- package/dist/chunk-3HWR5MIF.js +2 -0
- package/dist/chunk-3HWR5MIF.js.map +1 -0
- package/dist/chunk-4K6DIB7A.js +2 -0
- package/dist/chunk-4K6DIB7A.js.map +1 -0
- package/dist/chunk-BJKK7MKL.js +5 -0
- package/dist/chunk-BJKK7MKL.js.map +1 -0
- package/dist/chunk-FWWD2YSS.cjs +2 -0
- package/dist/chunk-FWWD2YSS.cjs.map +1 -0
- package/dist/chunk-GWEBEL7E.js +2 -0
- package/dist/chunk-GWEBEL7E.js.map +1 -0
- package/dist/chunk-J4TFVNKP.cjs +32 -0
- package/dist/chunk-J4TFVNKP.cjs.map +1 -0
- package/dist/chunk-KI5MVV64.cjs +2 -0
- package/dist/chunk-KI5MVV64.cjs.map +1 -0
- package/dist/chunk-N4IP63GR.js +2 -0
- package/dist/chunk-N4IP63GR.js.map +1 -0
- package/dist/chunk-PEDMDFZM.js +2 -0
- package/dist/chunk-PEDMDFZM.js.map +1 -0
- package/dist/chunk-Q3E2UVUK.js +2 -0
- package/dist/chunk-Q3E2UVUK.js.map +1 -0
- package/dist/chunk-RRB7VGW7.js +2 -0
- package/dist/chunk-RRB7VGW7.js.map +1 -0
- package/dist/chunk-UVM6CYWX.cjs +2 -0
- package/dist/chunk-UVM6CYWX.cjs.map +1 -0
- package/dist/chunk-Y5HEEST4.cjs +2 -0
- package/dist/chunk-Y5HEEST4.cjs.map +1 -0
- package/dist/chunk-YFCIWM3C.cjs +2 -0
- package/dist/chunk-YFCIWM3C.cjs.map +1 -0
- package/dist/chunk-ZE7R72IH.cjs +2 -0
- package/dist/chunk-ZE7R72IH.cjs.map +1 -0
- package/dist/core.cjs +2 -0
- package/dist/core.cjs.map +1 -0
- package/dist/core.js +2 -0
- package/dist/core.js.map +1 -0
- package/dist/index.cjs +51 -5458
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +51 -4579
- package/dist/index.js.map +1 -1
- package/dist/machine.cjs +2 -0
- package/dist/machine.cjs.map +1 -0
- package/dist/machine.js +2 -0
- package/dist/machine.js.map +1 -0
- package/dist/offline.cjs +2 -0
- package/dist/offline.cjs.map +1 -0
- package/dist/offline.js +2 -0
- package/dist/offline.js.map +1 -0
- package/dist/pwa.cjs +2 -0
- package/dist/pwa.cjs.map +1 -0
- package/dist/pwa.js +2 -0
- package/dist/pwa.js.map +1 -0
- package/dist/ssr.cjs +2 -0
- package/dist/ssr.cjs.map +1 -0
- package/dist/ssr.js +2 -0
- package/dist/ssr.js.map +1 -0
- package/dist/store.cjs +2 -0
- package/dist/store.cjs.map +1 -0
- package/dist/store.js +2 -0
- package/dist/store.js.map +1 -0
- package/dist/sync.cjs +2 -0
- package/dist/sync.cjs.map +1 -0
- package/dist/sync.js +2 -0
- package/dist/sync.js.map +1 -0
- package/dist/test.cjs +4 -369
- package/dist/test.cjs.map +1 -1
- package/dist/test.js +4 -165
- package/dist/test.js.map +1 -1
- package/package.json +30 -5
- package/dist/chunk-D3IR22HI.js +0 -662
- package/dist/chunk-D3IR22HI.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/sync.ts"],"names":["LWWRegister","initialValue","peerId","value","ts","remote","createWebSocketTransport","options","ws","opHandlers","presenceHandlers","op","handler","i","data","e","msg","h","createLocalTransport","peerIdCounter","createSync","roomId","initialState","transport","registers","stateSignals","key","signal","state","original","register","proxy","fn","peers","connected","presence","peerPresenceMap","unsubOps","unsubPresence","remotePeerId","map","next"],"mappings":"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","file":"chunk-KI5MVV64.cjs","sourcesContent":["/**\n * Collaborative signals with CRDT.\n *\n * Make any signal multiplayer with one line. Multiple users can\n * edit the same state simultaneously with automatic conflict\n * resolution via Last-Writer-Wins Register and Operation-based CRDTs.\n *\n * ```ts\n * const doc = createSync('doc-123', {\n * title: '',\n * blocks: [],\n * cursor: { x: 0, y: 0 },\n * });\n *\n * doc.state.title.set('Hello'); // syncs to all peers\n * doc.peers(); // list of connected users\n * doc.presence.set({ cursor: { x: 10, y: 20 } });\n * ```\n */\n\nimport { signal, computed } from './signals.js';\nimport type { Signal, ReadonlySignal } from './signals.js';\n\n// =========================================================================\n// CRDT — Last-Writer-Wins Register\n// =========================================================================\n\nexport interface LWWEntry<T> {\n value: T;\n timestamp: number;\n peerId: string;\n}\n\n/**\n * Last-Writer-Wins Register — simplest CRDT for single values.\n * The write with the highest timestamp wins on conflict.\n */\nexport class LWWRegister<T> {\n private entry: LWWEntry<T>;\n\n constructor(initialValue: T, peerId: string) {\n this.entry = { value: initialValue, timestamp: Date.now(), peerId };\n }\n\n get value(): T {\n return this.entry.value;\n }\n\n get timestamp(): number {\n return this.entry.timestamp;\n }\n\n set(value: T, peerId: string): boolean {\n const ts = Date.now();\n // Local writes always succeed (same peer always advances its own state).\n // Cross-peer conflicts resolve by highest timestamp, then peerId tiebreak.\n if (\n peerId === this.entry.peerId ||\n ts > this.entry.timestamp ||\n (ts === this.entry.timestamp && peerId > this.entry.peerId)\n ) {\n this.entry = { value, timestamp: Math.max(ts, this.entry.timestamp + 1), peerId };\n return true;\n }\n return false;\n }\n\n merge(remote: LWWEntry<T>): boolean {\n if (\n remote.timestamp > this.entry.timestamp ||\n (remote.timestamp === this.entry.timestamp && remote.peerId > this.entry.peerId)\n ) {\n this.entry = remote;\n return true;\n }\n return false;\n }\n\n toEntry(): LWWEntry<T> {\n return { ...this.entry };\n }\n}\n\n// =========================================================================\n// Operation log for list CRDTs\n// =========================================================================\n\nexport type SyncOp =\n | { type: 'set'; key: string; value: unknown; timestamp: number; peerId: string }\n | { type: 'insert'; key: string; index: number; value: unknown; timestamp: number; peerId: string }\n | { type: 'delete'; key: string; index: number; timestamp: number; peerId: string };\n\n// =========================================================================\n// Sync transport interface\n// =========================================================================\n\nexport interface SyncTransport {\n /** Send an operation to peers */\n send(op: SyncOp): void;\n /** Listen for operations from peers */\n onReceive(handler: (op: SyncOp) => void): () => void;\n /** Listen for peer presence updates */\n onPresence?(handler: (peerId: string, data: unknown) => void): () => void;\n /** Send presence data */\n sendPresence?(data: unknown): void;\n /** Connect to the sync channel */\n connect(): void;\n /** Disconnect */\n disconnect(): void;\n}\n\n// =========================================================================\n// WebSocket transport\n// =========================================================================\n\nexport interface WebSocketTransportOptions {\n url: string;\n room: string;\n protocols?: string | string[];\n}\n\nexport function createWebSocketTransport(options: WebSocketTransportOptions): SyncTransport {\n let ws: WebSocket | null = null;\n const opHandlers: Array<(op: SyncOp) => void> = [];\n const presenceHandlers: Array<(peerId: string, data: unknown) => void> = [];\n\n return {\n send(op: SyncOp) {\n ws?.send(JSON.stringify({ type: 'op', room: options.room, ...op }));\n },\n onReceive(handler) {\n opHandlers.push(handler);\n return () => {\n const i = opHandlers.indexOf(handler);\n if (i !== -1) opHandlers.splice(i, 1);\n };\n },\n onPresence(handler) {\n presenceHandlers.push(handler);\n return () => {\n const i = presenceHandlers.indexOf(handler);\n if (i !== -1) presenceHandlers.splice(i, 1);\n };\n },\n sendPresence(data) {\n ws?.send(JSON.stringify({ type: 'presence', room: options.room, data }));\n },\n connect() {\n ws = new WebSocket(options.url, options.protocols);\n ws.onmessage = (e) => {\n try {\n const msg = JSON.parse(e.data);\n if (msg.type === 'op') {\n for (const h of opHandlers) h(msg);\n } else if (msg.type === 'presence') {\n for (const h of presenceHandlers) h(msg.peerId, msg.data);\n }\n } catch { /* ignore parse errors */ }\n };\n ws.onopen = () => {\n ws?.send(JSON.stringify({ type: 'join', room: options.room }));\n };\n },\n disconnect() {\n ws?.close();\n ws = null;\n },\n };\n}\n\n// =========================================================================\n// In-memory transport (for testing / single-tab)\n// =========================================================================\n\nexport function createLocalTransport(): SyncTransport {\n const opHandlers: Array<(op: SyncOp) => void> = [];\n return {\n send(op) {\n for (const h of opHandlers) h(op);\n },\n onReceive(handler) {\n opHandlers.push(handler);\n return () => {\n const i = opHandlers.indexOf(handler);\n if (i !== -1) opHandlers.splice(i, 1);\n };\n },\n connect() {},\n disconnect() {},\n };\n}\n\n// =========================================================================\n// createSync — the main API\n// =========================================================================\n\nexport interface SyncOptions {\n /** Transport for sending/receiving operations */\n transport?: SyncTransport;\n /** Unique peer ID (default: random) */\n peerId?: string;\n}\n\nexport interface SyncDoc<T extends Record<string, unknown>> {\n /** Reactive synced state — each key is a Signal */\n state: { [K in keyof T]: Signal<T[K]> };\n /** Connected peers (reactive) */\n peers: ReadonlySignal<PeerInfo[]>;\n /** Local presence data */\n presence: Signal<Record<string, unknown>>;\n /** Peer presence map (reactive) */\n peerPresence: ReadonlySignal<Map<string, unknown>>;\n /** This peer's ID */\n peerId: string;\n /** Whether connected */\n connected: ReadonlySignal<boolean>;\n /** Connect to the sync channel */\n connect(): void;\n /** Disconnect */\n disconnect(): void;\n /** Dispose the sync doc */\n dispose(): void;\n}\n\nexport interface PeerInfo {\n id: string;\n joinedAt: number;\n}\n\nlet peerIdCounter = 0;\n\n/**\n * Create a collaborative synced document.\n *\n * ```ts\n * const doc = createSync('room-1', { title: '', count: 0 }, {\n * transport: createWebSocketTransport({ url: 'wss://sync.example.com', room: 'room-1' }),\n * });\n *\n * doc.state.title.set('Hello'); // auto-syncs to all peers\n * doc.peers(); // connected users\n * ```\n */\nexport function createSync<T extends Record<string, unknown>>(\n roomId: string,\n initialState: T,\n options: SyncOptions = {},\n): SyncDoc<T> {\n const peerId = options.peerId ?? `peer-${++peerIdCounter}-${Date.now()}`;\n const transport = options.transport ?? createLocalTransport();\n\n // Create CRDT registers and signals for each state key\n const registers = new Map<string, LWWRegister<unknown>>();\n const stateSignals: Record<string, Signal<unknown>> = {};\n\n for (const [key, value] of Object.entries(initialState)) {\n registers.set(key, new LWWRegister(value, peerId));\n stateSignals[key] = signal(value);\n }\n\n // Intercept signal.set to broadcast operations\n const state = {} as { [K in keyof T]: Signal<T[K]> };\n for (const key of Object.keys(initialState)) {\n const original = stateSignals[key];\n const register = registers.get(key)!;\n\n const proxy: Signal<any> = (() => original()) as any;\n proxy.set = (value: any) => {\n register.set(value, peerId);\n original.set(value);\n transport.send({\n type: 'set',\n key,\n value,\n timestamp: register.timestamp,\n peerId,\n });\n };\n proxy.update = (fn: (prev: any) => any) => {\n proxy.set(fn(original()));\n };\n proxy.peek = () => original.peek();\n\n (state as any)[key] = proxy;\n }\n\n // Peers\n const peers = signal<PeerInfo[]>([]);\n const connected = signal(false);\n const presence = signal<Record<string, unknown>>({});\n const peerPresenceMap = signal(new Map<string, unknown>());\n\n // Listen for remote operations\n const unsubOps = transport.onReceive((op) => {\n if (op.type === 'set' && registers.has(op.key)) {\n const register = registers.get(op.key)!;\n const merged = register.merge({\n value: op.value,\n timestamp: op.timestamp,\n peerId: op.peerId,\n });\n if (merged) {\n stateSignals[op.key].set(op.value);\n }\n }\n });\n\n // Listen for presence\n const unsubPresence = transport.onPresence?.((remotePeerId, data) => {\n peerPresenceMap.update((map) => {\n const next = new Map(map);\n next.set(remotePeerId, data);\n return next;\n });\n });\n\n return {\n state,\n peers: () => peers(),\n presence,\n peerPresence: () => peerPresenceMap(),\n peerId,\n connected: () => connected(),\n connect() {\n transport.connect();\n connected.set(true);\n },\n disconnect() {\n transport.disconnect();\n connected.set(false);\n },\n dispose() {\n unsubOps();\n unsubPresence?.();\n transport.disconnect();\n },\n };\n}\n"]}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import {c,d}from'./chunk-4K6DIB7A.js';async function k(a,n=1){return new Promise((c,r)=>{let t=indexedDB.open(a,n);t.onupgradeneeded=()=>{let i=t.result;i.objectStoreNames.contains("items")||i.createObjectStore("items"),i.objectStoreNames.contains("pending")||i.createObjectStore("pending",{autoIncrement:true});},t.onsuccess=()=>c(t.result),t.onerror=()=>r(t.error);})}async function x(a,n){return new Promise((c,r)=>{let i=a.transaction(n,"readonly").objectStore(n).getAll();i.onsuccess=()=>c(i.result),i.onerror=()=>r(i.error);})}async function D(a,n,c,r){return new Promise((t,i)=>{let d=a.transaction(n,"readwrite");d.objectStore(n).put(r,c),d.oncomplete=()=>t(),d.onerror=()=>i(d.error);})}async function I(a,n,c){return new Promise((r,t)=>{let i=a.transaction(n,"readwrite");i.objectStore(n).delete(c),i.oncomplete=()=>r(),i.onerror=()=>t(i.error);})}async function y(a,n){return new Promise((c,r)=>{let t=a.transaction(n,"readwrite");t.objectStore(n).clear(),t.oncomplete=()=>c(),t.onerror=()=>r(t.error);})}function B(a,n={}){let c$1=n.keyField??"id",r=c([]),t=c([]),i=c(false),d$1=c(typeof navigator<"u"?navigator.onLine:true),b=d(()=>t().length),s=null,m=null,T=false;typeof window<"u"&&(window.addEventListener("online",()=>{d$1.set(true),w();}),window.addEventListener("offline",()=>d$1.set(false)));async function O(){if(!(typeof indexedDB>"u"))try{s=await k(`akash-offline-${a}`,n.version??1);let e=await x(s,"items");r.set(e);let o=await x(s,"pending");t.set(o);}catch{}}if(O(),n.sync){let e=n.sync.interval??3e4;m=setInterval(()=>{d$1()&&b()>0&&!i()&&w();},e);}function g(e){return String(e[c$1])}function v(e){let o=g(e);r.update(l=>{let f=l.findIndex(u=>g(u)===o);if(f!==-1){let u=[...l];return u[f]=e,u}return [...l,e]}),S({type:"put",key:o,value:e,timestamp:Date.now()}),s&&D(s,"items",o,e);}function j(e){r.update(o=>o.filter(l=>g(l)!==e)),S({type:"delete",key:e,timestamp:Date.now()}),s&&I(s,"items",e);}function S(e){t.update(o=>[...o,e]),s&&s.transaction("pending","readwrite").objectStore("pending").add(e);}async function w(){if(!n.sync||i()||T)return;let e=t();if(e.length===0)return;i.set(true);let o=n.sync.fetch??globalThis.fetch.bind(globalThis);try{if((await o(n.sync.url,{method:"POST",headers:{"Content-Type":"application/json",...n.sync.headers},body:JSON.stringify({ops:e})})).ok){t.set([]),s&&await y(s,"pending");let f=await o(n.sync.url,{headers:n.sync.headers});if(f.ok){let u=await f.json();if(r.set(u),s){await y(s,"items");for(let P of u)await D(s,"items",g(P),P);}}}}catch{}finally{i.set(false);}}return {items:()=>r(),get(e){return r().find(o=>g(o)===e)},put:v,add:v,update(e,o){let l=r().find(f=>g(f)===e);l&&v({...l,...o});},remove:j,clear(){r.set([]),t.set([]),s&&(y(s,"items"),y(s,"pending"));},pending:b,syncing:()=>i(),online:()=>d$1(),sync:w,dispose(){T=true,m&&clearInterval(m),s?.close();}}}export{B as a};//# sourceMappingURL=chunk-N4IP63GR.js.map
|
|
2
|
+
//# sourceMappingURL=chunk-N4IP63GR.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/offline.ts"],"names":["openDB","name","version","resolve","reject","request","db","idbGetAll","store","req","idbPut","key","value","tx","idbDelete","idbClear","createOfflineStore","options","keyField","items","signal","pendingOps","syncing","online","pending","computed","syncTimer","disposed","syncNow","init","stored","ops","interval","getKey","item","put","list","idx","i","next","queueOp","remove","op","fetchFn","serverResponse","serverItems","partial","existing"],"mappings":"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","file":"chunk-N4IP63GR.js","sourcesContent":["/**\n * Offline-first store with IndexedDB persistence and background sync.\n *\n * Data persists across page reloads. Changes made offline queue up\n * and sync automatically when connection returns. Conflict resolution\n * via configurable strategies (last-write-wins, merge, custom).\n *\n * ```ts\n * const todos = createOfflineStore('todos', {\n * sync: { url: '/api/todos', strategy: 'last-write-wins' },\n * });\n *\n * todos.add({ id: '1', text: 'Buy milk', done: false });\n * todos.items(); // reactive list\n * todos.syncing(); // boolean\n * todos.pending(); // number of unsynced changes\n * ```\n */\n\nimport { signal, computed } from './signals.js';\nimport type { Signal, ReadonlySignal } from './signals.js';\n\n// =========================================================================\n// Types\n// =========================================================================\n\nexport type ConflictStrategy = 'last-write-wins' | 'client-wins' | 'server-wins' | 'manual';\n\nexport interface OfflineStoreOptions<T> {\n /** Sync configuration */\n sync?: {\n /** Server URL for sync */\n url: string;\n /** Conflict resolution strategy (default: 'last-write-wins') */\n strategy?: ConflictStrategy;\n /** Sync interval in ms (default: 30000) */\n interval?: number;\n /** Custom fetch */\n fetch?: typeof globalThis.fetch;\n /** Auth headers */\n headers?: Record<string, string>;\n };\n /** Key field for items (default: 'id') */\n keyField?: string;\n /** Version for schema migrations */\n version?: number;\n}\n\nexport interface OfflineStore<T extends Record<string, unknown>> {\n /** All items (reactive) */\n items: ReadonlySignal<T[]>;\n /** Get a single item by key */\n get(key: string): T | undefined;\n /** Add or update an item */\n put(item: T): void;\n /** Add a new item */\n add(item: T): void;\n /** Update an existing item */\n update(key: string, partial: Partial<T>): void;\n /** Remove an item by key */\n remove(key: string): void;\n /** Clear all items */\n clear(): void;\n /** Number of unsynced changes */\n pending: ReadonlySignal<number>;\n /** Whether sync is in progress */\n syncing: ReadonlySignal<boolean>;\n /** Whether online */\n online: ReadonlySignal<boolean>;\n /** Force a sync now */\n sync(): Promise<void>;\n /** Dispose the store (stop sync, close DB) */\n dispose(): void;\n}\n\n/** An operation in the change queue */\ninterface PendingOp<T> {\n type: 'put' | 'delete';\n key: string;\n value?: T;\n timestamp: number;\n}\n\n// =========================================================================\n// IndexedDB wrapper\n// =========================================================================\n\nasync function openDB(name: string, version = 1): Promise<IDBDatabase> {\n return new Promise((resolve, reject) => {\n const request = indexedDB.open(name, version);\n request.onupgradeneeded = () => {\n const db = request.result;\n if (!db.objectStoreNames.contains('items')) {\n db.createObjectStore('items');\n }\n if (!db.objectStoreNames.contains('pending')) {\n db.createObjectStore('pending', { autoIncrement: true });\n }\n };\n request.onsuccess = () => resolve(request.result);\n request.onerror = () => reject(request.error);\n });\n}\n\nasync function idbGetAll<T>(db: IDBDatabase, store: string): Promise<T[]> {\n return new Promise((resolve, reject) => {\n const tx = db.transaction(store, 'readonly');\n const req = tx.objectStore(store).getAll();\n req.onsuccess = () => resolve(req.result);\n req.onerror = () => reject(req.error);\n });\n}\n\nasync function idbPut(db: IDBDatabase, store: string, key: string, value: unknown): Promise<void> {\n return new Promise((resolve, reject) => {\n const tx = db.transaction(store, 'readwrite');\n tx.objectStore(store).put(value, key);\n tx.oncomplete = () => resolve();\n tx.onerror = () => reject(tx.error);\n });\n}\n\nasync function idbDelete(db: IDBDatabase, store: string, key: string): Promise<void> {\n return new Promise((resolve, reject) => {\n const tx = db.transaction(store, 'readwrite');\n tx.objectStore(store).delete(key);\n tx.oncomplete = () => resolve();\n tx.onerror = () => reject(tx.error);\n });\n}\n\nasync function idbClear(db: IDBDatabase, store: string): Promise<void> {\n return new Promise((resolve, reject) => {\n const tx = db.transaction(store, 'readwrite');\n tx.objectStore(store).clear();\n tx.oncomplete = () => resolve();\n tx.onerror = () => reject(tx.error);\n });\n}\n\n// =========================================================================\n// createOfflineStore\n// =========================================================================\n\n/**\n * Create an offline-first store backed by IndexedDB.\n */\nexport function createOfflineStore<T extends Record<string, unknown>>(\n name: string,\n options: OfflineStoreOptions<T> = {},\n): OfflineStore<T> {\n const keyField = options.keyField ?? 'id';\n const items = signal<T[]>([]);\n const pendingOps = signal<PendingOp<T>[]>([]);\n const syncing = signal(false);\n const online = signal(typeof navigator !== 'undefined' ? navigator.onLine : true);\n const pending = computed(() => pendingOps().length);\n\n let db: IDBDatabase | null = null;\n let syncTimer: ReturnType<typeof setInterval> | null = null;\n let disposed = false;\n\n // Online/offline tracking\n if (typeof window !== 'undefined') {\n window.addEventListener('online', () => {\n online.set(true);\n syncNow();\n });\n window.addEventListener('offline', () => online.set(false));\n }\n\n // Initialize — load from IndexedDB\n async function init(): Promise<void> {\n if (typeof indexedDB === 'undefined') return;\n try {\n db = await openDB(`akash-offline-${name}`, options.version ?? 1);\n const stored = await idbGetAll<T>(db, 'items');\n items.set(stored);\n const ops = await idbGetAll<PendingOp<T>>(db, 'pending');\n pendingOps.set(ops);\n } catch { /* IndexedDB not available */ }\n }\n\n init();\n\n // Start periodic sync\n if (options.sync) {\n const interval = options.sync.interval ?? 30000;\n syncTimer = setInterval(() => {\n if (online() && pending() > 0 && !syncing()) {\n syncNow();\n }\n }, interval);\n }\n\n function getKey(item: T): string {\n return String((item as any)[keyField]);\n }\n\n function put(item: T): void {\n const key = getKey(item);\n items.update((list) => {\n const idx = list.findIndex((i) => getKey(i) === key);\n if (idx !== -1) {\n const next = [...list];\n next[idx] = item;\n return next;\n }\n return [...list, item];\n });\n\n queueOp({ type: 'put', key, value: item, timestamp: Date.now() });\n if (db) idbPut(db, 'items', key, item);\n }\n\n function remove(key: string): void {\n items.update((list) => list.filter((i) => getKey(i) !== key));\n queueOp({ type: 'delete', key, timestamp: Date.now() });\n if (db) idbDelete(db, 'items', key);\n }\n\n function queueOp(op: PendingOp<T>): void {\n pendingOps.update((ops) => [...ops, op]);\n if (db) {\n const tx = db.transaction('pending', 'readwrite');\n tx.objectStore('pending').add(op);\n }\n }\n\n async function syncNow(): Promise<void> {\n if (!options.sync || syncing() || disposed) return;\n const ops = pendingOps();\n if (ops.length === 0) return;\n\n syncing.set(true);\n const fetchFn = options.sync.fetch ?? globalThis.fetch.bind(globalThis);\n\n try {\n const response = await fetchFn(options.sync.url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n ...options.sync.headers,\n },\n body: JSON.stringify({ ops }),\n });\n\n if (response.ok) {\n pendingOps.set([]);\n if (db) await idbClear(db, 'pending');\n\n // Fetch latest server state\n const serverResponse = await fetchFn(options.sync.url, {\n headers: options.sync.headers,\n });\n if (serverResponse.ok) {\n const serverItems = await serverResponse.json() as T[];\n items.set(serverItems);\n // Update IndexedDB\n if (db) {\n await idbClear(db, 'items');\n for (const item of serverItems) {\n await idbPut(db, 'items', getKey(item), item);\n }\n }\n }\n }\n } catch { /* Sync failed — ops stay queued */ }\n finally {\n syncing.set(false);\n }\n }\n\n return {\n items: () => items(),\n get(key: string) { return items().find((i) => getKey(i) === key); },\n put,\n add: put,\n update(key: string, partial: Partial<T>) {\n const existing = items().find((i) => getKey(i) === key);\n if (existing) put({ ...existing, ...partial });\n },\n remove,\n clear() {\n items.set([]);\n pendingOps.set([]);\n if (db) {\n idbClear(db, 'items');\n idbClear(db, 'pending');\n }\n },\n pending,\n syncing: () => syncing(),\n online: () => online(),\n sync: syncNow,\n dispose() {\n disposed = true;\n if (syncTimer) clearInterval(syncTimer);\n db?.close();\n },\n };\n}\n"]}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import {c}from'./chunk-4K6DIB7A.js';var g=class{entry;constructor(e,n){this.entry={value:e,timestamp:Date.now(),peerId:n};}get value(){return this.entry.value}get timestamp(){return this.entry.timestamp}set(e,n){let o=Date.now();return n===this.entry.peerId||o>this.entry.timestamp||o===this.entry.timestamp&&n>this.entry.peerId?(this.entry={value:e,timestamp:Math.max(o,this.entry.timestamp+1),peerId:n},true):false}merge(e){return e.timestamp>this.entry.timestamp||e.timestamp===this.entry.timestamp&&e.peerId>this.entry.peerId?(this.entry=e,true):false}toEntry(){return {...this.entry}}};function I(i){let e=null,n=[],o=[];return {send(t){e?.send(JSON.stringify({type:"op",room:i.room,...t}));},onReceive(t){return n.push(t),()=>{let s=n.indexOf(t);s!==-1&&n.splice(s,1);}},onPresence(t){return o.push(t),()=>{let s=o.indexOf(t);s!==-1&&o.splice(s,1);}},sendPresence(t){e?.send(JSON.stringify({type:"presence",room:i.room,data:t}));},connect(){e=new WebSocket(i.url,i.protocols),e.onmessage=t=>{try{let s=JSON.parse(t.data);if(s.type==="op")for(let p of n)p(s);else if(s.type==="presence")for(let p of o)p(s.peerId,s.data);}catch{}},e.onopen=()=>{e?.send(JSON.stringify({type:"join",room:i.room}));};},disconnect(){e?.close(),e=null;}}}function h(){let i=[];return {send(e){for(let n of i)n(e);},onReceive(e){return i.push(e),()=>{let n=i.indexOf(e);n!==-1&&i.splice(n,1);}},connect(){},disconnect(){}}}var w=0;function O(i,e,n={}){let o=n.peerId??`peer-${++w}-${Date.now()}`,t=n.transport??h(),s=new Map,p={};for(let[r,c$1]of Object.entries(e))s.set(r,new g(c$1,o)),p[r]=c(c$1);let l={};for(let r of Object.keys(e)){let c=p[r],y=s.get(r),a=(()=>c());a.set=u=>{y.set(u,o),c.set(u),t.send({type:"set",key:r,value:u,timestamp:y.timestamp,peerId:o});},a.update=u=>{a.set(u(c()));},a.peek=()=>c.peek(),l[r]=a;}let S=c([]),m=c(false),k=c({}),f=c(new Map),v=t.onReceive(r=>{r.type==="set"&&s.has(r.key)&&s.get(r.key).merge({value:r.value,timestamp:r.timestamp,peerId:r.peerId})&&p[r.key].set(r.value);}),T=t.onPresence?.((r,c)=>{f.update(y=>{let a=new Map(y);return a.set(r,c),a});});return {state:l,peers:()=>S(),presence:k,peerPresence:()=>f(),peerId:o,connected:()=>m(),connect(){t.connect(),m.set(true);},disconnect(){t.disconnect(),m.set(false);},dispose(){v(),T?.(),t.disconnect();}}}export{g as a,I as b,h as c,O as d};//# sourceMappingURL=chunk-PEDMDFZM.js.map
|
|
2
|
+
//# sourceMappingURL=chunk-PEDMDFZM.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/sync.ts"],"names":["LWWRegister","initialValue","peerId","value","ts","remote","createWebSocketTransport","options","ws","opHandlers","presenceHandlers","op","handler","i","data","e","msg","h","createLocalTransport","peerIdCounter","createSync","roomId","initialState","transport","registers","stateSignals","key","signal","state","original","register","proxy","fn","peers","connected","presence","peerPresenceMap","unsubOps","unsubPresence","remotePeerId","map","next"],"mappings":"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","file":"chunk-PEDMDFZM.js","sourcesContent":["/**\n * Collaborative signals with CRDT.\n *\n * Make any signal multiplayer with one line. Multiple users can\n * edit the same state simultaneously with automatic conflict\n * resolution via Last-Writer-Wins Register and Operation-based CRDTs.\n *\n * ```ts\n * const doc = createSync('doc-123', {\n * title: '',\n * blocks: [],\n * cursor: { x: 0, y: 0 },\n * });\n *\n * doc.state.title.set('Hello'); // syncs to all peers\n * doc.peers(); // list of connected users\n * doc.presence.set({ cursor: { x: 10, y: 20 } });\n * ```\n */\n\nimport { signal, computed } from './signals.js';\nimport type { Signal, ReadonlySignal } from './signals.js';\n\n// =========================================================================\n// CRDT — Last-Writer-Wins Register\n// =========================================================================\n\nexport interface LWWEntry<T> {\n value: T;\n timestamp: number;\n peerId: string;\n}\n\n/**\n * Last-Writer-Wins Register — simplest CRDT for single values.\n * The write with the highest timestamp wins on conflict.\n */\nexport class LWWRegister<T> {\n private entry: LWWEntry<T>;\n\n constructor(initialValue: T, peerId: string) {\n this.entry = { value: initialValue, timestamp: Date.now(), peerId };\n }\n\n get value(): T {\n return this.entry.value;\n }\n\n get timestamp(): number {\n return this.entry.timestamp;\n }\n\n set(value: T, peerId: string): boolean {\n const ts = Date.now();\n // Local writes always succeed (same peer always advances its own state).\n // Cross-peer conflicts resolve by highest timestamp, then peerId tiebreak.\n if (\n peerId === this.entry.peerId ||\n ts > this.entry.timestamp ||\n (ts === this.entry.timestamp && peerId > this.entry.peerId)\n ) {\n this.entry = { value, timestamp: Math.max(ts, this.entry.timestamp + 1), peerId };\n return true;\n }\n return false;\n }\n\n merge(remote: LWWEntry<T>): boolean {\n if (\n remote.timestamp > this.entry.timestamp ||\n (remote.timestamp === this.entry.timestamp && remote.peerId > this.entry.peerId)\n ) {\n this.entry = remote;\n return true;\n }\n return false;\n }\n\n toEntry(): LWWEntry<T> {\n return { ...this.entry };\n }\n}\n\n// =========================================================================\n// Operation log for list CRDTs\n// =========================================================================\n\nexport type SyncOp =\n | { type: 'set'; key: string; value: unknown; timestamp: number; peerId: string }\n | { type: 'insert'; key: string; index: number; value: unknown; timestamp: number; peerId: string }\n | { type: 'delete'; key: string; index: number; timestamp: number; peerId: string };\n\n// =========================================================================\n// Sync transport interface\n// =========================================================================\n\nexport interface SyncTransport {\n /** Send an operation to peers */\n send(op: SyncOp): void;\n /** Listen for operations from peers */\n onReceive(handler: (op: SyncOp) => void): () => void;\n /** Listen for peer presence updates */\n onPresence?(handler: (peerId: string, data: unknown) => void): () => void;\n /** Send presence data */\n sendPresence?(data: unknown): void;\n /** Connect to the sync channel */\n connect(): void;\n /** Disconnect */\n disconnect(): void;\n}\n\n// =========================================================================\n// WebSocket transport\n// =========================================================================\n\nexport interface WebSocketTransportOptions {\n url: string;\n room: string;\n protocols?: string | string[];\n}\n\nexport function createWebSocketTransport(options: WebSocketTransportOptions): SyncTransport {\n let ws: WebSocket | null = null;\n const opHandlers: Array<(op: SyncOp) => void> = [];\n const presenceHandlers: Array<(peerId: string, data: unknown) => void> = [];\n\n return {\n send(op: SyncOp) {\n ws?.send(JSON.stringify({ type: 'op', room: options.room, ...op }));\n },\n onReceive(handler) {\n opHandlers.push(handler);\n return () => {\n const i = opHandlers.indexOf(handler);\n if (i !== -1) opHandlers.splice(i, 1);\n };\n },\n onPresence(handler) {\n presenceHandlers.push(handler);\n return () => {\n const i = presenceHandlers.indexOf(handler);\n if (i !== -1) presenceHandlers.splice(i, 1);\n };\n },\n sendPresence(data) {\n ws?.send(JSON.stringify({ type: 'presence', room: options.room, data }));\n },\n connect() {\n ws = new WebSocket(options.url, options.protocols);\n ws.onmessage = (e) => {\n try {\n const msg = JSON.parse(e.data);\n if (msg.type === 'op') {\n for (const h of opHandlers) h(msg);\n } else if (msg.type === 'presence') {\n for (const h of presenceHandlers) h(msg.peerId, msg.data);\n }\n } catch { /* ignore parse errors */ }\n };\n ws.onopen = () => {\n ws?.send(JSON.stringify({ type: 'join', room: options.room }));\n };\n },\n disconnect() {\n ws?.close();\n ws = null;\n },\n };\n}\n\n// =========================================================================\n// In-memory transport (for testing / single-tab)\n// =========================================================================\n\nexport function createLocalTransport(): SyncTransport {\n const opHandlers: Array<(op: SyncOp) => void> = [];\n return {\n send(op) {\n for (const h of opHandlers) h(op);\n },\n onReceive(handler) {\n opHandlers.push(handler);\n return () => {\n const i = opHandlers.indexOf(handler);\n if (i !== -1) opHandlers.splice(i, 1);\n };\n },\n connect() {},\n disconnect() {},\n };\n}\n\n// =========================================================================\n// createSync — the main API\n// =========================================================================\n\nexport interface SyncOptions {\n /** Transport for sending/receiving operations */\n transport?: SyncTransport;\n /** Unique peer ID (default: random) */\n peerId?: string;\n}\n\nexport interface SyncDoc<T extends Record<string, unknown>> {\n /** Reactive synced state — each key is a Signal */\n state: { [K in keyof T]: Signal<T[K]> };\n /** Connected peers (reactive) */\n peers: ReadonlySignal<PeerInfo[]>;\n /** Local presence data */\n presence: Signal<Record<string, unknown>>;\n /** Peer presence map (reactive) */\n peerPresence: ReadonlySignal<Map<string, unknown>>;\n /** This peer's ID */\n peerId: string;\n /** Whether connected */\n connected: ReadonlySignal<boolean>;\n /** Connect to the sync channel */\n connect(): void;\n /** Disconnect */\n disconnect(): void;\n /** Dispose the sync doc */\n dispose(): void;\n}\n\nexport interface PeerInfo {\n id: string;\n joinedAt: number;\n}\n\nlet peerIdCounter = 0;\n\n/**\n * Create a collaborative synced document.\n *\n * ```ts\n * const doc = createSync('room-1', { title: '', count: 0 }, {\n * transport: createWebSocketTransport({ url: 'wss://sync.example.com', room: 'room-1' }),\n * });\n *\n * doc.state.title.set('Hello'); // auto-syncs to all peers\n * doc.peers(); // connected users\n * ```\n */\nexport function createSync<T extends Record<string, unknown>>(\n roomId: string,\n initialState: T,\n options: SyncOptions = {},\n): SyncDoc<T> {\n const peerId = options.peerId ?? `peer-${++peerIdCounter}-${Date.now()}`;\n const transport = options.transport ?? createLocalTransport();\n\n // Create CRDT registers and signals for each state key\n const registers = new Map<string, LWWRegister<unknown>>();\n const stateSignals: Record<string, Signal<unknown>> = {};\n\n for (const [key, value] of Object.entries(initialState)) {\n registers.set(key, new LWWRegister(value, peerId));\n stateSignals[key] = signal(value);\n }\n\n // Intercept signal.set to broadcast operations\n const state = {} as { [K in keyof T]: Signal<T[K]> };\n for (const key of Object.keys(initialState)) {\n const original = stateSignals[key];\n const register = registers.get(key)!;\n\n const proxy: Signal<any> = (() => original()) as any;\n proxy.set = (value: any) => {\n register.set(value, peerId);\n original.set(value);\n transport.send({\n type: 'set',\n key,\n value,\n timestamp: register.timestamp,\n peerId,\n });\n };\n proxy.update = (fn: (prev: any) => any) => {\n proxy.set(fn(original()));\n };\n proxy.peek = () => original.peek();\n\n (state as any)[key] = proxy;\n }\n\n // Peers\n const peers = signal<PeerInfo[]>([]);\n const connected = signal(false);\n const presence = signal<Record<string, unknown>>({});\n const peerPresenceMap = signal(new Map<string, unknown>());\n\n // Listen for remote operations\n const unsubOps = transport.onReceive((op) => {\n if (op.type === 'set' && registers.has(op.key)) {\n const register = registers.get(op.key)!;\n const merged = register.merge({\n value: op.value,\n timestamp: op.timestamp,\n peerId: op.peerId,\n });\n if (merged) {\n stateSignals[op.key].set(op.value);\n }\n }\n });\n\n // Listen for presence\n const unsubPresence = transport.onPresence?.((remotePeerId, data) => {\n peerPresenceMap.update((map) => {\n const next = new Map(map);\n next.set(remotePeerId, data);\n return next;\n });\n });\n\n return {\n state,\n peers: () => peers(),\n presence,\n peerPresence: () => peerPresenceMap(),\n peerId,\n connected: () => connected(),\n connect() {\n transport.connect();\n connected.set(true);\n },\n disconnect() {\n transport.disconnect();\n connected.set(false);\n },\n dispose() {\n unsubOps();\n unsubPresence?.();\n transport.disconnect();\n },\n };\n}\n"]}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
function A(e,t,n={}){let{duration:r=300,easing:o="ease",delay:u=0,iterations:m=1,direction:d="normal",fill:s="forwards",onComplete:p}=n,c=[{},{}];for(let[y,h]of Object.entries(t)){let l=y==="y"?"translateY":y==="x"?"translateX":y;if(Array.isArray(h)){let[i,g]=h;l==="translateY"||l==="translateX"?(c[0].transform=`${l}(${typeof i=="number"?i+"px":i})`,c[1].transform=`${l}(${typeof g=="number"?g+"px":g})`):(c[0][l]=i,c[1][l]=g);}else c[1][l]=h;}let a=e.animate(c,{duration:r,easing:o,delay:u,iterations:m,direction:d,fill:s}),b=new Promise(y=>{a.onfinish=()=>{p?.(),y();};});return {play:()=>a.play(),pause:()=>a.pause(),cancel:()=>a.cancel(),reverse:()=>a.reverse(),finished:b}}function S(e,t,n={}){let{stagger:r=50,from:o="start",...u}=n,m=typeof e=="string"?Array.from(document.querySelectorAll(e)):e,d=[],s=m.length;return m.forEach((p,c)=>{let a=u.delay??0;switch(o){case "start":a+=c*r;break;case "end":a+=(s-1-c)*r;break;case "center":a+=Math.abs(Math.floor(s/2)-c)*r;break}d.push(A(p,t,{...u,delay:a}));}),d}async function M(e){for(let[t,n,r]of e)await A(t,n,r).finished;}async function w(e){let t=e.map(([n,r,o])=>A(n,r,o));await Promise.all(t.map(n=>n.finished));}function C(e,t,n={}){let{stiffness:r=100,damping:o=10,mass:u=1,threshold:m=.01,onComplete:d}=n,s={},p={},c=window.getComputedStyle(e);for(let i of Object.keys(t))s[i]=parseFloat(c.getPropertyValue(i))||0,p[i]=0;let a=true,b=0,y,h=new Promise(i=>{y=i;});function l(){if(!a)return;let i=true,g=1/60;for(let f of Object.keys(t)){let v=s[f]-t[f],O=-r*v,k=-o*p[f],P=(O+k)/u;p[f]+=P*g,s[f]+=p[f]*g,(Math.abs(p[f])>m||Math.abs(v)>m)&&(i=false);}if(x(e,s),i){for(let f of Object.keys(t))s[f]=t[f];x(e,s),a=false,d?.(),y();}else b=requestAnimationFrame(l);}return b=requestAnimationFrame(l),{play(){a||(a=true,l());},pause(){a=false,cancelAnimationFrame(b);},cancel(){a=false,cancelAnimationFrame(b);},reverse(){for(let i of Object.keys(t))p[i]=-p[i];},finished:h}}function x(e,t){let n=[];for(let[r,o]of Object.entries(t))switch(r){case "x":n.push(`translateX(${o}px)`);break;case "y":n.push(`translateY(${o}px)`);break;case "scale":n.push(`scale(${o})`);break;case "rotate":n.push(`rotate(${o}deg)`);break;case "opacity":e.style.opacity=String(o);break;default:e.style.setProperty(r,String(o));break}n.length>0&&(e.style.transform=n.join(" "));}function E(e){return e}function R(e,t={}){return {states:e,transitionTo(n,r,o){let u=e[r];if(!u)throw new Error(`Unknown animation state: ${r}`);let m={};for(let[d,s]of Object.entries(u))m[d]=s;return A(n,m,{...t,...o})}}}export{A as a,S as b,M as c,w as d,C as e,E as f,R as g};//# sourceMappingURL=chunk-Q3E2UVUK.js.map
|
|
2
|
+
//# sourceMappingURL=chunk-Q3E2UVUK.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/animate.ts"],"names":["animate","el","properties","options","duration","easing","delay","iterations","direction","fill","onComplete","keyframes","prop","value","cssProperty","from","to","animation","finished","resolve","animateStagger","selector","stagger","animOptions","elements","controls","count","i","animateSequence","steps","props","opts","animateGroup","c","animateSpring","target","stiffness","damping","mass","threshold","current","velocity","computed","animating","rafId","resolveFinished","step","allSettled","dt","displacement","springForce","dampingForce","acceleration","applySpringValues","values","transforms","frames","defineStates","states","defaultOptions","stateName","key"],"mappings":"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","file":"chunk-Q3E2UVUK.js","sourcesContent":["/**\n * Animation module.\n *\n * State-based animations, stagger, group, sequence, keyframes,\n * and spring physics. Goes far beyond CSS transitions.\n *\n * ```ts\n * const fadeIn = animate(el, { opacity: [0, 1] }, { duration: 300 });\n * const staggered = animateStagger('.item', { opacity: [0, 1], y: [20, 0] }, { stagger: 50 });\n * const spring = animateSpring(el, { scale: 1.2 }, { stiffness: 300, damping: 20 });\n * ```\n */\n\n// =========================================================================\n// Types\n// =========================================================================\n\nexport interface AnimationOptions {\n /** Duration in ms (default: 300) */\n duration?: number;\n /** Easing function or CSS easing string (default: 'ease') */\n easing?: string;\n /** Delay before animation starts in ms */\n delay?: number;\n /** Number of iterations (Infinity for loop) */\n iterations?: number;\n /** Direction: normal, reverse, alternate */\n direction?: PlaybackDirection;\n /** Fill mode */\n fill?: FillMode;\n /** Callback when animation completes */\n onComplete?: () => void;\n}\n\nexport interface StaggerOptions extends AnimationOptions {\n /** Delay between each element in ms */\n stagger?: number;\n /** Stagger from: 'start', 'center', 'end' */\n from?: 'start' | 'center' | 'end';\n}\n\nexport interface SpringOptions {\n /** Spring stiffness (default: 100) */\n stiffness?: number;\n /** Damping ratio (default: 10) */\n damping?: number;\n /** Mass (default: 1) */\n mass?: number;\n /** Velocity threshold to stop (default: 0.01) */\n threshold?: number;\n /** Callback when animation completes */\n onComplete?: () => void;\n}\n\nexport interface AnimationControl {\n /** Play the animation */\n play(): void;\n /** Pause the animation */\n pause(): void;\n /** Cancel the animation */\n cancel(): void;\n /** Reverse the animation */\n reverse(): void;\n /** Promise that resolves when animation completes */\n finished: Promise<void>;\n}\n\ntype PropertyValue = number | string | [number | string, number | string];\n\n// =========================================================================\n// animate() — Web Animations API wrapper\n// =========================================================================\n\n/**\n * Animate an element using the Web Animations API.\n *\n * ```ts\n * const ctrl = animate(el, {\n * opacity: [0, 1],\n * transform: ['translateY(20px)', 'translateY(0)'],\n * }, { duration: 300, easing: 'ease-out' });\n *\n * await ctrl.finished;\n * ```\n */\nexport function animate(\n el: HTMLElement,\n properties: Record<string, PropertyValue>,\n options: AnimationOptions = {},\n): AnimationControl {\n const {\n duration = 300,\n easing = 'ease',\n delay = 0,\n iterations = 1,\n direction = 'normal',\n fill = 'forwards',\n onComplete,\n } = options;\n\n // Build keyframes\n const keyframes: Keyframe[] = [{}, {}];\n for (const [prop, value] of Object.entries(properties)) {\n const cssProperty = prop === 'y' ? 'translateY'\n : prop === 'x' ? 'translateX'\n : prop;\n\n if (Array.isArray(value)) {\n const [from, to] = value;\n if (cssProperty === 'translateY' || cssProperty === 'translateX') {\n (keyframes[0] as any).transform = `${cssProperty}(${typeof from === 'number' ? from + 'px' : from})`;\n (keyframes[1] as any).transform = `${cssProperty}(${typeof to === 'number' ? to + 'px' : to})`;\n } else {\n (keyframes[0] as any)[cssProperty] = from;\n (keyframes[1] as any)[cssProperty] = to;\n }\n } else {\n (keyframes[1] as any)[cssProperty] = value;\n }\n }\n\n const animation = el.animate(keyframes, {\n duration,\n easing,\n delay,\n iterations,\n direction,\n fill,\n });\n\n const finished = new Promise<void>((resolve) => {\n animation.onfinish = () => {\n onComplete?.();\n resolve();\n };\n });\n\n return {\n play: () => animation.play(),\n pause: () => animation.pause(),\n cancel: () => animation.cancel(),\n reverse: () => animation.reverse(),\n finished,\n };\n}\n\n// =========================================================================\n// animateStagger() — staggered animations\n// =========================================================================\n\n/**\n * Animate multiple elements with staggered timing.\n *\n * ```ts\n * animateStagger('.list-item', {\n * opacity: [0, 1],\n * y: [20, 0],\n * }, { stagger: 50, duration: 300 });\n * ```\n */\nexport function animateStagger(\n selector: string | HTMLElement[],\n properties: Record<string, PropertyValue>,\n options: StaggerOptions = {},\n): AnimationControl[] {\n const { stagger = 50, from = 'start', ...animOptions } = options;\n\n const elements: HTMLElement[] = typeof selector === 'string'\n ? Array.from(document.querySelectorAll<HTMLElement>(selector))\n : selector;\n\n const controls: AnimationControl[] = [];\n const count = elements.length;\n\n elements.forEach((el, i) => {\n let delay = (animOptions.delay ?? 0);\n\n switch (from) {\n case 'start': delay += i * stagger; break;\n case 'end': delay += (count - 1 - i) * stagger; break;\n case 'center': delay += Math.abs(Math.floor(count / 2) - i) * stagger; break;\n }\n\n controls.push(animate(el, properties, { ...animOptions, delay }));\n });\n\n return controls;\n}\n\n// =========================================================================\n// animateSequence() — sequential animations\n// =========================================================================\n\n/**\n * Run animations in sequence, one after another.\n *\n * ```ts\n * await animateSequence([\n * [el1, { opacity: [0, 1] }, { duration: 200 }],\n * [el2, { opacity: [0, 1] }, { duration: 200 }],\n * ]);\n * ```\n */\nexport async function animateSequence(\n steps: Array<[HTMLElement, Record<string, PropertyValue>, AnimationOptions?]>,\n): Promise<void> {\n for (const [el, props, opts] of steps) {\n const ctrl = animate(el, props, opts);\n await ctrl.finished;\n }\n}\n\n// =========================================================================\n// animateGroup() — parallel animations\n// =========================================================================\n\n/**\n * Run multiple animations in parallel, wait for all to complete.\n */\nexport async function animateGroup(\n steps: Array<[HTMLElement, Record<string, PropertyValue>, AnimationOptions?]>,\n): Promise<void> {\n const controls = steps.map(([el, props, opts]) => animate(el, props, opts));\n await Promise.all(controls.map((c) => c.finished));\n}\n\n// =========================================================================\n// animateSpring() — spring physics animation\n// =========================================================================\n\n/**\n * Animate with spring physics (no CSS easing — uses requestAnimationFrame).\n *\n * ```ts\n * animateSpring(el, { scale: 1.2, rotate: 10 }, {\n * stiffness: 300,\n * damping: 20,\n * });\n * ```\n */\nexport function animateSpring(\n el: HTMLElement,\n target: Record<string, number>,\n options: SpringOptions = {},\n): AnimationControl {\n const {\n stiffness = 100,\n damping = 10,\n mass = 1,\n threshold = 0.01,\n onComplete,\n } = options;\n\n const current: Record<string, number> = {};\n const velocity: Record<string, number> = {};\n\n // Initialize from current computed values\n const computed = window.getComputedStyle(el);\n for (const prop of Object.keys(target)) {\n current[prop] = parseFloat(computed.getPropertyValue(prop)) || 0;\n velocity[prop] = 0;\n }\n\n let animating = true;\n let rafId = 0;\n\n let resolveFinished: () => void;\n const finished = new Promise<void>((resolve) => { resolveFinished = resolve; });\n\n function step(): void {\n if (!animating) return;\n\n let allSettled = true;\n const dt = 1 / 60; // assume 60fps\n\n for (const prop of Object.keys(target)) {\n const displacement = current[prop] - target[prop];\n const springForce = -stiffness * displacement;\n const dampingForce = -damping * velocity[prop];\n const acceleration = (springForce + dampingForce) / mass;\n\n velocity[prop] += acceleration * dt;\n current[prop] += velocity[prop] * dt;\n\n if (Math.abs(velocity[prop]) > threshold || Math.abs(displacement) > threshold) {\n allSettled = false;\n }\n }\n\n // Apply\n applySpringValues(el, current);\n\n if (allSettled) {\n // Snap to target\n for (const prop of Object.keys(target)) {\n current[prop] = target[prop];\n }\n applySpringValues(el, current);\n animating = false;\n onComplete?.();\n resolveFinished();\n } else {\n rafId = requestAnimationFrame(step);\n }\n }\n\n rafId = requestAnimationFrame(step);\n\n return {\n play() { if (!animating) { animating = true; step(); } },\n pause() { animating = false; cancelAnimationFrame(rafId); },\n cancel() { animating = false; cancelAnimationFrame(rafId); },\n reverse() {\n for (const prop of Object.keys(target)) {\n velocity[prop] = -velocity[prop];\n }\n },\n finished,\n };\n}\n\nfunction applySpringValues(el: HTMLElement, values: Record<string, number>): void {\n const transforms: string[] = [];\n for (const [prop, value] of Object.entries(values)) {\n switch (prop) {\n case 'x': transforms.push(`translateX(${value}px)`); break;\n case 'y': transforms.push(`translateY(${value}px)`); break;\n case 'scale': transforms.push(`scale(${value})`); break;\n case 'rotate': transforms.push(`rotate(${value}deg)`); break;\n case 'opacity': el.style.opacity = String(value); break;\n default: el.style.setProperty(prop, String(value)); break;\n }\n }\n if (transforms.length > 0) {\n el.style.transform = transforms.join(' ');\n }\n}\n\n// =========================================================================\n// Keyframes helper\n// =========================================================================\n\n/**\n * Define keyframes for multi-step animations.\n *\n * ```ts\n * const bounce = keyframes([\n * { offset: 0, transform: 'translateY(0)' },\n * { offset: 0.5, transform: 'translateY(-30px)' },\n * { offset: 1, transform: 'translateY(0)' },\n * ]);\n *\n * el.animate(bounce, { duration: 600 });\n * ```\n */\nexport function keyframes(frames: Keyframe[]): Keyframe[] {\n return frames;\n}\n\n// =========================================================================\n// State-based animations\n// =========================================================================\n\nexport interface AnimationState {\n [property: string]: string | number;\n}\n\n/**\n * Define state-based animations.\n *\n * ```ts\n * const toggle = defineStates({\n * open: { height: 'auto', opacity: 1 },\n * closed: { height: 0, opacity: 0 },\n * }, { duration: 300 });\n *\n * toggle.transitionTo(el, 'open');\n * toggle.transitionTo(el, 'closed');\n * ```\n */\nexport function defineStates(\n states: Record<string, AnimationState>,\n defaultOptions: AnimationOptions = {},\n) {\n return {\n states,\n transitionTo(el: HTMLElement, stateName: string, options?: AnimationOptions): AnimationControl {\n const target = states[stateName];\n if (!target) throw new Error(`Unknown animation state: ${stateName}`);\n\n const props: Record<string, PropertyValue> = {};\n for (const [key, value] of Object.entries(target)) {\n props[key] = value;\n }\n\n return animate(el, props, { ...defaultOptions, ...options });\n },\n };\n}\n"]}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import {c,d}from'./chunk-4K6DIB7A.js';function p(t){let n=c(t.initial),o=c(t.context??{}),C=c([t.initial]),g=d(()=>t.states[n()]?.type==="final"),v=d(()=>{let e=t.states[n()];return e?.on?Object.keys(e.on):[]}),u=t.states[t.initial];u?.entry&&u.entry({data:o(),event:""});function y(e){if(g())return;let T=n(),a=t.states[T];if(!a?.on)return;let i=a.on[e];if(!i)return;let s,d,l;if(typeof i=="string")s=i;else {let r=i;s=r.target,d=r.guard,l=r.action;}let x={data:o(),event:e};if(d&&!d(x))return;a.exit&&a.exit(x),l&&l(x),o.set(x.data),n.set(s),C.update(r=>[...r,s]);let S=t.states[s];S?.entry&&S.entry({data:o(),event:e});}function E(e){let T=t.states[n()];if(!T?.on)return false;let a=T.on[e];if(!a)return false;if(typeof a!="string"){let i=a;if(i.guard)return i.guard({data:o(),event:e})}return true}return {state:()=>n(),context:()=>o(),send:y,matches:e=>n()===e,done:g,reset(){n.set(t.initial),o.set(t.context??{}),C.set([t.initial]);},history:()=>C(),can:E,nextEvents:v}}export{p as a};//# sourceMappingURL=chunk-RRB7VGW7.js.map
|
|
2
|
+
//# sourceMappingURL=chunk-RRB7VGW7.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/machine.ts"],"names":["createMachine","config","currentState","signal","contextData","stateHistory","done","computed","nextEvents","stateCfg","initialStateCfg","send","event","state","transition","target","guard","action","t","ctx","h","targetCfg","can"],"mappings":"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","file":"chunk-RRB7VGW7.js","sourcesContent":["/**\n * State machines for complex UI flows.\n *\n * Finite state machines with typed states, events, guards,\n * actions, and reactive current state signal.\n *\n * ```ts\n * const checkout = createMachine({\n * initial: 'cart',\n * states: {\n * cart: { on: { CHECKOUT: 'shipping' } },\n * shipping: { on: { NEXT: 'payment', BACK: 'cart' } },\n * payment: { on: { PAY: 'processing', BACK: 'shipping' } },\n * processing: { on: { SUCCESS: 'complete', FAIL: 'payment' } },\n * complete: { type: 'final' },\n * },\n * });\n *\n * checkout.state(); // 'cart'\n * checkout.send('CHECKOUT');\n * checkout.state(); // 'shipping'\n * checkout.matches('shipping'); // true\n * ```\n */\n\nimport { signal, computed } from './signals.js';\nimport type { ReadonlySignal } from './signals.js';\n\n// =========================================================================\n// Types\n// =========================================================================\n\nexport interface MachineConfig<TState extends string, TEvent extends string, TContext = unknown> {\n /** Initial state */\n initial: TState;\n /** Initial context data */\n context?: TContext;\n /** State definitions */\n states: Record<TState, StateConfig<TState, TEvent, TContext>>;\n}\n\nexport interface StateConfig<TState extends string, TEvent extends string, TContext = unknown> {\n /** Transitions: event → target state */\n on?: Partial<Record<TEvent, TState | TransitionConfig<TState, TEvent, TContext>>>;\n /** Entry action — runs when entering this state */\n entry?: (ctx: MachineContext<TContext>) => void;\n /** Exit action — runs when leaving this state */\n exit?: (ctx: MachineContext<TContext>) => void;\n /** Final state — machine stops accepting events */\n type?: 'final';\n}\n\nexport interface TransitionConfig<TState extends string, TEvent extends string, TContext = unknown> {\n /** Target state */\n target: TState;\n /** Guard — transition only if this returns true */\n guard?: (ctx: MachineContext<TContext>) => boolean;\n /** Action — runs during the transition */\n action?: (ctx: MachineContext<TContext>) => void;\n}\n\nexport interface MachineContext<TContext> {\n /** The context data (mutable) */\n data: TContext;\n /** The current event that triggered the transition */\n event: string;\n}\n\nexport interface Machine<TState extends string, TEvent extends string, TContext = unknown> {\n /** Current state (reactive signal) */\n state: ReadonlySignal<TState>;\n /** Context data (reactive signal) */\n context: ReadonlySignal<TContext>;\n /** Send an event to the machine */\n send(event: TEvent, payload?: Record<string, unknown>): void;\n /** Check if currently in a specific state */\n matches(state: TState): boolean;\n /** Whether the machine is in a final state */\n done: ReadonlySignal<boolean>;\n /** Reset to initial state */\n reset(): void;\n /** State history */\n history: ReadonlySignal<TState[]>;\n /** Can a specific event be sent in the current state? */\n can(event: TEvent): boolean;\n /** Get all possible events from current state */\n nextEvents: ReadonlySignal<TEvent[]>;\n}\n\n// =========================================================================\n// createMachine\n// =========================================================================\n\n/**\n * Create a finite state machine.\n */\nexport function createMachine<\n TState extends string,\n TEvent extends string,\n TContext = unknown,\n>(config: MachineConfig<TState, TEvent, TContext>): Machine<TState, TEvent, TContext> {\n const currentState = signal<TState>(config.initial);\n const contextData = signal<TContext>((config.context ?? {}) as TContext);\n const stateHistory = signal<TState[]>([config.initial]);\n\n const done = computed(() => {\n const stateCfg = config.states[currentState()];\n return stateCfg?.type === 'final';\n });\n\n const nextEvents = computed((): TEvent[] => {\n const stateCfg = config.states[currentState()];\n if (!stateCfg?.on) return [];\n return Object.keys(stateCfg.on) as TEvent[];\n });\n\n // Run entry action for initial state\n const initialStateCfg = config.states[config.initial];\n if (initialStateCfg?.entry) {\n initialStateCfg.entry({ data: contextData() as TContext, event: '' });\n }\n\n function send(event: TEvent): void {\n if (done()) return; // Final state — no more transitions\n\n const state = currentState();\n const stateCfg = config.states[state];\n if (!stateCfg?.on) return;\n\n const transition = stateCfg.on[event];\n if (!transition) return;\n\n let target: TState;\n let guard: ((ctx: MachineContext<TContext>) => boolean) | undefined;\n let action: ((ctx: MachineContext<TContext>) => void) | undefined;\n\n if (typeof transition === 'string') {\n target = transition;\n } else {\n const t = transition as TransitionConfig<TState, TEvent, TContext>;\n target = t.target;\n guard = t.guard;\n action = t.action;\n }\n\n const ctx: MachineContext<TContext> = {\n data: contextData() as TContext,\n event,\n };\n\n // Check guard\n if (guard && !guard(ctx)) return;\n\n // Exit action\n if (stateCfg.exit) {\n stateCfg.exit(ctx);\n }\n\n // Transition action\n if (action) {\n action(ctx);\n }\n\n // Update context if modified\n contextData.set(ctx.data);\n\n // Enter new state\n currentState.set(target);\n stateHistory.update((h) => [...h, target]);\n\n // Entry action for new state\n const targetCfg = config.states[target];\n if (targetCfg?.entry) {\n targetCfg.entry({ data: contextData() as TContext, event });\n }\n }\n\n function can(event: TEvent): boolean {\n const stateCfg = config.states[currentState()];\n if (!stateCfg?.on) return false;\n const transition = stateCfg.on[event];\n if (!transition) return false;\n\n if (typeof transition !== 'string') {\n const t = transition as TransitionConfig<TState, TEvent, TContext>;\n if (t.guard) {\n return t.guard({ data: contextData() as TContext, event });\n }\n }\n return true;\n }\n\n return {\n state: () => currentState(),\n context: () => contextData(),\n send,\n matches: (state: TState) => currentState() === state,\n done,\n reset() {\n currentState.set(config.initial);\n contextData.set((config.context ?? {}) as TContext);\n stateHistory.set([config.initial]);\n },\n history: () => stateHistory(),\n can,\n nextEvents,\n };\n}\n"]}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
'use strict';var chunkZE7R72IH_cjs=require('./chunk-ZE7R72IH.cjs');async function k(a,n=1){return new Promise((c,r)=>{let t=indexedDB.open(a,n);t.onupgradeneeded=()=>{let i=t.result;i.objectStoreNames.contains("items")||i.createObjectStore("items"),i.objectStoreNames.contains("pending")||i.createObjectStore("pending",{autoIncrement:true});},t.onsuccess=()=>c(t.result),t.onerror=()=>r(t.error);})}async function x(a,n){return new Promise((c,r)=>{let i=a.transaction(n,"readonly").objectStore(n).getAll();i.onsuccess=()=>c(i.result),i.onerror=()=>r(i.error);})}async function D(a,n,c,r){return new Promise((t,i)=>{let d=a.transaction(n,"readwrite");d.objectStore(n).put(r,c),d.oncomplete=()=>t(),d.onerror=()=>i(d.error);})}async function I(a,n,c){return new Promise((r,t)=>{let i=a.transaction(n,"readwrite");i.objectStore(n).delete(c),i.oncomplete=()=>r(),i.onerror=()=>t(i.error);})}async function y(a,n){return new Promise((c,r)=>{let t=a.transaction(n,"readwrite");t.objectStore(n).clear(),t.oncomplete=()=>c(),t.onerror=()=>r(t.error);})}function B(a,n={}){let c=n.keyField??"id",r=chunkZE7R72IH_cjs.c([]),t=chunkZE7R72IH_cjs.c([]),i=chunkZE7R72IH_cjs.c(false),d=chunkZE7R72IH_cjs.c(typeof navigator<"u"?navigator.onLine:true),b=chunkZE7R72IH_cjs.d(()=>t().length),s=null,m=null,T=false;typeof window<"u"&&(window.addEventListener("online",()=>{d.set(true),w();}),window.addEventListener("offline",()=>d.set(false)));async function O(){if(!(typeof indexedDB>"u"))try{s=await k(`akash-offline-${a}`,n.version??1);let e=await x(s,"items");r.set(e);let o=await x(s,"pending");t.set(o);}catch{}}if(O(),n.sync){let e=n.sync.interval??3e4;m=setInterval(()=>{d()&&b()>0&&!i()&&w();},e);}function g(e){return String(e[c])}function v(e){let o=g(e);r.update(l=>{let f=l.findIndex(u=>g(u)===o);if(f!==-1){let u=[...l];return u[f]=e,u}return [...l,e]}),S({type:"put",key:o,value:e,timestamp:Date.now()}),s&&D(s,"items",o,e);}function j(e){r.update(o=>o.filter(l=>g(l)!==e)),S({type:"delete",key:e,timestamp:Date.now()}),s&&I(s,"items",e);}function S(e){t.update(o=>[...o,e]),s&&s.transaction("pending","readwrite").objectStore("pending").add(e);}async function w(){if(!n.sync||i()||T)return;let e=t();if(e.length===0)return;i.set(true);let o=n.sync.fetch??globalThis.fetch.bind(globalThis);try{if((await o(n.sync.url,{method:"POST",headers:{"Content-Type":"application/json",...n.sync.headers},body:JSON.stringify({ops:e})})).ok){t.set([]),s&&await y(s,"pending");let f=await o(n.sync.url,{headers:n.sync.headers});if(f.ok){let u=await f.json();if(r.set(u),s){await y(s,"items");for(let P of u)await D(s,"items",g(P),P);}}}}catch{}finally{i.set(false);}}return {items:()=>r(),get(e){return r().find(o=>g(o)===e)},put:v,add:v,update(e,o){let l=r().find(f=>g(f)===e);l&&v({...l,...o});},remove:j,clear(){r.set([]),t.set([]),s&&(y(s,"items"),y(s,"pending"));},pending:b,syncing:()=>i(),online:()=>d(),sync:w,dispose(){T=true,m&&clearInterval(m),s?.close();}}}exports.a=B;//# sourceMappingURL=chunk-UVM6CYWX.cjs.map
|
|
2
|
+
//# sourceMappingURL=chunk-UVM6CYWX.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/offline.ts"],"names":["openDB","name","version","resolve","reject","request","db","idbGetAll","store","req","idbPut","key","value","tx","idbDelete","idbClear","createOfflineStore","options","keyField","items","signal","pendingOps","syncing","online","pending","computed","syncTimer","disposed","syncNow","init","stored","ops","interval","getKey","item","put","list","idx","i","next","queueOp","remove","op","fetchFn","serverResponse","serverItems","partial","existing"],"mappings":"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","file":"chunk-UVM6CYWX.cjs","sourcesContent":["/**\n * Offline-first store with IndexedDB persistence and background sync.\n *\n * Data persists across page reloads. Changes made offline queue up\n * and sync automatically when connection returns. Conflict resolution\n * via configurable strategies (last-write-wins, merge, custom).\n *\n * ```ts\n * const todos = createOfflineStore('todos', {\n * sync: { url: '/api/todos', strategy: 'last-write-wins' },\n * });\n *\n * todos.add({ id: '1', text: 'Buy milk', done: false });\n * todos.items(); // reactive list\n * todos.syncing(); // boolean\n * todos.pending(); // number of unsynced changes\n * ```\n */\n\nimport { signal, computed } from './signals.js';\nimport type { Signal, ReadonlySignal } from './signals.js';\n\n// =========================================================================\n// Types\n// =========================================================================\n\nexport type ConflictStrategy = 'last-write-wins' | 'client-wins' | 'server-wins' | 'manual';\n\nexport interface OfflineStoreOptions<T> {\n /** Sync configuration */\n sync?: {\n /** Server URL for sync */\n url: string;\n /** Conflict resolution strategy (default: 'last-write-wins') */\n strategy?: ConflictStrategy;\n /** Sync interval in ms (default: 30000) */\n interval?: number;\n /** Custom fetch */\n fetch?: typeof globalThis.fetch;\n /** Auth headers */\n headers?: Record<string, string>;\n };\n /** Key field for items (default: 'id') */\n keyField?: string;\n /** Version for schema migrations */\n version?: number;\n}\n\nexport interface OfflineStore<T extends Record<string, unknown>> {\n /** All items (reactive) */\n items: ReadonlySignal<T[]>;\n /** Get a single item by key */\n get(key: string): T | undefined;\n /** Add or update an item */\n put(item: T): void;\n /** Add a new item */\n add(item: T): void;\n /** Update an existing item */\n update(key: string, partial: Partial<T>): void;\n /** Remove an item by key */\n remove(key: string): void;\n /** Clear all items */\n clear(): void;\n /** Number of unsynced changes */\n pending: ReadonlySignal<number>;\n /** Whether sync is in progress */\n syncing: ReadonlySignal<boolean>;\n /** Whether online */\n online: ReadonlySignal<boolean>;\n /** Force a sync now */\n sync(): Promise<void>;\n /** Dispose the store (stop sync, close DB) */\n dispose(): void;\n}\n\n/** An operation in the change queue */\ninterface PendingOp<T> {\n type: 'put' | 'delete';\n key: string;\n value?: T;\n timestamp: number;\n}\n\n// =========================================================================\n// IndexedDB wrapper\n// =========================================================================\n\nasync function openDB(name: string, version = 1): Promise<IDBDatabase> {\n return new Promise((resolve, reject) => {\n const request = indexedDB.open(name, version);\n request.onupgradeneeded = () => {\n const db = request.result;\n if (!db.objectStoreNames.contains('items')) {\n db.createObjectStore('items');\n }\n if (!db.objectStoreNames.contains('pending')) {\n db.createObjectStore('pending', { autoIncrement: true });\n }\n };\n request.onsuccess = () => resolve(request.result);\n request.onerror = () => reject(request.error);\n });\n}\n\nasync function idbGetAll<T>(db: IDBDatabase, store: string): Promise<T[]> {\n return new Promise((resolve, reject) => {\n const tx = db.transaction(store, 'readonly');\n const req = tx.objectStore(store).getAll();\n req.onsuccess = () => resolve(req.result);\n req.onerror = () => reject(req.error);\n });\n}\n\nasync function idbPut(db: IDBDatabase, store: string, key: string, value: unknown): Promise<void> {\n return new Promise((resolve, reject) => {\n const tx = db.transaction(store, 'readwrite');\n tx.objectStore(store).put(value, key);\n tx.oncomplete = () => resolve();\n tx.onerror = () => reject(tx.error);\n });\n}\n\nasync function idbDelete(db: IDBDatabase, store: string, key: string): Promise<void> {\n return new Promise((resolve, reject) => {\n const tx = db.transaction(store, 'readwrite');\n tx.objectStore(store).delete(key);\n tx.oncomplete = () => resolve();\n tx.onerror = () => reject(tx.error);\n });\n}\n\nasync function idbClear(db: IDBDatabase, store: string): Promise<void> {\n return new Promise((resolve, reject) => {\n const tx = db.transaction(store, 'readwrite');\n tx.objectStore(store).clear();\n tx.oncomplete = () => resolve();\n tx.onerror = () => reject(tx.error);\n });\n}\n\n// =========================================================================\n// createOfflineStore\n// =========================================================================\n\n/**\n * Create an offline-first store backed by IndexedDB.\n */\nexport function createOfflineStore<T extends Record<string, unknown>>(\n name: string,\n options: OfflineStoreOptions<T> = {},\n): OfflineStore<T> {\n const keyField = options.keyField ?? 'id';\n const items = signal<T[]>([]);\n const pendingOps = signal<PendingOp<T>[]>([]);\n const syncing = signal(false);\n const online = signal(typeof navigator !== 'undefined' ? navigator.onLine : true);\n const pending = computed(() => pendingOps().length);\n\n let db: IDBDatabase | null = null;\n let syncTimer: ReturnType<typeof setInterval> | null = null;\n let disposed = false;\n\n // Online/offline tracking\n if (typeof window !== 'undefined') {\n window.addEventListener('online', () => {\n online.set(true);\n syncNow();\n });\n window.addEventListener('offline', () => online.set(false));\n }\n\n // Initialize — load from IndexedDB\n async function init(): Promise<void> {\n if (typeof indexedDB === 'undefined') return;\n try {\n db = await openDB(`akash-offline-${name}`, options.version ?? 1);\n const stored = await idbGetAll<T>(db, 'items');\n items.set(stored);\n const ops = await idbGetAll<PendingOp<T>>(db, 'pending');\n pendingOps.set(ops);\n } catch { /* IndexedDB not available */ }\n }\n\n init();\n\n // Start periodic sync\n if (options.sync) {\n const interval = options.sync.interval ?? 30000;\n syncTimer = setInterval(() => {\n if (online() && pending() > 0 && !syncing()) {\n syncNow();\n }\n }, interval);\n }\n\n function getKey(item: T): string {\n return String((item as any)[keyField]);\n }\n\n function put(item: T): void {\n const key = getKey(item);\n items.update((list) => {\n const idx = list.findIndex((i) => getKey(i) === key);\n if (idx !== -1) {\n const next = [...list];\n next[idx] = item;\n return next;\n }\n return [...list, item];\n });\n\n queueOp({ type: 'put', key, value: item, timestamp: Date.now() });\n if (db) idbPut(db, 'items', key, item);\n }\n\n function remove(key: string): void {\n items.update((list) => list.filter((i) => getKey(i) !== key));\n queueOp({ type: 'delete', key, timestamp: Date.now() });\n if (db) idbDelete(db, 'items', key);\n }\n\n function queueOp(op: PendingOp<T>): void {\n pendingOps.update((ops) => [...ops, op]);\n if (db) {\n const tx = db.transaction('pending', 'readwrite');\n tx.objectStore('pending').add(op);\n }\n }\n\n async function syncNow(): Promise<void> {\n if (!options.sync || syncing() || disposed) return;\n const ops = pendingOps();\n if (ops.length === 0) return;\n\n syncing.set(true);\n const fetchFn = options.sync.fetch ?? globalThis.fetch.bind(globalThis);\n\n try {\n const response = await fetchFn(options.sync.url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n ...options.sync.headers,\n },\n body: JSON.stringify({ ops }),\n });\n\n if (response.ok) {\n pendingOps.set([]);\n if (db) await idbClear(db, 'pending');\n\n // Fetch latest server state\n const serverResponse = await fetchFn(options.sync.url, {\n headers: options.sync.headers,\n });\n if (serverResponse.ok) {\n const serverItems = await serverResponse.json() as T[];\n items.set(serverItems);\n // Update IndexedDB\n if (db) {\n await idbClear(db, 'items');\n for (const item of serverItems) {\n await idbPut(db, 'items', getKey(item), item);\n }\n }\n }\n }\n } catch { /* Sync failed — ops stay queued */ }\n finally {\n syncing.set(false);\n }\n }\n\n return {\n items: () => items(),\n get(key: string) { return items().find((i) => getKey(i) === key); },\n put,\n add: put,\n update(key: string, partial: Partial<T>) {\n const existing = items().find((i) => getKey(i) === key);\n if (existing) put({ ...existing, ...partial });\n },\n remove,\n clear() {\n items.set([]);\n pendingOps.set([]);\n if (db) {\n idbClear(db, 'items');\n idbClear(db, 'pending');\n }\n },\n pending,\n syncing: () => syncing(),\n online: () => online(),\n sync: syncNow,\n dispose() {\n disposed = true;\n if (syncTimer) clearInterval(syncTimer);\n db?.close();\n },\n };\n}\n"]}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
'use strict';function A(e,t,n={}){let{duration:r=300,easing:o="ease",delay:u=0,iterations:m=1,direction:d="normal",fill:s="forwards",onComplete:p}=n,c=[{},{}];for(let[y,h]of Object.entries(t)){let l=y==="y"?"translateY":y==="x"?"translateX":y;if(Array.isArray(h)){let[i,g]=h;l==="translateY"||l==="translateX"?(c[0].transform=`${l}(${typeof i=="number"?i+"px":i})`,c[1].transform=`${l}(${typeof g=="number"?g+"px":g})`):(c[0][l]=i,c[1][l]=g);}else c[1][l]=h;}let a=e.animate(c,{duration:r,easing:o,delay:u,iterations:m,direction:d,fill:s}),b=new Promise(y=>{a.onfinish=()=>{p?.(),y();};});return {play:()=>a.play(),pause:()=>a.pause(),cancel:()=>a.cancel(),reverse:()=>a.reverse(),finished:b}}function S(e,t,n={}){let{stagger:r=50,from:o="start",...u}=n,m=typeof e=="string"?Array.from(document.querySelectorAll(e)):e,d=[],s=m.length;return m.forEach((p,c)=>{let a=u.delay??0;switch(o){case "start":a+=c*r;break;case "end":a+=(s-1-c)*r;break;case "center":a+=Math.abs(Math.floor(s/2)-c)*r;break}d.push(A(p,t,{...u,delay:a}));}),d}async function M(e){for(let[t,n,r]of e)await A(t,n,r).finished;}async function w(e){let t=e.map(([n,r,o])=>A(n,r,o));await Promise.all(t.map(n=>n.finished));}function C(e,t,n={}){let{stiffness:r=100,damping:o=10,mass:u=1,threshold:m=.01,onComplete:d}=n,s={},p={},c=window.getComputedStyle(e);for(let i of Object.keys(t))s[i]=parseFloat(c.getPropertyValue(i))||0,p[i]=0;let a=true,b=0,y,h=new Promise(i=>{y=i;});function l(){if(!a)return;let i=true,g=1/60;for(let f of Object.keys(t)){let v=s[f]-t[f],O=-r*v,k=-o*p[f],P=(O+k)/u;p[f]+=P*g,s[f]+=p[f]*g,(Math.abs(p[f])>m||Math.abs(v)>m)&&(i=false);}if(x(e,s),i){for(let f of Object.keys(t))s[f]=t[f];x(e,s),a=false,d?.(),y();}else b=requestAnimationFrame(l);}return b=requestAnimationFrame(l),{play(){a||(a=true,l());},pause(){a=false,cancelAnimationFrame(b);},cancel(){a=false,cancelAnimationFrame(b);},reverse(){for(let i of Object.keys(t))p[i]=-p[i];},finished:h}}function x(e,t){let n=[];for(let[r,o]of Object.entries(t))switch(r){case "x":n.push(`translateX(${o}px)`);break;case "y":n.push(`translateY(${o}px)`);break;case "scale":n.push(`scale(${o})`);break;case "rotate":n.push(`rotate(${o}deg)`);break;case "opacity":e.style.opacity=String(o);break;default:e.style.setProperty(r,String(o));break}n.length>0&&(e.style.transform=n.join(" "));}function E(e){return e}function R(e,t={}){return {states:e,transitionTo(n,r,o){let u=e[r];if(!u)throw new Error(`Unknown animation state: ${r}`);let m={};for(let[d,s]of Object.entries(u))m[d]=s;return A(n,m,{...t,...o})}}}exports.a=A;exports.b=S;exports.c=M;exports.d=w;exports.e=C;exports.f=E;exports.g=R;//# sourceMappingURL=chunk-Y5HEEST4.cjs.map
|
|
2
|
+
//# sourceMappingURL=chunk-Y5HEEST4.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/animate.ts"],"names":["animate","el","properties","options","duration","easing","delay","iterations","direction","fill","onComplete","keyframes","prop","value","cssProperty","from","to","animation","finished","resolve","animateStagger","selector","stagger","animOptions","elements","controls","count","i","animateSequence","steps","props","opts","animateGroup","c","animateSpring","target","stiffness","damping","mass","threshold","current","velocity","computed","animating","rafId","resolveFinished","step","allSettled","dt","displacement","springForce","dampingForce","acceleration","applySpringValues","values","transforms","frames","defineStates","states","defaultOptions","stateName","key"],"mappings":"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","file":"chunk-Y5HEEST4.cjs","sourcesContent":["/**\n * Animation module.\n *\n * State-based animations, stagger, group, sequence, keyframes,\n * and spring physics. Goes far beyond CSS transitions.\n *\n * ```ts\n * const fadeIn = animate(el, { opacity: [0, 1] }, { duration: 300 });\n * const staggered = animateStagger('.item', { opacity: [0, 1], y: [20, 0] }, { stagger: 50 });\n * const spring = animateSpring(el, { scale: 1.2 }, { stiffness: 300, damping: 20 });\n * ```\n */\n\n// =========================================================================\n// Types\n// =========================================================================\n\nexport interface AnimationOptions {\n /** Duration in ms (default: 300) */\n duration?: number;\n /** Easing function or CSS easing string (default: 'ease') */\n easing?: string;\n /** Delay before animation starts in ms */\n delay?: number;\n /** Number of iterations (Infinity for loop) */\n iterations?: number;\n /** Direction: normal, reverse, alternate */\n direction?: PlaybackDirection;\n /** Fill mode */\n fill?: FillMode;\n /** Callback when animation completes */\n onComplete?: () => void;\n}\n\nexport interface StaggerOptions extends AnimationOptions {\n /** Delay between each element in ms */\n stagger?: number;\n /** Stagger from: 'start', 'center', 'end' */\n from?: 'start' | 'center' | 'end';\n}\n\nexport interface SpringOptions {\n /** Spring stiffness (default: 100) */\n stiffness?: number;\n /** Damping ratio (default: 10) */\n damping?: number;\n /** Mass (default: 1) */\n mass?: number;\n /** Velocity threshold to stop (default: 0.01) */\n threshold?: number;\n /** Callback when animation completes */\n onComplete?: () => void;\n}\n\nexport interface AnimationControl {\n /** Play the animation */\n play(): void;\n /** Pause the animation */\n pause(): void;\n /** Cancel the animation */\n cancel(): void;\n /** Reverse the animation */\n reverse(): void;\n /** Promise that resolves when animation completes */\n finished: Promise<void>;\n}\n\ntype PropertyValue = number | string | [number | string, number | string];\n\n// =========================================================================\n// animate() — Web Animations API wrapper\n// =========================================================================\n\n/**\n * Animate an element using the Web Animations API.\n *\n * ```ts\n * const ctrl = animate(el, {\n * opacity: [0, 1],\n * transform: ['translateY(20px)', 'translateY(0)'],\n * }, { duration: 300, easing: 'ease-out' });\n *\n * await ctrl.finished;\n * ```\n */\nexport function animate(\n el: HTMLElement,\n properties: Record<string, PropertyValue>,\n options: AnimationOptions = {},\n): AnimationControl {\n const {\n duration = 300,\n easing = 'ease',\n delay = 0,\n iterations = 1,\n direction = 'normal',\n fill = 'forwards',\n onComplete,\n } = options;\n\n // Build keyframes\n const keyframes: Keyframe[] = [{}, {}];\n for (const [prop, value] of Object.entries(properties)) {\n const cssProperty = prop === 'y' ? 'translateY'\n : prop === 'x' ? 'translateX'\n : prop;\n\n if (Array.isArray(value)) {\n const [from, to] = value;\n if (cssProperty === 'translateY' || cssProperty === 'translateX') {\n (keyframes[0] as any).transform = `${cssProperty}(${typeof from === 'number' ? from + 'px' : from})`;\n (keyframes[1] as any).transform = `${cssProperty}(${typeof to === 'number' ? to + 'px' : to})`;\n } else {\n (keyframes[0] as any)[cssProperty] = from;\n (keyframes[1] as any)[cssProperty] = to;\n }\n } else {\n (keyframes[1] as any)[cssProperty] = value;\n }\n }\n\n const animation = el.animate(keyframes, {\n duration,\n easing,\n delay,\n iterations,\n direction,\n fill,\n });\n\n const finished = new Promise<void>((resolve) => {\n animation.onfinish = () => {\n onComplete?.();\n resolve();\n };\n });\n\n return {\n play: () => animation.play(),\n pause: () => animation.pause(),\n cancel: () => animation.cancel(),\n reverse: () => animation.reverse(),\n finished,\n };\n}\n\n// =========================================================================\n// animateStagger() — staggered animations\n// =========================================================================\n\n/**\n * Animate multiple elements with staggered timing.\n *\n * ```ts\n * animateStagger('.list-item', {\n * opacity: [0, 1],\n * y: [20, 0],\n * }, { stagger: 50, duration: 300 });\n * ```\n */\nexport function animateStagger(\n selector: string | HTMLElement[],\n properties: Record<string, PropertyValue>,\n options: StaggerOptions = {},\n): AnimationControl[] {\n const { stagger = 50, from = 'start', ...animOptions } = options;\n\n const elements: HTMLElement[] = typeof selector === 'string'\n ? Array.from(document.querySelectorAll<HTMLElement>(selector))\n : selector;\n\n const controls: AnimationControl[] = [];\n const count = elements.length;\n\n elements.forEach((el, i) => {\n let delay = (animOptions.delay ?? 0);\n\n switch (from) {\n case 'start': delay += i * stagger; break;\n case 'end': delay += (count - 1 - i) * stagger; break;\n case 'center': delay += Math.abs(Math.floor(count / 2) - i) * stagger; break;\n }\n\n controls.push(animate(el, properties, { ...animOptions, delay }));\n });\n\n return controls;\n}\n\n// =========================================================================\n// animateSequence() — sequential animations\n// =========================================================================\n\n/**\n * Run animations in sequence, one after another.\n *\n * ```ts\n * await animateSequence([\n * [el1, { opacity: [0, 1] }, { duration: 200 }],\n * [el2, { opacity: [0, 1] }, { duration: 200 }],\n * ]);\n * ```\n */\nexport async function animateSequence(\n steps: Array<[HTMLElement, Record<string, PropertyValue>, AnimationOptions?]>,\n): Promise<void> {\n for (const [el, props, opts] of steps) {\n const ctrl = animate(el, props, opts);\n await ctrl.finished;\n }\n}\n\n// =========================================================================\n// animateGroup() — parallel animations\n// =========================================================================\n\n/**\n * Run multiple animations in parallel, wait for all to complete.\n */\nexport async function animateGroup(\n steps: Array<[HTMLElement, Record<string, PropertyValue>, AnimationOptions?]>,\n): Promise<void> {\n const controls = steps.map(([el, props, opts]) => animate(el, props, opts));\n await Promise.all(controls.map((c) => c.finished));\n}\n\n// =========================================================================\n// animateSpring() — spring physics animation\n// =========================================================================\n\n/**\n * Animate with spring physics (no CSS easing — uses requestAnimationFrame).\n *\n * ```ts\n * animateSpring(el, { scale: 1.2, rotate: 10 }, {\n * stiffness: 300,\n * damping: 20,\n * });\n * ```\n */\nexport function animateSpring(\n el: HTMLElement,\n target: Record<string, number>,\n options: SpringOptions = {},\n): AnimationControl {\n const {\n stiffness = 100,\n damping = 10,\n mass = 1,\n threshold = 0.01,\n onComplete,\n } = options;\n\n const current: Record<string, number> = {};\n const velocity: Record<string, number> = {};\n\n // Initialize from current computed values\n const computed = window.getComputedStyle(el);\n for (const prop of Object.keys(target)) {\n current[prop] = parseFloat(computed.getPropertyValue(prop)) || 0;\n velocity[prop] = 0;\n }\n\n let animating = true;\n let rafId = 0;\n\n let resolveFinished: () => void;\n const finished = new Promise<void>((resolve) => { resolveFinished = resolve; });\n\n function step(): void {\n if (!animating) return;\n\n let allSettled = true;\n const dt = 1 / 60; // assume 60fps\n\n for (const prop of Object.keys(target)) {\n const displacement = current[prop] - target[prop];\n const springForce = -stiffness * displacement;\n const dampingForce = -damping * velocity[prop];\n const acceleration = (springForce + dampingForce) / mass;\n\n velocity[prop] += acceleration * dt;\n current[prop] += velocity[prop] * dt;\n\n if (Math.abs(velocity[prop]) > threshold || Math.abs(displacement) > threshold) {\n allSettled = false;\n }\n }\n\n // Apply\n applySpringValues(el, current);\n\n if (allSettled) {\n // Snap to target\n for (const prop of Object.keys(target)) {\n current[prop] = target[prop];\n }\n applySpringValues(el, current);\n animating = false;\n onComplete?.();\n resolveFinished();\n } else {\n rafId = requestAnimationFrame(step);\n }\n }\n\n rafId = requestAnimationFrame(step);\n\n return {\n play() { if (!animating) { animating = true; step(); } },\n pause() { animating = false; cancelAnimationFrame(rafId); },\n cancel() { animating = false; cancelAnimationFrame(rafId); },\n reverse() {\n for (const prop of Object.keys(target)) {\n velocity[prop] = -velocity[prop];\n }\n },\n finished,\n };\n}\n\nfunction applySpringValues(el: HTMLElement, values: Record<string, number>): void {\n const transforms: string[] = [];\n for (const [prop, value] of Object.entries(values)) {\n switch (prop) {\n case 'x': transforms.push(`translateX(${value}px)`); break;\n case 'y': transforms.push(`translateY(${value}px)`); break;\n case 'scale': transforms.push(`scale(${value})`); break;\n case 'rotate': transforms.push(`rotate(${value}deg)`); break;\n case 'opacity': el.style.opacity = String(value); break;\n default: el.style.setProperty(prop, String(value)); break;\n }\n }\n if (transforms.length > 0) {\n el.style.transform = transforms.join(' ');\n }\n}\n\n// =========================================================================\n// Keyframes helper\n// =========================================================================\n\n/**\n * Define keyframes for multi-step animations.\n *\n * ```ts\n * const bounce = keyframes([\n * { offset: 0, transform: 'translateY(0)' },\n * { offset: 0.5, transform: 'translateY(-30px)' },\n * { offset: 1, transform: 'translateY(0)' },\n * ]);\n *\n * el.animate(bounce, { duration: 600 });\n * ```\n */\nexport function keyframes(frames: Keyframe[]): Keyframe[] {\n return frames;\n}\n\n// =========================================================================\n// State-based animations\n// =========================================================================\n\nexport interface AnimationState {\n [property: string]: string | number;\n}\n\n/**\n * Define state-based animations.\n *\n * ```ts\n * const toggle = defineStates({\n * open: { height: 'auto', opacity: 1 },\n * closed: { height: 0, opacity: 0 },\n * }, { duration: 300 });\n *\n * toggle.transitionTo(el, 'open');\n * toggle.transitionTo(el, 'closed');\n * ```\n */\nexport function defineStates(\n states: Record<string, AnimationState>,\n defaultOptions: AnimationOptions = {},\n) {\n return {\n states,\n transitionTo(el: HTMLElement, stateName: string, options?: AnimationOptions): AnimationControl {\n const target = states[stateName];\n if (!target) throw new Error(`Unknown animation state: ${stateName}`);\n\n const props: Record<string, PropertyValue> = {};\n for (const [key, value] of Object.entries(target)) {\n props[key] = value;\n }\n\n return animate(el, props, { ...defaultOptions, ...options });\n },\n };\n}\n"]}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
'use strict';var chunkZE7R72IH_cjs=require('./chunk-ZE7R72IH.cjs');function p(t){let n=chunkZE7R72IH_cjs.c(t.initial),o=chunkZE7R72IH_cjs.c(t.context??{}),C=chunkZE7R72IH_cjs.c([t.initial]),g=chunkZE7R72IH_cjs.d(()=>t.states[n()]?.type==="final"),v=chunkZE7R72IH_cjs.d(()=>{let e=t.states[n()];return e?.on?Object.keys(e.on):[]}),u=t.states[t.initial];u?.entry&&u.entry({data:o(),event:""});function y(e){if(g())return;let T=n(),a=t.states[T];if(!a?.on)return;let i=a.on[e];if(!i)return;let s,d,l;if(typeof i=="string")s=i;else {let r=i;s=r.target,d=r.guard,l=r.action;}let x={data:o(),event:e};if(d&&!d(x))return;a.exit&&a.exit(x),l&&l(x),o.set(x.data),n.set(s),C.update(r=>[...r,s]);let S=t.states[s];S?.entry&&S.entry({data:o(),event:e});}function E(e){let T=t.states[n()];if(!T?.on)return false;let a=T.on[e];if(!a)return false;if(typeof a!="string"){let i=a;if(i.guard)return i.guard({data:o(),event:e})}return true}return {state:()=>n(),context:()=>o(),send:y,matches:e=>n()===e,done:g,reset(){n.set(t.initial),o.set(t.context??{}),C.set([t.initial]);},history:()=>C(),can:E,nextEvents:v}}exports.a=p;//# sourceMappingURL=chunk-YFCIWM3C.cjs.map
|
|
2
|
+
//# sourceMappingURL=chunk-YFCIWM3C.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/machine.ts"],"names":["createMachine","config","currentState","signal","contextData","stateHistory","done","computed","nextEvents","stateCfg","initialStateCfg","send","event","state","transition","target","guard","action","t","ctx","h","targetCfg","can"],"mappings":"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","file":"chunk-YFCIWM3C.cjs","sourcesContent":["/**\n * State machines for complex UI flows.\n *\n * Finite state machines with typed states, events, guards,\n * actions, and reactive current state signal.\n *\n * ```ts\n * const checkout = createMachine({\n * initial: 'cart',\n * states: {\n * cart: { on: { CHECKOUT: 'shipping' } },\n * shipping: { on: { NEXT: 'payment', BACK: 'cart' } },\n * payment: { on: { PAY: 'processing', BACK: 'shipping' } },\n * processing: { on: { SUCCESS: 'complete', FAIL: 'payment' } },\n * complete: { type: 'final' },\n * },\n * });\n *\n * checkout.state(); // 'cart'\n * checkout.send('CHECKOUT');\n * checkout.state(); // 'shipping'\n * checkout.matches('shipping'); // true\n * ```\n */\n\nimport { signal, computed } from './signals.js';\nimport type { ReadonlySignal } from './signals.js';\n\n// =========================================================================\n// Types\n// =========================================================================\n\nexport interface MachineConfig<TState extends string, TEvent extends string, TContext = unknown> {\n /** Initial state */\n initial: TState;\n /** Initial context data */\n context?: TContext;\n /** State definitions */\n states: Record<TState, StateConfig<TState, TEvent, TContext>>;\n}\n\nexport interface StateConfig<TState extends string, TEvent extends string, TContext = unknown> {\n /** Transitions: event → target state */\n on?: Partial<Record<TEvent, TState | TransitionConfig<TState, TEvent, TContext>>>;\n /** Entry action — runs when entering this state */\n entry?: (ctx: MachineContext<TContext>) => void;\n /** Exit action — runs when leaving this state */\n exit?: (ctx: MachineContext<TContext>) => void;\n /** Final state — machine stops accepting events */\n type?: 'final';\n}\n\nexport interface TransitionConfig<TState extends string, TEvent extends string, TContext = unknown> {\n /** Target state */\n target: TState;\n /** Guard — transition only if this returns true */\n guard?: (ctx: MachineContext<TContext>) => boolean;\n /** Action — runs during the transition */\n action?: (ctx: MachineContext<TContext>) => void;\n}\n\nexport interface MachineContext<TContext> {\n /** The context data (mutable) */\n data: TContext;\n /** The current event that triggered the transition */\n event: string;\n}\n\nexport interface Machine<TState extends string, TEvent extends string, TContext = unknown> {\n /** Current state (reactive signal) */\n state: ReadonlySignal<TState>;\n /** Context data (reactive signal) */\n context: ReadonlySignal<TContext>;\n /** Send an event to the machine */\n send(event: TEvent, payload?: Record<string, unknown>): void;\n /** Check if currently in a specific state */\n matches(state: TState): boolean;\n /** Whether the machine is in a final state */\n done: ReadonlySignal<boolean>;\n /** Reset to initial state */\n reset(): void;\n /** State history */\n history: ReadonlySignal<TState[]>;\n /** Can a specific event be sent in the current state? */\n can(event: TEvent): boolean;\n /** Get all possible events from current state */\n nextEvents: ReadonlySignal<TEvent[]>;\n}\n\n// =========================================================================\n// createMachine\n// =========================================================================\n\n/**\n * Create a finite state machine.\n */\nexport function createMachine<\n TState extends string,\n TEvent extends string,\n TContext = unknown,\n>(config: MachineConfig<TState, TEvent, TContext>): Machine<TState, TEvent, TContext> {\n const currentState = signal<TState>(config.initial);\n const contextData = signal<TContext>((config.context ?? {}) as TContext);\n const stateHistory = signal<TState[]>([config.initial]);\n\n const done = computed(() => {\n const stateCfg = config.states[currentState()];\n return stateCfg?.type === 'final';\n });\n\n const nextEvents = computed((): TEvent[] => {\n const stateCfg = config.states[currentState()];\n if (!stateCfg?.on) return [];\n return Object.keys(stateCfg.on) as TEvent[];\n });\n\n // Run entry action for initial state\n const initialStateCfg = config.states[config.initial];\n if (initialStateCfg?.entry) {\n initialStateCfg.entry({ data: contextData() as TContext, event: '' });\n }\n\n function send(event: TEvent): void {\n if (done()) return; // Final state — no more transitions\n\n const state = currentState();\n const stateCfg = config.states[state];\n if (!stateCfg?.on) return;\n\n const transition = stateCfg.on[event];\n if (!transition) return;\n\n let target: TState;\n let guard: ((ctx: MachineContext<TContext>) => boolean) | undefined;\n let action: ((ctx: MachineContext<TContext>) => void) | undefined;\n\n if (typeof transition === 'string') {\n target = transition;\n } else {\n const t = transition as TransitionConfig<TState, TEvent, TContext>;\n target = t.target;\n guard = t.guard;\n action = t.action;\n }\n\n const ctx: MachineContext<TContext> = {\n data: contextData() as TContext,\n event,\n };\n\n // Check guard\n if (guard && !guard(ctx)) return;\n\n // Exit action\n if (stateCfg.exit) {\n stateCfg.exit(ctx);\n }\n\n // Transition action\n if (action) {\n action(ctx);\n }\n\n // Update context if modified\n contextData.set(ctx.data);\n\n // Enter new state\n currentState.set(target);\n stateHistory.update((h) => [...h, target]);\n\n // Entry action for new state\n const targetCfg = config.states[target];\n if (targetCfg?.entry) {\n targetCfg.entry({ data: contextData() as TContext, event });\n }\n }\n\n function can(event: TEvent): boolean {\n const stateCfg = config.states[currentState()];\n if (!stateCfg?.on) return false;\n const transition = stateCfg.on[event];\n if (!transition) return false;\n\n if (typeof transition !== 'string') {\n const t = transition as TransitionConfig<TState, TEvent, TContext>;\n if (t.guard) {\n return t.guard({ data: contextData() as TContext, event });\n }\n }\n return true;\n }\n\n return {\n state: () => currentState(),\n context: () => contextData(),\n send,\n matches: (state: TState) => currentState() === state,\n done,\n reset() {\n currentState.set(config.initial);\n contextData.set((config.context ?? {}) as TContext);\n stateHistory.set([config.initial]);\n },\n history: () => stateHistory(),\n can,\n nextEvents,\n };\n}\n"]}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
'use strict';var r=new Set,c=new Set,i=false,f=0,a=false;function l(){if(!i){for(i=true,a=false;r.size>0||c.size>0;){if(r.size>0){let e=[...r].sort(b);r.clear();for(let u of e)u.run();}if(c.size>0){let e=[...c].sort(b);c.clear();for(let u of e)u.run();}}i=false;}}function p(e){e.isRender?r.add(e):c.add(e),f===0&&!i&&!a&&(a=true,queueMicrotask(l));}function g(e){f++;try{e();}finally{f--,f===0&&l();}}function b(e,u){return (e.depth??0)-(u.depth??0)}function y(){l();}var s=null;function w(e,u){let t={value:e,subscribers:new Set,equals:u?.equals??Object.is},n=()=>(h(t),t.value);return n.set=o=>{t.equals(t.value,o)||(t.value=o,d(t));},n.update=o=>{n.set(o(t.value));},n.peek=()=>t.value,n}function E(e,u){let t={_tag:"computed",fn:e,value:void 0,state:1,subscribers:new Set,sources:new Set,equals:u?.equals??Object.is};return ()=>(s&&(t.subscribers.add(s),"sources"in s&&s.sources.add(t)),t.state!==0&&S(t),t.value)}function S(e){for(let t of e.sources)t.subscribers.delete(e);e.sources.clear();let u=s;s=e;try{let t=e.fn(),n=e.value===void 0||!e.equals(e.value,t);e.value=t,e.state=0,n&&d(e);}finally{s=u;}}function k(e,u){let t={_tag:"effect",fn:e,cleanup:null,sources:new Set,disposed:false,isRender:u?.render??false,run(){v(t);}};return v(t),()=>{t.disposed=true,T(t);for(let n of t.sources)n.subscribers.delete(t);t.sources.clear();}}function v(e){if(e.disposed)return;if(e.sources.size>0){let t=false;for(let n of e.sources)if("_tag"in n&&n._tag==="computed"){if(n.state===1){let o=n.value;S(n),n.equals(o,n.value)||(t=true);}}else t=true;if(!t)return}T(e);for(let t of e.sources)t.subscribers.delete(e);e.sources.clear();let u=s;s=e;try{let t=e.fn();typeof t=="function"&&(e.cleanup=t);}finally{s=u;}}function T(e){e.cleanup&&(e.cleanup(),e.cleanup=null);}function q(e){let u=s;s=null;try{return e()}finally{s=u;}}function h(e){s&&(e.subscribers.add(s),"sources"in s&&s.sources.add(e));}function d(e){for(let u of e.subscribers)u._tag==="computed"?(u.state=1,d(u)):u._tag==="effect"&&p(u);}exports.a=g;exports.b=y;exports.c=w;exports.d=E;exports.e=k;exports.f=q;//# sourceMappingURL=chunk-ZE7R72IH.cjs.map
|
|
2
|
+
//# sourceMappingURL=chunk-ZE7R72IH.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/scheduler.ts","../src/signals.ts"],"names":["pendingRender","pendingUser","flushing","batchDepth","flushScheduled","flush","queue","byDepth","fx","scheduleEffect","batch","fn","a","b","flushSync","currentSubscriber","signal","initialValue","options","node","read","trackSubscriber","value","notifySubscribers","computed","recompute","source","prevSubscriber","newValue","changed","effect","runEffect","cleanupEffect","anyChanged","oldValue","result","untrack","prev","sub"],"mappings":"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","file":"chunk-ZE7R72IH.cjs","sourcesContent":["/**\n * Microtask-based effect scheduler with priority levels and deduplication.\n *\n * Render effects (DOM bindings) run before user effects to ensure\n * DOM is consistent before user-side effects execute.\n */\n\nexport interface ScheduledEffect {\n run(): void;\n isRender: boolean;\n /** Depth in the dependency graph (0 = root). Lower depth runs first. */\n depth?: number;\n}\n\nconst pendingRender = new Set<ScheduledEffect>();\nconst pendingUser = new Set<ScheduledEffect>();\nlet flushing = false;\nlet batchDepth = 0;\nlet flushScheduled = false;\n\nfunction flush(): void {\n if (flushing) return;\n flushing = true;\n flushScheduled = false;\n\n // Process render effects first, then user effects.\n // Effects may enqueue more effects during flush, so loop until empty.\n while (pendingRender.size > 0 || pendingUser.size > 0) {\n // Drain render effects (sorted by depth — parents before children)\n if (pendingRender.size > 0) {\n const queue = [...pendingRender].sort(byDepth);\n pendingRender.clear();\n for (const fx of queue) {\n fx.run();\n }\n }\n\n // Drain user effects (sorted by depth)\n if (pendingUser.size > 0) {\n const queue = [...pendingUser].sort(byDepth);\n pendingUser.clear();\n for (const fx of queue) {\n fx.run();\n }\n }\n }\n\n flushing = false;\n}\n\nexport function scheduleEffect(fx: ScheduledEffect): void {\n if (fx.isRender) {\n pendingRender.add(fx);\n } else {\n pendingUser.add(fx);\n }\n\n if (batchDepth === 0 && !flushing && !flushScheduled) {\n flushScheduled = true;\n queueMicrotask(flush);\n }\n}\n\n/**\n * Batch multiple signal writes — subscribers are notified only once\n * at the end of the batch.\n */\nexport function batch(fn: () => void): void {\n batchDepth++;\n try {\n fn();\n } finally {\n batchDepth--;\n if (batchDepth === 0) {\n flush();\n }\n }\n}\n\n/** Sort effects by depth (lower depth first = parents before children) */\nfunction byDepth(a: ScheduledEffect, b: ScheduledEffect): number {\n return (a.depth ?? 0) - (b.depth ?? 0);\n}\n\n/** Synchronously flush all pending effects. Useful for testing. */\nexport function flushSync(): void {\n flush();\n}\n","/**\n * Fine-grained reactivity system.\n *\n * Inspired by SolidJS/Preact Signals. Provides signal(), computed(),\n * effect(), and untrack() primitives with automatic dependency tracking\n * and glitch-free diamond dependency resolution.\n */\n\nimport { scheduleEffect, type ScheduledEffect } from './scheduler.js';\n\n// --- Tracking scope ---\n\ntype Subscriber = EffectNode | ComputedNode<unknown>;\n\nlet currentSubscriber: Subscriber | null = null;\n\n// --- Signal ---\n\nexport interface Signal<T> {\n /** Read the current value (tracks dependency if inside a reactive scope) */\n (): T;\n /** Set a new value */\n set(value: T): void;\n /** Update the value using the previous value */\n update(fn: (prev: T) => T): void;\n /** Read without tracking (no dependency registered) */\n peek(): T;\n}\n\nexport type ReadonlySignal<T> = () => T;\n\ninterface SignalNode<T> {\n value: T;\n subscribers: Set<Subscriber>;\n equals: (a: T, b: T) => boolean;\n}\n\nexport function signal<T>(\n initialValue: T,\n options?: { equals?: (a: T, b: T) => boolean },\n): Signal<T> {\n const node: SignalNode<T> = {\n value: initialValue,\n subscribers: new Set(),\n equals: options?.equals ?? Object.is,\n };\n\n const read = (): T => {\n trackSubscriber(node);\n return node.value;\n };\n\n read.set = (value: T): void => {\n if (node.equals(node.value, value)) return;\n node.value = value;\n notifySubscribers(node);\n };\n\n read.update = (fn: (prev: T) => T): void => {\n read.set(fn(node.value));\n };\n\n read.peek = (): T => node.value;\n\n return read;\n}\n\n// --- Computed ---\n\nconst enum ComputedState {\n Clean = 0,\n Dirty = 1,\n}\n\ninterface ComputedNode<T> {\n _tag: 'computed';\n fn: () => T;\n value: T | undefined;\n state: ComputedState;\n subscribers: Set<Subscriber>;\n sources: Set<SignalNode<unknown> | ComputedNode<unknown>>;\n equals: (a: T, b: T) => boolean;\n}\n\nexport function computed<T>(\n fn: () => T,\n options?: { equals?: (a: T, b: T) => boolean },\n): ReadonlySignal<T> {\n const node: ComputedNode<T> = {\n _tag: 'computed',\n fn,\n value: undefined,\n state: ComputedState.Dirty,\n subscribers: new Set(),\n sources: new Set(),\n equals: options?.equals ?? Object.is,\n };\n\n const read = (): T => {\n // Track this computed as a dependency of the current subscriber\n if (currentSubscriber) {\n node.subscribers.add(currentSubscriber);\n if ('sources' in currentSubscriber) {\n currentSubscriber.sources.add(node);\n }\n }\n\n if (node.state !== ComputedState.Clean) {\n recompute(node);\n }\n\n return node.value as T;\n };\n\n return read;\n}\n\nfunction recompute<T>(node: ComputedNode<T>): void {\n // Clean up old source subscriptions\n for (const source of node.sources) {\n source.subscribers.delete(node);\n }\n node.sources.clear();\n\n const prevSubscriber = currentSubscriber;\n currentSubscriber = node;\n\n try {\n const newValue = node.fn();\n const changed =\n node.value === undefined || !node.equals(node.value, newValue);\n node.value = newValue;\n node.state = ComputedState.Clean;\n\n // Only propagate if value actually changed\n if (changed) {\n notifySubscribers(node);\n }\n } finally {\n currentSubscriber = prevSubscriber;\n }\n}\n\n// --- Effect ---\n\ninterface EffectNode extends ScheduledEffect {\n _tag: 'effect';\n fn: () => void | (() => void);\n cleanup: (() => void) | null;\n sources: Set<SignalNode<unknown> | ComputedNode<unknown>>;\n disposed: boolean;\n isRender: boolean;\n}\n\nexport function effect(\n fn: () => void | (() => void),\n options?: { render?: boolean },\n): () => void {\n const node: EffectNode = {\n _tag: 'effect',\n fn,\n cleanup: null,\n sources: new Set(),\n disposed: false,\n isRender: options?.render ?? false,\n run() {\n runEffect(node);\n },\n };\n\n // Run immediately to establish dependencies\n runEffect(node);\n\n // Return dispose function\n return () => {\n node.disposed = true;\n cleanupEffect(node);\n for (const source of node.sources) {\n source.subscribers.delete(node);\n }\n node.sources.clear();\n };\n}\n\nfunction runEffect(node: EffectNode): void {\n if (node.disposed) return;\n\n // Before re-running, check if any dirty computed source actually changed.\n // If all computed sources resolved to the same value, skip the re-run.\n if (node.sources.size > 0) {\n let anyChanged = false;\n for (const source of node.sources) {\n if ('_tag' in source && source._tag === 'computed') {\n if (source.state === ComputedState.Dirty) {\n const oldValue = source.value;\n recompute(source);\n if (!source.equals(oldValue as never, source.value as never)) {\n anyChanged = true;\n }\n }\n } else {\n // Plain signal source — if we got scheduled, something changed\n anyChanged = true;\n }\n }\n if (!anyChanged) return;\n }\n\n // Clean up previous run\n cleanupEffect(node);\n\n // Clean up old source subscriptions\n for (const source of node.sources) {\n source.subscribers.delete(node);\n }\n node.sources.clear();\n\n const prevSubscriber = currentSubscriber;\n currentSubscriber = node;\n\n try {\n const result = node.fn();\n if (typeof result === 'function') {\n node.cleanup = result;\n }\n } finally {\n currentSubscriber = prevSubscriber;\n }\n}\n\nfunction cleanupEffect(node: EffectNode): void {\n if (node.cleanup) {\n node.cleanup();\n node.cleanup = null;\n }\n}\n\n// --- Untrack ---\n\n/** Execute a function without tracking any signal reads */\nexport function untrack<T>(fn: () => T): T {\n const prev = currentSubscriber;\n currentSubscriber = null;\n try {\n return fn();\n } finally {\n currentSubscriber = prev;\n }\n}\n\n// --- Internal helpers ---\n\nfunction trackSubscriber(\n node: SignalNode<unknown> | ComputedNode<unknown>,\n): void {\n if (currentSubscriber) {\n node.subscribers.add(currentSubscriber);\n\n if ('sources' in currentSubscriber) {\n currentSubscriber.sources.add(node);\n }\n }\n}\n\nfunction notifySubscribers(\n node: SignalNode<unknown> | ComputedNode<unknown>,\n): void {\n for (const sub of node.subscribers) {\n if (sub._tag === 'computed') {\n // Mark dirty. The computed will re-evaluate lazily when read.\n sub.state = ComputedState.Dirty;\n // Propagate through the computed chain to reach effects.\n // The effects will re-read the computed, triggering recompute,\n // and only update DOM if the value actually changed.\n notifySubscribers(sub);\n } else if (sub._tag === 'effect') {\n scheduleEffect(sub);\n }\n }\n}\n"]}
|
package/dist/core.cjs
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
'use strict';var chunk2PUQBTK5_cjs=require('./chunk-2PUQBTK5.cjs'),chunkZE7R72IH_cjs=require('./chunk-ZE7R72IH.cjs');Object.defineProperty(exports,"For",{enumerable:true,get:function(){return chunk2PUQBTK5_cjs.r}});Object.defineProperty(exports,"Show",{enumerable:true,get:function(){return chunk2PUQBTK5_cjs.q}});Object.defineProperty(exports,"bindProperty",{enumerable:true,get:function(){return chunk2PUQBTK5_cjs.m}});Object.defineProperty(exports,"bindText",{enumerable:true,get:function(){return chunk2PUQBTK5_cjs.l}});Object.defineProperty(exports,"bindVisible",{enumerable:true,get:function(){return chunk2PUQBTK5_cjs.n}});Object.defineProperty(exports,"cloneTemplate",{enumerable:true,get:function(){return chunk2PUQBTK5_cjs.j}});Object.defineProperty(exports,"createContext",{enumerable:true,get:function(){return chunk2PUQBTK5_cjs.e}});Object.defineProperty(exports,"createElement",{enumerable:true,get:function(){return chunk2PUQBTK5_cjs.h}});Object.defineProperty(exports,"createText",{enumerable:true,get:function(){return chunk2PUQBTK5_cjs.i}});Object.defineProperty(exports,"defineComponent",{enumerable:true,get:function(){return chunk2PUQBTK5_cjs.y}});Object.defineProperty(exports,"inject",{enumerable:true,get:function(){return chunk2PUQBTK5_cjs.g}});Object.defineProperty(exports,"insert",{enumerable:true,get:function(){return chunk2PUQBTK5_cjs.t}});Object.defineProperty(exports,"nodeToDOM",{enumerable:true,get:function(){return chunk2PUQBTK5_cjs.s}});Object.defineProperty(exports,"onError",{enumerable:true,get:function(){return chunk2PUQBTK5_cjs.w}});Object.defineProperty(exports,"onMount",{enumerable:true,get:function(){return chunk2PUQBTK5_cjs.u}});Object.defineProperty(exports,"onUnmount",{enumerable:true,get:function(){return chunk2PUQBTK5_cjs.v}});Object.defineProperty(exports,"provide",{enumerable:true,get:function(){return chunk2PUQBTK5_cjs.f}});Object.defineProperty(exports,"ref",{enumerable:true,get:function(){return chunk2PUQBTK5_cjs.x}});Object.defineProperty(exports,"renderConditional",{enumerable:true,get:function(){return chunk2PUQBTK5_cjs.o}});Object.defineProperty(exports,"renderList",{enumerable:true,get:function(){return chunk2PUQBTK5_cjs.p}});Object.defineProperty(exports,"setProperty",{enumerable:true,get:function(){return chunk2PUQBTK5_cjs.k}});Object.defineProperty(exports,"batch",{enumerable:true,get:function(){return chunkZE7R72IH_cjs.a}});Object.defineProperty(exports,"computed",{enumerable:true,get:function(){return chunkZE7R72IH_cjs.d}});Object.defineProperty(exports,"effect",{enumerable:true,get:function(){return chunkZE7R72IH_cjs.e}});Object.defineProperty(exports,"flushSync",{enumerable:true,get:function(){return chunkZE7R72IH_cjs.b}});Object.defineProperty(exports,"signal",{enumerable:true,get:function(){return chunkZE7R72IH_cjs.c}});Object.defineProperty(exports,"untrack",{enumerable:true,get:function(){return chunkZE7R72IH_cjs.f}});//# sourceMappingURL=core.cjs.map
|
|
2
|
+
//# sourceMappingURL=core.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"core.cjs"}
|
package/dist/core.js
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
export{r as For,q as Show,m as bindProperty,l as bindText,n as bindVisible,j as cloneTemplate,e as createContext,h as createElement,i as createText,y as defineComponent,g as inject,t as insert,s as nodeToDOM,w as onError,u as onMount,v as onUnmount,f as provide,x as ref,o as renderConditional,p as renderList,k as setProperty}from'./chunk-BJKK7MKL.js';export{a as batch,d as computed,e as effect,b as flushSync,c as signal,f as untrack}from'./chunk-4K6DIB7A.js';//# sourceMappingURL=core.js.map
|
|
2
|
+
//# sourceMappingURL=core.js.map
|
package/dist/core.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"core.js"}
|