mirror of
https://github.com/tenrok/OverlayScrollbars.git
synced 2026-05-29 21:14:07 +03:00
add viewport is target mode
This commit is contained in:
+189
-111
@@ -195,6 +195,17 @@ function attr(elm, attrName, value) {
|
||||
|
||||
elm && elm.setAttribute(attrName, value);
|
||||
}
|
||||
const attrClass = (elm, attrName, value, add) => {
|
||||
const currValues = attr(elm, attrName) || '';
|
||||
const currValuesSet = new Set(currValues.split(' '));
|
||||
currValuesSet[add ? 'add' : 'delete'](value);
|
||||
attr(elm, attrName, from(currValuesSet).join(' ').trim());
|
||||
};
|
||||
const hasAttrClass = (elm, attrName, value) => {
|
||||
const currValues = attr(elm, attrName) || '';
|
||||
const currValuesSet = new Set(currValues.split(' '));
|
||||
return currValuesSet.has(value);
|
||||
};
|
||||
const removeAttr = (elm, attrName) => {
|
||||
elm && elm.removeAttribute(attrName);
|
||||
};
|
||||
@@ -213,6 +224,11 @@ const find = (selector, elm) => {
|
||||
return rootElm ? push(arr, rootElm.querySelectorAll(selector)) : arr;
|
||||
};
|
||||
|
||||
const findFirst = (selector, elm) => {
|
||||
const rootElm = elm ? isElement(elm) ? elm : null : document;
|
||||
return rootElm ? rootElm.querySelector(selector) : null;
|
||||
};
|
||||
|
||||
const is = (elm, selector) => {
|
||||
if (isElement(elm)) {
|
||||
const fn = elmPrototype.matches || elmPrototype.msMatchesSelector;
|
||||
@@ -226,6 +242,32 @@ const contents = elm => elm ? from(elm.childNodes) : [];
|
||||
|
||||
const parent = elm => elm ? elm.parentElement : null;
|
||||
|
||||
const closest = (elm, selector) => {
|
||||
if (isElement(elm)) {
|
||||
const closestFn = elmPrototype.closest;
|
||||
|
||||
if (closestFn) {
|
||||
return closestFn.call(elm, selector);
|
||||
}
|
||||
|
||||
do {
|
||||
if (is(elm, selector)) {
|
||||
return elm;
|
||||
}
|
||||
|
||||
elm = parent(elm);
|
||||
} while (elm);
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
const liesBetween = (elm, highBoundarySelector, deepBoundarySelector) => {
|
||||
const closestHighBoundaryElm = elm && closest(elm, highBoundarySelector);
|
||||
const closestDeepBoundaryElm = elm && findFirst(deepBoundarySelector, closestHighBoundaryElm);
|
||||
return closestHighBoundaryElm && closestDeepBoundaryElm ? closestHighBoundaryElm === elm || closestDeepBoundaryElm === elm || closest(closest(elm, deepBoundarySelector), highBoundarySelector) !== closestHighBoundaryElm : false;
|
||||
};
|
||||
|
||||
const before = (parentElm, preferredAnchor, insertedElms) => {
|
||||
if (insertedElms) {
|
||||
let anchor = preferredAnchor;
|
||||
@@ -349,7 +391,7 @@ const classListAction = (elm, className, action) => {
|
||||
let i = 0;
|
||||
let result = false;
|
||||
|
||||
if (elm && isString(className)) {
|
||||
if (elm && className && isString(className)) {
|
||||
const classes = className.match(rnothtmlwhite) || [];
|
||||
result = classes.length > 0;
|
||||
|
||||
@@ -360,6 +402,8 @@ const classListAction = (elm, className, action) => {
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
const hasClass = (elm, className) => classListAction(elm, className, (classList, clazz) => classList.contains(clazz));
|
||||
const removeClass = (elm, className) => {
|
||||
classListAction(elm, className, (classList, clazz) => classList.remove(clazz));
|
||||
};
|
||||
@@ -367,22 +411,6 @@ const addClass = (elm, className) => {
|
||||
classListAction(elm, className, (classList, clazz) => classList.add(clazz));
|
||||
return removeClass.bind(0, elm, className);
|
||||
};
|
||||
const diffClass = (classNameA, classNameB) => {
|
||||
const classNameASplit = classNameA && classNameA.split(' ');
|
||||
const classNameBSplit = classNameB && classNameB.split(' ');
|
||||
const tempObj = {};
|
||||
each(classNameASplit, className => {
|
||||
tempObj[className] = 1;
|
||||
});
|
||||
each(classNameBSplit, className => {
|
||||
if (tempObj[className]) {
|
||||
delete tempObj[className];
|
||||
} else {
|
||||
tempObj[className] = 1;
|
||||
}
|
||||
});
|
||||
return keys(tempObj);
|
||||
};
|
||||
|
||||
const equal = (a, b, props, propMutation) => {
|
||||
if (a && b) {
|
||||
@@ -688,6 +716,10 @@ const classNameEnvironment = 'os-environment';
|
||||
const classNameEnvironmentFlexboxGlue = `${classNameEnvironment}-flexbox-glue`;
|
||||
const classNameEnvironmentFlexboxGlueMax = `${classNameEnvironmentFlexboxGlue}-max`;
|
||||
const dataAttributeHost = 'data-overlayscrollbars';
|
||||
const dataAttributeHostOverflowX = `${dataAttributeHost}-overflow-x`;
|
||||
const dataAttributeHostOverflowY = `${dataAttributeHost}-overflow-y`;
|
||||
const dataValueHostOverflowVisible = 'overflowVisible';
|
||||
const dataValueHostViewportScrollbarStyling = 'viewportStyled';
|
||||
const classNamePadding = 'os-padding';
|
||||
const classNameViewport = 'os-viewport';
|
||||
const classNameViewportArrange = `${classNameViewport}-arrange`;
|
||||
@@ -716,17 +748,21 @@ const stringify = value => JSON.stringify(value, (_, val) => {
|
||||
});
|
||||
|
||||
const defaultOptions = {
|
||||
resize: 'none',
|
||||
paddingAbsolute: false,
|
||||
updating: {
|
||||
elementEvents: [['img', 'load']],
|
||||
debounce: [0, 33],
|
||||
attributes: null,
|
||||
debounce: [0, 33]
|
||||
ignoreMutation: null
|
||||
},
|
||||
overflow: {
|
||||
x: 'scroll',
|
||||
y: 'scroll'
|
||||
},
|
||||
nativeScrollbarsOverlaid: {
|
||||
show: false,
|
||||
initialize: false
|
||||
},
|
||||
scrollbars: {
|
||||
visibility: 'auto',
|
||||
autoHide: 'never',
|
||||
@@ -734,18 +770,6 @@ const defaultOptions = {
|
||||
dragScroll: true,
|
||||
clickScroll: false,
|
||||
touch: true
|
||||
},
|
||||
textarea: {
|
||||
dynWidth: false,
|
||||
dynHeight: false,
|
||||
inheritedAttrs: ['style', 'class']
|
||||
},
|
||||
nativeScrollbarsOverlaid: {
|
||||
show: false,
|
||||
initialize: false
|
||||
},
|
||||
callbacks: {
|
||||
onUpdated: null
|
||||
}
|
||||
};
|
||||
const getOptionsDiff = (currOptions, newOptions) => {
|
||||
@@ -988,8 +1012,8 @@ const dynamicCreationFromStrategy = (target, initializationValue, strategy) => {
|
||||
return result === true ? createDiv() : result;
|
||||
};
|
||||
|
||||
const addDataAttrHost = elm => {
|
||||
attr(elm, dataAttributeHost, '');
|
||||
const addDataAttrHost = (elm, value) => {
|
||||
attr(elm, dataAttributeHost, value || '');
|
||||
return removeAttr.bind(0, elm, dataAttributeHost);
|
||||
};
|
||||
|
||||
@@ -1014,20 +1038,28 @@ const createStructureSetupElements = target => {
|
||||
const ownerDocument = targetElement.ownerDocument;
|
||||
const bodyElm = ownerDocument.body;
|
||||
const wnd = ownerDocument.defaultView;
|
||||
const singleElmSupport = !!ResizeObserverConstructor && _nativeScrollbarStyling;
|
||||
const potentialViewportElement = staticCreationFromStrategy(targetElement, targetStructureInitialization.viewport, viewportInitializationStrategy);
|
||||
const potentiallySingleElm = potentialViewportElement === targetElement;
|
||||
const viewportIsTarget = singleElmSupport && potentiallySingleElm;
|
||||
const viewportElement = potentiallySingleElm && !viewportIsTarget ? staticCreationFromStrategy(targetElement) : potentialViewportElement;
|
||||
const evaluatedTargetObj = {
|
||||
_target: targetElement,
|
||||
_host: isTextarea ? staticCreationFromStrategy(targetElement, targetStructureInitialization.host, hostInitializationStrategy) : targetElement,
|
||||
_viewport: staticCreationFromStrategy(targetElement, targetStructureInitialization.viewport, viewportInitializationStrategy),
|
||||
_viewport: viewportElement,
|
||||
_padding: dynamicCreationFromStrategy(targetElement, targetStructureInitialization.padding, paddingInitializationStrategy),
|
||||
_content: dynamicCreationFromStrategy(targetElement, targetStructureInitialization.content, contentInitializationStrategy),
|
||||
_viewportArrange: createUniqueViewportArrangeElement(),
|
||||
_viewportArrange: !viewportIsTarget && createUniqueViewportArrangeElement(),
|
||||
_windowElm: wnd,
|
||||
_documentElm: ownerDocument,
|
||||
_htmlElm: parent(bodyElm),
|
||||
_bodyElm: bodyElm,
|
||||
_isTextarea: isTextarea,
|
||||
_isBody: isBody,
|
||||
_targetIsElm: targetIsElm
|
||||
_targetIsElm: targetIsElm,
|
||||
_viewportIsTarget: viewportIsTarget,
|
||||
_viewportHasClass: (className, attributeClassName) => viewportIsTarget ? hasAttrClass(viewportElement, dataAttributeHost, attributeClassName) : hasClass(viewportElement, className),
|
||||
_viewportAddRemoveClass: (className, attributeClassName, add) => viewportIsTarget ? attrClass(viewportElement, dataAttributeHost, attributeClassName, add) : (add ? addClass : removeClass)(viewportElement, className)
|
||||
};
|
||||
const generatedElements = keys(evaluatedTargetObj).reduce((arr, key) => {
|
||||
const value = evaluatedTargetObj[key];
|
||||
@@ -1048,9 +1080,9 @@ const createStructureSetupElements = target => {
|
||||
const isTextareaHostGenerated = isTextarea && elementIsGenerated(_host);
|
||||
const targetContents = isTextarea ? _target : contents([_content, _viewport, _padding, _host, _target].find(elm => elementIsGenerated(elm) === false));
|
||||
const contentSlot = _content || _viewport;
|
||||
const removeHostDataAttr = addDataAttrHost(_host);
|
||||
const removeHostDataAttr = addDataAttrHost(_host, viewportIsTarget ? 'viewport' : 'host');
|
||||
const removePaddingClass = addClass(_padding, classNamePadding);
|
||||
const removeViewportClass = addClass(_viewport, classNameViewport);
|
||||
const removeViewportClass = addClass(_viewport, !viewportIsTarget && classNameViewport);
|
||||
const removeContentClass = addClass(_content, classNameContent);
|
||||
|
||||
if (isTextareaHostGenerated) {
|
||||
@@ -1063,34 +1095,31 @@ const createStructureSetupElements = target => {
|
||||
|
||||
appendChildren(contentSlot, targetContents);
|
||||
appendChildren(_host, _padding);
|
||||
appendChildren(_padding || _host, _viewport);
|
||||
appendChildren(_padding || _host, !viewportIsTarget && _viewport);
|
||||
appendChildren(_viewport, _content);
|
||||
push(destroyFns, () => {
|
||||
if (targetIsElm) {
|
||||
appendChildren(_host, contents(contentSlot));
|
||||
removeElements(_padding || _viewport);
|
||||
removeHostDataAttr();
|
||||
} else {
|
||||
if (elementIsGenerated(_content)) {
|
||||
unwrap(_content);
|
||||
}
|
||||
removeHostDataAttr();
|
||||
removeAttr(_viewport, dataAttributeHostOverflowX);
|
||||
removeAttr(_viewport, dataAttributeHostOverflowY);
|
||||
|
||||
if (elementIsGenerated(_viewport)) {
|
||||
unwrap(_viewport);
|
||||
}
|
||||
|
||||
if (elementIsGenerated(_padding)) {
|
||||
unwrap(_padding);
|
||||
}
|
||||
|
||||
removeHostDataAttr();
|
||||
removePaddingClass();
|
||||
removeViewportClass();
|
||||
removeContentClass();
|
||||
if (elementIsGenerated(_content)) {
|
||||
unwrap(_content);
|
||||
}
|
||||
|
||||
if (elementIsGenerated(_viewport)) {
|
||||
unwrap(_viewport);
|
||||
}
|
||||
|
||||
if (elementIsGenerated(_padding)) {
|
||||
unwrap(_padding);
|
||||
}
|
||||
|
||||
removePaddingClass();
|
||||
removeViewportClass();
|
||||
removeContentClass();
|
||||
});
|
||||
|
||||
if (_nativeScrollbarStyling) {
|
||||
if (_nativeScrollbarStyling && !viewportIsTarget) {
|
||||
push(destroyFns, removeClass.bind(0, _viewport, classNameViewportScrollbarStyling));
|
||||
}
|
||||
|
||||
@@ -1121,8 +1150,7 @@ const createTrinsicUpdate = (structureSetupElements, state) => {
|
||||
|
||||
if (heightIntrinsicChanged) {
|
||||
style(_content, {
|
||||
height: _heightIntrinsic ? '' : '100%',
|
||||
display: _heightIntrinsic ? '' : 'inline'
|
||||
height: _heightIntrinsic ? '' : '100%'
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1138,7 +1166,8 @@ const createPaddingUpdate = (structureSetupElements, state) => {
|
||||
const {
|
||||
_host,
|
||||
_padding,
|
||||
_viewport
|
||||
_viewport,
|
||||
_viewportIsTarget: _isSingleElm
|
||||
} = structureSetupElements;
|
||||
const [updatePaddingCache, currentPaddingCache] = createCache({
|
||||
_equal: equalTRBL,
|
||||
@@ -1165,7 +1194,7 @@ const createPaddingUpdate = (structureSetupElements, state) => {
|
||||
[padding, paddingChanged] = updatePaddingCache(force);
|
||||
}
|
||||
|
||||
const paddingStyleChanged = paddingAbsoluteChanged || _directionChanged || paddingChanged;
|
||||
const paddingStyleChanged = !_isSingleElm && (paddingAbsoluteChanged || _directionChanged || paddingChanged);
|
||||
|
||||
if (paddingStyleChanged) {
|
||||
const paddingRelative = !paddingAbsolute || !_padding && !_nativeScrollbarStyling;
|
||||
@@ -1234,7 +1263,7 @@ const getOverflowAmount = (viewportScrollSize, viewportClientSize, sizeFraction)
|
||||
};
|
||||
};
|
||||
|
||||
const conditionalClass = (elm, classNames, condition) => condition ? addClass(elm, classNames) : removeClass(elm, classNames);
|
||||
const conditionalClass = (elm, classNames, add) => add ? addClass(elm, classNames) : removeClass(elm, classNames);
|
||||
|
||||
const overflowIsVisible = overflowBehavior => overflowBehavior.indexOf(strVisible) === 0;
|
||||
|
||||
@@ -1244,7 +1273,9 @@ const createOverflowUpdate = (structureSetupElements, state) => {
|
||||
_host,
|
||||
_padding,
|
||||
_viewport,
|
||||
_viewportArrange
|
||||
_viewportArrange,
|
||||
_viewportIsTarget,
|
||||
_viewportAddRemoveClass
|
||||
} = structureSetupElements;
|
||||
const {
|
||||
_nativeScrollbarSize,
|
||||
@@ -1252,7 +1283,7 @@ const createOverflowUpdate = (structureSetupElements, state) => {
|
||||
_nativeScrollbarStyling,
|
||||
_nativeScrollbarIsOverlaid
|
||||
} = getEnvironment();
|
||||
const doViewportArrange = !_nativeScrollbarStyling && (_nativeScrollbarIsOverlaid.x || _nativeScrollbarIsOverlaid.y);
|
||||
const doViewportArrange = !_viewportIsTarget && !_nativeScrollbarStyling && (_nativeScrollbarIsOverlaid.x || _nativeScrollbarIsOverlaid.y);
|
||||
const [updateSizeFraction, getCurrentSizeFraction] = createCache(whCacheOptions, fractionalSize.bind(0, _host));
|
||||
const [updateViewportScrollSizeCache, getCurrentViewportScrollSizeCache] = createCache(whCacheOptions, scrollSize.bind(0, _viewport));
|
||||
const [updateOverflowAmountCache, getCurrentOverflowAmountCache] = createCache(whCacheOptions);
|
||||
@@ -1483,7 +1514,7 @@ const createOverflowUpdate = (structureSetupElements, state) => {
|
||||
const [showNativeOverlaidScrollbarsOption, showNativeOverlaidScrollbarsChanged] = checkOption('nativeScrollbarsOverlaid.show');
|
||||
const [overflow, overflowChanged] = checkOption('overflow');
|
||||
const showNativeOverlaidScrollbars = showNativeOverlaidScrollbarsOption && _nativeScrollbarIsOverlaid.x && _nativeScrollbarIsOverlaid.y;
|
||||
const adjustFlexboxGlue = !_flexboxGlue && (_sizeChanged || _contentMutation || _hostMutation || showNativeOverlaidScrollbarsChanged || _heightIntrinsicChanged);
|
||||
const adjustFlexboxGlue = !_viewportIsTarget && !_flexboxGlue && (_sizeChanged || _contentMutation || _hostMutation || showNativeOverlaidScrollbarsChanged || _heightIntrinsicChanged);
|
||||
const overflowXVisible = overflowIsVisible(overflow.x);
|
||||
const overflowYVisible = overflowIsVisible(overflow.y);
|
||||
const overflowVisible = overflowXVisible || overflowYVisible;
|
||||
@@ -1493,7 +1524,7 @@ const createOverflowUpdate = (structureSetupElements, state) => {
|
||||
let preMeasureViewportOverflowState;
|
||||
|
||||
if (showNativeOverlaidScrollbarsChanged && _nativeScrollbarStyling) {
|
||||
conditionalClass(_viewport, classNameViewportScrollbarStyling, !showNativeOverlaidScrollbars);
|
||||
_viewportAddRemoveClass(classNameViewportScrollbarStyling, dataValueHostViewportScrollbarStyling, !showNativeOverlaidScrollbars);
|
||||
}
|
||||
|
||||
if (adjustFlexboxGlue) {
|
||||
@@ -1503,7 +1534,7 @@ const createOverflowUpdate = (structureSetupElements, state) => {
|
||||
|
||||
if (_sizeChanged || _paddingStyleChanged || _contentMutation || _directionChanged || showNativeOverlaidScrollbarsChanged) {
|
||||
if (overflowVisible) {
|
||||
removeClass(_viewport, classNameOverflowVisible);
|
||||
_viewportAddRemoveClass(classNameOverflowVisible, dataValueHostOverflowVisible, false);
|
||||
}
|
||||
|
||||
const [redoViewportArrange, undoViewportArrangeOverflowState] = undoViewportArrange(showNativeOverlaidScrollbars, _directionIsRTL, preMeasureViewportOverflowState);
|
||||
@@ -1548,18 +1579,26 @@ const createOverflowUpdate = (structureSetupElements, state) => {
|
||||
};
|
||||
const viewportOverflowState = setViewportOverflowState(showNativeOverlaidScrollbars, hasOverflow, overflow, viewportStyle);
|
||||
const viewportArranged = arrangeViewport(viewportOverflowState, viewportScrollSize, sizeFraction, _directionIsRTL);
|
||||
hideNativeScrollbars(viewportOverflowState, _directionIsRTL, viewportArranged, viewportStyle);
|
||||
|
||||
if (!_viewportIsTarget) {
|
||||
hideNativeScrollbars(viewportOverflowState, _directionIsRTL, viewportArranged, viewportStyle);
|
||||
}
|
||||
|
||||
if (adjustFlexboxGlue) {
|
||||
fixFlexboxGlue(viewportOverflowState, _heightIntrinsic);
|
||||
}
|
||||
|
||||
style(_viewport, viewportStyle);
|
||||
if (_viewportIsTarget) {
|
||||
attr(_host, dataAttributeHostOverflowX, viewportStyle.overflowX);
|
||||
attr(_host, dataAttributeHostOverflowY, viewportStyle.overflowY);
|
||||
} else {
|
||||
style(_viewport, viewportStyle);
|
||||
}
|
||||
}
|
||||
|
||||
attr(_host, dataAttributeHost, removeClipping ? 'overflowVisible' : '');
|
||||
attrClass(_host, dataAttributeHost, dataValueHostOverflowVisible, removeClipping);
|
||||
conditionalClass(_padding, classNameOverflowVisible, removeClipping);
|
||||
conditionalClass(_viewport, classNameOverflowVisible, overflowVisible);
|
||||
!_viewportIsTarget && conditionalClass(_viewport, classNameOverflowVisible, overflowVisible);
|
||||
const [overflowStyle, overflowStyleChanged] = updateOverflowStyleCache(getViewportOverflowState(showNativeOverlaidScrollbars)._overflowStyle);
|
||||
setState({
|
||||
_overflowStyle: overflowStyle,
|
||||
@@ -1910,7 +1949,6 @@ const createDOMObserver = (target, isContentObserver, callback, options) => {
|
||||
_eventContentChange,
|
||||
_nestedTargetSelector,
|
||||
_ignoreTargetChange,
|
||||
_ignoreNestedTargetChange,
|
||||
_ignoreContentChange
|
||||
} = options || {};
|
||||
const [destroyEventContentChange, updateEventContentChangeElements] = createEventContentChange(target, debounce(() => {
|
||||
@@ -1926,7 +1964,7 @@ const createDOMObserver = (target, isContentObserver, callback, options) => {
|
||||
const observedAttributes = finalAttributes.concat(finalStyleChangingAttributes);
|
||||
|
||||
const observerCallback = mutations => {
|
||||
const ignoreTargetChange = (isContentObserver ? _ignoreNestedTargetChange : _ignoreTargetChange) || noop;
|
||||
const ignoreTargetChange = _ignoreTargetChange || noop;
|
||||
const ignoreContentChange = _ignoreContentChange || noop;
|
||||
const targetChangedAttrs = [];
|
||||
const totalAddedNodes = [];
|
||||
@@ -2002,20 +2040,11 @@ const createDOMObserver = (target, isContentObserver, callback, options) => {
|
||||
}];
|
||||
};
|
||||
|
||||
const ignorePrefix = 'os-';
|
||||
const hostSelector = `[${dataAttributeHost}]`;
|
||||
const viewportSelector = `.${classNameViewport}`;
|
||||
const viewportAttrsFromTarget = ['tabindex'];
|
||||
const baseStyleChangingAttrsTextarea = ['wrap', 'cols', 'rows'];
|
||||
const baseStyleChangingAttrs = ['id', 'class', 'style', 'open'];
|
||||
|
||||
const ignoreTargetChange = (target, attrName, oldValue, newValue) => {
|
||||
if (attrName === 'class' && oldValue && newValue) {
|
||||
const diff = diffClass(oldValue, newValue);
|
||||
return !!diff.find(addedOrRemovedClass => addedOrRemovedClass.indexOf(ignorePrefix) !== 0);
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
const createStructureSetupObservers = (structureSetupElements, state, structureSetupUpdate) => {
|
||||
let debounceTimeout;
|
||||
let debounceMaxDelay;
|
||||
@@ -2025,12 +2054,34 @@ const createStructureSetupObservers = (structureSetupElements, state, structureS
|
||||
_host,
|
||||
_viewport,
|
||||
_content,
|
||||
_isTextarea
|
||||
_isTextarea,
|
||||
_viewportIsTarget,
|
||||
_viewportHasClass,
|
||||
_viewportAddRemoveClass
|
||||
} = structureSetupElements;
|
||||
const {
|
||||
_nativeScrollbarStyling,
|
||||
_flexboxGlue
|
||||
} = getEnvironment();
|
||||
const [updateContentSizeCache] = createCache({
|
||||
_equal: equalWH,
|
||||
_initialValue: {
|
||||
w: 0,
|
||||
h: 0
|
||||
}
|
||||
}, () => {
|
||||
const has = _viewportHasClass(classNameOverflowVisible, dataValueHostOverflowVisible);
|
||||
|
||||
has && _viewportAddRemoveClass(classNameOverflowVisible, dataValueHostOverflowVisible);
|
||||
const contentScroll = scrollSize(_content);
|
||||
const viewportScroll = scrollSize(_viewport);
|
||||
const fractional = fractionalSize(_viewport);
|
||||
has && _viewportAddRemoveClass(classNameOverflowVisible, dataValueHostOverflowVisible, true);
|
||||
return {
|
||||
w: viewportScroll.w + contentScroll.w + fractional.w,
|
||||
h: viewportScroll.h + contentScroll.h + fractional.h
|
||||
};
|
||||
});
|
||||
const contentMutationObserverAttr = _isTextarea ? baseStyleChangingAttrsTextarea : baseStyleChangingAttrs.concat(baseStyleChangingAttrsTextarea);
|
||||
const structureSetupUpdateWithDebouncedAdaptiveUpdateHints = debounce(structureSetupUpdate, {
|
||||
_timeout: () => debounceTimeout,
|
||||
@@ -2094,10 +2145,14 @@ const createStructureSetupObservers = (structureSetupElements, state, structureS
|
||||
};
|
||||
|
||||
const onContentMutation = contentChangedTroughEvent => {
|
||||
const [, contentSizeChanged] = updateContentSizeCache();
|
||||
const updateFn = contentChangedTroughEvent ? structureSetupUpdate : structureSetupUpdateWithDebouncedAdaptiveUpdateHints;
|
||||
updateFn({
|
||||
_contentMutation: true
|
||||
});
|
||||
|
||||
if (contentSizeChanged) {
|
||||
updateFn({
|
||||
_contentMutation: true
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const onHostMutation = (targetChangedAttrs, targetStyleChanged) => {
|
||||
@@ -2105,28 +2160,34 @@ const createStructureSetupObservers = (structureSetupElements, state, structureS
|
||||
structureSetupUpdateWithDebouncedAdaptiveUpdateHints({
|
||||
_hostMutation: true
|
||||
});
|
||||
} else {
|
||||
} else if (!_viewportIsTarget) {
|
||||
updateViewportAttrsFromHost(targetChangedAttrs);
|
||||
}
|
||||
};
|
||||
|
||||
const destroyTrinsicObserver = (_content || !_flexboxGlue) && createTrinsicObserver(_host, onTrinsicChanged);
|
||||
const destroySizeObserver = createSizeObserver(_host, onSizeChanged, {
|
||||
const destroySizeObserver = !_viewportIsTarget && createSizeObserver(_host, onSizeChanged, {
|
||||
_appear: true,
|
||||
_direction: !_nativeScrollbarStyling
|
||||
});
|
||||
const [destroyHostMutationObserver] = createDOMObserver(_host, false, onHostMutation, {
|
||||
_styleChangingAttributes: baseStyleChangingAttrs,
|
||||
_attributes: baseStyleChangingAttrs.concat(viewportAttrsFromTarget),
|
||||
_ignoreTargetChange: ignoreTargetChange
|
||||
_attributes: baseStyleChangingAttrs.concat(viewportAttrsFromTarget)
|
||||
});
|
||||
const viewportIsTargetResizeObserver = _viewportIsTarget && new ResizeObserverConstructor(onSizeChanged.bind(0, {
|
||||
_sizeChanged: true
|
||||
}));
|
||||
viewportIsTargetResizeObserver && viewportIsTargetResizeObserver.observe(_host);
|
||||
updateViewportAttrsFromHost();
|
||||
return [checkOption => {
|
||||
const [elementEvents, elementEventsChanged] = checkOption('updating.elementEvents');
|
||||
const [ignoreMutation] = checkOption('updating.ignoreMutation');
|
||||
const [attributes, attributesChanged] = checkOption('updating.attributes');
|
||||
const [elementEvents, elementEventsChanged] = checkOption('updating.elementEvents');
|
||||
const [debounceValue, debounceChanged] = checkOption('updating.debounce');
|
||||
const updateContentMutationObserver = elementEventsChanged || attributesChanged;
|
||||
|
||||
const ignoreMutationFromOptions = mutation => isFunction(ignoreMutation) && ignoreMutation(mutation);
|
||||
|
||||
if (updateContentMutationObserver) {
|
||||
if (contentMutationObserver) {
|
||||
contentMutationObserver[1]();
|
||||
@@ -2137,7 +2198,15 @@ const createStructureSetupObservers = (structureSetupElements, state, structureS
|
||||
_styleChangingAttributes: contentMutationObserverAttr.concat(attributes || []),
|
||||
_attributes: contentMutationObserverAttr.concat(attributes || []),
|
||||
_eventContentChange: elementEvents,
|
||||
_ignoreNestedTargetChange: ignoreTargetChange
|
||||
_nestedTargetSelector: hostSelector,
|
||||
_ignoreContentChange: (mutation, isNestedTarget) => {
|
||||
const {
|
||||
target,
|
||||
attributeName
|
||||
} = mutation;
|
||||
const ignore = !isNestedTarget && attributeName ? liesBetween(target, hostSelector, viewportSelector) : false;
|
||||
return ignore || !!ignoreMutationFromOptions(mutation);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -2160,7 +2229,8 @@ const createStructureSetupObservers = (structureSetupElements, state, structureS
|
||||
}, () => {
|
||||
contentMutationObserver && contentMutationObserver[0]();
|
||||
destroyTrinsicObserver && destroyTrinsicObserver();
|
||||
destroySizeObserver();
|
||||
destroySizeObserver && destroySizeObserver();
|
||||
viewportIsTargetResizeObserver && viewportIsTargetResizeObserver.disconnect();
|
||||
destroyHostMutationObserver();
|
||||
}];
|
||||
};
|
||||
@@ -2335,18 +2405,16 @@ const optionsTemplateTypes = ['boolean', 'number', 'string', 'array', 'object',
|
||||
const numberAllowedValues = optionsTemplateTypes.number;
|
||||
const booleanAllowedValues = optionsTemplateTypes.boolean;
|
||||
const arrayNullValues = [optionsTemplateTypes.array, optionsTemplateTypes.null];
|
||||
const stringArrayNullAllowedValues = [optionsTemplateTypes.string, optionsTemplateTypes.array, optionsTemplateTypes.null];
|
||||
const resizeAllowedValues = 'none both horizontal vertical';
|
||||
const overflowAllowedValues = 'hidden scroll visible visible-hidden';
|
||||
const scrollbarsVisibilityAllowedValues = 'visible hidden auto';
|
||||
const scrollbarsAutoHideAllowedValues = 'never scroll leavemove';
|
||||
({
|
||||
resize: resizeAllowedValues,
|
||||
paddingAbsolute: booleanAllowedValues,
|
||||
updating: {
|
||||
elementEvents: arrayNullValues,
|
||||
attributes: arrayNullValues,
|
||||
debounce: [optionsTemplateTypes.number, optionsTemplateTypes.array, optionsTemplateTypes.null]
|
||||
debounce: [optionsTemplateTypes.number, optionsTemplateTypes.array, optionsTemplateTypes.null],
|
||||
ignoreMutation: [optionsTemplateTypes.function, optionsTemplateTypes.null]
|
||||
},
|
||||
overflow: {
|
||||
x: overflowAllowedValues,
|
||||
@@ -2360,17 +2428,9 @@ const scrollbarsAutoHideAllowedValues = 'never scroll leavemove';
|
||||
clickScroll: booleanAllowedValues,
|
||||
touch: booleanAllowedValues
|
||||
},
|
||||
textarea: {
|
||||
dynWidth: booleanAllowedValues,
|
||||
dynHeight: booleanAllowedValues,
|
||||
inheritedAttrs: stringArrayNullAllowedValues
|
||||
},
|
||||
nativeScrollbarsOverlaid: {
|
||||
show: booleanAllowedValues,
|
||||
initialize: booleanAllowedValues
|
||||
},
|
||||
callbacks: {
|
||||
onUpdated: [optionsTemplateTypes.function, optionsTemplateTypes.null]
|
||||
}
|
||||
});
|
||||
const optionsValidationPluginName = '__osOptionsValidationPlugin';
|
||||
@@ -2469,7 +2529,8 @@ const OverlayScrollbars = (target, options, eventListeners) => {
|
||||
|
||||
on: addEvent,
|
||||
off: removeEvent,
|
||||
state: () => {
|
||||
|
||||
state() {
|
||||
const {
|
||||
_overflowAmount,
|
||||
_overflowStyle,
|
||||
@@ -2486,6 +2547,23 @@ const OverlayScrollbars = (target, options, eventListeners) => {
|
||||
});
|
||||
},
|
||||
|
||||
elements() {
|
||||
const {
|
||||
_target,
|
||||
_host,
|
||||
_padding,
|
||||
_viewport,
|
||||
_content
|
||||
} = structureState._elements;
|
||||
return assignDeep({}, {
|
||||
target: _target,
|
||||
host: _host,
|
||||
padding: _padding || _viewport,
|
||||
viewport: _viewport,
|
||||
content: _content || _viewport
|
||||
});
|
||||
},
|
||||
|
||||
update(force) {
|
||||
update({}, force);
|
||||
},
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+205
-118
@@ -218,6 +218,17 @@
|
||||
|
||||
elm && elm.setAttribute(attrName, value);
|
||||
}
|
||||
var attrClass = function attrClass(elm, attrName, value, add) {
|
||||
var currValues = attr(elm, attrName) || '';
|
||||
var currValuesSet = new Set(currValues.split(' '));
|
||||
currValuesSet[add ? 'add' : 'delete'](value);
|
||||
attr(elm, attrName, from(currValuesSet).join(' ').trim());
|
||||
};
|
||||
var hasAttrClass = function hasAttrClass(elm, attrName, value) {
|
||||
var currValues = attr(elm, attrName) || '';
|
||||
var currValuesSet = new Set(currValues.split(' '));
|
||||
return currValuesSet.has(value);
|
||||
};
|
||||
var removeAttr = function removeAttr(elm, attrName) {
|
||||
elm && elm.removeAttribute(attrName);
|
||||
};
|
||||
@@ -236,6 +247,11 @@
|
||||
return rootElm ? push(arr, rootElm.querySelectorAll(selector)) : arr;
|
||||
};
|
||||
|
||||
var findFirst = function findFirst(selector, elm) {
|
||||
var rootElm = elm ? isElement(elm) ? elm : null : document;
|
||||
return rootElm ? rootElm.querySelector(selector) : null;
|
||||
};
|
||||
|
||||
var is = function is(elm, selector) {
|
||||
if (isElement(elm)) {
|
||||
var fn = elmPrototype.matches || elmPrototype.msMatchesSelector;
|
||||
@@ -253,6 +269,32 @@
|
||||
return elm ? elm.parentElement : null;
|
||||
};
|
||||
|
||||
var closest = function closest(elm, selector) {
|
||||
if (isElement(elm)) {
|
||||
var closestFn = elmPrototype.closest;
|
||||
|
||||
if (closestFn) {
|
||||
return closestFn.call(elm, selector);
|
||||
}
|
||||
|
||||
do {
|
||||
if (is(elm, selector)) {
|
||||
return elm;
|
||||
}
|
||||
|
||||
elm = parent(elm);
|
||||
} while (elm);
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
var liesBetween = function liesBetween(elm, highBoundarySelector, deepBoundarySelector) {
|
||||
var closestHighBoundaryElm = elm && closest(elm, highBoundarySelector);
|
||||
var closestDeepBoundaryElm = elm && findFirst(deepBoundarySelector, closestHighBoundaryElm);
|
||||
return closestHighBoundaryElm && closestDeepBoundaryElm ? closestHighBoundaryElm === elm || closestDeepBoundaryElm === elm || closest(closest(elm, deepBoundarySelector), highBoundarySelector) !== closestHighBoundaryElm : false;
|
||||
};
|
||||
|
||||
var before = function before(parentElm, preferredAnchor, insertedElms) {
|
||||
if (insertedElms) {
|
||||
var anchor = preferredAnchor;
|
||||
@@ -386,7 +428,7 @@
|
||||
var i = 0;
|
||||
var result = false;
|
||||
|
||||
if (elm && isString(className)) {
|
||||
if (elm && className && isString(className)) {
|
||||
var classes = className.match(rnothtmlwhite) || [];
|
||||
result = classes.length > 0;
|
||||
|
||||
@@ -397,6 +439,12 @@
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
var hasClass = function hasClass(elm, className) {
|
||||
return classListAction(elm, className, function (classList, clazz) {
|
||||
return classList.contains(clazz);
|
||||
});
|
||||
};
|
||||
var removeClass = function removeClass(elm, className) {
|
||||
classListAction(elm, className, function (classList, clazz) {
|
||||
return classList.remove(clazz);
|
||||
@@ -408,22 +456,6 @@
|
||||
});
|
||||
return removeClass.bind(0, elm, className);
|
||||
};
|
||||
var diffClass = function diffClass(classNameA, classNameB) {
|
||||
var classNameASplit = classNameA && classNameA.split(' ');
|
||||
var classNameBSplit = classNameB && classNameB.split(' ');
|
||||
var tempObj = {};
|
||||
each(classNameASplit, function (className) {
|
||||
tempObj[className] = 1;
|
||||
});
|
||||
each(classNameBSplit, function (className) {
|
||||
if (tempObj[className]) {
|
||||
delete tempObj[className];
|
||||
} else {
|
||||
tempObj[className] = 1;
|
||||
}
|
||||
});
|
||||
return keys(tempObj);
|
||||
};
|
||||
|
||||
var equal = function equal(a, b, props, propMutation) {
|
||||
if (a && b) {
|
||||
@@ -774,6 +806,10 @@
|
||||
var classNameEnvironmentFlexboxGlue = classNameEnvironment + "-flexbox-glue";
|
||||
var classNameEnvironmentFlexboxGlueMax = classNameEnvironmentFlexboxGlue + "-max";
|
||||
var dataAttributeHost = 'data-overlayscrollbars';
|
||||
var dataAttributeHostOverflowX = dataAttributeHost + "-overflow-x";
|
||||
var dataAttributeHostOverflowY = dataAttributeHost + "-overflow-y";
|
||||
var dataValueHostOverflowVisible = 'overflowVisible';
|
||||
var dataValueHostViewportScrollbarStyling = 'viewportStyled';
|
||||
var classNamePadding = 'os-padding';
|
||||
var classNameViewport = 'os-viewport';
|
||||
var classNameViewportArrange = classNameViewport + "-arrange";
|
||||
@@ -804,17 +840,21 @@
|
||||
};
|
||||
|
||||
var defaultOptions = {
|
||||
resize: 'none',
|
||||
paddingAbsolute: false,
|
||||
updating: {
|
||||
elementEvents: [['img', 'load']],
|
||||
debounce: [0, 33],
|
||||
attributes: null,
|
||||
debounce: [0, 33]
|
||||
ignoreMutation: null
|
||||
},
|
||||
overflow: {
|
||||
x: 'scroll',
|
||||
y: 'scroll'
|
||||
},
|
||||
nativeScrollbarsOverlaid: {
|
||||
show: false,
|
||||
initialize: false
|
||||
},
|
||||
scrollbars: {
|
||||
visibility: 'auto',
|
||||
autoHide: 'never',
|
||||
@@ -822,18 +862,6 @@
|
||||
dragScroll: true,
|
||||
clickScroll: false,
|
||||
touch: true
|
||||
},
|
||||
textarea: {
|
||||
dynWidth: false,
|
||||
dynHeight: false,
|
||||
inheritedAttrs: ['style', 'class']
|
||||
},
|
||||
nativeScrollbarsOverlaid: {
|
||||
show: false,
|
||||
initialize: false
|
||||
},
|
||||
callbacks: {
|
||||
onUpdated: null
|
||||
}
|
||||
};
|
||||
var getOptionsDiff = function getOptionsDiff(currOptions, newOptions) {
|
||||
@@ -1085,8 +1113,8 @@
|
||||
return result === true ? createDiv() : result;
|
||||
};
|
||||
|
||||
var addDataAttrHost = function addDataAttrHost(elm) {
|
||||
attr(elm, dataAttributeHost, '');
|
||||
var addDataAttrHost = function addDataAttrHost(elm, value) {
|
||||
attr(elm, dataAttributeHost, value || '');
|
||||
return removeAttr.bind(0, elm, dataAttributeHost);
|
||||
};
|
||||
|
||||
@@ -1109,20 +1137,32 @@
|
||||
var ownerDocument = targetElement.ownerDocument;
|
||||
var bodyElm = ownerDocument.body;
|
||||
var wnd = ownerDocument.defaultView;
|
||||
var singleElmSupport = !!ResizeObserverConstructor && _nativeScrollbarStyling;
|
||||
var potentialViewportElement = staticCreationFromStrategy(targetElement, targetStructureInitialization.viewport, viewportInitializationStrategy);
|
||||
var potentiallySingleElm = potentialViewportElement === targetElement;
|
||||
var viewportIsTarget = singleElmSupport && potentiallySingleElm;
|
||||
var viewportElement = potentiallySingleElm && !viewportIsTarget ? staticCreationFromStrategy(targetElement) : potentialViewportElement;
|
||||
var evaluatedTargetObj = {
|
||||
_target: targetElement,
|
||||
_host: isTextarea ? staticCreationFromStrategy(targetElement, targetStructureInitialization.host, hostInitializationStrategy) : targetElement,
|
||||
_viewport: staticCreationFromStrategy(targetElement, targetStructureInitialization.viewport, viewportInitializationStrategy),
|
||||
_viewport: viewportElement,
|
||||
_padding: dynamicCreationFromStrategy(targetElement, targetStructureInitialization.padding, paddingInitializationStrategy),
|
||||
_content: dynamicCreationFromStrategy(targetElement, targetStructureInitialization.content, contentInitializationStrategy),
|
||||
_viewportArrange: createUniqueViewportArrangeElement(),
|
||||
_viewportArrange: !viewportIsTarget && createUniqueViewportArrangeElement(),
|
||||
_windowElm: wnd,
|
||||
_documentElm: ownerDocument,
|
||||
_htmlElm: parent(bodyElm),
|
||||
_bodyElm: bodyElm,
|
||||
_isTextarea: isTextarea,
|
||||
_isBody: isBody,
|
||||
_targetIsElm: targetIsElm
|
||||
_targetIsElm: targetIsElm,
|
||||
_viewportIsTarget: viewportIsTarget,
|
||||
_viewportHasClass: function _viewportHasClass(className, attributeClassName) {
|
||||
return viewportIsTarget ? hasAttrClass(viewportElement, dataAttributeHost, attributeClassName) : hasClass(viewportElement, className);
|
||||
},
|
||||
_viewportAddRemoveClass: function _viewportAddRemoveClass(className, attributeClassName, add) {
|
||||
return viewportIsTarget ? attrClass(viewportElement, dataAttributeHost, attributeClassName, add) : (add ? addClass : removeClass)(viewportElement, className);
|
||||
}
|
||||
};
|
||||
var generatedElements = keys(evaluatedTargetObj).reduce(function (arr, key) {
|
||||
var value = evaluatedTargetObj[key];
|
||||
@@ -1145,9 +1185,9 @@
|
||||
return elementIsGenerated(elm) === false;
|
||||
}));
|
||||
var contentSlot = _content || _viewport;
|
||||
var removeHostDataAttr = addDataAttrHost(_host);
|
||||
var removeHostDataAttr = addDataAttrHost(_host, viewportIsTarget ? 'viewport' : 'host');
|
||||
var removePaddingClass = addClass(_padding, classNamePadding);
|
||||
var removeViewportClass = addClass(_viewport, classNameViewport);
|
||||
var removeViewportClass = addClass(_viewport, !viewportIsTarget && classNameViewport);
|
||||
var removeContentClass = addClass(_content, classNameContent);
|
||||
|
||||
if (isTextareaHostGenerated) {
|
||||
@@ -1160,34 +1200,31 @@
|
||||
|
||||
appendChildren(contentSlot, targetContents);
|
||||
appendChildren(_host, _padding);
|
||||
appendChildren(_padding || _host, _viewport);
|
||||
appendChildren(_padding || _host, !viewportIsTarget && _viewport);
|
||||
appendChildren(_viewport, _content);
|
||||
push(destroyFns, function () {
|
||||
if (targetIsElm) {
|
||||
appendChildren(_host, contents(contentSlot));
|
||||
removeElements(_padding || _viewport);
|
||||
removeHostDataAttr();
|
||||
} else {
|
||||
if (elementIsGenerated(_content)) {
|
||||
unwrap(_content);
|
||||
}
|
||||
removeHostDataAttr();
|
||||
removeAttr(_viewport, dataAttributeHostOverflowX);
|
||||
removeAttr(_viewport, dataAttributeHostOverflowY);
|
||||
|
||||
if (elementIsGenerated(_viewport)) {
|
||||
unwrap(_viewport);
|
||||
}
|
||||
|
||||
if (elementIsGenerated(_padding)) {
|
||||
unwrap(_padding);
|
||||
}
|
||||
|
||||
removeHostDataAttr();
|
||||
removePaddingClass();
|
||||
removeViewportClass();
|
||||
removeContentClass();
|
||||
if (elementIsGenerated(_content)) {
|
||||
unwrap(_content);
|
||||
}
|
||||
|
||||
if (elementIsGenerated(_viewport)) {
|
||||
unwrap(_viewport);
|
||||
}
|
||||
|
||||
if (elementIsGenerated(_padding)) {
|
||||
unwrap(_padding);
|
||||
}
|
||||
|
||||
removePaddingClass();
|
||||
removeViewportClass();
|
||||
removeContentClass();
|
||||
});
|
||||
|
||||
if (_nativeScrollbarStyling) {
|
||||
if (_nativeScrollbarStyling && !viewportIsTarget) {
|
||||
push(destroyFns, removeClass.bind(0, _viewport, classNameViewportScrollbarStyling));
|
||||
}
|
||||
|
||||
@@ -1214,8 +1251,7 @@
|
||||
|
||||
if (heightIntrinsicChanged) {
|
||||
style(_content, {
|
||||
height: _heightIntrinsic ? '' : '100%',
|
||||
display: _heightIntrinsic ? '' : 'inline'
|
||||
height: _heightIntrinsic ? '' : '100%'
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1231,7 +1267,8 @@
|
||||
setState = state[1];
|
||||
var _host = structureSetupElements._host,
|
||||
_padding = structureSetupElements._padding,
|
||||
_viewport = structureSetupElements._viewport;
|
||||
_viewport = structureSetupElements._viewport,
|
||||
_isSingleElm = structureSetupElements._viewportIsTarget;
|
||||
|
||||
var _createCache = createCache({
|
||||
_equal: equalTRBL,
|
||||
@@ -1269,7 +1306,7 @@
|
||||
paddingChanged = _updatePaddingCache[1];
|
||||
}
|
||||
|
||||
var paddingStyleChanged = paddingAbsoluteChanged || _directionChanged || paddingChanged;
|
||||
var paddingStyleChanged = !_isSingleElm && (paddingAbsoluteChanged || _directionChanged || paddingChanged);
|
||||
|
||||
if (paddingStyleChanged) {
|
||||
var paddingRelative = !paddingAbsolute || !_padding && !_nativeScrollbarStyling;
|
||||
@@ -1336,8 +1373,8 @@
|
||||
};
|
||||
};
|
||||
|
||||
var conditionalClass = function conditionalClass(elm, classNames, condition) {
|
||||
return condition ? addClass(elm, classNames) : removeClass(elm, classNames);
|
||||
var conditionalClass = function conditionalClass(elm, classNames, add) {
|
||||
return add ? addClass(elm, classNames) : removeClass(elm, classNames);
|
||||
};
|
||||
|
||||
var overflowIsVisible = function overflowIsVisible(overflowBehavior) {
|
||||
@@ -1350,7 +1387,9 @@
|
||||
var _host = structureSetupElements._host,
|
||||
_padding = structureSetupElements._padding,
|
||||
_viewport = structureSetupElements._viewport,
|
||||
_viewportArrange = structureSetupElements._viewportArrange;
|
||||
_viewportArrange = structureSetupElements._viewportArrange,
|
||||
_viewportIsTarget = structureSetupElements._viewportIsTarget,
|
||||
_viewportAddRemoveClass = structureSetupElements._viewportAddRemoveClass;
|
||||
|
||||
var _getEnvironment = getEnvironment(),
|
||||
_nativeScrollbarSize = _getEnvironment._nativeScrollbarSize,
|
||||
@@ -1358,7 +1397,7 @@
|
||||
_nativeScrollbarStyling = _getEnvironment._nativeScrollbarStyling,
|
||||
_nativeScrollbarIsOverlaid = _getEnvironment._nativeScrollbarIsOverlaid;
|
||||
|
||||
var doViewportArrange = !_nativeScrollbarStyling && (_nativeScrollbarIsOverlaid.x || _nativeScrollbarIsOverlaid.y);
|
||||
var doViewportArrange = !_viewportIsTarget && !_nativeScrollbarStyling && (_nativeScrollbarIsOverlaid.x || _nativeScrollbarIsOverlaid.y);
|
||||
|
||||
var _createCache = createCache(whCacheOptions, fractionalSize.bind(0, _host)),
|
||||
updateSizeFraction = _createCache[0],
|
||||
@@ -1603,7 +1642,7 @@
|
||||
overflowChanged = _checkOption2[1];
|
||||
|
||||
var showNativeOverlaidScrollbars = showNativeOverlaidScrollbarsOption && _nativeScrollbarIsOverlaid.x && _nativeScrollbarIsOverlaid.y;
|
||||
var adjustFlexboxGlue = !_flexboxGlue && (_sizeChanged || _contentMutation || _hostMutation || showNativeOverlaidScrollbarsChanged || _heightIntrinsicChanged);
|
||||
var adjustFlexboxGlue = !_viewportIsTarget && !_flexboxGlue && (_sizeChanged || _contentMutation || _hostMutation || showNativeOverlaidScrollbarsChanged || _heightIntrinsicChanged);
|
||||
var overflowXVisible = overflowIsVisible(overflow.x);
|
||||
var overflowYVisible = overflowIsVisible(overflow.y);
|
||||
var overflowVisible = overflowXVisible || overflowYVisible;
|
||||
@@ -1613,7 +1652,7 @@
|
||||
var preMeasureViewportOverflowState;
|
||||
|
||||
if (showNativeOverlaidScrollbarsChanged && _nativeScrollbarStyling) {
|
||||
conditionalClass(_viewport, classNameViewportScrollbarStyling, !showNativeOverlaidScrollbars);
|
||||
_viewportAddRemoveClass(classNameViewportScrollbarStyling, dataValueHostViewportScrollbarStyling, !showNativeOverlaidScrollbars);
|
||||
}
|
||||
|
||||
if (adjustFlexboxGlue) {
|
||||
@@ -1623,7 +1662,7 @@
|
||||
|
||||
if (_sizeChanged || _paddingStyleChanged || _contentMutation || _directionChanged || showNativeOverlaidScrollbarsChanged) {
|
||||
if (overflowVisible) {
|
||||
removeClass(_viewport, classNameOverflowVisible);
|
||||
_viewportAddRemoveClass(classNameOverflowVisible, dataValueHostOverflowVisible, false);
|
||||
}
|
||||
|
||||
var _undoViewportArrange = undoViewportArrange(showNativeOverlaidScrollbars, _directionIsRTL, preMeasureViewportOverflowState),
|
||||
@@ -1683,18 +1722,26 @@
|
||||
};
|
||||
var viewportOverflowState = setViewportOverflowState(showNativeOverlaidScrollbars, hasOverflow, overflow, viewportStyle);
|
||||
var viewportArranged = arrangeViewport(viewportOverflowState, viewportScrollSize, sizeFraction, _directionIsRTL);
|
||||
hideNativeScrollbars(viewportOverflowState, _directionIsRTL, viewportArranged, viewportStyle);
|
||||
|
||||
if (!_viewportIsTarget) {
|
||||
hideNativeScrollbars(viewportOverflowState, _directionIsRTL, viewportArranged, viewportStyle);
|
||||
}
|
||||
|
||||
if (adjustFlexboxGlue) {
|
||||
fixFlexboxGlue(viewportOverflowState, _heightIntrinsic);
|
||||
}
|
||||
|
||||
style(_viewport, viewportStyle);
|
||||
if (_viewportIsTarget) {
|
||||
attr(_host, dataAttributeHostOverflowX, viewportStyle.overflowX);
|
||||
attr(_host, dataAttributeHostOverflowY, viewportStyle.overflowY);
|
||||
} else {
|
||||
style(_viewport, viewportStyle);
|
||||
}
|
||||
}
|
||||
|
||||
attr(_host, dataAttributeHost, removeClipping ? 'overflowVisible' : '');
|
||||
attrClass(_host, dataAttributeHost, dataValueHostOverflowVisible, removeClipping);
|
||||
conditionalClass(_padding, classNameOverflowVisible, removeClipping);
|
||||
conditionalClass(_viewport, classNameOverflowVisible, overflowVisible);
|
||||
!_viewportIsTarget && conditionalClass(_viewport, classNameOverflowVisible, overflowVisible);
|
||||
|
||||
var _updateOverflowStyleC = updateOverflowStyleCache(getViewportOverflowState(showNativeOverlaidScrollbars)._overflowStyle),
|
||||
overflowStyle = _updateOverflowStyleC[0],
|
||||
@@ -2070,7 +2117,6 @@
|
||||
_eventContentChange = _ref._eventContentChange,
|
||||
_nestedTargetSelector = _ref._nestedTargetSelector,
|
||||
_ignoreTargetChange = _ref._ignoreTargetChange,
|
||||
_ignoreNestedTargetChange = _ref._ignoreNestedTargetChange,
|
||||
_ignoreContentChange = _ref._ignoreContentChange;
|
||||
|
||||
var _createEventContentCh = createEventContentChange(target, debounce(function () {
|
||||
@@ -2089,7 +2135,7 @@
|
||||
var observedAttributes = finalAttributes.concat(finalStyleChangingAttributes);
|
||||
|
||||
var observerCallback = function observerCallback(mutations) {
|
||||
var ignoreTargetChange = (isContentObserver ? _ignoreNestedTargetChange : _ignoreTargetChange) || noop;
|
||||
var ignoreTargetChange = _ignoreTargetChange || noop;
|
||||
var ignoreContentChange = _ignoreContentChange || noop;
|
||||
var targetChangedAttrs = [];
|
||||
var totalAddedNodes = [];
|
||||
@@ -2165,22 +2211,11 @@
|
||||
}];
|
||||
};
|
||||
|
||||
var ignorePrefix = 'os-';
|
||||
var hostSelector = "[" + dataAttributeHost + "]";
|
||||
var viewportSelector = "." + classNameViewport;
|
||||
var viewportAttrsFromTarget = ['tabindex'];
|
||||
var baseStyleChangingAttrsTextarea = ['wrap', 'cols', 'rows'];
|
||||
var baseStyleChangingAttrs = ['id', 'class', 'style', 'open'];
|
||||
|
||||
var ignoreTargetChange = function ignoreTargetChange(target, attrName, oldValue, newValue) {
|
||||
if (attrName === 'class' && oldValue && newValue) {
|
||||
var diff = diffClass(oldValue, newValue);
|
||||
return !!diff.find(function (addedOrRemovedClass) {
|
||||
return addedOrRemovedClass.indexOf(ignorePrefix) !== 0;
|
||||
});
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
var createStructureSetupObservers = function createStructureSetupObservers(structureSetupElements, state, structureSetupUpdate) {
|
||||
var debounceTimeout;
|
||||
var debounceMaxDelay;
|
||||
@@ -2189,12 +2224,36 @@
|
||||
var _host = structureSetupElements._host,
|
||||
_viewport = structureSetupElements._viewport,
|
||||
_content = structureSetupElements._content,
|
||||
_isTextarea = structureSetupElements._isTextarea;
|
||||
_isTextarea = structureSetupElements._isTextarea,
|
||||
_viewportIsTarget = structureSetupElements._viewportIsTarget,
|
||||
_viewportHasClass = structureSetupElements._viewportHasClass,
|
||||
_viewportAddRemoveClass = structureSetupElements._viewportAddRemoveClass;
|
||||
|
||||
var _getEnvironment = getEnvironment(),
|
||||
_nativeScrollbarStyling = _getEnvironment._nativeScrollbarStyling,
|
||||
_flexboxGlue = _getEnvironment._flexboxGlue;
|
||||
|
||||
var _createCache = createCache({
|
||||
_equal: equalWH,
|
||||
_initialValue: {
|
||||
w: 0,
|
||||
h: 0
|
||||
}
|
||||
}, function () {
|
||||
var has = _viewportHasClass(classNameOverflowVisible, dataValueHostOverflowVisible);
|
||||
|
||||
has && _viewportAddRemoveClass(classNameOverflowVisible, dataValueHostOverflowVisible);
|
||||
var contentScroll = scrollSize(_content);
|
||||
var viewportScroll = scrollSize(_viewport);
|
||||
var fractional = fractionalSize(_viewport);
|
||||
has && _viewportAddRemoveClass(classNameOverflowVisible, dataValueHostOverflowVisible, true);
|
||||
return {
|
||||
w: viewportScroll.w + contentScroll.w + fractional.w,
|
||||
h: viewportScroll.h + contentScroll.h + fractional.h
|
||||
};
|
||||
}),
|
||||
updateContentSizeCache = _createCache[0];
|
||||
|
||||
var contentMutationObserverAttr = _isTextarea ? baseStyleChangingAttrsTextarea : baseStyleChangingAttrs.concat(baseStyleChangingAttrsTextarea);
|
||||
var structureSetupUpdateWithDebouncedAdaptiveUpdateHints = debounce(structureSetupUpdate, {
|
||||
_timeout: function _timeout() {
|
||||
@@ -2261,10 +2320,16 @@
|
||||
};
|
||||
|
||||
var onContentMutation = function onContentMutation(contentChangedTroughEvent) {
|
||||
var _updateContentSizeCac = updateContentSizeCache(),
|
||||
contentSizeChanged = _updateContentSizeCac[1];
|
||||
|
||||
var updateFn = contentChangedTroughEvent ? structureSetupUpdate : structureSetupUpdateWithDebouncedAdaptiveUpdateHints;
|
||||
updateFn({
|
||||
_contentMutation: true
|
||||
});
|
||||
|
||||
if (contentSizeChanged) {
|
||||
updateFn({
|
||||
_contentMutation: true
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
var onHostMutation = function onHostMutation(targetChangedAttrs, targetStyleChanged) {
|
||||
@@ -2272,40 +2337,50 @@
|
||||
structureSetupUpdateWithDebouncedAdaptiveUpdateHints({
|
||||
_hostMutation: true
|
||||
});
|
||||
} else {
|
||||
} else if (!_viewportIsTarget) {
|
||||
updateViewportAttrsFromHost(targetChangedAttrs);
|
||||
}
|
||||
};
|
||||
|
||||
var destroyTrinsicObserver = (_content || !_flexboxGlue) && createTrinsicObserver(_host, onTrinsicChanged);
|
||||
var destroySizeObserver = createSizeObserver(_host, onSizeChanged, {
|
||||
var destroySizeObserver = !_viewportIsTarget && createSizeObserver(_host, onSizeChanged, {
|
||||
_appear: true,
|
||||
_direction: !_nativeScrollbarStyling
|
||||
});
|
||||
|
||||
var _createDOMObserver = createDOMObserver(_host, false, onHostMutation, {
|
||||
_styleChangingAttributes: baseStyleChangingAttrs,
|
||||
_attributes: baseStyleChangingAttrs.concat(viewportAttrsFromTarget),
|
||||
_ignoreTargetChange: ignoreTargetChange
|
||||
_attributes: baseStyleChangingAttrs.concat(viewportAttrsFromTarget)
|
||||
}),
|
||||
destroyHostMutationObserver = _createDOMObserver[0];
|
||||
|
||||
var viewportIsTargetResizeObserver = _viewportIsTarget && new ResizeObserverConstructor(onSizeChanged.bind(0, {
|
||||
_sizeChanged: true
|
||||
}));
|
||||
viewportIsTargetResizeObserver && viewportIsTargetResizeObserver.observe(_host);
|
||||
updateViewportAttrsFromHost();
|
||||
return [function (checkOption) {
|
||||
var _checkOption = checkOption('updating.elementEvents'),
|
||||
elementEvents = _checkOption[0],
|
||||
elementEventsChanged = _checkOption[1];
|
||||
var _checkOption = checkOption('updating.ignoreMutation'),
|
||||
ignoreMutation = _checkOption[0];
|
||||
|
||||
var _checkOption2 = checkOption('updating.attributes'),
|
||||
attributes = _checkOption2[0],
|
||||
attributesChanged = _checkOption2[1];
|
||||
|
||||
var _checkOption3 = checkOption('updating.debounce'),
|
||||
debounceValue = _checkOption3[0],
|
||||
debounceChanged = _checkOption3[1];
|
||||
var _checkOption3 = checkOption('updating.elementEvents'),
|
||||
elementEvents = _checkOption3[0],
|
||||
elementEventsChanged = _checkOption3[1];
|
||||
|
||||
var _checkOption4 = checkOption('updating.debounce'),
|
||||
debounceValue = _checkOption4[0],
|
||||
debounceChanged = _checkOption4[1];
|
||||
|
||||
var updateContentMutationObserver = elementEventsChanged || attributesChanged;
|
||||
|
||||
var ignoreMutationFromOptions = function ignoreMutationFromOptions(mutation) {
|
||||
return isFunction(ignoreMutation) && ignoreMutation(mutation);
|
||||
};
|
||||
|
||||
if (updateContentMutationObserver) {
|
||||
if (contentMutationObserver) {
|
||||
contentMutationObserver[1]();
|
||||
@@ -2316,7 +2391,13 @@
|
||||
_styleChangingAttributes: contentMutationObserverAttr.concat(attributes || []),
|
||||
_attributes: contentMutationObserverAttr.concat(attributes || []),
|
||||
_eventContentChange: elementEvents,
|
||||
_ignoreNestedTargetChange: ignoreTargetChange
|
||||
_nestedTargetSelector: hostSelector,
|
||||
_ignoreContentChange: function _ignoreContentChange(mutation, isNestedTarget) {
|
||||
var target = mutation.target,
|
||||
attributeName = mutation.attributeName;
|
||||
var ignore = !isNestedTarget && attributeName ? liesBetween(target, hostSelector, viewportSelector) : false;
|
||||
return ignore || !!ignoreMutationFromOptions(mutation);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -2339,7 +2420,8 @@
|
||||
}, function () {
|
||||
contentMutationObserver && contentMutationObserver[0]();
|
||||
destroyTrinsicObserver && destroyTrinsicObserver();
|
||||
destroySizeObserver();
|
||||
destroySizeObserver && destroySizeObserver();
|
||||
viewportIsTargetResizeObserver && viewportIsTargetResizeObserver.disconnect();
|
||||
destroyHostMutationObserver();
|
||||
}];
|
||||
};
|
||||
@@ -2521,18 +2603,16 @@
|
||||
var numberAllowedValues = optionsTemplateTypes.number;
|
||||
var booleanAllowedValues = optionsTemplateTypes.boolean;
|
||||
var arrayNullValues = [optionsTemplateTypes.array, optionsTemplateTypes.null];
|
||||
var stringArrayNullAllowedValues = [optionsTemplateTypes.string, optionsTemplateTypes.array, optionsTemplateTypes.null];
|
||||
var resizeAllowedValues = 'none both horizontal vertical';
|
||||
var overflowAllowedValues = 'hidden scroll visible visible-hidden';
|
||||
var scrollbarsVisibilityAllowedValues = 'visible hidden auto';
|
||||
var scrollbarsAutoHideAllowedValues = 'never scroll leavemove';
|
||||
({
|
||||
resize: resizeAllowedValues,
|
||||
paddingAbsolute: booleanAllowedValues,
|
||||
updating: {
|
||||
elementEvents: arrayNullValues,
|
||||
attributes: arrayNullValues,
|
||||
debounce: [optionsTemplateTypes.number, optionsTemplateTypes.array, optionsTemplateTypes.null]
|
||||
debounce: [optionsTemplateTypes.number, optionsTemplateTypes.array, optionsTemplateTypes.null],
|
||||
ignoreMutation: [optionsTemplateTypes.function, optionsTemplateTypes.null]
|
||||
},
|
||||
overflow: {
|
||||
x: overflowAllowedValues,
|
||||
@@ -2546,17 +2626,9 @@
|
||||
clickScroll: booleanAllowedValues,
|
||||
touch: booleanAllowedValues
|
||||
},
|
||||
textarea: {
|
||||
dynWidth: booleanAllowedValues,
|
||||
dynHeight: booleanAllowedValues,
|
||||
inheritedAttrs: stringArrayNullAllowedValues
|
||||
},
|
||||
nativeScrollbarsOverlaid: {
|
||||
show: booleanAllowedValues,
|
||||
initialize: booleanAllowedValues
|
||||
},
|
||||
callbacks: {
|
||||
onUpdated: [optionsTemplateTypes.function, optionsTemplateTypes.null]
|
||||
}
|
||||
});
|
||||
var optionsValidationPluginName = '__osOptionsValidationPlugin';
|
||||
@@ -2683,6 +2755,21 @@
|
||||
paddingAbsolute: _paddingAbsolute
|
||||
});
|
||||
},
|
||||
elements: function elements() {
|
||||
var _structureState$_elem = structureState._elements,
|
||||
_target = _structureState$_elem._target,
|
||||
_host = _structureState$_elem._host,
|
||||
_padding = _structureState$_elem._padding,
|
||||
_viewport = _structureState$_elem._viewport,
|
||||
_content = _structureState$_elem._content;
|
||||
return assignDeep({}, {
|
||||
target: _target,
|
||||
host: _host,
|
||||
padding: _padding || _viewport,
|
||||
viewport: _viewport,
|
||||
content: _content || _viewport
|
||||
});
|
||||
},
|
||||
update: function update(force) {
|
||||
_update({}, force);
|
||||
},
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -3,6 +3,10 @@ export const classNameEnvironmentFlexboxGlue = `${classNameEnvironment}-flexbox-
|
||||
export const classNameEnvironmentFlexboxGlueMax = `${classNameEnvironmentFlexboxGlue}-max`;
|
||||
|
||||
export const dataAttributeHost = 'data-overlayscrollbars';
|
||||
export const dataAttributeHostOverflowX = `${dataAttributeHost}-overflow-x`;
|
||||
export const dataAttributeHostOverflowY = `${dataAttributeHost}-overflow-y`;
|
||||
export const dataValueHostOverflowVisible = 'overflowVisible';
|
||||
export const dataValueHostViewportScrollbarStyling = 'viewportStyled';
|
||||
export const classNamePadding = 'os-padding';
|
||||
export const classNameViewport = 'os-viewport';
|
||||
export const classNameViewportArrange = `${classNameViewport}-arrange`;
|
||||
|
||||
@@ -10,6 +10,7 @@ import {
|
||||
indexOf,
|
||||
removeElements,
|
||||
removeClass,
|
||||
hasClass,
|
||||
push,
|
||||
runEach,
|
||||
insertBefore,
|
||||
@@ -18,9 +19,14 @@ import {
|
||||
isFunction,
|
||||
keys,
|
||||
removeAttr,
|
||||
attrClass,
|
||||
hasAttrClass,
|
||||
ResizeObserverConstructor,
|
||||
} from 'support';
|
||||
import {
|
||||
dataAttributeHost,
|
||||
dataAttributeHostOverflowX,
|
||||
dataAttributeHostOverflowY,
|
||||
classNamePadding,
|
||||
classNameViewport,
|
||||
classNameViewportArrange,
|
||||
@@ -51,6 +57,9 @@ export interface StructureSetupElementsObj {
|
||||
_windowElm: Window;
|
||||
_documentElm: Document;
|
||||
_targetIsElm: boolean;
|
||||
_viewportIsTarget: boolean;
|
||||
_viewportHasClass: (className: string, attributeClassName: string) => boolean;
|
||||
_viewportAddRemoveClass: (className: string, attributeClassName: string, add?: boolean) => void;
|
||||
}
|
||||
|
||||
let contentArrangeCounter = 0;
|
||||
@@ -80,8 +89,8 @@ const createUniqueViewportArrangeElement = (): HTMLStyleElement | false => {
|
||||
|
||||
const staticCreationFromStrategy = (
|
||||
target: OSTargetElement,
|
||||
initializationValue: HTMLElement | undefined,
|
||||
strategy: StructureInitializationStrategyStaticElement
|
||||
initializationValue?: HTMLElement | undefined,
|
||||
strategy?: StructureInitializationStrategyStaticElement
|
||||
): HTMLElement => {
|
||||
const result =
|
||||
initializationValue ||
|
||||
@@ -104,8 +113,8 @@ const dynamicCreationFromStrategy = (
|
||||
return result === true ? createDiv() : result;
|
||||
};
|
||||
|
||||
const addDataAttrHost = (elm: HTMLElement) => {
|
||||
attr(elm, dataAttributeHost, '');
|
||||
const addDataAttrHost = (elm: HTMLElement, value?: string | false | null | undefined) => {
|
||||
attr(elm, dataAttributeHost, value || '');
|
||||
return removeAttr.bind(0, elm, dataAttributeHost);
|
||||
};
|
||||
|
||||
@@ -127,6 +136,18 @@ export const createStructureSetupElements = (target: OSTarget): StructureSetupEl
|
||||
const ownerDocument = targetElement!.ownerDocument;
|
||||
const bodyElm = ownerDocument.body as HTMLBodyElement;
|
||||
const wnd = ownerDocument.defaultView as Window;
|
||||
const singleElmSupport = !!ResizeObserverConstructor && _nativeScrollbarStyling;
|
||||
const potentialViewportElement = staticCreationFromStrategy(
|
||||
targetElement,
|
||||
targetStructureInitialization.viewport,
|
||||
viewportInitializationStrategy
|
||||
);
|
||||
const potentiallySingleElm = potentialViewportElement === targetElement;
|
||||
const viewportIsTarget = singleElmSupport && potentiallySingleElm;
|
||||
const viewportElement =
|
||||
potentiallySingleElm && !viewportIsTarget
|
||||
? staticCreationFromStrategy(targetElement)
|
||||
: potentialViewportElement;
|
||||
const evaluatedTargetObj: StructureSetupElementsObj = {
|
||||
_target: targetElement,
|
||||
_host: isTextarea
|
||||
@@ -136,11 +157,7 @@ export const createStructureSetupElements = (target: OSTarget): StructureSetupEl
|
||||
hostInitializationStrategy
|
||||
)
|
||||
: (targetElement as HTMLElement),
|
||||
_viewport: staticCreationFromStrategy(
|
||||
targetElement,
|
||||
targetStructureInitialization.viewport,
|
||||
viewportInitializationStrategy
|
||||
),
|
||||
_viewport: viewportElement,
|
||||
_padding: dynamicCreationFromStrategy(
|
||||
targetElement,
|
||||
targetStructureInitialization.padding,
|
||||
@@ -151,7 +168,7 @@ export const createStructureSetupElements = (target: OSTarget): StructureSetupEl
|
||||
targetStructureInitialization.content,
|
||||
contentInitializationStrategy
|
||||
),
|
||||
_viewportArrange: createUniqueViewportArrangeElement(),
|
||||
_viewportArrange: !viewportIsTarget && createUniqueViewportArrangeElement(),
|
||||
_windowElm: wnd,
|
||||
_documentElm: ownerDocument,
|
||||
_htmlElm: parent(bodyElm) as HTMLHtmlElement,
|
||||
@@ -159,6 +176,15 @@ export const createStructureSetupElements = (target: OSTarget): StructureSetupEl
|
||||
_isTextarea: isTextarea,
|
||||
_isBody: isBody,
|
||||
_targetIsElm: targetIsElm,
|
||||
_viewportIsTarget: viewportIsTarget,
|
||||
_viewportHasClass: (className: string, attributeClassName: string) =>
|
||||
viewportIsTarget
|
||||
? hasAttrClass(viewportElement, dataAttributeHost, attributeClassName)
|
||||
: hasClass(viewportElement, className),
|
||||
_viewportAddRemoveClass: (className: string, attributeClassName: string, add?: boolean) =>
|
||||
viewportIsTarget
|
||||
? attrClass(viewportElement, dataAttributeHost, attributeClassName, add)
|
||||
: (add ? addClass : removeClass)(viewportElement, className),
|
||||
};
|
||||
const generatedElements = keys(evaluatedTargetObj).reduce((arr, key: string) => {
|
||||
const value = evaluatedTargetObj[key];
|
||||
@@ -177,9 +203,9 @@ export const createStructureSetupElements = (target: OSTarget): StructureSetupEl
|
||||
)
|
||||
);
|
||||
const contentSlot = _content || _viewport;
|
||||
const removeHostDataAttr = addDataAttrHost(_host);
|
||||
const removeHostDataAttr = addDataAttrHost(_host, viewportIsTarget ? 'viewport' : 'host');
|
||||
const removePaddingClass = addClass(_padding, classNamePadding);
|
||||
const removeViewportClass = addClass(_viewport, classNameViewport);
|
||||
const removeViewportClass = addClass(_viewport, !viewportIsTarget && classNameViewport);
|
||||
const removeContentClass = addClass(_content, classNameContent);
|
||||
|
||||
// only insert host for textarea after target if it was generated
|
||||
@@ -194,32 +220,29 @@ export const createStructureSetupElements = (target: OSTarget): StructureSetupEl
|
||||
|
||||
appendChildren(contentSlot, targetContents);
|
||||
appendChildren(_host, _padding);
|
||||
appendChildren(_padding || _host, _viewport);
|
||||
appendChildren(_padding || _host, !viewportIsTarget && _viewport);
|
||||
appendChildren(_viewport, _content);
|
||||
|
||||
push(destroyFns, () => {
|
||||
if (targetIsElm) {
|
||||
appendChildren(_host, contents(contentSlot));
|
||||
removeElements(_padding || _viewport);
|
||||
removeHostDataAttr();
|
||||
} else {
|
||||
if (elementIsGenerated(_content)) {
|
||||
unwrap(_content);
|
||||
}
|
||||
if (elementIsGenerated(_viewport)) {
|
||||
unwrap(_viewport);
|
||||
}
|
||||
if (elementIsGenerated(_padding)) {
|
||||
unwrap(_padding);
|
||||
}
|
||||
removeHostDataAttr();
|
||||
removePaddingClass();
|
||||
removeViewportClass();
|
||||
removeContentClass();
|
||||
removeHostDataAttr();
|
||||
removeAttr(_viewport, dataAttributeHostOverflowX);
|
||||
removeAttr(_viewport, dataAttributeHostOverflowY);
|
||||
|
||||
if (elementIsGenerated(_content)) {
|
||||
unwrap(_content);
|
||||
}
|
||||
if (elementIsGenerated(_viewport)) {
|
||||
unwrap(_viewport);
|
||||
}
|
||||
if (elementIsGenerated(_padding)) {
|
||||
unwrap(_padding);
|
||||
}
|
||||
removePaddingClass();
|
||||
removeViewportClass();
|
||||
removeContentClass();
|
||||
});
|
||||
|
||||
if (_nativeScrollbarStyling) {
|
||||
if (_nativeScrollbarStyling && !viewportIsTarget) {
|
||||
push(destroyFns, removeClass.bind(0, _viewport, classNameViewportScrollbarStyling));
|
||||
}
|
||||
if (_viewportArrange) {
|
||||
|
||||
@@ -15,13 +15,16 @@ import {
|
||||
createCache,
|
||||
WH,
|
||||
fractionalSize,
|
||||
removeClass,
|
||||
addClass,
|
||||
hasClass,
|
||||
isFunction,
|
||||
ResizeObserverConstructor,
|
||||
} from 'support';
|
||||
import { getEnvironment } from 'environment';
|
||||
import { dataAttributeHost, classNameViewport, classNameOverflowVisible } from 'classnames';
|
||||
import {
|
||||
dataAttributeHost,
|
||||
dataValueHostOverflowVisible,
|
||||
classNameViewport,
|
||||
classNameOverflowVisible,
|
||||
} from 'classnames';
|
||||
import { createSizeObserver, SizeObserverCallbackParams } from 'observers/sizeObserver';
|
||||
import { createTrinsicObserver } from 'observers/trinsicObserver';
|
||||
import { createDOMObserver, DOMObserver } from 'observers/domObserver';
|
||||
@@ -66,22 +69,31 @@ export const createStructureSetupObservers = (
|
||||
let debounceMaxDelay: number | false | undefined;
|
||||
let contentMutationObserver: DOMObserver | undefined;
|
||||
const [, setState] = state;
|
||||
const { _host, _viewport, _content, _isTextarea } = structureSetupElements;
|
||||
const {
|
||||
_host,
|
||||
_viewport,
|
||||
_content,
|
||||
_isTextarea,
|
||||
_viewportIsTarget,
|
||||
_viewportHasClass,
|
||||
_viewportAddRemoveClass,
|
||||
} = structureSetupElements;
|
||||
const { _nativeScrollbarStyling, _flexboxGlue } = getEnvironment();
|
||||
|
||||
const [updateContentSizeCache] = createCache<WH<number>>(
|
||||
{
|
||||
_equal: equalWH,
|
||||
_initialValue: { w: 0, h: 0 },
|
||||
},
|
||||
() => {
|
||||
const has = hasClass(_viewport, classNameOverflowVisible);
|
||||
has && removeClass(_viewport, classNameOverflowVisible);
|
||||
const has = _viewportHasClass(classNameOverflowVisible, dataValueHostOverflowVisible);
|
||||
has && _viewportAddRemoveClass(classNameOverflowVisible, dataValueHostOverflowVisible);
|
||||
|
||||
const contentScroll = scrollSize(_content);
|
||||
const viewportScroll = scrollSize(_viewport);
|
||||
const fractional = fractionalSize(_viewport);
|
||||
|
||||
has && addClass(_viewport, classNameOverflowVisible);
|
||||
has && _viewportAddRemoveClass(classNameOverflowVisible, dataValueHostOverflowVisible, true);
|
||||
return {
|
||||
w: viewportScroll.w + contentScroll.w + fractional.w,
|
||||
h: viewportScroll.h + contentScroll.h + fractional.h,
|
||||
@@ -162,22 +174,29 @@ export const createStructureSetupObservers = (
|
||||
structureSetupUpdateWithDebouncedAdaptiveUpdateHints({
|
||||
_hostMutation: true,
|
||||
});
|
||||
} else {
|
||||
} else if (!_viewportIsTarget) {
|
||||
updateViewportAttrsFromHost(targetChangedAttrs);
|
||||
}
|
||||
};
|
||||
|
||||
const destroyTrinsicObserver =
|
||||
(_content || !_flexboxGlue) && createTrinsicObserver(_host, onTrinsicChanged);
|
||||
const destroySizeObserver = createSizeObserver(_host, onSizeChanged, {
|
||||
_appear: true,
|
||||
_direction: !_nativeScrollbarStyling,
|
||||
});
|
||||
const destroySizeObserver =
|
||||
!_viewportIsTarget &&
|
||||
createSizeObserver(_host, onSizeChanged, {
|
||||
_appear: true,
|
||||
_direction: !_nativeScrollbarStyling,
|
||||
});
|
||||
const [destroyHostMutationObserver] = createDOMObserver(_host, false, onHostMutation, {
|
||||
_styleChangingAttributes: baseStyleChangingAttrs,
|
||||
_attributes: baseStyleChangingAttrs.concat(viewportAttrsFromTarget),
|
||||
});
|
||||
|
||||
const viewportIsTargetResizeObserver =
|
||||
_viewportIsTarget &&
|
||||
new ResizeObserverConstructor!(onSizeChanged.bind(0, { _sizeChanged: true }));
|
||||
|
||||
viewportIsTargetResizeObserver && viewportIsTargetResizeObserver.observe(_host);
|
||||
updateViewportAttrsFromHost();
|
||||
|
||||
return [
|
||||
@@ -239,7 +258,8 @@ export const createStructureSetupObservers = (
|
||||
() => {
|
||||
contentMutationObserver && contentMutationObserver[0](); // destroy
|
||||
destroyTrinsicObserver && destroyTrinsicObserver();
|
||||
destroySizeObserver();
|
||||
destroySizeObserver && destroySizeObserver();
|
||||
viewportIsTargetResizeObserver && viewportIsTargetResizeObserver.disconnect();
|
||||
destroyHostMutationObserver();
|
||||
},
|
||||
];
|
||||
|
||||
+42
-10
@@ -14,6 +14,7 @@ import {
|
||||
noop,
|
||||
each,
|
||||
equalXY,
|
||||
attrClass,
|
||||
} from 'support';
|
||||
import { getEnvironment } from 'environment';
|
||||
import {
|
||||
@@ -21,6 +22,10 @@ import {
|
||||
classNameViewportScrollbarStyling,
|
||||
classNameOverflowVisible,
|
||||
dataAttributeHost,
|
||||
dataAttributeHostOverflowX,
|
||||
dataAttributeHostOverflowY,
|
||||
dataValueHostViewportScrollbarStyling,
|
||||
dataValueHostOverflowVisible,
|
||||
} from 'classnames';
|
||||
import type { StyleObject, OverflowStyle } from 'typings';
|
||||
import type { OverflowBehavior } from 'options';
|
||||
@@ -71,8 +76,8 @@ const getOverflowAmount = (
|
||||
const conditionalClass = (
|
||||
elm: Element | false | null | undefined,
|
||||
classNames: string,
|
||||
condition: boolean
|
||||
) => (condition ? addClass(elm, classNames) : removeClass(elm, classNames));
|
||||
add: boolean
|
||||
) => (add ? addClass(elm, classNames) : removeClass(elm, classNames));
|
||||
|
||||
const overflowIsVisible = (overflowBehavior: string) => overflowBehavior.indexOf(strVisible) === 0;
|
||||
|
||||
@@ -86,7 +91,14 @@ export const createOverflowUpdate: CreateStructureUpdateSegment = (
|
||||
state
|
||||
) => {
|
||||
const [getState, setState] = state;
|
||||
const { _host, _padding, _viewport, _viewportArrange } = structureSetupElements;
|
||||
const {
|
||||
_host,
|
||||
_padding,
|
||||
_viewport,
|
||||
_viewportArrange,
|
||||
_viewportIsTarget,
|
||||
_viewportAddRemoveClass,
|
||||
} = structureSetupElements;
|
||||
const {
|
||||
_nativeScrollbarSize,
|
||||
_flexboxGlue,
|
||||
@@ -94,7 +106,9 @@ export const createOverflowUpdate: CreateStructureUpdateSegment = (
|
||||
_nativeScrollbarIsOverlaid,
|
||||
} = getEnvironment();
|
||||
const doViewportArrange =
|
||||
!_nativeScrollbarStyling && (_nativeScrollbarIsOverlaid.x || _nativeScrollbarIsOverlaid.y);
|
||||
!_viewportIsTarget &&
|
||||
!_nativeScrollbarStyling &&
|
||||
(_nativeScrollbarIsOverlaid.x || _nativeScrollbarIsOverlaid.y);
|
||||
|
||||
const [updateSizeFraction, getCurrentSizeFraction] = createCache<WH<number>>(
|
||||
whCacheOptions,
|
||||
@@ -426,6 +440,7 @@ export const createOverflowUpdate: CreateStructureUpdateSegment = (
|
||||
_nativeScrollbarIsOverlaid.x &&
|
||||
_nativeScrollbarIsOverlaid.y;
|
||||
const adjustFlexboxGlue =
|
||||
!_viewportIsTarget &&
|
||||
!_flexboxGlue &&
|
||||
(_sizeChanged ||
|
||||
_contentMutation ||
|
||||
@@ -443,7 +458,11 @@ export const createOverflowUpdate: CreateStructureUpdateSegment = (
|
||||
let preMeasureViewportOverflowState: ViewportOverflowState | undefined;
|
||||
|
||||
if (showNativeOverlaidScrollbarsChanged && _nativeScrollbarStyling) {
|
||||
conditionalClass(_viewport, classNameViewportScrollbarStyling, !showNativeOverlaidScrollbars);
|
||||
_viewportAddRemoveClass(
|
||||
classNameViewportScrollbarStyling,
|
||||
dataValueHostViewportScrollbarStyling,
|
||||
!showNativeOverlaidScrollbars
|
||||
);
|
||||
}
|
||||
|
||||
if (adjustFlexboxGlue) {
|
||||
@@ -459,7 +478,7 @@ export const createOverflowUpdate: CreateStructureUpdateSegment = (
|
||||
showNativeOverlaidScrollbarsChanged
|
||||
) {
|
||||
if (overflowVisible) {
|
||||
removeClass(_viewport, classNameOverflowVisible);
|
||||
_viewportAddRemoveClass(classNameOverflowVisible, dataValueHostOverflowVisible, false);
|
||||
}
|
||||
|
||||
const [redoViewportArrange, undoViewportArrangeOverflowState] = undoViewportArrange(
|
||||
@@ -550,18 +569,31 @@ export const createOverflowUpdate: CreateStructureUpdateSegment = (
|
||||
sizeFraction,
|
||||
_directionIsRTL
|
||||
);
|
||||
hideNativeScrollbars(viewportOverflowState, _directionIsRTL, viewportArranged, viewportStyle);
|
||||
|
||||
if (!_viewportIsTarget) {
|
||||
hideNativeScrollbars(
|
||||
viewportOverflowState,
|
||||
_directionIsRTL,
|
||||
viewportArranged,
|
||||
viewportStyle
|
||||
);
|
||||
}
|
||||
|
||||
if (adjustFlexboxGlue) {
|
||||
fixFlexboxGlue(viewportOverflowState, _heightIntrinsic);
|
||||
}
|
||||
|
||||
style(_viewport, viewportStyle);
|
||||
if (_viewportIsTarget) {
|
||||
attr(_host, dataAttributeHostOverflowX, viewportStyle.overflowX as string);
|
||||
attr(_host, dataAttributeHostOverflowY, viewportStyle.overflowY as string);
|
||||
} else {
|
||||
style(_viewport, viewportStyle);
|
||||
}
|
||||
}
|
||||
|
||||
attr(_host, dataAttributeHost, removeClipping ? 'overflowVisible' : '');
|
||||
attrClass(_host, dataAttributeHost, dataValueHostOverflowVisible, removeClipping);
|
||||
conditionalClass(_padding, classNameOverflowVisible, removeClipping);
|
||||
conditionalClass(_viewport, classNameOverflowVisible, overflowVisible);
|
||||
!_viewportIsTarget && conditionalClass(_viewport, classNameOverflowVisible, overflowVisible);
|
||||
|
||||
const [overflowStyle, overflowStyleChanged] = updateOverflowStyleCache(
|
||||
getViewportOverflowState(showNativeOverlaidScrollbars)._overflowStyle
|
||||
|
||||
+3
-2
@@ -13,7 +13,7 @@ export const createPaddingUpdate: CreateStructureUpdateSegment = (
|
||||
state
|
||||
) => {
|
||||
const [getState, setState] = state;
|
||||
const { _host, _padding, _viewport } = structureSetupElements;
|
||||
const { _host, _padding, _viewport, _viewportIsTarget: _isSingleElm } = structureSetupElements;
|
||||
const [updatePaddingCache, currentPaddingCache] = createCache(
|
||||
{
|
||||
_equal: equalTRBL,
|
||||
@@ -34,7 +34,8 @@ export const createPaddingUpdate: CreateStructureUpdateSegment = (
|
||||
[padding, paddingChanged] = updatePaddingCache(force);
|
||||
}
|
||||
|
||||
const paddingStyleChanged = paddingAbsoluteChanged || _directionChanged || paddingChanged;
|
||||
const paddingStyleChanged =
|
||||
!_isSingleElm && (paddingAbsoluteChanged || _directionChanged || paddingChanged);
|
||||
|
||||
if (paddingStyleChanged) {
|
||||
// if there is no padding element and no scrollbar styling, paddingAbsolute isn't supported
|
||||
|
||||
@@ -57,10 +57,13 @@
|
||||
.os-viewport {
|
||||
-ms-overflow-style: scrollbar !important;
|
||||
}
|
||||
[data-overlayscrollbars~='viewportStyled'],
|
||||
.os-viewport-scrollbar-styled.os-environment,
|
||||
.os-viewport-scrollbar-styled.os-viewport {
|
||||
scrollbar-width: none !important;
|
||||
}
|
||||
[data-overlayscrollbars~='viewportStyled']::-webkit-scrollbar,
|
||||
[data-overlayscrollbars~='viewportStyled']::-webkit-scrollbar-corner,
|
||||
.os-viewport-scrollbar-styled.os-environment::-webkit-scrollbar,
|
||||
.os-viewport-scrollbar-styled.os-viewport::-webkit-scrollbar,
|
||||
.os-viewport-scrollbar-styled.os-environment::-webkit-scrollbar-corner,
|
||||
@@ -72,7 +75,7 @@
|
||||
background: transparent !important;
|
||||
}
|
||||
|
||||
[data-overlayscrollbars],
|
||||
[data-overlayscrollbars~='host'],
|
||||
.os-padding {
|
||||
position: relative;
|
||||
display: flex;
|
||||
@@ -115,6 +118,18 @@
|
||||
[data-overlayscrollbars~='overflowVisible'] {
|
||||
overflow: visible !important;
|
||||
}
|
||||
[data-overlayscrollbars-overflow-x='hidden'] {
|
||||
overflow-x: hidden !important;
|
||||
}
|
||||
[data-overlayscrollbars-overflow-x='scroll'] {
|
||||
overflow-x: scroll !important;
|
||||
}
|
||||
[data-overlayscrollbars-overflow-x='hidden'] {
|
||||
overflow-y: hidden !important;
|
||||
}
|
||||
[data-overlayscrollbars-overflow-y='scroll'] {
|
||||
overflow-y: scroll !important;
|
||||
}
|
||||
|
||||
.os-padding,
|
||||
.os-viewport {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { from } from 'support/utils/array';
|
||||
import { isUndefined } from 'support/utils/types';
|
||||
|
||||
type GetSetPropName = 'scrollLeft' | 'scrollTop' | 'value';
|
||||
@@ -5,7 +6,7 @@ type GetSetPropName = 'scrollLeft' | 'scrollTop' | 'value';
|
||||
function getSetProp(
|
||||
topLeft: GetSetPropName,
|
||||
fallback: number | string,
|
||||
elm: HTMLElement | HTMLInputElement | null,
|
||||
elm: HTMLElement | HTMLInputElement | false | null | undefined,
|
||||
value?: number | string
|
||||
): number | string | void {
|
||||
if (isUndefined(value)) {
|
||||
@@ -21,10 +22,14 @@ function getSetProp(
|
||||
* @param attrName The attribute name which shall be get or set.
|
||||
* @param value The value of the attribute which shall be set.
|
||||
*/
|
||||
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 | false | null | undefined, attrName: string): string | null;
|
||||
export function attr(
|
||||
elm: HTMLElement | null,
|
||||
elm: HTMLElement | false | null | undefined,
|
||||
attrName: string,
|
||||
value: string
|
||||
): void;
|
||||
export function attr(
|
||||
elm: HTMLElement | false | null | undefined,
|
||||
attrName: string,
|
||||
value?: string
|
||||
): string | null | void {
|
||||
@@ -34,12 +39,35 @@ export function attr(
|
||||
elm && elm.setAttribute(attrName, value);
|
||||
}
|
||||
|
||||
export const attrClass = (
|
||||
elm: HTMLElement | false | null | undefined,
|
||||
attrName: string,
|
||||
value: string,
|
||||
add?: boolean
|
||||
) => {
|
||||
const currValues = attr(elm, attrName) || '';
|
||||
const currValuesSet = new Set(currValues.split(' '));
|
||||
currValuesSet[add ? 'add' : 'delete'](value);
|
||||
|
||||
attr(elm, attrName, from(currValuesSet).join(' ').trim());
|
||||
};
|
||||
|
||||
export const hasAttrClass = (
|
||||
elm: HTMLElement | false | null | undefined,
|
||||
attrName: string,
|
||||
value: string
|
||||
) => {
|
||||
const currValues = attr(elm, attrName) || '';
|
||||
const currValuesSet = new Set(currValues.split(' '));
|
||||
return currValuesSet.has(value);
|
||||
};
|
||||
|
||||
/**
|
||||
* Removes the given attribute from the given element.
|
||||
* @param elm The element of which the attribute shall be removed.
|
||||
* @param attrName The attribute name.
|
||||
*/
|
||||
export const removeAttr = (elm: Element | null, attrName: string): void => {
|
||||
export const removeAttr = (elm: Element | false | null | undefined, attrName: string): void => {
|
||||
elm && elm.removeAttribute(attrName);
|
||||
};
|
||||
|
||||
@@ -48,9 +76,12 @@ export const removeAttr = (elm: Element | null, attrName: string): void => {
|
||||
* @param elm The element of which the scrollLeft value shall be get or set.
|
||||
* @param value The scrollLeft value which shall be set.
|
||||
*/
|
||||
export function scrollLeft(elm: HTMLElement | null): number;
|
||||
export function scrollLeft(elm: HTMLElement | null, value: number): void;
|
||||
export function scrollLeft(elm: HTMLElement | null, value?: number): number | void {
|
||||
export function scrollLeft(elm: HTMLElement | false | null | undefined): number;
|
||||
export function scrollLeft(elm: HTMLElement | false | null | undefined, value: number): void;
|
||||
export function scrollLeft(
|
||||
elm: HTMLElement | false | null | undefined,
|
||||
value?: number
|
||||
): number | void {
|
||||
return getSetProp('scrollLeft', 0, elm, value) as number;
|
||||
}
|
||||
|
||||
@@ -59,9 +90,12 @@ export function scrollLeft(elm: HTMLElement | null, value?: number): number | vo
|
||||
* @param elm The element of which the scrollTop value shall be get or set.
|
||||
* @param value The scrollTop value which shall be set.
|
||||
*/
|
||||
export function scrollTop(elm: HTMLElement | null): number;
|
||||
export function scrollTop(elm: HTMLElement | null, value: number): void;
|
||||
export function scrollTop(elm: HTMLElement | null, value?: number): number | void {
|
||||
export function scrollTop(elm: HTMLElement | false | null | undefined): number;
|
||||
export function scrollTop(elm: HTMLElement | false | null | undefined, value: number): void;
|
||||
export function scrollTop(
|
||||
elm: HTMLElement | false | null | undefined,
|
||||
value?: number
|
||||
): number | void {
|
||||
return getSetProp('scrollTop', 0, elm, value) as number;
|
||||
}
|
||||
|
||||
@@ -70,8 +104,11 @@ export function scrollTop(elm: HTMLElement | null, value?: number): number | voi
|
||||
* @param elm The input element of which the value shall be get or set.
|
||||
* @param value The value which shall be set.
|
||||
*/
|
||||
export function val(elm: HTMLInputElement | null): string;
|
||||
export function val(elm: HTMLInputElement | null, value: string): void;
|
||||
export function val(elm: HTMLInputElement | null, value?: string): string | void {
|
||||
export function val(elm: HTMLInputElement | false | null | undefined): string;
|
||||
export function val(elm: HTMLInputElement | false | null | undefined, value: string): void;
|
||||
export function val(
|
||||
elm: HTMLInputElement | false | null | undefined,
|
||||
value?: string
|
||||
): string | void {
|
||||
return getSetProp('value', '', elm, value) as string;
|
||||
}
|
||||
|
||||
@@ -5,14 +5,14 @@ import { keys } from 'support/utils/object';
|
||||
const rnothtmlwhite = /[^\x20\t\r\n\f]+/g;
|
||||
const classListAction = (
|
||||
elm: Element | false | null | undefined,
|
||||
className: string,
|
||||
className: string | false | null | undefined,
|
||||
action: (elmClassList: DOMTokenList, clazz: string) => boolean | void
|
||||
): boolean => {
|
||||
let clazz: string;
|
||||
let i = 0;
|
||||
let result = false;
|
||||
|
||||
if (elm && isString(className)) {
|
||||
if (elm && className && isString(className)) {
|
||||
const classes: Array<string> = className.match(rnothtmlwhite) || [];
|
||||
result = classes.length > 0;
|
||||
while ((clazz = classes[i++])) {
|
||||
@@ -27,15 +27,20 @@ const classListAction = (
|
||||
* @param elm The element.
|
||||
* @param className The class name(s).
|
||||
*/
|
||||
export const hasClass = (elm: Element | false | null | undefined, className: string): boolean =>
|
||||
classListAction(elm, className, (classList, clazz) => classList.contains(clazz));
|
||||
export const hasClass = (
|
||||
elm: Element | false | null | undefined,
|
||||
className: string | false | null | undefined
|
||||
): boolean => classListAction(elm, className, (classList, clazz) => classList.contains(clazz));
|
||||
|
||||
/**
|
||||
* Removes the given class name(s) from the given element.
|
||||
* @param elm The element.
|
||||
* @param className The class name(s) which shall be removed. (separated by spaces)
|
||||
*/
|
||||
export const removeClass = (elm: Element | false | null | undefined, className: string): void => {
|
||||
export const removeClass = (
|
||||
elm: Element | false | null | undefined,
|
||||
className: string | false | null | undefined
|
||||
): void => {
|
||||
classListAction(elm, className, (classList, clazz) => classList.remove(clazz));
|
||||
};
|
||||
|
||||
@@ -47,7 +52,7 @@ export const removeClass = (elm: Element | false | null | undefined, className:
|
||||
*/
|
||||
export const addClass = (
|
||||
elm: Element | false | null | undefined,
|
||||
className: string
|
||||
className: string | false | null | undefined
|
||||
): (() => void) => {
|
||||
classListAction(elm, className, (classList, clazz) => classList.add(clazz));
|
||||
return removeClass.bind(0, elm, className);
|
||||
|
||||
+10
-5
@@ -110,7 +110,7 @@ let updateCount = 0;
|
||||
const osInstance =
|
||||
// @ts-ignore
|
||||
(window.os = OverlayScrollbars(
|
||||
{ target: target!, content: useContentElement },
|
||||
{ target: target!, viewport: target!, content: useContentElement },
|
||||
{ nativeScrollbarsOverlaid: { initialize: true } },
|
||||
{
|
||||
updated() {
|
||||
@@ -255,18 +255,23 @@ selectCallbackEnv(containerDirectionSelect);
|
||||
selectCallbackEnv(containerMinMaxSelect);
|
||||
|
||||
const checkMetrics = async (checkComparison: CheckComparisonObj) => {
|
||||
const {
|
||||
host: targetHost,
|
||||
viewport: targetViewport,
|
||||
padding: targetPadding,
|
||||
} = osInstance.elements();
|
||||
const viewportIsTarget = targetHost === targetViewport;
|
||||
const { metrics: oldMetrics, updCount: oldUpdCount } = checkComparison;
|
||||
const currMetrics = getMetrics(comparison!);
|
||||
await waitForOrFailTest(async () => {
|
||||
if (!metricsDimensionsEqual(oldMetrics, currMetrics)) {
|
||||
if (!viewportIsTarget && !metricsDimensionsEqual(oldMetrics, currMetrics)) {
|
||||
should.ok(updateCount > oldUpdCount, 'Update should have been triggered.');
|
||||
}
|
||||
});
|
||||
await waitForOrFailTest(async () => {
|
||||
const comparisonMetrics = getMetrics(comparison!);
|
||||
const targetMetrics = getMetrics(target!);
|
||||
const targetViewport = osInstance.elements().viewport;
|
||||
const targetPadding = osInstance.elements().padding;
|
||||
|
||||
const { x: overflowOptionX, y: overflowOptionY } = osInstance.options().overflow;
|
||||
const overflowOptionXVisible = isVisibleOverflow(overflowOptionX);
|
||||
const overflowOptionYVisible = isVisibleOverflow(overflowOptionY);
|
||||
@@ -446,7 +451,7 @@ const checkMetrics = async (checkComparison: CheckComparisonObj) => {
|
||||
'visible',
|
||||
'Host Overflow should be visible with visible overflowing content.'
|
||||
);
|
||||
} else {
|
||||
} else if (!viewportIsTarget) {
|
||||
should.equal(
|
||||
hostOverflowStyle,
|
||||
'hidden',
|
||||
|
||||
@@ -89,13 +89,14 @@ body {
|
||||
}
|
||||
}
|
||||
|
||||
#target::after {
|
||||
#target[data-overlayscrollbars~='host']::after {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#target[data-overlayscrollbars~='viewport'],
|
||||
#comparison {
|
||||
overflow: hidden;
|
||||
z-index: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.resize {
|
||||
@@ -152,7 +153,7 @@ body {
|
||||
width: auto;
|
||||
display: inline-block;
|
||||
}
|
||||
.widthAuto > #target {
|
||||
.widthAuto > #target[data-overlayscrollbars~='host'] {
|
||||
display: inline-flex;
|
||||
}
|
||||
.widthHundred > .container,
|
||||
|
||||
+15
-16
@@ -62,23 +62,22 @@ type RemoveEventListener<NameArgsMap extends Record<string, any>> = <Name extend
|
||||
type InitialEventListeners<NameArgsMap extends Record<string, any>> = {
|
||||
[K in Extract<keyof NameArgsMap, string>]?: EventListenerGroup<NameArgsMap, K>;
|
||||
};
|
||||
type ResizeBehavior = "none" | "both" | "horizontal" | "vertical";
|
||||
type OverflowBehavior = "hidden" | "scroll" | "visible" | "visible-hidden" | "visible-scroll";
|
||||
type VisibilityBehavior = "visible" | "hidden" | "auto";
|
||||
type AutoHideBehavior = "never" | "scroll" | "leave" | "move";
|
||||
interface OSOptions {
|
||||
resize: ResizeBehavior;
|
||||
paddingAbsolute: boolean;
|
||||
updating: {
|
||||
elementEvents: Array<[
|
||||
string,
|
||||
string
|
||||
elementSelector: string,
|
||||
eventNames: string
|
||||
]> | null;
|
||||
attributes: string[] | null;
|
||||
debounce: number | [
|
||||
number,
|
||||
number
|
||||
] | null;
|
||||
debounce: [
|
||||
timeout: number,
|
||||
maxWait: number
|
||||
] | number | null; // (if tuple: [timeout: 0, maxWait: 33], if number: [timeout: number, maxWait: false]) debounce for content Changes
|
||||
ignoreMutation: ((mutation: MutationRecord) => any) | null;
|
||||
};
|
||||
overflow: {
|
||||
x: OverflowBehavior;
|
||||
@@ -92,18 +91,10 @@ interface OSOptions {
|
||||
clickScroll: boolean;
|
||||
touch: boolean;
|
||||
};
|
||||
textarea: {
|
||||
dynWidth: boolean;
|
||||
dynHeight: boolean;
|
||||
inheritedAttrs: string | Array<string> | null;
|
||||
};
|
||||
nativeScrollbarsOverlaid: {
|
||||
show: boolean;
|
||||
initialize: boolean;
|
||||
};
|
||||
callbacks: {
|
||||
onUpdated: (() => any) | null;
|
||||
};
|
||||
}
|
||||
type StructureInitializationStrategyElementFn<T> = ((target: OSTargetElement) => HTMLElement | T) | T;
|
||||
type ScrollbarsInitializationStrategyElementFn<T> = ((target: OSTargetElement, host: HTMLElement, viewport: HTMLElement) => HTMLElement | T) | T;
|
||||
@@ -203,12 +194,20 @@ interface OverlayScrollbarsState {
|
||||
overflowStyle: XY<OverflowStyle>;
|
||||
hasOverflow: XY<boolean>;
|
||||
}
|
||||
interface OverlayScrollbarsElements {
|
||||
target: HTMLElement;
|
||||
host: HTMLElement;
|
||||
padding: HTMLElement;
|
||||
viewport: HTMLElement;
|
||||
content: HTMLElement;
|
||||
}
|
||||
interface OverlayScrollbars {
|
||||
options(): OSOptions;
|
||||
options(newOptions?: PartialOptions<OSOptions>): OSOptions;
|
||||
update(force?: boolean): void;
|
||||
destroy(): void;
|
||||
state(): OverlayScrollbarsState;
|
||||
elements(): OverlayScrollbarsElements;
|
||||
on: AddOSEventListener;
|
||||
off: RemoveOSEventListener;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user