@opendata-ai/openchart-vanilla 8.0.0-rc.2 → 8.0.0-rc.21

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.
Files changed (145) hide show
  1. package/dist/{chunk-W34KN7FD.js → chunk-2NAQRP66.js} +2 -2
  2. package/dist/chunk-DCODCLWI.js +234 -0
  3. package/dist/chunk-DCODCLWI.js.map +1 -0
  4. package/dist/{chunk-5EOV5JQZ.js → chunk-EKAUQAAX.js} +50 -46
  5. package/dist/chunk-EKAUQAAX.js.map +1 -0
  6. package/dist/{chunk-ENXSUXC5.js → chunk-KNT5AZ2O.js} +7309 -5490
  7. package/dist/chunk-KNT5AZ2O.js.map +1 -0
  8. package/dist/chunk-RM5XS6NR.js +113 -0
  9. package/dist/chunk-RM5XS6NR.js.map +1 -0
  10. package/dist/chunk-T32UHMZA.js +282 -0
  11. package/dist/chunk-T32UHMZA.js.map +1 -0
  12. package/dist/export-gif.d.ts +113 -0
  13. package/dist/export-gif.js +21 -0
  14. package/dist/export-gif.js.map +1 -0
  15. package/dist/index.d.ts +283 -24
  16. package/dist/index.js +2012 -763
  17. package/dist/index.js.map +1 -1
  18. package/dist/{mount-CUKQLeqD.d.ts → mount-Dvv8NYIv.d.ts} +117 -3
  19. package/dist/simulation-worker.js +83 -2
  20. package/dist/static.js +7 -69
  21. package/dist/static.js.map +1 -1
  22. package/dist/story/index.d.ts +3 -2
  23. package/dist/story/index.js +5 -3
  24. package/dist/story/index.js.map +1 -1
  25. package/dist/styles.css +1 -1
  26. package/dist/styles.css.map +1 -1
  27. package/package.json +14 -6
  28. package/dist/chunk-5EOV5JQZ.js.map +0 -1
  29. package/dist/chunk-ENXSUXC5.js.map +0 -1
  30. package/src/__test-fixtures__/dom.ts +0 -70
  31. package/src/__test-fixtures__/specs.ts +0 -214
  32. package/src/__tests__/animation.test.ts +0 -358
  33. package/src/__tests__/annotations-render.test.ts +0 -201
  34. package/src/__tests__/compound-labels.test.ts +0 -122
  35. package/src/__tests__/continuous-legend.test.ts +0 -91
  36. package/src/__tests__/crosshair.test.ts +0 -130
  37. package/src/__tests__/edit-events.test.ts +0 -902
  38. package/src/__tests__/events.test.ts +0 -387
  39. package/src/__tests__/export.test.ts +0 -241
  40. package/src/__tests__/font-race.test.ts +0 -199
  41. package/src/__tests__/gradient-ids.test.ts +0 -159
  42. package/src/__tests__/gradient-utils.test.ts +0 -125
  43. package/src/__tests__/known-bugs-render.test.ts +0 -183
  44. package/src/__tests__/map.test.ts +0 -293
  45. package/src/__tests__/mount.test.ts +0 -357
  46. package/src/__tests__/pattern-fills.test.ts +0 -105
  47. package/src/__tests__/resize-timing.test.ts +0 -218
  48. package/src/__tests__/sankey.test.ts +0 -133
  49. package/src/__tests__/selection-events.test.ts +0 -869
  50. package/src/__tests__/series-search.test.ts +0 -311
  51. package/src/__tests__/static.test.ts +0 -141
  52. package/src/__tests__/svg-renderer.test.ts +0 -895
  53. package/src/__tests__/table-keyboard.test.ts +0 -361
  54. package/src/__tests__/table-mount.test.ts +0 -639
  55. package/src/__tests__/tilemap.test.ts +0 -158
  56. package/src/__tests__/tooltip.test.ts +0 -337
  57. package/src/__tests__/transition.test.ts +0 -1777
  58. package/src/__tests__/you-draw-it.test.ts +0 -273
  59. package/src/animation-vars.ts +0 -42
  60. package/src/animation.ts +0 -76
  61. package/src/barlist-mount.ts +0 -383
  62. package/src/barlist-renderer.ts +0 -267
  63. package/src/dom-helpers.ts +0 -17
  64. package/src/export.ts +0 -482
  65. package/src/gradient-utils.ts +0 -138
  66. package/src/graph/__tests__/canvas-renderer.test.ts +0 -713
  67. package/src/graph/__tests__/graph-mount.test.ts +0 -213
  68. package/src/graph/__tests__/interaction.test.ts +0 -205
  69. package/src/graph/__tests__/keyboard.test.ts +0 -653
  70. package/src/graph/__tests__/search.test.ts +0 -88
  71. package/src/graph/__tests__/simulation.test.ts +0 -233
  72. package/src/graph/__tests__/spatial-index.test.ts +0 -142
  73. package/src/graph/__tests__/zoom.test.ts +0 -203
  74. package/src/graph/canvas-renderer.ts +0 -747
  75. package/src/graph/interaction.ts +0 -367
  76. package/src/graph/keyboard.ts +0 -208
  77. package/src/graph/search.ts +0 -50
  78. package/src/graph/simulation-worker-url.ts +0 -12
  79. package/src/graph/simulation-worker.ts +0 -278
  80. package/src/graph/simulation.ts +0 -422
  81. package/src/graph/spatial-index.ts +0 -121
  82. package/src/graph/types.ts +0 -47
  83. package/src/graph/worker-protocol.ts +0 -70
  84. package/src/graph/zoom.ts +0 -134
  85. package/src/graph-mount.ts +0 -888
  86. package/src/index.ts +0 -76
  87. package/src/interactions/chart-events.ts +0 -139
  88. package/src/interactions/crosshair.ts +0 -233
  89. package/src/interactions/drag-handler.ts +0 -175
  90. package/src/interactions/editing-drags.ts +0 -515
  91. package/src/interactions/index.ts +0 -25
  92. package/src/interactions/keyboard-nav.ts +0 -111
  93. package/src/interactions/legend-interaction.ts +0 -46
  94. package/src/interactions/selection.ts +0 -280
  95. package/src/interactions/tooltip-events.ts +0 -72
  96. package/src/map-camera.ts +0 -88
  97. package/src/map-mount.ts +0 -701
  98. package/src/map-renderer.ts +0 -338
  99. package/src/map-transition.ts +0 -83
  100. package/src/measure-text.ts +0 -134
  101. package/src/mount.ts +0 -1382
  102. package/src/pattern-utils.ts +0 -110
  103. package/src/renderers/annotations.ts +0 -388
  104. package/src/renderers/axes.ts +0 -351
  105. package/src/renderers/brand.ts +0 -87
  106. package/src/renderers/chrome.ts +0 -196
  107. package/src/renderers/endpoint-labels.ts +0 -150
  108. package/src/renderers/legend.ts +0 -311
  109. package/src/renderers/marks.ts +0 -561
  110. package/src/renderers/metrics.ts +0 -63
  111. package/src/renderers/svg-dom.ts +0 -40
  112. package/src/renderers/table-cells.ts +0 -446
  113. package/src/resize-observer.ts +0 -46
  114. package/src/sankey-mount.ts +0 -622
  115. package/src/sankey-renderer.ts +0 -614
  116. package/src/series-search.ts +0 -392
  117. package/src/static.ts +0 -251
  118. package/src/story/__tests__/camera-math.test.ts +0 -145
  119. package/src/story/__tests__/create-chart-story.test.ts +0 -317
  120. package/src/story/__tests__/progress-math.test.ts +0 -95
  121. package/src/story/__tests__/scroll-driver.test.ts +0 -130
  122. package/src/story/__tests__/tween.test.ts +0 -159
  123. package/src/story/camera-math.ts +0 -125
  124. package/src/story/create-chart-story.ts +0 -353
  125. package/src/story/crossfade.ts +0 -70
  126. package/src/story/index.ts +0 -39
  127. package/src/story/progress-math.ts +0 -85
  128. package/src/story/resolve-camera-target.ts +0 -119
  129. package/src/story/scroll-driver.ts +0 -206
  130. package/src/story/story-camera.ts +0 -49
  131. package/src/story/tween.ts +0 -112
  132. package/src/story/types.ts +0 -76
  133. package/src/svg-ids.ts +0 -23
  134. package/src/svg-renderer.ts +0 -383
  135. package/src/table-keyboard.ts +0 -266
  136. package/src/table-mount.ts +0 -567
  137. package/src/table-renderer.ts +0 -414
  138. package/src/text-edit-overlay.ts +0 -255
  139. package/src/theme-tokens.ts +0 -51
  140. package/src/tilemap-mount.ts +0 -511
  141. package/src/tilemap-renderer.ts +0 -396
  142. package/src/tooltip.ts +0 -177
  143. package/src/transition.ts +0 -2816
  144. package/src/you-draw-it.ts +0 -480
  145. /package/dist/{chunk-W34KN7FD.js.map → chunk-2NAQRP66.js.map} +0 -0
@@ -1,121 +0,0 @@
1
- /**
2
- * Spatial index for fast node hit-testing.
3
- *
4
- * Wraps d3-quadtree to provide findNearest (accounts for node radius)
5
- * and findInRect queries. Tracks a generation counter to avoid unnecessary
6
- * rebuilds when positions haven't changed.
7
- */
8
-
9
- import { type Quadtree, quadtree } from 'd3-quadtree';
10
- import type { PositionedNode } from './types';
11
-
12
- export class SpatialIndex {
13
- private tree: Quadtree<PositionedNode> | null = null;
14
- private nodes: PositionedNode[] = [];
15
- private maxRadius = 0;
16
- private generation = 0;
17
-
18
- /** Rebuild the quadtree from the current set of positioned nodes. */
19
- rebuild(nodes: PositionedNode[]): void {
20
- this.nodes = nodes;
21
- this.maxRadius = 0;
22
- for (const n of nodes) {
23
- if (n.radius > this.maxRadius) this.maxRadius = n.radius;
24
- }
25
-
26
- this.tree = quadtree<PositionedNode>()
27
- .x((d) => d.x)
28
- .y((d) => d.y)
29
- .addAll(nodes);
30
- this.generation++;
31
- }
32
-
33
- /** Current generation counter. Increments on each rebuild. */
34
- getGeneration(): number {
35
- return this.generation;
36
- }
37
-
38
- /**
39
- * Find the nearest node to (x, y) within maxDistance.
40
- * Accounts for node radius: a hit occurs if the point is inside
41
- * the node circle (distance to center < node.radius), or if the
42
- * edge-to-edge distance is within maxDistance.
43
- */
44
- findNearest(x: number, y: number, maxDistance: number = Infinity): PositionedNode | null {
45
- if (!this.tree || this.nodes.length === 0) return null;
46
-
47
- // The effective search radius for the quadtree needs to include
48
- // the largest node radius, because we might be "inside" a large node
49
- // whose center is far from our search point.
50
- const searchRadius = maxDistance + this.maxRadius;
51
-
52
- let best: PositionedNode | null = null;
53
- let bestEffectiveDist = maxDistance + this.maxRadius + 1;
54
-
55
- this.tree.visit((node, x0, y0, x1, y1) => {
56
- // Closest point in this quad to our target
57
- const closestX = Math.max(x0, Math.min(x, x1));
58
- const closestY = Math.max(y0, Math.min(y, y1));
59
- const quadDist = Math.hypot(closestX - x, closestY - y);
60
-
61
- // Prune: if the closest edge of this quad is beyond searchRadius, skip
62
- if (quadDist > searchRadius) return true;
63
-
64
- // Check leaf data
65
- if (!node.length) {
66
- let current = node;
67
- do {
68
- const d = current.data;
69
- if (d) {
70
- const dist = Math.hypot(d.x - x, d.y - y);
71
- // Effective distance: subtract the node's radius.
72
- // If we're inside the circle, effective distance is 0.
73
- const effectiveDist = Math.max(0, dist - d.radius);
74
- if (effectiveDist <= maxDistance && effectiveDist < bestEffectiveDist) {
75
- bestEffectiveDist = effectiveDist;
76
- best = d;
77
- }
78
- }
79
- } while ((current = current.next!));
80
- }
81
-
82
- return false;
83
- });
84
-
85
- return best;
86
- }
87
-
88
- /** Find all nodes whose centers fall within the given rectangle. */
89
- findInRect(x1: number, y1: number, x2: number, y2: number): PositionedNode[] {
90
- if (!this.tree) return [];
91
-
92
- const minX = Math.min(x1, x2);
93
- const minY = Math.min(y1, y2);
94
- const maxX = Math.max(x1, x2);
95
- const maxY = Math.max(y1, y2);
96
-
97
- const results: PositionedNode[] = [];
98
-
99
- this.tree.visit((node, qx0, qy0, qx1, qy1) => {
100
- // If quad doesn't overlap the search rect, skip
101
- if (qx0 > maxX || qx1 < minX || qy0 > maxY || qy1 < minY) {
102
- return true;
103
- }
104
-
105
- // Check leaf nodes
106
- if (!node.length) {
107
- let current = node;
108
- do {
109
- const d = current.data;
110
- if (d && d.x >= minX && d.x <= maxX && d.y >= minY && d.y <= maxY) {
111
- results.push(d);
112
- }
113
- } while ((current = current.next!));
114
- }
115
-
116
- return false;
117
- });
118
-
119
- return results;
120
- }
121
- }
@@ -1,47 +0,0 @@
1
- /**
2
- * Shared types for the graph adapter.
3
- *
4
- * These extend the engine's compiled types with positional information set by
5
- * the force simulation at runtime. The engine produces CompiledGraphNode/Edge
6
- * objects with visual properties but no x/y coords. After simulation, we get
7
- * PositionedNode/Edge that the canvas renderer can draw.
8
- */
9
-
10
- import type { ResolvedTheme } from '@opendata-ai/openchart-core';
11
- import type { CompiledGraphEdge, CompiledGraphNode } from '@opendata-ai/openchart-engine';
12
-
13
- /** A compiled node with simulation-assigned x/y position. */
14
- export interface PositionedNode extends CompiledGraphNode {
15
- x: number;
16
- y: number;
17
- }
18
-
19
- /** A compiled edge with resolved source/target screen positions. */
20
- export interface PositionedEdge extends CompiledGraphEdge {
21
- sourceX: number;
22
- sourceY: number;
23
- targetX: number;
24
- targetY: number;
25
- }
26
-
27
- /**
28
- * Complete render state passed to the canvas renderer each frame.
29
- *
30
- * Assembled by the graph mount from simulation positions, interaction state,
31
- * and theme. The renderer is stateless -- it draws whatever this says.
32
- */
33
- export interface GraphRenderState {
34
- nodes: PositionedNode[];
35
- edges: PositionedEdge[];
36
- transform: { x: number; y: number; k: number };
37
- hoveredNodeId: string | null;
38
- hoveredEdgeId: string | null;
39
- selectedNodeIds: Set<string>;
40
- adjacencyMap: Map<string, Set<string>>;
41
- theme: ResolvedTheme;
42
- searchMatches: Set<string> | null;
43
- /** True during active pan/zoom gestures. Renderer skips labels and glow. */
44
- isGesturing: boolean;
45
- /** Whether the tryOpenData.ai watermark is enabled. */
46
- watermark: boolean;
47
- }
@@ -1,70 +0,0 @@
1
- /**
2
- * Message protocol between the main thread and the simulation Web Worker.
3
- *
4
- * Defines the shape of messages going in both directions, plus the internal
5
- * node/edge types the simulation works with. These are intentionally simple
6
- * and independent from the engine's compiled types so the worker can be
7
- * built as a standalone IIFE without workspace imports.
8
- */
9
-
10
- // ---------------------------------------------------------------------------
11
- // Simulation data shapes (used internally by worker + sync fallback)
12
- // ---------------------------------------------------------------------------
13
-
14
- /** Minimal node shape for the force simulation. */
15
- export interface SimNode {
16
- id: string;
17
- x?: number;
18
- y?: number;
19
- radius: number;
20
- community?: string;
21
- }
22
-
23
- /** Minimal edge shape for the force simulation. */
24
- export interface SimEdge {
25
- source: string;
26
- target: string;
27
- }
28
-
29
- /** Inline simulation config (mirrors engine SimulationConfig). */
30
- export interface WorkerSimulationConfig {
31
- chargeStrength: number;
32
- linkDistance: number;
33
- clustering: { field: string; strength: number } | null;
34
- alphaDecay: number;
35
- velocityDecay: number;
36
- collisionRadius: number;
37
- collisionPadding?: number;
38
- linkStrength?: number;
39
- centerForce?: boolean;
40
- }
41
-
42
- // ---------------------------------------------------------------------------
43
- // Main -> Worker messages
44
- // ---------------------------------------------------------------------------
45
-
46
- export type WorkerInMessage =
47
- | {
48
- type: 'init';
49
- nodes: SimNode[];
50
- edges: SimEdge[];
51
- config: WorkerSimulationConfig;
52
- }
53
- | { type: 'reheat'; alpha?: number }
54
- | { type: 'pin'; nodeId: string; x: number; y: number }
55
- | { type: 'unpin'; nodeId: string }
56
- | { type: 'drag'; nodeId: string; x: number; y: number }
57
- | { type: 'stop' };
58
-
59
- // ---------------------------------------------------------------------------
60
- // Worker -> Main messages
61
- // ---------------------------------------------------------------------------
62
-
63
- export type WorkerOutMessage =
64
- | {
65
- type: 'positions';
66
- nodes: Array<{ id: string; x: number; y: number }>;
67
- alpha: number;
68
- }
69
- | { type: 'settled' }
70
- | { type: 'error'; message: string };
package/src/graph/zoom.ts DELETED
@@ -1,134 +0,0 @@
1
- /**
2
- * Immutable zoom transform for graph pan/zoom.
3
- *
4
- * Provides coordinate conversion between screen space (canvas pixels)
5
- * and graph space (simulation coordinates). All mutations return new
6
- * instances rather than modifying in place.
7
- */
8
-
9
- import type { PositionedNode } from './types';
10
-
11
- export class ZoomTransform {
12
- constructor(
13
- readonly x: number,
14
- readonly y: number,
15
- readonly k: number,
16
- ) {}
17
-
18
- /** Convert screen coordinates to graph coordinates. */
19
- screenToGraph(sx: number, sy: number): { x: number; y: number } {
20
- return {
21
- x: (sx - this.x) / this.k,
22
- y: (sy - this.y) / this.k,
23
- };
24
- }
25
-
26
- /** Convert graph coordinates to screen coordinates. */
27
- graphToScreen(gx: number, gy: number): { x: number; y: number } {
28
- return {
29
- x: gx * this.k + this.x,
30
- y: gy * this.k + this.y,
31
- };
32
- }
33
-
34
- /**
35
- * Zoom to a target scale, keeping the given screen-space pivot
36
- * point fixed (content under the cursor stays under the cursor).
37
- */
38
- zoomAt(targetK: number, pivotX: number, pivotY: number): ZoomTransform {
39
- // The graph point under the pivot should remain at the same screen position.
40
- // Before: pivotX = gx * k + x => gx = (pivotX - x) / k
41
- // After: pivotX = gx * targetK + newX => newX = pivotX - gx * targetK
42
- const gx = (pivotX - this.x) / this.k;
43
- const gy = (pivotY - this.y) / this.k;
44
- return new ZoomTransform(pivotX - gx * targetK, pivotY - gy * targetK, targetK);
45
- }
46
-
47
- /** Pan by a screen-space delta. */
48
- pan(dx: number, dy: number): ZoomTransform {
49
- return new ZoomTransform(this.x + dx, this.y + dy, this.k);
50
- }
51
-
52
- /**
53
- * Compute a transform that fits all nodes within the given canvas
54
- * dimensions with the specified padding.
55
- *
56
- * Returns the transform and the ideal content height (in screen pixels)
57
- * so callers can shrink the canvas to eliminate dead space.
58
- */
59
- static fitBounds(
60
- nodes: PositionedNode[],
61
- canvasW: number,
62
- canvasH: number,
63
- padding: number = 40,
64
- ): { transform: ZoomTransform; contentHeight: number } {
65
- if (nodes.length === 0) {
66
- return { transform: ZoomTransform.identity(), contentHeight: canvasH };
67
- }
68
-
69
- let minX = Infinity;
70
- let minY = Infinity;
71
- let maxX = -Infinity;
72
- let maxY = -Infinity;
73
-
74
- for (const n of nodes) {
75
- const r = n.radius;
76
- if (n.x - r < minX) minX = n.x - r;
77
- if (n.y - r < minY) minY = n.y - r;
78
- if (n.x + r > maxX) maxX = n.x + r;
79
- if (n.y + r > maxY) maxY = n.y + r;
80
- }
81
-
82
- let graphW = maxX - minX;
83
- let graphH = maxY - minY;
84
-
85
- if (graphW === 0 && graphH === 0) {
86
- // All nodes at the same point; just center
87
- return {
88
- transform: new ZoomTransform(canvasW / 2 - minX, canvasH / 2 - minY, 1),
89
- contentHeight: padding * 2,
90
- };
91
- }
92
-
93
- // When called early in the simulation (first tick), the bounding box
94
- // underestimates the final spread. Apply a spread multiplier based on
95
- // node count: larger graphs expand more as charge forces push nodes
96
- // apart over subsequent ticks. The sqrt scaling mirrors how d3-force
97
- // charge repulsion grows with node count.
98
- if (nodes.length > 50) {
99
- const spread = 1 + Math.sqrt(nodes.length) / 120;
100
- const cx = (minX + maxX) / 2;
101
- const cy = (minY + maxY) / 2;
102
- graphW *= spread;
103
- graphH *= spread;
104
- minX = cx - graphW / 2;
105
- maxX = cx + graphW / 2;
106
- minY = cy - graphH / 2;
107
- maxY = cy + graphH / 2;
108
- }
109
-
110
- const availW = canvasW - padding * 2;
111
- const availH = canvasH - padding * 2;
112
- // Cap at 1 so the graph never renders larger than its natural size
113
- const k = Math.min(1, availW / graphW, availH / graphH);
114
-
115
- // Center both axes so the graph sits in the middle of the viewport
116
- const cx = (minX + maxX) / 2;
117
- const cy = (minY + maxY) / 2;
118
- const tx = canvasW / 2 - cx * k;
119
- const ty = canvasH / 2 - cy * k;
120
-
121
- // Content height = scaled graph extent + top and bottom padding
122
- const contentHeight = graphH * k + padding * 2;
123
-
124
- return {
125
- transform: new ZoomTransform(tx, ty, k),
126
- contentHeight,
127
- };
128
- }
129
-
130
- /** Identity transform (no pan, no zoom). */
131
- static identity(): ZoomTransform {
132
- return new ZoomTransform(0, 0, 1);
133
- }
134
- }