diff --git a/.storybook/main.js b/.storybook/main.js
index 14101545..92f8381d 100644
--- a/.storybook/main.js
+++ b/.storybook/main.js
@@ -1,18 +1,7 @@
export default {
stories: ['../stories/**/*.stories.@(js|jsx|ts|tsx)'],
- addons: [
- {
- name: '@storybook/addon-storysource',
- options: {
- loaderOptions: {
- injectStoryParameters: false,
- },
- },
- },
- '@storybook/addon-links',
- '@storybook/addon-essentials',
- ],
+ addons: ['@storybook/addon-links', '@storybook/addon-docs'],
staticDirs: ['../stories/data'],
diff --git a/.storybook/preview.js b/.storybook/preview.js
index 5cec7488..7b5636bc 100644
--- a/.storybook/preview.js
+++ b/.storybook/preview.js
@@ -3,5 +3,8 @@ import './stories.css';
export const parameters = {
controls: { expanded: true, hideNoControlsWarning: true },
+ docs: {
+ codePanel: true,
+ },
};
export const tags = ['autodocs'];
diff --git a/README.md b/README.md
index 5381a04e..e3259616 100644
--- a/README.md
+++ b/README.md
@@ -1,23 +1,21 @@
-# react-plot
-
-Library of React components to render SVG 2D plots.
-
-Check our exhaustive [documentation here](https://react-plot.zakodium.com/).
-
-
-
Maintained by Zakodium
+
+
+# react-plot
-[![NPM version][npm-image]][npm-url]
-[![npm download][download-image]][download-url]
+[](https://www.npmjs.com/package/react-plot)
+[](https://www.npmjs.com/package/react-plot)
+[](https://github.com/zakodium-oss/react-plot/blob/main/LICENSE)
-
+Library of React components to render SVG 2D plots.
+
+Check our exhaustive [documentation here](https://react-plot.zakodium.com/).
## [Storybook](https://react-plot.pages.dev/)
@@ -111,8 +109,3 @@ function Example() {
## License
[MIT](./LICENSE)
-
-[npm-image]: https://img.shields.io/npm/v/react-plot.svg?style=flat-square
-[npm-url]: https://www.npmjs.com/package/react-plot
-[download-image]: https://img.shields.io/npm/dm/react-plot.svg?style=flat-square
-[download-url]: https://www.npmjs.com/package/react-plot
diff --git a/eslint.config.js b/eslint.config.js
index 7e66236d..a5236cae 100644
--- a/eslint.config.js
+++ b/eslint.config.js
@@ -1,14 +1,19 @@
+import { defineConfig, globalIgnores } from 'eslint/config';
import react from 'eslint-config-zakodium/react';
import ts from 'eslint-config-zakodium/ts';
import unicorn from 'eslint-config-zakodium/unicorn';
+import storybook from 'eslint-plugin-storybook';
-export default [
- {
- ignores: ['lib', 'node_modules', 'playwright/.cache', 'storybook-static'],
- },
- ...ts,
- ...react,
- ...unicorn,
+export default defineConfig(
+ globalIgnores([
+ 'lib',
+ 'node_modules',
+ 'playwright/.cache',
+ 'storybook-static',
+ ]),
+ ts,
+ react,
+ unicorn,
{
rules: {
'@typescript-eslint/no-dynamic-delete': 'off',
@@ -21,4 +26,5 @@ export default [
'@typescript-eslint/unbound-method': 'off',
},
},
-];
+ ...storybook.configs['flat/recommended'],
+);
diff --git a/package.json b/package.json
index 15742027..e9f7d57a 100644
--- a/package.json
+++ b/package.json
@@ -52,38 +52,39 @@
"react": ">=18.0.0"
},
"devDependencies": {
- "@playwright/experimental-ct-react": "^1.48.0",
+ "@playwright/experimental-ct-react": "^1.53.0",
"@simbathesailor/use-what-changed": "^2.0.0",
- "@storybook/addon-essentials": "^8.3.5",
- "@storybook/addon-links": "^8.3.5",
- "@storybook/addon-storysource": "^8.3.5",
- "@storybook/react": "^8.3.5",
- "@storybook/react-vite": "^8.3.5",
+ "@storybook/addon-docs": "^9.0.8",
+ "@storybook/addon-links": "^9.0.8",
+ "@storybook/react-vite": "^9.0.8",
"@types/d3-array": "^3.2.1",
- "@types/d3-scale": "^4.0.8",
- "@types/d3-scale-chromatic": "^3.0.3",
- "@types/d3-shape": "^3.1.6",
+ "@types/d3-scale": "^4.0.9",
+ "@types/d3-scale-chromatic": "^3.1.0",
+ "@types/d3-shape": "^3.1.7",
"@types/node": "^22.7.5",
"@types/point-in-polygon": "^1.1.5",
- "@types/react": "^18.3.11",
- "@types/react-dom": "^18.3.1",
- "eslint": "^9.12.0",
- "eslint-config-zakodium": "^13.0.0",
- "isotopic-distribution": "^3.3.2",
+ "@types/react": "^19.1.8",
+ "@types/react-dom": "^19.1.6",
+ "@zakodium/tsconfig": "^1.0.1",
+ "eslint": "^9.28.0",
+ "eslint-config-zakodium": "^15.0.1",
+ "eslint-plugin-storybook": "^9.0.8",
+ "isotopic-distribution": "^3.4.14",
"iv-analysis": "^0.4.0",
"ml-dataset-iris": "^1.2.1",
"ml-directional-distribution": "^0.1.1",
"ml-pca": "^4.1.1",
"ml-regression-simple-linear": "^3.0.1",
- "ml-spectra-processing": "^14.6.0",
- "ms-spectrum": "^3.6.7",
+ "ml-spectra-processing": "^14.12.0",
+ "ms-spectrum": "^3.9.0",
"point-in-polygon": "^1.1.0",
- "prettier": "^3.3.3",
- "react": "^18.3.1",
- "react-dom": "^18.3.1",
- "react-error-boundary": "^4.0.13",
+ "prettier": "^3.5.3",
+ "react": "^19.1.0",
+ "react-dom": "^19.1.0",
+ "react-error-boundary": "^6.0.0",
"rimraf": "^6.0.1",
- "typescript": "^5.6.3"
+ "storybook": "^9.0.8",
+ "typescript": "^5.8.3"
},
"dependencies": {
"d3-array": "^3.2.4",
@@ -92,9 +93,9 @@
"d3-shape": "^3.2.0",
"immer": "^10.1.1",
"ml-distance-euclidean": "^2.0.0",
- "react-d3-utils": "^2.0.0"
+ "react-d3-utils": "^3.1.0"
},
"volta": {
- "node": "22.9.0"
+ "node": "22.16.0"
}
}
diff --git a/src/components/Annotations/Annotations.tsx b/src/components/Annotations/Annotations.tsx
index b6f97775..f5b76f42 100644
--- a/src/components/Annotations/Annotations.tsx
+++ b/src/components/Annotations/Annotations.tsx
@@ -1,4 +1,4 @@
-import { type ReactElement, type ReactNode } from 'react';
+import type { ReactElement, ReactNode } from 'react';
export interface AnnotationsProps {
children: ReactNode;
diff --git a/src/components/Annotations/Group.tsx b/src/components/Annotations/Group.tsx
index 18806788..de97bb23 100644
--- a/src/components/Annotations/Group.tsx
+++ b/src/components/Annotations/Group.tsx
@@ -1,5 +1,6 @@
import type { CSSProperties, ReactNode } from 'react';
-import { type Align, AlignGroup } from 'react-d3-utils';
+import type { Align } from 'react-d3-utils';
+import { AlignGroup } from 'react-d3-utils';
import { usePosition } from '../../hooks.js';
import type { ScalarValue } from '../../types.js';
diff --git a/src/components/Axis/Axis.tsx b/src/components/Axis/Axis.tsx
index 6b0bbc44..2f8b8fdf 100644
--- a/src/components/Axis/Axis.tsx
+++ b/src/components/Axis/Axis.tsx
@@ -1,5 +1,6 @@
import type { ScaleLinear, ScaleLogarithmic, ScaleTime } from 'd3-scale';
-import { type CSSProperties, type ReactNode, useEffect } from 'react';
+import type { CSSProperties, ReactNode } from 'react';
+import { useEffect } from 'react';
import {
usePlotContext,
diff --git a/src/components/Axis/HorizontalAxis.tsx b/src/components/Axis/HorizontalAxis.tsx
index 01420630..c4978ad3 100644
--- a/src/components/Axis/HorizontalAxis.tsx
+++ b/src/components/Axis/HorizontalAxis.tsx
@@ -79,12 +79,14 @@ export default function HorizontalAxis(props: AxisRendererProps) {
y2: y,
textPosition: textOffset + tickLength,
};
- default:
+ case undefined:
return {
y1: 0,
y: 0,
textPosition: 0,
};
+ default:
+ throw new Error(`Invalid tick position ${String(tickPosition)}`);
}
}
const gridLinesElement =
diff --git a/src/components/Axis/HorizontalAxisGridLines.tsx b/src/components/Axis/HorizontalAxisGridLines.tsx
index 06a1226c..a4b7202e 100644
--- a/src/components/Axis/HorizontalAxisGridLines.tsx
+++ b/src/components/Axis/HorizontalAxisGridLines.tsx
@@ -1,4 +1,5 @@
-import { type CSSProperties, type ReactElement, useMemo } from 'react';
+import type { CSSProperties, ReactElement } from 'react';
+import { useMemo } from 'react';
import type { Position } from '../../types.js';
diff --git a/src/components/Axis/HorizontalAxisLabel.tsx b/src/components/Axis/HorizontalAxisLabel.tsx
index f652c146..8609f4bc 100644
--- a/src/components/Axis/HorizontalAxisLabel.tsx
+++ b/src/components/Axis/HorizontalAxisLabel.tsx
@@ -1,5 +1,6 @@
import type { CSSProperties, ReactNode } from 'react';
-import { type Align, AlignGroup } from 'react-d3-utils';
+import type { Align } from 'react-d3-utils';
+import { AlignGroup } from 'react-d3-utils';
interface HorizontalAxisLabelProps {
plotWidth: number;
diff --git a/src/components/Axis/LinearAxis.tsx b/src/components/Axis/LinearAxis.tsx
index 87f21c35..0f1c32b2 100644
--- a/src/components/Axis/LinearAxis.tsx
+++ b/src/components/Axis/LinearAxis.tsx
@@ -18,9 +18,14 @@ function LinearAxis(props: LinearAxisProps) {
const direction =
position === 'left' || position === 'right' ? 'vertical' : 'horizontal';
- const primaryTicks = useLinearPrimaryTicks(scale, direction, axisRef, {
- tickFormat: tickLabelFormat,
- });
+ const { ticks: primaryTicks } = useLinearPrimaryTicks(
+ scale,
+ direction,
+ axisRef,
+ {
+ tickFormat: tickLabelFormat,
+ },
+ );
const AxisComponent =
direction === 'vertical' ? VerticalAxis : HorizontalAxis;
diff --git a/src/components/Axis/Ticks.tsx b/src/components/Axis/Ticks.tsx
index 439ccd9f..625b80a2 100644
--- a/src/components/Axis/Ticks.tsx
+++ b/src/components/Axis/Ticks.tsx
@@ -1,8 +1,8 @@
-import {
- type CSSProperties,
- type ReactElement,
- type ReactNode,
- type SVGAttributes,
+import type {
+ CSSProperties,
+ ReactElement,
+ ReactNode,
+ SVGAttributes,
} from 'react';
import type { Scales, TicksType } from './types.js';
diff --git a/src/components/Axis/TimeAxis.tsx b/src/components/Axis/TimeAxis.tsx
index f5f997b6..78d87aac 100644
--- a/src/components/Axis/TimeAxis.tsx
+++ b/src/components/Axis/TimeAxis.tsx
@@ -18,7 +18,7 @@ function TimeAxis(props: TimeAxisProps) {
const direction =
position === 'left' || position === 'right' ? 'vertical' : 'horizontal';
- const primaryTicks = useTimeTicks(scale, direction, axisRef, {
+ const { ticks: primaryTicks } = useTimeTicks(scale, direction, axisRef, {
tickFormat: tickLabelFormat,
});
diff --git a/src/components/Axis/VerticalAxis.tsx b/src/components/Axis/VerticalAxis.tsx
index b243e4a4..6454da03 100644
--- a/src/components/Axis/VerticalAxis.tsx
+++ b/src/components/Axis/VerticalAxis.tsx
@@ -76,12 +76,14 @@ export default function VerticalAxis(props: AxisRendererProps) {
x2: x,
textPosition: textOffset + tickLength,
};
- default:
+ case undefined:
return {
x1: 0,
x2: 0,
textPosition: 3,
};
+ default:
+ throw new Error(`Invalid tick position ${String(tickPosition)}`);
}
}
const gridLinesElement =
diff --git a/src/components/Axis/VerticalAxisGridLines.tsx b/src/components/Axis/VerticalAxisGridLines.tsx
index 98110034..6c352335 100644
--- a/src/components/Axis/VerticalAxisGridLines.tsx
+++ b/src/components/Axis/VerticalAxisGridLines.tsx
@@ -1,4 +1,5 @@
-import { type CSSProperties, type ReactElement, useMemo } from 'react';
+import type { CSSProperties, ReactElement } from 'react';
+import { useMemo } from 'react';
import type { Position } from '../../types.js';
diff --git a/src/components/Axis/VerticalAxisLabel.tsx b/src/components/Axis/VerticalAxisLabel.tsx
index a14bbae2..6cbd8318 100644
--- a/src/components/Axis/VerticalAxisLabel.tsx
+++ b/src/components/Axis/VerticalAxisLabel.tsx
@@ -1,5 +1,6 @@
import type { CSSProperties, ReactNode } from 'react';
-import { type Align, AlignGroup } from 'react-d3-utils';
+import type { Align } from 'react-d3-utils';
+import { AlignGroup } from 'react-d3-utils';
import VerticalText from '../VerticalText.js';
diff --git a/src/components/Axis/types.ts b/src/components/Axis/types.ts
index 848a3f8f..35fc45fe 100644
--- a/src/components/Axis/types.ts
+++ b/src/components/Axis/types.ts
@@ -1,10 +1,6 @@
import type { ScaleLinear, ScaleLogarithmic, ScaleTime } from 'd3-scale';
import type { CSSProperties, ReactNode, Ref } from 'react';
-import type {
- PrimaryLinearTicks,
- PrimaryLogTicks,
- TimeTicks,
-} from 'react-d3-utils';
+import type { Tick } from 'react-d3-utils';
import type { Position, TickLabelFormat, TickPosition } from '../../types.js';
@@ -44,4 +40,4 @@ export interface AxisChildProps extends AxisCommonProps {
tickLabelFormat?: TickLabelFormat;
}
-export type TicksType = PrimaryLinearTicks | PrimaryLogTicks | TimeTicks;
+export type TicksType = Tick | Tick;
diff --git a/src/components/ErrorBars.tsx b/src/components/ErrorBars.tsx
index a5b9029e..43951961 100644
--- a/src/components/ErrorBars.tsx
+++ b/src/components/ErrorBars.tsx
@@ -1,4 +1,5 @@
-import { type SVGAttributes, useMemo } from 'react';
+import type { SVGAttributes } from 'react';
+import { useMemo } from 'react';
import { usePlotContext } from '../contexts/plotContext.js';
import type { SeriesPointWithError } from '../types.js';
diff --git a/src/components/Heading.tsx b/src/components/Heading.tsx
index 8a05828d..d2631a5a 100644
--- a/src/components/Heading.tsx
+++ b/src/components/Heading.tsx
@@ -1,4 +1,5 @@
-import { type CSSProperties, useEffect } from 'react';
+import type { CSSProperties } from 'react';
+import { useEffect } from 'react';
import { AlignGroup, useBBoxObserver } from 'react-d3-utils';
import {
diff --git a/src/components/Legend.tsx b/src/components/Legend.tsx
index 59053bd9..4262271f 100644
--- a/src/components/Legend.tsx
+++ b/src/components/Legend.tsx
@@ -1,6 +1,8 @@
/* eslint-disable react/no-array-index-key */
-import { type CSSProperties, useContext, useEffect, useMemo } from 'react';
-import { AlignGroup, type AlignGroupProps } from 'react-d3-utils';
+import type { CSSProperties } from 'react';
+import { useContext, useEffect, useMemo } from 'react';
+import type { AlignGroupProps } from 'react-d3-utils';
+import { AlignGroup } from 'react-d3-utils';
import { useLegend } from '../contexts/legendContext.js';
import { legendOffsetContext } from '../contexts/legendOffsetContext.js';
@@ -13,7 +15,7 @@ import { functionalStyle } from '../utils.js';
import { markersMap } from './Markers.map.js';
-type Positions = { [K in Position]?: number };
+type Positions = Partial>;
interface ValidatedPosition {
key?: Position;
@@ -121,7 +123,7 @@ export type LegendProps = {
labelStyle?: CSSFuncProps<{ id: string }>;
lineStyle?: CSSFuncProps<{ id: string }>;
showHide?: boolean;
-} & { [K in Position]?: number };
+} & Partial>;
export function Legend(options: LegendProps) {
const {
diff --git a/src/components/Plot.tsx b/src/components/Plot.tsx
index 07c2e6d0..e61f40f2 100644
--- a/src/components/Plot.tsx
+++ b/src/components/Plot.tsx
@@ -1,24 +1,20 @@
import { scaleOrdinal } from 'd3-scale';
import { schemeSet1 } from 'd3-scale-chromatic';
import { produce } from 'immer';
-import {
- type CSSProperties,
- type ReactNode,
- type Reducer,
- useEffect,
- useMemo,
- useReducer,
-} from 'react';
+import type { CSSProperties, ReactNode, Reducer } from 'react';
+import { useEffect, useMemo, useReducer } from 'react';
import { useBBoxObserver } from 'react-d3-utils';
import { LegendProvider } from '../contexts/legendContext.provider.js';
+import type {
+ PlotContext,
+ PlotReducerActions,
+ PlotState,
+} from '../contexts/plotContext.js';
import {
- type PlotContext,
plotContext,
plotDispatchContext,
plotReducer,
- type PlotReducerActions,
- type PlotState,
useAxisContext,
} from '../contexts/plotContext.js';
import {
@@ -122,7 +118,7 @@ export function Plot(props: PlotProps) {
} = props;
const plotId = useId(undefined, 'plot');
- const [state, dispatch] = useReducer(reducerCurr, initialState, undefined);
+ const [state, dispatch] = useReducer(reducerCurr, initialState);
const {
series,
diff --git a/src/components/PlotObject.tsx b/src/components/PlotObject.tsx
index e9e3c93c..008be5b3 100644
--- a/src/components/PlotObject.tsx
+++ b/src/components/PlotObject.tsx
@@ -3,27 +3,29 @@ import type { CSSProperties, ReactNode } from 'react';
import type { Margins } from '../types.js';
-import {
- Annotation,
- type AnnotationArrowProps,
- type AnnotationCircleProps,
- type AnnotationEllipseProps,
- type AnnotationGroupProps,
- type AnnotationLineProps,
- type AnnotationRectangleProps,
- Annotations,
- type AnnotationShapeProps,
- type AnnotationTextProps,
+import type {
+ AnnotationArrowProps,
+ AnnotationCircleProps,
+ AnnotationEllipseProps,
+ AnnotationGroupProps,
+ AnnotationLineProps,
+ AnnotationRectangleProps,
+ AnnotationShapeProps,
+ AnnotationTextProps,
} from './Annotations/index.js';
-import { Axis, type AxisProps } from './Axis/Axis.js';
-import { ParallelAxis, type ParallelAxisProps } from './Axis/ParallelAxis.js';
-import { Legend, type LegendProps } from './Legend.js';
-import { Plot, type PlotProps } from './Plot.js';
-import { LineSeries, type LineSeriesProps } from './Series/LineSeries.js';
-import {
- ScatterSeries,
- type ScatterSeriesProps,
-} from './Series/ScatterSeries.js';
+import { Annotation, Annotations } from './Annotations/index.js';
+import type { AxisProps } from './Axis/Axis.js';
+import { Axis } from './Axis/Axis.js';
+import type { ParallelAxisProps } from './Axis/ParallelAxis.js';
+import { ParallelAxis } from './Axis/ParallelAxis.js';
+import type { LegendProps } from './Legend.js';
+import { Legend } from './Legend.js';
+import type { PlotProps } from './Plot.js';
+import { Plot } from './Plot.js';
+import type { LineSeriesProps } from './Series/LineSeries.js';
+import { LineSeries } from './Series/LineSeries.js';
+import type { ScatterSeriesProps } from './Series/ScatterSeries.js';
+import { ScatterSeries } from './Series/ScatterSeries.js';
export type PlotObjectAnnotations =
// This for each annotation option
diff --git a/src/components/Series/BarSeries.tsx b/src/components/Series/BarSeries.tsx
index 117165dd..c31ae672 100644
--- a/src/components/Series/BarSeries.tsx
+++ b/src/components/Series/BarSeries.tsx
@@ -1,4 +1,5 @@
-import { type CSSProperties, useEffect, useMemo } from 'react';
+import type { CSSProperties } from 'react';
+import { useEffect, useMemo } from 'react';
import { useLegend } from '../../contexts/legendContext.js';
import { usePlotContext } from '../../contexts/plotContext.js';
@@ -76,6 +77,7 @@ export function BarSeries(props: BarSeriesProps) {
return () =>
legendDispatch({ type: 'REMOVE_LEGEND_LABEL', payload: { id } });
}
+ return undefined;
}, [colorLine, legendDispatch, label, shape, id, hidden]);
if (hidden) return null;
return (
diff --git a/src/components/Series/LineSeries.tsx b/src/components/Series/LineSeries.tsx
index 941d18c0..a91e2cf9 100644
--- a/src/components/Series/LineSeries.tsx
+++ b/src/components/Series/LineSeries.tsx
@@ -1,5 +1,6 @@
import { line } from 'd3-shape';
-import { type CSSProperties, memo, useEffect, useMemo } from 'react';
+import type { CSSProperties } from 'react';
+import { memo, useEffect, useMemo } from 'react';
import { useLegend } from '../../contexts/legendContext.js';
import { usePlotContext } from '../../contexts/plotContext.js';
@@ -7,7 +8,8 @@ import { useIsSeriesVisible, useShift } from '../../hooks.js';
import type { CSSFuncProps, SeriesPoint, Shape } from '../../types.js';
import { functionalStyle, useId, validateAxis } from '../../utils.js';
-import { ScatterSeries, type ScatterSeriesProps } from './ScatterSeries.js';
+import type { ScatterSeriesProps } from './ScatterSeries.js';
+import { ScatterSeries } from './ScatterSeries.js';
export interface LineSeriesProps
extends Omit<
@@ -69,6 +71,7 @@ function LineSeriesInner(
return () =>
legendDispatch({ type: 'REMOVE_LEGEND_LABEL', payload: { id } });
}
+ return undefined;
}, [
hidden,
colorScaler,
diff --git a/src/components/Series/RangeSeries.tsx b/src/components/Series/RangeSeries.tsx
index be444462..45d58fd4 100644
--- a/src/components/Series/RangeSeries.tsx
+++ b/src/components/Series/RangeSeries.tsx
@@ -1,6 +1,7 @@
import { extent } from 'd3-array';
import { area } from 'd3-shape';
-import { type CSSProperties, memo, useEffect, useMemo } from 'react';
+import type { CSSProperties } from 'react';
+import { memo, useEffect, useMemo } from 'react';
import { useLegend } from '../../contexts/legendContext.js';
import {
@@ -87,6 +88,7 @@ function RangeSeriesInner(
payload: { id },
});
}
+ return undefined;
}, [label, legendDispatch, lineStyle.fill, lineStyle.stroke, id, hidden]);
if (hidden) return null;
diff --git a/src/components/Series/ScatterSeries.tsx b/src/components/Series/ScatterSeries.tsx
index 6d5101dd..b0871d59 100644
--- a/src/components/Series/ScatterSeries.tsx
+++ b/src/components/Series/ScatterSeries.tsx
@@ -1,5 +1,6 @@
import { extent } from 'd3-array';
-import { type SVGAttributes, useEffect, useMemo } from 'react';
+import type { SVGAttributes } from 'react';
+import { useEffect, useMemo } from 'react';
import { useLegend } from '../../contexts/legendContext.js';
import {
@@ -98,6 +99,7 @@ export function ScatterSeries(
return () =>
legendDispatch({ type: 'REMOVE_LEGEND_LABEL', payload: { id } });
}
+ return undefined;
}, [
colorScaler,
hidden,
diff --git a/src/components/Series/Series.tsx b/src/components/Series/Series.tsx
index 8eb1ea4e..ebea23df 100644
--- a/src/components/Series/Series.tsx
+++ b/src/components/Series/Series.tsx
@@ -1,4 +1,4 @@
-import { type ReactElement, type ReactNode } from 'react';
+import type { ReactElement, ReactNode } from 'react';
export interface SeriesProps {
children: ReactNode;
diff --git a/src/components/Tracking.tsx b/src/components/Tracking.tsx
index 1c1e60d6..745f4d3e 100644
--- a/src/components/Tracking.tsx
+++ b/src/components/Tracking.tsx
@@ -5,11 +5,11 @@ import type {
PlotAxisContext,
PlotSeriesState,
} from '../contexts/plotContext.js';
-import {
- type EventName,
- type PlotEventsPlotActions,
+import type {
+ EventName,
+ PlotEventsPlotActions,
} from '../contexts/plotController/usePlotEvents.js';
-import { type SeriesPoint } from '../types.js';
+import type { SeriesPoint } from '../types.js';
import { closestPoint, toNumber } from '../utils.js';
export interface ClosestInfo {
diff --git a/src/contexts/bboxContext.ts b/src/contexts/bboxContext.ts
index f5b61550..8ee0a570 100644
--- a/src/contexts/bboxContext.ts
+++ b/src/contexts/bboxContext.ts
@@ -1,3 +1,4 @@
-import { createContext, type Ref } from 'react';
+import type { Ref } from 'react';
+import { createContext } from 'react';
export const bboxContext = createContext[>(null);
diff --git a/src/contexts/legendContext.provider.tsx b/src/contexts/legendContext.provider.tsx
index 7df7391f..8a0d19ee 100644
--- a/src/contexts/legendContext.provider.tsx
+++ b/src/contexts/legendContext.provider.tsx
@@ -1,11 +1,9 @@
import { produce } from 'immer';
-import { type ReactNode, type Reducer, useMemo, useReducer } from 'react';
+import type { ReactNode, Reducer } from 'react';
+import { useMemo, useReducer } from 'react';
-import {
- type LegendActions,
- legendContext,
- type LegendState,
-} from './legendContext.js';
+import type { LegendActions, LegendState } from './legendContext.js';
+import { legendContext } from './legendContext.js';
const legendReducer: Reducer = produce(
(draft: LegendState, action: LegendActions) => {
diff --git a/src/contexts/legendContext.ts b/src/contexts/legendContext.ts
index 33bfc4dc..004765e0 100644
--- a/src/contexts/legendContext.ts
+++ b/src/contexts/legendContext.ts
@@ -1,4 +1,5 @@
-import { createContext, type Dispatch, useContext } from 'react';
+import type { Dispatch } from 'react';
+import { createContext, useContext } from 'react';
import type { ActionType, Shape } from '../types.js';
diff --git a/src/contexts/plotContext.ts b/src/contexts/plotContext.ts
index 6ee42fee..b99240df 100644
--- a/src/contexts/plotContext.ts
+++ b/src/contexts/plotContext.ts
@@ -1,16 +1,14 @@
import { max, min } from 'd3-array';
-import {
- type ScaleContinuousNumeric,
- type ScaleLinear,
- scaleLinear,
- scaleLog,
- type ScaleLogarithmic,
- type ScaleOrdinal,
- scaleOrdinal,
- type ScaleTime,
- scaleTime,
+import type {
+ ScaleContinuousNumeric,
+ ScaleLinear,
+ ScaleLogarithmic,
+ ScaleOrdinal,
+ ScaleTime,
} from 'd3-scale';
-import { createContext, type Dispatch, useContext, useMemo } from 'react';
+import { scaleLinear, scaleLog, scaleOrdinal, scaleTime } from 'd3-scale';
+import type { Dispatch } from 'react';
+import { createContext, useContext, useMemo } from 'react';
import type { AxisScale } from '../components/Axis/Axis.js';
import type { LegendPosition } from '../components/Legend.js';
diff --git a/src/contexts/plotController/nestableContext.tsx b/src/contexts/plotController/nestableContext.tsx
index 7a3d7c8d..7688a52d 100644
--- a/src/contexts/plotController/nestableContext.tsx
+++ b/src/contexts/plotController/nestableContext.tsx
@@ -1,4 +1,5 @@
-import { createContext, type ReactNode, useContext, useMemo } from 'react';
+import type { ReactNode } from 'react';
+import { createContext, useContext, useMemo } from 'react';
export function createNestableContext(defaultValue: T) {
const context = createContext]