add visibility, autoHide and autoHide delay functionality

This commit is contained in:
Rene
2022-07-14 16:18:12 +02:00
parent e07f79d0bf
commit e89dbd0018
27 changed files with 2363 additions and 1885 deletions
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large Load Diff
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 it is too large Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -28,3 +28,7 @@ export const classNameScrollbarHorizontal = `${classNameScrollbar}-horizontal`;
export const classNameScrollbarVertical = `${classNameScrollbar}-vertical`;
export const classNameScrollbarTrack = 'os-scrollbar-track';
export const classNameScrollbarHandle = 'os-scrollbar-handle';
export const classNamesScrollbarVisible = `${classNameScrollbar}-visible`;
export const classNamesScrollbarCornerless = `${classNameScrollbar}-cornerless`;
export const classNamesScrollbarInteraction = `${classNameScrollbar}-interaction`;
export const classNamesScrollbarAutoHidden = `${classNameScrollbar}-auto-hidden`;
+4 -4
View File
@@ -18,9 +18,9 @@ export type OverflowBehavior =
| 'visible-hidden'
| 'visible-scroll';
export type VisibilityBehavior = 'visible' | 'hidden' | 'auto';
export type ScrollbarVisibilityBehavior = 'visible' | 'hidden' | 'auto';
export type AutoHideBehavior = 'never' | 'scroll' | 'leave' | 'move';
export type ScrollbarAutoHideBehavior = 'never' | 'scroll' | 'leave' | 'move';
export type ScrollBehavior = 'always' | 'ifneeded' | 'never';
@@ -51,8 +51,8 @@ export interface Options {
y: OverflowBehavior;
};
scrollbars: {
visibility: VisibilityBehavior;
autoHide: AutoHideBehavior;
visibility: ScrollbarVisibilityBehavior;
autoHide: ScrollbarAutoHideBehavior;
autoHideDelay: number;
dragScroll: boolean;
clickScroll: boolean;
@@ -176,11 +176,10 @@ export const OverlayScrollbars: OverlayScrollbarsStatic = (
const [updateScrollbars, scrollbarsState, destroyScrollbars] = createScrollbarsSetup(
target,
currentOptions,
structureState._elements
structureState
);
const update = (changedOptions: PartialOptions<Options>, force?: boolean) => {
updateStructure(changedOptions, force);
updateScrollbars(changedOptions, force);
updateStructure(changedOptions, !!force);
};
const removeEnvListener = addEnvListener(update.bind(0, {}, true));
const destroy = (withdrawn?: boolean) => {
@@ -255,6 +254,10 @@ export const OverlayScrollbars: OverlayScrollbarsStatic = (
destroy: destroy.bind(0),
};
structureState._addOnUpdatedListener((updateHints, changedOptions, force: boolean) => {
updateScrollbars(changedOptions, force, updateHints);
});
each(keys(plugins), (pluginName) => {
const pluginInstance = plugins[pluginName];
if (isFunction(pluginInstance)) {
@@ -1,4 +1,9 @@
import { Options, OverflowBehavior, VisibilityBehavior, AutoHideBehavior } from 'options';
import {
Options,
OverflowBehavior,
ScrollbarVisibilityBehavior,
ScrollbarAutoHideBehavior,
} from 'options';
import {
validateOptions,
OptionsTemplate,
@@ -13,9 +18,9 @@ const booleanAllowedValues: OptionsTemplateValue<boolean> = oTypes.boolean;
const arrayNullValues: OptionsTemplateValue<Array<unknown> | null> = [oTypes.array, oTypes.null];
const overflowAllowedValues: OptionsTemplateValue<OverflowBehavior> =
'hidden scroll visible visible-hidden';
const scrollbarsVisibilityAllowedValues: OptionsTemplateValue<VisibilityBehavior> =
const scrollbarsVisibilityAllowedValues: OptionsTemplateValue<ScrollbarVisibilityBehavior> =
'visible hidden auto';
const scrollbarsAutoHideAllowedValues: OptionsTemplateValue<AutoHideBehavior> =
const scrollbarsAutoHideAllowedValues: OptionsTemplateValue<ScrollbarAutoHideBehavior> =
'never scroll leavemove';
const optionsTemplate: OptionsTemplate<Options> = {
@@ -1,10 +1,21 @@
import { appendChildren, createDiv, removeElements } from 'support';
import {
addClass,
appendChildren,
createDiv,
each,
on,
push,
removeClass,
removeElements,
runEachAndClear,
} from 'support';
import {
classNameScrollbar,
classNameScrollbarHorizontal,
classNameScrollbarVertical,
classNameScrollbarTrack,
classNameScrollbarHandle,
classNamesScrollbarInteraction,
} from 'classnames';
import { getEnvironment } from 'environment';
import { dynamicInitializationElement as generalDynamicInitializationElement } from 'initialization';
@@ -22,9 +33,20 @@ export interface ScrollbarStructure {
_handle: HTMLElement;
}
export interface ScrollbarsSetupElement {
_scrollbarStructures: ScrollbarStructure[];
_clone: () => ScrollbarStructure;
_addRemoveClass: (classNames: string, add?: boolean) => void;
// _removeClass: (classNames: string) => void;
/*
_addEventListener: () => void;
_removeEventListener: () => void;
*/
}
export interface ScrollbarsSetupElementsObj {
_horizontalScrollbarStructure: ScrollbarStructure;
_verticalScrollbarStructure: ScrollbarStructure;
_horizontal: ScrollbarsSetupElement;
_vertical: ScrollbarsSetupElement;
}
export type ScrollbarsSetupElements = [
@@ -33,20 +55,8 @@ export type ScrollbarsSetupElements = [
destroy: () => void
];
const generateScrollbarDOM = (scrollbarClassName: string): ScrollbarStructure => {
const scrollbar = createDiv(`${classNameScrollbar} ${scrollbarClassName} os-theme-dark`);
const track = createDiv(classNameScrollbarTrack);
const handle = createDiv(classNameScrollbarHandle);
appendChildren(scrollbar, track);
appendChildren(track, handle);
return {
_scrollbar: scrollbar,
_track: track,
_handle: handle,
};
};
const interactionStartEventNames = 'touchstart mouseenter';
const interactionEndEventNames = 'touchend touchcancel mouseleave';
export const createScrollbarsSetupElements = (
target: InitializationTarget,
@@ -65,24 +75,84 @@ export const createScrollbarsSetupElements = (
environmentScrollbarSlot,
initializationScrollbarSlot
);
const horizontalScrollbarStructure = generateScrollbarDOM(classNameScrollbarHorizontal);
const verticalScrollbarStructure = generateScrollbarDOM(classNameScrollbarVertical);
const { _scrollbar: horizontalScrollbar } = horizontalScrollbarStructure;
const { _scrollbar: verticalScrollbar } = verticalScrollbarStructure;
const appendElements = () => {
appendChildren(evaluatedScrollbarSlot, horizontalScrollbar);
appendChildren(evaluatedScrollbarSlot, verticalScrollbar);
const scrollbarsAddRemoveClass = (
scrollbarStructures: ScrollbarStructure[],
classNames: string,
add?: boolean
) => {
const action = add ? addClass : removeClass;
each(scrollbarStructures, (scrollbarStructure) => {
action(scrollbarStructure._scrollbar, classNames);
});
};
const destroyFns: (() => void)[] = [];
const horizontalScrollbars: ScrollbarStructure[] = [];
const verticalScrollbars: ScrollbarStructure[] = [];
const addRemoveClassHorizontal = scrollbarsAddRemoveClass.bind(0, horizontalScrollbars);
const addRemoveClassVertical = scrollbarsAddRemoveClass.bind(0, verticalScrollbars);
const generateScrollbarDOM = (horizontal?: boolean): ScrollbarStructure => {
const scrollbarClassName = horizontal
? classNameScrollbarHorizontal
: classNameScrollbarVertical;
const arrToPush = horizontal ? horizontalScrollbars : verticalScrollbars;
const scrollbar = createDiv(`${classNameScrollbar} ${scrollbarClassName} os-theme-dark`);
const track = createDiv(classNameScrollbarTrack);
const handle = createDiv(classNameScrollbarHandle);
const result = {
_scrollbar: scrollbar,
_track: track,
_handle: handle,
};
appendChildren(scrollbar, track);
appendChildren(track, handle);
push(destroyFns, removeElements.bind(0, scrollbar));
push(arrToPush, result);
push(
destroyFns,
on(scrollbar, interactionStartEventNames, () => {
addRemoveClassHorizontal(classNamesScrollbarInteraction, true);
addRemoveClassVertical(classNamesScrollbarInteraction, true);
})
);
push(
destroyFns,
on(scrollbar, interactionEndEventNames, () => {
addRemoveClassHorizontal(classNamesScrollbarInteraction);
addRemoveClassVertical(classNamesScrollbarInteraction);
})
);
return result;
};
const generateHorizontalScrollbarStructure = generateScrollbarDOM.bind(0, true);
const generateVerticalScrollbarStructure = generateScrollbarDOM.bind(0, false);
const appendElements = () => {
appendChildren(evaluatedScrollbarSlot, horizontalScrollbars[0]._scrollbar);
appendChildren(evaluatedScrollbarSlot, verticalScrollbars[0]._scrollbar);
};
generateHorizontalScrollbarStructure();
generateVerticalScrollbarStructure();
return [
{
_horizontalScrollbarStructure: horizontalScrollbarStructure,
_verticalScrollbarStructure: verticalScrollbarStructure,
_horizontal: {
_scrollbarStructures: horizontalScrollbars,
_clone: generateHorizontalScrollbarStructure,
_addRemoveClass: addRemoveClassHorizontal,
},
_vertical: {
_scrollbarStructures: verticalScrollbars,
_clone: generateVerticalScrollbarStructure,
_addRemoveClass: addRemoveClassVertical,
},
},
appendElements,
removeElements.bind(0, [horizontalScrollbar, verticalScrollbar]),
runEachAndClear.bind(0, destroyFns),
];
};
@@ -1,12 +1,23 @@
import { rAF, cAF, isFunction, on, runEachAndClear } from 'support';
import { createState, createOptionCheck } from 'setups/setups';
import {
createScrollbarsSetupElements,
ScrollbarsSetupElementsObj,
} from 'setups/scrollbarsSetup/scrollbarsSetup.elements';
import type { StructureSetupElementsObj } from 'setups/structureSetup/structureSetup.elements';
import type { ReadonlyOSOptions } from 'options';
import type { Setup } from 'setups';
import {
classNamesScrollbarVisible,
classNamesScrollbarCornerless,
classNamesScrollbarAutoHidden,
} from 'classnames';
import type { StructureSetupUpdateHints } from 'setups/structureSetup/structureSetup.update';
import type {
ReadonlyOSOptions,
ScrollbarVisibilityBehavior,
ScrollbarAutoHideBehavior,
} from 'options';
import type { Setup, StructureSetupState, StructureSetupStaticState } from 'setups';
import type { InitializationTarget } from 'initialization';
import type { OverflowStyle } from 'typings';
// eslint-disable-next-line @typescript-eslint/no-empty-interface
export interface ScrollbarsSetupState {}
@@ -16,33 +27,154 @@ export interface ScrollbarsSetupStaticState {
_appendElements: () => void;
}
const createSelfCancelTimeout = (timeout?: number | (() => number)) => {
let id: number;
const setT = timeout ? (window.setTimeout as (...args: any[]) => number) : rAF!;
const clearT = timeout ? window.clearTimeout : cAF!;
return [
(callback: () => any) => {
clearT(id);
// @ts-ignore
id = setT(callback, isFunction(timeout) ? timeout() : timeout);
},
() => clearT(id),
] as [timeout: (callback: () => any) => void, clear: () => void];
};
export const createScrollbarsSetup = (
target: InitializationTarget,
options: ReadonlyOSOptions,
structureSetupElements: StructureSetupElementsObj
): Setup<ScrollbarsSetupState, ScrollbarsSetupStaticState> => {
structureSetupState: (() => StructureSetupState) & StructureSetupStaticState
): Setup<ScrollbarsSetupState, ScrollbarsSetupStaticState, [StructureSetupUpdateHints]> => {
let globalAutoHideDelay = 0;
let autoHideIsMove: boolean;
let autoHideIsLeave: boolean;
let autoHideNotNever: boolean;
let mouseInHost: boolean;
const state = createState({});
const [getState] = state;
const [requestMouseMoveAnimationFrame, cancelMouseMoveAnimationFrame] = createSelfCancelTimeout();
const [requestScrollAnimationFrame, cancelScrollAnimationFrame] = createSelfCancelTimeout();
const [scrollTimeout, clearScrollTimeout] = createSelfCancelTimeout(100);
const [auotHideMoveTimeout, clearAutoHideTimeout] = createSelfCancelTimeout(100);
const [auotHideTimeout, clearAutoTimeout] = createSelfCancelTimeout(() => globalAutoHideDelay);
const [elements, appendElements, destroyElements] = createScrollbarsSetupElements(
target,
structureSetupElements
structureSetupState._elements
);
const { _host, _viewport } = structureSetupState._elements;
const { _horizontal, _vertical } = elements;
const { _addRemoveClass: addRemoveClassHorizontal } = _horizontal;
const { _addRemoveClass: addRemoveClassVertical } = _vertical;
const manageScrollbarsAutoHide = (removeAutoHide: boolean, delayless?: boolean) => {
clearAutoTimeout();
if (removeAutoHide) {
addRemoveClassHorizontal(classNamesScrollbarAutoHidden);
addRemoveClassVertical(classNamesScrollbarAutoHidden);
} else {
const hide = () => {
addRemoveClassHorizontal(classNamesScrollbarAutoHidden, true);
addRemoveClassVertical(classNamesScrollbarAutoHidden, true);
};
if (globalAutoHideDelay > 0 && !delayless) {
auotHideTimeout(hide);
} else {
hide();
}
}
};
const onHostMouseEnter = () => {
mouseInHost = autoHideIsLeave;
mouseInHost && manageScrollbarsAutoHide(true);
};
const destroyFns: (() => void)[] = [
clearScrollTimeout,
clearAutoTimeout,
clearAutoHideTimeout,
cancelScrollAnimationFrame,
cancelMouseMoveAnimationFrame,
destroyElements,
on(_host, 'mouseover', onHostMouseEnter, { _once: true }),
on(_host, 'mouseenter', onHostMouseEnter),
on(_host, 'mouseleave', () => {
mouseInHost = false;
autoHideIsLeave && manageScrollbarsAutoHide(false);
}),
on(_host, 'mousemove', () => {
autoHideIsMove &&
requestMouseMoveAnimationFrame(() => {
clearScrollTimeout();
manageScrollbarsAutoHide(true);
auotHideMoveTimeout(() => {
autoHideIsMove && manageScrollbarsAutoHide(false);
});
});
}),
on(_viewport, 'scroll', () => {
autoHideNotNever &&
requestScrollAnimationFrame(() => {
manageScrollbarsAutoHide(true);
scrollTimeout(() => {
autoHideNotNever && !mouseInHost && manageScrollbarsAutoHide(false);
});
});
}),
];
const scrollbarsSetupState = getState.bind(0) as (() => ScrollbarsSetupState) &
ScrollbarsSetupStaticState;
scrollbarsSetupState._elements = elements;
scrollbarsSetupState._appendElements = appendElements;
return [
(changedOptions, force?) => {
(changedOptions, force, structureUpdateHints) => {
const { _overflowEdgeChanged, _overflowAmountChanged, _overflowStyleChanged } =
structureUpdateHints;
const checkOption = createOptionCheck(options, changedOptions, force);
// eslint-disable-next-line no-console
console.log(checkOption);
const [visibility, visibilityChanged] =
checkOption<ScrollbarVisibilityBehavior>('scrollbars.visibility');
const [autoHide, autoHideChanged] =
checkOption<ScrollbarAutoHideBehavior>('scrollbars.autoHide');
const [autoHideDelay] = checkOption<number>('scrollbars.autoHideDelay');
const [dragScrolling, dragScrollingChanged] = checkOption<boolean>(
'scrollbars.dragScrolling'
);
const [touchSupport, touchSupportChanged] = checkOption<boolean>('scrollbars.touchSupport');
const updateHandleSize = _overflowEdgeChanged || _overflowAmountChanged;
const updateVisibility = _overflowStyleChanged || visibilityChanged;
const setScrollbarVisibility = (
overflowStyle: OverflowStyle,
addRemoveClass: (classNames: string, add?: boolean) => void
) => {
const isVisible =
visibility === 'visible' || (visibility === 'auto' && overflowStyle === 'scroll');
addRemoveClass(classNamesScrollbarVisible, isVisible);
return isVisible;
};
globalAutoHideDelay = autoHideDelay;
if (updateVisibility) {
const { _overflowStyle } = structureSetupState();
const xVisible = setScrollbarVisibility(_overflowStyle.x, addRemoveClassHorizontal);
const yVisible = setScrollbarVisibility(_overflowStyle.y, addRemoveClassVertical);
const hasCorner = xVisible && yVisible;
addRemoveClassHorizontal(classNamesScrollbarCornerless, !hasCorner);
addRemoveClassVertical(classNamesScrollbarCornerless, !hasCorner);
}
if (autoHideChanged) {
autoHideIsMove = autoHide === 'move';
autoHideIsLeave = autoHide === 'leave';
autoHideNotNever = autoHide !== 'never';
manageScrollbarsAutoHide(!autoHideNotNever, true);
}
},
scrollbarsSetupState,
() => {
destroyElements();
},
runEachAndClear.bind(0, destroyFns),
];
};
@@ -1,117 +0,0 @@
import { each, isNumber, scrollLeft, scrollTop, assignDeep, keys } from 'support';
import { getEnvironment } from 'environment';
import {
createTrinsicUpdate,
createPaddingUpdate,
createOverflowUpdate,
} from 'setups/structureSetup/updateSegments';
import type { SetupState, SetupUpdateSegment, SetupUpdateCheckOption } from 'setups';
import type { StructureSetupState } from 'setups/structureSetup';
import type { StructureSetupElementsObj } from 'setups/structureSetup/structureSetup.elements';
export type CreateStructureUpdateSegment = (
structureSetupElements: StructureSetupElementsObj,
state: SetupState<StructureSetupState>
) => StructureSetupUpdateSegment;
export type StructureSetupUpdateSegment = SetupUpdateSegment<StructureSetupUpdateHints>;
export type StructureSetupUpdate = (
checkOption: SetupUpdateCheckOption,
updateHints: Partial<StructureSetupUpdateHints>,
force?: boolean
) => StructureSetupUpdateHints;
export interface StructureSetupUpdateHints {
_sizeChanged: boolean;
_directionChanged: boolean;
_heightIntrinsicChanged: boolean;
_overflowAmountChanged: boolean;
_overflowStyleChanged: boolean;
_paddingStyleChanged: boolean;
_hostMutation: boolean;
_contentMutation: boolean;
}
const prepareUpdateHints = <T extends StructureSetupUpdateHints>(
leading: Required<T>,
adaptive?: Partial<T>,
force?: boolean
): Required<T> => {
const result = {};
const finalAdaptive = adaptive || {};
const objKeys = keys(leading).concat(keys(finalAdaptive));
each(objKeys, (key) => {
const leadingValue = leading[key];
const adaptiveValue = finalAdaptive[key];
result[key] = !!(force || leadingValue || adaptiveValue);
});
return result as Required<T>;
};
export const createStructureSetupUpdate = (
structureSetupElements: StructureSetupElementsObj,
state: SetupState<StructureSetupState>
): StructureSetupUpdate => {
const { _viewport } = structureSetupElements;
const {
_nativeScrollbarsHiding: _nativeScrollbarStyling,
_nativeScrollbarsOverlaid: _nativeScrollbarIsOverlaid,
_flexboxGlue,
} = getEnvironment();
const doViewportArrange =
!_nativeScrollbarStyling && (_nativeScrollbarIsOverlaid.x || _nativeScrollbarIsOverlaid.y);
const updateSegments: StructureSetupUpdateSegment[] = [
createTrinsicUpdate(structureSetupElements, state),
createPaddingUpdate(structureSetupElements, state),
createOverflowUpdate(structureSetupElements, state),
];
return (
checkOption: SetupUpdateCheckOption,
updateHints: Partial<StructureSetupUpdateHints>,
force?: boolean
) => {
const initialUpdateHints = prepareUpdateHints(
assignDeep(
{
_sizeChanged: false,
_paddingStyleChanged: false,
_directionChanged: false,
_heightIntrinsicChanged: false,
_overflowAmountChanged: false,
_overflowStyleChanged: false,
_hostMutation: false,
_contentMutation: false,
},
updateHints
),
{},
force
);
const adjustScrollOffset = doViewportArrange || !_flexboxGlue;
const scrollOffsetX = adjustScrollOffset && scrollLeft(_viewport);
const scrollOffsetY = adjustScrollOffset && scrollTop(_viewport);
let adaptivedUpdateHints: Required<StructureSetupUpdateHints> = initialUpdateHints;
each(updateSegments, (updateSegment) => {
adaptivedUpdateHints = prepareUpdateHints<StructureSetupUpdateHints>(
adaptivedUpdateHints,
updateSegment(adaptivedUpdateHints, checkOption, !!force) || {},
force
);
});
if (isNumber(scrollOffsetX)) {
scrollLeft(_viewport, scrollOffsetX);
}
if (isNumber(scrollOffsetY)) {
scrollTop(_viewport, scrollOffsetY);
}
return adaptivedUpdateHints;
};
};
@@ -4,7 +4,11 @@ import type { PartialOptions } from 'typings';
export type SetupElements<T extends Record<string, any>> = [elements: T, destroy: () => void];
export type SetupUpdate<T = void> = (changedOptions: PartialOptions<Options>, force?: boolean) => T;
export type SetupUpdate<T extends any[]> = (
changedOptions: PartialOptions<Options>,
force: boolean,
...args: T
) => void;
export type SetupUpdateCheckOption = <T>(path: string) => [value: T, changed: boolean];
@@ -19,11 +23,11 @@ export type SetupState<T extends Record<string, any>> = [
set: (newState: Partial<T>) => void
];
export type Setup<DynamicState, StaticState extends Record<string, any> = Record<string, any>> = [
update: SetupUpdate,
state: (() => DynamicState) & StaticState,
destroy: () => void
];
export type Setup<
DynamicState,
StaticState extends Record<string, any> = Record<string, any>,
A extends any[] = []
> = [update: SetupUpdate<A>, state: (() => DynamicState) & StaticState, destroy: () => void];
const getPropByPath = <T>(obj: any, path: string): T =>
obj
@@ -1,9 +1,9 @@
import { each, isNumber, scrollLeft, scrollTop, assignDeep, keys } from 'support';
import { getEnvironment } from 'environment';
import {
createTrinsicUpdate,
createPaddingUpdate,
createOverflowUpdate,
createTrinsicUpdateSegment,
createPaddingUpdateSegment,
createOverflowUpdateSegment,
} from 'setups/structureSetup/updateSegments';
import type { SetupState, SetupUpdateSegment, SetupUpdateCheckOption } from 'setups';
import type { StructureSetupState } from 'setups/structureSetup';
@@ -66,9 +66,9 @@ export const createStructureSetupUpdate = (
!_nativeScrollbarStyling && (_nativeScrollbarIsOverlaid.x || _nativeScrollbarIsOverlaid.y);
const updateSegments: StructureSetupUpdateSegment[] = [
createTrinsicUpdate(structureSetupElements, state),
createPaddingUpdate(structureSetupElements, state),
createOverflowUpdate(structureSetupElements, state),
createTrinsicUpdateSegment(structureSetupElements, state),
createPaddingUpdateSegment(structureSetupElements, state),
createOverflowUpdateSegment(structureSetupElements, state),
];
return (
@@ -93,7 +93,7 @@ const overflowIsVisible = (overflowBehavior: string) => overflowBehavior.indexOf
* @param structureUpdateHub
* @returns
*/
export const createOverflowUpdate: CreateStructureUpdateSegment = (
export const createOverflowUpdateSegment: CreateStructureUpdateSegment = (
structureSetupElements,
state
) => {
@@ -8,7 +8,7 @@ import type { CreateStructureUpdateSegment } from 'setups/structureSetup/structu
* @param structureUpdateHub
* @returns
*/
export const createPaddingUpdate: CreateStructureUpdateSegment = (
export const createPaddingUpdateSegment: CreateStructureUpdateSegment = (
structureSetupElements,
state
) => {
@@ -7,7 +7,7 @@ import type { CreateStructureUpdateSegment } from 'setups/structureSetup/structu
* @param structureUpdateHub
* @returns
*/
export const createTrinsicUpdate: CreateStructureUpdateSegment = (
export const createTrinsicUpdateSegment: CreateStructureUpdateSegment = (
structureSetupElements,
state
) => {
@@ -1,11 +1,10 @@
.os-scrollbar-transition {
transition: opacity 0.3s, visibility 0.3s, top 0.3s, right 0.3s, bottom 0.3s, left 0.3s;
}
.os-scrollbar {
transition: opacity 0.3s, visibility 0.3s, top 0.3s, right 0.3s, bottom 0.3s, left 0.3s;
pointer-events: none;
position: absolute;
opacity: 1;
z-index: 0;
opacity: 0;
visibility: hidden;
}
.os-scrollbar-track {
pointer-events: auto;
@@ -48,14 +47,25 @@
right: auto;
left: 0;
}
.os-scrollbar-hidden {
.os-scrollbar-visible {
opacity: 1;
visibility: visible;
}
.os-scrollbar-auto-hidden {
opacity: 0;
visibility: hidden;
pointer-events: none;
}
.os-scrollbar:hover {
opacity: 1 !important;
visibility: visible !important;
.os-scrollbar-interaction.os-scrollbar-visible {
opacity: 1;
visibility: visible;
}
.os-scrollbar.os-scrollbar-horizontal.os-scrollbar-cornerless {
left: 0;
right: 0;
}
.os-scrollbar.os-scrollbar-vertical.os-scrollbar-cornerless {
top: 0;
bottom: 0;
}
/*
@@ -62,7 +62,7 @@ export const on = <T extends Event = Event>(
options?: OnOptions
): (() => void) => {
const doSupportPassiveEvents = supportPassiveEvents();
const passive = (doSupportPassiveEvents && options && options._passive) || false;
const passive = (doSupportPassiveEvents && options && options._passive) ?? doSupportPassiveEvents;
const capture = (options && options._capture) || false;
const once = (options && options._once) || false;
const offListeners: (() => void)[] = [];
@@ -3,7 +3,7 @@ import { from } from 'support/utils/array';
import { rAF, cAF } from 'support/compatibility/apis';
const clearTimeouts = (id: number | undefined) => {
id && window.clearTimeout(id);
id && clearTimeout(id);
id && cAF!(id);
};
@@ -49,7 +49,7 @@ export const debounce = <FunctionToDebounce extends (...args: any) => any>(
let prevArguments: Parameters<FunctionToDebounce> | null | undefined;
let latestArguments: Parameters<FunctionToDebounce> | null | undefined;
const { _timeout, _maxDelay, _mergeParams } = options || {};
const setT = window.setTimeout;
const setT = setTimeout as (...args: any[]) => number;
const invokeFunctionToDebounce = function (args: IArguments) {
clearTimeouts(timeoutId);
@@ -75,7 +75,7 @@ export const isPlainObject = <T = any>(obj: any): obj is PlainObject<T> => {
* @param obj The object which shall be checked.
*/
export const isHTMLElement = (obj: any): obj is HTMLElement => {
const instanceofObj = window.HTMLElement;
const instanceofObj = HTMLElement;
return obj
? instanceofObj
? obj instanceof instanceofObj
@@ -88,7 +88,7 @@ export const isHTMLElement = (obj: any): obj is HTMLElement => {
* @param obj The object which shall be checked.
*/
export const isElement = (obj: any): obj is Element => {
const instanceofObj = window.Element;
const instanceofObj = Element;
return obj
? instanceofObj
? obj instanceof instanceofObj
@@ -39,7 +39,7 @@ describe('dom events', () => {
const once = options?._once;
const expectObjAdd = passive
? {
passive: (options && options._passive) || false,
passive: (options && options._passive) ?? passive,
capture: (options && options._capture) || false,
}
: options?._capture || false;
@@ -104,6 +104,8 @@ body {
background: blue;
border: 1px solid black;
padding: 10px;
height: 10000px;
width: 10000px;
}
.percent {
+7 -4
View File
@@ -24,8 +24,8 @@ type InitialEventListeners<EventMap extends Record<string, any[]>> = {
[K in keyof EventMap]?: EventListener<EventMap> | EventListener<EventMap>[];
};
type OverflowBehavior = "hidden" | "scroll" | "visible" | "visible-hidden" | "visible-scroll";
type VisibilityBehavior = "visible" | "hidden" | "auto";
type AutoHideBehavior = "never" | "scroll" | "leave" | "move";
type ScrollbarVisibilityBehavior = "visible" | "hidden" | "auto";
type ScrollbarAutoHideBehavior = "never" | "scroll" | "leave" | "move";
interface Options {
paddingAbsolute: boolean;
updating: {
@@ -45,8 +45,8 @@ interface Options {
y: OverflowBehavior;
};
scrollbars: {
visibility: VisibilityBehavior;
autoHide: AutoHideBehavior;
visibility: ScrollbarVisibilityBehavior;
autoHide: ScrollbarAutoHideBehavior;
autoHideDelay: number;
dragScroll: boolean;
clickScroll: boolean;
@@ -115,6 +115,7 @@ interface StructureSetupState {
_padding: TRBL;
_paddingAbsolute: boolean;
_viewportPaddingStyle: StyleObject;
_overflowEdge: XY<number>;
_overflowAmount: XY<number>;
_overflowStyle: XY<OverflowStyle>;
_hasOverflow: XY<boolean>;
@@ -196,6 +197,7 @@ interface Environment {
interface State {
padding: TRBL;
paddingAbsolute: boolean;
overflowEdge: XY<number>;
overflowAmount: XY<number>;
overflowStyle: XY<OverflowStyle>;
hasOverflow: XY<boolean>;
@@ -213,6 +215,7 @@ interface OnUpdatedEventListenerArgs {
sizeChanged: boolean;
directionChanged: boolean;
heightIntrinsicChanged: boolean;
overflowEdgeChanged: boolean;
overflowAmountChanged: boolean;
overflowStyleChanged: boolean;
hostMutation: boolean;
+27 -22
View File
@@ -66,33 +66,38 @@ export const resize = (element: HTMLElement) => {
dragResizeBtn = undefined;
};
on(resizeBtn, strMouseTouchDownEvent, (event: MouseEvent | TouchEvent) => {
const { currentTarget } = event;
const correctButton = (event as MouseEvent).buttons === 1 || event.which === 1;
const isTouchEvent = (event as TouchEvent).touches !== undefined;
const mouseOffsetHolder = isTouchEvent
? (event as TouchEvent).touches[0]
: (event as MouseEvent);
on(
resizeBtn,
strMouseTouchDownEvent,
(event: MouseEvent | TouchEvent) => {
const { currentTarget } = event;
const correctButton = (event as MouseEvent).buttons === 1 || event.which === 1;
const isTouchEvent = (event as TouchEvent).touches !== undefined;
const mouseOffsetHolder = isTouchEvent
? (event as TouchEvent).touches[0]
: (event as MouseEvent);
if (correctButton || isTouchEvent) {
dragStartPosition.x = mouseOffsetHolder.pageX;
dragStartPosition.y = mouseOffsetHolder.pageY;
if (correctButton || isTouchEvent) {
dragStartPosition.x = mouseOffsetHolder.pageX;
dragStartPosition.y = mouseOffsetHolder.pageY;
dragResizeBtn = currentTarget as HTMLElement;
dragResizer = parent(currentTarget as HTMLElement) as HTMLElement;
dragResizeBtn = currentTarget as HTMLElement;
dragResizer = parent(currentTarget as HTMLElement) as HTMLElement;
const cSize = clientSize(element);
dragStartSize.w = cSize.w;
dragStartSize.h = cSize.h;
const cSize = clientSize(element);
dragStartSize.w = cSize.w;
dragStartSize.h = cSize.h;
on(document, strSelectStartEvent, onSelectStart);
on(document, strMouseTouchMoveEvent, resizerResize);
on(document, strMouseTouchUpEvent, resizerResized);
on(document, strSelectStartEvent, onSelectStart, { _passive: false });
on(document, strMouseTouchMoveEvent, resizerResize, { _passive: false });
on(document, strMouseTouchUpEvent, resizerResized, { _passive: false });
event.preventDefault();
event.stopPropagation();
}
});
event.preventDefault();
event.stopPropagation();
}
},
{ _passive: false }
);
return {
addResizeListener(listener: ResizeListener) {