peryl 1.5.2 → 1.5.4
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 +31 -17
- package/demo/hsml-app-form-validation_demo.html +1 -0
- package/demo/hsml-app-form-validation_demo.ts +22 -23
- package/demo/hsml-app-form_demo.html +1 -0
- package/demo/hsml-app-form_demo.ts +24 -20
- package/demo/hsml-app-test_demo.ts +36 -41
- package/demo/hsml-app-tictactoe_demo.ts +17 -16
- package/demo/hsml-app_demo.html +1 -0
- package/demo/hsml-app_demo.ts +16 -16
- package/demo/hsml-appel_demo.html +7 -0
- package/demo/hsml-appel_demo.ts +47 -27
- package/demo/hsml-appi_demo.ts +15 -22
- package/demo/hsml_demo.ts +27 -22
- package/demo/js/hsml-app-js-happi_demo.html +28 -21
- package/demo/js/hsml-app-js_demo.html +15 -17
- package/dist/browser-esmodule/encode.js.map +1 -1
- package/dist/browser-esmodule/hsml-app.js +114 -123
- 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 +118 -127
- 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.8e406f15.js +2 -0
- package/dist/demo/hsml-app-form-validation_demo.8e406f15.js.map +1 -0
- package/dist/demo/hsml-app-form-validation_demo.9a95cff3.js +2 -0
- package/dist/demo/hsml-app-form-validation_demo.9a95cff3.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.950b2a09.js +2 -0
- package/dist/demo/hsml-app-form_demo.950b2a09.js.map +1 -0
- package/dist/demo/hsml-app-form_demo.ea3af725.js +2 -0
- package/dist/demo/hsml-app-form_demo.ea3af725.js.map +1 -0
- package/dist/demo/hsml-app-form_demo.html +1 -1
- package/dist/demo/hsml-app-test_demo.36a210b8.js +2 -0
- package/dist/demo/hsml-app-test_demo.36a210b8.js.map +1 -0
- package/dist/demo/hsml-app-test_demo.6ab4ea94.js +2 -0
- package/dist/demo/hsml-app-test_demo.6ab4ea94.js.map +1 -0
- package/dist/demo/hsml-app-test_demo.html +1 -1
- package/dist/demo/hsml-app-tictactoe_demo.7a91c368.js +2 -0
- package/dist/demo/hsml-app-tictactoe_demo.7a91c368.js.map +1 -0
- package/dist/demo/hsml-app-tictactoe_demo.97905c2f.js +2 -0
- package/dist/demo/hsml-app-tictactoe_demo.97905c2f.js.map +1 -0
- package/dist/demo/hsml-app-tictactoe_demo.html +1 -1
- package/dist/demo/hsml-app_demo.b5c1d27d.js +2 -0
- package/dist/demo/hsml-app_demo.b5c1d27d.js.map +1 -0
- package/dist/demo/hsml-app_demo.bbebbbcf.js +2 -0
- package/dist/demo/hsml-app_demo.bbebbbcf.js.map +1 -0
- package/dist/demo/hsml-app_demo.html +1 -1
- package/dist/demo/hsml-appel_demo.4d9e135c.js +2 -0
- package/dist/demo/hsml-appel_demo.4d9e135c.js.map +1 -0
- package/dist/demo/hsml-appel_demo.7ddb6fb3.js +2 -0
- package/dist/demo/hsml-appel_demo.7ddb6fb3.js.map +1 -0
- package/dist/demo/hsml-appel_demo.html +1 -1
- package/dist/demo/hsml-appi_demo.e5e28a65.js +2 -0
- package/dist/demo/hsml-appi_demo.e5e28a65.js.map +1 -0
- package/dist/demo/hsml-appi_demo.fef950c1.js +2 -0
- package/dist/demo/hsml-appi_demo.fef950c1.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 +63 -42
- package/dist/hsml-app.js +110 -117
- 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 +305 -197
- 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/src/hsml-app.ts
CHANGED
|
@@ -5,31 +5,60 @@ const log = console.log;
|
|
|
5
5
|
const error = console.error;
|
|
6
6
|
const warn = console.warn;
|
|
7
7
|
|
|
8
|
-
export type HState<
|
|
9
|
-
|
|
10
|
-
export type
|
|
8
|
+
export type HState<State> = () => State;
|
|
9
|
+
|
|
10
|
+
export type HView<State, HActionType extends string> = (
|
|
11
|
+
state: State
|
|
12
|
+
) => HElements<HActionType>;
|
|
13
|
+
|
|
14
|
+
export type HView1<State, HActionType extends string> = (
|
|
15
|
+
state: State
|
|
16
|
+
) => HElement<HActionType>;
|
|
17
|
+
|
|
18
|
+
export type HAppActionType =
|
|
19
|
+
| "happ-init"
|
|
20
|
+
| "happ-mount"
|
|
21
|
+
| "happ-umount"
|
|
22
|
+
| "happ-update"
|
|
23
|
+
| "happ-action"
|
|
24
|
+
| "happ-attribute";
|
|
25
|
+
|
|
26
|
+
export enum HAppActions {
|
|
27
|
+
init = "happ-init",
|
|
28
|
+
mount = "happ-mount",
|
|
29
|
+
umount = "happ-umount",
|
|
30
|
+
update = "happ-update",
|
|
31
|
+
action = "happ-action",
|
|
32
|
+
attribute = "happ-attribute"
|
|
33
|
+
}
|
|
11
34
|
|
|
12
|
-
export interface HAction {
|
|
13
|
-
type:
|
|
35
|
+
export interface HAction<HActionType extends string> {
|
|
36
|
+
type: HActionType | HAppActionType | HAppActions;
|
|
14
37
|
data?: any;
|
|
15
38
|
event?: Event;
|
|
16
39
|
}
|
|
17
40
|
|
|
18
|
-
export type
|
|
19
|
-
|
|
20
|
-
|
|
41
|
+
export type HDispatchScope =
|
|
42
|
+
| "element"
|
|
43
|
+
| "window";
|
|
21
44
|
|
|
22
|
-
export
|
|
45
|
+
export enum HDispatchScopes {
|
|
46
|
+
element = "element",
|
|
47
|
+
window = "window"
|
|
48
|
+
}
|
|
23
49
|
|
|
24
|
-
export type
|
|
25
|
-
|
|
50
|
+
export type HDispatch<HActionType extends string> = (
|
|
51
|
+
type: HAction<HActionType>["type"],
|
|
52
|
+
data?: HAction<HActionType>["data"],
|
|
53
|
+
scope?: HDispatchScope | HDispatchScopes
|
|
54
|
+
) => Promise<void>;
|
|
26
55
|
|
|
27
|
-
export
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
56
|
+
export type HDispatcher<State, HActionType extends string> = (
|
|
57
|
+
// this: HApp<State, HActionType>,
|
|
58
|
+
action: HAction<HActionType>,
|
|
59
|
+
state: State,
|
|
60
|
+
dispatch: HDispatch<HActionType>
|
|
61
|
+
) => Promise<void>;
|
|
33
62
|
|
|
34
63
|
const schedule = window.requestAnimationFrame ||
|
|
35
64
|
// window.webkitRequestAnimationFrame ||
|
|
@@ -45,164 +74,254 @@ const unschedule = window.cancelAnimationFrame ||
|
|
|
45
74
|
// (window as any).msCancelAnimationFrame ||
|
|
46
75
|
function (handle: number) { window.clearTimeout(handle); };
|
|
47
76
|
|
|
48
|
-
const msgAction = "
|
|
49
|
-
const msgDispatch = "
|
|
50
|
-
const msgRender = "
|
|
51
|
-
const msgUpdate = "
|
|
52
|
-
|
|
53
|
-
export function happ<STATE>(state: HState<STATE>,
|
|
54
|
-
view: HView<STATE>,
|
|
55
|
-
dispatcher: HDispatcher<STATE>,
|
|
56
|
-
element: Element | string | null = document.body) {
|
|
57
|
-
return new HApp<STATE>(state, view, dispatcher, element);
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
// HAppI
|
|
77
|
+
const msgAction = "action:";
|
|
78
|
+
const msgDispatch = "dispatch:";
|
|
79
|
+
const msgRender = "render:";
|
|
80
|
+
const msgUpdate = "update:";
|
|
61
81
|
|
|
62
|
-
|
|
82
|
+
const HAPP = "happ";
|
|
63
83
|
|
|
64
|
-
export interface HAppI<
|
|
65
|
-
state
|
|
66
|
-
view
|
|
67
|
-
dispatcher
|
|
68
|
-
|
|
84
|
+
export interface HAppI<State, HActionType extends string> {
|
|
85
|
+
state: HState<State>;
|
|
86
|
+
view: HView<State, HActionType>;
|
|
87
|
+
dispatcher: HDispatcher<State, HActionType>;
|
|
88
|
+
element?: Element | string | null;
|
|
89
|
+
debug?: boolean;
|
|
90
|
+
name?: string;
|
|
91
|
+
attributes?: string[];
|
|
69
92
|
}
|
|
70
93
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
94
|
+
/**
|
|
95
|
+
* HApp definition
|
|
96
|
+
*
|
|
97
|
+
* @param hAppI HApp definition
|
|
98
|
+
* @returns HApp instance
|
|
99
|
+
*/
|
|
100
|
+
export function happ<State, HActionType extends string>(hAppI: {
|
|
101
|
+
state: HState<State>;
|
|
102
|
+
view: HView<State, HActionType>;
|
|
103
|
+
dispatcher: HDispatcher<State, HActionType>;
|
|
104
|
+
element: Element | string | null;
|
|
105
|
+
debug?: boolean;
|
|
106
|
+
name?: string;
|
|
107
|
+
// attributes?: string[];
|
|
108
|
+
}) {
|
|
109
|
+
return new HApp<State, HActionType>(
|
|
110
|
+
hAppI.state,
|
|
111
|
+
hAppI.view,
|
|
112
|
+
hAppI.dispatcher,
|
|
113
|
+
hAppI.element,
|
|
114
|
+
hAppI.debug,
|
|
115
|
+
hAppI.name
|
|
116
|
+
// hAppI!.attributes
|
|
117
|
+
);
|
|
74
118
|
}
|
|
75
119
|
|
|
76
|
-
//
|
|
77
|
-
|
|
78
|
-
export function
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
120
|
+
// export type Class<T = object> = new (...args: any[]) => T;
|
|
121
|
+
|
|
122
|
+
// export function happi<State, HActionType extends string>(
|
|
123
|
+
// hAppI: Class<HAppI<State, HActionType>>,
|
|
124
|
+
// element?: Element | string | null,
|
|
125
|
+
// debug? boolean,
|
|
126
|
+
// name?: string,
|
|
127
|
+
// attributes: string[]
|
|
128
|
+
// ) {
|
|
129
|
+
// const hapi = new hAppI();
|
|
130
|
+
// return new HApp<State, HActionType>(
|
|
131
|
+
// hapi.state,
|
|
132
|
+
// hapi.view,
|
|
133
|
+
// hapi.dispatcher,
|
|
134
|
+
// element,
|
|
135
|
+
// debug
|
|
136
|
+
// );
|
|
137
|
+
// }
|
|
84
138
|
|
|
85
|
-
|
|
86
|
-
return elementAttrs;
|
|
87
|
-
}
|
|
139
|
+
// HAppEl
|
|
88
140
|
|
|
89
|
-
|
|
141
|
+
/**
|
|
142
|
+
* HApp custom HTML element definition.
|
|
143
|
+
*
|
|
144
|
+
* @param hAppI HApp definition
|
|
145
|
+
*/
|
|
146
|
+
export function happel<State, HActionType extends string>(hAppI: {
|
|
147
|
+
state: HState<State>;
|
|
148
|
+
view: HView<State, HActionType>;
|
|
149
|
+
dispatcher: HDispatcher<State, HActionType>;
|
|
150
|
+
/** Element suffix name, element name patern is `happ-${name}` */
|
|
151
|
+
name: string;
|
|
152
|
+
/** Element attribute list */
|
|
153
|
+
attributes: string[];
|
|
154
|
+
debug?: boolean;
|
|
155
|
+
}): void {
|
|
156
|
+
customElements.define(
|
|
157
|
+
`${HAPP}-${hAppI.name}`,
|
|
158
|
+
class HAppElement extends HTMLElement {
|
|
159
|
+
static get observedAttributes() {
|
|
160
|
+
return hAppI.attributes;
|
|
161
|
+
}
|
|
90
162
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
163
|
+
private _happel: HApp<State, HActionType>;
|
|
164
|
+
|
|
165
|
+
constructor() {
|
|
166
|
+
super();
|
|
167
|
+
this._happel = new HApp<State, HActionType>(
|
|
168
|
+
hAppI.state,
|
|
169
|
+
hAppI.view,
|
|
170
|
+
hAppI.dispatcher,
|
|
171
|
+
undefined,
|
|
172
|
+
hAppI.debug,
|
|
173
|
+
hAppI.name,
|
|
174
|
+
hAppI.attributes
|
|
175
|
+
);
|
|
176
|
+
(this._happel as any).customElement = this;
|
|
177
|
+
}
|
|
96
178
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
179
|
+
connectedCallback() {
|
|
180
|
+
// this._happel.mount(this);
|
|
181
|
+
this.attachShadow({ mode: "open" });
|
|
182
|
+
this._happel.mount(this.shadowRoot as any);
|
|
183
|
+
}
|
|
102
184
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
185
|
+
disconnectedCallback() {
|
|
186
|
+
this._happel.umount();
|
|
187
|
+
}
|
|
106
188
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
189
|
+
adoptedCallback() {
|
|
190
|
+
this._happel.update();
|
|
191
|
+
}
|
|
110
192
|
|
|
111
|
-
|
|
112
|
-
|
|
193
|
+
attributeChangedCallback(
|
|
194
|
+
attrName: string,
|
|
195
|
+
oldVal: string | null,
|
|
196
|
+
newVal: string | null
|
|
197
|
+
) {
|
|
198
|
+
this._happel.dispatch(HAppActions.attribute, {
|
|
199
|
+
attrName,
|
|
200
|
+
oldVal,
|
|
201
|
+
newVal,
|
|
202
|
+
});
|
|
203
|
+
}
|
|
113
204
|
}
|
|
114
|
-
|
|
115
|
-
});
|
|
205
|
+
);
|
|
116
206
|
}
|
|
117
207
|
|
|
118
|
-
|
|
208
|
+
/**
|
|
209
|
+
* HSML App
|
|
210
|
+
*/
|
|
211
|
+
export class HApp<State, HActionType extends string> implements HHandlerCtx<HActionType> {
|
|
119
212
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
export type HControllers<State, TypeofActionEnum> = { [actionType in keyof TypeofActionEnum]?: HController<State>; };
|
|
125
|
-
|
|
126
|
-
export function controllersDdispatcher<State, TyopeofActionEnum>(controllers: HControllers<State, TyopeofActionEnum>): HDispatcher<State> {
|
|
127
|
-
return async function (this: HApp<State>, action) {
|
|
128
|
-
const controller = controllers[action.type as keyof TyopeofActionEnum];
|
|
129
|
-
if (controller) {
|
|
130
|
-
controller.apply<HApp<State>, [any?, Event?], void>(this, [action.data, action.event]);
|
|
131
|
-
} else {
|
|
132
|
-
warn("no controller for action", action);
|
|
133
|
-
}
|
|
134
|
-
};
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
const HAPP = "happ";
|
|
213
|
+
readonly state: State;
|
|
214
|
+
readonly view: HView<State, HActionType>;
|
|
215
|
+
readonly dispatcher: HDispatcher<State, HActionType>;
|
|
138
216
|
|
|
139
|
-
|
|
217
|
+
debug: boolean;
|
|
140
218
|
|
|
141
|
-
|
|
219
|
+
readonly name: string;
|
|
220
|
+
readonly attributes: string[];
|
|
142
221
|
|
|
143
|
-
readonly
|
|
144
|
-
readonly
|
|
145
|
-
readonly dispatcher: HDispatcher<STATE>;
|
|
222
|
+
readonly element?: HTMLElement;
|
|
223
|
+
readonly refs: { [key: string]: HTMLElement } = {};
|
|
146
224
|
|
|
147
225
|
readonly customElement?: HTMLElement; // happ custom html element
|
|
148
226
|
|
|
149
|
-
readonly dom?: HTMLElement;
|
|
150
|
-
readonly refs: { [key: string]: HTMLElement } = {};
|
|
151
|
-
|
|
152
227
|
private _updateSched?: number;
|
|
153
228
|
|
|
154
|
-
private _onDispatch?: HDispatcher<
|
|
229
|
+
// private _onDispatch?: HDispatcher<State>;
|
|
155
230
|
|
|
156
231
|
private _windowEventListener?: (event: Event) => void;
|
|
157
232
|
|
|
158
|
-
constructor(
|
|
233
|
+
constructor(
|
|
234
|
+
state: HState<State>,
|
|
235
|
+
view: HView<State, HActionType>,
|
|
236
|
+
dispatcher?: HDispatcher<State, HActionType>,
|
|
237
|
+
element?: Element | string | null,
|
|
238
|
+
debug?: boolean ,
|
|
239
|
+
name?: string,
|
|
240
|
+
attributes?: string[]
|
|
241
|
+
) {
|
|
242
|
+
this.debug = debug ?? false;
|
|
243
|
+
this.name = name ?? HAPP;
|
|
244
|
+
this.attributes = attributes ?? [];
|
|
159
245
|
this.state = state();
|
|
160
246
|
this.view = view;
|
|
161
|
-
this.dispatcher = dispatcher ?? (async (a) => log(msgAction, a.type, a.data));
|
|
162
|
-
this.
|
|
247
|
+
this.dispatcher = dispatcher ?? (async (a) => log(this.name, msgAction, a.type, a.data));
|
|
248
|
+
this._dispatchAction(HAppActions.init, this).then(() => element && this.mount(element));
|
|
163
249
|
}
|
|
164
250
|
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
!this.customElement && this.dom && elementDispatchCustomEvent(this.dom, type, data);
|
|
172
|
-
this.update();
|
|
173
|
-
} catch (e) {
|
|
174
|
-
error(msgDispatch, e);
|
|
175
|
-
}
|
|
251
|
+
dispatch: HDispatch<HActionType> = async (
|
|
252
|
+
type: HActionType | HAppActionType,
|
|
253
|
+
data?: any,
|
|
254
|
+
scope?: HDispatchScope
|
|
255
|
+
): Promise<void> => {
|
|
256
|
+
return this._dispatchAction(type, data, undefined, scope);
|
|
176
257
|
}
|
|
177
258
|
|
|
178
|
-
onDispatch = (dispatcher: HDispatcher<
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
259
|
+
// onDispatch = (dispatcher: HDispatcher<State>): this => {
|
|
260
|
+
// this._onDispatch = dispatcher;
|
|
261
|
+
// return this;
|
|
262
|
+
// }
|
|
263
|
+
|
|
264
|
+
private async _dispatchAction(
|
|
265
|
+
type: HActionType | HAppActionType,
|
|
266
|
+
data?: any,
|
|
267
|
+
event?: Event,
|
|
268
|
+
scope?: HDispatchScope
|
|
269
|
+
): Promise<void> {
|
|
270
|
+
if (this.debug) {
|
|
271
|
+
log(this.name, msgAction, { type, data, event });
|
|
186
272
|
const t0 = performance.now();
|
|
187
|
-
await this._dispatch(type, data, event);
|
|
273
|
+
await this._dispatch(type, data, event, scope);
|
|
188
274
|
const t1 = performance.now();
|
|
189
|
-
log(msgDispatch, `${t1 - t0} ms`, this.state);
|
|
275
|
+
log(this.name, msgDispatch, `${t1 - t0} ms`, this.state);
|
|
190
276
|
} else {
|
|
191
|
-
await this._dispatch(type, data, event);
|
|
277
|
+
await this._dispatch(type, data, event, scope);
|
|
192
278
|
}
|
|
193
279
|
}
|
|
194
280
|
|
|
195
|
-
|
|
196
|
-
|
|
281
|
+
private async _dispatch(
|
|
282
|
+
type: HActionType | HAppActionType,
|
|
283
|
+
data: any,
|
|
284
|
+
event?: Event,
|
|
285
|
+
scope?: HDispatchScope
|
|
286
|
+
) {
|
|
287
|
+
try {
|
|
288
|
+
await this.dispatcher(
|
|
289
|
+
{ type: type as HActionType, data, event },
|
|
290
|
+
this.state,
|
|
291
|
+
this.dispatch
|
|
292
|
+
);
|
|
293
|
+
this.update();
|
|
294
|
+
scope === "element" && this._dispatchElement(type, data);
|
|
295
|
+
scope === "window" && this._dispatchWindow(type, data);
|
|
296
|
+
} catch (e) {
|
|
297
|
+
error(this.name, msgDispatch, e);
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
private _dispatchElement: HDispatch<HActionType> = async (
|
|
302
|
+
type: HActionType | HAppActionType,
|
|
303
|
+
data?: any
|
|
304
|
+
): Promise<void> => {
|
|
305
|
+
this.customElement && elementDispatchCustomEvent(this.customElement, HAppActions.action, { type, data });
|
|
306
|
+
!this.customElement && this.element && elementDispatchCustomEvent(this.element, HAppActions.action, { type, data });
|
|
307
|
+
// this.customElement && elementDispatchCustomEvent(this.customElement, type, data);
|
|
308
|
+
// !this.customElement && this.element && elementDispatchCustomEvent(this.element, type, data);
|
|
309
|
+
// this._onDispatch?.({ type, data, event }, this.state, this.dispatch);
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
private _dispatchWindow: HDispatch<HActionType> = async (
|
|
313
|
+
type: HActionType | HAppActionType,
|
|
314
|
+
data?: any): Promise<void> => {
|
|
315
|
+
window.dispatchEvent(new CustomEvent(HAppActions.action, { detail: { type, data } }));
|
|
197
316
|
}
|
|
198
317
|
|
|
199
318
|
windowDispatchOn() {
|
|
200
319
|
if (!this._windowEventListener) {
|
|
201
320
|
this._windowEventListener = (event: Event) => {
|
|
202
|
-
const action = (event as CustomEvent).detail as HAction
|
|
203
|
-
this.
|
|
321
|
+
const action = (event as CustomEvent).detail as HAction<HActionType>;
|
|
322
|
+
this._dispatchAction(action.type, action.data);
|
|
204
323
|
};
|
|
205
|
-
window.addEventListener(
|
|
324
|
+
window.addEventListener(HAppActions.action, this._windowEventListener);
|
|
206
325
|
} else {
|
|
207
326
|
warn("windowEventListener olready setted");
|
|
208
327
|
}
|
|
@@ -210,34 +329,34 @@ export class HApp<STATE> implements HHandlerCtx {
|
|
|
210
329
|
|
|
211
330
|
windowDispatchOff() {
|
|
212
331
|
if (this._windowEventListener) {
|
|
213
|
-
window.removeEventListener(
|
|
332
|
+
window.removeEventListener(HAppActions.action, this._windowEventListener);
|
|
214
333
|
}
|
|
215
334
|
}
|
|
216
335
|
|
|
217
|
-
render = (): HElements => {
|
|
218
|
-
if (
|
|
336
|
+
render = (): HElements<HActionType> => {
|
|
337
|
+
if (this.debug) {
|
|
219
338
|
const t0 = performance.now();
|
|
220
339
|
let hsmls;
|
|
221
340
|
try {
|
|
222
341
|
hsmls = this.view(this.state);
|
|
223
342
|
} catch (e) {
|
|
224
|
-
error(msgRender, e);
|
|
343
|
+
error(this.name, msgRender, e);
|
|
225
344
|
}
|
|
226
345
|
const t1 = performance.now();
|
|
227
|
-
log(msgRender, `${t1 - t0} ms`, hsmls);
|
|
346
|
+
log(this.name, msgRender, `${t1 - t0} ms`, hsmls);
|
|
228
347
|
return hsmls ?? [];
|
|
229
348
|
} else {
|
|
230
349
|
let hsmls;
|
|
231
350
|
try {
|
|
232
351
|
hsmls = this.view(this.state);
|
|
233
352
|
} catch (e) {
|
|
234
|
-
error(msgRender, e);
|
|
353
|
+
error(this.name, msgRender, e);
|
|
235
354
|
}
|
|
236
355
|
return hsmls ?? [];
|
|
237
356
|
}
|
|
238
357
|
}
|
|
239
358
|
|
|
240
|
-
actionCb = (
|
|
359
|
+
actionCb = (actionType: HActionType, data: HAttrOnData, event: Event): void => {
|
|
241
360
|
data = (data?.constructor === Function)
|
|
242
361
|
? (data as HAttrOnDataFnc)(event)
|
|
243
362
|
: data;
|
|
@@ -248,53 +367,66 @@ export class HApp<STATE> implements HHandlerCtx {
|
|
|
248
367
|
data = formData(event);
|
|
249
368
|
}
|
|
250
369
|
}
|
|
251
|
-
this.
|
|
370
|
+
this._dispatchAction(actionType, data, event);
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
private _updateDom<HActionType extends string>(
|
|
374
|
+
el: Element,
|
|
375
|
+
hsml: HElements<HActionType>,
|
|
376
|
+
ctx: HHandlerCtx<HActionType>
|
|
377
|
+
): void {
|
|
378
|
+
if (this.debug) {
|
|
379
|
+
const t0 = performance.now();
|
|
380
|
+
hsmls2idomPatch(el, hsml, ctx);
|
|
381
|
+
const t1 = performance.now();
|
|
382
|
+
log(this.name, msgUpdate, `${t1 - t0} ms`, el);
|
|
383
|
+
} else {
|
|
384
|
+
hsmls2idomPatch(el, hsml, ctx);
|
|
385
|
+
}
|
|
252
386
|
}
|
|
253
387
|
|
|
254
|
-
mount = (e: Element | string | null
|
|
255
|
-
const el = (typeof e === "string")
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
if ((el as any)[HAPP]) {
|
|
259
|
-
const a = (el as any)[HAPP] as HApp<STATE>;
|
|
388
|
+
mount = (e: Element | string | null): this => {
|
|
389
|
+
const el = (typeof e === "string") ? document.getElementById(e) : e;
|
|
390
|
+
if (el && (el as any)[HAPP]) {
|
|
391
|
+
const a = (el as any)[HAPP] as HApp<State, HActionType>;
|
|
260
392
|
a.umount();
|
|
261
393
|
}
|
|
262
|
-
if (!this.
|
|
263
|
-
(this as any).
|
|
394
|
+
if (el && !this.element) {
|
|
395
|
+
(this as any).element = el;
|
|
264
396
|
(el as any)[HAPP] = this;
|
|
265
397
|
const hsmls = (this as any).render();
|
|
266
|
-
|
|
267
|
-
this.
|
|
398
|
+
this._updateDom<HActionType>(el, hsmls, this);
|
|
399
|
+
this._dispatchAction(HAppActions.mount, this.element);
|
|
268
400
|
}
|
|
269
401
|
return this;
|
|
270
402
|
}
|
|
271
403
|
|
|
272
404
|
umount = (): this => {
|
|
273
|
-
if (this.
|
|
274
|
-
this.
|
|
275
|
-
if (this.
|
|
276
|
-
this.
|
|
405
|
+
if (this.element) {
|
|
406
|
+
this._dispatchAction(HAppActions.umount, this.element);
|
|
407
|
+
if (this.element.hasAttribute(HAPP)) {
|
|
408
|
+
this.element.removeAttribute(HAPP);
|
|
277
409
|
}
|
|
278
|
-
const aNodes = this.
|
|
410
|
+
const aNodes = this.element.querySelectorAll(`[${HAPP}]`);
|
|
279
411
|
for (let i = 0; i < aNodes.length; i++) {
|
|
280
|
-
const a = (aNodes[i] as any).happ as HApp<
|
|
412
|
+
const a = (aNodes[i] as any).happ as HApp<State, HActionType>;
|
|
281
413
|
a?.umount();
|
|
282
414
|
}
|
|
283
|
-
while (this.
|
|
284
|
-
this.
|
|
415
|
+
while (this.element.firstChild /*.hasChildNodes()*/) {
|
|
416
|
+
this.element.removeChild(this.element.firstChild);
|
|
285
417
|
}
|
|
286
|
-
delete (this.
|
|
287
|
-
(this as any).
|
|
418
|
+
delete (this.element as any).happ;
|
|
419
|
+
(this as any).element = undefined;
|
|
288
420
|
}
|
|
289
421
|
return this;
|
|
290
422
|
}
|
|
291
423
|
|
|
292
424
|
update = (): this => {
|
|
293
|
-
if (this.
|
|
425
|
+
if (this.element && !this._updateSched) {
|
|
294
426
|
this._updateSched = schedule(() => {
|
|
295
|
-
if (this.
|
|
427
|
+
if (this.element) {
|
|
296
428
|
const hsmls = this.render();
|
|
297
|
-
|
|
429
|
+
this._updateDom<HActionType>(this.element, hsmls, this);
|
|
298
430
|
}
|
|
299
431
|
this._updateSched = undefined;
|
|
300
432
|
});
|
|
@@ -302,47 +434,40 @@ export class HApp<STATE> implements HHandlerCtx {
|
|
|
302
434
|
return this;
|
|
303
435
|
}
|
|
304
436
|
|
|
305
|
-
toHsml = (): HElement => {
|
|
306
|
-
if (this.
|
|
437
|
+
toHsml = (): HElement<HActionType> => {
|
|
438
|
+
if (this.element) {
|
|
307
439
|
if (this._updateSched) {
|
|
308
440
|
unschedule(this._updateSched);
|
|
309
441
|
this._updateSched = undefined;
|
|
310
442
|
} else {
|
|
311
|
-
return ["div", {
|
|
443
|
+
return ["div", { skip: true }];
|
|
312
444
|
}
|
|
313
445
|
}
|
|
314
446
|
const hsmls = this.render();
|
|
315
447
|
hsmls.push(
|
|
316
448
|
(e: Element) => {
|
|
317
|
-
if (!this.
|
|
318
|
-
(this as any).
|
|
449
|
+
if (!this.element) {
|
|
450
|
+
(this as any).element = e;
|
|
319
451
|
(e as any).happ = this;
|
|
320
|
-
this.
|
|
452
|
+
this._dispatchAction(HAppActions.mount, this.element);
|
|
321
453
|
}
|
|
322
454
|
});
|
|
323
455
|
return ["div", hsmls];
|
|
324
456
|
}
|
|
325
457
|
|
|
326
458
|
toHtml = (): string => {
|
|
327
|
-
return this.
|
|
459
|
+
return this.element ? this.element.outerHTML : "";
|
|
328
460
|
}
|
|
329
461
|
|
|
330
462
|
}
|
|
331
463
|
|
|
332
|
-
function
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
log(msgUpdate, `${t1 - t0} ms`, el);
|
|
338
|
-
} else {
|
|
339
|
-
hsmls2idomPatch(el, hsml, ctx);
|
|
340
|
-
}
|
|
341
|
-
}
|
|
342
|
-
|
|
343
|
-
function elementDispatchCustomEvent(el: HTMLElement, type: string, data: any) {
|
|
464
|
+
function elementDispatchCustomEvent<HActionType extends string>(
|
|
465
|
+
el: HTMLElement,
|
|
466
|
+
type: HActionType,
|
|
467
|
+
data: any
|
|
468
|
+
) {
|
|
344
469
|
el?.dispatchEvent(new CustomEvent(type, { detail: data }));
|
|
345
|
-
(el as any)[`on${type
|
|
470
|
+
(el as any)[`on${type}`]?.(new CustomEvent(type, { detail: data }));
|
|
346
471
|
}
|
|
347
472
|
|
|
348
473
|
function formData(e: Event): { [k: string]: string | number | boolean | null | Array<string | null> } | string | number | boolean | null | Array<string | null> {
|
|
@@ -491,20 +616,3 @@ function formInputData(el: Element): { [k: string]: string | number | boolean |
|
|
|
491
616
|
}
|
|
492
617
|
return data;
|
|
493
618
|
}
|
|
494
|
-
|
|
495
|
-
// export const formInputData = <STATE>(dispatcher: Actions<STATE>): Actions<STATE> =>
|
|
496
|
-
// (app: App<STATE>, action: string | number, data?: any, event?: Event): void => {
|
|
497
|
-
// if (data === undefined && event) {
|
|
498
|
-
// data = inputEventData(event);
|
|
499
|
-
// }
|
|
500
|
-
// dispatcher(app, action, data, event);
|
|
501
|
-
// };
|
|
502
|
-
|
|
503
|
-
// // Decorator
|
|
504
|
-
// export function FormInputData() {
|
|
505
|
-
// return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
|
|
506
|
-
// const method = descriptor.value;
|
|
507
|
-
// descriptor.value = formInputData(method);
|
|
508
|
-
// return descriptor;
|
|
509
|
-
// };
|
|
510
|
-
// }
|