import React from 'react' import { area } from 'd3-shape' import { buildCurveFn, CurveType } from '../lib/curve' import { combineGetters, createDataScale, scaleZero } from '../lib/scales' import { AnimationProps, CartesianScale, DataAccessor, DataGetter, NativeEventHandlers, SvgAttributesGetters, toAccessor, } from '../lib/types' import { useCartesianContext } from './internal' import { Elements } from './Elements' export type AreaAxesConfig = | DataAccessor | { base: DataGetter; to: DataAccessor } function sanitizeAxesConfig( config: AreaAxesConfig, scale: CartesianScale ): { base: DataAccessor; to: DataAccessor } { if (typeof config === 'function') { return { to: config, base: () => scaleZero(scale) } } const { base, to } = config return { to, base: toAccessor(base) } } export interface AreaProps extends AnimationProps, Pick, 'x' | 'y1' | 'y2'>, Omit, 'x' | 'y1' | 'y2'>, NativeEventHandlers { data: T[] 'x-data': DataAccessor 'y-data': AreaAxesConfig curve?: CurveType } export function Area({ data, 'x-data': dataX, 'y-data': _dataY, curve = 'line', x: _x, y1: _y1, y2: _y2, ...props }: AreaProps) { const { xScale, yScale } = useCartesianContext() const curveFn = buildCurveFn(curve) const dataY = sanitizeAxesConfig(_dataY, yScale) const x = combineGetters([createDataScale(dataX, xScale, 0), _x]) const y1 = combineGetters([createDataScale(dataY.base, yScale, 0), _y1]) const y2 = combineGetters([createDataScale(dataY.to, yScale, 0), _y2]) const d = (data: T[]) => { const points = data .map((d) => [x(d), y1(d), y2(d)]) .filter((d) => d.every((p) => !isNaN(p))) return ( area() .x((d) => d[0]) .y0((d) => d[1]) .y1((d) => d[2]) .curve(curveFn)(points) ?? '' ) } return }