-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathResizeObserver.ts
More file actions
97 lines (87 loc) · 2.92 KB
/
ResizeObserver.ts
File metadata and controls
97 lines (87 loc) · 2.92 KB
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
class ObserverHelper {
private readonly __resizeObserver: ResizeObserver;
private readonly __resizeCallbacks: Map<Element, Map<Element, Function>>;
constructor() {
this.__resizeCallbacks = new Map();
this.__resizeObserver = new ResizeObserver((entries) => {
entries.forEach((entry) => {
const listeners = this.__resizeCallbacks.get(entry.target);
listeners?.forEach((resizeCallback) => { resizeCallback(entry); });
});
});
}
isSizeChanged = (value1: number, value2: number, delta: number): boolean => !value1 || Math.abs(value2 - value1) > delta;
debounce = (func: Function, timeout: number): ((...args: any[]) => void) => {
let timer: number;
return (...args: any[]): void => {
window.clearTimeout(timer);
timer = window.setTimeout(() => {
func.apply(this, args);
}, timeout);
};
};
resizeCallback = (component: any, resizeAction: Function, delta = 1) => (container: ResizeObserverEntry): void => {
const { width, height } = container.contentRect;
if (
this.isSizeChanged(component.__observableWidth, width, delta)
|| this.isSizeChanged(component.__observableHeight, height, delta)
) {
component.__observableHeight = height;
component.__observableWidth = width;
if (width === 0 || height === 0) return;
resizeAction?.apply(component);
}
};
subscribe(
component: any,
element: Element | null,
resizeAction: Function,
delta: number,
delay: number,
): void {
if (!resizeAction || !element) {
// eslint-disable-next-line no-console
console.error('Subscription failed. No resize callback or element passed');
return;
}
let listeners = this.__resizeCallbacks.get(element);
if (!listeners) {
this.__resizeObserver.observe(element);
listeners = new Map<Element, Function>();
}
const newResizeCallback = this.resizeCallback(
component,
resizeAction,
delta,
);
listeners.set(
component.element(),
delay ? this.debounce(newResizeCallback, delay) : newResizeCallback,
);
this.__resizeCallbacks.set(element, listeners);
component.on('disposing', ({ component: disposingComponent }: any): void => {
this.unsubscribe(element, disposingComponent.element());
});
}
unsubscribe(key1: Element, key2: Element): void {
const listeners = this.__resizeCallbacks.get(key1);
if (!listeners) {
// eslint-disable-next-line no-console
console.error('Unsubscribe failed');
return;
}
listeners.delete(key2);
if (listeners.size === 0) {
this.__resizeCallbacks.delete(key1);
this.__resizeObserver.unobserve(key1);
} else {
this.__resizeCallbacks.set(key1, listeners);
}
}
disconnect(): void {
this.__resizeCallbacks.clear();
this.__resizeObserver.disconnect();
}
}
const observerInstance = new ObserverHelper();
export default observerInstance;