Embed market: dynamically adjust graph height
This commit is contained in:
parent
b6281b0b56
commit
7d8a87615a
|
@ -1,3 +1,3 @@
|
|||
export function filterDefined<T>(array: (T | null | undefined)[]) {
|
||||
return array.filter((item) => item) as T[]
|
||||
return array.filter((item) => item !== null && item !== undefined) as T[]
|
||||
}
|
||||
|
|
|
@ -14,8 +14,9 @@ const NUM_LINES = 6
|
|||
export function AnswersGraph(props: {
|
||||
contract: FullContract<DPM, FreeResponse>
|
||||
bets: Bet[]
|
||||
height?: number
|
||||
}) {
|
||||
const { contract } = props
|
||||
const { contract, height } = props
|
||||
const { createdTime, resolutionTime, closeTime, answers } = contract
|
||||
|
||||
const bets = useBets(contract.id) ?? props.bets
|
||||
|
@ -86,7 +87,7 @@ export function AnswersGraph(props: {
|
|||
return (
|
||||
<div
|
||||
className="w-full overflow-hidden"
|
||||
style={{ height: !width || width >= 800 ? 350 : 225 }}
|
||||
style={{ height: height ?? (!width || width >= 800 ? 350 : 225) }}
|
||||
>
|
||||
<ResponsiveLine
|
||||
data={data}
|
||||
|
|
|
@ -10,8 +10,9 @@ import { useWindowSize } from '../hooks/use-window-size'
|
|||
export function ContractProbGraph(props: {
|
||||
contract: FullContract<DPM | CPMM, Binary>
|
||||
bets: Bet[]
|
||||
height?: number
|
||||
}) {
|
||||
const { contract } = props
|
||||
const { contract, height } = props
|
||||
const { resolutionTime, closeTime } = contract
|
||||
|
||||
const bets = useBetsWithoutAntes(contract, props.bets).filter(
|
||||
|
@ -63,7 +64,7 @@ export function ContractProbGraph(props: {
|
|||
return (
|
||||
<div
|
||||
className="w-full overflow-hidden"
|
||||
style={{ height: !width || width >= 800 ? 400 : 250 }}
|
||||
style={{ height: height ?? (!width || width >= 800 ? 400 : 250) }}
|
||||
>
|
||||
<ResponsiveLine
|
||||
data={data}
|
||||
|
|
|
@ -1,15 +1,16 @@
|
|||
import clsx from 'clsx'
|
||||
import { CSSProperties } from 'react'
|
||||
import { CSSProperties, Ref } from 'react'
|
||||
|
||||
export function Col(props: {
|
||||
children?: any
|
||||
className?: string
|
||||
style?: CSSProperties
|
||||
ref?: Ref<HTMLDivElement>
|
||||
}) {
|
||||
const { children, className, style } = props
|
||||
const { children, className, style, ref } = props
|
||||
|
||||
return (
|
||||
<div className={clsx(className, 'flex flex-col')} style={style}>
|
||||
<div className={clsx(className, 'flex flex-col')} style={style} ref={ref}>
|
||||
{children}
|
||||
</div>
|
||||
)
|
||||
|
|
63
web/hooks/use-measure-size.ts
Normal file
63
web/hooks/use-measure-size.ts
Normal file
|
@ -0,0 +1,63 @@
|
|||
import _ from 'lodash'
|
||||
import { RefObject, useMemo, useLayoutEffect, useRef, useState } from 'react'
|
||||
|
||||
type elem_size =
|
||||
| { width: number; height: number }
|
||||
| { width: undefined; height: undefined }
|
||||
|
||||
const getSize = (elem: HTMLElement | null) =>
|
||||
elem
|
||||
? { width: elem.offsetWidth, height: elem.offsetHeight }
|
||||
: { width: undefined, height: undefined }
|
||||
|
||||
export function useListenElemSize<T extends HTMLElement>(
|
||||
elemRef: RefObject<T | null>,
|
||||
callback: (size: elem_size) => void,
|
||||
debounceMs: number | undefined = undefined
|
||||
) {
|
||||
const handleResize = useMemo(() => {
|
||||
let updateSize = () => {
|
||||
if (elemRef.current) callback(getSize(elemRef.current))
|
||||
}
|
||||
|
||||
return debounceMs
|
||||
? _.debounce(updateSize, debounceMs, { leading: false, trailing: true })
|
||||
: updateSize
|
||||
}, [callback, elemRef, debounceMs])
|
||||
|
||||
let elem = elemRef.current
|
||||
|
||||
useLayoutEffect(() => {
|
||||
if (!elemRef.current) return
|
||||
|
||||
const resizeObserver = new ResizeObserver(handleResize)
|
||||
resizeObserver.observe(elemRef.current)
|
||||
|
||||
return () => resizeObserver.disconnect()
|
||||
}, [elemRef, elem, handleResize])
|
||||
}
|
||||
|
||||
export function useMeasureSize(debounceMs: number | undefined = undefined) {
|
||||
const elemRef = useRef<HTMLElement | null>(null)
|
||||
const [size, setSize] = useState(() => getSize(null))
|
||||
const sizeRef = useRef<elem_size>(size)
|
||||
|
||||
const setSizeIfDifferent = (newSize: typeof size) => {
|
||||
if (newSize?.height !== size?.height || newSize?.width !== size?.width) {
|
||||
sizeRef.current = newSize
|
||||
setSize(newSize)
|
||||
}
|
||||
}
|
||||
|
||||
useListenElemSize(elemRef, setSizeIfDifferent, debounceMs)
|
||||
|
||||
const setElem = (elem: HTMLElement | null) => {
|
||||
elemRef.current = elem
|
||||
|
||||
if (elem) {
|
||||
setSizeIfDifferent(getSize(elem))
|
||||
}
|
||||
}
|
||||
|
||||
return { setElem, elemRef, sizeRef, ...size }
|
||||
}
|
|
@ -18,7 +18,9 @@ import { Spacer } from '../../../components/layout/spacer'
|
|||
import { Linkify } from '../../../components/linkify'
|
||||
import { SiteLink } from '../../../components/site-link'
|
||||
import { useContractWithPreload } from '../../../hooks/use-contract'
|
||||
import { useMeasureSize } from '../../../hooks/use-measure-size'
|
||||
import { fromPropz, usePropz } from '../../../hooks/use-propz'
|
||||
import { useWindowSize } from '../../../hooks/use-window-size'
|
||||
import { listAllBets } from '../../../lib/firebase/bets'
|
||||
import {
|
||||
contractPath,
|
||||
|
@ -85,9 +87,18 @@ function ContractEmbed(props: { contract: Contract; bets: Bet[] }) {
|
|||
|
||||
const href = `https://${DOMAIN}${contractPath(contract)}`
|
||||
|
||||
const { height: windowHeight } = useWindowSize()
|
||||
const { setElem, height: topSectionHeight } = useMeasureSize()
|
||||
const paddingBottom = 8
|
||||
|
||||
const graphHeight =
|
||||
windowHeight && topSectionHeight
|
||||
? windowHeight - topSectionHeight - paddingBottom
|
||||
: 0
|
||||
|
||||
return (
|
||||
<Col className="w-full flex-1 bg-white py-2">
|
||||
<Col className="relative">
|
||||
<Col className="w-full flex-1 bg-white">
|
||||
<div className="flex flex-col relative pt-2" ref={setElem}>
|
||||
<SiteLink
|
||||
className="absolute top-0 left-0 w-full h-full z-20"
|
||||
href={href}
|
||||
|
@ -112,15 +123,20 @@ function ContractEmbed(props: { contract: Contract; bets: Bet[] }) {
|
|||
</Row>
|
||||
|
||||
<Spacer h={2} />
|
||||
</Col>
|
||||
</div>
|
||||
|
||||
<div className="mx-1">
|
||||
<div className="mx-1" style={{ paddingBottom }}>
|
||||
{isBinary ? (
|
||||
<ContractProbGraph contract={contract} bets={bets} />
|
||||
<ContractProbGraph
|
||||
contract={contract}
|
||||
bets={bets}
|
||||
height={graphHeight}
|
||||
/>
|
||||
) : (
|
||||
<AnswersGraph
|
||||
contract={contract as FullContract<DPM, FreeResponse>}
|
||||
bets={bets}
|
||||
height={graphHeight}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
|
|
Loading…
Reference in New Issue
Block a user