source: imaps-frontend/node_modules/@popperjs/core/lib/modifiers/flip.js.flow

main
Last change on this file was 79a0317, checked in by stefan toskovski <stefantoska84@…>, 4 days ago

F4 Finalna Verzija

  • Property mode set to 100644
File size: 4.8 KB
Line 
1// @flow
2import type { Placement, Boundary, RootBoundary } from '../enums';
3import type { ModifierArguments, Modifier, Padding } from '../types';
4import getOppositePlacement from '../utils/getOppositePlacement';
5import getBasePlacement from '../utils/getBasePlacement';
6import getOppositeVariationPlacement from '../utils/getOppositeVariationPlacement';
7import detectOverflow from '../utils/detectOverflow';
8import computeAutoPlacement from '../utils/computeAutoPlacement';
9import { bottom, top, start, right, left, auto } from '../enums';
10import getVariation from '../utils/getVariation';
11
12// eslint-disable-next-line import/no-unused-modules
13export type Options = {
14 mainAxis: boolean,
15 altAxis: boolean,
16 fallbackPlacements: Array<Placement>,
17 padding: Padding,
18 boundary: Boundary,
19 rootBoundary: RootBoundary,
20 altBoundary: boolean,
21 flipVariations: boolean,
22 allowedAutoPlacements: Array<Placement>,
23};
24
25function getExpandedFallbackPlacements(placement: Placement): Array<Placement> {
26 if (getBasePlacement(placement) === auto) {
27 return [];
28 }
29
30 const oppositePlacement = getOppositePlacement(placement);
31
32 return [
33 getOppositeVariationPlacement(placement),
34 oppositePlacement,
35 getOppositeVariationPlacement(oppositePlacement),
36 ];
37}
38
39function flip({ state, options, name }: ModifierArguments<Options>) {
40 if (state.modifiersData[name]._skip) {
41 return;
42 }
43
44 const {
45 mainAxis: checkMainAxis = true,
46 altAxis: checkAltAxis = true,
47 fallbackPlacements: specifiedFallbackPlacements,
48 padding,
49 boundary,
50 rootBoundary,
51 altBoundary,
52 flipVariations = true,
53 allowedAutoPlacements,
54 } = options;
55
56 const preferredPlacement = state.options.placement;
57 const basePlacement = getBasePlacement(preferredPlacement);
58 const isBasePlacement = basePlacement === preferredPlacement;
59
60 const fallbackPlacements =
61 specifiedFallbackPlacements ||
62 (isBasePlacement || !flipVariations
63 ? [getOppositePlacement(preferredPlacement)]
64 : getExpandedFallbackPlacements(preferredPlacement));
65
66 const placements = [preferredPlacement, ...fallbackPlacements].reduce(
67 (acc, placement) => {
68 return acc.concat(
69 getBasePlacement(placement) === auto
70 ? computeAutoPlacement(state, {
71 placement,
72 boundary,
73 rootBoundary,
74 padding,
75 flipVariations,
76 allowedAutoPlacements,
77 })
78 : placement
79 );
80 },
81 []
82 );
83
84 const referenceRect = state.rects.reference;
85 const popperRect = state.rects.popper;
86
87 const checksMap = new Map();
88 let makeFallbackChecks = true;
89 let firstFittingPlacement = placements[0];
90
91 for (let i = 0; i < placements.length; i++) {
92 const placement = placements[i];
93 const basePlacement = getBasePlacement(placement);
94 const isStartVariation = getVariation(placement) === start;
95 const isVertical = [top, bottom].indexOf(basePlacement) >= 0;
96 const len = isVertical ? 'width' : 'height';
97
98 const overflow = detectOverflow(state, {
99 placement,
100 boundary,
101 rootBoundary,
102 altBoundary,
103 padding,
104 });
105
106 let mainVariationSide: any = isVertical
107 ? isStartVariation
108 ? right
109 : left
110 : isStartVariation
111 ? bottom
112 : top;
113
114 if (referenceRect[len] > popperRect[len]) {
115 mainVariationSide = getOppositePlacement(mainVariationSide);
116 }
117
118 const altVariationSide: any = getOppositePlacement(mainVariationSide);
119
120 const checks = [];
121
122 if (checkMainAxis) {
123 checks.push(overflow[basePlacement] <= 0);
124 }
125
126 if (checkAltAxis) {
127 checks.push(
128 overflow[mainVariationSide] <= 0,
129 overflow[altVariationSide] <= 0
130 );
131 }
132
133 if (checks.every((check) => check)) {
134 firstFittingPlacement = placement;
135 makeFallbackChecks = false;
136 break;
137 }
138
139 checksMap.set(placement, checks);
140 }
141
142 if (makeFallbackChecks) {
143 // `2` may be desired in some cases – research later
144 const numberOfChecks = flipVariations ? 3 : 1;
145
146 for (let i = numberOfChecks; i > 0; i--) {
147 const fittingPlacement = placements.find((placement) => {
148 const checks = checksMap.get(placement);
149 if (checks) {
150 return checks.slice(0, i).every((check) => check);
151 }
152 });
153
154 if (fittingPlacement) {
155 firstFittingPlacement = fittingPlacement;
156 break;
157 }
158 }
159 }
160
161 if (state.placement !== firstFittingPlacement) {
162 state.modifiersData[name]._skip = true;
163 state.placement = firstFittingPlacement;
164 state.reset = true;
165 }
166}
167
168// eslint-disable-next-line import/no-unused-modules
169export type FlipModifier = Modifier<'flip', Options>;
170export default ({
171 name: 'flip',
172 enabled: true,
173 phase: 'main',
174 fn: flip,
175 requiresIfExists: ['offset'],
176 data: { _skip: false },
177}: FlipModifier);
Note: See TracBrowser for help on using the repository browser.