@cdc/chart 4.24.9 → 4.24.11

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 (95) hide show
  1. package/LICENSE +201 -0
  2. package/dist/cdcchart.js +45911 -41739
  3. package/examples/feature/boxplot/boxplot-data.json +88 -22
  4. package/examples/feature/boxplot/boxplot.json +540 -16
  5. package/examples/feature/boxplot/testing.csv +7 -7
  6. package/examples/feature/sankey/sankey-example-data.json +0 -1
  7. package/examples/private/test.json +20092 -0
  8. package/index.html +4 -4
  9. package/package.json +2 -2
  10. package/src/CdcChart.tsx +209 -188
  11. package/src/_stories/Chart.CustomColors.stories.tsx +19 -0
  12. package/src/_stories/Chart.DynamicSeries.stories.tsx +27 -0
  13. package/src/_stories/Chart.Legend.Gradient.stories.tsx +74 -0
  14. package/src/_stories/Chart.stories.tsx +30 -3
  15. package/src/_stories/ChartAxisLabels.stories.tsx +20 -0
  16. package/src/_stories/ChartAxisTitles.stories.tsx +53 -0
  17. package/src/_stories/ChartEditor.stories.tsx +27 -0
  18. package/src/_stories/ChartLine.Suppression.stories.tsx +25 -0
  19. package/src/_stories/ChartPrefixSuffix.stories.tsx +159 -0
  20. package/src/_stories/_mock/boxplot_multiseries.json +647 -0
  21. package/src/_stories/_mock/dynamic_series_bar_config.json +723 -0
  22. package/src/_stories/_mock/dynamic_series_config.json +979 -0
  23. package/src/_stories/_mock/horizontal_bar.json +257 -0
  24. package/src/_stories/_mock/large_x_axis_labels.json +261 -0
  25. package/src/_stories/_mock/paired-bar.json +262 -0
  26. package/src/_stories/_mock/pie_with_data.json +255 -0
  27. package/{examples/feature/scatterplot/scatterplot.json → src/_stories/_mock/scatterplot_mock.json} +62 -92
  28. package/src/_stories/_mock/simplified_line.json +1510 -0
  29. package/src/_stories/_mock/suppression_mock.json +1549 -0
  30. package/src/components/Annotations/components/AnnotationDraggable.tsx +0 -3
  31. package/src/components/Annotations/components/AnnotationDropdown.tsx +1 -1
  32. package/src/components/Axis/Categorical.Axis.tsx +22 -4
  33. package/src/components/BarChart/components/BarChart.Horizontal.tsx +95 -16
  34. package/src/components/BarChart/components/BarChart.StackedHorizontal.tsx +41 -17
  35. package/src/components/BarChart/components/BarChart.StackedVertical.tsx +43 -9
  36. package/src/components/BarChart/components/BarChart.Vertical.tsx +123 -47
  37. package/src/components/BarChart/helpers/index.ts +23 -5
  38. package/src/components/BoxPlot/BoxPlot.tsx +189 -0
  39. package/src/components/BrushChart.tsx +3 -2
  40. package/src/components/DeviationBar.jsx +58 -8
  41. package/src/components/EditorPanel/EditorPanel.tsx +127 -102
  42. package/src/components/EditorPanel/components/Panels/Panel.Annotate.tsx +11 -28
  43. package/src/components/EditorPanel/components/Panels/Panel.BoxPlot.tsx +51 -6
  44. package/src/components/EditorPanel/components/Panels/Panel.General.tsx +21 -4
  45. package/src/components/EditorPanel/components/Panels/Panel.Regions.tsx +40 -9
  46. package/src/components/EditorPanel/components/Panels/Panel.Sankey.tsx +3 -3
  47. package/src/components/EditorPanel/components/Panels/Panel.Series.tsx +121 -56
  48. package/src/components/EditorPanel/components/Panels/Panel.Visual.tsx +296 -35
  49. package/src/components/EditorPanel/components/panels.scss +4 -6
  50. package/src/components/EditorPanel/editor-panel.scss +0 -8
  51. package/src/components/EditorPanel/helpers/tests/updateFieldRankByValue.test.ts +38 -0
  52. package/src/components/EditorPanel/helpers/updateFieldRankByValue.ts +42 -0
  53. package/src/components/EditorPanel/useEditorPermissions.ts +16 -1
  54. package/src/components/ForestPlot/ForestPlot.tsx +2 -3
  55. package/src/components/ForestPlot/ForestPlotProps.ts +2 -0
  56. package/src/components/Legend/Legend.Component.tsx +23 -24
  57. package/src/components/Legend/Legend.Suppression.tsx +25 -20
  58. package/src/components/Legend/Legend.tsx +16 -18
  59. package/src/components/Legend/helpers/index.ts +16 -19
  60. package/src/components/LegendWrapper.tsx +3 -1
  61. package/src/components/LineChart/components/LineChart.Circle.tsx +10 -0
  62. package/src/components/LineChart/helpers.ts +48 -43
  63. package/src/components/LineChart/index.tsx +88 -82
  64. package/src/components/LinearChart.tsx +747 -562
  65. package/src/components/PairedBarChart.jsx +50 -10
  66. package/src/components/PieChart/PieChart.tsx +1 -6
  67. package/src/components/Regions/components/Regions.tsx +33 -19
  68. package/src/components/Sankey/index.tsx +50 -32
  69. package/src/components/Sankey/sankey.scss +6 -5
  70. package/src/components/Sankey/useSankeyAlert.tsx +60 -0
  71. package/src/components/ScatterPlot/ScatterPlot.jsx +20 -4
  72. package/src/components/ZoomBrush.tsx +25 -6
  73. package/src/coreStyles_chart.scss +3 -0
  74. package/src/data/initial-state.js +8 -10
  75. package/src/helpers/configHelpers.ts +28 -0
  76. package/src/helpers/handleRankByValue.ts +15 -0
  77. package/src/helpers/sizeHelpers.ts +25 -0
  78. package/src/helpers/tests/handleRankByValue.test.ts +37 -0
  79. package/src/helpers/tests/sizeHelpers.test.ts +80 -0
  80. package/src/hooks/useColorPalette.js +10 -2
  81. package/src/hooks/useLegendClasses.ts +13 -22
  82. package/src/hooks/useMinMax.ts +27 -13
  83. package/src/hooks/useReduceData.ts +43 -10
  84. package/src/hooks/useScales.ts +87 -38
  85. package/src/hooks/useTooltip.tsx +62 -53
  86. package/src/index.jsx +1 -0
  87. package/src/scss/DataTable.scss +5 -4
  88. package/src/scss/main.scss +57 -70
  89. package/src/types/ChartConfig.ts +43 -34
  90. package/src/types/ChartContext.ts +22 -15
  91. package/src/types/ForestPlot.ts +8 -0
  92. package/src/_stories/Chart.Legend.Gradient.tsx +0 -19
  93. package/src/_stories/ChartBrush.stories.tsx +0 -19
  94. package/src/components/BoxPlot/BoxPlot.jsx +0 -111
  95. package/src/components/LinearChart.jsx +0 -817
@@ -1,7 +1,12 @@
1
1
  import { useContext, FC } from 'react'
2
2
 
3
3
  // external libraries
4
- import { AccordionItem, AccordionItemHeading, AccordionItemPanel, AccordionItemButton } from 'react-accessible-accordion'
4
+ import {
5
+ AccordionItem,
6
+ AccordionItemHeading,
7
+ AccordionItemPanel,
8
+ AccordionItemButton
9
+ } from 'react-accessible-accordion'
5
10
 
6
11
  // core
7
12
  import { TextField, Select, CheckBox } from '@cdc/core/components/EditorPanel/Inputs'
@@ -22,9 +27,21 @@ const PanelVisual: FC<PanelProps> = props => {
22
27
  const { config, updateConfig, colorPalettes, twoColorPalette } = useContext<ChartContext>(ConfigContext)
23
28
  const { visual } = config
24
29
  const { setLollipopShape, updateField } = useEditorPanelContext()
25
- const { visHasBarBorders, visCanAnimate, visSupportsNonSequentialPallete, headerColors, visSupportsTooltipOpacity, visSupportsTooltipLines, visSupportsBarSpace, visSupportsBarThickness, visHasDataCutoff, visSupportsSequentialPallete, visSupportsReverseColorPalette, visHasSingleSeriesTooltip } =
26
- useEditorPermissions()
27
- const { twoColorPalettes, sequential, nonSequential } = useColorPalette(config, updateConfig)
30
+ const {
31
+ visHasBarBorders,
32
+ visCanAnimate,
33
+ visSupportsNonSequentialPallete,
34
+ headerColors,
35
+ visSupportsTooltipOpacity,
36
+ visSupportsTooltipLines,
37
+ visSupportsBarSpace,
38
+ visSupportsBarThickness,
39
+ visHasDataCutoff,
40
+ visSupportsSequentialPallete,
41
+ visSupportsReverseColorPalette,
42
+ visHasSingleSeriesTooltip
43
+ } = useEditorPermissions()
44
+ const { twoColorPalettes, sequential, nonSequential, accessibleColors } = useColorPalette(config, updateConfig)
28
45
 
29
46
  const updateColor = (property, _value) => {
30
47
  console.log('value', _value)
@@ -76,26 +93,98 @@ const PanelVisual: FC<PanelProps> = props => {
76
93
  </label>
77
94
  </div>
78
95
  </fieldset>
79
- <Select value={config.lollipopColorStyle ? config.lollipopColorStyle : 'two-tone'} fieldName='lollipopColorStyle' label='Lollipop Color Style' updateField={updateField} options={['regular', 'two-tone']} />
80
- <Select value={config.lollipopSize ? config.lollipopSize : 'small'} fieldName='lollipopSize' label='Lollipop Size' updateField={updateField} options={['small', 'medium', 'large']} />
96
+ <Select
97
+ value={config.lollipopColorStyle ? config.lollipopColorStyle : 'two-tone'}
98
+ fieldName='lollipopColorStyle'
99
+ label='Lollipop Color Style'
100
+ updateField={updateField}
101
+ options={['regular', 'two-tone']}
102
+ />
103
+ <Select
104
+ value={config.lollipopSize ? config.lollipopSize : 'small'}
105
+ fieldName='lollipopSize'
106
+ label='Lollipop Size'
107
+ updateField={updateField}
108
+ options={['small', 'medium', 'large']}
109
+ />
81
110
  </>
82
111
  )}
83
112
  {config.visualizationType === 'Box Plot' && (
84
113
  <fieldset className='fieldset fieldset--boxplot'>
85
114
  <legend className=''>Box Plot Settings</legend>
86
- <Select value={config.boxplot.borders} fieldName='borders' section='boxplot' label='Box Plot Borders' updateField={updateField} options={['true', 'false']} />
87
- <CheckBox value={config.boxplot.plotOutlierValues} fieldName='plotOutlierValues' section='boxplot' label='Plot Outliers' updateField={updateField} />
88
- <CheckBox value={config.boxplot.plotNonOutlierValues} fieldName='plotNonOutlierValues' section='boxplot' label='Plot non-outlier values' updateField={updateField} />
115
+ <Select
116
+ value={config.boxplot.borders}
117
+ fieldName='borders'
118
+ section='boxplot'
119
+ label='Box Plot Borders'
120
+ updateField={updateField}
121
+ options={['true', 'false']}
122
+ />
123
+ <CheckBox
124
+ value={config.boxplot.plotOutlierValues}
125
+ fieldName='plotOutlierValues'
126
+ section='boxplot'
127
+ label='Plot Outliers'
128
+ updateField={updateField}
129
+ />
130
+ <CheckBox
131
+ value={config.boxplot.plotNonOutlierValues}
132
+ fieldName='plotNonOutlierValues'
133
+ section='boxplot'
134
+ label='Plot non-outlier values'
135
+ updateField={updateField}
136
+ />
89
137
  </fieldset>
90
138
  )}
91
- <Select value={config.fontSize} fieldName='fontSize' label='Font Size' updateField={updateField} options={['small', 'medium', 'large']} />
92
- {visHasBarBorders() && <Select value={config.barHasBorder} fieldName='barHasBorder' label='Bar Borders' updateField={updateField} options={['true', 'false']} />}
93
- {visCanAnimate() && <CheckBox value={config.animate} fieldName='animate' label='Animate Visualization' updateField={updateField} />}
139
+ <Select
140
+ value={config.fontSize}
141
+ fieldName='fontSize'
142
+ label='Font Size'
143
+ updateField={updateField}
144
+ options={['small', 'medium', 'large']}
145
+ />
146
+ {visHasBarBorders() && (
147
+ <Select
148
+ value={config.barHasBorder}
149
+ fieldName='barHasBorder'
150
+ label='Bar Borders'
151
+ updateField={updateField}
152
+ options={['true', 'false']}
153
+ />
154
+ )}
155
+ {visCanAnimate() && (
156
+ <CheckBox
157
+ value={config.animate}
158
+ fieldName='animate'
159
+ label='Animate Visualization'
160
+ updateField={updateField}
161
+ />
162
+ )}
94
163
  {/*<CheckBox value={config.animateReplay} fieldName="animateReplay" label="Replay Animation When Filters Are Changed" updateField={updateField} />*/}
95
- {((config.series?.some(series => series.type === 'Line' || series.type === 'dashed-lg' || series.type === 'dashed-sm' || series.type === 'dashed-md') && config.visualizationType === 'Combo') || config.visualizationType === 'Line') && (
164
+ {((config.series?.some(
165
+ series =>
166
+ series.type === 'Line' ||
167
+ series.type === 'dashed-lg' ||
168
+ series.type === 'dashed-sm' ||
169
+ series.type === 'dashed-md'
170
+ ) &&
171
+ config.visualizationType === 'Combo') ||
172
+ config.visualizationType === 'Line') && (
96
173
  <>
97
- <Select value={config.lineDatapointStyle} fieldName='lineDatapointStyle' label='Line Datapoint Style' updateField={updateField} options={['hidden', 'hover', 'always show']} />
98
- <Select value={config.lineDatapointColor} fieldName='lineDatapointColor' label='Line Datapoint Color' updateField={updateField} options={['Same as Line', 'Lighter than Line']} />
174
+ <Select
175
+ value={config.lineDatapointStyle}
176
+ fieldName='lineDatapointStyle'
177
+ label='Line Datapoint Style'
178
+ updateField={updateField}
179
+ options={['hidden', 'hover', 'always show']}
180
+ />
181
+ <Select
182
+ value={config.lineDatapointColor}
183
+ fieldName='lineDatapointColor'
184
+ label='Line Datapoint Color'
185
+ updateField={updateField}
186
+ options={['Same as Line', 'Lighter than Line']}
187
+ />
99
188
  </>
100
189
  )}
101
190
  {/* eslint-disable */}
@@ -121,7 +210,15 @@ const PanelVisual: FC<PanelProps> = props => {
121
210
  <label>
122
211
  <span className='edit-label'>Chart Color Palette</span>
123
212
  </label>
124
- {visSupportsReverseColorPalette() && <InputToggle fieldName='isPaletteReversed' size='small' label='Use selected palette in reverse order' updateField={updateField} value={config.isPaletteReversed} />}
213
+ {visSupportsReverseColorPalette() && (
214
+ <InputToggle
215
+ fieldName='isPaletteReversed'
216
+ size='small'
217
+ label='Use selected palette in reverse order'
218
+ updateField={updateField}
219
+ value={config.isPaletteReversed}
220
+ />
221
+ )}
125
222
  {visSupportsSequentialPallete() && (
126
223
  <>
127
224
  <span>Sequential</span>
@@ -175,6 +272,38 @@ const PanelVisual: FC<PanelProps> = props => {
175
272
  backgroundColor: colorPalettes[palette][6]
176
273
  }
177
274
 
275
+ return (
276
+ <button
277
+ title={palette}
278
+ key={palette}
279
+ onClick={e => {
280
+ e.preventDefault()
281
+ updateConfig({ ...config, palette })
282
+ }}
283
+ className={config.palette === palette ? 'selected' : ''}
284
+ >
285
+ <span style={colorOne}></span>
286
+ <span style={colorTwo}></span>
287
+ <span style={colorThree}></span>
288
+ </button>
289
+ )
290
+ })}
291
+ </ul>
292
+ <span>Colorblind Safe</span>
293
+ <ul className='color-palette'>
294
+ {accessibleColors.map(palette => {
295
+ const colorOne = {
296
+ backgroundColor: colorPalettes[palette][2]
297
+ }
298
+
299
+ const colorTwo = {
300
+ backgroundColor: colorPalettes[palette][3]
301
+ }
302
+
303
+ const colorThree = {
304
+ backgroundColor: colorPalettes[palette][5]
305
+ }
306
+
178
307
  return (
179
308
  <button
180
309
  title={palette}
@@ -199,22 +328,47 @@ const PanelVisual: FC<PanelProps> = props => {
199
328
  {config.visualizationType === 'Sankey' && (
200
329
  <>
201
330
  <span className='sankey__color-input'>
202
- <input type='color' value={config.sankey.nodeColor.default} id='storyNodeColor' name='storyNodeColor' onChange={e => updateColor('nodeColor', e.target.value)} />
331
+ <input
332
+ type='color'
333
+ value={config.sankey.nodeColor.default}
334
+ id='storyNodeColor'
335
+ name='storyNodeColor'
336
+ onChange={e => updateColor('nodeColor', e.target.value)}
337
+ />
203
338
  <label htmlFor='storyNodeColor'>Story Node Color</label>
204
339
  </span>
205
340
  <span className='sankey__color-input'>
206
- <input type='color' value={config.sankey.storyNodeFontColor || 'red'} id='storyNodeFontColor' name='storyNodeFontColor' onChange={e => updateColor('storyNodeFontColor', e.target.value)} />
341
+ <input
342
+ type='color'
343
+ value={config.sankey.storyNodeFontColor || 'red'}
344
+ id='storyNodeFontColor'
345
+ name='storyNodeFontColor'
346
+ onChange={e => updateColor('storyNodeFontColor', e.target.value)}
347
+ />
207
348
  <label htmlFor='storyNodeFontColor'>Story Node Font Color</label>
208
349
  </span>
209
350
  <span className='sankey__color-input'>
210
- <input type='color' value={config.sankey.linkColor.default} id='linkColor' name='linkColor' onChange={e => updateColor('linkColor', e.target.value)} />
351
+ <input
352
+ type='color'
353
+ value={config.sankey.linkColor.default}
354
+ id='linkColor'
355
+ name='linkColor'
356
+ onChange={e => updateColor('linkColor', e.target.value)}
357
+ />
211
358
  <label htmlFor='linkColor'>Link Color</label>
212
359
  </span>
213
360
  </>
214
361
  )}
215
362
  {(config.visualizationType === 'Paired Bar' || config.visualizationType === 'Deviation Bar') && (
216
363
  <>
217
- <InputToggle section='twoColor' fieldName='isPaletteReversed' size='small' label='Use selected palette in reverse order' updateField={updateField} value={config.twoColor.isPaletteReversed} />
364
+ <InputToggle
365
+ section='twoColor'
366
+ fieldName='isPaletteReversed'
367
+ size='small'
368
+ label='Use selected palette in reverse order'
369
+ updateField={updateField}
370
+ value={config.twoColor.isPaletteReversed}
371
+ />
218
372
  <ul className='color-palette'>
219
373
  {twoColorPalettes.map(palette => {
220
374
  const colorOne = {
@@ -258,32 +412,131 @@ const PanelVisual: FC<PanelProps> = props => {
258
412
  <Icon display='question' style={{ marginLeft: '0.5rem' }} />
259
413
  </Tooltip.Target>
260
414
  <Tooltip.Content>
261
- <p>Any value below the cut-off value is included in a special "less than" category. This option supports special conditions like suppressed data.</p>
415
+ <p>
416
+ Any value below the cut-off value is included in a special "less than" category. This option
417
+ supports special conditions like suppressed data.
418
+ </p>
262
419
  </Tooltip.Content>
263
420
  </Tooltip>
264
421
  }
265
422
  />
266
423
  </>
267
424
  )}
268
- {visSupportsBarThickness() && config.orientation === 'horizontal' && !config.isLollipopChart && config.yAxis.labelPlacement !== 'On Bar' && <TextField type='number' value={config.barHeight || '25'} fieldName='barHeight' label=' Bar Thickness' updateField={updateField} min={15} />}
269
- {((config.visualizationType === 'Bar' && config.orientation !== 'horizontal') || config.visualizationType === 'Combo') && <TextField value={config.barThickness} type='number' fieldName='barThickness' label='Bar Thickness' updateField={updateField} />}
270
- {visSupportsBarSpace() && <TextField type='number' value={config.barSpace || '15'} fieldName='barSpace' label='Bar Space' updateField={updateField} min={0} />}
271
- {(config.visualizationType === 'Bar' || config.visualizationType === 'Line' || config.visualizationType === 'Combo') && <CheckBox value={config.topAxis.hasLine} section='topAxis' fieldName='hasLine' label='Add Top Axis Line' updateField={updateField} />}
425
+ {visSupportsBarThickness() &&
426
+ config.orientation === 'horizontal' &&
427
+ !config.isLollipopChart &&
428
+ config.yAxis.labelPlacement !== 'On Bar' && (
429
+ <TextField
430
+ type='number'
431
+ value={config.barHeight || '25'}
432
+ fieldName='barHeight'
433
+ label=' Bar Thickness'
434
+ updateField={updateField}
435
+ min={15}
436
+ />
437
+ )}
438
+ {(config.orientation !== 'horizontal' || config.visualizationType === 'Combo') && (
439
+ <TextField
440
+ value={config.barThickness}
441
+ type='number'
442
+ fieldName='barThickness'
443
+ label='Bar Thickness'
444
+ updateField={updateField}
445
+ />
446
+ )}
447
+ {visSupportsBarSpace() && (
448
+ <TextField
449
+ type='number'
450
+ value={config.barSpace || '15'}
451
+ fieldName='barSpace'
452
+ label='Bar Space'
453
+ updateField={updateField}
454
+ min={0}
455
+ />
456
+ )}
457
+ {(config.visualizationType === 'Bar' ||
458
+ config.visualizationType === 'Line' ||
459
+ config.visualizationType === 'Combo') && (
460
+ <CheckBox
461
+ value={config.topAxis.hasLine}
462
+ section='topAxis'
463
+ fieldName='hasLine'
464
+ label='Add Top Axis Line'
465
+ updateField={updateField}
466
+ />
467
+ )}
272
468
  {config.visualizationType === 'Spark Line' && (
273
469
  <div className='cove-accordion__panel-section checkbox-group'>
274
- <CheckBox value={visual?.border} section='visual' fieldName='border' label='Show Border' updateField={updateField} />
275
- <CheckBox value={visual?.borderColorTheme} section='visual' fieldName='borderColorTheme' label='Use Border Color Theme' updateField={updateField} />
276
- <CheckBox value={visual?.accent} section='visual' fieldName='accent' label='Use Accent Style' updateField={updateField} />
277
- <CheckBox value={visual?.background} section='visual' fieldName='background' label='Use Theme Background Color' updateField={updateField} />
278
- <CheckBox value={visual?.hideBackgroundColor} section='visual' fieldName='hideBackgroundColor' label='Hide Background Color' updateField={updateField} />
470
+ <CheckBox
471
+ value={visual?.border}
472
+ section='visual'
473
+ fieldName='border'
474
+ label='Show Border'
475
+ updateField={updateField}
476
+ />
477
+ <CheckBox
478
+ value={visual?.borderColorTheme}
479
+ section='visual'
480
+ fieldName='borderColorTheme'
481
+ label='Use Border Color Theme'
482
+ updateField={updateField}
483
+ />
484
+ <CheckBox
485
+ value={visual?.accent}
486
+ section='visual'
487
+ fieldName='accent'
488
+ label='Use Accent Style'
489
+ updateField={updateField}
490
+ />
491
+ <CheckBox
492
+ value={visual?.background}
493
+ section='visual'
494
+ fieldName='background'
495
+ label='Use Theme Background Color'
496
+ updateField={updateField}
497
+ />
498
+ <CheckBox
499
+ value={visual?.hideBackgroundColor}
500
+ section='visual'
501
+ fieldName='hideBackgroundColor'
502
+ label='Hide Background Color'
503
+ updateField={updateField}
504
+ />
279
505
  </div>
280
506
  )}
281
- {(config.visualizationType === 'Line' || config.visualizationType === 'Combo') && <CheckBox value={config.showLineSeriesLabels} fieldName='showLineSeriesLabels' label='Append Series Name to End of Line Charts' updateField={updateField} />}
282
- {(config.visualizationType === 'Line' || config.visualizationType === 'Combo') && config.showLineSeriesLabels && <CheckBox value={config.colorMatchLineSeriesLabels} fieldName='colorMatchLineSeriesLabels' label='Match Series Color to Name at End of Line Charts' updateField={updateField} />}
507
+ {(config.visualizationType === 'Line' || config.visualizationType === 'Combo') && (
508
+ <CheckBox
509
+ value={config.showLineSeriesLabels}
510
+ fieldName='showLineSeriesLabels'
511
+ label='Append Series Name to End of Line Charts'
512
+ updateField={updateField}
513
+ />
514
+ )}
515
+ {(config.visualizationType === 'Line' || config.visualizationType === 'Combo') &&
516
+ config.showLineSeriesLabels && (
517
+ <CheckBox
518
+ value={config.colorMatchLineSeriesLabels}
519
+ fieldName='colorMatchLineSeriesLabels'
520
+ label='Match Series Color to Name at End of Line Charts'
521
+ updateField={updateField}
522
+ />
523
+ )}
283
524
  {visSupportsTooltipLines() && (
284
525
  <>
285
- <CheckBox value={visual.verticalHoverLine} fieldName='verticalHoverLine' section='visual' label='Vertical Hover Line' updateField={updateField} />
286
- <CheckBox value={visual.horizontalHoverLine} fieldName='horizontalHoverLine' section='visual' label='Horizontal Hover Line' updateField={updateField} />
526
+ <CheckBox
527
+ value={visual.verticalHoverLine}
528
+ fieldName='verticalHoverLine'
529
+ section='visual'
530
+ label='Vertical Hover Line'
531
+ updateField={updateField}
532
+ />
533
+ <CheckBox
534
+ value={visual.horizontalHoverLine}
535
+ fieldName='horizontalHoverLine'
536
+ section='visual'
537
+ label='Horizontal Hover Line'
538
+ updateField={updateField}
539
+ />
287
540
  </>
288
541
  )}
289
542
  {visSupportsTooltipOpacity() && (
@@ -304,7 +557,15 @@ const PanelVisual: FC<PanelProps> = props => {
304
557
  />
305
558
  </label>
306
559
  )}
307
- {visHasSingleSeriesTooltip() && <CheckBox value={config.tooltips.singleSeries} fieldName='singleSeries' section='tooltips' label='SHOW HOVER FOR SINGLE DATA SERIES' updateField={updateField} />}
560
+ {visHasSingleSeriesTooltip() && (
561
+ <CheckBox
562
+ value={config.tooltips.singleSeries}
563
+ fieldName='singleSeries'
564
+ section='tooltips'
565
+ label='SHOW HOVER FOR SINGLE DATA SERIES'
566
+ updateField={updateField}
567
+ />
568
+ )}
308
569
  <label>
309
570
  <span className='edit-label column-heading'>No Data Message</span>
310
571
  <input
@@ -1,9 +1,7 @@
1
- @import '@cdc/core/styles/v2/themes/color-definitions';
2
-
3
1
  .date-highlight {
4
2
  select,
5
3
  input {
6
- background: $lightestGray;
4
+ background: var(--lightestGray);
7
5
  }
8
6
 
9
7
  &__day-selection {
@@ -15,17 +13,17 @@
15
13
  .week-button {
16
14
  margin-bottom: 0;
17
15
  border-radius: 50%;
18
- color: $darkGray;
16
+ color: var(--darkGray);
19
17
  width: 24px;
20
18
  height: 24px;
21
19
  display: flex;
22
20
  align-items: center;
23
21
  justify-content: center;
24
- background: $lightestGray;
22
+ background: var(--lightestGray);
25
23
  margin: 5px 2px 0;
26
24
 
27
25
  &--active {
28
- background: $primary;
26
+ background: var(--primary);
29
27
  color: white;
30
28
  }
31
29
  }
@@ -1,11 +1,3 @@
1
- @import '@cdc/core/styles/base';
2
- @import '@cdc/core/styles/v2/themes/color-definitions';
3
-
4
- //TODO: Remove after COVE refactor
5
- .cove {
6
- @import '@cdc/core/styles/v2/layout/tooltip.scss';
7
- }
8
-
9
1
  .cdc-open-viz-module.type-chart {
10
2
  .viewport-overrides {
11
3
  button {
@@ -0,0 +1,38 @@
1
+ import { updateFieldRankByValue } from '../updateFieldRankByValue'
2
+
3
+ describe('updateFieldRankByValue', () => {
4
+ it('should update rankByValue to "asc" and return new config', () => {
5
+ const config = { rankByValue: undefined }
6
+ const newValue = 'asc'
7
+ const preTransformedData = [{ value: 3 }, { value: 1 }, { value: 2 }]
8
+
9
+ const [newConfig] = updateFieldRankByValue(config, newValue, preTransformedData)
10
+
11
+ expect(newConfig.rankByValue).toBe('asc')
12
+ })
13
+
14
+ it('should return new config and sorted data when newValue is undefined and config.rankByValue is set', () => {
15
+ const config = {
16
+ rankByValue: 'asc',
17
+ data: [{ value: 1 }, { value: 2 }, { value: 3 }],
18
+ xAxis: { dataKey: 'value' }
19
+ }
20
+ const newValue = undefined
21
+ const preTransformedData = [{ value: 3 }, { value: 1 }, { value: 2 }]
22
+
23
+ const [newConfig, newData] = updateFieldRankByValue(config, newValue, preTransformedData)
24
+
25
+ expect(newConfig.rankByValue).toBeUndefined()
26
+ expect(newData).toEqual([{ value: 1 }, { value: 2 }, { value: 3 }])
27
+ })
28
+
29
+ it('should return new config when newValue is undefined and config.rankByValue is not set', () => {
30
+ const config = { rankByValue: undefined }
31
+ const newValue = undefined
32
+ const preTransformedData = [{ value: 3 }, { value: 1 }, { value: 2 }]
33
+
34
+ const [newConfig] = updateFieldRankByValue(config, newValue, preTransformedData)
35
+
36
+ expect(newConfig.rankByValue).toBeUndefined()
37
+ })
38
+ })
@@ -0,0 +1,42 @@
1
+ import DataTransform from '@cdc/core/helpers/DataTransform'
2
+ import { ChartConfig } from '../../../types/ChartConfig'
3
+ import _ from 'lodash'
4
+
5
+ const transform = new DataTransform()
6
+
7
+ const indexOfObj = (data, obj) => {
8
+ for (let i = 0; i < data.length; i++) {
9
+ let keys = Object.keys(data[i])
10
+ let equal = true
11
+ for (let j = 0; j < keys.length; j++) {
12
+ if (data[i][keys[j]] !== obj[keys[j]]) {
13
+ equal = false
14
+ break
15
+ }
16
+ }
17
+ if (equal) {
18
+ return i
19
+ }
20
+ }
21
+ return -1
22
+ }
23
+
24
+ export const updateFieldRankByValue = (
25
+ config: ChartConfig,
26
+ newValue: 'asc' | 'desc' | undefined,
27
+ preTransformedData: Object[]
28
+ ): [ChartConfig, Object[]?] => {
29
+ const newConfig = _.cloneDeep(config)
30
+ newConfig.rankByValue = newValue
31
+
32
+ if (config.rankByValue && !newValue) {
33
+ const cleanData = config?.xAxis?.dataKey ? transform.cleanData(config.data, config.xAxis.dataKey) : config.data
34
+ const newData = preTransformedData.sort((a, b) => {
35
+ const aIndex = indexOfObj(cleanData, a)
36
+ const bIndex = indexOfObj(cleanData, b)
37
+ return aIndex - bIndex
38
+ })
39
+ return [newConfig, newData]
40
+ }
41
+ return [newConfig]
42
+ }
@@ -44,6 +44,18 @@ export const useEditorPermissions = () => {
44
44
  return true
45
45
  }
46
46
 
47
+ const visSupportsDateCategoryAxisMin = () => {
48
+ const enabledCharts = ['Scatter Plot']
49
+ if (enabledCharts.includes(visualizationType)) return true
50
+ return false
51
+ }
52
+
53
+ const visSupportsDateCategoryAxisMax = () => {
54
+ const enabledCharts = ['Scatter Plot']
55
+ if (enabledCharts.includes(visualizationType)) return true
56
+ return false
57
+ }
58
+
47
59
  const visSupportsSuperTitle = () => {
48
60
  const disabledCharts = ['Spark Line']
49
61
  if (disabledCharts.includes(visualizationType)) return false
@@ -88,7 +100,7 @@ export const useEditorPermissions = () => {
88
100
  const visHasLegend = () => {
89
101
  switch (visualizationType) {
90
102
  case 'Box Plot':
91
- return false
103
+ return true
92
104
  case 'Forest Plot':
93
105
  return false
94
106
  case 'Spark Line':
@@ -337,6 +349,7 @@ export const useEditorPermissions = () => {
337
349
  const visSupportsDateCategoryHeight = () => {
338
350
  const disabledCharts = ['Spark Line', 'Sankey', 'Bump Chart']
339
351
  if (disabledCharts.includes(visualizationType)) return false
352
+ if (config.orientation !== 'horizontal') return false
340
353
  return true
341
354
  }
342
355
 
@@ -413,6 +426,8 @@ export const useEditorPermissions = () => {
413
426
  visSupportsChartHeight,
414
427
  visSupportsMobileChartHeight,
415
428
  visSupportsDateCategoryAxis,
429
+ visSupportsDateCategoryAxisMin,
430
+ visSupportsDateCategoryAxisMax,
416
431
  visSupportsDateCategoryAxisLabel,
417
432
  visSupportsDateCategoryAxisLine,
418
433
  visSupportsDateCategoryAxisTicks,
@@ -16,9 +16,8 @@ import { type ChartContext } from '@cdc/chart/src/types/ChartContext'
16
16
  import ConfigContext from '../../ConfigContext'
17
17
  import { getFontSize } from '@cdc/core/helpers/cove/number'
18
18
 
19
- const ForestPlot = (props: ForestPlotProps) => {
19
+ const ForestPlot = ({ xScale, yScale, config, height, width, handleTooltipMouseOff, handleTooltipMouseOver, forestPlotRightLabelRef }: ForestPlotProps) => {
20
20
  const { rawData: data, updateConfig } = useContext<ChartContext>(ConfigContext)
21
- const { xScale, yScale, config, height, width, handleTooltipMouseOff, handleTooltipMouseOver } = props
22
21
  const { forestPlot } = config as ChartConfig
23
22
  const labelPosition = config.xAxis.tickWidthMax + 10
24
23
  const [initialLogTicksSet, setInitialLogTicks] = useState(false)
@@ -243,7 +242,7 @@ const ForestPlot = (props: ForestPlotProps) => {
243
242
  )}
244
243
 
245
244
  {forestPlot.rightLabel && (
246
- <Text className='forest-plot__right-label' x={forestPlot.type === 'Linear' ? xScale(0) + 25 : xScale(1) + 25} y={height + labelPosition} textAnchor='start' verticalAnchor='start'>
245
+ <Text innerRef={forestPlotRightLabelRef} className='forest-plot__right-label' x={forestPlot.type === 'Linear' ? xScale(0) + 25 : xScale(1) + 25} y={height + labelPosition} textAnchor='start' verticalAnchor='start'>
247
246
  {forestPlot.rightLabel}
248
247
  </Text>
249
248
  )}
@@ -8,6 +8,8 @@ export type ForestPlotProps = {
8
8
  /** config - standard chart config */
9
9
  config: ChartConfig
10
10
  /** height - height of chart */
11
+ /** forestPlotLeftLabelRef - ref for left label for resizing svg*/
12
+ forestPlotRightLabelRef: React.RefObject<SVGSVGElement>
11
13
  height: number
12
14
  /** width - width of chart */
13
15
  width: number