@opendata-ai/openchart-vanilla 8.0.0-rc.8 → 8.0.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.
Files changed (147) hide show
  1. package/dist/{chunk-W34KN7FD.js → chunk-2NAQRP66.js} +2 -2
  2. package/dist/{chunk-UZ7J3NOF.js → chunk-6BUCYCLD.js} +7314 -5605
  3. package/dist/chunk-6BUCYCLD.js.map +1 -0
  4. package/dist/chunk-DCODCLWI.js +234 -0
  5. package/dist/chunk-DCODCLWI.js.map +1 -0
  6. package/dist/{chunk-5EOV5JQZ.js → chunk-EKAUQAAX.js} +50 -46
  7. package/dist/chunk-EKAUQAAX.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 +309 -27
  16. package/dist/index.js +2020 -836
  17. package/dist/index.js.map +1 -1
  18. package/dist/{mount-CUKQLeqD.d.ts → mount-CL-nA0f-.d.ts} +85 -2
  19. package/dist/simulation-worker.js +83 -2
  20. package/dist/static.d.ts +2 -0
  21. package/dist/static.js +8 -69
  22. package/dist/static.js.map +1 -1
  23. package/dist/story/index.d.ts +25 -9
  24. package/dist/story/index.js +9 -7
  25. package/dist/story/index.js.map +1 -1
  26. package/dist/styles.css +1 -1
  27. package/dist/styles.css.map +1 -1
  28. package/package.json +14 -6
  29. package/dist/chunk-5EOV5JQZ.js.map +0 -1
  30. package/dist/chunk-UZ7J3NOF.js.map +0 -1
  31. package/src/__test-fixtures__/dom.ts +0 -70
  32. package/src/__test-fixtures__/specs.ts +0 -214
  33. package/src/__tests__/animation.test.ts +0 -358
  34. package/src/__tests__/annotations-render.test.ts +0 -201
  35. package/src/__tests__/compound-labels.test.ts +0 -122
  36. package/src/__tests__/continuous-legend.test.ts +0 -91
  37. package/src/__tests__/crosshair.test.ts +0 -130
  38. package/src/__tests__/edit-events.test.ts +0 -950
  39. package/src/__tests__/events.test.ts +0 -387
  40. package/src/__tests__/export.test.ts +0 -241
  41. package/src/__tests__/font-race.test.ts +0 -199
  42. package/src/__tests__/gradient-ids.test.ts +0 -159
  43. package/src/__tests__/gradient-utils.test.ts +0 -125
  44. package/src/__tests__/known-bugs-render.test.ts +0 -183
  45. package/src/__tests__/map.test.ts +0 -636
  46. package/src/__tests__/mount.test.ts +0 -357
  47. package/src/__tests__/pattern-fills.test.ts +0 -105
  48. package/src/__tests__/resize-timing.test.ts +0 -218
  49. package/src/__tests__/sankey.test.ts +0 -133
  50. package/src/__tests__/selection-events.test.ts +0 -869
  51. package/src/__tests__/series-search.test.ts +0 -311
  52. package/src/__tests__/static.test.ts +0 -141
  53. package/src/__tests__/svg-renderer.test.ts +0 -895
  54. package/src/__tests__/table-keyboard.test.ts +0 -361
  55. package/src/__tests__/table-mount.test.ts +0 -639
  56. package/src/__tests__/tilemap.test.ts +0 -158
  57. package/src/__tests__/tooltip.test.ts +0 -337
  58. package/src/__tests__/transition.test.ts +0 -1792
  59. package/src/__tests__/update-scrolly-matrix.test.ts +0 -563
  60. package/src/__tests__/you-draw-it.test.ts +0 -273
  61. package/src/animation-vars.ts +0 -42
  62. package/src/animation.ts +0 -76
  63. package/src/barlist-mount.ts +0 -383
  64. package/src/barlist-renderer.ts +0 -267
  65. package/src/dom-helpers.ts +0 -17
  66. package/src/export.ts +0 -482
  67. package/src/gradient-utils.ts +0 -138
  68. package/src/graph/__tests__/canvas-renderer.test.ts +0 -713
  69. package/src/graph/__tests__/graph-mount.test.ts +0 -213
  70. package/src/graph/__tests__/interaction.test.ts +0 -205
  71. package/src/graph/__tests__/keyboard.test.ts +0 -653
  72. package/src/graph/__tests__/search.test.ts +0 -88
  73. package/src/graph/__tests__/simulation.test.ts +0 -233
  74. package/src/graph/__tests__/spatial-index.test.ts +0 -142
  75. package/src/graph/__tests__/zoom.test.ts +0 -203
  76. package/src/graph/canvas-renderer.ts +0 -747
  77. package/src/graph/interaction.ts +0 -367
  78. package/src/graph/keyboard.ts +0 -208
  79. package/src/graph/search.ts +0 -50
  80. package/src/graph/simulation-worker-url.ts +0 -12
  81. package/src/graph/simulation-worker.ts +0 -278
  82. package/src/graph/simulation.ts +0 -422
  83. package/src/graph/spatial-index.ts +0 -121
  84. package/src/graph/types.ts +0 -47
  85. package/src/graph/worker-protocol.ts +0 -70
  86. package/src/graph/zoom.ts +0 -134
  87. package/src/graph-mount.ts +0 -888
  88. package/src/index.ts +0 -76
  89. package/src/interactions/chart-events.ts +0 -139
  90. package/src/interactions/crosshair.ts +0 -233
  91. package/src/interactions/drag-handler.ts +0 -175
  92. package/src/interactions/editing-drags.ts +0 -515
  93. package/src/interactions/index.ts +0 -25
  94. package/src/interactions/keyboard-nav.ts +0 -111
  95. package/src/interactions/legend-interaction.ts +0 -46
  96. package/src/interactions/selection.ts +0 -280
  97. package/src/interactions/tooltip-events.ts +0 -72
  98. package/src/map-camera.ts +0 -111
  99. package/src/map-mount.ts +0 -792
  100. package/src/map-renderer.ts +0 -460
  101. package/src/map-transition.ts +0 -99
  102. package/src/measure-text.ts +0 -134
  103. package/src/mount.ts +0 -1382
  104. package/src/pattern-utils.ts +0 -110
  105. package/src/renderers/annotations.ts +0 -388
  106. package/src/renderers/axes.ts +0 -351
  107. package/src/renderers/brand.ts +0 -87
  108. package/src/renderers/chrome.ts +0 -196
  109. package/src/renderers/endpoint-labels.ts +0 -150
  110. package/src/renderers/legend.ts +0 -311
  111. package/src/renderers/marks.ts +0 -561
  112. package/src/renderers/metrics.ts +0 -63
  113. package/src/renderers/svg-dom.ts +0 -40
  114. package/src/renderers/table-cells.ts +0 -446
  115. package/src/resize-observer.ts +0 -46
  116. package/src/sankey-mount.ts +0 -622
  117. package/src/sankey-renderer.ts +0 -614
  118. package/src/series-search.ts +0 -392
  119. package/src/static.ts +0 -251
  120. package/src/story/__tests__/camera-math.test.ts +0 -145
  121. package/src/story/__tests__/create-chart-story.test.ts +0 -317
  122. package/src/story/__tests__/progress-math.test.ts +0 -95
  123. package/src/story/__tests__/scroll-driver.test.ts +0 -130
  124. package/src/story/__tests__/tween.test.ts +0 -159
  125. package/src/story/camera-math.ts +0 -125
  126. package/src/story/create-chart-story.ts +0 -353
  127. package/src/story/crossfade.ts +0 -70
  128. package/src/story/index.ts +0 -39
  129. package/src/story/progress-math.ts +0 -85
  130. package/src/story/resolve-camera-target.ts +0 -119
  131. package/src/story/scroll-driver.ts +0 -206
  132. package/src/story/story-camera.ts +0 -49
  133. package/src/story/tween.ts +0 -112
  134. package/src/story/types.ts +0 -76
  135. package/src/svg-ids.ts +0 -23
  136. package/src/svg-renderer.ts +0 -383
  137. package/src/table-keyboard.ts +0 -266
  138. package/src/table-mount.ts +0 -567
  139. package/src/table-renderer.ts +0 -414
  140. package/src/text-edit-overlay.ts +0 -255
  141. package/src/theme-tokens.ts +0 -51
  142. package/src/tilemap-mount.ts +0 -511
  143. package/src/tilemap-renderer.ts +0 -396
  144. package/src/tooltip.ts +0 -177
  145. package/src/transition.ts +0 -2816
  146. package/src/you-draw-it.ts +0 -480
  147. /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
- }