@cfasim-ui/charts 0.1.2 → 0.1.4

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cfasim-ui/charts",
3
- "version": "0.1.2",
3
+ "version": "0.1.4",
4
4
  "type": "module",
5
5
  "description": "Chart visualization components for cfasim-ui",
6
6
  "license": "Apache-2.0",
@@ -16,13 +16,23 @@
16
16
  ".": "./src/index.ts"
17
17
  },
18
18
  "dependencies": {
19
+ "d3-geo": "^3.1.1",
20
+ "d3-selection": "^3.0.0",
21
+ "d3-zoom": "^3.0.0",
19
22
  "reka-ui": "^2.9.2",
20
- "@cfasim-ui/shared": "0.1.2"
23
+ "topojson-client": "^3.1.0",
24
+ "us-atlas": "^3.0.1",
25
+ "@cfasim-ui/shared": "0.1.4"
21
26
  },
22
27
  "peerDependencies": {
23
28
  "vue": "^3.5.0"
24
29
  },
25
30
  "devDependencies": {
31
+ "@types/d3-geo": "^3.1.0",
32
+ "@types/d3-selection": "^3.0.11",
33
+ "@types/d3-zoom": "^3.0.8",
34
+ "@types/topojson-client": "^3.1.5",
35
+ "@types/topojson-specification": "^1.0.5",
26
36
  "@vitejs/plugin-vue": "^6.0.5",
27
37
  "@vue/test-utils": "^2.4.6",
28
38
  "happy-dom": "^20.8.4",
@@ -0,0 +1,330 @@
1
+ # ChoroplethMap
2
+
3
+ A US choropleth map using D3's Albers USA projection, which repositions Alaska and Hawaii to the bottom left. Supports state-level, county-level, and HSA-level (Health Service Areas) rendering via the `geoType` prop. Includes built-in GeoJSON for all US states, territories, counties, and 949 HSAs.
4
+
5
+ ## Examples
6
+
7
+ ### Basic with state data
8
+
9
+ <ComponentDemo>
10
+ <ChoroplethMap
11
+ :data="[
12
+ { id: '06', value: 100 },
13
+ { id: '36', value: 80 },
14
+ { id: '48', value: 90 },
15
+ { id: '12', value: 70 },
16
+ { id: '17', value: 60 },
17
+ { id: '37', value: 50 },
18
+ { id: '42', value: 55 },
19
+ { id: '39', value: 45 },
20
+ { id: '13', value: 40 },
21
+ { id: '26', value: 35 },
22
+ ]"
23
+ title="Cases by State"
24
+ :legend-title="'Cases'"
25
+ :height="400"
26
+ />
27
+
28
+ <template #code>
29
+
30
+ ```vue
31
+ <ChoroplethMap
32
+ :data="[
33
+ { id: '06', value: 100 },
34
+ { id: '36', value: 80 },
35
+ { id: '48', value: 90 },
36
+ { id: '12', value: 70 },
37
+ { id: '17', value: 60 },
38
+ ]"
39
+ title="Cases by State"
40
+ :legend-title="'Cases'"
41
+ :height="400"
42
+ />
43
+ ```
44
+
45
+ </template>
46
+ </ComponentDemo>
47
+
48
+ ### Custom color scale
49
+
50
+ <ComponentDemo>
51
+ <ChoroplethMap
52
+ :data="[
53
+ { id: 'California', value: 100 },
54
+ { id: 'Texas', value: 85 },
55
+ { id: 'Florida', value: 70 },
56
+ { id: 'New York', value: 90 },
57
+ { id: 'Pennsylvania', value: 50 },
58
+ { id: 'Illinois', value: 60 },
59
+ { id: 'Ohio', value: 40 },
60
+ { id: 'Georgia', value: 55 },
61
+ { id: 'North Carolina', value: 45 },
62
+ { id: 'Michigan', value: 35 },
63
+ ]"
64
+ :color-scale="{ min: '#fff5f0', max: '#a50f15' }"
65
+ :legend-title="'Severity'"
66
+ :height="400"
67
+ />
68
+
69
+ <template #code>
70
+
71
+ ```vue
72
+ <ChoroplethMap
73
+ :data="[
74
+ { id: 'California', value: 100 },
75
+ { id: 'Texas', value: 85 },
76
+ { id: 'Florida', value: 70 },
77
+ { id: 'New York', value: 90 },
78
+ ]"
79
+ :color-scale="{ min: '#fff5f0', max: '#a50f15' }"
80
+ :legend-title="'Severity'"
81
+ :height="400"
82
+ />
83
+ ```
84
+
85
+ </template>
86
+ </ComponentDemo>
87
+
88
+ ### Threshold color scale
89
+
90
+ Use an array of `ThresholdStop` objects instead of a linear scale. Each stop defines a `min` threshold — values at or above that threshold get the stop's color. The highest matching stop wins.
91
+
92
+ <ComponentDemo>
93
+ <ChoroplethMap
94
+ :data="[
95
+ { id: 'California', value: 80 },
96
+ { id: 'Texas', value: 45 },
97
+ { id: 'Florida', value: 60 },
98
+ { id: 'New York', value: 25 },
99
+ { id: 'Pennsylvania', value: 8 },
100
+ { id: 'Illinois', value: 55 },
101
+ { id: 'Ohio', value: 30 },
102
+ { id: 'Georgia', value: 70 },
103
+ { id: 'North Carolina', value: 15 },
104
+ { id: 'Michigan', value: 3 },
105
+ ]"
106
+ :color-scale="[
107
+ { min: 0, color: '#fee5d9', label: 'Low' },
108
+ { min: 10, color: '#fcae91', label: 'Some' },
109
+ { min: 30, color: '#fb6a4a', label: 'Moderate' },
110
+ { min: 60, color: '#cb181d', label: 'High' },
111
+ ]"
112
+ title="Risk Level"
113
+ :legend-title="'Risk'"
114
+ :height="400"
115
+ />
116
+
117
+ <template #code>
118
+
119
+ ```vue
120
+ <ChoroplethMap
121
+ :data="stateData"
122
+ :color-scale="[
123
+ { min: 0, color: '#fee5d9', label: 'Low' },
124
+ { min: 10, color: '#fcae91', label: 'Some' },
125
+ { min: 30, color: '#fb6a4a', label: 'Moderate' },
126
+ { min: 60, color: '#cb181d', label: 'High' },
127
+ ]"
128
+ title="Risk Level"
129
+ :legend-title="'Risk'"
130
+ :height="400"
131
+ />
132
+ ```
133
+
134
+ </template>
135
+ </ComponentDemo>
136
+
137
+ ### Categorical color scale
138
+
139
+ Use an array of `CategoricalStop` objects to map string values to colors. Each stop defines a `value` to match and a `color` to apply.
140
+
141
+ <ComponentDemo>
142
+ <ChoroplethMap
143
+ :data="[
144
+ { id: 'California', value: 'high' },
145
+ { id: 'Texas', value: 'medium' },
146
+ { id: 'Florida', value: 'high' },
147
+ { id: 'New York', value: 'low' },
148
+ { id: 'Pennsylvania', value: 'low' },
149
+ { id: 'Illinois', value: 'medium' },
150
+ { id: 'Ohio', value: 'low' },
151
+ { id: 'Georgia', value: 'high' },
152
+ { id: 'North Carolina', value: 'medium' },
153
+ { id: 'Michigan', value: 'low' },
154
+ ]"
155
+ :color-scale="[
156
+ { value: 'low', color: '#fee5d9' },
157
+ { value: 'medium', color: '#fb6a4a' },
158
+ { value: 'high', color: '#cb181d' },
159
+ ]"
160
+ title="Risk Category"
161
+ :legend-title="'Risk'"
162
+ :height="400"
163
+ />
164
+
165
+ <template #code>
166
+
167
+ ```vue
168
+ <ChoroplethMap
169
+ :data="stateData"
170
+ :color-scale="[
171
+ { value: 'low', color: '#fee5d9' },
172
+ { value: 'medium', color: '#fb6a4a' },
173
+ { value: 'high', color: '#cb181d' },
174
+ ]"
175
+ title="Risk Category"
176
+ :legend-title="'Risk'"
177
+ :height="400"
178
+ />
179
+ ```
180
+
181
+ </template>
182
+ </ComponentDemo>
183
+
184
+ ### County-level map with pan and zoom
185
+
186
+ Set `geoType="counties"` to render county-level data using 5-digit FIPS codes. State borders are drawn on top for context. Use `pan` and `zoom` props to enable interactive navigation — useful for dense county data.
187
+
188
+ <ComponentDemo>
189
+ <ChoroplethMap
190
+ geo-type="counties"
191
+ :pan="true"
192
+ :zoom="true"
193
+ :data="[
194
+ { id: '06037', value: 100 },
195
+ { id: '06073', value: 80 },
196
+ { id: '06059', value: 70 },
197
+ { id: '36061', value: 90 },
198
+ { id: '36047', value: 75 },
199
+ { id: '17031', value: 85 },
200
+ { id: '48201', value: 65 },
201
+ { id: '04013', value: 60 },
202
+ { id: '12086', value: 55 },
203
+ { id: '53033', value: 50 },
204
+ ]"
205
+ title="Cases by County"
206
+ :legend-title="'Cases'"
207
+ :height="400"
208
+ />
209
+
210
+ <template #code>
211
+
212
+ ```vue
213
+ <ChoroplethMap
214
+ geo-type="counties"
215
+ pan
216
+ zoom
217
+ :data="[
218
+ { id: '06037', value: 100 },
219
+ { id: '36061', value: 90 },
220
+ { id: '17031', value: 85 },
221
+ { id: '48201', value: 65 },
222
+ { id: '04013', value: 60 },
223
+ ]"
224
+ title="Cases by County"
225
+ :legend-title="'Cases'"
226
+ :height="400"
227
+ />
228
+ ```
229
+
230
+ </template>
231
+ </ComponentDemo>
232
+
233
+ ### HSA-level map
234
+
235
+ Set `geoType="hsas"` to render Health Service Area boundaries. HSAs are dissolved from county boundaries using a built-in FIPS-to-HSA mapping. Use 6-digit HSA codes as IDs. State borders are overlaid for context.
236
+
237
+ <ComponentDemo>
238
+ <ChoroplethMap
239
+ geo-type="hsas"
240
+ :pan="true"
241
+ :zoom="true"
242
+ :data="[
243
+ { id: '010259', value: 100 },
244
+ { id: '060766', value: 90 },
245
+ { id: '120159', value: 85 },
246
+ { id: '090121', value: 70 },
247
+ { id: '110061', value: 60 },
248
+ { id: '040765', value: 55 },
249
+ { id: '080731', value: 50 },
250
+ { id: '050527', value: 45 },
251
+ { id: '100075', value: 40 },
252
+ { id: '020820', value: 35 },
253
+ ]"
254
+ title="Cases by HSA"
255
+ :legend-title="'Cases'"
256
+ :height="400"
257
+ />
258
+
259
+ <template #code>
260
+
261
+ ```vue
262
+ <ChoroplethMap
263
+ geo-type="hsas"
264
+ pan
265
+ zoom
266
+ :data="[
267
+ { id: '010259', value: 100 },
268
+ { id: '060766', value: 90 },
269
+ { id: '120159', value: 85 },
270
+ { id: '090121', value: 70 },
271
+ { id: '110061', value: 60 },
272
+ ]"
273
+ title="Cases by HSA"
274
+ :legend-title="'Cases'"
275
+ :height="400"
276
+ />
277
+ ```
278
+
279
+ </template>
280
+ </ComponentDemo>
281
+
282
+ <!--@include: ./_api/choropleth-map.md-->
283
+
284
+ ### StateData
285
+
286
+ ```ts
287
+ interface StateData {
288
+ /** FIPS code (e.g. "06" for California, "06037" for LA County) or name */
289
+ id: string;
290
+ value: number | string;
291
+ }
292
+ ```
293
+
294
+ ### ChoroplethColorScale
295
+
296
+ ```ts
297
+ interface ChoroplethColorScale {
298
+ /** Minimum color (CSS color string). Default: "#e5f0fa" */
299
+ min?: string;
300
+ /** Maximum color (CSS color string). Default: "#08519c" */
301
+ max?: string;
302
+ }
303
+ ```
304
+
305
+ ### ThresholdStop
306
+
307
+ Pass an array of `ThresholdStop` as `colorScale` for discrete color buckets instead of a linear gradient. The highest matching `min` wins.
308
+
309
+ ```ts
310
+ interface ThresholdStop {
311
+ /** Lower bound (inclusive). Values at or above this get this color. */
312
+ min: number;
313
+ color: string;
314
+ /** Optional label for the legend (defaults to the min value) */
315
+ label?: string;
316
+ }
317
+ ```
318
+
319
+ ### CategoricalStop
320
+
321
+ Pass an array of `CategoricalStop` as `colorScale` to map string values to colors. States whose `value` matches a stop's `value` get that color; unmatched values get `noDataColor`.
322
+
323
+ ```ts
324
+ interface CategoricalStop {
325
+ /** The categorical value to match */
326
+ value: string;
327
+ /** CSS color string */
328
+ color: string;
329
+ }
330
+ ```