diff --git a/.changeset/rare-cars-shake.md b/.changeset/rare-cars-shake.md new file mode 100644 index 000000000..8840905d4 --- /dev/null +++ b/.changeset/rare-cars-shake.md @@ -0,0 +1,5 @@ +--- +"victory-tooltip": patch +--- + +Convert victory-tooltip to TS diff --git a/packages/victory-tooltip/src/flyout.test.js b/packages/victory-tooltip/src/flyout.test.tsx similarity index 89% rename from packages/victory-tooltip/src/flyout.test.js rename to packages/victory-tooltip/src/flyout.test.tsx index a793efa5f..aa0918738 100644 --- a/packages/victory-tooltip/src/flyout.test.js +++ b/packages/victory-tooltip/src/flyout.test.tsx @@ -1,7 +1,9 @@ import React from "react"; -import { Flyout } from "victory-tooltip"; import { render } from "@testing-library/react"; +import { SVGWrapper } from "../../../test/helpers"; +import Flyout from './flyout'; + describe("victory-primitives/flyout", () => { const baseProps = { x: 100, @@ -17,7 +19,7 @@ describe("victory-primitives/flyout", () => { describe("rendering", () => { it("renders a flyout path", () => { const { container } = render(, { - wrapper: "svg", + wrapper: SVGWrapper, }); const path = container.querySelector("path"); diff --git a/packages/victory-tooltip/src/flyout.js b/packages/victory-tooltip/src/flyout.tsx similarity index 74% rename from packages/victory-tooltip/src/flyout.js rename to packages/victory-tooltip/src/flyout.tsx index df5dc0fe7..f4ac76b7a 100644 --- a/packages/victory-tooltip/src/flyout.js +++ b/packages/victory-tooltip/src/flyout.tsx @@ -1,15 +1,21 @@ /* eslint no-magic-numbers: ["error", { "ignore": [-1, 0, 1, 2] }]*/ import React from "react"; -import PropTypes from "prop-types"; -import { Helpers, CommonProps, Path, UserProps } from "victory-core"; +import { + Helpers, + Path, + UserProps, + VictoryCommonPrimitiveProps, + OrientationTypes, + NumberOrCallback, +} from "victory-core"; import { isPlainObject, assign } from "lodash"; const getVerticalPath = (props) => { const { pointerWidth, cornerRadius, orientation, width, height, center } = props; const sign = orientation === "bottom" ? 1 : -1; - const x = props.x + (props.dx || 0); - const y = props.y + (props.dy || 0); + const x = props.x || 0 + (props.dx || 0); + const y = props.y || 0 + (props.dy || 0); const centerX = isPlainObject(center) && center.x; const centerY = isPlainObject(center) && center.y; const pointerEdge = centerY + sign * (height / 2); @@ -66,14 +72,14 @@ const getHorizontalPath = (props) => { z`; }; -const getFlyoutPath = (props) => { +const getFlyoutPath = (props: FlyoutProps) => { const orientation = props.orientation || "top"; return orientation === "left" || orientation === "right" ? getHorizontalPath(props) : getVerticalPath(props); }; -const evaluateProps = (props) => { +const evaluateProps = (props: FlyoutProps) => { /** * Potential evaluated props are: * `id` @@ -91,38 +97,41 @@ const defaultProps = { shapeRendering: "auto", }; -const Flyout = (props) => { +export interface FlyoutProps extends VictoryCommonPrimitiveProps { + center?: { + x?: number | null; + y?: number | null; + }; + cornerRadius?: NumberOrCallback; + datum?: object; + dx?: NumberOrCallback; + dy?: NumberOrCallback; + height?: NumberOrCallback; + orientation?: OrientationTypes; + pathComponent?: React.ReactElement; + pointerLength?: NumberOrCallback; + pointerWidth?: NumberOrCallback; + width?: NumberOrCallback; + x?: number; + y?: number; +} + +export const Flyout: React.FC = (props) => { props = evaluateProps({ ...defaultProps, ...props }); const userProps = UserProps.getSafeUserProps(props); - return React.cloneElement(props.pathComponent, { - ...props.events, - ...userProps, - style: props.style, - d: getFlyoutPath(props), - className: props.className, - shapeRendering: props.shapeRendering, - role: props.role, - transform: props.transform, - clipPath: props.clipPath, - }); + return props.pathComponent + ? React.cloneElement(props.pathComponent, { + ...props.events, + ...userProps, + style: props.style, + d: getFlyoutPath(props), + className: props.className, + shapeRendering: props.shapeRendering, + role: props.role, + transform: props.transform, + clipPath: props.clipPath, + }) + : null; }; - -Flyout.propTypes = { - ...CommonProps.primitiveProps, - center: PropTypes.shape({ x: PropTypes.number, y: PropTypes.number }), - cornerRadius: PropTypes.number, - datum: PropTypes.object, - dx: PropTypes.number, - dy: PropTypes.number, - height: PropTypes.number, - orientation: PropTypes.oneOf(["top", "bottom", "left", "right"]), - pathComponent: PropTypes.element, - pointerLength: PropTypes.number, - pointerWidth: PropTypes.number, - width: PropTypes.number, - x: PropTypes.number, - y: PropTypes.number, -}; - export default Flyout; diff --git a/packages/victory-tooltip/src/index.d.ts b/packages/victory-tooltip/src/index.d.ts deleted file mode 100644 index 56a92f1e6..000000000 --- a/packages/victory-tooltip/src/index.d.ts +++ /dev/null @@ -1,92 +0,0 @@ -import * as React from "react"; -import { - OrientationTypes, - NumberOrCallback, - StringOrNumberOrCallback, - VictoryCommonProps, - VictoryLabelableProps, - VictoryThemeDefinition, - VictoryStyleObject, - VictoryLabelStyleObject, - PaddingOrCallback, - EventPropTypeInterface, -} from "victory-core"; - -export interface VictoryTooltipProps extends VictoryLabelableProps { - active?: boolean; - activateData?: boolean; - activePoints?: any[]; - angle?: string | number; - center?: { x: number | undefined; y: number | undefined }; - centerOffset?: { - x?: NumberOrCallback; - y?: NumberOrCallback; - }; - constrainToVisibleArea?: boolean; - cornerRadius?: NumberOrCallback; - datum?: {}; - data?: any[]; - dx?: NumberOrCallback; - dy?: NumberOrCallback; - groupComponent?: React.ReactElement; - height?: number; - horizontal?: boolean; - events?: { [key: string]: (event: React.SyntheticEvent) => void }; - flyoutHeight?: NumberOrCallback; - flyoutWidth?: NumberOrCallback; - flyoutStyle?: VictoryStyleObject; - flyoutComponent?: React.ReactElement; - flyoutPadding?: PaddingOrCallback; - index?: number | string; - orientation?: OrientationTypes | ((...args: any[]) => OrientationTypes); - pointerLength?: NumberOrCallback; - pointerOrientation?: - | OrientationTypes - | ((...args: any[]) => OrientationTypes); - pointerWidth?: NumberOrCallback; - renderInPortal?: boolean; - style?: VictoryLabelStyleObject | VictoryLabelStyleObject[]; - text?: StringOrNumberOrCallback | string[] | number[]; - theme?: VictoryThemeDefinition; - width?: number; - x?: number; - y?: number; -} - -export interface FlyoutProps extends VictoryCommonProps { - active?: boolean; - center?: { - x?: number; - y?: number; - }; - className?: string; - cornerRadius?: number; - data?: any[]; - datum?: object; - dx?: number; - dy?: number; - events?: object; - height?: number; - id?: string | number; - index?: number; - orientation?: OrientationTypes; - pathComponent?: React.ReactElement; - pointerLength?: number; - pointerWidth?: number; - role?: string; - shapeRendering?: string; - style?: VictoryStyleObject; - transform?: string; - width?: number; - x?: number; - y?: number; -} - -export class Flyout extends React.Component {} - -export class VictoryTooltip extends React.Component { - static defaultEvents: EventPropTypeInterface< - string, - StringOrNumberOrCallback - >[]; -} diff --git a/packages/victory-tooltip/src/index.js b/packages/victory-tooltip/src/index.js deleted file mode 100644 index 3e290c3e2..000000000 --- a/packages/victory-tooltip/src/index.js +++ /dev/null @@ -1,2 +0,0 @@ -export { default as VictoryTooltip } from "./victory-tooltip"; -export { default as Flyout } from "./flyout"; diff --git a/packages/victory-tooltip/src/index.ts b/packages/victory-tooltip/src/index.ts new file mode 100644 index 000000000..c5e666721 --- /dev/null +++ b/packages/victory-tooltip/src/index.ts @@ -0,0 +1,2 @@ +export * from "./victory-tooltip"; +export * from "./flyout"; diff --git a/packages/victory-tooltip/src/victory-tooltip.test.js b/packages/victory-tooltip/src/victory-tooltip.test.tsx similarity index 89% rename from packages/victory-tooltip/src/victory-tooltip.test.js rename to packages/victory-tooltip/src/victory-tooltip.test.tsx index cb6c918d0..644e78762 100644 --- a/packages/victory-tooltip/src/victory-tooltip.test.js +++ b/packages/victory-tooltip/src/victory-tooltip.test.tsx @@ -1,13 +1,14 @@ import React from "react"; -import { Flyout, VictoryTooltip } from "victory-tooltip"; import { VictoryContainer, VictoryLabel } from "victory-core"; import { fireEvent, screen, render } from "@testing-library/react"; +import Flyout from './flyout'; +import { VictoryTooltip, VictoryTooltipProps } from './victory-tooltip'; + describe("components/victory-tooltip", () => { const flyoutId = "flyout-1"; const labelId = "label-1"; - /** @type {VictoryTooltipProps} */ const baseProps = { x: 0, y: 0, @@ -17,7 +18,7 @@ describe("components/victory-tooltip", () => { text: "such text, wow", flyoutComponent: , labelComponent: , - }; + } as VictoryTooltipProps; it("renders nothing when not active", () => { render(, { @@ -32,7 +33,7 @@ describe("components/victory-tooltip", () => { const output = screen.getByTestId(labelId); expect(output).toBeInTheDocument(); expect(output).toBeVisible(); - expect(output).toHaveTextContent(baseProps.text); + expect(output).toHaveTextContent(baseProps.text as string); }); it("renders a flyout and a label", () => { diff --git a/packages/victory-tooltip/src/victory-tooltip.js b/packages/victory-tooltip/src/victory-tooltip.tsx similarity index 89% rename from packages/victory-tooltip/src/victory-tooltip.js rename to packages/victory-tooltip/src/victory-tooltip.tsx index 0335422b2..4c7cd0ca8 100644 --- a/packages/victory-tooltip/src/victory-tooltip.js +++ b/packages/victory-tooltip/src/victory-tooltip.tsx @@ -5,11 +5,19 @@ import { TextSize, Helpers, LabelHelpers, + NumberOrCallback, + PaddingOrCallback, + OrientationTypes, VictoryLabel, + VictoryLabelProps, + VictoryLabelableProps, + VictoryLabelStyleObject, + VictoryStyleObject, VictoryTheme, + VictoryThemeDefinition, VictoryPortal, } from "victory-core"; -import Flyout from "./flyout"; +import { Flyout } from "./flyout"; import { assign, defaults, uniqueId, isPlainObject, orderBy } from "lodash"; const fallbackProps = { @@ -18,10 +26,11 @@ const fallbackProps = { pointerWidth: 10, }; -export default class VictoryTooltip extends React.Component { +export class VictoryTooltip extends React.Component { static displayName = "VictoryTooltip"; static role = "tooltip"; static propTypes = { + ...VictoryLabel.propTypes, activateData: PropTypes.bool, active: PropTypes.oneOfType([PropTypes.bool, PropTypes.func]), activePoints: PropTypes.array, @@ -39,11 +48,6 @@ export default class VictoryTooltip extends React.Component { CustomPropTypes.nonNegative, PropTypes.func, ]), - data: PropTypes.array, - datum: PropTypes.object, - dx: PropTypes.oneOfType([PropTypes.number, PropTypes.func]), - dy: PropTypes.oneOfType([PropTypes.number, PropTypes.func]), - events: PropTypes.object, flyoutComponent: PropTypes.element, flyoutHeight: PropTypes.oneOfType([ CustomPropTypes.nonNegative, @@ -64,12 +68,8 @@ export default class VictoryTooltip extends React.Component { CustomPropTypes.nonNegative, PropTypes.func, ]), - groupComponent: PropTypes.element, - height: PropTypes.number, - horizontal: PropTypes.bool, id: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), index: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), - labelComponent: PropTypes.element, orientation: PropTypes.oneOfType([ PropTypes.oneOf(["top", "bottom", "left", "right"]), PropTypes.func, @@ -86,23 +86,8 @@ export default class VictoryTooltip extends React.Component { CustomPropTypes.nonNegative, PropTypes.func, ]), - polar: PropTypes.bool, - renderInPortal: PropTypes.bool, - scale: PropTypes.shape({ - x: CustomPropTypes.scale, - y: CustomPropTypes.scale, - }), style: PropTypes.oneOfType([PropTypes.object, PropTypes.array]), - text: PropTypes.oneOfType([ - PropTypes.string, - PropTypes.number, - PropTypes.func, - PropTypes.array, - ]), - theme: PropTypes.object, width: PropTypes.number, - x: PropTypes.number, - y: PropTypes.number, }; static defaultProps = { @@ -141,7 +126,9 @@ export default class VictoryTooltip extends React.Component { ]; }; - constructor(props) { + id: number | string; + + constructor(props: VictoryTooltipProps) { super(props); this.id = props.id === undefined ? uniqueId("tooltip-") : props.id; } @@ -159,7 +146,7 @@ export default class VictoryTooltip extends React.Component { getPolarOrientation(props, datum) { const degrees = LabelHelpers.getDegrees(props, datum); const placement = props.labelPlacement || "vertical"; - if (placement === " vertical") { + if (placement === "vertical") { return this.getVerticalOrientations(degrees); } else if (placement === "parallel") { return degrees < 90 || degrees > 270 ? "right" : "left"; @@ -305,6 +292,7 @@ export default class VictoryTooltip extends React.Component { getTransform(props) { const { x, y, style } = props; const labelStyle = style || {}; + const angle = labelStyle.angle || props.angle || this.getDefaultAngle(props); return angle ? `rotate(${angle} ${x} ${y})` : undefined; @@ -447,10 +435,14 @@ export default class VictoryTooltip extends React.Component { return { flyoutHeight: flyoutHeight ? Helpers.evaluateProp(flyoutHeight, props) - : getHeight(props, labelSize, orientation), + : // TODO: Any reason for this? Are we replacing this function or something? + // Maybe we're just keeping the reference alive? + // : getHeight(props, labelSize, orientation), + getHeight(), flyoutWidth: flyoutWidth ? Helpers.evaluateProp(flyoutWidth, props) - : getWidth(props, labelSize, orientation), + : // : getWidth(props, labelSize, orientation), + getWidth(), }; } @@ -557,7 +549,7 @@ export default class VictoryTooltip extends React.Component { const active = Helpers.evaluateProp(props.active, props); const { renderInPortal } = props; if (!active) { - return renderInPortal ? {null} : null; + return renderInPortal ? : null; } const evaluatedProps = this.getEvaluatedProps(props); const { flyoutComponent, labelComponent, groupComponent } = evaluatedProps; @@ -585,3 +577,41 @@ export default class VictoryTooltip extends React.Component { return this.renderTooltip(props); } } + +export interface VictoryTooltipProps + extends VictoryLabelableProps, + VictoryLabelProps { + activateData?: boolean; + active?: boolean; + activePoints?: any[]; + angle: VictoryLabelStyleObject["angle"]; + center?: { x?: number; y?: number }; + centerOffset?: { + x?: NumberOrCallback; + y?: NumberOrCallback; + }; + constrainToVisibleArea?: boolean; + cornerRadius?: NumberOrCallback; + height?: number; + horizontal?: boolean; + flyoutComponent?: React.ReactElement; + flyoutHeight?: NumberOrCallback; + flyoutPadding?: PaddingOrCallback; + flyoutStyle?: VictoryStyleObject; + flyoutWidth?: NumberOrCallback; + id?: number | string; + index?: number | string; + orientation?: OrientationTypes | ((...args: any[]) => OrientationTypes); + pointerLength?: NumberOrCallback; + pointerOrientation?: + | OrientationTypes + | ((...args: any[]) => OrientationTypes); + pointerWidth?: NumberOrCallback; + style?: + | (VictoryLabelStyleObject & { + angle?: number; + }) + | VictoryLabelStyleObject[]; + theme?: VictoryThemeDefinition; + width?: number; +}