merge conflicts

This commit is contained in:
Rene Haas
2022-07-18 21:46:00 +02:00
12 changed files with 181 additions and 42 deletions
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -4,6 +4,7 @@ import {
createDiv, createDiv,
each, each,
isEmptyArray, isEmptyArray,
noop,
on, on,
push, push,
removeClass, removeClass,
@@ -11,6 +12,7 @@ import {
runEachAndClear, runEachAndClear,
setT, setT,
stopPropagation, stopPropagation,
style,
} from 'support'; } from 'support';
import { import {
classNameScrollbar, classNameScrollbar,
@@ -30,6 +32,7 @@ import type {
ScrollbarsInitializationStrategy, ScrollbarsInitializationStrategy,
ScrollbarsDynamicInitializationElement, ScrollbarsDynamicInitializationElement,
} from 'setups/scrollbarsSetup/scrollbarsSetup.initialization'; } from 'setups/scrollbarsSetup/scrollbarsSetup.initialization';
import { StyleObject } from 'typings';
export interface ScrollbarStructure { export interface ScrollbarStructure {
_scrollbar: HTMLElement; _scrollbar: HTMLElement;
@@ -40,7 +43,16 @@ export interface ScrollbarStructure {
export interface ScrollbarsSetupElement { export interface ScrollbarsSetupElement {
_scrollbarStructures: ScrollbarStructure[]; _scrollbarStructures: ScrollbarStructure[];
_clone: () => ScrollbarStructure; _clone: () => ScrollbarStructure;
_addRemoveClass: (classNames: string | false | null | undefined, add?: boolean) => void; _addRemoveClass: (
classNames: string,
add?: boolean,
elm?: (scrollbarStructure: ScrollbarStructure) => HTMLElement | false | null | undefined
) => void;
_handleStyle: (
elmStyle: (
scrollbarStructure: ScrollbarStructure
) => [HTMLElement | false | null | undefined, StyleObject]
) => void;
// _removeClass: (classNames: string) => void; // _removeClass: (classNames: string) => void;
/* /*
_addEventListener: () => void; _addEventListener: () => void;
@@ -89,12 +101,24 @@ export const createScrollbarsSetupElements = (
); );
const scrollbarsAddRemoveClass = ( const scrollbarsAddRemoveClass = (
scrollbarStructures: ScrollbarStructure[], scrollbarStructures: ScrollbarStructure[],
classNames: string | false | null | undefined, classNames: string,
add?: boolean add?: boolean,
elm?: (scrollbarStructure: ScrollbarStructure) => HTMLElement | false | null | undefined
) => { ) => {
const action = add ? addClass : removeClass; const action = add ? addClass : removeClass;
each(scrollbarStructures, (scrollbarStructure) => { each(scrollbarStructures, (scrollbarStructure) => {
action(scrollbarStructure._scrollbar, classNames); action((elm || noop)(scrollbarStructure) || scrollbarStructure._scrollbar, classNames);
});
};
const scrollbarsHandleStyle = (
scrollbarStructures: ScrollbarStructure[],
elmStyle: (
scrollbarStructure: ScrollbarStructure
) => [HTMLElement | false | null | undefined, StyleObject]
) => {
each(scrollbarStructures, (scrollbarStructure) => {
const [elm, styles] = elmStyle(scrollbarStructure);
style(elm, styles);
}); });
}; };
const destroyFns: (() => void)[] = []; const destroyFns: (() => void)[] = [];
@@ -160,11 +184,13 @@ export const createScrollbarsSetupElements = (
_scrollbarStructures: horizontalScrollbars, _scrollbarStructures: horizontalScrollbars,
_clone: generateHorizontalScrollbarStructure, _clone: generateHorizontalScrollbarStructure,
_addRemoveClass: addRemoveClassHorizontal, _addRemoveClass: addRemoveClassHorizontal,
_handleStyle: scrollbarsHandleStyle.bind(0, horizontalScrollbars),
}, },
_vertical: { _vertical: {
_scrollbarStructures: verticalScrollbars, _scrollbarStructures: verticalScrollbars,
_clone: generateVerticalScrollbarStructure, _clone: generateVerticalScrollbarStructure,
_addRemoveClass: addRemoveClassVertical, _addRemoveClass: addRemoveClassVertical,
_handleStyle: scrollbarsHandleStyle.bind(0, verticalScrollbars),
}, },
}, },
appendElements, appendElements,
@@ -2,6 +2,7 @@ import { rAF, cAF, isFunction, on, runEachAndClear, setT, clearT } from 'support
import { createState, createOptionCheck } from 'setups/setups'; import { createState, createOptionCheck } from 'setups/setups';
import { import {
createScrollbarsSetupElements, createScrollbarsSetupElements,
ScrollbarsSetupElement,
ScrollbarsSetupElementsObj, ScrollbarsSetupElementsObj,
} from 'setups/scrollbarsSetup/scrollbarsSetup.elements'; } from 'setups/scrollbarsSetup/scrollbarsSetup.elements';
import { import {
@@ -17,7 +18,7 @@ import type {
} from 'options'; } from 'options';
import type { Setup, StructureSetupState, StructureSetupStaticState } from 'setups'; import type { Setup, StructureSetupState, StructureSetupStaticState } from 'setups';
import type { InitializationTarget } from 'initialization'; import type { InitializationTarget } from 'initialization';
import type { OverflowStyle } from 'typings'; import type { OverflowStyle, StyleObject } from 'typings';
// eslint-disable-next-line @typescript-eslint/no-empty-interface // eslint-disable-next-line @typescript-eslint/no-empty-interface
export interface ScrollbarsSetupState {} export interface ScrollbarsSetupState {}
@@ -27,6 +28,7 @@ export interface ScrollbarsSetupStaticState {
_appendElements: () => void; _appendElements: () => void;
} }
const { min } = Math;
const createSelfCancelTimeout = (timeout?: number | (() => number)) => { const createSelfCancelTimeout = (timeout?: number | (() => number)) => {
let id: number; let id: number;
const setTFn = timeout ? setT : rAF!; const setTFn = timeout ? setT : rAF!;
@@ -41,6 +43,105 @@ const createSelfCancelTimeout = (timeout?: number | (() => number)) => {
] as [timeout: (callback: () => any) => void, clear: () => void]; ] as [timeout: (callback: () => any) => void, clear: () => void];
}; };
const refreshScrollbarHandleLength = (
setStyleFn: ScrollbarsSetupElement['_handleStyle'],
structureSetupState: StructureSetupState,
isHorizontal?: boolean
) => {
const { _overflowAmount, _overflowEdge } = structureSetupState;
const axis = isHorizontal ? 'x' : 'y';
const viewportSize = _overflowEdge[axis];
const overflowAmount = _overflowAmount[axis];
const handleRatio = min(1, viewportSize / (viewportSize + overflowAmount));
setStyleFn((structure) => [
structure._handle,
{
[isHorizontal ? 'width' : 'height']: `${(handleRatio * 100).toFixed(3)}%`,
},
]);
};
const refreshScrollbarHandlePosition = (
setStyleFn: (styles: StyleObject) => void,
structureSetupState: StructureSetupState,
isHorizontal?: boolean
) => {
/*
//measure the handle length to respect min & max length
var handleLength = scrollbarVarsInfo._handleLength;
var trackLength = scrollbarVars._track[0]['offset' + scrollbarVars._Width_Height];
var handleTrackDiff = trackLength - handleLength;
var handleCSS = {};
var transformOffset;
var translateValue;
//DONT use the variable '_contentScrollSizeCache[scrollbarVars._w_h]' instead of '_viewportElement[0]['scroll' + scrollbarVars._Width_Height]'
// because its a bit behind during the small delay when content size updates
//(delay = mutationObserverContentLag, if its 0 then this var could be used)
var maxScroll =
(_viewportElementNative[_strScroll + scrollbarVars._Width_Height] -
_viewportElementNative['client' + scrollbarVars._Width_Height]) *
(_rtlScrollBehavior.n && isRTLisHorizontal ? -1 : 1); //* -1 if rtl scroll max is negative
var getScrollRatio = function (base) {
return isNaN(base / maxScroll) ? 0 : MATH.max(0, MATH.min(1, base / maxScroll));
};
var getHandleOffset = function (scrollRatio) {
var offset = handleTrackDiff * scrollRatio;
offset = isNaN(offset) ? 0 : offset;
offset =
isRTLisHorizontal && !_rtlScrollBehavior.i ? trackLength - handleLength - offset : offset;
offset = MATH.max(0, offset);
return offset;
};
var scrollRatio = getScrollRatio(nativeScroll);
var unsnappedScrollRatio = getScrollRatio(currentScroll);
var handleOffset = getHandleOffset(unsnappedScrollRatio);
var snappedHandleOffset = getHandleOffset(scrollRatio);
scrollbarVarsInfo._maxScroll = maxScroll;
scrollbarVarsInfo._currentScroll = nativeScroll;
scrollbarVarsInfo._currentScrollRatio = scrollRatio;
if (_supportTransform) {
transformOffset = isRTLisHorizontal
? -(trackLength - handleLength - handleOffset)
: handleOffset; //in px
//transformOffset = (transformOffset / trackLength * 100) * (trackLength / handleLength); //in %
translateValue = isHorizontal
? strTranslateBrace + transformOffset + 'px, 0)'
: strTranslateBrace + '0, ' + transformOffset + 'px)';
handleCSS[strTransform] = translateValue;
//apply or clear up transition
if (_supportTransition)
handleCSS[strTransition] =
transition && MATH.abs(handleOffset - scrollbarVarsInfo._handleOffset) > 1
? getCSSTransitionString(scrollbarVars._handle) +
', ' +
(strTransform + _strSpace + transitionDuration + 'ms')
: _strEmpty;
} else handleCSS[scrollbarVars._left_top] = handleOffset;
//only apply css if offset has changed and overflow exists.
if (!nativeOverlayScrollbarsAreActive()) {
scrollbarVars._handle.css(handleCSS);
//clear up transition
if (_supportTransform && _supportTransition && transition) {
scrollbarVars._handle.one(_strTransitionEndEvent, function () {
if (!_destroyed) scrollbarVars._handle.css(strTransition, _strEmpty);
});
}
}
scrollbarVarsInfo._handleOffset = handleOffset;
scrollbarVarsInfo._snappedHandleOffset = snappedHandleOffset;
scrollbarVarsInfo._trackLength = trackLength;
*/
};
export const createScrollbarsSetup = ( export const createScrollbarsSetup = (
target: InitializationTarget, target: InitializationTarget,
options: ReadonlyOSOptions, options: ReadonlyOSOptions,
@@ -66,8 +167,8 @@ export const createScrollbarsSetup = (
); );
const { _host, _viewport } = structureSetupState._elements; const { _host, _viewport } = structureSetupState._elements;
const { _horizontal, _vertical } = elements; const { _horizontal, _vertical } = elements;
const { _addRemoveClass: addRemoveClassHorizontal } = _horizontal; const { _addRemoveClass: addRemoveClassHorizontal, _handleStyle: styleHorizontal } = _horizontal;
const { _addRemoveClass: addRemoveClassVertical } = _vertical; const { _addRemoveClass: addRemoveClassVertical, _handleStyle: styleVertical } = _vertical;
const manageScrollbarsAutoHide = (removeAutoHide: boolean, delayless?: boolean) => { const manageScrollbarsAutoHide = (removeAutoHide: boolean, delayless?: boolean) => {
clearAutoTimeout(); clearAutoTimeout();
if (removeAutoHide) { if (removeAutoHide) {
@@ -133,6 +234,7 @@ export const createScrollbarsSetup = (
const { _overflowEdgeChanged, _overflowAmountChanged, _overflowStyleChanged } = const { _overflowEdgeChanged, _overflowAmountChanged, _overflowStyleChanged } =
structureUpdateHints; structureUpdateHints;
const checkOption = createOptionCheck(options, changedOptions, force); const checkOption = createOptionCheck(options, changedOptions, force);
const currStructureSetupState = structureSetupState();
const [theme, themeChanged] = checkOption<string | null>('scrollbars.theme'); const [theme, themeChanged] = checkOption<string | null>('scrollbars.theme');
const [visibility, visibilityChanged] = const [visibility, visibilityChanged] =
@@ -145,7 +247,7 @@ export const createScrollbarsSetup = (
); );
const [touchSupport, touchSupportChanged] = checkOption<boolean>('scrollbars.touchSupport'); const [touchSupport, touchSupportChanged] = checkOption<boolean>('scrollbars.touchSupport');
const updateHandleSize = _overflowEdgeChanged || _overflowAmountChanged; const updateHandle = _overflowEdgeChanged || _overflowAmountChanged;
const updateVisibility = _overflowStyleChanged || visibilityChanged; const updateVisibility = _overflowStyleChanged || visibilityChanged;
const setScrollbarVisibility = ( const setScrollbarVisibility = (
@@ -161,7 +263,7 @@ export const createScrollbarsSetup = (
globalAutoHideDelay = autoHideDelay; globalAutoHideDelay = autoHideDelay;
if (updateVisibility) { if (updateVisibility) {
const { _overflowStyle } = structureSetupState(); const { _overflowStyle } = currStructureSetupState;
const xVisible = setScrollbarVisibility(_overflowStyle.x, addRemoveClassHorizontal); const xVisible = setScrollbarVisibility(_overflowStyle.x, addRemoveClassHorizontal);
const yVisible = setScrollbarVisibility(_overflowStyle.y, addRemoveClassVertical); const yVisible = setScrollbarVisibility(_overflowStyle.y, addRemoveClassVertical);
@@ -184,6 +286,10 @@ export const createScrollbarsSetup = (
autoHideNotNever = autoHide !== 'never'; autoHideNotNever = autoHide !== 'never';
manageScrollbarsAutoHide(!autoHideNotNever, true); manageScrollbarsAutoHide(!autoHideNotNever, true);
} }
if (updateHandle) {
refreshScrollbarHandleLength(styleHorizontal, currStructureSetupState, true);
refreshScrollbarHandleLength(styleVertical, currStructureSetupState);
}
}, },
scrollbarsSetupState, scrollbarsSetupState,
runEachAndClear.bind(0, destroyFns), runEachAndClear.bind(0, destroyFns),
@@ -20,6 +20,8 @@ import {
closest, closest,
assignDeep, assignDeep,
push, push,
scrollLeft,
scrollTop,
} from 'support'; } from 'support';
import { getEnvironment } from 'environment'; import { getEnvironment } from 'environment';
import { import {
@@ -28,6 +30,7 @@ import {
classNameViewport, classNameViewport,
classNameOverflowVisible, classNameOverflowVisible,
classNameScrollbar, classNameScrollbar,
classNameViewportArrange,
} from 'classnames'; } from 'classnames';
import { createSizeObserver, SizeObserverCallbackParams } from 'observers/sizeObserver'; import { createSizeObserver, SizeObserverCallbackParams } from 'observers/sizeObserver';
import { createTrinsicObserver } from 'observers/trinsicObserver'; import { createTrinsicObserver } from 'observers/trinsicObserver';
@@ -91,14 +94,21 @@ export const createStructureSetupObservers = (
_initialValue: { w: 0, h: 0 }, _initialValue: { w: 0, h: 0 },
}, },
() => { () => {
const has = _viewportHasClass(classNameOverflowVisible, dataValueHostOverflowVisible); const hasOver = _viewportHasClass(classNameOverflowVisible, dataValueHostOverflowVisible);
has && _viewportAddRemoveClass(classNameOverflowVisible, dataValueHostOverflowVisible); const hasVpStyle = _viewportHasClass(classNameViewportArrange, '');
const scrollOffsetX = hasVpStyle && scrollLeft(_viewport);
const scrollOffsetY = hasVpStyle && scrollTop(_viewport);
_viewportAddRemoveClass(classNameOverflowVisible, dataValueHostOverflowVisible);
_viewportAddRemoveClass(classNameViewportArrange, '');
const contentScroll = scrollSize(_content); const contentScroll = scrollSize(_content);
const viewportScroll = scrollSize(_viewport); const viewportScroll = scrollSize(_viewport);
const fractional = fractionalSize(_viewport); const fractional = fractionalSize(_viewport);
has && _viewportAddRemoveClass(classNameOverflowVisible, dataValueHostOverflowVisible, true); _viewportAddRemoveClass(classNameOverflowVisible, dataValueHostOverflowVisible, hasOver);
_viewportAddRemoveClass(classNameViewportArrange, '', hasVpStyle);
scrollLeft(_viewport, scrollOffsetX);
scrollTop(_viewport, scrollOffsetY);
return { return {
w: viewportScroll.w + contentScroll.w + fractional.w, w: viewportScroll.w + contentScroll.w + fractional.w,
h: viewportScroll.h + contentScroll.h + fractional.h, h: viewportScroll.h + contentScroll.h + fractional.h,
@@ -1,4 +1,4 @@
import { each, isNumber, scrollLeft, scrollTop, assignDeep, keys } from 'support'; import { each, scrollLeft, scrollTop, assignDeep, keys } from 'support';
import { getEnvironment } from 'environment'; import { getEnvironment } from 'environment';
import { import {
createTrinsicUpdateSegment, createTrinsicUpdateSegment,
@@ -107,12 +107,8 @@ export const createStructureSetupUpdate = (
); );
}); });
if (isNumber(scrollOffsetX)) { scrollLeft(_viewport, scrollOffsetX);
scrollLeft(_viewport, scrollOffsetX); scrollTop(_viewport, scrollOffsetY);
}
if (isNumber(scrollOffsetY)) {
scrollTop(_viewport, scrollOffsetY);
}
return adaptivedUpdateHints; return adaptivedUpdateHints;
}; };
@@ -13,7 +13,7 @@ body > .os-scrollbar {
transition: none; transition: none;
} }
.os-scrollbar-track { .os-scrollbar-track {
pointer-events: auto; pointer-events: none;
position: relative; position: relative;
height: 100%; height: 100%;
width: 100%; width: 100%;
@@ -21,14 +21,14 @@ body > .os-scrollbar {
border: none !important; border: none !important;
} }
.os-scrollbar-handle { .os-scrollbar-handle {
pointer-events: auto; pointer-events: none;
position: absolute; position: absolute;
width: 100%; width: 100%;
height: 100%; height: 100%;
} }
.os-scrollbar-handle-off, .os-scrollbar-handle-interactive,
.os-scrollbar-track-off { .os-scrollbar-track-interactive {
pointer-events: none; pointer-events: auto;
} }
.os-scrollbar-unusable, .os-scrollbar-unusable,
.os-scrollbar-unusable * { .os-scrollbar-unusable * {
@@ -1,5 +1,5 @@
import { from } from 'support/utils/array'; import { from } from 'support/utils/array';
import { isUndefined } from 'support/utils/types'; import { isNull, isUndefined } from 'support/utils/types';
type GetSetPropName = 'scrollLeft' | 'scrollTop' | 'value'; type GetSetPropName = 'scrollLeft' | 'scrollTop' | 'value';
@@ -14,20 +14,20 @@ type Attr = {
type GetSetProp<T> = { type GetSetProp<T> = {
(elm: HTMLElement | false | null | undefined): T; (elm: HTMLElement | false | null | undefined): T;
(elm: HTMLElement | false | null | undefined, value: T): void; (elm: HTMLElement | false | null | undefined, value: T | false | null): void;
(elm: HTMLElement | false | null | undefined, value?: T): number | void; (elm: HTMLElement | false | null | undefined, value?: T | false | null): T | void;
}; };
const getSetProp = ( const getSetProp = (
topLeft: GetSetPropName, topLeft: GetSetPropName,
fallback: number | string, fallback: number | string,
elm: HTMLElement | HTMLInputElement | false | null | undefined, elm: HTMLElement | HTMLInputElement | false | null | undefined,
value?: number | string value?: number | string | false | null
): number | string | void => { ): number | string | void => {
if (isUndefined(value)) { if (isUndefined(value)) {
return elm ? elm[topLeft] : fallback; return elm ? elm[topLeft] : fallback;
} }
elm && (elm[topLeft] = value); elm && !isNull(value) && value !== false && (elm[topLeft] = value);
}; };
/** /**
@@ -61,11 +61,13 @@ export const attrClass = (
value: string, value: string,
add?: boolean add?: boolean
) => { ) => {
const currValues = attr(elm, attrName) || ''; if (value) {
const currValuesSet = new Set(currValues.split(' ')); const currValues = attr(elm, attrName) || '';
currValuesSet[add ? 'add' : 'delete'](value); const currValuesSet = new Set(currValues.split(' '));
currValuesSet[add ? 'add' : 'delete'](value);
attr(elm, attrName, from(currValuesSet).join(' ').trim()); attr(elm, attrName, from(currValuesSet).join(' ').trim());
}
}; };
/** /**
@@ -101,7 +103,7 @@ export const removeAttr = (elm: Element | false | null | undefined, attrName: st
*/ */
export const scrollLeft = (( export const scrollLeft = ((
elm: HTMLElement | false | null | undefined, elm: HTMLElement | false | null | undefined,
value?: number value?: number | false | null
): number | void => getSetProp('scrollLeft', 0, elm, value) as number) as GetSetProp<number>; ): number | void => getSetProp('scrollLeft', 0, elm, value) as number) as GetSetProp<number>;
/** /**
@@ -111,7 +113,7 @@ export const scrollLeft = ((
*/ */
export const scrollTop = (( export const scrollTop = ((
elm: HTMLElement | false | null | undefined, elm: HTMLElement | false | null | undefined,
value?: number value?: number | false | null
): number | void => getSetProp('scrollTop', 0, elm, value) as number) as GetSetProp<number>; ): number | void => getSetProp('scrollTop', 0, elm, value) as number) as GetSetProp<number>;
/** /**
@@ -74,7 +74,7 @@ const contents = (elm: InputElementType): ReadonlyArray<ChildNode> =>
*/ */
const parent = (elm: InputElementType): OutputElementType => (elm ? elm.parentElement : null); const parent = (elm: InputElementType): OutputElementType => (elm ? elm.parentElement : null);
export const closest = (elm: InputElementType, selector: string): OutputElementType => { const closest = (elm: InputElementType, selector: string): OutputElementType => {
if (isElement(elm)) { if (isElement(elm)) {
const closestFn = elmPrototype.closest; const closestFn = elmPrototype.closest;
if (closestFn) { if (closestFn) {
@@ -113,4 +113,4 @@ const liesBetween = (
: false; : false;
}; };
export { find, findFirst, is, children, contents, parent, liesBetween }; export { find, findFirst, is, children, contents, parent, liesBetween, closest };
@@ -30,7 +30,6 @@ if (!window.ResizeObserver) {
addPlugin(sizeObserverPlugin); addPlugin(sizeObserverPlugin);
} }
if (!OverlayScrollbars.env().scrollbarsHiding) { if (!OverlayScrollbars.env().scrollbarsHiding) {
console.log('added');
addPlugin(scrollbarsHidingPlugin); addPlugin(scrollbarsHidingPlugin);
} }