@opendata-ai/openchart-vanilla 2.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 (44) hide show
  1. package/dist/index.d.ts +327 -0
  2. package/dist/index.js +4745 -0
  3. package/dist/index.js.map +1 -0
  4. package/dist/simulation-worker.js +1196 -0
  5. package/package.json +58 -0
  6. package/src/__test-fixtures__/dom.ts +42 -0
  7. package/src/__test-fixtures__/specs.ts +187 -0
  8. package/src/__tests__/edit-events.test.ts +747 -0
  9. package/src/__tests__/events.test.ts +336 -0
  10. package/src/__tests__/export.test.ts +150 -0
  11. package/src/__tests__/mount.test.ts +219 -0
  12. package/src/__tests__/svg-renderer.test.ts +609 -0
  13. package/src/__tests__/table-mount.test.ts +484 -0
  14. package/src/__tests__/tooltip.test.ts +201 -0
  15. package/src/export.ts +105 -0
  16. package/src/graph/__tests__/canvas-renderer.test.ts +704 -0
  17. package/src/graph/__tests__/graph-mount.test.ts +213 -0
  18. package/src/graph/__tests__/interaction.test.ts +205 -0
  19. package/src/graph/__tests__/keyboard.test.ts +653 -0
  20. package/src/graph/__tests__/search.test.ts +88 -0
  21. package/src/graph/__tests__/simulation.test.ts +233 -0
  22. package/src/graph/__tests__/spatial-index.test.ts +142 -0
  23. package/src/graph/__tests__/zoom.test.ts +195 -0
  24. package/src/graph/canvas-renderer.ts +660 -0
  25. package/src/graph/interaction.ts +359 -0
  26. package/src/graph/keyboard.ts +208 -0
  27. package/src/graph/search.ts +50 -0
  28. package/src/graph/simulation-worker-url.ts +30 -0
  29. package/src/graph/simulation-worker.ts +265 -0
  30. package/src/graph/simulation.ts +350 -0
  31. package/src/graph/spatial-index.ts +121 -0
  32. package/src/graph/types.ts +44 -0
  33. package/src/graph/worker-protocol.ts +67 -0
  34. package/src/graph/zoom.ts +104 -0
  35. package/src/graph-mount.ts +675 -0
  36. package/src/index.ts +56 -0
  37. package/src/mount.ts +1639 -0
  38. package/src/renderers/table-cells.ts +444 -0
  39. package/src/resize-observer.ts +46 -0
  40. package/src/svg-renderer.ts +914 -0
  41. package/src/table-keyboard.ts +266 -0
  42. package/src/table-mount.ts +532 -0
  43. package/src/table-renderer.ts +350 -0
  44. package/src/tooltip.ts +120 -0
package/package.json ADDED
@@ -0,0 +1,58 @@
1
+ {
2
+ "name": "@opendata-ai/openchart-vanilla",
3
+ "version": "2.0.0",
4
+ "description": "Vanilla JS renderer for openchart: SVG charts, HTML tables, force-directed graphs",
5
+ "license": "Apache-2.0",
6
+ "author": "Riley Hilliard",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "https://github.com/tryopendata/openchart.git",
10
+ "directory": "packages/vanilla"
11
+ },
12
+ "homepage": "https://github.com/tryopendata/openchart#readme",
13
+ "bugs": "https://github.com/tryopendata/openchart/issues",
14
+ "publishConfig": {
15
+ "access": "public"
16
+ },
17
+ "engines": {
18
+ "node": ">=18"
19
+ },
20
+ "type": "module",
21
+ "main": "dist/index.js",
22
+ "types": "dist/index.d.ts",
23
+ "exports": {
24
+ ".": {
25
+ "types": "./dist/index.d.ts",
26
+ "import": "./dist/index.js"
27
+ },
28
+ "./simulation-worker": "./dist/simulation-worker.js"
29
+ },
30
+ "files": [
31
+ "dist",
32
+ "src"
33
+ ],
34
+ "sideEffects": false,
35
+ "keywords": [
36
+ "chart",
37
+ "visualization",
38
+ "svg",
39
+ "data-table",
40
+ "vanilla-js",
41
+ "d3"
42
+ ],
43
+ "scripts": {
44
+ "build": "tsup && bun build src/graph/simulation-worker.ts --outfile dist/simulation-worker.js --target=browser --format=iife",
45
+ "test": "vitest run",
46
+ "typecheck": "tsc --noEmit"
47
+ },
48
+ "dependencies": {
49
+ "@opendata-ai/openchart-core": "2.0.0",
50
+ "@opendata-ai/openchart-engine": "2.0.0",
51
+ "d3-force": "^3.0.0",
52
+ "d3-quadtree": "^3.0.1"
53
+ },
54
+ "devDependencies": {
55
+ "@types/d3-force": "^3.0.10",
56
+ "@types/d3-quadtree": "^3.0.6"
57
+ }
58
+ }
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Shared DOM helpers for vanilla package tests.
3
+ *
4
+ * Provides container creation with mocked getBoundingClientRect (needed because
5
+ * happy-dom has no layout engine) and mouse event construction.
6
+ */
7
+
8
+ /**
9
+ * Create an HTMLDivElement with mocked dimensions, appended to document.body.
10
+ * happy-dom returns zero for getBoundingClientRect by default, so we provide
11
+ * realistic values for the chart/table compilation pipeline to work with.
12
+ */
13
+ export function createContainer(width = 600, height = 400): HTMLDivElement {
14
+ const container = document.createElement('div');
15
+ Object.defineProperty(container, 'getBoundingClientRect', {
16
+ value: () => ({
17
+ width,
18
+ height,
19
+ top: 0,
20
+ left: 0,
21
+ right: width,
22
+ bottom: height,
23
+ x: 0,
24
+ y: 0,
25
+ toJSON: () => ({}),
26
+ }),
27
+ });
28
+ document.body.appendChild(container);
29
+ return container;
30
+ }
31
+
32
+ /**
33
+ * Create a MouseEvent with clientX/clientY coordinates.
34
+ * happy-dom supports basic MouseEvent construction.
35
+ */
36
+ export function createMouseEvent(type: string, x = 100, y = 100): MouseEvent {
37
+ return new MouseEvent(type, {
38
+ bubbles: true,
39
+ clientX: x,
40
+ clientY: y,
41
+ });
42
+ }
@@ -0,0 +1,187 @@
1
+ /**
2
+ * Shared chart, table, and graph spec fixtures for vanilla package tests.
3
+ *
4
+ * These cover all chart types and common configurations so individual test
5
+ * files don't need to duplicate spec definitions.
6
+ */
7
+
8
+ import type { ChartSpec, GraphSpec, TableSpec } from '@opendata-ai/openchart-engine';
9
+
10
+ // ---------------------------------------------------------------------------
11
+ // Line chart specs
12
+ // ---------------------------------------------------------------------------
13
+
14
+ export const lineSpec: ChartSpec = {
15
+ type: 'line',
16
+ data: [
17
+ { date: '2020-01-01', value: 10, country: 'US' },
18
+ { date: '2021-01-01', value: 40, country: 'US' },
19
+ { date: '2020-01-01', value: 15, country: 'UK' },
20
+ { date: '2021-01-01', value: 35, country: 'UK' },
21
+ ],
22
+ encoding: {
23
+ x: { field: 'date', type: 'temporal' },
24
+ y: { field: 'value', type: 'quantitative' },
25
+ color: { field: 'country', type: 'nominal' },
26
+ },
27
+ chrome: {
28
+ title: 'GDP Growth',
29
+ subtitle: 'US vs UK over time',
30
+ source: 'World Bank',
31
+ },
32
+ };
33
+
34
+ export const singleSeriesLineSpec: ChartSpec = {
35
+ type: 'line',
36
+ data: [
37
+ { date: '2020-01-01', value: 10 },
38
+ { date: '2021-01-01', value: 40 },
39
+ { date: '2022-01-01', value: 25 },
40
+ ],
41
+ encoding: {
42
+ x: { field: 'date', type: 'temporal' },
43
+ y: { field: 'value', type: 'quantitative' },
44
+ },
45
+ };
46
+
47
+ // ---------------------------------------------------------------------------
48
+ // Bar chart specs
49
+ // ---------------------------------------------------------------------------
50
+
51
+ export const barSpec: ChartSpec = {
52
+ type: 'bar',
53
+ data: [
54
+ { name: 'A', value: 10 },
55
+ { name: 'B', value: 30 },
56
+ { name: 'C', value: 20 },
57
+ ],
58
+ encoding: {
59
+ x: { field: 'value', type: 'quantitative' },
60
+ y: { field: 'name', type: 'nominal' },
61
+ },
62
+ chrome: {
63
+ title: 'Updated Chart',
64
+ },
65
+ };
66
+
67
+ // ---------------------------------------------------------------------------
68
+ // Column chart specs
69
+ // ---------------------------------------------------------------------------
70
+
71
+ export const columnSpec: ChartSpec = {
72
+ type: 'column',
73
+ data: [
74
+ { category: 'Q1', revenue: 100 },
75
+ { category: 'Q2', revenue: 200 },
76
+ { category: 'Q3', revenue: 150 },
77
+ ],
78
+ encoding: {
79
+ x: { field: 'category', type: 'nominal' },
80
+ y: { field: 'revenue', type: 'quantitative' },
81
+ },
82
+ chrome: {
83
+ title: 'Quarterly Revenue',
84
+ },
85
+ };
86
+
87
+ // ---------------------------------------------------------------------------
88
+ // Scatter chart specs
89
+ // ---------------------------------------------------------------------------
90
+
91
+ export const scatterSpec: ChartSpec = {
92
+ type: 'scatter',
93
+ data: [
94
+ { x: 10, y: 20, group: 'A' },
95
+ { x: 30, y: 40, group: 'A' },
96
+ { x: 50, y: 10, group: 'B' },
97
+ { x: 60, y: 30, group: 'B' },
98
+ ],
99
+ encoding: {
100
+ x: { field: 'x', type: 'quantitative' },
101
+ y: { field: 'y', type: 'quantitative' },
102
+ color: { field: 'group', type: 'nominal' },
103
+ },
104
+ chrome: {
105
+ title: 'Scatter Plot',
106
+ },
107
+ };
108
+
109
+ // ---------------------------------------------------------------------------
110
+ // Pie chart specs
111
+ // ---------------------------------------------------------------------------
112
+
113
+ export const pieSpec: ChartSpec = {
114
+ type: 'pie',
115
+ data: [
116
+ { category: 'Red', value: 30 },
117
+ { category: 'Blue', value: 50 },
118
+ { category: 'Green', value: 20 },
119
+ ],
120
+ encoding: {
121
+ color: { field: 'category', type: 'nominal' },
122
+ y: { field: 'value', type: 'quantitative' },
123
+ },
124
+ chrome: {
125
+ title: 'Market Share',
126
+ },
127
+ };
128
+
129
+ // ---------------------------------------------------------------------------
130
+ // Multi-series bar spec (grouped)
131
+ // ---------------------------------------------------------------------------
132
+
133
+ export const multiSeriesBarSpec: ChartSpec = {
134
+ type: 'bar',
135
+ data: [
136
+ { name: 'A', value: 10, group: 'X' },
137
+ { name: 'B', value: 30, group: 'X' },
138
+ { name: 'A', value: 20, group: 'Y' },
139
+ { name: 'B', value: 15, group: 'Y' },
140
+ ],
141
+ encoding: {
142
+ x: { field: 'value', type: 'quantitative' },
143
+ y: { field: 'name', type: 'nominal' },
144
+ color: { field: 'group', type: 'nominal' },
145
+ },
146
+ };
147
+
148
+ // ---------------------------------------------------------------------------
149
+ // Table specs
150
+ // ---------------------------------------------------------------------------
151
+
152
+ export function makeTableSpec(overrides?: Partial<TableSpec>): TableSpec {
153
+ return {
154
+ type: 'table',
155
+ data: [
156
+ { name: 'Alice', age: 30, city: 'Portland' },
157
+ { name: 'Bob', age: 25, city: 'Seattle' },
158
+ { name: 'Charlie', age: 35, city: 'Portland' },
159
+ { name: 'Diana', age: 28, city: 'Denver' },
160
+ { name: 'Eve', age: 22, city: 'Seattle' },
161
+ ],
162
+ columns: [
163
+ { key: 'name', label: 'Name' },
164
+ { key: 'age', label: 'Age' },
165
+ { key: 'city', label: 'City' },
166
+ ],
167
+ chrome: { title: 'People' },
168
+ ...overrides,
169
+ };
170
+ }
171
+
172
+ // ---------------------------------------------------------------------------
173
+ // Graph specs
174
+ // ---------------------------------------------------------------------------
175
+
176
+ export const graphSpec: GraphSpec = {
177
+ type: 'graph',
178
+ nodes: [
179
+ { id: 'a', label: 'Node A', community: 'group1' },
180
+ { id: 'b', label: 'Node B', community: 'group1' },
181
+ { id: 'c', label: 'Node C', community: 'group2' },
182
+ ],
183
+ edges: [
184
+ { source: 'a', target: 'b' },
185
+ { source: 'b', target: 'c' },
186
+ ],
187
+ };