Skip to content

Commit

Permalink
Improve types in victory-core helpers (#2999)
Browse files Browse the repository at this point in the history
  • Loading branch information
carbonrobot authored Dec 6, 2024
1 parent efc701b commit 618bd6d
Show file tree
Hide file tree
Showing 18 changed files with 191 additions and 61 deletions.
16 changes: 16 additions & 0 deletions .changeset/poor-crabs-hear.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
---
"victory-axis": patch
"victory-chart": patch
"victory-core": patch
"victory-cursor-container": patch
"victory-group": patch
"victory-legend": patch
"victory-pie": patch
"victory-polar-axis": patch
"victory-scatter": patch
"victory-stack": patch
"victory-tooltip": patch
"victory-voronoi-container": patch
---

Improve types in victory-core helpers
2 changes: 1 addition & 1 deletion packages/victory-axis/src/helper-methods.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -467,7 +467,7 @@ const getOrientation = (props) => {
const getCalculatedValues = (props) => {
const defaultStyles = getStyleObject(props);
const style = getStyles(props, defaultStyles);
const padding = Helpers.getPadding(props);
const padding = Helpers.getPadding(props.padding);
const labelPadding = getLabelPadding(props, style);
const stringTicks = Axis.stringTicks(props) ? props.tickValues : undefined;
const axis = Axis.getAxis(props);
Expand Down
2 changes: 1 addition & 1 deletion packages/victory-chart/src/helper-methods.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ export function getCalculatedProps(initialProps, childComponents) {

const origin = polar ? Helpers.getPolarOrigin(props) : Axis.getOrigin(domain);

const padding = Helpers.getPadding(props);
const padding = Helpers.getPadding(props.padding);

return {
categories,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ export class VictoryClipContainer extends React.Component<
translateX = 0,
translateY = 0,
} = props;
const clipPadding = Helpers.getPadding({ padding: props.clipPadding });
const clipPadding = Helpers.getPadding(props.clipPadding);
const radius = props.radius || Helpers.getRadius(props);
return {
x: (polar ? origin.x : translateX) - clipPadding.left,
Expand Down Expand Up @@ -158,9 +158,7 @@ export class VictoryClipContainer extends React.Component<
rectComponent,
clipPathComponent,
} = props;
const { top, bottom, left, right } = Helpers.getPadding({
padding: props.clipPadding,
});
const { top, bottom, left, right } = Helpers.getPadding(props.clipPadding);
let child;
if (polar) {
const radius = props.radius || Helpers.getRadius(props);
Expand Down
4 changes: 2 additions & 2 deletions packages/victory-core/src/victory-label/victory-label.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -146,11 +146,11 @@ const getBackgroundPadding = (props) => {
if (props.backgroundPadding && Array.isArray(props.backgroundPadding)) {
return props.backgroundPadding.map((backgroundPadding) => {
const padding = Helpers.evaluateProp(backgroundPadding, props);
return Helpers.getPadding({ padding });
return Helpers.getPadding(padding);
});
}
const padding = Helpers.evaluateProp(props.backgroundPadding, props);
return Helpers.getPadding({ padding });
return Helpers.getPadding(padding);
};

const getLineHeight = (props) => {
Expand Down
6 changes: 3 additions & 3 deletions packages/victory-core/src/victory-util/helpers.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ describe("victory-util/helpers", () => {
describe("getPadding", () => {
it("sets padding from a single number", () => {
const props = { padding: 40 };
expect(Helpers.getPadding(props)).toEqual({
expect(Helpers.getPadding(props.padding)).toEqual({
top: 40,
bottom: 40,
left: 40,
Expand All @@ -177,14 +177,14 @@ describe("victory-util/helpers", () => {
const props = {
padding: { top: 20, bottom: 40, left: 60, right: 80 },
};
expect(Helpers.getPadding(props)).toEqual(props.padding);
expect(Helpers.getPadding(props.padding)).toEqual(props.padding);
});

it("fills missing values with 0", () => {
const props = {
padding: { top: 40, bottom: 40 },
};
expect(Helpers.getPadding(props)).toEqual({
expect(Helpers.getPadding(props.padding)).toEqual({
top: 40,
bottom: 40,
left: 0,
Expand Down
184 changes: 149 additions & 35 deletions packages/victory-core/src/victory-util/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,29 +5,73 @@ import pick from "lodash/pick";

import { ValueOrAccessor } from "../types/prop-types";

// Private Functions
export type ElementPadding = {
top: number;
bottom: number;
left: number;
right: number;
};

export type MaybePointData = {
x?: number;
x0?: number;
x1?: number;
y?: number;
y0?: number;
y1?: number;
_x?: number;
_x0?: number;
_x1?: number;
_y?: number;
_y0?: number;
_y1?: number;
_voronoiX?: number;
_voronoiY?: number;
};

function getCartesianRange(props, axis) {
// determine how to lay the axis and what direction positive and negative are
const vertical = axis !== "x";
const padding = getPadding(props);
/**
* Determine the range of a cartesian axis
*/
function getCartesianRange(options: {
axis: "x" | "y";
height: number;
width: number;
padding: ElementPadding;
}): [number, number] {
const vertical = options.axis !== "x";
if (vertical) {
return [props.height - padding.bottom, padding.top];
return [options.height - options.padding.bottom, options.padding.top];
}
return [padding.left, props.width - padding.right];
return [options.padding.left, options.width - options.padding.right];
}

function getPolarRange(props, axis) {
if (axis === "x") {
const startAngle = degreesToRadians(props.startAngle || 0);
const endAngle = degreesToRadians(props.endAngle || 360);
/**
* Determine the range of a polar axis in radians
*/
function getPolarRange(options: {
axis: "x" | "y";
innerRadius?: number;
startAngle?: number;
endAngle?: number;
padding: ElementPadding;
height: number;
width: number;
}): [number, number] {
if (options.axis === "x") {
const startAngle = degreesToRadians(options.startAngle || 0);
const endAngle = degreesToRadians(options.endAngle || 360);
return [startAngle, endAngle];
}
return [props.innerRadius || 0, getRadius(props)];
return [
options.innerRadius || 0,
getRadius({
height: options.height,
width: options.width,
padding: options.padding,
}),
];
}

// Exported Functions

/**
* Creates an object composed of the inverted keys and values of object.
* If object contains duplicate values, subsequent values overwrite property assignments of previous values.
Expand Down Expand Up @@ -65,21 +109,36 @@ export function omit<T, Keys extends keyof T>(
return newObject;
}

export function getPoint(datum) {
const exists = (val) => val !== undefined;
/**
* Coalesce the x and y values from a data point
*/
export function getPoint(datum: MaybePointData): MaybePointData {
const { _x, _x1, _x0, _voronoiX, _y, _y1, _y0, _voronoiY } = datum;
const defaultX = exists(_x1) ? _x1 : _x;
const defaultY = exists(_y1) ? _y1 : _y;
const defaultX = _x1 ?? _x;
const defaultY = _y1 ?? _y;

const point = {
x: exists(_voronoiX) ? _voronoiX : defaultX,
x0: exists(_x0) ? _x0 : _x,
y: exists(_voronoiY) ? _voronoiY : defaultY,
y0: exists(_y0) ? _y0 : _y,
x: _voronoiX ?? defaultX,
x0: _x0 ?? _x,
y: _voronoiY ?? defaultY,
y0: _y0 ?? _y,
};

return defaults({}, point, datum);
}

export function scalePoint(props, datum) {
/**
* Scale a point based on the origin, direction, and given scale function
*/
export function scalePoint(
props: {
scale: { x: (x?: number) => number; y: (y?: number) => number };
polar?: boolean;
horizontal?: boolean;
origin?: { x: number; y: number };
},
datum: MaybePointData,
) {
const { scale, polar, horizontal } = props;
const d = getPoint(datum);
const origin = props.origin || { x: 0, y: 0 };
Expand All @@ -95,8 +154,12 @@ export function scalePoint(props, datum) {
};
}

export function getPadding(props, name = "padding") {
const padding = props[name];
/**
* Returns a padding value from a number or partial padding values
*/
export function getPadding(
padding?: number | Partial<ElementPadding>,
): ElementPadding {
const paddingVal = typeof padding === "number" ? padding : 0;
const paddingObj = typeof padding === "object" ? padding : {};
return {
Expand All @@ -107,7 +170,10 @@ export function getPadding(props, name = "padding") {
};
}

export function isTooltip(component) {
/**
* Returns true if the component is defined as a tooltip
*/
export function isTooltip(component?: { type?: { role?: string } }) {
const labelRole = component && component.type && component.type.role;
return labelRole === "tooltip";
}
Expand Down Expand Up @@ -140,6 +206,9 @@ export function getStyles(style, defaultStyles) {
};
}

/**
* Returns the value of a prop or accessor function with the given props
*/
export function evaluateProp<TValue>(
prop: ValueOrAccessor<TValue, Record<string, any>>,
props: Record<string, any>,
Expand Down Expand Up @@ -168,15 +237,29 @@ export function radiansToDegrees(radians) {
return typeof radians === "number" ? radians / (Math.PI / 180) : radians;
}

export function getRadius(props) {
const { left, right, top, bottom } = getPadding(props);
const { width, height } = props;
/**
* Get the maximum radius that will fit in the container
*/
export function getRadius(options: {
height: number;
width: number;
padding: ElementPadding;
}) {
const { width, height, padding } = options;
const { left, right, top, bottom } = padding;
return Math.min(width - left - right, height - top - bottom) / 2;
}

export function getPolarOrigin(props) {
/**
* Returns the origin for a polar chart within the padded area
*/
export function getPolarOrigin(props: {
height: number;
width: number;
padding: ElementPadding;
}): { x: number; y: number } {
const { width, height } = props;
const { top, bottom, left, right } = getPadding(props);
const { top, bottom, left, right } = getPadding(props.padding);
const radius = Math.min(width - left - right, height - top - bottom) / 2;
const offsetWidth = width / 2 + left - right;
const offsetHeight = height / 2 + top - bottom;
Expand All @@ -186,15 +269,43 @@ export function getPolarOrigin(props) {
};
}

export function getRange(props, axis) {
/**
* Determine the range of an axis based on the given props
*/
export function getRange(
props: {
range?: [number, number];
polar?: boolean;
innerRadius?: number;
startAngle?: number;
endAngle?: number;
height: number;
width: number;
padding: number | Partial<ElementPadding>;
},
axis: "x" | "y",
) {
if (props.range && props.range[axis]) {
return props.range[axis];
} else if (props.range && Array.isArray(props.range)) {
return props.range;
}
return props.polar
? getPolarRange(props, axis)
: getCartesianRange(props, axis);
? getPolarRange({
axis,
innerRadius: props.innerRadius,
startAngle: props.startAngle,
endAngle: props.endAngle,
height: props.height,
width: props.width,
padding: getPadding(props.padding),
})
: getCartesianRange({
axis,
height: props.height,
width: props.width,
padding: getPadding(props.padding),
});
}

/**
Expand Down Expand Up @@ -392,7 +503,10 @@ export function reduceChildren<
* @returns {Boolean} returns true if the props object contains `horizontal: true` of if any
* children or nested children are horizontal
*/
export function isHorizontal(props) {
export function isHorizontal(props: {
horizontal?: boolean;
children?: React.ReactNode;
}) {
if (props.horizontal !== undefined || !props.children) {
return props.horizontal;
}
Expand Down
5 changes: 0 additions & 5 deletions packages/victory-core/src/victory-util/type-helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,6 @@ export function getValueForAxis<T = unknown>(
return value;
}

// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
export function isFunction<T = Function>(func?: unknown): func is T {
return typeof func === "function";
}

export function isDate(value: unknown): value is Date {
return value instanceof Date;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ export const useVictoryCursorContainer = (
: props.children;
return Helpers.getPadding(child?.props);
}
return Helpers.getPadding(props);
return Helpers.getPadding(props.padding);
};

const getCursorElements = () => {
Expand Down
2 changes: 1 addition & 1 deletion packages/victory-group/src/helper-methods.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ export function getCalculatedProps(initialProps, childComponents) {
};

const origin = polar ? props.origin : Helpers.getPolarOrigin(props);
const padding = Helpers.getPadding(props);
const padding = Helpers.getPadding(props.padding);
return {
datasets,
categories,
Expand Down
2 changes: 1 addition & 1 deletion packages/victory-legend/src/helper-methods.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ const getCalculatedValues = (props) => {
const style = getStyles(props, defaultStyles);
const colorScale = getColorScale(props);
const isHorizontal = orientation === "horizontal";
const borderPadding = Helpers.getPadding({ padding: props.borderPadding });
const borderPadding = Helpers.getPadding(props.borderPadding);
return Object.assign({}, props, {
style,
isHorizontal,
Expand Down
Loading

0 comments on commit 618bd6d

Please sign in to comment.