@vectojs/core 0.1.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.
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-M2IZPGOL.mjs → chunk-H3QIE77O.mjs} +316 -12
  4. package/dist/{chunk-53DAQC3U.js → chunk-LA3FJLP2.js} +369 -65
  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 +121 -136
  10. package/dist/index.mjs +19 -34
  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} +71 -201
  37. package/dist/tree/Scene.d.ts +302 -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
@@ -0,0 +1,302 @@
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
+ * 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;
78
+ }
79
+ /** Frame-rate the loop is capped to when the OS requests reduced motion. */
80
+ export declare const REDUCED_MOTION_FPS = 30;
81
+ export interface A11yTreeNode {
82
+ id: string;
83
+ tag: string;
84
+ role?: string;
85
+ label?: string;
86
+ value?: string;
87
+ checked?: boolean;
88
+ expanded?: boolean;
89
+ valuemin?: string;
90
+ valuemax?: string;
91
+ children: A11yTreeNode[];
92
+ }
93
+ /**
94
+ * Top-level orchestrator that owns the entity tree, drive the render loop,
95
+ * and maintains the accessibility/automation shadow layer.
96
+ *
97
+ * Create one `Scene` per `<canvas>` element. Add {@link Entity} objects via
98
+ * {@link add}, then call {@link start} to begin the 60-FPS render loop.
99
+ *
100
+ * @example
101
+ * const scene = new Scene(document.querySelector('canvas')!);
102
+ * scene.add(new CircleEntity().setPosition(100, 100));
103
+ * scene.start();
104
+ */
105
+ export declare class Scene {
106
+ private static webglCreator;
107
+ private static webgpuManagerClass;
108
+ static registerWebGLPointRendererCreator(creator: WebGLPointRendererCreator): void;
109
+ static registerWebGPUParticleSystemManager(managerClass: any): void;
110
+ private root;
111
+ overlayRoot: Entity;
112
+ private renderer;
113
+ private isRunning;
114
+ private lastTime;
115
+ canvas: HTMLCanvasElement;
116
+ /**
117
+ * Redraw strategy:
118
+ * - `'always'` (default): re-render every animation frame (legacy behavior).
119
+ * - `'onDemand'`: only re-render when the scene is marked dirty (via
120
+ * {@link markDirty}) or while an animation is pending. Ideal for static /
121
+ * event-driven UIs where idle frames should cost ~0.
122
+ */
123
+ renderMode: 'always' | 'onDemand';
124
+ private dirty;
125
+ /** Whether to throttle rendering to 2 FPS when the scene is static to save power. */
126
+ autoThrottle: boolean;
127
+ /**
128
+ * Frame-rate cap (power saving). `0` = uncapped (native refresh). When set,
129
+ * the loop renders at most `maxFPS` times per second; animations still run,
130
+ * just less often. See {@link SceneOptions.maxFPS}.
131
+ */
132
+ maxFPS: number;
133
+ /** Whether the OS prefers-reduced-motion setting auto-caps the loop. */
134
+ respectReducedMotion: boolean;
135
+ /** Cached media-query list; `.matches` is read live each frame. */
136
+ private reducedMotionQuery;
137
+ /** True when the OS asks for reduced motion and we respect it. Read by the animation drivers. */
138
+ get prefersReducedMotion(): boolean;
139
+ /**
140
+ * Throttle interval (ms) for the a11y/automation shadow sync. `0` = every
141
+ * frame. See {@link SceneOptions.a11ySyncInterval}.
142
+ */
143
+ a11ySyncInterval: number;
144
+ /** Timestamp of the last a11y sync, for throttling. */
145
+ private lastA11ySync;
146
+ /** True if we skipped an a11y sync during animation and need to sync when at rest. */
147
+ private a11yPendingSyncAfterAnimation;
148
+ private a11yRoot;
149
+ private a11yElements;
150
+ private resizeHandler;
151
+ private focusedA11yElement;
152
+ private caretBlinkTimer;
153
+ a11yNeedsReorder: boolean;
154
+ private portalRoot;
155
+ private fullViewportElements;
156
+ private normalElements;
157
+ private activeIds;
158
+ private activePortalsThisFrame;
159
+ private activePortalsPrevFrame;
160
+ private portalEntities;
161
+ private renderOrderCounter;
162
+ private pointRenderer;
163
+ private glCanvas;
164
+ private debugA11y;
165
+ width: number;
166
+ height: number;
167
+ private disableWindowResize;
168
+ private destroyed;
169
+ private device;
170
+ private deviceLost;
171
+ particleBackend: 'auto' | 'webgpu' | 'cpu';
172
+ private _webgpuDisabled;
173
+ get webgpuDisabled(): boolean;
174
+ set webgpuDisabled(value: boolean);
175
+ private recoveryTimerId;
176
+ private manager;
177
+ private initializingWebGPU;
178
+ private gpuCanvas;
179
+ private gpuContext;
180
+ private mouseX;
181
+ private mouseY;
182
+ private pointerMoveListener;
183
+ private pointerLeaveListener;
184
+ private hasWarnedZeroSize;
185
+ constructor(canvas: HTMLCanvasElement, options?: SceneOptions);
186
+ /**
187
+ * Expose the underlying {@link IRenderer} for advanced direct-draw operations.
188
+ *
189
+ * @returns The active renderer instance.
190
+ */
191
+ getRenderer(): IRenderer;
192
+ /**
193
+ * Add a top-level entity to the scene graph.
194
+ *
195
+ * @param entity - The entity to attach to the scene root.
196
+ * @returns `this` for method chaining.
197
+ * @example scene.add(new CircleEntity());
198
+ */
199
+ add(entity: Entity): this;
200
+ private removeA11yRecursively;
201
+ /**
202
+ * Remove a top-level entity from the scene graph and clean up its
203
+ * accessibility shadow elements recursively.
204
+ *
205
+ * @param entity - The entity to detach from the scene root.
206
+ * @returns `this` for method chaining.
207
+ */
208
+ remove(entity: Entity): this;
209
+ /**
210
+ * Tear down the a11y/automation shadow nodes for `entity` and its descendants
211
+ * without removing it from the scene graph. Components that manage dynamic
212
+ * interactive *child* entities (e.g. a {@link Entity}'s per-link hotspots) call
213
+ * this before discarding those children so their shadow `<a>`/controls don't
214
+ * leak (the per-frame `syncA11y` only creates/updates, it never prunes).
215
+ *
216
+ * @param entity - The subtree whose shadow nodes should be removed.
217
+ */
218
+ detachA11y(entity: Entity): void;
219
+ /**
220
+ * Add an overlay entity to the overlay root, bypassing main tree clipping bounds.
221
+ */
222
+ showOverlay(overlay: Entity): void;
223
+ /**
224
+ * Remove an overlay entity from the overlay root.
225
+ */
226
+ hideOverlay(overlay: Entity): void;
227
+ /**
228
+ * Tear down the Scene, halt the loop, and clean up event listeners and DOM elements.
229
+ */
230
+ destroy(): void;
231
+ private setupEvents;
232
+ /**
233
+ * Begin the `requestAnimationFrame` render loop.
234
+ *
235
+ * Idempotent — calling `start()` on an already-running scene is a no-op.
236
+ */
237
+ start(): void;
238
+ /** Schedule the next frame, or no-op where `requestAnimationFrame` is absent (SSR). */
239
+ private scheduleFrame;
240
+ /**
241
+ * Halt the render loop after the current frame completes.
242
+ *
243
+ * Call {@link start} again to resume rendering.
244
+ */
245
+ stop(): void;
246
+ /**
247
+ * Mark the scene as needing a redraw on the next frame.
248
+ *
249
+ * Only meaningful in `onDemand` {@link renderMode}: call it after mutating
250
+ * entity state outside of {@link Entity.animate} so the change is rendered.
251
+ */
252
+ markDirty(): void;
253
+ /** True when any node in the subtree has a pending animation. */
254
+ private hasAnyPendingAnimation;
255
+ /** True when any node in the subtree is interactive (drives a11y sync). */
256
+ private hasAnyInteractive;
257
+ private syncA11y;
258
+ private enforceA11yDomOrder;
259
+ getA11yTree(): A11yTreeNode[];
260
+ private renderPortalDOM;
261
+ private reconcilePortals;
262
+ /**
263
+ * The frame-rate cap actually in effect: the explicit {@link maxFPS}, further
264
+ * lowered to {@link REDUCED_MOTION_FPS} when the OS requests reduced motion
265
+ * (and {@link respectReducedMotion} is on). `0` means uncapped.
266
+ */
267
+ private effectiveMaxFPS;
268
+ private loop;
269
+ /**
270
+ * Render the entire scene graph onto the specified renderer.
271
+ *
272
+ * @param renderer - The renderer instance to draw to.
273
+ * @param dt - Delta time in milliseconds (default 0).
274
+ * @param time - Current absolute time in milliseconds (default 0).
275
+ */
276
+ render(renderer: IRenderer, dt?: number, time?: number): void;
277
+ /**
278
+ * Export the current scene state to a lightweight, flat SVG XML string.
279
+ */
280
+ toSVG(): string;
281
+ /**
282
+ * Manually resize the Scene's viewport.
283
+ */
284
+ resize(width: number, height: number): void;
285
+ /**
286
+ * Gets the accessibility DOM element projected for the given entity ID.
287
+ */
288
+ getA11yElement(entityId: string): HTMLElement | undefined;
289
+ /**
290
+ * Gets the root entity of the scene.
291
+ */
292
+ getRoot(): Entity;
293
+ /**
294
+ * Finds the topmost interactive entity at the given coordinates.
295
+ */
296
+ findEntityAt(x: number, y: number): Entity | null;
297
+ private initWebGPUContext;
298
+ private setupDeviceLostHandler;
299
+ private recreateWebGPUDeviceWithRetry;
300
+ private renderCPUParticles;
301
+ private findHitRecursively;
302
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vectojs/core",
3
- "version": "0.1.0",
3
+ "version": "0.2.1",
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": {},