improve code for fractional sizes

This commit is contained in:
Rene Haas
2022-07-02 11:36:28 +02:00
parent 14a49a52ff
commit bea88a9d9b
17 changed files with 800 additions and 705 deletions
+1
View File
@@ -94,6 +94,7 @@ module.exports = {
'no-void': 'off', 'no-void': 'off',
'no-empty-function': 'off', 'no-empty-function': 'off',
'no-new-func': 'off', 'no-new-func': 'off',
'import/order': 'off',
}, },
}, },
{ {
+2
View File
@@ -60,11 +60,13 @@ module.exports = (testDir, onListening = null) => {
port, port,
onListening, onListening,
}), }),
/*
rollupPluginLivereload({ rollupPluginLivereload({
watch: dist, watch: dist,
port: port - 1, port: port - 1,
verbose: false, verbose: false,
}), }),
*/
] ]
: []), : []),
], ],
+289 -244
View File
@@ -360,12 +360,13 @@ const classListAction = (elm, className, action) => {
return result; return result;
}; };
const addClass = (elm, className) => {
classListAction(elm, className, (classList, clazz) => classList.add(clazz));
};
const removeClass = (elm, className) => { const removeClass = (elm, className) => {
classListAction(elm, className, (classList, clazz) => classList.remove(clazz)); classListAction(elm, className, (classList, clazz) => classList.remove(clazz));
}; };
const addClass = (elm, className) => {
classListAction(elm, className, (classList, clazz) => classList.add(clazz));
return removeClass.bind(0, elm, className);
};
const diffClass = (classNameA, classNameB) => { const diffClass = (classNameA, classNameB) => {
const classNameASplit = classNameA && classNameA.split(' '); const classNameASplit = classNameA && classNameA.split(' ');
const classNameBSplit = classNameB && classNameB.split(' '); const classNameBSplit = classNameB && classNameB.split(' ');
@@ -383,77 +384,6 @@ const diffClass = (classNameA, classNameB) => {
return keys(tempObj); return keys(tempObj);
}; };
const zeroObj$1 = {
w: 0,
h: 0
};
const windowSize = () => ({
w: window.innerWidth,
h: window.innerHeight
});
const offsetSize = elm => elm ? {
w: elm.offsetWidth,
h: elm.offsetHeight
} : zeroObj$1;
const clientSize = elm => elm ? {
w: elm.clientWidth,
h: elm.clientHeight
} : zeroObj$1;
const scrollSize = elm => elm ? {
w: elm.scrollWidth,
h: elm.scrollHeight
} : zeroObj$1;
const getBoundingClientRect = elm => elm.getBoundingClientRect();
let passiveEventsSupport;
const supportPassiveEvents = () => {
if (isUndefined(passiveEventsSupport)) {
passiveEventsSupport = false;
try {
window.addEventListener('test', null, Object.defineProperty({}, 'passive', {
get: function () {
passiveEventsSupport = true;
}
}));
} catch (e) {}
}
return passiveEventsSupport;
};
const splitEventNames = eventNames => eventNames.split(' ');
const off = (target, eventNames, listener, capture) => {
each(splitEventNames(eventNames), eventName => {
target.removeEventListener(eventName, listener, capture);
});
};
const on = (target, eventNames, listener, options) => {
const doSupportPassiveEvents = supportPassiveEvents();
const passive = doSupportPassiveEvents && options && options._passive || false;
const capture = options && options._capture || false;
const once = options && options._once || false;
const offListeners = [];
const nativeOptions = doSupportPassiveEvents ? {
passive,
capture
} : capture;
each(splitEventNames(eventNames), eventName => {
const finalListener = once ? evt => {
target.removeEventListener(eventName, finalListener, capture);
listener && listener(evt);
} : listener;
push(offListeners, off.bind(null, target, eventName, finalListener, capture));
target.addEventListener(eventName, finalListener, nativeOptions);
});
return runEach.bind(0, offListeners);
};
const stopPropagation = evt => evt.stopPropagation();
const preventDefault = evt => evt.preventDefault();
const stopAndPrevent = evt => stopPropagation(evt) || preventDefault(evt);
const equal = (a, b, props, propMutation) => { const equal = (a, b, props, propMutation) => {
if (a && b) { if (a && b) {
let result = true; let result = true;
@@ -603,6 +533,85 @@ const topRightBottomLeft = (elm, propertyPrefix, propertySuffix) => {
}; };
}; };
const zeroObj$1 = {
w: 0,
h: 0
};
const windowSize = () => ({
w: window.innerWidth,
h: window.innerHeight
});
const offsetSize = elm => elm ? {
w: elm.offsetWidth,
h: elm.offsetHeight
} : zeroObj$1;
const clientSize = elm => elm ? {
w: elm.clientWidth,
h: elm.clientHeight
} : zeroObj$1;
const scrollSize = elm => elm ? {
w: elm.scrollWidth,
h: elm.scrollHeight
} : zeroObj$1;
const fractionalSize = elm => {
const cssHeight = parseFloat(style(elm, 'height')) || 0;
const cssWidth = parseFloat(style(elm, 'height')) || 0;
return {
w: cssWidth - Math.round(cssWidth),
h: cssHeight - Math.round(cssHeight)
};
};
const getBoundingClientRect = elm => elm.getBoundingClientRect();
let passiveEventsSupport;
const supportPassiveEvents = () => {
if (isUndefined(passiveEventsSupport)) {
passiveEventsSupport = false;
try {
window.addEventListener('test', null, Object.defineProperty({}, 'passive', {
get: function () {
passiveEventsSupport = true;
}
}));
} catch (e) {}
}
return passiveEventsSupport;
};
const splitEventNames = eventNames => eventNames.split(' ');
const off = (target, eventNames, listener, capture) => {
each(splitEventNames(eventNames), eventName => {
target.removeEventListener(eventName, listener, capture);
});
};
const on = (target, eventNames, listener, options) => {
const doSupportPassiveEvents = supportPassiveEvents();
const passive = doSupportPassiveEvents && options && options._passive || false;
const capture = options && options._capture || false;
const once = options && options._once || false;
const offListeners = [];
const nativeOptions = doSupportPassiveEvents ? {
passive,
capture
} : capture;
each(splitEventNames(eventNames), eventName => {
const finalListener = once ? evt => {
target.removeEventListener(eventName, finalListener, capture);
listener && listener(evt);
} : listener;
push(offListeners, off.bind(null, target, eventName, finalListener, capture));
target.addEventListener(eventName, finalListener, nativeOptions);
});
return runEach.bind(0, offListeners);
};
const stopPropagation = evt => evt.stopPropagation();
const preventDefault = evt => evt.preventDefault();
const stopAndPrevent = evt => stopPropagation(evt) || preventDefault(evt);
const zeroObj = { const zeroObj = {
x: 0, x: 0,
y: 0 y: 0
@@ -675,35 +684,6 @@ const createState = initialState => {
}]; }];
}; };
function getDefaultExportFromCjs (x) {
return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
}
var _extends$1 = {exports: {}};
(function (module) {
function _extends() {
module.exports = _extends = Object.assign ? Object.assign.bind() : 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;
}, module.exports.__esModule = true, module.exports["default"] = module.exports;
return _extends.apply(this, arguments);
}
module.exports = _extends, module.exports.__esModule = true, module.exports["default"] = module.exports;
})(_extends$1);
const _extends = getDefaultExportFromCjs(_extends$1.exports);
const classNameEnvironment = 'os-environment'; const classNameEnvironment = 'os-environment';
const classNameEnvironmentFlexboxGlue = `${classNameEnvironment}-flexbox-glue`; const classNameEnvironmentFlexboxGlue = `${classNameEnvironment}-flexbox-glue`;
const classNameEnvironmentFlexboxGlueMax = `${classNameEnvironmentFlexboxGlue}-max`; const classNameEnvironmentFlexboxGlueMax = `${classNameEnvironmentFlexboxGlue}-max`;
@@ -797,34 +777,36 @@ const getOptionsDiff = (currOptions, newOptions) => {
let environmentInstance; let environmentInstance;
const { const {
abs: abs$1, abs,
round: round$1 round: round$1
} = Math; } = Math;
const diffBiggerThanOne = (valOne, valTwo) => { const diffBiggerThanOne = (valOne, valTwo) => {
const absValOne = abs$1(valOne); const absValOne = abs(valOne);
const absValTwo = abs$1(valTwo); const absValTwo = abs(valTwo);
return !(absValOne === absValTwo || absValOne + 1 === absValTwo || absValOne - 1 === absValTwo); return !(absValOne === absValTwo || absValOne + 1 === absValTwo || absValOne - 1 === absValTwo);
}; };
const getNativeScrollbarSize = (body, measureElm) => { const getNativeScrollbarSize = (body, measureElm, measureElmChild) => {
appendChildren(body, measureElm); appendChildren(body, measureElm);
const cSize = clientSize(measureElm); const cSize = clientSize(measureElm);
const oSize = offsetSize(measureElm); const oSize = offsetSize(measureElm);
const fSize = fractionalSize(measureElmChild);
return { return {
x: oSize.h - cSize.h, x: oSize.h - cSize.h + fSize.h,
y: oSize.w - cSize.w y: oSize.w - cSize.w + fSize.w
}; };
}; };
const getNativeScrollbarStyling = testElm => { const getNativeScrollbarStyling = testElm => {
let result = false; let result = false;
addClass(testElm, classNameViewportScrollbarStyling); const revertClass = addClass(testElm, classNameViewportScrollbarStyling);
try { try {
result = style(testElm, cssProperty('scrollbar-width')) === 'none' || window.getComputedStyle(testElm, '::-webkit-scrollbar').getPropertyValue('display') === 'none'; result = style(testElm, cssProperty('scrollbar-width')) === 'none' || window.getComputedStyle(testElm, '::-webkit-scrollbar').getPropertyValue('display') === 'none';
} catch (ex) {} } catch (ex) {}
revertClass();
return result; return result;
}; };
@@ -847,14 +829,16 @@ const getRtlScrollBehavior = (parentElm, childElm) => {
}; };
const getFlexboxGlue = (parentElm, childElm) => { const getFlexboxGlue = (parentElm, childElm) => {
addClass(parentElm, classNameEnvironmentFlexboxGlue); const revertFbxGlue = addClass(parentElm, classNameEnvironmentFlexboxGlue);
const minOffsetsizeParent = getBoundingClientRect(parentElm); const minOffsetsizeParent = getBoundingClientRect(parentElm);
const minOffsetsize = getBoundingClientRect(childElm); const minOffsetsize = getBoundingClientRect(childElm);
const supportsMin = equalBCRWH(minOffsetsize, minOffsetsizeParent, true); const supportsMin = equalBCRWH(minOffsetsize, minOffsetsizeParent, true);
addClass(parentElm, classNameEnvironmentFlexboxGlueMax); const revertFbxGlueMax = addClass(parentElm, classNameEnvironmentFlexboxGlueMax);
const maxOffsetsizeParent = getBoundingClientRect(parentElm); const maxOffsetsizeParent = getBoundingClientRect(parentElm);
const maxOffsetsize = getBoundingClientRect(childElm); const maxOffsetsize = getBoundingClientRect(childElm);
const supportsMax = equalBCRWH(maxOffsetsize, maxOffsetsizeParent, true); const supportsMax = equalBCRWH(maxOffsetsize, maxOffsetsizeParent, true);
revertFbxGlue();
revertFbxGlueMax();
return supportsMin && supportsMax; return supportsMin && supportsMax;
}; };
@@ -867,8 +851,8 @@ const getWindowDPR = () => {
const getDefaultInitializationStrategy = nativeScrollbarStyling => ({ const getDefaultInitializationStrategy = nativeScrollbarStyling => ({
_host: null, _host: null,
_viewport: null, _viewport: null,
_padding: null, _padding: !nativeScrollbarStyling,
_content: null, _content: false,
_scrollbarsSlot: null _scrollbarsSlot: null
}); });
@@ -880,15 +864,18 @@ const createEnvironment = () => {
const envElm = envDOM[0]; const envElm = envDOM[0];
const envChildElm = envElm.firstChild; const envChildElm = envElm.firstChild;
const onChangedListener = new Set(); const onChangedListener = new Set();
const nativeScrollbarSize = getNativeScrollbarSize(body, envElm); const [updateNativeScrollbarSizeCache, getNativeScrollbarSizeCache] = createCache({
_initialValue: getNativeScrollbarSize(body, envElm, envChildElm),
_equal: equalXY
});
const [nativeScrollbarSize] = getNativeScrollbarSizeCache();
const nativeScrollbarStyling = getNativeScrollbarStyling(envElm); const nativeScrollbarStyling = getNativeScrollbarStyling(envElm);
const nativeScrollbarIsOverlaid = { const nativeScrollbarIsOverlaid = {
x: nativeScrollbarSize.x === 0, x: nativeScrollbarSize.x === 0,
y: nativeScrollbarSize.y === 0 y: nativeScrollbarSize.y === 0
}; };
const defaultInitializationStrategy = getDefaultInitializationStrategy(); const initializationStrategy = getDefaultInitializationStrategy(nativeScrollbarStyling);
let initializationStrategy = defaultInitializationStrategy; const defaultDefaultOptions = assignDeep({}, defaultOptions);
let defaultDefaultOptions = defaultOptions;
const env = { const env = {
_nativeScrollbarSize: nativeScrollbarSize, _nativeScrollbarSize: nativeScrollbarSize,
_nativeScrollbarIsOverlaid: nativeScrollbarIsOverlaid, _nativeScrollbarIsOverlaid: nativeScrollbarIsOverlaid,
@@ -902,20 +889,20 @@ const createEnvironment = () => {
return () => onChangedListener.delete(listener); return () => onChangedListener.delete(listener);
}, },
_getInitializationStrategy: () => _extends({}, initializationStrategy), _getInitializationStrategy: assignDeep.bind(0, {}, initializationStrategy),
_setInitializationStrategy(newInitializationStrategy) { _setInitializationStrategy(newInitializationStrategy) {
initializationStrategy = assignDeep({}, initializationStrategy, newInitializationStrategy); assignDeep(initializationStrategy, newInitializationStrategy);
}, },
_getDefaultOptions: () => _extends({}, defaultDefaultOptions), _getDefaultOptions: assignDeep.bind(0, {}, defaultDefaultOptions),
_setDefaultOptions(newDefaultOptions) { _setDefaultOptions(newDefaultOptions) {
defaultDefaultOptions = assignDeep({}, defaultDefaultOptions, newDefaultOptions); assignDeep(defaultDefaultOptions, newDefaultOptions);
}, },
_defaultInitializationStrategy: defaultInitializationStrategy, _defaultInitializationStrategy: assignDeep({}, initializationStrategy),
_defaultDefaultOptions: defaultDefaultOptions _defaultDefaultOptions: assignDeep({}, defaultDefaultOptions)
}; };
removeAttr(envElm, 'style'); removeAttr(envElm, 'style');
removeElements(envElm); removeElements(envElm);
@@ -923,7 +910,6 @@ const createEnvironment = () => {
if (!nativeScrollbarStyling && (!nativeScrollbarIsOverlaid.x || !nativeScrollbarIsOverlaid.y)) { if (!nativeScrollbarStyling && (!nativeScrollbarIsOverlaid.x || !nativeScrollbarIsOverlaid.y)) {
let size = windowSize(); let size = windowSize();
let dpr = getWindowDPR(); let dpr = getWindowDPR();
let scrollbarSize = nativeScrollbarSize;
window.addEventListener('resize', () => { window.addEventListener('resize', () => {
if (onChangedListener.size) { if (onChangedListener.size) {
const sizeNew = windowSize(); const sizeNew = windowSize();
@@ -933,12 +919,12 @@ const createEnvironment = () => {
}; };
if (deltaSize.w === 0 && deltaSize.h === 0) return; if (deltaSize.w === 0 && deltaSize.h === 0) return;
const deltaAbsSize = { const deltaAbsSize = {
w: abs$1(deltaSize.w), w: abs(deltaSize.w),
h: abs$1(deltaSize.h) h: abs(deltaSize.h)
}; };
const deltaAbsRatio = { const deltaAbsRatio = {
w: abs$1(round$1(sizeNew.w / (size.w / 100.0))), w: abs(round$1(sizeNew.w / (size.w / 100.0))),
h: abs$1(round$1(sizeNew.h / (size.h / 100.0))) h: abs(round$1(sizeNew.h / (size.h / 100.0)))
}; };
const dprNew = getWindowDPR(); const dprNew = getWindowDPR();
const deltaIsBigger = deltaAbsSize.w > 2 && deltaAbsSize.h > 2; const deltaIsBigger = deltaAbsSize.w > 2 && deltaAbsSize.h > 2;
@@ -947,16 +933,13 @@ const createEnvironment = () => {
const isZoom = deltaIsBigger && difference && dprChanged; const isZoom = deltaIsBigger && difference && dprChanged;
if (isZoom) { if (isZoom) {
const newScrollbarSize = getNativeScrollbarSize(body, envElm); const [scrollbarSize, scrollbarSizeChanged] = updateNativeScrollbarSizeCache(getNativeScrollbarSize(body, envElm, envChildElm));
environmentInstance._nativeScrollbarSize.x = newScrollbarSize.x; assignDeep(environmentInstance._nativeScrollbarSize, scrollbarSize);
environmentInstance._nativeScrollbarSize.y = newScrollbarSize.y;
removeElements(envElm); removeElements(envElm);
if (scrollbarSize.x !== newScrollbarSize.x || scrollbarSize.y !== newScrollbarSize.y) { if (scrollbarSizeChanged) {
runEach(onChangedListener); runEach(onChangedListener);
} }
scrollbarSize = newScrollbarSize;
} }
size = sizeNew; size = sizeNew;
@@ -1005,14 +988,9 @@ const staticCreationFromStrategy = (target, initializationValue, strategy, eleme
return result || createDiv(elementClass); return result || createDiv(elementClass);
}; };
const dynamicCreationFromStrategy = (target, initializationValue, strategy, elementClass, defaultValue) => { const dynamicCreationFromStrategy = (target, initializationValue, strategy, elementClass) => {
const takeInitializationValue = isBoolean(initializationValue) || initializationValue; const takeInitializationValue = isBoolean(initializationValue) || initializationValue;
const result = takeInitializationValue ? initializationValue : isFunction(strategy) ? strategy(target) : strategy; const result = takeInitializationValue ? initializationValue : isFunction(strategy) ? strategy(target) : strategy;
if (result === null) {
return defaultValue ? createDiv(elementClass) : false;
}
return result === true ? createDiv(elementClass) : result; return result === true ? createDiv(elementClass) : result;
}; };
@@ -1041,8 +1019,8 @@ const createStructureSetupElements = target => {
_target: targetElement, _target: targetElement,
_host: isTextarea ? staticCreationFromStrategy(targetElement, targetStructureInitialization.host, hostInitializationStrategy, classNameHost) : targetElement, _host: isTextarea ? staticCreationFromStrategy(targetElement, targetStructureInitialization.host, hostInitializationStrategy, classNameHost) : targetElement,
_viewport: staticCreationFromStrategy(targetElement, targetStructureInitialization.viewport, viewportInitializationStrategy, classNameViewport), _viewport: staticCreationFromStrategy(targetElement, targetStructureInitialization.viewport, viewportInitializationStrategy, classNameViewport),
_padding: dynamicCreationFromStrategy(targetElement, targetStructureInitialization.padding, paddingInitializationStrategy, classNamePadding, !_nativeScrollbarStyling), _padding: dynamicCreationFromStrategy(targetElement, targetStructureInitialization.padding, paddingInitializationStrategy, classNamePadding),
_content: dynamicCreationFromStrategy(targetElement, targetStructureInitialization.content, contentInitializationStrategy, classNameContent, false), _content: dynamicCreationFromStrategy(targetElement, targetStructureInitialization.content, contentInitializationStrategy, classNameContent),
_viewportArrange: createUniqueViewportArrangeElement(), _viewportArrange: createUniqueViewportArrangeElement(),
_windowElm: wnd, _windowElm: wnd,
_documentElm: ownerDocument, _documentElm: ownerDocument,
@@ -1125,32 +1103,35 @@ const createStructureSetupElements = target => {
return [evaluatedTargetObj, runEach.bind(0, destroyFns)]; return [evaluatedTargetObj, runEach.bind(0, destroyFns)];
}; };
const createTrinsicUpdate = structureSetupElements => { const createTrinsicUpdate = (structureSetupElements, state) => {
const { const {
_content _content
} = structureSetupElements; } = structureSetupElements;
const [getState] = state;
return updateHints => { return updateHints => {
const { const {
_heightIntrinsic _heightIntrinsic
} = getState();
const {
_heightIntrinsicChanged
} = updateHints; } = updateHints;
const [heightIntrinsic, heightIntrinsicChanged] = _heightIntrinsic;
if (heightIntrinsicChanged) { if (_heightIntrinsicChanged) {
style(_content, { style(_content, {
height: heightIntrinsic ? '' : '100%', height: _heightIntrinsic ? '' : '100%',
display: heightIntrinsic ? '' : 'inline' display: _heightIntrinsic ? '' : 'inline'
}); });
} }
return { return {
_sizeChanged: heightIntrinsicChanged, _sizeChanged: _heightIntrinsicChanged,
_contentMutation: heightIntrinsicChanged _contentMutation: _heightIntrinsicChanged
}; };
}; };
}; };
const createPaddingUpdate = (structureSetupElements, state) => { const createPaddingUpdate = (structureSetupElements, state) => {
const [, setState] = state; const [getState, setState] = state;
const { const {
_host, _host,
_padding, _padding,
@@ -1166,12 +1147,14 @@ const createPaddingUpdate = (structureSetupElements, state) => {
_nativeScrollbarStyling, _nativeScrollbarStyling,
_flexboxGlue _flexboxGlue
} = getEnvironment(); } = getEnvironment();
const {
_directionIsRTL
} = getState();
const { const {
_sizeChanged, _sizeChanged,
_directionIsRTL, _contentMutation,
_contentMutation _directionChanged
} = updateHints; } = updateHints;
const [directionIsRTL, directionChanged] = _directionIsRTL;
const [paddingAbsolute, paddingAbsoluteChanged] = checkOption('paddingAbsolute'); const [paddingAbsolute, paddingAbsoluteChanged] = checkOption('paddingAbsolute');
const contentMutation = !_flexboxGlue && _contentMutation; const contentMutation = !_flexboxGlue && _contentMutation;
@@ -1179,19 +1162,19 @@ const createPaddingUpdate = (structureSetupElements, state) => {
[padding, paddingChanged] = updatePaddingCache(force); [padding, paddingChanged] = updatePaddingCache(force);
} }
const paddingStyleChanged = paddingAbsoluteChanged || directionChanged || paddingChanged; const paddingStyleChanged = paddingAbsoluteChanged || _directionChanged || paddingChanged;
if (paddingStyleChanged) { if (paddingStyleChanged) {
const paddingRelative = !paddingAbsolute || !_padding && !_nativeScrollbarStyling; const paddingRelative = !paddingAbsolute || !_padding && !_nativeScrollbarStyling;
const paddingHorizontal = padding.r + padding.l; const paddingHorizontal = padding.r + padding.l;
const paddingVertical = padding.t + padding.b; const paddingVertical = padding.t + padding.b;
const paddingStyle = { const paddingStyle = {
marginRight: paddingRelative && !directionIsRTL ? -paddingHorizontal : 0, marginRight: paddingRelative && !_directionIsRTL ? -paddingHorizontal : 0,
marginBottom: paddingRelative ? -paddingVertical : 0, marginBottom: paddingRelative ? -paddingVertical : 0,
marginLeft: paddingRelative && directionIsRTL ? -paddingHorizontal : 0, marginLeft: paddingRelative && _directionIsRTL ? -paddingHorizontal : 0,
top: paddingRelative ? -padding.t : 0, top: paddingRelative ? -padding.t : 0,
right: paddingRelative ? directionIsRTL ? -padding.r : 'auto' : 0, right: paddingRelative ? _directionIsRTL ? -padding.r : 'auto' : 0,
left: paddingRelative ? directionIsRTL ? 'auto' : -padding.l : 0, left: paddingRelative ? _directionIsRTL ? 'auto' : -padding.l : 0,
width: paddingRelative ? `calc(100% + ${paddingHorizontal}px)` : '' width: paddingRelative ? `calc(100% + ${paddingHorizontal}px)` : ''
}; };
const viewportStyle = { const viewportStyle = {
@@ -1217,7 +1200,6 @@ const createPaddingUpdate = (structureSetupElements, state) => {
const { const {
max, max,
abs,
round round
} = Math; } = Math;
const overlaidScrollbarsHideOffset = 42; const overlaidScrollbarsHideOffset = 42;
@@ -1236,17 +1218,6 @@ const xyCacheOptions = {
} }
}; };
const sizeFraction = elm => {
const viewportOffsetSize = offsetSize(elm);
const viewportRect = getBoundingClientRect(elm);
return {
w: viewportRect.width - viewportOffsetSize.w,
h: viewportRect.height - viewportOffsetSize.h
};
};
const fractionalPixelRatioTollerance = () => window.devicePixelRatio % 1 === 0 ? 0 : 1;
const setAxisOverflowStyle = (horizontal, overflowAmount, behavior, styleObj) => { const setAxisOverflowStyle = (horizontal, overflowAmount, behavior, styleObj) => {
const overflowKey = horizontal ? 'overflowX' : 'overflowY'; const overflowKey = horizontal ? 'overflowX' : 'overflowY';
const behaviorIsVisible = behavior.indexOf('visible') === 0; const behaviorIsVisible = behavior.indexOf('visible') === 0;
@@ -1268,10 +1239,18 @@ const setAxisOverflowStyle = (horizontal, overflowAmount, behavior, styleObj) =>
}; };
}; };
const getOverflowAmount = (viewportScrollSize, viewportClientSize, viewportSizeFraction) => ({ const getOverflowAmount = (viewportScrollSize, viewportClientSize, sizeFraction) => {
w: max(0, round(max(0, viewportScrollSize.w - viewportClientSize.w) - (fractionalPixelRatioTollerance() || max(0, viewportSizeFraction.w)))), const condition = raw => window.devicePixelRatio % 2 !== 0 ? raw > 1 : raw > 0;
h: max(0, round(max(0, viewportScrollSize.h - viewportClientSize.h) - (fractionalPixelRatioTollerance() || max(0, viewportSizeFraction.h))))
}); const amount = {
w: max(0, viewportScrollSize.w - viewportClientSize.w - max(0, sizeFraction.w)),
h: max(0, viewportScrollSize.h - viewportClientSize.h - max(0, sizeFraction.h))
};
return {
w: condition(amount.w) ? amount.w : 0,
h: condition(amount.h) ? amount.h : 0
};
};
const createOverflowUpdate = (structureSetupElements, state) => { const createOverflowUpdate = (structureSetupElements, state) => {
const [getState, setState] = state; const [getState, setState] = state;
@@ -1287,7 +1266,7 @@ const createOverflowUpdate = (structureSetupElements, state) => {
_nativeScrollbarIsOverlaid _nativeScrollbarIsOverlaid
} = getEnvironment(); } = getEnvironment();
const doViewportArrange = !_nativeScrollbarStyling && (_nativeScrollbarIsOverlaid.x || _nativeScrollbarIsOverlaid.y); const doViewportArrange = !_nativeScrollbarStyling && (_nativeScrollbarIsOverlaid.x || _nativeScrollbarIsOverlaid.y);
const [updateViewportSizeFraction, getCurrentViewportSizeFraction] = createCache(whCacheOptions, sizeFraction.bind(0, _viewport)); const [updateSizeFraction, getCurrentSizeFraction] = createCache(whCacheOptions, fractionalSize.bind(0, _host));
const [updateViewportScrollSizeCache, getCurrentViewportScrollSizeCache] = createCache(whCacheOptions, scrollSize.bind(0, _viewport)); const [updateViewportScrollSizeCache, getCurrentViewportScrollSizeCache] = createCache(whCacheOptions, scrollSize.bind(0, _viewport));
const [updateOverflowAmountCache, getCurrentOverflowAmountCache] = createCache(whCacheOptions); const [updateOverflowAmountCache, getCurrentOverflowAmountCache] = createCache(whCacheOptions);
const [updateOverflowScrollCache] = createCache(xyCacheOptions); const [updateOverflowScrollCache] = createCache(xyCacheOptions);
@@ -1306,11 +1285,11 @@ const createOverflowUpdate = (structureSetupElements, state) => {
_overflowScroll, _overflowScroll,
_scrollbarsHideOffset _scrollbarsHideOffset
} = viewportOverflowState; } = viewportOverflowState;
const hostSizeFraction = sizeFraction(_host); const hostCssHeight = parseFloat(style(_host, 'height'));
const hostClientSize = clientSize(_host); const hostClientSize = clientSize(_host);
const isContentBox = style(_viewport, 'boxSizing') === 'content-box'; const isContentBox = style(_viewport, 'boxSizing') === 'content-box';
const paddingVertical = _paddingAbsolute || isContentBox ? _padding.b + _padding.t : 0; const paddingVertical = _paddingAbsolute || isContentBox ? _padding.b + _padding.t : 0;
const fractionalClientHeight = hostClientSize.h + (abs(hostSizeFraction.h) < 1 ? hostSizeFraction.h : 0); const fractionalClientHeight = hostClientSize.h + (hostCssHeight - round(hostCssHeight));
const subtractXScrollbar = !(_nativeScrollbarIsOverlaid.x && isContentBox); const subtractXScrollbar = !(_nativeScrollbarIsOverlaid.x && isContentBox);
style(_viewport, { style(_viewport, {
height: fractionalClientHeight + (_overflowScroll.x && subtractXScrollbar ? _scrollbarsHideOffset.x : 0) - paddingVertical height: fractionalClientHeight + (_overflowScroll.x && subtractXScrollbar ? _scrollbarsHideOffset.x : 0) - paddingVertical
@@ -1369,7 +1348,7 @@ const createOverflowUpdate = (structureSetupElements, state) => {
return getViewportOverflowState(showNativeOverlaidScrollbars, viewportStyleObj); return getViewportOverflowState(showNativeOverlaidScrollbars, viewportStyleObj);
}; };
const arrangeViewport = (viewportOverflowState, viewportScrollSize, viewportSizeFraction, directionIsRTL) => { const arrangeViewport = (viewportOverflowState, viewportScrollSize, sizeFraction, directionIsRTL) => {
if (doViewportArrange) { if (doViewportArrange) {
const { const {
_viewportPaddingStyle _viewportPaddingStyle
@@ -1389,8 +1368,8 @@ const createOverflowUpdate = (structureSetupElements, state) => {
const viewportArrangeHorizontalPaddingKey = directionIsRTL ? 'paddingRight' : 'paddingLeft'; const viewportArrangeHorizontalPaddingKey = directionIsRTL ? 'paddingRight' : 'paddingLeft';
const viewportArrangeHorizontalPaddingValue = _viewportPaddingStyle[viewportArrangeHorizontalPaddingKey]; const viewportArrangeHorizontalPaddingValue = _viewportPaddingStyle[viewportArrangeHorizontalPaddingKey];
const viewportArrangeVerticalPaddingValue = _viewportPaddingStyle.paddingTop; const viewportArrangeVerticalPaddingValue = _viewportPaddingStyle.paddingTop;
const fractionalContentWidth = viewportScrollSize.w + (abs(viewportSizeFraction.w) < 1 ? viewportSizeFraction.w : 0); const fractionalContentWidth = viewportScrollSize.w + sizeFraction.w;
const fractionalContenHeight = viewportScrollSize.h + (abs(viewportSizeFraction.h) < 1 ? viewportSizeFraction.h : 0); const fractionalContenHeight = viewportScrollSize.h + sizeFraction.h;
const arrangeSize = { const arrangeSize = {
w: hideOffsetY && arrangeY ? `${hideOffsetY + fractionalContentWidth - viewportArrangeHorizontalPaddingValue}px` : '', w: hideOffsetY && arrangeY ? `${hideOffsetY + fractionalContentWidth - viewportArrangeHorizontalPaddingValue}px` : '',
h: hideOffsetX && arrangeX ? `${hideOffsetX + fractionalContenHeight - viewportArrangeVerticalPaddingValue}px` : '' h: hideOffsetX && arrangeX ? `${hideOffsetX + fractionalContenHeight - viewportArrangeVerticalPaddingValue}px` : ''
@@ -1478,10 +1457,6 @@ const createOverflowUpdate = (structureSetupElements, state) => {
finalPaddingStyle[prop] = viewportPaddingStyle[prop]; finalPaddingStyle[prop] = viewportPaddingStyle[prop];
}); });
if (!_flexboxGlue) {
finalPaddingStyle.height = '';
}
if (arrangeX) { if (arrangeX) {
assignProps('marginBottom paddingTop paddingBottom'); assignProps('marginBottom paddingTop paddingBottom');
} }
@@ -1492,6 +1467,11 @@ const createOverflowUpdate = (structureSetupElements, state) => {
const prevStyle = style(_viewport, keys(finalPaddingStyle)); const prevStyle = style(_viewport, keys(finalPaddingStyle));
removeClass(_viewport, classNameViewportArrange); removeClass(_viewport, classNameViewportArrange);
if (!_flexboxGlue) {
finalPaddingStyle.height = '';
}
style(_viewport, finalPaddingStyle); style(_viewport, finalPaddingStyle);
return [() => { return [() => {
hideNativeScrollbars(finalViewportOverflowState, directionIsRTL, doViewportArrange, prevStyle); hideNativeScrollbars(finalViewportOverflowState, directionIsRTL, doViewportArrange, prevStyle);
@@ -1505,19 +1485,21 @@ const createOverflowUpdate = (structureSetupElements, state) => {
return (updateHints, checkOption, force) => { return (updateHints, checkOption, force) => {
const { const {
_directionIsRTL,
_heightIntrinsic,
_sizeChanged, _sizeChanged,
_hostMutation, _hostMutation,
_contentMutation, _contentMutation,
_paddingStyleChanged _paddingStyleChanged,
_heightIntrinsicChanged,
_directionChanged
} = updateHints; } = updateHints;
const [heightIntrinsic, heightIntrinsicChanged] = _heightIntrinsic; const {
const [directionIsRTL, directionChanged] = _directionIsRTL; _heightIntrinsic,
_directionIsRTL
} = getState();
const [showNativeOverlaidScrollbarsOption, showNativeOverlaidScrollbarsChanged] = checkOption('nativeScrollbarsOverlaid.show'); const [showNativeOverlaidScrollbarsOption, showNativeOverlaidScrollbarsChanged] = checkOption('nativeScrollbarsOverlaid.show');
const showNativeOverlaidScrollbars = showNativeOverlaidScrollbarsOption && _nativeScrollbarIsOverlaid.x && _nativeScrollbarIsOverlaid.y; const showNativeOverlaidScrollbars = showNativeOverlaidScrollbarsOption && _nativeScrollbarIsOverlaid.x && _nativeScrollbarIsOverlaid.y;
const adjustFlexboxGlue = !_flexboxGlue && (_sizeChanged || _contentMutation || _hostMutation || showNativeOverlaidScrollbarsChanged || heightIntrinsicChanged); const adjustFlexboxGlue = !_flexboxGlue && (_sizeChanged || _contentMutation || _hostMutation || showNativeOverlaidScrollbarsChanged || _heightIntrinsicChanged);
let viewportSizeFractionCache = getCurrentViewportSizeFraction(force); let sizeFractionCache = getCurrentSizeFraction(force);
let viewportScrollSizeCache = getCurrentViewportScrollSizeCache(force); let viewportScrollSizeCache = getCurrentViewportScrollSizeCache(force);
let overflowAmuntCache = getCurrentOverflowAmountCache(force); let overflowAmuntCache = getCurrentOverflowAmountCache(force);
let preMeasureViewportOverflowState; let preMeasureViewportOverflowState;
@@ -1532,19 +1514,19 @@ const createOverflowUpdate = (structureSetupElements, state) => {
if (adjustFlexboxGlue) { if (adjustFlexboxGlue) {
preMeasureViewportOverflowState = getViewportOverflowState(showNativeOverlaidScrollbars); preMeasureViewportOverflowState = getViewportOverflowState(showNativeOverlaidScrollbars);
fixFlexboxGlue(preMeasureViewportOverflowState, !!heightIntrinsic); fixFlexboxGlue(preMeasureViewportOverflowState, _heightIntrinsic);
} }
if (_sizeChanged || _paddingStyleChanged || _contentMutation || showNativeOverlaidScrollbarsChanged || directionChanged) { if (_sizeChanged || _paddingStyleChanged || _contentMutation || _directionChanged || showNativeOverlaidScrollbarsChanged) {
const [redoViewportArrange, undoViewportArrangeOverflowState] = undoViewportArrange(showNativeOverlaidScrollbars, directionIsRTL, preMeasureViewportOverflowState); const [redoViewportArrange, undoViewportArrangeOverflowState] = undoViewportArrange(showNativeOverlaidScrollbars, _directionIsRTL, preMeasureViewportOverflowState);
const [_viewportSizeFraction, viewportSizeFractionCahnged] = viewportSizeFractionCache = updateViewportSizeFraction(force); const [_sizeFraction, _sizeFractionChanged] = sizeFractionCache = updateSizeFraction(force);
const [_viewportScrollSize, _viewportScrollSizeChanged] = viewportScrollSizeCache = updateViewportScrollSizeCache(force); const [_viewportScrollSize, _viewportScrollSizeChanged] = viewportScrollSizeCache = updateViewportScrollSizeCache(force);
const viewportContentSize = clientSize(_viewport); const viewportContentSize = clientSize(_viewport);
let arrangedViewportScrollSize = _viewportScrollSize; let arrangedViewportScrollSize = _viewportScrollSize;
let arrangedViewportClientSize = viewportContentSize; let arrangedViewportClientSize = viewportContentSize;
redoViewportArrange(); redoViewportArrange();
if ((_viewportScrollSizeChanged || viewportSizeFractionCahnged || showNativeOverlaidScrollbarsChanged) && undoViewportArrangeOverflowState && !showNativeOverlaidScrollbars && arrangeViewport(undoViewportArrangeOverflowState, _viewportScrollSize, _viewportSizeFraction, directionIsRTL)) { if ((_viewportScrollSizeChanged || _sizeFractionChanged || showNativeOverlaidScrollbarsChanged) && undoViewportArrangeOverflowState && !showNativeOverlaidScrollbars && arrangeViewport(undoViewportArrangeOverflowState, _viewportScrollSize, _sizeFraction, _directionIsRTL)) {
arrangedViewportClientSize = clientSize(_viewport); arrangedViewportClientSize = clientSize(_viewport);
arrangedViewportScrollSize = scrollSize(_viewport); arrangedViewportScrollSize = scrollSize(_viewport);
} }
@@ -1555,15 +1537,15 @@ const createOverflowUpdate = (structureSetupElements, state) => {
}, { }, {
w: arrangedViewportClientSize.w + max(0, viewportContentSize.w - _viewportScrollSize.w), w: arrangedViewportClientSize.w + max(0, viewportContentSize.w - _viewportScrollSize.w),
h: arrangedViewportClientSize.h + max(0, viewportContentSize.h - _viewportScrollSize.h) h: arrangedViewportClientSize.h + max(0, viewportContentSize.h - _viewportScrollSize.h)
}, _viewportSizeFraction), force); }, _sizeFraction), force);
} }
const [viewportSizeFraction, viewportSizeFractionChanged] = viewportSizeFractionCache; const [sizeFraction, sizeFractionChanged] = sizeFractionCache;
const [viewportScrollSize, viewportScrollSizeChanged] = viewportScrollSizeCache; const [viewportScrollSize, viewportScrollSizeChanged] = viewportScrollSizeCache;
const [overflowAmount, overflowAmountChanged] = overflowAmuntCache; const [overflowAmount, overflowAmountChanged] = overflowAmuntCache;
const [overflow, overflowChanged] = checkOption('overflow'); const [overflow, overflowChanged] = checkOption('overflow');
if (_paddingStyleChanged || viewportSizeFractionChanged || viewportScrollSizeChanged || overflowAmountChanged || overflowChanged || showNativeOverlaidScrollbarsChanged || directionChanged || adjustFlexboxGlue) { if (_paddingStyleChanged || _directionChanged || sizeFractionChanged || viewportScrollSizeChanged || overflowAmountChanged || overflowChanged || showNativeOverlaidScrollbarsChanged || adjustFlexboxGlue) {
const viewportStyle = { const viewportStyle = {
marginRight: 0, marginRight: 0,
marginBottom: 0, marginBottom: 0,
@@ -1573,24 +1555,27 @@ const createOverflowUpdate = (structureSetupElements, state) => {
overflowX: '' overflowX: ''
}; };
const viewportOverflowState = setViewportOverflowState(showNativeOverlaidScrollbars, overflowAmount, overflow, viewportStyle); const viewportOverflowState = setViewportOverflowState(showNativeOverlaidScrollbars, overflowAmount, overflow, viewportStyle);
const viewportArranged = arrangeViewport(viewportOverflowState, viewportScrollSize, viewportSizeFraction, directionIsRTL); const viewportArranged = arrangeViewport(viewportOverflowState, viewportScrollSize, sizeFraction, _directionIsRTL);
hideNativeScrollbars(viewportOverflowState, directionIsRTL, viewportArranged, viewportStyle); const [overflowScroll, overflowScrollChanged] = updateOverflowScrollCache(viewportOverflowState._overflowScroll);
hideNativeScrollbars(viewportOverflowState, _directionIsRTL, viewportArranged, viewportStyle);
if (adjustFlexboxGlue) { if (adjustFlexboxGlue) {
fixFlexboxGlue(viewportOverflowState, !!heightIntrinsic); fixFlexboxGlue(viewportOverflowState, _heightIntrinsic);
} }
style(_viewport, viewportStyle); style(_viewport, viewportStyle);
setState({ setState({
_viewportOverflowScrollCache: updateOverflowScrollCache(viewportOverflowState._overflowScroll), _viewportOverflowScroll: overflowScroll,
_viewportOverflowAmountCache: overflowAmuntCache _viewportOverflowAmount: overflowAmount
}); });
return {
_overflowAmountChanged: overflowAmountChanged,
_overflowScrollChanged: overflowScrollChanged
};
} }
}; };
}; };
const booleanCacheValuesFallback = [false, false, false];
const applyForceToCache = (cacheValues, force) => [cacheValues[0], force || cacheValues[1], cacheValues[2]]; const applyForceToCache = (cacheValues, force) => [cacheValues[0], force || cacheValues[1], cacheValues[2]];
const prepareUpdateHints = (leading, adaptive, force) => { const prepareUpdateHints = (leading, adaptive, force) => {
@@ -1600,7 +1585,7 @@ const prepareUpdateHints = (leading, adaptive, force) => {
each(objKeys, key => { each(objKeys, key => {
const leadingValue = leading[key]; const leadingValue = leading[key];
const adaptiveValue = finalAdaptive[key]; const adaptiveValue = finalAdaptive[key];
result[key] = isBoolean(leadingValue) ? !!force || !!leadingValue || !!adaptiveValue : applyForceToCache(leadingValue || booleanCacheValuesFallback, force); result[key] = isBoolean(leadingValue) ? !!force || !!leadingValue || !!adaptiveValue : applyForceToCache(leadingValue, force);
}); });
return result; return result;
}; };
@@ -1615,16 +1600,24 @@ const createStructureSetupUpdate = (structureSetupElements, state) => {
_flexboxGlue _flexboxGlue
} = getEnvironment(); } = getEnvironment();
const doViewportArrange = !_nativeScrollbarStyling && (_nativeScrollbarIsOverlaid.x || _nativeScrollbarIsOverlaid.y); const doViewportArrange = !_nativeScrollbarStyling && (_nativeScrollbarIsOverlaid.x || _nativeScrollbarIsOverlaid.y);
const updateSegments = [createTrinsicUpdate(structureSetupElements), createPaddingUpdate(structureSetupElements, state), createOverflowUpdate(structureSetupElements, state)]; const updateSegments = [createTrinsicUpdate(structureSetupElements, state), createPaddingUpdate(structureSetupElements, state), createOverflowUpdate(structureSetupElements, state)];
return (checkOption, updateHints, force) => { return (checkOption, updateHints, force) => {
const initialUpdateHints = prepareUpdateHints(assignDeep({ const initialUpdateHints = prepareUpdateHints(assignDeep({
_sizeChanged: false, _sizeChanged: false,
_hostMutation: false, _hostMutation: false,
_contentMutation: false, _contentMutation: false,
_paddingStyleChanged: false, _paddingStyleChanged: false,
_directionIsRTL: booleanCacheValuesFallback, _directionChanged: false,
_heightIntrinsic: booleanCacheValuesFallback _heightIntrinsicChanged: false,
}, updateHints), {}, force); _overflowScrollChanged: false,
_overflowAmountChanged: false
}, Object.keys(updateHints).reduce((acc, key) => {
if (!isUndefined(updateHints[key])) {
acc[key] = updateHints[key];
}
return acc;
}, {})), {}, force);
const adjustScrollOffset = doViewportArrange || !_flexboxGlue; const adjustScrollOffset = doViewportArrange || !_flexboxGlue;
const scrollOffsetX = adjustScrollOffset && scrollLeft(_viewport); const scrollOffsetX = adjustScrollOffset && scrollLeft(_viewport);
const scrollOffsetY = adjustScrollOffset && scrollTop(_viewport); const scrollOffsetY = adjustScrollOffset && scrollTop(_viewport);
@@ -2031,10 +2024,11 @@ const ignoreTargetChange = (target, attrName, oldValue, newValue) => {
return false; return false;
}; };
const createStructureSetupObservers = (structureSetupElements, structureSetupUpdate) => { const createStructureSetupObservers = (structureSetupElements, state, structureSetupUpdate) => {
let debounceTimeout; let debounceTimeout;
let debounceMaxDelay; let debounceMaxDelay;
let contentMutationObserver; let contentMutationObserver;
const [, setState] = state;
const { const {
_host, _host,
_viewport, _viewport,
@@ -2085,10 +2079,14 @@ const createStructureSetupObservers = (structureSetupElements, structureSetupUpd
}); });
}; };
const onTrinsicChanged = heightIntrinsic => { const onTrinsicChanged = heightIntrinsicCache => {
structureSetupUpdate({ const [heightIntrinsic, heightIntrinsicChanged] = heightIntrinsicCache;
setState({
_heightIntrinsic: heightIntrinsic _heightIntrinsic: heightIntrinsic
}); });
structureSetupUpdate({
_heightIntrinsicChanged: heightIntrinsicChanged
});
}; };
const onSizeChanged = ({ const onSizeChanged = ({
@@ -2097,9 +2095,19 @@ const createStructureSetupObservers = (structureSetupElements, structureSetupUpd
_appear _appear
}) => { }) => {
const updateFn = !_sizeChanged || _appear ? structureSetupUpdate : structureSetupUpdateWithDebouncedAdaptiveUpdateHints; const updateFn = !_sizeChanged || _appear ? structureSetupUpdate : structureSetupUpdateWithDebouncedAdaptiveUpdateHints;
let directionChanged = false;
if (_directionIsRTLCache) {
const [directionIsRTL, directionIsRTLChanged] = _directionIsRTLCache;
directionChanged = directionIsRTLChanged;
setState({
_directionIsRTL: directionIsRTL
});
}
updateFn({ updateFn({
_sizeChanged, _sizeChanged,
_directionIsRTL: _directionIsRTLCache _directionChanged: directionChanged
}); });
}; };
@@ -2183,14 +2191,6 @@ const initialStructureSetupUpdateState = {
l: 0 l: 0
}, },
_paddingAbsolute: false, _paddingAbsolute: false,
_viewportOverflowScrollCache: [{
x: false,
y: false
}, false],
_viewportOverflowAmountCache: [{
w: 0,
h: 0
}, false],
_viewportPaddingStyle: { _viewportPaddingStyle: {
marginRight: 0, marginRight: 0,
marginBottom: 0, marginBottom: 0,
@@ -2199,7 +2199,17 @@ const initialStructureSetupUpdateState = {
paddingRight: 0, paddingRight: 0,
paddingBottom: 0, paddingBottom: 0,
paddingLeft: 0 paddingLeft: 0
} },
_viewportOverflowAmount: {
w: 0,
h: 0
},
_viewportOverflowScroll: {
x: false,
y: false
},
_heightIntrinsic: false,
_directionIsRTL: false
}; };
const createStructureSetup = (target, options) => { const createStructureSetup = (target, options) => {
const checkOptionsFallback = createOptionCheck(options, {}); const checkOptionsFallback = createOptionCheck(options, {});
@@ -2213,12 +2223,9 @@ const createStructureSetup = (target, options) => {
const [elements, destroyElements] = createStructureSetupElements(target); const [elements, destroyElements] = createStructureSetupElements(target);
const updateStructure = createStructureSetupUpdate(elements, state); const updateStructure = createStructureSetupUpdate(elements, state);
const [updateObservers, destroyObservers] = createStructureSetupObservers(elements, updateHints => { const [updateObservers, destroyObservers] = createStructureSetupObservers(elements, state, updateHints => {
runOnUpdatedListeners(updateStructure(checkOptionsFallback, updateHints)); runOnUpdatedListeners(updateStructure(checkOptionsFallback, updateHints));
}); });
const removeEnvListener = getEnvironment()._addListener(updateStructure.bind(0, checkOptionsFallback, {}, true));
const structureSetupState = getUpdateState.bind(0); const structureSetupState = getUpdateState.bind(0);
structureSetupState._addOnUpdatedListener = listener => { structureSetupState._addOnUpdatedListener = listener => {
@@ -2232,7 +2239,6 @@ const createStructureSetup = (target, options) => {
runOnUpdatedListeners(updateStructure(checkOption, {}, force)); runOnUpdatedListeners(updateStructure(checkOption, {}, force));
}, structureSetupState, () => { }, structureSetupState, () => {
onUpdatedListeners.clear(); onUpdatedListeners.clear();
removeEnvListener();
destroyObservers(); destroyObservers();
destroyElements(); destroyElements();
}]; }];
@@ -2305,6 +2311,35 @@ const addPlugin = addedPlugin => each(isArray(addedPlugin) ? addedPlugin : [adde
pluginRegistry[plugin[0]] = plugin[1]; pluginRegistry[plugin[0]] = plugin[1];
}); });
function getDefaultExportFromCjs (x) {
return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
}
var _extends = {exports: {}};
(function (module) {
function _extends() {
module.exports = _extends = Object.assign ? Object.assign.bind() : 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;
}, module.exports.__esModule = true, module.exports["default"] = module.exports;
return _extends.apply(this, arguments);
}
module.exports = _extends, module.exports.__esModule = true, module.exports["default"] = module.exports;
})(_extends);
getDefaultExportFromCjs(_extends.exports);
const templateTypePrefixSuffix = ['__TPL_', '_TYPE__']; const templateTypePrefixSuffix = ['__TPL_', '_TYPE__'];
const optionsTemplateTypes = ['boolean', 'number', 'string', 'array', 'object', 'function', 'null'].reduce((result, item) => { const optionsTemplateTypes = ['boolean', 'number', 'string', 'array', 'object', 'function', 'null'].reduce((result, item) => {
result[item] = templateTypePrefixSuffix[0] + item + templateTypePrefixSuffix[1]; result[item] = templateTypePrefixSuffix[0] + item + templateTypePrefixSuffix[1];
@@ -2383,7 +2418,8 @@ const createOverflowChangedArgs = (overflowAmount, overflowScroll) => ({
const OverlayScrollbars = (target, options, eventListeners) => { const OverlayScrollbars = (target, options, eventListeners) => {
const { const {
_getDefaultOptions, _getDefaultOptions,
_nativeScrollbarIsOverlaid _nativeScrollbarIsOverlaid,
_addListener: addEnvListener
} = getEnvironment(); } = getEnvironment();
const plugins = getPlugins(); const plugins = getPlugins();
const instanceTarget = isHTMLElement(target) ? target : target.target; const instanceTarget = isHTMLElement(target) ? target : target.target;
@@ -2418,31 +2454,39 @@ const OverlayScrollbars = (target, options, eventListeners) => {
structureState._addOnUpdatedListener((updateHints, changedOptions, force) => { structureState._addOnUpdatedListener((updateHints, changedOptions, force) => {
const { const {
_viewportOverflowAmountCache: overflowAmountCache, _sizeChanged,
_viewportOverflowScrollCache: overflowScrollCache _contentMutation,
_hostMutation,
_directionChanged,
_heightIntrinsicChanged,
_overflowAmountChanged,
_overflowScrollChanged
} = updateHints;
const {
_viewportOverflowAmount,
_viewportOverflowScroll
} = structureState(); } = structureState();
const [overflowAmount, overflowAmountChanged, prevOverflowAmount] = overflowAmountCache;
const [overflowScroll, overflowScrollChanged, prevOverflowScroll] = overflowScrollCache;
if (overflowAmountChanged || overflowScrollChanged) { if (_overflowAmountChanged || _overflowScrollChanged) {
triggerEvent('overflowChanged', assignDeep({}, createOverflowChangedArgs(overflowAmount, overflowScroll), { triggerEvent('overflowChanged', assignDeep({}, createOverflowChangedArgs(_viewportOverflowAmount, _viewportOverflowScroll), {
previous: createOverflowChangedArgs(prevOverflowAmount, prevOverflowScroll) previous: createOverflowChangedArgs(_viewportOverflowAmount, _viewportOverflowScroll)
})); }));
} }
triggerEvent('updated', { triggerEvent('updated', {
updateHints: { updateHints: {
sizeChanged: updateHints._sizeChanged, sizeChanged: _sizeChanged,
contentMutation: updateHints._contentMutation, contentMutation: _contentMutation,
hostMutation: updateHints._hostMutation, hostMutation: _hostMutation,
directionChanged: updateHints._directionIsRTL[1], directionChanged: _directionChanged,
heightIntrinsicChanged: updateHints._heightIntrinsic[1] heightIntrinsicChanged: _heightIntrinsicChanged
}, },
changedOptions, changedOptions,
force force
}); });
}); });
const removeEnvListener = addEnvListener(update.bind(0, {}, true));
const instance = { const instance = {
options(newOptions) { options(newOptions) {
if (newOptions) { if (newOptions) {
@@ -2460,7 +2504,7 @@ const OverlayScrollbars = (target, options, eventListeners) => {
on: addEvent, on: addEvent,
off: removeEvent, off: removeEvent,
state: () => ({ state: () => ({
_overflowAmount: structureState()._viewportOverflowAmountCache[0] _overflowAmount: structureState()._viewportOverflowAmount
}), }),
update(force) { update(force) {
@@ -2469,6 +2513,7 @@ const OverlayScrollbars = (target, options, eventListeners) => {
destroy: () => { destroy: () => {
removeInstance(instanceTarget); removeInstance(instanceTarget);
removeEnvListener();
removeEvent(); removeEvent();
destroyScrollbars(); destroyScrollbars();
destroyStructure(); destroyStructure();
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+19 -9
View File
@@ -3,6 +3,7 @@ import {
addClass, addClass,
style, style,
appendChildren, appendChildren,
fractionalSize,
clientSize, clientSize,
absoluteCoordinates, absoluteCoordinates,
offsetSize, offsetSize,
@@ -105,27 +106,33 @@ const diffBiggerThanOne = (valOne: number, valTwo: number): boolean => {
return !(absValOne === absValTwo || absValOne + 1 === absValTwo || absValOne - 1 === absValTwo); return !(absValOne === absValTwo || absValOne + 1 === absValTwo || absValOne - 1 === absValTwo);
}; };
const getNativeScrollbarSize = (body: HTMLElement, measureElm: HTMLElement): XY => { const getNativeScrollbarSize = (
body: HTMLElement,
measureElm: HTMLElement,
measureElmChild: HTMLElement
): XY => {
appendChildren(body, measureElm); appendChildren(body, measureElm);
const cSize = clientSize(measureElm); const cSize = clientSize(measureElm);
const oSize = offsetSize(measureElm); const oSize = offsetSize(measureElm);
const fSize = fractionalSize(measureElmChild);
return { return {
x: oSize.h - cSize.h, x: oSize.h - cSize.h + fSize.h,
y: oSize.w - cSize.w, y: oSize.w - cSize.w + fSize.w,
}; };
}; };
const getNativeScrollbarStyling = (testElm: HTMLElement): boolean => { const getNativeScrollbarStyling = (testElm: HTMLElement): boolean => {
let result = false; let result = false;
addClass(testElm, classNameViewportScrollbarStyling); const revertClass = addClass(testElm, classNameViewportScrollbarStyling);
try { try {
result = result =
style(testElm, cssProperty('scrollbar-width')) === 'none' || style(testElm, cssProperty('scrollbar-width')) === 'none' ||
window.getComputedStyle(testElm, '::-webkit-scrollbar').getPropertyValue('display') === window.getComputedStyle(testElm, '::-webkit-scrollbar').getPropertyValue('display') ===
'none'; 'none';
} catch (ex) {} } catch (ex) {}
revertClass();
return result; return result;
}; };
@@ -160,16 +167,19 @@ const getRtlScrollBehavior = (
}; };
const getFlexboxGlue = (parentElm: HTMLElement, childElm: HTMLElement): boolean => { const getFlexboxGlue = (parentElm: HTMLElement, childElm: HTMLElement): boolean => {
addClass(parentElm, classNameEnvironmentFlexboxGlue); const revertFbxGlue = addClass(parentElm, classNameEnvironmentFlexboxGlue);
const minOffsetsizeParent = getBoundingClientRect(parentElm); const minOffsetsizeParent = getBoundingClientRect(parentElm);
const minOffsetsize = getBoundingClientRect(childElm); const minOffsetsize = getBoundingClientRect(childElm);
const supportsMin = equalBCRWH(minOffsetsize, minOffsetsizeParent, true); const supportsMin = equalBCRWH(minOffsetsize, minOffsetsizeParent, true);
addClass(parentElm, classNameEnvironmentFlexboxGlueMax); const revertFbxGlueMax = addClass(parentElm, classNameEnvironmentFlexboxGlueMax);
const maxOffsetsizeParent = getBoundingClientRect(parentElm); const maxOffsetsizeParent = getBoundingClientRect(parentElm);
const maxOffsetsize = getBoundingClientRect(childElm); const maxOffsetsize = getBoundingClientRect(childElm);
const supportsMax = equalBCRWH(maxOffsetsize, maxOffsetsizeParent, true); const supportsMax = equalBCRWH(maxOffsetsize, maxOffsetsizeParent, true);
revertFbxGlue();
revertFbxGlueMax();
return supportsMin && supportsMax; return supportsMin && supportsMax;
}; };
@@ -200,7 +210,7 @@ const createEnvironment = (): Environment => {
const envChildElm = envElm.firstChild as HTMLElement; const envChildElm = envElm.firstChild as HTMLElement;
const onChangedListener: Set<OnEnvironmentChanged> = new Set(); const onChangedListener: Set<OnEnvironmentChanged> = new Set();
const [updateNativeScrollbarSizeCache, getNativeScrollbarSizeCache] = createCache({ const [updateNativeScrollbarSizeCache, getNativeScrollbarSizeCache] = createCache({
_initialValue: getNativeScrollbarSize(body, envElm), _initialValue: getNativeScrollbarSize(body, envElm, envChildElm),
_equal: equalXY, _equal: equalXY,
}); });
const [nativeScrollbarSize] = getNativeScrollbarSizeCache(); const [nativeScrollbarSize] = getNativeScrollbarSizeCache();
@@ -276,7 +286,7 @@ const createEnvironment = (): Environment => {
if (isZoom) { if (isZoom) {
const [scrollbarSize, scrollbarSizeChanged] = updateNativeScrollbarSizeCache( const [scrollbarSize, scrollbarSizeChanged] = updateNativeScrollbarSizeCache(
getNativeScrollbarSize(body, envElm) getNativeScrollbarSize(body, envElm, envChildElm)
); );
assignDeep(environmentInstance._nativeScrollbarSize, scrollbarSize); // keep the object same! assignDeep(environmentInstance._nativeScrollbarSize, scrollbarSize); // keep the object same!
@@ -6,6 +6,7 @@ import {
XY, XY,
style, style,
scrollSize, scrollSize,
fractionalSize,
CacheValues, CacheValues,
equalWH, equalWH,
addClass, addClass,
@@ -42,16 +43,6 @@ const xyCacheOptions = {
_equal: equalXY, _equal: equalXY,
_initialValue: { x: false, y: false }, _initialValue: { x: false, y: false },
}; };
const getSizeFraction = (elm: HTMLElement): WH<number> => {
const cssHeight = parseFloat(style(elm, 'height'));
const cssWidth = parseFloat(style(elm, 'height'));
return {
w: cssWidth - round(cssWidth),
h: cssHeight - round(cssHeight),
};
};
const fractionalPixelRatioTollerance = () => (window.devicePixelRatio % 1 === 0 ? 0 : 1);
const setAxisOverflowStyle = ( const setAxisOverflowStyle = (
horizontal: boolean, horizontal: boolean,
overflowAmount: number, overflowAmount: number,
@@ -80,23 +71,19 @@ const setAxisOverflowStyle = (
const getOverflowAmount = ( const getOverflowAmount = (
viewportScrollSize: WH<number>, viewportScrollSize: WH<number>,
viewportClientSize: WH<number>, viewportClientSize: WH<number>,
viewportSizeFraction: WH<number> sizeFraction: WH<number>
) => ({ ) => {
w: max( const condition = (raw: number) => (window.devicePixelRatio % 2 !== 0 ? raw > 1 : raw > 0);
0, const amount = {
round( w: max(0, viewportScrollSize.w - viewportClientSize.w - max(0, sizeFraction.w)),
max(0, viewportScrollSize.w - viewportClientSize.w) - h: max(0, viewportScrollSize.h - viewportClientSize.h - max(0, sizeFraction.h)),
(fractionalPixelRatioTollerance() || max(0, viewportSizeFraction.w)) };
)
), return {
h: max( w: condition(amount.w) ? amount.w : 0,
0, h: condition(amount.h) ? amount.h : 0,
round( };
max(0, viewportScrollSize.h - viewportClientSize.h) - };
(fractionalPixelRatioTollerance() || max(0, viewportSizeFraction.h))
)
),
});
/** /**
* Lifecycle with the responsibility to set the correct overflow and scrollbar hiding styles of the viewport element. * Lifecycle with the responsibility to set the correct overflow and scrollbar hiding styles of the viewport element.
@@ -120,7 +107,7 @@ export const createOverflowUpdate: CreateStructureUpdateSegment = (
const [updateSizeFraction, getCurrentSizeFraction] = createCache<WH<number>>( const [updateSizeFraction, getCurrentSizeFraction] = createCache<WH<number>>(
whCacheOptions, whCacheOptions,
getSizeFraction.bind(0, _host) fractionalSize.bind(0, _host)
); );
const [updateViewportScrollSizeCache, getCurrentViewportScrollSizeCache] = createCache< const [updateViewportScrollSizeCache, getCurrentViewportScrollSizeCache] = createCache<
@@ -30,15 +30,6 @@ const classListAction = (
export const hasClass = (elm: Element | false | null | undefined, className: string): boolean => export const hasClass = (elm: Element | false | null | undefined, className: string): boolean =>
classListAction(elm, className, (classList, clazz) => classList.contains(clazz)); classListAction(elm, className, (classList, clazz) => classList.contains(clazz));
/**
* Adds the given class name(s) to the given element.
* @param elm The element.
* @param className The class name(s) which shall be added. (separated by spaces)
*/
export const addClass = (elm: Element | false | null | undefined, className: string): void => {
classListAction(elm, className, (classList, clazz) => classList.add(clazz));
};
/** /**
* Removes the given class name(s) from the given element. * Removes the given class name(s) from the given element.
* @param elm The element. * @param elm The element.
@@ -48,6 +39,20 @@ export const removeClass = (elm: Element | false | null | undefined, className:
classListAction(elm, className, (classList, clazz) => classList.remove(clazz)); classListAction(elm, className, (classList, clazz) => classList.remove(clazz));
}; };
/**
* Adds the given class name(s) to the given element.
* @param elm The element.
* @param className The class name(s) which shall be added. (separated by spaces)
* @returns A function which removes the added class name(s).
*/
export const addClass = (
elm: Element | false | null | undefined,
className: string
): (() => void) => {
classListAction(elm, className, (classList, clazz) => classList.add(clazz));
return removeClass.bind(0, elm, className);
};
/** /**
* Takes two className strings, compares them and returns the difference as array. * Takes two className strings, compares them and returns the difference as array.
* @param classNameA ClassName A. * @param classNameA ClassName A.
@@ -1,3 +1,5 @@
import { style } from 'support/dom/style';
export interface WH<T = number> { export interface WH<T = number> {
w: T; w: T;
h: T; h: T;
@@ -54,6 +56,19 @@ export const scrollSize = (elm: HTMLElement | null | undefined): WH =>
} }
: zeroObj; : zeroObj;
/**
* Returns the fractional- width and height of the passed element. If the element is null the width and height values are 0.
* @param elm The element of which the fractional- width and height shall be returned.
*/
export const fractionalSize = (elm: HTMLElement | null | undefined): WH => {
const cssHeight = parseFloat(style(elm, 'height')) || 0;
const cssWidth = parseFloat(style(elm, 'height')) || 0;
return {
w: cssWidth - Math.round(cssWidth),
h: cssHeight - Math.round(cssHeight),
};
};
/** /**
* Returns the BoundingClientRect of the passed element. * Returns the BoundingClientRect of the passed element.
* @param elm The element of which the BoundingClientRect shall be returned. * @param elm The element of which the BoundingClientRect shall be returned.
@@ -27,14 +27,21 @@ describe('dom class names', () => {
}); });
test('single', () => { test('single', () => {
addClass(testElm, 'test-class'); const remove = addClass(testElm, 'test-class');
expect(hasClassName('test-class')).toBe(true); expect(hasClassName('test-class')).toBe(true);
remove();
expect(hasClassName('test-class')).toBe(false);
}); });
test('multiple', () => { test('multiple', () => {
addClass(testElm, 'test-class test-class2'); const remove = addClass(testElm, 'test-class test-class2');
expect(hasClassName('test-class')).toBe(true); expect(hasClassName('test-class')).toBe(true);
expect(hasClassName('test-class2')).toBe(true); expect(hasClassName('test-class2')).toBe(true);
remove();
expect(hasClassName('test-class')).toBe(false);
expect(hasClassName('test-class2')).toBe(false);
}); });
test('null', () => { test('null', () => {
@@ -1,6 +1,14 @@
import { isNumber, isPlainObject } from 'support/utils/types'; import { isNumber, isPlainObject } from 'support/utils/types';
import { createDiv } from 'support/dom/create'; import { createDiv } from 'support/dom/create';
import { windowSize, offsetSize, clientSize, scrollSize, getBoundingClientRect, hasDimensions } from 'support/dom/dimensions'; import {
windowSize,
offsetSize,
clientSize,
scrollSize,
fractionalSize,
getBoundingClientRect,
hasDimensions,
} from 'support/dom/dimensions';
describe('dom dimensions', () => { describe('dom dimensions', () => {
describe('offsetSize', () => { describe('offsetSize', () => {
@@ -51,6 +59,22 @@ describe('dom dimensions', () => {
}); });
}); });
describe('fractionalSize', () => {
test('DOM element', () => {
const result = fractionalSize(document.body);
expect(isPlainObject(result)).toBe(true);
expect(isNumber(result.w)).toBe(true);
expect(isNumber(result.h)).toBe(true);
});
test('null', () => {
const result = fractionalSize(null);
expect(isPlainObject(result)).toBe(true);
expect(isNumber(result.w)).toBe(true);
expect(isNumber(result.h)).toBe(true);
});
});
test('windowSize', () => { test('windowSize', () => {
const result = windowSize(); const result = windowSize();
expect(isPlainObject(result)).toBe(true); expect(isPlainObject(result)).toBe(true);
@@ -21,12 +21,12 @@ import { timeout } from '@/testing-browser/timeout';
interface Metrics { interface Metrics {
offset: { offset: {
left: string | number; left: number;
top: string | number; top: number;
}; };
size: { size: {
width: string | number; width: number;
height: string | number; height: number;
}; };
scroll: { scroll: {
width: number; width: number;
@@ -37,12 +37,12 @@ interface Metrics {
y: boolean; y: boolean;
}; };
percentElm: { percentElm: {
width: string | number; width: number;
height: string | number; height: number;
}; };
endElm: { endElm: {
width: string | number; width: number;
height: string | number; height: number;
}; };
} }
@@ -60,48 +60,55 @@ const getMetrics = (elm: HTMLElement): Metrics => {
const comparisonBCR = getBoundingClientRect(elm!); const comparisonBCR = getBoundingClientRect(elm!);
const comparisonPercentBCR = getBoundingClientRect(elm!.querySelector('.percent')!); const comparisonPercentBCR = getBoundingClientRect(elm!.querySelector('.percent')!);
const comparisonEndBCR = getBoundingClientRect(elm!.querySelector('.end')!); const comparisonEndBCR = getBoundingClientRect(elm!.querySelector('.end')!);
const targetViewport = target!.querySelector<HTMLElement>('.os-viewport'); const scrollMeasure = () => {
const condition = (raw: number) => (window.devicePixelRatio % 2 !== 0 ? raw > 1 : raw > 0);
const amount = {
width: Math.max(0, comparison!.scrollWidth - comparison!.clientWidth),
height: Math.max(0, comparison!.scrollHeight - comparison!.clientHeight),
};
return {
width: condition(amount.width) ? amount.width : 0,
height: condition(amount.height) ? amount.height : 0,
};
};
const scrollMeasure = (elm: HTMLElement) => ({ const results = {
width: Math.max(0, elm!.scrollWidth - elm!.clientWidth), offset: {
height: Math.max(0, elm!.scrollHeight - elm!.clientHeight), left: parseFloat(
}); (comparisonBCR.left - comparisonEnvBCR.left).toFixed(
Math.min(fixedDigitsOffset, fixedDigits)
const hasOverflow = (elm: HTMLElement) => { )
const measure = scrollMeasure(elm); ),
return elmIsTarget top: parseFloat(
(comparisonBCR.top - comparisonEnvBCR.top).toFixed(Math.min(fixedDigitsOffset, fixedDigits))
),
},
size: {
width: parseFloat(comparisonBCR.width.toFixed(fixedDigits)),
height: parseFloat(comparisonBCR.height.toFixed(fixedDigits)),
},
scroll: elmIsTarget
? {
width: Math.round(osInstance.state()._overflowAmount.w),
height: Math.round(osInstance.state()._overflowAmount.h),
}
: scrollMeasure(),
hasOverflow: elmIsTarget
? { ? {
x: osInstance.state()._overflowAmount.w > 0, x: osInstance.state()._overflowAmount.w > 0,
y: osInstance.state()._overflowAmount.h > 0, y: osInstance.state()._overflowAmount.h > 0,
} }
: { : {
x: measure.width > 0, x: scrollMeasure().width > 0,
y: measure.height > 0, y: scrollMeasure().height > 0,
}; },
};
const results = {
offset: {
left: (comparisonBCR.left - comparisonEnvBCR.left).toFixed(
Math.min(fixedDigitsOffset, fixedDigits)
),
top: (comparisonBCR.top - comparisonEnvBCR.top).toFixed(
Math.min(fixedDigitsOffset, fixedDigits)
),
},
size: {
width: comparisonBCR.width.toFixed(fixedDigits),
height: comparisonBCR.height.toFixed(fixedDigits),
},
scroll: elmIsTarget ? scrollMeasure(targetViewport!) : scrollMeasure(comparison!),
hasOverflow: elmIsTarget ? hasOverflow(targetViewport!) : hasOverflow(comparison!),
percentElm: { percentElm: {
width: comparisonPercentBCR.width.toFixed(fixedDigits), width: parseFloat(comparisonPercentBCR.width.toFixed(fixedDigits)),
height: comparisonPercentBCR.height.toFixed(fixedDigits), height: parseFloat(comparisonPercentBCR.height.toFixed(fixedDigits)),
}, },
endElm: { endElm: {
width: comparisonEndBCR.width.toFixed(fixedDigits), width: parseFloat(comparisonEndBCR.width.toFixed(fixedDigits)),
height: comparisonEndBCR.height.toFixed(fixedDigits), height: parseFloat(comparisonEndBCR.height.toFixed(fixedDigits)),
}, },
}; };
@@ -121,14 +128,6 @@ const metricsDimensionsEqual = (a: Metrics, b: Metrics) => {
return JSON.stringify(aDimensions) === JSON.stringify(bDimensions); return JSON.stringify(aDimensions) === JSON.stringify(bDimensions);
}; };
const plusMinusArr = (original: number, plusMinus: number) => {
const arr = Array.from(Array(plusMinus).keys())
.map((_, index) => original + (index + 1))
.concat(Array.from(Array(plusMinus).keys()).map((_, index) => original - (index + 1)));
arr.push(original);
return arr;
};
// @ts-ignore // @ts-ignore
const msie11 = !!window.MSInputMethodContext && !!document.documentMode; const msie11 = !!window.MSInputMethodContext && !!document.documentMode;
const msedge = window.navigator.userAgent.toLowerCase().indexOf('edge') > -1; const msedge = window.navigator.userAgent.toLowerCase().indexOf('edge') > -1;
@@ -138,7 +137,6 @@ msie11 && addClass(document.body, 'msie11');
const useContentElement = false; const useContentElement = false;
const fixedDigits = msie11 ? 1 : 3; const fixedDigits = msie11 ? 1 : 3;
const fixedDigitsOffset = 3; const fixedDigitsOffset = 3;
const fractionalPixelRatioTollerance = 2; // nss=true && any overlaid ? 2 : 1;
const startBtn: HTMLButtonElement | null = document.querySelector('#start'); const startBtn: HTMLButtonElement | null = document.querySelector('#start');
const target: HTMLElement | null = document.querySelector('#target'); const target: HTMLElement | null = document.querySelector('#target');
@@ -245,79 +243,27 @@ const checkMetrics = async (checkComparison: CheckComparisonObj) => {
const targetMetrics = getMetrics(target!); const targetMetrics = getMetrics(target!);
const targetViewport = target!.querySelector<HTMLElement>('.os-viewport'); const targetViewport = target!.querySelector<HTMLElement>('.os-viewport');
should.equal(targetMetrics.offset.left, comparisonMetrics.offset.left, 'Offset left equality.'); should.equal(
should.equal(targetMetrics.offset.top, comparisonMetrics.offset.top, 'Offset top equality.'); targetMetrics.scroll.width,
comparisonMetrics.scroll.width,
`Scroll width equality. (${osInstance.state()._overflowAmount.w})`
);
should.equal(
targetMetrics.scroll.height,
comparisonMetrics.scroll.height,
`Scroll height equality. (${osInstance.state()._overflowAmount.h})`
);
should.equal(targetMetrics.size.width, comparisonMetrics.size.width, 'Size width equality.'); should.equal(
should.equal(targetMetrics.size.height, comparisonMetrics.size.height, 'Size height equality.'); targetMetrics.hasOverflow.x,
comparisonMetrics.hasOverflow.x,
console.log(comparisonMetrics, osInstance.state()._overflowAmount.h); 'Has overflow x equality.'
);
if (isFractionalPixelRatio()) { should.equal(
should.ok( targetMetrics.hasOverflow.y,
plusMinusArr(targetMetrics.scroll.width, fractionalPixelRatioTollerance).indexOf( comparisonMetrics.hasOverflow.y,
comparisonMetrics.scroll.width 'Has overflow y equality.'
) > -1, );
`Scroll width equality. (+-${fractionalPixelRatioTollerance}) | Target: ${targetMetrics.scroll.width} | Comparison: ${comparisonMetrics.scroll.width}`
);
should.ok(
plusMinusArr(targetMetrics.scroll.height, fractionalPixelRatioTollerance).indexOf(
comparisonMetrics.scroll.height
) > -1,
`Scroll height equality. (+-${fractionalPixelRatioTollerance}) | Target: ${targetMetrics.scroll.height} | Comparison: ${comparisonMetrics.scroll.height}`
);
should.ok(
plusMinusArr(osInstance.state()._overflowAmount.w, fractionalPixelRatioTollerance).indexOf(
comparisonMetrics.scroll.width
) > -1,
`Overflow amount width equality. (+-${fractionalPixelRatioTollerance}) | Amount: ${
osInstance.state()._overflowAmount.w
} | Comparison: ${comparisonMetrics.scroll.width}`
);
should.ok(
plusMinusArr(osInstance.state()._overflowAmount.h, fractionalPixelRatioTollerance).indexOf(
comparisonMetrics.scroll.height
) > -1,
`Overflow amount height equality. (+-${fractionalPixelRatioTollerance}) | Amount: ${
osInstance.state()._overflowAmount.h
} | Comparison: ${comparisonMetrics.scroll.height}`
);
} else {
/*
should.equal(
targetMetrics.scroll.width,
comparisonMetrics.scroll.width,
'Scroll width equality.'
);
should.equal(
targetMetrics.scroll.height,
comparisonMetrics.scroll.height,
'Scroll height equality.'
);
*/
should.equal(
osInstance.state()._overflowAmount.w,
comparisonMetrics.scroll.width,
'Overflow amount width equality.'
);
should.equal(
osInstance.state()._overflowAmount.h,
comparisonMetrics.scroll.height,
'Overflow amount height equality.'
);
should.equal(
targetMetrics.hasOverflow.x,
comparisonMetrics.hasOverflow.x,
'Has overflow x equality.'
);
should.equal(
targetMetrics.hasOverflow.y,
comparisonMetrics.hasOverflow.y,
'Has overflow y equality.'
);
}
if (targetMetrics.hasOverflow.x) { if (targetMetrics.hasOverflow.x) {
should.equal( should.equal(
@@ -365,6 +311,12 @@ const checkMetrics = async (checkComparison: CheckComparisonObj) => {
); );
} }
should.equal(targetMetrics.offset.left, comparisonMetrics.offset.left, 'Offset left equality.');
should.equal(targetMetrics.offset.top, comparisonMetrics.offset.top, 'Offset top equality.');
should.equal(targetMetrics.size.width, comparisonMetrics.size.width, 'Size width equality.');
should.equal(targetMetrics.size.height, comparisonMetrics.size.height, 'Size height equality.');
should.equal( should.equal(
targetMetrics.percentElm.width, targetMetrics.percentElm.width,
comparisonMetrics.percentElm.width, comparisonMetrics.percentElm.width,
@@ -14,7 +14,7 @@ test.describe('StructureLifecycle', () => {
} }
}; };
test.describe(`structureLifecycles ${withText} native scrollbar styling`, () => { test.describe(`${withText} native scrollbar styling`, () => {
test.describe.configure({ mode: 'parallel' }); test.describe.configure({ mode: 'parallel' });
test('default', async ({ page }) => { test('default', async ({ page }) => {
+1
View File
@@ -6,6 +6,7 @@ module.exports = {
actionTimeout: 300, actionTimeout: 300,
navigationTimeout: 1000, navigationTimeout: 1000,
retries: 0, retries: 0,
workers: 4,
projects: [ projects: [
{ {
name: 'Chromium', name: 'Chromium',