@vectojs/core 1.27.1 → 1.28.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.
package/dist/index.js CHANGED
@@ -3893,6 +3893,7 @@ var Scene = (_class7 = class _Scene {
3893
3893
  let el = this.a11yElements.get(node.id);
3894
3894
  const attrs = node.getA11yAttributes();
3895
3895
  const expectedTag = attrs.tag || "div";
3896
+ let emitInitialScroll = null;
3896
3897
  if (el && el.tagName.toLowerCase() !== expectedTag.toLowerCase()) {
3897
3898
  if (el === this.focusedA11yElement) {
3898
3899
  this.focusedA11yElement = null;
@@ -3980,6 +3981,26 @@ var Scene = (_class7 = class _Scene {
3980
3981
  },
3981
3982
  { passive: false }
3982
3983
  );
3984
+ const scrollTarget = el;
3985
+ const emitScroll = () => {
3986
+ node.emit("scroll", {
3987
+ scrollTop: scrollTarget.scrollTop,
3988
+ scrollLeft: scrollTarget.scrollLeft,
3989
+ scrollHeight: scrollTarget.scrollHeight,
3990
+ scrollWidth: scrollTarget.scrollWidth,
3991
+ clientHeight: scrollTarget.clientHeight,
3992
+ clientWidth: scrollTarget.clientWidth
3993
+ });
3994
+ };
3995
+ el.addEventListener(
3996
+ "scroll",
3997
+ () => {
3998
+ emitScroll();
3999
+ this.markDirty();
4000
+ },
4001
+ { passive: true }
4002
+ );
4003
+ emitInitialScroll = emitScroll;
3983
4004
  el.addEventListener("keydown", (e) => {
3984
4005
  node.dispatchEvent(new (0, _chunkZ3HFY75Rjs.VectoJSEvent)("keydown", node, e));
3985
4006
  });
@@ -4210,6 +4231,7 @@ var Scene = (_class7 = class _Scene {
4210
4231
  if (el.style.padding !== padding) el.style.padding = padding;
4211
4232
  if (el.style.boxSizing !== "border-box") el.style.boxSizing = "border-box";
4212
4233
  if (el instanceof HTMLTextAreaElement) el.style.resize = "none";
4234
+ if (el.style.scrollbarWidth !== "none") el.style.scrollbarWidth = "none";
4213
4235
  }
4214
4236
  const nestedIn = container && attrs.role && container.owned.has(attrs.role) ? container : null;
4215
4237
  if (node.a11yFullViewport) {
@@ -4256,6 +4278,7 @@ var Scene = (_class7 = class _Scene {
4256
4278
  const display = visible ? "" : "none";
4257
4279
  if (el.style.display !== display) el.style.display = display;
4258
4280
  }
4281
+ _optionalChain([emitInitialScroll, 'optionalCall', _122 => _122()]);
4259
4282
  }
4260
4283
  if (this._phaseTiming) {
4261
4284
  const projectionStart = performance.now();
@@ -4494,9 +4517,9 @@ var Scene = (_class7 = class _Scene {
4494
4517
  for (let lineIndex = 0; lineIndex < grid.lines.length; lineIndex++) {
4495
4518
  const gridLine = grid.lines[lineIndex];
4496
4519
  const projectedLine = projectionLines[lineIndex];
4497
- const lineHeight = _nullishCoalesce(_optionalChain([projectedLine, 'optionalAccess', _122 => _122.lineHeight]), () => ( grid.lineHeight));
4498
- const baseline = _nullishCoalesce(_optionalChain([projectedLine, 'optionalAccess', _123 => _123.baseline]), () => ( grid.baseline));
4499
- const lineFont = _nullishCoalesce(_optionalChain([projectedLine, 'optionalAccess', _124 => _124.font]), () => ( grid.font));
4520
+ const lineHeight = _nullishCoalesce(_optionalChain([projectedLine, 'optionalAccess', _123 => _123.lineHeight]), () => ( grid.lineHeight));
4521
+ const baseline = _nullishCoalesce(_optionalChain([projectedLine, 'optionalAccess', _124 => _124.baseline]), () => ( grid.baseline));
4522
+ const lineFont = _nullishCoalesce(_optionalChain([projectedLine, 'optionalAccess', _125 => _125.font]), () => ( grid.font));
4500
4523
  const lineSignature = contentGridLineSignature(
4501
4524
  grid,
4502
4525
  gridLine,
@@ -4516,8 +4539,8 @@ var Scene = (_class7 = class _Scene {
4516
4539
  lineElement.dir = "ltr";
4517
4540
  lineElement.dataset.vectoGridLine = `${lineIndex}`;
4518
4541
  lineElement.style.position = "absolute";
4519
- lineElement.style.left = `${_nullishCoalesce(_optionalChain([projectedLine, 'optionalAccess', _125 => _125.x]), () => ( 0))}px`;
4520
- lineElement.style.top = `${(_nullishCoalesce(_optionalChain([projectedLine, 'optionalAccess', _126 => _126.y]), () => ( lineIndex * grid.lineHeight))) + baseline - _text.cssLineBoxBaseline.call(void 0, lineFont, lineHeight)}px`;
4542
+ lineElement.style.left = `${_nullishCoalesce(_optionalChain([projectedLine, 'optionalAccess', _126 => _126.x]), () => ( 0))}px`;
4543
+ lineElement.style.top = `${(_nullishCoalesce(_optionalChain([projectedLine, 'optionalAccess', _127 => _127.y]), () => ( lineIndex * grid.lineHeight))) + baseline - _text.cssLineBoxBaseline.call(void 0, lineFont, lineHeight)}px`;
4521
4544
  lineElement.style.width = `${gridLine.width}px`;
4522
4545
  lineElement.style.height = `${lineHeight}px`;
4523
4546
  lineElement.style.whiteSpace = "pre";
@@ -4587,7 +4610,7 @@ var Scene = (_class7 = class _Scene {
4587
4610
  if (selectionLine !== null && selectionLine >= grid.lines.length) {
4588
4611
  rebuiltSelectionLine = true;
4589
4612
  }
4590
- _optionalChain([el, 'access', _127 => _127.lastElementChild, 'optionalAccess', _128 => _128.remove, 'call', _129 => _129()]);
4613
+ _optionalChain([el, 'access', _128 => _128.lastElementChild, 'optionalAccess', _129 => _129.remove, 'call', _130 => _130()]);
4591
4614
  }
4592
4615
  if (rebuiltSelectionLine) this.releaseContentSelectionForRebuild(el);
4593
4616
  el.dataset.vectoProjectionLines = signature;
@@ -4651,7 +4674,7 @@ var Scene = (_class7 = class _Scene {
4651
4674
  if (previous !== void 0 && typeof cancelAnimationFrame === "function") {
4652
4675
  cancelAnimationFrame(previous);
4653
4676
  }
4654
- _optionalChain([this, 'access', _130 => _130.contentGridCalibrationProbes, 'access', _131 => _131.get, 'call', _132 => _132(entityId), 'optionalAccess', _133 => _133.remove, 'call', _134 => _134()]);
4677
+ _optionalChain([this, 'access', _131 => _131.contentGridCalibrationProbes, 'access', _132 => _132.get, 'call', _133 => _133(entityId), 'optionalAccess', _134 => _134.remove, 'call', _135 => _135()]);
4655
4678
  this.contentGridCalibrationProbes.delete(entityId);
4656
4679
  const calibrationStart = typeof performance !== "undefined" ? performance.now() : 0;
4657
4680
  const probe = document.createElement("div");
@@ -4685,7 +4708,7 @@ var Scene = (_class7 = class _Scene {
4685
4708
  target.dataset.vectoGridCalib = generation;
4686
4709
  continue;
4687
4710
  }
4688
- const sourceText = _nullishCoalesce(_optionalChain([target, 'access', _135 => _135.textContent, 'optionalAccess', _136 => _136.slice, 'call', _137 => _137(0, sourceLength)]), () => ( ""));
4711
+ const sourceText = _nullishCoalesce(_optionalChain([target, 'access', _136 => _136.textContent, 'optionalAccess', _137 => _137.slice, 'call', _138 => _138(0, sourceLength)]), () => ( ""));
4689
4712
  if (!sourceText) {
4690
4713
  target.dataset.vectoGridCalib = generation;
4691
4714
  continue;
@@ -4912,12 +4935,12 @@ var Scene = (_class7 = class _Scene {
4912
4935
  syncOverlayGeometry() {
4913
4936
  const parent = this.canvas.parentElement;
4914
4937
  if (!parent) return;
4915
- const canvasRect = _optionalChain([this, 'access', _138 => _138.canvas, 'access', _139 => _139.getBoundingClientRect, 'optionalCall', _140 => _140()]);
4916
- const parentRect = _optionalChain([parent, 'access', _141 => _141.getBoundingClientRect, 'optionalCall', _142 => _142()]);
4917
- const cssWidth = _optionalChain([canvasRect, 'optionalAccess', _143 => _143.width]) || this.canvas.clientWidth || this.width;
4918
- const cssHeight = _optionalChain([canvasRect, 'optionalAccess', _144 => _144.height]) || this.canvas.clientHeight || this.height;
4919
- const left = (_nullishCoalesce(_optionalChain([canvasRect, 'optionalAccess', _145 => _145.left]), () => ( 0))) - (_nullishCoalesce(_optionalChain([parentRect, 'optionalAccess', _146 => _146.left]), () => ( 0))) - (parent.clientLeft || 0) + parent.scrollLeft;
4920
- const top = (_nullishCoalesce(_optionalChain([canvasRect, 'optionalAccess', _147 => _147.top]), () => ( 0))) - (_nullishCoalesce(_optionalChain([parentRect, 'optionalAccess', _148 => _148.top]), () => ( 0))) - (parent.clientTop || 0) + parent.scrollTop;
4938
+ const canvasRect = _optionalChain([this, 'access', _139 => _139.canvas, 'access', _140 => _140.getBoundingClientRect, 'optionalCall', _141 => _141()]);
4939
+ const parentRect = _optionalChain([parent, 'access', _142 => _142.getBoundingClientRect, 'optionalCall', _143 => _143()]);
4940
+ const cssWidth = _optionalChain([canvasRect, 'optionalAccess', _144 => _144.width]) || this.canvas.clientWidth || this.width;
4941
+ const cssHeight = _optionalChain([canvasRect, 'optionalAccess', _145 => _145.height]) || this.canvas.clientHeight || this.height;
4942
+ const left = (_nullishCoalesce(_optionalChain([canvasRect, 'optionalAccess', _146 => _146.left]), () => ( 0))) - (_nullishCoalesce(_optionalChain([parentRect, 'optionalAccess', _147 => _147.left]), () => ( 0))) - (parent.clientLeft || 0) + parent.scrollLeft;
4943
+ const top = (_nullishCoalesce(_optionalChain([canvasRect, 'optionalAccess', _148 => _148.top]), () => ( 0))) - (_nullishCoalesce(_optionalChain([parentRect, 'optionalAccess', _149 => _149.top]), () => ( 0))) - (parent.clientTop || 0) + parent.scrollTop;
4921
4944
  const scaleX = this.width > 0 ? cssWidth / this.width : 1;
4922
4945
  const scaleY = this.height > 0 ? cssHeight / this.height : 1;
4923
4946
  const prev = this._overlayGeometry;
@@ -5056,7 +5079,7 @@ var Scene = (_class7 = class _Scene {
5056
5079
  * (and {@link respectReducedMotion} is on). `0` means uncapped.
5057
5080
  */
5058
5081
  effectiveMaxFPS() {
5059
- const reduced = this.respectReducedMotion && !!_optionalChain([this, 'access', _149 => _149.reducedMotionQuery, 'optionalAccess', _150 => _150.matches]);
5082
+ const reduced = this.respectReducedMotion && !!_optionalChain([this, 'access', _150 => _150.reducedMotionQuery, 'optionalAccess', _151 => _151.matches]);
5060
5083
  if (reduced)
5061
5084
  return this.maxFPS > 0 ? Math.min(this.maxFPS, REDUCED_MOTION_FPS) : REDUCED_MOTION_FPS;
5062
5085
  return this.maxFPS;
@@ -5151,7 +5174,7 @@ var Scene = (_class7 = class _Scene {
5151
5174
  * @param time - Current absolute time in milliseconds (default 0).
5152
5175
  */
5153
5176
  render(renderer, dt = 0, time = 0) {
5154
- if (_optionalChain([renderer, 'access', _151 => _151.isContextLost, 'optionalCall', _152 => _152()])) return;
5177
+ if (_optionalChain([renderer, 'access', _152 => _152.isContextLost, 'optionalCall', _153 => _153()])) return;
5155
5178
  const isMainRenderer = renderer === this.renderer;
5156
5179
  if (isMainRenderer && this.a11yRoot && this.canvas.parentElement) {
5157
5180
  const parentStyle = this.canvas.parentElement.style;
@@ -5295,7 +5318,7 @@ var Scene = (_class7 = class _Scene {
5295
5318
  }
5296
5319
  renderer.clear();
5297
5320
  if (isMainRenderer) {
5298
- _optionalChain([this, 'access', _153 => _153.pointRenderer, 'optionalAccess', _154 => _154.begin, 'call', _155 => _155()]);
5321
+ _optionalChain([this, 'access', _154 => _154.pointRenderer, 'optionalAccess', _155 => _155.begin, 'call', _156 => _156()]);
5299
5322
  }
5300
5323
  const vw = this.width;
5301
5324
  const vh = this.height;
@@ -5509,9 +5532,9 @@ var Scene = (_class7 = class _Scene {
5509
5532
  const flushT0 = this._phaseTiming ? performance.now() : 0;
5510
5533
  renderer.flush();
5511
5534
  if (isMainRenderer) {
5512
- _optionalChain([this, 'access', _156 => _156.pointRenderer, 'optionalAccess', _157 => _157.flush, 'call', _158 => _158()]);
5535
+ _optionalChain([this, 'access', _157 => _157.pointRenderer, 'optionalAccess', _158 => _158.flush, 'call', _159 => _159()]);
5513
5536
  }
5514
- _optionalChain([renderer, 'access', _159 => _159.present, 'optionalCall', _160 => _160()]);
5537
+ _optionalChain([renderer, 'access', _160 => _160.present, 'optionalCall', _161 => _161()]);
5515
5538
  if (this._phaseTiming) this._recordPhase("flush", performance.now() - flushT0);
5516
5539
  if (flushTiming) endVectoUserTiming(flushTiming);
5517
5540
  if (this._devActive) {
@@ -5792,8 +5815,8 @@ function pointInBounds(b, x, y) {
5792
5815
  function contentGridLineSignature(grid, line, projected, lineHeight, baseline, font, isFirstLine) {
5793
5816
  const parts = [
5794
5817
  // Line box: position, size, and the font that resolves its baseline.
5795
- `${_nullishCoalesce(_optionalChain([projected, 'optionalAccess', _161 => _161.x]), () => ( 0))}`,
5796
- `${_nullishCoalesce(_optionalChain([projected, 'optionalAccess', _162 => _162.y]), () => ( ""))}`,
5818
+ `${_nullishCoalesce(_optionalChain([projected, 'optionalAccess', _162 => _162.x]), () => ( 0))}`,
5819
+ `${_nullishCoalesce(_optionalChain([projected, 'optionalAccess', _163 => _163.y]), () => ( ""))}`,
5797
5820
  `${lineHeight}`,
5798
5821
  `${baseline}`,
5799
5822
  font,
@@ -5980,7 +6003,7 @@ var GridTextEntity = (_class9 = class extends _chunkZ3HFY75Rjs.Entity {
5980
6003
  updateGrid(ascii) {
5981
6004
  this.grid = ascii;
5982
6005
  this.rows = ascii.length;
5983
- this.cols = _optionalChain([ascii, 'access', _163 => _163[0], 'optionalAccess', _164 => _164.length]) || 0;
6006
+ this.cols = _optionalChain([ascii, 'access', _164 => _164[0], 'optionalAccess', _165 => _165.length]) || 0;
5984
6007
  }
5985
6008
  isPointInside(_globalX, _globalY) {
5986
6009
  return false;
@@ -6090,7 +6113,7 @@ var SplineEntity = (_class10 = class extends _chunkZ3HFY75Rjs.Entity {
6090
6113
  this.width = this.bounds.width;
6091
6114
  this.height = this.bounds.height;
6092
6115
  const isGradient = (c) => c !== null && !Array.isArray(c);
6093
- this.containsGradient = (_nullishCoalesce(_optionalChain([this, 'access', _165 => _165.doc, 'access', _166 => _166.equations, 'optionalAccess', _167 => _167.some, 'call', _168 => _168((eq) => isGradient(eq.color_rgb))]), () => ( false))) || (_nullishCoalesce(_optionalChain([this, 'access', _169 => _169.doc, 'access', _170 => _170.paths, 'optionalAccess', _171 => _171.some, 'call', _172 => _172((p) => isGradient(p.color_rgb))]), () => ( false)));
6116
+ this.containsGradient = (_nullishCoalesce(_optionalChain([this, 'access', _166 => _166.doc, 'access', _167 => _167.equations, 'optionalAccess', _168 => _168.some, 'call', _169 => _169((eq) => isGradient(eq.color_rgb))]), () => ( false))) || (_nullishCoalesce(_optionalChain([this, 'access', _170 => _170.doc, 'access', _171 => _171.paths, 'optionalAccess', _172 => _172.some, 'call', _173 => _173((p) => isGradient(p.color_rgb))]), () => ( false)));
6094
6117
  this.interactive = true;
6095
6118
  }
6096
6119
  computeBounds() {
package/dist/index.mjs CHANGED
@@ -3892,6 +3892,7 @@ var Scene = class _Scene {
3892
3892
  let el = this.a11yElements.get(node.id);
3893
3893
  const attrs = node.getA11yAttributes();
3894
3894
  const expectedTag = attrs.tag || "div";
3895
+ let emitInitialScroll = null;
3895
3896
  if (el && el.tagName.toLowerCase() !== expectedTag.toLowerCase()) {
3896
3897
  if (el === this.focusedA11yElement) {
3897
3898
  this.focusedA11yElement = null;
@@ -3979,6 +3980,26 @@ var Scene = class _Scene {
3979
3980
  },
3980
3981
  { passive: false }
3981
3982
  );
3983
+ const scrollTarget = el;
3984
+ const emitScroll = () => {
3985
+ node.emit("scroll", {
3986
+ scrollTop: scrollTarget.scrollTop,
3987
+ scrollLeft: scrollTarget.scrollLeft,
3988
+ scrollHeight: scrollTarget.scrollHeight,
3989
+ scrollWidth: scrollTarget.scrollWidth,
3990
+ clientHeight: scrollTarget.clientHeight,
3991
+ clientWidth: scrollTarget.clientWidth
3992
+ });
3993
+ };
3994
+ el.addEventListener(
3995
+ "scroll",
3996
+ () => {
3997
+ emitScroll();
3998
+ this.markDirty();
3999
+ },
4000
+ { passive: true }
4001
+ );
4002
+ emitInitialScroll = emitScroll;
3982
4003
  el.addEventListener("keydown", (e) => {
3983
4004
  node.dispatchEvent(new VectoJSEvent("keydown", node, e));
3984
4005
  });
@@ -4209,6 +4230,7 @@ var Scene = class _Scene {
4209
4230
  if (el.style.padding !== padding) el.style.padding = padding;
4210
4231
  if (el.style.boxSizing !== "border-box") el.style.boxSizing = "border-box";
4211
4232
  if (el instanceof HTMLTextAreaElement) el.style.resize = "none";
4233
+ if (el.style.scrollbarWidth !== "none") el.style.scrollbarWidth = "none";
4212
4234
  }
4213
4235
  const nestedIn = container && attrs.role && container.owned.has(attrs.role) ? container : null;
4214
4236
  if (node.a11yFullViewport) {
@@ -4255,6 +4277,7 @@ var Scene = class _Scene {
4255
4277
  const display = visible ? "" : "none";
4256
4278
  if (el.style.display !== display) el.style.display = display;
4257
4279
  }
4280
+ emitInitialScroll?.();
4258
4281
  }
4259
4282
  if (this._phaseTiming) {
4260
4283
  const projectionStart = performance.now();
@@ -374,7 +374,30 @@ export interface A11yAttributes {
374
374
  /**
375
375
  * Union of all pointer/interaction events that can be emitted by an {@link Entity}.
376
376
  */
377
- export type VectoEvent = 'click' | 'dblclick' | 'hover' | 'pointerdown' | 'pointerup' | 'pointercancel' | 'pointermove' | 'pointerleave' | 'change' | 'focus' | 'blur' | 'wheel' | 'keydown' | 'keyup';
377
+ export type VectoEvent = 'click' | 'dblclick' | 'hover' | 'pointerdown' | 'pointerup' | 'pointercancel' | 'pointermove' | 'pointerleave' | 'change' | 'focus' | 'blur' | 'wheel' | 'scroll' | 'keydown' | 'keyup';
378
+ /**
379
+ * Payload of the {@link VectoEvent} `'scroll'`: the scroll geometry of an
380
+ * entity's accessibility/automation shadow node, in CSS pixels.
381
+ *
382
+ * An entity that paints its own view of scrollable content (a text editor, a
383
+ * list) should treat these as authoritative while the mirror exists — the
384
+ * browser resolved them against the same content, and any offset the element
385
+ * reports (`selectionStart` from a click) is relative to them.
386
+ */
387
+ export interface ScrollEventPayload {
388
+ /** The mirror's vertical scroll offset. */
389
+ scrollTop: number;
390
+ /** The mirror's horizontal scroll offset. */
391
+ scrollLeft: number;
392
+ /** Full scrollable content height, including the part out of view. */
393
+ scrollHeight: number;
394
+ /** Full scrollable content width, including the part out of view. */
395
+ scrollWidth: number;
396
+ /** Visible height inside the mirror's padding box (excludes any scrollbar). */
397
+ clientHeight: number;
398
+ /** Visible width inside the mirror's padding box (excludes any scrollbar). */
399
+ clientWidth: number;
400
+ }
378
401
  /** Options for {@link Entity.on} / {@link Entity.off}. */
379
402
  export interface ListenerOptions {
380
403
  /** Register the listener for the capture phase (root→target) instead of bubble. */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vectojs/core",
3
- "version": "1.27.1",
3
+ "version": "1.28.0",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -65,7 +65,7 @@
65
65
  },
66
66
  "dependencies": {
67
67
  "@vectojs/animation": "^0.1.1",
68
- "@vectojs/layout": "^0.5.0",
68
+ "@vectojs/layout": "^0.6.0",
69
69
  "@vectojs/math": "^0.1.1",
70
70
  "@vectojs/text": "^0.3.0"
71
71
  },