@cdc/chart 4.26.5 → 4.26.7

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 (128) hide show
  1. package/CONFIG.md +20 -14
  2. package/dist/{cdcchart-DQ00cQCm.es.js → cdcchart-BWVIUcAF.es.js} +5 -55
  3. package/dist/cdcchart.js +36554 -34320
  4. package/examples/feature/heatmap/average-age-categorical.json +1 -1
  5. package/examples/feature/heatmap/calendar-heatmap.json +1 -1
  6. package/examples/feature/heatmap/sparse-aggregation.json +1 -1
  7. package/examples/private/bad-y-axis.json +543 -0
  8. package/examples/private/bar-chart-negative-value.json +455 -0
  9. package/examples/private/flueview.json +22051 -0
  10. package/package.json +3 -11
  11. package/src/CdcChart.tsx +7 -6
  12. package/src/CdcChartComponent.tsx +71 -18
  13. package/src/_stories/Chart.PieLabels.stories.tsx +47 -0
  14. package/src/_stories/Chart.SeriesColorAssignments.stories.tsx +183 -0
  15. package/src/_stories/Chart.YAxisAutoMaxStrategy.stories.tsx +52 -0
  16. package/src/_stories/Chart.YAxisFilterDomain.stories.tsx +90 -0
  17. package/src/_stories/Chart.smoke.stories.tsx +14 -1
  18. package/src/_stories/ChartAnnotation.smoke.stories.tsx +10 -0
  19. package/src/_stories/ChartPrefixSuffix.smoke.stories.tsx +28 -1
  20. package/src/_stories/_mock/annotation_event-line_mock.json +1064 -0
  21. package/src/_stories/_mock/heatmap-average-age-categorical.json +1 -1
  22. package/src/_stories/_mock/heatmap.json +1 -1
  23. package/src/components/Annotations/components/AnnotationDraggable.styles.css +22 -1
  24. package/src/components/Annotations/components/AnnotationDraggable.tsx +219 -119
  25. package/src/components/Annotations/tests/AnnotationDraggable.test.tsx +198 -0
  26. package/src/components/Axis/LeftAxis.tsx +3 -0
  27. package/src/components/Axis/LeftAxisGridlines.tsx +8 -1
  28. package/src/components/Axis/RightAxis.tsx +3 -0
  29. package/src/components/Axis/tests/AxisTickValues.test.tsx +86 -0
  30. package/src/components/BarChart/components/BarChart.Horizontal.tsx +1 -2
  31. package/src/components/BarChart/components/BarChart.StackedHorizontal.tsx +1 -1
  32. package/src/components/BarChart/components/BarChart.StackedVertical.tsx +1 -1
  33. package/src/components/BarChart/components/BarChart.Vertical.tsx +1 -2
  34. package/src/components/BarChart/helpers/getBarData.ts +28 -28
  35. package/src/components/BarChart/helpers/getBarHeights.ts +2 -2
  36. package/src/components/BarChart/helpers/tests/useBarChart.test.tsx +98 -0
  37. package/src/components/BarChart/helpers/useBarChart.ts +4 -5
  38. package/src/components/BoxPlot/BoxPlot.Horizontal.tsx +7 -6
  39. package/src/components/BoxPlot/BoxPlot.Vertical.tsx +9 -7
  40. package/src/components/BoxPlot/helpers/index.ts +4 -3
  41. package/src/components/Brush/BrushSelector.tsx +1 -1
  42. package/src/components/EditorPanel/EditorPanel.tsx +457 -165
  43. package/src/components/EditorPanel/components/Panels/Panel.Annotate.tsx +101 -52
  44. package/src/components/EditorPanel/components/Panels/Panel.General.tsx +16 -7
  45. package/src/components/EditorPanel/components/Panels/Panel.PatternSettings.tsx +3 -3
  46. package/src/components/EditorPanel/components/Panels/Panel.Series.tsx +19 -4
  47. package/src/components/EditorPanel/components/Panels/Panel.SmallMultiples.test.tsx +98 -0
  48. package/src/components/EditorPanel/components/Panels/Panel.SmallMultiples.tsx +10 -0
  49. package/src/components/EditorPanel/components/Panels/Panel.Visual.test.tsx +484 -0
  50. package/src/components/EditorPanel/components/Panels/Panel.Visual.tsx +3 -0
  51. package/src/components/EditorPanel/components/Panels/SeriesColorAssignments.tsx +262 -0
  52. package/src/components/EditorPanel/components/Panels/panelVisual.styles.css +32 -0
  53. package/src/components/EditorPanel/components/panels.scss +10 -0
  54. package/src/components/EditorPanel/editor-panel.scss +47 -0
  55. package/src/components/EditorPanel/helpers/getVisualizationTypeConfigUpdate.ts +6 -2
  56. package/src/components/EditorPanel/helpers/tests/getVisualizationTypeConfigUpdate.test.ts +20 -2
  57. package/src/components/EditorPanel/helpers/updateFieldRankByValue.ts +3 -3
  58. package/src/components/EditorPanel/useEditorPermissions.test.tsx +288 -11
  59. package/src/components/EditorPanel/useEditorPermissions.ts +46 -6
  60. package/src/components/Forecasting/Forecasting.tsx +1 -1
  61. package/src/components/HeatMap/components/HeatMap.tsx +22 -17
  62. package/src/components/HeatMap/components/HeatMapGradientLegend.tsx +29 -15
  63. package/src/components/HeatMap/heatmap.css +15 -1
  64. package/src/components/HeatMap/tests/HeatMap.test.tsx +39 -7
  65. package/src/components/Legend/Legend.Component.tsx +56 -61
  66. package/src/components/Legend/Legend.Suppression.tsx +3 -3
  67. package/src/components/Legend/LegendGroup/LegendGroup.tsx +0 -1
  68. package/src/components/Legend/helpers/createFormatLabels.test.ts +88 -0
  69. package/src/components/Legend/helpers/createFormatLabels.tsx +6 -1
  70. package/src/components/LineChart/helpers.test.ts +230 -1
  71. package/src/components/LineChart/helpers.ts +25 -14
  72. package/src/components/LineChart/index.tsx +23 -7
  73. package/src/components/LinearChart/tests/LinearChart.test.tsx +30 -0
  74. package/src/components/LinearChart.tsx +51 -15
  75. package/src/components/PieChart/PieChart.tsx +117 -10
  76. package/src/components/PieChart/helpers/labelPlacement.test.ts +88 -0
  77. package/src/components/PieChart/helpers/labelPlacement.ts +95 -0
  78. package/src/components/ScatterPlot/ScatterPlot.jsx +5 -13
  79. package/src/components/SmallMultiples/SmallMultipleTile.tsx +3 -0
  80. package/src/components/SmallMultiples/SmallMultiples.tsx +38 -9
  81. package/src/components/SmallMultiples/tests/SmallMultiples.test.tsx +170 -0
  82. package/src/data/initial-state.js +3 -0
  83. package/src/helpers/calculateLeftYAxisWidth.ts +9 -3
  84. package/src/helpers/categoryOrder.ts +60 -0
  85. package/src/helpers/colorAssignmentHelpers.ts +102 -0
  86. package/src/helpers/dataHelpers.ts +11 -1
  87. package/src/helpers/getAxisMaxOverride.ts +16 -0
  88. package/src/helpers/getBoxPlotConfig.ts +19 -12
  89. package/src/helpers/getCleanTopTickMax.ts +64 -0
  90. package/src/helpers/getColorScale.ts +18 -9
  91. package/src/helpers/getComboChartConfig.ts +0 -1
  92. package/src/helpers/getExcludedData.ts +0 -1
  93. package/src/helpers/getHasBoundarySuppression.ts +27 -0
  94. package/src/helpers/getMinMax.ts +25 -22
  95. package/src/helpers/getNewRuntime.ts +0 -2
  96. package/src/helpers/getPiePercent.ts +3 -3
  97. package/src/helpers/getYAxisDomainData.ts +38 -0
  98. package/src/helpers/getYAxisFinalizationEligibility.ts +40 -0
  99. package/src/helpers/hasSpacedInlineLabel.ts +10 -0
  100. package/src/helpers/isConvertLineToBarGraph.ts +2 -2
  101. package/src/helpers/seriesColumnSettings.ts +26 -7
  102. package/src/helpers/sizeHelpers.ts +0 -2
  103. package/src/helpers/smallMultiplesHelpers.ts +5 -0
  104. package/src/helpers/tests/calculateLeftYAxisWidth.test.ts +38 -0
  105. package/src/helpers/tests/categoryOrder.test.ts +57 -0
  106. package/src/helpers/tests/dataHelpers.test.ts +135 -0
  107. package/src/helpers/tests/getAxisMaxOverride.test.ts +36 -0
  108. package/src/helpers/tests/getCleanTopTickMax.test.ts +165 -0
  109. package/src/helpers/tests/getColorScale.test.ts +197 -0
  110. package/src/helpers/tests/getMinMax.test.ts +211 -0
  111. package/src/helpers/tests/getYAxisDomainData.test.ts +119 -0
  112. package/src/helpers/tests/getYAxisFinalizationEligibility.test.ts +185 -0
  113. package/src/helpers/tests/{getYAxisAutoPaddingMode.test.ts → hasSpacedInlineLabel.test.ts} +17 -32
  114. package/src/helpers/tests/seriesColumnSettings.test.ts +76 -2
  115. package/src/helpers/tests/smallMultiplesHelpers.test.ts +99 -0
  116. package/src/hooks/tests/useRightAxis.test.tsx +268 -0
  117. package/src/hooks/tests/useScales.test.tsx +302 -27
  118. package/src/hooks/tests/useTooltip.test.tsx +132 -0
  119. package/src/hooks/useRightAxis.ts +35 -25
  120. package/src/hooks/useScales.ts +45 -28
  121. package/src/hooks/useTooltip.tsx +17 -11
  122. package/src/store/chart.reducer.ts +0 -1
  123. package/src/test/CdcChart.dataTable.test.tsx +216 -0
  124. package/src/types/ChartConfig.ts +6 -1
  125. package/src/types/ChartContext.ts +3 -0
  126. package/src/helpers/getYAxisAutoPadding.ts +0 -55
  127. package/src/helpers/getYAxisAutoPaddingMode.ts +0 -17
  128. package/src/helpers/tests/getYAxisAutoPadding.test.ts +0 -37
@@ -2,6 +2,7 @@ import React, { useContext } from 'react'
2
2
  import { Draggable } from '@hello-pangea/dnd'
3
3
  import ConfigContext from '../../../../ConfigContext.js'
4
4
  import { useEditorPermissions } from '../../useEditorPermissions'
5
+ import { EVENT_LINE_LABEL_OFFSET } from '../../../Annotations/components/AnnotationDraggable'
5
6
 
6
7
  // CDC Core
7
8
  import Accordion from '@cdc/core/components/ui/Accordion'
@@ -63,6 +64,7 @@ const PanelAnnotate: React.FC<PanelProps> = props => {
63
64
  const handleAddAnnotation = () => {
64
65
  const newAnnotation = {
65
66
  text: 'New annotation',
67
+ style: 'callout',
66
68
  anchorMode: 'fixed',
67
69
  fontSize: 16,
68
70
  bezier: 10,
@@ -213,7 +215,48 @@ const PanelAnnotate: React.FC<PanelProps> = props => {
213
215
  />
214
216
  </label>
215
217
 
216
- {visSupportsDataAnnotations() && (
218
+ <Select
219
+ label='Annotation Style:'
220
+ value={annotation.style || 'callout'}
221
+ options={[
222
+ { value: 'callout', label: 'Callout' },
223
+ {
224
+ value: 'event-line',
225
+ label: visSupportsDataAnnotations()
226
+ ? 'Event Line'
227
+ : 'Event Line (requires Line/Bar/Combo/Area/Forecasting, vertical)'
228
+ }
229
+ ]}
230
+ section='annotations'
231
+ subsection={null}
232
+ fieldName='style'
233
+ updateField={(section, subsection, fieldName, value) => {
234
+ const updatedAnnotations = cloneDeep(config?.annotations)
235
+ const target = updatedAnnotations[index]
236
+ target.style = value
237
+
238
+ if (value === 'event-line') {
239
+ target.anchorMode = 'data'
240
+ if (!target.dataX) {
241
+ target.dataX = transformedData?.[0]?.[config.xAxis.dataKey] || ''
242
+ }
243
+ target.seriesKey = ''
244
+ target.edit = { subject: false, label: true }
245
+ target.dx =
246
+ typeof target.dx === 'number' && target.dx < 0
247
+ ? -EVENT_LINE_LABEL_OFFSET
248
+ : EVENT_LINE_LABEL_OFFSET
249
+ if (target.dy === undefined || target.dy === null) target.dy = -120
250
+ }
251
+
252
+ updateConfig({
253
+ ...config,
254
+ annotations: updatedAnnotations
255
+ })
256
+ }}
257
+ />
258
+
259
+ {visSupportsDataAnnotations() && annotation.style !== 'event-line' && (
217
260
  <Select
218
261
  label='Position Mode:'
219
262
  value={annotation.anchorMode || 'fixed'}
@@ -246,24 +289,26 @@ const PanelAnnotate: React.FC<PanelProps> = props => {
246
289
  />
247
290
  )}
248
291
 
249
- {visSupportsDataAnnotations() && annotation.anchorMode === 'data' && (
250
- <Select
251
- label='Series:'
252
- value={annotation.seriesKey || config.series?.[0]?.dataKey || ''}
253
- options={config.series.map(s => s.dataKey)}
254
- section='annotations'
255
- subsection={null}
256
- fieldName='seriesKey'
257
- updateField={(section, subsection, fieldName, value) => {
258
- const updatedAnnotations = cloneDeep(config?.annotations)
259
- updatedAnnotations[index].seriesKey = value || config.series?.[0]?.dataKey
260
- updateConfig({
261
- ...config,
262
- annotations: updatedAnnotations
263
- })
264
- }}
265
- />
266
- )}
292
+ {visSupportsDataAnnotations() &&
293
+ annotation.style !== 'event-line' &&
294
+ annotation.anchorMode === 'data' && (
295
+ <Select
296
+ label='Series:'
297
+ value={annotation.seriesKey || config.series?.[0]?.dataKey || ''}
298
+ options={config.series.map(s => s.dataKey)}
299
+ section='annotations'
300
+ subsection={null}
301
+ fieldName='seriesKey'
302
+ updateField={(section, subsection, fieldName, value) => {
303
+ const updatedAnnotations = cloneDeep(config?.annotations)
304
+ updatedAnnotations[index].seriesKey = value || config.series?.[0]?.dataKey
305
+ updateConfig({
306
+ ...config,
307
+ annotations: updatedAnnotations
308
+ })
309
+ }}
310
+ />
311
+ )}
267
312
 
268
313
  <label>
269
314
  Opacity
@@ -313,24 +358,26 @@ const PanelAnnotate: React.FC<PanelProps> = props => {
313
358
  }}
314
359
  />
315
360
 
316
- <Select
317
- label='Connection Type:'
318
- value={config?.annotations[index]?.connectionType}
319
- options={['Select', 'curve', 'line', 'elbow', 'none']}
320
- section='annotations'
321
- subsection={null}
322
- fieldName='connectionType'
323
- updateField={(section, subsection, fieldName, value) => {
324
- const updatedAnnotations = cloneDeep(config?.annotations)
325
- updatedAnnotations[index].connectionType = value
326
- updateConfig({
327
- ...config,
328
- annotations: updatedAnnotations
329
- })
330
- }}
331
- />
361
+ {annotation.style !== 'event-line' && (
362
+ <Select
363
+ label='Connection Type:'
364
+ value={config?.annotations[index]?.connectionType}
365
+ options={['Select', 'curve', 'line', 'elbow', 'none']}
366
+ section='annotations'
367
+ subsection={null}
368
+ fieldName='connectionType'
369
+ updateField={(section, subsection, fieldName, value) => {
370
+ const updatedAnnotations = cloneDeep(config?.annotations)
371
+ updatedAnnotations[index].connectionType = value
372
+ updateConfig({
373
+ ...config,
374
+ annotations: updatedAnnotations
375
+ })
376
+ }}
377
+ />
378
+ )}
332
379
 
333
- {annotation.connectionType === 'curve' && (
380
+ {annotation.style !== 'event-line' && annotation.connectionType === 'curve' && (
334
381
  <>
335
382
  <label>
336
383
  Curve Control
@@ -353,22 +400,24 @@ const PanelAnnotate: React.FC<PanelProps> = props => {
353
400
  </>
354
401
  )}
355
402
 
356
- <Select
357
- label='Marker'
358
- value={annotation.marker}
359
- options={['arrow', 'circle']}
360
- section='annotations'
361
- subsection={null}
362
- fieldName='marker'
363
- updateField={(section, subsection, fieldName, value) => {
364
- const updatedAnnotations = cloneDeep(config?.annotations)
365
- updatedAnnotations[index].marker = value
366
- updateConfig({
367
- ...config,
368
- annotations: updatedAnnotations
369
- })
370
- }}
371
- />
403
+ {annotation.style !== 'event-line' && (
404
+ <Select
405
+ label='Marker'
406
+ value={annotation.marker}
407
+ options={['arrow', 'circle']}
408
+ section='annotations'
409
+ subsection={null}
410
+ fieldName='marker'
411
+ updateField={(section, subsection, fieldName, value) => {
412
+ const updatedAnnotations = cloneDeep(config?.annotations)
413
+ updatedAnnotations[index].marker = value
414
+ updateConfig({
415
+ ...config,
416
+ annotations: updatedAnnotations
417
+ })
418
+ }}
419
+ />
420
+ )}
372
421
  </AccordionItemPanel>
373
422
  </AccordionItem>
374
423
  </AccessibleAccordion>
@@ -308,7 +308,7 @@ const PanelGeneral: FC<PanelProps> = props => {
308
308
  <CheckBox
309
309
  value={config.labels}
310
310
  fieldName='labels'
311
- label='Display label on data'
311
+ label={visualizationType === 'Pie' ? 'Display Category and Percentage Labels' : 'Display label on data'}
312
312
  updateField={updateField}
313
313
  tooltip={
314
314
  <Tooltip style={{ textTransform: 'none' }}>
@@ -316,12 +316,21 @@ const PanelGeneral: FC<PanelProps> = props => {
316
316
  <Icon display='question' style={{ marginLeft: '0.5rem' }} />
317
317
  </Tooltip.Target>
318
318
  <Tooltip.Content>
319
- <p>Recommended set to display for Section 508 compliance.</p>
320
- <hr />
321
- <p>
322
- Selecting this option will <i> not </i> hide the display of "zero value", "suppressed data", or
323
- "missing data" indicators on the chart (if applicable).
324
- </p>
319
+ {visualizationType === 'Pie' ? (
320
+ <p>
321
+ Labels that do not fit and donut labels will display outside of chart. Use a Custom Segment
322
+ Order to resolve overlapping labels.
323
+ </p>
324
+ ) : (
325
+ <>
326
+ <p>Recommended set to display for Section 508 compliance.</p>
327
+ <hr />
328
+ <p>
329
+ Selecting this option will <i> not </i> hide the display of "zero value", "suppressed data",
330
+ or "missing data" indicators on the chart (if applicable).
331
+ </p>
332
+ </>
333
+ )}
325
334
  </Tooltip.Content>
326
335
  </Tooltip>
327
336
  }
@@ -68,7 +68,7 @@ const PanelPatternSettings: FC<PanelProps> = props => {
68
68
  case 'large':
69
69
  return 16
70
70
  default:
71
- return 8
71
+ return 10
72
72
  }
73
73
  }
74
74
 
@@ -192,7 +192,7 @@ const PanelPatternSettings: FC<PanelProps> = props => {
192
192
  shape: 'circles' as const,
193
193
  dataKey: defaultDataKey,
194
194
  dataValue: '',
195
- patternSize: 8, // Default pattern size
195
+ patternSize: 10, // Default pattern size
196
196
  contrastCheck: performContrastCheck(newPatternKey, defaultColor)
197
197
  }
198
198
  }
@@ -437,7 +437,7 @@ const PanelPatternSettings: FC<PanelProps> = props => {
437
437
 
438
438
  <Select
439
439
  label='Pattern Size:'
440
- value={getPatternSizeText(p.patternSize || 8)}
440
+ value={getPatternSizeText(p.patternSize || 10)}
441
441
  options={patternSizes}
442
442
  fieldName={`pattern-size-${domPatternKey}`}
443
443
  updateField={(section, subsection, fieldName, value) =>
@@ -556,6 +556,22 @@ const SeriesColumnSettings = props => {
556
556
  })
557
557
  }
558
558
 
559
+ const updateSeriesRoundToPlace = value => {
560
+ const trimmed = value === undefined || value === null ? '' : String(value).trim()
561
+ if (!trimmed) {
562
+ updateSeriesColumn('roundToPlace', undefined)
563
+ return
564
+ }
565
+
566
+ const numericValue = Number(trimmed)
567
+ if (!Number.isFinite(numericValue)) {
568
+ updateSeriesColumn('roundToPlace', undefined)
569
+ return
570
+ }
571
+
572
+ updateSeriesColumn('roundToPlace', Math.max(0, Math.min(20, Math.round(numericValue))))
573
+ }
574
+
559
575
  return (
560
576
  <>
561
577
  <span className='divider-heading'>Series Column Settings</span>
@@ -586,14 +602,13 @@ const SeriesColumnSettings = props => {
586
602
  />
587
603
  <TextField
588
604
  type='number'
589
- value={columnConfig.roundToPlace ?? 0}
605
+ value={columnConfig.roundToPlace ?? ''}
590
606
  section='seriesColumn'
591
607
  subsection={series.dataKey}
592
608
  fieldName='roundToPlace'
593
609
  label='Round'
594
- updateField={(_section, _subsection, _fieldName, value) =>
595
- updateSeriesColumn('roundToPlace', Number(value) || 0)
596
- }
610
+ updateField={(_section, _subsection, _fieldName, value) => updateSeriesRoundToPlace(value)}
611
+ min={0}
597
612
  />
598
613
  </div>
599
614
  <CheckBox
@@ -0,0 +1,98 @@
1
+ import React from 'react'
2
+ import { Accordion } from 'react-accessible-accordion'
3
+ import { render, screen, fireEvent } from '@testing-library/react'
4
+ import { describe, expect, it, vi } from 'vitest'
5
+ import ConfigContext from '../../../../ConfigContext'
6
+ import EditorPanelContext from '../../EditorPanelContext'
7
+ import PanelSmallMultiples from './Panel.SmallMultiples'
8
+ import { createMockChartContext, createMockConfig } from '../../../LinearChart/tests/mockConfigContext'
9
+
10
+ vi.mock('@cdc/core/components/ui/Icon', () => ({
11
+ default: () => <span data-testid='icon' />
12
+ }))
13
+
14
+ const renderPanel = config => {
15
+ const context = createMockChartContext(config, {
16
+ rawData: [{ Date: '2024-01-01', series_a: 1, series_b: 2 }]
17
+ } as any)
18
+
19
+ render(
20
+ <ConfigContext.Provider value={context}>
21
+ <EditorPanelContext.Provider value={{ updateField: vi.fn() }}>
22
+ <Accordion allowZeroExpanded>
23
+ <PanelSmallMultiples name='Small Multiples' />
24
+ </Accordion>
25
+ </EditorPanelContext.Provider>
26
+ </ConfigContext.Provider>
27
+ )
28
+
29
+ fireEvent.click(screen.getByRole('button', { name: 'Small Multiples' }))
30
+ }
31
+
32
+ describe('PanelSmallMultiples color assignments warning', () => {
33
+ it('shows the by-series same-color override warning only when assignments are active', () => {
34
+ const config = createMockConfig({
35
+ visualizationType: 'Line',
36
+ general: {
37
+ palette: {
38
+ colorAssignmentMode: 'by-value',
39
+ colorAssignments: [{ key: 'series_a', color: '#123456' }]
40
+ }
41
+ } as any,
42
+ smallMultiples: {
43
+ mode: 'by-series',
44
+ colorMode: 'same'
45
+ },
46
+ series: [
47
+ { dataKey: 'series_a', name: 'Alpha', type: 'Line' },
48
+ { dataKey: 'series_b', name: 'Beta', type: 'Line' }
49
+ ] as any
50
+ })
51
+
52
+ renderPanel(config)
53
+
54
+ expect(screen.queryByText(/Color assignments are enabled/)).toBeInTheDocument()
55
+ })
56
+
57
+ it('does not show the override warning when assignment mode is ordered', () => {
58
+ const config = createMockConfig({
59
+ visualizationType: 'Line',
60
+ general: {
61
+ palette: {
62
+ colorAssignmentMode: 'ordered',
63
+ colorAssignments: [{ key: 'series_a', color: '#123456' }]
64
+ }
65
+ } as any,
66
+ smallMultiples: {
67
+ mode: 'by-series',
68
+ colorMode: 'same'
69
+ },
70
+ series: [{ dataKey: 'series_a', name: 'Alpha', type: 'Line' }] as any
71
+ })
72
+
73
+ renderPanel(config)
74
+
75
+ expect(screen.queryByText(/Color assignments are enabled/)).not.toBeInTheDocument()
76
+ })
77
+
78
+ it('does not show the override warning when assignments only contain stale keys', () => {
79
+ const config = createMockConfig({
80
+ visualizationType: 'Line',
81
+ general: {
82
+ palette: {
83
+ colorAssignmentMode: 'by-value',
84
+ colorAssignments: [{ key: 'removed_series', color: '#123456' }]
85
+ }
86
+ } as any,
87
+ smallMultiples: {
88
+ mode: 'by-series',
89
+ colorMode: 'same'
90
+ },
91
+ series: [{ dataKey: 'series_a', name: 'Alpha', type: 'Line' }] as any
92
+ })
93
+
94
+ renderPanel(config)
95
+
96
+ expect(screen.queryByText(/Color assignments are enabled/)).not.toBeInTheDocument()
97
+ })
98
+ })
@@ -20,6 +20,7 @@ import { useEditorPanelContext } from '../../EditorPanelContext.js'
20
20
  import ConfigContext from '../../../../ConfigContext.js'
21
21
  import { PanelProps } from '../PanelProps'
22
22
  import { getTileKeys } from '../../../../helpers/smallMultiplesHelpers'
23
+ import { hasSeriesColorAssignmentOverrides } from '../../../../helpers/colorAssignmentHelpers'
23
24
 
24
25
  const PanelSmallMultiples: FC<PanelProps> = props => {
25
26
  const { config, rawData, updateConfig } = useContext<ChartContext>(ConfigContext)
@@ -273,6 +274,15 @@ const PanelSmallMultiples: FC<PanelProps> = props => {
273
274
  }
274
275
  />
275
276
 
277
+ {config.smallMultiples?.mode === 'by-series' &&
278
+ config.smallMultiples?.colorMode === 'same' &&
279
+ hasSeriesColorAssignmentOverrides(config) && (
280
+ <p className='small-multiples-color-assignment-warning mt-1'>
281
+ Color assignments are enabled in the Visual section, so tiles will use their assigned series
282
+ colors instead of the &lsquo;Same Color&rsquo; setting.
283
+ </p>
284
+ )}
285
+
276
286
  {/* Custom Tile Titles - only show for by-column mode */}
277
287
  {config.smallMultiples?.mode === 'by-column' && (
278
288
  <div>