diff --git a/web/components/charts/generic-charts.tsx b/web/components/charts/generic-charts.tsx index 2d9bfc44..c4034a97 100644 --- a/web/components/charts/generic-charts.tsx +++ b/web/components/charts/generic-charts.tsx @@ -20,10 +20,12 @@ import { AreaWithTopStroke, Point, TooltipComponent, + computeColorStops, formatPct, } from './helpers' import { useEvent } from 'web/hooks/use-event' import { formatMoney } from 'common/util/format' +import { nanoid } from 'nanoid' export type MultiPoint = Point export type HistoryPoint = Point @@ -161,7 +163,7 @@ export const MultiValueHistoryChart =

(props: { const series = useMemo(() => { const d3Stack = stack() .keys(range(0, Math.max(...data.map(({ y }) => y.length)))) - .value(({ y }, o) => y[o]) + .value(({ y }, k) => y[k]) .order(stackOrderReverse) return d3Stack(data) }, [data]) @@ -214,7 +216,7 @@ export const SingleValueHistoryChart =

(props: { data: P[] w: number h: number - color: string + color: string | ((p: P) => string) margin: Margin xScale: ScaleTime yScale: ScaleContinuousNumeric @@ -269,6 +271,13 @@ export const SingleValueHistoryChart =

(props: { } }) + const gradientId = useMemo(() => nanoid(), []) + const stops = useMemo( + () => + typeof color !== 'string' ? computeColorStops(data, color, px) : null, + [color, data, px] + ) + return ( (props: { onMouseOver={onMouseOver} Tooltip={Tooltip} > + {stops && ( + + + {stops.map((s, i) => ( + + ))} + + + )} ( export const AreaPath = memo(AreaPathInternal) as typeof AreaPathInternal export const AreaWithTopStroke = (props: { - color: string data: P[] + color: string px: number | ((p: P) => number) py0: number | ((p: P) => number) py1: number | ((p: P) => number) curve: CurveFactory }) => { - const { color, data, px, py0, py1, curve } = props + const { data, color, px, py0, py1, curve } = props return ( ( + data: P[], + pc: (p: P) => string, + px: (p: P) => number +) => { + const segments: { x: number; color: string }[] = [] + let currOffset = 0 + let currColor = pc(data[0]) + for (const p of data) { + const c = pc(p) + if (c !== currColor) { + segments.push({ x: currOffset, color: currColor }) + currOffset = px(p) + currColor = c + } + } + segments.push({ x: currOffset, color: currColor }) + + const stops: { x: number; color: string }[] = [] + stops.push({ x: segments[0].x, color: segments[0].color }) + for (const s of segments.slice(1)) { + stops.push({ x: s.x, color: stops[stops.length - 1].color }) + stops.push({ x: s.x, color: s.color }) + } + return stops +} + export const getDateRange = (contract: Contract) => { const { createdTime, closeTime, resolutionTime } = contract const isClosed = !!closeTime && Date.now() > closeTime