UNPKG

hybrids

Version:

A JavaScript framework for creating fully-featured web applications, components libraries, and single web components with unique declarative and functional architecture

465 lines (387 loc) 13.2 kB
export type Property<E, V> = | (V extends string | number | boolean | null | undefined ? V : never) | ((host: E & HTMLElement, value?: any) => V) | Descriptor<E, V>; export interface Descriptor<E, V> { value: V | ((host: E & HTMLElement, value?: any) => V); connect?( host: E & HTMLElement & { __property_key__: V }, key: "__property_key__", invalidate: () => void, ): Function | void; observe?(host: E & HTMLElement, value: V, lastValue: V): void; reflect?: boolean | ((value: V) => string); } export interface UpdateFunction<E> { (host: E & HTMLElement, target?: ShadowRoot | Text | E): void; } export interface RenderFunction<E> { (host: E & HTMLElement): UpdateFunction<E>; } export interface RenderDescriptor<E> extends Descriptor<E, RenderFunction<E>> { value: RenderFunction<E>; reflect?: never; shadow?: boolean | ShadowRootInit; } export type ComponentBase = { tag: string; __router__connect__?: ViewOptions; }; export type Component<E> = ComponentBase & { [property in Extract< keyof Omit<E, keyof HTMLElement>, string >]: property extends "render" ? RenderFunction<E> | RenderDescriptor<E> : Property<E, E[property]>; } & { render?: RenderFunction<E> | RenderDescriptor<E>; }; export interface HybridElement<E> { new (): E & HTMLElement; prototype: E & HTMLElement; } /* Define */ export function define<E>(component: Component<E>): typeof component; export namespace define { function compile<E>(component: Component<E>): HybridElement<E>; function from( components: { [path: string]: Component<any> }, options?: { prefix?: string; root?: string | string[] }, ): void; } /* Mount */ export function mount<E>( target: HTMLElement, component: Component<E>, ): () => void; /* Factories */ export function parent<E, V>( componentOrFn: Component<V> | ((component: Component<E>) => boolean), ): Descriptor<E, V>; export function children<E, V>( componentOrFn: Component<V> | ((component: Component<E>) => boolean), options?: { deep?: boolean; nested?: boolean }, ): Descriptor<E, V[]>; /* Store */ export type ModelInstance = { id?: ModelIdentifier } & object & NonArrayObject & NonModelDefinition; export type EnumerableInstance = { id: ModelIdentifier } & ModelInstance; export type SingletonInstance = { id?: never } & ModelInstance; export type Unarray<T> = T extends Array<infer U> ? U : T; export type NonConstructor = { readonly prototype?: never }; export type NonArrayObject = { [Symbol.iterator]?: never } & object; export type NonModelDefinition = { __store__connect__?: never } & object; export type Model<M extends ModelInstance> = NonArrayObject & { [property in keyof Omit<M, "id">]-?: NonNullable< M[property] > extends Array<any> ? | NestedArrayModel<NonNullable<M[property]>> | (NonConstructor & (( model: M, ) => undefined extends M[property] ? undefined | NestedArrayModel<M[property]> : NestedArrayModel<M[property]>)) : NonNullable<M[property]> extends string | String ? string | (NonConstructor & ((model: M) => M[property])) : NonNullable<M[property]> extends number | Number ? number | (NonConstructor & ((model: M) => M[property])) : NonNullable<M[property]> extends boolean | Boolean ? boolean | (NonConstructor & ((model: M) => M[property])) : NonNullable<M[property]> extends ModelInstance ? | Model<NonNullable<M[property]>> | (NonConstructor & (( model: M, ) => undefined extends M[property] ? undefined | Model<NonNullable<M[property]>> : Model<NonNullable<M[property]>>)) : NonNullable<M[property]> extends NonArrayObject ? | NonNullable<M[property]> | (NonConstructor & ((model: M) => M[property])) : never; } & (M extends EnumerableInstance ? { id: true; } : {}) & { __store__connect__?: Storage<M> | Storage<M>["get"]; }; export type NestedArrayModel<T> = NonNullable<Unarray<T>> extends string | String ? T | string[] | [String | StringConstructor] : NonNullable<Unarray<T>> extends number | Number ? T | number[] | [Number | NumberConstructor] : NonNullable<Unarray<T>> extends boolean | Boolean ? T | boolean[] | [Boolean | BooleanConstructor] : NonNullable<Unarray<T>> extends EnumerableInstance ? | [Model<NonNullable<Unarray<T>>>] | [Model<NonNullable<Unarray<T>>>, { loose?: boolean }] : NonNullable<Unarray<T>> extends NonArrayObject ? T : never; export type ModelIdentifier = | string | Record<string, string | boolean | number | null> | undefined; export type ModelValues<M extends ModelInstance> = { [property in keyof M]?: NonNullable<M[property]> extends Array<any> ? Array<ModelValues<Unarray<NonNullable<M[property]>>>> : NonNullable<M[property]> extends ModelInstance ? ModelValues<NonNullable<M[property]>> : M[property]; }; export type StorageValues<M extends ModelInstance> = { [property in keyof M]?: NonNullable<M[property]> extends EnumerableInstance ? NonNullable<M[property]> | M["id"] : NonNullable<M[property]> extends EnumerableInstance[] ? (NonNullable<Unarray<M[property]>> | M["id"])[] : M[property]; }; export type StorageResult<M extends ModelInstance> = | StorageValues<M> | null | undefined; export type Storage<M extends ModelInstance> = { get?: (id: ModelIdentifier) => StorageResult<M> | Promise<StorageResult<M>>; set?: ( id: ModelIdentifier, values: M | null, keys: [keyof M], ) => StorageResult<M> | Promise<StorageResult<M>>; list?: ( id: ModelIdentifier, ) => Array<StorageResult<M>> | Promise<Array<StorageResult<M>>>; observe?: (id: ModelIdentifier, model: M | null, lastModel: M | null) => void; cache?: boolean | number; offline?: boolean | number; loose?: boolean; }; // Enumerable - This overload must be the first one, then its signature and documentation will be displayed in intelephence by default. export function store<E, M extends EnumerableInstance>( model: Model<M>, options?: { draft?: false; id?: keyof E | ((host: E) => ModelIdentifier) }, ): Descriptor<E, M | undefined>; // Enumerable Draft export function store<E, M extends EnumerableInstance>( model: Model<M>, options: { draft: true; id?: keyof E | ((host: E) => ModelIdentifier) }, ): Descriptor<E, M>; // Enumerable Listing export function store<E, M extends EnumerableInstance>( model: [Model<M>], options?: { draft?: false; id?: keyof E | ((host: E) => ModelIdentifier); loose?: boolean; }, ): Descriptor<E, M[]>; // Singleton export function store<E, M extends SingletonInstance>( model: M extends Array<any> ? never : Model<M>, options?: { draft?: false; id?: keyof E | ((host: E) => ModelIdentifier) }, ): Descriptor<E, M>; // Singleton Draft export function store<E, M extends SingletonInstance>( model: M extends Array<any> ? never : Model<M>, options: { draft: true; id?: keyof E | ((host: E) => ModelIdentifier) }, ): Descriptor<E, M>; export namespace store { const connect = "__store__connect__"; function get<M extends ModelInstance>( Model: Model<M>, id?: ModelIdentifier, ): M; function get<M extends ModelInstance>( Model: [Model<M>], id?: ModelIdentifier, ): M[]; function set<M extends ModelInstance>( model: Model<M> | M, values: ModelValues<M> | null, ): Promise<M>; function sync<M extends ModelInstance>( model: Model<M> | M, values: ModelValues<M> | null, ): M; function clear<M extends ModelInstance>( model: Model<M> | [Model<M>] | M, clearValue?: boolean, ): void; function pending<M extends ModelInstance>(model: M): false | Promise<M>; function pending<M extends ModelInstance>( ...models: Array<M> ): false | Promise<typeof models>; function error<M extends ModelInstance>( model: M, propertyName?: keyof M | null, ): false | Error | any; function ready<M extends ModelInstance>(model: M): boolean; function ready<M extends ModelInstance>(...models: Array<M>): boolean; function submit<M extends ModelInstance>( draft: M, values?: ModelValues<M>, ): Promise<M>; function resolve<M extends ModelInstance>(model: M): Promise<M>; function resolve<M extends ModelInstance>( model: Model<M>, id?: ModelIdentifier, ): Promise<M>; function resolve<M extends ModelInstance>( model: [Model<M>], id?: ModelIdentifier, ): Promise<M[]>; function ref<T>(fn: () => T): () => T; function record<V>(value: V): Record<string, V>; function record<V extends () => {}>(value: V): Record<string, ReturnType<V>>; interface ValidateFunction<M extends ModelInstance, T> { (value: T, key: string, model: M): string | boolean | void; } function value<M extends ModelInstance>( defaultValue: string, validate?: ValidateFunction<M, string> | RegExp, errorMessage?: string, ): string; function value<M extends ModelInstance>( defaultValue: number, validate?: ValidateFunction<M, number> | RegExp, errorMessage?: string, ): number; function value<M extends ModelInstance>( defaultValue: boolean, validate?: ValidateFunction<M, number> | RegExp, errorMessage?: string, ): boolean; function observe<M extends ModelInstance>( model: Model<M>, callback: ( id: ModelIdentifier, model: M | null, lastModel: M | null, ) => void, ): () => void; } /* Router */ export interface ViewOptions { url?: string; multiple?: boolean; dialog?: boolean; replace?: boolean; stack?: ComponentBase[] | (() => ComponentBase[]); guard?: () => boolean; } export function router<E>( views: | ComponentBase | ComponentBase[] | (() => ComponentBase | ComponentBase[]), options?: { url?: string; params?: Array<keyof E>; transition?: boolean; }, ): Descriptor<E, HTMLElement[]>; export namespace router { const connect = "__router__connect__"; function debug(value?: boolean): void; type UrlParams<E> = { [property in keyof E]?: E[property]; }; type UrlOptions = { scrollToTop?: boolean; }; function url<E>( view: ComponentBase, params?: UrlParams<E> & UrlOptions, ): URL | ""; function backUrl(options?: { nested?: boolean } & UrlOptions): URL | ""; function guardUrl(params?: UrlParams<any> & UrlOptions): URL | ""; function currentUrl<E>(params?: UrlParams<E> & UrlOptions): URL | ""; function active( views: ComponentBase | ComponentBase[], options?: { stack?: boolean }, ): boolean; function resolve<P>(event: Event, promise: Promise<P>): Promise<P>; } /* Localize */ export type Messages = { [key: string]: { message: | string | { zero?: string; one?: string; two?: string; few?: string; many?: string; other?: string; }; description?: string; }; }; export function localize(lang: string, messages: Messages): void; export function localize( translate: ( key: string, context: string, ) => string | ((num: number) => string), options?: { format?: "chrome.i18n"; }, ): void; export namespace localize { const languages: string[]; } export function msg(parts: TemplateStringsArray, ...args: unknown[]): string; export namespace msg { function html<E>( parts: TemplateStringsArray, ...args: unknown[] ): UpdateFunctionWithMethods<E>; function svg<E>( parts: TemplateStringsArray, ...args: unknown[] ): UpdateFunctionWithMethods<E>; } /* Utils */ export function dispatch( host: EventTarget, eventType: string, options?: CustomEventInit, ): boolean; export function debug(): void; /* Template Engine */ export interface UpdateFunctionWithMethods<E> extends UpdateFunction<E> { key: (id: any) => this; style: (...styles: Array<string | CSSStyleSheet>) => this; css: (parts: TemplateStringsArray, ...args: unknown[]) => this; use: (fn: (template: UpdateFunction<E>) => UpdateFunction<E>) => this; } export interface EventHandler<E> { (host: E & HTMLElement, event?: Event): any; } export function html<E>( parts: TemplateStringsArray, ...args: unknown[] ): UpdateFunctionWithMethods<E>; export namespace html { function set<E>(property: keyof E, valueOrPath?: any): EventHandler<E>; function set<E, M>(property: M, valueOrPath: string | null): EventHandler<E>; function resolve<E>( promise: Promise<any>, placeholder?: UpdateFunction<E>, delay?: number, ): UpdateFunction<E>; function transition<E>(template: UpdateFunction<E>): UpdateFunction<E>; function msg(parts: TemplateStringsArray, ...args: unknown[]): string; } export function svg<E>( parts: TemplateStringsArray, ...args: unknown[] ): UpdateFunctionWithMethods<E>;