mirror of
https://github.com/tenrok/OverlayScrollbars.git
synced 2026-06-07 12:22:28 +03:00
padding Lifecycle
This commit is contained in:
@@ -123,7 +123,7 @@ const createEnvironment = (): Environment => {
|
||||
|
||||
const onChangedListener: Set<OnEnvironmentChanged> = new Set();
|
||||
const nativeScrollbarSize = getNativeScrollbarSize(body, envElm);
|
||||
const nativeScrollbarStyling = false; //getNativeScrollbarStyling(envElm); TODO: Re-enable
|
||||
const nativeScrollbarStyling = false; //getNativeScrollbarStyling(envElm); TODO: Re - enable;
|
||||
const nativeScrollbarIsOverlaid = {
|
||||
x: nativeScrollbarSize.x === 0,
|
||||
y: nativeScrollbarSize.y === 0,
|
||||
|
||||
@@ -1,13 +1,39 @@
|
||||
import { CacheValues, each, push, validateOptions, assignDeep, isEmptyObject, OptionsValidated } from 'support';
|
||||
import { TRBL, CacheValues, each, push, OptionsValidated, hasOwnProperty } from 'support';
|
||||
import { Options } from 'options';
|
||||
import { getEnvironment, Environment } from 'environment';
|
||||
import { getEnvironment } from 'environment';
|
||||
import { StructureSetup } from 'setups/structureSetup';
|
||||
import { createStructureLifecycle } from 'lifecycles/structureLifecycle';
|
||||
import { createPaddingLifecycle } from 'lifecycles/paddingLifecycle';
|
||||
import { createOverflowLifecycle } from 'lifecycles/overflowLifecycle';
|
||||
import { LifecycleUpdateFunction, LifecycleUpdateHints } from 'lifecycles/lifecycleUpdateFunction';
|
||||
import { createSizeObserver } from 'observers/sizeObserver';
|
||||
import { createTrinsicObserver } from 'observers/trinsicObserver';
|
||||
import { createDOMObserver } from 'observers/domObserver';
|
||||
import { StyleObject } from 'typings';
|
||||
|
||||
export type LifecycleCheckOption = <T>(path: string) => LifecycleOptionInfo<T>;
|
||||
|
||||
export interface LifecycleOptionInfo<T> {
|
||||
readonly _value: T;
|
||||
_changed: boolean;
|
||||
}
|
||||
|
||||
export interface LifecycleAdaptiveUpdateHints {
|
||||
_sizeChanged: boolean;
|
||||
_hostMutation: boolean;
|
||||
_contentMutation: boolean;
|
||||
_paddingStyleChanged: boolean;
|
||||
}
|
||||
|
||||
export interface LifecycleUpdateHints extends LifecycleAdaptiveUpdateHints {
|
||||
_directionIsRTL: CacheValues<boolean>;
|
||||
_heightIntrinsic: CacheValues<boolean>;
|
||||
}
|
||||
|
||||
export type Lifecycle = (
|
||||
updateHints: LifecycleUpdateHints,
|
||||
checkOption: LifecycleCheckOption,
|
||||
force: boolean
|
||||
) => Partial<LifecycleAdaptiveUpdateHints> | void;
|
||||
|
||||
export interface LifecycleHubInstance {
|
||||
_update(changedOptions?: OptionsValidated<Options> | null, force?: boolean): void;
|
||||
@@ -17,9 +43,23 @@ export interface LifecycleHubInstance {
|
||||
export interface LifecycleHub {
|
||||
_options: Options;
|
||||
_structureSetup: StructureSetup;
|
||||
_getPadding(): TRBL;
|
||||
_setPadding(newPadding?: TRBL | null): void;
|
||||
_getPaddingStyle(): StyleObject;
|
||||
_setPaddingStyle(newPaddingStlye?: StyleObject | null): void;
|
||||
}
|
||||
|
||||
const getPropByPath = <T>(obj: any, path: string): T =>
|
||||
obj && path.split('.').reduce((o, prop) => (o && hasOwnProperty(o, prop) ? o[prop] : undefined), obj);
|
||||
|
||||
const attrs = ['id', 'class', 'style', 'open'];
|
||||
const paddingFallback: TRBL = { t: 0, r: 0, b: 0, l: 0 };
|
||||
const viewportPaddingStyleFallback: StyleObject = {
|
||||
marginTop: 0,
|
||||
marginRight: 0,
|
||||
marginBottom: 0,
|
||||
marginLeft: 0,
|
||||
};
|
||||
const directionIsRTLCacheValuesFallback: CacheValues<boolean> = {
|
||||
_value: false,
|
||||
_previous: false,
|
||||
@@ -32,6 +72,8 @@ const heightIntrinsicCacheValuesFallback: CacheValues<boolean> = {
|
||||
};
|
||||
|
||||
export const createLifecycleHub = (options: Options, structureSetup: StructureSetup): LifecycleHubInstance => {
|
||||
let padding = paddingFallback;
|
||||
let viewportPaddingStyle = viewportPaddingStyleFallback;
|
||||
const { _host, _viewport, _content } = structureSetup._targetObj;
|
||||
const {
|
||||
_nativeScrollbarStyling,
|
||||
@@ -39,39 +81,66 @@ export const createLifecycleHub = (options: Options, structureSetup: StructureSe
|
||||
_addListener: addEnvironmentListener,
|
||||
_removeListener: removeEnvironmentListener,
|
||||
} = getEnvironment();
|
||||
const lifecycles: LifecycleUpdateFunction[] = [];
|
||||
const lifecycles: Lifecycle[] = [];
|
||||
const instance: LifecycleHub = {
|
||||
_options: options,
|
||||
_structureSetup: structureSetup,
|
||||
_getPadding: () => padding,
|
||||
_setPadding(newPadding) {
|
||||
padding = newPadding || paddingFallback;
|
||||
},
|
||||
_getPaddingStyle: () => viewportPaddingStyle,
|
||||
_setPaddingStyle(newPaddingStlye: StyleObject) {
|
||||
viewportPaddingStyle = newPaddingStlye || viewportPaddingStyleFallback;
|
||||
},
|
||||
};
|
||||
|
||||
// push(lifecycles, createStructureLifecycle(instance));
|
||||
push(lifecycles, createPaddingLifecycle(instance));
|
||||
push(lifecycles, createOverflowLifecycle(instance));
|
||||
|
||||
const runLifecycles = (updateHints?: Partial<LifecycleUpdateHints> | null, changedOptions?: OptionsValidated<Options> | null, force?: boolean) => {
|
||||
let { _directionIsRTL, _heightIntrinsic, _sizeChanged = force || false, _hostMutation = force || false, _contentMutation = force || false } =
|
||||
updateHints || {};
|
||||
let {
|
||||
_directionIsRTL,
|
||||
_heightIntrinsic,
|
||||
_sizeChanged = force || false,
|
||||
_hostMutation = force || false,
|
||||
_contentMutation = force || false,
|
||||
_paddingStyleChanged = force || false,
|
||||
} = updateHints || {};
|
||||
const finalDirectionIsRTL =
|
||||
_directionIsRTL || (sizeObserver ? sizeObserver._getCurrentCacheValues(force)._directionIsRTL : directionIsRTLCacheValuesFallback);
|
||||
const finalHeightIntrinsic =
|
||||
_heightIntrinsic || (trinsicObserver ? trinsicObserver._getCurrentCacheValues(force)._heightIntrinsic : heightIntrinsicCacheValuesFallback);
|
||||
const checkOption: LifecycleCheckOption = (path) => ({
|
||||
_value: getPropByPath(options, path),
|
||||
_changed: force || getPropByPath(changedOptions, path) !== undefined,
|
||||
});
|
||||
|
||||
each(lifecycles, (lifecycle) => {
|
||||
const { _sizeChanged: adaptiveSizeChanged, _hostMutation: adaptiveHostMutation, _contentMutation: adaptiveContentMutation } = lifecycle(
|
||||
{
|
||||
_directionIsRTL: finalDirectionIsRTL,
|
||||
_heightIntrinsic: finalHeightIntrinsic,
|
||||
_sizeChanged,
|
||||
_hostMutation,
|
||||
_contentMutation,
|
||||
},
|
||||
changedOptions,
|
||||
force
|
||||
);
|
||||
const {
|
||||
_sizeChanged: adaptiveSizeChanged,
|
||||
_hostMutation: adaptiveHostMutation,
|
||||
_contentMutation: adaptiveContentMutation,
|
||||
_paddingStyleChanged: adaptivePaddingStyleChanged,
|
||||
} =
|
||||
lifecycle(
|
||||
{
|
||||
_directionIsRTL: finalDirectionIsRTL,
|
||||
_heightIntrinsic: finalHeightIntrinsic,
|
||||
_sizeChanged,
|
||||
_hostMutation,
|
||||
_contentMutation,
|
||||
_paddingStyleChanged,
|
||||
},
|
||||
checkOption,
|
||||
!!force
|
||||
) || {};
|
||||
|
||||
_sizeChanged = adaptiveSizeChanged || _sizeChanged;
|
||||
_hostMutation = adaptiveHostMutation || _hostMutation;
|
||||
_contentMutation = adaptiveContentMutation || _contentMutation;
|
||||
_paddingStyleChanged = adaptivePaddingStyleChanged || _paddingStyleChanged;
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
@@ -1,52 +0,0 @@
|
||||
import { CacheValues, OptionsValidated, hasOwnProperty } from 'support';
|
||||
import { Options } from 'options';
|
||||
import { LifecycleHub } from 'lifecycles/lifecycleHub';
|
||||
|
||||
export interface LifecycleAdaptiveUpdateHints {
|
||||
_sizeChanged: boolean;
|
||||
_hostMutation: boolean;
|
||||
_contentMutation: boolean;
|
||||
}
|
||||
|
||||
export interface LifecycleUpdateHints extends LifecycleAdaptiveUpdateHints {
|
||||
_directionIsRTL: CacheValues<boolean>;
|
||||
_heightIntrinsic: CacheValues<boolean>;
|
||||
}
|
||||
|
||||
export type LifecycleUpdateFunction = (
|
||||
updateHints: LifecycleUpdateHints,
|
||||
changedOptions?: OptionsValidated<Options> | null,
|
||||
force?: boolean
|
||||
) => Partial<LifecycleAdaptiveUpdateHints>;
|
||||
|
||||
export interface LifecycleOptionInfo<T> {
|
||||
readonly _value: T;
|
||||
_changed: boolean;
|
||||
}
|
||||
|
||||
export type LifecycleCheckOption = <T>(path: string) => LifecycleOptionInfo<T>;
|
||||
|
||||
const getPropByPath = <T>(obj: any, path: string): T =>
|
||||
obj && path.split('.').reduce((o, prop) => (o && hasOwnProperty(o, prop) ? o[prop] : undefined), obj);
|
||||
|
||||
/**
|
||||
* Creates a update function for a lifecycle.
|
||||
* @param lifecycleHub The LifecycleHub which is managing this lifecylce.
|
||||
* @param updateFunction The update function where cache and options updates are handled. Has two arguments which are the changedOptions and the changedCache objects.
|
||||
*/
|
||||
export const createLifecycleUpdateFunction = (
|
||||
lifecycleHub: LifecycleHub,
|
||||
updateFunction: (
|
||||
force: boolean,
|
||||
updateHints: LifecycleUpdateHints,
|
||||
checkOption: LifecycleCheckOption
|
||||
) => Partial<LifecycleAdaptiveUpdateHints> | void
|
||||
): LifecycleUpdateFunction => {
|
||||
return (updateHints: LifecycleUpdateHints, changedOptions?: OptionsValidated<Options> | null, force?: boolean) => {
|
||||
const checkOption: LifecycleCheckOption = (path) => ({
|
||||
_value: getPropByPath(lifecycleHub._options, path),
|
||||
_changed: force || getPropByPath(changedOptions, path) !== undefined,
|
||||
});
|
||||
return updateFunction(!!force, updateHints, checkOption) || {};
|
||||
};
|
||||
};
|
||||
@@ -5,19 +5,18 @@ import {
|
||||
equalXY,
|
||||
style,
|
||||
scrollSize,
|
||||
offsetSize,
|
||||
CacheValues,
|
||||
equalWH,
|
||||
scrollLeft,
|
||||
scrollTop,
|
||||
addClass,
|
||||
removeClass,
|
||||
clientSize,
|
||||
} from 'support';
|
||||
import { createLifecycleUpdateFunction, LifecycleUpdateFunction } from 'lifecycles/lifecycleUpdateFunction';
|
||||
import { LifecycleHub } from 'lifecycles/lifecycleHub';
|
||||
import { LifecycleHub, Lifecycle } from 'lifecycles/lifecycleHub';
|
||||
import { getEnvironment } from 'environment';
|
||||
import { OverflowBehavior } from 'options';
|
||||
import { PlainObject } from 'typings';
|
||||
import { StyleObject } from 'typings';
|
||||
import { classNameViewportScrollbarStyling } from 'classnames';
|
||||
|
||||
const overlaidScrollbarsHideOffset = 42;
|
||||
@@ -27,8 +26,9 @@ interface OverflowAmountCacheContext {
|
||||
_viewportSize: WH<number>;
|
||||
}
|
||||
|
||||
export const createOverflowLifecycle = (lifecycleHub: LifecycleHub): LifecycleUpdateFunction => {
|
||||
const { _host, _padding, _viewport, _content, _contentArrange } = lifecycleHub._structureSetup._targetObj;
|
||||
export const createOverflowLifecycle = (lifecycleHub: LifecycleHub): Lifecycle => {
|
||||
const { _structureSetup, _getPaddingStyle } = lifecycleHub;
|
||||
const { _host, _padding, _viewport, _content, _contentArrange } = _structureSetup._targetObj;
|
||||
const { _update: updateContentScrollSizeCache, _current: getCurrentContentScrollSizeCache } = createCache<WH<number>>(
|
||||
() => scrollSize(_content || _viewport),
|
||||
{ _equal: equalWH }
|
||||
@@ -41,7 +41,7 @@ export const createOverflowLifecycle = (lifecycleHub: LifecycleHub): LifecycleUp
|
||||
{ _equal: equalXY }
|
||||
);
|
||||
|
||||
const setViewportOverflowStyle = (horizontal: boolean, amount: number, behavior: OverflowBehavior, styleObj: PlainObject) => {
|
||||
const setViewportOverflowStyle = (horizontal: boolean, amount: number, behavior: OverflowBehavior, styleObj: StyleObject) => {
|
||||
const overflowKey = horizontal ? 'overflowX' : 'overflowY';
|
||||
//const scrollMaxKey = horizontal ? 'scrollLeftMax' : 'scrollTopMax';
|
||||
const behaviorIsScroll = behavior === 'scroll';
|
||||
@@ -65,40 +65,43 @@ export const createOverflowLifecycle = (lifecycleHub: LifecycleHub): LifecycleUp
|
||||
contentScrollSize: WH<number>,
|
||||
showNativeOverlaidScrollbars: boolean,
|
||||
directionIsRTL: boolean,
|
||||
viewportStyleObj: PlainObject,
|
||||
contentStyleObj: PlainObject
|
||||
viewportStyleObj: StyleObject,
|
||||
contentStyleObj: StyleObject
|
||||
) => {
|
||||
const { _nativeScrollbarSize, _nativeScrollbarIsOverlaid, _nativeScrollbarStyling } = getEnvironment();
|
||||
const { x: overlaidX, y: overlaidY } = _nativeScrollbarIsOverlaid;
|
||||
const paddingStyle = _getPaddingStyle();
|
||||
const scrollX = viewportStyleObj.overflowX === 'scroll';
|
||||
const scrollY = viewportStyleObj.overflowY === 'scroll';
|
||||
const horizontalMarginKey = directionIsRTL ? 'marginLeft' : 'marginRight';
|
||||
const horizontalBorderKey = directionIsRTL ? 'borderLeft' : 'borderRight';
|
||||
const overlaidHideOffset = _content && !showNativeOverlaidScrollbars ? overlaidScrollbarsHideOffset : 0;
|
||||
const horizontalPaddingValue = paddingStyle[horizontalMarginKey] as number;
|
||||
const overlaidHideOffset = _content && !_nativeScrollbarStyling && !showNativeOverlaidScrollbars ? overlaidScrollbarsHideOffset : 0;
|
||||
const scrollbarsHideOffset = {
|
||||
x: overlaidX ? overlaidHideOffset : _nativeScrollbarSize.x,
|
||||
y: overlaidY ? overlaidHideOffset : _nativeScrollbarSize.y,
|
||||
x: scrollX && !_nativeScrollbarStyling ? (overlaidX ? overlaidHideOffset : _nativeScrollbarSize.x) : 0,
|
||||
y: scrollY && !_nativeScrollbarStyling ? (overlaidY ? overlaidHideOffset : _nativeScrollbarSize.y) : 0,
|
||||
};
|
||||
|
||||
// vertical
|
||||
viewportStyleObj.marginBottom = -scrollbarsHideOffset.x + (paddingStyle.marginBottom as number);
|
||||
contentStyleObj.borderBottom = scrollX && overlaidX && overlaidHideOffset ? overlaidScrollbarsHideBorderStyle : '';
|
||||
|
||||
// horizontal
|
||||
viewportStyleObj.maxWidth = `calc(100% + ${scrollbarsHideOffset.y + horizontalPaddingValue * -1}px)`;
|
||||
viewportStyleObj[horizontalMarginKey] = -scrollbarsHideOffset.y + horizontalPaddingValue;
|
||||
contentStyleObj[horizontalBorderKey] = scrollY && overlaidY && overlaidHideOffset ? overlaidScrollbarsHideBorderStyle : '';
|
||||
|
||||
// adjust content arrange (content arrange doesn't exist if its not needed)
|
||||
style(_contentArrange, {
|
||||
width: scrollY && !showNativeOverlaidScrollbars ? overlaidHideOffset + contentScrollSize.w : '',
|
||||
height: scrollX && !showNativeOverlaidScrollbars ? overlaidHideOffset + contentScrollSize.h : '',
|
||||
});
|
||||
|
||||
// hide overflowing scrollbars if there are any
|
||||
if (!_nativeScrollbarStyling) {
|
||||
if (scrollX) {
|
||||
viewportStyleObj.marginBottom = -scrollbarsHideOffset.x;
|
||||
|
||||
contentStyleObj.borderBottom = overlaidX && overlaidHideOffset ? overlaidScrollbarsHideBorderStyle : '';
|
||||
}
|
||||
if (scrollY) {
|
||||
viewportStyleObj.maxWidth = `calc(100% + ${scrollbarsHideOffset.y}px)`;
|
||||
viewportStyleObj[horizontalMarginKey] = -scrollbarsHideOffset.y;
|
||||
|
||||
contentStyleObj[horizontalBorderKey] = overlaidY && overlaidHideOffset ? overlaidScrollbarsHideBorderStyle : '';
|
||||
}
|
||||
|
||||
if (_contentArrange) {
|
||||
style(_contentArrange, {
|
||||
width: scrollY && !showNativeOverlaidScrollbars ? overlaidHideOffset + contentScrollSize.w : '',
|
||||
height: scrollX && !showNativeOverlaidScrollbars ? overlaidHideOffset + contentScrollSize.h : '',
|
||||
});
|
||||
}
|
||||
style(_padding, {
|
||||
overflow: scrollX || scrollY ? 'hidden' : 'visible',
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
@@ -128,16 +131,16 @@ export const createOverflowLifecycle = (lifecycleHub: LifecycleHub): LifecycleUp
|
||||
scrollTop(_viewport, offsetTop);
|
||||
};
|
||||
|
||||
return createLifecycleUpdateFunction(lifecycleHub, (force, updateHints, checkOption) => {
|
||||
const { _directionIsRTL, _heightIntrinsic, _sizeChanged, _hostMutation, _contentMutation } = updateHints;
|
||||
return (updateHints, checkOption, force) => {
|
||||
const { _directionIsRTL, _heightIntrinsic, _sizeChanged, _hostMutation, _contentMutation, _paddingStyleChanged } = updateHints;
|
||||
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();
|
||||
let overflowAmuntCache: CacheValues<XY<number>> = getCurrentOverflowAmountCache(force);
|
||||
let contentScrollSizeCache: CacheValues<WH<number>> = getCurrentContentScrollSizeCache(force);
|
||||
|
||||
if (showNativeOverlaidScrollbarsChanged && _nativeScrollbarStyling) {
|
||||
if (showNativeOverlaidScrollbars) {
|
||||
@@ -148,20 +151,21 @@ export const createOverflowLifecycle = (lifecycleHub: LifecycleHub): LifecycleUp
|
||||
}
|
||||
|
||||
if (_sizeChanged || _contentMutation) {
|
||||
const viewportOffsetSize = offsetSize(_padding);
|
||||
const contentClientSize = offsetSize(_content || _viewport);
|
||||
const contentArrangeOffsetSize = offsetSize(_contentArrange);
|
||||
const viewportSize = clientSize(_viewport); // needs to be client Size because possible scrollbar offset
|
||||
const viewportScrollSize = scrollSize(_viewport);
|
||||
const contentClientSize = clientSize(_content || _viewport); // needs to be client Size because applied border for content arrange on content
|
||||
const contentArrangeOffsetSize = clientSize(_contentArrange); // can be offset size aswell
|
||||
|
||||
contentScrollSizeCache = updateContentScrollSizeCache(force);
|
||||
const { _value: contentScrollSize } = contentScrollSizeCache;
|
||||
overflowAmuntCache = updateOverflowAmountCache(force, {
|
||||
_contentScrollSize: {
|
||||
w: Math.max(contentScrollSize!.w, contentArrangeOffsetSize.w),
|
||||
h: Math.max(contentScrollSize!.h, contentArrangeOffsetSize.h),
|
||||
w: Math.max(contentScrollSize!.w, viewportScrollSize.w, contentArrangeOffsetSize.w),
|
||||
h: Math.max(contentScrollSize!.h, viewportScrollSize.h, contentArrangeOffsetSize.h),
|
||||
},
|
||||
_viewportSize: {
|
||||
w: viewportOffsetSize.w + Math.max(0, contentClientSize.w - contentScrollSize!.w),
|
||||
h: viewportOffsetSize.h + Math.max(0, contentClientSize.h - contentScrollSize!.h),
|
||||
w: viewportSize.w + Math.max(0, contentClientSize.w - contentScrollSize!.w),
|
||||
h: viewportSize.h + Math.max(0, contentClientSize.h - contentScrollSize!.h),
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -176,6 +180,7 @@ export const createOverflowLifecycle = (lifecycleHub: LifecycleHub): LifecycleUp
|
||||
const adjustDirection = directionChanged && !_nativeScrollbarStyling;
|
||||
|
||||
if (
|
||||
_paddingStyleChanged ||
|
||||
contentScrollSizeChanged ||
|
||||
overflowAmountChanged ||
|
||||
overflowChanged ||
|
||||
@@ -183,7 +188,7 @@ export const createOverflowLifecycle = (lifecycleHub: LifecycleHub): LifecycleUp
|
||||
adjustDirection ||
|
||||
adjustFlexboxGlue
|
||||
) {
|
||||
const viewportStyle: PlainObject = {
|
||||
const viewportStyle: StyleObject = {
|
||||
overflowY: '',
|
||||
overflowX: '',
|
||||
marginTop: '',
|
||||
@@ -192,7 +197,7 @@ export const createOverflowLifecycle = (lifecycleHub: LifecycleHub): LifecycleUp
|
||||
marginLeft: '',
|
||||
maxWidth: '',
|
||||
};
|
||||
const contentStyle: PlainObject = {
|
||||
const contentStyle: StyleObject = {
|
||||
borderTop: '',
|
||||
borderRight: '',
|
||||
borderBottom: '',
|
||||
@@ -225,9 +230,12 @@ export const createOverflowLifecycle = (lifecycleHub: LifecycleHub): LifecycleUp
|
||||
// TODO: Test without content
|
||||
// TODO: Test without padding
|
||||
// TODO: hide host || padding overflow if scroll x or y
|
||||
// TODO: fix false overflow bug (fractal scroll size)
|
||||
// TODO: add trinsic lifecycle
|
||||
// TODO: remove lifecycleHub get set padding if not needed
|
||||
|
||||
style(_viewport, viewportStyle);
|
||||
style(_content, contentStyle);
|
||||
}
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
import { createCache, topRightBottomLeft, TRBL, equalTRBL, style } from 'support';
|
||||
import { LifecycleHub, Lifecycle } from 'lifecycles/lifecycleHub';
|
||||
import { StyleObject } from 'typings';
|
||||
import { getEnvironment } from 'environment';
|
||||
|
||||
export const createPaddingLifecycle = (lifecycleHub: LifecycleHub): Lifecycle => {
|
||||
const { _host, _padding, _viewport } = lifecycleHub._structureSetup._targetObj;
|
||||
const { _update: updatePaddingCache, _current: currentPaddingCache } = createCache(() => topRightBottomLeft(_host, 'padding'), {
|
||||
_equal: equalTRBL,
|
||||
});
|
||||
|
||||
/*
|
||||
const onTrinsicChanged = (heightIntrinsic: CacheValues<boolean>) => {
|
||||
const { _changed, _value } = heightIntrinsic;
|
||||
if (_changed) {
|
||||
style(_content, { height: _value ? 'auto' : '100%' });
|
||||
}
|
||||
};
|
||||
*/
|
||||
|
||||
return (updateHints, checkOption, force) => {
|
||||
let { _value: padding, _changed: paddingChanged } = currentPaddingCache(force);
|
||||
const { _nativeScrollbarStyling } = getEnvironment();
|
||||
const { _sizeChanged, _directionIsRTL } = updateHints;
|
||||
const { _value: directionIsRTL, _changed: directionRTLChanged } = _directionIsRTL;
|
||||
const { _value: paddingAbsolute, _changed: paddingAbsoluteChanged } = checkOption('paddingAbsolute');
|
||||
|
||||
if (_sizeChanged || paddingChanged) {
|
||||
({ _value: padding, _changed: paddingChanged } = updatePaddingCache(force));
|
||||
}
|
||||
|
||||
const paddingStyleChanged = paddingAbsoluteChanged || directionRTLChanged || paddingChanged;
|
||||
|
||||
if (paddingStyleChanged) {
|
||||
// if there is no padding element and no scrollbar styling padding absolute isn't supported
|
||||
const { _value: padding } = updatePaddingCache(force);
|
||||
const paddingRelative = !paddingAbsolute || (!_padding && !_nativeScrollbarStyling);
|
||||
const paddingHorizontal = padding!.r + padding!.l;
|
||||
const paddingVertical = padding!.t + padding!.b;
|
||||
const paddingStyle: StyleObject = {
|
||||
marginTop: '',
|
||||
marginRight: '',
|
||||
marginBottom: '',
|
||||
marginLeft: '',
|
||||
top: '',
|
||||
right: '',
|
||||
bottom: '',
|
||||
left: '',
|
||||
maxWidth: '',
|
||||
};
|
||||
const viewportStyle: StyleObject = {
|
||||
paddingTop: '',
|
||||
paddingRight: '',
|
||||
paddingBottom: '',
|
||||
paddingLeft: '',
|
||||
};
|
||||
|
||||
if (paddingRelative) {
|
||||
const horizontalPositionKey = directionIsRTL ? 'right' : 'left';
|
||||
const horizontalPositionValue = directionIsRTL ? padding!.r : padding!.l;
|
||||
const horizontalMarginKey = directionIsRTL ? 'marginLeft' : 'marginRight';
|
||||
|
||||
paddingStyle.top = -padding!.t;
|
||||
paddingStyle[horizontalPositionKey] = -horizontalPositionValue;
|
||||
paddingStyle.marginBottom = -paddingVertical;
|
||||
paddingStyle[horizontalMarginKey] = -paddingHorizontal;
|
||||
paddingStyle.maxWidth = `calc(100% + ${paddingHorizontal}px)`;
|
||||
|
||||
viewportStyle.paddingTop = padding!.t;
|
||||
viewportStyle.paddingRight = padding!.r;
|
||||
viewportStyle.paddingBottom = padding!.b;
|
||||
viewportStyle.paddingLeft = padding!.l;
|
||||
}
|
||||
|
||||
// if there is no padding element apply the style to the viewport element instead
|
||||
style(_padding || _viewport, paddingStyle);
|
||||
style(_viewport, viewportStyle);
|
||||
|
||||
lifecycleHub._setPadding(padding);
|
||||
lifecycleHub._setPaddingStyle(!_padding ? paddingStyle : null);
|
||||
}
|
||||
|
||||
return {
|
||||
_paddingStyleChanged: paddingStyleChanged,
|
||||
};
|
||||
};
|
||||
};
|
||||
@@ -1,6 +1,6 @@
|
||||
import { each, keys } from 'support/utils';
|
||||
import { isString, isNumber, isArray } from 'support/utils/types';
|
||||
import { PlainObject } from 'typings';
|
||||
import { PlainObject, StyleObject } from 'typings';
|
||||
|
||||
export interface TRBL {
|
||||
t: number;
|
||||
@@ -9,7 +9,6 @@ export interface TRBL {
|
||||
l: number;
|
||||
}
|
||||
|
||||
type CssStyles = { [key: string]: string | number };
|
||||
const cssNumber = {
|
||||
animationiterationcount: 1,
|
||||
columncount: 1,
|
||||
@@ -49,10 +48,10 @@ const setCSSVal = (elm: HTMLElement | null | undefined, prop: string, val: strin
|
||||
* @param elm The element to which the styles shall be applied to / be read from.
|
||||
* @param styles The styles which shall be set or read.
|
||||
*/
|
||||
export function style(elm: HTMLElement | null | undefined, styles: CssStyles): void;
|
||||
export function style(elm: HTMLElement | null | undefined, styles: StyleObject): void;
|
||||
export function style(elm: HTMLElement | null | undefined, styles: string): string;
|
||||
export function style(elm: HTMLElement | null | undefined, styles: Array<string> | string): { [key: string]: string };
|
||||
export function style(elm: HTMLElement | null | undefined, styles: CssStyles | Array<string> | string): { [key: string]: string } | string | void {
|
||||
export function style(elm: HTMLElement | null | undefined, styles: StyleObject | Array<string> | string): { [key: string]: string } | string | void {
|
||||
const getSingleStyle = isString(styles);
|
||||
const getStyles = isArray(styles) || getSingleStyle;
|
||||
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
export type PlainObject<T = any> = { [name: string]: T };
|
||||
|
||||
export type StyleObject = {
|
||||
[K in keyof CSSStyleDeclaration]?: string | number;
|
||||
}
|
||||
|
||||
export type InternalVersionOf<T> = {
|
||||
[K in keyof T as `_${Uncapitalize<string & K>}`]: T[K];
|
||||
};
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@ import { createDiv, appendChildren, parent, style, on, off, addClass, WH, XY, cl
|
||||
import { OverlayScrollbars } from 'overlayscrollbars/OverlayScrollbars';
|
||||
|
||||
const targetElm = document.querySelector('#target') as HTMLElement;
|
||||
window.os = OverlayScrollbars(targetElm);
|
||||
window.os = OverlayScrollbars({ target: targetElm, padding: null });
|
||||
|
||||
export const resize = (element: HTMLElement) => {
|
||||
const strMouseTouchDownEvent = 'mousedown touchstart';
|
||||
|
||||
Reference in New Issue
Block a user