diff --git a/.changeset/proud-islands-smoke.md b/.changeset/proud-islands-smoke.md new file mode 100644 index 000000000..718bc661e --- /dev/null +++ b/.changeset/proud-islands-smoke.md @@ -0,0 +1,13 @@ +--- +"victory-box-plot": patch +"victory-brush-container": patch +"victory-core": patch +"victory-create-container": patch +"victory-cursor-container": patch +"victory-scatter": patch +"victory-selection-container": patch +"victory-voronoi": patch +"victory-voronoi-container": patch +--- + +Replace lodash array utils with native code diff --git a/packages/victory-box-plot/src/victory-box-plot.tsx b/packages/victory-box-plot/src/victory-box-plot.tsx index bf86b4789..b789f4406 100644 --- a/packages/victory-box-plot/src/victory-box-plot.tsx +++ b/packages/victory-box-plot/src/victory-box-plot.tsx @@ -1,5 +1,4 @@ import React from "react"; -import { flatten } from "lodash"; import { Helpers, VictoryLabel, @@ -182,8 +181,8 @@ class VictoryBoxPlotBase extends React.Component { renderBoxPlot(props) { const types = ["q1", "q3", "max", "min", "median"]; - const dataComponents = flatten( - types.map((type) => { + const dataComponents = types + .map((type) => { return this.dataKeys.reduce((validDataComponents, _key, index) => { const baseComponent = props[`${type}Component`]; const componentProps = this.getComponentProps( @@ -198,11 +197,11 @@ class VictoryBoxPlotBase extends React.Component { } return validDataComponents; }, [] as React.ReactElement[]); - }), - ); + }) + .flat(); - const labelComponents = flatten( - types.map((type) => { + const labelComponents = types + .map((type) => { const components = this.dataKeys.reduce( (validComponents, _key, index) => { const name = `${type}Labels`; @@ -222,8 +221,9 @@ class VictoryBoxPlotBase extends React.Component { [] as React.ReactElement[], ); return components.filter(Boolean); - }), - ); + }) + .flat(); + const children = [...dataComponents, ...labelComponents]; return this.renderContainer(props.groupComponent, children); } diff --git a/packages/victory-core/src/victory-util/add-events.tsx b/packages/victory-core/src/victory-util/add-events.tsx index 746deb791..0f0daefb6 100644 --- a/packages/victory-core/src/victory-util/add-events.tsx +++ b/packages/victory-core/src/victory-util/add-events.tsx @@ -1,5 +1,5 @@ import React from "react"; -import { defaults, difference, isEmpty, keys, pick, without } from "lodash"; +import { defaults, difference, isEmpty, keys, pick } from "lodash"; import type { ComponentEvent } from "./events"; import * as Events from "./events"; import isEqual from "react-fast-compare"; @@ -424,7 +424,7 @@ export function addEvents< // Used by `VictoryLine` and `VictoryArea` renderContinuousData(props: TProps) { const { dataComponent, labelComponent, groupComponent } = props; - const dataKeys = without(this.dataKeys, "all"); + const dataKeys = this.dataKeys.filter((value) => value !== "all"); const labelComponents = dataKeys.reduce((memo, key) => { let newMemo = memo; const labelProps = this.getComponentProps( diff --git a/packages/victory-core/src/victory-util/axis.tsx b/packages/victory-core/src/victory-util/axis.tsx index d34ae19c5..c3d5d29f4 100644 --- a/packages/victory-core/src/victory-util/axis.tsx +++ b/packages/victory-core/src/victory-util/axis.tsx @@ -1,14 +1,5 @@ import React from "react"; -import { - defaults, - identity, - isObject, - invert, - uniq, - orderBy, - includes, - without, -} from "lodash"; +import { defaults, identity, isObject, invert, uniq, orderBy } from "lodash"; import * as Collection from "./collection"; import * as Domain from "./domain"; import * as Helpers from "./helpers"; @@ -299,7 +290,7 @@ export function getTicks(props, scale: D3Scale, filterZero = false) { : scale.domain(); const ticks = downsampleTicks(scaledTickArray, tickCount); if (filterZero) { - const filteredTicks = includes(ticks, 0) ? without(ticks, 0) : ticks; + const filteredTicks = ticks.filter((value) => value !== 0); return filteredTicks.length ? filteredTicks : ticks; } return ticks; diff --git a/packages/victory-core/src/victory-util/data.ts b/packages/victory-core/src/victory-util/data.ts index 6b66cff2e..6a207154c 100644 --- a/packages/victory-core/src/victory-util/data.ts +++ b/packages/victory-core/src/victory-util/data.ts @@ -2,13 +2,11 @@ import React from "react"; import { uniq, - last, isPlainObject, property, orderBy, isEmpty, isEqual, - includes, isUndefined, omitBy, } from "lodash"; @@ -45,7 +43,9 @@ function generateDataArray(props, axis) { const domainMin = Math.min(...domain); const step = (domainMax - domainMin) / samples; const values = Helpers.range(domainMin, domainMax, step); - return last(values) === domainMax ? values : values.concat(domainMax); + return values[values.length - 1] === domainMax + ? values + : values.concat(domainMax); } // Returns sorted data. If no sort keys are provided, data is returned unaltered. @@ -454,5 +454,5 @@ export function isDataComponent(component) { "stack", "voronoi", ]; - return includes(whitelist, role); + return whitelist.includes(role); } diff --git a/packages/victory-core/src/victory-util/domain.ts b/packages/victory-core/src/victory-util/domain.ts index 3d3ab2147..52da12f65 100644 --- a/packages/victory-core/src/victory-util/domain.ts +++ b/packages/victory-core/src/victory-util/domain.ts @@ -1,6 +1,6 @@ /* eslint-disable no-use-before-define */ import React from "react"; -import { flatten, isPlainObject, sortedUniq, includes, isDate } from "lodash"; +import { isPlainObject, sortedUniq, isDate } from "lodash"; import * as Data from "./data"; import * as Scale from "./scale"; import * as Helpers from "./helpers"; @@ -42,7 +42,7 @@ function getDomainPadding(props, axis) { function getFlatData(dataset, axis: "x" | "y") { const axisKey = `_${axis}`; - return flatten(dataset).map((datum: any) => { + return dataset.flat().map((datum: any) => { return datum[axisKey] && datum[axisKey][1] !== undefined ? datum[axisKey][1] : datum[axisKey]; @@ -54,7 +54,7 @@ function getExtremeFromData(dataset, axis, type = "min") { type === "max" ? Math.max(...arr) : Math.min(...arr); const initialValue = type === "max" ? -Infinity : Infinity; let containsDate = false; - const result = flatten(dataset).reduce((memo: number, datum: any) => { + const result = dataset.flat().reduce((memo: number, datum: any) => { const current0 = datum[`_${axis}0`] !== undefined ? datum[`_${axis}0`] : datum[`_${axis}`]; const current1 = @@ -459,5 +459,5 @@ export function isDomainComponent(component) { "stack", "voronoi", ]; - return includes(whitelist, role); + return whitelist.includes(role); } diff --git a/packages/victory-core/src/victory-util/events.ts b/packages/victory-core/src/victory-util/events.ts index e6aa719fa..ddb8e90fe 100644 --- a/packages/victory-core/src/victory-util/events.ts +++ b/packages/victory-core/src/victory-util/events.ts @@ -1,5 +1,5 @@ /* eslint-disable no-use-before-define */ -import { isEmpty, without, pickBy, omitBy, uniq, includes, keys } from "lodash"; +import { isEmpty, pickBy, omitBy, uniq, keys } from "lodash"; import type { EventMixinCalculatedValues } from "./add-events"; import { isFunction } from "./helpers"; @@ -50,7 +50,7 @@ export function getEvents( const targetEvents = events.reduce((memo, event) => { if (event.target !== undefined) { const matchesTarget = Array.isArray(event.target) - ? includes(event.target, target) + ? event.target.includes(target) : `${event.target}` === `${target}`; return matchesTarget ? memo.concat(event) : memo; } @@ -157,8 +157,8 @@ export function getScopedEvents( } if (eventReturn.eventKey === "all") { return newBaseProps[childName] - ? without(keys(newBaseProps[childName]), "parent") - : without(keys(newBaseProps), "parent"); + ? keys(newBaseProps[childName]).filter((value) => value !== "parent") + : keys(newBaseProps).filter((value) => value !== "parent"); } else if (eventReturn.eventKey === undefined && eventKey === "parent") { return newBaseProps[childName] ? keys(newBaseProps[childName]) @@ -233,7 +233,9 @@ export function getScopedEvents( // returns an entire mutated state for all children const allChildNames = - childNames === "all" ? without(keys(newBaseProps), "parent") : childNames; + childNames === "all" + ? keys(newBaseProps).filter((value) => value !== "parent") + : childNames; return Array.isArray(allChildNames) ? allChildNames.reduce((memo, childName) => { return Object.assign(memo, getReturnByChild(childName)); @@ -438,7 +440,7 @@ export function getExternalMutation( } else if (Array.isArray(mutation[type])) { // coerce arrays to strings before matching const stringArray = mutation[type].map((m) => `${m}`); - return includes(stringArray, identifier[type]); + return stringArray.includes(identifier[type]); } return false; }; diff --git a/packages/victory-core/src/victory-util/hooks/use-animation-state.ts b/packages/victory-core/src/victory-util/hooks/use-animation-state.ts index 0d44857eb..8c85d6369 100644 --- a/packages/victory-core/src/victory-util/hooks/use-animation-state.ts +++ b/packages/victory-core/src/victory-util/hooks/use-animation-state.ts @@ -1,5 +1,5 @@ import React from "react"; -import { defaults, some } from "lodash"; +import { defaults } from "lodash"; import * as Collection from "../collection"; import * as Transitions from "../transitions"; @@ -91,15 +91,15 @@ export const useAnimationState = (initialState = INITIAL_STATE) => { const nextChildren = React.Children.toArray(nextProps.children); const isContinuous = (child) => { const check = (c) => c.type && c.type.continuous; - return Array.isArray(child) ? some(child, check) : check(child); + return Array.isArray(child) ? child.some(check) : check(child); }; const continuous = !props.polar && - some(oldChildren, (child: React.ReactElement) => { + oldChildren.some((child: any) => { return ( isContinuous(child) || - (child.props.children && isContinuous(child.props.children)) + (child?.props?.children && isContinuous(child.props.children)) ); }); const { diff --git a/packages/victory-core/src/victory-util/scale.ts b/packages/victory-core/src/victory-util/scale.ts index c968b8154..e90f18350 100644 --- a/packages/victory-core/src/victory-util/scale.ts +++ b/packages/victory-core/src/victory-util/scale.ts @@ -1,5 +1,5 @@ /* eslint-disable no-use-before-define */ -import { includes, isPlainObject } from "lodash"; +import { isPlainObject } from "lodash"; import * as Helpers from "./helpers"; import * as Collection from "./collection"; import * as d3Scale from "victory-vendor/d3-scale"; @@ -30,7 +30,7 @@ export function validScale( Helpers.isFunction(scale.range) ); } else if (typeof scale === "string") { - return includes(supportedScaleStrings, scale); + return (supportedScaleStrings as ReadonlyArray).includes(scale); } return false; } diff --git a/packages/victory-core/src/victory-util/wrapper.tsx b/packages/victory-core/src/victory-util/wrapper.tsx index ef18726f0..2c39e0166 100644 --- a/packages/victory-core/src/victory-util/wrapper.tsx +++ b/packages/victory-core/src/victory-util/wrapper.tsx @@ -1,11 +1,4 @@ -import { - defaults, - flatten, - uniq, - groupBy, - uniqBy, - isPlainObject, -} from "lodash"; +import { defaults, uniq, groupBy, uniqBy, isPlainObject } from "lodash"; import React from "react"; import * as Axis from "./axis"; import * as Style from "./style"; @@ -428,7 +421,7 @@ export function getCategoryAndAxisStringsFromChildren( : []; const categoryStrings = categories || getStringsFromCategories(childComponents, axis); - return uniq(flatten([...categoryStrings, ...axisStrings])); + return uniq([...categoryStrings, ...axisStrings].flat()); } export function getStringsFromChildren(props, childComponents) { @@ -440,8 +433,8 @@ export function getStringsFromChildren(props, childComponents) { const dataStrings = getStringsFromData(children); return { - x: uniq(flatten([...xStrings, ...dataStrings.x])), - y: uniq(flatten([...yStrings, ...dataStrings.y])), + x: uniq([...xStrings, ...dataStrings.x].flat()), + y: uniq([...yStrings, ...dataStrings.y].flat()), }; } diff --git a/packages/victory-create-container/src/create-container.ts b/packages/victory-create-container/src/create-container.ts index e0c3f739e..9c1ea5815 100644 --- a/packages/victory-create-container/src/create-container.ts +++ b/packages/victory-create-container/src/create-container.ts @@ -1,5 +1,5 @@ import React from "react"; -import { toPairs, groupBy, forOwn, includes, flow, isEmpty } from "lodash"; +import { toPairs, groupBy, forOwn, flow, isEmpty } from "lodash"; import { Helpers, VictoryContainer, Log } from "victory-core"; import { voronoiContainerMixin } from "victory-voronoi-container"; import { zoomContainerMixin } from "victory-zoom-container"; @@ -121,7 +121,7 @@ const checkBehaviorName = ( behavior: ContainerType, behaviors: ContainerType[], ) => { - if (behavior && !includes(behaviors, behavior)) { + if (behavior && !behaviors.includes(behavior)) { Log.warn( `"${behavior}" is not a valid behavior. Choose from [${behaviors.join( ", ", diff --git a/packages/victory-selection-container/src/selection-helpers.tsx b/packages/victory-selection-container/src/selection-helpers.tsx index 78b18d9af..6d6d530e9 100644 --- a/packages/victory-selection-container/src/selection-helpers.tsx +++ b/packages/victory-selection-container/src/selection-helpers.tsx @@ -1,5 +1,5 @@ import { Selection, Data, Helpers, Datum } from "victory-core"; -import { defaults, throttle, includes } from "lodash"; +import { defaults, throttle } from "lodash"; import React from "react"; const ON_MOUSE_MOVE_THROTTLE_MS = 16; @@ -26,7 +26,7 @@ class SelectionHelpersClass { const iteratee = (child, childName, parent) => { const blacklist = props.selectionBlacklist || []; let childElement; - if (!Data.isDataComponent(child) || includes(blacklist, childName)) { + if (!Data.isDataComponent(child) || blacklist.includes(childName)) { return null; } else if (child.type && Helpers.isFunction(child.type.getData)) { childElement = parent ? React.cloneElement(child, parent.props) : child; diff --git a/packages/victory-voronoi-container/src/voronoi-helpers.ts b/packages/victory-voronoi-container/src/voronoi-helpers.ts index d559a45c3..b373fafae 100644 --- a/packages/victory-voronoi-container/src/voronoi-helpers.ts +++ b/packages/victory-voronoi-container/src/voronoi-helpers.ts @@ -1,5 +1,5 @@ import { Collection, Selection, Data, Helpers } from "victory-core"; -import { isEmpty, includes, isString, isRegExp, throttle } from "lodash"; +import { isEmpty, isString, isRegExp, throttle } from "lodash"; import isEqual from "react-fast-compare"; import Delaunay from "delaunay-find/lib/index.js"; import React from "react"; @@ -71,7 +71,7 @@ class VoronoiHelpersClass { const isRegExpMatch = blacklistRegExp.some((regExp) => regExp.test(name)); if ( !Data.isDataComponent(child) || - includes(blacklistStr, name) || + blacklistStr.includes(name) || isRegExpMatch ) { return null; diff --git a/packages/victory-voronoi/src/helper-methods.ts b/packages/victory-voronoi/src/helper-methods.ts index e93e107d1..81eb25f9f 100644 --- a/packages/victory-voronoi/src/helper-methods.ts +++ b/packages/victory-voronoi/src/helper-methods.ts @@ -1,4 +1,3 @@ -import { without } from "lodash"; // victory-vendor note: This module is still CommonJS, so not part of victory-vendor. import { voronoi as d3Voronoi } from "d3-voronoi"; import { Helpers, LabelHelpers, Scale, Domain, Data } from "victory-core"; @@ -122,7 +121,7 @@ export const getBaseProps = (initialProps, fallbackProps) => { }; return data.reduce((childProps, datum, index) => { - const polygon = without(polygons[index], "data"); + const polygon = polygons[index]?.filter((value) => value !== "data"); const eventKey = !Helpers.isNil(datum.eventKey) ? datum.eventKey : index; const { x, y } = Helpers.scalePoint(props, datum); const dataProps = {