@cdc/chart 4.25.8 → 4.25.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (145) hide show
  1. package/.claude/settings.local.json +9 -0
  2. package/dist/{cdcchart-1a1724a1.es.js → cdcchart-dgT_1dIT.es.js} +136 -151
  3. package/dist/cdcchart.js +44236 -40355
  4. package/examples/feature/__data__/planet-example-data.json +0 -30
  5. package/examples/feature/boxplot/valid-boxplot.csv +38 -17
  6. package/examples/grouped-bar-test.json +400 -0
  7. package/examples/private/DEV-11825.json +573 -0
  8. package/examples/private/d.json +382 -0
  9. package/examples/private/example-2.json +49784 -0
  10. package/examples/private/f2.json +1 -0
  11. package/examples/private/f4.json +1577 -0
  12. package/examples/private/forecast.json +1180 -0
  13. package/examples/private/lollipop.json +468 -0
  14. package/examples/private/na.json +913 -0
  15. package/examples/private/new.json +48756 -0
  16. package/examples/private/pie-chart-legend.json +904 -0
  17. package/examples/private/test-data.csv +28 -0
  18. package/examples/suppressed_tooltip.json +480 -0
  19. package/index.html +2 -133
  20. package/package.json +25 -7
  21. package/src/CdcChart.tsx +9 -13
  22. package/src/CdcChartComponent.tsx +403 -92
  23. package/src/_stories/Chart.Anchors.stories.tsx +2 -2
  24. package/src/_stories/Chart.BoxPlot.stories.tsx +1 -1
  25. package/src/_stories/Chart.CI.stories.tsx +1 -1
  26. package/src/_stories/Chart.Combo.stories.tsx +18 -0
  27. package/src/_stories/Chart.CustomColors.stories.tsx +1 -1
  28. package/src/_stories/Chart.DynamicSeries.stories.tsx +2 -2
  29. package/src/_stories/Chart.Filters.stories.tsx +2 -2
  30. package/src/_stories/Chart.Forecast.stories.tsx +36 -0
  31. package/src/_stories/Chart.HTMLInDataTable.stories.tsx +520 -0
  32. package/src/_stories/Chart.Legend.Gradient.stories.tsx +2 -2
  33. package/src/_stories/Chart.Patterns.stories.tsx +20 -0
  34. package/src/_stories/Chart.PreserveDecimals.stories.tsx +220 -0
  35. package/src/_stories/Chart.ScatterPlot.stories.tsx +1 -1
  36. package/src/_stories/Chart.SmallMultiples.stories.tsx +47 -0
  37. package/src/_stories/Chart.stories.tsx +8 -5
  38. package/src/_stories/Chart.tooltip.stories.tsx +1 -1
  39. package/src/_stories/ChartAnnotation.stories.tsx +7 -4
  40. package/src/_stories/ChartAxisLabels.stories.tsx +2 -2
  41. package/src/_stories/ChartAxisTitles.stories.tsx +2 -2
  42. package/src/_stories/ChartBar.Editor.stories.tsx +3580 -0
  43. package/src/_stories/ChartEditor.Editor.stories.tsx +658 -0
  44. package/src/_stories/ChartEditor.stories.tsx +59 -60
  45. package/src/_stories/ChartLine.Suppression.stories.tsx +1 -1
  46. package/src/_stories/ChartLine.Symbols.stories.tsx +1 -1
  47. package/src/_stories/ChartPrefixSuffix.stories.tsx +2 -2
  48. package/src/_stories/_mock/combo.json +451 -0
  49. package/src/_stories/_mock/editor-test-configs.json +376 -0
  50. package/src/_stories/_mock/editor-test-datasets.json +477 -0
  51. package/src/_stories/_mock/editor-tests/bar-chart-editor-test.json +255 -0
  52. package/src/_stories/_mock/editor-tests/bar-chart-general-test.json +267 -0
  53. package/src/_stories/_mock/editor-tests/bar-chart-test.json +237 -0
  54. package/src/_stories/_mock/forecast_combo_with_gaps.json +913 -0
  55. package/src/_stories/_mock/pie_config.json +257 -62
  56. package/src/_stories/_mock/small_multiples/small_multiples_bars.json +1944 -0
  57. package/src/_stories/_mock/small_multiples/small_multiples_big_data_bars.json +1114 -0
  58. package/src/_stories/_mock/small_multiples/small_multiples_lines.json +2646 -0
  59. package/src/_stories/_mock/small_multiples/small_multiples_lines_colors.json +1305 -0
  60. package/src/_stories/_mock/small_multiples/small_multiples_stacked_bars.json +1936 -0
  61. package/src/_stories/_mock/stacked-pattern-test.json +520 -0
  62. package/src/components/Annotations/components/AnnotationDraggable.tsx +1 -0
  63. package/src/components/Annotations/components/AnnotationDropdown.tsx +1 -1
  64. package/src/components/Annotations/components/findNearestDatum.ts +6 -41
  65. package/src/components/AreaChart/components/AreaChart.Stacked.jsx +10 -6
  66. package/src/components/AreaChart/index.tsx +1 -2
  67. package/src/components/BarChart/components/BarChart.Horizontal.tsx +161 -22
  68. package/src/components/BarChart/components/BarChart.StackedHorizontal.tsx +138 -5
  69. package/src/components/BarChart/components/BarChart.StackedVertical.tsx +215 -73
  70. package/src/components/BarChart/components/BarChart.Vertical.tsx +155 -22
  71. package/src/components/BarChart/helpers/index.ts +43 -4
  72. package/src/components/BarChart/helpers/lollipopColors.ts +27 -0
  73. package/src/components/BarChart/helpers/useBarChart.ts +25 -3
  74. package/src/components/BoxPlot/BoxPlot.Vertical.tsx +2 -1
  75. package/src/components/BoxPlot/helpers/index.ts +3 -3
  76. package/src/components/Brush/BrushChart.tsx +1 -1
  77. package/src/components/DeviationBar.jsx +9 -6
  78. package/src/components/EditorPanel/EditorPanel.tsx +563 -229
  79. package/src/components/EditorPanel/EditorPanelContext.ts +3 -0
  80. package/src/components/EditorPanel/components/Panels/Panel.Annotate.tsx +96 -111
  81. package/src/components/EditorPanel/components/Panels/Panel.General.tsx +19 -1
  82. package/src/components/EditorPanel/components/Panels/Panel.PatternSettings.tsx +461 -0
  83. package/src/components/EditorPanel/components/Panels/Panel.Series.tsx +80 -67
  84. package/src/components/EditorPanel/components/Panels/Panel.SmallMultiples.tsx +422 -0
  85. package/src/components/EditorPanel/components/Panels/Panel.Visual.tsx +188 -139
  86. package/src/components/EditorPanel/components/Panels/index.tsx +5 -1
  87. package/src/components/EditorPanel/components/Panels/panelVisual.styles.css +0 -8
  88. package/src/components/EditorPanel/editor-panel.scss +0 -20
  89. package/src/components/EditorPanel/helpers/updateFieldRankByValue.ts +49 -48
  90. package/src/components/EditorPanel/useEditorPermissions.ts +7 -15
  91. package/src/components/Forecasting/Forecasting.tsx +175 -27
  92. package/src/components/ForestPlot/ForestPlot.tsx +11 -7
  93. package/src/components/ForestPlot/ForestPlotProps.ts +1 -1
  94. package/src/components/Legend/Legend.Component.tsx +114 -14
  95. package/src/components/Legend/helpers/createFormatLabels.tsx +230 -171
  96. package/src/components/Legend/helpers/getLegendClasses.ts +0 -1
  97. package/src/components/LegendWrapper.tsx +1 -1
  98. package/src/components/LineChart/LineChartProps.ts +0 -3
  99. package/src/components/LineChart/components/LineChart.Circle.tsx +2 -2
  100. package/src/components/LineChart/helpers.ts +1 -1
  101. package/src/components/LineChart/index.tsx +38 -15
  102. package/src/components/LinearChart.tsx +96 -84
  103. package/src/components/PairedBarChart.jsx +6 -4
  104. package/src/components/PieChart/PieChart.tsx +170 -54
  105. package/src/components/Regions/components/Regions.tsx +3 -24
  106. package/src/components/Sankey/components/Sankey.tsx +7 -1
  107. package/src/components/Sankey/types/index.ts +1 -1
  108. package/src/components/ScatterPlot/ScatterPlot.jsx +32 -4
  109. package/src/components/SmallMultiples/SmallMultipleTile.tsx +198 -0
  110. package/src/components/SmallMultiples/SmallMultiples.css +32 -0
  111. package/src/components/SmallMultiples/SmallMultiples.tsx +271 -0
  112. package/src/components/SmallMultiples/index.ts +2 -0
  113. package/src/data/initial-state.js +327 -293
  114. package/src/helpers/buildForecastPaletteMappings.ts +112 -0
  115. package/src/helpers/buildForecastPaletteOptions.ts +71 -0
  116. package/src/helpers/getColorScale.ts +82 -8
  117. package/src/{hooks/useMinMax.ts → helpers/getMinMax.ts} +14 -7
  118. package/src/helpers/getNewRuntime.ts +1 -1
  119. package/src/helpers/getTransformedData.ts +1 -1
  120. package/src/helpers/getYAxisAutoPadding.ts +53 -0
  121. package/src/helpers/smallMultiplesHelpers.ts +529 -0
  122. package/src/hooks/useChartHoverAnalytics.tsx +44 -0
  123. package/src/hooks/useProgrammaticTooltip.ts +96 -0
  124. package/src/hooks/useReduceData.ts +105 -70
  125. package/src/hooks/useScales.ts +88 -34
  126. package/src/hooks/useSmallMultipleSynchronization.ts +59 -0
  127. package/src/hooks/useTooltip.tsx +116 -29
  128. package/src/index.jsx +0 -2
  129. package/src/scss/main.scss +13 -80
  130. package/src/store/chart.actions.ts +2 -0
  131. package/src/store/chart.reducer.ts +5 -1
  132. package/src/test/CdcChart.test.jsx +8 -3
  133. package/src/types/ChartConfig.ts +53 -11
  134. package/src/types/ChartContext.ts +4 -0
  135. package/vite.config.js +1 -1
  136. package/vitest.config.ts +16 -0
  137. package/src/_stories/_mock/pie_data.json +0 -218
  138. package/src/components/AreaChart/components/AreaChart.jsx +0 -109
  139. package/src/coreStyles_chart.scss +0 -3
  140. package/src/helpers/configHelpers.ts +0 -28
  141. package/src/helpers/generateColorsArray.ts +0 -8
  142. package/src/helpers/sort.ts +0 -7
  143. package/src/hooks/useActiveElement.js +0 -19
  144. package/src/hooks/useChartClasses.js +0 -41
  145. package/src/hooks/useColorPalette.js +0 -76
@@ -23,6 +23,9 @@ export type EditorPanelContext = {
23
23
  isPaletteReversed?: boolean
24
24
  handleRemoveHighlightedBar?: Function
25
25
  setLollipopShape?: Function
26
+ handlePaletteSelection?: (palette: string) => void
27
+ handleTwoColorPaletteSelection?: (palette: string) => void
28
+ handleForecastPaletteSelection?: (palette: string, seriesIndex: number, stageIndex: number) => void
26
29
  }
27
30
 
28
31
  const EditorPanelContext = createContext<EditorPanelContext>(null)
@@ -4,6 +4,7 @@ import ConfigContext from '../../../../ConfigContext.js'
4
4
  // CDC Core
5
5
  import Accordion from '@cdc/core/components/ui/Accordion'
6
6
  import Button from '@cdc/core/components/elements/Button'
7
+ import { CheckBox, Select } from '@cdc/core/components/EditorPanel/Inputs'
7
8
  import _ from 'lodash'
8
9
 
9
10
  // types
@@ -14,6 +15,29 @@ import './../panels.scss'
14
15
  const PanelAnnotate: React.FC<PanelProps> = props => {
15
16
  const { updateConfig, config, svgRef } = useContext(ConfigContext)
16
17
 
18
+ const updateField = (section, subsection, fieldName, value) => {
19
+ if (subsection) {
20
+ updateConfig({
21
+ ...config,
22
+ [section]: {
23
+ ...config[section],
24
+ [subsection]: {
25
+ ...config[section][subsection],
26
+ [fieldName]: value
27
+ }
28
+ }
29
+ })
30
+ } else {
31
+ updateConfig({
32
+ ...config,
33
+ [section]: {
34
+ ...config[section],
35
+ [fieldName]: value
36
+ }
37
+ })
38
+ }
39
+ }
40
+
17
41
  const handleAnnotationUpdate = (value, property, index) => {
18
42
  const svgContainer = document.querySelector('.chart-container > svg')?.getBoundingClientRect()
19
43
  const newSvgDims = [svgContainer?.width, svgContainer?.height]
@@ -67,8 +91,8 @@ const PanelAnnotate: React.FC<PanelProps> = props => {
67
91
  config.xAxis.type === 'date'
68
92
  ? new Date(config?.data?.[0]?.[config.xAxis.dataKey]).getTime()
69
93
  : config.xAxis.type === 'categorical'
70
- ? '1/15/2016'
71
- : '',
94
+ ? '1/15/2016'
95
+ : '',
72
96
  yKey: '',
73
97
  dx: 20,
74
98
  dy: -20,
@@ -96,22 +120,14 @@ const PanelAnnotate: React.FC<PanelProps> = props => {
96
120
  return (
97
121
  <Accordion key={props.name}>
98
122
  <Accordion.Section title={props.name} key={props.name}>
99
- <label key={`key-1`}>
100
- Show Annotation Dropdown
101
- <input
102
- type='checkbox'
103
- checked={config?.general?.showAnnotationDropdown || false}
104
- onChange={e => {
105
- updateConfig({
106
- ...config,
107
- general: {
108
- ...config.general,
109
- showAnnotationDropdown: e.target.checked
110
- }
111
- })
112
- }}
113
- />
114
- </label>
123
+ <CheckBox
124
+ value={config?.general?.showAnnotationDropdown || false}
125
+ section='general'
126
+ subsection={null}
127
+ fieldName='showAnnotationDropdown'
128
+ label='Show Annotation Dropdown'
129
+ updateField={updateField}
130
+ />
115
131
 
116
132
  {config.general.showAnnotationDropdown && (
117
133
  <label key={`key-2`}>
@@ -164,61 +180,53 @@ const PanelAnnotate: React.FC<PanelProps> = props => {
164
180
  />
165
181
  </label>
166
182
 
167
- <label>
168
- Edit Subject
169
- <input
170
- type='checkbox'
171
- checked={config?.annotations[index]?.edit?.subject || false}
172
- onChange={e => {
173
- const updatedAnnotations = _.cloneDeep(config?.annotations)
174
- updatedAnnotations[index].edit.subject = e.target.checked
175
- updateConfig({
176
- ...config,
177
- annotations: updatedAnnotations
178
- })
179
- }}
180
- />
181
- </label>
182
- <label>
183
- Edit Label
184
- <input
185
- type='checkbox'
186
- checked={config?.annotations[index]?.edit?.label || false}
187
- onChange={e => {
188
- const updatedAnnotations = _.cloneDeep(config?.annotations)
189
- updatedAnnotations[index].edit.label = e.target.checked
190
- updateConfig({
191
- ...config,
192
- annotations: updatedAnnotations
193
- })
194
- }}
195
- />
196
- </label>
183
+ <CheckBox
184
+ value={config?.annotations[index]?.edit?.subject || false}
185
+ section='annotations'
186
+ subsection={null}
187
+ fieldName={`${index}.edit.subject`}
188
+ label='Edit Subject'
189
+ updateField={(section, subsection, fieldName, value) => {
190
+ const updatedAnnotations = _.cloneDeep(config?.annotations)
191
+ updatedAnnotations[index].edit.subject = value
192
+ updateConfig({
193
+ ...config,
194
+ annotations: updatedAnnotations
195
+ })
196
+ }}
197
+ />
198
+ <CheckBox
199
+ value={config?.annotations[index]?.edit?.label || false}
200
+ section='annotations'
201
+ subsection={null}
202
+ fieldName={`${index}.edit.label`}
203
+ label='Edit Label'
204
+ updateField={(section, subsection, fieldName, value) => {
205
+ const updatedAnnotations = _.cloneDeep(config?.annotations)
206
+ updatedAnnotations[index].edit.label = value
207
+ updateConfig({
208
+ ...config,
209
+ annotations: updatedAnnotations
210
+ })
211
+ }}
212
+ />
197
213
 
198
- <label>
199
- Connection Type:
200
- <select
201
- key='annotation-connection-type'
202
- onChange={e => {
203
- const updatedAnnotations = _.cloneDeep(config?.annotations)
204
- updatedAnnotations[index].connectionType = e.target.value
205
- updateConfig({
206
- ...config,
207
- annotations: updatedAnnotations
208
- })
209
- }}
210
- value={config?.annotations[index]?.connectionType}
211
- >
212
- <option key='select' value='select'>
213
- Select
214
- </option>
215
- {['curve', 'line', 'elbow', 'none'].map((side, index) => (
216
- <option key={side} value={side}>
217
- {side}
218
- </option>
219
- ))}
220
- </select>
221
- </label>
214
+ <Select
215
+ label='Connection Type:'
216
+ value={config?.annotations[index]?.connectionType}
217
+ options={['Select', 'curve', 'line', 'elbow', 'none']}
218
+ section='annotations'
219
+ subsection={null}
220
+ fieldName='connectionType'
221
+ updateField={(section, subsection, fieldName, value) => {
222
+ const updatedAnnotations = _.cloneDeep(config?.annotations)
223
+ updatedAnnotations[index].connectionType = value
224
+ updateConfig({
225
+ ...config,
226
+ annotations: updatedAnnotations
227
+ })
228
+ }}
229
+ />
222
230
 
223
231
  {annotation.connectionType === 'curve' && (
224
232
  <>
@@ -243,45 +251,22 @@ const PanelAnnotate: React.FC<PanelProps> = props => {
243
251
  </>
244
252
  )}
245
253
 
246
- {/* <label>
247
- Connection Location:
248
- <select
249
- onChange={e => {
250
- const updatedAnnotations = _.cloneDeep(config?.annotations)
251
- updatedAnnotations[index].connectionLocation = e.target.value
252
- updateConfig({
253
- ...config,
254
- annotations: updatedAnnotations
255
- })
256
- }}
257
- >
258
- {['auto', 'left', 'top', 'bottom', 'right'].map((side, index) => (
259
- <option key={side} value={side}>
260
- {side}
261
- </option>
262
- ))}
263
- </select>
264
- </label> */}
265
-
266
- <label>
267
- Marker
268
- <select
269
- key='annotation-marker'
270
- value={annotation.marker}
271
- onChange={e => {
272
- const updatedAnnotations = _.cloneDeep(config?.annotations)
273
- updatedAnnotations[index].marker = e.target.value
274
- updateConfig({
275
- ...config,
276
- annotations: updatedAnnotations
277
- })
278
- }}
279
- >
280
- {['arrow', 'circle'].map((column, columnIndex) => {
281
- return <option key={`col-${columnIndex}`}>{column}</option>
282
- })}
283
- </select>
284
- </label>
254
+ <Select
255
+ label='Marker'
256
+ value={annotation.marker}
257
+ options={['arrow', 'circle']}
258
+ section='annotations'
259
+ subsection={null}
260
+ fieldName='marker'
261
+ updateField={(section, subsection, fieldName, value) => {
262
+ const updatedAnnotations = _.cloneDeep(config?.annotations)
263
+ updatedAnnotations[index].marker = value
264
+ updateConfig({
265
+ ...config,
266
+ annotations: updatedAnnotations
267
+ })
268
+ }}
269
+ />
285
270
 
286
271
  <Button className='btn btn-danger full-width' onClick={() => handleRemoveAnnotation(index)}>
287
272
  Delete Annotation
@@ -21,7 +21,7 @@ import ConfigContext from '../../../../ConfigContext.js'
21
21
  import { PanelProps } from '../PanelProps'
22
22
 
23
23
  const PanelGeneral: FC<PanelProps> = props => {
24
- const { config } = useContext(ConfigContext)
24
+ const { config, updateConfig } = useContext(ConfigContext)
25
25
  const { updateField } = useEditorPanelContext()
26
26
  const {
27
27
  enabledChartTypes,
@@ -62,6 +62,24 @@ const PanelGeneral: FC<PanelProps> = props => {
62
62
  label='Chart Type'
63
63
  updateField={updateField}
64
64
  options={enabledChartTypes}
65
+ onChange={event => {
66
+ const newVisType = event.target.value
67
+
68
+ updateField(null, null, 'visualizationType', newVisType)
69
+
70
+ if (newVisType === 'Forecasting' && config.xAxis.type === 'categorical') {
71
+ updateConfig({
72
+ ...config,
73
+ visualizationType: newVisType,
74
+ xAxis: {
75
+ ...config.xAxis,
76
+ type: 'date',
77
+ dateParseFormat: config.xAxis.dateParseFormat || '%Y-%m-%d',
78
+ dateDisplayFormat: config.xAxis.dateDisplayFormat || '%Y-%m-%d'
79
+ }
80
+ })
81
+ }
82
+ }}
65
83
  />
66
84
  )}
67
85
  {visSupportsChartHeight() && config.orientation === 'vertical' && (