@public-ui/components
Version:
Contains all web components that belong to KoliBri - The accessible HTML-Standard.
117 lines (116 loc) • 6.9 kB
TypeScript
import type { EventEmitter } from '../../stencil-public-runtime';
import type { JSXBase } from '../../stencil-public-runtime';
import type { Prop } from '../props';
type Callback<T> = (value?: T) => void;
export type StrictFields<T> = {
[K in keyof T]-?: NonNullable<T[K]>;
};
type UnionToIntersection<U> = (U extends unknown ? (arg: U) => void : never) extends (arg: infer I) => void ? I : never;
export type InternalOf<P> = {
[K in keyof P as K extends `__input_${string}` | '__propInternal__' ? never : K]: P[K];
};
type ExternalOf<P> = {
[K in keyof P as K extends `__input_${string}` | '__propInternal__' ? never : K]: `__input_${K & string}` extends keyof P ? NonNullable<P[`__input_${K & string}`]> : P[K];
};
type PropsDefinition = {
Optional?: Record<string, unknown>;
Required?: Record<string, unknown>;
};
export interface ComponentApi {
Callbacks?: Record<string, () => unknown>;
Emitters?: Record<string, unknown>;
Listeners?: Record<string, unknown>;
Methods?: Record<string, (...args: never[]) => unknown>;
Props?: PropsDefinition;
Refs?: Record<string, HTMLElement>;
States: Record<never, never>;
}
type AnyPropDef = {
readonly __phantomProp__?: Prop<string, unknown, unknown>;
readonly propName: string;
getDefaultValue(): unknown;
};
type ExtractPhantomProp<D> = D extends {
readonly __phantomProp__?: infer P extends Prop<string, unknown, unknown>;
} ? P : never;
type MergePropsFromArray<A extends readonly AnyPropDef[]> = UnionToIntersection<ExtractPhantomProp<A[number]>>;
export type PropsConfigShape = {
optional?: readonly AnyPropDef[];
required?: readonly AnyPropDef[];
};
export type ApiFromConfig<Config extends PropsConfigShape, Extra extends Partial<Omit<ComponentApi, 'Props'>> = Record<never, never>> = {
Props: {
Optional: Config['optional'] extends readonly AnyPropDef[] ? MergePropsFromArray<Config['optional']> : Record<never, never>;
Required: Config['required'] extends readonly AnyPropDef[] ? MergePropsFromArray<Config['required']> : Record<never, never>;
};
States: Extra extends {
States: infer S extends Record<string, unknown>;
} ? S : Record<never, never>;
} & Omit<Extra, 'Props' | 'States'>;
type PropsEntry<T extends ComponentApi, K extends keyof PropsDefinition> = T['Props'] extends PropsDefinition ? T['Props'][K] extends Record<string, unknown> ? T['Props'][K] : Record<never, never> : Record<never, never>;
type RequiredProps<T extends ComponentApi> = PropsEntry<T, 'Required'>;
type OptionalProps<T extends ComponentApi> = PropsEntry<T, 'Optional'>;
type AllProps<T extends ComponentApi> = RequiredProps<T> & OptionalProps<T>;
export type ResolvedProps<T extends ComponentApi> = InternalOf<RequiredProps<T>> & Partial<InternalOf<OptionalProps<T>>>;
export type ResolvedInputProps<T extends ComponentApi> = ExternalOf<RequiredProps<T>> & Partial<ExternalOf<OptionalProps<T>>>;
type ApiField<T extends ComponentApi, K extends keyof ComponentApi> = T[K] extends Record<string, unknown> ? T[K] : Record<never, never>;
type ExtractCallbacks<T extends ComponentApi> = ApiField<T, 'Callbacks'>;
type ExtractEmitters<T extends ComponentApi> = ApiField<T, 'Emitters'>;
type ExtractListeners<T extends ComponentApi> = ApiField<T, 'Listeners'>;
type ExtractMethods<T extends ComponentApi> = ApiField<T, 'Methods'>;
type ExtractRefs<T extends ComponentApi> = ApiField<T, 'Refs'>;
type ExtractStates<T extends ComponentApi> = InternalOf<ApiField<T, 'States'>>;
type InternalProps<T extends ComponentApi> = InternalOf<AllProps<T>>;
type ExternalProps<T extends ComponentApi> = ExternalOf<AllProps<T>>;
export type SetStateFn<Api extends ComponentApi> = <K extends keyof InternalOf<NonNullable<Api['States']>>>(key: K, value: InternalOf<NonNullable<Api['States']>>[K]) => void;
export type GetStateFn<Api extends ComponentApi> = <K extends keyof InternalOf<NonNullable<Api['States']>>>(key: K) => InternalOf<NonNullable<Api['States']>>[K];
export type StateAccess<Api extends ComponentApi> = {
setState: SetStateFn<Api>;
getState: GetStateFn<Api>;
};
type PromiseMethod<Methods> = {
[K in keyof Methods]: Methods[K] extends (...args: infer A) => infer R ? (...args: A) => Promise<Awaited<R>> : Methods[K];
};
type ComponentPropsRequired<Props> = {
[K in keyof Props as `_${Lowercase<string & K>}`]: Props[K];
};
type ComponentPropsOptional<Props> = {
[K in keyof Props as `_${Lowercase<string & K>}`]?: Props[K];
};
type ComponentProps<T extends ComponentApi> = ComponentPropsRequired<ExternalOf<RequiredProps<T>>> & ComponentPropsOptional<ExternalOf<OptionalProps<T>>>;
type ComponentWatchers<Props> = {
[K in keyof Props as `watch${Capitalize<string & K>}`]: Callback<Props[K]>;
};
type ComponentEmitters<Emitters> = {
[K in keyof Emitters as `${Lowercase<string & K>}`]: EventEmitter<Emitters[K]>;
};
type ComponentListeners<Listeners> = {
[K in keyof Listeners as `on${Capitalize<string & K>}`]: (event: Listeners[K]) => void;
};
export type WebComponentInterface<T extends ComponentApi> = {
componentWillLoad(): void;
} & ComponentProps<T> & StrictFields<ExtractStates<T>> & ComponentWatchers<ExternalProps<T>> & ComponentEmitters<ExtractEmitters<T>> & PromiseMethod<ExtractMethods<T>> & ComponentListeners<ExtractListeners<T>>;
type ComponentCallbacks<Callbacks> = {
[K in keyof Callbacks as `handle${Capitalize<string & K>}`]: Callbacks[K];
};
type ComponentRefs<Refs> = {
[K in keyof Refs as `ref${Capitalize<string & K>}`]: (element?: Refs[K]) => void;
};
type FunctionalComponentEmitters<Emitters> = {
[K in keyof Emitters as `on${Capitalize<string & K>}`]: EventEmitter<Emitters[K]>;
};
export type FunctionalComponentProps<T extends ComponentApi> = StrictFields<InternalProps<T>> & StrictFields<ExtractStates<T>> & ComponentCallbacks<ExtractCallbacks<T>> & ComponentRefs<ExtractRefs<T>> & FunctionalComponentEmitters<ExtractEmitters<T>> & Partial<Omit<JSXBase.HTMLAttributes<HTMLElement>, keyof InternalProps<T> | keyof ExtractStates<T>>>;
type ControllerCallbackHandlers<Callbacks> = {
[K in keyof Callbacks as `handle${Capitalize<string & K>}`]: (element?: Callbacks[K]) => void;
};
type ControllerListeners<Listeners> = {
[K in keyof Listeners as `on${Capitalize<string & K>}`]: (event: Listeners[K]) => void;
};
type ControllerRefSetters<Refs> = {
[K in keyof Refs as `set${Capitalize<string & K>}Ref`]: (element?: Refs[K]) => void;
};
export type ControllerInterface<T extends ComponentApi = ComponentApi> = {
componentWillLoad(props: ResolvedInputProps<T>): void;
getRenderProp<K extends keyof InternalProps<T>>(key: K): StrictFields<InternalProps<T>>[K];
} & ComponentWatchers<ExternalProps<T>> & ControllerCallbackHandlers<ExtractCallbacks<T>> & ControllerListeners<ExtractListeners<T>> & ExtractMethods<T> & ControllerRefSetters<ExtractRefs<T>>;
export {};