@vectojs/core 1.32.6 → 1.33.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -73,62 +73,66 @@ var VectoJSEvent = (_class = class {
73
73
  get deltaY() {
74
74
  return _optionalChain([this, 'access', _9 => _9.nativeEvent, 'optionalAccess', _10 => _10.deltaY]);
75
75
  }
76
+ /** Native wheel delta mode (0=pixels, 1=lines, 2=pages), if this wraps a `WheelEvent`. */
77
+ get deltaMode() {
78
+ return _optionalChain([this, 'access', _11 => _11.nativeEvent, 'optionalAccess', _12 => _12.deltaMode]);
79
+ }
76
80
  /** Native pointer X, if this wraps a pointer/mouse event. */
77
81
  get clientX() {
78
- return _optionalChain([this, 'access', _11 => _11.nativeEvent, 'optionalAccess', _12 => _12.clientX]);
82
+ return _optionalChain([this, 'access', _13 => _13.nativeEvent, 'optionalAccess', _14 => _14.clientX]);
79
83
  }
80
84
  /** Native pointer Y, if this wraps a pointer/mouse event. */
81
85
  get clientY() {
82
- return _optionalChain([this, 'access', _13 => _13.nativeEvent, 'optionalAccess', _14 => _14.clientY]);
86
+ return _optionalChain([this, 'access', _15 => _15.nativeEvent, 'optionalAccess', _16 => _16.clientY]);
83
87
  }
84
88
  get resolvedScenePoint() {
85
89
  if (this.explicitScenePoint) return this.explicitScenePoint;
86
90
  const native = this.nativeEvent;
87
- if (_optionalChain([native, 'optionalAccess', _15 => _15.vectoSceneX]) !== void 0 && native.vectoSceneY !== void 0) {
91
+ if (_optionalChain([native, 'optionalAccess', _17 => _17.vectoSceneX]) !== void 0 && native.vectoSceneY !== void 0) {
88
92
  return { x: native.vectoSceneX, y: native.vectoSceneY };
89
93
  }
90
- if (_optionalChain([native, 'optionalAccess', _16 => _16.clientX]) === void 0 || native.clientY === void 0) return void 0;
94
+ if (_optionalChain([native, 'optionalAccess', _18 => _18.clientX]) === void 0 || native.clientY === void 0) return void 0;
91
95
  const scene = this.target.scene;
92
- return _nullishCoalesce(_optionalChain([scene, 'optionalAccess', _17 => _17.clientToScene, 'optionalCall', _18 => _18(native.clientX, native.clientY)]), () => ( {
96
+ return _nullishCoalesce(_optionalChain([scene, 'optionalAccess', _19 => _19.clientToScene, 'optionalCall', _20 => _20(native.clientX, native.clientY)]), () => ( {
93
97
  x: native.clientX,
94
98
  y: native.clientY
95
99
  }));
96
100
  }
97
101
  /** Pointer X in the Scene's logical coordinate space. */
98
102
  get sceneX() {
99
- return _optionalChain([this, 'access', _19 => _19.resolvedScenePoint, 'optionalAccess', _20 => _20.x]);
103
+ return _optionalChain([this, 'access', _21 => _21.resolvedScenePoint, 'optionalAccess', _22 => _22.x]);
100
104
  }
101
105
  /** Pointer Y in the Scene's logical coordinate space. */
102
106
  get sceneY() {
103
- return _optionalChain([this, 'access', _21 => _21.resolvedScenePoint, 'optionalAccess', _22 => _22.y]);
107
+ return _optionalChain([this, 'access', _23 => _23.resolvedScenePoint, 'optionalAccess', _24 => _24.y]);
104
108
  }
105
109
  /** Pointer X local to the entity whose listener is currently running. */
106
110
  get localX() {
107
111
  const point = this.resolvedScenePoint;
108
112
  if (!point) return void 0;
109
- return _optionalChain([this, 'access', _23 => _23.currentTarget, 'access', _24 => _24.worldToLocal, 'call', _25 => _25(point.x, point.y), 'optionalAccess', _26 => _26.x]);
113
+ return _optionalChain([this, 'access', _25 => _25.currentTarget, 'access', _26 => _26.worldToLocal, 'call', _27 => _27(point.x, point.y), 'optionalAccess', _28 => _28.x]);
110
114
  }
111
115
  /** Pointer Y local to the entity whose listener is currently running. */
112
116
  get localY() {
113
117
  const point = this.resolvedScenePoint;
114
118
  if (!point) return void 0;
115
- return _optionalChain([this, 'access', _27 => _27.currentTarget, 'access', _28 => _28.worldToLocal, 'call', _29 => _29(point.x, point.y), 'optionalAccess', _30 => _30.y]);
119
+ return _optionalChain([this, 'access', _29 => _29.currentTarget, 'access', _30 => _30.worldToLocal, 'call', _31 => _31(point.x, point.y), 'optionalAccess', _32 => _32.y]);
116
120
  }
117
121
  get shiftKey() {
118
- return !!_optionalChain([this, 'access', _31 => _31.nativeEvent, 'optionalAccess', _32 => _32.shiftKey]);
122
+ return !!_optionalChain([this, 'access', _33 => _33.nativeEvent, 'optionalAccess', _34 => _34.shiftKey]);
119
123
  }
120
124
  get ctrlKey() {
121
- return !!_optionalChain([this, 'access', _33 => _33.nativeEvent, 'optionalAccess', _34 => _34.ctrlKey]);
125
+ return !!_optionalChain([this, 'access', _35 => _35.nativeEvent, 'optionalAccess', _36 => _36.ctrlKey]);
122
126
  }
123
127
  get altKey() {
124
- return !!_optionalChain([this, 'access', _35 => _35.nativeEvent, 'optionalAccess', _36 => _36.altKey]);
128
+ return !!_optionalChain([this, 'access', _37 => _37.nativeEvent, 'optionalAccess', _38 => _38.altKey]);
125
129
  }
126
130
  get metaKey() {
127
- return !!_optionalChain([this, 'access', _37 => _37.nativeEvent, 'optionalAccess', _38 => _38.metaKey]);
131
+ return !!_optionalChain([this, 'access', _39 => _39.nativeEvent, 'optionalAccess', _40 => _40.metaKey]);
128
132
  }
129
133
  /** Native key, if this wraps a keyboard event. */
130
134
  get key() {
131
- return _optionalChain([this, 'access', _39 => _39.nativeEvent, 'optionalAccess', _40 => _40.key]);
135
+ return _optionalChain([this, 'access', _41 => _41.nativeEvent, 'optionalAccess', _42 => _42.key]);
132
136
  }
133
137
  }, _class);
134
138
  var Entity = (_class2 = class {
@@ -318,13 +322,40 @@ var Entity = (_class2 = class {
318
322
  * fixed viewport. Off by default (children render unclipped). Canvas2D only.
319
323
  */
320
324
  __init36() {this.clipChildren = false}
325
+ /**
326
+ * Group this subtree's projected text into its own accessibility **region**,
327
+ * without clipping anything.
328
+ *
329
+ * The projection sorts every mirror into visual reading order, and it bands
330
+ * them into rows per region so that side-by-side columns stay contiguous runs
331
+ * in the DOM. That matters beyond reading order: a native `Selection` covers
332
+ * everything between its anchor and focus in DOM order, so two columns banded
333
+ * together let a vertical drag through one of them swallow the other.
334
+ *
335
+ * {@link clipChildren} also establishes a region, because a clipper is
336
+ * usually the column boundary you want. Reach for this flag when the two
337
+ * needs come apart — a sidebar, a card deck or any column that must not be
338
+ * absorbed by its neighbour's drag, but that draws nothing and has no reason
339
+ * to clip. Measured in a real app before this existed: a table-of-contents
340
+ * sidebar had to switch `clipChildren` on purely to escape the body column's
341
+ * bands, buying a per-frame `save`/`clip`/`restore` for an entity that paints
342
+ * nothing.
343
+ *
344
+ * Unlike `clipChildren`, this is honoured regardless of the node's box. The
345
+ * zero-area exemption on the clipping path exists because a zero-area clipper
346
+ * clips nothing; grouping is a declaration of intent that never consults
347
+ * geometry, and a pure grouping container often leaves `width`/`height` at 0.
348
+ *
349
+ * Off by default. Regions nest: the nearest enclosing region wins.
350
+ */
351
+ __init37() {this.a11yRegion = false}
321
352
  // Lazily allocated (see _drivers above). Most entities never register a
322
353
  // listener or an imperative animate() tween.
323
- __init37() {this.listeners = null}
354
+ __init38() {this.listeners = null}
324
355
  /** Capture-phase listeners (fired root→target before bubble). */
325
- __init38() {this.captureListeners = null}
326
- __init39() {this.animations = null}
327
- constructor(id) {;_class2.prototype.__init3.call(this);_class2.prototype.__init4.call(this);_class2.prototype.__init5.call(this);_class2.prototype.__init6.call(this);_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);
356
+ __init39() {this.captureListeners = null}
357
+ __init40() {this.animations = null}
358
+ constructor(id) {;_class2.prototype.__init3.call(this);_class2.prototype.__init4.call(this);_class2.prototype.__init5.call(this);_class2.prototype.__init6.call(this);_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);
328
359
  this.id = id || `entity_${Math.random().toString(36).substring(2, 9)}`;
329
360
  }
330
361
  /**
@@ -358,7 +389,7 @@ var Entity = (_class2 = class {
358
389
  const s = this.scene;
359
390
  if (s) {
360
391
  s.a11yNeedsReorder = true;
361
- _optionalChain([s, 'access', _41 => _41.markStructureChanged, 'optionalCall', _42 => _42()]);
392
+ _optionalChain([s, 'access', _43 => _43.markStructureChanged, 'optionalCall', _44 => _44()]);
362
393
  s.markDirty({ entity: this.id, reason: "child-added" });
363
394
  child._notifyMounted();
364
395
  }
@@ -388,7 +419,7 @@ var Entity = (_class2 = class {
388
419
  if (s) {
389
420
  s.detachA11y(child);
390
421
  s.a11yNeedsReorder = true;
391
- _optionalChain([s, 'access', _43 => _43.markStructureChanged, 'optionalCall', _44 => _44()]);
422
+ _optionalChain([s, 'access', _45 => _45.markStructureChanged, 'optionalCall', _46 => _46()]);
392
423
  s.markDirty({ entity: this.id, reason: "child-removed" });
393
424
  }
394
425
  }
@@ -443,7 +474,7 @@ var Entity = (_class2 = class {
443
474
  startTime: -1,
444
475
  startProps: {}
445
476
  });
446
- _optionalChain([this, 'access', _45 => _45.scene, 'optionalAccess', _46 => _46.markDirty, 'call', _47 => _47({ entity: this.id, reason: "animation-start" })]);
477
+ _optionalChain([this, 'access', _47 => _47.scene, 'optionalAccess', _48 => _48.markDirty, 'call', _49 => _49({ entity: this.id, reason: "animation-start" })]);
447
478
  return this;
448
479
  }
449
480
  /** Write a driver-computed value to a backing field without re-triggering the setter. */
@@ -490,26 +521,26 @@ var Entity = (_class2 = class {
490
521
  * that need to seed a starting state (e.g. the presence helper's enter `from`).
491
522
  */
492
523
  setImmediate(prop, v) {
493
- const existing = _optionalChain([this, 'access', _48 => _48._drivers, 'optionalAccess', _49 => _49.get, 'call', _50 => _50(prop)]);
524
+ const existing = _optionalChain([this, 'access', _50 => _50._drivers, 'optionalAccess', _51 => _51.get, 'call', _52 => _52(prop)]);
494
525
  if (existing) this._settleDriver(existing);
495
- _optionalChain([this, 'access', _51 => _51._drivers, 'optionalAccess', _52 => _52.delete, 'call', _53 => _53(prop)]);
526
+ _optionalChain([this, 'access', _53 => _53._drivers, 'optionalAccess', _54 => _54.delete, 'call', _55 => _55(prop)]);
496
527
  this._applyAnimated(prop, v);
497
528
  }
498
529
  _settleDriver(driver) {
499
530
  const active = driver;
500
531
  const onDone = active.onDone;
501
532
  active.onDone = void 0;
502
- _optionalChain([onDone, 'optionalCall', _54 => _54()]);
533
+ _optionalChain([onDone, 'optionalCall', _56 => _56()]);
503
534
  }
504
535
  _spawnDriver(prop, to, cfg) {
505
- if (prop !== "opacity" && _optionalChain([this, 'access', _55 => _55.scene, 'optionalAccess', _56 => _56.prefersReducedMotion])) {
506
- const existing2 = _optionalChain([this, 'access', _57 => _57._drivers, 'optionalAccess', _58 => _58.get, 'call', _59 => _59(prop)]);
536
+ if (prop !== "opacity" && _optionalChain([this, 'access', _57 => _57.scene, 'optionalAccess', _58 => _58.prefersReducedMotion])) {
537
+ const existing2 = _optionalChain([this, 'access', _59 => _59._drivers, 'optionalAccess', _60 => _60.get, 'call', _61 => _61(prop)]);
507
538
  if (existing2) this._settleDriver(existing2);
508
- _optionalChain([this, 'access', _60 => _60._drivers, 'optionalAccess', _61 => _61.delete, 'call', _62 => _62(prop)]);
539
+ _optionalChain([this, 'access', _62 => _62._drivers, 'optionalAccess', _63 => _63.delete, 'call', _64 => _64(prop)]);
509
540
  this._applyAnimated(prop, to);
510
541
  return;
511
542
  }
512
- const existing = _optionalChain([this, 'access', _63 => _63._drivers, 'optionalAccess', _64 => _64.get, 'call', _65 => _65(prop)]);
543
+ const existing = _optionalChain([this, 'access', _65 => _65._drivers, 'optionalAccess', _66 => _66.get, 'call', _67 => _67(prop)]);
513
544
  if (existing) {
514
545
  this._settleDriver(existing);
515
546
  existing.retarget(to);
@@ -518,12 +549,12 @@ var Entity = (_class2 = class {
518
549
  const from = this._currentOf(prop);
519
550
  const driver = _animation.isTweenConfig.call(void 0, cfg) ? new (0, _animation.TweenDriver)(from, to, cfg) : new (0, _animation.SpringDriver)(from, to, cfg === "spring" ? {} : cfg);
520
551
  (this._drivers ??= /* @__PURE__ */ new Map()).set(prop, driver);
521
- _optionalChain([this, 'access', _66 => _66.scene, 'optionalAccess', _67 => _67.markDirty, 'call', _68 => _68({ entity: this.id, reason: "driver-added" })]);
522
- _optionalChain([this, 'access', _69 => _69.scene, 'optionalAccess', _70 => _70._registerActiveDriverEntity, 'call', _71 => _71(this)]);
552
+ _optionalChain([this, 'access', _68 => _68.scene, 'optionalAccess', _69 => _69.markDirty, 'call', _70 => _70({ entity: this.id, reason: "driver-added" })]);
553
+ _optionalChain([this, 'access', _71 => _71.scene, 'optionalAccess', _72 => _72._registerActiveDriverEntity, 'call', _73 => _73(this)]);
523
554
  }
524
555
  /** Assignment path when a declarative transition is configured for `prop`. */
525
556
  _animateProp(prop, to) {
526
- const cfg = _optionalChain([this, 'access', _72 => _72._transitions, 'optionalAccess', _73 => _73.get, 'call', _74 => _74(prop)]);
557
+ const cfg = _optionalChain([this, 'access', _74 => _74._transitions, 'optionalAccess', _75 => _75.get, 'call', _76 => _76(prop)]);
527
558
  if (!cfg) {
528
559
  this._applyAnimated(prop, to);
529
560
  return;
@@ -552,7 +583,7 @@ var Entity = (_class2 = class {
552
583
  entries.map(
553
584
  (e) => new Promise((resolve) => {
554
585
  this._spawnDriver(e[0], e[1], cfg);
555
- const d = _optionalChain([this, 'access', _75 => _75._drivers, 'optionalAccess', _76 => _76.get, 'call', _77 => _77(e[0])]);
586
+ const d = _optionalChain([this, 'access', _77 => _77._drivers, 'optionalAccess', _78 => _78.get, 'call', _79 => _79(e[0])]);
556
587
  if (!d)
557
588
  resolve();
558
589
  else d.onDone = resolve;
@@ -574,7 +605,7 @@ var Entity = (_class2 = class {
574
605
  this._applyAnimated(prop, driver.value);
575
606
  }
576
607
  }
577
- _optionalChain([this, 'access', _78 => _78.scene, 'optionalAccess', _79 => _79.markDirty, 'call', _80 => _80({ entity: this.id, reason: "driver-tick" })]);
608
+ _optionalChain([this, 'access', _80 => _80.scene, 'optionalAccess', _81 => _81.markDirty, 'call', _82 => _82({ entity: this.id, reason: "driver-tick" })]);
578
609
  }
579
610
  /**
580
611
  * Internal: this entity's active-driver map (read-only view), or `null` if
@@ -599,7 +630,7 @@ var Entity = (_class2 = class {
599
630
  if (driver.isDone()) {
600
631
  this._applyAnimated(prop, driver.target);
601
632
  this._settleDriver(driver);
602
- _optionalChain([this, 'access', _81 => _81._drivers, 'optionalAccess', _82 => _82.delete, 'call', _83 => _83(prop)]);
633
+ _optionalChain([this, 'access', _83 => _83._drivers, 'optionalAccess', _84 => _84.delete, 'call', _85 => _85(prop)]);
603
634
  } else {
604
635
  this._applyAnimated(prop, driver.value);
605
636
  }
@@ -660,7 +691,7 @@ var Entity = (_class2 = class {
660
691
  * @example entity.on('click', (e) => console.log('clicked', e));
661
692
  */
662
693
  on(event, callback, options) {
663
- const map = _optionalChain([options, 'optionalAccess', _84 => _84.capture]) ? this.captureListeners ??= /* @__PURE__ */ new Map() : this.listeners ??= /* @__PURE__ */ new Map();
694
+ const map = _optionalChain([options, 'optionalAccess', _86 => _86.capture]) ? this.captureListeners ??= /* @__PURE__ */ new Map() : this.listeners ??= /* @__PURE__ */ new Map();
664
695
  if (!map.has(event)) {
665
696
  map.set(event, []);
666
697
  }
@@ -676,7 +707,7 @@ var Entity = (_class2 = class {
676
707
  * @returns `this` for method chaining.
677
708
  */
678
709
  off(event, callback, options) {
679
- const handlers = _optionalChain([(_optionalChain([options, 'optionalAccess', _85 => _85.capture]) ? this.captureListeners : this.listeners), 'optionalAccess', _86 => _86.get, 'call', _87 => _87(event)]);
710
+ const handlers = _optionalChain([(_optionalChain([options, 'optionalAccess', _87 => _87.capture]) ? this.captureListeners : this.listeners), 'optionalAccess', _88 => _88.get, 'call', _89 => _89(event)]);
680
711
  if (handlers) {
681
712
  const idx = handlers.indexOf(callback);
682
713
  if (idx !== -1) handlers.splice(idx, 1);
@@ -713,8 +744,8 @@ var Entity = (_class2 = class {
713
744
  }
714
745
  this._drivers.clear();
715
746
  }
716
- _optionalChain([this, 'access', _88 => _88.listeners, 'optionalAccess', _89 => _89.clear, 'call', _90 => _90()]);
717
- _optionalChain([this, 'access', _91 => _91.captureListeners, 'optionalAccess', _92 => _92.clear, 'call', _93 => _93()]);
747
+ _optionalChain([this, 'access', _90 => _90.listeners, 'optionalAccess', _91 => _91.clear, 'call', _92 => _92()]);
748
+ _optionalChain([this, 'access', _93 => _93.captureListeners, 'optionalAccess', _94 => _94.clear, 'call', _95 => _95()]);
718
749
  if (this.parent) {
719
750
  this.parent.remove(this);
720
751
  }
@@ -729,7 +760,7 @@ var Entity = (_class2 = class {
729
760
  * @param payload - Arbitrary data forwarded to each listener.
730
761
  */
731
762
  emit(event, payload) {
732
- const handlers = _optionalChain([this, 'access', _94 => _94.listeners, 'optionalAccess', _95 => _95.get, 'call', _96 => _96(event)]);
763
+ const handlers = _optionalChain([this, 'access', _96 => _96.listeners, 'optionalAccess', _97 => _97.get, 'call', _98 => _98(event)]);
733
764
  if (handlers) {
734
765
  handlers.forEach((h) => h(payload));
735
766
  }
@@ -743,19 +774,19 @@ var Entity = (_class2 = class {
743
774
  * with `requestAnimationFrame(() => document.getElementById(id)?.focus())`.
744
775
  */
745
776
  focus() {
746
- const el = _optionalChain([this, 'access', _97 => _97.scene, 'optionalAccess', _98 => _98.getA11yElement, 'call', _99 => _99(this.id)]);
777
+ const el = _optionalChain([this, 'access', _99 => _99.scene, 'optionalAccess', _100 => _100.getA11yElement, 'call', _101 => _101(this.id)]);
747
778
  if (el) {
748
779
  el.focus();
749
780
  return;
750
781
  }
751
782
  requestAnimationFrame(() => {
752
- const retry = _optionalChain([this, 'access', _100 => _100.scene, 'optionalAccess', _101 => _101.getA11yElement, 'call', _102 => _102(this.id)]);
783
+ const retry = _optionalChain([this, 'access', _102 => _102.scene, 'optionalAccess', _103 => _103.getA11yElement, 'call', _104 => _104(this.id)]);
753
784
  if (retry) retry.focus();
754
785
  });
755
786
  }
756
787
  /** Run one node's listeners for the event, honoring stopImmediatePropagation. */
757
788
  fireListeners(node, map, event) {
758
- const handlers = _optionalChain([map, 'optionalAccess', _103 => _103.get, 'call', _104 => _104(event.type)]);
789
+ const handlers = _optionalChain([map, 'optionalAccess', _105 => _105.get, 'call', _106 => _106(event.type)]);
759
790
  if (!handlers) return;
760
791
  event.currentTarget = node;
761
792
  for (const h of handlers.slice()) {
@@ -1142,7 +1173,7 @@ var Entity = (_class2 = class {
1142
1173
  * @returns `true` if at least one animation or property driver remains.
1143
1174
  */
1144
1175
  hasPendingAnimations() {
1145
- return (_nullishCoalesce(_optionalChain([this, 'access', _105 => _105.animations, 'optionalAccess', _106 => _106.length]), () => ( 0))) > 0 || (_nullishCoalesce(_optionalChain([this, 'access', _107 => _107._drivers, 'optionalAccess', _108 => _108.size]), () => ( 0))) > 0;
1176
+ return (_nullishCoalesce(_optionalChain([this, 'access', _107 => _107.animations, 'optionalAccess', _108 => _108.length]), () => ( 0))) > 0 || (_nullishCoalesce(_optionalChain([this, 'access', _109 => _109._drivers, 'optionalAccess', _110 => _110.size]), () => ( 0))) > 0;
1146
1177
  }
1147
1178
  }, _class2);
1148
1179
 
@@ -1164,22 +1195,22 @@ var MSDFTextEntity = (_class3 = class extends Entity {
1164
1195
  // joined by soft hyphens (U+00AD); the worker then treats those as break
1165
1196
  // opportunities. `text` keeps the original string for a11y/content
1166
1197
  // projection; `layoutText` is the soft-hyphen-annotated string sent to layout.
1167
- __init40() {this.hyphenator = null}
1168
- __init41() {this.layoutText = ""}
1169
- __init42() {this.text = ""}
1170
- __init43() {this.lastRenderedSeqId = 0}
1198
+ __init41() {this.hyphenator = null}
1199
+ __init42() {this.layoutText = ""}
1200
+ __init43() {this.text = ""}
1201
+ __init44() {this.lastRenderedSeqId = 0}
1171
1202
  /** Bumped by {@link queueLayout}; read by `Scene` to skip an unchanged sync. */
1172
- __init44() {this.contentEpoch = 0}
1203
+ __init45() {this.contentEpoch = 0}
1173
1204
  // Atlas-decode subscription (see watchAtlasDecode). Held so `destroy()` can
1174
1205
  // release it: the handler closes over `this`, so leaving it attached to a
1175
1206
  // long-lived shared atlas image would retain the whole entity.
1176
- __init45() {this.atlasDecodeTarget = null}
1177
- __init46() {this.atlasDecodeHandler = null}
1178
- __init47() {this.rgbColorCache = /* @__PURE__ */ new Map()}
1179
- __init48() {this.fontStringCache = []}
1180
- __init49() {this.layoutResult = null}
1207
+ __init46() {this.atlasDecodeTarget = null}
1208
+ __init47() {this.atlasDecodeHandler = null}
1209
+ __init48() {this.rgbColorCache = /* @__PURE__ */ new Map()}
1210
+ __init49() {this.fontStringCache = []}
1211
+ __init50() {this.layoutResult = null}
1181
1212
  constructor(text, options) {
1182
- super();_class3.prototype.__init40.call(this);_class3.prototype.__init41.call(this);_class3.prototype.__init42.call(this);_class3.prototype.__init43.call(this);_class3.prototype.__init44.call(this);_class3.prototype.__init45.call(this);_class3.prototype.__init46.call(this);_class3.prototype.__init47.call(this);_class3.prototype.__init48.call(this);_class3.prototype.__init49.call(this);;
1213
+ super();_class3.prototype.__init41.call(this);_class3.prototype.__init42.call(this);_class3.prototype.__init43.call(this);_class3.prototype.__init44.call(this);_class3.prototype.__init45.call(this);_class3.prototype.__init46.call(this);_class3.prototype.__init47.call(this);_class3.prototype.__init48.call(this);_class3.prototype.__init49.call(this);_class3.prototype.__init50.call(this);;
1183
1214
  this.font = options.font;
1184
1215
  this.texture = options.texture;
1185
1216
  this.fallbackFont = _nullishCoalesce(options.fallbackFont, () => ( "sans-serif"));
@@ -1224,7 +1255,7 @@ var MSDFTextEntity = (_class3 = class extends Entity {
1224
1255
  const target = this.texture;
1225
1256
  this.atlasDecodeHandler = () => {
1226
1257
  this.detachAtlasDecodeListener();
1227
- _optionalChain([this, 'access', _109 => _109.scene, 'optionalAccess', _110 => _110.markDirty, 'call', _111 => _111()]);
1258
+ _optionalChain([this, 'access', _111 => _111.scene, 'optionalAccess', _112 => _112.markDirty, 'call', _113 => _113()]);
1228
1259
  };
1229
1260
  target.addEventListener("load", this.atlasDecodeHandler);
1230
1261
  target.addEventListener("error", this.atlasDecodeHandler);
@@ -1303,7 +1334,7 @@ var MSDFTextEntity = (_class3 = class extends Entity {
1303
1334
  if (res.seqId < this.lastRenderedSeqId) return;
1304
1335
  this.lastRenderedSeqId = res.seqId;
1305
1336
  this.layoutResult = res;
1306
- _optionalChain([this, 'access', _112 => _112.scene, 'optionalAccess', _113 => _113.markDirty, 'call', _114 => _114()]);
1337
+ _optionalChain([this, 'access', _114 => _114.scene, 'optionalAccess', _115 => _115.markDirty, 'call', _116 => _116()]);
1307
1338
  }
1308
1339
  });
1309
1340
  }
@@ -1455,23 +1486,23 @@ var SVGEntity = (_class4 = class extends Entity {
1455
1486
  * rasterized. Set to `'transparent'` to opt out and keep the box empty.
1456
1487
  * Default `'rgba(248,113,113,0.9)'`.
1457
1488
  */
1458
- __init50() {this.fallbackStroke = "rgba(248,113,113,0.9)"}
1489
+ __init51() {this.fallbackStroke = "rgba(248,113,113,0.9)"}
1459
1490
  /** Fill behind the fallback marker. Default `'rgba(248,113,113,0.12)'`. */
1460
- __init51() {this.fallbackFill = "rgba(248,113,113,0.12)"}
1461
- __init52() {this.svgSource = ""}
1462
- __init53() {this.imageBitmap = null}
1463
- __init54() {this.imageElement = null}
1464
- __init55() {this.blobURL = null}
1465
- __init56() {this.currentImg = null}
1466
- __init57() {this.lodTimeout = null}
1467
- __init58() {this.rasterFailed = false}
1468
- __init59() {this.cachedDoc = null}
1469
- __init60() {this.baseWidth = 100}
1470
- __init61() {this.baseHeight = 100}
1471
- __init62() {this.lastRasterizedScale = 1}
1472
- __init63() {this.targetScale = 1}
1491
+ __init52() {this.fallbackFill = "rgba(248,113,113,0.12)"}
1492
+ __init53() {this.svgSource = ""}
1493
+ __init54() {this.imageBitmap = null}
1494
+ __init55() {this.imageElement = null}
1495
+ __init56() {this.blobURL = null}
1496
+ __init57() {this.currentImg = null}
1497
+ __init58() {this.lodTimeout = null}
1498
+ __init59() {this.rasterFailed = false}
1499
+ __init60() {this.cachedDoc = null}
1500
+ __init61() {this.baseWidth = 100}
1501
+ __init62() {this.baseHeight = 100}
1502
+ __init63() {this.lastRasterizedScale = 1}
1503
+ __init64() {this.targetScale = 1}
1473
1504
  constructor(svgSource, id) {
1474
- super(id);_class4.prototype.__init50.call(this);_class4.prototype.__init51.call(this);_class4.prototype.__init52.call(this);_class4.prototype.__init53.call(this);_class4.prototype.__init54.call(this);_class4.prototype.__init55.call(this);_class4.prototype.__init56.call(this);_class4.prototype.__init57.call(this);_class4.prototype.__init58.call(this);_class4.prototype.__init59.call(this);_class4.prototype.__init60.call(this);_class4.prototype.__init61.call(this);_class4.prototype.__init62.call(this);_class4.prototype.__init63.call(this);;
1505
+ super(id);_class4.prototype.__init51.call(this);_class4.prototype.__init52.call(this);_class4.prototype.__init53.call(this);_class4.prototype.__init54.call(this);_class4.prototype.__init55.call(this);_class4.prototype.__init56.call(this);_class4.prototype.__init57.call(this);_class4.prototype.__init58.call(this);_class4.prototype.__init59.call(this);_class4.prototype.__init60.call(this);_class4.prototype.__init61.call(this);_class4.prototype.__init62.call(this);_class4.prototype.__init63.call(this);_class4.prototype.__init64.call(this);;
1475
1506
  this.setSVGSource(svgSource);
1476
1507
  }
1477
1508
  setSVGSource(svgSource) {
@@ -71,6 +71,10 @@ var VectoJSEvent = class {
71
71
  get deltaY() {
72
72
  return this.nativeEvent?.deltaY;
73
73
  }
74
+ /** Native wheel delta mode (0=pixels, 1=lines, 2=pages), if this wraps a `WheelEvent`. */
75
+ get deltaMode() {
76
+ return this.nativeEvent?.deltaMode;
77
+ }
74
78
  /** Native pointer X, if this wraps a pointer/mouse event. */
75
79
  get clientX() {
76
80
  return this.nativeEvent?.clientX;
@@ -316,6 +320,33 @@ var Entity = class {
316
320
  * fixed viewport. Off by default (children render unclipped). Canvas2D only.
317
321
  */
318
322
  clipChildren = false;
323
+ /**
324
+ * Group this subtree's projected text into its own accessibility **region**,
325
+ * without clipping anything.
326
+ *
327
+ * The projection sorts every mirror into visual reading order, and it bands
328
+ * them into rows per region so that side-by-side columns stay contiguous runs
329
+ * in the DOM. That matters beyond reading order: a native `Selection` covers
330
+ * everything between its anchor and focus in DOM order, so two columns banded
331
+ * together let a vertical drag through one of them swallow the other.
332
+ *
333
+ * {@link clipChildren} also establishes a region, because a clipper is
334
+ * usually the column boundary you want. Reach for this flag when the two
335
+ * needs come apart — a sidebar, a card deck or any column that must not be
336
+ * absorbed by its neighbour's drag, but that draws nothing and has no reason
337
+ * to clip. Measured in a real app before this existed: a table-of-contents
338
+ * sidebar had to switch `clipChildren` on purely to escape the body column's
339
+ * bands, buying a per-frame `save`/`clip`/`restore` for an entity that paints
340
+ * nothing.
341
+ *
342
+ * Unlike `clipChildren`, this is honoured regardless of the node's box. The
343
+ * zero-area exemption on the clipping path exists because a zero-area clipper
344
+ * clips nothing; grouping is a declaration of intent that never consults
345
+ * geometry, and a pure grouping container often leaves `width`/`height` at 0.
346
+ *
347
+ * Off by default. Regions nest: the nearest enclosing region wins.
348
+ */
349
+ a11yRegion = false;
319
350
  // Lazily allocated (see _drivers above). Most entities never register a
320
351
  // listener or an imperative animate() tween.
321
352
  listeners = null;
@@ -87,8 +87,8 @@ export declare function polySegmentToBezier(seg: SplineSegment): BezierControlPo
87
87
  * scene.add(new SplineEntity(doc).setPosition(100, 100));
88
88
  */
89
89
  export declare class SplineEntity extends Entity {
90
- doc: SplineDocument;
91
- lineWidth: number;
90
+ private _doc;
91
+ private _lineWidth;
92
92
  defaultColor: string;
93
93
  hitTolerance: number;
94
94
  private cache;
@@ -99,10 +99,26 @@ export declare class SplineEntity extends Entity {
99
99
  /** Logical (CSS-pixel) size of the baked bitmap — the blit destination size. */
100
100
  private bakedWidth;
101
101
  private bakedHeight;
102
- /** Gradient strokes can't be baked to a solid-color bitmap; they render per-frame. */
103
- private readonly containsGradient;
102
+ /**
103
+ * Gradient strokes can't be baked to a solid-color bitmap; they render
104
+ * per-frame. Derived from `_doc`, so it is NOT readonly — assigning a new
105
+ * document has to recompute it (see the `doc` setter).
106
+ */
107
+ private containsGradient;
104
108
  /** Lazily-flattened polylines (one Float32Array of [x,y,...] per segment) for hit-testing. */
105
109
  private polylines;
110
+ /**
111
+ * The spline document to render. Assigning a new document invalidates all
112
+ * caches (baked canvas, flattened polylines, bounds).
113
+ */
114
+ get doc(): SplineDocument;
115
+ set doc(value: SplineDocument);
116
+ /**
117
+ * Stroke width in local units. Assigning a new value invalidates the baked
118
+ * canvas and hit-test polylines so visual and hit geometry stay consistent.
119
+ */
120
+ get lineWidth(): number;
121
+ set lineWidth(value: number);
106
122
  /**
107
123
  * When `true`, the renderer draws a rounded-rect outline of the entity's
108
124
  * local bounds after painting the curves. Useful for drag feedback and
@@ -110,6 +126,14 @@ export declare class SplineEntity extends Entity {
110
126
  */
111
127
  showBounds: boolean;
112
128
  constructor(doc: SplineDocument, opts?: SplineOptions);
129
+ /**
130
+ * Whether any stroke in the current document is a gradient. Shared by the
131
+ * constructor and the `doc` setter so both stay in agreement — the flag picks
132
+ * the render path, so a stale value renders a gradient as a flat color.
133
+ */
134
+ private computeContainsGradient;
135
+ /** Clear cached baked canvas and hit-test polylines. */
136
+ private invalidateCache;
113
137
  private computeBounds;
114
138
  /** @inheritdoc */
115
139
  getBounds(): Bounds;