/* eslint-disable no-use-before-define */ import React from "react"; import { Helpers, Scale, Axis, Wrapper } from "victory-core"; import { defaults } from "lodash"; const fallbackProps = { width: 450, height: 300, padding: 50, }; function getAxisProps(child, props, calculatedProps) { const { domain, scale, stringMap, categories, horizontal } = calculatedProps; return { stringMap, horizontal, categories, startAngle: props.startAngle, endAngle: props.endAngle, innerRadius: props.innerRadius, domain, scale, }; } export function getBackgroundWithProps(props, calculatedProps) { const backgroundElement = props.backgroundComponent; const height = props.polar ? calculatedProps.range.y[1] : calculatedProps.range.y[0] - calculatedProps.range.y[1]; const width = calculatedProps.range.x[1] - calculatedProps.range.x[0]; const xScale = props.horizontal ? calculatedProps.scale.y.range()[0] : calculatedProps.scale.x.range()[0]; const yScale = props.horizontal ? calculatedProps.scale.x.range()[1] : calculatedProps.scale.y.range()[1]; const xCoordinate = props.polar ? calculatedProps.origin.x : xScale; const yCoordinate = props.polar ? calculatedProps.origin.y : yScale; const parentName = props.name || "chart"; const backgroundProps = { height, polar: props.polar, scale: calculatedProps.scale, style: props.style.background, x: xCoordinate, y: yCoordinate, key: `${parentName}-background`, width, }; return React.cloneElement( backgroundElement, defaults({}, backgroundElement.props, backgroundProps), ); } function getChildProps(child, props, calculatedProps) { const axisChild = Axis.findAxisComponents([child]); if (axisChild.length > 0) { return getAxisProps(axisChild[0], props, calculatedProps); } const { categories, domain, range, scale, stringMap, horizontal } = calculatedProps; return { categories, domain, range, scale, stringMap, horizontal }; } function getStyles(props) { const styleProps = props.style && props.style.parent; return { parent: defaults({}, styleProps, { height: "100%", width: "100%", userSelect: "none", }), }; } export function getCalculatedProps(initialProps, childComponents) { const style = getStyles(initialProps); const props = Helpers.modifyProps(initialProps, fallbackProps, "chart"); const { horizontal, polar } = props; const allStrings = Wrapper.getStringsFromChildren(props, childComponents); const categories = Wrapper.getCategories(props, childComponents, allStrings); const stringMap = createStringMap(props, childComponents, allStrings); const domain = { x: getDomain( Object.assign({}, props, { categories }), "x", childComponents, ), y: getDomain( Object.assign({}, props, { categories }), "y", childComponents, ), }; const range = { x: Helpers.getRange(props, "x"), y: Helpers.getRange(props, "y"), }; const baseScale = { x: Scale.getScaleFromProps(props, "x") || Wrapper.getScale(props, "x"), y: Scale.getScaleFromProps(props, "y") || Wrapper.getScale(props, "y"), }; const scale = { x: baseScale.x.domain(domain.x).range(horizontal ? range.y : range.x), y: baseScale.y.domain(domain.y).range(horizontal ? range.x : range.y), }; const origin = polar ? Helpers.getPolarOrigin(props) : Axis.getOrigin(domain); const padding = Helpers.getPadding(props); return { categories, domain, range, horizontal, scale, stringMap, style, origin, padding, }; } export function getChildren(props, childComponents, calculatedProps) { const children = childComponents || getChildComponents(props); const newCalculatedProps = calculatedProps || getCalculatedProps(props, children); const baseStyle = newCalculatedProps.style.parent; const { height, polar, theme, width } = props; const { origin, horizontal } = newCalculatedProps; const parentName = props.name || "chart"; return children.filter(React.isValidElement).map((child, index) => { const role = child.type && child.type.role; const style = Array.isArray(child.props.style) ? child.props.style : defaults({}, child.props.style, { parent: baseStyle }); const childProps = getChildProps(child, props, newCalculatedProps); const name = child.props.name || `${parentName}-${role}-${index}`; const newProps = defaults( { horizontal, height, polar, theme, width, style, name, origin: polar ? origin : undefined, padding: newCalculatedProps.padding, key: `${name}-key-${index}`, standalone: false, }, childProps, ); return React.cloneElement(child, newProps); }); } export const getChildComponents = (props, defaultAxes?) => { let childComponents = React.Children.toArray(props.children); if (childComponents.length === 0) { childComponents.push(defaultAxes.independent, defaultAxes.dependent); } else { const axisComponents = { dependent: Axis.getAxisComponentsWithParent(childComponents, "dependent"), independent: Axis.getAxisComponentsWithParent( childComponents, "independent", ), }; if ( axisComponents.dependent.length === 0 && axisComponents.independent.length === 0 ) { childComponents = props.prependDefaultAxes ? [defaultAxes.independent, defaultAxes.dependent].concat( childComponents, ) : childComponents.concat([ defaultAxes.independent, defaultAxes.dependent, ]); } } return childComponents; }; const getDomain = (props, axis, childComponents) => { const children = childComponents || React.Children.toArray(props.children); const domain = Wrapper.getDomain(props, axis, children); const axisComponent = Axis.getAxisComponent(children, axis); const invertDomain = axisComponent && axisComponent.props && axisComponent.props.invertAxis; return invertDomain ? domain.concat().reverse() : domain; }; const createStringMap = (props, childComponents, allStrings) => { const x = !allStrings.x || allStrings.x.length === 0 ? null : allStrings.x.reduce((memo, string, index) => { memo[string] = index + 1; return memo; }, {}); const y = !allStrings.y || allStrings.y.length === 0 ? null : allStrings.y.reduce((memo, string, index) => { memo[string] = index + 1; return memo; }, {}); return { x, y }; };