mirror of
https://github.com/tenrok/OverlayScrollbars.git
synced 2026-05-17 07:29:40 +03:00
improve cache code and prettier
This commit is contained in:
@@ -83,11 +83,18 @@ module.exports = (esm, options, declarationFiles = false) => {
|
||||
rollupBabelInputPlugin({
|
||||
...(esm ? babelConfigEsm : babelConfigUmd),
|
||||
assumptions: {
|
||||
enumerableModuleMeta: false,
|
||||
constantReexports: true,
|
||||
iterableIsArray: true,
|
||||
objectRestNoSymbols: true,
|
||||
noNewArrows: true,
|
||||
noClassCalls: true,
|
||||
ignoreToPrimitiveHint: true,
|
||||
ignoreFunctionLength: true,
|
||||
// privateFieldsAsProperties: true,
|
||||
// setPublicClassFields: true,
|
||||
setSpreadProperties: true,
|
||||
pureGetters: true,
|
||||
},
|
||||
plugins: [
|
||||
'@babel/plugin-transform-runtime',
|
||||
|
||||
+59
-65
@@ -1,16 +1,16 @@
|
||||
const createCache = (update, options) => {
|
||||
function createCache(options, update) {
|
||||
const {
|
||||
_initialValue,
|
||||
_equal,
|
||||
_alwaysUpdateValues
|
||||
} = options || {};
|
||||
} = options;
|
||||
let _value = _initialValue;
|
||||
|
||||
let _previous;
|
||||
|
||||
const cacheUpdate = (force, context) => {
|
||||
const cacheUpdateContextual = (newValue, force) => {
|
||||
const curr = _value;
|
||||
const newVal = update ? update(context, _value, _previous) : context;
|
||||
const newVal = newValue;
|
||||
const changed = force || (_equal ? !_equal(curr, newVal) : curr !== newVal);
|
||||
|
||||
if (changed || _alwaysUpdateValues) {
|
||||
@@ -21,8 +21,12 @@ const createCache = (update, options) => {
|
||||
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 {
|
||||
@@ -35,9 +39,7 @@ function isUndefined(obj) {
|
||||
function isNull(obj) {
|
||||
return obj === null;
|
||||
}
|
||||
const type = obj => {
|
||||
return isUndefined(obj) || isNull(obj) ? `${obj}` : toString.call(obj).replace(/^\[object (.+)\]$/, '$1').toLowerCase();
|
||||
};
|
||||
const type = obj => isUndefined(obj) || isNull(obj) ? `${obj}` : toString.call(obj).replace(/^\[object (.+)\]$/, '$1').toLowerCase();
|
||||
function isNumber(obj) {
|
||||
return typeof obj === 'number';
|
||||
}
|
||||
@@ -100,7 +102,7 @@ function each(source, callback) {
|
||||
|
||||
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) => {
|
||||
!arrayIsSingleItem && !isString(items) && isArrayLike(items) ? Array.prototype.push.apply(array, items) : array.push(items);
|
||||
return array;
|
||||
@@ -116,7 +118,7 @@ const from = arr => {
|
||||
});
|
||||
return result;
|
||||
};
|
||||
const isEmptyArray = array => array && array.length === 0;
|
||||
const isEmptyArray = array => !!array && array.length === 0;
|
||||
const runEach = (arr, 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 equalBCRWH = (a, b, round) => equal(a, b, ['width', 'height'], round && (value => Math.round(value)));
|
||||
|
||||
const setT = window.setTimeout;
|
||||
|
||||
const clearTimeouts = id => {
|
||||
id && window.clearTimeout(id);
|
||||
id && cAF(id);
|
||||
@@ -481,7 +481,8 @@ const debounce = (functionToDebounce, options) => {
|
||||
_timeout,
|
||||
_maxDelay,
|
||||
_mergeParams
|
||||
} = options;
|
||||
} = options || {};
|
||||
const setT = window.setTimeout;
|
||||
|
||||
const invokeFunctionToDebounce = function invokeFunctionToDebounce(args) {
|
||||
clearTimeouts(timeoutId);
|
||||
@@ -499,7 +500,7 @@ const debounce = (functionToDebounce, options) => {
|
||||
};
|
||||
|
||||
const debouncedFn = function debouncedFn() {
|
||||
const args = arguments;
|
||||
const args = from(arguments);
|
||||
const finalTimeout = isFunction(_timeout) ? _timeout() : _timeout;
|
||||
const hasTimeout = isNumber(finalTimeout) && finalTimeout >= 0;
|
||||
|
||||
@@ -510,11 +511,6 @@ const debounce = (functionToDebounce, options) => {
|
||||
const mergeParamsResult = mergeParms(args);
|
||||
const invokedArgs = mergeParamsResult || args;
|
||||
const boundInvoke = invokeFunctionToDebounce.bind(0, invokedArgs);
|
||||
|
||||
if (!mergeParamsResult) {
|
||||
invokeFunctionToDebounce(prevArguments || args);
|
||||
}
|
||||
|
||||
clearTimeouts(timeoutId);
|
||||
timeoutId = setTimeoutFn(boundInvoke, finalTimeout);
|
||||
|
||||
@@ -550,13 +546,13 @@ const setCSSVal = (elm, prop, val) => {
|
||||
try {
|
||||
if (elm) {
|
||||
const {
|
||||
style
|
||||
style: elmStyle
|
||||
} = elm;
|
||||
|
||||
if (!isUndefined(style[prop])) {
|
||||
style[prop] = adaptCSSVal(prop, val);
|
||||
if (!isUndefined(elmStyle[prop])) {
|
||||
elmStyle[prop] = adaptCSSVal(prop, val);
|
||||
} else {
|
||||
style.setProperty(prop, val);
|
||||
elmStyle.setProperty(prop, val);
|
||||
}
|
||||
}
|
||||
} catch (e) {}
|
||||
@@ -717,9 +713,7 @@ const validateRecursive = (options, template, optionsDiff, doWriteErrors, propPa
|
||||
};
|
||||
};
|
||||
|
||||
const validateOptions = (options, template, optionsDiff, doWriteErrors) => {
|
||||
return validateRecursive(options, template, optionsDiff || {}, doWriteErrors || false);
|
||||
};
|
||||
const validateOptions = (options, template, optionsDiff, doWriteErrors) => validateRecursive(options, template, optionsDiff || {}, doWriteErrors || false);
|
||||
|
||||
const transformOptions = optionsWithOptionsTemplate => {
|
||||
const result = {
|
||||
@@ -1224,7 +1218,7 @@ const createSizeObserver = (target, onSizeChangedCallback, options) => {
|
||||
const sizeObserver = baseElements[0];
|
||||
const listenerElement = sizeObserver.firstChild;
|
||||
const getIsDirectionRTL = getElmDirectionIsRTL.bind(0, sizeObserver);
|
||||
const [updateResizeObserverContentRectCache] = createCache(0, {
|
||||
const [updateResizeObserverContentRectCache] = createCache({
|
||||
_initialValue: undefined,
|
||||
_alwaysUpdateValues: true,
|
||||
_equal: (currVal, newVal) => !(!currVal || !domRectHasDimensions(currVal) && domRectHasDimensions(newVal))
|
||||
@@ -1238,7 +1232,7 @@ const createSizeObserver = (target, onSizeChangedCallback, options) => {
|
||||
let doDirectionScroll = true;
|
||||
|
||||
if (isResizeObserverCall) {
|
||||
const [currRContentRect,, prevContentRect] = updateResizeObserverContentRectCache(0, sizeChangedContext.pop().contentRect);
|
||||
const [currRContentRect,, prevContentRect] = updateResizeObserverContentRectCache(sizeChangedContext.pop().contentRect);
|
||||
const hasDimensions = domRectHasDimensions(currRContentRect);
|
||||
const hadDimensions = domRectHasDimensions(prevContentRect);
|
||||
skip = !prevContentRect || !hasDimensions;
|
||||
@@ -1332,9 +1326,9 @@ const createSizeObserver = (target, onSizeChangedCallback, options) => {
|
||||
}
|
||||
|
||||
if (observeDirectionChange) {
|
||||
directionIsRTLCache = createCache(getIsDirectionRTL, {
|
||||
directionIsRTLCache = createCache({
|
||||
_initialValue: !getIsDirectionRTL()
|
||||
});
|
||||
}, getIsDirectionRTL);
|
||||
const [updateDirectionIsRTLCache] = directionIsRTLCache;
|
||||
push(offListeners, on(sizeObserver, scrollEventName, event => {
|
||||
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 trinsicObserver = createDiv(classNameTrinsicObserver);
|
||||
const offListeners = [];
|
||||
const [updateHeightIntrinsicCache, getCurrentHeightIntrinsicCache] = createCache(ioEntryOrSize => ioEntryOrSize.h === 0 || ioEntryOrSize.isIntersecting || ioEntryOrSize.intersectionRatio > 0, {
|
||||
const [updateHeightIntrinsicCache, getCurrentHeightIntrinsicCache] = createCache({
|
||||
_initialValue: false
|
||||
});
|
||||
|
||||
const triggerOnTrinsicChangedCallback = updateValue => {
|
||||
if (updateValue) {
|
||||
const heightIntrinsic = updateHeightIntrinsicCache(0, updateValue);
|
||||
const heightIntrinsic = updateHeightIntrinsicCache(isHeightIntrinsic(updateValue));
|
||||
const [, heightIntrinsicChanged] = heightIntrinsic;
|
||||
|
||||
if (heightIntrinsicChanged) {
|
||||
@@ -1819,10 +1815,10 @@ const createPaddingLifecycle = lifecycleHub => {
|
||||
_padding,
|
||||
_viewport
|
||||
} = _structureSetup._targetObj;
|
||||
const [updatePaddingCache, currentPaddingCache] = createCache(topRightBottomLeft.bind(0, _host, 'padding'), {
|
||||
const [updatePaddingCache, currentPaddingCache] = createCache({
|
||||
_equal: equalTRBL,
|
||||
_initialValue: topRightBottomLeft()
|
||||
});
|
||||
}, topRightBottomLeft.bind(0, _host, 'padding', ''));
|
||||
return (updateHints, checkOption, force) => {
|
||||
let [padding, paddingChanged] = currentPaddingCache(force);
|
||||
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 {
|
||||
_structureSetup,
|
||||
@@ -1939,16 +1940,9 @@ const createOverflowLifecycle = lifecycleHub => {
|
||||
_viewport,
|
||||
_viewportArrange
|
||||
} = _structureSetup._targetObj;
|
||||
const [updateViewportSizeFraction, getCurrentViewportSizeFraction] = createCache(sizeFraction.bind(0, _viewport), whCacheOptions);
|
||||
const [updateViewportScrollSizeCache, getCurrentViewportScrollSizeCache] = createCache(scrollSize.bind(0, _viewport), whCacheOptions);
|
||||
const [updateOverflowAmountCache, getCurrentOverflowAmountCache] = createCache(({
|
||||
_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 [updateViewportSizeFraction, getCurrentViewportSizeFraction] = createCache(whCacheOptions, sizeFraction.bind(0, _viewport));
|
||||
const [updateViewportScrollSizeCache, getCurrentViewportScrollSizeCache] = createCache(whCacheOptions, scrollSize.bind(0, _viewport));
|
||||
const [updateOverflowAmountCache, getCurrentOverflowAmountCache] = createCache(whCacheOptions);
|
||||
|
||||
const fixFlexboxGlue = (viewportOverflowState, heightIntrinsic) => {
|
||||
style(_viewport, {
|
||||
@@ -1998,9 +1992,13 @@ const createOverflowLifecycle = lifecycleHub => {
|
||||
x: styleObj.overflowX === 'scroll',
|
||||
y: styleObj.overflowY === 'scroll'
|
||||
};
|
||||
const nonScrollbarStylingHideOffset = {
|
||||
x: overlaidX ? arrangeHideOffset : _nativeScrollbarSize.x,
|
||||
y: overlaidY ? arrangeHideOffset : _nativeScrollbarSize.y
|
||||
};
|
||||
const scrollbarsHideOffset = {
|
||||
x: scroll.x && !_nativeScrollbarStyling ? overlaidX ? arrangeHideOffset : _nativeScrollbarSize.x : 0,
|
||||
y: scroll.y && !_nativeScrollbarStyling ? overlaidY ? arrangeHideOffset : _nativeScrollbarSize.y : 0
|
||||
x: scroll.x && !_nativeScrollbarStyling ? nonScrollbarStylingHideOffset.x : 0,
|
||||
y: scroll.y && !_nativeScrollbarStyling ? nonScrollbarStylingHideOffset.y : 0
|
||||
};
|
||||
return {
|
||||
_overflowScroll: scroll,
|
||||
@@ -2223,30 +2221,26 @@ const createOverflowLifecycle = lifecycleHub => {
|
||||
_redoViewportArrange,
|
||||
_viewportOverflowState: undoViewportArrangeOverflowState
|
||||
} = undoViewportArrange(showNativeOverlaidScrollbars, directionIsRTL, preMeasureViewportOverflowState);
|
||||
const [_viewportSizeFraction2, viewportSizeFractionCahnged] = viewportSizeFractionCache = updateViewportSizeFraction(force);
|
||||
const [_viewportScrollSize2, _viewportScrollSizeChanged] = viewportScrollSizeCache = updateViewportScrollSizeCache(force);
|
||||
const [_viewportSizeFraction, viewportSizeFractionCahnged] = viewportSizeFractionCache = updateViewportSizeFraction(force);
|
||||
const [_viewportScrollSize, _viewportScrollSizeChanged] = viewportScrollSizeCache = updateViewportScrollSizeCache(force);
|
||||
const viewportContentSize = clientSize(_viewport);
|
||||
let arrangedViewportScrollSize = _viewportScrollSize2;
|
||||
let arrangedViewportScrollSize = _viewportScrollSize;
|
||||
let arrangedViewportClientSize = viewportContentSize;
|
||||
|
||||
_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);
|
||||
arrangedViewportScrollSize = scrollSize(_viewport);
|
||||
}
|
||||
|
||||
overflowAmuntCache = updateOverflowAmountCache(force, {
|
||||
_viewportSizeFraction: _viewportSizeFraction2,
|
||||
_viewportScrollSize: {
|
||||
w: max(_viewportScrollSize2.w, arrangedViewportScrollSize.w),
|
||||
h: max(_viewportScrollSize2.h, arrangedViewportScrollSize.h)
|
||||
},
|
||||
_viewportClientSize: {
|
||||
w: arrangedViewportClientSize.w + max(0, viewportContentSize.w - _viewportScrollSize2.w),
|
||||
h: arrangedViewportClientSize.h + max(0, viewportContentSize.h - _viewportScrollSize2.h)
|
||||
}
|
||||
});
|
||||
overflowAmuntCache = updateOverflowAmountCache(getOverflowAmount({
|
||||
w: max(_viewportScrollSize.w, arrangedViewportScrollSize.w),
|
||||
h: max(_viewportScrollSize.h, arrangedViewportScrollSize.h)
|
||||
}, {
|
||||
w: arrangedViewportClientSize.w + max(0, viewportContentSize.w - _viewportScrollSize.w),
|
||||
h: arrangedViewportClientSize.h + max(0, viewportContentSize.h - _viewportScrollSize.h)
|
||||
}, _viewportSizeFraction), force);
|
||||
}
|
||||
|
||||
const [viewportSizeFraction, viewportSizeFractionChanged] = viewportSizeFractionCache;
|
||||
@@ -2400,9 +2394,9 @@ const createLifecycleHub = (options, structureSetup, scrollbarsSetup) => {
|
||||
_destroy: destroyObservers
|
||||
} = 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);
|
||||
console.log(getEnvironment());
|
||||
return {
|
||||
@@ -2451,7 +2445,7 @@ const OverlayScrollbars = (target, options, extensions) => {
|
||||
state: () => lifecycleHub._state(),
|
||||
|
||||
update(force) {
|
||||
lifecycleHub._update(null, force);
|
||||
lifecycleHub._update({}, force);
|
||||
},
|
||||
|
||||
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());
|
||||
})(this, (function () { 'use strict';
|
||||
|
||||
var createCache = function createCache(update, options) {
|
||||
var _ref = options || {},
|
||||
_initialValue = _ref._initialValue,
|
||||
_equal = _ref._equal,
|
||||
_alwaysUpdateValues = _ref._alwaysUpdateValues;
|
||||
|
||||
function createCache(options, update) {
|
||||
var _initialValue = options._initialValue,
|
||||
_equal = options._equal,
|
||||
_alwaysUpdateValues = options._alwaysUpdateValues;
|
||||
var _value = _initialValue;
|
||||
|
||||
var _previous;
|
||||
|
||||
var cacheUpdate = function cacheUpdate(force, context) {
|
||||
var cacheUpdateContextual = function cacheUpdateContextual(newValue, force) {
|
||||
var curr = _value;
|
||||
var newVal = update ? update(context, _value, _previous) : context;
|
||||
var newVal = newValue;
|
||||
var changed = force || (_equal ? !_equal(curr, newVal) : curr !== newVal);
|
||||
|
||||
if (changed || _alwaysUpdateValues) {
|
||||
@@ -27,10 +25,16 @@
|
||||
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 [update ? cacheUpdateIsolated : cacheUpdateContextual, getCurrentCache];
|
||||
}
|
||||
|
||||
var ElementNodeType = Node.ELEMENT_NODE;
|
||||
var _Object$prototype = Object.prototype,
|
||||
@@ -110,7 +114,7 @@
|
||||
return source;
|
||||
}
|
||||
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) {
|
||||
!arrayIsSingleItem && !isString(items) && isArrayLike(items) ? Array.prototype.push.apply(array, items) : array.push(items);
|
||||
@@ -128,7 +132,7 @@
|
||||
return result;
|
||||
};
|
||||
var isEmptyArray = function isEmptyArray(array) {
|
||||
return array && array.length === 0;
|
||||
return !!array && array.length === 0;
|
||||
};
|
||||
var runEach = function runEach(arr, p1) {
|
||||
var runFn = function runFn(fn) {
|
||||
@@ -529,8 +533,6 @@
|
||||
});
|
||||
};
|
||||
|
||||
var setT = window.setTimeout;
|
||||
|
||||
var clearTimeouts = function clearTimeouts(id) {
|
||||
id && window.clearTimeout(id);
|
||||
id && cAF(id);
|
||||
@@ -542,9 +544,13 @@
|
||||
var maxTimeoutId;
|
||||
var prevArguments;
|
||||
var latestArguments;
|
||||
var _timeout = options._timeout,
|
||||
_maxDelay = options._maxDelay,
|
||||
_mergeParams = options._mergeParams;
|
||||
|
||||
var _ref = options || {},
|
||||
_timeout = _ref._timeout,
|
||||
_maxDelay = _ref._maxDelay,
|
||||
_mergeParams = _ref._mergeParams;
|
||||
|
||||
var setT = window.setTimeout;
|
||||
|
||||
var invokeFunctionToDebounce = function invokeFunctionToDebounce(args) {
|
||||
clearTimeouts(timeoutId);
|
||||
@@ -564,7 +570,7 @@
|
||||
};
|
||||
|
||||
var debouncedFn = function debouncedFn() {
|
||||
var args = arguments;
|
||||
var args = from(arguments);
|
||||
var finalTimeout = isFunction(_timeout) ? _timeout() : _timeout;
|
||||
var hasTimeout = isNumber(finalTimeout) && finalTimeout >= 0;
|
||||
|
||||
@@ -575,11 +581,6 @@
|
||||
var mergeParamsResult = mergeParms(args);
|
||||
var invokedArgs = mergeParamsResult || args;
|
||||
var boundInvoke = invokeFunctionToDebounce.bind(0, invokedArgs);
|
||||
|
||||
if (!mergeParamsResult) {
|
||||
invokeFunctionToDebounce(prevArguments || args);
|
||||
}
|
||||
|
||||
clearTimeouts(timeoutId);
|
||||
timeoutId = setTimeoutFn(boundInvoke, finalTimeout);
|
||||
|
||||
@@ -618,12 +619,12 @@
|
||||
var setCSSVal = function setCSSVal(elm, prop, val) {
|
||||
try {
|
||||
if (elm) {
|
||||
var _style = elm.style;
|
||||
var elmStyle = elm.style;
|
||||
|
||||
if (!isUndefined(_style[prop])) {
|
||||
_style[prop] = adaptCSSVal(prop, val);
|
||||
if (!isUndefined(elmStyle[prop])) {
|
||||
elmStyle[prop] = adaptCSSVal(prop, val);
|
||||
} else {
|
||||
_style.setProperty(prop, val);
|
||||
elmStyle.setProperty(prop, val);
|
||||
}
|
||||
}
|
||||
} catch (e) {}
|
||||
@@ -1288,7 +1289,7 @@
|
||||
var listenerElement = sizeObserver.firstChild;
|
||||
var getIsDirectionRTL = getElmDirectionIsRTL.bind(0, sizeObserver);
|
||||
|
||||
var _createCache = createCache(0, {
|
||||
var _createCache = createCache({
|
||||
_initialValue: undefined,
|
||||
_alwaysUpdateValues: true,
|
||||
_equal: function _equal(currVal, newVal) {
|
||||
@@ -1305,7 +1306,7 @@
|
||||
var doDirectionScroll = true;
|
||||
|
||||
if (isResizeObserverCall) {
|
||||
var _updateResizeObserver = updateResizeObserverContentRectCache(0, sizeChangedContext.pop().contentRect),
|
||||
var _updateResizeObserver = updateResizeObserverContentRectCache(sizeChangedContext.pop().contentRect),
|
||||
currRContentRect = _updateResizeObserver[0],
|
||||
prevContentRect = _updateResizeObserver[2];
|
||||
|
||||
@@ -1402,9 +1403,9 @@
|
||||
}
|
||||
|
||||
if (observeDirectionChange) {
|
||||
directionIsRTLCache = createCache(getIsDirectionRTL, {
|
||||
directionIsRTLCache = createCache({
|
||||
_initialValue: !getIsDirectionRTL()
|
||||
});
|
||||
}, getIsDirectionRTL);
|
||||
var _directionIsRTLCache = directionIsRTLCache,
|
||||
updateDirectionIsRTLCache = _directionIsRTLCache[0];
|
||||
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 trinsicObserver = createDiv(classNameTrinsicObserver);
|
||||
var offListeners = [];
|
||||
|
||||
var _createCache = createCache(function (ioEntryOrSize) {
|
||||
return ioEntryOrSize.h === 0 || ioEntryOrSize.isIntersecting || ioEntryOrSize.intersectionRatio > 0;
|
||||
}, {
|
||||
var _createCache = createCache({
|
||||
_initialValue: false
|
||||
}),
|
||||
updateHeightIntrinsicCache = _createCache[0],
|
||||
@@ -1463,7 +1466,7 @@
|
||||
|
||||
var triggerOnTrinsicChangedCallback = function triggerOnTrinsicChangedCallback(updateValue) {
|
||||
if (updateValue) {
|
||||
var heightIntrinsic = updateHeightIntrinsicCache(0, updateValue);
|
||||
var heightIntrinsic = updateHeightIntrinsicCache(isHeightIntrinsic(updateValue));
|
||||
var heightIntrinsicChanged = heightIntrinsic[1];
|
||||
|
||||
if (heightIntrinsicChanged) {
|
||||
@@ -1889,10 +1892,10 @@
|
||||
_padding = _structureSetup$_targ._padding,
|
||||
_viewport = _structureSetup$_targ._viewport;
|
||||
|
||||
var _createCache = createCache(topRightBottomLeft.bind(0, _host, 'padding'), {
|
||||
var _createCache = createCache({
|
||||
_equal: equalTRBL,
|
||||
_initialValue: topRightBottomLeft()
|
||||
}),
|
||||
}, topRightBottomLeft.bind(0, _host, 'padding', '')),
|
||||
updatePaddingCache = _createCache[0],
|
||||
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 _structureSetup = lifecycleHub._structureSetup,
|
||||
_doViewportArrange = lifecycleHub._doViewportArrange,
|
||||
@@ -2019,23 +2029,15 @@
|
||||
_viewport = _structureSetup$_targ._viewport,
|
||||
_viewportArrange = _structureSetup$_targ._viewportArrange;
|
||||
|
||||
var _createCache = createCache(sizeFraction.bind(0, _viewport), whCacheOptions),
|
||||
var _createCache = createCache(whCacheOptions, sizeFraction.bind(0, _viewport)),
|
||||
updateViewportSizeFraction = _createCache[0],
|
||||
getCurrentViewportSizeFraction = _createCache[1];
|
||||
|
||||
var _createCache2 = createCache(scrollSize.bind(0, _viewport), whCacheOptions),
|
||||
var _createCache2 = createCache(whCacheOptions, scrollSize.bind(0, _viewport)),
|
||||
updateViewportScrollSizeCache = _createCache2[0],
|
||||
getCurrentViewportScrollSizeCache = _createCache2[1];
|
||||
|
||||
var _createCache3 = createCache(function (_ref) {
|
||||
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),
|
||||
var _createCache3 = createCache(whCacheOptions),
|
||||
updateOverflowAmountCache = _createCache3[0],
|
||||
getCurrentOverflowAmountCache = _createCache3[1];
|
||||
|
||||
@@ -2081,9 +2083,13 @@
|
||||
x: styleObj.overflowX === 'scroll',
|
||||
y: styleObj.overflowY === 'scroll'
|
||||
};
|
||||
var nonScrollbarStylingHideOffset = {
|
||||
x: overlaidX ? arrangeHideOffset : _nativeScrollbarSize.x,
|
||||
y: overlaidY ? arrangeHideOffset : _nativeScrollbarSize.y
|
||||
};
|
||||
var scrollbarsHideOffset = {
|
||||
x: scroll.x && !_nativeScrollbarStyling ? overlaidX ? arrangeHideOffset : _nativeScrollbarSize.x : 0,
|
||||
y: scroll.y && !_nativeScrollbarStyling ? overlaidY ? arrangeHideOffset : _nativeScrollbarSize.y : 0
|
||||
x: scroll.x && !_nativeScrollbarStyling ? nonScrollbarStylingHideOffset.x : 0,
|
||||
y: scroll.y && !_nativeScrollbarStyling ? nonScrollbarStylingHideOffset.y : 0
|
||||
};
|
||||
return {
|
||||
_overflowScroll: scroll,
|
||||
@@ -2289,41 +2295,37 @@
|
||||
_redoViewportArrange = _undoViewportArrange._redoViewportArrange,
|
||||
undoViewportArrangeOverflowState = _undoViewportArrange._viewportOverflowState;
|
||||
|
||||
var _viewportSizeFraction3 = viewportSizeFractionCache = updateViewportSizeFraction(force),
|
||||
_viewportSizeFraction2 = _viewportSizeFraction3[0],
|
||||
viewportSizeFractionCahnged = _viewportSizeFraction3[1];
|
||||
var _viewportSizeFraction2 = viewportSizeFractionCache = updateViewportSizeFraction(force),
|
||||
_viewportSizeFraction = _viewportSizeFraction2[0],
|
||||
viewportSizeFractionCahnged = _viewportSizeFraction2[1];
|
||||
|
||||
var _viewportScrollSizeCa = viewportScrollSizeCache = updateViewportScrollSizeCache(force),
|
||||
_viewportScrollSize2 = _viewportScrollSizeCa[0],
|
||||
_viewportScrollSize = _viewportScrollSizeCa[0],
|
||||
_viewportScrollSizeChanged = _viewportScrollSizeCa[1];
|
||||
|
||||
var viewportContentSize = clientSize(_viewport);
|
||||
var arrangedViewportScrollSize = _viewportScrollSize2;
|
||||
var arrangedViewportScrollSize = _viewportScrollSize;
|
||||
var arrangedViewportClientSize = viewportContentSize;
|
||||
|
||||
_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);
|
||||
arrangedViewportScrollSize = scrollSize(_viewport);
|
||||
}
|
||||
|
||||
overflowAmuntCache = updateOverflowAmountCache(force, {
|
||||
_viewportSizeFraction: _viewportSizeFraction2,
|
||||
_viewportScrollSize: {
|
||||
w: max(_viewportScrollSize2.w, arrangedViewportScrollSize.w),
|
||||
h: max(_viewportScrollSize2.h, arrangedViewportScrollSize.h)
|
||||
},
|
||||
_viewportClientSize: {
|
||||
w: arrangedViewportClientSize.w + max(0, viewportContentSize.w - _viewportScrollSize2.w),
|
||||
h: arrangedViewportClientSize.h + max(0, viewportContentSize.h - _viewportScrollSize2.h)
|
||||
}
|
||||
});
|
||||
overflowAmuntCache = updateOverflowAmountCache(getOverflowAmount({
|
||||
w: max(_viewportScrollSize.w, arrangedViewportScrollSize.w),
|
||||
h: max(_viewportScrollSize.h, arrangedViewportScrollSize.h)
|
||||
}, {
|
||||
w: arrangedViewportClientSize.w + max(0, viewportContentSize.w - _viewportScrollSize.w),
|
||||
h: arrangedViewportClientSize.h + max(0, viewportContentSize.h - _viewportScrollSize.h)
|
||||
}, _viewportSizeFraction), force);
|
||||
}
|
||||
|
||||
var _viewportSizeFraction4 = viewportSizeFractionCache,
|
||||
viewportSizeFraction = _viewportSizeFraction4[0],
|
||||
viewportSizeFractionChanged = _viewportSizeFraction4[1];
|
||||
var _viewportSizeFraction3 = viewportSizeFractionCache,
|
||||
viewportSizeFraction = _viewportSizeFraction3[0],
|
||||
viewportSizeFractionChanged = _viewportSizeFraction3[1];
|
||||
var _viewportScrollSizeCa2 = viewportScrollSizeCache,
|
||||
viewportScrollSize = _viewportScrollSizeCa2[0],
|
||||
viewportScrollSizeChanged = _viewportScrollSizeCa2[1];
|
||||
@@ -2490,10 +2492,10 @@
|
||||
destroyObservers = _lifecycleHubOservers._destroy;
|
||||
|
||||
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);
|
||||
console.log(getEnvironment());
|
||||
return {
|
||||
@@ -2541,7 +2543,7 @@
|
||||
return lifecycleHub._state();
|
||||
},
|
||||
update: function update(force) {
|
||||
lifecycleHub._update(null, force);
|
||||
lifecycleHub._update({}, force);
|
||||
},
|
||||
destroy: function 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 = () => {
|
||||
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(),
|
||||
_equal: (currTime, newTime) => {
|
||||
const delta = newTime! - currTime!;
|
||||
@@ -34,9 +34,9 @@ const createAutoUpdateLoop = (): AutoUpdateLoop => {
|
||||
/* istanbul ignore next */
|
||||
if (!isEmptyArray(loopFunctions) && loopIsRunning) {
|
||||
loopId = rAF!(loop);
|
||||
const { _changed, _value, _previous } = updateTimeCache(0, newTime);
|
||||
if (_changed) {
|
||||
runEach(loopFunctions, _value! - _previous!);
|
||||
const [value, changed, previous] = updateTimeCache(newTime || performance.now());
|
||||
if (changed) {
|
||||
runEach(loopFunctions, value - previous!);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -60,9 +60,9 @@ const createAutoUpdateLoop = (): AutoUpdateLoop => {
|
||||
push(loopFunctions, fn);
|
||||
|
||||
if (!loopIsRunning && !isEmptyArray(loopFunctions)) {
|
||||
//getEnvironment()._autoUpdateLoop = loopIsRunning = true;
|
||||
// getEnvironment()._autoUpdateLoop = loopIsRunning = true;
|
||||
|
||||
updateTimeCache(true);
|
||||
updateTimeCache(performance.now(), true);
|
||||
loop();
|
||||
}
|
||||
|
||||
@@ -70,7 +70,7 @@ const createAutoUpdateLoop = (): AutoUpdateLoop => {
|
||||
loopFunctions.splice(indexOf(loopFunctions, fn), 1);
|
||||
|
||||
if (isEmptyArray(loopFunctions) && loopIsRunning) {
|
||||
//getEnvironment()._autoUpdateLoop = loopIsRunning = false;
|
||||
// getEnvironment()._autoUpdateLoop = loopIsRunning = false;
|
||||
|
||||
cAF!(loopId!);
|
||||
loopId = undefined;
|
||||
|
||||
@@ -58,7 +58,7 @@ export interface LifecycleHubState {
|
||||
}
|
||||
|
||||
export interface LifecycleHubInstance {
|
||||
_update(changedOptions?: PartialOptions<OSOptions> | null, force?: boolean): void;
|
||||
_update(changedOptions: PartialOptions<OSOptions>, force?: boolean): void;
|
||||
_state(): LifecycleHubState;
|
||||
_destroy(): void;
|
||||
}
|
||||
@@ -139,8 +139,8 @@ export const createLifecycleHub = (
|
||||
];
|
||||
|
||||
const updateLifecycles = (
|
||||
updateHints?: Partial<LifecycleUpdateHints> | null,
|
||||
changedOptions?: Partial<OSOptions> | null,
|
||||
updateHints: Partial<LifecycleUpdateHints>,
|
||||
changedOptions?: Partial<OSOptions>,
|
||||
force?: boolean
|
||||
) => {
|
||||
let {
|
||||
@@ -221,9 +221,9 @@ export const createLifecycleHub = (
|
||||
_destroy: destroyObservers,
|
||||
} = lifecycleHubOservers(instance, updateLifecycles);
|
||||
|
||||
const update = (changedOptions?: Partial<OSOptions> | null, force?: boolean) =>
|
||||
updateLifecycles(null, changedOptions, force);
|
||||
const envUpdateListener = update.bind(null, null, true);
|
||||
const update = (changedOptions: Partial<OSOptions>, force?: boolean) =>
|
||||
updateLifecycles({}, changedOptions, force);
|
||||
const envUpdateListener = update.bind(0, {}, true);
|
||||
addEnvironmentListener(envUpdateListener);
|
||||
|
||||
console.log(getEnvironment());
|
||||
|
||||
@@ -44,7 +44,7 @@ const ignoreTargetChange = (
|
||||
|
||||
export const lifecycleHubOservers = (
|
||||
instance: LifecycleHub,
|
||||
updateLifecycles: (updateHints?: Partial<LifecycleUpdateHints> | null) => unknown
|
||||
updateLifecycles: (updateHints: Partial<LifecycleUpdateHints>) => unknown
|
||||
) => {
|
||||
let debounceTimeout: number | false | undefined;
|
||||
let debounceMaxDelay: number | false | undefined;
|
||||
@@ -57,34 +57,31 @@ export const lifecycleHubOservers = (
|
||||
const contentMutationObserverAttr = _isTextarea
|
||||
? baseStyleChangingAttrsTextarea
|
||||
: baseStyleChangingAttrs.concat(baseStyleChangingAttrsTextarea);
|
||||
const updateLifecyclesWithDebouncedAdaptiveUpdateHints = debounce(
|
||||
updateLifecycles as (updateHints: Partial<LifecycleUpdateHints>) => any,
|
||||
{
|
||||
_timeout: () => debounceTimeout,
|
||||
_maxDelay: () => debounceMaxDelay,
|
||||
_mergeParams(prev, curr) {
|
||||
const {
|
||||
_sizeChanged: prevSizeChanged,
|
||||
_hostMutation: prevHostMutation,
|
||||
_contentMutation: prevContentMutation,
|
||||
} = prev[0];
|
||||
const {
|
||||
_sizeChanged: currSizeChanged,
|
||||
_hostMutation: currvHostMutation,
|
||||
_contentMutation: currContentMutation,
|
||||
} = curr[0];
|
||||
const merged: [Partial<LifecycleUpdateHints>] = [
|
||||
{
|
||||
_sizeChanged: prevSizeChanged || currSizeChanged,
|
||||
_hostMutation: prevHostMutation || currvHostMutation,
|
||||
_contentMutation: prevContentMutation || currContentMutation,
|
||||
},
|
||||
];
|
||||
const updateLifecyclesWithDebouncedAdaptiveUpdateHints = debounce(updateLifecycles, {
|
||||
_timeout: () => debounceTimeout,
|
||||
_maxDelay: () => debounceMaxDelay,
|
||||
_mergeParams(prev, curr) {
|
||||
const {
|
||||
_sizeChanged: prevSizeChanged,
|
||||
_hostMutation: prevHostMutation,
|
||||
_contentMutation: prevContentMutation,
|
||||
} = prev[0];
|
||||
const {
|
||||
_sizeChanged: currSizeChanged,
|
||||
_hostMutation: currvHostMutation,
|
||||
_contentMutation: currContentMutation,
|
||||
} = curr[0];
|
||||
const merged: [Partial<LifecycleUpdateHints>] = [
|
||||
{
|
||||
_sizeChanged: prevSizeChanged || currSizeChanged,
|
||||
_hostMutation: prevHostMutation || currvHostMutation,
|
||||
_contentMutation: prevContentMutation || currContentMutation,
|
||||
},
|
||||
];
|
||||
|
||||
return merged;
|
||||
},
|
||||
}
|
||||
);
|
||||
return merged;
|
||||
},
|
||||
});
|
||||
|
||||
const updateViewportAttrsFromHost = (attributes?: string[]) => {
|
||||
each(attributes || viewportAttrsFromTarget, (attribute) => {
|
||||
|
||||
@@ -22,12 +22,6 @@ import { OverflowBehavior } from 'options';
|
||||
import { StyleObject } from 'typings';
|
||||
import { classNameViewportArrange, classNameViewportScrollbarStyling } from 'classnames';
|
||||
|
||||
interface OverflowAmountCacheContext {
|
||||
_viewportScrollSize: WH<number>;
|
||||
_viewportClientSize: WH<number>;
|
||||
_viewportSizeFraction: WH<number>;
|
||||
}
|
||||
|
||||
interface ViewportOverflowState {
|
||||
_scrollbarsHideOffset: XY<number>;
|
||||
_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.
|
||||
* @param lifecycleHub
|
||||
@@ -100,34 +115,15 @@ export const createOverflowLifecycle = (lifecycleHub: LifecycleHub): Lifecycle =
|
||||
const { _host, _viewport, _viewportArrange } = _structureSetup._targetObj;
|
||||
|
||||
const [updateViewportSizeFraction, getCurrentViewportSizeFraction] = createCache<WH<number>>(
|
||||
sizeFraction.bind(0, _viewport),
|
||||
whCacheOptions
|
||||
whCacheOptions,
|
||||
sizeFraction.bind(0, _viewport)
|
||||
);
|
||||
|
||||
const [updateViewportScrollSizeCache, getCurrentViewportScrollSizeCache] = createCache<
|
||||
WH<number>
|
||||
>(scrollSize.bind(0, _viewport), whCacheOptions);
|
||||
>(whCacheOptions, scrollSize.bind(0, _viewport));
|
||||
|
||||
const [updateOverflowAmountCache, getCurrentOverflowAmountCache] = createCache<
|
||||
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))
|
||||
)
|
||||
),
|
||||
}),
|
||||
const [updateOverflowAmountCache, getCurrentOverflowAmountCache] = createCache<WH<number>>(
|
||||
whCacheOptions
|
||||
);
|
||||
|
||||
@@ -195,19 +191,13 @@ export const createOverflowLifecycle = (lifecycleHub: LifecycleHub): Lifecycle =
|
||||
x: styleObj.overflowX === 'scroll',
|
||||
y: styleObj.overflowY === 'scroll',
|
||||
};
|
||||
const nonScrollbarStylingHideOffset = {
|
||||
x: overlaidX ? arrangeHideOffset : _nativeScrollbarSize.x,
|
||||
y: overlaidY ? arrangeHideOffset : _nativeScrollbarSize.y,
|
||||
};
|
||||
const scrollbarsHideOffset = {
|
||||
x:
|
||||
scroll.x && !_nativeScrollbarStyling
|
||||
? overlaidX
|
||||
? arrangeHideOffset
|
||||
: _nativeScrollbarSize.x
|
||||
: 0,
|
||||
y:
|
||||
scroll.y && !_nativeScrollbarStyling
|
||||
? overlaidY
|
||||
? arrangeHideOffset
|
||||
: _nativeScrollbarSize.y
|
||||
: 0,
|
||||
x: scroll.x && !_nativeScrollbarStyling ? nonScrollbarStylingHideOffset.x : 0,
|
||||
y: scroll.y && !_nativeScrollbarStyling ? nonScrollbarStylingHideOffset.y : 0,
|
||||
};
|
||||
|
||||
return {
|
||||
@@ -486,7 +476,7 @@ export const createOverflowLifecycle = (lifecycleHub: LifecycleHub): Lifecycle =
|
||||
_viewportOverflowState: undoViewportArrangeOverflowState,
|
||||
} = undoViewportArrange(
|
||||
showNativeOverlaidScrollbars,
|
||||
directionIsRTL!,
|
||||
directionIsRTL,
|
||||
preMeasureViewportOverflowState
|
||||
);
|
||||
const [
|
||||
@@ -498,7 +488,7 @@ export const createOverflowLifecycle = (lifecycleHub: LifecycleHub): Lifecycle =
|
||||
viewportScrollSizeChanged,
|
||||
] = (viewportScrollSizeCache = updateViewportScrollSizeCache(force));
|
||||
const viewportContentSize = clientSize(_viewport);
|
||||
let arrangedViewportScrollSize = viewportScrollSize!;
|
||||
let arrangedViewportScrollSize = viewportScrollSize;
|
||||
let arrangedViewportClientSize = viewportContentSize;
|
||||
|
||||
_redoViewportArrange();
|
||||
@@ -512,26 +502,29 @@ export const createOverflowLifecycle = (lifecycleHub: LifecycleHub): Lifecycle =
|
||||
!showNativeOverlaidScrollbars &&
|
||||
arrangeViewport(
|
||||
undoViewportArrangeOverflowState,
|
||||
viewportScrollSize!,
|
||||
viewportSizeFraction!,
|
||||
directionIsRTL!
|
||||
viewportScrollSize,
|
||||
viewportSizeFraction,
|
||||
directionIsRTL
|
||||
)
|
||||
) {
|
||||
arrangedViewportClientSize = clientSize(_viewport);
|
||||
arrangedViewportScrollSize = scrollSize(_viewport);
|
||||
}
|
||||
|
||||
overflowAmuntCache = updateOverflowAmountCache(force, {
|
||||
_viewportSizeFraction: viewportSizeFraction!,
|
||||
_viewportScrollSize: {
|
||||
w: max(viewportScrollSize.w, arrangedViewportScrollSize.w),
|
||||
h: max(viewportScrollSize.h, arrangedViewportScrollSize.h),
|
||||
},
|
||||
_viewportClientSize: {
|
||||
w: arrangedViewportClientSize.w + max(0, viewportContentSize.w - viewportScrollSize.w),
|
||||
h: arrangedViewportClientSize.h + max(0, viewportContentSize.h - viewportScrollSize.h),
|
||||
},
|
||||
});
|
||||
overflowAmuntCache = updateOverflowAmountCache(
|
||||
getOverflowAmount(
|
||||
{
|
||||
w: max(viewportScrollSize.w, arrangedViewportScrollSize.w),
|
||||
h: max(viewportScrollSize.h, arrangedViewportScrollSize.h),
|
||||
}, // scroll size
|
||||
{
|
||||
w: arrangedViewportClientSize.w + max(0, viewportContentSize.w - viewportScrollSize.w),
|
||||
h: arrangedViewportClientSize.h + max(0, viewportContentSize.h - viewportScrollSize.h),
|
||||
}, // client size
|
||||
viewportSizeFraction
|
||||
),
|
||||
force
|
||||
);
|
||||
}
|
||||
|
||||
const [viewportSizeFraction, viewportSizeFractionChanged] = viewportSizeFractionCache;
|
||||
@@ -560,17 +553,17 @@ export const createOverflowLifecycle = (lifecycleHub: LifecycleHub): Lifecycle =
|
||||
|
||||
const viewportOverflowState = setViewportOverflowState(
|
||||
showNativeOverlaidScrollbars,
|
||||
overflowAmount!,
|
||||
overflowAmount,
|
||||
overflow,
|
||||
viewportStyle
|
||||
);
|
||||
const viewportArranged = arrangeViewport(
|
||||
viewportOverflowState,
|
||||
viewportScrollSize!,
|
||||
viewportSizeFraction!,
|
||||
directionIsRTL!
|
||||
viewportScrollSize,
|
||||
viewportSizeFraction,
|
||||
directionIsRTL
|
||||
);
|
||||
hideNativeScrollbars(viewportOverflowState, directionIsRTL!, viewportArranged, viewportStyle);
|
||||
hideNativeScrollbars(viewportOverflowState, directionIsRTL, viewportArranged, viewportStyle);
|
||||
|
||||
if (adjustFlexboxGlue) {
|
||||
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 { StyleObject } from 'typings';
|
||||
import { getEnvironment } from 'environment';
|
||||
@@ -11,12 +11,12 @@ import { getEnvironment } from 'environment';
|
||||
export const createPaddingLifecycle = (lifecycleHub: LifecycleHub): Lifecycle => {
|
||||
const { _structureSetup, _setLifecycleCommunication } = lifecycleHub;
|
||||
const { _host, _padding, _viewport } = _structureSetup._targetObj;
|
||||
const [updatePaddingCache, currentPaddingCache] = createCache<TRBL>(
|
||||
topRightBottomLeft.bind(0, _host, 'padding'),
|
||||
const [updatePaddingCache, currentPaddingCache] = createCache(
|
||||
{
|
||||
_equal: equalTRBL,
|
||||
_initialValue: topRightBottomLeft(),
|
||||
}
|
||||
},
|
||||
topRightBottomLeft.bind(0, _host, 'padding', '')
|
||||
);
|
||||
|
||||
return (updateHints, checkOption, force) => {
|
||||
@@ -62,7 +62,7 @@ export const createPaddingLifecycle = (lifecycleHub: LifecycleHub): Lifecycle =>
|
||||
_setLifecycleCommunication({
|
||||
_paddingInfo: {
|
||||
_absolute: !paddingRelative,
|
||||
_padding: padding!,
|
||||
_padding: padding,
|
||||
},
|
||||
_viewportPaddingStyle: _padding
|
||||
? 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;
|
||||
|
||||
@@ -22,7 +35,11 @@ interface DOMTargetObserverOptions extends DOMObserverOptionsBase {
|
||||
|
||||
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 = (
|
||||
mutation: MutationRecord,
|
||||
@@ -42,7 +59,9 @@ export type DOMObserverCallback<ContentObserver extends boolean> = ContentObserv
|
||||
? DOMContentObserverCallback
|
||||
: 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 {
|
||||
_destroy: () => void;
|
||||
@@ -56,7 +75,11 @@ export interface DOMObserver {
|
||||
* @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.
|
||||
*/
|
||||
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 destroyed = false;
|
||||
const _destroy = () => {
|
||||
@@ -68,7 +91,10 @@ const createEventContentChange = (target: Element, callback: (...args: any) => a
|
||||
if (item) {
|
||||
const selector = item[0];
|
||||
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)) {
|
||||
push(arr, [elements, eventNames.trim()], true);
|
||||
@@ -141,7 +167,10 @@ export const createDOMObserver = <ContentObserver extends boolean>(
|
||||
_ignoreNestedTargetChange,
|
||||
_ignoreContentChange,
|
||||
} = (options as DOMContentObserverOptions & DOMTargetObserverOptions) || {};
|
||||
const { _destroy: destroyEventContentChange, _updateElements: updateEventContentChangeElements } = createEventContentChange(
|
||||
const {
|
||||
_destroy: destroyEventContentChange,
|
||||
_updateElements: updateEventContentChangeElements,
|
||||
} = createEventContentChange(
|
||||
target,
|
||||
debounce(
|
||||
() => {
|
||||
@@ -159,7 +188,8 @@ export const createDOMObserver = <ContentObserver extends boolean>(
|
||||
const finalStyleChangingAttributes = _styleChangingAttributes || [];
|
||||
const observedAttributes = finalAttributes.concat(finalStyleChangingAttributes);
|
||||
const observerCallback = (mutations: MutationRecord[]) => {
|
||||
const ignoreTargetChange = (isContentObserver ? _ignoreNestedTargetChange : _ignoreTargetChange) || noop;
|
||||
const ignoreTargetChange =
|
||||
(isContentObserver ? _ignoreNestedTargetChange : _ignoreTargetChange) || noop;
|
||||
const ignoreContentChange = _ignoreContentChange || noop;
|
||||
const targetChangedAttrs: string[] = [];
|
||||
const totalAddedNodes: Node[] = [];
|
||||
@@ -171,19 +201,25 @@ export const createDOMObserver = <ContentObserver extends boolean>(
|
||||
const isAttributesType = type === 'attributes';
|
||||
const isChildListType = type === 'childList';
|
||||
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 styleChangingAttrChanged = indexOf(finalStyleChangingAttributes, attributeName) > -1 && attributeChanged;
|
||||
const styleChangingAttrChanged =
|
||||
indexOf(finalStyleChangingAttributes, attributeName) > -1 && attributeChanged;
|
||||
|
||||
// if is content observer and something changed in children
|
||||
if (isContentObserver && !targetIsMutationTarget) {
|
||||
const notOnlyAttrChanged = !isAttributesType;
|
||||
const contentAttrChanged = isAttributesType && styleChangingAttrChanged;
|
||||
const isNestedTarget = contentAttrChanged && _nestedTargetSelector && is(mutationTarget, _nestedTargetSelector);
|
||||
const isNestedTarget =
|
||||
contentAttrChanged && _nestedTargetSelector && is(mutationTarget, _nestedTargetSelector);
|
||||
const baseAssertion = isNestedTarget
|
||||
? !ignoreTargetChange(mutationTarget, attributeName!, oldValue, attributeValue as string | null)
|
||||
? !ignoreTargetChange(mutationTarget, attributeName!, oldValue, attributeValue)
|
||||
: notOnlyAttrChanged || contentAttrChanged;
|
||||
const contentFinalChanged = baseAssertion && !ignoreContentChange(mutation, !!isNestedTarget, target, options);
|
||||
const contentFinalChanged =
|
||||
baseAssertion && !ignoreContentChange(mutation, !!isNestedTarget, target, options);
|
||||
|
||||
push(totalAddedNodes, addedNodes);
|
||||
|
||||
@@ -195,7 +231,7 @@ export const createDOMObserver = <ContentObserver extends boolean>(
|
||||
!isContentObserver &&
|
||||
targetIsMutationTarget &&
|
||||
attributeChanged &&
|
||||
!ignoreTargetChange(mutationTarget, attributeName!, oldValue, attributeValue as string | null)
|
||||
!ignoreTargetChange(mutationTarget, attributeName!, oldValue, attributeValue)
|
||||
) {
|
||||
push(targetChangedAttrs, attributeName!);
|
||||
targetStyleChanged = targetStyleChanged || styleChangingAttrChanged;
|
||||
|
||||
@@ -81,10 +81,7 @@ export const createSizeObserver = (
|
||||
const sizeObserver = baseElements[0] as HTMLElement;
|
||||
const listenerElement = sizeObserver.firstChild as HTMLElement;
|
||||
const getIsDirectionRTL = getElmDirectionIsRTL.bind(0, sizeObserver);
|
||||
const [updateResizeObserverContentRectCache] = createCache<
|
||||
DOMRectReadOnly | undefined,
|
||||
DOMRectReadOnly
|
||||
>(0, {
|
||||
const [updateResizeObserverContentRectCache] = createCache<DOMRectReadOnly | undefined>({
|
||||
_initialValue: undefined,
|
||||
_alwaysUpdateValues: true,
|
||||
_equal: (currVal, newVal) =>
|
||||
@@ -112,7 +109,6 @@ export const createSizeObserver = (
|
||||
// if triggered from RO.
|
||||
if (isResizeObserverCall) {
|
||||
const [currRContentRect, , prevContentRect] = updateResizeObserverContentRectCache(
|
||||
0,
|
||||
(sizeChangedContext as ResizeObserverEntry[]).pop()!.contentRect
|
||||
);
|
||||
const hasDimensions = domRectHasDimensions(currRContentRect);
|
||||
@@ -234,9 +230,12 @@ export const createSizeObserver = (
|
||||
}
|
||||
|
||||
if (observeDirectionChange) {
|
||||
directionIsRTLCache = createCache(getIsDirectionRTL, {
|
||||
_initialValue: !getIsDirectionRTL(), // invert current value to trigger initial change
|
||||
});
|
||||
directionIsRTLCache = createCache(
|
||||
{
|
||||
_initialValue: !getIsDirectionRTL(), // invert current value to trigger initial change
|
||||
},
|
||||
getIsDirectionRTL
|
||||
);
|
||||
const [updateDirectionIsRTLCache] = directionIsRTLCache;
|
||||
|
||||
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.
|
||||
* @param target The element which shall be observed.
|
||||
@@ -34,24 +39,15 @@ export const createTrinsicObserver = (
|
||||
): TrinsicObserver => {
|
||||
const trinsicObserver = createDiv(classNameTrinsicObserver);
|
||||
const offListeners: (() => void)[] = [];
|
||||
const [updateHeightIntrinsicCache, getCurrentHeightIntrinsicCache] = createCache<
|
||||
boolean,
|
||||
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 [updateHeightIntrinsicCache, getCurrentHeightIntrinsicCache] = createCache({
|
||||
_initialValue: false,
|
||||
});
|
||||
|
||||
const triggerOnTrinsicChangedCallback = (
|
||||
updateValue?: IntersectionObserverEntry | WH<number>
|
||||
) => {
|
||||
if (updateValue) {
|
||||
const heightIntrinsic = updateHeightIntrinsicCache(0, updateValue);
|
||||
const heightIntrinsic = updateHeightIntrinsicCache(isHeightIntrinsic(updateValue));
|
||||
const [, heightIntrinsicChanged] = heightIntrinsic;
|
||||
|
||||
if (heightIntrinsicChanged) {
|
||||
|
||||
@@ -59,7 +59,7 @@ export const OverlayScrollbars: OverlayScrollbarsStatic = (
|
||||
},
|
||||
state: () => lifecycleHub._state(),
|
||||
update(force?: boolean) {
|
||||
lifecycleHub._update(null, force);
|
||||
lifecycleHub._update({}, force);
|
||||
},
|
||||
destroy: () => lifecycleHub._destroy(),
|
||||
};
|
||||
|
||||
+44
-41
@@ -1,49 +1,49 @@
|
||||
export type CacheValues<T> = [
|
||||
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> {
|
||||
export interface CacheOptions<Value> {
|
||||
// initial value of _value.
|
||||
_initialValue: T;
|
||||
_initialValue: Value;
|
||||
// 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.
|
||||
_alwaysUpdateValues?: boolean;
|
||||
}
|
||||
|
||||
export type CacheUpdate<T, C> = undefined extends C
|
||||
? (force?: boolean | 0, context?: C) => CacheValues<T>
|
||||
: (force: boolean | 0, context: C) => CacheValues<T>;
|
||||
export type CacheValues<T> = [
|
||||
T, // value
|
||||
boolean, // changed
|
||||
T? // previous
|
||||
];
|
||||
|
||||
export type UpdateCachePropFunction<Value, Ctx> = undefined extends Ctx
|
||||
? (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<Value> = (currentVal: Value, newVal: Value) => boolean;
|
||||
|
||||
export type EqualCachePropFunction<T> = (currentVal?: T, newVal?: T) => boolean;
|
||||
export type CacheUpdater<Value> = (current: Value, previous?: Value) => Value;
|
||||
|
||||
export const createCache = <Value, Ctx = undefined>(
|
||||
update: UpdateCachePropFunction<Value, Ctx>,
|
||||
options: CacheOptions<Value>
|
||||
): Cache<Value, Ctx> => {
|
||||
export type UpdateCacheContextual<Value> = (newValue: Value, force?: boolean) => CacheValues<Value>;
|
||||
|
||||
export type UpdateCache<Value> = (force?: boolean) => CacheValues<Value>;
|
||||
|
||||
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;
|
||||
let _value: Value = _initialValue;
|
||||
let _previous: Value | undefined;
|
||||
|
||||
const cacheUpdate = ((force?: boolean | 0, context?: Ctx) => {
|
||||
const cacheUpdateContextual: UpdateCacheContextual<Value> = (newValue, force?) => {
|
||||
const curr = _value;
|
||||
// @ts-ignore
|
||||
// update can only not be a function if C extends T as described in "UpdateCachePropFunction" type definition
|
||||
// if C extends T the cast (context as T) is perfectly valid
|
||||
const newVal = update ? update(context, _value, _previous) : (context as T);
|
||||
|
||||
const newVal = newValue;
|
||||
const changed = force || (_equal ? !_equal(curr, newVal) : curr !== newVal);
|
||||
|
||||
if (changed || _alwaysUpdateValues) {
|
||||
@@ -52,14 +52,17 @@ export const createCache = <Value, Ctx = undefined>(
|
||||
}
|
||||
|
||||
return [_value, changed, _previous];
|
||||
}) as CacheUpdate<Value, Ctx>;
|
||||
};
|
||||
const cacheUpdateIsolated: UpdateCache<Value> = (force?) =>
|
||||
cacheUpdateContextual(update!(_value, _previous), force);
|
||||
|
||||
return [
|
||||
cacheUpdate,
|
||||
(force?: boolean) => [
|
||||
_value,
|
||||
!!force, // changed
|
||||
_previous,
|
||||
],
|
||||
const getCurrentCache: GetCurrentCache<Value> = (force?: boolean) => [
|
||||
_value,
|
||||
!!force, // changed
|
||||
_previous,
|
||||
];
|
||||
};
|
||||
|
||||
return [update ? cacheUpdateIsolated : cacheUpdateContextual, getCurrentCache] as
|
||||
| CacheContextual<Value>
|
||||
| Cache<Value>;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
import { jsAPI } from 'support/compatibility/vendors';
|
||||
|
||||
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 cAF = jsAPI<typeof cancelAnimationFrame>('cancelAnimationFrame');
|
||||
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, 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)) {
|
||||
return elm ? elm.getAttribute(attrName) : null;
|
||||
}
|
||||
|
||||
@@ -53,7 +53,10 @@ export const removeClass = (elm: Element | false | null | undefined, className:
|
||||
* @param classNameA ClassName A.
|
||||
* @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 classNameBSplit = classNameB && classNameB.split(' ');
|
||||
const tempObj = {};
|
||||
|
||||
@@ -3,7 +3,8 @@ export interface WH<T = number> {
|
||||
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 = {
|
||||
w: 0,
|
||||
h: 0,
|
||||
@@ -63,4 +64,5 @@ export const getBoundingClientRect = (elm: HTMLElement): DOMRect => elm.getBound
|
||||
* Determines whether the passed element has any dimensions.
|
||||
* @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 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) => {
|
||||
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.
|
||||
* @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 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) {
|
||||
let anchor: Node | null | undefined = preferredAnchor;
|
||||
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 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);
|
||||
};
|
||||
|
||||
|
||||
@@ -10,19 +10,19 @@ export interface TRBL {
|
||||
}
|
||||
|
||||
const cssNumber = {
|
||||
//animationiterationcount: 1,
|
||||
//columncount: 1,
|
||||
//fillopacity: 1,
|
||||
//flexgrow: 1,
|
||||
//flexshrink: 1,
|
||||
//fontweight: 1,
|
||||
//lineheight: 1,
|
||||
// animationiterationcount: 1,
|
||||
// columncount: 1,
|
||||
// fillopacity: 1,
|
||||
// flexgrow: 1,
|
||||
// flexshrink: 1,
|
||||
// fontweight: 1,
|
||||
// lineheight: 1,
|
||||
// order: 1,
|
||||
// orphans: 1,
|
||||
// widows: 1,
|
||||
// zoom: 1,
|
||||
opacity: 1,
|
||||
//order: 1,
|
||||
//orphans: 1,
|
||||
//widows: 1,
|
||||
zindex: 1,
|
||||
//zoom: 1,
|
||||
};
|
||||
|
||||
const parseToZeroOrNumber = (value: string, toFloat?: boolean): number => {
|
||||
@@ -31,18 +31,25 @@ const parseToZeroOrNumber = (value: string, toFloat?: boolean): number => {
|
||||
/* istanbul ignore next */
|
||||
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 =>
|
||||
/* istanbul ignore next */
|
||||
computedStyle != null ? computedStyle[prop] || computedStyle.getPropertyValue(prop) : elm.style[prop];
|
||||
const setCSSVal = (elm: HTMLElement | false | null | undefined, prop: string, val: string | number): void => {
|
||||
computedStyle != null
|
||||
? computedStyle[prop] || computedStyle.getPropertyValue(prop)
|
||||
: elm.style[prop];
|
||||
const setCSSVal = (
|
||||
elm: HTMLElement | false | null | undefined,
|
||||
prop: string,
|
||||
val: string | number
|
||||
): void => {
|
||||
try {
|
||||
if (elm) {
|
||||
const { style } = elm;
|
||||
if (!isUndefined(style[prop])) {
|
||||
style[prop] = adaptCSSVal(prop, val);
|
||||
const { style: elmStyle } = elm;
|
||||
if (!isUndefined(elmStyle[prop])) {
|
||||
elmStyle[prop] = adaptCSSVal(prop, val);
|
||||
} else {
|
||||
style.setProperty(prop, val as string);
|
||||
elmStyle.setProperty(prop, val as string);
|
||||
}
|
||||
}
|
||||
} 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 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>(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>(
|
||||
elm: HTMLElement | false | null | undefined,
|
||||
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>(
|
||||
elm: HTMLElement | false | null | undefined,
|
||||
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 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 finalSuffix = propertySuffix ? `-${propertySuffix}` : '';
|
||||
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.
|
||||
* @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.
|
||||
@@ -97,7 +98,11 @@ const closest = (elm: InputElementType, selector: string): OutputElementType =>
|
||||
* @param highBoundarySelector The high 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 closestDeepBoundaryElm = elm && findFirst(deepBoundarySelector, closestHighBoundaryElm);
|
||||
|
||||
|
||||
@@ -14,7 +14,10 @@ export interface OptionsWithOptionsTemplateTransformation<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> = {
|
||||
[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 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 = {
|
||||
_template: {},
|
||||
_options: {},
|
||||
};
|
||||
|
||||
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)) {
|
||||
result._template[key] = val[1];
|
||||
|
||||
@@ -1,10 +1,21 @@
|
||||
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';
|
||||
|
||||
export type OptionsObjectType = Record<string, 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 OptionsTemplateNativeTypes = OptionsTemplateTypeMap[keyof OptionsTemplateTypeMap];
|
||||
|
||||
@@ -71,13 +82,18 @@ const templateTypePrefixSuffix: readonly [string, string] = ['__TPL_', '_TYPE__'
|
||||
* Key = normal type string
|
||||
* value = template type string
|
||||
*/
|
||||
const optionsTemplateTypes: OptionsTemplateTypesDictionary = ['boolean', 'number', 'string', 'array', 'object', 'function', 'null'].reduce(
|
||||
(result, item) => {
|
||||
result[item] = templateTypePrefixSuffix[0] + item + templateTypePrefixSuffix[1];
|
||||
return result;
|
||||
},
|
||||
{} as OptionsTemplateTypesDictionary
|
||||
);
|
||||
const optionsTemplateTypes: OptionsTemplateTypesDictionary = [
|
||||
'boolean',
|
||||
'number',
|
||||
'string',
|
||||
'array',
|
||||
'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:
|
||||
@@ -111,13 +127,20 @@ const validateRecursive = <T extends PlainObject>(
|
||||
each(props, (prop: Extract<keyof T, string>) => {
|
||||
const optionsDiffValue: any = isUndefined(optionsDiff[prop]) ? {} : optionsDiff[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 propPrefix = propPath ? `${propPath}.` : '';
|
||||
|
||||
// if the template has a object as value, it means that the options are complex (verschachtelt)
|
||||
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;
|
||||
optionsCopy[prop] = validatedResult._foreign as any;
|
||||
|
||||
@@ -163,9 +186,15 @@ const validateRecursive = <T extends PlainObject>(
|
||||
});
|
||||
|
||||
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);
|
||||
if (doStringifyComparison ? stringify(optionsValue) !== stringify(optionsDiffValue) : optionsValue !== optionsDiffValue) {
|
||||
if (
|
||||
doStringifyComparison
|
||||
? stringify(optionsValue) !== stringify(optionsDiffValue)
|
||||
: optionsValue !== optionsDiffValue
|
||||
) {
|
||||
validatedOptions[prop] = optionsValue;
|
||||
}
|
||||
} 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` +
|
||||
`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>,
|
||||
optionsDiff?: T | null,
|
||||
doWriteErrors?: boolean
|
||||
): OptionsValidationResult<T> => {
|
||||
): OptionsValidationResult<T> =>
|
||||
/*
|
||||
if (!isEmptyObject(foreign) && doWriteErrors)
|
||||
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);
|
||||
}
|
||||
*/
|
||||
return validateRecursive<T>(options, template, optionsDiff || ({} as T), doWriteErrors || false);
|
||||
};
|
||||
validateRecursive<T>(options, template, optionsDiff || ({} as T), doWriteErrors || false);
|
||||
|
||||
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';
|
||||
|
||||
type RunEachItem = ((...args: any) => any | any[]) | null | undefined;
|
||||
@@ -56,21 +56,17 @@ export function each<T>(
|
||||
* @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.
|
||||
*/
|
||||
export const indexOf = <T = any>(arr: Array<T>, item: T, fromIndex?: number): number =>
|
||||
arr.indexOf(item, fromIndex);
|
||||
export const indexOf = <T = any>(arr: T[], item: T, fromIndex?: number): number =>
|
||||
isArray(arr) ? arr.indexOf(item, fromIndex) : -1;
|
||||
|
||||
/**
|
||||
* Pushesh all given items into the given array and returns it.
|
||||
* @param array The array the items shall be pushed into.
|
||||
* @param items The items which shall be pushed into the array.
|
||||
*/
|
||||
export const push = <T>(
|
||||
array: Array<T>,
|
||||
items: T | ArrayLike<T>,
|
||||
arrayIsSingleItem?: boolean
|
||||
): Array<T> => {
|
||||
export const push = <T>(array: T[], items: T | ArrayLike<T>, arrayIsSingleItem?: boolean): T[] => {
|
||||
!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);
|
||||
return array;
|
||||
};
|
||||
@@ -83,7 +79,7 @@ export const from = <T = any>(arr: ArrayLike<T>) => {
|
||||
if (Array.from) {
|
||||
return Array.from(arr);
|
||||
}
|
||||
const result: Array<T> = [];
|
||||
const result: T[] = [];
|
||||
|
||||
each(arr, (elm) => {
|
||||
push(result, elm);
|
||||
@@ -96,7 +92,7 @@ export const from = <T = any>(arr: ArrayLike<T>) => {
|
||||
* Check whether the passed array is empty.
|
||||
* @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;
|
||||
|
||||
/**
|
||||
|
||||
@@ -6,7 +6,8 @@ import { each } from 'support/utils/array';
|
||||
* @param obj The object.
|
||||
* @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.
|
||||
@@ -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
|
||||
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, W>(target: T, 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>(
|
||||
target: T,
|
||||
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>(
|
||||
target: T,
|
||||
object1?: U,
|
||||
|
||||
@@ -11,14 +11,13 @@ export function isNull(obj: any): obj is null {
|
||||
return obj === null;
|
||||
}
|
||||
|
||||
export const type: (obj: any) => string = (obj) => {
|
||||
return isUndefined(obj) || isNull(obj)
|
||||
export const type: (obj: any) => string = (obj) =>
|
||||
isUndefined(obj) || isNull(obj)
|
||||
? `${obj}`
|
||||
: toString
|
||||
.call(obj)
|
||||
.replace(/^\[object (.+)\]$/, '$1')
|
||||
.toLowerCase();
|
||||
};
|
||||
|
||||
export function isNumber(obj: any): obj is 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 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 {
|
||||
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 {
|
||||
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';
|
||||
|
||||
const createUpdater = <T, C = unknown>(updaterReturn: (i: number) => T) => {
|
||||
const fn = jest.fn();
|
||||
const createUpdater = <T>(updaterReturn: (i: number) => T) => {
|
||||
let index = 0;
|
||||
const update = (context?: C, curr?: T, prev?: T): T => {
|
||||
fn(context, curr, prev);
|
||||
index += 1;
|
||||
return updaterReturn(index);
|
||||
};
|
||||
const updater = jest.fn(
|
||||
(): T => {
|
||||
index += 1;
|
||||
return updaterReturn(index);
|
||||
}
|
||||
);
|
||||
|
||||
return [fn, update];
|
||||
return updater;
|
||||
};
|
||||
|
||||
describe('cache', () => {
|
||||
test('creates and updates cache', () => {
|
||||
const [fn, updater] = createUpdater((i) => `${i}`);
|
||||
const updater = createUpdater((i) => `${i}`);
|
||||
const _initialValue = '';
|
||||
const [updateCache, getCurrentCache] = createCache<string>(updater, {
|
||||
_initialValue,
|
||||
});
|
||||
const [updateCache, getCurrentCache] = createCache<string>(
|
||||
{
|
||||
_initialValue,
|
||||
},
|
||||
updater
|
||||
);
|
||||
|
||||
let [value, changed, previous] = updateCache();
|
||||
expect([value, false, previous]).toEqual(getCurrentCache());
|
||||
expect(fn).toHaveBeenLastCalledWith(undefined, _initialValue, undefined);
|
||||
expect(updater).toHaveBeenLastCalledWith(_initialValue, undefined);
|
||||
expect(value).toBe('1');
|
||||
expect(previous).toBe(_initialValue);
|
||||
expect(changed).toBe(true);
|
||||
|
||||
[value, changed, previous] = updateCache();
|
||||
expect([value, false, previous]).toEqual(getCurrentCache());
|
||||
expect(fn).toHaveBeenLastCalledWith(undefined, '1', _initialValue);
|
||||
expect(updater).toHaveBeenLastCalledWith('1', _initialValue);
|
||||
expect(value).toBe('2');
|
||||
expect(previous).toBe('1');
|
||||
expect(changed).toBe(true);
|
||||
});
|
||||
|
||||
describe('context', () => {
|
||||
test('creates and updates cache with context', () => {
|
||||
describe('contextual cache', () => {
|
||||
test('creates and updates contextual cache', () => {
|
||||
interface ContextObj {
|
||||
test: string;
|
||||
even: number;
|
||||
}
|
||||
const _initialValue = false;
|
||||
const updateFn = jest.fn();
|
||||
const updater = (context?: ContextObj, current?: boolean, previous?: boolean) => {
|
||||
updateFn(context, current, previous);
|
||||
return context!.test === 'test' || context!.even % 2 === 0;
|
||||
};
|
||||
const [updateCache, getCurrentCache] = createCache(updater, { _initialValue });
|
||||
const updater = (context: ContextObj) => context!.test === 'test' || context!.even % 2 === 0;
|
||||
const [updateCache, getCurrentCache] = createCache({ _initialValue });
|
||||
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(updateFn).toHaveBeenLastCalledWith(firstCtx, _initialValue, undefined);
|
||||
expect(value).toBe(true);
|
||||
expect(previous).toBe(_initialValue);
|
||||
expect(changed).toBe(true);
|
||||
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(updateFn).toHaveBeenLastCalledWith(firstCtx, true, _initialValue);
|
||||
expect(value).toBe(true);
|
||||
expect(previous).toBe(_initialValue);
|
||||
expect(changed).toBe(false);
|
||||
|
||||
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(updateFn).toHaveBeenLastCalledWith(scndCtx, true, _initialValue);
|
||||
expect(value).toBe(false);
|
||||
expect(previous).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(updateFn).toHaveBeenLastCalledWith(scndCtx, false, true);
|
||||
expect(value).toBe(false);
|
||||
expect(previous).toBe(true);
|
||||
expect(changed).toBe(false);
|
||||
|
||||
[value, changed, previous] = updateCache(true, scndCtx);
|
||||
[value, changed, previous] = updateCache(updater(scndCtx), true);
|
||||
expect([value, false, previous]).toEqual(getCurrentCache());
|
||||
expect(updateFn).toHaveBeenLastCalledWith(scndCtx, false, true);
|
||||
expect(value).toBe(false);
|
||||
expect(previous).toBe(false);
|
||||
expect(changed).toBe(true);
|
||||
});
|
||||
|
||||
test('creates and updates cache with context shorthand', () => {
|
||||
test('creates and updates contextual cache with direct passing', () => {
|
||||
interface ContextObj {
|
||||
test: string;
|
||||
even: number;
|
||||
}
|
||||
const _initialValue = undefined;
|
||||
const firstCtx = { test: 'test', even: 2 };
|
||||
const [_update] = createCache<ContextObj | undefined, ContextObj>(0, {
|
||||
const [updateCache] = createCache<ContextObj | undefined>({
|
||||
_initialValue,
|
||||
});
|
||||
|
||||
let [value, changed, previous] = _update(0, firstCtx);
|
||||
let [value, changed, previous] = updateCache(firstCtx);
|
||||
expect(value).toBe(firstCtx);
|
||||
expect(previous).toBe(undefined);
|
||||
expect(changed).toBe(true);
|
||||
|
||||
[value, changed, previous] = _update(0, firstCtx);
|
||||
[value, changed, previous] = updateCache(firstCtx);
|
||||
expect(value).toBe(firstCtx);
|
||||
expect(previous).toBe(undefined);
|
||||
expect(changed).toBe(false);
|
||||
|
||||
const scndCtx = { test: 'nah', even: 1 };
|
||||
|
||||
[value, changed, previous] = _update(0, scndCtx);
|
||||
[value, changed, previous] = updateCache(scndCtx);
|
||||
expect(value).toBe(scndCtx);
|
||||
expect(previous).toBe(firstCtx);
|
||||
expect(changed).toBe(true);
|
||||
|
||||
[value, changed, previous] = _update(0, scndCtx);
|
||||
[value, changed, previous] = updateCache(scndCtx);
|
||||
expect(value).toBe(scndCtx);
|
||||
expect(previous).toBe(firstCtx);
|
||||
expect(changed).toBe(false);
|
||||
|
||||
[value, changed, previous] = _update(true, scndCtx);
|
||||
[value, changed, previous] = updateCache(scndCtx, true);
|
||||
expect(value).toBe(scndCtx);
|
||||
expect(previous).toBe(scndCtx);
|
||||
expect(changed).toBe(true);
|
||||
@@ -131,65 +125,73 @@ describe('cache', () => {
|
||||
|
||||
describe('equal', () => {
|
||||
test('with equal always true', () => {
|
||||
const [fn, updater] = createUpdater((i) => i);
|
||||
const [updateCache, getCurrentCache] = createCache<number | undefined>(updater, {
|
||||
_initialValue: undefined,
|
||||
_equal: () => true,
|
||||
});
|
||||
const updater = createUpdater<number | undefined>((i) => i);
|
||||
const [updateCache, getCurrentCache] = createCache<number | undefined>(
|
||||
{
|
||||
_initialValue: undefined,
|
||||
_equal: () => true,
|
||||
},
|
||||
updater
|
||||
);
|
||||
|
||||
let [value, changed, previous] = updateCache();
|
||||
expect([value, false, previous]).toEqual(getCurrentCache());
|
||||
expect(fn).toHaveBeenLastCalledWith(undefined, undefined, undefined);
|
||||
expect(updater).toHaveBeenLastCalledWith(undefined, undefined);
|
||||
expect(value).toBe(undefined);
|
||||
expect(previous).toBe(undefined);
|
||||
expect(changed).toBe(false);
|
||||
|
||||
[value, changed, previous] = updateCache();
|
||||
expect([value, false, previous]).toEqual(getCurrentCache());
|
||||
expect(fn).toHaveBeenLastCalledWith(undefined, undefined, undefined);
|
||||
expect(updater).toHaveBeenLastCalledWith(undefined, undefined);
|
||||
expect(value).toBe(undefined);
|
||||
expect(previous).toBe(undefined);
|
||||
expect(changed).toBe(false);
|
||||
});
|
||||
|
||||
test('with equal always false', () => {
|
||||
const [fn, updater] = createUpdater(() => 1);
|
||||
const [updateCache, getCurrentCache] = createCache<number | undefined>(updater, {
|
||||
_initialValue: undefined,
|
||||
_equal: () => false,
|
||||
});
|
||||
const updater = createUpdater<number | undefined>(() => 1);
|
||||
const [updateCache, getCurrentCache] = createCache<number | undefined>(
|
||||
{
|
||||
_initialValue: undefined,
|
||||
_equal: () => false,
|
||||
},
|
||||
updater
|
||||
);
|
||||
|
||||
let [value, changed, previous] = updateCache();
|
||||
expect([value, false, previous]).toEqual(getCurrentCache());
|
||||
expect(fn).toHaveBeenLastCalledWith(undefined, undefined, undefined);
|
||||
expect(updater).toHaveBeenLastCalledWith(undefined, undefined);
|
||||
expect(value).toBe(1);
|
||||
expect(previous).toBe(undefined);
|
||||
expect(changed).toBe(true);
|
||||
|
||||
[value, changed, previous] = updateCache();
|
||||
expect([value, false, previous]).toEqual(getCurrentCache());
|
||||
expect(fn).toHaveBeenLastCalledWith(undefined, 1, undefined);
|
||||
expect(updater).toHaveBeenLastCalledWith(1, undefined);
|
||||
expect(value).toBe(1);
|
||||
expect(previous).toBe(1);
|
||||
expect(changed).toBe(true);
|
||||
});
|
||||
|
||||
test('with object equal', () => {
|
||||
const obj = { a: -1, b: -1 };
|
||||
const [fn, updater] = createUpdater((i) => ({ a: i, b: i + 1 }));
|
||||
const [updateCache] = createCache<typeof obj | undefined>(updater, {
|
||||
_initialValue: undefined,
|
||||
_equal: (a, b) => a?.a === b?.a && a?.b === b?.b,
|
||||
});
|
||||
const updater = createUpdater((i) => ({ a: i, b: i + 1 }));
|
||||
const [updateCache] = createCache(
|
||||
{
|
||||
_initialValue: undefined,
|
||||
_equal: (a, b) => a?.a === b?.a && a?.b === b?.b,
|
||||
},
|
||||
updater
|
||||
);
|
||||
|
||||
let [value, changed, previous] = updateCache();
|
||||
expect(fn).toHaveBeenLastCalledWith(undefined, undefined, undefined);
|
||||
expect(updater).toHaveBeenLastCalledWith(undefined, undefined);
|
||||
expect(value).toEqual({ a: 1, b: 2 });
|
||||
expect(previous).toBe(undefined);
|
||||
expect(changed).toBe(true);
|
||||
|
||||
[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(previous).toEqual({ a: 1, b: 2 });
|
||||
expect(changed).toBe(true);
|
||||
@@ -198,19 +200,19 @@ describe('cache', () => {
|
||||
|
||||
describe('inital value', () => {
|
||||
test('creates and updates cache with initialValue', () => {
|
||||
const [fn, updater] = createUpdater((i) => i);
|
||||
const [updateCache, getCurrentCache] = createCache<number>(updater, { _initialValue: 0 });
|
||||
const updater = createUpdater((i) => i);
|
||||
const [updateCache, getCurrentCache] = createCache<number>({ _initialValue: 0 }, updater);
|
||||
|
||||
let [value, changed, previous] = updateCache();
|
||||
expect([value, false, previous]).toEqual(getCurrentCache());
|
||||
expect(fn).toHaveBeenLastCalledWith(undefined, 0, undefined);
|
||||
expect(updater).toHaveBeenLastCalledWith(0, undefined);
|
||||
expect(value).toBe(1);
|
||||
expect(previous).toBe(0);
|
||||
expect(changed).toBe(true);
|
||||
|
||||
[value, changed, previous] = updateCache();
|
||||
expect([value, false, previous]).toEqual(getCurrentCache());
|
||||
expect(fn).toHaveBeenLastCalledWith(undefined, 1, 0);
|
||||
expect(updater).toHaveBeenLastCalledWith(1, 0);
|
||||
expect(value).toBe(2);
|
||||
expect(previous).toBe(1);
|
||||
expect(changed).toBe(true);
|
||||
@@ -218,20 +220,23 @@ describe('cache', () => {
|
||||
|
||||
test('creates and updates cache with initialValue and equal', () => {
|
||||
const obj = { a: -1, b: -1 };
|
||||
const [fn, updater] = createUpdater((i) => ({ a: i, b: i + 1 }));
|
||||
const [updateCache] = createCache<typeof obj>(updater, {
|
||||
_initialValue: obj,
|
||||
_equal: (a, b) => a?.a === b?.a && a?.b === b?.b,
|
||||
});
|
||||
const updater = createUpdater((i) => ({ a: i, b: i + 1 }));
|
||||
const [updateCache] = createCache(
|
||||
{
|
||||
_initialValue: obj,
|
||||
_equal: (a, b) => a?.a === b?.a && a?.b === b?.b,
|
||||
},
|
||||
updater
|
||||
);
|
||||
|
||||
let [value, changed, previous] = updateCache();
|
||||
expect(fn).toHaveBeenLastCalledWith(undefined, obj, undefined);
|
||||
expect(updater).toHaveBeenLastCalledWith(obj, undefined);
|
||||
expect(value).toEqual({ a: 1, b: 2 });
|
||||
expect(previous).toBe(obj);
|
||||
expect(changed).toBe(true);
|
||||
|
||||
[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(previous).toEqual({ a: 1, b: 2 });
|
||||
expect(changed).toBe(true);
|
||||
@@ -240,44 +245,47 @@ describe('cache', () => {
|
||||
|
||||
describe('always update values', () => {
|
||||
test('creates and updates cache with alwaysUpdateValues and equal always true', () => {
|
||||
const [fn, updater] = createUpdater((i) => i);
|
||||
const [updateCache] = createCache<number | undefined>(updater, {
|
||||
_initialValue: undefined,
|
||||
_alwaysUpdateValues: true,
|
||||
_equal: () => true,
|
||||
});
|
||||
const updater = createUpdater<number | undefined>((i) => i);
|
||||
const [updateCache] = createCache<number | undefined>(
|
||||
{
|
||||
_initialValue: undefined,
|
||||
_alwaysUpdateValues: true,
|
||||
_equal: () => true,
|
||||
},
|
||||
updater
|
||||
);
|
||||
|
||||
let [value, changed, previous] = updateCache();
|
||||
expect(fn).toHaveBeenLastCalledWith(undefined, undefined, undefined);
|
||||
expect(updater).toHaveBeenLastCalledWith(undefined, undefined);
|
||||
expect(value).toBe(1);
|
||||
expect(previous).toBe(undefined);
|
||||
expect(changed).toBe(false);
|
||||
|
||||
[value, changed, previous] = updateCache();
|
||||
expect(fn).toHaveBeenLastCalledWith(undefined, 1, undefined);
|
||||
expect(updater).toHaveBeenLastCalledWith(1, undefined);
|
||||
expect(value).toBe(2);
|
||||
expect(previous).toBe(1);
|
||||
expect(changed).toBe(false);
|
||||
});
|
||||
|
||||
test('creates and updates cache with context shorthand and alwaysUpdateValues', () => {
|
||||
test('creates and updates contextual cache with alwaysUpdateValues', () => {
|
||||
interface ContextObj {
|
||||
test: string;
|
||||
even: number;
|
||||
}
|
||||
const [updateCache, getCurrentCache] = createCache<ContextObj | undefined, ContextObj>(0, {
|
||||
const [updateCache, getCurrentCache] = createCache<ContextObj | undefined>({
|
||||
_initialValue: undefined,
|
||||
_alwaysUpdateValues: true,
|
||||
});
|
||||
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).toBe(firstCtx);
|
||||
expect(previous).toBe(undefined);
|
||||
expect(changed).toBe(true);
|
||||
|
||||
[value, changed, previous] = updateCache(0, firstCtx);
|
||||
[value, changed, previous] = updateCache(firstCtx);
|
||||
expect([value, false, previous]).toEqual(getCurrentCache());
|
||||
expect(value).toBe(firstCtx);
|
||||
expect(previous).toBe(firstCtx);
|
||||
@@ -285,19 +293,19 @@ describe('cache', () => {
|
||||
|
||||
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).toBe(scndCtx);
|
||||
expect(previous).toBe(firstCtx);
|
||||
expect(changed).toBe(true);
|
||||
|
||||
[value, changed, previous] = updateCache(0, scndCtx);
|
||||
[value, changed, previous] = updateCache(scndCtx);
|
||||
expect([value, false, previous]).toEqual(getCurrentCache());
|
||||
expect(value).toBe(scndCtx);
|
||||
expect(previous).toBe(scndCtx);
|
||||
expect(changed).toBe(false);
|
||||
|
||||
[value, changed, previous] = updateCache(true, scndCtx);
|
||||
[value, changed, previous] = updateCache(scndCtx, true);
|
||||
expect([value, false, previous]).toEqual(getCurrentCache());
|
||||
expect(value).toBe(scndCtx);
|
||||
expect(previous).toBe(scndCtx);
|
||||
@@ -307,21 +315,24 @@ describe('cache', () => {
|
||||
|
||||
describe('constant', () => {
|
||||
test('updates constant initially without intial value', () => {
|
||||
const [fn, updater] = createUpdater(() => true);
|
||||
const [updateCache, getCurrentCache] = createCache<boolean | undefined>(updater, {
|
||||
_initialValue: undefined,
|
||||
});
|
||||
const updater = createUpdater<boolean | undefined>(() => true);
|
||||
const [updateCache, getCurrentCache] = createCache<boolean | undefined>(
|
||||
{
|
||||
_initialValue: undefined,
|
||||
},
|
||||
updater
|
||||
);
|
||||
|
||||
let [value, changed, previous] = updateCache();
|
||||
expect([value, false, previous]).toEqual(getCurrentCache());
|
||||
expect(fn).toHaveBeenLastCalledWith(undefined, undefined, undefined);
|
||||
expect(updater).toHaveBeenLastCalledWith(undefined, undefined);
|
||||
expect(value).toBe(true);
|
||||
expect(previous).toBe(undefined);
|
||||
expect(changed).toBe(true);
|
||||
|
||||
[value, changed, previous] = updateCache();
|
||||
expect([value, false, previous]).toEqual(getCurrentCache());
|
||||
expect(fn).toHaveBeenLastCalledWith(undefined, true, undefined);
|
||||
expect(updater).toHaveBeenLastCalledWith(true, undefined);
|
||||
expect(value).toBe(true);
|
||||
expect(previous).toBe(undefined);
|
||||
expect(changed).toBe(false);
|
||||
@@ -329,52 +340,55 @@ describe('cache', () => {
|
||||
|
||||
test('doesnt update constant with initial value', () => {
|
||||
const obj = { constant: true };
|
||||
const [fn, updater] = createUpdater(() => obj);
|
||||
const [updateCache] = createCache<typeof obj>(updater, { _initialValue: obj });
|
||||
const updater = createUpdater(() => obj);
|
||||
const [updateCache] = createCache({ _initialValue: obj }, updater);
|
||||
|
||||
let [value, changed, previous] = updateCache();
|
||||
expect(fn).toHaveBeenLastCalledWith(undefined, obj, undefined);
|
||||
expect(updater).toHaveBeenLastCalledWith(obj, undefined);
|
||||
expect(value).toBe(obj);
|
||||
expect(previous).toBe(undefined);
|
||||
expect(changed).toBe(false);
|
||||
|
||||
[value, changed, previous] = updateCache();
|
||||
expect(fn).toHaveBeenLastCalledWith(undefined, obj, undefined);
|
||||
expect(updater).toHaveBeenLastCalledWith(obj, undefined);
|
||||
expect(value).toBe(obj);
|
||||
expect(previous).toBe(undefined);
|
||||
expect(changed).toBe(false);
|
||||
});
|
||||
|
||||
test('updates constant with force', () => {
|
||||
const [fn, updater] = createUpdater(() => 'constant');
|
||||
const [updateCache, getCurrentCache] = createCache<string | undefined>(updater, {
|
||||
_initialValue: undefined,
|
||||
});
|
||||
const updater = createUpdater<string | undefined>(() => 'constant');
|
||||
const [updateCache, getCurrentCache] = createCache<string | undefined>(
|
||||
{
|
||||
_initialValue: undefined,
|
||||
},
|
||||
updater
|
||||
);
|
||||
|
||||
let [value, changed, previous] = updateCache();
|
||||
expect([value, false, previous]).toEqual(getCurrentCache());
|
||||
expect(fn).toHaveBeenLastCalledWith(undefined, undefined, undefined);
|
||||
expect(updater).toHaveBeenLastCalledWith(undefined, undefined);
|
||||
expect(value).toBe('constant');
|
||||
expect(previous).toBe(undefined);
|
||||
expect(changed).toBe(true);
|
||||
|
||||
[value, changed, previous] = updateCache(true);
|
||||
expect([value, false, previous]).toEqual(getCurrentCache());
|
||||
expect(fn).toHaveBeenLastCalledWith(undefined, 'constant', undefined);
|
||||
expect(updater).toHaveBeenLastCalledWith('constant', undefined);
|
||||
expect(value).toBe('constant');
|
||||
expect(previous).toBe('constant');
|
||||
expect(changed).toBe(true);
|
||||
|
||||
[value, changed, previous] = updateCache(false);
|
||||
expect([value, false, previous]).toEqual(getCurrentCache());
|
||||
expect(fn).toHaveBeenLastCalledWith(undefined, 'constant', 'constant');
|
||||
expect(updater).toHaveBeenLastCalledWith('constant', 'constant');
|
||||
expect(value).toBe('constant');
|
||||
expect(previous).toBe('constant');
|
||||
expect(changed).toBe(false);
|
||||
|
||||
[value, changed, previous] = updateCache();
|
||||
expect([value, false, previous]).toEqual(getCurrentCache());
|
||||
expect(fn).toHaveBeenLastCalledWith(undefined, 'constant', 'constant');
|
||||
expect(updater).toHaveBeenLastCalledWith('constant', 'constant');
|
||||
expect(value).toBe('constant');
|
||||
expect(previous).toBe('constant');
|
||||
expect(changed).toBe(false);
|
||||
|
||||
Reference in New Issue
Block a user