@akashjs/runtime 0.1.2 → 0.1.4

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.
Files changed (79) hide show
  1. package/dist/animate.cjs +2 -0
  2. package/dist/animate.cjs.map +1 -0
  3. package/dist/animate.js +2 -0
  4. package/dist/animate.js.map +1 -0
  5. package/dist/chunk-2UTALKTF.js +5 -0
  6. package/dist/chunk-2UTALKTF.js.map +1 -0
  7. package/dist/chunk-2X7GUBTG.cjs +2 -0
  8. package/dist/chunk-2X7GUBTG.cjs.map +1 -0
  9. package/dist/chunk-3HWR5MIF.js +2 -0
  10. package/dist/chunk-3HWR5MIF.js.map +1 -0
  11. package/dist/chunk-3Q7GK4DL.cjs +2 -0
  12. package/dist/chunk-3Q7GK4DL.cjs.map +1 -0
  13. package/dist/chunk-6G3EALVL.js +2 -0
  14. package/dist/chunk-6G3EALVL.js.map +1 -0
  15. package/dist/chunk-AQDP6FRO.cjs +5 -0
  16. package/dist/chunk-AQDP6FRO.cjs.map +1 -0
  17. package/dist/chunk-FB3CM2UH.cjs +2 -0
  18. package/dist/chunk-FB3CM2UH.cjs.map +1 -0
  19. package/dist/chunk-FX7RHVM5.js +2 -0
  20. package/dist/chunk-FX7RHVM5.js.map +1 -0
  21. package/dist/chunk-IH54XQBC.cjs +2 -0
  22. package/dist/chunk-IH54XQBC.cjs.map +1 -0
  23. package/dist/chunk-IXRAKXD7.js +2 -0
  24. package/dist/chunk-IXRAKXD7.js.map +1 -0
  25. package/dist/chunk-ONEN7EMK.cjs +2 -0
  26. package/dist/chunk-ONEN7EMK.cjs.map +1 -0
  27. package/dist/chunk-PGZQFMX2.cjs +32 -0
  28. package/dist/chunk-PGZQFMX2.cjs.map +1 -0
  29. package/dist/chunk-Q3E2UVUK.js +2 -0
  30. package/dist/chunk-Q3E2UVUK.js.map +1 -0
  31. package/dist/chunk-TPFWKMCK.js +2 -0
  32. package/dist/chunk-TPFWKMCK.js.map +1 -0
  33. package/dist/chunk-TXBFQLNL.js +32 -0
  34. package/dist/chunk-TXBFQLNL.js.map +1 -0
  35. package/dist/chunk-UID3D5XB.js +2 -0
  36. package/dist/chunk-UID3D5XB.js.map +1 -0
  37. package/dist/chunk-Y5HEEST4.cjs +2 -0
  38. package/dist/chunk-Y5HEEST4.cjs.map +1 -0
  39. package/dist/chunk-YZORCUDS.cjs +2 -0
  40. package/dist/chunk-YZORCUDS.cjs.map +1 -0
  41. package/dist/core.cjs +2 -0
  42. package/dist/core.cjs.map +1 -0
  43. package/dist/core.js +2 -0
  44. package/dist/core.js.map +1 -0
  45. package/dist/index.cjs +52 -5454
  46. package/dist/index.cjs.map +1 -1
  47. package/dist/index.js +52 -4575
  48. package/dist/index.js.map +1 -1
  49. package/dist/machine.cjs +2 -0
  50. package/dist/machine.cjs.map +1 -0
  51. package/dist/machine.js +2 -0
  52. package/dist/machine.js.map +1 -0
  53. package/dist/offline.cjs +2 -0
  54. package/dist/offline.cjs.map +1 -0
  55. package/dist/offline.js +2 -0
  56. package/dist/offline.js.map +1 -0
  57. package/dist/pwa.cjs +2 -0
  58. package/dist/pwa.cjs.map +1 -0
  59. package/dist/pwa.js +2 -0
  60. package/dist/pwa.js.map +1 -0
  61. package/dist/ssr.cjs +2 -0
  62. package/dist/ssr.cjs.map +1 -0
  63. package/dist/ssr.js +2 -0
  64. package/dist/ssr.js.map +1 -0
  65. package/dist/store.cjs +2 -0
  66. package/dist/store.cjs.map +1 -0
  67. package/dist/store.js +2 -0
  68. package/dist/store.js.map +1 -0
  69. package/dist/sync.cjs +2 -0
  70. package/dist/sync.cjs.map +1 -0
  71. package/dist/sync.js +2 -0
  72. package/dist/sync.js.map +1 -0
  73. package/dist/test.cjs +4 -369
  74. package/dist/test.cjs.map +1 -1
  75. package/dist/test.js +4 -165
  76. package/dist/test.js.map +1 -1
  77. package/package.json +31 -4
  78. package/dist/chunk-D3IR22HI.js +0 -662
  79. package/dist/chunk-D3IR22HI.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/offline.ts"],"names":["openDB","name","version","resolve","reject","request","db","err","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","initPromise","interval","getKey","item","put","list","idx","i","next","queueOp","remove","op","fetchFn","serverResponse","serverItems","partial","existing"],"mappings":"sCAuFA,eAAeA,CAAAA,CAAOC,EAAcC,CAAAA,CAAU,CAAA,CAAyB,CACrE,OAAI,OAAO,UAAc,GAAA,CAChB,OAAA,CAAQ,OAAO,IAAI,KAAA,CAAM,yBAAyB,CAAC,CAAA,CAErD,IAAI,OAAA,CAAQ,CAACC,CAAAA,CAASC,CAAAA,GAAW,CACtC,GAAI,CACF,IAAMC,CAAAA,CAAU,UAAU,IAAA,CAAKJ,CAAAA,CAAMC,CAAO,CAAA,CAC5CG,CAAAA,CAAQ,gBAAkB,IAAM,CAC9B,IAAMC,CAAAA,CAAKD,CAAAA,CAAQ,OACdC,CAAAA,CAAG,gBAAA,CAAiB,SAAS,OAAO,CAAA,EACvCA,CAAAA,CAAG,iBAAA,CAAkB,OAAO,CAAA,CAEzBA,EAAG,gBAAA,CAAiB,QAAA,CAAS,SAAS,CAAA,EACzCA,CAAAA,CAAG,kBAAkB,SAAA,CAAW,CAAE,cAAe,CAAA,CAAK,CAAC,EAE3D,CAAA,CACAD,CAAAA,CAAQ,UAAY,IAAMF,CAAAA,CAAQE,EAAQ,MAAM,CAAA,CAChDA,CAAAA,CAAQ,OAAA,CAAU,IAAMD,CAAAA,CAAOC,EAAQ,KAAA,EAAS,IAAI,MAAM,uBAAuB,CAAC,EACpF,CAAA,MAASE,CAAAA,CAAK,CACZH,CAAAA,CAAOG,CAAG,EACZ,CACF,CAAC,CACH,CAEA,eAAeC,EAAaF,CAAAA,CAAiBG,CAAAA,CAA6B,CACxE,OAAO,IAAI,OAAA,CAAQ,CAACN,CAAAA,CAASC,CAAAA,GAAW,CAEtC,IAAMM,CAAAA,CADKJ,EAAG,WAAA,CAAYG,CAAAA,CAAO,UAAU,CAAA,CAC5B,WAAA,CAAYA,CAAK,CAAA,CAAE,MAAA,GAClCC,CAAAA,CAAI,SAAA,CAAY,IAAMP,CAAAA,CAAQO,CAAAA,CAAI,MAAM,CAAA,CACxCA,CAAAA,CAAI,OAAA,CAAU,IAAMN,CAAAA,CAAOM,CAAAA,CAAI,KAAK,EACtC,CAAC,CACH,CAEA,eAAeC,EAAOL,CAAAA,CAAiBG,CAAAA,CAAeG,EAAaC,CAAAA,CAA+B,CAChG,OAAO,IAAI,OAAA,CAAQ,CAACV,CAAAA,CAASC,CAAAA,GAAW,CACtC,IAAMU,CAAAA,CAAKR,CAAAA,CAAG,YAAYG,CAAAA,CAAO,WAAW,EAC5CK,CAAAA,CAAG,WAAA,CAAYL,CAAK,CAAA,CAAE,GAAA,CAAII,EAAOD,CAAG,CAAA,CACpCE,EAAG,UAAA,CAAa,IAAMX,GAAQ,CAC9BW,CAAAA,CAAG,QAAU,IAAMV,CAAAA,CAAOU,CAAAA,CAAG,KAAK,EACpC,CAAC,CACH,CAEA,eAAeC,EAAUT,CAAAA,CAAiBG,CAAAA,CAAeG,EAA4B,CACnF,OAAO,IAAI,OAAA,CAAQ,CAACT,EAASC,CAAAA,GAAW,CACtC,IAAMU,CAAAA,CAAKR,CAAAA,CAAG,YAAYG,CAAAA,CAAO,WAAW,CAAA,CAC5CK,CAAAA,CAAG,WAAA,CAAYL,CAAK,EAAE,MAAA,CAAOG,CAAG,EAChCE,CAAAA,CAAG,UAAA,CAAa,IAAMX,CAAAA,EAAQ,CAC9BW,EAAG,OAAA,CAAU,IAAMV,EAAOU,CAAAA,CAAG,KAAK,EACpC,CAAC,CACH,CAEA,eAAeE,CAAAA,CAASV,CAAAA,CAAiBG,CAAAA,CAA8B,CACrE,OAAO,IAAI,OAAA,CAAQ,CAACN,EAASC,CAAAA,GAAW,CACtC,IAAMU,CAAAA,CAAKR,CAAAA,CAAG,YAAYG,CAAAA,CAAO,WAAW,EAC5CK,CAAAA,CAAG,WAAA,CAAYL,CAAK,CAAA,CAAE,KAAA,GACtBK,CAAAA,CAAG,UAAA,CAAa,IAAMX,CAAAA,EAAQ,CAC9BW,CAAAA,CAAG,QAAU,IAAMV,CAAAA,CAAOU,EAAG,KAAK,EACpC,CAAC,CACH,CASO,SAASG,CAAAA,CACdhB,CAAAA,CACAiB,EAAkC,EAAC,CAClB,CACjB,IAAMC,GAAAA,CAAWD,EAAQ,QAAA,EAAY,IAAA,CAC/BE,CAAAA,CAAQC,CAAAA,CAAY,EAAE,EACtBC,CAAAA,CAAaD,CAAAA,CAAuB,EAAE,CAAA,CACtCE,EAAUF,CAAAA,CAAO,KAAK,EACtBG,CAAAA,CAASH,CAAAA,CAAO,OAAO,SAAA,CAAc,GAAA,CAAc,UAAU,MAAA,CAAS,IAAI,EAC1EI,CAAAA,CAAUC,CAAAA,CAAS,IAAMJ,CAAAA,EAAW,CAAE,MAAM,EAE9ChB,CAAAA,CAAyB,IAAA,CACzBqB,EAAmD,IAAA,CACnDC,CAAAA,CAAW,MAGX,OAAO,MAAA,CAAW,MACpB,MAAA,CAAO,gBAAA,CAAiB,SAAU,IAAM,CACtCJ,EAAO,GAAA,CAAI,IAAI,EACfK,CAAAA,GACF,CAAC,CAAA,CACD,MAAA,CAAO,gBAAA,CAAiB,UAAW,IAAML,CAAAA,CAAO,IAAI,KAAK,CAAC,GAI5D,eAAeM,CAAAA,EAAsB,CACnC,GAAI,EAAA,OAAO,UAAc,GAAA,CAAA,CACzB,GAAI,CACFxB,CAAAA,CAAK,MAAMN,EAAO,CAAA,cAAA,EAAiBC,CAAI,CAAA,CAAA,CAAIiB,CAAAA,CAAQ,OAAA,EAAW,CAAC,EAC/D,IAAMa,CAAAA,CAAS,MAAMvB,CAAAA,CAAaF,CAAAA,CAAI,OAAO,CAAA,CAC7Cc,CAAAA,CAAM,IAAIW,CAAM,CAAA,CAChB,IAAMC,CAAAA,CAAM,MAAMxB,EAAwBF,CAAAA,CAAI,SAAS,EACvDgB,CAAAA,CAAW,GAAA,CAAIU,CAAG,EACpB,CAAA,MAASzB,CAAAA,CAAK,CAAE,OAAA,CAAQ,KAAA,CAAM,uCAAwCA,CAAG,EAAG,CAC9E,CAEA,IAAM0B,CAAAA,CAAcH,CAAAA,EAAK,CAGzB,GAAIZ,EAAQ,IAAA,CAAM,CAChB,IAAMgB,CAAAA,CAAWhB,CAAAA,CAAQ,KAAK,QAAA,EAAY,GAAA,CAC1CS,CAAAA,CAAY,WAAA,CAAY,IAAM,CACxBH,GAAO,EAAKC,CAAAA,GAAY,CAAA,EAAK,CAACF,GAAQ,EACxCM,CAAAA,GAEJ,CAAA,CAAGK,CAAQ,EACb,CAEA,SAASC,EAAOC,CAAAA,CAAiB,CAC/B,OAAO,MAAA,CAAQA,CAAAA,CAAajB,GAAQ,CAAC,CACvC,CAEA,SAASkB,CAAAA,CAAID,CAAAA,CAAe,CAC1B,IAAMxB,CAAAA,CAAMuB,EAAOC,CAAI,CAAA,CACvBhB,EAAM,MAAA,CAAQkB,CAAAA,EAAS,CACrB,IAAMC,CAAAA,CAAMD,EAAK,SAAA,CAAWE,CAAAA,EAAML,EAAOK,CAAC,CAAA,GAAM5B,CAAG,CAAA,CACnD,GAAI2B,CAAAA,GAAQ,GAAI,CACd,IAAME,EAAO,CAAC,GAAGH,CAAI,CAAA,CACrB,OAAAG,EAAKF,CAAG,CAAA,CAAIH,EACLK,CACT,CACA,OAAO,CAAC,GAAGH,EAAMF,CAAI,CACvB,CAAC,CAAA,CAEDM,CAAAA,CAAQ,CAAE,KAAM,KAAA,CAAO,GAAA,CAAA9B,EAAK,KAAA,CAAOwB,CAAAA,CAAM,UAAW,IAAA,CAAK,GAAA,EAAM,CAAC,CAAA,CAC5D9B,GAAIK,CAAAA,CAAOL,CAAAA,CAAI,QAASM,CAAAA,CAAKwB,CAAI,EACvC,CAEA,SAASO,CAAAA,CAAO/B,CAAAA,CAAmB,CACjCQ,CAAAA,CAAM,OAAQkB,CAAAA,EAASA,CAAAA,CAAK,OAAQE,CAAAA,EAAML,CAAAA,CAAOK,CAAC,CAAA,GAAM5B,CAAG,CAAC,CAAA,CAC5D8B,CAAAA,CAAQ,CAAE,IAAA,CAAM,QAAA,CAAU,IAAA9B,CAAAA,CAAK,SAAA,CAAW,KAAK,GAAA,EAAM,CAAC,CAAA,CAClDN,CAAAA,EAAIS,CAAAA,CAAUT,EAAI,OAAA,CAASM,CAAG,EACpC,CAEA,SAAS8B,EAAQE,CAAAA,CAAwB,CACvCtB,EAAW,MAAA,CAAQU,CAAAA,EAAQ,CAAC,GAAGA,CAAAA,CAAKY,CAAE,CAAC,CAAA,CACnCtC,GACSA,CAAAA,CAAG,WAAA,CAAY,SAAA,CAAW,WAAW,CAAA,CAC7C,WAAA,CAAY,SAAS,CAAA,CAAE,GAAA,CAAIsC,CAAE,EAEpC,CAEA,eAAef,CAAAA,EAAyB,CAEtC,GADA,MAAMI,CAAAA,CACF,CAACf,CAAAA,CAAQ,IAAA,EAAQK,GAAQ,EAAKK,CAAAA,CAAU,OAC5C,IAAMI,CAAAA,CAAMV,CAAAA,EAAW,CACvB,GAAIU,CAAAA,CAAI,SAAW,CAAA,CAAG,OAEtBT,EAAQ,GAAA,CAAI,IAAI,EAChB,IAAMsB,CAAAA,CAAU3B,EAAQ,IAAA,CAAK,KAAA,EAAS,WAAW,KAAA,CAAM,IAAA,CAAK,UAAU,CAAA,CAEtE,GAAI,CAUF,GAAA,CATiB,MAAM2B,CAAAA,CAAQ3B,CAAAA,CAAQ,IAAA,CAAK,GAAA,CAAK,CAC/C,MAAA,CAAQ,MAAA,CACR,QAAS,CACP,cAAA,CAAgB,mBAChB,GAAGA,CAAAA,CAAQ,KAAK,OAClB,CAAA,CACA,KAAM,IAAA,CAAK,SAAA,CAAU,CAAE,GAAA,CAAAc,CAAI,CAAC,CAC9B,CAAC,CAAA,EAEY,EAAA,CAAI,CACfV,CAAAA,CAAW,IAAI,EAAE,EACbhB,CAAAA,EAAI,MAAMU,EAASV,CAAAA,CAAI,SAAS,EAGpC,IAAMwC,CAAAA,CAAiB,MAAMD,CAAAA,CAAQ3B,CAAAA,CAAQ,KAAK,GAAA,CAAK,CACrD,QAASA,CAAAA,CAAQ,IAAA,CAAK,OACxB,CAAC,CAAA,CACD,GAAI4B,EAAe,EAAA,CAAI,CACrB,IAAMC,CAAAA,CAAc,MAAMD,EAAe,IAAA,EAAK,CAG9C,GAFA1B,CAAAA,CAAM,GAAA,CAAI2B,CAAW,CAAA,CAEjBzC,CAAAA,CAAI,CACN,MAAMU,CAAAA,CAASV,EAAI,OAAO,CAAA,CAC1B,IAAA,IAAW8B,CAAAA,IAAQW,CAAAA,CACjB,MAAMpC,EAAOL,CAAAA,CAAI,OAAA,CAAS6B,EAAOC,CAAI,CAAA,CAAGA,CAAI,EAEhD,CACF,CACF,CACF,CAAA,MAAS7B,EAAK,CAAE,OAAA,CAAQ,KAAK,gCAAA,CAAkCA,CAAG,EAAG,CAAA,OACrE,CACEgB,CAAAA,CAAQ,GAAA,CAAI,KAAK,EACnB,CACF,CAEA,OAAO,CACL,KAAA,CAAO,IAAMH,GAAM,CACnB,GAAA,CAAIR,EAAa,CAAE,OAAOQ,GAAM,CAAE,IAAA,CAAMoB,GAAML,CAAAA,CAAOK,CAAC,IAAM5B,CAAG,CAAG,CAAA,CAClE,GAAA,CAAAyB,CAAAA,CACA,GAAA,CAAKA,EACL,MAAA,CAAOzB,CAAAA,CAAaoC,EAAqB,CACvC,IAAMC,EAAW7B,CAAAA,EAAM,CAAE,KAAMoB,CAAAA,EAAML,CAAAA,CAAOK,CAAC,CAAA,GAAM5B,CAAG,EAClDqC,CAAAA,EAAUZ,CAAAA,CAAI,CAAE,GAAGY,CAAAA,CAAU,GAAGD,CAAQ,CAAC,EAC/C,EACA,MAAA,CAAAL,CAAAA,CACA,OAAQ,CACNvB,CAAAA,CAAM,IAAI,EAAE,EACZE,CAAAA,CAAW,GAAA,CAAI,EAAE,CAAA,CACbhB,IACFU,CAAAA,CAASV,CAAAA,CAAI,OAAO,CAAA,CACpBU,CAAAA,CAASV,CAAAA,CAAI,SAAS,CAAA,EAE1B,CAAA,CACA,QAAAmB,CAAAA,CACA,OAAA,CAAS,IAAMF,CAAAA,EAAQ,CACvB,OAAQ,IAAMC,CAAAA,EAAO,CACrB,IAAA,CAAMK,CAAAA,CACN,OAAA,EAAU,CACRD,CAAAA,CAAW,IAAA,CACPD,GAAW,aAAA,CAAcA,CAAS,EACtCrB,CAAAA,EAAI,KAAA,GACN,CACF,CACF","file":"chunk-IXRAKXD7.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 if (typeof indexedDB === 'undefined') {\n return Promise.reject(new Error('IndexedDB not available'));\n }\n return new Promise((resolve, reject) => {\n try {\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 ?? new Error('IndexedDB open failed'));\n } catch (err) {\n reject(err);\n }\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 (err) { console.error('[AkashJS] Offline store init failed:', err); }\n }\n\n const initPromise = 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 await initPromise;\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 (err) { console.warn('[AkashJS] Offline sync failed:', err); }\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';var chunk3Q7GK4DL_cjs=require('./chunk-3Q7GK4DL.cjs');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 s=Date.now();return n===this.entry.peerId||s>this.entry.timestamp||s===this.entry.timestamp&&n>this.entry.peerId?(this.entry={value:e,timestamp:Math.max(s,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=[],s=[];return {send(t){e?.send(JSON.stringify({type:"op",room:i.room,...t}));},onReceive(t){n.push(t);let o=false;return ()=>{if(o)return;o=true;let c=n.indexOf(t);c!==-1&&n.splice(c,1);}},onPresence(t){return s.push(t),()=>{let o=s.indexOf(t);o!==-1&&s.splice(o,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 o=JSON.parse(t.data);if(o.type==="op")for(let c of n)c(o);else if(o.type==="presence")for(let c of s)c(o.peerId,o.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){i.push(e);let n=false;return ()=>{if(n)return;n=true;let s=i.indexOf(e);s!==-1&&i.splice(s,1);}},connect(){},disconnect(){}}}var w=0;function O(i,e,n={}){let s=n.peerId??`peer-${++w}-${Date.now()}`,t=n.transport??h(),o=new Map,c={};for(let[r,a]of Object.entries(e))o.set(r,new g(a,s)),c[r]=chunk3Q7GK4DL_cjs.c(a);let l={};for(let r of Object.keys(e)){let a=c[r],y=o.get(r),p=(()=>a());p.set=u=>{y.set(u,s),a.set(u),t.send({type:"set",key:r,value:u,timestamp:y.timestamp,peerId:s});},p.update=u=>{p.set(u(a()));},p.peek=()=>a.peek(),l[r]=p;}let S=chunk3Q7GK4DL_cjs.c([]),m=chunk3Q7GK4DL_cjs.c(false),k=chunk3Q7GK4DL_cjs.c({}),f=chunk3Q7GK4DL_cjs.c(new Map),v=t.onReceive(r=>{r.type==="set"&&o.has(r.key)&&o.get(r.key).merge({value:r.value,timestamp:r.timestamp,peerId:r.peerId})&&c[r.key].set(r.value);}),T=t.onPresence?.((r,a)=>{f.update(y=>{let p=new Map(y);return p.set(r,a),p});});return {state:l,peers:()=>S(),presence:k,peerPresence:()=>f(),peerId:s,connected:()=>m(),connect(){t.connect(),m.set(true);},disconnect(){t.disconnect(),m.set(false);},dispose(){v(),T?.(),t.disconnect();}}}exports.a=g;exports.b=I;exports.c=h;exports.d=O;//# sourceMappingURL=chunk-ONEN7EMK.cjs.map
2
+ //# sourceMappingURL=chunk-ONEN7EMK.cjs.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","removed","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-ONEN7EMK.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 let removed = false;\n return () => {\n if (removed) return;\n removed = true;\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 let removed = false;\n return () => {\n if (removed) return;\n removed = true;\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,32 @@
1
+ 'use strict';var chunk3Q7GK4DL_cjs=require('./chunk-3Q7GK4DL.cjs');function f(r,e={}){let t=chunk3Q7GK4DL_cjs.c(false),a=chunk3Q7GK4DL_cjs.c(false),s=chunk3Q7GK4DL_cjs.c(!navigator.onLine),i=null;window.addEventListener("online",()=>s.set(false)),window.addEventListener("offline",()=>s.set(true));let u=new Promise((h,l)=>{if(!("serviceWorker"in navigator)){l(new Error("Service workers not supported"));return}navigator.serviceWorker.register(r,{scope:e.scope}).then(n=>{i=n,t.set(true),e.onReady?.(n),h(n),n.addEventListener("updatefound",()=>{let o=n.installing;o&&o.addEventListener("statechange",()=>{o.state==="installed"&&navigator.serviceWorker.controller&&(a.set(true),e.onUpdate?.(n),e.autoReload&&(o.postMessage({type:"SKIP_WAITING"}),window.location.reload()));});});}).catch(n=>{e.onError?.(n),l(n);});});return {registered:()=>t(),updateAvailable:()=>a(),offline:()=>s(),ready:u,async update(){i&&await i.update();},skipWaiting(){i?.waiting&&(i.waiting.postMessage({type:"SKIP_WAITING"}),window.location.reload());},async unregister(){return i?i.unregister():false}}}function v(r){let e=`// Auto-generated service worker by AkashJS
2
+ const CACHE_VERSION = 'v1';
3
+
4
+ self.addEventListener('install', (event) => {
5
+ self.skipWaiting();
6
+ });
7
+
8
+ self.addEventListener('activate', (event) => {
9
+ event.waitUntil(clients.claim());
10
+ });
11
+
12
+ self.addEventListener('message', (event) => {
13
+ if (event.data?.type === 'SKIP_WAITING') {
14
+ self.skipWaiting();
15
+ }
16
+ });
17
+
18
+ self.addEventListener('fetch', (event) => {
19
+ const url = new URL(event.request.url);
20
+ `;for(let t of r){let a=t.match instanceof RegExp?t.match.toString():`new RegExp(${JSON.stringify(t.match.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"))})`,s=t.cacheName??"akash-cache";e+=`
21
+ if (${a}.test(url.pathname)) {
22
+ event.respondWith(${p(t.strategy,s)});
23
+ return;
24
+ }
25
+ `;}return e+=`
26
+ // Default: network-first
27
+ event.respondWith(
28
+ fetch(event.request).catch(() => caches.match(event.request))
29
+ );
30
+ });
31
+ `,e}function p(r,e){switch(r){case "cache-first":return `caches.match(event.request).then(cached => cached || fetch(event.request).then(response => { const clone = response.clone(); caches.open('${e}').then(cache => cache.put(event.request, clone)); return response; }))`;case "network-first":return `fetch(event.request).then(response => { const clone = response.clone(); caches.open('${e}').then(cache => cache.put(event.request, clone)); return response; }).catch(() => caches.match(event.request))`;case "stale-while-revalidate":return `caches.match(event.request).then(cached => { const fetchPromise = fetch(event.request).then(response => { caches.open('${e}').then(cache => cache.put(event.request, response.clone())); return response; }); return cached || fetchPromise; })`;case "network-only":return "fetch(event.request)";case "cache-only":return "caches.match(event.request)"}}async function y(r,e){return await Notification.requestPermission()!=="granted"?null:await r.pushManager.subscribe({userVisibleOnly:true,applicationServerKey:d(e)})}function d(r){let e="=".repeat((4-r.length%4)%4),t=(r+e).replace(/-/g,"+").replace(/_/g,"/"),a=atob(t);return Uint8Array.from(a,s=>s.charCodeAt(0))}exports.a=f;exports.b=v;exports.c=y;//# sourceMappingURL=chunk-PGZQFMX2.cjs.map
32
+ //# sourceMappingURL=chunk-PGZQFMX2.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/pwa.ts"],"names":["registerServiceWorker","swUrl","options","registered","signal","updateAvailable","offline","registration","ready","resolve","reject","reg","newWorker","err","generateSWScript","routes","script","route","pattern","cacheName","generateStrategyCode","strategy","subscribePush","vapidPublicKey","urlBase64ToUint8Array","base64String","padding","base64","rawData","char"],"mappings":"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","file":"chunk-PGZQFMX2.cjs","sourcesContent":["/**\n * PWA / Service Worker support.\n *\n * Register service workers, configure caching strategies,\n * handle updates, and manage push notifications.\n *\n * ```ts\n * const sw = registerServiceWorker('/sw.js', {\n * onUpdate: () => toast.info('New version available!'),\n * });\n * sw.ready; // Promise<ServiceWorkerRegistration>\n * sw.update(); // check for updates\n * ```\n */\n\nimport { signal } from './signals.js';\nimport type { ReadonlySignal } from './signals.js';\n\n// =========================================================================\n// Types\n// =========================================================================\n\nexport interface SWOptions {\n /** Callback when a new version is available */\n onUpdate?: (registration: ServiceWorkerRegistration) => void;\n /** Callback when the SW is ready */\n onReady?: (registration: ServiceWorkerRegistration) => void;\n /** Callback on registration error */\n onError?: (error: Error) => void;\n /** Auto-reload on update (default: false) */\n autoReload?: boolean;\n /** Scope of the service worker */\n scope?: string;\n}\n\nexport interface SWRegistration {\n /** Whether the SW is registered */\n registered: ReadonlySignal<boolean>;\n /** Whether an update is available */\n updateAvailable: ReadonlySignal<boolean>;\n /** Whether the app is running offline */\n offline: ReadonlySignal<boolean>;\n /** The raw SW registration (available after ready) */\n ready: Promise<ServiceWorkerRegistration>;\n /** Check for updates */\n update(): Promise<void>;\n /** Skip waiting and activate new SW */\n skipWaiting(): void;\n /** Unregister the service worker */\n unregister(): Promise<boolean>;\n}\n\n// =========================================================================\n// Service Worker registration\n// =========================================================================\n\n/**\n * Register a service worker with update detection.\n */\nexport function registerServiceWorker(\n swUrl: string,\n options: SWOptions = {},\n): SWRegistration {\n const registered = signal(false);\n const updateAvailable = signal(false);\n const offline = signal(!navigator.onLine);\n\n let registration: ServiceWorkerRegistration | null = null;\n\n // Track online/offline\n window.addEventListener('online', () => offline.set(false));\n window.addEventListener('offline', () => offline.set(true));\n\n const ready = new Promise<ServiceWorkerRegistration>((resolve, reject) => {\n if (!('serviceWorker' in navigator)) {\n reject(new Error('Service workers not supported'));\n return;\n }\n\n navigator.serviceWorker\n .register(swUrl, { scope: options.scope })\n .then((reg) => {\n registration = reg;\n registered.set(true);\n options.onReady?.(reg);\n resolve(reg);\n\n // Listen for updates\n reg.addEventListener('updatefound', () => {\n const newWorker = reg.installing;\n if (!newWorker) return;\n\n newWorker.addEventListener('statechange', () => {\n if (newWorker.state === 'installed' && navigator.serviceWorker.controller) {\n updateAvailable.set(true);\n options.onUpdate?.(reg);\n\n if (options.autoReload) {\n newWorker.postMessage({ type: 'SKIP_WAITING' });\n window.location.reload();\n }\n }\n });\n });\n })\n .catch((err) => {\n options.onError?.(err);\n reject(err);\n });\n });\n\n return {\n registered: () => registered(),\n updateAvailable: () => updateAvailable(),\n offline: () => offline(),\n ready,\n async update() {\n if (registration) {\n await registration.update();\n }\n },\n skipWaiting() {\n if (registration?.waiting) {\n registration.waiting.postMessage({ type: 'SKIP_WAITING' });\n window.location.reload();\n }\n },\n async unregister() {\n if (registration) {\n return registration.unregister();\n }\n return false;\n },\n };\n}\n\n// =========================================================================\n// Caching strategies (for SW scripts)\n// =========================================================================\n\nexport type CacheStrategy = 'cache-first' | 'network-first' | 'stale-while-revalidate' | 'network-only' | 'cache-only';\n\nexport interface CacheRoute {\n /** URL pattern to match (string or regex) */\n match: string | RegExp;\n /** Caching strategy */\n strategy: CacheStrategy;\n /** Cache name */\n cacheName?: string;\n /** Max entries in cache */\n maxEntries?: number;\n /** Max age in seconds */\n maxAgeSeconds?: number;\n}\n\n/**\n * Generate a service worker script from cache route configs.\n *\n * ```ts\n * const swScript = generateSWScript([\n * { match: /\\.(?:js|css)$/, strategy: 'cache-first', cacheName: 'assets' },\n * { match: '/api/', strategy: 'network-first', maxAgeSeconds: 300 },\n * { match: /\\.(?:png|jpg|svg)$/, strategy: 'cache-first', cacheName: 'images' },\n * ]);\n * ```\n */\nexport function generateSWScript(routes: CacheRoute[]): string {\n let script = `// Auto-generated service worker by AkashJS\nconst CACHE_VERSION = 'v1';\n\nself.addEventListener('install', (event) => {\n self.skipWaiting();\n});\n\nself.addEventListener('activate', (event) => {\n event.waitUntil(clients.claim());\n});\n\nself.addEventListener('message', (event) => {\n if (event.data?.type === 'SKIP_WAITING') {\n self.skipWaiting();\n }\n});\n\nself.addEventListener('fetch', (event) => {\n const url = new URL(event.request.url);\n`;\n\n for (const route of routes) {\n const pattern = route.match instanceof RegExp\n ? route.match.toString()\n : `new RegExp(${JSON.stringify(route.match.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&'))})`;\n\n const cacheName = route.cacheName ?? 'akash-cache';\n\n script += `\n if (${pattern}.test(url.pathname)) {\n event.respondWith(${generateStrategyCode(route.strategy, cacheName)});\n return;\n }\n`;\n }\n\n script += `\n // Default: network-first\n event.respondWith(\n fetch(event.request).catch(() => caches.match(event.request))\n );\n});\n`;\n\n return script;\n}\n\nfunction generateStrategyCode(strategy: CacheStrategy, cacheName: string): string {\n switch (strategy) {\n case 'cache-first':\n return `caches.match(event.request).then(cached => cached || fetch(event.request).then(response => { const clone = response.clone(); caches.open('${cacheName}').then(cache => cache.put(event.request, clone)); return response; }))`;\n case 'network-first':\n return `fetch(event.request).then(response => { const clone = response.clone(); caches.open('${cacheName}').then(cache => cache.put(event.request, clone)); return response; }).catch(() => caches.match(event.request))`;\n case 'stale-while-revalidate':\n return `caches.match(event.request).then(cached => { const fetchPromise = fetch(event.request).then(response => { caches.open('${cacheName}').then(cache => cache.put(event.request, response.clone())); return response; }); return cached || fetchPromise; })`;\n case 'network-only':\n return `fetch(event.request)`;\n case 'cache-only':\n return `caches.match(event.request)`;\n }\n}\n\n// =========================================================================\n// Push notifications\n// =========================================================================\n\n/**\n * Request push notification permission and subscribe.\n */\nexport async function subscribePush(\n registration: ServiceWorkerRegistration,\n vapidPublicKey: string,\n): Promise<PushSubscription | null> {\n const permission = await Notification.requestPermission();\n if (permission !== 'granted') return null;\n\n const subscription = await registration.pushManager.subscribe({\n userVisibleOnly: true,\n applicationServerKey: urlBase64ToUint8Array(vapidPublicKey),\n });\n\n return subscription;\n}\n\nfunction urlBase64ToUint8Array(base64String: string): Uint8Array {\n const padding = '='.repeat((4 - (base64String.length % 4)) % 4);\n const base64 = (base64String + padding).replace(/-/g, '+').replace(/_/g, '/');\n const rawData = atob(base64);\n return Uint8Array.from(rawData, (char) => char.charCodeAt(0));\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-FX7RHVM5.js';var S=new Map;function p(r,a){return ()=>{if(S.has(r))return S.get(r);let s=a.state(),n=u(r,s,a);return S.set(r,n),n}}function u(r,a,s){let n={},i=Object.keys(a);for(let e of i)n[e]=c(a[e]);let c$1={};if(s.getters)for(let[e,t]of Object.entries(s.getters))c$1[e]=d(()=>t(n));let o={$id:r};for(let e of i)o[e]=n[e];for(let[e,t]of Object.entries(c$1))o[e]=t;if(s.actions)for(let[e,t]of Object.entries(s.actions))o[e]=(...d)=>t.apply(n,d);o.$reset=()=>{let e=s.state();for(let t of i)n[t].set(e[t]);},o.$snapshot=()=>{let e={};for(let t of i)e[t]=n[t]();return e};let g=new Set;return o.$subscribe=e=>(g.add(e),()=>g.delete(e)),o}function l(){S.clear();}export{p as a,l as b};//# sourceMappingURL=chunk-TPFWKMCK.js.map
2
+ //# sourceMappingURL=chunk-TPFWKMCK.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/store.ts"],"names":["storeInstances","defineStore","id","definition","initialState","store","createStoreInstance","stateSignals","stateKeys","key","signal","getterComputeds","getterFn","computed","comp","actionFn","args","fresh","snapshot","subscribers","callback","clearStores"],"mappings":"sCA4EA,IAAMA,CAAAA,CAAiB,IAAI,GAAA,CAQpB,SAASC,EAKdC,CAAAA,CACAC,CAAAA,CACsB,CACtB,OAAO,IAAM,CAEX,GAAIH,CAAAA,CAAe,GAAA,CAAIE,CAAE,CAAA,CACvB,OAAOF,EAAe,GAAA,CAAIE,CAAE,CAAA,CAG9B,IAAME,CAAAA,CAAeD,CAAAA,CAAW,OAAM,CAChCE,CAAAA,CAAQC,EAAoBJ,CAAAA,CAAIE,CAAAA,CAAcD,CAAU,CAAA,CAC9D,OAAAH,CAAAA,CAAe,GAAA,CAAIE,CAAAA,CAAIG,CAAK,EACrBA,CACT,CACF,CAEA,SAASC,CAAAA,CAKPJ,CAAAA,CACAE,EACAD,CAAAA,CACgB,CAEhB,IAAMI,CAAAA,CAAgD,EAAC,CACjDC,EAAY,MAAA,CAAO,IAAA,CAAKJ,CAAY,CAAA,CAE1C,IAAA,IAAWK,KAAOD,CAAAA,CAChBD,CAAAA,CAAaE,CAAG,CAAA,CAAIC,CAAAA,CAAON,CAAAA,CAAaK,CAAG,CAAC,CAAA,CAI9C,IAAME,GAAAA,CAA2D,EAAC,CAClE,GAAIR,CAAAA,CAAW,OAAA,CACb,IAAA,GAAW,CAACM,CAAAA,CAAKG,CAAQ,IAAK,MAAA,CAAO,OAAA,CAAQT,EAAW,OAAO,CAAA,CAC7DQ,IAAgBF,CAAG,CAAA,CAAII,CAAAA,CAAS,IAC7BD,CAAAA,CAAsBL,CAAY,CACrC,CAAA,CAKJ,IAAMF,CAAAA,CAAa,CAAE,GAAA,CAAKH,CAAG,EAG7B,IAAA,IAAWO,CAAAA,IAAOD,CAAAA,CAChBH,CAAAA,CAAMI,CAAG,CAAA,CAAIF,EAAaE,CAAG,CAAA,CAI/B,OAAW,CAACA,CAAAA,CAAKK,CAAI,CAAA,GAAK,MAAA,CAAO,OAAA,CAAQH,GAAe,CAAA,CACtDN,CAAAA,CAAMI,CAAG,CAAA,CAAIK,CAAAA,CAIf,GAAIX,CAAAA,CAAW,OAAA,CACb,OAAW,CAACM,CAAAA,CAAKM,CAAQ,CAAA,GAAK,MAAA,CAAO,OAAA,CAAQZ,EAAW,OAAO,CAAA,CAC7DE,EAAMI,CAAG,CAAA,CAAI,IAAIO,CAAAA,GACdD,CAAAA,CAAsB,KAAA,CAAMR,CAAAA,CAAcS,CAAI,CAAA,CAKrDX,EAAM,MAAA,CAAS,IAAM,CACnB,IAAMY,CAAAA,CAAQd,CAAAA,CAAW,OAAM,CAC/B,IAAA,IAAWM,CAAAA,IAAOD,CAAAA,CAChBD,CAAAA,CAAaE,CAAG,EAAE,GAAA,CAAIQ,CAAAA,CAAMR,CAAc,CAAC,EAE/C,EAGAJ,CAAAA,CAAM,SAAA,CAAY,IAAS,CACzB,IAAMa,CAAAA,CAAoC,EAAC,CAC3C,IAAA,IAAWT,CAAAA,IAAOD,CAAAA,CAChBU,CAAAA,CAAST,CAAG,EAAIF,CAAAA,CAAaE,CAAG,CAAA,EAAE,CAEpC,OAAOS,CACT,EAGA,IAAMC,CAAAA,CAAc,IAAI,GAAA,CACxB,OAAAd,EAAM,UAAA,CAAce,CAAAA,GAClBD,CAAAA,CAAY,GAAA,CAAIC,CAAQ,CAAA,CACjB,IAAMD,CAAAA,CAAY,MAAA,CAAOC,CAAQ,CAAA,CAAA,CAGnCf,CACT,CAKO,SAASgB,CAAAA,EAAoB,CAClCrB,CAAAA,CAAe,KAAA,GACjB","file":"chunk-TPFWKMCK.js","sourcesContent":["/**\n * Global state management via defineStore().\n *\n * Stores are singleton signal containers that persist across\n * components. They provide shared state, computed getters,\n * and actions — no external library needed.\n *\n * ```ts\n * const useCounterStore = defineStore('counter', {\n * state: () => ({ count: 0, name: 'Counter' }),\n * getters: {\n * doubled: (state) => state.count() * 2,\n * },\n * actions: {\n * increment() { this.count.update(c => c + 1); },\n * reset() { this.count.set(0); },\n * },\n * });\n *\n * // In any component:\n * const store = useCounterStore();\n * store.count(); // 0\n * store.doubled(); // 0\n * store.increment();\n * store.count(); // 1\n * ```\n */\n\nimport { signal, computed } from './signals.js';\nimport type { Signal, ReadonlySignal } from './signals.js';\n\n// --- Types ---\n\ntype StateFactory<S> = () => S;\n\ntype Getters<S, G> = {\n [K in keyof G]: (state: SignalifiedState<S>) => G[K];\n};\n\ntype Actions<A> = {\n [K in keyof A]: A[K] extends (...args: infer P) => infer R\n ? (...args: P) => R\n : never;\n};\n\n/** Maps plain state values to signals */\ntype SignalifiedState<S> = {\n [K in keyof S]: Signal<S[K]>;\n};\n\n/** The store instance returned to consumers */\nexport type Store<S, G, A> = SignalifiedState<S> & {\n [K in keyof G]: ReadonlySignal<G[K]>;\n} & {\n [K in keyof A]: A[K] extends (...args: infer P) => infer R\n ? (...args: P) => R\n : never;\n} & {\n /** Reset all state to initial values */\n $reset(): void;\n /** Subscribe to all state changes */\n $subscribe(callback: (state: S) => void): () => void;\n /** Get a plain snapshot of current state */\n $snapshot(): S;\n /** Store ID */\n $id: string;\n};\n\nexport interface StoreDefinition<S, G, A> {\n state: StateFactory<S>;\n getters?: Getters<S, G>;\n actions?: A;\n}\n\n// --- Store registry (singleton) ---\n\nconst storeInstances = new Map<string, Store<any, any, any>>();\n\n// --- defineStore ---\n\n/**\n * Define a global store. Returns a composable function that\n * always returns the same store instance (singleton).\n */\nexport function defineStore<\n S extends Record<string, unknown>,\n G extends Record<string, unknown> = {},\n A extends Record<string, (...args: any[]) => any> = {},\n>(\n id: string,\n definition: StoreDefinition<S, G, A>,\n): () => Store<S, G, A> {\n return () => {\n // Return existing instance if already created\n if (storeInstances.has(id)) {\n return storeInstances.get(id) as Store<S, G, A>;\n }\n\n const initialState = definition.state();\n const store = createStoreInstance(id, initialState, definition);\n storeInstances.set(id, store);\n return store;\n };\n}\n\nfunction createStoreInstance<\n S extends Record<string, unknown>,\n G extends Record<string, unknown>,\n A extends Record<string, (...args: any[]) => any>,\n>(\n id: string,\n initialState: S,\n definition: StoreDefinition<S, G, A>,\n): Store<S, G, A> {\n // Create signals for each state property\n const stateSignals: Record<string, Signal<unknown>> = {};\n const stateKeys = Object.keys(initialState);\n\n for (const key of stateKeys) {\n stateSignals[key] = signal(initialState[key]);\n }\n\n // Create computed getters\n const getterComputeds: Record<string, ReadonlySignal<unknown>> = {};\n if (definition.getters) {\n for (const [key, getterFn] of Object.entries(definition.getters)) {\n getterComputeds[key] = computed(() =>\n (getterFn as Function)(stateSignals),\n );\n }\n }\n\n // Build the store object\n const store: any = { $id: id };\n\n // Add state signals\n for (const key of stateKeys) {\n store[key] = stateSignals[key];\n }\n\n // Add getters\n for (const [key, comp] of Object.entries(getterComputeds)) {\n store[key] = comp;\n }\n\n // Bind actions with `this` pointing to the store's state signals\n if (definition.actions) {\n for (const [key, actionFn] of Object.entries(definition.actions)) {\n store[key] = (...args: unknown[]) =>\n (actionFn as Function).apply(stateSignals, args);\n }\n }\n\n // $reset\n store.$reset = () => {\n const fresh = definition.state();\n for (const key of stateKeys) {\n stateSignals[key].set(fresh[key as keyof S]);\n }\n };\n\n // $snapshot\n store.$snapshot = (): S => {\n const snapshot: Record<string, unknown> = {};\n for (const key of stateKeys) {\n snapshot[key] = stateSignals[key]();\n }\n return snapshot as S;\n };\n\n // $subscribe\n const subscribers = new Set<(state: S) => void>();\n store.$subscribe = (callback: (state: S) => void): (() => void) => {\n subscribers.add(callback);\n return () => subscribers.delete(callback);\n };\n\n return store as Store<S, G, A>;\n}\n\n/**\n * Clear all store instances (useful for testing).\n */\nexport function clearStores(): void {\n storeInstances.clear();\n}\n"]}
@@ -0,0 +1,32 @@
1
+ import {c}from'./chunk-FX7RHVM5.js';function f(r,e={}){let t=c(false),a=c(false),s=c(!navigator.onLine),i=null;window.addEventListener("online",()=>s.set(false)),window.addEventListener("offline",()=>s.set(true));let u=new Promise((h,l)=>{if(!("serviceWorker"in navigator)){l(new Error("Service workers not supported"));return}navigator.serviceWorker.register(r,{scope:e.scope}).then(n=>{i=n,t.set(true),e.onReady?.(n),h(n),n.addEventListener("updatefound",()=>{let o=n.installing;o&&o.addEventListener("statechange",()=>{o.state==="installed"&&navigator.serviceWorker.controller&&(a.set(true),e.onUpdate?.(n),e.autoReload&&(o.postMessage({type:"SKIP_WAITING"}),window.location.reload()));});});}).catch(n=>{e.onError?.(n),l(n);});});return {registered:()=>t(),updateAvailable:()=>a(),offline:()=>s(),ready:u,async update(){i&&await i.update();},skipWaiting(){i?.waiting&&(i.waiting.postMessage({type:"SKIP_WAITING"}),window.location.reload());},async unregister(){return i?i.unregister():false}}}function v(r){let e=`// Auto-generated service worker by AkashJS
2
+ const CACHE_VERSION = 'v1';
3
+
4
+ self.addEventListener('install', (event) => {
5
+ self.skipWaiting();
6
+ });
7
+
8
+ self.addEventListener('activate', (event) => {
9
+ event.waitUntil(clients.claim());
10
+ });
11
+
12
+ self.addEventListener('message', (event) => {
13
+ if (event.data?.type === 'SKIP_WAITING') {
14
+ self.skipWaiting();
15
+ }
16
+ });
17
+
18
+ self.addEventListener('fetch', (event) => {
19
+ const url = new URL(event.request.url);
20
+ `;for(let t of r){let a=t.match instanceof RegExp?t.match.toString():`new RegExp(${JSON.stringify(t.match.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"))})`,s=t.cacheName??"akash-cache";e+=`
21
+ if (${a}.test(url.pathname)) {
22
+ event.respondWith(${p(t.strategy,s)});
23
+ return;
24
+ }
25
+ `;}return e+=`
26
+ // Default: network-first
27
+ event.respondWith(
28
+ fetch(event.request).catch(() => caches.match(event.request))
29
+ );
30
+ });
31
+ `,e}function p(r,e){switch(r){case "cache-first":return `caches.match(event.request).then(cached => cached || fetch(event.request).then(response => { const clone = response.clone(); caches.open('${e}').then(cache => cache.put(event.request, clone)); return response; }))`;case "network-first":return `fetch(event.request).then(response => { const clone = response.clone(); caches.open('${e}').then(cache => cache.put(event.request, clone)); return response; }).catch(() => caches.match(event.request))`;case "stale-while-revalidate":return `caches.match(event.request).then(cached => { const fetchPromise = fetch(event.request).then(response => { caches.open('${e}').then(cache => cache.put(event.request, response.clone())); return response; }); return cached || fetchPromise; })`;case "network-only":return "fetch(event.request)";case "cache-only":return "caches.match(event.request)"}}async function y(r,e){return await Notification.requestPermission()!=="granted"?null:await r.pushManager.subscribe({userVisibleOnly:true,applicationServerKey:d(e)})}function d(r){let e="=".repeat((4-r.length%4)%4),t=(r+e).replace(/-/g,"+").replace(/_/g,"/"),a=atob(t);return Uint8Array.from(a,s=>s.charCodeAt(0))}export{f as a,v as b,y as c};//# sourceMappingURL=chunk-TXBFQLNL.js.map
32
+ //# sourceMappingURL=chunk-TXBFQLNL.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/pwa.ts"],"names":["registerServiceWorker","swUrl","options","registered","signal","updateAvailable","offline","registration","ready","resolve","reject","reg","newWorker","err","generateSWScript","routes","script","route","pattern","cacheName","generateStrategyCode","strategy","subscribePush","vapidPublicKey","urlBase64ToUint8Array","base64String","padding","base64","rawData","char"],"mappings":"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","file":"chunk-TXBFQLNL.js","sourcesContent":["/**\n * PWA / Service Worker support.\n *\n * Register service workers, configure caching strategies,\n * handle updates, and manage push notifications.\n *\n * ```ts\n * const sw = registerServiceWorker('/sw.js', {\n * onUpdate: () => toast.info('New version available!'),\n * });\n * sw.ready; // Promise<ServiceWorkerRegistration>\n * sw.update(); // check for updates\n * ```\n */\n\nimport { signal } from './signals.js';\nimport type { ReadonlySignal } from './signals.js';\n\n// =========================================================================\n// Types\n// =========================================================================\n\nexport interface SWOptions {\n /** Callback when a new version is available */\n onUpdate?: (registration: ServiceWorkerRegistration) => void;\n /** Callback when the SW is ready */\n onReady?: (registration: ServiceWorkerRegistration) => void;\n /** Callback on registration error */\n onError?: (error: Error) => void;\n /** Auto-reload on update (default: false) */\n autoReload?: boolean;\n /** Scope of the service worker */\n scope?: string;\n}\n\nexport interface SWRegistration {\n /** Whether the SW is registered */\n registered: ReadonlySignal<boolean>;\n /** Whether an update is available */\n updateAvailable: ReadonlySignal<boolean>;\n /** Whether the app is running offline */\n offline: ReadonlySignal<boolean>;\n /** The raw SW registration (available after ready) */\n ready: Promise<ServiceWorkerRegistration>;\n /** Check for updates */\n update(): Promise<void>;\n /** Skip waiting and activate new SW */\n skipWaiting(): void;\n /** Unregister the service worker */\n unregister(): Promise<boolean>;\n}\n\n// =========================================================================\n// Service Worker registration\n// =========================================================================\n\n/**\n * Register a service worker with update detection.\n */\nexport function registerServiceWorker(\n swUrl: string,\n options: SWOptions = {},\n): SWRegistration {\n const registered = signal(false);\n const updateAvailable = signal(false);\n const offline = signal(!navigator.onLine);\n\n let registration: ServiceWorkerRegistration | null = null;\n\n // Track online/offline\n window.addEventListener('online', () => offline.set(false));\n window.addEventListener('offline', () => offline.set(true));\n\n const ready = new Promise<ServiceWorkerRegistration>((resolve, reject) => {\n if (!('serviceWorker' in navigator)) {\n reject(new Error('Service workers not supported'));\n return;\n }\n\n navigator.serviceWorker\n .register(swUrl, { scope: options.scope })\n .then((reg) => {\n registration = reg;\n registered.set(true);\n options.onReady?.(reg);\n resolve(reg);\n\n // Listen for updates\n reg.addEventListener('updatefound', () => {\n const newWorker = reg.installing;\n if (!newWorker) return;\n\n newWorker.addEventListener('statechange', () => {\n if (newWorker.state === 'installed' && navigator.serviceWorker.controller) {\n updateAvailable.set(true);\n options.onUpdate?.(reg);\n\n if (options.autoReload) {\n newWorker.postMessage({ type: 'SKIP_WAITING' });\n window.location.reload();\n }\n }\n });\n });\n })\n .catch((err) => {\n options.onError?.(err);\n reject(err);\n });\n });\n\n return {\n registered: () => registered(),\n updateAvailable: () => updateAvailable(),\n offline: () => offline(),\n ready,\n async update() {\n if (registration) {\n await registration.update();\n }\n },\n skipWaiting() {\n if (registration?.waiting) {\n registration.waiting.postMessage({ type: 'SKIP_WAITING' });\n window.location.reload();\n }\n },\n async unregister() {\n if (registration) {\n return registration.unregister();\n }\n return false;\n },\n };\n}\n\n// =========================================================================\n// Caching strategies (for SW scripts)\n// =========================================================================\n\nexport type CacheStrategy = 'cache-first' | 'network-first' | 'stale-while-revalidate' | 'network-only' | 'cache-only';\n\nexport interface CacheRoute {\n /** URL pattern to match (string or regex) */\n match: string | RegExp;\n /** Caching strategy */\n strategy: CacheStrategy;\n /** Cache name */\n cacheName?: string;\n /** Max entries in cache */\n maxEntries?: number;\n /** Max age in seconds */\n maxAgeSeconds?: number;\n}\n\n/**\n * Generate a service worker script from cache route configs.\n *\n * ```ts\n * const swScript = generateSWScript([\n * { match: /\\.(?:js|css)$/, strategy: 'cache-first', cacheName: 'assets' },\n * { match: '/api/', strategy: 'network-first', maxAgeSeconds: 300 },\n * { match: /\\.(?:png|jpg|svg)$/, strategy: 'cache-first', cacheName: 'images' },\n * ]);\n * ```\n */\nexport function generateSWScript(routes: CacheRoute[]): string {\n let script = `// Auto-generated service worker by AkashJS\nconst CACHE_VERSION = 'v1';\n\nself.addEventListener('install', (event) => {\n self.skipWaiting();\n});\n\nself.addEventListener('activate', (event) => {\n event.waitUntil(clients.claim());\n});\n\nself.addEventListener('message', (event) => {\n if (event.data?.type === 'SKIP_WAITING') {\n self.skipWaiting();\n }\n});\n\nself.addEventListener('fetch', (event) => {\n const url = new URL(event.request.url);\n`;\n\n for (const route of routes) {\n const pattern = route.match instanceof RegExp\n ? route.match.toString()\n : `new RegExp(${JSON.stringify(route.match.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&'))})`;\n\n const cacheName = route.cacheName ?? 'akash-cache';\n\n script += `\n if (${pattern}.test(url.pathname)) {\n event.respondWith(${generateStrategyCode(route.strategy, cacheName)});\n return;\n }\n`;\n }\n\n script += `\n // Default: network-first\n event.respondWith(\n fetch(event.request).catch(() => caches.match(event.request))\n );\n});\n`;\n\n return script;\n}\n\nfunction generateStrategyCode(strategy: CacheStrategy, cacheName: string): string {\n switch (strategy) {\n case 'cache-first':\n return `caches.match(event.request).then(cached => cached || fetch(event.request).then(response => { const clone = response.clone(); caches.open('${cacheName}').then(cache => cache.put(event.request, clone)); return response; }))`;\n case 'network-first':\n return `fetch(event.request).then(response => { const clone = response.clone(); caches.open('${cacheName}').then(cache => cache.put(event.request, clone)); return response; }).catch(() => caches.match(event.request))`;\n case 'stale-while-revalidate':\n return `caches.match(event.request).then(cached => { const fetchPromise = fetch(event.request).then(response => { caches.open('${cacheName}').then(cache => cache.put(event.request, response.clone())); return response; }); return cached || fetchPromise; })`;\n case 'network-only':\n return `fetch(event.request)`;\n case 'cache-only':\n return `caches.match(event.request)`;\n }\n}\n\n// =========================================================================\n// Push notifications\n// =========================================================================\n\n/**\n * Request push notification permission and subscribe.\n */\nexport async function subscribePush(\n registration: ServiceWorkerRegistration,\n vapidPublicKey: string,\n): Promise<PushSubscription | null> {\n const permission = await Notification.requestPermission();\n if (permission !== 'granted') return null;\n\n const subscription = await registration.pushManager.subscribe({\n userVisibleOnly: true,\n applicationServerKey: urlBase64ToUint8Array(vapidPublicKey),\n });\n\n return subscription;\n}\n\nfunction urlBase64ToUint8Array(base64String: string): Uint8Array {\n const padding = '='.repeat((4 - (base64String.length % 4)) % 4);\n const base64 = (base64String + padding).replace(/-/g, '+').replace(/_/g, '/');\n const rawData = atob(base64);\n return Uint8Array.from(rawData, (char) => char.charCodeAt(0));\n}\n"]}
@@ -0,0 +1,2 @@
1
+ import {c}from'./chunk-FX7RHVM5.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 s=Date.now();return n===this.entry.peerId||s>this.entry.timestamp||s===this.entry.timestamp&&n>this.entry.peerId?(this.entry={value:e,timestamp:Math.max(s,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=[],s=[];return {send(t){e?.send(JSON.stringify({type:"op",room:i.room,...t}));},onReceive(t){n.push(t);let o=false;return ()=>{if(o)return;o=true;let c=n.indexOf(t);c!==-1&&n.splice(c,1);}},onPresence(t){return s.push(t),()=>{let o=s.indexOf(t);o!==-1&&s.splice(o,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 o=JSON.parse(t.data);if(o.type==="op")for(let c of n)c(o);else if(o.type==="presence")for(let c of s)c(o.peerId,o.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){i.push(e);let n=false;return ()=>{if(n)return;n=true;let s=i.indexOf(e);s!==-1&&i.splice(s,1);}},connect(){},disconnect(){}}}var w=0;function O(i,e,n={}){let s=n.peerId??`peer-${++w}-${Date.now()}`,t=n.transport??h(),o=new Map,c$1={};for(let[r,a]of Object.entries(e))o.set(r,new g(a,s)),c$1[r]=c(a);let l={};for(let r of Object.keys(e)){let a=c$1[r],y=o.get(r),p=(()=>a());p.set=u=>{y.set(u,s),a.set(u),t.send({type:"set",key:r,value:u,timestamp:y.timestamp,peerId:s});},p.update=u=>{p.set(u(a()));},p.peek=()=>a.peek(),l[r]=p;}let S=c([]),m=c(false),k=c({}),f=c(new Map),v=t.onReceive(r=>{r.type==="set"&&o.has(r.key)&&o.get(r.key).merge({value:r.value,timestamp:r.timestamp,peerId:r.peerId})&&c$1[r.key].set(r.value);}),T=t.onPresence?.((r,a)=>{f.update(y=>{let p=new Map(y);return p.set(r,a),p});});return {state:l,peers:()=>S(),presence:k,peerPresence:()=>f(),peerId:s,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-UID3D5XB.js.map
2
+ //# sourceMappingURL=chunk-UID3D5XB.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","removed","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-UID3D5XB.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 let removed = false;\n return () => {\n if (removed) return;\n removed = true;\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 let removed = false;\n return () => {\n if (removed) return;\n removed = true;\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
+ '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":"aAqFO,SAASA,EACdC,CAAAA,CACAC,CAAAA,CACAC,EAA4B,EAAC,CACX,CAClB,GAAM,CACJ,QAAA,CAAAC,CAAAA,CAAW,IACX,MAAA,CAAAC,CAAAA,CAAS,OACT,KAAA,CAAAC,CAAAA,CAAQ,EACR,UAAA,CAAAC,CAAAA,CAAa,CAAA,CACb,SAAA,CAAAC,EAAY,QAAA,CACZ,IAAA,CAAAC,EAAO,UAAA,CACP,UAAA,CAAAC,CACF,CAAA,CAAIP,CAAAA,CAGEQ,CAAAA,CAAwB,CAAC,EAAC,CAAG,EAAE,CAAA,CACrC,IAAA,GAAW,CAACC,CAAAA,CAAMC,CAAK,CAAA,GAAK,MAAA,CAAO,QAAQX,CAAU,CAAA,CAAG,CACtD,IAAMY,CAAAA,CAAcF,IAAS,GAAA,CAAM,YAAA,CAC/BA,CAAAA,GAAS,GAAA,CAAM,aACfA,CAAAA,CAEJ,GAAI,MAAM,OAAA,CAAQC,CAAK,EAAG,CACxB,GAAM,CAACE,CAAAA,CAAMC,CAAE,CAAA,CAAIH,CAAAA,CACfC,IAAgB,YAAA,EAAgBA,CAAAA,GAAgB,cACjDH,CAAAA,CAAU,CAAC,EAAU,SAAA,CAAY,CAAA,EAAGG,CAAW,CAAA,CAAA,EAAI,OAAOC,GAAS,QAAA,CAAWA,CAAAA,CAAO,KAAOA,CAAI,CAAA,CAAA,CAAA,CAChGJ,CAAAA,CAAU,CAAC,EAAU,SAAA,CAAY,CAAA,EAAGG,CAAW,CAAA,CAAA,EAAI,OAAOE,GAAO,QAAA,CAAWA,CAAAA,CAAK,IAAA,CAAOA,CAAE,MAE1FL,CAAAA,CAAU,CAAC,EAAUG,CAAW,CAAA,CAAIC,EACpCJ,CAAAA,CAAU,CAAC,CAAA,CAAUG,CAAW,EAAIE,CAAAA,EAEzC,CAAA,KACGL,EAAU,CAAC,CAAA,CAAUG,CAAW,CAAA,CAAID,EAEzC,CAEA,IAAMI,CAAAA,CAAYhB,EAAG,OAAA,CAAQU,CAAAA,CAAW,CACtC,QAAA,CAAAP,CAAAA,CACA,OAAAC,CAAAA,CACA,KAAA,CAAAC,CAAAA,CACA,UAAA,CAAAC,EACA,SAAA,CAAAC,CAAAA,CACA,KAAAC,CACF,CAAC,EAEKS,CAAAA,CAAW,IAAI,OAAA,CAAeC,CAAAA,EAAY,CAC9CF,CAAAA,CAAU,QAAA,CAAW,IAAM,CACzBP,CAAAA,KACAS,CAAAA,GACF,EACF,CAAC,EAED,OAAO,CACL,KAAM,IAAMF,CAAAA,CAAU,MAAK,CAC3B,KAAA,CAAO,IAAMA,CAAAA,CAAU,KAAA,GACvB,MAAA,CAAQ,IAAMA,EAAU,MAAA,EAAO,CAC/B,QAAS,IAAMA,CAAAA,CAAU,OAAA,EAAQ,CACjC,SAAAC,CACF,CACF,CAgBO,SAASE,CAAAA,CACdC,EACAnB,CAAAA,CACAC,CAAAA,CAA0B,EAAC,CACP,CACpB,GAAM,CAAE,QAAAmB,CAAAA,CAAU,EAAA,CAAI,KAAAP,CAAAA,CAAO,OAAA,CAAS,GAAGQ,CAAY,EAAIpB,CAAAA,CAEnDqB,CAAAA,CAA0B,OAAOH,CAAAA,EAAa,QAAA,CAChD,MAAM,IAAA,CAAK,QAAA,CAAS,gBAAA,CAA8BA,CAAQ,CAAC,CAAA,CAC3DA,CAAAA,CAEEI,EAA+B,EAAC,CAChCC,EAAQF,CAAAA,CAAS,MAAA,CAEvB,OAAAA,CAAAA,CAAS,QAAQ,CAACvB,CAAAA,CAAI0B,IAAM,CAC1B,IAAIrB,EAASiB,CAAAA,CAAY,KAAA,EAAS,CAAA,CAElC,OAAQR,GACN,KAAK,QAAST,CAAAA,EAASqB,CAAAA,CAAIL,EAAS,MACpC,KAAK,KAAA,CAAOhB,CAAAA,EAAAA,CAAUoB,EAAQ,CAAA,CAAIC,CAAAA,EAAKL,EAAS,MAChD,KAAK,SAAUhB,CAAAA,EAAS,IAAA,CAAK,IAAI,IAAA,CAAK,KAAA,CAAMoB,EAAQ,CAAC,CAAA,CAAIC,CAAC,CAAA,CAAIL,CAAAA,CAAS,KACzE,CAEAG,CAAAA,CAAS,IAAA,CAAKzB,CAAAA,CAAQC,EAAIC,CAAAA,CAAY,CAAE,GAAGqB,CAAAA,CAAa,KAAA,CAAAjB,CAAM,CAAC,CAAC,EAClE,CAAC,EAEMmB,CACT,CAgBA,eAAsBG,CAAAA,CACpBC,CAAAA,CACe,CACf,IAAA,GAAW,CAAC5B,CAAAA,CAAI6B,CAAAA,CAAOC,CAAI,CAAA,GAAKF,CAAAA,CAE9B,MADa7B,CAAAA,CAAQC,CAAAA,CAAI6B,EAAOC,CAAI,CAAA,CACzB,SAEf,CASA,eAAsBC,EACpBH,CAAAA,CACe,CACf,IAAMJ,CAAAA,CAAWI,CAAAA,CAAM,IAAI,CAAC,CAAC5B,CAAAA,CAAI6B,CAAAA,CAAOC,CAAI,CAAA,GAAM/B,CAAAA,CAAQC,EAAI6B,CAAAA,CAAOC,CAAI,CAAC,CAAA,CAC1E,MAAM,OAAA,CAAQ,GAAA,CAAIN,EAAS,GAAA,CAAKQ,CAAAA,EAAMA,EAAE,QAAQ,CAAC,EACnD,CAgBO,SAASC,CAAAA,CACdjC,CAAAA,CACAkC,EACAhC,CAAAA,CAAyB,GACP,CAClB,GAAM,CACJ,SAAA,CAAAiC,CAAAA,CAAY,IACZ,OAAA,CAAAC,CAAAA,CAAU,GACV,IAAA,CAAAC,CAAAA,CAAO,EACP,SAAA,CAAAC,CAAAA,CAAY,IACZ,UAAA,CAAA7B,CACF,CAAA,CAAIP,CAAAA,CAEEqC,EAAkC,EAAC,CACnCC,EAAmC,EAAC,CAGpCC,EAAW,MAAA,CAAO,gBAAA,CAAiBzC,CAAE,CAAA,CAC3C,QAAWW,CAAAA,IAAQ,MAAA,CAAO,KAAKuB,CAAM,CAAA,CACnCK,EAAQ5B,CAAI,CAAA,CAAI,UAAA,CAAW8B,CAAAA,CAAS,iBAAiB9B,CAAI,CAAC,GAAK,CAAA,CAC/D6B,CAAAA,CAAS7B,CAAI,CAAA,CAAI,CAAA,CAGnB,IAAI+B,CAAAA,CAAY,KACZC,CAAAA,CAAQ,CAAA,CAERC,EACE3B,CAAAA,CAAW,IAAI,QAAeC,CAAAA,EAAY,CAAE0B,CAAAA,CAAkB1B,EAAS,CAAC,CAAA,CAE9E,SAAS2B,GAAa,CACpB,GAAI,CAACH,CAAAA,CAAW,OAEhB,IAAII,CAAAA,CAAa,KACXC,CAAAA,CAAK,CAAA,CAAI,GAEf,IAAA,IAAWpC,CAAAA,IAAQ,OAAO,IAAA,CAAKuB,CAAM,CAAA,CAAG,CACtC,IAAMc,CAAAA,CAAeT,CAAAA,CAAQ5B,CAAI,CAAA,CAAIuB,CAAAA,CAAOvB,CAAI,CAAA,CAC1CsC,CAAAA,CAAc,CAACd,CAAAA,CAAYa,CAAAA,CAC3BE,EAAe,CAACd,CAAAA,CAAUI,EAAS7B,CAAI,CAAA,CACvCwC,GAAgBF,CAAAA,CAAcC,CAAAA,EAAgBb,CAAAA,CAEpDG,CAAAA,CAAS7B,CAAI,CAAA,EAAKwC,CAAAA,CAAeJ,EACjCR,CAAAA,CAAQ5B,CAAI,GAAK6B,CAAAA,CAAS7B,CAAI,CAAA,CAAIoC,CAAAA,CAAAA,CAE9B,KAAK,GAAA,CAAIP,CAAAA,CAAS7B,CAAI,CAAC,CAAA,CAAI2B,GAAa,IAAA,CAAK,GAAA,CAAIU,CAAY,CAAA,CAAIV,KACnEQ,CAAAA,CAAa,KAAA,EAEjB,CAKA,GAFAM,CAAAA,CAAkBpD,EAAIuC,CAAO,CAAA,CAEzBO,EAAY,CAEd,IAAA,IAAWnC,KAAQ,MAAA,CAAO,IAAA,CAAKuB,CAAM,CAAA,CACnCK,CAAAA,CAAQ5B,CAAI,CAAA,CAAIuB,CAAAA,CAAOvB,CAAI,CAAA,CAE7ByC,EAAkBpD,CAAAA,CAAIuC,CAAO,EAC7BG,CAAAA,CAAY,KAAA,CACZjC,KAAa,CACbmC,CAAAA,GACF,CAAA,KACED,EAAQ,qBAAA,CAAsBE,CAAI,EAEtC,CAEA,OAAAF,EAAQ,qBAAA,CAAsBE,CAAI,CAAA,CAE3B,CACL,MAAO,CAAOH,CAAAA,GAAaA,EAAY,IAAA,CAAMG,CAAAA,IAAU,CAAA,CACvD,KAAA,EAAQ,CAAEH,CAAAA,CAAY,KAAA,CAAO,qBAAqBC,CAAK,EAAG,EAC1D,MAAA,EAAS,CAAED,EAAY,KAAA,CAAO,oBAAA,CAAqBC,CAAK,EAAG,EAC3D,OAAA,EAAU,CACR,QAAWhC,CAAAA,IAAQ,MAAA,CAAO,KAAKuB,CAAM,CAAA,CACnCM,CAAAA,CAAS7B,CAAI,EAAI,CAAC6B,CAAAA,CAAS7B,CAAI,EAEnC,CAAA,CACA,SAAAM,CACF,CACF,CAEA,SAASmC,EAAkBpD,CAAAA,CAAiBqD,CAAAA,CAAsC,CAChF,IAAMC,CAAAA,CAAuB,EAAC,CAC9B,IAAA,GAAW,CAAC3C,CAAAA,CAAMC,CAAK,IAAK,MAAA,CAAO,OAAA,CAAQyC,CAAM,CAAA,CAC/C,OAAQ1C,GACN,KAAK,GAAA,CAAK2C,CAAAA,CAAW,KAAK,CAAA,WAAA,EAAc1C,CAAK,KAAK,CAAA,CAAG,MACrD,KAAK,GAAA,CAAK0C,CAAAA,CAAW,IAAA,CAAK,CAAA,WAAA,EAAc1C,CAAK,CAAA,GAAA,CAAK,CAAA,CAAG,MACrD,KAAK,OAAA,CAAS0C,EAAW,IAAA,CAAK,CAAA,MAAA,EAAS1C,CAAK,CAAA,CAAA,CAAG,EAAG,MAClD,KAAK,SAAU0C,CAAAA,CAAW,IAAA,CAAK,UAAU1C,CAAK,CAAA,IAAA,CAAM,EAAG,MACvD,KAAK,UAAWZ,CAAAA,CAAG,KAAA,CAAM,QAAU,MAAA,CAAOY,CAAK,EAAG,MAClD,QAASZ,CAAAA,CAAG,KAAA,CAAM,YAAYW,CAAAA,CAAM,MAAA,CAAOC,CAAK,CAAC,CAAA,CAAG,KACtD,CAEE0C,CAAAA,CAAW,MAAA,CAAS,CAAA,GACtBtD,EAAG,KAAA,CAAM,SAAA,CAAYsD,EAAW,IAAA,CAAK,GAAG,GAE5C,CAmBO,SAAS5C,CAAAA,CAAU6C,CAAAA,CAAgC,CACxD,OAAOA,CACT,CAuBO,SAASC,CAAAA,CACdC,EACAC,CAAAA,CAAmC,GACnC,CACA,OAAO,CACL,MAAA,CAAAD,CAAAA,CACA,aAAazD,CAAAA,CAAiB2D,CAAAA,CAAmBzD,EAA8C,CAC7F,IAAMgC,CAAAA,CAASuB,CAAAA,CAAOE,CAAS,CAAA,CAC/B,GAAI,CAACzB,CAAAA,CAAQ,MAAM,IAAI,KAAA,CAAM,CAAA,yBAAA,EAA4ByB,CAAS,CAAA,CAAE,EAEpE,IAAM9B,CAAAA,CAAuC,EAAC,CAC9C,IAAA,GAAW,CAAC+B,CAAAA,CAAKhD,CAAK,CAAA,GAAK,MAAA,CAAO,QAAQsB,CAAM,CAAA,CAC9CL,EAAM+B,CAAG,CAAA,CAAIhD,EAGf,OAAOb,CAAAA,CAAQC,EAAI6B,CAAAA,CAAO,CAAE,GAAG6B,CAAAA,CAAgB,GAAGxD,CAAQ,CAAC,CAC7D,CACF,CACF","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 chunk3Q7GK4DL_cjs=require('./chunk-3Q7GK4DL.cjs');var S=new Map;function p(r,a){return ()=>{if(S.has(r))return S.get(r);let s=a.state(),n=u(r,s,a);return S.set(r,n),n}}function u(r,a,s){let n={},i=Object.keys(a);for(let e of i)n[e]=chunk3Q7GK4DL_cjs.c(a[e]);let c={};if(s.getters)for(let[e,t]of Object.entries(s.getters))c[e]=chunk3Q7GK4DL_cjs.d(()=>t(n));let o={$id:r};for(let e of i)o[e]=n[e];for(let[e,t]of Object.entries(c))o[e]=t;if(s.actions)for(let[e,t]of Object.entries(s.actions))o[e]=(...d)=>t.apply(n,d);o.$reset=()=>{let e=s.state();for(let t of i)n[t].set(e[t]);},o.$snapshot=()=>{let e={};for(let t of i)e[t]=n[t]();return e};let g=new Set;return o.$subscribe=e=>(g.add(e),()=>g.delete(e)),o}function l(){S.clear();}exports.a=p;exports.b=l;//# sourceMappingURL=chunk-YZORCUDS.cjs.map
2
+ //# sourceMappingURL=chunk-YZORCUDS.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/store.ts"],"names":["storeInstances","defineStore","id","definition","initialState","store","createStoreInstance","stateSignals","stateKeys","key","signal","getterComputeds","getterFn","computed","comp","actionFn","args","fresh","snapshot","subscribers","callback","clearStores"],"mappings":"mEA4EA,IAAMA,CAAAA,CAAiB,IAAI,GAAA,CAQpB,SAASC,EAKdC,CAAAA,CACAC,CAAAA,CACsB,CACtB,OAAO,IAAM,CAEX,GAAIH,CAAAA,CAAe,GAAA,CAAIE,CAAE,CAAA,CACvB,OAAOF,EAAe,GAAA,CAAIE,CAAE,CAAA,CAG9B,IAAME,CAAAA,CAAeD,CAAAA,CAAW,OAAM,CAChCE,CAAAA,CAAQC,EAAoBJ,CAAAA,CAAIE,CAAAA,CAAcD,CAAU,CAAA,CAC9D,OAAAH,CAAAA,CAAe,GAAA,CAAIE,CAAAA,CAAIG,CAAK,EACrBA,CACT,CACF,CAEA,SAASC,CAAAA,CAKPJ,CAAAA,CACAE,EACAD,CAAAA,CACgB,CAEhB,IAAMI,CAAAA,CAAgD,EAAC,CACjDC,EAAY,MAAA,CAAO,IAAA,CAAKJ,CAAY,CAAA,CAE1C,IAAA,IAAWK,KAAOD,CAAAA,CAChBD,CAAAA,CAAaE,CAAG,CAAA,CAAIC,mBAAAA,CAAON,CAAAA,CAAaK,CAAG,CAAC,CAAA,CAI9C,IAAME,CAAAA,CAA2D,EAAC,CAClE,GAAIR,CAAAA,CAAW,OAAA,CACb,IAAA,GAAW,CAACM,CAAAA,CAAKG,CAAQ,IAAK,MAAA,CAAO,OAAA,CAAQT,EAAW,OAAO,CAAA,CAC7DQ,EAAgBF,CAAG,CAAA,CAAII,mBAAAA,CAAS,IAC7BD,CAAAA,CAAsBL,CAAY,CACrC,CAAA,CAKJ,IAAMF,CAAAA,CAAa,CAAE,GAAA,CAAKH,CAAG,EAG7B,IAAA,IAAWO,CAAAA,IAAOD,CAAAA,CAChBH,CAAAA,CAAMI,CAAG,CAAA,CAAIF,EAAaE,CAAG,CAAA,CAI/B,OAAW,CAACA,CAAAA,CAAKK,CAAI,CAAA,GAAK,MAAA,CAAO,OAAA,CAAQH,CAAe,CAAA,CACtDN,CAAAA,CAAMI,CAAG,CAAA,CAAIK,CAAAA,CAIf,GAAIX,CAAAA,CAAW,OAAA,CACb,OAAW,CAACM,CAAAA,CAAKM,CAAQ,CAAA,GAAK,MAAA,CAAO,OAAA,CAAQZ,EAAW,OAAO,CAAA,CAC7DE,EAAMI,CAAG,CAAA,CAAI,IAAIO,CAAAA,GACdD,CAAAA,CAAsB,KAAA,CAAMR,CAAAA,CAAcS,CAAI,CAAA,CAKrDX,EAAM,MAAA,CAAS,IAAM,CACnB,IAAMY,CAAAA,CAAQd,CAAAA,CAAW,OAAM,CAC/B,IAAA,IAAWM,CAAAA,IAAOD,CAAAA,CAChBD,CAAAA,CAAaE,CAAG,EAAE,GAAA,CAAIQ,CAAAA,CAAMR,CAAc,CAAC,EAE/C,EAGAJ,CAAAA,CAAM,SAAA,CAAY,IAAS,CACzB,IAAMa,CAAAA,CAAoC,EAAC,CAC3C,IAAA,IAAWT,CAAAA,IAAOD,CAAAA,CAChBU,CAAAA,CAAST,CAAG,EAAIF,CAAAA,CAAaE,CAAG,CAAA,EAAE,CAEpC,OAAOS,CACT,EAGA,IAAMC,CAAAA,CAAc,IAAI,GAAA,CACxB,OAAAd,EAAM,UAAA,CAAce,CAAAA,GAClBD,CAAAA,CAAY,GAAA,CAAIC,CAAQ,CAAA,CACjB,IAAMD,CAAAA,CAAY,MAAA,CAAOC,CAAQ,CAAA,CAAA,CAGnCf,CACT,CAKO,SAASgB,CAAAA,EAAoB,CAClCrB,CAAAA,CAAe,KAAA,GACjB","file":"chunk-YZORCUDS.cjs","sourcesContent":["/**\n * Global state management via defineStore().\n *\n * Stores are singleton signal containers that persist across\n * components. They provide shared state, computed getters,\n * and actions — no external library needed.\n *\n * ```ts\n * const useCounterStore = defineStore('counter', {\n * state: () => ({ count: 0, name: 'Counter' }),\n * getters: {\n * doubled: (state) => state.count() * 2,\n * },\n * actions: {\n * increment() { this.count.update(c => c + 1); },\n * reset() { this.count.set(0); },\n * },\n * });\n *\n * // In any component:\n * const store = useCounterStore();\n * store.count(); // 0\n * store.doubled(); // 0\n * store.increment();\n * store.count(); // 1\n * ```\n */\n\nimport { signal, computed } from './signals.js';\nimport type { Signal, ReadonlySignal } from './signals.js';\n\n// --- Types ---\n\ntype StateFactory<S> = () => S;\n\ntype Getters<S, G> = {\n [K in keyof G]: (state: SignalifiedState<S>) => G[K];\n};\n\ntype Actions<A> = {\n [K in keyof A]: A[K] extends (...args: infer P) => infer R\n ? (...args: P) => R\n : never;\n};\n\n/** Maps plain state values to signals */\ntype SignalifiedState<S> = {\n [K in keyof S]: Signal<S[K]>;\n};\n\n/** The store instance returned to consumers */\nexport type Store<S, G, A> = SignalifiedState<S> & {\n [K in keyof G]: ReadonlySignal<G[K]>;\n} & {\n [K in keyof A]: A[K] extends (...args: infer P) => infer R\n ? (...args: P) => R\n : never;\n} & {\n /** Reset all state to initial values */\n $reset(): void;\n /** Subscribe to all state changes */\n $subscribe(callback: (state: S) => void): () => void;\n /** Get a plain snapshot of current state */\n $snapshot(): S;\n /** Store ID */\n $id: string;\n};\n\nexport interface StoreDefinition<S, G, A> {\n state: StateFactory<S>;\n getters?: Getters<S, G>;\n actions?: A;\n}\n\n// --- Store registry (singleton) ---\n\nconst storeInstances = new Map<string, Store<any, any, any>>();\n\n// --- defineStore ---\n\n/**\n * Define a global store. Returns a composable function that\n * always returns the same store instance (singleton).\n */\nexport function defineStore<\n S extends Record<string, unknown>,\n G extends Record<string, unknown> = {},\n A extends Record<string, (...args: any[]) => any> = {},\n>(\n id: string,\n definition: StoreDefinition<S, G, A>,\n): () => Store<S, G, A> {\n return () => {\n // Return existing instance if already created\n if (storeInstances.has(id)) {\n return storeInstances.get(id) as Store<S, G, A>;\n }\n\n const initialState = definition.state();\n const store = createStoreInstance(id, initialState, definition);\n storeInstances.set(id, store);\n return store;\n };\n}\n\nfunction createStoreInstance<\n S extends Record<string, unknown>,\n G extends Record<string, unknown>,\n A extends Record<string, (...args: any[]) => any>,\n>(\n id: string,\n initialState: S,\n definition: StoreDefinition<S, G, A>,\n): Store<S, G, A> {\n // Create signals for each state property\n const stateSignals: Record<string, Signal<unknown>> = {};\n const stateKeys = Object.keys(initialState);\n\n for (const key of stateKeys) {\n stateSignals[key] = signal(initialState[key]);\n }\n\n // Create computed getters\n const getterComputeds: Record<string, ReadonlySignal<unknown>> = {};\n if (definition.getters) {\n for (const [key, getterFn] of Object.entries(definition.getters)) {\n getterComputeds[key] = computed(() =>\n (getterFn as Function)(stateSignals),\n );\n }\n }\n\n // Build the store object\n const store: any = { $id: id };\n\n // Add state signals\n for (const key of stateKeys) {\n store[key] = stateSignals[key];\n }\n\n // Add getters\n for (const [key, comp] of Object.entries(getterComputeds)) {\n store[key] = comp;\n }\n\n // Bind actions with `this` pointing to the store's state signals\n if (definition.actions) {\n for (const [key, actionFn] of Object.entries(definition.actions)) {\n store[key] = (...args: unknown[]) =>\n (actionFn as Function).apply(stateSignals, args);\n }\n }\n\n // $reset\n store.$reset = () => {\n const fresh = definition.state();\n for (const key of stateKeys) {\n stateSignals[key].set(fresh[key as keyof S]);\n }\n };\n\n // $snapshot\n store.$snapshot = (): S => {\n const snapshot: Record<string, unknown> = {};\n for (const key of stateKeys) {\n snapshot[key] = stateSignals[key]();\n }\n return snapshot as S;\n };\n\n // $subscribe\n const subscribers = new Set<(state: S) => void>();\n store.$subscribe = (callback: (state: S) => void): (() => void) => {\n subscribers.add(callback);\n return () => subscribers.delete(callback);\n };\n\n return store as Store<S, G, A>;\n}\n\n/**\n * Clear all store instances (useful for testing).\n */\nexport function clearStores(): void {\n storeInstances.clear();\n}\n"]}
package/dist/core.cjs ADDED
@@ -0,0 +1,2 @@
1
+ 'use strict';var chunkAQDP6FRO_cjs=require('./chunk-AQDP6FRO.cjs'),chunk3Q7GK4DL_cjs=require('./chunk-3Q7GK4DL.cjs');Object.defineProperty(exports,"For",{enumerable:true,get:function(){return chunkAQDP6FRO_cjs.t}});Object.defineProperty(exports,"Show",{enumerable:true,get:function(){return chunkAQDP6FRO_cjs.s}});Object.defineProperty(exports,"bindProperty",{enumerable:true,get:function(){return chunkAQDP6FRO_cjs.o}});Object.defineProperty(exports,"bindText",{enumerable:true,get:function(){return chunkAQDP6FRO_cjs.n}});Object.defineProperty(exports,"bindVisible",{enumerable:true,get:function(){return chunkAQDP6FRO_cjs.p}});Object.defineProperty(exports,"cloneTemplate",{enumerable:true,get:function(){return chunkAQDP6FRO_cjs.l}});Object.defineProperty(exports,"createContext",{enumerable:true,get:function(){return chunkAQDP6FRO_cjs.g}});Object.defineProperty(exports,"createElement",{enumerable:true,get:function(){return chunkAQDP6FRO_cjs.j}});Object.defineProperty(exports,"createText",{enumerable:true,get:function(){return chunkAQDP6FRO_cjs.k}});Object.defineProperty(exports,"defineComponent",{enumerable:true,get:function(){return chunkAQDP6FRO_cjs.A}});Object.defineProperty(exports,"inject",{enumerable:true,get:function(){return chunkAQDP6FRO_cjs.i}});Object.defineProperty(exports,"insert",{enumerable:true,get:function(){return chunkAQDP6FRO_cjs.v}});Object.defineProperty(exports,"nodeToDOM",{enumerable:true,get:function(){return chunkAQDP6FRO_cjs.u}});Object.defineProperty(exports,"onError",{enumerable:true,get:function(){return chunkAQDP6FRO_cjs.y}});Object.defineProperty(exports,"onMount",{enumerable:true,get:function(){return chunkAQDP6FRO_cjs.w}});Object.defineProperty(exports,"onUnmount",{enumerable:true,get:function(){return chunkAQDP6FRO_cjs.x}});Object.defineProperty(exports,"provide",{enumerable:true,get:function(){return chunkAQDP6FRO_cjs.h}});Object.defineProperty(exports,"ref",{enumerable:true,get:function(){return chunkAQDP6FRO_cjs.z}});Object.defineProperty(exports,"renderConditional",{enumerable:true,get:function(){return chunkAQDP6FRO_cjs.q}});Object.defineProperty(exports,"renderList",{enumerable:true,get:function(){return chunkAQDP6FRO_cjs.r}});Object.defineProperty(exports,"setProperty",{enumerable:true,get:function(){return chunkAQDP6FRO_cjs.m}});Object.defineProperty(exports,"batch",{enumerable:true,get:function(){return chunk3Q7GK4DL_cjs.a}});Object.defineProperty(exports,"computed",{enumerable:true,get:function(){return chunk3Q7GK4DL_cjs.d}});Object.defineProperty(exports,"effect",{enumerable:true,get:function(){return chunk3Q7GK4DL_cjs.e}});Object.defineProperty(exports,"flushSync",{enumerable:true,get:function(){return chunk3Q7GK4DL_cjs.b}});Object.defineProperty(exports,"signal",{enumerable:true,get:function(){return chunk3Q7GK4DL_cjs.c}});Object.defineProperty(exports,"untrack",{enumerable:true,get:function(){return chunk3Q7GK4DL_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{t as For,s as Show,o as bindProperty,n as bindText,p as bindVisible,l as cloneTemplate,g as createContext,j as createElement,k as createText,A as defineComponent,i as inject,v as insert,u as nodeToDOM,y as onError,w as onMount,x as onUnmount,h as provide,z as ref,q as renderConditional,r as renderList,m as setProperty}from'./chunk-2UTALKTF.js';export{a as batch,d as computed,e as effect,b as flushSync,c as signal,f as untrack}from'./chunk-FX7RHVM5.js';//# sourceMappingURL=core.js.map
2
+ //# sourceMappingURL=core.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"core.js"}