Skip to content

Commit

Permalink
Merge branch 'main' into ts-migrate/victory-native
Browse files Browse the repository at this point in the history
  • Loading branch information
KenanYusuf committed Jan 25, 2024
2 parents 7769579 + 492675f commit db9f876
Show file tree
Hide file tree
Showing 14 changed files with 552 additions and 389 deletions.
5 changes: 5 additions & 0 deletions .changeset/kind-rivers-kick.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"victory-pie": patch
---

Migrate victory-pie to TypeScript
18 changes: 16 additions & 2 deletions demo/js/components/victory-pie-demo.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { random, range } from "lodash";
import React from "react";
import { VictoryPie } from "victory-pie";
import { VictoryTooltip } from "victory-tooltip";
import { VictoryTheme } from "victory-core";
import { VictoryTheme, LineSegment } from "victory-core";

export default class App extends React.Component {
constructor(props) {
Expand Down Expand Up @@ -228,7 +228,7 @@ export default class App extends React.Component {
<VictoryPie
style={{ ...this.state.style, labels: { fontSize: 0 } }}
data={this.state.data}
innerRadius={100}
innerRadius={90}
animate={{ duration: 2000 }}
colorScale={this.state.colorScale}
/>
Expand Down Expand Up @@ -317,6 +317,20 @@ export default class App extends React.Component {
{ x: 8, y: 1, l: 315 },
]}
/>
<VictoryPie
style={{ parent: parentStyle }}
labelIndicator
/>
<VictoryPie
style={{ parent: parentStyle }}
labelIndicator={<LineSegment style={{opacity:"1",strokeWidth:"1px",stroke: "red"}}/>}
/>
<VictoryPie
style={{ parent: parentStyle }}
labelIndicator={<LineSegment style={{opacity:"1",strokeWidth:"1px",strokeDasharray: "1",stroke: "red"}}/>}
labelIndicatorInnerOffset={35}
labelIndicatorOuterOffset={4}
/>
</div>
</div>
);
Expand Down
16 changes: 15 additions & 1 deletion demo/ts/components/victory-pie-demo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React from "react";
import { random, range } from "lodash";
import { VictoryPie } from "victory-pie";
import { VictoryTooltip } from "victory-tooltip";
import { VictoryTheme } from "victory-core";
import { VictoryTheme, LineSegment } from "victory-core";

interface VictoryPieDemoState {
data: {
Expand Down Expand Up @@ -306,6 +306,20 @@ export default class VictoryPieDemo extends React.Component<
animate={{ duration: 2000 }}
innerRadius={140}
/>
<VictoryPie
style={{ parent: parentStyle }}
labelIndicator
/>
<VictoryPie
style={{ parent: parentStyle }}
labelIndicator={<LineSegment style={{opacity:"1",strokeWidth:"1px",stroke: "red"}}/>}
/>
<VictoryPie
style={{ parent: parentStyle }}
labelIndicator={<LineSegment style={{opacity:"1",strokeWidth:"1px",strokeDasharray: "1",stroke: "red"}}/>}
labelIndicatorInnerOffset={45}
labelIndicatorOuterOffset={15}
/>
</div>
</div>
);
Expand Down
54 changes: 53 additions & 1 deletion docs/src/content/docs/victory-pie.md
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,7 @@ The `labelPosition` prop specifies the position of each label relative to its co

`type: number || function`

The `labelRadius` prop defines the radius of the arc that will be used for positioning each slice label. If this prop is not set, the label radius will default to the radius of the pie + label padding. If this prop is given as a function, it will be evaluated for each label `VictoryPie` renders, and will be evaluated with the props that correspond to that label, as well as the radius and innerRadius of the corresponding slice.
The `labelRadius` prop defines the radius of the arc that will be used for positioning each slice label. If this prop is not set, the label radius will default to the radius of the pie + label padding. If this prop is given as a function, it will be evaluated for each label `VictoryPie` renders, and will be evaluated with the props that correspond to that label, as well as the radius and innerRadius of the corresponding slice. If `labelIndicator` prop is being used, passed `labelRadius`(> radius) is used to calculate the co-ordinates of the outer indicator line. If no specific value for labelRadius is passed , default values will be considered. The outer indicator line length is the difference between `labelRadius` and `labelIndicatorOuterOffset`.

```playground
<VictoryPie
Expand Down Expand Up @@ -519,6 +519,58 @@ See the [Data Accessors Guide][] for more detail on formatting and processing da
y={(d) => d.value + d.error}
```

## labelIndicator

`type: boolean || element`

The `labelIndicator` prop defines the label indicator line between labels and the pie chart. If this prop is used as a boolean,then the default indicator will be displayed. To customize or pass your own styling `<LineSegment/>` can be passed to labelIndicator. LabelIndicator is functional only when labelPosition = "centroid". To adjust the labelIndicator length, `labelIndicatorInnerOffset` and `labelIndicatorOuterOffset` props can be used alongside labelIndicator.

```playground
<div>
<VictoryPie
data={sampleData}
labelIndicator
/>
<VictoryPie
data={sampleData}
labelIndicator={<LineSegment style = {{stroke:"red", strokeDasharray:1,fill: "none",}}/>}
/>
<VictoryPie
data={sampleData}
labelIndicator={<LineSegment style = {{stroke:"red", strokeDasharray:1,fill: "none",}}/>}
labelIndicatorInnerOffset={10}
labelIndicatorOuterOffset={5}
/>
</div>
```
## labelIndicatorInnerOffset

`type: number`

The `labelIndicatorInnerOffset` prop defines the offset by which the indicator length inside pie chart is being drawn. Higher the number shorter the length.

```playground
<VictoryPie
data={sampleData}
labelIndicator
labelIndicatorInnerOffset={10}
/>
```

## labelIndicatorOuterOffset

`type: number`

The `labelIndicatorOuterOffset` prop defines the offset by which the indicator length outside the pie chart is being drawn. Higher the number shorter the length.

```playground
<VictoryPie
data={sampleData}
labelIndicator
labelIndicatorOuterOffset={5}
/>
```

[animations guide]: /guides/animations
[data accessors guide]: /guides/data-accessors
[custom components guide]: /guides/custom-components
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,15 +36,15 @@ describe("components/victory-errorbar", () => {
it("renders an svg with the correct width and height", () => {
const { container } = render(<VictoryErrorBar />);
const svg = container.querySelector("svg");
expect(svg.style.width).toEqual("100%");
expect(svg.style.height).toEqual("100%");
expect(svg!.style.width).toEqual("100%");
expect(svg!.style.height).toEqual("100%");
});

it("renders an svg with the correct viewBox", () => {
const { container } = render(<VictoryErrorBar />);
const svg = container.querySelector("svg");
const viewBoxValue = `0 0 ${450} ${300}`;
expect(svg.getAttribute("viewBox")).toEqual(viewBoxValue);
expect(svg!.getAttribute("viewBox")).toEqual(viewBoxValue);
});

it("renders 4 errors", () => {
Expand Down Expand Up @@ -104,7 +104,7 @@ describe("components/victory-errorbar", () => {
render(<VictoryErrorBar data={data} sortKey="x" {...defaultProps} />);
const xValues = screen
.getAllByTestId("error-bar")
.map((node) => parseInt(node.getAttribute("data-x")));
.map((node) => parseInt(node.getAttribute("data-x")!));
expect(xValues).toEqual([0, 1, 2, 3, 4]);
});

Expand All @@ -124,7 +124,7 @@ describe("components/victory-errorbar", () => {
);
const yValues = screen
.getAllByTestId("error-bar")
.map((node) => parseInt(node.getAttribute("data-y")));
.map((node) => parseInt(node.getAttribute("data-y")!));
expect(yValues).toEqual([4, 3, 2, 1, 0]);
});

Expand Down Expand Up @@ -1017,7 +1017,7 @@ describe("components/victory-errorbar", () => {
/>,
);
const svg = container.querySelector("svg");
fireEvent.click(svg);
fireEvent.click(svg!);
expect(clickHandler).toBeCalled();
});

Expand Down Expand Up @@ -1091,7 +1091,7 @@ describe("components/victory-errorbar", () => {
expect(g.getAttribute("aria-label")).toEqual(
`error bar chart, x ${data[i].x}`,
);
expect(parseInt(g.getAttribute("tabindex"), 10)).toEqual(i + 2);
expect(parseInt(g.getAttribute("tabindex")!, 10)).toEqual(i + 2);
});
});
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ const getSlices = (props, data) => {
.startAngle(Helpers.degreesToRadians(props.startAngle))
.endAngle(Helpers.degreesToRadians(props.endAngle))
.padAngle(Helpers.degreesToRadians(padAngle))
.value((datum) => {
.value((datum: any) => {
return datum._y;
});
return layoutFunction(data);
Expand All @@ -62,7 +62,7 @@ const getSlices = (props, data) => {
const getCalculatedValues = (props) => {
const { colorScale } = props;
const styleObject = Helpers.getDefaultStyles(props, "pie");
const style = Helpers.getStyles(props.style, styleObject, "auto", "100%");
const style = Helpers.getStyles(props.style, styleObject);
const colors = Array.isArray(colorScale)
? colorScale
: Style.getColorScale(colorScale);
Expand Down Expand Up @@ -100,10 +100,13 @@ const getLabelText = (props, datum, index) => {
return checkForValidText(text);
};

const getLabelArc = (radius, labelRadius, style) => {
const getLabelArc = (labelRadius) => {
return d3Shape.arc().outerRadius(labelRadius).innerRadius(labelRadius);
};

const getCalculatedLabelRadius = (radius, labelRadius, style) => {
const padding = (style && style.padding) || 0;
const arcRadius = labelRadius || radius + padding;
return d3Shape.arc().outerRadius(arcRadius).innerRadius(arcRadius);
return labelRadius || radius + padding;
};

const getLabelPosition = (arc, slice, position) => {
Expand Down Expand Up @@ -195,7 +198,12 @@ const getLabelProps = (text, dataProps, calculatedValues) => {
labelStyle,
assign({ labelRadius, text }, dataProps),
);
const labelArc = getLabelArc(defaultRadius, labelRadius, evaluatedStyle);
const calculatedLabelRadius = getCalculatedLabelRadius(
defaultRadius,
labelRadius,
evaluatedStyle,
);
const labelArc = getLabelArc(calculatedLabelRadius);
const position = getLabelPosition(labelArc, slice, labelPosition);
const baseAngle = getBaseLabelAngle(slice, labelPosition, labelStyle);
const labelAngle = getLabelAngle(baseAngle, labelPlacement);
Expand All @@ -219,6 +227,7 @@ const getLabelProps = (text, dataProps, calculatedValues) => {
textAnchor,
verticalAnchor,
angle: labelAngle,
calculatedLabelRadius,
};

if (!Helpers.isTooltip(labelComponent)) {
Expand All @@ -228,6 +237,57 @@ const getLabelProps = (text, dataProps, calculatedValues) => {
return defaults({}, labelProps, Helpers.omit(tooltipTheme, ["style"]));
};

export const getXOffsetMultiplayerByAngle = (angle) =>
Math.cos(angle - Helpers.degreesToRadians(90));
export const getYOffsetMultiplayerByAngle = (angle) =>
Math.sin(angle - Helpers.degreesToRadians(90));
export const getXOffset = (offset, angle) =>
offset * getXOffsetMultiplayerByAngle(angle);
export const getYOffset = (offset, angle) =>
offset * getYOffsetMultiplayerByAngle(angle);
export const getAverage = (array) =>
array.reduce((acc, cur) => acc + cur, 0) / array.length;

export const getLabelIndicatorPropsForLineSegment = (
props,
calculatedValues,
labelProps,
) => {
const {
innerRadius,
radius,
slice: { startAngle, endAngle },
labelIndicatorInnerOffset,
labelIndicatorOuterOffset,
index,
} = props;

const { height, width } = calculatedValues;
const { calculatedLabelRadius } = labelProps;
// calculation
const middleRadius = getAverage([innerRadius, radius]);
const midAngle = getAverage([endAngle, startAngle]);
const centerX = width / 2;
const centerY = height / 2;
const innerOffset = middleRadius + labelIndicatorInnerOffset;
const outerOffset = calculatedLabelRadius - labelIndicatorOuterOffset;

const x1 = centerX + getXOffset(innerOffset, midAngle);
const y1 = centerY + getYOffset(innerOffset, midAngle);

const x2 = centerX + getXOffset(outerOffset, midAngle);
const y2 = centerY + getYOffset(outerOffset, midAngle);

const labelIndicatorProps = {
x1,
y1,
x2,
y2,
index,
};
return defaults({}, labelIndicatorProps);
};

export const getBaseProps = (initialProps, fallbackProps) => {
const props = Helpers.modifyProps(initialProps, fallbackProps, "pie");
const calculatedValues = getCalculatedValues(props);
Expand All @@ -248,6 +308,7 @@ export const getBaseProps = (initialProps, fallbackProps) => {
cornerRadius,
padAngle,
disableInlineStyles,
labelIndicator,
} = calculatedValues;
const radius = props.radius || defaultRadius;
const initialChildProps = {
Expand Down Expand Up @@ -288,6 +349,17 @@ export const getBaseProps = (initialProps, fallbackProps) => {
assign({}, props, dataProps),
calculatedValues,
);
if (labelIndicator) {
const labelProps = childProps[eventKey].labels;
if (labelProps.calculatedLabelRadius > radius) {
childProps[eventKey].labelIndicators =
getLabelIndicatorPropsForLineSegment(
assign({}, props, dataProps),
calculatedValues,
labelProps,
);
}
}
}
return childProps;
}, initialChildProps);
Expand Down
Loading

0 comments on commit db9f876

Please sign in to comment.