@vectojs/core 1.20.0 → 1.21.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -8,13 +8,14 @@
8
8
 
9
9
 
10
10
 
11
- var _chunkL4SWVP2Hjs = require('./chunk-L4SWVP2H.js');
12
11
 
12
+ var _chunkGKSCJ6AFjs = require('./chunk-GKSCJ6AF.js');
13
13
 
14
14
 
15
15
 
16
16
 
17
- var _chunkYLH7F4ZVjs = require('./chunk-YLH7F4ZV.js');
17
+
18
+ var _chunkAGP4VLF4js = require('./chunk-AGP4VLF4.js');
18
19
 
19
20
  // src/tree/Scene.ts
20
21
  var _animation = require('@vectojs/animation'); _createStarExport(_animation);
@@ -29,7 +30,7 @@ var PARTICLE_OFFSET_ORIGIN_X = 4;
29
30
  var PARTICLE_OFFSET_ORIGIN_Y = 5;
30
31
  var PARTICLE_OFFSET_SIZE = 6;
31
32
  var PARTICLE_OFFSET_LIFE = 7;
32
- var ComputeParticleEntity = (_class = class extends _chunkYLH7F4ZVjs.Entity {
33
+ var ComputeParticleEntity = (_class = class extends _chunkAGP4VLF4js.Entity {
33
34
 
34
35
 
35
36
 
@@ -1688,66 +1689,89 @@ var Scene = (_class7 = class _Scene {
1688
1689
  __init53() {this.contentGridCalibrationFrames = /* @__PURE__ */ new Map()}
1689
1690
  /** Detached, untransformed font probes used by the cold calibration pass. */
1690
1691
  __init54() {this.contentGridCalibrationProbes = /* @__PURE__ */ new Map()}
1692
+ /**
1693
+ * Monotonic stamp identifying the conditions grid cells were calibrated under.
1694
+ *
1695
+ * Calibration measures the difference between the advance the canvas grid assigns
1696
+ * a cluster and the width the browser lays it out at, then writes a per-cell
1697
+ * `scaleX`. That result stays valid until the font or the page scale changes, and
1698
+ * it lives on the cell element — so a cell carrying this stamp needs no further
1699
+ * work.
1700
+ *
1701
+ * The scan that feeds calibration was O(cells) on every revision bump: for a
1702
+ * streaming code block it re-derived a measurement key for every cell in the
1703
+ * block each frame in order to produce only ~20 distinct keys, costing about
1704
+ * 2.5 ms/frame after the `style.font` fix and still over half of `a11ySync`. Since
1705
+ * carrier reuse (#244) leaves untouched lines — and therefore their calibrated
1706
+ * transforms — in place, cells stamped with the current generation can simply be
1707
+ * skipped, making the scan O(new cells) instead.
1708
+ *
1709
+ * A plain incrementing integer rather than the descriptive calibration key,
1710
+ * because it goes into an attribute selector and must not need escaping.
1711
+ */
1712
+ __init55() {this.contentGridCalibrationGeneration = 0}
1713
+ /** The `(fontEpoch, pageScale)` pair the current generation corresponds to. */
1714
+ __init56() {this.contentGridCalibrationStamp = ""}
1691
1715
  /** Invalidates grid font calibration after browser font availability changes. */
1692
- __init55() {this.contentFontEpoch = 0}
1716
+ __init57() {this.contentFontEpoch = 0}
1693
1717
  /** Cached Canvas-to-client scale for the current font/viewport epoch. */
1694
- __init56() {this.contentMetricScaleEpoch = -1}
1695
- __init57() {this.contentMetricScaleX = 1}
1696
- __init58() {this.contentProjectionEnabled = true}
1718
+ __init58() {this.contentMetricScaleEpoch = -1}
1719
+ __init59() {this.contentMetricScaleX = 1}
1720
+ __init60() {this.contentProjectionEnabled = true}
1697
1721
  // Virtualization margin (px) for content projection; `undefined` → one
1698
1722
  // viewport height, resolved at sync time. `Infinity` = materialize everything.
1699
- __init59() {this.contentProjectionMargin = void 0}
1723
+ __init61() {this.contentProjectionMargin = void 0}
1700
1724
  /**
1701
1725
  * True while a text-selection drag that started on a projection's blank
1702
1726
  * region (no text node under the press) is being driven manually — the
1703
1727
  * browser has no native anchor for it, so mousemove extends the Selection
1704
1728
  * from the position we resolved ourselves.
1705
1729
  */
1706
- __init60() {this.blankRegionSelectionDrag = false}
1707
- __init61() {this.contentSelectionAnchor = null}
1708
- __init62() {this.contentSelectionEndListener = null}
1730
+ __init62() {this.blankRegionSelectionDrag = false}
1731
+ __init63() {this.contentSelectionAnchor = null}
1732
+ __init64() {this.contentSelectionEndListener = null}
1709
1733
  // Animation/interactive flags collected during the render walk (tree-walk
1710
1734
  // fusion): the loop reads last frame's answers instead of re-walking the
1711
1735
  // tree up to 4× per tick. Start true so the first tick stays conservative.
1712
- __init63() {this.frameHadAnimation = true}
1713
- __init64() {this.frameHadInteractive = true}
1736
+ __init65() {this.frameHadAnimation = true}
1737
+ __init66() {this.frameHadInteractive = true}
1714
1738
 
1715
1739
  /** Active `(resolution: Ndppx)` media query watching for a runtime DPR change
1716
1740
  * (window moved between monitors, browser zoom) so the canvas backing store
1717
1741
  * can be re-scaled — otherwise it stays rasterized at the old DPR and blurs.
1718
1742
  * A resolution media query only fires when leaving its exact value, so the
1719
1743
  * handler re-arms a fresh query for the new DPR each time. */
1720
- __init65() {this.dprMediaQuery = null}
1744
+ __init67() {this.dprMediaQuery = null}
1721
1745
  /** For embedded (`disableWindowResize`) scenes: observes the canvas element so
1722
1746
  * a CSS/layout-driven size change re-runs `resize()`. A window `resize`
1723
1747
  * listener never fires for these (the window isn't what changed), so without
1724
1748
  * this an embedded canvas stayed at its initial size forever. */
1725
- __init66() {this.canvasResizeObserver = null}
1726
- __init67() {this.dprChangeHandler = null}
1727
- __init68() {this.focusedA11yElement = null}
1749
+ __init68() {this.canvasResizeObserver = null}
1750
+ __init69() {this.dprChangeHandler = null}
1751
+ __init70() {this.focusedA11yElement = null}
1728
1752
  /** Last geometry `syncOverlayGeometry` wrote, so an unchanged frame can skip the
1729
1753
  * style writes entirely. Reset to `null` to force the next sync (a new overlay
1730
1754
  * layer was created and has never been positioned). */
1731
- __init69() {this._overlayGeometry = null}
1755
+ __init71() {this._overlayGeometry = null}
1732
1756
  /** Shadow elements the pointer is currently inside. Lets a removal that happens
1733
1757
  * mid-hover synthesize the `pointerleave` the browser never sends for a
1734
1758
  * detached element, so the entity doesn't keep its hover state. */
1735
- __init70() {this.hoveredA11yElements = /* @__PURE__ */ new WeakSet()}
1759
+ __init72() {this.hoveredA11yElements = /* @__PURE__ */ new WeakSet()}
1736
1760
  /** Persistent tabindex=-1 element in a11yRoot. When the focused a11y mirror is
1737
1761
  * pruned (virtualization/streaming/removal) while it holds focus, we move
1738
1762
  * focus here instead of letting the browser drop it to <body> — keeping the
1739
1763
  * screen-reader virtual cursor inside the scene's a11y region. */
1740
- __init71() {this.focusSentinel = null}
1741
- __init72() {this.caretBlinkTimer = null}
1742
- __init73() {this.a11yNeedsReorder = true}
1743
- __init74() {this.portalRoot = null}
1744
- __init75() {this.fullViewportElements = []}
1745
- __init76() {this.normalElements = []}
1746
- __init77() {this.activeIds = /* @__PURE__ */ new Set()}
1747
- __init78() {this.activePortalsThisFrame = /* @__PURE__ */ new Set()}
1748
- __init79() {this.activePortalsPrevFrame = /* @__PURE__ */ new Set()}
1749
- __init80() {this.portalEntities = /* @__PURE__ */ new Map()}
1750
- __init81() {this.renderOrderCounter = 0}
1764
+ __init73() {this.focusSentinel = null}
1765
+ __init74() {this.caretBlinkTimer = null}
1766
+ __init75() {this.a11yNeedsReorder = true}
1767
+ __init76() {this.portalRoot = null}
1768
+ __init77() {this.fullViewportElements = []}
1769
+ __init78() {this.normalElements = []}
1770
+ __init79() {this.activeIds = /* @__PURE__ */ new Set()}
1771
+ __init80() {this.activePortalsThisFrame = /* @__PURE__ */ new Set()}
1772
+ __init81() {this.activePortalsPrevFrame = /* @__PURE__ */ new Set()}
1773
+ __init82() {this.portalEntities = /* @__PURE__ */ new Map()}
1774
+ __init83() {this.renderOrderCounter = 0}
1751
1775
  /**
1752
1776
  * Monotonic render-frame counter, bumped once per authoritative `render()`
1753
1777
  * pass. Entities stamp their per-frame world-matrix cache with this value and
@@ -1756,7 +1780,7 @@ var Scene = (_class7 = class _Scene {
1756
1780
  * back to the ancestor walk. Public for the same reason `Entity._getTrig`/
1757
1781
  * `_setWorldCache` are: it is a cross-class render-internal contract.
1758
1782
  */
1759
- __init82() {this.currentFrame = 0}
1783
+ __init84() {this.currentFrame = 0}
1760
1784
  // ── WASM transform backend (invisible accelerator) ──────────────────────────
1761
1785
  // When `_transformBackend === 'wasm'`, the main render walk sources each
1762
1786
  // entity's world matrix from an SoA store composed by `_wasm` (see
@@ -1764,24 +1788,24 @@ var Scene = (_class7 = class _Scene {
1764
1788
  // fallback and the default: a null backend, a non-main renderer, or any entity
1765
1789
  // absent from the store all fall back to the JS composition, so WASM can only
1766
1790
  // ever change *how fast* a world matrix is produced, never *what* it is.
1767
- __init83() {this._wasm = null}
1768
- __init84() {this._transformBackend = "js"}
1791
+ __init85() {this._wasm = null}
1792
+ __init86() {this._transformBackend = "js"}
1769
1793
  // Resident store state (Stage 3). The store layout — slot assignment + sibling
1770
1794
  // runs — depends only on tree TOPOLOGY, so it is rebuilt only when the
1771
1795
  // structure changes (add/remove/reparent bump `_structureVersion`). Between
1772
1796
  // rebuilds the per-frame cost is: gather each entity's transform into the
1773
1797
  // resident wasm input view + run the kernel — no reallocation, no readback.
1774
- __init85() {this._treeStore = null}
1775
- __init86() {this._slotEntity = []}
1798
+ __init87() {this._treeStore = null}
1799
+ __init88() {this._slotEntity = []}
1776
1800
  // store slot -> entity (also validates slots)
1777
- __init87() {this._wasmInputs = null}
1778
- __init88() {this._wasmWorld = null}
1779
- __init89() {this._structureVersion = 0}
1780
- __init90() {this._storeStructureVersion = -1}
1801
+ __init89() {this._wasmInputs = null}
1802
+ __init90() {this._wasmWorld = null}
1803
+ __init91() {this._structureVersion = 0}
1804
+ __init92() {this._storeStructureVersion = -1}
1781
1805
  // Cached list of ComputeParticleEntity instances in the tree, keyed by the
1782
1806
  // structure version it was gathered at. Rebuilt only on a topology change.
1783
- __init91() {this._computeEntities = []}
1784
- __init92() {this._computeEntitiesVersion = -1}
1807
+ __init93() {this._computeEntities = []}
1808
+ __init94() {this._computeEntitiesVersion = -1}
1785
1809
  /** Invalidate the resident WASM store layout; the next wasm-mode frame rebuilds
1786
1810
  * it. Called by `Entity.add`/`remove` (topology changes only). */
1787
1811
  markStructureChanged() {
@@ -1863,7 +1887,7 @@ var Scene = (_class7 = class _Scene {
1863
1887
  * cached globally; the instance is per-Scene, which is the isolation that
1864
1888
  * actually matters.
1865
1889
  */
1866
- __init93() {this._wasmRuntime = null}
1890
+ __init95() {this._wasmRuntime = null}
1867
1891
  /**
1868
1892
  * Load (or reuse) this Scene's shared WASM runtime.
1869
1893
  *
@@ -1891,30 +1915,30 @@ var Scene = (_class7 = class _Scene {
1891
1915
  get wasmRuntime() {
1892
1916
  return this._wasmRuntime;
1893
1917
  }
1894
- __init94() {this._hitWasm = null}
1918
+ __init96() {this._hitWasm = null}
1895
1919
  // Cache key: which frame + structure version the grid was last (successfully,
1896
1920
  // non-overflowing) built for. findEntityAt is called ad-hoc (pointer
1897
1921
  // hover/click), not every frame, so the grid is refreshed lazily on demand
1898
1922
  // rather than proactively every render() — unlike the transform store, which
1899
1923
  // every frame's draw depends on.
1900
- __init95() {this._hitGridFrame = -1}
1901
- __init96() {this._hitGridOk = false}
1902
- __init97() {this._hitSlotEntity = []}
1903
- __init98() {this._hitBoundless = []}
1924
+ __init97() {this._hitGridFrame = -1}
1925
+ __init98() {this._hitGridOk = false}
1926
+ __init99() {this._hitSlotEntity = []}
1927
+ __init100() {this._hitBoundless = []}
1904
1928
  /** Reused buffer for the fused gather, so a pointer query allocates nothing. */
1905
- __init99() {this._hitGatherBuffer = null}
1929
+ __init101() {this._hitGatherBuffer = null}
1906
1930
  /**
1907
1931
  * Whether the last grid build sourced its AABBs from the WASM transform store
1908
1932
  * rather than recomputing them in JS. Diagnostic only — both paths must
1909
1933
  * produce the same entity for a given point.
1910
1934
  */
1911
- __init100() {this._hitFusedGather = false}
1935
+ __init102() {this._hitFusedGather = false}
1912
1936
  /**
1913
1937
  * Whether `compute_aabbs` has run against the current frame's world matrices.
1914
1938
  * The AABB pass is only meaningful after a `compose_*`, so the fused gather
1915
1939
  * must not read the views before then.
1916
1940
  */
1917
- __init101() {this._wasmAabbsFresh = false}
1941
+ __init103() {this._wasmAabbsFresh = false}
1918
1942
  /** Did the last hit-grid build use the fused (WASM-store) gather? */
1919
1943
  get hitGatherPath() {
1920
1944
  return this._hitFusedGather ? "fused" : "js";
@@ -2028,25 +2052,25 @@ var Scene = (_class7 = class _Scene {
2028
2052
  // EasingFn (which cannot cross into WASM) all fall through to it — WASM can
2029
2053
  // only ever change *how* a driver is advanced, never *what* value it lands
2030
2054
  // on.
2031
- __init102() {this._animWasm = null}
2055
+ __init104() {this._animWasm = null}
2032
2056
  // Entities with at least one active driver, added by Entity._spawnDriver.
2033
2057
  // Self-pruning: _tickBatchedDrivers drops an entry the first time it visits
2034
2058
  // an entity whose drivers have since all completed or been removed. This is
2035
2059
  // what lets the batch pass find its candidates in O(active drivers), not
2036
2060
  // O(tree size) — the exact mistake G3's first integrated benchmark made.
2037
- __init103() {this._activeDriverEntities = /* @__PURE__ */ new Set()}
2061
+ __init105() {this._activeDriverEntities = /* @__PURE__ */ new Set()}
2038
2062
  // Reused across frames instead of allocating a fresh array + N {entity,prop,
2039
2063
  // driver} objects every call — the integrated benchmark
2040
2064
  // (benchmarks/anim-wasm-scene) found that allocation churn was the
2041
2065
  // dominant integrated cost, not the wasm kernel itself. Parallel arrays,
2042
2066
  // truncated to the live count after each use so a stale tail slot never
2043
2067
  // pins a no-longer-active entity/driver in memory.
2044
- __init104() {this._springEntities = []}
2045
- __init105() {this._springProps = []}
2046
- __init106() {this._springDrivers = []}
2047
- __init107() {this._tweenEntities = []}
2048
- __init108() {this._tweenProps = []}
2049
- __init109() {this._tweenDrivers = []}
2068
+ __init106() {this._springEntities = []}
2069
+ __init107() {this._springProps = []}
2070
+ __init108() {this._springDrivers = []}
2071
+ __init109() {this._tweenEntities = []}
2072
+ __init110() {this._tweenProps = []}
2073
+ __init111() {this._tweenDrivers = []}
2050
2074
  /**
2051
2075
  * Minimum number of batchable (spring, or named-easing tween) active drivers
2052
2076
  * before a frame engages the WASM batch path at all; below it, every driver
@@ -2118,7 +2142,7 @@ var Scene = (_class7 = class _Scene {
2118
2142
  * Setting {@link animDriverGateCount} overwrites all three, so existing code
2119
2143
  * that tuned the single knob keeps working unchanged.
2120
2144
  */
2121
- __init110() {this._animBatchedLastFrame = false}
2145
+ __init112() {this._animBatchedLastFrame = false}
2122
2146
  /**
2123
2147
  * Whether the WASM batch path actually ran on the most recent frame.
2124
2148
  *
@@ -2130,7 +2154,7 @@ var Scene = (_class7 = class _Scene {
2130
2154
  get animBatchedLastFrame() {
2131
2155
  return this._animBatchedLastFrame;
2132
2156
  }
2133
- __init111() {this.animGate = {
2157
+ __init113() {this.animGate = {
2134
2158
  spring: 128,
2135
2159
  tween: 256,
2136
2160
  mixed: 128
@@ -2168,7 +2192,7 @@ var Scene = (_class7 = class _Scene {
2168
2192
  // (benchmarks/particle-wasm). f32 (matches the WGSL shader), bit-identical to
2169
2193
  // a JS f32 reference oracle; updateCPU (f64) stays the permanent fallback when
2170
2194
  // no backend is installed or a scene runs on WebGPU.
2171
- __init112() {this._particleWasm = null}
2195
+ __init114() {this._particleWasm = null}
2172
2196
  /** Which backend runs the CPU particle simulation. Reflects only whether a
2173
2197
  * backend is installed (the WebGPU compute path, when active, is used first
2174
2198
  * regardless). */
@@ -2418,46 +2442,46 @@ var Scene = (_class7 = class _Scene {
2418
2442
  * sync, so retaining the order prevents a newly opened overlay from spending
2419
2443
  * its first frame below previously projected controls.
2420
2444
  */
2421
- __init113() {this.a11yRenderOrders = /* @__PURE__ */ new Map()}
2445
+ __init115() {this.a11yRenderOrders = /* @__PURE__ */ new Map()}
2422
2446
  // Optional WebGL point-cloud layer (see SceneOptions.pointBackend).
2423
- __init114() {this.pointRenderer = null}
2424
- __init115() {this.glCanvas = null}
2425
- __init116() {this.glContextLostHandler = null}
2426
- __init117() {this.glContextRestoredHandler = null}
2447
+ __init116() {this.pointRenderer = null}
2448
+ __init117() {this.glCanvas = null}
2449
+ __init118() {this.glContextLostHandler = null}
2450
+ __init119() {this.glContextRestoredHandler = null}
2427
2451
 
2428
2452
 
2429
2453
 
2430
- __init118() {this.disableWindowResize = false}
2454
+ __init120() {this.disableWindowResize = false}
2431
2455
  /** See {@link SceneOptions.maxDPR}. `undefined` = uncapped (real DPR). */
2432
2456
 
2433
2457
  // WebGPU properties
2434
- __init119() {this.destroyed = false}
2435
- __init120() {this.device = null}
2436
- __init121() {this.deviceLost = false}
2437
- __init122() {this.particleBackend = "auto"}
2438
- __init123() {this._webgpuDisabled = false}
2458
+ __init121() {this.destroyed = false}
2459
+ __init122() {this.device = null}
2460
+ __init123() {this.deviceLost = false}
2461
+ __init124() {this.particleBackend = "auto"}
2462
+ __init125() {this._webgpuDisabled = false}
2439
2463
  get webgpuDisabled() {
2440
2464
  return this._webgpuDisabled || this.particleBackend === "cpu";
2441
2465
  }
2442
2466
  set webgpuDisabled(value) {
2443
2467
  this._webgpuDisabled = value;
2444
2468
  }
2445
- __init124() {this.recoveryTimerId = null}
2446
- __init125() {this.manager = null}
2447
- __init126() {this.initializingWebGPU = false}
2448
- __init127() {this.gpuCanvas = null}
2449
- __init128() {this.gpuContext = null}
2469
+ __init126() {this.recoveryTimerId = null}
2470
+ __init127() {this.manager = null}
2471
+ __init128() {this.initializingWebGPU = false}
2472
+ __init129() {this.gpuCanvas = null}
2473
+ __init130() {this.gpuContext = null}
2450
2474
  /** True while the GPU canvas holds a presented particle frame (needs clearing when they leave). */
2451
- __init129() {this.gpuHasContent = false}
2452
- __init130() {this.mouseX = -9999}
2453
- __init131() {this.mouseY = -9999}
2454
- __init132() {this.pointerMoveListener = null}
2455
- __init133() {this.pointerLeaveListener = null}
2475
+ __init131() {this.gpuHasContent = false}
2476
+ __init132() {this.mouseX = -9999}
2477
+ __init133() {this.mouseY = -9999}
2478
+ __init134() {this.pointerMoveListener = null}
2479
+ __init135() {this.pointerLeaveListener = null}
2456
2480
  /** Element the pointer listeners are bound to (parent container if present,
2457
2481
  * else the canvas). Stored so `destroy()` detaches from the same element. */
2458
- __init134() {this.pointerEventTarget = null}
2459
- __init135() {this.hasWarnedZeroSize = false}
2460
- __init136() {this.fontLoadHandler = null}
2482
+ __init136() {this.pointerEventTarget = null}
2483
+ __init137() {this.hasWarnedZeroSize = false}
2484
+ __init138() {this.fontLoadHandler = null}
2461
2485
  // ── Dev-mode warning infrastructure ──────────────────────────────
2462
2486
  //
2463
2487
  // Enable with `Scene.devMode = true` or by setting `globalThis.__DEV__`.
@@ -2475,7 +2499,7 @@ var Scene = (_class7 = class _Scene {
2475
2499
  return false;
2476
2500
  }
2477
2501
 
2478
- __init137() {this._devFrameCount = 0}
2502
+ __init139() {this._devFrameCount = 0}
2479
2503
  _devWarn(message) {
2480
2504
  if (!this._devActive) return;
2481
2505
  console.warn(`[vectojs/dev] ${message}`);
@@ -2519,7 +2543,7 @@ var Scene = (_class7 = class _Scene {
2519
2543
  };
2520
2544
  walkProjections(this.root);
2521
2545
  }
2522
- constructor(canvas, options = {}) {;_class7.prototype.__init25.call(this);_class7.prototype.__init26.call(this);_class7.prototype.__init27.call(this);_class7.prototype.__init28.call(this);_class7.prototype.__init29.call(this);_class7.prototype.__init30.call(this);_class7.prototype.__init31.call(this);_class7.prototype.__init32.call(this);_class7.prototype.__init33.call(this);_class7.prototype.__init34.call(this);_class7.prototype.__init35.call(this);_class7.prototype.__init36.call(this);_class7.prototype.__init37.call(this);_class7.prototype.__init38.call(this);_class7.prototype.__init39.call(this);_class7.prototype.__init40.call(this);_class7.prototype.__init41.call(this);_class7.prototype.__init42.call(this);_class7.prototype.__init43.call(this);_class7.prototype.__init44.call(this);_class7.prototype.__init45.call(this);_class7.prototype.__init46.call(this);_class7.prototype.__init47.call(this);_class7.prototype.__init48.call(this);_class7.prototype.__init49.call(this);_class7.prototype.__init50.call(this);_class7.prototype.__init51.call(this);_class7.prototype.__init52.call(this);_class7.prototype.__init53.call(this);_class7.prototype.__init54.call(this);_class7.prototype.__init55.call(this);_class7.prototype.__init56.call(this);_class7.prototype.__init57.call(this);_class7.prototype.__init58.call(this);_class7.prototype.__init59.call(this);_class7.prototype.__init60.call(this);_class7.prototype.__init61.call(this);_class7.prototype.__init62.call(this);_class7.prototype.__init63.call(this);_class7.prototype.__init64.call(this);_class7.prototype.__init65.call(this);_class7.prototype.__init66.call(this);_class7.prototype.__init67.call(this);_class7.prototype.__init68.call(this);_class7.prototype.__init69.call(this);_class7.prototype.__init70.call(this);_class7.prototype.__init71.call(this);_class7.prototype.__init72.call(this);_class7.prototype.__init73.call(this);_class7.prototype.__init74.call(this);_class7.prototype.__init75.call(this);_class7.prototype.__init76.call(this);_class7.prototype.__init77.call(this);_class7.prototype.__init78.call(this);_class7.prototype.__init79.call(this);_class7.prototype.__init80.call(this);_class7.prototype.__init81.call(this);_class7.prototype.__init82.call(this);_class7.prototype.__init83.call(this);_class7.prototype.__init84.call(this);_class7.prototype.__init85.call(this);_class7.prototype.__init86.call(this);_class7.prototype.__init87.call(this);_class7.prototype.__init88.call(this);_class7.prototype.__init89.call(this);_class7.prototype.__init90.call(this);_class7.prototype.__init91.call(this);_class7.prototype.__init92.call(this);_class7.prototype.__init93.call(this);_class7.prototype.__init94.call(this);_class7.prototype.__init95.call(this);_class7.prototype.__init96.call(this);_class7.prototype.__init97.call(this);_class7.prototype.__init98.call(this);_class7.prototype.__init99.call(this);_class7.prototype.__init100.call(this);_class7.prototype.__init101.call(this);_class7.prototype.__init102.call(this);_class7.prototype.__init103.call(this);_class7.prototype.__init104.call(this);_class7.prototype.__init105.call(this);_class7.prototype.__init106.call(this);_class7.prototype.__init107.call(this);_class7.prototype.__init108.call(this);_class7.prototype.__init109.call(this);_class7.prototype.__init110.call(this);_class7.prototype.__init111.call(this);_class7.prototype.__init112.call(this);_class7.prototype.__init113.call(this);_class7.prototype.__init114.call(this);_class7.prototype.__init115.call(this);_class7.prototype.__init116.call(this);_class7.prototype.__init117.call(this);_class7.prototype.__init118.call(this);_class7.prototype.__init119.call(this);_class7.prototype.__init120.call(this);_class7.prototype.__init121.call(this);_class7.prototype.__init122.call(this);_class7.prototype.__init123.call(this);_class7.prototype.__init124.call(this);_class7.prototype.__init125.call(this);_class7.prototype.__init126.call(this);_class7.prototype.__init127.call(this);_class7.prototype.__init128.call(this);_class7.prototype.__init129.call(this);_class7.prototype.__init130.call(this);_class7.prototype.__init131.call(this);_class7.prototype.__init132.call(this);_class7.prototype.__init133.call(this);_class7.prototype.__init134.call(this);_class7.prototype.__init135.call(this);_class7.prototype.__init136.call(this);_class7.prototype.__init137.call(this);
2546
+ constructor(canvas, options = {}) {;_class7.prototype.__init25.call(this);_class7.prototype.__init26.call(this);_class7.prototype.__init27.call(this);_class7.prototype.__init28.call(this);_class7.prototype.__init29.call(this);_class7.prototype.__init30.call(this);_class7.prototype.__init31.call(this);_class7.prototype.__init32.call(this);_class7.prototype.__init33.call(this);_class7.prototype.__init34.call(this);_class7.prototype.__init35.call(this);_class7.prototype.__init36.call(this);_class7.prototype.__init37.call(this);_class7.prototype.__init38.call(this);_class7.prototype.__init39.call(this);_class7.prototype.__init40.call(this);_class7.prototype.__init41.call(this);_class7.prototype.__init42.call(this);_class7.prototype.__init43.call(this);_class7.prototype.__init44.call(this);_class7.prototype.__init45.call(this);_class7.prototype.__init46.call(this);_class7.prototype.__init47.call(this);_class7.prototype.__init48.call(this);_class7.prototype.__init49.call(this);_class7.prototype.__init50.call(this);_class7.prototype.__init51.call(this);_class7.prototype.__init52.call(this);_class7.prototype.__init53.call(this);_class7.prototype.__init54.call(this);_class7.prototype.__init55.call(this);_class7.prototype.__init56.call(this);_class7.prototype.__init57.call(this);_class7.prototype.__init58.call(this);_class7.prototype.__init59.call(this);_class7.prototype.__init60.call(this);_class7.prototype.__init61.call(this);_class7.prototype.__init62.call(this);_class7.prototype.__init63.call(this);_class7.prototype.__init64.call(this);_class7.prototype.__init65.call(this);_class7.prototype.__init66.call(this);_class7.prototype.__init67.call(this);_class7.prototype.__init68.call(this);_class7.prototype.__init69.call(this);_class7.prototype.__init70.call(this);_class7.prototype.__init71.call(this);_class7.prototype.__init72.call(this);_class7.prototype.__init73.call(this);_class7.prototype.__init74.call(this);_class7.prototype.__init75.call(this);_class7.prototype.__init76.call(this);_class7.prototype.__init77.call(this);_class7.prototype.__init78.call(this);_class7.prototype.__init79.call(this);_class7.prototype.__init80.call(this);_class7.prototype.__init81.call(this);_class7.prototype.__init82.call(this);_class7.prototype.__init83.call(this);_class7.prototype.__init84.call(this);_class7.prototype.__init85.call(this);_class7.prototype.__init86.call(this);_class7.prototype.__init87.call(this);_class7.prototype.__init88.call(this);_class7.prototype.__init89.call(this);_class7.prototype.__init90.call(this);_class7.prototype.__init91.call(this);_class7.prototype.__init92.call(this);_class7.prototype.__init93.call(this);_class7.prototype.__init94.call(this);_class7.prototype.__init95.call(this);_class7.prototype.__init96.call(this);_class7.prototype.__init97.call(this);_class7.prototype.__init98.call(this);_class7.prototype.__init99.call(this);_class7.prototype.__init100.call(this);_class7.prototype.__init101.call(this);_class7.prototype.__init102.call(this);_class7.prototype.__init103.call(this);_class7.prototype.__init104.call(this);_class7.prototype.__init105.call(this);_class7.prototype.__init106.call(this);_class7.prototype.__init107.call(this);_class7.prototype.__init108.call(this);_class7.prototype.__init109.call(this);_class7.prototype.__init110.call(this);_class7.prototype.__init111.call(this);_class7.prototype.__init112.call(this);_class7.prototype.__init113.call(this);_class7.prototype.__init114.call(this);_class7.prototype.__init115.call(this);_class7.prototype.__init116.call(this);_class7.prototype.__init117.call(this);_class7.prototype.__init118.call(this);_class7.prototype.__init119.call(this);_class7.prototype.__init120.call(this);_class7.prototype.__init121.call(this);_class7.prototype.__init122.call(this);_class7.prototype.__init123.call(this);_class7.prototype.__init124.call(this);_class7.prototype.__init125.call(this);_class7.prototype.__init126.call(this);_class7.prototype.__init127.call(this);_class7.prototype.__init128.call(this);_class7.prototype.__init129.call(this);_class7.prototype.__init130.call(this);_class7.prototype.__init131.call(this);_class7.prototype.__init132.call(this);_class7.prototype.__init133.call(this);_class7.prototype.__init134.call(this);_class7.prototype.__init135.call(this);_class7.prototype.__init136.call(this);_class7.prototype.__init137.call(this);_class7.prototype.__init138.call(this);_class7.prototype.__init139.call(this);
2523
2547
  this.canvas = canvas;
2524
2548
  this.debugA11y = _nullishCoalesce(options.debugA11y, () => ( false));
2525
2549
  this.disableWindowResize = _nullishCoalesce(options.disableWindowResize, () => ( false));
@@ -2550,7 +2574,7 @@ var Scene = (_class7 = class _Scene {
2550
2574
  this.forcedColorsChangeHandler = () => this.markDirty();
2551
2575
  _optionalChain([this, 'access', _45 => _45.forcedColorsQuery, 'access', _46 => _46.addEventListener, 'optionalCall', _47 => _47("change", this.forcedColorsChangeHandler)]);
2552
2576
  }
2553
- this.root = new class RootEntity extends _chunkYLH7F4ZVjs.Entity {
2577
+ this.root = new class RootEntity extends _chunkAGP4VLF4js.Entity {
2554
2578
  isPointInside() {
2555
2579
  return false;
2556
2580
  }
@@ -2559,7 +2583,7 @@ var Scene = (_class7 = class _Scene {
2559
2583
  }
2560
2584
  }("root");
2561
2585
  this.root._scene = this;
2562
- this.overlayRoot = new class OverlayRoot extends _chunkYLH7F4ZVjs.Entity {
2586
+ this.overlayRoot = new class OverlayRoot extends _chunkAGP4VLF4js.Entity {
2563
2587
  isPointInside() {
2564
2588
  return false;
2565
2589
  }
@@ -2570,7 +2594,7 @@ var Scene = (_class7 = class _Scene {
2570
2594
  if (options.renderer) {
2571
2595
  this.renderer = options.renderer;
2572
2596
  } else {
2573
- this.renderer = new (0, _chunkL4SWVP2Hjs.CanvasRenderer)(
2597
+ this.renderer = new (0, _chunkGKSCJ6AFjs.CanvasRenderer)(
2574
2598
  canvas,
2575
2599
  this.disableWindowResize ? { width: this.width, height: this.height } : void 0,
2576
2600
  this.maxDPR
@@ -2796,12 +2820,35 @@ var Scene = (_class7 = class _Scene {
2796
2820
  this.contentSelectionAnchor = null;
2797
2821
  if (this.a11yRoot) this.a11yRoot.style.pointerEvents = "none";
2798
2822
  }
2823
+ /**
2824
+ * Index of the carrier line currently holding a selection inside `el`, or
2825
+ * `null`.
2826
+ *
2827
+ * Lets a partial re-materialization decide whether the user's selection is even
2828
+ * affected. Checks the tracked anchor first (it survives a drag) and falls back
2829
+ * to the live DOM selection.
2830
+ */
2831
+ contentGridSelectionLine(el) {
2832
+ const candidates = [_optionalChain([this, 'access', _62 => _62.contentSelectionAnchor, 'optionalAccess', _63 => _63.node])];
2833
+ if (typeof window !== "undefined" && typeof window.getSelection === "function") {
2834
+ const selection = window.getSelection();
2835
+ candidates.push(_optionalChain([selection, 'optionalAccess', _64 => _64.anchorNode]), _optionalChain([selection, 'optionalAccess', _65 => _65.focusNode]));
2836
+ }
2837
+ for (const candidate of candidates) {
2838
+ if (!candidate || !el.contains(candidate)) continue;
2839
+ let cursor = candidate;
2840
+ while (cursor && cursor.parentNode !== el) cursor = cursor.parentNode;
2841
+ const lineIndex = _optionalChain([cursor, 'optionalAccess', _66 => _66.dataset, 'optionalAccess', _67 => _67.vectoGridLine]);
2842
+ if (lineIndex !== void 0) return Number(lineIndex);
2843
+ }
2844
+ return null;
2845
+ }
2799
2846
  releaseContentSelectionForRebuild(el) {
2800
2847
  const selection = typeof window !== "undefined" && typeof window.getSelection === "function" ? window.getSelection() : null;
2801
- const ownsSelection = this.contentSelectionAnchor && el.contains(this.contentSelectionAnchor.node) || (_optionalChain([selection, 'optionalAccess', _62 => _62.anchorNode]) ? el.contains(selection.anchorNode) : false) || (_optionalChain([selection, 'optionalAccess', _63 => _63.focusNode]) ? el.contains(selection.focusNode) : false);
2848
+ const ownsSelection = this.contentSelectionAnchor && el.contains(this.contentSelectionAnchor.node) || (_optionalChain([selection, 'optionalAccess', _68 => _68.anchorNode]) ? el.contains(selection.anchorNode) : false) || (_optionalChain([selection, 'optionalAccess', _69 => _69.focusNode]) ? el.contains(selection.focusNode) : false);
2802
2849
  if (!ownsSelection) return;
2803
2850
  this.endContentSelectionDrag();
2804
- _optionalChain([selection, 'optionalAccess', _64 => _64.removeAllRanges, 'call', _65 => _65()]);
2851
+ _optionalChain([selection, 'optionalAccess', _70 => _70.removeAllRanges, 'call', _71 => _71()]);
2805
2852
  }
2806
2853
  /**
2807
2854
  * Rebuild a content-projection element's DOM (`rebuild`) while preserving a
@@ -2860,7 +2907,7 @@ var Scene = (_class7 = class _Scene {
2860
2907
  }
2861
2908
  /** Convert browser viewport coordinates into this Scene's logical coordinates. */
2862
2909
  clientToScene(clientX, clientY) {
2863
- const rect = _optionalChain([this, 'access', _66 => _66.canvas, 'access', _67 => _67.getBoundingClientRect, 'optionalCall', _68 => _68()]);
2910
+ const rect = _optionalChain([this, 'access', _72 => _72.canvas, 'access', _73 => _73.getBoundingClientRect, 'optionalCall', _74 => _74()]);
2864
2911
  if (!rect) return { x: clientX, y: clientY };
2865
2912
  const cssWidth = rect.width || this.canvas.clientWidth || this.width;
2866
2913
  const cssHeight = rect.height || this.canvas.clientHeight || this.height;
@@ -2881,13 +2928,24 @@ var Scene = (_class7 = class _Scene {
2881
2928
  this.registerActiveDriverSubtree(entity);
2882
2929
  return this;
2883
2930
  }
2884
- clearContentGridState(entityId, el) {
2931
+ /**
2932
+ * Reset per-grid calibration and bookkeeping before a (re)materialization.
2933
+ *
2934
+ * @param entityId - Owning entity, keyed into the calibration maps.
2935
+ * @param el - The projection element.
2936
+ * @param releaseSelection - Whether to drop a selection this element owns.
2937
+ * Pass `false` when carrier lines are being reused: the selection's DOM nodes
2938
+ * survive the pass, so tearing it down would wipe a user's selection on every
2939
+ * streamed chunk — the exact bug `preserveContentSelectionAcrossRebuild`
2940
+ * exists to prevent on the non-grid path.
2941
+ */
2942
+ clearContentGridState(entityId, el, releaseSelection = true) {
2885
2943
  const calibrationFrame = this.contentGridCalibrationFrames.get(entityId);
2886
2944
  if (calibrationFrame !== void 0 && typeof cancelAnimationFrame === "function") {
2887
2945
  cancelAnimationFrame(calibrationFrame);
2888
2946
  }
2889
2947
  this.contentGridCalibrationFrames.delete(entityId);
2890
- _optionalChain([this, 'access', _69 => _69.contentGridCalibrationProbes, 'access', _70 => _70.get, 'call', _71 => _71(entityId), 'optionalAccess', _72 => _72.remove, 'call', _73 => _73()]);
2948
+ _optionalChain([this, 'access', _75 => _75.contentGridCalibrationProbes, 'access', _76 => _76.get, 'call', _77 => _77(entityId), 'optionalAccess', _78 => _78.remove, 'call', _79 => _79()]);
2891
2949
  this.contentGridCalibrationProbes.delete(entityId);
2892
2950
  delete el.dataset.vectoGridCalibrationPending;
2893
2951
  delete el.dataset.vectoGridCalibration;
@@ -2897,7 +2955,7 @@ var Scene = (_class7 = class _Scene {
2897
2955
  delete el.dataset.vectoGridMaterializeMs;
2898
2956
  delete el.dataset.vectoGridCalibrationSamples;
2899
2957
  delete el.dataset.vectoGridCalibrationMs;
2900
- this.releaseContentSelectionForRebuild(el);
2958
+ if (releaseSelection) this.releaseContentSelectionForRebuild(el);
2901
2959
  }
2902
2960
  /**
2903
2961
  * Drop any projected elements under `node` without touching the entity tree.
@@ -2939,7 +2997,7 @@ var Scene = (_class7 = class _Scene {
2939
2997
  }
2940
2998
  if (this.hoveredA11yElements.has(el)) {
2941
2999
  this.hoveredA11yElements.delete(el);
2942
- node.dispatchEvent(new (0, _chunkYLH7F4ZVjs.VectoJSEvent)("pointerleave", node, void 0, false));
3000
+ node.dispatchEvent(new (0, _chunkAGP4VLF4js.VectoJSEvent)("pointerleave", node, void 0, false));
2943
3001
  }
2944
3002
  this.preserveFocusOnRemoval(el);
2945
3003
  el.remove();
@@ -3041,12 +3099,12 @@ var Scene = (_class7 = class _Scene {
3041
3099
  this.canvasResizeObserver = null;
3042
3100
  }
3043
3101
  if (this.dprMediaQuery && this.dprChangeHandler) {
3044
- _optionalChain([this, 'access', _74 => _74.dprMediaQuery, 'access', _75 => _75.removeEventListener, 'optionalCall', _76 => _76("change", this.dprChangeHandler)]);
3102
+ _optionalChain([this, 'access', _80 => _80.dprMediaQuery, 'access', _81 => _81.removeEventListener, 'optionalCall', _82 => _82("change", this.dprChangeHandler)]);
3045
3103
  this.dprMediaQuery = null;
3046
3104
  this.dprChangeHandler = null;
3047
3105
  }
3048
3106
  if (this.forcedColorsQuery && this.forcedColorsChangeHandler) {
3049
- _optionalChain([this, 'access', _77 => _77.forcedColorsQuery, 'access', _78 => _78.removeEventListener, 'optionalCall', _79 => _79("change", this.forcedColorsChangeHandler)]);
3107
+ _optionalChain([this, 'access', _83 => _83.forcedColorsQuery, 'access', _84 => _84.removeEventListener, 'optionalCall', _85 => _85("change", this.forcedColorsChangeHandler)]);
3050
3108
  this.forcedColorsQuery = null;
3051
3109
  this.forcedColorsChangeHandler = null;
3052
3110
  }
@@ -3064,9 +3122,9 @@ var Scene = (_class7 = class _Scene {
3064
3122
  }
3065
3123
  this.pointerEventTarget = null;
3066
3124
  }
3067
- _optionalChain([this, 'access', _80 => _80.a11yRoot, 'optionalAccess', _81 => _81.remove, 'call', _82 => _82()]);
3125
+ _optionalChain([this, 'access', _86 => _86.a11yRoot, 'optionalAccess', _87 => _87.remove, 'call', _88 => _88()]);
3068
3126
  this.focusSentinel = null;
3069
- _optionalChain([this, 'access', _83 => _83.portalRoot, 'optionalAccess', _84 => _84.remove, 'call', _85 => _85()]);
3127
+ _optionalChain([this, 'access', _89 => _89.portalRoot, 'optionalAccess', _90 => _90.remove, 'call', _91 => _91()]);
3070
3128
  this.a11yElements.clear();
3071
3129
  for (const el of this.contentElements.values()) el.remove();
3072
3130
  this.contentElements.clear();
@@ -3089,10 +3147,10 @@ var Scene = (_class7 = class _Scene {
3089
3147
  }
3090
3148
  this.glContextLostHandler = null;
3091
3149
  this.glContextRestoredHandler = null;
3092
- _optionalChain([this, 'access', _86 => _86.pointRenderer, 'optionalAccess', _87 => _87.destroy, 'call', _88 => _88()]);
3093
- _optionalChain([this, 'access', _89 => _89.renderer, 'access', _90 => _90.dispose, 'optionalCall', _91 => _91()]);
3094
- _optionalChain([this, 'access', _92 => _92.glCanvas, 'optionalAccess', _93 => _93.remove, 'call', _94 => _94()]);
3095
- _optionalChain([this, 'access', _95 => _95.gpuCanvas, 'optionalAccess', _96 => _96.remove, 'call', _97 => _97()]);
3150
+ _optionalChain([this, 'access', _92 => _92.pointRenderer, 'optionalAccess', _93 => _93.destroy, 'call', _94 => _94()]);
3151
+ _optionalChain([this, 'access', _95 => _95.renderer, 'access', _96 => _96.dispose, 'optionalCall', _97 => _97()]);
3152
+ _optionalChain([this, 'access', _98 => _98.glCanvas, 'optionalAccess', _99 => _99.remove, 'call', _100 => _100()]);
3153
+ _optionalChain([this, 'access', _101 => _101.gpuCanvas, 'optionalAccess', _102 => _102.remove, 'call', _103 => _103()]);
3096
3154
  this.gpuCanvas = null;
3097
3155
  this.gpuContext = null;
3098
3156
  if (this.recoveryTimerId) {
@@ -3104,7 +3162,7 @@ var Scene = (_class7 = class _Scene {
3104
3162
  this.manager = null;
3105
3163
  }
3106
3164
  if (this.device) {
3107
- _optionalChain([this, 'access', _98 => _98.device, 'access', _99 => _99.destroy, 'optionalCall', _100 => _100()]);
3165
+ _optionalChain([this, 'access', _104 => _104.device, 'access', _105 => _105.destroy, 'optionalCall', _106 => _106()]);
3108
3166
  this.device = null;
3109
3167
  }
3110
3168
  }
@@ -3227,6 +3285,26 @@ var Scene = (_class7 = class _Scene {
3227
3285
  get overlayRootEntity() {
3228
3286
  return this.overlayRoot;
3229
3287
  }
3288
+ /**
3289
+ * Advance and render exactly one frame, synchronously.
3290
+ *
3291
+ * This renders UNCONDITIONALLY: it consults neither {@link renderMode} nor
3292
+ * {@link dirty}, and it does not apply the `always`-mode idle auto-throttle.
3293
+ * That is deliberate — a deterministic driver (video export, a test, a
3294
+ * fixed-step benchmark) asks for a frame because it wants that frame, not a
3295
+ * scheduler opinion about whether it is needed.
3296
+ *
3297
+ * The consequence is a measurement footgun worth stating explicitly: a
3298
+ * benchmark that drives frames through `step()` CANNOT observe frame skipping,
3299
+ * so `always` and `onDemand` produce byte-identical draw counts through this
3300
+ * path. An investigation into whether `onDemand` skips redundant repaints once
3301
+ * concluded "it does not" on exactly that basis; on the real rAF loop the same
3302
+ * workload rendered ~1.0 frames per content change. To measure anything about
3303
+ * scheduling, use {@link start} and let `requestAnimationFrame` drive.
3304
+ *
3305
+ * @param dt Seconds to advance. Not clamped by `MAX_FRAME_DT` — the caller
3306
+ * chooses the step, since determinism is the point.
3307
+ */
3230
3308
  step(dt) {
3231
3309
  const time = this.lastTime + dt;
3232
3310
  this.lastTime = time;
@@ -3245,6 +3323,24 @@ var Scene = (_class7 = class _Scene {
3245
3323
  this.dirty = true;
3246
3324
  if (this._dirtyTracking && source) this.recordDirtyReason(source);
3247
3325
  }
3326
+ /**
3327
+ * Increments whenever the tree's shape changes: add, remove or reparent.
3328
+ *
3329
+ * Already maintained for the resident WASM transform store (see
3330
+ * {@link markStructureChanged}, called from `Entity.add`/`remove`), and exposed
3331
+ * here because a cache of the tree's shape — a DevTools tree model, a serialized
3332
+ * snapshot — is valid exactly as long as this value is unchanged. Comparing it is
3333
+ * O(1) against re-walking the tree, which is what it replaces: DevTools rebuilt
3334
+ * both trees on a fixed 500 ms interval, a constant cost proportional to entity
3335
+ * count, purely because it had no way to ask whether the shape had changed.
3336
+ *
3337
+ * Property changes do NOT bump it. Moving or restyling an entity leaves the
3338
+ * shape intact, so a consumer that also cares about values must read those
3339
+ * directly rather than rebuilding a tree.
3340
+ */
3341
+ get structureVersion() {
3342
+ return this._structureVersion;
3343
+ }
3248
3344
  /**
3249
3345
  * Record who marked the scene dirty and why.
3250
3346
  *
@@ -3371,6 +3467,7 @@ var Scene = (_class7 = class _Scene {
3371
3467
  this.pruneA11ySubtree(node);
3372
3468
  return;
3373
3469
  }
3470
+ const nodeStart = this._phaseTiming ? performance.now() : 0;
3374
3471
  if (this.shouldProjectA11y(node)) {
3375
3472
  let el = this.a11yElements.get(node.id);
3376
3473
  const attrs = node.getA11yAttributes();
@@ -3412,20 +3509,20 @@ var Scene = (_class7 = class _Scene {
3412
3509
  el.style.background = "transparent";
3413
3510
  }
3414
3511
  el.addEventListener("click", (e) => {
3415
- node.dispatchEvent(new (0, _chunkYLH7F4ZVjs.VectoJSEvent)("click", node, e));
3512
+ node.dispatchEvent(new (0, _chunkAGP4VLF4js.VectoJSEvent)("click", node, e));
3416
3513
  });
3417
3514
  el.addEventListener("dblclick", (e) => {
3418
- node.dispatchEvent(new (0, _chunkYLH7F4ZVjs.VectoJSEvent)("dblclick", node, e));
3515
+ node.dispatchEvent(new (0, _chunkAGP4VLF4js.VectoJSEvent)("dblclick", node, e));
3419
3516
  });
3420
3517
  el.addEventListener("mouseenter", (e) => {
3421
3518
  if (this.debugA11y) el.style.backgroundColor = "rgba(56, 189, 248, 0.2)";
3422
3519
  this.hoveredA11yElements.add(el);
3423
- node.dispatchEvent(new (0, _chunkYLH7F4ZVjs.VectoJSEvent)("hover", node, e, false));
3520
+ node.dispatchEvent(new (0, _chunkAGP4VLF4js.VectoJSEvent)("hover", node, e, false));
3424
3521
  });
3425
3522
  el.addEventListener("mouseleave", (e) => {
3426
3523
  if (this.debugA11y) el.style.backgroundColor = "rgba(56, 189, 248, 0.05)";
3427
3524
  this.hoveredA11yElements.delete(el);
3428
- node.dispatchEvent(new (0, _chunkYLH7F4ZVjs.VectoJSEvent)("pointerleave", node, e, false));
3525
+ node.dispatchEvent(new (0, _chunkAGP4VLF4js.VectoJSEvent)("pointerleave", node, e, false));
3429
3526
  });
3430
3527
  const capEl = el;
3431
3528
  const releasePointer = (event) => {
@@ -3441,32 +3538,32 @@ var Scene = (_class7 = class _Scene {
3441
3538
  };
3442
3539
  el.addEventListener("pointerdown", (e) => {
3443
3540
  if (typeof capEl.setPointerCapture === "function") capEl.setPointerCapture(e.pointerId);
3444
- node.dispatchEvent(new (0, _chunkYLH7F4ZVjs.VectoJSEvent)("pointerdown", node, e));
3541
+ node.dispatchEvent(new (0, _chunkAGP4VLF4js.VectoJSEvent)("pointerdown", node, e));
3445
3542
  });
3446
3543
  el.addEventListener("pointerup", (e) => {
3447
3544
  releasePointer(e);
3448
- node.dispatchEvent(new (0, _chunkYLH7F4ZVjs.VectoJSEvent)("pointerup", node, e));
3545
+ node.dispatchEvent(new (0, _chunkAGP4VLF4js.VectoJSEvent)("pointerup", node, e));
3449
3546
  });
3450
3547
  el.addEventListener("pointercancel", (e) => {
3451
3548
  releasePointer(e);
3452
- node.dispatchEvent(new (0, _chunkYLH7F4ZVjs.VectoJSEvent)("pointercancel", node, e));
3549
+ node.dispatchEvent(new (0, _chunkAGP4VLF4js.VectoJSEvent)("pointercancel", node, e));
3453
3550
  });
3454
3551
  el.addEventListener(
3455
3552
  "pointermove",
3456
- (e) => node.dispatchEvent(new (0, _chunkYLH7F4ZVjs.VectoJSEvent)("pointermove", node, e))
3553
+ (e) => node.dispatchEvent(new (0, _chunkAGP4VLF4js.VectoJSEvent)("pointermove", node, e))
3457
3554
  );
3458
3555
  el.addEventListener(
3459
3556
  "wheel",
3460
3557
  (e) => {
3461
- node.dispatchEvent(new (0, _chunkYLH7F4ZVjs.VectoJSEvent)("wheel", node, e));
3558
+ node.dispatchEvent(new (0, _chunkAGP4VLF4js.VectoJSEvent)("wheel", node, e));
3462
3559
  },
3463
3560
  { passive: false }
3464
3561
  );
3465
3562
  el.addEventListener("keydown", (e) => {
3466
- node.dispatchEvent(new (0, _chunkYLH7F4ZVjs.VectoJSEvent)("keydown", node, e));
3563
+ node.dispatchEvent(new (0, _chunkAGP4VLF4js.VectoJSEvent)("keydown", node, e));
3467
3564
  });
3468
3565
  el.addEventListener("keyup", (e) => {
3469
- node.dispatchEvent(new (0, _chunkYLH7F4ZVjs.VectoJSEvent)("keyup", node, e));
3566
+ node.dispatchEvent(new (0, _chunkAGP4VLF4js.VectoJSEvent)("keyup", node, e));
3470
3567
  });
3471
3568
  if (el instanceof HTMLInputElement || el instanceof HTMLTextAreaElement) {
3472
3569
  const input = el;
@@ -3497,7 +3594,7 @@ var Scene = (_class7 = class _Scene {
3497
3594
  el.addEventListener("compositionupdate", (e) => {
3498
3595
  const data = _nullishCoalesce(e.data, () => ( ""));
3499
3596
  composition = {
3500
- start: _nullishCoalesce(_optionalChain([composition, 'optionalAccess', _101 => _101.start]), () => ( 0)),
3597
+ start: _nullishCoalesce(_optionalChain([composition, 'optionalAccess', _107 => _107.start]), () => ( 0)),
3501
3598
  length: data.length
3502
3599
  };
3503
3600
  forward();
@@ -3532,7 +3629,7 @@ var Scene = (_class7 = class _Scene {
3532
3629
  el.addEventListener("keydown", (e) => {
3533
3630
  if (e.key === "Enter" || e.key === " ") {
3534
3631
  e.preventDefault();
3535
- node.dispatchEvent(new (0, _chunkYLH7F4ZVjs.VectoJSEvent)("click", node, e));
3632
+ node.dispatchEvent(new (0, _chunkAGP4VLF4js.VectoJSEvent)("click", node, e));
3536
3633
  }
3537
3634
  });
3538
3635
  }
@@ -3570,7 +3667,7 @@ var Scene = (_class7 = class _Scene {
3570
3667
  this.syncOptionalAttribute(
3571
3668
  el,
3572
3669
  "href",
3573
- attrs.href === void 0 ? void 0 : _chunkL4SWVP2Hjs.sanitizeUrl.call(void 0, attrs.href)
3670
+ attrs.href === void 0 ? void 0 : _chunkGKSCJ6AFjs.sanitizeUrl.call(void 0, attrs.href)
3574
3671
  );
3575
3672
  this.syncOptionalAttribute(el, "target", attrs.target);
3576
3673
  }
@@ -3713,7 +3810,14 @@ var Scene = (_class7 = class _Scene {
3713
3810
  if (el.style.display !== display) el.style.display = display;
3714
3811
  }
3715
3812
  }
3716
- this.syncContentProjection(node);
3813
+ if (this._phaseTiming) {
3814
+ const projectionStart = performance.now();
3815
+ this.syncContentProjection(node);
3816
+ this._recordPhase("contentProjection", performance.now() - projectionStart);
3817
+ this._recordPhase("a11yNodes", projectionStart - nodeStart);
3818
+ } else {
3819
+ this.syncContentProjection(node);
3820
+ }
3717
3821
  for (const child of node.children) this.syncA11y(child);
3718
3822
  if (node === this.root) {
3719
3823
  for (const overlay of this.overlayRoot.children) this.syncA11y(overlay);
@@ -3814,7 +3918,7 @@ var Scene = (_class7 = class _Scene {
3814
3918
  el.addEventListener(
3815
3919
  "wheel",
3816
3920
  (e2) => {
3817
- node.dispatchEvent(new (0, _chunkYLH7F4ZVjs.VectoJSEvent)("wheel", node, e2));
3921
+ node.dispatchEvent(new (0, _chunkAGP4VLF4js.VectoJSEvent)("wheel", node, e2));
3818
3922
  },
3819
3923
  { passive: false }
3820
3924
  );
@@ -3827,7 +3931,9 @@ var Scene = (_class7 = class _Scene {
3827
3931
  this.clearContentGridState(node.id, el);
3828
3932
  }
3829
3933
  if (projection.grid) {
3934
+ const gridSyncStart = this._phaseTiming ? performance.now() : 0;
3830
3935
  this.syncContentGridProjection(node, el, projection, projection.grid);
3936
+ if (this._phaseTiming) this._recordPhase("gridSync", performance.now() - gridSyncStart);
3831
3937
  } else if (lines && lines.length > 0) {
3832
3938
  const signature = JSON.stringify({
3833
3939
  lines,
@@ -3933,21 +4039,38 @@ var Scene = (_class7 = class _Scene {
3933
4039
  const signature = `${grid.revision}`;
3934
4040
  if (el.dataset.vectoContentGrid !== signature) {
3935
4041
  const materializeStart = typeof performance !== "undefined" ? performance.now() : 0;
3936
- this.clearContentGridState(node.id, el);
3937
- el.replaceChildren();
4042
+ this.clearContentGridState(node.id, el, false);
3938
4043
  const projectionLines = _nullishCoalesce(projection.lines, () => ( []));
4044
+ const selectionLine = this.contentGridSelectionLine(el);
4045
+ let rebuiltSelectionLine = false;
4046
+ const existingLines = el.children;
3939
4047
  for (let lineIndex = 0; lineIndex < grid.lines.length; lineIndex++) {
3940
4048
  const gridLine = grid.lines[lineIndex];
3941
4049
  const projectedLine = projectionLines[lineIndex];
3942
- const lineHeight = _nullishCoalesce(_optionalChain([projectedLine, 'optionalAccess', _102 => _102.lineHeight]), () => ( grid.lineHeight));
3943
- const baseline = _nullishCoalesce(_optionalChain([projectedLine, 'optionalAccess', _103 => _103.baseline]), () => ( grid.baseline));
3944
- const lineFont = _nullishCoalesce(_optionalChain([projectedLine, 'optionalAccess', _104 => _104.font]), () => ( grid.font));
4050
+ const lineHeight = _nullishCoalesce(_optionalChain([projectedLine, 'optionalAccess', _108 => _108.lineHeight]), () => ( grid.lineHeight));
4051
+ const baseline = _nullishCoalesce(_optionalChain([projectedLine, 'optionalAccess', _109 => _109.baseline]), () => ( grid.baseline));
4052
+ const lineFont = _nullishCoalesce(_optionalChain([projectedLine, 'optionalAccess', _110 => _110.font]), () => ( grid.font));
4053
+ const lineSignature = contentGridLineSignature(
4054
+ grid,
4055
+ gridLine,
4056
+ projectedLine,
4057
+ lineHeight,
4058
+ baseline,
4059
+ lineFont,
4060
+ lineIndex === 0
4061
+ );
4062
+ const reusable = existingLines[lineIndex];
4063
+ if (reusable !== void 0 && reusable.dataset.vectoGridLineSig === lineSignature && reusable.dataset.vectoGridLine === `${lineIndex}`) {
4064
+ continue;
4065
+ }
4066
+ if (selectionLine !== null && selectionLine === lineIndex) rebuiltSelectionLine = true;
3945
4067
  const lineElement = document.createElement("span");
4068
+ lineElement.dataset.vectoGridLineSig = lineSignature;
3946
4069
  lineElement.dir = "ltr";
3947
4070
  lineElement.dataset.vectoGridLine = `${lineIndex}`;
3948
4071
  lineElement.style.position = "absolute";
3949
- lineElement.style.left = `${_nullishCoalesce(_optionalChain([projectedLine, 'optionalAccess', _105 => _105.x]), () => ( 0))}px`;
3950
- lineElement.style.top = `${(_nullishCoalesce(_optionalChain([projectedLine, 'optionalAccess', _106 => _106.y]), () => ( lineIndex * grid.lineHeight))) + baseline - _text.cssLineBoxBaseline.call(void 0, lineFont, lineHeight)}px`;
4072
+ lineElement.style.left = `${_nullishCoalesce(_optionalChain([projectedLine, 'optionalAccess', _111 => _111.x]), () => ( 0))}px`;
4073
+ lineElement.style.top = `${(_nullishCoalesce(_optionalChain([projectedLine, 'optionalAccess', _112 => _112.y]), () => ( lineIndex * grid.lineHeight))) + baseline - _text.cssLineBoxBaseline.call(void 0, lineFont, lineHeight)}px`;
3951
4074
  lineElement.style.width = `${gridLine.width}px`;
3952
4075
  lineElement.style.height = `${lineHeight}px`;
3953
4076
  lineElement.style.whiteSpace = "pre";
@@ -3984,6 +4107,8 @@ var Scene = (_class7 = class _Scene {
3984
4107
  cellElement.style.font = lineFont;
3985
4108
  cellElement.style.lineHeight = `${lineHeight}px`;
3986
4109
  cellElement.style.transformOrigin = "0 50%";
4110
+ cellElement.dataset.vectoGridFont = lineFont;
4111
+ cellElement.dataset.vectoGridLineHeight = `${lineHeight}px`;
3987
4112
  lineElement.appendChild(cellElement);
3988
4113
  logicalX += cell.advance;
3989
4114
  }
@@ -4007,13 +4132,24 @@ var Scene = (_class7 = class _Scene {
4007
4132
  lineElement.appendChild(marker);
4008
4133
  }
4009
4134
  }
4010
- el.appendChild(lineElement);
4135
+ const occupant = el.children[lineIndex];
4136
+ if (occupant) el.replaceChild(lineElement, occupant);
4137
+ else el.appendChild(lineElement);
4011
4138
  }
4139
+ while (el.children.length > grid.lines.length) {
4140
+ if (selectionLine !== null && selectionLine >= grid.lines.length) {
4141
+ rebuiltSelectionLine = true;
4142
+ }
4143
+ _optionalChain([el, 'access', _113 => _113.lastElementChild, 'optionalAccess', _114 => _114.remove, 'call', _115 => _115()]);
4144
+ }
4145
+ if (rebuiltSelectionLine) this.releaseContentSelectionForRebuild(el);
4012
4146
  el.dataset.vectoProjectionLines = signature;
4013
4147
  el.dataset.vectoContentGrid = signature;
4014
4148
  el.dataset.vectoGridCarriers = `${el.querySelectorAll("[data-vecto-grid-cell]").length}`;
4015
4149
  if (typeof performance !== "undefined") {
4016
- el.dataset.vectoGridMaterializeMs = `${performance.now() - materializeStart}`;
4150
+ const materializeMs = performance.now() - materializeStart;
4151
+ el.dataset.vectoGridMaterializeMs = `${materializeMs}`;
4152
+ if (this._phaseTiming) this._recordPhase("gridMaterialize", materializeMs);
4017
4153
  }
4018
4154
  delete el.dataset.vectoGridCalibration;
4019
4155
  delete el.dataset.vectoGridReady;
@@ -4021,7 +4157,11 @@ var Scene = (_class7 = class _Scene {
4021
4157
  const pageScaleX = this.getContentMetricScaleX();
4022
4158
  const calibrationKey = `${signature}:${this.contentFontEpoch}:${pageScaleX.toFixed(4)}`;
4023
4159
  if (el.dataset.vectoGridCalibration !== calibrationKey) {
4160
+ const calibStart = this._phaseTiming ? performance.now() : 0;
4024
4161
  this.scheduleContentGridCalibration(node.id, el, calibrationKey, pageScaleX);
4162
+ if (this._phaseTiming) {
4163
+ this._recordPhase("gridCalibrateSchedule", performance.now() - calibStart);
4164
+ }
4025
4165
  }
4026
4166
  }
4027
4167
  getContentMetricScaleX() {
@@ -4039,11 +4179,32 @@ var Scene = (_class7 = class _Scene {
4039
4179
  scheduleContentGridCalibration(entityId, el, calibrationKey, pageScaleX) {
4040
4180
  if (typeof requestAnimationFrame !== "function") return;
4041
4181
  if (el.dataset.vectoGridCalibrationPending === calibrationKey) return;
4182
+ const stamp = `${this.contentFontEpoch}:${pageScaleX.toFixed(4)}`;
4183
+ if (this.contentGridCalibrationStamp !== stamp) {
4184
+ this.contentGridCalibrationStamp = stamp;
4185
+ this.contentGridCalibrationGeneration++;
4186
+ }
4187
+ const generation = `${this.contentGridCalibrationGeneration}`;
4188
+ const pendingCells = el.querySelectorAll(
4189
+ `[data-vecto-grid-cell]:not([data-vecto-grid-calib="${generation}"])`
4190
+ );
4191
+ if (pendingCells.length === 0) {
4192
+ el.dataset.vectoGridCalibrationSamples = "0";
4193
+ delete el.dataset.vectoGridCalibrationPending;
4194
+ const readyFrame = requestAnimationFrame(() => {
4195
+ this.contentGridCalibrationFrames.delete(entityId);
4196
+ if (!el.isConnected) return;
4197
+ el.dataset.vectoGridCalibration = calibrationKey;
4198
+ el.dataset.vectoGridReady = "true";
4199
+ });
4200
+ this.contentGridCalibrationFrames.set(entityId, readyFrame);
4201
+ return;
4202
+ }
4042
4203
  const previous = this.contentGridCalibrationFrames.get(entityId);
4043
4204
  if (previous !== void 0 && typeof cancelAnimationFrame === "function") {
4044
4205
  cancelAnimationFrame(previous);
4045
4206
  }
4046
- _optionalChain([this, 'access', _107 => _107.contentGridCalibrationProbes, 'access', _108 => _108.get, 'call', _109 => _109(entityId), 'optionalAccess', _110 => _110.remove, 'call', _111 => _111()]);
4207
+ _optionalChain([this, 'access', _116 => _116.contentGridCalibrationProbes, 'access', _117 => _117.get, 'call', _118 => _118(entityId), 'optionalAccess', _119 => _119.remove, 'call', _120 => _120()]);
4047
4208
  this.contentGridCalibrationProbes.delete(entityId);
4048
4209
  const calibrationStart = typeof performance !== "undefined" ? performance.now() : 0;
4049
4210
  const probe = document.createElement("div");
@@ -4069,18 +4230,22 @@ var Scene = (_class7 = class _Scene {
4069
4230
  probe.append(probeOrigin, probeX);
4070
4231
  const measurements = [];
4071
4232
  const measurementsByKey = /* @__PURE__ */ new Map();
4072
- for (const target of el.querySelectorAll("[data-vecto-grid-cell]")) {
4233
+ const scanStart = this._phaseTiming ? performance.now() : 0;
4234
+ for (const target of pendingCells) {
4073
4235
  const sourceLength = Number(_nullishCoalesce(target.dataset.vectoGridSourceLength, () => ( 0)));
4074
4236
  const targetWidth = Number(_nullishCoalesce(target.dataset.vectoGridAdvance, () => ( 0)));
4075
- if (sourceLength <= 0 || targetWidth <= 0) continue;
4076
- const sourceText = _nullishCoalesce(_optionalChain([target, 'access', _112 => _112.textContent, 'optionalAccess', _113 => _113.slice, 'call', _114 => _114(0, sourceLength)]), () => ( ""));
4077
- if (!sourceText) continue;
4078
- const measurementKey = JSON.stringify([
4079
- target.style.font,
4080
- target.style.lineHeight,
4081
- targetWidth,
4082
- sourceText
4083
- ]);
4237
+ if (sourceLength <= 0 || targetWidth <= 0) {
4238
+ target.dataset.vectoGridCalib = generation;
4239
+ continue;
4240
+ }
4241
+ const sourceText = _nullishCoalesce(_optionalChain([target, 'access', _121 => _121.textContent, 'optionalAccess', _122 => _122.slice, 'call', _123 => _123(0, sourceLength)]), () => ( ""));
4242
+ if (!sourceText) {
4243
+ target.dataset.vectoGridCalib = generation;
4244
+ continue;
4245
+ }
4246
+ const cellFont = _nullishCoalesce(target.dataset.vectoGridFont, () => ( ""));
4247
+ const cellLineHeight = _nullishCoalesce(target.dataset.vectoGridLineHeight, () => ( ""));
4248
+ const measurementKey = JSON.stringify([cellFont, cellLineHeight, targetWidth, sourceText]);
4084
4249
  const shared = measurementsByKey.get(measurementKey);
4085
4250
  if (shared) {
4086
4251
  shared.targets.push(target);
@@ -4092,8 +4257,8 @@ var Scene = (_class7 = class _Scene {
4092
4257
  carrier.style.left = "0";
4093
4258
  carrier.style.top = "0";
4094
4259
  carrier.style.whiteSpace = "pre";
4095
- carrier.style.font = target.style.font;
4096
- carrier.style.lineHeight = target.style.lineHeight;
4260
+ carrier.style.font = cellFont;
4261
+ carrier.style.lineHeight = cellLineHeight;
4097
4262
  carrier.style.fontVariantLigatures = "none";
4098
4263
  carrier.style.fontKerning = "none";
4099
4264
  const source = document.createTextNode(sourceText);
@@ -4108,7 +4273,17 @@ var Scene = (_class7 = class _Scene {
4108
4273
  measurements.push(measurement);
4109
4274
  measurementsByKey.set(measurementKey, measurement);
4110
4275
  }
4276
+ if (this._phaseTiming) this._recordPhase("calibScan", performance.now() - scanStart);
4277
+ if (measurements.length === 0) {
4278
+ el.dataset.vectoGridCalibration = calibrationKey;
4279
+ el.dataset.vectoGridReady = "true";
4280
+ el.dataset.vectoGridCalibrationSamples = "0";
4281
+ delete el.dataset.vectoGridCalibrationPending;
4282
+ return;
4283
+ }
4284
+ const appendStart = this._phaseTiming ? performance.now() : 0;
4111
4285
  (_nullishCoalesce(_nullishCoalesce(this.a11yRoot, () => ( document.body)), () => ( document.documentElement))).appendChild(probe);
4286
+ if (this._phaseTiming) this._recordPhase("calibProbeBuild", performance.now() - appendStart);
4112
4287
  el.dataset.vectoGridCalibrationSamples = `${measurements.length}`;
4113
4288
  this.contentGridCalibrationProbes.set(entityId, probe);
4114
4289
  el.dataset.vectoGridCalibrationPending = calibrationKey;
@@ -4152,6 +4327,7 @@ var Scene = (_class7 = class _Scene {
4152
4327
  }
4153
4328
  for (const { element, scale } of updates) {
4154
4329
  element.style.transform = Math.abs(scale - 1) <= 1e-3 ? "" : `scaleX(${scale})`;
4330
+ element.dataset.vectoGridCalib = generation;
4155
4331
  }
4156
4332
  el.dataset.vectoGridCalibration = calibrationKey;
4157
4333
  el.dataset.vectoGridReady = "true";
@@ -4273,12 +4449,12 @@ var Scene = (_class7 = class _Scene {
4273
4449
  syncOverlayGeometry() {
4274
4450
  const parent = this.canvas.parentElement;
4275
4451
  if (!parent) return;
4276
- const canvasRect = _optionalChain([this, 'access', _115 => _115.canvas, 'access', _116 => _116.getBoundingClientRect, 'optionalCall', _117 => _117()]);
4277
- const parentRect = _optionalChain([parent, 'access', _118 => _118.getBoundingClientRect, 'optionalCall', _119 => _119()]);
4278
- const cssWidth = _optionalChain([canvasRect, 'optionalAccess', _120 => _120.width]) || this.canvas.clientWidth || this.width;
4279
- const cssHeight = _optionalChain([canvasRect, 'optionalAccess', _121 => _121.height]) || this.canvas.clientHeight || this.height;
4280
- const left = (_nullishCoalesce(_optionalChain([canvasRect, 'optionalAccess', _122 => _122.left]), () => ( 0))) - (_nullishCoalesce(_optionalChain([parentRect, 'optionalAccess', _123 => _123.left]), () => ( 0))) - (parent.clientLeft || 0) + parent.scrollLeft;
4281
- const top = (_nullishCoalesce(_optionalChain([canvasRect, 'optionalAccess', _124 => _124.top]), () => ( 0))) - (_nullishCoalesce(_optionalChain([parentRect, 'optionalAccess', _125 => _125.top]), () => ( 0))) - (parent.clientTop || 0) + parent.scrollTop;
4452
+ const canvasRect = _optionalChain([this, 'access', _124 => _124.canvas, 'access', _125 => _125.getBoundingClientRect, 'optionalCall', _126 => _126()]);
4453
+ const parentRect = _optionalChain([parent, 'access', _127 => _127.getBoundingClientRect, 'optionalCall', _128 => _128()]);
4454
+ const cssWidth = _optionalChain([canvasRect, 'optionalAccess', _129 => _129.width]) || this.canvas.clientWidth || this.width;
4455
+ const cssHeight = _optionalChain([canvasRect, 'optionalAccess', _130 => _130.height]) || this.canvas.clientHeight || this.height;
4456
+ const left = (_nullishCoalesce(_optionalChain([canvasRect, 'optionalAccess', _131 => _131.left]), () => ( 0))) - (_nullishCoalesce(_optionalChain([parentRect, 'optionalAccess', _132 => _132.left]), () => ( 0))) - (parent.clientLeft || 0) + parent.scrollLeft;
4457
+ const top = (_nullishCoalesce(_optionalChain([canvasRect, 'optionalAccess', _133 => _133.top]), () => ( 0))) - (_nullishCoalesce(_optionalChain([parentRect, 'optionalAccess', _134 => _134.top]), () => ( 0))) - (parent.clientTop || 0) + parent.scrollTop;
4282
4458
  const scaleX = this.width > 0 ? cssWidth / this.width : 1;
4283
4459
  const scaleY = this.height > 0 ? cssHeight / this.height : 1;
4284
4460
  const prev = this._overlayGeometry;
@@ -4417,7 +4593,7 @@ var Scene = (_class7 = class _Scene {
4417
4593
  * (and {@link respectReducedMotion} is on). `0` means uncapped.
4418
4594
  */
4419
4595
  effectiveMaxFPS() {
4420
- const reduced = this.respectReducedMotion && !!_optionalChain([this, 'access', _126 => _126.reducedMotionQuery, 'optionalAccess', _127 => _127.matches]);
4596
+ const reduced = this.respectReducedMotion && !!_optionalChain([this, 'access', _135 => _135.reducedMotionQuery, 'optionalAccess', _136 => _136.matches]);
4421
4597
  if (reduced)
4422
4598
  return this.maxFPS > 0 ? Math.min(this.maxFPS, REDUCED_MOTION_FPS) : REDUCED_MOTION_FPS;
4423
4599
  return this.maxFPS;
@@ -4490,7 +4666,7 @@ var Scene = (_class7 = class _Scene {
4490
4666
  * @param time - Current absolute time in milliseconds (default 0).
4491
4667
  */
4492
4668
  render(renderer, dt = 0, time = 0) {
4493
- if (_optionalChain([renderer, 'access', _128 => _128.isContextLost, 'optionalCall', _129 => _129()])) return;
4669
+ if (_optionalChain([renderer, 'access', _137 => _137.isContextLost, 'optionalCall', _138 => _138()])) return;
4494
4670
  const isMainRenderer = renderer === this.renderer;
4495
4671
  if (isMainRenderer && this.a11yRoot && this.canvas.parentElement) {
4496
4672
  const parentStyle = this.canvas.parentElement.style;
@@ -4616,14 +4792,14 @@ var Scene = (_class7 = class _Scene {
4616
4792
  }
4617
4793
  renderer.clear();
4618
4794
  if (isMainRenderer) {
4619
- _optionalChain([this, 'access', _130 => _130.pointRenderer, 'optionalAccess', _131 => _131.begin, 'call', _132 => _132()]);
4795
+ _optionalChain([this, 'access', _139 => _139.pointRenderer, 'optionalAccess', _140 => _140.begin, 'call', _141 => _141()]);
4620
4796
  }
4621
4797
  const vw = this.width;
4622
4798
  const vh = this.height;
4623
4799
  let walkHadAnimation = false;
4624
4800
  let walkHadInteractive = false;
4625
4801
  const runUpdate = (node) => {
4626
- const overridesUpdate = node.update !== _chunkYLH7F4ZVjs.Entity.prototype.update;
4802
+ const overridesUpdate = node.update !== _chunkAGP4VLF4js.Entity.prototype.update;
4627
4803
  let pending = node.hasPendingAnimations();
4628
4804
  if (pending || overridesUpdate) {
4629
4805
  node.update(dt, time);
@@ -4632,7 +4808,7 @@ var Scene = (_class7 = class _Scene {
4632
4808
  if (pending) walkHadAnimation = true;
4633
4809
  if (!walkHadInteractive && node.interactive) walkHadInteractive = true;
4634
4810
  if (this._devActive && this._devFrameCount % 120 === 0) {
4635
- if (overridesUpdate && node.hasPendingAnimations === _chunkYLH7F4ZVjs.Entity.prototype.hasPendingAnimations) {
4811
+ if (overridesUpdate && node.hasPendingAnimations === _chunkAGP4VLF4js.Entity.prototype.hasPendingAnimations) {
4636
4812
  this._devWarn(
4637
4813
  `Entity "${node.id}" overrides update() but not hasPendingAnimations(). Custom motion in update() without overriding hasPendingAnimations() causes the idle throttle to drop the animation to ~2fps. Override hasPendingAnimations() to return true while motion is in flight.`
4638
4814
  );
@@ -4813,9 +4989,9 @@ var Scene = (_class7 = class _Scene {
4813
4989
  const flushT0 = this._phaseTiming ? performance.now() : 0;
4814
4990
  renderer.flush();
4815
4991
  if (isMainRenderer) {
4816
- _optionalChain([this, 'access', _133 => _133.pointRenderer, 'optionalAccess', _134 => _134.flush, 'call', _135 => _135()]);
4992
+ _optionalChain([this, 'access', _142 => _142.pointRenderer, 'optionalAccess', _143 => _143.flush, 'call', _144 => _144()]);
4817
4993
  }
4818
- _optionalChain([renderer, 'access', _136 => _136.present, 'optionalCall', _137 => _137()]);
4994
+ _optionalChain([renderer, 'access', _145 => _145.present, 'optionalCall', _146 => _146()]);
4819
4995
  if (this._phaseTiming) this._recordPhase("flush", performance.now() - flushT0);
4820
4996
  if (this._devActive) {
4821
4997
  this._devFrameCount++;
@@ -4826,7 +5002,7 @@ var Scene = (_class7 = class _Scene {
4826
5002
  * Export the current scene state to a lightweight, flat SVG XML string.
4827
5003
  */
4828
5004
  toSVG() {
4829
- const renderer = new (0, _chunkL4SWVP2Hjs.SVGRenderer)(this.width, this.height);
5005
+ const renderer = new (0, _chunkGKSCJ6AFjs.SVGRenderer)(this.width, this.height);
4830
5006
  this.render(renderer, 0, 0);
4831
5007
  return renderer.toXMLString();
4832
5008
  }
@@ -5092,6 +5268,41 @@ function intersectBounds(a, b) {
5092
5268
  function pointInBounds(b, x, y) {
5093
5269
  return x >= b.x && x <= b.x + b.width && y >= b.y && y <= b.y + b.height;
5094
5270
  }
5271
+ function contentGridLineSignature(grid, line, projected, lineHeight, baseline, font, isFirstLine) {
5272
+ const parts = [
5273
+ // Line box: position, size, and the font that resolves its baseline.
5274
+ `${_nullishCoalesce(_optionalChain([projected, 'optionalAccess', _147 => _147.x]), () => ( 0))}`,
5275
+ `${_nullishCoalesce(_optionalChain([projected, 'optionalAccess', _148 => _148.y]), () => ( ""))}`,
5276
+ `${lineHeight}`,
5277
+ `${baseline}`,
5278
+ font,
5279
+ `${line.width}`,
5280
+ // The trailing hard break belongs to this line and lands in the DOM text.
5281
+ grid.source.slice(line.sourceEnd, line.nextSourceStart),
5282
+ // The basis markers are appended only to line 0, so a line moving to or from
5283
+ // index 0 changes its DOM even when nothing else does.
5284
+ isFirstLine ? "1" : "0"
5285
+ ];
5286
+ if (line.cells.length === 0) {
5287
+ parts.push("empty");
5288
+ } else {
5289
+ for (const cell of line.cells) {
5290
+ parts.push(
5291
+ `${cell.sourceStart}`,
5292
+ `${cell.sourceEnd}`,
5293
+ `${cell.x}`,
5294
+ `${cell.advance}`,
5295
+ `${cell.level}`,
5296
+ cell.sourceCaretOffsets.join("."),
5297
+ // Source text, not `cell.glyph`: the carrier holds the original characters
5298
+ // (the shaped glyph is the canvas's business), so a change in shaping alone
5299
+ // must not invalidate a carrier, and a change in source must.
5300
+ grid.source.slice(cell.sourceStart, cell.sourceEnd)
5301
+ );
5302
+ }
5303
+ }
5304
+ return parts.join("");
5305
+ }
5095
5306
 
5096
5307
  // src/components/TextEntity.ts
5097
5308
 
@@ -5103,20 +5314,20 @@ function defaultMeasurer() {
5103
5314
  if (sharedMeasurer === void 0) sharedMeasurer = _layout.createCanvasMeasurer.call(void 0, "sans-serif");
5104
5315
  return sharedMeasurer;
5105
5316
  }
5106
- var TextEntity = (_class8 = class extends _chunkYLH7F4ZVjs.Entity {
5317
+ var TextEntity = (_class8 = class extends _chunkAGP4VLF4js.Entity {
5107
5318
 
5108
5319
 
5109
5320
 
5110
5321
 
5111
- __init138() {this.nodes = []}
5322
+ __init140() {this.nodes = []}
5112
5323
 
5113
- __init139() {this.fillStyle = "#94a3b8"}
5114
- __init140() {this.strokeStyle = null}
5115
- __init141() {this.hoveredFillStyle = "#ffffff"}
5116
- __init142() {this.lineWidth = 1}
5117
- __init143() {this.isHovered = false}
5324
+ __init141() {this.fillStyle = "#94a3b8"}
5325
+ __init142() {this.strokeStyle = null}
5326
+ __init143() {this.hoveredFillStyle = "#ffffff"}
5327
+ __init144() {this.lineWidth = 1}
5328
+ __init145() {this.isHovered = false}
5118
5329
  constructor(text, atlas, maxWidth, fontSize = 24) {
5119
- super();_class8.prototype.__init138.call(this);_class8.prototype.__init139.call(this);_class8.prototype.__init140.call(this);_class8.prototype.__init141.call(this);_class8.prototype.__init142.call(this);_class8.prototype.__init143.call(this);;
5330
+ super();_class8.prototype.__init140.call(this);_class8.prototype.__init141.call(this);_class8.prototype.__init142.call(this);_class8.prototype.__init143.call(this);_class8.prototype.__init144.call(this);_class8.prototype.__init145.call(this);;
5120
5331
  this.text = text;
5121
5332
  this.atlas = atlas;
5122
5333
  this.fontSize = fontSize;
@@ -5229,17 +5440,17 @@ var TextEntity = (_class8 = class extends _chunkYLH7F4ZVjs.Entity {
5229
5440
  }, _class8);
5230
5441
 
5231
5442
  // src/components/GridTextEntity.ts
5232
- var GridTextEntity = (_class9 = class extends _chunkYLH7F4ZVjs.Entity {
5443
+ var GridTextEntity = (_class9 = class extends _chunkAGP4VLF4js.Entity {
5233
5444
 
5234
- __init144() {this.fillStyle = "#ffffff"}
5235
- __init145() {this.grid = []}
5445
+ __init146() {this.fillStyle = "#ffffff"}
5446
+ __init147() {this.grid = []}
5236
5447
  // Array of rows
5237
- __init146() {this.cols = 0}
5238
- __init147() {this.rows = 0}
5448
+ __init148() {this.cols = 0}
5449
+ __init149() {this.rows = 0}
5239
5450
 
5240
5451
 
5241
5452
  constructor(_atlas, fontSize = 10) {
5242
- super();_class9.prototype.__init144.call(this);_class9.prototype.__init145.call(this);_class9.prototype.__init146.call(this);_class9.prototype.__init147.call(this);;
5453
+ super();_class9.prototype.__init146.call(this);_class9.prototype.__init147.call(this);_class9.prototype.__init148.call(this);_class9.prototype.__init149.call(this);;
5243
5454
  this.fontSize = fontSize;
5244
5455
  this.charWidth = fontSize * 1;
5245
5456
  this.charHeight = fontSize * 1.1;
@@ -5248,7 +5459,7 @@ var GridTextEntity = (_class9 = class extends _chunkYLH7F4ZVjs.Entity {
5248
5459
  updateGrid(ascii) {
5249
5460
  this.grid = ascii;
5250
5461
  this.rows = ascii.length;
5251
- this.cols = _optionalChain([ascii, 'access', _138 => _138[0], 'optionalAccess', _139 => _139.length]) || 0;
5462
+ this.cols = _optionalChain([ascii, 'access', _149 => _149[0], 'optionalAccess', _150 => _150.length]) || 0;
5252
5463
  }
5253
5464
  isPointInside(_globalX, _globalY) {
5254
5465
  return false;
@@ -5323,7 +5534,7 @@ function distSqToSegment(px, py, x1, y1, x2, y2) {
5323
5534
  const ey = py - cy;
5324
5535
  return ex * ex + ey * ey;
5325
5536
  }
5326
- var SplineEntity = (_class10 = class extends _chunkYLH7F4ZVjs.Entity {
5537
+ var SplineEntity = (_class10 = class extends _chunkAGP4VLF4js.Entity {
5327
5538
 
5328
5539
 
5329
5540
 
@@ -5331,23 +5542,23 @@ var SplineEntity = (_class10 = class extends _chunkYLH7F4ZVjs.Entity {
5331
5542
 
5332
5543
 
5333
5544
 
5334
- __init148() {this.offscreen = null}
5335
- __init149() {this.baked = false}
5545
+ __init150() {this.offscreen = null}
5546
+ __init151() {this.baked = false}
5336
5547
  /** Logical (CSS-pixel) size of the baked bitmap — the blit destination size. */
5337
- __init150() {this.bakedWidth = 0}
5338
- __init151() {this.bakedHeight = 0}
5548
+ __init152() {this.bakedWidth = 0}
5549
+ __init153() {this.bakedHeight = 0}
5339
5550
  /** Gradient strokes can't be baked to a solid-color bitmap; they render per-frame. */
5340
5551
 
5341
5552
  /** Lazily-flattened polylines (one Float32Array of [x,y,...] per segment) for hit-testing. */
5342
- __init152() {this.polylines = null}
5553
+ __init154() {this.polylines = null}
5343
5554
  /**
5344
5555
  * When `true`, the renderer draws a rounded-rect outline of the entity's
5345
5556
  * local bounds after painting the curves. Useful for drag feedback and
5346
5557
  * debugging hit areas. Defaults to `false`.
5347
5558
  */
5348
- __init153() {this.showBounds = false}
5559
+ __init155() {this.showBounds = false}
5349
5560
  constructor(doc, opts = {}) {
5350
- super();_class10.prototype.__init148.call(this);_class10.prototype.__init149.call(this);_class10.prototype.__init150.call(this);_class10.prototype.__init151.call(this);_class10.prototype.__init152.call(this);_class10.prototype.__init153.call(this);;
5561
+ super();_class10.prototype.__init150.call(this);_class10.prototype.__init151.call(this);_class10.prototype.__init152.call(this);_class10.prototype.__init153.call(this);_class10.prototype.__init154.call(this);_class10.prototype.__init155.call(this);;
5351
5562
  this.doc = doc;
5352
5563
  this.lineWidth = _nullishCoalesce(opts.lineWidth, () => ( 2));
5353
5564
  this.cache = _nullishCoalesce(opts.cache, () => ( true));
@@ -5358,7 +5569,7 @@ var SplineEntity = (_class10 = class extends _chunkYLH7F4ZVjs.Entity {
5358
5569
  this.width = this.bounds.width;
5359
5570
  this.height = this.bounds.height;
5360
5571
  const isGradient = (c) => c !== null && !Array.isArray(c);
5361
- this.containsGradient = (_nullishCoalesce(_optionalChain([this, 'access', _140 => _140.doc, 'access', _141 => _141.equations, 'optionalAccess', _142 => _142.some, 'call', _143 => _143((eq) => isGradient(eq.color_rgb))]), () => ( false))) || (_nullishCoalesce(_optionalChain([this, 'access', _144 => _144.doc, 'access', _145 => _145.paths, 'optionalAccess', _146 => _146.some, 'call', _147 => _147((p) => isGradient(p.color_rgb))]), () => ( false)));
5572
+ this.containsGradient = (_nullishCoalesce(_optionalChain([this, 'access', _151 => _151.doc, 'access', _152 => _152.equations, 'optionalAccess', _153 => _153.some, 'call', _154 => _154((eq) => isGradient(eq.color_rgb))]), () => ( false))) || (_nullishCoalesce(_optionalChain([this, 'access', _155 => _155.doc, 'access', _156 => _156.paths, 'optionalAccess', _157 => _157.some, 'call', _158 => _158((p) => isGradient(p.color_rgb))]), () => ( false)));
5362
5573
  this.interactive = true;
5363
5574
  }
5364
5575
  computeBounds() {
@@ -5598,7 +5809,7 @@ async function loadSpline(url) {
5598
5809
  }
5599
5810
 
5600
5811
  // src/components/Rect.ts
5601
- var Rect = class extends _chunkYLH7F4ZVjs.Entity {
5812
+ var Rect = class extends _chunkAGP4VLF4js.Entity {
5602
5813
 
5603
5814
 
5604
5815
 
@@ -5647,7 +5858,7 @@ var Rect = class extends _chunkYLH7F4ZVjs.Entity {
5647
5858
  };
5648
5859
 
5649
5860
  // src/components/Circle.ts
5650
- var Circle = class extends _chunkYLH7F4ZVjs.Entity {
5861
+ var Circle = class extends _chunkAGP4VLF4js.Entity {
5651
5862
 
5652
5863
 
5653
5864
 
@@ -5707,7 +5918,7 @@ var Circle = class extends _chunkYLH7F4ZVjs.Entity {
5707
5918
  };
5708
5919
 
5709
5920
  // src/components/Group.ts
5710
- var Group = class extends _chunkYLH7F4ZVjs.Entity {
5921
+ var Group = class extends _chunkAGP4VLF4js.Entity {
5711
5922
  constructor(...children) {
5712
5923
  super();
5713
5924
  if (children.length > 0) this.add(...children);
@@ -5726,21 +5937,21 @@ var _math = require('@vectojs/math'); _createStarExport(_math);
5726
5937
 
5727
5938
 
5728
5939
  // src/tree/DOMPortalEntity.ts
5729
- var DOMPortalEntity = (_class11 = class extends _chunkYLH7F4ZVjs.Entity {
5940
+ var DOMPortalEntity = (_class11 = class extends _chunkAGP4VLF4js.Entity {
5730
5941
 
5731
- __init154() {this.isDOMPortal = true}
5732
- __init155() {this.domListeners = []}
5733
- __init156() {this.resizeObserver = null}
5734
- __init157() {this.domBound = false}
5735
- __init158() {this.cachedWidth = 100}
5736
- __init159() {this.cachedHeight = 100}
5737
- __init160() {this.lastWidth = ""}
5738
- __init161() {this.lastHeight = ""}
5739
- __init162() {this.lastTransform = ""}
5740
- __init163() {this.lastZIndex = ""}
5741
- __init164() {this.lastOpacity = ""}
5942
+ __init156() {this.isDOMPortal = true}
5943
+ __init157() {this.domListeners = []}
5944
+ __init158() {this.resizeObserver = null}
5945
+ __init159() {this.domBound = false}
5946
+ __init160() {this.cachedWidth = 100}
5947
+ __init161() {this.cachedHeight = 100}
5948
+ __init162() {this.lastWidth = ""}
5949
+ __init163() {this.lastHeight = ""}
5950
+ __init164() {this.lastTransform = ""}
5951
+ __init165() {this.lastZIndex = ""}
5952
+ __init166() {this.lastOpacity = ""}
5742
5953
  constructor(domElement, width, height, id) {
5743
- super(id);_class11.prototype.__init154.call(this);_class11.prototype.__init155.call(this);_class11.prototype.__init156.call(this);_class11.prototype.__init157.call(this);_class11.prototype.__init158.call(this);_class11.prototype.__init159.call(this);_class11.prototype.__init160.call(this);_class11.prototype.__init161.call(this);_class11.prototype.__init162.call(this);_class11.prototype.__init163.call(this);_class11.prototype.__init164.call(this);;
5954
+ super(id);_class11.prototype.__init156.call(this);_class11.prototype.__init157.call(this);_class11.prototype.__init158.call(this);_class11.prototype.__init159.call(this);_class11.prototype.__init160.call(this);_class11.prototype.__init161.call(this);_class11.prototype.__init162.call(this);_class11.prototype.__init163.call(this);_class11.prototype.__init164.call(this);_class11.prototype.__init165.call(this);_class11.prototype.__init166.call(this);;
5744
5955
  this.domElement = domElement;
5745
5956
  this.width = _nullishCoalesce(width, () => ( 0));
5746
5957
  this.height = _nullishCoalesce(height, () => ( 0));
@@ -5782,7 +5993,7 @@ var DOMPortalEntity = (_class11 = class extends _chunkYLH7F4ZVjs.Entity {
5782
5993
  ];
5783
5994
  for (const type of events) {
5784
5995
  const handler = (e) => {
5785
- this.dispatchEvent(new (0, _chunkYLH7F4ZVjs.VectoJSEvent)(type, this, e));
5996
+ this.dispatchEvent(new (0, _chunkAGP4VLF4js.VectoJSEvent)(type, this, e));
5786
5997
  };
5787
5998
  this.domElement.addEventListener(type, handler);
5788
5999
  this.domListeners.push({ type, handler, capture: false });
@@ -5793,7 +6004,7 @@ var DOMPortalEntity = (_class11 = class extends _chunkYLH7F4ZVjs.Entity {
5793
6004
  ];
5794
6005
  for (const { native, vecto } of hoverEvents) {
5795
6006
  const handler = (e) => {
5796
- this.dispatchEvent(new (0, _chunkYLH7F4ZVjs.VectoJSEvent)(vecto, this, e, false));
6007
+ this.dispatchEvent(new (0, _chunkAGP4VLF4js.VectoJSEvent)(vecto, this, e, false));
5797
6008
  };
5798
6009
  this.domElement.addEventListener(native, handler);
5799
6010
  this.domListeners.push({ type: native, handler, capture: false });
@@ -5801,7 +6012,7 @@ var DOMPortalEntity = (_class11 = class extends _chunkYLH7F4ZVjs.Entity {
5801
6012
  const focusEvents = ["focus", "blur"];
5802
6013
  for (const type of focusEvents) {
5803
6014
  const handler = (e) => {
5804
- this.dispatchEvent(new (0, _chunkYLH7F4ZVjs.VectoJSEvent)(type, this, e, true));
6015
+ this.dispatchEvent(new (0, _chunkAGP4VLF4js.VectoJSEvent)(type, this, e, true));
5805
6016
  };
5806
6017
  this.domElement.addEventListener(type, handler, true);
5807
6018
  this.domListeners.push({ type, handler, capture: true });
@@ -5852,8 +6063,9 @@ var DOMPortalEntity = (_class11 = class extends _chunkYLH7F4ZVjs.Entity {
5852
6063
  }, _class11);
5853
6064
 
5854
6065
  // src/index.ts
5855
- Scene.registerWebGLPointRendererCreator(_chunkL4SWVP2Hjs.createWebGLPointRenderer);
5856
- Scene.registerWebGPUParticleSystemManager(_chunkL4SWVP2Hjs.WebGPUParticleSystemManager);
6066
+ Scene.registerWebGLPointRendererCreator(_chunkGKSCJ6AFjs.createWebGLPointRenderer);
6067
+ Scene.registerWebGPUParticleSystemManager(_chunkGKSCJ6AFjs.WebGPUParticleSystemManager);
6068
+
5857
6069
 
5858
6070
 
5859
6071
 
@@ -5888,4 +6100,4 @@ Scene.registerWebGPUParticleSystemManager(_chunkL4SWVP2Hjs.WebGPUParticleSystemM
5888
6100
 
5889
6101
 
5890
6102
 
5891
- exports.CanvasRenderer = _chunkL4SWVP2Hjs.CanvasRenderer; exports.Circle = Circle; exports.ComputeParticleEntity = ComputeParticleEntity; exports.DOMPortalEntity = DOMPortalEntity; exports.Entity = _chunkYLH7F4ZVjs.Entity; exports.GridTextEntity = GridTextEntity; exports.Group = Group; exports.MSDFTextEntity = _chunkYLH7F4ZVjs.MSDFTextEntity; exports.PARTICLE_OFFSET_LIFE = PARTICLE_OFFSET_LIFE; exports.PARTICLE_OFFSET_ORIGIN_X = PARTICLE_OFFSET_ORIGIN_X; exports.PARTICLE_OFFSET_ORIGIN_Y = PARTICLE_OFFSET_ORIGIN_Y; exports.PARTICLE_OFFSET_POSITION_X = PARTICLE_OFFSET_POSITION_X; exports.PARTICLE_OFFSET_POSITION_Y = PARTICLE_OFFSET_POSITION_Y; exports.PARTICLE_OFFSET_SIZE = PARTICLE_OFFSET_SIZE; exports.PARTICLE_OFFSET_VELOCITY_X = PARTICLE_OFFSET_VELOCITY_X; exports.PARTICLE_OFFSET_VELOCITY_Y = PARTICLE_OFFSET_VELOCITY_Y; exports.PARTICLE_STRIDE_FLOATS = PARTICLE_STRIDE_FLOATS; exports.REDUCED_MOTION_FPS = REDUCED_MOTION_FPS; exports.Rect = Rect; exports.SVGEntity = _chunkYLH7F4ZVjs.SVGEntity; exports.SVGRenderer = _chunkL4SWVP2Hjs.SVGRenderer; exports.Scene = Scene; exports.SplineEntity = SplineEntity; exports.TextEntity = TextEntity; exports.TextRasterCache = _chunkL4SWVP2Hjs.TextRasterCache; exports.VectoJSEvent = _chunkYLH7F4ZVjs.VectoJSEvent; exports.WebGPUParticleSystemManager = _chunkL4SWVP2Hjs.WebGPUParticleSystemManager; exports.createWebGLPointRenderer = _chunkL4SWVP2Hjs.createWebGLPointRenderer; exports.isSafeUrl = _chunkL4SWVP2Hjs.isSafeUrl; exports.loadSpline = loadSpline; exports.parseColorToRGBA = _chunkL4SWVP2Hjs.parseColorToRGBA; exports.polySegmentToBezier = polySegmentToBezier; exports.sanitizeUrl = _chunkL4SWVP2Hjs.sanitizeUrl;
6103
+ exports.CanvasRenderer = _chunkGKSCJ6AFjs.CanvasRenderer; exports.Circle = Circle; exports.ComputeParticleEntity = ComputeParticleEntity; exports.DOMPortalEntity = DOMPortalEntity; exports.Entity = _chunkAGP4VLF4js.Entity; exports.GlyphRasterAtlas = _chunkGKSCJ6AFjs.GlyphRasterAtlas; exports.GridTextEntity = GridTextEntity; exports.Group = Group; exports.MSDFTextEntity = _chunkAGP4VLF4js.MSDFTextEntity; exports.PARTICLE_OFFSET_LIFE = PARTICLE_OFFSET_LIFE; exports.PARTICLE_OFFSET_ORIGIN_X = PARTICLE_OFFSET_ORIGIN_X; exports.PARTICLE_OFFSET_ORIGIN_Y = PARTICLE_OFFSET_ORIGIN_Y; exports.PARTICLE_OFFSET_POSITION_X = PARTICLE_OFFSET_POSITION_X; exports.PARTICLE_OFFSET_POSITION_Y = PARTICLE_OFFSET_POSITION_Y; exports.PARTICLE_OFFSET_SIZE = PARTICLE_OFFSET_SIZE; exports.PARTICLE_OFFSET_VELOCITY_X = PARTICLE_OFFSET_VELOCITY_X; exports.PARTICLE_OFFSET_VELOCITY_Y = PARTICLE_OFFSET_VELOCITY_Y; exports.PARTICLE_STRIDE_FLOATS = PARTICLE_STRIDE_FLOATS; exports.REDUCED_MOTION_FPS = REDUCED_MOTION_FPS; exports.Rect = Rect; exports.SVGEntity = _chunkAGP4VLF4js.SVGEntity; exports.SVGRenderer = _chunkGKSCJ6AFjs.SVGRenderer; exports.Scene = Scene; exports.SplineEntity = SplineEntity; exports.TextEntity = TextEntity; exports.TextRasterCache = _chunkGKSCJ6AFjs.TextRasterCache; exports.VectoJSEvent = _chunkAGP4VLF4js.VectoJSEvent; exports.WebGPUParticleSystemManager = _chunkGKSCJ6AFjs.WebGPUParticleSystemManager; exports.createWebGLPointRenderer = _chunkGKSCJ6AFjs.createWebGLPointRenderer; exports.isSafeUrl = _chunkGKSCJ6AFjs.isSafeUrl; exports.loadSpline = loadSpline; exports.parseColorToRGBA = _chunkGKSCJ6AFjs.parseColorToRGBA; exports.polySegmentToBezier = polySegmentToBezier; exports.sanitizeUrl = _chunkGKSCJ6AFjs.sanitizeUrl;