From 718249c6be6d57bbe64244030e0dc342a2c8678e Mon Sep 17 00:00:00 2001 From: Rene Date: Sun, 28 Mar 2021 22:54:38 +0200 Subject: [PATCH] implement nativeScrollbarsOverlaid.show option --- .../src/lifecycles/overflowLifecycle.ts | 121 ++++++++++++------ .../src/lifecycles/structureLifecycle.ts | 2 +- .../src/setups/structureSetup.ts | 9 +- 3 files changed, 88 insertions(+), 44 deletions(-) diff --git a/packages/overlayscrollbars/src/lifecycles/overflowLifecycle.ts b/packages/overlayscrollbars/src/lifecycles/overflowLifecycle.ts index 9cdcd82..be24021 100644 --- a/packages/overlayscrollbars/src/lifecycles/overflowLifecycle.ts +++ b/packages/overlayscrollbars/src/lifecycles/overflowLifecycle.ts @@ -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, - 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( + 'nativeScrollbarsOverlaid.show' + ); + const adjustFlexboxGlue = !_flexboxGlue && (_sizeChanged || _contentMutation || _hostMutation || showNativeOverlaidScrollbarsChanged); + const showNativeOverlaidScrollbars = showNativeOverlaidScrollbarsOption && _nativeScrollbarIsOverlaid.x && _nativeScrollbarIsOverlaid.y; let overflowAmuntCache: CacheValues> = getCurrentOverflowAmountCache(); let contentScrollSizeCache: CacheValues> = 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 diff --git a/packages/overlayscrollbars/src/lifecycles/structureLifecycle.ts b/packages/overlayscrollbars/src/lifecycles/structureLifecycle.ts index 40db949..d68cd34 100644 --- a/packages/overlayscrollbars/src/lifecycles/structureLifecycle.ts +++ b/packages/overlayscrollbars/src/lifecycles/structureLifecycle.ts @@ -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'; diff --git a/packages/overlayscrollbars/src/setups/structureSetup.ts b/packages/overlayscrollbars/src/setups/structureSetup.ts index c1019f9..1efcb01 100644 --- a/packages/overlayscrollbars/src/setups/structureSetup.ts +++ b/packages/overlayscrollbars/src/setups/structureSetup.ts @@ -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; }