diff --git a/src/component/1d/Chart1D.tsx b/src/component/1d/Chart1D.tsx
index c5793a5f4..0ab20edbc 100644
--- a/src/component/1d/Chart1D.tsx
+++ b/src/component/1d/Chart1D.tsx
@@ -2,10 +2,10 @@ import FloatMoleculeStructures from '../tool/FloatMoleculeStructures';
import ApdoizationLine from './ApodizationLine';
import ExclusionZonesAnnotations from './ExclusionZonesAnnotations';
-import IntegralsSeries from './IntegralsSeries';
import LinesSeries from './LinesSeries';
import XAxis from './XAxis';
import DatabaseElements from './database/DatabaseElements';
+import IntegralsSeries from './integral/IntegralsSeries';
import JGraph from './jCouplingGraph/JGraph';
import MultiAnalysisRanges from './multiAnalysis/MultiAnalysisRanges';
import PeakAnnotations from './peaks/PeakAnnotations';
diff --git a/src/component/1d/IntegralResizable.tsx b/src/component/1d/IntegralResizable.tsx
deleted file mode 100644
index 2c355aa94..000000000
--- a/src/component/1d/IntegralResizable.tsx
+++ /dev/null
@@ -1,140 +0,0 @@
-/** @jsxImportSource @emotion/react */
-import { css } from '@emotion/react';
-import { useCallback } from 'react';
-
-import { useChartData } from '../context/ChartContext';
-import { useDispatch } from '../context/DispatchContext';
-import { useGlobal } from '../context/GlobalContext';
-import { useScaleChecked } from '../context/ScaleContext';
-import Resizer from '../elements/resizer/Resizer';
-import { HighlightEventSource, useHighlight } from '../highlight/index';
-import { RESIZE_INTEGRAL } from '../reducer/types/Types';
-import { options } from '../toolbar/ToolTypes';
-import { formatNumber } from '../utility/formatNumber';
-
-const stylesOnHover = css`
- pointer-events: bounding-box;
- @-moz-document url-prefix() {
- pointer-events: fill;
- }
- .highlight {
- fill: transparent;
- }
- .target {
- visibility: hidden;
- }
-`;
-
-const stylesHighlighted = css`
- pointer-events: bounding-box;
-
- @-moz-document url-prefix() {
- pointer-events: fill;
- }
- fill: #ff6f0057;
-
- .target {
- visibility: visible;
- }
-`;
-
-interface IntegralResizableProps {
- integralData: {
- id: string;
- from: number;
- to: number;
- integral?: number;
- };
- integralFormat: string;
-}
-
-function IntegralResizable({
- integralData,
- integralFormat,
-}: IntegralResizableProps) {
- const {
- height,
- margin,
- toolOptions: { selectedTool },
- } = useChartData();
- const { viewerRef } = useGlobal();
- const { scaleX } = useScaleChecked();
- const dispatch = useDispatch();
- const { id, integral } = integralData;
- const highlight = useHighlight([id], {
- type: HighlightEventSource.INTEGRAL,
- extra: { id },
- });
-
- const handleOnStopResizing = useCallback(
- (position) => {
- dispatch({
- type: RESIZE_INTEGRAL,
- payload: {
- data: {
- ...integralData,
- from: scaleX().invert(position.x2),
- to: scaleX().invert(position.x1),
- },
- },
- });
- },
- [dispatch, integralData, scaleX],
- );
-
- const handleOnEnterNotation = useCallback(() => {
- highlight.show();
- }, [highlight]);
-
- const handleOnMouseLeaveNotation = useCallback(() => {
- highlight.hide();
- }, [highlight]);
-
- const from = integralData.from ? scaleX()(integralData.from) : 0;
- const to = integralData.to ? scaleX()(integralData.to) : 0;
-
- return (
-
-
- {({ x1, x2 }, isActive) => (
-
-
-
- {integral !== undefined
- ? formatNumber(integral, integralFormat)
- : ''}
-
-
- )}
-
-
- );
-}
-
-export default IntegralResizable;
diff --git a/src/component/1d/Integral.tsx b/src/component/1d/integral/Integral.tsx
similarity index 86%
rename from src/component/1d/Integral.tsx
rename to src/component/1d/integral/Integral.tsx
index 4038fc61d..e42271f5d 100644
--- a/src/component/1d/Integral.tsx
+++ b/src/component/1d/integral/Integral.tsx
@@ -1,5 +1,5 @@
-import useIntegralPath from '../hooks/useIntegralPath';
-import { usePanelPreferences } from '../hooks/usePanelPreferences';
+import useIntegralPath from '../../hooks/useIntegralPath';
+import { usePanelPreferences } from '../../hooks/usePanelPreferences';
import IntegralResizable from './IntegralResizable';
diff --git a/src/component/1d/integral/IntegralIndicator.tsx b/src/component/1d/integral/IntegralIndicator.tsx
new file mode 100644
index 000000000..e46deaf1e
--- /dev/null
+++ b/src/component/1d/integral/IntegralIndicator.tsx
@@ -0,0 +1,48 @@
+import { CSSProperties } from 'react';
+
+import { useChartData } from '../../context/ChartContext';
+import { formatNumber } from '../../utility/formatNumber';
+
+interface IntegralIndicatorProps {
+ value: number | undefined;
+ format: string;
+ width: number;
+ opacity?: number;
+}
+
+const styles: Record<'text' | 'path', CSSProperties> = {
+ text: {
+ fontSize: '11px',
+ textAnchor: 'middle',
+ dominantBaseline: 'middle',
+ writingMode: 'vertical-rl',
+ fill: 'black',
+ },
+ path: {
+ fill: 'none',
+ strokeWidth: '1px',
+ shapeRendering: 'crispEdges',
+ stroke: 'black',
+ },
+};
+
+export function IntegralIndicator(props: IntegralIndicatorProps) {
+ const { value, width, format, opacity = 1 } = props;
+ const { height, margin } = useChartData();
+
+ const bottom = height - margin.bottom;
+
+ return (
+
+
+ {value ? formatNumber(value, format) : ''}
+
+
+
+ );
+}
diff --git a/src/component/1d/integral/IntegralResizable.tsx b/src/component/1d/integral/IntegralResizable.tsx
new file mode 100644
index 000000000..ecc11a703
--- /dev/null
+++ b/src/component/1d/integral/IntegralResizable.tsx
@@ -0,0 +1,130 @@
+/** @jsxImportSource @emotion/react */
+import { css } from '@emotion/react';
+
+import { useChartData } from '../../context/ChartContext';
+import { useDispatch } from '../../context/DispatchContext';
+import { useGlobal } from '../../context/GlobalContext';
+import { useScaleChecked } from '../../context/ScaleContext';
+import Resizer from '../../elements/resizer/Resizer';
+import { HighlightEventSource, useHighlight } from '../../highlight/index';
+import { RESIZE_INTEGRAL } from '../../reducer/types/Types';
+import { options } from '../../toolbar/ToolTypes';
+
+import { IntegralIndicator } from './IntegralIndicator';
+
+const stylesOnHover = css`
+ pointer-events: bounding-box;
+ @-moz-document url-prefix() {
+ pointer-events: fill;
+ }
+ .highlight {
+ fill: transparent;
+ }
+ .target {
+ visibility: hidden;
+ }
+`;
+
+const stylesHighlighted = css`
+ pointer-events: bounding-box;
+
+ @-moz-document url-prefix() {
+ pointer-events: fill;
+ }
+ fill: #ff6f0057;
+
+ .target {
+ visibility: visible;
+ }
+`;
+
+interface IntegralResizableProps {
+ integralData: {
+ id: string;
+ from: number;
+ to: number;
+ integral?: number;
+ };
+ integralFormat: string;
+}
+
+function IntegralResizable({
+ integralData,
+ integralFormat,
+}: IntegralResizableProps) {
+ const {
+ height,
+ margin,
+ toolOptions: { selectedTool },
+ } = useChartData();
+ const { viewerRef } = useGlobal();
+ const { scaleX } = useScaleChecked();
+ const dispatch = useDispatch();
+ const { id, integral } = integralData;
+ const highlight = useHighlight([id], {
+ type: HighlightEventSource.INTEGRAL,
+ extra: { id },
+ });
+
+ function handleOnStopResizing(position) {
+ dispatch({
+ type: RESIZE_INTEGRAL,
+ payload: {
+ data: {
+ ...integralData,
+ from: scaleX().invert(position.x2),
+ to: scaleX().invert(position.x1),
+ },
+ },
+ });
+ }
+
+ const from = integralData.from ? scaleX()(integralData.from) : 0;
+ const to = integralData.to ? scaleX()(integralData.to) : 0;
+
+ const bottom = height - margin.bottom;
+
+ return (
+ highlight.show()}
+ onMouseLeave={() => highlight.hide()}
+ >
+
+ {({ x1, x2 }, isActive) => {
+ const width = x2 - x1;
+
+ return (
+
+
+
+
+ );
+ }}
+
+
+ );
+}
+
+export default IntegralResizable;
diff --git a/src/component/1d/IntegralsSeries.tsx b/src/component/1d/integral/IntegralsSeries.tsx
similarity index 85%
rename from src/component/1d/IntegralsSeries.tsx
rename to src/component/1d/integral/IntegralsSeries.tsx
index b6daec0b5..68bf05985 100644
--- a/src/component/1d/IntegralsSeries.tsx
+++ b/src/component/1d/integral/IntegralsSeries.tsx
@@ -1,8 +1,8 @@
import { useMemo } from 'react';
-import { isSpectrum1D } from '../../data/data1d/Spectrum1D';
-import { useChartData } from '../context/ChartContext';
-import { useActiveSpectrum } from '../reducer/Reducer';
+import { isSpectrum1D } from '../../../data/data1d/Spectrum1D';
+import { useChartData } from '../../context/ChartContext';
+import { useActiveSpectrum } from '../../reducer/Reducer';
import Integral from './Integral';
diff --git a/src/component/1d/ranges/Range.tsx b/src/component/1d/ranges/Range.tsx
index 3408d0c9c..be8229674 100644
--- a/src/component/1d/ranges/Range.tsx
+++ b/src/component/1d/ranges/Range.tsx
@@ -1,6 +1,5 @@
/** @jsxImportSource @emotion/react */
import { css } from '@emotion/react';
-import { useCallback, useState, useEffect } from 'react';
import { Signal1D } from '../../../data/types/data1d';
import { checkRangeKind } from '../../../data/utilities/RangeUtilities';
@@ -16,7 +15,7 @@ import Resizer from '../../elements/resizer/Resizer';
import { HighlightEventSource, useHighlight } from '../../highlight';
import { RESIZE_RANGE } from '../../reducer/types/Types';
import { options } from '../../toolbar/ToolTypes';
-import { formatNumber } from '../../utility/formatNumber';
+import { IntegralIndicator } from '../integral/IntegralIndicator';
import MultiplicityTree from '../multiplicityTree/MultiplicityTree';
const stylesOnHover = css`
@@ -24,11 +23,10 @@ const stylesOnHover = css`
@-moz-document url-prefix() {
pointer-events: fill;
}
- user-select: 'none';
- -webkit-user-select: none; /* Chrome all / Safari all */
- -moz-user-select: none; /* Firefox all */
-
- .delete-button {
+ .highlight {
+ fill: transparent;
+ }
+ .target {
visibility: hidden;
}
`;
@@ -39,13 +37,10 @@ const stylesHighlighted = css`
@-moz-document url-prefix() {
pointer-events: fill;
}
- .range-area {
- height: 100%;
- fill: #ff6f0057;
- }
- .delete-button {
+ fill: #ff6f0057;
+
+ .target {
visibility: visible;
- cursor: pointer;
}
`;
@@ -87,59 +82,44 @@ function Range({
const { scaleX } = useScaleChecked();
const dispatch = useDispatch();
- const [reduceOpacity, setReduceOpacity] = useState(false);
- const [isBlockedByEditing, setIsBlockedByEditing] = useState(false);
-
- useEffect(() => {
- if (selectedTool && selectedTool === options.editRange.id) {
- setIsBlockedByEditing(true);
- } else {
- setIsBlockedByEditing(false);
- }
- }, [selectedTool]);
-
- useEffect(() => {
- setReduceOpacity(!checkRangeKind(rangeData));
- }, [rangeData]);
-
- const handleOnStopResizing = useCallback(
- (position) => {
- dispatch({
- type: RESIZE_RANGE,
- data: {
- ...rangeData,
- from: scaleX().invert(position.x2),
- to: scaleX().invert(position.x1),
- },
- });
- },
- [dispatch, rangeData, scaleX],
- );
+ const isBlockedByEditing =
+ selectedTool && selectedTool === options.editRange.id;
+
+ function handleOnStopResizing(position) {
+ dispatch({
+ type: RESIZE_RANGE,
+ data: {
+ ...rangeData,
+ from: scaleX().invert(position.x2),
+ to: scaleX().invert(position.x1),
+ },
+ });
+ }
- const mouseEnterHandler = useCallback(() => {
+ function mouseEnterHandler() {
assignmentRange.show('x');
highlightRange.show();
- }, [assignmentRange, highlightRange]);
+ }
- const mouseLeaveHandler = useCallback(() => {
+ function mouseLeaveHandler() {
assignmentRange.hide();
highlightRange.hide();
- }, [assignmentRange, highlightRange]);
-
- const assignHandler = useCallback(
- (e) => {
- if (
- selectedTool === options.rangePicking.id &&
- e.shiftKey &&
- !isBlockedByEditing
- ) {
- assignmentRange.setActive('x');
- }
- },
- [assignmentRange, isBlockedByEditing, selectedTool],
- );
+ }
+
+ function assignHandler(e) {
+ if (
+ selectedTool === options.rangePicking.id &&
+ e.shiftKey &&
+ !isBlockedByEditing
+ ) {
+ assignmentRange.setActive('x');
+ }
+ }
const from = scaleX()(rangeData.from);
const to = scaleX()(rangeData.to);
+
+ const isNotSignal = !checkRangeKind(rangeData);
+
return (
- {({ x1, x2 }, isActive) => (
-
-
- {
+ const width = x2 - x1;
+ return (
+
- {integration !== undefined
- ? formatNumber(integration, relativeFormat)
- : ''}
-
-
- )}
+
+
+
+ );
+ }}
{showMultiplicityTrees &&
diff --git a/src/component/1d/utilities/scale.ts b/src/component/1d/utilities/scale.ts
index a55dedc42..f927e01a3 100644
--- a/src/component/1d/utilities/scale.ts
+++ b/src/component/1d/utilities/scale.ts
@@ -13,8 +13,8 @@ function getYScale(state, spectrumId: number | null | string = null) {
const { height, margin, verticalAlign, yDomain, yDomains } = state;
const _height =
verticalAlign.align === 'center'
- ? (height - 30) / 2
- : height - margin.bottom - 30;
+ ? (height - 40) / 2
+ : height - margin.bottom - 40;
let domainY: [number, number] | [] = [];
if (spectrumId === null || yDomains[spectrumId] === undefined) {
domainY = [0, yDomain[1]];
diff --git a/src/component/reducer/Reducer.ts b/src/component/reducer/Reducer.ts
index 145204524..2f2c0888d 100644
--- a/src/component/reducer/Reducer.ts
+++ b/src/component/reducer/Reducer.ts
@@ -153,7 +153,7 @@ export const getInitialState = (): State => ({
margin: {
top: 10,
right: 20,
- bottom: 70,
+ bottom: 50,
left: 0,
},
mode: 'RTL',
diff --git a/src/component/reducer/core/Constants.ts b/src/component/reducer/core/Constants.ts
index 424355163..a66189c4a 100644
--- a/src/component/reducer/core/Constants.ts
+++ b/src/component/reducer/core/Constants.ts
@@ -10,7 +10,7 @@ export const MARGIN = {
'1D': {
top: 10,
right: 10,
- bottom: 70,
+ bottom: 50,
left: 10,
},
};
diff --git a/test-e2e/panels/integral.test.ts b/test-e2e/panels/integral.test.ts
index 05dbd7cf6..5e9a6dbf1 100644
--- a/test-e2e/panels/integral.test.ts
+++ b/test-e2e/panels/integral.test.ts
@@ -17,7 +17,7 @@ async function addIntegral(
// Should have integral with at least 1000 points
const path = (await nmrium.page.getAttribute(
- `_react=Integral >> nth=${childIndex} >> path`,
+ `_react=Integral >> nth=${childIndex} >> path >> nth=0`,
'd',
)) as string;
expect(path.length).toBeGreaterThan(1000);
@@ -46,7 +46,7 @@ async function resizeIntegral(nmrium: NmriumPage) {
await nmrium.page.mouse.up();
const path = (await nmrium.page.getAttribute(
- '_react=Integral >> nth=0 >> path',
+ '_react=Integral >> nth=0 >> path >> nth=0',
'd',
)) as string;