@vectojs/core 0.2.3 → 0.2.4
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/README.md +110 -33
- package/dist/{chunk-6I53LI3Z.js → chunk-76NMTLYL.js} +1 -1
- package/dist/{chunk-YSS44ADQ.mjs → chunk-B3Z3JEJH.mjs} +1 -1
- package/dist/{chunk-VVOQNUBK.js → chunk-IKLYTHAL.js} +8 -8
- package/dist/{chunk-LIOJ37MH.mjs → chunk-MCULB5VC.mjs} +1 -1
- package/dist/{chunk-ISGOYXPF.mjs → chunk-P6MDWIEX.mjs} +40 -10
- package/dist/{chunk-TXA3LZDM.js → chunk-TPNADFNN.js} +58 -9
- package/dist/{chunk-KPWVPGHR.js → chunk-TQ4H357Q.js} +42 -12
- package/dist/{chunk-NKOQV3RM.mjs → chunk-WEQRBXT2.mjs} +58 -9
- package/dist/index.js +33 -32
- package/dist/index.mjs +5 -4
- package/dist/layout/LayoutWorkerSource.d.ts +1 -1
- package/dist/layout.js +3 -3
- package/dist/layout.mjs +2 -2
- package/dist/renderer.js +2 -2
- package/dist/renderer.mjs +1 -1
- package/dist/text.js +3 -3
- package/dist/text.mjs +2 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,55 +1,132 @@
|
|
|
1
1
|
# @vectojs/core
|
|
2
2
|
|
|
3
|
-
>
|
|
4
|
-
> Tree with an accessibility/automation projection layer.
|
|
3
|
+
> Scene, layout, interaction, text, rendering, and semantic projection for canvas-native interfaces.
|
|
5
4
|
|
|
6
|
-
|
|
5
|
+
[](https://www.npmjs.com/package/@vectojs/core)
|
|
6
|
+
[](https://github.com/vectojs/vectojs/actions/workflows/ci.yml)
|
|
7
|
+
[](https://github.com/vectojs/vectojs/blob/main/LICENSE)
|
|
7
8
|
|
|
8
|
-
|
|
9
|
+
`@vectojs/core` is the runtime beneath VectoJS. It owns the retained `Scene`/`Entity` tree, affine
|
|
10
|
+
transforms, render scheduling, layout, text flow, spatial hit-testing, event propagation, renderer
|
|
11
|
+
backends, and the accessibility/automation projection layer.
|
|
9
12
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
transparent DOM node through the **`a11yRoot`** shadow layer, so a pure-canvas page stays
|
|
14
|
-
accessible and drivable by assistive tech and AI agents.
|
|
13
|
+
[Core guide](https://vectojs.xuepoo.xyz/learn/core-scene/) ·
|
|
14
|
+
[API reference](https://vectojs.xuepoo.xyz/reference/core-api/) ·
|
|
15
|
+
[Main repository](https://github.com/vectojs/vectojs)
|
|
15
16
|
|
|
16
|
-
|
|
17
|
-
with a cold/hot `prepare`/`layoutPrepared` split), `SpatialHashGrid`, `LayoutResultBuffer`
|
|
18
|
-
(reusable typed storage), `SplineEntity` (native vectomancy math-curve rendering + curve-accurate hit-testing),
|
|
19
|
-
`CanvasRenderer`, and a `WebGLPointRenderer` point/rect batch layer.
|
|
17
|
+
## Install
|
|
20
18
|
|
|
21
|
-
|
|
19
|
+
```bash
|
|
20
|
+
bun add @vectojs/core
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Minimal scene
|
|
22
24
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
on-demand redraw, draw-call batching, a WebGL2 point layer, and a cold/hot text layout split.
|
|
26
|
-
Results are machine- and workload-dependent.
|
|
25
|
+
```ts
|
|
26
|
+
import { Entity, type IRenderer, Scene } from '@vectojs/core';
|
|
27
27
|
|
|
28
|
-
|
|
28
|
+
class Dot extends Entity {
|
|
29
|
+
constructor() {
|
|
30
|
+
super();
|
|
31
|
+
this.width = 48;
|
|
32
|
+
this.height = 48;
|
|
33
|
+
this.interactive = true;
|
|
34
|
+
this.on('click', () => this.animate({ scaleX: 1.25, scaleY: 1.25 }, 120));
|
|
35
|
+
}
|
|
29
36
|
|
|
30
|
-
|
|
31
|
-
|
|
37
|
+
isPointInside(globalX: number, globalY: number): boolean {
|
|
38
|
+
const local = this.worldToLocal(globalX, globalY);
|
|
39
|
+
return !!local && Math.hypot(local.x - 24, local.y - 24) <= 24;
|
|
40
|
+
}
|
|
32
41
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
return Math.hypot(x - this.x, y - this.y) < 50;
|
|
42
|
+
getA11yAttributes() {
|
|
43
|
+
return { tag: 'button' as const, role: 'button', label: 'Animated dot' };
|
|
36
44
|
}
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
45
|
+
|
|
46
|
+
render(renderer: IRenderer): void {
|
|
47
|
+
renderer.beginPath();
|
|
48
|
+
renderer.arc(24, 24, 24, 0, Math.PI * 2);
|
|
49
|
+
renderer.fill('#22d3ee');
|
|
41
50
|
}
|
|
42
51
|
}
|
|
43
52
|
|
|
44
|
-
const canvas = document.querySelector('canvas')!;
|
|
53
|
+
const canvas = document.querySelector<HTMLCanvasElement>('canvas')!;
|
|
45
54
|
const scene = new Scene(canvas);
|
|
46
|
-
scene.
|
|
55
|
+
scene.renderMode = 'onDemand';
|
|
56
|
+
scene.add(new Dot().setPosition(80, 80));
|
|
57
|
+
scene.start();
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## Runtime building blocks
|
|
61
|
+
|
|
62
|
+
| Area | Main APIs | Purpose |
|
|
63
|
+
| ----------- | ----------------------------------------------- | ---------------------------------------------------------------------- |
|
|
64
|
+
| Scene graph | `Scene`, `Entity` | ownership, transforms, lifecycle, update/render traversal |
|
|
65
|
+
| Layout | `LayoutEngine`, layout subpath | prepared text/rich-text layout, wrapping, exclusions, reusable buffers |
|
|
66
|
+
| Interaction | entity events, `SpatialHashGrid` | hit-testing and DOM-like capture/bubble dispatch |
|
|
67
|
+
| Text | `TextEntity`, `MSDFTextEntity`, `SplineEntity` | Canvas text, GPU text, and mathematical curves |
|
|
68
|
+
| Rendering | `IRenderer`, `CanvasRenderer`, renderer subpath | backend-neutral drawing contract and concrete renderers |
|
|
69
|
+
| GPU paths | WebGL point batching, WebGPU particles | high-volume points/rects and compute-driven particles |
|
|
70
|
+
| Semantics | `A11yAttributes`, Scene projection | role/name/state, native inputs, screen readers, Playwright/agents |
|
|
71
|
+
| Animation | `animate`, springs, transitions, `Scene.step()` | real-time or deterministic fixed-step motion |
|
|
72
|
+
|
|
73
|
+
## Scene lifecycle
|
|
74
|
+
|
|
75
|
+
```ts
|
|
76
|
+
const scene = new Scene(canvas, {
|
|
77
|
+
maxFPS: 60,
|
|
78
|
+
pointBackend: 'canvas', // or 'webgl'
|
|
79
|
+
particleBackend: 'cpu', // or 'webgpu' when supported
|
|
80
|
+
});
|
|
81
|
+
scene.renderMode = 'onDemand'; // redraw only when dirty
|
|
82
|
+
|
|
83
|
+
scene.resize(width, height); // logical CSS pixels
|
|
84
|
+
scene.markDirty();
|
|
47
85
|
scene.start();
|
|
86
|
+
scene.stop();
|
|
87
|
+
scene.step(1000 / 60); // deterministic single step
|
|
88
|
+
scene.destroy(); // release renderers, workers, observers, and semantic DOM
|
|
48
89
|
```
|
|
49
90
|
|
|
50
|
-
|
|
51
|
-
|
|
91
|
+
Always call `destroy()` when a framework component unmounts. A `Scene` owns browser observers,
|
|
92
|
+
renderer resources, layout work, and projected DOM nodes.
|
|
93
|
+
|
|
94
|
+
## Package entry points
|
|
95
|
+
|
|
96
|
+
```ts
|
|
97
|
+
import { Scene, Entity } from '@vectojs/core';
|
|
98
|
+
import { LayoutEngine } from '@vectojs/core/layout';
|
|
99
|
+
import type { IRenderer } from '@vectojs/core/renderer';
|
|
100
|
+
import { TextEntity } from '@vectojs/core/text';
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
Both ESM and CommonJS outputs are published with TypeScript declarations.
|
|
104
|
+
|
|
105
|
+
## Accessibility and automation
|
|
106
|
+
|
|
107
|
+
Canvas pixels have no semantics. Interactive entities can implement `getA11yAttributes()`; the
|
|
108
|
+
Scene projects transparent DOM nodes over their world-space bounds and forwards native input back
|
|
109
|
+
into the VectoJS event system.
|
|
110
|
+
|
|
111
|
+
This projection is intentionally thin. Applications still own accessible names, keyboard behavior,
|
|
112
|
+
focus order, contrast, and correct control semantics. See the
|
|
113
|
+
[accessibility guide](https://vectojs.xuepoo.xyz/learn/accessibility/).
|
|
114
|
+
|
|
115
|
+
## Performance model
|
|
116
|
+
|
|
117
|
+
Useful levers include on-demand rendering, viewport culling, spatial hashing, prepared text layout,
|
|
118
|
+
typed reusable buffers, batched WebGL points, and optional WebGPU particle compute. None makes every
|
|
119
|
+
workload allocation-free or GPU-bound; profile the renderer and entity types used by your app.
|
|
120
|
+
|
|
121
|
+
Run the repository benchmarks with `bun run benchmark`, `bun run compare:dom`, and
|
|
122
|
+
`bun run compare`.
|
|
123
|
+
|
|
124
|
+
## Related packages
|
|
125
|
+
|
|
126
|
+
- [`@vectojs/ui`](https://github.com/vectojs/vectojs/tree/main/packages/ui) — high-level accessible components
|
|
127
|
+
- [`@vectojs/three`](https://github.com/vectojs/vectojs/tree/main/packages/three) — Three.js/WebXR projection and raycast routing
|
|
128
|
+
- [`@vectojs/video-exporter`](https://github.com/vectojs/vectojs/tree/main/packages/video-exporter) — deterministic H.264 capture
|
|
52
129
|
|
|
53
130
|
## License
|
|
54
131
|
|
|
55
|
-
MIT © 2026 Xuepoo
|
|
132
|
+
[MIT](https://github.com/vectojs/vectojs/blob/main/LICENSE) © 2026 Xuepoo
|
|
@@ -296,7 +296,7 @@ var BidiResolver = class _BidiResolver {
|
|
|
296
296
|
};
|
|
297
297
|
|
|
298
298
|
// src/layout/LayoutWorkerSource.ts
|
|
299
|
-
var WORKER_SOURCE_STRING = '"use strict";(()=>{var
|
|
299
|
+
var WORKER_SOURCE_STRING = '"use strict";(()=>{var k=new Map;function n(t){return typeof t=="number"&&Number.isFinite(t)}function H(t){return t.origin?t.origin===self.location.origin:!0}function M(t){if(!t||typeof t!="object")return!1;let e=t;return typeof e.id=="string"&&n(e.seqId)&&typeof e.text=="string"&&typeof e.fontId=="string"&&(e.fontData===void 0||typeof e.fontData=="object")&&n(e.maxWidth)&&n(e.maxHeight)&&n(e.fontSize)&&(e.lineHeight===void 0||n(e.lineHeight))&&(e.letterSpacing===void 0||n(e.letterSpacing))}self.onmessage=t=>{if(!H(t)||!M(t.data))return;let{id:e,seqId:F,text:q,fontId:d,fontData:f,maxWidth:y,maxHeight:I,fontSize:i,lineHeight:A,letterSpacing:D}=t.data;f&&k.set(d,f);let s=k.get(d);if(!s)return;let g=[],l=[],p=[],m=[],o=0,a=0,h=s.metrics?.ascender??.8,W=s.metrics?.descender??-.2,b=A??i*(h-W),x=Array.from(q);for(let c=0;c<x.length;c++){let u=x[c].codePointAt(0),S=(s.glyphs?.find(C=>C.unicode===u)?.advance??1)*i;o+S>y&&u===32&&(o=0,a++),g.push(u),l.push(o);let w=a*b+h*i;p.push(w),m.push(-256),o+=S+(D??0)}let r={id:e,seqId:F,width:Math.min(o,y),height:(a+1)*b,codePoints:new Uint32Array(g),xCoords:new Float32Array(l),yCoords:new Float32Array(p),packedStyles:new Uint32Array(m)};self.postMessage(r,[r.codePoints.buffer,r.xCoords.buffer,r.yCoords.buffer,r.packedStyles.buffer])};})();\n';
|
|
300
300
|
|
|
301
301
|
// src/layout/LayoutWorkerManager.ts
|
|
302
302
|
var LayoutWorkerManager = (_class2 = class _LayoutWorkerManager {
|
|
@@ -296,7 +296,7 @@ var BidiResolver = class _BidiResolver {
|
|
|
296
296
|
};
|
|
297
297
|
|
|
298
298
|
// src/layout/LayoutWorkerSource.ts
|
|
299
|
-
var WORKER_SOURCE_STRING = '"use strict";(()=>{var
|
|
299
|
+
var WORKER_SOURCE_STRING = '"use strict";(()=>{var k=new Map;function n(t){return typeof t=="number"&&Number.isFinite(t)}function H(t){return t.origin?t.origin===self.location.origin:!0}function M(t){if(!t||typeof t!="object")return!1;let e=t;return typeof e.id=="string"&&n(e.seqId)&&typeof e.text=="string"&&typeof e.fontId=="string"&&(e.fontData===void 0||typeof e.fontData=="object")&&n(e.maxWidth)&&n(e.maxHeight)&&n(e.fontSize)&&(e.lineHeight===void 0||n(e.lineHeight))&&(e.letterSpacing===void 0||n(e.letterSpacing))}self.onmessage=t=>{if(!H(t)||!M(t.data))return;let{id:e,seqId:F,text:q,fontId:d,fontData:f,maxWidth:y,maxHeight:I,fontSize:i,lineHeight:A,letterSpacing:D}=t.data;f&&k.set(d,f);let s=k.get(d);if(!s)return;let g=[],l=[],p=[],m=[],o=0,a=0,h=s.metrics?.ascender??.8,W=s.metrics?.descender??-.2,b=A??i*(h-W),x=Array.from(q);for(let c=0;c<x.length;c++){let u=x[c].codePointAt(0),S=(s.glyphs?.find(C=>C.unicode===u)?.advance??1)*i;o+S>y&&u===32&&(o=0,a++),g.push(u),l.push(o);let w=a*b+h*i;p.push(w),m.push(-256),o+=S+(D??0)}let r={id:e,seqId:F,width:Math.min(o,y),height:(a+1)*b,codePoints:new Uint32Array(g),xCoords:new Float32Array(l),yCoords:new Float32Array(p),packedStyles:new Uint32Array(m)};self.postMessage(r,[r.codePoints.buffer,r.xCoords.buffer,r.yCoords.buffer,r.packedStyles.buffer])};})();\n';
|
|
300
300
|
|
|
301
301
|
// src/layout/LayoutWorkerManager.ts
|
|
302
302
|
var LayoutWorkerManager = class _LayoutWorkerManager {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; } var _class; var _class2;
|
|
2
2
|
|
|
3
3
|
|
|
4
|
-
var
|
|
4
|
+
var _chunk76NMTLYLjs = require('./chunk-76NMTLYL.js');
|
|
5
5
|
|
|
6
6
|
// src/layout/LayoutEngine.ts
|
|
7
7
|
function computeLineSegments(top, bottom, maxWidth, exclusions) {
|
|
@@ -142,8 +142,8 @@ var LayoutEngine = (_class = class {
|
|
|
142
142
|
offset += paragraph.length + 1;
|
|
143
143
|
continue;
|
|
144
144
|
}
|
|
145
|
-
const { shapedText, indexMap } =
|
|
146
|
-
const levels =
|
|
145
|
+
const { shapedText, indexMap } = _chunk76NMTLYLjs.ArabicShaper.shapeArabic(paragraph);
|
|
146
|
+
const levels = _chunk76NMTLYLjs.BidiResolver.resolveLevels(shapedText);
|
|
147
147
|
const words = [];
|
|
148
148
|
let shapedCharIdx = 0;
|
|
149
149
|
let pFallback = false;
|
|
@@ -192,7 +192,7 @@ var LayoutEngine = (_class = class {
|
|
|
192
192
|
words,
|
|
193
193
|
isEmpty: false,
|
|
194
194
|
fallbackToCanvas: pFallback || void 0,
|
|
195
|
-
baseLevel:
|
|
195
|
+
baseLevel: _chunk76NMTLYLjs.BidiResolver.getBaseLevel(shapedText)
|
|
196
196
|
};
|
|
197
197
|
if (this.paragraphCache.size > 1e3) this.paragraphCache.clear();
|
|
198
198
|
this.paragraphCache.set(key, prepared);
|
|
@@ -264,8 +264,8 @@ var LayoutEngine = (_class = class {
|
|
|
264
264
|
offset += paragraph.length + 1;
|
|
265
265
|
continue;
|
|
266
266
|
}
|
|
267
|
-
const { shapedText, indexMap } =
|
|
268
|
-
const levels =
|
|
267
|
+
const { shapedText, indexMap } = _chunk76NMTLYLjs.ArabicShaper.shapeArabic(paragraph);
|
|
268
|
+
const levels = _chunk76NMTLYLjs.BidiResolver.resolveLevels(shapedText);
|
|
269
269
|
const words = [];
|
|
270
270
|
let shapedCharIdx = 0;
|
|
271
271
|
let pFallback = false;
|
|
@@ -317,7 +317,7 @@ var LayoutEngine = (_class = class {
|
|
|
317
317
|
words,
|
|
318
318
|
isEmpty: false,
|
|
319
319
|
fallbackToCanvas: pFallback || void 0,
|
|
320
|
-
baseLevel:
|
|
320
|
+
baseLevel: _chunk76NMTLYLjs.BidiResolver.getBaseLevel(shapedText)
|
|
321
321
|
};
|
|
322
322
|
if (this.richParagraphCache.size > 1e3) this.richParagraphCache.clear();
|
|
323
323
|
this.richParagraphCache.set(key, prepared);
|
|
@@ -372,7 +372,7 @@ var LayoutEngine = (_class = class {
|
|
|
372
372
|
}
|
|
373
373
|
for (const run of runs) {
|
|
374
374
|
const runStartX = run[0].x;
|
|
375
|
-
|
|
375
|
+
_chunk76NMTLYLjs.BidiResolver.reorderVisual(run, paragraphBaseLevel);
|
|
376
376
|
let x = runStartX;
|
|
377
377
|
for (const node of run) {
|
|
378
378
|
node.x = x;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
LayoutWorkerManager
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-B3Z3JEJH.mjs";
|
|
4
4
|
|
|
5
5
|
// src/math/SpringPhysics.ts
|
|
6
6
|
var SpringPhysics = class {
|
|
@@ -1118,6 +1118,36 @@ var MSDFTextEntity = class extends Entity {
|
|
|
1118
1118
|
};
|
|
1119
1119
|
|
|
1120
1120
|
// src/text/SVGEntity.ts
|
|
1121
|
+
function isSvgWhitespace(ch) {
|
|
1122
|
+
return ch === " " || ch === " " || ch === "\n" || ch === "\r";
|
|
1123
|
+
}
|
|
1124
|
+
function readSvgAttribute(source, name) {
|
|
1125
|
+
const lowerSource = source.toLowerCase();
|
|
1126
|
+
const svgStart = lowerSource.indexOf("<svg");
|
|
1127
|
+
if (svgStart < 0) return null;
|
|
1128
|
+
const tagEnd = source.indexOf(">", svgStart + 4);
|
|
1129
|
+
if (tagEnd < 0) return null;
|
|
1130
|
+
const tag = source.slice(svgStart + 4, tagEnd);
|
|
1131
|
+
const lowerTag = tag.toLowerCase();
|
|
1132
|
+
const lowerName = name.toLowerCase();
|
|
1133
|
+
for (let i = 0; i < tag.length; i++) {
|
|
1134
|
+
const before = i === 0 ? " " : tag[i - 1];
|
|
1135
|
+
if (!isSvgWhitespace(before)) continue;
|
|
1136
|
+
if (!lowerTag.startsWith(lowerName, i)) continue;
|
|
1137
|
+
let cursor = i + lowerName.length;
|
|
1138
|
+
while (cursor < tag.length && isSvgWhitespace(tag[cursor])) cursor++;
|
|
1139
|
+
if (tag[cursor] !== "=") continue;
|
|
1140
|
+
cursor++;
|
|
1141
|
+
while (cursor < tag.length && isSvgWhitespace(tag[cursor])) cursor++;
|
|
1142
|
+
const quote = tag[cursor];
|
|
1143
|
+
if (quote !== '"' && quote !== "'") continue;
|
|
1144
|
+
const valueStart = cursor + 1;
|
|
1145
|
+
const valueEnd = tag.indexOf(quote, valueStart);
|
|
1146
|
+
if (valueEnd < 0) return null;
|
|
1147
|
+
return tag.slice(valueStart, valueEnd);
|
|
1148
|
+
}
|
|
1149
|
+
return null;
|
|
1150
|
+
}
|
|
1121
1151
|
var SVGEntity = class extends Entity {
|
|
1122
1152
|
svgSource = "";
|
|
1123
1153
|
imageBitmap = null;
|
|
@@ -1169,17 +1199,17 @@ var SVGEntity = class extends Entity {
|
|
|
1169
1199
|
}
|
|
1170
1200
|
}
|
|
1171
1201
|
} catch (e) {
|
|
1172
|
-
console.error("Failed parsing SVG via DOMParser, falling back to
|
|
1202
|
+
console.error("Failed parsing SVG via DOMParser, falling back to attribute scan:", e);
|
|
1173
1203
|
}
|
|
1174
1204
|
} else {
|
|
1175
|
-
const
|
|
1176
|
-
const
|
|
1177
|
-
const
|
|
1178
|
-
if (
|
|
1179
|
-
width = parseFloat(
|
|
1180
|
-
height = parseFloat(
|
|
1181
|
-
} else if (
|
|
1182
|
-
const parts =
|
|
1205
|
+
const wAttr = readSvgAttribute(this.svgSource, "width");
|
|
1206
|
+
const hAttr = readSvgAttribute(this.svgSource, "height");
|
|
1207
|
+
const vbAttr = readSvgAttribute(this.svgSource, "viewBox");
|
|
1208
|
+
if (wAttr && hAttr) {
|
|
1209
|
+
width = parseFloat(wAttr) || 100;
|
|
1210
|
+
height = parseFloat(hAttr) || 100;
|
|
1211
|
+
} else if (vbAttr) {
|
|
1212
|
+
const parts = vbAttr.split(/[\s,]+/).map(parseFloat);
|
|
1183
1213
|
if (parts.length === 4) {
|
|
1184
1214
|
width = parts[2];
|
|
1185
1215
|
height = parts[3];
|
|
@@ -230,6 +230,55 @@ function isSafeUrl(urlStr) {
|
|
|
230
230
|
}
|
|
231
231
|
|
|
232
232
|
// src/renderer/SVGRenderer.ts
|
|
233
|
+
function parseFontSizeToken(font) {
|
|
234
|
+
for (let i = 0; i < font.length; i++) {
|
|
235
|
+
const ch = font[i];
|
|
236
|
+
if (!(ch >= "0" && ch <= "9" || ch === ".")) continue;
|
|
237
|
+
let j = i + 1;
|
|
238
|
+
while (j < font.length) {
|
|
239
|
+
const next = font[j];
|
|
240
|
+
if (next >= "0" && next <= "9" || next === ".") {
|
|
241
|
+
j++;
|
|
242
|
+
} else {
|
|
243
|
+
break;
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
const unit = font.startsWith("rem", j) ? "rem" : font.startsWith("em", j) ? "em" : font.startsWith("px", j) ? "px" : null;
|
|
247
|
+
if (!unit) {
|
|
248
|
+
i = j;
|
|
249
|
+
continue;
|
|
250
|
+
}
|
|
251
|
+
let end = j + unit.length;
|
|
252
|
+
if (font[end] === "/") {
|
|
253
|
+
end++;
|
|
254
|
+
while (end < font.length && font[end] !== " " && font[end] !== " ") end++;
|
|
255
|
+
}
|
|
256
|
+
const value = Number.parseFloat(font.slice(i, j));
|
|
257
|
+
return Number.isFinite(value) ? { value, unit, start: i, end } : null;
|
|
258
|
+
}
|
|
259
|
+
return null;
|
|
260
|
+
}
|
|
261
|
+
function fontFamilyFromShorthand(font, sizeToken) {
|
|
262
|
+
const withoutSize = sizeToken ? `${font.slice(0, sizeToken.start)} ${font.slice(sizeToken.end)}`.trim() : font.trim();
|
|
263
|
+
const family = withoutSize.split(" ").map((part) => part.trim()).filter(
|
|
264
|
+
(part) => part && ![
|
|
265
|
+
"bold",
|
|
266
|
+
"italic",
|
|
267
|
+
"oblique",
|
|
268
|
+
"normal",
|
|
269
|
+
"900",
|
|
270
|
+
"800",
|
|
271
|
+
"700",
|
|
272
|
+
"600",
|
|
273
|
+
"500",
|
|
274
|
+
"400",
|
|
275
|
+
"300",
|
|
276
|
+
"200",
|
|
277
|
+
"100"
|
|
278
|
+
].includes(part.toLowerCase())
|
|
279
|
+
).join(" ");
|
|
280
|
+
return family || "sans-serif";
|
|
281
|
+
}
|
|
233
282
|
var SVGRenderer = (_class2 = class {
|
|
234
283
|
|
|
235
284
|
|
|
@@ -455,17 +504,17 @@ var SVGRenderer = (_class2 = class {
|
|
|
455
504
|
}
|
|
456
505
|
fillText(text, x, y, font, color) {
|
|
457
506
|
this.flush();
|
|
458
|
-
const
|
|
459
|
-
let fontSize =
|
|
460
|
-
if (
|
|
507
|
+
const sizeToken = parseFontSizeToken(font);
|
|
508
|
+
let fontSize = sizeToken ? sizeToken.value : 16;
|
|
509
|
+
if (sizeToken && sizeToken.unit !== "px") {
|
|
461
510
|
fontSize = fontSize * 16;
|
|
462
511
|
}
|
|
463
|
-
const
|
|
464
|
-
const
|
|
465
|
-
const
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
const fontFamily =
|
|
512
|
+
const lowerFont = font.toLowerCase();
|
|
513
|
+
const fontStyle = lowerFont.includes("italic") ? "italic" : lowerFont.includes("oblique") ? "oblique" : "normal";
|
|
514
|
+
const fontWeight = lowerFont.includes("bold") ? "bold" : _nullishCoalesce(["900", "800", "700", "600", "500", "400", "300", "200", "100"].find(
|
|
515
|
+
(weight) => lowerFont.includes(weight)
|
|
516
|
+
), () => ( "normal"));
|
|
517
|
+
const fontFamily = fontFamilyFromShorthand(font, sizeToken);
|
|
469
518
|
const fillVal = this.escapeXML(this.resolveGradient(color));
|
|
470
519
|
const transformStr = `matrix(${this.ma},${this.mb},${this.mc},${this.md},${this.me},${this.mf})`;
|
|
471
520
|
this.buffer.push(
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; } var _class; var _class2; var _class3; var _class4; var _class5; var _class6; var _class7;
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var _chunk76NMTLYLjs = require('./chunk-76NMTLYL.js');
|
|
4
4
|
|
|
5
5
|
// src/math/SpringPhysics.ts
|
|
6
6
|
var SpringPhysics = (_class = class {
|
|
@@ -1008,7 +1008,7 @@ var MSDFTextEntity = (_class6 = class extends Entity {
|
|
|
1008
1008
|
setText(text) {
|
|
1009
1009
|
if (this.text === text && this.layoutResult) return;
|
|
1010
1010
|
this.text = text;
|
|
1011
|
-
|
|
1011
|
+
_chunk76NMTLYLjs.LayoutWorkerManager.getInstance().queueLayout(this.id, this.text, {
|
|
1012
1012
|
fontId: this.font.id,
|
|
1013
1013
|
fontSize: this.fontSize,
|
|
1014
1014
|
maxWidth: 1e3,
|
|
@@ -1112,12 +1112,42 @@ var MSDFTextEntity = (_class6 = class extends Entity {
|
|
|
1112
1112
|
}
|
|
1113
1113
|
}
|
|
1114
1114
|
destroy() {
|
|
1115
|
-
|
|
1115
|
+
_chunk76NMTLYLjs.LayoutWorkerManager.getInstance().cancelLayout(this.id);
|
|
1116
1116
|
super.destroy();
|
|
1117
1117
|
}
|
|
1118
1118
|
}, _class6);
|
|
1119
1119
|
|
|
1120
1120
|
// src/text/SVGEntity.ts
|
|
1121
|
+
function isSvgWhitespace(ch) {
|
|
1122
|
+
return ch === " " || ch === " " || ch === "\n" || ch === "\r";
|
|
1123
|
+
}
|
|
1124
|
+
function readSvgAttribute(source, name) {
|
|
1125
|
+
const lowerSource = source.toLowerCase();
|
|
1126
|
+
const svgStart = lowerSource.indexOf("<svg");
|
|
1127
|
+
if (svgStart < 0) return null;
|
|
1128
|
+
const tagEnd = source.indexOf(">", svgStart + 4);
|
|
1129
|
+
if (tagEnd < 0) return null;
|
|
1130
|
+
const tag = source.slice(svgStart + 4, tagEnd);
|
|
1131
|
+
const lowerTag = tag.toLowerCase();
|
|
1132
|
+
const lowerName = name.toLowerCase();
|
|
1133
|
+
for (let i = 0; i < tag.length; i++) {
|
|
1134
|
+
const before = i === 0 ? " " : tag[i - 1];
|
|
1135
|
+
if (!isSvgWhitespace(before)) continue;
|
|
1136
|
+
if (!lowerTag.startsWith(lowerName, i)) continue;
|
|
1137
|
+
let cursor = i + lowerName.length;
|
|
1138
|
+
while (cursor < tag.length && isSvgWhitespace(tag[cursor])) cursor++;
|
|
1139
|
+
if (tag[cursor] !== "=") continue;
|
|
1140
|
+
cursor++;
|
|
1141
|
+
while (cursor < tag.length && isSvgWhitespace(tag[cursor])) cursor++;
|
|
1142
|
+
const quote = tag[cursor];
|
|
1143
|
+
if (quote !== '"' && quote !== "'") continue;
|
|
1144
|
+
const valueStart = cursor + 1;
|
|
1145
|
+
const valueEnd = tag.indexOf(quote, valueStart);
|
|
1146
|
+
if (valueEnd < 0) return null;
|
|
1147
|
+
return tag.slice(valueStart, valueEnd);
|
|
1148
|
+
}
|
|
1149
|
+
return null;
|
|
1150
|
+
}
|
|
1121
1151
|
var SVGEntity = (_class7 = class extends Entity {
|
|
1122
1152
|
__init40() {this.svgSource = ""}
|
|
1123
1153
|
__init41() {this.imageBitmap = null}
|
|
@@ -1169,17 +1199,17 @@ var SVGEntity = (_class7 = class extends Entity {
|
|
|
1169
1199
|
}
|
|
1170
1200
|
}
|
|
1171
1201
|
} catch (e) {
|
|
1172
|
-
console.error("Failed parsing SVG via DOMParser, falling back to
|
|
1202
|
+
console.error("Failed parsing SVG via DOMParser, falling back to attribute scan:", e);
|
|
1173
1203
|
}
|
|
1174
1204
|
} else {
|
|
1175
|
-
const
|
|
1176
|
-
const
|
|
1177
|
-
const
|
|
1178
|
-
if (
|
|
1179
|
-
width = parseFloat(
|
|
1180
|
-
height = parseFloat(
|
|
1181
|
-
} else if (
|
|
1182
|
-
const parts =
|
|
1205
|
+
const wAttr = readSvgAttribute(this.svgSource, "width");
|
|
1206
|
+
const hAttr = readSvgAttribute(this.svgSource, "height");
|
|
1207
|
+
const vbAttr = readSvgAttribute(this.svgSource, "viewBox");
|
|
1208
|
+
if (wAttr && hAttr) {
|
|
1209
|
+
width = parseFloat(wAttr) || 100;
|
|
1210
|
+
height = parseFloat(hAttr) || 100;
|
|
1211
|
+
} else if (vbAttr) {
|
|
1212
|
+
const parts = vbAttr.split(/[\s,]+/).map(parseFloat);
|
|
1183
1213
|
if (parts.length === 4) {
|
|
1184
1214
|
width = parts[2];
|
|
1185
1215
|
height = parts[3];
|
|
@@ -230,6 +230,55 @@ function isSafeUrl(urlStr) {
|
|
|
230
230
|
}
|
|
231
231
|
|
|
232
232
|
// src/renderer/SVGRenderer.ts
|
|
233
|
+
function parseFontSizeToken(font) {
|
|
234
|
+
for (let i = 0; i < font.length; i++) {
|
|
235
|
+
const ch = font[i];
|
|
236
|
+
if (!(ch >= "0" && ch <= "9" || ch === ".")) continue;
|
|
237
|
+
let j = i + 1;
|
|
238
|
+
while (j < font.length) {
|
|
239
|
+
const next = font[j];
|
|
240
|
+
if (next >= "0" && next <= "9" || next === ".") {
|
|
241
|
+
j++;
|
|
242
|
+
} else {
|
|
243
|
+
break;
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
const unit = font.startsWith("rem", j) ? "rem" : font.startsWith("em", j) ? "em" : font.startsWith("px", j) ? "px" : null;
|
|
247
|
+
if (!unit) {
|
|
248
|
+
i = j;
|
|
249
|
+
continue;
|
|
250
|
+
}
|
|
251
|
+
let end = j + unit.length;
|
|
252
|
+
if (font[end] === "/") {
|
|
253
|
+
end++;
|
|
254
|
+
while (end < font.length && font[end] !== " " && font[end] !== " ") end++;
|
|
255
|
+
}
|
|
256
|
+
const value = Number.parseFloat(font.slice(i, j));
|
|
257
|
+
return Number.isFinite(value) ? { value, unit, start: i, end } : null;
|
|
258
|
+
}
|
|
259
|
+
return null;
|
|
260
|
+
}
|
|
261
|
+
function fontFamilyFromShorthand(font, sizeToken) {
|
|
262
|
+
const withoutSize = sizeToken ? `${font.slice(0, sizeToken.start)} ${font.slice(sizeToken.end)}`.trim() : font.trim();
|
|
263
|
+
const family = withoutSize.split(" ").map((part) => part.trim()).filter(
|
|
264
|
+
(part) => part && ![
|
|
265
|
+
"bold",
|
|
266
|
+
"italic",
|
|
267
|
+
"oblique",
|
|
268
|
+
"normal",
|
|
269
|
+
"900",
|
|
270
|
+
"800",
|
|
271
|
+
"700",
|
|
272
|
+
"600",
|
|
273
|
+
"500",
|
|
274
|
+
"400",
|
|
275
|
+
"300",
|
|
276
|
+
"200",
|
|
277
|
+
"100"
|
|
278
|
+
].includes(part.toLowerCase())
|
|
279
|
+
).join(" ");
|
|
280
|
+
return family || "sans-serif";
|
|
281
|
+
}
|
|
233
282
|
var SVGRenderer = class {
|
|
234
283
|
width;
|
|
235
284
|
height;
|
|
@@ -455,17 +504,17 @@ var SVGRenderer = class {
|
|
|
455
504
|
}
|
|
456
505
|
fillText(text, x, y, font, color) {
|
|
457
506
|
this.flush();
|
|
458
|
-
const
|
|
459
|
-
let fontSize =
|
|
460
|
-
if (
|
|
507
|
+
const sizeToken = parseFontSizeToken(font);
|
|
508
|
+
let fontSize = sizeToken ? sizeToken.value : 16;
|
|
509
|
+
if (sizeToken && sizeToken.unit !== "px") {
|
|
461
510
|
fontSize = fontSize * 16;
|
|
462
511
|
}
|
|
463
|
-
const
|
|
464
|
-
const
|
|
465
|
-
const
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
const fontFamily =
|
|
512
|
+
const lowerFont = font.toLowerCase();
|
|
513
|
+
const fontStyle = lowerFont.includes("italic") ? "italic" : lowerFont.includes("oblique") ? "oblique" : "normal";
|
|
514
|
+
const fontWeight = lowerFont.includes("bold") ? "bold" : ["900", "800", "700", "600", "500", "400", "300", "200", "100"].find(
|
|
515
|
+
(weight) => lowerFont.includes(weight)
|
|
516
|
+
) ?? "normal";
|
|
517
|
+
const fontFamily = fontFamilyFromShorthand(font, sizeToken);
|
|
469
518
|
const fillVal = this.escapeXML(this.resolveGradient(color));
|
|
470
519
|
const transformStr = `matrix(${this.ma},${this.mb},${this.mc},${this.md},${this.me},${this.mf})`;
|
|
471
520
|
this.buffer.push(
|
package/dist/index.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
|
|
4
4
|
|
|
5
5
|
|
|
6
|
-
var
|
|
6
|
+
var _chunkIKLYTHALjs = require('./chunk-IKLYTHAL.js');
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
|
|
@@ -12,7 +12,7 @@ var _chunkVVOQNUBKjs = require('./chunk-VVOQNUBK.js');
|
|
|
12
12
|
|
|
13
13
|
|
|
14
14
|
|
|
15
|
-
var
|
|
15
|
+
var _chunkTPNADFNNjs = require('./chunk-TPNADFNN.js');
|
|
16
16
|
|
|
17
17
|
|
|
18
18
|
|
|
@@ -24,12 +24,12 @@ var _chunkTXA3LZDMjs = require('./chunk-TXA3LZDM.js');
|
|
|
24
24
|
|
|
25
25
|
|
|
26
26
|
|
|
27
|
-
var
|
|
27
|
+
var _chunkTQ4H357Qjs = require('./chunk-TQ4H357Q.js');
|
|
28
28
|
|
|
29
29
|
|
|
30
30
|
|
|
31
31
|
|
|
32
|
-
var
|
|
32
|
+
var _chunk76NMTLYLjs = require('./chunk-76NMTLYL.js');
|
|
33
33
|
|
|
34
34
|
// src/tree/ComputeParticleEntity.ts
|
|
35
35
|
var PARTICLE_STRIDE_FLOATS = 8;
|
|
@@ -41,7 +41,7 @@ var PARTICLE_OFFSET_ORIGIN_X = 4;
|
|
|
41
41
|
var PARTICLE_OFFSET_ORIGIN_Y = 5;
|
|
42
42
|
var PARTICLE_OFFSET_SIZE = 6;
|
|
43
43
|
var PARTICLE_OFFSET_LIFE = 7;
|
|
44
|
-
var ComputeParticleEntity = (_class = class extends
|
|
44
|
+
var ComputeParticleEntity = (_class = class extends _chunkTQ4H357Qjs.Entity {
|
|
45
45
|
|
|
46
46
|
|
|
47
47
|
|
|
@@ -410,7 +410,7 @@ var Scene = (_class2 = class _Scene {
|
|
|
410
410
|
this.particleBackend = _nullishCoalesce(options.particleBackend, () => ( "auto"));
|
|
411
411
|
this.a11ySyncInterval = _nullishCoalesce(options.a11ySyncInterval, () => ( 0));
|
|
412
412
|
this.reducedMotionQuery = typeof window !== "undefined" && typeof window.matchMedia === "function" ? window.matchMedia("(prefers-reduced-motion: reduce)") : null;
|
|
413
|
-
this.root = new class RootEntity extends
|
|
413
|
+
this.root = new class RootEntity extends _chunkTQ4H357Qjs.Entity {
|
|
414
414
|
isPointInside() {
|
|
415
415
|
return false;
|
|
416
416
|
}
|
|
@@ -419,7 +419,7 @@ var Scene = (_class2 = class _Scene {
|
|
|
419
419
|
}
|
|
420
420
|
}("root");
|
|
421
421
|
this.root._scene = this;
|
|
422
|
-
this.overlayRoot = new class OverlayRoot extends
|
|
422
|
+
this.overlayRoot = new class OverlayRoot extends _chunkTQ4H357Qjs.Entity {
|
|
423
423
|
isPointInside() {
|
|
424
424
|
return false;
|
|
425
425
|
}
|
|
@@ -430,7 +430,7 @@ var Scene = (_class2 = class _Scene {
|
|
|
430
430
|
if (options.renderer) {
|
|
431
431
|
this.renderer = options.renderer;
|
|
432
432
|
} else {
|
|
433
|
-
this.renderer = new (0,
|
|
433
|
+
this.renderer = new (0, _chunkTPNADFNNjs.CanvasRenderer)(canvas);
|
|
434
434
|
}
|
|
435
435
|
if (typeof document !== "undefined") {
|
|
436
436
|
this.a11yRoot = document.createElement("div");
|
|
@@ -760,42 +760,42 @@ var Scene = (_class2 = class _Scene {
|
|
|
760
760
|
el.style.background = "transparent";
|
|
761
761
|
}
|
|
762
762
|
el.addEventListener("click", (e) => {
|
|
763
|
-
node.dispatchEvent(new (0,
|
|
763
|
+
node.dispatchEvent(new (0, _chunkTQ4H357Qjs.VectoJSEvent)("click", node, e));
|
|
764
764
|
});
|
|
765
765
|
el.addEventListener("mouseenter", (e) => {
|
|
766
766
|
if (this.debugA11y) el.style.backgroundColor = "rgba(56, 189, 248, 0.2)";
|
|
767
|
-
node.dispatchEvent(new (0,
|
|
767
|
+
node.dispatchEvent(new (0, _chunkTQ4H357Qjs.VectoJSEvent)("hover", node, e, false));
|
|
768
768
|
});
|
|
769
769
|
el.addEventListener("mouseleave", (e) => {
|
|
770
770
|
if (this.debugA11y) el.style.backgroundColor = "rgba(56, 189, 248, 0.05)";
|
|
771
|
-
node.dispatchEvent(new (0,
|
|
771
|
+
node.dispatchEvent(new (0, _chunkTQ4H357Qjs.VectoJSEvent)("pointerleave", node, e, false));
|
|
772
772
|
});
|
|
773
773
|
const capEl = el;
|
|
774
774
|
el.addEventListener("pointerdown", (e) => {
|
|
775
775
|
if (typeof capEl.setPointerCapture === "function") capEl.setPointerCapture(e.pointerId);
|
|
776
|
-
node.dispatchEvent(new (0,
|
|
776
|
+
node.dispatchEvent(new (0, _chunkTQ4H357Qjs.VectoJSEvent)("pointerdown", node, e));
|
|
777
777
|
});
|
|
778
778
|
el.addEventListener("pointerup", (e) => {
|
|
779
779
|
if (typeof capEl.releasePointerCapture === "function")
|
|
780
780
|
capEl.releasePointerCapture(e.pointerId);
|
|
781
|
-
node.dispatchEvent(new (0,
|
|
781
|
+
node.dispatchEvent(new (0, _chunkTQ4H357Qjs.VectoJSEvent)("pointerup", node, e));
|
|
782
782
|
});
|
|
783
783
|
el.addEventListener(
|
|
784
784
|
"pointermove",
|
|
785
|
-
(e) => node.dispatchEvent(new (0,
|
|
785
|
+
(e) => node.dispatchEvent(new (0, _chunkTQ4H357Qjs.VectoJSEvent)("pointermove", node, e))
|
|
786
786
|
);
|
|
787
787
|
el.addEventListener(
|
|
788
788
|
"wheel",
|
|
789
789
|
(e) => {
|
|
790
|
-
node.dispatchEvent(new (0,
|
|
790
|
+
node.dispatchEvent(new (0, _chunkTQ4H357Qjs.VectoJSEvent)("wheel", node, e));
|
|
791
791
|
},
|
|
792
792
|
{ passive: false }
|
|
793
793
|
);
|
|
794
794
|
el.addEventListener("keydown", (e) => {
|
|
795
|
-
node.dispatchEvent(new (0,
|
|
795
|
+
node.dispatchEvent(new (0, _chunkTQ4H357Qjs.VectoJSEvent)("keydown", node, e));
|
|
796
796
|
});
|
|
797
797
|
el.addEventListener("keyup", (e) => {
|
|
798
|
-
node.dispatchEvent(new (0,
|
|
798
|
+
node.dispatchEvent(new (0, _chunkTQ4H357Qjs.VectoJSEvent)("keyup", node, e));
|
|
799
799
|
});
|
|
800
800
|
if (el instanceof HTMLInputElement || el instanceof HTMLTextAreaElement) {
|
|
801
801
|
const input = el;
|
|
@@ -809,6 +809,7 @@ var Scene = (_class2 = class _Scene {
|
|
|
809
809
|
selectionEnd: _nullishCoalesce(input.selectionEnd, () => ( input.value.length)),
|
|
810
810
|
composition
|
|
811
811
|
});
|
|
812
|
+
this.markDirty();
|
|
812
813
|
};
|
|
813
814
|
el.addEventListener("input", forward);
|
|
814
815
|
el.addEventListener("change", forward);
|
|
@@ -867,7 +868,7 @@ var Scene = (_class2 = class _Scene {
|
|
|
867
868
|
el.addEventListener("keydown", (e) => {
|
|
868
869
|
if (e.key === "Enter" || e.key === " ") {
|
|
869
870
|
e.preventDefault();
|
|
870
|
-
node.dispatchEvent(new (0,
|
|
871
|
+
node.dispatchEvent(new (0, _chunkTQ4H357Qjs.VectoJSEvent)("click", node, e));
|
|
871
872
|
}
|
|
872
873
|
});
|
|
873
874
|
}
|
|
@@ -892,7 +893,7 @@ var Scene = (_class2 = class _Scene {
|
|
|
892
893
|
if (el.placeholder !== attrs.placeholder) el.placeholder = attrs.placeholder;
|
|
893
894
|
}
|
|
894
895
|
if (attrs.href !== void 0 && el instanceof HTMLAnchorElement) {
|
|
895
|
-
const safeHref =
|
|
896
|
+
const safeHref = _chunkTPNADFNNjs.sanitizeUrl.call(void 0, attrs.href);
|
|
896
897
|
if (el.getAttribute("href") !== safeHref) el.setAttribute("href", safeHref);
|
|
897
898
|
}
|
|
898
899
|
if (el instanceof HTMLImageElement) {
|
|
@@ -1440,7 +1441,7 @@ var Scene = (_class2 = class _Scene {
|
|
|
1440
1441
|
* Export the current scene state to a lightweight, flat SVG XML string.
|
|
1441
1442
|
*/
|
|
1442
1443
|
toSVG() {
|
|
1443
|
-
const renderer = new (0,
|
|
1444
|
+
const renderer = new (0, _chunkTPNADFNNjs.SVGRenderer)(this.width, this.height);
|
|
1444
1445
|
this.render(renderer, 0, 0);
|
|
1445
1446
|
return renderer.toXMLString();
|
|
1446
1447
|
}
|
|
@@ -1603,10 +1604,10 @@ var Scene = (_class2 = class _Scene {
|
|
|
1603
1604
|
// src/components/TextEntity.ts
|
|
1604
1605
|
var sharedMeasurer;
|
|
1605
1606
|
function defaultMeasurer() {
|
|
1606
|
-
if (sharedMeasurer === void 0) sharedMeasurer =
|
|
1607
|
+
if (sharedMeasurer === void 0) sharedMeasurer = _chunkIKLYTHALjs.createCanvasMeasurer.call(void 0, "sans-serif");
|
|
1607
1608
|
return sharedMeasurer;
|
|
1608
1609
|
}
|
|
1609
|
-
var TextEntity = (_class3 = class extends
|
|
1610
|
+
var TextEntity = (_class3 = class extends _chunkTQ4H357Qjs.Entity {
|
|
1610
1611
|
|
|
1611
1612
|
|
|
1612
1613
|
|
|
@@ -1623,7 +1624,7 @@ var TextEntity = (_class3 = class extends _chunkKPWVPGHRjs.Entity {
|
|
|
1623
1624
|
this.text = text;
|
|
1624
1625
|
this.atlas = atlas;
|
|
1625
1626
|
this.fontSize = fontSize;
|
|
1626
|
-
this.layout = new (0,
|
|
1627
|
+
this.layout = new (0, _chunkIKLYTHALjs.LayoutEngine)(maxWidth, 1e4, defaultMeasurer());
|
|
1627
1628
|
this.prepared = this.layout.prepare(this.text, this.atlas, this.fontSize);
|
|
1628
1629
|
this.applyLayout();
|
|
1629
1630
|
this.interactive = true;
|
|
@@ -1704,7 +1705,7 @@ var TextEntity = (_class3 = class extends _chunkKPWVPGHRjs.Entity {
|
|
|
1704
1705
|
}, _class3);
|
|
1705
1706
|
|
|
1706
1707
|
// src/components/GridTextEntity.ts
|
|
1707
|
-
var GridTextEntity = (_class4 = class extends
|
|
1708
|
+
var GridTextEntity = (_class4 = class extends _chunkTQ4H357Qjs.Entity {
|
|
1708
1709
|
|
|
1709
1710
|
__init54() {this.fillStyle = "#ffffff"}
|
|
1710
1711
|
__init55() {this.grid = []}
|
|
@@ -1798,7 +1799,7 @@ function distSqToSegment(px, py, x1, y1, x2, y2) {
|
|
|
1798
1799
|
const ey = py - cy;
|
|
1799
1800
|
return ex * ex + ey * ey;
|
|
1800
1801
|
}
|
|
1801
|
-
var SplineEntity = (_class5 = class extends
|
|
1802
|
+
var SplineEntity = (_class5 = class extends _chunkTQ4H357Qjs.Entity {
|
|
1802
1803
|
|
|
1803
1804
|
|
|
1804
1805
|
|
|
@@ -2155,7 +2156,7 @@ var SpatialHashGrid = (_class6 = class {
|
|
|
2155
2156
|
}, _class6);
|
|
2156
2157
|
|
|
2157
2158
|
// src/tree/DOMPortalEntity.ts
|
|
2158
|
-
var DOMPortalEntity = (_class7 = class extends
|
|
2159
|
+
var DOMPortalEntity = (_class7 = class extends _chunkTQ4H357Qjs.Entity {
|
|
2159
2160
|
|
|
2160
2161
|
__init64() {this.isDOMPortal = true}
|
|
2161
2162
|
__init65() {this.domListeners = []}
|
|
@@ -2190,7 +2191,7 @@ var DOMPortalEntity = (_class7 = class extends _chunkKPWVPGHRjs.Entity {
|
|
|
2190
2191
|
const events = ["click", "pointerdown", "pointerup", "pointermove", "wheel"];
|
|
2191
2192
|
for (const type of events) {
|
|
2192
2193
|
const handler = (e) => {
|
|
2193
|
-
this.dispatchEvent(new (0,
|
|
2194
|
+
this.dispatchEvent(new (0, _chunkTQ4H357Qjs.VectoJSEvent)(type, this, e));
|
|
2194
2195
|
};
|
|
2195
2196
|
this.domElement.addEventListener(type, handler);
|
|
2196
2197
|
this.domListeners.push({ type, handler, capture: false });
|
|
@@ -2201,7 +2202,7 @@ var DOMPortalEntity = (_class7 = class extends _chunkKPWVPGHRjs.Entity {
|
|
|
2201
2202
|
];
|
|
2202
2203
|
for (const { native, vecto } of hoverEvents) {
|
|
2203
2204
|
const handler = (e) => {
|
|
2204
|
-
this.dispatchEvent(new (0,
|
|
2205
|
+
this.dispatchEvent(new (0, _chunkTQ4H357Qjs.VectoJSEvent)(vecto, this, e, false));
|
|
2205
2206
|
};
|
|
2206
2207
|
this.domElement.addEventListener(native, handler);
|
|
2207
2208
|
this.domListeners.push({ type: native, handler, capture: false });
|
|
@@ -2209,7 +2210,7 @@ var DOMPortalEntity = (_class7 = class extends _chunkKPWVPGHRjs.Entity {
|
|
|
2209
2210
|
const focusEvents = ["focus", "blur"];
|
|
2210
2211
|
for (const type of focusEvents) {
|
|
2211
2212
|
const handler = (e) => {
|
|
2212
|
-
this.dispatchEvent(new (0,
|
|
2213
|
+
this.dispatchEvent(new (0, _chunkTQ4H357Qjs.VectoJSEvent)(type, this, e, true));
|
|
2213
2214
|
};
|
|
2214
2215
|
this.domElement.addEventListener(type, handler, true);
|
|
2215
2216
|
this.domListeners.push({ type, handler, capture: true });
|
|
@@ -2248,8 +2249,8 @@ var DOMPortalEntity = (_class7 = class extends _chunkKPWVPGHRjs.Entity {
|
|
|
2248
2249
|
}, _class7);
|
|
2249
2250
|
|
|
2250
2251
|
// src/index.ts
|
|
2251
|
-
Scene.registerWebGLPointRendererCreator(
|
|
2252
|
-
Scene.registerWebGPUParticleSystemManager(
|
|
2252
|
+
Scene.registerWebGLPointRendererCreator(_chunkTPNADFNNjs.createWebGLPointRenderer);
|
|
2253
|
+
Scene.registerWebGPUParticleSystemManager(_chunkTPNADFNNjs.WebGPUParticleSystemManager);
|
|
2253
2254
|
|
|
2254
2255
|
|
|
2255
2256
|
|
|
@@ -2294,4 +2295,4 @@ Scene.registerWebGPUParticleSystemManager(_chunkTXA3LZDMjs.WebGPUParticleSystemM
|
|
|
2294
2295
|
|
|
2295
2296
|
|
|
2296
2297
|
|
|
2297
|
-
exports.ArabicShaper =
|
|
2298
|
+
exports.ArabicShaper = _chunk76NMTLYLjs.ArabicShaper; exports.BidiResolver = _chunk76NMTLYLjs.BidiResolver; exports.CanvasRenderer = _chunkTPNADFNNjs.CanvasRenderer; exports.ComputeParticleEntity = ComputeParticleEntity; exports.DOMPortalEntity = DOMPortalEntity; exports.Easing = _chunkTQ4H357Qjs.Easing; exports.Entity = _chunkTQ4H357Qjs.Entity; exports.GridTextEntity = GridTextEntity; exports.LayoutEngine = _chunkIKLYTHALjs.LayoutEngine; exports.LayoutResultBuffer = _chunkIKLYTHALjs.LayoutResultBuffer; exports.LayoutWorkerManager = _chunk76NMTLYLjs.LayoutWorkerManager; exports.MSDFFont = _chunkTQ4H357Qjs.MSDFFont; exports.MSDFTextEntity = _chunkTQ4H357Qjs.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 = _chunkTQ4H357Qjs.SVGEntity; exports.SVGRenderer = _chunkTPNADFNNjs.SVGRenderer; exports.Scene = Scene; exports.SpatialHashGrid = SpatialHashGrid; exports.SplineEntity = SplineEntity; exports.SpringDriver = _chunkTQ4H357Qjs.SpringDriver; exports.SpringPhysics = _chunkTQ4H357Qjs.SpringPhysics; exports.TextEntity = TextEntity; exports.TweenDriver = _chunkTQ4H357Qjs.TweenDriver; exports.VectoJSEvent = _chunkTQ4H357Qjs.VectoJSEvent; exports.WebGPUParticleSystemManager = _chunkTPNADFNNjs.WebGPUParticleSystemManager; exports.computeLineSegments = _chunkIKLYTHALjs.computeLineSegments; exports.createCanvasMeasurer = _chunkIKLYTHALjs.createCanvasMeasurer; exports.createWebGLPointRenderer = _chunkTPNADFNNjs.createWebGLPointRenderer; exports.isSafeUrl = _chunkTPNADFNNjs.isSafeUrl; exports.isTweenConfig = _chunkTQ4H357Qjs.isTweenConfig; exports.loadSpline = loadSpline; exports.parseColorToRGBA = _chunkTPNADFNNjs.parseColorToRGBA; exports.polySegmentToBezier = polySegmentToBezier; exports.sanitizeUrl = _chunkTPNADFNNjs.sanitizeUrl;
|
package/dist/index.mjs
CHANGED
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
LayoutResultBuffer,
|
|
4
4
|
computeLineSegments,
|
|
5
5
|
createCanvasMeasurer
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-MCULB5VC.mjs";
|
|
7
7
|
import {
|
|
8
8
|
CanvasRenderer,
|
|
9
9
|
SVGRenderer,
|
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
isSafeUrl,
|
|
13
13
|
parseColorToRGBA,
|
|
14
14
|
sanitizeUrl
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-WEQRBXT2.mjs";
|
|
16
16
|
import {
|
|
17
17
|
Easing,
|
|
18
18
|
Entity,
|
|
@@ -24,12 +24,12 @@ import {
|
|
|
24
24
|
TweenDriver,
|
|
25
25
|
VectoJSEvent,
|
|
26
26
|
isTweenConfig
|
|
27
|
-
} from "./chunk-
|
|
27
|
+
} from "./chunk-P6MDWIEX.mjs";
|
|
28
28
|
import {
|
|
29
29
|
ArabicShaper,
|
|
30
30
|
BidiResolver,
|
|
31
31
|
LayoutWorkerManager
|
|
32
|
-
} from "./chunk-
|
|
32
|
+
} from "./chunk-B3Z3JEJH.mjs";
|
|
33
33
|
|
|
34
34
|
// src/tree/ComputeParticleEntity.ts
|
|
35
35
|
var PARTICLE_STRIDE_FLOATS = 8;
|
|
@@ -809,6 +809,7 @@ var Scene = class _Scene {
|
|
|
809
809
|
selectionEnd: input.selectionEnd ?? input.value.length,
|
|
810
810
|
composition
|
|
811
811
|
});
|
|
812
|
+
this.markDirty();
|
|
812
813
|
};
|
|
813
814
|
el.addEventListener("input", forward);
|
|
814
815
|
el.addEventListener("change", forward);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const WORKER_SOURCE_STRING = "\"use strict\";(()=>{var
|
|
1
|
+
export declare const WORKER_SOURCE_STRING = "\"use strict\";(()=>{var k=new Map;function n(t){return typeof t==\"number\"&&Number.isFinite(t)}function H(t){return t.origin?t.origin===self.location.origin:!0}function M(t){if(!t||typeof t!=\"object\")return!1;let e=t;return typeof e.id==\"string\"&&n(e.seqId)&&typeof e.text==\"string\"&&typeof e.fontId==\"string\"&&(e.fontData===void 0||typeof e.fontData==\"object\")&&n(e.maxWidth)&&n(e.maxHeight)&&n(e.fontSize)&&(e.lineHeight===void 0||n(e.lineHeight))&&(e.letterSpacing===void 0||n(e.letterSpacing))}self.onmessage=t=>{if(!H(t)||!M(t.data))return;let{id:e,seqId:F,text:q,fontId:d,fontData:f,maxWidth:y,maxHeight:I,fontSize:i,lineHeight:A,letterSpacing:D}=t.data;f&&k.set(d,f);let s=k.get(d);if(!s)return;let g=[],l=[],p=[],m=[],o=0,a=0,h=s.metrics?.ascender??.8,W=s.metrics?.descender??-.2,b=A??i*(h-W),x=Array.from(q);for(let c=0;c<x.length;c++){let u=x[c].codePointAt(0),S=(s.glyphs?.find(C=>C.unicode===u)?.advance??1)*i;o+S>y&&u===32&&(o=0,a++),g.push(u),l.push(o);let w=a*b+h*i;p.push(w),m.push(-256),o+=S+(D??0)}let r={id:e,seqId:F,width:Math.min(o,y),height:(a+1)*b,codePoints:new Uint32Array(g),xCoords:new Float32Array(l),yCoords:new Float32Array(p),packedStyles:new Uint32Array(m)};self.postMessage(r,[r.codePoints.buffer,r.xCoords.buffer,r.yCoords.buffer,r.packedStyles.buffer])};})();\n";
|
package/dist/layout.js
CHANGED
|
@@ -3,14 +3,14 @@
|
|
|
3
3
|
|
|
4
4
|
|
|
5
5
|
|
|
6
|
-
var
|
|
6
|
+
var _chunkIKLYTHALjs = require('./chunk-IKLYTHAL.js');
|
|
7
7
|
|
|
8
8
|
|
|
9
|
-
var
|
|
9
|
+
var _chunk76NMTLYLjs = require('./chunk-76NMTLYL.js');
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
|
|
13
13
|
|
|
14
14
|
|
|
15
15
|
|
|
16
|
-
exports.LayoutEngine =
|
|
16
|
+
exports.LayoutEngine = _chunkIKLYTHALjs.LayoutEngine; exports.LayoutResultBuffer = _chunkIKLYTHALjs.LayoutResultBuffer; exports.LayoutWorkerManager = _chunk76NMTLYLjs.LayoutWorkerManager; exports.computeLineSegments = _chunkIKLYTHALjs.computeLineSegments; exports.createCanvasMeasurer = _chunkIKLYTHALjs.createCanvasMeasurer;
|
package/dist/layout.mjs
CHANGED
|
@@ -3,10 +3,10 @@ import {
|
|
|
3
3
|
LayoutResultBuffer,
|
|
4
4
|
computeLineSegments,
|
|
5
5
|
createCanvasMeasurer
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-MCULB5VC.mjs";
|
|
7
7
|
import {
|
|
8
8
|
LayoutWorkerManager
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-B3Z3JEJH.mjs";
|
|
10
10
|
export {
|
|
11
11
|
LayoutEngine,
|
|
12
12
|
LayoutResultBuffer,
|
package/dist/renderer.js
CHANGED
|
@@ -4,11 +4,11 @@
|
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
|
|
7
|
-
var
|
|
7
|
+
var _chunkTPNADFNNjs = require('./chunk-TPNADFNN.js');
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
|
|
13
13
|
|
|
14
|
-
exports.CanvasRenderer =
|
|
14
|
+
exports.CanvasRenderer = _chunkTPNADFNNjs.CanvasRenderer; exports.SVGRenderer = _chunkTPNADFNNjs.SVGRenderer; exports.WebGPUParticleSystemManager = _chunkTPNADFNNjs.WebGPUParticleSystemManager; exports.createWebGLPointRenderer = _chunkTPNADFNNjs.createWebGLPointRenderer; exports.parseColorToRGBA = _chunkTPNADFNNjs.parseColorToRGBA;
|
package/dist/renderer.mjs
CHANGED
package/dist/text.js
CHANGED
|
@@ -2,15 +2,15 @@
|
|
|
2
2
|
|
|
3
3
|
|
|
4
4
|
|
|
5
|
-
var
|
|
5
|
+
var _chunkTQ4H357Qjs = require('./chunk-TQ4H357Q.js');
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
|
|
9
|
-
var
|
|
9
|
+
var _chunk76NMTLYLjs = require('./chunk-76NMTLYL.js');
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
|
|
13
13
|
|
|
14
14
|
|
|
15
15
|
|
|
16
|
-
exports.ArabicShaper =
|
|
16
|
+
exports.ArabicShaper = _chunk76NMTLYLjs.ArabicShaper; exports.BidiResolver = _chunk76NMTLYLjs.BidiResolver; exports.MSDFFont = _chunkTQ4H357Qjs.MSDFFont; exports.MSDFTextEntity = _chunkTQ4H357Qjs.MSDFTextEntity; exports.SVGEntity = _chunkTQ4H357Qjs.SVGEntity;
|
package/dist/text.mjs
CHANGED
|
@@ -2,11 +2,11 @@ import {
|
|
|
2
2
|
MSDFFont,
|
|
3
3
|
MSDFTextEntity,
|
|
4
4
|
SVGEntity
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-P6MDWIEX.mjs";
|
|
6
6
|
import {
|
|
7
7
|
ArabicShaper,
|
|
8
8
|
BidiResolver
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-B3Z3JEJH.mjs";
|
|
10
10
|
export {
|
|
11
11
|
ArabicShaper,
|
|
12
12
|
BidiResolver,
|