Skip to content

Commit

Permalink
Migrate victory-selection-container to TS (#2706)
Browse files Browse the repository at this point in the history
  • Loading branch information
KenanYusuf authored Jan 10, 2024
1 parent d8ae39a commit c4be363
Show file tree
Hide file tree
Showing 9 changed files with 86 additions and 113 deletions.
5 changes: 5 additions & 0 deletions .changeset/orange-items-cross.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"victory-selection-container": patch
---

Migrated victory-selection-container to TypeScript
3 changes: 2 additions & 1 deletion packages/victory-selection-container/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@
"react": ">=16.6.0"
},
"devDependencies": {
"victory-bar": "^36.8.1"
"victory-bar": "^36.8.1",
"victory-selection-container": "*"
},
"publishConfig": {
"provenance": true
Expand Down
41 changes: 0 additions & 41 deletions packages/victory-selection-container/src/index.d.ts

This file was deleted.

5 changes: 0 additions & 5 deletions packages/victory-selection-container/src/index.js

This file was deleted.

2 changes: 2 additions & 0 deletions packages/victory-selection-container/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from "./victory-selection-container";
export * from "./selection-helpers";
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { assign } from "lodash";
import React from "react";
import { VictoryBar } from "victory-bar";
import SelectionHelpers from "victory-selection-container/lib/selection-helpers";
import { SelectionHelpers } from "victory-selection-container";
import * as d3Scale from "victory-vendor/d3-scale";

const scale = { x: d3Scale.scaleLinear(), y: d3Scale.scaleLinear() };
Expand Down Expand Up @@ -47,12 +47,7 @@ describe("helpers/selection", () => {
},
];
const props = { scale, x1: 0, y1: 0, x2: 0.5, y2: 0.5 };
const bounds = { x: [0, 1], y: [10, 15] };
const filteredData = SelectionHelpers.filterDatasets(
props,
datasets,
bounds,
);
const filteredData = SelectionHelpers.filterDatasets(props, datasets);
expect(filteredData).toBeNull();
});

Expand All @@ -63,13 +58,8 @@ describe("helpers/selection", () => {
];
const childName = "a";
const datasets = [{ childName, data }];
const bounds = { x: [0, 1], y: [0, 10] };
const props = { scale, x1: 0, y1: 0, x2: 0.5, y2: 0.5 };
const filteredData = SelectionHelpers.filterDatasets(
props,
datasets,
bounds,
);
const filteredData = SelectionHelpers.filterDatasets(props, datasets);
const expected = { eventKey: [0], data: [data[0]] };
expect(filteredData).toEqual([assign({ childName }, expected)]);
});
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
import { Selection, Data, Helpers } from "victory-core";
import { Selection, Data, Helpers, Datum } from "victory-core";
import { assign, defaults, throttle, isFunction, includes } from "lodash";
import React from "react";

const SelectionHelpers = {
const ON_MOUSE_MOVE_THROTTLE_MS = 16;

class SelectionHelpersClass {
getDimension(props) {
const { horizontal, selectionDimension } = props;
if (!horizontal || !selectionDimension) {
return selectionDimension;
}
return selectionDimension === "x" ? "y" : "x";
},
}

getDatasets(props) {
if (props.data) {
Expand Down Expand Up @@ -38,11 +40,11 @@ const SelectionHelpers = {
iteratee,
props,
);
},
}

filterDatasets(props, datasets, bounds) {
filterDatasets(props, datasets) {
const filtered = datasets.reduce((memo, dataset) => {
const selectedData = this.getSelectedData(props, dataset.data, bounds);
const selectedData = this.getSelectedData(props, dataset.data);
memo = selectedData
? memo.concat({
childName: dataset.childName,
Expand All @@ -53,7 +55,7 @@ const SelectionHelpers = {
return memo;
}, []);
return filtered.length ? filtered : null;
},
}

getSelectedData(props, dataset) {
const { x1, y1, x2, y2 } = props;
Expand All @@ -66,8 +68,8 @@ const SelectionHelpers = {
scaledPoint.y <= Math.max(y1, y2)
);
};
const eventKey = [];
const data = [];
const eventKey: number[] = [];
const data: Datum[] = [];
let count = 0;
for (let index = 0, len = dataset.length; index < len; index++) {
const datum = dataset[index];
Expand All @@ -78,10 +80,9 @@ const SelectionHelpers = {
}
}
return count > 0 ? { eventKey, data } : null;
},
}

// eslint-disable-next-line complexity, max-statements
onMouseDown(evt, targetProps) {
onMouseDown = (evt, targetProps) => {
evt.preventDefault();
const { activateSelectedData, allowSelection, polar, selectedData } =
targetProps;
Expand Down Expand Up @@ -126,9 +127,9 @@ const SelectionHelpers = {
: [];

return parentMutation.concat(...dataMutation);
},
};

onMouseMove(evt, targetProps) {
private handleMouseMove = (evt, targetProps) => {
const { allowSelection, select, polar } = targetProps;
const dimension = this.getDimension(targetProps);
if (!allowSelection || !select) {
Expand All @@ -150,9 +151,14 @@ const SelectionHelpers = {
return { x2, y2, parentSVG };
},
};
},
};

onMouseMove = throttle(this.handleMouseMove, ON_MOUSE_MOVE_THROTTLE_MS, {
leading: true,
trailing: false,
});

onMouseUp(evt, targetProps) {
onMouseUp = (evt, targetProps) => {
const { activateSelectedData, allowSelection, x2, y2 } = targetProps;
if (!allowSelection) {
return null;
Expand All @@ -169,7 +175,7 @@ const SelectionHelpers = {
}
const datasets = this.getDatasets(targetProps);
const bounds = Selection.getBounds(targetProps);
const selectedData = this.filterDatasets(targetProps, datasets, bounds);
const selectedData = this.filterDatasets(targetProps, datasets);
const mutatedProps = {
selectedData,
datasets,
Expand Down Expand Up @@ -209,16 +215,7 @@ const SelectionHelpers = {
: [];

return parentMutation.concat(dataMutation);
},
};

export default {
...SelectionHelpers,
onMouseDown: SelectionHelpers.onMouseDown.bind(SelectionHelpers),
onMouseUp: SelectionHelpers.onMouseUp.bind(SelectionHelpers),
onMouseMove: throttle(
SelectionHelpers.onMouseMove.bind(SelectionHelpers),
16, // eslint-disable-line no-magic-numbers
{ leading: true, trailing: false },
),
};
};
}

export const SelectionHelpers = new SelectionHelpersClass();
Original file line number Diff line number Diff line change
@@ -1,23 +1,45 @@
import PropTypes from "prop-types";
import React from "react";
import { VictoryContainer, Rect } from "victory-core";
import SelectionHelpers from "./selection-helpers";
import {
Datum,
Rect,
VictoryContainer,
VictoryContainerProps,
} from "victory-core";
import { SelectionHelpers } from "./selection-helpers";

export const selectionContainerMixin = (base) =>
class VictorySelectionContainer extends base {
export interface VictorySelectionContainerProps extends VictoryContainerProps {
activateSelectedData?: boolean;
allowSelection?: boolean;
disable?: boolean;
onSelection?: (
points: {
childName?: string | string[];
eventKey?: string | number;
data?: Datum[];
}[],
bounds: {
x: number | Date;
y: number | Date;
}[],
props: VictorySelectionContainerProps,
) => void;
horizontal?: boolean;
onSelectionCleared?: (props: VictorySelectionContainerProps) => void;
selectionBlacklist?: string[];
selectionComponent?: React.ReactElement;
selectionDimension?: "x" | "y";
selectionStyle?: React.CSSProperties;
}

type ComponentClass<TProps> = { new (props: TProps): React.Component<TProps> };

export function selectionContainerMixin<
TBase extends ComponentClass<TProps>,
TProps extends VictorySelectionContainerProps,
>(Base: TBase) {
// @ts-expect-error "TS2545: A mixin class must have a constructor with a single rest parameter of type 'any[]'."
return class VictorySelectionContainer extends Base {
static displayName = "VictorySelectionContainer";
static propTypes = {
...VictoryContainer.propTypes,
activateSelectedData: PropTypes.bool,
allowSelection: PropTypes.bool,
disable: PropTypes.bool,
onSelection: PropTypes.func,
onSelectionCleared: PropTypes.func,
selectionBlacklist: PropTypes.arrayOf(PropTypes.string),
selectionComponent: PropTypes.element,
selectionDimension: PropTypes.oneOf(["x", "y"]),
selectionStyle: PropTypes.object,
};
static defaultProps = {
...VictoryContainer.defaultProps,
activateSelectedData: true,
Expand All @@ -30,7 +52,7 @@ export const selectionContainerMixin = (base) =>
},
};

static defaultEvents = (props) => {
static defaultEvents = (props: TProps) => {
return [
{
target: "parent",
Expand Down Expand Up @@ -90,12 +112,12 @@ export const selectionContainerMixin = (base) =>
}

// Overrides method in VictoryContainer
getChildren(props) {
getChildren(props: TProps) {
return [...React.Children.toArray(props.children), this.getRect(props)];
}
};
}

export default selectionContainerMixin(VictoryContainer);
// @ts-expect-error IMPORTANT: when converting this file to TypeScript, you must export the type as well:
// export const VictorySelectionContainer = selectionContainerMixin(VictoryContainer);
// export type VictorySelectionContainer = typeof VictorySelectionContainer;
export const VictorySelectionContainer =
selectionContainerMixin(VictoryContainer);
export type VictorySelectionContainer = typeof VictorySelectionContainer;
2 changes: 2 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 comment on commit c4be363

@vercel
Copy link

@vercel vercel bot commented on c4be363 Jan 10, 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.