@vectojs/core 1.10.0 → 1.11.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/dist/{chunk-GKLTTGBR.js → chunk-2Z23LTH3.js} +20 -1
- package/dist/{chunk-J2P6QZJV.mjs → chunk-XIEQHSBB.mjs} +19 -0
- package/dist/index.js +213 -122
- package/dist/index.mjs +94 -3
- package/dist/text.js +2 -2
- package/dist/text.mjs +1 -1
- package/dist/tree/Entity.d.ts +10 -1
- package/dist/tree/Scene.d.ts +15 -0
- package/package.json +1 -1
|
@@ -710,6 +710,25 @@ var Entity = (_class4 = class {
|
|
|
710
710
|
handlers.forEach((h) => h(payload));
|
|
711
711
|
}
|
|
712
712
|
}
|
|
713
|
+
/**
|
|
714
|
+
* Programmatically focus the entity's projected a11y shadow element, if one
|
|
715
|
+
* exists. After `scene.add(entity)` the shadow element is typically created
|
|
716
|
+
* on the next a11y sync (within one animation frame), so this method retries
|
|
717
|
+
* once on the next rAF if the element isn't immediately available — matching
|
|
718
|
+
* the timing pattern the prior workaround described in findings.md achieved
|
|
719
|
+
* with `requestAnimationFrame(() => document.getElementById(id)?.focus())`.
|
|
720
|
+
*/
|
|
721
|
+
focus() {
|
|
722
|
+
const el = _optionalChain([this, 'access', _57 => _57.scene, 'optionalAccess', _58 => _58.getA11yElement, 'call', _59 => _59(this.id)]);
|
|
723
|
+
if (el) {
|
|
724
|
+
el.focus();
|
|
725
|
+
return;
|
|
726
|
+
}
|
|
727
|
+
requestAnimationFrame(() => {
|
|
728
|
+
const retry = _optionalChain([this, 'access', _60 => _60.scene, 'optionalAccess', _61 => _61.getA11yElement, 'call', _62 => _62(this.id)]);
|
|
729
|
+
if (retry) retry.focus();
|
|
730
|
+
});
|
|
731
|
+
}
|
|
713
732
|
/** Run one node's listeners for the event, honoring stopImmediatePropagation. */
|
|
714
733
|
fireListeners(node, map, event) {
|
|
715
734
|
const handlers = map.get(event.type);
|
|
@@ -1141,7 +1160,7 @@ var MSDFTextEntity = (_class6 = class extends Entity {
|
|
|
1141
1160
|
if (res.seqId < this.lastRenderedSeqId) return;
|
|
1142
1161
|
this.lastRenderedSeqId = res.seqId;
|
|
1143
1162
|
this.layoutResult = res;
|
|
1144
|
-
_optionalChain([this, 'access',
|
|
1163
|
+
_optionalChain([this, 'access', _63 => _63.scene, 'optionalAccess', _64 => _64.markDirty, 'call', _65 => _65()]);
|
|
1145
1164
|
}
|
|
1146
1165
|
});
|
|
1147
1166
|
}
|
|
@@ -710,6 +710,25 @@ var Entity = class {
|
|
|
710
710
|
handlers.forEach((h) => h(payload));
|
|
711
711
|
}
|
|
712
712
|
}
|
|
713
|
+
/**
|
|
714
|
+
* Programmatically focus the entity's projected a11y shadow element, if one
|
|
715
|
+
* exists. After `scene.add(entity)` the shadow element is typically created
|
|
716
|
+
* on the next a11y sync (within one animation frame), so this method retries
|
|
717
|
+
* once on the next rAF if the element isn't immediately available — matching
|
|
718
|
+
* the timing pattern the prior workaround described in findings.md achieved
|
|
719
|
+
* with `requestAnimationFrame(() => document.getElementById(id)?.focus())`.
|
|
720
|
+
*/
|
|
721
|
+
focus() {
|
|
722
|
+
const el = this.scene?.getA11yElement(this.id);
|
|
723
|
+
if (el) {
|
|
724
|
+
el.focus();
|
|
725
|
+
return;
|
|
726
|
+
}
|
|
727
|
+
requestAnimationFrame(() => {
|
|
728
|
+
const retry = this.scene?.getA11yElement(this.id);
|
|
729
|
+
if (retry) retry.focus();
|
|
730
|
+
});
|
|
731
|
+
}
|
|
713
732
|
/** Run one node's listeners for the event, honoring stopImmediatePropagation. */
|
|
714
733
|
fireListeners(node, map, event) {
|
|
715
734
|
const handlers = map.get(event.type);
|
package/dist/index.js
CHANGED
|
@@ -27,7 +27,7 @@ var _chunkORCPCIJ7js = require('./chunk-ORCPCIJ7.js');
|
|
|
27
27
|
|
|
28
28
|
|
|
29
29
|
|
|
30
|
-
var
|
|
30
|
+
var _chunk2Z23LTH3js = require('./chunk-2Z23LTH3.js');
|
|
31
31
|
|
|
32
32
|
|
|
33
33
|
|
|
@@ -44,7 +44,7 @@ var PARTICLE_OFFSET_ORIGIN_X = 4;
|
|
|
44
44
|
var PARTICLE_OFFSET_ORIGIN_Y = 5;
|
|
45
45
|
var PARTICLE_OFFSET_SIZE = 6;
|
|
46
46
|
var PARTICLE_OFFSET_LIFE = 7;
|
|
47
|
-
var ComputeParticleEntity = (_class = class extends
|
|
47
|
+
var ComputeParticleEntity = (_class = class extends _chunk2Z23LTH3js.Entity {
|
|
48
48
|
|
|
49
49
|
|
|
50
50
|
|
|
@@ -701,48 +701,116 @@ var Scene = (_class2 = class _Scene {
|
|
|
701
701
|
__init39() {this.activePortalsPrevFrame = /* @__PURE__ */ new Set()}
|
|
702
702
|
__init40() {this.portalEntities = /* @__PURE__ */ new Map()}
|
|
703
703
|
__init41() {this.renderOrderCounter = 0}
|
|
704
|
+
/**
|
|
705
|
+
* Authoritative paint order for semantic nodes discovered during the main
|
|
706
|
+
* render. A node may not have a DOM projection until the following a11y
|
|
707
|
+
* sync, so retaining the order prevents a newly opened overlay from spending
|
|
708
|
+
* its first frame below previously projected controls.
|
|
709
|
+
*/
|
|
710
|
+
__init42() {this.a11yRenderOrders = /* @__PURE__ */ new Map()}
|
|
704
711
|
// Optional WebGL point-cloud layer (see SceneOptions.pointBackend).
|
|
705
|
-
|
|
706
|
-
|
|
712
|
+
__init43() {this.pointRenderer = null}
|
|
713
|
+
__init44() {this.glCanvas = null}
|
|
707
714
|
|
|
708
715
|
|
|
709
716
|
|
|
710
|
-
|
|
717
|
+
__init45() {this.disableWindowResize = false}
|
|
711
718
|
/** See {@link SceneOptions.maxDPR}. `undefined` = uncapped (real DPR). */
|
|
712
719
|
|
|
713
720
|
// WebGPU properties
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
721
|
+
__init46() {this.destroyed = false}
|
|
722
|
+
__init47() {this.device = null}
|
|
723
|
+
__init48() {this.deviceLost = false}
|
|
724
|
+
__init49() {this.particleBackend = "auto"}
|
|
725
|
+
__init50() {this._webgpuDisabled = false}
|
|
719
726
|
get webgpuDisabled() {
|
|
720
727
|
return this._webgpuDisabled || this.particleBackend === "cpu";
|
|
721
728
|
}
|
|
722
729
|
set webgpuDisabled(value) {
|
|
723
730
|
this._webgpuDisabled = value;
|
|
724
731
|
}
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
732
|
+
__init51() {this.recoveryTimerId = null}
|
|
733
|
+
__init52() {this.manager = null}
|
|
734
|
+
__init53() {this.initializingWebGPU = false}
|
|
735
|
+
__init54() {this.gpuCanvas = null}
|
|
736
|
+
__init55() {this.gpuContext = null}
|
|
730
737
|
/** True while the GPU canvas holds a presented particle frame (needs clearing when they leave). */
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
738
|
+
__init56() {this.gpuHasContent = false}
|
|
739
|
+
__init57() {this.mouseX = -9999}
|
|
740
|
+
__init58() {this.mouseY = -9999}
|
|
741
|
+
__init59() {this.pointerMoveListener = null}
|
|
742
|
+
__init60() {this.pointerLeaveListener = null}
|
|
743
|
+
__init61() {this.hasWarnedZeroSize = false}
|
|
744
|
+
__init62() {this.fontLoadHandler = null}
|
|
745
|
+
// ── Dev-mode warning infrastructure ──────────────────────────────
|
|
746
|
+
//
|
|
747
|
+
// Enable with `Scene.devMode = true` or by setting `globalThis.__DEV__`.
|
|
748
|
+
// Auto-detected when `NODE_ENV === 'development'`.
|
|
749
|
+
//
|
|
750
|
+
// Checks run once every ~120 frames (~2s at 60fps) to keep overhead
|
|
751
|
+
// negligible even when dev mode is on.
|
|
752
|
+
/** Toggle development-mode runtime warnings globally. */
|
|
753
|
+
static __initStatic3() {this.devMode = false}
|
|
754
|
+
static _devModeDetected() {
|
|
755
|
+
if (_Scene.devMode) return true;
|
|
756
|
+
const gp = typeof globalThis !== "undefined" ? globalThis : void 0;
|
|
757
|
+
if (_optionalChain([gp, 'optionalAccess', _23 => _23.__DEV__])) return true;
|
|
758
|
+
if (_optionalChain([gp, 'optionalAccess', _24 => _24.process, 'optionalAccess', _25 => _25.env, 'optionalAccess', _26 => _26.NODE_ENV]) === "development") return true;
|
|
759
|
+
return false;
|
|
760
|
+
}
|
|
761
|
+
|
|
762
|
+
__init63() {this._devFrameCount = 0}
|
|
763
|
+
_devWarn(message) {
|
|
764
|
+
if (!this._devActive) return;
|
|
765
|
+
console.warn(`[vectojs/dev] ${message}`);
|
|
766
|
+
}
|
|
767
|
+
/** @internal Periodic dev checks — called once per frame in dev mode. */
|
|
768
|
+
_devRunChecks() {
|
|
769
|
+
this._devFrameCount++;
|
|
770
|
+
if (this._devFrameCount % 120 !== 0) return;
|
|
771
|
+
if (this.a11yElements) {
|
|
772
|
+
let interactiveCount = 0;
|
|
773
|
+
const walk = (node) => {
|
|
774
|
+
if (node.interactive && node.width > 0) interactiveCount++;
|
|
775
|
+
for (const c of node.children) walk(c);
|
|
776
|
+
};
|
|
777
|
+
walk(this.root);
|
|
778
|
+
for (const c of this.overlayRoot.children) walk(c);
|
|
779
|
+
const shadowCount = this.a11yElements.size;
|
|
780
|
+
if (shadowCount > interactiveCount + 2) {
|
|
781
|
+
this._devWarn(
|
|
782
|
+
`a11yElements (${shadowCount}) exceeds interactive entities (${interactiveCount}). Call scene.detachA11y(entity) before removing interactive children from the tree, or their shadow nodes leak.`
|
|
783
|
+
);
|
|
784
|
+
}
|
|
785
|
+
}
|
|
786
|
+
let checked = 0;
|
|
787
|
+
const walkProjections = (node) => {
|
|
788
|
+
if (checked > 10) return;
|
|
789
|
+
const proj = _optionalChain([node, 'access', _27 => _27.getContentProjection, 'optionalCall', _28 => _28()]);
|
|
790
|
+
if (_optionalChain([proj, 'optionalAccess', _29 => _29.text]) && proj.selectable !== false) {
|
|
791
|
+
const el = _optionalChain([this, 'access', _30 => _30.contentElements, 'optionalAccess', _31 => _31.get, 'call', _32 => _32(node.id)]);
|
|
792
|
+
if (el) {
|
|
793
|
+
const projectedText = el.textContent || "";
|
|
794
|
+
if (projectedText !== "" && projectedText !== proj.text) {
|
|
795
|
+
this._devWarn(
|
|
796
|
+
`Content projection mismatch for entity "${node.id}": projection says "${proj.text.slice(0, 60)}" but DOM shows "${projectedText.slice(0, 60)}". Ensure getContentProjection() output matches what drawSelf renders.`
|
|
797
|
+
);
|
|
798
|
+
}
|
|
799
|
+
}
|
|
800
|
+
}
|
|
801
|
+
checked++;
|
|
802
|
+
for (const c of node.children) walkProjections(c);
|
|
803
|
+
};
|
|
804
|
+
walkProjections(this.root);
|
|
805
|
+
}
|
|
806
|
+
constructor(canvas, options = {}) {;_class2.prototype.__init7.call(this);_class2.prototype.__init8.call(this);_class2.prototype.__init9.call(this);_class2.prototype.__init10.call(this);_class2.prototype.__init11.call(this);_class2.prototype.__init12.call(this);_class2.prototype.__init13.call(this);_class2.prototype.__init14.call(this);_class2.prototype.__init15.call(this);_class2.prototype.__init16.call(this);_class2.prototype.__init17.call(this);_class2.prototype.__init18.call(this);_class2.prototype.__init19.call(this);_class2.prototype.__init20.call(this);_class2.prototype.__init21.call(this);_class2.prototype.__init22.call(this);_class2.prototype.__init23.call(this);_class2.prototype.__init24.call(this);_class2.prototype.__init25.call(this);_class2.prototype.__init26.call(this);_class2.prototype.__init27.call(this);_class2.prototype.__init28.call(this);_class2.prototype.__init29.call(this);_class2.prototype.__init30.call(this);_class2.prototype.__init31.call(this);_class2.prototype.__init32.call(this);_class2.prototype.__init33.call(this);_class2.prototype.__init34.call(this);_class2.prototype.__init35.call(this);_class2.prototype.__init36.call(this);_class2.prototype.__init37.call(this);_class2.prototype.__init38.call(this);_class2.prototype.__init39.call(this);_class2.prototype.__init40.call(this);_class2.prototype.__init41.call(this);_class2.prototype.__init42.call(this);_class2.prototype.__init43.call(this);_class2.prototype.__init44.call(this);_class2.prototype.__init45.call(this);_class2.prototype.__init46.call(this);_class2.prototype.__init47.call(this);_class2.prototype.__init48.call(this);_class2.prototype.__init49.call(this);_class2.prototype.__init50.call(this);_class2.prototype.__init51.call(this);_class2.prototype.__init52.call(this);_class2.prototype.__init53.call(this);_class2.prototype.__init54.call(this);_class2.prototype.__init55.call(this);_class2.prototype.__init56.call(this);_class2.prototype.__init57.call(this);_class2.prototype.__init58.call(this);_class2.prototype.__init59.call(this);_class2.prototype.__init60.call(this);_class2.prototype.__init61.call(this);_class2.prototype.__init62.call(this);_class2.prototype.__init63.call(this);
|
|
739
807
|
this.canvas = canvas;
|
|
740
808
|
this.debugA11y = _nullishCoalesce(options.debugA11y, () => ( false));
|
|
741
809
|
this.disableWindowResize = _nullishCoalesce(options.disableWindowResize, () => ( false));
|
|
742
810
|
this.maxDPR = options.maxDPR;
|
|
743
811
|
if (this.disableWindowResize) {
|
|
744
|
-
const styleWidth = parseInlinePx(_optionalChain([canvas, 'access',
|
|
745
|
-
const styleHeight = parseInlinePx(_optionalChain([canvas, 'access',
|
|
812
|
+
const styleWidth = parseInlinePx(_optionalChain([canvas, 'access', _33 => _33.style, 'optionalAccess', _34 => _34.width]));
|
|
813
|
+
const styleHeight = parseInlinePx(_optionalChain([canvas, 'access', _35 => _35.style, 'optionalAccess', _36 => _36.height]));
|
|
746
814
|
this.width = _nullishCoalesce(styleWidth, () => ( (canvas.width || canvas.clientWidth || 0)));
|
|
747
815
|
this.height = _nullishCoalesce(styleHeight, () => ( (canvas.height || canvas.clientHeight || 0)));
|
|
748
816
|
} else {
|
|
@@ -750,15 +818,16 @@ var Scene = (_class2 = class _Scene {
|
|
|
750
818
|
this.height = typeof window !== "undefined" ? window.innerHeight : canvas.clientHeight || canvas.height || 600;
|
|
751
819
|
}
|
|
752
820
|
const globalProcess = typeof globalThis !== "undefined" ? globalThis.process : void 0;
|
|
753
|
-
const isTest = globalProcess && (_optionalChain([globalProcess, 'access',
|
|
821
|
+
const isTest = globalProcess && (_optionalChain([globalProcess, 'access', _37 => _37.env, 'optionalAccess', _38 => _38.NODE_ENV]) === "test" || _optionalChain([globalProcess, 'access', _39 => _39.env, 'optionalAccess', _40 => _40.VITEST]) === "true");
|
|
754
822
|
this.maxFPS = _nullishCoalesce(options.maxFPS, () => ( (isTest ? 0 : 60)));
|
|
755
823
|
this.respectReducedMotion = _nullishCoalesce(options.respectReducedMotion, () => ( true));
|
|
756
824
|
this.autoThrottle = _nullishCoalesce(options.autoThrottle, () => ( true));
|
|
757
825
|
this.particleBackend = _nullishCoalesce(options.particleBackend, () => ( "auto"));
|
|
758
826
|
this.a11ySyncInterval = _nullishCoalesce(options.a11ySyncInterval, () => ( 0));
|
|
759
827
|
this.contentProjectionEnabled = _nullishCoalesce(options.contentProjection, () => ( true));
|
|
828
|
+
this._devActive = _Scene._devModeDetected();
|
|
760
829
|
this.reducedMotionQuery = typeof window !== "undefined" && typeof window.matchMedia === "function" ? window.matchMedia("(prefers-reduced-motion: reduce)") : null;
|
|
761
|
-
this.root = new class RootEntity extends
|
|
830
|
+
this.root = new class RootEntity extends _chunk2Z23LTH3js.Entity {
|
|
762
831
|
isPointInside() {
|
|
763
832
|
return false;
|
|
764
833
|
}
|
|
@@ -767,7 +836,7 @@ var Scene = (_class2 = class _Scene {
|
|
|
767
836
|
}
|
|
768
837
|
}("root");
|
|
769
838
|
this.root._scene = this;
|
|
770
|
-
this.overlayRoot = new class OverlayRoot extends
|
|
839
|
+
this.overlayRoot = new class OverlayRoot extends _chunk2Z23LTH3js.Entity {
|
|
771
840
|
isPointInside() {
|
|
772
841
|
return false;
|
|
773
842
|
}
|
|
@@ -920,7 +989,7 @@ var Scene = (_class2 = class _Scene {
|
|
|
920
989
|
};
|
|
921
990
|
if (typeof document !== "undefined" && document.fonts) {
|
|
922
991
|
this.fontLoadHandler = () => {
|
|
923
|
-
|
|
992
|
+
_chunk2Z23LTH3js.clearCssLineBoxMetrics.call(void 0, );
|
|
924
993
|
this.contentFontEpoch++;
|
|
925
994
|
this.markDirty();
|
|
926
995
|
};
|
|
@@ -936,10 +1005,10 @@ var Scene = (_class2 = class _Scene {
|
|
|
936
1005
|
}
|
|
937
1006
|
releaseContentSelectionForRebuild(el) {
|
|
938
1007
|
const selection = typeof window !== "undefined" && typeof window.getSelection === "function" ? window.getSelection() : null;
|
|
939
|
-
const ownsSelection = this.contentSelectionAnchor && el.contains(this.contentSelectionAnchor.node) || (_optionalChain([selection, 'optionalAccess',
|
|
1008
|
+
const ownsSelection = this.contentSelectionAnchor && el.contains(this.contentSelectionAnchor.node) || (_optionalChain([selection, 'optionalAccess', _41 => _41.anchorNode]) ? el.contains(selection.anchorNode) : false) || (_optionalChain([selection, 'optionalAccess', _42 => _42.focusNode]) ? el.contains(selection.focusNode) : false);
|
|
940
1009
|
if (!ownsSelection) return;
|
|
941
1010
|
this.endContentSelectionDrag();
|
|
942
|
-
_optionalChain([selection, 'optionalAccess',
|
|
1011
|
+
_optionalChain([selection, 'optionalAccess', _43 => _43.removeAllRanges, 'call', _44 => _44()]);
|
|
943
1012
|
}
|
|
944
1013
|
/**
|
|
945
1014
|
* Expose the underlying {@link IRenderer} for advanced direct-draw operations.
|
|
@@ -951,7 +1020,7 @@ var Scene = (_class2 = class _Scene {
|
|
|
951
1020
|
}
|
|
952
1021
|
/** Convert browser viewport coordinates into this Scene's logical coordinates. */
|
|
953
1022
|
clientToScene(clientX, clientY) {
|
|
954
|
-
const rect = _optionalChain([this, 'access',
|
|
1023
|
+
const rect = _optionalChain([this, 'access', _45 => _45.canvas, 'access', _46 => _46.getBoundingClientRect, 'optionalCall', _47 => _47()]);
|
|
955
1024
|
if (!rect) return { x: clientX, y: clientY };
|
|
956
1025
|
const cssWidth = rect.width || this.canvas.clientWidth || this.width;
|
|
957
1026
|
const cssHeight = rect.height || this.canvas.clientHeight || this.height;
|
|
@@ -977,7 +1046,7 @@ var Scene = (_class2 = class _Scene {
|
|
|
977
1046
|
cancelAnimationFrame(calibrationFrame);
|
|
978
1047
|
}
|
|
979
1048
|
this.contentGridCalibrationFrames.delete(entityId);
|
|
980
|
-
_optionalChain([this, 'access',
|
|
1049
|
+
_optionalChain([this, 'access', _48 => _48.contentGridCalibrationProbes, 'access', _49 => _49.get, 'call', _50 => _50(entityId), 'optionalAccess', _51 => _51.remove, 'call', _52 => _52()]);
|
|
981
1050
|
this.contentGridCalibrationProbes.delete(entityId);
|
|
982
1051
|
delete el.dataset.vectoGridCalibrationPending;
|
|
983
1052
|
delete el.dataset.vectoGridCalibration;
|
|
@@ -1093,8 +1162,8 @@ var Scene = (_class2 = class _Scene {
|
|
|
1093
1162
|
this.canvas.removeEventListener("pointerleave", this.pointerLeaveListener);
|
|
1094
1163
|
}
|
|
1095
1164
|
}
|
|
1096
|
-
_optionalChain([this, 'access',
|
|
1097
|
-
_optionalChain([this, 'access',
|
|
1165
|
+
_optionalChain([this, 'access', _53 => _53.a11yRoot, 'optionalAccess', _54 => _54.remove, 'call', _55 => _55()]);
|
|
1166
|
+
_optionalChain([this, 'access', _56 => _56.portalRoot, 'optionalAccess', _57 => _57.remove, 'call', _58 => _58()]);
|
|
1098
1167
|
this.a11yElements.clear();
|
|
1099
1168
|
for (const el of this.contentElements.values()) el.remove();
|
|
1100
1169
|
this.contentElements.clear();
|
|
@@ -1107,10 +1176,10 @@ var Scene = (_class2 = class _Scene {
|
|
|
1107
1176
|
for (const probe of this.contentGridCalibrationProbes.values()) probe.remove();
|
|
1108
1177
|
this.contentGridCalibrationProbes.clear();
|
|
1109
1178
|
this.endContentSelectionDrag();
|
|
1110
|
-
_optionalChain([this, 'access',
|
|
1111
|
-
_optionalChain([this, 'access',
|
|
1112
|
-
_optionalChain([this, 'access',
|
|
1113
|
-
_optionalChain([this, 'access',
|
|
1179
|
+
_optionalChain([this, 'access', _59 => _59.pointRenderer, 'optionalAccess', _60 => _60.destroy, 'call', _61 => _61()]);
|
|
1180
|
+
_optionalChain([this, 'access', _62 => _62.renderer, 'access', _63 => _63.dispose, 'optionalCall', _64 => _64()]);
|
|
1181
|
+
_optionalChain([this, 'access', _65 => _65.glCanvas, 'optionalAccess', _66 => _66.remove, 'call', _67 => _67()]);
|
|
1182
|
+
_optionalChain([this, 'access', _68 => _68.gpuCanvas, 'optionalAccess', _69 => _69.remove, 'call', _70 => _70()]);
|
|
1114
1183
|
this.gpuCanvas = null;
|
|
1115
1184
|
this.gpuContext = null;
|
|
1116
1185
|
if (this.recoveryTimerId) {
|
|
@@ -1122,7 +1191,7 @@ var Scene = (_class2 = class _Scene {
|
|
|
1122
1191
|
this.manager = null;
|
|
1123
1192
|
}
|
|
1124
1193
|
if (this.device) {
|
|
1125
|
-
_optionalChain([this, 'access',
|
|
1194
|
+
_optionalChain([this, 'access', _71 => _71.device, 'access', _72 => _72.destroy, 'optionalCall', _73 => _73()]);
|
|
1126
1195
|
this.device = null;
|
|
1127
1196
|
}
|
|
1128
1197
|
}
|
|
@@ -1271,15 +1340,18 @@ var Scene = (_class2 = class _Scene {
|
|
|
1271
1340
|
el.style.background = "transparent";
|
|
1272
1341
|
}
|
|
1273
1342
|
el.addEventListener("click", (e) => {
|
|
1274
|
-
node.dispatchEvent(new (0,
|
|
1343
|
+
node.dispatchEvent(new (0, _chunk2Z23LTH3js.VectoJSEvent)("click", node, e));
|
|
1344
|
+
});
|
|
1345
|
+
el.addEventListener("dblclick", (e) => {
|
|
1346
|
+
node.dispatchEvent(new (0, _chunk2Z23LTH3js.VectoJSEvent)("dblclick", node, e));
|
|
1275
1347
|
});
|
|
1276
1348
|
el.addEventListener("mouseenter", (e) => {
|
|
1277
1349
|
if (this.debugA11y) el.style.backgroundColor = "rgba(56, 189, 248, 0.2)";
|
|
1278
|
-
node.dispatchEvent(new (0,
|
|
1350
|
+
node.dispatchEvent(new (0, _chunk2Z23LTH3js.VectoJSEvent)("hover", node, e, false));
|
|
1279
1351
|
});
|
|
1280
1352
|
el.addEventListener("mouseleave", (e) => {
|
|
1281
1353
|
if (this.debugA11y) el.style.backgroundColor = "rgba(56, 189, 248, 0.05)";
|
|
1282
|
-
node.dispatchEvent(new (0,
|
|
1354
|
+
node.dispatchEvent(new (0, _chunk2Z23LTH3js.VectoJSEvent)("pointerleave", node, e, false));
|
|
1283
1355
|
});
|
|
1284
1356
|
const capEl = el;
|
|
1285
1357
|
const releasePointer = (event) => {
|
|
@@ -1295,32 +1367,32 @@ var Scene = (_class2 = class _Scene {
|
|
|
1295
1367
|
};
|
|
1296
1368
|
el.addEventListener("pointerdown", (e) => {
|
|
1297
1369
|
if (typeof capEl.setPointerCapture === "function") capEl.setPointerCapture(e.pointerId);
|
|
1298
|
-
node.dispatchEvent(new (0,
|
|
1370
|
+
node.dispatchEvent(new (0, _chunk2Z23LTH3js.VectoJSEvent)("pointerdown", node, e));
|
|
1299
1371
|
});
|
|
1300
1372
|
el.addEventListener("pointerup", (e) => {
|
|
1301
1373
|
releasePointer(e);
|
|
1302
|
-
node.dispatchEvent(new (0,
|
|
1374
|
+
node.dispatchEvent(new (0, _chunk2Z23LTH3js.VectoJSEvent)("pointerup", node, e));
|
|
1303
1375
|
});
|
|
1304
1376
|
el.addEventListener("pointercancel", (e) => {
|
|
1305
1377
|
releasePointer(e);
|
|
1306
|
-
node.dispatchEvent(new (0,
|
|
1378
|
+
node.dispatchEvent(new (0, _chunk2Z23LTH3js.VectoJSEvent)("pointercancel", node, e));
|
|
1307
1379
|
});
|
|
1308
1380
|
el.addEventListener(
|
|
1309
1381
|
"pointermove",
|
|
1310
|
-
(e) => node.dispatchEvent(new (0,
|
|
1382
|
+
(e) => node.dispatchEvent(new (0, _chunk2Z23LTH3js.VectoJSEvent)("pointermove", node, e))
|
|
1311
1383
|
);
|
|
1312
1384
|
el.addEventListener(
|
|
1313
1385
|
"wheel",
|
|
1314
1386
|
(e) => {
|
|
1315
|
-
node.dispatchEvent(new (0,
|
|
1387
|
+
node.dispatchEvent(new (0, _chunk2Z23LTH3js.VectoJSEvent)("wheel", node, e));
|
|
1316
1388
|
},
|
|
1317
1389
|
{ passive: false }
|
|
1318
1390
|
);
|
|
1319
1391
|
el.addEventListener("keydown", (e) => {
|
|
1320
|
-
node.dispatchEvent(new (0,
|
|
1392
|
+
node.dispatchEvent(new (0, _chunk2Z23LTH3js.VectoJSEvent)("keydown", node, e));
|
|
1321
1393
|
});
|
|
1322
1394
|
el.addEventListener("keyup", (e) => {
|
|
1323
|
-
node.dispatchEvent(new (0,
|
|
1395
|
+
node.dispatchEvent(new (0, _chunk2Z23LTH3js.VectoJSEvent)("keyup", node, e));
|
|
1324
1396
|
});
|
|
1325
1397
|
if (el instanceof HTMLInputElement || el instanceof HTMLTextAreaElement) {
|
|
1326
1398
|
const input = el;
|
|
@@ -1347,7 +1419,7 @@ var Scene = (_class2 = class _Scene {
|
|
|
1347
1419
|
});
|
|
1348
1420
|
el.addEventListener("compositionupdate", (e) => {
|
|
1349
1421
|
const data = _nullishCoalesce(e.data, () => ( ""));
|
|
1350
|
-
composition = { start: _nullishCoalesce(_optionalChain([composition, 'optionalAccess',
|
|
1422
|
+
composition = { start: _nullishCoalesce(_optionalChain([composition, 'optionalAccess', _74 => _74.start]), () => ( 0)), length: data.length };
|
|
1351
1423
|
forward();
|
|
1352
1424
|
});
|
|
1353
1425
|
el.addEventListener("compositionend", () => {
|
|
@@ -1380,7 +1452,7 @@ var Scene = (_class2 = class _Scene {
|
|
|
1380
1452
|
el.addEventListener("keydown", (e) => {
|
|
1381
1453
|
if (e.key === "Enter" || e.key === " ") {
|
|
1382
1454
|
e.preventDefault();
|
|
1383
|
-
node.dispatchEvent(new (0,
|
|
1455
|
+
node.dispatchEvent(new (0, _chunk2Z23LTH3js.VectoJSEvent)("click", node, e));
|
|
1384
1456
|
}
|
|
1385
1457
|
});
|
|
1386
1458
|
}
|
|
@@ -1398,6 +1470,10 @@ var Scene = (_class2 = class _Scene {
|
|
|
1398
1470
|
if (el.style.pointerEvents !== semanticPointerEvents) {
|
|
1399
1471
|
el.style.pointerEvents = semanticPointerEvents;
|
|
1400
1472
|
}
|
|
1473
|
+
const renderOrder = this.a11yRenderOrders.get(node.id);
|
|
1474
|
+
if (renderOrder !== void 0 && el.style.zIndex !== String(renderOrder)) {
|
|
1475
|
+
el.style.zIndex = String(renderOrder);
|
|
1476
|
+
}
|
|
1401
1477
|
const implicitTabIndex = !isNativelyFocusable(el) && attrs.role && INTERACTIVE_A11Y_ROLES.has(attrs.role) ? 0 : null;
|
|
1402
1478
|
const desiredTabIndex = _nullishCoalesce(attrs.tabIndex, () => ( implicitTabIndex));
|
|
1403
1479
|
if (desiredTabIndex === null) {
|
|
@@ -1539,7 +1615,7 @@ var Scene = (_class2 = class _Scene {
|
|
|
1539
1615
|
el.addEventListener(
|
|
1540
1616
|
"wheel",
|
|
1541
1617
|
(e2) => {
|
|
1542
|
-
node.dispatchEvent(new (0,
|
|
1618
|
+
node.dispatchEvent(new (0, _chunk2Z23LTH3js.VectoJSEvent)("wheel", node, e2));
|
|
1543
1619
|
},
|
|
1544
1620
|
{ passive: false }
|
|
1545
1621
|
);
|
|
@@ -1570,7 +1646,7 @@ var Scene = (_class2 = class _Scene {
|
|
|
1570
1646
|
lineElement.style.position = "absolute";
|
|
1571
1647
|
lineElement.dir = "auto";
|
|
1572
1648
|
lineElement.style.left = `${line.x}px`;
|
|
1573
|
-
lineElement.style.top = `${line.y + line.baseline -
|
|
1649
|
+
lineElement.style.top = `${line.y + line.baseline - _chunk2Z23LTH3js.cssLineBoxBaseline.call(void 0, lineFont, lineHeight2)}px`;
|
|
1574
1650
|
lineElement.style.whiteSpace = "pre";
|
|
1575
1651
|
if (lineFont) lineElement.style.font = lineFont;
|
|
1576
1652
|
lineElement.style.lineHeight = `${lineHeight2}px`;
|
|
@@ -1622,7 +1698,7 @@ var Scene = (_class2 = class _Scene {
|
|
|
1622
1698
|
const { a, b, c, d, e, f } = node.getWorldTransform();
|
|
1623
1699
|
const contentX = _nullishCoalesce(projection.contentX, () => ( 0));
|
|
1624
1700
|
const contentY = _nullishCoalesce(projection.contentY, () => ( 0));
|
|
1625
|
-
const baselineOffset = lines && lines.length > 0 ? 0 : projection.baseline === void 0 ? 0 : projection.baseline -
|
|
1701
|
+
const baselineOffset = lines && lines.length > 0 ? 0 : projection.baseline === void 0 ? 0 : projection.baseline - _chunk2Z23LTH3js.cssLineBoxBaseline.call(void 0, font, _nullishCoalesce(projection.lineHeight, () => ( 16)));
|
|
1626
1702
|
const localY = contentY + baselineOffset;
|
|
1627
1703
|
el.style.left = `${e + a * contentX + c * localY}px`;
|
|
1628
1704
|
el.style.top = `${f + b * contentX + d * localY}px`;
|
|
@@ -1686,15 +1762,15 @@ var Scene = (_class2 = class _Scene {
|
|
|
1686
1762
|
for (let lineIndex = 0; lineIndex < grid.lines.length; lineIndex++) {
|
|
1687
1763
|
const gridLine = grid.lines[lineIndex];
|
|
1688
1764
|
const projectedLine = projectionLines[lineIndex];
|
|
1689
|
-
const lineHeight = _nullishCoalesce(_optionalChain([projectedLine, 'optionalAccess',
|
|
1690
|
-
const baseline = _nullishCoalesce(_optionalChain([projectedLine, 'optionalAccess',
|
|
1691
|
-
const lineFont = _nullishCoalesce(_optionalChain([projectedLine, 'optionalAccess',
|
|
1765
|
+
const lineHeight = _nullishCoalesce(_optionalChain([projectedLine, 'optionalAccess', _75 => _75.lineHeight]), () => ( grid.lineHeight));
|
|
1766
|
+
const baseline = _nullishCoalesce(_optionalChain([projectedLine, 'optionalAccess', _76 => _76.baseline]), () => ( grid.baseline));
|
|
1767
|
+
const lineFont = _nullishCoalesce(_optionalChain([projectedLine, 'optionalAccess', _77 => _77.font]), () => ( grid.font));
|
|
1692
1768
|
const lineElement = document.createElement("span");
|
|
1693
1769
|
lineElement.dir = "ltr";
|
|
1694
1770
|
lineElement.dataset.vectoGridLine = `${lineIndex}`;
|
|
1695
1771
|
lineElement.style.position = "absolute";
|
|
1696
|
-
lineElement.style.left = `${_nullishCoalesce(_optionalChain([projectedLine, 'optionalAccess',
|
|
1697
|
-
lineElement.style.top = `${(_nullishCoalesce(_optionalChain([projectedLine, 'optionalAccess',
|
|
1772
|
+
lineElement.style.left = `${_nullishCoalesce(_optionalChain([projectedLine, 'optionalAccess', _78 => _78.x]), () => ( 0))}px`;
|
|
1773
|
+
lineElement.style.top = `${(_nullishCoalesce(_optionalChain([projectedLine, 'optionalAccess', _79 => _79.y]), () => ( lineIndex * grid.lineHeight))) + baseline - _chunk2Z23LTH3js.cssLineBoxBaseline.call(void 0, lineFont, lineHeight)}px`;
|
|
1698
1774
|
lineElement.style.width = `${gridLine.width}px`;
|
|
1699
1775
|
lineElement.style.height = `${lineHeight}px`;
|
|
1700
1776
|
lineElement.style.whiteSpace = "pre";
|
|
@@ -1790,7 +1866,7 @@ var Scene = (_class2 = class _Scene {
|
|
|
1790
1866
|
if (previous !== void 0 && typeof cancelAnimationFrame === "function") {
|
|
1791
1867
|
cancelAnimationFrame(previous);
|
|
1792
1868
|
}
|
|
1793
|
-
_optionalChain([this, 'access',
|
|
1869
|
+
_optionalChain([this, 'access', _80 => _80.contentGridCalibrationProbes, 'access', _81 => _81.get, 'call', _82 => _82(entityId), 'optionalAccess', _83 => _83.remove, 'call', _84 => _84()]);
|
|
1794
1870
|
this.contentGridCalibrationProbes.delete(entityId);
|
|
1795
1871
|
const calibrationStart = typeof performance !== "undefined" ? performance.now() : 0;
|
|
1796
1872
|
const probe = document.createElement("div");
|
|
@@ -1820,7 +1896,7 @@ var Scene = (_class2 = class _Scene {
|
|
|
1820
1896
|
const sourceLength = Number(_nullishCoalesce(target.dataset.vectoGridSourceLength, () => ( 0)));
|
|
1821
1897
|
const targetWidth = Number(_nullishCoalesce(target.dataset.vectoGridAdvance, () => ( 0)));
|
|
1822
1898
|
if (sourceLength <= 0 || targetWidth <= 0) continue;
|
|
1823
|
-
const sourceText = _nullishCoalesce(_optionalChain([target, 'access',
|
|
1899
|
+
const sourceText = _nullishCoalesce(_optionalChain([target, 'access', _85 => _85.textContent, 'optionalAccess', _86 => _86.slice, 'call', _87 => _87(0, sourceLength)]), () => ( ""));
|
|
1824
1900
|
if (!sourceText) continue;
|
|
1825
1901
|
const measurementKey = JSON.stringify([
|
|
1826
1902
|
target.style.font,
|
|
@@ -1970,12 +2046,12 @@ var Scene = (_class2 = class _Scene {
|
|
|
1970
2046
|
syncOverlayGeometry() {
|
|
1971
2047
|
const parent = this.canvas.parentElement;
|
|
1972
2048
|
if (!parent) return;
|
|
1973
|
-
const canvasRect = _optionalChain([this, 'access',
|
|
1974
|
-
const parentRect = _optionalChain([parent, 'access',
|
|
1975
|
-
const cssWidth = _optionalChain([canvasRect, 'optionalAccess',
|
|
1976
|
-
const cssHeight = _optionalChain([canvasRect, 'optionalAccess',
|
|
1977
|
-
const left = (_nullishCoalesce(_optionalChain([canvasRect, 'optionalAccess',
|
|
1978
|
-
const top = (_nullishCoalesce(_optionalChain([canvasRect, 'optionalAccess',
|
|
2049
|
+
const canvasRect = _optionalChain([this, 'access', _88 => _88.canvas, 'access', _89 => _89.getBoundingClientRect, 'optionalCall', _90 => _90()]);
|
|
2050
|
+
const parentRect = _optionalChain([parent, 'access', _91 => _91.getBoundingClientRect, 'optionalCall', _92 => _92()]);
|
|
2051
|
+
const cssWidth = _optionalChain([canvasRect, 'optionalAccess', _93 => _93.width]) || this.canvas.clientWidth || this.width;
|
|
2052
|
+
const cssHeight = _optionalChain([canvasRect, 'optionalAccess', _94 => _94.height]) || this.canvas.clientHeight || this.height;
|
|
2053
|
+
const left = (_nullishCoalesce(_optionalChain([canvasRect, 'optionalAccess', _95 => _95.left]), () => ( 0))) - (_nullishCoalesce(_optionalChain([parentRect, 'optionalAccess', _96 => _96.left]), () => ( 0))) - (parent.clientLeft || 0) + parent.scrollLeft;
|
|
2054
|
+
const top = (_nullishCoalesce(_optionalChain([canvasRect, 'optionalAccess', _97 => _97.top]), () => ( 0))) - (_nullishCoalesce(_optionalChain([parentRect, 'optionalAccess', _98 => _98.top]), () => ( 0))) - (parent.clientTop || 0) + parent.scrollTop;
|
|
1979
2055
|
const scaleX = this.width > 0 ? cssWidth / this.width : 1;
|
|
1980
2056
|
const scaleY = this.height > 0 ? cssHeight / this.height : 1;
|
|
1981
2057
|
for (const root of [this.a11yRoot, this.portalRoot]) {
|
|
@@ -2100,7 +2176,7 @@ var Scene = (_class2 = class _Scene {
|
|
|
2100
2176
|
* (and {@link respectReducedMotion} is on). `0` means uncapped.
|
|
2101
2177
|
*/
|
|
2102
2178
|
effectiveMaxFPS() {
|
|
2103
|
-
const reduced = this.respectReducedMotion && !!_optionalChain([this, 'access',
|
|
2179
|
+
const reduced = this.respectReducedMotion && !!_optionalChain([this, 'access', _99 => _99.reducedMotionQuery, 'optionalAccess', _100 => _100.matches]);
|
|
2104
2180
|
if (reduced)
|
|
2105
2181
|
return this.maxFPS > 0 ? Math.min(this.maxFPS, REDUCED_MOTION_FPS) : REDUCED_MOTION_FPS;
|
|
2106
2182
|
return this.maxFPS;
|
|
@@ -2158,6 +2234,7 @@ var Scene = (_class2 = class _Scene {
|
|
|
2158
2234
|
}
|
|
2159
2235
|
if (isMainRenderer) {
|
|
2160
2236
|
this.renderOrderCounter = 0;
|
|
2237
|
+
this.a11yRenderOrders.clear();
|
|
2161
2238
|
this.activePortalsThisFrame.clear();
|
|
2162
2239
|
}
|
|
2163
2240
|
const computeEntities = [];
|
|
@@ -2278,7 +2355,7 @@ var Scene = (_class2 = class _Scene {
|
|
|
2278
2355
|
}
|
|
2279
2356
|
renderer.clear();
|
|
2280
2357
|
if (isMainRenderer) {
|
|
2281
|
-
_optionalChain([this, 'access',
|
|
2358
|
+
_optionalChain([this, 'access', _101 => _101.pointRenderer, 'optionalAccess', _102 => _102.begin, 'call', _103 => _103()]);
|
|
2282
2359
|
}
|
|
2283
2360
|
const vw = this.width;
|
|
2284
2361
|
const vh = this.height;
|
|
@@ -2289,6 +2366,13 @@ var Scene = (_class2 = class _Scene {
|
|
|
2289
2366
|
node.update(dt, time);
|
|
2290
2367
|
if (!walkHadAnimation && node.hasPendingAnimations()) walkHadAnimation = true;
|
|
2291
2368
|
if (!walkHadInteractive && node.interactive) walkHadInteractive = true;
|
|
2369
|
+
if (this._devActive && this._devFrameCount % 120 === 0) {
|
|
2370
|
+
if (node.update !== _chunk2Z23LTH3js.Entity.prototype.update && node.hasPendingAnimations === _chunk2Z23LTH3js.Entity.prototype.hasPendingAnimations) {
|
|
2371
|
+
this._devWarn(
|
|
2372
|
+
`Entity "${node.id}" overrides update() but not hasPendingAnimations(). Custom motion in update() without overriding hasPendingAnimations() causes the idle throttle to drop the animation to ~2fps. Override hasPendingAnimations() to return true while motion is in flight.`
|
|
2373
|
+
);
|
|
2374
|
+
}
|
|
2375
|
+
}
|
|
2292
2376
|
}
|
|
2293
2377
|
const cos = Math.cos(node.rotation);
|
|
2294
2378
|
const sin = Math.sin(node.rotation);
|
|
@@ -2309,8 +2393,11 @@ var Scene = (_class2 = class _Scene {
|
|
|
2309
2393
|
const orthogonalTolerance = Math.max(1, worldScaleX * worldScaleY) * 1e-6;
|
|
2310
2394
|
const isSimilarityTransform = Number.isFinite(worldScaleX) && Number.isFinite(worldScaleY) && Math.abs(worldScaleX - worldScaleY) <= scaleTolerance && Math.abs(a * c + b * d) <= orthogonalTolerance;
|
|
2311
2395
|
const a11yEl = isMainRenderer ? this.a11yElements.get(node.id) : void 0;
|
|
2312
|
-
|
|
2313
|
-
|
|
2396
|
+
const willProjectA11y = isMainRenderer && node.interactive && (node.width > 0 || node.a11yFullViewport);
|
|
2397
|
+
if (a11yEl || willProjectA11y) {
|
|
2398
|
+
const renderOrder = this.renderOrderCounter++;
|
|
2399
|
+
if (willProjectA11y) this.a11yRenderOrders.set(node.id, renderOrder);
|
|
2400
|
+
if (a11yEl) a11yEl.style.zIndex = String(renderOrder);
|
|
2314
2401
|
}
|
|
2315
2402
|
if (node.isDOMPortal) {
|
|
2316
2403
|
if (isMainRenderer) {
|
|
@@ -2416,9 +2503,13 @@ var Scene = (_class2 = class _Scene {
|
|
|
2416
2503
|
}
|
|
2417
2504
|
renderer.flush();
|
|
2418
2505
|
if (isMainRenderer) {
|
|
2419
|
-
_optionalChain([this, 'access',
|
|
2506
|
+
_optionalChain([this, 'access', _104 => _104.pointRenderer, 'optionalAccess', _105 => _105.flush, 'call', _106 => _106()]);
|
|
2507
|
+
}
|
|
2508
|
+
_optionalChain([renderer, 'access', _107 => _107.present, 'optionalCall', _108 => _108()]);
|
|
2509
|
+
if (this._devActive) {
|
|
2510
|
+
this._devFrameCount++;
|
|
2511
|
+
this._devRunChecks();
|
|
2420
2512
|
}
|
|
2421
|
-
_optionalChain([renderer, 'access', _97 => _97.present, 'optionalCall', _98 => _98()]);
|
|
2422
2513
|
}
|
|
2423
2514
|
/**
|
|
2424
2515
|
* Export the current scene state to a lightweight, flat SVG XML string.
|
|
@@ -2622,7 +2713,7 @@ var Scene = (_class2 = class _Scene {
|
|
|
2622
2713
|
}
|
|
2623
2714
|
return null;
|
|
2624
2715
|
}
|
|
2625
|
-
}, _class2.__initStatic(), _class2.__initStatic2(), _class2);
|
|
2716
|
+
}, _class2.__initStatic(), _class2.__initStatic2(), _class2.__initStatic3(), _class2);
|
|
2626
2717
|
|
|
2627
2718
|
// src/components/TextEntity.ts
|
|
2628
2719
|
var sharedMeasurer;
|
|
@@ -2630,20 +2721,20 @@ function defaultMeasurer() {
|
|
|
2630
2721
|
if (sharedMeasurer === void 0) sharedMeasurer = _chunkBA5HUUDFjs.createCanvasMeasurer.call(void 0, "sans-serif");
|
|
2631
2722
|
return sharedMeasurer;
|
|
2632
2723
|
}
|
|
2633
|
-
var TextEntity = (_class3 = class extends
|
|
2724
|
+
var TextEntity = (_class3 = class extends _chunk2Z23LTH3js.Entity {
|
|
2634
2725
|
|
|
2635
2726
|
|
|
2636
2727
|
|
|
2637
2728
|
|
|
2638
|
-
|
|
2729
|
+
__init64() {this.nodes = []}
|
|
2639
2730
|
|
|
2640
|
-
|
|
2641
|
-
|
|
2642
|
-
|
|
2643
|
-
|
|
2644
|
-
|
|
2731
|
+
__init65() {this.fillStyle = "#94a3b8"}
|
|
2732
|
+
__init66() {this.strokeStyle = null}
|
|
2733
|
+
__init67() {this.hoveredFillStyle = "#ffffff"}
|
|
2734
|
+
__init68() {this.lineWidth = 1}
|
|
2735
|
+
__init69() {this.isHovered = false}
|
|
2645
2736
|
constructor(text, atlas, maxWidth, fontSize = 24) {
|
|
2646
|
-
super();_class3.prototype.
|
|
2737
|
+
super();_class3.prototype.__init64.call(this);_class3.prototype.__init65.call(this);_class3.prototype.__init66.call(this);_class3.prototype.__init67.call(this);_class3.prototype.__init68.call(this);_class3.prototype.__init69.call(this);;
|
|
2647
2738
|
this.text = text;
|
|
2648
2739
|
this.atlas = atlas;
|
|
2649
2740
|
this.fontSize = fontSize;
|
|
@@ -2756,17 +2847,17 @@ var TextEntity = (_class3 = class extends _chunkGKLTTGBRjs.Entity {
|
|
|
2756
2847
|
}, _class3);
|
|
2757
2848
|
|
|
2758
2849
|
// src/components/GridTextEntity.ts
|
|
2759
|
-
var GridTextEntity = (_class4 = class extends
|
|
2850
|
+
var GridTextEntity = (_class4 = class extends _chunk2Z23LTH3js.Entity {
|
|
2760
2851
|
|
|
2761
|
-
|
|
2762
|
-
|
|
2852
|
+
__init70() {this.fillStyle = "#ffffff"}
|
|
2853
|
+
__init71() {this.grid = []}
|
|
2763
2854
|
// Array of rows
|
|
2764
|
-
|
|
2765
|
-
|
|
2855
|
+
__init72() {this.cols = 0}
|
|
2856
|
+
__init73() {this.rows = 0}
|
|
2766
2857
|
|
|
2767
2858
|
|
|
2768
2859
|
constructor(_atlas, fontSize = 10) {
|
|
2769
|
-
super();_class4.prototype.
|
|
2860
|
+
super();_class4.prototype.__init70.call(this);_class4.prototype.__init71.call(this);_class4.prototype.__init72.call(this);_class4.prototype.__init73.call(this);;
|
|
2770
2861
|
this.fontSize = fontSize;
|
|
2771
2862
|
this.charWidth = fontSize * 1;
|
|
2772
2863
|
this.charHeight = fontSize * 1.1;
|
|
@@ -2775,7 +2866,7 @@ var GridTextEntity = (_class4 = class extends _chunkGKLTTGBRjs.Entity {
|
|
|
2775
2866
|
updateGrid(ascii) {
|
|
2776
2867
|
this.grid = ascii;
|
|
2777
2868
|
this.rows = ascii.length;
|
|
2778
|
-
this.cols = _optionalChain([ascii, 'access',
|
|
2869
|
+
this.cols = _optionalChain([ascii, 'access', _109 => _109[0], 'optionalAccess', _110 => _110.length]) || 0;
|
|
2779
2870
|
}
|
|
2780
2871
|
isPointInside(_globalX, _globalY) {
|
|
2781
2872
|
return false;
|
|
@@ -2850,7 +2941,7 @@ function distSqToSegment(px, py, x1, y1, x2, y2) {
|
|
|
2850
2941
|
const ey = py - cy;
|
|
2851
2942
|
return ex * ex + ey * ey;
|
|
2852
2943
|
}
|
|
2853
|
-
var SplineEntity = (_class5 = class extends
|
|
2944
|
+
var SplineEntity = (_class5 = class extends _chunk2Z23LTH3js.Entity {
|
|
2854
2945
|
|
|
2855
2946
|
|
|
2856
2947
|
|
|
@@ -2858,23 +2949,23 @@ var SplineEntity = (_class5 = class extends _chunkGKLTTGBRjs.Entity {
|
|
|
2858
2949
|
|
|
2859
2950
|
|
|
2860
2951
|
|
|
2861
|
-
|
|
2862
|
-
|
|
2952
|
+
__init74() {this.offscreen = null}
|
|
2953
|
+
__init75() {this.baked = false}
|
|
2863
2954
|
/** Logical (CSS-pixel) size of the baked bitmap — the blit destination size. */
|
|
2864
|
-
|
|
2865
|
-
|
|
2955
|
+
__init76() {this.bakedWidth = 0}
|
|
2956
|
+
__init77() {this.bakedHeight = 0}
|
|
2866
2957
|
/** Gradient strokes can't be baked to a solid-color bitmap; they render per-frame. */
|
|
2867
2958
|
|
|
2868
2959
|
/** Lazily-flattened polylines (one Float32Array of [x,y,...] per segment) for hit-testing. */
|
|
2869
|
-
|
|
2960
|
+
__init78() {this.polylines = null}
|
|
2870
2961
|
/**
|
|
2871
2962
|
* When `true`, the renderer draws a rounded-rect outline of the entity's
|
|
2872
2963
|
* local bounds after painting the curves. Useful for drag feedback and
|
|
2873
2964
|
* debugging hit areas. Defaults to `false`.
|
|
2874
2965
|
*/
|
|
2875
|
-
|
|
2966
|
+
__init79() {this.showBounds = false}
|
|
2876
2967
|
constructor(doc, opts = {}) {
|
|
2877
|
-
super();_class5.prototype.
|
|
2968
|
+
super();_class5.prototype.__init74.call(this);_class5.prototype.__init75.call(this);_class5.prototype.__init76.call(this);_class5.prototype.__init77.call(this);_class5.prototype.__init78.call(this);_class5.prototype.__init79.call(this);;
|
|
2878
2969
|
this.doc = doc;
|
|
2879
2970
|
this.lineWidth = _nullishCoalesce(opts.lineWidth, () => ( 2));
|
|
2880
2971
|
this.cache = _nullishCoalesce(opts.cache, () => ( true));
|
|
@@ -2885,7 +2976,7 @@ var SplineEntity = (_class5 = class extends _chunkGKLTTGBRjs.Entity {
|
|
|
2885
2976
|
this.width = this.bounds.width;
|
|
2886
2977
|
this.height = this.bounds.height;
|
|
2887
2978
|
const isGradient = (c) => c !== null && !Array.isArray(c);
|
|
2888
|
-
this.containsGradient = (_nullishCoalesce(_optionalChain([this, 'access',
|
|
2979
|
+
this.containsGradient = (_nullishCoalesce(_optionalChain([this, 'access', _111 => _111.doc, 'access', _112 => _112.equations, 'optionalAccess', _113 => _113.some, 'call', _114 => _114((eq) => isGradient(eq.color_rgb))]), () => ( false))) || (_nullishCoalesce(_optionalChain([this, 'access', _115 => _115.doc, 'access', _116 => _116.paths, 'optionalAccess', _117 => _117.some, 'call', _118 => _118((p) => isGradient(p.color_rgb))]), () => ( false)));
|
|
2889
2980
|
this.interactive = true;
|
|
2890
2981
|
}
|
|
2891
2982
|
computeBounds() {
|
|
@@ -3125,7 +3216,7 @@ async function loadSpline(url) {
|
|
|
3125
3216
|
}
|
|
3126
3217
|
|
|
3127
3218
|
// src/components/Rect.ts
|
|
3128
|
-
var Rect = class extends
|
|
3219
|
+
var Rect = class extends _chunk2Z23LTH3js.Entity {
|
|
3129
3220
|
|
|
3130
3221
|
|
|
3131
3222
|
|
|
@@ -3174,7 +3265,7 @@ var Rect = class extends _chunkGKLTTGBRjs.Entity {
|
|
|
3174
3265
|
};
|
|
3175
3266
|
|
|
3176
3267
|
// src/components/Circle.ts
|
|
3177
|
-
var Circle = class extends
|
|
3268
|
+
var Circle = class extends _chunk2Z23LTH3js.Entity {
|
|
3178
3269
|
|
|
3179
3270
|
|
|
3180
3271
|
|
|
@@ -3234,7 +3325,7 @@ var Circle = class extends _chunkGKLTTGBRjs.Entity {
|
|
|
3234
3325
|
};
|
|
3235
3326
|
|
|
3236
3327
|
// src/components/Group.ts
|
|
3237
|
-
var Group = class extends
|
|
3328
|
+
var Group = class extends _chunk2Z23LTH3js.Entity {
|
|
3238
3329
|
constructor(...children) {
|
|
3239
3330
|
super();
|
|
3240
3331
|
if (children.length > 0) this.add(...children);
|
|
@@ -3249,9 +3340,9 @@ var Group = class extends _chunkGKLTTGBRjs.Entity {
|
|
|
3249
3340
|
// src/math/SpatialHashGrid.ts
|
|
3250
3341
|
var SpatialHashGrid = (_class6 = class {
|
|
3251
3342
|
|
|
3252
|
-
|
|
3253
|
-
|
|
3254
|
-
constructor(cellSize = 64) {;_class6.prototype.
|
|
3343
|
+
__init80() {this.grid = /* @__PURE__ */ new Map()}
|
|
3344
|
+
__init81() {this.entityCells = /* @__PURE__ */ new Map()}
|
|
3345
|
+
constructor(cellSize = 64) {;_class6.prototype.__init80.call(this);_class6.prototype.__init81.call(this);
|
|
3255
3346
|
this.cellSize = cellSize;
|
|
3256
3347
|
}
|
|
3257
3348
|
hash(cx, cy) {
|
|
@@ -3305,7 +3396,7 @@ var SpatialHashGrid = (_class6 = class {
|
|
|
3305
3396
|
const keys = this.entityCells.get(id);
|
|
3306
3397
|
if (!keys) return;
|
|
3307
3398
|
for (const key of keys) {
|
|
3308
|
-
_optionalChain([this, 'access',
|
|
3399
|
+
_optionalChain([this, 'access', _119 => _119.grid, 'access', _120 => _120.get, 'call', _121 => _121(key), 'optionalAccess', _122 => _122.delete, 'call', _123 => _123(id)]);
|
|
3309
3400
|
}
|
|
3310
3401
|
this.entityCells.delete(id);
|
|
3311
3402
|
}
|
|
@@ -3341,20 +3432,20 @@ var SpatialHashGrid = (_class6 = class {
|
|
|
3341
3432
|
}, _class6);
|
|
3342
3433
|
|
|
3343
3434
|
// src/tree/DOMPortalEntity.ts
|
|
3344
|
-
var DOMPortalEntity = (_class7 = class extends
|
|
3435
|
+
var DOMPortalEntity = (_class7 = class extends _chunk2Z23LTH3js.Entity {
|
|
3345
3436
|
|
|
3346
|
-
|
|
3347
|
-
|
|
3348
|
-
|
|
3349
|
-
|
|
3350
|
-
|
|
3351
|
-
|
|
3352
|
-
|
|
3353
|
-
|
|
3354
|
-
|
|
3355
|
-
|
|
3437
|
+
__init82() {this.isDOMPortal = true}
|
|
3438
|
+
__init83() {this.domListeners = []}
|
|
3439
|
+
__init84() {this.resizeObserver = null}
|
|
3440
|
+
__init85() {this.cachedWidth = 100}
|
|
3441
|
+
__init86() {this.cachedHeight = 100}
|
|
3442
|
+
__init87() {this.lastWidth = ""}
|
|
3443
|
+
__init88() {this.lastHeight = ""}
|
|
3444
|
+
__init89() {this.lastTransform = ""}
|
|
3445
|
+
__init90() {this.lastZIndex = ""}
|
|
3446
|
+
__init91() {this.lastOpacity = ""}
|
|
3356
3447
|
constructor(domElement, width, height, id) {
|
|
3357
|
-
super(id);_class7.prototype.
|
|
3448
|
+
super(id);_class7.prototype.__init82.call(this);_class7.prototype.__init83.call(this);_class7.prototype.__init84.call(this);_class7.prototype.__init85.call(this);_class7.prototype.__init86.call(this);_class7.prototype.__init87.call(this);_class7.prototype.__init88.call(this);_class7.prototype.__init89.call(this);_class7.prototype.__init90.call(this);_class7.prototype.__init91.call(this);;
|
|
3358
3449
|
this.domElement = domElement;
|
|
3359
3450
|
this.width = _nullishCoalesce(width, () => ( 0));
|
|
3360
3451
|
this.height = _nullishCoalesce(height, () => ( 0));
|
|
@@ -3383,7 +3474,7 @@ var DOMPortalEntity = (_class7 = class extends _chunkGKLTTGBRjs.Entity {
|
|
|
3383
3474
|
];
|
|
3384
3475
|
for (const type of events) {
|
|
3385
3476
|
const handler = (e) => {
|
|
3386
|
-
this.dispatchEvent(new (0,
|
|
3477
|
+
this.dispatchEvent(new (0, _chunk2Z23LTH3js.VectoJSEvent)(type, this, e));
|
|
3387
3478
|
};
|
|
3388
3479
|
this.domElement.addEventListener(type, handler);
|
|
3389
3480
|
this.domListeners.push({ type, handler, capture: false });
|
|
@@ -3394,7 +3485,7 @@ var DOMPortalEntity = (_class7 = class extends _chunkGKLTTGBRjs.Entity {
|
|
|
3394
3485
|
];
|
|
3395
3486
|
for (const { native, vecto } of hoverEvents) {
|
|
3396
3487
|
const handler = (e) => {
|
|
3397
|
-
this.dispatchEvent(new (0,
|
|
3488
|
+
this.dispatchEvent(new (0, _chunk2Z23LTH3js.VectoJSEvent)(vecto, this, e, false));
|
|
3398
3489
|
};
|
|
3399
3490
|
this.domElement.addEventListener(native, handler);
|
|
3400
3491
|
this.domListeners.push({ type: native, handler, capture: false });
|
|
@@ -3402,7 +3493,7 @@ var DOMPortalEntity = (_class7 = class extends _chunkGKLTTGBRjs.Entity {
|
|
|
3402
3493
|
const focusEvents = ["focus", "blur"];
|
|
3403
3494
|
for (const type of focusEvents) {
|
|
3404
3495
|
const handler = (e) => {
|
|
3405
|
-
this.dispatchEvent(new (0,
|
|
3496
|
+
this.dispatchEvent(new (0, _chunk2Z23LTH3js.VectoJSEvent)(type, this, e, true));
|
|
3406
3497
|
};
|
|
3407
3498
|
this.domElement.addEventListener(type, handler, true);
|
|
3408
3499
|
this.domListeners.push({ type, handler, capture: true });
|
|
@@ -3493,4 +3584,4 @@ Scene.registerWebGPUParticleSystemManager(_chunkORCPCIJ7js.WebGPUParticleSystemM
|
|
|
3493
3584
|
|
|
3494
3585
|
|
|
3495
3586
|
|
|
3496
|
-
exports.ArabicShaper = _chunk4AR425ARjs.ArabicShaper; exports.BidiResolver = _chunk4AR425ARjs.BidiResolver; exports.CanvasRenderer = _chunkORCPCIJ7js.CanvasRenderer; exports.Circle = Circle; exports.ComputeParticleEntity = ComputeParticleEntity; exports.DOMPortalEntity = DOMPortalEntity; exports.Easing =
|
|
3587
|
+
exports.ArabicShaper = _chunk4AR425ARjs.ArabicShaper; exports.BidiResolver = _chunk4AR425ARjs.BidiResolver; exports.CanvasRenderer = _chunkORCPCIJ7js.CanvasRenderer; exports.Circle = Circle; exports.ComputeParticleEntity = ComputeParticleEntity; exports.DOMPortalEntity = DOMPortalEntity; exports.Easing = _chunk2Z23LTH3js.Easing; exports.Entity = _chunk2Z23LTH3js.Entity; exports.GridTextEntity = GridTextEntity; exports.Group = Group; exports.LayoutEngine = _chunkBA5HUUDFjs.LayoutEngine; exports.LayoutResultBuffer = _chunkBA5HUUDFjs.LayoutResultBuffer; exports.LayoutWorkerManager = _chunk4AR425ARjs.LayoutWorkerManager; exports.MSDFFont = _chunk2Z23LTH3js.MSDFFont; exports.MSDFTextEntity = _chunk2Z23LTH3js.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.Rect = Rect; exports.SVGEntity = _chunk2Z23LTH3js.SVGEntity; exports.SVGRenderer = _chunkORCPCIJ7js.SVGRenderer; exports.Scene = Scene; exports.SpatialHashGrid = SpatialHashGrid; exports.SplineEntity = SplineEntity; exports.SpringDriver = _chunk2Z23LTH3js.SpringDriver; exports.SpringPhysics = _chunk2Z23LTH3js.SpringPhysics; exports.TextEntity = TextEntity; exports.TweenDriver = _chunk2Z23LTH3js.TweenDriver; exports.VectoJSEvent = _chunk2Z23LTH3js.VectoJSEvent; exports.WebGPUParticleSystemManager = _chunkORCPCIJ7js.WebGPUParticleSystemManager; exports.clearCssLineBoxMetrics = _chunk2Z23LTH3js.clearCssLineBoxMetrics; exports.computeLineSegments = _chunkBA5HUUDFjs.computeLineSegments; exports.createCanvasMeasurer = _chunkBA5HUUDFjs.createCanvasMeasurer; exports.createWebGLPointRenderer = _chunkORCPCIJ7js.createWebGLPointRenderer; exports.cssLineBoxBaseline = _chunk2Z23LTH3js.cssLineBoxBaseline; exports.isSafeUrl = _chunkORCPCIJ7js.isSafeUrl; exports.isTweenConfig = _chunk2Z23LTH3js.isTweenConfig; exports.loadSpline = loadSpline; exports.parseColorToRGBA = _chunkORCPCIJ7js.parseColorToRGBA; exports.polySegmentToBezier = polySegmentToBezier; exports.prepareContentGrid = _chunk2Z23LTH3js.prepareContentGrid; exports.sanitizeUrl = _chunkORCPCIJ7js.sanitizeUrl;
|
package/dist/index.mjs
CHANGED
|
@@ -27,7 +27,7 @@ import {
|
|
|
27
27
|
cssLineBoxBaseline,
|
|
28
28
|
isTweenConfig,
|
|
29
29
|
prepareContentGrid
|
|
30
|
-
} from "./chunk-
|
|
30
|
+
} from "./chunk-XIEQHSBB.mjs";
|
|
31
31
|
import {
|
|
32
32
|
ArabicShaper,
|
|
33
33
|
BidiResolver,
|
|
@@ -701,6 +701,13 @@ var Scene = class _Scene {
|
|
|
701
701
|
activePortalsPrevFrame = /* @__PURE__ */ new Set();
|
|
702
702
|
portalEntities = /* @__PURE__ */ new Map();
|
|
703
703
|
renderOrderCounter = 0;
|
|
704
|
+
/**
|
|
705
|
+
* Authoritative paint order for semantic nodes discovered during the main
|
|
706
|
+
* render. A node may not have a DOM projection until the following a11y
|
|
707
|
+
* sync, so retaining the order prevents a newly opened overlay from spending
|
|
708
|
+
* its first frame below previously projected controls.
|
|
709
|
+
*/
|
|
710
|
+
a11yRenderOrders = /* @__PURE__ */ new Map();
|
|
704
711
|
// Optional WebGL point-cloud layer (see SceneOptions.pointBackend).
|
|
705
712
|
pointRenderer = null;
|
|
706
713
|
glCanvas = null;
|
|
@@ -735,6 +742,67 @@ var Scene = class _Scene {
|
|
|
735
742
|
pointerLeaveListener = null;
|
|
736
743
|
hasWarnedZeroSize = false;
|
|
737
744
|
fontLoadHandler = null;
|
|
745
|
+
// ── Dev-mode warning infrastructure ──────────────────────────────
|
|
746
|
+
//
|
|
747
|
+
// Enable with `Scene.devMode = true` or by setting `globalThis.__DEV__`.
|
|
748
|
+
// Auto-detected when `NODE_ENV === 'development'`.
|
|
749
|
+
//
|
|
750
|
+
// Checks run once every ~120 frames (~2s at 60fps) to keep overhead
|
|
751
|
+
// negligible even when dev mode is on.
|
|
752
|
+
/** Toggle development-mode runtime warnings globally. */
|
|
753
|
+
static devMode = false;
|
|
754
|
+
static _devModeDetected() {
|
|
755
|
+
if (_Scene.devMode) return true;
|
|
756
|
+
const gp = typeof globalThis !== "undefined" ? globalThis : void 0;
|
|
757
|
+
if (gp?.__DEV__) return true;
|
|
758
|
+
if (gp?.process?.env?.NODE_ENV === "development") return true;
|
|
759
|
+
return false;
|
|
760
|
+
}
|
|
761
|
+
_devActive;
|
|
762
|
+
_devFrameCount = 0;
|
|
763
|
+
_devWarn(message) {
|
|
764
|
+
if (!this._devActive) return;
|
|
765
|
+
console.warn(`[vectojs/dev] ${message}`);
|
|
766
|
+
}
|
|
767
|
+
/** @internal Periodic dev checks — called once per frame in dev mode. */
|
|
768
|
+
_devRunChecks() {
|
|
769
|
+
this._devFrameCount++;
|
|
770
|
+
if (this._devFrameCount % 120 !== 0) return;
|
|
771
|
+
if (this.a11yElements) {
|
|
772
|
+
let interactiveCount = 0;
|
|
773
|
+
const walk = (node) => {
|
|
774
|
+
if (node.interactive && node.width > 0) interactiveCount++;
|
|
775
|
+
for (const c of node.children) walk(c);
|
|
776
|
+
};
|
|
777
|
+
walk(this.root);
|
|
778
|
+
for (const c of this.overlayRoot.children) walk(c);
|
|
779
|
+
const shadowCount = this.a11yElements.size;
|
|
780
|
+
if (shadowCount > interactiveCount + 2) {
|
|
781
|
+
this._devWarn(
|
|
782
|
+
`a11yElements (${shadowCount}) exceeds interactive entities (${interactiveCount}). Call scene.detachA11y(entity) before removing interactive children from the tree, or their shadow nodes leak.`
|
|
783
|
+
);
|
|
784
|
+
}
|
|
785
|
+
}
|
|
786
|
+
let checked = 0;
|
|
787
|
+
const walkProjections = (node) => {
|
|
788
|
+
if (checked > 10) return;
|
|
789
|
+
const proj = node.getContentProjection?.();
|
|
790
|
+
if (proj?.text && proj.selectable !== false) {
|
|
791
|
+
const el = this.contentElements?.get(node.id);
|
|
792
|
+
if (el) {
|
|
793
|
+
const projectedText = el.textContent || "";
|
|
794
|
+
if (projectedText !== "" && projectedText !== proj.text) {
|
|
795
|
+
this._devWarn(
|
|
796
|
+
`Content projection mismatch for entity "${node.id}": projection says "${proj.text.slice(0, 60)}" but DOM shows "${projectedText.slice(0, 60)}". Ensure getContentProjection() output matches what drawSelf renders.`
|
|
797
|
+
);
|
|
798
|
+
}
|
|
799
|
+
}
|
|
800
|
+
}
|
|
801
|
+
checked++;
|
|
802
|
+
for (const c of node.children) walkProjections(c);
|
|
803
|
+
};
|
|
804
|
+
walkProjections(this.root);
|
|
805
|
+
}
|
|
738
806
|
constructor(canvas, options = {}) {
|
|
739
807
|
this.canvas = canvas;
|
|
740
808
|
this.debugA11y = options.debugA11y ?? false;
|
|
@@ -757,6 +825,7 @@ var Scene = class _Scene {
|
|
|
757
825
|
this.particleBackend = options.particleBackend ?? "auto";
|
|
758
826
|
this.a11ySyncInterval = options.a11ySyncInterval ?? 0;
|
|
759
827
|
this.contentProjectionEnabled = options.contentProjection ?? true;
|
|
828
|
+
this._devActive = _Scene._devModeDetected();
|
|
760
829
|
this.reducedMotionQuery = typeof window !== "undefined" && typeof window.matchMedia === "function" ? window.matchMedia("(prefers-reduced-motion: reduce)") : null;
|
|
761
830
|
this.root = new class RootEntity extends Entity {
|
|
762
831
|
isPointInside() {
|
|
@@ -1273,6 +1342,9 @@ var Scene = class _Scene {
|
|
|
1273
1342
|
el.addEventListener("click", (e) => {
|
|
1274
1343
|
node.dispatchEvent(new VectoJSEvent("click", node, e));
|
|
1275
1344
|
});
|
|
1345
|
+
el.addEventListener("dblclick", (e) => {
|
|
1346
|
+
node.dispatchEvent(new VectoJSEvent("dblclick", node, e));
|
|
1347
|
+
});
|
|
1276
1348
|
el.addEventListener("mouseenter", (e) => {
|
|
1277
1349
|
if (this.debugA11y) el.style.backgroundColor = "rgba(56, 189, 248, 0.2)";
|
|
1278
1350
|
node.dispatchEvent(new VectoJSEvent("hover", node, e, false));
|
|
@@ -1398,6 +1470,10 @@ var Scene = class _Scene {
|
|
|
1398
1470
|
if (el.style.pointerEvents !== semanticPointerEvents) {
|
|
1399
1471
|
el.style.pointerEvents = semanticPointerEvents;
|
|
1400
1472
|
}
|
|
1473
|
+
const renderOrder = this.a11yRenderOrders.get(node.id);
|
|
1474
|
+
if (renderOrder !== void 0 && el.style.zIndex !== String(renderOrder)) {
|
|
1475
|
+
el.style.zIndex = String(renderOrder);
|
|
1476
|
+
}
|
|
1401
1477
|
const implicitTabIndex = !isNativelyFocusable(el) && attrs.role && INTERACTIVE_A11Y_ROLES.has(attrs.role) ? 0 : null;
|
|
1402
1478
|
const desiredTabIndex = attrs.tabIndex ?? implicitTabIndex;
|
|
1403
1479
|
if (desiredTabIndex === null) {
|
|
@@ -2158,6 +2234,7 @@ var Scene = class _Scene {
|
|
|
2158
2234
|
}
|
|
2159
2235
|
if (isMainRenderer) {
|
|
2160
2236
|
this.renderOrderCounter = 0;
|
|
2237
|
+
this.a11yRenderOrders.clear();
|
|
2161
2238
|
this.activePortalsThisFrame.clear();
|
|
2162
2239
|
}
|
|
2163
2240
|
const computeEntities = [];
|
|
@@ -2289,6 +2366,13 @@ var Scene = class _Scene {
|
|
|
2289
2366
|
node.update(dt, time);
|
|
2290
2367
|
if (!walkHadAnimation && node.hasPendingAnimations()) walkHadAnimation = true;
|
|
2291
2368
|
if (!walkHadInteractive && node.interactive) walkHadInteractive = true;
|
|
2369
|
+
if (this._devActive && this._devFrameCount % 120 === 0) {
|
|
2370
|
+
if (node.update !== Entity.prototype.update && node.hasPendingAnimations === Entity.prototype.hasPendingAnimations) {
|
|
2371
|
+
this._devWarn(
|
|
2372
|
+
`Entity "${node.id}" overrides update() but not hasPendingAnimations(). Custom motion in update() without overriding hasPendingAnimations() causes the idle throttle to drop the animation to ~2fps. Override hasPendingAnimations() to return true while motion is in flight.`
|
|
2373
|
+
);
|
|
2374
|
+
}
|
|
2375
|
+
}
|
|
2292
2376
|
}
|
|
2293
2377
|
const cos = Math.cos(node.rotation);
|
|
2294
2378
|
const sin = Math.sin(node.rotation);
|
|
@@ -2309,8 +2393,11 @@ var Scene = class _Scene {
|
|
|
2309
2393
|
const orthogonalTolerance = Math.max(1, worldScaleX * worldScaleY) * 1e-6;
|
|
2310
2394
|
const isSimilarityTransform = Number.isFinite(worldScaleX) && Number.isFinite(worldScaleY) && Math.abs(worldScaleX - worldScaleY) <= scaleTolerance && Math.abs(a * c + b * d) <= orthogonalTolerance;
|
|
2311
2395
|
const a11yEl = isMainRenderer ? this.a11yElements.get(node.id) : void 0;
|
|
2312
|
-
|
|
2313
|
-
|
|
2396
|
+
const willProjectA11y = isMainRenderer && node.interactive && (node.width > 0 || node.a11yFullViewport);
|
|
2397
|
+
if (a11yEl || willProjectA11y) {
|
|
2398
|
+
const renderOrder = this.renderOrderCounter++;
|
|
2399
|
+
if (willProjectA11y) this.a11yRenderOrders.set(node.id, renderOrder);
|
|
2400
|
+
if (a11yEl) a11yEl.style.zIndex = String(renderOrder);
|
|
2314
2401
|
}
|
|
2315
2402
|
if (node.isDOMPortal) {
|
|
2316
2403
|
if (isMainRenderer) {
|
|
@@ -2419,6 +2506,10 @@ var Scene = class _Scene {
|
|
|
2419
2506
|
this.pointRenderer?.flush();
|
|
2420
2507
|
}
|
|
2421
2508
|
renderer.present?.();
|
|
2509
|
+
if (this._devActive) {
|
|
2510
|
+
this._devFrameCount++;
|
|
2511
|
+
this._devRunChecks();
|
|
2512
|
+
}
|
|
2422
2513
|
}
|
|
2423
2514
|
/**
|
|
2424
2515
|
* Export the current scene state to a lightweight, flat SVG XML string.
|
package/dist/text.js
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
|
|
8
|
-
var
|
|
8
|
+
var _chunk2Z23LTH3js = require('./chunk-2Z23LTH3.js');
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
|
|
@@ -19,4 +19,4 @@ var _chunk4AR425ARjs = require('./chunk-4AR425AR.js');
|
|
|
19
19
|
|
|
20
20
|
|
|
21
21
|
|
|
22
|
-
exports.ArabicShaper = _chunk4AR425ARjs.ArabicShaper; exports.BidiResolver = _chunk4AR425ARjs.BidiResolver; exports.MSDFFont =
|
|
22
|
+
exports.ArabicShaper = _chunk4AR425ARjs.ArabicShaper; exports.BidiResolver = _chunk4AR425ARjs.BidiResolver; exports.MSDFFont = _chunk2Z23LTH3js.MSDFFont; exports.MSDFTextEntity = _chunk2Z23LTH3js.MSDFTextEntity; exports.SVGEntity = _chunk2Z23LTH3js.SVGEntity; exports.clearCssLineBoxMetrics = _chunk2Z23LTH3js.clearCssLineBoxMetrics; exports.cssLineBoxBaseline = _chunk2Z23LTH3js.cssLineBoxBaseline; exports.prepareContentGrid = _chunk2Z23LTH3js.prepareContentGrid;
|
package/dist/text.mjs
CHANGED
package/dist/tree/Entity.d.ts
CHANGED
|
@@ -192,7 +192,7 @@ export interface A11yAttributes {
|
|
|
192
192
|
/**
|
|
193
193
|
* Union of all pointer/interaction events that can be emitted by an {@link Entity}.
|
|
194
194
|
*/
|
|
195
|
-
export type VectoEvent = 'click' | 'hover' | 'pointerdown' | 'pointerup' | 'pointercancel' | 'pointermove' | 'pointerleave' | 'change' | 'focus' | 'blur' | 'wheel' | 'keydown' | 'keyup';
|
|
195
|
+
export type VectoEvent = 'click' | 'dblclick' | 'hover' | 'pointerdown' | 'pointerup' | 'pointercancel' | 'pointermove' | 'pointerleave' | 'change' | 'focus' | 'blur' | 'wheel' | 'keydown' | 'keyup';
|
|
196
196
|
/** Options for {@link Entity.on} / {@link Entity.off}. */
|
|
197
197
|
export interface ListenerOptions {
|
|
198
198
|
/** Register the listener for the capture phase (root→target) instead of bubble. */
|
|
@@ -470,6 +470,15 @@ export declare abstract class Entity {
|
|
|
470
470
|
* @param payload - Arbitrary data forwarded to each listener.
|
|
471
471
|
*/
|
|
472
472
|
emit(event: VectoEvent, payload: any): void;
|
|
473
|
+
/**
|
|
474
|
+
* Programmatically focus the entity's projected a11y shadow element, if one
|
|
475
|
+
* exists. After `scene.add(entity)` the shadow element is typically created
|
|
476
|
+
* on the next a11y sync (within one animation frame), so this method retries
|
|
477
|
+
* once on the next rAF if the element isn't immediately available — matching
|
|
478
|
+
* the timing pattern the prior workaround described in findings.md achieved
|
|
479
|
+
* with `requestAnimationFrame(() => document.getElementById(id)?.focus())`.
|
|
480
|
+
*/
|
|
481
|
+
focus(): void;
|
|
473
482
|
/** Run one node's listeners for the event, honoring stopImmediatePropagation. */
|
|
474
483
|
private fireListeners;
|
|
475
484
|
/**
|
package/dist/tree/Scene.d.ts
CHANGED
|
@@ -205,6 +205,13 @@ export declare class Scene {
|
|
|
205
205
|
private activePortalsPrevFrame;
|
|
206
206
|
private portalEntities;
|
|
207
207
|
private renderOrderCounter;
|
|
208
|
+
/**
|
|
209
|
+
* Authoritative paint order for semantic nodes discovered during the main
|
|
210
|
+
* render. A node may not have a DOM projection until the following a11y
|
|
211
|
+
* sync, so retaining the order prevents a newly opened overlay from spending
|
|
212
|
+
* its first frame below previously projected controls.
|
|
213
|
+
*/
|
|
214
|
+
private a11yRenderOrders;
|
|
208
215
|
private pointRenderer;
|
|
209
216
|
private glCanvas;
|
|
210
217
|
private debugA11y;
|
|
@@ -233,6 +240,14 @@ export declare class Scene {
|
|
|
233
240
|
private pointerLeaveListener;
|
|
234
241
|
private hasWarnedZeroSize;
|
|
235
242
|
private fontLoadHandler;
|
|
243
|
+
/** Toggle development-mode runtime warnings globally. */
|
|
244
|
+
static devMode: boolean;
|
|
245
|
+
private static _devModeDetected;
|
|
246
|
+
private _devActive;
|
|
247
|
+
private _devFrameCount;
|
|
248
|
+
private _devWarn;
|
|
249
|
+
/** @internal Periodic dev checks — called once per frame in dev mode. */
|
|
250
|
+
private _devRunChecks;
|
|
236
251
|
constructor(canvas: HTMLCanvasElement, options?: SceneOptions);
|
|
237
252
|
private endContentSelectionDrag;
|
|
238
253
|
private releaseContentSelectionForRebuild;
|