@llui/dom 0.0.22 → 0.0.24

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 (97) hide show
  1. package/README.md +26 -21
  2. package/dist/dom-env.d.ts +67 -0
  3. package/dist/dom-env.d.ts.map +1 -0
  4. package/dist/dom-env.js +61 -0
  5. package/dist/dom-env.js.map +1 -0
  6. package/dist/el-split.d.ts.map +1 -1
  7. package/dist/el-split.js +4 -4
  8. package/dist/el-split.js.map +1 -1
  9. package/dist/el-template.d.ts +14 -1
  10. package/dist/el-template.d.ts.map +1 -1
  11. package/dist/el-template.js +41 -7
  12. package/dist/el-template.js.map +1 -1
  13. package/dist/elements.js +2 -2
  14. package/dist/elements.js.map +1 -1
  15. package/dist/hmr.d.ts.map +1 -1
  16. package/dist/hmr.js +1 -0
  17. package/dist/hmr.js.map +1 -1
  18. package/dist/index.d.ts +3 -1
  19. package/dist/index.d.ts.map +1 -1
  20. package/dist/index.js +3 -1
  21. package/dist/index.js.map +1 -1
  22. package/dist/mathml-elements.js +2 -2
  23. package/dist/mathml-elements.js.map +1 -1
  24. package/dist/mount.d.ts +8 -0
  25. package/dist/mount.d.ts.map +1 -1
  26. package/dist/mount.js +14 -9
  27. package/dist/mount.js.map +1 -1
  28. package/dist/primitives/branch.js +1 -1
  29. package/dist/primitives/branch.js.map +1 -1
  30. package/dist/primitives/child.d.ts.map +1 -1
  31. package/dist/primitives/child.js +5 -2
  32. package/dist/primitives/child.js.map +1 -1
  33. package/dist/primitives/client-only.d.ts +108 -0
  34. package/dist/primitives/client-only.d.ts.map +1 -0
  35. package/dist/primitives/client-only.js +110 -0
  36. package/dist/primitives/client-only.js.map +1 -0
  37. package/dist/primitives/each.d.ts.map +1 -1
  38. package/dist/primitives/each.js +19 -9
  39. package/dist/primitives/each.js.map +1 -1
  40. package/dist/primitives/foreign.d.ts.map +1 -1
  41. package/dist/primitives/foreign.js +83 -44
  42. package/dist/primitives/foreign.js.map +1 -1
  43. package/dist/primitives/lazy.js +2 -2
  44. package/dist/primitives/lazy.js.map +1 -1
  45. package/dist/primitives/selector.js +1 -1
  46. package/dist/primitives/selector.js.map +1 -1
  47. package/dist/primitives/slice.d.ts.map +1 -1
  48. package/dist/primitives/slice.js +14 -0
  49. package/dist/primitives/slice.js.map +1 -1
  50. package/dist/primitives/text.js +3 -3
  51. package/dist/primitives/text.js.map +1 -1
  52. package/dist/primitives/unsafe-html.js +11 -13
  53. package/dist/primitives/unsafe-html.js.map +1 -1
  54. package/dist/primitives/virtual-each.d.ts.map +1 -1
  55. package/dist/primitives/virtual-each.js +5 -3
  56. package/dist/primitives/virtual-each.js.map +1 -1
  57. package/dist/render-context.d.ts +9 -0
  58. package/dist/render-context.d.ts.map +1 -1
  59. package/dist/render-context.js.map +1 -1
  60. package/dist/ssr/jsdom.d.ts +18 -0
  61. package/dist/ssr/jsdom.d.ts.map +1 -0
  62. package/dist/ssr/jsdom.js +38 -0
  63. package/dist/ssr/jsdom.js.map +1 -0
  64. package/dist/ssr/legacy.d.ts +25 -0
  65. package/dist/ssr/legacy.d.ts.map +1 -0
  66. package/dist/ssr/legacy.js +61 -0
  67. package/dist/ssr/legacy.js.map +1 -0
  68. package/dist/ssr/linkedom.d.ts +17 -0
  69. package/dist/ssr/linkedom.d.ts.map +1 -0
  70. package/dist/ssr/linkedom.js +36 -0
  71. package/dist/ssr/linkedom.js.map +1 -0
  72. package/dist/ssr-dom.d.ts +11 -7
  73. package/dist/ssr-dom.d.ts.map +1 -1
  74. package/dist/ssr-dom.js +10 -31
  75. package/dist/ssr-dom.js.map +1 -1
  76. package/dist/ssr.d.ts +10 -5
  77. package/dist/ssr.d.ts.map +1 -1
  78. package/dist/ssr.js +11 -7
  79. package/dist/ssr.js.map +1 -1
  80. package/dist/svg-elements.js +2 -2
  81. package/dist/svg-elements.js.map +1 -1
  82. package/dist/types.d.ts +27 -5
  83. package/dist/types.d.ts.map +1 -1
  84. package/dist/types.js.map +1 -1
  85. package/dist/update-loop.d.ts +3 -1
  86. package/dist/update-loop.d.ts.map +1 -1
  87. package/dist/update-loop.js +15 -1
  88. package/dist/update-loop.js.map +1 -1
  89. package/dist/view-helpers.d.ts +7 -0
  90. package/dist/view-helpers.d.ts.map +1 -1
  91. package/dist/view-helpers.js +2 -0
  92. package/dist/view-helpers.js.map +1 -1
  93. package/package.json +25 -1
  94. package/dist/scope.d.ts +0 -39
  95. package/dist/scope.d.ts.map +0 -1
  96. package/dist/scope.js +0 -250
  97. package/dist/scope.js.map +0 -1
package/dist/scope.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"scope.js","sourceRoot":"","sources":["../src/scope.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Scope, Binding } from './types.js'\nimport type { ComponentInstance } from './update-loop.js'\n\nlet nextId = 1\n\n/**\n * Walk up the scope chain to find the owning ComponentInstance. The\n * instance is stamped onto the rootScope by `installDevTools`, so this\n * returns null in production (no devtools) or for scopes that haven't\n * yet been parented to a tracked root (e.g., during initial creation).\n */\nfunction findInstance(scope: Scope): ComponentInstance | null {\n let s: Scope | null = scope\n while (s) {\n if (s.instance) return s.instance\n s = s.parent\n }\n return null\n}\n\n// Shared empty arrays — avoid allocating per scope when unused\nconst EMPTY_SCOPES: Scope[] = []\nconst EMPTY_DISPOSERS: Array<() => void> = []\nconst EMPTY_BINDINGS: Binding[] = []\nconst EMPTY_UPDATERS: Array<() => void> = []\n\n// Scope pool — reuse disposed scope objects to reduce GC pressure.\n// Capped to avoid memory leaks in apps that create/destroy thousands of rows.\nconst SCOPE_POOL: Scope[] = []\nconst SCOPE_POOL_MAX = 2048\n\n// Dev-mode flag. Flipped to true by installDevTools() once any component\n// instance has a disposer log. In production this stays false forever,\n// and disposeScope skips findInstance entirely — zero cost.\nlet anyDisposerLogInstalled = false\n\n/** @internal — called by devtools.ts::installDevTools */\nexport function _markDisposerLogInstalled(): void {\n anyDisposerLogInstalled = true\n}\n\n/** @internal Drain the scope pool — for testing only */\nexport function _drainScopePool(): void {\n SCOPE_POOL.length = 0\n}\n\nexport function createScope(parent: Scope | null): Scope {\n let scope: Scope\n if (SCOPE_POOL.length > 0) {\n scope = SCOPE_POOL.pop()!\n scope.id = nextId++\n scope.parent = parent\n // Arrays already reset to empties by dispose. Reset dev-only hints\n // so recycled scopes don't carry stale tagging/back-refs. Cheap\n // (two undefined writes) and keeps production-identical behavior\n // when these fields are never set.\n scope.disposalCause = undefined\n scope.instance = undefined\n scope._kind = undefined\n } else {\n scope = {\n id: nextId++,\n parent,\n children: EMPTY_SCOPES,\n disposers: EMPTY_DISPOSERS,\n bindings: EMPTY_BINDINGS,\n itemUpdaters: EMPTY_UPDATERS,\n }\n }\n\n if (parent) {\n if (parent.children === EMPTY_SCOPES) parent.children = []\n parent.children.push(scope)\n }\n\n return scope\n}\n\n/**\n * Dispose a scope and all its children. By default, detaches the scope\n * from its parent's `children` array via `indexOf + splice` — O(N) per\n * call, which becomes O(N²) when disposing many sibling scopes in bulk\n * (e.g. `each` clearing 1000 rows).\n *\n * Pass `skipParentRemoval = true` when the caller will batch-remove\n * children afterwards (see `removeOrphanedFromParent`). The scope's\n * `parent` pointer is still set to `null` so the caller can identify\n * orphaned entries.\n */\nexport function disposeScope(scope: Scope, skipParentRemoval = false): void {\n if (scope.disposers.length === 0 && scope.children.length === 0 && scope.bindings.length === 0) {\n // Dev-only: still emit a DisposerEvent for empty scopes — the log\n // is meant to capture every scope the app destroys, not only ones\n // that had attached work. Outer flag check keeps production (no\n // devtools ever installed) at true zero cost — no parent-chain walk.\n if (anyDisposerLogInstalled) {\n const inst = findInstance(scope)\n if (inst?._disposerLog !== undefined) {\n inst._disposerLog.push({\n scopeId: String(scope.id),\n cause: scope.disposalCause ?? 'component-unmount',\n timestamp: Date.now(),\n })\n }\n }\n if (!skipParentRemoval) removeFromParent(scope)\n scope.parent = null\n // Don't pool empty scopes from the early-return path — they may be\n // disposed idempotently (twice), which would create pool duplicates\n return\n }\n\n // When skipParentRemoval is true, children don't mutate during disposal —\n // iterate directly without allocating a copy. Otherwise, clone to avoid\n // mutation during iteration.\n const children = skipParentRemoval ? scope.children : scope.children.slice()\n for (const child of children) {\n disposeScope(child, skipParentRemoval)\n }\n\n for (const disposer of scope.disposers) {\n disposer()\n }\n\n // Dev-only: emit disposer events into the owning instance's log.\n // Outer flag check keeps production (no devtools ever installed) at\n // true zero cost — skips the O(depth) parent-chain walk entirely.\n if (anyDisposerLogInstalled) {\n const inst = findInstance(scope)\n if (inst?._disposerLog !== undefined) {\n inst._disposerLog.push({\n scopeId: String(scope.id),\n cause: scope.disposalCause ?? 'component-unmount',\n timestamp: Date.now(),\n })\n }\n }\n\n // Mark bindings as dead and break closure/DOM retention\n for (const binding of scope.bindings) {\n binding.dead = true\n binding.accessor = null!\n binding.node = null!\n binding.lastValue = undefined\n }\n\n // Reset to shared empties — don't just truncate, so pooled scopes\n // don't hold allocated-but-empty arrays\n scope.disposers = EMPTY_DISPOSERS\n scope.bindings = EMPTY_BINDINGS\n scope.children = EMPTY_SCOPES\n scope.itemUpdaters = EMPTY_UPDATERS\n\n if (!skipParentRemoval) removeFromParent(scope)\n scope.parent = null\n\n // Return to pool for reuse\n if (SCOPE_POOL.length < SCOPE_POOL_MAX) SCOPE_POOL.push(scope)\n}\n\n/**\n * Batch-remove children with `parent === null` from `parent.children`.\n * Called after a bulk `disposeScope(child, true)` pass to collapse the\n * individual O(N) splice operations into one O(N) scan.\n */\nexport function removeOrphanedChildren(parent: Scope): void {\n const children = parent.children\n let w = 0\n for (let r = 0; r < children.length; r++) {\n if (children[r]!.parent !== null) children[w++] = children[r]!\n }\n children.length = w\n}\n\n/**\n * Bulk dispose an array of sibling scopes — avoids per-scope function call\n * overhead. Used by each() clear path where 1000+ scopes are disposed at once.\n * Caller must call removeOrphanedChildren(parent) afterwards.\n */\nexport function disposeScopesBulk(scopes: Scope[]): void {\n for (let i = 0; i < scopes.length; i++) {\n const scope = scopes[i]!\n // Recursively dispose children\n const children = scope.children\n if (children.length > 0) {\n disposeScopesBulk(children)\n }\n // Run disposers\n const disposers = scope.disposers\n for (let d = 0; d < disposers.length; d++) disposers[d]!()\n // Dev-only: emit disposer events — same guard as disposeScope.\n if (anyDisposerLogInstalled) {\n const inst = findInstance(scope)\n if (inst?._disposerLog !== undefined) {\n inst._disposerLog.push({\n scopeId: String(scope.id),\n cause: scope.disposalCause ?? 'component-unmount',\n timestamp: Date.now(),\n })\n }\n }\n // Mark bindings dead\n const bindings = scope.bindings\n for (let b = 0; b < bindings.length; b++) {\n const binding = bindings[b]!\n binding.dead = true\n binding.accessor = null!\n binding.node = null!\n binding.lastValue = undefined\n }\n // Reset to shared empties + detach from parent + return to pool\n scope.disposers = EMPTY_DISPOSERS\n scope.bindings = EMPTY_BINDINGS\n scope.children = EMPTY_SCOPES\n scope.itemUpdaters = EMPTY_UPDATERS\n scope.parent = null\n if (SCOPE_POOL.length < SCOPE_POOL_MAX) SCOPE_POOL.push(scope)\n }\n}\n\nexport function addBinding(scope: Scope, binding: Binding): void {\n binding.ownerScope = scope\n if (scope.bindings === EMPTY_BINDINGS) scope.bindings = []\n scope.bindings.push(binding)\n}\n\nexport function addItemUpdater(scope: Scope, updater: () => void): void {\n if (scope.itemUpdaters === EMPTY_UPDATERS) scope.itemUpdaters = []\n scope.itemUpdaters.push(updater)\n}\n\n/**\n * Register a per-item updater that compares the new value against the last\n * value before applying. Shared by `text()`, `elSplit()`, and `elTemplate()`\n * so the equality-check logic lives in one place.\n *\n * @param apply - DOM write: receives the new value when it differs\n * @returns the initial value (caller should apply it to the DOM)\n */\nexport function addCheckedItemUpdater<V>(scope: Scope, get: () => V, apply: (value: V) => void): V {\n let last: V = get()\n addItemUpdater(scope, () => {\n const v = get()\n if (v === last || (v !== v && last !== last)) return\n last = v\n apply(v)\n })\n return last\n}\n\nexport function addDisposer(scope: Scope, disposer: () => void): void {\n if (scope.disposers === EMPTY_DISPOSERS) scope.disposers = []\n scope.disposers.push(disposer)\n}\n\nfunction removeFromParent(scope: Scope): void {\n if (scope.parent) {\n const idx = scope.parent.children.indexOf(scope)\n if (idx !== -1) {\n scope.parent.children.splice(idx, 1)\n }\n }\n}\n"]}