Line data Source code
1 1 : let SCROLLBAR_WIDTH: number | null = null;
2 1 : let SCROLLBAR_HEIGHT: number | null = null;
3 :
4 : // Overlay scrollbars report no layout size but still paint over content.
5 1 : const OVERLAY_SCROLLBAR_WIDTH = 12;
6 1 : const OVERLAY_SCROLLBAR_HEIGHT = 12;
7 :
8 : // Kudos to: https://www.robinwieruch.de/react-hook-scrollbar-width/
9 :
10 1 : export const useScrollbarWidth = () => {
11 1 : if (SCROLLBAR_WIDTH !== null) {
12 1 : return SCROLLBAR_WIDTH;
13 : }
14 :
15 : // Creating invisible container
16 1 : const outer = document.createElement('div');
17 1 : outer.style.visibility = 'hidden';
18 1 : outer.style.overflow = 'scroll';
19 1 : (outer.style as any).msOverflowStyle = 'scrollbar';
20 1 : document.body.appendChild(outer);
21 :
22 : // Creating inner element and placing it in the container
23 1 : const inner = document.createElement('div');
24 1 : outer.appendChild(inner);
25 :
26 : // Calculating difference between container's full width and the child width
27 1 : SCROLLBAR_WIDTH = Math.max(
28 1 : outer.offsetWidth - inner.offsetWidth,
29 1 : OVERLAY_SCROLLBAR_WIDTH,
30 1 : );
31 :
32 : // Removing temporary elements from the DOM
33 1 : outer.parentNode?.removeChild(outer);
34 1 : return SCROLLBAR_WIDTH;
35 1 : };
36 :
37 1 : export const useScrollbarHeight = () => {
38 1 : if (SCROLLBAR_HEIGHT !== null) {
39 1 : return SCROLLBAR_HEIGHT;
40 : }
41 :
42 : // Creating invisible container
43 1 : const outer = document.createElement('div');
44 1 : outer.style.visibility = 'hidden';
45 1 : outer.style.overflow = 'scroll';
46 1 : (outer.style as any).msOverflowStyle = 'scrollbar';
47 1 : document.body.appendChild(outer);
48 :
49 : // Creating inner element and placing it in the container
50 1 : const inner = document.createElement('div');
51 1 : outer.appendChild(inner);
52 :
53 : // Calculating difference between container's full height and the child height
54 1 : SCROLLBAR_HEIGHT = Math.max(
55 1 : outer.offsetHeight - inner.offsetHeight,
56 1 : OVERLAY_SCROLLBAR_HEIGHT,
57 1 : );
58 :
59 : // Removing temporary elements from the DOM
60 1 : outer.parentNode?.removeChild(outer);
61 1 : return SCROLLBAR_HEIGHT;
62 1 : };
|