web-utility
Version:
Web front-end toolkit based on TypeScript
368 lines (366 loc) • 20.2 kB
TypeScript
export function sum(...data: number[]): number;
export function averageOf(...data: number[]): number;
export function varianceOf(data: number[], sample?: boolean): number;
export function standardDeviationOf(data: number[], sample?: boolean): number;
export function hypotenuseOf(...data: number[]): number;
export function carryFloat(raw: number, length: number): string;
export function fixFloat(raw: number, length?: number): string;
export abstract class Scalar {
value: number;
abstract units: {
base: number;
name: string;
}[];
constructor(value: number);
valueOf(): number;
toShortString(fractionDigits?: number): string;
static distanceOf<T extends Scalar>(a: number, b: number): T;
}
export type Constructor<T> = new (...args: any[]) => T;
export type AbstractClass<T> = abstract new (...args: any[]) => T;
export type Values<T> = Required<T>[keyof T];
export type TypeKeys<T, D> = {
[K in keyof T]: Required<T>[K] extends D ? K : never;
}[keyof T];
export type PickSingle<T> = T extends infer S | (infer S)[] ? S : T;
export type PickData<T> = Omit<T, TypeKeys<T, Function>>;
export type DataKeys<T> = Exclude<keyof T, TypeKeys<T, Function>>;
export function likeNull(value?: any): boolean;
export function isEmpty(value?: any): boolean;
/**
* @see {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/toStringTag}
*/
export const classNameOf: (data: any) => string;
export function assertInheritance(Sub: Function, Super: Function): boolean;
export function proxyPrototype<T extends object>(target: T, dataStore: Record<IndexKey, any>, setter?: (key: IndexKey, value: any) => any): void;
export function isUnsafeNumeric(raw: string): boolean;
export function byteLength(raw: string): number;
export type HyphenCase<T extends string> = T extends `${infer L}${infer R}` ? `${L extends Uppercase<L> ? `-${Lowercase<L>}` : L}${HyphenCase<R>}` : T;
export function toHyphenCase(raw: string): string;
export type CamelCase<Raw extends string, Delimiter extends string = '-'> = Uncapitalize<Raw extends `${infer L}${Delimiter}${infer R}` ? `${Capitalize<L>}${Capitalize<CamelCase<R>>}` : `${Capitalize<Raw>}`>;
export function toCamelCase(raw: string, large?: boolean): string;
export function uniqueID(): string;
export function objectFrom<V, K extends string>(values: V[], keys: K[]): Record<K, V>;
export enum DiffStatus {
Old = -1,
Same = 0,
New = 1
}
export function diffKeys<T extends IndexKey>(oldList: T[], newList: T[]): {
map: Record<T, DiffStatus>;
group: Record<GroupKey<[string, DiffStatus]>, [string, DiffStatus][]>;
};
export type ResultArray<T> = T extends ArrayLike<infer D> ? D[] : T[];
export function likeArray(data?: any): data is ArrayLike<any>;
export type TypedArray = Int8Array | Uint8Array | Uint8ClampedArray | Int16Array | Uint16Array | Int32Array | Uint32Array | Float32Array | Float64Array | BigInt64Array | BigUint64Array;
/**
* @see {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray}
*/
export const isTypedArray: (data: any) => data is TypedArray;
export function makeArray<T>(data?: T): ResultArray<T>;
export const splitArray: <T>(array: T[], unitLength: number) => T[][];
export type IndexKey = number | string | symbol;
export type GroupKey<T extends Record<IndexKey, any>> = keyof T | IndexKey;
export type Iteratee<T extends Record<IndexKey, any>> = keyof T | ((item: T) => GroupKey<T> | GroupKey<T>[]);
export function groupBy<T extends Record<IndexKey, any>>(list: T[], iteratee: Iteratee<T>): Record<GroupKey<T>, T[]>;
export function countBy<T extends Record<IndexKey, any>>(list: T[], iteratee: Iteratee<T>): {
[k: string]: number;
};
export function findDeep<T>(list: T[], subKey: TypeKeys<Required<T>, any[]>, handler: (item: T) => boolean): T[];
export type TreeNode<IK extends string, PK extends string, CK extends string> = {
[key in IK]: number | string;
} & {
[key in PK]?: number | string;
} & {
[key in CK]?: TreeNode<IK, PK, CK>[];
};
export function treeFrom<IK extends string, PK extends string, CK extends string, N extends TreeNode<IK, PK, CK>>(list: N[], idKey?: IK, parentIdKey?: PK, childrenKey?: CK): N[];
export function cache<I, O>(executor: (cleaner: () => void, ...data: I[]) => O, title: string): (...data: I[]) => O;
export interface IteratorController<V = any, E = Error> {
next: (value: V) => any;
error: (error: E) => any;
complete: () => any;
}
export function createAsyncIterator<V, E = Error>(executor: (controller: IteratorController<V, E>) => (() => any) | void): AsyncGenerator<Awaited<V>, void, unknown>;
export function mergeStream<T, R = void, N = T>(...sources: (() => AsyncIterator<T, R, N>)[]): AsyncGenerator<any, void, unknown>;
export class ByteSize extends Scalar {
units: {
base: number;
name: string;
}[];
}
export const Second = 1000;
export const Minute: number;
export const Quarter: number;
export const Hour: number;
export const Day: number;
export const Week: number;
export const Year: number;
export const Month: number;
export const Season: number;
export class Timestamp extends Scalar {
units: {
base: number;
name: string;
}[];
toShortString(fractionDigits?: number): string;
}
export type TimeData = number | string | Date;
/**
* @deprecated since v4.4, use {@link Timestamp.distanceOf} instead.
*/
export function diffTime(end: TimeData, start?: TimeData): {
distance: number;
unit: string;
};
export function formatDate(time?: TimeData, template?: string): string;
export function changeMonth(date: TimeData, delta: number): Date;
export function parseJSON(raw: string): any;
export function toJSValue(raw: string): any;
export function parseTextTable<T = {}>(raw: string, header?: boolean, separator?: string): any[][] | T[];
export function isXDomain(URI: string): boolean;
export type JSONValue = number | boolean | string | null;
export interface URLData<E = unknown> {
[key: string]: JSONValue | JSONValue[] | URLData | URLData[] | E;
}
export function parseURLData(raw?: string, toBuiltIn?: boolean): URLData;
export function buildURLData(map: string[][] | Record<string, any>): URLSearchParams;
export function blobOf(URI: string | URL): Promise<Blob>;
/**
* Blob logic forked from axes's
*
* @see http://www.cnblogs.com/axes/p/4603984.html
*/
export function blobFrom(URI: string): Blob;
export const parseCookie: <T extends Record<string, string>>(value?: string) => T;
export interface CookieAttribute {
domain?: string;
path?: string;
expires?: Date;
'max-age'?: number;
samesite?: 'lax' | 'strict' | 'none';
secure?: boolean;
partitioned?: boolean;
}
export function setCookie(key: string, value: string, attributes?: CookieAttribute): string;
/**
* CRC-32 algorithm forked from Bakasen's
*
* @see http://blog.csdn.net/bakasen/article/details/6043797
*/
export function makeCRC32(raw: string): string;
export type SHAAlgorithm = 'SHA-1' | 'SHA-256' | 'SHA-384' | 'SHA-512';
/**
* @see https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/digest#Converting_a_digest_to_a_hex_string
*/
export function makeSHA(raw: string, algorithm?: SHAAlgorithm): Promise<string>;
export type SelfCloseTags = 'area' | 'base' | 'br' | 'col' | 'embed' | 'hr' | 'img' | 'input' | 'link' | 'meta' | 'param' | 'source' | 'track' | 'wbr';
export type ShadowableTags = 'article' | 'aside' | 'blockquote' | 'body' | 'div' | 'footer' | 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' | 'header' | 'main' | 'nav' | 'p' | 'section' | 'span' | `${string}-${string}`;
export type EventTypes = {
[K in keyof typeof globalThis]: K extends `${infer N}Event` ? N extends '' ? never : N : never;
}[keyof typeof globalThis];
export type UniqueEventNames = {
[K in keyof HTMLElementEventMap]: K extends `${Lowercase<EventTypes>}${string}` ? never : K extends `${string}${Lowercase<EventTypes>}` ? never : K;
}[keyof HTMLElementEventMap];
export type ComplexUniqueEventNames = {
[K in UniqueEventNames]: K extends `${infer L}${UniqueEventNames}` ? L extends '' ? never : K : never;
}[UniqueEventNames];
export type SimpleEventNames = Exclude<UniqueEventNames, ComplexUniqueEventNames>;
export type EventHandlerNames<T extends Element> = {
[K in keyof T]: K extends `on${infer N}` ? T[K] extends (event: Event) => any ? N : never : never;
}[keyof T];
export type CamelEventName<T extends string> = T extends SimpleEventNames ? Capitalize<T> : T extends `${infer L}${SimpleEventNames}` ? T extends `${L}${infer R}` ? `${Capitalize<L>}${Capitalize<R>}` : T : T extends `${Lowercase<EventTypes>}${infer R}` ? T extends `${infer L}${R}` ? `${Capitalize<L>}${Capitalize<R>}` : T : T extends `${infer L}${Lowercase<EventTypes>}` ? T extends `${L}${infer R}` ? `${Capitalize<L>}${Capitalize<R>}` : T : T;
export type EventHandlers<T extends Element, M extends HTMLElementEventMap = HTMLElementEventMap> = {
[K in EventHandlerNames<T> as `on${CamelEventName<K>}`]: (event: M[K]) => any;
};
export type ContainerEvents = 'focusin' | 'focusout';
export type ContainerEventHandlers<T extends keyof HTMLElementTagNameMap> = T extends SelfCloseTags ? {} : {
[K in ContainerEvents as `on${CamelEventName<K>}`]: (event: HTMLElementEventMap[K]) => any;
};
export type XMLOwnKeys<T extends HTMLElement | SVGElement | MathMLElement = HTMLElement> = Exclude<keyof T, keyof Node | keyof EventTarget>;
/**
* @deprecated since v4.4.2, use {@link XMLOwnKeys} instead
*/
export type HTMLOwnKeys<T extends HTMLElement = HTMLElement> = XMLOwnKeys<T>;
/**
* @deprecated since v4.4.2, use {@link XMLOwnKeys} instead
*/
export type SVGOwnKeys<T extends SVGElement = SVGElement> = XMLOwnKeys<T>;
export type CSSStyles = Partial<Omit<PickData<CSSStyleDeclaration>, 'length' | 'parentRule'> & Record<string, any>>;
export type CSSRule = Record<string, CSSStyles>;
export type CSSObject = CSSRule | Record<string, CSSRule>;
export type DOMProps_Read2Write<T extends Partial<Element>> = {
[K in keyof T]: T[K] extends HTMLElement ? string : T[K] extends DOMTokenList ? string : T[K] extends Element ? string : T[K] extends CSSStyleDeclaration ? CSSStyles : T[K];
};
export type HTMLProps<T extends HTMLElement> = Partial<ARIAMixin & EventHandlers<T> & DOMProps_Read2Write<Pick<T, Extract<DataKeys<T>, XMLOwnKeys<T>>>>>;
export type SVGProps_Read2Write<T extends Partial<SVGElement>> = {
[K in keyof T]: T[K] extends SVGAnimatedString | SVGAnimatedBoolean | SVGAnimatedEnumeration | SVGAnimatedNumber | SVGAnimatedNumberList | SVGAnimatedInteger | SVGAnimatedLength | SVGAnimatedLengthList | SVGAnimatedPoints | SVGAnimatedAngle | SVGAnimatedRect | SVGAnimatedPreserveAspectRatio | SVGAnimatedTransformList ? string : T[K];
};
export type SVGProps<T extends SVGElement> = Partial<EventHandlers<T, SVGElementEventMap> & SVGProps_Read2Write<DOMProps_Read2Write<Pick<T, Extract<DataKeys<T>, XMLOwnKeys<T>>>>>>;
export type MathMLProps<T extends MathMLElement> = Partial<EventHandlers<T, MathMLElementEventMap> & DOMProps_Read2Write<Pick<T, Extract<DataKeys<T>, XMLOwnKeys<T>>>>>;
export interface HTMLHyperLinkProps extends HTMLProps<HTMLAnchorElement & HTMLAreaElement> {
href?: string;
target?: '_self' | '_parent' | '_top' | '_blank';
}
export type HTMLTableCellProps = HTMLProps<HTMLTableCellElement>;
export type BaseFieldProps = Partial<Pick<HTMLInputElement, 'name' | 'defaultValue' | 'value' | 'required' | 'disabled'>>;
export interface BaseInputProps extends Partial<Pick<HTMLInputElement, 'readOnly' | 'placeholder'>> {
list?: string;
}
export type TextFieldProps = BaseInputProps & Partial<Pick<HTMLInputElement, 'size' | 'minLength' | 'maxLength' | 'pattern' | 'autocomplete' | 'spellcheck'>>;
export type NumberFieldProps = BaseInputProps & Partial<Pick<HTMLInputElement, 'min' | 'max' | 'step'>>;
export type HTMLFieldInternals = Pick<HTMLInputElement, 'form' | 'validity' | 'validationMessage' | 'willValidate' | 'checkValidity' | 'reportValidity'>;
export type HTMLFieldProps<T extends HTMLElement = HTMLInputElement> = HTMLProps<T> & BaseFieldProps;
export interface HTMLButtonProps extends HTMLFieldProps<HTMLButtonElement> {
}
export interface HTMLInputProps extends HTMLFieldProps, Omit<BaseInputProps, 'list'> {
type?: 'checkbox' | 'color' | 'date' | 'datetime-local' | 'email' | 'file' | 'hidden' | 'month' | 'number' | 'password' | 'radio' | 'range' | 'search' | 'tel' | 'text' | 'time' | 'url' | 'week' | HTMLButtonProps['type'];
}
export type HTMLField = HTMLInputElement & HTMLTextAreaElement & HTMLSelectElement & HTMLFieldSetElement;
/**
* @see https://developers.google.com/web/fundamentals/web-components/customelements#reactions
*/
export interface CustomElement extends HTMLElement {
/**
* Called every time the element is inserted into the DOM
*/
connectedCallback?(): void;
/**
* Called every time the element is removed from the DOM.
*/
disconnectedCallback?(): void;
/**
* Called when an observed attribute has been added, removed, updated, or replaced.
* Also called for initial values when an element is created by the parser, or upgraded.
*
* Note: only attributes listed in static `observedAttributes` property will receive this callback.
*/
attributeChangedCallback?(name: string, oldValue: string, newValue: string): void;
/**
* The custom element has been moved into a new document
* (e.g. someone called `document.adoptNode(el)`).
*/
adoptedCallback?(): void;
}
/**
* @see https://developers.google.com/web/fundamentals/web-components/customelements#attrchanges
*/
export interface CustomElementClass<T extends CustomElement = CustomElement> {
new (...data: any[]): T;
observedAttributes?: string[];
}
/**
* @see https://web.dev/more-capable-form-controls/#lifecycle-callbacks
*/
export interface CustomFormElement extends CustomElement, BaseFieldProps, HTMLFieldInternals {
/**
* Called when the browser associates the element with a form element,
* or disassociates the element from a form element.
*/
formAssociatedCallback?(form: HTMLFormElement): void;
/**
* Called after the disabled state of the element changes,
* either because the disabled attribute of this element was added or removed;
* or because the disabled state changed on a `<fieldset>` that's an ancestor of this element.
*
* @param disabled This parameter represents the new disabled state of the element.
*/
formDisabledCallback?(disabled: boolean): void;
/**
* Called after the form is reset.
* The element should reset itself to some kind of default state.
*/
formResetCallback?(): void;
/**
* Called in one of two circumstances:
* - When the browser restores the state of the element (for example, after a navigation, or when the browser restarts). The `mode` argument is `"restore"` in this case.
* - When the browser's input-assist features such as form autofilling sets a value. The `mode` argument is `"autocomplete"` in this case.
*
* @param state The type of this argument depends on how the `this.internals.setFormValue()` method was called.
* @param mode
*/
formStateRestoreCallback?(state: string | File | FormData, mode: 'restore' | 'autocomplete'): void;
}
/**
* @see https://web.dev/more-capable-form-controls/#defining-a-form-associated-custom-element
*/
export interface CustomFormElementClass extends CustomElementClass<CustomFormElement> {
formAssociated?: boolean;
}
export const XMLNamespace: {
html: string;
svg: string;
math: string;
};
export function templateOf(tagName: string): Element;
export function elementTypeOf(tagName: string): "html" | "xml";
export function isHTMLElementClass<T extends Constructor<HTMLElement>>(Class: any): Class is T;
export function tagNameOf(Class: CustomElementConstructor): string;
export function isDOMReadOnly<T extends keyof HTMLElementTagNameMap>(tagName: T, propertyName: keyof HTMLProps<HTMLElementTagNameMap[T]>): boolean;
export function parseDOM(HTML: string): ChildNode[];
export function stringifyDOM(node: Node): string;
export function walkDOM<T extends Node = Node>(root: Node, type?: Node['nodeType']): Generator<T>;
export function getVisibleText(root: Element): string;
/**
* Split a DOM tree into Pages like PDF files
*
* @param pageHeight the default value is A4 paper's height
* @param pageWidth the default value is A4 paper's width
*/
export function splitPages({ offsetWidth, children }: HTMLElement, pageHeight?: number, pageWidth?: number): Element[][];
export interface CSSOptions extends Pick<HTMLLinkElement, 'title' | 'media' | 'crossOrigin' | 'integrity'> {
alternate?: boolean;
}
export function importCSS(URI: string, { alternate, ...options }?: CSSOptions): Promise<CSSStyleSheet>;
export function stringifyCSS(data: CSSStyles | CSSObject, depth?: number, indent?: string): string;
export function insertToCursor(...nodes: Node[]): void;
export function scrollTo(selector: string, root?: Element, align?: ScrollLogicalPosition, justify?: ScrollLogicalPosition): void;
export interface ScrollEvent {
target: HTMLHeadingElement;
links: (HTMLAnchorElement | HTMLAreaElement)[];
}
export function watchScroll(box: HTMLElement, handler: (event: ScrollEvent) => any, depth?: number): {
level: number;
id: string;
text: string;
}[];
export function watchVisible(root: Element, handler: (visible: boolean) => any): void;
export function formToJSON<T extends object = URLData<File>>(form: HTMLFormElement | HTMLFieldSetElement): T;
export function sleep(seconds?: number): Promise<void>;
export function asyncLoop(executor: (...data: any[]) => any, seconds?: number): () => boolean;
export type DelegateEventHandler<T = any> = (event: Event, currentTarget: Element, detail?: T) => any;
export function delegate<T>(selector: string, handler: DelegateEventHandler<T>): (this: Node, event: Event) => any;
export const documentReady: Promise<void>;
export function promisify<T extends Event>(scope: string, element: Element): Promise<T>;
export type MessageGlobal = Window | Worker;
export function createMessageServer(handlers: Record<string, (data: any) => any | Promise<any>>): () => void;
export function createMessageClient(target: Window | Worker, origin?: string): (type: string, data?: any) => Promise<unknown>;
export function serviceWorkerUpdate(registration: ServiceWorkerRegistration): Promise<ServiceWorker>;
export interface CartesianCoordinate {
x: number;
y: number;
z?: number;
}
export class PageVector {
from: CartesianCoordinate;
to: CartesianCoordinate;
constructor(from: CartesianCoordinate, to: CartesianCoordinate);
get length(): number;
get direction(): "forward" | "backward" | "right" | "left" | "up" | "down";
}
export function getSwipeVector(from: CartesianCoordinate, to: CartesianCoordinate, threshold?: number): PageVector;
export interface AnimationEvents {
transition: TransitionEvent;
animation: AnimationEvent;
}
export type AnimationType = keyof AnimationEvents;
export function durationOf(type: AnimationType, element: HTMLElement): number;
export function watchMotion<T extends AnimationType>(type: T, element: HTMLElement): Promise<void | Awaited<AnimationEvents[T]>>;
export function transitIn(element: HTMLElement, className: string, display?: string): Promise<void | TransitionEvent>;
export function animateIn(element: HTMLElement, className: string, display?: string): Promise<void | AnimationEvent>;
export function transitOut(element: HTMLElement, className: string, remove?: boolean): Promise<void>;
export function animateOut(element: HTMLElement, className: string, remove?: boolean): Promise<void>;
export function describe(title: string, cases: () => any): Promise<void>;
export type Expector = (status: boolean | (() => boolean)) => void;
export function it<T>(title: string, userCase: (expect: Expector) => T | Promise<T>, secondsOut?: number): Promise<T>;
//# sourceMappingURL=index.d.ts.map