@@ -24,6 +24,7 @@ import {
24
24
getRangeForScatterMarkerSize ,
25
25
domainRangeOfDateForAreaLineScatterVerticalBarCharts ,
26
26
domainRangeOfNumericForAreaLineScatterCharts ,
27
+ sortAxisCategories ,
27
28
} from '../../utilities/index' ;
28
29
import {
29
30
AccessibilityProps ,
@@ -135,6 +136,17 @@ export const ScatterChart: React.FunctionComponent<ScatterChartProps> = React.fo
135
136
? ( getTypeOfAxis ( props . data . scatterChartData ! [ 0 ] . data [ 0 ] . x , true ) as XAxisTypes )
136
137
: XAxisTypes . StringAxis ;
137
138
139
+ // Detect y axis type (numeric or string)
140
+ const _yAxisType : YAxisType =
141
+ props . data . scatterChartData &&
142
+ props . data . scatterChartData . length > 0 &&
143
+ props . data . scatterChartData [ 0 ] . data &&
144
+ props . data . scatterChartData [ 0 ] . data . length > 0
145
+ ? typeof props . data . scatterChartData [ 0 ] . data [ 0 ] . y === 'string'
146
+ ? YAxisType . StringAxis
147
+ : YAxisType . NumericAxis
148
+ : YAxisType . NumericAxis ;
149
+
138
150
const pointsRef = React . useRef < ScatterChartDataWithIndex [ ] | [ ] > ( [ ] ) ;
139
151
// eslint-disable-next-line @typescript-eslint/no-explicit-any
140
152
const calloutPointsRef = React . useRef < any [ ] > ( [ ] ) ;
@@ -300,6 +312,47 @@ export const ScatterChart: React.FunctionComponent<ScatterChartProps> = React.fo
300
312
) ;
301
313
}
302
314
315
+ function _getOrderedYAxisLabels ( ) {
316
+ const shouldOrderYAxisLabelsByCategoryOrder =
317
+ _yAxisType === YAxisType . StringAxis && props . yAxisCategoryOrder !== 'default' ;
318
+ if ( ! shouldOrderYAxisLabelsByCategoryOrder ) {
319
+ // Collect all unique string y values from all data points in all series, in reverse order
320
+ const yLabelsSet = new Set < string > ( ) ;
321
+ for ( let i = _points . length - 1 ; i >= 0 ; i -- ) {
322
+ const point = _points [ i ] ;
323
+ if ( point . data && Array . isArray ( point . data ) ) {
324
+ for ( const d of point . data ) {
325
+ if ( typeof d . y === 'string' ) {
326
+ yLabelsSet . add ( d . y ) ;
327
+ }
328
+ }
329
+ }
330
+ }
331
+ return Array . from ( yLabelsSet ) ;
332
+ }
333
+
334
+ return sortAxisCategories ( _mapCategoryToValues ( ) , props . yAxisCategoryOrder ) ;
335
+ }
336
+
337
+ function _mapCategoryToValues ( ) {
338
+ const categoryToValues : Record < string , number [ ] > = { } ;
339
+ _points . forEach ( point => {
340
+ if ( point . data && Array . isArray ( point . data ) ) {
341
+ point . data . forEach ( d => {
342
+ if ( typeof d . y === 'string' ) {
343
+ if ( ! categoryToValues [ d . y ] ) {
344
+ categoryToValues [ d . y ] = [ ] ;
345
+ }
346
+ if ( typeof d . x === 'number' ) {
347
+ categoryToValues [ d . y ] . push ( d . x ) ;
348
+ }
349
+ }
350
+ } ) ;
351
+ }
352
+ } ) ;
353
+ return categoryToValues ;
354
+ }
355
+
303
356
function _onLegendSelectionChange (
304
357
legendsSelected : string [ ] ,
305
358
event : React . MouseEvent < HTMLButtonElement > ,
@@ -343,7 +396,7 @@ export const ScatterChart: React.FunctionComponent<ScatterChartProps> = React.fo
343
396
} ) ! ;
344
397
345
398
const extraMaxPixels =
346
- _xAxisType !== XAxisTypes . StringAxis
399
+ _xAxisType !== XAxisTypes . StringAxis && _yAxisType !== YAxisType . StringAxis
347
400
? getRangeForScatterMarkerSize ( {
348
401
data : _points ,
349
402
xScale : _xAxisScale ,
@@ -363,7 +416,11 @@ export const ScatterChart: React.FunctionComponent<ScatterChartProps> = React.fo
363
416
for ( let j = 0 ; j < _points [ i ] . data . length ; j ++ ) {
364
417
const { x, y, xAxisCalloutData, xAxisCalloutAccessibilityData } = _points ?. [ i ] ?. data [ j ] ;
365
418
const xPoint = _xAxisScale ?.( x ) ;
366
- const yPoint = _yAxisScale ?.( y ) ;
419
+ // Use string y axis scale if needed
420
+ const yPoint =
421
+ _yAxisType === YAxisType . StringAxis
422
+ ? _yAxisScale ?.( y ) + ( _yAxisScale ?. bandwidth ? _yAxisScale . bandwidth ( ) / 2 : 0 )
423
+ : _yAxisScale ?.( y ) ;
367
424
if ( ! isPlottable ( xPoint , yPoint ) ) {
368
425
continue ;
369
426
}
@@ -673,6 +730,9 @@ export const ScatterChart: React.FunctionComponent<ScatterChartProps> = React.fo
673
730
674
731
_xAxisLabels = [ ...new Set ( xAxisLabels ) ] ;
675
732
733
+ // Compute unique y axis labels for string y axis
734
+ const _yAxisLabels : string [ ] = _getOrderedYAxisLabels ( ) ;
735
+
676
736
return ! _isChartEmpty ( ) ? (
677
737
< CartesianChart
678
738
{ ...props }
@@ -685,6 +745,9 @@ export const ScatterChart: React.FunctionComponent<ScatterChartProps> = React.fo
685
745
getmargins = { _getMargins }
686
746
getGraphData = { _initializeScatterChartData }
687
747
xAxisType = { _xAxisType }
748
+ yAxisType = { _yAxisType }
749
+ // Pass stringDatasetForYAxisDomain only if y axis is string
750
+ { ...( _yAxisType === YAxisType . StringAxis ? { stringDatasetForYAxisDomain : _yAxisLabels } : { } ) }
688
751
getMinMaxOfYAxis = { _getNumericMinMaxOfY }
689
752
getDomainNRangeValues = { _getDomainNRangeValues }
690
753
createYAxis = { createNumericYAxis }
0 commit comments