peryl 1.5.2 → 1.5.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +30 -16
- package/demo/hsml-app-form-validation_demo.ts +22 -23
- package/demo/hsml-app-form_demo.ts +24 -20
- package/demo/hsml-app-test_demo.ts +35 -36
- package/demo/hsml-app-tictactoe_demo.ts +16 -15
- package/demo/hsml-app_demo.ts +20 -12
- package/demo/hsml-appel_demo.html +7 -0
- package/demo/hsml-appel_demo.ts +33 -25
- package/demo/hsml-appi_demo.ts +9 -9
- package/demo/hsml_demo.ts +27 -22
- package/demo/js/hsml-app-js-happi_demo.html +16 -8
- package/demo/js/hsml-app-js_demo.html +15 -15
- package/dist/browser-esmodule/encode.js.map +1 -1
- package/dist/browser-esmodule/hsml-app.js +67 -73
- package/dist/browser-esmodule/hsml-app.js.map +1 -1
- package/dist/browser-esmodule/hsml-convert.js.map +1 -1
- package/dist/browser-esmodule/hsml-dom.js +3 -3
- package/dist/browser-esmodule/hsml-dom.js.map +1 -1
- package/dist/browser-esmodule/hsml-h.js.map +1 -1
- package/dist/browser-esmodule/hsml-html.js +2 -2
- package/dist/browser-esmodule/hsml-html.js.map +1 -1
- package/dist/browser-esmodule/hsml-idom.js +5 -5
- package/dist/browser-esmodule/hsml-idom.js.map +1 -1
- package/dist/browser-esmodule/hsml.js.map +1 -1
- package/dist/browser-esmodule/http.js.map +1 -1
- package/dist/browser-esmodule/index.js +71 -77
- package/dist/browser-esmodule/index.js.map +1 -1
- package/dist/browser-esmodule/router.js.map +1 -1
- package/dist/browser-umd/encode.js +1 -1
- package/dist/browser-umd/encode.js.map +1 -1
- package/dist/browser-umd/hsml-app.js +1 -1
- package/dist/browser-umd/hsml-app.js.map +1 -1
- package/dist/browser-umd/hsml-convert.js.map +1 -1
- package/dist/browser-umd/hsml-dom.js +1 -1
- package/dist/browser-umd/hsml-dom.js.map +1 -1
- package/dist/browser-umd/hsml-h.js.map +1 -1
- package/dist/browser-umd/hsml-html.js +1 -1
- package/dist/browser-umd/hsml-html.js.map +1 -1
- package/dist/browser-umd/hsml-idom.js +1 -1
- package/dist/browser-umd/hsml-idom.js.map +1 -1
- package/dist/browser-umd/hsml.js.map +1 -1
- package/dist/browser-umd/http.js +1 -1
- package/dist/browser-umd/http.js.map +1 -1
- package/dist/browser-umd/index.js +1 -1
- package/dist/browser-umd/index.js.map +1 -1
- package/dist/browser-umd/router.js +1 -1
- package/dist/browser-umd/router.js.map +1 -1
- package/dist/browser-umd/validators-moment.js +1 -1
- package/dist/browser-umd/validators-moment.js.map +1 -1
- package/dist/browser-umd/validators-numeral.js.map +1 -1
- package/dist/demo/encode_demo.ce182166.js.map +1 -1
- package/dist/demo/encode_demo.f40a44eb.js.map +1 -1
- package/dist/demo/hsml-app-form-validation_demo.a9e2c583.js +2 -0
- package/dist/demo/hsml-app-form-validation_demo.a9e2c583.js.map +1 -0
- package/dist/demo/hsml-app-form-validation_demo.bb392ab0.js +2 -0
- package/dist/demo/hsml-app-form-validation_demo.bb392ab0.js.map +1 -0
- package/dist/demo/hsml-app-form-validation_demo.c6856b02.js +2 -0
- package/dist/demo/hsml-app-form-validation_demo.c6856b02.js.map +1 -0
- package/dist/demo/hsml-app-form-validation_demo.fdcc0b2d.js +2 -0
- package/dist/demo/hsml-app-form-validation_demo.fdcc0b2d.js.map +1 -0
- package/dist/demo/hsml-app-form-validation_demo.html +1 -1
- package/dist/demo/hsml-app-form_demo.e36ef1e9.js +2 -0
- package/dist/demo/hsml-app-form_demo.e36ef1e9.js.map +1 -0
- package/dist/demo/hsml-app-form_demo.fd22dfcf.js +2 -0
- package/dist/demo/hsml-app-form_demo.fd22dfcf.js.map +1 -0
- package/dist/demo/hsml-app-form_demo.html +1 -1
- package/dist/demo/hsml-app-test_demo.ba5f166c.js +2 -0
- package/dist/demo/hsml-app-test_demo.ba5f166c.js.map +1 -0
- package/dist/demo/hsml-app-test_demo.e8b5e4b2.js +2 -0
- package/dist/demo/hsml-app-test_demo.e8b5e4b2.js.map +1 -0
- package/dist/demo/hsml-app-test_demo.html +1 -1
- package/dist/demo/hsml-app-tictactoe_demo.03d8363f.js +2 -0
- package/dist/demo/hsml-app-tictactoe_demo.03d8363f.js.map +1 -0
- package/dist/demo/hsml-app-tictactoe_demo.399f8e69.js +2 -0
- package/dist/demo/hsml-app-tictactoe_demo.399f8e69.js.map +1 -0
- package/dist/demo/hsml-app-tictactoe_demo.html +1 -1
- package/dist/demo/hsml-app_demo.44aa1072.js +2 -0
- package/dist/demo/hsml-app_demo.44aa1072.js.map +1 -0
- package/dist/demo/hsml-app_demo.70ef3e7a.js +2 -0
- package/dist/demo/hsml-app_demo.70ef3e7a.js.map +1 -0
- package/dist/demo/hsml-app_demo.html +1 -1
- package/dist/demo/hsml-appel_demo.2a9f7f3f.js +2 -0
- package/dist/demo/hsml-appel_demo.2a9f7f3f.js.map +1 -0
- package/dist/demo/hsml-appel_demo.bea7849a.js +2 -0
- package/dist/demo/hsml-appel_demo.bea7849a.js.map +1 -0
- package/dist/demo/hsml-appel_demo.html +1 -1
- package/dist/demo/hsml-appi_demo.3dc5de90.js +2 -0
- package/dist/demo/hsml-appi_demo.3dc5de90.js.map +1 -0
- package/dist/demo/hsml-appi_demo.bfc7056a.js +2 -0
- package/dist/demo/hsml-appi_demo.bfc7056a.js.map +1 -0
- package/dist/demo/hsml-appi_demo.html +1 -1
- package/dist/demo/hsml-convert_demo.0ea1fa3b.js.map +1 -1
- package/dist/demo/hsml-convert_demo.63e3e7b5.js.map +1 -1
- package/dist/demo/{hsml_demo.ff950ba1.js → hsml_demo.a248689a.js} +2 -2
- package/dist/demo/hsml_demo.a248689a.js.map +1 -0
- package/dist/demo/hsml_demo.eb3b08be.js +2 -0
- package/dist/demo/hsml_demo.eb3b08be.js.map +1 -0
- package/dist/demo/hsml_demo.html +1 -1
- package/dist/demo/http_demo.3e7da3d8.js.map +1 -1
- package/dist/demo/http_demo.8e435f23.js.map +1 -1
- package/dist/demo/i18n_demo.html +1 -1
- package/dist/demo/router_demo.3cfa03aa.js.map +1 -1
- package/dist/demo/router_demo.89ab1681.js.map +1 -1
- package/dist/demo/{validators_demo.252e13a6.js → validators_demo.90ff6001.js} +2 -2
- package/dist/demo/validators_demo.90ff6001.js.map +1 -0
- package/dist/demo/{validators_demo.66893723.js → validators_demo.ef5b2dea.js} +2 -2
- package/dist/demo/validators_demo.ef5b2dea.js.map +1 -0
- package/dist/demo/validators_demo.html +1 -1
- package/dist/encode.js +1 -1
- package/dist/encode.js.map +1 -1
- package/dist/hsml-app.d.ts +38 -37
- package/dist/hsml-app.js +60 -62
- package/dist/hsml-app.js.map +1 -1
- package/dist/hsml-convert.d.ts +3 -3
- package/dist/hsml-convert.js.map +1 -1
- package/dist/hsml-dom.d.ts +2 -2
- package/dist/hsml-dom.js +3 -3
- package/dist/hsml-dom.js.map +1 -1
- package/dist/hsml-h.d.ts +8 -8
- package/dist/hsml-h.js.map +1 -1
- package/dist/hsml-html.d.ts +4 -4
- package/dist/hsml-html.js +2 -2
- package/dist/hsml-html.js.map +1 -1
- package/dist/hsml-idom.d.ts +2 -2
- package/dist/hsml-idom.js +5 -5
- package/dist/hsml-idom.js.map +1 -1
- package/dist/hsml.d.ts +26 -27
- package/dist/hsml.js.map +1 -1
- package/dist/http.js +1 -1
- package/dist/http.js.map +1 -1
- package/dist/router.js +1 -1
- package/dist/router.js.map +1 -1
- package/package.json +8 -8
- package/src/hsml-app.ts +209 -144
- package/src/hsml-convert.ts +8 -8
- package/src/hsml-dom.ts +18 -18
- package/src/hsml-h.ts +10 -10
- package/src/hsml-html.ts +19 -19
- package/src/hsml-idom.ts +25 -25
- package/src/hsml.ts +46 -143
- package/demo/hsml-appc_demo.html +0 -16
- package/demo/hsml-appc_demo.ts +0 -49
- package/dist/demo/hsml-app-form-validation_demo.0b03b743.js +0 -2
- package/dist/demo/hsml-app-form-validation_demo.0b03b743.js.map +0 -1
- package/dist/demo/hsml-app-form-validation_demo.b3a5c810.js +0 -2
- package/dist/demo/hsml-app-form-validation_demo.b3a5c810.js.map +0 -1
- package/dist/demo/hsml-app-form-validation_demo.d3925067.js +0 -2
- package/dist/demo/hsml-app-form-validation_demo.d3925067.js.map +0 -1
- package/dist/demo/hsml-app-form-validation_demo.f757d763.js +0 -2
- package/dist/demo/hsml-app-form-validation_demo.f757d763.js.map +0 -1
- package/dist/demo/hsml-app-form_demo.007ffcaa.js +0 -2
- package/dist/demo/hsml-app-form_demo.007ffcaa.js.map +0 -1
- package/dist/demo/hsml-app-form_demo.a034239d.js +0 -2
- package/dist/demo/hsml-app-form_demo.a034239d.js.map +0 -1
- package/dist/demo/hsml-app-test_demo.35c14dc9.js +0 -2
- package/dist/demo/hsml-app-test_demo.35c14dc9.js.map +0 -1
- package/dist/demo/hsml-app-test_demo.3c7e16ae.js +0 -2
- package/dist/demo/hsml-app-test_demo.3c7e16ae.js.map +0 -1
- package/dist/demo/hsml-app-tictactoe_demo.5f4861c1.js +0 -2
- package/dist/demo/hsml-app-tictactoe_demo.5f4861c1.js.map +0 -1
- package/dist/demo/hsml-app-tictactoe_demo.7deeabad.js +0 -2
- package/dist/demo/hsml-app-tictactoe_demo.7deeabad.js.map +0 -1
- package/dist/demo/hsml-app_demo.87d83c29.js +0 -2
- package/dist/demo/hsml-app_demo.87d83c29.js.map +0 -1
- package/dist/demo/hsml-app_demo.941a13a6.js +0 -2
- package/dist/demo/hsml-app_demo.941a13a6.js.map +0 -1
- package/dist/demo/hsml-appc_demo.0234ff15.js +0 -2
- package/dist/demo/hsml-appc_demo.0234ff15.js.map +0 -1
- package/dist/demo/hsml-appc_demo.f5783031.js +0 -2
- package/dist/demo/hsml-appc_demo.f5783031.js.map +0 -1
- package/dist/demo/hsml-appc_demo.html +0 -1
- package/dist/demo/hsml-appel_demo.0e8a4d4c.js +0 -2
- package/dist/demo/hsml-appel_demo.0e8a4d4c.js.map +0 -1
- package/dist/demo/hsml-appel_demo.1a5c2c26.js +0 -2
- package/dist/demo/hsml-appel_demo.1a5c2c26.js.map +0 -1
- package/dist/demo/hsml-appi_demo.2c3fb511.js +0 -2
- package/dist/demo/hsml-appi_demo.2c3fb511.js.map +0 -1
- package/dist/demo/hsml-appi_demo.427fdebd.js +0 -2
- package/dist/demo/hsml-appi_demo.427fdebd.js.map +0 -1
- package/dist/demo/hsml_demo.33f28c29.js +0 -2
- package/dist/demo/hsml_demo.33f28c29.js.map +0 -1
- package/dist/demo/hsml_demo.ff950ba1.js.map +0 -1
- package/dist/demo/validators_demo.252e13a6.js.map +0 -1
- package/dist/demo/validators_demo.66893723.js.map +0 -1
package/README.md
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
# PeRyL
|
|
2
2
|
|
|
3
|
-
TypeScript/JavaScript library and tools for rapid server and client side web
|
|
3
|
+
TypeScript/JavaScript library and tools for rapid server and client side web
|
|
4
|
+
applications development.
|
|
4
5
|
|
|
5
6
|
## HApp - PeRyL HSML App
|
|
6
7
|
|
|
7
|
-
`HApp` - HSML App, TypeScript/JavaScript Web UI framework for rapid SPA web
|
|
8
|
+
`HApp` - HSML App, TypeScript/JavaScript Web UI framework for rapid SPA web
|
|
9
|
+
applications development based on Flux single directional data flow architecture.
|
|
8
10
|
|
|
9
11
|
Read [Tutorial](HApp.md) to learn how to write HApp.
|
|
10
12
|
|
|
@@ -35,13 +37,15 @@ HApp example code:
|
|
|
35
37
|
<script src="https://unpkg.com/peryl/dist/browser-umd/hsml-app.js"></script>
|
|
36
38
|
<script>
|
|
37
39
|
|
|
38
|
-
|
|
40
|
+
// Flux single directional data flow architecture actions
|
|
41
|
+
const Actions = {
|
|
39
42
|
title: "title",
|
|
40
43
|
dec: "dec",
|
|
41
44
|
inc: "inc",
|
|
42
45
|
clear: "clear"
|
|
43
46
|
}
|
|
44
47
|
|
|
48
|
+
// Flux single directional data flow architecture state/store init
|
|
45
49
|
function state() {
|
|
46
50
|
return {
|
|
47
51
|
title: "Counter",
|
|
@@ -49,24 +53,29 @@ HApp example code:
|
|
|
49
53
|
};
|
|
50
54
|
}
|
|
51
55
|
|
|
56
|
+
// Flux single directional data flow architecture view
|
|
52
57
|
function view(state) {
|
|
58
|
+
// HSML (Hyper Script Markup Language) HTML reprezentation
|
|
53
59
|
return [
|
|
54
60
|
["h2",
|
|
61
|
+
// conditional class
|
|
55
62
|
{ classes: [["w3-text-light-grey", !state.title]] },
|
|
56
63
|
state.title || "No title"
|
|
57
64
|
],
|
|
58
65
|
["p", [
|
|
59
66
|
["label", "Title:"],
|
|
67
|
+
// Input element static classes declaration
|
|
60
68
|
["input.w3-input.w3-border", {
|
|
61
69
|
type: "text",
|
|
62
70
|
name: "title",
|
|
63
71
|
value: new String(state.title),
|
|
64
|
-
|
|
72
|
+
// On click action definition
|
|
73
|
+
on: ["input", Actions.title]
|
|
65
74
|
}]
|
|
66
75
|
]],
|
|
67
76
|
["p", [
|
|
68
77
|
["button.w3-button.w3-blue",
|
|
69
|
-
{ on: ["click",
|
|
78
|
+
{ on: ["click", Actions.clear] },
|
|
70
79
|
"Clear title"
|
|
71
80
|
]
|
|
72
81
|
]],
|
|
@@ -85,42 +94,46 @@ HApp example code:
|
|
|
85
94
|
]
|
|
86
95
|
]],
|
|
87
96
|
["button.w3-button.w3-blue",
|
|
88
|
-
|
|
97
|
+
// On click action definition with attached data
|
|
98
|
+
{ on: ["click", Actions.dec, 1] },
|
|
89
99
|
[["i.fa.fa-chevron-left"]]
|
|
90
100
|
],
|
|
91
101
|
" ",
|
|
92
102
|
["button.w3-button.w3-blue",
|
|
93
|
-
{ on: ["click",
|
|
103
|
+
{ on: ["click", Actions.inc, 2] },
|
|
94
104
|
[["i.fa.fa-chevron-right"]]
|
|
95
105
|
]
|
|
96
106
|
]]
|
|
97
107
|
]
|
|
98
108
|
};
|
|
99
109
|
|
|
110
|
+
// Flux single directional data flow architecture dispatcher
|
|
100
111
|
async function dispatcher(action, state, dispatch) {
|
|
101
112
|
console.log("action:", action);
|
|
102
113
|
|
|
103
114
|
switch (action.type) {
|
|
104
|
-
|
|
105
|
-
case
|
|
106
|
-
case
|
|
115
|
+
// HSML App (HApp) lifecycle actions
|
|
116
|
+
case HAppActions.init:
|
|
117
|
+
case HAppActions.mount:
|
|
118
|
+
case HAppActions.umount:
|
|
107
119
|
break;
|
|
108
120
|
|
|
109
|
-
case
|
|
121
|
+
case Actions.title:
|
|
122
|
+
// Action data resolved automatically form input
|
|
110
123
|
state.title = action.data.title;
|
|
111
124
|
break;
|
|
112
125
|
|
|
113
|
-
case
|
|
126
|
+
case Actions.inc:
|
|
114
127
|
state.count = state.count + action.data;
|
|
115
128
|
// async action call
|
|
116
|
-
setTimeout(() => dispatch(
|
|
129
|
+
setTimeout(() => dispatch(Actions.dec, 1), 1e3);
|
|
117
130
|
break;
|
|
118
131
|
|
|
119
|
-
case
|
|
132
|
+
case Actions.dec:
|
|
120
133
|
state.count = state.count - action.data;
|
|
121
134
|
break;
|
|
122
135
|
|
|
123
|
-
case
|
|
136
|
+
case Actions.clear:
|
|
124
137
|
state.title = "";
|
|
125
138
|
break;
|
|
126
139
|
|
|
@@ -129,8 +142,9 @@ HApp example code:
|
|
|
129
142
|
}
|
|
130
143
|
};
|
|
131
144
|
|
|
132
|
-
|
|
145
|
+
HApp.debug = true; // Print console flux lifecycle details
|
|
133
146
|
|
|
147
|
+
// Run HApp application on html element with id "app"
|
|
134
148
|
new HApp(state, view, dispatcher, "app");
|
|
135
149
|
|
|
136
150
|
</script>
|
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
import { HElement,
|
|
2
|
-
import {
|
|
1
|
+
import { HElement, hjoin } from "../src/hsml";
|
|
2
|
+
import { HAppActions, HDispatcher, HState, HView, happ } from "../src/hsml-app";
|
|
3
3
|
import { BooleanValidator, DateValidator, FormValidator, FormValidatorData, NumberValidator, SelectValidator, StringValidator } from "../src/validators";
|
|
4
|
-
import { happ } from "../src/hsml-app";
|
|
5
4
|
|
|
6
|
-
export interface
|
|
5
|
+
export interface Data {
|
|
7
6
|
name: string;
|
|
8
7
|
born: Date;
|
|
9
8
|
children: number;
|
|
@@ -12,18 +11,18 @@ export interface FormValidationData {
|
|
|
12
11
|
sport: string;
|
|
13
12
|
}
|
|
14
13
|
|
|
15
|
-
export interface
|
|
14
|
+
export interface State {
|
|
16
15
|
title: string;
|
|
17
|
-
data:
|
|
16
|
+
data: Data;
|
|
18
17
|
genders: {
|
|
19
18
|
label: string;
|
|
20
19
|
value: string;
|
|
21
20
|
}[];
|
|
22
21
|
sports: string[];
|
|
23
|
-
validatorData?: FormValidatorData<
|
|
22
|
+
validatorData?: FormValidatorData<Data>;
|
|
24
23
|
}
|
|
25
24
|
|
|
26
|
-
export const
|
|
25
|
+
export const state: HState<State> = function () {
|
|
27
26
|
return {
|
|
28
27
|
title: "Form Validation",
|
|
29
28
|
data: {
|
|
@@ -42,20 +41,20 @@ export const formValidationState: HState<FormValidationState> = function () {
|
|
|
42
41
|
}
|
|
43
42
|
};
|
|
44
43
|
|
|
45
|
-
export enum
|
|
44
|
+
export enum Actions {
|
|
46
45
|
change = "form-validation-change",
|
|
47
46
|
submit = "form-validation-submit"
|
|
48
47
|
}
|
|
49
48
|
|
|
50
|
-
export const
|
|
49
|
+
export const view: HView<State, Actions> = function (state) {
|
|
51
50
|
return [
|
|
52
51
|
["div.w3-content", [
|
|
53
52
|
["h1", state.title],
|
|
54
53
|
["form.w3-container",
|
|
55
54
|
{
|
|
56
55
|
on: [
|
|
57
|
-
["change",
|
|
58
|
-
["submit",
|
|
56
|
+
["change", Actions.change],
|
|
57
|
+
["submit", Actions.submit]
|
|
59
58
|
]
|
|
60
59
|
},
|
|
61
60
|
[
|
|
@@ -65,7 +64,7 @@ export const formValidationView: HView<FormValidationState> = function (state):
|
|
|
65
64
|
type: "text",
|
|
66
65
|
name: "name",
|
|
67
66
|
value: state.validatorData!.str.name,
|
|
68
|
-
on: ["input",
|
|
67
|
+
on: ["input", Actions.change]
|
|
69
68
|
}]
|
|
70
69
|
]]
|
|
71
70
|
]],
|
|
@@ -104,7 +103,7 @@ export const formValidationView: HView<FormValidationState> = function (state):
|
|
|
104
103
|
["p.w3-text-red", [state.validatorData!.err.married]],
|
|
105
104
|
["p",
|
|
106
105
|
hjoin(
|
|
107
|
-
state.genders.map<HElement
|
|
106
|
+
state.genders.map<HElement<Actions>>(gender => (
|
|
108
107
|
["label", [
|
|
109
108
|
["input.w3-radio", {
|
|
110
109
|
type: "radio",
|
|
@@ -126,7 +125,7 @@ export const formValidationView: HView<FormValidationState> = function (state):
|
|
|
126
125
|
{ value: "", disabled: true, selected: true },
|
|
127
126
|
"Sport"
|
|
128
127
|
],
|
|
129
|
-
...state.sports.map<HElement
|
|
128
|
+
...state.sports.map<HElement<Actions>>(sport => (
|
|
130
129
|
["option",
|
|
131
130
|
{
|
|
132
131
|
value: sport,
|
|
@@ -146,19 +145,19 @@ export const formValidationView: HView<FormValidationState> = function (state):
|
|
|
146
145
|
];
|
|
147
146
|
};
|
|
148
147
|
|
|
149
|
-
let formValidator: FormValidator<
|
|
148
|
+
let formValidator: FormValidator<Data>;
|
|
150
149
|
|
|
151
|
-
export const
|
|
150
|
+
export const dispatcher: HDispatcher<State, Actions> = async function (action, state) {
|
|
152
151
|
console.log("action", action);
|
|
153
152
|
|
|
154
153
|
switch (action.type) {
|
|
155
154
|
|
|
156
|
-
case
|
|
155
|
+
case HAppActions.init:
|
|
157
156
|
formValidator = validator(state);
|
|
158
157
|
state.validatorData = formValidator.data();
|
|
159
158
|
break;
|
|
160
159
|
|
|
161
|
-
case
|
|
160
|
+
case Actions.change:
|
|
162
161
|
formValidator.validate({
|
|
163
162
|
...state.validatorData!.str,
|
|
164
163
|
...action.data
|
|
@@ -167,7 +166,7 @@ export const formValidationDispatcher: HDispatcher<FormValidationState> = async
|
|
|
167
166
|
console.log("obj:", JSON.stringify(state.validatorData, null, 4));
|
|
168
167
|
break;
|
|
169
168
|
|
|
170
|
-
case
|
|
169
|
+
case Actions.submit:
|
|
171
170
|
action.event!.preventDefault();
|
|
172
171
|
// console.log(action.data);
|
|
173
172
|
formValidator.validate(action.data);
|
|
@@ -185,8 +184,8 @@ export const formValidationDispatcher: HDispatcher<FormValidationState> = async
|
|
|
185
184
|
}
|
|
186
185
|
};
|
|
187
186
|
|
|
188
|
-
export function validator(formState:
|
|
189
|
-
return new FormValidator<
|
|
187
|
+
export function validator(formState: State): FormValidator<Data> {
|
|
188
|
+
return new FormValidator<Data>()
|
|
190
189
|
.addValidator("name", new StringValidator(
|
|
191
190
|
{
|
|
192
191
|
required: true,
|
|
@@ -299,4 +298,4 @@ function datetimeLocal(date: Date) {
|
|
|
299
298
|
}
|
|
300
299
|
}
|
|
301
300
|
|
|
302
|
-
happ<
|
|
301
|
+
happ<State, Actions>(state, view, dispatcher);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { HElement,
|
|
2
|
-
import {
|
|
1
|
+
import { HElement, hjoin } from "../src/hsml";
|
|
2
|
+
import { HAppActions, HDispatcher, HState, HView, happ } from "../src/hsml-app";
|
|
3
3
|
|
|
4
4
|
interface FormData {
|
|
5
5
|
name: string;
|
|
@@ -10,7 +10,7 @@ interface FormData {
|
|
|
10
10
|
sport: string;
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
-
interface
|
|
13
|
+
interface State {
|
|
14
14
|
title: string;
|
|
15
15
|
data: FormData;
|
|
16
16
|
genders: {
|
|
@@ -20,7 +20,7 @@ interface FormState {
|
|
|
20
20
|
sports: string[];
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
-
const
|
|
23
|
+
const state: HState<State> = function () {
|
|
24
24
|
return {
|
|
25
25
|
title: "HSML App Form",
|
|
26
26
|
data: {
|
|
@@ -40,12 +40,16 @@ const formState: HState<FormState> = function () {
|
|
|
40
40
|
};
|
|
41
41
|
};
|
|
42
42
|
|
|
43
|
-
|
|
43
|
+
// type FormActions =
|
|
44
|
+
// "form-change" |
|
|
45
|
+
// "form-submit";
|
|
46
|
+
|
|
47
|
+
enum Actions {
|
|
44
48
|
change = "form-change",
|
|
45
49
|
submit = "form-submit"
|
|
46
50
|
}
|
|
47
51
|
|
|
48
|
-
const
|
|
52
|
+
const view: HView<State, Actions> = function (state) {
|
|
49
53
|
return [
|
|
50
54
|
["div.w3-content.w3-light-gray", [
|
|
51
55
|
["div.w3-container", [
|
|
@@ -53,8 +57,8 @@ const formView: HView<FormState> = function (state): HElements {
|
|
|
53
57
|
["form.w3-panel",
|
|
54
58
|
{
|
|
55
59
|
on: [
|
|
56
|
-
["change",
|
|
57
|
-
["submit",
|
|
60
|
+
["change", Actions.change],
|
|
61
|
+
["submit", Actions.submit]
|
|
58
62
|
]
|
|
59
63
|
},
|
|
60
64
|
[
|
|
@@ -104,7 +108,7 @@ const formView: HView<FormState> = function (state): HElements {
|
|
|
104
108
|
]],
|
|
105
109
|
["p",
|
|
106
110
|
hjoin(
|
|
107
|
-
state.genders.map<HElement
|
|
111
|
+
state.genders.map<HElement<Actions>>(gender => (
|
|
108
112
|
["label", [
|
|
109
113
|
["input.w3-radio", {
|
|
110
114
|
type: "radio",
|
|
@@ -129,7 +133,7 @@ const formView: HView<FormState> = function (state): HElements {
|
|
|
129
133
|
},
|
|
130
134
|
"Sport"
|
|
131
135
|
],
|
|
132
|
-
...state.sports.map<HElement
|
|
136
|
+
...state.sports.map<HElement<Actions>>(sport => (
|
|
133
137
|
["option",
|
|
134
138
|
{
|
|
135
139
|
value: sport,
|
|
@@ -149,21 +153,21 @@ const formView: HView<FormState> = function (state): HElements {
|
|
|
149
153
|
];
|
|
150
154
|
};
|
|
151
155
|
|
|
152
|
-
const
|
|
156
|
+
const dispatcher: HDispatcher<State, Actions> = async function (action, state) {
|
|
153
157
|
switch (action.type) {
|
|
154
158
|
|
|
155
|
-
case
|
|
156
|
-
case
|
|
157
|
-
case
|
|
158
|
-
case
|
|
159
|
+
case HAppActions.init:
|
|
160
|
+
case HAppActions.mount:
|
|
161
|
+
case HAppActions.umount:
|
|
162
|
+
case HAppActions.elementAttr:
|
|
159
163
|
break;
|
|
160
164
|
|
|
161
|
-
case
|
|
162
|
-
console.log("
|
|
165
|
+
case Actions.change:
|
|
166
|
+
console.log("FormActions.change", JSON.stringify(action.data, null, 4));
|
|
163
167
|
break;
|
|
164
168
|
|
|
165
|
-
case
|
|
166
|
-
console.log("
|
|
169
|
+
case Actions.submit:
|
|
170
|
+
console.log("FormActions.submit", JSON.stringify(action.data, null, 4));
|
|
167
171
|
const formData = JSON.stringify(action.data, null, 4);
|
|
168
172
|
alert(`Form submit: \n${formData}`);
|
|
169
173
|
state.data = { ...state.data, ...action.data };
|
|
@@ -177,4 +181,4 @@ function datetimeLocal(date: Date) {
|
|
|
177
181
|
return date.toISOString().slice(0, 16);
|
|
178
182
|
}
|
|
179
183
|
|
|
180
|
-
happ<
|
|
184
|
+
happ<State, Actions>(state, view, dispatcher);
|
|
@@ -1,45 +1,45 @@
|
|
|
1
|
-
import { HElement
|
|
2
|
-
import { HApp,
|
|
1
|
+
import { HElement } from "../src/hsml";
|
|
2
|
+
import { HApp, HAppActions, HDispatcher, HState, HView, HView1, happ } from "../src/hsml-app";
|
|
3
3
|
|
|
4
4
|
interface CounterState {
|
|
5
5
|
count: number;
|
|
6
6
|
}
|
|
7
7
|
|
|
8
|
-
enum
|
|
8
|
+
enum CounterActions {
|
|
9
9
|
dec = "counter-dec",
|
|
10
10
|
inc = "counter-inc"
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
-
const counterView: HView1<CounterState> = (state
|
|
13
|
+
const counterView: HView1<CounterState, CounterActions> = (state) => {
|
|
14
14
|
return ["div~reference", [
|
|
15
15
|
["h2", ["Counter"]],
|
|
16
16
|
["p", [
|
|
17
17
|
["em", ["Count"]], ": ", state.count,
|
|
18
18
|
" ",
|
|
19
|
-
["button", { on: ["click",
|
|
20
|
-
["button", { on: ["click",
|
|
19
|
+
["button", { on: ["click", CounterActions.dec, 1] }, ["-"]],
|
|
20
|
+
["button", { on: ["click", CounterActions.inc, 2] }, ["+"]]
|
|
21
21
|
]]
|
|
22
22
|
]];
|
|
23
23
|
};
|
|
24
24
|
|
|
25
|
-
const counterDispatcher: HDispatcher<CounterState> = async function (this: HApp<CounterState>, action, state, dispatch) {
|
|
25
|
+
const counterDispatcher: HDispatcher<CounterState, CounterActions> = async function (this: HApp<CounterState, CounterActions>, action, state, dispatch) {
|
|
26
26
|
console.log("action counter:", action);
|
|
27
27
|
// console.log("state counter:", state);
|
|
28
28
|
// console.log("happ counter:", this);
|
|
29
29
|
|
|
30
30
|
switch (action.type) {
|
|
31
|
-
case
|
|
31
|
+
case HAppActions.mount:
|
|
32
32
|
this.windowDispatchOn();
|
|
33
33
|
break;
|
|
34
|
-
case
|
|
34
|
+
case HAppActions.umount:
|
|
35
35
|
this.windowDispatchOff();
|
|
36
36
|
break;
|
|
37
37
|
|
|
38
|
-
case
|
|
38
|
+
case CounterActions.inc:
|
|
39
39
|
state.count = state.count + action.data as number;
|
|
40
|
-
setTimeout(() => dispatch(
|
|
40
|
+
setTimeout(() => dispatch(CounterActions.dec, 1), 1e3); // async call
|
|
41
41
|
break;
|
|
42
|
-
case
|
|
42
|
+
case CounterActions.dec:
|
|
43
43
|
state.count = state.count - action.data as number;
|
|
44
44
|
break;
|
|
45
45
|
}
|
|
@@ -51,7 +51,7 @@ interface State {
|
|
|
51
51
|
x?: boolean | Boolean;
|
|
52
52
|
}
|
|
53
53
|
|
|
54
|
-
enum
|
|
54
|
+
enum Actions {
|
|
55
55
|
title = "title",
|
|
56
56
|
clear = "clear",
|
|
57
57
|
formSubmit = "formSubmit",
|
|
@@ -69,7 +69,7 @@ const state: HState<State> = function () {
|
|
|
69
69
|
};
|
|
70
70
|
};
|
|
71
71
|
|
|
72
|
-
const view: HView<State> = function (state
|
|
72
|
+
const view: HView<State, Actions | CounterActions> = function (state) {
|
|
73
73
|
return [
|
|
74
74
|
["h2", [state.title]],
|
|
75
75
|
["p", [
|
|
@@ -79,13 +79,13 @@ const view: HView<State> = function (state: State): HElements {
|
|
|
79
79
|
type: "text",
|
|
80
80
|
// name: "title",
|
|
81
81
|
value: new String(state.title),
|
|
82
|
-
on: ["input",
|
|
82
|
+
on: ["input", Actions.title]
|
|
83
83
|
}
|
|
84
84
|
], " ",
|
|
85
85
|
["button.w3-button.w3-blue",
|
|
86
86
|
{
|
|
87
87
|
type: "button",
|
|
88
|
-
on: ["click",
|
|
88
|
+
on: ["click", Actions.clear]
|
|
89
89
|
},
|
|
90
90
|
["Clear title"]
|
|
91
91
|
]
|
|
@@ -95,8 +95,8 @@ const view: HView<State> = function (state: State): HElements {
|
|
|
95
95
|
["form",
|
|
96
96
|
{
|
|
97
97
|
on: [
|
|
98
|
-
["submit",
|
|
99
|
-
["change",
|
|
98
|
+
["submit", Actions.formSubmit],
|
|
99
|
+
["change", Actions.formChange]
|
|
100
100
|
]
|
|
101
101
|
},
|
|
102
102
|
[
|
|
@@ -137,13 +137,13 @@ const view: HView<State> = function (state: State): HElements {
|
|
|
137
137
|
"s ",
|
|
138
138
|
["select", { name: "s" },
|
|
139
139
|
["s1", "s2", "s3"]
|
|
140
|
-
.map<HElement
|
|
140
|
+
.map<HElement<Actions>>(l => ["option", { value: l }, [l]])
|
|
141
141
|
],
|
|
142
142
|
["br"],
|
|
143
143
|
"sm ",
|
|
144
144
|
["select", { name: "sm", multiple: true },
|
|
145
145
|
["sm1", "sm2", "sm3"]
|
|
146
|
-
.map<HElement
|
|
146
|
+
.map<HElement<Actions>>(l => ["option", { value: l }, [l]])
|
|
147
147
|
],
|
|
148
148
|
["br"],
|
|
149
149
|
["textarea", { name: "ta" },
|
|
@@ -157,10 +157,10 @@ const view: HView<State> = function (state: State): HElements {
|
|
|
157
157
|
],
|
|
158
158
|
["h2", ["Action event"]],
|
|
159
159
|
["p", [
|
|
160
|
-
["button", { on: ["click",
|
|
160
|
+
["button", { on: ["click", Actions.xXx] }, ["xXx"]]
|
|
161
161
|
]],
|
|
162
162
|
["h2", ["Props update"]],
|
|
163
|
-
["input", { type: "checkbox", name: "x", on: ["change",
|
|
163
|
+
["input", { type: "checkbox", name: "x", on: ["change", Actions.x] }],
|
|
164
164
|
["input", { type: "checkbox", checked: state.x }],
|
|
165
165
|
["input", { type: "radio", name: "y", checked: state.x }],
|
|
166
166
|
["input", { type: "radio", name: "y", checked: !state.x }],
|
|
@@ -168,7 +168,7 @@ const view: HView<State> = function (state: State): HElements {
|
|
|
168
168
|
];
|
|
169
169
|
};
|
|
170
170
|
|
|
171
|
-
const dispatcher: HDispatcher<State> = async function (this: HApp<State>, action, state, dispatch) {
|
|
171
|
+
const dispatcher: HDispatcher<State, Actions | CounterActions> = async function (this: HApp<State, Actions>, action, state, dispatch) {
|
|
172
172
|
console.log("action:", action);
|
|
173
173
|
// console.log("state:", state);
|
|
174
174
|
// console.log("happ:", this);
|
|
@@ -176,30 +176,29 @@ const dispatcher: HDispatcher<State> = async function (this: HApp<State>, action
|
|
|
176
176
|
counterDispatcher.call(this, action, state.counter, dispatch);
|
|
177
177
|
|
|
178
178
|
switch (action.type) {
|
|
179
|
-
case
|
|
180
|
-
case
|
|
181
|
-
case
|
|
179
|
+
case HAppActions.init:
|
|
180
|
+
case HAppActions.mount:
|
|
181
|
+
case HAppActions.umount:
|
|
182
182
|
break;
|
|
183
|
-
case
|
|
183
|
+
case Actions.title:
|
|
184
184
|
state.title = action.data;
|
|
185
185
|
break;
|
|
186
|
-
case
|
|
186
|
+
case Actions.clear:
|
|
187
187
|
state.title = "";
|
|
188
188
|
break;
|
|
189
|
-
case
|
|
189
|
+
case Actions.formSubmit:
|
|
190
190
|
console.log("FormSubmit:", JSON.stringify(action.data));
|
|
191
191
|
const fe = action.event!.target as HTMLFormElement;
|
|
192
192
|
const fd = new FormData(fe);
|
|
193
193
|
console.log("FormData:", JSON.stringify([...fd.entries()]));
|
|
194
194
|
break;
|
|
195
|
-
case
|
|
195
|
+
case Actions.formChange:
|
|
196
196
|
console.log("FormChange:", JSON.stringify(action.data));
|
|
197
197
|
break;
|
|
198
|
-
case
|
|
199
|
-
|
|
200
|
-
this.windowDispatch(CounterAction.dec, 1);
|
|
198
|
+
case Actions.xXx:
|
|
199
|
+
dispatch(CounterActions.dec, 1, "window");
|
|
201
200
|
break;
|
|
202
|
-
case
|
|
201
|
+
case Actions.x:
|
|
203
202
|
console.log("data.x", typeof action.data.x, action.data.x);
|
|
204
203
|
// state.x = new Boolean(action.data.x === "true");
|
|
205
204
|
// state.x = action.data.x === "true";
|
|
@@ -214,8 +213,8 @@ const dispatcher: HDispatcher<State> = async function (this: HApp<State>, action
|
|
|
214
213
|
// HApp.debug = true;
|
|
215
214
|
HApp.debug = window.location.hostname === "localhost";
|
|
216
215
|
|
|
217
|
-
const app = happ<State>(state, view, dispatcher)
|
|
218
|
-
.onDispatch(async (action, state, dispatch) => console.log("onDspatch:", action, state))
|
|
216
|
+
const app = happ<State, Actions | CounterActions>(state, view, dispatcher)
|
|
217
|
+
// .onDispatch(async (action, state, dispatch) => console.log("onDspatch:", action, state))
|
|
219
218
|
.mount(document.getElementById("app"));
|
|
220
219
|
|
|
221
220
|
(self as any).app = app;
|
|
@@ -5,14 +5,15 @@ const NBSP = "\u00A0";
|
|
|
5
5
|
const CIRC = "\u25EF";
|
|
6
6
|
const CROS = "\u2A2F";
|
|
7
7
|
|
|
8
|
-
interface
|
|
8
|
+
interface State {
|
|
9
9
|
board: string[][];
|
|
10
10
|
turn: number;
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
-
const enum
|
|
13
|
+
const enum Actions {
|
|
14
14
|
mark = "mark",
|
|
15
|
-
reset = "reset"
|
|
15
|
+
reset = "reset",
|
|
16
|
+
noop = "noop"
|
|
16
17
|
}
|
|
17
18
|
|
|
18
19
|
const boardInit = () => [
|
|
@@ -21,14 +22,14 @@ const boardInit = () => [
|
|
|
21
22
|
[NBSP, NBSP, NBSP]
|
|
22
23
|
];
|
|
23
24
|
|
|
24
|
-
function state():
|
|
25
|
+
function state(): State {
|
|
25
26
|
return {
|
|
26
27
|
board: boardInit(),
|
|
27
28
|
turn: 0
|
|
28
29
|
};
|
|
29
30
|
}
|
|
30
31
|
|
|
31
|
-
function view(state:
|
|
32
|
+
function view(state: State): HElements<Actions> {
|
|
32
33
|
return [
|
|
33
34
|
["div.w3-content", [
|
|
34
35
|
["h1", ["Tic-Tac-Toe Demo"]],
|
|
@@ -36,8 +37,8 @@ function view(state: TicTacToeState): HElements {
|
|
|
36
37
|
["p.w3-xlarge", [
|
|
37
38
|
"Player: ", state.turn ? CROS : CIRC,
|
|
38
39
|
]],
|
|
39
|
-
["div", state.board.map<HElement
|
|
40
|
-
["div", row.map<HElement
|
|
40
|
+
["div", state.board.map<HElement<Actions>>((row, y) =>
|
|
41
|
+
["div", row.map<HElement<Actions>>((col, x) =>
|
|
41
42
|
["button.w3-button.w3-white.w3-border.w3-border-gray",
|
|
42
43
|
{
|
|
43
44
|
styles: {
|
|
@@ -48,38 +49,38 @@ function view(state: TicTacToeState): HElements {
|
|
|
48
49
|
height: "2em"
|
|
49
50
|
},
|
|
50
51
|
on: (col === NBSP)
|
|
51
|
-
? ["click",
|
|
52
|
-
: ["click",
|
|
52
|
+
? ["click", Actions.mark, { x, y, turn: state.turn }]
|
|
53
|
+
: ["click", Actions.noop]
|
|
53
54
|
},
|
|
54
55
|
col
|
|
55
56
|
])
|
|
56
57
|
])
|
|
57
58
|
],
|
|
58
59
|
["p", [
|
|
59
|
-
["button.w3-button.w3-blue", { on: ["click",
|
|
60
|
+
["button.w3-button.w3-blue", { on: ["click", Actions.reset] }, "Reset"]
|
|
60
61
|
]]
|
|
61
62
|
]]
|
|
62
63
|
]]
|
|
63
64
|
];
|
|
64
65
|
}
|
|
65
66
|
|
|
66
|
-
|
|
67
|
+
|
|
68
|
+
async function dispatcher(action: HAction<Actions>, state: State, dispatch: HDispatch<Actions>): Promise<void> {
|
|
67
69
|
console.log("action", action);
|
|
68
70
|
|
|
69
71
|
switch (action.type) {
|
|
70
72
|
|
|
71
|
-
case
|
|
73
|
+
case Actions.reset:
|
|
72
74
|
state.board = boardInit();
|
|
73
75
|
break;
|
|
74
76
|
|
|
75
|
-
case
|
|
77
|
+
case Actions.mark:
|
|
76
78
|
state.board[action.data.y][action.data.x] = action.data.turn ? CROS : CIRC;
|
|
77
79
|
state.turn = action.data.turn ? 0 : 1;
|
|
78
80
|
break;
|
|
79
81
|
}
|
|
80
82
|
}
|
|
81
83
|
|
|
82
|
-
const app = happ<
|
|
84
|
+
const app = happ<State, Actions>(state, view, dispatcher);
|
|
83
85
|
|
|
84
86
|
(self as any).app = app;
|
|
85
|
-
|