54 lines
3.3 KiB
JavaScript
54 lines
3.3 KiB
JavaScript
import * as React from 'react';
|
|
import { styleSingleton } from 'react-style-singleton';
|
|
import { fullWidthClassName, zeroRightClassName, noScrollbarsClassName, removedBarSizeVariable } from './constants';
|
|
import { getGapWidth } from './utils';
|
|
var Style = styleSingleton();
|
|
export var lockAttribute = 'data-scroll-locked';
|
|
// important tip - once we measure scrollBar width and remove them
|
|
// we could not repeat this operation
|
|
// thus we are using style-singleton - only the first "yet correct" style will be applied.
|
|
var getStyles = function (_a, allowRelative, gapMode, important) {
|
|
var left = _a.left, top = _a.top, right = _a.right, gap = _a.gap;
|
|
if (gapMode === void 0) { gapMode = 'margin'; }
|
|
return "\n .".concat(noScrollbarsClassName, " {\n overflow: hidden ").concat(important, ";\n padding-right: ").concat(gap, "px ").concat(important, ";\n }\n body[").concat(lockAttribute, "] {\n overflow: hidden ").concat(important, ";\n overscroll-behavior: contain;\n ").concat([
|
|
allowRelative && "position: relative ".concat(important, ";"),
|
|
gapMode === 'margin' &&
|
|
"\n padding-left: ".concat(left, "px;\n padding-top: ").concat(top, "px;\n padding-right: ").concat(right, "px;\n margin-left:0;\n margin-top:0;\n margin-right: ").concat(gap, "px ").concat(important, ";\n "),
|
|
gapMode === 'padding' && "padding-right: ".concat(gap, "px ").concat(important, ";"),
|
|
]
|
|
.filter(Boolean)
|
|
.join(''), "\n }\n \n .").concat(zeroRightClassName, " {\n right: ").concat(gap, "px ").concat(important, ";\n }\n \n .").concat(fullWidthClassName, " {\n margin-right: ").concat(gap, "px ").concat(important, ";\n }\n \n .").concat(zeroRightClassName, " .").concat(zeroRightClassName, " {\n right: 0 ").concat(important, ";\n }\n \n .").concat(fullWidthClassName, " .").concat(fullWidthClassName, " {\n margin-right: 0 ").concat(important, ";\n }\n \n body[").concat(lockAttribute, "] {\n ").concat(removedBarSizeVariable, ": ").concat(gap, "px;\n }\n");
|
|
};
|
|
var getCurrentUseCounter = function () {
|
|
var counter = parseInt(document.body.getAttribute(lockAttribute) || '0', 10);
|
|
return isFinite(counter) ? counter : 0;
|
|
};
|
|
export var useLockAttribute = function () {
|
|
React.useEffect(function () {
|
|
document.body.setAttribute(lockAttribute, (getCurrentUseCounter() + 1).toString());
|
|
return function () {
|
|
var newCounter = getCurrentUseCounter() - 1;
|
|
if (newCounter <= 0) {
|
|
document.body.removeAttribute(lockAttribute);
|
|
}
|
|
else {
|
|
document.body.setAttribute(lockAttribute, newCounter.toString());
|
|
}
|
|
};
|
|
}, []);
|
|
};
|
|
/**
|
|
* Removes page scrollbar and blocks page scroll when mounted
|
|
*/
|
|
export var RemoveScrollBar = function (_a) {
|
|
var noRelative = _a.noRelative, noImportant = _a.noImportant, _b = _a.gapMode, gapMode = _b === void 0 ? 'margin' : _b;
|
|
useLockAttribute();
|
|
/*
|
|
gap will be measured on every component mount
|
|
however it will be used only by the "first" invocation
|
|
due to singleton nature of <Style
|
|
*/
|
|
var gap = React.useMemo(function () { return getGapWidth(gapMode); }, [gapMode]);
|
|
return React.createElement(Style, { styles: getStyles(gap, !noRelative, gapMode, !noImportant ? '!important' : '') });
|
|
};
|