mirror of
https://github.com/tenrok/OverlayScrollbars.git
synced 2026-05-24 02:54:07 +03:00
improve initialization
This commit is contained in:
@@ -7,6 +7,7 @@ export const dataAttributeHostOverflowX = `${dataAttributeHost}-overflow-x`;
|
||||
export const dataAttributeHostOverflowY = `${dataAttributeHost}-overflow-y`;
|
||||
export const dataValueHostOverflowVisible = 'overflowVisible';
|
||||
export const dataValueHostScrollbarHidden = 'scrollbarHidden';
|
||||
export const dataValueHostUpdating = 'updating';
|
||||
export const classNamePadding = 'os-padding';
|
||||
export const classNameViewport = 'os-viewport';
|
||||
export const classNameViewportArrange = `${classNameViewport}-arrange`;
|
||||
|
||||
@@ -28,7 +28,7 @@ import {
|
||||
} from 'classnames';
|
||||
import { Options, defaultOptions } from 'options';
|
||||
import { DeepPartial } from 'typings';
|
||||
import { DefaultInitialization } from 'initialization';
|
||||
import { Initialization } from 'initialization';
|
||||
import { getPlugins, ScrollbarsHidingPluginInstance, scrollbarsHidingPluginName } from 'plugins';
|
||||
|
||||
type EnvironmentEventMap = {
|
||||
@@ -42,11 +42,11 @@ export interface InternalEnvironment {
|
||||
readonly _rtlScrollBehavior: { n: boolean; i: boolean };
|
||||
readonly _flexboxGlue: boolean;
|
||||
readonly _cssCustomProperties: boolean;
|
||||
readonly _staticDefaultInitialization: DefaultInitialization;
|
||||
readonly _staticDefaultInitialization: Initialization;
|
||||
readonly _staticDefaultOptions: Options;
|
||||
_addListener(listener: EventListener<EnvironmentEventMap, '_'>): () => void;
|
||||
_getDefaultInitialization(): DefaultInitialization;
|
||||
_setDefaultInitialization(newInitialization: DeepPartial<DefaultInitialization>): void;
|
||||
_getDefaultInitialization(): Initialization;
|
||||
_setDefaultInitialization(newInitialization: DeepPartial<Initialization>): void;
|
||||
_getDefaultOptions(): Options;
|
||||
_setDefaultOptions(newDefaultOptions: DeepPartial<Options>): void;
|
||||
}
|
||||
@@ -152,15 +152,18 @@ const createEnvironment = (): InternalEnvironment => {
|
||||
x: nativeScrollbarsSize.x === 0,
|
||||
y: nativeScrollbarsSize.y === 0,
|
||||
};
|
||||
const defaultInitialization = {
|
||||
const staticDefaultInitialization: Initialization = {
|
||||
host: null,
|
||||
padding: !nativeScrollbarsHiding,
|
||||
viewport: (target) => nativeScrollbarsHiding && target === target.ownerDocument.body && target,
|
||||
content: false,
|
||||
scrollbarsSlot: true,
|
||||
cancel: {
|
||||
nativeScrollbarsOverlaid: true,
|
||||
body: null,
|
||||
},
|
||||
};
|
||||
const defaultDefaultOptions = assignDeep({}, defaultOptions);
|
||||
const staticDefaultOptions = assignDeep({}, defaultOptions);
|
||||
|
||||
const env: InternalEnvironment = {
|
||||
_nativeScrollbarsSize: nativeScrollbarsSize,
|
||||
@@ -170,20 +173,20 @@ const createEnvironment = (): InternalEnvironment => {
|
||||
_rtlScrollBehavior: getRtlScrollBehavior(envElm, envChildElm),
|
||||
_flexboxGlue: getFlexboxGlue(envElm, envChildElm),
|
||||
_addListener: (listener) => addEvent('_', listener),
|
||||
_getDefaultInitialization: assignDeep<DefaultInitialization, DefaultInitialization>.bind(
|
||||
_getDefaultInitialization: assignDeep<Initialization, Initialization>.bind(
|
||||
0,
|
||||
{} as DefaultInitialization,
|
||||
defaultInitialization
|
||||
{} as Initialization,
|
||||
staticDefaultInitialization
|
||||
),
|
||||
_setDefaultInitialization(newInitializationStrategy) {
|
||||
assignDeep(defaultInitialization, newInitializationStrategy);
|
||||
assignDeep(staticDefaultInitialization, newInitializationStrategy);
|
||||
},
|
||||
_getDefaultOptions: assignDeep<Options, Options>.bind(0, {} as Options, defaultDefaultOptions),
|
||||
_getDefaultOptions: assignDeep<Options, Options>.bind(0, {} as Options, staticDefaultOptions),
|
||||
_setDefaultOptions(newDefaultOptions) {
|
||||
assignDeep(defaultDefaultOptions, newDefaultOptions);
|
||||
assignDeep(staticDefaultOptions, newDefaultOptions);
|
||||
},
|
||||
_staticDefaultInitialization: assignDeep({}, defaultInitialization),
|
||||
_staticDefaultOptions: assignDeep({}, defaultDefaultOptions),
|
||||
_staticDefaultInitialization: assignDeep({}, staticDefaultInitialization),
|
||||
_staticDefaultOptions: assignDeep({}, staticDefaultOptions),
|
||||
};
|
||||
|
||||
removeAttr(envElm, 'style');
|
||||
|
||||
@@ -1,41 +1,31 @@
|
||||
import { isBoolean, isFunction, isNull, isUndefined } from 'support';
|
||||
import type {
|
||||
StructureInitialization,
|
||||
DefaultStructureInitialization,
|
||||
} from 'setups/structureSetup';
|
||||
import type {
|
||||
ScrollbarsInitialization,
|
||||
DefaultScrollbarsInitialization,
|
||||
} from 'setups/scrollbarsSetup';
|
||||
import { isFunction, isHTMLElement, isNull, isUndefined } from 'support';
|
||||
import type { StructureInitialization } from 'setups/structureSetup';
|
||||
import type { ScrollbarsInitialization } from 'setups/scrollbarsSetup';
|
||||
import { getEnvironment } from 'environment';
|
||||
import { DeepPartial } from 'typings';
|
||||
import { StructureSetupElementsObj } from 'setups/structureSetup/structureSetup.elements';
|
||||
|
||||
type StaticInitialization = HTMLElement | null | undefined;
|
||||
type DynamicInitialization = HTMLElement | boolean | null | undefined;
|
||||
|
||||
export type CancelInitialization = {
|
||||
cancel: {
|
||||
nativeScrollbarsOverlaid: boolean | undefined;
|
||||
body: boolean | null | undefined;
|
||||
};
|
||||
};
|
||||
type StaticInitialization = HTMLElement | false | null;
|
||||
type DynamicInitialization = HTMLElement | boolean | null;
|
||||
|
||||
export type InitializationTargetElement = HTMLElement | HTMLTextAreaElement;
|
||||
|
||||
export type InitializationTargetObject = StructureInitialization &
|
||||
ScrollbarsInitialization &
|
||||
DeepPartial<CancelInitialization>;
|
||||
export type Initialization = Omit<StructureInitialization, 'target'> &
|
||||
ScrollbarsInitialization & {
|
||||
cancel: {
|
||||
nativeScrollbarsOverlaid: boolean;
|
||||
body: boolean | null;
|
||||
};
|
||||
};
|
||||
|
||||
export type InitializationTargetObject = DeepPartial<Initialization> &
|
||||
Pick<StructureInitialization, 'target'>;
|
||||
|
||||
export type InitializationTarget = InitializationTargetElement | InitializationTargetObject;
|
||||
|
||||
export type DefaultInitialization = DefaultStructureInitialization &
|
||||
DefaultScrollbarsInitialization &
|
||||
CancelInitialization;
|
||||
|
||||
/**
|
||||
* Static elements MUST be present.
|
||||
* Null or undefined behave like if this element wasn't specified during initialization.
|
||||
* With false, null or undefined the element will be generated, otherwise the specified element is taken.
|
||||
*/
|
||||
export type StaticInitializationElement<Args extends any[]> =
|
||||
| ((...args: Args) => StaticInitialization)
|
||||
@@ -43,17 +33,14 @@ export type StaticInitializationElement<Args extends any[]> =
|
||||
|
||||
/**
|
||||
* Dynamic element CAN be present.
|
||||
* If its a element the element will be handled as the repsective element.
|
||||
* True means that the respective dynamic element is forced to be generated.
|
||||
* False means that the respective dynamic element is forced NOT to be generated.
|
||||
* Null or undefined behave like if this element wasn't specified during initialization.
|
||||
* If its a element the element will be taken as the repsective element.
|
||||
* With true the element will be generated.
|
||||
* With false, null or undefined the element won't be generated.
|
||||
*/
|
||||
export type DynamicInitializationElement<Args extends any[]> =
|
||||
| ((...args: Args) => DynamicInitialization)
|
||||
| DynamicInitialization;
|
||||
|
||||
export type DefaultInitializtationElement<InitElm> = Exclude<InitElm, HTMLElement>;
|
||||
|
||||
export type FallbackInitializtationElement<
|
||||
InitElm extends StaticInitializationElement<any> | DynamicInitializationElement<any>
|
||||
> = Extract<InitElm, (...args: any[]) => any> extends (...args: infer P) => any
|
||||
@@ -66,40 +53,42 @@ const resolveInitialization = <T>(value: any, args: any): T =>
|
||||
const staticInitializationElement = <T extends StaticInitializationElement<any>>(
|
||||
args: Parameters<Extract<T, (...args: any[]) => any>>,
|
||||
fallbackStaticInitializationElement: FallbackInitializtationElement<T>,
|
||||
defaultStaticInitializationElementStrategy?: DefaultInitializtationElement<T>,
|
||||
staticInitializationElementValue?: T | false
|
||||
): HTMLElement =>
|
||||
resolveInitialization<StaticInitialization>(
|
||||
staticInitializationElementValue ||
|
||||
resolveInitialization<StaticInitialization>(defaultStaticInitializationElementStrategy, args),
|
||||
defaultStaticInitializationElementStrategy: T,
|
||||
staticInitializationElementValue?: T
|
||||
): HTMLElement => {
|
||||
const staticInitialization = isUndefined(staticInitializationElementValue)
|
||||
? defaultStaticInitializationElementStrategy
|
||||
: staticInitializationElementValue;
|
||||
const resolvedInitialization = resolveInitialization<StaticInitialization>(
|
||||
staticInitialization,
|
||||
args
|
||||
) || fallbackStaticInitializationElement.apply(0, args);
|
||||
);
|
||||
return resolvedInitialization || fallbackStaticInitializationElement();
|
||||
};
|
||||
|
||||
const dynamicInitializationElement = <T extends DynamicInitializationElement<any>>(
|
||||
args: Parameters<Extract<T, (...args: any[]) => any>>,
|
||||
fallbackDynamicInitializationElement: FallbackInitializtationElement<T>,
|
||||
defaultDynamicInitializationElementStrategy?: DefaultInitializtationElement<T>,
|
||||
dynamicInitializationElementValue?: T | false
|
||||
defaultDynamicInitializationElementStrategy: T,
|
||||
dynamicInitializationElementValue?: T
|
||||
): HTMLElement | false => {
|
||||
let result = resolveInitialization<DynamicInitialization>(
|
||||
dynamicInitializationElementValue,
|
||||
const dynamicInitialization = isUndefined(dynamicInitializationElementValue)
|
||||
? defaultDynamicInitializationElementStrategy
|
||||
: dynamicInitializationElementValue;
|
||||
const resolvedInitialization = resolveInitialization<DynamicInitialization>(
|
||||
dynamicInitialization,
|
||||
args
|
||||
);
|
||||
|
||||
if (isNull(result) || isUndefined(result)) {
|
||||
result = resolveInitialization<DynamicInitialization>(
|
||||
defaultDynamicInitializationElementStrategy,
|
||||
args
|
||||
);
|
||||
}
|
||||
|
||||
return result === true || isNull(result) || isUndefined(result)
|
||||
? fallbackDynamicInitializationElement.apply(0, args)
|
||||
: result;
|
||||
return (
|
||||
!!resolvedInitialization &&
|
||||
(isHTMLElement(resolvedInitialization)
|
||||
? resolvedInitialization
|
||||
: fallbackDynamicInitializationElement())
|
||||
);
|
||||
};
|
||||
|
||||
const cancelInitialization = (
|
||||
cancelInitializationValue: DeepPartial<CancelInitialization['cancel']> | false | null | undefined,
|
||||
cancelInitializationValue: DeepPartial<Initialization['cancel']> | false | null | undefined,
|
||||
structureSetupElements: StructureSetupElementsObj
|
||||
): boolean => {
|
||||
const { nativeScrollbarsOverlaid, body } = cancelInitializationValue || {};
|
||||
@@ -110,7 +99,7 @@ const cancelInitialization = (
|
||||
|
||||
const resolvedNativeScrollbarsOverlaid =
|
||||
nativeScrollbarsOverlaid ?? defaultNativeScrollbarsOverlaid;
|
||||
const resolvedDocumentScrollingElement = isBoolean(body) || isNull(body) ? body : defaultbody;
|
||||
const resolvedDocumentScrollingElement = isUndefined(body) ? defaultbody : body;
|
||||
|
||||
const finalNativeScrollbarsOverlaid =
|
||||
(_nativeScrollbarsOverlaid.x || _nativeScrollbarsOverlaid.y) &&
|
||||
|
||||
@@ -21,12 +21,7 @@ import {
|
||||
} from 'plugins';
|
||||
import { addInstance, getInstance, removeInstance } from 'instances';
|
||||
import type { DeepPartial, OverflowStyle } from 'typings';
|
||||
import {
|
||||
InitializationTarget,
|
||||
InitializationTargetObject,
|
||||
DefaultInitialization,
|
||||
cancelInitialization,
|
||||
} from 'initialization';
|
||||
import { InitializationTarget, Initialization, cancelInitialization } from 'initialization';
|
||||
import type {
|
||||
InitialEventListeners as GeneralInitialEventListeners,
|
||||
EventListener as GeneralEventListener,
|
||||
@@ -34,7 +29,7 @@ import type {
|
||||
|
||||
export interface OverlayScrollbarsStatic {
|
||||
(
|
||||
target: InitializationTarget | InitializationTargetObject,
|
||||
target: InitializationTarget,
|
||||
options?: DeepPartial<Options>,
|
||||
eventListeners?: GeneralInitialEventListeners<EventListenerMap>
|
||||
): OverlayScrollbars;
|
||||
@@ -50,11 +45,11 @@ export interface Environment {
|
||||
rtlScrollBehavior: { n: boolean; i: boolean };
|
||||
flexboxGlue: boolean;
|
||||
cssCustomProperties: boolean;
|
||||
staticDefaultInitialization: DefaultInitialization;
|
||||
staticDefaultInitialization: Initialization;
|
||||
staticDefaultOptions: Options;
|
||||
|
||||
getDefaultInitialization(): DefaultInitialization;
|
||||
setDefaultInitialization(newDefaultInitialization: DeepPartial<DefaultInitialization>): void;
|
||||
getDefaultInitialization(): Initialization;
|
||||
setDefaultInitialization(newDefaultInitialization: DeepPartial<Initialization>): void;
|
||||
getDefaultOptions(): Options;
|
||||
setDefaultOptions(newDefaultOptions: DeepPartial<Options>): void;
|
||||
}
|
||||
|
||||
@@ -29,7 +29,6 @@ import type { InitializationTarget } from 'initialization';
|
||||
import type { StructureSetupElementsObj } from 'setups/structureSetup/structureSetup.elements';
|
||||
import type {
|
||||
ScrollbarsInitialization,
|
||||
DefaultScrollbarsInitialization,
|
||||
ScrollbarsDynamicInitializationElement,
|
||||
} from 'setups/scrollbarsSetup/scrollbarsSetup.initialization';
|
||||
import { StyleObject } from 'typings';
|
||||
@@ -86,8 +85,7 @@ export const createScrollbarsSetupElements = (
|
||||
structureSetupElements: StructureSetupElementsObj
|
||||
): ScrollbarsSetupElements => {
|
||||
const { _getDefaultInitialization } = getEnvironment();
|
||||
const { scrollbarsSlot: defaultScrollbarSlot } =
|
||||
_getDefaultInitialization() as DefaultScrollbarsInitialization;
|
||||
const { scrollbarsSlot: defaultScrollbarSlot } = _getDefaultInitialization();
|
||||
const { _documentElm, _target, _host, _viewport, _targetIsElm } = structureSetupElements;
|
||||
const scrollbarSlot = _targetIsElm ? null : (target as ScrollbarsInitialization).scrollbarsSlot;
|
||||
const evaluatedScrollbarSlot =
|
||||
|
||||
+2
-10
@@ -1,8 +1,4 @@
|
||||
import type {
|
||||
InitializationTargetElement,
|
||||
DefaultInitializtationElement,
|
||||
DynamicInitializationElement,
|
||||
} from 'initialization';
|
||||
import type { InitializationTargetElement, DynamicInitializationElement } from 'initialization';
|
||||
|
||||
export type ScrollbarsDynamicInitializationElement = DynamicInitializationElement<
|
||||
[target: InitializationTargetElement, host: HTMLElement, viewport: HTMLElement]
|
||||
@@ -17,9 +13,5 @@ export type ScrollbarsDynamicInitializationElement = DynamicInitializationElemen
|
||||
* Null or Undefined means that the environment initialization strategy is used.
|
||||
*/
|
||||
export interface ScrollbarsInitialization {
|
||||
scrollbarsSlot?: ScrollbarsDynamicInitializationElement;
|
||||
scrollbarsSlot: ScrollbarsDynamicInitializationElement;
|
||||
}
|
||||
|
||||
export type DefaultScrollbarsInitialization = {
|
||||
[K in keyof ScrollbarsInitialization]: DefaultInitializtationElement<ScrollbarsInitialization[K]>;
|
||||
};
|
||||
|
||||
@@ -1,9 +1,21 @@
|
||||
import { rAF, cAF, isFunction, on, runEachAndClear, setT, clearT } from 'support';
|
||||
import {
|
||||
rAF,
|
||||
cAF,
|
||||
isFunction,
|
||||
on,
|
||||
runEachAndClear,
|
||||
setT,
|
||||
clearT,
|
||||
parent,
|
||||
scrollLeft,
|
||||
scrollTop,
|
||||
} from 'support';
|
||||
import { createState, createOptionCheck } from 'setups/setups';
|
||||
import {
|
||||
createScrollbarsSetupElements,
|
||||
ScrollbarsSetupElement,
|
||||
ScrollbarsSetupElementsObj,
|
||||
ScrollbarStructure,
|
||||
} from 'setups/scrollbarsSetup/scrollbarsSetup.elements';
|
||||
import {
|
||||
classNamesScrollbarVisible,
|
||||
@@ -18,7 +30,7 @@ import type {
|
||||
} from 'options';
|
||||
import type { Setup, StructureSetupState, StructureSetupStaticState } from 'setups';
|
||||
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
|
||||
export interface ScrollbarsSetupState {}
|
||||
@@ -121,10 +133,20 @@ export const createScrollbarsSetup = (
|
||||
target,
|
||||
structureSetupState._elements
|
||||
);
|
||||
const { _host, _viewport } = structureSetupState._elements;
|
||||
const { _host, _viewport, _viewportIsTarget, _isBody } = structureSetupState._elements;
|
||||
const { _horizontal, _vertical } = elements;
|
||||
const { _addRemoveClass: addRemoveClassHorizontal, _handleStyle: styleHorizontal } = _horizontal;
|
||||
const { _addRemoveClass: addRemoveClassVertical, _handleStyle: styleVertical } = _vertical;
|
||||
const styleScrollbarPosition = (structure: ScrollbarStructure) => {
|
||||
const { _scrollbar } = structure;
|
||||
const elm = _viewportIsTarget && _isBody && parent(_scrollbar) === _viewport && _scrollbar;
|
||||
return [
|
||||
elm,
|
||||
{
|
||||
transform: elm ? `translate(${scrollLeft(_viewport)}px, ${scrollTop(_viewport)}px)` : '',
|
||||
},
|
||||
] as [HTMLElement | false, StyleObject];
|
||||
};
|
||||
const manageScrollbarsAutoHide = (removeAutoHide: boolean, delayless?: boolean) => {
|
||||
clearAutoTimeout();
|
||||
if (removeAutoHide) {
|
||||
@@ -146,6 +168,7 @@ export const createScrollbarsSetup = (
|
||||
mouseInHost = autoHideIsLeave;
|
||||
mouseInHost && manageScrollbarsAutoHide(true);
|
||||
};
|
||||
|
||||
const destroyFns: (() => void)[] = [
|
||||
clearScrollTimeout,
|
||||
clearAutoTimeout,
|
||||
@@ -181,6 +204,9 @@ export const createScrollbarsSetup = (
|
||||
autoHideNotNever && !mouseInHost && manageScrollbarsAutoHide(false);
|
||||
});
|
||||
});
|
||||
|
||||
_viewportIsTarget && styleHorizontal(styleScrollbarPosition);
|
||||
_viewportIsTarget && styleVertical(styleScrollbarPosition);
|
||||
}),
|
||||
];
|
||||
const scrollbarsSetupState = getState.bind(0) as (() => ScrollbarsSetupState) &
|
||||
|
||||
@@ -19,8 +19,6 @@ import {
|
||||
removeAttr,
|
||||
attrClass,
|
||||
hasAttrClass,
|
||||
ResizeObserverConstructor,
|
||||
hasOwnProperty,
|
||||
noop,
|
||||
} from 'support';
|
||||
import {
|
||||
@@ -38,9 +36,12 @@ import type { ScrollbarsHidingPluginInstance } from 'plugins/scrollbarsHidingPlu
|
||||
import {
|
||||
staticInitializationElement as generalStaticInitializationElement,
|
||||
dynamicInitializationElement as generalDynamicInitializationElement,
|
||||
} from 'initialization';
|
||||
import type {
|
||||
InitializationTarget,
|
||||
InitializationTargetElement,
|
||||
InitializationTargetObject,
|
||||
} from 'initialization';
|
||||
import type { InitializationTarget, InitializationTargetElement } from 'initialization';
|
||||
import type {
|
||||
StructureDynamicInitializationElement,
|
||||
StructureStaticInitializationElement,
|
||||
@@ -93,18 +94,18 @@ export const createStructureSetupElements = (
|
||||
const createUniqueViewportArrangeElement =
|
||||
scrollbarsHidingPlugin && scrollbarsHidingPlugin._createUniqueViewportArrangeElement;
|
||||
const {
|
||||
host: defaultHostInitializationStrategy,
|
||||
viewport: defaultViewportInitializationStrategy,
|
||||
padding: defaultPaddingInitializationStrategy,
|
||||
content: defaultContentInitializationStrategy,
|
||||
host: defaultHostInitialization,
|
||||
viewport: defaultViewportInitialization,
|
||||
padding: defaultPaddingInitialization,
|
||||
content: defaultContentInitialization,
|
||||
} = _getDefaultInitialization();
|
||||
const targetIsElm = isHTMLElement(target);
|
||||
const targetStructureInitialization = (targetIsElm ? {} : target) as InitializationTargetObject;
|
||||
const {
|
||||
host: hostInitializationStrategy,
|
||||
padding: paddingInitializationStrategy,
|
||||
viewport: viewportInitializationStrategy,
|
||||
content: contentInitializationStrategy,
|
||||
host: hostInitialization,
|
||||
padding: paddingInitialization,
|
||||
viewport: viewportInitialization,
|
||||
content: contentInitialization,
|
||||
} = targetStructureInitialization;
|
||||
|
||||
const targetElement = targetIsElm ? target : targetStructureInitialization.target;
|
||||
@@ -112,9 +113,6 @@ export const createStructureSetupElements = (
|
||||
const ownerDocument = targetElement.ownerDocument;
|
||||
const isBody = targetElement === ownerDocument.body;
|
||||
const wnd = ownerDocument.defaultView as Window;
|
||||
const singleElmSupport = isBody
|
||||
? _nativeScrollbarsHiding
|
||||
: !!ResizeObserverConstructor && !isTextarea && _nativeScrollbarsHiding;
|
||||
const staticInitializationElement =
|
||||
generalStaticInitializationElement<StructureStaticInitializationElement>.bind(0, [
|
||||
targetElement,
|
||||
@@ -123,43 +121,31 @@ export const createStructureSetupElements = (
|
||||
generalDynamicInitializationElement<StructureDynamicInitializationElement>.bind(0, [
|
||||
targetElement,
|
||||
]);
|
||||
const viewportElement = [
|
||||
staticInitializationElement(
|
||||
createNewDiv,
|
||||
defaultViewportInitializationStrategy,
|
||||
isBody && !hasOwnProperty(targetStructureInitialization, 'viewport')
|
||||
? targetElement
|
||||
: viewportInitializationStrategy
|
||||
),
|
||||
staticInitializationElement(createNewDiv, defaultViewportInitializationStrategy),
|
||||
staticInitializationElement(createNewDiv),
|
||||
].filter((potentialViewport) =>
|
||||
singleElmSupport ? true : potentialViewport !== targetElement
|
||||
)[0];
|
||||
const viewportElement = staticInitializationElement(
|
||||
createNewDiv,
|
||||
defaultViewportInitialization,
|
||||
viewportInitialization
|
||||
);
|
||||
const viewportIsTarget = viewportElement === targetElement;
|
||||
const evaluatedTargetObj: StructureSetupElementsObj = {
|
||||
_target: targetElement,
|
||||
_host: isTextarea
|
||||
? staticInitializationElement(
|
||||
createNewDiv,
|
||||
defaultHostInitializationStrategy,
|
||||
hostInitializationStrategy
|
||||
)
|
||||
? staticInitializationElement(createNewDiv, defaultHostInitialization, hostInitialization)
|
||||
: (targetElement as HTMLElement),
|
||||
_viewport: viewportElement,
|
||||
_padding:
|
||||
!viewportIsTarget &&
|
||||
dynamicInitializationElement(
|
||||
createNewDiv,
|
||||
defaultPaddingInitializationStrategy,
|
||||
paddingInitializationStrategy
|
||||
defaultPaddingInitialization,
|
||||
paddingInitialization
|
||||
),
|
||||
_content:
|
||||
!viewportIsTarget &&
|
||||
dynamicInitializationElement(
|
||||
createNewDiv,
|
||||
defaultContentInitializationStrategy,
|
||||
contentInitializationStrategy
|
||||
defaultContentInitialization,
|
||||
contentInitialization
|
||||
),
|
||||
_viewportArrange:
|
||||
!viewportIsTarget &&
|
||||
|
||||
+4
-11
@@ -2,7 +2,6 @@ import type {
|
||||
InitializationTargetElement,
|
||||
StaticInitializationElement,
|
||||
DynamicInitializationElement,
|
||||
DefaultInitializtationElement,
|
||||
} from 'initialization';
|
||||
|
||||
export type StructureStaticInitializationElement = StaticInitializationElement<
|
||||
@@ -25,14 +24,8 @@ export type StructureDynamicInitializationElement = DynamicInitializationElement
|
||||
*/
|
||||
export interface StructureInitialization {
|
||||
target: InitializationTargetElement;
|
||||
host?: StructureStaticInitializationElement; // only relevant for textarea
|
||||
viewport?: StructureStaticInitializationElement;
|
||||
padding?: StructureDynamicInitializationElement;
|
||||
content?: StructureDynamicInitializationElement;
|
||||
host: StructureStaticInitializationElement; // only relevant for textarea
|
||||
viewport: StructureStaticInitializationElement;
|
||||
padding: StructureDynamicInitializationElement;
|
||||
content: StructureDynamicInitializationElement;
|
||||
}
|
||||
|
||||
export type DefaultStructureInitialization = {
|
||||
[K in keyof Omit<StructureInitialization, 'target'>]: DefaultInitializtationElement<
|
||||
StructureInitialization[K]
|
||||
>;
|
||||
};
|
||||
|
||||
@@ -27,6 +27,7 @@ import { getEnvironment } from 'environment';
|
||||
import {
|
||||
dataAttributeHost,
|
||||
dataValueHostOverflowVisible,
|
||||
dataValueHostUpdating,
|
||||
classNameViewport,
|
||||
classNameOverflowVisible,
|
||||
classNameScrollbar,
|
||||
@@ -100,6 +101,7 @@ export const createStructureSetupObservers = (
|
||||
const scrollOffsetY = hasVpStyle && scrollTop(_viewport);
|
||||
_viewportAddRemoveClass(classNameOverflowVisible, dataValueHostOverflowVisible);
|
||||
_viewportAddRemoveClass(classNameViewportArrange, '');
|
||||
_viewportAddRemoveClass('', dataValueHostUpdating, true);
|
||||
|
||||
const contentScroll = scrollSize(_content);
|
||||
const viewportScroll = scrollSize(_viewport);
|
||||
@@ -107,6 +109,7 @@ export const createStructureSetupObservers = (
|
||||
|
||||
_viewportAddRemoveClass(classNameOverflowVisible, dataValueHostOverflowVisible, hasOver);
|
||||
_viewportAddRemoveClass(classNameViewportArrange, '', hasVpStyle);
|
||||
_viewportAddRemoveClass('', dataValueHostUpdating, false);
|
||||
scrollLeft(_viewport, scrollOffsetX);
|
||||
scrollTop(_viewport, scrollOffsetY);
|
||||
return {
|
||||
@@ -224,7 +227,8 @@ export const createStructureSetupObservers = (
|
||||
|
||||
const viewportIsTargetResizeObserver =
|
||||
_viewportIsTarget &&
|
||||
new ResizeObserverConstructor!(onSizeChanged.bind(0, { _sizeChanged: true }));
|
||||
ResizeObserverConstructor &&
|
||||
new ResizeObserverConstructor(onSizeChanged.bind(0, { _sizeChanged: true }));
|
||||
|
||||
viewportIsTargetResizeObserver && viewportIsTargetResizeObserver.observe(_host);
|
||||
updateViewportAttrsFromHost();
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { each, scrollLeft, scrollTop, assignDeep, keys } from 'support';
|
||||
import { getEnvironment } from 'environment';
|
||||
import { dataValueHostUpdating } from 'classnames';
|
||||
import {
|
||||
createTrinsicUpdateSegment,
|
||||
createPaddingUpdateSegment,
|
||||
@@ -56,7 +57,7 @@ export const createStructureSetupUpdate = (
|
||||
structureSetupElements: StructureSetupElementsObj,
|
||||
state: SetupState<StructureSetupState>
|
||||
): StructureSetupUpdate => {
|
||||
const { _viewport } = structureSetupElements;
|
||||
const { _viewport, _viewportAddRemoveClass } = structureSetupElements;
|
||||
const { _nativeScrollbarsHiding, _nativeScrollbarsOverlaid, _flexboxGlue } = getEnvironment();
|
||||
const doViewportArrange =
|
||||
!_nativeScrollbarsHiding && (_nativeScrollbarsOverlaid.x || _nativeScrollbarsOverlaid.y);
|
||||
@@ -93,6 +94,7 @@ export const createStructureSetupUpdate = (
|
||||
const adjustScrollOffset = doViewportArrange || !_flexboxGlue;
|
||||
const scrollOffsetX = adjustScrollOffset && scrollLeft(_viewport);
|
||||
const scrollOffsetY = adjustScrollOffset && scrollTop(_viewport);
|
||||
_viewportAddRemoveClass('', dataValueHostUpdating, true);
|
||||
|
||||
let adaptivedUpdateHints: Required<StructureSetupUpdateHints> = initialUpdateHints;
|
||||
each(updateSegments, (updateSegment) => {
|
||||
@@ -105,6 +107,7 @@ export const createStructureSetupUpdate = (
|
||||
|
||||
scrollLeft(_viewport, scrollOffsetX);
|
||||
scrollTop(_viewport, scrollOffsetY);
|
||||
_viewportAddRemoveClass('', dataValueHostUpdating);
|
||||
|
||||
return adaptivedUpdateHints;
|
||||
};
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
[data-overlayscrollbars~='updating'] > .os-scrollbar {
|
||||
display: none !important;
|
||||
}
|
||||
.os-scrollbar {
|
||||
contain: strict;
|
||||
transition: opacity 0.3s, visibility 0.3s, top 0.3s, right 0.3s, bottom 0.3s, left 0.3s;
|
||||
|
||||
@@ -42,19 +42,13 @@ const getCSSVal = (elm: HTMLElement, computedStyle: CSSStyleDeclaration, prop: s
|
||||
? computedStyle[prop] || computedStyle.getPropertyValue(prop)
|
||||
: elm.style[prop];
|
||||
|
||||
const setCSSVal = (
|
||||
elm: HTMLElement | false | null | undefined,
|
||||
prop: string,
|
||||
val: string | number
|
||||
): void => {
|
||||
const setCSSVal = (elm: HTMLElement, prop: string, val: string | number): void => {
|
||||
try {
|
||||
if (elm) {
|
||||
const { style: elmStyle } = elm;
|
||||
if (!isUndefined(elmStyle[prop])) {
|
||||
elmStyle[prop] = adaptCSSVal(prop, val);
|
||||
} else {
|
||||
elmStyle.setProperty(prop, val as string);
|
||||
}
|
||||
const { style: elmStyle } = elm;
|
||||
if (!isUndefined(elmStyle[prop])) {
|
||||
elmStyle[prop] = adaptCSSVal(prop, val);
|
||||
} else {
|
||||
elmStyle.setProperty(prop, val as string);
|
||||
}
|
||||
} catch (e) {}
|
||||
};
|
||||
@@ -96,7 +90,7 @@ export function style<CustomCssProps>(
|
||||
}
|
||||
return getStylesResult;
|
||||
}
|
||||
each(keys(styles), (key) => setCSSVal(elm, key, styles[key]));
|
||||
elm && each(keys(styles), (key) => setCSSVal(elm, key, styles[key]));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+19
-23
@@ -5,7 +5,8 @@ import {
|
||||
createStructureSetupElements,
|
||||
StructureSetupElementsObj,
|
||||
} from 'setups/structureSetup/structureSetup.elements';
|
||||
import type { InitializationTarget, DefaultInitializtationElement } from 'initialization';
|
||||
import { addPlugin, scrollbarsHidingPlugin } from 'plugins';
|
||||
import type { InitializationTarget } from 'initialization';
|
||||
import type {
|
||||
StructureInitialization,
|
||||
StructureStaticInitializationElement,
|
||||
@@ -25,6 +26,8 @@ jest.mock('support/compatibility/apis', () => {
|
||||
};
|
||||
});
|
||||
|
||||
addPlugin(scrollbarsHidingPlugin);
|
||||
|
||||
interface StructureSetupElementsProxy {
|
||||
input: InitializationTarget;
|
||||
elements: StructureSetupElementsObj;
|
||||
@@ -178,38 +181,33 @@ const assertCorrectSetupElements = (
|
||||
expect(_content).toBeFalsy();
|
||||
}
|
||||
|
||||
const { _isTextarea, _isBody, _bodyElm, _htmlElm, _documentElm, _windowElm } = elements;
|
||||
const { _isTextarea, _isBody, _documentElm, _windowElm } = elements;
|
||||
|
||||
expect(_isTextarea).toBe(isTextarea);
|
||||
expect(_isBody).toBe(isBody);
|
||||
expect(_windowElm).toBe(document.defaultView);
|
||||
expect(_documentElm).toBe(document);
|
||||
expect(_htmlElm).toBe(document.body.parentElement);
|
||||
expect(_bodyElm).toBe(document.body);
|
||||
|
||||
expect(typeof destroy).toBe('function');
|
||||
|
||||
const { _nativeScrollbarsHiding, _cssCustomProperties, _getDefaultInitialization } = environment;
|
||||
const {
|
||||
_nativeScrollbarsHiding: _nativeScrollbarStyling,
|
||||
_cssCustomProperties,
|
||||
_getInitializationStrategy,
|
||||
} = environment;
|
||||
const {
|
||||
_host: hostInitStrategy,
|
||||
_viewport: viewportInitStrategy,
|
||||
_padding: paddingInitStrategy,
|
||||
_content: contentInitStrategy,
|
||||
} = _getInitializationStrategy();
|
||||
host: hostInitStrategy,
|
||||
viewport: viewportInitStrategy,
|
||||
padding: paddingInitStrategy,
|
||||
content: contentInitStrategy,
|
||||
} = _getDefaultInitialization();
|
||||
const inputIsElement = isHTMLElement(input);
|
||||
const inputAsObj = input as StructureInitialization;
|
||||
const styleElm = document.querySelector('style');
|
||||
const checkStrategyDependendElements = (
|
||||
elm: Element | null,
|
||||
inputStrategy: StructureStaticInitializationElement | StructureDynamicInitializationElement,
|
||||
inputStrategy:
|
||||
| StructureStaticInitializationElement
|
||||
| StructureDynamicInitializationElement
|
||||
| undefined,
|
||||
isStaticStrategy: boolean,
|
||||
strategy:
|
||||
| DefaultInitializtationElement<StructureStaticInitializationElement>
|
||||
| DefaultInitializtationElement<StructureDynamicInitializationElement>,
|
||||
strategy: StructureStaticInitializationElement | StructureDynamicInitializationElement,
|
||||
kind: 'padding' | 'viewport' | 'content' | 'host'
|
||||
) => {
|
||||
const input = isFunction(inputStrategy) ? inputStrategy(target) : inputStrategy;
|
||||
@@ -223,8 +221,7 @@ const assertCorrectSetupElements = (
|
||||
}
|
||||
if (input === undefined) {
|
||||
if (isStaticStrategy) {
|
||||
strategy =
|
||||
strategy as DefaultInitializtationElement<StructureStaticInitializationElement>;
|
||||
strategy = strategy as StructureStaticInitializationElement;
|
||||
if (typeof strategy === 'function') {
|
||||
const result = strategy(target);
|
||||
if (_viewportIsTarget) {
|
||||
@@ -242,8 +239,7 @@ const assertCorrectSetupElements = (
|
||||
expect(elm).toBeTruthy();
|
||||
}
|
||||
} else {
|
||||
strategy =
|
||||
strategy as DefaultInitializtationElement<StructureDynamicInitializationElement>;
|
||||
strategy = strategy as StructureDynamicInitializationElement;
|
||||
|
||||
if (typeof strategy === 'function') {
|
||||
const result = strategy(target);
|
||||
@@ -278,7 +274,7 @@ const assertCorrectSetupElements = (
|
||||
}
|
||||
};
|
||||
|
||||
if (_nativeScrollbarStyling || _cssCustomProperties) {
|
||||
if (_nativeScrollbarsHiding || _cssCustomProperties) {
|
||||
expect(styleElm).toBeFalsy();
|
||||
} else {
|
||||
expect(styleElm).toBeTruthy();
|
||||
|
||||
+1699
File diff suppressed because it is too large
Load Diff
@@ -298,11 +298,11 @@ body {
|
||||
|
||||
// disable native scrollbar styling detection
|
||||
.nss {
|
||||
.os-viewport-scrollbar-styled.os-environment {
|
||||
.os-viewport-scrollbar-hidden.os-environment {
|
||||
scrollbar-width: auto !important;
|
||||
}
|
||||
.os-viewport-scrollbar-styled.os-environment::-webkit-scrollbar,
|
||||
.os-viewport-scrollbar-styled.os-environment::-webkit-scrollbar-corner {
|
||||
.os-viewport-scrollbar-hidden.os-environment::-webkit-scrollbar,
|
||||
.os-viewport-scrollbar-hidden.os-environment::-webkit-scrollbar-corner {
|
||||
display: block !important;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user