@cdc/chart 4.26.1 → 4.26.3
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.local.md +79 -0
- package/LICENSE +201 -0
- package/dist/{cdcchart-dgT_1dIT.es.js → cdcchart-DQ00cQCm.es.js} +1 -20
- package/dist/cdcchart.js +54742 -49796
- package/examples/data/data-with-metadata.json +10 -0
- package/examples/default.json +378 -0
- package/examples/feature/__data__/horizon-chart-data.json +373 -0
- package/examples/feature/annotations/index.json +3 -6
- package/examples/feature/horizon/horizon-chart.json +395 -0
- package/examples/feature/pie/planet-pie-example-config.json +2 -1
- package/examples/line-chart-states.json +1085 -0
- package/examples/metadata-variables.json +58 -0
- package/examples/private/123.json +694 -0
- package/examples/private/anchor-issue.json +4094 -0
- package/examples/private/backwards-slider.json +10430 -0
- package/examples/private/georgia.csv +160 -0
- package/examples/private/timeline-data.json +1 -0
- package/examples/private/timeline.json +389 -0
- package/examples/radar-chart-simple.json +133 -0
- package/examples/radar-chart.json +148 -0
- package/index.html +1 -31
- package/package.json +57 -59
- package/src/CdcChart.tsx +8 -4
- package/src/CdcChartComponent.tsx +398 -284
- package/src/_stories/Chart.Anchors.stories.tsx +10 -0
- package/src/_stories/Chart.BoxPlot.stories.tsx +7 -0
- package/src/_stories/Chart.CI.stories.tsx +13 -0
- package/src/_stories/Chart.Combo.stories.tsx +17 -0
- package/src/_stories/Chart.CustomColors.stories.tsx +78 -0
- package/src/_stories/Chart.Defaults.stories.tsx +95 -0
- package/src/_stories/Chart.DynamicSeries.stories.tsx +19 -0
- package/src/_stories/Chart.Filters.stories.tsx +4 -0
- package/src/_stories/Chart.Forecast.stories.tsx +4 -0
- package/src/_stories/Chart.HTMLInDataTable.stories.tsx +22 -0
- package/src/_stories/Chart.Legend.Gradient.stories.tsx +28 -0
- package/src/_stories/Chart.Patterns.stories.tsx +4 -0
- package/src/_stories/Chart.PreserveDecimals.stories.tsx +25 -0
- package/src/_stories/Chart.Regions.Categorical.stories.tsx +13 -0
- package/src/_stories/Chart.Regions.DateScale.stories.tsx +19 -0
- package/src/_stories/Chart.Regions.DateTimeScale.stories.tsx +25 -10
- package/src/_stories/Chart.ScatterPlot.stories.tsx +4 -0
- package/src/_stories/Chart.SmallMultiples.stories.tsx +16 -0
- package/src/_stories/Chart.SmallestLeftAxisMax.stories.tsx +64 -0
- package/src/_stories/Chart.stories.tsx +72 -1
- package/src/_stories/Chart.tooltip.stories.tsx +7 -0
- package/src/_stories/ChartAnnotation.stories.tsx +10 -0
- package/src/_stories/ChartAxisLabels.stories.tsx +4 -0
- package/src/_stories/ChartAxisTitles.stories.tsx +10 -0
- package/src/_stories/ChartBar.Editor.stories.tsx +97 -38
- package/src/_stories/ChartBrush.Editor.stories.tsx +11 -25
- package/src/_stories/ChartBrush.Matrix.Continuous.stories.tsx +41 -0
- package/src/_stories/ChartBrush.Matrix.Date.stories.tsx +114 -0
- package/src/_stories/ChartBrush.Matrix.DateTime.stories.tsx +78 -0
- package/src/_stories/ChartBrush.stories.tsx +7 -0
- package/src/_stories/ChartEditor.Editor.stories.tsx +1 -1
- package/src/_stories/ChartEditor.stories.tsx +7 -0
- package/src/_stories/ChartLine.QuadrantAngles.stories.tsx +89 -0
- package/src/_stories/ChartLine.Suppression.stories.tsx +7 -0
- package/src/_stories/ChartLine.Symbols.stories.tsx +4 -0
- package/src/_stories/ChartPrefixSuffix.stories.tsx +46 -1
- package/src/_stories/TechAdoptionWithLinks.stories.tsx +7 -0
- package/src/_stories/_mock/brush_continuous.json +86 -0
- package/src/_stories/_mock/brush_date_large.json +176 -0
- package/src/_stories/_mock/line_chart_angle_near_zero_fall.json +195 -0
- package/src/_stories/_mock/line_chart_angle_near_zero_rise.json +195 -0
- package/src/_stories/_mock/line_chart_angle_q1_steep_upward.json +195 -0
- package/src/_stories/_mock/line_chart_angle_q2_gentle_downward.json +195 -0
- package/src/_stories/_mock/line_chart_angle_q3_steep_downward.json +195 -0
- package/src/_stories/_mock/line_chart_angle_q4_gentle_upward.json +195 -0
- package/src/_stories/_mock/line_chart_quadrant_angles.json +264 -0
- package/src/_stories/_mock/paired-bar-abbr.json +421 -0
- package/src/_stories/_mock/pie_custom_colors.json +268 -0
- package/src/_stories/_mock/smallest_left_axis_max.json +104 -0
- package/src/components/Annotations/components/AnnotationDraggable.styles.css +14 -20
- package/src/components/Annotations/components/AnnotationDraggable.tsx +240 -116
- package/src/components/Annotations/components/AnnotationDropdown.styles.css +1 -2
- package/src/components/Annotations/components/AnnotationDropdown.tsx +8 -12
- package/src/components/Annotations/components/AnnotationList.styles.css +12 -18
- package/src/components/Annotations/components/AnnotationList.tsx +5 -4
- package/src/components/Annotations/components/findNearestDatum.ts +75 -85
- package/src/components/Annotations/helpers/getVisibleAnnotations.ts +38 -0
- package/src/components/Axis/BottomAxis.tsx +277 -0
- package/src/components/Axis/LeftAxis.tsx +404 -0
- package/src/components/Axis/LeftAxisGridlines.tsx +77 -0
- package/src/components/Axis/PairedBarAxis.tsx +192 -0
- package/src/components/Axis/README.md +94 -0
- package/src/components/Axis/RightAxis.tsx +108 -0
- package/src/components/Axis/axis.constants.ts +21 -0
- package/src/components/Axis/index.ts +7 -0
- package/src/components/BarChart/components/BarChart.Horizontal.tsx +12 -28
- package/src/components/BarChart/components/BarChart.StackedHorizontal.tsx +12 -30
- package/src/components/BarChart/components/BarChart.StackedVertical.tsx +12 -31
- package/src/components/BarChart/components/BarChart.Vertical.tsx +12 -28
- package/src/components/BarChart/components/BarChart.tsx +7 -1
- package/src/components/BarChart/helpers/getPatternUrl.ts +94 -0
- package/src/components/BarChart/helpers/tests/getPatternUrl.test.ts +134 -0
- package/src/components/BarChart/helpers/useBarChart.ts +3 -0
- package/src/components/Brush/BrushSelector.tsx +155 -22
- package/src/components/Brush/MiniChartPreview.tsx +133 -21
- package/src/components/EditorPanel/EditorPanel.tsx +81 -54
- package/src/components/EditorPanel/components/Panels/Panel.Annotate.tsx +67 -29
- package/src/components/EditorPanel/components/Panels/Panel.ForestPlotSettings.tsx +0 -78
- package/src/components/EditorPanel/components/Panels/Panel.General.tsx +120 -2
- package/src/components/EditorPanel/components/Panels/Panel.PatternSettings.tsx +25 -43
- package/src/components/EditorPanel/components/Panels/Panel.Radar.tsx +353 -0
- package/src/components/EditorPanel/components/Panels/Panel.Series.tsx +83 -3
- package/src/components/EditorPanel/components/Panels/Panel.Visual.tsx +66 -43
- package/src/components/EditorPanel/components/Panels/index.tsx +2 -0
- package/src/components/EditorPanel/editor-panel.scss +1 -1
- package/src/components/EditorPanel/useEditorPermissions.ts +55 -26
- package/src/components/ForestPlot/ForestPlot.tsx +26 -22
- package/src/components/HorizonChart/HorizonChart.tsx +131 -0
- package/src/components/HorizonChart/components/HorizonBand.tsx +160 -0
- package/src/components/HorizonChart/helpers/calculateHorizonBands.ts +27 -0
- package/src/components/HorizonChart/helpers/getHorizonLayerColors.ts +40 -0
- package/src/components/HorizonChart/index.tsx +3 -0
- package/src/components/Legend/Legend.Component.tsx +52 -4
- package/src/components/Legend/Legend.tsx +1 -1
- package/src/components/Legend/LegendGroup/LegendGroup.styles.css +4 -4
- package/src/components/Legend/LegendValueRange.tsx +77 -0
- package/src/components/Legend/helpers/createFormatLabels.tsx +16 -2
- package/src/components/Legend/helpers/generateValueRanges.ts +92 -0
- package/src/components/LineChart/helpers/README.md +292 -0
- package/src/components/LineChart/helpers/labelPositioning.test.ts +245 -0
- package/src/components/LineChart/helpers/labelPositioning.ts +304 -0
- package/src/components/LineChart/index.tsx +44 -8
- package/src/components/LinearChart/README.md +109 -0
- package/src/components/LinearChart/VisualizationRenderer.tsx +267 -0
- package/src/components/LinearChart/linearChart.constants.ts +84 -0
- package/src/components/LinearChart/tests/LinearChart.test.tsx +278 -0
- package/src/components/LinearChart/tests/mockConfigContext.ts +131 -0
- package/src/components/LinearChart/utils/tickFormatting.ts +146 -0
- package/src/components/LinearChart.tsx +268 -1057
- package/src/components/PieChart/PieChart.tsx +20 -5
- package/src/components/RadarChart/RadarAxis.tsx +78 -0
- package/src/components/RadarChart/RadarChart.tsx +298 -0
- package/src/components/RadarChart/RadarGrid.tsx +64 -0
- package/src/components/RadarChart/RadarPolygon.tsx +91 -0
- package/src/components/RadarChart/helpers.ts +83 -0
- package/src/components/RadarChart/index.tsx +3 -0
- package/src/components/Regions/components/Regions.tsx +6 -6
- package/src/components/Sankey/components/Sankey.tsx +3 -3
- package/src/components/Sankey/sankey.scss +1 -1
- package/src/components/SmallMultiples/SmallMultiples.css +5 -5
- package/src/components/Sparkline/index.scss +4 -2
- package/src/components/WarmingStripes/WarmingStripes.tsx +95 -25
- package/src/components/WarmingStripes/WarmingStripesGradientLegend.css +8 -8
- package/src/data/initial-state.js +37 -15
- package/src/data/legacy-defaults.ts +18 -0
- package/src/helpers/abbreviateNumber.ts +24 -17
- package/src/helpers/getChartPatternId.ts +17 -0
- package/src/helpers/getExcludedData.ts +4 -0
- package/src/helpers/getMinMax.ts +16 -2
- package/src/helpers/handleChartAriaLabels.ts +19 -19
- package/src/helpers/handleLineType.ts +22 -18
- package/src/helpers/seriesColumnSettings.ts +114 -0
- package/src/helpers/tests/countNumOfTicks.test.ts +77 -0
- package/src/helpers/tests/seriesColumnSettings.test.ts +84 -0
- package/src/hooks/useProgrammaticTooltip.ts +23 -2
- package/src/hooks/useRightAxis.ts +14 -0
- package/src/hooks/useScales.ts +99 -56
- package/src/hooks/useTooltip.tsx +23 -3
- package/src/scss/main.scss +157 -79
- package/src/selectors/README.md +68 -0
- package/src/store/chart.reducer.ts +2 -0
- package/src/test/CdcChart.test.jsx +2 -2
- package/src/types/ChartConfig.ts +22 -0
- package/src/types/ChartContext.ts +1 -0
- package/src/types/Horizon.ts +64 -0
- package/tests/fixtures/chart-config-with-metadata.json +29 -0
- package/tests/fixtures/data-with-metadata.json +10 -0
- package/preview.html +0 -1616
- package/src/components/Annotations/components/helpers/index.tsx +0 -46
|
@@ -0,0 +1,353 @@
|
|
|
1
|
+
import { useContext, FC } from 'react'
|
|
2
|
+
import {
|
|
3
|
+
AccordionItem,
|
|
4
|
+
AccordionItemHeading,
|
|
5
|
+
AccordionItemPanel,
|
|
6
|
+
AccordionItemButton
|
|
7
|
+
} from 'react-accessible-accordion'
|
|
8
|
+
import { TextField, Select, CheckBox } from '@cdc/core/components/EditorPanel/Inputs'
|
|
9
|
+
import Tooltip from '@cdc/core/components/ui/Tooltip'
|
|
10
|
+
import Icon from '@cdc/core/components/ui/Icon'
|
|
11
|
+
import ConfigContext from '../../../../ConfigContext'
|
|
12
|
+
import { useEditorPanelContext } from '../../EditorPanelContext'
|
|
13
|
+
import { type PanelProps } from './../PanelProps'
|
|
14
|
+
import { ChartContext } from '../../../../types/ChartContext'
|
|
15
|
+
|
|
16
|
+
const PanelRadar: FC<PanelProps> = props => {
|
|
17
|
+
const { config, rawData } = useContext<ChartContext>(ConfigContext)
|
|
18
|
+
const { updateField } = useEditorPanelContext()
|
|
19
|
+
|
|
20
|
+
if (config.visualizationType !== 'Radar') return null
|
|
21
|
+
|
|
22
|
+
const radar = config.radar || {}
|
|
23
|
+
|
|
24
|
+
// Get available columns from the data
|
|
25
|
+
const getColumns = () => {
|
|
26
|
+
if (!rawData || rawData.length === 0) return []
|
|
27
|
+
return Object.keys(rawData[0])
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
return (
|
|
31
|
+
<AccordionItem>
|
|
32
|
+
<AccordionItemHeading>
|
|
33
|
+
<AccordionItemButton>{props.name}</AccordionItemButton>
|
|
34
|
+
</AccordionItemHeading>
|
|
35
|
+
<AccordionItemPanel>
|
|
36
|
+
{/* Data Settings */}
|
|
37
|
+
<fieldset className='fieldset'>
|
|
38
|
+
<legend style={{ fontSize: '16px', fontWeight: 'bold', marginBottom: '10px' }}>Data Settings</legend>
|
|
39
|
+
|
|
40
|
+
<Select
|
|
41
|
+
value={config.xAxis?.dataKey || ''}
|
|
42
|
+
section='xAxis'
|
|
43
|
+
fieldName='dataKey'
|
|
44
|
+
label='Category Column'
|
|
45
|
+
initial='Select'
|
|
46
|
+
required={true}
|
|
47
|
+
updateField={updateField}
|
|
48
|
+
options={getColumns()}
|
|
49
|
+
tooltip={
|
|
50
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
51
|
+
<Tooltip.Target>
|
|
52
|
+
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
53
|
+
</Tooltip.Target>
|
|
54
|
+
<Tooltip.Content>
|
|
55
|
+
<p>Select the column containing category labels for each axis of the radar chart.</p>
|
|
56
|
+
</Tooltip.Content>
|
|
57
|
+
</Tooltip>
|
|
58
|
+
}
|
|
59
|
+
/>
|
|
60
|
+
</fieldset>
|
|
61
|
+
|
|
62
|
+
{/* Number Formatting */}
|
|
63
|
+
<fieldset className='fieldset' style={{ marginTop: '20px' }}>
|
|
64
|
+
<legend style={{ fontSize: '16px', fontWeight: 'bold', marginBottom: '10px' }}>Number Formatting</legend>
|
|
65
|
+
|
|
66
|
+
<CheckBox
|
|
67
|
+
value={config.dataFormat?.commas}
|
|
68
|
+
section='dataFormat'
|
|
69
|
+
fieldName='commas'
|
|
70
|
+
label='Add Commas'
|
|
71
|
+
updateField={updateField}
|
|
72
|
+
tooltip={
|
|
73
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
74
|
+
<Tooltip.Target>
|
|
75
|
+
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
76
|
+
</Tooltip.Target>
|
|
77
|
+
<Tooltip.Content>
|
|
78
|
+
<p>Add commas to numeric values in tooltips and data table.</p>
|
|
79
|
+
</Tooltip.Content>
|
|
80
|
+
</Tooltip>
|
|
81
|
+
}
|
|
82
|
+
/>
|
|
83
|
+
|
|
84
|
+
<TextField
|
|
85
|
+
value={config.dataFormat?.roundTo ?? 0}
|
|
86
|
+
type='number'
|
|
87
|
+
section='dataFormat'
|
|
88
|
+
fieldName='roundTo'
|
|
89
|
+
label='Round to Decimal Point'
|
|
90
|
+
updateField={updateField}
|
|
91
|
+
min={0}
|
|
92
|
+
/>
|
|
93
|
+
|
|
94
|
+
<div className='two-col-inputs'>
|
|
95
|
+
<TextField
|
|
96
|
+
value={config.dataFormat?.prefix || ''}
|
|
97
|
+
section='dataFormat'
|
|
98
|
+
fieldName='prefix'
|
|
99
|
+
label='Prefix'
|
|
100
|
+
updateField={updateField}
|
|
101
|
+
tooltip={
|
|
102
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
103
|
+
<Tooltip.Target>
|
|
104
|
+
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
105
|
+
</Tooltip.Target>
|
|
106
|
+
<Tooltip.Content>
|
|
107
|
+
<p>Enter a data prefix (such as "$"), if applicable.</p>
|
|
108
|
+
</Tooltip.Content>
|
|
109
|
+
</Tooltip>
|
|
110
|
+
}
|
|
111
|
+
/>
|
|
112
|
+
<TextField
|
|
113
|
+
value={config.dataFormat?.suffix || ''}
|
|
114
|
+
section='dataFormat'
|
|
115
|
+
fieldName='suffix'
|
|
116
|
+
label='Suffix'
|
|
117
|
+
updateField={updateField}
|
|
118
|
+
tooltip={
|
|
119
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
120
|
+
<Tooltip.Target>
|
|
121
|
+
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
122
|
+
</Tooltip.Target>
|
|
123
|
+
<Tooltip.Content>
|
|
124
|
+
<p>Enter a data suffix (such as "%"), if applicable.</p>
|
|
125
|
+
</Tooltip.Content>
|
|
126
|
+
</Tooltip>
|
|
127
|
+
}
|
|
128
|
+
/>
|
|
129
|
+
</div>
|
|
130
|
+
</fieldset>
|
|
131
|
+
|
|
132
|
+
{/* Grid Settings */}
|
|
133
|
+
<fieldset className='fieldset' style={{ marginTop: '20px' }}>
|
|
134
|
+
<legend style={{ fontSize: '16px', fontWeight: 'bold', marginBottom: '10px' }}>Grid Settings</legend>
|
|
135
|
+
|
|
136
|
+
<TextField
|
|
137
|
+
type='number'
|
|
138
|
+
value={radar.gridRings ?? 5}
|
|
139
|
+
fieldName='gridRings'
|
|
140
|
+
section='radar'
|
|
141
|
+
label='Number of Grid Rings'
|
|
142
|
+
updateField={updateField}
|
|
143
|
+
min={3}
|
|
144
|
+
max={10}
|
|
145
|
+
tooltip={
|
|
146
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
147
|
+
<Tooltip.Target>
|
|
148
|
+
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
149
|
+
</Tooltip.Target>
|
|
150
|
+
<Tooltip.Content>
|
|
151
|
+
<p>Number of concentric rings in the grid (3-10)</p>
|
|
152
|
+
</Tooltip.Content>
|
|
153
|
+
</Tooltip>
|
|
154
|
+
}
|
|
155
|
+
/>
|
|
156
|
+
|
|
157
|
+
<CheckBox
|
|
158
|
+
value={radar.showGridRings ?? true}
|
|
159
|
+
fieldName='showGridRings'
|
|
160
|
+
section='radar'
|
|
161
|
+
label='Show Grid Rings'
|
|
162
|
+
updateField={updateField}
|
|
163
|
+
/>
|
|
164
|
+
|
|
165
|
+
<Select
|
|
166
|
+
value={radar.gridRingStyle ?? 'polygons'}
|
|
167
|
+
fieldName='gridRingStyle'
|
|
168
|
+
section='radar'
|
|
169
|
+
label='Grid Style'
|
|
170
|
+
updateField={updateField}
|
|
171
|
+
options={['polygons', 'circles']}
|
|
172
|
+
tooltip={
|
|
173
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
174
|
+
<Tooltip.Target>
|
|
175
|
+
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
176
|
+
</Tooltip.Target>
|
|
177
|
+
<Tooltip.Content>
|
|
178
|
+
<p>Shape of the grid rings - polygons match the data shape, circles are rounded</p>
|
|
179
|
+
</Tooltip.Content>
|
|
180
|
+
</Tooltip>
|
|
181
|
+
}
|
|
182
|
+
/>
|
|
183
|
+
</fieldset>
|
|
184
|
+
|
|
185
|
+
{/* Scale Settings */}
|
|
186
|
+
<fieldset className='fieldset' style={{ marginTop: '20px' }}>
|
|
187
|
+
<legend style={{ fontSize: '16px', fontWeight: 'bold', marginBottom: '10px' }}>Scale Settings</legend>
|
|
188
|
+
|
|
189
|
+
<TextField
|
|
190
|
+
type='number'
|
|
191
|
+
value={radar.scaleMin ?? 0}
|
|
192
|
+
fieldName='scaleMin'
|
|
193
|
+
section='radar'
|
|
194
|
+
label='Minimum Value'
|
|
195
|
+
updateField={updateField}
|
|
196
|
+
tooltip={
|
|
197
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
198
|
+
<Tooltip.Target>
|
|
199
|
+
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
200
|
+
</Tooltip.Target>
|
|
201
|
+
<Tooltip.Content>
|
|
202
|
+
<p>Minimum value for the radar scale (center point)</p>
|
|
203
|
+
</Tooltip.Content>
|
|
204
|
+
</Tooltip>
|
|
205
|
+
}
|
|
206
|
+
/>
|
|
207
|
+
|
|
208
|
+
<TextField
|
|
209
|
+
type='number'
|
|
210
|
+
value={radar.scaleMax ?? ''}
|
|
211
|
+
fieldName='scaleMax'
|
|
212
|
+
section='radar'
|
|
213
|
+
label='Maximum Value'
|
|
214
|
+
updateField={updateField}
|
|
215
|
+
placeholder='Auto-calculated'
|
|
216
|
+
tooltip={
|
|
217
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
218
|
+
<Tooltip.Target>
|
|
219
|
+
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
220
|
+
</Tooltip.Target>
|
|
221
|
+
<Tooltip.Content>
|
|
222
|
+
<p>Maximum value for the radar scale. Leave empty to auto-calculate from data.</p>
|
|
223
|
+
</Tooltip.Content>
|
|
224
|
+
</Tooltip>
|
|
225
|
+
}
|
|
226
|
+
/>
|
|
227
|
+
</fieldset>
|
|
228
|
+
|
|
229
|
+
{/* Visual Settings */}
|
|
230
|
+
<fieldset className='fieldset' style={{ marginTop: '20px' }}>
|
|
231
|
+
<legend style={{ fontSize: '16px', fontWeight: 'bold', marginBottom: '10px' }}>Visual Settings</legend>
|
|
232
|
+
|
|
233
|
+
<CheckBox
|
|
234
|
+
value={radar.showFill ?? false}
|
|
235
|
+
fieldName='showFill'
|
|
236
|
+
section='radar'
|
|
237
|
+
label='Show Fill'
|
|
238
|
+
updateField={updateField}
|
|
239
|
+
tooltip={
|
|
240
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
241
|
+
<Tooltip.Target>
|
|
242
|
+
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
243
|
+
</Tooltip.Target>
|
|
244
|
+
<Tooltip.Content>
|
|
245
|
+
<p>Fill the polygon area with color. When off, only the outline is shown.</p>
|
|
246
|
+
</Tooltip.Content>
|
|
247
|
+
</Tooltip>
|
|
248
|
+
}
|
|
249
|
+
/>
|
|
250
|
+
|
|
251
|
+
{(radar.showFill ?? false) && (
|
|
252
|
+
<TextField
|
|
253
|
+
type='number'
|
|
254
|
+
value={radar.fillOpacity ?? 0.3}
|
|
255
|
+
fieldName='fillOpacity'
|
|
256
|
+
section='radar'
|
|
257
|
+
label='Fill Opacity'
|
|
258
|
+
updateField={updateField}
|
|
259
|
+
min={0}
|
|
260
|
+
max={1}
|
|
261
|
+
step={0.1}
|
|
262
|
+
tooltip={
|
|
263
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
264
|
+
<Tooltip.Target>
|
|
265
|
+
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
266
|
+
</Tooltip.Target>
|
|
267
|
+
<Tooltip.Content>
|
|
268
|
+
<p>Opacity of the polygon fill (0 = transparent, 1 = solid)</p>
|
|
269
|
+
</Tooltip.Content>
|
|
270
|
+
</Tooltip>
|
|
271
|
+
}
|
|
272
|
+
/>
|
|
273
|
+
)}
|
|
274
|
+
|
|
275
|
+
<TextField
|
|
276
|
+
type='number'
|
|
277
|
+
value={radar.strokeWidth ?? 2}
|
|
278
|
+
fieldName='strokeWidth'
|
|
279
|
+
section='radar'
|
|
280
|
+
label='Stroke Width'
|
|
281
|
+
updateField={updateField}
|
|
282
|
+
min={1}
|
|
283
|
+
max={5}
|
|
284
|
+
tooltip={
|
|
285
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
286
|
+
<Tooltip.Target>
|
|
287
|
+
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
288
|
+
</Tooltip.Target>
|
|
289
|
+
<Tooltip.Content>
|
|
290
|
+
<p>Width of the polygon outline</p>
|
|
291
|
+
</Tooltip.Content>
|
|
292
|
+
</Tooltip>
|
|
293
|
+
}
|
|
294
|
+
/>
|
|
295
|
+
|
|
296
|
+
<CheckBox
|
|
297
|
+
value={radar.showPoints ?? true}
|
|
298
|
+
fieldName='showPoints'
|
|
299
|
+
section='radar'
|
|
300
|
+
label='Show Data Points'
|
|
301
|
+
updateField={updateField}
|
|
302
|
+
tooltip={
|
|
303
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
304
|
+
<Tooltip.Target>
|
|
305
|
+
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
306
|
+
</Tooltip.Target>
|
|
307
|
+
<Tooltip.Content>
|
|
308
|
+
<p>Display circular markers at each data point vertex</p>
|
|
309
|
+
</Tooltip.Content>
|
|
310
|
+
</Tooltip>
|
|
311
|
+
}
|
|
312
|
+
/>
|
|
313
|
+
|
|
314
|
+
{(radar.showPoints ?? true) && (
|
|
315
|
+
<TextField
|
|
316
|
+
type='number'
|
|
317
|
+
value={radar.pointRadius ?? 4}
|
|
318
|
+
fieldName='pointRadius'
|
|
319
|
+
section='radar'
|
|
320
|
+
label='Point Size'
|
|
321
|
+
updateField={updateField}
|
|
322
|
+
min={2}
|
|
323
|
+
max={10}
|
|
324
|
+
/>
|
|
325
|
+
)}
|
|
326
|
+
|
|
327
|
+
<TextField
|
|
328
|
+
type='number'
|
|
329
|
+
value={radar.axisLabelOffset ?? 15}
|
|
330
|
+
fieldName='axisLabelOffset'
|
|
331
|
+
section='radar'
|
|
332
|
+
label='Axis Label Offset'
|
|
333
|
+
updateField={updateField}
|
|
334
|
+
min={5}
|
|
335
|
+
max={50}
|
|
336
|
+
tooltip={
|
|
337
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
338
|
+
<Tooltip.Target>
|
|
339
|
+
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
340
|
+
</Tooltip.Target>
|
|
341
|
+
<Tooltip.Content>
|
|
342
|
+
<p>Distance between axis endpoint and label</p>
|
|
343
|
+
</Tooltip.Content>
|
|
344
|
+
</Tooltip>
|
|
345
|
+
}
|
|
346
|
+
/>
|
|
347
|
+
</fieldset>
|
|
348
|
+
</AccordionItemPanel>
|
|
349
|
+
</AccordionItem>
|
|
350
|
+
)
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
export default PanelRadar
|
|
@@ -8,8 +8,9 @@ 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
12
|
import { buildForecastPaletteOptions } from '../../../../helpers/buildForecastPaletteOptions'
|
|
13
|
+
import { getSeriesColumnConfig, upsertSeriesColumnConfig } from '../../../../helpers/seriesColumnSettings'
|
|
13
14
|
|
|
14
15
|
// Third Party
|
|
15
16
|
import {
|
|
@@ -50,7 +51,6 @@ const SeriesWrapper = props => {
|
|
|
50
51
|
forecastingStages.forEach(stage => {
|
|
51
52
|
forecastingStageArr.push({ key: stage })
|
|
52
53
|
})
|
|
53
|
-
// debugger
|
|
54
54
|
series[index].stages = forecastingStageArr
|
|
55
55
|
series[index].stageColumn = series[index].dataKey
|
|
56
56
|
}
|
|
@@ -539,6 +539,84 @@ const SeriesDisplayInTooltip = props => {
|
|
|
539
539
|
)
|
|
540
540
|
}
|
|
541
541
|
|
|
542
|
+
const SeriesColumnSettings = props => {
|
|
543
|
+
const { series } = props
|
|
544
|
+
const { config, updateConfig } = useContext(ConfigContext)
|
|
545
|
+
const { columnConfig } = getSeriesColumnConfig(config.columns || {}, series.dataKey)
|
|
546
|
+
|
|
547
|
+
const updateSeriesColumn = (fieldName, value) => {
|
|
548
|
+
const columns = upsertSeriesColumnConfig(config.columns || {}, series.dataKey, {
|
|
549
|
+
[fieldName]: value
|
|
550
|
+
})
|
|
551
|
+
|
|
552
|
+
updateConfig({
|
|
553
|
+
...config,
|
|
554
|
+
columns
|
|
555
|
+
})
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
return (
|
|
559
|
+
<>
|
|
560
|
+
<span className='divider-heading'>Series Column Settings</span>
|
|
561
|
+
<TextField
|
|
562
|
+
value={columnConfig.label || ''}
|
|
563
|
+
section='seriesColumn'
|
|
564
|
+
subsection={series.dataKey}
|
|
565
|
+
fieldName='label'
|
|
566
|
+
label='Label'
|
|
567
|
+
updateField={(_section, _subsection, _fieldName, value) => updateSeriesColumn('label', value)}
|
|
568
|
+
/>
|
|
569
|
+
<div className='three-col'>
|
|
570
|
+
<TextField
|
|
571
|
+
value={columnConfig.prefix || ''}
|
|
572
|
+
section='seriesColumn'
|
|
573
|
+
subsection={series.dataKey}
|
|
574
|
+
fieldName='prefix'
|
|
575
|
+
label='Prefix'
|
|
576
|
+
updateField={(_section, _subsection, _fieldName, value) => updateSeriesColumn('prefix', value)}
|
|
577
|
+
/>
|
|
578
|
+
<TextField
|
|
579
|
+
value={columnConfig.suffix || ''}
|
|
580
|
+
section='seriesColumn'
|
|
581
|
+
subsection={series.dataKey}
|
|
582
|
+
fieldName='suffix'
|
|
583
|
+
label='Suffix'
|
|
584
|
+
updateField={(_section, _subsection, _fieldName, value) => updateSeriesColumn('suffix', value)}
|
|
585
|
+
/>
|
|
586
|
+
<TextField
|
|
587
|
+
type='number'
|
|
588
|
+
value={columnConfig.roundToPlace ?? 0}
|
|
589
|
+
section='seriesColumn'
|
|
590
|
+
subsection={series.dataKey}
|
|
591
|
+
fieldName='roundToPlace'
|
|
592
|
+
label='Round'
|
|
593
|
+
updateField={(_section, _subsection, _fieldName, value) =>
|
|
594
|
+
updateSeriesColumn('roundToPlace', Number(value) || 0)
|
|
595
|
+
}
|
|
596
|
+
/>
|
|
597
|
+
</div>
|
|
598
|
+
<CheckBox
|
|
599
|
+
value={columnConfig.commas || false}
|
|
600
|
+
section='seriesColumn'
|
|
601
|
+
subsection={series.dataKey}
|
|
602
|
+
fieldName='commas'
|
|
603
|
+
label='Add Commas to Numbers'
|
|
604
|
+
updateField={(_section, _subsection, _fieldName, value) => updateSeriesColumn('commas', value)}
|
|
605
|
+
/>
|
|
606
|
+
{config.table.showVertical && (
|
|
607
|
+
<CheckBox
|
|
608
|
+
value={columnConfig.dataTable ?? true}
|
|
609
|
+
section='seriesColumn'
|
|
610
|
+
subsection={series.dataKey}
|
|
611
|
+
fieldName='dataTable'
|
|
612
|
+
label='Show in Data Table'
|
|
613
|
+
updateField={(_section, _subsection, _fieldName, value) => updateSeriesColumn('dataTable', value)}
|
|
614
|
+
/>
|
|
615
|
+
)}
|
|
616
|
+
</>
|
|
617
|
+
)
|
|
618
|
+
}
|
|
619
|
+
|
|
542
620
|
const SeriesButtonRemove = props => {
|
|
543
621
|
const { config, updateConfig } = useContext(ConfigContext)
|
|
544
622
|
const { series, index } = props
|
|
@@ -638,6 +716,7 @@ const SeriesItem = props => {
|
|
|
638
716
|
{chartsWithOptions.includes(config.visualizationType) && (
|
|
639
717
|
<AccordionItemPanel>
|
|
640
718
|
<Series.Input.Name series={series} index={i} />
|
|
719
|
+
<Series.Input.ColumnSettings series={series} index={i} />
|
|
641
720
|
{showDynamicCategory && (
|
|
642
721
|
<>
|
|
643
722
|
<Select
|
|
@@ -723,7 +802,8 @@ const Series = {
|
|
|
723
802
|
},
|
|
724
803
|
Input: {
|
|
725
804
|
Name: SeriesInputName,
|
|
726
|
-
Weight: SeriesInputWeight
|
|
805
|
+
Weight: SeriesInputWeight,
|
|
806
|
+
ColumnSettings: SeriesColumnSettings
|
|
727
807
|
},
|
|
728
808
|
Checkbox: {
|
|
729
809
|
DisplayInTooltip: SeriesDisplayInTooltip
|
|
@@ -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/
|
|
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'>
|
|
@@ -241,6 +275,27 @@ const PanelVisual: FC<PanelProps> = props => {
|
|
|
241
275
|
updateField={updateField}
|
|
242
276
|
options={['Same as Line', 'Lighter than Line']}
|
|
243
277
|
/>
|
|
278
|
+
<CheckBox
|
|
279
|
+
value={config.general?.useIntelligentLineChartLabels ?? false}
|
|
280
|
+
section='general'
|
|
281
|
+
fieldName='useIntelligentLineChartLabels'
|
|
282
|
+
label='Use Intelligent Label Positioning'
|
|
283
|
+
updateField={updateField}
|
|
284
|
+
tooltip={
|
|
285
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
286
|
+
<Tooltip.Target>
|
|
287
|
+
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
288
|
+
</Tooltip.Target>
|
|
289
|
+
<Tooltip.Content>
|
|
290
|
+
<p>
|
|
291
|
+
Automatically positions data labels to avoid overlapping with line segments based on the direction
|
|
292
|
+
and location of data points. When disabled, all labels are positioned above and centered on their
|
|
293
|
+
data points.
|
|
294
|
+
</p>
|
|
295
|
+
</Tooltip.Content>
|
|
296
|
+
</Tooltip>
|
|
297
|
+
}
|
|
298
|
+
/>
|
|
244
299
|
<CheckBox
|
|
245
300
|
value={!(config as LineChartConfig).isolatedDotsSameSize}
|
|
246
301
|
fieldName='isolatedDotsSameSize'
|
|
@@ -251,7 +306,6 @@ const PanelVisual: FC<PanelProps> = props => {
|
|
|
251
306
|
/>
|
|
252
307
|
</>
|
|
253
308
|
)}
|
|
254
|
-
<HeaderThemeSelector selectedTheme={config.theme} onThemeSelect={theme => updateConfig({ ...config, theme })} />
|
|
255
309
|
{(visSupportsNonSequentialPallete() || visSupportsNonSequentialPallete()) && (
|
|
256
310
|
<>
|
|
257
311
|
<label>
|
|
@@ -398,7 +452,6 @@ const PanelVisual: FC<PanelProps> = props => {
|
|
|
398
452
|
}}
|
|
399
453
|
label='Custom Color Order'
|
|
400
454
|
minColors={1}
|
|
401
|
-
maxColors={20}
|
|
402
455
|
/>
|
|
403
456
|
</div>
|
|
404
457
|
)}
|
|
@@ -553,45 +606,6 @@ const PanelVisual: FC<PanelProps> = props => {
|
|
|
553
606
|
updateField={updateField}
|
|
554
607
|
/>
|
|
555
608
|
)}
|
|
556
|
-
{config.visualizationType === 'Spark Line' && (
|
|
557
|
-
<div className='cove-accordion__panel-section checkbox-group'>
|
|
558
|
-
<CheckBox
|
|
559
|
-
value={visual?.border}
|
|
560
|
-
section='visual'
|
|
561
|
-
fieldName='border'
|
|
562
|
-
label='Show Border'
|
|
563
|
-
updateField={updateField}
|
|
564
|
-
/>
|
|
565
|
-
<CheckBox
|
|
566
|
-
value={visual?.borderColorTheme}
|
|
567
|
-
section='visual'
|
|
568
|
-
fieldName='borderColorTheme'
|
|
569
|
-
label='Use Border Color Theme'
|
|
570
|
-
updateField={updateField}
|
|
571
|
-
/>
|
|
572
|
-
<CheckBox
|
|
573
|
-
value={visual?.accent}
|
|
574
|
-
section='visual'
|
|
575
|
-
fieldName='accent'
|
|
576
|
-
label='Use Accent Style'
|
|
577
|
-
updateField={updateField}
|
|
578
|
-
/>
|
|
579
|
-
<CheckBox
|
|
580
|
-
value={visual?.background}
|
|
581
|
-
section='visual'
|
|
582
|
-
fieldName='background'
|
|
583
|
-
label='Use Theme Background Color'
|
|
584
|
-
updateField={updateField}
|
|
585
|
-
/>
|
|
586
|
-
<CheckBox
|
|
587
|
-
value={visual?.hideBackgroundColor}
|
|
588
|
-
section='visual'
|
|
589
|
-
fieldName='hideBackgroundColor'
|
|
590
|
-
label='Hide Background Color'
|
|
591
|
-
updateField={updateField}
|
|
592
|
-
/>
|
|
593
|
-
</div>
|
|
594
|
-
)}
|
|
595
609
|
{(config.visualizationType === 'Line' || config.visualizationType === 'Combo') && (
|
|
596
610
|
<CheckBox
|
|
597
611
|
value={config.showLineSeriesLabels}
|
|
@@ -670,6 +684,15 @@ const PanelVisual: FC<PanelProps> = props => {
|
|
|
670
684
|
}
|
|
671
685
|
/>
|
|
672
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
|
+
)}
|
|
673
696
|
</AccordionItemPanel>
|
|
674
697
|
</AccordionItem>
|
|
675
698
|
)
|
|
@@ -5,6 +5,7 @@ import General from './Panel.General'
|
|
|
5
5
|
import BoxPlot from './Panel.BoxPlot'
|
|
6
6
|
import Visual from './Panel.Visual'
|
|
7
7
|
import Sankey from './Panel.Sankey'
|
|
8
|
+
import Radar from './Panel.Radar'
|
|
8
9
|
import Annotate from './Panel.Annotate'
|
|
9
10
|
import PatternSettings from './Panel.PatternSettings'
|
|
10
11
|
import SmallMultiples from './Panel.SmallMultiples'
|
|
@@ -17,6 +18,7 @@ const Panels = {
|
|
|
17
18
|
BoxPlot,
|
|
18
19
|
Visual,
|
|
19
20
|
Sankey,
|
|
21
|
+
Radar,
|
|
20
22
|
Annotate,
|
|
21
23
|
PatternSettings,
|
|
22
24
|
SmallMultiples
|