import type {
Range as RangeType,
Ranges as RangesType,
} from '@zakodium/nmr-types';
import type { Spectrum1D } from '@zakodium/nmrium-core';
import { memo } from 'react';
import { useChartData } from '../../context/ChartContext.js';
import { useScaleChecked } from '../../context/ScaleContext.js';
import { usePanelPreferences } from '../../hooks/usePanelPreferences.js';
import useSpectrum from '../../hooks/useSpectrum.js';
import { useTextMetrics } from '../../hooks/useTextMetrics.js';
import { stackOverlappingLabelsMap } from '../../utility/stackOverlappingLabels.js';
import Range from './Range.js';
interface RangesInnerProps {
selectedTool: string;
ranges: RangesType;
relativeFormat: string;
}
const labelSize = 14;
type ProcessedRange = RangeType & {
labelWidth: number;
startPosition: number;
signalId: string;
assignment: string;
};
function useStackRangesAssignmentsLabels(ranges: RangeType[]) {
const { scaleX } = useScaleChecked();
const { getTextWidth } = useTextMetrics({ labelSize });
if (ranges.length === 0) return null;
const processedRanges: ProcessedRange[] = [];
for (const range of ranges) {
const { from, signals } = range;
const startPosition = scaleX()(from);
for (const signal of signals) {
const { id, assignment = '' } = signal;
const labelWidth = getTextWidth(assignment);
processedRanges.push({
...range,
labelWidth,
startPosition,
signalId: id,
assignment,
});
}
}
processedRanges.sort((a, b) => b.startPosition - a.startPosition);
return stackOverlappingLabelsMap(processedRanges, {
startPositionKey: 'startPosition',
labelWidthKey: 'labelWidth',
padding: 0,
idKey: 'signalId',
});
}
function RangesInner({
ranges,
selectedTool,
relativeFormat,
}: RangesInnerProps) {
const assignmentLabelsStackIndexes = useStackRangesAssignmentsLabels(
ranges.values,
);
return (
{ranges.values.map((range) => (
))}
);
}
const MemoizedRanges = memo(RangesInner);
const emptyData = { ranges: {}, info: {}, display: {} };
export default function Ranges() {
const {
view: {
spectra: { activeTab },
},
toolOptions: { selectedTool },
} = useChartData();
const spectrum = useSpectrum(emptyData) as Spectrum1D;
const rangesPreferences = usePanelPreferences('ranges', activeTab);
if (
!spectrum.ranges?.values ||
!spectrum.display.isVisible ||
spectrum.info?.isFid
) {
return null;
}
return (
);
}