##// END OF EJS Templates
Support for Function Components...
cin -
r34:e8012fdf09ae 1.0.0-rc16 default
parent child
Show More
@@ -0,0 +1,32
1 import dom = require("dojo/dom-construct");
2 import attr = require("dojo/dom-attr");
3 import { argumentNotNull } from "@implab/core-amd/safe";
4 import { BuildContextBase } from "./BuildContextBase";
5
6
7 export class FunctionComponentContext extends BuildContextBase<Element> {
8 private _component: (props: any) => Element;
9
10 private _element: Element | undefined;
11
12 constructor(component: (props: any) => Element) {
13 super();
14 argumentNotNull(component, "component");
15
16 this._component = component;
17 }
18
19 _create(attrs: object, children: any[]) {
20 const _attrs: any = attrs || {};
21 _attrs.children = children.map(x => this.getChildDom(x));
22
23 this._element = this._component.call(null, _attrs);
24 }
25
26 _getDomNode() {
27 if (!this._element)
28 throw new Error("The instance of the widget isn't created");
29 return this._element;
30 }
31
32 }
@@ -0,0 +1,13
1 var rjs = require('requirejs');
2
3 rjs.config({
4 baseUrl: '.',
5 nodeRequire: require,
6 packages: [
7 { name: "dojo", location: "../../node_modules/dojo" },
8 { name: "@implab", location: "../../node_modules/@implab" }
9 ]
10 });
11
12
13 rjs(['./plan']); No newline at end of file
@@ -0,0 +1,10
1 import { Baz } from "./mock/Baz";
2
3 console.log("Declare tests");
4
5 const baz = new Baz();
6
7 const data: string[] = [];
8 baz.writeHello(data);
9
10 console.log(data.join("\n"));
@@ -0,0 +1,17
1 import { djclass, djbase } from "../declare";
2
3 interface Super {
4 writeHello(out: string[]): void;
5
6 }
7
8 @djclass
9 export class BarMixin extends djbase<Super>() {
10 writeHello(out: string[]) {
11 out.push("-> Bar");
12
13 super.writeHello(out);
14
15 out.push("<- Bar");
16 }
17 }
@@ -0,0 +1,15
1 import { djbase, djclass } from "../declare";
2 import { FooMixin } from "./FooMixin";
3 import { BarMixin } from "./BarMixin";
4 import { BoxMixin } from "./BoxMixin";
5
6 @djclass
7 export class Baz extends djbase(FooMixin, BarMixin, BoxMixin) {
8 writeHello(out: string[]) {
9 out.push("-> Baz");
10
11 super.writeHello(out);
12
13 out.push("<- Baz");
14 }
15 }
@@ -0,0 +1,16
1 import { djbase, djclass } from "../declare";
2
3 interface Super {
4 writeHello(out: string[]): void;
5 }
6
7 @djclass
8 export class BoxMixin extends djbase<Super>() {
9 writeHello(out: string[]) {
10 out.push("-> Box");
11
12 super.writeHello(out);
13
14 out.push("<- Box");
15 }
16 }
@@ -0,0 +1,16
1 import { djclass, djbase } from "../declare";
2
3 interface Super {
4 writeHello(out: string[]): void;
5 }
6
7 @djclass
8 export class FooMixin extends djbase<Super>() {
9 writeHello(out: string[]) {
10 out.push("-> Foo");
11
12 super.writeHello(out);
13
14 out.push("<- Foo");
15 }
16 } No newline at end of file
@@ -0,0 +1,1
1 import "./DeclareTests"; No newline at end of file
@@ -1,33 +1,40
1 1 import { Constructor } from "@implab/core-amd/interfaces";
2 2 import { HtmlElementContext } from "./tsx/HtmlElementContext";
3 3 import { WidgetContext } from "./tsx/WidgetContext";
4 4 import { isWidgetConstructor, BuildContext } from "./tsx/traits";
5 import { FunctionComponentContext } from "./tsx/FunctionComponentContext";
5 6
6 export function createElement<T extends Constructor>(elementType: string | T, ...args: any[]): BuildContext {
7 export function createElement<T extends Constructor | string | ((props: any) => Element)>(elementType: T, ...args: any[]): BuildContext {
7 8 if (typeof elementType === "string") {
8 9 const ctx = new HtmlElementContext(elementType);
9 10 if (args)
10 11 args.forEach(x => ctx.visitNext(x));
11 12
12 13 return ctx;
13 14 } else if (isWidgetConstructor(elementType)) {
14 15 const ctx = new WidgetContext(elementType);
15 16 if (args)
16 17 args.forEach(x => ctx.visitNext(x));
17 18
18 19 return ctx;
20 } else if (typeof elementType === "function") {
21 const ctx = new FunctionComponentContext(elementType as (props: any) => Element);
22 if (args)
23 args.forEach(x => ctx.visitNext(x));
24
25 return ctx;
19 26 } else {
20 27 throw new Error(`The element type '${elementType}' is unsupported`);
21 28 }
22 29 }
23 30
24 31 export interface EventDetails<T = any> {
25 32 detail: T;
26 33 }
27 34
28 35 export interface EventSelector {
29 36 selectorTarget: HTMLElement;
30 37 target: HTMLElement;
31 38 }
32 39
33 40 export type DojoMouseEvent<T = any> = MouseEvent & EventSelector & EventDetails<T>;
@@ -1,76 +1,68
1 1 import { isNull, mixin } from "@implab/core-amd/safe";
2 2 import { isPlainObject, isNode, isBuildContext, DojoNodePosition, BuildContext } from "./traits";
3 3
4 4 import dom = require("dojo/dom-construct");
5 5
6 6 export abstract class BuildContextBase<TNode extends Node> implements BuildContext<TNode> {
7 _attrs = {};
7 private _attrs = {};
8 8
9 _children = new Array();
9 private _children = new Array();
10 10
11 _created: boolean = false;
11 private _created: boolean = false;
12 12
13 13 visitNext(v: any) {
14 if (this._created)
15 throw new Error("The Element is already created");
16
14 17 if (isNull(v))
15 18 return;
16 19
17 20 if (isPlainObject(v)) {
18
19 if (this._created)
20 this._setAttrs(v);
21 else
22 21 mixin(this._attrs, v);
23 22 } else if (v instanceof Array) {
24 v.forEach(x => this._addChild(x));
23 v.forEach(x => this.visitNext(x));
25 24 } else {
26 if (this._created)
27 this._addChild(v);
28 else
29 25 this._children.push(v);
30 26 }
31 27 }
32 28
33 29 getChildDom(v: any) {
34 30 const tv = typeof v;
35 31 if (tv === "string" || tv === "number" || tv === "boolean" || v instanceof RegExp || v instanceof Date) {
36 32 return document.createTextNode(v.toString());
37 33 } else if (isNode(v)) {
38 34 return v;
39 35 } else if (isBuildContext(v)) {
40 36 return v.getDomNode();
41 37 } else {
42 38 throw new Error("Invalid parameter");
43 39 }
44 40 }
45 41
46 42 abstract _getDomNode(): TNode;
47 43
48 44 ensureCreated() {
49 45 if (!this._created) {
50 46 this._create(this._attrs, this._children);
51 47 this._children = [];
52 48 this._attrs = {};
53 49 this._created = true;
54 50 }
55 51 }
56 52
57 53 /** @deprecated use getDomNode() */
58 54 getDomElement() {
59 55 return this.getDomNode();
60 56 }
61 57
62 58 getDomNode() {
63 59 this.ensureCreated();
64 60 return this._getDomNode();
65 61 }
66 62
67 63 placeAt(refNode: string | Node, position?: DojoNodePosition) {
68 64 dom.place(this.getDomNode(), refNode, position);
69 65 }
70 66
71 abstract _addChild(child: any): void;
72
73 abstract _setAttrs(attrs: object): void;
74
75 67 abstract _create(attrs: object, children: any[]): void;
76 68 }
@@ -1,45 +1,38
1 1 import dom = require("dojo/dom-construct");
2 2 import attr = require("dojo/dom-attr");
3 3 import { argumentNotEmptyString } from "@implab/core-amd/safe";
4 4 import { BuildContextBase } from "./BuildContextBase";
5 5
6 6 export class HtmlElementContext extends BuildContextBase<HTMLElement> {
7 7 elementType: string;
8 8
9 9 _element: HTMLElement | undefined;
10 10
11 11 constructor(elementType: string) {
12 12 argumentNotEmptyString(elementType, "elementType");
13 13 super();
14 14
15 15 this.elementType = elementType;
16 16 }
17 17
18 18 _addChild(child: any): void {
19 19 if (!this._element)
20 20 throw new Error("The HTML element isn't created");
21 21 dom.place(this.getChildDom(child), this._element);
22 22 }
23 23
24 _setAttrs(attrs: object): void {
25 if (!this._element)
26 throw new Error("The HTML element isn't created");
27
28 attr.set(this._element, attrs);
29 }
30
31 24 _create(attrs: object, children: any[]) {
32 25 this._element = dom.create(this.elementType, attrs);
33 26
34 27 if (children)
35 28 children.forEach(v => this._addChild(v));
36 29 }
37 30
38 31 _getDomNode() {
39 32 if (!this._element)
40 33 throw new Error("The HTML element isn't created");
41 34
42 35 return this._element;
43 36 }
44 37
45 38 }
@@ -1,55 +1,51
1 1 import dom = require("dojo/dom-construct");
2 2 import { argumentNotNull } from "@implab/core-amd/safe";
3 3 import { BuildContextBase } from "./BuildContextBase";
4 4 import { MapOf } from "@implab/core-amd/interfaces";
5 5
6 6 // tslint:disable-next-line: class-name
7 7 export interface _Widget {
8 8 domNode: Node;
9 9
10 10 get(attr: string): any;
11 11
12 12 set(attr: string, value: any): void;
13 13 set(attrs: MapOf<any>): void;
14 14
15 15 containerNode?: Node
16 16 }
17 17
18 18 export type _WidgetCtor = new (attrs: any, srcNode?: string | Node) => _Widget;
19 19
20 20 export class WidgetContext extends BuildContextBase<Node> {
21 21 widgetClass: _WidgetCtor;
22 22
23 23 _instance: _Widget | undefined;
24 24
25 25 constructor(widgetClass: _WidgetCtor) {
26 26 super();
27 27 argumentNotNull(widgetClass, "widgetClass");
28 28
29 29 this.widgetClass = widgetClass;
30 30 }
31 31
32 32 _addChild(child: any): void {
33 33 if (!this._instance || !this._instance.containerNode)
34 34 throw new Error("Widget doesn't support adding children");
35 35
36 36 dom.place(this.getChildDom(child), this._instance.containerNode);
37 37 }
38 38
39 _setAttrs(attrs: object): void {
40 this._instance?.set(attrs);
41 }
42
43 39 _create(attrs: object, children: any[]) {
44 this._instance = new this.widgetClass(this._attrs);
40 this._instance = new this.widgetClass(attrs);
45 41 if (children)
46 42 children.forEach(x => this._addChild(x));
47 43 }
48 44
49 45 _getDomNode() {
50 46 if (!this._instance)
51 47 throw new Error("The instance of the widget isn't created");
52 48 return this._instance.domNode;
53 49 }
54 50
55 51 }
@@ -1,25 +1,30
1 1 declare module "@implab/djx/css!*" {
2 2 const result: { url: string };
3 3 export = result;
4 4 }
5 5
6 6 declare namespace JSX {
7 interface IntrinsicElements {
8 [name: string]: any;
7 interface DjxIntrinsicAttributes {
8 class: string;
9 "data-dojo-attach-point": string;
10 "data-dojo-attach-event": string;
11 }
12 type IntrinsicElements = {
13 [name in keyof HTMLElementTagNameMap]: Partial<Omit<HTMLElementTagNameMap[name], "children"> & DjxIntrinsicAttributes>;
9 14 }
10 15 }
11 16
12 17 declare namespace dijit {
13 18 interface _WidgetBase {
14 19
15 20 _started?: boolean;
16 21
17 22 _set<K extends keyof this>(key: K, value: this[K]): void;
18 23 }
19 24
20 25 interface TooltipDialog {
21 26
22 27 content: any;
23 28
24 29 }
25 30 } No newline at end of file
@@ -1,43 +1,46
1 1 import { djbase, djclass, bind, prototype, AbstractConstructor } from "../declare";
2 2
3 3 import { DjxWidgetBase } from "../tsx/DjxWidgetBase";
4 4 import { createElement } from "../tsx";
5 5
6 6 interface MyWidgetAttrs {
7 7 title: string;
8 8
9 9 counter: number;
10 10 }
11 11
12 12 interface MyWidgetEvents {
13 13 "count-inc": Event;
14 14
15 15 "count-dec": Event;
16 16 }
17 17
18 18
19 19 @djclass
20 20 export class MyWidget extends djbase(DjxWidgetBase as AbstractConstructor<DjxWidgetBase<MyWidgetAttrs, MyWidgetEvents>>) {
21 21
22 22 @bind({node: "titleNode", type:"innerHTML"})
23 23 title = "";
24 24
25 25 @prototype()
26 26 counter = 0;
27 27
28 28 render() {
29 const Frame = (props: any) => <div>{props.children}</div>;
29 30 return <div>
30 31 <h1 data-dojo-attach-point="titleNode"></h1>
31 <span onclick={() => this._onIncClick()}>[+]</span>
32 <span onclick={() => this._onDecClick()}>[-]</span>
32 <Frame>
33 <span class="up-button" onclick={e => this._onIncClick(e)}>[+]</span>
34 <span class="down-button" onclick={() => this._onDecClick()}>[-]</span>
35 </Frame>
33 36 </div>;
34 37 }
35 38
36 _onIncClick() {
39 _onIncClick(e: MouseEvent) {
37 40 this.emit("count-inc", { bubbles: false } );
38 41 }
39 42
40 43 _onDecClick() {
41 44 this.emit("count-dec", { bubbles: false } );
42 45 }
43 46 }
1 NO CONTENT: file was removed
General Comments 0
You need to be logged in to leave comments. Login now