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