From 1da45d319d924cf6995797a2b033da48da3cf4bc Mon Sep 17 00:00:00 2001 From: Kenan Yusuf Date: Fri, 19 Jan 2024 16:44:32 +0000 Subject: [PATCH] Migrate victory-voronoi-container to TypeScript (#2727) --- .changeset/olive-bananas-stare.md | 5 ++ .../victory-voronoi-container/src/index.d.ts | 44 ------------ .../victory-voronoi-container/src/index.js | 5 -- .../victory-voronoi-container/src/index.ts | 2 + ...ainer.js => victory-voronoi-container.tsx} | 70 +++++++++---------- ...{voronoi-helpers.js => voronoi-helpers.ts} | 54 +++++++------- 6 files changed, 67 insertions(+), 113 deletions(-) create mode 100644 .changeset/olive-bananas-stare.md delete mode 100644 packages/victory-voronoi-container/src/index.d.ts delete mode 100644 packages/victory-voronoi-container/src/index.js create mode 100644 packages/victory-voronoi-container/src/index.ts rename packages/victory-voronoi-container/src/{victory-voronoi-container.js => victory-voronoi-container.tsx} (82%) rename packages/victory-voronoi-container/src/{voronoi-helpers.js => voronoi-helpers.ts} (93%) diff --git a/.changeset/olive-bananas-stare.md b/.changeset/olive-bananas-stare.md new file mode 100644 index 000000000..e1494608f --- /dev/null +++ b/.changeset/olive-bananas-stare.md @@ -0,0 +1,5 @@ +--- +"victory-voronoi-container": patch +--- + +Migrate victory-voronoi-container to TypeScript diff --git a/packages/victory-voronoi-container/src/index.d.ts b/packages/victory-voronoi-container/src/index.d.ts deleted file mode 100644 index 341c1826a..000000000 --- a/packages/victory-voronoi-container/src/index.d.ts +++ /dev/null @@ -1,44 +0,0 @@ -import * as React from "react"; -import { PaddingProps, VictoryContainerProps } from "victory-core"; - -export interface VictoryVoronoiContainerProps extends VictoryContainerProps { - activateData?: boolean; - activateLabels?: boolean; - disable?: boolean; - labels?: (point: any, index: number, points: any[]) => string; - labelComponent?: React.ReactElement; - mouseFollowTooltips?: boolean; - onActivated?: (points: any[], props: VictoryVoronoiContainerProps) => void; - onDeactivated?: (points: any[], props: VictoryVoronoiContainerProps) => void; - radius?: number; - voronoiBlacklist?: (string | RegExp)[]; - voronoiDimension?: "x" | "y"; - voronoiPadding?: PaddingProps; -} - -export class VictoryVoronoiContainer extends React.Component< - VictoryVoronoiContainerProps, - any -> {} - -export const VoronoiHelpers: { - withinBounds(props: any, point: any): any; - getDatasets(props: any): any; - findPoints(datasets: any, point: any): any; - withinRadius(point: any, mousePosition: any, radius: any): any; - getVoronoiPoints(props: any, mousePosition: any): any; - getActiveMutations(props: any, point: any): any; - getInactiveMutations(props: any, point: any): any; - getParentMutation( - activePoints: any, - mousePosition: any, - parentSVG: any, - vIndex: any, - ): any; - onActivated(props: any, points: any): any; - onDeactivated(props: any, points: any): any; - onMouseLeave(evt: any, targetProps: any): any; - onMouseMove(evt: any, targetProps: any): any; -}; - -export const voronoiContainerMixin: (base: Function) => Function; diff --git a/packages/victory-voronoi-container/src/index.js b/packages/victory-voronoi-container/src/index.js deleted file mode 100644 index bde28af9b..000000000 --- a/packages/victory-voronoi-container/src/index.js +++ /dev/null @@ -1,5 +0,0 @@ -export { - voronoiContainerMixin, - default as VictoryVoronoiContainer, -} from "./victory-voronoi-container"; -export { default as VoronoiHelpers } from "./voronoi-helpers"; diff --git a/packages/victory-voronoi-container/src/index.ts b/packages/victory-voronoi-container/src/index.ts new file mode 100644 index 000000000..313e652a9 --- /dev/null +++ b/packages/victory-voronoi-container/src/index.ts @@ -0,0 +1,2 @@ +export * from "./victory-voronoi-container"; +export * from "./voronoi-helpers"; diff --git a/packages/victory-voronoi-container/src/victory-voronoi-container.js b/packages/victory-voronoi-container/src/victory-voronoi-container.tsx similarity index 82% rename from packages/victory-voronoi-container/src/victory-voronoi-container.js rename to packages/victory-voronoi-container/src/victory-voronoi-container.tsx index 8bdc3e5ae..f2ed14ad3 100644 --- a/packages/victory-voronoi-container/src/victory-voronoi-container.js +++ b/packages/victory-voronoi-container/src/victory-voronoi-container.tsx @@ -1,44 +1,41 @@ /* eslint-disable react/no-multi-comp */ -import PropTypes from "prop-types"; import React from "react"; import { defaults, isFunction, pick } from "lodash"; import { VictoryTooltip } from "victory-tooltip"; import { VictoryContainer, Helpers, - PropTypes as CustomPropTypes, + VictoryContainerProps, + PaddingProps, } from "victory-core"; -import VoronoiHelpers from "./voronoi-helpers"; +import { VoronoiHelpers } from "./voronoi-helpers"; -export const voronoiContainerMixin = (base) => - class VictoryVoronoiContainer extends base { +type ComponentClass = { new (props: TProps): React.Component }; + +export interface VictoryVoronoiContainerProps extends VictoryContainerProps { + activateData?: boolean; + activateLabels?: boolean; + disable?: boolean; + labels?: (point: any, index: number, points: any[]) => string; + labelComponent?: React.ReactElement; + mouseFollowTooltips?: boolean; + onActivated?: (points: any[], props: VictoryVoronoiContainerProps) => void; + onDeactivated?: (points: any[], props: VictoryVoronoiContainerProps) => void; + radius?: number; + voronoiBlacklist?: (string | RegExp)[]; + voronoiDimension?: "x" | "y"; + voronoiPadding?: PaddingProps; +} + +export function voronoiContainerMixin< + TBase extends ComponentClass, + TProps extends VictoryVoronoiContainerProps, +>(Base: TBase) { + // @ts-expect-error "TS2545: A mixin class must have a constructor with a single rest parameter of type 'any[]'." + return class VictoryVoronoiContainer extends Base { static displayName = "VictoryVoronoiContainer"; - static propTypes = { - ...VictoryContainer.propTypes, - activateData: PropTypes.bool, - activateLabels: PropTypes.bool, - disable: PropTypes.bool, - labelComponent: PropTypes.element, - labels: PropTypes.func, - mouseFollowTooltips: PropTypes.bool, - onActivated: PropTypes.func, - onDeactivated: PropTypes.func, - radius: PropTypes.number, - voronoiBlacklist: PropTypes.arrayOf( - PropTypes.oneOfType([PropTypes.string, CustomPropTypes.regExp]), - ), - voronoiDimension: PropTypes.oneOf(["x", "y"]), - voronoiPadding: PropTypes.oneOfType([ - PropTypes.number, - PropTypes.shape({ - top: PropTypes.number, - bottom: PropTypes.number, - left: PropTypes.number, - right: PropTypes.number, - }), - ]), - }; - static defaultProps = { + + static defaultProps: VictoryVoronoiContainerProps = { ...VictoryContainer.defaultProps, activateData: true, activateLabels: true, @@ -46,7 +43,7 @@ export const voronoiContainerMixin = (base) => voronoiPadding: 5, }; - static defaultEvents = (props) => { + static defaultEvents = (props: VictoryVoronoiContainerProps) => { return [ { target: "parent", @@ -233,15 +230,14 @@ export const voronoiContainerMixin = (base) => } // Overrides method in VictoryContainer - getChildren(props) { + getChildren(props: VictoryVoronoiContainerProps) { return [ ...React.Children.toArray(props.children), this.getTooltip(props), ]; } }; +} -export default voronoiContainerMixin(VictoryContainer); -// @ts-expect-error IMPORTANT: when converting this file to TypeScript, you must export the type as well: -// export const VictoryVoronoiContainer = voronoiContainerMixin(VictoryContainer); -// export type VictoryVoronoiContainer = typeof VictoryVoronoiContainer; +export const VictoryVoronoiContainer = voronoiContainerMixin(VictoryContainer); +export type VictoryVoronoiContainer = typeof VictoryVoronoiContainer; diff --git a/packages/victory-voronoi-container/src/voronoi-helpers.js b/packages/victory-voronoi-container/src/voronoi-helpers.ts similarity index 93% rename from packages/victory-voronoi-container/src/voronoi-helpers.js rename to packages/victory-voronoi-container/src/voronoi-helpers.ts index 6f15bd373..25364f544 100644 --- a/packages/victory-voronoi-container/src/voronoi-helpers.js +++ b/packages/victory-voronoi-container/src/voronoi-helpers.ts @@ -1,18 +1,20 @@ import { Collection, Selection, Data, Helpers } from "victory-core"; import { assign, - throttle, isFunction, isEmpty, includes, isString, isRegExp, + throttle, } from "lodash"; import isEqual from "react-fast-compare"; import Delaunay from "delaunay-find/lib/index.js"; import React from "react"; -const VoronoiHelpers = { +const ON_MOUSE_MOVE_THROTTLE_MS = 32; + +class VoronoiHelpersClass { withinBounds(props, point) { const { width, height, polar, origin, scale } = props; const padding = Helpers.getPadding(props, "voronoiPadding"); @@ -29,7 +31,7 @@ const VoronoiHelpers = { y >= padding.top && y <= height - padding.bottom ); - }, + } getDatasets(props) { const minDomain = { @@ -37,7 +39,7 @@ const VoronoiHelpers = { y: Collection.getMinValue(props.domain.y), }; const children = React.Children.toArray(props.children); - const addMeta = (data, name, child) => { + const addMeta = (data, name?, child?) => { const continuous = child && child.type && child.type.continuous; const style = child ? child.props && child.props.style : props.style; return data.map((datum, index) => { @@ -91,13 +93,13 @@ const VoronoiHelpers = { }; return Helpers.reduceChildren(children, iteratee, props); - }, + } findPoints(datasets, point) { return datasets.filter((d) => { return point._voronoiX === d._voronoiX && point._voronoiY === d._voronoiY; }); - }, + } withinRadius(point, mousePosition, radius) { if (!point) { @@ -110,7 +112,7 @@ const VoronoiHelpers = { const distanceSquared = Math.pow(x - point[0], 2) + Math.pow(y - point[1], 2); return distanceSquared < Math.pow(radius, 2); - }, + } getVoronoiPoints(props, mousePosition) { const datasets = this.getDatasets(props); @@ -129,7 +131,7 @@ const VoronoiHelpers = { ? this.findPoints(datasets, datasets[index]) : []; return { points, index }; - }, + } getActiveMutations(props, point) { const { childName, continuous } = point; @@ -155,7 +157,7 @@ const VoronoiHelpers = { mutation: () => ({ active: true }), }; }); - }, + } getInactiveMutations(props, point) { const { childName, continuous } = point; @@ -180,10 +182,10 @@ const VoronoiHelpers = { mutation: () => null, }; }); - }, + } // eslint-disable-next-line max-params - getParentMutation(activePoints, mousePosition, parentSVG, vIndex) { + getParentMutation(activePoints, mousePosition?, parentSVG?, vIndex?) { return [ { target: "parent", @@ -191,21 +193,21 @@ const VoronoiHelpers = { mutation: () => ({ activePoints, mousePosition, parentSVG, vIndex }), }, ]; - }, + } onActivated(props, points) { if (isFunction(props.onActivated)) { props.onActivated(points, props); } - }, + } onDeactivated(props, points) { if (isFunction(props.onDeactivated)) { props.onDeactivated(points, props); } - }, + } - onMouseLeave(evt, targetProps) { + onMouseLeave = (evt, targetProps) => { const activePoints = targetProps.activePoints || []; this.onDeactivated(targetProps, activePoints); const inactiveMutations = activePoints.length @@ -214,9 +216,9 @@ const VoronoiHelpers = { ) : []; return this.getParentMutation([]).concat(...inactiveMutations); - }, + }; - onMouseMove(evt, targetProps) { + private handleMouseMove = (evt, targetProps) => { // eslint-disable-line max-statements const activePoints = targetProps.activePoints || []; const parentSVG = targetProps.parentSVG || Selection.getParentSVG(evt); @@ -256,14 +258,12 @@ const VoronoiHelpers = { ) : []; return parentMutations.concat(...inactiveMutations, ...activeMutations); - }, -}; + }; + + onMouseMove = throttle(this.handleMouseMove, ON_MOUSE_MOVE_THROTTLE_MS, { + leading: true, + trailing: false, + }); +} -export default { - onMouseLeave: VoronoiHelpers.onMouseLeave.bind(VoronoiHelpers), - onMouseMove: throttle( - VoronoiHelpers.onMouseMove.bind(VoronoiHelpers), - 32, // eslint-disable-line no-magic-numbers - { leading: true, trailing: false }, - ), -}; +export const VoronoiHelpers = new VoronoiHelpersClass();