@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
@@ -0,0 +1,112 @@
1
+ /**
2
+ * Builds a palette lookup map with backward-compatibility mappings for forecast charts
3
+ *
4
+ * This function creates multiple naming format mappings to support:
5
+ * - V1 configs using old naming like "Sequential Blue" (Title Case with spaces)
6
+ * - V2 configs using new naming like "sequential-blue" (lowercase with hyphens)
7
+ * - MPX legacy aliases (v1 only)
8
+ *
9
+ * @param processedPalettes - The palette data processed through updatePaletteNames
10
+ * @param paletteVersion - The palette version (1 or 2) from the config
11
+ * @returns A palette map with keys in various formats pointing to color arrays
12
+ */
13
+ export const buildForecastPaletteMappings = (
14
+ processedPalettes: Record<string, string[]>,
15
+ paletteVersion: number
16
+ ): Record<string, string[]> => {
17
+ const paletteMap: Record<string, string[]> = {}
18
+
19
+ // Create base mappings with multiple naming formats for backward compatibility:
20
+ // - sequential-blue (hyphenated)
21
+ // - sequential_blue (underscore)
22
+ // - Sequential Blue (with spaces)
23
+ Object.keys(processedPalettes).forEach(key => {
24
+ const value = processedPalettes[key]
25
+ // Original key
26
+ paletteMap[key] = value
27
+ // Lowercase with hyphens
28
+ paletteMap[key.toLowerCase().replace(/ /g, '-')] = value
29
+ // Lowercase with underscores
30
+ paletteMap[key.toLowerCase().replace(/ /g, '_')] = value
31
+ // Original key variations
32
+ paletteMap[key.replace(/_/g, '-')] = value
33
+ paletteMap[key.toLowerCase()] = value
34
+ })
35
+
36
+ if (paletteVersion === 1) {
37
+ // V1: Add MPX legacy aliases
38
+ // Note: Sequential Blue Two was aliased as "Sequential Blue 2 (MPX)" and Sequential Orange as "Sequential Orange (MPX)"
39
+ const MPX_ALIASES: Record<string, string[]> = {
40
+ 'sequential-blue-two': ['sequential-blue-2-(mpx)', 'sequential-blue-2-(MPX)'],
41
+ 'sequential-blue-tworeverse': ['sequential-blue-2-(mpx)reverse', 'sequential-blue-2-(MPX)reverse'],
42
+ 'sequential-orange': ['sequential-orange-(mpx)', 'sequential-orange-(MPX)'],
43
+ 'sequential-orangereverse': ['sequential-orange-(mpx)reverse', 'sequential-orange-(MPX)reverse']
44
+ }
45
+
46
+ Object.entries(MPX_ALIASES).forEach(([canonical, aliases]) => {
47
+ const palette = paletteMap[canonical]
48
+ if (palette) {
49
+ aliases.forEach(alias => {
50
+ paletteMap[alias] = palette
51
+ })
52
+ }
53
+ })
54
+ } else {
55
+ // V2: Add backward compatibility mappings for migrated configs
56
+ // Map old v1 sequential palette names (Title Case with spaces) to v2 palettes
57
+ // Also includes MPX aliases since users may have selected those in v1
58
+ const V2_MIGRATION_ALIASES: Record<string, string[]> = {
59
+ 'sequential-blue': [
60
+ 'Sequential Blue',
61
+ 'sequential blue',
62
+ 'Sequential Blue Two',
63
+ 'Sequential Blue Three',
64
+ 'sequential-blue-2-(mpx)',
65
+ 'sequential-blue-2-(MPX)',
66
+ 'Sequential Blue 2 (MPX)'
67
+ ],
68
+ 'sequential-bluereverse': [
69
+ 'Sequential Blue Reverse',
70
+ 'sequential bluereverse',
71
+ 'Sequential Blue Two Reverse',
72
+ 'Sequential Blue Three Reverse',
73
+ 'sequential-blue-2-(mpx)reverse',
74
+ 'sequential-blue-2-(MPX)reverse',
75
+ 'Sequential Blue 2 (MPX) Reverse'
76
+ ],
77
+ 'sequential-green': ['Sequential Green', 'sequential green'],
78
+ 'sequential-greenreverse': ['Sequential Green Reverse', 'sequential greenreverse'],
79
+ 'sequential-orange': [
80
+ 'Sequential Orange',
81
+ 'sequential orange',
82
+ 'Sequential Orange Two',
83
+ 'sequential-orange-(mpx)',
84
+ 'sequential-orange-(MPX)',
85
+ 'Sequential Orange (MPX)'
86
+ ],
87
+ 'sequential-orangereverse': [
88
+ 'Sequential Orange Reverse',
89
+ 'sequential orangereverse',
90
+ 'Sequential Orange Two Reverse',
91
+ 'sequential-orange-(mpx)reverse',
92
+ 'sequential-orange-(MPX)reverse',
93
+ 'Sequential Orange (MPX) Reverse'
94
+ ],
95
+ 'sequential-purple': ['Sequential Purple', 'sequential purple'],
96
+ 'sequential-purplereverse': ['Sequential Purple Reverse', 'sequential purplereverse'],
97
+ 'sequential-teal': ['Sequential Teal', 'sequential teal'],
98
+ 'sequential-tealreverse': ['Sequential Teal Reverse', 'sequential tealreverse']
99
+ }
100
+
101
+ Object.entries(V2_MIGRATION_ALIASES).forEach(([canonical, aliases]) => {
102
+ const palette = paletteMap[canonical]
103
+ if (palette) {
104
+ aliases.forEach(alias => {
105
+ paletteMap[alias] = palette
106
+ })
107
+ }
108
+ })
109
+ }
110
+
111
+ return paletteMap
112
+ }
@@ -0,0 +1,71 @@
1
+ /**
2
+ * Builds user-friendly palette options for forecast color dropdowns
3
+ *
4
+ * This function takes processed palette data and transforms it into a format
5
+ * suitable for dropdown UI with clean, readable display names.
6
+ *
7
+ * @param processedPalettes - The palette data processed through updatePaletteNames
8
+ * @param paletteVersion - The palette version (1 or 2) from the config
9
+ * @returns An object with kebab-case keys and user-friendly display names as values
10
+ */
11
+ export const buildForecastPaletteOptions = (
12
+ processedPalettes: Record<string, string[]>,
13
+ paletteVersion: number
14
+ ): Record<string, string> => {
15
+ const paletteOptions: Record<string, string> = {}
16
+
17
+ // Create user-friendly options with clean, readable names
18
+ Object.keys(processedPalettes).forEach(key => {
19
+ // Clean up the display name:
20
+ // 1. Replace underscores with spaces
21
+ // 2. Add space before "reverse" if it's concatenated
22
+ // 3. Capitalize first letter of each word
23
+ const cleanName = key
24
+ .replace(/_/g, ' ') // Replace underscores with spaces
25
+ .replace(/reverse$/i, ' Reverse') // Add space before reverse
26
+ .replace(/\b\w/g, char => char.toUpperCase()) // Capitalize first letter of each word
27
+
28
+ // Use lowercase with hyphens as the key for consistency with existing saved values
29
+ // Convert both underscores and spaces to hyphens
30
+ const displayKey = key.replace(/_/g, '-').replace(/ /g, '-').toLowerCase()
31
+ paletteOptions[displayKey] = cleanName
32
+ })
33
+
34
+ // Add MPX aliases for v1 backward compatibility (these were historical names)
35
+ if (paletteVersion === 1) {
36
+ // Map "Sequential Blue Two" to MPX alias
37
+ if (paletteOptions['sequential-blue-two']) {
38
+ paletteOptions['sequential-blue-2-(mpx)'] = 'Sequential Blue 2 (MPX)'
39
+ }
40
+ if (paletteOptions['sequential-blue-tworeverse']) {
41
+ paletteOptions['sequential-blue-2-(mpx)reverse'] = 'Sequential Blue 2 (MPX) Reverse'
42
+ }
43
+ // Map "Sequential Orange" to MPX alias
44
+ if (paletteOptions['sequential-orange']) {
45
+ paletteOptions['sequential-orange-(mpx)'] = 'Sequential Orange (MPX)'
46
+ }
47
+ if (paletteOptions['sequential-orangereverse']) {
48
+ paletteOptions['sequential-orange-(mpx)reverse'] = 'Sequential Orange (MPX) Reverse'
49
+ }
50
+ } else {
51
+ // V2 backward compatibility: add options for old v1 sequential palette names
52
+ // These are for migrated configs that still have v1-style names like "Sequential Blue"
53
+ if (paletteOptions['sequential-blue']) {
54
+ paletteOptions['sequential-blue'] = 'Sequential Blue'
55
+ }
56
+ if (paletteOptions['sequential-green']) {
57
+ paletteOptions['sequential-green'] = 'Sequential Green'
58
+ }
59
+ if (paletteOptions['sequential-orange']) {
60
+ paletteOptions['sequential-orange'] = 'Sequential Orange'
61
+ }
62
+ if (paletteOptions['sequential-purple']) {
63
+ paletteOptions['sequential-purple'] = 'Sequential Purple'
64
+ }
65
+ if (paletteOptions['sequential-teal']) {
66
+ paletteOptions['sequential-teal'] = 'Sequential Teal'
67
+ }
68
+ }
69
+
70
+ return paletteOptions
71
+ }
@@ -1,20 +1,94 @@
1
- import { colorPalettesChart as colorPalettes, twoColorPalette } from '@cdc/core/data/colorPalettes'
1
+ import { twoColorPalette } from '@cdc/core/data/colorPalettes'
2
+ import { filterChartColorPalettes } from '@cdc/core/helpers/filterColorPalettes'
3
+ import { getColorPaletteVersion } from '@cdc/core/helpers/getColorPaletteVersion'
2
4
  import { scaleOrdinal } from '@visx/scale'
3
5
  import { ChartConfig } from '../types/ChartConfig'
6
+ import { paletteMigrationMap } from '@cdc/core/helpers/palettes/migratePaletteName'
7
+ import { getFallbackColorPalette, migratePaletteWithMap } from '@cdc/core/helpers/palettes/utils'
8
+ import {
9
+ v2ColorDistribution,
10
+ divergentColorDistribution,
11
+ colorblindColorDistribution
12
+ } from '@cdc/core/helpers/palettes/colorDistributions'
4
13
 
5
14
  export const getColorScale = (config: ChartConfig): ((value: string) => string) => {
6
15
  const configPalette = ['Paired Bar', 'Deviation Bar'].includes(config.visualizationType)
7
16
  ? config.twoColor.palette
8
- : config.palette
9
- const allPalettes: Record<string, string[]> = { ...colorPalettes, ...twoColorPalette }
10
- let palette = config.customColors || allPalettes[configPalette]
11
- let numberOfKeys = config.runtime.seriesKeys.length
17
+ : config.general?.palette?.name
18
+ const colorPalettes = filterChartColorPalettes(config)
19
+
20
+ // Get the correct version of two-color palettes
21
+ const version = getColorPaletteVersion(config)
22
+ const versionKey = `v${version}`
23
+ const versionedTwoColorPalette = twoColorPalette[versionKey] || twoColorPalette.v2
24
+
25
+ // For paired/deviation bars, only use two-color palettes
26
+ const palettesSource = ['Paired Bar', 'Deviation Bar'].includes(config.visualizationType)
27
+ ? versionedTwoColorPalette
28
+ : colorPalettes
29
+
30
+ const allPalettes: Record<string, string[]> = { ...versionedTwoColorPalette, ...colorPalettes }
31
+
32
+ // Migrate old palette name if needed
33
+ const migratedPaletteName = configPalette ? configPalette : getFallbackColorPalette(config)
34
+
35
+ // Check for customColorsOrdered first (direct 1-to-1 mapping, no distribution needed)
36
+ if (config.general?.palette?.customColorsOrdered && Array.isArray(config.general.palette.customColorsOrdered)) {
37
+ const customColorsOrdered = config.general.palette.customColorsOrdered
38
+ return scaleOrdinal({
39
+ domain: config.runtime.seriesLabelsAll,
40
+ range: customColorsOrdered,
41
+ unknown: null
42
+ })
43
+ }
12
44
 
13
- while (numberOfKeys > palette.length) {
14
- palette = palette.concat(palette)
45
+ let palette =
46
+ config.general?.palette?.customColors ||
47
+ palettesSource[migratePaletteWithMap(migratedPaletteName, paletteMigrationMap, false)] ||
48
+ palettesSource[configPalette]
49
+
50
+ // Fallback to a default palette if none found
51
+ if (!palette) {
52
+ console.warn(`Palette "${configPalette}" not found, falling back to default`)
53
+ palette = Object.values(allPalettes)[0] || ['#1f77b4', '#ff7f0e', '#2ca02c', '#d62728', '#9467bd']
15
54
  }
16
55
 
17
- palette = palette.slice(0, numberOfKeys)
56
+ let numberOfKeys = config.runtime.seriesKeys.length
57
+
58
+ // Apply enhanced color distribution (same logic as pie charts)
59
+ const paletteVersion = getColorPaletteVersion(config)
60
+
61
+ // Skip enhanced distribution if not v2, too many keys, or wrong palette length
62
+ if (paletteVersion !== 2 || numberOfKeys > 9 || palette.length !== 9) {
63
+ // Use existing logic for v1 palettes and other cases
64
+ while (numberOfKeys > palette.length) {
65
+ palette = palette.concat(palette)
66
+ }
67
+ palette = palette.slice(0, numberOfKeys)
68
+ } else {
69
+ // Apply enhanced distribution for v2 palettes
70
+ const isSequential = configPalette && configPalette.includes('sequential')
71
+ const isDivergent = configPalette && configPalette.includes('divergent')
72
+ const isColorblindSafe =
73
+ configPalette && (configPalette.includes('colorblindsafe') || configPalette.includes('qualitative_standard'))
74
+
75
+ // Determine which distribution to use based on palette type
76
+ let distributionMap = null
77
+ if (isDivergent) {
78
+ distributionMap = divergentColorDistribution
79
+ } else if (isColorblindSafe) {
80
+ distributionMap = colorblindColorDistribution
81
+ } else if (isSequential) {
82
+ distributionMap = v2ColorDistribution
83
+ }
84
+
85
+ if (distributionMap && distributionMap[numberOfKeys]) {
86
+ const distributionIndices = distributionMap[numberOfKeys]
87
+ palette = distributionIndices.map((index: number) => palette[index])
88
+ } else {
89
+ palette = palette.slice(0, numberOfKeys)
90
+ }
91
+ }
18
92
 
19
93
  return scaleOrdinal({
20
94
  domain: config.runtime.seriesLabelsAll,
@@ -1,9 +1,7 @@
1
1
  import { ChartConfig } from '../types/ChartConfig'
2
2
  import _ from 'lodash'
3
- import ConfigContext from '../ConfigContext'
4
- import { useContext } from 'react'
5
3
 
6
- type UseMinMaxProps = {
4
+ type GetMinMaxProps = {
7
5
  /** config - standard chart config */
8
6
  config: ChartConfig
9
7
  /** minValue - starting minimum value */
@@ -18,9 +16,20 @@ type UseMinMaxProps = {
18
16
  tableData: Object[]
19
17
  /** isAllLine: if all series are line type including dashed lines */
20
18
  isAllLine: boolean
19
+ /** convertLineToBarGraph - whether line charts should be rendered as bar graphs */
20
+ convertLineToBarGraph?: boolean
21
21
  }
22
22
 
23
- const useMinMax = ({ config, minValue, maxValue, existPositiveValue, data, isAllLine, tableData }: UseMinMaxProps) => {
23
+ const getMinMax = ({
24
+ config,
25
+ minValue,
26
+ maxValue,
27
+ existPositiveValue,
28
+ data,
29
+ isAllLine,
30
+ tableData,
31
+ convertLineToBarGraph
32
+ }: GetMinMaxProps) => {
24
33
  let min = 0
25
34
  let max = 0
26
35
 
@@ -28,8 +37,6 @@ const useMinMax = ({ config, minValue, maxValue, existPositiveValue, data, isAll
28
37
  let leftMax = 0
29
38
  let rightMax = 0
30
39
 
31
- const { convertLineToBarGraph } = useContext(ConfigContext)
32
-
33
40
  if (!data) {
34
41
  return { min, max }
35
42
  }
@@ -238,4 +245,4 @@ const useMinMax = ({ config, minValue, maxValue, existPositiveValue, data, isAll
238
245
 
239
246
  return { min, max, leftMax, rightMax }
240
247
  }
241
- export default useMinMax
248
+ export default getMinMax
@@ -1,7 +1,7 @@
1
1
  import _ from 'lodash'
2
2
 
3
3
  export const getNewRuntime = (visualizationConfig, newFilteredData) => {
4
- const runtime = _.cloneDeep(visualizationConfig.runtime) || {}
4
+ const runtime = visualizationConfig.runtime ? { ...visualizationConfig.runtime } : {}
5
5
  runtime.series = []
6
6
  runtime.seriesLabels = {}
7
7
  runtime.seriesLabelsAll = []
@@ -14,7 +14,7 @@ export const getTransformedData = ({
14
14
  const data =
15
15
  Array.isArray(brushData) && brushData.length > 0
16
16
  ? brushData
17
- : Array.isArray(filteredData) && filteredData.length > 0
17
+ : Array.isArray(filteredData)
18
18
  ? filteredData
19
19
  : excludedData
20
20
 
@@ -0,0 +1,53 @@
1
+ import { ChartConfig } from '../types/ChartConfig'
2
+
3
+ /**
4
+ * Calculates the Y-axis auto padding to prevent data labels from overlapping with axis tick labels.
5
+ * This is used when inline labels are enabled and there's potential for overlap.
6
+ *
7
+ * @param yScale - The D3 scale object for the Y-axis (must have .ticks() method)
8
+ * @param handleNumTicks - The number of ticks to display on the axis
9
+ * @param maxValue - The maximum data value (from useReduceData)
10
+ * @param minValue - The minimum data value (from useReduceData)
11
+ * @param config - The chart configuration object
12
+ * @returns The calculated auto padding percentage (0-100+), or 0 if no padding needed
13
+ */
14
+ export const getYAxisAutoPadding = (
15
+ yScale: any,
16
+ handleNumTicks: number,
17
+ maxValue: number,
18
+ minValue: number,
19
+ config: ChartConfig
20
+ ): number => {
21
+ // Early returns for cases where auto padding is not needed
22
+ if (!yScale?.ticks || config.orientation === 'horizontal' || config.yAxis?.max) {
23
+ return 0
24
+ }
25
+
26
+ const ticks = yScale.ticks(handleNumTicks)
27
+
28
+ if (!Array.isArray(ticks) || ticks.length === 0) {
29
+ return 0
30
+ }
31
+
32
+ // minimum percentage of the max value that the distance should be from the top grid line
33
+ const MINIMUM_DISTANCE_PERCENTAGE = 0.025
34
+
35
+ const topGridLine = Math.max(...ticks)
36
+ const needsPaddingThreshold = topGridLine - maxValue * MINIMUM_DISTANCE_PERCENTAGE
37
+ const maxValueIsGreaterThanThreshold = maxValue > needsPaddingThreshold
38
+
39
+ if (!maxValueIsGreaterThanThreshold) return 0
40
+
41
+ const tickGap = ticks.length === 1 ? ticks[0] : ticks[1] - ticks[0]
42
+ const nextTick = Math.max(...ticks) + tickGap
43
+ const divideBy = minValue < 0 ? maxValue / 2 : maxValue
44
+ const calculatedPadding = (nextTick - maxValue) / divideBy
45
+
46
+ // if auto padding is too close to next tick, add one more ticks worth of padding
47
+ const newPadding =
48
+ calculatedPadding > MINIMUM_DISTANCE_PERCENTAGE ? calculatedPadding : calculatedPadding + tickGap / divideBy
49
+
50
+ /* sometimes even though the padding is getting to the next tick exactly,
51
+ d3 still doesn't show the tick. we add 0.1 to ensure to tip it over the edge */
52
+ return newPadding * 100 + 0.1
53
+ }