Skip to content

Commit 5fb8379

Browse files
committed
charts added axes configs
1 parent 4e5471d commit 5fb8379

3 files changed

Lines changed: 117 additions & 36 deletions

File tree

src/Shared/Components/Charts/Chart.component.tsx

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,8 @@ ChartJSTooltip.positioners.barElementCenterPositioner = (items, eventPosition) =
158158
* @param type - Chart type: 'area', 'pie', 'stackedBar', 'stackedBarHorizontal', or 'line'
159159
* @param xAxisLabels - Array of labels for the x-axis (or categories for pie charts)
160160
* @param datasets - Chart data: array of datasets for most charts, single dataset object for pie charts
161+
* @param xAxisConfig
162+
* @param yAxisConfig
161163
*
162164
* @performance
163165
* **Memoization Recommendations:**
@@ -201,6 +203,8 @@ const Chart = (props: ChartProps) => {
201203
xScaleTitle,
202204
yAxisMax,
203205
yScaleTitle,
206+
xAxisConfig,
207+
yAxisConfig,
204208
} = props
205209
const { getTooltipContent, placement } = tooltipConfig || { placement: 'top' }
206210

@@ -294,7 +298,20 @@ const Chart = (props: ChartProps) => {
294298
return () => {
295299
chartRef.current.destroy()
296300
}
297-
}, [type, datasets, labels, appTheme, hideAxis, referenceLines, xAxisMax, xScaleTitle, yAxisMax, yScaleTitle])
301+
}, [
302+
type,
303+
datasets,
304+
labels,
305+
appTheme,
306+
hideAxis,
307+
referenceLines,
308+
xAxisMax,
309+
xScaleTitle,
310+
yAxisMax,
311+
yScaleTitle,
312+
xAxisConfig,
313+
yAxisConfig,
314+
])
298315

299316
return (
300317
<div className="h-100 w-100 dc__position-rel">

src/Shared/Components/Charts/types.ts

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,13 +50,26 @@ export interface ReferenceLineConfigType {
5050
value: number
5151
}
5252

53+
export interface AxisConfig {
54+
title?: string
55+
unit?: string
56+
unitPosition?: 'prefix' | 'suffix'
57+
labelFormatter?: (value: number | string, index: number) => string | string[] | number | number[]
58+
hide?: boolean
59+
max?: number
60+
min?: number
61+
stepSize?: number
62+
}
63+
5364
type XYAxisMax = {
5465
xAxisMax?: number
5566
yAxisMax?: number
5667
/**
5768
* Optional reference lines to draw across the chart
5869
*/
5970
referenceLines?: ReferenceLineConfigType[]
71+
xAxisConfig?: AxisConfig
72+
yAxisConfig?: AxisConfig
6073
}
6174

6275
type OnChartClickHandler = (datasetName: string, value: number) => void
@@ -116,9 +129,7 @@ export type ChartProps = {
116129
placement?: TooltipProps['placement']
117130
datasetValueFormatter?: (value: number) => string | number
118131
}
119-
/** A title for x axis */
120132
xScaleTitle?: string
121-
/** A title for y axis */
122133
yScaleTitle?: string
123134
} & TypeAndDatasetsType
124135

src/Shared/Components/Charts/utils.tsx

Lines changed: 86 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import {
2323
MAX_BAR_THICKNESS,
2424
} from './constants'
2525
import {
26+
AxisConfig,
2627
ChartColorKey,
2728
ChartProps,
2829
ChartType,
@@ -173,6 +174,66 @@ const getScaleTickTitleConfig = (title: string, appTheme: AppThemeType): ScaleOp
173174
color: CHART_AXIS_LABELS_COLOR[appTheme],
174175
})
175176

177+
/**
178+
* Formats a value with unit based on axis configuration
179+
*/
180+
const formatValueWithUnit = (value: number | string, axisConfig?: AxisConfig): string => {
181+
if (!axisConfig?.unit) {
182+
return String(value)
183+
}
184+
185+
const { unit, unitPosition = 'suffix' } = axisConfig
186+
const valueStr = String(value)
187+
188+
return unitPosition === 'prefix' ? `${unit}${valueStr}` : `${valueStr}${unit}`
189+
}
190+
191+
/**
192+
* Creates a comprehensive axis configuration with enhanced customization
193+
*/
194+
const getEnhancedAxisConfig = (
195+
axisConfig: AxisConfig | undefined,
196+
legacyTitle: string | undefined,
197+
legacyMax: number | undefined,
198+
appTheme: AppThemeType,
199+
isHidden: boolean,
200+
hideLabels: boolean = false,
201+
): ScaleOptions<'linear'> => {
202+
// Merge legacy props with new axis config (new config takes priority)
203+
const title = axisConfig?.title || legacyTitle
204+
const max = axisConfig?.max !== undefined ? axisConfig.max : legacyMax
205+
const hide = axisConfig?.hide !== undefined ? axisConfig.hide : isHidden
206+
207+
return {
208+
display: !hide,
209+
min: axisConfig?.min,
210+
max,
211+
border: {
212+
color: CHART_AXIS_COLORS[appTheme],
213+
},
214+
grid: {
215+
color: CHART_GRID_LINES_COLORS[appTheme],
216+
},
217+
title: getScaleTickTitleConfig(title || '', appTheme),
218+
ticks: {
219+
display: !hideLabels && !hide,
220+
color: CHART_AXIS_LABELS_COLOR[appTheme],
221+
font: {
222+
family: "'IBM Plex Sans', 'Open Sans', 'Roboto'",
223+
size: 12,
224+
lineHeight: '150%',
225+
weight: 400,
226+
},
227+
stepSize: axisConfig?.stepSize,
228+
callback:
229+
axisConfig?.labelFormatter ||
230+
((value) =>
231+
// Apply unit formatting if specified
232+
formatValueWithUnit(value, axisConfig)),
233+
},
234+
}
235+
}
236+
176237
// Get default options based on chart type
177238
export const getDefaultOptions = ({
178239
chartProps,
@@ -189,6 +250,8 @@ export const getDefaultOptions = ({
189250
yAxisMax,
190251
xScaleTitle,
191252
yScaleTitle,
253+
xAxisConfig,
254+
yAxisConfig,
192255
yScaleTickFormat,
193256
xScaleTickFormat,
194257
xAxisLabels,
@@ -249,54 +312,44 @@ export const getDefaultOptions = ({
249312
: {}),
250313
}
251314

252-
const commonScaleConfig = {
253-
display: !hideAxis,
254-
border: {
255-
color: CHART_AXIS_COLORS[appTheme],
256-
},
257-
grid: {
258-
color: CHART_GRID_LINES_COLORS[appTheme],
259-
},
260-
ticks: {
261-
display: !hideXAxisLabels,
262-
color: CHART_AXIS_LABELS_COLOR[appTheme],
263-
font: {
264-
family: "'IBM Plex Sans', 'Open Sans', 'Roboto'",
265-
size: 12,
266-
lineHeight: '150%',
267-
weight: 400,
268-
},
269-
},
270-
} satisfies ScaleOptions<'linear'>
315+
// Create enhanced axis configurations
316+
const enhancedXAxisConfig = getEnhancedAxisConfig(
317+
xAxisConfig,
318+
xScaleTitle,
319+
xAxisMax,
320+
appTheme,
321+
hideAxis,
322+
hideXAxisLabels,
323+
)
271324

325+
const enhancedYAxisConfig = getEnhancedAxisConfig(yAxisConfig, yScaleTitle, yAxisMax, appTheme, hideAxis, false)
326+
327+
// Apply legacy tick formatters if no custom formatter is provided in axis config
272328
const commonXScaleConfig = {
273-
...commonScaleConfig,
274-
max: xAxisMax,
275-
title: getScaleTickTitleConfig(xScaleTitle, appTheme),
329+
...enhancedXAxisConfig,
276330
ticks: {
277-
...commonScaleConfig.ticks,
278-
...((type !== 'stackedBarHorizontal' && typeof xScaleTickFormat === 'function') ||
279-
(type === 'stackedBarHorizontal' && typeof yScaleTickFormat === 'function')
331+
...enhancedXAxisConfig.ticks,
332+
autoSkip: false,
333+
...(!xAxisConfig?.labelFormatter &&
334+
((type !== 'stackedBarHorizontal' && typeof xScaleTickFormat === 'function') ||
335+
(type === 'stackedBarHorizontal' && typeof yScaleTickFormat === 'function'))
280336
? {
281337
callback:
282338
type === 'stackedBarHorizontal'
283339
? (value, index) => yScaleTickFormat(Number(value), index)
284340
: (_, index) => xScaleTickFormat(xAxisLabels[index], index),
285341
}
286342
: {}),
287-
autoSkip: false,
288343
},
289344
} satisfies ScaleOptions<'linear'>
290345

291346
const commonYScaleConfig = {
292-
...commonScaleConfig,
293-
max: yAxisMax,
294-
title: getScaleTickTitleConfig(yScaleTitle, appTheme),
295-
// for stackedBarHorizon
347+
...enhancedYAxisConfig,
296348
ticks: {
297-
...commonScaleConfig.ticks,
298-
...((type === 'stackedBarHorizontal' && typeof xScaleTickFormat === 'function') ||
299-
(type !== 'stackedBarHorizontal' && typeof yScaleTickFormat === 'function')
349+
...enhancedYAxisConfig.ticks,
350+
...(!yAxisConfig?.labelFormatter &&
351+
((type === 'stackedBarHorizontal' && typeof xScaleTickFormat === 'function') ||
352+
(type !== 'stackedBarHorizontal' && typeof yScaleTickFormat === 'function'))
300353
? {
301354
callback:
302355
type !== 'stackedBarHorizontal'

0 commit comments

Comments
 (0)