import type { CSSProperties } from 'react'; import { useMemo } from 'react'; import { useBrushTracker } from '../../EventsTrackers/BrushTracker.js'; import { useMouseTracker } from '../../EventsTrackers/MouseTracker.js'; import { useChartData } from '../../context/ChartContext.js'; import { useActiveSpectrum } from '../../hooks/useActiveSpectrum.js'; import { useFormatNumberByNucleus } from '../../hooks/useFormatNumberByNucleus.js'; import type { Spectrum1DTraces } from '../useTracesSpectra.js'; import type { Get2DDimensionLayoutReturn } from '../utilities/DimensionLayout.js'; import { LAYOUT, getLayoutID } from '../utilities/DimensionLayout.js'; import { get1DYScale, useScale2DX, useScale2DY } from '../utilities/scale.js'; const style: CSSProperties = { cursor: 'crosshair', position: 'absolute', paddingRight: '5px', fontWeight: 'bold', pointerEvents: 'none', overflow: 'visible', userSelect: 'none', zIndex: 10, }; interface XYLabelPointerProps { layout: Get2DDimensionLayoutReturn; data1D: Spectrum1DTraces; } export default function XYLabelPointer(props: XYLabelPointerProps) { const { layout, data1D } = props; const position = useMouseTracker(); const { step } = useBrushTracker(); const { margin, width, height, yDomains, view: { spectra: { activeTab }, }, } = useChartData(); const activeSpectrum = useActiveSpectrum(); const trackID = position && getLayoutID(layout, { startX: position.x, startY: position.y, }); const nuclei = activeTab.split(','); const [formatX, formatY] = useFormatNumberByNucleus(nuclei); const scale2DX = useScale2DX(); const scale2DY = useScale2DY(); const hasTraces = data1D.x || data1D.y; const scaleX = useMemo(() => { if (!activeSpectrum || !hasTraces) { return scale2DX; } switch (trackID) { case LAYOUT.top: case LAYOUT.main: { return scale2DX; } case LAYOUT.left: { return scale2DY; } default: return null; } }, [activeSpectrum, hasTraces, scale2DX, scale2DY, trackID]); const scaleY = useMemo(() => { if (!activeSpectrum || !hasTraces) { return scale2DY; } switch (trackID) { case LAYOUT.main: { return scale2DY; } case LAYOUT.top: { return data1D.x ? get1DYScale(yDomains[data1D.x.id], margin.top) : null; } case LAYOUT.left: { return data1D.y ? get1DYScale(yDomains[data1D.y.id], margin.left) : null; } default: return null; } }, [ activeSpectrum, data1D.x, data1D.y, hasTraces, margin.left, margin.top, scale2DY, trackID, yDomains, ]); if ( step === 'brushing' || !position || position.y < margin.top || position.x < margin.left || position.x > width - margin.right || position.y > height - margin.bottom ) { return null; } const getXValue = (x = null) => { switch (trackID) { case LAYOUT.main: case LAYOUT.top: { return scaleX?.invert(x || position.x); } case LAYOUT.left: { return scaleX?.invert(x || position.y); } default: return 0; } }; const getYValue = () => { switch (trackID) { case LAYOUT.main: case LAYOUT.top: { return scaleY?.invert(position.y); } case LAYOUT.left: { return scaleY?.invert(position.x); } default: return 0; } }; return (