-
Notifications
You must be signed in to change notification settings - Fork 139
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix(ts-typings): update TS type definitions (#1012)
* fix(ts-typings): refactor 'h' annotations with jsx and support special attributes when using TSX * test(definitions): add test for class attribute within TSX and 'h' * refactor(ts-typings): restructure definitions to separate files with only proper API exported * test(definitions): add tests for all use cases with new typings. Also add Stateless components * chore(ts-typings): apply ts formatter to all typings to prevent unconsistency * fix(ts-typings): temporary fix anchor element issue caused by TS * fix(ts-typings): properly support slot attributes on custom elements referenced via class
- Loading branch information
Showing
7 changed files
with
444 additions
and
212 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,113 +1,21 @@ | ||
export { } from "./jsx"; | ||
|
||
// UMD library | ||
export as namespace skate; | ||
|
||
export type ComponentProps <El, T> = { | ||
[P in keyof T]: PropOptions<El, T[P]>; | ||
}; | ||
|
||
interface ComponentDefaultProps { | ||
children?: JSX.Element[]; | ||
key?: string; | ||
} | ||
|
||
export class Component<Props> extends HTMLElement { | ||
// Special hack for own components type checking. | ||
// It works in combination with ElementAttributesProperty. It placed in jsx.d.ts. | ||
// more detail, see: https://www.typescriptlang.org/docs/handbook/jsx.html | ||
// and https://github.com/skatejs/skatejs/pull/952#issuecomment-264500153 | ||
_props: Props & ComponentDefaultProps; | ||
|
||
static is: string; | ||
static readonly props: ComponentProps<any, any>; | ||
static readonly observedAttributes: string[]; | ||
|
||
// Custom Elements v1 | ||
connectedCallback(): void; | ||
disconnectedCallback(): void; | ||
attributeChangedCallback(name: string, oldValue: null | string, newValue: null | string): void; | ||
adoptedCallback?(): void; | ||
|
||
// SkateJS life cycle | ||
updatedCallback(previousProps: { [nameOrSymbol: string]: any }): boolean | void; | ||
renderCallback(): any; | ||
renderedCallback(): void; | ||
|
||
// SkateJS DEPRECATED | ||
static created?(elem: Component<any>): void; | ||
static attached?(elem: Component<any>): void; | ||
static detached?(elem: Component<any>): void; | ||
static attributeChanged?(elem: Component<any>, data: { name: string, oldValue: null | string, newValue: null | string }): void; | ||
static updated(elem: Component<any>, prevProps: { [nameOrSymbol: string]: any }): boolean; | ||
static render?(elem: Component<any>): any | undefined; | ||
static rendered?(elem: Component<any>): void; | ||
} | ||
|
||
type AttributeReflectionBaseType = boolean | string; | ||
type AttributeReflectionConfig = AttributeReflectionBaseType | { | ||
source?: AttributeReflectionBaseType, | ||
target?: AttributeReflectionBaseType | ||
} | ||
export interface PropOptions<El, T> { | ||
attribute?: AttributeReflectionConfig ; | ||
coerce?: (value: any) => T | null | undefined; | ||
default?: T | null | undefined | ((elem: El, data: { name: string; }) => T | null | undefined); | ||
deserialize?: (value: string | null) => T | null | undefined; | ||
get?: <R>(elem: El, data: { name: string; internalValue: T; }) => R; | ||
initial?: T | null | undefined | ((elem: El, data: { name: string; }) => T | null | undefined); | ||
serialize?: (value: T | null | undefined) => string | null; | ||
set?: (elem: El, data: { name: string; newValue: T | null | undefined; oldValue: T | null | undefined; }) => void; | ||
} | ||
|
||
export var define: { | ||
(name: string, ctor: Function): any; | ||
(ctor: Function): any; | ||
}; | ||
|
||
export interface EmitOptions { | ||
bubbles?: boolean; | ||
cancelable?: boolean; | ||
composed?: boolean; | ||
detail?: any; | ||
} | ||
export function emit(elem: EventTarget, name: string, opts?: EmitOptions): void; | ||
|
||
export var h: typeof vdom.element; | ||
|
||
export function link(elem: Component<any>, target?: string): (e: Event) => void; | ||
|
||
export var prop: { | ||
create<T>(attr: PropOptions<any, T>): PropOptions<any, T> & ((attr: PropOptions<any, T>) => PropOptions<any, T>); | ||
|
||
number(attr?: PropOptions<any, number>): PropOptions<any, number>; | ||
boolean(attr?: PropOptions<any, boolean>): PropOptions<any, boolean>; | ||
string(attr?: PropOptions<any, string>): PropOptions<any, string>; | ||
array<T>(attr?: PropOptions<any, T[]>): PropOptions<any, T[]>; | ||
object<T extends Object>(attr?: PropOptions<any, T>): PropOptions<any, T>; | ||
}; | ||
|
||
export function props(elem: Component<any>, props?: any): void; | ||
|
||
export function ready(elem: Component<any>, done: (c: Component<any>) => void): void; | ||
|
||
// DEPRECATED | ||
// export var symbols: any; | ||
|
||
type VDOMElementTName = string | typeof Component | typeof vdom.element | { id: string; }; | ||
type VDOMElementChild = Function | string | number; | ||
type VDOMElementSet = VDOMElementChild | VDOMElementChild[]; | ||
|
||
export var vdom: { | ||
element(tname: VDOMElementTName, attrs: { key: any; statics: any; } & any, ...chren: VDOMElementSet[]): Component<any> | any; | ||
element(tname: VDOMElementTName, ...chren: VDOMElementSet[]): Component<any> | any; | ||
builder(): typeof vdom.element; | ||
builder(...tags: string[]): (typeof vdom.element)[]; | ||
|
||
attr(...args: any[]): void; | ||
elementClose: Function; | ||
elementOpen: Function; | ||
elementOpenEnd: Function; | ||
elementOpenStart: Function; | ||
elementVoid: Function; | ||
text: Function; | ||
}; | ||
// empty reexport so user get's JSX to global | ||
export { } from './ts-typings/jsx'; | ||
|
||
// Public API | ||
export { | ||
Component, | ||
ComponentProps, | ||
StatelessComponent, | ||
SFC, | ||
prop, | ||
props, | ||
ready, | ||
link, | ||
define, | ||
emit, | ||
h, | ||
vdom | ||
} from './ts-typings/api'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,138 @@ | ||
import { Key, HTMLProps } from './common'; | ||
|
||
export type ComponentProps<El, T> = { | ||
[P in keyof T]: PropOptions<El, T[P]>; | ||
}; | ||
|
||
interface ComponentDefaultProps { | ||
children?: VDOMElement<any>[]; | ||
key?: Key; | ||
} | ||
|
||
export interface StatelessComponent<Props> { | ||
(props: Props, children?: VDOMNode): VDOMElement<any>, | ||
} | ||
export type SFC<P> = StatelessComponent<P>; | ||
|
||
interface ComponentClass<PropsType> { | ||
new (props?: PropsType): Component<PropsType>; | ||
} | ||
export class Component<Props> extends HTMLElement { | ||
// Special hack for own components type checking. | ||
// It works in combination with ElementAttributesProperty. It placed in jsx.d.ts. | ||
// more detail, see: https://www.typescriptlang.org/docs/handbook/jsx.html | ||
// and https://github.com/skatejs/skatejs/pull/952#issuecomment-264500153 | ||
_props: Props & ComponentDefaultProps; | ||
// this is not possible yet? ... without this we have to duplicate props definition with class props definition | ||
// [K in keyof Props]: Props[K], | ||
|
||
static readonly props: ComponentProps<any, any>; | ||
static readonly observedAttributes: string[]; | ||
|
||
// Custom Elements v1 | ||
connectedCallback(): void; | ||
disconnectedCallback(): void; | ||
attributeChangedCallback(name: string, oldValue: null | string, newValue: null | string): void; | ||
adoptedCallback?(): void; | ||
|
||
// SkateJS life cycle | ||
updatedCallback(previousProps: { [nameOrSymbol: string]: any }): boolean | void; | ||
renderCallback(): VDOMElement<any> | VDOMElement<any>[] | null; | ||
renderedCallback(): void; | ||
|
||
// SkateJS DEPRECATED | ||
static created?(elem: Component<any>): void; | ||
static attached?(elem: Component<any>): void; | ||
static detached?(elem: Component<any>): void; | ||
static attributeChanged?(elem: Component<any>, data: { name: string, oldValue: null | string, newValue: null | string }): void; | ||
static updated(elem: Component<any>, prevProps: { [nameOrSymbol: string]: any }): boolean; | ||
static render?(elem: Component<any>): VDOMElement<any> | VDOMElement<any>[] | null; | ||
static rendered?(elem: Component<any>): void; | ||
} | ||
|
||
|
||
type AttributeReflectionBaseType = boolean | string; | ||
type AttributeReflectionConfig = AttributeReflectionBaseType | { | ||
source?: AttributeReflectionBaseType, | ||
target?: AttributeReflectionBaseType | ||
} | ||
export interface PropOptions<El, T> { | ||
attribute?: AttributeReflectionConfig; | ||
coerce?: (value: any) => T | null | undefined; | ||
default?: T | null | undefined | ((elem: El, data: { name: string; }) => T | null | undefined); | ||
deserialize?: (value: string | null) => T | null | undefined; | ||
get?: <R>(elem: El, data: { name: string; internalValue: T; }) => R; | ||
initial?: T | null | undefined | ((elem: El, data: { name: string; }) => T | null | undefined); | ||
serialize?: (value: T | null | undefined) => string | null; | ||
set?: (elem: El, data: { name: string; newValue: T | null | undefined; oldValue: T | null | undefined; }) => void; | ||
} | ||
|
||
export var define: { | ||
(name: string, ctor: Function): any; | ||
(ctor: Function): any; | ||
}; | ||
|
||
export interface EmitOptions { | ||
bubbles?: boolean; | ||
cancelable?: boolean; | ||
composed?: boolean; | ||
detail?: any; | ||
} | ||
export function emit(elem: EventTarget, name: string, opts?: EmitOptions): void; | ||
|
||
export var h: typeof vdom.element; | ||
|
||
export function link(elem: Component<any>, target?: string): (e: Event) => void; | ||
|
||
export var prop: { | ||
create<T>(attr: PropOptions<any, T>): PropOptions<any, T> & ((attr: PropOptions<any, T>) => PropOptions<any, T>); | ||
|
||
number(attr?: PropOptions<any, number>): PropOptions<any, number>; | ||
boolean(attr?: PropOptions<any, boolean>): PropOptions<any, boolean>; | ||
string(attr?: PropOptions<any, string>): PropOptions<any, string>; | ||
array<T>(attr?: PropOptions<any, T[]>): PropOptions<any, T[]>; | ||
object<T extends Object>(attr?: PropOptions<any, T>): PropOptions<any, T>; | ||
}; | ||
|
||
export function props(elem: Component<any>, props?: any): void; | ||
|
||
export function ready(elem: Component<any>, done: (c: Component<any>) => void): void; | ||
|
||
// @DEPRECATED | ||
// export var symbols: any; | ||
|
||
|
||
// | ||
// VDOM Nodes | ||
// ---------------------------------------------------------------------- | ||
|
||
export interface VDOMElement<P> { | ||
type: VDOMElementType<P>; | ||
props: P; | ||
key: Key | null; | ||
} | ||
type VDOMText = string | number; | ||
type VDOMChild = VDOMElement<any> | VDOMText; | ||
|
||
// Should be Array<VDOMNode> but type aliases cannot be recursive | ||
type VDOMFragment = {} | Array<VDOMChild | any[] | boolean>; | ||
type VDOMNode = VDOMChild | VDOMFragment | boolean | null | undefined; | ||
|
||
type VDOMElementType<P> = string | { id: string } | ComponentClass<P> | SFC<P>; | ||
|
||
export var vdom: { | ||
|
||
element<P>(type: VDOMElementType<P>, attrs?: HTMLProps<HTMLElement> | P, ...children: VDOMChild[]): VDOMElement<any>, | ||
element<P>(type: VDOMElementType<P>, ...children: VDOMChild[]): VDOMElement<any>, | ||
|
||
builder(): typeof vdom.element; | ||
builder(...tags: string[]): ((attrs?: HTMLProps<HTMLElement>, ...children: VDOMChild[]) => VDOMElement<any>)[]; | ||
|
||
attr(...args: any[]): void; | ||
elementClose: Function; | ||
elementOpen: Function; | ||
elementOpenEnd: Function; | ||
elementOpenStart: Function; | ||
elementVoid: Function; | ||
text: Function; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
export type Key = string | number; | ||
export type Ref<T> = string | ((instance: T) => any); | ||
|
||
interface Attributes { | ||
key?: Key, | ||
// this will be possible removed and added just to ClassAttributes because of https://github.com/skatejs/skatejs/issues/1020 | ||
slot?: string, | ||
} | ||
interface ClassAttributes<T> extends Attributes { | ||
ref?: Ref<T>, | ||
} | ||
|
||
// | ||
// JSX Related types | ||
// ---------------------------------------------------------------------- | ||
|
||
export type HTMLProps<T extends Element> = Partial<T> & IncrementalHyperscriptAttributes<T>; | ||
export type IncrementalHyperscriptAttributes<T> = IncrementalDomHTMLAttributes<T> & HyperscriptHTMLAttributes & HyperscriptEventHandler<T>; | ||
|
||
interface IncrementalDomHTMLAttributes<T> { | ||
key?: Key, | ||
ref?: Ref<T>, | ||
statics?: string[], | ||
skip?: boolean, | ||
} | ||
interface HyperscriptHTMLAttributes { | ||
class?: string, | ||
} | ||
|
||
interface HyperscriptEventHandler<T> { | ||
onAbort?: typeof HTMLElement.prototype.onabort; | ||
onActivate?: typeof HTMLElement.prototype.onactivate; | ||
onBeforeactivate?: typeof HTMLElement.prototype.onbeforeactivate; | ||
onBeforecopy?: typeof HTMLElement.prototype.onbeforecopy; | ||
onBeforecut?: typeof HTMLElement.prototype.onbeforecut; | ||
onBeforedeactivate?: typeof HTMLElement.prototype.onbeforedeactivate; | ||
onBeforepaste?: typeof HTMLElement.prototype.onbeforepaste; | ||
onBlur?: typeof HTMLElement.prototype.onblur; | ||
onCanplay?: typeof HTMLElement.prototype.oncanplay; | ||
onCanplaythrough?: typeof HTMLElement.prototype.oncanplaythrough; | ||
onChange?: typeof HTMLElement.prototype.onchange; | ||
onClick?: typeof HTMLElement.prototype.onclick; | ||
onContextmenu?: typeof HTMLElement.prototype.oncontextmenu; | ||
onCopy?: typeof HTMLElement.prototype.oncopy; | ||
onCuechange?: typeof HTMLElement.prototype.oncuechange; | ||
onCut?: typeof HTMLElement.prototype.oncut; | ||
onDblclick?: typeof HTMLElement.prototype.ondblclick; | ||
onDeactivate?: typeof HTMLElement.prototype.ondeactivate; | ||
onDrag?: typeof HTMLElement.prototype.ondrag; | ||
onDragend?: typeof HTMLElement.prototype.ondragend; | ||
onDragenter?: typeof HTMLElement.prototype.ondragenter; | ||
onDragleave?: typeof HTMLElement.prototype.ondragleave; | ||
onDragover?: typeof HTMLElement.prototype.ondragover; | ||
onDragstart?: typeof HTMLElement.prototype.ondragstart; | ||
onDrop?: typeof HTMLElement.prototype.ondrop; | ||
onDurationchange?: typeof HTMLElement.prototype.ondurationchange; | ||
onEmptied?: typeof HTMLElement.prototype.onemptied; | ||
onEnded?: typeof HTMLElement.prototype.onended; | ||
onError?: typeof HTMLElement.prototype.onerror; | ||
onFocus?: typeof HTMLElement.prototype.onfocus; | ||
onInput?: typeof HTMLElement.prototype.oninput; | ||
onInvalid?: typeof HTMLElement.prototype.oninvalid; | ||
onKeydown?: typeof HTMLElement.prototype.onkeydown; | ||
onKeypress?: typeof HTMLElement.prototype.onkeypress; | ||
onKeyup?: typeof HTMLElement.prototype.onkeyup; | ||
onLoad?: typeof HTMLElement.prototype.onload; | ||
onLoadeddata?: typeof HTMLElement.prototype.onloadeddata; | ||
onLoadedmetadata?: typeof HTMLElement.prototype.onloadedmetadata; | ||
onLoadstart?: typeof HTMLElement.prototype.onloadstart; | ||
onMousedown?: typeof HTMLElement.prototype.onmousedown; | ||
onMouseenter?: typeof HTMLElement.prototype.onmouseenter; | ||
onMouseleave?: typeof HTMLElement.prototype.onmouseleave; | ||
onMousemove?: typeof HTMLElement.prototype.onmousemove; | ||
onMouseout?: typeof HTMLElement.prototype.onmouseout; | ||
onMouseover?: typeof HTMLElement.prototype.onmouseover; | ||
onMouseup?: typeof HTMLElement.prototype.onmouseup; | ||
onMousewheel?: typeof HTMLElement.prototype.onmousewheel; | ||
onMscontentzoom?: typeof HTMLElement.prototype.onmscontentzoom; | ||
onMsmanipulationstatechanged?: typeof HTMLElement.prototype.onmsmanipulationstatechanged; | ||
onPaste?: typeof HTMLElement.prototype.onpaste; | ||
onPause?: typeof HTMLElement.prototype.onpause; | ||
onPlay?: typeof HTMLElement.prototype.onplay; | ||
onPlaying?: typeof HTMLElement.prototype.onplaying; | ||
onProgress?: typeof HTMLElement.prototype.onprogress; | ||
onRatechange?: typeof HTMLElement.prototype.onratechange; | ||
onReset?: typeof HTMLElement.prototype.onreset; | ||
onScroll?: typeof HTMLElement.prototype.onscroll; | ||
onSeeked?: typeof HTMLElement.prototype.onseeked; | ||
onSeeking?: typeof HTMLElement.prototype.onseeking; | ||
onSelect?: typeof HTMLElement.prototype.onselect; | ||
onSelectstart?: typeof HTMLElement.prototype.onselectstart; | ||
onStalled?: typeof HTMLElement.prototype.onstalled; | ||
onSubmit?: typeof HTMLElement.prototype.onsubmit; | ||
onSuspend?: typeof HTMLElement.prototype.onsuspend; | ||
onTimeupdate?: typeof HTMLElement.prototype.ontimeupdate; | ||
onVolumechange?: typeof HTMLElement.prototype.onvolumechange; | ||
onWaiting?: typeof HTMLElement.prototype.onwaiting; | ||
} |
Oops, something went wrong.