@cdc/chart 4.24.7 → 4.24.9-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 (53) hide show
  1. package/LICENSE +201 -0
  2. package/dist/cdcchart.js +47567 -42391
  3. package/examples/cases-year.json +13379 -0
  4. package/examples/gallery/bar-chart-vertical/combo-line-chart.json +76 -15
  5. package/examples/gallery/bar-chart-vertical/vertical-bar-chart-stacked.json +5 -5
  6. package/index.html +17 -8
  7. package/package.json +2 -2
  8. package/src/CdcChart.tsx +382 -133
  9. package/src/_stories/Chart.Legend.Gradient.tsx +19 -0
  10. package/src/_stories/_mock/legend.gradient_mock.json +236 -0
  11. package/src/components/Annotations/components/AnnotationDraggable.tsx +64 -11
  12. package/src/components/Axis/Categorical.Axis.tsx +145 -0
  13. package/src/components/BarChart/components/BarChart.Horizontal.tsx +4 -3
  14. package/src/components/BarChart/components/BarChart.StackedHorizontal.tsx +1 -1
  15. package/src/components/BarChart/components/BarChart.StackedVertical.tsx +2 -5
  16. package/src/components/BarChart/components/BarChart.Vertical.tsx +17 -8
  17. package/src/components/BarChart/helpers/index.ts +5 -16
  18. package/src/components/BrushChart.tsx +205 -0
  19. package/src/components/EditorPanel/EditorPanel.tsx +1767 -510
  20. package/src/components/EditorPanel/components/Panels/Panel.Annotate.tsx +22 -8
  21. package/src/components/EditorPanel/components/Panels/Panel.General.tsx +190 -37
  22. package/src/components/EditorPanel/components/Panels/Panel.Sankey.tsx +43 -7
  23. package/src/components/EditorPanel/components/Panels/Panel.Series.tsx +4 -4
  24. package/src/components/EditorPanel/components/Panels/Panel.Visual.tsx +1 -11
  25. package/src/components/EditorPanel/editor-panel.scss +16 -3
  26. package/src/components/EditorPanel/{useEditorPermissions.js → useEditorPermissions.ts} +90 -19
  27. package/src/components/Legend/Legend.Component.tsx +185 -193
  28. package/src/components/Legend/Legend.Suppression.tsx +146 -0
  29. package/src/components/Legend/Legend.tsx +21 -5
  30. package/src/components/Legend/helpers/index.ts +33 -3
  31. package/src/components/LegendWrapper.tsx +26 -0
  32. package/src/components/LineChart/LineChartProps.ts +1 -18
  33. package/src/components/LineChart/components/LineChart.BumpCircle.tsx +103 -0
  34. package/src/components/LineChart/components/LineChart.Circle.tsx +57 -8
  35. package/src/components/LineChart/helpers.ts +55 -11
  36. package/src/components/LineChart/index.tsx +113 -38
  37. package/src/components/LinearChart.tsx +1366 -0
  38. package/src/components/PieChart/PieChart.tsx +74 -17
  39. package/src/components/Sankey/index.tsx +22 -16
  40. package/src/components/Sparkline/components/SparkLine.tsx +2 -2
  41. package/src/data/initial-state.js +13 -3
  42. package/src/hooks/useLegendClasses.ts +52 -15
  43. package/src/hooks/useMinMax.ts +4 -4
  44. package/src/hooks/useScales.ts +34 -24
  45. package/src/hooks/useTooltip.tsx +85 -22
  46. package/src/scss/DataTable.scss +2 -1
  47. package/src/scss/main.scss +107 -14
  48. package/src/types/ChartConfig.ts +34 -8
  49. package/src/types/ChartContext.ts +5 -4
  50. package/examples/feature/line/line-chart.json +0 -449
  51. package/src/components/BrushHandle.jsx +0 -17
  52. package/src/components/LineChart/index.scss +0 -1
  53. package/src/components/LinearChart.jsx +0 -817
@@ -0,0 +1,19 @@
1
+ import type { Meta, StoryObj } from '@storybook/react'
2
+ import chartGradientConfig from './_mock/legend.gradient_mock.json'
3
+
4
+ import Chart from '../CdcChart'
5
+
6
+ const meta: Meta<typeof Chart> = {
7
+ title: 'Components/Templates/Chart/Legend',
8
+ component: Chart
9
+ }
10
+
11
+ type Story = StoryObj<typeof Chart>
12
+
13
+ export const Legend_gradient: Story = {
14
+ args: {
15
+ config: chartGradientConfig
16
+ }
17
+ }
18
+
19
+ export default meta
@@ -0,0 +1,236 @@
1
+ {
2
+ "annotations": [],
3
+ "type": "chart",
4
+ "debugSvg": false,
5
+ "chartMessage": { "noData": "No Data Available" },
6
+ "title": "Combo Bar-Line Chart",
7
+ "showTitle": true,
8
+ "showDownloadMediaButton": false,
9
+ "theme": "theme-purple",
10
+ "animate": false,
11
+ "fontSize": "medium",
12
+ "lineDatapointStyle": "hover",
13
+ "lineDatapointColor": "Same as Line",
14
+ "barHasBorder": "false",
15
+ "isLollipopChart": false,
16
+ "lollipopShape": "circle",
17
+ "lollipopColorStyle": "two-tone",
18
+ "visualizationSubType": "regular",
19
+ "barStyle": "flat",
20
+ "roundingStyle": "standard",
21
+ "tipRounding": "top",
22
+ "isResponsiveTicks": false,
23
+ "general": { "annotationDropdownText": "Annotations", "showDownloadButton": false, "showMissingDataLabel": true, "showSuppressedSymbol": true, "showZeroValueDataLabel": true },
24
+ "padding": { "left": 5, "right": 5 },
25
+ "preliminaryData": [],
26
+ "yAxis": {
27
+ "hideAxis": false,
28
+ "displayNumbersOnBar": false,
29
+ "hideLabel": false,
30
+ "hideTicks": false,
31
+ "size": "68",
32
+ "gridLines": true,
33
+ "enablePadding": false,
34
+ "min": "",
35
+ "max": "",
36
+ "labelColor": "#333",
37
+ "tickLabelColor": "#333",
38
+ "tickColor": "#333",
39
+ "rightHideAxis": true,
40
+ "rightAxisSize": 50,
41
+ "rightLabel": "",
42
+ "rightLabelOffsetSize": 0,
43
+ "rightAxisLabelColor": "#333",
44
+ "rightAxisTickLabelColor": "#333",
45
+ "rightAxisTickColor": "#333",
46
+ "numTicks": "",
47
+ "axisPadding": 0,
48
+ "scalePadding": 10,
49
+ "tickRotation": 0,
50
+ "anchors": [],
51
+ "shoMissingDataLabel": true,
52
+ "showMissingDataLine": true,
53
+ "categories": [],
54
+ "label": "Y-Axis Label Example",
55
+ "maxValue": 1000
56
+ },
57
+ "boxplot": {
58
+ "plots": [],
59
+ "borders": "true",
60
+ "firstQuartilePercentage": 25,
61
+ "thirdQuartilePercentage": 75,
62
+ "boxWidthPercentage": 40,
63
+ "plotOutlierValues": false,
64
+ "plotNonOutlierValues": true,
65
+ "legend": { "showHowToReadText": false, "howToReadText": "" },
66
+ "labels": { "q1": "Lower Quartile", "q2": "q2", "q3": "Upper Quartile", "q4": "q4", "minimum": "Minimum", "maximum": "Maximum", "mean": "Mean", "median": "Median", "sd": "Standard Deviation", "iqr": "Interquartile Range", "total": "Total", "outliers": "Outliers", "values": "Values" }
67
+ },
68
+ "topAxis": { "hasLine": false },
69
+ "isLegendValue": false,
70
+ "barThickness": 0.35,
71
+ "barHeight": 25,
72
+ "barSpace": 15,
73
+ "heights": { "vertical": 300, "horizontal": 750 },
74
+ "xAxis": {
75
+ "sortDates": false,
76
+ "anchors": [],
77
+ "type": "date-time",
78
+ "showTargetLabel": true,
79
+ "targetLabel": "Target",
80
+ "hideAxis": false,
81
+ "hideLabel": false,
82
+ "hideTicks": false,
83
+ "size": "78",
84
+ "tickRotation": "25",
85
+ "min": "",
86
+ "max": "",
87
+ "labelColor": "#333",
88
+ "tickLabelColor": "#333",
89
+ "tickColor": "#333",
90
+ "numTicks": "",
91
+ "labelOffset": 65,
92
+ "axisPadding": 0,
93
+ "target": 0,
94
+ "maxTickRotation": 0,
95
+ "dataKey": "Date",
96
+ "label": "X-Axis Example Label",
97
+ "dateParseFormat": "%m/%d/%Y",
98
+ "dateDisplayFormat": "%m/%d/%Y",
99
+ "tickWidthMax": 91,
100
+ "padding": 6,
101
+ "axisBBox": 164.5282745361328
102
+ },
103
+ "table": {
104
+ "label": "Data Table",
105
+ "expanded": true,
106
+ "limitHeight": false,
107
+ "height": "",
108
+ "caption": "",
109
+ "showDownloadUrl": false,
110
+ "showDataTableLink": true,
111
+ "indexLabel": "",
112
+ "download": true,
113
+ "showVertical": false,
114
+ "dateDisplayFormat": "",
115
+ "showMissingDataLabel": true,
116
+ "showSuppressedSymbol": true,
117
+ "show": true
118
+ },
119
+ "orientation": "vertical",
120
+ "color": "pinkpurple",
121
+ "columns": {},
122
+ "legend": {
123
+ "hide": false,
124
+ "behavior": "highlight",
125
+ "axisAlign": true,
126
+ "singleRow": false,
127
+ "colorCode": "",
128
+ "reverseLabelOrder": false,
129
+ "description": "",
130
+ "dynamicLegend": false,
131
+ "dynamicLegendDefaultText": "Show All",
132
+ "dynamicLegendItemLimit": 5,
133
+ "dynamicLegendItemLimitMessage": "Dynamic Legend Item Limit Hit.",
134
+ "dynamicLegendChartMessage": "Select Options from the Legend",
135
+ "label": "",
136
+ "lineMode": false,
137
+ "verticalSorted": false,
138
+ "highlightOnHover": false,
139
+ "hideSuppressedLabels": false,
140
+ "seriesHighlight": [],
141
+ "style": "gradient",
142
+ "subStyle": "smooth",
143
+ "hasBorder": true,
144
+ "tickRotation": "0",
145
+ "position": "top"
146
+ },
147
+ "brush": {
148
+ "height": 25,
149
+ "active": false,
150
+ "data": [
151
+ { "Date": "1/15/2016", "Data 1": "1000", "Data 2": "110", "Data 3": "100", "Data 4": "90", "Monthly-Goal": "100" },
152
+ { "Date": "2/15/2016", "Data 1": "100", "Data 2": "110", "Data 3": "100", "Data 4": "100", "Monthly-Goal": "100" },
153
+ { "Date": "3/15/2016", "Data 1": "80", "Data 2": "90", "Data 3": "100", "Data 4": "120", "Monthly-Goal": "110" },
154
+ { "Date": "4/15/2016", "Data 1": "80", "Data 2": "90", "Data 3": "110", "Data 4": "120", "Monthly-Goal": "110" },
155
+ { "Date": "5/15/2016", "Data 1": "70", "Data 2": "90", "Data 3": "110", "Data 4": "130", "Monthly-Goal": "120" },
156
+ { "Date": "6/15/2016", "Data 1": "100", "Data 2": "120", "Data 3": "120", "Data 4": "130", "Monthly-Goal": "120" },
157
+ { "Date": "7/15/2016", "Data 1": "110", "Data 2": "140", "Data 3": "120", "Data 4": "130", "Monthly-Goal": "130" },
158
+ { "Date": "8/15/2016", "Data 1": "110", "Data 2": "130", "Data 3": "120", "Data 4": "140", "Monthly-Goal": "130" },
159
+ { "Date": "9/15/2016", "Data 1": "120", "Data 2": "130", "Data 3": "120", "Data 4": "150", "Monthly-Goal": "140" }
160
+ ]
161
+ },
162
+ "exclusions": { "active": false, "keys": [] },
163
+ "palette": "sequential-blue",
164
+ "isPaletteReversed": false,
165
+ "twoColor": { "palette": "monochrome-1", "isPaletteReversed": false },
166
+ "labels": false,
167
+ "dataFormat": { "commas": false, "prefix": "", "suffix": "", "abbreviated": false, "bottomSuffix": "", "bottomPrefix": "", "bottomAbbreviated": false },
168
+ "confidenceKeys": {},
169
+ "visual": { "border": true, "accent": true, "background": true, "verticalHoverLine": false, "horizontalHoverLine": false },
170
+ "useLogScale": false,
171
+ "filterBehavior": "Filter Change",
172
+ "highlightedBarValues": [],
173
+ "series": [
174
+ { "dataKey": "Data 2", "type": "Bar", "axis": "Left", "tooltip": true },
175
+ { "dataKey": "Data 1", "type": "Bar", "axis": "Left", "tooltip": true },
176
+ { "dataKey": "Data 3", "type": "Bar", "axis": "Left", "tooltip": true }
177
+ ],
178
+ "tooltips": { "opacity": 90, "singleSeries": false, "dateDisplayFormat": "" },
179
+ "forestPlot": {
180
+ "startAt": 0,
181
+ "colors": { "line": "", "shape": "" },
182
+ "lineOfNoEffect": { "show": true },
183
+ "type": "",
184
+ "pooledResult": { "diamondHeight": 5, "column": "" },
185
+ "estimateField": "",
186
+ "estimateRadius": "",
187
+ "shape": "",
188
+ "rowHeight": 20,
189
+ "description": { "show": true, "text": "description", "location": 0 },
190
+ "result": { "show": true, "text": "result", "location": 100 },
191
+ "radius": { "min": 1, "max": 8, "scalingColumn": "" },
192
+ "regression": { "lower": 0, "upper": 0, "estimateField": 0 },
193
+ "leftWidthOffset": 0,
194
+ "rightWidthOffset": 0,
195
+ "showZeroLine": false,
196
+ "leftLabel": "",
197
+ "rightLabel": "",
198
+ "hideDateCategoryCol": false
199
+ },
200
+ "area": { "isStacked": false },
201
+ "sankey": {
202
+ "title": { "defaultColor": "black" },
203
+ "iterations": 1,
204
+ "rxValue": 0.9,
205
+ "overallSize": { "width": 900, "height": 700 },
206
+ "margin": { "margin_y": 25, "margin_x": 0 },
207
+ "nodeSize": { "nodeWidth": 26, "nodeHeight": 40 },
208
+ "nodePadding": 55,
209
+ "nodeFontColor": "black",
210
+ "nodeColor": { "default": "#ff8500", "inactive": "#808080" },
211
+ "linkColor": { "default": "#ffc900", "inactive": "#D3D3D3" },
212
+ "opacity": { "nodeOpacityDefault": 1, "nodeOpacityInactive": 0.1, "LinkOpacityDefault": 1, "LinkOpacityInactive": 0.1 },
213
+ "storyNodeFontColor": "#006778",
214
+ "storyNodeText": [],
215
+ "nodeValueStyle": { "textBefore": "(", "textAfter": ")" },
216
+ "data": []
217
+ },
218
+ "suppressedData": [],
219
+ "height": "332",
220
+ "data": [
221
+ { "Date": "1/15/2016", "Data 1": "$1,000", "Data 2": "110", "Data 3": "100", "Data 4": "90", "Monthly-Goal": "100" },
222
+ { "Date": "2/15/2016", "Data 1": "100", "Data 2": "110", "Data 3": "100", "Data 4": "100", "Monthly-Goal": "100" },
223
+ { "Date": "3/15/2016", "Data 1": "80", "Data 2": "90", "Data 3": "100", "Data 4": "120", "Monthly-Goal": "110" },
224
+ { "Date": "4/15/2016", "Data 1": "80", "Data 2": "90", "Data 3": "110", "Data 4": "120", "Monthly-Goal": "110" },
225
+ { "Date": "5/15/2016", "Data 1": "70", "Data 2": "90", "Data 3": "110", "Data 4": "130", "Monthly-Goal": "120" },
226
+ { "Date": "6/15/2016", "Data 1": "100", "Data 2": "120", "Data 3": "120", "Data 4": "130", "Monthly-Goal": "120" },
227
+ { "Date": "7/15/2016", "Data 1": "110", "Data 2": "140", "Data 3": "120", "Data 4": "130", "Monthly-Goal": "130" },
228
+ { "Date": "8/15/2016", "Data 1": "110", "Data 2": "130", "Data 3": "120", "Data 4": "140", "Monthly-Goal": "130" },
229
+ { "Date": "9/15/2016", "Data 1": "120", "Data 2": "130", "Data 3": "120", "Data 4": "150", "Monthly-Goal": "140" }
230
+ ],
231
+ "visualizationType": "Bar",
232
+ "filters": [],
233
+ "validated": 4.23,
234
+ "dynamicMarginTop": 0,
235
+ "version": "4.24.9"
236
+ }
@@ -90,9 +90,17 @@ const Annotations = ({ xScale, yScale, xScaleAnnotation, xMax, svgRef, onDragSta
90
90
  props.x
91
91
  )
92
92
 
93
- updatedAnnotations[index] = { ...updatedAnnotations[index], x: xScaleAnnotation.invert(xScale(nearestDatum.x)), y: yScale(nearestDatum.y) }
93
+ updatedAnnotations[index] = {
94
+ ...updatedAnnotations[index],
95
+ x: xScaleAnnotation.invert(xScale(nearestDatum.x)),
96
+ y: yScale(nearestDatum.y)
97
+ }
94
98
  } else {
95
- updatedAnnotations[index] = { ...updatedAnnotations[index], x: xScaleAnnotation.invert(props.x), y: props.y }
99
+ updatedAnnotations[index] = {
100
+ ...updatedAnnotations[index],
101
+ x: xScaleAnnotation.invert(props.x),
102
+ y: props.y
103
+ }
96
104
  }
97
105
  }
98
106
 
@@ -102,7 +110,12 @@ const Annotations = ({ xScale, yScale, xScaleAnnotation, xMax, svgRef, onDragSta
102
110
  })
103
111
  }}
104
112
  >
105
- <HtmlLabel className='annotation__desktop-label' showAnchorLine={false} horizontalAnchor={handleConnectionHorizontalType(annotation, xScale, config)} verticalAnchor={handleConnectionVerticalType(annotation, xScale, config)}>
113
+ <HtmlLabel
114
+ className='annotation__desktop-label'
115
+ showAnchorLine={false}
116
+ horizontalAnchor={handleConnectionHorizontalType(annotation, xScale, config)}
117
+ verticalAnchor={handleConnectionVerticalType(annotation, xScale, config)}
118
+ >
106
119
  <div
107
120
  style={{
108
121
  borderRadius: 5, // Optional: set border radius
@@ -113,7 +126,7 @@ const Annotations = ({ xScale, yScale, xScaleAnnotation, xMax, svgRef, onDragSta
113
126
  justifyContent: 'start',
114
127
  flexDirection: 'row'
115
128
  }}
116
- role='presentation'
129
+ // role='presentation'
117
130
  tabIndex={0}
118
131
  aria-label={`Annotation text that reads: ${annotation.text}`}
119
132
  >
@@ -127,22 +140,62 @@ const Annotations = ({ xScale, yScale, xScaleAnnotation, xMax, svgRef, onDragSta
127
140
  <div style={{ fontSize: fontSizes[config.fontSize] }} dangerouslySetInnerHTML={sanitizedData()} />
128
141
  </div>
129
142
  </HtmlLabel>
130
- {annotation.connectionType === 'line' && <Connector type='line' pathProps={{ markerStart: `url(#marker-start--${index})` }} />}
131
- {annotation.connectionType === 'elbow' && <Connector type='elbow' pathProps={{ markerStart: `url(#marker-start--${index})` }} />}
143
+ {annotation.connectionType === 'line' && (
144
+ <Connector type='line' pathProps={{ markerStart: `url(#marker-start--${index})` }} />
145
+ )}
146
+ {annotation.connectionType === 'elbow' && (
147
+ <Connector type='elbow' pathProps={{ markerStart: `url(#marker-start--${index})` }} />
148
+ )}
132
149
  {annotation.connectionType === 'curve' && (
133
150
  <LinePath
134
151
  d={`M ${annotationX},${annotation.y}
135
- Q ${annotationX + annotation.dx / 2}, ${annotation.y + annotation.dy / 2 + Number(annotation?.bezier) || 0} ${annotationX + annotation.dx},${annotation.y + annotation.dy}`}
152
+ Q ${annotationX + annotation.dx / 2}, ${
153
+ annotation.y + annotation.dy / 2 + Number(annotation?.bezier) || 0
154
+ } ${annotationX + annotation.dx},${annotation.y + annotation.dy}`}
136
155
  stroke='black'
137
156
  strokeWidth='2'
138
157
  fill='none'
139
158
  marker-start={`url(#marker-start--${index})`}
140
159
  />
141
160
  )}
142
- {annotation.marker === 'circle' && <CircleSubject id={`marker-start--${index}`} className='circle-subject' stroke={colorScale(annotation.seriesKey)} radius={8} />}
143
- {annotation.marker === 'arrow' && <MarkerArrow fill='black' id={`marker-start--${index}`} x={annotationX} y={annotation.y} stroke='#333' markerWidth={10} size={10} strokeWidth={1} orient='auto-start-reverse' markerUnits='userSpaceOnUse' />}
144
- <circle fill='white' cx={annotationX + annotation.dx} cy={annotation.y + annotation.dy} r={16} className='annotation__mobile-label annotation__mobile-label-circle' stroke={colorScale(annotation.seriesKey)} />
145
- <text height={16} x={annotationX + annotation.dx} y={annotation.y + annotation.dy} className='annotation__mobile-label' alignmentBaseline='middle' textAnchor='middle'>
161
+ {annotation.marker === 'circle' && (
162
+ <CircleSubject
163
+ id={`marker-start--${index}`}
164
+ className='circle-subject'
165
+ stroke={colorScale(annotation.seriesKey)}
166
+ radius={8}
167
+ />
168
+ )}
169
+ {annotation.marker === 'arrow' && (
170
+ <MarkerArrow
171
+ fill='black'
172
+ id={`marker-start--${index}`}
173
+ x={annotationX}
174
+ y={annotation.y}
175
+ stroke='#333'
176
+ markerWidth={10}
177
+ size={10}
178
+ strokeWidth={1}
179
+ orient='auto-start-reverse'
180
+ markerUnits='userSpaceOnUse'
181
+ />
182
+ )}
183
+ <circle
184
+ fill='white'
185
+ cx={annotationX + annotation.dx}
186
+ cy={annotation.y + annotation.dy}
187
+ r={16}
188
+ className='annotation__mobile-label annotation__mobile-label-circle'
189
+ stroke={colorScale(annotation.seriesKey)}
190
+ />
191
+ <text
192
+ height={16}
193
+ x={annotationX + annotation.dx}
194
+ y={annotation.y + annotation.dy}
195
+ className='annotation__mobile-label'
196
+ alignmentBaseline='middle'
197
+ textAnchor='middle'
198
+ >
146
199
  {index + 1}
147
200
  </text>
148
201
  </AnnotationComponent>
@@ -0,0 +1,145 @@
1
+ import React, { useContext } from 'react'
2
+ import { BarStack, Line } from '@visx/shape'
3
+ import { scaleBand, scaleLinear, scaleOrdinal } from '@visx/scale'
4
+ import { Group } from '@visx/group'
5
+ import { Text } from '@visx/text'
6
+ import ConfigContext from '../../ConfigContext'
7
+ import chroma from 'chroma-js'
8
+ import createBarElement from '@cdc/core/components/createBarElement'
9
+ import { useBarChart } from '../../hooks/useBarChart'
10
+
11
+ const CategoricalYAxis = ({ yMax, leftSize, max, xMax }) => {
12
+ const { config, getTextWidth } = useContext(ConfigContext)
13
+ const { fontSize } = useBarChart()
14
+
15
+ const { orientation } = config
16
+
17
+ const getValidColor = (color, defaultColor = '#f1f1f1') => {
18
+ try {
19
+ return chroma(color).hex() // Returns the color if valid
20
+ } catch (e) {
21
+ return defaultColor
22
+ }
23
+ }
24
+
25
+ const categories = config.yAxis?.categories
26
+
27
+ const createDataShape = categories => {
28
+ const categoryObj = [...categories].reduce((acc, item) => {
29
+ acc[item.label] = item.height
30
+ return acc
31
+ }, {})
32
+
33
+ return categoryObj
34
+ }
35
+ const updateCategory = categoryObj => {
36
+ // Get all the heights in the object
37
+ const heights = Object.keys(categoryObj)
38
+
39
+ // Get the last label
40
+ const lastheight = heights[heights.length - 1]
41
+
42
+ // Check if the last label's value is empty
43
+ if (categoryObj[lastheight] === '') {
44
+ // Calculate the sum of the numeric values of all other heights
45
+ const sumOfValues = heights.slice(0, -1).reduce((sum, label) => {
46
+ const value = parseInt(categoryObj[label], 10)
47
+ return sum + (isNaN(value) ? 0 : value)
48
+ }, 0)
49
+
50
+ // Calculate the new value for the last emty height
51
+ const newValue = max - sumOfValues
52
+
53
+ // Update the last height with the new value
54
+ categoryObj[lastheight] = newValue.toString()
55
+ }
56
+
57
+ return [categoryObj]
58
+ }
59
+
60
+ const transformedData = updateCategory(createDataShape(categories))
61
+
62
+ // Define the scales
63
+ const xScaleValue = 0
64
+
65
+ const xScale = scaleBand<number>({
66
+ domain: [xScaleValue],
67
+ padding: 0,
68
+ range: [0, leftSize]
69
+ })
70
+
71
+ const yScale = scaleLinear({
72
+ domain: [0, max],
73
+ range: [yMax, 0],
74
+ clamp: true
75
+ })
76
+
77
+ const colorScale = scaleOrdinal({
78
+ domain: categories.map(d => d?.label),
79
+ range: categories.map(d => getValidColor(d?.color?.trim()))
80
+ })
81
+
82
+ const keys = Object.keys(transformedData[0])
83
+ return (
84
+ <Group left={leftSize - xScale.bandwidth()} top={0}>
85
+ <BarStack data={transformedData} keys={keys} x={() => xScale(xScaleValue)} xScale={xScale} yScale={yScale} color={colorScale}>
86
+ {barStacks =>
87
+ barStacks.map(barStack =>
88
+ barStack.bars.map(bar => {
89
+ const isLastIndex = config.yAxis.categories.length - 1 === barStack.index
90
+ const textSize = fontSize[config.fontSize] / 1.3
91
+ const textColor = chroma(bar.color).luminance() < 0.4 ? '#fff' : '#000'
92
+ const textWidth = getTextWidth(bar.key, `normal ${textSize}px sans-serif`)
93
+ const displayText = Number(textWidth) < bar.width && bar.height > textSize
94
+ const tooltip = `<ul>
95
+ <li class="tooltip-heading""> Label : ${bar.key} </li>
96
+ </li></ul>`
97
+ return (
98
+ <Group key={`${barStack.index}--${bar.index}--${orientation}`}>
99
+ <Group key={`bar-stack-${barStack.index}-${bar.index}`} id={`barStack${barStack.index}-${bar.index}`} className='stack vertical'>
100
+ {createBarElement({
101
+ type: 'axisBar',
102
+ config: config,
103
+ index: barStack.index,
104
+ background: colorScale(bar.key),
105
+ borderColor: '#333',
106
+ borderStyle: 'solid',
107
+ borderWidth: 0,
108
+ width: xScale.bandwidth(),
109
+ height: bar.height,
110
+ x: bar.x,
111
+ y: bar.y,
112
+ tooltipHtml: tooltip,
113
+ tooltipId: `cdc-open-viz-tooltip-${config.runtime.uniqueId}`
114
+ })}
115
+ {/* Label for axis stacks */}
116
+ <Text // ignore
117
+ display={!displayText ? 'none' : 'block'}
118
+ key={`text-${barStack.index}-${bar.index}`}
119
+ x={bar.x + xScale.bandwidth() / 2}
120
+ y={bar.y + bar.height / 2}
121
+ fill={textColor}
122
+ textAnchor='middle'
123
+ verticalAnchor='middle'
124
+ style={{ fontSize: textSize }}
125
+ >
126
+ {bar.key}
127
+ </Text>
128
+ {/* gridLines */}
129
+ {config.runtime.yAxis.gridLines && <Line from={{ x: bar.x + xScale.bandwidth(), y: bar.y }} to={{ x: xMax + xScale.bandwidth(), y: bar.y }} stroke='rgba(0,0,0,0.3)' />}
130
+ {/* White background spacing between stackes */}
131
+ {!isLastIndex && <rect x={bar.x} y={bar.y} width={bar.width} height={1} fill={'#fff'}></rect>}
132
+ {/* Right side Axis line */}
133
+ <rect x={bar.x + bar.width} y={0} width={1} height={yMax} fill={'#000'}></rect>
134
+ </Group>
135
+ </Group>
136
+ )
137
+ })
138
+ )
139
+ }
140
+ </BarStack>
141
+ </Group>
142
+ )
143
+ }
144
+
145
+ export default CategoricalYAxis
@@ -51,7 +51,7 @@ export const BarChartHorizontal = () => {
51
51
  return updateBars(barGroups).map((barGroup, index) => (
52
52
  <Group className={`bar-group-${barGroup.index}-${barGroup.x0}--${index} ${config.orientation}`} key={`bar-group-${barGroup.index}-${barGroup.x0}--${index}`} id={`bar-group-${barGroup.index}-${barGroup.x0}--${index}`} top={barGroup.y}>
53
53
  {barGroup.bars.map((bar, index) => {
54
- const scaleVal = config.useLogScale ? 0.1 : 0
54
+ const scaleVal = config.yAxis.type === 'logarithmic' ? 0.1 : 0
55
55
  let highlightedBarValues = config.highlightedBarValues.map(item => item.value).filter(item => item !== ('' || undefined))
56
56
  highlightedBarValues = config.xAxis.type === 'date' ? HighLightedBarUtils.formatDates(highlightedBarValues) : highlightedBarValues
57
57
  let transparentBar = config.legend.behavior === 'highlight' && seriesHighlight.length > 0 && seriesHighlight.indexOf(bar.key) === -1
@@ -75,7 +75,7 @@ export const BarChartHorizontal = () => {
75
75
  const barDefaultLabel = !config.yAxis.displayNumbersOnBar ? '' : yAxisValue
76
76
 
77
77
  // check if bar text/value string fits into each bars.
78
- const textWidth = (getTextWidth as any)(barDefaultLabel, `normal ${fontSize[config.fontSize]}px sans-serif`)
78
+ const textWidth = getTextWidth(barDefaultLabel, `normal ${fontSize[config.fontSize]}px sans-serif`)
79
79
  const textFits = Number(textWidth) < defaultBarWidth - 5
80
80
 
81
81
  // control text position
@@ -177,6 +177,7 @@ export const BarChartHorizontal = () => {
177
177
  const hasAsterisk = String(pd.symbol).includes('Asterisk')
178
178
  const verticalAnchor = hasAsterisk ? 'middle' : 'end'
179
179
  const iconSize = pd.symbol === 'Asterisk' ? barHeight * 1.2 : pd.symbol === 'Double Asterisk' ? barHeight : barHeight / 1.5
180
+ const fillColor = pd.displayGray ? '#8b8b8a' : '#000'
180
181
  return (
181
182
  <Text // prettier-ignore
182
183
  key={index}
@@ -185,7 +186,7 @@ export const BarChartHorizontal = () => {
185
186
  opacity={transparentBar ? 0.5 : 1}
186
187
  x={barX}
187
188
  y={config.barHeight / 2 + config.barHeight * bar.index}
188
- fill={'#000'}
189
+ fill={fillColor}
189
190
  dy={config.barHeight / 5}
190
191
  dx={10}
191
192
  textAnchor='start'
@@ -49,7 +49,7 @@ const BarChartStackedHorizontal = () => {
49
49
  const xAxisValue = formatNumber(data[bar.index][bar.key], 'left')
50
50
  const yAxisValue = config.runtime.yAxis.type === 'date' ? formatDate(parseDate(data[bar.index][config.runtime.originalXAxis.dataKey])) : data[bar.index][config.runtime.originalXAxis.dataKey]
51
51
  const yAxisTooltip = config.runtime.yAxis.label ? `${config.runtime.yAxis.label}: ${yAxisValue}` : yAxisValue
52
- const textWidth = (getTextWidth as any)(xAxisValue, `normal ${fontSize[config.fontSize]}px sans-serif`)
52
+ const textWidth = getTextWidth(xAxisValue, `normal ${fontSize[config.fontSize]}px sans-serif`)
53
53
  const additionalColTooltip = getAdditionalColumn(hoveredBar)
54
54
  const tooltipBody = `${config.runtime.seriesLabels[bar.key]}: ${xAxisValue}`
55
55
  const tooltip = `<ul>
@@ -30,8 +30,8 @@ const BarChartStackedVertical = () => {
30
30
  barStack.bars.map(bar => {
31
31
  let transparentBar = config.legend.behavior === 'highlight' && seriesHighlight.length > 0 && seriesHighlight.indexOf(bar.key) === -1
32
32
  let displayBar = config.legend.behavior === 'highlight' || seriesHighlight.length === 0 || seriesHighlight.indexOf(bar.key) !== -1
33
- let barThickness = isDateAxisType ? (seriesScale.range()[1] - seriesScale.range()[0]) : (xMax / barStack.bars.length)
34
- if(config.runtime.xAxis.type !== 'date') barThickness = config.barThickness * barThickness
33
+ let barThickness = isDateAxisType ? seriesScale.range()[1] - seriesScale.range()[0] : xMax / barStack.bars.length
34
+ if (config.runtime.xAxis.type !== 'date') barThickness = config.barThickness * barThickness
35
35
  // tooltips
36
36
  const rawXValue = bar.bar.data[config.runtime.xAxis.dataKey]
37
37
  const xAxisValue = isDateAxisType ? formatDate(parseDate(rawXValue)) : rawXValue
@@ -52,9 +52,6 @@ const BarChartStackedVertical = () => {
52
52
  return (
53
53
  <Group key={`${barStack.index}--${bar.index}--${orientation}`}>
54
54
  <Group key={`bar-stack-${barStack.index}-${bar.index}`} id={`barStack${barStack.index}-${bar.index}`} className='stack vertical'>
55
- <Text display={config.labels && displayBar ? 'block' : 'none'} opacity={transparentBar ? 0.5 : 1} x={barX + barWidth / 2} y={bar.y - 5} fill={'#000'} textAnchor='middle'>
56
- {yAxisValue}
57
- </Text>
58
55
  {createBarElement({
59
56
  config: config,
60
57
  seriesHighlight,