@vectojs/core 1.39.1 → 1.40.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.
@@ -27,16 +27,22 @@ var VectoJSEvent = class {
27
27
  nativeEvent;
28
28
  /** Whether the event bubbles past its target (capture always runs). */
29
29
  bubbles;
30
+ /**
31
+ * Which transport delivered this event ({@link VectoEventSource}).
32
+ * `undefined` for unattributed legacy/synthetic dispatches.
33
+ */
34
+ source;
30
35
  explicitScenePoint;
31
36
  stopped = false;
32
37
  stoppedImmediate = false;
33
- constructor(type, target, nativeEvent, bubbles = true, scenePoint) {
38
+ constructor(type, target, nativeEvent, bubbles = true, scenePoint, source) {
34
39
  this.type = type;
35
40
  this.target = target;
36
41
  this.currentTarget = target;
37
42
  this.nativeEvent = nativeEvent;
38
43
  this.bubbles = bubbles;
39
44
  this.explicitScenePoint = scenePoint;
45
+ this.source = source;
40
46
  }
41
47
  /** Stop the event from reaching the next node in the propagation path. */
42
48
  stopPropagation() {
@@ -330,6 +336,41 @@ var Entity = class {
330
336
  * faint-but-live control.
331
337
  */
332
338
  a11yHidden = false;
339
+ /**
340
+ * Opt-in to the DOM visual projection (RFC2, implemented by `@vectojs/dom`).
341
+ * Plain data only — core never materializes an element from this; a
342
+ * registered `ProjectionBackend` does.
343
+ *
344
+ * Name mapping: this field IS the RFC4 §2 `projection` policy
345
+ * (`ProjectionPolicy`: `'canvas' | 'dom' | 'auto'` in
346
+ * `tree/scene/ProjectionPolicy.ts`) — predates the RFC, so the field keeps
347
+ * its name and the RFC spelling lives on the value type.
348
+ *
349
+ * - `'canvas'` (default): today's rendering. Zero behavior change.
350
+ * - `'dom'`: the node materializes as a live `HTMLElement` positioned by its
351
+ * world matrix. The live element replaces the transparent a11y mirror
352
+ * (same single-delivery reasoning as `DOMPortalEntity`), so opting in
353
+ * requires a DOM backend and a DOM environment for the AT representation.
354
+ * - `'auto'`: negotiated per node per frame by `Scene.resolveProjectionFor`
355
+ * (RFC4 §3: explicit beats automatic, fallbacks reported with reasons,
356
+ * hysteresis against flip-flop, no-DOM short-circuits to canvas).
357
+ */
358
+ domPolicy = "canvas";
359
+ /**
360
+ * Backend-side creation hint for a `'dom'`-policy node (tag/content mapping
361
+ * key, e.g. `'text' | 'button' | 'input' | 'container' | 'transform'`). Plain
362
+ * string so custom nodes need no DOM types in core; `@vectojs/dom` owns the
363
+ * registry. `''` means a plain positioned `div` with no content sync.
364
+ */
365
+ domKind = "";
366
+ /**
367
+ * Internal cache owned by the DOM backend: true while the node has a live
368
+ * projected element. The render walk reads it to skip canvas paint for
369
+ * DOM-resident nodes (so a mounted node is never double-drawn) and falls
370
+ * through to canvas while false (SSR / no backend registered). Do not set
371
+ * by hand — the backend sets it on mount and clears it on unmount.
372
+ */
373
+ domResident = false;
333
374
  /**
334
375
  * Clip this node's children to its local box (`[0,0]–[width,height]`) while
335
376
  * rendering. Combined with translating a content child, this is how
@@ -631,8 +672,7 @@ var Entity = class {
631
672
  (e) => new Promise((resolve) => {
632
673
  this._spawnDriver(e[0], e[1], cfg);
633
674
  const d = this._drivers?.get(e[0]);
634
- if (!d)
635
- resolve();
675
+ if (!d) resolve();
636
676
  else d.onDone = resolve;
637
677
  })
638
678
  )
@@ -822,6 +862,7 @@ var Entity = class {
822
862
  el.focus();
823
863
  return;
824
864
  }
865
+ if (typeof requestAnimationFrame === "undefined") return;
825
866
  requestAnimationFrame(() => {
826
867
  const retry = this.scene?.getA11yElement(this.id);
827
868
  if (retry) retry.focus();
@@ -1188,6 +1229,10 @@ var Entity = class {
1188
1229
  * `selectable` is set — natively selectable. Returns `null` by default.
1189
1230
  * Read on the a11y sync cadence, so text changes propagate automatically.
1190
1231
  *
1232
+ * This is the descriptor half of the `ContentProjection` row of
1233
+ * `ProjectionBackend` (`tree/scene/ProjectionBackend.ts`): the entity
1234
+ * describes *what* to project, the scene owns *how* it is materialized.
1235
+ *
1191
1236
  * @param hint - Optional advice about which part of the entity is worth
1192
1237
  * describing. Purely an optimization: ignoring it is always correct, which
1193
1238
  * is why it is a parameter rather than a required contract change. See
@@ -29,16 +29,22 @@ var VectoJSEvent = (_class = class {
29
29
 
30
30
  /** Whether the event bubbles past its target (capture always runs). */
31
31
 
32
+ /**
33
+ * Which transport delivered this event ({@link VectoEventSource}).
34
+ * `undefined` for unattributed legacy/synthetic dispatches.
35
+ */
36
+
32
37
 
33
38
  __init() {this.stopped = false}
34
39
  __init2() {this.stoppedImmediate = false}
35
- constructor(type, target, nativeEvent, bubbles = true, scenePoint) {;_class.prototype.__init.call(this);_class.prototype.__init2.call(this);
40
+ constructor(type, target, nativeEvent, bubbles = true, scenePoint, source) {;_class.prototype.__init.call(this);_class.prototype.__init2.call(this);
36
41
  this.type = type;
37
42
  this.target = target;
38
43
  this.currentTarget = target;
39
44
  this.nativeEvent = nativeEvent;
40
45
  this.bubbles = bubbles;
41
46
  this.explicitScenePoint = scenePoint;
47
+ this.source = source;
42
48
  }
43
49
  /** Stop the event from reaching the next node in the propagation path. */
44
50
  stopPropagation() {
@@ -332,13 +338,48 @@ var Entity = (_class2 = class {
332
338
  * faint-but-live control.
333
339
  */
334
340
  __init36() {this.a11yHidden = false}
341
+ /**
342
+ * Opt-in to the DOM visual projection (RFC2, implemented by `@vectojs/dom`).
343
+ * Plain data only — core never materializes an element from this; a
344
+ * registered `ProjectionBackend` does.
345
+ *
346
+ * Name mapping: this field IS the RFC4 §2 `projection` policy
347
+ * (`ProjectionPolicy`: `'canvas' | 'dom' | 'auto'` in
348
+ * `tree/scene/ProjectionPolicy.ts`) — predates the RFC, so the field keeps
349
+ * its name and the RFC spelling lives on the value type.
350
+ *
351
+ * - `'canvas'` (default): today's rendering. Zero behavior change.
352
+ * - `'dom'`: the node materializes as a live `HTMLElement` positioned by its
353
+ * world matrix. The live element replaces the transparent a11y mirror
354
+ * (same single-delivery reasoning as `DOMPortalEntity`), so opting in
355
+ * requires a DOM backend and a DOM environment for the AT representation.
356
+ * - `'auto'`: negotiated per node per frame by `Scene.resolveProjectionFor`
357
+ * (RFC4 §3: explicit beats automatic, fallbacks reported with reasons,
358
+ * hysteresis against flip-flop, no-DOM short-circuits to canvas).
359
+ */
360
+ __init37() {this.domPolicy = "canvas"}
361
+ /**
362
+ * Backend-side creation hint for a `'dom'`-policy node (tag/content mapping
363
+ * key, e.g. `'text' | 'button' | 'input' | 'container' | 'transform'`). Plain
364
+ * string so custom nodes need no DOM types in core; `@vectojs/dom` owns the
365
+ * registry. `''` means a plain positioned `div` with no content sync.
366
+ */
367
+ __init38() {this.domKind = ""}
368
+ /**
369
+ * Internal cache owned by the DOM backend: true while the node has a live
370
+ * projected element. The render walk reads it to skip canvas paint for
371
+ * DOM-resident nodes (so a mounted node is never double-drawn) and falls
372
+ * through to canvas while false (SSR / no backend registered). Do not set
373
+ * by hand — the backend sets it on mount and clears it on unmount.
374
+ */
375
+ __init39() {this.domResident = false}
335
376
  /**
336
377
  * Clip this node's children to its local box (`[0,0]–[width,height]`) while
337
378
  * rendering. Combined with translating a content child, this is how
338
379
  * scroll/overflow containers (e.g. `ScrollView`) keep their content inside a
339
380
  * fixed viewport. Off by default (children render unclipped). Canvas2D only.
340
381
  */
341
- __init37() {this.clipChildren = false}
382
+ __init40() {this.clipChildren = false}
342
383
  /**
343
384
  * Group this subtree's projected text into its own accessibility **region**,
344
385
  * without clipping anything.
@@ -365,14 +406,14 @@ var Entity = (_class2 = class {
365
406
  *
366
407
  * Off by default. Regions nest: the nearest enclosing region wins.
367
408
  */
368
- __init38() {this.a11yRegion = false}
409
+ __init41() {this.a11yRegion = false}
369
410
  // Lazily allocated (see _drivers above). Most entities never register a
370
411
  // listener or an imperative animate() tween.
371
- __init39() {this.listeners = null}
412
+ __init42() {this.listeners = null}
372
413
  /** Capture-phase listeners (fired root→target before bubble). */
373
- __init40() {this.captureListeners = null}
374
- __init41() {this.animations = null}
375
- 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);_class2.prototype.__init41.call(this);
414
+ __init43() {this.captureListeners = null}
415
+ __init44() {this.animations = null}
416
+ 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);_class2.prototype.__init41.call(this);_class2.prototype.__init42.call(this);_class2.prototype.__init43.call(this);_class2.prototype.__init44.call(this);
376
417
  this.id = id || `entity_${Math.random().toString(36).substring(2, 9)}`;
377
418
  }
378
419
  /**
@@ -633,8 +674,7 @@ var Entity = (_class2 = class {
633
674
  (e) => new Promise((resolve) => {
634
675
  this._spawnDriver(e[0], e[1], cfg);
635
676
  const d = _optionalChain([this, 'access', _84 => _84._drivers, 'optionalAccess', _85 => _85.get, 'call', _86 => _86(e[0])]);
636
- if (!d)
637
- resolve();
677
+ if (!d) resolve();
638
678
  else d.onDone = resolve;
639
679
  })
640
680
  )
@@ -824,6 +864,7 @@ var Entity = (_class2 = class {
824
864
  el.focus();
825
865
  return;
826
866
  }
867
+ if (typeof requestAnimationFrame === "undefined") return;
827
868
  requestAnimationFrame(() => {
828
869
  const retry = _optionalChain([this, 'access', _109 => _109.scene, 'optionalAccess', _110 => _110.getA11yElement, 'call', _111 => _111(this.id)]);
829
870
  if (retry) retry.focus();
@@ -1190,6 +1231,10 @@ var Entity = (_class2 = class {
1190
1231
  * `selectable` is set — natively selectable. Returns `null` by default.
1191
1232
  * Read on the a11y sync cadence, so text changes propagate automatically.
1192
1233
  *
1234
+ * This is the descriptor half of the `ContentProjection` row of
1235
+ * `ProjectionBackend` (`tree/scene/ProjectionBackend.ts`): the entity
1236
+ * describes *what* to project, the scene owns *how* it is materialized.
1237
+ *
1193
1238
  * @param hint - Optional advice about which part of the entity is worth
1194
1239
  * describing. Purely an optimization: ignoring it is always correct, which
1195
1240
  * is why it is a parameter rather than a required contract change. See
@@ -1267,27 +1312,27 @@ var MSDFTextEntity = (_class3 = class extends Entity {
1267
1312
  // joined by soft hyphens (U+00AD); the worker then treats those as break
1268
1313
  // opportunities. `text` keeps the original string for a11y/content
1269
1314
  // projection; `layoutText` is the soft-hyphen-annotated string sent to layout.
1270
- __init42() {this.hyphenator = null}
1271
- __init43() {this.layoutText = ""}
1272
- __init44() {this.text = ""}
1273
- __init45() {this.lastRenderedSeqId = 0}
1315
+ __init45() {this.hyphenator = null}
1316
+ __init46() {this.layoutText = ""}
1317
+ __init47() {this.text = ""}
1318
+ __init48() {this.lastRenderedSeqId = 0}
1274
1319
  /** Bumped by {@link queueLayout}; read by `Scene` to skip an unchanged sync. */
1275
- __init46() {this.contentEpoch = 0}
1320
+ __init49() {this.contentEpoch = 0}
1276
1321
  // Atlas-decode subscription (see watchAtlasDecode). Held so `destroy()` can
1277
1322
  // release it: the handler closes over `this`, so leaving it attached to a
1278
1323
  // long-lived shared atlas image would retain the whole entity.
1279
- __init47() {this.atlasDecodeTarget = null}
1280
- __init48() {this.atlasDecodeHandler = null}
1281
- __init49() {this.fontStringCache = []}
1282
- __init50() {this.layoutResult = null}
1324
+ __init50() {this.atlasDecodeTarget = null}
1325
+ __init51() {this.atlasDecodeHandler = null}
1326
+ __init52() {this.fontStringCache = []}
1327
+ __init53() {this.layoutResult = null}
1283
1328
  /**
1284
1329
  * Visual rows rebuilt from {@link layoutResult} (see
1285
1330
  * {@link rebuildProjectionLines}). Empty until a layout reply lands and the
1286
1331
  * reply's shaped glyphs can be mapped back to the source text 1:1.
1287
1332
  */
1288
- __init51() {this.projectionLines = []}
1333
+ __init54() {this.projectionLines = []}
1289
1334
  constructor(text, options) {
1290
- super();_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);_class3.prototype.__init51.call(this);;
1335
+ super();_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);_class3.prototype.__init51.call(this);_class3.prototype.__init52.call(this);_class3.prototype.__init53.call(this);_class3.prototype.__init54.call(this);;
1291
1336
  this.font = options.font;
1292
1337
  this.texture = options.texture;
1293
1338
  this.fallbackFont = _nullishCoalesce(options.fallbackFont, () => ( "sans-serif"));
@@ -1671,23 +1716,23 @@ var SVGEntity = (_class4 = class extends Entity {
1671
1716
  * rasterized. Set to `'transparent'` to opt out and keep the box empty.
1672
1717
  * Default `'rgba(248,113,113,0.9)'`.
1673
1718
  */
1674
- __init52() {this.fallbackStroke = "rgba(248,113,113,0.9)"}
1719
+ __init55() {this.fallbackStroke = "rgba(248,113,113,0.9)"}
1675
1720
  /** Fill behind the fallback marker. Default `'rgba(248,113,113,0.12)'`. */
1676
- __init53() {this.fallbackFill = "rgba(248,113,113,0.12)"}
1677
- __init54() {this.svgSource = ""}
1678
- __init55() {this.imageBitmap = null}
1679
- __init56() {this.imageElement = null}
1680
- __init57() {this.blobURL = null}
1681
- __init58() {this.currentImg = null}
1682
- __init59() {this.lodTimeout = null}
1683
- __init60() {this.rasterFailed = false}
1684
- __init61() {this.cachedDoc = null}
1685
- __init62() {this.baseWidth = 100}
1686
- __init63() {this.baseHeight = 100}
1687
- __init64() {this.lastRasterizedScale = 1}
1688
- __init65() {this.targetScale = 1}
1721
+ __init56() {this.fallbackFill = "rgba(248,113,113,0.12)"}
1722
+ __init57() {this.svgSource = ""}
1723
+ __init58() {this.imageBitmap = null}
1724
+ __init59() {this.imageElement = null}
1725
+ __init60() {this.blobURL = null}
1726
+ __init61() {this.currentImg = null}
1727
+ __init62() {this.lodTimeout = null}
1728
+ __init63() {this.rasterFailed = false}
1729
+ __init64() {this.cachedDoc = null}
1730
+ __init65() {this.baseWidth = 100}
1731
+ __init66() {this.baseHeight = 100}
1732
+ __init67() {this.lastRasterizedScale = 1}
1733
+ __init68() {this.targetScale = 1}
1689
1734
  constructor(svgSource, id) {
1690
- super(id);_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);_class4.prototype.__init65.call(this);;
1735
+ super(id);_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);_class4.prototype.__init65.call(this);_class4.prototype.__init66.call(this);_class4.prototype.__init67.call(this);_class4.prototype.__init68.call(this);;
1691
1736
  this.setSVGSource(svgSource);
1692
1737
  }
1693
1738
  setSVGSource(svgSource) {
@@ -0,0 +1,110 @@
1
+ import { Entity, type A11yAttributes } from '../tree/Entity';
2
+ import type { IRenderer } from '../renderer/IRenderer';
3
+ /**
4
+ * One item in a {@link VirtualizedSetAggregate}: the stable identity and the
5
+ * accessible name a hotspot announces for it.
6
+ */
7
+ export interface VirtualizedSetItem {
8
+ /** Stable identity across re-binds; survives reordering and filtering. */
9
+ id: string;
10
+ /** Accessible name announced for the item. */
11
+ label: string;
12
+ }
13
+ export interface VirtualizedSetAggregateOptions {
14
+ /** Full item set; the container label always states this count. Default `[]`. */
15
+ items?: VirtualizedSetItem[];
16
+ /** Container name; the count is appended (`'Messages, 10000 items'`). */
17
+ label?: string;
18
+ /** Container role. Default `'list'` (owns `listitem` per `A11Y_REQUIRED_OWNED`). */
19
+ role?: string;
20
+ /** Hotspot role. Default `'listitem'`. */
21
+ itemRole?: string;
22
+ /** Row height in local px; hotspots stack vertically at this stride. Default `28`. */
23
+ rowHeight?: number;
24
+ /** Hotspot pool size. Default: enough slots to cover `height`, at least 1. */
25
+ visibleCapacity?: number;
26
+ /** Container width in local px. Default `0` (set it — a zero box never projects). */
27
+ width?: number;
28
+ /** Container height in local px. Default `0`. */
29
+ height?: number;
30
+ /** Called when an item is activated (Enter/Space/click-through). */
31
+ onActivate?: (item: VirtualizedSetItem, index: number) => void;
32
+ }
33
+ /**
34
+ * Aggregate semantics for a virtualized set (RFC3 §4.4, CTX-0599).
35
+ *
36
+ * One persistent container (`role` + `aria-label` with the count) plus roving
37
+ * focus plus a small pool of hotspot entities re-bound to whichever items
38
+ * currently occupy each visible slot — O(viewport) DOM nodes for an
39
+ * arbitrarily large dataset. The pattern is the `Tree`/`Table` hotspot
40
+ * precedent (`packages/ui/src/Tree.ts:98-113`, `packages/table/src/Table.ts`):
41
+ * a transparent, focusable child per visible row with a roving `tabIndex` and
42
+ * `pointerEvents: 'none'`, while the parent owns the keyboard model and the
43
+ * pool.
44
+ *
45
+ * Pointer ownership: neither the container nor the hotspots take the pointer
46
+ * (both project `pointer-events: none`), so a real click/drag reaches the
47
+ * owner's canvas handling or an underlying selectable-text mirror underneath.
48
+ * Keyboard focus and AT-synthesized `click` still work — the same contract the
49
+ * `Tree`/`Table` hotspots rely on. A mouse/touch owner forwards its own tap
50
+ * path into {@link activateItem}; `'onDemand'` alone is deliberately not the
51
+ * story here (also `content/reference/core-a11y.md:207-214`).
52
+ *
53
+ * Painting belongs to the owner: `render` is a no-op (like `RowHotspot`), so
54
+ * pair this with canvas-painted rows or subclass and override `render`.
55
+ */
56
+ export declare class VirtualizedSetAggregate extends Entity {
57
+ private _items;
58
+ private _label;
59
+ private _role;
60
+ private _itemRole;
61
+ private _rowHeight;
62
+ private _visibleCapacity;
63
+ private _onActivate;
64
+ /** First item index currently bound to the pool (the scroll window). */
65
+ private _visibleStart;
66
+ /** Item id owning the roving tab stop / keyboard focus. */
67
+ private _activeId;
68
+ private _selectedId;
69
+ /** One focusable hotspot per visible slot; re-bound, never rebuilt per item. */
70
+ private _hotspots;
71
+ constructor(opts?: VirtualizedSetAggregateOptions);
72
+ /** Full item count — the number the container label states. */
73
+ get itemCount(): number;
74
+ /** Live pool size (bounded by the visible capacity, never by the item count). */
75
+ get poolSize(): number;
76
+ /** First item index currently bound to the pool. */
77
+ get visibleStart(): number;
78
+ getA11yAttributes(): A11yAttributes;
79
+ render(_renderer: IRenderer): void;
80
+ /** Axis-aligned hit-test against the container box (the `UIComponent` default). */
81
+ isPointInside(globalX: number, globalY: number): boolean;
82
+ /** Replace the item set; the pool re-binds and the label count follows. */
83
+ setItems(items: VirtualizedSetItem[]): void;
84
+ /** Move the pool window to start at `start` (the scroll position). */
85
+ setVisibleStart(start: number): void;
86
+ /**
87
+ * Keep one hotspot per visible slot, positioned over it. The pool is sized
88
+ * to the viewport (capacity), each slot re-bound to whatever item currently
89
+ * occupies it — the `Tree._syncHotspots` shape, minus tree structure.
90
+ */
91
+ private _syncHotspots;
92
+ /** Whether `id` owns the roving tab stop: active, else selected, else first. */
93
+ isTabStop(id: string): boolean;
94
+ isSelected(id: string): boolean;
95
+ /** Item role the hotspots announce (kept on the parent: one source of truth). */
96
+ get itemRole(): string;
97
+ /** Activate an item (pointer tap-through or Enter/Space): selects and notifies. */
98
+ activateItem(id: string, focusIt?: boolean): void;
99
+ /** Move keyboard focus to the hotspot currently bound to `id`, if any. */
100
+ focusItem(id: string): void;
101
+ /**
102
+ * Aggregate keyboard model: Up/Down move the active item (scrolling the pool
103
+ * window so it stays bound), Home/End jump, Enter/Space activate. The active
104
+ * item is focused as it moves so focus is never stranded on a re-bound slot.
105
+ */
106
+ handleItemKey(e: KeyboardEvent, id: string): void;
107
+ /** Scroll the pool window just enough to keep `index` bound. */
108
+ private _ensureVisible;
109
+ update(_dt: number, _time: number): void;
110
+ }
package/dist/index.d.ts CHANGED
@@ -10,7 +10,12 @@ export * from './renderer/TextRasterCache';
10
10
  export * from './performance/UserTiming';
11
11
  export * from './tree/Entity';
12
12
  export * from './tree/Scene';
13
+ export * from './tree/scene/HitResult';
14
+ export * from './tree/scene/ProjectionBackend';
15
+ export * from './tree/scene/ProjectionPolicy';
16
+ export * from './tree/scene/SemanticProjectionPolicy';
13
17
  export * from './components/TextEntity';
18
+ export * from './components/VirtualizedSetAggregate';
14
19
  export * from './components/GridTextEntity';
15
20
  export * from './components/SplineEntity';
16
21
  export * from './components/Rect';