= CurrentEvent extends Event ? True : never;
/**
* @todo Rename Handler to Listener
*/
type DOMEventHandlerKeys = {
[I in keyof P]-?: NonNullable
extends DOMEventHandlerValue
? CheckEvent
: P[I] extends { value: DOMEventHandlerValue }
? CheckEvent
: never;
}[keyof P];
interface DOMEventHandlerType extends FunctionConstructor {}
interface DOMEventHandlerValue {
(event: CurrentEvent): any;
}
type DOMEventType = {
[I in keyof "0" as `on${Type}`]: {
type: DOMEventHandlerType;
value: DOMEventHandlerValue;
};
};
interface DOM$Attrs {
[prop: `\$${string}`]: Nullable;
}
interface DOMUnknown {
[prop: string]: any;
}
type DOMEventTarget = {
[I in keyof CurrentEvent]: I extends "currentTarget"
? CurrentTarget
: I extends "target"
? Target
: CurrentEvent[I];
};
type DOMTarget<
Target,
CurrentEvent,
Targets = Element | Node
> = CurrentEvent extends {
customTarget: infer EventTarget;
}
? DOMTarget, EventTarget>
: DOMEventTarget;
type DOMGetEventBefore = Value extends DOMEventHandlerValue<
infer Event
>
? DOMEvent>
: null;
type DOMGetEvent<
Type extends string,
Element extends AtomicoStatic
> = Element extends {
"##props": infer Props;
}
? `on${Type}` extends keyof Props
? DOMGetEventBefore, DOMThis>
: Event
: Event;
type DOMEvent<
Target = HTMLElement,
CurrentEvent = Event
> = Target extends string
? CurrentEvent extends AtomicoStatic
? DOMGetEvent
: DOMEventType
: DOMTarget, CurrentEvent>;
type DOMEventHandler = Handler extends (
ev: infer CurrentEvent
) => any
? CurrentEvent extends Event
? (ev: DOMEvent) => any
: Handler
: Handler;
type DOMEvents = {
[Prop in keyof Target]?: Prop extends `on${string}`
? DOMEventHandler
: Target[Prop];
};
type DOMCustomTarget = { customTarget: Target };
type DOMTag = Props extends null
? PropsNullable<
Omit, DOMCleanKeys> &
DOMGenericProperties &
DOMRef
> &
DOM$Attrs &
DOMUnknown
: PropsNullable<
Props &
Omit, keyof Props | DOMCleanKeys> &
DOMGenericProperties &
DOMRef
> &
DOM$Attrs &
DOMUnknown;
type DOMTags = {
[Tag in keyof HTMLTags]: Tag extends keyof HTMLMerge
? DOMTag
: DOMTag;
};
type DOMThis = Element extends new (
...args: any[]
) => infer This
? This
: Element;
interface AtomicoElements {
host: HTMLElement;
}
interface DOMCustomTags {
slot: HTMLSlotElement & {
onslotchange: (event: Event & DOMCustomTarget) => void;
assignNode: ChildNode;
};
form: DOMFormElement & {
onsubmit: (
event: SubmitEvent & DOMCustomTarget
) => any;
onchange: (event: Event & DOMCustomTarget) => any;
oninput: (event: Event & DOMCustomTarget) => any;
};
input: DOMCustomTag<
HTMLInputElement,
{
min: string | number;
max: string | number;
step: string | number;
value: string | number;
}
>;
}
type JSXElements = DOMTags &
DOMTags &
DOMTags;
type JSXProxy = {
[I in keyof Props]?: I extends `on${string}`
? NonNullable extends DOMEventHandlerValue
? Nullable<
(
ev: DOMEventTarget
) => any
>
: Props[I]
: I extends "ref"
? DOMRefValue
: Props[I];
};
type JSXProps = T extends Atomico
? T extends { new (props: infer Props): any }
? Props
: DOMTag
: T extends keyof JSXElements
? JSXElements[T]
: T extends string
? DOMTag
: DOMTag>;
type AtomicoThis = Props &
DOMThis & {
update(): Promise;
updated: Promise;
mounted: Promise;
unmounted: Promise;
readonly symbolId: unique symbol;
};
interface AtomicoStatic extends HTMLElement {
styles: Sheets[];
props: SchemaInfer;
/**
* Meta property, allows associating the component's
* props in typescript to external environments.
*/
readonly "##props": Props;
/**
* Allows to identify a constructor created with Atomico
*/
readonly "##atomico": true;
}
interface Atomico
extends AtomicoStatic {
new (
props?: JSXProxy<
DOMTag, Props>,
AtomicoThis
>
): AtomicoThis;
}
type EventInit = CustomEventInit & {
type: string;
base?: typeof CustomEvent | typeof Event;
};
/**
* Interface to fill in unknown properties like any | null | undefined
*/
interface FillObject {
[index: string]: any;
}
type FillArray = any[];
type FillFunction = (...args: any[]) => any;
type FillPromise = Promise;
type FillConstructor = abstract new (...args: any) => any;
type SchemaEvent = {
event?: EventInit;
};
type SchemaBase = SchemaEvent & {
attr?: string;
};
type SchemaReflect = SchemaBase & {
reflect?: boolean;
} & type;
type SchemaProp = SchemaEvent & type;
type SchemaOnlyPropWrapper =
| SchemaProp<{
type: Constructor;
}>
| SchemaProp<{
type: Constructor;
value: Type;
}>
| SchemaProp<{
type: Constructor;
value: () => Type;
}>;
type SchemaReflectWrapper =
| SchemaReflect<{
type: Constructor;
}>
| SchemaReflect<{
type: Constructor;
value: Type;
}>
| SchemaReflect<{
type: Constructor;
value: () => Type;
}>;
type SchemaAny =
| SchemaReflect<{
value: Type;
}>
| SchemaReflect<{
value: () => Type;
}>
| SchemaReflect<{}>;
type SchemaTypeCustom =
| TypeCustom
| SchemaReflectWrapper, any>;
type TypeString =
| StringConstructor
| SchemaReflectWrapper;
type TypeBoolean =
| BooleanConstructor
| SchemaReflectWrapper;
type TypeNumber =
| NumberConstructor
| SchemaReflectWrapper;
type TypePromise =
| PromiseConstructor
| SchemaOnlyPropWrapper;
type TypeSymbol =
| SymbolConstructor
| SchemaOnlyPropWrapper;
type TypeFunction =
| FunctionConstructor
| SchemaOnlyPropWrapper;
type TypeArray =
| ArrayConstructor
| SchemaReflectWrapper;
type TypeObject =
| ObjectConstructor
| SchemaReflectWrapper;
type TypeAny = null | SchemaAny;
type Self = typeof window;
type SelfIgnore =
| StringConstructor
| NumberConstructor
| BooleanConstructor
| FunctionConstructor
| ObjectConstructor
| PromiseConstructor
| SymbolConstructor
| ArrayConstructor;
type SafeGlobal =
| "Event"
| "URL"
| "Range"
| "Image"
| "Crypto"
| "File"
| "Date"
| "Set"
| "Map"
| "RegExp"
| "Animation"
| `${string}Event`
| `Event${string}`
| `Clipboard${string}`
| `Animation${string}`
| `Form${string}`
| `Font${string}`
| `DOM${string}`
| `Touch${string}`
| `Mutation${string}`
| `Intersection${string}`
| `Message${string}`
| `HTML${string}`
| `SVG${string}`
| `Audio${string}`
| `Document${string}`
| `Weak${string}`
| `CSS${string}`
| `File${string}`;
type SelfConstructors = Pick<
Self,
{
[I in keyof Self]-?: I extends string
? I extends Capitalize
? Self[I] extends FillConstructor
? Self[I] extends SelfIgnore
? never
: I extends SafeGlobal
? I
: never
: never
: never
: never;
}[keyof Self]
>;
type TypeConstructor =
| type
| SchemaOnlyPropWrapper>;
type TypesSelfValues = {
[I in keyof SelfConstructors]-?: InstanceType;
}[keyof SelfConstructors];
type GetTypeSelf = {
[I in keyof SelfConstructors]-?: value extends InstanceType<
SelfConstructors[I]
>
? keyof value extends keyof InstanceType
? SelfConstructors[I]
: never
: never;
}[keyof SelfConstructors];
type TypesDiscard = type extends FillFunction
? TypeFunction
: type extends FillObject
? TypeObject
: TypeAny;
type Type = type extends string
? TypeString
: type extends number
? TypeNumber
: type extends boolean
? TypeBoolean
: type extends TypeCustom
? SchemaTypeCustom
: type extends FillPromise
? TypePromise
: type extends symbol
? TypeSymbol
: type extends FillArray
? TypeArray
: type extends DOMStringMap
? TypeObject
: type extends TypesSelfValues
? GetTypeSelf extends never
? TypesDiscard
: TypeConstructor>
: TypesDiscard;
type SchemaInfer = Required<
Omit<
{
[I in keyof Props]: Type;
},
DOMEventHandlerKeys
>
>;
type TypeCustom