mirror of
https://github.com/tenrok/OverlayScrollbars.git
synced 2026-06-21 03:00:35 +03:00
improve cache code and prettier
This commit is contained in:
@@ -83,11 +83,18 @@ module.exports = (esm, options, declarationFiles = false) => {
|
|||||||
rollupBabelInputPlugin({
|
rollupBabelInputPlugin({
|
||||||
...(esm ? babelConfigEsm : babelConfigUmd),
|
...(esm ? babelConfigEsm : babelConfigUmd),
|
||||||
assumptions: {
|
assumptions: {
|
||||||
|
enumerableModuleMeta: false,
|
||||||
|
constantReexports: true,
|
||||||
iterableIsArray: true,
|
iterableIsArray: true,
|
||||||
|
objectRestNoSymbols: true,
|
||||||
noNewArrows: true,
|
noNewArrows: true,
|
||||||
noClassCalls: true,
|
noClassCalls: true,
|
||||||
ignoreToPrimitiveHint: true,
|
ignoreToPrimitiveHint: true,
|
||||||
ignoreFunctionLength: true,
|
ignoreFunctionLength: true,
|
||||||
|
// privateFieldsAsProperties: true,
|
||||||
|
// setPublicClassFields: true,
|
||||||
|
setSpreadProperties: true,
|
||||||
|
pureGetters: true,
|
||||||
},
|
},
|
||||||
plugins: [
|
plugins: [
|
||||||
'@babel/plugin-transform-runtime',
|
'@babel/plugin-transform-runtime',
|
||||||
|
|||||||
+59
-65
@@ -1,16 +1,16 @@
|
|||||||
const createCache = (update, options) => {
|
function createCache(options, update) {
|
||||||
const {
|
const {
|
||||||
_initialValue,
|
_initialValue,
|
||||||
_equal,
|
_equal,
|
||||||
_alwaysUpdateValues
|
_alwaysUpdateValues
|
||||||
} = options || {};
|
} = options;
|
||||||
let _value = _initialValue;
|
let _value = _initialValue;
|
||||||
|
|
||||||
let _previous;
|
let _previous;
|
||||||
|
|
||||||
const cacheUpdate = (force, context) => {
|
const cacheUpdateContextual = (newValue, force) => {
|
||||||
const curr = _value;
|
const curr = _value;
|
||||||
const newVal = update ? update(context, _value, _previous) : context;
|
const newVal = newValue;
|
||||||
const changed = force || (_equal ? !_equal(curr, newVal) : curr !== newVal);
|
const changed = force || (_equal ? !_equal(curr, newVal) : curr !== newVal);
|
||||||
|
|
||||||
if (changed || _alwaysUpdateValues) {
|
if (changed || _alwaysUpdateValues) {
|
||||||
@@ -21,8 +21,12 @@ const createCache = (update, options) => {
|
|||||||
return [_value, changed, _previous];
|
return [_value, changed, _previous];
|
||||||
};
|
};
|
||||||
|
|
||||||
return [cacheUpdate, force => [_value, !!force, _previous]];
|
const cacheUpdateIsolated = force => cacheUpdateContextual(update(_value, _previous), force);
|
||||||
};
|
|
||||||
|
const getCurrentCache = force => [_value, !!force, _previous];
|
||||||
|
|
||||||
|
return [update ? cacheUpdateIsolated : cacheUpdateContextual, getCurrentCache];
|
||||||
|
}
|
||||||
|
|
||||||
const ElementNodeType = Node.ELEMENT_NODE;
|
const ElementNodeType = Node.ELEMENT_NODE;
|
||||||
const {
|
const {
|
||||||
@@ -35,9 +39,7 @@ function isUndefined(obj) {
|
|||||||
function isNull(obj) {
|
function isNull(obj) {
|
||||||
return obj === null;
|
return obj === null;
|
||||||
}
|
}
|
||||||
const type = obj => {
|
const type = obj => isUndefined(obj) || isNull(obj) ? `${obj}` : toString.call(obj).replace(/^\[object (.+)\]$/, '$1').toLowerCase();
|
||||||
return isUndefined(obj) || isNull(obj) ? `${obj}` : toString.call(obj).replace(/^\[object (.+)\]$/, '$1').toLowerCase();
|
|
||||||
};
|
|
||||||
function isNumber(obj) {
|
function isNumber(obj) {
|
||||||
return typeof obj === 'number';
|
return typeof obj === 'number';
|
||||||
}
|
}
|
||||||
@@ -100,7 +102,7 @@ function each(source, callback) {
|
|||||||
|
|
||||||
return source;
|
return source;
|
||||||
}
|
}
|
||||||
const indexOf = (arr, item, fromIndex) => arr.indexOf(item, fromIndex);
|
const indexOf = (arr, item, fromIndex) => isArray(arr) ? arr.indexOf(item, fromIndex) : -1;
|
||||||
const push = (array, items, arrayIsSingleItem) => {
|
const push = (array, items, arrayIsSingleItem) => {
|
||||||
!arrayIsSingleItem && !isString(items) && isArrayLike(items) ? Array.prototype.push.apply(array, items) : array.push(items);
|
!arrayIsSingleItem && !isString(items) && isArrayLike(items) ? Array.prototype.push.apply(array, items) : array.push(items);
|
||||||
return array;
|
return array;
|
||||||
@@ -116,7 +118,7 @@ const from = arr => {
|
|||||||
});
|
});
|
||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
const isEmptyArray = array => array && array.length === 0;
|
const isEmptyArray = array => !!array && array.length === 0;
|
||||||
const runEach = (arr, p1) => {
|
const runEach = (arr, p1) => {
|
||||||
const runFn = fn => fn && fn(p1);
|
const runFn = fn => fn && fn(p1);
|
||||||
|
|
||||||
@@ -464,8 +466,6 @@ const equalWH = (a, b) => equal(a, b, ['w', 'h']);
|
|||||||
const equalTRBL = (a, b) => equal(a, b, ['t', 'r', 'b', 'l']);
|
const equalTRBL = (a, b) => equal(a, b, ['t', 'r', 'b', 'l']);
|
||||||
const equalBCRWH = (a, b, round) => equal(a, b, ['width', 'height'], round && (value => Math.round(value)));
|
const equalBCRWH = (a, b, round) => equal(a, b, ['width', 'height'], round && (value => Math.round(value)));
|
||||||
|
|
||||||
const setT = window.setTimeout;
|
|
||||||
|
|
||||||
const clearTimeouts = id => {
|
const clearTimeouts = id => {
|
||||||
id && window.clearTimeout(id);
|
id && window.clearTimeout(id);
|
||||||
id && cAF(id);
|
id && cAF(id);
|
||||||
@@ -481,7 +481,8 @@ const debounce = (functionToDebounce, options) => {
|
|||||||
_timeout,
|
_timeout,
|
||||||
_maxDelay,
|
_maxDelay,
|
||||||
_mergeParams
|
_mergeParams
|
||||||
} = options;
|
} = options || {};
|
||||||
|
const setT = window.setTimeout;
|
||||||
|
|
||||||
const invokeFunctionToDebounce = function invokeFunctionToDebounce(args) {
|
const invokeFunctionToDebounce = function invokeFunctionToDebounce(args) {
|
||||||
clearTimeouts(timeoutId);
|
clearTimeouts(timeoutId);
|
||||||
@@ -499,7 +500,7 @@ const debounce = (functionToDebounce, options) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const debouncedFn = function debouncedFn() {
|
const debouncedFn = function debouncedFn() {
|
||||||
const args = arguments;
|
const args = from(arguments);
|
||||||
const finalTimeout = isFunction(_timeout) ? _timeout() : _timeout;
|
const finalTimeout = isFunction(_timeout) ? _timeout() : _timeout;
|
||||||
const hasTimeout = isNumber(finalTimeout) && finalTimeout >= 0;
|
const hasTimeout = isNumber(finalTimeout) && finalTimeout >= 0;
|
||||||
|
|
||||||
@@ -510,11 +511,6 @@ const debounce = (functionToDebounce, options) => {
|
|||||||
const mergeParamsResult = mergeParms(args);
|
const mergeParamsResult = mergeParms(args);
|
||||||
const invokedArgs = mergeParamsResult || args;
|
const invokedArgs = mergeParamsResult || args;
|
||||||
const boundInvoke = invokeFunctionToDebounce.bind(0, invokedArgs);
|
const boundInvoke = invokeFunctionToDebounce.bind(0, invokedArgs);
|
||||||
|
|
||||||
if (!mergeParamsResult) {
|
|
||||||
invokeFunctionToDebounce(prevArguments || args);
|
|
||||||
}
|
|
||||||
|
|
||||||
clearTimeouts(timeoutId);
|
clearTimeouts(timeoutId);
|
||||||
timeoutId = setTimeoutFn(boundInvoke, finalTimeout);
|
timeoutId = setTimeoutFn(boundInvoke, finalTimeout);
|
||||||
|
|
||||||
@@ -550,13 +546,13 @@ const setCSSVal = (elm, prop, val) => {
|
|||||||
try {
|
try {
|
||||||
if (elm) {
|
if (elm) {
|
||||||
const {
|
const {
|
||||||
style
|
style: elmStyle
|
||||||
} = elm;
|
} = elm;
|
||||||
|
|
||||||
if (!isUndefined(style[prop])) {
|
if (!isUndefined(elmStyle[prop])) {
|
||||||
style[prop] = adaptCSSVal(prop, val);
|
elmStyle[prop] = adaptCSSVal(prop, val);
|
||||||
} else {
|
} else {
|
||||||
style.setProperty(prop, val);
|
elmStyle.setProperty(prop, val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (e) {}
|
} catch (e) {}
|
||||||
@@ -717,9 +713,7 @@ const validateRecursive = (options, template, optionsDiff, doWriteErrors, propPa
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
const validateOptions = (options, template, optionsDiff, doWriteErrors) => {
|
const validateOptions = (options, template, optionsDiff, doWriteErrors) => validateRecursive(options, template, optionsDiff || {}, doWriteErrors || false);
|
||||||
return validateRecursive(options, template, optionsDiff || {}, doWriteErrors || false);
|
|
||||||
};
|
|
||||||
|
|
||||||
const transformOptions = optionsWithOptionsTemplate => {
|
const transformOptions = optionsWithOptionsTemplate => {
|
||||||
const result = {
|
const result = {
|
||||||
@@ -1224,7 +1218,7 @@ const createSizeObserver = (target, onSizeChangedCallback, options) => {
|
|||||||
const sizeObserver = baseElements[0];
|
const sizeObserver = baseElements[0];
|
||||||
const listenerElement = sizeObserver.firstChild;
|
const listenerElement = sizeObserver.firstChild;
|
||||||
const getIsDirectionRTL = getElmDirectionIsRTL.bind(0, sizeObserver);
|
const getIsDirectionRTL = getElmDirectionIsRTL.bind(0, sizeObserver);
|
||||||
const [updateResizeObserverContentRectCache] = createCache(0, {
|
const [updateResizeObserverContentRectCache] = createCache({
|
||||||
_initialValue: undefined,
|
_initialValue: undefined,
|
||||||
_alwaysUpdateValues: true,
|
_alwaysUpdateValues: true,
|
||||||
_equal: (currVal, newVal) => !(!currVal || !domRectHasDimensions(currVal) && domRectHasDimensions(newVal))
|
_equal: (currVal, newVal) => !(!currVal || !domRectHasDimensions(currVal) && domRectHasDimensions(newVal))
|
||||||
@@ -1238,7 +1232,7 @@ const createSizeObserver = (target, onSizeChangedCallback, options) => {
|
|||||||
let doDirectionScroll = true;
|
let doDirectionScroll = true;
|
||||||
|
|
||||||
if (isResizeObserverCall) {
|
if (isResizeObserverCall) {
|
||||||
const [currRContentRect,, prevContentRect] = updateResizeObserverContentRectCache(0, sizeChangedContext.pop().contentRect);
|
const [currRContentRect,, prevContentRect] = updateResizeObserverContentRectCache(sizeChangedContext.pop().contentRect);
|
||||||
const hasDimensions = domRectHasDimensions(currRContentRect);
|
const hasDimensions = domRectHasDimensions(currRContentRect);
|
||||||
const hadDimensions = domRectHasDimensions(prevContentRect);
|
const hadDimensions = domRectHasDimensions(prevContentRect);
|
||||||
skip = !prevContentRect || !hasDimensions;
|
skip = !prevContentRect || !hasDimensions;
|
||||||
@@ -1332,9 +1326,9 @@ const createSizeObserver = (target, onSizeChangedCallback, options) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (observeDirectionChange) {
|
if (observeDirectionChange) {
|
||||||
directionIsRTLCache = createCache(getIsDirectionRTL, {
|
directionIsRTLCache = createCache({
|
||||||
_initialValue: !getIsDirectionRTL()
|
_initialValue: !getIsDirectionRTL()
|
||||||
});
|
}, getIsDirectionRTL);
|
||||||
const [updateDirectionIsRTLCache] = directionIsRTLCache;
|
const [updateDirectionIsRTLCache] = directionIsRTLCache;
|
||||||
push(offListeners, on(sizeObserver, scrollEventName, event => {
|
push(offListeners, on(sizeObserver, scrollEventName, event => {
|
||||||
const directionIsRTLCacheValues = updateDirectionIsRTLCache();
|
const directionIsRTLCacheValues = updateDirectionIsRTLCache();
|
||||||
@@ -1379,16 +1373,18 @@ const createSizeObserver = (target, onSizeChangedCallback, options) => {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const isHeightIntrinsic = ioEntryOrSize => ioEntryOrSize.h === 0 || ioEntryOrSize.isIntersecting || ioEntryOrSize.intersectionRatio > 0;
|
||||||
|
|
||||||
const createTrinsicObserver = (target, onTrinsicChangedCallback) => {
|
const createTrinsicObserver = (target, onTrinsicChangedCallback) => {
|
||||||
const trinsicObserver = createDiv(classNameTrinsicObserver);
|
const trinsicObserver = createDiv(classNameTrinsicObserver);
|
||||||
const offListeners = [];
|
const offListeners = [];
|
||||||
const [updateHeightIntrinsicCache, getCurrentHeightIntrinsicCache] = createCache(ioEntryOrSize => ioEntryOrSize.h === 0 || ioEntryOrSize.isIntersecting || ioEntryOrSize.intersectionRatio > 0, {
|
const [updateHeightIntrinsicCache, getCurrentHeightIntrinsicCache] = createCache({
|
||||||
_initialValue: false
|
_initialValue: false
|
||||||
});
|
});
|
||||||
|
|
||||||
const triggerOnTrinsicChangedCallback = updateValue => {
|
const triggerOnTrinsicChangedCallback = updateValue => {
|
||||||
if (updateValue) {
|
if (updateValue) {
|
||||||
const heightIntrinsic = updateHeightIntrinsicCache(0, updateValue);
|
const heightIntrinsic = updateHeightIntrinsicCache(isHeightIntrinsic(updateValue));
|
||||||
const [, heightIntrinsicChanged] = heightIntrinsic;
|
const [, heightIntrinsicChanged] = heightIntrinsic;
|
||||||
|
|
||||||
if (heightIntrinsicChanged) {
|
if (heightIntrinsicChanged) {
|
||||||
@@ -1819,10 +1815,10 @@ const createPaddingLifecycle = lifecycleHub => {
|
|||||||
_padding,
|
_padding,
|
||||||
_viewport
|
_viewport
|
||||||
} = _structureSetup._targetObj;
|
} = _structureSetup._targetObj;
|
||||||
const [updatePaddingCache, currentPaddingCache] = createCache(topRightBottomLeft.bind(0, _host, 'padding'), {
|
const [updatePaddingCache, currentPaddingCache] = createCache({
|
||||||
_equal: equalTRBL,
|
_equal: equalTRBL,
|
||||||
_initialValue: topRightBottomLeft()
|
_initialValue: topRightBottomLeft()
|
||||||
});
|
}, topRightBottomLeft.bind(0, _host, 'padding', ''));
|
||||||
return (updateHints, checkOption, force) => {
|
return (updateHints, checkOption, force) => {
|
||||||
let [padding, paddingChanged] = currentPaddingCache(force);
|
let [padding, paddingChanged] = currentPaddingCache(force);
|
||||||
const {
|
const {
|
||||||
@@ -1927,6 +1923,11 @@ const setAxisOverflowStyle = (horizontal, overflowAmount, behavior, styleObj) =>
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const getOverflowAmount = (viewportScrollSize, viewportClientSize, viewportSizeFraction) => ({
|
||||||
|
w: max(0, round(max(0, viewportScrollSize.w - viewportClientSize.w) - (fractionalPixelRatioTollerance() || max(0, viewportSizeFraction.w)))),
|
||||||
|
h: max(0, round(max(0, viewportScrollSize.h - viewportClientSize.h) - (fractionalPixelRatioTollerance() || max(0, viewportSizeFraction.h))))
|
||||||
|
});
|
||||||
|
|
||||||
const createOverflowLifecycle = lifecycleHub => {
|
const createOverflowLifecycle = lifecycleHub => {
|
||||||
const {
|
const {
|
||||||
_structureSetup,
|
_structureSetup,
|
||||||
@@ -1939,16 +1940,9 @@ const createOverflowLifecycle = lifecycleHub => {
|
|||||||
_viewport,
|
_viewport,
|
||||||
_viewportArrange
|
_viewportArrange
|
||||||
} = _structureSetup._targetObj;
|
} = _structureSetup._targetObj;
|
||||||
const [updateViewportSizeFraction, getCurrentViewportSizeFraction] = createCache(sizeFraction.bind(0, _viewport), whCacheOptions);
|
const [updateViewportSizeFraction, getCurrentViewportSizeFraction] = createCache(whCacheOptions, sizeFraction.bind(0, _viewport));
|
||||||
const [updateViewportScrollSizeCache, getCurrentViewportScrollSizeCache] = createCache(scrollSize.bind(0, _viewport), whCacheOptions);
|
const [updateViewportScrollSizeCache, getCurrentViewportScrollSizeCache] = createCache(whCacheOptions, scrollSize.bind(0, _viewport));
|
||||||
const [updateOverflowAmountCache, getCurrentOverflowAmountCache] = createCache(({
|
const [updateOverflowAmountCache, getCurrentOverflowAmountCache] = createCache(whCacheOptions);
|
||||||
_viewportScrollSize,
|
|
||||||
_viewportClientSize,
|
|
||||||
_viewportSizeFraction
|
|
||||||
}) => ({
|
|
||||||
w: max(0, round(max(0, _viewportScrollSize.w - _viewportClientSize.w) - (fractionalPixelRatioTollerance() || max(0, _viewportSizeFraction.w)))),
|
|
||||||
h: max(0, round(max(0, _viewportScrollSize.h - _viewportClientSize.h) - (fractionalPixelRatioTollerance() || max(0, _viewportSizeFraction.h))))
|
|
||||||
}), whCacheOptions);
|
|
||||||
|
|
||||||
const fixFlexboxGlue = (viewportOverflowState, heightIntrinsic) => {
|
const fixFlexboxGlue = (viewportOverflowState, heightIntrinsic) => {
|
||||||
style(_viewport, {
|
style(_viewport, {
|
||||||
@@ -1998,9 +1992,13 @@ const createOverflowLifecycle = lifecycleHub => {
|
|||||||
x: styleObj.overflowX === 'scroll',
|
x: styleObj.overflowX === 'scroll',
|
||||||
y: styleObj.overflowY === 'scroll'
|
y: styleObj.overflowY === 'scroll'
|
||||||
};
|
};
|
||||||
|
const nonScrollbarStylingHideOffset = {
|
||||||
|
x: overlaidX ? arrangeHideOffset : _nativeScrollbarSize.x,
|
||||||
|
y: overlaidY ? arrangeHideOffset : _nativeScrollbarSize.y
|
||||||
|
};
|
||||||
const scrollbarsHideOffset = {
|
const scrollbarsHideOffset = {
|
||||||
x: scroll.x && !_nativeScrollbarStyling ? overlaidX ? arrangeHideOffset : _nativeScrollbarSize.x : 0,
|
x: scroll.x && !_nativeScrollbarStyling ? nonScrollbarStylingHideOffset.x : 0,
|
||||||
y: scroll.y && !_nativeScrollbarStyling ? overlaidY ? arrangeHideOffset : _nativeScrollbarSize.y : 0
|
y: scroll.y && !_nativeScrollbarStyling ? nonScrollbarStylingHideOffset.y : 0
|
||||||
};
|
};
|
||||||
return {
|
return {
|
||||||
_overflowScroll: scroll,
|
_overflowScroll: scroll,
|
||||||
@@ -2223,30 +2221,26 @@ const createOverflowLifecycle = lifecycleHub => {
|
|||||||
_redoViewportArrange,
|
_redoViewportArrange,
|
||||||
_viewportOverflowState: undoViewportArrangeOverflowState
|
_viewportOverflowState: undoViewportArrangeOverflowState
|
||||||
} = undoViewportArrange(showNativeOverlaidScrollbars, directionIsRTL, preMeasureViewportOverflowState);
|
} = undoViewportArrange(showNativeOverlaidScrollbars, directionIsRTL, preMeasureViewportOverflowState);
|
||||||
const [_viewportSizeFraction2, viewportSizeFractionCahnged] = viewportSizeFractionCache = updateViewportSizeFraction(force);
|
const [_viewportSizeFraction, viewportSizeFractionCahnged] = viewportSizeFractionCache = updateViewportSizeFraction(force);
|
||||||
const [_viewportScrollSize2, _viewportScrollSizeChanged] = viewportScrollSizeCache = updateViewportScrollSizeCache(force);
|
const [_viewportScrollSize, _viewportScrollSizeChanged] = viewportScrollSizeCache = updateViewportScrollSizeCache(force);
|
||||||
const viewportContentSize = clientSize(_viewport);
|
const viewportContentSize = clientSize(_viewport);
|
||||||
let arrangedViewportScrollSize = _viewportScrollSize2;
|
let arrangedViewportScrollSize = _viewportScrollSize;
|
||||||
let arrangedViewportClientSize = viewportContentSize;
|
let arrangedViewportClientSize = viewportContentSize;
|
||||||
|
|
||||||
_redoViewportArrange();
|
_redoViewportArrange();
|
||||||
|
|
||||||
if ((_viewportScrollSizeChanged || viewportSizeFractionCahnged || showNativeOverlaidScrollbarsChanged) && undoViewportArrangeOverflowState && !showNativeOverlaidScrollbars && arrangeViewport(undoViewportArrangeOverflowState, _viewportScrollSize2, _viewportSizeFraction2, directionIsRTL)) {
|
if ((_viewportScrollSizeChanged || viewportSizeFractionCahnged || showNativeOverlaidScrollbarsChanged) && undoViewportArrangeOverflowState && !showNativeOverlaidScrollbars && arrangeViewport(undoViewportArrangeOverflowState, _viewportScrollSize, _viewportSizeFraction, directionIsRTL)) {
|
||||||
arrangedViewportClientSize = clientSize(_viewport);
|
arrangedViewportClientSize = clientSize(_viewport);
|
||||||
arrangedViewportScrollSize = scrollSize(_viewport);
|
arrangedViewportScrollSize = scrollSize(_viewport);
|
||||||
}
|
}
|
||||||
|
|
||||||
overflowAmuntCache = updateOverflowAmountCache(force, {
|
overflowAmuntCache = updateOverflowAmountCache(getOverflowAmount({
|
||||||
_viewportSizeFraction: _viewportSizeFraction2,
|
w: max(_viewportScrollSize.w, arrangedViewportScrollSize.w),
|
||||||
_viewportScrollSize: {
|
h: max(_viewportScrollSize.h, arrangedViewportScrollSize.h)
|
||||||
w: max(_viewportScrollSize2.w, arrangedViewportScrollSize.w),
|
}, {
|
||||||
h: max(_viewportScrollSize2.h, arrangedViewportScrollSize.h)
|
w: arrangedViewportClientSize.w + max(0, viewportContentSize.w - _viewportScrollSize.w),
|
||||||
},
|
h: arrangedViewportClientSize.h + max(0, viewportContentSize.h - _viewportScrollSize.h)
|
||||||
_viewportClientSize: {
|
}, _viewportSizeFraction), force);
|
||||||
w: arrangedViewportClientSize.w + max(0, viewportContentSize.w - _viewportScrollSize2.w),
|
|
||||||
h: arrangedViewportClientSize.h + max(0, viewportContentSize.h - _viewportScrollSize2.h)
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const [viewportSizeFraction, viewportSizeFractionChanged] = viewportSizeFractionCache;
|
const [viewportSizeFraction, viewportSizeFractionChanged] = viewportSizeFractionCache;
|
||||||
@@ -2400,9 +2394,9 @@ const createLifecycleHub = (options, structureSetup, scrollbarsSetup) => {
|
|||||||
_destroy: destroyObservers
|
_destroy: destroyObservers
|
||||||
} = lifecycleHubOservers(instance, updateLifecycles);
|
} = lifecycleHubOservers(instance, updateLifecycles);
|
||||||
|
|
||||||
const update = (changedOptions, force) => updateLifecycles(null, changedOptions, force);
|
const update = (changedOptions, force) => updateLifecycles({}, changedOptions, force);
|
||||||
|
|
||||||
const envUpdateListener = update.bind(null, null, true);
|
const envUpdateListener = update.bind(0, {}, true);
|
||||||
addEnvironmentListener(envUpdateListener);
|
addEnvironmentListener(envUpdateListener);
|
||||||
console.log(getEnvironment());
|
console.log(getEnvironment());
|
||||||
return {
|
return {
|
||||||
@@ -2451,7 +2445,7 @@ const OverlayScrollbars = (target, options, extensions) => {
|
|||||||
state: () => lifecycleHub._state(),
|
state: () => lifecycleHub._state(),
|
||||||
|
|
||||||
update(force) {
|
update(force) {
|
||||||
lifecycleHub._update(null, force);
|
lifecycleHub._update({}, force);
|
||||||
},
|
},
|
||||||
|
|
||||||
destroy: () => lifecycleHub._destroy()
|
destroy: () => lifecycleHub._destroy()
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+76
-74
@@ -4,19 +4,17 @@
|
|||||||
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.OverlayScrollbars = factory());
|
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.OverlayScrollbars = factory());
|
||||||
})(this, (function () { 'use strict';
|
})(this, (function () { 'use strict';
|
||||||
|
|
||||||
var createCache = function createCache(update, options) {
|
function createCache(options, update) {
|
||||||
var _ref = options || {},
|
var _initialValue = options._initialValue,
|
||||||
_initialValue = _ref._initialValue,
|
_equal = options._equal,
|
||||||
_equal = _ref._equal,
|
_alwaysUpdateValues = options._alwaysUpdateValues;
|
||||||
_alwaysUpdateValues = _ref._alwaysUpdateValues;
|
|
||||||
|
|
||||||
var _value = _initialValue;
|
var _value = _initialValue;
|
||||||
|
|
||||||
var _previous;
|
var _previous;
|
||||||
|
|
||||||
var cacheUpdate = function cacheUpdate(force, context) {
|
var cacheUpdateContextual = function cacheUpdateContextual(newValue, force) {
|
||||||
var curr = _value;
|
var curr = _value;
|
||||||
var newVal = update ? update(context, _value, _previous) : context;
|
var newVal = newValue;
|
||||||
var changed = force || (_equal ? !_equal(curr, newVal) : curr !== newVal);
|
var changed = force || (_equal ? !_equal(curr, newVal) : curr !== newVal);
|
||||||
|
|
||||||
if (changed || _alwaysUpdateValues) {
|
if (changed || _alwaysUpdateValues) {
|
||||||
@@ -27,10 +25,16 @@
|
|||||||
return [_value, changed, _previous];
|
return [_value, changed, _previous];
|
||||||
};
|
};
|
||||||
|
|
||||||
return [cacheUpdate, function (force) {
|
var cacheUpdateIsolated = function cacheUpdateIsolated(force) {
|
||||||
|
return cacheUpdateContextual(update(_value, _previous), force);
|
||||||
|
};
|
||||||
|
|
||||||
|
var getCurrentCache = function getCurrentCache(force) {
|
||||||
return [_value, !!force, _previous];
|
return [_value, !!force, _previous];
|
||||||
}];
|
};
|
||||||
};
|
|
||||||
|
return [update ? cacheUpdateIsolated : cacheUpdateContextual, getCurrentCache];
|
||||||
|
}
|
||||||
|
|
||||||
var ElementNodeType = Node.ELEMENT_NODE;
|
var ElementNodeType = Node.ELEMENT_NODE;
|
||||||
var _Object$prototype = Object.prototype,
|
var _Object$prototype = Object.prototype,
|
||||||
@@ -110,7 +114,7 @@
|
|||||||
return source;
|
return source;
|
||||||
}
|
}
|
||||||
var indexOf = function indexOf(arr, item, fromIndex) {
|
var indexOf = function indexOf(arr, item, fromIndex) {
|
||||||
return arr.indexOf(item, fromIndex);
|
return isArray(arr) ? arr.indexOf(item, fromIndex) : -1;
|
||||||
};
|
};
|
||||||
var push = function push(array, items, arrayIsSingleItem) {
|
var push = function push(array, items, arrayIsSingleItem) {
|
||||||
!arrayIsSingleItem && !isString(items) && isArrayLike(items) ? Array.prototype.push.apply(array, items) : array.push(items);
|
!arrayIsSingleItem && !isString(items) && isArrayLike(items) ? Array.prototype.push.apply(array, items) : array.push(items);
|
||||||
@@ -128,7 +132,7 @@
|
|||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
var isEmptyArray = function isEmptyArray(array) {
|
var isEmptyArray = function isEmptyArray(array) {
|
||||||
return array && array.length === 0;
|
return !!array && array.length === 0;
|
||||||
};
|
};
|
||||||
var runEach = function runEach(arr, p1) {
|
var runEach = function runEach(arr, p1) {
|
||||||
var runFn = function runFn(fn) {
|
var runFn = function runFn(fn) {
|
||||||
@@ -529,8 +533,6 @@
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
var setT = window.setTimeout;
|
|
||||||
|
|
||||||
var clearTimeouts = function clearTimeouts(id) {
|
var clearTimeouts = function clearTimeouts(id) {
|
||||||
id && window.clearTimeout(id);
|
id && window.clearTimeout(id);
|
||||||
id && cAF(id);
|
id && cAF(id);
|
||||||
@@ -542,9 +544,13 @@
|
|||||||
var maxTimeoutId;
|
var maxTimeoutId;
|
||||||
var prevArguments;
|
var prevArguments;
|
||||||
var latestArguments;
|
var latestArguments;
|
||||||
var _timeout = options._timeout,
|
|
||||||
_maxDelay = options._maxDelay,
|
var _ref = options || {},
|
||||||
_mergeParams = options._mergeParams;
|
_timeout = _ref._timeout,
|
||||||
|
_maxDelay = _ref._maxDelay,
|
||||||
|
_mergeParams = _ref._mergeParams;
|
||||||
|
|
||||||
|
var setT = window.setTimeout;
|
||||||
|
|
||||||
var invokeFunctionToDebounce = function invokeFunctionToDebounce(args) {
|
var invokeFunctionToDebounce = function invokeFunctionToDebounce(args) {
|
||||||
clearTimeouts(timeoutId);
|
clearTimeouts(timeoutId);
|
||||||
@@ -564,7 +570,7 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
var debouncedFn = function debouncedFn() {
|
var debouncedFn = function debouncedFn() {
|
||||||
var args = arguments;
|
var args = from(arguments);
|
||||||
var finalTimeout = isFunction(_timeout) ? _timeout() : _timeout;
|
var finalTimeout = isFunction(_timeout) ? _timeout() : _timeout;
|
||||||
var hasTimeout = isNumber(finalTimeout) && finalTimeout >= 0;
|
var hasTimeout = isNumber(finalTimeout) && finalTimeout >= 0;
|
||||||
|
|
||||||
@@ -575,11 +581,6 @@
|
|||||||
var mergeParamsResult = mergeParms(args);
|
var mergeParamsResult = mergeParms(args);
|
||||||
var invokedArgs = mergeParamsResult || args;
|
var invokedArgs = mergeParamsResult || args;
|
||||||
var boundInvoke = invokeFunctionToDebounce.bind(0, invokedArgs);
|
var boundInvoke = invokeFunctionToDebounce.bind(0, invokedArgs);
|
||||||
|
|
||||||
if (!mergeParamsResult) {
|
|
||||||
invokeFunctionToDebounce(prevArguments || args);
|
|
||||||
}
|
|
||||||
|
|
||||||
clearTimeouts(timeoutId);
|
clearTimeouts(timeoutId);
|
||||||
timeoutId = setTimeoutFn(boundInvoke, finalTimeout);
|
timeoutId = setTimeoutFn(boundInvoke, finalTimeout);
|
||||||
|
|
||||||
@@ -618,12 +619,12 @@
|
|||||||
var setCSSVal = function setCSSVal(elm, prop, val) {
|
var setCSSVal = function setCSSVal(elm, prop, val) {
|
||||||
try {
|
try {
|
||||||
if (elm) {
|
if (elm) {
|
||||||
var _style = elm.style;
|
var elmStyle = elm.style;
|
||||||
|
|
||||||
if (!isUndefined(_style[prop])) {
|
if (!isUndefined(elmStyle[prop])) {
|
||||||
_style[prop] = adaptCSSVal(prop, val);
|
elmStyle[prop] = adaptCSSVal(prop, val);
|
||||||
} else {
|
} else {
|
||||||
_style.setProperty(prop, val);
|
elmStyle.setProperty(prop, val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (e) {}
|
} catch (e) {}
|
||||||
@@ -1288,7 +1289,7 @@
|
|||||||
var listenerElement = sizeObserver.firstChild;
|
var listenerElement = sizeObserver.firstChild;
|
||||||
var getIsDirectionRTL = getElmDirectionIsRTL.bind(0, sizeObserver);
|
var getIsDirectionRTL = getElmDirectionIsRTL.bind(0, sizeObserver);
|
||||||
|
|
||||||
var _createCache = createCache(0, {
|
var _createCache = createCache({
|
||||||
_initialValue: undefined,
|
_initialValue: undefined,
|
||||||
_alwaysUpdateValues: true,
|
_alwaysUpdateValues: true,
|
||||||
_equal: function _equal(currVal, newVal) {
|
_equal: function _equal(currVal, newVal) {
|
||||||
@@ -1305,7 +1306,7 @@
|
|||||||
var doDirectionScroll = true;
|
var doDirectionScroll = true;
|
||||||
|
|
||||||
if (isResizeObserverCall) {
|
if (isResizeObserverCall) {
|
||||||
var _updateResizeObserver = updateResizeObserverContentRectCache(0, sizeChangedContext.pop().contentRect),
|
var _updateResizeObserver = updateResizeObserverContentRectCache(sizeChangedContext.pop().contentRect),
|
||||||
currRContentRect = _updateResizeObserver[0],
|
currRContentRect = _updateResizeObserver[0],
|
||||||
prevContentRect = _updateResizeObserver[2];
|
prevContentRect = _updateResizeObserver[2];
|
||||||
|
|
||||||
@@ -1402,9 +1403,9 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (observeDirectionChange) {
|
if (observeDirectionChange) {
|
||||||
directionIsRTLCache = createCache(getIsDirectionRTL, {
|
directionIsRTLCache = createCache({
|
||||||
_initialValue: !getIsDirectionRTL()
|
_initialValue: !getIsDirectionRTL()
|
||||||
});
|
}, getIsDirectionRTL);
|
||||||
var _directionIsRTLCache = directionIsRTLCache,
|
var _directionIsRTLCache = directionIsRTLCache,
|
||||||
updateDirectionIsRTLCache = _directionIsRTLCache[0];
|
updateDirectionIsRTLCache = _directionIsRTLCache[0];
|
||||||
push(offListeners, on(sizeObserver, scrollEventName, function (event) {
|
push(offListeners, on(sizeObserver, scrollEventName, function (event) {
|
||||||
@@ -1449,13 +1450,15 @@
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var isHeightIntrinsic = function isHeightIntrinsic(ioEntryOrSize) {
|
||||||
|
return ioEntryOrSize.h === 0 || ioEntryOrSize.isIntersecting || ioEntryOrSize.intersectionRatio > 0;
|
||||||
|
};
|
||||||
|
|
||||||
var createTrinsicObserver = function createTrinsicObserver(target, onTrinsicChangedCallback) {
|
var createTrinsicObserver = function createTrinsicObserver(target, onTrinsicChangedCallback) {
|
||||||
var trinsicObserver = createDiv(classNameTrinsicObserver);
|
var trinsicObserver = createDiv(classNameTrinsicObserver);
|
||||||
var offListeners = [];
|
var offListeners = [];
|
||||||
|
|
||||||
var _createCache = createCache(function (ioEntryOrSize) {
|
var _createCache = createCache({
|
||||||
return ioEntryOrSize.h === 0 || ioEntryOrSize.isIntersecting || ioEntryOrSize.intersectionRatio > 0;
|
|
||||||
}, {
|
|
||||||
_initialValue: false
|
_initialValue: false
|
||||||
}),
|
}),
|
||||||
updateHeightIntrinsicCache = _createCache[0],
|
updateHeightIntrinsicCache = _createCache[0],
|
||||||
@@ -1463,7 +1466,7 @@
|
|||||||
|
|
||||||
var triggerOnTrinsicChangedCallback = function triggerOnTrinsicChangedCallback(updateValue) {
|
var triggerOnTrinsicChangedCallback = function triggerOnTrinsicChangedCallback(updateValue) {
|
||||||
if (updateValue) {
|
if (updateValue) {
|
||||||
var heightIntrinsic = updateHeightIntrinsicCache(0, updateValue);
|
var heightIntrinsic = updateHeightIntrinsicCache(isHeightIntrinsic(updateValue));
|
||||||
var heightIntrinsicChanged = heightIntrinsic[1];
|
var heightIntrinsicChanged = heightIntrinsic[1];
|
||||||
|
|
||||||
if (heightIntrinsicChanged) {
|
if (heightIntrinsicChanged) {
|
||||||
@@ -1889,10 +1892,10 @@
|
|||||||
_padding = _structureSetup$_targ._padding,
|
_padding = _structureSetup$_targ._padding,
|
||||||
_viewport = _structureSetup$_targ._viewport;
|
_viewport = _structureSetup$_targ._viewport;
|
||||||
|
|
||||||
var _createCache = createCache(topRightBottomLeft.bind(0, _host, 'padding'), {
|
var _createCache = createCache({
|
||||||
_equal: equalTRBL,
|
_equal: equalTRBL,
|
||||||
_initialValue: topRightBottomLeft()
|
_initialValue: topRightBottomLeft()
|
||||||
}),
|
}, topRightBottomLeft.bind(0, _host, 'padding', '')),
|
||||||
updatePaddingCache = _createCache[0],
|
updatePaddingCache = _createCache[0],
|
||||||
currentPaddingCache = _createCache[1];
|
currentPaddingCache = _createCache[1];
|
||||||
|
|
||||||
@@ -2009,6 +2012,13 @@
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var getOverflowAmount = function getOverflowAmount(viewportScrollSize, viewportClientSize, viewportSizeFraction) {
|
||||||
|
return {
|
||||||
|
w: max(0, round(max(0, viewportScrollSize.w - viewportClientSize.w) - (fractionalPixelRatioTollerance() || max(0, viewportSizeFraction.w)))),
|
||||||
|
h: max(0, round(max(0, viewportScrollSize.h - viewportClientSize.h) - (fractionalPixelRatioTollerance() || max(0, viewportSizeFraction.h))))
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
var createOverflowLifecycle = function createOverflowLifecycle(lifecycleHub) {
|
var createOverflowLifecycle = function createOverflowLifecycle(lifecycleHub) {
|
||||||
var _structureSetup = lifecycleHub._structureSetup,
|
var _structureSetup = lifecycleHub._structureSetup,
|
||||||
_doViewportArrange = lifecycleHub._doViewportArrange,
|
_doViewportArrange = lifecycleHub._doViewportArrange,
|
||||||
@@ -2019,23 +2029,15 @@
|
|||||||
_viewport = _structureSetup$_targ._viewport,
|
_viewport = _structureSetup$_targ._viewport,
|
||||||
_viewportArrange = _structureSetup$_targ._viewportArrange;
|
_viewportArrange = _structureSetup$_targ._viewportArrange;
|
||||||
|
|
||||||
var _createCache = createCache(sizeFraction.bind(0, _viewport), whCacheOptions),
|
var _createCache = createCache(whCacheOptions, sizeFraction.bind(0, _viewport)),
|
||||||
updateViewportSizeFraction = _createCache[0],
|
updateViewportSizeFraction = _createCache[0],
|
||||||
getCurrentViewportSizeFraction = _createCache[1];
|
getCurrentViewportSizeFraction = _createCache[1];
|
||||||
|
|
||||||
var _createCache2 = createCache(scrollSize.bind(0, _viewport), whCacheOptions),
|
var _createCache2 = createCache(whCacheOptions, scrollSize.bind(0, _viewport)),
|
||||||
updateViewportScrollSizeCache = _createCache2[0],
|
updateViewportScrollSizeCache = _createCache2[0],
|
||||||
getCurrentViewportScrollSizeCache = _createCache2[1];
|
getCurrentViewportScrollSizeCache = _createCache2[1];
|
||||||
|
|
||||||
var _createCache3 = createCache(function (_ref) {
|
var _createCache3 = createCache(whCacheOptions),
|
||||||
var _viewportScrollSize = _ref._viewportScrollSize,
|
|
||||||
_viewportClientSize = _ref._viewportClientSize,
|
|
||||||
_viewportSizeFraction = _ref._viewportSizeFraction;
|
|
||||||
return {
|
|
||||||
w: max(0, round(max(0, _viewportScrollSize.w - _viewportClientSize.w) - (fractionalPixelRatioTollerance() || max(0, _viewportSizeFraction.w)))),
|
|
||||||
h: max(0, round(max(0, _viewportScrollSize.h - _viewportClientSize.h) - (fractionalPixelRatioTollerance() || max(0, _viewportSizeFraction.h))))
|
|
||||||
};
|
|
||||||
}, whCacheOptions),
|
|
||||||
updateOverflowAmountCache = _createCache3[0],
|
updateOverflowAmountCache = _createCache3[0],
|
||||||
getCurrentOverflowAmountCache = _createCache3[1];
|
getCurrentOverflowAmountCache = _createCache3[1];
|
||||||
|
|
||||||
@@ -2081,9 +2083,13 @@
|
|||||||
x: styleObj.overflowX === 'scroll',
|
x: styleObj.overflowX === 'scroll',
|
||||||
y: styleObj.overflowY === 'scroll'
|
y: styleObj.overflowY === 'scroll'
|
||||||
};
|
};
|
||||||
|
var nonScrollbarStylingHideOffset = {
|
||||||
|
x: overlaidX ? arrangeHideOffset : _nativeScrollbarSize.x,
|
||||||
|
y: overlaidY ? arrangeHideOffset : _nativeScrollbarSize.y
|
||||||
|
};
|
||||||
var scrollbarsHideOffset = {
|
var scrollbarsHideOffset = {
|
||||||
x: scroll.x && !_nativeScrollbarStyling ? overlaidX ? arrangeHideOffset : _nativeScrollbarSize.x : 0,
|
x: scroll.x && !_nativeScrollbarStyling ? nonScrollbarStylingHideOffset.x : 0,
|
||||||
y: scroll.y && !_nativeScrollbarStyling ? overlaidY ? arrangeHideOffset : _nativeScrollbarSize.y : 0
|
y: scroll.y && !_nativeScrollbarStyling ? nonScrollbarStylingHideOffset.y : 0
|
||||||
};
|
};
|
||||||
return {
|
return {
|
||||||
_overflowScroll: scroll,
|
_overflowScroll: scroll,
|
||||||
@@ -2289,41 +2295,37 @@
|
|||||||
_redoViewportArrange = _undoViewportArrange._redoViewportArrange,
|
_redoViewportArrange = _undoViewportArrange._redoViewportArrange,
|
||||||
undoViewportArrangeOverflowState = _undoViewportArrange._viewportOverflowState;
|
undoViewportArrangeOverflowState = _undoViewportArrange._viewportOverflowState;
|
||||||
|
|
||||||
var _viewportSizeFraction3 = viewportSizeFractionCache = updateViewportSizeFraction(force),
|
var _viewportSizeFraction2 = viewportSizeFractionCache = updateViewportSizeFraction(force),
|
||||||
_viewportSizeFraction2 = _viewportSizeFraction3[0],
|
_viewportSizeFraction = _viewportSizeFraction2[0],
|
||||||
viewportSizeFractionCahnged = _viewportSizeFraction3[1];
|
viewportSizeFractionCahnged = _viewportSizeFraction2[1];
|
||||||
|
|
||||||
var _viewportScrollSizeCa = viewportScrollSizeCache = updateViewportScrollSizeCache(force),
|
var _viewportScrollSizeCa = viewportScrollSizeCache = updateViewportScrollSizeCache(force),
|
||||||
_viewportScrollSize2 = _viewportScrollSizeCa[0],
|
_viewportScrollSize = _viewportScrollSizeCa[0],
|
||||||
_viewportScrollSizeChanged = _viewportScrollSizeCa[1];
|
_viewportScrollSizeChanged = _viewportScrollSizeCa[1];
|
||||||
|
|
||||||
var viewportContentSize = clientSize(_viewport);
|
var viewportContentSize = clientSize(_viewport);
|
||||||
var arrangedViewportScrollSize = _viewportScrollSize2;
|
var arrangedViewportScrollSize = _viewportScrollSize;
|
||||||
var arrangedViewportClientSize = viewportContentSize;
|
var arrangedViewportClientSize = viewportContentSize;
|
||||||
|
|
||||||
_redoViewportArrange();
|
_redoViewportArrange();
|
||||||
|
|
||||||
if ((_viewportScrollSizeChanged || viewportSizeFractionCahnged || showNativeOverlaidScrollbarsChanged) && undoViewportArrangeOverflowState && !showNativeOverlaidScrollbars && arrangeViewport(undoViewportArrangeOverflowState, _viewportScrollSize2, _viewportSizeFraction2, directionIsRTL)) {
|
if ((_viewportScrollSizeChanged || viewportSizeFractionCahnged || showNativeOverlaidScrollbarsChanged) && undoViewportArrangeOverflowState && !showNativeOverlaidScrollbars && arrangeViewport(undoViewportArrangeOverflowState, _viewportScrollSize, _viewportSizeFraction, directionIsRTL)) {
|
||||||
arrangedViewportClientSize = clientSize(_viewport);
|
arrangedViewportClientSize = clientSize(_viewport);
|
||||||
arrangedViewportScrollSize = scrollSize(_viewport);
|
arrangedViewportScrollSize = scrollSize(_viewport);
|
||||||
}
|
}
|
||||||
|
|
||||||
overflowAmuntCache = updateOverflowAmountCache(force, {
|
overflowAmuntCache = updateOverflowAmountCache(getOverflowAmount({
|
||||||
_viewportSizeFraction: _viewportSizeFraction2,
|
w: max(_viewportScrollSize.w, arrangedViewportScrollSize.w),
|
||||||
_viewportScrollSize: {
|
h: max(_viewportScrollSize.h, arrangedViewportScrollSize.h)
|
||||||
w: max(_viewportScrollSize2.w, arrangedViewportScrollSize.w),
|
}, {
|
||||||
h: max(_viewportScrollSize2.h, arrangedViewportScrollSize.h)
|
w: arrangedViewportClientSize.w + max(0, viewportContentSize.w - _viewportScrollSize.w),
|
||||||
},
|
h: arrangedViewportClientSize.h + max(0, viewportContentSize.h - _viewportScrollSize.h)
|
||||||
_viewportClientSize: {
|
}, _viewportSizeFraction), force);
|
||||||
w: arrangedViewportClientSize.w + max(0, viewportContentSize.w - _viewportScrollSize2.w),
|
|
||||||
h: arrangedViewportClientSize.h + max(0, viewportContentSize.h - _viewportScrollSize2.h)
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var _viewportSizeFraction4 = viewportSizeFractionCache,
|
var _viewportSizeFraction3 = viewportSizeFractionCache,
|
||||||
viewportSizeFraction = _viewportSizeFraction4[0],
|
viewportSizeFraction = _viewportSizeFraction3[0],
|
||||||
viewportSizeFractionChanged = _viewportSizeFraction4[1];
|
viewportSizeFractionChanged = _viewportSizeFraction3[1];
|
||||||
var _viewportScrollSizeCa2 = viewportScrollSizeCache,
|
var _viewportScrollSizeCa2 = viewportScrollSizeCache,
|
||||||
viewportScrollSize = _viewportScrollSizeCa2[0],
|
viewportScrollSize = _viewportScrollSizeCa2[0],
|
||||||
viewportScrollSizeChanged = _viewportScrollSizeCa2[1];
|
viewportScrollSizeChanged = _viewportScrollSizeCa2[1];
|
||||||
@@ -2490,10 +2492,10 @@
|
|||||||
destroyObservers = _lifecycleHubOservers._destroy;
|
destroyObservers = _lifecycleHubOservers._destroy;
|
||||||
|
|
||||||
var update = function update(changedOptions, force) {
|
var update = function update(changedOptions, force) {
|
||||||
return updateLifecycles(null, changedOptions, force);
|
return updateLifecycles({}, changedOptions, force);
|
||||||
};
|
};
|
||||||
|
|
||||||
var envUpdateListener = update.bind(null, null, true);
|
var envUpdateListener = update.bind(0, {}, true);
|
||||||
addEnvironmentListener(envUpdateListener);
|
addEnvironmentListener(envUpdateListener);
|
||||||
console.log(getEnvironment());
|
console.log(getEnvironment());
|
||||||
return {
|
return {
|
||||||
@@ -2541,7 +2543,7 @@
|
|||||||
return lifecycleHub._state();
|
return lifecycleHub._state();
|
||||||
},
|
},
|
||||||
update: function update(force) {
|
update: function update(force) {
|
||||||
lifecycleHub._update(null, force);
|
lifecycleHub._update({}, force);
|
||||||
},
|
},
|
||||||
destroy: function destroy() {
|
destroy: function destroy() {
|
||||||
return lifecycleHub._destroy();
|
return lifecycleHub._destroy();
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -23,7 +23,7 @@ const createAutoUpdateLoop = (): AutoUpdateLoop => {
|
|||||||
const updateLoopInterval = () => {
|
const updateLoopInterval = () => {
|
||||||
loopInterval = isEmptyArray(intervals) ? defaultLoopInterval : Math.min.apply(null, intervals);
|
loopInterval = isEmptyArray(intervals) ? defaultLoopInterval : Math.min.apply(null, intervals);
|
||||||
};
|
};
|
||||||
const { _update: updateTimeCache } = createCache<number, number | undefined>((ctx) => ctx || performance.now(), {
|
const [updateTimeCache] = createCache<number>({
|
||||||
_initialValue: performance.now(),
|
_initialValue: performance.now(),
|
||||||
_equal: (currTime, newTime) => {
|
_equal: (currTime, newTime) => {
|
||||||
const delta = newTime! - currTime!;
|
const delta = newTime! - currTime!;
|
||||||
@@ -34,9 +34,9 @@ const createAutoUpdateLoop = (): AutoUpdateLoop => {
|
|||||||
/* istanbul ignore next */
|
/* istanbul ignore next */
|
||||||
if (!isEmptyArray(loopFunctions) && loopIsRunning) {
|
if (!isEmptyArray(loopFunctions) && loopIsRunning) {
|
||||||
loopId = rAF!(loop);
|
loopId = rAF!(loop);
|
||||||
const { _changed, _value, _previous } = updateTimeCache(0, newTime);
|
const [value, changed, previous] = updateTimeCache(newTime || performance.now());
|
||||||
if (_changed) {
|
if (changed) {
|
||||||
runEach(loopFunctions, _value! - _previous!);
|
runEach(loopFunctions, value - previous!);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -60,9 +60,9 @@ const createAutoUpdateLoop = (): AutoUpdateLoop => {
|
|||||||
push(loopFunctions, fn);
|
push(loopFunctions, fn);
|
||||||
|
|
||||||
if (!loopIsRunning && !isEmptyArray(loopFunctions)) {
|
if (!loopIsRunning && !isEmptyArray(loopFunctions)) {
|
||||||
//getEnvironment()._autoUpdateLoop = loopIsRunning = true;
|
// getEnvironment()._autoUpdateLoop = loopIsRunning = true;
|
||||||
|
|
||||||
updateTimeCache(true);
|
updateTimeCache(performance.now(), true);
|
||||||
loop();
|
loop();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -70,7 +70,7 @@ const createAutoUpdateLoop = (): AutoUpdateLoop => {
|
|||||||
loopFunctions.splice(indexOf(loopFunctions, fn), 1);
|
loopFunctions.splice(indexOf(loopFunctions, fn), 1);
|
||||||
|
|
||||||
if (isEmptyArray(loopFunctions) && loopIsRunning) {
|
if (isEmptyArray(loopFunctions) && loopIsRunning) {
|
||||||
//getEnvironment()._autoUpdateLoop = loopIsRunning = false;
|
// getEnvironment()._autoUpdateLoop = loopIsRunning = false;
|
||||||
|
|
||||||
cAF!(loopId!);
|
cAF!(loopId!);
|
||||||
loopId = undefined;
|
loopId = undefined;
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ export interface LifecycleHubState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface LifecycleHubInstance {
|
export interface LifecycleHubInstance {
|
||||||
_update(changedOptions?: PartialOptions<OSOptions> | null, force?: boolean): void;
|
_update(changedOptions: PartialOptions<OSOptions>, force?: boolean): void;
|
||||||
_state(): LifecycleHubState;
|
_state(): LifecycleHubState;
|
||||||
_destroy(): void;
|
_destroy(): void;
|
||||||
}
|
}
|
||||||
@@ -139,8 +139,8 @@ export const createLifecycleHub = (
|
|||||||
];
|
];
|
||||||
|
|
||||||
const updateLifecycles = (
|
const updateLifecycles = (
|
||||||
updateHints?: Partial<LifecycleUpdateHints> | null,
|
updateHints: Partial<LifecycleUpdateHints>,
|
||||||
changedOptions?: Partial<OSOptions> | null,
|
changedOptions?: Partial<OSOptions>,
|
||||||
force?: boolean
|
force?: boolean
|
||||||
) => {
|
) => {
|
||||||
let {
|
let {
|
||||||
@@ -221,9 +221,9 @@ export const createLifecycleHub = (
|
|||||||
_destroy: destroyObservers,
|
_destroy: destroyObservers,
|
||||||
} = lifecycleHubOservers(instance, updateLifecycles);
|
} = lifecycleHubOservers(instance, updateLifecycles);
|
||||||
|
|
||||||
const update = (changedOptions?: Partial<OSOptions> | null, force?: boolean) =>
|
const update = (changedOptions: Partial<OSOptions>, force?: boolean) =>
|
||||||
updateLifecycles(null, changedOptions, force);
|
updateLifecycles({}, changedOptions, force);
|
||||||
const envUpdateListener = update.bind(null, null, true);
|
const envUpdateListener = update.bind(0, {}, true);
|
||||||
addEnvironmentListener(envUpdateListener);
|
addEnvironmentListener(envUpdateListener);
|
||||||
|
|
||||||
console.log(getEnvironment());
|
console.log(getEnvironment());
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ const ignoreTargetChange = (
|
|||||||
|
|
||||||
export const lifecycleHubOservers = (
|
export const lifecycleHubOservers = (
|
||||||
instance: LifecycleHub,
|
instance: LifecycleHub,
|
||||||
updateLifecycles: (updateHints?: Partial<LifecycleUpdateHints> | null) => unknown
|
updateLifecycles: (updateHints: Partial<LifecycleUpdateHints>) => unknown
|
||||||
) => {
|
) => {
|
||||||
let debounceTimeout: number | false | undefined;
|
let debounceTimeout: number | false | undefined;
|
||||||
let debounceMaxDelay: number | false | undefined;
|
let debounceMaxDelay: number | false | undefined;
|
||||||
@@ -57,34 +57,31 @@ export const lifecycleHubOservers = (
|
|||||||
const contentMutationObserverAttr = _isTextarea
|
const contentMutationObserverAttr = _isTextarea
|
||||||
? baseStyleChangingAttrsTextarea
|
? baseStyleChangingAttrsTextarea
|
||||||
: baseStyleChangingAttrs.concat(baseStyleChangingAttrsTextarea);
|
: baseStyleChangingAttrs.concat(baseStyleChangingAttrsTextarea);
|
||||||
const updateLifecyclesWithDebouncedAdaptiveUpdateHints = debounce(
|
const updateLifecyclesWithDebouncedAdaptiveUpdateHints = debounce(updateLifecycles, {
|
||||||
updateLifecycles as (updateHints: Partial<LifecycleUpdateHints>) => any,
|
_timeout: () => debounceTimeout,
|
||||||
{
|
_maxDelay: () => debounceMaxDelay,
|
||||||
_timeout: () => debounceTimeout,
|
_mergeParams(prev, curr) {
|
||||||
_maxDelay: () => debounceMaxDelay,
|
const {
|
||||||
_mergeParams(prev, curr) {
|
_sizeChanged: prevSizeChanged,
|
||||||
const {
|
_hostMutation: prevHostMutation,
|
||||||
_sizeChanged: prevSizeChanged,
|
_contentMutation: prevContentMutation,
|
||||||
_hostMutation: prevHostMutation,
|
} = prev[0];
|
||||||
_contentMutation: prevContentMutation,
|
const {
|
||||||
} = prev[0];
|
_sizeChanged: currSizeChanged,
|
||||||
const {
|
_hostMutation: currvHostMutation,
|
||||||
_sizeChanged: currSizeChanged,
|
_contentMutation: currContentMutation,
|
||||||
_hostMutation: currvHostMutation,
|
} = curr[0];
|
||||||
_contentMutation: currContentMutation,
|
const merged: [Partial<LifecycleUpdateHints>] = [
|
||||||
} = curr[0];
|
{
|
||||||
const merged: [Partial<LifecycleUpdateHints>] = [
|
_sizeChanged: prevSizeChanged || currSizeChanged,
|
||||||
{
|
_hostMutation: prevHostMutation || currvHostMutation,
|
||||||
_sizeChanged: prevSizeChanged || currSizeChanged,
|
_contentMutation: prevContentMutation || currContentMutation,
|
||||||
_hostMutation: prevHostMutation || currvHostMutation,
|
},
|
||||||
_contentMutation: prevContentMutation || currContentMutation,
|
];
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
return merged;
|
return merged;
|
||||||
},
|
},
|
||||||
}
|
});
|
||||||
);
|
|
||||||
|
|
||||||
const updateViewportAttrsFromHost = (attributes?: string[]) => {
|
const updateViewportAttrsFromHost = (attributes?: string[]) => {
|
||||||
each(attributes || viewportAttrsFromTarget, (attribute) => {
|
each(attributes || viewportAttrsFromTarget, (attribute) => {
|
||||||
|
|||||||
@@ -22,12 +22,6 @@ import { OverflowBehavior } from 'options';
|
|||||||
import { StyleObject } from 'typings';
|
import { StyleObject } from 'typings';
|
||||||
import { classNameViewportArrange, classNameViewportScrollbarStyling } from 'classnames';
|
import { classNameViewportArrange, classNameViewportScrollbarStyling } from 'classnames';
|
||||||
|
|
||||||
interface OverflowAmountCacheContext {
|
|
||||||
_viewportScrollSize: WH<number>;
|
|
||||||
_viewportClientSize: WH<number>;
|
|
||||||
_viewportSizeFraction: WH<number>;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface ViewportOverflowState {
|
interface ViewportOverflowState {
|
||||||
_scrollbarsHideOffset: XY<number>;
|
_scrollbarsHideOffset: XY<number>;
|
||||||
_scrollbarsHideOffsetArrange: XY<boolean>;
|
_scrollbarsHideOffsetArrange: XY<boolean>;
|
||||||
@@ -84,6 +78,27 @@ const setAxisOverflowStyle = (
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const getOverflowAmount = (
|
||||||
|
viewportScrollSize: WH<number>,
|
||||||
|
viewportClientSize: WH<number>,
|
||||||
|
viewportSizeFraction: WH<number>
|
||||||
|
) => ({
|
||||||
|
w: max(
|
||||||
|
0,
|
||||||
|
round(
|
||||||
|
max(0, viewportScrollSize.w - viewportClientSize.w) -
|
||||||
|
(fractionalPixelRatioTollerance() || max(0, viewportSizeFraction.w))
|
||||||
|
)
|
||||||
|
),
|
||||||
|
h: max(
|
||||||
|
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.
|
||||||
* @param lifecycleHub
|
* @param lifecycleHub
|
||||||
@@ -100,34 +115,15 @@ export const createOverflowLifecycle = (lifecycleHub: LifecycleHub): Lifecycle =
|
|||||||
const { _host, _viewport, _viewportArrange } = _structureSetup._targetObj;
|
const { _host, _viewport, _viewportArrange } = _structureSetup._targetObj;
|
||||||
|
|
||||||
const [updateViewportSizeFraction, getCurrentViewportSizeFraction] = createCache<WH<number>>(
|
const [updateViewportSizeFraction, getCurrentViewportSizeFraction] = createCache<WH<number>>(
|
||||||
sizeFraction.bind(0, _viewport),
|
whCacheOptions,
|
||||||
whCacheOptions
|
sizeFraction.bind(0, _viewport)
|
||||||
);
|
);
|
||||||
|
|
||||||
const [updateViewportScrollSizeCache, getCurrentViewportScrollSizeCache] = createCache<
|
const [updateViewportScrollSizeCache, getCurrentViewportScrollSizeCache] = createCache<
|
||||||
WH<number>
|
WH<number>
|
||||||
>(scrollSize.bind(0, _viewport), whCacheOptions);
|
>(whCacheOptions, scrollSize.bind(0, _viewport));
|
||||||
|
|
||||||
const [updateOverflowAmountCache, getCurrentOverflowAmountCache] = createCache<
|
const [updateOverflowAmountCache, getCurrentOverflowAmountCache] = createCache<WH<number>>(
|
||||||
WH<number>,
|
|
||||||
OverflowAmountCacheContext
|
|
||||||
>(
|
|
||||||
({ _viewportScrollSize, _viewportClientSize, _viewportSizeFraction }) => ({
|
|
||||||
w: max(
|
|
||||||
0,
|
|
||||||
round(
|
|
||||||
max(0, _viewportScrollSize.w - _viewportClientSize.w) -
|
|
||||||
(fractionalPixelRatioTollerance() || max(0, _viewportSizeFraction.w))
|
|
||||||
)
|
|
||||||
),
|
|
||||||
h: max(
|
|
||||||
0,
|
|
||||||
round(
|
|
||||||
max(0, _viewportScrollSize.h - _viewportClientSize.h) -
|
|
||||||
(fractionalPixelRatioTollerance() || max(0, _viewportSizeFraction.h))
|
|
||||||
)
|
|
||||||
),
|
|
||||||
}),
|
|
||||||
whCacheOptions
|
whCacheOptions
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -195,19 +191,13 @@ export const createOverflowLifecycle = (lifecycleHub: LifecycleHub): Lifecycle =
|
|||||||
x: styleObj.overflowX === 'scroll',
|
x: styleObj.overflowX === 'scroll',
|
||||||
y: styleObj.overflowY === 'scroll',
|
y: styleObj.overflowY === 'scroll',
|
||||||
};
|
};
|
||||||
|
const nonScrollbarStylingHideOffset = {
|
||||||
|
x: overlaidX ? arrangeHideOffset : _nativeScrollbarSize.x,
|
||||||
|
y: overlaidY ? arrangeHideOffset : _nativeScrollbarSize.y,
|
||||||
|
};
|
||||||
const scrollbarsHideOffset = {
|
const scrollbarsHideOffset = {
|
||||||
x:
|
x: scroll.x && !_nativeScrollbarStyling ? nonScrollbarStylingHideOffset.x : 0,
|
||||||
scroll.x && !_nativeScrollbarStyling
|
y: scroll.y && !_nativeScrollbarStyling ? nonScrollbarStylingHideOffset.y : 0,
|
||||||
? overlaidX
|
|
||||||
? arrangeHideOffset
|
|
||||||
: _nativeScrollbarSize.x
|
|
||||||
: 0,
|
|
||||||
y:
|
|
||||||
scroll.y && !_nativeScrollbarStyling
|
|
||||||
? overlaidY
|
|
||||||
? arrangeHideOffset
|
|
||||||
: _nativeScrollbarSize.y
|
|
||||||
: 0,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@@ -486,7 +476,7 @@ export const createOverflowLifecycle = (lifecycleHub: LifecycleHub): Lifecycle =
|
|||||||
_viewportOverflowState: undoViewportArrangeOverflowState,
|
_viewportOverflowState: undoViewportArrangeOverflowState,
|
||||||
} = undoViewportArrange(
|
} = undoViewportArrange(
|
||||||
showNativeOverlaidScrollbars,
|
showNativeOverlaidScrollbars,
|
||||||
directionIsRTL!,
|
directionIsRTL,
|
||||||
preMeasureViewportOverflowState
|
preMeasureViewportOverflowState
|
||||||
);
|
);
|
||||||
const [
|
const [
|
||||||
@@ -498,7 +488,7 @@ export const createOverflowLifecycle = (lifecycleHub: LifecycleHub): Lifecycle =
|
|||||||
viewportScrollSizeChanged,
|
viewportScrollSizeChanged,
|
||||||
] = (viewportScrollSizeCache = updateViewportScrollSizeCache(force));
|
] = (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();
|
||||||
@@ -512,26 +502,29 @@ export const createOverflowLifecycle = (lifecycleHub: LifecycleHub): Lifecycle =
|
|||||||
!showNativeOverlaidScrollbars &&
|
!showNativeOverlaidScrollbars &&
|
||||||
arrangeViewport(
|
arrangeViewport(
|
||||||
undoViewportArrangeOverflowState,
|
undoViewportArrangeOverflowState,
|
||||||
viewportScrollSize!,
|
viewportScrollSize,
|
||||||
viewportSizeFraction!,
|
viewportSizeFraction,
|
||||||
directionIsRTL!
|
directionIsRTL
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
arrangedViewportClientSize = clientSize(_viewport);
|
arrangedViewportClientSize = clientSize(_viewport);
|
||||||
arrangedViewportScrollSize = scrollSize(_viewport);
|
arrangedViewportScrollSize = scrollSize(_viewport);
|
||||||
}
|
}
|
||||||
|
|
||||||
overflowAmuntCache = updateOverflowAmountCache(force, {
|
overflowAmuntCache = updateOverflowAmountCache(
|
||||||
_viewportSizeFraction: viewportSizeFraction!,
|
getOverflowAmount(
|
||||||
_viewportScrollSize: {
|
{
|
||||||
w: max(viewportScrollSize.w, arrangedViewportScrollSize.w),
|
w: max(viewportScrollSize.w, arrangedViewportScrollSize.w),
|
||||||
h: max(viewportScrollSize.h, arrangedViewportScrollSize.h),
|
h: max(viewportScrollSize.h, arrangedViewportScrollSize.h),
|
||||||
},
|
}, // scroll size
|
||||||
_viewportClientSize: {
|
{
|
||||||
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),
|
||||||
},
|
}, // client size
|
||||||
});
|
viewportSizeFraction
|
||||||
|
),
|
||||||
|
force
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const [viewportSizeFraction, viewportSizeFractionChanged] = viewportSizeFractionCache;
|
const [viewportSizeFraction, viewportSizeFractionChanged] = viewportSizeFractionCache;
|
||||||
@@ -560,17 +553,17 @@ export const createOverflowLifecycle = (lifecycleHub: LifecycleHub): Lifecycle =
|
|||||||
|
|
||||||
const viewportOverflowState = setViewportOverflowState(
|
const viewportOverflowState = setViewportOverflowState(
|
||||||
showNativeOverlaidScrollbars,
|
showNativeOverlaidScrollbars,
|
||||||
overflowAmount!,
|
overflowAmount,
|
||||||
overflow,
|
overflow,
|
||||||
viewportStyle
|
viewportStyle
|
||||||
);
|
);
|
||||||
const viewportArranged = arrangeViewport(
|
const viewportArranged = arrangeViewport(
|
||||||
viewportOverflowState,
|
viewportOverflowState,
|
||||||
viewportScrollSize!,
|
viewportScrollSize,
|
||||||
viewportSizeFraction!,
|
viewportSizeFraction,
|
||||||
directionIsRTL!
|
directionIsRTL
|
||||||
);
|
);
|
||||||
hideNativeScrollbars(viewportOverflowState, directionIsRTL!, viewportArranged, viewportStyle);
|
hideNativeScrollbars(viewportOverflowState, directionIsRTL, viewportArranged, viewportStyle);
|
||||||
|
|
||||||
if (adjustFlexboxGlue) {
|
if (adjustFlexboxGlue) {
|
||||||
fixFlexboxGlue(viewportOverflowState, !!heightIntrinsic);
|
fixFlexboxGlue(viewportOverflowState, !!heightIntrinsic);
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { createCache, topRightBottomLeft, equalTRBL, style, TRBL } from 'support';
|
import { createCache, topRightBottomLeft, equalTRBL, style } from 'support';
|
||||||
import { LifecycleHub, Lifecycle } from 'lifecycles/lifecycleHub';
|
import { LifecycleHub, Lifecycle } from 'lifecycles/lifecycleHub';
|
||||||
import { StyleObject } from 'typings';
|
import { StyleObject } from 'typings';
|
||||||
import { getEnvironment } from 'environment';
|
import { getEnvironment } from 'environment';
|
||||||
@@ -11,12 +11,12 @@ import { getEnvironment } from 'environment';
|
|||||||
export const createPaddingLifecycle = (lifecycleHub: LifecycleHub): Lifecycle => {
|
export const createPaddingLifecycle = (lifecycleHub: LifecycleHub): Lifecycle => {
|
||||||
const { _structureSetup, _setLifecycleCommunication } = lifecycleHub;
|
const { _structureSetup, _setLifecycleCommunication } = lifecycleHub;
|
||||||
const { _host, _padding, _viewport } = _structureSetup._targetObj;
|
const { _host, _padding, _viewport } = _structureSetup._targetObj;
|
||||||
const [updatePaddingCache, currentPaddingCache] = createCache<TRBL>(
|
const [updatePaddingCache, currentPaddingCache] = createCache(
|
||||||
topRightBottomLeft.bind(0, _host, 'padding'),
|
|
||||||
{
|
{
|
||||||
_equal: equalTRBL,
|
_equal: equalTRBL,
|
||||||
_initialValue: topRightBottomLeft(),
|
_initialValue: topRightBottomLeft(),
|
||||||
}
|
},
|
||||||
|
topRightBottomLeft.bind(0, _host, 'padding', '')
|
||||||
);
|
);
|
||||||
|
|
||||||
return (updateHints, checkOption, force) => {
|
return (updateHints, checkOption, force) => {
|
||||||
@@ -62,7 +62,7 @@ export const createPaddingLifecycle = (lifecycleHub: LifecycleHub): Lifecycle =>
|
|||||||
_setLifecycleCommunication({
|
_setLifecycleCommunication({
|
||||||
_paddingInfo: {
|
_paddingInfo: {
|
||||||
_absolute: !paddingRelative,
|
_absolute: !paddingRelative,
|
||||||
_padding: padding!,
|
_padding: padding,
|
||||||
},
|
},
|
||||||
_viewportPaddingStyle: _padding
|
_viewportPaddingStyle: _padding
|
||||||
? viewportStyle
|
? viewportStyle
|
||||||
|
|||||||
@@ -1,4 +1,17 @@
|
|||||||
import { each, noop, debounce, indexOf, isString, MutationObserverConstructor, isEmptyArray, on, attr, is, find, push } from 'support';
|
import {
|
||||||
|
each,
|
||||||
|
noop,
|
||||||
|
debounce,
|
||||||
|
indexOf,
|
||||||
|
isString,
|
||||||
|
MutationObserverConstructor,
|
||||||
|
isEmptyArray,
|
||||||
|
on,
|
||||||
|
attr,
|
||||||
|
is,
|
||||||
|
find,
|
||||||
|
push,
|
||||||
|
} from 'support';
|
||||||
|
|
||||||
type DOMContentObserverCallback = (contentChangedTroughEvent: boolean) => any;
|
type DOMContentObserverCallback = (contentChangedTroughEvent: boolean) => any;
|
||||||
|
|
||||||
@@ -22,7 +35,11 @@ interface DOMTargetObserverOptions extends DOMObserverOptionsBase {
|
|||||||
|
|
||||||
type ContentChangeArrayItem = [string?, string?] | null | undefined;
|
type ContentChangeArrayItem = [string?, string?] | null | undefined;
|
||||||
|
|
||||||
export type DOMObserverEventContentChange = Array<ContentChangeArrayItem> | false | null | undefined;
|
export type DOMObserverEventContentChange =
|
||||||
|
| Array<ContentChangeArrayItem>
|
||||||
|
| false
|
||||||
|
| null
|
||||||
|
| undefined;
|
||||||
|
|
||||||
export type DOMObserverIgnoreContentChange = (
|
export type DOMObserverIgnoreContentChange = (
|
||||||
mutation: MutationRecord,
|
mutation: MutationRecord,
|
||||||
@@ -42,7 +59,9 @@ export type DOMObserverCallback<ContentObserver extends boolean> = ContentObserv
|
|||||||
? DOMContentObserverCallback
|
? DOMContentObserverCallback
|
||||||
: DOMTargetObserverCallback;
|
: DOMTargetObserverCallback;
|
||||||
|
|
||||||
export type DOMObserverOptions<ContentObserver extends boolean> = ContentObserver extends true ? DOMContentObserverOptions : DOMTargetObserverOptions;
|
export type DOMObserverOptions<ContentObserver extends boolean> = ContentObserver extends true
|
||||||
|
? DOMContentObserverOptions
|
||||||
|
: DOMTargetObserverOptions;
|
||||||
|
|
||||||
export interface DOMObserver {
|
export interface DOMObserver {
|
||||||
_destroy: () => void;
|
_destroy: () => void;
|
||||||
@@ -56,7 +75,11 @@ export interface DOMObserver {
|
|||||||
* @param callback Callback which is called if one of the elements emits the corresponding event.
|
* @param callback Callback which is called if one of the elements emits the corresponding event.
|
||||||
* @returns A object which contains a set of helper functions to destroy and update the observation of elements.
|
* @returns A object which contains a set of helper functions to destroy and update the observation of elements.
|
||||||
*/
|
*/
|
||||||
const createEventContentChange = (target: Element, callback: (...args: any) => any, eventContentChange?: DOMObserverEventContentChange) => {
|
const createEventContentChange = (
|
||||||
|
target: Element,
|
||||||
|
callback: (...args: any) => any,
|
||||||
|
eventContentChange?: DOMObserverEventContentChange
|
||||||
|
) => {
|
||||||
let map: WeakMap<Node, [string, () => any]> | undefined; // weak map to prevent memory leak for detached elements
|
let map: WeakMap<Node, [string, () => any]> | undefined; // weak map to prevent memory leak for detached elements
|
||||||
let destroyed = false;
|
let destroyed = false;
|
||||||
const _destroy = () => {
|
const _destroy = () => {
|
||||||
@@ -68,7 +91,10 @@ const createEventContentChange = (target: Element, callback: (...args: any) => a
|
|||||||
if (item) {
|
if (item) {
|
||||||
const selector = item[0];
|
const selector = item[0];
|
||||||
const eventNames = item[1];
|
const eventNames = item[1];
|
||||||
const elements = eventNames && selector && (getElements ? getElements(selector) : find(selector, target));
|
const elements =
|
||||||
|
eventNames &&
|
||||||
|
selector &&
|
||||||
|
(getElements ? getElements(selector) : find(selector, target));
|
||||||
|
|
||||||
if (elements && elements.length && eventNames && isString(eventNames)) {
|
if (elements && elements.length && eventNames && isString(eventNames)) {
|
||||||
push(arr, [elements, eventNames.trim()], true);
|
push(arr, [elements, eventNames.trim()], true);
|
||||||
@@ -141,7 +167,10 @@ export const createDOMObserver = <ContentObserver extends boolean>(
|
|||||||
_ignoreNestedTargetChange,
|
_ignoreNestedTargetChange,
|
||||||
_ignoreContentChange,
|
_ignoreContentChange,
|
||||||
} = (options as DOMContentObserverOptions & DOMTargetObserverOptions) || {};
|
} = (options as DOMContentObserverOptions & DOMTargetObserverOptions) || {};
|
||||||
const { _destroy: destroyEventContentChange, _updateElements: updateEventContentChangeElements } = createEventContentChange(
|
const {
|
||||||
|
_destroy: destroyEventContentChange,
|
||||||
|
_updateElements: updateEventContentChangeElements,
|
||||||
|
} = createEventContentChange(
|
||||||
target,
|
target,
|
||||||
debounce(
|
debounce(
|
||||||
() => {
|
() => {
|
||||||
@@ -159,7 +188,8 @@ export const createDOMObserver = <ContentObserver extends boolean>(
|
|||||||
const finalStyleChangingAttributes = _styleChangingAttributes || [];
|
const finalStyleChangingAttributes = _styleChangingAttributes || [];
|
||||||
const observedAttributes = finalAttributes.concat(finalStyleChangingAttributes);
|
const observedAttributes = finalAttributes.concat(finalStyleChangingAttributes);
|
||||||
const observerCallback = (mutations: MutationRecord[]) => {
|
const observerCallback = (mutations: MutationRecord[]) => {
|
||||||
const ignoreTargetChange = (isContentObserver ? _ignoreNestedTargetChange : _ignoreTargetChange) || noop;
|
const ignoreTargetChange =
|
||||||
|
(isContentObserver ? _ignoreNestedTargetChange : _ignoreTargetChange) || noop;
|
||||||
const ignoreContentChange = _ignoreContentChange || noop;
|
const ignoreContentChange = _ignoreContentChange || noop;
|
||||||
const targetChangedAttrs: string[] = [];
|
const targetChangedAttrs: string[] = [];
|
||||||
const totalAddedNodes: Node[] = [];
|
const totalAddedNodes: Node[] = [];
|
||||||
@@ -171,19 +201,25 @@ export const createDOMObserver = <ContentObserver extends boolean>(
|
|||||||
const isAttributesType = type === 'attributes';
|
const isAttributesType = type === 'attributes';
|
||||||
const isChildListType = type === 'childList';
|
const isChildListType = type === 'childList';
|
||||||
const targetIsMutationTarget = target === mutationTarget;
|
const targetIsMutationTarget = target === mutationTarget;
|
||||||
const attributeValue = isAttributesType && isString(attributeName) ? attr(mutationTarget as HTMLElement, attributeName!) : 0;
|
const attributeValue =
|
||||||
|
isAttributesType && isString(attributeName)
|
||||||
|
? attr(mutationTarget as HTMLElement, attributeName!)
|
||||||
|
: 0;
|
||||||
const attributeChanged = attributeValue !== 0 && oldValue !== attributeValue;
|
const attributeChanged = attributeValue !== 0 && oldValue !== attributeValue;
|
||||||
const styleChangingAttrChanged = indexOf(finalStyleChangingAttributes, attributeName) > -1 && attributeChanged;
|
const styleChangingAttrChanged =
|
||||||
|
indexOf(finalStyleChangingAttributes, attributeName) > -1 && attributeChanged;
|
||||||
|
|
||||||
// if is content observer and something changed in children
|
// if is content observer and something changed in children
|
||||||
if (isContentObserver && !targetIsMutationTarget) {
|
if (isContentObserver && !targetIsMutationTarget) {
|
||||||
const notOnlyAttrChanged = !isAttributesType;
|
const notOnlyAttrChanged = !isAttributesType;
|
||||||
const contentAttrChanged = isAttributesType && styleChangingAttrChanged;
|
const contentAttrChanged = isAttributesType && styleChangingAttrChanged;
|
||||||
const isNestedTarget = contentAttrChanged && _nestedTargetSelector && is(mutationTarget, _nestedTargetSelector);
|
const isNestedTarget =
|
||||||
|
contentAttrChanged && _nestedTargetSelector && is(mutationTarget, _nestedTargetSelector);
|
||||||
const baseAssertion = isNestedTarget
|
const baseAssertion = isNestedTarget
|
||||||
? !ignoreTargetChange(mutationTarget, attributeName!, oldValue, attributeValue as string | null)
|
? !ignoreTargetChange(mutationTarget, attributeName!, oldValue, attributeValue)
|
||||||
: notOnlyAttrChanged || contentAttrChanged;
|
: notOnlyAttrChanged || contentAttrChanged;
|
||||||
const contentFinalChanged = baseAssertion && !ignoreContentChange(mutation, !!isNestedTarget, target, options);
|
const contentFinalChanged =
|
||||||
|
baseAssertion && !ignoreContentChange(mutation, !!isNestedTarget, target, options);
|
||||||
|
|
||||||
push(totalAddedNodes, addedNodes);
|
push(totalAddedNodes, addedNodes);
|
||||||
|
|
||||||
@@ -195,7 +231,7 @@ export const createDOMObserver = <ContentObserver extends boolean>(
|
|||||||
!isContentObserver &&
|
!isContentObserver &&
|
||||||
targetIsMutationTarget &&
|
targetIsMutationTarget &&
|
||||||
attributeChanged &&
|
attributeChanged &&
|
||||||
!ignoreTargetChange(mutationTarget, attributeName!, oldValue, attributeValue as string | null)
|
!ignoreTargetChange(mutationTarget, attributeName!, oldValue, attributeValue)
|
||||||
) {
|
) {
|
||||||
push(targetChangedAttrs, attributeName!);
|
push(targetChangedAttrs, attributeName!);
|
||||||
targetStyleChanged = targetStyleChanged || styleChangingAttrChanged;
|
targetStyleChanged = targetStyleChanged || styleChangingAttrChanged;
|
||||||
|
|||||||
@@ -81,10 +81,7 @@ export const createSizeObserver = (
|
|||||||
const sizeObserver = baseElements[0] as HTMLElement;
|
const sizeObserver = baseElements[0] as HTMLElement;
|
||||||
const listenerElement = sizeObserver.firstChild as HTMLElement;
|
const listenerElement = sizeObserver.firstChild as HTMLElement;
|
||||||
const getIsDirectionRTL = getElmDirectionIsRTL.bind(0, sizeObserver);
|
const getIsDirectionRTL = getElmDirectionIsRTL.bind(0, sizeObserver);
|
||||||
const [updateResizeObserverContentRectCache] = createCache<
|
const [updateResizeObserverContentRectCache] = createCache<DOMRectReadOnly | undefined>({
|
||||||
DOMRectReadOnly | undefined,
|
|
||||||
DOMRectReadOnly
|
|
||||||
>(0, {
|
|
||||||
_initialValue: undefined,
|
_initialValue: undefined,
|
||||||
_alwaysUpdateValues: true,
|
_alwaysUpdateValues: true,
|
||||||
_equal: (currVal, newVal) =>
|
_equal: (currVal, newVal) =>
|
||||||
@@ -112,7 +109,6 @@ export const createSizeObserver = (
|
|||||||
// if triggered from RO.
|
// if triggered from RO.
|
||||||
if (isResizeObserverCall) {
|
if (isResizeObserverCall) {
|
||||||
const [currRContentRect, , prevContentRect] = updateResizeObserverContentRectCache(
|
const [currRContentRect, , prevContentRect] = updateResizeObserverContentRectCache(
|
||||||
0,
|
|
||||||
(sizeChangedContext as ResizeObserverEntry[]).pop()!.contentRect
|
(sizeChangedContext as ResizeObserverEntry[]).pop()!.contentRect
|
||||||
);
|
);
|
||||||
const hasDimensions = domRectHasDimensions(currRContentRect);
|
const hasDimensions = domRectHasDimensions(currRContentRect);
|
||||||
@@ -234,9 +230,12 @@ export const createSizeObserver = (
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (observeDirectionChange) {
|
if (observeDirectionChange) {
|
||||||
directionIsRTLCache = createCache(getIsDirectionRTL, {
|
directionIsRTLCache = createCache(
|
||||||
_initialValue: !getIsDirectionRTL(), // invert current value to trigger initial change
|
{
|
||||||
});
|
_initialValue: !getIsDirectionRTL(), // invert current value to trigger initial change
|
||||||
|
},
|
||||||
|
getIsDirectionRTL
|
||||||
|
);
|
||||||
const [updateDirectionIsRTLCache] = directionIsRTLCache;
|
const [updateDirectionIsRTLCache] = directionIsRTLCache;
|
||||||
|
|
||||||
push(
|
push(
|
||||||
|
|||||||
@@ -22,6 +22,11 @@ export interface TrinsicObserver {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const isHeightIntrinsic = (ioEntryOrSize: IntersectionObserverEntry | WH<number>): boolean =>
|
||||||
|
(ioEntryOrSize as WH<number>).h === 0 ||
|
||||||
|
(ioEntryOrSize as IntersectionObserverEntry).isIntersecting ||
|
||||||
|
(ioEntryOrSize as IntersectionObserverEntry).intersectionRatio > 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a trinsic observer which observes changes to intrinsic or extrinsic sizing for the height of the target element.
|
* Creates a trinsic observer which observes changes to intrinsic or extrinsic sizing for the height of the target element.
|
||||||
* @param target The element which shall be observed.
|
* @param target The element which shall be observed.
|
||||||
@@ -34,24 +39,15 @@ export const createTrinsicObserver = (
|
|||||||
): TrinsicObserver => {
|
): TrinsicObserver => {
|
||||||
const trinsicObserver = createDiv(classNameTrinsicObserver);
|
const trinsicObserver = createDiv(classNameTrinsicObserver);
|
||||||
const offListeners: (() => void)[] = [];
|
const offListeners: (() => void)[] = [];
|
||||||
const [updateHeightIntrinsicCache, getCurrentHeightIntrinsicCache] = createCache<
|
const [updateHeightIntrinsicCache, getCurrentHeightIntrinsicCache] = createCache({
|
||||||
boolean,
|
_initialValue: false,
|
||||||
IntersectionObserverEntry | WH<number>
|
});
|
||||||
>(
|
|
||||||
(ioEntryOrSize: IntersectionObserverEntry | WH<number>) =>
|
|
||||||
(ioEntryOrSize! as WH<number>).h === 0 ||
|
|
||||||
(ioEntryOrSize! as IntersectionObserverEntry).isIntersecting ||
|
|
||||||
(ioEntryOrSize! as IntersectionObserverEntry).intersectionRatio > 0,
|
|
||||||
{
|
|
||||||
_initialValue: false,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
const triggerOnTrinsicChangedCallback = (
|
const triggerOnTrinsicChangedCallback = (
|
||||||
updateValue?: IntersectionObserverEntry | WH<number>
|
updateValue?: IntersectionObserverEntry | WH<number>
|
||||||
) => {
|
) => {
|
||||||
if (updateValue) {
|
if (updateValue) {
|
||||||
const heightIntrinsic = updateHeightIntrinsicCache(0, updateValue);
|
const heightIntrinsic = updateHeightIntrinsicCache(isHeightIntrinsic(updateValue));
|
||||||
const [, heightIntrinsicChanged] = heightIntrinsic;
|
const [, heightIntrinsicChanged] = heightIntrinsic;
|
||||||
|
|
||||||
if (heightIntrinsicChanged) {
|
if (heightIntrinsicChanged) {
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ export const OverlayScrollbars: OverlayScrollbarsStatic = (
|
|||||||
},
|
},
|
||||||
state: () => lifecycleHub._state(),
|
state: () => lifecycleHub._state(),
|
||||||
update(force?: boolean) {
|
update(force?: boolean) {
|
||||||
lifecycleHub._update(null, force);
|
lifecycleHub._update({}, force);
|
||||||
},
|
},
|
||||||
destroy: () => lifecycleHub._destroy(),
|
destroy: () => lifecycleHub._destroy(),
|
||||||
};
|
};
|
||||||
|
|||||||
+44
-41
@@ -1,49 +1,49 @@
|
|||||||
export type CacheValues<T> = [
|
export interface CacheOptions<Value> {
|
||||||
T, // value
|
|
||||||
boolean, // changed
|
|
||||||
T | undefined // previous
|
|
||||||
];
|
|
||||||
|
|
||||||
export type Cache<Value, Ctx = undefined> = [
|
|
||||||
CacheUpdate<Value, Ctx>,
|
|
||||||
(force?: boolean) => CacheValues<Value> // getCurrent
|
|
||||||
];
|
|
||||||
|
|
||||||
export interface CacheOptions<T> {
|
|
||||||
// initial value of _value.
|
// initial value of _value.
|
||||||
_initialValue: T;
|
_initialValue: Value;
|
||||||
// Custom comparison function if shallow compare isn't enough. Returns true if nothing changed.
|
// Custom comparison function if shallow compare isn't enough. Returns true if nothing changed.
|
||||||
_equal?: EqualCachePropFunction<T>;
|
_equal?: EqualCachePropFunction<Value>;
|
||||||
// If true always updates _value and _previous, otherwise they update only when they changed.
|
// If true always updates _value and _previous, otherwise they update only when they changed.
|
||||||
_alwaysUpdateValues?: boolean;
|
_alwaysUpdateValues?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type CacheUpdate<T, C> = undefined extends C
|
export type CacheValues<T> = [
|
||||||
? (force?: boolean | 0, context?: C) => CacheValues<T>
|
T, // value
|
||||||
: (force: boolean | 0, context: C) => CacheValues<T>;
|
boolean, // changed
|
||||||
|
T? // previous
|
||||||
|
];
|
||||||
|
|
||||||
export type UpdateCachePropFunction<Value, Ctx> = undefined extends Ctx
|
export type EqualCachePropFunction<Value> = (currentVal: Value, newVal: Value) => boolean;
|
||||||
? (context?: Ctx, current?: Value, previous?: Value) => Value
|
|
||||||
: Ctx extends Value
|
|
||||||
? ((context: Ctx, current?: Value, previous?: Value) => Value) | 0
|
|
||||||
: (context: Ctx, current?: Value, previous?: Value) => Value;
|
|
||||||
|
|
||||||
export type EqualCachePropFunction<T> = (currentVal?: T, newVal?: T) => boolean;
|
export type CacheUpdater<Value> = (current: Value, previous?: Value) => Value;
|
||||||
|
|
||||||
export const createCache = <Value, Ctx = undefined>(
|
export type UpdateCacheContextual<Value> = (newValue: Value, force?: boolean) => CacheValues<Value>;
|
||||||
update: UpdateCachePropFunction<Value, Ctx>,
|
|
||||||
options: CacheOptions<Value>
|
export type UpdateCache<Value> = (force?: boolean) => CacheValues<Value>;
|
||||||
): Cache<Value, Ctx> => {
|
|
||||||
|
export type GetCurrentCache<Value> = (force?: boolean) => CacheValues<Value>;
|
||||||
|
|
||||||
|
export type Cache<Value> = [UpdateCache<Value>, GetCurrentCache<Value>];
|
||||||
|
|
||||||
|
export type CacheContextual<Value> = [UpdateCacheContextual<Value>, GetCurrentCache<Value>];
|
||||||
|
|
||||||
|
export function createCache<Value>(options: CacheOptions<Value>): CacheContextual<Value>;
|
||||||
|
export function createCache<Value>(
|
||||||
|
options: CacheOptions<Value>,
|
||||||
|
update: CacheUpdater<Value>
|
||||||
|
): Cache<Value>;
|
||||||
|
export function createCache<Value>(
|
||||||
|
options: CacheOptions<Value>,
|
||||||
|
update?: CacheUpdater<Value>
|
||||||
|
): CacheContextual<Value> | Cache<Value> {
|
||||||
const { _initialValue, _equal, _alwaysUpdateValues } = options;
|
const { _initialValue, _equal, _alwaysUpdateValues } = options;
|
||||||
let _value: Value = _initialValue;
|
let _value: Value = _initialValue;
|
||||||
let _previous: Value | undefined;
|
let _previous: Value | undefined;
|
||||||
|
|
||||||
const cacheUpdate = ((force?: boolean | 0, context?: Ctx) => {
|
const cacheUpdateContextual: UpdateCacheContextual<Value> = (newValue, force?) => {
|
||||||
const curr = _value;
|
const curr = _value;
|
||||||
// @ts-ignore
|
|
||||||
// update can only not be a function if C extends T as described in "UpdateCachePropFunction" type definition
|
const newVal = newValue;
|
||||||
// if C extends T the cast (context as T) is perfectly valid
|
|
||||||
const newVal = update ? update(context, _value, _previous) : (context as T);
|
|
||||||
const changed = force || (_equal ? !_equal(curr, newVal) : curr !== newVal);
|
const changed = force || (_equal ? !_equal(curr, newVal) : curr !== newVal);
|
||||||
|
|
||||||
if (changed || _alwaysUpdateValues) {
|
if (changed || _alwaysUpdateValues) {
|
||||||
@@ -52,14 +52,17 @@ export const createCache = <Value, Ctx = undefined>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
return [_value, changed, _previous];
|
return [_value, changed, _previous];
|
||||||
}) as CacheUpdate<Value, Ctx>;
|
};
|
||||||
|
const cacheUpdateIsolated: UpdateCache<Value> = (force?) =>
|
||||||
|
cacheUpdateContextual(update!(_value, _previous), force);
|
||||||
|
|
||||||
return [
|
const getCurrentCache: GetCurrentCache<Value> = (force?: boolean) => [
|
||||||
cacheUpdate,
|
_value,
|
||||||
(force?: boolean) => [
|
!!force, // changed
|
||||||
_value,
|
_previous,
|
||||||
!!force, // changed
|
|
||||||
_previous,
|
|
||||||
],
|
|
||||||
];
|
];
|
||||||
};
|
|
||||||
|
return [update ? cacheUpdateIsolated : cacheUpdateContextual, getCurrentCache] as
|
||||||
|
| CacheContextual<Value>
|
||||||
|
| Cache<Value>;
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
import { jsAPI } from 'support/compatibility/vendors';
|
import { jsAPI } from 'support/compatibility/vendors';
|
||||||
|
|
||||||
export const MutationObserverConstructor = jsAPI<typeof MutationObserver>('MutationObserver');
|
export const MutationObserverConstructor = jsAPI<typeof MutationObserver>('MutationObserver');
|
||||||
export const IntersectionObserverConstructor = jsAPI<typeof IntersectionObserver>('IntersectionObserver');
|
export const IntersectionObserverConstructor = jsAPI<typeof IntersectionObserver>(
|
||||||
|
'IntersectionObserver'
|
||||||
|
);
|
||||||
export const ResizeObserverConstructor = jsAPI<typeof ResizeObserver>('ResizeObserver');
|
export const ResizeObserverConstructor = jsAPI<typeof ResizeObserver>('ResizeObserver');
|
||||||
export const cAF = jsAPI<typeof cancelAnimationFrame>('cancelAnimationFrame');
|
export const cAF = jsAPI<typeof cancelAnimationFrame>('cancelAnimationFrame');
|
||||||
export const rAF = jsAPI<typeof requestAnimationFrame>('requestAnimationFrame');
|
export const rAF = jsAPI<typeof requestAnimationFrame>('requestAnimationFrame');
|
||||||
|
|||||||
@@ -23,7 +23,11 @@ function getSetProp(
|
|||||||
*/
|
*/
|
||||||
export function attr(elm: HTMLElement | null, attrName: string): string | null;
|
export function attr(elm: HTMLElement | null, attrName: string): string | null;
|
||||||
export function attr(elm: HTMLElement | null, attrName: string, value: string): void;
|
export function attr(elm: HTMLElement | null, attrName: string, value: string): void;
|
||||||
export function attr(elm: HTMLElement | null, attrName: string, value?: string): string | null | void {
|
export function attr(
|
||||||
|
elm: HTMLElement | null,
|
||||||
|
attrName: string,
|
||||||
|
value?: string
|
||||||
|
): string | null | void {
|
||||||
if (isUndefined(value)) {
|
if (isUndefined(value)) {
|
||||||
return elm ? elm.getAttribute(attrName) : null;
|
return elm ? elm.getAttribute(attrName) : null;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -53,7 +53,10 @@ export const removeClass = (elm: Element | false | null | undefined, className:
|
|||||||
* @param classNameA ClassName A.
|
* @param classNameA ClassName A.
|
||||||
* @param classNameB ClassName B.
|
* @param classNameB ClassName B.
|
||||||
*/
|
*/
|
||||||
export const diffClass = (classNameA: string | null | undefined, classNameB: string | null | undefined) => {
|
export const diffClass = (
|
||||||
|
classNameA: string | null | undefined,
|
||||||
|
classNameB: string | null | undefined
|
||||||
|
) => {
|
||||||
const classNameASplit = classNameA && classNameA.split(' ');
|
const classNameASplit = classNameA && classNameA.split(' ');
|
||||||
const classNameBSplit = classNameB && classNameB.split(' ');
|
const classNameBSplit = classNameB && classNameB.split(' ');
|
||||||
const tempObj = {};
|
const tempObj = {};
|
||||||
|
|||||||
@@ -3,7 +3,8 @@ export interface WH<T = number> {
|
|||||||
h: T;
|
h: T;
|
||||||
}
|
}
|
||||||
|
|
||||||
const elementHasDimensions = (elm: HTMLElement): boolean => !!(elm.offsetWidth || elm.offsetHeight || elm.getClientRects().length);
|
const elementHasDimensions = (elm: HTMLElement): boolean =>
|
||||||
|
!!(elm.offsetWidth || elm.offsetHeight || elm.getClientRects().length);
|
||||||
const zeroObj: WH = {
|
const zeroObj: WH = {
|
||||||
w: 0,
|
w: 0,
|
||||||
h: 0,
|
h: 0,
|
||||||
@@ -63,4 +64,5 @@ export const getBoundingClientRect = (elm: HTMLElement): DOMRect => elm.getBound
|
|||||||
* Determines whether the passed element has any dimensions.
|
* Determines whether the passed element has any dimensions.
|
||||||
* @param elm The element.
|
* @param elm The element.
|
||||||
*/
|
*/
|
||||||
export const hasDimensions = (elm: HTMLElement | null | undefined): boolean => (elm ? elementHasDimensions(elm as HTMLElement) : false);
|
export const hasDimensions = (elm: HTMLElement | null | undefined): boolean =>
|
||||||
|
elm ? elementHasDimensions(elm as HTMLElement) : false;
|
||||||
|
|||||||
@@ -37,7 +37,12 @@ export interface OnOptions {
|
|||||||
* @param listener The listener which shall be removed.
|
* @param listener The listener which shall be removed.
|
||||||
* @param capture The options of the removed listener.
|
* @param capture The options of the removed listener.
|
||||||
*/
|
*/
|
||||||
export const off = <T extends Event = Event>(target: EventTarget, eventNames: string, listener: (event: T) => any, capture?: boolean): void => {
|
export const off = <T extends Event = Event>(
|
||||||
|
target: EventTarget,
|
||||||
|
eventNames: string,
|
||||||
|
listener: (event: T) => any,
|
||||||
|
capture?: boolean
|
||||||
|
): void => {
|
||||||
each(splitEventNames(eventNames), (eventName) => {
|
each(splitEventNames(eventNames), (eventName) => {
|
||||||
target.removeEventListener(eventName, listener as EventListener, capture);
|
target.removeEventListener(eventName, listener as EventListener, capture);
|
||||||
});
|
});
|
||||||
@@ -99,4 +104,5 @@ export const preventDefault = (evt: Event): void => evt.preventDefault();
|
|||||||
* Shorthand for the stopPropagation and preventDefault event Method.
|
* Shorthand for the stopPropagation and preventDefault event Method.
|
||||||
* @param evt The event of which the stopPropagation and preventDefault methods shall be called.
|
* @param evt The event of which the stopPropagation and preventDefault methods shall be called.
|
||||||
*/
|
*/
|
||||||
export const stopAndPrevent = (evt: Event): void => (stopPropagation(evt) as undefined) || (preventDefault(evt) as undefined);
|
export const stopAndPrevent = (evt: Event): void =>
|
||||||
|
(stopPropagation(evt) as undefined) || (preventDefault(evt) as undefined);
|
||||||
|
|||||||
@@ -10,7 +10,11 @@ type NodeCollection = ArrayLike<Node> | Node | false | null | undefined;
|
|||||||
* @param preferredAnchor The element before which the Nodes shall be inserted or null if the elements shall be appended at the end.
|
* @param preferredAnchor The element before which the Nodes shall be inserted or null if the elements shall be appended at the end.
|
||||||
* @param insertedElms The Nodes which shall be inserted.
|
* @param insertedElms The Nodes which shall be inserted.
|
||||||
*/
|
*/
|
||||||
const before = (parentElm: Node | false | null | undefined, preferredAnchor: Node | null | undefined, insertedElms: NodeCollection): void => {
|
const before = (
|
||||||
|
parentElm: Node | false | null | undefined,
|
||||||
|
preferredAnchor: Node | null | undefined,
|
||||||
|
insertedElms: NodeCollection
|
||||||
|
): void => {
|
||||||
if (insertedElms) {
|
if (insertedElms) {
|
||||||
let anchor: Node | null | undefined = preferredAnchor;
|
let anchor: Node | null | undefined = preferredAnchor;
|
||||||
let fragment: DocumentFragment | Node | null | undefined;
|
let fragment: DocumentFragment | Node | null | undefined;
|
||||||
@@ -68,7 +72,10 @@ export const prependChildren = (node: Node | null | undefined, children: NodeCol
|
|||||||
* @param node The Node before which the given Nodes shall be inserted.
|
* @param node The Node before which the given Nodes shall be inserted.
|
||||||
* @param insertedNodes The Nodes which shall be inserted.
|
* @param insertedNodes The Nodes which shall be inserted.
|
||||||
*/
|
*/
|
||||||
export const insertBefore = (node: Node | null | undefined, insertedNodes: NodeCollection): void => {
|
export const insertBefore = (
|
||||||
|
node: Node | null | undefined,
|
||||||
|
insertedNodes: NodeCollection
|
||||||
|
): void => {
|
||||||
before(parent(node), node, insertedNodes);
|
before(parent(node), node, insertedNodes);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -10,19 +10,19 @@ export interface TRBL {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const cssNumber = {
|
const cssNumber = {
|
||||||
//animationiterationcount: 1,
|
// animationiterationcount: 1,
|
||||||
//columncount: 1,
|
// columncount: 1,
|
||||||
//fillopacity: 1,
|
// fillopacity: 1,
|
||||||
//flexgrow: 1,
|
// flexgrow: 1,
|
||||||
//flexshrink: 1,
|
// flexshrink: 1,
|
||||||
//fontweight: 1,
|
// fontweight: 1,
|
||||||
//lineheight: 1,
|
// lineheight: 1,
|
||||||
|
// order: 1,
|
||||||
|
// orphans: 1,
|
||||||
|
// widows: 1,
|
||||||
|
// zoom: 1,
|
||||||
opacity: 1,
|
opacity: 1,
|
||||||
//order: 1,
|
|
||||||
//orphans: 1,
|
|
||||||
//widows: 1,
|
|
||||||
zindex: 1,
|
zindex: 1,
|
||||||
//zoom: 1,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const parseToZeroOrNumber = (value: string, toFloat?: boolean): number => {
|
const parseToZeroOrNumber = (value: string, toFloat?: boolean): number => {
|
||||||
@@ -31,18 +31,25 @@ const parseToZeroOrNumber = (value: string, toFloat?: boolean): number => {
|
|||||||
/* istanbul ignore next */
|
/* istanbul ignore next */
|
||||||
return Number.isNaN(num) ? 0 : num;
|
return Number.isNaN(num) ? 0 : num;
|
||||||
};
|
};
|
||||||
const adaptCSSVal = (prop: string, val: string | number): string | number => (!cssNumber[prop.toLowerCase()] && isNumber(val) ? `${val}px` : val);
|
const adaptCSSVal = (prop: string, val: string | number): string | number =>
|
||||||
|
!cssNumber[prop.toLowerCase()] && isNumber(val) ? `${val}px` : val;
|
||||||
const getCSSVal = (elm: HTMLElement, computedStyle: CSSStyleDeclaration, prop: string): string =>
|
const getCSSVal = (elm: HTMLElement, computedStyle: CSSStyleDeclaration, prop: string): string =>
|
||||||
/* istanbul ignore next */
|
/* istanbul ignore next */
|
||||||
computedStyle != null ? computedStyle[prop] || computedStyle.getPropertyValue(prop) : elm.style[prop];
|
computedStyle != null
|
||||||
const setCSSVal = (elm: HTMLElement | false | null | undefined, prop: string, val: string | number): void => {
|
? computedStyle[prop] || computedStyle.getPropertyValue(prop)
|
||||||
|
: elm.style[prop];
|
||||||
|
const setCSSVal = (
|
||||||
|
elm: HTMLElement | false | null | undefined,
|
||||||
|
prop: string,
|
||||||
|
val: string | number
|
||||||
|
): void => {
|
||||||
try {
|
try {
|
||||||
if (elm) {
|
if (elm) {
|
||||||
const { style } = elm;
|
const { style: elmStyle } = elm;
|
||||||
if (!isUndefined(style[prop])) {
|
if (!isUndefined(elmStyle[prop])) {
|
||||||
style[prop] = adaptCSSVal(prop, val);
|
elmStyle[prop] = adaptCSSVal(prop, val);
|
||||||
} else {
|
} else {
|
||||||
style.setProperty(prop, val as string);
|
elmStyle.setProperty(prop, val as string);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (e) {}
|
} catch (e) {}
|
||||||
@@ -53,9 +60,18 @@ const setCSSVal = (elm: HTMLElement | false | null | undefined, prop: string, va
|
|||||||
* @param elm The element to which the styles shall be applied to / be read from.
|
* @param elm The element to which the styles shall be applied to / be read from.
|
||||||
* @param styles The styles which shall be set or read.
|
* @param styles The styles which shall be set or read.
|
||||||
*/
|
*/
|
||||||
export function style<CustomCssProps>(elm: HTMLElement | false | null | undefined, styles: StyleObject<CustomCssProps>): void;
|
export function style<CustomCssProps>(
|
||||||
export function style<CustomCssProps>(elm: HTMLElement | false | null | undefined, styles: string): string;
|
elm: HTMLElement | false | null | undefined,
|
||||||
export function style<CustomCssProps>(elm: HTMLElement | false | null | undefined, styles: Array<string> | string): { [key: string]: string };
|
styles: StyleObject<CustomCssProps>
|
||||||
|
): void;
|
||||||
|
export function style<CustomCssProps>(
|
||||||
|
elm: HTMLElement | false | null | undefined,
|
||||||
|
styles: string
|
||||||
|
): string;
|
||||||
|
export function style<CustomCssProps>(
|
||||||
|
elm: HTMLElement | false | null | undefined,
|
||||||
|
styles: Array<string> | string
|
||||||
|
): { [key: string]: string };
|
||||||
export function style<CustomCssProps>(
|
export function style<CustomCssProps>(
|
||||||
elm: HTMLElement | false | null | undefined,
|
elm: HTMLElement | false | null | undefined,
|
||||||
styles: StyleObject<CustomCssProps> | Array<string> | string
|
styles: StyleObject<CustomCssProps> | Array<string> | string
|
||||||
@@ -101,7 +117,11 @@ export const show = (elm: HTMLElement | false | null | undefined): void => {
|
|||||||
* @param propertyPrefix The css property prefix. (e.g. "border")
|
* @param propertyPrefix The css property prefix. (e.g. "border")
|
||||||
* @param propertySuffix The css property suffix. (e.g. "width")
|
* @param propertySuffix The css property suffix. (e.g. "width")
|
||||||
*/
|
*/
|
||||||
export const topRightBottomLeft = (elm?: HTMLElement | false | null | undefined, propertyPrefix?: string, propertySuffix?: string): TRBL => {
|
export const topRightBottomLeft = (
|
||||||
|
elm?: HTMLElement | false | null | undefined,
|
||||||
|
propertyPrefix?: string,
|
||||||
|
propertySuffix?: string
|
||||||
|
): TRBL => {
|
||||||
const finalPrefix = propertyPrefix ? `${propertyPrefix}-` : '';
|
const finalPrefix = propertyPrefix ? `${propertyPrefix}-` : '';
|
||||||
const finalSuffix = propertySuffix ? `-${propertySuffix}` : '';
|
const finalSuffix = propertySuffix ? `-${propertySuffix}` : '';
|
||||||
const top = `${finalPrefix}top${finalSuffix}`;
|
const top = `${finalPrefix}top${finalSuffix}`;
|
||||||
|
|||||||
@@ -65,7 +65,8 @@ const children = (elm: InputElementType, selector?: string): ReadonlyArray<Eleme
|
|||||||
* Returns the childNodes (incl. text-nodes or comments etc.) of the passed element. An empty array is returned if the passed element is null.
|
* Returns the childNodes (incl. text-nodes or comments etc.) of the passed element. An empty array is returned if the passed element is null.
|
||||||
* @param elm The element of which the childNodes shall be returned.
|
* @param elm The element of which the childNodes shall be returned.
|
||||||
*/
|
*/
|
||||||
const contents = (elm: InputElementType): ReadonlyArray<ChildNode> => (elm ? from(elm.childNodes) : []);
|
const contents = (elm: InputElementType): ReadonlyArray<ChildNode> =>
|
||||||
|
elm ? from(elm.childNodes) : [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the parent element of the passed element, or null if the passed element is null.
|
* Returns the parent element of the passed element, or null if the passed element is null.
|
||||||
@@ -97,7 +98,11 @@ const closest = (elm: InputElementType, selector: string): OutputElementType =>
|
|||||||
* @param highBoundarySelector The high boundary selector.
|
* @param highBoundarySelector The high boundary selector.
|
||||||
* @param deepBoundarySelector The deep boundary selector.
|
* @param deepBoundarySelector The deep boundary selector.
|
||||||
*/
|
*/
|
||||||
const liesBetween = (elm: InputElementType, highBoundarySelector: string, deepBoundarySelector: string): boolean => {
|
const liesBetween = (
|
||||||
|
elm: InputElementType,
|
||||||
|
highBoundarySelector: string,
|
||||||
|
deepBoundarySelector: string
|
||||||
|
): boolean => {
|
||||||
const closestHighBoundaryElm = elm && closest(elm, highBoundarySelector);
|
const closestHighBoundaryElm = elm && closest(elm, highBoundarySelector);
|
||||||
const closestDeepBoundaryElm = elm && findFirst(deepBoundarySelector, closestHighBoundaryElm);
|
const closestDeepBoundaryElm = elm && findFirst(deepBoundarySelector, closestHighBoundaryElm);
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,10 @@ export interface OptionsWithOptionsTemplateTransformation<T> {
|
|||||||
_options: T;
|
_options: T;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type OptionsWithOptionsTemplateValue<T extends OptionsTemplateNativeTypes> = [T, OptionsTemplateValue<T>];
|
export type OptionsWithOptionsTemplateValue<T extends OptionsTemplateNativeTypes> = [
|
||||||
|
T,
|
||||||
|
OptionsTemplateValue<T>
|
||||||
|
];
|
||||||
|
|
||||||
export type OptionsWithOptionsTemplate<T> = {
|
export type OptionsWithOptionsTemplate<T> = {
|
||||||
[P in keyof T]: T[P] extends OptionsObjectType
|
[P in keyof T]: T[P] extends OptionsObjectType
|
||||||
@@ -29,14 +32,17 @@ export type OptionsWithOptionsTemplate<T> = {
|
|||||||
* @param optionsWithOptionsTemplate The OptionsWithOptionsTemplate<T> object which shall be converted.
|
* @param optionsWithOptionsTemplate The OptionsWithOptionsTemplate<T> object which shall be converted.
|
||||||
* @param toTemplate True if the given OptionsWithOptionsTemplate<T> shall be converted to its corresponding Template object.
|
* @param toTemplate True if the given OptionsWithOptionsTemplate<T> shall be converted to its corresponding Template object.
|
||||||
*/
|
*/
|
||||||
export const transformOptions = <T>(optionsWithOptionsTemplate: OptionsWithOptionsTemplate<T>): OptionsWithOptionsTemplateTransformation<T> => {
|
export const transformOptions = <T>(
|
||||||
|
optionsWithOptionsTemplate: OptionsWithOptionsTemplate<T>
|
||||||
|
): OptionsWithOptionsTemplateTransformation<T> => {
|
||||||
const result: any = {
|
const result: any = {
|
||||||
_template: {},
|
_template: {},
|
||||||
_options: {},
|
_options: {},
|
||||||
};
|
};
|
||||||
|
|
||||||
each(keys(optionsWithOptionsTemplate), (key: Extract<keyof T, string>) => {
|
each(keys(optionsWithOptionsTemplate), (key: Extract<keyof T, string>) => {
|
||||||
const val: PlainObject | OptionsTemplateTypes | Array<OptionsTemplateTypes> = optionsWithOptionsTemplate[key];
|
const val: PlainObject | OptionsTemplateTypes | Array<OptionsTemplateTypes> =
|
||||||
|
optionsWithOptionsTemplate[key];
|
||||||
|
|
||||||
if (isArray(val)) {
|
if (isArray(val)) {
|
||||||
result._template[key] = val[1];
|
result._template[key] = val[1];
|
||||||
|
|||||||
@@ -1,10 +1,21 @@
|
|||||||
import { each, hasOwnProperty, keys, push, isEmptyObject } from 'support/utils';
|
import { each, hasOwnProperty, keys, push, isEmptyObject } from 'support/utils';
|
||||||
import { type, isArray, isUndefined, isPlainObject, isString, isNumber, isBoolean } from 'support/utils/types';
|
import {
|
||||||
|
type,
|
||||||
|
isArray,
|
||||||
|
isUndefined,
|
||||||
|
isPlainObject,
|
||||||
|
isString,
|
||||||
|
isNumber,
|
||||||
|
isBoolean,
|
||||||
|
} from 'support/utils/types';
|
||||||
import { PlainObject } from 'typings';
|
import { PlainObject } from 'typings';
|
||||||
|
|
||||||
export type OptionsObjectType = Record<string, unknown>;
|
export type OptionsObjectType = Record<string, unknown>;
|
||||||
export type OptionsFunctionType = (this: unknown, ...args: unknown[]) => unknown;
|
export type OptionsFunctionType = (this: unknown, ...args: unknown[]) => unknown;
|
||||||
export type OptionsTemplateType<T extends OptionsTemplateNativeTypes> = ExtractPropsKey<OptionsTemplateTypeMap, T>;
|
export type OptionsTemplateType<T extends OptionsTemplateNativeTypes> = ExtractPropsKey<
|
||||||
|
OptionsTemplateTypeMap,
|
||||||
|
T
|
||||||
|
>;
|
||||||
export type OptionsTemplateTypes = keyof OptionsTemplateTypeMap;
|
export type OptionsTemplateTypes = keyof OptionsTemplateTypeMap;
|
||||||
export type OptionsTemplateNativeTypes = OptionsTemplateTypeMap[keyof OptionsTemplateTypeMap];
|
export type OptionsTemplateNativeTypes = OptionsTemplateTypeMap[keyof OptionsTemplateTypeMap];
|
||||||
|
|
||||||
@@ -71,13 +82,18 @@ const templateTypePrefixSuffix: readonly [string, string] = ['__TPL_', '_TYPE__'
|
|||||||
* Key = normal type string
|
* Key = normal type string
|
||||||
* value = template type string
|
* value = template type string
|
||||||
*/
|
*/
|
||||||
const optionsTemplateTypes: OptionsTemplateTypesDictionary = ['boolean', 'number', 'string', 'array', 'object', 'function', 'null'].reduce(
|
const optionsTemplateTypes: OptionsTemplateTypesDictionary = [
|
||||||
(result, item) => {
|
'boolean',
|
||||||
result[item] = templateTypePrefixSuffix[0] + item + templateTypePrefixSuffix[1];
|
'number',
|
||||||
return result;
|
'string',
|
||||||
},
|
'array',
|
||||||
{} as OptionsTemplateTypesDictionary
|
'object',
|
||||||
);
|
'function',
|
||||||
|
'null',
|
||||||
|
].reduce((result, item) => {
|
||||||
|
result[item] = templateTypePrefixSuffix[0] + item + templateTypePrefixSuffix[1];
|
||||||
|
return result;
|
||||||
|
}, {} as OptionsTemplateTypesDictionary);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Validates the given options object according to the given template object and returns a object which looks like:
|
* Validates the given options object according to the given template object and returns a object which looks like:
|
||||||
@@ -111,13 +127,20 @@ const validateRecursive = <T extends PlainObject>(
|
|||||||
each(props, (prop: Extract<keyof T, string>) => {
|
each(props, (prop: Extract<keyof T, string>) => {
|
||||||
const optionsDiffValue: any = isUndefined(optionsDiff[prop]) ? {} : optionsDiff[prop];
|
const optionsDiffValue: any = isUndefined(optionsDiff[prop]) ? {} : optionsDiff[prop];
|
||||||
const optionsValue: any = options[prop];
|
const optionsValue: any = options[prop];
|
||||||
const templateValue: PlainObject | string | OptionsTemplateTypes | Array<OptionsTemplateTypes> = template[prop];
|
const templateValue: PlainObject | string | OptionsTemplateTypes | Array<OptionsTemplateTypes> =
|
||||||
|
template[prop];
|
||||||
const templateIsComplex = isPlainObject(templateValue);
|
const templateIsComplex = isPlainObject(templateValue);
|
||||||
const propPrefix = propPath ? `${propPath}.` : '';
|
const propPrefix = propPath ? `${propPath}.` : '';
|
||||||
|
|
||||||
// if the template has a object as value, it means that the options are complex (verschachtelt)
|
// if the template has a object as value, it means that the options are complex (verschachtelt)
|
||||||
if (templateIsComplex && isPlainObject(optionsValue)) {
|
if (templateIsComplex && isPlainObject(optionsValue)) {
|
||||||
const validatedResult = validateRecursive(optionsValue, templateValue as T, optionsDiffValue, doWriteErrors, propPrefix + prop);
|
const validatedResult = validateRecursive(
|
||||||
|
optionsValue,
|
||||||
|
templateValue as T,
|
||||||
|
optionsDiffValue,
|
||||||
|
doWriteErrors,
|
||||||
|
propPrefix + prop
|
||||||
|
);
|
||||||
validatedOptions[prop] = validatedResult._validated as any;
|
validatedOptions[prop] = validatedResult._validated as any;
|
||||||
optionsCopy[prop] = validatedResult._foreign as any;
|
optionsCopy[prop] = validatedResult._foreign as any;
|
||||||
|
|
||||||
@@ -163,9 +186,15 @@ const validateRecursive = <T extends PlainObject>(
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (isValid) {
|
if (isValid) {
|
||||||
const isPrimitiveArr = isArray(optionsValue) && !optionsValue.some((val) => !isNumber(val) && !isString(val) && !isBoolean(val));
|
const isPrimitiveArr =
|
||||||
|
isArray(optionsValue) &&
|
||||||
|
!optionsValue.some((val) => !isNumber(val) && !isString(val) && !isBoolean(val));
|
||||||
const doStringifyComparison = isPrimitiveArr || isPlainObject(optionsValue);
|
const doStringifyComparison = isPrimitiveArr || isPlainObject(optionsValue);
|
||||||
if (doStringifyComparison ? stringify(optionsValue) !== stringify(optionsDiffValue) : optionsValue !== optionsDiffValue) {
|
if (
|
||||||
|
doStringifyComparison
|
||||||
|
? stringify(optionsValue) !== stringify(optionsDiffValue)
|
||||||
|
: optionsValue !== optionsDiffValue
|
||||||
|
) {
|
||||||
validatedOptions[prop] = optionsValue;
|
validatedOptions[prop] = optionsValue;
|
||||||
}
|
}
|
||||||
} else if (doWriteErrors) {
|
} else if (doWriteErrors) {
|
||||||
@@ -173,7 +202,11 @@ const validateRecursive = <T extends PlainObject>(
|
|||||||
`${
|
`${
|
||||||
`The option "${propPrefix}${prop}" wasn't set, because it doesn't accept the type [ ${optionsValueType.toUpperCase()} ] with the value of "${optionsValue}".\r\n` +
|
`The option "${propPrefix}${prop}" wasn't set, because it doesn't accept the type [ ${optionsValueType.toUpperCase()} ] with the value of "${optionsValue}".\r\n` +
|
||||||
`Accepted types are: [ ${errorPossibleTypes.join(', ').toUpperCase()} ].\r\n`
|
`Accepted types are: [ ${errorPossibleTypes.join(', ').toUpperCase()} ].\r\n`
|
||||||
}${errorEnumStrings.length > 0 ? `\r\nValid strings are: [ ${errorEnumStrings.join(', ')} ].` : ''}`
|
}${
|
||||||
|
errorEnumStrings.length > 0
|
||||||
|
? `\r\nValid strings are: [ ${errorEnumStrings.join(', ')} ].`
|
||||||
|
: ''
|
||||||
|
}`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -209,7 +242,7 @@ const validateOptions = <T extends PlainObject>(
|
|||||||
template: OptionsTemplate<T>,
|
template: OptionsTemplate<T>,
|
||||||
optionsDiff?: T | null,
|
optionsDiff?: T | null,
|
||||||
doWriteErrors?: boolean
|
doWriteErrors?: boolean
|
||||||
): OptionsValidationResult<T> => {
|
): OptionsValidationResult<T> =>
|
||||||
/*
|
/*
|
||||||
if (!isEmptyObject(foreign) && doWriteErrors)
|
if (!isEmptyObject(foreign) && doWriteErrors)
|
||||||
console.warn(`The following options are discarded due to invalidity:\r\n ${window.JSON.stringify(foreign, null, 2)}`);
|
console.warn(`The following options are discarded due to invalidity:\r\n ${window.JSON.stringify(foreign, null, 2)}`);
|
||||||
@@ -219,7 +252,6 @@ const validateOptions = <T extends PlainObject>(
|
|||||||
Object.assign(result.validated, foreign);
|
Object.assign(result.validated, foreign);
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
return validateRecursive<T>(options, template, optionsDiff || ({} as T), doWriteErrors || false);
|
validateRecursive<T>(options, template, optionsDiff || ({} as T), doWriteErrors || false);
|
||||||
};
|
|
||||||
|
|
||||||
export { validateOptions, optionsTemplateTypes };
|
export { validateOptions, optionsTemplateTypes };
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { isArrayLike, isString } from 'support/utils/types';
|
import { isArrayLike, isString, isArray } from 'support/utils/types';
|
||||||
import { PlainObject } from 'typings';
|
import { PlainObject } from 'typings';
|
||||||
|
|
||||||
type RunEachItem = ((...args: any) => any | any[]) | null | undefined;
|
type RunEachItem = ((...args: any) => any | any[]) | null | undefined;
|
||||||
@@ -56,21 +56,17 @@ export function each<T>(
|
|||||||
* @param item The item.
|
* @param item The item.
|
||||||
* @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the search starts at index 0.
|
* @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the search starts at index 0.
|
||||||
*/
|
*/
|
||||||
export const indexOf = <T = any>(arr: Array<T>, item: T, fromIndex?: number): number =>
|
export const indexOf = <T = any>(arr: T[], item: T, fromIndex?: number): number =>
|
||||||
arr.indexOf(item, fromIndex);
|
isArray(arr) ? arr.indexOf(item, fromIndex) : -1;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pushesh all given items into the given array and returns it.
|
* Pushesh all given items into the given array and returns it.
|
||||||
* @param array The array the items shall be pushed into.
|
* @param array The array the items shall be pushed into.
|
||||||
* @param items The items which shall be pushed into the array.
|
* @param items The items which shall be pushed into the array.
|
||||||
*/
|
*/
|
||||||
export const push = <T>(
|
export const push = <T>(array: T[], items: T | ArrayLike<T>, arrayIsSingleItem?: boolean): T[] => {
|
||||||
array: Array<T>,
|
|
||||||
items: T | ArrayLike<T>,
|
|
||||||
arrayIsSingleItem?: boolean
|
|
||||||
): Array<T> => {
|
|
||||||
!arrayIsSingleItem && !isString(items) && isArrayLike(items)
|
!arrayIsSingleItem && !isString(items) && isArrayLike(items)
|
||||||
? Array.prototype.push.apply(array, items as Array<T>)
|
? Array.prototype.push.apply(array, items as T[])
|
||||||
: array.push(items as T);
|
: array.push(items as T);
|
||||||
return array;
|
return array;
|
||||||
};
|
};
|
||||||
@@ -83,7 +79,7 @@ export const from = <T = any>(arr: ArrayLike<T>) => {
|
|||||||
if (Array.from) {
|
if (Array.from) {
|
||||||
return Array.from(arr);
|
return Array.from(arr);
|
||||||
}
|
}
|
||||||
const result: Array<T> = [];
|
const result: T[] = [];
|
||||||
|
|
||||||
each(arr, (elm) => {
|
each(arr, (elm) => {
|
||||||
push(result, elm);
|
push(result, elm);
|
||||||
@@ -96,7 +92,7 @@ export const from = <T = any>(arr: ArrayLike<T>) => {
|
|||||||
* Check whether the passed array is empty.
|
* Check whether the passed array is empty.
|
||||||
* @param array The array which shall be checked.
|
* @param array The array which shall be checked.
|
||||||
*/
|
*/
|
||||||
export const isEmptyArray = (array: Array<any> | null | undefined): boolean =>
|
export const isEmptyArray = (array: any[] | null | undefined): boolean =>
|
||||||
!!array && array.length === 0;
|
!!array && array.length === 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -6,7 +6,8 @@ import { each } from 'support/utils/array';
|
|||||||
* @param obj The object.
|
* @param obj The object.
|
||||||
* @param prop The name of the property.
|
* @param prop The name of the property.
|
||||||
*/
|
*/
|
||||||
export const hasOwnProperty = (obj: any, prop: string | number | symbol): boolean => Object.prototype.hasOwnProperty.call(obj, prop);
|
export const hasOwnProperty = (obj: any, prop: string | number | symbol): boolean =>
|
||||||
|
Object.prototype.hasOwnProperty.call(obj, prop);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the names of the enumerable string properties and methods of an object.
|
* Returns the names of the enumerable string properties and methods of an object.
|
||||||
@@ -17,9 +18,27 @@ export const keys = (obj: any): Array<string> => (obj ? Object.keys(obj) : []);
|
|||||||
// https://github.com/jquery/jquery/blob/master/src/core.js#L116
|
// https://github.com/jquery/jquery/blob/master/src/core.js#L116
|
||||||
export function assignDeep<T, U>(target: T, object1: U): T & U;
|
export function assignDeep<T, U>(target: T, object1: U): T & U;
|
||||||
export function assignDeep<T, U, V>(target: T, object1: U, object2: V): T & U & V;
|
export function assignDeep<T, U, V>(target: T, object1: U, object2: V): T & U & V;
|
||||||
export function assignDeep<T, U, V, W>(target: T, object1: U, object2: V, object3: W): T & U & V & W;
|
export function assignDeep<T, U, V, W>(
|
||||||
export function assignDeep<T, U, V, W, X>(target: T, object1: U, object2: V, object3: W, object4: X): T & U & V & W & X;
|
target: T,
|
||||||
export function assignDeep<T, U, V, W, X, Y>(target: T, object1: U, object2: V, object3: W, object4: X, object5: Y): T & U & V & W & X & Y;
|
object1: U,
|
||||||
|
object2: V,
|
||||||
|
object3: W
|
||||||
|
): T & U & V & W;
|
||||||
|
export function assignDeep<T, U, V, W, X>(
|
||||||
|
target: T,
|
||||||
|
object1: U,
|
||||||
|
object2: V,
|
||||||
|
object3: W,
|
||||||
|
object4: X
|
||||||
|
): T & U & V & W & X;
|
||||||
|
export function assignDeep<T, U, V, W, X, Y>(
|
||||||
|
target: T,
|
||||||
|
object1: U,
|
||||||
|
object2: V,
|
||||||
|
object3: W,
|
||||||
|
object4: X,
|
||||||
|
object5: Y
|
||||||
|
): T & U & V & W & X & Y;
|
||||||
export function assignDeep<T, U, V, W, X, Y, Z>(
|
export function assignDeep<T, U, V, W, X, Y, Z>(
|
||||||
target: T,
|
target: T,
|
||||||
object1?: U,
|
object1?: U,
|
||||||
|
|||||||
@@ -11,14 +11,13 @@ export function isNull(obj: any): obj is null {
|
|||||||
return obj === null;
|
return obj === null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const type: (obj: any) => string = (obj) => {
|
export const type: (obj: any) => string = (obj) =>
|
||||||
return isUndefined(obj) || isNull(obj)
|
isUndefined(obj) || isNull(obj)
|
||||||
? `${obj}`
|
? `${obj}`
|
||||||
: toString
|
: toString
|
||||||
.call(obj)
|
.call(obj)
|
||||||
.replace(/^\[object (.+)\]$/, '$1')
|
.replace(/^\[object (.+)\]$/, '$1')
|
||||||
.toLowerCase();
|
.toLowerCase();
|
||||||
};
|
|
||||||
|
|
||||||
export function isNumber(obj: any): obj is number {
|
export function isNumber(obj: any): obj is number {
|
||||||
return typeof obj === 'number';
|
return typeof obj === 'number';
|
||||||
@@ -52,7 +51,11 @@ export function isArrayLike<T extends PlainObject = any>(obj: any): obj is Array
|
|||||||
const length = !!obj && obj.length;
|
const length = !!obj && obj.length;
|
||||||
const lengthCorrectFormat = isNumber(length) && length > -1 && length % 1 == 0; // eslint-disable-line eqeqeq
|
const lengthCorrectFormat = isNumber(length) && length > -1 && length % 1 == 0; // eslint-disable-line eqeqeq
|
||||||
|
|
||||||
return isArray(obj) || (!isFunction(obj) && lengthCorrectFormat) ? (length > 0 && isObject(obj) ? length - 1 in obj : true) : false;
|
return isArray(obj) || (!isFunction(obj) && lengthCorrectFormat)
|
||||||
|
? length > 0 && isObject(obj)
|
||||||
|
? length - 1 in obj
|
||||||
|
: true
|
||||||
|
: false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -88,7 +91,11 @@ export function isPlainObject<T = any>(obj: any): obj is PlainObject<T> {
|
|||||||
*/
|
*/
|
||||||
export function isHTMLElement(obj: any): obj is HTMLElement {
|
export function isHTMLElement(obj: any): obj is HTMLElement {
|
||||||
const instanceofObj = window.HTMLElement;
|
const instanceofObj = window.HTMLElement;
|
||||||
return obj ? (instanceofObj ? obj instanceof instanceofObj : obj.nodeType === ElementNodeType) : false;
|
return obj
|
||||||
|
? instanceofObj
|
||||||
|
? obj instanceof instanceofObj
|
||||||
|
: obj.nodeType === ElementNodeType
|
||||||
|
: false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -97,5 +104,9 @@ export function isHTMLElement(obj: any): obj is HTMLElement {
|
|||||||
*/
|
*/
|
||||||
export function isElement(obj: any): obj is Element {
|
export function isElement(obj: any): obj is Element {
|
||||||
const instanceofObj = window.Element;
|
const instanceofObj = window.Element;
|
||||||
return obj ? (instanceofObj ? obj instanceof instanceofObj : obj.nodeType === ElementNodeType) : false;
|
return obj
|
||||||
|
? instanceofObj
|
||||||
|
? obj instanceof instanceofObj
|
||||||
|
: obj.nodeType === ElementNodeType
|
||||||
|
: false;
|
||||||
}
|
}
|
||||||
|
|||||||
+119
-105
@@ -1,128 +1,122 @@
|
|||||||
import { createCache } from 'support/cache';
|
import { createCache } from 'support/cache';
|
||||||
|
|
||||||
const createUpdater = <T, C = unknown>(updaterReturn: (i: number) => T) => {
|
const createUpdater = <T>(updaterReturn: (i: number) => T) => {
|
||||||
const fn = jest.fn();
|
|
||||||
let index = 0;
|
let index = 0;
|
||||||
const update = (context?: C, curr?: T, prev?: T): T => {
|
const updater = jest.fn(
|
||||||
fn(context, curr, prev);
|
(): T => {
|
||||||
index += 1;
|
index += 1;
|
||||||
return updaterReturn(index);
|
return updaterReturn(index);
|
||||||
};
|
}
|
||||||
|
);
|
||||||
|
|
||||||
return [fn, update];
|
return updater;
|
||||||
};
|
};
|
||||||
|
|
||||||
describe('cache', () => {
|
describe('cache', () => {
|
||||||
test('creates and updates cache', () => {
|
test('creates and updates cache', () => {
|
||||||
const [fn, updater] = createUpdater((i) => `${i}`);
|
const updater = createUpdater((i) => `${i}`);
|
||||||
const _initialValue = '';
|
const _initialValue = '';
|
||||||
const [updateCache, getCurrentCache] = createCache<string>(updater, {
|
const [updateCache, getCurrentCache] = createCache<string>(
|
||||||
_initialValue,
|
{
|
||||||
});
|
_initialValue,
|
||||||
|
},
|
||||||
|
updater
|
||||||
|
);
|
||||||
|
|
||||||
let [value, changed, previous] = updateCache();
|
let [value, changed, previous] = updateCache();
|
||||||
expect([value, false, previous]).toEqual(getCurrentCache());
|
expect([value, false, previous]).toEqual(getCurrentCache());
|
||||||
expect(fn).toHaveBeenLastCalledWith(undefined, _initialValue, undefined);
|
expect(updater).toHaveBeenLastCalledWith(_initialValue, undefined);
|
||||||
expect(value).toBe('1');
|
expect(value).toBe('1');
|
||||||
expect(previous).toBe(_initialValue);
|
expect(previous).toBe(_initialValue);
|
||||||
expect(changed).toBe(true);
|
expect(changed).toBe(true);
|
||||||
|
|
||||||
[value, changed, previous] = updateCache();
|
[value, changed, previous] = updateCache();
|
||||||
expect([value, false, previous]).toEqual(getCurrentCache());
|
expect([value, false, previous]).toEqual(getCurrentCache());
|
||||||
expect(fn).toHaveBeenLastCalledWith(undefined, '1', _initialValue);
|
expect(updater).toHaveBeenLastCalledWith('1', _initialValue);
|
||||||
expect(value).toBe('2');
|
expect(value).toBe('2');
|
||||||
expect(previous).toBe('1');
|
expect(previous).toBe('1');
|
||||||
expect(changed).toBe(true);
|
expect(changed).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('context', () => {
|
describe('contextual cache', () => {
|
||||||
test('creates and updates cache with context', () => {
|
test('creates and updates contextual cache', () => {
|
||||||
interface ContextObj {
|
interface ContextObj {
|
||||||
test: string;
|
test: string;
|
||||||
even: number;
|
even: number;
|
||||||
}
|
}
|
||||||
const _initialValue = false;
|
const _initialValue = false;
|
||||||
const updateFn = jest.fn();
|
const updater = (context: ContextObj) => context!.test === 'test' || context!.even % 2 === 0;
|
||||||
const updater = (context?: ContextObj, current?: boolean, previous?: boolean) => {
|
const [updateCache, getCurrentCache] = createCache({ _initialValue });
|
||||||
updateFn(context, current, previous);
|
|
||||||
return context!.test === 'test' || context!.even % 2 === 0;
|
|
||||||
};
|
|
||||||
const [updateCache, getCurrentCache] = createCache(updater, { _initialValue });
|
|
||||||
const firstCtx = { test: 'test', even: 2 };
|
const firstCtx = { test: 'test', even: 2 };
|
||||||
|
|
||||||
let [value, changed, previous] = updateCache(0, firstCtx);
|
let [value, changed, previous] = updateCache(updater(firstCtx));
|
||||||
expect([value, false, previous]).toEqual(getCurrentCache());
|
expect([value, false, previous]).toEqual(getCurrentCache());
|
||||||
expect(updateFn).toHaveBeenLastCalledWith(firstCtx, _initialValue, undefined);
|
|
||||||
expect(value).toBe(true);
|
expect(value).toBe(true);
|
||||||
expect(previous).toBe(_initialValue);
|
expect(previous).toBe(_initialValue);
|
||||||
expect(changed).toBe(true);
|
expect(changed).toBe(true);
|
||||||
expect([value, false, previous]).toEqual(getCurrentCache());
|
expect([value, false, previous]).toEqual(getCurrentCache());
|
||||||
|
|
||||||
[value, changed, previous] = updateCache(0, firstCtx);
|
[value, changed, previous] = updateCache(updater(firstCtx));
|
||||||
expect([value, false, previous]).toEqual(getCurrentCache());
|
expect([value, false, previous]).toEqual(getCurrentCache());
|
||||||
expect(updateFn).toHaveBeenLastCalledWith(firstCtx, true, _initialValue);
|
|
||||||
expect(value).toBe(true);
|
expect(value).toBe(true);
|
||||||
expect(previous).toBe(_initialValue);
|
expect(previous).toBe(_initialValue);
|
||||||
expect(changed).toBe(false);
|
expect(changed).toBe(false);
|
||||||
|
|
||||||
const scndCtx = { test: 'nah', even: 1 };
|
const scndCtx = { test: 'nah', even: 1 };
|
||||||
|
|
||||||
[value, changed, previous] = updateCache(0, scndCtx);
|
[value, changed, previous] = updateCache(updater(scndCtx));
|
||||||
expect([value, false, previous]).toEqual(getCurrentCache());
|
expect([value, false, previous]).toEqual(getCurrentCache());
|
||||||
expect(updateFn).toHaveBeenLastCalledWith(scndCtx, true, _initialValue);
|
|
||||||
expect(value).toBe(false);
|
expect(value).toBe(false);
|
||||||
expect(previous).toBe(true);
|
expect(previous).toBe(true);
|
||||||
expect(changed).toBe(true);
|
expect(changed).toBe(true);
|
||||||
|
|
||||||
[value, changed, previous] = updateCache(0, scndCtx);
|
[value, changed, previous] = updateCache(updater(scndCtx));
|
||||||
expect([value, false, previous]).toEqual(getCurrentCache());
|
expect([value, false, previous]).toEqual(getCurrentCache());
|
||||||
expect(updateFn).toHaveBeenLastCalledWith(scndCtx, false, true);
|
|
||||||
expect(value).toBe(false);
|
expect(value).toBe(false);
|
||||||
expect(previous).toBe(true);
|
expect(previous).toBe(true);
|
||||||
expect(changed).toBe(false);
|
expect(changed).toBe(false);
|
||||||
|
|
||||||
[value, changed, previous] = updateCache(true, scndCtx);
|
[value, changed, previous] = updateCache(updater(scndCtx), true);
|
||||||
expect([value, false, previous]).toEqual(getCurrentCache());
|
expect([value, false, previous]).toEqual(getCurrentCache());
|
||||||
expect(updateFn).toHaveBeenLastCalledWith(scndCtx, false, true);
|
|
||||||
expect(value).toBe(false);
|
expect(value).toBe(false);
|
||||||
expect(previous).toBe(false);
|
expect(previous).toBe(false);
|
||||||
expect(changed).toBe(true);
|
expect(changed).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('creates and updates cache with context shorthand', () => {
|
test('creates and updates contextual cache with direct passing', () => {
|
||||||
interface ContextObj {
|
interface ContextObj {
|
||||||
test: string;
|
test: string;
|
||||||
even: number;
|
even: number;
|
||||||
}
|
}
|
||||||
const _initialValue = undefined;
|
const _initialValue = undefined;
|
||||||
const firstCtx = { test: 'test', even: 2 };
|
const firstCtx = { test: 'test', even: 2 };
|
||||||
const [_update] = createCache<ContextObj | undefined, ContextObj>(0, {
|
const [updateCache] = createCache<ContextObj | undefined>({
|
||||||
_initialValue,
|
_initialValue,
|
||||||
});
|
});
|
||||||
|
|
||||||
let [value, changed, previous] = _update(0, firstCtx);
|
let [value, changed, previous] = updateCache(firstCtx);
|
||||||
expect(value).toBe(firstCtx);
|
expect(value).toBe(firstCtx);
|
||||||
expect(previous).toBe(undefined);
|
expect(previous).toBe(undefined);
|
||||||
expect(changed).toBe(true);
|
expect(changed).toBe(true);
|
||||||
|
|
||||||
[value, changed, previous] = _update(0, firstCtx);
|
[value, changed, previous] = updateCache(firstCtx);
|
||||||
expect(value).toBe(firstCtx);
|
expect(value).toBe(firstCtx);
|
||||||
expect(previous).toBe(undefined);
|
expect(previous).toBe(undefined);
|
||||||
expect(changed).toBe(false);
|
expect(changed).toBe(false);
|
||||||
|
|
||||||
const scndCtx = { test: 'nah', even: 1 };
|
const scndCtx = { test: 'nah', even: 1 };
|
||||||
|
|
||||||
[value, changed, previous] = _update(0, scndCtx);
|
[value, changed, previous] = updateCache(scndCtx);
|
||||||
expect(value).toBe(scndCtx);
|
expect(value).toBe(scndCtx);
|
||||||
expect(previous).toBe(firstCtx);
|
expect(previous).toBe(firstCtx);
|
||||||
expect(changed).toBe(true);
|
expect(changed).toBe(true);
|
||||||
|
|
||||||
[value, changed, previous] = _update(0, scndCtx);
|
[value, changed, previous] = updateCache(scndCtx);
|
||||||
expect(value).toBe(scndCtx);
|
expect(value).toBe(scndCtx);
|
||||||
expect(previous).toBe(firstCtx);
|
expect(previous).toBe(firstCtx);
|
||||||
expect(changed).toBe(false);
|
expect(changed).toBe(false);
|
||||||
|
|
||||||
[value, changed, previous] = _update(true, scndCtx);
|
[value, changed, previous] = updateCache(scndCtx, true);
|
||||||
expect(value).toBe(scndCtx);
|
expect(value).toBe(scndCtx);
|
||||||
expect(previous).toBe(scndCtx);
|
expect(previous).toBe(scndCtx);
|
||||||
expect(changed).toBe(true);
|
expect(changed).toBe(true);
|
||||||
@@ -131,65 +125,73 @@ describe('cache', () => {
|
|||||||
|
|
||||||
describe('equal', () => {
|
describe('equal', () => {
|
||||||
test('with equal always true', () => {
|
test('with equal always true', () => {
|
||||||
const [fn, updater] = createUpdater((i) => i);
|
const updater = createUpdater<number | undefined>((i) => i);
|
||||||
const [updateCache, getCurrentCache] = createCache<number | undefined>(updater, {
|
const [updateCache, getCurrentCache] = createCache<number | undefined>(
|
||||||
_initialValue: undefined,
|
{
|
||||||
_equal: () => true,
|
_initialValue: undefined,
|
||||||
});
|
_equal: () => true,
|
||||||
|
},
|
||||||
|
updater
|
||||||
|
);
|
||||||
|
|
||||||
let [value, changed, previous] = updateCache();
|
let [value, changed, previous] = updateCache();
|
||||||
expect([value, false, previous]).toEqual(getCurrentCache());
|
expect([value, false, previous]).toEqual(getCurrentCache());
|
||||||
expect(fn).toHaveBeenLastCalledWith(undefined, undefined, undefined);
|
expect(updater).toHaveBeenLastCalledWith(undefined, undefined);
|
||||||
expect(value).toBe(undefined);
|
expect(value).toBe(undefined);
|
||||||
expect(previous).toBe(undefined);
|
expect(previous).toBe(undefined);
|
||||||
expect(changed).toBe(false);
|
expect(changed).toBe(false);
|
||||||
|
|
||||||
[value, changed, previous] = updateCache();
|
[value, changed, previous] = updateCache();
|
||||||
expect([value, false, previous]).toEqual(getCurrentCache());
|
expect([value, false, previous]).toEqual(getCurrentCache());
|
||||||
expect(fn).toHaveBeenLastCalledWith(undefined, undefined, undefined);
|
expect(updater).toHaveBeenLastCalledWith(undefined, undefined);
|
||||||
expect(value).toBe(undefined);
|
expect(value).toBe(undefined);
|
||||||
expect(previous).toBe(undefined);
|
expect(previous).toBe(undefined);
|
||||||
expect(changed).toBe(false);
|
expect(changed).toBe(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('with equal always false', () => {
|
test('with equal always false', () => {
|
||||||
const [fn, updater] = createUpdater(() => 1);
|
const updater = createUpdater<number | undefined>(() => 1);
|
||||||
const [updateCache, getCurrentCache] = createCache<number | undefined>(updater, {
|
const [updateCache, getCurrentCache] = createCache<number | undefined>(
|
||||||
_initialValue: undefined,
|
{
|
||||||
_equal: () => false,
|
_initialValue: undefined,
|
||||||
});
|
_equal: () => false,
|
||||||
|
},
|
||||||
|
updater
|
||||||
|
);
|
||||||
|
|
||||||
let [value, changed, previous] = updateCache();
|
let [value, changed, previous] = updateCache();
|
||||||
expect([value, false, previous]).toEqual(getCurrentCache());
|
expect([value, false, previous]).toEqual(getCurrentCache());
|
||||||
expect(fn).toHaveBeenLastCalledWith(undefined, undefined, undefined);
|
expect(updater).toHaveBeenLastCalledWith(undefined, undefined);
|
||||||
expect(value).toBe(1);
|
expect(value).toBe(1);
|
||||||
expect(previous).toBe(undefined);
|
expect(previous).toBe(undefined);
|
||||||
expect(changed).toBe(true);
|
expect(changed).toBe(true);
|
||||||
|
|
||||||
[value, changed, previous] = updateCache();
|
[value, changed, previous] = updateCache();
|
||||||
expect([value, false, previous]).toEqual(getCurrentCache());
|
expect([value, false, previous]).toEqual(getCurrentCache());
|
||||||
expect(fn).toHaveBeenLastCalledWith(undefined, 1, undefined);
|
expect(updater).toHaveBeenLastCalledWith(1, undefined);
|
||||||
expect(value).toBe(1);
|
expect(value).toBe(1);
|
||||||
expect(previous).toBe(1);
|
expect(previous).toBe(1);
|
||||||
expect(changed).toBe(true);
|
expect(changed).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('with object equal', () => {
|
test('with object equal', () => {
|
||||||
const obj = { a: -1, b: -1 };
|
const updater = createUpdater((i) => ({ a: i, b: i + 1 }));
|
||||||
const [fn, updater] = createUpdater((i) => ({ a: i, b: i + 1 }));
|
const [updateCache] = createCache(
|
||||||
const [updateCache] = createCache<typeof obj | undefined>(updater, {
|
{
|
||||||
_initialValue: undefined,
|
_initialValue: undefined,
|
||||||
_equal: (a, b) => a?.a === b?.a && a?.b === b?.b,
|
_equal: (a, b) => a?.a === b?.a && a?.b === b?.b,
|
||||||
});
|
},
|
||||||
|
updater
|
||||||
|
);
|
||||||
|
|
||||||
let [value, changed, previous] = updateCache();
|
let [value, changed, previous] = updateCache();
|
||||||
expect(fn).toHaveBeenLastCalledWith(undefined, undefined, undefined);
|
expect(updater).toHaveBeenLastCalledWith(undefined, undefined);
|
||||||
expect(value).toEqual({ a: 1, b: 2 });
|
expect(value).toEqual({ a: 1, b: 2 });
|
||||||
expect(previous).toBe(undefined);
|
expect(previous).toBe(undefined);
|
||||||
expect(changed).toBe(true);
|
expect(changed).toBe(true);
|
||||||
|
|
||||||
[value, changed, previous] = updateCache();
|
[value, changed, previous] = updateCache();
|
||||||
expect(fn).toHaveBeenLastCalledWith(undefined, { a: 1, b: 2 }, undefined);
|
expect(updater).toHaveBeenLastCalledWith({ a: 1, b: 2 }, undefined);
|
||||||
expect(value).toEqual({ a: 2, b: 3 });
|
expect(value).toEqual({ a: 2, b: 3 });
|
||||||
expect(previous).toEqual({ a: 1, b: 2 });
|
expect(previous).toEqual({ a: 1, b: 2 });
|
||||||
expect(changed).toBe(true);
|
expect(changed).toBe(true);
|
||||||
@@ -198,19 +200,19 @@ describe('cache', () => {
|
|||||||
|
|
||||||
describe('inital value', () => {
|
describe('inital value', () => {
|
||||||
test('creates and updates cache with initialValue', () => {
|
test('creates and updates cache with initialValue', () => {
|
||||||
const [fn, updater] = createUpdater((i) => i);
|
const updater = createUpdater((i) => i);
|
||||||
const [updateCache, getCurrentCache] = createCache<number>(updater, { _initialValue: 0 });
|
const [updateCache, getCurrentCache] = createCache<number>({ _initialValue: 0 }, updater);
|
||||||
|
|
||||||
let [value, changed, previous] = updateCache();
|
let [value, changed, previous] = updateCache();
|
||||||
expect([value, false, previous]).toEqual(getCurrentCache());
|
expect([value, false, previous]).toEqual(getCurrentCache());
|
||||||
expect(fn).toHaveBeenLastCalledWith(undefined, 0, undefined);
|
expect(updater).toHaveBeenLastCalledWith(0, undefined);
|
||||||
expect(value).toBe(1);
|
expect(value).toBe(1);
|
||||||
expect(previous).toBe(0);
|
expect(previous).toBe(0);
|
||||||
expect(changed).toBe(true);
|
expect(changed).toBe(true);
|
||||||
|
|
||||||
[value, changed, previous] = updateCache();
|
[value, changed, previous] = updateCache();
|
||||||
expect([value, false, previous]).toEqual(getCurrentCache());
|
expect([value, false, previous]).toEqual(getCurrentCache());
|
||||||
expect(fn).toHaveBeenLastCalledWith(undefined, 1, 0);
|
expect(updater).toHaveBeenLastCalledWith(1, 0);
|
||||||
expect(value).toBe(2);
|
expect(value).toBe(2);
|
||||||
expect(previous).toBe(1);
|
expect(previous).toBe(1);
|
||||||
expect(changed).toBe(true);
|
expect(changed).toBe(true);
|
||||||
@@ -218,20 +220,23 @@ describe('cache', () => {
|
|||||||
|
|
||||||
test('creates and updates cache with initialValue and equal', () => {
|
test('creates and updates cache with initialValue and equal', () => {
|
||||||
const obj = { a: -1, b: -1 };
|
const obj = { a: -1, b: -1 };
|
||||||
const [fn, updater] = createUpdater((i) => ({ a: i, b: i + 1 }));
|
const updater = createUpdater((i) => ({ a: i, b: i + 1 }));
|
||||||
const [updateCache] = createCache<typeof obj>(updater, {
|
const [updateCache] = createCache(
|
||||||
_initialValue: obj,
|
{
|
||||||
_equal: (a, b) => a?.a === b?.a && a?.b === b?.b,
|
_initialValue: obj,
|
||||||
});
|
_equal: (a, b) => a?.a === b?.a && a?.b === b?.b,
|
||||||
|
},
|
||||||
|
updater
|
||||||
|
);
|
||||||
|
|
||||||
let [value, changed, previous] = updateCache();
|
let [value, changed, previous] = updateCache();
|
||||||
expect(fn).toHaveBeenLastCalledWith(undefined, obj, undefined);
|
expect(updater).toHaveBeenLastCalledWith(obj, undefined);
|
||||||
expect(value).toEqual({ a: 1, b: 2 });
|
expect(value).toEqual({ a: 1, b: 2 });
|
||||||
expect(previous).toBe(obj);
|
expect(previous).toBe(obj);
|
||||||
expect(changed).toBe(true);
|
expect(changed).toBe(true);
|
||||||
|
|
||||||
[value, changed, previous] = updateCache();
|
[value, changed, previous] = updateCache();
|
||||||
expect(fn).toHaveBeenLastCalledWith(undefined, { a: 1, b: 2 }, obj);
|
expect(updater).toHaveBeenLastCalledWith({ a: 1, b: 2 }, obj);
|
||||||
expect(value).toEqual({ a: 2, b: 3 });
|
expect(value).toEqual({ a: 2, b: 3 });
|
||||||
expect(previous).toEqual({ a: 1, b: 2 });
|
expect(previous).toEqual({ a: 1, b: 2 });
|
||||||
expect(changed).toBe(true);
|
expect(changed).toBe(true);
|
||||||
@@ -240,44 +245,47 @@ describe('cache', () => {
|
|||||||
|
|
||||||
describe('always update values', () => {
|
describe('always update values', () => {
|
||||||
test('creates and updates cache with alwaysUpdateValues and equal always true', () => {
|
test('creates and updates cache with alwaysUpdateValues and equal always true', () => {
|
||||||
const [fn, updater] = createUpdater((i) => i);
|
const updater = createUpdater<number | undefined>((i) => i);
|
||||||
const [updateCache] = createCache<number | undefined>(updater, {
|
const [updateCache] = createCache<number | undefined>(
|
||||||
_initialValue: undefined,
|
{
|
||||||
_alwaysUpdateValues: true,
|
_initialValue: undefined,
|
||||||
_equal: () => true,
|
_alwaysUpdateValues: true,
|
||||||
});
|
_equal: () => true,
|
||||||
|
},
|
||||||
|
updater
|
||||||
|
);
|
||||||
|
|
||||||
let [value, changed, previous] = updateCache();
|
let [value, changed, previous] = updateCache();
|
||||||
expect(fn).toHaveBeenLastCalledWith(undefined, undefined, undefined);
|
expect(updater).toHaveBeenLastCalledWith(undefined, undefined);
|
||||||
expect(value).toBe(1);
|
expect(value).toBe(1);
|
||||||
expect(previous).toBe(undefined);
|
expect(previous).toBe(undefined);
|
||||||
expect(changed).toBe(false);
|
expect(changed).toBe(false);
|
||||||
|
|
||||||
[value, changed, previous] = updateCache();
|
[value, changed, previous] = updateCache();
|
||||||
expect(fn).toHaveBeenLastCalledWith(undefined, 1, undefined);
|
expect(updater).toHaveBeenLastCalledWith(1, undefined);
|
||||||
expect(value).toBe(2);
|
expect(value).toBe(2);
|
||||||
expect(previous).toBe(1);
|
expect(previous).toBe(1);
|
||||||
expect(changed).toBe(false);
|
expect(changed).toBe(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('creates and updates cache with context shorthand and alwaysUpdateValues', () => {
|
test('creates and updates contextual cache with alwaysUpdateValues', () => {
|
||||||
interface ContextObj {
|
interface ContextObj {
|
||||||
test: string;
|
test: string;
|
||||||
even: number;
|
even: number;
|
||||||
}
|
}
|
||||||
const [updateCache, getCurrentCache] = createCache<ContextObj | undefined, ContextObj>(0, {
|
const [updateCache, getCurrentCache] = createCache<ContextObj | undefined>({
|
||||||
_initialValue: undefined,
|
_initialValue: undefined,
|
||||||
_alwaysUpdateValues: true,
|
_alwaysUpdateValues: true,
|
||||||
});
|
});
|
||||||
const firstCtx = { test: 'test', even: 2 };
|
const firstCtx = { test: 'test', even: 2 };
|
||||||
|
|
||||||
let [value, changed, previous] = updateCache(0, firstCtx);
|
let [value, changed, previous] = updateCache(firstCtx);
|
||||||
expect([value, false, previous]).toEqual(getCurrentCache());
|
expect([value, false, previous]).toEqual(getCurrentCache());
|
||||||
expect(value).toBe(firstCtx);
|
expect(value).toBe(firstCtx);
|
||||||
expect(previous).toBe(undefined);
|
expect(previous).toBe(undefined);
|
||||||
expect(changed).toBe(true);
|
expect(changed).toBe(true);
|
||||||
|
|
||||||
[value, changed, previous] = updateCache(0, firstCtx);
|
[value, changed, previous] = updateCache(firstCtx);
|
||||||
expect([value, false, previous]).toEqual(getCurrentCache());
|
expect([value, false, previous]).toEqual(getCurrentCache());
|
||||||
expect(value).toBe(firstCtx);
|
expect(value).toBe(firstCtx);
|
||||||
expect(previous).toBe(firstCtx);
|
expect(previous).toBe(firstCtx);
|
||||||
@@ -285,19 +293,19 @@ describe('cache', () => {
|
|||||||
|
|
||||||
const scndCtx = { test: 'nah', even: 1 };
|
const scndCtx = { test: 'nah', even: 1 };
|
||||||
|
|
||||||
[value, changed, previous] = updateCache(0, scndCtx);
|
[value, changed, previous] = updateCache(scndCtx);
|
||||||
expect([value, false, previous]).toEqual(getCurrentCache());
|
expect([value, false, previous]).toEqual(getCurrentCache());
|
||||||
expect(value).toBe(scndCtx);
|
expect(value).toBe(scndCtx);
|
||||||
expect(previous).toBe(firstCtx);
|
expect(previous).toBe(firstCtx);
|
||||||
expect(changed).toBe(true);
|
expect(changed).toBe(true);
|
||||||
|
|
||||||
[value, changed, previous] = updateCache(0, scndCtx);
|
[value, changed, previous] = updateCache(scndCtx);
|
||||||
expect([value, false, previous]).toEqual(getCurrentCache());
|
expect([value, false, previous]).toEqual(getCurrentCache());
|
||||||
expect(value).toBe(scndCtx);
|
expect(value).toBe(scndCtx);
|
||||||
expect(previous).toBe(scndCtx);
|
expect(previous).toBe(scndCtx);
|
||||||
expect(changed).toBe(false);
|
expect(changed).toBe(false);
|
||||||
|
|
||||||
[value, changed, previous] = updateCache(true, scndCtx);
|
[value, changed, previous] = updateCache(scndCtx, true);
|
||||||
expect([value, false, previous]).toEqual(getCurrentCache());
|
expect([value, false, previous]).toEqual(getCurrentCache());
|
||||||
expect(value).toBe(scndCtx);
|
expect(value).toBe(scndCtx);
|
||||||
expect(previous).toBe(scndCtx);
|
expect(previous).toBe(scndCtx);
|
||||||
@@ -307,21 +315,24 @@ describe('cache', () => {
|
|||||||
|
|
||||||
describe('constant', () => {
|
describe('constant', () => {
|
||||||
test('updates constant initially without intial value', () => {
|
test('updates constant initially without intial value', () => {
|
||||||
const [fn, updater] = createUpdater(() => true);
|
const updater = createUpdater<boolean | undefined>(() => true);
|
||||||
const [updateCache, getCurrentCache] = createCache<boolean | undefined>(updater, {
|
const [updateCache, getCurrentCache] = createCache<boolean | undefined>(
|
||||||
_initialValue: undefined,
|
{
|
||||||
});
|
_initialValue: undefined,
|
||||||
|
},
|
||||||
|
updater
|
||||||
|
);
|
||||||
|
|
||||||
let [value, changed, previous] = updateCache();
|
let [value, changed, previous] = updateCache();
|
||||||
expect([value, false, previous]).toEqual(getCurrentCache());
|
expect([value, false, previous]).toEqual(getCurrentCache());
|
||||||
expect(fn).toHaveBeenLastCalledWith(undefined, undefined, undefined);
|
expect(updater).toHaveBeenLastCalledWith(undefined, undefined);
|
||||||
expect(value).toBe(true);
|
expect(value).toBe(true);
|
||||||
expect(previous).toBe(undefined);
|
expect(previous).toBe(undefined);
|
||||||
expect(changed).toBe(true);
|
expect(changed).toBe(true);
|
||||||
|
|
||||||
[value, changed, previous] = updateCache();
|
[value, changed, previous] = updateCache();
|
||||||
expect([value, false, previous]).toEqual(getCurrentCache());
|
expect([value, false, previous]).toEqual(getCurrentCache());
|
||||||
expect(fn).toHaveBeenLastCalledWith(undefined, true, undefined);
|
expect(updater).toHaveBeenLastCalledWith(true, undefined);
|
||||||
expect(value).toBe(true);
|
expect(value).toBe(true);
|
||||||
expect(previous).toBe(undefined);
|
expect(previous).toBe(undefined);
|
||||||
expect(changed).toBe(false);
|
expect(changed).toBe(false);
|
||||||
@@ -329,52 +340,55 @@ describe('cache', () => {
|
|||||||
|
|
||||||
test('doesnt update constant with initial value', () => {
|
test('doesnt update constant with initial value', () => {
|
||||||
const obj = { constant: true };
|
const obj = { constant: true };
|
||||||
const [fn, updater] = createUpdater(() => obj);
|
const updater = createUpdater(() => obj);
|
||||||
const [updateCache] = createCache<typeof obj>(updater, { _initialValue: obj });
|
const [updateCache] = createCache({ _initialValue: obj }, updater);
|
||||||
|
|
||||||
let [value, changed, previous] = updateCache();
|
let [value, changed, previous] = updateCache();
|
||||||
expect(fn).toHaveBeenLastCalledWith(undefined, obj, undefined);
|
expect(updater).toHaveBeenLastCalledWith(obj, undefined);
|
||||||
expect(value).toBe(obj);
|
expect(value).toBe(obj);
|
||||||
expect(previous).toBe(undefined);
|
expect(previous).toBe(undefined);
|
||||||
expect(changed).toBe(false);
|
expect(changed).toBe(false);
|
||||||
|
|
||||||
[value, changed, previous] = updateCache();
|
[value, changed, previous] = updateCache();
|
||||||
expect(fn).toHaveBeenLastCalledWith(undefined, obj, undefined);
|
expect(updater).toHaveBeenLastCalledWith(obj, undefined);
|
||||||
expect(value).toBe(obj);
|
expect(value).toBe(obj);
|
||||||
expect(previous).toBe(undefined);
|
expect(previous).toBe(undefined);
|
||||||
expect(changed).toBe(false);
|
expect(changed).toBe(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('updates constant with force', () => {
|
test('updates constant with force', () => {
|
||||||
const [fn, updater] = createUpdater(() => 'constant');
|
const updater = createUpdater<string | undefined>(() => 'constant');
|
||||||
const [updateCache, getCurrentCache] = createCache<string | undefined>(updater, {
|
const [updateCache, getCurrentCache] = createCache<string | undefined>(
|
||||||
_initialValue: undefined,
|
{
|
||||||
});
|
_initialValue: undefined,
|
||||||
|
},
|
||||||
|
updater
|
||||||
|
);
|
||||||
|
|
||||||
let [value, changed, previous] = updateCache();
|
let [value, changed, previous] = updateCache();
|
||||||
expect([value, false, previous]).toEqual(getCurrentCache());
|
expect([value, false, previous]).toEqual(getCurrentCache());
|
||||||
expect(fn).toHaveBeenLastCalledWith(undefined, undefined, undefined);
|
expect(updater).toHaveBeenLastCalledWith(undefined, undefined);
|
||||||
expect(value).toBe('constant');
|
expect(value).toBe('constant');
|
||||||
expect(previous).toBe(undefined);
|
expect(previous).toBe(undefined);
|
||||||
expect(changed).toBe(true);
|
expect(changed).toBe(true);
|
||||||
|
|
||||||
[value, changed, previous] = updateCache(true);
|
[value, changed, previous] = updateCache(true);
|
||||||
expect([value, false, previous]).toEqual(getCurrentCache());
|
expect([value, false, previous]).toEqual(getCurrentCache());
|
||||||
expect(fn).toHaveBeenLastCalledWith(undefined, 'constant', undefined);
|
expect(updater).toHaveBeenLastCalledWith('constant', undefined);
|
||||||
expect(value).toBe('constant');
|
expect(value).toBe('constant');
|
||||||
expect(previous).toBe('constant');
|
expect(previous).toBe('constant');
|
||||||
expect(changed).toBe(true);
|
expect(changed).toBe(true);
|
||||||
|
|
||||||
[value, changed, previous] = updateCache(false);
|
[value, changed, previous] = updateCache(false);
|
||||||
expect([value, false, previous]).toEqual(getCurrentCache());
|
expect([value, false, previous]).toEqual(getCurrentCache());
|
||||||
expect(fn).toHaveBeenLastCalledWith(undefined, 'constant', 'constant');
|
expect(updater).toHaveBeenLastCalledWith('constant', 'constant');
|
||||||
expect(value).toBe('constant');
|
expect(value).toBe('constant');
|
||||||
expect(previous).toBe('constant');
|
expect(previous).toBe('constant');
|
||||||
expect(changed).toBe(false);
|
expect(changed).toBe(false);
|
||||||
|
|
||||||
[value, changed, previous] = updateCache();
|
[value, changed, previous] = updateCache();
|
||||||
expect([value, false, previous]).toEqual(getCurrentCache());
|
expect([value, false, previous]).toEqual(getCurrentCache());
|
||||||
expect(fn).toHaveBeenLastCalledWith(undefined, 'constant', 'constant');
|
expect(updater).toHaveBeenLastCalledWith('constant', 'constant');
|
||||||
expect(value).toBe('constant');
|
expect(value).toBe('constant');
|
||||||
expect(previous).toBe('constant');
|
expect(previous).toBe('constant');
|
||||||
expect(changed).toBe(false);
|
expect(changed).toBe(false);
|
||||||
|
|||||||
Reference in New Issue
Block a user