@cdc/chart 4.25.11 → 4.26.2

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 (181) hide show
  1. package/CLAUDE.local.md +79 -0
  2. package/dist/{cdcchart-dgT_1dIT.es.js → cdcchart-DQ00cQCm.es.js} +1 -20
  3. package/dist/cdcchart.js +51401 -50814
  4. package/examples/default.json +378 -0
  5. package/examples/feature/__data__/horizon-chart-data.json +373 -0
  6. package/examples/feature/annotations/index.json +3 -6
  7. package/examples/feature/horizon/horizon-chart.json +395 -0
  8. package/examples/feature/pie/planet-pie-example-config.json +48 -2
  9. package/examples/line-chart-states.json +1085 -0
  10. package/examples/private/123.json +694 -0
  11. package/examples/private/DEV-12100.json +1303 -0
  12. package/examples/private/anchor-issue.json +4094 -0
  13. package/examples/private/backwards-slider.json +10430 -0
  14. package/examples/private/cat-y.json +1235 -0
  15. package/examples/private/data-points.json +228 -0
  16. package/examples/private/georgia.csv +160 -0
  17. package/examples/private/height.json +3915 -0
  18. package/examples/private/links.json +569 -0
  19. package/examples/private/quadrant.txt +30 -0
  20. package/examples/private/test-forecast.json +5510 -0
  21. package/examples/private/timeline-data.json +1 -0
  22. package/examples/private/timeline.json +389 -0
  23. package/examples/private/warming-stripe-test.json +2578 -0
  24. package/examples/private/warming-stripes.json +4763 -0
  25. package/examples/radar-chart-simple.json +133 -0
  26. package/examples/radar-chart.json +148 -0
  27. package/examples/tech-adoption-with-links.json +560 -0
  28. package/index.html +1 -36
  29. package/package.json +59 -60
  30. package/src/CdcChartComponent.tsx +206 -89
  31. package/src/_stories/Chart.Anchors.stories.tsx +10 -0
  32. package/src/_stories/Chart.BoxPlot.stories.tsx +7 -0
  33. package/src/_stories/Chart.CI.stories.tsx +13 -0
  34. package/src/_stories/Chart.Combo.stories.tsx +17 -0
  35. package/src/_stories/Chart.CustomColors.stories.tsx +4 -0
  36. package/src/_stories/Chart.DynamicSeries.stories.tsx +19 -0
  37. package/src/_stories/Chart.Filters.stories.tsx +4 -0
  38. package/src/_stories/Chart.Forecast.stories.tsx +4 -0
  39. package/src/_stories/Chart.HTMLInDataTable.stories.tsx +22 -0
  40. package/src/_stories/Chart.Legend.Gradient.stories.tsx +28 -0
  41. package/src/_stories/Chart.Patterns.stories.tsx +4 -0
  42. package/src/_stories/Chart.PreserveDecimals.stories.tsx +25 -0
  43. package/src/_stories/Chart.Regions.Categorical.stories.tsx +161 -0
  44. package/src/_stories/Chart.Regions.DateScale.stories.tsx +216 -0
  45. package/src/_stories/Chart.Regions.DateTimeScale.stories.tsx +312 -0
  46. package/src/_stories/Chart.ScatterPlot.stories.tsx +4 -0
  47. package/src/_stories/Chart.SmallMultiples.stories.tsx +16 -0
  48. package/src/_stories/Chart.stories.tsx +45 -0
  49. package/src/_stories/Chart.tooltip.stories.tsx +7 -0
  50. package/src/_stories/ChartAnnotation.stories.tsx +10 -0
  51. package/src/_stories/ChartAxisLabels.stories.tsx +4 -0
  52. package/src/_stories/ChartAxisTitles.stories.tsx +10 -0
  53. package/src/_stories/ChartBar.Editor.stories.tsx +11 -6
  54. package/src/_stories/ChartBrush.Editor.stories.tsx +295 -0
  55. package/src/_stories/ChartBrush.Matrix.Continuous.stories.tsx +41 -0
  56. package/src/_stories/ChartBrush.Matrix.Date.stories.tsx +114 -0
  57. package/src/_stories/ChartBrush.Matrix.DateTime.stories.tsx +78 -0
  58. package/src/_stories/ChartBrush.stories.tsx +57 -0
  59. package/src/_stories/ChartEditor.Editor.stories.tsx +3 -5
  60. package/src/_stories/ChartEditor.stories.tsx +7 -0
  61. package/src/_stories/ChartLine.QuadrantAngles.stories.tsx +89 -0
  62. package/src/_stories/ChartLine.Suppression.stories.tsx +7 -0
  63. package/src/_stories/ChartLine.Symbols.stories.tsx +4 -0
  64. package/src/_stories/ChartPrefixSuffix.stories.tsx +46 -1
  65. package/src/_stories/TechAdoptionWithLinks.stories.tsx +34 -0
  66. package/src/_stories/_mock/brush_continuous.json +86 -0
  67. package/src/_stories/_mock/brush_date_large.json +176 -0
  68. package/src/_stories/_mock/brush_enabled.json +326 -0
  69. package/src/_stories/_mock/brush_mock.json +2 -69
  70. package/src/_stories/_mock/horizontal-bars-dynamic-y-axis.json +413 -0
  71. package/src/_stories/_mock/line_chart_angle_near_zero_fall.json +195 -0
  72. package/src/_stories/_mock/line_chart_angle_near_zero_rise.json +195 -0
  73. package/src/_stories/_mock/line_chart_angle_q1_steep_upward.json +195 -0
  74. package/src/_stories/_mock/line_chart_angle_q2_gentle_downward.json +195 -0
  75. package/src/_stories/_mock/line_chart_angle_q3_steep_downward.json +195 -0
  76. package/src/_stories/_mock/line_chart_angle_q4_gentle_upward.json +195 -0
  77. package/src/_stories/_mock/line_chart_quadrant_angles.json +264 -0
  78. package/src/components/Annotations/components/AnnotationDraggable.styles.css +11 -17
  79. package/src/components/Annotations/components/AnnotationDraggable.tsx +240 -116
  80. package/src/components/Annotations/components/AnnotationDropdown.styles.css +1 -2
  81. package/src/components/Annotations/components/AnnotationDropdown.tsx +8 -12
  82. package/src/components/Annotations/components/AnnotationList.styles.css +4 -10
  83. package/src/components/Annotations/components/AnnotationList.tsx +5 -4
  84. package/src/components/Annotations/components/findNearestDatum.ts +75 -85
  85. package/src/components/Annotations/helpers/getVisibleAnnotations.ts +38 -0
  86. package/src/components/AreaChart/components/AreaChart.Stacked.jsx +1 -2
  87. package/src/components/Axis/BottomAxis.tsx +270 -0
  88. package/src/components/Axis/Categorical.Axis.tsx +6 -7
  89. package/src/components/Axis/LeftAxis.tsx +404 -0
  90. package/src/components/Axis/LeftAxisGridlines.tsx +77 -0
  91. package/src/components/Axis/PairedBarAxis.tsx +186 -0
  92. package/src/components/Axis/README.md +94 -0
  93. package/src/components/Axis/RightAxis.tsx +108 -0
  94. package/src/components/Axis/axis.constants.ts +21 -0
  95. package/src/components/Axis/index.ts +7 -0
  96. package/src/components/BarChart/components/BarChart.Horizontal.tsx +178 -24
  97. package/src/components/BarChart/components/BarChart.StackedHorizontal.tsx +3 -1
  98. package/src/components/BarChart/components/BarChart.StackedVertical.tsx +1 -0
  99. package/src/components/BarChart/components/BarChart.Vertical.tsx +6 -8
  100. package/src/components/BarChart/components/BarChart.tsx +7 -1
  101. package/src/components/BarChart/components/context.tsx +1 -0
  102. package/src/components/BarChart/helpers/useBarChart.ts +14 -2
  103. package/src/components/Brush/BrushSelector.tsx +1390 -0
  104. package/src/components/Brush/MiniChartPreview.tsx +400 -0
  105. package/src/components/DeviationBar.jsx +9 -7
  106. package/src/components/EditorPanel/EditorPanel.tsx +2734 -2595
  107. package/src/components/EditorPanel/components/Panels/Panel.Annotate.tsx +60 -22
  108. package/src/components/EditorPanel/components/Panels/Panel.ForestPlotSettings.tsx +56 -34
  109. package/src/components/EditorPanel/components/Panels/Panel.General.tsx +137 -30
  110. package/src/components/EditorPanel/components/Panels/Panel.PatternSettings.tsx +2 -0
  111. package/src/components/EditorPanel/components/Panels/Panel.Radar.tsx +353 -0
  112. package/src/components/EditorPanel/components/Panels/Panel.Series.tsx +0 -1
  113. package/src/components/EditorPanel/components/Panels/Panel.SmallMultiples.tsx +30 -25
  114. package/src/components/EditorPanel/components/Panels/Panel.Visual.tsx +42 -28
  115. package/src/components/EditorPanel/components/Panels/index.tsx +2 -0
  116. package/src/components/EditorPanel/useEditorPermissions.ts +81 -39
  117. package/src/components/HorizonChart/HorizonChart.tsx +131 -0
  118. package/src/components/HorizonChart/components/HorizonBand.tsx +160 -0
  119. package/src/components/HorizonChart/helpers/calculateHorizonBands.ts +27 -0
  120. package/src/components/HorizonChart/helpers/getHorizonLayerColors.ts +40 -0
  121. package/src/components/HorizonChart/index.tsx +3 -0
  122. package/src/components/Legend/Legend.Component.tsx +52 -4
  123. package/src/components/Legend/Legend.tsx +4 -3
  124. package/src/components/Legend/LegendValueRange.tsx +77 -0
  125. package/src/components/Legend/helpers/createFormatLabels.tsx +164 -2
  126. package/src/components/Legend/helpers/generateValueRanges.ts +92 -0
  127. package/src/components/Legend/helpers/index.ts +10 -6
  128. package/src/components/LineChart/helpers/README.md +292 -0
  129. package/src/components/LineChart/helpers/labelPositioning.test.ts +245 -0
  130. package/src/components/LineChart/helpers/labelPositioning.ts +304 -0
  131. package/src/components/LineChart/index.tsx +44 -8
  132. package/src/components/LinearChart/README.md +109 -0
  133. package/src/components/LinearChart/VisualizationRenderer.tsx +267 -0
  134. package/src/components/LinearChart/linearChart.constants.ts +84 -0
  135. package/src/components/LinearChart/tests/LinearChart.test.tsx +201 -0
  136. package/src/components/LinearChart/tests/mockConfigContext.ts +129 -0
  137. package/src/components/LinearChart/utils/tickFormatting.ts +146 -0
  138. package/src/components/LinearChart.tsx +338 -1082
  139. package/src/components/PairedBarChart.jsx +20 -3
  140. package/src/components/PieChart/PieChart.tsx +1 -1
  141. package/src/components/RadarChart/RadarAxis.tsx +78 -0
  142. package/src/components/RadarChart/RadarChart.tsx +298 -0
  143. package/src/components/RadarChart/RadarGrid.tsx +64 -0
  144. package/src/components/RadarChart/RadarPolygon.tsx +91 -0
  145. package/src/components/RadarChart/helpers.ts +83 -0
  146. package/src/components/RadarChart/index.tsx +3 -0
  147. package/src/components/Regions/components/Regions.tsx +365 -122
  148. package/src/components/ScatterPlot/ScatterPlot.jsx +2 -2
  149. package/src/components/SmallMultiples/SmallMultipleTile.tsx +5 -1
  150. package/src/components/WarmingStripes/WarmingStripes.tsx +230 -0
  151. package/src/components/WarmingStripes/WarmingStripesGradientLegend.css +35 -0
  152. package/src/components/WarmingStripes/WarmingStripesGradientLegend.tsx +104 -0
  153. package/src/components/WarmingStripes/index.tsx +3 -0
  154. package/src/data/initial-state.js +17 -2
  155. package/src/helpers/calculateHorizontalBarCategoryLabelWidth.ts +57 -0
  156. package/src/helpers/getExcludedData.ts +4 -0
  157. package/src/helpers/getMinMax.ts +12 -7
  158. package/src/helpers/handleChartAriaLabels.ts +19 -19
  159. package/src/helpers/handleLineType.ts +22 -18
  160. package/src/helpers/sizeHelpers.ts +0 -20
  161. package/src/helpers/smallMultiplesHelpers.ts +1 -1
  162. package/src/hooks/useChartHoverAnalytics.tsx +10 -9
  163. package/src/hooks/useProgrammaticTooltip.ts +23 -2
  164. package/src/hooks/useScales.ts +18 -1
  165. package/src/hooks/useTooltip.tsx +34 -10
  166. package/src/scss/DataTable.scss +0 -4
  167. package/src/scss/main.scss +22 -3
  168. package/src/selectors/README.md +68 -0
  169. package/src/store/chart.reducer.ts +2 -0
  170. package/src/test/CdcChart.test.jsx +1 -1
  171. package/src/types/ChartConfig.ts +21 -0
  172. package/src/types/ChartContext.ts +1 -0
  173. package/src/types/Horizon.ts +64 -0
  174. package/src/types/Label.ts +1 -0
  175. package/src/utils/analyticsTracking.ts +19 -0
  176. package/LICENSE +0 -201
  177. package/src/components/Annotations/components/helpers/index.tsx +0 -46
  178. package/src/components/Brush/BrushChart.tsx +0 -128
  179. package/src/components/Brush/BrushController.tsx +0 -71
  180. package/src/components/Brush/types.tsx +0 -8
  181. package/src/components/BrushChart.tsx +0 -223
@@ -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
@@ -50,7 +50,6 @@ const SeriesWrapper = props => {
50
50
  forecastingStages.forEach(stage => {
51
51
  forecastingStageArr.push({ key: stage })
52
52
  })
53
- // debugger
54
53
  series[index].stages = forecastingStageArr
55
54
  series[index].stageColumn = series[index].dataKey
56
55
  }
@@ -1,4 +1,4 @@
1
- import { useContext, FC } from 'react'
1
+ import { useContext, FC, useMemo } from 'react'
2
2
  import { DragDropContext, Droppable, Draggable } from '@hello-pangea/dnd'
3
3
  import {
4
4
  AccordionItem,
@@ -11,6 +11,7 @@ import {
11
11
  import { TextField, Select, CheckBox } from '@cdc/core/components/EditorPanel/Inputs'
12
12
  import Tooltip from '@cdc/core/components/ui/Tooltip'
13
13
  import Icon from '@cdc/core/components/ui/Icon'
14
+ import { useDataColumns } from '@cdc/core/hooks/useDataColumns'
14
15
 
15
16
  // contexts
16
17
  import { ChartContext } from './../../../../types/ChartContext.js'
@@ -25,30 +26,30 @@ const PanelSmallMultiples: FC<PanelProps> = props => {
25
26
  const { updateField } = useEditorPanelContext()
26
27
  const { visSupportsSmallMultiples } = useEditorPermissions()
27
28
 
28
- const getColumns = (filter = true) => {
29
- let columns = {}
30
- rawData?.forEach(row => {
31
- Object.keys(row).forEach(columnName => (columns[columnName] = true))
32
- })
33
-
34
- if (filter) {
35
- const { lower, upper } = config.confidenceKeys || {}
36
- Object.keys(columns).forEach(key => {
37
- if (
38
- (config.series && config.series.filter(series => series.dataKey === key).length > 0) ||
39
- (config.confidenceKeys &&
40
- Object.keys(config.confidenceKeys).includes(key) &&
41
- ((lower && upper) || lower || upper) &&
42
- key !== lower &&
43
- key !== upper)
44
- ) {
45
- delete columns[key]
46
- }
47
- })
48
- }
29
+ // Extract column names from data with memoization (replaces getColumns)
30
+ const allColumns = useDataColumns(rawData)
49
31
 
50
- return Object.keys(columns)
51
- }
32
+ // Filter out series columns and confidence key columns (except lower and upper)
33
+ const filteredColumns = useMemo(() => {
34
+ const { lower, upper } = config.confidenceKeys || {}
35
+ return allColumns.filter(key => {
36
+ // Filter out series columns
37
+ if (config.series && config.series.some(series => series.dataKey === key)) {
38
+ return false
39
+ }
40
+ // Filter out confidence key columns (except lower and upper)
41
+ if (
42
+ config.confidenceKeys &&
43
+ Object.keys(config.confidenceKeys).includes(key) &&
44
+ ((lower && upper) || lower || upper) &&
45
+ key !== lower &&
46
+ key !== upper
47
+ ) {
48
+ return false
49
+ }
50
+ return true
51
+ })
52
+ }, [allColumns, config.series, config.confidenceKeys])
52
53
 
53
54
  return (
54
55
  <>
@@ -91,7 +92,7 @@ const PanelSmallMultiples: FC<PanelProps> = props => {
91
92
  label='Tile By Column'
92
93
  initial='Select Column'
93
94
  updateField={updateField}
94
- options={getColumns()}
95
+ options={filteredColumns}
95
96
  />
96
97
  )}
97
98
 
@@ -184,6 +185,8 @@ const PanelSmallMultiples: FC<PanelProps> = props => {
184
185
  value={currentOrderType}
185
186
  options={tileOrderOptions}
186
187
  label='Tile Order'
188
+ fieldName='tileOrderType'
189
+ section='smallMultiples'
187
190
  updateField={(_section, _subsection, _fieldName, value) => {
188
191
  handleOrderTypeChange(value)
189
192
  }}
@@ -244,6 +247,8 @@ const PanelSmallMultiples: FC<PanelProps> = props => {
244
247
  }
245
248
  ]}
246
249
  label='Color Mode'
250
+ fieldName='colorMode'
251
+ section='smallMultiples'
247
252
  updateField={(_section, _subsection, _fieldName, value) => {
248
253
  updateConfig({
249
254
  ...config,
@@ -241,6 +241,27 @@ const PanelVisual: FC<PanelProps> = props => {
241
241
  updateField={updateField}
242
242
  options={['Same as Line', 'Lighter than Line']}
243
243
  />
244
+ <CheckBox
245
+ value={config.general?.useIntelligentLineChartLabels ?? false}
246
+ section='general'
247
+ fieldName='useIntelligentLineChartLabels'
248
+ label='Use Intelligent Label Positioning'
249
+ updateField={updateField}
250
+ tooltip={
251
+ <Tooltip style={{ textTransform: 'none' }}>
252
+ <Tooltip.Target>
253
+ <Icon display='question' style={{ marginLeft: '0.5rem' }} />
254
+ </Tooltip.Target>
255
+ <Tooltip.Content>
256
+ <p>
257
+ Automatically positions data labels to avoid overlapping with line segments based on the direction
258
+ and location of data points. When disabled, all labels are positioned above and centered on their
259
+ data points.
260
+ </p>
261
+ </Tooltip.Content>
262
+ </Tooltip>
263
+ }
264
+ />
244
265
  <CheckBox
245
266
  value={!(config as LineChartConfig).isolatedDotsSameSize}
246
267
  fieldName='isolatedDotsSameSize'
@@ -319,16 +340,21 @@ const PanelVisual: FC<PanelProps> = props => {
319
340
  colorIndices={[2, 4, 6]}
320
341
  className='color-palette'
321
342
  />
322
- <span>Colorblind Safe</span>
323
- <PaletteSelector
324
- palettes={accessibleColors}
325
- colorPalettes={colorPalettes}
326
- config={config}
327
- onPaletteSelect={handlePaletteSelection}
328
- selectedPalette={getCurrentPaletteName(config)}
329
- colorIndices={[2, 3, 5]}
330
- className='color-palette'
331
- />
343
+
344
+ {config.visualizationType !== 'Warming Stripes' && (
345
+ <>
346
+ <span>Colorblind Safe</span>
347
+ <PaletteSelector
348
+ palettes={accessibleColors}
349
+ colorPalettes={colorPalettes}
350
+ config={config}
351
+ onPaletteSelect={handlePaletteSelection}
352
+ selectedPalette={getCurrentPaletteName(config)}
353
+ colorIndices={[2, 3, 5]}
354
+ className='color-palette'
355
+ />
356
+ </>
357
+ )}
332
358
  </>
333
359
  )}
334
360
 
@@ -393,7 +419,6 @@ const PanelVisual: FC<PanelProps> = props => {
393
419
  }}
394
420
  label='Custom Color Order'
395
421
  minColors={1}
396
- maxColors={20}
397
422
  />
398
423
  </div>
399
424
  )}
@@ -516,28 +541,17 @@ const PanelVisual: FC<PanelProps> = props => {
516
541
  />
517
542
  </>
518
543
  )}
519
- {visSupportsBarThickness() &&
520
- config.orientation === 'horizontal' &&
521
- !config.isLollipopChart &&
522
- config.yAxis.labelPlacement !== 'On Bar' && (
544
+
545
+ {(config.orientation !== 'horizontal' || config.visualizationType === 'Combo') &&
546
+ config.visualizationType !== 'Warming Stripes' && (
523
547
  <TextField
548
+ value={config.barThickness}
524
549
  type='number'
525
- value={config.barHeight || '25'}
526
- fieldName='barHeight'
527
- label=' Bar Thickness'
550
+ fieldName='barThickness'
551
+ label='Bar Thickness'
528
552
  updateField={updateField}
529
- min={15}
530
553
  />
531
554
  )}
532
- {(config.orientation !== 'horizontal' || config.visualizationType === 'Combo') && (
533
- <TextField
534
- value={config.barThickness}
535
- type='number'
536
- fieldName='barThickness'
537
- label='Bar Thickness'
538
- updateField={updateField}
539
- />
540
- )}
541
555
  {visSupportsBarSpace() && (
542
556
  <TextField
543
557
  type='number'
@@ -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