Welcome to mirror list, hosted at ThFree Co, Russian Federation.

arrow.js.flow « modifiers « lib « package « popperjs - github.com/gohugoio/hugo-mod-jslibs-dist.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 03666f5f698245b7cb2e743a5c66a0383ed5b447 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
// @flow
import type { Modifier, ModifierArguments, Padding, Rect } from '../types';
import type { Placement } from '../enums';
import getBasePlacement from '../utils/getBasePlacement';
import getLayoutRect from '../dom-utils/getLayoutRect';
import contains from '../dom-utils/contains';
import getOffsetParent from '../dom-utils/getOffsetParent';
import getMainAxisFromPlacement from '../utils/getMainAxisFromPlacement';
import { within } from '../utils/within';
import mergePaddingObject from '../utils/mergePaddingObject';
import expandToHashMap from '../utils/expandToHashMap';
import { left, right, basePlacements, top, bottom } from '../enums';
import { isHTMLElement } from '../dom-utils/instanceOf';

// eslint-disable-next-line import/no-unused-modules
export type Options = {
  element: HTMLElement | string | null,
  padding:
    | Padding
    | (({|
        popper: Rect,
        reference: Rect,
        placement: Placement,
      |}) => Padding),
};

const toPaddingObject = (padding, state) => {
  padding =
    typeof padding === 'function'
      ? padding({ ...state.rects, placement: state.placement })
      : padding;

  return mergePaddingObject(
    typeof padding !== 'number'
      ? padding
      : expandToHashMap(padding, basePlacements)
  );
};

function arrow({ state, name, options }: ModifierArguments<Options>) {
  const arrowElement = state.elements.arrow;
  const popperOffsets = state.modifiersData.popperOffsets;
  const basePlacement = getBasePlacement(state.placement);
  const axis = getMainAxisFromPlacement(basePlacement);
  const isVertical = [left, right].indexOf(basePlacement) >= 0;
  const len = isVertical ? 'height' : 'width';

  if (!arrowElement || !popperOffsets) {
    return;
  }

  const paddingObject = toPaddingObject(options.padding, state);
  const arrowRect = getLayoutRect(arrowElement);
  const minProp = axis === 'y' ? top : left;
  const maxProp = axis === 'y' ? bottom : right;

  const endDiff =
    state.rects.reference[len] +
    state.rects.reference[axis] -
    popperOffsets[axis] -
    state.rects.popper[len];
  const startDiff = popperOffsets[axis] - state.rects.reference[axis];

  const arrowOffsetParent = getOffsetParent(arrowElement);
  const clientSize = arrowOffsetParent
    ? axis === 'y'
      ? arrowOffsetParent.clientHeight || 0
      : arrowOffsetParent.clientWidth || 0
    : 0;

  const centerToReference = endDiff / 2 - startDiff / 2;

  // Make sure the arrow doesn't overflow the popper if the center point is
  // outside of the popper bounds
  const min = paddingObject[minProp];
  const max = clientSize - arrowRect[len] - paddingObject[maxProp];
  const center = clientSize / 2 - arrowRect[len] / 2 + centerToReference;
  const offset = within(min, center, max);

  // Prevents breaking syntax highlighting...
  const axisProp: string = axis;
  state.modifiersData[name] = {
    [axisProp]: offset,
    centerOffset: offset - center,
  };
}

function effect({ state, options }: ModifierArguments<Options>) {
  let { element: arrowElement = '[data-popper-arrow]' } = options;

  if (arrowElement == null) {
    return;
  }

  // CSS selector
  if (typeof arrowElement === 'string') {
    arrowElement = state.elements.popper.querySelector(arrowElement);

    if (!arrowElement) {
      return;
    }
  }

  if (false) {
    if (!isHTMLElement(arrowElement)) {
      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(' ')
      );
    }
  }

  if (!contains(state.elements.popper, arrowElement)) {
    if (false) {
      console.error(
        [
          'Popper: "arrow" modifier\'s `element` must be a child of the popper',
          'element.',
        ].join(' ')
      );
    }

    return;
  }

  state.elements.arrow = arrowElement;
}

// eslint-disable-next-line import/no-unused-modules
export type ArrowModifier = Modifier<'arrow', Options>;
export default ({
  name: 'arrow',
  enabled: true,
  phase: 'main',
  fn: arrow,
  effect,
  requires: ['popperOffsets'],
  requiresIfExists: ['preventOverflow'],
}: ArrowModifier);