@cdc/chart 4.23.10 → 4.24.1
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/dist/cdcchart.js +34606 -32218
- package/examples/feature/bar/additional-column-tooltip.json +446 -0
- package/examples/feature/bar/example-bar-chart.json +1 -46
- package/examples/feature/bar/lollipop.json +156 -0
- package/examples/feature/bar/tall-data.json +98 -0
- package/examples/feature/combo/planet-combo-example-config.json +99 -9
- package/examples/feature/dev-4261.json +399 -0
- package/examples/feature/forest-plot/forest-plot.json +63 -19
- package/examples/feature/forest-plot/{broken.json → linear.json} +77 -23
- package/examples/feature/forest-plot/log.json +26 -0
- package/examples/feature/forest-plot/logarithmic.json +271 -0
- package/examples/feature/line/line-chart-preliminary.json +346 -0
- package/examples/feature/line/line-points.json +340 -0
- package/examples/feature/regions/index.json +462 -0
- package/examples/feature/scatterplot/scatterplot.json +272 -33
- package/examples/gallery/bar-chart-vertical/combo-line-chart.json +181 -48
- package/examples/private/chart-t.json +3740 -0
- package/examples/private/combo.json +369 -0
- package/examples/private/epi-data.csv +13 -0
- package/examples/private/epi-data.json +62 -0
- package/examples/private/epi.json +403 -0
- package/examples/private/occupancy.json +109283 -0
- package/examples/private/prod-line-config.json +401 -0
- package/examples/private/region-data.json +822 -0
- package/examples/private/region-testing.json +312 -0
- package/examples/private/scaling.json +45325 -0
- package/examples/private/testing-data.json +1739 -0
- package/examples/private/testing.json +816 -0
- package/examples/sparkline-multilple.json +846 -0
- package/index.html +12 -8
- package/package.json +3 -3
- package/src/CdcChart.tsx +42 -211
- package/src/ConfigContext.tsx +6 -0
- package/src/_stories/Chart.stories.tsx +188 -0
- package/src/_stories/Chart.tooltip.stories.tsx +305 -0
- package/src/_stories/ChartBrush.stories.tsx +19 -0
- package/src/_stories/ChartEditor.stories.tsx +22 -0
- package/src/_stories/ChartLine.preliminary.tsx +19 -0
- package/src/_stories/ChartSuppress.stories.tsx +19 -0
- package/src/_stories/_mock/brush_mock.json +393 -0
- package/src/_stories/_mock/pie_config.json +191 -0
- package/src/_stories/_mock/pie_data.json +218 -0
- package/src/_stories/_mock/preliminary_mock.json +346 -0
- package/src/_stories/_mock/suppress_mock.json +911 -0
- package/src/components/{AreaChart.Stacked.jsx → AreaChart/components/AreaChart.Stacked.jsx} +6 -7
- package/src/components/{AreaChart.jsx → AreaChart/components/AreaChart.jsx} +7 -36
- package/src/components/AreaChart/index.tsx +4 -0
- package/src/components/{BarChart.Horizontal.jsx → BarChart/components/BarChart.Horizontal.tsx} +111 -34
- package/src/components/{BarChart.StackedHorizontal.jsx → BarChart/components/BarChart.StackedHorizontal.tsx} +55 -20
- package/src/components/BarChart/components/BarChart.StackedVertical.tsx +106 -0
- package/src/components/{BarChart.Vertical.jsx → BarChart/components/BarChart.Vertical.tsx} +162 -34
- package/src/components/BarChart/components/BarChart.jsx +39 -0
- package/src/components/{BarChartType.jsx → BarChart/components/BarChartType.jsx} +0 -2
- package/src/components/BarChart/components/context.tsx +13 -0
- package/src/components/BarChart/index.tsx +3 -0
- package/src/components/{BoxPlot.jsx → BoxPlot/BoxPlot.jsx} +1 -1
- package/src/components/BoxPlot/index.tsx +3 -0
- package/src/components/DeviationBar.jsx +4 -3
- package/src/components/{EditorPanel.jsx → EditorPanel/EditorPanel.tsx} +807 -865
- package/src/components/EditorPanel/components/Panel.DateHighlighting.tsx +109 -0
- package/src/components/{ForestPlotSettings.jsx → EditorPanel/components/Panel.ForestPlotSettings.tsx} +190 -220
- package/src/components/EditorPanel/components/Panel.Regions.tsx +168 -0
- package/src/components/{Series.jsx → EditorPanel/components/Panel.Series.tsx} +23 -4
- package/src/components/EditorPanel/components/PanelProps.ts +3 -0
- package/src/components/EditorPanel/components/Panels.tsx +13 -0
- package/src/components/EditorPanel/components/panels.scss +72 -0
- package/src/components/EditorPanel/editor-panel.scss +751 -0
- package/src/components/EditorPanel/index.tsx +3 -0
- package/src/{hooks → components/EditorPanel}/useEditorPermissions.js +50 -5
- package/src/components/{Forecasting.jsx → Forecasting/Forecasting.jsx} +1 -1
- package/src/components/Forecasting/index.tsx +3 -0
- package/src/components/ForestPlot/ForestPlot.tsx +254 -0
- package/src/components/ForestPlot/ForestPlotProps.ts +18 -0
- package/src/components/ForestPlot/index.scss +1 -0
- package/src/components/ForestPlot/index.tsx +3 -0
- package/src/components/Legend/Legend.tsx +347 -0
- package/src/components/Legend/index.tsx +3 -0
- package/src/components/LineChart/LineChartProps.ts +46 -0
- package/src/components/{LineChart.Circle.tsx → LineChart/components/LineChart.Circle.tsx} +36 -30
- package/src/components/LineChart/helpers.ts +45 -0
- package/src/components/LineChart/index.scss +1 -0
- package/src/components/{LineChart.tsx → LineChart/index.tsx} +83 -42
- package/src/components/LinearChart.jsx +125 -82
- package/src/components/PairedBarChart.jsx +2 -2
- package/src/components/{PieChart.jsx → PieChart/PieChart.tsx} +16 -7
- package/src/components/PieChart/index.tsx +3 -0
- package/src/components/Regions/components/Regions.tsx +135 -0
- package/src/components/Regions/index.tsx +3 -0
- package/src/components/{ScatterPlot.jsx → ScatterPlot/ScatterPlot.jsx} +3 -3
- package/src/components/ScatterPlot/index.tsx +3 -0
- package/src/components/{SparkLine.jsx → Sparkline/SparkLine.jsx} +2 -2
- package/src/components/Sparkline/index.tsx +3 -0
- package/src/components/ZoomBrush.tsx +168 -0
- package/src/data/initial-state.js +30 -16
- package/src/helpers/abbreviateNumber.ts +17 -0
- package/src/helpers/computeMarginBottom.ts +55 -0
- package/src/helpers/filterData.ts +18 -0
- package/src/helpers/generateColorsArray.ts +8 -0
- package/src/helpers/getQuartiles.ts +30 -0
- package/src/helpers/handleChartAriaLabels.ts +19 -0
- package/src/helpers/handleLineType.ts +18 -0
- package/src/helpers/lineOptions.ts +18 -0
- package/src/helpers/sort.ts +7 -0
- package/src/helpers/tests/computeMarginBottom.test.ts +20 -0
- package/src/hooks/useBarChart.js +72 -7
- package/src/hooks/useColorScale.ts +50 -0
- package/src/hooks/{useMinMax.js → useMinMax.ts} +75 -23
- package/src/hooks/{useRightAxis.js → useRightAxis.ts} +10 -2
- package/src/hooks/{useScales.js → useScales.ts} +64 -17
- package/src/hooks/{useTooltip.jsx → useTooltip.tsx} +84 -55
- package/src/scss/main.scss +70 -38
- package/src/types/ChartConfig.ts +178 -0
- package/src/types/ChartContext.ts +54 -0
- package/src/types/ForestPlot.ts +53 -0
- package/examples/feature/scatterplot/scatterplot-continuous.csv +0 -17
- package/src/ConfigContext.jsx +0 -5
- package/src/components/BarChart.StackedVertical.jsx +0 -95
- package/src/components/BarChart.jsx +0 -30
- package/src/components/ForestPlot.jsx +0 -191
- package/src/components/Legend.jsx +0 -277
- package/src/scss/LinearChart.scss +0 -0
- package/src/scss/editor-panel.scss +0 -745
- package/src/scss/legend.scss +0 -206
- package/src/scss/mixins.scss +0 -0
- package/src/scss/variables.scss +0 -1
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import { memo, useContext } from 'react'
|
|
2
|
+
import { useEditorPermissions } from './../useEditorPermissions.js'
|
|
3
|
+
import { AccordionItem, AccordionItemHeading, AccordionItemPanel, AccordionItemButton } from 'react-accessible-accordion'
|
|
4
|
+
import { type ChartConfig } from './../../../types/ChartConfig.js'
|
|
5
|
+
import { TextField, Select } from '@cdc/core/components/EditorPanel/Inputs'
|
|
6
|
+
import Tooltip from '@cdc/core/components/ui/Tooltip'
|
|
7
|
+
import Icon from '@cdc/core/components/ui/Icon'
|
|
8
|
+
import { type ChartContext } from '../../../types/ChartContext'
|
|
9
|
+
import { type PanelProps } from './PanelProps'
|
|
10
|
+
import ConfigContext from '../../../ConfigContext'
|
|
11
|
+
|
|
12
|
+
const RegionSettings = memo(({ config, updateConfig }: { config: ChartConfig; updateConfig: Function }) => {
|
|
13
|
+
let regionUpdate = (fieldName, value, i) => {
|
|
14
|
+
let regions = []
|
|
15
|
+
|
|
16
|
+
if (config.regions) {
|
|
17
|
+
regions = [...config.regions]
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
regions[i][fieldName] = value
|
|
21
|
+
updateConfig({ ...config, regions })
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// only for Regions
|
|
25
|
+
let updateField = (section, subsection, fieldName, value, i) => regionUpdate(fieldName, value, i)
|
|
26
|
+
|
|
27
|
+
let removeColumn = i => {
|
|
28
|
+
let regions = []
|
|
29
|
+
|
|
30
|
+
if (config.regions) {
|
|
31
|
+
regions = [...config.regions]
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
regions.splice(i, 1)
|
|
35
|
+
|
|
36
|
+
updateConfig({ ...config, regions })
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
let addColumn = () => {
|
|
40
|
+
let regions = []
|
|
41
|
+
|
|
42
|
+
if (config.regions) {
|
|
43
|
+
regions = [...config.regions]
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
regions.push({})
|
|
47
|
+
|
|
48
|
+
updateConfig({ ...config, regions })
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const fromOptions = ['Fixed', 'Previous Days']
|
|
52
|
+
const toOptions = ['Last Date', 'Fixed']
|
|
53
|
+
|
|
54
|
+
return (
|
|
55
|
+
<>
|
|
56
|
+
{config.regions &&
|
|
57
|
+
config.regions.map(({ label, color, from, to, background, range = 'Custom' }, i) => (
|
|
58
|
+
<div className='edit-block' key={`region-${i}`}>
|
|
59
|
+
<button
|
|
60
|
+
type='button'
|
|
61
|
+
className='remove-column'
|
|
62
|
+
onClick={event => {
|
|
63
|
+
event.preventDefault()
|
|
64
|
+
removeColumn(i)
|
|
65
|
+
}}
|
|
66
|
+
>
|
|
67
|
+
Remove
|
|
68
|
+
</button>
|
|
69
|
+
<TextField value={label} label='Region Label' fieldName='label' i={i} updateField={updateField} />
|
|
70
|
+
<div className='two-col-inputs'>
|
|
71
|
+
<TextField value={color} label='Text Color' fieldName='color' updateField={(section, subsection, fieldName, value) => regionUpdate(fieldName, value, i)} />
|
|
72
|
+
<TextField value={background} label='Background' fieldName='background' updateField={(section, subsection, fieldName, value) => regionUpdate(fieldName, value, i)} />
|
|
73
|
+
</div>
|
|
74
|
+
|
|
75
|
+
<Select
|
|
76
|
+
value={config.regions[i].fromType ?? 'Fixed'}
|
|
77
|
+
label='Minimum Region Type'
|
|
78
|
+
initial={'Select'}
|
|
79
|
+
required={true}
|
|
80
|
+
onChange={e => {
|
|
81
|
+
if (e.target.value !== '' && e.target.value !== 'Select') {
|
|
82
|
+
const newRegions = [...config.regions]
|
|
83
|
+
newRegions[i].fromType = e.target.value
|
|
84
|
+
updateConfig({
|
|
85
|
+
...config,
|
|
86
|
+
regions: newRegions
|
|
87
|
+
})
|
|
88
|
+
}
|
|
89
|
+
e.target.value = ''
|
|
90
|
+
}}
|
|
91
|
+
options={fromOptions}
|
|
92
|
+
/>
|
|
93
|
+
|
|
94
|
+
{(config.regions[i].fromType === 'Fixed' || config.regions[i].fromType === 'Previous Days' || !config.regions[i].fromType) && (
|
|
95
|
+
<>
|
|
96
|
+
<TextField
|
|
97
|
+
value={from}
|
|
98
|
+
label={config.regions[i].fromType === 'Fixed' || !config.regions[i]?.fromType ? 'From Value' : 'Previous Number of Days'}
|
|
99
|
+
fieldName='from'
|
|
100
|
+
updateField={(section, subsection, fieldName, value) => regionUpdate(fieldName, value, i)}
|
|
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>The date needs to be in the original format of the data. Not the displayed format of the data.</p>
|
|
108
|
+
</Tooltip.Content>
|
|
109
|
+
</Tooltip>
|
|
110
|
+
}
|
|
111
|
+
/>
|
|
112
|
+
</>
|
|
113
|
+
)}
|
|
114
|
+
|
|
115
|
+
<Select
|
|
116
|
+
value={config.regions[i].toType ?? 'Fixed'}
|
|
117
|
+
label='Maximum Region Type'
|
|
118
|
+
initial={'Select'}
|
|
119
|
+
required={true}
|
|
120
|
+
onChange={e => {
|
|
121
|
+
if (e.target.value !== '' && e.target.value !== 'Select') {
|
|
122
|
+
const newRegions = [...config.regions]
|
|
123
|
+
newRegions[i].toType = e.target.value
|
|
124
|
+
updateConfig({
|
|
125
|
+
...config,
|
|
126
|
+
regions: newRegions
|
|
127
|
+
})
|
|
128
|
+
}
|
|
129
|
+
e.target.value = ''
|
|
130
|
+
}}
|
|
131
|
+
options={toOptions}
|
|
132
|
+
/>
|
|
133
|
+
|
|
134
|
+
{(config.regions[i].toType === 'Fixed' || !config.regions[i].toType) && <TextField value={to} label='To Value' fieldName='to' updateField={(section, subsection, fieldName, value) => regionUpdate(fieldName, value, i)} />}
|
|
135
|
+
</div>
|
|
136
|
+
))}
|
|
137
|
+
{!config.regions && <p style={{ textAlign: 'center' }}>There are currently no regions.</p>}
|
|
138
|
+
<button
|
|
139
|
+
type='button'
|
|
140
|
+
className='btn full-width'
|
|
141
|
+
onClick={e => {
|
|
142
|
+
e.preventDefault()
|
|
143
|
+
addColumn()
|
|
144
|
+
}}
|
|
145
|
+
>
|
|
146
|
+
Add Region
|
|
147
|
+
</button>
|
|
148
|
+
</>
|
|
149
|
+
)
|
|
150
|
+
})
|
|
151
|
+
|
|
152
|
+
const RegionsPanel = ({ name }: PanelProps) => {
|
|
153
|
+
const { visSupportsRegions } = useEditorPermissions()
|
|
154
|
+
const { config, updateConfig } = useContext<ChartContext>(ConfigContext)
|
|
155
|
+
|
|
156
|
+
return visSupportsRegions() ? (
|
|
157
|
+
<AccordionItem>
|
|
158
|
+
<AccordionItemHeading>
|
|
159
|
+
<AccordionItemButton>{name}</AccordionItemButton>
|
|
160
|
+
</AccordionItemHeading>
|
|
161
|
+
<AccordionItemPanel>
|
|
162
|
+
<RegionSettings config={config} updateConfig={updateConfig} />
|
|
163
|
+
</AccordionItemPanel>
|
|
164
|
+
</AccordionItem>
|
|
165
|
+
) : null
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
export default RegionsPanel
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React, { useContext } from 'react'
|
|
2
|
-
import ConfigContext from '
|
|
2
|
+
import ConfigContext from '../../../ConfigContext'
|
|
3
3
|
|
|
4
4
|
// Core
|
|
5
5
|
import InputSelect from '@cdc/core/components/inputs/InputSelect'
|
|
@@ -16,7 +16,7 @@ import { colorPalettesChart, sequentialPalettes } from '@cdc/core/data/colorPale
|
|
|
16
16
|
const SeriesContext = React.createContext()
|
|
17
17
|
|
|
18
18
|
const SeriesWrapper = props => {
|
|
19
|
-
const { updateConfig, config } = useContext(ConfigContext)
|
|
19
|
+
const { updateConfig, config, rawData } = useContext(ConfigContext)
|
|
20
20
|
|
|
21
21
|
const { getColumns, selectComponent } = props
|
|
22
22
|
|
|
@@ -26,6 +26,26 @@ const SeriesWrapper = props => {
|
|
|
26
26
|
let series = [...config.series]
|
|
27
27
|
series[index][property] = value
|
|
28
28
|
|
|
29
|
+
// Reset bars to the left axis if changed.
|
|
30
|
+
if (property === 'type') {
|
|
31
|
+
if (value === 'Bar') {
|
|
32
|
+
series[index].axis = 'Left'
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// dynamically add in the forecasting fields
|
|
37
|
+
if (series[index].type === 'Forecasting') {
|
|
38
|
+
let forecastingStages = Array.from(new Set(rawData.map(item => item[series[index].dataKey])))
|
|
39
|
+
let forecastingStageArr = []
|
|
40
|
+
|
|
41
|
+
forecastingStages.forEach(stage => {
|
|
42
|
+
forecastingStageArr.push({ key: stage })
|
|
43
|
+
})
|
|
44
|
+
// debugger
|
|
45
|
+
series[index].stages = forecastingStageArr
|
|
46
|
+
series[index].stageColumn = series[index].dataKey
|
|
47
|
+
}
|
|
48
|
+
|
|
29
49
|
updateConfig({ ...config, series })
|
|
30
50
|
}
|
|
31
51
|
|
|
@@ -124,7 +144,6 @@ const SeriesDropdownForecastingStage = props => {
|
|
|
124
144
|
const { index, series } = props
|
|
125
145
|
|
|
126
146
|
// Only combo charts are allowed to have different options
|
|
127
|
-
if (series.type !== 'Forecasting') return
|
|
128
147
|
|
|
129
148
|
return (
|
|
130
149
|
<InputSelect
|
|
@@ -408,7 +427,7 @@ const SeriesDropdownConfidenceInterval = props => {
|
|
|
408
427
|
const SeriesInputName = props => {
|
|
409
428
|
const { series, index: i } = props
|
|
410
429
|
const { config, updateConfig } = useContext(ConfigContext)
|
|
411
|
-
const adjustableNameSeriesTypes = ['Bar', 'Line', 'Area Chart']
|
|
430
|
+
const adjustableNameSeriesTypes = ['Bar', 'Line', 'Area Chart', 'dashed-sm', 'dashed-md', 'dashed-lg']
|
|
412
431
|
|
|
413
432
|
if (config.visualizationType === 'Combo') return
|
|
414
433
|
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import ForestPlotSettings from './Panel.ForestPlotSettings'
|
|
2
|
+
import Series from './Panel.Series.jsx'
|
|
3
|
+
import DateHighlighting from './Panel.DateHighlighting'
|
|
4
|
+
import Regions from './Panel.Regions'
|
|
5
|
+
|
|
6
|
+
const Panels = {
|
|
7
|
+
ForestPlot: ForestPlotSettings,
|
|
8
|
+
Series: Series,
|
|
9
|
+
DateHighlighting,
|
|
10
|
+
Regions
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export default Panels
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
@import '@cdc/core/styles/v2/themes/color-definitions';
|
|
2
|
+
|
|
3
|
+
.date-highlight {
|
|
4
|
+
select,
|
|
5
|
+
input {
|
|
6
|
+
background: $lightestGray;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
&__day-selection {
|
|
10
|
+
display: flex;
|
|
11
|
+
flex-direction: row;
|
|
12
|
+
flex-wrap: wrap;
|
|
13
|
+
padding: 20px 0;
|
|
14
|
+
|
|
15
|
+
.week-button {
|
|
16
|
+
margin-bottom: 0;
|
|
17
|
+
border-radius: 50%;
|
|
18
|
+
color: $darkGray;
|
|
19
|
+
width: 24px;
|
|
20
|
+
height: 24px;
|
|
21
|
+
display: flex;
|
|
22
|
+
align-items: center;
|
|
23
|
+
justify-content: center;
|
|
24
|
+
background: $lightestGray;
|
|
25
|
+
margin: 5px 2px 0;
|
|
26
|
+
|
|
27
|
+
&--active {
|
|
28
|
+
background: $primary;
|
|
29
|
+
color: white;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
&__occurance {
|
|
35
|
+
display: flex;
|
|
36
|
+
|
|
37
|
+
input[type='number']::-webkit-inner-spin-button,
|
|
38
|
+
input[type='number']::-webkit-outer-spin-button {
|
|
39
|
+
opacity: 1;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
input[type='number'] {
|
|
43
|
+
margin: 0 10px;
|
|
44
|
+
min-width: 50px;
|
|
45
|
+
width: 50px;
|
|
46
|
+
max-width: 50px;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
.radio-group {
|
|
51
|
+
display: flex;
|
|
52
|
+
align-items: center;
|
|
53
|
+
justify-content: space-between;
|
|
54
|
+
|
|
55
|
+
.group {
|
|
56
|
+
display: flex;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
input[type='number'] {
|
|
60
|
+
margin: 0 10px;
|
|
61
|
+
min-width: 50px;
|
|
62
|
+
width: 50px;
|
|
63
|
+
max-width: 50px;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// reset spacing
|
|
67
|
+
input,
|
|
68
|
+
label {
|
|
69
|
+
margin-top: 0 !important;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|