@archetypeai/ds-cli 0.3.7
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/LICENSE +21 -0
- package/README.md +123 -0
- package/bin.js +77 -0
- package/commands/add.js +42 -0
- package/commands/create.js +238 -0
- package/commands/init.js +199 -0
- package/files/AGENTS.md +63 -0
- package/files/CLAUDE.md +63 -0
- package/files/LICENSE +21 -0
- package/files/rules/accessibility.md +219 -0
- package/files/rules/charts.md +352 -0
- package/files/rules/components.md +267 -0
- package/files/rules/design-principles.md +56 -0
- package/files/rules/linting.md +31 -0
- package/files/rules/state.md +405 -0
- package/files/rules/styling.md +245 -0
- package/files/skills/apply-ds/SKILL.md +117 -0
- package/files/skills/apply-ds/scripts/setup.sh +271 -0
- package/files/skills/build-pattern/SKILL.md +202 -0
- package/files/skills/create-dashboard/SKILL.md +189 -0
- package/files/skills/deploy-worker/SKILL.md +231 -0
- package/files/skills/deploy-worker/references/wrangler-commands.md +327 -0
- package/files/skills/fix-accessibility/SKILL.md +184 -0
- package/files/skills/fix-metadata/SKILL.md +118 -0
- package/files/skills/fix-metadata/assets/favicon.ico +0 -0
- package/files/skills/setup-chart/SKILL.md +225 -0
- package/files/skills/setup-chart/data/embedding.csv +42 -0
- package/files/skills/setup-chart/data/timeseries.csv +173 -0
- package/files/skills/setup-chart/references/scatter-chart.md +229 -0
- package/files/skills/setup-chart/references/sensor-chart.md +156 -0
- package/lib/add-ds-config-codeagent.js +154 -0
- package/lib/add-ds-ui-svelte.js +93 -0
- package/lib/scaffold-ds-svelte-project.js +272 -0
- package/lib/use-package-manager.js +65 -0
- package/lib/use-shadcn-svelte-registry.js +26 -0
- package/lib/validate-url.js +31 -0
- package/package.json +34 -0
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: setup-chart
|
|
3
|
+
description: Sets up data visualizations using layerchart and the Chart primitive. Use when creating line charts, scatter plots, area charts, time series visualizations, sensor displays, embedding plots, streaming data charts, or any data visualization component. Also use when the user asks about charting, graphing, plotting data, visualizing metrics, displaying real-time sensor data, or showing scatter/cluster plots.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Setting Up Charts
|
|
7
|
+
|
|
8
|
+
Build charts using layerchart wrapped in the Chart.Container primitive.
|
|
9
|
+
|
|
10
|
+
## Discovering Components
|
|
11
|
+
|
|
12
|
+
Before building, check which components are installed in the project already:
|
|
13
|
+
|
|
14
|
+
1. List `$lib/components/ui/` to discover available primitives and patterns
|
|
15
|
+
2. Only use components that actually exist in the project
|
|
16
|
+
3. Charts require at minimum: `chart`. For card-wrapped charts: `card`, `chart`
|
|
17
|
+
|
|
18
|
+
## Chart Primitive Installation
|
|
19
|
+
|
|
20
|
+
The `chart` primitive is a multi-file package (chart-container, chart-style, chart-tooltip, scatter-tooltip, chart-utils, index). These files use relative imports between each other (e.g., `./chart-utils.js`).
|
|
21
|
+
|
|
22
|
+
**NEVER manually create chart primitive files.** Always install via the registry:
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
npx shadcn-svelte@latest add --registry https://design-system.archetypeai.workers.dev/r chart
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
If you create individual files by hand, relative imports will break and the chart will fail to render.
|
|
29
|
+
|
|
30
|
+
## Choosing a Chart Type
|
|
31
|
+
|
|
32
|
+
| User wants | Pattern | Reference |
|
|
33
|
+
| ------------------------------------------------------------------- | ------------ | ---------------------------------------------------------- |
|
|
34
|
+
| Line chart, time series, sensor data, streaming lines | SensorChart | [references/sensor-chart.md](references/sensor-chart.md) |
|
|
35
|
+
| Scatter plot, cluster visualization, embedding plot, 2D point cloud | ScatterChart | [references/scatter-chart.md](references/scatter-chart.md) |
|
|
36
|
+
|
|
37
|
+
Read the appropriate reference file for pattern-specific props, complete examples, and data preparation.
|
|
38
|
+
|
|
39
|
+
## Sample Data
|
|
40
|
+
|
|
41
|
+
**WARNING: Always `cp` the CSV files. NEVER recreate or rewrite the CSV data.**
|
|
42
|
+
|
|
43
|
+
Forbidden methods for CSVs: `Write` tool, `cat >`, `echo >`, heredoc. These will corrupt or truncate the data.
|
|
44
|
+
|
|
45
|
+
### Time Series Data (for SensorChart)
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
mkdir -p src/lib/data
|
|
49
|
+
cp data/timeseries.csv src/lib/data/timeseries.csv
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
174 rows of accelerometer + gyroscope readings. Columns: `timestamp`, `accel_x`, `accel_y`, `accel_z`, `gyro_x`.
|
|
53
|
+
|
|
54
|
+
### Embedding Data (for ScatterChart)
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
mkdir -p src/lib/data
|
|
58
|
+
cp data/embedding.csv src/lib/data/embedding.csv
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
40 rows of 2D embedding coordinates. Columns: `file_path`, `variates`, `indices`, `read_indices`, `window_sizes`, `sensor_timestamps`, `timestamps`, `embeddings_1`, `embeddings_2`.
|
|
62
|
+
|
|
63
|
+
For scatter charts, map `embeddings_1` to x and `embeddings_2` to y.
|
|
64
|
+
|
|
65
|
+
## CSV Loading Pattern
|
|
66
|
+
|
|
67
|
+
Load CSV data using Vite's `?raw` import:
|
|
68
|
+
|
|
69
|
+
```svelte
|
|
70
|
+
<script>
|
|
71
|
+
import timeseriesCsv from '$lib/data/timeseries.csv?raw';
|
|
72
|
+
|
|
73
|
+
function parseCsv(csvText) {
|
|
74
|
+
const lines = csvText
|
|
75
|
+
.trim()
|
|
76
|
+
.split('\n')
|
|
77
|
+
.filter((line) => line.trim());
|
|
78
|
+
if (lines.length === 0) return [];
|
|
79
|
+
const headers = lines[0].split(',').map((h) => h.trim());
|
|
80
|
+
return lines.slice(1).map((line) => {
|
|
81
|
+
const values = line.split(',');
|
|
82
|
+
const row = {};
|
|
83
|
+
headers.forEach((header, index) => {
|
|
84
|
+
row[header] = values[index]?.trim() || '';
|
|
85
|
+
});
|
|
86
|
+
return row;
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const rawRows = parseCsv(timeseriesCsv);
|
|
91
|
+
const data = rawRows.map((row) => ({
|
|
92
|
+
timestamp: new Date(row.timestamp),
|
|
93
|
+
accel_x: parseFloat(row.accel_x),
|
|
94
|
+
accel_y: parseFloat(row.accel_y),
|
|
95
|
+
accel_z: parseFloat(row.accel_z)
|
|
96
|
+
}));
|
|
97
|
+
</script>
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
## Chart.Container
|
|
101
|
+
|
|
102
|
+
Always wrap charts in `Chart.Container` with a config:
|
|
103
|
+
|
|
104
|
+
```svelte
|
|
105
|
+
<Chart.Container config={chartConfig} class="aspect-auto h-[220px] w-full">
|
|
106
|
+
<!-- chart content -->
|
|
107
|
+
</Chart.Container>
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
The config maps data keys to labels and colors for tooltips/legends.
|
|
111
|
+
|
|
112
|
+
## Semantic Chart Colors
|
|
113
|
+
|
|
114
|
+
Use theme colors for consistency:
|
|
115
|
+
|
|
116
|
+
```javascript
|
|
117
|
+
const chartColors = [
|
|
118
|
+
'var(--chart-1)', // purple
|
|
119
|
+
'var(--chart-2)', // red-orange
|
|
120
|
+
'var(--chart-3)', // green
|
|
121
|
+
'var(--chart-4)', // yellow
|
|
122
|
+
'var(--chart-5)' // coral
|
|
123
|
+
];
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
Build series config:
|
|
127
|
+
|
|
128
|
+
```javascript
|
|
129
|
+
let series = $derived(
|
|
130
|
+
Object.entries(signals).map(([key, label], i) => ({
|
|
131
|
+
key,
|
|
132
|
+
label,
|
|
133
|
+
color: chartColors[i % chartColors.length]
|
|
134
|
+
}))
|
|
135
|
+
);
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
## D3 Scales
|
|
139
|
+
|
|
140
|
+
### Time Scale (x-axis with dates)
|
|
141
|
+
|
|
142
|
+
```javascript
|
|
143
|
+
import { scaleUtc } from 'd3-scale';
|
|
144
|
+
|
|
145
|
+
xScale={scaleUtc()}
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
### Linear Scale (numeric values)
|
|
149
|
+
|
|
150
|
+
```javascript
|
|
151
|
+
import { scaleLinear } from 'd3-scale';
|
|
152
|
+
|
|
153
|
+
yScale={scaleLinear()}
|
|
154
|
+
yDomain={[0, 100]} // fixed domain
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
## Streaming Data Pattern
|
|
158
|
+
|
|
159
|
+
For real-time charts with a sliding window, use `maxPoints`. Both SensorChart and ScatterChart support this prop.
|
|
160
|
+
|
|
161
|
+
The pattern works by:
|
|
162
|
+
|
|
163
|
+
1. Slicing data to keep only the last `maxPoints` entries
|
|
164
|
+
2. For line charts: re-indexing x-axis with `_index` (not timestamps) so the line scrolls smoothly
|
|
165
|
+
3. For scatter charts: the sliding window just drops old points
|
|
166
|
+
|
|
167
|
+
```javascript
|
|
168
|
+
let displayData = $derived(maxPoints && data.length > maxPoints ? data.slice(-maxPoints) : data);
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
See the pattern-specific reference files for complete streaming examples.
|
|
172
|
+
|
|
173
|
+
## Axis Configuration
|
|
174
|
+
|
|
175
|
+
```svelte
|
|
176
|
+
<LineChart
|
|
177
|
+
axis="both"
|
|
178
|
+
props={{
|
|
179
|
+
xAxis: {
|
|
180
|
+
format: (date) => formatTime(date)
|
|
181
|
+
},
|
|
182
|
+
yAxis: {
|
|
183
|
+
ticks: [0, 25, 50, 75, 100],
|
|
184
|
+
format: (v) => `${v}%`
|
|
185
|
+
},
|
|
186
|
+
grid: {
|
|
187
|
+
y: true,
|
|
188
|
+
x: false
|
|
189
|
+
}
|
|
190
|
+
}}
|
|
191
|
+
/>
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
## Curve Types
|
|
195
|
+
|
|
196
|
+
```javascript
|
|
197
|
+
import { curveNatural, curveMonotoneX, curveStep, curveLinear } from 'd3-shape';
|
|
198
|
+
|
|
199
|
+
props={{
|
|
200
|
+
spline: {
|
|
201
|
+
curve: curveNatural, // smooth natural curve
|
|
202
|
+
strokeWidth: 1.5
|
|
203
|
+
}
|
|
204
|
+
}}
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
## Legend Pattern
|
|
208
|
+
|
|
209
|
+
```svelte
|
|
210
|
+
{#if series.length > 0}
|
|
211
|
+
<div class="flex items-center justify-center gap-10">
|
|
212
|
+
{#each series as s (s.key)}
|
|
213
|
+
<div class="flex items-center gap-2">
|
|
214
|
+
<div class="size-2 rounded-full bg-(--legend-color)" style:--legend-color={s.color}></div>
|
|
215
|
+
<span class="text-foreground text-sm">{s.label}</span>
|
|
216
|
+
</div>
|
|
217
|
+
{/each}
|
|
218
|
+
</div>
|
|
219
|
+
{/if}
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
## Pattern References
|
|
223
|
+
|
|
224
|
+
- [references/sensor-chart.md](references/sensor-chart.md) — SensorChart pattern: line charts, time series, sensor data, streaming lines
|
|
225
|
+
- [references/scatter-chart.md](references/scatter-chart.md) — ScatterChart pattern: scatter plots, cluster visualizations, embedding plots
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
file_path,variates,indices,read_indices,window_sizes,sensor_timestamps,timestamps,embeddings_1,embeddings_2
|
|
2
|
+
generated_embeddings,['generated'],0,1,200,,1766149222.5279047,-4.264917850494385,5.006392955780029
|
|
3
|
+
generated_embeddings,['generated'],1,50,200,,1766149222.529853,-7.026721477508545,5.073069095611572
|
|
4
|
+
generated_embeddings,['generated'],2,100,200,,1766149222.5314155,1.4411457777023315,2.207289934158325
|
|
5
|
+
generated_embeddings,['generated'],3,150,200,,1766149222.532959,3.0368189811706543,3.9874227046966553
|
|
6
|
+
generated_embeddings,['generated'],4,200,200,,1766149222.5344896,-7.378081798553467,0.6962316632270813
|
|
7
|
+
generated_embeddings,['generated'],5,250,200,,1766149222.5360217,0.612908124923706,3.646008253097534
|
|
8
|
+
generated_embeddings,['generated'],6,300,200,,1766149222.5375504,-7.465826034545898,4.672569274902344
|
|
9
|
+
generated_embeddings,['generated'],7,350,200,,1766149222.5390422,-0.9298160672187805,4.850907802581787
|
|
10
|
+
generated_embeddings,['generated'],8,400,200,,1766149222.5405467,-2.408599615097046,2.6918227672576904
|
|
11
|
+
generated_embeddings,['generated'],9,450,200,,1766149222.5420597,-1.5119256973266602,-4.184278964996338
|
|
12
|
+
generated_embeddings,['generated'],10,500,200,,1766149222.5438602,-1.4998648166656494,1.512027621269226
|
|
13
|
+
generated_embeddings,['generated'],11,550,200,,1766149222.5454378,-1.5811705589294434,-1.5503257513046265
|
|
14
|
+
generated_embeddings,['generated'],12,600,200,,1766149222.5469103,-0.364311546087265,-0.29250064492225647
|
|
15
|
+
generated_embeddings,['generated'],13,650,200,,1766149222.5484564,-6.965754508972168,0.5354546904563904
|
|
16
|
+
generated_embeddings,['generated'],14,700,200,,1766149222.549931,-5.198845386505127,1.8451766967773438
|
|
17
|
+
generated_embeddings,['generated'],15,750,200,,1766149222.5514324,-2.2832343578338623,7.585117340087891
|
|
18
|
+
generated_embeddings,['generated'],16,800,200,,1766149222.5528893,3.638500690460205,5.14137601852417
|
|
19
|
+
generated_embeddings,['generated'],17,850,200,,1766149222.5543745,0.9260262250900269,6.648405075073242
|
|
20
|
+
generated_embeddings,['generated'],18,900,200,,1766149222.55585,-8.119987487792969,-0.10295911878347397
|
|
21
|
+
generated_embeddings,['generated'],19,950,200,,1766149222.5574868,-7.078490734100342,2.0733516216278076
|
|
22
|
+
generated_embeddings,['generated'],20,1000,200,,1766149222.5591319,-1.8562607765197754,-2.187143564224243
|
|
23
|
+
generated_embeddings,['generated'],21,1050,200,,1766149222.5607052,3.012232542037964,2.348400354385376
|
|
24
|
+
generated_embeddings,['generated'],22,1100,200,,1766149222.5621753,-0.7242431044578552,-2.2224466800689697
|
|
25
|
+
generated_embeddings,['generated'],23,1150,200,,1766149222.563713,-3.9314167499542236,-3.053118944168091
|
|
26
|
+
generated_embeddings,['generated'],24,1200,200,,1766149222.565205,-1.467191457748413,5.957578182220459
|
|
27
|
+
generated_embeddings,['generated'],25,1250,200,,1766149222.5668693,1.1312074661254883,1.0873385667800903
|
|
28
|
+
generated_embeddings,['generated'],26,1300,200,,1766149222.5686667,2.0910732746124268,3.9601945877075195
|
|
29
|
+
generated_embeddings,['generated'],27,1350,200,,1766149222.5703473,-3.0276665687561035,-1.3890628814697266
|
|
30
|
+
generated_embeddings,['generated'],28,1400,200,,1766149222.571948,-1.1647858619689941,3.6265182495117188
|
|
31
|
+
generated_embeddings,['generated'],29,1450,200,,1766149222.5734956,2.260096549987793,6.622683525085449
|
|
32
|
+
generated_embeddings,['generated'],30,1500,200,,1766149222.5749714,-1.4464548826217651,0.35110077261924744
|
|
33
|
+
generated_embeddings,['generated'],31,1550,200,,1766149222.6459424,-0.30969828367233276,-5.230212688446045
|
|
34
|
+
generated_embeddings,['generated'],32,1600,200,,1766149222.6485584,-1.1643826961517334,8.152813911437988
|
|
35
|
+
generated_embeddings,['generated'],33,1650,200,,1766149222.6511843,-8.0643310546875,2.013965606689453
|
|
36
|
+
generated_embeddings,['generated'],34,1700,200,,1766149222.6536982,2.844578504562378,-0.32172882556915283
|
|
37
|
+
generated_embeddings,['generated'],35,1750,200,,1766149222.655967,-2.65649676322937,-4.302304744720459
|
|
38
|
+
generated_embeddings,['generated'],36,1800,200,,1766149222.6577477,1.2002593278884888,-0.875177264213562
|
|
39
|
+
generated_embeddings,['generated'],37,1850,200,,1766149222.6600926,-5.551851749420166,-0.39295172691345215
|
|
40
|
+
generated_embeddings,['generated'],38,1900,200,,1766149222.6625884,-2.554903745651245,4.787562370300293
|
|
41
|
+
generated_embeddings,['generated'],39,1950,200,,1766149222.6651347,-0.3774823844432831,7.247701168060303
|
|
42
|
+
generated_embeddings,['generated'],40,2000,200,,1766149222.6669827,0.04732463136315346,2.124326229095459
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
timestamp,accel_x,accel_y,accel_z,gyro_x
|
|
2
|
+
2025-12-18T11:59:19.026,0.1890,-0.4520,10.1160,0.0520
|
|
3
|
+
2025-12-18T11:59:19.385,0.1960,-0.2880,9.7190,0.0650
|
|
4
|
+
2025-12-18T11:59:19.745,0.1920,1.4160,9.4020,0.1080
|
|
5
|
+
2025-12-18T11:59:20.105,0.3840,-0.0390,10.5110,0.0730
|
|
6
|
+
2025-12-18T11:59:20.495,-0.3130,1.0760,9.7470,0.0920
|
|
7
|
+
2025-12-18T11:59:20.855,0.1100,-0.2560,10.1950,0.0630
|
|
8
|
+
2025-12-18T11:59:21.245,0.1380,1.1840,9.4520,0.0960
|
|
9
|
+
2025-12-18T11:59:21.605,0.5500,-0.8570,10.4170,0.0510
|
|
10
|
+
2025-12-18T11:59:21.964,0.3750,-2.0910,9.7140,0.0760
|
|
11
|
+
2025-12-18T11:59:22.325,-0.5450,0.0770,14.3010,0.2210
|
|
12
|
+
2025-12-18T11:59:22.685,-0.4010,-1.4970,9.9420,0.0310
|
|
13
|
+
2025-12-18T11:59:23.046,-0.6070,2.8970,11.1630,0.0210
|
|
14
|
+
2025-12-18T11:59:23.406,-0.0680,-3.0620,11.5280,0.1230
|
|
15
|
+
2025-12-18T11:59:23.765,0.3030,-1.1480,10.2460,0.0140
|
|
16
|
+
2025-12-18T11:59:24.124,1.2820,-5.6660,10.4560,0.0870
|
|
17
|
+
2025-12-18T11:59:24.485,-2.6880,-1.5620,13.4540,0.2940
|
|
18
|
+
2025-12-18T11:59:24.845,0.4540,2.6020,10.2280,-0.0360
|
|
19
|
+
2025-12-18T11:59:25.234,2.6200,-3.8350,18.6830,-0.0370
|
|
20
|
+
2025-12-18T11:59:25.594,3.9580,-5.5560,14.2030,-0.0420
|
|
21
|
+
2025-12-18T11:59:25.954,-0.3570,3.5960,9.4070,0.1220
|
|
22
|
+
2025-12-18T11:59:26.315,0.0250,-1.2590,9.2540,0.1390
|
|
23
|
+
2025-12-18T11:59:26.675,0.2890,-1.5450,11.1560,0.1530
|
|
24
|
+
2025-12-18T11:59:27.034,1.2520,5.0750,8.4700,0.0280
|
|
25
|
+
2025-12-18T11:59:27.395,-1.4140,4.6280,6.8410,0.4220
|
|
26
|
+
2025-12-18T11:59:27.754,-1.9030,1.2000,3.2110,0.3090
|
|
27
|
+
2025-12-18T11:59:28.115,-2.0360,-1.5030,12.7090,-0.0010
|
|
28
|
+
2025-12-18T11:59:28.474,-0.8450,0.4580,6.9350,-0.0020
|
|
29
|
+
2025-12-18T11:59:28.835,0.6430,-4.1260,10.0840,0.0400
|
|
30
|
+
2025-12-18T11:59:29.195,1.8960,-1.9580,8.8740,-0.0580
|
|
31
|
+
2025-12-18T11:59:29.554,-1.8360,5.4370,8.0940,0.2280
|
|
32
|
+
2025-12-18T11:59:29.916,-0.3870,1.3590,10.2950,0.1140
|
|
33
|
+
2025-12-18T11:59:30.275,-3.8030,4.2280,2.6830,0.2410
|
|
34
|
+
2025-12-18T11:59:30.636,0.6420,1.0430,8.2390,0.0420
|
|
35
|
+
2025-12-18T11:59:30.994,-0.2140,-2.8540,7.2860,0.0240
|
|
36
|
+
2025-12-18T11:59:31.385,-1.0420,0.7680,9.9050,0.1670
|
|
37
|
+
2025-12-18T11:59:31.746,0.0050,-2.0170,10.5880,0.0720
|
|
38
|
+
2025-12-18T11:59:32.106,-0.5990,-0.8470,7.2530,-0.0500
|
|
39
|
+
2025-12-18T11:59:32.495,-0.5810,-3.4210,9.4760,0.0530
|
|
40
|
+
2025-12-18T11:59:32.884,1.2100,5.2390,8.6950,0.1440
|
|
41
|
+
2025-12-18T11:59:33.245,2.1570,2.1650,9.6940,-0.1220
|
|
42
|
+
2025-12-18T11:59:33.636,-0.0390,4.0340,9.9600,0.1300
|
|
43
|
+
2025-12-18T11:59:33.995,1.0880,-2.3770,11.6230,0.0320
|
|
44
|
+
2025-12-18T11:59:34.355,0.9460,-3.3420,8.0590,0.0290
|
|
45
|
+
2025-12-18T11:59:34.745,1.3130,-6.7080,12.3780,-0.0010
|
|
46
|
+
2025-12-18T11:59:35.105,-0.3730,1.2110,5.0210,0.1350
|
|
47
|
+
2025-12-18T11:59:35.465,0.2470,0.7230,10.8070,0.1340
|
|
48
|
+
2025-12-18T11:59:35.855,-0.6580,0.2040,11.3760,0.0950
|
|
49
|
+
2025-12-18T11:59:36.215,-0.7350,-0.4350,9.5600,0.1220
|
|
50
|
+
2025-12-18T11:59:36.575,-0.8670,-1.8350,14.4140,-0.1740
|
|
51
|
+
2025-12-18T11:59:36.965,-0.3720,-6.5680,18.5880,-0.3050
|
|
52
|
+
2025-12-18T11:59:37.325,-2.2520,-8.8900,17.1430,-0.3110
|
|
53
|
+
2025-12-18T11:59:37.684,2.7120,3.1940,5.1660,0.0470
|
|
54
|
+
2025-12-18T11:59:38.074,-3.5780,-3.2990,18.1620,-0.3760
|
|
55
|
+
2025-12-18T11:59:38.436,3.5910,4.4790,1.2950,0.4200
|
|
56
|
+
2025-12-18T11:59:38.854,4.0650,4.7110,1.6420,0.0870
|
|
57
|
+
2025-12-18T11:59:39.245,-2.9510,-0.1110,5.5350,-0.2120
|
|
58
|
+
2025-12-18T11:59:39.605,-1.8750,1.2880,9.2180,-0.1850
|
|
59
|
+
2025-12-18T11:59:39.995,2.4030,6.9100,4.1760,0.3790
|
|
60
|
+
2025-12-18T11:59:40.385,2.7460,2.5740,5.6110,0.0070
|
|
61
|
+
2025-12-18T11:59:40.774,-0.1320,3.0490,6.0400,-0.0890
|
|
62
|
+
2025-12-18T11:59:41.166,-0.3110,-10.3500,19.3390,0.0580
|
|
63
|
+
2025-12-18T11:59:41.585,-3.4370,-1.8500,15.8080,-0.2880
|
|
64
|
+
2025-12-18T11:59:41.974,0.8410,5.5890,-1.1620,0.1290
|
|
65
|
+
2025-12-18T11:59:42.395,1.3200,-3.1870,11.5840,0.2120
|
|
66
|
+
2025-12-18T11:59:42.755,2.4270,5.4690,5.5710,0.1640
|
|
67
|
+
2025-12-18T11:59:43.146,-0.9730,-4.2020,16.8160,-0.0410
|
|
68
|
+
2025-12-18T11:59:43.565,1.5150,3.3110,3.4680,0.1030
|
|
69
|
+
2025-12-18T11:59:43.925,2.6640,6.5320,1.2450,0.7220
|
|
70
|
+
2025-12-18T11:59:44.315,1.5940,-8.4110,19.3840,0.4320
|
|
71
|
+
2025-12-18T11:59:44.734,0.0500,4.6950,6.6240,-0.1130
|
|
72
|
+
2025-12-18T11:59:45.095,1.6520,-9.1350,18.4250,0.2630
|
|
73
|
+
2025-12-18T11:59:45.485,3.9440,-6.8010,9.8890,0.3090
|
|
74
|
+
2025-12-18T11:59:45.874,3.7510,7.4760,0.8670,0.4830
|
|
75
|
+
2025-12-18T11:59:46.235,-2.7450,-6.2040,19.5520,-0.4880
|
|
76
|
+
2025-12-18T11:59:46.654,1.4990,6.7780,6.4820,0.3890
|
|
77
|
+
2025-12-18T11:59:47.106,1.6460,11.5470,0.5820,0.6810
|
|
78
|
+
2025-12-18T11:59:47.465,-0.4940,4.5900,3.5600,-0.0920
|
|
79
|
+
2025-12-18T11:59:47.825,-2.8510,-7.3860,19.9930,-0.4210
|
|
80
|
+
2025-12-18T11:59:48.214,-1.1790,0.3080,13.7020,-0.1740
|
|
81
|
+
2025-12-18T11:59:48.575,2.5550,8.5370,2.4340,-0.3790
|
|
82
|
+
2025-12-18T11:59:48.965,0.4300,2.7240,5.2420,0.0760
|
|
83
|
+
2025-12-18T11:59:49.354,2.6380,-0.7380,8.8470,0.2990
|
|
84
|
+
2025-12-18T11:59:49.745,1.9810,-7.2530,16.8620,0.0130
|
|
85
|
+
2025-12-18T11:59:50.165,-1.3620,3.4680,5.2770,0.0200
|
|
86
|
+
2025-12-18T11:59:50.525,-0.7450,-7.9100,14.6990,-0.3440
|
|
87
|
+
2025-12-18T11:59:50.914,1.9770,-5.9410,12.4400,0.1070
|
|
88
|
+
2025-12-18T11:59:51.334,-0.6920,-1.2800,11.5940,0.0730
|
|
89
|
+
2025-12-18T11:59:51.695,-0.6960,4.2050,5.1520,0.3980
|
|
90
|
+
2025-12-18T11:59:52.085,-1.4730,0.5710,7.4510,0.9630
|
|
91
|
+
2025-12-18T11:59:52.505,2.5050,-14.7900,17.4770,0.8450
|
|
92
|
+
2025-12-18T11:59:52.866,-0.4710,-10.3050,17.3690,0.2180
|
|
93
|
+
2025-12-18T11:59:53.284,-1.7870,-2.1160,11.0960,-0.8520
|
|
94
|
+
2025-12-18T11:59:53.674,-1.6460,-0.4830,12.5280,-0.3050
|
|
95
|
+
2025-12-18T11:59:54.034,-3.9450,0.9640,6.7580,0.2910
|
|
96
|
+
2025-12-18T11:59:54.395,-1.5660,2.2150,13.4600,0.0800
|
|
97
|
+
2025-12-18T11:59:54.785,1.0360,-2.0170,10.0730,0.0100
|
|
98
|
+
2025-12-18T11:59:55.145,0.0810,-3.3830,11.1490,-0.0460
|
|
99
|
+
2025-12-18T11:59:55.506,-0.0980,-0.3670,10.2080,0.1510
|
|
100
|
+
2025-12-18T11:59:55.894,1.7220,-5.1250,12.6980,-0.0030
|
|
101
|
+
2025-12-18T11:59:56.254,0.4280,-1.2620,10.2240,-0.0520
|
|
102
|
+
2025-12-18T11:59:56.615,0.8490,-5.0640,11.6790,-0.0240
|
|
103
|
+
2025-12-18T11:59:57.005,-2.2270,1.1370,8.3600,0.2040
|
|
104
|
+
2025-12-18T11:59:57.364,-1.1110,0.7460,11.4370,0.1240
|
|
105
|
+
2025-12-18T11:59:57.725,0.9480,0.6990,7.5360,0.0230
|
|
106
|
+
2025-12-18T11:59:58.115,-1.5800,4.2310,8.2850,0.1880
|
|
107
|
+
2025-12-18T11:59:58.476,-0.5790,5.1130,7.0250,0.1890
|
|
108
|
+
2025-12-18T11:59:58.835,-0.5000,-1.6980,9.7920,0.1840
|
|
109
|
+
2025-12-18T11:59:59.224,1.7260,-5.5130,12.9430,-0.0280
|
|
110
|
+
2025-12-18T11:59:59.584,-0.1110,5.1420,8.6460,0.1220
|
|
111
|
+
2025-12-18T11:59:59.944,0.9940,3.1530,13.0680,0.1350
|
|
112
|
+
2025-12-18T12:00:00.335,0.7130,1.4830,9.3260,-0.0340
|
|
113
|
+
2025-12-18T12:00:00.695,0.0260,-3.5330,11.6870,-0.0410
|
|
114
|
+
2025-12-18T12:00:01.054,1.4420,-5.0590,10.7280,-0.1060
|
|
115
|
+
2025-12-18T12:00:01.444,0.9450,2.4720,9.2050,0.2120
|
|
116
|
+
2025-12-18T12:00:01.805,0.2180,1.2110,9.1290,0.1800
|
|
117
|
+
2025-12-18T12:00:02.165,0.6360,-2.3960,6.8780,0.1970
|
|
118
|
+
2025-12-18T12:00:02.524,2.4690,-4.4470,12.4650,-0.0890
|
|
119
|
+
2025-12-18T12:00:02.885,1.7310,-3.1590,10.2650,0.0150
|
|
120
|
+
2025-12-18T12:00:03.245,1.0660,1.2650,10.3760,-0.0390
|
|
121
|
+
2025-12-18T12:00:03.605,-2.0150,5.8150,6.9080,0.1940
|
|
122
|
+
2025-12-18T12:00:03.966,-4.0450,6.8410,8.0330,0.8820
|
|
123
|
+
2025-12-18T12:00:04.325,0.8570,-4.5100,15.1960,-0.1570
|
|
124
|
+
2025-12-18T12:00:04.684,-0.3390,2.4440,5.5800,0.1580
|
|
125
|
+
2025-12-18T12:00:05.046,-0.2450,3.0810,7.3040,0.2490
|
|
126
|
+
2025-12-18T12:00:05.405,0.2580,-0.5810,10.5630,-0.0290
|
|
127
|
+
2025-12-18T12:00:05.766,0.1330,2.1830,7.2200,0.1160
|
|
128
|
+
2025-12-18T12:00:06.124,-0.5080,-6.0440,16.8750,-0.3870
|
|
129
|
+
2025-12-18T12:00:06.484,3.0850,6.4510,2.1960,0.5360
|
|
130
|
+
2025-12-18T12:00:06.845,-4.0590,-0.2240,12.6650,-0.1900
|
|
131
|
+
2025-12-18T12:00:07.206,0.6470,-7.1230,19.0130,-0.1410
|
|
132
|
+
2025-12-18T12:00:07.566,2.2360,4.3020,5.1600,0.1010
|
|
133
|
+
2025-12-18T12:00:07.925,5.5770,8.2210,3.8220,0.3710
|
|
134
|
+
2025-12-18T12:00:08.285,2.5050,14.1950,-0.5680,0.5790
|
|
135
|
+
2025-12-18T12:00:08.645,0.1860,4.4140,2.6670,-0.3700
|
|
136
|
+
2025-12-18T12:00:09.004,2.5000,0.8120,5.0820,0.2080
|
|
137
|
+
2025-12-18T12:00:09.365,2.1460,1.5800,6.0780,0.1890
|
|
138
|
+
2025-12-18T12:00:09.725,1.8340,-4.0210,9.7260,0.2980
|
|
139
|
+
2025-12-18T12:00:10.115,-3.4790,-4.4490,20.3770,-0.3130
|
|
140
|
+
2025-12-18T12:00:10.475,-3.1320,-10.5160,24.4490,-0.5370
|
|
141
|
+
2025-12-18T12:00:10.834,0.8210,0.3210,5.5990,0.3950
|
|
142
|
+
2025-12-18T12:00:11.226,5.5890,8.2990,6.2940,0.2770
|
|
143
|
+
2025-12-18T12:00:11.585,2.4810,2.3180,3.2850,0.7610
|
|
144
|
+
2025-12-18T12:00:11.944,-0.3020,-25.0620,27.6680,0.3670
|
|
145
|
+
2025-12-18T12:00:12.337,9.7470,26.9150,4.8350,-0.4910
|
|
146
|
+
2025-12-18T12:00:12.725,0.8010,-15.9930,18.2350,-0.4910
|
|
147
|
+
2025-12-18T12:00:13.085,2.4450,11.1290,2.7290,1.3170
|
|
148
|
+
2025-12-18T12:00:13.446,7.3340,-30.0030,-16.4990,1.0320
|
|
149
|
+
2025-12-18T12:00:13.805,0.7600,13.7080,7.1970,0.1820
|
|
150
|
+
2025-12-18T12:00:14.165,0.8090,-4.9290,14.6590,-0.0560
|
|
151
|
+
2025-12-18T12:00:14.585,0.9420,0.3490,8.5430,0.1330
|
|
152
|
+
2025-12-18T12:00:15.006,-0.6410,2.1160,9.5970,0.1180
|
|
153
|
+
2025-12-18T12:00:15.395,0.2360,1.7850,8.9440,0.0900
|
|
154
|
+
2025-12-18T12:00:15.784,-0.0110,-0.4760,10.2020,0.0900
|
|
155
|
+
2025-12-18T12:00:16.144,-0.7110,0.8690,8.8840,0.1010
|
|
156
|
+
2025-12-18T12:00:16.505,0.4780,0.0930,10.0960,0.0620
|
|
157
|
+
2025-12-18T12:00:16.866,0.1630,-0.2600,10.0300,0.0650
|
|
158
|
+
2025-12-18T12:00:17.225,0.2150,0.0400,10.1090,0.0700
|
|
159
|
+
2025-12-18T12:00:17.584,0.1650,0.0250,10.0980,0.0690
|
|
160
|
+
2025-12-18T12:00:17.946,0.1620,0.0010,10.0470,0.0700
|
|
161
|
+
2025-12-18T12:00:18.305,0.1830,0.0220,10.0720,0.0690
|
|
162
|
+
2025-12-18T12:00:18.665,0.1620,0.0280,10.0660,0.0700
|
|
163
|
+
2025-12-18T12:00:19.055,0.1680,0.0130,10.0890,0.0690
|
|
164
|
+
2025-12-18T12:00:19.414,0.1620,0.0270,10.0820,0.0720
|
|
165
|
+
2025-12-18T12:00:19.775,0.1790,0.0150,10.0880,0.0690
|
|
166
|
+
2025-12-18T12:00:20.134,0.1720,0.0190,10.0970,0.0700
|
|
167
|
+
2025-12-18T12:00:20.525,0.1650,0.0130,10.0860,0.0700
|
|
168
|
+
2025-12-18T12:00:20.884,0.1670,0.0190,10.0840,0.0690
|
|
169
|
+
2025-12-18T12:00:21.275,0.1740,0.0250,10.0900,0.0690
|
|
170
|
+
2025-12-18T12:00:21.637,0.1690,0.0220,10.0880,0.0700
|
|
171
|
+
2025-12-18T12:00:21.995,0.1840,0.0160,10.0700,0.0690
|
|
172
|
+
2025-12-18T12:00:22.385,0.1690,0.0080,10.0850,0.0720
|
|
173
|
+
2025-12-18T12:00:22.745,0.1730,0.0320,10.0850,0.0700
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
# ScatterChart Pattern Reference
|
|
2
|
+
|
|
3
|
+
Scatter plots for cluster visualizations, embedding data, and 2D point clouds.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npx shadcn-svelte@latest add --registry https://design-system.archetypeai.workers.dev/r scatter-chart
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
This installs `ScatterChart.svelte` and its dependencies (`card`, `chart`, `utils`, `layerchart`, `d3-scale`).
|
|
12
|
+
|
|
13
|
+
## Props
|
|
14
|
+
|
|
15
|
+
| Prop | Type | Default | Description |
|
|
16
|
+
| ------------- | -------------------------- | ------------ | -------------------------------------------------------------------------- |
|
|
17
|
+
| `title` | string | `"SCATTER"` | Card header label |
|
|
18
|
+
| `icon` | Component | undefined | Lucide icon component for header |
|
|
19
|
+
| `data` | Array<Record<string, any>> | `[]` | Array of data points |
|
|
20
|
+
| `xKey` | string | `"x"` | Data key for x-axis values |
|
|
21
|
+
| `yKey` | string | `"y"` | Data key for y-axis values |
|
|
22
|
+
| `categoryKey` | string | undefined | Data key for category grouping; when set, points split into colored series |
|
|
23
|
+
| `categories` | Record<string, string> | `{}` | Map of category value to display label |
|
|
24
|
+
| `maxPoints` | number | undefined | Enables streaming mode with sliding window |
|
|
25
|
+
| `xMin` | number | **required** | Minimum x-axis value |
|
|
26
|
+
| `xMax` | number | **required** | Maximum x-axis value |
|
|
27
|
+
| `yMin` | number | **required** | Minimum y-axis value |
|
|
28
|
+
| `yMax` | number | **required** | Maximum y-axis value |
|
|
29
|
+
| `xTicks` | number[] | undefined | Explicit x-axis tick values |
|
|
30
|
+
| `yTicks` | number[] | undefined | Explicit y-axis tick values |
|
|
31
|
+
| `class` | string | undefined | Additional CSS classes |
|
|
32
|
+
|
|
33
|
+
## Key Behaviors
|
|
34
|
+
|
|
35
|
+
- **Category mode** (`categoryKey` + `categories` set): Points are split into colored series by category value. Each category gets its own legend entry and color from theme palette.
|
|
36
|
+
- **Single series mode** (no `categoryKey`): All points rendered as one series with `--chart-1` color.
|
|
37
|
+
- **Streaming mode** (`maxPoints` set): Sliding window drops oldest points as new ones arrive.
|
|
38
|
+
- **Tooltip**: Uses voronoi-based hover with `Chart.ScatterTooltip` showing x/y coordinates.
|
|
39
|
+
- **Scales**: Both axes use `scaleLinear()` (numeric data only, no time axis).
|
|
40
|
+
|
|
41
|
+
## Preparing Embedding Data
|
|
42
|
+
|
|
43
|
+
The `embedding.csv` contains dimensionality-reduced coordinates. To prepare it for ScatterChart:
|
|
44
|
+
|
|
45
|
+
```svelte
|
|
46
|
+
<script>
|
|
47
|
+
import embeddingCsv from '$lib/data/embedding.csv?raw';
|
|
48
|
+
|
|
49
|
+
function parseCsv(csvText) {
|
|
50
|
+
const lines = csvText
|
|
51
|
+
.trim()
|
|
52
|
+
.split('\n')
|
|
53
|
+
.filter((line) => line.trim());
|
|
54
|
+
if (lines.length === 0) return [];
|
|
55
|
+
const headers = lines[0].split(',').map((h) => h.trim());
|
|
56
|
+
return lines.slice(1).map((line) => {
|
|
57
|
+
const values = line.split(',');
|
|
58
|
+
const row = {};
|
|
59
|
+
headers.forEach((header, index) => {
|
|
60
|
+
row[header] = values[index]?.trim() || '';
|
|
61
|
+
});
|
|
62
|
+
return row;
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const rawRows = parseCsv(embeddingCsv);
|
|
67
|
+
const data = rawRows.map((row) => ({
|
|
68
|
+
x: parseFloat(row.embeddings_1),
|
|
69
|
+
y: parseFloat(row.embeddings_2)
|
|
70
|
+
}));
|
|
71
|
+
</script>
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## Complete Example — Clustered Scatter
|
|
75
|
+
|
|
76
|
+
```svelte
|
|
77
|
+
<script>
|
|
78
|
+
import ScatterChart from '$lib/components/ui/ScatterChart.svelte';
|
|
79
|
+
import ScatterChartIcon from '@lucide/svelte/icons/scatter-chart';
|
|
80
|
+
import embeddingCsv from '$lib/data/embedding.csv?raw';
|
|
81
|
+
|
|
82
|
+
function parseCsv(csvText) {
|
|
83
|
+
const lines = csvText
|
|
84
|
+
.trim()
|
|
85
|
+
.split('\n')
|
|
86
|
+
.filter((line) => line.trim());
|
|
87
|
+
if (lines.length === 0) return [];
|
|
88
|
+
const headers = lines[0].split(',').map((h) => h.trim());
|
|
89
|
+
return lines.slice(1).map((line) => {
|
|
90
|
+
const values = line.split(',');
|
|
91
|
+
const row = {};
|
|
92
|
+
headers.forEach((header, index) => {
|
|
93
|
+
row[header] = values[index]?.trim() || '';
|
|
94
|
+
});
|
|
95
|
+
return row;
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
const rawRows = parseCsv(embeddingCsv);
|
|
100
|
+
const data = rawRows.map((row) => ({
|
|
101
|
+
x: parseFloat(row.embeddings_1),
|
|
102
|
+
y: parseFloat(row.embeddings_2),
|
|
103
|
+
cluster:
|
|
104
|
+
parseFloat(row.embeddings_1) < -2
|
|
105
|
+
? 'left'
|
|
106
|
+
: parseFloat(row.embeddings_1) > 2
|
|
107
|
+
? 'right'
|
|
108
|
+
: 'center'
|
|
109
|
+
}));
|
|
110
|
+
|
|
111
|
+
const categories = {
|
|
112
|
+
left: 'Cluster A',
|
|
113
|
+
center: 'Cluster B',
|
|
114
|
+
right: 'Cluster C'
|
|
115
|
+
};
|
|
116
|
+
</script>
|
|
117
|
+
|
|
118
|
+
<ScatterChart
|
|
119
|
+
title="EMBEDDING CLUSTERS"
|
|
120
|
+
icon={ScatterChartIcon}
|
|
121
|
+
{data}
|
|
122
|
+
categoryKey="cluster"
|
|
123
|
+
{categories}
|
|
124
|
+
xMin={-10}
|
|
125
|
+
xMax={5}
|
|
126
|
+
yMin={-6}
|
|
127
|
+
yMax={10}
|
|
128
|
+
xTicks={[-10, -5, 0, 5]}
|
|
129
|
+
yTicks={[-5, 0, 5, 10]}
|
|
130
|
+
/>
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
## Complete Example — Streaming Scatter
|
|
134
|
+
|
|
135
|
+
```svelte
|
|
136
|
+
<script>
|
|
137
|
+
import { onMount, onDestroy } from 'svelte';
|
|
138
|
+
import ScatterChart from '$lib/components/ui/ScatterChart.svelte';
|
|
139
|
+
import ScatterChartIcon from '@lucide/svelte/icons/scatter-chart';
|
|
140
|
+
|
|
141
|
+
let streamData = $state([]);
|
|
142
|
+
let interval;
|
|
143
|
+
|
|
144
|
+
const clusters = ['alpha', 'beta', 'gamma'];
|
|
145
|
+
const categories = { alpha: 'Alpha', beta: 'Beta', gamma: 'Gamma' };
|
|
146
|
+
|
|
147
|
+
onMount(() => {
|
|
148
|
+
interval = setInterval(() => {
|
|
149
|
+
const cluster = clusters[Math.floor(Math.random() * clusters.length)];
|
|
150
|
+
const cx = cluster === 'alpha' ? -5 : cluster === 'beta' ? 0 : 3;
|
|
151
|
+
const cy = cluster === 'alpha' ? 3 : cluster === 'beta' ? -2 : 5;
|
|
152
|
+
streamData = [
|
|
153
|
+
...streamData,
|
|
154
|
+
{
|
|
155
|
+
x: cx + (Math.random() - 0.5) * 4,
|
|
156
|
+
y: cy + (Math.random() - 0.5) * 4,
|
|
157
|
+
cluster
|
|
158
|
+
}
|
|
159
|
+
];
|
|
160
|
+
}, 200);
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
onDestroy(() => clearInterval(interval));
|
|
164
|
+
</script>
|
|
165
|
+
|
|
166
|
+
<ScatterChart
|
|
167
|
+
title="STREAMING EMBEDDINGS"
|
|
168
|
+
icon={ScatterChartIcon}
|
|
169
|
+
data={streamData}
|
|
170
|
+
categoryKey="cluster"
|
|
171
|
+
{categories}
|
|
172
|
+
maxPoints={60}
|
|
173
|
+
xMin={-10}
|
|
174
|
+
xMax={5}
|
|
175
|
+
yMin={-6}
|
|
176
|
+
yMax={10}
|
|
177
|
+
xTicks={[-10, -5, 0, 5]}
|
|
178
|
+
yTicks={[-5, 0, 5, 10]}
|
|
179
|
+
/>
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
## Building Inline (Without Pattern)
|
|
183
|
+
|
|
184
|
+
If the `scatter-chart` pattern is not installed, use `card` + `chart` primitives with `ScatterChart` from layerchart:
|
|
185
|
+
|
|
186
|
+
```svelte
|
|
187
|
+
<script>
|
|
188
|
+
import * as Chart from '$lib/components/ui/chart/index.js';
|
|
189
|
+
import { ScatterChart } from 'layerchart';
|
|
190
|
+
import { scaleLinear } from 'd3-scale';
|
|
191
|
+
|
|
192
|
+
let { data } = $props();
|
|
193
|
+
|
|
194
|
+
const chartConfig = {
|
|
195
|
+
data: { label: 'Points', color: 'var(--chart-1)' }
|
|
196
|
+
};
|
|
197
|
+
|
|
198
|
+
const series = [
|
|
199
|
+
{
|
|
200
|
+
key: 'data',
|
|
201
|
+
label: 'Points',
|
|
202
|
+
color: 'var(--chart-1)',
|
|
203
|
+
data: data.map((d) => ({ x: d.x, y: d.y }))
|
|
204
|
+
}
|
|
205
|
+
];
|
|
206
|
+
</script>
|
|
207
|
+
|
|
208
|
+
<Chart.Container config={chartConfig} class="aspect-auto h-[220px] w-full">
|
|
209
|
+
<ScatterChart
|
|
210
|
+
{data}
|
|
211
|
+
x="x"
|
|
212
|
+
y="y"
|
|
213
|
+
xScale={scaleLinear()}
|
|
214
|
+
yScale={scaleLinear()}
|
|
215
|
+
{series}
|
|
216
|
+
legend={false}
|
|
217
|
+
labels={false}
|
|
218
|
+
props={{
|
|
219
|
+
points: { fillOpacity: 0.6, strokeWidth: 1, r: 3 },
|
|
220
|
+
highlight: { points: { r: 5 } },
|
|
221
|
+
tooltip: { context: { mode: 'voronoi' } }
|
|
222
|
+
}}
|
|
223
|
+
>
|
|
224
|
+
{#snippet tooltip()}
|
|
225
|
+
<Chart.ScatterTooltip />
|
|
226
|
+
{/snippet}
|
|
227
|
+
</ScatterChart>
|
|
228
|
+
</Chart.Container>
|
|
229
|
+
```
|