import type { JSX, ComponentType, ComponentPropsWithoutRef, HTMLAttributes, Context, } from 'react'; export type PlainObject = Record; export type EmptyObject = Record; export type MergeObjects = T extends EmptyObject ? U extends EmptyObject ? EmptyObject : U : U extends EmptyObject ? T : T & U; export type PropsFor> = T extends string ? T extends keyof JSX.IntrinsicElements ? JSX.IntrinsicElements[T] : T extends ComponentType ? ComponentPropsWithoutRef : HTMLAttributes : T extends ComponentType ? ComponentPropsWithoutRef : never; export type FunctionKeys = { [K in keyof T]-?: NonNullable extends (...args: any[]) => any ? K : never; }[keyof T]; export type DeepPartial = T extends (infer U)[] ? DeepPartial[] : T extends readonly (infer U)[] ? readonly DeepPartial[] : T extends PlainObject ? { [K in keyof T]?: DeepPartial; } : T; export type Predicate = ( node: Node, ) => boolean; type MaybeFunctionReturnType = T extends (...args: any[]) => any ? ReturnType : unknown; type MaybeFunctionParameters = T extends (...args: any[]) => any ? Parameters : []; export interface RootApi< Props, Context extends PlainObject = EmptyObject, Actions extends PlainObject = EmptyObject, > extends Disposable { readonly context: Context; readonly actions: Actions; readonly signal: AbortSignal; mount(): void; unmount(): void; setProps(props: Partial): void; act(action: () => T, options?: {update?: boolean}): T; // Not until we need it... // forceUpdate(): void; } export interface NodeApi { readonly props: Props; readonly type: string | ComponentType | null; readonly instance: any; readonly children: (Node | string)[]; readonly descendants: (Node | string)[]; readonly text: string; prop(key: K): Props[K]; is | string>( type: Type, ): this is Node, Extensions>; find | string>( type: Type, props?: Partial>, ): Node, Extensions> | null; findAll | string>( type: Type, props?: Partial>, ): Node, Extensions>[]; findWhere | string = ComponentType>( predicate: Predicate, ): Node, Extensions> | null; findAllWhere< Type extends ComponentType | string = ComponentType, >( predicate: Predicate, ): Node, Extensions>[]; findContext(context: Context): Type | undefined; trigger>( prop: K, ...args: DeepPartial> ): MaybeFunctionReturnType>; triggerKeypath(keypath: string, ...args: unknown[]): T; debug(options?: DebugOptions): string; toString(): string; } export type Node< Props, Extensions extends PlainObject = EmptyObject, > = EmptyObject extends Extensions ? NodeApi : NodeApi & Omit>; export type Root< Props, Context extends PlainObject = EmptyObject, Actions extends PlainObject = EmptyObject, Extensions extends PlainObject = EmptyObject, > = Node & RootApi; export interface DebugOptions { all?: boolean; depth?: number; verbosity?: number; } export interface HTMLNodeExtensions { readonly isDOM: boolean; readonly domNodes: HTMLElement[]; readonly domNode: HTMLElement | null; readonly html: string; readonly text: string; data(key: string): string | undefined; }