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.
Files changed (184) hide show
  1. package/README.md +30 -16
  2. package/demo/hsml-app-form-validation_demo.ts +22 -23
  3. package/demo/hsml-app-form_demo.ts +24 -20
  4. package/demo/hsml-app-test_demo.ts +35 -36
  5. package/demo/hsml-app-tictactoe_demo.ts +16 -15
  6. package/demo/hsml-app_demo.ts +20 -12
  7. package/demo/hsml-appel_demo.html +7 -0
  8. package/demo/hsml-appel_demo.ts +33 -25
  9. package/demo/hsml-appi_demo.ts +9 -9
  10. package/demo/hsml_demo.ts +27 -22
  11. package/demo/js/hsml-app-js-happi_demo.html +16 -8
  12. package/demo/js/hsml-app-js_demo.html +15 -15
  13. package/dist/browser-esmodule/encode.js.map +1 -1
  14. package/dist/browser-esmodule/hsml-app.js +67 -73
  15. package/dist/browser-esmodule/hsml-app.js.map +1 -1
  16. package/dist/browser-esmodule/hsml-convert.js.map +1 -1
  17. package/dist/browser-esmodule/hsml-dom.js +3 -3
  18. package/dist/browser-esmodule/hsml-dom.js.map +1 -1
  19. package/dist/browser-esmodule/hsml-h.js.map +1 -1
  20. package/dist/browser-esmodule/hsml-html.js +2 -2
  21. package/dist/browser-esmodule/hsml-html.js.map +1 -1
  22. package/dist/browser-esmodule/hsml-idom.js +5 -5
  23. package/dist/browser-esmodule/hsml-idom.js.map +1 -1
  24. package/dist/browser-esmodule/hsml.js.map +1 -1
  25. package/dist/browser-esmodule/http.js.map +1 -1
  26. package/dist/browser-esmodule/index.js +71 -77
  27. package/dist/browser-esmodule/index.js.map +1 -1
  28. package/dist/browser-esmodule/router.js.map +1 -1
  29. package/dist/browser-umd/encode.js +1 -1
  30. package/dist/browser-umd/encode.js.map +1 -1
  31. package/dist/browser-umd/hsml-app.js +1 -1
  32. package/dist/browser-umd/hsml-app.js.map +1 -1
  33. package/dist/browser-umd/hsml-convert.js.map +1 -1
  34. package/dist/browser-umd/hsml-dom.js +1 -1
  35. package/dist/browser-umd/hsml-dom.js.map +1 -1
  36. package/dist/browser-umd/hsml-h.js.map +1 -1
  37. package/dist/browser-umd/hsml-html.js +1 -1
  38. package/dist/browser-umd/hsml-html.js.map +1 -1
  39. package/dist/browser-umd/hsml-idom.js +1 -1
  40. package/dist/browser-umd/hsml-idom.js.map +1 -1
  41. package/dist/browser-umd/hsml.js.map +1 -1
  42. package/dist/browser-umd/http.js +1 -1
  43. package/dist/browser-umd/http.js.map +1 -1
  44. package/dist/browser-umd/index.js +1 -1
  45. package/dist/browser-umd/index.js.map +1 -1
  46. package/dist/browser-umd/router.js +1 -1
  47. package/dist/browser-umd/router.js.map +1 -1
  48. package/dist/browser-umd/validators-moment.js +1 -1
  49. package/dist/browser-umd/validators-moment.js.map +1 -1
  50. package/dist/browser-umd/validators-numeral.js.map +1 -1
  51. package/dist/demo/encode_demo.ce182166.js.map +1 -1
  52. package/dist/demo/encode_demo.f40a44eb.js.map +1 -1
  53. package/dist/demo/hsml-app-form-validation_demo.a9e2c583.js +2 -0
  54. package/dist/demo/hsml-app-form-validation_demo.a9e2c583.js.map +1 -0
  55. package/dist/demo/hsml-app-form-validation_demo.bb392ab0.js +2 -0
  56. package/dist/demo/hsml-app-form-validation_demo.bb392ab0.js.map +1 -0
  57. package/dist/demo/hsml-app-form-validation_demo.c6856b02.js +2 -0
  58. package/dist/demo/hsml-app-form-validation_demo.c6856b02.js.map +1 -0
  59. package/dist/demo/hsml-app-form-validation_demo.fdcc0b2d.js +2 -0
  60. package/dist/demo/hsml-app-form-validation_demo.fdcc0b2d.js.map +1 -0
  61. package/dist/demo/hsml-app-form-validation_demo.html +1 -1
  62. package/dist/demo/hsml-app-form_demo.e36ef1e9.js +2 -0
  63. package/dist/demo/hsml-app-form_demo.e36ef1e9.js.map +1 -0
  64. package/dist/demo/hsml-app-form_demo.fd22dfcf.js +2 -0
  65. package/dist/demo/hsml-app-form_demo.fd22dfcf.js.map +1 -0
  66. package/dist/demo/hsml-app-form_demo.html +1 -1
  67. package/dist/demo/hsml-app-test_demo.ba5f166c.js +2 -0
  68. package/dist/demo/hsml-app-test_demo.ba5f166c.js.map +1 -0
  69. package/dist/demo/hsml-app-test_demo.e8b5e4b2.js +2 -0
  70. package/dist/demo/hsml-app-test_demo.e8b5e4b2.js.map +1 -0
  71. package/dist/demo/hsml-app-test_demo.html +1 -1
  72. package/dist/demo/hsml-app-tictactoe_demo.03d8363f.js +2 -0
  73. package/dist/demo/hsml-app-tictactoe_demo.03d8363f.js.map +1 -0
  74. package/dist/demo/hsml-app-tictactoe_demo.399f8e69.js +2 -0
  75. package/dist/demo/hsml-app-tictactoe_demo.399f8e69.js.map +1 -0
  76. package/dist/demo/hsml-app-tictactoe_demo.html +1 -1
  77. package/dist/demo/hsml-app_demo.44aa1072.js +2 -0
  78. package/dist/demo/hsml-app_demo.44aa1072.js.map +1 -0
  79. package/dist/demo/hsml-app_demo.70ef3e7a.js +2 -0
  80. package/dist/demo/hsml-app_demo.70ef3e7a.js.map +1 -0
  81. package/dist/demo/hsml-app_demo.html +1 -1
  82. package/dist/demo/hsml-appel_demo.2a9f7f3f.js +2 -0
  83. package/dist/demo/hsml-appel_demo.2a9f7f3f.js.map +1 -0
  84. package/dist/demo/hsml-appel_demo.bea7849a.js +2 -0
  85. package/dist/demo/hsml-appel_demo.bea7849a.js.map +1 -0
  86. package/dist/demo/hsml-appel_demo.html +1 -1
  87. package/dist/demo/hsml-appi_demo.3dc5de90.js +2 -0
  88. package/dist/demo/hsml-appi_demo.3dc5de90.js.map +1 -0
  89. package/dist/demo/hsml-appi_demo.bfc7056a.js +2 -0
  90. package/dist/demo/hsml-appi_demo.bfc7056a.js.map +1 -0
  91. package/dist/demo/hsml-appi_demo.html +1 -1
  92. package/dist/demo/hsml-convert_demo.0ea1fa3b.js.map +1 -1
  93. package/dist/demo/hsml-convert_demo.63e3e7b5.js.map +1 -1
  94. package/dist/demo/{hsml_demo.ff950ba1.js → hsml_demo.a248689a.js} +2 -2
  95. package/dist/demo/hsml_demo.a248689a.js.map +1 -0
  96. package/dist/demo/hsml_demo.eb3b08be.js +2 -0
  97. package/dist/demo/hsml_demo.eb3b08be.js.map +1 -0
  98. package/dist/demo/hsml_demo.html +1 -1
  99. package/dist/demo/http_demo.3e7da3d8.js.map +1 -1
  100. package/dist/demo/http_demo.8e435f23.js.map +1 -1
  101. package/dist/demo/i18n_demo.html +1 -1
  102. package/dist/demo/router_demo.3cfa03aa.js.map +1 -1
  103. package/dist/demo/router_demo.89ab1681.js.map +1 -1
  104. package/dist/demo/{validators_demo.252e13a6.js → validators_demo.90ff6001.js} +2 -2
  105. package/dist/demo/validators_demo.90ff6001.js.map +1 -0
  106. package/dist/demo/{validators_demo.66893723.js → validators_demo.ef5b2dea.js} +2 -2
  107. package/dist/demo/validators_demo.ef5b2dea.js.map +1 -0
  108. package/dist/demo/validators_demo.html +1 -1
  109. package/dist/encode.js +1 -1
  110. package/dist/encode.js.map +1 -1
  111. package/dist/hsml-app.d.ts +38 -37
  112. package/dist/hsml-app.js +60 -62
  113. package/dist/hsml-app.js.map +1 -1
  114. package/dist/hsml-convert.d.ts +3 -3
  115. package/dist/hsml-convert.js.map +1 -1
  116. package/dist/hsml-dom.d.ts +2 -2
  117. package/dist/hsml-dom.js +3 -3
  118. package/dist/hsml-dom.js.map +1 -1
  119. package/dist/hsml-h.d.ts +8 -8
  120. package/dist/hsml-h.js.map +1 -1
  121. package/dist/hsml-html.d.ts +4 -4
  122. package/dist/hsml-html.js +2 -2
  123. package/dist/hsml-html.js.map +1 -1
  124. package/dist/hsml-idom.d.ts +2 -2
  125. package/dist/hsml-idom.js +5 -5
  126. package/dist/hsml-idom.js.map +1 -1
  127. package/dist/hsml.d.ts +26 -27
  128. package/dist/hsml.js.map +1 -1
  129. package/dist/http.js +1 -1
  130. package/dist/http.js.map +1 -1
  131. package/dist/router.js +1 -1
  132. package/dist/router.js.map +1 -1
  133. package/package.json +8 -8
  134. package/src/hsml-app.ts +209 -144
  135. package/src/hsml-convert.ts +8 -8
  136. package/src/hsml-dom.ts +18 -18
  137. package/src/hsml-h.ts +10 -10
  138. package/src/hsml-html.ts +19 -19
  139. package/src/hsml-idom.ts +25 -25
  140. package/src/hsml.ts +46 -143
  141. package/demo/hsml-appc_demo.html +0 -16
  142. package/demo/hsml-appc_demo.ts +0 -49
  143. package/dist/demo/hsml-app-form-validation_demo.0b03b743.js +0 -2
  144. package/dist/demo/hsml-app-form-validation_demo.0b03b743.js.map +0 -1
  145. package/dist/demo/hsml-app-form-validation_demo.b3a5c810.js +0 -2
  146. package/dist/demo/hsml-app-form-validation_demo.b3a5c810.js.map +0 -1
  147. package/dist/demo/hsml-app-form-validation_demo.d3925067.js +0 -2
  148. package/dist/demo/hsml-app-form-validation_demo.d3925067.js.map +0 -1
  149. package/dist/demo/hsml-app-form-validation_demo.f757d763.js +0 -2
  150. package/dist/demo/hsml-app-form-validation_demo.f757d763.js.map +0 -1
  151. package/dist/demo/hsml-app-form_demo.007ffcaa.js +0 -2
  152. package/dist/demo/hsml-app-form_demo.007ffcaa.js.map +0 -1
  153. package/dist/demo/hsml-app-form_demo.a034239d.js +0 -2
  154. package/dist/demo/hsml-app-form_demo.a034239d.js.map +0 -1
  155. package/dist/demo/hsml-app-test_demo.35c14dc9.js +0 -2
  156. package/dist/demo/hsml-app-test_demo.35c14dc9.js.map +0 -1
  157. package/dist/demo/hsml-app-test_demo.3c7e16ae.js +0 -2
  158. package/dist/demo/hsml-app-test_demo.3c7e16ae.js.map +0 -1
  159. package/dist/demo/hsml-app-tictactoe_demo.5f4861c1.js +0 -2
  160. package/dist/demo/hsml-app-tictactoe_demo.5f4861c1.js.map +0 -1
  161. package/dist/demo/hsml-app-tictactoe_demo.7deeabad.js +0 -2
  162. package/dist/demo/hsml-app-tictactoe_demo.7deeabad.js.map +0 -1
  163. package/dist/demo/hsml-app_demo.87d83c29.js +0 -2
  164. package/dist/demo/hsml-app_demo.87d83c29.js.map +0 -1
  165. package/dist/demo/hsml-app_demo.941a13a6.js +0 -2
  166. package/dist/demo/hsml-app_demo.941a13a6.js.map +0 -1
  167. package/dist/demo/hsml-appc_demo.0234ff15.js +0 -2
  168. package/dist/demo/hsml-appc_demo.0234ff15.js.map +0 -1
  169. package/dist/demo/hsml-appc_demo.f5783031.js +0 -2
  170. package/dist/demo/hsml-appc_demo.f5783031.js.map +0 -1
  171. package/dist/demo/hsml-appc_demo.html +0 -1
  172. package/dist/demo/hsml-appel_demo.0e8a4d4c.js +0 -2
  173. package/dist/demo/hsml-appel_demo.0e8a4d4c.js.map +0 -1
  174. package/dist/demo/hsml-appel_demo.1a5c2c26.js +0 -2
  175. package/dist/demo/hsml-appel_demo.1a5c2c26.js.map +0 -1
  176. package/dist/demo/hsml-appi_demo.2c3fb511.js +0 -2
  177. package/dist/demo/hsml-appi_demo.2c3fb511.js.map +0 -1
  178. package/dist/demo/hsml-appi_demo.427fdebd.js +0 -2
  179. package/dist/demo/hsml-appi_demo.427fdebd.js.map +0 -1
  180. package/dist/demo/hsml_demo.33f28c29.js +0 -2
  181. package/dist/demo/hsml_demo.33f28c29.js.map +0 -1
  182. package/dist/demo/hsml_demo.ff950ba1.js.map +0 -1
  183. package/dist/demo/validators_demo.252e13a6.js.map +0 -1
  184. package/dist/demo/validators_demo.66893723.js.map +0 -1
package/src/hsml-app.ts CHANGED
@@ -5,31 +5,58 @@ const log = console.log;
5
5
  const error = console.error;
6
6
  const warn = console.warn;
7
7
 
8
- export type HState<STATE> = () => STATE;
9
- export type HView<STATE> = (state: STATE) => HElements;
10
- export type HView1<STATE> = (state: STATE) => HElement;
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
+ | "init"
20
+ | "mount"
21
+ | "umount"
22
+ | "action"
23
+ | "elementAttr";
24
+
25
+ export enum HAppActions {
26
+ init = "init",
27
+ mount = "mount",
28
+ umount = "umount",
29
+ action = "action",
30
+ elementAttr = "elementAttr"
31
+ }
11
32
 
12
- export interface HAction {
13
- type: string;
33
+ export interface HAction<HActionType extends string> {
34
+ type: HActionType | HAppActionType | HAppActions;
14
35
  data?: any;
15
36
  event?: Event;
16
37
  }
17
38
 
18
- export type HDispatch = (type: HAction["type"],
19
- data?: HAction["data"],
20
- event?: HAction["event"]) => Promise<void>;
39
+ export type HDispatchScope =
40
+ | "element"
41
+ | "window";
21
42
 
22
- export type HUpdate = () => void;
43
+ export enum HDispatchScopes {
44
+ element = "element",
45
+ window = "window"
46
+ }
23
47
 
24
- export type HDispatcher<STATE> = (action: HAction, state: STATE, dispatch: HDispatch) => Promise<void>;
25
- // export type HDispatcher<STATE> = (this: HApp<STATE>, action: HAction, state: STATE, dispatch: HDispatch) => Promise<void>;
48
+ export type HDispatch<HActionType extends string> = (
49
+ type: HAction<HActionType>["type"],
50
+ data?: HAction<HActionType>["data"],
51
+ scope?: HDispatchScope | HDispatchScopes
52
+ ) => Promise<void>;
26
53
 
27
- export enum HAppAction {
28
- _init = "_init",
29
- _mount = "_mount",
30
- _umount = "_umount",
31
- _element = "_element"
32
- }
54
+ export type HDispatcher<State, HActionType extends string> = (
55
+ // this: HApp<State, HActionType>,
56
+ action: HAction<HActionType>,
57
+ state: State,
58
+ dispatch: HDispatch<HActionType>
59
+ ) => Promise<void>;
33
60
 
34
61
  const schedule = window.requestAnimationFrame ||
35
62
  // window.webkitRequestAnimationFrame ||
@@ -50,99 +77,108 @@ const msgDispatch = "HApp dispatch:";
50
77
  const msgRender = "HApp render:";
51
78
  const msgUpdate = "HApp update:";
52
79
 
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);
80
+ export function happ<State, HActionType extends string>(
81
+ state: HState<State>,
82
+ view: HView<State, HActionType>,
83
+ dispatcher: HDispatcher<State, HActionType>,
84
+ element: Element | string | null = document.body
85
+ ) {
86
+ return new HApp<State, HActionType>(state, view, dispatcher, element);
58
87
  }
59
88
 
60
89
  // HAppI
61
90
 
62
91
  export type Class<T = object> = new (...args: any[]) => T;
63
92
 
64
- export interface HAppI<STATE> {
65
- state(): STATE;
66
- view(state: STATE): HElements;
67
- dispatcher(action: HAction, state: STATE, dispatch: HDispatch): Promise<void>;
68
- // dispatcher(this: HApp<STATE>, action: HAction, state: STATE, dispatch: HDispatch): Promise<void>;
93
+ export interface HAppI<State, HActionType extends string> {
94
+ state(): State;
95
+ view(state: State): HElements<HActionType>;
96
+ dispatcher(
97
+ // this: HApp<State, HActionType>,
98
+ action: HAction<HActionType>,
99
+ state: State,
100
+ dispatch: HDispatch<HActionType>
101
+ ): Promise<void>;
69
102
  }
70
103
 
71
- export function happi<STATE>(hAppI: Class<HAppI<STATE>>, e: Element | string | null = document.body) {
104
+ export function happi<State, HActionType extends string>(
105
+ hAppI: Class<HAppI<State, HActionType>>,
106
+ element: Element | string | null = document.body
107
+ ) {
72
108
  const hapi = new hAppI();
73
- return new HApp<STATE>(hapi.state, hapi.view, hapi.dispatcher, e);
109
+ return new HApp<State, HActionType>(
110
+ hapi.state,
111
+ hapi.view,
112
+ hapi.dispatcher,
113
+ element
114
+ );
74
115
  }
75
116
 
76
117
  // HAppEl
77
118
 
78
- export function happel<STATE>(elementName: string,
79
- elementAttrs: string[],
80
- state: HState<STATE>,
81
- view: HView<STATE>,
82
- dispatcher: HDispatcher<STATE>): void {
83
- customElements.define(elementName, class HAppElement extends HTMLElement {
84
-
85
- static get observedAttributes() {
86
- return elementAttrs;
87
- }
88
-
89
- private _happel: HApp<STATE>;
90
-
91
- constructor() {
92
- super();
93
- this._happel = new HApp<STATE>(state, view, dispatcher);
94
- (this._happel as any).customElement = this;
95
- }
96
-
97
- connectedCallback() {
98
- // this._happel.mount(this);
99
- this.attachShadow({ mode: "open" });
100
- this._happel.mount(this.shadowRoot as any);
101
- }
102
-
103
- disconnectedCallback() {
104
- this._happel.umount();
105
- }
106
-
107
- adoptedCallback() {
108
- this._happel.update();
109
- }
119
+ export function happel<State, HActionType extends string>(
120
+ elementName: string,
121
+ elementAttrs: string[],
122
+ state: HState<State>,
123
+ view: HView<State, HActionType>,
124
+ dispatcher: HDispatcher<State, HActionType>
125
+ ): void {
126
+ customElements.define(
127
+ elementName,
128
+ class HAppElement extends HTMLElement {
129
+ static get observedAttributes() {
130
+ return elementAttrs;
131
+ }
110
132
 
111
- attributeChangedCallback(attrName: string, oldVal: string | null, newVal: string | null) {
112
- this._happel.dispatch(HAppAction._element, { attrName, oldVal, newVal });
113
- }
133
+ private _happel: HApp<State, HActionType>;
114
134
 
115
- });
116
- }
135
+ constructor() {
136
+ super();
137
+ this._happel = new HApp<State, HActionType>(
138
+ state,
139
+ view,
140
+ dispatcher
141
+ );
142
+ (this._happel as any).customElement = this;
143
+ }
117
144
 
118
- // HAppC
145
+ connectedCallback() {
146
+ // this._happel.mount(this);
147
+ this.attachShadow({ mode: "open" });
148
+ this._happel.mount(this.shadowRoot as any);
149
+ }
119
150
 
120
- export type HController<State> = (this: HApp<State>,
121
- data?: HAction["data"],
122
- event?: HAction["event"]) => void;
151
+ disconnectedCallback() {
152
+ this._happel.umount();
153
+ }
123
154
 
124
- export type HControllers<State, TypeofActionEnum> = { [actionType in keyof TypeofActionEnum]?: HController<State>; };
155
+ adoptedCallback() {
156
+ this._happel.update();
157
+ }
125
158
 
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);
159
+ attributeChangedCallback(
160
+ attrName: string,
161
+ oldVal: string | null,
162
+ newVal: string | null
163
+ ) {
164
+ this._happel.dispatch("elementAttr", {
165
+ attrName,
166
+ oldVal,
167
+ newVal,
168
+ });
169
+ }
133
170
  }
134
- };
171
+ );
135
172
  }
136
173
 
137
174
  const HAPP = "happ";
138
175
 
139
- export class HApp<STATE> implements HHandlerCtx {
140
-
176
+ export class HApp<State, HActionType extends string> implements HHandlerCtx<HActionType> {
141
177
  static debug = false;
142
178
 
143
- readonly state: STATE;
144
- readonly view: HView<STATE>;
145
- readonly dispatcher: HDispatcher<STATE>;
179
+ readonly state: State;
180
+ readonly view: HView<State, HActionType>;
181
+ readonly dispatcher: HDispatcher<State, HActionType>;
146
182
 
147
183
  readonly customElement?: HTMLElement; // happ custom html element
148
184
 
@@ -151,58 +187,96 @@ export class HApp<STATE> implements HHandlerCtx {
151
187
 
152
188
  private _updateSched?: number;
153
189
 
154
- private _onDispatch?: HDispatcher<STATE>;
190
+ // private _onDispatch?: HDispatcher<State>;
155
191
 
156
192
  private _windowEventListener?: (event: Event) => void;
157
193
 
158
- constructor(state: HState<STATE>, view: HView<STATE>, dispatcher?: HDispatcher<STATE>, e: Element | string | null = document.body) {
194
+ constructor(
195
+ state: HState<State>,
196
+ view: HView<State, HActionType>,
197
+ dispatcher?: HDispatcher<State, HActionType>,
198
+ element: Element | string | null = document.body
199
+ ) {
159
200
  this.state = state();
160
201
  this.view = view;
161
202
  this.dispatcher = dispatcher ?? (async (a) => log(msgAction, a.type, a.data));
162
- this.dispatch(HAppAction._init, this).then(() => this.mount(e));
203
+ this._dispatchAction("init", this).then(() => this.mount(element));
163
204
  }
164
205
 
165
- private async _dispatch(type: string, data: any, event: Event | undefined) {
166
- try {
167
- await this.dispatcher({ type, data, event }, this.state, this.dispatch);
168
- this._onDispatch?.({ type, data, event }, this.state, this.dispatch);
169
- this.dom && elementDispatchCustomEvent(this.dom, HAPP, { type, data, event });
170
- this.customElement && elementDispatchCustomEvent(this.customElement, type, data);
171
- !this.customElement && this.dom && elementDispatchCustomEvent(this.dom, type, data);
172
- this.update();
173
- } catch (e) {
174
- error(msgDispatch, e);
175
- }
176
- }
177
-
178
- onDispatch = (dispatcher: HDispatcher<STATE>): this => {
179
- this._onDispatch = dispatcher;
180
- return this;
206
+ dispatch: HDispatch<HActionType> = async (
207
+ type: HActionType | HAppActionType,
208
+ data?: any,
209
+ scope?: HDispatchScope
210
+ ): Promise<void> => {
211
+ return this._dispatchAction(type, data, undefined, scope);
181
212
  }
182
213
 
183
- dispatch: HDispatch = async (type: string, data?: any, event?: Event): Promise<void> => {
214
+ // onDispatch = (dispatcher: HDispatcher<State>): this => {
215
+ // this._onDispatch = dispatcher;
216
+ // return this;
217
+ // }
218
+
219
+ private async _dispatchAction(
220
+ type: HActionType | HAppActionType,
221
+ data?: any,
222
+ event?: Event,
223
+ scope?: HDispatchScope
224
+ ): Promise<void> {
184
225
  if (HApp.debug) {
185
226
  log(msgAction, { type, data, event });
186
227
  const t0 = performance.now();
187
- await this._dispatch(type, data, event);
228
+ await this._dispatch(type, data, event, scope);
188
229
  const t1 = performance.now();
189
230
  log(msgDispatch, `${t1 - t0} ms`, this.state);
190
231
  } else {
191
- await this._dispatch(type, data, event);
232
+ await this._dispatch(type, data, event, scope);
192
233
  }
193
234
  }
194
235
 
195
- windowDispatch: HDispatch = async (type: string, data?: any, event?: Event): Promise<void> => {
196
- window.dispatchEvent(new CustomEvent(HAPP, { detail: { type, data } }));
236
+ private async _dispatch(
237
+ type: HActionType | HAppActionType,
238
+ data: any,
239
+ event?: Event,
240
+ scope?: HDispatchScope
241
+ ) {
242
+ try {
243
+ await this.dispatcher(
244
+ { type: type as HActionType, data, event },
245
+ this.state,
246
+ this.dispatch
247
+ );
248
+ this.update();
249
+ scope === "element" && this._dispatchElement(type, data);
250
+ scope === "window" && this._dispatchWindow(type, data);
251
+ } catch (e) {
252
+ error(msgDispatch, e);
253
+ }
254
+ }
255
+
256
+ private _dispatchElement: HDispatch<HActionType> = async (
257
+ type: HActionType | HAppActionType,
258
+ data?: any
259
+ ): Promise<void> => {
260
+ this.customElement && elementDispatchCustomEvent(this.customElement, "action", { type, data });
261
+ !this.customElement && this.dom && elementDispatchCustomEvent(this.dom, "action", { type, data });
262
+ // this.customElement && elementDispatchCustomEvent(this.customElement, type, data);
263
+ // !this.customElement && this.dom && elementDispatchCustomEvent(this.dom, type, data);
264
+ // this._onDispatch?.({ type, data, event }, this.state, this.dispatch);
265
+ }
266
+
267
+ private _dispatchWindow: HDispatch<HActionType> = async (
268
+ type: HActionType | HAppActionType,
269
+ data?: any): Promise<void> => {
270
+ window.dispatchEvent(new CustomEvent("action", { detail: { type, data } }));
197
271
  }
198
272
 
199
273
  windowDispatchOn() {
200
274
  if (!this._windowEventListener) {
201
275
  this._windowEventListener = (event: Event) => {
202
- const action = (event as CustomEvent).detail as HAction;
203
- this.dispatch(action.type, action.data, event);
276
+ const action = (event as CustomEvent).detail as HAction<HActionType>;
277
+ this._dispatchAction(action.type, action.data);
204
278
  };
205
- window.addEventListener(HAPP, this._windowEventListener);
279
+ window.addEventListener("action", this._windowEventListener);
206
280
  } else {
207
281
  warn("windowEventListener olready setted");
208
282
  }
@@ -210,11 +284,11 @@ export class HApp<STATE> implements HHandlerCtx {
210
284
 
211
285
  windowDispatchOff() {
212
286
  if (this._windowEventListener) {
213
- window.removeEventListener(HAPP, this._windowEventListener);
287
+ window.removeEventListener("action", this._windowEventListener);
214
288
  }
215
289
  }
216
290
 
217
- render = (): HElements => {
291
+ render = (): HElements<HActionType> => {
218
292
  if (HApp.debug) {
219
293
  const t0 = performance.now();
220
294
  let hsmls;
@@ -237,7 +311,7 @@ export class HApp<STATE> implements HHandlerCtx {
237
311
  }
238
312
  }
239
313
 
240
- actionCb = (action: string, data: HAttrOnData, event: Event): void => {
314
+ actionCb = (actionType: HActionType, data: HAttrOnData, event: Event): void => {
241
315
  data = (data?.constructor === Function)
242
316
  ? (data as HAttrOnDataFnc)(event)
243
317
  : data;
@@ -248,7 +322,7 @@ export class HApp<STATE> implements HHandlerCtx {
248
322
  data = formData(event);
249
323
  }
250
324
  }
251
- this.dispatch(action, data, event);
325
+ this._dispatchAction(actionType, data, event);
252
326
  }
253
327
 
254
328
  mount = (e: Element | string | null = document.body): this => {
@@ -256,28 +330,28 @@ export class HApp<STATE> implements HHandlerCtx {
256
330
  ? document.getElementById(e) ?? document.body
257
331
  : e ?? document.body;
258
332
  if ((el as any)[HAPP]) {
259
- const a = (el as any)[HAPP] as HApp<STATE>;
333
+ const a = (el as any)[HAPP] as HApp<State, HActionType>;
260
334
  a.umount();
261
335
  }
262
336
  if (!this.dom) {
263
337
  (this as any).dom = el;
264
338
  (el as any)[HAPP] = this;
265
339
  const hsmls = (this as any).render();
266
- updateDom(el, hsmls, this);
267
- this.dispatch(HAppAction._mount, this.dom);
340
+ updateDom<HActionType>(el, hsmls, this);
341
+ this._dispatchAction("mount", this.dom);
268
342
  }
269
343
  return this;
270
344
  }
271
345
 
272
346
  umount = (): this => {
273
347
  if (this.dom) {
274
- this.dispatch(HAppAction._umount, this.dom);
348
+ this._dispatchAction("umount", this.dom);
275
349
  if (this.dom.hasAttribute(HAPP)) {
276
350
  this.dom.removeAttribute(HAPP);
277
351
  }
278
352
  const aNodes = this.dom.querySelectorAll(`[${HAPP}]`);
279
353
  for (let i = 0; i < aNodes.length; i++) {
280
- const a = (aNodes[i] as any).happ as HApp<STATE>;
354
+ const a = (aNodes[i] as any).happ as HApp<State, HActionType>;
281
355
  a?.umount();
282
356
  }
283
357
  while (this.dom.firstChild /*.hasChildNodes()*/) {
@@ -294,7 +368,7 @@ export class HApp<STATE> implements HHandlerCtx {
294
368
  this._updateSched = schedule(() => {
295
369
  if (this.dom) {
296
370
  const hsmls = this.render();
297
- updateDom(this.dom, hsmls, this);
371
+ updateDom<HActionType>(this.dom, hsmls, this);
298
372
  }
299
373
  this._updateSched = undefined;
300
374
  });
@@ -302,13 +376,13 @@ export class HApp<STATE> implements HHandlerCtx {
302
376
  return this;
303
377
  }
304
378
 
305
- toHsml = (): HElement => {
379
+ toHsml = (): HElement<HActionType> => {
306
380
  if (this.dom) {
307
381
  if (this._updateSched) {
308
382
  unschedule(this._updateSched);
309
383
  this._updateSched = undefined;
310
384
  } else {
311
- return ["div", { _skip: true }];
385
+ return ["div", { skip: true }];
312
386
  }
313
387
  }
314
388
  const hsmls = this.render();
@@ -317,7 +391,7 @@ export class HApp<STATE> implements HHandlerCtx {
317
391
  if (!this.dom) {
318
392
  (this as any).dom = e;
319
393
  (e as any).happ = this;
320
- this.dispatch(HAppAction._mount, this.dom);
394
+ this._dispatchAction("mount", this.dom);
321
395
  }
322
396
  });
323
397
  return ["div", hsmls];
@@ -329,7 +403,11 @@ export class HApp<STATE> implements HHandlerCtx {
329
403
 
330
404
  }
331
405
 
332
- function updateDom(el: Element, hsml: HElements, ctx: HHandlerCtx): void {
406
+ function updateDom<HActionType extends string>(
407
+ el: Element,
408
+ hsml: HElements<HActionType>,
409
+ ctx: HHandlerCtx<HActionType>
410
+ ): void {
333
411
  if (HApp.debug) {
334
412
  const t0 = performance.now();
335
413
  hsmls2idomPatch(el, hsml, ctx);
@@ -340,9 +418,13 @@ function updateDom(el: Element, hsml: HElements, ctx: HHandlerCtx): void {
340
418
  }
341
419
  }
342
420
 
343
- function elementDispatchCustomEvent(el: HTMLElement, type: string, data: any) {
421
+ function elementDispatchCustomEvent<HActionType extends string>(
422
+ el: HTMLElement,
423
+ type: HActionType,
424
+ data: any
425
+ ) {
344
426
  el?.dispatchEvent(new CustomEvent(type, { detail: data }));
345
- (el as any)[`on${type.toLowerCase()}`]?.(new CustomEvent(type, { detail: data }));
427
+ (el as any)[`on${type}`]?.(new CustomEvent(type, { detail: data }));
346
428
  }
347
429
 
348
430
  function formData(e: Event): { [k: string]: string | number | boolean | null | Array<string | null> } | string | number | boolean | null | Array<string | null> {
@@ -491,20 +573,3 @@ function formInputData(el: Element): { [k: string]: string | number | boolean |
491
573
  }
492
574
  return data;
493
575
  }
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
- // }
@@ -114,14 +114,14 @@ interface Handler {
114
114
  close(tag: string): void;
115
115
  }
116
116
 
117
- class HsmlHandler implements Handler {
117
+ class HsmlHandler<HActionType extends string> implements Handler {
118
118
 
119
- private _root = [[]] as HElements[];
119
+ private _root = [[]] as HElements<HActionType>[];
120
120
  private _nodePath = [] as any; // path that consist of previous hsml nodes
121
121
  private _pointer = this._root;
122
122
  private _dataRegex = /data-(.+)/;
123
123
 
124
- root(): HElement {
124
+ root(): HElement<HActionType> {
125
125
  return this._root[0][0];
126
126
  }
127
127
 
@@ -175,7 +175,7 @@ class HsmlHandler implements Handler {
175
175
  const children: any[] = [];
176
176
  hsmlNode.push(children);
177
177
 
178
- this._pointer[this._pointer.length - 1].push(hsmlNode as HElement);
178
+ this._pointer[this._pointer.length - 1].push(hsmlNode as HElement<HActionType>);
179
179
  this._nodePath.push(hsmlNode);
180
180
  this._pointer = hsmlNode;
181
181
  // console.log(">>>", hsmlPath.map(x => x[0]));
@@ -222,13 +222,13 @@ function domTraverse(node: Node, handler: Handler ): void {
222
222
  }
223
223
  }
224
224
 
225
- export function dom2hsml(node: Node): HElement {
226
- const h = new HsmlHandler();
225
+ export function dom2hsml<HActionType extends string>(node: Node): HElement<HActionType> {
226
+ const h = new HsmlHandler<HActionType>();
227
227
  node && domTraverse(node, h);
228
228
  return h.root();
229
229
  }
230
230
 
231
- export function html2hsml(html: string): HElement {
231
+ export function html2hsml<HActionType extends string>(html: string): HElement<HActionType> {
232
232
  const node = new DOMParser()
233
233
  .parseFromString(html, "text/html")
234
234
  .getElementsByTagName("body")[0]
@@ -236,7 +236,7 @@ export function html2hsml(html: string): HElement {
236
236
  return node && dom2hsml(node);
237
237
  }
238
238
 
239
- export function hsml2str(hsml: HElement, condense = true): HElement {
239
+ export function hsml2str<HActionType extends string>(hsml: HElement<HActionType>, condense = true): HElement<HActionType> {
240
240
  let str = JSON.stringify(hsml, undefined, 4);
241
241
  if (condense) {
242
242
  str = str.replace(/(\[)\s+(\"[a-zA-Z0-9_\#\.-]+\")\s+(\],?)$/mg, "$1$2$3");