@elurjs/core 3.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (191) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +157 -0
  3. package/dist/lib/async.cjs +16 -0
  4. package/dist/lib/async.js +123 -0
  5. package/dist/lib/component.cjs +2 -0
  6. package/dist/lib/component.js +66 -0
  7. package/dist/lib/context.cjs +2 -0
  8. package/dist/lib/context.js +52 -0
  9. package/dist/lib/devtools.cjs +59 -0
  10. package/dist/lib/devtools.js +419 -0
  11. package/dist/lib/elur/async.cjs +16 -0
  12. package/dist/lib/elur/async.cjs.map +1 -0
  13. package/dist/lib/elur/async.d.cts +32 -0
  14. package/dist/lib/elur/async.d.ts +32 -0
  15. package/dist/lib/elur/async.js +123 -0
  16. package/dist/lib/elur/async.js.map +1 -0
  17. package/dist/lib/elur/component.cjs +2 -0
  18. package/dist/lib/elur/component.cjs.map +1 -0
  19. package/dist/lib/elur/component.d.cts +17 -0
  20. package/dist/lib/elur/component.d.ts +17 -0
  21. package/dist/lib/elur/component.js +66 -0
  22. package/dist/lib/elur/component.js.map +1 -0
  23. package/dist/lib/elur/context.cjs +2 -0
  24. package/dist/lib/elur/context.cjs.map +1 -0
  25. package/dist/lib/elur/context.d.cts +29 -0
  26. package/dist/lib/elur/context.d.ts +29 -0
  27. package/dist/lib/elur/context.js +52 -0
  28. package/dist/lib/elur/context.js.map +1 -0
  29. package/dist/lib/elur/devtools.cjs +59 -0
  30. package/dist/lib/elur/devtools.cjs.map +1 -0
  31. package/dist/lib/elur/devtools.d.cts +24 -0
  32. package/dist/lib/elur/devtools.d.ts +24 -0
  33. package/dist/lib/elur/devtools.js +419 -0
  34. package/dist/lib/elur/devtools.js.map +1 -0
  35. package/dist/lib/elur/form.cjs +2 -0
  36. package/dist/lib/elur/form.cjs.map +1 -0
  37. package/dist/lib/elur/form.d.cts +283 -0
  38. package/dist/lib/elur/form.d.ts +283 -0
  39. package/dist/lib/elur/form.js +315 -0
  40. package/dist/lib/elur/form.js.map +1 -0
  41. package/dist/lib/elur/hydrate/index.cjs +2 -0
  42. package/dist/lib/elur/hydrate/index.cjs.map +1 -0
  43. package/dist/lib/elur/hydrate/index.d.cts +13 -0
  44. package/dist/lib/elur/hydrate/index.d.ts +13 -0
  45. package/dist/lib/elur/hydrate/index.js +410 -0
  46. package/dist/lib/elur/hydrate/index.js.map +1 -0
  47. package/dist/lib/elur/index.d.cts +19 -0
  48. package/dist/lib/elur/index.d.ts +19 -0
  49. package/dist/lib/elur/lifecycle.cjs +2 -0
  50. package/dist/lib/elur/lifecycle.cjs.map +1 -0
  51. package/dist/lib/elur/lifecycle.d.cts +45 -0
  52. package/dist/lib/elur/lifecycle.d.ts +45 -0
  53. package/dist/lib/elur/lifecycle.js +39 -0
  54. package/dist/lib/elur/lifecycle.js.map +1 -0
  55. package/dist/lib/elur/plugins.cjs +2 -0
  56. package/dist/lib/elur/plugins.cjs.map +1 -0
  57. package/dist/lib/elur/plugins.d.cts +48 -0
  58. package/dist/lib/elur/plugins.d.ts +48 -0
  59. package/dist/lib/elur/plugins.js +59 -0
  60. package/dist/lib/elur/plugins.js.map +1 -0
  61. package/dist/lib/elur/reactivity.cjs +2 -0
  62. package/dist/lib/elur/reactivity.cjs.map +1 -0
  63. package/dist/lib/elur/reactivity.d.cts +60 -0
  64. package/dist/lib/elur/reactivity.d.ts +60 -0
  65. package/dist/lib/elur/reactivity.js +188 -0
  66. package/dist/lib/elur/reactivity.js.map +1 -0
  67. package/dist/lib/elur/router.cjs +12 -0
  68. package/dist/lib/elur/router.cjs.map +1 -0
  69. package/dist/lib/elur/router.d.cts +137 -0
  70. package/dist/lib/elur/router.d.ts +137 -0
  71. package/dist/lib/elur/router.js +513 -0
  72. package/dist/lib/elur/router.js.map +1 -0
  73. package/dist/lib/elur/server/index.cjs +2 -0
  74. package/dist/lib/elur/server/index.cjs.map +1 -0
  75. package/dist/lib/elur/server/index.d.cts +44 -0
  76. package/dist/lib/elur/server/index.d.ts +44 -0
  77. package/dist/lib/elur/server/index.js +307 -0
  78. package/dist/lib/elur/server/index.js.map +1 -0
  79. package/dist/lib/elur/store.cjs +2 -0
  80. package/dist/lib/elur/store.cjs.map +1 -0
  81. package/dist/lib/elur/store.d.cts +137 -0
  82. package/dist/lib/elur/store.d.ts +137 -0
  83. package/dist/lib/elur/store.js +143 -0
  84. package/dist/lib/elur/store.js.map +1 -0
  85. package/dist/lib/elur/template/bindings.cjs +2 -0
  86. package/dist/lib/elur/template/bindings.cjs.map +1 -0
  87. package/dist/lib/elur/template/bindings.d.cts +40 -0
  88. package/dist/lib/elur/template/bindings.d.ts +40 -0
  89. package/dist/lib/elur/template/bindings.js +214 -0
  90. package/dist/lib/elur/template/bindings.js.map +1 -0
  91. package/dist/lib/elur/template/dom-write.cjs +2 -0
  92. package/dist/lib/elur/template/dom-write.cjs.map +1 -0
  93. package/dist/lib/elur/template/dom-write.d.cts +5 -0
  94. package/dist/lib/elur/template/dom-write.d.ts +5 -0
  95. package/dist/lib/elur/template/dom-write.js +16 -0
  96. package/dist/lib/elur/template/dom-write.js.map +1 -0
  97. package/dist/lib/elur/template/error-boundary.cjs +2 -0
  98. package/dist/lib/elur/template/error-boundary.cjs.map +1 -0
  99. package/dist/lib/elur/template/error-boundary.d.cts +7 -0
  100. package/dist/lib/elur/template/error-boundary.d.ts +7 -0
  101. package/dist/lib/elur/template/error-boundary.js +90 -0
  102. package/dist/lib/elur/template/error-boundary.js.map +1 -0
  103. package/dist/lib/elur/template/html.cjs +2 -0
  104. package/dist/lib/elur/template/html.cjs.map +1 -0
  105. package/dist/lib/elur/template/html.d.cts +8 -0
  106. package/dist/lib/elur/template/html.d.ts +8 -0
  107. package/dist/lib/elur/template/html.js +104 -0
  108. package/dist/lib/elur/template/html.js.map +1 -0
  109. package/dist/lib/elur/template/index.cjs +1 -0
  110. package/dist/lib/elur/template/index.d.cts +15 -0
  111. package/dist/lib/elur/template/index.d.ts +15 -0
  112. package/dist/lib/elur/template/index.js +13 -0
  113. package/dist/lib/elur/template/keyed-diff.cjs +2 -0
  114. package/dist/lib/elur/template/keyed-diff.cjs.map +1 -0
  115. package/dist/lib/elur/template/keyed-diff.d.cts +32 -0
  116. package/dist/lib/elur/template/keyed-diff.d.ts +32 -0
  117. package/dist/lib/elur/template/keyed-diff.js +100 -0
  118. package/dist/lib/elur/template/keyed-diff.js.map +1 -0
  119. package/dist/lib/elur/template/keyed.cjs +2 -0
  120. package/dist/lib/elur/template/keyed.cjs.map +1 -0
  121. package/dist/lib/elur/template/keyed.d.cts +27 -0
  122. package/dist/lib/elur/template/keyed.d.ts +27 -0
  123. package/dist/lib/elur/template/keyed.js +52 -0
  124. package/dist/lib/elur/template/keyed.js.map +1 -0
  125. package/dist/lib/elur/template/mount-helpers.cjs +2 -0
  126. package/dist/lib/elur/template/mount-helpers.cjs.map +1 -0
  127. package/dist/lib/elur/template/mount-helpers.d.cts +29 -0
  128. package/dist/lib/elur/template/mount-helpers.d.ts +29 -0
  129. package/dist/lib/elur/template/mount-helpers.js +132 -0
  130. package/dist/lib/elur/template/mount-helpers.js.map +1 -0
  131. package/dist/lib/elur/template/node-binding.cjs +2 -0
  132. package/dist/lib/elur/template/node-binding.cjs.map +1 -0
  133. package/dist/lib/elur/template/node-binding.d.cts +6 -0
  134. package/dist/lib/elur/template/node-binding.d.ts +6 -0
  135. package/dist/lib/elur/template/node-binding.js +95 -0
  136. package/dist/lib/elur/template/node-binding.js.map +1 -0
  137. package/dist/lib/elur/template/portal.cjs +2 -0
  138. package/dist/lib/elur/template/portal.cjs.map +1 -0
  139. package/dist/lib/elur/template/portal.d.cts +19 -0
  140. package/dist/lib/elur/template/portal.d.ts +19 -0
  141. package/dist/lib/elur/template/portal.js +49 -0
  142. package/dist/lib/elur/template/portal.js.map +1 -0
  143. package/dist/lib/elur/template/raw.cjs +2 -0
  144. package/dist/lib/elur/template/raw.cjs.map +1 -0
  145. package/dist/lib/elur/template/raw.d.cts +9 -0
  146. package/dist/lib/elur/template/raw.d.ts +9 -0
  147. package/dist/lib/elur/template/raw.js +29 -0
  148. package/dist/lib/elur/template/raw.js.map +1 -0
  149. package/dist/lib/elur/template/sanitize.cjs +2 -0
  150. package/dist/lib/elur/template/sanitize.cjs.map +1 -0
  151. package/dist/lib/elur/template/sanitize.d.cts +16 -0
  152. package/dist/lib/elur/template/sanitize.d.ts +16 -0
  153. package/dist/lib/elur/template/sanitize.js +29 -0
  154. package/dist/lib/elur/template/sanitize.js.map +1 -0
  155. package/dist/lib/elur/template/transitions.cjs +2 -0
  156. package/dist/lib/elur/template/transitions.cjs.map +1 -0
  157. package/dist/lib/elur/template/transitions.d.cts +43 -0
  158. package/dist/lib/elur/template/transitions.d.ts +43 -0
  159. package/dist/lib/elur/template/transitions.js +96 -0
  160. package/dist/lib/elur/template/transitions.js.map +1 -0
  161. package/dist/lib/elur/template/types.cjs +2 -0
  162. package/dist/lib/elur/template/types.cjs.map +1 -0
  163. package/dist/lib/elur/template/types.d.cts +114 -0
  164. package/dist/lib/elur/template/types.d.ts +114 -0
  165. package/dist/lib/elur/template/types.js +23 -0
  166. package/dist/lib/elur/template/types.js.map +1 -0
  167. package/dist/lib/elur.cjs +1 -0
  168. package/dist/lib/elur.js +18 -0
  169. package/dist/lib/form.cjs +2 -0
  170. package/dist/lib/form.js +315 -0
  171. package/dist/lib/hydrate.cjs +2 -0
  172. package/dist/lib/hydrate.js +410 -0
  173. package/dist/lib/index.cjs +1 -0
  174. package/dist/lib/index.d.cts +2 -0
  175. package/dist/lib/index.d.ts +2 -0
  176. package/dist/lib/index.js +18 -0
  177. package/dist/lib/lifecycle.cjs +2 -0
  178. package/dist/lib/lifecycle.js +39 -0
  179. package/dist/lib/plugins.cjs +2 -0
  180. package/dist/lib/plugins.js +59 -0
  181. package/dist/lib/router.cjs +12 -0
  182. package/dist/lib/router.js +513 -0
  183. package/dist/lib/server.cjs +2 -0
  184. package/dist/lib/server.js +307 -0
  185. package/dist/lib/signals.cjs +2 -0
  186. package/dist/lib/signals.js +188 -0
  187. package/dist/lib/store.cjs +2 -0
  188. package/dist/lib/store.js +143 -0
  189. package/dist/lib/template.cjs +1 -0
  190. package/dist/lib/template.js +13 -0
  191. package/package.json +216 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"async.js","names":[],"sources":["../../src/elur/async.ts"],"sourcesContent":["import { signal, effect, Signal } from \"./reactivity.js\";\nimport { ElurComponent } from \"./lifecycle.js\";\nimport { type ElurTemplate, html, isElurTemplate } from \"./template/index.js\";\n\n// --- Types ---\n\ntype AsyncState<T> =\n | { status: \"pending\" }\n | { status: \"resolved\"; data: T }\n | { status: \"error\"; error: unknown };\n\nexport interface SuspenseOptions {\n fallback?: ElurTemplate;\n errorFallback?: (err: unknown) => ElurTemplate;\n resetOnRefresh?: boolean;\n invalidate?: Signal<unknown>;\n cacheKey?: string;\n staleTime?: number;\n}\n\n// --- Default fallbacks ---\n\nfunction defaultLoadingFallback(): ElurTemplate {\n return html`\n <span style=\"color:#52525b;font-size:13px;display:inline-flex;align-items:center;gap:6px\">\n <span class=\"elur-spinner\" style=\"\n display:inline-block;width:14px;height:14px;border-radius:50%;\n border:2px solid #38bdf840;border-top-color:#38bdf8;\n animation:elur-spin .7s linear infinite\n \"></span>\n Loading…\n </span>\n <style>@keyframes elur-spin{to{transform:rotate(360deg)}}</style>\n `;\n}\n\nfunction defaultErrorTemplate(err: unknown): ElurTemplate {\n return html`\n <span style=\"color:#f87171;font-size:13px\">\n ⚠ ${err instanceof Error ? err.message : String(err)}\n </span>\n `;\n}\n\n// --- Suspense Cache ---\n\ninterface SuspenseCacheEntry<T = unknown> {\n data?: T;\n fetchedAt: number;\n subscribers: number;\n}\n\nconst _suspenseCache = new Map<string, SuspenseCacheEntry>();\n\nconst DEFAULT_CACHE_TIME = 5 * 60 * 1000;\nlet _suspenseGcTimer: ReturnType<typeof setInterval> | null = null;\nlet _suspenseCacheTime = DEFAULT_CACHE_TIME;\n\nfunction _startSuspenseGC(): void {\n if (_suspenseGcTimer !== null) return;\n _suspenseGcTimer = setInterval(() => {\n const now = Date.now();\n for (const [key, entry] of _suspenseCache) {\n if (entry.subscribers <= 0 && now - entry.fetchedAt > _suspenseCacheTime) {\n _suspenseCache.delete(key);\n }\n }\n if (_suspenseCache.size === 0 && _suspenseGcTimer !== null) {\n clearInterval(_suspenseGcTimer);\n _suspenseGcTimer = null;\n }\n }, 60_000);\n}\n\nfunction _getSuspenseCacheEntry<T>(key: string): SuspenseCacheEntry<T> | undefined {\n const entry = _suspenseCache.get(key);\n if (entry && entry.fetchedAt > 0) return entry as SuspenseCacheEntry<T>;\n return undefined;\n}\n\nfunction _setSuspenseCacheEntry<T>(key: string, data: T): void {\n const existing = _suspenseCache.get(key);\n _suspenseCache.set(key, {\n data,\n fetchedAt: Date.now(),\n subscribers: existing?.subscribers ?? 0,\n });\n _startSuspenseGC();\n}\n\nfunction _subscribeSuspenseCache(key: string): void {\n const entry = _suspenseCache.get(key);\n if (entry) {\n entry.subscribers++;\n } else {\n _suspenseCache.set(key, { fetchedAt: 0, subscribers: 1 } as SuspenseCacheEntry<any>);\n }\n}\n\nfunction _unsubscribeSuspenseCache(key: string): void {\n const entry = _suspenseCache.get(key);\n if (entry) entry.subscribers = Math.max(0, entry.subscribers - 1);\n}\n\nfunction _isSuspenseCacheFresh(key: string, staleTime: number): boolean {\n const entry = _suspenseCache.get(key);\n if (!entry) return false;\n return Date.now() - entry.fetchedAt < staleTime;\n}\n\n// --- suspend() ---\n\n/**\n * Runs an async function and renders based on its state (pending/resolved/error).\n *\n * ```ts\n * const refresh = signal(0);\n * suspend(() => fetchData(), render, { invalidate: refresh });\n * refresh.update(n => n + 1);\n * ```\n */\nexport function suspend<T>(\n asyncFn: () => Promise<T>,\n renderFn: (data: T) => ElurTemplate | ElurComponent,\n options: SuspenseOptions = {}\n): ElurComponent {\n const {\n fallback,\n errorFallback,\n resetOnRefresh = false,\n invalidate,\n cacheKey,\n staleTime = 0,\n } = options;\n\n const resolvedFallback = fallback ?? defaultLoadingFallback();\n const resolvedErrorFallback = errorFallback ?? defaultErrorTemplate;\n\n class SuspendComponent extends ElurComponent {\n private _state: Signal<AsyncState<T>>;\n private _disposeWatcher: (() => void) | undefined;\n\n constructor() {\n super();\n const cached = cacheKey ? _getSuspenseCacheEntry<T>(cacheKey) : undefined;\n\n this._state = signal<AsyncState<T>>(\n cached && cached.data !== undefined\n ? { status: \"resolved\", data: cached.data }\n : { status: \"pending\" }\n );\n }\n\n onMount(): (() => void) | void {\n if (cacheKey) _subscribeSuspenseCache(cacheKey);\n\n const cached = cacheKey ? _getSuspenseCacheEntry<T>(cacheKey) : undefined;\n\n if (cached && _isSuspenseCacheFresh(cacheKey!, staleTime)) {\n // fresh — skip\n } else if (cached) {\n this._fetch();\n } else {\n this._run();\n }\n\n if (invalidate) {\n let first = true;\n this._disposeWatcher = effect(() => {\n invalidate.value;\n if (first) { first = false; return; }\n if (cacheKey) _suspenseCache.delete(cacheKey);\n this._run();\n });\n }\n\n return () => {\n this._disposeWatcher?.();\n if (cacheKey) _unsubscribeSuspenseCache(cacheKey);\n };\n }\n\n private _run(): void {\n if (resetOnRefresh || this._state.peek().status === \"pending\") {\n this._state.value = { status: \"pending\" };\n }\n this._fetch();\n }\n\n private _fetch(): void {\n asyncFn().then(\n (data) => {\n if (cacheKey) _setSuspenseCacheEntry(cacheKey, data);\n this._state.value = { status: \"resolved\", data };\n },\n (err) => { this._state.value = { status: \"error\", error: err }; }\n );\n }\n\n render(): ElurTemplate {\n return html`<div class=\"elur-suspense\" style=\"display:contents\">${() => {\n const s = this._state.value;\n if (s.status === \"pending\") return resolvedFallback;\n if (s.status === \"error\") return resolvedErrorFallback(s.error);\n return renderFn(s.data);\n }}</div>`;\n }\n }\n\n return new SuspendComponent();\n}\n\n// --- lazy() ---\n\nexport interface LazyOptions {\n /** Component selector when the module uses a named export. Defaults to `mod.default`. */\n selector?: (mod: Record<string, unknown>) => new () => ElurComponent;\n /** Template shown while the component is loading. */\n fallback?: ElurTemplate;\n}\n\n/**\n * Wraps a dynamic import for lazy-loading route components.\n * The module is loaded once and cached. Supports both default and named exports.\n */\nexport function lazy(\n importFn: () => Promise<Record<string, unknown>>,\n options?: ElurTemplate | LazyOptions\n): () => ElurComponent {\n const opts: LazyOptions =\n options === undefined || isElurTemplate(options as object)\n ? { fallback: options as ElurTemplate | undefined }\n : (options as LazyOptions);\n\n const selector = opts.selector ?? ((mod) => mod.default as new () => ElurComponent);\n let Cached: (new () => ElurComponent) | null = null;\n\n return (): ElurComponent => {\n if (Cached) return new Cached();\n\n return suspend(\n async () => {\n const mod = await importFn();\n Cached = selector(mod);\n return Cached;\n },\n (Comp) => new Comp(),\n { fallback: opts.fallback }\n );\n };\n}"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`./lifecycle.cjs`),t=require(`./context.cjs`),n=require(`./router.cjs`);function r(e){let t=typeof e==`string`?document.querySelector(e):e;if(!t)throw Error(`[elur] mount: container not found: ${e}`);return t}function i(i,a,o){if(e.isElurComponent(i)){let s=r(a);e._debugComponentMountStart(i),t._pushComponentContext();let c=()=>{},l=!1;try{o?.router&&(t.provide(n.RouterKey,o.router),n._debugRegisterRouter(o.router));try{i.onInit?.()}catch(e){if(i.onError)i.onError(e);else throw e}try{c=i.render()._render(s,null)}catch(e){if(i.onError)i.onError(e),c=()=>{},l=!0;else throw e}}finally{e._debugComponentMountEnd(i),t._popComponentContext()}let u;if(!l)try{let e=i.onMount?.();typeof e==`function`&&(u=e)}catch(e){if(i.onError)i.onError(e);else throw e}return{unmount(){try{i.onUnmount?.()}catch{}try{u?.()}catch{}c(),o?.router&&n._debugUnregisterRouter(o.router),e._debugComponentUnmount(i)}}}if(!o?.router)return i.mount(a);let s=r(a);t._pushComponentContext();let c;try{t.provide(n.RouterKey,o.router),n._debugRegisterRouter(o.router),c=i._render(s,null)}finally{t._popComponentContext()}return{unmount(){c(),n._debugUnregisterRouter(o.router)}}}exports.mount=i;
2
+ //# sourceMappingURL=component.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"component.cjs","names":[],"sources":["../../src/elur/component.ts"],"sourcesContent":["import type { ElurTemplate, ElurMountHandle } from \"./template/index.js\";\nimport {\n isElurComponent,\n _debugComponentMountStart,\n _debugComponentMountEnd,\n _debugComponentUnmount,\n type ElurComponent,\n} from \"./lifecycle.js\";\nimport { _pushComponentContext, _popComponentContext, provide } from \"./context.js\";\nimport { RouterKey, type Router, _debugRegisterRouter, _debugUnregisterRouter } from \"./router.js\";\n\nexport interface MountOptions {\n router?: Router;\n}\n\nfunction _resolveContainer(container: Element | string): Element {\n const el =\n typeof container === \"string\"\n ? (document.querySelector(container) as Element)\n : container;\n if (!el) {\n throw new Error(`[elur] mount: container not found: ${container}`);\n }\n return el;\n}\n\n/**\n * Mounts a ElurTemplate or ElurComponent into the DOM.\n *\n * mount(Counter(), \"#app\"); // ElurTemplate (function component)\n * mount(new Timer(), \"#app\"); // ElurComponent (class with lifecycle)\n *\n * @param component ElurTemplate (result of html``) or a ElurComponent instance.\n * @param container CSS selector or HTMLElement to mount into.\n * @returns { unmount() } — disposes effects and removes DOM.\n */\nexport function mount(\n component: ElurTemplate | ElurComponent,\n container: Element | string,\n options?: MountOptions\n): ElurMountHandle {\n if (isElurComponent(component)) {\n const el = _resolveContainer(container);\n\n _debugComponentMountStart(component);\n _pushComponentContext();\n let cleanup: () => void = () => { };\n let renderFailed = false;\n try {\n if (options?.router) {\n provide(RouterKey, options.router);\n _debugRegisterRouter(options.router);\n }\n try { component.onInit?.(); } catch (e) { if (component.onError) component.onError(e); else throw e; }\n try {\n cleanup = component.render()._render(el, null);\n } catch (e) {\n if (component.onError) {\n component.onError(e);\n cleanup = () => { };\n renderFailed = true;\n } else {\n throw e;\n }\n }\n } finally {\n _debugComponentMountEnd(component);\n _popComponentContext();\n }\n\n let mountCleanup: (() => void) | undefined;\n if (!renderFailed) {\n try {\n const ret = component.onMount?.();\n if (typeof ret === \"function\") mountCleanup = ret;\n } catch (e) {\n if (component.onError) component.onError(e);\n else throw e;\n }\n }\n\n return {\n unmount() {\n try { component.onUnmount?.(); } catch { /* ignore */ }\n try { mountCleanup?.(); } catch { /* ignore */ }\n cleanup();\n if (options?.router) _debugUnregisterRouter(options.router);\n _debugComponentUnmount(component);\n },\n };\n }\n\n if (!options?.router) {\n // ElurTemplate: delegar al método .mount() interno\n return (component as ElurTemplate).mount(container);\n }\n\n // For template roots, create a context frame so elurRouter()/inject() can resolve.\n const el = _resolveContainer(container);\n _pushComponentContext();\n let cleanup: () => void;\n try {\n provide(RouterKey, options.router);\n _debugRegisterRouter(options.router);\n cleanup = (component as ElurTemplate)._render(el, null);\n } finally {\n _popComponentContext();\n }\n\n return {\n unmount() {\n cleanup();\n _debugUnregisterRouter(options.router!);\n },\n };\n}\n"],"mappings":"2JAeA,SAAS,EAAkB,EAAsC,CAC7D,IAAM,EACF,OAAO,GAAc,SACd,SAAS,cAAc,EAAU,CAClC,EACV,GAAI,CAAC,EACD,MAAU,MAAM,sCAAsC,IAAY,CAEtE,OAAO,EAaX,SAAgB,EACZ,EACA,EACA,EACe,CACf,GAAI,EAAA,gBAAgB,EAAU,CAAE,CAC5B,IAAM,EAAK,EAAkB,EAAU,CAEvC,EAAA,0BAA0B,EAAU,CACpC,EAAA,uBAAuB,CACvB,IAAI,MAA4B,GAC5B,EAAe,GACnB,GAAI,CACI,GAAS,SACT,EAAA,QAAQ,EAAA,UAAW,EAAQ,OAAO,CAClC,EAAA,qBAAqB,EAAQ,OAAO,EAExC,GAAI,CAAE,EAAU,UAAU,OAAW,EAAG,CAAE,GAAI,EAAU,QAAS,EAAU,QAAQ,EAAE,MAAO,MAAM,EAClG,GAAI,CACA,EAAU,EAAU,QAAQ,CAAC,QAAQ,EAAI,KAAK,OACzC,EAAG,CACR,GAAI,EAAU,QACV,EAAU,QAAQ,EAAE,CACpB,MAAgB,GAChB,EAAe,QAEf,MAAM,UAGR,CACN,EAAA,wBAAwB,EAAU,CAClC,EAAA,sBAAsB,CAG1B,IAAI,EACJ,GAAI,CAAC,EACD,GAAI,CACA,IAAM,EAAM,EAAU,WAAW,CAC7B,OAAO,GAAQ,aAAY,EAAe,SACzC,EAAG,CACR,GAAI,EAAU,QAAS,EAAU,QAAQ,EAAE,MACtC,MAAM,EAInB,MAAO,CACH,SAAU,CACN,GAAI,CAAE,EAAU,aAAa,MAAU,EACvC,GAAI,CAAE,KAAgB,MAAU,EAChC,GAAS,CACL,GAAS,QAAQ,EAAA,uBAAuB,EAAQ,OAAO,CAC3D,EAAA,uBAAuB,EAAU,EAExC,CAGL,GAAI,CAAC,GAAS,OAEV,OAAQ,EAA2B,MAAM,EAAU,CAIvD,IAAM,EAAK,EAAkB,EAAU,CACvC,EAAA,uBAAuB,CACvB,IAAI,EACJ,GAAI,CACA,EAAA,QAAQ,EAAA,UAAW,EAAQ,OAAO,CAClC,EAAA,qBAAqB,EAAQ,OAAO,CACpC,EAAW,EAA2B,QAAQ,EAAI,KAAK,QACjD,CACN,EAAA,sBAAsB,CAG1B,MAAO,CACH,SAAU,CACN,GAAS,CACT,EAAA,uBAAuB,EAAQ,OAAQ,EAE9C"}
@@ -0,0 +1,17 @@
1
+ import type { ElurTemplate, ElurMountHandle } from "./template/index.js";
2
+ import { type ElurComponent } from "./lifecycle.js";
3
+ import { type Router } from "./router.js";
4
+ export interface MountOptions {
5
+ router?: Router;
6
+ }
7
+ /**
8
+ * Mounts a ElurTemplate or ElurComponent into the DOM.
9
+ *
10
+ * mount(Counter(), "#app"); // ElurTemplate (function component)
11
+ * mount(new Timer(), "#app"); // ElurComponent (class with lifecycle)
12
+ *
13
+ * @param component ElurTemplate (result of html``) or a ElurComponent instance.
14
+ * @param container CSS selector or HTMLElement to mount into.
15
+ * @returns { unmount() } — disposes effects and removes DOM.
16
+ */
17
+ export declare function mount(component: ElurTemplate | ElurComponent, container: Element | string, options?: MountOptions): ElurMountHandle;
@@ -0,0 +1,17 @@
1
+ import type { ElurTemplate, ElurMountHandle } from "./template/index.js";
2
+ import { type ElurComponent } from "./lifecycle.js";
3
+ import { type Router } from "./router.js";
4
+ export interface MountOptions {
5
+ router?: Router;
6
+ }
7
+ /**
8
+ * Mounts a ElurTemplate or ElurComponent into the DOM.
9
+ *
10
+ * mount(Counter(), "#app"); // ElurTemplate (function component)
11
+ * mount(new Timer(), "#app"); // ElurComponent (class with lifecycle)
12
+ *
13
+ * @param component ElurTemplate (result of html``) or a ElurComponent instance.
14
+ * @param container CSS selector or HTMLElement to mount into.
15
+ * @returns { unmount() } — disposes effects and removes DOM.
16
+ */
17
+ export declare function mount(component: ElurTemplate | ElurComponent, container: Element | string, options?: MountOptions): ElurMountHandle;
@@ -0,0 +1,66 @@
1
+ import { _debugComponentMountEnd as e, _debugComponentMountStart as t, _debugComponentUnmount as n, isElurComponent as r } from "./lifecycle.js";
2
+ import { _popComponentContext as i, _pushComponentContext as a, provide as o } from "./context.js";
3
+ import { RouterKey as s, _debugRegisterRouter as c, _debugUnregisterRouter as l } from "./router.js";
4
+ //#region src/elur/component.ts
5
+ function u(e) {
6
+ let t = typeof e == "string" ? document.querySelector(e) : e;
7
+ if (!t) throw Error(`[elur] mount: container not found: ${e}`);
8
+ return t;
9
+ }
10
+ function d(d, f, p) {
11
+ if (r(d)) {
12
+ let r = u(f);
13
+ t(d), a();
14
+ let m = () => {}, h = !1;
15
+ try {
16
+ p?.router && (o(s, p.router), c(p.router));
17
+ try {
18
+ d.onInit?.();
19
+ } catch (e) {
20
+ if (d.onError) d.onError(e);
21
+ else throw e;
22
+ }
23
+ try {
24
+ m = d.render()._render(r, null);
25
+ } catch (e) {
26
+ if (d.onError) d.onError(e), m = () => {}, h = !0;
27
+ else throw e;
28
+ }
29
+ } finally {
30
+ e(d), i();
31
+ }
32
+ let g;
33
+ if (!h) try {
34
+ let e = d.onMount?.();
35
+ typeof e == "function" && (g = e);
36
+ } catch (e) {
37
+ if (d.onError) d.onError(e);
38
+ else throw e;
39
+ }
40
+ return { unmount() {
41
+ try {
42
+ d.onUnmount?.();
43
+ } catch {}
44
+ try {
45
+ g?.();
46
+ } catch {}
47
+ m(), p?.router && l(p.router), n(d);
48
+ } };
49
+ }
50
+ if (!p?.router) return d.mount(f);
51
+ let m = u(f);
52
+ a();
53
+ let h;
54
+ try {
55
+ o(s, p.router), c(p.router), h = d._render(m, null);
56
+ } finally {
57
+ i();
58
+ }
59
+ return { unmount() {
60
+ h(), l(p.router);
61
+ } };
62
+ }
63
+ //#endregion
64
+ export { d as mount };
65
+
66
+ //# sourceMappingURL=component.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"component.js","names":[],"sources":["../../src/elur/component.ts"],"sourcesContent":["import type { ElurTemplate, ElurMountHandle } from \"./template/index.js\";\nimport {\n isElurComponent,\n _debugComponentMountStart,\n _debugComponentMountEnd,\n _debugComponentUnmount,\n type ElurComponent,\n} from \"./lifecycle.js\";\nimport { _pushComponentContext, _popComponentContext, provide } from \"./context.js\";\nimport { RouterKey, type Router, _debugRegisterRouter, _debugUnregisterRouter } from \"./router.js\";\n\nexport interface MountOptions {\n router?: Router;\n}\n\nfunction _resolveContainer(container: Element | string): Element {\n const el =\n typeof container === \"string\"\n ? (document.querySelector(container) as Element)\n : container;\n if (!el) {\n throw new Error(`[elur] mount: container not found: ${container}`);\n }\n return el;\n}\n\n/**\n * Mounts a ElurTemplate or ElurComponent into the DOM.\n *\n * mount(Counter(), \"#app\"); // ElurTemplate (function component)\n * mount(new Timer(), \"#app\"); // ElurComponent (class with lifecycle)\n *\n * @param component ElurTemplate (result of html``) or a ElurComponent instance.\n * @param container CSS selector or HTMLElement to mount into.\n * @returns { unmount() } — disposes effects and removes DOM.\n */\nexport function mount(\n component: ElurTemplate | ElurComponent,\n container: Element | string,\n options?: MountOptions\n): ElurMountHandle {\n if (isElurComponent(component)) {\n const el = _resolveContainer(container);\n\n _debugComponentMountStart(component);\n _pushComponentContext();\n let cleanup: () => void = () => { };\n let renderFailed = false;\n try {\n if (options?.router) {\n provide(RouterKey, options.router);\n _debugRegisterRouter(options.router);\n }\n try { component.onInit?.(); } catch (e) { if (component.onError) component.onError(e); else throw e; }\n try {\n cleanup = component.render()._render(el, null);\n } catch (e) {\n if (component.onError) {\n component.onError(e);\n cleanup = () => { };\n renderFailed = true;\n } else {\n throw e;\n }\n }\n } finally {\n _debugComponentMountEnd(component);\n _popComponentContext();\n }\n\n let mountCleanup: (() => void) | undefined;\n if (!renderFailed) {\n try {\n const ret = component.onMount?.();\n if (typeof ret === \"function\") mountCleanup = ret;\n } catch (e) {\n if (component.onError) component.onError(e);\n else throw e;\n }\n }\n\n return {\n unmount() {\n try { component.onUnmount?.(); } catch { /* ignore */ }\n try { mountCleanup?.(); } catch { /* ignore */ }\n cleanup();\n if (options?.router) _debugUnregisterRouter(options.router);\n _debugComponentUnmount(component);\n },\n };\n }\n\n if (!options?.router) {\n // ElurTemplate: delegar al método .mount() interno\n return (component as ElurTemplate).mount(container);\n }\n\n // For template roots, create a context frame so elurRouter()/inject() can resolve.\n const el = _resolveContainer(container);\n _pushComponentContext();\n let cleanup: () => void;\n try {\n provide(RouterKey, options.router);\n _debugRegisterRouter(options.router);\n cleanup = (component as ElurTemplate)._render(el, null);\n } finally {\n _popComponentContext();\n }\n\n return {\n unmount() {\n cleanup();\n _debugUnregisterRouter(options.router!);\n },\n };\n}\n"],"mappings":";;;;AAeA,SAAS,EAAkB,GAAsC;CAC7D,IAAM,IACF,OAAO,KAAc,WACd,SAAS,cAAc,EAAU,GAClC;AACV,KAAI,CAAC,EACD,OAAU,MAAM,sCAAsC,IAAY;AAEtE,QAAO;;AAaX,SAAgB,EACZ,GACA,GACA,GACe;AACf,KAAI,EAAgB,EAAU,EAAE;EAC5B,IAAM,IAAK,EAAkB,EAAU;AAGvC,EADA,EAA0B,EAAU,EACpC,GAAuB;EACvB,IAAI,UAA4B,IAC5B,IAAe;AACnB,MAAI;AACA,GAAI,GAAS,WACT,EAAQ,GAAW,EAAQ,OAAO,EAClC,EAAqB,EAAQ,OAAO;AAExC,OAAI;AAAE,MAAU,UAAU;YAAW,GAAG;AAAE,QAAI,EAAU,QAAS,GAAU,QAAQ,EAAE;QAAO,OAAM;;AAClG,OAAI;AACA,QAAU,EAAU,QAAQ,CAAC,QAAQ,GAAI,KAAK;YACzC,GAAG;AACR,QAAI,EAAU,QAGV,CAFA,EAAU,QAAQ,EAAE,EACpB,UAAgB,IAChB,IAAe;QAEf,OAAM;;YAGR;AAEN,GADA,EAAwB,EAAU,EAClC,GAAsB;;EAG1B,IAAI;AACJ,MAAI,CAAC,EACD,KAAI;GACA,IAAM,IAAM,EAAU,WAAW;AACjC,GAAI,OAAO,KAAQ,eAAY,IAAe;WACzC,GAAG;AACR,OAAI,EAAU,QAAS,GAAU,QAAQ,EAAE;OACtC,OAAM;;AAInB,SAAO,EACH,UAAU;AACN,OAAI;AAAE,MAAU,aAAa;WAAU;AACvC,OAAI;AAAE,SAAgB;WAAU;AAGhC,GAFA,GAAS,EACL,GAAS,UAAQ,EAAuB,EAAQ,OAAO,EAC3D,EAAuB,EAAU;KAExC;;AAGL,KAAI,CAAC,GAAS,OAEV,QAAQ,EAA2B,MAAM,EAAU;CAIvD,IAAM,IAAK,EAAkB,EAAU;AACvC,IAAuB;CACvB,IAAI;AACJ,KAAI;AAGA,EAFA,EAAQ,GAAW,EAAQ,OAAO,EAClC,EAAqB,EAAQ,OAAO,EACpC,IAAW,EAA2B,QAAQ,GAAI,KAAK;WACjD;AACN,KAAsB;;AAG1B,QAAO,EACH,UAAU;AAEN,EADA,GAAS,EACT,EAAuB,EAAQ,OAAQ;IAE9C"}
@@ -0,0 +1,2 @@
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});function e(e){return Symbol(e)}var t=[],n;function r(){return n?.()??t}function i(e){n=e}function a(){return[...r()]}function o(e,t){let n=r(),i=n.splice(0);e.forEach(e=>n.push(e));try{return t()}finally{n.splice(0),i.forEach(e=>n.push(e))}}function s(){r().push(new Map)}function c(){r().pop()}function l(e,t){let n=r(),i=n.splice(0);e.forEach(e=>n.push(e)),n.push(new Map);try{return t()}finally{n.splice(0),i.forEach(e=>n.push(e))}}function u(e,t){let n=r(),i=n[n.length-1];if(!i)throw Error(`[elur] provide() must be called inside onInit() of a ElurComponent.`);i.set(e,t)}function d(e,t){let n=r();for(let t=n.length-1;t>=0;t--)if(n[t].has(e))return n[t].get(e);return t}exports._captureContextSnapshot=a,exports._popComponentContext=c,exports._pushComponentContext=s,exports._setContextScopeResolver=i,exports._withComponentContext=l,exports._withContextSnapshot=o,exports.createInjectionKey=e,exports.inject=d,exports.provide=u;
2
+ //# sourceMappingURL=context.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.cjs","names":[],"sources":["../../src/elur/context.ts"],"sourcesContent":["// --- Public types ---\n\n/** Typed key for provide/inject. Generic `T` enforces type safety between provider and consumer. */\nexport type InjectionKey<T> = symbol & { readonly __elurType?: T };\n\n/** Creates a unique typed InjectionKey. */\nexport function createInjectionKey<T>(description?: string): InjectionKey<T> {\n return Symbol(description) as InjectionKey<T>;\n}\n\n// --- Internal stack ---\n\n/** Stack of provide maps, one per active component in the render tree. */\nconst _stack: Map<unknown, unknown>[] = [];\nlet _scopeResolver: (() => Map<unknown, unknown>[] | undefined) | undefined;\n\nfunction currentStack(): Map<unknown, unknown>[] {\n return _scopeResolver?.() ?? _stack;\n}\n\nexport function _setContextScopeResolver(\n resolver: (() => Map<unknown, unknown>[] | undefined) | undefined,\n): void {\n _scopeResolver = resolver;\n}\n\n/** @internal — returns a copy of the stack for capturing in effect closures. */\nexport function _captureContextSnapshot(): Map<unknown, unknown>[] {\n return [...currentStack()];\n}\n\nexport function _withContextSnapshot<T>(\n snapshot: Map<unknown, unknown>[],\n fn: () => T,\n): T {\n const stack = currentStack();\n const saved = stack.splice(0);\n snapshot.forEach((entry) => stack.push(entry));\n try {\n return fn();\n } finally {\n stack.splice(0);\n saved.forEach((entry) => stack.push(entry));\n }\n}\n\n/** @internal — pushes an empty context for a new component (static render). */\nexport function _pushComponentContext(): void {\n currentStack().push(new Map());\n}\n\n/** @internal — pops the current component context (static render). */\nexport function _popComponentContext(): void {\n currentStack().pop();\n}\n\n/**\n * @internal — executes `fn` with `parentSnapshot` as ancestors and a fresh\n * empty context on top, then restores the previous stack.\n */\nexport function _withComponentContext<T>(\n parentSnapshot: Map<unknown, unknown>[],\n fn: () => T\n): T {\n const stack = currentStack();\n const saved = stack.splice(0);\n parentSnapshot.forEach(m => stack.push(m));\n stack.push(new Map());\n try {\n return fn();\n } finally {\n stack.splice(0);\n saved.forEach(m => stack.push(m));\n }\n}\n\n// --- Public API ---\n\n/**\n * Registers a value so descendant components can retrieve it via `inject()`.\n * Must be called inside `onInit()` of a ElurComponent.\n */\nexport function provide<T>(\n key: InjectionKey<T> | string | symbol,\n value: T\n): void {\n const stack = currentStack();\n const top = stack[stack.length - 1];\n if (!top) {\n throw new Error(\n \"[elur] provide() must be called inside onInit() of a ElurComponent.\"\n );\n }\n top.set(key, value);\n}\n\n/**\n * Retrieves a value provided by an ancestor component.\n * Searches child-to-parent; returns `undefined` if the key was not provided.\n */\nexport function inject<T>(\n key: InjectionKey<T> | string | symbol,\n defaultValue?: T\n): T | undefined {\n const stack = currentStack();\n for (let i = stack.length - 1; i >= 0; i--) {\n if (stack[i].has(key)) {\n return stack[i].get(key) as T;\n }\n }\n return defaultValue;\n}\n"],"mappings":"mEAMA,SAAgB,EAAsB,EAAuC,CACzE,OAAO,OAAO,EAAY,CAM9B,IAAM,EAAkC,EAAE,CACtC,EAEJ,SAAS,GAAwC,CAC7C,OAAO,KAAkB,EAAI,EAGjC,SAAgB,EACZ,EACI,CACJ,EAAiB,EAIrB,SAAgB,GAAmD,CAC/D,MAAO,CAAC,GAAG,GAAc,CAAC,CAG9B,SAAgB,EACZ,EACA,EACC,CACD,IAAM,EAAQ,GAAc,CACtB,EAAQ,EAAM,OAAO,EAAE,CAC7B,EAAS,QAAS,GAAU,EAAM,KAAK,EAAM,CAAC,CAC9C,GAAI,CACA,OAAO,GAAI,QACL,CACN,EAAM,OAAO,EAAE,CACf,EAAM,QAAS,GAAU,EAAM,KAAK,EAAM,CAAC,EAKnD,SAAgB,GAA8B,CAC1C,GAAc,CAAC,KAAK,IAAI,IAAM,CAIlC,SAAgB,GAA6B,CACzC,GAAc,CAAC,KAAK,CAOxB,SAAgB,EACZ,EACA,EACC,CACD,IAAM,EAAQ,GAAc,CACtB,EAAQ,EAAM,OAAO,EAAE,CAC7B,EAAe,QAAQ,GAAK,EAAM,KAAK,EAAE,CAAC,CAC1C,EAAM,KAAK,IAAI,IAAM,CACrB,GAAI,CACA,OAAO,GAAI,QACL,CACN,EAAM,OAAO,EAAE,CACf,EAAM,QAAQ,GAAK,EAAM,KAAK,EAAE,CAAC,EAUzC,SAAgB,EACZ,EACA,EACI,CACJ,IAAM,EAAQ,GAAc,CACtB,EAAM,EAAM,EAAM,OAAS,GACjC,GAAI,CAAC,EACD,MAAU,MACN,sEACH,CAEL,EAAI,IAAI,EAAK,EAAM,CAOvB,SAAgB,EACZ,EACA,EACa,CACb,IAAM,EAAQ,GAAc,CAC5B,IAAK,IAAI,EAAI,EAAM,OAAS,EAAG,GAAK,EAAG,IACnC,GAAI,EAAM,GAAG,IAAI,EAAI,CACjB,OAAO,EAAM,GAAG,IAAI,EAAI,CAGhC,OAAO"}
@@ -0,0 +1,29 @@
1
+ /** Typed key for provide/inject. Generic `T` enforces type safety between provider and consumer. */
2
+ export type InjectionKey<T> = symbol & {
3
+ readonly __elurType?: T;
4
+ };
5
+ /** Creates a unique typed InjectionKey. */
6
+ export declare function createInjectionKey<T>(description?: string): InjectionKey<T>;
7
+ export declare function _setContextScopeResolver(resolver: (() => Map<unknown, unknown>[] | undefined) | undefined): void;
8
+ /** @internal — returns a copy of the stack for capturing in effect closures. */
9
+ export declare function _captureContextSnapshot(): Map<unknown, unknown>[];
10
+ export declare function _withContextSnapshot<T>(snapshot: Map<unknown, unknown>[], fn: () => T): T;
11
+ /** @internal — pushes an empty context for a new component (static render). */
12
+ export declare function _pushComponentContext(): void;
13
+ /** @internal — pops the current component context (static render). */
14
+ export declare function _popComponentContext(): void;
15
+ /**
16
+ * @internal — executes `fn` with `parentSnapshot` as ancestors and a fresh
17
+ * empty context on top, then restores the previous stack.
18
+ */
19
+ export declare function _withComponentContext<T>(parentSnapshot: Map<unknown, unknown>[], fn: () => T): T;
20
+ /**
21
+ * Registers a value so descendant components can retrieve it via `inject()`.
22
+ * Must be called inside `onInit()` of a ElurComponent.
23
+ */
24
+ export declare function provide<T>(key: InjectionKey<T> | string | symbol, value: T): void;
25
+ /**
26
+ * Retrieves a value provided by an ancestor component.
27
+ * Searches child-to-parent; returns `undefined` if the key was not provided.
28
+ */
29
+ export declare function inject<T>(key: InjectionKey<T> | string | symbol, defaultValue?: T): T | undefined;
@@ -0,0 +1,29 @@
1
+ /** Typed key for provide/inject. Generic `T` enforces type safety between provider and consumer. */
2
+ export type InjectionKey<T> = symbol & {
3
+ readonly __elurType?: T;
4
+ };
5
+ /** Creates a unique typed InjectionKey. */
6
+ export declare function createInjectionKey<T>(description?: string): InjectionKey<T>;
7
+ export declare function _setContextScopeResolver(resolver: (() => Map<unknown, unknown>[] | undefined) | undefined): void;
8
+ /** @internal — returns a copy of the stack for capturing in effect closures. */
9
+ export declare function _captureContextSnapshot(): Map<unknown, unknown>[];
10
+ export declare function _withContextSnapshot<T>(snapshot: Map<unknown, unknown>[], fn: () => T): T;
11
+ /** @internal — pushes an empty context for a new component (static render). */
12
+ export declare function _pushComponentContext(): void;
13
+ /** @internal — pops the current component context (static render). */
14
+ export declare function _popComponentContext(): void;
15
+ /**
16
+ * @internal — executes `fn` with `parentSnapshot` as ancestors and a fresh
17
+ * empty context on top, then restores the previous stack.
18
+ */
19
+ export declare function _withComponentContext<T>(parentSnapshot: Map<unknown, unknown>[], fn: () => T): T;
20
+ /**
21
+ * Registers a value so descendant components can retrieve it via `inject()`.
22
+ * Must be called inside `onInit()` of a ElurComponent.
23
+ */
24
+ export declare function provide<T>(key: InjectionKey<T> | string | symbol, value: T): void;
25
+ /**
26
+ * Retrieves a value provided by an ancestor component.
27
+ * Searches child-to-parent; returns `undefined` if the key was not provided.
28
+ */
29
+ export declare function inject<T>(key: InjectionKey<T> | string | symbol, defaultValue?: T): T | undefined;
@@ -0,0 +1,52 @@
1
+ //#region src/elur/context.ts
2
+ function e(e) {
3
+ return Symbol(e);
4
+ }
5
+ var t = [], n;
6
+ function r() {
7
+ return n?.() ?? t;
8
+ }
9
+ function i(e) {
10
+ n = e;
11
+ }
12
+ function a() {
13
+ return [...r()];
14
+ }
15
+ function o(e, t) {
16
+ let n = r(), i = n.splice(0);
17
+ e.forEach((e) => n.push(e));
18
+ try {
19
+ return t();
20
+ } finally {
21
+ n.splice(0), i.forEach((e) => n.push(e));
22
+ }
23
+ }
24
+ function s() {
25
+ r().push(/* @__PURE__ */ new Map());
26
+ }
27
+ function c() {
28
+ r().pop();
29
+ }
30
+ function l(e, t) {
31
+ let n = r(), i = n.splice(0);
32
+ e.forEach((e) => n.push(e)), n.push(/* @__PURE__ */ new Map());
33
+ try {
34
+ return t();
35
+ } finally {
36
+ n.splice(0), i.forEach((e) => n.push(e));
37
+ }
38
+ }
39
+ function u(e, t) {
40
+ let n = r(), i = n[n.length - 1];
41
+ if (!i) throw Error("[elur] provide() must be called inside onInit() of a ElurComponent.");
42
+ i.set(e, t);
43
+ }
44
+ function d(e, t) {
45
+ let n = r();
46
+ for (let t = n.length - 1; t >= 0; t--) if (n[t].has(e)) return n[t].get(e);
47
+ return t;
48
+ }
49
+ //#endregion
50
+ export { a as _captureContextSnapshot, c as _popComponentContext, s as _pushComponentContext, i as _setContextScopeResolver, l as _withComponentContext, o as _withContextSnapshot, e as createInjectionKey, d as inject, u as provide };
51
+
52
+ //# sourceMappingURL=context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.js","names":[],"sources":["../../src/elur/context.ts"],"sourcesContent":["// --- Public types ---\n\n/** Typed key for provide/inject. Generic `T` enforces type safety between provider and consumer. */\nexport type InjectionKey<T> = symbol & { readonly __elurType?: T };\n\n/** Creates a unique typed InjectionKey. */\nexport function createInjectionKey<T>(description?: string): InjectionKey<T> {\n return Symbol(description) as InjectionKey<T>;\n}\n\n// --- Internal stack ---\n\n/** Stack of provide maps, one per active component in the render tree. */\nconst _stack: Map<unknown, unknown>[] = [];\nlet _scopeResolver: (() => Map<unknown, unknown>[] | undefined) | undefined;\n\nfunction currentStack(): Map<unknown, unknown>[] {\n return _scopeResolver?.() ?? _stack;\n}\n\nexport function _setContextScopeResolver(\n resolver: (() => Map<unknown, unknown>[] | undefined) | undefined,\n): void {\n _scopeResolver = resolver;\n}\n\n/** @internal — returns a copy of the stack for capturing in effect closures. */\nexport function _captureContextSnapshot(): Map<unknown, unknown>[] {\n return [...currentStack()];\n}\n\nexport function _withContextSnapshot<T>(\n snapshot: Map<unknown, unknown>[],\n fn: () => T,\n): T {\n const stack = currentStack();\n const saved = stack.splice(0);\n snapshot.forEach((entry) => stack.push(entry));\n try {\n return fn();\n } finally {\n stack.splice(0);\n saved.forEach((entry) => stack.push(entry));\n }\n}\n\n/** @internal — pushes an empty context for a new component (static render). */\nexport function _pushComponentContext(): void {\n currentStack().push(new Map());\n}\n\n/** @internal — pops the current component context (static render). */\nexport function _popComponentContext(): void {\n currentStack().pop();\n}\n\n/**\n * @internal — executes `fn` with `parentSnapshot` as ancestors and a fresh\n * empty context on top, then restores the previous stack.\n */\nexport function _withComponentContext<T>(\n parentSnapshot: Map<unknown, unknown>[],\n fn: () => T\n): T {\n const stack = currentStack();\n const saved = stack.splice(0);\n parentSnapshot.forEach(m => stack.push(m));\n stack.push(new Map());\n try {\n return fn();\n } finally {\n stack.splice(0);\n saved.forEach(m => stack.push(m));\n }\n}\n\n// --- Public API ---\n\n/**\n * Registers a value so descendant components can retrieve it via `inject()`.\n * Must be called inside `onInit()` of a ElurComponent.\n */\nexport function provide<T>(\n key: InjectionKey<T> | string | symbol,\n value: T\n): void {\n const stack = currentStack();\n const top = stack[stack.length - 1];\n if (!top) {\n throw new Error(\n \"[elur] provide() must be called inside onInit() of a ElurComponent.\"\n );\n }\n top.set(key, value);\n}\n\n/**\n * Retrieves a value provided by an ancestor component.\n * Searches child-to-parent; returns `undefined` if the key was not provided.\n */\nexport function inject<T>(\n key: InjectionKey<T> | string | symbol,\n defaultValue?: T\n): T | undefined {\n const stack = currentStack();\n for (let i = stack.length - 1; i >= 0; i--) {\n if (stack[i].has(key)) {\n return stack[i].get(key) as T;\n }\n }\n return defaultValue;\n}\n"],"mappings":";AAMA,SAAgB,EAAsB,GAAuC;AACzE,QAAO,OAAO,EAAY;;AAM9B,IAAM,IAAkC,EAAE,EACtC;AAEJ,SAAS,IAAwC;AAC7C,QAAO,KAAkB,IAAI;;AAGjC,SAAgB,EACZ,GACI;AACJ,KAAiB;;AAIrB,SAAgB,IAAmD;AAC/D,QAAO,CAAC,GAAG,GAAc,CAAC;;AAG9B,SAAgB,EACZ,GACA,GACC;CACD,IAAM,IAAQ,GAAc,EACtB,IAAQ,EAAM,OAAO,EAAE;AAC7B,GAAS,SAAS,MAAU,EAAM,KAAK,EAAM,CAAC;AAC9C,KAAI;AACA,SAAO,GAAI;WACL;AAEN,EADA,EAAM,OAAO,EAAE,EACf,EAAM,SAAS,MAAU,EAAM,KAAK,EAAM,CAAC;;;AAKnD,SAAgB,IAA8B;AAC1C,IAAc,CAAC,qBAAK,IAAI,KAAK,CAAC;;AAIlC,SAAgB,IAA6B;AACzC,IAAc,CAAC,KAAK;;AAOxB,SAAgB,EACZ,GACA,GACC;CACD,IAAM,IAAQ,GAAc,EACtB,IAAQ,EAAM,OAAO,EAAE;AAE7B,CADA,EAAe,SAAQ,MAAK,EAAM,KAAK,EAAE,CAAC,EAC1C,EAAM,qBAAK,IAAI,KAAK,CAAC;AACrB,KAAI;AACA,SAAO,GAAI;WACL;AAEN,EADA,EAAM,OAAO,EAAE,EACf,EAAM,SAAQ,MAAK,EAAM,KAAK,EAAE,CAAC;;;AAUzC,SAAgB,EACZ,GACA,GACI;CACJ,IAAM,IAAQ,GAAc,EACtB,IAAM,EAAM,EAAM,SAAS;AACjC,KAAI,CAAC,EACD,OAAU,MACN,sEACH;AAEL,GAAI,IAAI,GAAK,EAAM;;AAOvB,SAAgB,EACZ,GACA,GACa;CACb,IAAM,IAAQ,GAAc;AAC5B,MAAK,IAAI,IAAI,EAAM,SAAS,GAAG,KAAK,GAAG,IACnC,KAAI,EAAM,GAAG,IAAI,EAAI,CACjB,QAAO,EAAM,GAAG,IAAI,EAAI;AAGhC,QAAO"}
@@ -0,0 +1,59 @@
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`./signals.cjs`),t=require(`./lifecycle.cjs`),n=require(`./router.cjs`);var r={enabled:!1,activeTab:`signals`,renderedTab:null,refreshId:null,root:null,panel:null,content:null,dispose:null,renderKeys:{signals:``,components:``,router:``},scrollMemo:{signals:{top:0,left:0},components:{top:0,left:0},router:{top:0,left:0}}},i=new Set,a=new WeakMap,o=1,s=50,c=new WeakMap,l=new Map,u=[],d=1;function f(e){return typeof WeakRef<`u`?new WeakRef(e):{deref:()=>e}}function p(e){return typeof WeakRef<`u`?new WeakRef(e):{deref:()=>e}}function m(e){e.history.length>s&&e.history.splice(0,e.history.length-s)}function h(e,t){let n=a.get(e);if(n)return m(n),n;let r=Date.now(),s={id:o++,createdAt:r,lastUpdated:r,history:[{at:r,value:t}]};return a.set(e,s),i.add(f(e)),s}function g(){let e=[];for(let t of Array.from(i)){let n=t.deref();if(!n){i.delete(t);continue}let r=a.get(n);if(!r)continue;let o=n._subs?.size??0;e.push({id:r.id,value:n.peek(),subscriberCount:o,createdAt:r.createdAt,lastUpdated:r.lastUpdated,history:r.history.slice()})}return e.sort((e,t)=>t.lastUpdated-e.lastUpdated),e}function _(e){let t=e._debugName;if(t&&t.trim())return t;let n=e.constructor;return n?.name&&n.name.trim()?n.name:`AnonymousComponent`}function v(e){let t=e._slots;return t instanceof Map?Array.from(t.keys()).map(e=>String(e)):[]}function y(e){let t={};for(let n of Object.keys(e)){if(n===`__isElurComponent`||n===`children`||n===`_debugName`||n.startsWith(`_`))continue;let r=e[n];typeof r!=`function`&&(t[n]=r)}return t}function b(e){if(!e)return[];if(e===`*`)return[`*`];let t=e.split(`/`).filter(Boolean),n=[],r=``;for(let e of t)r+=`/`+e,n.push(r);return n.length>0?n:[`/`]}function x(){let e=[];for(let[t,n]of l){let r=n.ref.deref();if(!r){l.delete(t);continue}n.debugName=_(r),n.hasDefaultSlot=r.children!=null,n.slotNames=v(r),n.props=y(r),e.push({id:n.id,parentId:n.parentId,debugName:n.debugName,mountedAt:n.mountedAt,hasDefaultSlot:n.hasDefaultSlot,slotNames:[...n.slotNames],props:{...n.props}})}return e.sort((e,t)=>e.id-t.id),e}function S(e){let t=[e];for(;t.length>0;){let e=t.pop();for(let[n,r]of l)r.parentId===e&&t.push(n);l.delete(e)}}function C(){i.clear(),a=new WeakMap,o=1,c=new WeakMap,l.clear(),u.length=0,d=1}function w(e){if(typeof e==`string`)return e;if(typeof e==`number`||typeof e==`boolean`||e==null)return String(e);try{return JSON.stringify(e)}catch{return Object.prototype.toString.call(e)}}function T(e){return e.replace(/&/g,`&amp;`).replace(/</g,`&lt;`).replace(/>/g,`&gt;`).replace(/\"/g,`&quot;`).replace(/'/g,`&#39;`)}function E(e,t=90){let n=w(e);return n.length<=t?n:n.slice(0,t-1)+`…`}function D(e){if(!e)return`-`;let t=Date.now()-e;return t<1e3?`${t}ms ago`:t<6e4?`${Math.floor(t/1e3)}s ago`:`${Math.floor(t/6e4)}m ago`}function O(e){let t=g(),n=`${t.length}:${t.map(e=>`${e.id}-${e.lastUpdated}-${e.subscriberCount}`).join(`|`)}`;if(r.renderedTab===`signals`&&r.renderKeys.signals===n)return;r.renderKeys.signals=n,r.renderedTab=`signals`;let i=t.map(e=>{let t=w(e.value),n=E(e.value,120);return`<tr data-elur-devtools-signal-id="${e.id}">
2
+ <td style="padding:6px 8px;white-space:nowrap;">${e.id}</td>
3
+ <td style="padding:6px 8px;max-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-family:ui-monospace, SFMono-Regular, Menlo, monospace;" title="${T(t)}">${T(n)}</td>
4
+ <td>${e.subscriberCount}</td>
5
+ <td data-elur-devtools-history-count="${e.history.length}">${e.history.length}</td>
6
+ <td>${D(e.lastUpdated)}</td>
7
+ </tr>`}).join(``);e.innerHTML=`
8
+ <div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:8px;">
9
+ <strong>Signals</strong>
10
+ <span style="opacity:.8">${t.length} active</span>
11
+ </div>
12
+ <div data-elur-devtools-scroll="signals" style="max-height:260px;overflow:auto;overscroll-behavior:contain;border:1px solid #2f2f35;border-radius:8px;">
13
+ <table style="width:100%;border-collapse:collapse;font-size:12px;table-layout:fixed;">
14
+ <thead>
15
+ <tr style="background:#1f1f24;">
16
+ <th style="text-align:left;padding:6px 8px;width:42px;">ID</th>
17
+ <th style="text-align:left;padding:6px 8px;">Value</th>
18
+ <th style="text-align:left;padding:6px 8px;width:50px;">Subs</th>
19
+ <th style="text-align:left;padding:6px 8px;width:50px;">History</th>
20
+ <th style="text-align:left;padding:6px 8px;width:84px;">Updated</th>
21
+ </tr>
22
+ </thead>
23
+ <tbody>${i}</tbody>
24
+ </table>
25
+ </div>
26
+ <p style="margin:8px 0 0 0;font-size:11px;opacity:.75;">Click a row to log full history in console.</p>
27
+ `;for(let n of e.querySelectorAll(`tr[data-elur-devtools-signal-id]`))n.style.cursor=`pointer`,n.addEventListener(`click`,()=>{let e=Number(n.dataset.elurDevtoolsSignalId),r=t.find(t=>t.id===e);r&&(console.group(`[Elur DevTools] Signal #${r.id}`),console.log(`Current value:`,r.value),console.log(`Subscribers:`,r.subscriberCount),console.table(r.history.map(e=>({at:new Date(e.at).toISOString(),value:e.value}))),console.groupEnd())})}function k(e){let t=new Map,n=[];for(let n of e)t.set(n.id,{...n,children:[]});for(let e of t.values()){if(e.parentId==null){n.push(e);continue}let r=t.get(e.parentId);if(!r){n.push(e);continue}r.children.push(e)}return n}function A(e,t){let n=10+t*14,r=Object.keys(e.props).length>0?w(e.props):`{}`,i=e.slotNames.length>0?e.slotNames.join(`, `):`none`;return`<div style="padding:6px 8px 6px ${n}px;border-bottom:1px solid #24242b;">
28
+ <div><strong>${T(e.debugName)}</strong> <span style="opacity:.7">#${e.id}</span></div>
29
+ <div style="font-size:11px;opacity:.8;">slots: ${i} | default-slot: ${e.hasDefaultSlot?`yes`:`no`}</div>
30
+ <div style="font-size:11px;opacity:.8;">props: ${T(E(r,180))}</div>
31
+ </div>`+e.children.map(e=>A(e,t+1)).join(``)}function j(e){let t=x(),i=n._debugGetRouterInternal(),a=`${i?`${i.currentPath}|${i.matchedPath??``}`:`no-router`}:${t.length}:${t.map(e=>`${e.id}-${e.parentId}-${e.debugName}-${e.hasDefaultSlot}-${e.slotNames.join(`,`)}-${w(e.props)}`).join(`|`)}`;if(r.renderedTab===`components`&&r.renderKeys.components===a)return;r.renderKeys.components=a,r.renderedTab=`components`;let o=k(t);e.innerHTML=`
32
+ <div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:8px;">
33
+ <strong>Component Tree</strong>
34
+ <span style="opacity:.8">${t.length} mounted</span>
35
+ </div>
36
+ <div style="font-size:11px;opacity:.82;margin-bottom:8px;display:flex;gap:8px;flex-wrap:wrap;">
37
+ <span><b>current:</b> ${T(i?.currentPath??`-`)}</span>
38
+ <span><b>matched:</b> ${T(i?.matchedPath??`none`)}</span>
39
+ </div>
40
+ <div data-elur-devtools-scroll="components" style="max-height:280px;overflow:auto;overscroll-behavior:contain;border:1px solid #2f2f35;border-radius:8px;">
41
+ ${o.length>0?o.map(e=>A(e,0)).join(``):`<div style='padding:10px;opacity:.75'>No mounted components tracked. Enable devtools before your first mount() to capture initial tree.</div>`}
42
+ </div>
43
+ `}function M(e){let t=n._debugGetRouterInternal(),i=t?`${t.mode}|${t.base}|${t.currentPath}|${JSON.stringify(t.params)}|${JSON.stringify(t.query)}|${t.matchedPath}|${t.activeGuards.names.join(`,`)}`:`none`;if(r.renderedTab===`router`&&r.renderKeys.router===i)return;if(r.renderKeys.router=i,r.renderedTab=`router`,!t){e.innerHTML=`
44
+ <strong>Router State</strong>
45
+ <div style="margin-top:8px;opacity:.75">No active Elur router instance. Ensure your app uses createRouter()/RouterView from elur/router.</div>
46
+ `;return}let a=b(t.matchedPath);e.innerHTML=`
47
+ <strong>Router State</strong>
48
+ <div data-elur-devtools-scroll="router" style="margin-top:8px;font-size:12px;line-height:1.55;max-height:280px;overflow:auto;overscroll-behavior:contain;border:1px solid #2f2f35;border-radius:8px;padding:8px;">
49
+ <div><b>mode</b>: ${t.mode}</div>
50
+ <div><b>base</b>: ${t.base}</div>
51
+ <div><b>current</b>: ${T(t.currentPath)}</div>
52
+ <div><b>params</b>: ${T(w(t.params))}</div>
53
+ <div><b>query</b>: ${T(w(t.query))}</div>
54
+ <div><b>matched</b>: ${T(t.matchedPath??`none`)}</div>
55
+ <div><b>matched chain</b>: ${a.length>0?T(a.join(` -> `)):`none`}</div>
56
+ <div><b>guards</b>: ${t.activeGuards.names.length>0?T(t.activeGuards.names.join(`, `)):`none`}</div>
57
+ </div>
58
+ `}function N(e){if(!r.content)return;let t=r.content.querySelector(`[data-elur-devtools-scroll='${e}']`);t&&(r.scrollMemo[e]={top:t.scrollTop,left:t.scrollLeft})}function P(e){if(!r.content)return;let t=r.content.querySelector(`[data-elur-devtools-scroll='${e}']`);if(!t)return;let n=r.scrollMemo[e];t.scrollTop=n.top,t.scrollLeft=n.left,t.dataset.elurDevtoolsScrollBound!==`1`&&(t.addEventListener(`scroll`,()=>{r.scrollMemo[e]={top:t.scrollTop,left:t.scrollLeft}},{passive:!0}),t.dataset.elurDevtoolsScrollBound=`1`)}function F(e=!1){if(!r.content)return;let t=r.activeTab;if(e||N(t),r.activeTab===`signals`){O(r.content),P(`signals`);return}if(r.activeTab===`components`){j(r.content),P(`components`);return}M(r.content),P(`router`)}function I(){if(r.panel)for(let e of r.panel.querySelectorAll(`button[data-elur-devtools-tab]`)){let t=e.dataset.elurDevtoolsTab===r.activeTab;e.style.background=t?`#2d4c7a`:`#1f1f24`}}function L(e){let t=document.createElement(`div`);t.setAttribute(`data-elur-devtools-root`,``),t.style.position=`fixed`,t.style.zIndex=`2147483647`,t.style.bottom=`16px`,t.style.right=e.position===`bottom-right`?`16px`:`auto`,t.style.left=e.position===`bottom-left`?`16px`:`auto`,t.style.fontFamily=`ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, sans-serif`;let n=document.createElement(`button`);n.type=`button`,n.textContent=`Elur DevTools`,n.setAttribute(`data-elur-devtools-button`,``),n.style.background=`#111827`,n.style.color=`#f9fafb`,n.style.border=`1px solid #374151`,n.style.borderRadius=`999px`,n.style.padding=`8px 12px`,n.style.cursor=`pointer`,n.style.boxShadow=`0 6px 18px rgba(0,0,0,.3)`;let i=document.createElement(`div`);i.setAttribute(`data-elur-devtools-panel`,``),i.style.marginTop=`8px`,i.style.width=`460px`,i.style.maxWidth=`min(92vw, 460px)`,i.style.background=`#15151b`,i.style.color=`#e5e7eb`,i.style.border=`1px solid #2f2f35`,i.style.borderRadius=`12px`,i.style.padding=`10px`,i.style.display=`none`,i.style.boxShadow=`0 14px 28px rgba(0,0,0,.35)`;let a=document.createElement(`div`);a.style.display=`flex`,a.style.gap=`6px`,a.style.marginBottom=`10px`;let o=document.createElement(`div`);o.setAttribute(`data-elur-devtools-content`,``);let s=(e,t)=>{let n=document.createElement(`button`);return n.type=`button`,n.textContent=t,n.setAttribute(`data-elur-devtools-tab`,e),n.style.border=`1px solid #353543`,n.style.borderRadius=`8px`,n.style.padding=`6px 9px`,n.style.background=`#1f1f24`,n.style.color=`#d1d5db`,n.style.cursor=`pointer`,n.addEventListener(`click`,()=>{r.activeTab=e,I(),F(!0)}),n};a.appendChild(s(`signals`,`Signals`)),a.appendChild(s(`components`,`Components`)),a.appendChild(s(`router`,`Router`)),n.addEventListener(`click`,()=>{i.style.display=i.style.display===`none`?`block`:`none`,i.style.display===`block`&&(I(),F(!0))}),i.appendChild(a),i.appendChild(o),t.appendChild(n),t.appendChild(i),document.body.appendChild(t),r.root=t,r.panel=i,r.content=o}function R(){r.enabled&&(r.enabled=!1,r.refreshId!=null&&(clearInterval(r.refreshId),r.refreshId=null),e._setSignalDebugHooks(null),t._setComponentDebugHooks(null),C(),r.root?.parentNode&&r.root.parentNode.removeChild(r.root),r.root=null,r.panel=null,r.content=null,r.dispose=null,r.renderedTab=null,r.renderKeys={signals:``,components:``,router:``},r.scrollMemo={signals:{top:0,left:0},components:{top:0,left:0},router:{top:0,left:0}})}function z(n={}){if(typeof document>`u`)return{disable:()=>void 0};if(r.enabled&&r.dispose)return{disable:r.dispose};let o=Math.max(100,n.refreshMs??350);s=Math.max(1,n.historyLimit??50);let f=n.position??`bottom-right`;r.enabled=!0,r.activeTab=`signals`;for(let e of Array.from(i)){let t=e.deref();if(!t){i.delete(e);continue}let n=a.get(t);n&&m(n)}e._setSignalDebugHooks({onCreate(e,t){h(e,t)},onWrite(e,t){let n=h(e,t),r=Date.now();n.lastUpdated=r,n.history.push({at:r,value:t}),m(n)}}),t._setComponentDebugHooks({onMountStart(e){let t=c.get(e);t??(t=d++,c.set(e,t));let n=u.length>0?u[u.length-1]:null;l.set(t,{id:t,parentId:n,debugName:_(e),mountedAt:Date.now(),hasDefaultSlot:e.children!=null,slotNames:v(e),props:y(e),ref:p(e)}),u.push(t)},onMountEnd(e){let t=c.get(e);if(t==null)return;let n=l.get(t);if(n&&(n.debugName=_(e),n.hasDefaultSlot=e.children!=null,n.slotNames=v(e),n.props=y(e)),u[u.length-1]===t){u.pop();return}let r=u.lastIndexOf(t);r>=0&&u.splice(r,1)},onUnmount(e){let t=c.get(e);if(t==null)return;S(t);let n=u.lastIndexOf(t);n>=0&&u.splice(n,1)}}),L({position:f}),r.refreshId=setInterval(()=>{r.panel?.style.display===`block`&&F()},o),n.initiallyOpen&&r.panel&&(r.panel.style.display=`block`,I(),F(!0));let g=()=>R();return r.dispose=g,{disable:g}}exports._listSignals=g,exports.disableDevTools=R,exports.enableDevTools=z;
59
+ //# sourceMappingURL=devtools.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"devtools.cjs","names":[],"sources":["../../src/elur/devtools.ts"],"sourcesContent":["import { _debugGetRouterInternal } from \"./router.js\";\nimport {\n _setComponentDebugHooks,\n type ElurComponent,\n} from \"./lifecycle.js\";\nimport {\n _setSignalDebugHooks,\n type Signal,\n} from \"./reactivity.js\";\n\nexport interface DevToolsOptions {\n refreshMs?: number;\n historyLimit?: number;\n initiallyOpen?: boolean;\n position?: \"bottom-right\" | \"bottom-left\";\n}\n\ntype _DevToolsTab = \"signals\" | \"components\" | \"router\";\n\ninterface _DevToolsState {\n enabled: boolean;\n activeTab: _DevToolsTab;\n renderedTab: _DevToolsTab | null;\n refreshId: ReturnType<typeof setInterval> | null;\n root: HTMLDivElement | null;\n panel: HTMLDivElement | null;\n content: HTMLDivElement | null;\n dispose: (() => void) | null;\n renderKeys: Record<_DevToolsTab, string>;\n scrollMemo: Record<_DevToolsTab, { top: number; left: number }>;\n}\n\nconst _state: _DevToolsState = {\n enabled: false,\n activeTab: \"signals\",\n renderedTab: null,\n refreshId: null,\n root: null,\n panel: null,\n content: null,\n dispose: null,\n renderKeys: { signals: \"\", components: \"\", router: \"\" },\n scrollMemo: {\n signals: { top: 0, left: 0 },\n components: { top: 0, left: 0 },\n router: { top: 0, left: 0 },\n },\n};\n\ntype _SignalRef = { deref(): Signal<any> | undefined };\n\ninterface _SignalMeta {\n id: number;\n createdAt: number;\n lastUpdated: number;\n history: Array<{ at: number; value: unknown }>;\n}\n\ninterface _SignalSnapshot {\n id: number;\n value: unknown;\n subscriberCount: number;\n createdAt: number;\n lastUpdated: number;\n history: Array<{ at: number; value: unknown }>;\n}\n\ninterface _ComponentSnapshot {\n id: number;\n parentId: number | null;\n debugName: string;\n mountedAt: number;\n hasDefaultSlot: boolean;\n slotNames: string[];\n props: Record<string, unknown>;\n}\n\ninterface _ComponentRecord extends _ComponentSnapshot {\n ref: _ComponentRef;\n}\n\ntype _ComponentRef = { deref(): ElurComponent | undefined };\n\nconst _signalRefs = new Set<_SignalRef>();\nlet _signalMeta = new WeakMap<Signal<any>, _SignalMeta>();\nlet _signalSeq = 1;\nlet _signalHistoryLimit = 50;\n\nlet _componentIds = new WeakMap<ElurComponent, number>();\nconst _componentMounted = new Map<number, _ComponentRecord>();\nconst _componentMountStack: number[] = [];\nlet _componentSeq = 1;\n\nfunction _makeSignalRef<T>(s: Signal<T>): _SignalRef {\n if (typeof WeakRef !== \"undefined\") return new WeakRef(s) as _SignalRef;\n return { deref: () => s };\n}\n\nfunction _makeComponentRef(inst: ElurComponent): _ComponentRef {\n if (typeof WeakRef !== \"undefined\") return new WeakRef(inst) as _ComponentRef;\n return { deref: () => inst };\n}\n\nfunction _trimSignalHistory(meta: _SignalMeta): void {\n if (meta.history.length > _signalHistoryLimit) {\n meta.history.splice(0, meta.history.length - _signalHistoryLimit);\n }\n}\n\nfunction _ensureSignalMeta<T>(s: Signal<T>, initialValue: T): _SignalMeta {\n const existing = _signalMeta.get(s);\n if (existing) {\n _trimSignalHistory(existing);\n return existing;\n }\n\n const now = Date.now();\n const meta: _SignalMeta = {\n id: _signalSeq++,\n createdAt: now,\n lastUpdated: now,\n history: [{ at: now, value: initialValue }],\n };\n _signalMeta.set(s, meta);\n _signalRefs.add(_makeSignalRef(s));\n return meta;\n}\n\n/** @internal Exported for testing. */\nexport function _listSignals(): _SignalSnapshot[] {\n const out: _SignalSnapshot[] = [];\n\n for (const ref of Array.from(_signalRefs)) {\n const s = ref.deref();\n if (!s) {\n _signalRefs.delete(ref);\n continue;\n }\n\n const meta = _signalMeta.get(s);\n if (!meta) continue;\n\n const subCount = (s as unknown as { _subs?: Set<() => void> })._subs?.size ?? 0;\n\n out.push({\n id: meta.id,\n value: s.peek(),\n subscriberCount: subCount,\n createdAt: meta.createdAt,\n lastUpdated: meta.lastUpdated,\n history: meta.history.slice(),\n });\n }\n\n out.sort((a, b) => b.lastUpdated - a.lastUpdated);\n return out;\n}\n\nfunction _componentName(inst: ElurComponent): string {\n const maybeDebugName = (inst as { _debugName?: string })._debugName;\n if (maybeDebugName && maybeDebugName.trim()) return maybeDebugName;\n const ctor = (inst as { constructor?: { name?: string } }).constructor;\n return ctor?.name && ctor.name.trim() ? ctor.name : \"AnonymousComponent\";\n}\n\nfunction _componentSlotNames(inst: ElurComponent): string[] {\n const slots = (inst as unknown as { _slots?: unknown })._slots;\n if (!(slots instanceof Map)) return [];\n return Array.from(slots.keys()).map((k) => String(k));\n}\n\nfunction _componentProps(inst: ElurComponent): Record<string, unknown> {\n const out: Record<string, unknown> = {};\n for (const key of Object.keys(inst as unknown as Record<string, unknown>)) {\n if (\n key === \"__isElurComponent\" ||\n key === \"children\" ||\n key === \"_debugName\" ||\n key.startsWith(\"_\")\n ) {\n continue;\n }\n const value = (inst as unknown as Record<string, unknown>)[key];\n if (typeof value === \"function\") continue;\n out[key] = value;\n }\n return out;\n}\n\nfunction _mountPathChain(fullPath: string | null): string[] {\n if (!fullPath) return [];\n if (fullPath === \"*\") return [\"*\"];\n\n const parts = fullPath.split(\"/\").filter(Boolean);\n const out: string[] = [];\n let cur = \"\";\n for (const part of parts) {\n cur += \"/\" + part;\n out.push(cur);\n }\n return out.length > 0 ? out : [\"/\"];\n}\n\nfunction _listMountedComponents(): _ComponentSnapshot[] {\n const out: _ComponentSnapshot[] = [];\n\n for (const [id, item] of _componentMounted) {\n const inst = item.ref.deref();\n if (!inst) {\n _componentMounted.delete(id);\n continue;\n }\n\n // Keep rows fresh while panel is open (debug name/props can change after mount).\n item.debugName = _componentName(inst);\n item.hasDefaultSlot = inst.children != null;\n item.slotNames = _componentSlotNames(inst);\n item.props = _componentProps(inst);\n\n out.push({\n id: item.id,\n parentId: item.parentId,\n debugName: item.debugName,\n mountedAt: item.mountedAt,\n hasDefaultSlot: item.hasDefaultSlot,\n slotNames: [...item.slotNames],\n props: { ...item.props },\n });\n }\n\n out.sort((a, b) => a.id - b.id);\n return out;\n}\n\nfunction _removeMountedComponentSubtree(rootId: number): void {\n const pending = [rootId];\n while (pending.length > 0) {\n const current = pending.pop()!;\n for (const [id, record] of _componentMounted) {\n if (record.parentId === current) pending.push(id);\n }\n _componentMounted.delete(current);\n }\n}\n\nfunction _resetDevtoolsStores(): void {\n _signalRefs.clear();\n _signalMeta = new WeakMap<Signal<any>, _SignalMeta>();\n _signalSeq = 1;\n\n _componentIds = new WeakMap<ElurComponent, number>();\n _componentMounted.clear();\n _componentMountStack.length = 0;\n _componentSeq = 1;\n}\n\nfunction _safeStringify(value: unknown): string {\n if (typeof value === \"string\") return value;\n if (typeof value === \"number\" || typeof value === \"boolean\" || value == null) {\n return String(value);\n }\n try {\n return JSON.stringify(value);\n } catch {\n return Object.prototype.toString.call(value);\n }\n}\n\nfunction _escapeHtml(value: string): string {\n return value\n .replace(/&/g, \"&amp;\")\n .replace(/</g, \"&lt;\")\n .replace(/>/g, \"&gt;\")\n .replace(/\\\"/g, \"&quot;\")\n .replace(/'/g, \"&#39;\");\n}\n\nfunction _valuePreview(value: unknown, max = 90): string {\n const raw = _safeStringify(value);\n if (raw.length <= max) return raw;\n return raw.slice(0, max - 1) + \"…\";\n}\n\nfunction _relativeTime(ts: number): string {\n if (!ts) return \"-\";\n const diff = Date.now() - ts;\n if (diff < 1000) return `${diff}ms ago`;\n if (diff < 60_000) return `${Math.floor(diff / 1000)}s ago`;\n return `${Math.floor(diff / 60_000)}m ago`;\n}\n\nfunction _renderSignals(target: HTMLDivElement): void {\n const signals = _listSignals();\n const key = `${signals.length}:${signals.map((s) => `${s.id}-${s.lastUpdated}-${s.subscriberCount}`).join(\"|\")}`;\n if (_state.renderedTab === \"signals\" && _state.renderKeys.signals === key) return;\n _state.renderKeys.signals = key;\n _state.renderedTab = \"signals\";\n\n const rows = signals\n .map((s) => {\n const fullValue = _safeStringify(s.value);\n const preview = _valuePreview(s.value, 120);\n return `<tr data-elur-devtools-signal-id=\"${s.id}\">\n <td style=\"padding:6px 8px;white-space:nowrap;\">${s.id}</td>\n <td style=\"padding:6px 8px;max-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-family:ui-monospace, SFMono-Regular, Menlo, monospace;\" title=\"${_escapeHtml(fullValue)}\">${_escapeHtml(preview)}</td>\n <td>${s.subscriberCount}</td>\n <td data-elur-devtools-history-count=\"${s.history.length}\">${s.history.length}</td>\n <td>${_relativeTime(s.lastUpdated)}</td>\n </tr>`;\n })\n .join(\"\");\n\n target.innerHTML = `\n <div style=\"display:flex;justify-content:space-between;align-items:center;margin-bottom:8px;\">\n <strong>Signals</strong>\n <span style=\"opacity:.8\">${signals.length} active</span>\n </div>\n <div data-elur-devtools-scroll=\"signals\" style=\"max-height:260px;overflow:auto;overscroll-behavior:contain;border:1px solid #2f2f35;border-radius:8px;\">\n <table style=\"width:100%;border-collapse:collapse;font-size:12px;table-layout:fixed;\">\n <thead>\n <tr style=\"background:#1f1f24;\">\n <th style=\"text-align:left;padding:6px 8px;width:42px;\">ID</th>\n <th style=\"text-align:left;padding:6px 8px;\">Value</th>\n <th style=\"text-align:left;padding:6px 8px;width:50px;\">Subs</th>\n <th style=\"text-align:left;padding:6px 8px;width:50px;\">History</th>\n <th style=\"text-align:left;padding:6px 8px;width:84px;\">Updated</th>\n </tr>\n </thead>\n <tbody>${rows}</tbody>\n </table>\n </div>\n <p style=\"margin:8px 0 0 0;font-size:11px;opacity:.75;\">Click a row to log full history in console.</p>\n `;\n\n for (const row of target.querySelectorAll<HTMLTableRowElement>(\"tr[data-elur-devtools-signal-id]\")) {\n row.style.cursor = \"pointer\";\n row.addEventListener(\"click\", () => {\n const id = Number(row.dataset.elurDevtoolsSignalId);\n const signal = signals.find((s) => s.id === id);\n if (!signal) return;\n console.group(`[Elur DevTools] Signal #${signal.id}`);\n console.log(\"Current value:\", signal.value);\n console.log(\"Subscribers:\", signal.subscriberCount);\n console.table(signal.history.map((h) => ({ at: new Date(h.at).toISOString(), value: h.value })));\n console.groupEnd();\n });\n }\n}\n\ninterface _TreeNode extends _ComponentSnapshot {\n children: _TreeNode[];\n}\n\nfunction _buildComponentTree(rows: _ComponentSnapshot[]): _TreeNode[] {\n const byId = new Map<number, _TreeNode>();\n const roots: _TreeNode[] = [];\n\n for (const row of rows) {\n byId.set(row.id, { ...row, children: [] });\n }\n\n for (const node of byId.values()) {\n if (node.parentId == null) {\n roots.push(node);\n continue;\n }\n const parent = byId.get(node.parentId);\n if (!parent) {\n roots.push(node);\n continue;\n }\n parent.children.push(node);\n }\n\n return roots;\n}\n\nfunction _renderTreeNode(node: _TreeNode, depth: number): string {\n const pad = 10 + depth * 14;\n const props = Object.keys(node.props).length > 0 ? _safeStringify(node.props) : \"{}\";\n const slots = node.slotNames.length > 0 ? node.slotNames.join(\", \") : \"none\";\n\n const header = `<div style=\"padding:6px 8px 6px ${pad}px;border-bottom:1px solid #24242b;\">\n <div><strong>${_escapeHtml(node.debugName)}</strong> <span style=\"opacity:.7\">#${node.id}</span></div>\n <div style=\"font-size:11px;opacity:.8;\">slots: ${slots} | default-slot: ${node.hasDefaultSlot ? \"yes\" : \"no\"}</div>\n <div style=\"font-size:11px;opacity:.8;\">props: ${_escapeHtml(_valuePreview(props, 180))}</div>\n </div>`;\n\n return header + node.children.map((c) => _renderTreeNode(c, depth + 1)).join(\"\");\n}\n\nfunction _renderComponents(target: HTMLDivElement): void {\n const rows = _listMountedComponents();\n const router = _debugGetRouterInternal();\n const routeKey = router ? `${router.currentPath}|${router.matchedPath ?? \"\"}` : \"no-router\";\n const key = `${routeKey}:${rows.length}:${rows.map((r) => `${r.id}-${r.parentId}-${r.debugName}-${r.hasDefaultSlot}-${r.slotNames.join(\",\")}-${_safeStringify(r.props)}`).join(\"|\")}`;\n if (_state.renderedTab === \"components\" && _state.renderKeys.components === key) return;\n _state.renderKeys.components = key;\n _state.renderedTab = \"components\";\n\n const roots = _buildComponentTree(rows);\n\n target.innerHTML = `\n <div style=\"display:flex;justify-content:space-between;align-items:center;margin-bottom:8px;\">\n <strong>Component Tree</strong>\n <span style=\"opacity:.8\">${rows.length} mounted</span>\n </div>\n <div style=\"font-size:11px;opacity:.82;margin-bottom:8px;display:flex;gap:8px;flex-wrap:wrap;\">\n <span><b>current:</b> ${_escapeHtml(router?.currentPath ?? \"-\")}</span>\n <span><b>matched:</b> ${_escapeHtml(router?.matchedPath ?? \"none\")}</span>\n </div>\n <div data-elur-devtools-scroll=\"components\" style=\"max-height:280px;overflow:auto;overscroll-behavior:contain;border:1px solid #2f2f35;border-radius:8px;\">\n ${roots.length > 0\n ? roots.map((r) => _renderTreeNode(r, 0)).join(\"\")\n : \"<div style='padding:10px;opacity:.75'>No mounted components tracked. Enable devtools before your first mount() to capture initial tree.</div>\"}\n </div>\n `;\n}\n\nfunction _renderRouter(target: HTMLDivElement): void {\n const router = _debugGetRouterInternal();\n const key = router\n ? `${router.mode}|${router.base}|${router.currentPath}|${JSON.stringify(router.params)}|${JSON.stringify(router.query)}|${router.matchedPath}|${router.activeGuards.names.join(\",\")}`\n : \"none\";\n if (_state.renderedTab === \"router\" && _state.renderKeys.router === key) return;\n _state.renderKeys.router = key;\n _state.renderedTab = \"router\";\n\n if (!router) {\n target.innerHTML = `\n <strong>Router State</strong>\n <div style=\"margin-top:8px;opacity:.75\">No active Elur router instance. Ensure your app uses createRouter()/RouterView from elur/router.</div>\n `;\n return;\n }\n\n const chain = _mountPathChain(router.matchedPath);\n target.innerHTML = `\n <strong>Router State</strong>\n <div data-elur-devtools-scroll=\"router\" style=\"margin-top:8px;font-size:12px;line-height:1.55;max-height:280px;overflow:auto;overscroll-behavior:contain;border:1px solid #2f2f35;border-radius:8px;padding:8px;\">\n <div><b>mode</b>: ${router.mode}</div>\n <div><b>base</b>: ${router.base}</div>\n <div><b>current</b>: ${_escapeHtml(router.currentPath)}</div>\n <div><b>params</b>: ${_escapeHtml(_safeStringify(router.params))}</div>\n <div><b>query</b>: ${_escapeHtml(_safeStringify(router.query))}</div>\n <div><b>matched</b>: ${_escapeHtml(router.matchedPath ?? \"none\")}</div>\n <div><b>matched chain</b>: ${chain.length > 0 ? _escapeHtml(chain.join(\" -> \")) : \"none\"}</div>\n <div><b>guards</b>: ${router.activeGuards.names.length > 0 ? _escapeHtml(router.activeGuards.names.join(\", \")) : \"none\"}</div>\n </div>\n `;\n}\n\nfunction _rememberScroll(tab: _DevToolsTab): void {\n if (!_state.content) return;\n const box = _state.content.querySelector<HTMLElement>(`[data-elur-devtools-scroll='${tab}']`);\n if (!box) return;\n _state.scrollMemo[tab] = { top: box.scrollTop, left: box.scrollLeft };\n}\n\nfunction _restoreScroll(tab: _DevToolsTab): void {\n if (!_state.content) return;\n const box = _state.content.querySelector<HTMLElement>(`[data-elur-devtools-scroll='${tab}']`);\n if (!box) return;\n const memo = _state.scrollMemo[tab];\n box.scrollTop = memo.top;\n box.scrollLeft = memo.left;\n if (box.dataset.elurDevtoolsScrollBound !== \"1\") {\n box.addEventListener(\"scroll\", () => {\n _state.scrollMemo[tab] = { top: box.scrollTop, left: box.scrollLeft };\n }, { passive: true });\n box.dataset.elurDevtoolsScrollBound = \"1\";\n }\n}\n\nfunction _refreshPanel(force = false): void {\n if (!_state.content) return;\n\n const tab = _state.activeTab;\n if (!force) _rememberScroll(tab);\n\n if (_state.activeTab === \"signals\") {\n _renderSignals(_state.content);\n _restoreScroll(\"signals\");\n return;\n }\n if (_state.activeTab === \"components\") {\n _renderComponents(_state.content);\n _restoreScroll(\"components\");\n return;\n }\n _renderRouter(_state.content);\n _restoreScroll(\"router\");\n}\n\nfunction _syncTabButtons(): void {\n if (!_state.panel) return;\n for (const btn of _state.panel.querySelectorAll<HTMLButtonElement>(\"button[data-elur-devtools-tab]\")) {\n const isActive = btn.dataset.elurDevtoolsTab === _state.activeTab;\n btn.style.background = isActive ? \"#2d4c7a\" : \"#1f1f24\";\n }\n}\n\nfunction _createOverlay(options: Required<Pick<DevToolsOptions, \"position\">>): void {\n const root = document.createElement(\"div\");\n root.setAttribute(\"data-elur-devtools-root\", \"\");\n root.style.position = \"fixed\";\n root.style.zIndex = \"2147483647\";\n root.style.bottom = \"16px\";\n root.style.right = options.position === \"bottom-right\" ? \"16px\" : \"auto\";\n root.style.left = options.position === \"bottom-left\" ? \"16px\" : \"auto\";\n root.style.fontFamily = \"ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, sans-serif\";\n\n const button = document.createElement(\"button\");\n button.type = \"button\";\n button.textContent = \"Elur DevTools\";\n button.setAttribute(\"data-elur-devtools-button\", \"\");\n button.style.background = \"#111827\";\n button.style.color = \"#f9fafb\";\n button.style.border = \"1px solid #374151\";\n button.style.borderRadius = \"999px\";\n button.style.padding = \"8px 12px\";\n button.style.cursor = \"pointer\";\n button.style.boxShadow = \"0 6px 18px rgba(0,0,0,.3)\";\n\n const panel = document.createElement(\"div\");\n panel.setAttribute(\"data-elur-devtools-panel\", \"\");\n panel.style.marginTop = \"8px\";\n panel.style.width = \"460px\";\n panel.style.maxWidth = \"min(92vw, 460px)\";\n panel.style.background = \"#15151b\";\n panel.style.color = \"#e5e7eb\";\n panel.style.border = \"1px solid #2f2f35\";\n panel.style.borderRadius = \"12px\";\n panel.style.padding = \"10px\";\n panel.style.display = \"none\";\n panel.style.boxShadow = \"0 14px 28px rgba(0,0,0,.35)\";\n\n const tabs = document.createElement(\"div\");\n tabs.style.display = \"flex\";\n tabs.style.gap = \"6px\";\n tabs.style.marginBottom = \"10px\";\n\n const content = document.createElement(\"div\");\n content.setAttribute(\"data-elur-devtools-content\", \"\");\n\n const makeTab = (name: _DevToolsTab, label: string): HTMLButtonElement => {\n const t = document.createElement(\"button\");\n t.type = \"button\";\n t.textContent = label;\n t.setAttribute(\"data-elur-devtools-tab\", name);\n t.style.border = \"1px solid #353543\";\n t.style.borderRadius = \"8px\";\n t.style.padding = \"6px 9px\";\n t.style.background = \"#1f1f24\";\n t.style.color = \"#d1d5db\";\n t.style.cursor = \"pointer\";\n t.addEventListener(\"click\", () => {\n _state.activeTab = name;\n _syncTabButtons();\n _refreshPanel(true);\n });\n return t;\n };\n\n tabs.appendChild(makeTab(\"signals\", \"Signals\"));\n tabs.appendChild(makeTab(\"components\", \"Components\"));\n tabs.appendChild(makeTab(\"router\", \"Router\"));\n\n button.addEventListener(\"click\", () => {\n panel.style.display = panel.style.display === \"none\" ? \"block\" : \"none\";\n if (panel.style.display === \"block\") {\n _syncTabButtons();\n _refreshPanel(true);\n }\n });\n\n panel.appendChild(tabs);\n panel.appendChild(content);\n root.appendChild(button);\n root.appendChild(panel);\n document.body.appendChild(root);\n\n _state.root = root;\n _state.panel = panel;\n _state.content = content;\n}\n\nexport function disableDevTools(): void {\n if (!_state.enabled) return;\n _state.enabled = false;\n\n if (_state.refreshId != null) {\n clearInterval(_state.refreshId);\n _state.refreshId = null;\n }\n\n _setSignalDebugHooks(null);\n _setComponentDebugHooks(null);\n _resetDevtoolsStores();\n\n if (_state.root?.parentNode) {\n _state.root.parentNode.removeChild(_state.root);\n }\n\n _state.root = null;\n _state.panel = null;\n _state.content = null;\n _state.dispose = null;\n _state.renderedTab = null;\n _state.renderKeys = { signals: \"\", components: \"\", router: \"\" };\n _state.scrollMemo = {\n signals: { top: 0, left: 0 },\n components: { top: 0, left: 0 },\n router: { top: 0, left: 0 },\n };\n}\n\nexport function enableDevTools(options: DevToolsOptions = {}): { disable: () => void } {\n if (typeof document === \"undefined\") {\n return { disable: () => undefined };\n }\n\n if (_state.enabled && _state.dispose) {\n return { disable: _state.dispose };\n }\n\n const refreshMs = Math.max(100, options.refreshMs ?? 350);\n _signalHistoryLimit = Math.max(1, options.historyLimit ?? 50);\n const position = options.position ?? \"bottom-right\";\n\n _state.enabled = true;\n _state.activeTab = \"signals\";\n\n // Apply the new limit to histories that were already created before enableDevTools.\n for (const ref of Array.from(_signalRefs)) {\n const s = ref.deref();\n if (!s) {\n _signalRefs.delete(ref);\n continue;\n }\n const meta = _signalMeta.get(s);\n if (meta) _trimSignalHistory(meta);\n }\n\n _setSignalDebugHooks({\n onCreate(signal, initialValue) {\n _ensureSignalMeta(signal, initialValue);\n },\n onWrite(signal, value) {\n const meta = _ensureSignalMeta(signal, value);\n const now = Date.now();\n meta.lastUpdated = now;\n meta.history.push({ at: now, value });\n _trimSignalHistory(meta);\n },\n });\n\n _setComponentDebugHooks({\n onMountStart(inst) {\n let id = _componentIds.get(inst);\n if (id == null) {\n id = _componentSeq++;\n _componentIds.set(inst, id);\n }\n\n const parentId = _componentMountStack.length > 0\n ? _componentMountStack[_componentMountStack.length - 1]\n : null;\n\n _componentMounted.set(id, {\n id,\n parentId,\n debugName: _componentName(inst),\n mountedAt: Date.now(),\n hasDefaultSlot: inst.children != null,\n slotNames: _componentSlotNames(inst),\n props: _componentProps(inst),\n ref: _makeComponentRef(inst),\n });\n\n _componentMountStack.push(id);\n },\n onMountEnd(inst) {\n const id = _componentIds.get(inst);\n if (id == null) return;\n\n const entry = _componentMounted.get(id);\n if (entry) {\n entry.debugName = _componentName(inst);\n entry.hasDefaultSlot = inst.children != null;\n entry.slotNames = _componentSlotNames(inst);\n entry.props = _componentProps(inst);\n }\n\n if (_componentMountStack[_componentMountStack.length - 1] === id) {\n _componentMountStack.pop();\n return;\n }\n\n const idx = _componentMountStack.lastIndexOf(id);\n if (idx >= 0) _componentMountStack.splice(idx, 1);\n },\n onUnmount(inst) {\n const id = _componentIds.get(inst);\n if (id == null) return;\n\n _removeMountedComponentSubtree(id);\n\n const idx = _componentMountStack.lastIndexOf(id);\n if (idx >= 0) _componentMountStack.splice(idx, 1);\n },\n });\n\n _createOverlay({ position });\n\n _state.refreshId = setInterval(() => {\n if (_state.panel?.style.display === \"block\") {\n _refreshPanel();\n }\n }, refreshMs);\n\n if (options.initiallyOpen && _state.panel) {\n _state.panel.style.display = \"block\";\n _syncTabButtons();\n _refreshPanel(true);\n }\n\n const dispose = () => disableDevTools();\n _state.dispose = dispose;\n return { disable: dispose };\n}\n"],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ export interface DevToolsOptions {
2
+ refreshMs?: number;
3
+ historyLimit?: number;
4
+ initiallyOpen?: boolean;
5
+ position?: "bottom-right" | "bottom-left";
6
+ }
7
+ interface _SignalSnapshot {
8
+ id: number;
9
+ value: unknown;
10
+ subscriberCount: number;
11
+ createdAt: number;
12
+ lastUpdated: number;
13
+ history: Array<{
14
+ at: number;
15
+ value: unknown;
16
+ }>;
17
+ }
18
+ /** @internal Exported for testing. */
19
+ export declare function _listSignals(): _SignalSnapshot[];
20
+ export declare function disableDevTools(): void;
21
+ export declare function enableDevTools(options?: DevToolsOptions): {
22
+ disable: () => void;
23
+ };
24
+ export {};
@@ -0,0 +1,24 @@
1
+ export interface DevToolsOptions {
2
+ refreshMs?: number;
3
+ historyLimit?: number;
4
+ initiallyOpen?: boolean;
5
+ position?: "bottom-right" | "bottom-left";
6
+ }
7
+ interface _SignalSnapshot {
8
+ id: number;
9
+ value: unknown;
10
+ subscriberCount: number;
11
+ createdAt: number;
12
+ lastUpdated: number;
13
+ history: Array<{
14
+ at: number;
15
+ value: unknown;
16
+ }>;
17
+ }
18
+ /** @internal Exported for testing. */
19
+ export declare function _listSignals(): _SignalSnapshot[];
20
+ export declare function disableDevTools(): void;
21
+ export declare function enableDevTools(options?: DevToolsOptions): {
22
+ disable: () => void;
23
+ };
24
+ export {};