@cdc/core 4.26.1 → 4.26.2
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/.claude/agents/qa-test-developer.md +126 -0
- package/CLAUDE.local.md +67 -0
- package/_stories/Gallery.Charts.stories.tsx +34 -41
- package/_stories/Gallery.DataBite.stories.tsx +14 -7
- package/_stories/Gallery.Maps.stories.tsx +36 -27
- package/_stories/Gallery.WaffleChart.stories.tsx +1 -1
- package/_stories/PageART.stories.tsx +4 -3
- package/_stories/PageBRFSS.stories.tsx +20 -15
- package/_stories/PageCancerRegistries.stories.tsx +14 -14
- package/_stories/PageEasternEquineEncephalitis.stories.tsx +30 -16
- package/_stories/PageExcessiveAlcoholUse.stories.tsx +148 -143
- package/_stories/PageMaternalMortality.stories.tsx +4 -3
- package/_stories/PageOralHealth.stories.tsx +14 -9
- package/_stories/PageSmokingTobacco.stories.tsx +14 -9
- package/_stories/PageStateDiabetesProfiles.stories.tsx +14 -9
- package/_stories/PageWastewater.stories.tsx +40 -26
- package/_stories/VegaImport.stories.tsx +401 -0
- package/_stories/vega-fixtures/bars-with-line.json +444 -0
- package/_stories/vega-fixtures/bars.json +58 -0
- package/_stories/vega-fixtures/combo-bar-rolling-mean.json +88 -0
- package/_stories/vega-fixtures/combo.json +68 -0
- package/_stories/vega-fixtures/grouped-horizontal-bars.json +83 -0
- package/_stories/vega-fixtures/grouped-horizontal-bars2.json +231 -0
- package/_stories/vega-fixtures/horizontal-bar.json +427 -0
- package/_stories/vega-fixtures/horizontal-bars-with-bad-colors.json +197 -0
- package/_stories/vega-fixtures/horizontal-bars2.json +58 -0
- package/_stories/vega-fixtures/lines.json +227 -0
- package/_stories/vega-fixtures/measles-bars.json +348 -0
- package/_stories/vega-fixtures/measles-map.json +11101 -0
- package/_stories/vega-fixtures/measles-stacked-bars.json +2147 -0
- package/_stories/vega-fixtures/multi-dataset.json +255 -0
- package/_stories/vega-fixtures/no-data.json +14 -0
- package/_stories/vega-fixtures/pie-chart.json +94 -0
- package/_stories/vega-fixtures/repeat-spec.json +47 -0
- package/_stories/vega-fixtures/stacked-area.json +222 -0
- package/_stories/vega-fixtures/stacked-bar-with-rect.json +3412 -0
- package/_stories/vega-fixtures/stacked-bars-with-line.json +364 -0
- package/_stories/vega-fixtures/stacked-bars.json +212 -0
- package/_stories/vega-fixtures/stacked-horizontal-bars.json +140 -0
- package/_stories/vega-fixtures/warning-combo.json +59 -0
- package/_stories/vega-fixtures/warning-scatter-and-line.json +1182 -0
- package/assets/icon-chart-area.svg +1 -0
- package/assets/icon-chart-radar.svg +23 -0
- package/assets/logo2.svg +31 -0
- package/components/AdvancedEditor/EmbedEditor.tsx +270 -38
- package/components/CustomColorsEditor/CustomColorsEditor.tsx +3 -10
- package/components/DataTable/helpers/getSeriesName.ts +6 -0
- package/components/EditorPanel/VizFilterEditor/NestedDropdownEditor.tsx +14 -6
- package/components/EditorPanel/VizFilterEditor/VizFilterEditor.tsx +4 -0
- package/components/EditorPanel/VizFilterEditor/components/FilterOrder.tsx +33 -29
- package/components/Layout/components/Sidebar/components/sidebar.styles.scss +2 -2
- package/components/Layout/components/Visualization/index.tsx +11 -0
- package/components/MediaControls.tsx +0 -1
- package/components/_stories/CustomColorsEditor.stories.tsx +37 -0
- package/components/_stories/DataTable.stories.tsx +1 -0
- package/data/colorPalettes.ts +18 -5
- package/data/mapColorPalettes.ts +10 -0
- package/devTemplate/dev.js +235 -0
- package/devTemplate/index.html +30 -0
- package/devTemplate/preview.html +1503 -0
- package/devTemplate/sidebar.css +151 -0
- package/dist/cove-main.css +2803 -4471
- package/dist/cove-main.css.map +1 -1
- package/generateViteConfig.js +111 -2
- package/helpers/DataTransform.ts +1 -5
- package/helpers/cove/date.ts +33 -1
- package/helpers/cove/string.ts +29 -0
- package/helpers/coveUpdateWorker.ts +3 -1
- package/helpers/embed/embedCodeGenerator.ts +80 -0
- package/helpers/embed/embedHelper.js +158 -0
- package/helpers/embed/filterUtils.ts +121 -0
- package/helpers/embed/index.ts +21 -0
- package/helpers/embed/urlValidation.ts +119 -0
- package/helpers/filterVizData.ts +6 -1
- package/helpers/getFileExtension.ts +0 -6
- package/helpers/metrics/types.ts +3 -0
- package/helpers/palettes/colorDistributions.ts +1 -1
- package/helpers/palettes/utils.ts +12 -12
- package/helpers/parseCsvWithQuotes.ts +15 -14
- package/helpers/prepareScreenshot.ts +27 -7
- package/helpers/testing.ts +44 -0
- package/helpers/tests/DataTransform.test.ts +125 -0
- package/helpers/tests/date.test.ts +64 -0
- package/helpers/vegaConfig.ts +1 -1
- package/helpers/vegaConfigImport.ts +160 -0
- package/helpers/ver/4.26.1.ts +1 -1
- package/helpers/ver/4.26.2.ts +84 -0
- package/helpers/ver/tests/4.26.1.test.ts +105 -0
- package/helpers/ver/tests/4.26.2.test.ts +298 -0
- package/helpers/viewports.ts +2 -0
- package/package.json +27 -32
- package/styles/v2/components/editor.scss +9 -9
- package/styles/v2/utils/_grid.scss +8 -3
- package/types/Annotation.ts +10 -11
- package/types/General.ts +2 -0
- package/types/Palette.ts +21 -0
- package/types/Visualization.ts +6 -0
- package/_stories/StoryRenderingTests.stories.tsx +0 -164
- package/helpers/embedCodeGenerator.ts +0 -109
|
@@ -0,0 +1,298 @@
|
|
|
1
|
+
import update_4_26_2 from '../4.26.2'
|
|
2
|
+
import { expect, describe, it } from 'vitest'
|
|
3
|
+
|
|
4
|
+
describe('update_4_26_2', () => {
|
|
5
|
+
describe('migrateAnnotationDimensions', () => {
|
|
6
|
+
it('should convert Y position from absolute pixels to percentage and delete savedDimensions', () => {
|
|
7
|
+
const config: any = {
|
|
8
|
+
type: 'chart',
|
|
9
|
+
version: '4.26.1',
|
|
10
|
+
heights: { vertical: 400 },
|
|
11
|
+
annotations: [
|
|
12
|
+
{
|
|
13
|
+
text: 'Test Annotation',
|
|
14
|
+
x: 50,
|
|
15
|
+
y: 200,
|
|
16
|
+
savedDimensions: [800, 560], // old format: will be deleted
|
|
17
|
+
dx: 10,
|
|
18
|
+
dy: -10
|
|
19
|
+
}
|
|
20
|
+
]
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const result = update_4_26_2(config)
|
|
24
|
+
|
|
25
|
+
// Y is now calculated as percentage of heights.vertical (400)
|
|
26
|
+
expect(result.annotations[0].y).toBe(50) // 200 / 400 * 100 = 50
|
|
27
|
+
expect(result.annotations[0].x).toBe(50)
|
|
28
|
+
// savedDimensions should be deleted to preserve old dx/dy behavior
|
|
29
|
+
expect(result.annotations[0].savedDimensions).toBeUndefined()
|
|
30
|
+
// dx/dy should be preserved unchanged
|
|
31
|
+
expect(result.annotations[0].dx).toBe(10)
|
|
32
|
+
expect(result.annotations[0].dy).toBe(-10)
|
|
33
|
+
expect(result.version).toBe('4.26.2')
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
it('should handle multiple annotations with different Y positions', () => {
|
|
37
|
+
const config: any = {
|
|
38
|
+
type: 'chart',
|
|
39
|
+
version: '4.26.1',
|
|
40
|
+
heights: { vertical: 500 },
|
|
41
|
+
annotations: [
|
|
42
|
+
{
|
|
43
|
+
text: 'Top',
|
|
44
|
+
x: 25,
|
|
45
|
+
y: 100,
|
|
46
|
+
savedDimensions: [1000, 700]
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
text: 'Middle',
|
|
50
|
+
x: 75,
|
|
51
|
+
y: 250,
|
|
52
|
+
savedDimensions: [1000, 700]
|
|
53
|
+
}
|
|
54
|
+
]
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const result = update_4_26_2(config)
|
|
58
|
+
|
|
59
|
+
// Y calculated as percentage of heights.vertical (500)
|
|
60
|
+
expect(result.annotations[0].y).toBe(20) // 100 / 500 * 100 = 20
|
|
61
|
+
expect(result.annotations[1].y).toBe(50) // 250 / 500 * 100 = 50
|
|
62
|
+
// savedDimensions should be deleted
|
|
63
|
+
expect(result.annotations[0].savedDimensions).toBeUndefined()
|
|
64
|
+
expect(result.annotations[1].savedDimensions).toBeUndefined()
|
|
65
|
+
})
|
|
66
|
+
|
|
67
|
+
it('should use default vertical height (300) when heights not specified', () => {
|
|
68
|
+
const config: any = {
|
|
69
|
+
type: 'chart',
|
|
70
|
+
version: '4.26.1',
|
|
71
|
+
annotations: [
|
|
72
|
+
{
|
|
73
|
+
text: 'No heights config',
|
|
74
|
+
x: 50,
|
|
75
|
+
y: 150,
|
|
76
|
+
savedDimensions: [800, 560]
|
|
77
|
+
}
|
|
78
|
+
]
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const result = update_4_26_2(config)
|
|
82
|
+
|
|
83
|
+
// Uses default vertical height of 300
|
|
84
|
+
expect(result.annotations[0].y).toBe(50) // 150 / 300 * 100 = 50
|
|
85
|
+
expect(result.annotations[0].savedDimensions).toBeUndefined()
|
|
86
|
+
})
|
|
87
|
+
|
|
88
|
+
it('should use horizontal height for horizontal orientation', () => {
|
|
89
|
+
const config: any = {
|
|
90
|
+
type: 'chart',
|
|
91
|
+
version: '4.26.1',
|
|
92
|
+
orientation: 'horizontal',
|
|
93
|
+
heights: { horizontal: 750 },
|
|
94
|
+
annotations: [
|
|
95
|
+
{
|
|
96
|
+
text: 'Horizontal chart annotation',
|
|
97
|
+
x: 50,
|
|
98
|
+
y: 375,
|
|
99
|
+
savedDimensions: [800, 900]
|
|
100
|
+
}
|
|
101
|
+
]
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
const result = update_4_26_2(config)
|
|
105
|
+
|
|
106
|
+
// Uses heights.horizontal for horizontal charts
|
|
107
|
+
expect(result.annotations[0].y).toBe(50) // 375 / 750 * 100 = 50
|
|
108
|
+
expect(result.annotations[0].savedDimensions).toBeUndefined()
|
|
109
|
+
})
|
|
110
|
+
|
|
111
|
+
it('should handle dashboard configs with nested visualizations', () => {
|
|
112
|
+
const config: any = {
|
|
113
|
+
type: 'dashboard',
|
|
114
|
+
version: '4.26.1',
|
|
115
|
+
visualizations: {
|
|
116
|
+
chart1: {
|
|
117
|
+
type: 'chart',
|
|
118
|
+
heights: { vertical: 300 },
|
|
119
|
+
annotations: [
|
|
120
|
+
{
|
|
121
|
+
text: 'Chart 1 Annotation',
|
|
122
|
+
x: 30,
|
|
123
|
+
y: 150,
|
|
124
|
+
savedDimensions: [600, 450]
|
|
125
|
+
}
|
|
126
|
+
]
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
const result = update_4_26_2(config)
|
|
132
|
+
|
|
133
|
+
expect(result.visualizations.chart1.annotations[0].y).toBe(50) // 150 / 300 * 100 = 50
|
|
134
|
+
expect(result.visualizations.chart1.annotations[0].savedDimensions).toBeUndefined()
|
|
135
|
+
})
|
|
136
|
+
|
|
137
|
+
it('should preserve all other annotation properties and delete xKey entirely', () => {
|
|
138
|
+
const config: any = {
|
|
139
|
+
type: 'chart',
|
|
140
|
+
version: '4.26.1',
|
|
141
|
+
heights: { vertical: 500 },
|
|
142
|
+
annotations: [
|
|
143
|
+
{
|
|
144
|
+
text: 'Complex Annotation',
|
|
145
|
+
x: 50,
|
|
146
|
+
y: 250,
|
|
147
|
+
savedDimensions: [1000, 700],
|
|
148
|
+
dx: 20,
|
|
149
|
+
dy: -30,
|
|
150
|
+
xKey: 1577836800000,
|
|
151
|
+
yKey: '42',
|
|
152
|
+
seriesKey: 'series1',
|
|
153
|
+
marker: 'arrow'
|
|
154
|
+
}
|
|
155
|
+
]
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
const result = update_4_26_2(config)
|
|
159
|
+
|
|
160
|
+
const annotation = result.annotations[0]
|
|
161
|
+
expect(annotation.y).toBe(50) // 250 / 500 * 100 = 50
|
|
162
|
+
expect(annotation.text).toBe('Complex Annotation')
|
|
163
|
+
expect(annotation.dx).toBe(20)
|
|
164
|
+
expect(annotation.dy).toBe(-30)
|
|
165
|
+
// xKey is deleted entirely (not renamed to dataX) because old format
|
|
166
|
+
// stored timestamps but new dataX expects raw data values
|
|
167
|
+
expect(annotation.xKey).toBeUndefined()
|
|
168
|
+
expect(annotation.dataX).toBeUndefined()
|
|
169
|
+
expect(annotation.yKey).toBeUndefined()
|
|
170
|
+
// Non-empty seriesKey is preserved
|
|
171
|
+
expect(annotation.seriesKey).toBe('series1')
|
|
172
|
+
expect(annotation.savedDimensions).toBeUndefined()
|
|
173
|
+
})
|
|
174
|
+
|
|
175
|
+
it('should delete empty seriesKey', () => {
|
|
176
|
+
const config: any = {
|
|
177
|
+
type: 'chart',
|
|
178
|
+
version: '4.26.1',
|
|
179
|
+
heights: { vertical: 300 },
|
|
180
|
+
annotations: [
|
|
181
|
+
{
|
|
182
|
+
text: 'Annotation with empty seriesKey',
|
|
183
|
+
x: 50,
|
|
184
|
+
y: 150,
|
|
185
|
+
seriesKey: ''
|
|
186
|
+
}
|
|
187
|
+
]
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
const result = update_4_26_2(config)
|
|
191
|
+
|
|
192
|
+
// Empty seriesKey should be deleted to prevent yScale(undefined) errors
|
|
193
|
+
expect(result.annotations[0].seriesKey).toBeUndefined()
|
|
194
|
+
})
|
|
195
|
+
|
|
196
|
+
it('should handle config with no annotations', () => {
|
|
197
|
+
const config: any = {
|
|
198
|
+
type: 'chart',
|
|
199
|
+
version: '4.26.1',
|
|
200
|
+
title: 'Chart without annotations'
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
const result = update_4_26_2(config)
|
|
204
|
+
|
|
205
|
+
expect(result.annotations).toBeUndefined()
|
|
206
|
+
expect(result.title).toBe('Chart without annotations')
|
|
207
|
+
})
|
|
208
|
+
|
|
209
|
+
it('should handle annotation without savedDimensions', () => {
|
|
210
|
+
const config: any = {
|
|
211
|
+
type: 'chart',
|
|
212
|
+
version: '4.26.1',
|
|
213
|
+
heights: { vertical: 300 },
|
|
214
|
+
annotations: [
|
|
215
|
+
{
|
|
216
|
+
text: 'No savedDimensions',
|
|
217
|
+
x: 50,
|
|
218
|
+
y: 150
|
|
219
|
+
}
|
|
220
|
+
]
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
const result = update_4_26_2(config)
|
|
224
|
+
|
|
225
|
+
expect(result.annotations[0].y).toBe(50) // 150 / 300 * 100 = 50
|
|
226
|
+
expect(result.annotations[0].savedDimensions).toBeUndefined()
|
|
227
|
+
})
|
|
228
|
+
})
|
|
229
|
+
|
|
230
|
+
describe('combined migrations', () => {
|
|
231
|
+
it('should run all migrations together', () => {
|
|
232
|
+
const config: any = {
|
|
233
|
+
type: 'dashboard',
|
|
234
|
+
version: '4.26.1',
|
|
235
|
+
dashboard: {
|
|
236
|
+
sharedFilters: [
|
|
237
|
+
{
|
|
238
|
+
type: 'datafilter',
|
|
239
|
+
parents: 'parent-id'
|
|
240
|
+
}
|
|
241
|
+
]
|
|
242
|
+
},
|
|
243
|
+
visualizations: {
|
|
244
|
+
chart1: {
|
|
245
|
+
type: 'chart',
|
|
246
|
+
heights: { vertical: 400 },
|
|
247
|
+
brush: { enabled: true },
|
|
248
|
+
annotations: [
|
|
249
|
+
{
|
|
250
|
+
x: 50,
|
|
251
|
+
y: 200,
|
|
252
|
+
savedDimensions: [800, 560]
|
|
253
|
+
}
|
|
254
|
+
]
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
const result = update_4_26_2(config)
|
|
260
|
+
|
|
261
|
+
expect(result.visualizations.chart1.annotations[0].y).toBe(50) // 200 / 400 * 100 = 50
|
|
262
|
+
expect(result.visualizations.chart1.annotations[0].anchorMode).toBe('fixed')
|
|
263
|
+
expect(result.visualizations.chart1.annotations[0].savedDimensions).toBeUndefined()
|
|
264
|
+
expect(result.visualizations.chart1.annotations[0].dataX).toBeUndefined()
|
|
265
|
+
expect(result.version).toBe('4.26.2')
|
|
266
|
+
})
|
|
267
|
+
|
|
268
|
+
it('should migrate data model along with Y position', () => {
|
|
269
|
+
const config: any = {
|
|
270
|
+
type: 'chart',
|
|
271
|
+
version: '4.26.1',
|
|
272
|
+
heights: { vertical: 400 },
|
|
273
|
+
annotations: [
|
|
274
|
+
{
|
|
275
|
+
x: 50,
|
|
276
|
+
y: 200,
|
|
277
|
+
savedDimensions: [800, 560],
|
|
278
|
+
xKey: 1577836800000,
|
|
279
|
+
yKey: '42',
|
|
280
|
+
snapToNearestPoint: true
|
|
281
|
+
}
|
|
282
|
+
]
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
const result = update_4_26_2(config)
|
|
286
|
+
|
|
287
|
+
const annotation = result.annotations[0]
|
|
288
|
+
expect(annotation.y).toBe(50) // 200 / 400 * 100 = 50
|
|
289
|
+
expect(annotation.anchorMode).toBe('fixed')
|
|
290
|
+
// xKey is deleted entirely (not renamed to dataX) - format incompatible
|
|
291
|
+
expect(annotation.dataX).toBeUndefined()
|
|
292
|
+
expect(annotation.xKey).toBeUndefined()
|
|
293
|
+
expect(annotation.yKey).toBeUndefined()
|
|
294
|
+
expect(annotation.snapToNearestPoint).toBeUndefined()
|
|
295
|
+
expect(annotation.savedDimensions).toBeUndefined()
|
|
296
|
+
})
|
|
297
|
+
})
|
|
298
|
+
})
|
package/helpers/viewports.ts
CHANGED
|
@@ -15,4 +15,6 @@ export const isMobileTerritoryViewport = currentViewport => isBelowBreakpoint('s
|
|
|
15
15
|
|
|
16
16
|
export const isMobileFontViewport = currentViewport => isBelowBreakpoint('sm', currentViewport)
|
|
17
17
|
|
|
18
|
+
export const isMobileAnnotationViewport = currentViewport => isBelowBreakpoint('sm', currentViewport)
|
|
19
|
+
|
|
18
20
|
export const isMobileSmallMultiplesViewport = currentViewport => isBelowBreakpoint('md', currentViewport)
|
package/package.json
CHANGED
|
@@ -1,54 +1,49 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cdc/core",
|
|
3
|
-
"version": "4.26.
|
|
3
|
+
"version": "4.26.2",
|
|
4
4
|
"description": "Core components, styles, hooks, and helpers, for the CDC Open Visualization project",
|
|
5
|
-
"moduleName": "CdcCore",
|
|
6
|
-
"main": "dist/cdccore",
|
|
7
|
-
"type": "module",
|
|
8
|
-
"scripts": {
|
|
9
|
-
"test": "vitest run --environment jsdom --reporter verbose",
|
|
10
|
-
"test-watch": "vitest watch --reporter verbose",
|
|
11
|
-
"test-watch:ui": "vitest --ui",
|
|
12
|
-
"build": "sass styles/cove-main.scss dist/cove-main.css"
|
|
13
|
-
},
|
|
14
|
-
"repository": {
|
|
15
|
-
"type": "git",
|
|
16
|
-
"url": "git+https://github.com/CDCgov/cdc-open-viz.git"
|
|
17
|
-
},
|
|
18
|
-
"author": "Rob Shelnutt <rob@blackairplane.com>",
|
|
19
|
-
"homepage": "https://github.com/CDCgov/cdc-open-viz#readme",
|
|
20
|
-
"bugs": {
|
|
21
|
-
"url": "https://github.com/CDCgov/cdc-open-viz/issues"
|
|
22
|
-
},
|
|
23
5
|
"license": "Apache-2.0",
|
|
6
|
+
"author": "Rob Shelnutt <rob@blackairplane.com>",
|
|
7
|
+
"bugs": "https://github.com/CDCgov/cdc-open-viz/issues",
|
|
24
8
|
"dependencies": {
|
|
25
9
|
"@hello-pangea/dnd": "^16.2.0",
|
|
26
|
-
"chroma-js": "3.1.2",
|
|
27
|
-
"dompurify": "^3.
|
|
28
|
-
"html-react-parser": "5.2.3",
|
|
10
|
+
"chroma-js": "^3.1.2",
|
|
11
|
+
"dompurify": "^3.3.1",
|
|
12
|
+
"html-react-parser": "^5.2.3",
|
|
29
13
|
"html2canvas": "^1.4.1",
|
|
30
14
|
"json-edit-react": "^1.27.0",
|
|
31
|
-
"papaparse": "5.5.2",
|
|
15
|
+
"papaparse": "^5.5.2",
|
|
32
16
|
"prop-types": "^15.8.1",
|
|
33
17
|
"react-accessible-accordion": "^5.0.1",
|
|
34
18
|
"react-select": "^5.3.1",
|
|
35
19
|
"react-tooltip": "5.8.2-beta.3",
|
|
36
20
|
"resize-observer-polyfill": "^1.5.1",
|
|
37
|
-
"use-debounce": "^10.0
|
|
21
|
+
"use-debounce": "^10.1.0",
|
|
38
22
|
"vega": "^6.1.0",
|
|
39
23
|
"vega-lite": "^6.1.0"
|
|
40
24
|
},
|
|
41
|
-
"peerDependencies": {
|
|
42
|
-
"react": "^18.2.0",
|
|
43
|
-
"react-dom": "^18.2.0"
|
|
44
|
-
},
|
|
45
|
-
"gitHead": "7e3b27098c4eb7a24bc9c3654ad53f88d6419f16",
|
|
46
25
|
"devDependencies": {
|
|
47
26
|
"@rollup/plugin-dsv": "^3.0.2",
|
|
48
|
-
"@vitejs/plugin-react": "^
|
|
27
|
+
"@vitejs/plugin-react": "^5.1.2",
|
|
49
28
|
"sass": "^1.89.2",
|
|
50
|
-
"vite": "^
|
|
29
|
+
"vite": "^7.3.1",
|
|
51
30
|
"vite-plugin-css-injected-by-js": "^2.4.0",
|
|
52
31
|
"vite-plugin-svgr": "^4.2.0"
|
|
53
|
-
}
|
|
32
|
+
},
|
|
33
|
+
"gitHead": "be3413e8e1149abf94225108f86a7910f56e0616",
|
|
34
|
+
"homepage": "https://github.com/CDCgov/cdc-open-viz#readme",
|
|
35
|
+
"main": "dist/cdccore",
|
|
36
|
+
"moduleName": "CdcCore",
|
|
37
|
+
"peerDependencies": {
|
|
38
|
+
"react": "^18.2.0",
|
|
39
|
+
"react-dom": "^18.2.0"
|
|
40
|
+
},
|
|
41
|
+
"repository": "CDCgov/cdc-open-viz.git",
|
|
42
|
+
"scripts": {
|
|
43
|
+
"build": "sass styles/cove-main.scss dist/cove-main.css",
|
|
44
|
+
"test": "vitest run --environment jsdom --reporter verbose",
|
|
45
|
+
"test-watch": "vitest watch --reporter verbose",
|
|
46
|
+
"test-watch:ui": "vitest --ui"
|
|
47
|
+
},
|
|
48
|
+
"type": "module"
|
|
54
49
|
}
|
|
@@ -93,7 +93,7 @@
|
|
|
93
93
|
margin-top: 1em;
|
|
94
94
|
justify-content: space-between;
|
|
95
95
|
|
|
96
|
-
>label {
|
|
96
|
+
> label {
|
|
97
97
|
width: 48%;
|
|
98
98
|
margin-top: 0 !important;
|
|
99
99
|
}
|
|
@@ -130,7 +130,7 @@
|
|
|
130
130
|
cursor: pointer;
|
|
131
131
|
}
|
|
132
132
|
|
|
133
|
-
+li {
|
|
133
|
+
+ li {
|
|
134
134
|
border-top: $lightGray 1px solid;
|
|
135
135
|
}
|
|
136
136
|
}
|
|
@@ -189,7 +189,7 @@
|
|
|
189
189
|
display: flex;
|
|
190
190
|
justify-content: space-between;
|
|
191
191
|
|
|
192
|
-
>label {
|
|
192
|
+
> label {
|
|
193
193
|
margin-top: 0;
|
|
194
194
|
width: 30%;
|
|
195
195
|
display: inline-block;
|
|
@@ -237,7 +237,7 @@
|
|
|
237
237
|
margin-top: 0;
|
|
238
238
|
}
|
|
239
239
|
|
|
240
|
-
label+label {
|
|
240
|
+
label + label {
|
|
241
241
|
margin-top: 1em;
|
|
242
242
|
}
|
|
243
243
|
|
|
@@ -256,13 +256,13 @@
|
|
|
256
256
|
|
|
257
257
|
.sort-list {
|
|
258
258
|
list-style: none;
|
|
259
|
+
padding: 0;
|
|
259
260
|
|
|
260
|
-
>li {
|
|
261
|
-
margin-right: 0.3em;
|
|
261
|
+
> li {
|
|
262
262
|
margin-bottom: 0.3em;
|
|
263
263
|
}
|
|
264
264
|
|
|
265
|
-
li>div {
|
|
265
|
+
li > div {
|
|
266
266
|
display: block;
|
|
267
267
|
box-sizing: border-box;
|
|
268
268
|
border: 1px solid #d1d1d1;
|
|
@@ -270,8 +270,8 @@
|
|
|
270
270
|
background: #f1f1f1;
|
|
271
271
|
padding: 0.4em 0.6em;
|
|
272
272
|
font-size: 0.8em;
|
|
273
|
-
margin-bottom: 0.3em;
|
|
274
273
|
cursor: move;
|
|
274
|
+
width: 100%;
|
|
275
275
|
}
|
|
276
276
|
}
|
|
277
277
|
|
|
@@ -491,4 +491,4 @@ ul.color-palette {
|
|
|
491
491
|
// CheckBox component styling for EditorPanel/Inputs
|
|
492
492
|
.edit-checkbox {
|
|
493
493
|
margin-right: 8px;
|
|
494
|
-
}
|
|
494
|
+
}
|
|
@@ -3,18 +3,21 @@ $grid-gap-max: 64;
|
|
|
3
3
|
$grid-columns: 12;
|
|
4
4
|
|
|
5
5
|
@mixin create-grid-selectors($breakpoint: null) {
|
|
6
|
-
$infix: if($breakpoint ==
|
|
6
|
+
$infix: if(sass($breakpoint ==null): ""; else: "-#{$breakpoint}");
|
|
7
7
|
|
|
8
8
|
@for $i from 1 through $grid-columns {
|
|
9
9
|
.col#{$infix}-#{$i} {
|
|
10
10
|
grid-column-end: span $i;
|
|
11
11
|
}
|
|
12
|
+
|
|
12
13
|
.col-offset#{$infix}-#{$i} {
|
|
13
14
|
grid-column-start: $i + 1;
|
|
14
15
|
}
|
|
16
|
+
|
|
15
17
|
.row#{$infix}-#{$i} {
|
|
16
18
|
grid-row-end: span $i;
|
|
17
19
|
}
|
|
20
|
+
|
|
18
21
|
.row-offset#{$infix}-#{$i} {
|
|
19
22
|
grid-row-start: $i + 1;
|
|
20
23
|
}
|
|
@@ -23,11 +26,13 @@ $grid-columns: 12;
|
|
|
23
26
|
|
|
24
27
|
@mixin grid-gaps() {
|
|
25
28
|
$i: 0;
|
|
26
|
-
|
|
29
|
+
|
|
30
|
+
@while ($i * $grid-gap-offset) <=$grid-gap-max {
|
|
27
31
|
.grid-gap-#{$i} {
|
|
28
32
|
grid-gap: #{($i * $grid-gap-offset) + 'px'};
|
|
29
33
|
gap: #{($i * $grid-gap-offset) + 'px'};
|
|
30
34
|
}
|
|
35
|
+
|
|
31
36
|
$i: $i + 1;
|
|
32
37
|
}
|
|
33
38
|
}
|
|
@@ -44,4 +49,4 @@ $grid-columns: 12;
|
|
|
44
49
|
@media (min-width: $width) {
|
|
45
50
|
@include create-grid-selectors($breakpoint);
|
|
46
51
|
}
|
|
47
|
-
}
|
|
52
|
+
}
|
package/types/Annotation.ts
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
export type Annotation = {
|
|
2
|
+
// Positioning mode: fixed uses x/y percentages, data anchors to data point
|
|
3
|
+
anchorMode?: 'fixed' | 'data'
|
|
4
|
+
|
|
2
5
|
// background opacity of annotation
|
|
3
6
|
opacity: number
|
|
4
7
|
// HTML text string to display in annotation
|
|
@@ -15,26 +18,22 @@ export type Annotation = {
|
|
|
15
18
|
horizontal: boolean
|
|
16
19
|
vertical: boolean
|
|
17
20
|
}
|
|
18
|
-
//
|
|
19
|
-
|
|
20
|
-
//
|
|
21
|
-
yKey: string
|
|
22
|
-
// orignal x value of subject
|
|
23
|
-
originalX: number
|
|
24
|
-
// x of subject
|
|
21
|
+
// Data X value for data-anchored mode (timestamp, category, etc.)
|
|
22
|
+
dataX?: any
|
|
23
|
+
// x of subject (percentage 0-100)
|
|
25
24
|
x: number
|
|
26
|
-
// y of object
|
|
25
|
+
// y of object (percentage 0-100)
|
|
27
26
|
y: number
|
|
28
27
|
// x offset of label from subject
|
|
29
28
|
dx: number
|
|
30
29
|
// y offset of label from subject
|
|
31
30
|
dy: number
|
|
32
31
|
// assigned series that the annotation should snap to
|
|
33
|
-
seriesKey
|
|
34
|
-
// if the dragged item should be snapped to the nearest point
|
|
35
|
-
snapToNearestPoint: boolean
|
|
32
|
+
seriesKey?: string
|
|
36
33
|
// type of connecting line from label to subject
|
|
37
34
|
connectionType: 'line' | 'curve' | 'elbow' | 'none'
|
|
35
|
+
// curve control point offset for curve connection type
|
|
36
|
+
bezier?: number
|
|
38
37
|
// marker type highlighting the subject
|
|
39
38
|
marker: 'arrow' | 'circle'
|
|
40
39
|
// should the item be snapped to the subject?
|
package/types/General.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { BoxPlot } from './BoxPlot'
|
|
2
|
+
import { Palette } from './Palette'
|
|
2
3
|
|
|
3
4
|
export type General = {
|
|
4
5
|
boxplot: BoxPlot
|
|
@@ -12,4 +13,5 @@ export type General = {
|
|
|
12
13
|
hideNullValue: boolean
|
|
13
14
|
title: string
|
|
14
15
|
annotationDropdownText?: string
|
|
16
|
+
palette?: Palette
|
|
15
17
|
}
|
package/types/Palette.ts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export type PaletteVersion = '1.0' | '2.0'
|
|
2
|
+
|
|
3
|
+
export type PaletteBackup = {
|
|
4
|
+
name: string
|
|
5
|
+
type?: 'twoColor' | 'primary'
|
|
6
|
+
version?: PaletteVersion
|
|
7
|
+
isReversed?: boolean
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export type Palette = {
|
|
11
|
+
name?: string
|
|
12
|
+
customColors?: string[]
|
|
13
|
+
version?: PaletteVersion
|
|
14
|
+
isReversed?: boolean
|
|
15
|
+
backups?: PaletteBackup[]
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export type TwoColorConfig = {
|
|
19
|
+
palette?: string
|
|
20
|
+
isPaletteReversed?: boolean
|
|
21
|
+
}
|
package/types/Visualization.ts
CHANGED
|
@@ -11,6 +11,7 @@ import { General } from './General'
|
|
|
11
11
|
import { Runtime } from './Runtime'
|
|
12
12
|
import { DashboardFilters } from '@cdc/dashboard/src/types/DashboardFilters'
|
|
13
13
|
import Footnotes from './Footnotes'
|
|
14
|
+
import { TwoColorConfig } from './Palette'
|
|
14
15
|
|
|
15
16
|
// This was originally created as a catchall for the different types of visualizations.
|
|
16
17
|
// Currently it includes properties that ares specific to one Visualization type.
|
|
@@ -44,6 +45,11 @@ type DeprecatedVisualizationType = {
|
|
|
44
45
|
visualizationType: string
|
|
45
46
|
xAxis: Axis
|
|
46
47
|
preliminaryData: { type: 'effect' | 'suppression'; value: string }[]
|
|
48
|
+
twoColor?: TwoColorConfig
|
|
49
|
+
/** @deprecated Legacy v1 palette name - use general.palette.name instead */
|
|
50
|
+
palette?: string
|
|
51
|
+
/** @deprecated Legacy v1 color name - use general.palette.name instead */
|
|
52
|
+
color?: string
|
|
47
53
|
}
|
|
48
54
|
|
|
49
55
|
type StatefulProperties = {
|