improve initialization strategy and begin with scrollbars

This commit is contained in:
Rene
2021-06-11 18:19:11 +02:00
parent 3e743ac1b9
commit a20ae81f23
13 changed files with 1018 additions and 655 deletions
+1 -1
View File
@@ -60,7 +60,7 @@
"rollup-plugin-typescript2": "^0.27.1", "rollup-plugin-typescript2": "^0.27.1",
"should": "^13.2.3", "should": "^13.2.3",
"tslib": "^2.2.0", "tslib": "^2.2.0",
"typescript": "^4.2.4", "typescript": "^4.3.2",
"utf-8-validate": "^5.0.2" "utf-8-validate": "^5.0.2"
}, },
"scripts": { "scripts": {
@@ -17,3 +17,9 @@ export const classNameSizeObserverListenerItem = `${classNameSizeObserverListene
export const classNameSizeObserverListenerItemFinal = `${classNameSizeObserverListenerItem}-final`; export const classNameSizeObserverListenerItemFinal = `${classNameSizeObserverListenerItem}-final`;
export const classNameTrinsicObserver = 'os-trinsic-observer'; export const classNameTrinsicObserver = 'os-trinsic-observer';
export const classNameScrollbar = 'os-scrollbar';
export const classNameScrollbarHorizontal = `${classNameScrollbar}-horizontal`;
export const classNameScrollbarVertical = `${classNameScrollbar}-vertical`;
export const classNameScrollbarTrack = 'os-scrollbar-track';
export const classNameScrollbarHandle = 'os-scrollbar-handle';
+37 -5
View File
@@ -25,12 +25,40 @@ import {
classNameViewportScrollbarStyling, classNameViewportScrollbarStyling,
} from 'classnames'; } from 'classnames';
import { OSOptions, defaultOptions } from 'options'; import { OSOptions, defaultOptions } from 'options';
import { OSTargetElement } from 'typings';
export interface InitializationStrategy { type StructureInitializationElementFn<T> = ((target: OSTargetElement) => HTMLElement | T) | T;
_padding: boolean;
_content: boolean; type ScrollbarsInitializationElementFn<T> = ((target: OSTargetElement, host: HTMLElement, viewport: HTMLElement) => HTMLElement | T) | T;
/**
* A Static element is an element which MUST be generated.
* If null (or the returned result is null), the initialization function is generatig the element, otherwise
* the element returned by the function acts as the generated element.
*/
export type StructureInitializationStaticElement = StructureInitializationElementFn<null>;
/**
* A Dynamic element is an element which CAN be generated.
* If null (or the returned result is null), then the default behavior is used.
* If boolean (or the returned result is boolean), the generation of the element is forced (or not).
* If the function returns and element, the element returned by the function acts as the generated element.
*/
export type StructureInitializationDynamicElement = StructureInitializationElementFn<boolean | null>;
export interface StructureInitializationStrategy {
_host: StructureInitializationStaticElement;
_viewport: StructureInitializationStaticElement;
_padding: StructureInitializationDynamicElement;
_content: StructureInitializationDynamicElement;
} }
export interface ScrollbarsInitializationStrategy {
_scrollbarsSlot: ScrollbarsInitializationElementFn<null | undefined>;
}
export interface InitializationStrategy extends StructureInitializationStrategy, ScrollbarsInitializationStrategy {}
export type OnEnvironmentChanged = (env: Environment) => void; export type OnEnvironmentChanged = (env: Environment) => void;
export interface Environment { export interface Environment {
_nativeScrollbarSize: XY; _nativeScrollbarSize: XY;
@@ -132,9 +160,13 @@ const getWindowDPR = (): number => {
return window.devicePixelRatio || dDPI / sDPI; return window.devicePixelRatio || dDPI / sDPI;
}; };
// init function decides for all values
const getDefaultInitializationStrategy = (nativeScrollbarStyling: boolean): InitializationStrategy => ({ const getDefaultInitializationStrategy = (nativeScrollbarStyling: boolean): InitializationStrategy => ({
_padding: !nativeScrollbarStyling, _host: null,
_content: false, _viewport: null,
_padding: null,
_content: null,
_scrollbarsSlot: null,
}); });
const createEnvironment = (): Environment => { const createEnvironment = (): Environment => {
@@ -7,6 +7,7 @@ import { createTrinsicLifecycle } from 'lifecycles/trinsicLifecycle';
import { createPaddingLifecycle } from 'lifecycles/paddingLifecycle'; import { createPaddingLifecycle } from 'lifecycles/paddingLifecycle';
import { createOverflowLifecycle } from 'lifecycles/overflowLifecycle'; import { createOverflowLifecycle } from 'lifecycles/overflowLifecycle';
import { StyleObject } from 'typings'; import { StyleObject } from 'typings';
import { ScrollbarsSetup } from 'setups/scrollbarsSetup';
export type LifecycleCheckOption = <T>(path: string) => LifecycleOptionInfo<T>; export type LifecycleCheckOption = <T>(path: string) => LifecycleOptionInfo<T>;
@@ -99,7 +100,7 @@ const lifecycleCommunicationFallback: LifecycleCommunication = {
}, },
}; };
export const createLifecycleHub = (options: OSOptions, structureSetup: StructureSetup): LifecycleHubInstance => { export const createLifecycleHub = (options: OSOptions, structureSetup: StructureSetup, scrollbarsSetup: ScrollbarsSetup): LifecycleHubInstance => {
let lifecycleCommunication = lifecycleCommunicationFallback; let lifecycleCommunication = lifecycleCommunicationFallback;
const { _viewport } = structureSetup._targetObj; const { _viewport } = structureSetup._targetObj;
const { const {
@@ -201,6 +202,9 @@ export const createLifecycleHub = (options: OSOptions, structureSetup: Structure
_destroy() { _destroy() {
destroyObservers(); destroyObservers();
removeEnvironmentListener(envUpdateListener); removeEnvironmentListener(envUpdateListener);
structureSetup._destroy();
scrollbarsSetup._destroy();
}, },
}; };
}; };
@@ -1,12 +1,13 @@
import { OSTarget, OSTargetObject } from 'typings'; import { OSTarget, OSInitializationObject } from 'typings';
import { PartialOptions, validateOptions, assignDeep, isEmptyObject } from 'support'; import { PartialOptions, validateOptions, assignDeep, isEmptyObject } from 'support';
import { createStructureSetup, StructureSetup } from 'setups/structureSetup'; import { createStructureSetup, StructureSetup } from 'setups/structureSetup';
import { createScrollbarsSetup, ScrollbarsSetup } from 'setups/scrollbarsSetup';
import { createLifecycleHub } from 'lifecycles/lifecycleHub'; import { createLifecycleHub } from 'lifecycles/lifecycleHub';
import { OSOptions, optionsTemplate } from 'options'; import { OSOptions, optionsTemplate } from 'options';
import { getEnvironment } from 'environment'; import { getEnvironment } from 'environment';
export interface OverlayScrollbarsStatic { export interface OverlayScrollbarsStatic {
(target: OSTarget | OSTargetObject, options?: PartialOptions<OSOptions>, extensions?: any): OverlayScrollbars; (target: OSTarget | OSInitializationObject, options?: PartialOptions<OSOptions>, extensions?: any): OverlayScrollbars;
} }
export interface OverlayScrollbars { export interface OverlayScrollbars {
@@ -14,12 +15,13 @@ export interface OverlayScrollbars {
options(newOptions?: PartialOptions<OSOptions>): OSOptions; options(newOptions?: PartialOptions<OSOptions>): OSOptions;
update(force?: boolean): void; update(force?: boolean): void;
destroy(): void;
state(): any; state(): any;
} }
export const OverlayScrollbars: OverlayScrollbarsStatic = ( export const OverlayScrollbars: OverlayScrollbarsStatic = (
target: OSTarget | OSTargetObject, target: OSTarget | OSInitializationObject,
options?: PartialOptions<OSOptions>, options?: PartialOptions<OSOptions>,
extensions?: any extensions?: any
): OverlayScrollbars => { ): OverlayScrollbars => {
@@ -30,7 +32,9 @@ export const OverlayScrollbars: OverlayScrollbarsStatic = (
validateOptions(options || ({} as PartialOptions<OSOptions>), optionsTemplate, null, true)._validated validateOptions(options || ({} as PartialOptions<OSOptions>), optionsTemplate, null, true)._validated
); );
const structureSetup: StructureSetup = createStructureSetup(target); const structureSetup: StructureSetup = createStructureSetup(target);
const lifecycleHub = createLifecycleHub(currentOptions, structureSetup); const scrollbarsSetup: ScrollbarsSetup = createScrollbarsSetup(target, structureSetup);
const lifecycleHub = createLifecycleHub(currentOptions, structureSetup, scrollbarsSetup);
const instance: OverlayScrollbars = { const instance: OverlayScrollbars = {
options(newOptions?: PartialOptions<OSOptions>) { options(newOptions?: PartialOptions<OSOptions>) {
if (newOptions) { if (newOptions) {
@@ -47,6 +51,7 @@ export const OverlayScrollbars: OverlayScrollbarsStatic = (
update(force?: boolean) { update(force?: boolean) {
lifecycleHub._update(null, force); lifecycleHub._update(null, force);
}, },
destroy: () => lifecycleHub._destroy(),
}; };
instance.update(true); instance.update(true);
@@ -0,0 +1,70 @@
import { appendChildren, createDiv, removeElements, isFunction } from 'support';
import {
classNameScrollbar,
classNameScrollbarHorizontal,
classNameScrollbarVertical,
classNameScrollbarTrack,
classNameScrollbarHandle,
} from 'classnames';
import { getEnvironment, ScrollbarsInitializationStrategy } from 'environment';
import { OSTarget, ScrollbarsInitialization } from 'typings';
import { StructureSetup } from 'setups/structureSetup';
export interface ScrollbarStructure {
_scrollbar: HTMLElement;
_track: HTMLElement;
_handle: HTMLElement;
}
export interface ScrollbarsSetup {
_horizontalScrollbarStructure: ScrollbarStructure;
_verticalScrollbarStructure: ScrollbarStructure;
_destroy: () => void;
}
const generateScrollbarDOM = (scrollbarClassName: string): ScrollbarStructure => {
const scrollbar = createDiv(`${classNameScrollbar} ${scrollbarClassName}`);
const track = createDiv(classNameScrollbarTrack);
const handle = createDiv(classNameScrollbarHandle);
appendChildren(scrollbar, track);
appendChildren(track, handle);
return {
_scrollbar: scrollbar,
_track: track,
_handle: handle,
};
};
export const createScrollbarsSetup = (target: OSTarget | ScrollbarsInitialization, structureSetup: StructureSetup): ScrollbarsSetup => {
const { _getInitializationStrategy } = getEnvironment();
const { _scrollbarsSlot: environmentScrollbarSlot } = _getInitializationStrategy() as ScrollbarsInitializationStrategy;
const { _targetObj, _targetCtx } = structureSetup;
const { _target, _host, _viewport } = _targetObj;
const initializationScrollbarSlot = !_targetCtx._targetIsElm && (target as ScrollbarsInitialization).scrollbarsSlot;
const initializationScrollbarSlotResult = isFunction(initializationScrollbarSlot)
? initializationScrollbarSlot(_target, _host, _viewport)
: initializationScrollbarSlot;
const evaluatedScrollbarSlot =
initializationScrollbarSlotResult ||
(isFunction(environmentScrollbarSlot) ? environmentScrollbarSlot(_target, _host, _viewport) : environmentScrollbarSlot) ||
_host;
const horizontalScrollbarStructure = generateScrollbarDOM(classNameScrollbarHorizontal);
const verticalScrollbarStructure = generateScrollbarDOM(classNameScrollbarVertical);
const { _scrollbar: horizontalScrollbar } = horizontalScrollbarStructure;
const { _scrollbar: verticalScrollbar } = verticalScrollbarStructure;
appendChildren(evaluatedScrollbarSlot, horizontalScrollbar);
appendChildren(evaluatedScrollbarSlot, verticalScrollbar);
return {
_horizontalScrollbarStructure: horizontalScrollbarStructure,
_verticalScrollbarStructure: verticalScrollbarStructure,
_destroy() {
removeElements([horizontalScrollbar, verticalScrollbar]);
},
};
};
@@ -7,7 +7,7 @@ import {
insertAfter, insertAfter,
addClass, addClass,
parent, parent,
isUndefined, indexOf,
removeElements, removeElements,
removeClass, removeClass,
push, push,
@@ -15,6 +15,8 @@ import {
insertBefore, insertBefore,
attr, attr,
isBoolean, isBoolean,
isFunction,
keys,
} from 'support'; } from 'support';
import { import {
classNameHost, classNameHost,
@@ -24,8 +26,13 @@ import {
classNameContent, classNameContent,
classNameViewportScrollbarStyling, classNameViewportScrollbarStyling,
} from 'classnames'; } from 'classnames';
import { getEnvironment } from 'environment'; import {
import { OSTarget, OSTargetObject, OSTargetElement } from 'typings'; getEnvironment,
StructureInitializationStaticElement,
StructureInitializationDynamicElement,
StructureInitializationStrategy,
} from 'environment';
import { OSTarget, OSTargetElement, StructureInitialization } from 'typings';
export interface OSTargetContext { export interface OSTargetContext {
_isTextarea: boolean; _isTextarea: boolean;
@@ -34,15 +41,16 @@ export interface OSTargetContext {
_bodyElm: HTMLBodyElement; _bodyElm: HTMLBodyElement;
_windowElm: Window; _windowElm: Window;
_documentElm: HTMLDocument; _documentElm: HTMLDocument;
_targetIsElm: boolean;
} }
export interface PreparedOSTargetObject { export interface PreparedOSTargetObject {
_target: OSTargetElement; _target: OSTargetElement;
_host: HTMLElement; _host: HTMLElement;
_viewport: HTMLElement; _viewport: HTMLElement;
_padding: HTMLElement | false | null; _padding: HTMLElement | false;
_content: HTMLElement | false | null; _content: HTMLElement | false;
_viewportArrange: HTMLStyleElement | false | null; _viewportArrange: HTMLStyleElement | false;
} }
export interface StructureSetup { export interface StructureSetup {
@@ -51,60 +59,113 @@ export interface StructureSetup {
_destroy: () => void; _destroy: () => void;
} }
let contentArrangeCounter = 0;
const unwrap = (elm: HTMLElement | false | null | undefined) => { const unwrap = (elm: HTMLElement | false | null | undefined) => {
appendChildren(parent(elm), contents(elm)); appendChildren(parent(elm), contents(elm));
removeElements(elm); removeElements(elm);
}; };
let contentArrangeCounter = 0; const createUniqueViewportArrangeElement = (): HTMLStyleElement | false => {
const createUniqueViewportArrangeElement = (): HTMLStyleElement => { const { _nativeScrollbarStyling, _nativeScrollbarIsOverlaid, _cssCustomProperties } = getEnvironment();
const elm = document.createElement('style'); /* istanbul ignore next */
const create = !_cssCustomProperties && !_nativeScrollbarStyling && (_nativeScrollbarIsOverlaid.x || _nativeScrollbarIsOverlaid.y);
const result = create ? document.createElement('style') : false;
attr(elm, 'id', `${classNameViewportArrange}-${contentArrangeCounter}`); if (result) {
contentArrangeCounter++; attr(result, 'id', `${classNameViewportArrange}-${contentArrangeCounter}`);
contentArrangeCounter++;
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;
return result;
}; };
export const createStructureSetup = (target: OSTarget | OSTargetObject): StructureSetup => { const staticCreationFromStrategy = (
const { _getInitializationStrategy, _nativeScrollbarStyling, _nativeScrollbarIsOverlaid, _cssCustomProperties } = getEnvironment(); target: OSTargetElement,
const { _padding: paddingNeeded, _content: contentNeeded } = _getInitializationStrategy(); initializationValue: HTMLElement | undefined,
strategy: StructureInitializationStaticElement,
elementClass: string
): HTMLElement => {
const result = initializationValue ? initializationValue : isFunction(strategy) ? strategy(target) : (strategy as null);
return result ? result : createDiv(elementClass);
};
const dynamicCreationFromStrategy = (
target: OSTargetElement,
initializationValue: HTMLElement | boolean | undefined,
strategy: StructureInitializationDynamicElement,
elementClass: string,
defaultValue: boolean
): HTMLElement | false => {
const takeInitializationValue = isBoolean(initializationValue) || initializationValue;
const result = takeInitializationValue ? (initializationValue as boolean | HTMLElement) : isFunction(strategy) ? strategy(target) : strategy;
if (result === null) {
return defaultValue ? createDiv(elementClass) : false;
}
return result === true ? createDiv(elementClass) : result;
};
export const createStructureSetup = (target: OSTarget | StructureInitialization): StructureSetup => {
const { _getInitializationStrategy, _nativeScrollbarStyling } = getEnvironment();
const {
_host: hostInitializationStrategy,
_viewport: viewportInitializationStrategy,
_padding: paddingInitializationStrategy,
_content: contentInitializationStrategy,
} = _getInitializationStrategy() as StructureInitializationStrategy;
const targetIsElm = isHTMLElement(target); const targetIsElm = isHTMLElement(target);
const osTargetObj: Partial<PreparedOSTargetObject> = targetIsElm const targetStructureInitialization = target as StructureInitialization;
? ({} as Partial<PreparedOSTargetObject>) const targetElement = targetIsElm ? (target as OSTargetElement) : targetStructureInitialization.target;
: { const isTextarea = is(targetElement, 'textarea');
_host: (target as OSTargetObject).host, const isBody = !isTextarea && is(targetElement, 'body');
_target: (target as OSTargetObject).target, const ownerDocument: HTMLDocument = targetElement!.ownerDocument;
_viewport: (target as OSTargetObject).viewport, const bodyElm = ownerDocument.body as HTMLBodyElement;
_padding: evaluateCreationFromStrategy((target as OSTargetObject).padding, paddingNeeded), const wnd = ownerDocument.defaultView as Window;
_content: evaluateCreationFromStrategy((target as OSTargetObject).content, contentNeeded), const evaluatedTargetObj: PreparedOSTargetObject = {
}; _target: targetElement,
_host: isTextarea
if (targetIsElm) { ? staticCreationFromStrategy(targetElement, targetStructureInitialization.host, hostInitializationStrategy, classNameHost)
const viewport = createDiv(classNameViewport); : (targetElement as HTMLElement),
const padding = paddingNeeded && createDiv(classNamePadding); _viewport: staticCreationFromStrategy(targetElement, targetStructureInitialization.viewport, viewportInitializationStrategy, classNameViewport),
const content = contentNeeded && createDiv(classNameContent); _padding: dynamicCreationFromStrategy(
targetElement,
osTargetObj._target = target as OSTargetElement; targetStructureInitialization.padding,
osTargetObj._padding = padding; paddingInitializationStrategy,
osTargetObj._viewport = viewport; classNamePadding,
osTargetObj._content = content; !_nativeScrollbarStyling // default value for padding
} ),
_content: dynamicCreationFromStrategy(
let { _target, _padding, _viewport, _content } = osTargetObj; targetElement,
targetStructureInitialization.content,
contentInitializationStrategy,
classNameContent,
false // default value for content
),
_viewportArrange: createUniqueViewportArrangeElement(),
};
const ctx: OSTargetContext = {
_windowElm: wnd,
_documentElm: ownerDocument,
_htmlElm: parent(bodyElm) as HTMLHtmlElement,
_bodyElm: bodyElm,
_isTextarea: isTextarea,
_isBody: isBody,
_targetIsElm: targetIsElm,
};
const generatedElements = keys(evaluatedTargetObj).reduce((arr, key: string) => {
const value = evaluatedTargetObj[key];
return push(arr, value && !parent(value) ? value : false);
}, [] as HTMLElement[]);
const elementIsGenerated = (elm: HTMLElement | false) => (elm ? indexOf(generatedElements, elm) > -1 : null);
const { _target, _host, _padding, _viewport, _content, _viewportArrange } = evaluatedTargetObj;
const destroyFns: (() => any)[] = []; const destroyFns: (() => any)[] = [];
const isTextarea = is(_target, 'textarea'); const isTextareaHostGenerated = isTextarea && elementIsGenerated(_host);
const isBody = !isTextarea && is(_target, 'body'); const targetContents = isTextarea
const _host = (isTextarea ? osTargetObj._host || createDiv() : _target) as HTMLElement; ? _target
const getTargetContents = (contentSlot: HTMLElement) => (isTextarea ? (_target as HTMLTextAreaElement) : contents(contentSlot as HTMLElement)); : contents([_content, _viewport, _padding, _host, _target].find((elm) => elementIsGenerated(elm) === false));
const isTextareaHostGenerated = isTextarea && _host !== osTargetObj._host; const contentSlot = _content || _viewport;
// only insert host for textarea after target if it was generated // only insert host for textarea after target if it was generated
if (isTextareaHostGenerated) { if (isTextareaHostGenerated) {
@@ -116,88 +177,48 @@ export const createStructureSetup = (target: OSTarget | OSTargetObject): Structu
}); });
} }
if (targetIsElm) { appendChildren(contentSlot, targetContents);
const contentSlot = _content || _viewport; appendChildren(_host, _padding);
appendChildren(contentSlot, getTargetContents(_target!)); appendChildren(_padding || _host, _viewport);
appendChildren(_host, _padding); appendChildren(_viewport, _content);
appendChildren(_padding || _host, _viewport);
appendChildren(_viewport, _content);
push(destroyFns, () => {
appendChildren(_host, contents(contentSlot));
removeElements(_padding || _viewport);
removeClass(_host, classNameHost);
});
} else {
const contentContainingElm = _content || _viewport || _padding || _host;
const createPadding = isUndefined(_padding);
const createViewport = isUndefined(_viewport);
const createContent = isUndefined(_content);
const targetContents = getTargetContents(contentContainingElm);
_padding = osTargetObj._padding = createPadding ? createDiv() : _padding;
_viewport = osTargetObj._viewport = createViewport ? createDiv() : _viewport;
_content = osTargetObj._content = createContent ? createDiv() : _content;
appendChildren(_host, _padding);
appendChildren(_padding || _host, _viewport);
appendChildren(_viewport, _content);
const contentSlot = _content || _viewport;
appendChildren(contentSlot, targetContents);
push(destroyFns, () => {
if (createContent) {
unwrap(_content);
}
if (createViewport) {
unwrap(_viewport);
}
if (createPadding) {
unwrap(_padding);
}
removeClass(_host, classNameHost);
removeClass(_padding, classNamePadding);
removeClass(_viewport, classNameViewport);
removeClass(_content, classNameContent);
});
}
addClass(_host, classNameHost); addClass(_host, classNameHost);
addClass(_padding, classNamePadding); addClass(_padding, classNamePadding);
addClass(_viewport, classNameViewport); addClass(_viewport, classNameViewport);
addClass(_content, classNameContent); addClass(_content, classNameContent);
const ownerDocument: HTMLDocument = _target!.ownerDocument; push(destroyFns, () => {
const bodyElm = ownerDocument.body as HTMLBodyElement; if (targetIsElm) {
const wnd = ownerDocument.defaultView as Window; appendChildren(_host, contents(contentSlot));
const ctx: OSTargetContext = { removeElements(_padding || _viewport);
_windowElm: wnd, removeClass(_host, classNameHost);
_documentElm: ownerDocument, } else {
_htmlElm: parent(bodyElm) as HTMLHtmlElement, if (elementIsGenerated(_content)) {
_bodyElm: bodyElm, unwrap(_content);
_isTextarea: isTextarea, }
_isBody: isBody, if (elementIsGenerated(_viewport)) {
}; unwrap(_viewport);
// @ts-ignore }
const obj: PreparedOSTargetObject = { if (elementIsGenerated(_padding)) {
...osTargetObj, unwrap(_padding);
_host, }
}; removeClass(_host, classNameHost);
removeClass(_padding, classNamePadding);
removeClass(_viewport, classNameViewport);
removeClass(_content, classNameContent);
}
});
if (_nativeScrollbarStyling) { if (_nativeScrollbarStyling) {
push(destroyFns, removeClass.bind(0, _viewport, classNameViewportScrollbarStyling)); push(destroyFns, removeClass.bind(0, _viewport, classNameViewportScrollbarStyling));
} else if (!_cssCustomProperties && (_nativeScrollbarIsOverlaid.x || _nativeScrollbarIsOverlaid.y)) { }
const viewportArrangeElm = createUniqueViewportArrangeElement(); if (_viewportArrange) {
insertBefore(_viewport, _viewportArrange);
insertBefore(_viewport, viewportArrangeElm); push(destroyFns, removeElements.bind(0, _viewportArrange));
push(destroyFns, removeElements.bind(0, viewportArrangeElm));
obj._viewportArrange = viewportArrangeElm;
} }
return { return {
_targetObj: obj, _targetObj: evaluatedTargetObj,
_targetCtx: ctx, _targetCtx: ctx,
_destroy: () => { _destroy: () => {
runEach(destroyFns); runEach(destroyFns);
@@ -1,5 +1,6 @@
@import './sizeobserver.scss'; @import './sizeobserver.scss';
@import './trinsicobserver.scss'; @import './trinsicobserver.scss';
@import './scrollbars.scss';
.os-environment { .os-environment {
--os-custom-prop: -1; --os-custom-prop: -1;
File diff suppressed because one or more lines are too long
@@ -32,7 +32,7 @@ export function isBoolean(obj: any): obj is boolean {
return typeof obj === 'boolean'; return typeof obj === 'boolean';
} }
export function isFunction(obj: any): obj is (...args: Array<unknown>) => unknown { export function isFunction(obj: any): obj is (...args: any[]) => any {
return typeof obj === 'function'; return typeof obj === 'function';
} }
+34 -9
View File
@@ -1,3 +1,5 @@
export type PlainObject<T = any> = { [name: string]: T }; export type PlainObject<T = any> = { [name: string]: T };
export type StyleObject<CustomCssProps = ''> = { export type StyleObject<CustomCssProps = ''> = {
@@ -10,6 +12,19 @@ export type InternalVersionOf<T> = {
export type OSTargetElement = HTMLElement | HTMLTextAreaElement; export type OSTargetElement = HTMLElement | HTMLTextAreaElement;
/**
* Static elements MUST be present.
*/
type StructureInitializationStaticElement = HTMLElement;
/**
* 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.
*/
type StructureInitializationDynamicElement = HTMLElement | boolean;
/** /**
* Object for special initialization. * Object for special initialization.
* *
@@ -18,19 +33,29 @@ export type OSTargetElement = HTMLElement | HTMLTextAreaElement;
* If element is provided, the provided element takes all its responsibilities. * 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. * DOM hierarchy isn't checked in this case, its assumed that hieararchy is correct in such a case.
* *
* Undefined means that the plugin decides whether the respective element needs to be added or can be savely omitted. * Undefined means that the environment initialization strategy for the respective element is used.
* 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 { export interface StructureInitialization {
target: OSTargetElement; target: OSTargetElement;
host?: HTMLElement; host?: StructureInitializationStaticElement; // only relevant for textarea
padding?: HTMLElement | boolean; viewport?: StructureInitializationStaticElement;
viewport?: HTMLElement; padding?: StructureInitializationDynamicElement;
content?: HTMLElement | boolean; content?: StructureInitializationDynamicElement;
} }
export type OSTarget = OSTargetElement | OSTargetObject; /**
* Object for special initialization.
*
* scrollbarsSlot is the element to which the scrollbars are applied to. If null or undefined the plugin decides by itself whats the scrollbars slot.
*/
export interface ScrollbarsInitialization {
scrollbarsSlot?: null | HTMLElement | ((target: OSTargetElement, host: HTMLElement, viewport: HTMLElement) => null | HTMLElement);
}
export interface OSInitializationObject extends StructureInitialization, ScrollbarsInitialization {
}
export type OSTarget = OSTargetElement | OSInitializationObject;
/* /*
export namespace OverlayScrollbars { export namespace OverlayScrollbars {
File diff suppressed because it is too large Load Diff
+4 -4
View File
@@ -8790,10 +8790,10 @@ typescript@^3.9.3:
resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.9.7.tgz#98d600a5ebdc38f40cb277522f12dc800e9e25fa" resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.9.7.tgz#98d600a5ebdc38f40cb277522f12dc800e9e25fa"
integrity sha512-BLbiRkiBzAwsjut4x/dsibSTB6yWpwT5qWmC2OfuCg3GgVQCSgMs4vEctYPhsaGtd0AeuuHMkjZ2h2WG8MSzRw== integrity sha512-BLbiRkiBzAwsjut4x/dsibSTB6yWpwT5qWmC2OfuCg3GgVQCSgMs4vEctYPhsaGtd0AeuuHMkjZ2h2WG8MSzRw==
typescript@^4.2.4: typescript@^4.3.2:
version "4.2.4" version "4.3.2"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.2.4.tgz#8610b59747de028fda898a8aef0e103f156d0961" resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.3.2.tgz#399ab18aac45802d6f2498de5054fcbbe716a805"
integrity sha512-V+evlYHZnQkaz8TRBuxTA92yZBPotr5H+WhQ7bD3hZUndx5tGOa1fuCgeSjxAzM1RiN5IzvadIXTVefuuwZCRg== integrity sha512-zZ4hShnmnoVnAHpVHWpTcxdv7dWP60S2FsydQLV8V5PbS3FifjWFFRiHSWpDJahly88PRyV5teTSLoq4eG7mKw==
unicode-canonical-property-names-ecmascript@^1.0.4: unicode-canonical-property-names-ecmascript@^1.0.4:
version "1.0.4" version "1.0.4"