1 | // @flow
|
---|
2 | import type {
|
---|
3 | ModifierArguments,
|
---|
4 | Modifier,
|
---|
5 | Rect,
|
---|
6 | SideObject,
|
---|
7 | Offsets,
|
---|
8 | } from '../types';
|
---|
9 | import { top, bottom, left, right } from '../enums';
|
---|
10 | import detectOverflow from '../utils/detectOverflow';
|
---|
11 |
|
---|
12 | function getSideOffsets(
|
---|
13 | overflow: SideObject,
|
---|
14 | rect: Rect,
|
---|
15 | preventedOffsets: Offsets = { x: 0, y: 0 }
|
---|
16 | ): SideObject {
|
---|
17 | return {
|
---|
18 | top: overflow.top - rect.height - preventedOffsets.y,
|
---|
19 | right: overflow.right - rect.width + preventedOffsets.x,
|
---|
20 | bottom: overflow.bottom - rect.height + preventedOffsets.y,
|
---|
21 | left: overflow.left - rect.width - preventedOffsets.x,
|
---|
22 | };
|
---|
23 | }
|
---|
24 |
|
---|
25 | function isAnySideFullyClipped(overflow: SideObject): boolean {
|
---|
26 | return [top, right, bottom, left].some((side) => overflow[side] >= 0);
|
---|
27 | }
|
---|
28 |
|
---|
29 | function hide({ state, name }: ModifierArguments<{||}>) {
|
---|
30 | const referenceRect = state.rects.reference;
|
---|
31 | const popperRect = state.rects.popper;
|
---|
32 | const preventedOffsets = state.modifiersData.preventOverflow;
|
---|
33 |
|
---|
34 | const referenceOverflow = detectOverflow(state, {
|
---|
35 | elementContext: 'reference',
|
---|
36 | });
|
---|
37 | const popperAltOverflow = detectOverflow(state, {
|
---|
38 | altBoundary: true,
|
---|
39 | });
|
---|
40 |
|
---|
41 | const referenceClippingOffsets = getSideOffsets(
|
---|
42 | referenceOverflow,
|
---|
43 | referenceRect
|
---|
44 | );
|
---|
45 | const popperEscapeOffsets = getSideOffsets(
|
---|
46 | popperAltOverflow,
|
---|
47 | popperRect,
|
---|
48 | preventedOffsets
|
---|
49 | );
|
---|
50 |
|
---|
51 | const isReferenceHidden = isAnySideFullyClipped(referenceClippingOffsets);
|
---|
52 | const hasPopperEscaped = isAnySideFullyClipped(popperEscapeOffsets);
|
---|
53 |
|
---|
54 | state.modifiersData[name] = {
|
---|
55 | referenceClippingOffsets,
|
---|
56 | popperEscapeOffsets,
|
---|
57 | isReferenceHidden,
|
---|
58 | hasPopperEscaped,
|
---|
59 | };
|
---|
60 |
|
---|
61 | state.attributes.popper = {
|
---|
62 | ...state.attributes.popper,
|
---|
63 | 'data-popper-reference-hidden': isReferenceHidden,
|
---|
64 | 'data-popper-escaped': hasPopperEscaped,
|
---|
65 | };
|
---|
66 | }
|
---|
67 |
|
---|
68 | // eslint-disable-next-line import/no-unused-modules
|
---|
69 | export type HideModifier = Modifier<'hide', {||}>;
|
---|
70 | export default ({
|
---|
71 | name: 'hide',
|
---|
72 | enabled: true,
|
---|
73 | phase: 'main',
|
---|
74 | requiresIfExists: ['preventOverflow'],
|
---|
75 | fn: hide,
|
---|
76 | }: HideModifier);
|
---|