@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.
Files changed (99) hide show
  1. package/.claude/agents/qa-test-developer.md +126 -0
  2. package/CLAUDE.local.md +67 -0
  3. package/_stories/Gallery.Charts.stories.tsx +34 -41
  4. package/_stories/Gallery.DataBite.stories.tsx +14 -7
  5. package/_stories/Gallery.Maps.stories.tsx +36 -27
  6. package/_stories/Gallery.WaffleChart.stories.tsx +1 -1
  7. package/_stories/PageART.stories.tsx +4 -3
  8. package/_stories/PageBRFSS.stories.tsx +20 -15
  9. package/_stories/PageCancerRegistries.stories.tsx +14 -14
  10. package/_stories/PageEasternEquineEncephalitis.stories.tsx +30 -16
  11. package/_stories/PageExcessiveAlcoholUse.stories.tsx +148 -143
  12. package/_stories/PageMaternalMortality.stories.tsx +4 -3
  13. package/_stories/PageOralHealth.stories.tsx +14 -9
  14. package/_stories/PageSmokingTobacco.stories.tsx +14 -9
  15. package/_stories/PageStateDiabetesProfiles.stories.tsx +14 -9
  16. package/_stories/PageWastewater.stories.tsx +40 -26
  17. package/_stories/VegaImport.stories.tsx +401 -0
  18. package/_stories/vega-fixtures/bars-with-line.json +444 -0
  19. package/_stories/vega-fixtures/bars.json +58 -0
  20. package/_stories/vega-fixtures/combo-bar-rolling-mean.json +88 -0
  21. package/_stories/vega-fixtures/combo.json +68 -0
  22. package/_stories/vega-fixtures/grouped-horizontal-bars.json +83 -0
  23. package/_stories/vega-fixtures/grouped-horizontal-bars2.json +231 -0
  24. package/_stories/vega-fixtures/horizontal-bar.json +427 -0
  25. package/_stories/vega-fixtures/horizontal-bars-with-bad-colors.json +197 -0
  26. package/_stories/vega-fixtures/horizontal-bars2.json +58 -0
  27. package/_stories/vega-fixtures/lines.json +227 -0
  28. package/_stories/vega-fixtures/measles-bars.json +348 -0
  29. package/_stories/vega-fixtures/measles-map.json +11101 -0
  30. package/_stories/vega-fixtures/measles-stacked-bars.json +2147 -0
  31. package/_stories/vega-fixtures/multi-dataset.json +255 -0
  32. package/_stories/vega-fixtures/no-data.json +14 -0
  33. package/_stories/vega-fixtures/pie-chart.json +94 -0
  34. package/_stories/vega-fixtures/repeat-spec.json +47 -0
  35. package/_stories/vega-fixtures/stacked-area.json +222 -0
  36. package/_stories/vega-fixtures/stacked-bar-with-rect.json +3412 -0
  37. package/_stories/vega-fixtures/stacked-bars-with-line.json +364 -0
  38. package/_stories/vega-fixtures/stacked-bars.json +212 -0
  39. package/_stories/vega-fixtures/stacked-horizontal-bars.json +140 -0
  40. package/_stories/vega-fixtures/warning-combo.json +59 -0
  41. package/_stories/vega-fixtures/warning-scatter-and-line.json +1182 -0
  42. package/assets/icon-chart-area.svg +1 -0
  43. package/assets/icon-chart-radar.svg +23 -0
  44. package/assets/logo2.svg +31 -0
  45. package/components/AdvancedEditor/EmbedEditor.tsx +270 -38
  46. package/components/CustomColorsEditor/CustomColorsEditor.tsx +3 -10
  47. package/components/DataTable/helpers/getSeriesName.ts +6 -0
  48. package/components/EditorPanel/VizFilterEditor/NestedDropdownEditor.tsx +14 -6
  49. package/components/EditorPanel/VizFilterEditor/VizFilterEditor.tsx +4 -0
  50. package/components/EditorPanel/VizFilterEditor/components/FilterOrder.tsx +33 -29
  51. package/components/Layout/components/Sidebar/components/sidebar.styles.scss +2 -2
  52. package/components/Layout/components/Visualization/index.tsx +11 -0
  53. package/components/MediaControls.tsx +0 -1
  54. package/components/_stories/CustomColorsEditor.stories.tsx +37 -0
  55. package/components/_stories/DataTable.stories.tsx +1 -0
  56. package/data/colorPalettes.ts +18 -5
  57. package/data/mapColorPalettes.ts +10 -0
  58. package/devTemplate/dev.js +235 -0
  59. package/devTemplate/index.html +30 -0
  60. package/devTemplate/preview.html +1503 -0
  61. package/devTemplate/sidebar.css +151 -0
  62. package/dist/cove-main.css +2803 -4471
  63. package/dist/cove-main.css.map +1 -1
  64. package/generateViteConfig.js +111 -2
  65. package/helpers/DataTransform.ts +1 -5
  66. package/helpers/cove/date.ts +33 -1
  67. package/helpers/cove/string.ts +29 -0
  68. package/helpers/coveUpdateWorker.ts +3 -1
  69. package/helpers/embed/embedCodeGenerator.ts +80 -0
  70. package/helpers/embed/embedHelper.js +158 -0
  71. package/helpers/embed/filterUtils.ts +121 -0
  72. package/helpers/embed/index.ts +21 -0
  73. package/helpers/embed/urlValidation.ts +119 -0
  74. package/helpers/filterVizData.ts +6 -1
  75. package/helpers/getFileExtension.ts +0 -6
  76. package/helpers/metrics/types.ts +3 -0
  77. package/helpers/palettes/colorDistributions.ts +1 -1
  78. package/helpers/palettes/utils.ts +12 -12
  79. package/helpers/parseCsvWithQuotes.ts +15 -14
  80. package/helpers/prepareScreenshot.ts +27 -7
  81. package/helpers/testing.ts +44 -0
  82. package/helpers/tests/DataTransform.test.ts +125 -0
  83. package/helpers/tests/date.test.ts +64 -0
  84. package/helpers/vegaConfig.ts +1 -1
  85. package/helpers/vegaConfigImport.ts +160 -0
  86. package/helpers/ver/4.26.1.ts +1 -1
  87. package/helpers/ver/4.26.2.ts +84 -0
  88. package/helpers/ver/tests/4.26.1.test.ts +105 -0
  89. package/helpers/ver/tests/4.26.2.test.ts +298 -0
  90. package/helpers/viewports.ts +2 -0
  91. package/package.json +27 -32
  92. package/styles/v2/components/editor.scss +9 -9
  93. package/styles/v2/utils/_grid.scss +8 -3
  94. package/types/Annotation.ts +10 -11
  95. package/types/General.ts +2 -0
  96. package/types/Palette.ts +21 -0
  97. package/types/Visualization.ts +6 -0
  98. package/_stories/StoryRenderingTests.stories.tsx +0 -164
  99. 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
+ })
@@ -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.1",
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.2.4",
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.5",
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": "^4.3.4",
27
+ "@vitejs/plugin-react": "^5.1.2",
49
28
  "sass": "^1.89.2",
50
- "vite": "^5.4.21",
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 == null, '', '-#{$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
- @while ($i * $grid-gap-offset) <= $grid-gap-max {
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
+ }
@@ -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
- // x value for scaling
19
- xKey: string
20
- // y value for scaling
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: string
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
  }
@@ -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
+ }
@@ -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 = {