source: imaps-frontend/node_modules/@popperjs/core/lib/modifiers/computeStyles.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: 5.8 KB
Line 
1// @flow
2import type {
3 PositioningStrategy,
4 Offsets,
5 Modifier,
6 ModifierArguments,
7 Rect,
8 Window,
9} from '../types';
10import {
11 type BasePlacement,
12 type Variation,
13 top,
14 left,
15 right,
16 bottom,
17 end,
18} from '../enums';
19import getOffsetParent from '../dom-utils/getOffsetParent';
20import getWindow from '../dom-utils/getWindow';
21import getDocumentElement from '../dom-utils/getDocumentElement';
22import getComputedStyle from '../dom-utils/getComputedStyle';
23import getBasePlacement from '../utils/getBasePlacement';
24import getVariation from '../utils/getVariation';
25import { round } from '../utils/math';
26
27// eslint-disable-next-line import/no-unused-modules
28export type RoundOffsets = (
29 offsets: $Shape<{ x: number, y: number, centerOffset: number }>
30) => Offsets;
31
32// eslint-disable-next-line import/no-unused-modules
33export type Options = {
34 gpuAcceleration: boolean,
35 adaptive: boolean,
36 roundOffsets?: boolean | RoundOffsets,
37};
38
39const unsetSides = {
40 top: 'auto',
41 right: 'auto',
42 bottom: 'auto',
43 left: 'auto',
44};
45
46// Round the offsets to the nearest suitable subpixel based on the DPR.
47// Zooming can change the DPR, but it seems to report a value that will
48// cleanly divide the values into the appropriate subpixels.
49function roundOffsetsByDPR({ x, y }, win: Window): Offsets {
50 const dpr = win.devicePixelRatio || 1;
51
52 return {
53 x: round(x * dpr) / dpr || 0,
54 y: round(y * dpr) / dpr || 0,
55 };
56}
57
58export function mapToStyles({
59 popper,
60 popperRect,
61 placement,
62 variation,
63 offsets,
64 position,
65 gpuAcceleration,
66 adaptive,
67 roundOffsets,
68 isFixed,
69}: {
70 popper: HTMLElement,
71 popperRect: Rect,
72 placement: BasePlacement,
73 variation: ?Variation,
74 offsets: $Shape<{ x: number, y: number, centerOffset: number }>,
75 position: PositioningStrategy,
76 gpuAcceleration: boolean,
77 adaptive: boolean,
78 roundOffsets: boolean | RoundOffsets,
79 isFixed: boolean,
80}) {
81 let { x = 0, y = 0 } = offsets;
82
83 ({ x, y } =
84 typeof roundOffsets === 'function' ? roundOffsets({ x, y }) : { x, y });
85
86 const hasX = offsets.hasOwnProperty('x');
87 const hasY = offsets.hasOwnProperty('y');
88
89 let sideX: string = left;
90 let sideY: string = top;
91
92 const win: Window = window;
93
94 if (adaptive) {
95 let offsetParent = getOffsetParent(popper);
96 let heightProp = 'clientHeight';
97 let widthProp = 'clientWidth';
98
99 if (offsetParent === getWindow(popper)) {
100 offsetParent = getDocumentElement(popper);
101
102 if (
103 getComputedStyle(offsetParent).position !== 'static' &&
104 position === 'absolute'
105 ) {
106 heightProp = 'scrollHeight';
107 widthProp = 'scrollWidth';
108 }
109 }
110
111 // $FlowFixMe[incompatible-cast]: force type refinement, we compare offsetParent with window above, but Flow doesn't detect it
112 offsetParent = (offsetParent: Element);
113
114 if (
115 placement === top ||
116 ((placement === left || placement === right) && variation === end)
117 ) {
118 sideY = bottom;
119 const offsetY =
120 isFixed && offsetParent === win && win.visualViewport
121 ? win.visualViewport.height
122 : // $FlowFixMe[prop-missing]
123 offsetParent[heightProp];
124 y -= offsetY - popperRect.height;
125 y *= gpuAcceleration ? 1 : -1;
126 }
127
128 if (
129 placement === left ||
130 ((placement === top || placement === bottom) && variation === end)
131 ) {
132 sideX = right;
133 const offsetX =
134 isFixed && offsetParent === win && win.visualViewport
135 ? win.visualViewport.width
136 : // $FlowFixMe[prop-missing]
137 offsetParent[widthProp];
138 x -= offsetX - popperRect.width;
139 x *= gpuAcceleration ? 1 : -1;
140 }
141 }
142
143 const commonStyles = {
144 position,
145 ...(adaptive && unsetSides),
146 };
147
148 ({ x, y } =
149 roundOffsets === true
150 ? roundOffsetsByDPR({ x, y }, getWindow(popper))
151 : { x, y });
152
153 if (gpuAcceleration) {
154 return {
155 ...commonStyles,
156 [sideY]: hasY ? '0' : '',
157 [sideX]: hasX ? '0' : '',
158 // Layer acceleration can disable subpixel rendering which causes slightly
159 // blurry text on low PPI displays, so we want to use 2D transforms
160 // instead
161 transform:
162 (win.devicePixelRatio || 1) <= 1
163 ? `translate(${x}px, ${y}px)`
164 : `translate3d(${x}px, ${y}px, 0)`,
165 };
166 }
167
168 return {
169 ...commonStyles,
170 [sideY]: hasY ? `${y}px` : '',
171 [sideX]: hasX ? `${x}px` : '',
172 transform: '',
173 };
174}
175
176function computeStyles({ state, options }: ModifierArguments<Options>) {
177 const {
178 gpuAcceleration = true,
179 adaptive = true,
180 // defaults to use builtin `roundOffsetsByDPR`
181 roundOffsets = true,
182 } = options;
183
184 const commonStyles = {
185 placement: getBasePlacement(state.placement),
186 variation: getVariation(state.placement),
187 popper: state.elements.popper,
188 popperRect: state.rects.popper,
189 gpuAcceleration,
190 isFixed: state.options.strategy === 'fixed',
191 };
192
193 if (state.modifiersData.popperOffsets != null) {
194 state.styles.popper = {
195 ...state.styles.popper,
196 ...mapToStyles({
197 ...commonStyles,
198 offsets: state.modifiersData.popperOffsets,
199 position: state.options.strategy,
200 adaptive,
201 roundOffsets,
202 }),
203 };
204 }
205
206 if (state.modifiersData.arrow != null) {
207 state.styles.arrow = {
208 ...state.styles.arrow,
209 ...mapToStyles({
210 ...commonStyles,
211 offsets: state.modifiersData.arrow,
212 position: 'absolute',
213 adaptive: false,
214 roundOffsets,
215 }),
216 };
217 }
218
219 state.attributes.popper = {
220 ...state.attributes.popper,
221 'data-popper-placement': state.placement,
222 };
223}
224
225// eslint-disable-next-line import/no-unused-modules
226export type ComputeStylesModifier = Modifier<'computeStyles', Options>;
227export default ({
228 name: 'computeStyles',
229 enabled: true,
230 phase: 'beforeWrite',
231 fn: computeStyles,
232 data: {},
233}: ComputeStylesModifier);
Note: See TracBrowser for help on using the repository browser.