diff --git a/.changeset/slimy-guests-accept.md b/.changeset/slimy-guests-accept.md new file mode 100644 index 000000000..dea8131a2 --- /dev/null +++ b/.changeset/slimy-guests-accept.md @@ -0,0 +1,8 @@ +--- +"victory-bar": minor +"victory-chart": minor +"victory-core": minor +"victory-line": minor +--- + +Remove v37 experimental code diff --git a/.github/ISSUE_TEMPLATE/victory-turbo-component-re-write.md b/.github/ISSUE_TEMPLATE/victory-turbo-component-re-write.md deleted file mode 100644 index d5557b7f9..000000000 --- a/.github/ISSUE_TEMPLATE/victory-turbo-component-re-write.md +++ /dev/null @@ -1,24 +0,0 @@ ---- -name: Victory Turbo component re-write -about: This is a template for all victory turbo components -title: Victory [component] v37 -labels: turbo -assignees: '' - ---- - -## Implementation Notes -- New components should live inside a nested directory (currently v37). These components should not make changes to existing functionality. -- The victory event system will be excluded for now until we have more clarity on how Victory wants to handle events. -- [Add other notes here] - -## Checklist -- [ ] Basic data rendering as a standalone component -- [ ] Basic data rendering inside a `VictoryChart` -- [ ] Basic data rendering inside a `VictoryGroup` (if applicable) -- [ ] Basic data rendering inside a `VictoryStack` (if applicable) -- [ ] Styling with existing victory theme and inline styles -- [ ] Transitions -- [ ] Basic events like zoom and tooltips -- [ ] Copy existing tests, excluding events and helper methods -- [ ] Add documentation and tests for any API changes diff --git a/packages/victory-bar/src/v37/victory-bar-v1.tsx b/packages/victory-bar/src/v37/victory-bar-v1.tsx deleted file mode 100644 index 943d2871d..000000000 --- a/packages/victory-bar/src/v37/victory-bar-v1.tsx +++ /dev/null @@ -1,129 +0,0 @@ -/* eslint-disable react/no-multi-comp */ -import * as React from "react"; -import { - Datum, - NumberOrCallback, - VictoryCommonProps, - VictoryContainer, - VictoryDatableProps, -} from "victory-core"; -import { - useData, - useDomain, - useScale, - VictoryProvider, - VictoryProviderProps, -} from "victory-core/es/v37"; -import Bar from "../bar"; -import { getBarPosition } from "../helper-methods"; - -// This is a demo component that uses VictoryProvider to access calculated props and state. -// This component does not include events, animations, or styling. -// To test out, swap out the VictoryBar export in ./index.js and run `pnpm run storybook:server`. - -const defaultProps: VictoryProviderProps = { - data: [ - { x: 1, y: 1 }, - { x: 2, y: 2 }, - { x: 3, y: 3 }, - { x: 4, y: 4 }, - ], - height: 300, - includeZero: true, - padding: 50, - sortOrder: "ascending" as const, - width: 450, -}; - -export type VictoryBarAlignmentType = "start" | "middle" | "end"; -export interface VictoryBarProps - extends VictoryCommonProps, - VictoryDatableProps { - alignment?: VictoryBarAlignmentType; - barRatio?: number; - barWidth?: NumberOrCallback; - cornerRadius?: - | NumberOrCallback - | { - top?: NumberOrCallback; - topLeft?: NumberOrCallback; - topRight?: NumberOrCallback; - bottom?: NumberOrCallback; - bottomLeft?: NumberOrCallback; - bottomRight?: NumberOrCallback; - }; - dataComponent?: React.ReactElement; - groupComponent?: React.ReactElement; - horizontal?: boolean; -} - -// TODO: This would be a shared helper that allows us to access context values in the base component -export function withContainer( - WrappedComponent: (props: Props) => React.ReactElement, - initialProviderProps: Partial = {}, -) { - return (props: Props) => { - const providerProps = { - ...initialProviderProps, - ...props, - }; - const { standalone = true, containerComponent = } = - props; - if (standalone) { - return ( - - {React.cloneElement( - containerComponent, - providerProps, - , - )} - - ); - } - return ( - - - - ); - }; -} - -function VictoryBar({ - dataComponent = , - groupComponent = , - alignment, - barRatio, - barWidth, - cornerRadius, - horizontal = false, -}: VictoryBarProps) { - const scale = useScale(); - const data = useData(); - const domain = useDomain(); - - const children = data.map((datum: Datum, i: number) => { - const { x, y, x0, y0 } = getBarPosition( - { domain, scale, horizontal }, - datum, - ); - const dataProps = { - index: i, - key: `bar-${i}`, - alignment, - barRatio, - barWidth, - cornerRadius, - scale, - data, - x, - y, - x0, - y0, - datum, - }; - return React.cloneElement(dataComponent, dataProps); - }); - return React.cloneElement(groupComponent, {}, children); -} - -export default withContainer(VictoryBar, defaultProps); diff --git a/packages/victory-bar/src/v37/victory-bar-v2.tsx b/packages/victory-bar/src/v37/victory-bar-v2.tsx deleted file mode 100644 index d8fd5b53e..000000000 --- a/packages/victory-bar/src/v37/victory-bar-v2.tsx +++ /dev/null @@ -1,96 +0,0 @@ -/* eslint-disable react/no-multi-comp */ -import * as React from "react"; -import { Datum, NumberOrCallback } from "victory-core"; -import { - useData, - useDomain, - useScale, - useVictoryProviderSync, - VictoryCalculatedStateProps, - withContainer, -} from "victory-core/es/v37"; - -import Bar from "../bar"; -import { BarProps } from ".."; -import { getBarPosition } from "../helper-methods"; - -export type VictoryBarAlignmentType = "start" | "middle" | "end"; -export interface VictoryBarProps extends VictoryCalculatedStateProps { - alignment?: VictoryBarAlignmentType; - barRatio?: number; - barWidth?: NumberOrCallback; - cornerRadius?: - | NumberOrCallback - | { - top?: NumberOrCallback; - topLeft?: NumberOrCallback; - topRight?: NumberOrCallback; - bottom?: NumberOrCallback; - bottomLeft?: NumberOrCallback; - bottomRight?: NumberOrCallback; - }; - data?: Datum[]; - dataComponent?: React.ReactElement; - groupComponent?: React.ReactElement; - horizontal?: boolean; -} - -function VictoryBar({ - alignment = "middle", - barRatio, - barWidth, - cornerRadius, - data = [ - { x: 1, y: 1 }, - { x: 2, y: 2 }, - { x: 3, y: 3 }, - { x: 4, y: 4 }, - ], - dataComponent = , - groupComponent = , - includeZero = true, - horizontal = false, - sortOrder = "ascending", - ...props -}: VictoryBarProps) { - // Typescript works best when we provide defaults in the destructured - // component props. However, I am anticipating confusion about which props - // we will need to pass back up to the provider vs. the props that are only - // used in this component. - useVictoryProviderSync({ - data, - includeZero, - sortOrder, - ...props, - }); - const scale = useScale(); - const domain = useDomain(); - - // TODO: Do we need to get this from context? - const formattedData = useData(); - - const barPositionProps = { domain, scale, horizontal }; - - const children = formattedData.map((datum: Datum, i: number) => { - const { x, y, y0 } = getBarPosition(barPositionProps, datum); - const dataProps: BarProps & { key: string } = { - index: i, - key: `bar-${i}`, - alignment, - barRatio, - barWidth, - cornerRadius, - scale, - data, - x, - y, - y0, - datum, - }; - return React.cloneElement(dataComponent, dataProps); - }); - return React.cloneElement(groupComponent, {}, children); -} - -// @ts-expect-error we need to work out what props this withContainer wrapper accepts -export default withContainer(VictoryBar); diff --git a/packages/victory-bar/src/v37/victory-bar.stories.tsx b/packages/victory-bar/src/v37/victory-bar.stories.tsx deleted file mode 100644 index fd6820448..000000000 --- a/packages/victory-bar/src/v37/victory-bar.stories.tsx +++ /dev/null @@ -1,28 +0,0 @@ -/* eslint-disable react/no-multi-comp */ -import * as React from "react"; -import VictoryBar from "./victory-bar-v2"; -import VictoryChart from "victory-chart/es/v37/victory-chart"; - -export default { - title: "v37/VictoryBar", - parameters: { - chromatic: { disableSnapshot: true }, - }, - component: VictoryBar, -}; - -export const Demo = (props) => { - return ; -}; - -Demo.args = { - barRatio: 0.5, -}; - -export const WithChart = (props) => { - return ( - - - - ); -}; diff --git a/packages/victory-bar/src/v37/victory-bar.test.tsx b/packages/victory-bar/src/v37/victory-bar.test.tsx deleted file mode 100644 index a20a62a67..000000000 --- a/packages/victory-bar/src/v37/victory-bar.test.tsx +++ /dev/null @@ -1,278 +0,0 @@ -import * as React from "react"; -import { render, fireEvent, screen } from "@testing-library/react"; -import { range } from "lodash"; -import { VictoryChart } from "victory-chart"; -import { Bar, VictoryBar } from "victory-bar"; -import { isBar, getBarHeight } from "../../../../test/helpers"; - -describe("components/victory-bar", () => { - describe("default component rendering", () => { - it("attaches safe user props to the container component", () => { - render( - , - ); - - const container = screen.getByTestId("victory-bar"); - expect(screen.getByLabelText("Chart")).toBeDefined(); - expect(container).not.toHaveAttribute("unsafe-prop"); - expect(container.tagName).toEqual("svg"); - }); - - it("attaches safe user props to the group component if the component is rendered inside a VictoryChart", () => { - render( - , - { wrapper: VictoryChart }, - ); - - const container = screen.getByTestId("victory-bar"); - expect(screen.getByLabelText("Chart")).toBeDefined(); - expect(container).not.toHaveAttribute("unsafe-prop"); - expect(container.tagName).toEqual("g"); - }); - - it("renders an svg with the correct width and height", () => { - const { container } = render(); - const svg = container.querySelector("svg"); - expect(svg!.getAttribute("style")).toContain("width: 100%; height: 100%"); - }); - - it("renders an svg with the correct viewBox", () => { - const { container } = render(); - const svg = container.querySelector("svg"); - const viewBoxValue = `0 0 ${450} ${300}`; - expect(svg!.getAttribute("viewBox")).toEqual(viewBoxValue); - }); - - it("renders 4 bars", () => { - const { container } = render(); - const bars = container.querySelectorAll("path"); - expect(bars.length).toEqual(4); - }); - - it("renders each bar as a rectangle", () => { - const { container } = render(); - const barCommandStrings = Array.from( - container.querySelectorAll("path"), - ).map((bar) => bar.getAttribute("d")); - barCommandStrings.forEach((commandString) => { - expect(isBar(commandString)).toBeTruthy(); - }); - }); - }); - - describe("rendering data", () => { - it("renders bars for {x, y} shaped data (default)", () => { - const data = range(10).map((i) => ({ x: i, y: i })); - const { container } = render(); - const bars = container.querySelectorAll("path"); - expect(bars.length).toEqual(10); - }); - - it("renders ordered bars when sortKey is passed", () => { - const data = range(5) - .map((i) => ({ x: i, y: i })) - .reverse(); - const { container } = render(); - const barHeight = Array.from(container.querySelectorAll("path")).map( - (bar) => { - const commandString = bar.getAttribute("d"); - return getBarHeight(commandString); - }, - ); - - const ascendingBars = [...barHeight].sort((a, b) => a - b); - - expect(barHeight).toEqual(ascendingBars); - }); - - it("renders reverse ordered bars when sortOrder is descending", () => { - const data = range(5) - .map((i) => ({ x: i, y: i })) - .reverse(); - const { container } = render( - , - ); - const barHeight = Array.from(container.querySelectorAll("path")).map( - (bar) => { - const commandString = bar.getAttribute("d"); - return getBarHeight(commandString); - }, - ); - const descendingBars = [...barHeight].sort((a, b) => b - a); - - expect(barHeight).toEqual(descendingBars); - }); - - it("renders bars for array-shaped data", () => { - const data = range(20).map((i) => [i, i]); - const { container } = render(); - const bars = container.querySelectorAll("path"); - expect(bars).toHaveLength(20); - }); - - it("renders bars for deeply-nested data", () => { - const data = range(8).map((i) => ({ a: { b: [{ x: i, y: i }] } })); - const { container } = render( - , - ); - const bars = container.querySelectorAll("path"); - expect(bars).toHaveLength(8); - }); - - it("renders bars values with null accessor", () => { - const data = range(8); - const { container } = render( - // @ts-expect-error null is not assignable to DataGetterType - , - ); - const bars = container.querySelectorAll("path"); - expect(bars).toHaveLength(8); - }); - - it("renders bars with appropriate relative heights", () => { - const { container } = render( - , - ); - const bars = Array.from(container.querySelectorAll("path")); - const heights = bars.map((bar) => { - const commandString = bar.getAttribute("d"); - return getBarHeight(commandString); - }); - - expect(Math.trunc(heights[1] / 2)).toEqual(Math.trunc(heights[0])); - expect(((heights[2] / 3) * 2).toFixed(3)).toEqual(heights[1].toFixed(3)); - }); - - it("does not render data with null x or y values", () => { - const data = [ - { x: 1, y: 2 }, - { x: null, y: 4 }, - { x: 5, y: null }, - ]; - const { container } = render(); - expect(container.querySelectorAll("path")).toHaveLength(1); - }); - }); - - describe.skip("event handling", () => { - const clickHandler = jest.fn(); - - beforeEach(() => { - clickHandler.mockReset(); - }); - - it("attaches an event to the parent svg", () => { - const { container } = render( - , - ); - const bar = container.querySelector("path"); - fireEvent.click(bar!); - - expect(clickHandler).toHaveBeenCalled(); - }); - - it("attaches an event to data", () => { - const data = [ - { x: 0, y: 0, label: "0" }, - { x: 1, y: 1, label: "1" }, - { x: 2, y: 2, label: "2" }, - ]; - const { container } = render( - , - ); - const bars = container.querySelectorAll("path"); - bars.forEach((bar, index) => { - clickHandler.mockReset(); - fireEvent.click(bar); - expect(clickHandler).toHaveBeenCalled(); - - const barContext = clickHandler.mock.calls[0][1]; - expect(barContext.datum.x).toEqual(data[index].x); - }); - }); - - it("attaches an event to a label", () => { - const data = [ - { x: 0, y: 0, label: "label 0" }, - { x: 1, y: 1, label: "label 1" }, - { x: 2, y: 2, label: "label 2" }, - ]; - - render( - datum.label} - events={[ - { - target: "labels", - eventHandlers: { onClick: clickHandler }, - }, - ]} - />, - ); - const label = screen.getByText("label 1"); - - fireEvent.click(label); - - expect(clickHandler).toHaveBeenCalled(); - }); - }); - - describe("accessibility", () => { - it("adds an aria role to each bar in the series", () => { - const data = range(10).map((y, x) => ({ x, y })); - render(); - const presentationElements = screen.getAllByRole("presentation"); - expect(presentationElements).toHaveLength(11); // bars plus container - }); - - it("applies aria-label and tabIndex to the Bar primitive", () => { - const data = range(5, 11).map((y, x) => ({ y, x })); - const { container } = render( - `x: ${datum.x}`} - tabIndex={({ index }) => (index as number) + 1} - /> - } - />, - ); - - container.querySelectorAll("path").forEach((bar, index) => { - expect(parseInt(bar.getAttribute("tabindex")!)).toEqual(index + 1); - expect(bar.getAttribute("aria-label")).toEqual(`x: ${data[index].x}`); - }); - }); - }); -}); diff --git a/packages/victory-chart/src/v37/victory-chart.tsx b/packages/victory-chart/src/v37/victory-chart.tsx deleted file mode 100644 index 6864d6ba5..000000000 --- a/packages/victory-chart/src/v37/victory-chart.tsx +++ /dev/null @@ -1,91 +0,0 @@ -import * as React from "react"; -import { - CategoryPropType, - DomainPropType, - EventPropTypeInterface, - StringOrNumberOrCallback, - VictoryCommonProps, - VictoryStyleInterface, - VictoryStyleObject, -} from "victory-core"; -import { - withContainer, - useDomain, - useScale, - useData, -} from "victory-core/es/v37"; -import { AxesType } from ".."; -import { VictoryAxis, VictoryAxisProps } from "victory-axis"; - -interface VictoryChartProps extends VictoryCommonProps { - backgroundComponent?: React.ReactElement; - categories?: CategoryPropType; - children?: React.ReactNode | React.ReactNode[]; - desc?: string; - defaultAxes?: AxesType; - defaultPolarAxes?: AxesType; - domain?: DomainPropType; - endAngle?: number; - eventKey?: StringOrNumberOrCallback; - events?: EventPropTypeInterface< - string, - string[] | number[] | string | number - >[]; - innerRadius?: number; - prependDefaultAxes?: boolean; - startAngle?: number; - style?: Pick & { - background?: VictoryStyleObject; - }; - title?: string; -} - -const DEFAULT_AXES = { - independent: , - dependent: , -}; - -// TODO: This does not accept data -const VictoryChart = ({ - defaultAxes = DEFAULT_AXES, - groupComponent = , - children, -}: VictoryChartProps) => { - const scale = useScale(); - const data = useData(); - const domain = useDomain(); - - const axes = React.useMemo(() => { - const { dependent, independent } = { - ...defaultAxes, - ...DEFAULT_AXES, - }; - const axisProps: VictoryAxisProps = { - data, - domain, - // @ts-expect-error we need to fix this scale type - scale, - standalone: false, - }; - return [ - React.cloneElement(dependent, { ...axisProps, key: "dependent-axis" }), - React.cloneElement(independent, { - ...axisProps, - key: "independent-axis", - }), - ]; - }, [defaultAxes, domain, scale, data]); - - const childComponents = React.Children.map(children, (child, index) => { - // @ts-expect-error Why is this throwing a type error? - return React.cloneElement(child, { - key: `child-${index}`, - index, - standalone: false, - }); - }); - - return React.cloneElement(groupComponent, {}, axes, childComponents); -}; - -export default withContainer(VictoryChart); diff --git a/packages/victory-core/src/v37/clone.tsx b/packages/victory-core/src/v37/clone.tsx deleted file mode 100644 index 8b3346c4c..000000000 --- a/packages/victory-core/src/v37/clone.tsx +++ /dev/null @@ -1,30 +0,0 @@ -import React from "react"; - -/** - * Syntax sugar for `React.cloneElement`, so that we can use JSX instead - * - * @example - * // Before: - * const children = React.cloneElement(props.groupComponent, { prop2 }, props.children); - * return React.cloneElement(props.containerComponent, { prop1 }, children); - * - * // After: - * return ( - * - * - * {props.children} - * - * - * ); - */ -export const Clone = ( - props: React.PropsWithChildren< - { - element: React.ReactElement; - children?: React.ReactNode | React.ReactNode[]; - } & TProps - >, -) => { - const { children, element, ...rest } = props; - return React.cloneElement(element, rest as unknown as TProps, children); -}; diff --git a/packages/victory-core/src/v37/index.tsx b/packages/victory-core/src/v37/index.tsx deleted file mode 100644 index 6b054e46f..000000000 --- a/packages/victory-core/src/v37/index.tsx +++ /dev/null @@ -1,4 +0,0 @@ -export * from "./victory-state"; -export * from "./clone"; -export * from "./with-normalized-props"; -export * from "./with-container"; diff --git a/packages/victory-core/src/v37/victory-state/defaults.ts b/packages/victory-core/src/v37/victory-state/defaults.ts deleted file mode 100644 index 69c125fd3..000000000 --- a/packages/victory-core/src/v37/victory-state/defaults.ts +++ /dev/null @@ -1,2 +0,0 @@ -export const DEFAULT_HEIGHT = 300; -export const DEFAULT_WIDTH = 450; diff --git a/packages/victory-core/src/v37/victory-state/helpers/get-axis-data.ts b/packages/victory-core/src/v37/victory-state/helpers/get-axis-data.ts deleted file mode 100644 index 0e66fc75b..000000000 --- a/packages/victory-core/src/v37/victory-state/helpers/get-axis-data.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { AxisType, Datum, DomainValue } from "../../../types/prop-types"; -import { isKeyValueObject } from "../../../victory-util/type-helpers"; - -export function getAxisData(data: Datum[], axis: AxisType) { - return data.reduce((acc, datum) => { - if (isKeyValueObject(datum)) { - const value = datum[axis]; - if (value && typeof value !== "string") { - acc.push(value); - } - } - return acc; - }, [] as DomainValue[]); -} diff --git a/packages/victory-core/src/v37/victory-state/helpers/get-data.test.ts b/packages/victory-core/src/v37/victory-state/helpers/get-data.test.ts deleted file mode 100644 index 065d8cd5a..000000000 --- a/packages/victory-core/src/v37/victory-state/helpers/get-data.test.ts +++ /dev/null @@ -1,169 +0,0 @@ -import { range } from "lodash"; -import { getData } from "victory-core/lib/v37/victory-state/helpers/get-data"; - -describe("getData", () => { - it("returns an empty array if no data is passed in", () => { - expect(getData()).toEqual([]); - }); - - it("returns formatted data", () => { - const data = [ - { x: "kittens", y: 3 }, - { x: "cats", y: 5 }, - ]; - expect(getData({ data })).toMatchInlineSnapshot(` - Array [ - Object { - "_x": 1, - "_y": 3, - "x": "kittens", - "xName": "kittens", - "y": 3, - }, - Object { - "_x": 2, - "_y": 5, - "x": "cats", - "xName": "cats", - "y": 5, - }, - ] - `); - }); - - it("accepts date values", () => { - const data = [ - { - x: new Date(Date.UTC(2022, 0, 1)), - y: 10, - }, - { - x: new Date(Date.UTC(2022, 0, 2)), - y: 20, - }, - ]; - expect(getData({ data })).toMatchInlineSnapshot(` - Array [ - Object { - "_x": 2022-01-01T00:00:00.000Z, - "_y": 10, - "x": 2022-01-01T00:00:00.000Z, - "y": 10, - }, - Object { - "_x": 2022-01-02T00:00:00.000Z, - "_y": 20, - "x": 2022-01-02T00:00:00.000Z, - "y": 20, - }, - ] - `); - }); - - it("filters data with null x and y values", () => { - const data = [ - { - x: null, - y: 1, - }, - { - y: 2, - x: null, - }, - { - x: 3, - y: 3, - }, - ]; - expect(getData({ data })).toHaveLength(1); - }); - - it("returns formatted data witfh accessors", () => { - const data = [ - { one: "kittens", two: 3 }, - { one: "cats", two: 5 }, - ]; - expect(getData({ data, x: "one", y: "two" })).toMatchInlineSnapshot(` - Array [ - Object { - "_x": 1, - "_y": 3, - "one": "kittens", - "two": 3, - "x": "kittens", - "xName": "kittens", - "y": 3, - }, - Object { - "_x": 2, - "_y": 5, - "one": "cats", - "two": 5, - "x": "cats", - "xName": "cats", - "y": 5, - }, - ] - `); - }); - - it("does not sort data by default", () => { - const data = [ - { x: 2, y: 2 }, - { x: 1, y: 3 }, - { x: 3, y: 1 }, - ]; - - expect(getData({ data })).toEqual([ - { _x: 2, x: 2, _y: 2, y: 2 }, - { _x: 1, x: 1, _y: 3, y: 3 }, - { _x: 3, x: 3, _y: 1, y: 1 }, - ]); - }); - - it("sorts data according to sort key", () => { - const data = [ - { x: 1, y: 1, order: 2 }, - { x: 3, y: 3, order: 1 }, - { x: 2, y: 2, order: 3 }, - ]; - - expect(getData({ data, sortKey: "order" })).toEqual([ - { _x: 3, x: 3, _y: 3, y: 3, order: 1 }, - { _x: 1, x: 1, _y: 1, y: 1, order: 2 }, - { _x: 2, x: 2, _y: 2, y: 2, order: 3 }, - ]); - }); - - it("sorts data according to sort key and sort order", () => { - const data = [ - { x: 1, y: 1, order: 2 }, - { x: 3, y: 3, order: 1 }, - { x: 2, y: 2, order: 3 }, - ]; - - expect( - getData({ data, sortKey: "order", sortOrder: "descending" }), - ).toEqual([ - { _x: 2, x: 2, _y: 2, y: 2, order: 3 }, - { _x: 1, x: 1, _y: 1, y: 1, order: 2 }, - { _x: 3, x: 3, _y: 3, y: 3, order: 1 }, - ]); - }); - - it("formats deeply nested data", () => { - const data = range(8).map((i) => ({ a: { b: [{ x: i, y: i }] } })); - - expect(getData({ data, x: "a.b[0].x", y: "a.b[0].y" })).toHaveLength(8); - }); - - it("formats data from a range", () => { - const data = range(3); - - expect(getData({ data })).toEqual([ - { _x: 0, x: 0, _y: 0, y: 0 }, - { _x: 1, x: 1, _y: 1, y: 1 }, - { _x: 2, x: 2, _y: 2, y: 2 }, - ]); - }); -}); diff --git a/packages/victory-core/src/v37/victory-state/helpers/get-data.ts b/packages/victory-core/src/v37/victory-state/helpers/get-data.ts deleted file mode 100644 index d5ff4b013..000000000 --- a/packages/victory-core/src/v37/victory-state/helpers/get-data.ts +++ /dev/null @@ -1,78 +0,0 @@ -import { get, isNil, orderBy } from "lodash"; -import { Datum, DatumValue } from "../../../types/prop-types"; -import { isKeyValueObject } from "../../../victory-util/type-helpers"; -import { VictoryProviderProps } from "../types"; - -type DataProps = Pick< - VictoryProviderProps, - "data" | "x" | "y" | "sortKey" | "sortOrder" | "samples" ->; - -export interface FormattedDatum { - x: DatumValue; - y: DatumValue; - _x: number | Date; - _y: number | Date; - xName?: string; - yName?: string; - [key: string]: DatumValue; -} - -function getValue(datum: Datum, key: string): DatumValue { - if (typeof datum === "object") { - return get(datum, key); - } - return datum; -} - -function getNumericValue(value: DatumValue, fallback: number): number | Date { - if (typeof value === "number" || value instanceof Date) { - return value; - } - return fallback; -} - -export function getData({ - x: xAccessor = "x", - y: yAccessor = "y", - sortKey, - sortOrder = "ascending", - data = [], -}: DataProps = {}): FormattedDatum[] { - const formattedData = data.reduce((nonNullData, datum, index) => { - const x = getValue(datum, xAccessor); - const y = getValue(datum, yAccessor); - if (isNil(x) || isNil(y)) { - return nonNullData; - } - const _x = getNumericValue(x, index + 1); - const _y = getNumericValue(y, index + 1); - - // TODO: Get this value if it is different - const xName = typeof x === "string" ? x : undefined; - const yName = typeof y === "string" ? y : undefined; - - const additionalProperties = isKeyValueObject(datum) ? datum : {}; - - return [ - ...nonNullData, - { - x, - y, - _x, - _y, - // Only set these properties if they exist - ...(xName ? { xName } : {}), - ...(yName ? { yName } : {}), - ...additionalProperties, - }, - ]; - }, [] as FormattedDatum[]); - - if (sortKey) { - const order = sortOrder === "descending" ? "desc" : "asc"; - return orderBy(formattedData, sortKey, order); - } - - return formattedData; -} diff --git a/packages/victory-core/src/v37/victory-state/helpers/get-domain.test.ts b/packages/victory-core/src/v37/victory-state/helpers/get-domain.test.ts deleted file mode 100644 index 4dce72fbf..000000000 --- a/packages/victory-core/src/v37/victory-state/helpers/get-domain.test.ts +++ /dev/null @@ -1,98 +0,0 @@ -import { getDomain } from "victory-core/lib/v37/victory-state/helpers/get-domain"; - -describe("getDomain", () => { - it("returns a default domain if no data is provided", () => { - expect(getDomain({}, "x")).toEqual([0, 1]); - expect(getDomain({}, "y")).toEqual([0, 1]); - }); - - it("gets the domain from props", () => { - expect(getDomain({ domain: [0, 1] }, "x")).toEqual([0, 1]); - expect(getDomain({ domain: [0, 1] }, "y")).toEqual([0, 1]); - }); - - it("gets the domain from props for x and y", () => { - expect(getDomain({ domain: { x: [0, 1] } }, "x")).toEqual([0, 1]); - expect(getDomain({ domain: { y: [1, 2] } }, "y")).toEqual([1, 2]); - }); - - it("gets the domain from data if props don't exist for a particular axis", () => { - expect( - getDomain( - { - domain: { y: [1, 2] }, - data: [ - { x: 1, y: 3 }, - { x: 3, y: 5 }, - ], - }, - "x", - ), - ).toEqual([1, 3]); - }); - - it("gets the domain from data with dates", () => { - expect( - getDomain( - { - domain: { y: [1, 2] }, - data: [ - { x: new Date(2022, 0, 10), y: 1 }, - { x: new Date(2022, 0, 1), y: 2 }, - ], - }, - "x", - ), - ).toEqual([new Date(2022, 0, 1), new Date(2022, 0, 10)]); - }); - - it("returns a domain from minDomain and maxDomain if both are defined", () => { - const props = { minDomain: 1, maxDomain: 10 }; - expect(getDomain(props, "x")).toEqual([1, 10]); - }); - - it("returns a domain from minDoman and maxDomain if both are defined for x and y", () => { - const props = { - minDomain: { x: 1, y: 2 }, - maxDomain: { x: 10, y: 20 }, - }; - expect(getDomain(props, "x")).toEqual([1, 10]); - }); - - describe("with zero", () => { - it("ensures that the domain includes zero for the dependent axis", () => { - const props = { - data: [ - { x: 1, y: 3 }, - { x: 3, y: 5 }, - ], - includeZero: true, - }; - expect(getDomain(props, "y")).toEqual([0, 5]); - }); - - it("allows minimum domain values less than zero", () => { - const props = { - data: [ - { x: 1, y: -3 }, - { x: 3, y: 5 }, - ], - includeZero: true, - }; - expect(getDomain(props, "y")).toEqual([-3, 5]); - }); - - // TODO: Investigate this more - // Why is y0 different for each x/y value? Could minDomain be used instead? - it.skip("allows explicit y0 values in props.data to set the minimum domain", () => { - const props = { - data: [ - { x: 1, y: 3, y0: 2 }, - { x: 3, y: 5, y0: 3 }, - ], - includeZero: true, - }; - expect(getDomain(props, "y")).toEqual([2, 5]); - }); - }); -}); diff --git a/packages/victory-core/src/v37/victory-state/helpers/get-domain.ts b/packages/victory-core/src/v37/victory-state/helpers/get-domain.ts deleted file mode 100644 index 4315a6983..000000000 --- a/packages/victory-core/src/v37/victory-state/helpers/get-domain.ts +++ /dev/null @@ -1,62 +0,0 @@ -import * as d3Array from "victory-vendor/d3-array"; -import { getAxisData } from "./get-axis-data"; -import { - getValueForAxis, - isDate, - isTuple, -} from "../../../victory-util/type-helpers"; -import { VictoryProviderProps } from "../types"; -import { - Tuple, - AxisType, - DomainTuple, - DomainValue, -} from "../../../types/prop-types"; - -type DomainProps = Pick< - VictoryProviderProps, - "data" | "domain" | "maxDomain" | "minDomain" | "includeZero" ->; - -// TODO: What should this default value be? -const DEFAULT_MIN = 0; -const DEFAULT_MAX = 1; - -function getDomainFromMinMax( - min: number = DEFAULT_MIN, - max: number = DEFAULT_MAX, -): Tuple { - // TODO: Victoy currently has some really specific logic in getDomainFromMinMax - // that adds or subtracts a very small number from each domain to avoid the min - // and max being the same value. This has resulted in some weird behavior in the - // past, so we should revisit this. - return [min, max]; -} - -export function getDomain( - { data = [], includeZero, ...props }: DomainProps, - axis: AxisType, -): DomainTuple { - const domainFromProps = getValueForAxis(props.domain, axis); - const axisData = getAxisData(data, axis); - - if (includeZero && axis === "y") { - axisData.push(0); - } - - if (isTuple(domainFromProps)) { - return domainFromProps; - } - - const [min, max] = d3Array.extent(axisData) as DomainTuple | Tuple; - - const minDomain = getValueForAxis(props.minDomain, axis) || min; - const maxDomain = getValueForAxis(props.maxDomain, axis) || max; - - if (isDate(minDomain) && isDate(maxDomain)) { - return [min, max] as Tuple; - } - - // TODO: There might be an edge case here where we have mixed types - return getDomainFromMinMax(minDomain as number, maxDomain as number); -} diff --git a/packages/victory-core/src/v37/victory-state/helpers/get-range.test.ts b/packages/victory-core/src/v37/victory-state/helpers/get-range.test.ts deleted file mode 100644 index db24edce7..000000000 --- a/packages/victory-core/src/v37/victory-state/helpers/get-range.test.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { getRange } from "victory-core/lib/v37/victory-state/helpers/get-range"; - -describe("getRange", () => { - it("returns a range from props", () => { - const props = { - range: [0, 1], - }; - expect(getRange(props, "x")).toEqual([0, 1]); - }); - - it("returns a range based on props and axis", () => { - const props = { - width: 100, - height: 200, - padding: 0, - }; - const x = getRange(props, "x"); - expect(Array.isArray(x)).toBe(true); - expect(x).toHaveLength(2); - expect(x).toEqual([0, 100]); - - const y = getRange(props, "y"); - expect(Array.isArray(y)).toBe(true); - expect(y).toHaveLength(2); - expect(y).toEqual([200, 0]); - }); -}); diff --git a/packages/victory-core/src/v37/victory-state/helpers/get-range.ts b/packages/victory-core/src/v37/victory-state/helpers/get-range.ts deleted file mode 100644 index 917d3dabe..000000000 --- a/packages/victory-core/src/v37/victory-state/helpers/get-range.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { AxisType, Padding, RangeTuple } from "../../../types/prop-types"; -import { getPadding } from "../../../victory-util/helpers"; -import { getValueForAxis, isTuple } from "../../../victory-util/type-helpers"; -import { VictoryProviderProps } from "../types"; - -type RangeProps = Pick< - VictoryProviderProps, - "range" | "padding" | "height" | "width" ->; - -// TODO: Should we store these defaults somewhere? -const DEFAULT_HEIGHT = 300; -const DEFAULT_WIDTH = 450; - -// TODO: This does not include polar range -export function getRange( - { - range, - height = DEFAULT_HEIGHT, - width = DEFAULT_WIDTH, - ...props - }: RangeProps, - axis: AxisType, -) { - const rangeFromProps = getValueForAxis(range, axis); - - if (isTuple(rangeFromProps)) { - return rangeFromProps; - } - - // TODO: Convert this to TS - const padding = getPadding({ padding: props.padding }) as Padding; - const rangeForAxis = { - x: [padding.left, width - padding.right], - y: [height - padding.top, padding.bottom], - }; - - return rangeForAxis[axis]; -} diff --git a/packages/victory-core/src/v37/victory-state/helpers/get-scale.test.ts b/packages/victory-core/src/v37/victory-state/helpers/get-scale.test.ts deleted file mode 100644 index 578c1d7b3..000000000 --- a/packages/victory-core/src/v37/victory-state/helpers/get-scale.test.ts +++ /dev/null @@ -1,61 +0,0 @@ -import * as d3Scale from "victory-vendor/d3-scale"; -import { getScale } from "victory-core/lib/v37/victory-state/helpers/get-scale"; - -describe("getScale", () => { - it("gets the d3 scale from props", () => { - expect(getScale({ scale: d3Scale.scaleLog }, "x")).toEqual( - d3Scale.scaleLog, - ); - }); - - it("gets the d3 scale from props for an axis", () => { - expect(getScale({ scale: { x: d3Scale.scaleLog } }, "x")).toEqual( - d3Scale.scaleLog, - ); - }); - - it("returns a default scale when data is provided", () => { - const props = { - data: [{ x: 0, y: 1 }], - }; - const scale = getScale(props, "x"); - expect(scale).toBeInstanceOf(Function); - // Scale should be d3Scale.scaleLinear - expect(scale().domain()).toEqual(d3Scale.scaleLinear().domain()); - expect(scale().range()).toEqual(d3Scale.scaleLinear().range()); - }); - - it("returns a default scale when nothing is provided", () => { - const scale = getScale({}, "x"); - expect(scale).toBeInstanceOf(Function); - // Scale should be d3Scale.scaleLinear - expect(scale().domain()).toEqual(d3Scale.scaleLinear().domain()); - expect(scale().range()).toEqual(d3Scale.scaleLinear().range()); - }); - - it("returns a scale when a single scale string is provided in props", () => { - const scale = getScale({ scale: "log" }, "x"); - expect(scale).toBeInstanceOf(Function); - // Scale should be d3Scale.scaleLog - expect(scale().domain()).toEqual(d3Scale.scaleLog().domain()); - expect(scale().range()).toEqual(d3Scale.scaleLog().range()); - }); - - it("returns a scale when a scale string is provided in props for an axis", () => { - const scale = getScale({ scale: { x: "log" } }, "x"); - expect(scale).toBeInstanceOf(Function); - // Scale should be d3Scale.scaleLog - expect(scale().domain()).toEqual(d3Scale.scaleLog().domain()); - expect(scale().range()).toEqual(d3Scale.scaleLog().range()); - }); - - it("returns a time scale when data contains dates", () => { - const props = { - data: [{ x: new Date("2016-01-13"), y: 1 }], - }; - const scale = getScale(props, "x"); - expect(scale).toBeInstanceOf(Function); - expect(scale().domain()).toEqual(d3Scale.scaleTime().domain()); - expect(scale().range()).toEqual(d3Scale.scaleTime().range()); - }); -}); diff --git a/packages/victory-core/src/v37/victory-state/helpers/get-scale.ts b/packages/victory-core/src/v37/victory-state/helpers/get-scale.ts deleted file mode 100644 index ad5220575..000000000 --- a/packages/victory-core/src/v37/victory-state/helpers/get-scale.ts +++ /dev/null @@ -1,67 +0,0 @@ -import { - scaleLinear, - scaleTime, - scaleLog, - scaleSqrt, -} from "victory-vendor/d3-scale"; -import { AxisType, D3ScaleFn, ScalePropType } from "../../../types/prop-types"; -import * as Collection from "../../../victory-util/collection"; -import { - getValueForAxis, - isFunction, -} from "../../../victory-util/type-helpers"; -import { VictoryProviderProps } from "../types"; -import { getAxisData } from "./get-axis-data"; - -type Scale = ScalePropType | D3ScaleFn; - -type ScaleProps = Pick; - -const DEFAULT_SCALE = scaleLinear; - -function isD3Scale(scale?: unknown): scale is D3ScaleFn { - return ( - isFunction(scale) && - isFunction(scale().copy) && - isFunction(scale().domain) && - isFunction(scale().range) - ); -} - -function getD3ScaleFromString(scale: ScalePropType): D3ScaleFn { - switch (scale) { - case "linear": - return scaleLinear; - case "time": - return scaleTime; - case "log": - return scaleLog; - case "sqrt": - return scaleSqrt; - default: - return DEFAULT_SCALE; - } -} - -export function getScale( - { data = [], ...props }: ScaleProps, - axis: AxisType, -): D3ScaleFn { - const scale = getValueForAxis(props.scale, axis); - - if (isD3Scale(scale)) { - return scale; - } - - if (typeof scale === "string") { - return getD3ScaleFromString(scale); - } - - const axisData = getAxisData(data, axis); - - if (Collection.containsDates(axisData)) { - return scaleTime; - } - - return DEFAULT_SCALE; -} diff --git a/packages/victory-core/src/v37/victory-state/index.ts b/packages/victory-core/src/v37/victory-state/index.ts deleted file mode 100644 index 7d809bc43..000000000 --- a/packages/victory-core/src/v37/victory-state/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export * from "./victory-provider"; -export * from "./types"; -export * from "./with-victory-provider"; diff --git a/packages/victory-core/src/v37/victory-state/types.ts b/packages/victory-core/src/v37/victory-state/types.ts deleted file mode 100644 index 2501b0df8..000000000 --- a/packages/victory-core/src/v37/victory-state/types.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { - D3ScaleFn, - Datum, - DomainTuple, - RangeTuple, - ScalePropType, - ValueOrAxes, -} from "../../types/prop-types"; -import { PaddingProps } from "../../victory-theme/types"; - -// These are all the props that are used to calculate data, domain, range, and scale -export interface VictoryCalculatedStateProps { - data?: Datum[]; - domain?: ValueOrAxes; - height?: number; - includeZero?: boolean; - maxDomain?: ValueOrAxes; - minDomain?: ValueOrAxes; - padding?: PaddingProps; - range?: ValueOrAxes; - samples?: number; - scale?: ValueOrAxes; - sortKey?: string; - sortOrder?: "ascending" | "descending"; - width?: number; - x?: string; - y?: string; -} - -export interface VictoryProviderProps extends VictoryCalculatedStateProps { - children?: React.ReactNode; -} diff --git a/packages/victory-core/src/v37/victory-state/victory-provider.test.ts b/packages/victory-core/src/v37/victory-state/victory-provider.test.ts deleted file mode 100644 index b4515d6f6..000000000 --- a/packages/victory-core/src/v37/victory-state/victory-provider.test.ts +++ /dev/null @@ -1,44 +0,0 @@ -import { useVictoryContext, VictoryProvider } from "victory-core/lib/v37"; -import { act, renderHook } from "@testing-library/react-hooks"; - -describe("Victory Provider", () => { - it("returns default values", () => { - const { result } = renderHook(() => useVictoryContext((c) => c), { - wrapper: VictoryProvider, - }); - - expect(result.current.data).toHaveLength(0); - - // @ts-expect-error I have no idea why x and y do not exist on this type - const { x, y } = result.current.scale; - expect(x.domain()).toEqual([0, 1]); - expect(y.domain()).toEqual([0, 1]); - expect(x.range()).toEqual([0, 450]); - expect(y.range()).toEqual([300, 0]); - }); - - it.skip("syncs the child props with the provider state", () => { - const { result } = renderHook(() => useVictoryContext((c) => c), { - wrapper: VictoryProvider, - }); - - act(() => { - result.current.updateChildProps(Symbol("chart-1"), { - data: [ - { x: 1, y: 1 }, - { x: 2, y: 2 }, - ], - }); - }); - act(() => { - result.current.updateChildProps(Symbol("chart-2"), { - data: [ - { x: 3, y: 3 }, - { x: 4, y: 4 }, - ], - }); - }); - - expect(result.current.domain).toEqual({ x: [1, 4], y: [1, 4] }); - }); -}); diff --git a/packages/victory-core/src/v37/victory-state/victory-provider.tsx b/packages/victory-core/src/v37/victory-state/victory-provider.tsx deleted file mode 100644 index 31507a12f..000000000 --- a/packages/victory-core/src/v37/victory-state/victory-provider.tsx +++ /dev/null @@ -1,152 +0,0 @@ -import * as React from "react"; -import { createContext, useContext } from "react"; -import { D3ScaleFn, DomainTuple, ForAxes } from "../../types/prop-types"; -import { FormattedDatum, getData } from "./helpers/get-data"; -import { getDomain } from "./helpers/get-domain"; -import { getRange } from "./helpers/get-range"; -import { getScale } from "./helpers/get-scale"; -import { VictoryCalculatedStateProps, VictoryProviderProps } from "./types"; - -type ScaleType = Required>; -type DomainType = Required>; - -export interface ContextType { - data: FormattedDatum[]; - scale: ScaleType; - domain: DomainType; - updateChildProps: (id: symbol, props: VictoryProviderProps | null) => void; -} - -const VictoryContext = createContext(null); - -type CollectedProps = { [id: symbol]: VictoryCalculatedStateProps }; - -function useNormalizedProps(): ContextType { - const [collectedProps, setCollectedProps] = React.useState( - {}, - ); - - const updateChildProps = React.useCallback( - (id: symbol, newProps: VictoryCalculatedStateProps | null) => { - setCollectedProps((prev) => { - const result = { ...prev }; - if (newProps === null) { - delete result[id]; - } else { - result[id] = newProps; - } - return result; - }); - }, - [], - ); - - // TEMP: combine all props into a single result: - // TODO: instead, we should intelligently aggregate all these props - const props = Object.values( - collectedProps, - ).reduce( - (result, childProps) => Object.assign(result, childProps), - {}, - ); - - const data = React.useMemo(() => { - return getData(props); - }, [props]); - - const domain = React.useMemo(() => { - return { - x: getDomain(props, "x"), - y: getDomain(props, "y"), - }; - }, [props]); - - const range = React.useMemo( - () => ({ - x: getRange(props, "x"), - y: getRange(props, "y"), - }), - [props], - ); - - const scale = React.useMemo(() => { - const xBaseScaleFn = getScale(props, "x"); - const yBaseScaleFn = getScale(props, "y"); - - // @ts-expect-error: This is a valid scale function - const xScaleFn = xBaseScaleFn().domain(domain.x).range(range.x); - // @ts-expect-error: This is a valid scale function - const yScaleFn = yBaseScaleFn().domain(domain.y).range(range.y); - - return { - x: xScaleFn, - y: yScaleFn, - }; - }, [props, domain, range]); - - const normalizedProps = React.useMemo( - () => ({ - scale, - data, - domain, - updateChildProps, - }), - [scale, data, domain, updateChildProps], - ); - - return normalizedProps; -} - -export function VictoryProvider({ - children, - // Disabled due to TODO below which will require this obj. spread - // eslint-disable-next-line @typescript-eslint/no-unused-vars - ...providerProps -}: VictoryProviderProps) { - const value = useNormalizedProps(); - - // TODO: sync the providerProps - - return ( - {children} - ); -} - -export function useVictoryContextMaybe( - selector: (value: ContextType | null) => T, -): T { - const context = useContext(VictoryContext); - return selector(context); -} - -export function useVictoryContext(selector: (value: ContextType) => T): T { - const context = useContext(VictoryContext); - if (!context) { - throw new Error("useVictoryContext must be used within a VictoryProvider"); - } - return selector(context); -} - -export function useScale() { - return useVictoryContext((value) => value.scale); -} - -export function useData() { - return useVictoryContext((value) => value.data); -} - -export function useDomain() { - return useVictoryContext((value) => value.domain); -} - -// This function keeps props in sync betwen the VictoryProvider and child components -export function useVictoryProviderSync(props: VictoryCalculatedStateProps) { - const updateChildProps = useVictoryContext((value) => value.updateChildProps); - const [myId] = React.useState(() => - Symbol("UniqueIdFor(VictoryProviderChild)"), - ); - - React.useEffect(() => { - updateChildProps(myId, props); - }, [updateChildProps, props, myId]); -} diff --git a/packages/victory-core/src/v37/victory-state/with-victory-provider.tsx b/packages/victory-core/src/v37/victory-state/with-victory-provider.tsx deleted file mode 100644 index 273efc6df..000000000 --- a/packages/victory-core/src/v37/victory-state/with-victory-provider.tsx +++ /dev/null @@ -1,53 +0,0 @@ -import * as React from "react"; -import { useVictoryContextMaybe, VictoryProvider } from "./victory-provider"; -import { VictoryCommonProps } from "../../victory-util/common-props"; -import { Clone } from "../clone"; -import { VictoryProviderProps } from "./types"; - -/* eslint-disable react/prop-types */ - -/** - * Ensures the component is wrapped by a VictoryProvider, if not already. - */ -export function withVictoryProvider< - TComp extends React.FC, - TProps extends React.PropsWithChildren, ->(Comp: TComp): TComp { - const WithVictoryProvider = React.memo((props: TProps) => { - const updateChildProps = useVictoryContextMaybe( - (value) => value?.updateChildProps, - ); - const hasParentProvider = !!updateChildProps; - - React.useEffect(() => { - if (!hasParentProvider) return; - - const id = Symbol("WithVictoryProvider"); - updateChildProps(id, props as VictoryProviderProps); - // eslint-disable-next-line consistent-return - return () => updateChildProps(id, null); - }); - - // @ts-expect-error "TProps not assignable to LibraryManagedAttributes" - let result = {props.children}; - - if (!hasParentProvider) { - // Wrap with a parent Provider: - result = ( - - - {result} - - - ); - } - return result; - }); - const name = Comp.displayName || Comp.name; - WithVictoryProvider.displayName = name - ? `WithVictoryProvider(${name})` - : "WithVictoryProvider"; - - // @ts-expect-error "WithVictoryProvider does not overlap with TComp" - return WithVictoryProvider as TComp; -} diff --git a/packages/victory-core/src/v37/with-container.tsx b/packages/victory-core/src/v37/with-container.tsx deleted file mode 100644 index e9028c62e..000000000 --- a/packages/victory-core/src/v37/with-container.tsx +++ /dev/null @@ -1,38 +0,0 @@ -import React from "react"; -import { VictoryProvider, VictoryProviderProps } from "./victory-state"; -import { VictoryContainer } from "../victory-container/victory-container"; -import { VictoryCommonProps } from "../victory-util/common-props"; - -const defaultProviderProps = { - width: 450, - height: 300, - padding: 50, - data: [], -}; - -export function withContainer( - WrappedComponent: React.FC, - initialProviderProps: Partial = {}, -): React.FC { - return (props: Props) => { - const providerProps = { - ...defaultProviderProps, - ...initialProviderProps, - ...props, - }; - const { standalone = true, containerComponent = } = - props; - if (standalone) { - return ( - - {React.cloneElement( - containerComponent, - providerProps, - , - )} - - ); - } - return ; - }; -} diff --git a/packages/victory-core/src/v37/with-normalized-props.test.tsx b/packages/victory-core/src/v37/with-normalized-props.test.tsx deleted file mode 100644 index 4cdd627d1..000000000 --- a/packages/victory-core/src/v37/with-normalized-props.test.tsx +++ /dev/null @@ -1,56 +0,0 @@ -import { VictoryCommonProps } from "victory-core"; -import { withNormalizedProps } from "victory-core/lib/v37/with-normalized-props"; -import PropTypes from "prop-types"; -import React from "react"; - -it("withNormalizedProps", () => { - type MyProps = VictoryCommonProps & { foo: "FOO"; bar: "BAR"; baz?: "BAZ" }; - const MyCompRaw = (props: MyProps) => { - return ( - - {[ - props.foo.toUpperCase(), - props.bar.toUpperCase(), - // @ts-expect-error "baz is possibly undefined" - props.baz.toUpperCase(), - ].join("\n")} - - ); - }; - const MyComp = withNormalizedProps( - { - displayName: "MyComp", - defaultProps: { bar: "BAR" }, - }, - MyCompRaw, - ); - - MyComp.propTypes = { - bar: PropTypes.oneOf(["BAR" as const]).isRequired, - baz: PropTypes.oneOf(["BAZ" as const]), - foo: PropTypes.oneOf(["FOO" as const]).isRequired, - }; - - // eslint-disable-next-line @typescript-eslint/no-unused-vars - function testTypes() { - ; - ; - ; - - // All should error: - // @ts-expect-error Invalid props - ; - // @ts-expect-error Invalid props - ; - // @ts-expect-error Invalid props - ; - // @ts-expect-error Invalid props - ; - // @ts-expect-error Invalid props - ; - // @ts-expect-error Invalid props - ; - // @ts-expect-error Invalid props - ; - } -}); diff --git a/packages/victory-core/src/v37/with-normalized-props.tsx b/packages/victory-core/src/v37/with-normalized-props.tsx deleted file mode 100644 index 19231139f..000000000 --- a/packages/victory-core/src/v37/with-normalized-props.tsx +++ /dev/null @@ -1,43 +0,0 @@ -import { VictoryCommonProps } from "../victory-util/common-props"; -import React from "react"; -import { - useVictoryContext, - VictoryProviderProps, - withVictoryProvider, -} from "./victory-state"; - -type FC = (props: TProps) => JSX.Element; - -export function withNormalizedProps< - TProps extends React.PropsWithChildren, - TDefaultPropKeys extends keyof TProps, ->( - config: { - displayName: string; - propTypes?: React.WeakValidationMap>; - defaultProps: Pick; - /** @deprecated */ - initialProviderProps?: Partial; - }, - WrappedComponent: React.FC, -) { - WrappedComponent.displayName = config.displayName; - const WithNormalizedProps: FC = withVictoryProvider< - FC, - TProps - >((props: TProps) => { - const normalizedProps = useVictoryContext((v) => v); - - return ( - - {props.children} - - ); - }); - - return Object.assign(WithNormalizedProps, { - displayName: `WithNormalizedProps(${config.displayName}`, - defaultProps: config.defaultProps, - propTypes: config.propTypes, - }); -} diff --git a/packages/victory-line/src/v37/victory-line.stories.tsx b/packages/victory-line/src/v37/victory-line.stories.tsx deleted file mode 100644 index c2888cb45..000000000 --- a/packages/victory-line/src/v37/victory-line.stories.tsx +++ /dev/null @@ -1,30 +0,0 @@ -/* eslint-disable react/no-multi-comp */ -/* eslint-disable no-magic-numbers */ -import * as React from "react"; -import { VictoryLine } from "./victory-line"; -import VictoryChart from "victory-chart/es/v37/victory-chart"; -import { getData } from "../../../../stories/data"; - -export default { - title: "v37/VictoryLine", - parameters: { - chromatic: { disableSnapshot: true }, - }, - component: VictoryLine, -}; - -export const Demo = (props) => { - return ; -}; - -Demo.args = { - lineRatio: 0.5, -}; - -export const WithChart = (props) => { - return ( - - - - ); -}; diff --git a/packages/victory-line/src/v37/victory-line.tsx b/packages/victory-line/src/v37/victory-line.tsx deleted file mode 100644 index 78b85a38d..000000000 --- a/packages/victory-line/src/v37/victory-line.tsx +++ /dev/null @@ -1,84 +0,0 @@ -import PropTypes from "prop-types"; -import React from "react"; -import { Curve, CurveProps } from "../curve"; -import { - InterpolationPropType, - VictoryClipContainer, - VictoryClipContainerProps, - VictoryCommonProps, - VictoryContainer, - VictoryDatableProps, - VictoryLabel, - VictoryLabelableProps, - VictoryLabelProps, - VictoryStyleInterface, - VictoryTheme, -} from "victory-core"; -import { withNormalizedProps, Clone } from "victory-core/es/v37"; - -export interface VictoryLineProps - extends VictoryCommonProps, - VictoryDatableProps, - VictoryLabelableProps { - // eslint-disable-next-line @typescript-eslint/ban-types - interpolation?: InterpolationPropType | Function; - samples?: number; - style?: VictoryStyleInterface; - animate?: boolean; -} - -export const VictoryLine = withNormalizedProps( - { - displayName: "VictoryLine", - propTypes: { - interpolation: PropTypes.oneOfType([ - PropTypes.oneOf([ - "basis", - "bundle", - "cardinal", - "catmullRom", - "linear", - "monotoneX", - "monotoneY", - "natural", - "step", - "stepAfter", - "stepBefore", - ] as const), - PropTypes.func, - ]), - }, - defaultProps: { - width: 450, - height: 300, - padding: 50, - data: [ - { x: 1, y: 1 }, - { x: 2, y: 2 }, - { x: 3, y: 3 }, - { x: 4, y: 4 }, - ], - containerComponent: , - dataComponent: () as React.ReactElement, - interpolation: "linear", - labelComponent: ( - - ) as React.ReactElement, - groupComponent: ( - - ) as React.ReactElement, - samples: 50, - sortKey: "x", - sortOrder: "ascending", - standalone: true, - theme: VictoryTheme.grayscale, - }, - }, - (props: VictoryLineProps) => { - return ( - - - - ); - }, -);