-
Notifications
You must be signed in to change notification settings - Fork 13.5k
/
Copy pathios.enter.ts
129 lines (111 loc) · 4.1 KB
/
ios.enter.ts
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
import { createAnimation } from '@utils/animation/animation';
import { getElementRoot } from '@utils/helpers';
import type { Animation } from '../../../interface';
import {
calculateWindowAdjustment,
getArrowDimensions,
getPopoverDimensions,
getPopoverPosition,
shouldShowArrow,
} from '../utils';
const POPOVER_IOS_BODY_PADDING = 5;
/**
* iOS Popover Enter Animation
*/
// TODO(FW-2832): types
export const iosEnterAnimation = (baseEl: HTMLElement, opts?: any): Animation => {
const { event: ev, size, trigger, reference, side, align } = opts;
const doc = baseEl.ownerDocument as any;
const isRTL = doc.dir === 'rtl';
const bodyWidth = doc.defaultView.innerWidth;
const bodyHeight = doc.defaultView.innerHeight;
const root = getElementRoot(baseEl);
const contentEl = root.querySelector('.popover-content') as HTMLElement;
const arrowEl = root.querySelector('.popover-arrow') as HTMLElement | null;
const referenceSizeEl = trigger || ev?.detail?.ionShadowTarget || ev?.target;
const { contentWidth, contentHeight } = getPopoverDimensions(size, contentEl, referenceSizeEl);
const { arrowWidth, arrowHeight } = getArrowDimensions(arrowEl);
const defaultPosition = {
top: bodyHeight / 2 - contentHeight / 2,
left: bodyWidth / 2 - contentWidth / 2,
originX: isRTL ? 'right' : 'left',
originY: 'top',
};
const results = getPopoverPosition(
isRTL,
contentWidth,
contentHeight,
arrowWidth,
arrowHeight,
reference,
side,
align,
defaultPosition,
trigger,
ev
);
const padding = size === 'cover' ? 0 : POPOVER_IOS_BODY_PADDING;
const { originX, originY, top, left, bottom, arrowTop, arrowLeft, addPopoverBottomClass } = calculateWindowAdjustment(
side,
results.top,
results.left,
padding,
bodyWidth,
bodyHeight,
contentWidth,
contentHeight,
results.originX,
results.originY,
results.referenceCoordinates,
results.arrowTop,
results.arrowLeft,
arrowHeight
);
const baseAnimation = createAnimation();
const backdropAnimation = createAnimation();
const contentAnimation = createAnimation();
backdropAnimation
.addElement(root.querySelector('ion-backdrop')!)
.fromTo('opacity', 0.01, 'var(--backdrop-opacity)')
.beforeStyles({
'pointer-events': 'none',
})
.afterClearStyles(['pointer-events']);
// In Chromium, if the wrapper animates, the backdrop filter doesn't work.
// The Chromium team stated that this behavior is expected and not a bug. The element animating opacity creates a backdrop root for the backdrop-filter.
// To get around this, instead of animating the wrapper, animate both the arrow and content.
// https://bugs.chromium.org/p/chromium/issues/detail?id=1148826
contentAnimation
.addElement(root.querySelector('.popover-arrow')!)
.addElement(root.querySelector('.popover-content')!)
.fromTo('opacity', 0.01, 1);
// TODO(FW-4376) Ensure that arrow also blurs when translucent
return baseAnimation
.easing('ease')
.duration(100)
.beforeAddWrite(() => {
if (size === 'cover') {
baseEl.style.setProperty('--width', `${contentWidth}px`);
}
if (addPopoverBottomClass) {
baseEl.classList.add('popover-bottom');
}
if (bottom !== undefined) {
contentEl.style.setProperty('bottom', `${bottom}px`);
}
contentEl.style.setProperty('top', `calc(${top}px + var(--offset-y, 0))`);
contentEl.style.setProperty('left', `calc(${left}px + var(--offset-x, 0))`);
contentEl.style.setProperty('transform-origin', `${originY} ${originX}`);
if (arrowEl !== null) {
const didAdjustBounds = results.top !== top || results.left !== left;
const showArrow = shouldShowArrow(side, didAdjustBounds, ev, trigger);
if (showArrow) {
arrowEl.style.setProperty('top', `calc(${arrowTop}px + var(--offset-y, 0))`);
arrowEl.style.setProperty('left', `calc(${arrowLeft}px + var(--offset-x, 0))`);
} else {
arrowEl.style.setProperty('display', 'none');
}
}
})
.addAnimation([backdropAnimation, contentAnimation]);
};