@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.
Files changed (125) hide show
  1. package/dist/cdcchart.js +34606 -32218
  2. package/examples/feature/bar/additional-column-tooltip.json +446 -0
  3. package/examples/feature/bar/example-bar-chart.json +1 -46
  4. package/examples/feature/bar/lollipop.json +156 -0
  5. package/examples/feature/bar/tall-data.json +98 -0
  6. package/examples/feature/combo/planet-combo-example-config.json +99 -9
  7. package/examples/feature/dev-4261.json +399 -0
  8. package/examples/feature/forest-plot/forest-plot.json +63 -19
  9. package/examples/feature/forest-plot/{broken.json → linear.json} +77 -23
  10. package/examples/feature/forest-plot/log.json +26 -0
  11. package/examples/feature/forest-plot/logarithmic.json +271 -0
  12. package/examples/feature/line/line-chart-preliminary.json +346 -0
  13. package/examples/feature/line/line-points.json +340 -0
  14. package/examples/feature/regions/index.json +462 -0
  15. package/examples/feature/scatterplot/scatterplot.json +272 -33
  16. package/examples/gallery/bar-chart-vertical/combo-line-chart.json +181 -48
  17. package/examples/private/chart-t.json +3740 -0
  18. package/examples/private/combo.json +369 -0
  19. package/examples/private/epi-data.csv +13 -0
  20. package/examples/private/epi-data.json +62 -0
  21. package/examples/private/epi.json +403 -0
  22. package/examples/private/occupancy.json +109283 -0
  23. package/examples/private/prod-line-config.json +401 -0
  24. package/examples/private/region-data.json +822 -0
  25. package/examples/private/region-testing.json +312 -0
  26. package/examples/private/scaling.json +45325 -0
  27. package/examples/private/testing-data.json +1739 -0
  28. package/examples/private/testing.json +816 -0
  29. package/examples/sparkline-multilple.json +846 -0
  30. package/index.html +12 -8
  31. package/package.json +3 -3
  32. package/src/CdcChart.tsx +42 -211
  33. package/src/ConfigContext.tsx +6 -0
  34. package/src/_stories/Chart.stories.tsx +188 -0
  35. package/src/_stories/Chart.tooltip.stories.tsx +305 -0
  36. package/src/_stories/ChartBrush.stories.tsx +19 -0
  37. package/src/_stories/ChartEditor.stories.tsx +22 -0
  38. package/src/_stories/ChartLine.preliminary.tsx +19 -0
  39. package/src/_stories/ChartSuppress.stories.tsx +19 -0
  40. package/src/_stories/_mock/brush_mock.json +393 -0
  41. package/src/_stories/_mock/pie_config.json +191 -0
  42. package/src/_stories/_mock/pie_data.json +218 -0
  43. package/src/_stories/_mock/preliminary_mock.json +346 -0
  44. package/src/_stories/_mock/suppress_mock.json +911 -0
  45. package/src/components/{AreaChart.Stacked.jsx → AreaChart/components/AreaChart.Stacked.jsx} +6 -7
  46. package/src/components/{AreaChart.jsx → AreaChart/components/AreaChart.jsx} +7 -36
  47. package/src/components/AreaChart/index.tsx +4 -0
  48. package/src/components/{BarChart.Horizontal.jsx → BarChart/components/BarChart.Horizontal.tsx} +111 -34
  49. package/src/components/{BarChart.StackedHorizontal.jsx → BarChart/components/BarChart.StackedHorizontal.tsx} +55 -20
  50. package/src/components/BarChart/components/BarChart.StackedVertical.tsx +106 -0
  51. package/src/components/{BarChart.Vertical.jsx → BarChart/components/BarChart.Vertical.tsx} +162 -34
  52. package/src/components/BarChart/components/BarChart.jsx +39 -0
  53. package/src/components/{BarChartType.jsx → BarChart/components/BarChartType.jsx} +0 -2
  54. package/src/components/BarChart/components/context.tsx +13 -0
  55. package/src/components/BarChart/index.tsx +3 -0
  56. package/src/components/{BoxPlot.jsx → BoxPlot/BoxPlot.jsx} +1 -1
  57. package/src/components/BoxPlot/index.tsx +3 -0
  58. package/src/components/DeviationBar.jsx +4 -3
  59. package/src/components/{EditorPanel.jsx → EditorPanel/EditorPanel.tsx} +807 -865
  60. package/src/components/EditorPanel/components/Panel.DateHighlighting.tsx +109 -0
  61. package/src/components/{ForestPlotSettings.jsx → EditorPanel/components/Panel.ForestPlotSettings.tsx} +190 -220
  62. package/src/components/EditorPanel/components/Panel.Regions.tsx +168 -0
  63. package/src/components/{Series.jsx → EditorPanel/components/Panel.Series.tsx} +23 -4
  64. package/src/components/EditorPanel/components/PanelProps.ts +3 -0
  65. package/src/components/EditorPanel/components/Panels.tsx +13 -0
  66. package/src/components/EditorPanel/components/panels.scss +72 -0
  67. package/src/components/EditorPanel/editor-panel.scss +751 -0
  68. package/src/components/EditorPanel/index.tsx +3 -0
  69. package/src/{hooks → components/EditorPanel}/useEditorPermissions.js +50 -5
  70. package/src/components/{Forecasting.jsx → Forecasting/Forecasting.jsx} +1 -1
  71. package/src/components/Forecasting/index.tsx +3 -0
  72. package/src/components/ForestPlot/ForestPlot.tsx +254 -0
  73. package/src/components/ForestPlot/ForestPlotProps.ts +18 -0
  74. package/src/components/ForestPlot/index.scss +1 -0
  75. package/src/components/ForestPlot/index.tsx +3 -0
  76. package/src/components/Legend/Legend.tsx +347 -0
  77. package/src/components/Legend/index.tsx +3 -0
  78. package/src/components/LineChart/LineChartProps.ts +46 -0
  79. package/src/components/{LineChart.Circle.tsx → LineChart/components/LineChart.Circle.tsx} +36 -30
  80. package/src/components/LineChart/helpers.ts +45 -0
  81. package/src/components/LineChart/index.scss +1 -0
  82. package/src/components/{LineChart.tsx → LineChart/index.tsx} +83 -42
  83. package/src/components/LinearChart.jsx +125 -82
  84. package/src/components/PairedBarChart.jsx +2 -2
  85. package/src/components/{PieChart.jsx → PieChart/PieChart.tsx} +16 -7
  86. package/src/components/PieChart/index.tsx +3 -0
  87. package/src/components/Regions/components/Regions.tsx +135 -0
  88. package/src/components/Regions/index.tsx +3 -0
  89. package/src/components/{ScatterPlot.jsx → ScatterPlot/ScatterPlot.jsx} +3 -3
  90. package/src/components/ScatterPlot/index.tsx +3 -0
  91. package/src/components/{SparkLine.jsx → Sparkline/SparkLine.jsx} +2 -2
  92. package/src/components/Sparkline/index.tsx +3 -0
  93. package/src/components/ZoomBrush.tsx +168 -0
  94. package/src/data/initial-state.js +30 -16
  95. package/src/helpers/abbreviateNumber.ts +17 -0
  96. package/src/helpers/computeMarginBottom.ts +55 -0
  97. package/src/helpers/filterData.ts +18 -0
  98. package/src/helpers/generateColorsArray.ts +8 -0
  99. package/src/helpers/getQuartiles.ts +30 -0
  100. package/src/helpers/handleChartAriaLabels.ts +19 -0
  101. package/src/helpers/handleLineType.ts +18 -0
  102. package/src/helpers/lineOptions.ts +18 -0
  103. package/src/helpers/sort.ts +7 -0
  104. package/src/helpers/tests/computeMarginBottom.test.ts +20 -0
  105. package/src/hooks/useBarChart.js +72 -7
  106. package/src/hooks/useColorScale.ts +50 -0
  107. package/src/hooks/{useMinMax.js → useMinMax.ts} +75 -23
  108. package/src/hooks/{useRightAxis.js → useRightAxis.ts} +10 -2
  109. package/src/hooks/{useScales.js → useScales.ts} +64 -17
  110. package/src/hooks/{useTooltip.jsx → useTooltip.tsx} +84 -55
  111. package/src/scss/main.scss +70 -38
  112. package/src/types/ChartConfig.ts +178 -0
  113. package/src/types/ChartContext.ts +54 -0
  114. package/src/types/ForestPlot.ts +53 -0
  115. package/examples/feature/scatterplot/scatterplot-continuous.csv +0 -17
  116. package/src/ConfigContext.jsx +0 -5
  117. package/src/components/BarChart.StackedVertical.jsx +0 -95
  118. package/src/components/BarChart.jsx +0 -30
  119. package/src/components/ForestPlot.jsx +0 -191
  120. package/src/components/Legend.jsx +0 -277
  121. package/src/scss/LinearChart.scss +0 -0
  122. package/src/scss/editor-panel.scss +0 -745
  123. package/src/scss/legend.scss +0 -206
  124. package/src/scss/mixins.scss +0 -0
  125. 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 '../ConfigContext'
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,3 @@
1
+ export type PanelProps = {
2
+ name: string
3
+ }
@@ -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
+ }