diff --git a/.changeset/rude-kids-sniff.md b/.changeset/rude-kids-sniff.md new file mode 100644 index 000000000..f6ca75d9e --- /dev/null +++ b/.changeset/rude-kids-sniff.md @@ -0,0 +1,5 @@ +--- +"victory-voronoi-container": minor +--- + +Use only x and y coordinates for voronoi calculations, ignoring the baseline x0 and y0 coordinates. Fixes #2298. diff --git a/packages/victory-voronoi-container/src/voronoi-helpers.ts b/packages/victory-voronoi-container/src/voronoi-helpers.ts index 170b39ecc..2854bf76c 100644 --- a/packages/victory-voronoi-container/src/voronoi-helpers.ts +++ b/packages/victory-voronoi-container/src/voronoi-helpers.ts @@ -37,9 +37,9 @@ class VoronoiHelpersClass { const continuous = child && child.type && child.type.continuous; const style = child ? child.props && child.props.style : props.style; return data.map((datum, index) => { - const { x, y, y0, x0 } = Helpers.getPoint(datum); - const voronoiX = (Number(x) + Number(x0)) / 2; - const voronoiY = (Number(y) + Number(y0)) / 2; + const { x, y } = Helpers.getPoint(datum); + const voronoiX = Number(x); + const voronoiY = Number(y); return Object.assign( { diff --git a/stories/victory-charts/victory-voronoi/config.ts b/stories/victory-charts/victory-voronoi/config.ts new file mode 100644 index 000000000..c00bf10c9 --- /dev/null +++ b/stories/victory-charts/victory-voronoi/config.ts @@ -0,0 +1,27 @@ +import type { Meta, StoryObj } from "@storybook/react"; + +import { VictoryVoronoi, VictoryVoronoiProps } from "@/victory"; + +import { + VictoryCommonProps, + VictoryDatableProps, + VictoryMultiLabelableProps, +} from "../../utils/arg-types"; +import { componentContainer } from "../../utils/decorators"; + +type StoryProps = VictoryVoronoiProps & { + themeKey: string; +}; + +export const ComponentMeta: Meta> = { + component: VictoryVoronoi, + decorators: [componentContainer], + + argTypes: { + ...VictoryCommonProps, + ...VictoryDatableProps, + ...VictoryMultiLabelableProps, + }, +}; + +export type Story = StoryObj; diff --git a/stories/victory-charts/victory-voronoi/data.ts b/stories/victory-charts/victory-voronoi/data.ts new file mode 100644 index 000000000..ca944c3bd --- /dev/null +++ b/stories/victory-charts/victory-voronoi/data.ts @@ -0,0 +1,35 @@ +export const sampleData = [ + { x: 1, y: 2 }, + { x: 2, y: 3 }, + { x: 3, y: 5 }, + { x: 4, y: 4 }, + { x: 5, y: 7 }, +]; + +export const sampleDataWithLabels = [ + { x: 1, y: 2, label: "Dogs" }, + { x: 2, y: 3, label: "Cats" }, + { x: 3, y: 5, label: "Snakes" }, + { x: 4, y: 4, label: "Rabbits" }, + { x: 5, y: 7, label: "Birds" }, +]; + +export const sampleDataGroupOne = [ + { x: 1, y: -3 }, + { x: 2, y: 5 }, + { x: 3, y: 3 }, + { x: 4, y: 0 }, + { x: 5, y: -2 }, + { x: 6, y: -2 }, + { x: 7, y: 5 }, +]; + +export const sampleDataGroupTwo = [ + { x: 1, y: 3 }, + { x: 2, y: 1 }, + { x: 3, y: 2 }, + { x: 4, y: -2 }, + { x: 5, y: -1 }, + { x: 6, y: 2 }, + { x: 7, y: 3 }, +]; diff --git a/stories/victory-charts/victory-voronoi/voronoi-animation.stories.tsx b/stories/victory-charts/victory-voronoi/voronoi-animation.stories.tsx new file mode 100644 index 000000000..83c40bf05 --- /dev/null +++ b/stories/victory-charts/victory-voronoi/voronoi-animation.stories.tsx @@ -0,0 +1,64 @@ +import React from "react"; +import type { Meta } from "@storybook/react"; +import range from "lodash/range"; +import random from "lodash/random"; + +import { + VictoryChart, + VictoryVoronoi, + VictoryScatter, + VictoryTheme, +} from "@/victory"; + +import { Story, ComponentMeta } from "./config"; + +const meta: Meta = { + ...ComponentMeta, + title: "Victory Charts/VictoryVoronoi", +}; + +function getData() { + return range(20).map((i: number) => { + return { + x: random(600), + y: random(600), + i, + }; + }); +} + +export const Animation: Story = { + args: { + themeKey: "clean", + }, + render: function AnimationComponent(props) { + const [data, setData] = React.useState(getData()); + + React.useEffect(() => { + const setStateInterval = window.setInterval(() => { + setData(getData()); + }, 4000); + + return () => { + window.clearInterval(setStateInterval); + }; + }, []); + + return ( + + + + + ); + }, +}; + +export default meta; diff --git a/stories/victory-charts/victory-voronoi/voronoi-basic.stories.tsx b/stories/victory-charts/victory-voronoi/voronoi-basic.stories.tsx new file mode 100644 index 000000000..7263fba6a --- /dev/null +++ b/stories/victory-charts/victory-voronoi/voronoi-basic.stories.tsx @@ -0,0 +1,30 @@ +import React from "react"; +import type { Meta } from "@storybook/react"; + +import { VictoryChart, VictoryVoronoi, VictoryTheme } from "@/victory"; + +import { sampleData } from "./data"; +import { Story, ComponentMeta } from "./config"; + +const meta: Meta = { + ...ComponentMeta, + title: "Victory Charts/VictoryVoronoi", +}; + +export const Basic: Story = { + args: { + themeKey: "clean", + }, + render: (props) => ( + <> + + + + + ), +}; + +export default meta; diff --git a/stories/victory-charts/victory-voronoi/voronoi-circles.stories.tsx b/stories/victory-charts/victory-voronoi/voronoi-circles.stories.tsx new file mode 100644 index 000000000..46141a779 --- /dev/null +++ b/stories/victory-charts/victory-voronoi/voronoi-circles.stories.tsx @@ -0,0 +1,38 @@ +import React from "react"; +import type { Meta } from "@storybook/react"; + +import { + VictoryChart, + VictoryLine, + VictoryVoronoi, + VictoryScatter, + VictoryTheme, +} from "@/victory"; + +import { sampleData } from "./data"; +import { Story, ComponentMeta } from "./config"; + +const meta: Meta = { + ...ComponentMeta, + title: "Victory Charts/VictoryVoronoi", +}; + +export const Circles: Story = { + args: { + themeKey: "clean", + }, + render: (props) => ( + <> + + + + + + + ), +}; + +export default meta; diff --git a/stories/victory-charts/victory-voronoi/voronoi-events.stories.tsx b/stories/victory-charts/victory-voronoi/voronoi-events.stories.tsx new file mode 100644 index 000000000..3638e3ab3 --- /dev/null +++ b/stories/victory-charts/victory-voronoi/voronoi-events.stories.tsx @@ -0,0 +1,56 @@ +import React from "react"; +import type { Meta } from "@storybook/react"; + +import { VictoryChart, VictoryVoronoi, VictoryTheme } from "@/victory"; + +import { sampleData } from "./data"; +import { Story, ComponentMeta } from "./config"; + +const meta: Meta = { + ...ComponentMeta, + title: "Victory Charts/VictoryVoronoi", +}; + +export const Events: Story = { + args: { + themeKey: "clean", + }, + render: (props) => ( + <> + + { + return [ + { + target: "data", + mutation: (eventProps) => { + const fill = eventProps.style && eventProps.style.fill; + return fill === "white" + ? null + : { + style: { + fill: "white", + }, + }; + }, + }, + ]; + }, + }, + }, + ]} + data={sampleData} + /> + + + ), +}; + +export default meta; diff --git a/stories/victory-charts/victory-voronoi/voronoi-labels.stories.tsx b/stories/victory-charts/victory-voronoi/voronoi-labels.stories.tsx new file mode 100644 index 000000000..776ea9b8f --- /dev/null +++ b/stories/victory-charts/victory-voronoi/voronoi-labels.stories.tsx @@ -0,0 +1,39 @@ +import React from "react"; +import type { Meta } from "@storybook/react"; + +import { VictoryChart, VictoryVoronoi, VictoryTheme } from "@/victory"; + +import { sampleData, sampleDataWithLabels } from "./data"; +import { Story, ComponentMeta } from "./config"; + +const meta: Meta = { + ...ComponentMeta, + title: "Victory Charts/VictoryVoronoi", +}; + +export const Labels: Story = { + args: { + themeKey: "clean", + }, + render: (props) => ( + <> + + + + + `y: ${datum.y}`} + /> + + + ), +}; + +export default meta; diff --git a/stories/victory-charts/victory-voronoi/voronoi-standalone-rendering.stories.tsx b/stories/victory-charts/victory-voronoi/voronoi-standalone-rendering.stories.tsx new file mode 100644 index 000000000..f04845ce9 --- /dev/null +++ b/stories/victory-charts/victory-voronoi/voronoi-standalone-rendering.stories.tsx @@ -0,0 +1,42 @@ +import React from "react"; +import type { Meta } from "@storybook/react"; + +import { VictoryVoronoi, VictoryTheme } from "@/victory"; + +import { sampleData } from "./data"; +import { Story, ComponentMeta } from "./config"; + +const meta: Meta = { + ...ComponentMeta, + title: "Victory Charts/VictoryVoronoi", +}; + +export const StandaloneRendering: Story = { + args: { + themeKey: "clean", + }, + render: (props) => ( + <> + + + + + + + ), +}; + +export default meta; diff --git a/stories/victory-charts/victory-voronoi/voronoi-styles.stories.tsx b/stories/victory-charts/victory-voronoi/voronoi-styles.stories.tsx new file mode 100644 index 000000000..e911b52cd --- /dev/null +++ b/stories/victory-charts/victory-voronoi/voronoi-styles.stories.tsx @@ -0,0 +1,38 @@ +import React from "react"; +import type { Meta } from "@storybook/react"; + +import { VictoryChart, VictoryVoronoi, VictoryTheme } from "@/victory"; + +import { sampleData } from "./data"; +import { Story, ComponentMeta } from "./config"; + +const meta: Meta = { + ...ComponentMeta, + title: "Victory Charts/VictoryVoronoi", +}; + +export const Styles: Story = { + args: { + themeKey: "clean", + }, + render: (props) => ( + + + + ), +}; + +export default meta; diff --git a/stories/victory-charts/victory-voronoi/voronoi-tooltips-grouped.stories.tsx b/stories/victory-charts/victory-voronoi/voronoi-tooltips-grouped.stories.tsx new file mode 100644 index 000000000..88c0b5e83 --- /dev/null +++ b/stories/victory-charts/victory-voronoi/voronoi-tooltips-grouped.stories.tsx @@ -0,0 +1,55 @@ +import React from "react"; +import type { Meta } from "@storybook/react"; + +import { + VictoryVoronoi, + VictoryTheme, + VictoryChart, + VictoryGroup, + VictoryLine, + VictoryScatter, + VictoryTooltip, + VictoryVoronoiContainer, +} from "@/victory"; + +import { sampleDataGroupOne, sampleDataGroupTwo } from "./data"; +import { Story, ComponentMeta } from "./config"; + +const meta: Meta = { + ...ComponentMeta, + title: "Victory Charts/VictoryVoronoi", +}; + +export const TooltipsGrouped: Story = { + args: { + themeKey: "clean", + }, + render: (props) => ( + <> + } + theme={VictoryTheme[props.themeKey]} + > + `y: ${datum.y}`} + labelComponent={} + data={sampleDataGroupOne} + > + + (active ? 8 : 3)} /> + + `y: ${datum.y}`} + labelComponent={} + data={sampleDataGroupTwo} + > + + (active ? 8 : 3)} /> + + + + ), +}; + +export default meta; diff --git a/stories/victory-charts/victory-voronoi/voronoi-tooltips.stories.tsx b/stories/victory-charts/victory-voronoi/voronoi-tooltips.stories.tsx new file mode 100644 index 000000000..f0457e5cf --- /dev/null +++ b/stories/victory-charts/victory-voronoi/voronoi-tooltips.stories.tsx @@ -0,0 +1,39 @@ +import React from "react"; +import type { Meta } from "@storybook/react"; + +import { + VictoryChart, + VictoryVoronoi, + VictoryTooltip, + VictoryTheme, +} from "@/victory"; + +import { sampleDataWithLabels } from "./data"; +import { Story, ComponentMeta } from "./config"; + +const meta: Meta = { + ...ComponentMeta, + title: "Victory Charts/VictoryVoronoi", +}; + +export const Tooltips: Story = { + args: { + themeKey: "clean", + }, + render: (props) => ( + <> + + datum.y} + labelComponent={} + /> + + + ), +}; + +export default meta; diff --git a/stories/victory-charts/victory-voronoi/voronoi-y0.stories.tsx b/stories/victory-charts/victory-voronoi/voronoi-y0.stories.tsx new file mode 100644 index 000000000..8c5029715 --- /dev/null +++ b/stories/victory-charts/victory-voronoi/voronoi-y0.stories.tsx @@ -0,0 +1,64 @@ +import React from "react"; +import type { Meta } from "@storybook/react"; + +import { + VictoryChart, + VictoryArea, + VictoryVoronoi, + VictoryVoronoiContainer, + VictoryTooltip, + VictoryTheme, +} from "@/victory"; + +import { Story, ComponentMeta } from "./config"; + +const meta: Meta = { + ...ComponentMeta, + title: "Victory Charts/VictoryVoronoi", +}; + +export const y0: Story = { + args: { + themeKey: "clean", + }, + render: (props) => ( + <> + } + theme={VictoryTheme[props.themeKey]} + > + datum.y} + labelComponent={} + data={[ + { x: 1, y: 4 }, + { x: 2, y: 5 }, + { x: 3, y: 7 }, + ]} + y0={() => 2} + /> + datum.y} + labelComponent={} + data={[ + { x: 1, y: 2 }, + { x: 2, y: 3 }, + { x: 3, y: 5 }, + ]} + y0={() => 2} + /> + + + ), +}; + +export default meta;