diff options
author | Bjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com> | 2022-02-13 18:11:28 +0300 |
---|---|---|
committer | Bjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com> | 2022-02-13 18:11:28 +0300 |
commit | 02b6116825341c309c1ceef951f4ec3566728397 (patch) | |
tree | ab5d3625431db2f3076c3dded6f79b37af8cacf3 /popperjs/package/lib/modifiers/arrow.js.flow | |
parent | 7c4d83e324c73bb3dc1209ddefef733c5144424e (diff) |
Add popperjspopperjs/v2.21100.20000
Diffstat (limited to 'popperjs/package/lib/modifiers/arrow.js.flow')
-rw-r--r-- | popperjs/package/lib/modifiers/arrow.js.flow | 142 |
1 files changed, 142 insertions, 0 deletions
diff --git a/popperjs/package/lib/modifiers/arrow.js.flow b/popperjs/package/lib/modifiers/arrow.js.flow new file mode 100644 index 0000000..03666f5 --- /dev/null +++ b/popperjs/package/lib/modifiers/arrow.js.flow @@ -0,0 +1,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); |