diff --git a/examples/counters/src/index.ts b/examples/counters/src/index.ts index 3215940..01dbb0d 100644 --- a/examples/counters/src/index.ts +++ b/examples/counters/src/index.ts @@ -12,6 +12,7 @@ import { main1 } from "./version1"; import { main2 } from "./version2"; import { main3 } from "./version3"; import { counterList as main4 } from "./version4"; +import main5 from "./version5"; const { ul, li, p, br, button, h1, div } = elements; @@ -19,7 +20,8 @@ const numberToApp = { 1: main1, 2: main2, 3: main3, - 4: main4 + 4: main4, + 5: main5 }; type AppId = keyof (typeof numberToApp); @@ -56,10 +58,17 @@ const versionSelector = modelView( selectorButton("1", selected).output({ select1: "select" }), selectorButton("2", selected).output({ select2: "select" }), selectorButton("3", selected).output({ select3: "select" }), - selectorButton("4", selected).output({ select4: "select" }) + selectorButton("4", selected).output({ select4: "select" }), + selectorButton("5", selected).output({ select5: "select" }) ]) .map((o) => ({ - selectVersion: combine(o.select1, o.select2, o.select3, o.select4) + selectVersion: combine( + o.select1, + o.select2, + o.select3, + o.select4, + o.select5 + ) })) .output({ selectVersion: "selectVersion" }) ); diff --git a/examples/counters/src/version5.tsx b/examples/counters/src/version5.tsx new file mode 100644 index 0000000..986f42e --- /dev/null +++ b/examples/counters/src/version5.tsx @@ -0,0 +1,34 @@ +import { fgo, combine, F1 } from "@funkia/jabz"; +import { sample, scan, Stream, Behavior } from "@funkia/hareactive"; +import { createElement, modelView } from "../../../src"; + +type CounterModelInput = { + incrementClick: Stream; + decrementClick: Stream; +}; + +type CounterViewInput = { + count: Behavior; +}; + +const model = fgo(function*({ + incrementClick, + decrementClick +}: CounterModelInput) { + const increment = incrementClick.mapTo(1); + const decrement = decrementClick.mapTo(-1); + const changes = combine(increment, decrement); + const count: number = yield sample(scan((n, m) => n + m, 0, changes)); + return { count }; +}); + +const view = ({ count }: CounterViewInput) => ( +
+ Counter {count} + + +
+); + +const main = modelView(model, view)(); +export default main; diff --git a/examples/counters/tsconfig.json b/examples/counters/tsconfig.json index a72a631..dcf3660 100644 --- a/examples/counters/tsconfig.json +++ b/examples/counters/tsconfig.json @@ -1,6 +1,8 @@ { + "compilerOptions": { + "jsx": "react", + "jsxFactory": "createElement" + }, "extends": "../tsconfig.json", - "include": [ - "**/*.ts" - ] -} \ No newline at end of file + "include": ["**/*.ts", "**/*.tsx"] +} diff --git a/karma.conf.js b/karma.conf.js index 504605b..3405855 100644 --- a/karma.conf.js +++ b/karma.conf.js @@ -1,13 +1,15 @@ -module.exports = function (config) { +module.exports = function(config) { config.set({ frameworks: ["mocha", "karma-typescript"], files: [ { pattern: "src/**/*.ts" }, - { pattern: "test/**/*.ts" } + { pattern: "test/**/*.ts" }, + { pattern: "test/**/*.tsx" } ], preprocessors: { "src/**/*.ts": ["karma-typescript"], - "test/**/*.ts": ["karma-typescript"] + "test/**/*.ts": ["karma-typescript"], + "test/**/*.tsx": ["karma-typescript"] }, reporters: ["mocha", "karma-typescript"], browsers: ["Chrome"], diff --git a/package-lock.json b/package-lock.json index 0893d2f..2a60f4d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2560,12 +2560,14 @@ "balanced-match": { "version": "1.0.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "brace-expansion": { "version": "1.1.11", "bundled": true, "dev": true, + "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -2580,17 +2582,20 @@ "code-point-at": { "version": "1.1.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "concat-map": { "version": "0.0.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "console-control-strings": { "version": "1.1.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "core-util-is": { "version": "1.0.2", @@ -2707,7 +2712,8 @@ "inherits": { "version": "2.0.3", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "ini": { "version": "1.3.5", @@ -2719,6 +2725,7 @@ "version": "1.0.0", "bundled": true, "dev": true, + "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -2733,6 +2740,7 @@ "version": "3.0.4", "bundled": true, "dev": true, + "optional": true, "requires": { "brace-expansion": "^1.1.7" } @@ -2740,12 +2748,14 @@ "minimist": { "version": "0.0.8", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "minipass": { "version": "2.2.4", "bundled": true, "dev": true, + "optional": true, "requires": { "safe-buffer": "^5.1.1", "yallist": "^3.0.0" @@ -2764,6 +2774,7 @@ "version": "0.5.1", "bundled": true, "dev": true, + "optional": true, "requires": { "minimist": "0.0.8" } @@ -2844,7 +2855,8 @@ "number-is-nan": { "version": "1.0.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "object-assign": { "version": "4.1.1", @@ -2856,6 +2868,7 @@ "version": "1.4.0", "bundled": true, "dev": true, + "optional": true, "requires": { "wrappy": "1" } @@ -2977,6 +2990,7 @@ "version": "1.0.2", "bundled": true, "dev": true, + "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", diff --git a/src/elements.ts b/src/elements.ts index 04bcf14..a8da860 100644 --- a/src/elements.ts +++ b/src/elements.ts @@ -1,10 +1,5 @@ -import { Behavior, Stream } from "@funkia/hareactive"; -import { Component, ChildList } from "./component"; import { element, streamDescription, behaviorDescription } from "./dom-builder"; -// Required due to exports using the type -import { ClassDescriptionArray } from "./dom-builder"; - export const input = element("input", { actionDefinitions: { focus: (elm: HTMLElement): void => elm.focus() diff --git a/src/index.ts b/src/index.ts index 9e6f600..00b1090 100644 --- a/src/index.ts +++ b/src/index.ts @@ -3,3 +3,4 @@ export * from "./component"; export * from "./dom-builder"; import * as elements from "./elements"; export { elements }; +export * from "./jsx"; diff --git a/src/jsx.ts b/src/jsx.ts new file mode 100644 index 0000000..90780e0 --- /dev/null +++ b/src/jsx.ts @@ -0,0 +1,34 @@ +import { elements } from "."; +import { Component } from "./component"; +import { div } from "./elements"; +import { DefaultOutput, Properties, ElementCreator } from "./dom-builder"; + +export function createElement( + node: string, + props: Properties | null, + ...children: any[] +): Component<{}, DefaultOutput> { + console.log("node", node); + console.log("props", props); + console.log("children", children); + + const e: ElementCreator = node in elements ? (elements)[node] : div; + + if (props !== null) { + let o = undefined; + if ("output" in props && typeof props === "object") { + o = props.output; + delete props.output; + } + const el = e(props, children); + return o !== undefined ? el.output(o) : el; + } + return e(children); +} + +declare global { + namespace JSX { + type IntrinsicElements = { [k in keyof typeof elements]: any }; + type Element = Component; + } +} diff --git a/test/jsx.spec.tsx b/test/jsx.spec.tsx new file mode 100644 index 0000000..72ccc53 --- /dev/null +++ b/test/jsx.spec.tsx @@ -0,0 +1,7 @@ +import { use } from "chai"; +import * as chaiDom from "chai-dom"; +use(chaiDom); + +describe.only("jsx", () => { + it("basic", () => {}); +}); diff --git a/tsconfig.json b/tsconfig.json index 39915b8..c71c851 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -11,7 +11,9 @@ "strict": true, "strictPropertyInitialization": false, "noStrictGenericChecks": true, - "lib": ["dom", "es2017"] + "lib": ["dom", "es2017"], + "jsxFactory": "createElement", + "jsx": "react" }, "include": ["src/**/*", "test/**/*", "examples/**/*"], "exclude": ["node_modules"]