<commit_before>import Popover from 'zent-popover';
import capitalize from 'zent-utils/lodash/capitalize';

const { Position } = Popover;

// FIXME: this value couples with CSS style
const ARROW_OFFSET = 17;

const CenterArrowPosition = {
  TopLeft: Position.create((anchorBoundingBox, containerBoundingBox, contentDimension, options) => {
    const { right, left, top } = anchorBoundingBox;
    const middle = (left + right) / 2;
    const x = middle - ARROW_OFFSET;
    const y = top - contentDimension.height - options.cushion;

    return {
      getCSSStyle() {
        return {
          position: 'absolute',
          left: `${Math.round(x)}px`,
          top: `${Math.round(y)}px`
        };
      },

      name: 'position-top-left'
    };
  }),

  TopRight: Position.create((anchorBoundingBox, containerBoundingBox, contentDimension, options) => {
    const { right, left, top } = anchorBoundingBox;
    const middle = (left + right) / 2;
    const x = middle - (contentDimension.width - ARROW_OFFSET);
    const y = top - contentDimension.height - options.cushion;

    return {
      getCSSStyle() {
        return {
          position: 'absolute',
          left: `${Math.round(x)}px`,
          top: `${Math.round(y)}px`
        };
      },

      name: 'position-top-right'
    };
  }),

  BottomLeft: Position.create((anchorBoundingBox, containerBoundingBox, contentDimension, options) => {
    const { left, right, bottom } = anchorBoundingBox;
    const middle = (left + right) / 2;
    const x = middle - ARROW_OFFSET;
    const y = bottom + options.cushion;

    return {
      getCSSStyle() {
        return {
          position: 'absolute',
          left: `${Math.round(x)}px`,
          top: `${Math.round(y)}px`
        };
      },

      name: 'position-bottom-left'
    };
  }),

  BottomRight: Position.create((anchorBoundingBox, containerBoundingBox, contentDimension, options) => {
    const { left, right, bottom } = anchorBoundingBox;
    const middle = (left + right) / 2;
    const x = middle - (contentDimension.width - ARROW_OFFSET);
    const y = bottom + options.cushion;

    return {
      getCSSStyle() {
        return {
          position: 'absolute',
          left: `${Math.round(x)}px`,
          top: `${Math.round(y)}px`
        };
      },

      name: 'position-bottom-right'
    };
  }),

  LeftTop: Position.create((anchorBoundingBox, containerBoundingBox, contentDimension, options) => {
    const x = anchorBoundingBox.left - contentDimension.width - options.cushion;
    const middle = (anchorBoundingBox.top + anchorBoundingBox.bottom) / 2;
    const y = middle - ARROW_OFFSET;

    return {
      getCSSStyle() {
        return {
          position: 'absolute',
          left: `${Math.round(x)}px`,
          top: `${Math.round(y)}px`
        };
      },

      name: 'position-left-top'
    };
  }),

  LeftBottom: Position.create((anchorBoundingBox, containerBoundingBox, contentDimension, options) => {
    const x = anchorBoundingBox.left - contentDimension.width - options.cushion;
    const middle = (anchorBoundingBox.top + anchorBoundingBox.bottom) / 2;
    const y = middle - (contentDimension.height - ARROW_OFFSET);

    return {
      getCSSStyle() {
        return {
          position: 'absolute',
          left: `${Math.round(x)}px`,
          top: `${Math.round(y)}px`
        };
      },

      name: 'position-left-bottom'
    };
  }),

  RightTop: Position.create((anchorBoundingBox, containerBoundingBox, contentDimension, options) => {
    const { right, top, bottom } = anchorBoundingBox;
    const x = right + options.cushion;
    const middle = (top + bottom) / 2;
    const y = middle - ARROW_OFFSET;

    return {
      getCSSStyle() {
        return {
          position: 'absolute',
          left: `${Math.round(x)}px`,
          top: `${Math.round(y)}px`
        };
      },

      name: 'position-right-top'
    };
  }),

  RightBottom: Position.create((anchorBoundingBox, containerBoundingBox, contentDimension, options) => {
    const { right, top, bottom } = anchorBoundingBox;
    const x = right + options.cushion;
    const middle = (top + bottom) / 2;
    const y = middle - (contentDimension.height - ARROW_OFFSET);

    return {
      getCSSStyle() {
        return {
          position: 'absolute',
          left: `${Math.round(x)}px`,
          top: `${Math.round(y)}px`
        };
      },

      name: 'position-right-bottom'
    };
  })
};

export default function getPosition(position, centerArrow) {
  let positionName = position.split('-').map(s => capitalize(s)).join('');
  let pos = Position[positionName];

  // Choose a fallback in case position is invalid
  if (!pos) {
    pos = Position.TopCenter;
    positionName = 'TopCenter';
  }

  // *-center postions are not affected by centerArrow parameter
  if (!centerArrow || /^.+Center$/.test(positionName)) {
    return pos;
  }

  return CenterArrowPosition[positionName];
}<commit_msg>refactor: pull up duplicate code<commit_after>import Popover from 'zent-popover';
import capitalize from 'zent-utils/lodash/capitalize';

const { Position } = Popover;

// FIXME: this value couples with CSS style
const ARROW_OFFSET = 17;

const createPosition = (x, y, side) => {
  return {
    getCSSStyle() {
      return {
        position: 'absolute',
        left: `${Math.round(x)}px`,
        top: `${Math.round(y)}px`
      };
    },

    name: `position-${side}`
  };
};

const CenterArrowPosition = {
  ...(() => {
    const make = (getX, side) => Position.create((anchorBoundingBox, containerBoundingBox, contentDimension, options) => {
      const { right, left, top } = anchorBoundingBox;
      const middle = (left + right) / 2;
      const x = getX(middle, contentDimension);
      const y = top - contentDimension.height - options.cushion;

      return createPosition(x, y, `top-${side}`);
    });

    return {
      TopLeft: make(middle => middle - ARROW_OFFSET, 'left'),
      TopRight: make((middle, contentDimension) => middle - (contentDimension.width - ARROW_OFFSET), 'right')
    };
  })(),

  ...(() => {
    const make = (getX, side) => Position.create((anchorBoundingBox, containerBoundingBox, contentDimension, options) => {
      const { left, right, bottom } = anchorBoundingBox;
      const middle = (left + right) / 2;
      const x = getX(middle, contentDimension);
      const y = bottom + options.cushion;

      return createPosition(x, y, `bottom-${side}`);
    });

    return {
      BottomLeft: make(middle => middle - ARROW_OFFSET, 'left'),
      BottomRight: make((middle, contentDimension) => middle - (contentDimension.width - ARROW_OFFSET), 'right')
    };
  })(),

  ...(() => {
    const make = (getY, side) => Position.create((anchorBoundingBox, containerBoundingBox, contentDimension, options) => {
      const x = anchorBoundingBox.left - contentDimension.width - options.cushion;
      const middle = (anchorBoundingBox.top + anchorBoundingBox.bottom) / 2;
      const y = getY(middle, contentDimension);

      return createPosition(x, y, `left-${side}`);
    });

    return {
      LeftTop: make(middle => middle - ARROW_OFFSET, 'top'),
      LeftBottom: make((middle, contentDimension) => middle - (contentDimension.height - ARROW_OFFSET), 'bottom')
    };
  })(),

  ...(() => {
    const make = (getY, side) => Position.create((anchorBoundingBox, containerBoundingBox, contentDimension, options) => {
      const { right, top, bottom } = anchorBoundingBox;
      const x = right + options.cushion;
      const middle = (top + bottom) / 2;
      const y = getY(middle, contentDimension);

      return createPosition(x, y, `right-${side}`);
    });

    return {
      RightTop: make(middle => middle - ARROW_OFFSET, 'top'),
      RightBottom: make((middle, contentDimension) => middle - (contentDimension.height - ARROW_OFFSET), 'bottom')
    };
  })()
};

export default function getPosition(position, centerArrow) {
  let positionName = position.split('-').map(s => capitalize(s)).join('');
  let pos = Position[positionName];

  // Choose a fallback in case position is invalid
  if (!pos) {
    pos = Position.TopCenter;
    positionName = 'TopCenter';
  }

  // *-center postions are not affected by centerArrow parameter
  if (!centerArrow || /^.+Center$/.test(positionName)) {
    return pos;
  }

  return CenterArrowPosition[positionName];
}
{'fraction_non_alphanumeric': 0.14439526259121904, 'fraction_numerical': 0.0019141045579614787, 'mean_word_length': 2.781094527363184, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 34, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5304264', 'n_tokens_mistral': 2541, 'n_tokens_neox': 2541, 'n_words': 587}