@vectojs/core 1.35.3 → 1.37.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/{chunk-CHDJEHML.mjs → chunk-3MTVDXZQ.mjs} +16 -5
- package/dist/{chunk-XHPUCU5P.js → chunk-DSYYQ6BQ.js} +16 -5
- package/dist/{chunk-25PS5K7R.mjs → chunk-LWEMD34D.mjs} +18 -4
- package/dist/{chunk-MO24PVGT.js → chunk-ZYYP2M5D.js} +18 -4
- package/dist/index.js +175 -164
- package/dist/index.mjs +18 -7
- package/dist/renderer/CanvasRenderer.d.ts +1 -1
- package/dist/renderer/IRenderer.d.ts +8 -1
- package/dist/renderer/SVGRenderer.d.ts +1 -1
- package/dist/renderer.js +2 -2
- package/dist/renderer.mjs +1 -1
- package/dist/text/MSDFTextEntity.d.ts +2 -2
- package/dist/text.js +2 -2
- package/dist/text.mjs +1 -1
- package/dist/tree/ComputeParticleEntity.d.ts +2 -2
- package/dist/tree/Entity.d.ts +14 -3
- package/dist/tree/Scene.d.ts +29 -7
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -11,14 +11,14 @@ import {
|
|
|
11
11
|
parseColorToRGBA,
|
|
12
12
|
sanitizeUrl,
|
|
13
13
|
setRendererDevMode
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-LWEMD34D.mjs";
|
|
15
15
|
import {
|
|
16
16
|
Entity,
|
|
17
17
|
MSDFTextEntity,
|
|
18
18
|
SVGEntity,
|
|
19
19
|
VectoJSEvent,
|
|
20
20
|
contentLineInHint
|
|
21
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-3MTVDXZQ.mjs";
|
|
22
22
|
|
|
23
23
|
// src/tree/ComputeParticleEntity.ts
|
|
24
24
|
var PARTICLE_STRIDE_FLOATS = 8;
|
|
@@ -178,8 +178,8 @@ var ComputeParticleEntity = class extends Entity {
|
|
|
178
178
|
* render-tree walk, but this entity is still a normal tree member that
|
|
179
179
|
* walk visits — without this override, the base `Entity.hasPendingAnimations()`
|
|
180
180
|
* (always `false`) is what Scene sees, so `renderMode: 'always'`'s idle
|
|
181
|
-
* auto-throttle drops the WHOLE scene to
|
|
182
|
-
* the tree is animating, even while thousands of particles are visibly
|
|
181
|
+
* auto-throttle drops the WHOLE scene to the idle FPS floor the instant
|
|
182
|
+
* nothing else in the tree is animating, even while thousands of particles are visibly
|
|
183
183
|
* drifting or spring-settling. A spring+damping system asymptotically
|
|
184
184
|
* approaches zero velocity but never reaches it exactly, so this checks
|
|
185
185
|
* against a small epsilon rather than `!== 0` — otherwise this would
|
|
@@ -3435,6 +3435,7 @@ var SCENE_OPTION_KEYS = [
|
|
|
3435
3435
|
"contentSemanticMargin",
|
|
3436
3436
|
"debugA11y",
|
|
3437
3437
|
"disableWindowResize",
|
|
3438
|
+
"idleFPS",
|
|
3438
3439
|
"maxDPR",
|
|
3439
3440
|
"maxFPS",
|
|
3440
3441
|
"particleBackend",
|
|
@@ -3863,8 +3864,17 @@ var Scene = class _Scene {
|
|
|
3863
3864
|
if (value) this._dirty.mark(void 0, this.currentFrame);
|
|
3864
3865
|
else this._dirty.clear();
|
|
3865
3866
|
}
|
|
3866
|
-
/**
|
|
3867
|
+
/**
|
|
3868
|
+
* Whether to throttle the `'always'` loop when the scene is static to save
|
|
3869
|
+
* power. The idle floor is {@link Scene.idleFPS} (default 60).
|
|
3870
|
+
*/
|
|
3867
3871
|
autoThrottle = true;
|
|
3872
|
+
/**
|
|
3873
|
+
* Frame-rate floor for an idle `'always'` scene when {@link Scene.autoThrottle}
|
|
3874
|
+
* is on. Default `60`. Set `2` for the legacy aggressive idle sleep, `0` to
|
|
3875
|
+
* keep the scene's `maxFPS` cadence while idle.
|
|
3876
|
+
*/
|
|
3877
|
+
idleFPS = 60;
|
|
3868
3878
|
// --- Frame telemetry (read via `frameStats`) ---------------------------
|
|
3869
3879
|
/** Wall-clock ms spent inside the last `render()` call. */
|
|
3870
3880
|
_lastFrameMs = 0;
|
|
@@ -4794,6 +4804,7 @@ var Scene = class _Scene {
|
|
|
4794
4804
|
this.maxFPS = options.maxFPS ?? (isTest ? 0 : 60);
|
|
4795
4805
|
this.respectReducedMotion = options.respectReducedMotion ?? true;
|
|
4796
4806
|
this.autoThrottle = options.autoThrottle ?? true;
|
|
4807
|
+
this.idleFPS = options.idleFPS ?? 60;
|
|
4797
4808
|
this.phases.userTiming = options.userTiming ?? false;
|
|
4798
4809
|
this.particleBackend = options.particleBackend ?? "auto";
|
|
4799
4810
|
this.a11ySyncInterval = options.a11ySyncInterval ?? 0;
|
|
@@ -6739,7 +6750,7 @@ var Scene = class _Scene {
|
|
|
6739
6750
|
let cap = this.effectiveMaxFPS();
|
|
6740
6751
|
const isIdle = !this.dirty && !this.frameHadAnimation && !this.contentSemanticDeferred;
|
|
6741
6752
|
if (isIdle && this.autoThrottle && this.renderMode === "always" && this.maxFPS > 0) {
|
|
6742
|
-
cap = Math.min(cap,
|
|
6753
|
+
cap = Math.min(cap, this.idleFPS);
|
|
6743
6754
|
}
|
|
6744
6755
|
if (cap > 0 && time - this.lastTime < 1e3 / cap - 1) {
|
|
6745
6756
|
this._skippedFrames++;
|
|
@@ -6990,7 +7001,7 @@ var Scene = class _Scene {
|
|
|
6990
7001
|
if (this._devActive && this._devFrameCount % 120 === 0) {
|
|
6991
7002
|
if (overridesUpdate && node.hasPendingAnimations === Entity.prototype.hasPendingAnimations) {
|
|
6992
7003
|
this._devWarn(
|
|
6993
|
-
`Entity "${node.id}" overrides update() but not hasPendingAnimations(). Custom motion in update() without overriding hasPendingAnimations() causes the idle throttle to
|
|
7004
|
+
`Entity "${node.id}" overrides update() but not hasPendingAnimations(). Custom motion in update() without overriding hasPendingAnimations() causes the idle throttle to slow the animation. Override hasPendingAnimations() to return true while motion is in flight.`
|
|
6994
7005
|
);
|
|
6995
7006
|
}
|
|
6996
7007
|
}
|
|
@@ -133,7 +133,7 @@ export declare class CanvasRenderer implements IRenderer {
|
|
|
133
133
|
/** @inheritdoc */
|
|
134
134
|
setGlobalAlpha(alpha: number): void;
|
|
135
135
|
/** @inheritdoc */
|
|
136
|
-
clip(x: number, y: number, width: number, height: number): void;
|
|
136
|
+
clip(x: number, y: number, width: number, height: number, radii?: number | number[]): void;
|
|
137
137
|
/** @inheritdoc */
|
|
138
138
|
beginPath(): void;
|
|
139
139
|
/** @inheritdoc */
|
|
@@ -129,12 +129,19 @@ export interface IRenderer {
|
|
|
129
129
|
* Intersect the current clip region with a rectangle. Affects all subsequent
|
|
130
130
|
* draws until the next {@link restore}; wrap in {@link save}/{@link restore}.
|
|
131
131
|
*
|
|
132
|
+
* When `radii` is provided the clip is a rounded rectangle instead of a sharp
|
|
133
|
+
* one. Backends that can only express a rectangular clip (e.g. a scissor-test
|
|
134
|
+
* GPU path) may ignore `radii`, so it must be treated as a progressive
|
|
135
|
+
* enhancement rather than a guarantee.
|
|
136
|
+
*
|
|
132
137
|
* @param x - Left edge.
|
|
133
138
|
* @param y - Top edge.
|
|
134
139
|
* @param width - Rectangle width.
|
|
135
140
|
* @param height - Rectangle height.
|
|
141
|
+
* @param radii - Optional corner radius (uniform) or per-corner array, matching
|
|
142
|
+
* {@link roundRect}. Omit for a sharp rectangle.
|
|
136
143
|
*/
|
|
137
|
-
clip(x: number, y: number, width: number, height: number): void;
|
|
144
|
+
clip(x: number, y: number, width: number, height: number, radii?: number | number[]): void;
|
|
138
145
|
/** Begin a new sub-path, discarding the current path. */
|
|
139
146
|
beginPath(): void;
|
|
140
147
|
/**
|
|
@@ -72,7 +72,7 @@ export declare class SVGRenderer implements IRenderer {
|
|
|
72
72
|
stop: number;
|
|
73
73
|
color: string;
|
|
74
74
|
}[]): SVGLinearGradient;
|
|
75
|
-
clip(x: number, y: number, width: number, height: number): void;
|
|
75
|
+
clip(x: number, y: number, width: number, height: number, radii?: number | number[]): void;
|
|
76
76
|
toXMLString(): string;
|
|
77
77
|
private resolveGradient;
|
|
78
78
|
private escapeXML;
|
package/dist/renderer.js
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
|
|
13
|
-
var
|
|
13
|
+
var _chunkZYYP2M5Djs = require('./chunk-ZYYP2M5D.js');
|
|
14
14
|
|
|
15
15
|
|
|
16
16
|
|
|
@@ -22,4 +22,4 @@ var _chunkMO24PVGTjs = require('./chunk-MO24PVGT.js');
|
|
|
22
22
|
|
|
23
23
|
|
|
24
24
|
|
|
25
|
-
exports.CanvasRenderer =
|
|
25
|
+
exports.CanvasRenderer = _chunkZYYP2M5Djs.CanvasRenderer; exports.GlyphRasterAtlas = _chunkZYYP2M5Djs.GlyphRasterAtlas; exports.SVGRenderer = _chunkZYYP2M5Djs.SVGRenderer; exports.TextRasterCache = _chunkZYYP2M5Djs.TextRasterCache; exports.WebGPUParticleSystemManager = _chunkZYYP2M5Djs.WebGPUParticleSystemManager; exports.createWebGLPointRenderer = _chunkZYYP2M5Djs.createWebGLPointRenderer; exports.installRendererDevTraps = _chunkZYYP2M5Djs.installRendererDevTraps; exports.isRendererDevMode = _chunkZYYP2M5Djs.isRendererDevMode; exports.parseColorToRGBA = _chunkZYYP2M5Djs.parseColorToRGBA; exports.setRendererDevMode = _chunkZYYP2M5Djs.setRendererDevMode;
|
package/dist/renderer.mjs
CHANGED
|
@@ -59,8 +59,8 @@ export declare class MSDFTextEntity extends Entity {
|
|
|
59
59
|
*
|
|
60
60
|
* Measured on Chromium and Firefox (2026-07-31) with a 600 ms atlas: the
|
|
61
61
|
* scene's own rAF loop never uploaded a decoded atlas in EITHER render mode.
|
|
62
|
-
* `onDemand` skips idle frames outright; `always` throttles to
|
|
63
|
-
* idle, so whether it recovers is down to whether a throttled tick happens to
|
|
62
|
+
* `onDemand` skips idle frames outright; `always` throttles to the idle FPS
|
|
63
|
+
* floor when idle, so whether it recovers is down to whether a throttled tick happens to
|
|
64
64
|
* land after the decode — Chromium got one, Firefox did not. Neither is a
|
|
65
65
|
* mechanism, which is why this listener exists rather than relying on the
|
|
66
66
|
* frame loop to come back around.
|
package/dist/text.js
CHANGED
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
|
|
4
4
|
|
|
5
|
-
var
|
|
5
|
+
var _chunkDSYYQ6BQjs = require('./chunk-DSYYQ6BQ.js');
|
|
6
6
|
|
|
7
7
|
// src/text/index.ts
|
|
8
8
|
var _text = require('@vectojs/text'); _createStarExport(_text);
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
|
|
12
|
-
exports.MSDFTextEntity =
|
|
12
|
+
exports.MSDFTextEntity = _chunkDSYYQ6BQjs.MSDFTextEntity; exports.SVGEntity = _chunkDSYYQ6BQjs.SVGEntity;
|
package/dist/text.mjs
CHANGED
|
@@ -113,8 +113,8 @@ export declare class ComputeParticleEntity extends Entity {
|
|
|
113
113
|
* render-tree walk, but this entity is still a normal tree member that
|
|
114
114
|
* walk visits — without this override, the base `Entity.hasPendingAnimations()`
|
|
115
115
|
* (always `false`) is what Scene sees, so `renderMode: 'always'`'s idle
|
|
116
|
-
* auto-throttle drops the WHOLE scene to
|
|
117
|
-
* the tree is animating, even while thousands of particles are visibly
|
|
116
|
+
* auto-throttle drops the WHOLE scene to the idle FPS floor the instant
|
|
117
|
+
* nothing else in the tree is animating, even while thousands of particles are visibly
|
|
118
118
|
* drifting or spring-settling. A spring+damping system asymptotically
|
|
119
119
|
* approaches zero velocity but never reaches it exactly, so this checks
|
|
120
120
|
* against a small epsilon rather than `!== 0` — otherwise this would
|
package/dist/tree/Entity.d.ts
CHANGED
|
@@ -658,9 +658,20 @@ export declare abstract class Entity {
|
|
|
658
658
|
* and promotes it.
|
|
659
659
|
*
|
|
660
660
|
* `'never'` suppresses the node entirely. Prefer `interactive = false` unless
|
|
661
|
-
* the entity genuinely needs
|
|
662
|
-
* this exists so a purely decorative interactive surface can opt
|
|
663
|
-
*
|
|
661
|
+
* the entity genuinely needs to stay hit-testable without any semantic
|
|
662
|
+
* presence — this exists so a purely decorative interactive surface can opt
|
|
663
|
+
* out of the a11y tree.
|
|
664
|
+
*
|
|
665
|
+
* **Pointer input is routed through the projected mirror.** The engine binds
|
|
666
|
+
* `pointerdown`/`pointermove`/`pointerup`/`click`/`dblclick` to each shadow
|
|
667
|
+
* element (the canvas itself only tracks `mouseX`/`mouseY`), so an entity
|
|
668
|
+
* with no materialized node receives **no pointer events at all** — neither
|
|
669
|
+
* in `'never'` mode nor in `'onDemand'` before it is engaged (focused,
|
|
670
|
+
* pointer target, or `requestA11yProjection`). Canvas hit-testing exists
|
|
671
|
+
* (`Scene.findEntityAt`) but is a query API, not a dispatch path. For a
|
|
672
|
+
* pointer-reactive region with no role (e.g. a desktop click-catcher), use
|
|
673
|
+
* `'eager'` + `a11yFullViewport` + `tabIndex: -1` with a role-less
|
|
674
|
+
* `getA11yAttributes()`: the mirror is AT-invisible but pointer-visible.
|
|
664
675
|
*
|
|
665
676
|
* **This does not replace an aggregate description.** A thousand `'onDemand'`
|
|
666
677
|
* danmaku are individually reachable but say nothing collectively. The proven
|
package/dist/tree/Scene.d.ts
CHANGED
|
@@ -98,10 +98,22 @@ export interface SceneOptions {
|
|
|
98
98
|
*/
|
|
99
99
|
maxDPR?: number;
|
|
100
100
|
/**
|
|
101
|
-
* Enable automatic throttling
|
|
102
|
-
* and not marked dirty) to save power/CPU.
|
|
101
|
+
* Enable automatic throttling of the `'always'` loop when the scene is
|
|
102
|
+
* static (no active transitions and not marked dirty) to save power/CPU.
|
|
103
|
+
* The idle floor is 60 FPS by default; raise or lower it with
|
|
104
|
+
* {@link SceneOptions.idleFPS}. Default is `true`.
|
|
103
105
|
*/
|
|
104
106
|
autoThrottle?: boolean;
|
|
107
|
+
/**
|
|
108
|
+
* Frame-rate floor for an idle `'always'` scene when
|
|
109
|
+
* {@link SceneOptions.autoThrottle} is on. Default `60` — an idle scene
|
|
110
|
+
* keeps animating smoothly instead of stuttering at the old 2 FPS floor.
|
|
111
|
+
* Set e.g. `2` to restore the aggressive deep sleep for battery-critical
|
|
112
|
+
* scenes (the developer's explicit choice); `0` means "keep the scene's
|
|
113
|
+
* `maxFPS` cadence while idle". Ignored when `autoThrottle` is `false` or
|
|
114
|
+
* `renderMode` is `'onDemand'` (onDemand already renders zero idle frames).
|
|
115
|
+
*/
|
|
116
|
+
idleFPS?: number;
|
|
105
117
|
/**
|
|
106
118
|
* Emit User Timing marks and measures for render phases. Default `false`.
|
|
107
119
|
* Intended for short profiler captures; enable only while collecting one.
|
|
@@ -196,8 +208,9 @@ export interface SceneOptions {
|
|
|
196
208
|
readingDirection?: 'ltr' | 'rtl';
|
|
197
209
|
/**
|
|
198
210
|
* When to repaint:
|
|
199
|
-
* - `'always'` (default): drive a continuous rAF loop, throttling to
|
|
200
|
-
*
|
|
211
|
+
* - `'always'` (default): drive a continuous rAF loop, throttling to the
|
|
212
|
+
* {@link SceneOptions.idleFPS} floor (default 60) while the scene is idle
|
|
213
|
+
* if {@link SceneOptions.autoThrottle} is on.
|
|
201
214
|
* - `'onDemand'`: paint only after {@link Scene.markDirty} (or an active
|
|
202
215
|
* transition), so a genuinely static scene costs zero frames.
|
|
203
216
|
*
|
|
@@ -217,14 +230,14 @@ export interface SceneOptions {
|
|
|
217
230
|
* plain untranspiled JS, gets no diagnostic at all. `renderMode` was a public
|
|
218
231
|
* field with no matching option for several releases, and four `@vectojs` demos
|
|
219
232
|
* shipped `new Scene(canvas, { renderMode: 'onDemand' })` — reading correctly,
|
|
220
|
-
* doing nothing, and sitting on the
|
|
233
|
+
* doing nothing, and sitting on the idle FPS floor.
|
|
221
234
|
*
|
|
222
235
|
* Kept as a literal rather than derived from a type: `keyof SceneOptions` does
|
|
223
236
|
* not survive to runtime, so this list is the only form a constructor can check
|
|
224
237
|
* against. A new option must be added here too — the test suite asserts the two
|
|
225
238
|
* stay in sync.
|
|
226
239
|
*/
|
|
227
|
-
export declare const SCENE_OPTION_KEYS: readonly ['a11ySyncInterval', 'autoThrottle', 'contentProjection', 'contentProjectionMargin', 'contentSemanticBudget', 'contentSemanticMargin', 'debugA11y', 'disableWindowResize', 'maxDPR', 'maxFPS', 'particleBackend', 'pointBackend', 'readingDirection', 'renderer', 'renderMode', 'respectReducedMotion', 'userTiming'];
|
|
240
|
+
export declare const SCENE_OPTION_KEYS: readonly ['a11ySyncInterval', 'autoThrottle', 'contentProjection', 'contentProjectionMargin', 'contentSemanticBudget', 'contentSemanticMargin', 'debugA11y', 'disableWindowResize', 'idleFPS', 'maxDPR', 'maxFPS', 'particleBackend', 'pointBackend', 'readingDirection', 'renderer', 'renderMode', 'respectReducedMotion', 'userTiming'];
|
|
228
241
|
/** Frame-rate the loop is capped to when the OS requests reduced motion. */
|
|
229
242
|
export declare const REDUCED_MOTION_FPS = 30;
|
|
230
243
|
export type { AcceleratorReason, AcceleratorStatus, AcceleratorReport };
|
|
@@ -406,8 +419,17 @@ export declare class Scene {
|
|
|
406
419
|
*/
|
|
407
420
|
private get dirty();
|
|
408
421
|
private set dirty(value);
|
|
409
|
-
/**
|
|
422
|
+
/**
|
|
423
|
+
* Whether to throttle the `'always'` loop when the scene is static to save
|
|
424
|
+
* power. The idle floor is {@link Scene.idleFPS} (default 60).
|
|
425
|
+
*/
|
|
410
426
|
autoThrottle: boolean;
|
|
427
|
+
/**
|
|
428
|
+
* Frame-rate floor for an idle `'always'` scene when {@link Scene.autoThrottle}
|
|
429
|
+
* is on. Default `60`. Set `2` for the legacy aggressive idle sleep, `0` to
|
|
430
|
+
* keep the scene's `maxFPS` cadence while idle.
|
|
431
|
+
*/
|
|
432
|
+
idleFPS: number;
|
|
411
433
|
/** Wall-clock ms spent inside the last `render()` call. */
|
|
412
434
|
private _lastFrameMs;
|
|
413
435
|
/** Rolling exponential average of rendered-frame intervals, in ms. */
|