@vectojs/core 0.1.0 → 0.2.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.
Files changed (46) hide show
  1. package/dist/animation/drivers.d.ts +48 -0
  2. package/dist/animation/easing.d.ts +16 -0
  3. package/dist/{chunk-53DAQC3U.js → chunk-W3SFIVXO.js} +356 -60
  4. package/dist/{chunk-M2IZPGOL.mjs → chunk-Y2N7TGEH.mjs} +303 -7
  5. package/dist/components/GridTextEntity.d.ts +15 -0
  6. package/dist/components/SplineEntity.d.ts +144 -0
  7. package/dist/components/TextEntity.d.ts +35 -0
  8. package/dist/index.d.ts +26 -577
  9. package/dist/index.js +60 -78
  10. package/dist/index.mjs +15 -33
  11. package/dist/{layout.d.mts → layout/LayoutEngine.d.ts} +15 -70
  12. package/dist/layout/LayoutWorker.d.ts +23 -0
  13. package/dist/layout/LayoutWorkerManager.d.ts +22 -0
  14. package/dist/layout/LayoutWorkerSource.d.ts +1 -0
  15. package/dist/layout/index.d.ts +3 -0
  16. package/dist/layout/measure.d.ts +20 -0
  17. package/dist/math/SpatialHashGrid.d.ts +53 -0
  18. package/dist/math/SpringPhysics.d.ts +13 -0
  19. package/dist/renderer/CanvasRenderer.d.ts +81 -0
  20. package/dist/renderer/IRenderer.d.ts +178 -0
  21. package/dist/renderer/SVGRenderer.d.ts +69 -0
  22. package/dist/renderer/WebGLPointRenderer.d.ts +62 -0
  23. package/dist/renderer/WebGPUParticleSystemManager.d.ts +14 -0
  24. package/dist/renderer/colorParse.d.ts +17 -0
  25. package/dist/renderer/index.d.ts +6 -0
  26. package/dist/text/ArabicShaper.d.ts +10 -0
  27. package/dist/text/BidiResolver.d.ts +6 -0
  28. package/dist/{text.d.ts → text/MSDFFont.d.ts} +10 -82
  29. package/dist/text/MSDFTextEntity.d.ts +30 -0
  30. package/dist/text/SVGEntity.d.ts +22 -0
  31. package/dist/text/index.d.ts +5 -0
  32. package/dist/text.js +2 -2
  33. package/dist/text.mjs +1 -1
  34. package/dist/tree/ComputeParticleEntity.d.ts +118 -0
  35. package/dist/tree/DOMPortalEntity.d.ts +18 -0
  36. package/dist/{Entity-D-rfAFCf.d.mts → tree/Entity.d.ts} +59 -197
  37. package/dist/tree/Scene.d.ts +295 -0
  38. package/package.json +5 -5
  39. package/dist/Entity-D-rfAFCf.d.ts +0 -572
  40. package/dist/index-ByBDSmMK.d.mts +0 -365
  41. package/dist/index-C3Fd_XmG.d.ts +0 -365
  42. package/dist/index.d.mts +0 -577
  43. package/dist/layout.d.ts +0 -319
  44. package/dist/renderer.d.mts +0 -2
  45. package/dist/renderer.d.ts +0 -2
  46. package/dist/text.d.mts +0 -201
@@ -1,186 +1,10 @@
1
- /**
2
- * Renderer abstraction consumed by every {@link Entity}.
3
- *
4
- * Implementations wrap a concrete drawing backend (Canvas 2D, WebGL, …) and
5
- * expose a path-based drawing API. Entities must only depend on `IRenderer`
6
- * so they remain backend-agnostic.
7
- *
8
- * @example
9
- * // Inside an Entity.render() implementation:
10
- * render(r: IRenderer) {
11
- * r.beginPath();
12
- * r.fill('#38bdf8');
13
- * }
14
- */
15
- interface IRenderer {
16
- /** Clear the entire drawing surface to transparent / background color. */
17
- clear(): void;
18
- /** Push the current transform + state onto the renderer's stack. */
19
- save(): void;
20
- /** Pop the last saved transform + state from the renderer's stack. */
21
- restore(): void;
22
- /**
23
- * Apply a translation to the current transform matrix.
24
- *
25
- * @param x - Horizontal offset in pixels.
26
- * @param y - Vertical offset in pixels.
27
- */
28
- translate(x: number, y: number): void;
29
- /**
30
- * Apply a scale to the current transform matrix.
31
- *
32
- * @param x - Horizontal scale factor.
33
- * @param y - Vertical scale factor.
34
- */
35
- scale(x: number, y: number): void;
36
- /**
37
- * Apply a clockwise rotation to the current transform matrix.
38
- *
39
- * @param angle - Rotation angle in radians.
40
- */
41
- rotate(angle: number): void;
42
- /**
43
- * Set the global opacity applied to all subsequent draw calls.
44
- *
45
- * @param alpha - Opacity in the range `[0, 1]`.
46
- */
47
- setGlobalAlpha(alpha: number): void;
48
- /**
49
- * Intersect the current clip region with a rectangle. Affects all subsequent
50
- * draws until the next {@link restore}; wrap in {@link save}/{@link restore}.
51
- *
52
- * @param x - Left edge.
53
- * @param y - Top edge.
54
- * @param width - Rectangle width.
55
- * @param height - Rectangle height.
56
- */
57
- clip(x: number, y: number, width: number, height: number): void;
58
- /** Begin a new sub-path, discarding the current path. */
59
- beginPath(): void;
60
- /**
61
- * Move the pen to the given point without drawing a line.
62
- *
63
- * @param x - Target X coordinate.
64
- * @param y - Target Y coordinate.
65
- */
66
- moveTo(x: number, y: number): void;
67
- /**
68
- * Add a straight line segment from the current pen position to the given point.
69
- *
70
- * @param x - Target X coordinate.
71
- * @param y - Target Y coordinate.
72
- */
73
- lineTo(x: number, y: number): void;
74
- /**
75
- * Add a cubic Bézier curve to the current path.
76
- *
77
- * @param cp1x - X of the first control point.
78
- * @param cp1y - Y of the first control point.
79
- * @param cp2x - X of the second control point.
80
- * @param cp2y - Y of the second control point.
81
- * @param x - X of the end point.
82
- * @param y - Y of the end point.
83
- */
84
- bezierCurveTo(cp1x: number, cp1y: number, cp2x: number, cp2y: number, x: number, y: number): void;
85
- /** Close the current sub-path by drawing a line back to its starting point. */
86
- closePath(): void;
87
- /**
88
- * Add a circular arc to the current path.
89
- *
90
- * @param x - X of the arc center.
91
- * @param y - Y of the arc center.
92
- * @param radius - Arc radius in pixels.
93
- * @param startAngle - Start angle in radians (0 = 3 o'clock).
94
- * @param endAngle - End angle in radians.
95
- * @param counterclockwise - If `true`, draws the arc counter-clockwise.
96
- */
97
- arc(x: number, y: number, radius: number, startAngle: number, endAngle: number, counterclockwise?: boolean): void;
98
- /**
99
- * Add a rounded rectangle to the current path.
100
- *
101
- * @param x - Left edge.
102
- * @param y - Top edge.
103
- * @param width - Rectangle width.
104
- * @param height - Rectangle height.
105
- * @param radii - Corner radius (uniform) or per-corner array as accepted by `CanvasRenderingContext2D.roundRect()`.
106
- */
107
- roundRect(x: number, y: number, width: number, height: number, radii: number | number[]): void;
108
- /**
109
- * Draw an image or video frame into the canvas.
110
- *
111
- * @param source - The image source (HTMLImageElement, HTMLVideoElement, HTMLCanvasElement, etc.).
112
- * @param dx - Destination X.
113
- * @param dy - Destination Y.
114
- * @param dw - Destination width.
115
- * @param dh - Destination height.
116
- */
117
- drawImage(source: CanvasImageSource, dx: number, dy: number, dw: number, dh: number): void;
118
- /**
119
- * Fill the current path with the given color or gradient.
120
- *
121
- * @param colorOrGradient - CSS color string or a gradient object.
122
- */
123
- fill(colorOrGradient: string | any): void;
124
- /**
125
- * Stroke the current path with the given color or gradient.
126
- *
127
- * @param colorOrGradient - CSS color string or a gradient object.
128
- * @param lineWidth - Stroke width in pixels (default: `1`).
129
- */
130
- stroke(colorOrGradient: string | any, lineWidth?: number): void;
131
- /**
132
- * Render a text string at the given position.
133
- *
134
- * @param text - The string to draw.
135
- * @param x - Left edge of the text baseline.
136
- * @param y - Baseline Y coordinate.
137
- * @param font - CSS font shorthand, e.g. `'16px monospace'`.
138
- * @param color - CSS color string or gradient.
139
- */
140
- fillText(text: string, x: number, y: number, font: string, color: string | any): void;
141
- /**
142
- * Draw a filled circle through the order-preserving batch.
143
- *
144
- * Consecutive calls sharing the same `color` and `alpha` are coalesced into a
145
- * single path and committed with one `fill()` on {@link flush} (or when the
146
- * style changes / another draw call intervenes). Coordinates are in the
147
- * current transform space. This collapses the per-entity
148
- * `beginPath`/`arc`/`fill` of large point clouds into a handful of draw calls
149
- * while preserving painter's-order semantics.
150
- *
151
- * @param cx - Center X in the current transform space.
152
- * @param cy - Center Y in the current transform space.
153
- * @param radius - Circle radius.
154
- * @param color - CSS color string.
155
- * @param alpha - Opacity in `[0, 1]` (default `1`).
156
- */
157
- fillCircle(cx: number, cy: number, radius: number, color: string, alpha?: number): void;
158
- /**
159
- * Commit any pending batched draws (see {@link fillCircle}). Safe to call when
160
- * no batch is active (no-op). The {@link Scene} flushes at the end of each
161
- * sibling group and frame.
162
- */
163
- flush(): void;
164
- /**
165
- * Create a linear gradient between two points with the given color stops.
166
- *
167
- * @param x0 - X of the gradient start point.
168
- * @param y0 - Y of the gradient start point.
169
- * @param x1 - X of the gradient end point.
170
- * @param y1 - Y of the gradient end point.
171
- * @param colorStops - Array of `{ stop, color }` pairs where `stop` is in `[0, 1]`.
172
- * @returns An opaque gradient object suitable for {@link fill} or {@link stroke}.
173
- */
174
- createLinearGradient(x0: number, y0: number, x1: number, y1: number, colorStops: {
175
- stop: number;
176
- color: string;
177
- }[]): any;
178
- }
179
-
1
+ import { type MotionConfig, type TweenConfig, type SpringConfig } from '../animation/drivers';
2
+ /** A numeric transform/visual property that participates in the animation system. */
3
+ export type AnimatableProp = 'x' | 'y' | 'scaleX' | 'scaleY' | 'rotation' | 'opacity';
180
4
  /**
181
5
  * A 2-D coordinate in canvas/world space.
182
6
  */
183
- interface Point {
7
+ export interface Point {
184
8
  x: number;
185
9
  y: number;
186
10
  }
@@ -189,7 +13,7 @@ interface Point {
189
13
  *
190
14
  * Returned from {@link Entity.getBounds} to enable viewport culling.
191
15
  */
192
- interface Bounds {
16
+ export interface Bounds {
193
17
  x: number;
194
18
  y: number;
195
19
  width: number;
@@ -200,7 +24,7 @@ interface Bounds {
200
24
  * origin, returned from {@link Entity.getBatchCircle} to opt into the renderer's
201
25
  * draw-call batching fast-path.
202
26
  */
203
- interface BatchCircle {
27
+ export interface BatchCircle {
204
28
  /** Circle radius in the entity's local space. */
205
29
  radius: number;
206
30
  /** CSS fill color. */
@@ -211,7 +35,7 @@ interface BatchCircle {
211
35
  * origin, returned from {@link Entity.getBatchRect} to opt into the GPU
212
36
  * instanced-rectangle fast-path (WebGL `pointBackend` only).
213
37
  */
214
- interface BatchRect {
38
+ export interface BatchRect {
215
39
  /** Rectangle width in the entity's local space. */
216
40
  width: number;
217
41
  /** Rectangle height in the entity's local space. */
@@ -227,7 +51,7 @@ interface BatchRect {
227
51
  * to create and label the shadow DOM node (e.g. a real `<button>` or `<a href>`)
228
52
  * so the canvas stays accessible and clickable by automation/agents.
229
53
  */
230
- interface A11yAttributes {
54
+ export interface A11yAttributes {
231
55
  /** Shadow element tag to create. Defaults to `'div'`. */
232
56
  tag?: 'div' | 'a' | 'button' | 'img' | 'input' | 'textarea';
233
57
  /** ARIA role applied via the `role` attribute. */
@@ -263,9 +87,9 @@ interface A11yAttributes {
263
87
  /**
264
88
  * Union of all pointer/interaction events that can be emitted by an {@link Entity}.
265
89
  */
266
- type VectoEvent = 'click' | 'hover' | 'pointerdown' | 'pointerup' | 'pointermove' | 'pointerleave' | 'change' | 'focus' | 'blur' | 'wheel' | 'keydown' | 'keyup';
90
+ export type VectoEvent = 'click' | 'hover' | 'pointerdown' | 'pointerup' | 'pointermove' | 'pointerleave' | 'change' | 'focus' | 'blur' | 'wheel' | 'keydown' | 'keyup';
267
91
  /** Options for {@link Entity.on} / {@link Entity.off}. */
268
- interface ListenerOptions {
92
+ export interface ListenerOptions {
269
93
  /** Register the listener for the capture phase (root→target) instead of bubble. */
270
94
  capture?: boolean;
271
95
  }
@@ -279,7 +103,7 @@ interface ListenerOptions {
279
103
  * `clientX`, `key`, …) and `preventDefault()` pass through to `nativeEvent`, so
280
104
  * handlers written against the raw DOM event keep working.
281
105
  */
282
- declare class VectoJSEvent<N = unknown> {
106
+ export declare class VectoJSEvent<N = unknown> {
283
107
  /** The event name. */
284
108
  readonly type: VectoEvent;
285
109
  /** The entity the event originated on. */
@@ -334,7 +158,7 @@ declare class VectoJSEvent<N = unknown> {
334
158
  * }
335
159
  * }
336
160
  */
337
- declare abstract class Entity {
161
+ export declare abstract class Entity {
338
162
  id: string;
339
163
  children: Entity[];
340
164
  parent: Entity | null;
@@ -342,12 +166,28 @@ declare abstract class Entity {
342
166
  * Walk up the parent chain to find the scene this entity is currently attached to.
343
167
  */
344
168
  get scene(): any;
345
- x: number;
346
- y: number;
347
- scaleX: number;
348
- scaleY: number;
349
- rotation: number;
350
- opacity: number;
169
+ private _x;
170
+ private _y;
171
+ private _scaleX;
172
+ private _scaleY;
173
+ private _rotation;
174
+ private _opacity;
175
+ private _hasTransitions;
176
+ private _transitions;
177
+ private _drivers;
178
+ private _mounted;
179
+ get x(): number;
180
+ set x(v: number);
181
+ get y(): number;
182
+ set y(v: number);
183
+ get scaleX(): number;
184
+ set scaleX(v: number);
185
+ get scaleY(): number;
186
+ set scaleY(v: number);
187
+ get rotation(): number;
188
+ set rotation(v: number);
189
+ get opacity(): number;
190
+ set opacity(v: number);
351
191
  isDOMPortal: boolean;
352
192
  private _interactive;
353
193
  get interactive(): boolean;
@@ -383,6 +223,10 @@ declare abstract class Entity {
383
223
  * @returns `this` for method chaining.
384
224
  */
385
225
  add(child: Entity): this;
226
+ /** Called once when this entity becomes attached to a live Scene. Override to react. */
227
+ protected onMounted(): void;
228
+ /** Fire onMounted for this node and its descendants, guarded against double-fire. */
229
+ private _notifyMounted;
386
230
  /**
387
231
  * Remove a child entity from this node.
388
232
  *
@@ -411,6 +255,26 @@ declare abstract class Entity {
411
255
  * @example entity.animate({ x: 400, opacity: 0 }, 500);
412
256
  */
413
257
  animate(targetProps: Partial<this>, durationMs: number): this;
258
+ /** Write a driver-computed value to a backing field without re-triggering the setter. */
259
+ private _applyAnimated;
260
+ private _currentOf;
261
+ /**
262
+ * Write a value immediately, bypassing any configured transition. For subclasses
263
+ * that need to seed a starting state (e.g. the presence helper's enter `from`).
264
+ */
265
+ protected setImmediate(prop: AnimatableProp, v: number): void;
266
+ private _spawnDriver;
267
+ /** Assignment path when a declarative transition is configured for `prop`. */
268
+ private _animateProp;
269
+ /** Declare which properties animate, and how. Subsequent assignment animates them. */
270
+ setTransition(config: Partial<Record<AnimatableProp, MotionConfig>>): this;
271
+ /** Imperative tween toward targets; resolves when all reach their end. */
272
+ animateTo(props: Partial<Record<AnimatableProp, number>>, cfg: TweenConfig): Promise<void>;
273
+ /** Imperative spring toward targets; resolves when all reach rest. */
274
+ springTo(props: Partial<Record<AnimatableProp, number>>, cfg?: SpringConfig): Promise<void>;
275
+ private _driveTo;
276
+ /** Advance active property drivers one frame. Call from update(). */
277
+ protected tickDrivers(dt: number): void;
414
278
  /**
415
279
  * Advance the entity's internal state for one frame.
416
280
  *
@@ -420,7 +284,7 @@ declare abstract class Entity {
420
284
  * @param dt - Elapsed time since the last frame in milliseconds.
421
285
  * @param time - Absolute timestamp from `performance.now()`.
422
286
  */
423
- update(_dt: number, time: number): void;
287
+ update(dt: number, time: number): void;
424
288
  /**
425
289
  * Register a listener for a {@link VectoEvent}.
426
290
  *
@@ -568,5 +432,3 @@ declare abstract class Entity {
568
432
  */
569
433
  abstract render(renderer: any): void;
570
434
  }
571
-
572
- export { type A11yAttributes as A, type Bounds as B, Entity as E, type IRenderer as I, type ListenerOptions as L, type Point as P, type VectoEvent as V, type BatchCircle as a, type BatchRect as b, VectoJSEvent as c };
@@ -0,0 +1,295 @@
1
+ export interface IWebGLPointRenderer {
2
+ resize(width: number, height: number): void;
3
+ }
4
+ export type WebGLPointRendererCreator = (canvas: HTMLCanvasElement) => any;
5
+ export interface IWebGPUParticleSystemManager {
6
+ new (device: GPUDevice): any;
7
+ initPipelines(format: GPUTextureFormat): Promise<void> | void;
8
+ setupEntityResources(entity: any): void;
9
+ recordComputePass(pass: GPUComputePassEncoder, entity: any, dt: number, mouseX: number, mouseY: number, width: number, height: number): void;
10
+ recordRenderPass(renderPassEncoder: GPURenderPassEncoder, entity: any): void;
11
+ destroy(): void;
12
+ }
13
+ import { Entity } from './Entity';
14
+ import { IRenderer } from '../renderer/IRenderer';
15
+ /**
16
+ * Options for {@link Scene}.
17
+ */
18
+ export interface SceneOptions {
19
+ /**
20
+ * Backend for `getBatchCircle()` point-cloud entities:
21
+ * - `'canvas'` (default): the Canvas2D order-preserving same-color batch.
22
+ * - `'webgl'`: a stacked WebGL2 layer drawing all such circles in one draw
23
+ * call (10–100× throughput for 100k+). Auto-falls back to `'canvas'` when
24
+ * WebGL2 is unavailable. The GL layer composites above the 2D content, so its
25
+ * points don't interleave per-entity with 2D draws.
26
+ */
27
+ pointBackend?: 'canvas' | 'webgl';
28
+ /**
29
+ * Backend for particle simulation and rendering:
30
+ * - `'auto'` (default): tries WebGPU first, falls back to CPU if WebGPU is unavailable or fails.
31
+ * - `'webgpu'`: forces WebGPU.
32
+ * - `'cpu'`: forces CPU simulation and rendering (disabling WebGPU completely).
33
+ */
34
+ particleBackend?: 'auto' | 'webgpu' | 'cpu';
35
+ /**
36
+ * Render the accessibility/automation shadow nodes with a visible blue dashed
37
+ * outline (development aid). Default `false`: shadow nodes are transparent
38
+ * (`opacity:0`) — still operable by Playwright/assistive tech, but the canvas
39
+ * is the only thing seen.
40
+ */
41
+ debugA11y?: boolean;
42
+ /**
43
+ * Cap the render loop to at most this many frames per second (power saving —
44
+ * e.g. a quieter fan in a library). `0` (default) means uncapped (native
45
+ * refresh rate). Continuous animations still run, just less often. Also
46
+ * settable later via {@link Scene.maxFPS}.
47
+ */
48
+ maxFPS?: number;
49
+ /**
50
+ * When `true` (default), a system **prefers-reduced-motion** setting auto-caps
51
+ * the loop to {@link REDUCED_MOTION_FPS} (or the lower of that and `maxFPS`).
52
+ * Set `false` to ignore the OS setting.
53
+ */
54
+ respectReducedMotion?: boolean;
55
+ /**
56
+ * Throttle the accessibility/automation shadow-DOM sync to at most once per this
57
+ * many milliseconds. `0` (default) syncs every rendered frame. During heavy
58
+ * animation, a small value (e.g. `100`) keeps the a11y layer eventually
59
+ * consistent while sparing the per-frame DOM writes that can drag Canvas FPS.
60
+ * Also settable later via {@link Scene.a11ySyncInterval}.
61
+ */
62
+ a11ySyncInterval?: number;
63
+ /**
64
+ * Custom renderer implementation (e.g., ThreeRenderer from @vectojs/three).
65
+ * If provided, this renderer will be used for drawing rather than the default CanvasRenderer.
66
+ */
67
+ renderer?: IRenderer;
68
+ /**
69
+ * Disable the automatic registration of window resize listener.
70
+ * Useful when Vecto is running inside a custom layout container or offscreen canvas.
71
+ */
72
+ disableWindowResize?: boolean;
73
+ }
74
+ /** Frame-rate the loop is capped to when the OS requests reduced motion. */
75
+ export declare const REDUCED_MOTION_FPS = 30;
76
+ export interface A11yTreeNode {
77
+ id: string;
78
+ tag: string;
79
+ role?: string;
80
+ label?: string;
81
+ value?: string;
82
+ checked?: boolean;
83
+ expanded?: boolean;
84
+ valuemin?: string;
85
+ valuemax?: string;
86
+ children: A11yTreeNode[];
87
+ }
88
+ /**
89
+ * Top-level orchestrator that owns the entity tree, drive the render loop,
90
+ * and maintains the accessibility/automation shadow layer.
91
+ *
92
+ * Create one `Scene` per `<canvas>` element. Add {@link Entity} objects via
93
+ * {@link add}, then call {@link start} to begin the 60-FPS render loop.
94
+ *
95
+ * @example
96
+ * const scene = new Scene(document.querySelector('canvas')!);
97
+ * scene.add(new CircleEntity().setPosition(100, 100));
98
+ * scene.start();
99
+ */
100
+ export declare class Scene {
101
+ private static webglCreator;
102
+ private static webgpuManagerClass;
103
+ static registerWebGLPointRendererCreator(creator: WebGLPointRendererCreator): void;
104
+ static registerWebGPUParticleSystemManager(managerClass: any): void;
105
+ private root;
106
+ overlayRoot: Entity;
107
+ private renderer;
108
+ private isRunning;
109
+ private lastTime;
110
+ canvas: HTMLCanvasElement;
111
+ /**
112
+ * Redraw strategy:
113
+ * - `'always'` (default): re-render every animation frame (legacy behavior).
114
+ * - `'onDemand'`: only re-render when the scene is marked dirty (via
115
+ * {@link markDirty}) or while an animation is pending. Ideal for static /
116
+ * event-driven UIs where idle frames should cost ~0.
117
+ */
118
+ renderMode: 'always' | 'onDemand';
119
+ private dirty;
120
+ /**
121
+ * Frame-rate cap (power saving). `0` = uncapped (native refresh). When set,
122
+ * the loop renders at most `maxFPS` times per second; animations still run,
123
+ * just less often. See {@link SceneOptions.maxFPS}.
124
+ */
125
+ maxFPS: number;
126
+ /** Whether the OS prefers-reduced-motion setting auto-caps the loop. */
127
+ respectReducedMotion: boolean;
128
+ /** Cached media-query list; `.matches` is read live each frame. */
129
+ private reducedMotionQuery;
130
+ /** True when the OS asks for reduced motion and we respect it. Read by the animation drivers. */
131
+ get prefersReducedMotion(): boolean;
132
+ /**
133
+ * Throttle interval (ms) for the a11y/automation shadow sync. `0` = every
134
+ * frame. See {@link SceneOptions.a11ySyncInterval}.
135
+ */
136
+ a11ySyncInterval: number;
137
+ /** Timestamp of the last a11y sync, for throttling. */
138
+ private lastA11ySync;
139
+ /** True if we skipped an a11y sync during animation and need to sync when at rest. */
140
+ private a11yPendingSyncAfterAnimation;
141
+ private a11yRoot;
142
+ private a11yElements;
143
+ private resizeHandler;
144
+ private focusedA11yElement;
145
+ private caretBlinkTimer;
146
+ a11yNeedsReorder: boolean;
147
+ private portalRoot;
148
+ private fullViewportElements;
149
+ private normalElements;
150
+ private activeIds;
151
+ private activePortalsThisFrame;
152
+ private activePortalsPrevFrame;
153
+ private portalEntities;
154
+ private renderOrderCounter;
155
+ private pointRenderer;
156
+ private glCanvas;
157
+ private debugA11y;
158
+ width: number;
159
+ height: number;
160
+ private disableWindowResize;
161
+ private destroyed;
162
+ private device;
163
+ private deviceLost;
164
+ particleBackend: 'auto' | 'webgpu' | 'cpu';
165
+ private _webgpuDisabled;
166
+ get webgpuDisabled(): boolean;
167
+ set webgpuDisabled(value: boolean);
168
+ private recoveryTimerId;
169
+ private manager;
170
+ private initializingWebGPU;
171
+ private gpuCanvas;
172
+ private gpuContext;
173
+ private mouseX;
174
+ private mouseY;
175
+ private pointerMoveListener;
176
+ private pointerLeaveListener;
177
+ private hasWarnedZeroSize;
178
+ constructor(canvas: HTMLCanvasElement, options?: SceneOptions);
179
+ /**
180
+ * Expose the underlying {@link IRenderer} for advanced direct-draw operations.
181
+ *
182
+ * @returns The active renderer instance.
183
+ */
184
+ getRenderer(): IRenderer;
185
+ /**
186
+ * Add a top-level entity to the scene graph.
187
+ *
188
+ * @param entity - The entity to attach to the scene root.
189
+ * @returns `this` for method chaining.
190
+ * @example scene.add(new CircleEntity());
191
+ */
192
+ add(entity: Entity): this;
193
+ private removeA11yRecursively;
194
+ /**
195
+ * Remove a top-level entity from the scene graph and clean up its
196
+ * accessibility shadow elements recursively.
197
+ *
198
+ * @param entity - The entity to detach from the scene root.
199
+ * @returns `this` for method chaining.
200
+ */
201
+ remove(entity: Entity): this;
202
+ /**
203
+ * Tear down the a11y/automation shadow nodes for `entity` and its descendants
204
+ * without removing it from the scene graph. Components that manage dynamic
205
+ * interactive *child* entities (e.g. a {@link Entity}'s per-link hotspots) call
206
+ * this before discarding those children so their shadow `<a>`/controls don't
207
+ * leak (the per-frame `syncA11y` only creates/updates, it never prunes).
208
+ *
209
+ * @param entity - The subtree whose shadow nodes should be removed.
210
+ */
211
+ detachA11y(entity: Entity): void;
212
+ /**
213
+ * Add an overlay entity to the overlay root, bypassing main tree clipping bounds.
214
+ */
215
+ showOverlay(overlay: Entity): void;
216
+ /**
217
+ * Remove an overlay entity from the overlay root.
218
+ */
219
+ hideOverlay(overlay: Entity): void;
220
+ /**
221
+ * Tear down the Scene, halt the loop, and clean up event listeners and DOM elements.
222
+ */
223
+ destroy(): void;
224
+ private setupEvents;
225
+ /**
226
+ * Begin the `requestAnimationFrame` render loop.
227
+ *
228
+ * Idempotent — calling `start()` on an already-running scene is a no-op.
229
+ */
230
+ start(): void;
231
+ /** Schedule the next frame, or no-op where `requestAnimationFrame` is absent (SSR). */
232
+ private scheduleFrame;
233
+ /**
234
+ * Halt the render loop after the current frame completes.
235
+ *
236
+ * Call {@link start} again to resume rendering.
237
+ */
238
+ stop(): void;
239
+ /**
240
+ * Mark the scene as needing a redraw on the next frame.
241
+ *
242
+ * Only meaningful in `onDemand` {@link renderMode}: call it after mutating
243
+ * entity state outside of {@link Entity.animate} so the change is rendered.
244
+ */
245
+ markDirty(): void;
246
+ /** True when any node in the subtree has a pending animation. */
247
+ private hasAnyPendingAnimation;
248
+ /** True when any node in the subtree is interactive (drives a11y sync). */
249
+ private hasAnyInteractive;
250
+ private syncA11y;
251
+ private enforceA11yDomOrder;
252
+ getA11yTree(): A11yTreeNode[];
253
+ private renderPortalDOM;
254
+ private reconcilePortals;
255
+ /**
256
+ * The frame-rate cap actually in effect: the explicit {@link maxFPS}, further
257
+ * lowered to {@link REDUCED_MOTION_FPS} when the OS requests reduced motion
258
+ * (and {@link respectReducedMotion} is on). `0` means uncapped.
259
+ */
260
+ private effectiveMaxFPS;
261
+ private loop;
262
+ /**
263
+ * Render the entire scene graph onto the specified renderer.
264
+ *
265
+ * @param renderer - The renderer instance to draw to.
266
+ * @param dt - Delta time in milliseconds (default 0).
267
+ * @param time - Current absolute time in milliseconds (default 0).
268
+ */
269
+ render(renderer: IRenderer, dt?: number, time?: number): void;
270
+ /**
271
+ * Export the current scene state to a lightweight, flat SVG XML string.
272
+ */
273
+ toSVG(): string;
274
+ /**
275
+ * Manually resize the Scene's viewport.
276
+ */
277
+ resize(width: number, height: number): void;
278
+ /**
279
+ * Gets the accessibility DOM element projected for the given entity ID.
280
+ */
281
+ getA11yElement(entityId: string): HTMLElement | undefined;
282
+ /**
283
+ * Gets the root entity of the scene.
284
+ */
285
+ getRoot(): Entity;
286
+ /**
287
+ * Finds the topmost interactive entity at the given coordinates.
288
+ */
289
+ findEntityAt(x: number, y: number): Entity | null;
290
+ private initWebGPUContext;
291
+ private setupDeviceLostHandler;
292
+ private recreateWebGPUDeviceWithRetry;
293
+ private renderCPUParticles;
294
+ private findHitRecursively;
295
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vectojs/core",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -35,17 +35,17 @@
35
35
  "require": "./dist/index.js"
36
36
  },
37
37
  "./layout": {
38
- "types": "./dist/layout.d.ts",
38
+ "types": "./dist/layout/index.d.ts",
39
39
  "import": "./dist/layout.mjs",
40
40
  "require": "./dist/layout.js"
41
41
  },
42
42
  "./renderer": {
43
- "types": "./dist/renderer.d.ts",
43
+ "types": "./dist/renderer/index.d.ts",
44
44
  "import": "./dist/renderer.mjs",
45
45
  "require": "./dist/renderer.js"
46
46
  },
47
47
  "./text": {
48
- "types": "./dist/text.d.ts",
48
+ "types": "./dist/text/index.d.ts",
49
49
  "import": "./dist/text.mjs",
50
50
  "require": "./dist/text.js"
51
51
  }
@@ -54,7 +54,7 @@
54
54
  "dist"
55
55
  ],
56
56
  "scripts": {
57
- "build": "node scripts/build-worker.js && tsup",
57
+ "build": "node scripts/build-worker.js && tsup && tsc -p tsconfig.build.json",
58
58
  "test": "vitest run"
59
59
  },
60
60
  "dependencies": {},