import type { Spectrum1D } from '@zakodium/nmrium-core'; import { extent } from 'd3-array'; import throttle from 'lodash/throttle.js'; import { useCallback, useContext, useEffect, useRef, useState } from 'react'; import { useChartData } from '../../context/ChartContext.js'; import { useCore } from '../../context/CoreContext.js'; import { useScaleChecked } from '../../context/ScaleContext.js'; import { useToaster } from '../../context/ToasterContext.js'; import { useHighlightData } from '../../highlight/index.js'; import { usePanelPreferences } from '../../hooks/usePanelPreferences.js'; import { spinnerContext } from '../../loader/SpinnerContext.js'; import { PathBuilder } from '../../utility/PathBuilder.js'; import { getYScaleWithRation } from '../utilities/scale.js'; function DatabaseSpectrum() { const { height, margin } = useChartData(); const [path, setPath] = useState(); const [isLoading, setLoading] = useState(false); const { highlight } = useHighlightData(); const { scaleX, spectraBottomMargin } = useScaleChecked(); const toaster = useToaster(); const { color, marginBottom } = usePanelPreferences('database'); const { jcampURL: jcampRelativeURL = '', baseURL } = highlight?.sourceData?.extra || {}; const getSpinner = useContext(spinnerContext); const scaleY = useCallback( (yDomain: number[]) => getYScaleWithRation({ yDomain, height, margin: { ...margin, bottom: margin.bottom + marginBottom, top: margin.top, }, scaleRatio: 1, spectraBottomMargin, }), [height, margin, marginBottom, spectraBottomMargin], ); const core = useCore(); const loadSpectrum = useRef( throttle(async (baseURL: string | undefined, jcampRelativeURL: string) => { try { setLoading(true); const url = new URL(jcampRelativeURL, baseURL); const { state: { data }, } = await core.readFromWebSource({ entries: [{ relativePath: url.pathname, baseURL: url.origin }], }); setLoading(false); const spectrum = data?.spectra?.[0] || null; if (spectrum) { const pathBuilder = new PathBuilder(); const { x, re: y } = (spectrum as Spectrum1D).data; const yDomain = extent(y) as number[]; const finalScaleX = scaleX(); const finalScaleY = scaleY(yDomain); pathBuilder.moveTo(finalScaleX(x[0]), finalScaleY(y[0])); for (let i = 1; i < x.length; i++) { pathBuilder.lineTo(finalScaleX(x[i]), finalScaleY(y[i])); } setPath(pathBuilder.toString()); } } catch (error) { reportError(error); toaster.show({ message: 'Failed to Load spectrum', intent: 'danger' }); } }, 250), ); useEffect(() => { void loadSpectrum.current(baseURL, jcampRelativeURL); }, [baseURL, jcampRelativeURL, loadSpectrum]); if (highlight.sourceData?.type !== 'DATABASE') { return null; } return isLoading ? ( {getSpinner('Load Jcamp ....')} ) : ( ); } export default DatabaseSpectrum;