mirror of
https://github.com/tenrok/OverlayScrollbars.git
synced 2026-06-13 17:32:26 +03:00
improve options, environment and structure setup
This commit is contained in:
@@ -14,7 +14,10 @@ import {
|
||||
runEach,
|
||||
equalBCRWH,
|
||||
getBoundingClientRect,
|
||||
assignDeep,
|
||||
PartialOptions,
|
||||
} from 'support';
|
||||
import { OverlayScrollbarsOptions, defaultOptions } from 'options';
|
||||
import {
|
||||
classNameEnvironment,
|
||||
classNameEnvironmentFlexboxGlue,
|
||||
@@ -22,6 +25,11 @@ import {
|
||||
classNameViewportScrollbarStyling,
|
||||
} from 'classnames';
|
||||
|
||||
export interface InitializationStrategy {
|
||||
_padding: boolean;
|
||||
_content: boolean;
|
||||
}
|
||||
|
||||
export type OnEnvironmentChanged = (env: Environment) => void;
|
||||
export interface Environment {
|
||||
_autoUpdateLoop: boolean;
|
||||
@@ -33,11 +41,23 @@ export interface Environment {
|
||||
_cssCustomProperties: boolean;
|
||||
_addListener(listener: OnEnvironmentChanged): void;
|
||||
_removeListener(listener: OnEnvironmentChanged): void;
|
||||
_getInitializationStrategy(): InitializationStrategy;
|
||||
_setInitializationStrategy(newInitializationStrategy: Partial<InitializationStrategy>): void;
|
||||
_getDefaultOptions(): OverlayScrollbarsOptions;
|
||||
_setDefaultOptions(newDefaultOptions: PartialOptions<OverlayScrollbarsOptions>): void;
|
||||
_defaultInitializationStrategy: InitializationStrategy;
|
||||
_defaultDefaultOptions: OverlayScrollbarsOptions;
|
||||
}
|
||||
|
||||
let environmentInstance: Environment;
|
||||
const { abs, round } = Math;
|
||||
|
||||
const diffBiggerThanOne = (valOne: number, valTwo: number): boolean => {
|
||||
const absValOne = abs(valOne);
|
||||
const absValTwo = abs(valTwo);
|
||||
return !(absValOne === absValTwo || absValOne + 1 === absValTwo || absValOne - 1 === absValTwo);
|
||||
};
|
||||
|
||||
const getNativeScrollbarSize = (body: HTMLElement, measureElm: HTMLElement): XY => {
|
||||
appendChildren(body, measureElm);
|
||||
const cSize = clientSize(measureElm);
|
||||
@@ -111,18 +131,16 @@ const getWindowDPR = (): number => {
|
||||
return window.devicePixelRatio || dDPI / sDPI;
|
||||
};
|
||||
|
||||
const diffBiggerThanOne = (valOne: number, valTwo: number): boolean => {
|
||||
const absValOne = abs(valOne);
|
||||
const absValTwo = abs(valTwo);
|
||||
return !(absValOne === absValTwo || absValOne + 1 === absValTwo || absValOne - 1 === absValTwo);
|
||||
};
|
||||
const getDefaultInitializationStrategy = (nativeScrollbarStyling: boolean): InitializationStrategy => ({
|
||||
_padding: !nativeScrollbarStyling,
|
||||
_content: false,
|
||||
});
|
||||
|
||||
const createEnvironment = (): Environment => {
|
||||
const { body } = document;
|
||||
const envDOM = createDOM(`<div class="${classNameEnvironment}"><div></div></div>`);
|
||||
const envElm = envDOM[0] as HTMLElement;
|
||||
const envChildElm = envElm.firstChild as HTMLElement;
|
||||
|
||||
const onChangedListener: Set<OnEnvironmentChanged> = new Set();
|
||||
const nativeScrollbarSize = getNativeScrollbarSize(body, envElm);
|
||||
const nativeScrollbarStyling = false; //getNativeScrollbarStyling(envElm); //TODO: Re - enable;
|
||||
@@ -130,6 +148,9 @@ const createEnvironment = (): Environment => {
|
||||
x: nativeScrollbarSize.x === 0,
|
||||
y: nativeScrollbarSize.y === 0,
|
||||
};
|
||||
const defaultInitializationStrategy = getDefaultInitializationStrategy(nativeScrollbarStyling);
|
||||
let initializationStrategy = defaultInitializationStrategy;
|
||||
let defaultDefaultOptions = defaultOptions;
|
||||
|
||||
const env: Environment = {
|
||||
_autoUpdateLoop: false,
|
||||
@@ -145,6 +166,16 @@ const createEnvironment = (): Environment => {
|
||||
_removeListener(listener: OnEnvironmentChanged): void {
|
||||
onChangedListener.delete(listener);
|
||||
},
|
||||
_getInitializationStrategy: () => ({ ...initializationStrategy }),
|
||||
_setInitializationStrategy(newInitializationStrategy) {
|
||||
initializationStrategy = assignDeep({}, initializationStrategy, newInitializationStrategy);
|
||||
},
|
||||
_getDefaultOptions: () => ({ ...defaultDefaultOptions }),
|
||||
_setDefaultOptions(newDefaultOptions) {
|
||||
defaultDefaultOptions = assignDeep({}, defaultDefaultOptions, newDefaultOptions);
|
||||
},
|
||||
_defaultInitializationStrategy: defaultInitializationStrategy,
|
||||
_defaultDefaultOptions: defaultDefaultOptions,
|
||||
};
|
||||
|
||||
removeAttr(envElm, 'style');
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { XY, TRBL, CacheValues, each, push, keys, OptionsValidated, hasOwnProperty, isNumber, scrollLeft, scrollTop } from 'support';
|
||||
import { Options } from 'options';
|
||||
import { XY, TRBL, CacheValues, PartialOptions, each, push, keys, hasOwnProperty, isNumber, scrollLeft, scrollTop } from 'support';
|
||||
import { OverlayScrollbarsOptions } from 'options';
|
||||
import { getEnvironment } from 'environment';
|
||||
import { StructureSetup } from 'setups/structureSetup';
|
||||
import { createTrinsicLifecycle } from 'lifecycles/trinsicLifecycle';
|
||||
@@ -41,12 +41,12 @@ export type Lifecycle = (
|
||||
) => Partial<LifecycleAdaptiveUpdateHints> | void;
|
||||
|
||||
export interface LifecycleHubInstance {
|
||||
_update(changedOptions?: OptionsValidated<Options> | null, force?: boolean): void;
|
||||
_update(changedOptions?: PartialOptions<OverlayScrollbarsOptions> | null, force?: boolean): void;
|
||||
_destroy(): void;
|
||||
}
|
||||
|
||||
export interface LifecycleHub {
|
||||
_options: Options;
|
||||
_options: OverlayScrollbarsOptions;
|
||||
_structureSetup: StructureSetup;
|
||||
// whether the "viewport arrange" strategy must be used (true if no native scrollbar hiding and scrollbars are overlaid)
|
||||
_doViewportArrange: boolean;
|
||||
@@ -108,7 +108,7 @@ const heightIntrinsicCacheValuesFallback: CacheValues<boolean> = {
|
||||
_changed: false,
|
||||
};
|
||||
|
||||
export const createLifecycleHub = (options: Options, structureSetup: StructureSetup): LifecycleHubInstance => {
|
||||
export const createLifecycleHub = (options: OverlayScrollbarsOptions, structureSetup: StructureSetup): LifecycleHubInstance => {
|
||||
let paddingInfo = paddingInfoFallback;
|
||||
let viewportPaddingStyle = viewportPaddingStyleFallback;
|
||||
let viewportOverflowScroll = viewportOverflowScrollFallback;
|
||||
@@ -146,7 +146,7 @@ export const createLifecycleHub = (options: Options, structureSetup: StructureSe
|
||||
|
||||
const updateLifecycles = (
|
||||
updateHints?: Partial<LifecycleUpdateHints> | null,
|
||||
changedOptions?: OptionsValidated<Options> | null,
|
||||
changedOptions?: Partial<OverlayScrollbarsOptions> | null,
|
||||
force?: boolean
|
||||
) => {
|
||||
let {
|
||||
@@ -260,7 +260,7 @@ export const createLifecycleHub = (options: Options, structureSetup: StructureSe
|
||||
*/
|
||||
});
|
||||
|
||||
const update = (changedOptions?: OptionsValidated<Options> | null, force?: boolean) => {
|
||||
const update = (changedOptions?: Partial<OverlayScrollbarsOptions> | null, force?: boolean) => {
|
||||
updateLifecycles(null, changedOptions, force);
|
||||
};
|
||||
const envUpdateListener = update.bind(null, null, true);
|
||||
|
||||
@@ -24,35 +24,35 @@ export type SizeChangedCallback = (this: any, args?: SizeChangedArgs) => void;
|
||||
|
||||
export type UpdatedCallback = (this: any, args?: UpdatedArgs) => void;
|
||||
|
||||
export interface Options {
|
||||
resize?: ResizeBehavior;
|
||||
paddingAbsolute?: boolean;
|
||||
updating?: {
|
||||
elementEvents?: ReadonlyArray<[string, string]> | null;
|
||||
contentMutationDebounce?: number;
|
||||
hostMutationDebounce?: number;
|
||||
resizeDebounce?: number;
|
||||
export interface OverlayScrollbarsOptions {
|
||||
resize: ResizeBehavior;
|
||||
paddingAbsolute: boolean;
|
||||
updating: {
|
||||
elementEvents: ReadonlyArray<[string, string]> | null;
|
||||
contentMutationDebounce: number;
|
||||
hostMutationDebounce: number;
|
||||
resizeDebounce: number;
|
||||
};
|
||||
overflow?: {
|
||||
x?: OverflowBehavior;
|
||||
y?: OverflowBehavior;
|
||||
overflow: {
|
||||
x: OverflowBehavior;
|
||||
y: OverflowBehavior;
|
||||
};
|
||||
scrollbars?: {
|
||||
visibility?: VisibilityBehavior;
|
||||
autoHide?: AutoHideBehavior;
|
||||
autoHideDelay?: number;
|
||||
dragScroll?: boolean;
|
||||
clickScroll?: boolean;
|
||||
touch?: boolean;
|
||||
scrollbars: {
|
||||
visibility: VisibilityBehavior;
|
||||
autoHide: AutoHideBehavior;
|
||||
autoHideDelay: number;
|
||||
dragScroll: boolean;
|
||||
clickScroll: boolean;
|
||||
touch: boolean;
|
||||
};
|
||||
textarea?: {
|
||||
dynWidth?: boolean;
|
||||
dynHeight?: boolean;
|
||||
inheritedAttrs?: string | ReadonlyArray<string> | null;
|
||||
textarea: {
|
||||
dynWidth: boolean;
|
||||
dynHeight: boolean;
|
||||
inheritedAttrs: string | ReadonlyArray<string> | null;
|
||||
};
|
||||
nativeScrollbarsOverlaid?: {
|
||||
show?: boolean;
|
||||
initialize?: boolean;
|
||||
nativeScrollbarsOverlaid: {
|
||||
show: boolean;
|
||||
initialize: boolean;
|
||||
};
|
||||
/*
|
||||
callbacks?: {
|
||||
|
||||
@@ -6,7 +6,7 @@ import {
|
||||
OptionsWithOptionsTemplate,
|
||||
Func,
|
||||
} from 'support/options';
|
||||
import { ResizeBehavior, OverflowBehavior, VisibilityBehavior, AutoHideBehavior, Options } from 'options';
|
||||
import { ResizeBehavior, OverflowBehavior, VisibilityBehavior, AutoHideBehavior, OverlayScrollbarsOptions } from 'options';
|
||||
|
||||
const numberAllowedValues: OptionsTemplateValue<number> = oTypes.number;
|
||||
const stringArrayNullAllowedValues: OptionsTemplateValue<string | ReadonlyArray<string> | null> = [oTypes.string, oTypes.array, oTypes.null];
|
||||
@@ -33,7 +33,8 @@ const scrollbarsAutoHideAllowedValues: OptionsTemplateValue<AutoHideBehavior> =
|
||||
* Property "a" has a default value of 'default' and it can be a string or null
|
||||
* Property "b" has a default value of 250 and it can be number
|
||||
*/
|
||||
const defaultOptionsWithTemplate: OptionsWithOptionsTemplate<Required<Options>> = {
|
||||
|
||||
const defaultOptionsWithTemplate: OptionsWithOptionsTemplate<OverlayScrollbarsOptions> = {
|
||||
resize: ['none', resizeAllowedValues], // none || both || horizontal || vertical || n || b || h || v
|
||||
paddingAbsolute: booleanFalseTemplate, // true || false
|
||||
updating: {
|
||||
|
||||
@@ -1,20 +1,22 @@
|
||||
import { OSTarget, OSTargetObject } from 'typings';
|
||||
|
||||
import { validateOptions, assignDeep, isEmptyObject } from 'support';
|
||||
import { PartialOptions, validateOptions, assignDeep, isEmptyObject } from 'support';
|
||||
import { createStructureSetup, StructureSetup } from 'setups/structureSetup';
|
||||
import { createLifecycleHub } from 'lifecycles/lifecycleHub';
|
||||
import { Options, defaultOptions, optionsTemplate } from 'options';
|
||||
import { OverlayScrollbarsOptions, optionsTemplate } from 'options';
|
||||
import { getEnvironment } from 'environment';
|
||||
|
||||
const OverlayScrollbars = (target: OSTarget | OSTargetObject, options?: Options, extensions?: any): any => {
|
||||
const currentOptions: Required<Options> = assignDeep(
|
||||
const OverlayScrollbars = (target: OSTarget | OSTargetObject, options?: PartialOptions<OverlayScrollbarsOptions>, extensions?: any): any => {
|
||||
const { _getDefaultOptions } = getEnvironment();
|
||||
const currentOptions: OverlayScrollbarsOptions = assignDeep(
|
||||
{},
|
||||
defaultOptions,
|
||||
validateOptions<Options>(options || ({} as Options), optionsTemplate, null, true)._validated
|
||||
_getDefaultOptions(),
|
||||
validateOptions(options || ({} as PartialOptions<OverlayScrollbarsOptions>), optionsTemplate, null, true)._validated
|
||||
);
|
||||
const structureSetup: StructureSetup = createStructureSetup(target);
|
||||
const lifecycleHub = createLifecycleHub(currentOptions, structureSetup);
|
||||
const instance = {
|
||||
options(newOptions?: Options) {
|
||||
options(newOptions?: PartialOptions<OverlayScrollbarsOptions>) {
|
||||
if (newOptions) {
|
||||
const { _validated: _changedOptions } = validateOptions(newOptions, optionsTemplate, currentOptions, true);
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@ import {
|
||||
runEach,
|
||||
insertBefore,
|
||||
attr,
|
||||
isBoolean,
|
||||
} from 'support';
|
||||
import {
|
||||
classNameHost,
|
||||
@@ -24,7 +25,7 @@ import {
|
||||
classNameViewportScrollbarStyling,
|
||||
} from 'classnames';
|
||||
import { getEnvironment } from 'environment';
|
||||
import { OSTarget, OSTargetObject, InternalVersionOf, OSTargetElement } from 'typings';
|
||||
import { OSTarget, OSTargetObject, OSTargetElement } from 'typings';
|
||||
|
||||
export interface OSTargetContext {
|
||||
_isTextarea: boolean;
|
||||
@@ -35,9 +36,13 @@ export interface OSTargetContext {
|
||||
_documentElm: HTMLDocument;
|
||||
}
|
||||
|
||||
export interface PreparedOSTargetObject extends Required<InternalVersionOf<OSTargetObject>> {
|
||||
export interface PreparedOSTargetObject {
|
||||
_target: OSTargetElement;
|
||||
_host: HTMLElement;
|
||||
_viewportArrange: HTMLStyleElement | null;
|
||||
_viewport: HTMLElement;
|
||||
_padding: HTMLElement | false | null;
|
||||
_content: HTMLElement | false | null;
|
||||
_viewportArrange: HTMLStyleElement | false | null;
|
||||
}
|
||||
|
||||
export interface StructureSetup {
|
||||
@@ -46,13 +51,13 @@ export interface StructureSetup {
|
||||
_destroy: () => void;
|
||||
}
|
||||
|
||||
const unwrap = (elm: HTMLElement | null | undefined) => {
|
||||
const unwrap = (elm: HTMLElement | false | null | undefined) => {
|
||||
appendChildren(parent(elm), contents(elm));
|
||||
removeElements(elm);
|
||||
};
|
||||
|
||||
let contentArrangeCounter = 0;
|
||||
const createUniqueViewportArrangeElement = () => {
|
||||
const createUniqueViewportArrangeElement = (): HTMLStyleElement => {
|
||||
const elm = document.createElement('style');
|
||||
|
||||
attr(elm, 'id', `${classNameViewportArrange}-${contentArrangeCounter}`);
|
||||
@@ -60,26 +65,32 @@ const createUniqueViewportArrangeElement = () => {
|
||||
|
||||
return elm;
|
||||
};
|
||||
const evaluateCreationFromStrategy = (initializationValue: HTMLElement | boolean | undefined, strategy: boolean): HTMLElement | false | undefined => {
|
||||
const isBooleanValue = isBoolean(initializationValue);
|
||||
if (isBooleanValue || isUndefined(initializationValue)) {
|
||||
return (isBooleanValue ? initializationValue : strategy) && undefined;
|
||||
}
|
||||
return initializationValue as HTMLElement;
|
||||
};
|
||||
|
||||
export const createStructureSetup = (target: OSTarget | OSTargetObject): StructureSetup => {
|
||||
const { _getInitializationStrategy, _nativeScrollbarStyling, _nativeScrollbarIsOverlaid, _cssCustomProperties } = getEnvironment();
|
||||
const { _padding: paddingNeeded, _content: contentNeeded } = _getInitializationStrategy();
|
||||
const targetIsElm = isHTMLElement(target);
|
||||
const osTargetObj: InternalVersionOf<OSTargetObject> = targetIsElm
|
||||
? ({} as InternalVersionOf<OSTargetObject>)
|
||||
const osTargetObj: Partial<PreparedOSTargetObject> = targetIsElm
|
||||
? ({} as Partial<PreparedOSTargetObject>)
|
||||
: {
|
||||
_host: (target as OSTargetObject).host,
|
||||
_target: (target as OSTargetObject).target,
|
||||
_padding: (target as OSTargetObject).padding,
|
||||
_viewport: (target as OSTargetObject).viewport,
|
||||
_content: (target as OSTargetObject).content,
|
||||
_padding: evaluateCreationFromStrategy((target as OSTargetObject).padding, paddingNeeded),
|
||||
_content: evaluateCreationFromStrategy((target as OSTargetObject).content, contentNeeded),
|
||||
};
|
||||
|
||||
if (targetIsElm) {
|
||||
const padding = createDiv(classNamePadding);
|
||||
const viewport = createDiv(classNameViewport);
|
||||
const content = createDiv(classNameContent);
|
||||
|
||||
appendChildren(padding, viewport);
|
||||
appendChildren(viewport, content);
|
||||
const padding = paddingNeeded && createDiv(classNamePadding);
|
||||
const content = contentNeeded && createDiv(classNameContent);
|
||||
|
||||
osTargetObj._target = target as OSTargetElement;
|
||||
osTargetObj._padding = padding;
|
||||
@@ -106,12 +117,15 @@ export const createStructureSetup = (target: OSTarget | OSTargetObject): Structu
|
||||
}
|
||||
|
||||
if (targetIsElm) {
|
||||
appendChildren(_content!, getTargetContents(_target));
|
||||
const contentSlot = _content || _viewport;
|
||||
appendChildren(contentSlot, getTargetContents(_target!));
|
||||
appendChildren(_host, _padding);
|
||||
appendChildren(_padding || _host, _viewport);
|
||||
appendChildren(_viewport, _content);
|
||||
|
||||
push(destroyFns, () => {
|
||||
appendChildren(_host, contents(_content));
|
||||
removeElements(_padding);
|
||||
appendChildren(_host, contents(contentSlot));
|
||||
removeElements(_padding || _viewport);
|
||||
removeClass(_host, classNameHost);
|
||||
});
|
||||
} else {
|
||||
@@ -154,7 +168,7 @@ export const createStructureSetup = (target: OSTarget | OSTargetObject): Structu
|
||||
addClass(_viewport, classNameViewport);
|
||||
addClass(_content, classNameContent);
|
||||
|
||||
const ownerDocument: HTMLDocument = _target.ownerDocument;
|
||||
const ownerDocument: HTMLDocument = _target!.ownerDocument;
|
||||
const bodyElm = ownerDocument.body as HTMLBodyElement;
|
||||
const wnd = ownerDocument.defaultView as Window;
|
||||
const ctx: OSTargetContext = {
|
||||
@@ -171,7 +185,6 @@ export const createStructureSetup = (target: OSTarget | OSTargetObject): Structu
|
||||
_host,
|
||||
};
|
||||
|
||||
const { _nativeScrollbarStyling, _nativeScrollbarIsOverlaid, _cssCustomProperties } = getEnvironment();
|
||||
if (_nativeScrollbarStyling) {
|
||||
push(destroyFns, removeClass.bind(0, _viewport, classNameViewportScrollbarStyling));
|
||||
} else if (!_cssCustomProperties && (_nativeScrollbarIsOverlaid.x || _nativeScrollbarIsOverlaid.y)) {
|
||||
|
||||
@@ -4,7 +4,7 @@ import { keys } from 'support/utils/object';
|
||||
|
||||
const rnothtmlwhite = /[^\x20\t\r\n\f]+/g;
|
||||
const classListAction = (
|
||||
elm: Element | null | undefined,
|
||||
elm: Element | false | null | undefined,
|
||||
className: string,
|
||||
action: (elmClassList: DOMTokenList, clazz: string) => boolean | void
|
||||
): boolean => {
|
||||
@@ -27,7 +27,7 @@ const classListAction = (
|
||||
* @param elm The element.
|
||||
* @param className The class name(s).
|
||||
*/
|
||||
export const hasClass = (elm: Element | null | undefined, className: string): boolean =>
|
||||
export const hasClass = (elm: Element | false | null | undefined, className: string): boolean =>
|
||||
classListAction(elm, className, (classList, clazz) => classList.contains(clazz));
|
||||
|
||||
/**
|
||||
@@ -35,7 +35,7 @@ export const hasClass = (elm: Element | null | undefined, className: string): bo
|
||||
* @param elm The element.
|
||||
* @param className The class name(s) which shall be added. (separated by spaces)
|
||||
*/
|
||||
export const addClass = (elm: Element | null | undefined, className: string): void => {
|
||||
export const addClass = (elm: Element | false | null | undefined, className: string): void => {
|
||||
classListAction(elm, className, (classList, clazz) => classList.add(clazz));
|
||||
};
|
||||
|
||||
@@ -44,7 +44,7 @@ export const addClass = (elm: Element | null | undefined, className: string): vo
|
||||
* @param elm The element.
|
||||
* @param className The class name(s) which shall be removed. (separated by spaces)
|
||||
*/
|
||||
export const removeClass = (elm: Element | null | undefined, className: string): void => {
|
||||
export const removeClass = (elm: Element | false | null | undefined, className: string): void => {
|
||||
classListAction(elm, className, (classList, clazz) => classList.remove(clazz));
|
||||
};
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ import { isArrayLike } from 'support/utils/types';
|
||||
import { each, from } from 'support/utils/array';
|
||||
import { parent } from 'support/dom/traversal';
|
||||
|
||||
type NodeCollection = ArrayLike<Node> | Node | null | undefined;
|
||||
type NodeCollection = ArrayLike<Node> | Node | false | null | undefined;
|
||||
|
||||
/**
|
||||
* Inserts Nodes before the given preferredAnchor element.
|
||||
@@ -10,7 +10,7 @@ type NodeCollection = ArrayLike<Node> | Node | null | undefined;
|
||||
* @param preferredAnchor The element before which the Nodes shall be inserted or null if the elements shall be appended at the end.
|
||||
* @param insertedElms The Nodes which shall be inserted.
|
||||
*/
|
||||
const before = (parentElm: Node | null | undefined, preferredAnchor: Node | null | undefined, insertedElms: NodeCollection): void => {
|
||||
const before = (parentElm: Node | false | null | undefined, preferredAnchor: Node | null | undefined, insertedElms: NodeCollection): void => {
|
||||
if (insertedElms) {
|
||||
let anchor: Node | null | undefined = preferredAnchor;
|
||||
let fragment: DocumentFragment | Node | null | undefined;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { isElement } from 'support/utils/types';
|
||||
import { push, from } from 'support/utils/array';
|
||||
|
||||
type InputElementType = Element | Node | null | undefined;
|
||||
type InputElementType = Element | Node | false | null | undefined;
|
||||
type OutputElementType = Element | null;
|
||||
|
||||
const elmPrototype = Element.prototype;
|
||||
|
||||
@@ -3,6 +3,8 @@ import { PlainObject } from 'typings';
|
||||
export * from 'support/options/validation';
|
||||
export * from 'support/options/transformation';
|
||||
|
||||
type ObjectType = Record<string, unknown>;
|
||||
|
||||
export type Func = (this: any, ...args: any[]) => any;
|
||||
export type OptionsTemplateType<T extends OptionsTemplateNativeTypes> = ExtractPropsKey<OptionsTemplateTypeMap, T>;
|
||||
export type OptionsTemplateTypes = keyof OptionsTemplateTypeMap;
|
||||
@@ -12,29 +14,26 @@ export type OptionsTemplateValue<T extends OptionsTemplateNativeTypes = string>
|
||||
? OptionsTemplateValueNonEnum<T>
|
||||
: string
|
||||
: OptionsTemplateValueNonEnum<T>;
|
||||
export type OptionsTemplate<T extends Required<T>> = {
|
||||
[P in keyof T]: PlainObject extends T[P]
|
||||
? OptionsTemplate<Required<T[P]>>
|
||||
: T[P] extends OptionsTemplateNativeTypes
|
||||
? OptionsTemplateValue<T[P]>
|
||||
: never;
|
||||
};
|
||||
export type OptionsValidated<T> = {
|
||||
[P in keyof T]?: T[P];
|
||||
export type OptionsTemplate<T> = {
|
||||
[P in keyof T]: T[P] extends ObjectType ? OptionsTemplate<T[P]> : T[P] extends OptionsTemplateNativeTypes ? OptionsTemplateValue<T[P]> : never;
|
||||
};
|
||||
export type OptionsValidationResult<T> = {
|
||||
readonly _foreign: PlainObject;
|
||||
readonly _validated: OptionsValidated<T>;
|
||||
readonly _validated: PartialOptions<T>;
|
||||
};
|
||||
// Options With Options Template Typings:
|
||||
export type OptionsWithOptionsTemplateValue<T extends OptionsTemplateNativeTypes> = [T, OptionsTemplateValue<T>];
|
||||
export type OptionsWithOptionsTemplate<T extends Required<T>> = {
|
||||
[P in keyof T]: PlainObject extends T[P]
|
||||
[P in keyof T]: T[P] extends ObjectType
|
||||
? OptionsWithOptionsTemplate<Required<T[P]>>
|
||||
: T[P] extends OptionsTemplateNativeTypes
|
||||
? OptionsWithOptionsTemplateValue<T[P]>
|
||||
: never;
|
||||
};
|
||||
export type PartialOptions<T> = {
|
||||
[P in keyof T]?: T[P] extends ObjectType ? PartialOptions<T[P]> : T[P];
|
||||
};
|
||||
|
||||
type OptionsTemplateTypeMap = {
|
||||
__TPL_boolean_TYPE__: boolean;
|
||||
__TPL_number_TYPE__: number;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { each, hasOwnProperty, keys, push, isEmptyObject } from 'support/utils';
|
||||
import { type, isArray, isUndefined, isPlainObject, isString } from 'support/utils/types';
|
||||
import { OptionsTemplate, OptionsTemplateTypes, OptionsTemplateType, Func, OptionsValidationResult, OptionsValidated } from 'support/options';
|
||||
import { OptionsTemplate, OptionsTemplateTypes, OptionsTemplateType, PartialOptions, Func, OptionsValidationResult } from 'support/options';
|
||||
import { PlainObject } from 'typings';
|
||||
|
||||
const { stringify } = JSON;
|
||||
@@ -41,14 +41,14 @@ const optionsTemplateTypes: OptionsTemplateTypesDictionary = ['boolean', 'number
|
||||
* @param propPath The propertyPath which lead to this object. (used for error logging)
|
||||
*/
|
||||
const validateRecursive = <T extends PlainObject>(
|
||||
options: T,
|
||||
template: OptionsTemplate<Required<T>>,
|
||||
options: PartialOptions<T>,
|
||||
template: OptionsTemplate<T>,
|
||||
optionsDiff: T,
|
||||
doWriteErrors?: boolean,
|
||||
propPath?: string
|
||||
): OptionsValidationResult<T> => {
|
||||
const validatedOptions: OptionsValidated<T> = {};
|
||||
const optionsCopy: T = { ...options };
|
||||
const validatedOptions: PartialOptions<T> = {};
|
||||
const optionsCopy: PartialOptions<T> = { ...options };
|
||||
const props = keys(template).filter((prop) => hasOwnProperty(options, prop));
|
||||
|
||||
each(props, (prop: Extract<keyof T, string>) => {
|
||||
@@ -60,7 +60,7 @@ const validateRecursive = <T extends PlainObject>(
|
||||
|
||||
// if the template has a object as value, it means that the options are complex (verschachtelt)
|
||||
if (templateIsComplex && isPlainObject(optionsValue)) {
|
||||
const validatedResult = validateRecursive(optionsValue, templateValue as PlainObject, optionsDiffValue, doWriteErrors, propPrefix + prop);
|
||||
const validatedResult = validateRecursive(optionsValue, templateValue as T, optionsDiffValue, doWriteErrors, propPrefix + prop);
|
||||
validatedOptions[prop] = validatedResult._validated as any;
|
||||
optionsCopy[prop] = validatedResult._foreign as any;
|
||||
|
||||
@@ -147,8 +147,8 @@ const validateRecursive = <T extends PlainObject>(
|
||||
* @param doWriteErrors True if errors shall be logged into the console, false otherwise.
|
||||
*/
|
||||
const validateOptions = <T extends PlainObject>(
|
||||
options: T,
|
||||
template: OptionsTemplate<Required<T>>,
|
||||
options: PartialOptions<T>,
|
||||
template: OptionsTemplate<T>,
|
||||
optionsDiff?: T | null,
|
||||
doWriteErrors?: boolean
|
||||
): OptionsValidationResult<T> => {
|
||||
|
||||
@@ -18,14 +18,16 @@ export type OSTargetElement = HTMLElement | HTMLTextAreaElement;
|
||||
* If element is provided, the provided element takes all its responsibilities.
|
||||
* DOM hierarchy isn't checked in this case, its assumed that hieararchy is correct in such a case.
|
||||
*
|
||||
* If element is null it won't be generated, and the responsibilities (feautes) of this element are lost.
|
||||
* Undefined means that the plugin decides whether the respective element needs to be added or can be savely omitted.
|
||||
* True means that even if the plugin would decide to not generate the element, the element is still generated.
|
||||
* False means that event if the plugin would decide to generate the element, the element won't be generated.
|
||||
*/
|
||||
export interface OSTargetObject {
|
||||
target: OSTargetElement;
|
||||
host?: HTMLElement;
|
||||
padding?: HTMLElement | null;
|
||||
padding?: HTMLElement | boolean;
|
||||
viewport?: HTMLElement;
|
||||
content?: HTMLElement | null;
|
||||
content?: HTMLElement | boolean;
|
||||
}
|
||||
|
||||
export type OSTarget = OSTargetElement | OSTargetObject;
|
||||
|
||||
+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({ target: targetElm });
|
||||
window.os = OverlayScrollbars({ target: targetElm, content: null });
|
||||
|
||||
export const resize = (element: HTMLElement) => {
|
||||
const strMouseTouchDownEvent = 'mousedown touchstart';
|
||||
|
||||
@@ -3,6 +3,23 @@ import 'expect-playwright';
|
||||
import { Environment } from 'environment';
|
||||
import url from './.build/build.html';
|
||||
|
||||
/**
|
||||
* env test cases:
|
||||
* 1. overlaid scrollbars
|
||||
* - with scrollbar styling
|
||||
* - without scrollbar styling
|
||||
* - with css custom properties
|
||||
* - without css custom properties
|
||||
* 2. partially overlaid, partially normal scrollbars
|
||||
* - with scrollbar styling
|
||||
* - without scrollbar styling
|
||||
* - with css custom properties
|
||||
* - without css custom properties
|
||||
* 3. normal scrollbars
|
||||
* - with scrollbar styling
|
||||
* - without scrollbar styling
|
||||
*/
|
||||
|
||||
describe('StructureLifecycle', () => {
|
||||
beforeAll(async () => {
|
||||
await page.goto(url);
|
||||
|
||||
@@ -1,4 +1,19 @@
|
||||
import { Environment } from 'environment';
|
||||
import { OSTarget, OSTargetObject } from 'typings';
|
||||
import { createStructureSetup, StructureSetup } from 'setups/structureSetup';
|
||||
import { isHTMLElement } from 'support';
|
||||
|
||||
const mockGetEnvironment = jest.fn();
|
||||
jest.mock('environment', () => {
|
||||
return {
|
||||
getEnvironment: jest.fn().mockImplementation(() => mockGetEnvironment()),
|
||||
};
|
||||
});
|
||||
|
||||
interface StructureSetupProxy {
|
||||
input: OSTarget | OSTargetObject;
|
||||
setup: StructureSetup;
|
||||
}
|
||||
|
||||
const textareaId = 'textarea';
|
||||
const textareaHostId = 'host';
|
||||
@@ -69,7 +84,13 @@ const assertCorrectDOMStructure = (textarea?: boolean) => {
|
||||
}
|
||||
};
|
||||
|
||||
const assertCorrectSetup = (textarea: boolean, setup: StructureSetup) => {
|
||||
const createStructureSetupProxy = (target: OSTarget | OSTargetObject): StructureSetupProxy => ({
|
||||
input: target,
|
||||
setup: createStructureSetup(target),
|
||||
});
|
||||
|
||||
const assertCorrectSetup = (textarea: boolean, setupProxy: StructureSetupProxy, environment: Environment): StructureSetup => {
|
||||
const { input, setup } = setupProxy;
|
||||
const { _targetObj, _targetCtx, _destroy } = setup;
|
||||
const { _target, _host, _padding, _viewport, _content } = _targetObj;
|
||||
const { target, host, padding, viewport, content } = getElements(textarea);
|
||||
@@ -113,6 +134,43 @@ const assertCorrectSetup = (textarea: boolean, setup: StructureSetup) => {
|
||||
|
||||
expect(typeof _destroy).toBe('function');
|
||||
|
||||
const { _nativeScrollbarStyling, _cssCustomProperties, _getInitializationStrategy } = environment;
|
||||
const { _padding: paddingNeeded, _content: contentNeeded } = _getInitializationStrategy();
|
||||
const inputIsElement = isHTMLElement(input);
|
||||
const inputAsObj = input as OSTargetObject;
|
||||
const styleElm = document.querySelector('style');
|
||||
const checkStrategyDependendElements = (elm: Element | null, input: HTMLElement | boolean | undefined, strategy: boolean) => {
|
||||
if (input) {
|
||||
expect(elm).toBeTruthy();
|
||||
} else {
|
||||
if (input === false) {
|
||||
expect(elm).toBeFalsy();
|
||||
}
|
||||
if (input === undefined) {
|
||||
if (strategy) {
|
||||
expect(elm).toBeTruthy();
|
||||
} else {
|
||||
expect(elm).toBeFalsy();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if (_nativeScrollbarStyling || _cssCustomProperties) {
|
||||
expect(styleElm).toBeFalsy();
|
||||
} else {
|
||||
expect(styleElm).toBeTruthy();
|
||||
}
|
||||
|
||||
if (inputIsElement) {
|
||||
checkStrategyDependendElements(padding, undefined, paddingNeeded);
|
||||
checkStrategyDependendElements(content, undefined, contentNeeded);
|
||||
} else {
|
||||
const { padding: inputPadding, content: inputContent } = inputAsObj;
|
||||
checkStrategyDependendElements(padding, inputPadding, paddingNeeded);
|
||||
checkStrategyDependendElements(content, inputContent, contentNeeded);
|
||||
}
|
||||
|
||||
return setup;
|
||||
};
|
||||
|
||||
@@ -133,314 +191,594 @@ const assertCorrectDestroy = (snapshot: string, setup: StructureSetup) => {
|
||||
expect(snapshot).toBe(getSnapshot());
|
||||
};
|
||||
|
||||
const env: Environment = jest.requireActual('environment').getEnvironment();
|
||||
const envDefault = {
|
||||
name: 'default',
|
||||
env: env,
|
||||
};
|
||||
const envNativeScrollbarStyling = {
|
||||
name: 'native scrollbar styling',
|
||||
env: {
|
||||
...env,
|
||||
_nativeScrollbarStyling: true,
|
||||
},
|
||||
};
|
||||
const envCssCustomProperties = {
|
||||
name: 'custom css properties',
|
||||
env: {
|
||||
...env,
|
||||
_cssCustomProperties: true,
|
||||
},
|
||||
};
|
||||
const envInitStrategyMin = {
|
||||
name: 'initialization strategy min',
|
||||
env: {
|
||||
...env,
|
||||
_getInitializationStrategy: () => ({
|
||||
_content: false,
|
||||
_padding: false,
|
||||
}),
|
||||
},
|
||||
};
|
||||
const envInitStrategyMax = {
|
||||
name: 'initialization strategy max',
|
||||
env: {
|
||||
...env,
|
||||
_getInitializationStrategy: () => ({
|
||||
_content: true,
|
||||
_padding: true,
|
||||
}),
|
||||
},
|
||||
};
|
||||
|
||||
describe('structureSetup', () => {
|
||||
afterEach(() => clearBody());
|
||||
|
||||
[false, true].forEach((isTextarea) => {
|
||||
describe(isTextarea ? 'textarea' : 'element', () => {
|
||||
describe('basic', () => {
|
||||
test('Element', () => {
|
||||
const snapshot = fillBody(isTextarea);
|
||||
const setup = assertCorrectSetup(isTextarea, createStructureSetup(getTarget(isTextarea)));
|
||||
assertCorrectDOMStructure(isTextarea);
|
||||
assertCorrectDestroy(snapshot, setup);
|
||||
});
|
||||
|
||||
test('Object', () => {
|
||||
const snapshot = fillBody(isTextarea);
|
||||
const setup = assertCorrectSetup(isTextarea, createStructureSetup({ target: getTarget(isTextarea) }));
|
||||
assertCorrectDOMStructure(isTextarea);
|
||||
assertCorrectDestroy(snapshot, setup);
|
||||
});
|
||||
[envDefault, envNativeScrollbarStyling, envCssCustomProperties, envInitStrategyMin, envInitStrategyMax].forEach((envWithName) => {
|
||||
const { env: currEnv, name } = envWithName;
|
||||
describe(`Environment: ${name}`, () => {
|
||||
beforeAll(() => {
|
||||
mockGetEnvironment.mockImplementation(() => currEnv);
|
||||
});
|
||||
|
||||
describe('complex', () => {
|
||||
describe('single assigned', () => {
|
||||
test('padding', () => {
|
||||
const snapshot = fillBody(isTextarea, (content, hostId) => {
|
||||
return `<div id="${hostId}"><div id="padding">${content}</div></div>`;
|
||||
[false, true].forEach((isTextarea) => {
|
||||
describe(isTextarea ? 'textarea' : 'element', () => {
|
||||
describe('basic', () => {
|
||||
test('Element', () => {
|
||||
const snapshot = fillBody(isTextarea);
|
||||
const setup = assertCorrectSetup(isTextarea, createStructureSetupProxy(getTarget(isTextarea)), currEnv);
|
||||
assertCorrectDOMStructure(isTextarea);
|
||||
assertCorrectDestroy(snapshot, setup);
|
||||
});
|
||||
const setup = assertCorrectSetup(
|
||||
isTextarea,
|
||||
createStructureSetup({
|
||||
host: document.querySelector<HTMLElement>('#host')!,
|
||||
target: getTarget(isTextarea),
|
||||
padding: document.querySelector<HTMLElement>('#padding')!,
|
||||
})
|
||||
);
|
||||
assertCorrectDOMStructure(isTextarea);
|
||||
assertCorrectDestroy(snapshot, setup);
|
||||
});
|
||||
|
||||
test('viewport', () => {
|
||||
const snapshot = fillBody(isTextarea, (content, hostId) => {
|
||||
return `<div id="${hostId}"><div id="viewport">${content}</div></div>`;
|
||||
test('Object', () => {
|
||||
const snapshot = fillBody(isTextarea);
|
||||
const setup = assertCorrectSetup(isTextarea, createStructureSetupProxy({ target: getTarget(isTextarea) }), currEnv);
|
||||
assertCorrectDOMStructure(isTextarea);
|
||||
assertCorrectDestroy(snapshot, setup);
|
||||
});
|
||||
const setup = assertCorrectSetup(
|
||||
isTextarea,
|
||||
createStructureSetup({
|
||||
host: document.querySelector<HTMLElement>('#host')!,
|
||||
target: getTarget(isTextarea),
|
||||
viewport: document.querySelector<HTMLElement>('#viewport')!,
|
||||
})
|
||||
);
|
||||
assertCorrectDOMStructure(isTextarea);
|
||||
assertCorrectDestroy(snapshot, setup);
|
||||
});
|
||||
|
||||
test('content', () => {
|
||||
const snapshot = fillBody(isTextarea, (content, hostId) => {
|
||||
return `<div id="${hostId}"><div id="content">${content}</div></div>`;
|
||||
describe('complex', () => {
|
||||
describe('single assigned', () => {
|
||||
test('padding', () => {
|
||||
const snapshot = fillBody(isTextarea, (content, hostId) => {
|
||||
return `<div id="${hostId}"><div id="padding">${content}</div></div>`;
|
||||
});
|
||||
const setup = assertCorrectSetup(
|
||||
isTextarea,
|
||||
createStructureSetupProxy({
|
||||
host: document.querySelector<HTMLElement>('#host')!,
|
||||
target: getTarget(isTextarea),
|
||||
padding: document.querySelector<HTMLElement>('#padding')!,
|
||||
}),
|
||||
currEnv
|
||||
);
|
||||
assertCorrectDOMStructure(isTextarea);
|
||||
assertCorrectDestroy(snapshot, setup);
|
||||
});
|
||||
|
||||
test('viewport', () => {
|
||||
const snapshot = fillBody(isTextarea, (content, hostId) => {
|
||||
return `<div id="${hostId}"><div id="viewport">${content}</div></div>`;
|
||||
});
|
||||
const setup = assertCorrectSetup(
|
||||
isTextarea,
|
||||
createStructureSetupProxy({
|
||||
host: document.querySelector<HTMLElement>('#host')!,
|
||||
target: getTarget(isTextarea),
|
||||
viewport: document.querySelector<HTMLElement>('#viewport')!,
|
||||
}),
|
||||
currEnv
|
||||
);
|
||||
assertCorrectDOMStructure(isTextarea);
|
||||
assertCorrectDestroy(snapshot, setup);
|
||||
});
|
||||
|
||||
test('content', () => {
|
||||
const snapshot = fillBody(isTextarea, (content, hostId) => {
|
||||
return `<div id="${hostId}"><div id="content">${content}</div></div>`;
|
||||
});
|
||||
const setup = assertCorrectSetup(
|
||||
isTextarea,
|
||||
createStructureSetupProxy({
|
||||
host: document.querySelector<HTMLElement>('#host')!,
|
||||
target: getTarget(isTextarea),
|
||||
content: document.querySelector<HTMLElement>('#content')!,
|
||||
}),
|
||||
currEnv
|
||||
);
|
||||
assertCorrectDOMStructure(isTextarea);
|
||||
assertCorrectDestroy(snapshot, setup);
|
||||
});
|
||||
});
|
||||
const setup = assertCorrectSetup(
|
||||
isTextarea,
|
||||
createStructureSetup({
|
||||
host: document.querySelector<HTMLElement>('#host')!,
|
||||
target: getTarget(isTextarea),
|
||||
content: document.querySelector<HTMLElement>('#content')!,
|
||||
})
|
||||
);
|
||||
assertCorrectDOMStructure(isTextarea);
|
||||
assertCorrectDestroy(snapshot, setup);
|
||||
});
|
||||
});
|
||||
|
||||
describe('multiple assigned', () => {
|
||||
test('padding viewport content', () => {
|
||||
const snapshot = fillBody(isTextarea, (content, hostId) => {
|
||||
return `<div id="${hostId}"><div id="padding"><div id="viewport"><div id="content">${content}</div></div></div></div>`;
|
||||
describe('multiple assigned', () => {
|
||||
test('padding viewport content', () => {
|
||||
const snapshot = fillBody(isTextarea, (content, hostId) => {
|
||||
return `<div id="${hostId}"><div id="padding"><div id="viewport"><div id="content">${content}</div></div></div></div>`;
|
||||
});
|
||||
const setup = assertCorrectSetup(
|
||||
isTextarea,
|
||||
createStructureSetupProxy({
|
||||
host: document.querySelector<HTMLElement>('#host')!,
|
||||
target: getTarget(isTextarea),
|
||||
padding: document.querySelector<HTMLElement>('#padding')!,
|
||||
viewport: document.querySelector<HTMLElement>('#viewport')!,
|
||||
content: document.querySelector<HTMLElement>('#content')!,
|
||||
}),
|
||||
currEnv
|
||||
);
|
||||
assertCorrectDOMStructure(isTextarea);
|
||||
assertCorrectDestroy(snapshot, setup);
|
||||
});
|
||||
|
||||
test('padding viewport', () => {
|
||||
const snapshot = fillBody(isTextarea, (content, hostId) => {
|
||||
return `<div id="${hostId}"><div id="padding"><div id="viewport">${content}</div></div></div>`;
|
||||
});
|
||||
const setup = assertCorrectSetup(
|
||||
isTextarea,
|
||||
createStructureSetupProxy({
|
||||
host: document.querySelector<HTMLElement>('#host')!,
|
||||
target: getTarget(isTextarea),
|
||||
padding: document.querySelector<HTMLElement>('#padding')!,
|
||||
viewport: document.querySelector<HTMLElement>('#viewport')!,
|
||||
}),
|
||||
currEnv
|
||||
);
|
||||
assertCorrectDOMStructure(isTextarea);
|
||||
assertCorrectDestroy(snapshot, setup);
|
||||
});
|
||||
|
||||
test('padding content', () => {
|
||||
const snapshot = fillBody(isTextarea, (content, hostId) => {
|
||||
return `<div id="${hostId}"><div id="padding"><div id="content">${content}</div></div></div>`;
|
||||
});
|
||||
const setup = assertCorrectSetup(
|
||||
isTextarea,
|
||||
createStructureSetupProxy({
|
||||
host: document.querySelector<HTMLElement>('#host')!,
|
||||
target: getTarget(isTextarea),
|
||||
padding: document.querySelector<HTMLElement>('#padding')!,
|
||||
content: document.querySelector<HTMLElement>('#content')!,
|
||||
}),
|
||||
currEnv
|
||||
);
|
||||
assertCorrectDOMStructure(isTextarea);
|
||||
assertCorrectDestroy(snapshot, setup);
|
||||
});
|
||||
|
||||
test('viewport content', () => {
|
||||
const snapshot = fillBody(isTextarea, (content, hostId) => {
|
||||
return `<div id="${hostId}"><div id="viewport"><div id="content">${content}</div></div></div>`;
|
||||
});
|
||||
const setup = assertCorrectSetup(
|
||||
isTextarea,
|
||||
createStructureSetupProxy({
|
||||
host: document.querySelector<HTMLElement>('#host')!,
|
||||
target: getTarget(isTextarea),
|
||||
viewport: document.querySelector<HTMLElement>('#viewport')!,
|
||||
content: document.querySelector<HTMLElement>('#content')!,
|
||||
}),
|
||||
currEnv
|
||||
);
|
||||
assertCorrectDOMStructure(isTextarea);
|
||||
assertCorrectDestroy(snapshot, setup);
|
||||
});
|
||||
});
|
||||
const setup = assertCorrectSetup(
|
||||
isTextarea,
|
||||
createStructureSetup({
|
||||
host: document.querySelector<HTMLElement>('#host')!,
|
||||
target: getTarget(isTextarea),
|
||||
padding: document.querySelector<HTMLElement>('#padding')!,
|
||||
viewport: document.querySelector<HTMLElement>('#viewport')!,
|
||||
content: document.querySelector<HTMLElement>('#content')!,
|
||||
})
|
||||
);
|
||||
assertCorrectDOMStructure(isTextarea);
|
||||
assertCorrectDestroy(snapshot, setup);
|
||||
});
|
||||
|
||||
test('padding viewport', () => {
|
||||
const snapshot = fillBody(isTextarea, (content, hostId) => {
|
||||
return `<div id="${hostId}"><div id="padding"><div id="viewport">${content}</div></div></div>`;
|
||||
describe('single false', () => {
|
||||
test('padding', () => {
|
||||
const snapshot = fillBody(isTextarea);
|
||||
const setup = assertCorrectSetup(
|
||||
isTextarea,
|
||||
createStructureSetupProxy({
|
||||
target: getTarget(isTextarea),
|
||||
padding: false,
|
||||
}),
|
||||
currEnv
|
||||
);
|
||||
assertCorrectDOMStructure(isTextarea);
|
||||
assertCorrectDestroy(snapshot, setup);
|
||||
});
|
||||
|
||||
test('content', () => {
|
||||
const snapshot = fillBody(isTextarea);
|
||||
const setup = assertCorrectSetup(
|
||||
isTextarea,
|
||||
createStructureSetupProxy({
|
||||
target: getTarget(isTextarea),
|
||||
content: false,
|
||||
}),
|
||||
currEnv
|
||||
);
|
||||
assertCorrectDOMStructure(isTextarea);
|
||||
assertCorrectDestroy(snapshot, setup);
|
||||
});
|
||||
});
|
||||
const setup = assertCorrectSetup(
|
||||
isTextarea,
|
||||
createStructureSetup({
|
||||
host: document.querySelector<HTMLElement>('#host')!,
|
||||
target: getTarget(isTextarea),
|
||||
padding: document.querySelector<HTMLElement>('#padding')!,
|
||||
viewport: document.querySelector<HTMLElement>('#viewport')!,
|
||||
})
|
||||
);
|
||||
assertCorrectDOMStructure(isTextarea);
|
||||
assertCorrectDestroy(snapshot, setup);
|
||||
});
|
||||
|
||||
test('padding content', () => {
|
||||
const snapshot = fillBody(isTextarea, (content, hostId) => {
|
||||
return `<div id="${hostId}"><div id="padding"><div id="content">${content}</div></div></div>`;
|
||||
describe('single true', () => {
|
||||
test('padding', () => {
|
||||
const snapshot = fillBody(isTextarea);
|
||||
const setup = assertCorrectSetup(
|
||||
isTextarea,
|
||||
createStructureSetupProxy({
|
||||
target: getTarget(isTextarea),
|
||||
padding: true,
|
||||
}),
|
||||
currEnv
|
||||
);
|
||||
assertCorrectDOMStructure(isTextarea);
|
||||
assertCorrectDestroy(snapshot, setup);
|
||||
});
|
||||
|
||||
test('content', () => {
|
||||
const snapshot = fillBody(isTextarea);
|
||||
const setup = assertCorrectSetup(
|
||||
isTextarea,
|
||||
createStructureSetupProxy({
|
||||
target: getTarget(isTextarea),
|
||||
content: true,
|
||||
}),
|
||||
currEnv
|
||||
);
|
||||
assertCorrectDOMStructure(isTextarea);
|
||||
assertCorrectDestroy(snapshot, setup);
|
||||
});
|
||||
});
|
||||
const setup = assertCorrectSetup(
|
||||
isTextarea,
|
||||
createStructureSetup({
|
||||
host: document.querySelector<HTMLElement>('#host')!,
|
||||
target: getTarget(isTextarea),
|
||||
padding: document.querySelector<HTMLElement>('#padding')!,
|
||||
content: document.querySelector<HTMLElement>('#content')!,
|
||||
})
|
||||
);
|
||||
assertCorrectDOMStructure(isTextarea);
|
||||
assertCorrectDestroy(snapshot, setup);
|
||||
});
|
||||
|
||||
test('viewport content', () => {
|
||||
const snapshot = fillBody(isTextarea, (content, hostId) => {
|
||||
return `<div id="${hostId}"><div id="viewport"><div id="content">${content}</div></div></div>`;
|
||||
describe('multiple false', () => {
|
||||
test('padding & content', () => {
|
||||
const snapshot = fillBody(isTextarea);
|
||||
const setup = assertCorrectSetup(
|
||||
isTextarea,
|
||||
createStructureSetupProxy({
|
||||
target: getTarget(isTextarea),
|
||||
padding: false,
|
||||
content: false,
|
||||
}),
|
||||
currEnv
|
||||
);
|
||||
assertCorrectDOMStructure(isTextarea);
|
||||
assertCorrectDestroy(snapshot, setup);
|
||||
});
|
||||
});
|
||||
const setup = assertCorrectSetup(
|
||||
isTextarea,
|
||||
createStructureSetup({
|
||||
host: document.querySelector<HTMLElement>('#host')!,
|
||||
target: getTarget(isTextarea),
|
||||
viewport: document.querySelector<HTMLElement>('#viewport')!,
|
||||
content: document.querySelector<HTMLElement>('#content')!,
|
||||
})
|
||||
);
|
||||
assertCorrectDOMStructure(isTextarea);
|
||||
assertCorrectDestroy(snapshot, setup);
|
||||
});
|
||||
});
|
||||
|
||||
describe('single null', () => {
|
||||
test('padding', () => {
|
||||
const snapshot = fillBody(isTextarea);
|
||||
const setup = assertCorrectSetup(
|
||||
isTextarea,
|
||||
createStructureSetup({
|
||||
target: getTarget(isTextarea),
|
||||
padding: null,
|
||||
})
|
||||
);
|
||||
assertCorrectDOMStructure(isTextarea);
|
||||
assertCorrectDestroy(snapshot, setup);
|
||||
});
|
||||
|
||||
test('content', () => {
|
||||
const snapshot = fillBody(isTextarea);
|
||||
const setup = assertCorrectSetup(
|
||||
isTextarea,
|
||||
createStructureSetup({
|
||||
target: getTarget(isTextarea),
|
||||
content: null,
|
||||
})
|
||||
);
|
||||
assertCorrectDOMStructure(isTextarea);
|
||||
assertCorrectDestroy(snapshot, setup);
|
||||
});
|
||||
});
|
||||
|
||||
describe('multiple null', () => {
|
||||
test('padding & content', () => {
|
||||
const snapshot = fillBody(isTextarea);
|
||||
const setup = assertCorrectSetup(
|
||||
isTextarea,
|
||||
createStructureSetup({
|
||||
target: getTarget(isTextarea),
|
||||
padding: null,
|
||||
content: null,
|
||||
})
|
||||
);
|
||||
assertCorrectDOMStructure(isTextarea);
|
||||
assertCorrectDestroy(snapshot, setup);
|
||||
});
|
||||
});
|
||||
|
||||
describe('mixed', () => {
|
||||
test('null: padding & content | assigned: viewport', () => {
|
||||
const snapshot = fillBody(isTextarea, (content, hostId) => {
|
||||
return `<div id="${hostId}"><div id="viewport">${content}</div></div>`;
|
||||
describe('multiple true', () => {
|
||||
test('padding & content', () => {
|
||||
const snapshot = fillBody(isTextarea);
|
||||
const setup = assertCorrectSetup(
|
||||
isTextarea,
|
||||
createStructureSetupProxy({
|
||||
target: getTarget(isTextarea),
|
||||
padding: true,
|
||||
content: true,
|
||||
}),
|
||||
currEnv
|
||||
);
|
||||
assertCorrectDOMStructure(isTextarea);
|
||||
assertCorrectDestroy(snapshot, setup);
|
||||
});
|
||||
});
|
||||
const setup = assertCorrectSetup(
|
||||
isTextarea,
|
||||
createStructureSetup({
|
||||
host: document.querySelector<HTMLElement>('#host')!,
|
||||
target: getTarget(isTextarea),
|
||||
padding: null,
|
||||
viewport: document.querySelector<HTMLElement>('#viewport')!,
|
||||
content: null,
|
||||
})
|
||||
);
|
||||
assertCorrectDOMStructure(isTextarea);
|
||||
assertCorrectDestroy(snapshot, setup);
|
||||
});
|
||||
|
||||
test('null: padding | assigned: content', () => {
|
||||
const snapshot = fillBody(isTextarea, (content, hostId) => {
|
||||
return `<div id="${hostId}"><div id="content">${content}</div></div>`;
|
||||
});
|
||||
const setup = assertCorrectSetup(
|
||||
isTextarea,
|
||||
createStructureSetup({
|
||||
host: document.querySelector<HTMLElement>('#host')!,
|
||||
target: getTarget(isTextarea),
|
||||
padding: null,
|
||||
content: document.querySelector<HTMLElement>('#content')!,
|
||||
})
|
||||
);
|
||||
assertCorrectDOMStructure(isTextarea);
|
||||
assertCorrectDestroy(snapshot, setup);
|
||||
});
|
||||
describe('mixed', () => {
|
||||
test('false: padding & content | assigned: viewport', () => {
|
||||
const snapshot = fillBody(isTextarea, (content, hostId) => {
|
||||
return `<div id="${hostId}"><div id="viewport">${content}</div></div>`;
|
||||
});
|
||||
const setup = assertCorrectSetup(
|
||||
isTextarea,
|
||||
createStructureSetupProxy({
|
||||
host: document.querySelector<HTMLElement>('#host')!,
|
||||
target: getTarget(isTextarea),
|
||||
padding: false,
|
||||
viewport: document.querySelector<HTMLElement>('#viewport')!,
|
||||
content: false,
|
||||
}),
|
||||
currEnv
|
||||
);
|
||||
assertCorrectDOMStructure(isTextarea);
|
||||
assertCorrectDestroy(snapshot, setup);
|
||||
});
|
||||
|
||||
test('null: padding | assigned: viewport', () => {
|
||||
const snapshot = fillBody(isTextarea, (content, hostId) => {
|
||||
return `<div id="${hostId}"><div id="viewport">${content}</div></div>`;
|
||||
});
|
||||
const setup = assertCorrectSetup(
|
||||
isTextarea,
|
||||
createStructureSetup({
|
||||
host: document.querySelector<HTMLElement>('#host')!,
|
||||
target: getTarget(isTextarea),
|
||||
padding: null,
|
||||
viewport: document.querySelector<HTMLElement>('#viewport')!,
|
||||
})
|
||||
);
|
||||
assertCorrectDOMStructure(isTextarea);
|
||||
assertCorrectDestroy(snapshot, setup);
|
||||
});
|
||||
test('true: padding & content | assigned: viewport', () => {
|
||||
const snapshot = fillBody(isTextarea, (content, hostId) => {
|
||||
return `<div id="${hostId}"><div id="viewport">${content}</div></div>`;
|
||||
});
|
||||
const setup = assertCorrectSetup(
|
||||
isTextarea,
|
||||
createStructureSetupProxy({
|
||||
host: document.querySelector<HTMLElement>('#host')!,
|
||||
target: getTarget(isTextarea),
|
||||
padding: true,
|
||||
viewport: document.querySelector<HTMLElement>('#viewport')!,
|
||||
content: true,
|
||||
}),
|
||||
currEnv
|
||||
);
|
||||
assertCorrectDOMStructure(isTextarea);
|
||||
assertCorrectDestroy(snapshot, setup);
|
||||
});
|
||||
|
||||
test('null: padding | assigned: viewport & content', () => {
|
||||
const snapshot = fillBody(isTextarea, (content, hostId) => {
|
||||
return `<div id="${hostId}"><div id="viewport"><div id="content">${content}</div></div></div>`;
|
||||
});
|
||||
const setup = assertCorrectSetup(
|
||||
isTextarea,
|
||||
createStructureSetup({
|
||||
host: document.querySelector<HTMLElement>('#host')!,
|
||||
target: getTarget(isTextarea),
|
||||
viewport: document.querySelector<HTMLElement>('#viewport')!,
|
||||
padding: null,
|
||||
content: document.querySelector<HTMLElement>('#content')!,
|
||||
})
|
||||
);
|
||||
assertCorrectDOMStructure(isTextarea);
|
||||
assertCorrectDestroy(snapshot, setup);
|
||||
});
|
||||
test('true: content | false: padding | assigned: viewport', () => {
|
||||
const snapshot = fillBody(isTextarea, (content, hostId) => {
|
||||
return `<div id="${hostId}"><div id="viewport">${content}</div></div>`;
|
||||
});
|
||||
const setup = assertCorrectSetup(
|
||||
isTextarea,
|
||||
createStructureSetupProxy({
|
||||
host: document.querySelector<HTMLElement>('#host')!,
|
||||
target: getTarget(isTextarea),
|
||||
padding: false,
|
||||
viewport: document.querySelector<HTMLElement>('#viewport')!,
|
||||
content: true,
|
||||
}),
|
||||
currEnv
|
||||
);
|
||||
assertCorrectDOMStructure(isTextarea);
|
||||
assertCorrectDestroy(snapshot, setup);
|
||||
});
|
||||
|
||||
test('null: content | assigned: padding', () => {
|
||||
const snapshot = fillBody(isTextarea, (content, hostId) => {
|
||||
return `<div id="${hostId}"><div id="padding">${content}</div></div>`;
|
||||
});
|
||||
const setup = assertCorrectSetup(
|
||||
isTextarea,
|
||||
createStructureSetup({
|
||||
host: document.querySelector<HTMLElement>('#host')!,
|
||||
target: getTarget(isTextarea),
|
||||
padding: document.querySelector<HTMLElement>('#padding')!,
|
||||
content: null,
|
||||
})
|
||||
);
|
||||
assertCorrectDOMStructure(isTextarea);
|
||||
assertCorrectDestroy(snapshot, setup);
|
||||
});
|
||||
test('true: padding | false: content | assigned: viewport', () => {
|
||||
const snapshot = fillBody(isTextarea, (content, hostId) => {
|
||||
return `<div id="${hostId}"><div id="viewport">${content}</div></div>`;
|
||||
});
|
||||
const setup = assertCorrectSetup(
|
||||
isTextarea,
|
||||
createStructureSetupProxy({
|
||||
host: document.querySelector<HTMLElement>('#host')!,
|
||||
target: getTarget(isTextarea),
|
||||
padding: true,
|
||||
viewport: document.querySelector<HTMLElement>('#viewport')!,
|
||||
content: false,
|
||||
}),
|
||||
currEnv
|
||||
);
|
||||
assertCorrectDOMStructure(isTextarea);
|
||||
assertCorrectDestroy(snapshot, setup);
|
||||
});
|
||||
|
||||
test('null: content | assigned: viewport', () => {
|
||||
const snapshot = fillBody(isTextarea, (content, hostId) => {
|
||||
return `<div id="${hostId}"><div id="viewport">${content}</div></div>`;
|
||||
});
|
||||
const setup = assertCorrectSetup(
|
||||
isTextarea,
|
||||
createStructureSetup({
|
||||
host: document.querySelector<HTMLElement>('#host')!,
|
||||
target: getTarget(isTextarea),
|
||||
viewport: document.querySelector<HTMLElement>('#viewport')!,
|
||||
content: null,
|
||||
})
|
||||
);
|
||||
assertCorrectDOMStructure(isTextarea);
|
||||
assertCorrectDestroy(snapshot, setup);
|
||||
});
|
||||
test('false: padding | assigned: content', () => {
|
||||
const snapshot = fillBody(isTextarea, (content, hostId) => {
|
||||
return `<div id="${hostId}"><div id="content">${content}</div></div>`;
|
||||
});
|
||||
const setup = assertCorrectSetup(
|
||||
isTextarea,
|
||||
createStructureSetupProxy({
|
||||
host: document.querySelector<HTMLElement>('#host')!,
|
||||
target: getTarget(isTextarea),
|
||||
padding: false,
|
||||
content: document.querySelector<HTMLElement>('#content')!,
|
||||
}),
|
||||
currEnv
|
||||
);
|
||||
assertCorrectDOMStructure(isTextarea);
|
||||
assertCorrectDestroy(snapshot, setup);
|
||||
});
|
||||
|
||||
test('null: content | assigned: padding & viewport', () => {
|
||||
const snapshot = fillBody(isTextarea, (content, hostId) => {
|
||||
return `<div id="${hostId}"><div id="padding"><div id="viewport">${content}</div></div></div>`;
|
||||
test('true: padding | assigned: content', () => {
|
||||
const snapshot = fillBody(isTextarea, (content, hostId) => {
|
||||
return `<div id="${hostId}"><div id="content">${content}</div></div>`;
|
||||
});
|
||||
const setup = assertCorrectSetup(
|
||||
isTextarea,
|
||||
createStructureSetupProxy({
|
||||
host: document.querySelector<HTMLElement>('#host')!,
|
||||
target: getTarget(isTextarea),
|
||||
padding: true,
|
||||
content: document.querySelector<HTMLElement>('#content')!,
|
||||
}),
|
||||
currEnv
|
||||
);
|
||||
assertCorrectDOMStructure(isTextarea);
|
||||
assertCorrectDestroy(snapshot, setup);
|
||||
});
|
||||
|
||||
test('false: padding | assigned: viewport', () => {
|
||||
const snapshot = fillBody(isTextarea, (content, hostId) => {
|
||||
return `<div id="${hostId}"><div id="viewport">${content}</div></div>`;
|
||||
});
|
||||
const setup = assertCorrectSetup(
|
||||
isTextarea,
|
||||
createStructureSetupProxy({
|
||||
host: document.querySelector<HTMLElement>('#host')!,
|
||||
target: getTarget(isTextarea),
|
||||
padding: false,
|
||||
viewport: document.querySelector<HTMLElement>('#viewport')!,
|
||||
}),
|
||||
currEnv
|
||||
);
|
||||
assertCorrectDOMStructure(isTextarea);
|
||||
assertCorrectDestroy(snapshot, setup);
|
||||
});
|
||||
|
||||
test('true: padding | assigned: viewport', () => {
|
||||
const snapshot = fillBody(isTextarea, (content, hostId) => {
|
||||
return `<div id="${hostId}"><div id="viewport">${content}</div></div>`;
|
||||
});
|
||||
const setup = assertCorrectSetup(
|
||||
isTextarea,
|
||||
createStructureSetupProxy({
|
||||
host: document.querySelector<HTMLElement>('#host')!,
|
||||
target: getTarget(isTextarea),
|
||||
padding: true,
|
||||
viewport: document.querySelector<HTMLElement>('#viewport')!,
|
||||
}),
|
||||
currEnv
|
||||
);
|
||||
assertCorrectDOMStructure(isTextarea);
|
||||
assertCorrectDestroy(snapshot, setup);
|
||||
});
|
||||
|
||||
test('false: padding | assigned: viewport & content', () => {
|
||||
const snapshot = fillBody(isTextarea, (content, hostId) => {
|
||||
return `<div id="${hostId}"><div id="viewport"><div id="content">${content}</div></div></div>`;
|
||||
});
|
||||
const setup = assertCorrectSetup(
|
||||
isTextarea,
|
||||
createStructureSetupProxy({
|
||||
host: document.querySelector<HTMLElement>('#host')!,
|
||||
target: getTarget(isTextarea),
|
||||
viewport: document.querySelector<HTMLElement>('#viewport')!,
|
||||
padding: false,
|
||||
content: document.querySelector<HTMLElement>('#content')!,
|
||||
}),
|
||||
currEnv
|
||||
);
|
||||
assertCorrectDOMStructure(isTextarea);
|
||||
assertCorrectDestroy(snapshot, setup);
|
||||
});
|
||||
|
||||
test('true: padding | assigned: viewport & content', () => {
|
||||
const snapshot = fillBody(isTextarea, (content, hostId) => {
|
||||
return `<div id="${hostId}"><div id="viewport"><div id="content">${content}</div></div></div>`;
|
||||
});
|
||||
const setup = assertCorrectSetup(
|
||||
isTextarea,
|
||||
createStructureSetupProxy({
|
||||
host: document.querySelector<HTMLElement>('#host')!,
|
||||
target: getTarget(isTextarea),
|
||||
viewport: document.querySelector<HTMLElement>('#viewport')!,
|
||||
padding: true,
|
||||
content: document.querySelector<HTMLElement>('#content')!,
|
||||
}),
|
||||
currEnv
|
||||
);
|
||||
assertCorrectDOMStructure(isTextarea);
|
||||
assertCorrectDestroy(snapshot, setup);
|
||||
});
|
||||
|
||||
test('false: content | assigned: padding', () => {
|
||||
const snapshot = fillBody(isTextarea, (content, hostId) => {
|
||||
return `<div id="${hostId}"><div id="padding">${content}</div></div>`;
|
||||
});
|
||||
const setup = assertCorrectSetup(
|
||||
isTextarea,
|
||||
createStructureSetupProxy({
|
||||
host: document.querySelector<HTMLElement>('#host')!,
|
||||
target: getTarget(isTextarea),
|
||||
padding: document.querySelector<HTMLElement>('#padding')!,
|
||||
content: false,
|
||||
}),
|
||||
currEnv
|
||||
);
|
||||
assertCorrectDOMStructure(isTextarea);
|
||||
assertCorrectDestroy(snapshot, setup);
|
||||
});
|
||||
|
||||
test('true: content | assigned: padding', () => {
|
||||
const snapshot = fillBody(isTextarea, (content, hostId) => {
|
||||
return `<div id="${hostId}"><div id="padding">${content}</div></div>`;
|
||||
});
|
||||
const setup = assertCorrectSetup(
|
||||
isTextarea,
|
||||
createStructureSetupProxy({
|
||||
host: document.querySelector<HTMLElement>('#host')!,
|
||||
target: getTarget(isTextarea),
|
||||
padding: document.querySelector<HTMLElement>('#padding')!,
|
||||
content: true,
|
||||
}),
|
||||
currEnv
|
||||
);
|
||||
assertCorrectDOMStructure(isTextarea);
|
||||
assertCorrectDestroy(snapshot, setup);
|
||||
});
|
||||
|
||||
test('false: content | assigned: viewport', () => {
|
||||
const snapshot = fillBody(isTextarea, (content, hostId) => {
|
||||
return `<div id="${hostId}"><div id="viewport">${content}</div></div>`;
|
||||
});
|
||||
const setup = assertCorrectSetup(
|
||||
isTextarea,
|
||||
createStructureSetupProxy({
|
||||
host: document.querySelector<HTMLElement>('#host')!,
|
||||
target: getTarget(isTextarea),
|
||||
viewport: document.querySelector<HTMLElement>('#viewport')!,
|
||||
content: false,
|
||||
}),
|
||||
currEnv
|
||||
);
|
||||
assertCorrectDOMStructure(isTextarea);
|
||||
assertCorrectDestroy(snapshot, setup);
|
||||
});
|
||||
|
||||
test('true: content | assigned: viewport', () => {
|
||||
const snapshot = fillBody(isTextarea, (content, hostId) => {
|
||||
return `<div id="${hostId}"><div id="viewport">${content}</div></div>`;
|
||||
});
|
||||
const setup = assertCorrectSetup(
|
||||
isTextarea,
|
||||
createStructureSetupProxy({
|
||||
host: document.querySelector<HTMLElement>('#host')!,
|
||||
target: getTarget(isTextarea),
|
||||
viewport: document.querySelector<HTMLElement>('#viewport')!,
|
||||
content: true,
|
||||
}),
|
||||
currEnv
|
||||
);
|
||||
assertCorrectDOMStructure(isTextarea);
|
||||
assertCorrectDestroy(snapshot, setup);
|
||||
});
|
||||
|
||||
test('false: content | assigned: padding & viewport', () => {
|
||||
const snapshot = fillBody(isTextarea, (content, hostId) => {
|
||||
return `<div id="${hostId}"><div id="padding"><div id="viewport">${content}</div></div></div>`;
|
||||
});
|
||||
const setup = assertCorrectSetup(
|
||||
isTextarea,
|
||||
createStructureSetupProxy({
|
||||
host: document.querySelector<HTMLElement>('#host')!,
|
||||
target: getTarget(isTextarea),
|
||||
padding: document.querySelector<HTMLElement>('#padding')!,
|
||||
viewport: document.querySelector<HTMLElement>('#viewport')!,
|
||||
content: false,
|
||||
}),
|
||||
currEnv
|
||||
);
|
||||
assertCorrectDOMStructure(isTextarea);
|
||||
assertCorrectDestroy(snapshot, setup);
|
||||
});
|
||||
|
||||
test('true: content | assigned: padding & viewport', () => {
|
||||
const snapshot = fillBody(isTextarea, (content, hostId) => {
|
||||
return `<div id="${hostId}"><div id="padding"><div id="viewport">${content}</div></div></div>`;
|
||||
});
|
||||
const setup = assertCorrectSetup(
|
||||
isTextarea,
|
||||
createStructureSetupProxy({
|
||||
host: document.querySelector<HTMLElement>('#host')!,
|
||||
target: getTarget(isTextarea),
|
||||
padding: document.querySelector<HTMLElement>('#padding')!,
|
||||
viewport: document.querySelector<HTMLElement>('#viewport')!,
|
||||
content: true,
|
||||
}),
|
||||
currEnv
|
||||
);
|
||||
assertCorrectDOMStructure(isTextarea);
|
||||
assertCorrectDestroy(snapshot, setup);
|
||||
});
|
||||
});
|
||||
const setup = assertCorrectSetup(
|
||||
isTextarea,
|
||||
createStructureSetup({
|
||||
host: document.querySelector<HTMLElement>('#host')!,
|
||||
target: getTarget(isTextarea),
|
||||
padding: document.querySelector<HTMLElement>('#padding')!,
|
||||
viewport: document.querySelector<HTMLElement>('#viewport')!,
|
||||
content: null,
|
||||
})
|
||||
);
|
||||
assertCorrectDOMStructure(isTextarea);
|
||||
assertCorrectDestroy(snapshot, setup);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -4,18 +4,18 @@ import { assignDeep, isEmptyObject } from 'support/utils';
|
||||
type TestOptionsObj = { propA: 'propA'; null: null };
|
||||
type TestOptionsEnum = 'A' | 'B' | 'C';
|
||||
type TestOptions = {
|
||||
str?: string;
|
||||
strArrNull?: string | Array<string> | null;
|
||||
nullbool?: boolean | null;
|
||||
nested?: {
|
||||
num?: number;
|
||||
switch?: boolean;
|
||||
abc?: TestOptionsEnum;
|
||||
str: string;
|
||||
strArrNull: string | Array<string> | null;
|
||||
nullbool: boolean | null;
|
||||
nested: {
|
||||
num: number;
|
||||
switch: boolean;
|
||||
abc: TestOptionsEnum;
|
||||
};
|
||||
obj?: TestOptionsObj | null;
|
||||
abc?: TestOptionsEnum;
|
||||
arr?: Array<any>;
|
||||
func?: () => void;
|
||||
obj: TestOptionsObj | null;
|
||||
abc: TestOptionsEnum;
|
||||
arr: Array<any>;
|
||||
func: () => void;
|
||||
};
|
||||
|
||||
const options: TestOptions = {
|
||||
@@ -33,7 +33,7 @@ const options: TestOptions = {
|
||||
func: () => {},
|
||||
};
|
||||
|
||||
const template: OptionsTemplate<Required<TestOptions>> = {
|
||||
const template: OptionsTemplate<TestOptions> = {
|
||||
str: oTypes.string,
|
||||
strArrNull: [oTypes.string, oTypes.array, oTypes.null],
|
||||
nullbool: [oTypes.boolean, oTypes.null],
|
||||
@@ -385,7 +385,7 @@ describe('options validation', () => {
|
||||
});
|
||||
|
||||
test('nested object is undefined', () => {
|
||||
const modifiedOptions = assignDeep({}, options);
|
||||
const modifiedOptions: Partial<TestOptions> = assignDeep({}, options);
|
||||
modifiedOptions.nested = undefined;
|
||||
const result = validateOptions(modifiedOptions, template);
|
||||
const { _validated } = result;
|
||||
@@ -399,7 +399,7 @@ describe('options validation', () => {
|
||||
const { warn } = console;
|
||||
console.warn = jest.fn();
|
||||
|
||||
validateOptions(options, template, {}, true);
|
||||
validateOptions(options, template, null, true);
|
||||
expect(console.warn).not.toBeCalled();
|
||||
|
||||
console.warn = warn;
|
||||
@@ -410,7 +410,7 @@ describe('options validation', () => {
|
||||
console.warn = jest.fn();
|
||||
|
||||
const modifiedOptions = assignDeep({}, options, { str: 1 });
|
||||
validateOptions(modifiedOptions, template, {}, false);
|
||||
validateOptions(modifiedOptions, template, null, false);
|
||||
expect(console.warn).not.toBeCalled();
|
||||
|
||||
console.warn = warn;
|
||||
@@ -421,15 +421,15 @@ describe('options validation', () => {
|
||||
console.warn = jest.fn();
|
||||
|
||||
// str must be string
|
||||
validateOptions(assignDeep({}, options, { str: 1 }), template, {}, true);
|
||||
validateOptions(assignDeep({}, options, { str: 1 }), template, null, true);
|
||||
expect(console.warn).toBeCalledTimes(1);
|
||||
|
||||
// abc must be A | B | C
|
||||
validateOptions(assignDeep({}, options, { abc: 'some string' }), template, {}, true);
|
||||
validateOptions(assignDeep({}, options, { abc: 'some string' }), template, null, true);
|
||||
expect(console.warn).toBeCalledTimes(2);
|
||||
|
||||
// everthing OK
|
||||
validateOptions(assignDeep({}, options, { abc: 'C' }), template, {}, true);
|
||||
validateOptions(assignDeep({}, options, { abc: 'C' }), template, null, true);
|
||||
expect(console.warn).toBeCalledTimes(2);
|
||||
|
||||
console.warn = warn;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { XY, TRBL, CacheValues, OptionsValidated } from 'support';
|
||||
import { Options } from 'options';
|
||||
import { XY, TRBL, CacheValues } from 'support';
|
||||
import { OverlayScrollbarsOptions } from 'options';
|
||||
import { StructureSetup } from 'setups/structureSetup';
|
||||
import { StyleObject } from 'typings';
|
||||
export declare type LifecycleCheckOption = <T>(path: string) => LifecycleOptionInfo<T>;
|
||||
@@ -23,11 +23,11 @@ export interface LifecycleUpdateHints extends LifecycleAdaptiveUpdateHints {
|
||||
}
|
||||
export declare type Lifecycle = (updateHints: LifecycleUpdateHints, checkOption: LifecycleCheckOption, force: boolean) => Partial<LifecycleAdaptiveUpdateHints> | void;
|
||||
export interface LifecycleHubInstance {
|
||||
_update(changedOptions?: OptionsValidated<Options> | null, force?: boolean): void;
|
||||
_update(changedOptions?: Partial<OverlayScrollbarsOptions> | null, force?: boolean): void;
|
||||
_destroy(): void;
|
||||
}
|
||||
export interface LifecycleHub {
|
||||
_options: Options;
|
||||
_options: OverlayScrollbarsOptions;
|
||||
_structureSetup: StructureSetup;
|
||||
_doViewportArrange: boolean;
|
||||
_getPaddingInfo(): PaddingInfo;
|
||||
@@ -37,4 +37,4 @@ export interface LifecycleHub {
|
||||
_getViewportOverflowScroll(): XY<boolean>;
|
||||
_setViewportOverflowScroll(newViewportOverflowScroll: XY<boolean>): void;
|
||||
}
|
||||
export declare const createLifecycleHub: (options: Options, structureSetup: StructureSetup) => LifecycleHubInstance;
|
||||
export declare const createLifecycleHub: (options: OverlayScrollbarsOptions, structureSetup: StructureSetup) => LifecycleHubInstance;
|
||||
|
||||
+2
-2
@@ -1,2 +1,2 @@
|
||||
import { Options } from 'options';
|
||||
export declare const optionsTemplate: import("../support/options").OptionsTemplate<Required<Options>>, defaultOptions: Required<Options>;
|
||||
import { OverlayScrollbarsOptions } from 'options';
|
||||
export declare const optionsTemplate: import("../support/options").OptionsTemplate<Required<OverlayScrollbarsOptions>>, defaultOptions: Required<OverlayScrollbarsOptions>;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { OSTarget, OSTargetObject } from 'typings';
|
||||
import { Options } from 'options';
|
||||
declare const OverlayScrollbars: (target: OSTarget | OSTargetObject, options?: Options | undefined, extensions?: any) => any;
|
||||
import { OverlayScrollbarsOptions } from 'options';
|
||||
declare const OverlayScrollbars: (target: OSTarget | OSTargetObject, options?: OverlayScrollbarsOptions | undefined, extensions?: any) => any;
|
||||
export { OverlayScrollbars };
|
||||
|
||||
Reference in New Issue
Block a user