-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathmodal-manager-host-bridge.ts
82 lines (72 loc) · 2.73 KB
/
modal-manager-host-bridge.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
import { throttle } from 'throttle-debounce';
import { ModalManagerHostBridgeInterface } from './modal-manager-host-bridge-interface';
import { ModalManagerInterface } from './modal-manager-interface';
import { ModalManagerMode } from './modal-manager-mode';
/**
* The `ModalManagerHostBridge` is a bridge between the `ModalManager` and the
* host that sets up environment-specific changes when the modal opens and closes.
*
* For instance, when the modal opens, this adds a class to the `<body>` tag for styling
* and adds a `resize` listener to fix a Safari shadow root issue.
*
* Consumers can create their own `ModalManagerHostBridgeInterface` classes and pass
* them into the `ModalManager` if this one does not work for their environment.
*
* @export
* @class ModalManagerHostBridge
* @implements {ModalManagerHostBridgeInterface}
*/
export class ModalManagerHostBridge implements ModalManagerHostBridgeInterface {
private modalManager: ModalManagerInterface;
constructor(modalManager: ModalManagerInterface) {
this.modalManager = modalManager;
}
/**
* Handle the mode change
*
* @private
* @memberof ModalManager
*/
handleModeChange(mode: ModalManagerMode): void {
switch (mode) {
case ModalManagerMode.Open:
this.startResizeListener();
this.stopDocumentScroll();
break;
case ModalManagerMode.Closed:
this.stopResizeListener();
this.resumeDocumentScroll();
break;
}
}
private windowResizeThrottler: throttle<() => void> = throttle(
100,
this.updateModalContainerHeight,
{ noLeading: false, noTrailing: false }
).bind(this);
// This is a workaround for Safari. Safari does not update shadowRoot elements calculated
// based on the viewport size (ie. `calc(100vh - 10px)`). It does an initial calculation correctly,
// but resizing the window does not cause the calculation to update. Firefox and Chrome both handle
// this correctly.
// It doesn't matter what css variable you set, it is just forcing Safari to do an update.
// Also note that the value has to change on each update for Safari to do the update,
// ie. you can't just set a static value.
private updateModalContainerHeight(): void {
this.modalManager.style.setProperty(
'--containerHeight',
`${window.innerHeight}px`
);
}
private stopDocumentScroll(): void {
document.body.classList.add('modal-manager-open');
}
private resumeDocumentScroll(): void {
document.body.classList.remove('modal-manager-open');
}
private startResizeListener(): void {
window.addEventListener('resize', this.windowResizeThrottler);
}
private stopResizeListener(): void {
window.removeEventListener('resize', this.windowResizeThrottler);
}
}