mirror of
https://github.com/tenrok/OverlayScrollbars.git
synced 2026-06-07 02:52:26 +03:00
add environment class
This commit is contained in:
@@ -1,14 +1,19 @@
|
||||
export { default as not } from 'dir/not.png';
|
||||
import j from 'jquery';
|
||||
|
||||
var abc = 'abc';
|
||||
|
||||
const a = 1 + 1;
|
||||
var file = {
|
||||
a,
|
||||
};
|
||||
|
||||
const a$1 = 'a';
|
||||
const b = 'b';
|
||||
const c = 'c';
|
||||
|
||||
var index = j('div');
|
||||
|
||||
export default index;
|
||||
export { a$1 as a, abc, b, c, file };
|
||||
//# sourceMappingURL=overlayscrollbars-jquery.esm.js.map
|
||||
|
||||
@@ -1 +1 @@
|
||||
{"version":3,"file":"overlayscrollbars-jquery.esm.js","sources":["../src/dir/abc.js","../src/file.js","../src/test.js","../src/index.js"],"sourcesContent":["export default 'abc';\r\n","const a = 1 + 1;\r\nexport default {\r\n a,\r\n};\r\n","export const a = 'a';\r\nexport const b = 'b';\r\nexport const c = 'c';\r\n","import abc from 'dir/abc';\r\nimport not from 'dir/not.png';\r\nimport file from 'file';\r\nimport j from 'jquery';\r\nimport { a, b, c } from 'test';\r\n\r\nexport default j('div');\r\nexport { a, b, c, file, abc, not };\r\n"],"names":["a","b","c","j"],"mappings":";;AAAA,UAAe,KAAf;ACAA,MAAMA,CAAC,GAAG,IAAI,CAAd;AACA,WAAe;AACbA,EAAAA;AADa,CAAf;ACDY,MAACA,GAAC,GAAG,GAAL;AACA,MAACC,CAAC,GAAG,GAAL;AACA,MAACC,CAAC,GAAG,GAAL;ACIZ,YAAeC,CAAC,CAAC,KAAD,CAAhB;;;"}
|
||||
{"version":3,"file":"overlayscrollbars-jquery.esm.js","sources":["../src/dir/abc.js","../src/file.js","../src/test.js","../src/index.js"],"sourcesContent":["export default 'abc';\r\n","const a = 1 + 1;\r\nexport default {\r\n a,\r\n};\r\n","export const a = 'a';\r\nexport const b = 'b';\r\nexport const c = 'c';\r\n","import abc from 'dir/abc';\r\nimport not from 'dir/not.png';\r\nimport file from 'file';\r\nimport j from 'jquery';\r\nimport { a, b, c } from 'test';\r\n\r\nexport default j('div');\r\nexport { a, b, c, file, abc, not };\r\n"],"names":["a","b","c","j"],"mappings":";;;AAAA,UAAe,KAAf;;ACAA,MAAMA,CAAC,GAAG,IAAI,CAAd;AACA,WAAe;AACbA,EAAAA;AADa,CAAf;;MCDaA,GAAC,GAAG;MACJC,CAAC,GAAG;MACJC,CAAC,GAAG;;ACIjB,YAAeC,CAAC,CAAC,KAAD,CAAhB;;;;"}
|
||||
@@ -9,15 +9,20 @@
|
||||
|
||||
not_png = not_png && Object.prototype.hasOwnProperty.call(not_png, 'default') ? not_png['default'] : not_png;
|
||||
j = j && Object.prototype.hasOwnProperty.call(j, 'default') ? j['default'] : j;
|
||||
|
||||
var abc = 'abc';
|
||||
|
||||
var a = 1 + 1;
|
||||
var file = {
|
||||
a: a,
|
||||
};
|
||||
|
||||
var a$1 = 'a';
|
||||
var b = 'b';
|
||||
var c = 'c';
|
||||
|
||||
var index = j('div');
|
||||
|
||||
exports.not = not_png;
|
||||
exports.a = a$1;
|
||||
exports.abc = abc;
|
||||
@@ -25,8 +30,7 @@
|
||||
exports.c = c;
|
||||
exports.default = index;
|
||||
exports.file = file;
|
||||
Object.defineProperty(exports, '__esModule', {
|
||||
value: true,
|
||||
});
|
||||
|
||||
Object.defineProperty(exports, '__esModule', { value: true });
|
||||
});
|
||||
//# sourceMappingURL=overlayscrollbars-jquery.js.map
|
||||
|
||||
@@ -1 +1 @@
|
||||
{"version":3,"file":"overlayscrollbars-jquery.js","sources":["../src/dir/abc.js","../src/file.js","../src/test.js","../src/index.js"],"sourcesContent":["export default 'abc';\r\n","const a = 1 + 1;\r\nexport default {\r\n a,\r\n};\r\n","export const a = 'a';\r\nexport const b = 'b';\r\nexport const c = 'c';\r\n","import abc from 'dir/abc';\r\nimport not from 'dir/not.png';\r\nimport file from 'file';\r\nimport j from 'jquery';\r\nimport { a, b, c } from 'test';\r\n\r\nexport default j('div');\r\nexport { a, b, c, file, abc, not };\r\n"],"names":["a","b","c","j"],"mappings":";;;;;;;;;;;YAAe;ACAf,MAAMA,CAAC,GAAG,IAAI,CAAd;aACe;AACbA,IAAAA,CAAC,EAADA;AADa;MCDFA,GAAC,GAAG;MACJC,CAAC,GAAG;MACJC,CAAC,GAAG;cCIFC,CAAC,CAAC,KAAD;;;;;;;;;;;;"}
|
||||
{"version":3,"file":"overlayscrollbars-jquery.js","sources":["../src/dir/abc.js","../src/file.js","../src/test.js","../src/index.js"],"sourcesContent":["export default 'abc';\r\n","const a = 1 + 1;\r\nexport default {\r\n a,\r\n};\r\n","export const a = 'a';\r\nexport const b = 'b';\r\nexport const c = 'c';\r\n","import abc from 'dir/abc';\r\nimport not from 'dir/not.png';\r\nimport file from 'file';\r\nimport j from 'jquery';\r\nimport { a, b, c } from 'test';\r\n\r\nexport default j('div');\r\nexport { a, b, c, file, abc, not };\r\n"],"names":["a","b","c","j"],"mappings":";;;;;;;;;;;;AAAA,YAAe,KAAf;;ECAA,IAAMA,CAAC,GAAG,IAAI,CAAd;AACA,aAAe;EACbA,EAAAA,CAAC,EAADA;EADa,CAAf;;MCDaA,GAAC,GAAG;MACJC,CAAC,GAAG;MACJC,CAAC,GAAG;;ACIjB,cAAeC,CAAC,CAAC,KAAD,CAAhB;;;;;;;;;;;;"}
|
||||
+431
-12
@@ -1,20 +1,60 @@
|
||||
function isNumber(obj) {
|
||||
return typeof obj === 'number';
|
||||
}
|
||||
|
||||
function isString(obj) {
|
||||
return typeof obj === 'string';
|
||||
}
|
||||
function isFunction(obj) {
|
||||
return typeof obj === 'function';
|
||||
}
|
||||
|
||||
function isUndefined(obj) {
|
||||
return obj === undefined;
|
||||
}
|
||||
function isArray(obj) {
|
||||
return Array.isArray(obj);
|
||||
}
|
||||
|
||||
function isArrayLike(obj) {
|
||||
const length = !!obj && obj.length;
|
||||
return isArray(obj) || (!isFunction(obj) && isNumber(length) && length > -1 && length % 1 == 0);
|
||||
}
|
||||
|
||||
function getSetProp(topLeft, fallback, elm, value) {
|
||||
if (isUndefined(value)) {
|
||||
return elm ? elm[topLeft] : fallback;
|
||||
}
|
||||
|
||||
elm && (elm[topLeft] = value);
|
||||
}
|
||||
const removeAttr = (elm, attrName) => {
|
||||
elm == null ? void 0 : elm.removeAttribute(attrName);
|
||||
};
|
||||
function scrollLeft(elm, value) {
|
||||
return getSetProp('scrollLeft', 0, elm, value);
|
||||
}
|
||||
|
||||
const rnothtmlwhite = /[^\x20\t\r\n\f]+/g;
|
||||
|
||||
const classListAction = (elm, className, action) => {
|
||||
let clazz;
|
||||
let i = 0;
|
||||
let result = false;
|
||||
|
||||
if (elm && isString(className)) {
|
||||
const classes = className.match(rnothtmlwhite) || [];
|
||||
result = classes.length > 0;
|
||||
|
||||
while ((clazz = classes[i++])) {
|
||||
result = action(elm.classList, clazz) && result;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
const addClass = (elm, className) => {
|
||||
classListAction(elm, className, (classList, clazz) => classList.add(clazz));
|
||||
};
|
||||
|
||||
const hasOwnProperty = (obj, prop) => Object.prototype.hasOwnProperty.call(obj, prop);
|
||||
const keys = (obj) => (obj ? Object.keys(obj) : []);
|
||||
|
||||
function each(source, callback) {
|
||||
@@ -33,6 +73,41 @@ function each(source, callback) {
|
||||
|
||||
const contents = (elm) => (elm ? Array.from(elm.childNodes) : []);
|
||||
|
||||
const before = (parentElm, preferredAnchor, insertedElms) => {
|
||||
if (insertedElms) {
|
||||
let anchor = preferredAnchor;
|
||||
let fragment;
|
||||
|
||||
if (parentElm) {
|
||||
if (isArrayLike(insertedElms)) {
|
||||
fragment = document.createDocumentFragment();
|
||||
each(insertedElms, (insertedElm) => {
|
||||
if (insertedElm === anchor) {
|
||||
anchor = insertedElm.previousSibling;
|
||||
}
|
||||
|
||||
fragment.appendChild(insertedElm);
|
||||
});
|
||||
} else {
|
||||
fragment = insertedElms;
|
||||
}
|
||||
|
||||
if (preferredAnchor) {
|
||||
if (!anchor) {
|
||||
anchor = parentElm.firstChild;
|
||||
} else if (anchor !== preferredAnchor) {
|
||||
anchor = anchor.nextSibling;
|
||||
}
|
||||
}
|
||||
|
||||
parentElm.insertBefore(fragment, anchor);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const appendChildren = (node, children) => {
|
||||
before(node, null, children);
|
||||
};
|
||||
const removeElements = (nodes) => {
|
||||
if (isArrayLike(nodes)) {
|
||||
each(Array.from(nodes), (e) => removeElements(e));
|
||||
@@ -46,22 +121,369 @@ const removeElements = (nodes) => {
|
||||
};
|
||||
|
||||
const createDiv = () => document.createElement('div');
|
||||
|
||||
const createDOM = (html) => {
|
||||
const createdDiv = createDiv();
|
||||
createdDiv.innerHTML = html.trim();
|
||||
return each(contents(createdDiv), (elm) => removeElements(elm));
|
||||
};
|
||||
|
||||
const abc = {
|
||||
a: 1,
|
||||
b: 1,
|
||||
c: 1,
|
||||
const zeroDomRect = new DOMRect();
|
||||
const zeroObj = {
|
||||
w: 0,
|
||||
h: 0,
|
||||
};
|
||||
const windowSize = () => ({
|
||||
w: window.innerWidth,
|
||||
h: window.innerHeight,
|
||||
});
|
||||
const offsetSize = (elm) =>
|
||||
elm
|
||||
? {
|
||||
w: elm.offsetWidth,
|
||||
h: elm.offsetHeight,
|
||||
}
|
||||
: zeroObj;
|
||||
const clientSize = (elm) =>
|
||||
elm
|
||||
? {
|
||||
w: elm.clientWidth,
|
||||
h: elm.clientHeight,
|
||||
}
|
||||
: zeroObj;
|
||||
|
||||
const cssNumber = {
|
||||
animationiterationcount: 1,
|
||||
columncount: 1,
|
||||
fillopacity: 1,
|
||||
flexgrow: 1,
|
||||
flexshrink: 1,
|
||||
fontweight: 1,
|
||||
lineheight: 1,
|
||||
opacity: 1,
|
||||
order: 1,
|
||||
orphans: 1,
|
||||
widows: 1,
|
||||
zindex: 1,
|
||||
zoom: 1,
|
||||
};
|
||||
|
||||
const adaptCSSVal = (prop, val) => (!cssNumber[prop.toLowerCase()] && isNumber(val) ? `${val}px` : val);
|
||||
|
||||
const getCSSVal = (elm, computedStyle, prop) => (computedStyle != null ? computedStyle.getPropertyValue(prop) : elm.style[prop]);
|
||||
|
||||
const setCSSVal = (elm, prop, val) => {
|
||||
try {
|
||||
if (elm && elm.style[prop] !== undefined) {
|
||||
elm.style[prop] = adaptCSSVal(prop, val);
|
||||
}
|
||||
} catch (e) {}
|
||||
};
|
||||
|
||||
function style(elm, styles) {
|
||||
const getSingleStyle = isString(styles);
|
||||
const getStyles = isArray(styles) || getSingleStyle;
|
||||
|
||||
if (getStyles) {
|
||||
let getStylesResult = getSingleStyle ? '' : {};
|
||||
|
||||
if (elm) {
|
||||
const computedStyle = window.getComputedStyle(elm, null);
|
||||
getStylesResult = getSingleStyle
|
||||
? getCSSVal(elm, computedStyle, styles)
|
||||
: styles.reduce((result, key) => {
|
||||
result[key] = getCSSVal(elm, computedStyle, key);
|
||||
return result;
|
||||
}, getStylesResult);
|
||||
}
|
||||
|
||||
return getStylesResult;
|
||||
}
|
||||
|
||||
each(keys(styles), (key) => setCSSVal(elm, key, styles[key]));
|
||||
}
|
||||
|
||||
const zeroObj$1 = {
|
||||
x: 0,
|
||||
y: 0,
|
||||
};
|
||||
const offset = (elm) => {
|
||||
const rect = elm ? elm.getBoundingClientRect() : 0;
|
||||
return rect
|
||||
? {
|
||||
x: rect.left + window.pageYOffset,
|
||||
y: rect.top + window.pageXOffset,
|
||||
}
|
||||
: zeroObj$1;
|
||||
};
|
||||
|
||||
function _classPrivateFieldGet(receiver, privateMap) {
|
||||
var descriptor = privateMap.get(receiver);
|
||||
|
||||
if (!descriptor) {
|
||||
throw new TypeError('attempted to get private field on non-instance');
|
||||
}
|
||||
|
||||
if (descriptor.get) {
|
||||
return descriptor.get.call(receiver);
|
||||
}
|
||||
|
||||
return descriptor.value;
|
||||
}
|
||||
|
||||
var classPrivateFieldGet = _classPrivateFieldGet;
|
||||
|
||||
function _classPrivateFieldSet(receiver, privateMap, value) {
|
||||
var descriptor = privateMap.get(receiver);
|
||||
|
||||
if (!descriptor) {
|
||||
throw new TypeError('attempted to set private field on non-instance');
|
||||
}
|
||||
|
||||
if (descriptor.set) {
|
||||
descriptor.set.call(receiver, value);
|
||||
} else {
|
||||
if (!descriptor.writable) {
|
||||
throw new TypeError('attempted to set read only private field');
|
||||
}
|
||||
|
||||
descriptor.value = value;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
var classPrivateFieldSet = _classPrivateFieldSet;
|
||||
|
||||
const firstLetterToUpper = (str) => str.charAt(0).toUpperCase() + str.slice(1);
|
||||
const jsPrefixes = ['WebKit', 'Moz', 'O', 'MS', 'webkit', 'moz', 'o', 'ms'];
|
||||
const jsCache = {};
|
||||
const jsAPI = (name) => {
|
||||
let result = jsCache[name] || window[name];
|
||||
|
||||
if (hasOwnProperty(jsCache, name)) {
|
||||
return result;
|
||||
}
|
||||
|
||||
each(jsPrefixes, (prefix) => {
|
||||
result = result || window[prefix + firstLetterToUpper(name)];
|
||||
return !result;
|
||||
});
|
||||
jsCache[name] = result;
|
||||
return result;
|
||||
};
|
||||
|
||||
const resizeObserver = jsAPI('ResizeObserver');
|
||||
|
||||
function createCommonjsModule(fn, basedir, module) {
|
||||
return (
|
||||
(module = {
|
||||
path: basedir,
|
||||
exports: {},
|
||||
require: function (path, base) {
|
||||
return commonjsRequire(path, base === undefined || base === null ? module.path : base);
|
||||
},
|
||||
}),
|
||||
fn(module, module.exports),
|
||||
module.exports
|
||||
);
|
||||
}
|
||||
|
||||
function commonjsRequire() {
|
||||
throw new Error('Dynamic requires are not currently supported by @rollup/plugin-commonjs');
|
||||
}
|
||||
|
||||
var _extends_1 = createCommonjsModule(function (module) {
|
||||
function _extends() {
|
||||
module.exports = _extends =
|
||||
Object.assign ||
|
||||
function (target) {
|
||||
for (var i = 1; i < arguments.length; i++) {
|
||||
var source = arguments[i];
|
||||
|
||||
for (var key in source) {
|
||||
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
||||
target[key] = source[key];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return target;
|
||||
};
|
||||
|
||||
return _extends.apply(this, arguments);
|
||||
}
|
||||
|
||||
module.exports = _extends;
|
||||
});
|
||||
|
||||
const templateTypePrefixSuffix = ['__TPL_', '_TYPE__'];
|
||||
const optionsTemplateTypes = ['boolean', 'number', 'string', 'array', 'object', 'function', 'null'].reduce((result, item) => {
|
||||
result[item] = templateTypePrefixSuffix[0] + item + templateTypePrefixSuffix[1];
|
||||
return result;
|
||||
}, {});
|
||||
|
||||
const { abs, round } = Math;
|
||||
|
||||
const nativeScrollbarSize = (body, measureElm) => {
|
||||
appendChildren(body, measureElm);
|
||||
const cSize = clientSize(measureElm);
|
||||
const oSize = offsetSize(measureElm);
|
||||
return {
|
||||
x: oSize.h - cSize.h,
|
||||
y: oSize.w - cSize.w,
|
||||
};
|
||||
};
|
||||
|
||||
const nativeScrollbarStyling = (testElm) => {
|
||||
let result = false;
|
||||
addClass(testElm, 'os-viewport-native-scrollbars-invisible');
|
||||
|
||||
try {
|
||||
result =
|
||||
style(testElm, 'scrollbar-width') === 'none' || window.getComputedStyle(testElm, '::-webkit-scrollbar').getPropertyValue('display') === 'none';
|
||||
} catch (ex) {}
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
const rtlScrollBehavior = (parentElm, childElm) => {
|
||||
const strHidden = 'hidden';
|
||||
style(parentElm, {
|
||||
overflowX: strHidden,
|
||||
overflowY: strHidden,
|
||||
});
|
||||
scrollLeft(parentElm, 0);
|
||||
const parentOffset = offset(parentElm);
|
||||
const childOffset = offset(childElm);
|
||||
scrollLeft(parentElm, -999);
|
||||
const childOffsetAfterScroll = offset(childElm);
|
||||
return {
|
||||
i: parentOffset.x === childOffset.x,
|
||||
n: childOffset.x !== childOffsetAfterScroll.x,
|
||||
};
|
||||
};
|
||||
|
||||
const passiveEvents = () => {
|
||||
let supportsPassive = false;
|
||||
|
||||
try {
|
||||
window.addEventListener(
|
||||
'test',
|
||||
null,
|
||||
Object.defineProperty({}, 'passive', {
|
||||
get: function () {
|
||||
supportsPassive = true;
|
||||
},
|
||||
})
|
||||
);
|
||||
} catch (e) {}
|
||||
|
||||
return supportsPassive;
|
||||
};
|
||||
|
||||
const windowDPR = () => {
|
||||
const dDPI = window.screen.deviceXDPI || 0;
|
||||
const sDPI = window.screen.logicalXDPI || 1;
|
||||
return window.devicePixelRatio || dDPI / sDPI;
|
||||
};
|
||||
|
||||
const diffBiggerThanOne = (valOne, valTwo) => {
|
||||
const absValOne = abs(valOne);
|
||||
const absValTwo = abs(valTwo);
|
||||
return !(absValOne === absValTwo || absValOne + 1 === absValTwo || absValOne - 1 === absValTwo);
|
||||
};
|
||||
|
||||
var _onChangedListener = new WeakMap();
|
||||
|
||||
class Environment {
|
||||
constructor() {
|
||||
_onChangedListener.set(this, {
|
||||
writable: true,
|
||||
value: void 0,
|
||||
});
|
||||
|
||||
classPrivateFieldSet(this, _onChangedListener, new Set());
|
||||
|
||||
const _self = this;
|
||||
|
||||
const { body } = document;
|
||||
const envDOM = createDOM('<div id="os-dummy-scrollbar-size"><div></div></div>');
|
||||
const envElm = envDOM[0];
|
||||
const envChildElm = envElm.firstChild;
|
||||
const nScrollBarSize = nativeScrollbarSize(body, envElm);
|
||||
const nativeScrollbarIsOverlaid = {
|
||||
x: nScrollBarSize.x === 0,
|
||||
y: nScrollBarSize.y === 0,
|
||||
};
|
||||
_self.autoUpdateLoop = false;
|
||||
_self.nativeScrollbarSize = nScrollBarSize;
|
||||
_self.nativeScrollbarIsOverlaid = nativeScrollbarIsOverlaid;
|
||||
_self.nativeScrollbarStyling = nativeScrollbarStyling(envElm);
|
||||
_self.rtlScrollBehavior = rtlScrollBehavior(envElm, envChildElm);
|
||||
_self.supportPassiveEvents = passiveEvents();
|
||||
_self.supportResizeObserver = !!jsAPI('ResizeObserver');
|
||||
removeAttr(envElm, 'style');
|
||||
removeElements(envElm);
|
||||
|
||||
if (nativeScrollbarIsOverlaid.x && nativeScrollbarIsOverlaid.y) {
|
||||
let size = windowSize();
|
||||
let dpr = windowDPR();
|
||||
|
||||
const onChangedListener = classPrivateFieldGet(this, _onChangedListener);
|
||||
|
||||
window.addEventListener('resize', () => {
|
||||
if (onChangedListener.size) {
|
||||
const sizeNew = windowSize();
|
||||
const deltaSize = {
|
||||
w: sizeNew.w - size.w,
|
||||
h: sizeNew.h - size.h,
|
||||
};
|
||||
if (deltaSize.w === 0 && deltaSize.h === 0) return;
|
||||
const deltaAbsSize = {
|
||||
w: abs(deltaSize.w),
|
||||
h: abs(deltaSize.h),
|
||||
};
|
||||
const deltaAbsRatio = {
|
||||
w: abs(round(sizeNew.w / (size.w / 100.0))),
|
||||
h: abs(round(sizeNew.h / (size.h / 100.0))),
|
||||
};
|
||||
const dprNew = windowDPR();
|
||||
const deltaIsBigger = deltaAbsSize.w > 2 && deltaAbsSize.h > 2;
|
||||
const difference = !diffBiggerThanOne(deltaAbsRatio.w, deltaAbsRatio.h);
|
||||
const dprChanged = dprNew !== dpr && dpr > 0;
|
||||
const isZoom = deltaIsBigger && difference && dprChanged;
|
||||
const oldScrollbarSize = _self.nativeScrollbarSize;
|
||||
let newScrollbarSize;
|
||||
|
||||
if (isZoom) {
|
||||
newScrollbarSize = _self.nativeScrollbarSize = nativeScrollbarSize(body, envElm);
|
||||
removeElements(envElm);
|
||||
|
||||
if (oldScrollbarSize.x !== newScrollbarSize.x || oldScrollbarSize.y !== newScrollbarSize.y) {
|
||||
onChangedListener.forEach((listener) => listener && listener(_self));
|
||||
}
|
||||
}
|
||||
|
||||
size = sizeNew;
|
||||
dpr = dprNew;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
addListener(listener) {
|
||||
classPrivateFieldGet(this, _onChangedListener).add(listener);
|
||||
}
|
||||
|
||||
removeListener(listener) {
|
||||
classPrivateFieldGet(this, _onChangedListener).delete(listener);
|
||||
}
|
||||
}
|
||||
|
||||
const env = new Environment();
|
||||
var index = () => {
|
||||
const { a, b, c } = abc;
|
||||
return [
|
||||
env,
|
||||
createDOM(
|
||||
'\
|
||||
<div class="os-host">\
|
||||
@@ -86,9 +508,6 @@ var index = () => {
|
||||
<div class="os-scrollbar-corner"></div>\
|
||||
</div>'
|
||||
),
|
||||
a,
|
||||
b,
|
||||
c,
|
||||
];
|
||||
};
|
||||
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+457
-15
@@ -10,20 +10,64 @@
|
||||
function isNumber(obj) {
|
||||
return typeof obj === 'number';
|
||||
}
|
||||
|
||||
function isString(obj) {
|
||||
return typeof obj === 'string';
|
||||
}
|
||||
function isFunction(obj) {
|
||||
return typeof obj === 'function';
|
||||
}
|
||||
|
||||
function isUndefined(obj) {
|
||||
return obj === undefined;
|
||||
}
|
||||
function isArray(obj) {
|
||||
return Array.isArray(obj);
|
||||
}
|
||||
|
||||
function isArrayLike(obj) {
|
||||
var length = !!obj && obj.length;
|
||||
return isArray(obj) || (!isFunction(obj) && isNumber(length) && length > -1 && length % 1 == 0);
|
||||
}
|
||||
|
||||
function getSetProp(topLeft, fallback, elm, value) {
|
||||
if (isUndefined(value)) {
|
||||
return elm ? elm[topLeft] : fallback;
|
||||
}
|
||||
|
||||
elm && (elm[topLeft] = value);
|
||||
}
|
||||
var removeAttr = function removeAttr(elm, attrName) {
|
||||
elm == null ? void 0 : elm.removeAttribute(attrName);
|
||||
};
|
||||
function scrollLeft(elm, value) {
|
||||
return getSetProp('scrollLeft', 0, elm, value);
|
||||
}
|
||||
|
||||
var rnothtmlwhite = /[^\x20\t\r\n\f]+/g;
|
||||
|
||||
var classListAction = function classListAction(elm, className, action) {
|
||||
var clazz;
|
||||
var i = 0;
|
||||
var result = false;
|
||||
|
||||
if (elm && isString(className)) {
|
||||
var classes = className.match(rnothtmlwhite) || [];
|
||||
result = classes.length > 0;
|
||||
|
||||
while ((clazz = classes[i++])) {
|
||||
result = action(elm.classList, clazz) && result;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
var addClass = function addClass(elm, className) {
|
||||
classListAction(elm, className, function (classList, clazz) {
|
||||
return classList.add(clazz);
|
||||
});
|
||||
};
|
||||
|
||||
var hasOwnProperty = function hasOwnProperty(obj, prop) {
|
||||
return Object.prototype.hasOwnProperty.call(obj, prop);
|
||||
};
|
||||
var keys = function keys(obj) {
|
||||
return obj ? Object.keys(obj) : [];
|
||||
};
|
||||
@@ -48,6 +92,41 @@
|
||||
return elm ? Array.from(elm.childNodes) : [];
|
||||
};
|
||||
|
||||
var before = function before(parentElm, preferredAnchor, insertedElms) {
|
||||
if (insertedElms) {
|
||||
var anchor = preferredAnchor;
|
||||
var fragment;
|
||||
|
||||
if (parentElm) {
|
||||
if (isArrayLike(insertedElms)) {
|
||||
fragment = document.createDocumentFragment();
|
||||
each(insertedElms, function (insertedElm) {
|
||||
if (insertedElm === anchor) {
|
||||
anchor = insertedElm.previousSibling;
|
||||
}
|
||||
|
||||
fragment.appendChild(insertedElm);
|
||||
});
|
||||
} else {
|
||||
fragment = insertedElms;
|
||||
}
|
||||
|
||||
if (preferredAnchor) {
|
||||
if (!anchor) {
|
||||
anchor = parentElm.firstChild;
|
||||
} else if (anchor !== preferredAnchor) {
|
||||
anchor = anchor.nextSibling;
|
||||
}
|
||||
}
|
||||
|
||||
parentElm.insertBefore(fragment, anchor);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var appendChildren = function appendChildren(node, children) {
|
||||
before(node, null, children);
|
||||
};
|
||||
var removeElements = function removeElements(nodes) {
|
||||
if (isArrayLike(nodes)) {
|
||||
each(Array.from(nodes), function (e) {
|
||||
@@ -65,7 +144,6 @@
|
||||
var createDiv = function createDiv() {
|
||||
return document.createElement('div');
|
||||
};
|
||||
|
||||
var createDOM = function createDOM(html) {
|
||||
var createdDiv = createDiv();
|
||||
createdDiv.innerHTML = html.trim();
|
||||
@@ -74,17 +152,384 @@
|
||||
});
|
||||
};
|
||||
|
||||
var abc = {
|
||||
a: 1,
|
||||
b: 1,
|
||||
c: 1,
|
||||
var zeroDomRect = new DOMRect();
|
||||
var zeroObj = {
|
||||
w: 0,
|
||||
h: 0,
|
||||
};
|
||||
var windowSize = function windowSize() {
|
||||
return {
|
||||
w: window.innerWidth,
|
||||
h: window.innerHeight,
|
||||
};
|
||||
};
|
||||
var offsetSize = function offsetSize(elm) {
|
||||
return elm
|
||||
? {
|
||||
w: elm.offsetWidth,
|
||||
h: elm.offsetHeight,
|
||||
}
|
||||
: zeroObj;
|
||||
};
|
||||
var clientSize = function clientSize(elm) {
|
||||
return elm
|
||||
? {
|
||||
w: elm.clientWidth,
|
||||
h: elm.clientHeight,
|
||||
}
|
||||
: zeroObj;
|
||||
};
|
||||
|
||||
var index = function index() {
|
||||
var a = abc.a,
|
||||
b = abc.b,
|
||||
c = abc.c;
|
||||
var cssNumber = {
|
||||
animationiterationcount: 1,
|
||||
columncount: 1,
|
||||
fillopacity: 1,
|
||||
flexgrow: 1,
|
||||
flexshrink: 1,
|
||||
fontweight: 1,
|
||||
lineheight: 1,
|
||||
opacity: 1,
|
||||
order: 1,
|
||||
orphans: 1,
|
||||
widows: 1,
|
||||
zindex: 1,
|
||||
zoom: 1,
|
||||
};
|
||||
|
||||
var adaptCSSVal = function adaptCSSVal(prop, val) {
|
||||
return !cssNumber[prop.toLowerCase()] && isNumber(val) ? val + 'px' : val;
|
||||
};
|
||||
|
||||
var getCSSVal = function getCSSVal(elm, computedStyle, prop) {
|
||||
return computedStyle != null ? computedStyle.getPropertyValue(prop) : elm.style[prop];
|
||||
};
|
||||
|
||||
var setCSSVal = function setCSSVal(elm, prop, val) {
|
||||
try {
|
||||
if (elm && elm.style[prop] !== undefined) {
|
||||
elm.style[prop] = adaptCSSVal(prop, val);
|
||||
}
|
||||
} catch (e) {}
|
||||
};
|
||||
|
||||
function style(elm, styles) {
|
||||
var getSingleStyle = isString(styles);
|
||||
var getStyles = isArray(styles) || getSingleStyle;
|
||||
|
||||
if (getStyles) {
|
||||
var getStylesResult = getSingleStyle ? '' : {};
|
||||
|
||||
if (elm) {
|
||||
var computedStyle = window.getComputedStyle(elm, null);
|
||||
getStylesResult = getSingleStyle
|
||||
? getCSSVal(elm, computedStyle, styles)
|
||||
: styles.reduce(function (result, key) {
|
||||
result[key] = getCSSVal(elm, computedStyle, key);
|
||||
return result;
|
||||
}, getStylesResult);
|
||||
}
|
||||
|
||||
return getStylesResult;
|
||||
}
|
||||
|
||||
each(keys(styles), function (key) {
|
||||
return setCSSVal(elm, key, styles[key]);
|
||||
});
|
||||
}
|
||||
|
||||
var zeroObj$1 = {
|
||||
x: 0,
|
||||
y: 0,
|
||||
};
|
||||
var offset = function offset(elm) {
|
||||
var rect = elm ? elm.getBoundingClientRect() : 0;
|
||||
return rect
|
||||
? {
|
||||
x: rect.left + window.pageYOffset,
|
||||
y: rect.top + window.pageXOffset,
|
||||
}
|
||||
: zeroObj$1;
|
||||
};
|
||||
|
||||
function _classPrivateFieldGet(receiver, privateMap) {
|
||||
var descriptor = privateMap.get(receiver);
|
||||
|
||||
if (!descriptor) {
|
||||
throw new TypeError('attempted to get private field on non-instance');
|
||||
}
|
||||
|
||||
if (descriptor.get) {
|
||||
return descriptor.get.call(receiver);
|
||||
}
|
||||
|
||||
return descriptor.value;
|
||||
}
|
||||
|
||||
var classPrivateFieldGet = _classPrivateFieldGet;
|
||||
|
||||
function _classPrivateFieldSet(receiver, privateMap, value) {
|
||||
var descriptor = privateMap.get(receiver);
|
||||
|
||||
if (!descriptor) {
|
||||
throw new TypeError('attempted to set private field on non-instance');
|
||||
}
|
||||
|
||||
if (descriptor.set) {
|
||||
descriptor.set.call(receiver, value);
|
||||
} else {
|
||||
if (!descriptor.writable) {
|
||||
throw new TypeError('attempted to set read only private field');
|
||||
}
|
||||
|
||||
descriptor.value = value;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
var classPrivateFieldSet = _classPrivateFieldSet;
|
||||
|
||||
var firstLetterToUpper = function firstLetterToUpper(str) {
|
||||
return str.charAt(0).toUpperCase() + str.slice(1);
|
||||
};
|
||||
var jsPrefixes = ['WebKit', 'Moz', 'O', 'MS', 'webkit', 'moz', 'o', 'ms'];
|
||||
var jsCache = {};
|
||||
var jsAPI = function jsAPI(name) {
|
||||
var result = jsCache[name] || window[name];
|
||||
|
||||
if (hasOwnProperty(jsCache, name)) {
|
||||
return result;
|
||||
}
|
||||
|
||||
each(jsPrefixes, function (prefix) {
|
||||
result = result || window[prefix + firstLetterToUpper(name)];
|
||||
return !result;
|
||||
});
|
||||
jsCache[name] = result;
|
||||
return result;
|
||||
};
|
||||
|
||||
var resizeObserver = jsAPI('ResizeObserver');
|
||||
|
||||
function createCommonjsModule(fn, basedir, module) {
|
||||
return (
|
||||
(module = {
|
||||
path: basedir,
|
||||
exports: {},
|
||||
require: function (path, base) {
|
||||
return commonjsRequire(path, base === undefined || base === null ? module.path : base);
|
||||
},
|
||||
}),
|
||||
fn(module, module.exports),
|
||||
module.exports
|
||||
);
|
||||
}
|
||||
|
||||
function commonjsRequire() {
|
||||
throw new Error('Dynamic requires are not currently supported by @rollup/plugin-commonjs');
|
||||
}
|
||||
|
||||
var _extends_1 = createCommonjsModule(function (module) {
|
||||
function _extends() {
|
||||
module.exports = _extends =
|
||||
Object.assign ||
|
||||
function (target) {
|
||||
for (var i = 1; i < arguments.length; i++) {
|
||||
var source = arguments[i];
|
||||
|
||||
for (var key in source) {
|
||||
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
||||
target[key] = source[key];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return target;
|
||||
};
|
||||
|
||||
return _extends.apply(this, arguments);
|
||||
}
|
||||
|
||||
module.exports = _extends;
|
||||
});
|
||||
|
||||
var templateTypePrefixSuffix = ['__TPL_', '_TYPE__'];
|
||||
var optionsTemplateTypes = ['boolean', 'number', 'string', 'array', 'object', 'function', 'null'].reduce(function (result, item) {
|
||||
result[item] = templateTypePrefixSuffix[0] + item + templateTypePrefixSuffix[1];
|
||||
return result;
|
||||
}, {});
|
||||
|
||||
var abs = Math.abs,
|
||||
round = Math.round;
|
||||
|
||||
var nativeScrollbarSize = function nativeScrollbarSize(body, measureElm) {
|
||||
appendChildren(body, measureElm);
|
||||
var cSize = clientSize(measureElm);
|
||||
var oSize = offsetSize(measureElm);
|
||||
return {
|
||||
x: oSize.h - cSize.h,
|
||||
y: oSize.w - cSize.w,
|
||||
};
|
||||
};
|
||||
|
||||
var nativeScrollbarStyling = function nativeScrollbarStyling(testElm) {
|
||||
var result = false;
|
||||
addClass(testElm, 'os-viewport-native-scrollbars-invisible');
|
||||
|
||||
try {
|
||||
result =
|
||||
style(testElm, 'scrollbar-width') === 'none' ||
|
||||
window.getComputedStyle(testElm, '::-webkit-scrollbar').getPropertyValue('display') === 'none';
|
||||
} catch (ex) {}
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
var rtlScrollBehavior = function rtlScrollBehavior(parentElm, childElm) {
|
||||
var strHidden = 'hidden';
|
||||
style(parentElm, {
|
||||
overflowX: strHidden,
|
||||
overflowY: strHidden,
|
||||
});
|
||||
scrollLeft(parentElm, 0);
|
||||
var parentOffset = offset(parentElm);
|
||||
var childOffset = offset(childElm);
|
||||
scrollLeft(parentElm, -999);
|
||||
var childOffsetAfterScroll = offset(childElm);
|
||||
return {
|
||||
i: parentOffset.x === childOffset.x,
|
||||
n: childOffset.x !== childOffsetAfterScroll.x,
|
||||
};
|
||||
};
|
||||
|
||||
var passiveEvents = function passiveEvents() {
|
||||
var supportsPassive = false;
|
||||
|
||||
try {
|
||||
window.addEventListener(
|
||||
'test',
|
||||
null,
|
||||
Object.defineProperty({}, 'passive', {
|
||||
get: function get() {
|
||||
supportsPassive = true;
|
||||
},
|
||||
})
|
||||
);
|
||||
} catch (e) {}
|
||||
|
||||
return supportsPassive;
|
||||
};
|
||||
|
||||
var windowDPR = function windowDPR() {
|
||||
var dDPI = window.screen.deviceXDPI || 0;
|
||||
var sDPI = window.screen.logicalXDPI || 1;
|
||||
return window.devicePixelRatio || dDPI / sDPI;
|
||||
};
|
||||
|
||||
var diffBiggerThanOne = function diffBiggerThanOne(valOne, valTwo) {
|
||||
var absValOne = abs(valOne);
|
||||
var absValTwo = abs(valTwo);
|
||||
return !(absValOne === absValTwo || absValOne + 1 === absValTwo || absValOne - 1 === absValTwo);
|
||||
};
|
||||
|
||||
var _onChangedListener = new WeakMap();
|
||||
|
||||
var Environment = /*#__PURE__*/ (function () {
|
||||
function Environment() {
|
||||
_onChangedListener.set(this, {
|
||||
writable: true,
|
||||
value: void 0,
|
||||
});
|
||||
|
||||
classPrivateFieldSet(this, _onChangedListener, new Set());
|
||||
|
||||
var _self = this;
|
||||
|
||||
var _document = document,
|
||||
body = _document.body;
|
||||
var envDOM = createDOM('<div id="os-dummy-scrollbar-size"><div></div></div>');
|
||||
var envElm = envDOM[0];
|
||||
var envChildElm = envElm.firstChild;
|
||||
var nScrollBarSize = nativeScrollbarSize(body, envElm);
|
||||
var nativeScrollbarIsOverlaid = {
|
||||
x: nScrollBarSize.x === 0,
|
||||
y: nScrollBarSize.y === 0,
|
||||
};
|
||||
_self.autoUpdateLoop = false;
|
||||
_self.nativeScrollbarSize = nScrollBarSize;
|
||||
_self.nativeScrollbarIsOverlaid = nativeScrollbarIsOverlaid;
|
||||
_self.nativeScrollbarStyling = nativeScrollbarStyling(envElm);
|
||||
_self.rtlScrollBehavior = rtlScrollBehavior(envElm, envChildElm);
|
||||
_self.supportPassiveEvents = passiveEvents();
|
||||
_self.supportResizeObserver = !!jsAPI('ResizeObserver');
|
||||
removeAttr(envElm, 'style');
|
||||
removeElements(envElm);
|
||||
|
||||
if (nativeScrollbarIsOverlaid.x && nativeScrollbarIsOverlaid.y) {
|
||||
var size = windowSize();
|
||||
var dpr = windowDPR();
|
||||
|
||||
var onChangedListener = classPrivateFieldGet(this, _onChangedListener);
|
||||
|
||||
window.addEventListener('resize', function () {
|
||||
if (onChangedListener.size) {
|
||||
var sizeNew = windowSize();
|
||||
var deltaSize = {
|
||||
w: sizeNew.w - size.w,
|
||||
h: sizeNew.h - size.h,
|
||||
};
|
||||
if (deltaSize.w === 0 && deltaSize.h === 0) return;
|
||||
var deltaAbsSize = {
|
||||
w: abs(deltaSize.w),
|
||||
h: abs(deltaSize.h),
|
||||
};
|
||||
var deltaAbsRatio = {
|
||||
w: abs(round(sizeNew.w / (size.w / 100.0))),
|
||||
h: abs(round(sizeNew.h / (size.h / 100.0))),
|
||||
};
|
||||
var dprNew = windowDPR();
|
||||
var deltaIsBigger = deltaAbsSize.w > 2 && deltaAbsSize.h > 2;
|
||||
var difference = !diffBiggerThanOne(deltaAbsRatio.w, deltaAbsRatio.h);
|
||||
var dprChanged = dprNew !== dpr && dpr > 0;
|
||||
var isZoom = deltaIsBigger && difference && dprChanged;
|
||||
var oldScrollbarSize = _self.nativeScrollbarSize;
|
||||
var newScrollbarSize;
|
||||
|
||||
if (isZoom) {
|
||||
newScrollbarSize = _self.nativeScrollbarSize = nativeScrollbarSize(body, envElm);
|
||||
removeElements(envElm);
|
||||
|
||||
if (oldScrollbarSize.x !== newScrollbarSize.x || oldScrollbarSize.y !== newScrollbarSize.y) {
|
||||
onChangedListener.forEach(function (listener) {
|
||||
return listener && listener(_self);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
size = sizeNew;
|
||||
dpr = dprNew;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
var _proto = Environment.prototype;
|
||||
|
||||
_proto.addListener = function addListener(listener) {
|
||||
classPrivateFieldGet(this, _onChangedListener).add(listener);
|
||||
};
|
||||
|
||||
_proto.removeListener = function removeListener(listener) {
|
||||
classPrivateFieldGet(this, _onChangedListener).delete(listener);
|
||||
};
|
||||
|
||||
return Environment;
|
||||
})();
|
||||
|
||||
var env = new Environment();
|
||||
var index = function () {
|
||||
return [
|
||||
env,
|
||||
createDOM(
|
||||
'\
|
||||
<div class="os-host">\
|
||||
@@ -109,9 +554,6 @@
|
||||
<div class="os-scrollbar-corner"></div>\
|
||||
</div>'
|
||||
),
|
||||
a,
|
||||
b,
|
||||
c,
|
||||
];
|
||||
};
|
||||
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,201 @@
|
||||
import {
|
||||
createDOM,
|
||||
addClass,
|
||||
style,
|
||||
appendChildren,
|
||||
clientSize,
|
||||
offset,
|
||||
offsetSize,
|
||||
scrollLeft,
|
||||
jsAPI,
|
||||
XY,
|
||||
removeAttr,
|
||||
removeElements,
|
||||
windowSize,
|
||||
} from 'support';
|
||||
|
||||
type OnEnvironmentChanged = (env: Environment) => void;
|
||||
|
||||
const { abs, round } = Math;
|
||||
|
||||
const nativeScrollbarSize = (body: HTMLElement, measureElm: HTMLElement): XY => {
|
||||
appendChildren(body, measureElm);
|
||||
const cSize = clientSize(measureElm);
|
||||
const oSize = offsetSize(measureElm);
|
||||
|
||||
return {
|
||||
x: oSize.h - cSize.h,
|
||||
y: oSize.w - cSize.w,
|
||||
};
|
||||
};
|
||||
|
||||
const nativeScrollbarStyling = (testElm: HTMLElement): boolean => {
|
||||
let result = false;
|
||||
addClass(testElm, 'os-viewport-native-scrollbars-invisible');
|
||||
try {
|
||||
result =
|
||||
style(testElm, 'scrollbar-width') === 'none' || window.getComputedStyle(testElm, '::-webkit-scrollbar').getPropertyValue('display') === 'none';
|
||||
} catch (ex) {}
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
const rtlScrollBehavior = (parentElm: HTMLElement, childElm: HTMLElement): { i: boolean; n: boolean } => {
|
||||
const strHidden = 'hidden';
|
||||
style(parentElm, { overflowX: strHidden, overflowY: strHidden });
|
||||
scrollLeft(parentElm, 0);
|
||||
|
||||
const parentOffset = offset(parentElm);
|
||||
const childOffset = offset(childElm);
|
||||
scrollLeft(parentElm, -999); // https://github.com/KingSora/OverlayScrollbars/issues/187
|
||||
const childOffsetAfterScroll = offset(childElm);
|
||||
return {
|
||||
/**
|
||||
* origin direction = determines if the zero scroll position is on the left or right side
|
||||
* 'i' means 'invert' (i === true means that the axis must be inverted to be correct)
|
||||
* true = on the left side
|
||||
* false = on the right side
|
||||
*/
|
||||
i: parentOffset.x === childOffset.x,
|
||||
/**
|
||||
* negative = determines if the maximum scroll is positive or negative
|
||||
* 'n' means 'negate' (n === true means that the axis must be negated to be correct)
|
||||
* true = negative
|
||||
* false = positive
|
||||
*/
|
||||
n: childOffset.x !== childOffsetAfterScroll.x,
|
||||
};
|
||||
};
|
||||
|
||||
const passiveEvents = (): boolean => {
|
||||
let supportsPassive = false;
|
||||
try {
|
||||
/* eslint-disable */
|
||||
// @ts-ignore
|
||||
window.addEventListener(
|
||||
'test',
|
||||
null,
|
||||
Object.defineProperty({}, 'passive', {
|
||||
get: function () {
|
||||
supportsPassive = true;
|
||||
},
|
||||
})
|
||||
);
|
||||
/* eslint-enable */
|
||||
} catch (e) {}
|
||||
return supportsPassive;
|
||||
};
|
||||
|
||||
const windowDPR = (): number => {
|
||||
// eslint-disable-next-line
|
||||
// @ts-ignore
|
||||
const dDPI = window.screen.deviceXDPI || 0;
|
||||
// eslint-disable-next-line
|
||||
// @ts-ignore
|
||||
const sDPI = window.screen.logicalXDPI || 1;
|
||||
return window.devicePixelRatio || dDPI / sDPI;
|
||||
};
|
||||
|
||||
const diffBiggerThanOne = (valOne: number, valTwo: number): boolean => {
|
||||
const absValOne = abs(valOne);
|
||||
const absValTwo = abs(valTwo);
|
||||
return !(absValOne === absValTwo || absValOne + 1 === absValTwo || absValOne - 1 === absValTwo);
|
||||
};
|
||||
|
||||
export class Environment {
|
||||
#onChangedListener: Set<OnEnvironmentChanged> = new Set();
|
||||
|
||||
autoUpdateLoop!: boolean;
|
||||
|
||||
nativeScrollbarSize!: XY;
|
||||
|
||||
nativeScrollbarIsOverlaid!: XY<boolean>;
|
||||
|
||||
nativeScrollbarStyling!: boolean;
|
||||
|
||||
rtlScrollBehavior!: { n: boolean; i: boolean };
|
||||
|
||||
supportPassiveEvents!: boolean;
|
||||
|
||||
supportResizeObserver!: boolean;
|
||||
|
||||
constructor() {
|
||||
const _self = this;
|
||||
const { body } = document;
|
||||
const envDOM = createDOM('<div id="os-dummy-scrollbar-size"><div></div></div>');
|
||||
const envElm = envDOM[0] as HTMLElement;
|
||||
const envChildElm = envElm.firstChild as HTMLElement;
|
||||
|
||||
const nScrollBarSize = nativeScrollbarSize(body, envElm);
|
||||
const nativeScrollbarIsOverlaid = {
|
||||
x: nScrollBarSize.x === 0,
|
||||
y: nScrollBarSize.y === 0,
|
||||
};
|
||||
|
||||
_self.autoUpdateLoop = false;
|
||||
_self.nativeScrollbarSize = nScrollBarSize;
|
||||
_self.nativeScrollbarIsOverlaid = nativeScrollbarIsOverlaid;
|
||||
_self.nativeScrollbarStyling = nativeScrollbarStyling(envElm);
|
||||
_self.rtlScrollBehavior = rtlScrollBehavior(envElm, envChildElm);
|
||||
_self.supportPassiveEvents = passiveEvents();
|
||||
_self.supportResizeObserver = !!jsAPI('ResizeObserver');
|
||||
|
||||
removeAttr(envElm, 'style');
|
||||
removeElements(envElm);
|
||||
|
||||
if (nativeScrollbarIsOverlaid.x && nativeScrollbarIsOverlaid.y) {
|
||||
let size = windowSize();
|
||||
let dpr = windowDPR();
|
||||
const onChangedListener = this.#onChangedListener;
|
||||
|
||||
window.addEventListener('resize', () => {
|
||||
if (onChangedListener.size) {
|
||||
const sizeNew = windowSize();
|
||||
const deltaSize = {
|
||||
w: sizeNew.w - size.w,
|
||||
h: sizeNew.h - size.h,
|
||||
};
|
||||
|
||||
if (deltaSize.w === 0 && deltaSize.h === 0) return;
|
||||
|
||||
const deltaAbsSize = {
|
||||
w: abs(deltaSize.w),
|
||||
h: abs(deltaSize.h),
|
||||
};
|
||||
const deltaAbsRatio = {
|
||||
w: abs(round(sizeNew.w / (size.w / 100.0))),
|
||||
h: abs(round(sizeNew.h / (size.h / 100.0))),
|
||||
};
|
||||
const dprNew = windowDPR();
|
||||
const deltaIsBigger = deltaAbsSize.w > 2 && deltaAbsSize.h > 2;
|
||||
const difference = !diffBiggerThanOne(deltaAbsRatio.w, deltaAbsRatio.h);
|
||||
const dprChanged = dprNew !== dpr && dpr > 0;
|
||||
const isZoom = deltaIsBigger && difference && dprChanged;
|
||||
|
||||
const oldScrollbarSize = _self.nativeScrollbarSize;
|
||||
let newScrollbarSize;
|
||||
|
||||
if (isZoom) {
|
||||
newScrollbarSize = _self.nativeScrollbarSize = nativeScrollbarSize(body, envElm);
|
||||
removeElements(envElm);
|
||||
|
||||
if (oldScrollbarSize.x !== newScrollbarSize.x || oldScrollbarSize.y !== newScrollbarSize.y) {
|
||||
onChangedListener.forEach((listener) => listener && listener(_self));
|
||||
}
|
||||
}
|
||||
|
||||
size = sizeNew;
|
||||
dpr = dprNew;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
addListener(listener: OnEnvironmentChanged): void {
|
||||
this.#onChangedListener.add(listener);
|
||||
}
|
||||
|
||||
removeListener(listener: OnEnvironmentChanged): void {
|
||||
this.#onChangedListener.delete(listener);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
export * from 'environment/environment';
|
||||
@@ -1,14 +1,15 @@
|
||||
import { createDOM } from 'support/dom';
|
||||
import { Environment } from 'environment';
|
||||
|
||||
const abc = {
|
||||
a: 1,
|
||||
b: 1,
|
||||
c: 1,
|
||||
};
|
||||
|
||||
const env = new Environment();
|
||||
export default () => {
|
||||
const { a, b, c } = abc;
|
||||
return [
|
||||
env,
|
||||
createDOM(
|
||||
'\
|
||||
<div class="os-host">\
|
||||
@@ -33,8 +34,5 @@ export default () => {
|
||||
<div class="os-scrollbar-corner"></div>\
|
||||
</div>'
|
||||
),
|
||||
a,
|
||||
b,
|
||||
c,
|
||||
];
|
||||
};
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
import { WH } from 'support/dom';
|
||||
|
||||
const zeroDomRect = new DOMRect();
|
||||
const zeroObj: WH = {
|
||||
w: 0,
|
||||
h: 0,
|
||||
};
|
||||
|
||||
export const windowSize = (): WH => ({
|
||||
w: window.innerWidth,
|
||||
h: window.innerHeight,
|
||||
});
|
||||
|
||||
export const offsetSize = (elm: HTMLElement | null): WH =>
|
||||
elm
|
||||
? {
|
||||
w: elm.offsetWidth,
|
||||
h: elm.offsetHeight,
|
||||
}
|
||||
: zeroObj;
|
||||
|
||||
export const clientSize = (elm: HTMLElement | null): WH =>
|
||||
elm
|
||||
? {
|
||||
w: elm.clientWidth,
|
||||
h: elm.clientHeight,
|
||||
}
|
||||
: zeroObj;
|
||||
|
||||
export const getBoundingClientRect = (elm: HTMLElement | null): DOMRect => (elm ? elm.getBoundingClientRect() : zeroDomRect);
|
||||
@@ -1,7 +1,18 @@
|
||||
export * from 'support/dom/attribute';
|
||||
export * from 'support/dom/class';
|
||||
export * from 'support/dom/create';
|
||||
export * from 'support/dom/dimensions';
|
||||
export * from 'support/dom/style';
|
||||
export * from 'support/dom/manipulation';
|
||||
export * from 'support/dom/offset';
|
||||
export * from 'support/dom/traversal';
|
||||
|
||||
export interface XY<T = number> {
|
||||
x: T;
|
||||
y: T;
|
||||
}
|
||||
|
||||
export interface WH<T = number> {
|
||||
w: T;
|
||||
h: T;
|
||||
}
|
||||
|
||||
@@ -1,22 +1,24 @@
|
||||
const zeroObj = {
|
||||
left: 0,
|
||||
top: 0,
|
||||
import { XY } from 'support/dom';
|
||||
|
||||
const zeroObj: XY = {
|
||||
x: 0,
|
||||
y: 0,
|
||||
};
|
||||
|
||||
export const offset = (elm: HTMLElement | null) => {
|
||||
export const offset = (elm: HTMLElement | null): XY => {
|
||||
const rect = elm ? elm.getBoundingClientRect() : 0;
|
||||
return rect
|
||||
? {
|
||||
left: rect.left + window.pageYOffset,
|
||||
top: rect.top + window.pageXOffset,
|
||||
x: rect.left + window.pageYOffset,
|
||||
y: rect.top + window.pageXOffset,
|
||||
}
|
||||
: zeroObj;
|
||||
};
|
||||
|
||||
export const position = (elm: HTMLElement | null) =>
|
||||
export const position = (elm: HTMLElement | null): XY =>
|
||||
elm
|
||||
? {
|
||||
left: elm.offsetLeft,
|
||||
top: elm.offsetTop,
|
||||
x: elm.offsetLeft,
|
||||
y: elm.offsetTop,
|
||||
}
|
||||
: zeroObj;
|
||||
|
||||
@@ -6,15 +6,15 @@ describe('dom offset', () => {
|
||||
test('returns correct object with DOM element', () => {
|
||||
const result = offset(document.body);
|
||||
expect(isPlainObject(result)).toBe(true);
|
||||
expect(isNumber(result.left)).toBe(true);
|
||||
expect(isNumber(result.top)).toBe(true);
|
||||
expect(isNumber(result.x)).toBe(true);
|
||||
expect(isNumber(result.y)).toBe(true);
|
||||
});
|
||||
|
||||
test('returns correct object with null', () => {
|
||||
const result = offset(null);
|
||||
expect(isPlainObject(result)).toBe(true);
|
||||
expect(result.left).toBe(0);
|
||||
expect(result.top).toBe(0);
|
||||
expect(result.x).toBe(0);
|
||||
expect(result.y).toBe(0);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -22,15 +22,15 @@ describe('dom offset', () => {
|
||||
test('returns correct object with DOM element', () => {
|
||||
const result = position(document.body);
|
||||
expect(isPlainObject(result)).toBe(true);
|
||||
expect(isNumber(result.left)).toBe(true);
|
||||
expect(isNumber(result.top)).toBe(true);
|
||||
expect(isNumber(result.x)).toBe(true);
|
||||
expect(isNumber(result.y)).toBe(true);
|
||||
});
|
||||
|
||||
test('returns correct object with null', () => {
|
||||
const result = position(null);
|
||||
expect(isPlainObject(result)).toBe(true);
|
||||
expect(result.left).toBe(0);
|
||||
expect(result.top).toBe(0);
|
||||
expect(result.x).toBe(0);
|
||||
expect(result.y).toBe(0);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
import { XY } from 'support';
|
||||
declare type OnEnvironmentChanged = (env: Environment) => void;
|
||||
export declare class Environment {
|
||||
#private;
|
||||
autoUpdateLoop: boolean;
|
||||
nativeScrollbarSize: XY;
|
||||
nativeScrollbarIsOverlaid: XY<boolean>;
|
||||
nativeScrollbarStyling: boolean;
|
||||
rtlScrollBehavior: {
|
||||
n: boolean;
|
||||
i: boolean;
|
||||
};
|
||||
supportPassiveEvents: boolean;
|
||||
supportResizeObserver: boolean;
|
||||
constructor();
|
||||
addListener(listener: OnEnvironmentChanged): void;
|
||||
removeListener(listener: OnEnvironmentChanged): void;
|
||||
}
|
||||
export {};
|
||||
@@ -0,0 +1 @@
|
||||
export * from 'environment/environment';
|
||||
+2
-1
@@ -1,2 +1,3 @@
|
||||
declare const _default: () => (number | readonly Node[])[];
|
||||
import { Environment } from 'environment';
|
||||
declare const _default: () => (Environment | readonly Node[])[];
|
||||
export default _default;
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
import { WH } from 'support/dom';
|
||||
export declare const windowSize: () => WH;
|
||||
export declare const offsetSize: (elm: HTMLElement | null) => WH;
|
||||
export declare const clientSize: (elm: HTMLElement | null) => WH;
|
||||
export declare const getBoundingClientRect: (elm: HTMLElement | null) => DOMRect;
|
||||
@@ -1,7 +1,16 @@
|
||||
export * from 'support/dom/attribute';
|
||||
export * from 'support/dom/class';
|
||||
export * from 'support/dom/create';
|
||||
export * from 'support/dom/dimensions';
|
||||
export * from 'support/dom/style';
|
||||
export * from 'support/dom/manipulation';
|
||||
export * from 'support/dom/offset';
|
||||
export * from 'support/dom/traversal';
|
||||
export interface XY<T = number> {
|
||||
x: T;
|
||||
y: T;
|
||||
}
|
||||
export interface WH<T = number> {
|
||||
w: T;
|
||||
h: T;
|
||||
}
|
||||
|
||||
@@ -1,8 +1,3 @@
|
||||
export declare const offset: (elm: HTMLElement | null) => {
|
||||
left: number;
|
||||
top: number;
|
||||
};
|
||||
export declare const position: (elm: HTMLElement | null) => {
|
||||
left: number;
|
||||
top: number;
|
||||
};
|
||||
import { XY } from 'support/dom';
|
||||
export declare const offset: (elm: HTMLElement | null) => XY;
|
||||
export declare const position: (elm: HTMLElement | null) => XY;
|
||||
|
||||
Reference in New Issue
Block a user