virtual-tree-canvas 0.3.0 → 0.3.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "virtual-tree-canvas",
3
- "version": "0.3.0",
3
+ "version": "0.3.1",
4
4
  "description": "High-performance Canvas2D virtual tree/table widget for very large hierarchical datasets.",
5
5
  "type": "module",
6
6
  "main": "./src/index.js",
@@ -28,19 +28,21 @@ export class Canvas2DRenderer {
28
28
  if (!this.canvas || !this.ctx || !this.scene) return;
29
29
  const { viewport } = frameState;
30
30
  const dpr = Math.max(1, window.devicePixelRatio || 1);
31
- const width = Math.floor(this.canvas.clientWidth * dpr);
32
- const height = Math.floor(this.canvas.clientHeight * dpr);
31
+ const viewportWidth = Math.max(0, viewport.viewportWidth);
32
+ const viewportHeight = Math.max(0, viewport.viewportHeight);
33
+ if (viewportWidth <= 0 || viewportHeight <= 0) return;
34
+ const width = Math.floor(viewportWidth * dpr);
35
+ const height = Math.floor(viewportHeight * dpr);
33
36
  if (this.canvas.width !== width || this.canvas.height !== height) {
34
37
  this.canvas.width = width;
35
38
  this.canvas.height = height;
36
- viewport.resize(this.canvas.clientWidth, this.canvas.clientHeight);
37
39
  }
38
40
 
39
41
  const ctx = this.ctx;
40
42
  const theme = this.themeManager?.get() ?? {};
41
43
  ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
42
44
  ctx.fillStyle = theme.background ?? '#101419';
43
- ctx.fillRect(0, 0, this.canvas.clientWidth, this.canvas.clientHeight);
45
+ ctx.fillRect(0, 0, viewportWidth, viewportHeight);
44
46
 
45
47
  this.visibleNodeIndices = cullLayoutNodes(this.scene.layout.nodes, viewport.getWorldBounds());
46
48
  const visibleSet = new Set(this.visibleNodeIndices);
@@ -35,19 +35,21 @@ export class TreeRowRenderer {
35
35
  if (!this.canvas || !this.ctx || !this.scene) return;
36
36
  const { viewport, theme } = this.scene;
37
37
  const dpr = Math.max(1, window.devicePixelRatio || 1);
38
- const width = Math.floor(this.canvas.clientWidth * dpr);
39
- const height = Math.floor(this.canvas.clientHeight * dpr);
38
+ const viewportWidth = Math.max(0, viewport.viewportWidth);
39
+ const viewportHeight = Math.max(0, viewport.viewportHeight);
40
+ if (viewportWidth <= 0 || viewportHeight <= 0) return;
41
+ const width = Math.floor(viewportWidth * dpr);
42
+ const height = Math.floor(viewportHeight * dpr);
40
43
  if (this.canvas.width !== width || this.canvas.height !== height) {
41
44
  this.canvas.width = width;
42
45
  this.canvas.height = height;
43
- viewport.resize(this.canvas.clientWidth, this.canvas.clientHeight);
44
46
  }
45
47
 
46
48
  const ctx = this.ctx;
47
49
  const colors = theme.colors;
48
50
  ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
49
51
  ctx.fillStyle = colors.background;
50
- ctx.fillRect(0, 0, this.canvas.clientWidth, this.canvas.clientHeight);
52
+ ctx.fillRect(0, 0, viewportWidth, viewportHeight);
51
53
 
52
54
  ctx.save();
53
55
  ctx.translate(viewport.renderInsetX ?? 0, viewport.renderInsetY ?? 0);
@@ -63,6 +63,7 @@ export class TreeViewController {
63
63
  this.canvas = canvas;
64
64
  this.renderer.initialize(canvas);
65
65
  this.renderer.setScene(this.scene);
66
+ this.#observeCanvasSize();
66
67
  return this;
67
68
  }
68
69
 
@@ -564,7 +565,6 @@ export class TreeViewController {
564
565
  }
565
566
 
566
567
  renderMeasured(time = performance.now()) {
567
- this.#syncViewportFromCanvas();
568
568
  const sceneStart = performance.now();
569
569
  this.scene = this.createRenderScene();
570
570
  const sceneMs = performance.now() - sceneStart;
@@ -830,15 +830,16 @@ export class TreeViewController {
830
830
  return Math.max(0, Math.floor(this.viewport.scrollY / this.rowModel.rowHeight));
831
831
  }
832
832
 
833
- #syncViewportFromCanvas() {
834
- if (!this.canvas) return;
835
- const width = this.canvas.clientWidth;
836
- const height = this.canvas.clientHeight;
837
- if (width > 0 && height > 0 && (this.viewport.viewportWidth !== width || this.viewport.viewportHeight !== height)) {
838
- this.viewport.resize(width, height);
839
- this.#fitInspectorPaneColumn(width);
840
- this.#syncContentSize();
841
- }
833
+ #observeCanvasSize() {
834
+ if (!this.canvas || typeof ResizeObserver === 'undefined') return;
835
+ this.#resizeObserver?.disconnect();
836
+ this.#resizeObserver = new ResizeObserver((entries) => {
837
+ const entry = entries[0];
838
+ const width = Math.floor(entry?.contentRect?.width ?? 0);
839
+ const height = Math.floor(entry?.contentRect?.height ?? 0);
840
+ if (width > 0 && height > 0) this.resize(width, height);
841
+ });
842
+ this.#resizeObserver.observe(this.canvas);
842
843
  }
843
844
 
844
845
  #computeInspectorPaneLabelEnd(visibleRange) {
@@ -901,6 +902,8 @@ export class TreeViewController {
901
902
  this.#rebuildRows();
902
903
  if (focusId) this.focusedId = focusId;
903
904
  }
905
+
906
+ #resizeObserver = null;
904
907
  }
905
908
 
906
909
  function inspectorPaneLayout(width, depth = 0, indentWidth = 18, editorType = '', labelEnd = 0) {