Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Migrate victory-selection-container to TS #2706

Merged
merged 4 commits into from
Jan 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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.