@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.
- package/dist/index.d.ts +327 -0
- package/dist/index.js +4745 -0
- package/dist/index.js.map +1 -0
- package/dist/simulation-worker.js +1196 -0
- package/package.json +58 -0
- package/src/__test-fixtures__/dom.ts +42 -0
- package/src/__test-fixtures__/specs.ts +187 -0
- package/src/__tests__/edit-events.test.ts +747 -0
- package/src/__tests__/events.test.ts +336 -0
- package/src/__tests__/export.test.ts +150 -0
- package/src/__tests__/mount.test.ts +219 -0
- package/src/__tests__/svg-renderer.test.ts +609 -0
- package/src/__tests__/table-mount.test.ts +484 -0
- package/src/__tests__/tooltip.test.ts +201 -0
- package/src/export.ts +105 -0
- package/src/graph/__tests__/canvas-renderer.test.ts +704 -0
- package/src/graph/__tests__/graph-mount.test.ts +213 -0
- package/src/graph/__tests__/interaction.test.ts +205 -0
- package/src/graph/__tests__/keyboard.test.ts +653 -0
- package/src/graph/__tests__/search.test.ts +88 -0
- package/src/graph/__tests__/simulation.test.ts +233 -0
- package/src/graph/__tests__/spatial-index.test.ts +142 -0
- package/src/graph/__tests__/zoom.test.ts +195 -0
- package/src/graph/canvas-renderer.ts +660 -0
- package/src/graph/interaction.ts +359 -0
- package/src/graph/keyboard.ts +208 -0
- package/src/graph/search.ts +50 -0
- package/src/graph/simulation-worker-url.ts +30 -0
- package/src/graph/simulation-worker.ts +265 -0
- package/src/graph/simulation.ts +350 -0
- package/src/graph/spatial-index.ts +121 -0
- package/src/graph/types.ts +44 -0
- package/src/graph/worker-protocol.ts +67 -0
- package/src/graph/zoom.ts +104 -0
- package/src/graph-mount.ts +675 -0
- package/src/index.ts +56 -0
- package/src/mount.ts +1639 -0
- package/src/renderers/table-cells.ts +444 -0
- package/src/resize-observer.ts +46 -0
- package/src/svg-renderer.ts +914 -0
- package/src/table-keyboard.ts +266 -0
- package/src/table-mount.ts +532 -0
- package/src/table-renderer.ts +350 -0
- 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
|
+
};
|