@vectojs/core 1.32.0 → 1.32.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/index.js +155 -119
- package/dist/index.mjs +57 -21
- package/dist/tree/Scene.d.ts +22 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -2112,10 +2112,20 @@ var Scene = (_class7 = class _Scene {
|
|
|
2112
2112
|
* see {@link sortNormalElementsVisually}.
|
|
2113
2113
|
*/
|
|
2114
2114
|
__init92() {this.a11yOrderContainers = /* @__PURE__ */ new Set()}
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
|
|
2115
|
+
/**
|
|
2116
|
+
* Nearest `clipChildren` ancestor per ordered element — its *region* — reused
|
|
2117
|
+
* per pass. Written by `enforceA11yDomOrder`'s collect walk, which already has
|
|
2118
|
+
* the entity in hand, so a region costs one comparison per node rather than an
|
|
2119
|
+
* ancestor walk per element.
|
|
2120
|
+
*
|
|
2121
|
+
* Absent means the element sits under no clipping ancestor and belongs to the
|
|
2122
|
+
* implicit root region. See {@link sortNormalElementsVisually}.
|
|
2123
|
+
*/
|
|
2124
|
+
__init93() {this.a11yOrderRegions = /* @__PURE__ */ new Map()}
|
|
2125
|
+
__init94() {this.activePortalsThisFrame = /* @__PURE__ */ new Set()}
|
|
2126
|
+
__init95() {this.activePortalsPrevFrame = /* @__PURE__ */ new Set()}
|
|
2127
|
+
__init96() {this.portalEntities = /* @__PURE__ */ new Map()}
|
|
2128
|
+
__init97() {this.renderOrderCounter = 0}
|
|
2119
2129
|
/**
|
|
2120
2130
|
* Monotonic render-frame counter, bumped once per authoritative `render()`
|
|
2121
2131
|
* pass. Entities stamp their per-frame world-matrix cache with this value and
|
|
@@ -2124,7 +2134,7 @@ var Scene = (_class7 = class _Scene {
|
|
|
2124
2134
|
* back to the ancestor walk. Public for the same reason `Entity._getTrig`/
|
|
2125
2135
|
* `_setWorldCache` are: it is a cross-class render-internal contract.
|
|
2126
2136
|
*/
|
|
2127
|
-
|
|
2137
|
+
__init98() {this.currentFrame = 0}
|
|
2128
2138
|
// ── WASM transform backend (invisible accelerator) ──────────────────────────
|
|
2129
2139
|
// When `_transformBackend === 'wasm'`, the main render walk sources each
|
|
2130
2140
|
// entity's world matrix from an SoA store composed by `_wasm` (see
|
|
@@ -2132,24 +2142,24 @@ var Scene = (_class7 = class _Scene {
|
|
|
2132
2142
|
// fallback and the default: a null backend, a non-main renderer, or any entity
|
|
2133
2143
|
// absent from the store all fall back to the JS composition, so WASM can only
|
|
2134
2144
|
// ever change *how fast* a world matrix is produced, never *what* it is.
|
|
2135
|
-
|
|
2136
|
-
|
|
2145
|
+
__init99() {this._wasm = null}
|
|
2146
|
+
__init100() {this._transformBackend = "js"}
|
|
2137
2147
|
// Resident store state (Stage 3). The store layout — slot assignment + sibling
|
|
2138
2148
|
// runs — depends only on tree TOPOLOGY, so it is rebuilt only when the
|
|
2139
2149
|
// structure changes (add/remove/reparent bump `_structureVersion`). Between
|
|
2140
2150
|
// rebuilds the per-frame cost is: gather each entity's transform into the
|
|
2141
2151
|
// resident wasm input view + run the kernel — no reallocation, no readback.
|
|
2142
|
-
|
|
2143
|
-
|
|
2152
|
+
__init101() {this._treeStore = null}
|
|
2153
|
+
__init102() {this._slotEntity = []}
|
|
2144
2154
|
// store slot -> entity (also validates slots)
|
|
2145
|
-
|
|
2146
|
-
|
|
2147
|
-
|
|
2148
|
-
|
|
2155
|
+
__init103() {this._wasmInputs = null}
|
|
2156
|
+
__init104() {this._wasmWorld = null}
|
|
2157
|
+
__init105() {this._structureVersion = 0}
|
|
2158
|
+
__init106() {this._storeStructureVersion = -1}
|
|
2149
2159
|
// Cached list of ComputeParticleEntity instances in the tree, keyed by the
|
|
2150
2160
|
// structure version it was gathered at. Rebuilt only on a topology change.
|
|
2151
|
-
|
|
2152
|
-
|
|
2161
|
+
__init107() {this._computeEntities = []}
|
|
2162
|
+
__init108() {this._computeEntitiesVersion = -1}
|
|
2153
2163
|
/** Invalidate the resident WASM store layout; the next wasm-mode frame rebuilds
|
|
2154
2164
|
* it. Called by `Entity.add`/`remove` (topology changes only). */
|
|
2155
2165
|
markStructureChanged() {
|
|
@@ -2234,7 +2244,7 @@ var Scene = (_class7 = class _Scene {
|
|
|
2234
2244
|
* cached globally; the instance is per-Scene, which is the isolation that
|
|
2235
2245
|
* actually matters.
|
|
2236
2246
|
*/
|
|
2237
|
-
|
|
2247
|
+
__init109() {this._wasmRuntime = null}
|
|
2238
2248
|
/**
|
|
2239
2249
|
* Load (or reuse) this Scene's shared WASM runtime.
|
|
2240
2250
|
*
|
|
@@ -2262,30 +2272,30 @@ var Scene = (_class7 = class _Scene {
|
|
|
2262
2272
|
get wasmRuntime() {
|
|
2263
2273
|
return this._wasmRuntime;
|
|
2264
2274
|
}
|
|
2265
|
-
|
|
2275
|
+
__init110() {this._hitWasm = null}
|
|
2266
2276
|
// Cache key: which frame + structure version the grid was last (successfully,
|
|
2267
2277
|
// non-overflowing) built for. findEntityAt is called ad-hoc (pointer
|
|
2268
2278
|
// hover/click), not every frame, so the grid is refreshed lazily on demand
|
|
2269
2279
|
// rather than proactively every render() — unlike the transform store, which
|
|
2270
2280
|
// every frame's draw depends on.
|
|
2271
|
-
|
|
2272
|
-
|
|
2273
|
-
|
|
2274
|
-
|
|
2281
|
+
__init111() {this._hitGridFrame = -1}
|
|
2282
|
+
__init112() {this._hitGridOk = false}
|
|
2283
|
+
__init113() {this._hitSlotEntity = []}
|
|
2284
|
+
__init114() {this._hitBoundless = []}
|
|
2275
2285
|
/** Reused buffer for the fused gather, so a pointer query allocates nothing. */
|
|
2276
|
-
|
|
2286
|
+
__init115() {this._hitGatherBuffer = null}
|
|
2277
2287
|
/**
|
|
2278
2288
|
* Whether the last grid build sourced its AABBs from the WASM transform store
|
|
2279
2289
|
* rather than recomputing them in JS. Diagnostic only — both paths must
|
|
2280
2290
|
* produce the same entity for a given point.
|
|
2281
2291
|
*/
|
|
2282
|
-
|
|
2292
|
+
__init116() {this._hitFusedGather = false}
|
|
2283
2293
|
/**
|
|
2284
2294
|
* Whether `compute_aabbs` has run against the current frame's world matrices.
|
|
2285
2295
|
* The AABB pass is only meaningful after a `compose_*`, so the fused gather
|
|
2286
2296
|
* must not read the views before then.
|
|
2287
2297
|
*/
|
|
2288
|
-
|
|
2298
|
+
__init117() {this._wasmAabbsFresh = false}
|
|
2289
2299
|
/** Did the last hit-grid build use the fused (WASM-store) gather? */
|
|
2290
2300
|
get hitGatherPath() {
|
|
2291
2301
|
return this._hitFusedGather ? "fused" : "js";
|
|
@@ -2294,9 +2304,9 @@ var Scene = (_class7 = class _Scene {
|
|
|
2294
2304
|
* Why the transform accelerator did or did not run on the most recent frame.
|
|
2295
2305
|
* Written by the render walk and `_syncWasmStore`.
|
|
2296
2306
|
*/
|
|
2297
|
-
|
|
2307
|
+
__init118() {this._transformReason = "not-installed"}
|
|
2298
2308
|
/** Why the batched-driver accelerator did or did not run. */
|
|
2299
|
-
|
|
2309
|
+
__init119() {this._animReason = "not-installed"}
|
|
2300
2310
|
/**
|
|
2301
2311
|
* Why the hit-test accelerator did or did not serve the last pointer query.
|
|
2302
2312
|
* The grid is built lazily on demand, not every frame, so this describes the
|
|
@@ -2304,11 +2314,11 @@ var Scene = (_class7 = class _Scene {
|
|
|
2304
2314
|
* before a backend exists; `_ensureHitGrid` moves it to `'not-applicable'`
|
|
2305
2315
|
* once one is installed but nothing has queried yet.
|
|
2306
2316
|
*/
|
|
2307
|
-
|
|
2317
|
+
__init120() {this._hitReason = "not-installed"}
|
|
2308
2318
|
/** Why the particle accelerator did or did not run. */
|
|
2309
|
-
|
|
2319
|
+
__init121() {this._particleReason = "not-applicable"}
|
|
2310
2320
|
/** Which particle implementation actually simulated the most recent frame. */
|
|
2311
|
-
|
|
2321
|
+
__init122() {this._particlePath = "none"}
|
|
2312
2322
|
/**
|
|
2313
2323
|
* Per-frame status of every invisible accelerator: whether each is installed,
|
|
2314
2324
|
* whether it actually ran on the most recent frame, and why.
|
|
@@ -2468,25 +2478,25 @@ var Scene = (_class7 = class _Scene {
|
|
|
2468
2478
|
// EasingFn (which cannot cross into WASM) all fall through to it — WASM can
|
|
2469
2479
|
// only ever change *how* a driver is advanced, never *what* value it lands
|
|
2470
2480
|
// on.
|
|
2471
|
-
|
|
2481
|
+
__init123() {this._animWasm = null}
|
|
2472
2482
|
// Entities with at least one active driver, added by Entity._spawnDriver.
|
|
2473
2483
|
// Self-pruning: _tickBatchedDrivers drops an entry the first time it visits
|
|
2474
2484
|
// an entity whose drivers have since all completed or been removed. This is
|
|
2475
2485
|
// what lets the batch pass find its candidates in O(active drivers), not
|
|
2476
2486
|
// O(tree size) — the exact mistake G3's first integrated benchmark made.
|
|
2477
|
-
|
|
2487
|
+
__init124() {this._activeDriverEntities = /* @__PURE__ */ new Set()}
|
|
2478
2488
|
// Reused across frames instead of allocating a fresh array + N {entity,prop,
|
|
2479
2489
|
// driver} objects every call — the integrated benchmark
|
|
2480
2490
|
// (benchmarks/anim-wasm-scene) found that allocation churn was the
|
|
2481
2491
|
// dominant integrated cost, not the wasm kernel itself. Parallel arrays,
|
|
2482
2492
|
// truncated to the live count after each use so a stale tail slot never
|
|
2483
2493
|
// pins a no-longer-active entity/driver in memory.
|
|
2484
|
-
|
|
2485
|
-
|
|
2486
|
-
|
|
2487
|
-
|
|
2488
|
-
|
|
2489
|
-
|
|
2494
|
+
__init125() {this._springEntities = []}
|
|
2495
|
+
__init126() {this._springProps = []}
|
|
2496
|
+
__init127() {this._springDrivers = []}
|
|
2497
|
+
__init128() {this._tweenEntities = []}
|
|
2498
|
+
__init129() {this._tweenProps = []}
|
|
2499
|
+
__init130() {this._tweenDrivers = []}
|
|
2490
2500
|
/**
|
|
2491
2501
|
* Minimum number of batchable (spring, or named-easing tween) active drivers
|
|
2492
2502
|
* before a frame engages the WASM batch path at all; below it, every driver
|
|
@@ -2558,7 +2568,7 @@ var Scene = (_class7 = class _Scene {
|
|
|
2558
2568
|
* Setting {@link animDriverGateCount} overwrites all three, so existing code
|
|
2559
2569
|
* that tuned the single knob keeps working unchanged.
|
|
2560
2570
|
*/
|
|
2561
|
-
|
|
2571
|
+
__init131() {this._animBatchedLastFrame = false}
|
|
2562
2572
|
/**
|
|
2563
2573
|
* Whether the WASM batch path actually ran on the most recent frame.
|
|
2564
2574
|
*
|
|
@@ -2570,7 +2580,7 @@ var Scene = (_class7 = class _Scene {
|
|
|
2570
2580
|
get animBatchedLastFrame() {
|
|
2571
2581
|
return this._animBatchedLastFrame;
|
|
2572
2582
|
}
|
|
2573
|
-
|
|
2583
|
+
__init132() {this.animGate = {
|
|
2574
2584
|
spring: 128,
|
|
2575
2585
|
tween: 256,
|
|
2576
2586
|
mixed: 128
|
|
@@ -2608,7 +2618,7 @@ var Scene = (_class7 = class _Scene {
|
|
|
2608
2618
|
// (benchmarks/particle-wasm). f32 (matches the WGSL shader), bit-identical to
|
|
2609
2619
|
// a JS f32 reference oracle; updateCPU (f64) stays the permanent fallback when
|
|
2610
2620
|
// no backend is installed or a scene runs on WebGPU.
|
|
2611
|
-
|
|
2621
|
+
__init133() {this._particleWasm = null}
|
|
2612
2622
|
/** Which backend runs the CPU particle simulation. Reflects only whether a
|
|
2613
2623
|
* backend is installed (the WebGPU compute path, when active, is used first
|
|
2614
2624
|
* regardless). */
|
|
@@ -2885,24 +2895,24 @@ var Scene = (_class7 = class _Scene {
|
|
|
2885
2895
|
* sync, so retaining the order prevents a newly opened overlay from spending
|
|
2886
2896
|
* its first frame below previously projected controls.
|
|
2887
2897
|
*/
|
|
2888
|
-
|
|
2898
|
+
__init134() {this.a11yRenderOrders = /* @__PURE__ */ new Map()}
|
|
2889
2899
|
// Optional WebGL point-cloud layer (see SceneOptions.pointBackend).
|
|
2890
|
-
|
|
2891
|
-
|
|
2892
|
-
|
|
2893
|
-
|
|
2900
|
+
__init135() {this.pointRenderer = null}
|
|
2901
|
+
__init136() {this.glCanvas = null}
|
|
2902
|
+
__init137() {this.glContextLostHandler = null}
|
|
2903
|
+
__init138() {this.glContextRestoredHandler = null}
|
|
2894
2904
|
|
|
2895
2905
|
|
|
2896
2906
|
|
|
2897
|
-
|
|
2907
|
+
__init139() {this.disableWindowResize = false}
|
|
2898
2908
|
/** See {@link SceneOptions.maxDPR}. `undefined` = uncapped (real DPR). */
|
|
2899
2909
|
|
|
2900
2910
|
// WebGPU properties
|
|
2901
|
-
|
|
2902
|
-
|
|
2903
|
-
|
|
2904
|
-
|
|
2905
|
-
|
|
2911
|
+
__init140() {this.destroyed = false}
|
|
2912
|
+
__init141() {this.device = null}
|
|
2913
|
+
__init142() {this.deviceLost = false}
|
|
2914
|
+
__init143() {this.particleBackend = "auto"}
|
|
2915
|
+
__init144() {this._webgpuDisabled = false}
|
|
2906
2916
|
get webgpuDisabled() {
|
|
2907
2917
|
return this._webgpuDisabled || this.particleBackend === "cpu";
|
|
2908
2918
|
}
|
|
@@ -2930,22 +2940,22 @@ var Scene = (_class7 = class _Scene {
|
|
|
2930
2940
|
set webgpuDisabled(value) {
|
|
2931
2941
|
this._webgpuDisabled = value;
|
|
2932
2942
|
}
|
|
2933
|
-
|
|
2934
|
-
|
|
2935
|
-
|
|
2936
|
-
|
|
2937
|
-
|
|
2943
|
+
__init145() {this.recoveryTimerId = null}
|
|
2944
|
+
__init146() {this.manager = null}
|
|
2945
|
+
__init147() {this.initializingWebGPU = false}
|
|
2946
|
+
__init148() {this.gpuCanvas = null}
|
|
2947
|
+
__init149() {this.gpuContext = null}
|
|
2938
2948
|
/** True while the GPU canvas holds a presented particle frame (needs clearing when they leave). */
|
|
2939
|
-
|
|
2940
|
-
|
|
2941
|
-
|
|
2942
|
-
|
|
2943
|
-
|
|
2949
|
+
__init150() {this.gpuHasContent = false}
|
|
2950
|
+
__init151() {this.mouseX = -9999}
|
|
2951
|
+
__init152() {this.mouseY = -9999}
|
|
2952
|
+
__init153() {this.pointerMoveListener = null}
|
|
2953
|
+
__init154() {this.pointerLeaveListener = null}
|
|
2944
2954
|
/** Element the pointer listeners are bound to (parent container if present,
|
|
2945
2955
|
* else the canvas). Stored so `destroy()` detaches from the same element. */
|
|
2946
|
-
|
|
2947
|
-
|
|
2948
|
-
|
|
2956
|
+
__init155() {this.pointerEventTarget = null}
|
|
2957
|
+
__init156() {this.hasWarnedZeroSize = false}
|
|
2958
|
+
__init157() {this.fontLoadHandler = null}
|
|
2949
2959
|
// ── Dev-mode warning infrastructure ──────────────────────────────
|
|
2950
2960
|
//
|
|
2951
2961
|
// Enable with `Scene.devMode = true` or by setting `globalThis.__DEV__`.
|
|
@@ -2979,7 +2989,7 @@ var Scene = (_class7 = class _Scene {
|
|
|
2979
2989
|
return false;
|
|
2980
2990
|
}
|
|
2981
2991
|
|
|
2982
|
-
|
|
2992
|
+
__init158() {this._devFrameCount = 0}
|
|
2983
2993
|
_devWarn(message) {
|
|
2984
2994
|
if (!this._devActive) return;
|
|
2985
2995
|
console.warn(`[vectojs/dev] ${message}`);
|
|
@@ -3056,7 +3066,7 @@ var Scene = (_class7 = class _Scene {
|
|
|
3056
3066
|
};
|
|
3057
3067
|
walkProjections(this.root);
|
|
3058
3068
|
}
|
|
3059
|
-
constructor(canvas, options = {}) {;_class7.prototype.__init27.call(this);_class7.prototype.__init28.call(this);_class7.prototype.__init29.call(this);_class7.prototype.__init30.call(this);_class7.prototype.__init31.call(this);_class7.prototype.__init32.call(this);_class7.prototype.__init33.call(this);_class7.prototype.__init34.call(this);_class7.prototype.__init35.call(this);_class7.prototype.__init36.call(this);_class7.prototype.__init37.call(this);_class7.prototype.__init38.call(this);_class7.prototype.__init39.call(this);_class7.prototype.__init40.call(this);_class7.prototype.__init41.call(this);_class7.prototype.__init42.call(this);_class7.prototype.__init43.call(this);_class7.prototype.__init44.call(this);_class7.prototype.__init45.call(this);_class7.prototype.__init46.call(this);_class7.prototype.__init47.call(this);_class7.prototype.__init48.call(this);_class7.prototype.__init49.call(this);_class7.prototype.__init50.call(this);_class7.prototype.__init51.call(this);_class7.prototype.__init52.call(this);_class7.prototype.__init53.call(this);_class7.prototype.__init54.call(this);_class7.prototype.__init55.call(this);_class7.prototype.__init56.call(this);_class7.prototype.__init57.call(this);_class7.prototype.__init58.call(this);_class7.prototype.__init59.call(this);_class7.prototype.__init60.call(this);_class7.prototype.__init61.call(this);_class7.prototype.__init62.call(this);_class7.prototype.__init63.call(this);_class7.prototype.__init64.call(this);_class7.prototype.__init65.call(this);_class7.prototype.__init66.call(this);_class7.prototype.__init67.call(this);_class7.prototype.__init68.call(this);_class7.prototype.__init69.call(this);_class7.prototype.__init70.call(this);_class7.prototype.__init71.call(this);_class7.prototype.__init72.call(this);_class7.prototype.__init73.call(this);_class7.prototype.__init74.call(this);_class7.prototype.__init75.call(this);_class7.prototype.__init76.call(this);_class7.prototype.__init77.call(this);_class7.prototype.__init78.call(this);_class7.prototype.__init79.call(this);_class7.prototype.__init80.call(this);_class7.prototype.__init81.call(this);_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);_class7.prototype.__init92.call(this);_class7.prototype.__init93.call(this);_class7.prototype.__init94.call(this);_class7.prototype.__init95.call(this);_class7.prototype.__init96.call(this);_class7.prototype.__init97.call(this);_class7.prototype.__init98.call(this);_class7.prototype.__init99.call(this);_class7.prototype.__init100.call(this);_class7.prototype.__init101.call(this);_class7.prototype.__init102.call(this);_class7.prototype.__init103.call(this);_class7.prototype.__init104.call(this);_class7.prototype.__init105.call(this);_class7.prototype.__init106.call(this);_class7.prototype.__init107.call(this);_class7.prototype.__init108.call(this);_class7.prototype.__init109.call(this);_class7.prototype.__init110.call(this);_class7.prototype.__init111.call(this);_class7.prototype.__init112.call(this);_class7.prototype.__init113.call(this);_class7.prototype.__init114.call(this);_class7.prototype.__init115.call(this);_class7.prototype.__init116.call(this);_class7.prototype.__init117.call(this);_class7.prototype.__init118.call(this);_class7.prototype.__init119.call(this);_class7.prototype.__init120.call(this);_class7.prototype.__init121.call(this);_class7.prototype.__init122.call(this);_class7.prototype.__init123.call(this);_class7.prototype.__init124.call(this);_class7.prototype.__init125.call(this);_class7.prototype.__init126.call(this);_class7.prototype.__init127.call(this);_class7.prototype.__init128.call(this);_class7.prototype.__init129.call(this);_class7.prototype.__init130.call(this);_class7.prototype.__init131.call(this);_class7.prototype.__init132.call(this);_class7.prototype.__init133.call(this);_class7.prototype.__init134.call(this);_class7.prototype.__init135.call(this);_class7.prototype.__init136.call(this);_class7.prototype.__init137.call(this);_class7.prototype.__init138.call(this);_class7.prototype.__init139.call(this);_class7.prototype.__init140.call(this);_class7.prototype.__init141.call(this);_class7.prototype.__init142.call(this);_class7.prototype.__init143.call(this);_class7.prototype.__init144.call(this);_class7.prototype.__init145.call(this);_class7.prototype.__init146.call(this);_class7.prototype.__init147.call(this);_class7.prototype.__init148.call(this);_class7.prototype.__init149.call(this);_class7.prototype.__init150.call(this);_class7.prototype.__init151.call(this);_class7.prototype.__init152.call(this);_class7.prototype.__init153.call(this);_class7.prototype.__init154.call(this);_class7.prototype.__init155.call(this);_class7.prototype.__init156.call(this);_class7.prototype.__init157.call(this);
|
|
3069
|
+
constructor(canvas, options = {}) {;_class7.prototype.__init27.call(this);_class7.prototype.__init28.call(this);_class7.prototype.__init29.call(this);_class7.prototype.__init30.call(this);_class7.prototype.__init31.call(this);_class7.prototype.__init32.call(this);_class7.prototype.__init33.call(this);_class7.prototype.__init34.call(this);_class7.prototype.__init35.call(this);_class7.prototype.__init36.call(this);_class7.prototype.__init37.call(this);_class7.prototype.__init38.call(this);_class7.prototype.__init39.call(this);_class7.prototype.__init40.call(this);_class7.prototype.__init41.call(this);_class7.prototype.__init42.call(this);_class7.prototype.__init43.call(this);_class7.prototype.__init44.call(this);_class7.prototype.__init45.call(this);_class7.prototype.__init46.call(this);_class7.prototype.__init47.call(this);_class7.prototype.__init48.call(this);_class7.prototype.__init49.call(this);_class7.prototype.__init50.call(this);_class7.prototype.__init51.call(this);_class7.prototype.__init52.call(this);_class7.prototype.__init53.call(this);_class7.prototype.__init54.call(this);_class7.prototype.__init55.call(this);_class7.prototype.__init56.call(this);_class7.prototype.__init57.call(this);_class7.prototype.__init58.call(this);_class7.prototype.__init59.call(this);_class7.prototype.__init60.call(this);_class7.prototype.__init61.call(this);_class7.prototype.__init62.call(this);_class7.prototype.__init63.call(this);_class7.prototype.__init64.call(this);_class7.prototype.__init65.call(this);_class7.prototype.__init66.call(this);_class7.prototype.__init67.call(this);_class7.prototype.__init68.call(this);_class7.prototype.__init69.call(this);_class7.prototype.__init70.call(this);_class7.prototype.__init71.call(this);_class7.prototype.__init72.call(this);_class7.prototype.__init73.call(this);_class7.prototype.__init74.call(this);_class7.prototype.__init75.call(this);_class7.prototype.__init76.call(this);_class7.prototype.__init77.call(this);_class7.prototype.__init78.call(this);_class7.prototype.__init79.call(this);_class7.prototype.__init80.call(this);_class7.prototype.__init81.call(this);_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);_class7.prototype.__init92.call(this);_class7.prototype.__init93.call(this);_class7.prototype.__init94.call(this);_class7.prototype.__init95.call(this);_class7.prototype.__init96.call(this);_class7.prototype.__init97.call(this);_class7.prototype.__init98.call(this);_class7.prototype.__init99.call(this);_class7.prototype.__init100.call(this);_class7.prototype.__init101.call(this);_class7.prototype.__init102.call(this);_class7.prototype.__init103.call(this);_class7.prototype.__init104.call(this);_class7.prototype.__init105.call(this);_class7.prototype.__init106.call(this);_class7.prototype.__init107.call(this);_class7.prototype.__init108.call(this);_class7.prototype.__init109.call(this);_class7.prototype.__init110.call(this);_class7.prototype.__init111.call(this);_class7.prototype.__init112.call(this);_class7.prototype.__init113.call(this);_class7.prototype.__init114.call(this);_class7.prototype.__init115.call(this);_class7.prototype.__init116.call(this);_class7.prototype.__init117.call(this);_class7.prototype.__init118.call(this);_class7.prototype.__init119.call(this);_class7.prototype.__init120.call(this);_class7.prototype.__init121.call(this);_class7.prototype.__init122.call(this);_class7.prototype.__init123.call(this);_class7.prototype.__init124.call(this);_class7.prototype.__init125.call(this);_class7.prototype.__init126.call(this);_class7.prototype.__init127.call(this);_class7.prototype.__init128.call(this);_class7.prototype.__init129.call(this);_class7.prototype.__init130.call(this);_class7.prototype.__init131.call(this);_class7.prototype.__init132.call(this);_class7.prototype.__init133.call(this);_class7.prototype.__init134.call(this);_class7.prototype.__init135.call(this);_class7.prototype.__init136.call(this);_class7.prototype.__init137.call(this);_class7.prototype.__init138.call(this);_class7.prototype.__init139.call(this);_class7.prototype.__init140.call(this);_class7.prototype.__init141.call(this);_class7.prototype.__init142.call(this);_class7.prototype.__init143.call(this);_class7.prototype.__init144.call(this);_class7.prototype.__init145.call(this);_class7.prototype.__init146.call(this);_class7.prototype.__init147.call(this);_class7.prototype.__init148.call(this);_class7.prototype.__init149.call(this);_class7.prototype.__init150.call(this);_class7.prototype.__init151.call(this);_class7.prototype.__init152.call(this);_class7.prototype.__init153.call(this);_class7.prototype.__init154.call(this);_class7.prototype.__init155.call(this);_class7.prototype.__init156.call(this);_class7.prototype.__init157.call(this);_class7.prototype.__init158.call(this);
|
|
3060
3070
|
this.canvas = canvas;
|
|
3061
3071
|
this.debugA11y = _nullishCoalesce(options.debugA11y, () => ( false));
|
|
3062
3072
|
this.disableWindowResize = _nullishCoalesce(options.disableWindowResize, () => ( false));
|
|
@@ -5170,12 +5180,14 @@ var Scene = (_class7 = class _Scene {
|
|
|
5170
5180
|
this.fullViewportElements.length = 0;
|
|
5171
5181
|
this.normalElements.length = 0;
|
|
5172
5182
|
this.activeIds.clear();
|
|
5173
|
-
|
|
5183
|
+
this.a11yOrderRegions.clear();
|
|
5184
|
+
const collect = (node, region) => {
|
|
5174
5185
|
if (node.isDOMPortal) return;
|
|
5175
5186
|
const contentEl = this.contentElements.get(node.id);
|
|
5176
5187
|
if (contentEl) {
|
|
5177
5188
|
if (node.a11yFullViewport) this.fullViewportElements.push(contentEl);
|
|
5178
5189
|
else this.normalElements.push(contentEl);
|
|
5190
|
+
if (region) this.a11yOrderRegions.set(contentEl, region);
|
|
5179
5191
|
}
|
|
5180
5192
|
if (this.shouldProjectA11y(node)) {
|
|
5181
5193
|
const el = this.a11yElements.get(node.id);
|
|
@@ -5183,14 +5195,16 @@ var Scene = (_class7 = class _Scene {
|
|
|
5183
5195
|
this.activeIds.add(node.id);
|
|
5184
5196
|
if (node.a11yFullViewport) this.fullViewportElements.push(el);
|
|
5185
5197
|
else this.normalElements.push(el);
|
|
5198
|
+
if (region) this.a11yOrderRegions.set(el, region);
|
|
5186
5199
|
}
|
|
5187
5200
|
}
|
|
5188
|
-
|
|
5201
|
+
const childRegion = node.clipChildren && node.width > 0 && node.height > 0 ? node : region;
|
|
5202
|
+
for (const child of node.children) collect(child, childRegion);
|
|
5189
5203
|
if (node === this.root) {
|
|
5190
|
-
for (const overlay of this.overlayRoot.children) collect(overlay);
|
|
5204
|
+
for (const overlay of this.overlayRoot.children) collect(overlay, null);
|
|
5191
5205
|
}
|
|
5192
5206
|
};
|
|
5193
|
-
collect(this.root);
|
|
5207
|
+
collect(this.root, null);
|
|
5194
5208
|
let elementsPruned = false;
|
|
5195
5209
|
for (const [id, el] of this.a11yElements.entries()) {
|
|
5196
5210
|
if (!this.activeIds.has(id)) {
|
|
@@ -5252,6 +5266,18 @@ var Scene = (_class7 = class _Scene {
|
|
|
5252
5266
|
* parents, which no `insertBefore` ever acts on. Normalizing everything back
|
|
5253
5267
|
* to world coordinates here would cost a transform per element per frame to
|
|
5254
5268
|
* change nothing observable.
|
|
5269
|
+
*
|
|
5270
|
+
* Banding runs **per region** — per nearest `clipChildren` ancestor, recorded
|
|
5271
|
+
* by {@link enforceA11yDomOrder}'s collect walk — rather than once over the
|
|
5272
|
+
* whole scene. Purely visual banding is right for a screen reader but wrong
|
|
5273
|
+
* for selection: a DOM `Selection` covers everything between anchor and focus
|
|
5274
|
+
* in DOM order, so under one global banding a vertical drag through a
|
|
5275
|
+
* transcript also swallowed a sidebar whose headings happened to fall in the
|
|
5276
|
+
* same rows. Regions are laid out side by side, so ordering region-major keeps
|
|
5277
|
+
* each one a contiguous DOM run and a drag stays inside it, while reading
|
|
5278
|
+
* order *within* a region is unchanged. Regions are emitted in the order their
|
|
5279
|
+
* clipper is first reached by the depth-first walk, so a screen reader still
|
|
5280
|
+
* meets them in the author's declared order.
|
|
5255
5281
|
*/
|
|
5256
5282
|
sortNormalElementsVisually() {
|
|
5257
5283
|
const els = this.normalElements;
|
|
@@ -5279,30 +5305,40 @@ var Scene = (_class7 = class _Scene {
|
|
|
5279
5305
|
}
|
|
5280
5306
|
return { top, left };
|
|
5281
5307
|
};
|
|
5282
|
-
const
|
|
5308
|
+
const decorated = els.map((el, i) => {
|
|
5283
5309
|
const { top, left } = absolute(el);
|
|
5284
5310
|
return { el, i, top, left, container: containers.has(el) };
|
|
5285
5311
|
});
|
|
5286
|
-
|
|
5312
|
+
const regions = this.a11yOrderRegions;
|
|
5313
|
+
const buckets = /* @__PURE__ */ new Map();
|
|
5314
|
+
for (const d of decorated) {
|
|
5315
|
+
const key = _nullishCoalesce(regions.get(d.el), () => ( null));
|
|
5316
|
+
const bucket = buckets.get(key);
|
|
5317
|
+
if (bucket) bucket.push(d);
|
|
5318
|
+
else buckets.set(key, [d]);
|
|
5319
|
+
}
|
|
5287
5320
|
const bandBottom = (r) => r.top + (r.container ? 4 : heightOf(r.el));
|
|
5288
5321
|
const sorted = [];
|
|
5289
|
-
|
|
5290
|
-
|
|
5291
|
-
|
|
5292
|
-
|
|
5293
|
-
|
|
5294
|
-
|
|
5295
|
-
|
|
5296
|
-
|
|
5297
|
-
|
|
5298
|
-
|
|
5299
|
-
|
|
5300
|
-
|
|
5301
|
-
|
|
5302
|
-
|
|
5322
|
+
for (const order of buckets.values()) {
|
|
5323
|
+
order.sort((p, q) => p.top - q.top || p.i - q.i);
|
|
5324
|
+
let rowStart = 0;
|
|
5325
|
+
let rowBottom = order.length ? bandBottom(order[0]) : 0;
|
|
5326
|
+
const flushRow = (end) => {
|
|
5327
|
+
const row = order.slice(rowStart, end);
|
|
5328
|
+
row.sort((p, q) => (rtl ? q.left - p.left : p.left - q.left) || p.i - q.i);
|
|
5329
|
+
for (const r of row) sorted.push(r.el);
|
|
5330
|
+
};
|
|
5331
|
+
for (let k = 1; k < order.length; k++) {
|
|
5332
|
+
if (order[k].top < rowBottom) {
|
|
5333
|
+
rowBottom = Math.max(rowBottom, bandBottom(order[k]));
|
|
5334
|
+
} else {
|
|
5335
|
+
flushRow(k);
|
|
5336
|
+
rowStart = k;
|
|
5337
|
+
rowBottom = bandBottom(order[k]);
|
|
5338
|
+
}
|
|
5303
5339
|
}
|
|
5340
|
+
flushRow(order.length);
|
|
5304
5341
|
}
|
|
5305
|
-
flushRow(order.length);
|
|
5306
5342
|
for (let i = 0; i < sorted.length; i++) els[i] = sorted[i];
|
|
5307
5343
|
}
|
|
5308
5344
|
/** Keep DOM/WebGL overlay layers aligned with the canvas's CSS box. */
|
|
@@ -6237,17 +6273,17 @@ var TextEntity = (_class8 = class extends _chunkTRT2TRCWjs.Entity {
|
|
|
6237
6273
|
|
|
6238
6274
|
|
|
6239
6275
|
|
|
6240
|
-
|
|
6276
|
+
__init159() {this.nodes = []}
|
|
6241
6277
|
|
|
6242
|
-
|
|
6243
|
-
|
|
6244
|
-
|
|
6245
|
-
|
|
6246
|
-
|
|
6278
|
+
__init160() {this.fillStyle = "#94a3b8"}
|
|
6279
|
+
__init161() {this.strokeStyle = null}
|
|
6280
|
+
__init162() {this.hoveredFillStyle = "#ffffff"}
|
|
6281
|
+
__init163() {this.lineWidth = 1}
|
|
6282
|
+
__init164() {this.isHovered = false}
|
|
6247
6283
|
/** Bumped by {@link applyLayout}; read by `Scene` to skip an unchanged sync. */
|
|
6248
|
-
|
|
6284
|
+
__init165() {this.contentEpoch = 0}
|
|
6249
6285
|
constructor(text, atlas, maxWidth, fontSize = 24) {
|
|
6250
|
-
super();_class8.prototype.
|
|
6286
|
+
super();_class8.prototype.__init159.call(this);_class8.prototype.__init160.call(this);_class8.prototype.__init161.call(this);_class8.prototype.__init162.call(this);_class8.prototype.__init163.call(this);_class8.prototype.__init164.call(this);_class8.prototype.__init165.call(this);;
|
|
6251
6287
|
this.text = text;
|
|
6252
6288
|
this.atlas = atlas;
|
|
6253
6289
|
this.fontSize = fontSize;
|
|
@@ -6366,15 +6402,15 @@ var TextEntity = (_class8 = class extends _chunkTRT2TRCWjs.Entity {
|
|
|
6366
6402
|
// src/components/GridTextEntity.ts
|
|
6367
6403
|
var GridTextEntity = (_class9 = class extends _chunkTRT2TRCWjs.Entity {
|
|
6368
6404
|
|
|
6369
|
-
|
|
6370
|
-
|
|
6405
|
+
__init166() {this.fillStyle = "#ffffff"}
|
|
6406
|
+
__init167() {this.grid = []}
|
|
6371
6407
|
// Array of rows
|
|
6372
|
-
|
|
6373
|
-
|
|
6408
|
+
__init168() {this.cols = 0}
|
|
6409
|
+
__init169() {this.rows = 0}
|
|
6374
6410
|
|
|
6375
6411
|
|
|
6376
6412
|
constructor(_atlas, fontSize = 10) {
|
|
6377
|
-
super();_class9.prototype.
|
|
6413
|
+
super();_class9.prototype.__init166.call(this);_class9.prototype.__init167.call(this);_class9.prototype.__init168.call(this);_class9.prototype.__init169.call(this);;
|
|
6378
6414
|
this.fontSize = fontSize;
|
|
6379
6415
|
this.charWidth = fontSize * 1;
|
|
6380
6416
|
this.charHeight = fontSize * 1.1;
|
|
@@ -6466,23 +6502,23 @@ var SplineEntity = (_class10 = class extends _chunkTRT2TRCWjs.Entity {
|
|
|
6466
6502
|
|
|
6467
6503
|
|
|
6468
6504
|
|
|
6469
|
-
|
|
6470
|
-
|
|
6505
|
+
__init170() {this.offscreen = null}
|
|
6506
|
+
__init171() {this.baked = false}
|
|
6471
6507
|
/** Logical (CSS-pixel) size of the baked bitmap — the blit destination size. */
|
|
6472
|
-
|
|
6473
|
-
|
|
6508
|
+
__init172() {this.bakedWidth = 0}
|
|
6509
|
+
__init173() {this.bakedHeight = 0}
|
|
6474
6510
|
/** Gradient strokes can't be baked to a solid-color bitmap; they render per-frame. */
|
|
6475
6511
|
|
|
6476
6512
|
/** Lazily-flattened polylines (one Float32Array of [x,y,...] per segment) for hit-testing. */
|
|
6477
|
-
|
|
6513
|
+
__init174() {this.polylines = null}
|
|
6478
6514
|
/**
|
|
6479
6515
|
* When `true`, the renderer draws a rounded-rect outline of the entity's
|
|
6480
6516
|
* local bounds after painting the curves. Useful for drag feedback and
|
|
6481
6517
|
* debugging hit areas. Defaults to `false`.
|
|
6482
6518
|
*/
|
|
6483
|
-
|
|
6519
|
+
__init175() {this.showBounds = false}
|
|
6484
6520
|
constructor(doc, opts = {}) {
|
|
6485
|
-
super();_class10.prototype.
|
|
6521
|
+
super();_class10.prototype.__init170.call(this);_class10.prototype.__init171.call(this);_class10.prototype.__init172.call(this);_class10.prototype.__init173.call(this);_class10.prototype.__init174.call(this);_class10.prototype.__init175.call(this);;
|
|
6486
6522
|
this.doc = doc;
|
|
6487
6523
|
this.lineWidth = _nullishCoalesce(opts.lineWidth, () => ( 2));
|
|
6488
6524
|
this.cache = _nullishCoalesce(opts.cache, () => ( true));
|
|
@@ -6863,19 +6899,19 @@ var _math = require('@vectojs/math'); _createStarExport(_math);
|
|
|
6863
6899
|
// src/tree/DOMPortalEntity.ts
|
|
6864
6900
|
var DOMPortalEntity = (_class11 = class extends _chunkTRT2TRCWjs.Entity {
|
|
6865
6901
|
|
|
6866
|
-
|
|
6867
|
-
|
|
6868
|
-
|
|
6869
|
-
|
|
6870
|
-
|
|
6871
|
-
|
|
6872
|
-
|
|
6873
|
-
|
|
6874
|
-
|
|
6875
|
-
|
|
6876
|
-
|
|
6902
|
+
__init176() {this.isDOMPortal = true}
|
|
6903
|
+
__init177() {this.domListeners = []}
|
|
6904
|
+
__init178() {this.resizeObserver = null}
|
|
6905
|
+
__init179() {this.domBound = false}
|
|
6906
|
+
__init180() {this.cachedWidth = 100}
|
|
6907
|
+
__init181() {this.cachedHeight = 100}
|
|
6908
|
+
__init182() {this.lastWidth = ""}
|
|
6909
|
+
__init183() {this.lastHeight = ""}
|
|
6910
|
+
__init184() {this.lastTransform = ""}
|
|
6911
|
+
__init185() {this.lastZIndex = ""}
|
|
6912
|
+
__init186() {this.lastOpacity = ""}
|
|
6877
6913
|
constructor(domElement, width, height, id) {
|
|
6878
|
-
super(id);_class11.prototype.
|
|
6914
|
+
super(id);_class11.prototype.__init176.call(this);_class11.prototype.__init177.call(this);_class11.prototype.__init178.call(this);_class11.prototype.__init179.call(this);_class11.prototype.__init180.call(this);_class11.prototype.__init181.call(this);_class11.prototype.__init182.call(this);_class11.prototype.__init183.call(this);_class11.prototype.__init184.call(this);_class11.prototype.__init185.call(this);_class11.prototype.__init186.call(this);;
|
|
6879
6915
|
this.domElement = domElement;
|
|
6880
6916
|
this.width = _nullishCoalesce(width, () => ( 0));
|
|
6881
6917
|
this.height = _nullishCoalesce(height, () => ( 0));
|
package/dist/index.mjs
CHANGED
|
@@ -2111,6 +2111,16 @@ var Scene = class _Scene {
|
|
|
2111
2111
|
* see {@link sortNormalElementsVisually}.
|
|
2112
2112
|
*/
|
|
2113
2113
|
a11yOrderContainers = /* @__PURE__ */ new Set();
|
|
2114
|
+
/**
|
|
2115
|
+
* Nearest `clipChildren` ancestor per ordered element — its *region* — reused
|
|
2116
|
+
* per pass. Written by `enforceA11yDomOrder`'s collect walk, which already has
|
|
2117
|
+
* the entity in hand, so a region costs one comparison per node rather than an
|
|
2118
|
+
* ancestor walk per element.
|
|
2119
|
+
*
|
|
2120
|
+
* Absent means the element sits under no clipping ancestor and belongs to the
|
|
2121
|
+
* implicit root region. See {@link sortNormalElementsVisually}.
|
|
2122
|
+
*/
|
|
2123
|
+
a11yOrderRegions = /* @__PURE__ */ new Map();
|
|
2114
2124
|
activePortalsThisFrame = /* @__PURE__ */ new Set();
|
|
2115
2125
|
activePortalsPrevFrame = /* @__PURE__ */ new Set();
|
|
2116
2126
|
portalEntities = /* @__PURE__ */ new Map();
|
|
@@ -5169,12 +5179,14 @@ var Scene = class _Scene {
|
|
|
5169
5179
|
this.fullViewportElements.length = 0;
|
|
5170
5180
|
this.normalElements.length = 0;
|
|
5171
5181
|
this.activeIds.clear();
|
|
5172
|
-
|
|
5182
|
+
this.a11yOrderRegions.clear();
|
|
5183
|
+
const collect = (node, region) => {
|
|
5173
5184
|
if (node.isDOMPortal) return;
|
|
5174
5185
|
const contentEl = this.contentElements.get(node.id);
|
|
5175
5186
|
if (contentEl) {
|
|
5176
5187
|
if (node.a11yFullViewport) this.fullViewportElements.push(contentEl);
|
|
5177
5188
|
else this.normalElements.push(contentEl);
|
|
5189
|
+
if (region) this.a11yOrderRegions.set(contentEl, region);
|
|
5178
5190
|
}
|
|
5179
5191
|
if (this.shouldProjectA11y(node)) {
|
|
5180
5192
|
const el = this.a11yElements.get(node.id);
|
|
@@ -5182,14 +5194,16 @@ var Scene = class _Scene {
|
|
|
5182
5194
|
this.activeIds.add(node.id);
|
|
5183
5195
|
if (node.a11yFullViewport) this.fullViewportElements.push(el);
|
|
5184
5196
|
else this.normalElements.push(el);
|
|
5197
|
+
if (region) this.a11yOrderRegions.set(el, region);
|
|
5185
5198
|
}
|
|
5186
5199
|
}
|
|
5187
|
-
|
|
5200
|
+
const childRegion = node.clipChildren && node.width > 0 && node.height > 0 ? node : region;
|
|
5201
|
+
for (const child of node.children) collect(child, childRegion);
|
|
5188
5202
|
if (node === this.root) {
|
|
5189
|
-
for (const overlay of this.overlayRoot.children) collect(overlay);
|
|
5203
|
+
for (const overlay of this.overlayRoot.children) collect(overlay, null);
|
|
5190
5204
|
}
|
|
5191
5205
|
};
|
|
5192
|
-
collect(this.root);
|
|
5206
|
+
collect(this.root, null);
|
|
5193
5207
|
let elementsPruned = false;
|
|
5194
5208
|
for (const [id, el] of this.a11yElements.entries()) {
|
|
5195
5209
|
if (!this.activeIds.has(id)) {
|
|
@@ -5251,6 +5265,18 @@ var Scene = class _Scene {
|
|
|
5251
5265
|
* parents, which no `insertBefore` ever acts on. Normalizing everything back
|
|
5252
5266
|
* to world coordinates here would cost a transform per element per frame to
|
|
5253
5267
|
* change nothing observable.
|
|
5268
|
+
*
|
|
5269
|
+
* Banding runs **per region** — per nearest `clipChildren` ancestor, recorded
|
|
5270
|
+
* by {@link enforceA11yDomOrder}'s collect walk — rather than once over the
|
|
5271
|
+
* whole scene. Purely visual banding is right for a screen reader but wrong
|
|
5272
|
+
* for selection: a DOM `Selection` covers everything between anchor and focus
|
|
5273
|
+
* in DOM order, so under one global banding a vertical drag through a
|
|
5274
|
+
* transcript also swallowed a sidebar whose headings happened to fall in the
|
|
5275
|
+
* same rows. Regions are laid out side by side, so ordering region-major keeps
|
|
5276
|
+
* each one a contiguous DOM run and a drag stays inside it, while reading
|
|
5277
|
+
* order *within* a region is unchanged. Regions are emitted in the order their
|
|
5278
|
+
* clipper is first reached by the depth-first walk, so a screen reader still
|
|
5279
|
+
* meets them in the author's declared order.
|
|
5254
5280
|
*/
|
|
5255
5281
|
sortNormalElementsVisually() {
|
|
5256
5282
|
const els = this.normalElements;
|
|
@@ -5278,30 +5304,40 @@ var Scene = class _Scene {
|
|
|
5278
5304
|
}
|
|
5279
5305
|
return { top, left };
|
|
5280
5306
|
};
|
|
5281
|
-
const
|
|
5307
|
+
const decorated = els.map((el, i) => {
|
|
5282
5308
|
const { top, left } = absolute(el);
|
|
5283
5309
|
return { el, i, top, left, container: containers.has(el) };
|
|
5284
5310
|
});
|
|
5285
|
-
|
|
5311
|
+
const regions = this.a11yOrderRegions;
|
|
5312
|
+
const buckets = /* @__PURE__ */ new Map();
|
|
5313
|
+
for (const d of decorated) {
|
|
5314
|
+
const key = regions.get(d.el) ?? null;
|
|
5315
|
+
const bucket = buckets.get(key);
|
|
5316
|
+
if (bucket) bucket.push(d);
|
|
5317
|
+
else buckets.set(key, [d]);
|
|
5318
|
+
}
|
|
5286
5319
|
const bandBottom = (r) => r.top + (r.container ? 4 : heightOf(r.el));
|
|
5287
5320
|
const sorted = [];
|
|
5288
|
-
|
|
5289
|
-
|
|
5290
|
-
|
|
5291
|
-
|
|
5292
|
-
|
|
5293
|
-
|
|
5294
|
-
|
|
5295
|
-
|
|
5296
|
-
|
|
5297
|
-
|
|
5298
|
-
|
|
5299
|
-
|
|
5300
|
-
|
|
5301
|
-
|
|
5321
|
+
for (const order of buckets.values()) {
|
|
5322
|
+
order.sort((p, q) => p.top - q.top || p.i - q.i);
|
|
5323
|
+
let rowStart = 0;
|
|
5324
|
+
let rowBottom = order.length ? bandBottom(order[0]) : 0;
|
|
5325
|
+
const flushRow = (end) => {
|
|
5326
|
+
const row = order.slice(rowStart, end);
|
|
5327
|
+
row.sort((p, q) => (rtl ? q.left - p.left : p.left - q.left) || p.i - q.i);
|
|
5328
|
+
for (const r of row) sorted.push(r.el);
|
|
5329
|
+
};
|
|
5330
|
+
for (let k = 1; k < order.length; k++) {
|
|
5331
|
+
if (order[k].top < rowBottom) {
|
|
5332
|
+
rowBottom = Math.max(rowBottom, bandBottom(order[k]));
|
|
5333
|
+
} else {
|
|
5334
|
+
flushRow(k);
|
|
5335
|
+
rowStart = k;
|
|
5336
|
+
rowBottom = bandBottom(order[k]);
|
|
5337
|
+
}
|
|
5302
5338
|
}
|
|
5339
|
+
flushRow(order.length);
|
|
5303
5340
|
}
|
|
5304
|
-
flushRow(order.length);
|
|
5305
5341
|
for (let i = 0; i < sorted.length; i++) els[i] = sorted[i];
|
|
5306
5342
|
}
|
|
5307
5343
|
/** Keep DOM/WebGL overlay layers aligned with the canvas's CSS box. */
|
package/dist/tree/Scene.d.ts
CHANGED
|
@@ -719,6 +719,16 @@ export declare class Scene {
|
|
|
719
719
|
* see {@link sortNormalElementsVisually}.
|
|
720
720
|
*/
|
|
721
721
|
private a11yOrderContainers;
|
|
722
|
+
/**
|
|
723
|
+
* Nearest `clipChildren` ancestor per ordered element — its *region* — reused
|
|
724
|
+
* per pass. Written by `enforceA11yDomOrder`'s collect walk, which already has
|
|
725
|
+
* the entity in hand, so a region costs one comparison per node rather than an
|
|
726
|
+
* ancestor walk per element.
|
|
727
|
+
*
|
|
728
|
+
* Absent means the element sits under no clipping ancestor and belongs to the
|
|
729
|
+
* implicit root region. See {@link sortNormalElementsVisually}.
|
|
730
|
+
*/
|
|
731
|
+
private a11yOrderRegions;
|
|
722
732
|
private activePortalsThisFrame;
|
|
723
733
|
private activePortalsPrevFrame;
|
|
724
734
|
private portalEntities;
|
|
@@ -1609,6 +1619,18 @@ export declare class Scene {
|
|
|
1609
1619
|
* parents, which no `insertBefore` ever acts on. Normalizing everything back
|
|
1610
1620
|
* to world coordinates here would cost a transform per element per frame to
|
|
1611
1621
|
* change nothing observable.
|
|
1622
|
+
*
|
|
1623
|
+
* Banding runs **per region** — per nearest `clipChildren` ancestor, recorded
|
|
1624
|
+
* by {@link enforceA11yDomOrder}'s collect walk — rather than once over the
|
|
1625
|
+
* whole scene. Purely visual banding is right for a screen reader but wrong
|
|
1626
|
+
* for selection: a DOM `Selection` covers everything between anchor and focus
|
|
1627
|
+
* in DOM order, so under one global banding a vertical drag through a
|
|
1628
|
+
* transcript also swallowed a sidebar whose headings happened to fall in the
|
|
1629
|
+
* same rows. Regions are laid out side by side, so ordering region-major keeps
|
|
1630
|
+
* each one a contiguous DOM run and a drag stays inside it, while reading
|
|
1631
|
+
* order *within* a region is unchanged. Regions are emitted in the order their
|
|
1632
|
+
* clipper is first reached by the depth-first walk, so a screen reader still
|
|
1633
|
+
* meets them in the author's declared order.
|
|
1612
1634
|
*/
|
|
1613
1635
|
private sortNormalElementsVisually;
|
|
1614
1636
|
/** Keep DOM/WebGL overlay layers aligned with the canvas's CSS box. */
|