Fiddle around with everything, WIP FR charts
This commit is contained in:
parent
9dc0d1696e
commit
b6471a425a
|
@ -1,238 +0,0 @@
|
||||||
import { DatumValue } from '@nivo/core'
|
|
||||||
import { ResponsiveLine } from '@nivo/line'
|
|
||||||
import dayjs from 'dayjs'
|
|
||||||
import { groupBy, sortBy, sumBy } from 'lodash'
|
|
||||||
import { memo } from 'react'
|
|
||||||
|
|
||||||
import { Bet } from 'common/bet'
|
|
||||||
import { FreeResponseContract, MultipleChoiceContract } from 'common/contract'
|
|
||||||
import { getOutcomeProbability } from 'common/calculate'
|
|
||||||
import { useWindowSize } from 'web/hooks/use-window-size'
|
|
||||||
|
|
||||||
const NUM_LINES = 6
|
|
||||||
|
|
||||||
export const AnswersGraph = memo(function AnswersGraph(props: {
|
|
||||||
contract: FreeResponseContract | MultipleChoiceContract
|
|
||||||
bets: Bet[]
|
|
||||||
height?: number
|
|
||||||
}) {
|
|
||||||
const { contract, bets, height } = props
|
|
||||||
const { createdTime, resolutionTime, closeTime, answers } = contract
|
|
||||||
const now = Date.now()
|
|
||||||
|
|
||||||
const { probsByOutcome, sortedOutcomes } = computeProbsByOutcome(
|
|
||||||
bets,
|
|
||||||
contract
|
|
||||||
)
|
|
||||||
|
|
||||||
const isClosed = !!closeTime && now > closeTime
|
|
||||||
const latestTime = dayjs(
|
|
||||||
resolutionTime && isClosed
|
|
||||||
? Math.min(resolutionTime, closeTime)
|
|
||||||
: isClosed
|
|
||||||
? closeTime
|
|
||||||
: resolutionTime ?? now
|
|
||||||
)
|
|
||||||
|
|
||||||
const { width } = useWindowSize()
|
|
||||||
|
|
||||||
const isLargeWidth = !width || width > 800
|
|
||||||
const labelLength = isLargeWidth ? 50 : 20
|
|
||||||
|
|
||||||
// Add a fake datapoint so the line continues to the right
|
|
||||||
const endTime = latestTime.valueOf()
|
|
||||||
|
|
||||||
const times = sortBy([
|
|
||||||
createdTime,
|
|
||||||
...bets.map((bet) => bet.createdTime),
|
|
||||||
endTime,
|
|
||||||
])
|
|
||||||
const dateTimes = times.map((time) => new Date(time))
|
|
||||||
|
|
||||||
const data = sortedOutcomes.map((outcome) => {
|
|
||||||
const betProbs = probsByOutcome[outcome]
|
|
||||||
// Add extra point for contract start and end.
|
|
||||||
const probs = [0, ...betProbs, betProbs[betProbs.length - 1]]
|
|
||||||
|
|
||||||
const points = probs.map((prob, i) => ({
|
|
||||||
x: dateTimes[i],
|
|
||||||
y: Math.round(prob * 100),
|
|
||||||
}))
|
|
||||||
|
|
||||||
const answer =
|
|
||||||
answers?.find((answer) => answer.id === outcome)?.text ?? 'None'
|
|
||||||
const answerText =
|
|
||||||
answer.slice(0, labelLength) + (answer.length > labelLength ? '...' : '')
|
|
||||||
|
|
||||||
return { id: answerText, data: points }
|
|
||||||
})
|
|
||||||
|
|
||||||
data.reverse()
|
|
||||||
|
|
||||||
const yTickValues = [0, 25, 50, 75, 100]
|
|
||||||
|
|
||||||
const numXTickValues = isLargeWidth ? 5 : 2
|
|
||||||
const startDate = dayjs(contract.createdTime)
|
|
||||||
const endDate = startDate.add(1, 'hour').isAfter(latestTime)
|
|
||||||
? latestTime.add(1, 'hours')
|
|
||||||
: latestTime
|
|
||||||
const includeMinute = endDate.diff(startDate, 'hours') < 2
|
|
||||||
|
|
||||||
const multiYear = !startDate.isSame(latestTime, 'year')
|
|
||||||
const lessThanAWeek = startDate.add(1, 'week').isAfter(latestTime)
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
className="w-full"
|
|
||||||
style={{ height: height ?? (isLargeWidth ? 350 : 250) }}
|
|
||||||
>
|
|
||||||
<ResponsiveLine
|
|
||||||
data={data}
|
|
||||||
yScale={{ min: 0, max: 100, type: 'linear', stacked: true }}
|
|
||||||
yFormat={formatPercent}
|
|
||||||
gridYValues={yTickValues}
|
|
||||||
axisLeft={{
|
|
||||||
tickValues: yTickValues,
|
|
||||||
format: formatPercent,
|
|
||||||
}}
|
|
||||||
xScale={{
|
|
||||||
type: 'time',
|
|
||||||
min: startDate.toDate(),
|
|
||||||
max: endDate.toDate(),
|
|
||||||
}}
|
|
||||||
xFormat={(d) =>
|
|
||||||
formatTime(now, +d.valueOf(), multiYear, lessThanAWeek, lessThanAWeek)
|
|
||||||
}
|
|
||||||
axisBottom={{
|
|
||||||
tickValues: numXTickValues,
|
|
||||||
format: (time) =>
|
|
||||||
formatTime(now, +time, multiYear, lessThanAWeek, includeMinute),
|
|
||||||
}}
|
|
||||||
colors={[
|
|
||||||
'#fca5a5', // red-300
|
|
||||||
'#a5b4fc', // indigo-300
|
|
||||||
'#86efac', // green-300
|
|
||||||
'#fef08a', // yellow-200
|
|
||||||
'#fdba74', // orange-300
|
|
||||||
'#c084fc', // purple-400
|
|
||||||
]}
|
|
||||||
pointSize={0}
|
|
||||||
curve="stepAfter"
|
|
||||||
enableSlices="x"
|
|
||||||
enableGridX={!!width && width >= 800}
|
|
||||||
enableArea
|
|
||||||
areaOpacity={1}
|
|
||||||
margin={{ top: 20, right: 20, bottom: 25, left: 40 }}
|
|
||||||
legends={[
|
|
||||||
{
|
|
||||||
anchor: 'top-left',
|
|
||||||
direction: 'column',
|
|
||||||
justify: false,
|
|
||||||
translateX: isLargeWidth ? 5 : 2,
|
|
||||||
translateY: 0,
|
|
||||||
itemsSpacing: 0,
|
|
||||||
itemTextColor: 'black',
|
|
||||||
itemDirection: 'left-to-right',
|
|
||||||
itemWidth: isLargeWidth ? 288 : 138,
|
|
||||||
itemHeight: 20,
|
|
||||||
itemBackground: 'white',
|
|
||||||
itemOpacity: 0.9,
|
|
||||||
symbolSize: 12,
|
|
||||||
effects: [
|
|
||||||
{
|
|
||||||
on: 'hover',
|
|
||||||
style: {
|
|
||||||
itemBackground: 'rgba(255, 255, 255, 1)',
|
|
||||||
itemOpacity: 1,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
function formatPercent(y: DatumValue) {
|
|
||||||
return `${Math.round(+y.toString())}%`
|
|
||||||
}
|
|
||||||
|
|
||||||
function formatTime(
|
|
||||||
now: number,
|
|
||||||
time: number,
|
|
||||||
includeYear: boolean,
|
|
||||||
includeHour: boolean,
|
|
||||||
includeMinute: boolean
|
|
||||||
) {
|
|
||||||
const d = dayjs(time)
|
|
||||||
if (d.add(1, 'minute').isAfter(now) && d.subtract(1, 'minute').isBefore(now))
|
|
||||||
return 'Now'
|
|
||||||
|
|
||||||
let format: string
|
|
||||||
if (d.isSame(now, 'day')) {
|
|
||||||
format = '[Today]'
|
|
||||||
} else if (d.add(1, 'day').isSame(now, 'day')) {
|
|
||||||
format = '[Yesterday]'
|
|
||||||
} else {
|
|
||||||
format = 'MMM D'
|
|
||||||
}
|
|
||||||
|
|
||||||
if (includeMinute) {
|
|
||||||
format += ', h:mma'
|
|
||||||
} else if (includeHour) {
|
|
||||||
format += ', ha'
|
|
||||||
} else if (includeYear) {
|
|
||||||
format += ', YYYY'
|
|
||||||
}
|
|
||||||
|
|
||||||
return d.format(format)
|
|
||||||
}
|
|
||||||
|
|
||||||
const computeProbsByOutcome = (
|
|
||||||
bets: Bet[],
|
|
||||||
contract: FreeResponseContract | MultipleChoiceContract
|
|
||||||
) => {
|
|
||||||
const { totalBets, outcomeType } = contract
|
|
||||||
|
|
||||||
const betsByOutcome = groupBy(bets, (bet) => bet.outcome)
|
|
||||||
const outcomes = Object.keys(betsByOutcome).filter((outcome) => {
|
|
||||||
const maxProb = Math.max(
|
|
||||||
...betsByOutcome[outcome].map((bet) => bet.probAfter)
|
|
||||||
)
|
|
||||||
return (
|
|
||||||
(outcome !== '0' || outcomeType === 'MULTIPLE_CHOICE') &&
|
|
||||||
maxProb > 0.02 &&
|
|
||||||
totalBets[outcome] > 0.000000001
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
const trackedOutcomes = sortBy(
|
|
||||||
outcomes,
|
|
||||||
(outcome) => -1 * getOutcomeProbability(contract, outcome)
|
|
||||||
).slice(0, NUM_LINES)
|
|
||||||
|
|
||||||
const probsByOutcome = Object.fromEntries(
|
|
||||||
trackedOutcomes.map((outcome) => [outcome, [] as number[]])
|
|
||||||
)
|
|
||||||
const sharesByOutcome = Object.fromEntries(
|
|
||||||
Object.keys(betsByOutcome).map((outcome) => [outcome, 0])
|
|
||||||
)
|
|
||||||
|
|
||||||
for (const bet of bets) {
|
|
||||||
const { outcome, shares } = bet
|
|
||||||
sharesByOutcome[outcome] += shares
|
|
||||||
|
|
||||||
const sharesSquared = sumBy(
|
|
||||||
Object.values(sharesByOutcome).map((shares) => shares ** 2)
|
|
||||||
)
|
|
||||||
|
|
||||||
for (const outcome of trackedOutcomes) {
|
|
||||||
probsByOutcome[outcome].push(
|
|
||||||
sharesByOutcome[outcome] ** 2 / sharesSquared
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return { probsByOutcome, sortedOutcomes: trackedOutcomes }
|
|
||||||
}
|
|
|
@ -2,7 +2,11 @@ import React from 'react'
|
||||||
|
|
||||||
import { tradingAllowed } from 'web/lib/firebase/contracts'
|
import { tradingAllowed } from 'web/lib/firebase/contracts'
|
||||||
import { Col } from '../layout/col'
|
import { Col } from '../layout/col'
|
||||||
import { ContractProbGraph } from './contract-prob-graph'
|
import {
|
||||||
|
BinaryContractChart,
|
||||||
|
PseudoNumericContractChart,
|
||||||
|
ChoiceContractChart,
|
||||||
|
} from './contract-prob-graph'
|
||||||
import { useUser } from 'web/hooks/use-user'
|
import { useUser } from 'web/hooks/use-user'
|
||||||
import { Row } from '../layout/row'
|
import { Row } from '../layout/row'
|
||||||
import { Linkify } from '../linkify'
|
import { Linkify } from '../linkify'
|
||||||
|
@ -14,7 +18,6 @@ import {
|
||||||
} from './contract-card'
|
} from './contract-card'
|
||||||
import { Bet } from 'common/bet'
|
import { Bet } from 'common/bet'
|
||||||
import BetButton, { BinaryMobileBetting } from '../bet-button'
|
import BetButton, { BinaryMobileBetting } from '../bet-button'
|
||||||
import { AnswersGraph } from '../answers/answers-graph'
|
|
||||||
import {
|
import {
|
||||||
Contract,
|
Contract,
|
||||||
CPMMContract,
|
CPMMContract,
|
||||||
|
@ -83,7 +86,7 @@ const BinaryOverview = (props: { contract: BinaryContract; bets: Bet[] }) => {
|
||||||
/>
|
/>
|
||||||
</Row>
|
</Row>
|
||||||
</Col>
|
</Col>
|
||||||
<ContractProbGraph contract={contract} bets={[...bets].reverse()} />
|
<BinaryContractChart contract={contract} bets={bets} />
|
||||||
<Row className="items-center justify-between gap-4 xl:hidden">
|
<Row className="items-center justify-between gap-4 xl:hidden">
|
||||||
{tradingAllowed(contract) && (
|
{tradingAllowed(contract) && (
|
||||||
<BinaryMobileBetting contract={contract} />
|
<BinaryMobileBetting contract={contract} />
|
||||||
|
@ -109,7 +112,7 @@ const ChoiceOverview = (props: {
|
||||||
)}
|
)}
|
||||||
</Col>
|
</Col>
|
||||||
<Col className={'mb-1 gap-y-2'}>
|
<Col className={'mb-1 gap-y-2'}>
|
||||||
<AnswersGraph contract={contract} bets={[...bets].reverse()} />
|
<ChoiceContractChart contract={contract} bets={bets} />
|
||||||
</Col>
|
</Col>
|
||||||
</Col>
|
</Col>
|
||||||
)
|
)
|
||||||
|
@ -136,7 +139,7 @@ const PseudoNumericOverview = (props: {
|
||||||
{tradingAllowed(contract) && <BetWidget contract={contract} />}
|
{tradingAllowed(contract) && <BetWidget contract={contract} />}
|
||||||
</Row>
|
</Row>
|
||||||
</Col>
|
</Col>
|
||||||
<ContractProbGraph contract={contract} bets={[...bets].reverse()} />
|
<PseudoNumericContractChart contract={contract} bets={bets} />
|
||||||
</Col>
|
</Col>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,203 +1,521 @@
|
||||||
import { DatumValue } from '@nivo/core'
|
|
||||||
import { ResponsiveLine, SliceTooltipProps } from '@nivo/line'
|
|
||||||
import { BasicTooltip } from '@nivo/tooltip'
|
|
||||||
import dayjs from 'dayjs'
|
import dayjs from 'dayjs'
|
||||||
import { memo } from 'react'
|
import { memo, useEffect, useMemo, useRef, useState } from 'react'
|
||||||
import { Bet } from 'common/bet'
|
import { Bet } from 'common/bet'
|
||||||
import { getInitialProbability } from 'common/calculate'
|
import {
|
||||||
import { BinaryContract, PseudoNumericContract } from 'common/contract'
|
getInitialProbability,
|
||||||
import { useWindowSize } from 'web/hooks/use-window-size'
|
getOutcomeProbability,
|
||||||
|
getProbability,
|
||||||
|
} from 'common/calculate'
|
||||||
|
import {
|
||||||
|
Contract,
|
||||||
|
BinaryContract,
|
||||||
|
PseudoNumericContract,
|
||||||
|
FreeResponseContract,
|
||||||
|
MultipleChoiceContract,
|
||||||
|
} from 'common/contract'
|
||||||
|
import { useIsMobile } from 'web/hooks/use-is-mobile'
|
||||||
import { formatLargeNumber } from 'common/util/format'
|
import { formatLargeNumber } from 'common/util/format'
|
||||||
|
import { range, sortBy, groupBy, sumBy } from 'lodash'
|
||||||
|
import { useEvent } from 'web/hooks/use-event'
|
||||||
|
|
||||||
export const ContractProbGraph = memo(function ContractProbGraph(props: {
|
import * as d3 from 'd3'
|
||||||
contract: BinaryContract | PseudoNumericContract
|
|
||||||
bets: Bet[]
|
|
||||||
height?: number
|
|
||||||
}) {
|
|
||||||
const { contract, height } = props
|
|
||||||
const { resolutionTime, closeTime, outcomeType } = contract
|
|
||||||
const now = Date.now()
|
|
||||||
const isBinary = outcomeType === 'BINARY'
|
|
||||||
const isLogScale = outcomeType === 'PSEUDO_NUMERIC' && contract.isLogScale
|
|
||||||
|
|
||||||
const bets = props.bets.filter((bet) => !bet.isAnte && !bet.isRedemption)
|
const MARGIN = { top: 20, right: 10, bottom: 20, left: 40 }
|
||||||
|
const MARGIN_X = MARGIN.right + MARGIN.left
|
||||||
|
const MARGIN_Y = MARGIN.top + MARGIN.bottom
|
||||||
|
|
||||||
const startProb = getInitialProbability(contract)
|
type MultiPoint = readonly [Date, number[]]
|
||||||
|
type Point = readonly [Date, number]
|
||||||
|
|
||||||
const times = [contract.createdTime, ...bets.map((bet) => bet.createdTime)]
|
const useElementWidth = <T extends Element>(ref: React.RefObject<T>) => {
|
||||||
|
const [width, setWidth] = useState<number>()
|
||||||
const f: (p: number) => number = isBinary
|
useEffect(() => {
|
||||||
? (p) => p
|
const handleResize = () => {
|
||||||
: isLogScale
|
setWidth(ref.current?.clientWidth)
|
||||||
? (p) => p * Math.log10(contract.max - contract.min + 1)
|
|
||||||
: (p) => p * (contract.max - contract.min) + contract.min
|
|
||||||
|
|
||||||
const probs = [startProb, ...bets.map((bet) => bet.probAfter)].map(f)
|
|
||||||
|
|
||||||
const isClosed = !!closeTime && now > closeTime
|
|
||||||
const latestTime = dayjs(
|
|
||||||
resolutionTime && isClosed
|
|
||||||
? Math.min(resolutionTime, closeTime)
|
|
||||||
: isClosed
|
|
||||||
? closeTime
|
|
||||||
: resolutionTime ?? now
|
|
||||||
)
|
|
||||||
|
|
||||||
// Add a fake datapoint so the line continues to the right
|
|
||||||
times.push(latestTime.valueOf())
|
|
||||||
probs.push(probs[probs.length - 1])
|
|
||||||
|
|
||||||
const { width } = useWindowSize()
|
|
||||||
|
|
||||||
const quartiles = !width || width < 800 ? [0, 50, 100] : [0, 25, 50, 75, 100]
|
|
||||||
|
|
||||||
const yTickValues = isBinary
|
|
||||||
? quartiles
|
|
||||||
: quartiles.map((x) => x / 100).map(f)
|
|
||||||
|
|
||||||
const numXTickValues = !width || width < 800 ? 2 : 5
|
|
||||||
const startDate = dayjs(times[0])
|
|
||||||
const endDate = startDate.add(1, 'hour').isAfter(latestTime)
|
|
||||||
? latestTime.add(1, 'hours')
|
|
||||||
: latestTime
|
|
||||||
const includeMinute = endDate.diff(startDate, 'hours') < 2
|
|
||||||
|
|
||||||
// Minimum number of points for the graph to have. For smooth tooltip movement
|
|
||||||
// If we aren't actually loading any data yet, skip adding extra points to let page load faster
|
|
||||||
// This fn runs again once DOM is finished loading
|
|
||||||
const totalPoints = width && bets.length ? (width > 800 ? 300 : 50) : 1
|
|
||||||
|
|
||||||
const timeStep: number = latestTime.diff(startDate, 'ms') / totalPoints
|
|
||||||
|
|
||||||
const points: { x: Date; y: number }[] = []
|
|
||||||
const s = isBinary ? 100 : 1
|
|
||||||
|
|
||||||
for (let i = 0; i < times.length - 1; i++) {
|
|
||||||
const p = probs[i]
|
|
||||||
const d0 = times[i]
|
|
||||||
const d1 = times[i + 1]
|
|
||||||
const msDiff = d1 - d0
|
|
||||||
const numPoints = Math.floor(msDiff / timeStep)
|
|
||||||
points.push({ x: new Date(times[i]), y: s * p })
|
|
||||||
if (numPoints > 1) {
|
|
||||||
const thisTimeStep: number = msDiff / numPoints
|
|
||||||
for (let n = 1; n < numPoints; n++) {
|
|
||||||
points.push({ x: new Date(d0 + thisTimeStep * n), y: s * p })
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
handleResize()
|
||||||
|
window.addEventListener('resize', handleResize)
|
||||||
const data = [
|
return () => {
|
||||||
{ id: 'Yes', data: points, color: isBinary ? '#11b981' : '#5fa5f9' },
|
window.removeEventListener('resize', handleResize)
|
||||||
]
|
}
|
||||||
|
}, [ref])
|
||||||
const multiYear = !startDate.isSame(latestTime, 'year')
|
return width
|
||||||
const lessThanAWeek = startDate.add(8, 'day').isAfter(latestTime)
|
|
||||||
|
|
||||||
const formatter = isBinary
|
|
||||||
? formatPercent
|
|
||||||
: isLogScale
|
|
||||||
? (x: DatumValue) =>
|
|
||||||
formatLargeNumber(10 ** +x.valueOf() + contract.min - 1)
|
|
||||||
: (x: DatumValue) => formatLargeNumber(+x.valueOf())
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
className="w-full overflow-visible"
|
|
||||||
style={{ height: height ?? (!width || width >= 800 ? 250 : 150) }}
|
|
||||||
>
|
|
||||||
<ResponsiveLine
|
|
||||||
data={data}
|
|
||||||
yScale={
|
|
||||||
isBinary
|
|
||||||
? { min: 0, max: 100, type: 'linear' }
|
|
||||||
: isLogScale
|
|
||||||
? {
|
|
||||||
min: 0,
|
|
||||||
max: Math.log10(contract.max - contract.min + 1),
|
|
||||||
type: 'linear',
|
|
||||||
}
|
|
||||||
: { min: contract.min, max: contract.max, type: 'linear' }
|
|
||||||
}
|
|
||||||
yFormat={formatter}
|
|
||||||
gridYValues={yTickValues}
|
|
||||||
axisLeft={{
|
|
||||||
tickValues: yTickValues,
|
|
||||||
format: formatter,
|
|
||||||
}}
|
|
||||||
xScale={{
|
|
||||||
type: 'time',
|
|
||||||
min: startDate.toDate(),
|
|
||||||
max: endDate.toDate(),
|
|
||||||
}}
|
|
||||||
xFormat={(d) =>
|
|
||||||
formatTime(now, +d.valueOf(), multiYear, lessThanAWeek, lessThanAWeek)
|
|
||||||
}
|
|
||||||
axisBottom={{
|
|
||||||
tickValues: numXTickValues,
|
|
||||||
format: (time) =>
|
|
||||||
formatTime(now, +time, multiYear, lessThanAWeek, includeMinute),
|
|
||||||
}}
|
|
||||||
colors={{ datum: 'color' }}
|
|
||||||
curve="stepAfter"
|
|
||||||
enablePoints={false}
|
|
||||||
pointBorderWidth={1}
|
|
||||||
pointBorderColor="#fff"
|
|
||||||
enableSlices="x"
|
|
||||||
enableGridX={false}
|
|
||||||
enableArea
|
|
||||||
areaBaselineValue={isBinary || isLogScale ? 0 : contract.min}
|
|
||||||
margin={{ top: 20, right: 20, bottom: 25, left: 40 }}
|
|
||||||
animate={false}
|
|
||||||
sliceTooltip={SliceTooltip}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
const SliceTooltip = ({ slice }: SliceTooltipProps) => {
|
|
||||||
return (
|
|
||||||
<BasicTooltip
|
|
||||||
id={slice.points.map((point) => [
|
|
||||||
<span key="date">
|
|
||||||
<strong>{point.data[`yFormatted`]}</strong> {point.data['xFormatted']}
|
|
||||||
</span>,
|
|
||||||
])}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function formatPercent(y: DatumValue) {
|
const formatDate = (
|
||||||
return `${Math.round(+y.toString())}%`
|
date: Date,
|
||||||
}
|
opts: { includeYear: boolean; includeHour: boolean; includeMinute: boolean }
|
||||||
|
) => {
|
||||||
function formatTime(
|
const { includeYear, includeHour, includeMinute } = opts
|
||||||
now: number,
|
const d = dayjs(date)
|
||||||
time: number,
|
const now = Date.now()
|
||||||
includeYear: boolean,
|
|
||||||
includeHour: boolean,
|
|
||||||
includeMinute: boolean
|
|
||||||
) {
|
|
||||||
const d = dayjs(time)
|
|
||||||
if (d.add(1, 'minute').isAfter(now) && d.subtract(1, 'minute').isBefore(now))
|
if (d.add(1, 'minute').isAfter(now) && d.subtract(1, 'minute').isBefore(now))
|
||||||
return 'Now'
|
return 'Now'
|
||||||
|
|
||||||
let format: string
|
|
||||||
if (d.isSame(now, 'day')) {
|
if (d.isSame(now, 'day')) {
|
||||||
format = '[Today]'
|
return '[Today]'
|
||||||
} else if (d.add(1, 'day').isSame(now, 'day')) {
|
} else if (d.add(1, 'day').isSame(now, 'day')) {
|
||||||
format = '[Yesterday]'
|
return '[Yesterday]'
|
||||||
} else {
|
} else {
|
||||||
format = 'MMM D'
|
let format = 'MMM D'
|
||||||
|
if (includeMinute) {
|
||||||
|
format += ', h:mma'
|
||||||
|
} else if (includeHour) {
|
||||||
|
format += ', ha'
|
||||||
|
} else if (includeYear) {
|
||||||
|
format += ', YYYY'
|
||||||
|
}
|
||||||
|
return d.format(format)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (includeMinute) {
|
|
||||||
format += ', h:mma'
|
const getDateRange = (contract: Contract) => {
|
||||||
} else if (includeHour) {
|
const { createdTime, closeTime, resolutionTime } = contract
|
||||||
format += ', ha'
|
const now = Date.now()
|
||||||
} else if (includeYear) {
|
const isClosed = !!closeTime && now > closeTime
|
||||||
format += ', YYYY'
|
const endDate = resolutionTime ?? (isClosed ? closeTime : now)
|
||||||
}
|
// the graph should be minimum an hour wide
|
||||||
|
const adjustedEndDate = dayjs(createdTime).add(1, 'hour').isAfter(endDate)
|
||||||
return d.format(format)
|
? dayjs(endDate).add(1, 'hours')
|
||||||
|
: dayjs(endDate)
|
||||||
|
return [new Date(createdTime), adjustedEndDate.toDate()] as const
|
||||||
|
}
|
||||||
|
|
||||||
|
const getTickValues = (min: number, max: number, n: number) => {
|
||||||
|
const step = (max - min) / (n - 1)
|
||||||
|
return [min, ...range(1, n - 1).map((i) => min + step * i), max]
|
||||||
|
}
|
||||||
|
|
||||||
|
const getMultiChartData = (
|
||||||
|
contract: FreeResponseContract | MultipleChoiceContract,
|
||||||
|
bets: Bet[]
|
||||||
|
) => {
|
||||||
|
const { totalBets, outcomeType } = contract
|
||||||
|
|
||||||
|
const sortedBets = sortBy(bets, (b) => b.createdTime)
|
||||||
|
const betsByOutcome = groupBy(sortedBets, (bet) => bet.outcome)
|
||||||
|
const outcomes = Object.keys(betsByOutcome).filter((outcome) => {
|
||||||
|
const maxProb = Math.max(
|
||||||
|
...betsByOutcome[outcome].map((bet) => bet.probAfter)
|
||||||
|
)
|
||||||
|
return (
|
||||||
|
(outcome !== '0' || outcomeType === 'MULTIPLE_CHOICE') &&
|
||||||
|
maxProb > 0.02 &&
|
||||||
|
totalBets[outcome] > 0.000000001
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
const trackedOutcomes = sortBy(
|
||||||
|
outcomes,
|
||||||
|
(outcome) => -1 * getOutcomeProbability(contract, outcome)
|
||||||
|
)
|
||||||
|
.slice(0, 10)
|
||||||
|
.reverse()
|
||||||
|
|
||||||
|
const points: MultiPoint[] = []
|
||||||
|
|
||||||
|
const sharesByOutcome = Object.fromEntries(
|
||||||
|
Object.keys(betsByOutcome).map((outcome) => [outcome, 0])
|
||||||
|
)
|
||||||
|
|
||||||
|
for (const bet of sortedBets) {
|
||||||
|
const { outcome, shares } = bet
|
||||||
|
sharesByOutcome[outcome] += shares
|
||||||
|
|
||||||
|
const sharesSquared = sumBy(
|
||||||
|
Object.values(sharesByOutcome).map((shares) => shares ** 2)
|
||||||
|
)
|
||||||
|
points.push([
|
||||||
|
new Date(bet.createdTime),
|
||||||
|
trackedOutcomes.map(
|
||||||
|
(outcome) => sharesByOutcome[outcome] ** 2 / sharesSquared
|
||||||
|
),
|
||||||
|
])
|
||||||
|
}
|
||||||
|
|
||||||
|
const allPoints: MultiPoint[] = [
|
||||||
|
[new Date(contract.createdTime), trackedOutcomes.map((_) => 0)],
|
||||||
|
...points,
|
||||||
|
[
|
||||||
|
new Date(Date.now()),
|
||||||
|
trackedOutcomes.map((outcome) =>
|
||||||
|
getOutcomeProbability(contract, outcome)
|
||||||
|
),
|
||||||
|
],
|
||||||
|
]
|
||||||
|
return { points: allPoints, labels: trackedOutcomes }
|
||||||
|
}
|
||||||
|
|
||||||
|
const getChartData = (
|
||||||
|
contract: BinaryContract | PseudoNumericContract,
|
||||||
|
bets: Bet[]
|
||||||
|
): Point[] => {
|
||||||
|
const getY = (p: number) => {
|
||||||
|
if (contract.outcomeType === 'PSEUDO_NUMERIC') {
|
||||||
|
const { min, max } = contract
|
||||||
|
return p * (max - min) + min
|
||||||
|
} else {
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const sortedBets = sortBy(bets, (b) => b.createdTime)
|
||||||
|
const startProb = getInitialProbability(contract)
|
||||||
|
const endProb = getProbability(contract)
|
||||||
|
return [
|
||||||
|
[new Date(contract.createdTime), getY(startProb)] as const,
|
||||||
|
...sortedBets.map(
|
||||||
|
(b) => [new Date(b.createdTime), getY(b.probAfter)] as const
|
||||||
|
),
|
||||||
|
[new Date(Date.now()), getY(endProb)] as const,
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
const XAxis = (props: { w: number; h: number; scale: d3.AxisScale<Date> }) => {
|
||||||
|
const { h, scale } = props
|
||||||
|
const axisRef = useRef<SVGGElement>(null)
|
||||||
|
const [start, end] = scale.domain()
|
||||||
|
const fmt = getFormatterForDateRange(start, end)
|
||||||
|
useEffect(() => {
|
||||||
|
if (axisRef.current != null) {
|
||||||
|
const axis = d3.axisBottom(scale).tickFormat(fmt)
|
||||||
|
d3.select(axisRef.current)
|
||||||
|
.call(axis)
|
||||||
|
.call((g) => g.select('.domain').remove())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return <g ref={axisRef} transform={`translate(0, ${h})`} />
|
||||||
|
}
|
||||||
|
|
||||||
|
const YAxis = (props: {
|
||||||
|
w: number
|
||||||
|
h: number
|
||||||
|
scale: d3.AxisScale<number>
|
||||||
|
pct?: boolean
|
||||||
|
}) => {
|
||||||
|
const { w, h, scale, pct } = props
|
||||||
|
const axisRef = useRef<SVGGElement>(null)
|
||||||
|
const [min, max] = scale.domain()
|
||||||
|
const tickValues = getTickValues(min, max, h < 200 ? 3 : 5)
|
||||||
|
const fmt = (n: number) => (pct ? d3.format('.0%')(n) : formatLargeNumber(n))
|
||||||
|
useEffect(() => {
|
||||||
|
if (axisRef.current != null) {
|
||||||
|
const axis = d3.axisLeft(scale).tickValues(tickValues).tickFormat(fmt)
|
||||||
|
d3.select(axisRef.current)
|
||||||
|
.call(axis)
|
||||||
|
.call((g) => g.select('.domain').remove())
|
||||||
|
.call((g) =>
|
||||||
|
g.selectAll('.tick line').attr('x2', w).attr('stroke-opacity', 0.1)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return <g ref={axisRef} />
|
||||||
|
}
|
||||||
|
|
||||||
|
const LinePathInternal = <P,>(
|
||||||
|
props: {
|
||||||
|
data: P[]
|
||||||
|
px: number | ((p: P) => number)
|
||||||
|
py: number | ((p: P) => number)
|
||||||
|
} & React.SVGProps<SVGPathElement>
|
||||||
|
) => {
|
||||||
|
const { data, px, py, ...rest } = props
|
||||||
|
const line = d3.line<P>(px, py).curve(d3.curveStepAfter)
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||||
|
return <path {...rest} fill="none" d={line(data)!} />
|
||||||
|
}
|
||||||
|
const LinePath = memo(LinePathInternal) as typeof LinePathInternal
|
||||||
|
|
||||||
|
const AreaPathInternal = <P,>(
|
||||||
|
props: {
|
||||||
|
data: P[]
|
||||||
|
px: number | ((p: P) => number)
|
||||||
|
py0: number | ((p: P) => number)
|
||||||
|
py1: number | ((p: P) => number)
|
||||||
|
} & React.SVGProps<SVGPathElement>
|
||||||
|
) => {
|
||||||
|
const { data, px, py0, py1, ...rest } = props
|
||||||
|
const area = d3.area<P>(px, py0, py1).curve(d3.curveStepAfter)
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||||
|
return <path {...rest} d={area(data)!} />
|
||||||
|
}
|
||||||
|
const AreaPath = memo(AreaPathInternal) as typeof AreaPathInternal
|
||||||
|
|
||||||
|
const TwoAxisChart = (props: {
|
||||||
|
children: React.ReactNode
|
||||||
|
w: number
|
||||||
|
h: number
|
||||||
|
xScale: d3.ScaleTime<number, number>
|
||||||
|
yScale: d3.ScaleContinuousNumeric<number, number>
|
||||||
|
onMouseOver?: (ev: React.PointerEvent) => void
|
||||||
|
onMouseLeave?: (ev: React.PointerEvent) => void
|
||||||
|
pct?: boolean
|
||||||
|
}) => {
|
||||||
|
const { children, w, h, xScale, yScale, onMouseOver, onMouseLeave, pct } =
|
||||||
|
props
|
||||||
|
const innerW = w - MARGIN_X
|
||||||
|
const innerH = h - MARGIN_Y
|
||||||
|
return (
|
||||||
|
<svg className="w-full" width={w} height={h} viewBox={`0 0 ${w} ${h}`}>
|
||||||
|
<g transform={`translate(${MARGIN.left}, ${MARGIN.top})`}>
|
||||||
|
<XAxis scale={xScale} w={innerW} h={innerH} />
|
||||||
|
<YAxis scale={yScale} w={innerW} h={innerH} pct={pct} />
|
||||||
|
{children}
|
||||||
|
<rect
|
||||||
|
x="0"
|
||||||
|
y="0"
|
||||||
|
width={innerW}
|
||||||
|
height={innerH}
|
||||||
|
fill="none"
|
||||||
|
pointerEvents="all"
|
||||||
|
onPointerEnter={onMouseOver}
|
||||||
|
onPointerMove={onMouseOver}
|
||||||
|
onPointerLeave={onMouseLeave}
|
||||||
|
/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export const MultiValueHistoryChart = (props: {
|
||||||
|
data: MultiPoint[]
|
||||||
|
w: number
|
||||||
|
h: number
|
||||||
|
labels: readonly string[]
|
||||||
|
colors: readonly string[]
|
||||||
|
xScale: d3.ScaleTime<number, number>
|
||||||
|
yScale: d3.ScaleContinuousNumeric<number, number>
|
||||||
|
pct?: boolean
|
||||||
|
}) => {
|
||||||
|
const { colors, data, xScale, yScale, labels, w, h, pct } = props
|
||||||
|
const tooltipRef = useRef<HTMLDivElement>(null)
|
||||||
|
const stack = d3
|
||||||
|
.stack<MultiPoint, number>()
|
||||||
|
.keys(range(0, labels.length))
|
||||||
|
.value((p, o) => p[1][o])
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="relative">
|
||||||
|
<div
|
||||||
|
ref={tooltipRef}
|
||||||
|
style={{ display: 'none' }}
|
||||||
|
className="pointer-events-none absolute z-10 whitespace-pre rounded border-2 border-black bg-slate-600/75 p-2 text-white"
|
||||||
|
/>
|
||||||
|
<TwoAxisChart w={w} h={h} xScale={xScale} yScale={yScale} pct={pct}>
|
||||||
|
{stack(data).map((s, i) => (
|
||||||
|
<g key={s.key}>
|
||||||
|
<LinePath
|
||||||
|
data={s}
|
||||||
|
px={(p) => xScale(p.data[0])}
|
||||||
|
py={(p) => yScale(p[1])}
|
||||||
|
stroke={colors[i]}
|
||||||
|
/>
|
||||||
|
<AreaPath
|
||||||
|
data={s}
|
||||||
|
px={(p) => xScale(p.data[0])}
|
||||||
|
py0={(p) => yScale(p[0])}
|
||||||
|
py1={(p) => yScale(p[1])}
|
||||||
|
fill={colors[i]}
|
||||||
|
/>
|
||||||
|
</g>
|
||||||
|
))}
|
||||||
|
</TwoAxisChart>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export const SingleValueHistoryChart = (props: {
|
||||||
|
data: Point[]
|
||||||
|
w: number
|
||||||
|
h: number
|
||||||
|
color: string
|
||||||
|
xScale: d3.ScaleTime<number, number>
|
||||||
|
yScale: d3.ScaleContinuousNumeric<number, number>
|
||||||
|
pct?: boolean
|
||||||
|
}) => {
|
||||||
|
const { color, data, xScale, yScale, pct, w, h } = props
|
||||||
|
const tooltipRef = useRef<HTMLDivElement>(null)
|
||||||
|
const dates = useMemo(() => data.map(([d]) => d), [data])
|
||||||
|
const [startDate, endDate] = xScale.domain().map(dayjs)
|
||||||
|
const includeYear = !startDate.isSame(endDate, 'year')
|
||||||
|
const includeHour = startDate.add(8, 'day').isAfter(endDate)
|
||||||
|
const includeMinute = endDate.diff(startDate, 'hours') < 2
|
||||||
|
const formatX = (d: Date) =>
|
||||||
|
formatDate(d, { includeYear, includeHour, includeMinute })
|
||||||
|
const formatY = (n: number) =>
|
||||||
|
pct ? d3.format('.0%')(n) : formatLargeNumber(n)
|
||||||
|
|
||||||
|
const onMouseOver = useEvent((event: React.PointerEvent) => {
|
||||||
|
const tt = tooltipRef.current
|
||||||
|
if (tt != null) {
|
||||||
|
const [mouseX, mouseY] = d3.pointer(event)
|
||||||
|
const date = xScale.invert(mouseX)
|
||||||
|
const [_, prob] = data[d3.bisectCenter(dates, date)]
|
||||||
|
tt.innerHTML = `<strong>${formatY(prob)}</strong> ${formatX(date)}`
|
||||||
|
tt.style.display = 'block'
|
||||||
|
tt.style.top = mouseY - 10 + 'px'
|
||||||
|
tt.style.left = mouseX + 20 + 'px'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const onMouseLeave = useEvent(() => {
|
||||||
|
const tt = tooltipRef.current
|
||||||
|
if (tt != null) {
|
||||||
|
tt.style.display = 'none'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="relative">
|
||||||
|
<div
|
||||||
|
ref={tooltipRef}
|
||||||
|
style={{ display: 'none' }}
|
||||||
|
className="pointer-events-none absolute z-10 whitespace-pre rounded border-2 border-black bg-slate-600/75 p-2 text-white"
|
||||||
|
/>
|
||||||
|
<TwoAxisChart
|
||||||
|
w={w}
|
||||||
|
h={h}
|
||||||
|
xScale={xScale}
|
||||||
|
yScale={yScale}
|
||||||
|
pct={pct}
|
||||||
|
onMouseOver={onMouseOver}
|
||||||
|
onMouseLeave={onMouseLeave}
|
||||||
|
>
|
||||||
|
<LinePath
|
||||||
|
data={data}
|
||||||
|
px={(p) => xScale(p[0])}
|
||||||
|
py={(p) => yScale(p[1])}
|
||||||
|
stroke={color}
|
||||||
|
/>
|
||||||
|
<AreaPath
|
||||||
|
data={data}
|
||||||
|
px={(p) => xScale(p[0])}
|
||||||
|
py0={yScale(0)}
|
||||||
|
py1={(p) => yScale(p[1])}
|
||||||
|
fill={color}
|
||||||
|
fillOpacity={0.3}
|
||||||
|
/>
|
||||||
|
</TwoAxisChart>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export const ContractChart = (props: {
|
||||||
|
contract: Contract
|
||||||
|
bets: Bet[]
|
||||||
|
height?: number
|
||||||
|
}) => {
|
||||||
|
const { contract } = props
|
||||||
|
switch (contract.outcomeType) {
|
||||||
|
case 'BINARY':
|
||||||
|
return <BinaryContractChart {...{ ...props, contract }} />
|
||||||
|
case 'PSEUDO_NUMERIC':
|
||||||
|
return <PseudoNumericContractChart {...{ ...props, contract }} />
|
||||||
|
case 'FREE_RESPONSE':
|
||||||
|
case 'MULTIPLE_CHOICE':
|
||||||
|
return <ChoiceContractChart {...{ ...props, contract }} />
|
||||||
|
default:
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const getFormatterForDateRange = (start: Date, end: Date) => {
|
||||||
|
const opts = {
|
||||||
|
includeYear: !dayjs(start).isSame(end, 'year'),
|
||||||
|
includeHour: dayjs(start).add(8, 'day').isAfter(end),
|
||||||
|
includeMinute: dayjs(end).diff(start, 'hours') < 2,
|
||||||
|
}
|
||||||
|
return (d: Date) => formatDate(d, opts)
|
||||||
|
}
|
||||||
|
|
||||||
|
export const PseudoNumericContractChart = (props: {
|
||||||
|
contract: PseudoNumericContract
|
||||||
|
bets: Bet[]
|
||||||
|
height?: number
|
||||||
|
}) => {
|
||||||
|
const { contract, bets } = props
|
||||||
|
const data = useMemo(() => getChartData(contract, bets), [contract, bets])
|
||||||
|
const isMobile = useIsMobile(800)
|
||||||
|
const containerRef = useRef<HTMLDivElement>(null)
|
||||||
|
const width = useElementWidth(containerRef) ?? 0
|
||||||
|
const height = props.height ?? isMobile ? 150 : 250
|
||||||
|
const scaleType = contract.isLogScale ? d3.scaleLog : d3.scaleLinear
|
||||||
|
const xScale = d3.scaleTime(getDateRange(contract), [0, width - MARGIN_X])
|
||||||
|
const yScale = scaleType([contract.min, contract.max], [height - MARGIN_Y, 0])
|
||||||
|
return (
|
||||||
|
<div ref={containerRef}>
|
||||||
|
{width && (
|
||||||
|
<SingleValueHistoryChart
|
||||||
|
w={width}
|
||||||
|
h={height}
|
||||||
|
xScale={xScale}
|
||||||
|
yScale={yScale}
|
||||||
|
data={data}
|
||||||
|
color="#5fa5f9"
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export const BinaryContractChart = (props: {
|
||||||
|
contract: BinaryContract
|
||||||
|
bets: Bet[]
|
||||||
|
height?: number
|
||||||
|
}) => {
|
||||||
|
const { contract, bets } = props
|
||||||
|
const data = useMemo(() => getChartData(contract, bets), [contract, bets])
|
||||||
|
const isMobile = useIsMobile(800)
|
||||||
|
const containerRef = useRef<HTMLDivElement>(null)
|
||||||
|
const width = useElementWidth(containerRef) ?? 0
|
||||||
|
const height = props.height ?? isMobile ? 150 : 250
|
||||||
|
const xScale = d3.scaleTime(getDateRange(contract), [0, width - MARGIN_X])
|
||||||
|
const yScale = d3.scaleLinear([0, 1], [height - MARGIN_Y, 0])
|
||||||
|
return (
|
||||||
|
<div ref={containerRef}>
|
||||||
|
{width && (
|
||||||
|
<SingleValueHistoryChart
|
||||||
|
w={width}
|
||||||
|
h={height}
|
||||||
|
xScale={xScale}
|
||||||
|
yScale={yScale}
|
||||||
|
data={data}
|
||||||
|
color="#11b981"
|
||||||
|
pct
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export const ChoiceContractChart = (props: {
|
||||||
|
contract: FreeResponseContract | MultipleChoiceContract
|
||||||
|
bets: Bet[]
|
||||||
|
height?: number
|
||||||
|
}) => {
|
||||||
|
const { contract, bets } = props
|
||||||
|
const data = useMemo(
|
||||||
|
() => getMultiChartData(contract, bets),
|
||||||
|
[contract, bets]
|
||||||
|
)
|
||||||
|
const isMobile = useIsMobile(800)
|
||||||
|
const containerRef = useRef<HTMLDivElement>(null)
|
||||||
|
const width = useElementWidth(containerRef) ?? 0
|
||||||
|
const height = props.height ?? isMobile ? 150 : 250
|
||||||
|
const xScale = d3.scaleTime(getDateRange(contract), [0, width - MARGIN_X])
|
||||||
|
const yScale = d3.scaleLinear([0, 1], [height - MARGIN_Y, 0])
|
||||||
|
return (
|
||||||
|
<div ref={containerRef}>
|
||||||
|
{width && (
|
||||||
|
<MultiValueHistoryChart
|
||||||
|
w={width}
|
||||||
|
h={height}
|
||||||
|
xScale={xScale}
|
||||||
|
yScale={yScale}
|
||||||
|
data={data.points}
|
||||||
|
colors={d3.schemeCategory10}
|
||||||
|
labels={data.labels}
|
||||||
|
pct
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,6 +39,7 @@
|
||||||
"browser-image-compression": "2.0.0",
|
"browser-image-compression": "2.0.0",
|
||||||
"clsx": "1.1.1",
|
"clsx": "1.1.1",
|
||||||
"cors": "2.8.5",
|
"cors": "2.8.5",
|
||||||
|
"d3": "7.6.1",
|
||||||
"daisyui": "1.16.4",
|
"daisyui": "1.16.4",
|
||||||
"dayjs": "1.10.7",
|
"dayjs": "1.10.7",
|
||||||
"firebase": "9.9.3",
|
"firebase": "9.9.3",
|
||||||
|
@ -56,9 +57,9 @@
|
||||||
"react-expanding-textarea": "2.3.5",
|
"react-expanding-textarea": "2.3.5",
|
||||||
"react-hot-toast": "2.2.0",
|
"react-hot-toast": "2.2.0",
|
||||||
"react-instantsearch-hooks-web": "6.24.1",
|
"react-instantsearch-hooks-web": "6.24.1",
|
||||||
|
"react-masonry-css": "1.0.16",
|
||||||
"react-query": "3.39.0",
|
"react-query": "3.39.0",
|
||||||
"react-twitter-embed": "4.0.4",
|
"react-twitter-embed": "4.0.4",
|
||||||
"react-masonry-css": "1.0.16",
|
|
||||||
"string-similarity": "^4.0.4",
|
"string-similarity": "^4.0.4",
|
||||||
"tippy.js": "6.3.7"
|
"tippy.js": "6.3.7"
|
||||||
},
|
},
|
||||||
|
@ -66,6 +67,7 @@
|
||||||
"@tailwindcss/forms": "0.4.0",
|
"@tailwindcss/forms": "0.4.0",
|
||||||
"@tailwindcss/line-clamp": "^0.3.1",
|
"@tailwindcss/line-clamp": "^0.3.1",
|
||||||
"@tailwindcss/typography": "^0.5.1",
|
"@tailwindcss/typography": "^0.5.1",
|
||||||
|
"@types/d3": "7.4.0",
|
||||||
"@types/lodash": "4.14.178",
|
"@types/lodash": "4.14.178",
|
||||||
"@types/node": "16.11.11",
|
"@types/node": "16.11.11",
|
||||||
"@types/react": "17.0.43",
|
"@types/react": "17.0.43",
|
||||||
|
|
|
@ -2,7 +2,6 @@ import { Bet } from 'common/bet'
|
||||||
import { Contract } from 'common/contract'
|
import { Contract } from 'common/contract'
|
||||||
import { DOMAIN } from 'common/envs/constants'
|
import { DOMAIN } from 'common/envs/constants'
|
||||||
import { useState } from 'react'
|
import { useState } from 'react'
|
||||||
import { AnswersGraph } from 'web/components/answers/answers-graph'
|
|
||||||
import { BetInline } from 'web/components/bet-inline'
|
import { BetInline } from 'web/components/bet-inline'
|
||||||
import { Button } from 'web/components/button'
|
import { Button } from 'web/components/button'
|
||||||
import {
|
import {
|
||||||
|
@ -12,8 +11,7 @@ import {
|
||||||
PseudoNumericResolutionOrExpectation,
|
PseudoNumericResolutionOrExpectation,
|
||||||
} from 'web/components/contract/contract-card'
|
} from 'web/components/contract/contract-card'
|
||||||
import { MarketSubheader } from 'web/components/contract/contract-details'
|
import { MarketSubheader } from 'web/components/contract/contract-details'
|
||||||
import { ContractProbGraph } from 'web/components/contract/contract-prob-graph'
|
import { ContractChart } from 'web/components/contract/contract-prob-graph'
|
||||||
import { NumericGraph } from 'web/components/contract/numeric-graph'
|
|
||||||
import { Col } from 'web/components/layout/col'
|
import { Col } from 'web/components/layout/col'
|
||||||
import { Row } from 'web/components/layout/row'
|
import { Row } from 'web/components/layout/row'
|
||||||
import { Spacer } from 'web/components/layout/spacer'
|
import { Spacer } from 'web/components/layout/spacer'
|
||||||
|
@ -134,22 +132,7 @@ export function ContractEmbed(props: { contract: Contract; bets: Bet[] }) {
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<div className="mx-1 mb-2 min-h-0 flex-1" ref={setElem}>
|
<div className="mx-1 mb-2 min-h-0 flex-1" ref={setElem}>
|
||||||
{(isBinary || isPseudoNumeric) && (
|
<ContractChart contract={contract} bets={bets} height={graphHeight} />
|
||||||
<ContractProbGraph
|
|
||||||
contract={contract}
|
|
||||||
bets={[...bets].reverse()}
|
|
||||||
height={graphHeight}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{(outcomeType === 'FREE_RESPONSE' ||
|
|
||||||
outcomeType === 'MULTIPLE_CHOICE') && (
|
|
||||||
<AnswersGraph contract={contract} bets={bets} height={graphHeight} />
|
|
||||||
)}
|
|
||||||
|
|
||||||
{outcomeType === 'NUMERIC' && (
|
|
||||||
<NumericGraph contract={contract} height={graphHeight} />
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
</Col>
|
</Col>
|
||||||
)
|
)
|
||||||
|
|
500
yarn.lock
500
yarn.lock
|
@ -3250,6 +3250,216 @@
|
||||||
resolved "https://registry.yarnpkg.com/@types/cors/-/cors-2.8.12.tgz#6b2c510a7ad7039e98e7b8d3d6598f4359e5c080"
|
resolved "https://registry.yarnpkg.com/@types/cors/-/cors-2.8.12.tgz#6b2c510a7ad7039e98e7b8d3d6598f4359e5c080"
|
||||||
integrity sha512-vt+kDhq/M2ayberEtJcIN/hxXy1Pk+59g2FV/ZQceeaTyCtCucjL2Q7FXlFjtWn4n15KCr1NE2lNNFhp0lEThw==
|
integrity sha512-vt+kDhq/M2ayberEtJcIN/hxXy1Pk+59g2FV/ZQceeaTyCtCucjL2Q7FXlFjtWn4n15KCr1NE2lNNFhp0lEThw==
|
||||||
|
|
||||||
|
"@types/d3-array@*":
|
||||||
|
version "3.0.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/d3-array/-/d3-array-3.0.3.tgz#87d990bf504d14ad6b16766979d04e943c046dac"
|
||||||
|
integrity sha512-Reoy+pKnvsksN0lQUlcH6dOGjRZ/3WRwXR//m+/8lt1BXeI4xyaUZoqULNjyXXRuh0Mj4LNpkCvhUpQlY3X5xQ==
|
||||||
|
|
||||||
|
"@types/d3-axis@*":
|
||||||
|
version "3.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/d3-axis/-/d3-axis-3.0.1.tgz#6afc20744fa5cc0cbc3e2bd367b140a79ed3e7a8"
|
||||||
|
integrity sha512-zji/iIbdd49g9WN0aIsGcwcTBUkgLsCSwB+uH+LPVDAiKWENMtI3cJEWt+7/YYwelMoZmbBfzA3qCdrZ2XFNnw==
|
||||||
|
dependencies:
|
||||||
|
"@types/d3-selection" "*"
|
||||||
|
|
||||||
|
"@types/d3-brush@*":
|
||||||
|
version "3.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/d3-brush/-/d3-brush-3.0.1.tgz#ae5f17ce391935ca88b29000e60ee20452c6357c"
|
||||||
|
integrity sha512-B532DozsiTuQMHu2YChdZU0qsFJSio3Q6jmBYGYNp3gMDzBmuFFgPt9qKA4VYuLZMp4qc6eX7IUFUEsvHiXZAw==
|
||||||
|
dependencies:
|
||||||
|
"@types/d3-selection" "*"
|
||||||
|
|
||||||
|
"@types/d3-chord@*":
|
||||||
|
version "3.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/d3-chord/-/d3-chord-3.0.1.tgz#54c8856c19c8e4ab36a53f73ba737de4768ad248"
|
||||||
|
integrity sha512-eQfcxIHrg7V++W8Qxn6QkqBNBokyhdWSAS73AbkbMzvLQmVVBviknoz2SRS/ZJdIOmhcmmdCRE/NFOm28Z1AMw==
|
||||||
|
|
||||||
|
"@types/d3-color@*":
|
||||||
|
version "3.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/d3-color/-/d3-color-3.1.0.tgz#6594da178ded6c7c3842f3cc0ac84b156f12f2d4"
|
||||||
|
integrity sha512-HKuicPHJuvPgCD+np6Se9MQvS6OCbJmOjGvylzMJRlDwUXjKTTXs6Pwgk79O09Vj/ho3u1ofXnhFOaEWWPrlwA==
|
||||||
|
|
||||||
|
"@types/d3-contour@*":
|
||||||
|
version "3.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/d3-contour/-/d3-contour-3.0.1.tgz#9ff4e2fd2a3910de9c5097270a7da8a6ef240017"
|
||||||
|
integrity sha512-C3zfBrhHZvrpAAK3YXqLWVAGo87A4SvJ83Q/zVJ8rFWJdKejUnDYaWZPkA8K84kb2vDA/g90LTQAz7etXcgoQQ==
|
||||||
|
dependencies:
|
||||||
|
"@types/d3-array" "*"
|
||||||
|
"@types/geojson" "*"
|
||||||
|
|
||||||
|
"@types/d3-delaunay@*":
|
||||||
|
version "6.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/d3-delaunay/-/d3-delaunay-6.0.1.tgz#006b7bd838baec1511270cb900bf4fc377bbbf41"
|
||||||
|
integrity sha512-tLxQ2sfT0p6sxdG75c6f/ekqxjyYR0+LwPrsO1mbC9YDBzPJhs2HbJJRrn8Ez1DBoHRo2yx7YEATI+8V1nGMnQ==
|
||||||
|
|
||||||
|
"@types/d3-dispatch@*":
|
||||||
|
version "3.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/d3-dispatch/-/d3-dispatch-3.0.1.tgz#a1b18ae5fa055a6734cb3bd3cbc6260ef19676e3"
|
||||||
|
integrity sha512-NhxMn3bAkqhjoxabVJWKryhnZXXYYVQxaBnbANu0O94+O/nX9qSjrA1P1jbAQJxJf+VC72TxDX/YJcKue5bRqw==
|
||||||
|
|
||||||
|
"@types/d3-drag@*":
|
||||||
|
version "3.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/d3-drag/-/d3-drag-3.0.1.tgz#fb1e3d5cceeee4d913caa59dedf55c94cb66e80f"
|
||||||
|
integrity sha512-o1Va7bLwwk6h03+nSM8dpaGEYnoIG19P0lKqlic8Un36ymh9NSkNFX1yiXMKNMx8rJ0Kfnn2eovuFaL6Jvj0zA==
|
||||||
|
dependencies:
|
||||||
|
"@types/d3-selection" "*"
|
||||||
|
|
||||||
|
"@types/d3-dsv@*":
|
||||||
|
version "3.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/d3-dsv/-/d3-dsv-3.0.0.tgz#f3c61fb117bd493ec0e814856feb804a14cfc311"
|
||||||
|
integrity sha512-o0/7RlMl9p5n6FQDptuJVMxDf/7EDEv2SYEO/CwdG2tr1hTfUVi0Iavkk2ax+VpaQ/1jVhpnj5rq1nj8vwhn2A==
|
||||||
|
|
||||||
|
"@types/d3-ease@*":
|
||||||
|
version "3.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/d3-ease/-/d3-ease-3.0.0.tgz#c29926f8b596f9dadaeca062a32a45365681eae0"
|
||||||
|
integrity sha512-aMo4eaAOijJjA6uU+GIeW018dvy9+oH5Y2VPPzjjfxevvGQ/oRDs+tfYC9b50Q4BygRR8yE2QCLsrT0WtAVseA==
|
||||||
|
|
||||||
|
"@types/d3-fetch@*":
|
||||||
|
version "3.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/d3-fetch/-/d3-fetch-3.0.1.tgz#f9fa88b81aa2eea5814f11aec82ecfddbd0b8fe0"
|
||||||
|
integrity sha512-toZJNOwrOIqz7Oh6Q7l2zkaNfXkfR7mFSJvGvlD/Ciq/+SQ39d5gynHJZ/0fjt83ec3WL7+u3ssqIijQtBISsw==
|
||||||
|
dependencies:
|
||||||
|
"@types/d3-dsv" "*"
|
||||||
|
|
||||||
|
"@types/d3-force@*":
|
||||||
|
version "3.0.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/d3-force/-/d3-force-3.0.3.tgz#76cb20d04ae798afede1ea6e41750763ff5a9c82"
|
||||||
|
integrity sha512-z8GteGVfkWJMKsx6hwC3SiTSLspL98VNpmvLpEFJQpZPq6xpA1I8HNBDNSpukfK0Vb0l64zGFhzunLgEAcBWSA==
|
||||||
|
|
||||||
|
"@types/d3-format@*":
|
||||||
|
version "3.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/d3-format/-/d3-format-3.0.1.tgz#194f1317a499edd7e58766f96735bdc0216bb89d"
|
||||||
|
integrity sha512-5KY70ifCCzorkLuIkDe0Z9YTf9RR2CjBX1iaJG+rgM/cPP+sO+q9YdQ9WdhQcgPj1EQiJ2/0+yUkkziTG6Lubg==
|
||||||
|
|
||||||
|
"@types/d3-geo@*":
|
||||||
|
version "3.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/d3-geo/-/d3-geo-3.0.2.tgz#e7ec5f484c159b2c404c42d260e6d99d99f45d9a"
|
||||||
|
integrity sha512-DbqK7MLYA8LpyHQfv6Klz0426bQEf7bRTvhMy44sNGVyZoWn//B0c+Qbeg8Osi2Obdc9BLLXYAKpyWege2/7LQ==
|
||||||
|
dependencies:
|
||||||
|
"@types/geojson" "*"
|
||||||
|
|
||||||
|
"@types/d3-hierarchy@*":
|
||||||
|
version "3.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/d3-hierarchy/-/d3-hierarchy-3.1.0.tgz#4561bb7ace038f247e108295ef77b6a82193ac25"
|
||||||
|
integrity sha512-g+sey7qrCa3UbsQlMZZBOHROkFqx7KZKvUpRzI/tAp/8erZWpYq7FgNKvYwebi2LaEiVs1klhUfd3WCThxmmWQ==
|
||||||
|
|
||||||
|
"@types/d3-interpolate@*":
|
||||||
|
version "3.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/d3-interpolate/-/d3-interpolate-3.0.1.tgz#e7d17fa4a5830ad56fe22ce3b4fac8541a9572dc"
|
||||||
|
integrity sha512-jx5leotSeac3jr0RePOH1KdR9rISG91QIE4Q2PYTu4OymLTZfA3SrnURSLzKH48HmXVUru50b8nje4E79oQSQw==
|
||||||
|
dependencies:
|
||||||
|
"@types/d3-color" "*"
|
||||||
|
|
||||||
|
"@types/d3-path@*":
|
||||||
|
version "3.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/d3-path/-/d3-path-3.0.0.tgz#939e3a784ae4f80b1fde8098b91af1776ff1312b"
|
||||||
|
integrity sha512-0g/A+mZXgFkQxN3HniRDbXMN79K3CdTpLsevj+PXiTcb2hVyvkZUBg37StmgCQkaD84cUJ4uaDAWq7UJOQy2Tg==
|
||||||
|
|
||||||
|
"@types/d3-polygon@*":
|
||||||
|
version "3.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/d3-polygon/-/d3-polygon-3.0.0.tgz#5200a3fa793d7736fa104285fa19b0dbc2424b93"
|
||||||
|
integrity sha512-D49z4DyzTKXM0sGKVqiTDTYr+DHg/uxsiWDAkNrwXYuiZVd9o9wXZIo+YsHkifOiyBkmSWlEngHCQme54/hnHw==
|
||||||
|
|
||||||
|
"@types/d3-quadtree@*":
|
||||||
|
version "3.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/d3-quadtree/-/d3-quadtree-3.0.2.tgz#433112a178eb7df123aab2ce11c67f51cafe8ff5"
|
||||||
|
integrity sha512-QNcK8Jguvc8lU+4OfeNx+qnVy7c0VrDJ+CCVFS9srBo2GL9Y18CnIxBdTF3v38flrGy5s1YggcoAiu6s4fLQIw==
|
||||||
|
|
||||||
|
"@types/d3-random@*":
|
||||||
|
version "3.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/d3-random/-/d3-random-3.0.1.tgz#5c8d42b36cd4c80b92e5626a252f994ca6bfc953"
|
||||||
|
integrity sha512-IIE6YTekGczpLYo/HehAy3JGF1ty7+usI97LqraNa8IiDur+L44d0VOjAvFQWJVdZOJHukUJw+ZdZBlgeUsHOQ==
|
||||||
|
|
||||||
|
"@types/d3-scale-chromatic@*":
|
||||||
|
version "3.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/d3-scale-chromatic/-/d3-scale-chromatic-3.0.0.tgz#103124777e8cdec85b20b51fd3397c682ee1e954"
|
||||||
|
integrity sha512-dsoJGEIShosKVRBZB0Vo3C8nqSDqVGujJU6tPznsBJxNJNwMF8utmS83nvCBKQYPpjCzaaHcrf66iTRpZosLPw==
|
||||||
|
|
||||||
|
"@types/d3-scale@*":
|
||||||
|
version "4.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/d3-scale/-/d3-scale-4.0.2.tgz#41be241126af4630524ead9cb1008ab2f0f26e69"
|
||||||
|
integrity sha512-Yk4htunhPAwN0XGlIwArRomOjdoBFXC3+kCxK2Ubg7I9shQlVSJy/pG/Ht5ASN+gdMIalpk8TJ5xV74jFsetLA==
|
||||||
|
dependencies:
|
||||||
|
"@types/d3-time" "*"
|
||||||
|
|
||||||
|
"@types/d3-selection@*":
|
||||||
|
version "3.0.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/d3-selection/-/d3-selection-3.0.3.tgz#57be7da68e7d9c9b29efefd8ea5a9ef1171e42ba"
|
||||||
|
integrity sha512-Mw5cf6nlW1MlefpD9zrshZ+DAWL4IQ5LnWfRheW6xwsdaWOb6IRRu2H7XPAQcyXEx1D7XQWgdoKR83ui1/HlEA==
|
||||||
|
|
||||||
|
"@types/d3-shape@*":
|
||||||
|
version "3.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/d3-shape/-/d3-shape-3.1.0.tgz#1d87a6ddcf28285ef1e5c278ca4bdbc0658f3505"
|
||||||
|
integrity sha512-jYIYxFFA9vrJ8Hd4Se83YI6XF+gzDL1aC5DCsldai4XYYiVNdhtpGbA/GM6iyQ8ayhSp3a148LY34hy7A4TxZA==
|
||||||
|
dependencies:
|
||||||
|
"@types/d3-path" "*"
|
||||||
|
|
||||||
|
"@types/d3-time-format@*":
|
||||||
|
version "4.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/d3-time-format/-/d3-time-format-4.0.0.tgz#ee7b6e798f8deb2d9640675f8811d0253aaa1946"
|
||||||
|
integrity sha512-yjfBUe6DJBsDin2BMIulhSHmr5qNR5Pxs17+oW4DoVPyVIXZ+m6bs7j1UVKP08Emv6jRmYrYqxYzO63mQxy1rw==
|
||||||
|
|
||||||
|
"@types/d3-time@*":
|
||||||
|
version "3.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/d3-time/-/d3-time-3.0.0.tgz#e1ac0f3e9e195135361fa1a1d62f795d87e6e819"
|
||||||
|
integrity sha512-sZLCdHvBUcNby1cB6Fd3ZBrABbjz3v1Vm90nysCQ6Vt7vd6e/h9Lt7SiJUoEX0l4Dzc7P5llKyhqSi1ycSf1Hg==
|
||||||
|
|
||||||
|
"@types/d3-timer@*":
|
||||||
|
version "3.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/d3-timer/-/d3-timer-3.0.0.tgz#e2505f1c21ec08bda8915238e397fb71d2fc54ce"
|
||||||
|
integrity sha512-HNB/9GHqu7Fo8AQiugyJbv6ZxYz58wef0esl4Mv828w1ZKpAshw/uFWVDUcIB9KKFeFKoxS3cHY07FFgtTRZ1g==
|
||||||
|
|
||||||
|
"@types/d3-transition@*":
|
||||||
|
version "3.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/d3-transition/-/d3-transition-3.0.2.tgz#393dc3e3d55009a43cc6f252e73fccab6d78a8a4"
|
||||||
|
integrity sha512-jo5o/Rf+/u6uerJ/963Dc39NI16FQzqwOc54bwvksGAdVfvDrqDpVeq95bEvPtBwLCVZutAEyAtmSyEMxN7vxQ==
|
||||||
|
dependencies:
|
||||||
|
"@types/d3-selection" "*"
|
||||||
|
|
||||||
|
"@types/d3-zoom@*":
|
||||||
|
version "3.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/d3-zoom/-/d3-zoom-3.0.1.tgz#4bfc7e29625c4f79df38e2c36de52ec3e9faf826"
|
||||||
|
integrity sha512-7s5L9TjfqIYQmQQEUcpMAcBOahem7TRoSO/+Gkz02GbMVuULiZzjF2BOdw291dbO2aNon4m2OdFsRGaCq2caLQ==
|
||||||
|
dependencies:
|
||||||
|
"@types/d3-interpolate" "*"
|
||||||
|
"@types/d3-selection" "*"
|
||||||
|
|
||||||
|
"@types/d3@7.4.0":
|
||||||
|
version "7.4.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/d3/-/d3-7.4.0.tgz#fc5cac5b1756fc592a3cf1f3dc881bf08225f515"
|
||||||
|
integrity sha512-jIfNVK0ZlxcuRDKtRS/SypEyOQ6UHaFQBKv032X45VvxSJ6Yi5G9behy9h6tNTHTDGh5Vq+KbmBjUWLgY4meCA==
|
||||||
|
dependencies:
|
||||||
|
"@types/d3-array" "*"
|
||||||
|
"@types/d3-axis" "*"
|
||||||
|
"@types/d3-brush" "*"
|
||||||
|
"@types/d3-chord" "*"
|
||||||
|
"@types/d3-color" "*"
|
||||||
|
"@types/d3-contour" "*"
|
||||||
|
"@types/d3-delaunay" "*"
|
||||||
|
"@types/d3-dispatch" "*"
|
||||||
|
"@types/d3-drag" "*"
|
||||||
|
"@types/d3-dsv" "*"
|
||||||
|
"@types/d3-ease" "*"
|
||||||
|
"@types/d3-fetch" "*"
|
||||||
|
"@types/d3-force" "*"
|
||||||
|
"@types/d3-format" "*"
|
||||||
|
"@types/d3-geo" "*"
|
||||||
|
"@types/d3-hierarchy" "*"
|
||||||
|
"@types/d3-interpolate" "*"
|
||||||
|
"@types/d3-path" "*"
|
||||||
|
"@types/d3-polygon" "*"
|
||||||
|
"@types/d3-quadtree" "*"
|
||||||
|
"@types/d3-random" "*"
|
||||||
|
"@types/d3-scale" "*"
|
||||||
|
"@types/d3-scale-chromatic" "*"
|
||||||
|
"@types/d3-selection" "*"
|
||||||
|
"@types/d3-shape" "*"
|
||||||
|
"@types/d3-time" "*"
|
||||||
|
"@types/d3-time-format" "*"
|
||||||
|
"@types/d3-timer" "*"
|
||||||
|
"@types/d3-transition" "*"
|
||||||
|
"@types/d3-zoom" "*"
|
||||||
|
|
||||||
"@types/eslint-scope@^3.7.3":
|
"@types/eslint-scope@^3.7.3":
|
||||||
version "3.7.3"
|
version "3.7.3"
|
||||||
resolved "https://registry.yarnpkg.com/@types/eslint-scope/-/eslint-scope-3.7.3.tgz#125b88504b61e3c8bc6f870882003253005c3224"
|
resolved "https://registry.yarnpkg.com/@types/eslint-scope/-/eslint-scope-3.7.3.tgz#125b88504b61e3c8bc6f870882003253005c3224"
|
||||||
|
@ -3299,6 +3509,11 @@
|
||||||
"@types/express-serve-static-core" "*"
|
"@types/express-serve-static-core" "*"
|
||||||
"@types/serve-static" "*"
|
"@types/serve-static" "*"
|
||||||
|
|
||||||
|
"@types/geojson@*":
|
||||||
|
version "7946.0.10"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/geojson/-/geojson-7946.0.10.tgz#6dfbf5ea17142f7f9a043809f1cd4c448cb68249"
|
||||||
|
integrity sha512-Nmh0K3iWQJzniTuPRcJn5hxXkfB1T1pgB89SBig5PlJQU5yocazeu4jATJlaA0GYFKWMqDdvYemoSnF2pXgLVA==
|
||||||
|
|
||||||
"@types/google.maps@^3.45.3":
|
"@types/google.maps@^3.45.3":
|
||||||
version "3.49.0"
|
version "3.49.0"
|
||||||
resolved "https://registry.yarnpkg.com/@types/google.maps/-/google.maps-3.49.0.tgz#26fcf3d86ecbc6545db0e6691a434ec8132df48b"
|
resolved "https://registry.yarnpkg.com/@types/google.maps/-/google.maps-3.49.0.tgz#26fcf3d86ecbc6545db0e6691a434ec8132df48b"
|
||||||
|
@ -4834,6 +5049,11 @@ comma-separated-tokens@^1.0.0:
|
||||||
resolved "https://registry.yarnpkg.com/comma-separated-tokens/-/comma-separated-tokens-1.0.8.tgz#632b80b6117867a158f1080ad498b2fbe7e3f5ea"
|
resolved "https://registry.yarnpkg.com/comma-separated-tokens/-/comma-separated-tokens-1.0.8.tgz#632b80b6117867a158f1080ad498b2fbe7e3f5ea"
|
||||||
integrity sha512-GHuDRO12Sypu2cV70d1dkA2EUmXHgntrzbpvOB+Qy+49ypNfGgFQIC2fhhXbnyrJRynDCAARsT7Ou0M6hirpfw==
|
integrity sha512-GHuDRO12Sypu2cV70d1dkA2EUmXHgntrzbpvOB+Qy+49ypNfGgFQIC2fhhXbnyrJRynDCAARsT7Ou0M6hirpfw==
|
||||||
|
|
||||||
|
commander@7, commander@^7.2.0:
|
||||||
|
version "7.2.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/commander/-/commander-7.2.0.tgz#a36cb57d0b501ce108e4d20559a150a391d97ab7"
|
||||||
|
integrity sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==
|
||||||
|
|
||||||
commander@^2.20.0:
|
commander@^2.20.0:
|
||||||
version "2.20.3"
|
version "2.20.3"
|
||||||
resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33"
|
resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33"
|
||||||
|
@ -4844,11 +5064,6 @@ commander@^5.1.0:
|
||||||
resolved "https://registry.yarnpkg.com/commander/-/commander-5.1.0.tgz#46abbd1652f8e059bddaef99bbdcb2ad9cf179ae"
|
resolved "https://registry.yarnpkg.com/commander/-/commander-5.1.0.tgz#46abbd1652f8e059bddaef99bbdcb2ad9cf179ae"
|
||||||
integrity sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==
|
integrity sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==
|
||||||
|
|
||||||
commander@^7.2.0:
|
|
||||||
version "7.2.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/commander/-/commander-7.2.0.tgz#a36cb57d0b501ce108e4d20559a150a391d97ab7"
|
|
||||||
integrity sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==
|
|
||||||
|
|
||||||
commander@^8.0.0, commander@^8.3.0:
|
commander@^8.0.0, commander@^8.3.0:
|
||||||
version "8.3.0"
|
version "8.3.0"
|
||||||
resolved "https://registry.yarnpkg.com/commander/-/commander-8.3.0.tgz#4837ea1b2da67b9c616a67afbb0fafee567bca66"
|
resolved "https://registry.yarnpkg.com/commander/-/commander-8.3.0.tgz#4837ea1b2da67b9c616a67afbb0fafee567bca66"
|
||||||
|
@ -5242,11 +5457,60 @@ d3-array@2, d3-array@^2.3.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
internmap "^1.0.0"
|
internmap "^1.0.0"
|
||||||
|
|
||||||
|
"d3-array@2 - 3", "d3-array@2.10.0 - 3", "d3-array@2.5.0 - 3", d3-array@3, d3-array@^3.2.0:
|
||||||
|
version "3.2.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/d3-array/-/d3-array-3.2.0.tgz#15bf96cd9b7333e02eb8de8053d78962eafcff14"
|
||||||
|
integrity sha512-3yXFQo0oG3QCxbF06rMPFyGRMGJNS7NvsV1+2joOjbBE+9xvWQ8+GcMJAjRCzw06zQ3/arXeJgbPYcjUCuC+3g==
|
||||||
|
dependencies:
|
||||||
|
internmap "1 - 2"
|
||||||
|
|
||||||
|
d3-axis@3:
|
||||||
|
version "3.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/d3-axis/-/d3-axis-3.0.0.tgz#c42a4a13e8131d637b745fc2973824cfeaf93322"
|
||||||
|
integrity sha512-IH5tgjV4jE/GhHkRV0HiVYPDtvfjHQlQfJHs0usq7M30XcSBvOotpmH1IgkcXsO/5gEQZD43B//fc7SRT5S+xw==
|
||||||
|
|
||||||
|
d3-brush@3:
|
||||||
|
version "3.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/d3-brush/-/d3-brush-3.0.0.tgz#6f767c4ed8dcb79de7ede3e1c0f89e63ef64d31c"
|
||||||
|
integrity sha512-ALnjWlVYkXsVIGlOsuWH1+3udkYFI48Ljihfnh8FZPF2QS9o+PzGLBslO0PjzVoHLZ2KCVgAM8NVkXPJB2aNnQ==
|
||||||
|
dependencies:
|
||||||
|
d3-dispatch "1 - 3"
|
||||||
|
d3-drag "2 - 3"
|
||||||
|
d3-interpolate "1 - 3"
|
||||||
|
d3-selection "3"
|
||||||
|
d3-transition "3"
|
||||||
|
|
||||||
|
d3-chord@3:
|
||||||
|
version "3.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/d3-chord/-/d3-chord-3.0.1.tgz#d156d61f485fce8327e6abf339cb41d8cbba6966"
|
||||||
|
integrity sha512-VE5S6TNa+j8msksl7HwjxMHDM2yNK3XCkusIlpX5kwauBfXuyLAtNg9jCp/iHH61tgI4sb6R/EIMWCqEIdjT/g==
|
||||||
|
dependencies:
|
||||||
|
d3-path "1 - 3"
|
||||||
|
|
||||||
"d3-color@1 - 2", d3-color@^2.0.0:
|
"d3-color@1 - 2", d3-color@^2.0.0:
|
||||||
version "2.0.0"
|
version "2.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/d3-color/-/d3-color-2.0.0.tgz#8d625cab42ed9b8f601a1760a389f7ea9189d62e"
|
resolved "https://registry.yarnpkg.com/d3-color/-/d3-color-2.0.0.tgz#8d625cab42ed9b8f601a1760a389f7ea9189d62e"
|
||||||
integrity sha512-SPXi0TSKPD4g9tw0NMZFnR95XVgUZiBH+uUTqQuDu1OsE2zomHU7ho0FISciaPvosimixwHFl3WHLGabv6dDgQ==
|
integrity sha512-SPXi0TSKPD4g9tw0NMZFnR95XVgUZiBH+uUTqQuDu1OsE2zomHU7ho0FISciaPvosimixwHFl3WHLGabv6dDgQ==
|
||||||
|
|
||||||
|
"d3-color@1 - 3", d3-color@3:
|
||||||
|
version "3.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/d3-color/-/d3-color-3.1.0.tgz#395b2833dfac71507f12ac2f7af23bf819de24e2"
|
||||||
|
integrity sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==
|
||||||
|
|
||||||
|
d3-contour@4:
|
||||||
|
version "4.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/d3-contour/-/d3-contour-4.0.0.tgz#5a1337c6da0d528479acdb5db54bc81a0ff2ec6b"
|
||||||
|
integrity sha512-7aQo0QHUTu/Ko3cP9YK9yUTxtoDEiDGwnBHyLxG5M4vqlBkO/uixMRele3nfsfj6UXOcuReVpVXzAboGraYIJw==
|
||||||
|
dependencies:
|
||||||
|
d3-array "^3.2.0"
|
||||||
|
|
||||||
|
d3-delaunay@6:
|
||||||
|
version "6.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/d3-delaunay/-/d3-delaunay-6.0.2.tgz#7fd3717ad0eade2fc9939f4260acfb503f984e92"
|
||||||
|
integrity sha512-IMLNldruDQScrcfT+MWnazhHbDJhcRJyOEBAJfwQnHle1RPh6WDuLvxNArUju2VSMSUuKlY5BGHRJ2cYyoFLQQ==
|
||||||
|
dependencies:
|
||||||
|
delaunator "5"
|
||||||
|
|
||||||
d3-delaunay@^5.3.0:
|
d3-delaunay@^5.3.0:
|
||||||
version "5.3.0"
|
version "5.3.0"
|
||||||
resolved "https://registry.yarnpkg.com/d3-delaunay/-/d3-delaunay-5.3.0.tgz#b47f05c38f854a4e7b3cea80e0bb12e57398772d"
|
resolved "https://registry.yarnpkg.com/d3-delaunay/-/d3-delaunay-5.3.0.tgz#b47f05c38f854a4e7b3cea80e0bb12e57398772d"
|
||||||
|
@ -5254,16 +5518,76 @@ d3-delaunay@^5.3.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
delaunator "4"
|
delaunator "4"
|
||||||
|
|
||||||
|
"d3-dispatch@1 - 3", d3-dispatch@3:
|
||||||
|
version "3.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/d3-dispatch/-/d3-dispatch-3.0.1.tgz#5fc75284e9c2375c36c839411a0cf550cbfc4d5e"
|
||||||
|
integrity sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==
|
||||||
|
|
||||||
|
"d3-drag@2 - 3", d3-drag@3:
|
||||||
|
version "3.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/d3-drag/-/d3-drag-3.0.0.tgz#994aae9cd23c719f53b5e10e3a0a6108c69607ba"
|
||||||
|
integrity sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg==
|
||||||
|
dependencies:
|
||||||
|
d3-dispatch "1 - 3"
|
||||||
|
d3-selection "3"
|
||||||
|
|
||||||
|
"d3-dsv@1 - 3", d3-dsv@3:
|
||||||
|
version "3.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/d3-dsv/-/d3-dsv-3.0.1.tgz#c63af978f4d6a0d084a52a673922be2160789b73"
|
||||||
|
integrity sha512-UG6OvdI5afDIFP9w4G0mNq50dSOsXHJaRE8arAS5o9ApWnIElp8GZw1Dun8vP8OyHOZ/QJUKUJwxiiCCnUwm+Q==
|
||||||
|
dependencies:
|
||||||
|
commander "7"
|
||||||
|
iconv-lite "0.6"
|
||||||
|
rw "1"
|
||||||
|
|
||||||
|
"d3-ease@1 - 3", d3-ease@3:
|
||||||
|
version "3.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/d3-ease/-/d3-ease-3.0.1.tgz#9658ac38a2140d59d346160f1f6c30fda0bd12f4"
|
||||||
|
integrity sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==
|
||||||
|
|
||||||
|
d3-fetch@3:
|
||||||
|
version "3.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/d3-fetch/-/d3-fetch-3.0.1.tgz#83141bff9856a0edb5e38de89cdcfe63d0a60a22"
|
||||||
|
integrity sha512-kpkQIM20n3oLVBKGg6oHrUchHM3xODkTzjMoj7aWQFq5QEM+R6E4WkzT5+tojDY7yjez8KgCBRoj4aEr99Fdqw==
|
||||||
|
dependencies:
|
||||||
|
d3-dsv "1 - 3"
|
||||||
|
|
||||||
|
d3-force@3:
|
||||||
|
version "3.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/d3-force/-/d3-force-3.0.0.tgz#3e2ba1a61e70888fe3d9194e30d6d14eece155c4"
|
||||||
|
integrity sha512-zxV/SsA+U4yte8051P4ECydjD/S+qeYtnaIyAs9tgHCqfguma/aAQDjo85A9Z6EKhBirHRJHXIgJUlffT4wdLg==
|
||||||
|
dependencies:
|
||||||
|
d3-dispatch "1 - 3"
|
||||||
|
d3-quadtree "1 - 3"
|
||||||
|
d3-timer "1 - 3"
|
||||||
|
|
||||||
"d3-format@1 - 2":
|
"d3-format@1 - 2":
|
||||||
version "2.0.0"
|
version "2.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/d3-format/-/d3-format-2.0.0.tgz#a10bcc0f986c372b729ba447382413aabf5b0767"
|
resolved "https://registry.yarnpkg.com/d3-format/-/d3-format-2.0.0.tgz#a10bcc0f986c372b729ba447382413aabf5b0767"
|
||||||
integrity sha512-Ab3S6XuE/Q+flY96HXT0jOXcM4EAClYFnRGY5zsjRGNy6qCYrQsMffs7cV5Q9xejb35zxW5hf/guKw34kvIKsA==
|
integrity sha512-Ab3S6XuE/Q+flY96HXT0jOXcM4EAClYFnRGY5zsjRGNy6qCYrQsMffs7cV5Q9xejb35zxW5hf/guKw34kvIKsA==
|
||||||
|
|
||||||
|
"d3-format@1 - 3", d3-format@3:
|
||||||
|
version "3.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/d3-format/-/d3-format-3.1.0.tgz#9260e23a28ea5cb109e93b21a06e24e2ebd55641"
|
||||||
|
integrity sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA==
|
||||||
|
|
||||||
d3-format@^1.4.4:
|
d3-format@^1.4.4:
|
||||||
version "1.4.5"
|
version "1.4.5"
|
||||||
resolved "https://registry.yarnpkg.com/d3-format/-/d3-format-1.4.5.tgz#374f2ba1320e3717eb74a9356c67daee17a7edb4"
|
resolved "https://registry.yarnpkg.com/d3-format/-/d3-format-1.4.5.tgz#374f2ba1320e3717eb74a9356c67daee17a7edb4"
|
||||||
integrity sha512-J0piedu6Z8iB6TbIGfZgDzfXxUFN3qQRMofy2oPdXzQibYGqPB/9iMcxr/TGalU+2RsyDO+U4f33id8tbnSRMQ==
|
integrity sha512-J0piedu6Z8iB6TbIGfZgDzfXxUFN3qQRMofy2oPdXzQibYGqPB/9iMcxr/TGalU+2RsyDO+U4f33id8tbnSRMQ==
|
||||||
|
|
||||||
|
d3-geo@3:
|
||||||
|
version "3.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/d3-geo/-/d3-geo-3.0.1.tgz#4f92362fd8685d93e3b1fae0fd97dc8980b1ed7e"
|
||||||
|
integrity sha512-Wt23xBych5tSy9IYAM1FR2rWIBFWa52B/oF/GYe5zbdHrg08FU8+BuI6X4PvTwPDdqdAdq04fuWJpELtsaEjeA==
|
||||||
|
dependencies:
|
||||||
|
d3-array "2.5.0 - 3"
|
||||||
|
|
||||||
|
d3-hierarchy@3:
|
||||||
|
version "3.1.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/d3-hierarchy/-/d3-hierarchy-3.1.2.tgz#b01cd42c1eed3d46db77a5966cf726f8c09160c6"
|
||||||
|
integrity sha512-FX/9frcub54beBdugHjDCdikxThEqjnR93Qt7PvQTOHxyiNCAlvMrHhclk3cD5VeAaq9fxmfRp+CnWw9rEMBuA==
|
||||||
|
|
||||||
"d3-interpolate@1 - 2", "d3-interpolate@1.2.0 - 2", d3-interpolate@^2.0.1:
|
"d3-interpolate@1 - 2", "d3-interpolate@1.2.0 - 2", d3-interpolate@^2.0.1:
|
||||||
version "2.0.1"
|
version "2.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/d3-interpolate/-/d3-interpolate-2.0.1.tgz#98be499cfb8a3b94d4ff616900501a64abc91163"
|
resolved "https://registry.yarnpkg.com/d3-interpolate/-/d3-interpolate-2.0.1.tgz#98be499cfb8a3b94d4ff616900501a64abc91163"
|
||||||
|
@ -5271,11 +5595,46 @@ d3-format@^1.4.4:
|
||||||
dependencies:
|
dependencies:
|
||||||
d3-color "1 - 2"
|
d3-color "1 - 2"
|
||||||
|
|
||||||
|
"d3-interpolate@1 - 3", "d3-interpolate@1.2.0 - 3", d3-interpolate@3:
|
||||||
|
version "3.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/d3-interpolate/-/d3-interpolate-3.0.1.tgz#3c47aa5b32c5b3dfb56ef3fd4342078a632b400d"
|
||||||
|
integrity sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==
|
||||||
|
dependencies:
|
||||||
|
d3-color "1 - 3"
|
||||||
|
|
||||||
d3-path@1:
|
d3-path@1:
|
||||||
version "1.0.9"
|
version "1.0.9"
|
||||||
resolved "https://registry.yarnpkg.com/d3-path/-/d3-path-1.0.9.tgz#48c050bb1fe8c262493a8caf5524e3e9591701cf"
|
resolved "https://registry.yarnpkg.com/d3-path/-/d3-path-1.0.9.tgz#48c050bb1fe8c262493a8caf5524e3e9591701cf"
|
||||||
integrity sha512-VLaYcn81dtHVTjEHd8B+pbe9yHWpXKZUC87PzoFmsFrJqgFwDe/qxfp5MlfsfM1V5E/iVt0MmEbWQ7FVIXh/bg==
|
integrity sha512-VLaYcn81dtHVTjEHd8B+pbe9yHWpXKZUC87PzoFmsFrJqgFwDe/qxfp5MlfsfM1V5E/iVt0MmEbWQ7FVIXh/bg==
|
||||||
|
|
||||||
|
"d3-path@1 - 3", d3-path@3:
|
||||||
|
version "3.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/d3-path/-/d3-path-3.0.1.tgz#f09dec0aaffd770b7995f1a399152bf93052321e"
|
||||||
|
integrity sha512-gq6gZom9AFZby0YLduxT1qmrp4xpBA1YZr19OI717WIdKE2OM5ETq5qrHLb301IgxhLwcuxvGZVLeeWc/k1I6w==
|
||||||
|
|
||||||
|
d3-polygon@3:
|
||||||
|
version "3.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/d3-polygon/-/d3-polygon-3.0.1.tgz#0b45d3dd1c48a29c8e057e6135693ec80bf16398"
|
||||||
|
integrity sha512-3vbA7vXYwfe1SYhED++fPUQlWSYTTGmFmQiany/gdbiWgU/iEyQzyymwL9SkJjFFuCS4902BSzewVGsHHmHtXg==
|
||||||
|
|
||||||
|
"d3-quadtree@1 - 3", d3-quadtree@3:
|
||||||
|
version "3.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/d3-quadtree/-/d3-quadtree-3.0.1.tgz#6dca3e8be2b393c9a9d514dabbd80a92deef1a4f"
|
||||||
|
integrity sha512-04xDrxQTDTCFwP5H6hRhsRcb9xxv2RzkcsygFzmkSIOJy3PeRJP7sNk3VRIbKXcog561P9oU0/rVH6vDROAgUw==
|
||||||
|
|
||||||
|
d3-random@3:
|
||||||
|
version "3.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/d3-random/-/d3-random-3.0.1.tgz#d4926378d333d9c0bfd1e6fa0194d30aebaa20f4"
|
||||||
|
integrity sha512-FXMe9GfxTxqd5D6jFsQ+DJ8BJS4E/fT5mqqdjovykEB2oFbTMDVdg1MGFxfQW+FBOGoB++k8swBrgwSHT1cUXQ==
|
||||||
|
|
||||||
|
d3-scale-chromatic@3:
|
||||||
|
version "3.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/d3-scale-chromatic/-/d3-scale-chromatic-3.0.0.tgz#15b4ceb8ca2bb0dcb6d1a641ee03d59c3b62376a"
|
||||||
|
integrity sha512-Lx9thtxAKrO2Pq6OO2Ua474opeziKr279P/TKZsMAhYyNDD3EnCffdbgeSYN5O7m2ByQsxtuP2CSDczNUIZ22g==
|
||||||
|
dependencies:
|
||||||
|
d3-color "1 - 3"
|
||||||
|
d3-interpolate "1 - 3"
|
||||||
|
|
||||||
d3-scale-chromatic@^2.0.0:
|
d3-scale-chromatic@^2.0.0:
|
||||||
version "2.0.0"
|
version "2.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/d3-scale-chromatic/-/d3-scale-chromatic-2.0.0.tgz#c13f3af86685ff91323dc2f0ebd2dabbd72d8bab"
|
resolved "https://registry.yarnpkg.com/d3-scale-chromatic/-/d3-scale-chromatic-2.0.0.tgz#c13f3af86685ff91323dc2f0ebd2dabbd72d8bab"
|
||||||
|
@ -5284,6 +5643,17 @@ d3-scale-chromatic@^2.0.0:
|
||||||
d3-color "1 - 2"
|
d3-color "1 - 2"
|
||||||
d3-interpolate "1 - 2"
|
d3-interpolate "1 - 2"
|
||||||
|
|
||||||
|
d3-scale@4:
|
||||||
|
version "4.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/d3-scale/-/d3-scale-4.0.2.tgz#82b38e8e8ff7080764f8dcec77bd4be393689396"
|
||||||
|
integrity sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==
|
||||||
|
dependencies:
|
||||||
|
d3-array "2.10.0 - 3"
|
||||||
|
d3-format "1 - 3"
|
||||||
|
d3-interpolate "1.2.0 - 3"
|
||||||
|
d3-time "2.1.1 - 3"
|
||||||
|
d3-time-format "2 - 4"
|
||||||
|
|
||||||
d3-scale@^3.2.3:
|
d3-scale@^3.2.3:
|
||||||
version "3.3.0"
|
version "3.3.0"
|
||||||
resolved "https://registry.yarnpkg.com/d3-scale/-/d3-scale-3.3.0.tgz#28c600b29f47e5b9cd2df9749c206727966203f3"
|
resolved "https://registry.yarnpkg.com/d3-scale/-/d3-scale-3.3.0.tgz#28c600b29f47e5b9cd2df9749c206727966203f3"
|
||||||
|
@ -5295,6 +5665,18 @@ d3-scale@^3.2.3:
|
||||||
d3-time "^2.1.1"
|
d3-time "^2.1.1"
|
||||||
d3-time-format "2 - 3"
|
d3-time-format "2 - 3"
|
||||||
|
|
||||||
|
"d3-selection@2 - 3", d3-selection@3:
|
||||||
|
version "3.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/d3-selection/-/d3-selection-3.0.0.tgz#c25338207efa72cc5b9bd1458a1a41901f1e1b31"
|
||||||
|
integrity sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==
|
||||||
|
|
||||||
|
d3-shape@3:
|
||||||
|
version "3.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/d3-shape/-/d3-shape-3.1.0.tgz#c8a495652d83ea6f524e482fca57aa3f8bc32556"
|
||||||
|
integrity sha512-tGDh1Muf8kWjEDT/LswZJ8WF85yDZLvVJpYU9Nq+8+yW1Z5enxrmXOhTArlkaElU+CTn0OTVNli+/i+HP45QEQ==
|
||||||
|
dependencies:
|
||||||
|
d3-path "1 - 3"
|
||||||
|
|
||||||
d3-shape@^1.3.5:
|
d3-shape@^1.3.5:
|
||||||
version "1.3.7"
|
version "1.3.7"
|
||||||
resolved "https://registry.yarnpkg.com/d3-shape/-/d3-shape-1.3.7.tgz#df63801be07bc986bc54f63789b4fe502992b5d7"
|
resolved "https://registry.yarnpkg.com/d3-shape/-/d3-shape-1.3.7.tgz#df63801be07bc986bc54f63789b4fe502992b5d7"
|
||||||
|
@ -5309,6 +5691,13 @@ d3-shape@^1.3.5:
|
||||||
dependencies:
|
dependencies:
|
||||||
d3-time "1 - 2"
|
d3-time "1 - 2"
|
||||||
|
|
||||||
|
"d3-time-format@2 - 4", d3-time-format@4:
|
||||||
|
version "4.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/d3-time-format/-/d3-time-format-4.1.0.tgz#7ab5257a5041d11ecb4fe70a5c7d16a195bb408a"
|
||||||
|
integrity sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==
|
||||||
|
dependencies:
|
||||||
|
d3-time "1 - 3"
|
||||||
|
|
||||||
"d3-time@1 - 2", d3-time@^2.1.1:
|
"d3-time@1 - 2", d3-time@^2.1.1:
|
||||||
version "2.1.1"
|
version "2.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/d3-time/-/d3-time-2.1.1.tgz#e9d8a8a88691f4548e68ca085e5ff956724a6682"
|
resolved "https://registry.yarnpkg.com/d3-time/-/d3-time-2.1.1.tgz#e9d8a8a88691f4548e68ca085e5ff956724a6682"
|
||||||
|
@ -5316,11 +5705,81 @@ d3-shape@^1.3.5:
|
||||||
dependencies:
|
dependencies:
|
||||||
d3-array "2"
|
d3-array "2"
|
||||||
|
|
||||||
|
"d3-time@1 - 3", "d3-time@2.1.1 - 3", d3-time@3:
|
||||||
|
version "3.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/d3-time/-/d3-time-3.0.0.tgz#65972cb98ae2d4954ef5c932e8704061335d4975"
|
||||||
|
integrity sha512-zmV3lRnlaLI08y9IMRXSDshQb5Nj77smnfpnd2LrBa/2K281Jijactokeak14QacHs/kKq0AQ121nidNYlarbQ==
|
||||||
|
dependencies:
|
||||||
|
d3-array "2 - 3"
|
||||||
|
|
||||||
d3-time@^1.0.11:
|
d3-time@^1.0.11:
|
||||||
version "1.1.0"
|
version "1.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/d3-time/-/d3-time-1.1.0.tgz#b1e19d307dae9c900b7e5b25ffc5dcc249a8a0f1"
|
resolved "https://registry.yarnpkg.com/d3-time/-/d3-time-1.1.0.tgz#b1e19d307dae9c900b7e5b25ffc5dcc249a8a0f1"
|
||||||
integrity sha512-Xh0isrZ5rPYYdqhAVk8VLnMEidhz5aP7htAADH6MfzgmmicPkTo8LhkLxci61/lCB7n7UmE3bN0leRt+qvkLxA==
|
integrity sha512-Xh0isrZ5rPYYdqhAVk8VLnMEidhz5aP7htAADH6MfzgmmicPkTo8LhkLxci61/lCB7n7UmE3bN0leRt+qvkLxA==
|
||||||
|
|
||||||
|
"d3-timer@1 - 3", d3-timer@3:
|
||||||
|
version "3.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/d3-timer/-/d3-timer-3.0.1.tgz#6284d2a2708285b1abb7e201eda4380af35e63b0"
|
||||||
|
integrity sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==
|
||||||
|
|
||||||
|
"d3-transition@2 - 3", d3-transition@3:
|
||||||
|
version "3.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/d3-transition/-/d3-transition-3.0.1.tgz#6869fdde1448868077fdd5989200cb61b2a1645f"
|
||||||
|
integrity sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w==
|
||||||
|
dependencies:
|
||||||
|
d3-color "1 - 3"
|
||||||
|
d3-dispatch "1 - 3"
|
||||||
|
d3-ease "1 - 3"
|
||||||
|
d3-interpolate "1 - 3"
|
||||||
|
d3-timer "1 - 3"
|
||||||
|
|
||||||
|
d3-zoom@3:
|
||||||
|
version "3.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/d3-zoom/-/d3-zoom-3.0.0.tgz#d13f4165c73217ffeaa54295cd6969b3e7aee8f3"
|
||||||
|
integrity sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw==
|
||||||
|
dependencies:
|
||||||
|
d3-dispatch "1 - 3"
|
||||||
|
d3-drag "2 - 3"
|
||||||
|
d3-interpolate "1 - 3"
|
||||||
|
d3-selection "2 - 3"
|
||||||
|
d3-transition "2 - 3"
|
||||||
|
|
||||||
|
d3@7.6.1:
|
||||||
|
version "7.6.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/d3/-/d3-7.6.1.tgz#b21af9563485ed472802f8c611cc43be6c37c40c"
|
||||||
|
integrity sha512-txMTdIHFbcpLx+8a0IFhZsbp+PfBBPt8yfbmukZTQFroKuFqIwqswF0qE5JXWefylaAVpSXFoKm3yP+jpNLFLw==
|
||||||
|
dependencies:
|
||||||
|
d3-array "3"
|
||||||
|
d3-axis "3"
|
||||||
|
d3-brush "3"
|
||||||
|
d3-chord "3"
|
||||||
|
d3-color "3"
|
||||||
|
d3-contour "4"
|
||||||
|
d3-delaunay "6"
|
||||||
|
d3-dispatch "3"
|
||||||
|
d3-drag "3"
|
||||||
|
d3-dsv "3"
|
||||||
|
d3-ease "3"
|
||||||
|
d3-fetch "3"
|
||||||
|
d3-force "3"
|
||||||
|
d3-format "3"
|
||||||
|
d3-geo "3"
|
||||||
|
d3-hierarchy "3"
|
||||||
|
d3-interpolate "3"
|
||||||
|
d3-path "3"
|
||||||
|
d3-polygon "3"
|
||||||
|
d3-quadtree "3"
|
||||||
|
d3-random "3"
|
||||||
|
d3-scale "4"
|
||||||
|
d3-scale-chromatic "3"
|
||||||
|
d3-selection "3"
|
||||||
|
d3-shape "3"
|
||||||
|
d3-time "3"
|
||||||
|
d3-time-format "4"
|
||||||
|
d3-timer "3"
|
||||||
|
d3-transition "3"
|
||||||
|
d3-zoom "3"
|
||||||
|
|
||||||
daisyui@1.16.4:
|
daisyui@1.16.4:
|
||||||
version "1.16.4"
|
version "1.16.4"
|
||||||
resolved "https://registry.yarnpkg.com/daisyui/-/daisyui-1.16.4.tgz#52773401c0962e37ef40507d29f0e513c7f2856f"
|
resolved "https://registry.yarnpkg.com/daisyui/-/daisyui-1.16.4.tgz#52773401c0962e37ef40507d29f0e513c7f2856f"
|
||||||
|
@ -5464,6 +5923,13 @@ delaunator@4:
|
||||||
resolved "https://registry.yarnpkg.com/delaunator/-/delaunator-4.0.1.tgz#3d779687f57919a7a418f8ab947d3bddb6846957"
|
resolved "https://registry.yarnpkg.com/delaunator/-/delaunator-4.0.1.tgz#3d779687f57919a7a418f8ab947d3bddb6846957"
|
||||||
integrity sha512-WNPWi1IRKZfCt/qIDMfERkDp93+iZEmOxN2yy4Jg+Xhv8SLk2UTqqbe1sfiipn0and9QrE914/ihdx82Y/Giag==
|
integrity sha512-WNPWi1IRKZfCt/qIDMfERkDp93+iZEmOxN2yy4Jg+Xhv8SLk2UTqqbe1sfiipn0and9QrE914/ihdx82Y/Giag==
|
||||||
|
|
||||||
|
delaunator@5:
|
||||||
|
version "5.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/delaunator/-/delaunator-5.0.0.tgz#60f052b28bd91c9b4566850ebf7756efe821d81b"
|
||||||
|
integrity sha512-AyLvtyJdbv/U1GkiS6gUUzclRoAY4Gs75qkMygJJhU75LW4DNuSF2RMzpxs9jw9Oz1BobHjTdkG3zdP55VxAqw==
|
||||||
|
dependencies:
|
||||||
|
robust-predicates "^3.0.0"
|
||||||
|
|
||||||
delayed-stream@~1.0.0:
|
delayed-stream@~1.0.0:
|
||||||
version "1.0.0"
|
version "1.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
|
resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
|
||||||
|
@ -7381,6 +7847,13 @@ iconv-lite@0.4.24:
|
||||||
dependencies:
|
dependencies:
|
||||||
safer-buffer ">= 2.1.2 < 3"
|
safer-buffer ">= 2.1.2 < 3"
|
||||||
|
|
||||||
|
iconv-lite@0.6:
|
||||||
|
version "0.6.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.6.3.tgz#a52f80bf38da1952eb5c681790719871a1a72501"
|
||||||
|
integrity sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==
|
||||||
|
dependencies:
|
||||||
|
safer-buffer ">= 2.1.2 < 3.0.0"
|
||||||
|
|
||||||
icss-utils@^5.0.0, icss-utils@^5.1.0:
|
icss-utils@^5.0.0, icss-utils@^5.1.0:
|
||||||
version "5.1.0"
|
version "5.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/icss-utils/-/icss-utils-5.1.0.tgz#c6be6858abd013d768e98366ae47e25d5887b1ae"
|
resolved "https://registry.yarnpkg.com/icss-utils/-/icss-utils-5.1.0.tgz#c6be6858abd013d768e98366ae47e25d5887b1ae"
|
||||||
|
@ -7519,6 +7992,11 @@ internal-slot@^1.0.3:
|
||||||
has "^1.0.3"
|
has "^1.0.3"
|
||||||
side-channel "^1.0.4"
|
side-channel "^1.0.4"
|
||||||
|
|
||||||
|
"internmap@1 - 2":
|
||||||
|
version "2.0.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/internmap/-/internmap-2.0.3.tgz#6685f23755e43c524e251d29cbc97248e3061009"
|
||||||
|
integrity sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==
|
||||||
|
|
||||||
internmap@^1.0.0:
|
internmap@^1.0.0:
|
||||||
version "1.0.1"
|
version "1.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/internmap/-/internmap-1.0.1.tgz#0017cc8a3b99605f0302f2b198d272e015e5df95"
|
resolved "https://registry.yarnpkg.com/internmap/-/internmap-1.0.1.tgz#0017cc8a3b99605f0302f2b198d272e015e5df95"
|
||||||
|
@ -10672,6 +11150,11 @@ rimraf@3.0.2, rimraf@^3.0.0, rimraf@^3.0.2:
|
||||||
dependencies:
|
dependencies:
|
||||||
glob "^7.1.3"
|
glob "^7.1.3"
|
||||||
|
|
||||||
|
robust-predicates@^3.0.0:
|
||||||
|
version "3.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/robust-predicates/-/robust-predicates-3.0.1.tgz#ecde075044f7f30118682bd9fb3f123109577f9a"
|
||||||
|
integrity sha512-ndEIpszUHiG4HtDsQLeIuMvRsDnn8c8rYStabochtUeCvfuvNptb5TUbVD68LRAILPX7p9nqQGh4xJgn3EHS/g==
|
||||||
|
|
||||||
rope-sequence@^1.3.0:
|
rope-sequence@^1.3.0:
|
||||||
version "1.3.3"
|
version "1.3.3"
|
||||||
resolved "https://registry.yarnpkg.com/rope-sequence/-/rope-sequence-1.3.3.tgz#3f67fc106288b84b71532b4a5fd9d4881e4457f0"
|
resolved "https://registry.yarnpkg.com/rope-sequence/-/rope-sequence-1.3.3.tgz#3f67fc106288b84b71532b4a5fd9d4881e4457f0"
|
||||||
|
@ -10699,6 +11182,11 @@ run-parallel@^1.1.9:
|
||||||
dependencies:
|
dependencies:
|
||||||
queue-microtask "^1.2.2"
|
queue-microtask "^1.2.2"
|
||||||
|
|
||||||
|
rw@1:
|
||||||
|
version "1.3.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/rw/-/rw-1.3.3.tgz#3f862dfa91ab766b14885ef4d01124bfda074fb4"
|
||||||
|
integrity sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==
|
||||||
|
|
||||||
rxjs@^6.6.3:
|
rxjs@^6.6.3:
|
||||||
version "6.6.7"
|
version "6.6.7"
|
||||||
resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.6.7.tgz#90ac018acabf491bf65044235d5863c4dab804c9"
|
resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.6.7.tgz#90ac018acabf491bf65044235d5863c4dab804c9"
|
||||||
|
@ -10723,7 +11211,7 @@ safe-buffer@5.2.1, safe-buffer@>=5.1.0, safe-buffer@^5.0.1, safe-buffer@^5.1.0,
|
||||||
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6"
|
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6"
|
||||||
integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==
|
integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==
|
||||||
|
|
||||||
"safer-buffer@>= 2.1.2 < 3":
|
"safer-buffer@>= 2.1.2 < 3", "safer-buffer@>= 2.1.2 < 3.0.0":
|
||||||
version "2.1.2"
|
version "2.1.2"
|
||||||
resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
|
resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
|
||||||
integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
|
integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
|
||||||
|
|
Loading…
Reference in New Issue
Block a user