@vectojs/core 1.4.1 → 1.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +25 -0
- package/dist/{chunk-N7DNUDVY.mjs → chunk-3CODWSF3.mjs} +27 -0
- package/dist/{chunk-NHNOKBD4.js → chunk-DFNK6OV6.js} +28 -1
- package/dist/{chunk-FNXOS7IA.mjs → chunk-V7GUWG5C.mjs} +5 -2
- package/dist/{chunk-XLZDOFSB.js → chunk-ZBKKRYDH.js} +5 -2
- package/dist/index.d.ts +1 -0
- package/dist/index.js +112 -29
- package/dist/index.mjs +88 -5
- package/dist/layout.js +2 -2
- package/dist/layout.mjs +1 -1
- package/dist/text/Typography.d.ts +11 -0
- package/dist/text/index.d.ts +1 -0
- package/dist/text.js +6 -2
- package/dist/text.mjs +7 -3
- package/dist/tree/Entity.d.ts +44 -0
- package/dist/tree/Scene.d.ts +2 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -112,6 +112,31 @@ This projection is intentionally thin. Applications still own accessible names,
|
|
|
112
112
|
focus order, contrast, and correct control semantics. See the
|
|
113
113
|
[accessibility guide](https://vectojs.org/learn/accessibility/).
|
|
114
114
|
|
|
115
|
+
## Static content projection
|
|
116
|
+
|
|
117
|
+
Canvas-rendered text can opt into browser-native find, translation, selection, and copy without
|
|
118
|
+
turning the application into a DOM layout. Override `getContentProjection()` on the owning Entity;
|
|
119
|
+
the Scene creates a transparent, position-synchronized mirror while the VMT remains authoritative:
|
|
120
|
+
|
|
121
|
+
```ts
|
|
122
|
+
class SelectableLabel extends Entity {
|
|
123
|
+
getContentProjection() {
|
|
124
|
+
return {
|
|
125
|
+
text: 'Selectable canvas text',
|
|
126
|
+
font: '18px Inter',
|
|
127
|
+
lineHeight: 24,
|
|
128
|
+
selectable: true,
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
`selectable` controls whether the mirror receives pointer input. The Scene keeps projection order
|
|
135
|
+
aligned with VMT order, removes descendant mirrors with their subtree, and hides mirrors fully
|
|
136
|
+
outside the viewport or a `clipChildren` ancestor. Tooling can inspect the currently materialized
|
|
137
|
+
node with `scene.getContentElement(entityId)`. Virtualized or non-materialized off-viewport text is
|
|
138
|
+
not searchable until the application brings it into the active scene.
|
|
139
|
+
|
|
115
140
|
## Performance model
|
|
116
141
|
|
|
117
142
|
Useful levers include on-demand rendering, viewport culling, spatial hashing, prepared text layout,
|
|
@@ -939,6 +939,31 @@ var Entity = class {
|
|
|
939
939
|
}
|
|
940
940
|
};
|
|
941
941
|
|
|
942
|
+
// src/text/Typography.ts
|
|
943
|
+
var typographyContext;
|
|
944
|
+
var baselineCache = /* @__PURE__ */ new Map();
|
|
945
|
+
function cssLineBoxBaseline(font, lineHeight) {
|
|
946
|
+
if (typeof document === "undefined") return lineHeight * 0.8;
|
|
947
|
+
const key = `${font}\0${lineHeight}`;
|
|
948
|
+
const cached = baselineCache.get(key);
|
|
949
|
+
if (cached !== void 0) return cached;
|
|
950
|
+
if (typographyContext === void 0) {
|
|
951
|
+
typographyContext = document.createElement("canvas").getContext("2d");
|
|
952
|
+
}
|
|
953
|
+
if (!typographyContext) return lineHeight * 0.8;
|
|
954
|
+
typographyContext.font = font;
|
|
955
|
+
const metrics = typographyContext.measureText("Mg");
|
|
956
|
+
const ascent = metrics.fontBoundingBoxAscent || metrics.actualBoundingBoxAscent;
|
|
957
|
+
const descent = metrics.fontBoundingBoxDescent || metrics.actualBoundingBoxDescent;
|
|
958
|
+
if (!(ascent > 0) || !(descent >= 0)) return lineHeight * 0.8;
|
|
959
|
+
const baseline = (lineHeight - ascent - descent) / 2 + ascent;
|
|
960
|
+
baselineCache.set(key, baseline);
|
|
961
|
+
return baseline;
|
|
962
|
+
}
|
|
963
|
+
function clearCssLineBoxMetrics() {
|
|
964
|
+
baselineCache.clear();
|
|
965
|
+
}
|
|
966
|
+
|
|
942
967
|
// src/text/MSDFFont.ts
|
|
943
968
|
function kernKey(a, b) {
|
|
944
969
|
return a * 1114112 + b;
|
|
@@ -1442,6 +1467,8 @@ export {
|
|
|
1442
1467
|
SpringDriver,
|
|
1443
1468
|
VectoJSEvent,
|
|
1444
1469
|
Entity,
|
|
1470
|
+
cssLineBoxBaseline,
|
|
1471
|
+
clearCssLineBoxMetrics,
|
|
1445
1472
|
MSDFFont,
|
|
1446
1473
|
MSDFTextEntity,
|
|
1447
1474
|
SVGEntity
|
|
@@ -939,6 +939,31 @@ var Entity = (_class4 = class {
|
|
|
939
939
|
}
|
|
940
940
|
}, _class4);
|
|
941
941
|
|
|
942
|
+
// src/text/Typography.ts
|
|
943
|
+
var typographyContext;
|
|
944
|
+
var baselineCache = /* @__PURE__ */ new Map();
|
|
945
|
+
function cssLineBoxBaseline(font, lineHeight) {
|
|
946
|
+
if (typeof document === "undefined") return lineHeight * 0.8;
|
|
947
|
+
const key = `${font}\0${lineHeight}`;
|
|
948
|
+
const cached = baselineCache.get(key);
|
|
949
|
+
if (cached !== void 0) return cached;
|
|
950
|
+
if (typographyContext === void 0) {
|
|
951
|
+
typographyContext = document.createElement("canvas").getContext("2d");
|
|
952
|
+
}
|
|
953
|
+
if (!typographyContext) return lineHeight * 0.8;
|
|
954
|
+
typographyContext.font = font;
|
|
955
|
+
const metrics = typographyContext.measureText("Mg");
|
|
956
|
+
const ascent = metrics.fontBoundingBoxAscent || metrics.actualBoundingBoxAscent;
|
|
957
|
+
const descent = metrics.fontBoundingBoxDescent || metrics.actualBoundingBoxDescent;
|
|
958
|
+
if (!(ascent > 0) || !(descent >= 0)) return lineHeight * 0.8;
|
|
959
|
+
const baseline = (lineHeight - ascent - descent) / 2 + ascent;
|
|
960
|
+
baselineCache.set(key, baseline);
|
|
961
|
+
return baseline;
|
|
962
|
+
}
|
|
963
|
+
function clearCssLineBoxMetrics() {
|
|
964
|
+
baselineCache.clear();
|
|
965
|
+
}
|
|
966
|
+
|
|
942
967
|
// src/text/MSDFFont.ts
|
|
943
968
|
function kernKey(a, b) {
|
|
944
969
|
return a * 1114112 + b;
|
|
@@ -1445,4 +1470,6 @@ var SVGEntity = (_class7 = class extends Entity {
|
|
|
1445
1470
|
|
|
1446
1471
|
|
|
1447
1472
|
|
|
1448
|
-
|
|
1473
|
+
|
|
1474
|
+
|
|
1475
|
+
exports.SpringPhysics = SpringPhysics; exports.Easing = Easing; exports.isTweenConfig = isTweenConfig; exports.TweenDriver = TweenDriver; exports.SpringDriver = SpringDriver; exports.VectoJSEvent = VectoJSEvent; exports.Entity = Entity; exports.cssLineBoxBaseline = cssLineBoxBaseline; exports.clearCssLineBoxMetrics = clearCssLineBoxMetrics; exports.MSDFFont = MSDFFont; exports.MSDFTextEntity = MSDFTextEntity; exports.SVGEntity = SVGEntity;
|
|
@@ -598,8 +598,11 @@ var LayoutEngine = class {
|
|
|
598
598
|
currentLineNodes.push({
|
|
599
599
|
char: glyph.char,
|
|
600
600
|
x: currentX,
|
|
601
|
-
//
|
|
602
|
-
|
|
601
|
+
// Canvas text is positioned by baseline, while `y` is the local
|
|
602
|
+
// top used by the renderer. Offset smaller runs by their baseline
|
|
603
|
+
// delta, not by their full em-box delta, so mixed-size glyphs share
|
|
604
|
+
// one real baseline in every Canvas 2D implementation.
|
|
605
|
+
y: currentY + (pMax - gfs) * 0.8,
|
|
603
606
|
width: charWidth,
|
|
604
607
|
height: gfs,
|
|
605
608
|
style: glyph.style,
|
|
@@ -598,8 +598,11 @@ var LayoutEngine = (_class = class {
|
|
|
598
598
|
currentLineNodes.push({
|
|
599
599
|
char: glyph.char,
|
|
600
600
|
x: currentX,
|
|
601
|
-
//
|
|
602
|
-
|
|
601
|
+
// Canvas text is positioned by baseline, while `y` is the local
|
|
602
|
+
// top used by the renderer. Offset smaller runs by their baseline
|
|
603
|
+
// delta, not by their full em-box delta, so mixed-size glyphs share
|
|
604
|
+
// one real baseline in every Canvas 2D implementation.
|
|
605
|
+
y: currentY + (pMax - gfs) * 0.8,
|
|
603
606
|
width: charWidth,
|
|
604
607
|
height: gfs,
|
|
605
608
|
style: glyph.style,
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
|
|
4
4
|
|
|
5
5
|
|
|
6
|
-
var
|
|
6
|
+
var _chunkZBKKRYDHjs = require('./chunk-ZBKKRYDH.js');
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
|
|
@@ -24,7 +24,9 @@ var _chunkBPMNCGU7js = require('./chunk-BPMNCGU7.js');
|
|
|
24
24
|
|
|
25
25
|
|
|
26
26
|
|
|
27
|
-
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
var _chunkDFNK6OV6js = require('./chunk-DFNK6OV6.js');
|
|
28
30
|
|
|
29
31
|
|
|
30
32
|
|
|
@@ -41,7 +43,7 @@ var PARTICLE_OFFSET_ORIGIN_X = 4;
|
|
|
41
43
|
var PARTICLE_OFFSET_ORIGIN_Y = 5;
|
|
42
44
|
var PARTICLE_OFFSET_SIZE = 6;
|
|
43
45
|
var PARTICLE_OFFSET_LIFE = 7;
|
|
44
|
-
var ComputeParticleEntity = (_class = class extends
|
|
46
|
+
var ComputeParticleEntity = (_class = class extends _chunkDFNK6OV6js.Entity {
|
|
45
47
|
|
|
46
48
|
|
|
47
49
|
|
|
@@ -429,7 +431,7 @@ var Scene = (_class2 = class _Scene {
|
|
|
429
431
|
this.a11ySyncInterval = _nullishCoalesce(options.a11ySyncInterval, () => ( 0));
|
|
430
432
|
this.contentProjectionEnabled = _nullishCoalesce(options.contentProjection, () => ( true));
|
|
431
433
|
this.reducedMotionQuery = typeof window !== "undefined" && typeof window.matchMedia === "function" ? window.matchMedia("(prefers-reduced-motion: reduce)") : null;
|
|
432
|
-
this.root = new class RootEntity extends
|
|
434
|
+
this.root = new class RootEntity extends _chunkDFNK6OV6js.Entity {
|
|
433
435
|
isPointInside() {
|
|
434
436
|
return false;
|
|
435
437
|
}
|
|
@@ -438,7 +440,7 @@ var Scene = (_class2 = class _Scene {
|
|
|
438
440
|
}
|
|
439
441
|
}("root");
|
|
440
442
|
this.root._scene = this;
|
|
441
|
-
this.overlayRoot = new class OverlayRoot extends
|
|
443
|
+
this.overlayRoot = new class OverlayRoot extends _chunkDFNK6OV6js.Entity {
|
|
442
444
|
isPointInside() {
|
|
443
445
|
return false;
|
|
444
446
|
}
|
|
@@ -505,6 +507,7 @@ var Scene = (_class2 = class _Scene {
|
|
|
505
507
|
};
|
|
506
508
|
if (typeof document !== "undefined" && document.fonts) {
|
|
507
509
|
this.fontLoadHandler = () => {
|
|
510
|
+
_chunkDFNK6OV6js.clearCssLineBoxMetrics.call(void 0, );
|
|
508
511
|
this.markDirty();
|
|
509
512
|
};
|
|
510
513
|
document.fonts.ready.then(this.fontLoadHandler);
|
|
@@ -553,6 +556,7 @@ var Scene = (_class2 = class _Scene {
|
|
|
553
556
|
if (contentEl) {
|
|
554
557
|
contentEl.remove();
|
|
555
558
|
this.contentElements.delete(node.id);
|
|
559
|
+
this.a11yNeedsReorder = true;
|
|
556
560
|
}
|
|
557
561
|
const el = this.a11yElements.get(node.id);
|
|
558
562
|
if (el) {
|
|
@@ -801,42 +805,42 @@ var Scene = (_class2 = class _Scene {
|
|
|
801
805
|
el.style.background = "transparent";
|
|
802
806
|
}
|
|
803
807
|
el.addEventListener("click", (e) => {
|
|
804
|
-
node.dispatchEvent(new (0,
|
|
808
|
+
node.dispatchEvent(new (0, _chunkDFNK6OV6js.VectoJSEvent)("click", node, e));
|
|
805
809
|
});
|
|
806
810
|
el.addEventListener("mouseenter", (e) => {
|
|
807
811
|
if (this.debugA11y) el.style.backgroundColor = "rgba(56, 189, 248, 0.2)";
|
|
808
|
-
node.dispatchEvent(new (0,
|
|
812
|
+
node.dispatchEvent(new (0, _chunkDFNK6OV6js.VectoJSEvent)("hover", node, e, false));
|
|
809
813
|
});
|
|
810
814
|
el.addEventListener("mouseleave", (e) => {
|
|
811
815
|
if (this.debugA11y) el.style.backgroundColor = "rgba(56, 189, 248, 0.05)";
|
|
812
|
-
node.dispatchEvent(new (0,
|
|
816
|
+
node.dispatchEvent(new (0, _chunkDFNK6OV6js.VectoJSEvent)("pointerleave", node, e, false));
|
|
813
817
|
});
|
|
814
818
|
const capEl = el;
|
|
815
819
|
el.addEventListener("pointerdown", (e) => {
|
|
816
820
|
if (typeof capEl.setPointerCapture === "function") capEl.setPointerCapture(e.pointerId);
|
|
817
|
-
node.dispatchEvent(new (0,
|
|
821
|
+
node.dispatchEvent(new (0, _chunkDFNK6OV6js.VectoJSEvent)("pointerdown", node, e));
|
|
818
822
|
});
|
|
819
823
|
el.addEventListener("pointerup", (e) => {
|
|
820
824
|
if (typeof capEl.releasePointerCapture === "function")
|
|
821
825
|
capEl.releasePointerCapture(e.pointerId);
|
|
822
|
-
node.dispatchEvent(new (0,
|
|
826
|
+
node.dispatchEvent(new (0, _chunkDFNK6OV6js.VectoJSEvent)("pointerup", node, e));
|
|
823
827
|
});
|
|
824
828
|
el.addEventListener(
|
|
825
829
|
"pointermove",
|
|
826
|
-
(e) => node.dispatchEvent(new (0,
|
|
830
|
+
(e) => node.dispatchEvent(new (0, _chunkDFNK6OV6js.VectoJSEvent)("pointermove", node, e))
|
|
827
831
|
);
|
|
828
832
|
el.addEventListener(
|
|
829
833
|
"wheel",
|
|
830
834
|
(e) => {
|
|
831
|
-
node.dispatchEvent(new (0,
|
|
835
|
+
node.dispatchEvent(new (0, _chunkDFNK6OV6js.VectoJSEvent)("wheel", node, e));
|
|
832
836
|
},
|
|
833
837
|
{ passive: false }
|
|
834
838
|
);
|
|
835
839
|
el.addEventListener("keydown", (e) => {
|
|
836
|
-
node.dispatchEvent(new (0,
|
|
840
|
+
node.dispatchEvent(new (0, _chunkDFNK6OV6js.VectoJSEvent)("keydown", node, e));
|
|
837
841
|
});
|
|
838
842
|
el.addEventListener("keyup", (e) => {
|
|
839
|
-
node.dispatchEvent(new (0,
|
|
843
|
+
node.dispatchEvent(new (0, _chunkDFNK6OV6js.VectoJSEvent)("keyup", node, e));
|
|
840
844
|
});
|
|
841
845
|
if (el instanceof HTMLInputElement || el instanceof HTMLTextAreaElement) {
|
|
842
846
|
const input = el;
|
|
@@ -909,7 +913,7 @@ var Scene = (_class2 = class _Scene {
|
|
|
909
913
|
el.addEventListener("keydown", (e) => {
|
|
910
914
|
if (e.key === "Enter" || e.key === " ") {
|
|
911
915
|
e.preventDefault();
|
|
912
|
-
node.dispatchEvent(new (0,
|
|
916
|
+
node.dispatchEvent(new (0, _chunkDFNK6OV6js.VectoJSEvent)("click", node, e));
|
|
913
917
|
}
|
|
914
918
|
});
|
|
915
919
|
}
|
|
@@ -992,6 +996,16 @@ var Scene = (_class2 = class _Scene {
|
|
|
992
996
|
el.setAttribute("aria-valuenow", attrs.value);
|
|
993
997
|
}
|
|
994
998
|
}
|
|
999
|
+
if (attrs.textInputStyle !== void 0 && (el instanceof HTMLInputElement || el instanceof HTMLTextAreaElement)) {
|
|
1000
|
+
const textStyle = attrs.textInputStyle;
|
|
1001
|
+
if (el.style.font !== textStyle.font) el.style.font = textStyle.font;
|
|
1002
|
+
const lineHeight = `${textStyle.lineHeight}px`;
|
|
1003
|
+
if (el.style.lineHeight !== lineHeight) el.style.lineHeight = lineHeight;
|
|
1004
|
+
const padding = `${textStyle.padding}px`;
|
|
1005
|
+
if (el.style.padding !== padding) el.style.padding = padding;
|
|
1006
|
+
if (el.style.boxSizing !== "border-box") el.style.boxSizing = "border-box";
|
|
1007
|
+
if (el instanceof HTMLTextAreaElement) el.style.resize = "none";
|
|
1008
|
+
}
|
|
995
1009
|
if (node.a11yFullViewport) {
|
|
996
1010
|
el.style.left = "0px";
|
|
997
1011
|
el.style.top = "0px";
|
|
@@ -1028,6 +1042,7 @@ var Scene = (_class2 = class _Scene {
|
|
|
1028
1042
|
if (el) {
|
|
1029
1043
|
el.remove();
|
|
1030
1044
|
this.contentElements.delete(node.id);
|
|
1045
|
+
this.a11yNeedsReorder = true;
|
|
1031
1046
|
}
|
|
1032
1047
|
return;
|
|
1033
1048
|
}
|
|
@@ -1046,14 +1061,54 @@ var Scene = (_class2 = class _Scene {
|
|
|
1046
1061
|
el.addEventListener(
|
|
1047
1062
|
"wheel",
|
|
1048
1063
|
(e2) => {
|
|
1049
|
-
node.dispatchEvent(new (0,
|
|
1064
|
+
node.dispatchEvent(new (0, _chunkDFNK6OV6js.VectoJSEvent)("wheel", node, e2));
|
|
1050
1065
|
},
|
|
1051
1066
|
{ passive: false }
|
|
1052
1067
|
);
|
|
1053
1068
|
this.a11yRoot.appendChild(el);
|
|
1054
1069
|
this.contentElements.set(node.id, el);
|
|
1070
|
+
this.a11yNeedsReorder = true;
|
|
1071
|
+
}
|
|
1072
|
+
const lines = projection.lines;
|
|
1073
|
+
if (lines && lines.length > 0) {
|
|
1074
|
+
const signature = JSON.stringify({
|
|
1075
|
+
lines,
|
|
1076
|
+
fallbackFont: _nullishCoalesce(projection.font, () => ( "")),
|
|
1077
|
+
fallbackLineHeight: _nullishCoalesce(projection.lineHeight, () => ( 16))
|
|
1078
|
+
});
|
|
1079
|
+
if (el.dataset.vectoProjectionLines !== signature) {
|
|
1080
|
+
el.replaceChildren();
|
|
1081
|
+
for (let index = 0; index < lines.length; index++) {
|
|
1082
|
+
const line = lines[index];
|
|
1083
|
+
const lineElement = document.createElement("span");
|
|
1084
|
+
const lineFont = _nullishCoalesce(_nullishCoalesce(line.font, () => ( projection.font)), () => ( ""));
|
|
1085
|
+
const lineHeight2 = _nullishCoalesce(_nullishCoalesce(line.lineHeight, () => ( projection.lineHeight)), () => ( 16));
|
|
1086
|
+
lineElement.style.position = "absolute";
|
|
1087
|
+
lineElement.style.left = `${line.x}px`;
|
|
1088
|
+
lineElement.style.top = `${line.y + line.baseline - _chunkDFNK6OV6js.cssLineBoxBaseline.call(void 0, lineFont, lineHeight2)}px`;
|
|
1089
|
+
lineElement.style.whiteSpace = "pre";
|
|
1090
|
+
if (lineFont) lineElement.style.font = lineFont;
|
|
1091
|
+
lineElement.style.lineHeight = `${lineHeight2}px`;
|
|
1092
|
+
if (line.runs && line.runs.length > 0) {
|
|
1093
|
+
for (const run of line.runs) {
|
|
1094
|
+
const runElement = document.createElement("span");
|
|
1095
|
+
runElement.textContent = run.text;
|
|
1096
|
+
if (run.font) runElement.style.font = run.font;
|
|
1097
|
+
runElement.style.lineHeight = `${lineHeight2}px`;
|
|
1098
|
+
lineElement.appendChild(runElement);
|
|
1099
|
+
}
|
|
1100
|
+
} else {
|
|
1101
|
+
lineElement.textContent = line.text;
|
|
1102
|
+
}
|
|
1103
|
+
el.appendChild(lineElement);
|
|
1104
|
+
if (index < lines.length - 1) el.appendChild(document.createTextNode("\n"));
|
|
1105
|
+
}
|
|
1106
|
+
el.dataset.vectoProjectionLines = signature;
|
|
1107
|
+
}
|
|
1108
|
+
} else {
|
|
1109
|
+
if (el.textContent !== projection.text) el.textContent = projection.text;
|
|
1110
|
+
delete el.dataset.vectoProjectionLines;
|
|
1055
1111
|
}
|
|
1056
|
-
if (el.textContent !== projection.text) el.textContent = projection.text;
|
|
1057
1112
|
const font = _nullishCoalesce(projection.font, () => ( ""));
|
|
1058
1113
|
if (el.style.font !== font) el.style.font = font;
|
|
1059
1114
|
const lineHeight = projection.lineHeight !== void 0 ? `${projection.lineHeight}px` : "";
|
|
@@ -1071,13 +1126,18 @@ var Scene = (_class2 = class _Scene {
|
|
|
1071
1126
|
el.style.cursor = selectable ? "text" : "";
|
|
1072
1127
|
}
|
|
1073
1128
|
const { a, b, c, d, e, f } = node.getWorldTransform();
|
|
1074
|
-
|
|
1075
|
-
|
|
1129
|
+
const contentX = _nullishCoalesce(projection.contentX, () => ( 0));
|
|
1130
|
+
const contentY = _nullishCoalesce(projection.contentY, () => ( 0));
|
|
1131
|
+
const baselineOffset = lines && lines.length > 0 ? 0 : projection.baseline === void 0 ? 0 : projection.baseline - _chunkDFNK6OV6js.cssLineBoxBaseline.call(void 0, font, _nullishCoalesce(projection.lineHeight, () => ( 16)));
|
|
1132
|
+
const localY = contentY + baselineOffset;
|
|
1133
|
+
el.style.left = `${e + a * contentX + c * localY}px`;
|
|
1134
|
+
el.style.top = `${f + b * contentX + d * localY}px`;
|
|
1076
1135
|
if (node.width > 0) el.style.width = `${node.width}px`;
|
|
1077
1136
|
if (node.height > 0) el.style.height = `${node.height}px`;
|
|
1078
1137
|
el.style.transform = `matrix(${a}, ${b}, ${c}, ${d}, 0, 0)`;
|
|
1079
1138
|
let visible = true;
|
|
1080
1139
|
if (node.width > 0 && node.height > 0) {
|
|
1140
|
+
const worldCorners = [];
|
|
1081
1141
|
let minX = Infinity;
|
|
1082
1142
|
let minY = Infinity;
|
|
1083
1143
|
let maxX = -Infinity;
|
|
@@ -1087,12 +1147,29 @@ var Scene = (_class2 = class _Scene {
|
|
|
1087
1147
|
const ly = i & 2 ? node.height : 0;
|
|
1088
1148
|
const wx = a * lx + c * ly + e;
|
|
1089
1149
|
const wy = b * lx + d * ly + f;
|
|
1150
|
+
worldCorners.push({ x: wx, y: wy });
|
|
1090
1151
|
if (wx < minX) minX = wx;
|
|
1091
1152
|
if (wx > maxX) maxX = wx;
|
|
1092
1153
|
if (wy < minY) minY = wy;
|
|
1093
1154
|
if (wy > maxY) maxY = wy;
|
|
1094
1155
|
}
|
|
1095
1156
|
visible = maxX >= 0 && minX <= this.width && maxY >= 0 && minY <= this.height;
|
|
1157
|
+
for (let ancestor = node.parent; visible && ancestor; ancestor = ancestor.parent) {
|
|
1158
|
+
if (!ancestor.clipChildren || ancestor.width <= 0 || ancestor.height <= 0) continue;
|
|
1159
|
+
let localMinX = Infinity;
|
|
1160
|
+
let localMinY = Infinity;
|
|
1161
|
+
let localMaxX = -Infinity;
|
|
1162
|
+
let localMaxY = -Infinity;
|
|
1163
|
+
for (const corner of worldCorners) {
|
|
1164
|
+
const local = ancestor.worldToLocal(corner.x, corner.y);
|
|
1165
|
+
if (!local) continue;
|
|
1166
|
+
localMinX = Math.min(localMinX, local.x);
|
|
1167
|
+
localMinY = Math.min(localMinY, local.y);
|
|
1168
|
+
localMaxX = Math.max(localMaxX, local.x);
|
|
1169
|
+
localMaxY = Math.max(localMaxY, local.y);
|
|
1170
|
+
}
|
|
1171
|
+
visible = localMaxX >= 0 && localMinX <= ancestor.width && localMaxY >= 0 && localMinY <= ancestor.height;
|
|
1172
|
+
}
|
|
1096
1173
|
}
|
|
1097
1174
|
const display = visible ? "" : "none";
|
|
1098
1175
|
if (el.style.display !== display) el.style.display = display;
|
|
@@ -1640,6 +1717,10 @@ var Scene = (_class2 = class _Scene {
|
|
|
1640
1717
|
getA11yElement(entityId) {
|
|
1641
1718
|
return this.a11yElements.get(entityId);
|
|
1642
1719
|
}
|
|
1720
|
+
/** Gets the static-content DOM projection for an entity ID, when materialized. */
|
|
1721
|
+
getContentElement(entityId) {
|
|
1722
|
+
return this.contentElements.get(entityId);
|
|
1723
|
+
}
|
|
1643
1724
|
/**
|
|
1644
1725
|
* Gets the root entity of the scene.
|
|
1645
1726
|
*/
|
|
@@ -1808,10 +1889,10 @@ var Scene = (_class2 = class _Scene {
|
|
|
1808
1889
|
// src/components/TextEntity.ts
|
|
1809
1890
|
var sharedMeasurer;
|
|
1810
1891
|
function defaultMeasurer() {
|
|
1811
|
-
if (sharedMeasurer === void 0) sharedMeasurer =
|
|
1892
|
+
if (sharedMeasurer === void 0) sharedMeasurer = _chunkZBKKRYDHjs.createCanvasMeasurer.call(void 0, "sans-serif");
|
|
1812
1893
|
return sharedMeasurer;
|
|
1813
1894
|
}
|
|
1814
|
-
var TextEntity = (_class3 = class extends
|
|
1895
|
+
var TextEntity = (_class3 = class extends _chunkDFNK6OV6js.Entity {
|
|
1815
1896
|
|
|
1816
1897
|
|
|
1817
1898
|
|
|
@@ -1828,7 +1909,7 @@ var TextEntity = (_class3 = class extends _chunkNHNOKBD4js.Entity {
|
|
|
1828
1909
|
this.text = text;
|
|
1829
1910
|
this.atlas = atlas;
|
|
1830
1911
|
this.fontSize = fontSize;
|
|
1831
|
-
this.layout = new (0,
|
|
1912
|
+
this.layout = new (0, _chunkZBKKRYDHjs.LayoutEngine)(maxWidth, 1e4, defaultMeasurer());
|
|
1832
1913
|
this.prepared = this.layout.prepare(this.text, this.atlas, this.fontSize);
|
|
1833
1914
|
this.applyLayout();
|
|
1834
1915
|
this.interactive = true;
|
|
@@ -1937,7 +2018,7 @@ var TextEntity = (_class3 = class extends _chunkNHNOKBD4js.Entity {
|
|
|
1937
2018
|
}, _class3);
|
|
1938
2019
|
|
|
1939
2020
|
// src/components/GridTextEntity.ts
|
|
1940
|
-
var GridTextEntity = (_class4 = class extends
|
|
2021
|
+
var GridTextEntity = (_class4 = class extends _chunkDFNK6OV6js.Entity {
|
|
1941
2022
|
|
|
1942
2023
|
__init60() {this.fillStyle = "#ffffff"}
|
|
1943
2024
|
__init61() {this.grid = []}
|
|
@@ -2031,7 +2112,7 @@ function distSqToSegment(px, py, x1, y1, x2, y2) {
|
|
|
2031
2112
|
const ey = py - cy;
|
|
2032
2113
|
return ex * ex + ey * ey;
|
|
2033
2114
|
}
|
|
2034
|
-
var SplineEntity = (_class5 = class extends
|
|
2115
|
+
var SplineEntity = (_class5 = class extends _chunkDFNK6OV6js.Entity {
|
|
2035
2116
|
|
|
2036
2117
|
|
|
2037
2118
|
|
|
@@ -2400,7 +2481,7 @@ var SpatialHashGrid = (_class6 = class {
|
|
|
2400
2481
|
}, _class6);
|
|
2401
2482
|
|
|
2402
2483
|
// src/tree/DOMPortalEntity.ts
|
|
2403
|
-
var DOMPortalEntity = (_class7 = class extends
|
|
2484
|
+
var DOMPortalEntity = (_class7 = class extends _chunkDFNK6OV6js.Entity {
|
|
2404
2485
|
|
|
2405
2486
|
__init72() {this.isDOMPortal = true}
|
|
2406
2487
|
__init73() {this.domListeners = []}
|
|
@@ -2435,7 +2516,7 @@ var DOMPortalEntity = (_class7 = class extends _chunkNHNOKBD4js.Entity {
|
|
|
2435
2516
|
const events = ["click", "pointerdown", "pointerup", "pointermove", "wheel"];
|
|
2436
2517
|
for (const type of events) {
|
|
2437
2518
|
const handler = (e) => {
|
|
2438
|
-
this.dispatchEvent(new (0,
|
|
2519
|
+
this.dispatchEvent(new (0, _chunkDFNK6OV6js.VectoJSEvent)(type, this, e));
|
|
2439
2520
|
};
|
|
2440
2521
|
this.domElement.addEventListener(type, handler);
|
|
2441
2522
|
this.domListeners.push({ type, handler, capture: false });
|
|
@@ -2446,7 +2527,7 @@ var DOMPortalEntity = (_class7 = class extends _chunkNHNOKBD4js.Entity {
|
|
|
2446
2527
|
];
|
|
2447
2528
|
for (const { native, vecto } of hoverEvents) {
|
|
2448
2529
|
const handler = (e) => {
|
|
2449
|
-
this.dispatchEvent(new (0,
|
|
2530
|
+
this.dispatchEvent(new (0, _chunkDFNK6OV6js.VectoJSEvent)(vecto, this, e, false));
|
|
2450
2531
|
};
|
|
2451
2532
|
this.domElement.addEventListener(native, handler);
|
|
2452
2533
|
this.domListeners.push({ type: native, handler, capture: false });
|
|
@@ -2454,7 +2535,7 @@ var DOMPortalEntity = (_class7 = class extends _chunkNHNOKBD4js.Entity {
|
|
|
2454
2535
|
const focusEvents = ["focus", "blur"];
|
|
2455
2536
|
for (const type of focusEvents) {
|
|
2456
2537
|
const handler = (e) => {
|
|
2457
|
-
this.dispatchEvent(new (0,
|
|
2538
|
+
this.dispatchEvent(new (0, _chunkDFNK6OV6js.VectoJSEvent)(type, this, e, true));
|
|
2458
2539
|
};
|
|
2459
2540
|
this.domElement.addEventListener(type, handler, true);
|
|
2460
2541
|
this.domListeners.push({ type, handler, capture: true });
|
|
@@ -2539,4 +2620,6 @@ Scene.registerWebGPUParticleSystemManager(_chunkBPMNCGU7js.WebGPUParticleSystemM
|
|
|
2539
2620
|
|
|
2540
2621
|
|
|
2541
2622
|
|
|
2542
|
-
|
|
2623
|
+
|
|
2624
|
+
|
|
2625
|
+
exports.ArabicShaper = _chunkCTZQOM5Zjs.ArabicShaper; exports.BidiResolver = _chunkCTZQOM5Zjs.BidiResolver; exports.CanvasRenderer = _chunkBPMNCGU7js.CanvasRenderer; exports.ComputeParticleEntity = ComputeParticleEntity; exports.DOMPortalEntity = DOMPortalEntity; exports.Easing = _chunkDFNK6OV6js.Easing; exports.Entity = _chunkDFNK6OV6js.Entity; exports.GridTextEntity = GridTextEntity; exports.LayoutEngine = _chunkZBKKRYDHjs.LayoutEngine; exports.LayoutResultBuffer = _chunkZBKKRYDHjs.LayoutResultBuffer; exports.LayoutWorkerManager = _chunkCTZQOM5Zjs.LayoutWorkerManager; exports.MSDFFont = _chunkDFNK6OV6js.MSDFFont; exports.MSDFTextEntity = _chunkDFNK6OV6js.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 = _chunkDFNK6OV6js.SVGEntity; exports.SVGRenderer = _chunkBPMNCGU7js.SVGRenderer; exports.Scene = Scene; exports.SpatialHashGrid = SpatialHashGrid; exports.SplineEntity = SplineEntity; exports.SpringDriver = _chunkDFNK6OV6js.SpringDriver; exports.SpringPhysics = _chunkDFNK6OV6js.SpringPhysics; exports.TextEntity = TextEntity; exports.TweenDriver = _chunkDFNK6OV6js.TweenDriver; exports.VectoJSEvent = _chunkDFNK6OV6js.VectoJSEvent; exports.WebGPUParticleSystemManager = _chunkBPMNCGU7js.WebGPUParticleSystemManager; exports.clearCssLineBoxMetrics = _chunkDFNK6OV6js.clearCssLineBoxMetrics; exports.computeLineSegments = _chunkZBKKRYDHjs.computeLineSegments; exports.createCanvasMeasurer = _chunkZBKKRYDHjs.createCanvasMeasurer; exports.createWebGLPointRenderer = _chunkBPMNCGU7js.createWebGLPointRenderer; exports.cssLineBoxBaseline = _chunkDFNK6OV6js.cssLineBoxBaseline; exports.isSafeUrl = _chunkBPMNCGU7js.isSafeUrl; exports.isTweenConfig = _chunkDFNK6OV6js.isTweenConfig; exports.loadSpline = loadSpline; exports.parseColorToRGBA = _chunkBPMNCGU7js.parseColorToRGBA; exports.polySegmentToBezier = polySegmentToBezier; exports.sanitizeUrl = _chunkBPMNCGU7js.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-V7GUWG5C.mjs";
|
|
7
7
|
import {
|
|
8
8
|
CanvasRenderer,
|
|
9
9
|
SVGRenderer,
|
|
@@ -23,8 +23,10 @@ import {
|
|
|
23
23
|
SpringPhysics,
|
|
24
24
|
TweenDriver,
|
|
25
25
|
VectoJSEvent,
|
|
26
|
+
clearCssLineBoxMetrics,
|
|
27
|
+
cssLineBoxBaseline,
|
|
26
28
|
isTweenConfig
|
|
27
|
-
} from "./chunk-
|
|
29
|
+
} from "./chunk-3CODWSF3.mjs";
|
|
28
30
|
import {
|
|
29
31
|
ArabicShaper,
|
|
30
32
|
BidiResolver,
|
|
@@ -505,6 +507,7 @@ var Scene = class _Scene {
|
|
|
505
507
|
};
|
|
506
508
|
if (typeof document !== "undefined" && document.fonts) {
|
|
507
509
|
this.fontLoadHandler = () => {
|
|
510
|
+
clearCssLineBoxMetrics();
|
|
508
511
|
this.markDirty();
|
|
509
512
|
};
|
|
510
513
|
document.fonts.ready.then(this.fontLoadHandler);
|
|
@@ -553,6 +556,7 @@ var Scene = class _Scene {
|
|
|
553
556
|
if (contentEl) {
|
|
554
557
|
contentEl.remove();
|
|
555
558
|
this.contentElements.delete(node.id);
|
|
559
|
+
this.a11yNeedsReorder = true;
|
|
556
560
|
}
|
|
557
561
|
const el = this.a11yElements.get(node.id);
|
|
558
562
|
if (el) {
|
|
@@ -992,6 +996,16 @@ var Scene = class _Scene {
|
|
|
992
996
|
el.setAttribute("aria-valuenow", attrs.value);
|
|
993
997
|
}
|
|
994
998
|
}
|
|
999
|
+
if (attrs.textInputStyle !== void 0 && (el instanceof HTMLInputElement || el instanceof HTMLTextAreaElement)) {
|
|
1000
|
+
const textStyle = attrs.textInputStyle;
|
|
1001
|
+
if (el.style.font !== textStyle.font) el.style.font = textStyle.font;
|
|
1002
|
+
const lineHeight = `${textStyle.lineHeight}px`;
|
|
1003
|
+
if (el.style.lineHeight !== lineHeight) el.style.lineHeight = lineHeight;
|
|
1004
|
+
const padding = `${textStyle.padding}px`;
|
|
1005
|
+
if (el.style.padding !== padding) el.style.padding = padding;
|
|
1006
|
+
if (el.style.boxSizing !== "border-box") el.style.boxSizing = "border-box";
|
|
1007
|
+
if (el instanceof HTMLTextAreaElement) el.style.resize = "none";
|
|
1008
|
+
}
|
|
995
1009
|
if (node.a11yFullViewport) {
|
|
996
1010
|
el.style.left = "0px";
|
|
997
1011
|
el.style.top = "0px";
|
|
@@ -1028,6 +1042,7 @@ var Scene = class _Scene {
|
|
|
1028
1042
|
if (el) {
|
|
1029
1043
|
el.remove();
|
|
1030
1044
|
this.contentElements.delete(node.id);
|
|
1045
|
+
this.a11yNeedsReorder = true;
|
|
1031
1046
|
}
|
|
1032
1047
|
return;
|
|
1033
1048
|
}
|
|
@@ -1052,8 +1067,48 @@ var Scene = class _Scene {
|
|
|
1052
1067
|
);
|
|
1053
1068
|
this.a11yRoot.appendChild(el);
|
|
1054
1069
|
this.contentElements.set(node.id, el);
|
|
1070
|
+
this.a11yNeedsReorder = true;
|
|
1071
|
+
}
|
|
1072
|
+
const lines = projection.lines;
|
|
1073
|
+
if (lines && lines.length > 0) {
|
|
1074
|
+
const signature = JSON.stringify({
|
|
1075
|
+
lines,
|
|
1076
|
+
fallbackFont: projection.font ?? "",
|
|
1077
|
+
fallbackLineHeight: projection.lineHeight ?? 16
|
|
1078
|
+
});
|
|
1079
|
+
if (el.dataset.vectoProjectionLines !== signature) {
|
|
1080
|
+
el.replaceChildren();
|
|
1081
|
+
for (let index = 0; index < lines.length; index++) {
|
|
1082
|
+
const line = lines[index];
|
|
1083
|
+
const lineElement = document.createElement("span");
|
|
1084
|
+
const lineFont = line.font ?? projection.font ?? "";
|
|
1085
|
+
const lineHeight2 = line.lineHeight ?? projection.lineHeight ?? 16;
|
|
1086
|
+
lineElement.style.position = "absolute";
|
|
1087
|
+
lineElement.style.left = `${line.x}px`;
|
|
1088
|
+
lineElement.style.top = `${line.y + line.baseline - cssLineBoxBaseline(lineFont, lineHeight2)}px`;
|
|
1089
|
+
lineElement.style.whiteSpace = "pre";
|
|
1090
|
+
if (lineFont) lineElement.style.font = lineFont;
|
|
1091
|
+
lineElement.style.lineHeight = `${lineHeight2}px`;
|
|
1092
|
+
if (line.runs && line.runs.length > 0) {
|
|
1093
|
+
for (const run of line.runs) {
|
|
1094
|
+
const runElement = document.createElement("span");
|
|
1095
|
+
runElement.textContent = run.text;
|
|
1096
|
+
if (run.font) runElement.style.font = run.font;
|
|
1097
|
+
runElement.style.lineHeight = `${lineHeight2}px`;
|
|
1098
|
+
lineElement.appendChild(runElement);
|
|
1099
|
+
}
|
|
1100
|
+
} else {
|
|
1101
|
+
lineElement.textContent = line.text;
|
|
1102
|
+
}
|
|
1103
|
+
el.appendChild(lineElement);
|
|
1104
|
+
if (index < lines.length - 1) el.appendChild(document.createTextNode("\n"));
|
|
1105
|
+
}
|
|
1106
|
+
el.dataset.vectoProjectionLines = signature;
|
|
1107
|
+
}
|
|
1108
|
+
} else {
|
|
1109
|
+
if (el.textContent !== projection.text) el.textContent = projection.text;
|
|
1110
|
+
delete el.dataset.vectoProjectionLines;
|
|
1055
1111
|
}
|
|
1056
|
-
if (el.textContent !== projection.text) el.textContent = projection.text;
|
|
1057
1112
|
const font = projection.font ?? "";
|
|
1058
1113
|
if (el.style.font !== font) el.style.font = font;
|
|
1059
1114
|
const lineHeight = projection.lineHeight !== void 0 ? `${projection.lineHeight}px` : "";
|
|
@@ -1071,13 +1126,18 @@ var Scene = class _Scene {
|
|
|
1071
1126
|
el.style.cursor = selectable ? "text" : "";
|
|
1072
1127
|
}
|
|
1073
1128
|
const { a, b, c, d, e, f } = node.getWorldTransform();
|
|
1074
|
-
|
|
1075
|
-
|
|
1129
|
+
const contentX = projection.contentX ?? 0;
|
|
1130
|
+
const contentY = projection.contentY ?? 0;
|
|
1131
|
+
const baselineOffset = lines && lines.length > 0 ? 0 : projection.baseline === void 0 ? 0 : projection.baseline - cssLineBoxBaseline(font, projection.lineHeight ?? 16);
|
|
1132
|
+
const localY = contentY + baselineOffset;
|
|
1133
|
+
el.style.left = `${e + a * contentX + c * localY}px`;
|
|
1134
|
+
el.style.top = `${f + b * contentX + d * localY}px`;
|
|
1076
1135
|
if (node.width > 0) el.style.width = `${node.width}px`;
|
|
1077
1136
|
if (node.height > 0) el.style.height = `${node.height}px`;
|
|
1078
1137
|
el.style.transform = `matrix(${a}, ${b}, ${c}, ${d}, 0, 0)`;
|
|
1079
1138
|
let visible = true;
|
|
1080
1139
|
if (node.width > 0 && node.height > 0) {
|
|
1140
|
+
const worldCorners = [];
|
|
1081
1141
|
let minX = Infinity;
|
|
1082
1142
|
let minY = Infinity;
|
|
1083
1143
|
let maxX = -Infinity;
|
|
@@ -1087,12 +1147,29 @@ var Scene = class _Scene {
|
|
|
1087
1147
|
const ly = i & 2 ? node.height : 0;
|
|
1088
1148
|
const wx = a * lx + c * ly + e;
|
|
1089
1149
|
const wy = b * lx + d * ly + f;
|
|
1150
|
+
worldCorners.push({ x: wx, y: wy });
|
|
1090
1151
|
if (wx < minX) minX = wx;
|
|
1091
1152
|
if (wx > maxX) maxX = wx;
|
|
1092
1153
|
if (wy < minY) minY = wy;
|
|
1093
1154
|
if (wy > maxY) maxY = wy;
|
|
1094
1155
|
}
|
|
1095
1156
|
visible = maxX >= 0 && minX <= this.width && maxY >= 0 && minY <= this.height;
|
|
1157
|
+
for (let ancestor = node.parent; visible && ancestor; ancestor = ancestor.parent) {
|
|
1158
|
+
if (!ancestor.clipChildren || ancestor.width <= 0 || ancestor.height <= 0) continue;
|
|
1159
|
+
let localMinX = Infinity;
|
|
1160
|
+
let localMinY = Infinity;
|
|
1161
|
+
let localMaxX = -Infinity;
|
|
1162
|
+
let localMaxY = -Infinity;
|
|
1163
|
+
for (const corner of worldCorners) {
|
|
1164
|
+
const local = ancestor.worldToLocal(corner.x, corner.y);
|
|
1165
|
+
if (!local) continue;
|
|
1166
|
+
localMinX = Math.min(localMinX, local.x);
|
|
1167
|
+
localMinY = Math.min(localMinY, local.y);
|
|
1168
|
+
localMaxX = Math.max(localMaxX, local.x);
|
|
1169
|
+
localMaxY = Math.max(localMaxY, local.y);
|
|
1170
|
+
}
|
|
1171
|
+
visible = localMaxX >= 0 && localMinX <= ancestor.width && localMaxY >= 0 && localMinY <= ancestor.height;
|
|
1172
|
+
}
|
|
1096
1173
|
}
|
|
1097
1174
|
const display = visible ? "" : "none";
|
|
1098
1175
|
if (el.style.display !== display) el.style.display = display;
|
|
@@ -1640,6 +1717,10 @@ var Scene = class _Scene {
|
|
|
1640
1717
|
getA11yElement(entityId) {
|
|
1641
1718
|
return this.a11yElements.get(entityId);
|
|
1642
1719
|
}
|
|
1720
|
+
/** Gets the static-content DOM projection for an entity ID, when materialized. */
|
|
1721
|
+
getContentElement(entityId) {
|
|
1722
|
+
return this.contentElements.get(entityId);
|
|
1723
|
+
}
|
|
1643
1724
|
/**
|
|
1644
1725
|
* Gets the root entity of the scene.
|
|
1645
1726
|
*/
|
|
@@ -2530,9 +2611,11 @@ export {
|
|
|
2530
2611
|
TweenDriver,
|
|
2531
2612
|
VectoJSEvent,
|
|
2532
2613
|
WebGPUParticleSystemManager,
|
|
2614
|
+
clearCssLineBoxMetrics,
|
|
2533
2615
|
computeLineSegments,
|
|
2534
2616
|
createCanvasMeasurer,
|
|
2535
2617
|
createWebGLPointRenderer,
|
|
2618
|
+
cssLineBoxBaseline,
|
|
2536
2619
|
isSafeUrl,
|
|
2537
2620
|
isTweenConfig,
|
|
2538
2621
|
loadSpline,
|
package/dist/layout.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
|
|
4
4
|
|
|
5
5
|
|
|
6
|
-
var
|
|
6
|
+
var _chunkZBKKRYDHjs = require('./chunk-ZBKKRYDH.js');
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
var _chunkCTZQOM5Zjs = require('./chunk-CTZQOM5Z.js');
|
|
@@ -13,4 +13,4 @@ var _chunkCTZQOM5Zjs = require('./chunk-CTZQOM5Z.js');
|
|
|
13
13
|
|
|
14
14
|
|
|
15
15
|
|
|
16
|
-
exports.LayoutEngine =
|
|
16
|
+
exports.LayoutEngine = _chunkZBKKRYDHjs.LayoutEngine; exports.LayoutResultBuffer = _chunkZBKKRYDHjs.LayoutResultBuffer; exports.LayoutWorkerManager = _chunkCTZQOM5Zjs.LayoutWorkerManager; exports.computeLineSegments = _chunkZBKKRYDHjs.computeLineSegments; exports.createCanvasMeasurer = _chunkZBKKRYDHjs.createCanvasMeasurer;
|
package/dist/layout.mjs
CHANGED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Return the baseline offset inside a CSS line box for a canvas-compatible
|
|
3
|
+
* font. Canvas text and a native editor must use this identical value whenever
|
|
4
|
+
* one mirrors the other; CSS otherwise centers font metrics in the line box.
|
|
5
|
+
*
|
|
6
|
+
* The 0.8 fallback preserves the framework's deterministic, DOM-free text
|
|
7
|
+
* contract in SSR and test environments where Canvas 2D is unavailable.
|
|
8
|
+
*/
|
|
9
|
+
export declare function cssLineBoxBaseline(font: string, lineHeight: number): number;
|
|
10
|
+
/** Clear cached browser font metrics after a webfont finishes loading. */
|
|
11
|
+
export declare function clearCssLineBoxMetrics(): void;
|
package/dist/text/index.d.ts
CHANGED
package/dist/text.js
CHANGED
|
@@ -2,7 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
var _chunkDFNK6OV6js = require('./chunk-DFNK6OV6.js');
|
|
6
8
|
|
|
7
9
|
|
|
8
10
|
|
|
@@ -13,4 +15,6 @@ var _chunkCTZQOM5Zjs = require('./chunk-CTZQOM5Z.js');
|
|
|
13
15
|
|
|
14
16
|
|
|
15
17
|
|
|
16
|
-
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
exports.ArabicShaper = _chunkCTZQOM5Zjs.ArabicShaper; exports.BidiResolver = _chunkCTZQOM5Zjs.BidiResolver; exports.MSDFFont = _chunkDFNK6OV6js.MSDFFont; exports.MSDFTextEntity = _chunkDFNK6OV6js.MSDFTextEntity; exports.SVGEntity = _chunkDFNK6OV6js.SVGEntity; exports.clearCssLineBoxMetrics = _chunkDFNK6OV6js.clearCssLineBoxMetrics; exports.cssLineBoxBaseline = _chunkDFNK6OV6js.cssLineBoxBaseline;
|
package/dist/text.mjs
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
MSDFFont,
|
|
3
3
|
MSDFTextEntity,
|
|
4
|
-
SVGEntity
|
|
5
|
-
|
|
4
|
+
SVGEntity,
|
|
5
|
+
clearCssLineBoxMetrics,
|
|
6
|
+
cssLineBoxBaseline
|
|
7
|
+
} from "./chunk-3CODWSF3.mjs";
|
|
6
8
|
import {
|
|
7
9
|
ArabicShaper,
|
|
8
10
|
BidiResolver
|
|
@@ -12,5 +14,7 @@ export {
|
|
|
12
14
|
BidiResolver,
|
|
13
15
|
MSDFFont,
|
|
14
16
|
MSDFTextEntity,
|
|
15
|
-
SVGEntity
|
|
17
|
+
SVGEntity,
|
|
18
|
+
clearCssLineBoxMetrics,
|
|
19
|
+
cssLineBoxBaseline
|
|
16
20
|
};
|
package/dist/tree/Entity.d.ts
CHANGED
|
@@ -59,6 +59,27 @@ export interface BatchRect {
|
|
|
59
59
|
* find-in-page, screen readers, SEO crawlers, translation, `#:~:text=`
|
|
60
60
|
* fragments — operates on canvas-rendered text.
|
|
61
61
|
*/
|
|
62
|
+
export interface ContentProjectionRun {
|
|
63
|
+
/** Text written with one CSS font inside a projected visual line. */
|
|
64
|
+
text: string;
|
|
65
|
+
/** CSS font shorthand matching the canvas run. */
|
|
66
|
+
font?: string;
|
|
67
|
+
}
|
|
68
|
+
export interface ContentProjectionLine {
|
|
69
|
+
/** Text for browser find-in-page and native selection. */
|
|
70
|
+
text: string;
|
|
71
|
+
/** Local origin of the visual line inside the entity. */
|
|
72
|
+
x: number;
|
|
73
|
+
y: number;
|
|
74
|
+
/** Canvas baseline relative to `y`. */
|
|
75
|
+
baseline: number;
|
|
76
|
+
/** CSS font used for the line when it has no styled runs. */
|
|
77
|
+
font?: string;
|
|
78
|
+
/** Explicit line height for this line. */
|
|
79
|
+
lineHeight?: number;
|
|
80
|
+
/** Styled text runs in visual order. */
|
|
81
|
+
runs?: ContentProjectionRun[];
|
|
82
|
+
}
|
|
62
83
|
export interface ContentProjection {
|
|
63
84
|
/** The plain text content as rendered (line breaks as `\n`). */
|
|
64
85
|
text: string;
|
|
@@ -71,6 +92,27 @@ export interface ContentProjection {
|
|
|
71
92
|
* projection never intercepts pointer input meant for the canvas.
|
|
72
93
|
*/
|
|
73
94
|
selectable?: boolean;
|
|
95
|
+
/** Local x-origin of the rendered text inside the owning entity. */
|
|
96
|
+
contentX?: number;
|
|
97
|
+
/** Local y-origin of the rendered text inside the owning entity. */
|
|
98
|
+
contentY?: number;
|
|
99
|
+
/**
|
|
100
|
+
* Canvas baseline relative to `contentY` for the first line. When supplied,
|
|
101
|
+
* Scene aligns the DOM line box baseline instead of assuming both engines
|
|
102
|
+
* interpret the entity top as a text baseline.
|
|
103
|
+
*/
|
|
104
|
+
baseline?: number;
|
|
105
|
+
/** Explicit visual lines for mixed-style or internally inset text. */
|
|
106
|
+
lines?: ContentProjectionLine[];
|
|
107
|
+
}
|
|
108
|
+
/** Typography for a native input projected by the accessibility layer. */
|
|
109
|
+
export interface TextInputStyle {
|
|
110
|
+
/** CSS font shorthand shared with the canvas mirror. */
|
|
111
|
+
font: string;
|
|
112
|
+
/** Explicit line advance in CSS pixels. */
|
|
113
|
+
lineHeight: number;
|
|
114
|
+
/** Inner text inset in CSS pixels. */
|
|
115
|
+
padding: number;
|
|
74
116
|
}
|
|
75
117
|
/**
|
|
76
118
|
* Semantic attributes an {@link Entity} can project into the accessibility /
|
|
@@ -114,6 +156,8 @@ export interface A11yAttributes {
|
|
|
114
156
|
activedescendant?: string;
|
|
115
157
|
valuemin?: string;
|
|
116
158
|
valuemax?: string;
|
|
159
|
+
/** Explicit native editor typography; ignored for non-input elements. */
|
|
160
|
+
textInputStyle?: TextInputStyle;
|
|
117
161
|
}
|
|
118
162
|
/**
|
|
119
163
|
* Union of all pointer/interaction events that can be emitted by an {@link Entity}.
|
package/dist/tree/Scene.d.ts
CHANGED
|
@@ -330,6 +330,8 @@ export declare class Scene {
|
|
|
330
330
|
* Gets the accessibility DOM element projected for the given entity ID.
|
|
331
331
|
*/
|
|
332
332
|
getA11yElement(entityId: string): HTMLElement | undefined;
|
|
333
|
+
/** Gets the static-content DOM projection for an entity ID, when materialized. */
|
|
334
|
+
getContentElement(entityId: string): HTMLElement | undefined;
|
|
333
335
|
/**
|
|
334
336
|
* Gets the root entity of the scene.
|
|
335
337
|
*/
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vectojs/core",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.6.0",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
@@ -54,7 +54,7 @@
|
|
|
54
54
|
"scripts": {
|
|
55
55
|
"build": "node scripts/build-worker.js && tsup && tsc -p tsconfig.build.json",
|
|
56
56
|
"test": "vitest run",
|
|
57
|
-
"test:e2e": "bun e2e/hidpi.e2e.ts"
|
|
57
|
+
"test:e2e": "bun e2e/hidpi.e2e.ts && bun e2e/text-projection.e2e.ts"
|
|
58
58
|
},
|
|
59
59
|
"dependencies": {},
|
|
60
60
|
"devDependencies": {
|