Skip to content

Commit

Permalink
Migrate victory-voronoi to TypeScript (#2726)
Browse files Browse the repository at this point in the history
  • Loading branch information
KenanYusuf authored Jan 19, 2024
1 parent bb87499 commit e42ba31
Show file tree
Hide file tree
Showing 7 changed files with 73 additions and 100 deletions.
5 changes: 5 additions & 0 deletions .changeset/long-files-itch.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"victory-voronoi": patch
---

Migrate victory-voronoi to TypeScript
46 changes: 0 additions & 46 deletions packages/victory-voronoi/src/index.d.ts

This file was deleted.

2 changes: 0 additions & 2 deletions packages/victory-voronoi/src/index.js

This file was deleted.

2 changes: 2 additions & 0 deletions packages/victory-voronoi/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from "./victory-voronoi";
export * from "./voronoi";
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React from "react";
import { random, range } from "lodash";
import { calculateD3Path } from "../../../test/helpers";
import { VictoryVoronoi, Voronoi } from "victory-voronoi";
import { VictoryVoronoi, VictoryVoronoiProps, Voronoi } from "victory-voronoi";
import { fireEvent, render, screen } from "@testing-library/react";

describe("components/victory-voronoi", () => {
Expand All @@ -19,8 +19,8 @@ describe("components/victory-voronoi", () => {
it("renders an svg with the correct width and height", () => {
const { container } = render(<VictoryVoronoi />);
const svg = container.querySelector("svg");
expect(svg.style.width).toEqual("100%");
expect(svg.style.height).toEqual("100%");
expect(svg?.style.width).toEqual("100%");
expect(svg?.style.height).toEqual("100%");
});

it("renders an svg with the correct viewbox", () => {
Expand All @@ -33,7 +33,7 @@ describe("components/victory-voronoi", () => {

describe("component rendering with data", () => {
it("renders the correct d3 path", () => {
const props = {
const props: VictoryVoronoiProps = {
width: 400,
height: 300,
padding: 50,
Expand Down Expand Up @@ -68,7 +68,7 @@ describe("components/victory-voronoi", () => {

const renderedDataProps = screen
.getAllByTestId("voronoi-1")
.map((node) => JSON.parse(node.getAttribute("data-props-json")));
.map((node) => JSON.parse(node.getAttribute("data-props-json") || ""));
expect(renderedDataProps.map((props) => props.datum._x)).toEqual([
0, 1, 2, 3, 4,
]);
Expand All @@ -91,7 +91,7 @@ describe("components/victory-voronoi", () => {

const renderedDataProps = screen
.getAllByTestId("voronoi-1")
.map((node) => JSON.parse(node.getAttribute("data-props-json")));
.map((node) => JSON.parse(node.getAttribute("data-props-json") || ""));

expect(renderedDataProps.map((props) => props.datum._x)).toEqual([
4, 3, 2, 1, 0,
Expand Down Expand Up @@ -125,7 +125,7 @@ describe("components/victory-voronoi", () => {
/>,
);
const svg = container.querySelector("svg");
fireEvent.click(svg);
fireEvent.click(svg!);
expect(clickHandler).toBeCalled();
// the first argument is the standard evt object
expect(Object.keys(clickHandler.mock.calls[0][1])).toEqual(
Expand Down Expand Up @@ -164,7 +164,7 @@ describe("components/victory-voronoi", () => {
const clickHandler = jest.fn();
const { container } = render(
<VictoryVoronoi
label="okay"
labels={["okay"]}
events={[
{
target: "labels",
Expand All @@ -176,8 +176,7 @@ describe("components/victory-voronoi", () => {

const labels = container.querySelectorAll("text");

// TODO: figure out why there's no labels rendering?
expect(labels).toHaveLength(0);
expect(labels).toHaveLength(1);

labels.forEach((node, index) => {
clickHandler.mockClear();
Expand Down Expand Up @@ -211,7 +210,7 @@ describe("components/victory-voronoi", () => {
dataComponent={
<Voronoi
ariaLabel={({ datum }) => `${datum.x}`}
tabIndex={({ index }) => index + 6}
tabIndex={({ index }) => Number(index) + 6}
/>
}
/>,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import React from "react";
import {
PropTypes as CustomPropTypes,
Helpers,
VictoryLabel,
addEvents,
Expand All @@ -9,20 +8,46 @@ import {
DefaultTransitions,
Data,
Domain,
CommonProps,
UserProps,
EventPropTypeInterface,
EventsMixinClass,
VictoryCommonProps,
VictoryDatableProps,
VictoryLabelableProps,
VictoryMultiLabelableProps,
VictoryStyleInterface,
} from "victory-core";
import Voronoi from "./voronoi";
import { Voronoi } from "./voronoi";
import { getBaseProps } from "./helper-methods";

export type VictoryVoronoiSortOrderType = "ascending" | "descending";

export interface VictoryVoronoiProps
extends Omit<VictoryCommonProps, "polar">,
VictoryDatableProps,
VictoryLabelableProps,
VictoryMultiLabelableProps {
events?: EventPropTypeInterface<
string,
string | number | (string | number)[]
>[];
type?: number;
sortOrder?: VictoryVoronoiSortOrderType;
size?: number | { (data: any): number };
style?: VictoryStyleInterface;
}

const fallbackProps = {
width: 450,
height: 300,
padding: 50,
};

class VictoryVoronoi extends React.Component {
static animationWhitelist = [
// eslint-disable-next-line @typescript-eslint/no-empty-interface
interface VictoryVoronoiBase extends EventsMixinClass<VictoryVoronoiProps> {}

class VictoryVoronoiBase extends React.Component<VictoryVoronoiProps> {
static animationWhitelist: (keyof VictoryVoronoiProps)[] = [
"data",
"domain",
"height",
Expand All @@ -37,13 +62,7 @@ class VictoryVoronoi extends React.Component {
static role = "voronoi";
static defaultTransitions = DefaultTransitions.discreteTransitions();

static propTypes = {
...CommonProps.baseProps,
...CommonProps.dataProps,
size: CustomPropTypes.nonNegative,
};

static defaultProps = {
static defaultProps: VictoryVoronoiProps = {
containerComponent: <VictoryContainer />,
dataComponent: <Voronoi />,
labelComponent: <VictoryLabel />,
Expand All @@ -56,8 +75,9 @@ class VictoryVoronoi extends React.Component {

static getDomain = Domain.getDomain;
static getData = Data.getData;
static getBaseProps = (props) => getBaseProps(props, fallbackProps);
static expectedComponents = [
static getBaseProps = (props: VictoryVoronoiProps) =>
getBaseProps(props, fallbackProps);
static expectedComponents: (keyof VictoryVoronoiProps)[] = [
"dataComponent",
"labelComponent",
"groupComponent",
Expand All @@ -69,7 +89,7 @@ class VictoryVoronoi extends React.Component {
return !!this.props.animate;
}

render() {
render(): React.ReactElement {
const { animationWhitelist, role } = VictoryVoronoi;
const props = Helpers.modifyProps(this.props, fallbackProps, role);

Expand All @@ -87,4 +107,4 @@ class VictoryVoronoi extends React.Component {
}
}

export default addEvents(VictoryVoronoi);
export const VictoryVoronoi = addEvents(VictoryVoronoiBase);
Original file line number Diff line number Diff line change
@@ -1,24 +1,35 @@
/* eslint no-magic-numbers: ["error", { "ignore": [2] }]*/
import React from "react";
import PropTypes from "prop-types";
import { assign } from "lodash";
import {
Helpers,
CommonProps,
ClipPath,
Path,
Circle,
UserProps,
VictoryCommonPrimitiveProps,
} from "victory-core";

const getVoronoiPath = (props) => {
export interface VoronoiProps extends VictoryCommonPrimitiveProps {
circleComponent?: React.ReactElement;
clipId?: number | string;
clipPathComponent?: React.ReactElement;
datum?: any;
groupComponent?: React.ReactElement;
pathComponent?: React.ReactElement;
polygon?: [];
size?: number;
x?: number;
y?: number;
}

const getVoronoiPath = (props: VoronoiProps) => {
const { polygon } = props;
return Array.isArray(polygon) && polygon.length
? `M ${props.polygon.join("L")} Z`
? `M ${props.polygon?.join("L")} Z`
: "";
};

const evaluateProps = (props) => {
function evaluateProps<T extends VoronoiProps>(props: T) {
/**
* Potential evaluated props are:
* `aria-label`
Expand All @@ -33,7 +44,7 @@ const evaluateProps = (props) => {
const style = Helpers.evaluateStyle(props.style, props);
const tabIndex = Helpers.evaluateProp(props.tabIndex, props);
return assign({}, props, { ariaLabel, id, size, style, tabIndex });
};
}

const defaultProps = {
pathComponent: <Path />,
Expand All @@ -44,9 +55,8 @@ const defaultProps = {
shapeRendering: "auto",
};

const Voronoi = (initialProps) => {
export const Voronoi = (initialProps: VoronoiProps) => {
const props = evaluateProps({ ...defaultProps, ...initialProps });

const {
ariaLabel,
role,
Expand All @@ -58,6 +68,7 @@ const Voronoi = (initialProps) => {
size,
tabIndex,
} = props;

const voronoiPath = getVoronoiPath(props);
const sharedProps = {
"aria-label": ariaLabel,
Expand Down Expand Up @@ -99,19 +110,3 @@ const Voronoi = (initialProps) => {
d: voronoiPath,
});
};

Voronoi.propTypes = {
...CommonProps.primitiveProps,
circleComponent: PropTypes.element,
clipId: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
clipPathComponent: PropTypes.element,
datum: PropTypes.object,
groupComponent: PropTypes.element,
pathComponent: PropTypes.element,
polygon: PropTypes.array,
size: PropTypes.number,
x: PropTypes.number,
y: PropTypes.number,
};

export default Voronoi;

1 comment on commit e42ba31

@vercel
Copy link

@vercel vercel bot commented on e42ba31 Jan 19, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.