@vectojs/core 0.2.0 → 0.2.1

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.
@@ -729,15 +729,23 @@ var Entity = class {
729
729
  return null;
730
730
  }
731
731
  /**
732
- * Whether this entity still has a queued/running tween animation.
732
+ * Whether this entity still has a queued/running tween animation, or an
733
+ * active {@link setTransition}/{@link animateTo}/{@link springTo} property
734
+ * driver.
733
735
  *
734
- * Used by {@link Scene}'s `onDemand` render mode to keep redrawing while an
735
- * animation is in flight.
736
+ * Used by {@link Scene} to keep rendering continuously while an animation
737
+ * is in flight — both in `onDemand` render mode, and to hold off the
738
+ * `always`-mode idle auto-throttle. Without checking `_drivers` here, a
739
+ * property driver becomes invisible to that throttle: `markDirty()` called
740
+ * from inside `update()`/`tickDrivers()` is wiped by the loop's own
741
+ * `dirty = false` at the end of that same tick, so once the throttle
742
+ * engages an in-flight spring/tween only advances one animation-frame per
743
+ * external `markDirty()` trigger instead of every render frame.
736
744
  *
737
- * @returns `true` if at least one animation remains.
745
+ * @returns `true` if at least one animation or property driver remains.
738
746
  */
739
747
  hasPendingAnimations() {
740
- return this.animations.length > 0;
748
+ return this.animations.length > 0 || this._drivers.size > 0;
741
749
  }
742
750
  };
743
751
 
@@ -729,15 +729,23 @@ var Entity = (_class4 = class {
729
729
  return null;
730
730
  }
731
731
  /**
732
- * Whether this entity still has a queued/running tween animation.
732
+ * Whether this entity still has a queued/running tween animation, or an
733
+ * active {@link setTransition}/{@link animateTo}/{@link springTo} property
734
+ * driver.
733
735
  *
734
- * Used by {@link Scene}'s `onDemand` render mode to keep redrawing while an
735
- * animation is in flight.
736
+ * Used by {@link Scene} to keep rendering continuously while an animation
737
+ * is in flight — both in `onDemand` render mode, and to hold off the
738
+ * `always`-mode idle auto-throttle. Without checking `_drivers` here, a
739
+ * property driver becomes invisible to that throttle: `markDirty()` called
740
+ * from inside `update()`/`tickDrivers()` is wiped by the loop's own
741
+ * `dirty = false` at the end of that same tick, so once the throttle
742
+ * engages an in-flight spring/tween only advances one animation-frame per
743
+ * external `markDirty()` trigger instead of every render frame.
736
744
  *
737
- * @returns `true` if at least one animation remains.
745
+ * @returns `true` if at least one animation or property driver remains.
738
746
  */
739
747
  hasPendingAnimations() {
740
- return this.animations.length > 0;
748
+ return this.animations.length > 0 || this._drivers.size > 0;
741
749
  }
742
750
  }, _class4);
743
751
 
package/dist/index.js CHANGED
@@ -22,7 +22,7 @@ var _chunkLIX7DJTIjs = require('./chunk-LIX7DJTI.js');
22
22
 
23
23
 
24
24
 
25
- var _chunkW3SFIVXOjs = require('./chunk-W3SFIVXO.js');
25
+ var _chunkLA3FJLP2js = require('./chunk-LA3FJLP2.js');
26
26
 
27
27
 
28
28
 
@@ -39,7 +39,7 @@ var PARTICLE_OFFSET_ORIGIN_X = 4;
39
39
  var PARTICLE_OFFSET_ORIGIN_Y = 5;
40
40
  var PARTICLE_OFFSET_SIZE = 6;
41
41
  var PARTICLE_OFFSET_LIFE = 7;
42
- var ComputeParticleEntity = (_class = class extends _chunkW3SFIVXOjs.Entity {
42
+ var ComputeParticleEntity = (_class = class extends _chunkLA3FJLP2js.Entity {
43
43
 
44
44
 
45
45
 
@@ -318,16 +318,18 @@ var Scene = (_class2 = class _Scene {
318
318
  */
319
319
  __init9() {this.renderMode = "always"}
320
320
  __init10() {this.dirty = true}
321
+ /** Whether to throttle rendering to 2 FPS when the scene is static to save power. */
322
+ __init11() {this.autoThrottle = true}
321
323
  /**
322
324
  * Frame-rate cap (power saving). `0` = uncapped (native refresh). When set,
323
325
  * the loop renders at most `maxFPS` times per second; animations still run,
324
326
  * just less often. See {@link SceneOptions.maxFPS}.
325
327
  */
326
- __init11() {this.maxFPS = 60}
328
+ __init12() {this.maxFPS = 60}
327
329
  /** Whether the OS prefers-reduced-motion setting auto-caps the loop. */
328
- __init12() {this.respectReducedMotion = true}
330
+ __init13() {this.respectReducedMotion = true}
329
331
  /** Cached media-query list; `.matches` is read live each frame. */
330
- __init13() {this.reducedMotionQuery = null}
332
+ __init14() {this.reducedMotionQuery = null}
331
333
  /** True when the OS asks for reduced motion and we respect it. Read by the animation drivers. */
332
334
  get prefersReducedMotion() {
333
335
  return this.respectReducedMotion && !!_optionalChain([this, 'access', _13 => _13.reducedMotionQuery, 'optionalAccess', _14 => _14.matches]);
@@ -336,58 +338,58 @@ var Scene = (_class2 = class _Scene {
336
338
  * Throttle interval (ms) for the a11y/automation shadow sync. `0` = every
337
339
  * frame. See {@link SceneOptions.a11ySyncInterval}.
338
340
  */
339
- __init14() {this.a11ySyncInterval = 0}
341
+ __init15() {this.a11ySyncInterval = 0}
340
342
  /** Timestamp of the last a11y sync, for throttling. */
341
- __init15() {this.lastA11ySync = -Infinity}
343
+ __init16() {this.lastA11ySync = -Infinity}
342
344
  /** True if we skipped an a11y sync during animation and need to sync when at rest. */
343
- __init16() {this.a11yPendingSyncAfterAnimation = false}
345
+ __init17() {this.a11yPendingSyncAfterAnimation = false}
344
346
  // A11y / Automation Layer. `null` in non-DOM (SSR/Node) environments — the
345
347
  // whole projection degrades to a no-op so the engine's logic stays usable
346
348
  // server-side (e.g. headless layout / vector export) without jsdom.
347
349
 
348
- __init17() {this.a11yElements = /* @__PURE__ */ new Map()}
350
+ __init18() {this.a11yElements = /* @__PURE__ */ new Map()}
349
351
 
350
- __init18() {this.focusedA11yElement = null}
351
- __init19() {this.caretBlinkTimer = null}
352
- __init20() {this.a11yNeedsReorder = true}
353
- __init21() {this.portalRoot = null}
354
- __init22() {this.fullViewportElements = []}
355
- __init23() {this.normalElements = []}
356
- __init24() {this.activeIds = /* @__PURE__ */ new Set()}
357
- __init25() {this.activePortalsThisFrame = /* @__PURE__ */ new Set()}
358
- __init26() {this.activePortalsPrevFrame = /* @__PURE__ */ new Set()}
359
- __init27() {this.portalEntities = /* @__PURE__ */ new Map()}
360
- __init28() {this.renderOrderCounter = 0}
352
+ __init19() {this.focusedA11yElement = null}
353
+ __init20() {this.caretBlinkTimer = null}
354
+ __init21() {this.a11yNeedsReorder = true}
355
+ __init22() {this.portalRoot = null}
356
+ __init23() {this.fullViewportElements = []}
357
+ __init24() {this.normalElements = []}
358
+ __init25() {this.activeIds = /* @__PURE__ */ new Set()}
359
+ __init26() {this.activePortalsThisFrame = /* @__PURE__ */ new Set()}
360
+ __init27() {this.activePortalsPrevFrame = /* @__PURE__ */ new Set()}
361
+ __init28() {this.portalEntities = /* @__PURE__ */ new Map()}
362
+ __init29() {this.renderOrderCounter = 0}
361
363
  // Optional WebGL point-cloud layer (see SceneOptions.pointBackend).
362
- __init29() {this.pointRenderer = null}
363
- __init30() {this.glCanvas = null}
364
+ __init30() {this.pointRenderer = null}
365
+ __init31() {this.glCanvas = null}
364
366
 
365
367
 
366
368
 
367
- __init31() {this.disableWindowResize = false}
369
+ __init32() {this.disableWindowResize = false}
368
370
  // WebGPU properties
369
- __init32() {this.destroyed = false}
370
- __init33() {this.device = null}
371
- __init34() {this.deviceLost = false}
372
- __init35() {this.particleBackend = "auto"}
373
- __init36() {this._webgpuDisabled = false}
371
+ __init33() {this.destroyed = false}
372
+ __init34() {this.device = null}
373
+ __init35() {this.deviceLost = false}
374
+ __init36() {this.particleBackend = "auto"}
375
+ __init37() {this._webgpuDisabled = false}
374
376
  get webgpuDisabled() {
375
377
  return this._webgpuDisabled || this.particleBackend === "cpu";
376
378
  }
377
379
  set webgpuDisabled(value) {
378
380
  this._webgpuDisabled = value;
379
381
  }
380
- __init37() {this.recoveryTimerId = null}
381
- __init38() {this.manager = null}
382
- __init39() {this.initializingWebGPU = false}
383
- __init40() {this.gpuCanvas = null}
384
- __init41() {this.gpuContext = null}
385
- __init42() {this.mouseX = -9999}
386
- __init43() {this.mouseY = -9999}
387
- __init44() {this.pointerMoveListener = null}
388
- __init45() {this.pointerLeaveListener = null}
389
- __init46() {this.hasWarnedZeroSize = false}
390
- constructor(canvas, options = {}) {;_class2.prototype.__init7.call(this);_class2.prototype.__init8.call(this);_class2.prototype.__init9.call(this);_class2.prototype.__init10.call(this);_class2.prototype.__init11.call(this);_class2.prototype.__init12.call(this);_class2.prototype.__init13.call(this);_class2.prototype.__init14.call(this);_class2.prototype.__init15.call(this);_class2.prototype.__init16.call(this);_class2.prototype.__init17.call(this);_class2.prototype.__init18.call(this);_class2.prototype.__init19.call(this);_class2.prototype.__init20.call(this);_class2.prototype.__init21.call(this);_class2.prototype.__init22.call(this);_class2.prototype.__init23.call(this);_class2.prototype.__init24.call(this);_class2.prototype.__init25.call(this);_class2.prototype.__init26.call(this);_class2.prototype.__init27.call(this);_class2.prototype.__init28.call(this);_class2.prototype.__init29.call(this);_class2.prototype.__init30.call(this);_class2.prototype.__init31.call(this);_class2.prototype.__init32.call(this);_class2.prototype.__init33.call(this);_class2.prototype.__init34.call(this);_class2.prototype.__init35.call(this);_class2.prototype.__init36.call(this);_class2.prototype.__init37.call(this);_class2.prototype.__init38.call(this);_class2.prototype.__init39.call(this);_class2.prototype.__init40.call(this);_class2.prototype.__init41.call(this);_class2.prototype.__init42.call(this);_class2.prototype.__init43.call(this);_class2.prototype.__init44.call(this);_class2.prototype.__init45.call(this);_class2.prototype.__init46.call(this);
382
+ __init38() {this.recoveryTimerId = null}
383
+ __init39() {this.manager = null}
384
+ __init40() {this.initializingWebGPU = false}
385
+ __init41() {this.gpuCanvas = null}
386
+ __init42() {this.gpuContext = null}
387
+ __init43() {this.mouseX = -9999}
388
+ __init44() {this.mouseY = -9999}
389
+ __init45() {this.pointerMoveListener = null}
390
+ __init46() {this.pointerLeaveListener = null}
391
+ __init47() {this.hasWarnedZeroSize = false}
392
+ constructor(canvas, options = {}) {;_class2.prototype.__init7.call(this);_class2.prototype.__init8.call(this);_class2.prototype.__init9.call(this);_class2.prototype.__init10.call(this);_class2.prototype.__init11.call(this);_class2.prototype.__init12.call(this);_class2.prototype.__init13.call(this);_class2.prototype.__init14.call(this);_class2.prototype.__init15.call(this);_class2.prototype.__init16.call(this);_class2.prototype.__init17.call(this);_class2.prototype.__init18.call(this);_class2.prototype.__init19.call(this);_class2.prototype.__init20.call(this);_class2.prototype.__init21.call(this);_class2.prototype.__init22.call(this);_class2.prototype.__init23.call(this);_class2.prototype.__init24.call(this);_class2.prototype.__init25.call(this);_class2.prototype.__init26.call(this);_class2.prototype.__init27.call(this);_class2.prototype.__init28.call(this);_class2.prototype.__init29.call(this);_class2.prototype.__init30.call(this);_class2.prototype.__init31.call(this);_class2.prototype.__init32.call(this);_class2.prototype.__init33.call(this);_class2.prototype.__init34.call(this);_class2.prototype.__init35.call(this);_class2.prototype.__init36.call(this);_class2.prototype.__init37.call(this);_class2.prototype.__init38.call(this);_class2.prototype.__init39.call(this);_class2.prototype.__init40.call(this);_class2.prototype.__init41.call(this);_class2.prototype.__init42.call(this);_class2.prototype.__init43.call(this);_class2.prototype.__init44.call(this);_class2.prototype.__init45.call(this);_class2.prototype.__init46.call(this);_class2.prototype.__init47.call(this);
391
393
  this.canvas = canvas;
392
394
  this.debugA11y = _nullishCoalesce(options.debugA11y, () => ( false));
393
395
  this.disableWindowResize = _nullishCoalesce(options.disableWindowResize, () => ( false));
@@ -402,10 +404,11 @@ var Scene = (_class2 = class _Scene {
402
404
  const isTest = globalProcess && (_optionalChain([globalProcess, 'access', _15 => _15.env, 'optionalAccess', _16 => _16.NODE_ENV]) === "test" || _optionalChain([globalProcess, 'access', _17 => _17.env, 'optionalAccess', _18 => _18.VITEST]) === "true");
403
405
  this.maxFPS = _nullishCoalesce(options.maxFPS, () => ( (isTest ? 0 : 60)));
404
406
  this.respectReducedMotion = _nullishCoalesce(options.respectReducedMotion, () => ( true));
407
+ this.autoThrottle = _nullishCoalesce(options.autoThrottle, () => ( true));
405
408
  this.particleBackend = _nullishCoalesce(options.particleBackend, () => ( "auto"));
406
409
  this.a11ySyncInterval = _nullishCoalesce(options.a11ySyncInterval, () => ( 0));
407
410
  this.reducedMotionQuery = typeof window !== "undefined" && typeof window.matchMedia === "function" ? window.matchMedia("(prefers-reduced-motion: reduce)") : null;
408
- this.root = new class RootEntity extends _chunkW3SFIVXOjs.Entity {
411
+ this.root = new class RootEntity extends _chunkLA3FJLP2js.Entity {
409
412
  isPointInside() {
410
413
  return false;
411
414
  }
@@ -414,7 +417,7 @@ var Scene = (_class2 = class _Scene {
414
417
  }
415
418
  }("root");
416
419
  this.root._scene = this;
417
- this.overlayRoot = new class OverlayRoot extends _chunkW3SFIVXOjs.Entity {
420
+ this.overlayRoot = new class OverlayRoot extends _chunkLA3FJLP2js.Entity {
418
421
  isPointInside() {
419
422
  return false;
420
423
  }
@@ -722,42 +725,42 @@ var Scene = (_class2 = class _Scene {
722
725
  el.style.background = "transparent";
723
726
  }
724
727
  el.addEventListener("click", (e) => {
725
- node.dispatchEvent(new (0, _chunkW3SFIVXOjs.VectoJSEvent)("click", node, e));
728
+ node.dispatchEvent(new (0, _chunkLA3FJLP2js.VectoJSEvent)("click", node, e));
726
729
  });
727
730
  el.addEventListener("mouseenter", (e) => {
728
731
  if (this.debugA11y) el.style.backgroundColor = "rgba(56, 189, 248, 0.2)";
729
- node.dispatchEvent(new (0, _chunkW3SFIVXOjs.VectoJSEvent)("hover", node, e, false));
732
+ node.dispatchEvent(new (0, _chunkLA3FJLP2js.VectoJSEvent)("hover", node, e, false));
730
733
  });
731
734
  el.addEventListener("mouseleave", (e) => {
732
735
  if (this.debugA11y) el.style.backgroundColor = "rgba(56, 189, 248, 0.05)";
733
- node.dispatchEvent(new (0, _chunkW3SFIVXOjs.VectoJSEvent)("pointerleave", node, e, false));
736
+ node.dispatchEvent(new (0, _chunkLA3FJLP2js.VectoJSEvent)("pointerleave", node, e, false));
734
737
  });
735
738
  const capEl = el;
736
739
  el.addEventListener("pointerdown", (e) => {
737
740
  if (typeof capEl.setPointerCapture === "function") capEl.setPointerCapture(e.pointerId);
738
- node.dispatchEvent(new (0, _chunkW3SFIVXOjs.VectoJSEvent)("pointerdown", node, e));
741
+ node.dispatchEvent(new (0, _chunkLA3FJLP2js.VectoJSEvent)("pointerdown", node, e));
739
742
  });
740
743
  el.addEventListener("pointerup", (e) => {
741
744
  if (typeof capEl.releasePointerCapture === "function")
742
745
  capEl.releasePointerCapture(e.pointerId);
743
- node.dispatchEvent(new (0, _chunkW3SFIVXOjs.VectoJSEvent)("pointerup", node, e));
746
+ node.dispatchEvent(new (0, _chunkLA3FJLP2js.VectoJSEvent)("pointerup", node, e));
744
747
  });
745
748
  el.addEventListener(
746
749
  "pointermove",
747
- (e) => node.dispatchEvent(new (0, _chunkW3SFIVXOjs.VectoJSEvent)("pointermove", node, e))
750
+ (e) => node.dispatchEvent(new (0, _chunkLA3FJLP2js.VectoJSEvent)("pointermove", node, e))
748
751
  );
749
752
  el.addEventListener(
750
753
  "wheel",
751
754
  (e) => {
752
- node.dispatchEvent(new (0, _chunkW3SFIVXOjs.VectoJSEvent)("wheel", node, e));
755
+ node.dispatchEvent(new (0, _chunkLA3FJLP2js.VectoJSEvent)("wheel", node, e));
753
756
  },
754
757
  { passive: false }
755
758
  );
756
759
  el.addEventListener("keydown", (e) => {
757
- node.dispatchEvent(new (0, _chunkW3SFIVXOjs.VectoJSEvent)("keydown", node, e));
760
+ node.dispatchEvent(new (0, _chunkLA3FJLP2js.VectoJSEvent)("keydown", node, e));
758
761
  });
759
762
  el.addEventListener("keyup", (e) => {
760
- node.dispatchEvent(new (0, _chunkW3SFIVXOjs.VectoJSEvent)("keyup", node, e));
763
+ node.dispatchEvent(new (0, _chunkLA3FJLP2js.VectoJSEvent)("keyup", node, e));
761
764
  });
762
765
  if (el instanceof HTMLInputElement || el instanceof HTMLTextAreaElement) {
763
766
  const input = el;
@@ -829,7 +832,7 @@ var Scene = (_class2 = class _Scene {
829
832
  el.addEventListener("keydown", (e) => {
830
833
  if (e.key === "Enter" || e.key === " ") {
831
834
  e.preventDefault();
832
- node.dispatchEvent(new (0, _chunkW3SFIVXOjs.VectoJSEvent)("click", node, e));
835
+ node.dispatchEvent(new (0, _chunkLA3FJLP2js.VectoJSEvent)("click", node, e));
833
836
  }
834
837
  });
835
838
  }
@@ -1090,7 +1093,7 @@ var Scene = (_class2 = class _Scene {
1090
1093
  loop(time) {
1091
1094
  if (!this.isRunning) return;
1092
1095
  let cap = this.effectiveMaxFPS();
1093
- const isStatic = !this.dirty && !this.hasAnyPendingAnimation(this.root) && !this.hasAnyPendingAnimation(this.overlayRoot);
1096
+ const isStatic = this.autoThrottle && !this.dirty && !this.hasAnyPendingAnimation(this.root) && !this.hasAnyPendingAnimation(this.overlayRoot);
1094
1097
  if (isStatic && this.renderMode === "always" && this.maxFPS > 0) {
1095
1098
  cap = Math.min(cap, 2);
1096
1099
  }
@@ -1523,20 +1526,20 @@ function defaultMeasurer() {
1523
1526
  if (sharedMeasurer === void 0) sharedMeasurer = _chunk72WVPMSJjs.createCanvasMeasurer.call(void 0, "sans-serif");
1524
1527
  return sharedMeasurer;
1525
1528
  }
1526
- var TextEntity = (_class3 = class extends _chunkW3SFIVXOjs.Entity {
1529
+ var TextEntity = (_class3 = class extends _chunkLA3FJLP2js.Entity {
1527
1530
 
1528
1531
 
1529
1532
 
1530
1533
 
1531
- __init47() {this.nodes = []}
1534
+ __init48() {this.nodes = []}
1532
1535
 
1533
- __init48() {this.fillStyle = "#94a3b8"}
1534
- __init49() {this.strokeStyle = null}
1535
- __init50() {this.hoveredFillStyle = "#ffffff"}
1536
- __init51() {this.lineWidth = 1}
1537
- __init52() {this.isHovered = false}
1536
+ __init49() {this.fillStyle = "#94a3b8"}
1537
+ __init50() {this.strokeStyle = null}
1538
+ __init51() {this.hoveredFillStyle = "#ffffff"}
1539
+ __init52() {this.lineWidth = 1}
1540
+ __init53() {this.isHovered = false}
1538
1541
  constructor(text, atlas, maxWidth, fontSize = 24) {
1539
- super();_class3.prototype.__init47.call(this);_class3.prototype.__init48.call(this);_class3.prototype.__init49.call(this);_class3.prototype.__init50.call(this);_class3.prototype.__init51.call(this);_class3.prototype.__init52.call(this);;
1542
+ super();_class3.prototype.__init48.call(this);_class3.prototype.__init49.call(this);_class3.prototype.__init50.call(this);_class3.prototype.__init51.call(this);_class3.prototype.__init52.call(this);_class3.prototype.__init53.call(this);;
1540
1543
  this.text = text;
1541
1544
  this.atlas = atlas;
1542
1545
  this.fontSize = fontSize;
@@ -1622,17 +1625,17 @@ var TextEntity = (_class3 = class extends _chunkW3SFIVXOjs.Entity {
1622
1625
  }, _class3);
1623
1626
 
1624
1627
  // src/components/GridTextEntity.ts
1625
- var GridTextEntity = (_class4 = class extends _chunkW3SFIVXOjs.Entity {
1628
+ var GridTextEntity = (_class4 = class extends _chunkLA3FJLP2js.Entity {
1626
1629
 
1627
- __init53() {this.fillStyle = "#ffffff"}
1628
- __init54() {this.grid = []}
1630
+ __init54() {this.fillStyle = "#ffffff"}
1631
+ __init55() {this.grid = []}
1629
1632
  // Array of rows
1630
- __init55() {this.cols = 0}
1631
- __init56() {this.rows = 0}
1633
+ __init56() {this.cols = 0}
1634
+ __init57() {this.rows = 0}
1632
1635
 
1633
1636
 
1634
1637
  constructor(_atlas, fontSize = 10) {
1635
- super();_class4.prototype.__init53.call(this);_class4.prototype.__init54.call(this);_class4.prototype.__init55.call(this);_class4.prototype.__init56.call(this);;
1638
+ super();_class4.prototype.__init54.call(this);_class4.prototype.__init55.call(this);_class4.prototype.__init56.call(this);_class4.prototype.__init57.call(this);;
1636
1639
  this.fontSize = fontSize;
1637
1640
  this.charWidth = fontSize * 1;
1638
1641
  this.charHeight = fontSize * 1.1;
@@ -1716,7 +1719,7 @@ function distSqToSegment(px, py, x1, y1, x2, y2) {
1716
1719
  const ey = py - cy;
1717
1720
  return ex * ex + ey * ey;
1718
1721
  }
1719
- var SplineEntity = (_class5 = class extends _chunkW3SFIVXOjs.Entity {
1722
+ var SplineEntity = (_class5 = class extends _chunkLA3FJLP2js.Entity {
1720
1723
 
1721
1724
 
1722
1725
 
@@ -1724,18 +1727,18 @@ var SplineEntity = (_class5 = class extends _chunkW3SFIVXOjs.Entity {
1724
1727
 
1725
1728
 
1726
1729
 
1727
- __init57() {this.offscreen = null}
1728
- __init58() {this.baked = false}
1730
+ __init58() {this.offscreen = null}
1731
+ __init59() {this.baked = false}
1729
1732
  /** Lazily-flattened polylines (one Float32Array of [x,y,...] per segment) for hit-testing. */
1730
- __init59() {this.polylines = null}
1733
+ __init60() {this.polylines = null}
1731
1734
  /**
1732
1735
  * When `true`, the renderer draws a rounded-rect outline of the entity's
1733
1736
  * local bounds after painting the curves. Useful for drag feedback and
1734
1737
  * debugging hit areas. Defaults to `false`.
1735
1738
  */
1736
- __init60() {this.showBounds = false}
1739
+ __init61() {this.showBounds = false}
1737
1740
  constructor(doc, opts = {}) {
1738
- super();_class5.prototype.__init57.call(this);_class5.prototype.__init58.call(this);_class5.prototype.__init59.call(this);_class5.prototype.__init60.call(this);;
1741
+ super();_class5.prototype.__init58.call(this);_class5.prototype.__init59.call(this);_class5.prototype.__init60.call(this);_class5.prototype.__init61.call(this);;
1739
1742
  this.doc = doc;
1740
1743
  this.lineWidth = _nullishCoalesce(opts.lineWidth, () => ( 2));
1741
1744
  this.cache = _nullishCoalesce(opts.cache, () => ( true));
@@ -1982,9 +1985,9 @@ async function loadSpline(url) {
1982
1985
  // src/math/SpatialHashGrid.ts
1983
1986
  var SpatialHashGrid = (_class6 = class {
1984
1987
 
1985
- __init61() {this.grid = /* @__PURE__ */ new Map()}
1986
- __init62() {this.entityCells = /* @__PURE__ */ new Map()}
1987
- constructor(cellSize = 64) {;_class6.prototype.__init61.call(this);_class6.prototype.__init62.call(this);
1988
+ __init62() {this.grid = /* @__PURE__ */ new Map()}
1989
+ __init63() {this.entityCells = /* @__PURE__ */ new Map()}
1990
+ constructor(cellSize = 64) {;_class6.prototype.__init62.call(this);_class6.prototype.__init63.call(this);
1988
1991
  this.cellSize = cellSize;
1989
1992
  }
1990
1993
  hash(cx, cy) {
@@ -2074,19 +2077,19 @@ var SpatialHashGrid = (_class6 = class {
2074
2077
  }, _class6);
2075
2078
 
2076
2079
  // src/tree/DOMPortalEntity.ts
2077
- var DOMPortalEntity = (_class7 = class extends _chunkW3SFIVXOjs.Entity {
2080
+ var DOMPortalEntity = (_class7 = class extends _chunkLA3FJLP2js.Entity {
2078
2081
 
2079
- __init63() {this.isDOMPortal = true}
2080
- __init64() {this.domListeners = []}
2081
- __init65() {this.resizeObserver = null}
2082
- __init66() {this.cachedWidth = 100}
2083
- __init67() {this.cachedHeight = 100}
2084
- __init68() {this.lastWidth = ""}
2085
- __init69() {this.lastHeight = ""}
2086
- __init70() {this.lastTransform = ""}
2087
- __init71() {this.lastZIndex = ""}
2082
+ __init64() {this.isDOMPortal = true}
2083
+ __init65() {this.domListeners = []}
2084
+ __init66() {this.resizeObserver = null}
2085
+ __init67() {this.cachedWidth = 100}
2086
+ __init68() {this.cachedHeight = 100}
2087
+ __init69() {this.lastWidth = ""}
2088
+ __init70() {this.lastHeight = ""}
2089
+ __init71() {this.lastTransform = ""}
2090
+ __init72() {this.lastZIndex = ""}
2088
2091
  constructor(domElement, width, height, id) {
2089
- super(id);_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);;
2092
+ super(id);_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);;
2090
2093
  this.domElement = domElement;
2091
2094
  this.width = _nullishCoalesce(width, () => ( 0));
2092
2095
  this.height = _nullishCoalesce(height, () => ( 0));
@@ -2108,7 +2111,7 @@ var DOMPortalEntity = (_class7 = class extends _chunkW3SFIVXOjs.Entity {
2108
2111
  const events = ["click", "pointerdown", "pointerup", "pointermove", "wheel"];
2109
2112
  for (const type of events) {
2110
2113
  const handler = (e) => {
2111
- this.dispatchEvent(new (0, _chunkW3SFIVXOjs.VectoJSEvent)(type, this, e));
2114
+ this.dispatchEvent(new (0, _chunkLA3FJLP2js.VectoJSEvent)(type, this, e));
2112
2115
  };
2113
2116
  this.domElement.addEventListener(type, handler);
2114
2117
  this.domListeners.push({ type, handler, capture: false });
@@ -2119,7 +2122,7 @@ var DOMPortalEntity = (_class7 = class extends _chunkW3SFIVXOjs.Entity {
2119
2122
  ];
2120
2123
  for (const { native, vecto } of hoverEvents) {
2121
2124
  const handler = (e) => {
2122
- this.dispatchEvent(new (0, _chunkW3SFIVXOjs.VectoJSEvent)(vecto, this, e, false));
2125
+ this.dispatchEvent(new (0, _chunkLA3FJLP2js.VectoJSEvent)(vecto, this, e, false));
2123
2126
  };
2124
2127
  this.domElement.addEventListener(native, handler);
2125
2128
  this.domListeners.push({ type: native, handler, capture: false });
@@ -2127,7 +2130,7 @@ var DOMPortalEntity = (_class7 = class extends _chunkW3SFIVXOjs.Entity {
2127
2130
  const focusEvents = ["focus", "blur"];
2128
2131
  for (const type of focusEvents) {
2129
2132
  const handler = (e) => {
2130
- this.dispatchEvent(new (0, _chunkW3SFIVXOjs.VectoJSEvent)(type, this, e, true));
2133
+ this.dispatchEvent(new (0, _chunkLA3FJLP2js.VectoJSEvent)(type, this, e, true));
2131
2134
  };
2132
2135
  this.domElement.addEventListener(type, handler, true);
2133
2136
  this.domListeners.push({ type, handler, capture: true });
@@ -2217,4 +2220,4 @@ Scene.registerWebGPUParticleSystemManager(_chunkLIX7DJTIjs.WebGPUParticleSystemM
2217
2220
 
2218
2221
 
2219
2222
 
2220
- exports.ArabicShaper = _chunkRW6NC4RBjs.ArabicShaper; exports.BidiResolver = _chunkRW6NC4RBjs.BidiResolver; exports.CanvasRenderer = _chunkLIX7DJTIjs.CanvasRenderer; exports.ComputeParticleEntity = ComputeParticleEntity; exports.DOMPortalEntity = DOMPortalEntity; exports.Easing = _chunkW3SFIVXOjs.Easing; exports.Entity = _chunkW3SFIVXOjs.Entity; exports.GridTextEntity = GridTextEntity; exports.LayoutEngine = _chunk72WVPMSJjs.LayoutEngine; exports.LayoutResultBuffer = _chunk72WVPMSJjs.LayoutResultBuffer; exports.LayoutWorkerManager = _chunkRW6NC4RBjs.LayoutWorkerManager; exports.MSDFFont = _chunkW3SFIVXOjs.MSDFFont; exports.MSDFTextEntity = _chunkW3SFIVXOjs.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.SVGEntity = _chunkW3SFIVXOjs.SVGEntity; exports.SVGRenderer = _chunkLIX7DJTIjs.SVGRenderer; exports.Scene = Scene; exports.SpatialHashGrid = SpatialHashGrid; exports.SplineEntity = SplineEntity; exports.SpringDriver = _chunkW3SFIVXOjs.SpringDriver; exports.SpringPhysics = _chunkW3SFIVXOjs.SpringPhysics; exports.TextEntity = TextEntity; exports.TweenDriver = _chunkW3SFIVXOjs.TweenDriver; exports.VectoJSEvent = _chunkW3SFIVXOjs.VectoJSEvent; exports.WebGPUParticleSystemManager = _chunkLIX7DJTIjs.WebGPUParticleSystemManager; exports.computeLineSegments = _chunk72WVPMSJjs.computeLineSegments; exports.createCanvasMeasurer = _chunk72WVPMSJjs.createCanvasMeasurer; exports.createWebGLPointRenderer = _chunkLIX7DJTIjs.createWebGLPointRenderer; exports.isTweenConfig = _chunkW3SFIVXOjs.isTweenConfig; exports.loadSpline = loadSpline; exports.parseColorToRGBA = _chunkLIX7DJTIjs.parseColorToRGBA; exports.polySegmentToBezier = polySegmentToBezier;
2223
+ exports.ArabicShaper = _chunkRW6NC4RBjs.ArabicShaper; exports.BidiResolver = _chunkRW6NC4RBjs.BidiResolver; exports.CanvasRenderer = _chunkLIX7DJTIjs.CanvasRenderer; exports.ComputeParticleEntity = ComputeParticleEntity; exports.DOMPortalEntity = DOMPortalEntity; exports.Easing = _chunkLA3FJLP2js.Easing; exports.Entity = _chunkLA3FJLP2js.Entity; exports.GridTextEntity = GridTextEntity; exports.LayoutEngine = _chunk72WVPMSJjs.LayoutEngine; exports.LayoutResultBuffer = _chunk72WVPMSJjs.LayoutResultBuffer; exports.LayoutWorkerManager = _chunkRW6NC4RBjs.LayoutWorkerManager; exports.MSDFFont = _chunkLA3FJLP2js.MSDFFont; exports.MSDFTextEntity = _chunkLA3FJLP2js.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.SVGEntity = _chunkLA3FJLP2js.SVGEntity; exports.SVGRenderer = _chunkLIX7DJTIjs.SVGRenderer; exports.Scene = Scene; exports.SpatialHashGrid = SpatialHashGrid; exports.SplineEntity = SplineEntity; exports.SpringDriver = _chunkLA3FJLP2js.SpringDriver; exports.SpringPhysics = _chunkLA3FJLP2js.SpringPhysics; exports.TextEntity = TextEntity; exports.TweenDriver = _chunkLA3FJLP2js.TweenDriver; exports.VectoJSEvent = _chunkLA3FJLP2js.VectoJSEvent; exports.WebGPUParticleSystemManager = _chunkLIX7DJTIjs.WebGPUParticleSystemManager; exports.computeLineSegments = _chunk72WVPMSJjs.computeLineSegments; exports.createCanvasMeasurer = _chunk72WVPMSJjs.createCanvasMeasurer; exports.createWebGLPointRenderer = _chunkLIX7DJTIjs.createWebGLPointRenderer; exports.isTweenConfig = _chunkLA3FJLP2js.isTweenConfig; exports.loadSpline = loadSpline; exports.parseColorToRGBA = _chunkLIX7DJTIjs.parseColorToRGBA; exports.polySegmentToBezier = polySegmentToBezier;
package/dist/index.mjs CHANGED
@@ -22,7 +22,7 @@ import {
22
22
  TweenDriver,
23
23
  VectoJSEvent,
24
24
  isTweenConfig
25
- } from "./chunk-Y2N7TGEH.mjs";
25
+ } from "./chunk-H3QIE77O.mjs";
26
26
  import {
27
27
  ArabicShaper,
28
28
  BidiResolver,
@@ -318,6 +318,8 @@ var Scene = class _Scene {
318
318
  */
319
319
  renderMode = "always";
320
320
  dirty = true;
321
+ /** Whether to throttle rendering to 2 FPS when the scene is static to save power. */
322
+ autoThrottle = true;
321
323
  /**
322
324
  * Frame-rate cap (power saving). `0` = uncapped (native refresh). When set,
323
325
  * the loop renders at most `maxFPS` times per second; animations still run,
@@ -402,6 +404,7 @@ var Scene = class _Scene {
402
404
  const isTest = globalProcess && (globalProcess.env?.NODE_ENV === "test" || globalProcess.env?.VITEST === "true");
403
405
  this.maxFPS = options.maxFPS ?? (isTest ? 0 : 60);
404
406
  this.respectReducedMotion = options.respectReducedMotion ?? true;
407
+ this.autoThrottle = options.autoThrottle ?? true;
405
408
  this.particleBackend = options.particleBackend ?? "auto";
406
409
  this.a11ySyncInterval = options.a11ySyncInterval ?? 0;
407
410
  this.reducedMotionQuery = typeof window !== "undefined" && typeof window.matchMedia === "function" ? window.matchMedia("(prefers-reduced-motion: reduce)") : null;
@@ -1090,7 +1093,7 @@ var Scene = class _Scene {
1090
1093
  loop(time) {
1091
1094
  if (!this.isRunning) return;
1092
1095
  let cap = this.effectiveMaxFPS();
1093
- const isStatic = !this.dirty && !this.hasAnyPendingAnimation(this.root) && !this.hasAnyPendingAnimation(this.overlayRoot);
1096
+ const isStatic = this.autoThrottle && !this.dirty && !this.hasAnyPendingAnimation(this.root) && !this.hasAnyPendingAnimation(this.overlayRoot);
1094
1097
  if (isStatic && this.renderMode === "always" && this.maxFPS > 0) {
1095
1098
  cap = Math.min(cap, 2);
1096
1099
  }
package/dist/text.js CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
 
4
4
 
5
- var _chunkW3SFIVXOjs = require('./chunk-W3SFIVXO.js');
5
+ var _chunkLA3FJLP2js = require('./chunk-LA3FJLP2.js');
6
6
 
7
7
 
8
8
 
@@ -13,4 +13,4 @@ var _chunkRW6NC4RBjs = require('./chunk-RW6NC4RB.js');
13
13
 
14
14
 
15
15
 
16
- exports.ArabicShaper = _chunkRW6NC4RBjs.ArabicShaper; exports.BidiResolver = _chunkRW6NC4RBjs.BidiResolver; exports.MSDFFont = _chunkW3SFIVXOjs.MSDFFont; exports.MSDFTextEntity = _chunkW3SFIVXOjs.MSDFTextEntity; exports.SVGEntity = _chunkW3SFIVXOjs.SVGEntity;
16
+ exports.ArabicShaper = _chunkRW6NC4RBjs.ArabicShaper; exports.BidiResolver = _chunkRW6NC4RBjs.BidiResolver; exports.MSDFFont = _chunkLA3FJLP2js.MSDFFont; exports.MSDFTextEntity = _chunkLA3FJLP2js.MSDFTextEntity; exports.SVGEntity = _chunkLA3FJLP2js.SVGEntity;
package/dist/text.mjs CHANGED
@@ -2,7 +2,7 @@ import {
2
2
  MSDFFont,
3
3
  MSDFTextEntity,
4
4
  SVGEntity
5
- } from "./chunk-Y2N7TGEH.mjs";
5
+ } from "./chunk-H3QIE77O.mjs";
6
6
  import {
7
7
  ArabicShaper,
8
8
  BidiResolver
@@ -413,12 +413,20 @@ export declare abstract class Entity {
413
413
  */
414
414
  getBatchRect(): BatchRect | null;
415
415
  /**
416
- * Whether this entity still has a queued/running tween animation.
416
+ * Whether this entity still has a queued/running tween animation, or an
417
+ * active {@link setTransition}/{@link animateTo}/{@link springTo} property
418
+ * driver.
417
419
  *
418
- * Used by {@link Scene}'s `onDemand` render mode to keep redrawing while an
419
- * animation is in flight.
420
+ * Used by {@link Scene} to keep rendering continuously while an animation
421
+ * is in flight — both in `onDemand` render mode, and to hold off the
422
+ * `always`-mode idle auto-throttle. Without checking `_drivers` here, a
423
+ * property driver becomes invisible to that throttle: `markDirty()` called
424
+ * from inside `update()`/`tickDrivers()` is wiped by the loop's own
425
+ * `dirty = false` at the end of that same tick, so once the throttle
426
+ * engages an in-flight spring/tween only advances one animation-frame per
427
+ * external `markDirty()` trigger instead of every render frame.
420
428
  *
421
- * @returns `true` if at least one animation remains.
429
+ * @returns `true` if at least one animation or property driver remains.
422
430
  */
423
431
  hasPendingAnimations(): boolean;
424
432
  abstract isPointInside(globalX: number, globalY: number): boolean;
@@ -70,6 +70,11 @@ export interface SceneOptions {
70
70
  * Useful when Vecto is running inside a custom layout container or offscreen canvas.
71
71
  */
72
72
  disableWindowResize?: boolean;
73
+ /**
74
+ * Enable automatic throttling to 2 FPS when the scene is static (no active transitions
75
+ * and not marked dirty) to save power/CPU. Default is `true`.
76
+ */
77
+ autoThrottle?: boolean;
73
78
  }
74
79
  /** Frame-rate the loop is capped to when the OS requests reduced motion. */
75
80
  export declare const REDUCED_MOTION_FPS = 30;
@@ -117,6 +122,8 @@ export declare class Scene {
117
122
  */
118
123
  renderMode: 'always' | 'onDemand';
119
124
  private dirty;
125
+ /** Whether to throttle rendering to 2 FPS when the scene is static to save power. */
126
+ autoThrottle: boolean;
120
127
  /**
121
128
  * Frame-rate cap (power saving). `0` = uncapped (native refresh). When set,
122
129
  * the loop renders at most `maxFPS` times per second; animations still run,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vectojs/core",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },