Skip to content

Commit a53059f

Browse files
authored
Replace instances of lodash.range with native code (#2760)
1 parent c8c2eb2 commit a53059f

File tree

18 files changed

+190
-67
lines changed

18 files changed

+190
-67
lines changed

.changeset/shiny-cows-bathe.md

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
---
2+
"victory-area": patch
3+
"victory-bar": patch
4+
"victory-candlestick": patch
5+
"victory-core": patch
6+
"victory-errorbar": patch
7+
"victory-histogram": patch
8+
"victory-line": patch
9+
"victory-pie": patch
10+
"victory-scatter": patch
11+
"victory-voronoi": patch
12+
---
13+
14+
Replace instances of lodash.range with equivalent native code

packages/victory-area/src/victory-area.test.tsx

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import { fireEvent, render, screen } from "@testing-library/react";
2-
import { range } from "lodash";
32
import React from "react";
43
import { Area, VictoryArea, VictoryAreaProps } from "victory-area";
54
import { VictoryChart } from "victory-chart";
5+
import { Helpers } from "victory-core";
66
import { curveCatmullRom } from "victory-vendor/d3-shape";
77
import { calculateD3Path } from "../../../test/helpers/svg";
88

@@ -115,7 +115,7 @@ describe("components/victory-area", () => {
115115
scale: "linear",
116116
interpolation: "linear",
117117
sortKey: "x",
118-
data: range(5)
118+
data: Helpers.range(5)
119119
// eslint-disable-next-line max-nested-callbacks
120120
.map((i) => ({ x: i, y: i, y0: 0 }))
121121
.reverse(),
@@ -145,7 +145,7 @@ describe("components/victory-area", () => {
145145
interpolation: "linear",
146146
sortKey: "x",
147147
sortOrder: "descending",
148-
data: range(5)
148+
data: Helpers.range(5)
149149
.map((i) => ({ x: i, y: i, y0: 0 }))
150150
.reverse(),
151151
};

packages/victory-bar/src/victory-bar.test.tsx

+12-9
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
import * as React from "react";
22
import { render, fireEvent, screen } from "@testing-library/react";
3-
import { range } from "lodash";
43
import { VictoryChart } from "victory-chart";
54
import { Bar, VictoryBar } from "victory-bar";
5+
import { Helpers } from "victory-core";
6+
67
import { isBar, getBarHeight } from "../../../test/helpers";
78

89
describe("components/victory-bar", () => {
@@ -70,14 +71,14 @@ describe("components/victory-bar", () => {
7071

7172
describe("rendering data", () => {
7273
it("renders bars for {x, y} shaped data (default)", () => {
73-
const data = range(10).map((i) => ({ x: i, y: i }));
74+
const data = Helpers.range(10).map((i) => ({ x: i, y: i }));
7475
const { container } = render(<VictoryBar data={data} />);
7576
const bars = container.querySelectorAll("path");
7677
expect(bars.length).toEqual(10);
7778
});
7879

7980
it("renders ordered bars when sortKey is passed", () => {
80-
const data = range(5)
81+
const data = Helpers.range(5)
8182
.map((i) => ({ x: i, y: i }))
8283
.reverse();
8384
const { container } = render(<VictoryBar data={data} sortKey="x" />);
@@ -94,7 +95,7 @@ describe("components/victory-bar", () => {
9495
});
9596

9697
it("renders reverse ordered bars when sortOrder is descending", () => {
97-
const data = range(5)
98+
const data = Helpers.range(5)
9899
.map((i) => ({ x: i, y: i }))
99100
.reverse();
100101
const { container } = render(
@@ -112,14 +113,16 @@ describe("components/victory-bar", () => {
112113
});
113114

114115
it("renders bars for array-shaped data", () => {
115-
const data = range(20).map((i) => [i, i]);
116+
const data = Helpers.range(20).map((i) => [i, i]);
116117
const { container } = render(<VictoryBar data={data} x={0} y={1} />);
117118
const bars = container.querySelectorAll("path");
118119
expect(bars).toHaveLength(20);
119120
});
120121

121122
it("renders bars for deeply-nested data", () => {
122-
const data = range(8).map((i) => ({ a: { b: [{ x: i, y: i }] } }));
123+
const data = Helpers.range(8).map((i) => ({
124+
a: { b: [{ x: i, y: i }] },
125+
}));
123126
const { container } = render(
124127
<VictoryBar data={data} x="a.b[0].x" y="a.b[0].y" />,
125128
);
@@ -128,7 +131,7 @@ describe("components/victory-bar", () => {
128131
});
129132

130133
it("renders bars values with null accessor", () => {
131-
const data = range(8);
134+
const data = Helpers.range(8);
132135
const { container } = render(
133136
// @ts-expect-error "'null' is not assignable to 'x'"
134137
<VictoryBar data={data} x={null} y={null} />,
@@ -249,14 +252,14 @@ describe("components/victory-bar", () => {
249252

250253
describe("accessibility", () => {
251254
it("adds an aria role to each bar in the series", () => {
252-
const data = range(10).map((y, x) => ({ x, y }));
255+
const data = Helpers.range(10).map((y, x) => ({ x, y }));
253256
render(<VictoryBar data={data} />);
254257
const presentationElements = screen.getAllByRole("presentation");
255258
expect(presentationElements).toHaveLength(11); // bars plus container
256259
});
257260

258261
it("applies aria-label and tabIndex to the Bar primitive", () => {
259-
const data = range(5, 11).map((y, x) => ({ y, x }));
262+
const data = Helpers.range(5, 11).map((y, x) => ({ y, x }));
260263
const { container } = render(
261264
<VictoryBar
262265
data={data}

packages/victory-candlestick/src/helper-methods.test.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
import { range } from "lodash";
21
import { fromJS } from "immutable";
32
import { getData, getDomain } from "victory-candlestick/lib/helper-methods";
3+
import { Helpers } from "victory-core";
44

55
const immutableGetDataTest = {
66
createData: (x) => fromJS(x),
@@ -16,7 +16,7 @@ const getDataTest = {
1616
describe("getData", () => {
1717
it("sorts data by sortKey", () => {
1818
const data = createData(
19-
range(5)
19+
Helpers.range(5)
2020
.map((i) => ({ x: i, open: i, close: i, high: i, low: i }))
2121
.reverse(),
2222
);

packages/victory-candlestick/src/victory-candlestick.test.tsx

+8-8
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import { fireEvent, render, screen } from "@testing-library/react";
2-
import { range } from "lodash";
32
import React from "react";
43
import { Candle, VictoryCandlestick } from "victory-candlestick";
54
import { VictoryChart } from "victory-chart";
5+
import { Helpers } from "victory-core";
66

77
const MyCandle = () => <div data-testid="my-candle" />;
88

@@ -66,7 +66,7 @@ describe("components/victory-candlestick", () => {
6666

6767
describe("rendering data", () => {
6868
it("renders injected points for {x, y} shaped data (default)", () => {
69-
const data = range(5).map((i) => ({
69+
const data = Helpers.range(5).map((i) => ({
7070
x: i,
7171
open: i,
7272
close: i,
@@ -80,7 +80,7 @@ describe("components/victory-candlestick", () => {
8080
});
8181

8282
it("renders points for {x, y} shaped data (default)", () => {
83-
const data = range(5).map((i) => ({
83+
const data = Helpers.range(5).map((i) => ({
8484
x: i,
8585
open: i,
8686
close: i,
@@ -93,7 +93,7 @@ describe("components/victory-candlestick", () => {
9393
});
9494

9595
it("renders ordered bars when sortKey is passed", () => {
96-
const data = range(5)
96+
const data = Helpers.range(5)
9797
.map((i) => ({ x: i, open: i, close: i, high: i, low: i }))
9898
.reverse();
9999
const { container } = render(
@@ -108,7 +108,7 @@ describe("components/victory-candlestick", () => {
108108
});
109109

110110
it("renders reverse ordered bars when sortOrder is descending", () => {
111-
const data = range(5)
111+
const data = Helpers.range(5)
112112
.map((i) => ({ x: i, open: i, close: i, high: i, low: i }))
113113
.reverse();
114114
const { container } = render(
@@ -123,7 +123,7 @@ describe("components/victory-candlestick", () => {
123123
});
124124

125125
it("renders points for array-shaped data", () => {
126-
const data = range(10).map((i) => [i, i, i, i, i]);
126+
const data = Helpers.range(10).map((i) => [i, i, i, i, i]);
127127
const { container } = render(
128128
<VictoryCandlestick
129129
data={data}
@@ -139,7 +139,7 @@ describe("components/victory-candlestick", () => {
139139
});
140140

141141
it("renders points for deeply-nested data", () => {
142-
const data = range(20).map((i) => ({
142+
const data = Helpers.range(20).map((i) => ({
143143
a: { b: [{ x: i, open: i, close: i, high: i, low: i }] },
144144
}));
145145
const { container } = render(
@@ -157,7 +157,7 @@ describe("components/victory-candlestick", () => {
157157
});
158158

159159
it("renders data values with null accessor", () => {
160-
const data = range(10);
160+
const data = Helpers.range(10);
161161
const { container } = render(
162162
// @ts-expect-error "'null' is not assignable to 'x'"
163163
<VictoryCandlestick

packages/victory-core/src/exports.test.ts

+1
Original file line numberDiff line numberDiff line change
@@ -319,6 +319,7 @@ describe("victory-core", () => {
319319
"modifyProps": [Function],
320320
"omit": [Function],
321321
"radiansToDegrees": [Function],
322+
"range": [Function],
322323
"reduceChildren": [Function],
323324
"scalePoint": [Function],
324325
},

packages/victory-core/src/victory-util/axis.tsx

+1-2
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import {
66
isObject,
77
invert,
88
uniq,
9-
range,
109
orderBy,
1110
values,
1211
includes,
@@ -207,7 +206,7 @@ function getTickArray(props) {
207206
if (tickValues && Collection.containsStrings(tickValues)) {
208207
ticks = stringMap
209208
? tickValues.map((tick) => stringMap[tick])
210-
: range(1, tickValues.length + 1);
209+
: Helpers.range(1, tickValues.length + 1);
211210
}
212211
const tickArray = ticks ? uniq(ticks) : getTicksFromFormat();
213212
const buildTickArray = (arr: number[]) => {

packages/victory-core/src/victory-util/data.test.tsx

+10
Original file line numberDiff line numberDiff line change
@@ -336,6 +336,16 @@ describe("victory-util/data", () => {
336336
expect(returnData).toEqual(generatedReturn);
337337
});
338338

339+
it("generates a dataset from negative domain", () => {
340+
const generatedReturn = [
341+
{ x: -10, y: 0 },
342+
{ x: 10, y: 10 },
343+
];
344+
const props = { x: "x", y: "y", domain: { x: [-10, 10], y: [0, 10] } };
345+
const returnData = Data.generateData(props);
346+
expect(returnData).toEqual(generatedReturn);
347+
});
348+
339349
it("generates a dataset from domain and samples", () => {
340350
const generatedReturn = [
341351
{ x: 0, y: 0 },

packages/victory-core/src/victory-util/data.ts

+1-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
import React from "react";
33
import {
44
uniq,
5-
range,
65
last,
76
isFunction,
87
isPlainObject,
@@ -46,7 +45,7 @@ function generateDataArray(props, axis) {
4645
const domainMax = Math.max(...domain);
4746
const domainMin = Math.min(...domain);
4847
const step = (domainMax - domainMin) / samples;
49-
const values = range(domainMin, domainMax, step);
48+
const values = Helpers.range(domainMin, domainMax, step);
5049
return last(values) === domainMax ? values : values.concat(domainMax);
5150
}
5251

packages/victory-core/src/victory-util/helpers.test.ts

+46
Original file line numberDiff line numberDiff line change
@@ -202,4 +202,50 @@ describe("victory-util/helpers", () => {
202202
expect(undefinedAccessor(14)).toEqual(14);
203203
});
204204
});
205+
206+
describe("range", () => {
207+
it("returns an array of integers", () => {
208+
expect(Helpers.range(4)).toEqual([0, 1, 2, 3]);
209+
});
210+
211+
it("returns an array of integers for negative n", () => {
212+
expect(Helpers.range(-4)).toEqual([0, -1, -2, -3]);
213+
});
214+
215+
it("returns an array of integers from start to end", () => {
216+
expect(Helpers.range(1, 5)).toEqual([1, 2, 3, 4]);
217+
});
218+
219+
it("returns an array of integers from negative start to end", () => {
220+
expect(Helpers.range(-5, 5)).toEqual([-5, -4, -3, -2, -1, 0, 1, 2, 3, 4]);
221+
});
222+
223+
it("returns an array of integers from start to negative end", () => {
224+
expect(Helpers.range(5, -5)).toEqual([5, 4, 3, 2, 1, 0, -1, -2, -3, -4]);
225+
});
226+
227+
it("returns an array of integers using an increment", () => {
228+
expect(Helpers.range(0, 20, 5)).toEqual([0, 5, 10, 15]);
229+
});
230+
231+
it("returns an array of integers using an increment and negative start", () => {
232+
expect(Helpers.range(-10, 20, 5)).toEqual([-10, -5, 0, 5, 10, 15]);
233+
});
234+
235+
it("returns an array of numbers from a floating point increment", () => {
236+
expect(Helpers.range(0, 1, 0.2).length).toEqual(5);
237+
});
238+
239+
it("should parse non-integer values", () => {
240+
expect(Helpers.range(4.7)).toEqual([0, 1, 2, 3, 4]);
241+
});
242+
243+
it("should not throw on undefined start value", () => {
244+
expect(Helpers.range(undefined as any)).toEqual([]);
245+
});
246+
247+
it("should not throw on NaN start value", () => {
248+
expect(Helpers.range(NaN as any)).toEqual([]);
249+
});
250+
});
205251
});

packages/victory-core/src/victory-util/helpers.ts

+31
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,37 @@ export function getCurrentAxis(axis, horizontal) {
217217
return horizontal ? otherAxis : axis;
218218
}
219219

220+
/**
221+
* Creates an array of numbers (positive and/or negative) progressing
222+
* from start up to, but not including, end.
223+
* A step of -1 is used if a negative start is specified without an end or step.
224+
* If end is not specified, it's set to start with start then set to 0.
225+
*
226+
* @param start The length of the array to create, or the start value
227+
* @param end [The end value] If this is defined, start is the start value
228+
* @returns An array of the given length
229+
*/
230+
export function range(start: number, end?: number, increment?: number) {
231+
// when the end index is not given, start from 0
232+
const startIndex = end ? start : 0;
233+
234+
// when the end index is not given, the end of the range is the start index
235+
let endIndex = end ? end : start;
236+
237+
// ensure endIndex is not a falsy value
238+
if (!endIndex) endIndex = 0;
239+
240+
const k = endIndex - startIndex; // the value range
241+
const length = Math.abs(k); // the length of the range
242+
const sign = k / length || 1; // the sign of the range (negative or positive)
243+
const inc = increment || 1; // the step size of each increment
244+
245+
// normalize the array length when dealing with floating point values
246+
const arrayLength = Math.max(Math.ceil(length / inc), 0);
247+
248+
return Array.from(Array(arrayLength), (_, i) => startIndex + i * sign * inc);
249+
}
250+
220251
/**
221252
* @param {Array} children: an array of child components
222253
* @param {Function} iteratee: a function with arguments "child", "childName", and "parent"

packages/victory-core/src/victory-util/point-path-helpers.ts

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
/* eslint no-magic-numbers: ["error", { "ignore": [0, 1, 2, 2.5, 3] }]*/
2-
import { range } from "lodash";
2+
3+
import * as Helpers from "./helpers";
34

45
export function circle(x: number, y: number, size: number) {
56
return `M ${x}, ${y}
@@ -110,7 +111,7 @@ export function star(x: number, y: number, size: number) {
110111
const baseSize = 1.35 * size; // eslint-disable-line no-magic-numbers
111112
const angle = Math.PI / 5; // eslint-disable-line no-magic-numbers
112113
// eslint-disable-next-line no-magic-numbers
113-
const starCoords = range(10).map((index) => {
114+
const starCoords = Helpers.range(10).map((index) => {
114115
const length = index % 2 === 0 ? baseSize : baseSize / 2;
115116
return `${length * Math.sin(angle * (index + 1)) + x},
116117
${length * Math.cos(angle * (index + 1)) + y}`;

0 commit comments

Comments
 (0)