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 1020 additions and 657 deletions
+1 -1
View File
@@ -60,7 +60,7 @@
"rollup-plugin-typescript2": "^0.27.1",
"should": "^13.2.3",
"tslib": "^2.2.0",
"typescript": "^4.2.4",
"typescript": "^4.3.2",
"utf-8-validate": "^5.0.2"
},
"scripts": {
@@ -17,3 +17,9 @@ export const classNameSizeObserverListenerItem = `${classNameSizeObserverListene
export const classNameSizeObserverListenerItemFinal = `${classNameSizeObserverListenerItem}-final`;
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,
} from 'classnames';
import { OSOptions, defaultOptions } from 'options';
import { OSTargetElement } from 'typings';
export interface InitializationStrategy {
_padding: boolean;
_content: boolean;
type StructureInitializationElementFn<T> = ((target: OSTargetElement) => HTMLElement | T) | T;
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 interface Environment {
_nativeScrollbarSize: XY;
@@ -132,9 +160,13 @@ const getWindowDPR = (): number => {
return window.devicePixelRatio || dDPI / sDPI;
};
// init function decides for all values
const getDefaultInitializationStrategy = (nativeScrollbarStyling: boolean): InitializationStrategy => ({
_padding: !nativeScrollbarStyling,
_content: false,
_host: null,
_viewport: null,
_padding: null,
_content: null,
_scrollbarsSlot: null,
});
const createEnvironment = (): Environment => {
@@ -7,6 +7,7 @@ import { createTrinsicLifecycle } from 'lifecycles/trinsicLifecycle';
import { createPaddingLifecycle } from 'lifecycles/paddingLifecycle';
import { createOverflowLifecycle } from 'lifecycles/overflowLifecycle';
import { StyleObject } from 'typings';
import { ScrollbarsSetup } from 'setups/scrollbarsSetup';
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;
const { _viewport } = structureSetup._targetObj;
const {
@@ -201,6 +202,9 @@ export const createLifecycleHub = (options: OSOptions, structureSetup: Structure
_destroy() {
destroyObservers();
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 { createStructureSetup, StructureSetup } from 'setups/structureSetup';
import { createScrollbarsSetup, ScrollbarsSetup } from 'setups/scrollbarsSetup';
import { createLifecycleHub } from 'lifecycles/lifecycleHub';
import { OSOptions, optionsTemplate } from 'options';
import { getEnvironment } from 'environment';
export interface OverlayScrollbarsStatic {
(target: OSTarget | OSTargetObject, options?: PartialOptions<OSOptions>, extensions?: any): OverlayScrollbars;
(target: OSTarget | OSInitializationObject, options?: PartialOptions<OSOptions>, extensions?: any): OverlayScrollbars;
}
export interface OverlayScrollbars {
@@ -14,12 +15,13 @@ export interface OverlayScrollbars {
options(newOptions?: PartialOptions<OSOptions>): OSOptions;
update(force?: boolean): void;
destroy(): void;
state(): any;
}
export const OverlayScrollbars: OverlayScrollbarsStatic = (
target: OSTarget | OSTargetObject,
target: OSTarget | OSInitializationObject,
options?: PartialOptions<OSOptions>,
extensions?: any
): OverlayScrollbars => {
@@ -30,7 +32,9 @@ export const OverlayScrollbars: OverlayScrollbarsStatic = (
validateOptions(options || ({} as PartialOptions<OSOptions>), optionsTemplate, null, true)._validated
);
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 = {
options(newOptions?: PartialOptions<OSOptions>) {
if (newOptions) {
@@ -47,6 +51,7 @@ export const OverlayScrollbars: OverlayScrollbarsStatic = (
update(force?: boolean) {
lifecycleHub._update(null, force);
},
destroy: () => lifecycleHub._destroy(),
};
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,
addClass,
parent,
isUndefined,
indexOf,
removeElements,
removeClass,
push,
@@ -15,6 +15,8 @@ import {
insertBefore,
attr,
isBoolean,
isFunction,
keys,
} from 'support';
import {
classNameHost,
@@ -24,8 +26,13 @@ import {
classNameContent,
classNameViewportScrollbarStyling,
} from 'classnames';
import { getEnvironment } from 'environment';
import { OSTarget, OSTargetObject, OSTargetElement } from 'typings';
import {
getEnvironment,
StructureInitializationStaticElement,
StructureInitializationDynamicElement,
StructureInitializationStrategy,
} from 'environment';
import { OSTarget, OSTargetElement, StructureInitialization } from 'typings';
export interface OSTargetContext {
_isTextarea: boolean;
@@ -34,15 +41,16 @@ export interface OSTargetContext {
_bodyElm: HTMLBodyElement;
_windowElm: Window;
_documentElm: HTMLDocument;
_targetIsElm: boolean;
}
export interface PreparedOSTargetObject {
_target: OSTargetElement;
_host: HTMLElement;
_viewport: HTMLElement;
_padding: HTMLElement | false | null;
_content: HTMLElement | false | null;
_viewportArrange: HTMLStyleElement | false | null;
_padding: HTMLElement | false;
_content: HTMLElement | false;
_viewportArrange: HTMLStyleElement | false;
}
export interface StructureSetup {
@@ -51,60 +59,113 @@ export interface StructureSetup {
_destroy: () => void;
}
let contentArrangeCounter = 0;
const unwrap = (elm: HTMLElement | false | null | undefined) => {
appendChildren(parent(elm), contents(elm));
removeElements(elm);
};
let contentArrangeCounter = 0;
const createUniqueViewportArrangeElement = (): HTMLStyleElement => {
const elm = document.createElement('style');
const createUniqueViewportArrangeElement = (): HTMLStyleElement | false => {
const { _nativeScrollbarStyling, _nativeScrollbarIsOverlaid, _cssCustomProperties } = getEnvironment();
/* istanbul ignore next */
const create = !_cssCustomProperties && !_nativeScrollbarStyling && (_nativeScrollbarIsOverlaid.x || _nativeScrollbarIsOverlaid.y);
const result = create ? document.createElement('style') : false;
attr(elm, '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;
if (result) {
attr(result, 'id', `${classNameViewportArrange}-${contentArrangeCounter}`);
contentArrangeCounter++;
}
return initializationValue as HTMLElement;
return result;
};
export const createStructureSetup = (target: OSTarget | OSTargetObject): StructureSetup => {
const { _getInitializationStrategy, _nativeScrollbarStyling, _nativeScrollbarIsOverlaid, _cssCustomProperties } = getEnvironment();
const { _padding: paddingNeeded, _content: contentNeeded } = _getInitializationStrategy();
const staticCreationFromStrategy = (
target: OSTargetElement,
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 osTargetObj: Partial<PreparedOSTargetObject> = targetIsElm
? ({} as Partial<PreparedOSTargetObject>)
: {
_host: (target as OSTargetObject).host,
_target: (target as OSTargetObject).target,
_viewport: (target as OSTargetObject).viewport,
_padding: evaluateCreationFromStrategy((target as OSTargetObject).padding, paddingNeeded),
_content: evaluateCreationFromStrategy((target as OSTargetObject).content, contentNeeded),
};
if (targetIsElm) {
const viewport = createDiv(classNameViewport);
const padding = paddingNeeded && createDiv(classNamePadding);
const content = contentNeeded && createDiv(classNameContent);
osTargetObj._target = target as OSTargetElement;
osTargetObj._padding = padding;
osTargetObj._viewport = viewport;
osTargetObj._content = content;
}
let { _target, _padding, _viewport, _content } = osTargetObj;
const targetStructureInitialization = target as StructureInitialization;
const targetElement = targetIsElm ? (target as OSTargetElement) : targetStructureInitialization.target;
const isTextarea = is(targetElement, 'textarea');
const isBody = !isTextarea && is(targetElement, 'body');
const ownerDocument: HTMLDocument = targetElement!.ownerDocument;
const bodyElm = ownerDocument.body as HTMLBodyElement;
const wnd = ownerDocument.defaultView as Window;
const evaluatedTargetObj: PreparedOSTargetObject = {
_target: targetElement,
_host: isTextarea
? staticCreationFromStrategy(targetElement, targetStructureInitialization.host, hostInitializationStrategy, classNameHost)
: (targetElement as HTMLElement),
_viewport: staticCreationFromStrategy(targetElement, targetStructureInitialization.viewport, viewportInitializationStrategy, classNameViewport),
_padding: dynamicCreationFromStrategy(
targetElement,
targetStructureInitialization.padding,
paddingInitializationStrategy,
classNamePadding,
!_nativeScrollbarStyling // default value for padding
),
_content: dynamicCreationFromStrategy(
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 isTextarea = is(_target, 'textarea');
const isBody = !isTextarea && is(_target, 'body');
const _host = (isTextarea ? osTargetObj._host || createDiv() : _target) as HTMLElement;
const getTargetContents = (contentSlot: HTMLElement) => (isTextarea ? (_target as HTMLTextAreaElement) : contents(contentSlot as HTMLElement));
const isTextareaHostGenerated = isTextarea && _host !== osTargetObj._host;
const isTextareaHostGenerated = isTextarea && elementIsGenerated(_host);
const targetContents = isTextarea
? _target
: contents([_content, _viewport, _padding, _host, _target].find((elm) => elementIsGenerated(elm) === false));
const contentSlot = _content || _viewport;
// only insert host for textarea after target if it was generated
if (isTextareaHostGenerated) {
@@ -116,88 +177,48 @@ export const createStructureSetup = (target: OSTarget | OSTargetObject): Structu
});
}
if (targetIsElm) {
const contentSlot = _content || _viewport;
appendChildren(contentSlot, getTargetContents(_target!));
appendChildren(_host, _padding);
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);
});
}
appendChildren(contentSlot, targetContents);
appendChildren(_host, _padding);
appendChildren(_padding || _host, _viewport);
appendChildren(_viewport, _content);
addClass(_host, classNameHost);
addClass(_padding, classNamePadding);
addClass(_viewport, classNameViewport);
addClass(_content, classNameContent);
const ownerDocument: HTMLDocument = _target!.ownerDocument;
const bodyElm = ownerDocument.body as HTMLBodyElement;
const wnd = ownerDocument.defaultView as Window;
const ctx: OSTargetContext = {
_windowElm: wnd,
_documentElm: ownerDocument,
_htmlElm: parent(bodyElm) as HTMLHtmlElement,
_bodyElm: bodyElm,
_isTextarea: isTextarea,
_isBody: isBody,
};
// @ts-ignore
const obj: PreparedOSTargetObject = {
...osTargetObj,
_host,
};
push(destroyFns, () => {
if (targetIsElm) {
appendChildren(_host, contents(contentSlot));
removeElements(_padding || _viewport);
removeClass(_host, classNameHost);
} else {
if (elementIsGenerated(_content)) {
unwrap(_content);
}
if (elementIsGenerated(_viewport)) {
unwrap(_viewport);
}
if (elementIsGenerated(_padding)) {
unwrap(_padding);
}
removeClass(_host, classNameHost);
removeClass(_padding, classNamePadding);
removeClass(_viewport, classNameViewport);
removeClass(_content, classNameContent);
}
});
if (_nativeScrollbarStyling) {
push(destroyFns, removeClass.bind(0, _viewport, classNameViewportScrollbarStyling));
} else if (!_cssCustomProperties && (_nativeScrollbarIsOverlaid.x || _nativeScrollbarIsOverlaid.y)) {
const viewportArrangeElm = createUniqueViewportArrangeElement();
insertBefore(_viewport, viewportArrangeElm);
push(destroyFns, removeElements.bind(0, viewportArrangeElm));
obj._viewportArrange = viewportArrangeElm;
}
if (_viewportArrange) {
insertBefore(_viewport, _viewportArrange);
push(destroyFns, removeElements.bind(0, _viewportArrange));
}
return {
_targetObj: obj,
_targetObj: evaluatedTargetObj,
_targetCtx: ctx,
_destroy: () => {
runEach(destroyFns);
@@ -1,5 +1,6 @@
@import './sizeobserver.scss';
@import './trinsicobserver.scss';
@import './scrollbars.scss';
.os-environment {
--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';
}
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';
}
+34 -9
View File
@@ -1,3 +1,5 @@
export type PlainObject<T = any> = { [name: string]: T };
export type StyleObject<CustomCssProps = ''> = {
@@ -10,6 +12,19 @@ export type InternalVersionOf<T> = {
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.
*
@@ -18,19 +33,29 @@ 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.
*
* 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.
* Undefined means that the environment initialization strategy for the respective element is used.
*/
export interface OSTargetObject {
export interface StructureInitialization {
target: OSTargetElement;
host?: HTMLElement;
padding?: HTMLElement | boolean;
viewport?: HTMLElement;
content?: HTMLElement | boolean;
host?: StructureInitializationStaticElement; // only relevant for textarea
viewport?: StructureInitializationStaticElement;
padding?: StructureInitializationDynamicElement;
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 {
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"
integrity sha512-BLbiRkiBzAwsjut4x/dsibSTB6yWpwT5qWmC2OfuCg3GgVQCSgMs4vEctYPhsaGtd0AeuuHMkjZ2h2WG8MSzRw==
typescript@^4.2.4:
version "4.2.4"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.2.4.tgz#8610b59747de028fda898a8aef0e103f156d0961"
integrity sha512-V+evlYHZnQkaz8TRBuxTA92yZBPotr5H+WhQ7bD3hZUndx5tGOa1fuCgeSjxAzM1RiN5IzvadIXTVefuuwZCRg==
typescript@^4.3.2:
version "4.3.2"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.3.2.tgz#399ab18aac45802d6f2498de5054fcbbe716a805"
integrity sha512-zZ4hShnmnoVnAHpVHWpTcxdv7dWP60S2FsydQLV8V5PbS3FifjWFFRiHSWpDJahly88PRyV5teTSLoq4eG7mKw==
unicode-canonical-property-names-ecmascript@^1.0.4:
version "1.0.4"