arrow.js 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. import getBasePlacement from "../utils/getBasePlacement.js";
  2. import getLayoutRect from "../dom-utils/getLayoutRect.js";
  3. import contains from "../dom-utils/contains.js";
  4. import getOffsetParent from "../dom-utils/getOffsetParent.js";
  5. import getMainAxisFromPlacement from "../utils/getMainAxisFromPlacement.js";
  6. import { within } from "../utils/within.js";
  7. import mergePaddingObject from "../utils/mergePaddingObject.js";
  8. import expandToHashMap from "../utils/expandToHashMap.js";
  9. import { left, right, basePlacements, top, bottom } from "../enums.js";
  10. import { isHTMLElement } from "../dom-utils/instanceOf.js"; // eslint-disable-next-line import/no-unused-modules
  11. var toPaddingObject = function toPaddingObject(padding, state) {
  12. padding = typeof padding === 'function' ? padding(Object.assign({}, state.rects, {
  13. placement: state.placement
  14. })) : padding;
  15. return mergePaddingObject(typeof padding !== 'number' ? padding : expandToHashMap(padding, basePlacements));
  16. };
  17. function arrow(_ref) {
  18. var _state$modifiersData$;
  19. var state = _ref.state,
  20. name = _ref.name,
  21. options = _ref.options;
  22. var arrowElement = state.elements.arrow;
  23. var popperOffsets = state.modifiersData.popperOffsets;
  24. var basePlacement = getBasePlacement(state.placement);
  25. var axis = getMainAxisFromPlacement(basePlacement);
  26. var isVertical = [left, right].indexOf(basePlacement) >= 0;
  27. var len = isVertical ? 'height' : 'width';
  28. if (!arrowElement || !popperOffsets) {
  29. return;
  30. }
  31. var paddingObject = toPaddingObject(options.padding, state);
  32. var arrowRect = getLayoutRect(arrowElement);
  33. var minProp = axis === 'y' ? top : left;
  34. var maxProp = axis === 'y' ? bottom : right;
  35. var endDiff = state.rects.reference[len] + state.rects.reference[axis] - popperOffsets[axis] - state.rects.popper[len];
  36. var startDiff = popperOffsets[axis] - state.rects.reference[axis];
  37. var arrowOffsetParent = getOffsetParent(arrowElement);
  38. var clientSize = arrowOffsetParent ? axis === 'y' ? arrowOffsetParent.clientHeight || 0 : arrowOffsetParent.clientWidth || 0 : 0;
  39. var centerToReference = endDiff / 2 - startDiff / 2; // Make sure the arrow doesn't overflow the popper if the center point is
  40. // outside of the popper bounds
  41. var min = paddingObject[minProp];
  42. var max = clientSize - arrowRect[len] - paddingObject[maxProp];
  43. var center = clientSize / 2 - arrowRect[len] / 2 + centerToReference;
  44. var offset = within(min, center, max); // Prevents breaking syntax highlighting...
  45. var axisProp = axis;
  46. state.modifiersData[name] = (_state$modifiersData$ = {}, _state$modifiersData$[axisProp] = offset, _state$modifiersData$.centerOffset = offset - center, _state$modifiersData$);
  47. }
  48. function effect(_ref2) {
  49. var state = _ref2.state,
  50. options = _ref2.options;
  51. var _options$element = options.element,
  52. arrowElement = _options$element === void 0 ? '[data-popper-arrow]' : _options$element;
  53. if (arrowElement == null) {
  54. return;
  55. } // CSS selector
  56. if (typeof arrowElement === 'string') {
  57. arrowElement = state.elements.popper.querySelector(arrowElement);
  58. if (!arrowElement) {
  59. return;
  60. }
  61. }
  62. if (process.env.NODE_ENV !== "production") {
  63. if (!isHTMLElement(arrowElement)) {
  64. console.error(['Popper: "arrow" element must be an HTMLElement (not an SVGElement).', 'To use an SVG arrow, wrap it in an HTMLElement that will be used as', 'the arrow.'].join(' '));
  65. }
  66. }
  67. if (!contains(state.elements.popper, arrowElement)) {
  68. if (process.env.NODE_ENV !== "production") {
  69. console.error(['Popper: "arrow" modifier\'s `element` must be a child of the popper', 'element.'].join(' '));
  70. }
  71. return;
  72. }
  73. state.elements.arrow = arrowElement;
  74. } // eslint-disable-next-line import/no-unused-modules
  75. export default {
  76. name: 'arrow',
  77. enabled: true,
  78. phase: 'main',
  79. fn: arrow,
  80. effect: effect,
  81. requires: ['popperOffsets'],
  82. requiresIfExists: ['preventOverflow']
  83. };