@fluentui/react-charts 9.3.25 → 9.3.26
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.
- package/CHANGELOG.md +22 -2
- package/dist/index.d.cts +35 -0
- package/dist/index.d.ts +35 -0
- package/lib/components/AreaChart/AreaChart.js +3 -3
- package/lib/components/AreaChart/AreaChart.js.map +1 -1
- package/lib/components/DeclarativeChart/DeclarativeChart.js +1 -1
- package/lib/components/DeclarativeChart/DeclarativeChart.js.map +1 -1
- package/lib/components/DeclarativeChart/PlotlySchemaAdapter.js +5 -4
- package/lib/components/DeclarativeChart/PlotlySchemaAdapter.js.map +1 -1
- package/lib/components/FunnelChart/FunnelChart.js +1 -1
- package/lib/components/FunnelChart/FunnelChart.js.map +1 -1
- package/lib/components/GanttChart/GanttChart.js +2 -2
- package/lib/components/GanttChart/GanttChart.js.map +1 -1
- package/lib/components/GaugeChart/GaugeChart.js +22 -10
- package/lib/components/GaugeChart/GaugeChart.js.map +1 -1
- package/lib/components/GaugeChart/GaugeChart.types.js.map +1 -1
- package/lib/components/GroupedVerticalBarChart/GroupedVerticalBarChart.js +3 -3
- package/lib/components/GroupedVerticalBarChart/GroupedVerticalBarChart.js.map +1 -1
- package/lib/components/HeatMapChart/HeatMapChart.js +5 -5
- package/lib/components/HeatMapChart/HeatMapChart.js.map +1 -1
- package/lib/components/HorizontalBarChartWithAxis/HorizontalBarChartWithAxis.js +1 -1
- package/lib/components/HorizontalBarChartWithAxis/HorizontalBarChartWithAxis.js.map +1 -1
- package/lib/components/LineChart/LineChart.js +1 -1
- package/lib/components/LineChart/LineChart.js.map +1 -1
- package/lib/components/PolarChart/PolarChart.js +1 -1
- package/lib/components/PolarChart/PolarChart.js.map +1 -1
- package/lib/components/SankeyChart/SankeyChart.js +7 -7
- package/lib/components/SankeyChart/SankeyChart.js.map +1 -1
- package/lib/components/ScatterChart/ScatterChart.js +1 -1
- package/lib/components/ScatterChart/ScatterChart.js.map +1 -1
- package/lib/components/VegaDeclarativeChart/VegaLiteExpressionEvaluator.js +2 -1
- package/lib/components/VegaDeclarativeChart/VegaLiteExpressionEvaluator.js.map +1 -1
- package/lib/components/VegaDeclarativeChart/VegaLiteSchemaAdapter.js +8 -5
- package/lib/components/VegaDeclarativeChart/VegaLiteSchemaAdapter.js.map +1 -1
- package/lib/components/VerticalBarChart/VerticalBarChart.js +1 -1
- package/lib/components/VerticalBarChart/VerticalBarChart.js.map +1 -1
- package/lib/components/VerticalStackedBarChart/VerticalStackedBarChart.js +2 -2
- package/lib/components/VerticalStackedBarChart/VerticalStackedBarChart.js.map +1 -1
- package/lib/utilities/utilities.js +3 -2
- package/lib/utilities/utilities.js.map +1 -1
- package/lib-commonjs/components/AreaChart/AreaChart.cjs +3 -3
- package/lib-commonjs/components/AreaChart/AreaChart.cjs.map +1 -1
- package/lib-commonjs/components/DeclarativeChart/DeclarativeChart.cjs +1 -1
- package/lib-commonjs/components/DeclarativeChart/DeclarativeChart.cjs.map +1 -1
- package/lib-commonjs/components/DeclarativeChart/PlotlySchemaAdapter.cjs +5 -4
- package/lib-commonjs/components/DeclarativeChart/PlotlySchemaAdapter.cjs.map +1 -1
- package/lib-commonjs/components/FunnelChart/FunnelChart.cjs +1 -1
- package/lib-commonjs/components/FunnelChart/FunnelChart.cjs.map +1 -1
- package/lib-commonjs/components/GanttChart/GanttChart.cjs +2 -2
- package/lib-commonjs/components/GanttChart/GanttChart.cjs.map +1 -1
- package/lib-commonjs/components/GaugeChart/GaugeChart.cjs +22 -10
- package/lib-commonjs/components/GaugeChart/GaugeChart.cjs.map +1 -1
- package/lib-commonjs/components/GaugeChart/GaugeChart.types.cjs.map +1 -1
- package/lib-commonjs/components/GroupedVerticalBarChart/GroupedVerticalBarChart.cjs +3 -3
- package/lib-commonjs/components/GroupedVerticalBarChart/GroupedVerticalBarChart.cjs.map +1 -1
- package/lib-commonjs/components/HeatMapChart/HeatMapChart.cjs +5 -5
- package/lib-commonjs/components/HeatMapChart/HeatMapChart.cjs.map +1 -1
- package/lib-commonjs/components/HorizontalBarChartWithAxis/HorizontalBarChartWithAxis.cjs +1 -1
- package/lib-commonjs/components/HorizontalBarChartWithAxis/HorizontalBarChartWithAxis.cjs.map +1 -1
- package/lib-commonjs/components/LineChart/LineChart.cjs +1 -1
- package/lib-commonjs/components/LineChart/LineChart.cjs.map +1 -1
- package/lib-commonjs/components/PolarChart/PolarChart.cjs +1 -1
- package/lib-commonjs/components/PolarChart/PolarChart.cjs.map +1 -1
- package/lib-commonjs/components/SankeyChart/SankeyChart.cjs +7 -7
- package/lib-commonjs/components/SankeyChart/SankeyChart.cjs.map +1 -1
- package/lib-commonjs/components/ScatterChart/ScatterChart.cjs +1 -1
- package/lib-commonjs/components/ScatterChart/ScatterChart.cjs.map +1 -1
- package/lib-commonjs/components/VegaDeclarativeChart/VegaLiteExpressionEvaluator.cjs +2 -1
- package/lib-commonjs/components/VegaDeclarativeChart/VegaLiteExpressionEvaluator.cjs.map +1 -1
- package/lib-commonjs/components/VegaDeclarativeChart/VegaLiteSchemaAdapter.cjs +8 -5
- package/lib-commonjs/components/VegaDeclarativeChart/VegaLiteSchemaAdapter.cjs.map +1 -1
- package/lib-commonjs/components/VerticalBarChart/VerticalBarChart.cjs +1 -1
- package/lib-commonjs/components/VerticalBarChart/VerticalBarChart.cjs.map +1 -1
- package/lib-commonjs/components/VerticalStackedBarChart/VerticalStackedBarChart.cjs +2 -2
- package/lib-commonjs/components/VerticalStackedBarChart/VerticalStackedBarChart.cjs.map +1 -1
- package/lib-commonjs/utilities/utilities.cjs +3 -2
- package/lib-commonjs/utilities/utilities.cjs.map +1 -1
- package/package.json +9 -9
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/ScatterChart/ScatterChart.tsx"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport type { ScatterChartProps } from './ScatterChart.types';\nimport { useScatterChartStyles } from './useScatterChartStyles.styles';\nimport type { Axis as D3Axis } from 'd3-axis';\nimport { select as d3Select } from 'd3-selection';\nimport type { Legend } from '../Legends/index';\nimport { Legends } from '../Legends/index';\nimport { max as d3Max, min as d3Min } from 'd3-array';\nimport { useId } from '@fluentui/react-utilities';\nimport type { JSXElement } from '@fluentui/react-utilities';\nimport type { IDomainNRange } from '../../utilities/index';\nimport {\n areArraysEqual,\n createNumericYAxis,\n createStringYAxis,\n getDomainPaddingForMarkers,\n domainRangeOfXStringAxis,\n findNumericMinMaxOfY,\n YAxisType,\n isTextMode,\n isScatterPolarSeries,\n isPlottable,\n getRangeForScatterMarkerSize,\n calculateMarkerRadius,\n domainRangeOfDateForAreaLineScatterVerticalBarCharts,\n domainRangeOfNumericForAreaLineScatterCharts,\n sortAxisCategories,\n findCalloutPoints,\n} from '../../utilities/index';\nimport type {\n AccessibilityProps,\n ChildProps,\n CustomizedCalloutData,\n Margins,\n RefArrayData,\n ScatterChartDataPoint,\n ScatterChartPoints,\n YValueHover,\n} from '../../index';\nimport { CartesianChart } from '../../index';\nimport { tokens } from '@fluentui/react-theme';\nimport {\n calloutData,\n ChartTypes,\n XAxisTypes,\n getTypeOfAxis,\n getNextColor,\n getColorFromToken,\n} from '../../utilities/index';\nimport type { LineChartPoints } from '../../types/DataPoint';\nimport { renderScatterPolarCategoryLabels } from '../../utilities/scatterpolar-utils';\nimport { formatDateToLocaleString } from '@fluentui/chart-utilities';\nimport { useImageExport } from '../../utilities/hooks';\n\ntype NumericAxis = D3Axis<number | { valueOf(): number }>;\n\ntype ScatterChartDataWithIndex = ScatterChartPoints & { index: number };\n\n// Create a ScatterChart variant which uses these default styles and this styled subcomponent.\n/**\n * ScatterChart component\n * {@docCategory ScatterChart}\n */\nexport const ScatterChart: React.FunctionComponent<ScatterChartProps> = React.forwardRef<\n HTMLDivElement,\n ScatterChartProps\n>((props, forwardedRef) => {\n const _circleId: string = useId('circle');\n const _seriesId: string = useId('seriesID');\n const _verticalLine: string = useId('verticalLine');\n const _firstRenderOptimization = true;\n const _emptyChartId: string = useId('_ScatterChart_empty');\n let _points: ScatterChartDataWithIndex[] = _injectIndexPropertyInScatterChartData(props.data.scatterChartData);\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n let _xAxisScale: any = '';\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n let _yAxisScale: any = '';\n let _uniqueCallOutID: string | null = '';\n const _refArray: RefArrayData[] = [];\n let margins: Margins;\n let renderSeries: JSXElement[];\n let _xAxisLabels: string[] = [];\n const xAxisCalloutAccessibilityData: AccessibilityProps = {};\n let _xBandwidth = 0;\n const { cartesianChartRef, legendsRef: _legendsRef } = useImageExport(props.componentRef, props.hideLegend);\n const classes = useScatterChartStyles(props);\n\n const [hoverXValue, setHoverXValue] = React.useState<string | number>('');\n const [activeLegend, setActiveLegend] = React.useState<string>('');\n const [yValueHover, setYValueHover] = React.useState<YValueHover[]>([]);\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const [selectedLegendPoints, setSelectedLegendPoints] = React.useState<any[]>([]);\n const [isSelectedLegend, setIsSelectedLegend] = React.useState<boolean>(false);\n const [activePoint, setActivePoint] = React.useState<string>('');\n const [stackCalloutProps, setStackCalloutProps] = React.useState<CustomizedCalloutData>();\n const [dataPointCalloutProps, setDataPointCalloutProps] = React.useState<CustomizedCalloutData>();\n const [clickPosition, setClickPosition] = React.useState({ x: 0, y: 0 });\n const [isPopoverOpen, setPopoverOpen] = React.useState(false);\n const [selectedLegends, setSelectedLegends] = React.useState<string[]>(props.legendProps?.selectedLegends || []);\n const prevSelectedLegendsRef = React.useRef<string[] | undefined>(undefined);\n const _isTextMode = React.useRef(false);\n const _isScatterPolarRef = React.useRef(false);\n\n React.useEffect(() => {\n if (\n prevSelectedLegendsRef.current &&\n !areArraysEqual(prevSelectedLegendsRef.current, props.legendProps?.selectedLegends)\n ) {\n setSelectedLegends(props.legendProps?.selectedLegends || []);\n }\n prevSelectedLegendsRef.current = props.legendProps?.selectedLegends;\n }, [props.legendProps?.selectedLegends]);\n\n const _xAxisType: XAxisTypes =\n props.data.scatterChartData! &&\n props.data.scatterChartData!.length > 0 &&\n props.data.scatterChartData![0].data &&\n props.data.scatterChartData![0].data.length > 0\n ? (getTypeOfAxis(props.data.scatterChartData![0].data[0].x, true) as XAxisTypes)\n : XAxisTypes.StringAxis;\n\n // Detect y axis type (numeric or string)\n const _yAxisType: YAxisType =\n props.data.scatterChartData &&\n props.data.scatterChartData.length > 0 &&\n props.data.scatterChartData[0].data &&\n props.data.scatterChartData[0].data.length > 0\n ? typeof props.data.scatterChartData[0].data[0].y === 'string'\n ? YAxisType.StringAxis\n : YAxisType.NumericAxis\n : YAxisType.NumericAxis;\n\n const pointsRef = React.useRef<ScatterChartDataWithIndex[] | []>([]);\n const calloutPointsRef = React.useRef<Record<string, YValueHover[]>>({});\n React.useEffect(() => {\n /** note that height and width are not used to resize or set as dimesions of the chart,\n * fitParentContainer is responisble for setting the height and width or resizing of the svg/chart\n */\n\n if (_points !== _injectIndexPropertyInScatterChartData(props.data.scatterChartData) || props.data !== _points) {\n pointsRef.current = _injectIndexPropertyInScatterChartData(props.data.scatterChartData);\n calloutPointsRef.current = calloutData(pointsRef.current);\n }\n }, [props.height, props.width, props.data, _points]);\n\n function _injectIndexPropertyInScatterChartData(\n scatterChartData?: ScatterChartPoints[],\n ): ScatterChartDataWithIndex[] | [] {\n return scatterChartData\n ? scatterChartData.map((item: ScatterChartPoints, index: number) => {\n let color: string;\n if (typeof item.color === 'undefined') {\n color = getNextColor(index, 0);\n } else {\n color = getColorFromToken(item.color);\n }\n return {\n ...item,\n index: -1,\n color,\n };\n })\n : [];\n }\n\n function updatePosition(newX: number, newY: number) {\n const threshold = 1; // Set a threshold for movement\n const { x, y } = clickPosition;\n // Calculate the distance moved\n const distance = Math.sqrt(Math.pow(newX - x, 2) + Math.pow(newY - y, 2));\n // Update the position only if the distance moved is greater than the threshold\n if (distance > threshold) {\n setClickPosition({ x: newX, y: newY });\n setPopoverOpen(true);\n }\n }\n\n function _getNumericMinMaxOfY(\n points: ScatterChartPoints[],\n yAxisType?: YAxisType,\n ): { startValue: number; endValue: number } {\n const { startValue, endValue } = findNumericMinMaxOfY(points, yAxisType);\n const yPadding = getDomainPaddingForMarkers(startValue, endValue, props.yScaleType);\n\n return {\n startValue: startValue - yPadding.start,\n endValue: endValue + yPadding.end,\n };\n }\n\n function _getDomainNRangeValues(\n points: any,\n margins: Margins,\n width: number,\n chartType: ChartTypes,\n isRTL: boolean,\n xAxisType: XAxisTypes,\n barWidth: number,\n tickValues: Date[] | number[] | undefined,\n ) {\n let domainNRangeValue: IDomainNRange;\n if (xAxisType === XAxisTypes.NumericAxis) {\n domainNRangeValue = domainRangeOfNumericForAreaLineScatterCharts(\n points,\n margins,\n width,\n isRTL,\n props.xScaleType,\n true,\n props.xMinValue,\n props.xMaxValue,\n );\n } else if (xAxisType === XAxisTypes.DateAxis) {\n domainNRangeValue = domainRangeOfDateForAreaLineScatterVerticalBarCharts(\n points,\n margins,\n width,\n isRTL,\n tickValues! as Date[],\n chartType,\n );\n } else {\n domainNRangeValue = domainRangeOfXStringAxis(margins, width, isRTL);\n }\n return domainNRangeValue;\n }\n\n function _getMargins(_margins: Margins) {\n margins = _margins;\n }\n\n function _initializeScatterChartData(\n xScale: NumericAxis,\n yScale: NumericAxis,\n containerHeight: number,\n containerWidth: number,\n xElement: SVGElement | null,\n ) {\n _xAxisScale = xScale;\n _yAxisScale = yScale;\n _isTextMode.current = isTextMode(_points);\n _isScatterPolarRef.current = isScatterPolarSeries(_points);\n renderSeries = _createPlot(xElement!, containerHeight!);\n }\n\n function _onHoverCardHide() {\n setSelectedLegendPoints([]);\n setIsSelectedLegend(false);\n }\n\n function _createLegends(data: ScatterChartDataWithIndex[]): JSXElement {\n const { legendProps } = props;\n const isLegendMultiSelectEnabled = !!(legendProps && !!legendProps.canSelectMultipleLegends);\n const mapLegendToPoints: Record<string, ScatterChartDataWithIndex[]> = {};\n data.forEach((point: ScatterChartDataWithIndex) => {\n if (point.legend) {\n if (!mapLegendToPoints[point.legend]) {\n mapLegendToPoints[point.legend] = [];\n }\n mapLegendToPoints[point.legend].push(point);\n }\n });\n const legendDataItems: Legend[] = Object.entries(mapLegendToPoints).map(([legendTitle, points]) => {\n const representativePoint = points[0];\n // mapping data to the format Legends component needs\n const legend: Legend = {\n title: legendTitle,\n color: representativePoint.color!,\n onMouseOutAction: () => {\n setActiveLegend('');\n },\n hoverAction: () => {\n _handleChartMouseLeave();\n setActiveLegend(legendTitle);\n },\n ...(representativePoint.legendShape && {\n shape: representativePoint.legendShape,\n }),\n };\n return legend;\n });\n\n return (\n <Legends\n legends={[...legendDataItems]}\n enabledWrapLines={props.enabledLegendsWrapLines}\n overflowText={props.legendsOverflowText}\n {...(isLegendMultiSelectEnabled && { onLegendHoverCardLeave: _onHoverCardHide })}\n {...props.legendProps}\n selectedLegends={selectedLegends}\n onChange={_onLegendSelectionChange}\n legendRef={_legendsRef}\n />\n );\n }\n\n function _getOrderedYAxisLabels() {\n const shouldOrderYAxisLabelsByCategoryOrder =\n _yAxisType === YAxisType.StringAxis && props.yAxisCategoryOrder !== 'default';\n if (!shouldOrderYAxisLabelsByCategoryOrder) {\n // Collect all unique string y values from all data points in all series, in reverse order\n const yLabelsSet = new Set<string>();\n for (let i = _points.length - 1; i >= 0; i--) {\n const point = _points[i];\n if (point.data && Array.isArray(point.data)) {\n for (const d of point.data) {\n if (typeof d.y === 'string') {\n yLabelsSet.add(d.y);\n }\n }\n }\n }\n return Array.from(yLabelsSet);\n }\n\n return sortAxisCategories(_mapCategoryToValues(), props.yAxisCategoryOrder);\n }\n\n function _mapCategoryToValues() {\n const categoryToValues: Record<string, number[]> = {};\n _points.forEach(point => {\n if (point.data && Array.isArray(point.data)) {\n point.data.forEach(d => {\n if (typeof d.y === 'string') {\n if (!categoryToValues[d.y]) {\n categoryToValues[d.y] = [];\n }\n if (typeof d.x === 'number') {\n categoryToValues[d.y].push(d.x);\n }\n }\n });\n }\n });\n return categoryToValues;\n }\n\n function _onLegendSelectionChange(\n legendsSelected: string[],\n event: React.MouseEvent<HTMLButtonElement>,\n currentLegend?: Legend,\n ): void {\n if (props.legendProps?.canSelectMultipleLegends) {\n setSelectedLegends(legendsSelected);\n } else {\n setSelectedLegends(legendsSelected.slice(-1));\n }\n\n if (props.legendProps?.onChange) {\n props.legendProps.onChange(legendsSelected, event, currentLegend);\n }\n }\n\n function _getPointFill(seriesColor: string, pointId: string, pointIndex: number, isLastPoint: boolean) {\n if (activePoint === pointId) {\n return tokens.colorNeutralBackground1;\n } else {\n return seriesColor;\n }\n }\n\n function _createPlot(xElement: SVGElement, containerHeight: number): JSXElement[] {\n const series: JSXElement[] = [];\n if (isSelectedLegend) {\n _points = selectedLegendPoints;\n } else {\n _points = _injectIndexPropertyInScatterChartData(props.data.scatterChartData);\n }\n\n if (_xAxisType === XAxisTypes.StringAxis) {\n _xBandwidth = _xAxisScale.bandwidth() / 2;\n }\n\n const minMarkerSize =\n d3Min(_points, (point: ScatterChartPoints) => {\n return d3Min(point.data as ScatterChartDataPoint[], (item: ScatterChartDataPoint) => {\n return item.markerSize as number;\n });\n }) ?? 0;\n const maxMarkerSize =\n d3Max(_points, (point: ScatterChartPoints) => {\n return d3Max(point.data as ScatterChartDataPoint[], (item: ScatterChartDataPoint) => {\n return item.markerSize as number;\n });\n }) ?? 0;\n const isContinuousXY = _xAxisType !== XAxisTypes.StringAxis && _yAxisType !== YAxisType.StringAxis;\n const extraMaxPixels = isContinuousXY\n ? getRangeForScatterMarkerSize({\n data: _points,\n xScale: _xAxisScale,\n yScalePrimary: _yAxisScale,\n xScaleType: props.xScaleType,\n yScaleType: props.yScaleType,\n })\n : 0;\n\n for (let i = _points.length - 1; i >= 0; i--) {\n const pointsForSeries: JSXElement[] = [];\n\n const legendVal: string = _points[i].legend;\n const seriesColor: string = _points[i].color!;\n const verticaLineHeight = containerHeight - margins.bottom! + 6;\n\n for (let j = 0; j < _points[i].data.length; j++) {\n const { x, y, xAxisCalloutData, xAxisCalloutAccessibilityData } = _points?.[i]?.data[j];\n const xPoint = _xAxisScale?.(x);\n // Use string y axis scale if needed\n const yPoint =\n _yAxisType === YAxisType.StringAxis\n ? _yAxisScale?.(y) + (_yAxisScale?.bandwidth ? _yAxisScale.bandwidth() / 2 : 0)\n : _yAxisScale?.(y);\n if (!isPlottable(xPoint, yPoint)) {\n continue;\n }\n const seriesId = `${_seriesId}_${i}_${j}`;\n const circleId = `${_circleId}_${i}_${j}`;\n const pointMarkerSize = (_points[i].data[j] as ScatterChartDataPoint).markerSize;\n const circleRadius = calculateMarkerRadius({\n pointMarkerSize,\n minMarkerSize,\n maxMarkerSize,\n extraMaxPixels,\n isContinuousXY,\n isActive: activePoint === circleId,\n defaultRadius: 4,\n activeRadius: 6,\n });\n\n const isLegendSelected: boolean = _legendHighlighted(legendVal) || _noLegendHighlighted() || isSelectedLegend;\n\n const currentPointHidden = _points[i].hideNonActiveDots && activePoint !== circleId;\n const text = _points?.[i].data[j]?.text;\n if (!_isTextMode.current) {\n pointsForSeries.push(\n <>\n <circle\n id={circleId}\n key={circleId}\n r={circleRadius}\n cx={xPoint + _xBandwidth}\n cy={yPoint}\n data-is-focusable={isLegendSelected}\n onMouseOver={(event: React.MouseEvent<SVGElement>) =>\n _handleHover(\n x,\n y,\n verticaLineHeight,\n xAxisCalloutData,\n circleId,\n xAxisCalloutAccessibilityData,\n event,\n )\n }\n onMouseMove={(event: React.MouseEvent<SVGElement>) =>\n _handleHover(\n x,\n y,\n verticaLineHeight,\n xAxisCalloutData,\n circleId,\n xAxisCalloutAccessibilityData,\n event,\n )\n }\n onMouseOut={_handleMouseOut}\n onFocus={event =>\n _handleFocus(event, seriesId, x, xAxisCalloutData, circleId, xAxisCalloutAccessibilityData)\n }\n onBlur={_handleMouseOut}\n {..._getClickHandler(_points[i].data[j].onDataPointClick)}\n opacity={isLegendSelected && !currentPointHidden ? 1 : 0.1}\n fill={_getPointFill(seriesColor, circleId, j, false)}\n stroke={seriesColor}\n role=\"option\"\n aria-label={_getAriaLabel(i, j)}\n tabIndex={isLegendSelected ? 0 : undefined}\n />\n {text && (\n <text\n key={`${circleId}-label`}\n x={xPoint + _xBandwidth}\n y={yPoint + Math.max(circleRadius + 12, 16)}\n className={classes.markerLabel}\n >\n {text}\n </text>\n )}\n </>,\n );\n }\n }\n\n if (_isScatterPolarRef.current) {\n pointsForSeries.push(\n ...renderScatterPolarCategoryLabels({\n xAxisScale: _xAxisScale,\n yAxisScale: _yAxisScale,\n className: classes.markerLabel || '',\n lineOptions: (_points?.[i] as Partial<LineChartPoints>)?.lineOptions,\n }),\n );\n }\n\n series.push(\n <g\n key={`series_${i}`}\n role=\"listbox\"\n aria-label={`${legendVal}, series ${i + 1} of ${_points.length} with ${_points[i].data.length} data points.`}\n >\n {pointsForSeries}\n </g>,\n );\n }\n return series;\n }\n\n function _handleFocus(\n event: React.FocusEvent<SVGCircleElement, Element>,\n seriesId: string,\n x: number | Date | string,\n xAxisCalloutData: string | undefined,\n circleId: string,\n xAxisCalloutAccessibilityData?: AccessibilityProps,\n ) {\n let cx = 0;\n let cy = 0;\n\n const targetRect = (event.target as SVGCircleElement).getBoundingClientRect();\n cx = targetRect.left + targetRect.width / 2;\n cy = targetRect.top + targetRect.height / 2;\n updatePosition(cx, cy);\n _uniqueCallOutID = circleId;\n const formattedData = x instanceof Date ? formatDateToLocaleString(x, props.culture, props.useUTC as boolean) : x;\n const found = findCalloutPoints(calloutPointsRef.current, x) as CustomizedCalloutData | undefined;\n // if no points need to be called out then don't show vertical line and callout card\n\n if (found) {\n d3Select(`#${_verticalLine}`)\n .attr('transform', () => `translate(${_xAxisScale(x) + _xBandwidth}, 0)`)\n .attr('visibility', 'visibility');\n _refArray.forEach((obj: RefArrayData) => {\n if (obj.index === seriesId) {\n setPopoverOpen(true);\n xAxisCalloutData ? setHoverXValue(xAxisCalloutData) : setHoverXValue('' + formattedData);\n setYValueHover(found.values);\n setStackCalloutProps(found!);\n setDataPointCalloutProps(found!);\n setActivePoint(circleId);\n }\n });\n } else {\n setActivePoint(circleId);\n }\n }\n\n function _handleHover(\n x: number | Date | string,\n y: number,\n lineHeight: number,\n xAxisCalloutData: string | undefined,\n circleId: string,\n xAxisCalloutAccessibilityData: AccessibilityProps | undefined,\n mouseEvent: React.MouseEvent<SVGElement>,\n ) {\n mouseEvent?.persist();\n const formattedData = x instanceof Date ? formatDateToLocaleString(x, props.culture, props.useUTC as boolean) : x;\n const found = findCalloutPoints(calloutPointsRef.current, x) as CustomizedCalloutData | undefined;\n // if no points need to be called out then don't show vertical line and callout card\n\n if (found) {\n d3Select(`#${_verticalLine}`)\n .attr('transform', () => `translate(${_xAxisScale(x) + _xBandwidth}, ${_yAxisScale(y)})`)\n .attr('visibility', 'visibility')\n .attr('y2', `${lineHeight - _yAxisScale(y)}`);\n\n if (_uniqueCallOutID !== circleId) {\n _uniqueCallOutID = circleId;\n updatePosition(mouseEvent.clientX, mouseEvent.clientY);\n xAxisCalloutData ? setHoverXValue(xAxisCalloutData) : setHoverXValue('' + formattedData);\n setYValueHover(found.values);\n setStackCalloutProps(found!);\n setDataPointCalloutProps(found!);\n setActivePoint(circleId);\n }\n } else {\n setActivePoint(circleId);\n }\n }\n\n /**\n * Screen readers announce an element as clickable if the onClick attribute is set.\n * This function sets the attribute only when a click event handler is provided.*/\n\n function _getClickHandler(func?: () => void): { onClick?: () => void } {\n if (func) {\n return {\n onClick: func,\n };\n }\n\n return {};\n }\n\n function _handleMouseOut() {\n d3Select(`#${_verticalLine}`).attr('visibility', 'hidden');\n }\n\n function _handleChartMouseLeave() {\n _uniqueCallOutID = null;\n setActivePoint('');\n if (isPopoverOpen) {\n setPopoverOpen(false);\n }\n }\n\n function _getCustomizedCallout() {\n return props.onRenderCalloutPerStack\n ? props.onRenderCalloutPerStack(stackCalloutProps)\n : props.onRenderCalloutPerDataPoint\n ? props.onRenderCalloutPerDataPoint(dataPointCalloutProps)\n : null;\n }\n\n /**\n * This function checks if the given legend is highlighted or not.\n * A legend can be highlighted in 2 ways:\n * 1. selection: if the user clicks on it\n * 2. hovering: if there is no selected legend and the user hovers over it*/\n\n function _legendHighlighted(legend: string): boolean {\n return _getHighlightedLegend().includes(legend);\n }\n\n /**\n * This function checks if none of the legends is selected or hovered.*/\n\n function _noLegendHighlighted(): boolean {\n return _getHighlightedLegend().length === 0;\n }\n\n function _getHighlightedLegend(): string[] {\n return selectedLegends.length > 0 ? selectedLegends : activeLegend ? [activeLegend] : [];\n }\n\n function _getAriaLabel(seriesIndex: number, pointIndex: number): string {\n const series = _points[seriesIndex];\n const point = series.data[pointIndex];\n const formattedDate =\n point.x instanceof Date ? formatDateToLocaleString(point.x, props.culture, props.useUTC as boolean) : point.x;\n const xValue = point.xAxisCalloutData || formattedDate;\n const legend = series.legend;\n const yValue = point.yAxisCalloutData || point.y;\n return point.callOutAccessibilityData?.ariaLabel || `${xValue}. ${legend}, ${yValue}.`;\n }\n\n function _isChartEmpty(): boolean {\n return !(\n props.data &&\n props.data.scatterChartData &&\n props.data.scatterChartData.length > 0 &&\n props.data.scatterChartData.filter((item: ScatterChartPoints) => item.data.length).length > 0\n );\n }\n\n const { legendProps, tickValues, tickFormat } = props;\n _points = _injectIndexPropertyInScatterChartData(props.data.scatterChartData);\n\n let points = _points as ScatterChartPoints[];\n if (legendProps && !!legendProps.canSelectMultipleLegends) {\n points = selectedLegendPoints.length >= 1 ? selectedLegendPoints : _points;\n calloutPointsRef.current = calloutData(points);\n }\n\n let legendBars = null;\n // reduce computation cost by only creating legendBars\n // if when hideLegend is false.\n // NOTE: they are rendered only when hideLegend is false in CartesianChart.\n if (!props.hideLegend && !_isTextMode.current) {\n legendBars = _createLegends(_points!); // ToDo: Memoize legends to improve performance.\n }\n const calloutProps = {\n YValueHover: yValueHover,\n hoverXValue,\n descriptionMessage:\n props.getCalloutDescriptionMessage && stackCalloutProps\n ? props.getCalloutDescriptionMessage(stackCalloutProps)\n : undefined,\n 'data-is-focusable': true,\n xAxisCalloutAccessibilityData,\n ...props.calloutProps,\n clickPosition,\n isPopoverOpen,\n isCalloutForStack: true,\n culture: props.culture,\n isCartesian: true,\n customCallout: {\n customizedCallout: _getCustomizedCallout() !== null ? _getCustomizedCallout()! : undefined,\n customCalloutProps: props.calloutPropsPerDataPoint\n ? props.calloutPropsPerDataPoint(dataPointCalloutProps!)\n : undefined,\n },\n };\n const tickParams = {\n tickValues,\n tickFormat,\n };\n\n const xAxisLabels: string[] = _points\n .map((point: ScatterChartDataWithIndex) => point.data.map((dp: ScatterChartDataPoint) => dp.x as string))\n .flat();\n\n _xAxisLabels = [...new Set(xAxisLabels)];\n\n // Compute unique y axis labels for string y axis\n const _yAxisLabels: string[] = _getOrderedYAxisLabels();\n\n return !_isChartEmpty() ? (\n <CartesianChart\n {...props}\n chartTitle={props.data.chartTitle}\n points={points}\n chartType={ChartTypes.ScatterChart}\n calloutProps={calloutProps}\n tickParams={tickParams}\n legendBars={legendBars}\n getmargins={_getMargins}\n getGraphData={_initializeScatterChartData}\n xAxisType={_xAxisType}\n yAxisType={_yAxisType}\n // Pass stringDatasetForYAxisDomain only if y axis is string\n {...(_yAxisType === YAxisType.StringAxis ? { stringDatasetForYAxisDomain: _yAxisLabels } : {})}\n getMinMaxOfYAxis={_getNumericMinMaxOfY}\n getDomainNRangeValues={_getDomainNRangeValues}\n createYAxis={createNumericYAxis}\n createStringYAxis={createStringYAxis}\n onChartMouseLeave={_handleChartMouseLeave}\n enableFirstRenderOptimization={_firstRenderOptimization}\n datasetForXAxisDomain={_xAxisLabels}\n componentRef={cartesianChartRef}\n {...(_isScatterPolarRef.current ? { yMaxValue: 1, yMinValue: -1 } : {})}\n /* eslint-disable react/jsx-no-bind */\n\n children={(props: ChildProps) => {\n _xAxisScale = props.xScale!;\n _yAxisScale = props.yScalePrimary!;\n return (\n <>\n <g>\n <line\n x1={0}\n y1={0}\n x2={0}\n y2={props.containerHeight}\n stroke={'#323130'}\n id={_verticalLine}\n visibility={'hidden'}\n strokeDasharray={'5,5'}\n />\n <g>{renderSeries}</g>\n </g>\n </>\n );\n }}\n />\n ) : (\n <div id={_emptyChartId} role={'alert'} style={{ opacity: '0' }} aria-label={'Graph has no data to display'} />\n );\n});\nScatterChart.displayName = 'ScatterChart';\n"],"names":["React","useScatterChartStyles","select","d3Select","Legends","max","d3Max","min","d3Min","useId","areArraysEqual","createNumericYAxis","createStringYAxis","getDomainPaddingForMarkers","domainRangeOfXStringAxis","findNumericMinMaxOfY","YAxisType","isTextMode","isScatterPolarSeries","isPlottable","getRangeForScatterMarkerSize","calculateMarkerRadius","domainRangeOfDateForAreaLineScatterVerticalBarCharts","domainRangeOfNumericForAreaLineScatterCharts","sortAxisCategories","findCalloutPoints","CartesianChart","tokens","calloutData","ChartTypes","XAxisTypes","getTypeOfAxis","getNextColor","getColorFromToken","renderScatterPolarCategoryLabels","formatDateToLocaleString","useImageExport","ScatterChart","forwardRef","props","forwardedRef","_circleId","_seriesId","_verticalLine","_firstRenderOptimization","_emptyChartId","_points","_injectIndexPropertyInScatterChartData","data","scatterChartData","_xAxisScale","_yAxisScale","_uniqueCallOutID","_refArray","margins","renderSeries","_xAxisLabels","xAxisCalloutAccessibilityData","_xBandwidth","cartesianChartRef","legendsRef","_legendsRef","componentRef","hideLegend","classes","hoverXValue","setHoverXValue","useState","activeLegend","setActiveLegend","yValueHover","setYValueHover","selectedLegendPoints","setSelectedLegendPoints","isSelectedLegend","setIsSelectedLegend","activePoint","setActivePoint","stackCalloutProps","setStackCalloutProps","dataPointCalloutProps","setDataPointCalloutProps","clickPosition","setClickPosition","x","y","isPopoverOpen","setPopoverOpen","selectedLegends","setSelectedLegends","legendProps","prevSelectedLegendsRef","useRef","undefined","_isTextMode","_isScatterPolarRef","useEffect","current","_xAxisType","length","StringAxis","_yAxisType","NumericAxis","pointsRef","calloutPointsRef","height","width","map","item","index","color","updatePosition","newX","newY","threshold","distance","Math","sqrt","pow","_getNumericMinMaxOfY","points","yAxisType","startValue","endValue","yPadding","yScaleType","start","end","_getDomainNRangeValues","chartType","isRTL","xAxisType","barWidth","tickValues","domainNRangeValue","xScaleType","xMinValue","xMaxValue","DateAxis","_getMargins","_margins","_initializeScatterChartData","xScale","yScale","containerHeight","containerWidth","xElement","_createPlot","_onHoverCardHide","_createLegends","isLegendMultiSelectEnabled","canSelectMultipleLegends","mapLegendToPoints","forEach","point","legend","push","legendDataItems","Object","entries","legendTitle","representativePoint","title","onMouseOutAction","hoverAction","_handleChartMouseLeave","legendShape","shape","legends","enabledWrapLines","enabledLegendsWrapLines","overflowText","legendsOverflowText","onLegendHoverCardLeave","onChange","_onLegendSelectionChange","legendRef","_getOrderedYAxisLabels","shouldOrderYAxisLabelsByCategoryOrder","yAxisCategoryOrder","yLabelsSet","Set","i","Array","isArray","d","add","from","_mapCategoryToValues","categoryToValues","legendsSelected","event","currentLegend","slice","_getPointFill","seriesColor","pointId","pointIndex","isLastPoint","colorNeutralBackground1","series","bandwidth","minMarkerSize","markerSize","maxMarkerSize","isContinuousXY","extraMaxPixels","yScalePrimary","pointsForSeries","legendVal","verticaLineHeight","bottom","j","xAxisCalloutData","xPoint","yPoint","seriesId","circleId","pointMarkerSize","circleRadius","isActive","defaultRadius","activeRadius","isLegendSelected","_legendHighlighted","_noLegendHighlighted","currentPointHidden","hideNonActiveDots","text","circle","id","key","r","cx","cy","data-is-focusable","onMouseOver","_handleHover","onMouseMove","onMouseOut","_handleMouseOut","onFocus","_handleFocus","onBlur","_getClickHandler","onDataPointClick","opacity","fill","stroke","role","aria-label","_getAriaLabel","tabIndex","className","markerLabel","xAxisScale","yAxisScale","lineOptions","g","targetRect","target","getBoundingClientRect","left","top","formattedData","Date","culture","useUTC","found","attr","obj","values","lineHeight","mouseEvent","persist","clientX","clientY","func","onClick","_getCustomizedCallout","onRenderCalloutPerStack","onRenderCalloutPerDataPoint","_getHighlightedLegend","includes","seriesIndex","formattedDate","xValue","yValue","yAxisCalloutData","callOutAccessibilityData","ariaLabel","_isChartEmpty","filter","tickFormat","legendBars","calloutProps","YValueHover","descriptionMessage","getCalloutDescriptionMessage","isCalloutForStack","isCartesian","customCallout","customizedCallout","customCalloutProps","calloutPropsPerDataPoint","tickParams","xAxisLabels","dp","flat","_yAxisLabels","chartTitle","getmargins","getGraphData","stringDatasetForYAxisDomain","getMinMaxOfYAxis","getDomainNRangeValues","createYAxis","onChartMouseLeave","enableFirstRenderOptimization","datasetForXAxisDomain","yMaxValue","yMinValue","children","line","x1","y1","x2","y2","visibility","strokeDasharray","div","style","displayName"],"mappings":"AAAA;AAEA,YAAYA,WAAW,QAAQ;AAE/B,SAASC,qBAAqB,QAAQ,oCAAiC;AAEvE,SAASC,UAAUC,QAAQ,QAAQ,eAAe;AAElD,SAASC,OAAO,QAAQ,sBAAmB;AAC3C,SAASC,OAAOC,KAAK,EAAEC,OAAOC,KAAK,QAAQ,WAAW;AACtD,SAASC,KAAK,QAAQ,4BAA4B;AAGlD,SACEC,cAAc,EACdC,kBAAkB,EAClBC,iBAAiB,EACjBC,0BAA0B,EAC1BC,wBAAwB,EACxBC,oBAAoB,EACpBC,SAAS,EACTC,UAAU,EACVC,oBAAoB,EACpBC,WAAW,EACXC,4BAA4B,EAC5BC,qBAAqB,EACrBC,oDAAoD,EACpDC,4CAA4C,EAC5CC,kBAAkB,EAClBC,iBAAiB,QACZ,2BAAwB;AAW/B,SAASC,cAAc,QAAQ,iBAAc;AAC7C,SAASC,MAAM,QAAQ,wBAAwB;AAC/C,SACEC,WAAW,EACXC,UAAU,EACVC,UAAU,EACVC,aAAa,EACbC,YAAY,EACZC,iBAAiB,QACZ,2BAAwB;AAE/B,SAASC,gCAAgC,QAAQ,wCAAqC;AACtF,SAASC,wBAAwB,QAAQ,4BAA4B;AACrE,SAASC,cAAc,QAAQ,2BAAwB;AAMvD,8FAA8F;AAC9F;;;CAGC,GACD,OAAO,MAAMC,6BAA2DrC,MAAMsC,UAAU,CAGtF,CAACC,OAAOC;QAgC+DD,oBAanEA;IA5CJ,MAAME,YAAoBhC,MAAM;IAChC,MAAMiC,YAAoBjC,MAAM;IAChC,MAAMkC,gBAAwBlC,MAAM;IACpC,MAAMmC,2BAA2B;IACjC,MAAMC,gBAAwBpC,MAAM;IACpC,IAAIqC,UAAuCC,uCAAuCR,MAAMS,IAAI,CAACC,gBAAgB;IAC7G,8DAA8D;IAC9D,IAAIC,cAAmB;IACvB,8DAA8D;IAC9D,IAAIC,cAAmB;IACvB,IAAIC,mBAAkC;IACtC,MAAMC,YAA4B,EAAE;IACpC,IAAIC;IACJ,IAAIC;IACJ,IAAIC,eAAyB,EAAE;IAC/B,MAAMC,gCAAoD,CAAC;IAC3D,IAAIC,cAAc;IAClB,MAAM,EAAEC,iBAAiB,EAAEC,YAAYC,WAAW,EAAE,GAAGzB,eAAeG,MAAMuB,YAAY,EAAEvB,MAAMwB,UAAU;IAC1G,MAAMC,UAAU/D,sBAAsBsC;IAEtC,MAAM,CAAC0B,aAAaC,eAAe,GAAGlE,MAAMmE,QAAQ,CAAkB;IACtE,MAAM,CAACC,cAAcC,gBAAgB,GAAGrE,MAAMmE,QAAQ,CAAS;IAC/D,MAAM,CAACG,aAAaC,eAAe,GAAGvE,MAAMmE,QAAQ,CAAgB,EAAE;IACtE,8DAA8D;IAC9D,MAAM,CAACK,sBAAsBC,wBAAwB,GAAGzE,MAAMmE,QAAQ,CAAQ,EAAE;IAChF,MAAM,CAACO,kBAAkBC,oBAAoB,GAAG3E,MAAMmE,QAAQ,CAAU;IACxE,MAAM,CAACS,aAAaC,eAAe,GAAG7E,MAAMmE,QAAQ,CAAS;IAC7D,MAAM,CAACW,mBAAmBC,qBAAqB,GAAG/E,MAAMmE,QAAQ;IAChE,MAAM,CAACa,uBAAuBC,yBAAyB,GAAGjF,MAAMmE,QAAQ;IACxE,MAAM,CAACe,eAAeC,iBAAiB,GAAGnF,MAAMmE,QAAQ,CAAC;QAAEiB,GAAG;QAAGC,GAAG;IAAE;IACtE,MAAM,CAACC,eAAeC,eAAe,GAAGvF,MAAMmE,QAAQ,CAAC;IACvD,MAAM,CAACqB,iBAAiBC,mBAAmB,GAAGzF,MAAMmE,QAAQ,CAAW5B,EAAAA,qBAAAA,MAAMmD,WAAW,cAAjBnD,yCAAAA,mBAAmBiD,eAAe,KAAI,EAAE;IAC/G,MAAMG,yBAAyB3F,MAAM4F,MAAM,CAAuBC;IAClE,MAAMC,cAAc9F,MAAM4F,MAAM,CAAC;IACjC,MAAMG,qBAAqB/F,MAAM4F,MAAM,CAAC;IAExC5F,MAAMgG,SAAS,CAAC;YAGoCzD,oBAIjBA;QANjC,IACEoD,uBAAuBM,OAAO,IAC9B,CAACvF,eAAeiF,uBAAuBM,OAAO,GAAE1D,qBAAAA,MAAMmD,WAAW,cAAjBnD,yCAAAA,mBAAmBiD,eAAe,GAClF;gBACmBjD;YAAnBkD,mBAAmBlD,EAAAA,sBAAAA,MAAMmD,WAAW,cAAjBnD,0CAAAA,oBAAmBiD,eAAe,KAAI,EAAE;QAC7D;QACAG,uBAAuBM,OAAO,IAAG1D,sBAAAA,MAAMmD,WAAW,cAAjBnD,0CAAAA,oBAAmBiD,eAAe;IACrE,GAAG;SAACjD,sBAAAA,MAAMmD,WAAW,cAAjBnD,0CAAAA,oBAAmBiD,eAAe;KAAC;IAEvC,MAAMU,aACJ3D,MAAMS,IAAI,CAACC,gBAAgB,IAC3BV,MAAMS,IAAI,CAACC,gBAAgB,CAAEkD,MAAM,GAAG,KACtC5D,MAAMS,IAAI,CAACC,gBAAgB,AAAC,CAAC,EAAE,CAACD,IAAI,IACpCT,MAAMS,IAAI,CAACC,gBAAgB,AAAC,CAAC,EAAE,CAACD,IAAI,CAACmD,MAAM,GAAG,IACzCpE,cAAcQ,MAAMS,IAAI,CAACC,gBAAgB,AAAC,CAAC,EAAE,CAACD,IAAI,CAAC,EAAE,CAACoC,CAAC,EAAE,QAC1DtD,WAAWsE,UAAU;IAE3B,yCAAyC;IACzC,MAAMC,aACJ9D,MAAMS,IAAI,CAACC,gBAAgB,IAC3BV,MAAMS,IAAI,CAACC,gBAAgB,CAACkD,MAAM,GAAG,KACrC5D,MAAMS,IAAI,CAACC,gBAAgB,CAAC,EAAE,CAACD,IAAI,IACnCT,MAAMS,IAAI,CAACC,gBAAgB,CAAC,EAAE,CAACD,IAAI,CAACmD,MAAM,GAAG,IACzC,OAAO5D,MAAMS,IAAI,CAACC,gBAAgB,CAAC,EAAE,CAACD,IAAI,CAAC,EAAE,CAACqC,CAAC,KAAK,WAClDrE,UAAUoF,UAAU,GACpBpF,UAAUsF,WAAW,GACvBtF,UAAUsF,WAAW;IAE3B,MAAMC,YAAYvG,MAAM4F,MAAM,CAAmC,EAAE;IACnE,MAAMY,mBAAmBxG,MAAM4F,MAAM,CAAgC,CAAC;IACtE5F,MAAMgG,SAAS,CAAC;QACd;;KAEC,GAED,IAAIlD,YAAYC,uCAAuCR,MAAMS,IAAI,CAACC,gBAAgB,KAAKV,MAAMS,IAAI,KAAKF,SAAS;YAC7GyD,UAAUN,OAAO,GAAGlD,uCAAuCR,MAAMS,IAAI,CAACC,gBAAgB;YACtFuD,iBAAiBP,OAAO,GAAGrE,YAAY2E,UAAUN,OAAO;QAC1D;IACF,GAAG;QAAC1D,MAAMkE,MAAM;QAAElE,MAAMmE,KAAK;QAAEnE,MAAMS,IAAI;QAAEF;KAAQ;IAEnD,SAASC,uCACPE,gBAAuC;QAEvC,OAAOA,mBACHA,iBAAiB0D,GAAG,CAAC,CAACC,MAA0BC;YAC9C,IAAIC;YACJ,IAAI,OAAOF,KAAKE,KAAK,KAAK,aAAa;gBACrCA,QAAQ9E,aAAa6E,OAAO;YAC9B,OAAO;gBACLC,QAAQ7E,kBAAkB2E,KAAKE,KAAK;YACtC;YACA,OAAO;gBACL,GAAGF,IAAI;gBACPC,OAAO,CAAC;gBACRC;YACF;QACF,KACA,EAAE;IACR;IAEA,SAASC,eAAeC,IAAY,EAAEC,IAAY;QAChD,MAAMC,YAAY,GAAG,+BAA+B;QACpD,MAAM,EAAE9B,CAAC,EAAEC,CAAC,EAAE,GAAGH;QACjB,+BAA+B;QAC/B,MAAMiC,WAAWC,KAAKC,IAAI,CAACD,KAAKE,GAAG,CAACN,OAAO5B,GAAG,KAAKgC,KAAKE,GAAG,CAACL,OAAO5B,GAAG;QACtE,+EAA+E;QAC/E,IAAI8B,WAAWD,WAAW;YACxB/B,iBAAiB;gBAAEC,GAAG4B;gBAAM3B,GAAG4B;YAAK;YACpC1B,eAAe;QACjB;IACF;IAEA,SAASgC,qBACPC,MAA4B,EAC5BC,SAAqB;QAErB,MAAM,EAAEC,UAAU,EAAEC,QAAQ,EAAE,GAAG5G,qBAAqByG,QAAQC;QAC9D,MAAMG,WAAW/G,2BAA2B6G,YAAYC,UAAUpF,MAAMsF,UAAU;QAElF,OAAO;YACLH,YAAYA,aAAaE,SAASE,KAAK;YACvCH,UAAUA,WAAWC,SAASG,GAAG;QACnC;IACF;IAEA,SAASC,uBACPR,MAAW,EACXlE,OAAgB,EAChBoD,KAAa,EACbuB,SAAqB,EACrBC,KAAc,EACdC,SAAqB,EACrBC,QAAgB,EAChBC,UAAyC;QAEzC,IAAIC;QACJ,IAAIH,cAAcrG,WAAWwE,WAAW,EAAE;YACxCgC,oBAAoB/G,6CAClBiG,QACAlE,SACAoD,OACAwB,OACA3F,MAAMgG,UAAU,EAChB,MACAhG,MAAMiG,SAAS,EACfjG,MAAMkG,SAAS;QAEnB,OAAO,IAAIN,cAAcrG,WAAW4G,QAAQ,EAAE;YAC5CJ,oBAAoBhH,qDAClBkG,QACAlE,SACAoD,OACAwB,OACAG,YACAJ;QAEJ,OAAO;YACLK,oBAAoBxH,yBAAyBwC,SAASoD,OAAOwB;QAC/D;QACA,OAAOI;IACT;IAEA,SAASK,YAAYC,QAAiB;QACpCtF,UAAUsF;IACZ;IAEA,SAASC,4BACPC,MAAmB,EACnBC,MAAmB,EACnBC,eAAuB,EACvBC,cAAsB,EACtBC,QAA2B;QAE3BhG,cAAc4F;QACd3F,cAAc4F;QACdjD,YAAYG,OAAO,GAAGhF,WAAW6B;QACjCiD,mBAAmBE,OAAO,GAAG/E,qBAAqB4B;QAClDS,eAAe4F,YAAYD,UAAWF;IACxC;IAEA,SAASI;QACP3E,wBAAwB,EAAE;QAC1BE,oBAAoB;IACtB;IAEA,SAAS0E,eAAerG,IAAiC;QACvD,MAAM,EAAE0C,WAAW,EAAE,GAAGnD;QACxB,MAAM+G,6BAA6B,CAAC,CAAE5D,CAAAA,eAAe,CAAC,CAACA,YAAY6D,wBAAwB,AAAD;QAC1F,MAAMC,oBAAiE,CAAC;QACxExG,KAAKyG,OAAO,CAAC,CAACC;YACZ,IAAIA,MAAMC,MAAM,EAAE;gBAChB,IAAI,CAACH,iBAAiB,CAACE,MAAMC,MAAM,CAAC,EAAE;oBACpCH,iBAAiB,CAACE,MAAMC,MAAM,CAAC,GAAG,EAAE;gBACtC;gBACAH,iBAAiB,CAACE,MAAMC,MAAM,CAAC,CAACC,IAAI,CAACF;YACvC;QACF;QACA,MAAMG,kBAA4BC,OAAOC,OAAO,CAACP,mBAAmB7C,GAAG,CAAC,CAAC,CAACqD,aAAaxC,OAAO;YAC5F,MAAMyC,sBAAsBzC,MAAM,CAAC,EAAE;YACrC,qDAAqD;YACrD,MAAMmC,SAAiB;gBACrBO,OAAOF;gBACPlD,OAAOmD,oBAAoBnD,KAAK;gBAChCqD,kBAAkB;oBAChB9F,gBAAgB;gBAClB;gBACA+F,aAAa;oBACXC;oBACAhG,gBAAgB2F;gBAClB;gBACA,GAAIC,oBAAoBK,WAAW,IAAI;oBACrCC,OAAON,oBAAoBK,WAAW;gBACxC,CAAC;YACH;YACA,OAAOX;QACT;QAEA,qBACE,oBAACvJ;YACCoK,SAAS;mBAAIX;aAAgB;YAC7BY,kBAAkBlI,MAAMmI,uBAAuB;YAC/CC,cAAcpI,MAAMqI,mBAAmB;YACtC,GAAItB,8BAA8B;gBAAEuB,wBAAwBzB;YAAiB,CAAC;YAC9E,GAAG7G,MAAMmD,WAAW;YACrBF,iBAAiBA;YACjBsF,UAAUC;YACVC,WAAWnH;;IAGjB;IAEA,SAASoH;QACP,MAAMC,wCACJ7E,eAAerF,UAAUoF,UAAU,IAAI7D,MAAM4I,kBAAkB,KAAK;QACtE,IAAI,CAACD,uCAAuC;YAC1C,0FAA0F;YAC1F,MAAME,aAAa,IAAIC;YACvB,IAAK,IAAIC,IAAIxI,QAAQqD,MAAM,GAAG,GAAGmF,KAAK,GAAGA,IAAK;gBAC5C,MAAM5B,QAAQ5G,OAAO,CAACwI,EAAE;gBACxB,IAAI5B,MAAM1G,IAAI,IAAIuI,MAAMC,OAAO,CAAC9B,MAAM1G,IAAI,GAAG;oBAC3C,KAAK,MAAMyI,KAAK/B,MAAM1G,IAAI,CAAE;wBAC1B,IAAI,OAAOyI,EAAEpG,CAAC,KAAK,UAAU;4BAC3B+F,WAAWM,GAAG,CAACD,EAAEpG,CAAC;wBACpB;oBACF;gBACF;YACF;YACA,OAAOkG,MAAMI,IAAI,CAACP;QACpB;QAEA,OAAO5J,mBAAmBoK,wBAAwBrJ,MAAM4I,kBAAkB;IAC5E;IAEA,SAASS;QACP,MAAMC,mBAA6C,CAAC;QACpD/I,QAAQ2G,OAAO,CAACC,CAAAA;YACd,IAAIA,MAAM1G,IAAI,IAAIuI,MAAMC,OAAO,CAAC9B,MAAM1G,IAAI,GAAG;gBAC3C0G,MAAM1G,IAAI,CAACyG,OAAO,CAACgC,CAAAA;oBACjB,IAAI,OAAOA,EAAEpG,CAAC,KAAK,UAAU;wBAC3B,IAAI,CAACwG,gBAAgB,CAACJ,EAAEpG,CAAC,CAAC,EAAE;4BAC1BwG,gBAAgB,CAACJ,EAAEpG,CAAC,CAAC,GAAG,EAAE;wBAC5B;wBACA,IAAI,OAAOoG,EAAErG,CAAC,KAAK,UAAU;4BAC3ByG,gBAAgB,CAACJ,EAAEpG,CAAC,CAAC,CAACuE,IAAI,CAAC6B,EAAErG,CAAC;wBAChC;oBACF;gBACF;YACF;QACF;QACA,OAAOyG;IACT;IAEA,SAASd,yBACPe,eAAyB,EACzBC,KAA0C,EAC1CC,aAAsB;YAElBzJ,oBAMAA;QANJ,KAAIA,qBAAAA,MAAMmD,WAAW,cAAjBnD,yCAAAA,mBAAmBgH,wBAAwB,EAAE;YAC/C9D,mBAAmBqG;QACrB,OAAO;YACLrG,mBAAmBqG,gBAAgBG,KAAK,CAAC,CAAC;QAC5C;QAEA,KAAI1J,sBAAAA,MAAMmD,WAAW,cAAjBnD,0CAAAA,oBAAmBuI,QAAQ,EAAE;YAC/BvI,MAAMmD,WAAW,CAACoF,QAAQ,CAACgB,iBAAiBC,OAAOC;QACrD;IACF;IAEA,SAASE,cAAcC,WAAmB,EAAEC,OAAe,EAAEC,UAAkB,EAAEC,WAAoB;QACnG,IAAI1H,gBAAgBwH,SAAS;YAC3B,OAAOzK,OAAO4K,uBAAuB;QACvC,OAAO;YACL,OAAOJ;QACT;IACF;IAEA,SAAShD,YAAYD,QAAoB,EAAEF,eAAuB;QAChE,MAAMwD,SAAuB,EAAE;QAC/B,IAAI9H,kBAAkB;YACpB5B,UAAU0B;QACZ,OAAO;YACL1B,UAAUC,uCAAuCR,MAAMS,IAAI,CAACC,gBAAgB;QAC9E;QAEA,IAAIiD,eAAepE,WAAWsE,UAAU,EAAE;YACxC1C,cAAcR,YAAYuJ,SAAS,KAAK;QAC1C;YAGEjM;QADF,MAAMkM,gBACJlM,CAAAA,SAAAA,MAAMsC,SAAS,CAAC4G;YACd,OAAOlJ,MAAMkJ,MAAM1G,IAAI,EAA6B,CAAC4D;gBACnD,OAAOA,KAAK+F,UAAU;YACxB;QACF,gBAJAnM,oBAAAA,SAIM;YAENF;QADF,MAAMsM,gBACJtM,CAAAA,SAAAA,MAAMwC,SAAS,CAAC4G;YACd,OAAOpJ,MAAMoJ,MAAM1G,IAAI,EAA6B,CAAC4D;gBACnD,OAAOA,KAAK+F,UAAU;YACxB;QACF,gBAJArM,oBAAAA,SAIM;QACR,MAAMuM,iBAAiB3G,eAAepE,WAAWsE,UAAU,IAAIC,eAAerF,UAAUoF,UAAU;QAClG,MAAM0G,iBAAiBD,iBACnBzL,6BAA6B;YAC3B4B,MAAMF;YACNgG,QAAQ5F;YACR6J,eAAe5J;YACfoF,YAAYhG,MAAMgG,UAAU;YAC5BV,YAAYtF,MAAMsF,UAAU;QAC9B,KACA;QAEJ,IAAK,IAAIyD,IAAIxI,QAAQqD,MAAM,GAAG,GAAGmF,KAAK,GAAGA,IAAK;YAC5C,MAAM0B,kBAAgC,EAAE;YAExC,MAAMC,YAAoBnK,OAAO,CAACwI,EAAE,CAAC3B,MAAM;YAC3C,MAAMwC,cAAsBrJ,OAAO,CAACwI,EAAE,CAACxE,KAAK;YAC5C,MAAMoG,oBAAoBlE,kBAAkB1F,QAAQ6J,MAAM,GAAI;YAE9D,IAAK,IAAIC,IAAI,GAAGA,IAAItK,OAAO,CAACwI,EAAE,CAACtI,IAAI,CAACmD,MAAM,EAAEiH,IAAK;oBACmBtK,WA2BrDA;gBA3Bb,MAAM,EAAEsC,CAAC,EAAEC,CAAC,EAAEgI,gBAAgB,EAAE5J,6BAA6B,EAAE,GAAGX,oBAAAA,+BAAAA,YAAAA,OAAS,CAACwI,EAAE,cAAZxI,gCAAAA,UAAcE,IAAI,CAACoK,EAAE;gBACvF,MAAME,SAASpK,wBAAAA,kCAAAA,YAAckC;gBAC7B,oCAAoC;gBACpC,MAAMmI,SACJlH,eAAerF,UAAUoF,UAAU,GAC/BjD,CAAAA,wBAAAA,kCAAAA,YAAckC,MAAMlC,CAAAA,CAAAA,wBAAAA,kCAAAA,YAAasJ,SAAS,IAAGtJ,YAAYsJ,SAAS,KAAK,IAAI,CAAA,IAC3EtJ,wBAAAA,kCAAAA,YAAckC;gBACpB,IAAI,CAAClE,YAAYmM,QAAQC,SAAS;oBAChC;gBACF;gBACA,MAAMC,WAAW,GAAG9K,UAAU,CAAC,EAAE4I,EAAE,CAAC,EAAE8B,GAAG;gBACzC,MAAMK,WAAW,GAAGhL,UAAU,CAAC,EAAE6I,EAAE,CAAC,EAAE8B,GAAG;gBACzC,MAAMM,kBAAkB,AAAC5K,OAAO,CAACwI,EAAE,CAACtI,IAAI,CAACoK,EAAE,CAA2BT,UAAU;gBAChF,MAAMgB,eAAetM,sBAAsB;oBACzCqM;oBACAhB;oBACAE;oBACAE;oBACAD;oBACAe,UAAUhJ,gBAAgB6I;oBAC1BI,eAAe;oBACfC,cAAc;gBAChB;gBAEA,MAAMC,mBAA4BC,mBAAmBf,cAAcgB,0BAA0BvJ;gBAE7F,MAAMwJ,qBAAqBpL,OAAO,CAACwI,EAAE,CAAC6C,iBAAiB,IAAIvJ,gBAAgB6I;gBAC3E,MAAMW,OAAOtL,oBAAAA,+BAAAA,mBAAAA,OAAS,CAACwI,EAAE,CAACtI,IAAI,CAACoK,EAAE,cAApBtK,uCAAAA,iBAAsBsL,IAAI;gBACvC,IAAI,CAACtI,YAAYG,OAAO,EAAE;oBACxB+G,gBAAgBpD,IAAI,eAClB,wDACE,oBAACyE;wBACCC,IAAIb;wBACJc,KAAKd;wBACLe,GAAGb;wBACHc,IAAInB,SAAS5J;wBACbgL,IAAInB;wBACJoB,qBAAmBZ;wBACnBa,aAAa,CAAC7C,QACZ8C,aACEzJ,GACAC,GACA6H,mBACAG,kBACAI,UACAhK,+BACAsI;wBAGJ+C,aAAa,CAAC/C,QACZ8C,aACEzJ,GACAC,GACA6H,mBACAG,kBACAI,UACAhK,+BACAsI;wBAGJgD,YAAYC;wBACZC,SAASlD,CAAAA,QACPmD,aAAanD,OAAOyB,UAAUpI,GAAGiI,kBAAkBI,UAAUhK;wBAE/D0L,QAAQH;wBACP,GAAGI,iBAAiBtM,OAAO,CAACwI,EAAE,CAACtI,IAAI,CAACoK,EAAE,CAACiC,gBAAgB,CAAC;wBACzDC,SAASvB,oBAAoB,CAACG,qBAAqB,IAAI;wBACvDqB,MAAMrD,cAAcC,aAAasB,UAAUL,GAAG;wBAC9CoC,QAAQrD;wBACRsD,MAAK;wBACLC,cAAYC,cAAcrE,GAAG8B;wBAC7BwC,UAAU7B,mBAAmB,IAAIlI;wBAElCuI,sBACC,oBAACA;wBACCG,KAAK,GAAGd,SAAS,MAAM,CAAC;wBACxBrI,GAAGkI,SAAS5J;wBACZ2B,GAAGkI,SAASnG,KAAK/G,GAAG,CAACsN,eAAe,IAAI;wBACxCkC,WAAW7L,QAAQ8L,WAAW;uBAE7B1B;gBAKX;YACF;YAEA,IAAIrI,mBAAmBE,OAAO,EAAE;oBAMZnD;gBALlBkK,gBAAgBpD,IAAI,IACf1H,iCAAiC;oBAClC6N,YAAY7M;oBACZ8M,YAAY7M;oBACZ0M,WAAW7L,QAAQ8L,WAAW,IAAI;oBAClCG,WAAW,EAAGnN,oBAAAA,+BAAAA,aAAAA,OAAS,CAACwI,EAAE,cAAZxI,iCAAD,AAACA,WAA2CmN,WAAW;gBACtE;YAEJ;YAEAzD,OAAO5C,IAAI,eACT,oBAACsG;gBACC3B,KAAK,CAAC,OAAO,EAAEjD,GAAG;gBAClBmE,MAAK;gBACLC,cAAY,GAAGzC,UAAU,SAAS,EAAE3B,IAAI,EAAE,IAAI,EAAExI,QAAQqD,MAAM,CAAC,MAAM,EAAErD,OAAO,CAACwI,EAAE,CAACtI,IAAI,CAACmD,MAAM,CAAC,aAAa,CAAC;eAE3G6G;QAGP;QACA,OAAOR;IACT;IAEA,SAAS0C,aACPnD,KAAkD,EAClDyB,QAAgB,EAChBpI,CAAyB,EACzBiI,gBAAoC,EACpCI,QAAgB,EAChBhK,6BAAkD;QAElD,IAAIgL,KAAK;QACT,IAAIC,KAAK;QAET,MAAMyB,aAAa,AAACpE,MAAMqE,MAAM,CAAsBC,qBAAqB;QAC3E5B,KAAK0B,WAAWG,IAAI,GAAGH,WAAWzJ,KAAK,GAAG;QAC1CgI,KAAKyB,WAAWI,GAAG,GAAGJ,WAAW1J,MAAM,GAAG;QAC1CM,eAAe0H,IAAIC;QACnBtL,mBAAmBqK;QACnB,MAAM+C,gBAAgBpL,aAAaqL,OAAOtO,yBAAyBiD,GAAG7C,MAAMmO,OAAO,EAAEnO,MAAMoO,MAAM,IAAevL;QAChH,MAAMwL,QAAQnP,kBAAkB+E,iBAAiBP,OAAO,EAAEb;QAC1D,oFAAoF;QAEpF,IAAIwL,OAAO;YACTzQ,SAAS,CAAC,CAAC,EAAEwC,eAAe,EACzBkO,IAAI,CAAC,aAAa,IAAM,CAAC,UAAU,EAAE3N,YAAYkC,KAAK1B,YAAY,IAAI,CAAC,EACvEmN,IAAI,CAAC,cAAc;YACtBxN,UAAUoG,OAAO,CAAC,CAACqH;gBACjB,IAAIA,IAAIjK,KAAK,KAAK2G,UAAU;oBAC1BjI,eAAe;oBACf8H,mBAAmBnJ,eAAemJ,oBAAoBnJ,eAAe,KAAKsM;oBAC1EjM,eAAeqM,MAAMG,MAAM;oBAC3BhM,qBAAqB6L;oBACrB3L,yBAAyB2L;oBACzB/L,eAAe4I;gBACjB;YACF;QACF,OAAO;YACL5I,eAAe4I;QACjB;IACF;IAEA,SAASoB,aACPzJ,CAAyB,EACzBC,CAAS,EACT2L,UAAkB,EAClB3D,gBAAoC,EACpCI,QAAgB,EAChBhK,6BAA6D,EAC7DwN,UAAwC;QAExCA,uBAAAA,iCAAAA,WAAYC,OAAO;QACnB,MAAMV,gBAAgBpL,aAAaqL,OAAOtO,yBAAyBiD,GAAG7C,MAAMmO,OAAO,EAAEnO,MAAMoO,MAAM,IAAevL;QAChH,MAAMwL,QAAQnP,kBAAkB+E,iBAAiBP,OAAO,EAAEb;QAC1D,oFAAoF;QAEpF,IAAIwL,OAAO;YACTzQ,SAAS,CAAC,CAAC,EAAEwC,eAAe,EACzBkO,IAAI,CAAC,aAAa,IAAM,CAAC,UAAU,EAAE3N,YAAYkC,KAAK1B,YAAY,EAAE,EAAEP,YAAYkC,GAAG,CAAC,CAAC,EACvFwL,IAAI,CAAC,cAAc,cACnBA,IAAI,CAAC,MAAM,GAAGG,aAAa7N,YAAYkC,IAAI;YAE9C,IAAIjC,qBAAqBqK,UAAU;gBACjCrK,mBAAmBqK;gBACnB1G,eAAekK,WAAWE,OAAO,EAAEF,WAAWG,OAAO;gBACrD/D,mBAAmBnJ,eAAemJ,oBAAoBnJ,eAAe,KAAKsM;gBAC1EjM,eAAeqM,MAAMG,MAAM;gBAC3BhM,qBAAqB6L;gBACrB3L,yBAAyB2L;gBACzB/L,eAAe4I;YACjB;QACF,OAAO;YACL5I,eAAe4I;QACjB;IACF;IAEA;;kFAEgF,GAEhF,SAAS2B,iBAAiBiC,IAAiB;QACzC,IAAIA,MAAM;YACR,OAAO;gBACLC,SAASD;YACX;QACF;QAEA,OAAO,CAAC;IACV;IAEA,SAASrC;QACP7O,SAAS,CAAC,CAAC,EAAEwC,eAAe,EAAEkO,IAAI,CAAC,cAAc;IACnD;IAEA,SAASxG;QACPjH,mBAAmB;QACnByB,eAAe;QACf,IAAIS,eAAe;YACjBC,eAAe;QACjB;IACF;IAEA,SAASgM;QACP,OAAOhP,MAAMiP,uBAAuB,GAChCjP,MAAMiP,uBAAuB,CAAC1M,qBAC9BvC,MAAMkP,2BAA2B,GACjClP,MAAMkP,2BAA2B,CAACzM,yBAClC;IACN;IAEA;;;;4EAI0E,GAE1E,SAASgJ,mBAAmBrE,MAAc;QACxC,OAAO+H,wBAAwBC,QAAQ,CAAChI;IAC1C;IAEA;wEACsE,GAEtE,SAASsE;QACP,OAAOyD,wBAAwBvL,MAAM,KAAK;IAC5C;IAEA,SAASuL;QACP,OAAOlM,gBAAgBW,MAAM,GAAG,IAAIX,kBAAkBpB,eAAe;YAACA;SAAa,GAAG,EAAE;IAC1F;IAEA,SAASuL,cAAciC,WAAmB,EAAEvF,UAAkB;YAQrD3C;QAPP,MAAM8C,SAAS1J,OAAO,CAAC8O,YAAY;QACnC,MAAMlI,QAAQ8C,OAAOxJ,IAAI,CAACqJ,WAAW;QACrC,MAAMwF,gBACJnI,MAAMtE,CAAC,YAAYqL,OAAOtO,yBAAyBuH,MAAMtE,CAAC,EAAE7C,MAAMmO,OAAO,EAAEnO,MAAMoO,MAAM,IAAejH,MAAMtE,CAAC;QAC/G,MAAM0M,SAASpI,MAAM2D,gBAAgB,IAAIwE;QACzC,MAAMlI,SAAS6C,OAAO7C,MAAM;QAC5B,MAAMoI,SAASrI,MAAMsI,gBAAgB,IAAItI,MAAMrE,CAAC;QAChD,OAAOqE,EAAAA,kCAAAA,MAAMuI,wBAAwB,cAA9BvI,sDAAAA,gCAAgCwI,SAAS,KAAI,GAAGJ,OAAO,EAAE,EAAEnI,OAAO,EAAE,EAAEoI,OAAO,CAAC,CAAC;IACxF;IAEA,SAASI;QACP,OAAO,CACL5P,CAAAA,MAAMS,IAAI,IACVT,MAAMS,IAAI,CAACC,gBAAgB,IAC3BV,MAAMS,IAAI,CAACC,gBAAgB,CAACkD,MAAM,GAAG,KACrC5D,MAAMS,IAAI,CAACC,gBAAgB,CAACmP,MAAM,CAAC,CAACxL,OAA6BA,KAAK5D,IAAI,CAACmD,MAAM,EAAEA,MAAM,GAAG,CAAA;IAEhG;IAEA,MAAM,EAAET,WAAW,EAAE2C,UAAU,EAAEgK,UAAU,EAAE,GAAG9P;IAChDO,UAAUC,uCAAuCR,MAAMS,IAAI,CAACC,gBAAgB;IAE5E,IAAIuE,SAAS1E;IACb,IAAI4C,eAAe,CAAC,CAACA,YAAY6D,wBAAwB,EAAE;QACzD/B,SAAShD,qBAAqB2B,MAAM,IAAI,IAAI3B,uBAAuB1B;QACnE0D,iBAAiBP,OAAO,GAAGrE,YAAY4F;IACzC;IAEA,IAAI8K,aAAa;IACjB,sDAAsD;IACtD,+BAA+B;IAC/B,2EAA2E;IAC3E,IAAI,CAAC/P,MAAMwB,UAAU,IAAI,CAAC+B,YAAYG,OAAO,EAAE;QAC7CqM,aAAajJ,eAAevG,UAAW,gDAAgD;IACzF;IACA,MAAMyP,eAAe;QACnBC,aAAalO;QACbL;QACAwO,oBACElQ,MAAMmQ,4BAA4B,IAAI5N,oBAClCvC,MAAMmQ,4BAA4B,CAAC5N,qBACnCe;QACN,qBAAqB;QACrBpC;QACA,GAAGlB,MAAMgQ,YAAY;QACrBrN;QACAI;QACAqN,mBAAmB;QACnBjC,SAASnO,MAAMmO,OAAO;QACtBkC,aAAa;QACbC,eAAe;YACbC,mBAAmBvB,4BAA4B,OAAOA,0BAA2B1L;YACjFkN,oBAAoBxQ,MAAMyQ,wBAAwB,GAC9CzQ,MAAMyQ,wBAAwB,CAAChO,yBAC/Ba;QACN;IACF;IACA,MAAMoN,aAAa;QACjB5K;QACAgK;IACF;IAEA,MAAMa,cAAwBpQ,QAC3B6D,GAAG,CAAC,CAAC+C,QAAqCA,MAAM1G,IAAI,CAAC2D,GAAG,CAAC,CAACwM,KAA8BA,GAAG/N,CAAC,GAC5FgO,IAAI;IAEP5P,eAAe;WAAI,IAAI6H,IAAI6H;KAAa;IAExC,iDAAiD;IACjD,MAAMG,eAAyBpI;IAE/B,OAAO,CAACkH,gCACN,oBAACzQ;QACE,GAAGa,KAAK;QACT+Q,YAAY/Q,MAAMS,IAAI,CAACsQ,UAAU;QACjC9L,QAAQA;QACRS,WAAWpG,WAAWQ,YAAY;QAClCkQ,cAAcA;QACdU,YAAYA;QACZX,YAAYA;QACZiB,YAAY5K;QACZ6K,cAAc3K;QACdV,WAAWjC;QACXuB,WAAWpB;QAEV,GAAIA,eAAerF,UAAUoF,UAAU,GAAG;YAAEqN,6BAA6BJ;QAAa,IAAI,CAAC,CAAC;QAC7FK,kBAAkBnM;QAClBoM,uBAAuB3L;QACvB4L,aAAajT;QACbC,mBAAmBA;QACnBiT,mBAAmBxJ;QACnByJ,+BAA+BlR;QAC/BmR,uBAAuBvQ;QACvBM,cAAcH;QACb,GAAIoC,mBAAmBE,OAAO,GAAG;YAAE+N,WAAW;YAAGC,WAAW,CAAC;QAAE,IAAI,CAAC,CAAC;QACtE,oCAAoC,GAEpCC,UAAU,CAAC3R;YACTW,cAAcX,MAAMuG,MAAM;YAC1B3F,cAAcZ,MAAMwK,aAAa;YACjC,qBACE,wDACE,oBAACmD,yBACC,oBAACiE;gBACCC,IAAI;gBACJC,IAAI;gBACJC,IAAI;gBACJC,IAAIhS,MAAMyG,eAAe;gBACzBwG,QAAQ;gBACRlB,IAAI3L;gBACJ6R,YAAY;gBACZC,iBAAiB;8BAEnB,oBAACvE,WAAG3M;QAIZ;uBAGF,oBAACmR;QAAIpG,IAAIzL;QAAe4M,MAAM;QAASkF,OAAO;YAAErF,SAAS;QAAI;QAAGI,cAAY;;AAEhF,GAAG;AACHrN,aAAauS,WAAW,GAAG"}
|
|
1
|
+
{"version":3,"sources":["../src/components/ScatterChart/ScatterChart.tsx"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport type { ScatterChartProps } from './ScatterChart.types';\nimport { useScatterChartStyles } from './useScatterChartStyles.styles';\nimport type { Axis as D3Axis } from 'd3-axis';\nimport { select as d3Select } from 'd3-selection';\nimport type { Legend } from '../Legends/index';\nimport { Legends } from '../Legends/index';\nimport { max as d3Max, min as d3Min } from 'd3-array';\nimport { useId } from '@fluentui/react-utilities';\nimport type { JSXElement } from '@fluentui/react-utilities';\nimport type { IDomainNRange } from '../../utilities/index';\nimport {\n areArraysEqual,\n createNumericYAxis,\n createStringYAxis,\n getDomainPaddingForMarkers,\n domainRangeOfXStringAxis,\n findNumericMinMaxOfY,\n YAxisType,\n isTextMode,\n isScatterPolarSeries,\n isPlottable,\n getRangeForScatterMarkerSize,\n calculateMarkerRadius,\n domainRangeOfDateForAreaLineScatterVerticalBarCharts,\n domainRangeOfNumericForAreaLineScatterCharts,\n sortAxisCategories,\n findCalloutPoints,\n} from '../../utilities/index';\nimport type {\n AccessibilityProps,\n ChildProps,\n CustomizedCalloutData,\n Margins,\n RefArrayData,\n ScatterChartDataPoint,\n ScatterChartPoints,\n YValueHover,\n} from '../../index';\nimport { CartesianChart } from '../../index';\nimport { tokens } from '@fluentui/react-theme';\nimport {\n calloutData,\n ChartTypes,\n XAxisTypes,\n getTypeOfAxis,\n getNextColor,\n getColorFromToken,\n} from '../../utilities/index';\nimport type { LineChartPoints } from '../../types/DataPoint';\nimport { renderScatterPolarCategoryLabels } from '../../utilities/scatterpolar-utils';\nimport { formatDateToLocaleString } from '@fluentui/chart-utilities';\nimport { useImageExport } from '../../utilities/hooks';\n\ntype NumericAxis = D3Axis<number | { valueOf(): number }>;\n\ntype ScatterChartDataWithIndex = ScatterChartPoints & { index: number };\n\n// Create a ScatterChart variant which uses these default styles and this styled subcomponent.\n/**\n * ScatterChart component\n * {@docCategory ScatterChart}\n */\nexport const ScatterChart: React.FunctionComponent<ScatterChartProps> = React.forwardRef<\n HTMLDivElement,\n ScatterChartProps\n>((props, forwardedRef) => {\n const _circleId: string = useId('circle');\n const _seriesId: string = useId('seriesID');\n const _verticalLine: string = useId('verticalLine');\n const _firstRenderOptimization = true;\n const _emptyChartId: string = useId('_ScatterChart_empty');\n let _points: ScatterChartDataWithIndex[] = _injectIndexPropertyInScatterChartData(props.data.scatterChartData);\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n let _xAxisScale: any = '';\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n let _yAxisScale: any = '';\n let _uniqueCallOutID: string | null = '';\n const _refArray: RefArrayData[] = [];\n let margins: Margins;\n let renderSeries: JSXElement[];\n let _xAxisLabels: string[] = [];\n const xAxisCalloutAccessibilityData: AccessibilityProps = {};\n let _xBandwidth = 0;\n const { cartesianChartRef, legendsRef: _legendsRef } = useImageExport(props.componentRef, props.hideLegend);\n const classes = useScatterChartStyles(props);\n\n const [hoverXValue, setHoverXValue] = React.useState<string | number>('');\n const [activeLegend, setActiveLegend] = React.useState<string>('');\n const [yValueHover, setYValueHover] = React.useState<YValueHover[]>([]);\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const [selectedLegendPoints, setSelectedLegendPoints] = React.useState<any[]>([]);\n const [isSelectedLegend, setIsSelectedLegend] = React.useState<boolean>(false);\n const [activePoint, setActivePoint] = React.useState<string>('');\n const [stackCalloutProps, setStackCalloutProps] = React.useState<CustomizedCalloutData>();\n const [dataPointCalloutProps, setDataPointCalloutProps] = React.useState<CustomizedCalloutData>();\n const [clickPosition, setClickPosition] = React.useState({ x: 0, y: 0 });\n const [isPopoverOpen, setPopoverOpen] = React.useState(false);\n const [selectedLegends, setSelectedLegends] = React.useState<string[]>(props.legendProps?.selectedLegends || []);\n const prevSelectedLegendsRef = React.useRef<string[] | undefined>(undefined);\n const _isTextMode = React.useRef(false);\n const _isScatterPolarRef = React.useRef(false);\n\n React.useEffect(() => {\n if (\n prevSelectedLegendsRef.current &&\n !areArraysEqual(prevSelectedLegendsRef.current, props.legendProps?.selectedLegends)\n ) {\n setSelectedLegends(props.legendProps?.selectedLegends || []);\n }\n prevSelectedLegendsRef.current = props.legendProps?.selectedLegends;\n }, [props.legendProps?.selectedLegends]);\n\n const _xAxisType: XAxisTypes =\n props.data.scatterChartData! &&\n props.data.scatterChartData!.length > 0 &&\n props.data.scatterChartData![0].data &&\n props.data.scatterChartData![0].data.length > 0\n ? (getTypeOfAxis(props.data.scatterChartData![0].data[0].x, true) as XAxisTypes)\n : XAxisTypes.StringAxis;\n\n // Detect y axis type (numeric or string)\n const _yAxisType: YAxisType =\n props.data.scatterChartData &&\n props.data.scatterChartData.length > 0 &&\n props.data.scatterChartData[0].data &&\n props.data.scatterChartData[0].data.length > 0\n ? typeof props.data.scatterChartData[0].data[0].y === 'string'\n ? YAxisType.StringAxis\n : YAxisType.NumericAxis\n : YAxisType.NumericAxis;\n\n const pointsRef = React.useRef<ScatterChartDataWithIndex[] | []>([]);\n const calloutPointsRef = React.useRef<Record<string, YValueHover[]>>({});\n React.useEffect(() => {\n /** note that height and width are not used to resize or set as dimesions of the chart,\n * fitParentContainer is responisble for setting the height and width or resizing of the svg/chart\n */\n\n if (_points !== _injectIndexPropertyInScatterChartData(props.data.scatterChartData) || props.data !== _points) {\n pointsRef.current = _injectIndexPropertyInScatterChartData(props.data.scatterChartData);\n calloutPointsRef.current = calloutData(pointsRef.current);\n }\n }, [props.height, props.width, props.data, _points]);\n\n function _injectIndexPropertyInScatterChartData(\n scatterChartData?: ScatterChartPoints[],\n ): ScatterChartDataWithIndex[] | [] {\n return scatterChartData\n ? scatterChartData.map((item: ScatterChartPoints, index: number) => {\n let color: string;\n if (typeof item.color === 'undefined') {\n color = getNextColor(index, 0);\n } else {\n color = getColorFromToken(item.color);\n }\n return {\n ...item,\n index: -1,\n color,\n };\n })\n : [];\n }\n\n function updatePosition(newX: number, newY: number) {\n const threshold = 1; // Set a threshold for movement\n const { x, y } = clickPosition;\n // Calculate the distance moved\n const distance = Math.sqrt(Math.pow(newX - x, 2) + Math.pow(newY - y, 2));\n // Update the position only if the distance moved is greater than the threshold\n if (distance > threshold) {\n setClickPosition({ x: newX, y: newY });\n setPopoverOpen(true);\n }\n }\n\n function _getNumericMinMaxOfY(\n points: ScatterChartPoints[],\n yAxisType?: YAxisType,\n ): { startValue: number; endValue: number } {\n const { startValue, endValue } = findNumericMinMaxOfY(points, yAxisType);\n const yPadding = getDomainPaddingForMarkers(startValue, endValue, props.yScaleType);\n\n return {\n startValue: startValue - yPadding.start,\n endValue: endValue + yPadding.end,\n };\n }\n\n function _getDomainNRangeValues(\n points: any,\n margins: Margins,\n width: number,\n chartType: ChartTypes,\n isRTL: boolean,\n xAxisType: XAxisTypes,\n barWidth: number,\n tickValues: Date[] | number[] | undefined,\n ) {\n let domainNRangeValue: IDomainNRange;\n if (xAxisType === XAxisTypes.NumericAxis) {\n domainNRangeValue = domainRangeOfNumericForAreaLineScatterCharts(\n points,\n margins,\n width,\n isRTL,\n props.xScaleType,\n true,\n props.xMinValue,\n props.xMaxValue,\n );\n } else if (xAxisType === XAxisTypes.DateAxis) {\n domainNRangeValue = domainRangeOfDateForAreaLineScatterVerticalBarCharts(\n points,\n margins,\n width,\n isRTL,\n tickValues! as Date[],\n chartType,\n );\n } else {\n domainNRangeValue = domainRangeOfXStringAxis(margins, width, isRTL);\n }\n return domainNRangeValue;\n }\n\n function _getMargins(_margins: Margins) {\n margins = _margins;\n }\n\n function _initializeScatterChartData(\n xScale: NumericAxis,\n yScale: NumericAxis,\n containerHeight: number,\n containerWidth: number,\n xElement: SVGElement | null,\n ) {\n _xAxisScale = xScale;\n _yAxisScale = yScale;\n _isTextMode.current = isTextMode(_points);\n _isScatterPolarRef.current = isScatterPolarSeries(_points);\n renderSeries = _createPlot(xElement!, containerHeight!);\n }\n\n function _onHoverCardHide() {\n setSelectedLegendPoints([]);\n setIsSelectedLegend(false);\n }\n\n function _createLegends(data: ScatterChartDataWithIndex[]): JSXElement {\n const { legendProps } = props;\n const isLegendMultiSelectEnabled = !!(legendProps && !!legendProps.canSelectMultipleLegends);\n const mapLegendToPoints: Record<string, ScatterChartDataWithIndex[]> = Object.create(null);\n data.forEach((point: ScatterChartDataWithIndex) => {\n if (point.legend) {\n if (!mapLegendToPoints[point.legend]) {\n mapLegendToPoints[point.legend] = [];\n }\n mapLegendToPoints[point.legend].push(point);\n }\n });\n const legendDataItems: Legend[] = Object.entries(mapLegendToPoints).map(([legendTitle, points]) => {\n const representativePoint = points[0];\n // mapping data to the format Legends component needs\n const legend: Legend = {\n title: legendTitle,\n color: representativePoint.color!,\n onMouseOutAction: () => {\n setActiveLegend('');\n },\n hoverAction: () => {\n _handleChartMouseLeave();\n setActiveLegend(legendTitle);\n },\n ...(representativePoint.legendShape && {\n shape: representativePoint.legendShape,\n }),\n };\n return legend;\n });\n\n return (\n <Legends\n legends={[...legendDataItems]}\n enabledWrapLines={props.enabledLegendsWrapLines}\n overflowText={props.legendsOverflowText}\n {...(isLegendMultiSelectEnabled && { onLegendHoverCardLeave: _onHoverCardHide })}\n {...props.legendProps}\n selectedLegends={selectedLegends}\n onChange={_onLegendSelectionChange}\n legendRef={_legendsRef}\n />\n );\n }\n\n function _getOrderedYAxisLabels() {\n const shouldOrderYAxisLabelsByCategoryOrder =\n _yAxisType === YAxisType.StringAxis && props.yAxisCategoryOrder !== 'default';\n if (!shouldOrderYAxisLabelsByCategoryOrder) {\n // Collect all unique string y values from all data points in all series, in reverse order\n const yLabelsSet = new Set<string>();\n for (let i = _points.length - 1; i >= 0; i--) {\n const point = _points[i];\n if (point.data && Array.isArray(point.data)) {\n for (const d of point.data) {\n if (typeof d.y === 'string') {\n yLabelsSet.add(d.y);\n }\n }\n }\n }\n return Array.from(yLabelsSet);\n }\n\n return sortAxisCategories(_mapCategoryToValues(), props.yAxisCategoryOrder);\n }\n\n function _mapCategoryToValues() {\n const categoryToValues: Record<string, number[]> = {};\n _points.forEach(point => {\n if (point.data && Array.isArray(point.data)) {\n point.data.forEach(d => {\n if (typeof d.y === 'string') {\n if (!categoryToValues[d.y]) {\n categoryToValues[d.y] = [];\n }\n if (typeof d.x === 'number') {\n categoryToValues[d.y].push(d.x);\n }\n }\n });\n }\n });\n return categoryToValues;\n }\n\n function _onLegendSelectionChange(\n legendsSelected: string[],\n event: React.MouseEvent<HTMLButtonElement>,\n currentLegend?: Legend,\n ): void {\n if (props.legendProps?.canSelectMultipleLegends) {\n setSelectedLegends(legendsSelected);\n } else {\n setSelectedLegends(legendsSelected.slice(-1));\n }\n\n if (props.legendProps?.onChange) {\n props.legendProps.onChange(legendsSelected, event, currentLegend);\n }\n }\n\n function _getPointFill(seriesColor: string, pointId: string, pointIndex: number, isLastPoint: boolean) {\n if (activePoint === pointId) {\n return tokens.colorNeutralBackground1;\n } else {\n return seriesColor;\n }\n }\n\n function _createPlot(xElement: SVGElement, containerHeight: number): JSXElement[] {\n const series: JSXElement[] = [];\n if (isSelectedLegend) {\n _points = selectedLegendPoints;\n } else {\n _points = _injectIndexPropertyInScatterChartData(props.data.scatterChartData);\n }\n\n if (_xAxisType === XAxisTypes.StringAxis) {\n _xBandwidth = _xAxisScale.bandwidth() / 2;\n }\n\n const minMarkerSize =\n d3Min(_points, (point: ScatterChartPoints) => {\n return d3Min(point.data as ScatterChartDataPoint[], (item: ScatterChartDataPoint) => {\n return item.markerSize as number;\n });\n }) ?? 0;\n const maxMarkerSize =\n d3Max(_points, (point: ScatterChartPoints) => {\n return d3Max(point.data as ScatterChartDataPoint[], (item: ScatterChartDataPoint) => {\n return item.markerSize as number;\n });\n }) ?? 0;\n const isContinuousXY = _xAxisType !== XAxisTypes.StringAxis && _yAxisType !== YAxisType.StringAxis;\n const extraMaxPixels = isContinuousXY\n ? getRangeForScatterMarkerSize({\n data: _points,\n xScale: _xAxisScale,\n yScalePrimary: _yAxisScale,\n xScaleType: props.xScaleType,\n yScaleType: props.yScaleType,\n })\n : 0;\n\n for (let i = _points.length - 1; i >= 0; i--) {\n const pointsForSeries: JSXElement[] = [];\n\n const legendVal: string = _points[i].legend;\n const seriesColor: string = _points[i].color!;\n const verticaLineHeight = containerHeight - margins.bottom! + 6;\n\n for (let j = 0; j < _points[i].data.length; j++) {\n const { x, y, xAxisCalloutData, xAxisCalloutAccessibilityData } = _points?.[i]?.data[j];\n const xPoint = _xAxisScale?.(x);\n // Use string y axis scale if needed\n const yPoint =\n _yAxisType === YAxisType.StringAxis\n ? _yAxisScale?.(y) + (_yAxisScale?.bandwidth ? _yAxisScale.bandwidth() / 2 : 0)\n : _yAxisScale?.(y);\n if (!isPlottable(xPoint, yPoint)) {\n continue;\n }\n const seriesId = `${_seriesId}_${i}_${j}`;\n const circleId = `${_circleId}_${i}_${j}`;\n const pointMarkerSize = (_points[i].data[j] as ScatterChartDataPoint).markerSize;\n const circleRadius = calculateMarkerRadius({\n pointMarkerSize,\n minMarkerSize,\n maxMarkerSize,\n extraMaxPixels,\n isContinuousXY,\n isActive: activePoint === circleId,\n defaultRadius: 4,\n activeRadius: 6,\n });\n\n const isLegendSelected: boolean = _legendHighlighted(legendVal) || _noLegendHighlighted() || isSelectedLegend;\n\n const currentPointHidden = _points[i].hideNonActiveDots && activePoint !== circleId;\n const text = _points?.[i].data[j]?.text;\n if (!_isTextMode.current) {\n pointsForSeries.push(\n <>\n <circle\n id={circleId}\n key={circleId}\n r={circleRadius}\n cx={xPoint + _xBandwidth}\n cy={yPoint}\n data-is-focusable={isLegendSelected}\n onMouseOver={(event: React.MouseEvent<SVGElement>) =>\n _handleHover(\n x,\n y,\n verticaLineHeight,\n xAxisCalloutData,\n circleId,\n xAxisCalloutAccessibilityData,\n event,\n )\n }\n onMouseMove={(event: React.MouseEvent<SVGElement>) =>\n _handleHover(\n x,\n y,\n verticaLineHeight,\n xAxisCalloutData,\n circleId,\n xAxisCalloutAccessibilityData,\n event,\n )\n }\n onMouseOut={_handleMouseOut}\n onFocus={event =>\n _handleFocus(event, seriesId, x, xAxisCalloutData, circleId, xAxisCalloutAccessibilityData)\n }\n onBlur={_handleMouseOut}\n {..._getClickHandler(_points[i].data[j].onDataPointClick)}\n opacity={isLegendSelected && !currentPointHidden ? 1 : 0.1}\n fill={_getPointFill(seriesColor, circleId, j, false)}\n stroke={seriesColor}\n role=\"option\"\n aria-label={_getAriaLabel(i, j)}\n tabIndex={isLegendSelected ? 0 : undefined}\n />\n {text && (\n <text\n key={`${circleId}-label`}\n x={xPoint + _xBandwidth}\n y={yPoint + Math.max(circleRadius + 12, 16)}\n className={classes.markerLabel}\n >\n {text}\n </text>\n )}\n </>,\n );\n }\n }\n\n if (_isScatterPolarRef.current) {\n pointsForSeries.push(\n ...renderScatterPolarCategoryLabels({\n xAxisScale: _xAxisScale,\n yAxisScale: _yAxisScale,\n className: classes.markerLabel || '',\n lineOptions: (_points?.[i] as Partial<LineChartPoints>)?.lineOptions,\n }),\n );\n }\n\n series.push(\n <g\n key={`series_${i}`}\n role=\"listbox\"\n aria-label={`${legendVal}, series ${i + 1} of ${_points.length} with ${_points[i].data.length} data points.`}\n >\n {pointsForSeries}\n </g>,\n );\n }\n return series;\n }\n\n function _handleFocus(\n event: React.FocusEvent<SVGCircleElement, Element>,\n seriesId: string,\n x: number | Date | string,\n xAxisCalloutData: string | undefined,\n circleId: string,\n xAxisCalloutAccessibilityData?: AccessibilityProps,\n ) {\n let cx = 0;\n let cy = 0;\n\n const targetRect = (event.target as SVGCircleElement).getBoundingClientRect();\n cx = targetRect.left + targetRect.width / 2;\n cy = targetRect.top + targetRect.height / 2;\n updatePosition(cx, cy);\n _uniqueCallOutID = circleId;\n const formattedData = x instanceof Date ? formatDateToLocaleString(x, props.culture, props.useUTC as boolean) : x;\n const found = findCalloutPoints(calloutPointsRef.current, x) as CustomizedCalloutData | undefined;\n // if no points need to be called out then don't show vertical line and callout card\n\n if (found) {\n d3Select(`#${_verticalLine}`)\n .attr('transform', () => `translate(${_xAxisScale(x) + _xBandwidth}, 0)`)\n .attr('visibility', 'visibility');\n _refArray.forEach((obj: RefArrayData) => {\n if (obj.index === seriesId) {\n setPopoverOpen(true);\n xAxisCalloutData ? setHoverXValue(xAxisCalloutData) : setHoverXValue('' + formattedData);\n setYValueHover(found.values);\n setStackCalloutProps(found!);\n setDataPointCalloutProps(found!);\n setActivePoint(circleId);\n }\n });\n } else {\n setActivePoint(circleId);\n }\n }\n\n function _handleHover(\n x: number | Date | string,\n y: number,\n lineHeight: number,\n xAxisCalloutData: string | undefined,\n circleId: string,\n xAxisCalloutAccessibilityData: AccessibilityProps | undefined,\n mouseEvent: React.MouseEvent<SVGElement>,\n ) {\n mouseEvent?.persist();\n const formattedData = x instanceof Date ? formatDateToLocaleString(x, props.culture, props.useUTC as boolean) : x;\n const found = findCalloutPoints(calloutPointsRef.current, x) as CustomizedCalloutData | undefined;\n // if no points need to be called out then don't show vertical line and callout card\n\n if (found) {\n d3Select(`#${_verticalLine}`)\n .attr('transform', () => `translate(${_xAxisScale(x) + _xBandwidth}, ${_yAxisScale(y)})`)\n .attr('visibility', 'visibility')\n .attr('y2', `${lineHeight - _yAxisScale(y)}`);\n\n if (_uniqueCallOutID !== circleId) {\n _uniqueCallOutID = circleId;\n updatePosition(mouseEvent.clientX, mouseEvent.clientY);\n xAxisCalloutData ? setHoverXValue(xAxisCalloutData) : setHoverXValue('' + formattedData);\n setYValueHover(found.values);\n setStackCalloutProps(found!);\n setDataPointCalloutProps(found!);\n setActivePoint(circleId);\n }\n } else {\n setActivePoint(circleId);\n }\n }\n\n /**\n * Screen readers announce an element as clickable if the onClick attribute is set.\n * This function sets the attribute only when a click event handler is provided.*/\n\n function _getClickHandler(func?: () => void): { onClick?: () => void } {\n if (func) {\n return {\n onClick: func,\n };\n }\n\n return {};\n }\n\n function _handleMouseOut() {\n d3Select(`#${_verticalLine}`).attr('visibility', 'hidden');\n }\n\n function _handleChartMouseLeave() {\n _uniqueCallOutID = null;\n setActivePoint('');\n if (isPopoverOpen) {\n setPopoverOpen(false);\n }\n }\n\n function _getCustomizedCallout() {\n return props.onRenderCalloutPerStack\n ? props.onRenderCalloutPerStack(stackCalloutProps)\n : props.onRenderCalloutPerDataPoint\n ? props.onRenderCalloutPerDataPoint(dataPointCalloutProps)\n : null;\n }\n\n /**\n * This function checks if the given legend is highlighted or not.\n * A legend can be highlighted in 2 ways:\n * 1. selection: if the user clicks on it\n * 2. hovering: if there is no selected legend and the user hovers over it*/\n\n function _legendHighlighted(legend: string): boolean {\n return _getHighlightedLegend().includes(legend);\n }\n\n /**\n * This function checks if none of the legends is selected or hovered.*/\n\n function _noLegendHighlighted(): boolean {\n return _getHighlightedLegend().length === 0;\n }\n\n function _getHighlightedLegend(): string[] {\n return selectedLegends.length > 0 ? selectedLegends : activeLegend ? [activeLegend] : [];\n }\n\n function _getAriaLabel(seriesIndex: number, pointIndex: number): string {\n const series = _points[seriesIndex];\n const point = series.data[pointIndex];\n const formattedDate =\n point.x instanceof Date ? formatDateToLocaleString(point.x, props.culture, props.useUTC as boolean) : point.x;\n const xValue = point.xAxisCalloutData || formattedDate;\n const legend = series.legend;\n const yValue = point.yAxisCalloutData || point.y;\n return point.callOutAccessibilityData?.ariaLabel || `${xValue}. ${legend}, ${yValue}.`;\n }\n\n function _isChartEmpty(): boolean {\n return !(\n props.data &&\n props.data.scatterChartData &&\n props.data.scatterChartData.length > 0 &&\n props.data.scatterChartData.filter((item: ScatterChartPoints) => item.data.length).length > 0\n );\n }\n\n const { legendProps, tickValues, tickFormat } = props;\n _points = _injectIndexPropertyInScatterChartData(props.data.scatterChartData);\n\n let points = _points as ScatterChartPoints[];\n if (legendProps && !!legendProps.canSelectMultipleLegends) {\n points = selectedLegendPoints.length >= 1 ? selectedLegendPoints : _points;\n calloutPointsRef.current = calloutData(points);\n }\n\n let legendBars = null;\n // reduce computation cost by only creating legendBars\n // if when hideLegend is false.\n // NOTE: they are rendered only when hideLegend is false in CartesianChart.\n if (!props.hideLegend && !_isTextMode.current) {\n legendBars = _createLegends(_points!); // ToDo: Memoize legends to improve performance.\n }\n const calloutProps = {\n YValueHover: yValueHover,\n hoverXValue,\n descriptionMessage:\n props.getCalloutDescriptionMessage && stackCalloutProps\n ? props.getCalloutDescriptionMessage(stackCalloutProps)\n : undefined,\n 'data-is-focusable': true,\n xAxisCalloutAccessibilityData,\n ...props.calloutProps,\n clickPosition,\n isPopoverOpen,\n isCalloutForStack: true,\n culture: props.culture,\n isCartesian: true,\n customCallout: {\n customizedCallout: _getCustomizedCallout() !== null ? _getCustomizedCallout()! : undefined,\n customCalloutProps: props.calloutPropsPerDataPoint\n ? props.calloutPropsPerDataPoint(dataPointCalloutProps!)\n : undefined,\n },\n };\n const tickParams = {\n tickValues,\n tickFormat,\n };\n\n const xAxisLabels: string[] = _points\n .map((point: ScatterChartDataWithIndex) => point.data.map((dp: ScatterChartDataPoint) => dp.x as string))\n .flat();\n\n _xAxisLabels = [...new Set(xAxisLabels)];\n\n // Compute unique y axis labels for string y axis\n const _yAxisLabels: string[] = _getOrderedYAxisLabels();\n\n return !_isChartEmpty() ? (\n <CartesianChart\n {...props}\n chartTitle={props.data.chartTitle}\n points={points}\n chartType={ChartTypes.ScatterChart}\n calloutProps={calloutProps}\n tickParams={tickParams}\n legendBars={legendBars}\n getmargins={_getMargins}\n getGraphData={_initializeScatterChartData}\n xAxisType={_xAxisType}\n yAxisType={_yAxisType}\n // Pass stringDatasetForYAxisDomain only if y axis is string\n {...(_yAxisType === YAxisType.StringAxis ? { stringDatasetForYAxisDomain: _yAxisLabels } : {})}\n getMinMaxOfYAxis={_getNumericMinMaxOfY}\n getDomainNRangeValues={_getDomainNRangeValues}\n createYAxis={createNumericYAxis}\n createStringYAxis={createStringYAxis}\n onChartMouseLeave={_handleChartMouseLeave}\n enableFirstRenderOptimization={_firstRenderOptimization}\n datasetForXAxisDomain={_xAxisLabels}\n componentRef={cartesianChartRef}\n {...(_isScatterPolarRef.current ? { yMaxValue: 1, yMinValue: -1 } : {})}\n /* eslint-disable react/jsx-no-bind */\n\n children={(props: ChildProps) => {\n _xAxisScale = props.xScale!;\n _yAxisScale = props.yScalePrimary!;\n return (\n <>\n <g>\n <line\n x1={0}\n y1={0}\n x2={0}\n y2={props.containerHeight}\n stroke={'#323130'}\n id={_verticalLine}\n visibility={'hidden'}\n strokeDasharray={'5,5'}\n />\n <g>{renderSeries}</g>\n </g>\n </>\n );\n }}\n />\n ) : (\n <div id={_emptyChartId} role={'alert'} style={{ opacity: '0' }} aria-label={'Graph has no data to display'} />\n );\n});\nScatterChart.displayName = 'ScatterChart';\n"],"names":["React","useScatterChartStyles","select","d3Select","Legends","max","d3Max","min","d3Min","useId","areArraysEqual","createNumericYAxis","createStringYAxis","getDomainPaddingForMarkers","domainRangeOfXStringAxis","findNumericMinMaxOfY","YAxisType","isTextMode","isScatterPolarSeries","isPlottable","getRangeForScatterMarkerSize","calculateMarkerRadius","domainRangeOfDateForAreaLineScatterVerticalBarCharts","domainRangeOfNumericForAreaLineScatterCharts","sortAxisCategories","findCalloutPoints","CartesianChart","tokens","calloutData","ChartTypes","XAxisTypes","getTypeOfAxis","getNextColor","getColorFromToken","renderScatterPolarCategoryLabels","formatDateToLocaleString","useImageExport","ScatterChart","forwardRef","props","forwardedRef","_circleId","_seriesId","_verticalLine","_firstRenderOptimization","_emptyChartId","_points","_injectIndexPropertyInScatterChartData","data","scatterChartData","_xAxisScale","_yAxisScale","_uniqueCallOutID","_refArray","margins","renderSeries","_xAxisLabels","xAxisCalloutAccessibilityData","_xBandwidth","cartesianChartRef","legendsRef","_legendsRef","componentRef","hideLegend","classes","hoverXValue","setHoverXValue","useState","activeLegend","setActiveLegend","yValueHover","setYValueHover","selectedLegendPoints","setSelectedLegendPoints","isSelectedLegend","setIsSelectedLegend","activePoint","setActivePoint","stackCalloutProps","setStackCalloutProps","dataPointCalloutProps","setDataPointCalloutProps","clickPosition","setClickPosition","x","y","isPopoverOpen","setPopoverOpen","selectedLegends","setSelectedLegends","legendProps","prevSelectedLegendsRef","useRef","undefined","_isTextMode","_isScatterPolarRef","useEffect","current","_xAxisType","length","StringAxis","_yAxisType","NumericAxis","pointsRef","calloutPointsRef","height","width","map","item","index","color","updatePosition","newX","newY","threshold","distance","Math","sqrt","pow","_getNumericMinMaxOfY","points","yAxisType","startValue","endValue","yPadding","yScaleType","start","end","_getDomainNRangeValues","chartType","isRTL","xAxisType","barWidth","tickValues","domainNRangeValue","xScaleType","xMinValue","xMaxValue","DateAxis","_getMargins","_margins","_initializeScatterChartData","xScale","yScale","containerHeight","containerWidth","xElement","_createPlot","_onHoverCardHide","_createLegends","isLegendMultiSelectEnabled","canSelectMultipleLegends","mapLegendToPoints","Object","create","forEach","point","legend","push","legendDataItems","entries","legendTitle","representativePoint","title","onMouseOutAction","hoverAction","_handleChartMouseLeave","legendShape","shape","legends","enabledWrapLines","enabledLegendsWrapLines","overflowText","legendsOverflowText","onLegendHoverCardLeave","onChange","_onLegendSelectionChange","legendRef","_getOrderedYAxisLabels","shouldOrderYAxisLabelsByCategoryOrder","yAxisCategoryOrder","yLabelsSet","Set","i","Array","isArray","d","add","from","_mapCategoryToValues","categoryToValues","legendsSelected","event","currentLegend","slice","_getPointFill","seriesColor","pointId","pointIndex","isLastPoint","colorNeutralBackground1","series","bandwidth","minMarkerSize","markerSize","maxMarkerSize","isContinuousXY","extraMaxPixels","yScalePrimary","pointsForSeries","legendVal","verticaLineHeight","bottom","j","xAxisCalloutData","xPoint","yPoint","seriesId","circleId","pointMarkerSize","circleRadius","isActive","defaultRadius","activeRadius","isLegendSelected","_legendHighlighted","_noLegendHighlighted","currentPointHidden","hideNonActiveDots","text","circle","id","key","r","cx","cy","data-is-focusable","onMouseOver","_handleHover","onMouseMove","onMouseOut","_handleMouseOut","onFocus","_handleFocus","onBlur","_getClickHandler","onDataPointClick","opacity","fill","stroke","role","aria-label","_getAriaLabel","tabIndex","className","markerLabel","xAxisScale","yAxisScale","lineOptions","g","targetRect","target","getBoundingClientRect","left","top","formattedData","Date","culture","useUTC","found","attr","obj","values","lineHeight","mouseEvent","persist","clientX","clientY","func","onClick","_getCustomizedCallout","onRenderCalloutPerStack","onRenderCalloutPerDataPoint","_getHighlightedLegend","includes","seriesIndex","formattedDate","xValue","yValue","yAxisCalloutData","callOutAccessibilityData","ariaLabel","_isChartEmpty","filter","tickFormat","legendBars","calloutProps","YValueHover","descriptionMessage","getCalloutDescriptionMessage","isCalloutForStack","isCartesian","customCallout","customizedCallout","customCalloutProps","calloutPropsPerDataPoint","tickParams","xAxisLabels","dp","flat","_yAxisLabels","chartTitle","getmargins","getGraphData","stringDatasetForYAxisDomain","getMinMaxOfYAxis","getDomainNRangeValues","createYAxis","onChartMouseLeave","enableFirstRenderOptimization","datasetForXAxisDomain","yMaxValue","yMinValue","children","line","x1","y1","x2","y2","visibility","strokeDasharray","div","style","displayName"],"mappings":"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"}
|
|
@@ -55,6 +55,7 @@ const SAFE_FUNCTIONS = {
|
|
|
55
55
|
toString: (x)=>String(x),
|
|
56
56
|
toBoolean: (x)=>Boolean(x)
|
|
57
57
|
};
|
|
58
|
+
const SAFE_FUNCTION_VALUES = new Set(Object.values(SAFE_FUNCTIONS));
|
|
58
59
|
// ---------------------------------------------------------------------------
|
|
59
60
|
// Whitelisted constants
|
|
60
61
|
// ---------------------------------------------------------------------------
|
|
@@ -447,7 +448,7 @@ class ExpressionParser {
|
|
|
447
448
|
}
|
|
448
449
|
} else if (this._peek().type === '(') {
|
|
449
450
|
// Function call — only safe built-in functions are callable
|
|
450
|
-
if (typeof value !== 'function') {
|
|
451
|
+
if (typeof value !== 'function' || !SAFE_FUNCTION_VALUES.has(value)) {
|
|
451
452
|
throw new Error('Safe expression evaluator: function calls are only allowed for built-in functions');
|
|
452
453
|
}
|
|
453
454
|
this._advance();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/VegaDeclarativeChart/VegaLiteExpressionEvaluator.ts"],"sourcesContent":["/**\n * Safe expression evaluator for Vega-Lite expressions.\n *\n * Recursive-descent parser that only supports the safe subset of the\n * Vega-Lite expression language:\n * - Property access: datum.field, datum['field'] (own properties only)\n * - Arithmetic: +, -, *, /, %\n * - Comparison: ==, ===, !=, !==, <, >, <=, >=\n * - Logical: &&, ||, !\n * - Ternary: condition ? trueVal : falseVal\n * - Literals: numbers, strings, booleans, null\n * - Safe built-in functions: isValid, isDate, isNumber, isNaN, isFinite,\n * abs, ceil, floor, round, sqrt, log, exp, pow, min, max, length,\n * toNumber, toString, toBoolean\n * - Constants: PI, E, SQRT2, LN2, LN10, NaN, Infinity\n *\n * Everything else (assignment, arbitrary function calls, global access) is rejected.\n *\n * @see https://vega.github.io/vega/docs/expressions/\n */\n\n// ---------------------------------------------------------------------------\n// Token types\n// ---------------------------------------------------------------------------\ninterface Token {\n type: string;\n value: unknown;\n start: number;\n}\n\n// ---------------------------------------------------------------------------\n// Own-property check — only allow access to properties that exist directly\n// on the object (not inherited from the prototype chain). This is an allowlist\n// approach: constructor, __proto__, toString, valueOf, etc. are all inherited\n// and thus blocked automatically without maintaining a blocklist.\n// ---------------------------------------------------------------------------\nconst hasOwn = (obj: unknown, prop: string): boolean =>\n obj !== null && obj !== undefined && typeof obj === 'object' && Object.prototype.hasOwnProperty.call(obj, prop);\n\n// ---------------------------------------------------------------------------\n// Whitelisted built-in functions (mirrors the Vega expression function set)\n// ---------------------------------------------------------------------------\nconst SAFE_FUNCTIONS: Record<string, (...args: unknown[]) => unknown> = {\n isValid: (x: unknown) => x !== null && x !== undefined && (typeof x !== 'number' || !isNaN(x as number)),\n isDate: (x: unknown) => x instanceof Date,\n isNumber: (x: unknown) => typeof x === 'number' && !isNaN(x as number),\n isString: (x: unknown) => typeof x === 'string',\n isBoolean: (x: unknown) => typeof x === 'boolean',\n isArray: (x: unknown) => Array.isArray(x),\n isNaN: (x: unknown) => isNaN(x as number),\n isFinite: (x: unknown) => Number.isFinite(x),\n abs: (x: unknown) => Math.abs(x as number),\n ceil: (x: unknown) => Math.ceil(x as number),\n floor: (x: unknown) => Math.floor(x as number),\n round: (x: unknown) => Math.round(x as number),\n sqrt: (x: unknown) => Math.sqrt(x as number),\n log: (x: unknown) => Math.log(x as number),\n exp: (x: unknown) => Math.exp(x as number),\n pow: (x: unknown, y: unknown) => (x as number) ** (y as number),\n min: (...args: unknown[]) => Math.min(...(args as number[])),\n max: (...args: unknown[]) => Math.max(...(args as number[])),\n length: (x: unknown) => (typeof x === 'string' || Array.isArray(x) ? (x as string | unknown[]).length : 0),\n toNumber: (x: unknown) => Number(x),\n toString: (x: unknown) => String(x),\n toBoolean: (x: unknown) => Boolean(x),\n};\n\n// ---------------------------------------------------------------------------\n// Whitelisted constants\n// ---------------------------------------------------------------------------\nconst SAFE_CONSTANTS: Record<string, unknown> = {\n PI: Math.PI,\n E: Math.E,\n SQRT2: Math.SQRT2,\n LN2: Math.LN2,\n LN10: Math.LN10,\n NaN,\n Infinity,\n};\n\n// Set of all allowed top-level identifiers\nconst ALLOWED_IDENTIFIERS = new Set(['datum', ...Object.keys(SAFE_FUNCTIONS), ...Object.keys(SAFE_CONSTANTS)]);\n\n// ---------------------------------------------------------------------------\n// Tokenizer\n// ---------------------------------------------------------------------------\nfunction tokenize(expr: string): Token[] {\n const tokens: Token[] = [];\n let i = 0;\n\n while (i < expr.length) {\n // Skip whitespace\n if (/\\s/.test(expr[i])) {\n i++;\n continue;\n }\n\n // Numbers (including decimal and scientific notation)\n if (/[0-9]/.test(expr[i]) || (expr[i] === '.' && i + 1 < expr.length && /[0-9]/.test(expr[i + 1]))) {\n const start = i;\n while (i < expr.length && /[0-9.]/.test(expr[i])) {\n i++;\n }\n if (i < expr.length && (expr[i] === 'e' || expr[i] === 'E')) {\n i++;\n if (i < expr.length && (expr[i] === '+' || expr[i] === '-')) {\n i++;\n }\n while (i < expr.length && /[0-9]/.test(expr[i])) {\n i++;\n }\n }\n tokens.push({ type: 'number', value: parseFloat(expr.slice(start, i)), start });\n continue;\n }\n\n // Strings (single or double quoted)\n if (expr[i] === '\"' || expr[i] === \"'\") {\n const quote = expr[i];\n const start = i;\n i++;\n let str = '';\n while (i < expr.length && expr[i] !== quote) {\n if (expr[i] === '\\\\') {\n i++;\n if (i < expr.length) {\n switch (expr[i]) {\n case 'n':\n str += '\\n';\n break;\n case 't':\n str += '\\t';\n break;\n case '\\\\':\n str += '\\\\';\n break;\n case \"'\":\n str += \"'\";\n break;\n case '\"':\n str += '\"';\n break;\n default:\n str += expr[i];\n }\n }\n } else {\n str += expr[i];\n }\n i++;\n }\n if (i < expr.length) {\n i++; // Skip closing quote\n }\n tokens.push({ type: 'string', value: str, start });\n continue;\n }\n\n // Identifiers and keywords\n if (/[a-zA-Z_$]/.test(expr[i])) {\n const start = i;\n while (i < expr.length && /[a-zA-Z0-9_$]/.test(expr[i])) {\n i++;\n }\n const word = expr.slice(start, i);\n switch (word) {\n case 'true':\n tokens.push({ type: 'boolean', value: true, start });\n break;\n case 'false':\n tokens.push({ type: 'boolean', value: false, start });\n break;\n case 'null':\n tokens.push({ type: 'null', value: null, start });\n break;\n case 'undefined':\n tokens.push({ type: 'null', value: undefined, start });\n break;\n default:\n tokens.push({ type: 'ident', value: word, start });\n }\n continue;\n }\n\n // Multi-character operators\n const start = i;\n const three = expr.slice(i, i + 3);\n const two = expr.slice(i, i + 2);\n\n if (three === '===' || three === '!==') {\n tokens.push({ type: three, value: three, start });\n i += 3;\n continue;\n }\n if (two === '==' || two === '!=' || two === '<=' || two === '>=' || two === '&&' || two === '||') {\n tokens.push({ type: two, value: two, start });\n i += 2;\n continue;\n }\n\n // Single-character operators and punctuation\n const ch = expr[i];\n if ('+-*/%<>!.()[],?:'.includes(ch)) {\n tokens.push({ type: ch, value: ch, start });\n i++;\n continue;\n }\n\n // Any other character is rejected\n throw new Error(`Safe expression evaluator: unexpected character '${ch}' at position ${i}`);\n }\n\n tokens.push({ type: 'eof', value: null, start: i });\n return tokens;\n}\n\n// ---------------------------------------------------------------------------\n// Recursive-descent parser & evaluator\n//\n// Grammar (precedence low→high):\n// expr → ternary\n// ternary → logicalOr ('?' expr ':' expr)?\n// logicalOr → logicalAnd ('||' logicalAnd)*\n// logicalAnd → equality ('&&' equality)*\n// equality → comparison (('=='|'==='|'!='|'!==') comparison)*\n// comparison → additive (('<'|'>'|'<='|'>=') additive)*\n// additive → multiplicative (('+'|'-') multiplicative)*\n// multiplicative → unary (('*'|'/'|'%') unary)*\n// unary → ('!'|'-'|'+') unary | postfix\n// postfix → primary ('.' ident | '[' expr ']' | '(' args ')')*\n// primary → number | string | boolean | null | ident | '(' expr ')'\n// ---------------------------------------------------------------------------\nclass ExpressionParser {\n private tokens: Token[];\n private pos: number;\n private context: Record<string, unknown>;\n\n constructor(tokens: Token[], context: Record<string, unknown>) {\n this.tokens = tokens;\n this.pos = 0;\n this.context = context;\n }\n\n public parse(): unknown {\n const result = this._parseExpression();\n if (this._peek().type !== 'eof') {\n throw new Error(\n `Safe expression evaluator: unexpected token '${this._peek().type}' at position ${this._peek().start}`,\n );\n }\n return result;\n }\n\n private _peek(): Token {\n return this.tokens[this.pos];\n }\n\n private _advance(): Token {\n const token = this.tokens[this.pos];\n this.pos++;\n return token;\n }\n\n private _expect(type: string): Token {\n const token = this._peek();\n if (token.type !== type) {\n throw new Error(\n `Safe expression evaluator: expected '${type}' but got '${token.type}' at position ${token.start}`,\n );\n }\n return this._advance();\n }\n\n private _parseExpression(): unknown {\n return this._parseTernary();\n }\n\n private _parseTernary(): unknown {\n const condition = this._parseOr();\n if (this._peek().type === '?') {\n this._advance();\n const trueVal = this._parseExpression();\n this._expect(':');\n const falseVal = this._parseExpression();\n return condition ? trueVal : falseVal;\n }\n return condition;\n }\n\n private _parseOr(): unknown {\n let left = this._parseAnd();\n while (this._peek().type === '||') {\n this._advance();\n const right = this._parseAnd();\n left = left || right;\n }\n return left;\n }\n\n private _parseAnd(): unknown {\n let left = this._parseEquality();\n while (this._peek().type === '&&') {\n this._advance();\n const right = this._parseEquality();\n left = left && right;\n }\n return left;\n }\n\n private _parseEquality(): unknown {\n let left = this._parseComparison();\n while (['==', '===', '!=', '!=='].includes(this._peek().type)) {\n const op = this._advance().type;\n const right = this._parseComparison();\n switch (op) {\n case '==':\n // eslint-disable-next-line eqeqeq\n left = left == right;\n break;\n case '===':\n left = left === right;\n break;\n case '!=':\n // eslint-disable-next-line eqeqeq\n left = left != right;\n break;\n case '!==':\n left = left !== right;\n break;\n }\n }\n return left;\n }\n\n private _parseComparison(): unknown {\n let left = this._parseAdditive();\n while (['<', '>', '<=', '>='].includes(this._peek().type)) {\n const op = this._advance().type;\n const right = this._parseAdditive();\n switch (op) {\n case '<':\n left = (left as number) < (right as number);\n break;\n case '>':\n left = (left as number) > (right as number);\n break;\n case '<=':\n left = (left as number) <= (right as number);\n break;\n case '>=':\n left = (left as number) >= (right as number);\n break;\n }\n }\n return left;\n }\n\n private _parseAdditive(): unknown {\n let left = this._parseMultiplicative();\n while (['+', '-'].includes(this._peek().type)) {\n const op = this._advance().type;\n const right = this._parseMultiplicative();\n if (op === '+') {\n left =\n typeof left === 'string' || typeof right === 'string'\n ? String(left) + String(right)\n : (left as number) + (right as number);\n } else {\n left = (left as number) - (right as number);\n }\n }\n return left;\n }\n\n private _parseMultiplicative(): unknown {\n let left = this._parseUnary();\n while (['*', '/', '%'].includes(this._peek().type)) {\n const op = this._advance().type;\n const right = this._parseUnary();\n switch (op) {\n case '*':\n left = (left as number) * (right as number);\n break;\n case '/':\n left = (left as number) / (right as number);\n break;\n case '%':\n left = (left as number) % (right as number);\n break;\n }\n }\n return left;\n }\n\n private _parseUnary(): unknown {\n if (this._peek().type === '!') {\n this._advance();\n return !this._parseUnary();\n }\n if (this._peek().type === '-') {\n this._advance();\n return -(this._parseUnary() as number);\n }\n if (this._peek().type === '+') {\n this._advance();\n return +(this._parseUnary() as number);\n }\n return this._parsePostfix();\n }\n\n private _parsePostfix(): unknown {\n let value = this._parsePrimary();\n\n while (true) {\n if (this._peek().type === '.') {\n // Property access: obj.prop — only own properties allowed\n this._advance();\n const prop = this._expect('ident');\n const propName = prop.value as string;\n\n if (hasOwn(value, propName)) {\n value = (value as Record<string, unknown>)[propName];\n } else {\n value = undefined;\n }\n } else if (this._peek().type === '[') {\n // Bracket access: obj['prop'] or obj[expr] — only own properties allowed\n this._advance();\n const index = this._parseExpression();\n this._expect(']');\n\n const key = String(index);\n if (hasOwn(value, key)) {\n value = (value as Record<string, unknown>)[key];\n } else {\n value = undefined;\n }\n } else if (this._peek().type === '(') {\n // Function call — only safe built-in functions are callable\n if (typeof value !== 'function') {\n throw new Error('Safe expression evaluator: function calls are only allowed for built-in functions');\n }\n this._advance();\n const args: unknown[] = [];\n if (this._peek().type !== ')') {\n args.push(this._parseExpression());\n while (this._peek().type === ',') {\n this._advance();\n args.push(this._parseExpression());\n }\n }\n this._expect(')');\n value = (value as (...a: unknown[]) => unknown)(...args);\n } else {\n break;\n }\n }\n\n return value;\n }\n\n private _parsePrimary(): unknown {\n const token = this._peek();\n\n switch (token.type) {\n case 'number':\n case 'string':\n case 'boolean':\n case 'null':\n this._advance();\n return token.value;\n\n case 'ident': {\n const name = token.value as string;\n if (!ALLOWED_IDENTIFIERS.has(name)) {\n throw new Error(`Safe expression evaluator: unknown identifier '${name}'`);\n }\n this._advance();\n if (name === 'datum') {\n return this.context.datum;\n }\n if (name in SAFE_FUNCTIONS) {\n return SAFE_FUNCTIONS[name];\n }\n if (name in SAFE_CONSTANTS) {\n return SAFE_CONSTANTS[name];\n }\n return undefined;\n }\n\n case '(': {\n this._advance();\n const result = this._parseExpression();\n this._expect(')');\n return result;\n }\n\n default:\n throw new Error(`Safe expression evaluator: unexpected token '${token.type}' at position ${token.start}`);\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Safely evaluates a Vega-Lite expression string against a datum object.\n *\n * Only allows property access, arithmetic, comparison, logical operators,\n * ternary expressions, literals, and a whitelist of built-in functions.\n * Rejects assignment, arbitrary function calls, and global object access.\n *\n * @param expr - The Vega-Lite expression string to evaluate\n * @param datum - The data row object (accessible as `datum` in the expression)\n * @returns The result of evaluating the expression\n * @throws Error if the expression contains disallowed constructs\n */\nexport function safeEvaluateExpression(expr: string, datum: Record<string, unknown>): unknown {\n const tokens = tokenize(expr);\n const parser = new ExpressionParser(tokens, { datum });\n return parser.parse();\n}\n"],"names":["hasOwn","obj","prop","undefined","Object","prototype","hasOwnProperty","call","SAFE_FUNCTIONS","isValid","x","isNaN","isDate","Date","isNumber","isString","isBoolean","isArray","Array","isFinite","Number","abs","Math","ceil","floor","round","sqrt","log","exp","pow","y","min","args","max","length","toNumber","toString","String","toBoolean","Boolean","SAFE_CONSTANTS","PI","E","SQRT2","LN2","LN10","NaN","Infinity","ALLOWED_IDENTIFIERS","Set","keys","tokenize","expr","tokens","i","test","start","push","type","value","parseFloat","slice","quote","str","word","three","two","ch","includes","Error","ExpressionParser","parse","result","_parseExpression","_peek","pos","_advance","token","_expect","_parseTernary","condition","_parseOr","trueVal","falseVal","left","_parseAnd","right","_parseEquality","_parseComparison","op","_parseAdditive","_parseMultiplicative","_parseUnary","_parsePostfix","_parsePrimary","propName","index","key","name","has","context","datum","constructor","safeEvaluateExpression","parser"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../src/components/VegaDeclarativeChart/VegaLiteExpressionEvaluator.ts"],"sourcesContent":["/**\n * Safe expression evaluator for Vega-Lite expressions.\n *\n * Recursive-descent parser that only supports the safe subset of the\n * Vega-Lite expression language:\n * - Property access: datum.field, datum['field'] (own properties only)\n * - Arithmetic: +, -, *, /, %\n * - Comparison: ==, ===, !=, !==, <, >, <=, >=\n * - Logical: &&, ||, !\n * - Ternary: condition ? trueVal : falseVal\n * - Literals: numbers, strings, booleans, null\n * - Safe built-in functions: isValid, isDate, isNumber, isNaN, isFinite,\n * abs, ceil, floor, round, sqrt, log, exp, pow, min, max, length,\n * toNumber, toString, toBoolean\n * - Constants: PI, E, SQRT2, LN2, LN10, NaN, Infinity\n *\n * Everything else (assignment, arbitrary function calls, global access) is rejected.\n *\n * @see https://vega.github.io/vega/docs/expressions/\n */\n\n// ---------------------------------------------------------------------------\n// Token types\n// ---------------------------------------------------------------------------\ninterface Token {\n type: string;\n value: unknown;\n start: number;\n}\n\n// ---------------------------------------------------------------------------\n// Own-property check — only allow access to properties that exist directly\n// on the object (not inherited from the prototype chain). This is an allowlist\n// approach: constructor, __proto__, toString, valueOf, etc. are all inherited\n// and thus blocked automatically without maintaining a blocklist.\n// ---------------------------------------------------------------------------\nconst hasOwn = (obj: unknown, prop: string): boolean =>\n obj !== null && obj !== undefined && typeof obj === 'object' && Object.prototype.hasOwnProperty.call(obj, prop);\n\n// ---------------------------------------------------------------------------\n// Whitelisted built-in functions (mirrors the Vega expression function set)\n// ---------------------------------------------------------------------------\nconst SAFE_FUNCTIONS: Record<string, (...args: unknown[]) => unknown> = {\n isValid: (x: unknown) => x !== null && x !== undefined && (typeof x !== 'number' || !isNaN(x as number)),\n isDate: (x: unknown) => x instanceof Date,\n isNumber: (x: unknown) => typeof x === 'number' && !isNaN(x as number),\n isString: (x: unknown) => typeof x === 'string',\n isBoolean: (x: unknown) => typeof x === 'boolean',\n isArray: (x: unknown) => Array.isArray(x),\n isNaN: (x: unknown) => isNaN(x as number),\n isFinite: (x: unknown) => Number.isFinite(x),\n abs: (x: unknown) => Math.abs(x as number),\n ceil: (x: unknown) => Math.ceil(x as number),\n floor: (x: unknown) => Math.floor(x as number),\n round: (x: unknown) => Math.round(x as number),\n sqrt: (x: unknown) => Math.sqrt(x as number),\n log: (x: unknown) => Math.log(x as number),\n exp: (x: unknown) => Math.exp(x as number),\n pow: (x: unknown, y: unknown) => (x as number) ** (y as number),\n min: (...args: unknown[]) => Math.min(...(args as number[])),\n max: (...args: unknown[]) => Math.max(...(args as number[])),\n length: (x: unknown) => (typeof x === 'string' || Array.isArray(x) ? (x as string | unknown[]).length : 0),\n toNumber: (x: unknown) => Number(x),\n toString: (x: unknown) => String(x),\n toBoolean: (x: unknown) => Boolean(x),\n};\nconst SAFE_FUNCTION_VALUES = new Set(Object.values(SAFE_FUNCTIONS));\n\n// ---------------------------------------------------------------------------\n// Whitelisted constants\n// ---------------------------------------------------------------------------\nconst SAFE_CONSTANTS: Record<string, unknown> = {\n PI: Math.PI,\n E: Math.E,\n SQRT2: Math.SQRT2,\n LN2: Math.LN2,\n LN10: Math.LN10,\n NaN,\n Infinity,\n};\n\n// Set of all allowed top-level identifiers\nconst ALLOWED_IDENTIFIERS = new Set(['datum', ...Object.keys(SAFE_FUNCTIONS), ...Object.keys(SAFE_CONSTANTS)]);\n\n// ---------------------------------------------------------------------------\n// Tokenizer\n// ---------------------------------------------------------------------------\nfunction tokenize(expr: string): Token[] {\n const tokens: Token[] = [];\n let i = 0;\n\n while (i < expr.length) {\n // Skip whitespace\n if (/\\s/.test(expr[i])) {\n i++;\n continue;\n }\n\n // Numbers (including decimal and scientific notation)\n if (/[0-9]/.test(expr[i]) || (expr[i] === '.' && i + 1 < expr.length && /[0-9]/.test(expr[i + 1]))) {\n const start = i;\n while (i < expr.length && /[0-9.]/.test(expr[i])) {\n i++;\n }\n if (i < expr.length && (expr[i] === 'e' || expr[i] === 'E')) {\n i++;\n if (i < expr.length && (expr[i] === '+' || expr[i] === '-')) {\n i++;\n }\n while (i < expr.length && /[0-9]/.test(expr[i])) {\n i++;\n }\n }\n tokens.push({ type: 'number', value: parseFloat(expr.slice(start, i)), start });\n continue;\n }\n\n // Strings (single or double quoted)\n if (expr[i] === '\"' || expr[i] === \"'\") {\n const quote = expr[i];\n const start = i;\n i++;\n let str = '';\n while (i < expr.length && expr[i] !== quote) {\n if (expr[i] === '\\\\') {\n i++;\n if (i < expr.length) {\n switch (expr[i]) {\n case 'n':\n str += '\\n';\n break;\n case 't':\n str += '\\t';\n break;\n case '\\\\':\n str += '\\\\';\n break;\n case \"'\":\n str += \"'\";\n break;\n case '\"':\n str += '\"';\n break;\n default:\n str += expr[i];\n }\n }\n } else {\n str += expr[i];\n }\n i++;\n }\n if (i < expr.length) {\n i++; // Skip closing quote\n }\n tokens.push({ type: 'string', value: str, start });\n continue;\n }\n\n // Identifiers and keywords\n if (/[a-zA-Z_$]/.test(expr[i])) {\n const start = i;\n while (i < expr.length && /[a-zA-Z0-9_$]/.test(expr[i])) {\n i++;\n }\n const word = expr.slice(start, i);\n switch (word) {\n case 'true':\n tokens.push({ type: 'boolean', value: true, start });\n break;\n case 'false':\n tokens.push({ type: 'boolean', value: false, start });\n break;\n case 'null':\n tokens.push({ type: 'null', value: null, start });\n break;\n case 'undefined':\n tokens.push({ type: 'null', value: undefined, start });\n break;\n default:\n tokens.push({ type: 'ident', value: word, start });\n }\n continue;\n }\n\n // Multi-character operators\n const start = i;\n const three = expr.slice(i, i + 3);\n const two = expr.slice(i, i + 2);\n\n if (three === '===' || three === '!==') {\n tokens.push({ type: three, value: three, start });\n i += 3;\n continue;\n }\n if (two === '==' || two === '!=' || two === '<=' || two === '>=' || two === '&&' || two === '||') {\n tokens.push({ type: two, value: two, start });\n i += 2;\n continue;\n }\n\n // Single-character operators and punctuation\n const ch = expr[i];\n if ('+-*/%<>!.()[],?:'.includes(ch)) {\n tokens.push({ type: ch, value: ch, start });\n i++;\n continue;\n }\n\n // Any other character is rejected\n throw new Error(`Safe expression evaluator: unexpected character '${ch}' at position ${i}`);\n }\n\n tokens.push({ type: 'eof', value: null, start: i });\n return tokens;\n}\n\n// ---------------------------------------------------------------------------\n// Recursive-descent parser & evaluator\n//\n// Grammar (precedence low→high):\n// expr → ternary\n// ternary → logicalOr ('?' expr ':' expr)?\n// logicalOr → logicalAnd ('||' logicalAnd)*\n// logicalAnd → equality ('&&' equality)*\n// equality → comparison (('=='|'==='|'!='|'!==') comparison)*\n// comparison → additive (('<'|'>'|'<='|'>=') additive)*\n// additive → multiplicative (('+'|'-') multiplicative)*\n// multiplicative → unary (('*'|'/'|'%') unary)*\n// unary → ('!'|'-'|'+') unary | postfix\n// postfix → primary ('.' ident | '[' expr ']' | '(' args ')')*\n// primary → number | string | boolean | null | ident | '(' expr ')'\n// ---------------------------------------------------------------------------\nclass ExpressionParser {\n private tokens: Token[];\n private pos: number;\n private context: Record<string, unknown>;\n\n constructor(tokens: Token[], context: Record<string, unknown>) {\n this.tokens = tokens;\n this.pos = 0;\n this.context = context;\n }\n\n public parse(): unknown {\n const result = this._parseExpression();\n if (this._peek().type !== 'eof') {\n throw new Error(\n `Safe expression evaluator: unexpected token '${this._peek().type}' at position ${this._peek().start}`,\n );\n }\n return result;\n }\n\n private _peek(): Token {\n return this.tokens[this.pos];\n }\n\n private _advance(): Token {\n const token = this.tokens[this.pos];\n this.pos++;\n return token;\n }\n\n private _expect(type: string): Token {\n const token = this._peek();\n if (token.type !== type) {\n throw new Error(\n `Safe expression evaluator: expected '${type}' but got '${token.type}' at position ${token.start}`,\n );\n }\n return this._advance();\n }\n\n private _parseExpression(): unknown {\n return this._parseTernary();\n }\n\n private _parseTernary(): unknown {\n const condition = this._parseOr();\n if (this._peek().type === '?') {\n this._advance();\n const trueVal = this._parseExpression();\n this._expect(':');\n const falseVal = this._parseExpression();\n return condition ? trueVal : falseVal;\n }\n return condition;\n }\n\n private _parseOr(): unknown {\n let left = this._parseAnd();\n while (this._peek().type === '||') {\n this._advance();\n const right = this._parseAnd();\n left = left || right;\n }\n return left;\n }\n\n private _parseAnd(): unknown {\n let left = this._parseEquality();\n while (this._peek().type === '&&') {\n this._advance();\n const right = this._parseEquality();\n left = left && right;\n }\n return left;\n }\n\n private _parseEquality(): unknown {\n let left = this._parseComparison();\n while (['==', '===', '!=', '!=='].includes(this._peek().type)) {\n const op = this._advance().type;\n const right = this._parseComparison();\n switch (op) {\n case '==':\n // eslint-disable-next-line eqeqeq\n left = left == right;\n break;\n case '===':\n left = left === right;\n break;\n case '!=':\n // eslint-disable-next-line eqeqeq\n left = left != right;\n break;\n case '!==':\n left = left !== right;\n break;\n }\n }\n return left;\n }\n\n private _parseComparison(): unknown {\n let left = this._parseAdditive();\n while (['<', '>', '<=', '>='].includes(this._peek().type)) {\n const op = this._advance().type;\n const right = this._parseAdditive();\n switch (op) {\n case '<':\n left = (left as number) < (right as number);\n break;\n case '>':\n left = (left as number) > (right as number);\n break;\n case '<=':\n left = (left as number) <= (right as number);\n break;\n case '>=':\n left = (left as number) >= (right as number);\n break;\n }\n }\n return left;\n }\n\n private _parseAdditive(): unknown {\n let left = this._parseMultiplicative();\n while (['+', '-'].includes(this._peek().type)) {\n const op = this._advance().type;\n const right = this._parseMultiplicative();\n if (op === '+') {\n left =\n typeof left === 'string' || typeof right === 'string'\n ? String(left) + String(right)\n : (left as number) + (right as number);\n } else {\n left = (left as number) - (right as number);\n }\n }\n return left;\n }\n\n private _parseMultiplicative(): unknown {\n let left = this._parseUnary();\n while (['*', '/', '%'].includes(this._peek().type)) {\n const op = this._advance().type;\n const right = this._parseUnary();\n switch (op) {\n case '*':\n left = (left as number) * (right as number);\n break;\n case '/':\n left = (left as number) / (right as number);\n break;\n case '%':\n left = (left as number) % (right as number);\n break;\n }\n }\n return left;\n }\n\n private _parseUnary(): unknown {\n if (this._peek().type === '!') {\n this._advance();\n return !this._parseUnary();\n }\n if (this._peek().type === '-') {\n this._advance();\n return -(this._parseUnary() as number);\n }\n if (this._peek().type === '+') {\n this._advance();\n return +(this._parseUnary() as number);\n }\n return this._parsePostfix();\n }\n\n private _parsePostfix(): unknown {\n let value = this._parsePrimary();\n\n while (true) {\n if (this._peek().type === '.') {\n // Property access: obj.prop — only own properties allowed\n this._advance();\n const prop = this._expect('ident');\n const propName = prop.value as string;\n\n if (hasOwn(value, propName)) {\n value = (value as Record<string, unknown>)[propName];\n } else {\n value = undefined;\n }\n } else if (this._peek().type === '[') {\n // Bracket access: obj['prop'] or obj[expr] — only own properties allowed\n this._advance();\n const index = this._parseExpression();\n this._expect(']');\n\n const key = String(index);\n if (hasOwn(value, key)) {\n value = (value as Record<string, unknown>)[key];\n } else {\n value = undefined;\n }\n } else if (this._peek().type === '(') {\n // Function call — only safe built-in functions are callable\n if (typeof value !== 'function' || !SAFE_FUNCTION_VALUES.has(value as (...args: unknown[]) => unknown)) {\n throw new Error('Safe expression evaluator: function calls are only allowed for built-in functions');\n }\n this._advance();\n const args: unknown[] = [];\n if (this._peek().type !== ')') {\n args.push(this._parseExpression());\n while (this._peek().type === ',') {\n this._advance();\n args.push(this._parseExpression());\n }\n }\n this._expect(')');\n value = (value as (...a: unknown[]) => unknown)(...args);\n } else {\n break;\n }\n }\n\n return value;\n }\n\n private _parsePrimary(): unknown {\n const token = this._peek();\n\n switch (token.type) {\n case 'number':\n case 'string':\n case 'boolean':\n case 'null':\n this._advance();\n return token.value;\n\n case 'ident': {\n const name = token.value as string;\n if (!ALLOWED_IDENTIFIERS.has(name)) {\n throw new Error(`Safe expression evaluator: unknown identifier '${name}'`);\n }\n this._advance();\n if (name === 'datum') {\n return this.context.datum;\n }\n if (name in SAFE_FUNCTIONS) {\n return SAFE_FUNCTIONS[name];\n }\n if (name in SAFE_CONSTANTS) {\n return SAFE_CONSTANTS[name];\n }\n return undefined;\n }\n\n case '(': {\n this._advance();\n const result = this._parseExpression();\n this._expect(')');\n return result;\n }\n\n default:\n throw new Error(`Safe expression evaluator: unexpected token '${token.type}' at position ${token.start}`);\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Safely evaluates a Vega-Lite expression string against a datum object.\n *\n * Only allows property access, arithmetic, comparison, logical operators,\n * ternary expressions, literals, and a whitelist of built-in functions.\n * Rejects assignment, arbitrary function calls, and global object access.\n *\n * @param expr - The Vega-Lite expression string to evaluate\n * @param datum - The data row object (accessible as `datum` in the expression)\n * @returns The result of evaluating the expression\n * @throws Error if the expression contains disallowed constructs\n */\nexport function safeEvaluateExpression(expr: string, datum: Record<string, unknown>): unknown {\n const tokens = tokenize(expr);\n const parser = new ExpressionParser(tokens, { datum });\n return parser.parse();\n}\n"],"names":["hasOwn","obj","prop","undefined","Object","prototype","hasOwnProperty","call","SAFE_FUNCTIONS","isValid","x","isNaN","isDate","Date","isNumber","isString","isBoolean","isArray","Array","isFinite","Number","abs","Math","ceil","floor","round","sqrt","log","exp","pow","y","min","args","max","length","toNumber","toString","String","toBoolean","Boolean","SAFE_FUNCTION_VALUES","Set","values","SAFE_CONSTANTS","PI","E","SQRT2","LN2","LN10","NaN","Infinity","ALLOWED_IDENTIFIERS","keys","tokenize","expr","tokens","i","test","start","push","type","value","parseFloat","slice","quote","str","word","three","two","ch","includes","Error","ExpressionParser","parse","result","_parseExpression","_peek","pos","_advance","token","_expect","_parseTernary","condition","_parseOr","trueVal","falseVal","left","_parseAnd","right","_parseEquality","_parseComparison","op","_parseAdditive","_parseMultiplicative","_parseUnary","_parsePostfix","_parsePrimary","propName","index","key","has","name","context","datum","constructor","safeEvaluateExpression","parser"],"mappings":"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"}
|
|
@@ -188,7 +188,7 @@ const DEFAULT_TRUNCATE_CHARS = 20;
|
|
|
188
188
|
groups.get(key).push(row);
|
|
189
189
|
});
|
|
190
190
|
result = Array.from(groups.entries()).map(([key, rows])=>{
|
|
191
|
-
const baseRow =
|
|
191
|
+
const baseRow = Object.create(null);
|
|
192
192
|
groupby.forEach((g, i)=>{
|
|
193
193
|
baseRow[g] = rows[0][g];
|
|
194
194
|
});
|
|
@@ -2081,7 +2081,8 @@ export function transformVegaLiteToLineChartProps(spec, colorMap, isDarkTheme) {
|
|
|
2081
2081
|
// Extract color configuration
|
|
2082
2082
|
const { colorScheme, colorRange } = extractColorConfig(encoding);
|
|
2083
2083
|
// Group data by x value, then by color (stack)
|
|
2084
|
-
|
|
2084
|
+
// Null-prototype object so data-derived keys (e.g. "__proto__") cannot pollute Object.prototype.
|
|
2085
|
+
const mapXToDataPoints = Object.create(null);
|
|
2085
2086
|
const colorIndex = new Map();
|
|
2086
2087
|
let currentColorIndex = 0;
|
|
2087
2088
|
if (aggregatedData) {
|
|
@@ -2390,7 +2391,8 @@ export function transformVegaLiteToLineChartProps(spec, colorMap, isDarkTheme) {
|
|
|
2390
2391
|
// Extract color configuration
|
|
2391
2392
|
const { colorScheme, colorRange } = extractColorConfig(encoding);
|
|
2392
2393
|
// Group data by x value (name), then by color (series)
|
|
2393
|
-
|
|
2394
|
+
// Null-prototype objects so data-derived keys (e.g. "__proto__") cannot pollute Object.prototype.
|
|
2395
|
+
const groupedData = Object.create(null);
|
|
2394
2396
|
const colorIndex = new Map();
|
|
2395
2397
|
let currentColorIndex = 0;
|
|
2396
2398
|
dataValues.forEach((row)=>{
|
|
@@ -2403,7 +2405,7 @@ export function transformVegaLiteToLineChartProps(spec, colorMap, isDarkTheme) {
|
|
|
2403
2405
|
const xKey = String(xValue);
|
|
2404
2406
|
const legend = String(groupValue);
|
|
2405
2407
|
if (!groupedData[xKey]) {
|
|
2406
|
-
groupedData[xKey] =
|
|
2408
|
+
groupedData[xKey] = Object.create(null);
|
|
2407
2409
|
}
|
|
2408
2410
|
groupedData[xKey][legend] = yValue;
|
|
2409
2411
|
if (!colorIndex.has(legend)) {
|
|
@@ -2655,7 +2657,8 @@ export function transformVegaLiteToLineChartProps(spec, colorMap, isDarkTheme) {
|
|
|
2655
2657
|
});
|
|
2656
2658
|
}
|
|
2657
2659
|
// Group data by series (color encoding)
|
|
2658
|
-
|
|
2660
|
+
// Null-prototype object so data-derived keys (e.g. "__proto__") cannot pollute Object.prototype.
|
|
2661
|
+
const groupedData = Object.create(null);
|
|
2659
2662
|
dataValues.forEach((row)=>{
|
|
2660
2663
|
const seriesName = colorField && row[colorField] !== undefined ? String(row[colorField]) : 'default';
|
|
2661
2664
|
if (!groupedData[seriesName]) {
|