This commit is contained in:
Marshall Polaris 2022-09-28 20:55:23 -07:00
parent 5e3fe64683
commit c2a5ce6ba6
3 changed files with 26 additions and 32 deletions

View File

@ -8,6 +8,7 @@ import { FreeResponseContract, MultipleChoiceContract } from 'common/contract'
import { getOutcomeProbability } from 'common/calculate'
import { useIsMobile } from 'web/hooks/use-is-mobile'
import {
Legend,
MARGIN_X,
MARGIN_Y,
MAX_DATE,
@ -17,7 +18,6 @@ import {
formatDateInRange,
} from '../helpers'
import {
Legend,
MultiPoint,
MultiValueHistoryChart,
MultiValueHistoryTooltipProps,
@ -196,7 +196,6 @@ export const ChoiceContractChart = (props: {
yScale={yScale}
data={data}
colors={CATEGORY_COLORS}
labels={answers.map((answer) => answer.text)}
Tooltip={ChoiceTooltip}
pct
/>

View File

@ -23,7 +23,6 @@ import {
formatPct,
} from './helpers'
import { useEvent } from 'web/hooks/use-event'
import { Row } from 'web/components/layout/row'
export type MultiPoint<T = never> = { x: Date; y: number[]; datum?: T }
export type HistoryPoint<T = never> = { x: Date; y: number; datum?: T }
@ -36,28 +35,6 @@ const getTickValues = (min: number, max: number, n: number) => {
return [min, ...range(1, n - 1).map((i) => min + step * i), max]
}
type LegendItem = { color: string; label: string; value?: string }
export const Legend = (props: { className?: string; items: LegendItem[] }) => {
const { items, className } = props
return (
<ol className={className}>
{items.map((item) => (
<li key={item.label} className="flex flex-row justify-between">
<Row className="mr-2 items-center overflow-hidden">
<span
className="mr-2 h-4 w-4 shrink-0"
style={{ backgroundColor: item.color }}
></span>
<span className="overflow-hidden text-ellipsis">{item.label}</span>
</Row>
{item.value}
</li>
))}
</ol>
)
}
export const SingleValueDistributionChart = <T,>(props: {
data: DistributionPoint<T>[]
w: number
@ -158,14 +135,13 @@ export const MultiValueHistoryChart = <T,>(props: {
data: MultiPoint<T>[]
w: number
h: number
labels: readonly string[]
colors: readonly string[]
xScale: ScaleTime<number, number>
yScale: ScaleContinuousNumeric<number, number>
Tooltip?: TooltipContent<MultiValueHistoryTooltipProps<T>>
pct?: boolean
}) => {
const { colors, data, yScale, labels, w, h, Tooltip, pct } = props
const { colors, data, yScale, w, h, Tooltip, pct } = props
const [viewXScale, setViewXScale] = useState<ScaleTime<number, number>>()
const [mouseState, setMouseState] = useState<PositionValue<MultiPoint<T>>>()
@ -184,17 +160,16 @@ export const MultiValueHistoryChart = <T,>(props: {
const yAxis = pct
? axisLeft<number>(yScale).tickValues(pctTickValues).tickFormat(formatPct)
: axisLeft<number>(yScale)
return { xAxis, yAxis }
}, [w, h, pct, xScale, yScale])
const series = useMemo(() => {
const d3Stack = stack<MultiPoint<T>, number>()
.keys(range(0, labels.length))
.keys(range(0, Math.max(...data.map(({ y }) => y.length))))
.value(({ y }, o) => y[o])
.order(stackOrderReverse)
return d3Stack(data)
}, [data, labels.length])
}, [data])
const onSelect = useEvent((ev: D3BrushEvent<MultiPoint<T>>) => {
if (ev.selection) {

View File

@ -8,6 +8,7 @@ import dayjs from 'dayjs'
import clsx from 'clsx'
import { Contract } from 'common/contract'
import { Row } from 'web/components/layout/row'
export const MARGIN = { top: 20, right: 10, bottom: 20, left: 40 }
export const MARGIN_X = MARGIN.right + MARGIN.left
@ -181,8 +182,8 @@ export const SVGChart = <X, Y>(props: {
)
}
export type TooltipContent<P> = React.ComponentType<P>
export type TooltipPosition = { top: number; left: number }
export const TooltipContainer = (
props: TooltipPosition & { className?: string; children: React.ReactNode }
) => {
@ -200,7 +201,26 @@ export const TooltipContainer = (
)
}
export type TooltipContent<P> = React.ComponentType<P>
export type LegendItem = { color: string; label: string; value?: string }
export const Legend = (props: { className?: string; items: LegendItem[] }) => {
const { items, className } = props
return (
<ol className={className}>
{items.map((item) => (
<li key={item.label} className="flex flex-row justify-between">
<Row className="mr-2 items-center overflow-hidden">
<span
className="mr-2 h-4 w-4 shrink-0"
style={{ backgroundColor: item.color }}
></span>
<span className="overflow-hidden text-ellipsis">{item.label}</span>
</Row>
{item.value}
</li>
))}
</ol>
)
}
export const getDateRange = (contract: Contract) => {
const { createdTime, closeTime, resolutionTime } = contract