@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.
Files changed (37) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +123 -0
  3. package/bin.js +77 -0
  4. package/commands/add.js +42 -0
  5. package/commands/create.js +238 -0
  6. package/commands/init.js +199 -0
  7. package/files/AGENTS.md +63 -0
  8. package/files/CLAUDE.md +63 -0
  9. package/files/LICENSE +21 -0
  10. package/files/rules/accessibility.md +219 -0
  11. package/files/rules/charts.md +352 -0
  12. package/files/rules/components.md +267 -0
  13. package/files/rules/design-principles.md +56 -0
  14. package/files/rules/linting.md +31 -0
  15. package/files/rules/state.md +405 -0
  16. package/files/rules/styling.md +245 -0
  17. package/files/skills/apply-ds/SKILL.md +117 -0
  18. package/files/skills/apply-ds/scripts/setup.sh +271 -0
  19. package/files/skills/build-pattern/SKILL.md +202 -0
  20. package/files/skills/create-dashboard/SKILL.md +189 -0
  21. package/files/skills/deploy-worker/SKILL.md +231 -0
  22. package/files/skills/deploy-worker/references/wrangler-commands.md +327 -0
  23. package/files/skills/fix-accessibility/SKILL.md +184 -0
  24. package/files/skills/fix-metadata/SKILL.md +118 -0
  25. package/files/skills/fix-metadata/assets/favicon.ico +0 -0
  26. package/files/skills/setup-chart/SKILL.md +225 -0
  27. package/files/skills/setup-chart/data/embedding.csv +42 -0
  28. package/files/skills/setup-chart/data/timeseries.csv +173 -0
  29. package/files/skills/setup-chart/references/scatter-chart.md +229 -0
  30. package/files/skills/setup-chart/references/sensor-chart.md +156 -0
  31. package/lib/add-ds-config-codeagent.js +154 -0
  32. package/lib/add-ds-ui-svelte.js +93 -0
  33. package/lib/scaffold-ds-svelte-project.js +272 -0
  34. package/lib/use-package-manager.js +65 -0
  35. package/lib/use-shadcn-svelte-registry.js +26 -0
  36. package/lib/validate-url.js +31 -0
  37. 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
+ ```