@vectojs/core 1.5.0 → 1.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -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 +111 -32
- package/dist/index.mjs +87 -8
- 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 +45 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -112,6 +112,11 @@ 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
|
+
Interactive projected nodes capture the active pointer on `pointerdown` and route
|
|
116
|
+
`pointermove`, `pointerup`, and `pointercancel` through normal VMT capture/bubble propagation.
|
|
117
|
+
Treat `pointercancel` as rollback: discard transient gesture state and do not create durable
|
|
118
|
+
history. Pointer capture is released safely on both completion paths.
|
|
119
|
+
|
|
115
120
|
## Static content projection
|
|
116
121
|
|
|
117
122
|
Canvas-rendered text can opt into browser-native find, translation, selection, and copy without
|
|
@@ -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);
|
|
@@ -802,42 +805,56 @@ var Scene = (_class2 = class _Scene {
|
|
|
802
805
|
el.style.background = "transparent";
|
|
803
806
|
}
|
|
804
807
|
el.addEventListener("click", (e) => {
|
|
805
|
-
node.dispatchEvent(new (0,
|
|
808
|
+
node.dispatchEvent(new (0, _chunkDFNK6OV6js.VectoJSEvent)("click", node, e));
|
|
806
809
|
});
|
|
807
810
|
el.addEventListener("mouseenter", (e) => {
|
|
808
811
|
if (this.debugA11y) el.style.backgroundColor = "rgba(56, 189, 248, 0.2)";
|
|
809
|
-
node.dispatchEvent(new (0,
|
|
812
|
+
node.dispatchEvent(new (0, _chunkDFNK6OV6js.VectoJSEvent)("hover", node, e, false));
|
|
810
813
|
});
|
|
811
814
|
el.addEventListener("mouseleave", (e) => {
|
|
812
815
|
if (this.debugA11y) el.style.backgroundColor = "rgba(56, 189, 248, 0.05)";
|
|
813
|
-
node.dispatchEvent(new (0,
|
|
816
|
+
node.dispatchEvent(new (0, _chunkDFNK6OV6js.VectoJSEvent)("pointerleave", node, e, false));
|
|
814
817
|
});
|
|
815
818
|
const capEl = el;
|
|
819
|
+
const releasePointer = (event) => {
|
|
820
|
+
if (typeof capEl.releasePointerCapture !== "function") return;
|
|
821
|
+
if (typeof capEl.hasPointerCapture === "function" && !capEl.hasPointerCapture(event.pointerId)) {
|
|
822
|
+
return;
|
|
823
|
+
}
|
|
824
|
+
try {
|
|
825
|
+
capEl.releasePointerCapture(event.pointerId);
|
|
826
|
+
} catch (error) {
|
|
827
|
+
if (!(error instanceof DOMException) || error.name !== "NotFoundError") throw error;
|
|
828
|
+
}
|
|
829
|
+
};
|
|
816
830
|
el.addEventListener("pointerdown", (e) => {
|
|
817
831
|
if (typeof capEl.setPointerCapture === "function") capEl.setPointerCapture(e.pointerId);
|
|
818
|
-
node.dispatchEvent(new (0,
|
|
832
|
+
node.dispatchEvent(new (0, _chunkDFNK6OV6js.VectoJSEvent)("pointerdown", node, e));
|
|
819
833
|
});
|
|
820
834
|
el.addEventListener("pointerup", (e) => {
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
835
|
+
releasePointer(e);
|
|
836
|
+
node.dispatchEvent(new (0, _chunkDFNK6OV6js.VectoJSEvent)("pointerup", node, e));
|
|
837
|
+
});
|
|
838
|
+
el.addEventListener("pointercancel", (e) => {
|
|
839
|
+
releasePointer(e);
|
|
840
|
+
node.dispatchEvent(new (0, _chunkDFNK6OV6js.VectoJSEvent)("pointercancel", node, e));
|
|
824
841
|
});
|
|
825
842
|
el.addEventListener(
|
|
826
843
|
"pointermove",
|
|
827
|
-
(e) => node.dispatchEvent(new (0,
|
|
844
|
+
(e) => node.dispatchEvent(new (0, _chunkDFNK6OV6js.VectoJSEvent)("pointermove", node, e))
|
|
828
845
|
);
|
|
829
846
|
el.addEventListener(
|
|
830
847
|
"wheel",
|
|
831
848
|
(e) => {
|
|
832
|
-
node.dispatchEvent(new (0,
|
|
849
|
+
node.dispatchEvent(new (0, _chunkDFNK6OV6js.VectoJSEvent)("wheel", node, e));
|
|
833
850
|
},
|
|
834
851
|
{ passive: false }
|
|
835
852
|
);
|
|
836
853
|
el.addEventListener("keydown", (e) => {
|
|
837
|
-
node.dispatchEvent(new (0,
|
|
854
|
+
node.dispatchEvent(new (0, _chunkDFNK6OV6js.VectoJSEvent)("keydown", node, e));
|
|
838
855
|
});
|
|
839
856
|
el.addEventListener("keyup", (e) => {
|
|
840
|
-
node.dispatchEvent(new (0,
|
|
857
|
+
node.dispatchEvent(new (0, _chunkDFNK6OV6js.VectoJSEvent)("keyup", node, e));
|
|
841
858
|
});
|
|
842
859
|
if (el instanceof HTMLInputElement || el instanceof HTMLTextAreaElement) {
|
|
843
860
|
const input = el;
|
|
@@ -910,7 +927,7 @@ var Scene = (_class2 = class _Scene {
|
|
|
910
927
|
el.addEventListener("keydown", (e) => {
|
|
911
928
|
if (e.key === "Enter" || e.key === " ") {
|
|
912
929
|
e.preventDefault();
|
|
913
|
-
node.dispatchEvent(new (0,
|
|
930
|
+
node.dispatchEvent(new (0, _chunkDFNK6OV6js.VectoJSEvent)("click", node, e));
|
|
914
931
|
}
|
|
915
932
|
});
|
|
916
933
|
}
|
|
@@ -993,6 +1010,16 @@ var Scene = (_class2 = class _Scene {
|
|
|
993
1010
|
el.setAttribute("aria-valuenow", attrs.value);
|
|
994
1011
|
}
|
|
995
1012
|
}
|
|
1013
|
+
if (attrs.textInputStyle !== void 0 && (el instanceof HTMLInputElement || el instanceof HTMLTextAreaElement)) {
|
|
1014
|
+
const textStyle = attrs.textInputStyle;
|
|
1015
|
+
if (el.style.font !== textStyle.font) el.style.font = textStyle.font;
|
|
1016
|
+
const lineHeight = `${textStyle.lineHeight}px`;
|
|
1017
|
+
if (el.style.lineHeight !== lineHeight) el.style.lineHeight = lineHeight;
|
|
1018
|
+
const padding = `${textStyle.padding}px`;
|
|
1019
|
+
if (el.style.padding !== padding) el.style.padding = padding;
|
|
1020
|
+
if (el.style.boxSizing !== "border-box") el.style.boxSizing = "border-box";
|
|
1021
|
+
if (el instanceof HTMLTextAreaElement) el.style.resize = "none";
|
|
1022
|
+
}
|
|
996
1023
|
if (node.a11yFullViewport) {
|
|
997
1024
|
el.style.left = "0px";
|
|
998
1025
|
el.style.top = "0px";
|
|
@@ -1048,7 +1075,7 @@ var Scene = (_class2 = class _Scene {
|
|
|
1048
1075
|
el.addEventListener(
|
|
1049
1076
|
"wheel",
|
|
1050
1077
|
(e2) => {
|
|
1051
|
-
node.dispatchEvent(new (0,
|
|
1078
|
+
node.dispatchEvent(new (0, _chunkDFNK6OV6js.VectoJSEvent)("wheel", node, e2));
|
|
1052
1079
|
},
|
|
1053
1080
|
{ passive: false }
|
|
1054
1081
|
);
|
|
@@ -1056,7 +1083,46 @@ var Scene = (_class2 = class _Scene {
|
|
|
1056
1083
|
this.contentElements.set(node.id, el);
|
|
1057
1084
|
this.a11yNeedsReorder = true;
|
|
1058
1085
|
}
|
|
1059
|
-
|
|
1086
|
+
const lines = projection.lines;
|
|
1087
|
+
if (lines && lines.length > 0) {
|
|
1088
|
+
const signature = JSON.stringify({
|
|
1089
|
+
lines,
|
|
1090
|
+
fallbackFont: _nullishCoalesce(projection.font, () => ( "")),
|
|
1091
|
+
fallbackLineHeight: _nullishCoalesce(projection.lineHeight, () => ( 16))
|
|
1092
|
+
});
|
|
1093
|
+
if (el.dataset.vectoProjectionLines !== signature) {
|
|
1094
|
+
el.replaceChildren();
|
|
1095
|
+
for (let index = 0; index < lines.length; index++) {
|
|
1096
|
+
const line = lines[index];
|
|
1097
|
+
const lineElement = document.createElement("span");
|
|
1098
|
+
const lineFont = _nullishCoalesce(_nullishCoalesce(line.font, () => ( projection.font)), () => ( ""));
|
|
1099
|
+
const lineHeight2 = _nullishCoalesce(_nullishCoalesce(line.lineHeight, () => ( projection.lineHeight)), () => ( 16));
|
|
1100
|
+
lineElement.style.position = "absolute";
|
|
1101
|
+
lineElement.style.left = `${line.x}px`;
|
|
1102
|
+
lineElement.style.top = `${line.y + line.baseline - _chunkDFNK6OV6js.cssLineBoxBaseline.call(void 0, lineFont, lineHeight2)}px`;
|
|
1103
|
+
lineElement.style.whiteSpace = "pre";
|
|
1104
|
+
if (lineFont) lineElement.style.font = lineFont;
|
|
1105
|
+
lineElement.style.lineHeight = `${lineHeight2}px`;
|
|
1106
|
+
if (line.runs && line.runs.length > 0) {
|
|
1107
|
+
for (const run of line.runs) {
|
|
1108
|
+
const runElement = document.createElement("span");
|
|
1109
|
+
runElement.textContent = run.text;
|
|
1110
|
+
if (run.font) runElement.style.font = run.font;
|
|
1111
|
+
runElement.style.lineHeight = `${lineHeight2}px`;
|
|
1112
|
+
lineElement.appendChild(runElement);
|
|
1113
|
+
}
|
|
1114
|
+
} else {
|
|
1115
|
+
lineElement.textContent = line.text;
|
|
1116
|
+
}
|
|
1117
|
+
el.appendChild(lineElement);
|
|
1118
|
+
if (index < lines.length - 1) el.appendChild(document.createTextNode("\n"));
|
|
1119
|
+
}
|
|
1120
|
+
el.dataset.vectoProjectionLines = signature;
|
|
1121
|
+
}
|
|
1122
|
+
} else {
|
|
1123
|
+
if (el.textContent !== projection.text) el.textContent = projection.text;
|
|
1124
|
+
delete el.dataset.vectoProjectionLines;
|
|
1125
|
+
}
|
|
1060
1126
|
const font = _nullishCoalesce(projection.font, () => ( ""));
|
|
1061
1127
|
if (el.style.font !== font) el.style.font = font;
|
|
1062
1128
|
const lineHeight = projection.lineHeight !== void 0 ? `${projection.lineHeight}px` : "";
|
|
@@ -1074,8 +1140,12 @@ var Scene = (_class2 = class _Scene {
|
|
|
1074
1140
|
el.style.cursor = selectable ? "text" : "";
|
|
1075
1141
|
}
|
|
1076
1142
|
const { a, b, c, d, e, f } = node.getWorldTransform();
|
|
1077
|
-
|
|
1078
|
-
|
|
1143
|
+
const contentX = _nullishCoalesce(projection.contentX, () => ( 0));
|
|
1144
|
+
const contentY = _nullishCoalesce(projection.contentY, () => ( 0));
|
|
1145
|
+
const baselineOffset = lines && lines.length > 0 ? 0 : projection.baseline === void 0 ? 0 : projection.baseline - _chunkDFNK6OV6js.cssLineBoxBaseline.call(void 0, font, _nullishCoalesce(projection.lineHeight, () => ( 16)));
|
|
1146
|
+
const localY = contentY + baselineOffset;
|
|
1147
|
+
el.style.left = `${e + a * contentX + c * localY}px`;
|
|
1148
|
+
el.style.top = `${f + b * contentX + d * localY}px`;
|
|
1079
1149
|
if (node.width > 0) el.style.width = `${node.width}px`;
|
|
1080
1150
|
if (node.height > 0) el.style.height = `${node.height}px`;
|
|
1081
1151
|
el.style.transform = `matrix(${a}, ${b}, ${c}, ${d}, 0, 0)`;
|
|
@@ -1833,10 +1903,10 @@ var Scene = (_class2 = class _Scene {
|
|
|
1833
1903
|
// src/components/TextEntity.ts
|
|
1834
1904
|
var sharedMeasurer;
|
|
1835
1905
|
function defaultMeasurer() {
|
|
1836
|
-
if (sharedMeasurer === void 0) sharedMeasurer =
|
|
1906
|
+
if (sharedMeasurer === void 0) sharedMeasurer = _chunkZBKKRYDHjs.createCanvasMeasurer.call(void 0, "sans-serif");
|
|
1837
1907
|
return sharedMeasurer;
|
|
1838
1908
|
}
|
|
1839
|
-
var TextEntity = (_class3 = class extends
|
|
1909
|
+
var TextEntity = (_class3 = class extends _chunkDFNK6OV6js.Entity {
|
|
1840
1910
|
|
|
1841
1911
|
|
|
1842
1912
|
|
|
@@ -1853,7 +1923,7 @@ var TextEntity = (_class3 = class extends _chunkNHNOKBD4js.Entity {
|
|
|
1853
1923
|
this.text = text;
|
|
1854
1924
|
this.atlas = atlas;
|
|
1855
1925
|
this.fontSize = fontSize;
|
|
1856
|
-
this.layout = new (0,
|
|
1926
|
+
this.layout = new (0, _chunkZBKKRYDHjs.LayoutEngine)(maxWidth, 1e4, defaultMeasurer());
|
|
1857
1927
|
this.prepared = this.layout.prepare(this.text, this.atlas, this.fontSize);
|
|
1858
1928
|
this.applyLayout();
|
|
1859
1929
|
this.interactive = true;
|
|
@@ -1962,7 +2032,7 @@ var TextEntity = (_class3 = class extends _chunkNHNOKBD4js.Entity {
|
|
|
1962
2032
|
}, _class3);
|
|
1963
2033
|
|
|
1964
2034
|
// src/components/GridTextEntity.ts
|
|
1965
|
-
var GridTextEntity = (_class4 = class extends
|
|
2035
|
+
var GridTextEntity = (_class4 = class extends _chunkDFNK6OV6js.Entity {
|
|
1966
2036
|
|
|
1967
2037
|
__init60() {this.fillStyle = "#ffffff"}
|
|
1968
2038
|
__init61() {this.grid = []}
|
|
@@ -2056,7 +2126,7 @@ function distSqToSegment(px, py, x1, y1, x2, y2) {
|
|
|
2056
2126
|
const ey = py - cy;
|
|
2057
2127
|
return ex * ex + ey * ey;
|
|
2058
2128
|
}
|
|
2059
|
-
var SplineEntity = (_class5 = class extends
|
|
2129
|
+
var SplineEntity = (_class5 = class extends _chunkDFNK6OV6js.Entity {
|
|
2060
2130
|
|
|
2061
2131
|
|
|
2062
2132
|
|
|
@@ -2425,7 +2495,7 @@ var SpatialHashGrid = (_class6 = class {
|
|
|
2425
2495
|
}, _class6);
|
|
2426
2496
|
|
|
2427
2497
|
// src/tree/DOMPortalEntity.ts
|
|
2428
|
-
var DOMPortalEntity = (_class7 = class extends
|
|
2498
|
+
var DOMPortalEntity = (_class7 = class extends _chunkDFNK6OV6js.Entity {
|
|
2429
2499
|
|
|
2430
2500
|
__init72() {this.isDOMPortal = true}
|
|
2431
2501
|
__init73() {this.domListeners = []}
|
|
@@ -2457,10 +2527,17 @@ var DOMPortalEntity = (_class7 = class extends _chunkNHNOKBD4js.Entity {
|
|
|
2457
2527
|
});
|
|
2458
2528
|
this.resizeObserver.observe(this.domElement);
|
|
2459
2529
|
}
|
|
2460
|
-
const events = [
|
|
2530
|
+
const events = [
|
|
2531
|
+
"click",
|
|
2532
|
+
"pointerdown",
|
|
2533
|
+
"pointerup",
|
|
2534
|
+
"pointercancel",
|
|
2535
|
+
"pointermove",
|
|
2536
|
+
"wheel"
|
|
2537
|
+
];
|
|
2461
2538
|
for (const type of events) {
|
|
2462
2539
|
const handler = (e) => {
|
|
2463
|
-
this.dispatchEvent(new (0,
|
|
2540
|
+
this.dispatchEvent(new (0, _chunkDFNK6OV6js.VectoJSEvent)(type, this, e));
|
|
2464
2541
|
};
|
|
2465
2542
|
this.domElement.addEventListener(type, handler);
|
|
2466
2543
|
this.domListeners.push({ type, handler, capture: false });
|
|
@@ -2471,7 +2548,7 @@ var DOMPortalEntity = (_class7 = class extends _chunkNHNOKBD4js.Entity {
|
|
|
2471
2548
|
];
|
|
2472
2549
|
for (const { native, vecto } of hoverEvents) {
|
|
2473
2550
|
const handler = (e) => {
|
|
2474
|
-
this.dispatchEvent(new (0,
|
|
2551
|
+
this.dispatchEvent(new (0, _chunkDFNK6OV6js.VectoJSEvent)(vecto, this, e, false));
|
|
2475
2552
|
};
|
|
2476
2553
|
this.domElement.addEventListener(native, handler);
|
|
2477
2554
|
this.domListeners.push({ type: native, handler, capture: false });
|
|
@@ -2479,7 +2556,7 @@ var DOMPortalEntity = (_class7 = class extends _chunkNHNOKBD4js.Entity {
|
|
|
2479
2556
|
const focusEvents = ["focus", "blur"];
|
|
2480
2557
|
for (const type of focusEvents) {
|
|
2481
2558
|
const handler = (e) => {
|
|
2482
|
-
this.dispatchEvent(new (0,
|
|
2559
|
+
this.dispatchEvent(new (0, _chunkDFNK6OV6js.VectoJSEvent)(type, this, e, true));
|
|
2483
2560
|
};
|
|
2484
2561
|
this.domElement.addEventListener(type, handler, true);
|
|
2485
2562
|
this.domListeners.push({ type, handler, capture: true });
|
|
@@ -2564,4 +2641,6 @@ Scene.registerWebGPUParticleSystemManager(_chunkBPMNCGU7js.WebGPUParticleSystemM
|
|
|
2564
2641
|
|
|
2565
2642
|
|
|
2566
2643
|
|
|
2567
|
-
|
|
2644
|
+
|
|
2645
|
+
|
|
2646
|
+
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);
|
|
@@ -813,15 +816,29 @@ var Scene = class _Scene {
|
|
|
813
816
|
node.dispatchEvent(new VectoJSEvent("pointerleave", node, e, false));
|
|
814
817
|
});
|
|
815
818
|
const capEl = el;
|
|
819
|
+
const releasePointer = (event) => {
|
|
820
|
+
if (typeof capEl.releasePointerCapture !== "function") return;
|
|
821
|
+
if (typeof capEl.hasPointerCapture === "function" && !capEl.hasPointerCapture(event.pointerId)) {
|
|
822
|
+
return;
|
|
823
|
+
}
|
|
824
|
+
try {
|
|
825
|
+
capEl.releasePointerCapture(event.pointerId);
|
|
826
|
+
} catch (error) {
|
|
827
|
+
if (!(error instanceof DOMException) || error.name !== "NotFoundError") throw error;
|
|
828
|
+
}
|
|
829
|
+
};
|
|
816
830
|
el.addEventListener("pointerdown", (e) => {
|
|
817
831
|
if (typeof capEl.setPointerCapture === "function") capEl.setPointerCapture(e.pointerId);
|
|
818
832
|
node.dispatchEvent(new VectoJSEvent("pointerdown", node, e));
|
|
819
833
|
});
|
|
820
834
|
el.addEventListener("pointerup", (e) => {
|
|
821
|
-
|
|
822
|
-
capEl.releasePointerCapture(e.pointerId);
|
|
835
|
+
releasePointer(e);
|
|
823
836
|
node.dispatchEvent(new VectoJSEvent("pointerup", node, e));
|
|
824
837
|
});
|
|
838
|
+
el.addEventListener("pointercancel", (e) => {
|
|
839
|
+
releasePointer(e);
|
|
840
|
+
node.dispatchEvent(new VectoJSEvent("pointercancel", node, e));
|
|
841
|
+
});
|
|
825
842
|
el.addEventListener(
|
|
826
843
|
"pointermove",
|
|
827
844
|
(e) => node.dispatchEvent(new VectoJSEvent("pointermove", node, e))
|
|
@@ -993,6 +1010,16 @@ var Scene = class _Scene {
|
|
|
993
1010
|
el.setAttribute("aria-valuenow", attrs.value);
|
|
994
1011
|
}
|
|
995
1012
|
}
|
|
1013
|
+
if (attrs.textInputStyle !== void 0 && (el instanceof HTMLInputElement || el instanceof HTMLTextAreaElement)) {
|
|
1014
|
+
const textStyle = attrs.textInputStyle;
|
|
1015
|
+
if (el.style.font !== textStyle.font) el.style.font = textStyle.font;
|
|
1016
|
+
const lineHeight = `${textStyle.lineHeight}px`;
|
|
1017
|
+
if (el.style.lineHeight !== lineHeight) el.style.lineHeight = lineHeight;
|
|
1018
|
+
const padding = `${textStyle.padding}px`;
|
|
1019
|
+
if (el.style.padding !== padding) el.style.padding = padding;
|
|
1020
|
+
if (el.style.boxSizing !== "border-box") el.style.boxSizing = "border-box";
|
|
1021
|
+
if (el instanceof HTMLTextAreaElement) el.style.resize = "none";
|
|
1022
|
+
}
|
|
996
1023
|
if (node.a11yFullViewport) {
|
|
997
1024
|
el.style.left = "0px";
|
|
998
1025
|
el.style.top = "0px";
|
|
@@ -1056,7 +1083,46 @@ var Scene = class _Scene {
|
|
|
1056
1083
|
this.contentElements.set(node.id, el);
|
|
1057
1084
|
this.a11yNeedsReorder = true;
|
|
1058
1085
|
}
|
|
1059
|
-
|
|
1086
|
+
const lines = projection.lines;
|
|
1087
|
+
if (lines && lines.length > 0) {
|
|
1088
|
+
const signature = JSON.stringify({
|
|
1089
|
+
lines,
|
|
1090
|
+
fallbackFont: projection.font ?? "",
|
|
1091
|
+
fallbackLineHeight: projection.lineHeight ?? 16
|
|
1092
|
+
});
|
|
1093
|
+
if (el.dataset.vectoProjectionLines !== signature) {
|
|
1094
|
+
el.replaceChildren();
|
|
1095
|
+
for (let index = 0; index < lines.length; index++) {
|
|
1096
|
+
const line = lines[index];
|
|
1097
|
+
const lineElement = document.createElement("span");
|
|
1098
|
+
const lineFont = line.font ?? projection.font ?? "";
|
|
1099
|
+
const lineHeight2 = line.lineHeight ?? projection.lineHeight ?? 16;
|
|
1100
|
+
lineElement.style.position = "absolute";
|
|
1101
|
+
lineElement.style.left = `${line.x}px`;
|
|
1102
|
+
lineElement.style.top = `${line.y + line.baseline - cssLineBoxBaseline(lineFont, lineHeight2)}px`;
|
|
1103
|
+
lineElement.style.whiteSpace = "pre";
|
|
1104
|
+
if (lineFont) lineElement.style.font = lineFont;
|
|
1105
|
+
lineElement.style.lineHeight = `${lineHeight2}px`;
|
|
1106
|
+
if (line.runs && line.runs.length > 0) {
|
|
1107
|
+
for (const run of line.runs) {
|
|
1108
|
+
const runElement = document.createElement("span");
|
|
1109
|
+
runElement.textContent = run.text;
|
|
1110
|
+
if (run.font) runElement.style.font = run.font;
|
|
1111
|
+
runElement.style.lineHeight = `${lineHeight2}px`;
|
|
1112
|
+
lineElement.appendChild(runElement);
|
|
1113
|
+
}
|
|
1114
|
+
} else {
|
|
1115
|
+
lineElement.textContent = line.text;
|
|
1116
|
+
}
|
|
1117
|
+
el.appendChild(lineElement);
|
|
1118
|
+
if (index < lines.length - 1) el.appendChild(document.createTextNode("\n"));
|
|
1119
|
+
}
|
|
1120
|
+
el.dataset.vectoProjectionLines = signature;
|
|
1121
|
+
}
|
|
1122
|
+
} else {
|
|
1123
|
+
if (el.textContent !== projection.text) el.textContent = projection.text;
|
|
1124
|
+
delete el.dataset.vectoProjectionLines;
|
|
1125
|
+
}
|
|
1060
1126
|
const font = projection.font ?? "";
|
|
1061
1127
|
if (el.style.font !== font) el.style.font = font;
|
|
1062
1128
|
const lineHeight = projection.lineHeight !== void 0 ? `${projection.lineHeight}px` : "";
|
|
@@ -1074,8 +1140,12 @@ var Scene = class _Scene {
|
|
|
1074
1140
|
el.style.cursor = selectable ? "text" : "";
|
|
1075
1141
|
}
|
|
1076
1142
|
const { a, b, c, d, e, f } = node.getWorldTransform();
|
|
1077
|
-
|
|
1078
|
-
|
|
1143
|
+
const contentX = projection.contentX ?? 0;
|
|
1144
|
+
const contentY = projection.contentY ?? 0;
|
|
1145
|
+
const baselineOffset = lines && lines.length > 0 ? 0 : projection.baseline === void 0 ? 0 : projection.baseline - cssLineBoxBaseline(font, projection.lineHeight ?? 16);
|
|
1146
|
+
const localY = contentY + baselineOffset;
|
|
1147
|
+
el.style.left = `${e + a * contentX + c * localY}px`;
|
|
1148
|
+
el.style.top = `${f + b * contentX + d * localY}px`;
|
|
1079
1149
|
if (node.width > 0) el.style.width = `${node.width}px`;
|
|
1080
1150
|
if (node.height > 0) el.style.height = `${node.height}px`;
|
|
1081
1151
|
el.style.transform = `matrix(${a}, ${b}, ${c}, ${d}, 0, 0)`;
|
|
@@ -2457,7 +2527,14 @@ var DOMPortalEntity = class extends Entity {
|
|
|
2457
2527
|
});
|
|
2458
2528
|
this.resizeObserver.observe(this.domElement);
|
|
2459
2529
|
}
|
|
2460
|
-
const events = [
|
|
2530
|
+
const events = [
|
|
2531
|
+
"click",
|
|
2532
|
+
"pointerdown",
|
|
2533
|
+
"pointerup",
|
|
2534
|
+
"pointercancel",
|
|
2535
|
+
"pointermove",
|
|
2536
|
+
"wheel"
|
|
2537
|
+
];
|
|
2461
2538
|
for (const type of events) {
|
|
2462
2539
|
const handler = (e) => {
|
|
2463
2540
|
this.dispatchEvent(new VectoJSEvent(type, this, e));
|
|
@@ -2555,9 +2632,11 @@ export {
|
|
|
2555
2632
|
TweenDriver,
|
|
2556
2633
|
VectoJSEvent,
|
|
2557
2634
|
WebGPUParticleSystemManager,
|
|
2635
|
+
clearCssLineBoxMetrics,
|
|
2558
2636
|
computeLineSegments,
|
|
2559
2637
|
createCanvasMeasurer,
|
|
2560
2638
|
createWebGLPointRenderer,
|
|
2639
|
+
cssLineBoxBaseline,
|
|
2561
2640
|
isSafeUrl,
|
|
2562
2641
|
isTweenConfig,
|
|
2563
2642
|
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,11 +156,13 @@ 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}.
|
|
120
164
|
*/
|
|
121
|
-
export type VectoEvent = 'click' | 'hover' | 'pointerdown' | 'pointerup' | 'pointermove' | 'pointerleave' | 'change' | 'focus' | 'blur' | 'wheel' | 'keydown' | 'keyup';
|
|
165
|
+
export type VectoEvent = 'click' | 'hover' | 'pointerdown' | 'pointerup' | 'pointercancel' | 'pointermove' | 'pointerleave' | 'change' | 'focus' | 'blur' | 'wheel' | 'keydown' | 'keyup';
|
|
122
166
|
/** Options for {@link Entity.on} / {@link Entity.off}. */
|
|
123
167
|
export interface ListenerOptions {
|
|
124
168
|
/** Register the listener for the capture phase (root→target) instead of bubble. */
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vectojs/core",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.6.1",
|
|
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": {
|