|
1 | 1 | /* eslint-disable no-param-reassign */ |
| 2 | +import{removeCSS,updateCSS}from'./Dom/dynamicCSS'; |
2 | 3 |
|
3 | | -letcached: number; |
| 4 | +typeScrollBarSize={width: number;height: number}; |
4 | 5 |
|
5 | | -exportdefaultfunctiongetScrollBarSize(fresh?: boolean){ |
6 | | -if(typeofdocument==='undefined'){ |
7 | | -return0; |
8 | | -} |
| 6 | +typeExtendCSSStyleDeclaration=CSSStyleDeclaration&{ |
| 7 | +scrollbarColor?: string; |
| 8 | +scrollbarWidth?: string; |
| 9 | +}; |
9 | 10 |
|
10 | | -if(fresh||cached===undefined){ |
11 | | -constinner=document.createElement('div'); |
12 | | -inner.style.width='100%'; |
13 | | -inner.style.height='200px'; |
| 11 | +letcached: ScrollBarSize; |
14 | 12 |
|
15 | | -constouter=document.createElement('div'); |
16 | | -constouterStyle=outer.style; |
| 13 | +functionmeasureScrollbarSize(ele?: HTMLElement): ScrollBarSize{ |
| 14 | +constrandomId=`rc-scrollbar-measure-${Math.random() |
| 15 | +.toString(36) |
| 16 | +.substring(7)}`; |
| 17 | +constmeasureEle=document.createElement('div'); |
| 18 | +measureEle.id=randomId; |
17 | 19 |
|
18 | | -outerStyle.position='absolute'; |
19 | | -outerStyle.top='0'; |
20 | | -outerStyle.left='0'; |
21 | | -outerStyle.pointerEvents='none'; |
22 | | -outerStyle.visibility='hidden'; |
23 | | -outerStyle.width='200px'; |
24 | | -outerStyle.height='150px'; |
25 | | -outerStyle.overflow='hidden'; |
| 20 | +// Create Style |
| 21 | +constmeasureStyle: ExtendCSSStyleDeclaration=measureEle.style; |
| 22 | +measureStyle.position='absolute'; |
| 23 | +measureStyle.left='0'; |
| 24 | +measureStyle.top='0'; |
| 25 | +measureStyle.width='100px'; |
| 26 | +measureStyle.height='100px'; |
| 27 | +measureStyle.overflow='scroll'; |
26 | 28 |
|
27 | | -outer.appendChild(inner); |
| 29 | +// Clone Style if needed |
| 30 | +letfallbackWidth: number; |
| 31 | +letfallbackHeight: number; |
| 32 | +if(ele){ |
| 33 | +consttargetStyle: ExtendCSSStyleDeclaration=getComputedStyle(ele); |
| 34 | +measureStyle.scrollbarColor=targetStyle.scrollbarColor; |
| 35 | +measureStyle.scrollbarWidth=targetStyle.scrollbarWidth; |
28 | 36 |
|
29 | | -document.body.appendChild(outer); |
| 37 | +// Set Webkit style |
| 38 | +constwebkitScrollbarStyle=getComputedStyle(ele,'::-webkit-scrollbar'); |
30 | 39 |
|
31 | | -constwidthContained=inner.offsetWidth; |
32 | | -outer.style.overflow='scroll'; |
33 | | -letwidthScroll=inner.offsetWidth; |
| 40 | +// Try wrap to handle CSP case |
| 41 | +try{ |
| 42 | +updateCSS( |
| 43 | +` |
| 44 | + #${randomId}::-webkit-scrollbar { |
| 45 | + width: ${webkitScrollbarStyle.width}; |
| 46 | + height: ${webkitScrollbarStyle.height}; |
| 47 | + } |
| 48 | + `, |
| 49 | +randomId, |
| 50 | +); |
| 51 | +}catch(e){ |
| 52 | +// Can't wrap, just log error |
| 53 | +console.error(e); |
34 | 54 |
|
35 | | -if(widthContained===widthScroll){ |
36 | | -widthScroll=outer.clientWidth; |
| 55 | +// Get from style directly |
| 56 | +fallbackWidth=parseInt(webkitScrollbarStyle.width,10); |
| 57 | +fallbackHeight=parseInt(webkitScrollbarStyle.height,10); |
37 | 58 | } |
| 59 | +} |
38 | 60 |
|
39 | | -document.body.removeChild(outer); |
| 61 | +document.body.appendChild(measureEle); |
40 | 62 |
|
41 | | -cached=widthContained-widthScroll; |
42 | | -} |
43 | | -returncached; |
| 63 | +// Measure. Get fallback style if provided |
| 64 | +constscrollWidth= |
| 65 | +ele&&fallbackWidth&&!isNaN(fallbackWidth) |
| 66 | + ? fallbackWidth |
| 67 | + : measureEle.offsetWidth-measureEle.clientWidth; |
| 68 | +constscrollHeight= |
| 69 | +ele&&fallbackHeight&&!isNaN(fallbackHeight) |
| 70 | + ? fallbackHeight |
| 71 | + : measureEle.offsetHeight-measureEle.clientHeight; |
| 72 | + |
| 73 | +// Clean up |
| 74 | +document.body.removeChild(measureEle); |
| 75 | +removeCSS(randomId); |
| 76 | + |
| 77 | +return{ |
| 78 | +width: scrollWidth, |
| 79 | +height: scrollHeight, |
| 80 | +}; |
44 | 81 | } |
45 | 82 |
|
46 | | -functionensureSize(str: string){ |
47 | | -constmatch=str.match(/^(.*)px$/); |
48 | | -constvalue=Number(match?.[1]); |
49 | | -returnNumber.isNaN(value) ? getScrollBarSize() : value; |
| 83 | +exportdefaultfunctiongetScrollBarSize(fresh?: boolean): number{ |
| 84 | +if(typeofdocument==='undefined'){ |
| 85 | +return0; |
| 86 | +} |
| 87 | + |
| 88 | +if(fresh||cached===undefined){ |
| 89 | +cached=measureScrollbarSize(); |
| 90 | +} |
| 91 | +returncached.width; |
50 | 92 | } |
51 | 93 |
|
52 | 94 | exportfunctiongetTargetScrollBarSize(target: HTMLElement){ |
53 | | -if(typeofdocument==='undefined'||!target||!(targetinstanceofElement)){ |
| 95 | +if( |
| 96 | +typeofdocument==='undefined'|| |
| 97 | +!target|| |
| 98 | +!(targetinstanceofElement) |
| 99 | +){ |
54 | 100 | return{width: 0,height: 0}; |
55 | 101 | } |
56 | 102 |
|
57 | | -const{ width, height }=getComputedStyle(target,'::-webkit-scrollbar'); |
58 | | -return{ |
59 | | -width: ensureSize(width), |
60 | | -height: ensureSize(height), |
61 | | -}; |
| 103 | +returnmeasureScrollbarSize(target); |
62 | 104 | } |
0 commit comments