##// END OF EJS Templates
fixed cyclic module references tsx/traits, tsx/FunctionRendition, tsx/RenditionBase
fixed cyclic module references tsx/traits, tsx/FunctionRendition, tsx/RenditionBase

File last commit:

r89:367f8caa5bf8 v1.2.8 default
r89:367f8caa5bf8 v1.2.8 default
Show More
tsx.ts
119 lines | 4.4 KiB | video/mp2t | TypeScriptLexer
import { Constructor, IDestroyable, IRemovable } from "@implab/core-amd/interfaces";
import { HtmlRendition } from "./tsx/HtmlRendition";
import { WidgetRendition } from "./tsx/WidgetRendition";
import { destroy, isWidgetConstructor, Rendition } from "./tsx/traits";
import { FunctionRendition } from "./tsx/FunctionRendition";
import Stateful = require("dojo/Stateful");
import _WidgetBase = require("dijit/_WidgetBase");
import { DjxWidgetBase } from "./tsx/DjxWidgetBase";
export function createElement<T extends Constructor | string | ((props: any) => Element)>(elementType: T, ...args: any[]): Rendition {
if (typeof elementType === "string") {
const ctx = new HtmlRendition(elementType);
if (args)
args.forEach(x => ctx.visitNext(x));
return ctx;
} else if (isWidgetConstructor(elementType)) {
const ctx = new WidgetRendition(elementType);
if (args)
args.forEach(x => ctx.visitNext(x));
return ctx;
} else if (typeof elementType === "function") {
const ctx = new FunctionRendition(elementType as (props: any) => Element);
if (args)
args.forEach(x => ctx.visitNext(x));
return ctx;
} else {
throw new Error(`The element type '${elementType}' is unsupported`);
}
}
export interface EventDetails<T = any> {
detail: T;
}
export interface EventSelector {
selectorTarget: HTMLElement;
target: HTMLElement;
}
export type DojoMouseEvent<T = any> = MouseEvent & EventSelector & EventDetails<T>;
type StatefulProps<T> = T extends Stateful<infer A> ? A : never;
type CleanFn = (instance: IRemovable | IDestroyable) => void;
/**
* Observers the property and calls render callback each change.
*
* @param target The target object which property will be observed.
* @param prop The name of the property.
* @param render The callback which will be called every time the value is changed
* @param cleanupOrOwner The object with method `own` or an callback to register lifecycle for the observer.
* @returns Rendition which is created instantly
*/
export function watch<W extends _WidgetBase, K extends keyof W>(
target: W,
prop: K,
render: (model: W[K]) => any,
cleanupOrOwner?: { own: CleanFn } | CleanFn
): Rendition;
/**
* Observers the property and calls render callback each change.
*
* @param target The target object which property will be observed.
* @param prop The name of the property.
* @param render The callback which will be called every time the value is changed
* @param cleanupOrOwner The object with method `own` or an callback to register lifecycle for the observer.
* @returns Rendition which is created instantly
*/
export function watch<T extends Stateful, K extends keyof StatefulProps<T>>(
target: T,
prop: K,
render: (model: StatefulProps<T>[K]) => any,
cleanupOrOwner?: { own: CleanFn } | CleanFn
): Rendition;
export function watch<T extends Stateful, K extends keyof StatefulProps<T> & string>(
target: T,
prop: K,
render: (model: StatefulProps<T>[K]) => any,
cleanupOrOwner: { own: CleanFn } | CleanFn = () => { }
) {
let rendition = new FunctionRendition(() => render(target.get(prop)));
const _own = cleanupOrOwner instanceof Function ? cleanupOrOwner : (x: IRemovable) => cleanupOrOwner.own(x);
_own(target.watch(prop, (_name, oldValue, newValue) => {
if (oldValue !== newValue) {
const newRendition = new FunctionRendition(() => render(newValue));
newRendition.placeAt(rendition.getDomNode(), "replace");
destroy(rendition.getDomNode());
rendition = newRendition;
}
}));
return rendition;
}
/** Decorates the method which will be registered as the handle for the specified event.
* This decorator can be applied to DjxWidgetBase subclass methods.
*
* ```
* @on("click")
* _onClick(eventObj: MouseEvent) {
* // ...
* }
* ```
*/
export const on = <E extends string>(...eventNames: E[]) =>
<K extends string,
T extends DjxWidgetBase<any, { [p in E]: EV }>,
EV extends Event
>(
target: T,
key: K,
_descriptor: TypedPropertyDescriptor<(eventObj: EV) => void> | TypedPropertyDescriptor<() => void>
): any => {
const handlers = eventNames.map(eventName => ({ eventName, handlerMethod: key }))
target._eventHandlers = target._eventHandlers ? target._eventHandlers.concat(handlers) : handlers;
};