mirror of
https://github.com/tenrok/OverlayScrollbars.git
synced 2026-05-26 17:44:07 +03:00
implement nativeScrollbarsOverlaid.show option
This commit is contained in:
@@ -1,9 +1,24 @@
|
||||
import { createCache, WH, XY, equalXY, style, scrollSize, offsetSize, CacheValues, equalWH, scrollLeft, scrollTop } from 'support';
|
||||
import {
|
||||
createCache,
|
||||
WH,
|
||||
XY,
|
||||
equalXY,
|
||||
style,
|
||||
scrollSize,
|
||||
offsetSize,
|
||||
CacheValues,
|
||||
equalWH,
|
||||
scrollLeft,
|
||||
scrollTop,
|
||||
addClass,
|
||||
removeClass,
|
||||
} from 'support';
|
||||
import { createLifecycleUpdateFunction, LifecycleUpdateFunction } from 'lifecycles/lifecycleUpdateFunction';
|
||||
import { LifecycleHub } from 'lifecycles/lifecycleHub';
|
||||
import { getEnvironment } from 'environment';
|
||||
import { OverflowBehavior } from 'options';
|
||||
import { PlainObject } from 'typings';
|
||||
import { classNameViewportScrollbarStyling } from 'classnames';
|
||||
|
||||
const overlaidScrollbarsHideOffset = 42;
|
||||
const overlaidScrollbarsHideBorderStyle = `${overlaidScrollbarsHideOffset}px solid transparent`;
|
||||
@@ -48,75 +63,92 @@ export const createOverflowLifecycle = (lifecycleHub: LifecycleHub): LifecycleUp
|
||||
|
||||
const hideNativeScrollbars = (
|
||||
contentScrollSize: WH<number>,
|
||||
adjustFlexboxGlue: boolean,
|
||||
showNativeOverlaidScrollbars: boolean,
|
||||
directionIsRTL: boolean,
|
||||
heightIntrinsic: boolean,
|
||||
viewportStyleObj: PlainObject,
|
||||
contentStyleObj: PlainObject
|
||||
) => {
|
||||
const { _nativeScrollbarSize, _nativeScrollbarIsOverlaid, _nativeScrollbarStyling } = getEnvironment();
|
||||
const { x: overlaidX, y: overlaidY } = _nativeScrollbarIsOverlaid;
|
||||
const scrollX = viewportStyleObj.overflowX === 'scroll';
|
||||
const scrollY = viewportStyleObj.overflowY === 'scroll';
|
||||
const horizontalMarginKey = directionIsRTL ? 'marginLeft' : 'marginRight';
|
||||
const horizontalBorderKey = directionIsRTL ? 'borderLeft' : 'borderRight';
|
||||
const scrollXY = scrollY && scrollX;
|
||||
const hideOffset = _content ? overlaidScrollbarsHideOffset : 0;
|
||||
const offset = {
|
||||
x: _nativeScrollbarIsOverlaid.x ? hideOffset : _nativeScrollbarSize.x,
|
||||
y: _nativeScrollbarIsOverlaid.y ? hideOffset : _nativeScrollbarSize.y,
|
||||
const overlaidHideOffset = _content && !showNativeOverlaidScrollbars ? overlaidScrollbarsHideOffset : 0;
|
||||
const scrollbarsHideOffset = {
|
||||
x: overlaidX ? overlaidHideOffset : _nativeScrollbarSize.x,
|
||||
y: overlaidY ? overlaidHideOffset : _nativeScrollbarSize.y,
|
||||
};
|
||||
|
||||
if (!_nativeScrollbarStyling) {
|
||||
if (scrollX) {
|
||||
viewportStyleObj.marginBottom = `-${offset.x}px`;
|
||||
viewportStyleObj.marginBottom = `-${scrollbarsHideOffset.x}px`;
|
||||
|
||||
if (_nativeScrollbarIsOverlaid.x && hideOffset) {
|
||||
contentStyleObj.borderBottom = overlaidScrollbarsHideBorderStyle;
|
||||
}
|
||||
contentStyleObj.borderBottom = overlaidX && overlaidHideOffset ? overlaidScrollbarsHideBorderStyle : '';
|
||||
}
|
||||
if (scrollY) {
|
||||
viewportStyleObj.maxWidth = `calc(100% + ${offset.y}px)`;
|
||||
viewportStyleObj[horizontalMarginKey] = `-${offset.y}px`;
|
||||
viewportStyleObj.maxWidth = `calc(100% + ${scrollbarsHideOffset.y}px)`;
|
||||
viewportStyleObj[horizontalMarginKey] = `-${scrollbarsHideOffset.y}px`;
|
||||
|
||||
if (_nativeScrollbarIsOverlaid.y && hideOffset) {
|
||||
contentStyleObj[horizontalBorderKey] = overlaidScrollbarsHideBorderStyle;
|
||||
}
|
||||
contentStyleObj[horizontalBorderKey] = overlaidY && overlaidHideOffset ? overlaidScrollbarsHideBorderStyle : '';
|
||||
}
|
||||
|
||||
if (hideOffset && (offset.x || offset.y)) {
|
||||
if (_contentArrange) {
|
||||
const condition = scrollXY && !showNativeOverlaidScrollbars;
|
||||
style(_contentArrange, {
|
||||
width: scrollXY ? `${hideOffset + contentScrollSize.w}px` : '',
|
||||
height: scrollXY ? `${hideOffset + contentScrollSize.h}px` : '',
|
||||
width: condition ? `${overlaidHideOffset + contentScrollSize.w}px` : '',
|
||||
height: condition ? `${overlaidHideOffset + contentScrollSize.h}px` : '',
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (adjustFlexboxGlue) {
|
||||
const offsetLeft = scrollLeft(_viewport);
|
||||
const offsetTop = scrollTop(_viewport);
|
||||
return {
|
||||
_scrollbarsHideOffset: scrollbarsHideOffset,
|
||||
_scroll: {
|
||||
x: scrollX,
|
||||
y: scrollY,
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
const setFlexboxGlueStyle = (heightIntrinsic: boolean, scrollX: boolean, scrollbarsHideOffsetX: number) => {
|
||||
const offsetLeft = scrollLeft(_viewport);
|
||||
const offsetTop = scrollTop(_viewport);
|
||||
|
||||
style(_viewport, {
|
||||
maxHeight: '',
|
||||
});
|
||||
|
||||
if (heightIntrinsic) {
|
||||
style(_viewport, {
|
||||
maxHeight: '',
|
||||
maxHeight: `${_host.clientHeight + (scrollX ? scrollbarsHideOffsetX : 0)}px`,
|
||||
});
|
||||
|
||||
if (heightIntrinsic) {
|
||||
style(_viewport, {
|
||||
maxHeight: `${_host.clientHeight + (scrollX ? offset.x : 0)}px`,
|
||||
});
|
||||
}
|
||||
|
||||
scrollLeft(_viewport, offsetLeft);
|
||||
scrollTop(_viewport, offsetTop);
|
||||
}
|
||||
|
||||
scrollLeft(_viewport, offsetLeft);
|
||||
scrollTop(_viewport, offsetTop);
|
||||
};
|
||||
|
||||
return createLifecycleUpdateFunction(lifecycleHub, (force, updateHints, checkOption) => {
|
||||
const { _directionIsRTL, _heightIntrinsic, _sizeChanged, _hostMutation, _contentMutation } = updateHints;
|
||||
const { _flexboxGlue, _nativeScrollbarStyling } = getEnvironment();
|
||||
const adjustFlexboxGlue = !_flexboxGlue && (_sizeChanged || _contentMutation || _hostMutation);
|
||||
const { _flexboxGlue, _nativeScrollbarStyling, _nativeScrollbarIsOverlaid } = getEnvironment();
|
||||
const { _value: showNativeOverlaidScrollbarsOption, _changed: showNativeOverlaidScrollbarsChanged } = checkOption<boolean>(
|
||||
'nativeScrollbarsOverlaid.show'
|
||||
);
|
||||
const adjustFlexboxGlue = !_flexboxGlue && (_sizeChanged || _contentMutation || _hostMutation || showNativeOverlaidScrollbarsChanged);
|
||||
const showNativeOverlaidScrollbars = showNativeOverlaidScrollbarsOption && _nativeScrollbarIsOverlaid.x && _nativeScrollbarIsOverlaid.y;
|
||||
let overflowAmuntCache: CacheValues<XY<number>> = getCurrentOverflowAmountCache();
|
||||
let contentScrollSizeCache: CacheValues<WH<number>> = getCurrentContentScrollSizeCache();
|
||||
|
||||
if (showNativeOverlaidScrollbarsChanged && _nativeScrollbarStyling) {
|
||||
if (showNativeOverlaidScrollbars) {
|
||||
removeClass(_viewport, classNameViewportScrollbarStyling);
|
||||
} else {
|
||||
addClass(_viewport, classNameViewportScrollbarStyling);
|
||||
}
|
||||
}
|
||||
|
||||
if (_sizeChanged || _contentMutation) {
|
||||
const viewportOffsetSize = offsetSize(_padding);
|
||||
const contentClientSize = offsetSize(_content || _viewport);
|
||||
@@ -145,7 +177,14 @@ export const createOverflowLifecycle = (lifecycleHub: LifecycleHub): LifecycleUp
|
||||
}>('overflow');
|
||||
const adjustDirection = directionChanged && !_nativeScrollbarStyling;
|
||||
|
||||
if (contentScrollSizeChanged || overflowAmountChanged || overflowChanged || adjustDirection || adjustFlexboxGlue) {
|
||||
if (
|
||||
contentScrollSizeChanged ||
|
||||
overflowAmountChanged ||
|
||||
overflowChanged ||
|
||||
showNativeOverlaidScrollbarsChanged ||
|
||||
adjustDirection ||
|
||||
adjustFlexboxGlue
|
||||
) {
|
||||
const viewportStyle: PlainObject = {
|
||||
overflowY: '',
|
||||
overflowX: '',
|
||||
@@ -172,7 +211,17 @@ export const createOverflowLifecycle = (lifecycleHub: LifecycleHub): LifecycleUp
|
||||
viewportStyle.overflowY = yVisibleBehavior;
|
||||
}
|
||||
|
||||
hideNativeScrollbars(contentScrollSize!, adjustFlexboxGlue, directionIsRTL!, !!_heightIntrinsic._value, viewportStyle, contentStyle);
|
||||
const { _scrollbarsHideOffset, _scroll } = hideNativeScrollbars(
|
||||
contentScrollSize!,
|
||||
showNativeOverlaidScrollbars,
|
||||
directionIsRTL!,
|
||||
viewportStyle,
|
||||
contentStyle
|
||||
);
|
||||
|
||||
if (adjustFlexboxGlue) {
|
||||
setFlexboxGlueStyle(!!_heightIntrinsic._value, _scroll.x, _scrollbarsHideOffset.x);
|
||||
}
|
||||
|
||||
// TODO: enlargen viewport if div too small for firefox scrollbar hiding behavior
|
||||
// TODO: Test without content
|
||||
|
||||
@@ -13,7 +13,7 @@ import {
|
||||
scrollSize,
|
||||
offsetSize,
|
||||
} from 'support';
|
||||
import { createLifecycleUpdateFunction, Lifecycle } from 'lifecycles/lifecycleUpdateFunction';
|
||||
import { createLifecycleUpdateFunction } from 'lifecycles/lifecycleUpdateFunction';
|
||||
import { LifecycleHub } from 'lifecycles/lifecycleHub';
|
||||
import { getEnvironment, Environment } from 'environment';
|
||||
|
||||
|
||||
@@ -162,18 +162,13 @@ export const createStructureSetup = (target: OSTarget | OSTargetObject): Structu
|
||||
|
||||
const { _nativeScrollbarStyling, _nativeScrollbarIsOverlaid } = getEnvironment();
|
||||
if (_nativeScrollbarStyling) {
|
||||
addClass(_viewport, classNameViewportScrollbarStyling);
|
||||
push(destroyFns, () => {
|
||||
removeClass(_viewport, classNameViewportScrollbarStyling);
|
||||
});
|
||||
push(destroyFns, removeClass.bind(0, _viewport, classNameViewportScrollbarStyling));
|
||||
} else if (_nativeScrollbarIsOverlaid.x || _nativeScrollbarIsOverlaid.y) {
|
||||
if (obj._content) {
|
||||
const contentArrangeElm = createDiv(classNameContentArrange);
|
||||
|
||||
prependChildren(_viewport, contentArrangeElm);
|
||||
push(destroyFns, () => {
|
||||
removeElements(contentArrangeElm);
|
||||
});
|
||||
push(destroyFns, removeElements.bind(0, contentArrangeElm));
|
||||
|
||||
obj._contentArrange = contentArrangeElm;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user