rozetko
12 months ago
3 changed files with 133 additions and 3 deletions
@ -0,0 +1,121 @@
|
||||
import type { LineTimeSerie, LineOptions } from '@chartwerk/line-pod'; |
||||
import { LinePod } from '@chartwerk/line-pod'; |
||||
|
||||
import { useEffect, useRef, useState, PropsWithChildren, forwardRef } from 'react'; |
||||
|
||||
import * as _ from 'lodash'; |
||||
|
||||
export type AxisRange = [number, number] | undefined; |
||||
export type ChartwerkLinePodProps = { |
||||
id: string; |
||||
series: LineTimeSerie[]; |
||||
options: LineOptions; |
||||
className?: string; |
||||
// TODO: callback types should be exported from chartwerk
|
||||
onZoomIn?: (ranges: AxisRange[]) => void; |
||||
onZoomOut?: (centers: { x: number, y: number }) => void; |
||||
onMouseMove?: (event: any) => void; |
||||
onMouseOut?: () => void; |
||||
onLegendClick?: (idx: number) => void, |
||||
onPanning?: (event: { ranges: AxisRange[], d3Event: any }) => void; |
||||
onPanningEnd?: (ranges: AxisRange[]) => void; |
||||
onContextMenu?: (evt: any) => void; |
||||
onSharedCrosshairMove?: (evt: any) => void; |
||||
onRenderStart?: () => void, |
||||
onRenderEnd?: () => void, |
||||
} |
||||
|
||||
export const ChartwerkLinePod = forwardRef<HTMLDivElement, PropsWithChildren<ChartwerkLinePodProps>>((props, ref) => { |
||||
const [pod, setPod] = useState<LinePod | null>(null); |
||||
const [hack, setHack] = useState<number | null>(null); |
||||
|
||||
const chartRef = useRef(null); |
||||
const chart = chartRef.current; |
||||
|
||||
useEffect(() => { |
||||
// this function will be called on component unmount
|
||||
return () => { |
||||
if (pod === null) { |
||||
return; |
||||
} |
||||
|
||||
console.log('remove chart'); |
||||
|
||||
// @ts-ignore
|
||||
pod.removeEventListeners(); |
||||
} |
||||
}, []); |
||||
|
||||
useEffect(() => { |
||||
if (chart === null) { |
||||
return; |
||||
} |
||||
|
||||
let eventsCallbacks = _.cloneDeep(props.options.eventsCallbacks || {}); |
||||
if (props.onZoomIn) { |
||||
eventsCallbacks.zoomIn = props.onZoomIn; |
||||
} |
||||
if (props.onZoomOut) { |
||||
eventsCallbacks.zoomOut = props.onZoomOut; |
||||
} |
||||
if (props.onMouseMove) { |
||||
eventsCallbacks.mouseMove = props.onMouseMove; |
||||
} |
||||
if (props.onMouseOut) { |
||||
eventsCallbacks.mouseOut = props.onMouseOut; |
||||
} |
||||
if (props.onLegendClick) { |
||||
eventsCallbacks.onLegendClick = props.onLegendClick; |
||||
} |
||||
if (props.onPanning) { |
||||
eventsCallbacks.panning = props.onPanning; |
||||
} |
||||
if (props.onPanningEnd) { |
||||
eventsCallbacks.panningEnd = props.onPanningEnd; |
||||
} |
||||
if (props.onContextMenu) { |
||||
eventsCallbacks.contextMenu = props.onContextMenu; |
||||
} |
||||
if (props.onSharedCrosshairMove) { |
||||
eventsCallbacks.sharedCrosshairMove = props.onSharedCrosshairMove; |
||||
} |
||||
if (props.onRenderStart) { |
||||
eventsCallbacks.renderStart = props.onRenderStart; |
||||
} |
||||
|
||||
if (pod === null) { |
||||
console.log('create chart'); |
||||
|
||||
const newPod = new LinePod( |
||||
// @ts-ignore
|
||||
chart, |
||||
props.series, |
||||
{ |
||||
...props.options, |
||||
eventsCallbacks, |
||||
} |
||||
); |
||||
setPod(newPod); |
||||
newPod.render(); |
||||
} else { |
||||
pod.updateData(props.series, { |
||||
...props.options, |
||||
eventsCallbacks, |
||||
}); |
||||
} |
||||
}, [chart, pod, props.id, props.series, props.options]); |
||||
|
||||
// TODO: it's a hack to render the LinePod right after the div appears in DOM
|
||||
setTimeout(() => { |
||||
if (hack === null) { |
||||
setHack(1); |
||||
} |
||||
}, 1); |
||||
|
||||
return ( |
||||
<div ref={ref}> |
||||
<div id={props.id} className={props.className} ref={chartRef}></div> |
||||
{props.children} |
||||
</div> |
||||
); |
||||
}); |
Loading…
Reference in new issue