VictoryChart
-
+
-
+
{
-
+
+ Standalone Stack
+
+
+
+
+
+
+ )
+ }
+}
+
+export default App;
\ No newline at end of file
diff --git a/packages/victory-chart/src/index.d.ts b/packages/victory-chart/src/index.d.ts
index 03573ee63..123be7e52 100644
--- a/packages/victory-chart/src/index.d.ts
+++ b/packages/victory-chart/src/index.d.ts
@@ -18,6 +18,7 @@ export interface VictoryChartProps extends VictoryCommonProps {
backgroundComponent?: React.ReactElement;
categories?: CategoryPropType;
children?: React.ReactNode | React.ReactNode[];
+ desc?: string;
defaultAxes?: AxesType;
defaultPolarAxes?: AxesType;
domain?: DomainPropType;
@@ -33,6 +34,7 @@ export interface VictoryChartProps extends VictoryCommonProps {
style?: Pick
& {
background?: VictoryStyleObject;
};
+ title?: string;
}
export class VictoryChart extends React.Component {}
diff --git a/packages/victory-chart/src/victory-chart.js b/packages/victory-chart/src/victory-chart.js
index 1592b4580..2bdf17adf 100644
--- a/packages/victory-chart/src/victory-chart.js
+++ b/packages/victory-chart/src/victory-chart.js
@@ -3,13 +3,14 @@ import PropTypes from "prop-types";
import React from "react";
import {
Background,
+ CommonProps,
Helpers,
+ Hooks,
+ PropTypes as CustomPropTypes,
+ UserProps,
VictoryContainer,
VictoryTheme,
- CommonProps,
- PropTypes as CustomPropTypes,
Wrapper,
- Hooks
} from "victory-core";
import { VictorySharedEvents } from "victory-shared-events";
import { VictoryAxis } from "victory-axis";
@@ -124,12 +125,13 @@ const VictoryChart = (initialProps) => {
const defaultContainerProps = defaults(
{},
containerComponent.props,
- containerProps
+ containerProps,
+ UserProps.getSafeUserProps(initialProps)
);
return React.cloneElement(containerComponent, defaultContainerProps);
}
return groupComponent;
- }, [groupComponent, standalone, containerComponent, containerProps]);
+ }, [groupComponent, standalone, containerComponent, containerProps, initialProps]);
const events = React.useMemo(() => {
return Wrapper.getAllEvents(props);
diff --git a/packages/victory-core/src/index.js b/packages/victory-core/src/index.js
index 0c923ea46..d486de502 100644
--- a/packages/victory-core/src/index.js
+++ b/packages/victory-core/src/index.js
@@ -39,6 +39,7 @@ export * as Style from "./victory-util/style";
export * as TextSize from "./victory-util/textsize";
export { default as Timer } from "./victory-util/timer";
export * as Transitions from "./victory-util/transitions";
+export * as UserProps from "./victory-util/user-props";
export * as CommonProps from "./victory-util/common-props";
export * as Wrapper from "./victory-util/wrapper";
export * as Axis from "./victory-util/axis";
diff --git a/packages/victory-core/src/victory-container/victory-container.js b/packages/victory-core/src/victory-container/victory-container.js
index f51c3f6e3..3470922a4 100644
--- a/packages/victory-core/src/victory-container/victory-container.js
+++ b/packages/victory-core/src/victory-container/victory-container.js
@@ -6,6 +6,7 @@ import Portal from "../victory-portal/portal";
import PortalContext from "../victory-portal/portal-context";
import TimerContext from "../victory-util/timer-context";
import * as Helpers from "../victory-util/helpers";
+import * as UserProps from "../victory-util/user-props";
export default class VictoryContainer extends React.Component {
static displayName = "VictoryContainer";
@@ -192,9 +193,13 @@ export default class VictoryContainer extends React.Component {
preserveAspectRatio,
role
} = this.props;
+
const style = responsive
? this.props.style
: Helpers.omit(this.props.style, ["height", "width"]);
+
+ const userProps = UserProps.getSafeUserProps(this.props);
+
const svgProps = assign(
{
width,
@@ -213,7 +218,8 @@ export default class VictoryContainer extends React.Component {
.filter(Boolean)
.join(" ") || undefined,
viewBox: responsive ? `0 0 ${width} ${height}` : undefined,
- preserveAspectRatio: responsive ? preserveAspectRatio : undefined
+ preserveAspectRatio: responsive ? preserveAspectRatio : undefined,
+ ...userProps
},
events
);
diff --git a/packages/victory-core/src/victory-util/add-events.js b/packages/victory-core/src/victory-util/add-events.js
index 76b293679..71c0e765c 100644
--- a/packages/victory-core/src/victory-util/add-events.js
+++ b/packages/victory-core/src/victory-util/add-events.js
@@ -14,6 +14,7 @@ import {
import * as Events from "./events";
import isEqual from "react-fast-compare";
import VictoryTransition from "../victory-transition/victory-transition";
+import * as UserProps from '../victory-util/user-props';
const datumHasXandY = (datum) => {
return !isNil(datum._x) && !isNil(datum._y);
@@ -274,11 +275,14 @@ export default (WrappedComponent, options) => {
const parentProps = isContainer
? this.getComponentProps(component, "parent", "parent")
: {};
+
if (parentProps.events) {
this.globalEvents = Events.getGlobalEvents(parentProps.events);
parentProps.events = Events.omitGlobalEvents(parentProps.events);
}
- return React.cloneElement(component, parentProps, children);
+
+ const componentProps = { ...parentProps, ...parentProps.userProps };
+ return React.cloneElement(component, componentProps, children);
}
animateComponent(props, defaultAnimationWhitelist) {
@@ -327,23 +331,24 @@ export default (WrappedComponent, options) => {
renderData(props, shouldRenderDatum = datumHasXandY) {
const { dataComponent, labelComponent, groupComponent } = props;
-
+ const userProps = UserProps.getSafeUserProps(props);
+
const dataComponents = this.dataKeys.reduce(
(validDataComponents, _dataKey, index) => {
const dataProps = this.getComponentProps(
dataComponent,
"data",
index
- );
- if (shouldRenderDatum(dataProps.datum)) {
- validDataComponents.push(
- React.cloneElement(dataComponent, dataProps)
);
- }
- return validDataComponents;
- },
- []
- );
+ if (shouldRenderDatum(dataProps.datum)) {
+ validDataComponents.push(
+ React.cloneElement(dataComponent, dataProps)
+ );
+ }
+ return validDataComponents;
+ },
+ []
+ );
const labelComponents = this.dataKeys
.map((_dataKey, index) => {
@@ -360,7 +365,8 @@ export default (WrappedComponent, options) => {
.filter(Boolean);
const children = [...dataComponents, ...labelComponents];
- return this.renderContainer(groupComponent, children);
+ const group = React.cloneElement(groupComponent, { ...userProps }, children);
+ return this.renderContainer(group, children);
}
};
};
diff --git a/packages/victory-core/src/victory-util/user-props.js b/packages/victory-core/src/victory-util/user-props.js
new file mode 100644
index 000000000..88504cbd6
--- /dev/null
+++ b/packages/victory-core/src/victory-util/user-props.js
@@ -0,0 +1,64 @@
+/*
+ USER_PROPS_SAFELIST is to contain any string deemed safe for user props.
+ The startsWidth array will contain the start of any accepted user-prop that
+ starts with these characters.
+ The exactMatch will contain a list of exact prop names that are accepted.
+*/
+const USER_PROPS_SAFELIST = {
+ startsWith: ["data-", "aria-"],
+ exactMatch: []
+};
+
+/**
+ * doesPropStartWith: Function that takes a prop's key and runs it against all
+ * options in the USER_PROPS_SAFELIST and checks to see if it starts with any
+ * of those options.
+ * @param {string} key: prop key to be tested against whitelist
+ * @returns {Boolean}: returns true if the key starts with an option or false if
+ * otherwise
+ */
+const doesPropStartWith = (key) => {
+ let startsWith = false;
+
+ USER_PROPS_SAFELIST.startsWith.forEach((starterString) => {
+ const regex = new RegExp(`\\b(${starterString})(\\w|-)+`, "g");
+ if (regex.test(key)) startsWith = true;
+ });
+
+ return startsWith;
+};
+
+/**
+ * isExactMatch: checks to see if the given key matches any of the 'exactMatch'
+ * items in the whitelist
+ * @param {String} key: prop key to be tested against the whitelist-exact match
+ * array.
+ * @returns {Boolean}: return true if whitelist contains that key, otherwise
+ * returns false.
+ */
+const isExactMatch = (key) => USER_PROPS_SAFELIST.exactMatch.includes(key);
+
+/**
+ * testIfSafeProp: tests prop's key against both startsWith and exactMatch values
+ * @param {String} key: prop key to be tested against the whitelist
+ * @returns {Boolean}: returns true if found in whitelist, otherwise returns false
+ */
+const testIfSafeProp = (key) => {
+ if (doesPropStartWith(key) || isExactMatch(key)) return true;
+ return false;
+};
+
+/**
+ * getSafeUserProps - function that takes in a props object and removes any
+ * key-value entries that do not match filter strings in the USER_PROPS_SAFELIST
+ * object.
+ *
+ * @param {Object} props: props to be filtered against USER_PROPS_SAFELIST
+ * @returns {Object}: object containing remaining acceptable props
+ */
+export const getSafeUserProps = (props) => {
+ const propsToFilter = { ...props };
+ return Object.fromEntries(
+ Object.entries(propsToFilter).filter(([key]) => testIfSafeProp(key))
+ );
+};
\ No newline at end of file
diff --git a/packages/victory-group/src/victory-group.js b/packages/victory-group/src/victory-group.js
index f3a70ee92..b428f88f8 100644
--- a/packages/victory-group/src/victory-group.js
+++ b/packages/victory-group/src/victory-group.js
@@ -2,12 +2,13 @@ import { assign, defaults, isEmpty } from "lodash";
import PropTypes from "prop-types";
import React from "react";
import {
+ CommonProps,
Helpers,
+ Hooks,
+ UserProps,
VictoryContainer,
VictoryTheme,
- CommonProps,
Wrapper,
- Hooks
} from "victory-core";
import { VictorySharedEvents } from "victory-shared-events";
import { getChildren, useMemoizedProps } from "./helper-methods";
@@ -88,17 +89,21 @@ const VictoryGroup = (initialProps) => {
name
]);
+ const userProps = React.useMemo(() => UserProps.getSafeUserProps(initialProps), [initialProps]);
+
const container = React.useMemo(() => {
if (standalone) {
const defaultContainerProps = defaults(
{},
containerComponent.props,
- containerProps
+ containerProps,
+ userProps
);
return React.cloneElement(containerComponent, defaultContainerProps);
}
- return groupComponent;
- }, [groupComponent, standalone, containerComponent, containerProps]);
+
+ return React.cloneElement(groupComponent, userProps);
+ }, [groupComponent, standalone, containerComponent, containerProps, userProps]);
const events = React.useMemo(() => {
return Wrapper.getAllEvents(props);
diff --git a/packages/victory-stack/src/victory-stack.js b/packages/victory-stack/src/victory-stack.js
index 886beab46..84ebf6506 100644
--- a/packages/victory-stack/src/victory-stack.js
+++ b/packages/victory-stack/src/victory-stack.js
@@ -2,13 +2,14 @@ import { assign, defaults, isEmpty } from "lodash";
import PropTypes from "prop-types";
import React from "react";
import {
+ CommonProps,
Helpers,
+ Hooks,
+ PropTypes as CustomPropTypes,
+ UserProps,
VictoryContainer,
VictoryTheme,
- CommonProps,
Wrapper,
- PropTypes as CustomPropTypes,
- Hooks
} from "victory-core";
import { VictorySharedEvents } from "victory-shared-events";
import { getChildren, useMemoizedProps } from "./helper-methods";
@@ -94,18 +95,20 @@ const VictoryStack = (initialProps) => {
origin,
name
]);
+ const userProps = React.useMemo(() => UserProps.getSafeUserProps(initialProps), [initialProps]);
const container = React.useMemo(() => {
if (standalone) {
const defaultContainerProps = defaults(
{},
containerComponent.props,
- containerProps
+ containerProps,
+ userProps
);
return React.cloneElement(containerComponent, defaultContainerProps);
}
- return groupComponent;
- }, [groupComponent, standalone, containerComponent, containerProps]);
+ return React.cloneElement(groupComponent, userProps);
+ }, [groupComponent, standalone, containerComponent, containerProps, userProps]);
const events = React.useMemo(() => {
return Wrapper.getAllEvents(props);
diff --git a/packages/victory/src/index.js b/packages/victory/src/index.js
index 5f4fb2bc6..b578275b7 100644
--- a/packages/victory/src/index.js
+++ b/packages/victory/src/index.js
@@ -1,43 +1,44 @@
export {
+ addEvents,
+ Axis,
Background,
Border,
Box,
- ClipPath,
- LineSegment,
- Whisker,
Circle,
- Rect,
- Line,
- Path,
- TSpan,
- Text,
- Point,
- VictoryAnimation,
- VictoryContainer,
- VictoryLabel,
- VictoryTheme,
- VictoryTransition,
- VictoryPortal,
- Portal,
- VictoryClipContainer,
- addEvents,
+ ClipPath,
Collection,
Data,
DefaultTransitions,
Domain,
Events,
Helpers,
+ LabelHelpers,
+ Line,
+ LineSegment,
Log,
+ Path,
+ Point,
+ Portal,
PropTypes,
+ Rect,
Scale,
+ Selection,
Style,
+ Text,
TextSize,
Transitions,
- Selection,
- LabelHelpers,
- Axis,
+ TSpan,
+ UserProps,
+ VictoryAccessibleGroup,
+ VictoryAnimation,
+ VictoryClipContainer,
+ VictoryContainer,
+ VictoryLabel,
+ VictoryPortal,
+ VictoryTheme,
+ VictoryTransition,
+ Whisker,
Wrapper,
- VictoryAccessibleGroup
} from "victory-core";
export { VictoryChart } from "victory-chart";