@cdc/chart 4.25.10 → 4.26.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 (135) hide show
  1. package/dist/{cdcchart-1a1724a1.es.js → cdcchart-dgT_1dIT.es.js} +136 -151
  2. package/dist/cdcchart.js +44003 -43518
  3. package/examples/feature/__data__/planet-example-data.json +1 -1
  4. package/examples/feature/boxplot/valid-boxplot.csv +38 -17
  5. package/examples/feature/pie/planet-pie-example-config.json +48 -2
  6. package/examples/private/DEV-11825.json +573 -0
  7. package/examples/private/DEV-12100.json +1303 -0
  8. package/examples/private/cat-y.json +1235 -0
  9. package/examples/private/data-points.json +228 -0
  10. package/examples/private/height.json +3915 -0
  11. package/examples/private/links.json +569 -0
  12. package/examples/private/na.json +913 -0
  13. package/examples/private/quadrant.txt +30 -0
  14. package/examples/private/test-data.csv +28 -0
  15. package/examples/private/test-forecast.json +5510 -0
  16. package/examples/private/warming-stripe-test.json +2578 -0
  17. package/examples/private/warming-stripes.json +4763 -0
  18. package/examples/tech-adoption-with-links.json +560 -0
  19. package/index.html +16 -140
  20. package/package.json +6 -5
  21. package/preview.html +1616 -0
  22. package/src/CdcChart.tsx +8 -11
  23. package/src/CdcChartComponent.tsx +329 -124
  24. package/src/_stories/Chart.Combo.stories.tsx +18 -0
  25. package/src/_stories/Chart.Forecast.stories.tsx +36 -0
  26. package/src/_stories/Chart.HTMLInDataTable.stories.tsx +520 -0
  27. package/src/_stories/Chart.Patterns.stories.tsx +2 -1
  28. package/src/_stories/Chart.PreserveDecimals.stories.tsx +220 -0
  29. package/src/_stories/Chart.Regions.Categorical.stories.tsx +148 -0
  30. package/src/_stories/Chart.Regions.DateScale.stories.tsx +197 -0
  31. package/src/_stories/Chart.Regions.DateTimeScale.stories.tsx +297 -0
  32. package/src/_stories/Chart.SmallMultiples.stories.tsx +47 -0
  33. package/src/_stories/Chart.stories.tsx +8 -0
  34. package/src/_stories/ChartAnnotation.stories.tsx +6 -3
  35. package/src/_stories/ChartBar.Editor.stories.tsx +3585 -0
  36. package/src/_stories/ChartBrush.Editor.stories.tsx +295 -0
  37. package/src/_stories/ChartBrush.stories.tsx +50 -0
  38. package/src/_stories/ChartEditor.Editor.stories.tsx +656 -0
  39. package/src/_stories/ChartEditor.stories.tsx +1 -2
  40. package/src/_stories/TechAdoptionWithLinks.stories.tsx +27 -0
  41. package/src/_stories/_mock/brush_enabled.json +326 -0
  42. package/src/_stories/_mock/brush_mock.json +2 -69
  43. package/src/_stories/_mock/combo.json +451 -0
  44. package/src/_stories/_mock/editor-test-configs.json +376 -0
  45. package/src/_stories/_mock/editor-test-datasets.json +477 -0
  46. package/src/_stories/_mock/editor-tests/bar-chart-editor-test.json +255 -0
  47. package/src/_stories/_mock/editor-tests/bar-chart-general-test.json +267 -0
  48. package/src/_stories/_mock/editor-tests/bar-chart-test.json +237 -0
  49. package/src/_stories/_mock/forecast_combo_with_gaps.json +913 -0
  50. package/src/_stories/_mock/horizontal-bars-dynamic-y-axis.json +413 -0
  51. package/src/_stories/_mock/pie_config.json +257 -62
  52. package/src/_stories/_mock/small_multiples/small_multiples_bars.json +1944 -0
  53. package/src/_stories/_mock/small_multiples/small_multiples_big_data_bars.json +1114 -0
  54. package/src/_stories/_mock/small_multiples/small_multiples_lines.json +2646 -0
  55. package/src/_stories/_mock/small_multiples/small_multiples_lines_colors.json +1305 -0
  56. package/src/_stories/_mock/small_multiples/small_multiples_stacked_bars.json +1936 -0
  57. package/src/components/Annotations/components/findNearestDatum.ts +6 -41
  58. package/src/components/AreaChart/components/AreaChart.Stacked.jsx +10 -7
  59. package/src/components/AreaChart/index.tsx +1 -2
  60. package/src/components/Axis/Categorical.Axis.tsx +6 -7
  61. package/src/components/BarChart/components/BarChart.Horizontal.tsx +181 -27
  62. package/src/components/BarChart/components/BarChart.StackedHorizontal.tsx +3 -1
  63. package/src/components/BarChart/components/BarChart.StackedVertical.tsx +1 -0
  64. package/src/components/BarChart/components/BarChart.Vertical.tsx +8 -9
  65. package/src/components/BarChart/components/context.tsx +1 -0
  66. package/src/components/BarChart/helpers/useBarChart.ts +14 -2
  67. package/src/components/BoxPlot/helpers/index.ts +3 -3
  68. package/src/components/Brush/BrushSelector.tsx +1258 -0
  69. package/src/components/Brush/MiniChartPreview.tsx +283 -0
  70. package/src/components/DeviationBar.jsx +9 -7
  71. package/src/components/EditorPanel/EditorPanel.tsx +2720 -2586
  72. package/src/components/EditorPanel/components/Panels/Panel.Annotate.tsx +96 -111
  73. package/src/components/EditorPanel/components/Panels/Panel.ForestPlotSettings.tsx +56 -34
  74. package/src/components/EditorPanel/components/Panels/Panel.General.tsx +76 -31
  75. package/src/components/EditorPanel/components/Panels/Panel.PatternSettings.tsx +104 -55
  76. package/src/components/EditorPanel/components/Panels/Panel.Series.tsx +54 -49
  77. package/src/components/EditorPanel/components/Panels/Panel.SmallMultiples.tsx +427 -0
  78. package/src/components/EditorPanel/components/Panels/Panel.Visual.tsx +96 -48
  79. package/src/components/EditorPanel/components/Panels/index.tsx +3 -1
  80. package/src/components/EditorPanel/editor-panel.scss +0 -20
  81. package/src/components/EditorPanel/useEditorPermissions.ts +36 -31
  82. package/src/components/Forecasting/Forecasting.tsx +139 -21
  83. package/src/components/Legend/Legend.Component.tsx +16 -9
  84. package/src/components/Legend/Legend.tsx +3 -2
  85. package/src/components/Legend/helpers/createFormatLabels.tsx +325 -176
  86. package/src/components/Legend/helpers/getLegendClasses.ts +0 -1
  87. package/src/components/Legend/helpers/index.ts +10 -6
  88. package/src/components/LineChart/LineChartProps.ts +0 -3
  89. package/src/components/LineChart/helpers.ts +1 -1
  90. package/src/components/LineChart/index.tsx +36 -13
  91. package/src/components/LinearChart.tsx +559 -499
  92. package/src/components/PairedBarChart.jsx +20 -3
  93. package/src/components/Regions/components/Regions.tsx +366 -144
  94. package/src/components/Sankey/types/index.ts +1 -1
  95. package/src/components/ScatterPlot/ScatterPlot.jsx +2 -2
  96. package/src/components/SmallMultiples/SmallMultipleTile.tsx +202 -0
  97. package/src/components/SmallMultiples/SmallMultiples.css +32 -0
  98. package/src/components/SmallMultiples/SmallMultiples.tsx +271 -0
  99. package/src/components/SmallMultiples/index.ts +2 -0
  100. package/src/components/WarmingStripes/WarmingStripes.tsx +160 -0
  101. package/src/components/WarmingStripes/WarmingStripesGradientLegend.css +35 -0
  102. package/src/components/WarmingStripes/WarmingStripesGradientLegend.tsx +104 -0
  103. package/src/components/WarmingStripes/index.tsx +3 -0
  104. package/src/data/initial-state.js +16 -2
  105. package/src/helpers/buildForecastPaletteOptions.ts +0 -38
  106. package/src/helpers/calculateHorizontalBarCategoryLabelWidth.ts +57 -0
  107. package/src/helpers/getColorScale.ts +10 -0
  108. package/src/{hooks/useMinMax.ts → helpers/getMinMax.ts} +26 -14
  109. package/src/helpers/getYAxisAutoPadding.ts +53 -0
  110. package/src/helpers/sizeHelpers.ts +0 -20
  111. package/src/helpers/smallMultiplesHelpers.ts +529 -0
  112. package/src/hooks/useChartHoverAnalytics.tsx +10 -9
  113. package/src/hooks/useProgrammaticTooltip.ts +96 -0
  114. package/src/hooks/useScales.ts +98 -34
  115. package/src/hooks/useSmallMultipleSynchronization.ts +59 -0
  116. package/src/hooks/useTooltip.tsx +91 -25
  117. package/src/scss/DataTable.scss +0 -4
  118. package/src/scss/main.scss +18 -83
  119. package/src/store/chart.actions.ts +2 -0
  120. package/src/store/chart.reducer.ts +4 -0
  121. package/src/test/CdcChart.test.jsx +1 -1
  122. package/src/types/ChartConfig.ts +27 -6
  123. package/src/types/ChartContext.ts +3 -0
  124. package/src/types/Label.ts +1 -0
  125. package/src/utils/analyticsTracking.ts +19 -0
  126. package/LICENSE +0 -201
  127. package/src/_stories/_mock/pie_data.json +0 -218
  128. package/src/components/AreaChart/components/AreaChart.jsx +0 -109
  129. package/src/components/Brush/BrushChart.tsx +0 -128
  130. package/src/components/Brush/BrushController.tsx +0 -71
  131. package/src/components/Brush/types.tsx +0 -8
  132. package/src/components/BrushChart.tsx +0 -223
  133. package/src/helpers/sort.ts +0 -7
  134. package/src/hooks/useActiveElement.js +0 -19
  135. package/src/hooks/useChartClasses.js +0 -41
@@ -10,6 +10,7 @@ import Tooltip from '@cdc/core/components/ui/Tooltip'
10
10
  import Icon from '@cdc/core/components/ui/Icon'
11
11
  import Button from '@cdc/core/components/elements/Button'
12
12
  import Alert from '@cdc/core/components/Alert'
13
+ import { Select } from '@cdc/core/components/EditorPanel/Inputs'
13
14
  import ConfigContext from '../../../../ConfigContext'
14
15
  import { ChartContext } from '../../../../types/ChartContext'
15
16
  import { PanelProps } from '../PanelProps'
@@ -89,17 +90,22 @@ const PanelPatternSettings: FC<PanelProps> = props => {
89
90
  }
90
91
 
91
92
  // Checks contrast and logs warning if needed
92
- const checkAndLogContrast = (fill: string, patternColor: string, dataValue: string, dataKey: string): boolean => {
93
- if (!fill || !patternColor) return true // Default to true if colors are missing
93
+ const checkAndLogContrast = (
94
+ patternColor: string,
95
+ backgroundColor: string,
96
+ dataValue: string,
97
+ dataKey: string
98
+ ): boolean => {
99
+ if (!backgroundColor || !patternColor) return true // Default to true if colors are missing
94
100
 
95
- const contrastCheck = checkColorContrast(fill, patternColor)
101
+ const contrastCheck = checkColorContrast(patternColor, backgroundColor)
96
102
 
97
103
  if (!contrastCheck) {
98
104
  console.error(
99
105
  `COVE: pattern contrast check failed for ${dataValue} in ${dataKey} with:
100
106
  pattern color: ${patternColor}
101
- background color: ${fill}
102
- contrast: ${getColorContrast(fill, patternColor)}`
107
+ background color: ${backgroundColor}
108
+ contrast: ${getColorContrast(patternColor, backgroundColor)}`
103
109
  )
104
110
  }
105
111
 
@@ -108,7 +114,9 @@ const PanelPatternSettings: FC<PanelProps> = props => {
108
114
 
109
115
  // Perform contrast check for a specific pattern against actual bar colors
110
116
  const performContrastCheck = (patternKey: string, patternColor: string) => {
111
- if (!patternColor || patternColor === '') return true
117
+ if (!patternColor || patternColor === '') {
118
+ return true
119
+ }
112
120
 
113
121
  // Get the actual bar colors that the pattern will be overlaid on
114
122
  let seriesColors: string[] = []
@@ -138,8 +146,8 @@ const PanelPatternSettings: FC<PanelProps> = props => {
138
146
  const contrastResults: Array<{ color: string; passes: boolean; ratio: number | false }> = []
139
147
 
140
148
  seriesColors.forEach((barColor, index) => {
141
- const contrastPasses = checkAndLogContrast(barColor, patternColor, patternKey, `series-${index}`)
142
- const contrastRatio = getColorContrast(barColor, patternColor)
149
+ const contrastPasses = checkAndLogContrast(patternColor, barColor, patternKey, `series-${index}`)
150
+ const contrastRatio = getColorContrast(patternColor, barColor)
143
151
 
144
152
  contrastResults.push({
145
153
  color: barColor,
@@ -184,26 +192,48 @@ const PanelPatternSettings: FC<PanelProps> = props => {
184
192
  }
185
193
  }
186
194
 
187
- updateConfig({
195
+ const updatedConfig = {
188
196
  ...config,
189
197
  legend: {
190
198
  ...(config.legend || {}),
191
199
  patterns: newPatterns
200
+ },
201
+ runtime: {
202
+ ...config.runtime
192
203
  }
193
- })
204
+ }
205
+
206
+ // Check if all patterns pass and set error message
207
+ const allPatternsPass = Object.values(newPatterns).every((p: any) => p.contrastCheck !== false)
208
+ updatedConfig.runtime.editorErrorMessage = allPatternsPass
209
+ ? ''
210
+ : 'One or more patterns do not pass the WCAG 2.1 contrast ratio of 3:1.'
211
+
212
+ updateConfig(updatedConfig)
194
213
  }
195
214
 
196
215
  const handleRemovePattern = (patternKey: string) => {
197
216
  const newPatterns = { ...(legendCfg.patterns || {}) }
198
217
  delete newPatterns[patternKey]
199
218
 
200
- updateConfig({
219
+ const updatedConfig = {
201
220
  ...config,
202
221
  legend: {
203
222
  ...(config.legend || {}),
204
223
  patterns: newPatterns
224
+ },
225
+ runtime: {
226
+ ...config.runtime
205
227
  }
206
- })
228
+ }
229
+
230
+ // Check if all remaining patterns pass and clear error message if needed
231
+ const allPatternsPass = Object.values(newPatterns).every((p: any) => p.contrastCheck !== false)
232
+ if (allPatternsPass || Object.keys(newPatterns).length === 0) {
233
+ updatedConfig.runtime.editorErrorMessage = ''
234
+ }
235
+
236
+ updateConfig(updatedConfig)
207
237
  }
208
238
 
209
239
  const handlePatternKeyChange = (oldKey: string, newKey: string) => {
@@ -228,15 +258,33 @@ const PanelPatternSettings: FC<PanelProps> = props => {
228
258
  })
229
259
  }
230
260
 
261
+ const reviewColorContrast = (updatedConfig: any, patternKey: string) => {
262
+ // Re-check the contrast for the updated pattern
263
+ const pattern = updatedConfig.legend.patterns[patternKey]
264
+
265
+ if (pattern?.color) {
266
+ pattern.contrastCheck = performContrastCheck(patternKey, pattern.color)
267
+ }
268
+
269
+ // Update error message based on whether all patterns pass contrast checks
270
+ const allPatterns = Object.values(updatedConfig.legend.patterns || {})
271
+
272
+ const allPatternsPass = allPatterns.every((p: any) => p.contrastCheck !== false)
273
+
274
+ const errorMsg = allPatternsPass ? '' : 'One or more patterns do not pass the WCAG 2.1 contrast ratio of 3:1.'
275
+ // Set error message AFTER spreading runtime to avoid it being overwritten
276
+ updatedConfig.runtime.editorErrorMessage = errorMsg
277
+ }
278
+
231
279
  const handlePatternUpdate = (patternKey: string, field: string, value: any) => {
232
280
  const updatedPattern = {
233
281
  ...(legendCfg.patterns?.[patternKey] || {}),
234
282
  [field]: value
235
283
  }
236
284
 
237
- // Perform contrast check if color is being updated
238
- if (field === 'color') {
239
- updatedPattern.contrastCheck = performContrastCheck(patternKey, value)
285
+ // Clear dataValue if dataKey is being cleared or set to 'Select'
286
+ if (field === 'dataKey' && (value === 'Select' || value === '')) {
287
+ updatedPattern.dataValue = ''
240
288
  }
241
289
 
242
290
  const newPatterns = {
@@ -244,15 +292,27 @@ const PanelPatternSettings: FC<PanelProps> = props => {
244
292
  [patternKey]: updatedPattern
245
293
  }
246
294
 
247
- updateConfig({
295
+ const updatedConfig = {
248
296
  ...config,
249
297
  legend: {
250
298
  ...(config.legend || {}),
251
299
  patterns: newPatterns
300
+ },
301
+ runtime: {
302
+ ...config.runtime
252
303
  }
253
- })
304
+ }
305
+
306
+ // Perform contrast check whenever color changes (even if cleared)
307
+ if (field === 'color') {
308
+ reviewColorContrast(updatedConfig, patternKey)
309
+ }
310
+
311
+ updateConfig(updatedConfig)
254
312
  }
255
313
 
314
+ if (config.visualizationType === 'Warming Stripes') return
315
+
256
316
  return (
257
317
  <AccordionItem>
258
318
  <AccordionItemHeading>
@@ -294,19 +354,16 @@ const PanelPatternSettings: FC<PanelProps> = props => {
294
354
  />
295
355
  )}
296
356
 
297
- <label htmlFor={`pattern-datakey-${patternKey}`}>Data Key:</label>
298
- <select
299
- id={`pattern-datakey-${patternKey}`}
300
- value={p.dataKey || 'Select'}
301
- onChange={e => handlePatternUpdate(patternKey, 'dataKey', e.target.value)}
302
- >
303
- <option value='Select'>Select Data Key</option>
304
- {fieldOptions.map((option, index) => (
305
- <option value={option.value} key={index}>
306
- {option.label}
307
- </option>
308
- ))}
309
- </select>
357
+ <Select
358
+ label='Data Key:'
359
+ value={p.dataKey || ''}
360
+ options={fieldOptions}
361
+ initial='Select Data Key'
362
+ fieldName={`pattern-datakey-${patternKey}`}
363
+ updateField={(section, subsection, fieldName, value) =>
364
+ handlePatternUpdate(patternKey, 'dataKey', value)
365
+ }
366
+ />
310
367
 
311
368
  {p.dataKey && (
312
369
  <>
@@ -333,33 +390,25 @@ const PanelPatternSettings: FC<PanelProps> = props => {
333
390
  />
334
391
  </label>
335
392
 
336
- <label htmlFor={`pattern-type-${patternKey}`}>Pattern Type:</label>
337
- <select
338
- id={`pattern-type-${patternKey}`}
393
+ <Select
394
+ label='Pattern Type:'
339
395
  value={p.shape || 'circles'}
340
- onChange={e => handlePatternUpdate(patternKey, 'shape', e.target.value)}
341
- >
342
- {patternTypes.map((patternType, index) => (
343
- <option value={patternType.value} key={index}>
344
- {patternType.label}
345
- </option>
346
- ))}
347
- </select>
348
-
349
- <label htmlFor={`pattern-size-${patternKey}`}>Pattern Size:</label>
350
- <select
351
- id={`pattern-size-${patternKey}`}
396
+ options={patternTypes}
397
+ fieldName={`pattern-type-${patternKey}`}
398
+ updateField={(section, subsection, fieldName, value) =>
399
+ handlePatternUpdate(patternKey, 'shape', value)
400
+ }
401
+ />
402
+
403
+ <Select
404
+ label='Pattern Size:'
352
405
  value={getPatternSizeText(p.patternSize || 8)}
353
- onChange={e =>
354
- handlePatternUpdate(patternKey, 'patternSize', getPatternSizeNumeric(e.target.value))
406
+ options={patternSizes}
407
+ fieldName={`pattern-size-${patternKey}`}
408
+ updateField={(section, subsection, fieldName, value) =>
409
+ handlePatternUpdate(patternKey, 'patternSize', getPatternSizeNumeric(value))
355
410
  }
356
- >
357
- {patternSizes.map((size, index) => (
358
- <option value={size.value} key={index}>
359
- {size.label}
360
- </option>
361
- ))}
362
- </select>
411
+ />
363
412
 
364
413
  <div className='mt-3'>
365
414
  <label htmlFor={`pattern-color-${patternKey}`}>
@@ -380,7 +429,7 @@ const PanelPatternSettings: FC<PanelProps> = props => {
380
429
  </Tooltip>
381
430
  <input
382
431
  type='text'
383
- value={p.color || '#666666'}
432
+ value={p.color || ''}
384
433
  id={`pattern-color-${patternKey}`}
385
434
  onChange={e => handlePatternUpdate(patternKey, 'color', e.target.value)}
386
435
  placeholder='#666666'
@@ -2,7 +2,6 @@ import React, { useContext } from 'react'
2
2
  import ConfigContext from '../../../../ConfigContext'
3
3
 
4
4
  // Core
5
- import InputSelect from '@cdc/core/components/inputs/InputSelect'
6
5
  import Check from '@cdc/core/assets/icon-check.svg'
7
6
  import { approvedCurveTypes } from '@cdc/core/helpers/lineChartHelpers'
8
7
  import { colorPalettesChartV1, colorPalettesChartV2, sequentialPalettes } from '@cdc/core/data/colorPalettes'
@@ -98,12 +97,12 @@ const SeriesDropdownLineType = props => {
98
97
  })
99
98
 
100
99
  return (
101
- <InputSelect
100
+ <Select
102
101
  initial='Select an option'
103
102
  value={series.lineType ? series.lineType : 'curveLinear'}
104
103
  label='Series Line Type'
105
- onChange={event => {
106
- changeLineType(index, event.target.value)
104
+ updateField={(_section, _subsection, _fieldName, value) => {
105
+ changeLineType(index, value)
107
106
  }}
108
107
  options={options}
109
108
  />
@@ -118,35 +117,35 @@ const SeriesDropdownSeriesType = props => {
118
117
 
119
118
  const getOptions = () => {
120
119
  if (config.visualizationType === 'Combo') {
121
- return {
122
- Bar: 'Bar',
123
- Line: 'Line',
124
- 'dashed-sm': 'Small Dashed',
125
- 'dashed-md': 'Medium Dashed',
126
- 'dashed-lg': 'Large Dashed',
127
- 'Area Chart': 'Area Chart',
128
- Forecasting: 'Forecasting'
129
- }
120
+ return [
121
+ { value: 'Bar', label: 'Bar' },
122
+ { value: 'Line', label: 'Line' },
123
+ { value: 'dashed-sm', label: 'Small Dashed' },
124
+ { value: 'dashed-md', label: 'Medium Dashed' },
125
+ { value: 'dashed-lg', label: 'Large Dashed' },
126
+ { value: 'Area Chart', label: 'Area Chart' },
127
+ { value: 'Forecasting', label: 'Forecasting' }
128
+ ]
130
129
  }
131
130
  if (config.visualizationType === 'Line' || config.visualizationType === 'Bump Chart') {
132
- return {
133
- Line: 'Line',
134
- 'dashed-sm': 'Small Dashed',
135
- 'dashed-md': 'Medium Dashed',
136
- 'dashed-lg': 'Large Dashed'
137
- }
131
+ return [
132
+ { value: 'Line', label: 'Line' },
133
+ { value: 'dashed-sm', label: 'Small Dashed' },
134
+ { value: 'dashed-md', label: 'Medium Dashed' },
135
+ { value: 'dashed-lg', label: 'Large Dashed' }
136
+ ]
138
137
  }
139
138
  }
140
139
 
141
140
  // Allowable changes
142
141
  if (!['Line', 'Combo', 'Bump Chart'].includes(config.visualizationType)) return
143
142
  return (
144
- <InputSelect
143
+ <Select
145
144
  initial='Select an option'
146
145
  value={series.type}
147
146
  label='Series Type'
148
- onChange={event => {
149
- updateSeries(index, event.target.value, 'type')
147
+ updateField={(_section, _subsection, _fieldName, value) => {
148
+ updateSeries(index, value, 'type')
150
149
  }}
151
150
  options={getOptions()}
152
151
  />
@@ -162,13 +161,13 @@ const SeriesDropdownForecastingStage = props => {
162
161
  // Only combo charts are allowed to have different options
163
162
 
164
163
  return (
165
- <InputSelect
164
+ <Select
166
165
  initial='Select an option'
167
166
  value={series.stageColumn}
168
167
  label='Add Forecasting Stages'
169
- onChange={e => {
168
+ updateField={(_section, _subsection, _fieldName, value) => {
170
169
  let stageObjects = []
171
- let tempGroups = new Set(rawData?.map(item => item[e.target.value])) // [estimate, forecast, etc.]
170
+ let tempGroups = new Set(rawData?.map(item => item[value])) // [estimate, forecast, etc.]
172
171
  tempGroups = Array.from(tempGroups) // convert set to array
173
172
 
174
173
  tempGroups = tempGroups.filter(group => group !== undefined) // removes undefined
@@ -176,7 +175,7 @@ const SeriesDropdownForecastingStage = props => {
176
175
  tempGroups.forEach(group => stageObjects.push({ key: group }))
177
176
 
178
177
  const copyOfSeries = [...config.series] // copy the entire series array
179
- copyOfSeries[index] = { ...copyOfSeries[index], stages: stageObjects, stageColumn: e.target.value }
178
+ copyOfSeries[index] = { ...copyOfSeries[index], stages: stageObjects, stageColumn: value }
180
179
 
181
180
  updateConfig({
182
181
  ...config,
@@ -200,19 +199,19 @@ const SeriesDropdownForecastingColumn = props => {
200
199
  if (!series.stageColumn) return
201
200
 
202
201
  let tempGroups = new Set(rawData.map(item => item[series.stageColumn])) // [estimate, forecast, etc.]
203
- tempGroups = Array.from(tempGroups) // convert set to array
202
+ let tempGroupsArray = Array.from(tempGroups) // convert set to array
204
203
 
205
- tempGroups = tempGroups.filter(group => group !== undefined) // removes undefined
204
+ tempGroupsArray = tempGroupsArray.filter(group => group !== undefined) // removes undefined
206
205
 
207
206
  return (
208
- <InputSelect
207
+ <Select
209
208
  initial='Select an option'
210
209
  value={series.stageItem}
211
210
  label='Forecasting Item Column'
212
- onChange={event => {
213
- updateSeries(index, event.target.value, 'stageItem')
211
+ updateField={(_section, _subsection, _fieldName, value) => {
212
+ updateSeries(index, value, 'stageItem')
214
213
  }}
215
- options={tempGroups}
214
+ options={tempGroupsArray}
216
215
  />
217
216
  )
218
217
  }
@@ -229,17 +228,17 @@ const SeriesDropdownAxisPosition = props => {
229
228
  return
230
229
  }
231
230
  return (
232
- <InputSelect
231
+ <Select
233
232
  initial='Select an option'
234
233
  value={series.axis ? series.axis : 'Left'}
235
234
  label='Series Axis'
236
- onChange={event => {
237
- updateSeries(index, event.target.value, 'axis')
238
- }}
239
- options={{
240
- ['Left']: 'Left',
241
- ['Right']: 'Right'
235
+ updateField={(_section, _subsection, _fieldName, value) => {
236
+ updateSeries(index, value, 'axis')
242
237
  }}
238
+ options={[
239
+ { value: 'Left', label: 'Left' },
240
+ { value: 'Right', label: 'Right' }
241
+ ]}
243
242
  />
244
243
  )
245
244
  }
@@ -267,17 +266,23 @@ const SeriesDropdownForecastColor = props => {
267
266
 
268
267
  // For dropdown options, only show version-specific palettes
269
268
  const processedPalettes = updatePaletteNames(forecastPalettes)
270
- const paletteOptions = buildForecastPaletteOptions(processedPalettes, paletteVersion)
269
+ const paletteOptionsObject = buildForecastPaletteOptions(processedPalettes, paletteVersion)
270
+
271
+ // Convert object to array format for Select component
272
+ const paletteOptions = Object.entries(paletteOptionsObject).map(([value, label]) => ({
273
+ value,
274
+ label
275
+ }))
271
276
 
272
277
  return series?.stages?.map((stage, stageIndex) => (
273
- <InputSelect
278
+ <Select
274
279
  key={`${stage}--${stageIndex}`}
275
280
  initial='Select an option'
276
281
  value={config.series?.[index].stages?.[stageIndex].color || 'Select'}
277
282
  label={`${stage.key} Series Color`}
278
- onChange={event => {
283
+ updateField={(_section, _subsection, _fieldName, value) => {
279
284
  if (handleForecastPaletteSelection) {
280
- handleForecastPaletteSelection(event.target.value, index, stageIndex)
285
+ handleForecastPaletteSelection(value, index, stageIndex)
281
286
  }
282
287
  }}
283
288
  options={paletteOptions}
@@ -325,7 +330,7 @@ const SeriesDropdownConfidenceInterval = props => {
325
330
  </>
326
331
  </AccordionItemHeading>
327
332
  <AccordionItemPanel>
328
- <InputSelect
333
+ <Select
329
334
  initial='Select an option'
330
335
  value={
331
336
  config.series[index].confidenceIntervals[ciIndex].low
@@ -333,9 +338,9 @@ const SeriesDropdownConfidenceInterval = props => {
333
338
  : 'Select'
334
339
  }
335
340
  label='Low Confidence Interval'
336
- onChange={e => {
341
+ updateField={(_section, _subsection, _fieldName, value) => {
337
342
  const copiedConfidenceArray = [...config.series[index].confidenceIntervals]
338
- copiedConfidenceArray[ciIndex].low = e.target.value
343
+ copiedConfidenceArray[ciIndex].low = value
339
344
  const copyOfSeries = [...config.series] // copy the entire series array
340
345
  copyOfSeries[index] = { ...copyOfSeries[index], confidenceIntervals: copiedConfidenceArray }
341
346
  updateConfig({
@@ -345,7 +350,7 @@ const SeriesDropdownConfidenceInterval = props => {
345
350
  }}
346
351
  options={getColumns()}
347
352
  />
348
- <InputSelect
353
+ <Select
349
354
  initial='Select an option'
350
355
  value={
351
356
  config.series[index].confidenceIntervals[ciIndex].high
@@ -353,9 +358,9 @@ const SeriesDropdownConfidenceInterval = props => {
353
358
  : 'Select'
354
359
  }
355
360
  label='High Confidence Interval'
356
- onChange={e => {
361
+ updateField={(_section, _subsection, _fieldName, value) => {
357
362
  const copiedConfidenceArray = [...config.series[index].confidenceIntervals]
358
- copiedConfidenceArray[ciIndex].high = e.target.value
363
+ copiedConfidenceArray[ciIndex].high = value
359
364
  const copyOfSeries = [...config.series] // copy the entire series array
360
365
  copyOfSeries[index] = { ...copyOfSeries[index], confidenceIntervals: copiedConfidenceArray }
361
366
  updateConfig({