@cdc/chart 4.26.2 → 4.26.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.
Files changed (165) hide show
  1. package/CONFIG.md +169 -0
  2. package/README.md +42 -17
  3. package/dist/cdcchart.js +39419 -35180
  4. package/examples/__data__/data-with-metadata.json +10 -0
  5. package/examples/feature/bar/additional-column-tooltip.json +3 -3
  6. package/examples/feature/deviation/planet-deviation-config.json +2 -2
  7. package/examples/feature/paired-bar/paired-bar-example.json +2 -2
  8. package/examples/feature/pie/planet-pie-example-config.json +2 -1
  9. package/examples/feature/tests-case-rate/case-rate-example-config.json +2 -2
  10. package/examples/feature/tests-covid/covid-confidence-example-config.json +2 -2
  11. package/examples/feature/tests-covid/covid-example-config.json +2 -2
  12. package/examples/feature/tests-cutoff/cutoff-example-config.json +2 -2
  13. package/examples/feature/tests-non-numerics/planet-pie-example-config-nonnumeric.json +2 -2
  14. package/examples/metadata-variables.json +58 -0
  15. package/examples/minimal-example.json +24 -0
  16. package/examples/private/test2.json +35012 -0
  17. package/package.json +4 -4
  18. package/src/CdcChart.tsx +8 -4
  19. package/src/CdcChartComponent.tsx +326 -290
  20. package/src/_stories/Chart.CustomColors.smoke.stories.tsx +97 -0
  21. package/src/_stories/Chart.Defaults.smoke.stories.tsx +95 -0
  22. package/src/_stories/{Chart.HTMLInDataTable.stories.tsx → Chart.HTMLInDataTable.smoke.stories.tsx} +10 -0
  23. package/src/_stories/Chart.Minimal.smoke.stories.tsx +25 -0
  24. package/src/_stories/{Chart.SmallMultiples.stories.tsx → Chart.SmallMultiples.smoke.stories.tsx} +17 -1
  25. package/src/_stories/Chart.SmallestLeftAxisMax.smoke.stories.tsx +64 -0
  26. package/src/_stories/{Chart.stories.tsx → Chart.smoke.stories.tsx} +48 -2
  27. package/src/_stories/{Chart.tooltip.stories.tsx → Chart.tooltip.smoke.stories.tsx} +68 -0
  28. package/src/_stories/ChartBar.Editor.stories.tsx +177 -115
  29. package/src/_stories/ChartBrush.Editor.stories.tsx +11 -25
  30. package/src/_stories/ChartEditor.Editor.stories.tsx +24 -1
  31. package/src/_stories/{Chart.CustomColors.stories.tsx → ChartLine.DashedDates.smoke.stories.tsx} +4 -4
  32. package/src/_stories/_mock/line_chart_dashed_dates.json +276 -0
  33. package/src/_stories/_mock/paired-bar-abbr.json +421 -0
  34. package/src/_stories/_mock/paired-bar.json +1 -1
  35. package/src/_stories/_mock/pie_custom_colors.json +268 -0
  36. package/src/_stories/_mock/smallest_left_axis_max.json +104 -0
  37. package/src/components/Annotations/components/AnnotationDraggable.styles.css +10 -10
  38. package/src/components/Annotations/components/AnnotationDraggable.tsx +1 -1
  39. package/src/components/Annotations/components/AnnotationDropdown.styles.css +1 -1
  40. package/src/components/Annotations/components/AnnotationList.styles.css +11 -11
  41. package/src/components/AreaChart/components/AreaChart.Stacked.jsx +10 -2
  42. package/src/components/Axis/BottomAxis.tsx +10 -3
  43. package/src/components/Axis/LeftAxis.tsx +2 -4
  44. package/src/components/Axis/LeftAxisGridlines.tsx +1 -3
  45. package/src/components/Axis/PairedBarAxis.tsx +10 -4
  46. package/src/components/BarChart/components/BarChart.Horizontal.tsx +21 -33
  47. package/src/components/BarChart/components/BarChart.StackedHorizontal.tsx +21 -35
  48. package/src/components/BarChart/components/BarChart.StackedVertical.tsx +21 -36
  49. package/src/components/BarChart/components/BarChart.Vertical.tsx +21 -34
  50. package/src/components/BarChart/components/BarChart.tsx +2 -6
  51. package/src/components/BarChart/helpers/getPatternUrl.ts +94 -0
  52. package/src/components/BarChart/helpers/tests/getPatternUrl.test.ts +134 -0
  53. package/src/components/BarChart/helpers/useBarChart.ts +4 -1
  54. package/src/components/BoxPlot/BoxPlot.Vertical.tsx +3 -3
  55. package/src/components/Brush/BrushSelector.tsx +2 -1
  56. package/src/components/Brush/MiniChartPreview.tsx +21 -26
  57. package/src/components/EditorPanel/EditorPanel.tsx +692 -954
  58. package/src/components/EditorPanel/EditorPanelContext.ts +1 -1
  59. package/src/components/EditorPanel/components/Panels/Panel.Annotate.tsx +218 -167
  60. package/src/components/EditorPanel/components/Panels/Panel.ForestPlotSettings.tsx +0 -78
  61. package/src/components/EditorPanel/components/Panels/Panel.General.tsx +39 -1
  62. package/src/components/EditorPanel/components/Panels/Panel.PatternSettings.tsx +169 -135
  63. package/src/components/EditorPanel/components/Panels/Panel.Regions.tsx +154 -109
  64. package/src/components/EditorPanel/components/Panels/Panel.Sankey.tsx +3 -3
  65. package/src/components/EditorPanel/components/Panels/Panel.Series.tsx +95 -28
  66. package/src/components/EditorPanel/components/Panels/Panel.Visual.tsx +45 -42
  67. package/src/components/EditorPanel/editor-panel.scss +1 -1
  68. package/src/components/EditorPanel/useEditorPermissions.ts +1 -10
  69. package/src/components/Forecasting/Forecasting.tsx +2 -2
  70. package/src/components/ForestPlot/ForestPlot.tsx +26 -22
  71. package/src/components/HorizonChart/HorizonChart.tsx +10 -2
  72. package/src/components/HoverLine/HoverLine.tsx +6 -8
  73. package/src/components/Legend/Legend.Component.tsx +4 -4
  74. package/src/components/Legend/LegendGroup/LegendGroup.styles.css +9 -4
  75. package/src/components/Legend/LegendGroup/LegendGroup.tsx +3 -1
  76. package/src/components/Legend/helpers/createFormatLabels.tsx +3 -2
  77. package/src/components/Legend/helpers/index.ts +0 -2
  78. package/src/components/LineChart/LineChartProps.ts +1 -0
  79. package/src/components/LineChart/components/LineChart.BumpCircle.tsx +3 -2
  80. package/src/components/LineChart/index.tsx +11 -4
  81. package/src/components/LinearChart/VisualizationRenderer.tsx +11 -1
  82. package/src/components/LinearChart/tests/LinearChart.test.tsx +224 -0
  83. package/src/components/LinearChart/tests/mockConfigContext.ts +2 -0
  84. package/src/components/LinearChart.tsx +124 -47
  85. package/src/components/PairedBarChart.jsx +2 -2
  86. package/src/components/PieChart/PieChart.tsx +30 -13
  87. package/src/components/RadarChart/RadarChart.tsx +1 -1
  88. package/src/components/Regions/components/Regions.tsx +36 -26
  89. package/src/components/Sankey/components/Sankey.tsx +3 -3
  90. package/src/components/Sankey/sankey.scss +1 -1
  91. package/src/components/ScatterPlot/ScatterPlot.jsx +19 -17
  92. package/src/components/SmallMultiples/SmallMultipleTile.tsx +1 -0
  93. package/src/components/SmallMultiples/SmallMultiples.css +5 -5
  94. package/src/components/Sparkline/components/SparkLine.tsx +1 -1
  95. package/src/components/Sparkline/index.scss +4 -2
  96. package/src/components/WarmingStripes/WarmingStripes.tsx +5 -3
  97. package/src/components/WarmingStripes/WarmingStripesGradientLegend.css +8 -8
  98. package/src/data/initial-state.js +24 -14
  99. package/src/data/legacy-defaults.ts +18 -0
  100. package/src/helpers/abbreviateNumber.ts +24 -17
  101. package/src/helpers/calculateLeftYAxisWidth.ts +193 -0
  102. package/src/helpers/getChartPatternId.ts +17 -0
  103. package/src/helpers/getMinMax.ts +16 -2
  104. package/src/helpers/seriesColumnSettings.ts +114 -0
  105. package/src/helpers/tests/countNumOfTicks.test.ts +77 -0
  106. package/src/helpers/tests/seriesColumnSettings.test.ts +84 -0
  107. package/src/helpers/tests/tooltipHelpers.test.ts +151 -0
  108. package/src/helpers/tooltipHelpers.ts +176 -0
  109. package/src/hooks/useHighlightedBars.ts +9 -16
  110. package/src/hooks/useProgrammaticTooltip.ts +16 -2
  111. package/src/hooks/useRightAxis.ts +14 -0
  112. package/src/hooks/useScales.ts +92 -56
  113. package/src/hooks/useSmallMultipleSynchronization.ts +3 -4
  114. package/src/hooks/useTooltip.tsx +186 -40
  115. package/src/scss/main.scss +152 -79
  116. package/src/test/CdcChart.test.jsx +26 -2
  117. package/src/types/ChartConfig.ts +5 -0
  118. package/tests/fixtures/chart-config-with-metadata.json +29 -0
  119. package/tests/fixtures/data-with-metadata.json +10 -0
  120. package/examples/chart-regression-2.json +0 -2360
  121. package/examples/feature/__data__/age-adjusted-rates.json +0 -1486
  122. package/examples/feature/__data__/city-temperature.json +0 -2198
  123. package/examples/feature/bar/Barchart_with_negative.json +0 -34
  124. package/examples/feature/boxplot/box-plot-data.json +0 -71
  125. package/examples/feature/boxplot/boxplot-data.json +0 -156
  126. package/examples/feature/combo/combochart-categories_are_numbers .json +0 -18
  127. package/examples/feature/forest-plot/log.json +0 -26
  128. package/examples/feature/tests-date-exclusions/date-exclusions-data.json +0 -162
  129. package/examples/region-issue.json +0 -2065
  130. package/examples/xaxis.json +0 -493
  131. /package/examples/feature/bar/{tall-data.json → __data__/tall-data.json} +0 -0
  132. /package/examples/feature/deviation/{planet-deviation-data.json → __data__/planet-deviation-data.json} +0 -0
  133. /package/examples/feature/paired-bar/{paired-bar-data.json → __data__/paired-bar-data.json} +0 -0
  134. /package/examples/feature/paired-bar/{paired-bar-formatted.json → __data__/paired-bar-formatted.json} +0 -0
  135. /package/examples/feature/tests-case-rate/{case-rate-example-data.json → __data__/case-rate-example-data.json} +0 -0
  136. /package/examples/feature/tests-covid/{covid-example-data-confidence.json → __data__/covid-example-data-confidence.json} +0 -0
  137. /package/examples/feature/tests-covid/{covid-example-data.json → __data__/covid-example-data.json} +0 -0
  138. /package/examples/feature/tests-cutoff/{cutoff-example-data.json → __data__/cutoff-example-data.json} +0 -0
  139. /package/examples/feature/tests-non-numerics/{planet-example-data-nonnumeric.json → __data__/planet-example-data-nonnumeric.json} +0 -0
  140. /package/src/_stories/{Chart.Anchors.stories.tsx → Chart.Anchors.smoke.stories.tsx} +0 -0
  141. /package/src/_stories/{Chart.BoxPlot.stories.tsx → Chart.BoxPlot.smoke.stories.tsx} +0 -0
  142. /package/src/_stories/{Chart.CI.stories.tsx → Chart.CI.smoke.stories.tsx} +0 -0
  143. /package/src/_stories/{Chart.Combo.stories.tsx → Chart.Combo.smoke.stories.tsx} +0 -0
  144. /package/src/_stories/{Chart.DynamicSeries.stories.tsx → Chart.DynamicSeries.smoke.stories.tsx} +0 -0
  145. /package/src/_stories/{Chart.Filters.stories.tsx → Chart.Filters.smoke.stories.tsx} +0 -0
  146. /package/src/_stories/{Chart.Forecast.stories.tsx → Chart.Forecast.smoke.stories.tsx} +0 -0
  147. /package/src/_stories/{Chart.Legend.Gradient.stories.tsx → Chart.Legend.Gradient.smoke.stories.tsx} +0 -0
  148. /package/src/_stories/{Chart.Patterns.stories.tsx → Chart.Patterns.smoke.stories.tsx} +0 -0
  149. /package/src/_stories/{Chart.PreserveDecimals.stories.tsx → Chart.PreserveDecimals.smoke.stories.tsx} +0 -0
  150. /package/src/_stories/{Chart.Regions.Categorical.stories.tsx → Chart.Regions.Categorical.smoke.stories.tsx} +0 -0
  151. /package/src/_stories/{Chart.Regions.DateScale.stories.tsx → Chart.Regions.DateScale.smoke.stories.tsx} +0 -0
  152. /package/src/_stories/{Chart.Regions.DateTimeScale.stories.tsx → Chart.Regions.DateTimeScale.smoke.stories.tsx} +0 -0
  153. /package/src/_stories/{Chart.ScatterPlot.stories.tsx → Chart.ScatterPlot.smoke.stories.tsx} +0 -0
  154. /package/src/_stories/{ChartAnnotation.stories.tsx → ChartAnnotation.smoke.stories.tsx} +0 -0
  155. /package/src/_stories/{ChartAxisLabels.stories.tsx → ChartAxisLabels.smoke.stories.tsx} +0 -0
  156. /package/src/_stories/{ChartAxisTitles.stories.tsx → ChartAxisTitles.smoke.stories.tsx} +0 -0
  157. /package/src/_stories/{ChartBrush.Matrix.Continuous.stories.tsx → ChartBrush.Matrix.Continuous.smoke.stories.tsx} +0 -0
  158. /package/src/_stories/{ChartBrush.Matrix.Date.stories.tsx → ChartBrush.Matrix.Date.smoke.stories.tsx} +0 -0
  159. /package/src/_stories/{ChartBrush.Matrix.DateTime.stories.tsx → ChartBrush.Matrix.DateTime.smoke.stories.tsx} +0 -0
  160. /package/src/_stories/{ChartBrush.stories.tsx → ChartBrush.smoke.stories.tsx} +0 -0
  161. /package/src/_stories/{ChartLine.QuadrantAngles.stories.tsx → ChartLine.QuadrantAngles.smoke.stories.tsx} +0 -0
  162. /package/src/_stories/{ChartLine.Suppression.stories.tsx → ChartLine.Suppression.smoke.stories.tsx} +0 -0
  163. /package/src/_stories/{ChartLine.Symbols.stories.tsx → ChartLine.Symbols.smoke.stories.tsx} +0 -0
  164. /package/src/_stories/{ChartPrefixSuffix.stories.tsx → ChartPrefixSuffix.smoke.stories.tsx} +0 -0
  165. /package/src/_stories/{TechAdoptionWithLinks.stories.tsx → TechAdoptionWithLinks.smoke.stories.tsx} +0 -0
@@ -1,15 +1,19 @@
1
1
  import { memo, useContext } from 'react'
2
+ import { Draggable } from '@hello-pangea/dnd'
2
3
  import { useEditorPermissions } from '../../useEditorPermissions.js'
3
4
  import {
5
+ Accordion,
4
6
  AccordionItem,
5
7
  AccordionItemHeading,
6
8
  AccordionItemPanel,
7
9
  AccordionItemButton
8
10
  } from 'react-accessible-accordion'
9
11
  import { type ChartConfig } from '../../../../types/ChartConfig.js'
12
+ import GroupedList from '@cdc/core/components/EditorPanel/GroupedList'
10
13
  import { TextField, Select } from '@cdc/core/components/EditorPanel/Inputs'
11
14
  import Tooltip from '@cdc/core/components/ui/Tooltip'
12
15
  import Icon from '@cdc/core/components/ui/Icon'
16
+ import Button from '@cdc/core/components/elements/Button'
13
17
  import { type ChartContext } from '../../../../types/ChartContext.js'
14
18
  import { type PanelProps } from '../PanelProps.js'
15
19
  import ConfigContext from '../../../../ConfigContext.js'
@@ -53,129 +57,170 @@ const RegionSettings = memo(({ config, updateConfig }: { config: ChartConfig; up
53
57
  updateConfig({ ...config, regions })
54
58
  }
55
59
 
60
+ const moveRegion = (sourceIndex, destinationIndex) => {
61
+ const regions = config.regions ? [...config.regions] : []
62
+ const [movedRegion] = regions.splice(sourceIndex, 1)
63
+ regions.splice(destinationIndex, 0, movedRegion)
64
+ updateConfig({ ...config, regions })
65
+ }
66
+
56
67
  const fromOptions = ['Fixed', 'Previous Days']
57
68
  const toOptions = ['Last Date', 'Fixed']
58
69
 
59
70
  return (
60
71
  <>
61
- {config.regions &&
62
- config.regions.map(({ label, color, from, to, background, range = 'Custom' }, i) => (
63
- <div className='edit-block' key={`region-${i}`}>
64
- <button
65
- type='button'
66
- className='btn btn-danger remove-column'
67
- onClick={event => {
68
- event.preventDefault()
69
- removeColumn(i)
70
- }}
71
- >
72
- Remove
73
- </button>
74
- <TextField value={label} label='Region Label' fieldName='label' i={i} updateField={updateField} />
75
- <div className='two-col-inputs'>
76
- <TextField
77
- value={color}
78
- label='Text Color'
79
- fieldName='color'
80
- updateField={(section, subsection, fieldName, value) => regionUpdate(fieldName, value, i)}
81
- />
82
- <TextField
83
- value={background}
84
- label='Background'
85
- fieldName='background'
86
- updateField={(section, subsection, fieldName, value) => regionUpdate(fieldName, value, i)}
87
- />
88
- </div>
89
-
90
- <Select
91
- value={config.regions[i].fromType ?? 'Fixed'}
92
- label='Minimum Region Type'
93
- initial={'Select'}
94
- required={true}
95
- onChange={e => {
96
- if (e.target.value !== '' && e.target.value !== 'Select') {
97
- const newRegions = [...config.regions]
98
- newRegions[i].fromType = e.target.value
99
- updateConfig({
100
- ...config,
101
- regions: newRegions
102
- })
103
- }
104
- e.target.value = ''
105
- }}
106
- options={fromOptions}
107
- />
108
-
109
- {(config.regions[i].fromType === 'Fixed' ||
110
- config.regions[i].fromType === 'Previous Days' ||
111
- !config.regions[i].fromType) && (
112
- <>
113
- <TextField
114
- value={from}
115
- label={
116
- config.regions[i].fromType === 'Fixed' || !config.regions[i]?.fromType
117
- ? 'From Value'
118
- : 'Previous Number of Days'
119
- }
120
- fieldName='from'
121
- updateField={(section, subsection, fieldName, value) => regionUpdate(fieldName, value, i)}
122
- tooltip={
123
- <Tooltip style={{ textTransform: 'none' }}>
124
- <Tooltip.Target>
125
- <Icon display='question' style={{ marginLeft: '0.5rem' }} />
126
- </Tooltip.Target>
127
- <Tooltip.Content>
128
- <p>
129
- When using categorical (linear scale) match the data set value. When using date (linear / date
130
- time scale) match the x-axis value.
131
- </p>
132
- </Tooltip.Content>
133
- </Tooltip>
134
- }
135
- />
136
- </>
137
- )}
138
-
139
- <Select
140
- value={config.regions[i].toType ?? 'Fixed'}
141
- label='Maximum Region Type'
142
- initial={'Select'}
143
- required={true}
144
- onChange={e => {
145
- if (e.target.value !== '' && e.target.value !== 'Select') {
146
- const newRegions = [...config.regions]
147
- newRegions[i].toType = e.target.value
148
- updateConfig({
149
- ...config,
150
- regions: newRegions
151
- })
152
- }
153
- e.target.value = ''
154
- }}
155
- options={toOptions}
156
- />
157
-
158
- {(config.regions[i].toType === 'Fixed' || !config.regions[i].toType) && (
159
- <TextField
160
- value={to}
161
- label='To Value'
162
- fieldName='to'
163
- updateField={(section, subsection, fieldName, value) => regionUpdate(fieldName, value, i)}
164
- />
72
+ <GroupedList
73
+ items={config.regions}
74
+ label='Regions'
75
+ droppableId='chart-regions-order'
76
+ onDragEnd={({ source, destination }) => {
77
+ if (!destination || source.index === destination.index) return
78
+ moveRegion(source.index, destination.index)
79
+ }}
80
+ renderItem={({ label, color, from, to, background, range = 'Custom' }, i) => (
81
+ <Draggable key={`region-${i}`} draggableId={`region-${i}`} index={i}>
82
+ {(provided, snapshot) => (
83
+ <div
84
+ className={snapshot.isDragging ? 'currently-dragging' : ''}
85
+ style={provided.draggableProps.style}
86
+ ref={provided.innerRef}
87
+ {...provided.draggableProps}
88
+ {...provided.dragHandleProps}
89
+ >
90
+ <Accordion allowZeroExpanded preExpanded={['panel']}>
91
+ <AccordionItem uuid='panel' className='series-item series-item--chart'>
92
+ <AccordionItemHeading className='series-item__title'>
93
+ <AccordionItemButton className='accordion__button'>
94
+ <Icon display='move' size={15} style={{ cursor: 'default' }} />
95
+ {label || `Region ${i + 1}`}
96
+ </AccordionItemButton>
97
+ </AccordionItemHeading>
98
+ <AccordionItemPanel>
99
+ <div className='series-item__panel-actions'>
100
+ <Button
101
+ type='button'
102
+ variant='danger'
103
+ size='sm'
104
+ className='grouped-list__remove'
105
+ onClick={event => {
106
+ event.preventDefault()
107
+ removeColumn(i)
108
+ }}
109
+ >
110
+ Remove
111
+ </Button>
112
+ </div>
113
+ <TextField value={label} label='Region Label' fieldName='label' i={i} updateField={updateField} />
114
+ <div className='two-col-inputs'>
115
+ <TextField
116
+ value={color}
117
+ label='Text Color'
118
+ fieldName='color'
119
+ updateField={(section, subsection, fieldName, value) => regionUpdate(fieldName, value, i)}
120
+ />
121
+ <TextField
122
+ value={background}
123
+ label='Background'
124
+ fieldName='background'
125
+ updateField={(section, subsection, fieldName, value) => regionUpdate(fieldName, value, i)}
126
+ />
127
+ </div>
128
+
129
+ <Select
130
+ value={config.regions[i].fromType ?? 'Fixed'}
131
+ label='Minimum Region Type'
132
+ initial={'Select'}
133
+ required={true}
134
+ onChange={e => {
135
+ if (e.target.value !== '' && e.target.value !== 'Select') {
136
+ const newRegions = [...config.regions]
137
+ newRegions[i].fromType = e.target.value
138
+ updateConfig({
139
+ ...config,
140
+ regions: newRegions
141
+ })
142
+ }
143
+ e.target.value = ''
144
+ }}
145
+ options={fromOptions}
146
+ />
147
+
148
+ {(config.regions[i].fromType === 'Fixed' ||
149
+ config.regions[i].fromType === 'Previous Days' ||
150
+ !config.regions[i].fromType) && (
151
+ <>
152
+ <TextField
153
+ value={from}
154
+ label={
155
+ config.regions[i].fromType === 'Fixed' || !config.regions[i]?.fromType
156
+ ? 'From Value'
157
+ : 'Previous Number of Days'
158
+ }
159
+ fieldName='from'
160
+ updateField={(section, subsection, fieldName, value) => regionUpdate(fieldName, value, i)}
161
+ tooltip={
162
+ <Tooltip style={{ textTransform: 'none' }}>
163
+ <Tooltip.Target>
164
+ <Icon display='question' style={{ marginLeft: '0.5rem' }} />
165
+ </Tooltip.Target>
166
+ <Tooltip.Content>
167
+ <p>
168
+ When using categorical (linear scale) match the data set value. When using date
169
+ (linear / date time scale) match the x-axis value.
170
+ </p>
171
+ </Tooltip.Content>
172
+ </Tooltip>
173
+ }
174
+ />
175
+ </>
176
+ )}
177
+
178
+ <Select
179
+ value={config.regions[i].toType ?? 'Fixed'}
180
+ label='Maximum Region Type'
181
+ initial={'Select'}
182
+ required={true}
183
+ onChange={e => {
184
+ if (e.target.value !== '' && e.target.value !== 'Select') {
185
+ const newRegions = [...config.regions]
186
+ newRegions[i].toType = e.target.value
187
+ updateConfig({
188
+ ...config,
189
+ regions: newRegions
190
+ })
191
+ }
192
+ e.target.value = ''
193
+ }}
194
+ options={toOptions}
195
+ />
196
+
197
+ {(config.regions[i].toType === 'Fixed' || !config.regions[i].toType) && (
198
+ <TextField
199
+ value={to}
200
+ label='To Value'
201
+ fieldName='to'
202
+ updateField={(section, subsection, fieldName, value) => regionUpdate(fieldName, value, i)}
203
+ />
204
+ )}
205
+ </AccordionItemPanel>
206
+ </AccordionItem>
207
+ </Accordion>
208
+ </div>
165
209
  )}
166
- </div>
167
- ))}
210
+ </Draggable>
211
+ )}
212
+ />
168
213
  {!config.regions && <p style={{ textAlign: 'center' }}>There are currently no regions.</p>}
169
- <button
214
+ <Button
170
215
  type='button'
171
- className='btn btn-primary full-width'
216
+ variant='editor-primary'
172
217
  onClick={e => {
173
218
  e.preventDefault()
174
219
  addColumn()
175
220
  }}
176
221
  >
177
222
  Add Region
178
- </button>
223
+ </Button>
179
224
  </>
180
225
  )
181
226
  })
@@ -115,16 +115,16 @@ const SankeySettings: React.FC<PanelProps> = props => {
115
115
  </div>
116
116
  ))}
117
117
  {data?.storyNodeText?.length < 3 && (
118
- <button
118
+ <Button
119
119
  type='button'
120
- className='btn btn-primary full-width'
120
+ variant='editor-primary'
121
121
  onClick={e => {
122
122
  e.preventDefault()
123
123
  addStoryNode()
124
124
  }}
125
125
  >
126
126
  Add StoryNode
127
- </button>
127
+ </Button>
128
128
  )}
129
129
  {config.data?.[0]?.tooltips?.length > 0 && (
130
130
  <CheckBox
@@ -8,8 +8,10 @@ import { colorPalettesChartV1, colorPalettesChartV2, sequentialPalettes } from '
8
8
  import { updatePaletteNames } from '@cdc/core/helpers/updatePaletteNames'
9
9
  import { getColorPaletteVersion } from '@cdc/core/helpers/getColorPaletteVersion'
10
10
  import Icon from '@cdc/core/components/ui/Icon'
11
- import { Select } from '@cdc/core/components/EditorPanel/Inputs'
11
+ import { CheckBox, Select, TextField } from '@cdc/core/components/EditorPanel/Inputs'
12
+ import Button from '@cdc/core/components/elements/Button'
12
13
  import { buildForecastPaletteOptions } from '../../../../helpers/buildForecastPaletteOptions'
14
+ import { getSeriesColumnConfig, upsertSeriesColumnConfig } from '../../../../helpers/seriesColumnSettings'
13
15
 
14
16
  // Third Party
15
17
  import {
@@ -19,7 +21,7 @@ import {
19
21
  AccordionItemPanel,
20
22
  AccordionItemButton
21
23
  } from 'react-accessible-accordion'
22
- import { Draggable, DragDropContext, Droppable } from '@hello-pangea/dnd'
24
+ import { Draggable } from '@hello-pangea/dnd'
23
25
  import Tooltip from '@cdc/core/components/ui/Tooltip'
24
26
 
25
27
  const SeriesContext = React.createContext({})
@@ -374,8 +376,8 @@ const SeriesDropdownConfidenceInterval = props => {
374
376
  )
375
377
  })}
376
378
  </Accordion>
377
- <button
378
- className='btn btn-primary full-width'
379
+ <Button
380
+ variant='editor-primary'
379
381
  onClick={e => {
380
382
  e.preventDefault()
381
383
  let copiedIndex = null
@@ -396,7 +398,7 @@ const SeriesDropdownConfidenceInterval = props => {
396
398
  }}
397
399
  >
398
400
  Add Confidence Interval Group
399
- </button>
401
+ </Button>
400
402
  </fieldset>
401
403
  </div>
402
404
  )
@@ -538,6 +540,84 @@ const SeriesDisplayInTooltip = props => {
538
540
  )
539
541
  }
540
542
 
543
+ const SeriesColumnSettings = props => {
544
+ const { series } = props
545
+ const { config, updateConfig } = useContext(ConfigContext)
546
+ const { columnConfig } = getSeriesColumnConfig(config.columns || {}, series.dataKey)
547
+
548
+ const updateSeriesColumn = (fieldName, value) => {
549
+ const columns = upsertSeriesColumnConfig(config.columns || {}, series.dataKey, {
550
+ [fieldName]: value
551
+ })
552
+
553
+ updateConfig({
554
+ ...config,
555
+ columns
556
+ })
557
+ }
558
+
559
+ return (
560
+ <>
561
+ <span className='divider-heading'>Series Column Settings</span>
562
+ <TextField
563
+ value={columnConfig.label || ''}
564
+ section='seriesColumn'
565
+ subsection={series.dataKey}
566
+ fieldName='label'
567
+ label='Label'
568
+ updateField={(_section, _subsection, _fieldName, value) => updateSeriesColumn('label', value)}
569
+ />
570
+ <div className='three-col'>
571
+ <TextField
572
+ value={columnConfig.prefix || ''}
573
+ section='seriesColumn'
574
+ subsection={series.dataKey}
575
+ fieldName='prefix'
576
+ label='Prefix'
577
+ updateField={(_section, _subsection, _fieldName, value) => updateSeriesColumn('prefix', value)}
578
+ />
579
+ <TextField
580
+ value={columnConfig.suffix || ''}
581
+ section='seriesColumn'
582
+ subsection={series.dataKey}
583
+ fieldName='suffix'
584
+ label='Suffix'
585
+ updateField={(_section, _subsection, _fieldName, value) => updateSeriesColumn('suffix', value)}
586
+ />
587
+ <TextField
588
+ type='number'
589
+ value={columnConfig.roundToPlace ?? 0}
590
+ section='seriesColumn'
591
+ subsection={series.dataKey}
592
+ fieldName='roundToPlace'
593
+ label='Round'
594
+ updateField={(_section, _subsection, _fieldName, value) =>
595
+ updateSeriesColumn('roundToPlace', Number(value) || 0)
596
+ }
597
+ />
598
+ </div>
599
+ <CheckBox
600
+ value={columnConfig.commas || false}
601
+ section='seriesColumn'
602
+ subsection={series.dataKey}
603
+ fieldName='commas'
604
+ label='Add Commas to Numbers'
605
+ updateField={(_section, _subsection, _fieldName, value) => updateSeriesColumn('commas', value)}
606
+ />
607
+ {config.table.showVertical && (
608
+ <CheckBox
609
+ value={columnConfig.dataTable ?? true}
610
+ section='seriesColumn'
611
+ subsection={series.dataKey}
612
+ fieldName='dataTable'
613
+ label='Show in Data Table'
614
+ updateField={(_section, _subsection, _fieldName, value) => updateSeriesColumn('dataTable', value)}
615
+ />
616
+ )}
617
+ </>
618
+ )
619
+ }
620
+
541
621
  const SeriesButtonRemove = props => {
542
622
  const { config, updateConfig } = useContext(ConfigContext)
543
623
  const { series, index } = props
@@ -573,7 +653,7 @@ const SeriesButtonRemove = props => {
573
653
  }
574
654
  }
575
655
 
576
- const handleRemoveSeries = (e, series, index) => {
656
+ const handleRemoveSeries = (e, series) => {
577
657
  e.preventDefault()
578
658
  removeSeries(series.dataKey)
579
659
  }
@@ -581,9 +661,9 @@ const SeriesButtonRemove = props => {
581
661
  return (
582
662
  config.series &&
583
663
  config.series.length > 1 && (
584
- <button className='series-list__remove' onClick={e => handleRemoveSeries(e, series, index)}>
664
+ <Button variant='danger' size='sm' className='grouped-list__remove' onClick={e => handleRemoveSeries(e, series)}>
585
665
  Remove
586
- </button>
666
+ </Button>
587
667
  )
588
668
  )
589
669
  }
@@ -631,12 +711,15 @@ const SeriesItem = props => {
631
711
  >
632
712
  <Icon display='move' size={15} style={{ cursor: 'default' }} />
633
713
  {series.dataKey}
634
- <Series.Button.Remove series={series} index={i} />
635
714
  </AccordionItemButton>
636
715
  </AccordionItemHeading>
637
716
  {chartsWithOptions.includes(config.visualizationType) && (
638
717
  <AccordionItemPanel>
718
+ <div className='series-item__panel-actions'>
719
+ <Series.Button.Remove series={series} index={i} />
720
+ </div>
639
721
  <Series.Input.Name series={series} index={i} />
722
+ <Series.Input.ColumnSettings series={series} index={i} />
640
723
  {showDynamicCategory && (
641
724
  <>
642
725
  <Select
@@ -693,22 +776,6 @@ const SeriesItem = props => {
693
776
  )
694
777
  }
695
778
 
696
- const SeriesList = props => {
697
- const { series, getItemStyle, sortableItemStyles, chartsWithOptions } = props
698
- return series.map((series, i) => {
699
- return (
700
- <SeriesItem
701
- getItemStyle={getItemStyle}
702
- sortableItemStyles={sortableItemStyles}
703
- chartsWithOptions={chartsWithOptions}
704
- series={series}
705
- index={i}
706
- key={`series-list-${i}`}
707
- />
708
- )
709
- })
710
- }
711
-
712
779
  const Series = {
713
780
  Wrapper: SeriesWrapper,
714
781
  Dropdown: {
@@ -722,7 +789,8 @@ const Series = {
722
789
  },
723
790
  Input: {
724
791
  Name: SeriesInputName,
725
- Weight: SeriesInputWeight
792
+ Weight: SeriesInputWeight,
793
+ ColumnSettings: SeriesColumnSettings
726
794
  },
727
795
  Checkbox: {
728
796
  DisplayInTooltip: SeriesDisplayInTooltip
@@ -730,8 +798,7 @@ const Series = {
730
798
  Button: {
731
799
  Remove: SeriesButtonRemove
732
800
  },
733
- Item: SeriesItem,
734
- List: SeriesList
801
+ Item: SeriesItem
735
802
  }
736
803
 
737
804
  export default Series
@@ -1,5 +1,4 @@
1
1
  import { useContext, FC, useMemo } from 'react'
2
- import _ from 'lodash'
3
2
  import cloneConfig from '@cdc/core/helpers/cloneConfig'
4
3
 
5
4
  // external libraries
@@ -31,13 +30,16 @@ import { LineChartConfig } from '../../../../types/ChartConfig'
31
30
  import { PaletteSelector, DeveloperPaletteRollback } from '@cdc/core/components/PaletteSelector'
32
31
  import { HeaderThemeSelector } from '@cdc/core/components/HeaderThemeSelector'
33
32
  import { CustomColorsEditor } from '@cdc/core/components/CustomColorsEditor'
33
+ import StyleTreatmentSection from '@cdc/core/components/EditorPanel/sections/StyleTreatmentSection'
34
34
  import { getColorScale } from '../../../../helpers/getColorScale'
35
- import '@cdc/core/styles/v2/components/editor.scss'
35
+ import { ENABLE_CHART_MAP_TP5_TREATMENT_SELECTION, ENABLE_CHART_VISUAL_SETTINGS } from '@cdc/core/helpers/constants'
36
+ import '@cdc/core/components/EditorPanel/editor.scss'
36
37
  import './panelVisual.styles.css'
37
38
 
38
39
  const PanelVisual: FC<PanelProps> = props => {
39
40
  const { config, updateConfig, colorPalettes, twoColorPalette } = useContext<ChartContext>(ConfigContext)
40
41
  const { visual } = config
42
+ const styleTreatment = config.titleStyle === 'legacy' && !visual?.tp5Treatment ? 'legacy' : 'tp5'
41
43
 
42
44
  const { setLollipopShape, updateField, handlePaletteSelection, handleTwoColorPaletteSelection } =
43
45
  useEditorPanelContext()
@@ -89,12 +91,44 @@ const PanelVisual: FC<PanelProps> = props => {
89
91
  }
90
92
  }
91
93
 
94
+ const handleStyleTreatmentChange = (value: string) => {
95
+ const useTp5Treatment = value === 'tp5'
96
+
97
+ updateConfig({
98
+ ...config,
99
+ titleStyle: useTp5Treatment ? 'small' : 'legacy',
100
+ visual: {
101
+ ...config.visual,
102
+ tp5Treatment: useTp5Treatment,
103
+ border: useTp5Treatment ? false : config.visual?.border,
104
+ borderColorTheme: useTp5Treatment ? false : config.visual?.borderColorTheme,
105
+ accent: useTp5Treatment ? false : config.visual?.accent
106
+ }
107
+ })
108
+ }
109
+
92
110
  return (
93
111
  <AccordionItem className='panel-visual'>
94
112
  <AccordionItemHeading>
95
113
  <AccordionItemButton>Visual</AccordionItemButton>
96
114
  </AccordionItemHeading>
97
115
  <AccordionItemPanel>
116
+ <HeaderThemeSelector selectedTheme={config.theme} onThemeSelect={theme => updateConfig({ ...config, theme })} />
117
+ {ENABLE_CHART_VISUAL_SETTINGS && (
118
+ <StyleTreatmentSection
119
+ styleTreatment={styleTreatment}
120
+ onStyleTreatmentChange={handleStyleTreatmentChange}
121
+ showStyleTreatment={ENABLE_CHART_MAP_TP5_TREATMENT_SELECTION}
122
+ border={visual?.border}
123
+ borderColorTheme={visual?.borderColorTheme}
124
+ accent={visual?.accent}
125
+ background={visual?.background}
126
+ hideBackgroundColor={visual?.hideBackgroundColor}
127
+ showBackground={config.visualizationType === 'Spark Line'}
128
+ showHideBackgroundColor={config.visualizationType === 'Spark Line'}
129
+ updateField={updateField}
130
+ />
131
+ )}
98
132
  {(config.barStyle === 'lollipop' || config.isLollipopChart) && (
99
133
  <>
100
134
  <fieldset className='header'>
@@ -272,7 +306,6 @@ const PanelVisual: FC<PanelProps> = props => {
272
306
  />
273
307
  </>
274
308
  )}
275
- <HeaderThemeSelector selectedTheme={config.theme} onThemeSelect={theme => updateConfig({ ...config, theme })} />
276
309
  {(visSupportsNonSequentialPallete() || visSupportsNonSequentialPallete()) && (
277
310
  <>
278
311
  <label>
@@ -573,45 +606,6 @@ const PanelVisual: FC<PanelProps> = props => {
573
606
  updateField={updateField}
574
607
  />
575
608
  )}
576
- {config.visualizationType === 'Spark Line' && (
577
- <div className='cove-accordion__panel-section checkbox-group'>
578
- <CheckBox
579
- value={visual?.border}
580
- section='visual'
581
- fieldName='border'
582
- label='Show Border'
583
- updateField={updateField}
584
- />
585
- <CheckBox
586
- value={visual?.borderColorTheme}
587
- section='visual'
588
- fieldName='borderColorTheme'
589
- label='Use Border Color Theme'
590
- updateField={updateField}
591
- />
592
- <CheckBox
593
- value={visual?.accent}
594
- section='visual'
595
- fieldName='accent'
596
- label='Use Accent Style'
597
- updateField={updateField}
598
- />
599
- <CheckBox
600
- value={visual?.background}
601
- section='visual'
602
- fieldName='background'
603
- label='Use Theme Background Color'
604
- updateField={updateField}
605
- />
606
- <CheckBox
607
- value={visual?.hideBackgroundColor}
608
- section='visual'
609
- fieldName='hideBackgroundColor'
610
- label='Hide Background Color'
611
- updateField={updateField}
612
- />
613
- </div>
614
- )}
615
609
  {(config.visualizationType === 'Line' || config.visualizationType === 'Combo') && (
616
610
  <CheckBox
617
611
  value={config.showLineSeriesLabels}
@@ -690,6 +684,15 @@ const PanelVisual: FC<PanelProps> = props => {
690
684
  }
691
685
  />
692
686
  </label>
687
+ {isCoveDeveloperMode() && (
688
+ <CheckBox
689
+ value={visual?.highlightWrappers}
690
+ section='visual'
691
+ fieldName='highlightWrappers'
692
+ label='Highlight Layout Wrappers'
693
+ updateField={updateField}
694
+ />
695
+ )}
693
696
  </AccordionItemPanel>
694
697
  </AccordionItem>
695
698
  )
@@ -1,4 +1,4 @@
1
- .cdc-open-viz-module.type-chart {
1
+ .cove-visualization.type-chart {
2
2
  .viewport-overrides {
3
3
  button {
4
4
  width: 100%;