@vectojs/core 1.23.0 → 1.24.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
@@ -9,7 +9,7 @@
9
9
 
10
10
 
11
11
 
12
- var _chunkLHONR3GOjs = require('./chunk-LHONR3GO.js');
12
+ var _chunkKEBYJVD6js = require('./chunk-KEBYJVD6.js');
13
13
 
14
14
 
15
15
 
@@ -1243,6 +1243,79 @@ async function loadCoreWasmRuntime(source) {
1243
1243
  return createCoreWasmRuntime(module);
1244
1244
  }
1245
1245
 
1246
+ // src/performance/UserTiming.ts
1247
+ var VECTO_USER_TIMING = {
1248
+ scene: {
1249
+ transform: "vecto:scene:transform",
1250
+ drawWalk: "vecto:scene:draw-walk",
1251
+ entityPaint: "vecto:scene:entity-paint",
1252
+ flush: "vecto:scene:flush",
1253
+ a11ySync: "vecto:scene:a11y-sync"
1254
+ },
1255
+ markdown: {
1256
+ parse: "vecto:markdown:parse"
1257
+ }
1258
+ };
1259
+ var nextSpanId = 0;
1260
+ function beginVectoUserTiming(name) {
1261
+ const candidate = globalThis.performance;
1262
+ if (typeof _optionalChain([candidate, 'optionalAccess', _13 => _13.mark]) !== "function" || typeof candidate.measure !== "function") {
1263
+ return null;
1264
+ }
1265
+ const id = nextSpanId++;
1266
+ const startMark = `${name}:start:${id}`;
1267
+ const endMark = `${name}:end:${id}`;
1268
+ try {
1269
+ candidate.mark(startMark);
1270
+ return {
1271
+ name,
1272
+ startMark,
1273
+ endMark,
1274
+ performance: candidate
1275
+ };
1276
+ } catch (e7) {
1277
+ return null;
1278
+ }
1279
+ }
1280
+ function endVectoUserTiming(span) {
1281
+ if (!span) return;
1282
+ const timing = span.performance;
1283
+ try {
1284
+ timing.mark(span.endMark);
1285
+ timing.measure(span.name, span.startMark, span.endMark);
1286
+ } catch (e8) {
1287
+ } finally {
1288
+ try {
1289
+ _optionalChain([timing, 'access', _14 => _14.clearMarks, 'optionalCall', _15 => _15(span.startMark)]);
1290
+ _optionalChain([timing, 'access', _16 => _16.clearMarks, 'optionalCall', _17 => _17(span.endMark)]);
1291
+ } catch (e9) {
1292
+ }
1293
+ }
1294
+ }
1295
+ function measureVectoUserTiming(name, durationMs) {
1296
+ const candidate = globalThis.performance;
1297
+ if (typeof _optionalChain([candidate, 'optionalAccess', _18 => _18.now]) !== "function" || typeof candidate.mark !== "function" || typeof candidate.measure !== "function") {
1298
+ return;
1299
+ }
1300
+ const id = nextSpanId++;
1301
+ const startMark = `${name}:start:${id}`;
1302
+ const endMark = `${name}:end:${id}`;
1303
+ const endTime = candidate.now();
1304
+ const startTime = Math.max(0, endTime - Math.max(0, durationMs));
1305
+ try {
1306
+ candidate.mark(startMark, { startTime });
1307
+ candidate.mark(endMark, { startTime: endTime });
1308
+ candidate.measure(name, startMark, endMark);
1309
+ } catch (e10) {
1310
+ } finally {
1311
+ try {
1312
+ _optionalChain([candidate, 'access', _19 => _19.clearMarks, 'optionalCall', _20 => _20(startMark)]);
1313
+ _optionalChain([candidate, 'access', _21 => _21.clearMarks, 'optionalCall', _22 => _22(endMark)]);
1314
+ } catch (e11) {
1315
+ }
1316
+ }
1317
+ }
1318
+
1246
1319
  // src/tree/Scene.ts
1247
1320
  var _text = require('@vectojs/text'); _createStarExport(_text);
1248
1321
  var RANGE_VALUE_ROLES = /* @__PURE__ */ new Set(["slider", "spinbutton", "progressbar", "scrollbar", "meter"]);
@@ -1257,9 +1330,47 @@ var INTERACTIVE_A11Y_ROLES = /* @__PURE__ */ new Set([
1257
1330
  "slider",
1258
1331
  "combobox"
1259
1332
  ]);
1333
+ var A11Y_REQUIRED_OWNED = /* @__PURE__ */ new Map([
1334
+ ["grid", /* @__PURE__ */ new Set(["row", "rowgroup"])],
1335
+ ["table", /* @__PURE__ */ new Set(["row", "rowgroup"])],
1336
+ ["treegrid", /* @__PURE__ */ new Set(["row", "rowgroup"])],
1337
+ ["rowgroup", /* @__PURE__ */ new Set(["row"])],
1338
+ ["row", /* @__PURE__ */ new Set(["cell", "columnheader", "gridcell", "rowheader"])],
1339
+ ["tablist", /* @__PURE__ */ new Set(["tab"])],
1340
+ ["tree", /* @__PURE__ */ new Set(["treeitem", "group"])],
1341
+ ["group", /* @__PURE__ */ new Set(["treeitem", "menuitem", "menuitemcheckbox", "menuitemradio", "option"])],
1342
+ ["menu", /* @__PURE__ */ new Set(["menuitem", "menuitemcheckbox", "menuitemradio", "group", "separator"])],
1343
+ ["menubar", /* @__PURE__ */ new Set(["menuitem", "menuitemcheckbox", "menuitemradio", "group", "separator"])],
1344
+ ["listbox", /* @__PURE__ */ new Set(["option", "group"])],
1345
+ ["list", /* @__PURE__ */ new Set(["listitem"])]
1346
+ ]);
1260
1347
  function isNativelyFocusable(element) {
1261
1348
  return element instanceof HTMLButtonElement || element instanceof HTMLInputElement || element instanceof HTMLSelectElement || element instanceof HTMLTextAreaElement || element instanceof HTMLAnchorElement && element.hasAttribute("href");
1262
1349
  }
1350
+ var REBASED_BOX = { left: 0, top: 0, matrix: "" };
1351
+ function rebaseChildBox(parent, parentOriginX, parentOriginY, child, childOriginX, childOriginY) {
1352
+ const det = parent.a * parent.d - parent.b * parent.c;
1353
+ if (!Number.isFinite(det) || Math.abs(det) < 1e-12) {
1354
+ REBASED_BOX.left = 0;
1355
+ REBASED_BOX.top = 0;
1356
+ REBASED_BOX.matrix = "matrix(1, 0, 0, 1, 0, 0)";
1357
+ return REBASED_BOX;
1358
+ }
1359
+ const ia = parent.d / det;
1360
+ const ib = -parent.b / det;
1361
+ const ic = -parent.c / det;
1362
+ const id = parent.a / det;
1363
+ const dx = childOriginX - parentOriginX;
1364
+ const dy = childOriginY - parentOriginY;
1365
+ REBASED_BOX.left = ia * dx + ic * dy;
1366
+ REBASED_BOX.top = ib * dx + id * dy;
1367
+ const a = ia * child.a + ic * child.b;
1368
+ const b = ib * child.a + id * child.b;
1369
+ const c = ia * child.c + ic * child.d;
1370
+ const d = ib * child.c + id * child.d;
1371
+ REBASED_BOX.matrix = `matrix(${a}, ${b}, ${c}, ${d}, 0, 0)`;
1372
+ return REBASED_BOX;
1373
+ }
1263
1374
  var REDUCED_MOTION_FPS = 30;
1264
1375
  function parseInlinePx(value) {
1265
1376
  if (!value || !value.endsWith("px")) return null;
@@ -1345,9 +1456,9 @@ function parseCssMatrix(transform) {
1345
1456
  }
1346
1457
  function clientToGridLocal(contentEl, canvas, clientX, clientY) {
1347
1458
  const line = contentEl.querySelector("[data-vecto-grid-line]");
1348
- const originMarker = _optionalChain([line, 'optionalAccess', _13 => _13.querySelector, 'call', _14 => _14('[data-vecto-grid-basis="origin"]')]);
1349
- const xMarker = _optionalChain([line, 'optionalAccess', _15 => _15.querySelector, 'call', _16 => _16('[data-vecto-grid-basis="x"]')]);
1350
- const yMarker = _optionalChain([line, 'optionalAccess', _17 => _17.querySelector, 'call', _18 => _18('[data-vecto-grid-basis="y"]')]);
1459
+ const originMarker = _optionalChain([line, 'optionalAccess', _23 => _23.querySelector, 'call', _24 => _24('[data-vecto-grid-basis="origin"]')]);
1460
+ const xMarker = _optionalChain([line, 'optionalAccess', _25 => _25.querySelector, 'call', _26 => _26('[data-vecto-grid-basis="x"]')]);
1461
+ const yMarker = _optionalChain([line, 'optionalAccess', _27 => _27.querySelector, 'call', _28 => _28('[data-vecto-grid-basis="y"]')]);
1351
1462
  if (line && originMarker && xMarker && yMarker) {
1352
1463
  const origin = originMarker.getBoundingClientRect();
1353
1464
  const xPoint = xMarker.getBoundingClientRect();
@@ -1431,7 +1542,7 @@ function nearestTextPositionInLine(line, x, y) {
1431
1542
  nearest = { position: { node, offset }, distance: candidate.distance };
1432
1543
  }
1433
1544
  }
1434
- return _nullishCoalesce(_optionalChain([nearest, 'optionalAccess', _19 => _19.position]), () => ( null));
1545
+ return _nullishCoalesce(_optionalChain([nearest, 'optionalAccess', _29 => _29.position]), () => ( null));
1435
1546
  }
1436
1547
  function nearestTextPositionInProjection(contentEl, canvas, x, y, eventTarget) {
1437
1548
  if (contentEl.dataset.vectoContentGrid !== void 0) {
@@ -1445,7 +1556,7 @@ function nearestTextPositionInProjection(contentEl, canvas, x, y, eventTarget) {
1445
1556
  }
1446
1557
  targetLine = targetLine.parentElement;
1447
1558
  }
1448
- if (_optionalChain([targetLine, 'optionalAccess', _20 => _20.parentElement]) === contentEl) {
1559
+ if (_optionalChain([targetLine, 'optionalAccess', _30 => _30.parentElement]) === contentEl) {
1449
1560
  return nearestTextPositionInLine(targetLine, x, y);
1450
1561
  }
1451
1562
  let bestLine = null;
@@ -1532,13 +1643,13 @@ function extendSelection(selection, anchor, focus) {
1532
1643
  try {
1533
1644
  selection.setBaseAndExtent(anchor.node, anchor.offset, focus.node, focus.offset);
1534
1645
  return;
1535
- } catch (e7) {
1646
+ } catch (e12) {
1536
1647
  }
1537
1648
  try {
1538
1649
  selection.collapse(anchor.node, anchor.offset);
1539
1650
  selection.extend(focus.node, focus.offset);
1540
1651
  return;
1541
- } catch (e8) {
1652
+ } catch (e13) {
1542
1653
  }
1543
1654
  const anchorRange = document.createRange();
1544
1655
  anchorRange.setStart(anchor.node, anchor.offset);
@@ -1594,7 +1705,8 @@ var Scene = (_class7 = class _Scene {
1594
1705
  /** Cap on distinct recorded dirty reasons (see `recordDirtyReason`). */
1595
1706
  static __initStatic4() {this.MAX_DIRTY_REASONS = 200}
1596
1707
  __init32() {this._phaseTiming = false}
1597
- __init33() {this._phaseTotals = /* @__PURE__ */ new Map()}
1708
+ __init33() {this._userTiming = false}
1709
+ __init34() {this._phaseTotals = /* @__PURE__ */ new Map()}
1598
1710
  /**
1599
1711
  * Start or stop per-phase render timing.
1600
1712
  *
@@ -1616,6 +1728,19 @@ var Scene = (_class7 = class _Scene {
1616
1728
  get phaseTiming() {
1617
1729
  return this._phaseTiming;
1618
1730
  }
1731
+ /**
1732
+ * Enable or disable browser User Timing phase instrumentation.
1733
+ *
1734
+ * Off by default. The disabled frame path performs only boolean checks and
1735
+ * emits no Performance Timeline entries.
1736
+ */
1737
+ setUserTiming(enabled) {
1738
+ this._userTiming = enabled;
1739
+ }
1740
+ /** Whether browser User Timing phase instrumentation is enabled. */
1741
+ get userTiming() {
1742
+ return this._userTiming;
1743
+ }
1619
1744
  /**
1620
1745
  * Accumulate one phase sample.
1621
1746
  *
@@ -1657,32 +1782,32 @@ var Scene = (_class7 = class _Scene {
1657
1782
  clearRenderPhases() {
1658
1783
  this._phaseTotals.clear();
1659
1784
  }
1660
- __init34() {this._dirtyTracking = false}
1661
- __init35() {this._dirtyReasons = /* @__PURE__ */ new Map()}
1662
- __init36() {this.dirty = true}
1785
+ __init35() {this._dirtyTracking = false}
1786
+ __init36() {this._dirtyReasons = /* @__PURE__ */ new Map()}
1787
+ __init37() {this.dirty = true}
1663
1788
  /** Whether to throttle rendering to 2 FPS when the scene is static to save power. */
1664
- __init37() {this.autoThrottle = true}
1789
+ __init38() {this.autoThrottle = true}
1665
1790
  // --- Frame telemetry (read via `frameStats`) ---------------------------
1666
1791
  /** Wall-clock ms spent inside the last `render()` call. */
1667
- __init38() {this._lastFrameMs = 0}
1792
+ __init39() {this._lastFrameMs = 0}
1668
1793
  /** Rolling exponential average of rendered-frame intervals, in ms. */
1669
- __init39() {this._avgFrameIntervalMs = 0}
1794
+ __init40() {this._avgFrameIntervalMs = 0}
1670
1795
  /** dt (ms) handed to the last rendered frame. */
1671
- __init40() {this._lastDt = 0}
1796
+ __init41() {this._lastDt = 0}
1672
1797
  /** Count of frames actually rendered since the loop started. */
1673
- __init41() {this._renderedFrames = 0}
1798
+ __init42() {this._renderedFrames = 0}
1674
1799
  /** Count of rAF ticks skipped (idle / capped) since the loop started. */
1675
- __init42() {this._skippedFrames = 0}
1800
+ __init43() {this._skippedFrames = 0}
1676
1801
  /** `time` of the previous *rendered* frame, for interval measurement. */
1677
- __init43() {this._lastRenderTick = 0}
1802
+ __init44() {this._lastRenderTick = 0}
1678
1803
  /**
1679
1804
  * Frame-rate cap (power saving). `0` = uncapped (native refresh). When set,
1680
1805
  * the loop renders at most `maxFPS` times per second; animations still run,
1681
1806
  * just less often. See {@link SceneOptions.maxFPS}.
1682
1807
  */
1683
- __init44() {this.maxFPS = 60}
1808
+ __init45() {this.maxFPS = 60}
1684
1809
  /** Whether the OS prefers-reduced-motion setting auto-caps the loop. */
1685
- __init45() {this.respectReducedMotion = true}
1810
+ __init46() {this.respectReducedMotion = true}
1686
1811
  /**
1687
1812
  * Reading direction for accessibility tab/traversal order (`'ltr'` default,
1688
1813
  * `'rtl'`). Controls the inline sort within a visual row in
@@ -1698,18 +1823,18 @@ var Scene = (_class7 = class _Scene {
1698
1823
  this.a11yNeedsReorder = true;
1699
1824
  }
1700
1825
  }
1701
- __init46() {this._readingDirection = "ltr"}
1826
+ __init47() {this._readingDirection = "ltr"}
1702
1827
  /** Cached media-query list; `.matches` is read live each frame. */
1703
- __init47() {this.reducedMotionQuery = null}
1828
+ __init48() {this.reducedMotionQuery = null}
1704
1829
  /** Cached `(forced-colors: active)` query (Windows High Contrast etc.). A
1705
1830
  * canvas gets NO automatic forced-colors treatment from the browser (it's
1706
1831
  * opaque pixels), so components must read {@link forcedColors} and repaint
1707
1832
  * with system colors themselves; a change listener repaints idle scenes. */
1708
- __init48() {this.forcedColorsQuery = null}
1709
- __init49() {this.forcedColorsChangeHandler = null}
1833
+ __init49() {this.forcedColorsQuery = null}
1834
+ __init50() {this.forcedColorsChangeHandler = null}
1710
1835
  /** True when the OS asks for reduced motion and we respect it. Read by the animation drivers. */
1711
1836
  get prefersReducedMotion() {
1712
- return this.respectReducedMotion && !!_optionalChain([this, 'access', _21 => _21.reducedMotionQuery, 'optionalAccess', _22 => _22.matches]);
1837
+ return this.respectReducedMotion && !!_optionalChain([this, 'access', _31 => _31.reducedMotionQuery, 'optionalAccess', _32 => _32.matches]);
1713
1838
  }
1714
1839
  /**
1715
1840
  * True when the OS is in a forced-colors mode (Windows High Contrast, and the
@@ -1720,28 +1845,28 @@ var Scene = (_class7 = class _Scene {
1720
1845
  * when the setting toggles.
1721
1846
  */
1722
1847
  get forcedColors() {
1723
- return !!_optionalChain([this, 'access', _23 => _23.forcedColorsQuery, 'optionalAccess', _24 => _24.matches]);
1848
+ return !!_optionalChain([this, 'access', _33 => _33.forcedColorsQuery, 'optionalAccess', _34 => _34.matches]);
1724
1849
  }
1725
1850
  /**
1726
1851
  * Throttle interval (ms) for the a11y/automation shadow sync. `0` = every
1727
1852
  * frame. See {@link SceneOptions.a11ySyncInterval}.
1728
1853
  */
1729
- __init50() {this.a11ySyncInterval = 0}
1854
+ __init51() {this.a11ySyncInterval = 0}
1730
1855
  /** Timestamp of the last a11y sync, for throttling. */
1731
- __init51() {this.lastA11ySync = -Infinity}
1856
+ __init52() {this.lastA11ySync = -Infinity}
1732
1857
  /** True if we skipped an a11y sync during animation and need to sync when at rest. */
1733
- __init52() {this.a11yPendingSyncAfterAnimation = false}
1858
+ __init53() {this.a11yPendingSyncAfterAnimation = false}
1734
1859
  // A11y / Automation Layer. `null` in non-DOM (SSR/Node) environments — the
1735
1860
  // whole projection degrades to a no-op so the engine's logic stays usable
1736
1861
  // server-side (e.g. headless layout / vector export) without jsdom.
1737
1862
 
1738
- __init53() {this.a11yElements = /* @__PURE__ */ new Map()}
1863
+ __init54() {this.a11yElements = /* @__PURE__ */ new Map()}
1739
1864
  /** DOM nodes mirroring static text content, keyed by entity id. */
1740
- __init54() {this.contentElements = /* @__PURE__ */ new Map()}
1865
+ __init55() {this.contentElements = /* @__PURE__ */ new Map()}
1741
1866
  /** Pending cold font-calibration frame per projected grid entity. */
1742
- __init55() {this.contentGridCalibrationFrames = /* @__PURE__ */ new Map()}
1867
+ __init56() {this.contentGridCalibrationFrames = /* @__PURE__ */ new Map()}
1743
1868
  /** Detached, untransformed font probes used by the cold calibration pass. */
1744
- __init56() {this.contentGridCalibrationProbes = /* @__PURE__ */ new Map()}
1869
+ __init57() {this.contentGridCalibrationProbes = /* @__PURE__ */ new Map()}
1745
1870
  /**
1746
1871
  * Monotonic stamp identifying the conditions grid cells were calibrated under.
1747
1872
  *
@@ -1762,69 +1887,71 @@ var Scene = (_class7 = class _Scene {
1762
1887
  * A plain incrementing integer rather than the descriptive calibration key,
1763
1888
  * because it goes into an attribute selector and must not need escaping.
1764
1889
  */
1765
- __init57() {this.contentGridCalibrationGeneration = 0}
1890
+ __init58() {this.contentGridCalibrationGeneration = 0}
1766
1891
  /** The `(fontEpoch, pageScale)` pair the current generation corresponds to. */
1767
- __init58() {this.contentGridCalibrationStamp = ""}
1892
+ __init59() {this.contentGridCalibrationStamp = ""}
1768
1893
  /** Invalidates grid font calibration after browser font availability changes. */
1769
- __init59() {this.contentFontEpoch = 0}
1894
+ __init60() {this.contentFontEpoch = 0}
1770
1895
  /** Cached Canvas-to-client scale for the current font/viewport epoch. */
1771
- __init60() {this.contentMetricScaleEpoch = -1}
1772
- __init61() {this.contentMetricScaleX = 1}
1773
- __init62() {this.contentProjectionEnabled = true}
1896
+ __init61() {this.contentMetricScaleEpoch = -1}
1897
+ __init62() {this.contentMetricScaleX = 1}
1898
+ __init63() {this.contentProjectionEnabled = true}
1774
1899
  // Virtualization margin (px) for content projection; `undefined` → one
1775
1900
  // viewport height, resolved at sync time. `Infinity` = materialize everything.
1776
- __init63() {this.contentProjectionMargin = void 0}
1901
+ __init64() {this.contentProjectionMargin = void 0}
1777
1902
  /**
1778
1903
  * True while a text-selection drag that started on a projection's blank
1779
1904
  * region (no text node under the press) is being driven manually — the
1780
1905
  * browser has no native anchor for it, so mousemove extends the Selection
1781
1906
  * from the position we resolved ourselves.
1782
1907
  */
1783
- __init64() {this.blankRegionSelectionDrag = false}
1784
- __init65() {this.contentSelectionAnchor = null}
1785
- __init66() {this.contentSelectionEndListener = null}
1908
+ __init65() {this.blankRegionSelectionDrag = false}
1909
+ __init66() {this.contentSelectionAnchor = null}
1910
+ __init67() {this.contentSelectionEndListener = null}
1786
1911
  // Animation/interactive flags collected during the render walk (tree-walk
1787
1912
  // fusion): the loop reads last frame's answers instead of re-walking the
1788
1913
  // tree up to 4× per tick. Start true so the first tick stays conservative.
1789
- __init67() {this.frameHadAnimation = true}
1790
- __init68() {this.frameHadInteractive = true}
1914
+ __init68() {this.frameHadAnimation = true}
1915
+ __init69() {this.frameHadInteractive = true}
1791
1916
 
1792
1917
  /** Active `(resolution: Ndppx)` media query watching for a runtime DPR change
1793
1918
  * (window moved between monitors, browser zoom) so the canvas backing store
1794
1919
  * can be re-scaled — otherwise it stays rasterized at the old DPR and blurs.
1795
1920
  * A resolution media query only fires when leaving its exact value, so the
1796
1921
  * handler re-arms a fresh query for the new DPR each time. */
1797
- __init69() {this.dprMediaQuery = null}
1922
+ __init70() {this.dprMediaQuery = null}
1798
1923
  /** For embedded (`disableWindowResize`) scenes: observes the canvas element so
1799
1924
  * a CSS/layout-driven size change re-runs `resize()`. A window `resize`
1800
1925
  * listener never fires for these (the window isn't what changed), so without
1801
1926
  * this an embedded canvas stayed at its initial size forever. */
1802
- __init70() {this.canvasResizeObserver = null}
1803
- __init71() {this.dprChangeHandler = null}
1804
- __init72() {this.focusedA11yElement = null}
1927
+ __init71() {this.canvasResizeObserver = null}
1928
+ __init72() {this.dprChangeHandler = null}
1929
+ __init73() {this.focusedA11yElement = null}
1805
1930
  /** Last geometry `syncOverlayGeometry` wrote, so an unchanged frame can skip the
1806
1931
  * style writes entirely. Reset to `null` to force the next sync (a new overlay
1807
1932
  * layer was created and has never been positioned). */
1808
- __init73() {this._overlayGeometry = null}
1933
+ __init74() {this._overlayGeometry = null}
1809
1934
  /** Shadow elements the pointer is currently inside. Lets a removal that happens
1810
1935
  * mid-hover synthesize the `pointerleave` the browser never sends for a
1811
1936
  * detached element, so the entity doesn't keep its hover state. */
1812
- __init74() {this.hoveredA11yElements = /* @__PURE__ */ new WeakSet()}
1937
+ __init75() {this.hoveredA11yElements = /* @__PURE__ */ new WeakSet()}
1813
1938
  /** Persistent tabindex=-1 element in a11yRoot. When the focused a11y mirror is
1814
1939
  * pruned (virtualization/streaming/removal) while it holds focus, we move
1815
1940
  * focus here instead of letting the browser drop it to <body> — keeping the
1816
1941
  * screen-reader virtual cursor inside the scene's a11y region. */
1817
- __init75() {this.focusSentinel = null}
1818
- __init76() {this.caretBlinkTimer = null}
1819
- __init77() {this.a11yNeedsReorder = true}
1820
- __init78() {this.portalRoot = null}
1821
- __init79() {this.fullViewportElements = []}
1822
- __init80() {this.normalElements = []}
1823
- __init81() {this.activeIds = /* @__PURE__ */ new Set()}
1824
- __init82() {this.activePortalsThisFrame = /* @__PURE__ */ new Set()}
1825
- __init83() {this.activePortalsPrevFrame = /* @__PURE__ */ new Set()}
1826
- __init84() {this.portalEntities = /* @__PURE__ */ new Map()}
1827
- __init85() {this.renderOrderCounter = 0}
1942
+ __init76() {this.focusSentinel = null}
1943
+ __init77() {this.caretBlinkTimer = null}
1944
+ __init78() {this.a11yNeedsReorder = true}
1945
+ __init79() {this.portalRoot = null}
1946
+ __init80() {this.fullViewportElements = []}
1947
+ __init81() {this.normalElements = []}
1948
+ __init82() {this.activeIds = /* @__PURE__ */ new Set()}
1949
+ /** Per-parent insertion cursor, reused by `enforceA11yDomOrder`. */
1950
+ __init83() {this.a11yOrderCursors = /* @__PURE__ */ new Map()}
1951
+ __init84() {this.activePortalsThisFrame = /* @__PURE__ */ new Set()}
1952
+ __init85() {this.activePortalsPrevFrame = /* @__PURE__ */ new Set()}
1953
+ __init86() {this.portalEntities = /* @__PURE__ */ new Map()}
1954
+ __init87() {this.renderOrderCounter = 0}
1828
1955
  /**
1829
1956
  * Monotonic render-frame counter, bumped once per authoritative `render()`
1830
1957
  * pass. Entities stamp their per-frame world-matrix cache with this value and
@@ -1833,7 +1960,7 @@ var Scene = (_class7 = class _Scene {
1833
1960
  * back to the ancestor walk. Public for the same reason `Entity._getTrig`/
1834
1961
  * `_setWorldCache` are: it is a cross-class render-internal contract.
1835
1962
  */
1836
- __init86() {this.currentFrame = 0}
1963
+ __init88() {this.currentFrame = 0}
1837
1964
  // ── WASM transform backend (invisible accelerator) ──────────────────────────
1838
1965
  // When `_transformBackend === 'wasm'`, the main render walk sources each
1839
1966
  // entity's world matrix from an SoA store composed by `_wasm` (see
@@ -1841,24 +1968,24 @@ var Scene = (_class7 = class _Scene {
1841
1968
  // fallback and the default: a null backend, a non-main renderer, or any entity
1842
1969
  // absent from the store all fall back to the JS composition, so WASM can only
1843
1970
  // ever change *how fast* a world matrix is produced, never *what* it is.
1844
- __init87() {this._wasm = null}
1845
- __init88() {this._transformBackend = "js"}
1971
+ __init89() {this._wasm = null}
1972
+ __init90() {this._transformBackend = "js"}
1846
1973
  // Resident store state (Stage 3). The store layout — slot assignment + sibling
1847
1974
  // runs — depends only on tree TOPOLOGY, so it is rebuilt only when the
1848
1975
  // structure changes (add/remove/reparent bump `_structureVersion`). Between
1849
1976
  // rebuilds the per-frame cost is: gather each entity's transform into the
1850
1977
  // resident wasm input view + run the kernel — no reallocation, no readback.
1851
- __init89() {this._treeStore = null}
1852
- __init90() {this._slotEntity = []}
1978
+ __init91() {this._treeStore = null}
1979
+ __init92() {this._slotEntity = []}
1853
1980
  // store slot -> entity (also validates slots)
1854
- __init91() {this._wasmInputs = null}
1855
- __init92() {this._wasmWorld = null}
1856
- __init93() {this._structureVersion = 0}
1857
- __init94() {this._storeStructureVersion = -1}
1981
+ __init93() {this._wasmInputs = null}
1982
+ __init94() {this._wasmWorld = null}
1983
+ __init95() {this._structureVersion = 0}
1984
+ __init96() {this._storeStructureVersion = -1}
1858
1985
  // Cached list of ComputeParticleEntity instances in the tree, keyed by the
1859
1986
  // structure version it was gathered at. Rebuilt only on a topology change.
1860
- __init95() {this._computeEntities = []}
1861
- __init96() {this._computeEntitiesVersion = -1}
1987
+ __init97() {this._computeEntities = []}
1988
+ __init98() {this._computeEntitiesVersion = -1}
1862
1989
  /** Invalidate the resident WASM store layout; the next wasm-mode frame rebuilds
1863
1990
  * it. Called by `Entity.add`/`remove` (topology changes only). */
1864
1991
  markStructureChanged() {
@@ -1943,7 +2070,7 @@ var Scene = (_class7 = class _Scene {
1943
2070
  * cached globally; the instance is per-Scene, which is the isolation that
1944
2071
  * actually matters.
1945
2072
  */
1946
- __init97() {this._wasmRuntime = null}
2073
+ __init99() {this._wasmRuntime = null}
1947
2074
  /**
1948
2075
  * Load (or reuse) this Scene's shared WASM runtime.
1949
2076
  *
@@ -1971,30 +2098,30 @@ var Scene = (_class7 = class _Scene {
1971
2098
  get wasmRuntime() {
1972
2099
  return this._wasmRuntime;
1973
2100
  }
1974
- __init98() {this._hitWasm = null}
2101
+ __init100() {this._hitWasm = null}
1975
2102
  // Cache key: which frame + structure version the grid was last (successfully,
1976
2103
  // non-overflowing) built for. findEntityAt is called ad-hoc (pointer
1977
2104
  // hover/click), not every frame, so the grid is refreshed lazily on demand
1978
2105
  // rather than proactively every render() — unlike the transform store, which
1979
2106
  // every frame's draw depends on.
1980
- __init99() {this._hitGridFrame = -1}
1981
- __init100() {this._hitGridOk = false}
1982
- __init101() {this._hitSlotEntity = []}
1983
- __init102() {this._hitBoundless = []}
2107
+ __init101() {this._hitGridFrame = -1}
2108
+ __init102() {this._hitGridOk = false}
2109
+ __init103() {this._hitSlotEntity = []}
2110
+ __init104() {this._hitBoundless = []}
1984
2111
  /** Reused buffer for the fused gather, so a pointer query allocates nothing. */
1985
- __init103() {this._hitGatherBuffer = null}
2112
+ __init105() {this._hitGatherBuffer = null}
1986
2113
  /**
1987
2114
  * Whether the last grid build sourced its AABBs from the WASM transform store
1988
2115
  * rather than recomputing them in JS. Diagnostic only — both paths must
1989
2116
  * produce the same entity for a given point.
1990
2117
  */
1991
- __init104() {this._hitFusedGather = false}
2118
+ __init106() {this._hitFusedGather = false}
1992
2119
  /**
1993
2120
  * Whether `compute_aabbs` has run against the current frame's world matrices.
1994
2121
  * The AABB pass is only meaningful after a `compose_*`, so the fused gather
1995
2122
  * must not read the views before then.
1996
2123
  */
1997
- __init105() {this._wasmAabbsFresh = false}
2124
+ __init107() {this._wasmAabbsFresh = false}
1998
2125
  /** Did the last hit-grid build use the fused (WASM-store) gather? */
1999
2126
  get hitGatherPath() {
2000
2127
  return this._hitFusedGather ? "fused" : "js";
@@ -2003,9 +2130,9 @@ var Scene = (_class7 = class _Scene {
2003
2130
  * Why the transform accelerator did or did not run on the most recent frame.
2004
2131
  * Written by the render walk and `_syncWasmStore`.
2005
2132
  */
2006
- __init106() {this._transformReason = "not-installed"}
2133
+ __init108() {this._transformReason = "not-installed"}
2007
2134
  /** Why the batched-driver accelerator did or did not run. */
2008
- __init107() {this._animReason = "not-installed"}
2135
+ __init109() {this._animReason = "not-installed"}
2009
2136
  /**
2010
2137
  * Why the hit-test accelerator did or did not serve the last pointer query.
2011
2138
  * The grid is built lazily on demand, not every frame, so this describes the
@@ -2013,11 +2140,11 @@ var Scene = (_class7 = class _Scene {
2013
2140
  * before a backend exists; `_ensureHitGrid` moves it to `'not-applicable'`
2014
2141
  * once one is installed but nothing has queried yet.
2015
2142
  */
2016
- __init108() {this._hitReason = "not-installed"}
2143
+ __init110() {this._hitReason = "not-installed"}
2017
2144
  /** Why the particle accelerator did or did not run. */
2018
- __init109() {this._particleReason = "not-applicable"}
2145
+ __init111() {this._particleReason = "not-applicable"}
2019
2146
  /** Which particle implementation actually simulated the most recent frame. */
2020
- __init110() {this._particlePath = "none"}
2147
+ __init112() {this._particlePath = "none"}
2021
2148
  /**
2022
2149
  * Per-frame status of every invisible accelerator: whether each is installed,
2023
2150
  * whether it actually ran on the most recent frame, and why.
@@ -2154,7 +2281,7 @@ var Scene = (_class7 = class _Scene {
2154
2281
  const idx = cell[k];
2155
2282
  if (x < minx[idx] || x > maxx[idx] || y < miny[idx] || y > maxy[idx]) continue;
2156
2283
  const entity = this._hitSlotEntity[idx];
2157
- if (_optionalChain([entity, 'optionalAccess', _25 => _25.isPointInside, 'call', _26 => _26(x, y)]) && this.isHitEligible(entity, x, y)) {
2284
+ if (_optionalChain([entity, 'optionalAccess', _35 => _35.isPointInside, 'call', _36 => _36(x, y)]) && this.isHitEligible(entity, x, y)) {
2158
2285
  bestIndex = idx;
2159
2286
  bestEntity = entity;
2160
2287
  break;
@@ -2177,25 +2304,25 @@ var Scene = (_class7 = class _Scene {
2177
2304
  // EasingFn (which cannot cross into WASM) all fall through to it — WASM can
2178
2305
  // only ever change *how* a driver is advanced, never *what* value it lands
2179
2306
  // on.
2180
- __init111() {this._animWasm = null}
2307
+ __init113() {this._animWasm = null}
2181
2308
  // Entities with at least one active driver, added by Entity._spawnDriver.
2182
2309
  // Self-pruning: _tickBatchedDrivers drops an entry the first time it visits
2183
2310
  // an entity whose drivers have since all completed or been removed. This is
2184
2311
  // what lets the batch pass find its candidates in O(active drivers), not
2185
2312
  // O(tree size) — the exact mistake G3's first integrated benchmark made.
2186
- __init112() {this._activeDriverEntities = /* @__PURE__ */ new Set()}
2313
+ __init114() {this._activeDriverEntities = /* @__PURE__ */ new Set()}
2187
2314
  // Reused across frames instead of allocating a fresh array + N {entity,prop,
2188
2315
  // driver} objects every call — the integrated benchmark
2189
2316
  // (benchmarks/anim-wasm-scene) found that allocation churn was the
2190
2317
  // dominant integrated cost, not the wasm kernel itself. Parallel arrays,
2191
2318
  // truncated to the live count after each use so a stale tail slot never
2192
2319
  // pins a no-longer-active entity/driver in memory.
2193
- __init113() {this._springEntities = []}
2194
- __init114() {this._springProps = []}
2195
- __init115() {this._springDrivers = []}
2196
- __init116() {this._tweenEntities = []}
2197
- __init117() {this._tweenProps = []}
2198
- __init118() {this._tweenDrivers = []}
2320
+ __init115() {this._springEntities = []}
2321
+ __init116() {this._springProps = []}
2322
+ __init117() {this._springDrivers = []}
2323
+ __init118() {this._tweenEntities = []}
2324
+ __init119() {this._tweenProps = []}
2325
+ __init120() {this._tweenDrivers = []}
2199
2326
  /**
2200
2327
  * Minimum number of batchable (spring, or named-easing tween) active drivers
2201
2328
  * before a frame engages the WASM batch path at all; below it, every driver
@@ -2267,7 +2394,7 @@ var Scene = (_class7 = class _Scene {
2267
2394
  * Setting {@link animDriverGateCount} overwrites all three, so existing code
2268
2395
  * that tuned the single knob keeps working unchanged.
2269
2396
  */
2270
- __init119() {this._animBatchedLastFrame = false}
2397
+ __init121() {this._animBatchedLastFrame = false}
2271
2398
  /**
2272
2399
  * Whether the WASM batch path actually ran on the most recent frame.
2273
2400
  *
@@ -2279,7 +2406,7 @@ var Scene = (_class7 = class _Scene {
2279
2406
  get animBatchedLastFrame() {
2280
2407
  return this._animBatchedLastFrame;
2281
2408
  }
2282
- __init120() {this.animGate = {
2409
+ __init122() {this.animGate = {
2283
2410
  spring: 128,
2284
2411
  tween: 256,
2285
2412
  mixed: 128
@@ -2317,7 +2444,7 @@ var Scene = (_class7 = class _Scene {
2317
2444
  // (benchmarks/particle-wasm). f32 (matches the WGSL shader), bit-identical to
2318
2445
  // a JS f32 reference oracle; updateCPU (f64) stays the permanent fallback when
2319
2446
  // no backend is installed or a scene runs on WebGPU.
2320
- __init121() {this._particleWasm = null}
2447
+ __init123() {this._particleWasm = null}
2321
2448
  /** Which backend runs the CPU particle simulation. Reflects only whether a
2322
2449
  * backend is installed (the WebGPU compute path, when active, is used first
2323
2450
  * regardless). */
@@ -2594,24 +2721,24 @@ var Scene = (_class7 = class _Scene {
2594
2721
  * sync, so retaining the order prevents a newly opened overlay from spending
2595
2722
  * its first frame below previously projected controls.
2596
2723
  */
2597
- __init122() {this.a11yRenderOrders = /* @__PURE__ */ new Map()}
2724
+ __init124() {this.a11yRenderOrders = /* @__PURE__ */ new Map()}
2598
2725
  // Optional WebGL point-cloud layer (see SceneOptions.pointBackend).
2599
- __init123() {this.pointRenderer = null}
2600
- __init124() {this.glCanvas = null}
2601
- __init125() {this.glContextLostHandler = null}
2602
- __init126() {this.glContextRestoredHandler = null}
2726
+ __init125() {this.pointRenderer = null}
2727
+ __init126() {this.glCanvas = null}
2728
+ __init127() {this.glContextLostHandler = null}
2729
+ __init128() {this.glContextRestoredHandler = null}
2603
2730
 
2604
2731
 
2605
2732
 
2606
- __init127() {this.disableWindowResize = false}
2733
+ __init129() {this.disableWindowResize = false}
2607
2734
  /** See {@link SceneOptions.maxDPR}. `undefined` = uncapped (real DPR). */
2608
2735
 
2609
2736
  // WebGPU properties
2610
- __init128() {this.destroyed = false}
2611
- __init129() {this.device = null}
2612
- __init130() {this.deviceLost = false}
2613
- __init131() {this.particleBackend = "auto"}
2614
- __init132() {this._webgpuDisabled = false}
2737
+ __init130() {this.destroyed = false}
2738
+ __init131() {this.device = null}
2739
+ __init132() {this.deviceLost = false}
2740
+ __init133() {this.particleBackend = "auto"}
2741
+ __init134() {this._webgpuDisabled = false}
2615
2742
  get webgpuDisabled() {
2616
2743
  return this._webgpuDisabled || this.particleBackend === "cpu";
2617
2744
  }
@@ -2625,7 +2752,7 @@ var Scene = (_class7 = class _Scene {
2625
2752
  * active.
2626
2753
  */
2627
2754
  get webglDrawStats() {
2628
- return _nullishCoalesce(_optionalChain([this, 'access', _27 => _27.pointRenderer, 'optionalAccess', _28 => _28.stats, 'optionalCall', _29 => _29()]), () => ( null));
2755
+ return _nullishCoalesce(_optionalChain([this, 'access', _37 => _37.pointRenderer, 'optionalAccess', _38 => _38.stats, 'optionalCall', _39 => _39()]), () => ( null));
2629
2756
  }
2630
2757
  /**
2631
2758
  * Whether a WebGPU device is currently live for particle compute.
@@ -2639,22 +2766,22 @@ var Scene = (_class7 = class _Scene {
2639
2766
  set webgpuDisabled(value) {
2640
2767
  this._webgpuDisabled = value;
2641
2768
  }
2642
- __init133() {this.recoveryTimerId = null}
2643
- __init134() {this.manager = null}
2644
- __init135() {this.initializingWebGPU = false}
2645
- __init136() {this.gpuCanvas = null}
2646
- __init137() {this.gpuContext = null}
2769
+ __init135() {this.recoveryTimerId = null}
2770
+ __init136() {this.manager = null}
2771
+ __init137() {this.initializingWebGPU = false}
2772
+ __init138() {this.gpuCanvas = null}
2773
+ __init139() {this.gpuContext = null}
2647
2774
  /** True while the GPU canvas holds a presented particle frame (needs clearing when they leave). */
2648
- __init138() {this.gpuHasContent = false}
2649
- __init139() {this.mouseX = -9999}
2650
- __init140() {this.mouseY = -9999}
2651
- __init141() {this.pointerMoveListener = null}
2652
- __init142() {this.pointerLeaveListener = null}
2775
+ __init140() {this.gpuHasContent = false}
2776
+ __init141() {this.mouseX = -9999}
2777
+ __init142() {this.mouseY = -9999}
2778
+ __init143() {this.pointerMoveListener = null}
2779
+ __init144() {this.pointerLeaveListener = null}
2653
2780
  /** Element the pointer listeners are bound to (parent container if present,
2654
2781
  * else the canvas). Stored so `destroy()` detaches from the same element. */
2655
- __init143() {this.pointerEventTarget = null}
2656
- __init144() {this.hasWarnedZeroSize = false}
2657
- __init145() {this.fontLoadHandler = null}
2782
+ __init145() {this.pointerEventTarget = null}
2783
+ __init146() {this.hasWarnedZeroSize = false}
2784
+ __init147() {this.fontLoadHandler = null}
2658
2785
  // ── Dev-mode warning infrastructure ──────────────────────────────
2659
2786
  //
2660
2787
  // Enable with `Scene.devMode = true` or by setting `globalThis.__DEV__`.
@@ -2667,12 +2794,12 @@ var Scene = (_class7 = class _Scene {
2667
2794
  static _devModeDetected() {
2668
2795
  if (_Scene.devMode) return true;
2669
2796
  const gp = typeof globalThis !== "undefined" ? globalThis : void 0;
2670
- if (_optionalChain([gp, 'optionalAccess', _30 => _30.__DEV__])) return true;
2671
- if (_optionalChain([gp, 'optionalAccess', _31 => _31.process, 'optionalAccess', _32 => _32.env, 'optionalAccess', _33 => _33.NODE_ENV]) === "development") return true;
2797
+ if (_optionalChain([gp, 'optionalAccess', _40 => _40.__DEV__])) return true;
2798
+ if (_optionalChain([gp, 'optionalAccess', _41 => _41.process, 'optionalAccess', _42 => _42.env, 'optionalAccess', _43 => _43.NODE_ENV]) === "development") return true;
2672
2799
  return false;
2673
2800
  }
2674
2801
 
2675
- __init146() {this._devFrameCount = 0}
2802
+ __init148() {this._devFrameCount = 0}
2676
2803
  _devWarn(message) {
2677
2804
  if (!this._devActive) return;
2678
2805
  console.warn(`[vectojs/dev] ${message}`);
@@ -2699,9 +2826,9 @@ var Scene = (_class7 = class _Scene {
2699
2826
  let checked = 0;
2700
2827
  const walkProjections = (node) => {
2701
2828
  if (checked > 10) return;
2702
- const proj = _optionalChain([node, 'access', _34 => _34.getContentProjection, 'optionalCall', _35 => _35()]);
2703
- if (_optionalChain([proj, 'optionalAccess', _36 => _36.text]) && proj.selectable !== false) {
2704
- const el = _optionalChain([this, 'access', _37 => _37.contentElements, 'optionalAccess', _38 => _38.get, 'call', _39 => _39(node.id)]);
2829
+ const proj = _optionalChain([node, 'access', _44 => _44.getContentProjection, 'optionalCall', _45 => _45()]);
2830
+ if (_optionalChain([proj, 'optionalAccess', _46 => _46.text]) && proj.selectable !== false) {
2831
+ const el = _optionalChain([this, 'access', _47 => _47.contentElements, 'optionalAccess', _48 => _48.get, 'call', _49 => _49(node.id)]);
2705
2832
  if (el) {
2706
2833
  const projectedText = el.textContent || "";
2707
2834
  if (projectedText !== "" && projectedText !== proj.text) {
@@ -2716,14 +2843,14 @@ var Scene = (_class7 = class _Scene {
2716
2843
  };
2717
2844
  walkProjections(this.root);
2718
2845
  }
2719
- constructor(canvas, options = {}) {;_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);_class7.prototype.__init140.call(this);_class7.prototype.__init141.call(this);_class7.prototype.__init142.call(this);_class7.prototype.__init143.call(this);_class7.prototype.__init144.call(this);_class7.prototype.__init145.call(this);_class7.prototype.__init146.call(this);
2846
+ constructor(canvas, options = {}) {;_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);_class7.prototype.__init140.call(this);_class7.prototype.__init141.call(this);_class7.prototype.__init142.call(this);_class7.prototype.__init143.call(this);_class7.prototype.__init144.call(this);_class7.prototype.__init145.call(this);_class7.prototype.__init146.call(this);_class7.prototype.__init147.call(this);_class7.prototype.__init148.call(this);
2720
2847
  this.canvas = canvas;
2721
2848
  this.debugA11y = _nullishCoalesce(options.debugA11y, () => ( false));
2722
2849
  this.disableWindowResize = _nullishCoalesce(options.disableWindowResize, () => ( false));
2723
2850
  this.maxDPR = options.maxDPR;
2724
2851
  if (this.disableWindowResize) {
2725
- const styleWidth = parseInlinePx(_optionalChain([canvas, 'access', _40 => _40.style, 'optionalAccess', _41 => _41.width]));
2726
- const styleHeight = parseInlinePx(_optionalChain([canvas, 'access', _42 => _42.style, 'optionalAccess', _43 => _43.height]));
2852
+ const styleWidth = parseInlinePx(_optionalChain([canvas, 'access', _50 => _50.style, 'optionalAccess', _51 => _51.width]));
2853
+ const styleHeight = parseInlinePx(_optionalChain([canvas, 'access', _52 => _52.style, 'optionalAccess', _53 => _53.height]));
2727
2854
  this.width = _nullishCoalesce(styleWidth, () => ( (canvas.width || canvas.clientWidth || 0)));
2728
2855
  this.height = _nullishCoalesce(styleHeight, () => ( (canvas.height || canvas.clientHeight || 0)));
2729
2856
  } else {
@@ -2731,10 +2858,11 @@ var Scene = (_class7 = class _Scene {
2731
2858
  this.height = typeof window !== "undefined" ? window.innerHeight : canvas.clientHeight || canvas.height || 600;
2732
2859
  }
2733
2860
  const globalProcess = typeof globalThis !== "undefined" ? globalThis.process : void 0;
2734
- const isTest = globalProcess && (_optionalChain([globalProcess, 'access', _44 => _44.env, 'optionalAccess', _45 => _45.NODE_ENV]) === "test" || _optionalChain([globalProcess, 'access', _46 => _46.env, 'optionalAccess', _47 => _47.VITEST]) === "true");
2861
+ const isTest = globalProcess && (_optionalChain([globalProcess, 'access', _54 => _54.env, 'optionalAccess', _55 => _55.NODE_ENV]) === "test" || _optionalChain([globalProcess, 'access', _56 => _56.env, 'optionalAccess', _57 => _57.VITEST]) === "true");
2735
2862
  this.maxFPS = _nullishCoalesce(options.maxFPS, () => ( (isTest ? 0 : 60)));
2736
2863
  this.respectReducedMotion = _nullishCoalesce(options.respectReducedMotion, () => ( true));
2737
2864
  this.autoThrottle = _nullishCoalesce(options.autoThrottle, () => ( true));
2865
+ this._userTiming = _nullishCoalesce(options.userTiming, () => ( false));
2738
2866
  this.particleBackend = _nullishCoalesce(options.particleBackend, () => ( "auto"));
2739
2867
  this.a11ySyncInterval = _nullishCoalesce(options.a11ySyncInterval, () => ( 0));
2740
2868
  this.contentProjectionEnabled = _nullishCoalesce(options.contentProjection, () => ( true));
@@ -2745,7 +2873,7 @@ var Scene = (_class7 = class _Scene {
2745
2873
  if (typeof window !== "undefined" && typeof window.matchMedia === "function") {
2746
2874
  this.forcedColorsQuery = window.matchMedia("(forced-colors: active)");
2747
2875
  this.forcedColorsChangeHandler = () => this.markDirty();
2748
- _optionalChain([this, 'access', _48 => _48.forcedColorsQuery, 'access', _49 => _49.addEventListener, 'optionalCall', _50 => _50("change", this.forcedColorsChangeHandler)]);
2876
+ _optionalChain([this, 'access', _58 => _58.forcedColorsQuery, 'access', _59 => _59.addEventListener, 'optionalCall', _60 => _60("change", this.forcedColorsChangeHandler)]);
2749
2877
  }
2750
2878
  this.root = new class RootEntity extends _chunkAGP4VLF4js.Entity {
2751
2879
  isPointInside() {
@@ -2767,18 +2895,19 @@ var Scene = (_class7 = class _Scene {
2767
2895
  if (options.renderer) {
2768
2896
  this.renderer = options.renderer;
2769
2897
  } else {
2770
- this.renderer = new (0, _chunkLHONR3GOjs.CanvasRenderer)(
2898
+ this.renderer = new (0, _chunkKEBYJVD6js.CanvasRenderer)(
2771
2899
  canvas,
2772
2900
  this.disableWindowResize ? { width: this.width, height: this.height } : void 0,
2773
2901
  this.maxDPR
2774
2902
  );
2775
2903
  }
2776
- _optionalChain([this, 'access', _51 => _51.renderer, 'access', _52 => _52.onContextRestored, 'optionalCall', _53 => _53(() => {
2904
+ _optionalChain([this, 'access', _61 => _61.renderer, 'access', _62 => _62.onContextRestored, 'optionalCall', _63 => _63(() => {
2777
2905
  this.markDirty();
2778
- if (_optionalChain([this, 'access', _54 => _54.renderer, 'access', _55 => _55.isContextLost, 'optionalCall', _56 => _56()]) !== true) this.render(this.renderer);
2906
+ if (_optionalChain([this, 'access', _64 => _64.renderer, 'access', _65 => _65.isContextLost, 'optionalCall', _66 => _66()]) !== true) this.render(this.renderer);
2779
2907
  })]);
2780
2908
  if (typeof document !== "undefined") {
2781
2909
  this.a11yRoot = document.createElement("div");
2910
+ this.a11yRoot.setAttribute("data-vecto-a11y-root", "");
2782
2911
  this.a11yRoot.style.position = "absolute";
2783
2912
  this.a11yRoot.style.top = "0";
2784
2913
  this.a11yRoot.style.left = "0";
@@ -2944,7 +3073,7 @@ var Scene = (_class7 = class _Scene {
2944
3073
  watchDevicePixelRatio() {
2945
3074
  if (typeof window === "undefined" || typeof window.matchMedia !== "function") return;
2946
3075
  if (this.dprMediaQuery && this.dprChangeHandler) {
2947
- _optionalChain([this, 'access', _57 => _57.dprMediaQuery, 'access', _58 => _58.removeEventListener, 'optionalCall', _59 => _59("change", this.dprChangeHandler)]);
3076
+ _optionalChain([this, 'access', _67 => _67.dprMediaQuery, 'access', _68 => _68.removeEventListener, 'optionalCall', _69 => _69("change", this.dprChangeHandler)]);
2948
3077
  }
2949
3078
  const dpr = window.devicePixelRatio || 1;
2950
3079
  const query = window.matchMedia(`(resolution: ${dpr}dppx)`);
@@ -2952,7 +3081,7 @@ var Scene = (_class7 = class _Scene {
2952
3081
  this.resize(this.width, this.height);
2953
3082
  this.watchDevicePixelRatio();
2954
3083
  };
2955
- _optionalChain([query, 'access', _60 => _60.addEventListener, 'optionalCall', _61 => _61("change", handler)]);
3084
+ _optionalChain([query, 'access', _70 => _70.addEventListener, 'optionalCall', _71 => _71("change", handler)]);
2956
3085
  this.dprMediaQuery = query;
2957
3086
  this.dprChangeHandler = handler;
2958
3087
  }
@@ -2972,7 +3101,7 @@ var Scene = (_class7 = class _Scene {
2972
3101
  if (typeof gl.addEventListener !== "function") return;
2973
3102
  this.glContextLostHandler = (e) => {
2974
3103
  e.preventDefault();
2975
- _optionalChain([this, 'access', _62 => _62.pointRenderer, 'optionalAccess', _63 => _63.destroy, 'call', _64 => _64()]);
3104
+ _optionalChain([this, 'access', _72 => _72.pointRenderer, 'optionalAccess', _73 => _73.destroy, 'call', _74 => _74()]);
2976
3105
  this.pointRenderer = null;
2977
3106
  };
2978
3107
  this.glContextRestoredHandler = () => {
@@ -3002,26 +3131,26 @@ var Scene = (_class7 = class _Scene {
3002
3131
  * to the live DOM selection.
3003
3132
  */
3004
3133
  contentGridSelectionLine(el) {
3005
- const candidates = [_optionalChain([this, 'access', _65 => _65.contentSelectionAnchor, 'optionalAccess', _66 => _66.node])];
3134
+ const candidates = [_optionalChain([this, 'access', _75 => _75.contentSelectionAnchor, 'optionalAccess', _76 => _76.node])];
3006
3135
  if (typeof window !== "undefined" && typeof window.getSelection === "function") {
3007
3136
  const selection = window.getSelection();
3008
- candidates.push(_optionalChain([selection, 'optionalAccess', _67 => _67.anchorNode]), _optionalChain([selection, 'optionalAccess', _68 => _68.focusNode]));
3137
+ candidates.push(_optionalChain([selection, 'optionalAccess', _77 => _77.anchorNode]), _optionalChain([selection, 'optionalAccess', _78 => _78.focusNode]));
3009
3138
  }
3010
3139
  for (const candidate of candidates) {
3011
3140
  if (!candidate || !el.contains(candidate)) continue;
3012
3141
  let cursor = candidate;
3013
3142
  while (cursor && cursor.parentNode !== el) cursor = cursor.parentNode;
3014
- const lineIndex = _optionalChain([cursor, 'optionalAccess', _69 => _69.dataset, 'optionalAccess', _70 => _70.vectoGridLine]);
3143
+ const lineIndex = _optionalChain([cursor, 'optionalAccess', _79 => _79.dataset, 'optionalAccess', _80 => _80.vectoGridLine]);
3015
3144
  if (lineIndex !== void 0) return Number(lineIndex);
3016
3145
  }
3017
3146
  return null;
3018
3147
  }
3019
3148
  releaseContentSelectionForRebuild(el) {
3020
3149
  const selection = typeof window !== "undefined" && typeof window.getSelection === "function" ? window.getSelection() : null;
3021
- const ownsSelection = this.contentSelectionAnchor && el.contains(this.contentSelectionAnchor.node) || (_optionalChain([selection, 'optionalAccess', _71 => _71.anchorNode]) ? el.contains(selection.anchorNode) : false) || (_optionalChain([selection, 'optionalAccess', _72 => _72.focusNode]) ? el.contains(selection.focusNode) : false);
3150
+ const ownsSelection = this.contentSelectionAnchor && el.contains(this.contentSelectionAnchor.node) || (_optionalChain([selection, 'optionalAccess', _81 => _81.anchorNode]) ? el.contains(selection.anchorNode) : false) || (_optionalChain([selection, 'optionalAccess', _82 => _82.focusNode]) ? el.contains(selection.focusNode) : false);
3022
3151
  if (!ownsSelection) return;
3023
3152
  this.endContentSelectionDrag();
3024
- _optionalChain([selection, 'optionalAccess', _73 => _73.removeAllRanges, 'call', _74 => _74()]);
3153
+ _optionalChain([selection, 'optionalAccess', _83 => _83.removeAllRanges, 'call', _84 => _84()]);
3025
3154
  }
3026
3155
  /**
3027
3156
  * Rebuild a content-projection element's DOM (`rebuild`) while preserving a
@@ -3067,7 +3196,7 @@ var Scene = (_class7 = class _Scene {
3067
3196
  if (!anchor || !focus) return;
3068
3197
  try {
3069
3198
  selection.setBaseAndExtent(anchor.node, anchor.offset, focus.node, focus.offset);
3070
- } catch (e9) {
3199
+ } catch (e14) {
3071
3200
  }
3072
3201
  }
3073
3202
  /**
@@ -3080,7 +3209,7 @@ var Scene = (_class7 = class _Scene {
3080
3209
  }
3081
3210
  /** Convert browser viewport coordinates into this Scene's logical coordinates. */
3082
3211
  clientToScene(clientX, clientY) {
3083
- const rect = _optionalChain([this, 'access', _75 => _75.canvas, 'access', _76 => _76.getBoundingClientRect, 'optionalCall', _77 => _77()]);
3212
+ const rect = _optionalChain([this, 'access', _85 => _85.canvas, 'access', _86 => _86.getBoundingClientRect, 'optionalCall', _87 => _87()]);
3084
3213
  if (!rect) return { x: clientX, y: clientY };
3085
3214
  const cssWidth = rect.width || this.canvas.clientWidth || this.width;
3086
3215
  const cssHeight = rect.height || this.canvas.clientHeight || this.height;
@@ -3118,7 +3247,7 @@ var Scene = (_class7 = class _Scene {
3118
3247
  cancelAnimationFrame(calibrationFrame);
3119
3248
  }
3120
3249
  this.contentGridCalibrationFrames.delete(entityId);
3121
- _optionalChain([this, 'access', _78 => _78.contentGridCalibrationProbes, 'access', _79 => _79.get, 'call', _80 => _80(entityId), 'optionalAccess', _81 => _81.remove, 'call', _82 => _82()]);
3250
+ _optionalChain([this, 'access', _88 => _88.contentGridCalibrationProbes, 'access', _89 => _89.get, 'call', _90 => _90(entityId), 'optionalAccess', _91 => _91.remove, 'call', _92 => _92()]);
3122
3251
  this.contentGridCalibrationProbes.delete(entityId);
3123
3252
  delete el.dataset.vectoGridCalibrationPending;
3124
3253
  delete el.dataset.vectoGridCalibration;
@@ -3272,12 +3401,12 @@ var Scene = (_class7 = class _Scene {
3272
3401
  this.canvasResizeObserver = null;
3273
3402
  }
3274
3403
  if (this.dprMediaQuery && this.dprChangeHandler) {
3275
- _optionalChain([this, 'access', _83 => _83.dprMediaQuery, 'access', _84 => _84.removeEventListener, 'optionalCall', _85 => _85("change", this.dprChangeHandler)]);
3404
+ _optionalChain([this, 'access', _93 => _93.dprMediaQuery, 'access', _94 => _94.removeEventListener, 'optionalCall', _95 => _95("change", this.dprChangeHandler)]);
3276
3405
  this.dprMediaQuery = null;
3277
3406
  this.dprChangeHandler = null;
3278
3407
  }
3279
3408
  if (this.forcedColorsQuery && this.forcedColorsChangeHandler) {
3280
- _optionalChain([this, 'access', _86 => _86.forcedColorsQuery, 'access', _87 => _87.removeEventListener, 'optionalCall', _88 => _88("change", this.forcedColorsChangeHandler)]);
3409
+ _optionalChain([this, 'access', _96 => _96.forcedColorsQuery, 'access', _97 => _97.removeEventListener, 'optionalCall', _98 => _98("change", this.forcedColorsChangeHandler)]);
3281
3410
  this.forcedColorsQuery = null;
3282
3411
  this.forcedColorsChangeHandler = null;
3283
3412
  }
@@ -3295,9 +3424,9 @@ var Scene = (_class7 = class _Scene {
3295
3424
  }
3296
3425
  this.pointerEventTarget = null;
3297
3426
  }
3298
- _optionalChain([this, 'access', _89 => _89.a11yRoot, 'optionalAccess', _90 => _90.remove, 'call', _91 => _91()]);
3427
+ _optionalChain([this, 'access', _99 => _99.a11yRoot, 'optionalAccess', _100 => _100.remove, 'call', _101 => _101()]);
3299
3428
  this.focusSentinel = null;
3300
- _optionalChain([this, 'access', _92 => _92.portalRoot, 'optionalAccess', _93 => _93.remove, 'call', _94 => _94()]);
3429
+ _optionalChain([this, 'access', _102 => _102.portalRoot, 'optionalAccess', _103 => _103.remove, 'call', _104 => _104()]);
3301
3430
  this.a11yElements.clear();
3302
3431
  for (const el of this.contentElements.values()) el.remove();
3303
3432
  this.contentElements.clear();
@@ -3320,10 +3449,10 @@ var Scene = (_class7 = class _Scene {
3320
3449
  }
3321
3450
  this.glContextLostHandler = null;
3322
3451
  this.glContextRestoredHandler = null;
3323
- _optionalChain([this, 'access', _95 => _95.pointRenderer, 'optionalAccess', _96 => _96.destroy, 'call', _97 => _97()]);
3324
- _optionalChain([this, 'access', _98 => _98.renderer, 'access', _99 => _99.dispose, 'optionalCall', _100 => _100()]);
3325
- _optionalChain([this, 'access', _101 => _101.glCanvas, 'optionalAccess', _102 => _102.remove, 'call', _103 => _103()]);
3326
- _optionalChain([this, 'access', _104 => _104.gpuCanvas, 'optionalAccess', _105 => _105.remove, 'call', _106 => _106()]);
3452
+ _optionalChain([this, 'access', _105 => _105.pointRenderer, 'optionalAccess', _106 => _106.destroy, 'call', _107 => _107()]);
3453
+ _optionalChain([this, 'access', _108 => _108.renderer, 'access', _109 => _109.dispose, 'optionalCall', _110 => _110()]);
3454
+ _optionalChain([this, 'access', _111 => _111.glCanvas, 'optionalAccess', _112 => _112.remove, 'call', _113 => _113()]);
3455
+ _optionalChain([this, 'access', _114 => _114.gpuCanvas, 'optionalAccess', _115 => _115.remove, 'call', _116 => _116()]);
3327
3456
  this.gpuCanvas = null;
3328
3457
  this.gpuContext = null;
3329
3458
  if (this.recoveryTimerId) {
@@ -3335,7 +3464,7 @@ var Scene = (_class7 = class _Scene {
3335
3464
  this.manager = null;
3336
3465
  }
3337
3466
  if (this.device) {
3338
- _optionalChain([this, 'access', _107 => _107.device, 'access', _108 => _108.destroy, 'optionalCall', _109 => _109()]);
3467
+ _optionalChain([this, 'access', _117 => _117.device, 'access', _118 => _118.destroy, 'optionalCall', _119 => _119()]);
3339
3468
  this.device = null;
3340
3469
  }
3341
3470
  }
@@ -3631,7 +3760,7 @@ var Scene = (_class7 = class _Scene {
3631
3760
  shouldProjectA11y(node) {
3632
3761
  return node.interactive && (node.width > 0 || node.a11yFullViewport);
3633
3762
  }
3634
- syncA11y(node) {
3763
+ syncA11y(node, container = null) {
3635
3764
  if (!this.a11yRoot) return;
3636
3765
  if (node.isDOMPortal) {
3637
3766
  return;
@@ -3641,6 +3770,7 @@ var Scene = (_class7 = class _Scene {
3641
3770
  return;
3642
3771
  }
3643
3772
  const nodeStart = this._phaseTiming ? performance.now() : 0;
3773
+ let childContainer = container;
3644
3774
  if (this.shouldProjectA11y(node)) {
3645
3775
  let el = this.a11yElements.get(node.id);
3646
3776
  const attrs = node.getA11yAttributes();
@@ -3653,9 +3783,9 @@ var Scene = (_class7 = class _Scene {
3653
3783
  this.caretBlinkTimer = null;
3654
3784
  }
3655
3785
  }
3656
- if (el.parentNode === this.a11yRoot) {
3786
+ if (el.parentNode) {
3657
3787
  this.preserveFocusOnRemoval(el);
3658
- this.a11yRoot.removeChild(el);
3788
+ el.remove();
3659
3789
  }
3660
3790
  this.a11yElements.delete(node.id);
3661
3791
  el = void 0;
@@ -3767,7 +3897,7 @@ var Scene = (_class7 = class _Scene {
3767
3897
  el.addEventListener("compositionupdate", (e) => {
3768
3898
  const data = _nullishCoalesce(e.data, () => ( ""));
3769
3899
  composition = {
3770
- start: _nullishCoalesce(_optionalChain([composition, 'optionalAccess', _110 => _110.start]), () => ( 0)),
3900
+ start: _nullishCoalesce(_optionalChain([composition, 'optionalAccess', _120 => _120.start]), () => ( 0)),
3771
3901
  length: data.length
3772
3902
  };
3773
3903
  forward();
@@ -3840,7 +3970,7 @@ var Scene = (_class7 = class _Scene {
3840
3970
  this.syncOptionalAttribute(
3841
3971
  el,
3842
3972
  "href",
3843
- attrs.href === void 0 ? void 0 : _chunkLHONR3GOjs.sanitizeUrl.call(void 0, attrs.href)
3973
+ attrs.href === void 0 ? void 0 : _chunkKEBYJVD6js.sanitizeUrl.call(void 0, attrs.href)
3844
3974
  );
3845
3975
  this.syncOptionalAttribute(el, "target", attrs.target);
3846
3976
  }
@@ -3963,6 +4093,7 @@ var Scene = (_class7 = class _Scene {
3963
4093
  if (el.style.boxSizing !== "border-box") el.style.boxSizing = "border-box";
3964
4094
  if (el instanceof HTMLTextAreaElement) el.style.resize = "none";
3965
4095
  }
4096
+ const nestedIn = container && attrs.role && container.owned.has(attrs.role) ? container : null;
3966
4097
  if (node.a11yFullViewport) {
3967
4098
  el.style.left = "0px";
3968
4099
  el.style.top = "0px";
@@ -3973,11 +4104,36 @@ var Scene = (_class7 = class _Scene {
3973
4104
  } else {
3974
4105
  const worldTf = node.getWorldTransform();
3975
4106
  const { a, b, c, d, e, f } = worldTf;
3976
- el.style.left = `${e + node.a11yOffsetX}px`;
3977
- el.style.top = `${f + node.a11yOffsetY}px`;
4107
+ const originX = e + node.a11yOffsetX;
4108
+ const originY = f + node.a11yOffsetY;
4109
+ const parentEl = nestedIn && nestedIn.el !== el && nestedIn.el.isConnected ? nestedIn.el : this.a11yRoot;
4110
+ if (el.parentNode !== parentEl) {
4111
+ parentEl.appendChild(el);
4112
+ this.a11yNeedsReorder = true;
4113
+ }
4114
+ if (parentEl === this.a11yRoot) {
4115
+ el.style.left = `${originX}px`;
4116
+ el.style.top = `${originY}px`;
4117
+ el.style.transform = `matrix(${a}, ${b}, ${c}, ${d}, 0, 0)`;
4118
+ } else {
4119
+ const box = rebaseChildBox(
4120
+ nestedIn.transform,
4121
+ nestedIn.originX,
4122
+ nestedIn.originY,
4123
+ worldTf,
4124
+ originX,
4125
+ originY
4126
+ );
4127
+ el.style.left = `${box.left}px`;
4128
+ el.style.top = `${box.top}px`;
4129
+ el.style.transform = box.matrix;
4130
+ }
3978
4131
  el.style.width = `${node.width}px`;
3979
4132
  el.style.height = `${node.height}px`;
3980
- el.style.transform = `matrix(${a}, ${b}, ${c}, ${d}, 0, 0)`;
4133
+ const owned = attrs.role ? A11Y_REQUIRED_OWNED.get(attrs.role) : void 0;
4134
+ if (owned) {
4135
+ childContainer = { el, owned, transform: worldTf, originX, originY };
4136
+ }
3981
4137
  const visible = this.projectionBoxVisible(node, worldTf, 0);
3982
4138
  const display = visible ? "" : "none";
3983
4139
  if (el.style.display !== display) el.style.display = display;
@@ -3991,9 +4147,9 @@ var Scene = (_class7 = class _Scene {
3991
4147
  } else {
3992
4148
  this.syncContentProjection(node);
3993
4149
  }
3994
- for (const child of node.children) this.syncA11y(child);
4150
+ for (const child of node.children) this.syncA11y(child, childContainer);
3995
4151
  if (node === this.root) {
3996
- for (const overlay of this.overlayRoot.children) this.syncA11y(overlay);
4152
+ for (const overlay of this.overlayRoot.children) this.syncA11y(overlay, null);
3997
4153
  }
3998
4154
  }
3999
4155
  /**
@@ -4220,9 +4376,9 @@ var Scene = (_class7 = class _Scene {
4220
4376
  for (let lineIndex = 0; lineIndex < grid.lines.length; lineIndex++) {
4221
4377
  const gridLine = grid.lines[lineIndex];
4222
4378
  const projectedLine = projectionLines[lineIndex];
4223
- const lineHeight = _nullishCoalesce(_optionalChain([projectedLine, 'optionalAccess', _111 => _111.lineHeight]), () => ( grid.lineHeight));
4224
- const baseline = _nullishCoalesce(_optionalChain([projectedLine, 'optionalAccess', _112 => _112.baseline]), () => ( grid.baseline));
4225
- const lineFont = _nullishCoalesce(_optionalChain([projectedLine, 'optionalAccess', _113 => _113.font]), () => ( grid.font));
4379
+ const lineHeight = _nullishCoalesce(_optionalChain([projectedLine, 'optionalAccess', _121 => _121.lineHeight]), () => ( grid.lineHeight));
4380
+ const baseline = _nullishCoalesce(_optionalChain([projectedLine, 'optionalAccess', _122 => _122.baseline]), () => ( grid.baseline));
4381
+ const lineFont = _nullishCoalesce(_optionalChain([projectedLine, 'optionalAccess', _123 => _123.font]), () => ( grid.font));
4226
4382
  const lineSignature = contentGridLineSignature(
4227
4383
  grid,
4228
4384
  gridLine,
@@ -4242,8 +4398,8 @@ var Scene = (_class7 = class _Scene {
4242
4398
  lineElement.dir = "ltr";
4243
4399
  lineElement.dataset.vectoGridLine = `${lineIndex}`;
4244
4400
  lineElement.style.position = "absolute";
4245
- lineElement.style.left = `${_nullishCoalesce(_optionalChain([projectedLine, 'optionalAccess', _114 => _114.x]), () => ( 0))}px`;
4246
- lineElement.style.top = `${(_nullishCoalesce(_optionalChain([projectedLine, 'optionalAccess', _115 => _115.y]), () => ( lineIndex * grid.lineHeight))) + baseline - _text.cssLineBoxBaseline.call(void 0, lineFont, lineHeight)}px`;
4401
+ lineElement.style.left = `${_nullishCoalesce(_optionalChain([projectedLine, 'optionalAccess', _124 => _124.x]), () => ( 0))}px`;
4402
+ lineElement.style.top = `${(_nullishCoalesce(_optionalChain([projectedLine, 'optionalAccess', _125 => _125.y]), () => ( lineIndex * grid.lineHeight))) + baseline - _text.cssLineBoxBaseline.call(void 0, lineFont, lineHeight)}px`;
4247
4403
  lineElement.style.width = `${gridLine.width}px`;
4248
4404
  lineElement.style.height = `${lineHeight}px`;
4249
4405
  lineElement.style.whiteSpace = "pre";
@@ -4313,7 +4469,7 @@ var Scene = (_class7 = class _Scene {
4313
4469
  if (selectionLine !== null && selectionLine >= grid.lines.length) {
4314
4470
  rebuiltSelectionLine = true;
4315
4471
  }
4316
- _optionalChain([el, 'access', _116 => _116.lastElementChild, 'optionalAccess', _117 => _117.remove, 'call', _118 => _118()]);
4472
+ _optionalChain([el, 'access', _126 => _126.lastElementChild, 'optionalAccess', _127 => _127.remove, 'call', _128 => _128()]);
4317
4473
  }
4318
4474
  if (rebuiltSelectionLine) this.releaseContentSelectionForRebuild(el);
4319
4475
  el.dataset.vectoProjectionLines = signature;
@@ -4377,7 +4533,7 @@ var Scene = (_class7 = class _Scene {
4377
4533
  if (previous !== void 0 && typeof cancelAnimationFrame === "function") {
4378
4534
  cancelAnimationFrame(previous);
4379
4535
  }
4380
- _optionalChain([this, 'access', _119 => _119.contentGridCalibrationProbes, 'access', _120 => _120.get, 'call', _121 => _121(entityId), 'optionalAccess', _122 => _122.remove, 'call', _123 => _123()]);
4536
+ _optionalChain([this, 'access', _129 => _129.contentGridCalibrationProbes, 'access', _130 => _130.get, 'call', _131 => _131(entityId), 'optionalAccess', _132 => _132.remove, 'call', _133 => _133()]);
4381
4537
  this.contentGridCalibrationProbes.delete(entityId);
4382
4538
  const calibrationStart = typeof performance !== "undefined" ? performance.now() : 0;
4383
4539
  const probe = document.createElement("div");
@@ -4411,7 +4567,7 @@ var Scene = (_class7 = class _Scene {
4411
4567
  target.dataset.vectoGridCalib = generation;
4412
4568
  continue;
4413
4569
  }
4414
- const sourceText = _nullishCoalesce(_optionalChain([target, 'access', _124 => _124.textContent, 'optionalAccess', _125 => _125.slice, 'call', _126 => _126(0, sourceLength)]), () => ( ""));
4570
+ const sourceText = _nullishCoalesce(_optionalChain([target, 'access', _134 => _134.textContent, 'optionalAccess', _135 => _135.slice, 'call', _136 => _136(0, sourceLength)]), () => ( ""));
4415
4571
  if (!sourceText) {
4416
4572
  target.dataset.vectoGridCalib = generation;
4417
4573
  continue;
@@ -4551,9 +4707,9 @@ var Scene = (_class7 = class _Scene {
4551
4707
  this.caretBlinkTimer = null;
4552
4708
  }
4553
4709
  }
4554
- if (el.parentNode === this.a11yRoot) {
4710
+ if (el.parentNode) {
4555
4711
  this.preserveFocusOnRemoval(el);
4556
- this.a11yRoot.removeChild(el);
4712
+ el.remove();
4557
4713
  }
4558
4714
  this.a11yElements.delete(id);
4559
4715
  }
@@ -4566,23 +4722,39 @@ var Scene = (_class7 = class _Scene {
4566
4722
  const fullLen = this.fullViewportElements.length;
4567
4723
  const normalLen = this.normalElements.length;
4568
4724
  const totalLen = fullLen + normalLen;
4725
+ this.a11yOrderCursors.clear();
4569
4726
  for (let i = 0; i < totalLen; i++) {
4570
4727
  const expected = i < fullLen ? this.fullViewportElements[i] : this.normalElements[i - fullLen];
4571
- const current = this.a11yRoot.childNodes[i];
4728
+ const parent = expected.parentNode;
4729
+ if (!parent) continue;
4730
+ const at = _nullishCoalesce(this.a11yOrderCursors.get(parent), () => ( 0));
4731
+ this.a11yOrderCursors.set(parent, at + 1);
4732
+ const current = parent.childNodes[at];
4572
4733
  if (current !== expected) {
4573
- this.a11yRoot.insertBefore(expected, current || null);
4734
+ parent.insertBefore(expected, current || null);
4574
4735
  }
4575
4736
  }
4576
4737
  this.a11yNeedsReorder = false;
4577
4738
  }
4578
4739
  /**
4579
4740
  * Reorder `normalElements` (in place) into visual reading order using the
4580
- * world positions `syncA11y` already wrote to each element's inline style
4741
+ * positions `syncA11y` already wrote to each element's inline style
4581
4742
  * (`top`/`left`/`height`). Elements are grouped into rows top-to-bottom (an
4582
4743
  * element belongs to the current row while its top is above the row's
4583
4744
  * running bottom edge), then sorted within a row by `left` — ascending for
4584
4745
  * `'ltr'`, descending for `'rtl'`. The sort is stable, so entities at the
4585
4746
  * same position keep their scene-graph (collection) order as a tiebreak.
4747
+ *
4748
+ * Those inline values are world coordinates for a top-level mirror but
4749
+ * PARENT-RELATIVE for a nested one, so this list mixes coordinate spaces.
4750
+ * That is sound because the result is only ever applied per DOM parent
4751
+ * ({@link enforceA11yDomOrder} advances a cursor per parent), and all of one
4752
+ * parent's children share one space: a `grid`'s rows are all grid-relative, a
4753
+ * `row`'s cells all row-relative. Comparisons ACROSS spaces do happen while
4754
+ * banding, but they only affect the relative order of elements in different
4755
+ * parents, which no `insertBefore` ever acts on. Normalizing everything back
4756
+ * to world coordinates here would cost a transform per element per frame to
4757
+ * change nothing observable.
4586
4758
  */
4587
4759
  sortNormalElementsVisually() {
4588
4760
  const els = this.normalElements;
@@ -4622,12 +4794,12 @@ var Scene = (_class7 = class _Scene {
4622
4794
  syncOverlayGeometry() {
4623
4795
  const parent = this.canvas.parentElement;
4624
4796
  if (!parent) return;
4625
- const canvasRect = _optionalChain([this, 'access', _127 => _127.canvas, 'access', _128 => _128.getBoundingClientRect, 'optionalCall', _129 => _129()]);
4626
- const parentRect = _optionalChain([parent, 'access', _130 => _130.getBoundingClientRect, 'optionalCall', _131 => _131()]);
4627
- const cssWidth = _optionalChain([canvasRect, 'optionalAccess', _132 => _132.width]) || this.canvas.clientWidth || this.width;
4628
- const cssHeight = _optionalChain([canvasRect, 'optionalAccess', _133 => _133.height]) || this.canvas.clientHeight || this.height;
4629
- const left = (_nullishCoalesce(_optionalChain([canvasRect, 'optionalAccess', _134 => _134.left]), () => ( 0))) - (_nullishCoalesce(_optionalChain([parentRect, 'optionalAccess', _135 => _135.left]), () => ( 0))) - (parent.clientLeft || 0) + parent.scrollLeft;
4630
- const top = (_nullishCoalesce(_optionalChain([canvasRect, 'optionalAccess', _136 => _136.top]), () => ( 0))) - (_nullishCoalesce(_optionalChain([parentRect, 'optionalAccess', _137 => _137.top]), () => ( 0))) - (parent.clientTop || 0) + parent.scrollTop;
4797
+ const canvasRect = _optionalChain([this, 'access', _137 => _137.canvas, 'access', _138 => _138.getBoundingClientRect, 'optionalCall', _139 => _139()]);
4798
+ const parentRect = _optionalChain([parent, 'access', _140 => _140.getBoundingClientRect, 'optionalCall', _141 => _141()]);
4799
+ const cssWidth = _optionalChain([canvasRect, 'optionalAccess', _142 => _142.width]) || this.canvas.clientWidth || this.width;
4800
+ const cssHeight = _optionalChain([canvasRect, 'optionalAccess', _143 => _143.height]) || this.canvas.clientHeight || this.height;
4801
+ const left = (_nullishCoalesce(_optionalChain([canvasRect, 'optionalAccess', _144 => _144.left]), () => ( 0))) - (_nullishCoalesce(_optionalChain([parentRect, 'optionalAccess', _145 => _145.left]), () => ( 0))) - (parent.clientLeft || 0) + parent.scrollLeft;
4802
+ const top = (_nullishCoalesce(_optionalChain([canvasRect, 'optionalAccess', _146 => _146.top]), () => ( 0))) - (_nullishCoalesce(_optionalChain([parentRect, 'optionalAccess', _147 => _147.top]), () => ( 0))) - (parent.clientTop || 0) + parent.scrollTop;
4631
4803
  const scaleX = this.width > 0 ? cssWidth / this.width : 1;
4632
4804
  const scaleY = this.height > 0 ? cssHeight / this.height : 1;
4633
4805
  const prev = this._overlayGeometry;
@@ -4766,7 +4938,7 @@ var Scene = (_class7 = class _Scene {
4766
4938
  * (and {@link respectReducedMotion} is on). `0` means uncapped.
4767
4939
  */
4768
4940
  effectiveMaxFPS() {
4769
- const reduced = this.respectReducedMotion && !!_optionalChain([this, 'access', _138 => _138.reducedMotionQuery, 'optionalAccess', _139 => _139.matches]);
4941
+ const reduced = this.respectReducedMotion && !!_optionalChain([this, 'access', _148 => _148.reducedMotionQuery, 'optionalAccess', _149 => _149.matches]);
4770
4942
  if (reduced)
4771
4943
  return this.maxFPS > 0 ? Math.min(this.maxFPS, REDUCED_MOTION_FPS) : REDUCED_MOTION_FPS;
4772
4944
  return this.maxFPS;
@@ -4818,9 +4990,11 @@ var Scene = (_class7 = class _Scene {
4818
4990
  if ((hasInteractive || this.a11yElements.size > 0 || wantsContentSync) && (shouldSyncInterval || this.a11yPendingSyncAfterAnimation)) {
4819
4991
  this.lastA11ySync = time;
4820
4992
  if (hasInteractive || wantsContentSync) {
4993
+ const userTiming = this._userTiming ? beginVectoUserTiming(VECTO_USER_TIMING.scene.a11ySync) : null;
4821
4994
  const t0 = this._phaseTiming ? performance.now() : 0;
4822
4995
  this.syncA11y(this.root);
4823
4996
  if (this._phaseTiming) this._recordPhase("a11ySync", performance.now() - t0);
4997
+ if (userTiming) endVectoUserTiming(userTiming);
4824
4998
  }
4825
4999
  const t1 = this._phaseTiming ? performance.now() : 0;
4826
5000
  this.enforceA11yDomOrder();
@@ -4834,12 +5008,32 @@ var Scene = (_class7 = class _Scene {
4834
5008
  /**
4835
5009
  * Render the entire scene graph onto the specified renderer.
4836
5010
  *
5011
+ * Main-frame causal order is a correctness contract:
5012
+ *
5013
+ * 1. Browser/input callbacks finish before the scheduled frame begins.
5014
+ * 2. Batched property drivers and particle simulation advance.
5015
+ * 3. Entity `update()` hooks run.
5016
+ * 4. Transform inputs are gathered and world matrices are composed.
5017
+ * 5. Updated world bounds are tested for culling.
5018
+ * 6. Visible entities paint in scene-graph order.
5019
+ * 7. Canvas/GPU batches flush and retained renderers present.
5020
+ * 8. The rAF loop synchronizes content and accessibility projections after
5021
+ * this method returns.
5022
+ *
5023
+ * The causal order is fixed; physical walks may stay fused. The JavaScript
5024
+ * transform path interleaves update → compose → cull → paint per node in
5025
+ * pre-order. The WASM path updates the whole tree first, then gathers and
5026
+ * composes it in one store pass before the same cull/paint walk. Both must
5027
+ * expose an update's transform mutation in that same rendered frame.
5028
+ * Secondary renderers are read-only snapshots: they skip simulation and
5029
+ * updates, then compose/cull/paint/flush the current state.
5030
+ *
4837
5031
  * @param renderer - The renderer instance to draw to.
4838
5032
  * @param dt - Delta time in milliseconds (default 0).
4839
5033
  * @param time - Current absolute time in milliseconds (default 0).
4840
5034
  */
4841
5035
  render(renderer, dt = 0, time = 0) {
4842
- if (_optionalChain([renderer, 'access', _140 => _140.isContextLost, 'optionalCall', _141 => _141()])) return;
5036
+ if (_optionalChain([renderer, 'access', _150 => _150.isContextLost, 'optionalCall', _151 => _151()])) return;
4843
5037
  const isMainRenderer = renderer === this.renderer;
4844
5038
  if (isMainRenderer && this.a11yRoot && this.canvas.parentElement) {
4845
5039
  const parentStyle = this.canvas.parentElement.style;
@@ -4983,7 +5177,7 @@ var Scene = (_class7 = class _Scene {
4983
5177
  }
4984
5178
  renderer.clear();
4985
5179
  if (isMainRenderer) {
4986
- _optionalChain([this, 'access', _142 => _142.pointRenderer, 'optionalAccess', _143 => _143.begin, 'call', _144 => _144()]);
5180
+ _optionalChain([this, 'access', _152 => _152.pointRenderer, 'optionalAccess', _153 => _153.begin, 'call', _154 => _154()]);
4987
5181
  }
4988
5182
  const vw = this.width;
4989
5183
  const vh = this.height;
@@ -5019,10 +5213,13 @@ var Scene = (_class7 = class _Scene {
5019
5213
  updateWalk(this.root);
5020
5214
  for (const overlay of this.overlayRoot.children) updateWalk(overlay);
5021
5215
  }
5216
+ const transformTiming = this._userTiming ? beginVectoUserTiming(VECTO_USER_TIMING.scene.transform) : null;
5022
5217
  const wasmT0 = this._phaseTiming ? performance.now() : 0;
5023
5218
  const wasmWorld = wasmMain ? this._syncWasmStore() : null;
5024
5219
  if (this._phaseTiming) this._recordPhase("transform", performance.now() - wasmT0);
5220
+ if (transformTiming) endVectoUserTiming(transformTiming);
5025
5221
  const wasmSlotEntity = this._slotEntity;
5222
+ let userEntityPaintMs = 0;
5026
5223
  const renderNode = (node, pa, pb, pc, pd, pe, pf, parentOpacity) => {
5027
5224
  if (isMainRenderer && !wasmMain) {
5028
5225
  runUpdate(node);
@@ -5151,10 +5348,15 @@ var Scene = (_class7 = class _Scene {
5151
5348
  );
5152
5349
  }
5153
5350
  } else {
5154
- if (this._phaseTiming) {
5351
+ if (this._userTiming || this._phaseTiming) {
5155
5352
  const t0 = performance.now();
5156
- node.render(renderer);
5157
- this._recordPhase("entityPaint", performance.now() - t0);
5353
+ try {
5354
+ node.render(renderer);
5355
+ } finally {
5356
+ const elapsed = performance.now() - t0;
5357
+ if (this._userTiming) userEntityPaintMs += elapsed;
5358
+ if (this._phaseTiming) this._recordPhase("entityPaint", elapsed);
5359
+ }
5158
5360
  } else {
5159
5361
  node.render(renderer);
5160
5362
  }
@@ -5169,24 +5371,31 @@ var Scene = (_class7 = class _Scene {
5169
5371
  renderer.flush();
5170
5372
  renderer.restore();
5171
5373
  };
5374
+ const drawTiming = this._userTiming ? beginVectoUserTiming(VECTO_USER_TIMING.scene.drawWalk) : null;
5172
5375
  const drawT0 = this._phaseTiming ? performance.now() : 0;
5173
5376
  renderNode(this.root, 1, 0, 0, 1, 0, 0, 1);
5174
5377
  for (const overlay of this.overlayRoot.children) {
5175
5378
  renderNode(overlay, 1, 0, 0, 1, 0, 0, 1);
5176
5379
  }
5177
5380
  if (this._phaseTiming) this._recordPhase("drawWalk", performance.now() - drawT0);
5381
+ if (drawTiming) endVectoUserTiming(drawTiming);
5382
+ if (this._userTiming) {
5383
+ measureVectoUserTiming(VECTO_USER_TIMING.scene.entityPaint, userEntityPaintMs);
5384
+ }
5178
5385
  if (isMainRenderer) {
5179
5386
  this.frameHadAnimation = walkHadAnimation;
5180
5387
  this.frameHadInteractive = walkHadInteractive;
5181
5388
  this.reconcilePortals();
5182
5389
  }
5390
+ const flushTiming = this._userTiming ? beginVectoUserTiming(VECTO_USER_TIMING.scene.flush) : null;
5183
5391
  const flushT0 = this._phaseTiming ? performance.now() : 0;
5184
5392
  renderer.flush();
5185
5393
  if (isMainRenderer) {
5186
- _optionalChain([this, 'access', _145 => _145.pointRenderer, 'optionalAccess', _146 => _146.flush, 'call', _147 => _147()]);
5394
+ _optionalChain([this, 'access', _155 => _155.pointRenderer, 'optionalAccess', _156 => _156.flush, 'call', _157 => _157()]);
5187
5395
  }
5188
- _optionalChain([renderer, 'access', _148 => _148.present, 'optionalCall', _149 => _149()]);
5396
+ _optionalChain([renderer, 'access', _158 => _158.present, 'optionalCall', _159 => _159()]);
5189
5397
  if (this._phaseTiming) this._recordPhase("flush", performance.now() - flushT0);
5398
+ if (flushTiming) endVectoUserTiming(flushTiming);
5190
5399
  if (this._devActive) {
5191
5400
  this._devFrameCount++;
5192
5401
  this._devRunChecks();
@@ -5196,7 +5405,7 @@ var Scene = (_class7 = class _Scene {
5196
5405
  * Export the current scene state to a lightweight, flat SVG XML string.
5197
5406
  */
5198
5407
  toSVG() {
5199
- const renderer = new (0, _chunkLHONR3GOjs.SVGRenderer)(this.width, this.height);
5408
+ const renderer = new (0, _chunkKEBYJVD6js.SVGRenderer)(this.width, this.height);
5200
5409
  this.render(renderer, 0, 0);
5201
5410
  return renderer.toXMLString();
5202
5411
  }
@@ -5278,7 +5487,7 @@ var Scene = (_class7 = class _Scene {
5278
5487
  });
5279
5488
  pass.end();
5280
5489
  this.device.queue.submit([encoder.finish()]);
5281
- } catch (e10) {
5490
+ } catch (e15) {
5282
5491
  }
5283
5492
  this.gpuHasContent = false;
5284
5493
  }
@@ -5465,8 +5674,8 @@ function pointInBounds(b, x, y) {
5465
5674
  function contentGridLineSignature(grid, line, projected, lineHeight, baseline, font, isFirstLine) {
5466
5675
  const parts = [
5467
5676
  // Line box: position, size, and the font that resolves its baseline.
5468
- `${_nullishCoalesce(_optionalChain([projected, 'optionalAccess', _150 => _150.x]), () => ( 0))}`,
5469
- `${_nullishCoalesce(_optionalChain([projected, 'optionalAccess', _151 => _151.y]), () => ( ""))}`,
5677
+ `${_nullishCoalesce(_optionalChain([projected, 'optionalAccess', _160 => _160.x]), () => ( 0))}`,
5678
+ `${_nullishCoalesce(_optionalChain([projected, 'optionalAccess', _161 => _161.y]), () => ( ""))}`,
5470
5679
  `${lineHeight}`,
5471
5680
  `${baseline}`,
5472
5681
  font,
@@ -5513,15 +5722,15 @@ var TextEntity = (_class8 = class extends _chunkAGP4VLF4js.Entity {
5513
5722
 
5514
5723
 
5515
5724
 
5516
- __init147() {this.nodes = []}
5725
+ __init149() {this.nodes = []}
5517
5726
 
5518
- __init148() {this.fillStyle = "#94a3b8"}
5519
- __init149() {this.strokeStyle = null}
5520
- __init150() {this.hoveredFillStyle = "#ffffff"}
5521
- __init151() {this.lineWidth = 1}
5522
- __init152() {this.isHovered = false}
5727
+ __init150() {this.fillStyle = "#94a3b8"}
5728
+ __init151() {this.strokeStyle = null}
5729
+ __init152() {this.hoveredFillStyle = "#ffffff"}
5730
+ __init153() {this.lineWidth = 1}
5731
+ __init154() {this.isHovered = false}
5523
5732
  constructor(text, atlas, maxWidth, fontSize = 24) {
5524
- super();_class8.prototype.__init147.call(this);_class8.prototype.__init148.call(this);_class8.prototype.__init149.call(this);_class8.prototype.__init150.call(this);_class8.prototype.__init151.call(this);_class8.prototype.__init152.call(this);;
5733
+ super();_class8.prototype.__init149.call(this);_class8.prototype.__init150.call(this);_class8.prototype.__init151.call(this);_class8.prototype.__init152.call(this);_class8.prototype.__init153.call(this);_class8.prototype.__init154.call(this);;
5525
5734
  this.text = text;
5526
5735
  this.atlas = atlas;
5527
5736
  this.fontSize = fontSize;
@@ -5636,15 +5845,15 @@ var TextEntity = (_class8 = class extends _chunkAGP4VLF4js.Entity {
5636
5845
  // src/components/GridTextEntity.ts
5637
5846
  var GridTextEntity = (_class9 = class extends _chunkAGP4VLF4js.Entity {
5638
5847
 
5639
- __init153() {this.fillStyle = "#ffffff"}
5640
- __init154() {this.grid = []}
5848
+ __init155() {this.fillStyle = "#ffffff"}
5849
+ __init156() {this.grid = []}
5641
5850
  // Array of rows
5642
- __init155() {this.cols = 0}
5643
- __init156() {this.rows = 0}
5851
+ __init157() {this.cols = 0}
5852
+ __init158() {this.rows = 0}
5644
5853
 
5645
5854
 
5646
5855
  constructor(_atlas, fontSize = 10) {
5647
- super();_class9.prototype.__init153.call(this);_class9.prototype.__init154.call(this);_class9.prototype.__init155.call(this);_class9.prototype.__init156.call(this);;
5856
+ super();_class9.prototype.__init155.call(this);_class9.prototype.__init156.call(this);_class9.prototype.__init157.call(this);_class9.prototype.__init158.call(this);;
5648
5857
  this.fontSize = fontSize;
5649
5858
  this.charWidth = fontSize * 1;
5650
5859
  this.charHeight = fontSize * 1.1;
@@ -5653,7 +5862,7 @@ var GridTextEntity = (_class9 = class extends _chunkAGP4VLF4js.Entity {
5653
5862
  updateGrid(ascii) {
5654
5863
  this.grid = ascii;
5655
5864
  this.rows = ascii.length;
5656
- this.cols = _optionalChain([ascii, 'access', _152 => _152[0], 'optionalAccess', _153 => _153.length]) || 0;
5865
+ this.cols = _optionalChain([ascii, 'access', _162 => _162[0], 'optionalAccess', _163 => _163.length]) || 0;
5657
5866
  }
5658
5867
  isPointInside(_globalX, _globalY) {
5659
5868
  return false;
@@ -5736,23 +5945,23 @@ var SplineEntity = (_class10 = class extends _chunkAGP4VLF4js.Entity {
5736
5945
 
5737
5946
 
5738
5947
 
5739
- __init157() {this.offscreen = null}
5740
- __init158() {this.baked = false}
5948
+ __init159() {this.offscreen = null}
5949
+ __init160() {this.baked = false}
5741
5950
  /** Logical (CSS-pixel) size of the baked bitmap — the blit destination size. */
5742
- __init159() {this.bakedWidth = 0}
5743
- __init160() {this.bakedHeight = 0}
5951
+ __init161() {this.bakedWidth = 0}
5952
+ __init162() {this.bakedHeight = 0}
5744
5953
  /** Gradient strokes can't be baked to a solid-color bitmap; they render per-frame. */
5745
5954
 
5746
5955
  /** Lazily-flattened polylines (one Float32Array of [x,y,...] per segment) for hit-testing. */
5747
- __init161() {this.polylines = null}
5956
+ __init163() {this.polylines = null}
5748
5957
  /**
5749
5958
  * When `true`, the renderer draws a rounded-rect outline of the entity's
5750
5959
  * local bounds after painting the curves. Useful for drag feedback and
5751
5960
  * debugging hit areas. Defaults to `false`.
5752
5961
  */
5753
- __init162() {this.showBounds = false}
5962
+ __init164() {this.showBounds = false}
5754
5963
  constructor(doc, opts = {}) {
5755
- super();_class10.prototype.__init157.call(this);_class10.prototype.__init158.call(this);_class10.prototype.__init159.call(this);_class10.prototype.__init160.call(this);_class10.prototype.__init161.call(this);_class10.prototype.__init162.call(this);;
5964
+ super();_class10.prototype.__init159.call(this);_class10.prototype.__init160.call(this);_class10.prototype.__init161.call(this);_class10.prototype.__init162.call(this);_class10.prototype.__init163.call(this);_class10.prototype.__init164.call(this);;
5756
5965
  this.doc = doc;
5757
5966
  this.lineWidth = _nullishCoalesce(opts.lineWidth, () => ( 2));
5758
5967
  this.cache = _nullishCoalesce(opts.cache, () => ( true));
@@ -5763,7 +5972,7 @@ var SplineEntity = (_class10 = class extends _chunkAGP4VLF4js.Entity {
5763
5972
  this.width = this.bounds.width;
5764
5973
  this.height = this.bounds.height;
5765
5974
  const isGradient = (c) => c !== null && !Array.isArray(c);
5766
- this.containsGradient = (_nullishCoalesce(_optionalChain([this, 'access', _154 => _154.doc, 'access', _155 => _155.equations, 'optionalAccess', _156 => _156.some, 'call', _157 => _157((eq) => isGradient(eq.color_rgb))]), () => ( false))) || (_nullishCoalesce(_optionalChain([this, 'access', _158 => _158.doc, 'access', _159 => _159.paths, 'optionalAccess', _160 => _160.some, 'call', _161 => _161((p) => isGradient(p.color_rgb))]), () => ( false)));
5975
+ this.containsGradient = (_nullishCoalesce(_optionalChain([this, 'access', _164 => _164.doc, 'access', _165 => _165.equations, 'optionalAccess', _166 => _166.some, 'call', _167 => _167((eq) => isGradient(eq.color_rgb))]), () => ( false))) || (_nullishCoalesce(_optionalChain([this, 'access', _168 => _168.doc, 'access', _169 => _169.paths, 'optionalAccess', _170 => _170.some, 'call', _171 => _171((p) => isGradient(p.color_rgb))]), () => ( false)));
5767
5976
  this.interactive = true;
5768
5977
  }
5769
5978
  computeBounds() {
@@ -6133,19 +6342,19 @@ var _math = require('@vectojs/math'); _createStarExport(_math);
6133
6342
  // src/tree/DOMPortalEntity.ts
6134
6343
  var DOMPortalEntity = (_class11 = class extends _chunkAGP4VLF4js.Entity {
6135
6344
 
6136
- __init163() {this.isDOMPortal = true}
6137
- __init164() {this.domListeners = []}
6138
- __init165() {this.resizeObserver = null}
6139
- __init166() {this.domBound = false}
6140
- __init167() {this.cachedWidth = 100}
6141
- __init168() {this.cachedHeight = 100}
6142
- __init169() {this.lastWidth = ""}
6143
- __init170() {this.lastHeight = ""}
6144
- __init171() {this.lastTransform = ""}
6145
- __init172() {this.lastZIndex = ""}
6146
- __init173() {this.lastOpacity = ""}
6345
+ __init165() {this.isDOMPortal = true}
6346
+ __init166() {this.domListeners = []}
6347
+ __init167() {this.resizeObserver = null}
6348
+ __init168() {this.domBound = false}
6349
+ __init169() {this.cachedWidth = 100}
6350
+ __init170() {this.cachedHeight = 100}
6351
+ __init171() {this.lastWidth = ""}
6352
+ __init172() {this.lastHeight = ""}
6353
+ __init173() {this.lastTransform = ""}
6354
+ __init174() {this.lastZIndex = ""}
6355
+ __init175() {this.lastOpacity = ""}
6147
6356
  constructor(domElement, width, height, id) {
6148
- super(id);_class11.prototype.__init163.call(this);_class11.prototype.__init164.call(this);_class11.prototype.__init165.call(this);_class11.prototype.__init166.call(this);_class11.prototype.__init167.call(this);_class11.prototype.__init168.call(this);_class11.prototype.__init169.call(this);_class11.prototype.__init170.call(this);_class11.prototype.__init171.call(this);_class11.prototype.__init172.call(this);_class11.prototype.__init173.call(this);;
6357
+ super(id);_class11.prototype.__init165.call(this);_class11.prototype.__init166.call(this);_class11.prototype.__init167.call(this);_class11.prototype.__init168.call(this);_class11.prototype.__init169.call(this);_class11.prototype.__init170.call(this);_class11.prototype.__init171.call(this);_class11.prototype.__init172.call(this);_class11.prototype.__init173.call(this);_class11.prototype.__init174.call(this);_class11.prototype.__init175.call(this);;
6149
6358
  this.domElement = domElement;
6150
6359
  this.width = _nullishCoalesce(width, () => ( 0));
6151
6360
  this.height = _nullishCoalesce(height, () => ( 0));
@@ -6257,8 +6466,12 @@ var DOMPortalEntity = (_class11 = class extends _chunkAGP4VLF4js.Entity {
6257
6466
  }, _class11);
6258
6467
 
6259
6468
  // src/index.ts
6260
- Scene.registerWebGLPointRendererCreator(_chunkLHONR3GOjs.createWebGLPointRenderer);
6261
- Scene.registerWebGPUParticleSystemManager(_chunkLHONR3GOjs.WebGPUParticleSystemManager);
6469
+ Scene.registerWebGLPointRendererCreator(_chunkKEBYJVD6js.createWebGLPointRenderer);
6470
+ Scene.registerWebGPUParticleSystemManager(_chunkKEBYJVD6js.WebGPUParticleSystemManager);
6471
+
6472
+
6473
+
6474
+
6262
6475
 
6263
6476
 
6264
6477
 
@@ -6294,4 +6507,4 @@ Scene.registerWebGPUParticleSystemManager(_chunkLHONR3GOjs.WebGPUParticleSystemM
6294
6507
 
6295
6508
 
6296
6509
 
6297
- exports.CanvasRenderer = _chunkLHONR3GOjs.CanvasRenderer; exports.Circle = Circle; exports.ComputeParticleEntity = ComputeParticleEntity; exports.DOMPortalEntity = DOMPortalEntity; exports.Entity = _chunkAGP4VLF4js.Entity; exports.GlyphRasterAtlas = _chunkLHONR3GOjs.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 = _chunkLHONR3GOjs.SVGRenderer; exports.Scene = Scene; exports.SplineEntity = SplineEntity; exports.TextEntity = TextEntity; exports.TextRasterCache = _chunkLHONR3GOjs.TextRasterCache; exports.VectoJSEvent = _chunkAGP4VLF4js.VectoJSEvent; exports.WebGPUParticleSystemManager = _chunkLHONR3GOjs.WebGPUParticleSystemManager; exports.createWebGLPointRenderer = _chunkLHONR3GOjs.createWebGLPointRenderer; exports.isSafeUrl = _chunkLHONR3GOjs.isSafeUrl; exports.loadSpline = loadSpline; exports.parseColorToRGBA = _chunkLHONR3GOjs.parseColorToRGBA; exports.polySegmentToBezier = polySegmentToBezier; exports.sanitizeUrl = _chunkLHONR3GOjs.sanitizeUrl;
6510
+ exports.CanvasRenderer = _chunkKEBYJVD6js.CanvasRenderer; exports.Circle = Circle; exports.ComputeParticleEntity = ComputeParticleEntity; exports.DOMPortalEntity = DOMPortalEntity; exports.Entity = _chunkAGP4VLF4js.Entity; exports.GlyphRasterAtlas = _chunkKEBYJVD6js.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 = _chunkKEBYJVD6js.SVGRenderer; exports.Scene = Scene; exports.SplineEntity = SplineEntity; exports.TextEntity = TextEntity; exports.TextRasterCache = _chunkKEBYJVD6js.TextRasterCache; exports.VECTO_USER_TIMING = VECTO_USER_TIMING; exports.VectoJSEvent = _chunkAGP4VLF4js.VectoJSEvent; exports.WebGPUParticleSystemManager = _chunkKEBYJVD6js.WebGPUParticleSystemManager; exports.beginVectoUserTiming = beginVectoUserTiming; exports.createWebGLPointRenderer = _chunkKEBYJVD6js.createWebGLPointRenderer; exports.endVectoUserTiming = endVectoUserTiming; exports.isSafeUrl = _chunkKEBYJVD6js.isSafeUrl; exports.loadSpline = loadSpline; exports.measureVectoUserTiming = measureVectoUserTiming; exports.parseColorToRGBA = _chunkKEBYJVD6js.parseColorToRGBA; exports.polySegmentToBezier = polySegmentToBezier; exports.sanitizeUrl = _chunkKEBYJVD6js.sanitizeUrl;