{"version":3,"file":"index.mjs","names":["ReChartsScatterChart","Tooltip"],"sources":["../../src/ScatterChart/index.tsx"],"sourcesContent":["'use client';\n\nimport { Flexbox } from '@lobehub/ui';\nimport { Skeleton } from '@lobehub/ui/base-ui';\nimport { css, cssVar, cx } from 'antd-style';\nimport { ComponentType, HTMLAttributes, MouseEvent, forwardRef, useMemo, useState } from 'react';\nimport {\n  CartesianGrid,\n  Label,\n  Legend,\n  ScatterChart as ReChartsScatterChart,\n  ResponsiveContainer,\n  Scatter,\n  Tooltip,\n  XAxis,\n  YAxis,\n  ZAxis,\n} from 'recharts';\nimport { AxisDomain } from 'recharts/types/util/types';\n\nimport { renderShape } from '@/ScatterChart/renderShape';\nimport ChartLegend from '@/common/ChartLegend';\nimport { CustomTooltipProps } from '@/common/CustomTooltipProps';\nimport CustomYAxisTick from '@/common/CustomYAxisTick';\nimport {\n  constructCategories,\n  constructCategoryColors,\n  deepEqual,\n  getYAxisDomain,\n} from '@/common/utils';\nimport { useThemeColorRange } from '@/hooks/useThemeColorRange';\nimport type { EventProps } from '@/types/charts';\nimport { IntervalType, ValueFormatter } from '@/types/charts';\nimport { defaultValueFormatter } from '@/utils';\nimport { getMaxLabelLength } from '@/utils/getMaxLabelLength';\n\nimport BaseAnimationTimingProps from '../common/BaseAnimationTimingProps';\nimport NoData, { type NoDataProps } from '../common/NoData';\nimport ScatterChartTooltip from './ScatterChartTooltip';\nimport { styles } from './styles';\n\nexport type ScatterChartValueFormatter = {\n  size?: ValueFormatter;\n  x?: ValueFormatter;\n  y?: ValueFormatter;\n};\n\nexport interface ScatterChartProps\n  extends BaseAnimationTimingProps, HTMLAttributes<HTMLDivElement> {\n  allowDecimals?: boolean;\n  autoMinXValue?: boolean;\n  autoMinYValue?: boolean;\n  category: string;\n  colors?: string[];\n  customCategories?: {\n    [key: string]: string;\n  };\n  customTooltip?: ComponentType<CustomTooltipProps>;\n  data: any[];\n  enableLegendSlider?: boolean;\n  intervalType?: IntervalType;\n  loading?: boolean;\n  maxXValue?: number;\n  maxYValue?: number;\n  minXValue?: number;\n  minYValue?: number;\n  noDataText?: NoDataProps['noDataText'];\n  onValueChange?: (value: EventProps) => void;\n  rotateLabelX?: {\n    angle: number;\n    verticalShift: number;\n    xAxisHeight: number;\n  };\n  showGridLines?: boolean;\n  showLegend?: boolean;\n  showOpacity?: boolean;\n  showTooltip?: boolean;\n  showXAxis?: boolean;\n  showYAxis?: boolean;\n  size?: string;\n  sizeRange?: number[];\n  startEndOnly?: boolean;\n  tickGap?: number;\n  valueFormatter?: ScatterChartValueFormatter;\n  x: string;\n  xAxisLabel?: string;\n  y: string;\n  yAxisAlign?: 'left' | 'right';\n  yAxisLabel?: string;\n  yAxisWidth?: number;\n}\n\nconst ScatterChart = forwardRef<HTMLDivElement, ScatterChartProps>((props, ref) => {\n  const themeColorRange = useThemeColorRange();\n  const {\n    data = [],\n    x,\n    y,\n    size,\n    category,\n    colors = themeColorRange,\n    showOpacity = false,\n    yAxisAlign = 'left',\n    sizeRange = [1, 1000],\n    valueFormatter = {\n      size: defaultValueFormatter,\n      x: defaultValueFormatter,\n      y: defaultValueFormatter,\n    },\n    startEndOnly = false,\n    showXAxis = true,\n    showYAxis = true,\n    yAxisWidth,\n    intervalType = 'equidistantPreserveStart',\n    animationDuration = 900,\n    showAnimation = false,\n    showTooltip = true,\n    showLegend = true,\n    loading,\n    showGridLines = true,\n    autoMinXValue = false,\n    minXValue,\n    maxXValue,\n    autoMinYValue = false,\n    minYValue,\n    maxYValue,\n    allowDecimals = true,\n    noDataText,\n    onValueChange,\n    customTooltip,\n    rotateLabelX,\n    className,\n    enableLegendSlider = false,\n    tickGap = 5,\n    xAxisLabel,\n    yAxisLabel,\n    width = '100%',\n    height = 280,\n    style,\n    customCategories,\n    ...rest\n  } = props;\n\n  const [legendHeight, setLegendHeight] = useState(60);\n  const [activeNode, setActiveNode] = useState<any | undefined>();\n  const [activeLegend, setActiveLegend] = useState<string | undefined>();\n  const calculatedYAxisWidth: number | string = useMemo(() => {\n    if (yAxisWidth) return yAxisWidth;\n    return getMaxLabelLength({\n      data,\n      index: y,\n      isScatterChart: true,\n      margin: 0,\n      valueFormatter: valueFormatter?.y,\n    });\n  }, [yAxisWidth, data, valueFormatter, y]);\n\n  if (loading || !data) return <Skeleton height={height} width={width} />;\n\n  const CustomTooltip = customTooltip;\n  const hasOnValueChange = !!onValueChange;\n\n  const onNodeClick = (data: any, index: number, event: MouseEvent) => {\n    event.stopPropagation();\n    if (!hasOnValueChange) return;\n    if (deepEqual(activeNode, data.node)) {\n      setActiveLegend(undefined);\n      setActiveNode(undefined);\n      onValueChange?.(null);\n    } else {\n      setActiveNode(data.node);\n      setActiveLegend(data.payload[category]);\n      onValueChange?.({\n        categoryClicked: data.payload[category],\n        eventType: 'bubble',\n        ...data.payload,\n      });\n    }\n  };\n\n  const onCategoryClick = (dataKey: string) => {\n    if (!hasOnValueChange) return;\n    if (dataKey === activeLegend && !activeNode) {\n      setActiveLegend(undefined);\n      onValueChange?.(null);\n    } else {\n      setActiveLegend(dataKey);\n      onValueChange?.({\n        categoryClicked: dataKey,\n        eventType: 'category',\n      });\n    }\n    setActiveNode(undefined);\n  };\n\n  const categories = constructCategories(data, category);\n  const categoryColors = constructCategoryColors(categories, colors);\n\n  //maybe rename getYAxisDomain to getAxisDomain\n  const xAxisDomain = getYAxisDomain(autoMinXValue, minXValue, maxXValue);\n  const yAxisDomain = getYAxisDomain(autoMinYValue, minYValue, maxYValue);\n\n  return (\n    <Flexbox\n      className={className}\n      height={height}\n      ref={ref}\n      style={{ position: 'relative', ...style }}\n      width={width}\n      {...rest}\n    >\n      <ResponsiveContainer>\n        {data?.length ? (\n          <ReChartsScatterChart\n            margin={{\n              bottom: xAxisLabel ? 20 : undefined,\n              left: 20,\n              right: 20,\n              top: 5,\n            }}\n            onClick={\n              hasOnValueChange && (activeLegend || activeNode)\n                ? () => {\n                    setActiveNode(undefined);\n                    setActiveLegend(undefined);\n                    onValueChange?.(null);\n                  }\n                : undefined\n            }\n          >\n            {showGridLines ? (\n              <CartesianGrid className={styles.gridLines} horizontal={true} vertical={true} />\n            ) : null}\n            {x ? (\n              <XAxis\n                allowDataOverflow={true}\n                angle={rotateLabelX?.angle}\n                axisLine={false}\n                className={styles.label}\n                dataKey={x}\n                domain={xAxisDomain as AxisDomain}\n                dy={rotateLabelX?.verticalShift}\n                fill=\"\"\n                hide={!showXAxis}\n                interval={startEndOnly ? 'preserveStartEnd' : intervalType}\n                minTickGap={tickGap}\n                name={x}\n                stroke=\"\"\n                tick={{ transform: 'translate(0, 6)' }}\n                tickFormatter={valueFormatter.x}\n                tickLine={false}\n                ticks={startEndOnly ? [data[0][x], data.at(-1)[x]] : undefined}\n                type=\"number\"\n              >\n                {xAxisLabel && (\n                  <Label\n                    className={cx(styles.strongLabel, styles.emphasis)}\n                    offset={-20}\n                    position=\"insideBottom\"\n                  >\n                    {xAxisLabel}\n                  </Label>\n                )}\n              </XAxis>\n            ) : null}\n            {y ? (\n              <YAxis\n                allowDataOverflow={true}\n                allowDecimals={allowDecimals}\n                axisLine={false}\n                className={styles.label}\n                dataKey={y}\n                domain={yAxisDomain as AxisDomain}\n                fill=\"\"\n                hide={!showYAxis}\n                name={y}\n                stroke=\"\"\n                tick={(props) => (\n                  <CustomYAxisTick\n                    {...props}\n                    align={yAxisAlign}\n                    formatter={valueFormatter.y}\n                    textAnchor={yAxisAlign === 'left' ? 'start' : 'end'}\n                    yAxisLabel={Boolean(yAxisLabel)}\n                  />\n                )}\n                tickFormatter={valueFormatter.y}\n                tickLine={false}\n                type=\"number\"\n                width={calculatedYAxisWidth}\n              >\n                {yAxisLabel && (\n                  <Label\n                    angle={-90}\n                    className={cx(styles.strongLabel, styles.emphasis)}\n                    offset={-15}\n                    position=\"insideLeft\"\n                    style={{ textAnchor: 'middle' }}\n                  >\n                    {yAxisLabel}\n                  </Label>\n                )}\n              </YAxis>\n            ) : null}\n            <Tooltip\n              content={\n                showTooltip\n                  ? ({ active, payload, label }) => {\n                      const color = category ? payload?.[0]?.payload?.[category] : label;\n                      return CustomTooltip ? (\n                        <CustomTooltip\n                          active={active}\n                          customCategories={customCategories}\n                          label={color}\n                          payload={payload?.map((payloadItem) => ({\n                            ...payloadItem,\n                            color: categoryColors.get(color) ?? cssVar.colorPrimary,\n                          }))}\n                          valueFormatter={valueFormatter}\n                        />\n                      ) : (\n                        <ScatterChartTooltip\n                          active={active}\n                          axis={{ size: size, x: x, y: y }}\n                          category={category}\n                          categoryColors={categoryColors}\n                          customCategories={customCategories}\n                          label={color}\n                          payload={payload}\n                          valueFormatter={valueFormatter}\n                        />\n                      );\n                    }\n                  : undefined\n              }\n              cursor={{ stroke: cssVar.colorTextSecondary, strokeWidth: 1 }}\n              isAnimationActive={false}\n              wrapperStyle={{ outline: 'none' }}\n            />\n            {size ? <ZAxis dataKey={size} name={size} range={sizeRange} type=\"number\" /> : null}\n            {categories.map((cat) => {\n              return (\n                <Scatter\n                  animationDuration={animationDuration}\n                  className={cx(\n                    css`\n                      fill: ${categoryColors.get(cat) ?? cssVar.colorPrimary};\n                    `,\n                    showOpacity &&\n                      css`\n                        stroke: ${categoryColors.get(cat) ?? cssVar.colorPrimary};\n                      `,\n                  )}\n                  data={category ? data.filter((d) => d[category] === cat) : data}\n                  fill={`url(#${categoryColors.get(cat)})`}\n                  fillOpacity={showOpacity ? 0.7 : 1}\n                  isAnimationActive={showAnimation}\n                  key={cat}\n                  name={cat}\n                  onClick={onNodeClick}\n                  shape={(props: any) => renderShape(props, activeNode, activeLegend)}\n                  style={{\n                    cursor: onValueChange ? 'pointer' : undefined,\n                  }}\n                />\n              );\n            })}\n            {showLegend ? (\n              <Legend\n                content={({ payload }) =>\n                  ChartLegend(\n                    { payload },\n                    categoryColors,\n                    setLegendHeight,\n                    activeLegend,\n                    hasOnValueChange\n                      ? (clickedLegendItem: string) => onCategoryClick(clickedLegendItem)\n                      : undefined,\n                    enableLegendSlider,\n                    customCategories,\n                  )\n                }\n                height={legendHeight}\n                verticalAlign=\"top\"\n              />\n            ) : undefined}\n          </ReChartsScatterChart>\n        ) : (\n          <NoData noDataText={noDataText} />\n        )}\n      </ResponsiveContainer>\n    </Flexbox>\n  );\n});\n\nScatterChart.displayName = 'ScatterChart';\n\nexport default ScatterChart;\n"],"mappings":"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"}