text: import { Selection, Data, Helpers } from "victory-core";
  import { assign, defaults, throttle, isFunction, includes } from "lodash";
  import React from "react";
  
  const SelectionHelpers = {
    getDatasets(props) {
      if (props.data) {
        return [{ data: props.data }];
      }
  
      const getData = (childProps) => {
        const data = Data.getData(childProps);
        return Array.isArray(data) && data.length > 0 ? data : undefined;
      };
  
      const iteratee = (child, childName, parent) => {
        const blacklist = props.selectionBlacklist || [];
        if (!Data.isDataComponent(child) || includes(blacklist, childName)) {
          return null;
        } else if (child.type && isFunction(child.type.getData)) {
          child = parent ? React.cloneElement(child, parent.props) : child;
          const childData = child.props && child.type.getData(child.props);
          return childData ? { childName, data: childData } : null;
        } else {
          const childData = getData(child.props);
          return childData ? { childName, data: childData } : null;
        }
      };
      return Helpers.reduceChildren(React.Children.toArray(props.children), iteratee, props);
    },
  
    filterDatasets(props, datasets, bounds) {
      const filtered = datasets.reduce((memo, dataset) => {
        const selectedData = this.getSelectedData(props, dataset.data, bounds);
        memo = selectedData
          ? memo.concat({
              childName: dataset.childName,
              eventKey: selectedData.eventKey,
              data: selectedData.data
            })
          : memo;
        return memo;
      }, []);
      return filtered.length ? filtered : null;
    },
  
    getPoint(props, point) {
      if (!props.horizontal) {
        return point;
      }
      return {
        _x: point._y,
        _y: point._x,
        _x1: point._y1,
        _y1: point._x1,
        _x0: point._y0,
        _y0: point._x0
      };
    },
  
    getSelectedData(props, dataset) {
      const { x1, y1, x2, y2 } = props;
      const withinBounds = (d) => {
        const point = this.getPoint(props, d);
        const scaledPoint = Helpers.scalePoint(props, point);
        return (
          scaledPoint.x >= Math.min(x1, x2) &&
          scaledPoint.x <= Math.max(x1, x2) &&
          scaledPoint.y >= Math.min(y1, y2) &&
          scaledPoint.y <= Math.max(y1, y2)
        );
      };
      const eventKey = [];
      const data = [];
      let count = 0;
      for (let index = 0, len = dataset.length; index < len; index++) {
        const datum = dataset[index];
        if (withinBounds(datum)) {
          data[count] = datum;
          eventKey[count] = datum.eventKey === undefined ? index : datum.eventKey;
          count++;
        }
      }
      return count > 0 ? { eventKey, data } : null;
    },
  
    // eslint-disable-next-line complexity, max-statements
    onMouseDown(evt, targetProps) {
      evt.preventDefault();
      const { activateSelectedData, allowSelection, polar, selectedData } = targetProps;
      if (!allowSelection) {
        return {};
      }
      const dimension = targetProps.selectionDimension;
      const parentSVG = targetProps.parentSVG || Selection.getParentSVG(evt);
      const { x, y } = Selection.getSVGEventCoordinates(evt, parentSVG);
      const x1 = polar || dimension !== "y" ? x : Selection.getDomainCoordinates(targetProps).x[0];
      const y1 = polar || dimension !== "x" ? y : Selection.getDomainCoordinates(targetProps).y[0];
      const x2 = polar || dimension !== "y" ? x : Selection.getDomainCoordinates(targetProps).x[1];
      const y2 = polar || dimension !== "x" ? y : Selection.getDomainCoordinates(targetProps).y[1];
  
      const mutatedProps = { x1, y1, select: true, x2, y2, parentSVG };
      if (selectedData && isFunction(targetProps.onSelectionCleared)) {
        targetProps.onSelectionCleared(defaults({}, mutatedProps, targetProps));
      }
      const parentMutation = [{ target: "parent", mutation: () => mutatedProps }];
      const dataMutation =
        selectedData && activateSelectedData
          ? selectedData.map((d) => {
              return {
                childName: d.childName,
                eventKey: d.eventKey,
                target: "data",
                mutation: () => null
              };
            })
          : [];
  
      return parentMutation.concat(...dataMutation);
    },
  
    onMouseMove(evt, targetProps) {
      const { allowSelection, select, polar } = targetProps;
      const dimension = targetProps.selectionDimension;
      if (!allowSelection || !select) {
        return null;
      } else {
        const parentSVG = targetProps.parentSVG || Selection.getParentSVG(evt);
        const { x, y } = Selection.getSVGEventCoordinates(evt, parentSVG);
        const x2 = polar || dimension !== "y" ? x : Selection.getDomainCoordinates(targetProps).x[1];
        const y2 = polar || dimension !== "x" ? y : Selection.getDomainCoordinates(targetProps).y[1];
        return {
          target: "parent",
          mutation: () => {
            return { x2, y2, parentSVG };
          }
        };
      }
    },
  
    onMouseUp(evt, targetProps) {
      const { activateSelectedData, allowSelection, x2, y2 } = targetProps;
      if (!allowSelection) {
        return null;
      }
      if (!x2 || !y2) {
        return [
          {
            target: "parent",
            mutation: () => {
              return { select: false, x1: null, x2: null, y1: null, y2: null };
            }
          }
        ];
      }
      const datasets = this.getDatasets(targetProps);
      const bounds = Selection.getBounds(targetProps);
      const selectedData = this.filterDatasets(targetProps, datasets, bounds);
      const mutatedProps = {
        selectedData,
        datasets,
        select: false,
        x1: null,
        x2: null,
        y1: null,
        y2: null
      };
      const callbackMutation =
        selectedData && isFunction(targetProps.onSelection)
          ? targetProps.onSelection(selectedData, bounds, defaults({}, mutatedProps, targetProps))
          : {};
      const parentMutation = [
        {
          target: "parent",
          mutation: () => mutatedProps
        }
      ];
  
      const dataMutation =
        selectedData && activateSelectedData
          ? selectedData.map((d) => {
              return {
                childName: d.childName,
                eventKey: d.eventKey,
                target: "data",
                mutation: () => {
                  return assign({ active: true }, callbackMutation);
                }
              };
            })
          : [];
  
      return parentMutation.concat(dataMutation);
    }
  };
  
  export default {
    ...SelectionHelpers,
    onMouseDown: SelectionHelpers.onMouseDown.bind(SelectionHelpers),
    onMouseUp: SelectionHelpers.onMouseUp.bind(SelectionHelpers),
    onMouseMove: throttle(
      SelectionHelpers.onMouseMove.bind(SelectionHelpers),
      16, // eslint-disable-line no-magic-numbers
      { leading: true, trailing: false }
    )
  };
  