@hypen-space/web 0.4.36 → 0.4.37
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/dist/canvas/accessibility.js +174 -174
- package/dist/canvas/accessibility.js.map +1 -10
- package/dist/canvas/events.js +264 -360
- package/dist/canvas/events.js.map +1 -11
- package/dist/canvas/index.js +11 -47
- package/dist/canvas/index.js.map +1 -9
- package/dist/canvas/input.js +178 -289
- package/dist/canvas/input.js.map +1 -11
- package/dist/canvas/layout.js +349 -547
- package/dist/canvas/layout.js.map +1 -12
- package/dist/canvas/paint.js +1122 -1146
- package/dist/canvas/paint.js.map +1 -12
- package/dist/canvas/renderer.js +352 -2259
- package/dist/canvas/renderer.js.map +1 -17
- package/dist/canvas/text.js +129 -264
- package/dist/canvas/text.js.map +1 -11
- package/dist/canvas/types.js +7 -2
- package/dist/canvas/types.js.map +1 -9
- package/dist/canvas/utils.js +158 -161
- package/dist/canvas/utils.js.map +1 -10
- package/dist/client.js +19 -45
- package/dist/client.js.map +1 -9
- package/dist/dom/applicators/advanced-layout.js +105 -138
- package/dist/dom/applicators/advanced-layout.js.map +1 -10
- package/dist/dom/applicators/background.js +36 -76
- package/dist/dom/applicators/background.js.map +1 -10
- package/dist/dom/applicators/border.js +82 -106
- package/dist/dom/applicators/border.js.map +1 -10
- package/dist/dom/applicators/color.js +17 -58
- package/dist/dom/applicators/color.js.map +1 -10
- package/dist/dom/applicators/display.js +39 -79
- package/dist/dom/applicators/display.js.map +1 -10
- package/dist/dom/applicators/effects.js +121 -147
- package/dist/dom/applicators/effects.js.map +1 -10
- package/dist/dom/applicators/events.js +413 -450
- package/dist/dom/applicators/events.js.map +1 -11
- package/dist/dom/applicators/font.js +119 -140
- package/dist/dom/applicators/font.js.map +1 -10
- package/dist/dom/applicators/index.js +386 -1770
- package/dist/dom/applicators/index.js.map +1 -26
- package/dist/dom/applicators/layout.js +143 -149
- package/dist/dom/applicators/layout.js.map +1 -10
- package/dist/dom/applicators/margin.js +64 -105
- package/dist/dom/applicators/margin.js.map +1 -10
- package/dist/dom/applicators/padding.js +64 -105
- package/dist/dom/applicators/padding.js.map +1 -10
- package/dist/dom/applicators/size.js +169 -172
- package/dist/dom/applicators/size.js.map +1 -10
- package/dist/dom/applicators/transform.js +73 -114
- package/dist/dom/applicators/transform.js.map +1 -10
- package/dist/dom/applicators/transition.js +47 -88
- package/dist/dom/applicators/transition.js.map +1 -10
- package/dist/dom/applicators/types.js +7 -2
- package/dist/dom/applicators/types.js.map +1 -9
- package/dist/dom/applicators/typography.js +68 -109
- package/dist/dom/applicators/typography.js.map +1 -10
- package/dist/dom/canvas/index.js +49 -83
- package/dist/dom/canvas/index.js.map +1 -10
- package/dist/dom/components/app.js +16 -63
- package/dist/dom/components/app.js.map +1 -10
- package/dist/dom/components/audio.js +31 -76
- package/dist/dom/components/audio.js.map +1 -10
- package/dist/dom/components/avatar.js +41 -87
- package/dist/dom/components/avatar.js.map +1 -10
- package/dist/dom/components/badge.js +35 -83
- package/dist/dom/components/badge.js.map +1 -10
- package/dist/dom/components/button.js +26 -69
- package/dist/dom/components/button.js.map +1 -10
- package/dist/dom/components/card.js +13 -63
- package/dist/dom/components/card.js.map +1 -10
- package/dist/dom/components/center.js +21 -65
- package/dist/dom/components/center.js.map +1 -10
- package/dist/dom/components/checkbox.js +37 -82
- package/dist/dom/components/checkbox.js.map +1 -10
- package/dist/dom/components/column.js +16 -62
- package/dist/dom/components/column.js.map +1 -10
- package/dist/dom/components/container.js +11 -59
- package/dist/dom/components/container.js.map +1 -10
- package/dist/dom/components/divider.js +27 -73
- package/dist/dom/components/divider.js.map +1 -10
- package/dist/dom/components/grid.js +41 -80
- package/dist/dom/components/grid.js.map +1 -10
- package/dist/dom/components/heading.js +28 -74
- package/dist/dom/components/heading.js.map +1 -10
- package/dist/dom/components/hypenapp.js +291 -288
- package/dist/dom/components/hypenapp.js.map +1 -10
- package/dist/dom/components/image.js +18 -67
- package/dist/dom/components/image.js.map +1 -10
- package/dist/dom/components/index.js +109 -1427
- package/dist/dom/components/index.js.map +1 -42
- package/dist/dom/components/input.js +19 -69
- package/dist/dom/components/input.js.map +1 -10
- package/dist/dom/components/link.js +23 -70
- package/dist/dom/components/link.js.map +1 -10
- package/dist/dom/components/list.js +26 -72
- package/dist/dom/components/list.js.map +1 -10
- package/dist/dom/components/paragraph.js +14 -63
- package/dist/dom/components/paragraph.js.map +1 -10
- package/dist/dom/components/progressbar.js +38 -85
- package/dist/dom/components/progressbar.js.map +1 -10
- package/dist/dom/components/route.js +27 -73
- package/dist/dom/components/route.js.map +1 -10
- package/dist/dom/components/router.js +15 -62
- package/dist/dom/components/router.js.map +1 -10
- package/dist/dom/components/row.js +25 -70
- package/dist/dom/components/row.js.map +1 -10
- package/dist/dom/components/select.js +42 -85
- package/dist/dom/components/select.js.map +1 -10
- package/dist/dom/components/slider.js +31 -76
- package/dist/dom/components/slider.js.map +1 -10
- package/dist/dom/components/spacer.js +10 -60
- package/dist/dom/components/spacer.js.map +1 -10
- package/dist/dom/components/spinner.js +41 -88
- package/dist/dom/components/spinner.js.map +1 -10
- package/dist/dom/components/stack.js +19 -67
- package/dist/dom/components/stack.js.map +1 -10
- package/dist/dom/components/switch.js +50 -93
- package/dist/dom/components/switch.js.map +1 -10
- package/dist/dom/components/text.js +24 -69
- package/dist/dom/components/text.js.map +1 -10
- package/dist/dom/components/textarea.js +35 -79
- package/dist/dom/components/textarea.js.map +1 -10
- package/dist/dom/components/video.js +35 -79
- package/dist/dom/components/video.js.map +1 -10
- package/dist/dom/debug.js +159 -160
- package/dist/dom/debug.js.map +1 -10
- package/dist/dom/element-data.js +181 -143
- package/dist/dom/element-data.js.map +1 -10
- package/dist/dom/events.js +133 -142
- package/dist/dom/events.js.map +1 -10
- package/dist/dom/index.js +11 -48
- package/dist/dom/index.js.map +1 -9
- package/dist/dom/renderer.js +311 -3596
- package/dist/dom/renderer.js.map +1 -62
- package/dist/hypen.js +385 -3880
- package/dist/hypen.js.map +1 -63
- package/dist/index.js +36 -53
- package/dist/index.js.map +1 -9
- package/package.json +2 -2
package/dist/hypen.js
CHANGED
|
@@ -1,3909 +1,414 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
var __export = (target, all) => {
|
|
30
|
-
for (var name in all)
|
|
31
|
-
__defProp(target, name, {
|
|
32
|
-
get: all[name],
|
|
33
|
-
enumerable: true,
|
|
34
|
-
configurable: true,
|
|
35
|
-
set: __exportSetter.bind(all, name)
|
|
36
|
-
});
|
|
37
|
-
};
|
|
38
|
-
var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
|
|
39
|
-
|
|
40
|
-
// src/dom/components/column.ts
|
|
41
|
-
var exports_column = {};
|
|
42
|
-
__export(exports_column, {
|
|
43
|
-
columnHandler: () => columnHandler
|
|
44
|
-
});
|
|
45
|
-
var columnHandler;
|
|
46
|
-
var init_column = __esm(() => {
|
|
47
|
-
columnHandler = {
|
|
48
|
-
create() {
|
|
49
|
-
const el = document.createElement("div");
|
|
50
|
-
el.style.display = "flex";
|
|
51
|
-
el.style.flexDirection = "column";
|
|
52
|
-
el.style.alignItems = "flex-start";
|
|
53
|
-
el.dataset.hypenType = "column";
|
|
54
|
-
return el;
|
|
55
|
-
}
|
|
56
|
-
};
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
// src/dom/components/row.ts
|
|
60
|
-
var exports_row = {};
|
|
61
|
-
__export(exports_row, {
|
|
62
|
-
rowHandler: () => rowHandler
|
|
63
|
-
});
|
|
64
|
-
function ensureRowStyles() {
|
|
65
|
-
if (rowStylesInjected)
|
|
66
|
-
return;
|
|
67
|
-
rowStylesInjected = true;
|
|
68
|
-
const style = document.createElement("style");
|
|
69
|
-
style.id = "hypen-row-styles";
|
|
70
|
-
style.textContent = `
|
|
71
|
-
/* Row expands to fill width when it has children with flex/weight */
|
|
72
|
-
/* This matches iOS/Android behavior where weighted children cause parent to expand */
|
|
73
|
-
[data-hypen-type="row"]:has(> [data-hypen-flex]) {
|
|
74
|
-
width: 100%;
|
|
75
|
-
}
|
|
76
|
-
`;
|
|
77
|
-
document.head.appendChild(style);
|
|
78
|
-
}
|
|
79
|
-
var rowStylesInjected = false, rowHandler;
|
|
80
|
-
var init_row = __esm(() => {
|
|
81
|
-
rowHandler = {
|
|
82
|
-
create() {
|
|
83
|
-
ensureRowStyles();
|
|
84
|
-
const el = document.createElement("div");
|
|
85
|
-
el.style.display = "flex";
|
|
86
|
-
el.style.flexDirection = "row";
|
|
87
|
-
el.style.alignItems = "flex-start";
|
|
88
|
-
el.dataset.hypenType = "row";
|
|
89
|
-
return el;
|
|
90
|
-
}
|
|
91
|
-
};
|
|
92
|
-
});
|
|
93
|
-
|
|
94
|
-
// src/dom/components/text.ts
|
|
95
|
-
var exports_text = {};
|
|
96
|
-
__export(exports_text, {
|
|
97
|
-
textHandler: () => textHandler
|
|
98
|
-
});
|
|
99
|
-
var textHandler;
|
|
100
|
-
var init_text = __esm(() => {
|
|
101
|
-
textHandler = {
|
|
102
|
-
create() {
|
|
103
|
-
const el = document.createElement("span");
|
|
104
|
-
el.style.display = "inline-block";
|
|
105
|
-
el.style.lineHeight = "1";
|
|
106
|
-
el.style.verticalAlign = "top";
|
|
107
|
-
el.style.margin = "0";
|
|
108
|
-
el.style.padding = "0";
|
|
109
|
-
el.dataset.hypenType = "text";
|
|
110
|
-
return el;
|
|
111
|
-
},
|
|
112
|
-
applyProps(el, props) {
|
|
113
|
-
const text = props["0"] || props.text;
|
|
114
|
-
if (text !== undefined) {
|
|
115
|
-
el.dataset.textTemplate = String(text);
|
|
116
|
-
el.textContent = String(text);
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
};
|
|
120
|
-
});
|
|
121
|
-
|
|
122
|
-
// src/dom/components/image.ts
|
|
123
|
-
var exports_image = {};
|
|
124
|
-
__export(exports_image, {
|
|
125
|
-
imageHandler: () => imageHandler
|
|
126
|
-
});
|
|
127
|
-
var imageHandler;
|
|
128
|
-
var init_image = __esm(() => {
|
|
129
|
-
imageHandler = {
|
|
130
|
-
create() {
|
|
131
|
-
const el = document.createElement("img");
|
|
132
|
-
el.dataset.hypenType = "image";
|
|
133
|
-
return el;
|
|
134
|
-
},
|
|
135
|
-
applyProps(el, props) {
|
|
136
|
-
const img = el;
|
|
137
|
-
const src = props["0"] || props.url || props.src;
|
|
138
|
-
if (src !== undefined) {
|
|
139
|
-
img.src = String(src);
|
|
140
|
-
}
|
|
141
|
-
if (props.alt !== undefined) {
|
|
142
|
-
img.alt = String(props.alt);
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
};
|
|
146
|
-
});
|
|
147
|
-
|
|
148
|
-
// src/dom/components/button.ts
|
|
149
|
-
var exports_button = {};
|
|
150
|
-
__export(exports_button, {
|
|
151
|
-
buttonHandler: () => buttonHandler
|
|
152
|
-
});
|
|
153
|
-
var buttonHandler;
|
|
154
|
-
var init_button = __esm(() => {
|
|
155
|
-
buttonHandler = {
|
|
156
|
-
create() {
|
|
157
|
-
const el = document.createElement("button");
|
|
158
|
-
el.style.border = "none";
|
|
159
|
-
el.style.background = "none";
|
|
160
|
-
el.style.padding = "0";
|
|
161
|
-
el.style.margin = "0";
|
|
162
|
-
el.style.font = "inherit";
|
|
163
|
-
el.style.color = "inherit";
|
|
164
|
-
el.style.cursor = "pointer";
|
|
165
|
-
el.style.display = "flex";
|
|
166
|
-
el.style.flexDirection = "column";
|
|
167
|
-
el.style.alignItems = "flex-start";
|
|
168
|
-
el.dataset.hypenType = "button";
|
|
169
|
-
return el;
|
|
170
|
-
}
|
|
171
|
-
};
|
|
172
|
-
});
|
|
173
|
-
|
|
174
|
-
// src/dom/components/container.ts
|
|
175
|
-
var exports_container = {};
|
|
176
|
-
__export(exports_container, {
|
|
177
|
-
containerHandler: () => containerHandler
|
|
178
|
-
});
|
|
179
|
-
var containerHandler;
|
|
180
|
-
var init_container = __esm(() => {
|
|
181
|
-
containerHandler = {
|
|
182
|
-
create() {
|
|
183
|
-
const el = document.createElement("div");
|
|
184
|
-
el.dataset.hypenType = "container";
|
|
185
|
-
return el;
|
|
186
|
-
}
|
|
187
|
-
};
|
|
188
|
-
});
|
|
189
|
-
|
|
190
|
-
// src/dom/components/center.ts
|
|
191
|
-
var exports_center = {};
|
|
192
|
-
__export(exports_center, {
|
|
193
|
-
centerHandler: () => centerHandler
|
|
194
|
-
});
|
|
195
|
-
var centerHandler;
|
|
196
|
-
var init_center = __esm(() => {
|
|
197
|
-
centerHandler = {
|
|
198
|
-
create() {
|
|
199
|
-
const el = document.createElement("div");
|
|
200
|
-
el.style.display = "flex";
|
|
201
|
-
el.style.alignItems = "center";
|
|
202
|
-
el.style.justifyContent = "center";
|
|
203
|
-
el.style.width = "100%";
|
|
204
|
-
el.style.height = "100%";
|
|
205
|
-
el.style.alignSelf = "stretch";
|
|
206
|
-
el.dataset.hypenType = "center";
|
|
207
|
-
return el;
|
|
208
|
-
}
|
|
209
|
-
};
|
|
210
|
-
});
|
|
211
|
-
|
|
212
|
-
// src/dom/components/list.ts
|
|
213
|
-
var exports_list = {};
|
|
214
|
-
__export(exports_list, {
|
|
215
|
-
listHandler: () => listHandler
|
|
216
|
-
});
|
|
217
|
-
var listHandler;
|
|
218
|
-
var init_list = __esm(() => {
|
|
219
|
-
listHandler = {
|
|
220
|
-
create() {
|
|
221
|
-
const el = document.createElement("div");
|
|
222
|
-
el.style.display = "flex";
|
|
223
|
-
el.style.flexDirection = "column";
|
|
224
|
-
el.style.alignItems = "flex-start";
|
|
225
|
-
el.style.overflow = "auto";
|
|
226
|
-
el.dataset.hypenType = "list";
|
|
227
|
-
return el;
|
|
228
|
-
},
|
|
229
|
-
applyProps(el, props) {
|
|
230
|
-
const direction = props.direction || props["1"] || "vertical";
|
|
231
|
-
if (direction === "vertical") {
|
|
232
|
-
el.style.flexDirection = "column";
|
|
233
|
-
} else {
|
|
234
|
-
el.style.flexDirection = "row";
|
|
235
|
-
}
|
|
236
|
-
if (props.gap !== undefined) {
|
|
237
|
-
el.style.gap = typeof props.gap === "number" ? `${props.gap}px` : String(props.gap);
|
|
238
|
-
}
|
|
239
|
-
}
|
|
240
|
-
};
|
|
241
|
-
});
|
|
242
|
-
|
|
243
|
-
// src/dom/components/input.ts
|
|
244
|
-
var exports_input = {};
|
|
245
|
-
__export(exports_input, {
|
|
246
|
-
inputHandler: () => inputHandler
|
|
247
|
-
});
|
|
248
|
-
var inputHandler;
|
|
249
|
-
var init_input = __esm(() => {
|
|
250
|
-
inputHandler = {
|
|
251
|
-
create() {
|
|
252
|
-
const el = document.createElement("input");
|
|
253
|
-
el.dataset.hypenType = "input";
|
|
254
|
-
return el;
|
|
255
|
-
},
|
|
256
|
-
applyProps(el, props) {
|
|
257
|
-
const input = el;
|
|
258
|
-
if (props.type !== undefined) {
|
|
259
|
-
input.type = String(props.type);
|
|
260
|
-
}
|
|
261
|
-
if (props.placeholder !== undefined) {
|
|
262
|
-
input.placeholder = String(props.placeholder);
|
|
263
|
-
}
|
|
264
|
-
if (props.value !== undefined) {
|
|
265
|
-
input.value = String(props.value);
|
|
266
|
-
}
|
|
267
|
-
}
|
|
268
|
-
};
|
|
269
|
-
});
|
|
270
|
-
|
|
271
|
-
// src/dom/components/link.ts
|
|
272
|
-
var exports_link = {};
|
|
273
|
-
__export(exports_link, {
|
|
274
|
-
linkHandler: () => linkHandler
|
|
275
|
-
});
|
|
276
|
-
var linkHandler;
|
|
277
|
-
var init_link = __esm(() => {
|
|
278
|
-
linkHandler = {
|
|
279
|
-
create() {
|
|
280
|
-
const el = document.createElement("a");
|
|
281
|
-
el.dataset.hypenType = "link";
|
|
282
|
-
return el;
|
|
283
|
-
},
|
|
284
|
-
applyProps(el, props) {
|
|
285
|
-
const anchor = el;
|
|
286
|
-
const href = props["0"] || props.href;
|
|
287
|
-
if (href !== undefined) {
|
|
288
|
-
anchor.href = String(href);
|
|
289
|
-
}
|
|
290
|
-
if (props.target !== undefined) {
|
|
291
|
-
anchor.target = String(props.target);
|
|
292
|
-
}
|
|
293
|
-
if (props.rel !== undefined) {
|
|
294
|
-
anchor.rel = String(props.rel);
|
|
295
|
-
}
|
|
296
|
-
}
|
|
297
|
-
};
|
|
298
|
-
});
|
|
299
|
-
|
|
300
|
-
// src/dom/components/textarea.ts
|
|
301
|
-
var exports_textarea = {};
|
|
302
|
-
__export(exports_textarea, {
|
|
303
|
-
textareaHandler: () => textareaHandler
|
|
304
|
-
});
|
|
305
|
-
var textareaHandler;
|
|
306
|
-
var init_textarea = __esm(() => {
|
|
307
|
-
textareaHandler = {
|
|
308
|
-
create() {
|
|
309
|
-
const el = document.createElement("textarea");
|
|
310
|
-
el.dataset.hypenType = "textarea";
|
|
311
|
-
return el;
|
|
312
|
-
},
|
|
313
|
-
applyProps(el, props) {
|
|
314
|
-
const textarea = el;
|
|
315
|
-
const value = props.value ?? props["0"];
|
|
316
|
-
if (value !== undefined) {
|
|
317
|
-
textarea.value = String(value);
|
|
318
|
-
}
|
|
319
|
-
if (props.placeholder !== undefined) {
|
|
320
|
-
textarea.placeholder = String(props.placeholder);
|
|
321
|
-
}
|
|
322
|
-
if (props.rows !== undefined) {
|
|
323
|
-
textarea.rows = Number(props.rows);
|
|
324
|
-
}
|
|
325
|
-
if (props.cols !== undefined) {
|
|
326
|
-
textarea.cols = Number(props.cols);
|
|
327
|
-
}
|
|
328
|
-
if (props.disabled !== undefined) {
|
|
329
|
-
textarea.disabled = Boolean(props.disabled);
|
|
330
|
-
}
|
|
331
|
-
if (props.readonly !== undefined) {
|
|
332
|
-
textarea.readOnly = Boolean(props.readonly);
|
|
333
|
-
}
|
|
334
|
-
}
|
|
335
|
-
};
|
|
336
|
-
});
|
|
337
|
-
|
|
338
|
-
// src/dom/components/checkbox.ts
|
|
339
|
-
var exports_checkbox = {};
|
|
340
|
-
__export(exports_checkbox, {
|
|
341
|
-
checkboxHandler: () => checkboxHandler
|
|
342
|
-
});
|
|
343
|
-
var checkboxHandler;
|
|
344
|
-
var init_checkbox = __esm(() => {
|
|
345
|
-
checkboxHandler = {
|
|
346
|
-
create() {
|
|
347
|
-
const wrapper = document.createElement("label");
|
|
348
|
-
wrapper.dataset.hypenType = "checkbox";
|
|
349
|
-
wrapper.style.display = "inline-flex";
|
|
350
|
-
wrapper.style.alignItems = "center";
|
|
351
|
-
wrapper.style.gap = "8px";
|
|
352
|
-
wrapper.style.cursor = "pointer";
|
|
353
|
-
const input = document.createElement("input");
|
|
354
|
-
input.type = "checkbox";
|
|
355
|
-
input.dataset.hypenCheckbox = "true";
|
|
356
|
-
wrapper.appendChild(input);
|
|
357
|
-
return wrapper;
|
|
358
|
-
},
|
|
359
|
-
applyProps(el, props) {
|
|
360
|
-
const input = el.querySelector('input[type="checkbox"]');
|
|
361
|
-
if (!input)
|
|
362
|
-
return;
|
|
363
|
-
if (props.checked !== undefined) {
|
|
364
|
-
input.checked = Boolean(props.checked);
|
|
365
|
-
}
|
|
366
|
-
if (props.disabled !== undefined) {
|
|
367
|
-
input.disabled = Boolean(props.disabled);
|
|
368
|
-
}
|
|
369
|
-
const label = props["0"] || props.label;
|
|
370
|
-
if (label !== undefined) {
|
|
371
|
-
const textNodes = Array.from(el.childNodes).filter((node) => node.nodeType === Node.TEXT_NODE);
|
|
372
|
-
textNodes.forEach((node) => node.remove());
|
|
373
|
-
el.appendChild(document.createTextNode(String(label)));
|
|
374
|
-
}
|
|
375
|
-
}
|
|
376
|
-
};
|
|
377
|
-
});
|
|
378
|
-
|
|
379
|
-
// src/dom/components/select.ts
|
|
380
|
-
var exports_select = {};
|
|
381
|
-
__export(exports_select, {
|
|
382
|
-
selectHandler: () => selectHandler
|
|
383
|
-
});
|
|
384
|
-
var selectHandler;
|
|
385
|
-
var init_select = __esm(() => {
|
|
386
|
-
selectHandler = {
|
|
387
|
-
create() {
|
|
388
|
-
const el = document.createElement("select");
|
|
389
|
-
el.dataset.hypenType = "select";
|
|
390
|
-
return el;
|
|
391
|
-
},
|
|
392
|
-
applyProps(el, props) {
|
|
393
|
-
const select = el;
|
|
394
|
-
if (props.value !== undefined) {
|
|
395
|
-
select.value = String(props.value);
|
|
396
|
-
}
|
|
397
|
-
if (props.disabled !== undefined) {
|
|
398
|
-
select.disabled = Boolean(props.disabled);
|
|
399
|
-
}
|
|
400
|
-
if (props.multiple !== undefined) {
|
|
401
|
-
select.multiple = Boolean(props.multiple);
|
|
402
|
-
}
|
|
403
|
-
if (props.options && Array.isArray(props.options)) {
|
|
404
|
-
select.innerHTML = "";
|
|
405
|
-
props.options.forEach((opt) => {
|
|
406
|
-
const option = document.createElement("option");
|
|
407
|
-
if (typeof opt === "string") {
|
|
408
|
-
option.value = opt;
|
|
409
|
-
option.textContent = opt;
|
|
410
|
-
} else if (typeof opt === "object") {
|
|
411
|
-
option.value = String(opt.value ?? opt.label ?? "");
|
|
412
|
-
option.textContent = String(opt.label ?? opt.value ?? "");
|
|
413
|
-
if (opt.disabled)
|
|
414
|
-
option.disabled = true;
|
|
415
|
-
}
|
|
416
|
-
select.appendChild(option);
|
|
417
|
-
});
|
|
418
|
-
}
|
|
419
|
-
}
|
|
420
|
-
};
|
|
421
|
-
});
|
|
422
|
-
|
|
423
|
-
// src/dom/components/spacer.ts
|
|
424
|
-
var exports_spacer = {};
|
|
425
|
-
__export(exports_spacer, {
|
|
426
|
-
spacerHandler: () => spacerHandler
|
|
427
|
-
});
|
|
428
|
-
var spacerHandler;
|
|
429
|
-
var init_spacer = __esm(() => {
|
|
430
|
-
spacerHandler = {
|
|
431
|
-
create() {
|
|
432
|
-
const el = document.createElement("div");
|
|
433
|
-
el.style.flex = "1";
|
|
434
|
-
el.dataset.hypenType = "spacer";
|
|
435
|
-
return el;
|
|
436
|
-
}
|
|
437
|
-
};
|
|
438
|
-
});
|
|
439
|
-
|
|
440
|
-
// src/dom/components/stack.ts
|
|
441
|
-
var exports_stack = {};
|
|
442
|
-
__export(exports_stack, {
|
|
443
|
-
stackHandler: () => stackHandler
|
|
444
|
-
});
|
|
445
|
-
function ensureStackStyles() {
|
|
446
|
-
if (stackStylesInjected)
|
|
447
|
-
return;
|
|
448
|
-
stackStylesInjected = true;
|
|
449
|
-
const style = document.createElement("style");
|
|
450
|
-
style.id = "hypen-stack-styles";
|
|
451
|
-
style.textContent = `
|
|
452
|
-
[data-hypen-type="stack"] {
|
|
453
|
-
position: relative;
|
|
454
|
-
display: grid;
|
|
455
|
-
grid-template-areas: "stack";
|
|
456
|
-
/* Default alignment: top-left (matching iOS/Android ZStack default) */
|
|
457
|
-
justify-items: start;
|
|
458
|
-
align-items: start;
|
|
459
|
-
/* Ensure Stack participates properly in flex layouts (Row/Column) */
|
|
460
|
-
min-width: 0;
|
|
461
|
-
min-height: 0;
|
|
462
|
-
}
|
|
463
|
-
[data-hypen-type="stack"] > * {
|
|
464
|
-
grid-area: stack;
|
|
465
|
-
/* Don't set justify-self/align-self here - let parent's justify-items/align-items control */
|
|
466
|
-
}
|
|
467
|
-
`;
|
|
468
|
-
document.head.appendChild(style);
|
|
469
|
-
}
|
|
470
|
-
var stackStylesInjected = false, stackHandler;
|
|
471
|
-
var init_stack = __esm(() => {
|
|
472
|
-
stackHandler = {
|
|
473
|
-
create() {
|
|
474
|
-
ensureStackStyles();
|
|
475
|
-
const el = document.createElement("div");
|
|
476
|
-
el.dataset.hypenType = "stack";
|
|
477
|
-
return el;
|
|
478
|
-
}
|
|
479
|
-
};
|
|
480
|
-
});
|
|
481
|
-
|
|
482
|
-
// src/dom/components/divider.ts
|
|
483
|
-
var exports_divider = {};
|
|
484
|
-
__export(exports_divider, {
|
|
485
|
-
dividerHandler: () => dividerHandler
|
|
486
|
-
});
|
|
487
|
-
var dividerHandler;
|
|
488
|
-
var init_divider = __esm(() => {
|
|
489
|
-
dividerHandler = {
|
|
490
|
-
create() {
|
|
491
|
-
const el = document.createElement("hr");
|
|
492
|
-
el.dataset.hypenType = "divider";
|
|
493
|
-
el.style.border = "none";
|
|
494
|
-
el.style.borderTop = "1px solid #e0e0e0";
|
|
495
|
-
el.style.margin = "0";
|
|
496
|
-
return el;
|
|
497
|
-
},
|
|
498
|
-
applyProps(el, props) {
|
|
499
|
-
if (props.thickness !== undefined) {
|
|
500
|
-
const thickness = typeof props.thickness === "number" ? `${props.thickness}px` : String(props.thickness);
|
|
501
|
-
el.style.borderTopWidth = thickness;
|
|
502
|
-
}
|
|
503
|
-
if (props.orientation === "vertical") {
|
|
504
|
-
el.style.borderTop = "none";
|
|
505
|
-
el.style.borderLeft = "1px solid #e0e0e0";
|
|
506
|
-
el.style.height = "100%";
|
|
507
|
-
el.style.width = "0";
|
|
508
|
-
el.style.display = "inline-block";
|
|
509
|
-
}
|
|
510
|
-
}
|
|
511
|
-
};
|
|
512
|
-
});
|
|
513
|
-
|
|
514
|
-
// src/dom/components/grid.ts
|
|
515
|
-
var exports_grid = {};
|
|
516
|
-
__export(exports_grid, {
|
|
517
|
-
gridHandler: () => gridHandler
|
|
518
|
-
});
|
|
519
|
-
function ensureGridStyles() {
|
|
520
|
-
if (gridStylesInjected)
|
|
521
|
-
return;
|
|
522
|
-
gridStylesInjected = true;
|
|
523
|
-
const style = document.createElement("style");
|
|
524
|
-
style.id = "hypen-grid-styles";
|
|
525
|
-
style.textContent = `
|
|
526
|
-
/* Grid children stretch to fill cells by default (matches Android behavior) */
|
|
527
|
-
[data-hypen-type="grid"] > * {
|
|
528
|
-
justify-self: stretch;
|
|
529
|
-
align-self: stretch;
|
|
530
|
-
}
|
|
531
|
-
`;
|
|
532
|
-
document.head.appendChild(style);
|
|
533
|
-
}
|
|
534
|
-
var gridStylesInjected = false, gridHandler;
|
|
535
|
-
var init_grid = __esm(() => {
|
|
536
|
-
gridHandler = {
|
|
537
|
-
create() {
|
|
538
|
-
ensureGridStyles();
|
|
539
|
-
const el = document.createElement("div");
|
|
540
|
-
el.style.display = "grid";
|
|
541
|
-
el.dataset.hypenType = "grid";
|
|
542
|
-
return el;
|
|
543
|
-
},
|
|
544
|
-
applyProps(el, props) {
|
|
545
|
-
if (props.columns !== undefined) {
|
|
546
|
-
const columns = typeof props.columns === "number" ? `repeat(${props.columns}, 1fr)` : String(props.columns);
|
|
547
|
-
el.style.gridTemplateColumns = columns;
|
|
548
|
-
}
|
|
549
|
-
if (props.rows !== undefined) {
|
|
550
|
-
const rows = typeof props.rows === "number" ? `repeat(${props.rows}, 1fr)` : String(props.rows);
|
|
551
|
-
el.style.gridTemplateRows = rows;
|
|
552
|
-
}
|
|
553
|
-
if (props.gap !== undefined) {
|
|
554
|
-
const gap = typeof props.gap === "number" ? `${props.gap}px` : String(props.gap);
|
|
555
|
-
el.style.gap = gap;
|
|
556
|
-
}
|
|
557
|
-
}
|
|
558
|
-
};
|
|
559
|
-
});
|
|
560
|
-
|
|
561
|
-
// src/dom/components/card.ts
|
|
562
|
-
var exports_card = {};
|
|
563
|
-
__export(exports_card, {
|
|
564
|
-
cardHandler: () => cardHandler
|
|
565
|
-
});
|
|
566
|
-
var cardHandler;
|
|
567
|
-
var init_card = __esm(() => {
|
|
568
|
-
cardHandler = {
|
|
569
|
-
create() {
|
|
570
|
-
const el = document.createElement("div");
|
|
571
|
-
el.dataset.hypenType = "card";
|
|
572
|
-
el.style.backgroundColor = "#ffffff";
|
|
573
|
-
el.style.borderRadius = "8px";
|
|
574
|
-
el.style.boxShadow = "0 2px 4px rgba(0, 0, 0, 0.1)";
|
|
575
|
-
el.style.padding = "16px";
|
|
576
|
-
return el;
|
|
577
|
-
}
|
|
578
|
-
};
|
|
579
|
-
});
|
|
580
|
-
|
|
581
|
-
// src/dom/components/heading.ts
|
|
582
|
-
var exports_heading = {};
|
|
583
|
-
__export(exports_heading, {
|
|
584
|
-
headingHandler: () => headingHandler
|
|
585
|
-
});
|
|
586
|
-
var headingHandler;
|
|
587
|
-
var init_heading = __esm(() => {
|
|
588
|
-
headingHandler = {
|
|
589
|
-
create() {
|
|
590
|
-
const el = document.createElement("h2");
|
|
591
|
-
el.dataset.hypenType = "heading";
|
|
592
|
-
return el;
|
|
593
|
-
},
|
|
594
|
-
applyProps(el, props) {
|
|
595
|
-
if (props.level !== undefined) {
|
|
596
|
-
const level = Math.max(1, Math.min(6, Number(props.level)));
|
|
597
|
-
const newEl = document.createElement(`h${level}`);
|
|
598
|
-
newEl.dataset.hypenType = "heading";
|
|
599
|
-
newEl.innerHTML = el.innerHTML;
|
|
600
|
-
Array.from(el.attributes).forEach((attr) => {
|
|
601
|
-
newEl.setAttribute(attr.name, attr.value);
|
|
602
|
-
});
|
|
603
|
-
if (el.parentNode) {
|
|
604
|
-
el.parentNode.replaceChild(newEl, el);
|
|
605
|
-
}
|
|
606
|
-
}
|
|
607
|
-
const text = props["0"] || props.text;
|
|
608
|
-
if (text !== undefined) {
|
|
609
|
-
el.textContent = String(text);
|
|
610
|
-
}
|
|
611
|
-
}
|
|
612
|
-
};
|
|
613
|
-
});
|
|
614
|
-
|
|
615
|
-
// src/dom/components/switch.ts
|
|
616
|
-
var exports_switch = {};
|
|
617
|
-
__export(exports_switch, {
|
|
618
|
-
switchHandler: () => switchHandler
|
|
619
|
-
});
|
|
620
|
-
var switchHandler;
|
|
621
|
-
var init_switch = __esm(() => {
|
|
622
|
-
switchHandler = {
|
|
623
|
-
create() {
|
|
624
|
-
const wrapper = document.createElement("label");
|
|
625
|
-
wrapper.dataset.hypenType = "switch";
|
|
626
|
-
wrapper.style.display = "inline-flex";
|
|
627
|
-
wrapper.style.alignItems = "center";
|
|
628
|
-
wrapper.style.gap = "8px";
|
|
629
|
-
wrapper.style.cursor = "pointer";
|
|
630
|
-
const input = document.createElement("input");
|
|
631
|
-
input.type = "checkbox";
|
|
632
|
-
input.dataset.hypenSwitch = "true";
|
|
633
|
-
input.style.appearance = "none";
|
|
634
|
-
input.style.width = "44px";
|
|
635
|
-
input.style.height = "24px";
|
|
636
|
-
input.style.backgroundColor = "#ccc";
|
|
637
|
-
input.style.borderRadius = "12px";
|
|
638
|
-
input.style.position = "relative";
|
|
639
|
-
input.style.cursor = "pointer";
|
|
640
|
-
input.style.transition = "background-color 0.2s";
|
|
641
|
-
const style = document.createElement("style");
|
|
642
|
-
style.textContent = `
|
|
643
|
-
input[data-hypen-switch="true"]::before {
|
|
644
|
-
content: "";
|
|
645
|
-
position: absolute;
|
|
646
|
-
width: 20px;
|
|
647
|
-
height: 20px;
|
|
648
|
-
background-color: white;
|
|
649
|
-
border-radius: 50%;
|
|
650
|
-
top: 2px;
|
|
651
|
-
left: 2px;
|
|
652
|
-
transition: transform 0.2s;
|
|
653
|
-
}
|
|
654
|
-
input[data-hypen-switch="true"]:checked {
|
|
655
|
-
background-color: #4CAF50;
|
|
656
|
-
}
|
|
657
|
-
input[data-hypen-switch="true"]:checked::before {
|
|
658
|
-
transform: translateX(20px);
|
|
659
|
-
}
|
|
660
|
-
`;
|
|
661
|
-
wrapper.appendChild(style);
|
|
662
|
-
wrapper.appendChild(input);
|
|
663
|
-
return wrapper;
|
|
664
|
-
},
|
|
665
|
-
applyProps(el, props) {
|
|
666
|
-
const input = el.querySelector('input[type="checkbox"]');
|
|
667
|
-
if (!input)
|
|
668
|
-
return;
|
|
669
|
-
if (props.on !== undefined) {
|
|
670
|
-
input.checked = Boolean(props.on);
|
|
671
|
-
}
|
|
672
|
-
if (props.disabled !== undefined) {
|
|
673
|
-
input.disabled = Boolean(props.disabled);
|
|
674
|
-
}
|
|
675
|
-
const label = props["0"] || props.label;
|
|
676
|
-
if (label !== undefined) {
|
|
677
|
-
const textNodes = Array.from(el.childNodes).filter((node) => node.nodeType === Node.TEXT_NODE);
|
|
678
|
-
textNodes.forEach((node) => node.remove());
|
|
679
|
-
el.appendChild(document.createTextNode(String(label)));
|
|
680
|
-
}
|
|
681
|
-
}
|
|
682
|
-
};
|
|
683
|
-
});
|
|
684
|
-
|
|
685
|
-
// src/dom/components/slider.ts
|
|
686
|
-
var exports_slider = {};
|
|
687
|
-
__export(exports_slider, {
|
|
688
|
-
sliderHandler: () => sliderHandler
|
|
689
|
-
});
|
|
690
|
-
var sliderHandler;
|
|
691
|
-
var init_slider = __esm(() => {
|
|
692
|
-
sliderHandler = {
|
|
693
|
-
create() {
|
|
694
|
-
const el = document.createElement("input");
|
|
695
|
-
el.type = "range";
|
|
696
|
-
el.dataset.hypenType = "slider";
|
|
697
|
-
return el;
|
|
698
|
-
},
|
|
699
|
-
applyProps(el, props) {
|
|
700
|
-
const input = el;
|
|
701
|
-
if (props.value !== undefined) {
|
|
702
|
-
input.value = String(props.value);
|
|
703
|
-
}
|
|
704
|
-
if (props.min !== undefined) {
|
|
705
|
-
input.min = String(props.min);
|
|
706
|
-
}
|
|
707
|
-
if (props.max !== undefined) {
|
|
708
|
-
input.max = String(props.max);
|
|
709
|
-
}
|
|
710
|
-
if (props.step !== undefined) {
|
|
711
|
-
input.step = String(props.step);
|
|
712
|
-
}
|
|
713
|
-
if (props.disabled !== undefined) {
|
|
714
|
-
input.disabled = Boolean(props.disabled);
|
|
715
|
-
}
|
|
716
|
-
}
|
|
717
|
-
};
|
|
718
|
-
});
|
|
719
|
-
|
|
720
|
-
// src/dom/components/spinner.ts
|
|
721
|
-
var exports_spinner = {};
|
|
722
|
-
__export(exports_spinner, {
|
|
723
|
-
spinnerHandler: () => spinnerHandler
|
|
724
|
-
});
|
|
725
|
-
var spinnerHandler;
|
|
726
|
-
var init_spinner = __esm(() => {
|
|
727
|
-
spinnerHandler = {
|
|
728
|
-
create() {
|
|
729
|
-
const wrapper = document.createElement("div");
|
|
730
|
-
wrapper.dataset.hypenType = "spinner";
|
|
731
|
-
wrapper.style.display = "inline-block";
|
|
732
|
-
const spinner = document.createElement("div");
|
|
733
|
-
spinner.style.width = "40px";
|
|
734
|
-
spinner.style.height = "40px";
|
|
735
|
-
spinner.style.border = "4px solid #f3f3f3";
|
|
736
|
-
spinner.style.borderTop = "4px solid #3498db";
|
|
737
|
-
spinner.style.borderRadius = "50%";
|
|
738
|
-
spinner.style.animation = "spin 1s linear infinite";
|
|
739
|
-
const style = document.createElement("style");
|
|
740
|
-
style.textContent = `
|
|
741
|
-
@keyframes spin {
|
|
742
|
-
0% { transform: rotate(0deg); }
|
|
743
|
-
100% { transform: rotate(360deg); }
|
|
744
|
-
}
|
|
745
|
-
`;
|
|
746
|
-
wrapper.appendChild(style);
|
|
747
|
-
wrapper.appendChild(spinner);
|
|
748
|
-
return wrapper;
|
|
749
|
-
},
|
|
750
|
-
applyProps(el, props) {
|
|
751
|
-
const spinner = el.querySelector("div:not(style)");
|
|
752
|
-
if (!spinner)
|
|
753
|
-
return;
|
|
754
|
-
if (props.size !== undefined) {
|
|
755
|
-
const size = String(props.size);
|
|
756
|
-
const sizeMap = {
|
|
757
|
-
small: "24px",
|
|
758
|
-
medium: "40px",
|
|
759
|
-
large: "60px"
|
|
760
|
-
};
|
|
761
|
-
const actualSize = sizeMap[size] || size;
|
|
762
|
-
spinner.style.width = actualSize;
|
|
763
|
-
spinner.style.height = actualSize;
|
|
764
|
-
}
|
|
765
|
-
if (props.color !== undefined) {
|
|
766
|
-
spinner.style.borderTopColor = String(props.color);
|
|
767
|
-
}
|
|
768
|
-
}
|
|
769
|
-
};
|
|
770
|
-
});
|
|
771
|
-
|
|
772
|
-
// src/dom/components/badge.ts
|
|
773
|
-
var exports_badge = {};
|
|
774
|
-
__export(exports_badge, {
|
|
775
|
-
badgeHandler: () => badgeHandler
|
|
776
|
-
});
|
|
777
|
-
var badgeHandler;
|
|
778
|
-
var init_badge = __esm(() => {
|
|
779
|
-
badgeHandler = {
|
|
780
|
-
create() {
|
|
781
|
-
const el = document.createElement("span");
|
|
782
|
-
el.dataset.hypenType = "badge";
|
|
783
|
-
el.style.display = "inline-block";
|
|
784
|
-
el.style.padding = "4px 8px";
|
|
785
|
-
el.style.borderRadius = "4px";
|
|
786
|
-
el.style.fontSize = "12px";
|
|
787
|
-
el.style.fontWeight = "600";
|
|
788
|
-
el.style.backgroundColor = "#e0e0e0";
|
|
789
|
-
el.style.color = "#333";
|
|
790
|
-
return el;
|
|
791
|
-
},
|
|
792
|
-
applyProps(el, props) {
|
|
793
|
-
if (props.theme !== undefined) {
|
|
794
|
-
const theme = String(props.theme);
|
|
795
|
-
const themeColors = {
|
|
796
|
-
success: { bg: "#4CAF50", color: "#fff" },
|
|
797
|
-
error: { bg: "#f44336", color: "#fff" },
|
|
798
|
-
warning: { bg: "#ff9800", color: "#fff" },
|
|
799
|
-
info: { bg: "#2196F3", color: "#fff" },
|
|
800
|
-
default: { bg: "#e0e0e0", color: "#333" }
|
|
1
|
+
/**
|
|
2
|
+
* Hypen - High-Level API for Web Applications
|
|
3
|
+
*
|
|
4
|
+
* Simple API for rendering Hypen applications (like ReactDOM.render)
|
|
5
|
+
*/
|
|
6
|
+
import { Engine } from "@hypen-space/core/engine/browser";
|
|
7
|
+
import { HypenModuleInstance } from "@hypen-space/core/app";
|
|
8
|
+
import { HypenRouter } from "@hypen-space/core/router";
|
|
9
|
+
import { HypenGlobalContext } from "@hypen-space/core/context";
|
|
10
|
+
import { componentLoader } from "@hypen-space/core/loader";
|
|
11
|
+
import { Router, Route, Link } from "@hypen-space/core/components";
|
|
12
|
+
import { frameworkLoggers, setDebugMode } from "@hypen-space/core/logger";
|
|
13
|
+
import { DOMRenderer } from "./dom/renderer.js";
|
|
14
|
+
const log = frameworkLoggers.hypen;
|
|
15
|
+
export class Hypen {
|
|
16
|
+
engine = null;
|
|
17
|
+
renderer = null;
|
|
18
|
+
moduleInstance = null;
|
|
19
|
+
container = null;
|
|
20
|
+
config;
|
|
21
|
+
router;
|
|
22
|
+
globalContext;
|
|
23
|
+
moduleInstances = new Map();
|
|
24
|
+
constructor(config = {}) {
|
|
25
|
+
this.config = {
|
|
26
|
+
componentsDir: "./src/components",
|
|
27
|
+
debug: false,
|
|
28
|
+
...config,
|
|
801
29
|
};
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
}
|
|
806
|
-
const text = props["0"] || props.text;
|
|
807
|
-
if (text !== undefined) {
|
|
808
|
-
el.textContent = String(text);
|
|
809
|
-
}
|
|
810
|
-
}
|
|
811
|
-
};
|
|
812
|
-
});
|
|
813
|
-
|
|
814
|
-
// src/dom/components/avatar.ts
|
|
815
|
-
var exports_avatar = {};
|
|
816
|
-
__export(exports_avatar, {
|
|
817
|
-
avatarHandler: () => avatarHandler
|
|
818
|
-
});
|
|
819
|
-
var avatarHandler;
|
|
820
|
-
var init_avatar = __esm(() => {
|
|
821
|
-
avatarHandler = {
|
|
822
|
-
create() {
|
|
823
|
-
const el = document.createElement("div");
|
|
824
|
-
el.dataset.hypenType = "avatar";
|
|
825
|
-
el.style.display = "inline-flex";
|
|
826
|
-
el.style.alignItems = "center";
|
|
827
|
-
el.style.justifyContent = "center";
|
|
828
|
-
el.style.width = "40px";
|
|
829
|
-
el.style.height = "40px";
|
|
830
|
-
el.style.borderRadius = "50%";
|
|
831
|
-
el.style.backgroundColor = "#9e9e9e";
|
|
832
|
-
el.style.color = "#fff";
|
|
833
|
-
el.style.fontSize = "16px";
|
|
834
|
-
el.style.fontWeight = "600";
|
|
835
|
-
el.style.overflow = "hidden";
|
|
836
|
-
return el;
|
|
837
|
-
},
|
|
838
|
-
applyProps(el, props) {
|
|
839
|
-
const src = props["src.0"] || props["0"] || props.src || props.source;
|
|
840
|
-
if (src !== undefined) {
|
|
841
|
-
const img = document.createElement("img");
|
|
842
|
-
img.src = String(src);
|
|
843
|
-
img.style.width = "100%";
|
|
844
|
-
img.style.height = "100%";
|
|
845
|
-
img.style.objectFit = "cover";
|
|
846
|
-
el.innerHTML = "";
|
|
847
|
-
el.appendChild(img);
|
|
848
|
-
} else if (props.initials !== undefined) {
|
|
849
|
-
el.textContent = String(props.initials).toUpperCase();
|
|
850
|
-
}
|
|
851
|
-
if (props.size !== undefined) {
|
|
852
|
-
const size = typeof props.size === "number" ? `${props.size}px` : String(props.size);
|
|
853
|
-
el.style.width = size;
|
|
854
|
-
el.style.height = size;
|
|
855
|
-
}
|
|
856
|
-
}
|
|
857
|
-
};
|
|
858
|
-
});
|
|
859
|
-
|
|
860
|
-
// src/dom/components/progressbar.ts
|
|
861
|
-
var exports_progressbar = {};
|
|
862
|
-
__export(exports_progressbar, {
|
|
863
|
-
progressBarHandler: () => progressBarHandler
|
|
864
|
-
});
|
|
865
|
-
var progressBarHandler;
|
|
866
|
-
var init_progressbar = __esm(() => {
|
|
867
|
-
progressBarHandler = {
|
|
868
|
-
create() {
|
|
869
|
-
const wrapper = document.createElement("div");
|
|
870
|
-
wrapper.dataset.hypenType = "progressbar";
|
|
871
|
-
wrapper.style.width = "100%";
|
|
872
|
-
wrapper.style.height = "8px";
|
|
873
|
-
wrapper.style.backgroundColor = "#e0e0e0";
|
|
874
|
-
wrapper.style.borderRadius = "4px";
|
|
875
|
-
wrapper.style.overflow = "hidden";
|
|
876
|
-
const bar = document.createElement("div");
|
|
877
|
-
bar.dataset.hypenBar = "true";
|
|
878
|
-
bar.style.height = "100%";
|
|
879
|
-
bar.style.backgroundColor = "#2196F3";
|
|
880
|
-
bar.style.transition = "width 0.3s ease";
|
|
881
|
-
bar.style.width = "0%";
|
|
882
|
-
wrapper.appendChild(bar);
|
|
883
|
-
return wrapper;
|
|
884
|
-
},
|
|
885
|
-
applyProps(el, props) {
|
|
886
|
-
const bar = el.querySelector('[data-hypen-bar="true"]');
|
|
887
|
-
if (!bar)
|
|
888
|
-
return;
|
|
889
|
-
const value = Number(props.value || 0);
|
|
890
|
-
const max = Number(props.max || 100);
|
|
891
|
-
const percentage = Math.min(100, Math.max(0, value / max * 100));
|
|
892
|
-
bar.style.width = `${percentage}%`;
|
|
893
|
-
if (props.color !== undefined) {
|
|
894
|
-
bar.style.backgroundColor = String(props.color);
|
|
895
|
-
}
|
|
896
|
-
if (props.height !== undefined) {
|
|
897
|
-
const height = typeof props.height === "number" ? `${props.height}px` : String(props.height);
|
|
898
|
-
el.style.height = height;
|
|
899
|
-
}
|
|
900
|
-
}
|
|
901
|
-
};
|
|
902
|
-
});
|
|
903
|
-
|
|
904
|
-
// src/dom/components/video.ts
|
|
905
|
-
var exports_video = {};
|
|
906
|
-
__export(exports_video, {
|
|
907
|
-
videoHandler: () => videoHandler
|
|
908
|
-
});
|
|
909
|
-
var videoHandler;
|
|
910
|
-
var init_video = __esm(() => {
|
|
911
|
-
videoHandler = {
|
|
912
|
-
create() {
|
|
913
|
-
const el = document.createElement("video");
|
|
914
|
-
el.dataset.hypenType = "video";
|
|
915
|
-
return el;
|
|
916
|
-
},
|
|
917
|
-
applyProps(el, props) {
|
|
918
|
-
const video = el;
|
|
919
|
-
const src = props["0"] || props.src;
|
|
920
|
-
if (src !== undefined) {
|
|
921
|
-
video.src = String(src);
|
|
922
|
-
}
|
|
923
|
-
if (props.controls !== undefined) {
|
|
924
|
-
video.controls = Boolean(props.controls);
|
|
925
|
-
}
|
|
926
|
-
if (props.autoplay !== undefined) {
|
|
927
|
-
video.autoplay = Boolean(props.autoplay);
|
|
928
|
-
}
|
|
929
|
-
if (props.loop !== undefined) {
|
|
930
|
-
video.loop = Boolean(props.loop);
|
|
931
|
-
}
|
|
932
|
-
if (props.muted !== undefined) {
|
|
933
|
-
video.muted = Boolean(props.muted);
|
|
934
|
-
}
|
|
935
|
-
if (props.poster !== undefined) {
|
|
936
|
-
video.poster = String(props.poster);
|
|
937
|
-
}
|
|
938
|
-
}
|
|
939
|
-
};
|
|
940
|
-
});
|
|
941
|
-
|
|
942
|
-
// src/dom/components/audio.ts
|
|
943
|
-
var exports_audio = {};
|
|
944
|
-
__export(exports_audio, {
|
|
945
|
-
audioHandler: () => audioHandler
|
|
946
|
-
});
|
|
947
|
-
var audioHandler;
|
|
948
|
-
var init_audio = __esm(() => {
|
|
949
|
-
audioHandler = {
|
|
950
|
-
create() {
|
|
951
|
-
const el = document.createElement("audio");
|
|
952
|
-
el.dataset.hypenType = "audio";
|
|
953
|
-
return el;
|
|
954
|
-
},
|
|
955
|
-
applyProps(el, props) {
|
|
956
|
-
const audio = el;
|
|
957
|
-
const src = props["0"] || props.src;
|
|
958
|
-
if (src !== undefined) {
|
|
959
|
-
audio.src = String(src);
|
|
960
|
-
}
|
|
961
|
-
if (props.controls !== undefined) {
|
|
962
|
-
audio.controls = Boolean(props.controls);
|
|
963
|
-
}
|
|
964
|
-
if (props.autoplay !== undefined) {
|
|
965
|
-
audio.autoplay = Boolean(props.autoplay);
|
|
966
|
-
}
|
|
967
|
-
if (props.loop !== undefined) {
|
|
968
|
-
audio.loop = Boolean(props.loop);
|
|
969
|
-
}
|
|
970
|
-
if (props.muted !== undefined) {
|
|
971
|
-
audio.muted = Boolean(props.muted);
|
|
972
|
-
}
|
|
973
|
-
}
|
|
974
|
-
};
|
|
975
|
-
});
|
|
976
|
-
|
|
977
|
-
// src/dom/components/paragraph.ts
|
|
978
|
-
var exports_paragraph = {};
|
|
979
|
-
__export(exports_paragraph, {
|
|
980
|
-
paragraphHandler: () => paragraphHandler
|
|
981
|
-
});
|
|
982
|
-
var paragraphHandler;
|
|
983
|
-
var init_paragraph = __esm(() => {
|
|
984
|
-
paragraphHandler = {
|
|
985
|
-
create() {
|
|
986
|
-
const el = document.createElement("p");
|
|
987
|
-
el.dataset.hypenType = "paragraph";
|
|
988
|
-
return el;
|
|
989
|
-
},
|
|
990
|
-
applyProps(el, props) {
|
|
991
|
-
const text = props["0"] || props.text;
|
|
992
|
-
if (text !== undefined) {
|
|
993
|
-
el.textContent = String(text);
|
|
994
|
-
}
|
|
995
|
-
}
|
|
996
|
-
};
|
|
997
|
-
});
|
|
998
|
-
|
|
999
|
-
// src/dom/components/router.ts
|
|
1000
|
-
var exports_router = {};
|
|
1001
|
-
__export(exports_router, {
|
|
1002
|
-
routerHandler: () => routerHandler
|
|
1003
|
-
});
|
|
1004
|
-
var routerHandler;
|
|
1005
|
-
var init_router = __esm(() => {
|
|
1006
|
-
routerHandler = {
|
|
1007
|
-
create() {
|
|
1008
|
-
const el = document.createElement("div");
|
|
1009
|
-
el.style.display = "flex";
|
|
1010
|
-
el.style.flexDirection = "column";
|
|
1011
|
-
el.style.width = "100%";
|
|
1012
|
-
el.dataset.hypenType = "router";
|
|
1013
|
-
return el;
|
|
1014
|
-
},
|
|
1015
|
-
applyProps(el, props) {}
|
|
1016
|
-
};
|
|
1017
|
-
});
|
|
1018
|
-
|
|
1019
|
-
// src/dom/components/route.ts
|
|
1020
|
-
var exports_route = {};
|
|
1021
|
-
__export(exports_route, {
|
|
1022
|
-
routeHandler: () => routeHandler
|
|
1023
|
-
});
|
|
1024
|
-
import { frameworkLoggers } from "@hypen-space/core/logger";
|
|
1025
|
-
var log, routeHandler;
|
|
1026
|
-
var init_route = __esm(() => {
|
|
1027
|
-
log = frameworkLoggers.router;
|
|
1028
|
-
routeHandler = {
|
|
1029
|
-
create() {
|
|
1030
|
-
const el = document.createElement("div");
|
|
1031
|
-
el.style.display = "flex";
|
|
1032
|
-
el.style.flexDirection = "column";
|
|
1033
|
-
el.style.width = "100%";
|
|
1034
|
-
el.dataset.hypenType = "route";
|
|
1035
|
-
el.dataset.routeRendered = "false";
|
|
1036
|
-
return el;
|
|
1037
|
-
},
|
|
1038
|
-
applyProps(el, props) {
|
|
1039
|
-
const path = props.path || props["0"] || "/";
|
|
1040
|
-
el.dataset.routePath = String(path);
|
|
1041
|
-
const isLazy = props.__lazy === true;
|
|
1042
|
-
el.dataset.routeLazy = String(isLazy);
|
|
1043
|
-
const componentName = props.component || props.__lazy_child;
|
|
1044
|
-
if (componentName) {
|
|
1045
|
-
el.dataset.routeComponent = String(componentName);
|
|
1046
|
-
}
|
|
1047
|
-
log.debug(`Route created: path="${path}", lazy=${isLazy}, component="${el.dataset.routeComponent || "none"}"`);
|
|
1048
|
-
}
|
|
1049
|
-
};
|
|
1050
|
-
});
|
|
1051
|
-
|
|
1052
|
-
// src/dom/components/hypenapp.ts
|
|
1053
|
-
var exports_hypenapp = {};
|
|
1054
|
-
__export(exports_hypenapp, {
|
|
1055
|
-
hypenAppHandler: () => hypenAppHandler,
|
|
1056
|
-
disconnectHypenApp: () => disconnectHypenApp
|
|
1057
|
-
});
|
|
1058
|
-
import { RemoteEngine } from "@hypen-space/core/remote/client";
|
|
1059
|
-
import { frameworkLoggers as frameworkLoggers2 } from "@hypen-space/core/logger";
|
|
1060
|
-
function applyPatches(container, nodes, patches, engine, onRoot) {
|
|
1061
|
-
for (const patch of patches) {
|
|
1062
|
-
switch (patch.type) {
|
|
1063
|
-
case "create": {
|
|
1064
|
-
const el = createElement(patch.elementType, patch.props || {});
|
|
1065
|
-
el.dataset.hypenId = patch.id;
|
|
1066
|
-
el.__hypenEngine = engine;
|
|
1067
|
-
nodes.set(patch.id, el);
|
|
1068
|
-
break;
|
|
1069
|
-
}
|
|
1070
|
-
case "setProp": {
|
|
1071
|
-
const el = nodes.get(patch.id);
|
|
1072
|
-
if (el) {
|
|
1073
|
-
applyProp(el, patch.name, patch.value);
|
|
30
|
+
// Enable debug mode if configured
|
|
31
|
+
if (this.config.debug) {
|
|
32
|
+
setDebugMode(true);
|
|
1074
33
|
}
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
34
|
+
// Initialize router and global context
|
|
35
|
+
this.router = new HypenRouter();
|
|
36
|
+
this.globalContext = new HypenGlobalContext();
|
|
37
|
+
// Register built-in components
|
|
38
|
+
componentLoader.register("Router", Router, "");
|
|
39
|
+
componentLoader.register("Route", Route, "");
|
|
40
|
+
componentLoader.register("Link", Link, "");
|
|
41
|
+
// Store hypen engine instance in global context for built-in component access
|
|
42
|
+
this.globalContext.__hypenEngine = this;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Initialize the Hypen runtime
|
|
46
|
+
* Must be called before render()
|
|
47
|
+
*/
|
|
48
|
+
async init() {
|
|
49
|
+
log.debug("Initializing...");
|
|
50
|
+
// Initialize engine
|
|
51
|
+
this.engine = new Engine();
|
|
52
|
+
await this.engine.init({
|
|
53
|
+
wasmUrl: this.config.wasmUrl,
|
|
54
|
+
jsUrl: this.config.jsUrl,
|
|
55
|
+
});
|
|
56
|
+
log.debug("Engine initialized");
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Load all components from the components directory
|
|
60
|
+
*/
|
|
61
|
+
async loadComponents(componentsDir) {
|
|
62
|
+
const dir = componentsDir || this.config.componentsDir;
|
|
63
|
+
log.debug(`Loading components from ${dir}...`);
|
|
64
|
+
await componentLoader.loadFromComponentsDir(dir);
|
|
65
|
+
log.debug(`Loaded ${componentLoader.getNames().length} components`);
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Render a component to a DOM container
|
|
69
|
+
*
|
|
70
|
+
* @param componentName - Name of the component to render (e.g., "HomePage")
|
|
71
|
+
* @param containerSelector - CSS selector or HTMLElement for the mount point
|
|
72
|
+
*/
|
|
73
|
+
async render(componentName, containerSelector) {
|
|
74
|
+
if (!this.engine) {
|
|
75
|
+
throw new Error("[Hypen] Engine not initialized. Call init() first.");
|
|
1081
76
|
}
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
const child = nodes.get(patch.id);
|
|
1088
|
-
const beforeId = patch.beforeId;
|
|
1089
|
-
if (parent && child) {
|
|
1090
|
-
if (parentId === "root") {
|
|
1091
|
-
onRoot(patch.id);
|
|
1092
|
-
}
|
|
1093
|
-
if (beforeId) {
|
|
1094
|
-
const before = nodes.get(beforeId);
|
|
1095
|
-
if (before && before.parentNode === parent) {
|
|
1096
|
-
parent.insertBefore(child, before);
|
|
1097
|
-
} else if (!parent.contains(child)) {
|
|
1098
|
-
parent.appendChild(child);
|
|
77
|
+
// Get the container element
|
|
78
|
+
if (typeof containerSelector === "string") {
|
|
79
|
+
const element = document.querySelector(containerSelector);
|
|
80
|
+
if (!element) {
|
|
81
|
+
throw new Error(`[Hypen] Container not found: ${containerSelector}`);
|
|
1099
82
|
}
|
|
1100
|
-
|
|
1101
|
-
parent.appendChild(child);
|
|
1102
|
-
}
|
|
83
|
+
this.container = element;
|
|
1103
84
|
}
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
case "move": {
|
|
1107
|
-
const parentId = patch.parentId;
|
|
1108
|
-
const parent = parentId === "root" ? container : nodes.get(parentId);
|
|
1109
|
-
const child = nodes.get(patch.id);
|
|
1110
|
-
const beforeId = patch.beforeId;
|
|
1111
|
-
if (parent && child) {
|
|
1112
|
-
if (beforeId) {
|
|
1113
|
-
const before = nodes.get(beforeId);
|
|
1114
|
-
if (before && before.parentNode === parent) {
|
|
1115
|
-
parent.insertBefore(child, before);
|
|
1116
|
-
}
|
|
1117
|
-
} else {
|
|
1118
|
-
parent.appendChild(child);
|
|
1119
|
-
}
|
|
85
|
+
else {
|
|
86
|
+
this.container = containerSelector;
|
|
1120
87
|
}
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
if (el && el.parentNode) {
|
|
1126
|
-
el.parentNode.removeChild(el);
|
|
88
|
+
// Get the component definition
|
|
89
|
+
const component = componentLoader.get(componentName);
|
|
90
|
+
if (!component) {
|
|
91
|
+
throw new Error(`[Hypen] Component "${componentName}" not found. Available: ${componentLoader.getNames().join(", ")}`);
|
|
1127
92
|
}
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
const tagMap = {
|
|
1137
|
-
column: "div",
|
|
1138
|
-
row: "div",
|
|
1139
|
-
text: "span",
|
|
1140
|
-
button: "button",
|
|
1141
|
-
input: "input",
|
|
1142
|
-
image: "img",
|
|
1143
|
-
container: "div",
|
|
1144
|
-
box: "div",
|
|
1145
|
-
center: "div",
|
|
1146
|
-
list: "div",
|
|
1147
|
-
spacer: "div",
|
|
1148
|
-
stack: "div",
|
|
1149
|
-
divider: "hr",
|
|
1150
|
-
grid: "div",
|
|
1151
|
-
card: "div",
|
|
1152
|
-
heading: "h2",
|
|
1153
|
-
link: "a",
|
|
1154
|
-
textarea: "textarea",
|
|
1155
|
-
checkbox: "input",
|
|
1156
|
-
select: "select",
|
|
1157
|
-
slider: "input",
|
|
1158
|
-
switch: "input",
|
|
1159
|
-
spinner: "div",
|
|
1160
|
-
badge: "span",
|
|
1161
|
-
avatar: "img",
|
|
1162
|
-
progressbar: "div",
|
|
1163
|
-
video: "video",
|
|
1164
|
-
audio: "audio"
|
|
1165
|
-
};
|
|
1166
|
-
const tag = tagMap[normalizedType] || "div";
|
|
1167
|
-
const el = document.createElement(tag);
|
|
1168
|
-
el.dataset.hypenType = normalizedType;
|
|
1169
|
-
if (normalizedType === "column") {
|
|
1170
|
-
el.style.display = "flex";
|
|
1171
|
-
el.style.flexDirection = "column";
|
|
1172
|
-
} else if (normalizedType === "row") {
|
|
1173
|
-
el.style.display = "flex";
|
|
1174
|
-
el.style.flexDirection = "row";
|
|
1175
|
-
} else if (normalizedType === "center") {
|
|
1176
|
-
el.style.display = "flex";
|
|
1177
|
-
el.style.alignItems = "center";
|
|
1178
|
-
el.style.justifyContent = "center";
|
|
1179
|
-
} else if (normalizedType === "text") {
|
|
1180
|
-
if (props["0"]) {
|
|
1181
|
-
el.textContent = String(props["0"]);
|
|
1182
|
-
}
|
|
1183
|
-
} else if (normalizedType === "button") {
|
|
1184
|
-
el.style.cursor = "pointer";
|
|
1185
|
-
} else if (normalizedType === "checkbox" || normalizedType === "switch") {
|
|
1186
|
-
el.type = "checkbox";
|
|
1187
|
-
} else if (normalizedType === "slider") {
|
|
1188
|
-
el.type = "range";
|
|
1189
|
-
}
|
|
1190
|
-
return el;
|
|
1191
|
-
}
|
|
1192
|
-
function applyProp(el, name, value) {
|
|
1193
|
-
if (name === "0" || name === "text") {
|
|
1194
|
-
el.textContent = String(value);
|
|
1195
|
-
return;
|
|
1196
|
-
}
|
|
1197
|
-
const styleProps = {
|
|
1198
|
-
padding: "padding",
|
|
1199
|
-
margin: "margin",
|
|
1200
|
-
backgroundColor: "backgroundColor",
|
|
1201
|
-
background: "background",
|
|
1202
|
-
color: "color",
|
|
1203
|
-
fontSize: "fontSize",
|
|
1204
|
-
fontWeight: "fontWeight",
|
|
1205
|
-
width: "width",
|
|
1206
|
-
height: "height",
|
|
1207
|
-
minWidth: "minWidth",
|
|
1208
|
-
minHeight: "minHeight",
|
|
1209
|
-
maxWidth: "maxWidth",
|
|
1210
|
-
maxHeight: "maxHeight",
|
|
1211
|
-
borderRadius: "borderRadius",
|
|
1212
|
-
border: "border",
|
|
1213
|
-
gap: "gap",
|
|
1214
|
-
flex: "flex",
|
|
1215
|
-
opacity: "opacity",
|
|
1216
|
-
overflow: "overflow"
|
|
1217
|
-
};
|
|
1218
|
-
if (styleProps[name]) {
|
|
1219
|
-
const cssValue = typeof value === "number" ? `${value}px` : String(value);
|
|
1220
|
-
el.style[styleProps[name]] = cssValue;
|
|
1221
|
-
return;
|
|
1222
|
-
}
|
|
1223
|
-
if (name === "onClick" || name === "onclick") {
|
|
1224
|
-
el.onclick = () => {
|
|
1225
|
-
const engine = el.__hypenEngine;
|
|
1226
|
-
if (engine && typeof value === "string" && value.startsWith("@actions.")) {
|
|
1227
|
-
const action = value.replace("@actions.", "");
|
|
1228
|
-
engine.dispatchAction(action);
|
|
1229
|
-
}
|
|
1230
|
-
};
|
|
1231
|
-
return;
|
|
1232
|
-
}
|
|
1233
|
-
el.setAttribute(name, String(value));
|
|
1234
|
-
}
|
|
1235
|
-
function disconnectHypenApp(element) {
|
|
1236
|
-
const instance = activeInstances.get(element);
|
|
1237
|
-
if (instance) {
|
|
1238
|
-
instance.engine.disconnect();
|
|
1239
|
-
activeInstances.delete(element);
|
|
1240
|
-
}
|
|
1241
|
-
}
|
|
1242
|
-
var log2, activeInstances, hypenAppHandler;
|
|
1243
|
-
var init_hypenapp = __esm(() => {
|
|
1244
|
-
log2 = frameworkLoggers2.remote;
|
|
1245
|
-
activeInstances = new WeakMap;
|
|
1246
|
-
hypenAppHandler = {
|
|
1247
|
-
create() {
|
|
1248
|
-
const el = document.createElement("div");
|
|
1249
|
-
el.dataset.hypenType = "hypenapp";
|
|
1250
|
-
el.style.display = "contents";
|
|
1251
|
-
return el;
|
|
1252
|
-
},
|
|
1253
|
-
applyProps(element, props) {
|
|
1254
|
-
const url = props["0"] || props.url;
|
|
1255
|
-
if (!url || typeof url !== "string") {
|
|
1256
|
-
log2.error("HypenApp: URL is required");
|
|
1257
|
-
element.innerHTML = '<div style="color: red;">HypenApp: URL required</div>';
|
|
1258
|
-
return;
|
|
1259
|
-
}
|
|
1260
|
-
const existing = activeInstances.get(element);
|
|
1261
|
-
if (existing) {
|
|
1262
|
-
return;
|
|
1263
|
-
}
|
|
1264
|
-
const engine = new RemoteEngine(url, {
|
|
1265
|
-
autoReconnect: props.autoReconnect ?? true,
|
|
1266
|
-
reconnectInterval: props.reconnectInterval ?? 3000,
|
|
1267
|
-
maxReconnectAttempts: props.maxReconnectAttempts ?? 10
|
|
1268
|
-
});
|
|
1269
|
-
const nodes = new Map;
|
|
1270
|
-
let rootId = null;
|
|
1271
|
-
activeInstances.set(element, { engine, nodes });
|
|
1272
|
-
engine.onPatches((patches) => {
|
|
1273
|
-
applyPatches(element, nodes, patches, engine, (id) => {
|
|
1274
|
-
if (!rootId)
|
|
1275
|
-
rootId = id;
|
|
93
|
+
log.debug(`Rendering ${componentName} to`, this.container);
|
|
94
|
+
// Create renderer with debug config
|
|
95
|
+
this.renderer = new DOMRenderer(this.container, this.engine, {
|
|
96
|
+
enabled: this.config.debugHeatmap || false,
|
|
97
|
+
showHeatmap: this.config.debugHeatmap || false,
|
|
98
|
+
heatmapIncrement: this.config.heatmapIncrement || 5,
|
|
99
|
+
fadeOutDuration: this.config.heatmapFadeOut || 2000,
|
|
100
|
+
maxOpacity: 0.8,
|
|
1276
101
|
});
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
102
|
+
// Set render callback
|
|
103
|
+
this.engine.setRenderCallback((patches) => {
|
|
104
|
+
log.debug(`Applying ${patches.length} patches`);
|
|
105
|
+
this.renderer.applyPatches(patches);
|
|
106
|
+
});
|
|
107
|
+
// Set context on renderer for component composition
|
|
108
|
+
this.renderer.setContext(this.router, this.globalContext);
|
|
109
|
+
// Extract module ID from component name or .id() applicator
|
|
110
|
+
const moduleId = this.extractModuleId(componentName, component.template);
|
|
111
|
+
// Create module instance with router and global context
|
|
112
|
+
this.moduleInstance = new HypenModuleInstance(this.engine, component.module, this.router, this.globalContext);
|
|
113
|
+
// Register module in global context
|
|
114
|
+
this.globalContext.registerModule(moduleId, this.moduleInstance);
|
|
115
|
+
this.moduleInstances.set(moduleId, this.moduleInstance);
|
|
116
|
+
// Connect module state changes to renderer
|
|
117
|
+
this.moduleInstance.onStateChange(() => {
|
|
118
|
+
const mergedState = this.getMergedState();
|
|
119
|
+
log.debug(`State changed, merged state:`, mergedState);
|
|
120
|
+
this.renderer.updateState(mergedState);
|
|
121
|
+
});
|
|
122
|
+
// Set up component resolver for dynamic component composition
|
|
123
|
+
this.setupComponentResolver();
|
|
124
|
+
// Create module instances for ALL components that have state
|
|
125
|
+
this.createNestedModuleInstances();
|
|
126
|
+
// Render the UI template
|
|
127
|
+
this.engine.renderSource(component.template);
|
|
128
|
+
// Update renderer with initial state
|
|
129
|
+
this.renderer.updateState(this.getMergedState());
|
|
130
|
+
log.debug(`${componentName} rendered successfully`);
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Unmount and cleanup
|
|
134
|
+
*/
|
|
135
|
+
async unmount() {
|
|
136
|
+
log.debug("Unmounting...");
|
|
137
|
+
if (this.moduleInstance) {
|
|
138
|
+
await this.moduleInstance.destroy();
|
|
139
|
+
this.moduleInstance = null;
|
|
1303
140
|
}
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
}
|
|
1308
|
-
}
|
|
1309
|
-
};
|
|
1310
|
-
});
|
|
1311
|
-
|
|
1312
|
-
// src/dom/components/app.ts
|
|
1313
|
-
var exports_app = {};
|
|
1314
|
-
__export(exports_app, {
|
|
1315
|
-
appHandler: () => appHandler
|
|
1316
|
-
});
|
|
1317
|
-
var appHandler;
|
|
1318
|
-
var init_app = __esm(() => {
|
|
1319
|
-
appHandler = {
|
|
1320
|
-
create() {
|
|
1321
|
-
const el = document.createElement("div");
|
|
1322
|
-
el.style.display = "flex";
|
|
1323
|
-
el.style.flexDirection = "column";
|
|
1324
|
-
el.style.minHeight = "100vh";
|
|
1325
|
-
el.style.width = "100%";
|
|
1326
|
-
el.dataset.hypenType = "app";
|
|
1327
|
-
return el;
|
|
1328
|
-
}
|
|
1329
|
-
};
|
|
1330
|
-
});
|
|
1331
|
-
|
|
1332
|
-
// src/dom/components/index.ts
|
|
1333
|
-
class ComponentRegistry {
|
|
1334
|
-
handlers = new Map;
|
|
1335
|
-
constructor() {
|
|
1336
|
-
this.registerDefaults();
|
|
1337
|
-
}
|
|
1338
|
-
register(type, handler) {
|
|
1339
|
-
this.handlers.set(type.toLowerCase(), handler);
|
|
1340
|
-
}
|
|
1341
|
-
get(type) {
|
|
1342
|
-
if (!type)
|
|
1343
|
-
return;
|
|
1344
|
-
return this.handlers.get(type.toLowerCase());
|
|
1345
|
-
}
|
|
1346
|
-
createElement(type, props = {}) {
|
|
1347
|
-
if (!type)
|
|
1348
|
-
return null;
|
|
1349
|
-
const handler = this.get(type);
|
|
1350
|
-
if (!handler)
|
|
1351
|
-
return null;
|
|
1352
|
-
const element = handler.create();
|
|
1353
|
-
if (handler.applyProps) {
|
|
1354
|
-
handler.applyProps(element, props);
|
|
1355
|
-
}
|
|
1356
|
-
return element;
|
|
1357
|
-
}
|
|
1358
|
-
registerDefaults() {
|
|
1359
|
-
const { columnHandler: columnHandler2 } = (init_column(), __toCommonJS(exports_column));
|
|
1360
|
-
const { rowHandler: rowHandler2 } = (init_row(), __toCommonJS(exports_row));
|
|
1361
|
-
const { textHandler: textHandler2 } = (init_text(), __toCommonJS(exports_text));
|
|
1362
|
-
const { imageHandler: imageHandler2 } = (init_image(), __toCommonJS(exports_image));
|
|
1363
|
-
const { buttonHandler: buttonHandler2 } = (init_button(), __toCommonJS(exports_button));
|
|
1364
|
-
const { containerHandler: containerHandler2 } = (init_container(), __toCommonJS(exports_container));
|
|
1365
|
-
const { centerHandler: centerHandler2 } = (init_center(), __toCommonJS(exports_center));
|
|
1366
|
-
const { listHandler: listHandler2 } = (init_list(), __toCommonJS(exports_list));
|
|
1367
|
-
const { inputHandler: inputHandler2 } = (init_input(), __toCommonJS(exports_input));
|
|
1368
|
-
const { linkHandler: linkHandler2 } = (init_link(), __toCommonJS(exports_link));
|
|
1369
|
-
const { textareaHandler: textareaHandler2 } = (init_textarea(), __toCommonJS(exports_textarea));
|
|
1370
|
-
const { checkboxHandler: checkboxHandler2 } = (init_checkbox(), __toCommonJS(exports_checkbox));
|
|
1371
|
-
const { selectHandler: selectHandler2 } = (init_select(), __toCommonJS(exports_select));
|
|
1372
|
-
const { spacerHandler: spacerHandler2 } = (init_spacer(), __toCommonJS(exports_spacer));
|
|
1373
|
-
const { stackHandler: stackHandler2 } = (init_stack(), __toCommonJS(exports_stack));
|
|
1374
|
-
const { dividerHandler: dividerHandler2 } = (init_divider(), __toCommonJS(exports_divider));
|
|
1375
|
-
const { gridHandler: gridHandler2 } = (init_grid(), __toCommonJS(exports_grid));
|
|
1376
|
-
const { cardHandler: cardHandler2 } = (init_card(), __toCommonJS(exports_card));
|
|
1377
|
-
const { headingHandler: headingHandler2 } = (init_heading(), __toCommonJS(exports_heading));
|
|
1378
|
-
const { switchHandler: switchHandler2 } = (init_switch(), __toCommonJS(exports_switch));
|
|
1379
|
-
const { sliderHandler: sliderHandler2 } = (init_slider(), __toCommonJS(exports_slider));
|
|
1380
|
-
const { spinnerHandler: spinnerHandler2 } = (init_spinner(), __toCommonJS(exports_spinner));
|
|
1381
|
-
const { badgeHandler: badgeHandler2 } = (init_badge(), __toCommonJS(exports_badge));
|
|
1382
|
-
const { avatarHandler: avatarHandler2 } = (init_avatar(), __toCommonJS(exports_avatar));
|
|
1383
|
-
const { progressBarHandler: progressBarHandler2 } = (init_progressbar(), __toCommonJS(exports_progressbar));
|
|
1384
|
-
const { videoHandler: videoHandler2 } = (init_video(), __toCommonJS(exports_video));
|
|
1385
|
-
const { audioHandler: audioHandler2 } = (init_audio(), __toCommonJS(exports_audio));
|
|
1386
|
-
const { paragraphHandler: paragraphHandler2 } = (init_paragraph(), __toCommonJS(exports_paragraph));
|
|
1387
|
-
const { routerHandler: routerHandler2 } = (init_router(), __toCommonJS(exports_router));
|
|
1388
|
-
const { routeHandler: routeHandler2 } = (init_route(), __toCommonJS(exports_route));
|
|
1389
|
-
const { hypenAppHandler: hypenAppHandler2 } = (init_hypenapp(), __toCommonJS(exports_hypenapp));
|
|
1390
|
-
const { appHandler: appHandler2 } = (init_app(), __toCommonJS(exports_app));
|
|
1391
|
-
this.register("app", appHandler2);
|
|
1392
|
-
this.register("column", columnHandler2);
|
|
1393
|
-
this.register("row", rowHandler2);
|
|
1394
|
-
this.register("text", textHandler2);
|
|
1395
|
-
this.register("image", imageHandler2);
|
|
1396
|
-
this.register("button", buttonHandler2);
|
|
1397
|
-
this.register("container", containerHandler2);
|
|
1398
|
-
this.register("box", containerHandler2);
|
|
1399
|
-
this.register("center", centerHandler2);
|
|
1400
|
-
this.register("list", listHandler2);
|
|
1401
|
-
this.register("input", inputHandler2);
|
|
1402
|
-
this.register("link", linkHandler2);
|
|
1403
|
-
this.register("textarea", textareaHandler2);
|
|
1404
|
-
this.register("checkbox", checkboxHandler2);
|
|
1405
|
-
this.register("select", selectHandler2);
|
|
1406
|
-
this.register("spacer", spacerHandler2);
|
|
1407
|
-
this.register("stack", stackHandler2);
|
|
1408
|
-
this.register("divider", dividerHandler2);
|
|
1409
|
-
this.register("grid", gridHandler2);
|
|
1410
|
-
this.register("card", cardHandler2);
|
|
1411
|
-
this.register("heading", headingHandler2);
|
|
1412
|
-
this.register("switch", switchHandler2);
|
|
1413
|
-
this.register("slider", sliderHandler2);
|
|
1414
|
-
this.register("spinner", spinnerHandler2);
|
|
1415
|
-
this.register("badge", badgeHandler2);
|
|
1416
|
-
this.register("avatar", avatarHandler2);
|
|
1417
|
-
this.register("progressbar", progressBarHandler2);
|
|
1418
|
-
this.register("video", videoHandler2);
|
|
1419
|
-
this.register("audio", audioHandler2);
|
|
1420
|
-
this.register("paragraph", paragraphHandler2);
|
|
1421
|
-
this.register("router", routerHandler2);
|
|
1422
|
-
this.register("route", routeHandler2);
|
|
1423
|
-
this.register("hypenapp", hypenAppHandler2);
|
|
1424
|
-
}
|
|
1425
|
-
}
|
|
1426
|
-
|
|
1427
|
-
// src/dom/applicators/padding.ts
|
|
1428
|
-
var getNumericValue = (value) => {
|
|
1429
|
-
if (typeof value === "number")
|
|
1430
|
-
return value;
|
|
1431
|
-
if (typeof value === "object" && value["0"] !== undefined)
|
|
1432
|
-
return Number(value["0"]);
|
|
1433
|
-
if (typeof value === "string")
|
|
1434
|
-
return parseFloat(value);
|
|
1435
|
-
return null;
|
|
1436
|
-
};
|
|
1437
|
-
var paddingHandler = (el, value) => {
|
|
1438
|
-
if (typeof value === "number") {
|
|
1439
|
-
el.style.padding = `${value}px`;
|
|
1440
|
-
} else if (typeof value === "object") {
|
|
1441
|
-
if (value["0"] !== undefined && Object.keys(value).length === 1) {
|
|
1442
|
-
el.style.padding = `${value["0"]}px`;
|
|
1443
|
-
} else {
|
|
1444
|
-
if (value.left !== undefined)
|
|
1445
|
-
el.style.paddingLeft = `${value.left}px`;
|
|
1446
|
-
if (value.right !== undefined)
|
|
1447
|
-
el.style.paddingRight = `${value.right}px`;
|
|
1448
|
-
if (value.top !== undefined)
|
|
1449
|
-
el.style.paddingTop = `${value.top}px`;
|
|
1450
|
-
if (value.bottom !== undefined)
|
|
1451
|
-
el.style.paddingBottom = `${value.bottom}px`;
|
|
1452
|
-
}
|
|
1453
|
-
} else {
|
|
1454
|
-
el.style.padding = String(value);
|
|
1455
|
-
}
|
|
1456
|
-
};
|
|
1457
|
-
var paddingTopHandler = (el, value) => {
|
|
1458
|
-
const v = getNumericValue(value);
|
|
1459
|
-
if (v !== null)
|
|
1460
|
-
el.style.paddingTop = `${v}px`;
|
|
1461
|
-
};
|
|
1462
|
-
var paddingBottomHandler = (el, value) => {
|
|
1463
|
-
const v = getNumericValue(value);
|
|
1464
|
-
if (v !== null)
|
|
1465
|
-
el.style.paddingBottom = `${v}px`;
|
|
1466
|
-
};
|
|
1467
|
-
var paddingLeftHandler = (el, value) => {
|
|
1468
|
-
const v = getNumericValue(value);
|
|
1469
|
-
if (v !== null)
|
|
1470
|
-
el.style.paddingLeft = `${v}px`;
|
|
1471
|
-
};
|
|
1472
|
-
var paddingRightHandler = (el, value) => {
|
|
1473
|
-
const v = getNumericValue(value);
|
|
1474
|
-
if (v !== null)
|
|
1475
|
-
el.style.paddingRight = `${v}px`;
|
|
1476
|
-
};
|
|
1477
|
-
var paddingHorizontalHandler = (el, value) => {
|
|
1478
|
-
const v = getNumericValue(value);
|
|
1479
|
-
if (v !== null) {
|
|
1480
|
-
el.style.paddingLeft = `${v}px`;
|
|
1481
|
-
el.style.paddingRight = `${v}px`;
|
|
1482
|
-
}
|
|
1483
|
-
};
|
|
1484
|
-
var paddingVerticalHandler = (el, value) => {
|
|
1485
|
-
const v = getNumericValue(value);
|
|
1486
|
-
if (v !== null) {
|
|
1487
|
-
el.style.paddingTop = `${v}px`;
|
|
1488
|
-
el.style.paddingBottom = `${v}px`;
|
|
1489
|
-
}
|
|
1490
|
-
};
|
|
1491
|
-
|
|
1492
|
-
// src/dom/applicators/margin.ts
|
|
1493
|
-
var getNumericValue2 = (value) => {
|
|
1494
|
-
if (typeof value === "number")
|
|
1495
|
-
return value;
|
|
1496
|
-
if (typeof value === "object" && value["0"] !== undefined)
|
|
1497
|
-
return Number(value["0"]);
|
|
1498
|
-
if (typeof value === "string")
|
|
1499
|
-
return parseFloat(value);
|
|
1500
|
-
return null;
|
|
1501
|
-
};
|
|
1502
|
-
var marginHandler = (el, value) => {
|
|
1503
|
-
if (typeof value === "number") {
|
|
1504
|
-
el.style.margin = `${value}px`;
|
|
1505
|
-
} else if (typeof value === "object") {
|
|
1506
|
-
if (value["0"] !== undefined && Object.keys(value).length === 1) {
|
|
1507
|
-
el.style.margin = `${value["0"]}px`;
|
|
1508
|
-
} else {
|
|
1509
|
-
if (value.left !== undefined)
|
|
1510
|
-
el.style.marginLeft = `${value.left}px`;
|
|
1511
|
-
if (value.right !== undefined)
|
|
1512
|
-
el.style.marginRight = `${value.right}px`;
|
|
1513
|
-
if (value.top !== undefined)
|
|
1514
|
-
el.style.marginTop = `${value.top}px`;
|
|
1515
|
-
if (value.bottom !== undefined)
|
|
1516
|
-
el.style.marginBottom = `${value.bottom}px`;
|
|
1517
|
-
}
|
|
1518
|
-
} else {
|
|
1519
|
-
el.style.margin = String(value);
|
|
1520
|
-
}
|
|
1521
|
-
};
|
|
1522
|
-
var marginTopHandler = (el, value) => {
|
|
1523
|
-
const v = getNumericValue2(value);
|
|
1524
|
-
if (v !== null)
|
|
1525
|
-
el.style.marginTop = `${v}px`;
|
|
1526
|
-
};
|
|
1527
|
-
var marginBottomHandler = (el, value) => {
|
|
1528
|
-
const v = getNumericValue2(value);
|
|
1529
|
-
if (v !== null)
|
|
1530
|
-
el.style.marginBottom = `${v}px`;
|
|
1531
|
-
};
|
|
1532
|
-
var marginLeftHandler = (el, value) => {
|
|
1533
|
-
const v = getNumericValue2(value);
|
|
1534
|
-
if (v !== null)
|
|
1535
|
-
el.style.marginLeft = `${v}px`;
|
|
1536
|
-
};
|
|
1537
|
-
var marginRightHandler = (el, value) => {
|
|
1538
|
-
const v = getNumericValue2(value);
|
|
1539
|
-
if (v !== null)
|
|
1540
|
-
el.style.marginRight = `${v}px`;
|
|
1541
|
-
};
|
|
1542
|
-
var marginHorizontalHandler = (el, value) => {
|
|
1543
|
-
const v = getNumericValue2(value);
|
|
1544
|
-
if (v !== null) {
|
|
1545
|
-
el.style.marginLeft = `${v}px`;
|
|
1546
|
-
el.style.marginRight = `${v}px`;
|
|
1547
|
-
}
|
|
1548
|
-
};
|
|
1549
|
-
var marginVerticalHandler = (el, value) => {
|
|
1550
|
-
const v = getNumericValue2(value);
|
|
1551
|
-
if (v !== null) {
|
|
1552
|
-
el.style.marginTop = `${v}px`;
|
|
1553
|
-
el.style.marginBottom = `${v}px`;
|
|
1554
|
-
}
|
|
1555
|
-
};
|
|
1556
|
-
|
|
1557
|
-
// src/dom/applicators/color.ts
|
|
1558
|
-
var colorHandlers = {
|
|
1559
|
-
color: (el, value) => {
|
|
1560
|
-
el.style.color = String(value);
|
|
1561
|
-
},
|
|
1562
|
-
backgroundColor: (el, value) => {
|
|
1563
|
-
el.style.backgroundColor = String(value);
|
|
1564
|
-
},
|
|
1565
|
-
borderColor: (el, value) => {
|
|
1566
|
-
el.style.borderColor = String(value);
|
|
1567
|
-
},
|
|
1568
|
-
opacity: (el, value) => {
|
|
1569
|
-
el.style.opacity = String(value);
|
|
1570
|
-
}
|
|
1571
|
-
};
|
|
1572
|
-
|
|
1573
|
-
// src/dom/applicators/border.ts
|
|
1574
|
-
var borderHandlers = {
|
|
1575
|
-
border: (el, value) => {
|
|
1576
|
-
if (typeof value === "number") {
|
|
1577
|
-
el.style.borderWidth = `${value}px`;
|
|
1578
|
-
el.style.borderStyle = "solid";
|
|
1579
|
-
} else if (typeof value === "object" && value !== null) {
|
|
1580
|
-
const obj = value;
|
|
1581
|
-
if (obj.width !== undefined) {
|
|
1582
|
-
el.style.borderWidth = typeof obj.width === "number" ? `${obj.width}px` : String(obj.width);
|
|
1583
|
-
}
|
|
1584
|
-
if (obj.color !== undefined) {
|
|
1585
|
-
el.style.borderColor = String(obj.color);
|
|
1586
|
-
}
|
|
1587
|
-
if (obj.style !== undefined) {
|
|
1588
|
-
el.style.borderStyle = String(obj.style);
|
|
1589
|
-
} else {
|
|
1590
|
-
el.style.borderStyle = "solid";
|
|
1591
|
-
}
|
|
1592
|
-
if (obj.radius !== undefined) {
|
|
1593
|
-
el.style.borderRadius = typeof obj.radius === "number" ? `${obj.radius}px` : String(obj.radius);
|
|
1594
|
-
}
|
|
1595
|
-
} else if (typeof value === "string") {
|
|
1596
|
-
el.style.border = value;
|
|
1597
|
-
}
|
|
1598
|
-
},
|
|
1599
|
-
borderWidth: (el, value) => {
|
|
1600
|
-
el.style.borderWidth = typeof value === "number" ? `${value}px` : String(value);
|
|
1601
|
-
},
|
|
1602
|
-
borderStyle: (el, value) => {
|
|
1603
|
-
el.style.borderStyle = String(value);
|
|
1604
|
-
},
|
|
1605
|
-
borderRadius: (el, value) => {
|
|
1606
|
-
if (typeof value === "number") {
|
|
1607
|
-
el.style.borderRadius = `${value}px`;
|
|
1608
|
-
} else if (typeof value === "object" && value !== null) {
|
|
1609
|
-
const obj = value;
|
|
1610
|
-
const topLeft = obj.topLeft ?? obj.topStart ?? 0;
|
|
1611
|
-
const topRight = obj.topRight ?? obj.topEnd ?? 0;
|
|
1612
|
-
const bottomRight = obj.bottomRight ?? obj.bottomEnd ?? 0;
|
|
1613
|
-
const bottomLeft = obj.bottomLeft ?? obj.bottomStart ?? 0;
|
|
1614
|
-
const formatValue = (v) => typeof v === "number" ? `${v}px` : String(v);
|
|
1615
|
-
el.style.borderRadius = `${formatValue(topLeft)} ${formatValue(topRight)} ${formatValue(bottomRight)} ${formatValue(bottomLeft)}`;
|
|
1616
|
-
} else {
|
|
1617
|
-
el.style.borderRadius = String(value);
|
|
1618
|
-
}
|
|
1619
|
-
},
|
|
1620
|
-
cornerRadius: (el, value) => {
|
|
1621
|
-
if (typeof value === "number") {
|
|
1622
|
-
el.style.borderRadius = `${value}px`;
|
|
1623
|
-
} else if (typeof value === "object" && value !== null) {
|
|
1624
|
-
const obj = value;
|
|
1625
|
-
const topLeft = obj.topLeft ?? obj.topStart ?? 0;
|
|
1626
|
-
const topRight = obj.topRight ?? obj.topEnd ?? 0;
|
|
1627
|
-
const bottomRight = obj.bottomRight ?? obj.bottomEnd ?? 0;
|
|
1628
|
-
const bottomLeft = obj.bottomLeft ?? obj.bottomStart ?? 0;
|
|
1629
|
-
const formatValue = (v) => typeof v === "number" ? `${v}px` : String(v);
|
|
1630
|
-
el.style.borderRadius = `${formatValue(topLeft)} ${formatValue(topRight)} ${formatValue(bottomRight)} ${formatValue(bottomLeft)}`;
|
|
1631
|
-
} else {
|
|
1632
|
-
el.style.borderRadius = String(value);
|
|
1633
|
-
}
|
|
1634
|
-
}
|
|
1635
|
-
};
|
|
1636
|
-
|
|
1637
|
-
// src/dom/applicators/size.ts
|
|
1638
|
-
function parseSizeValue(value) {
|
|
1639
|
-
if (value === null || value === undefined)
|
|
1640
|
-
return null;
|
|
1641
|
-
if (typeof value === "number") {
|
|
1642
|
-
return `${value}px`;
|
|
1643
|
-
}
|
|
1644
|
-
const str = String(value).trim().toLowerCase();
|
|
1645
|
-
switch (str) {
|
|
1646
|
-
case "fill":
|
|
1647
|
-
case "match_parent":
|
|
1648
|
-
return "100%";
|
|
1649
|
-
case "wrap":
|
|
1650
|
-
case "wrap_content":
|
|
1651
|
-
case "auto":
|
|
1652
|
-
return "auto";
|
|
1653
|
-
case "infinity":
|
|
1654
|
-
case "inf":
|
|
1655
|
-
case "max":
|
|
1656
|
-
return "100%";
|
|
1657
|
-
}
|
|
1658
|
-
const match = str.match(/^(-?[\d.]+)\s*(px|dp|pt|%|vw|vh|vmin|vmax|em|rem)?$/);
|
|
1659
|
-
if (!match) {
|
|
1660
|
-
return str;
|
|
1661
|
-
}
|
|
1662
|
-
const num = parseFloat(match[1]);
|
|
1663
|
-
const unit = match[2] || "px";
|
|
1664
|
-
switch (unit) {
|
|
1665
|
-
case "px":
|
|
1666
|
-
return `${num}px`;
|
|
1667
|
-
case "dp":
|
|
1668
|
-
case "pt":
|
|
1669
|
-
return `${num}px`;
|
|
1670
|
-
case "%":
|
|
1671
|
-
return `${num}%`;
|
|
1672
|
-
case "vw":
|
|
1673
|
-
return `${num}vw`;
|
|
1674
|
-
case "vh":
|
|
1675
|
-
return `${num}vh`;
|
|
1676
|
-
case "vmin":
|
|
1677
|
-
return `${num}vmin`;
|
|
1678
|
-
case "vmax":
|
|
1679
|
-
return `${num}vmax`;
|
|
1680
|
-
case "em":
|
|
1681
|
-
return `${num}em`;
|
|
1682
|
-
case "rem":
|
|
1683
|
-
return `${num}rem`;
|
|
1684
|
-
default:
|
|
1685
|
-
return `${num}px`;
|
|
1686
|
-
}
|
|
1687
|
-
}
|
|
1688
|
-
var sizeHandlers = {
|
|
1689
|
-
width: (el, value) => {
|
|
1690
|
-
const size = parseSizeValue(value);
|
|
1691
|
-
if (size)
|
|
1692
|
-
el.style.width = size;
|
|
1693
|
-
},
|
|
1694
|
-
height: (el, value) => {
|
|
1695
|
-
const size = parseSizeValue(value);
|
|
1696
|
-
if (size)
|
|
1697
|
-
el.style.height = size;
|
|
1698
|
-
},
|
|
1699
|
-
minWidth: (el, value) => {
|
|
1700
|
-
const size = parseSizeValue(value);
|
|
1701
|
-
if (size)
|
|
1702
|
-
el.style.minWidth = size;
|
|
1703
|
-
},
|
|
1704
|
-
minHeight: (el, value) => {
|
|
1705
|
-
const size = parseSizeValue(value);
|
|
1706
|
-
if (size)
|
|
1707
|
-
el.style.minHeight = size;
|
|
1708
|
-
},
|
|
1709
|
-
maxWidth: (el, value) => {
|
|
1710
|
-
const size = parseSizeValue(value);
|
|
1711
|
-
if (size)
|
|
1712
|
-
el.style.maxWidth = size;
|
|
1713
|
-
},
|
|
1714
|
-
maxHeight: (el, value) => {
|
|
1715
|
-
const size = parseSizeValue(value);
|
|
1716
|
-
if (size)
|
|
1717
|
-
el.style.maxHeight = size;
|
|
1718
|
-
},
|
|
1719
|
-
size: (el, value) => {
|
|
1720
|
-
if (typeof value === "object" && value !== null) {
|
|
1721
|
-
const obj = value;
|
|
1722
|
-
if (obj.width !== undefined) {
|
|
1723
|
-
const w = parseSizeValue(obj.width);
|
|
1724
|
-
if (w)
|
|
1725
|
-
el.style.width = w;
|
|
1726
|
-
}
|
|
1727
|
-
if (obj.height !== undefined) {
|
|
1728
|
-
const h = parseSizeValue(obj.height);
|
|
1729
|
-
if (h)
|
|
1730
|
-
el.style.height = h;
|
|
1731
|
-
}
|
|
1732
|
-
} else {
|
|
1733
|
-
const size = parseSizeValue(value);
|
|
1734
|
-
if (size) {
|
|
1735
|
-
el.style.width = size;
|
|
1736
|
-
el.style.height = size;
|
|
1737
|
-
}
|
|
1738
|
-
}
|
|
1739
|
-
},
|
|
1740
|
-
fillMaxWidth: (el, value) => {
|
|
1741
|
-
if (value === false)
|
|
1742
|
-
return;
|
|
1743
|
-
const fraction = typeof value === "number" ? value : 1;
|
|
1744
|
-
if (fraction === 1) {
|
|
1745
|
-
el.style.alignSelf = "stretch";
|
|
1746
|
-
el.style.width = "100%";
|
|
1747
|
-
el.style.minWidth = "0";
|
|
1748
|
-
} else {
|
|
1749
|
-
el.style.width = `${fraction * 100}%`;
|
|
1750
|
-
}
|
|
1751
|
-
el.style.justifySelf = "stretch";
|
|
1752
|
-
},
|
|
1753
|
-
fillMaxHeight: (el, value) => {
|
|
1754
|
-
if (value === false)
|
|
1755
|
-
return;
|
|
1756
|
-
const fraction = typeof value === "number" ? value : 1;
|
|
1757
|
-
el.style.height = `${fraction * 100}%`;
|
|
1758
|
-
},
|
|
1759
|
-
fillMaxSize: (el, value) => {
|
|
1760
|
-
if (value === false)
|
|
1761
|
-
return;
|
|
1762
|
-
const fraction = typeof value === "number" ? value : 1;
|
|
1763
|
-
el.style.width = `${fraction * 100}%`;
|
|
1764
|
-
el.style.height = `${fraction * 100}%`;
|
|
1765
|
-
el.style.alignSelf = "stretch";
|
|
1766
|
-
el.style.minWidth = "0";
|
|
1767
|
-
}
|
|
1768
|
-
};
|
|
1769
|
-
|
|
1770
|
-
// src/dom/applicators/font.ts
|
|
1771
|
-
var loadedGoogleFonts = new Set;
|
|
1772
|
-
var systemFontKeywords = new Set([
|
|
1773
|
-
"default",
|
|
1774
|
-
"system",
|
|
1775
|
-
"system-ui",
|
|
1776
|
-
"inherit",
|
|
1777
|
-
"initial",
|
|
1778
|
-
"unset",
|
|
1779
|
-
"serif",
|
|
1780
|
-
"sans-serif",
|
|
1781
|
-
"monospace",
|
|
1782
|
-
"cursive",
|
|
1783
|
-
"fantasy",
|
|
1784
|
-
"-apple-system",
|
|
1785
|
-
"BlinkMacSystemFont",
|
|
1786
|
-
"Segoe UI",
|
|
1787
|
-
"Arial",
|
|
1788
|
-
"Helvetica",
|
|
1789
|
-
"Times New Roman",
|
|
1790
|
-
"Georgia",
|
|
1791
|
-
"Courier New",
|
|
1792
|
-
"Verdana",
|
|
1793
|
-
"Tahoma"
|
|
1794
|
-
]);
|
|
1795
|
-
function isSystemFont(fontName) {
|
|
1796
|
-
const normalized = fontName.toLowerCase().trim();
|
|
1797
|
-
return systemFontKeywords.has(normalized) || normalized.startsWith("-") || normalized.startsWith("ui-");
|
|
1798
|
-
}
|
|
1799
|
-
function loadGoogleFont(fontName) {
|
|
1800
|
-
const normalized = fontName.trim();
|
|
1801
|
-
if (loadedGoogleFonts.has(normalized) || isSystemFont(normalized)) {
|
|
1802
|
-
return;
|
|
1803
|
-
}
|
|
1804
|
-
loadedGoogleFonts.add(normalized);
|
|
1805
|
-
const link = document.createElement("link");
|
|
1806
|
-
link.rel = "stylesheet";
|
|
1807
|
-
link.href = `https://fonts.googleapis.com/css2?family=${encodeURIComponent(normalized)}:wght@100;200;300;400;500;600;700;800;900&display=swap`;
|
|
1808
|
-
document.head.appendChild(link);
|
|
1809
|
-
}
|
|
1810
|
-
function processFontFamily(value) {
|
|
1811
|
-
const fonts = value.split(",").map((f) => f.trim().replace(/["']/g, ""));
|
|
1812
|
-
for (const font of fonts) {
|
|
1813
|
-
if (!isSystemFont(font)) {
|
|
1814
|
-
loadGoogleFont(font);
|
|
1815
|
-
}
|
|
1816
|
-
}
|
|
1817
|
-
return fonts.map((f) => {
|
|
1818
|
-
if (f.includes(" ") && !f.startsWith('"') && !f.startsWith("'")) {
|
|
1819
|
-
return `"${f}"`;
|
|
1820
|
-
}
|
|
1821
|
-
return f;
|
|
1822
|
-
}).join(", ");
|
|
1823
|
-
}
|
|
1824
|
-
var fontHandlers = {
|
|
1825
|
-
fontSize: (el, value) => {
|
|
1826
|
-
el.style.fontSize = typeof value === "number" ? `${value}px` : String(value);
|
|
1827
|
-
},
|
|
1828
|
-
fontWeight: (el, value) => {
|
|
1829
|
-
el.style.fontWeight = String(value);
|
|
1830
|
-
},
|
|
1831
|
-
fontFamily: (el, value) => {
|
|
1832
|
-
const fontValue = String(value);
|
|
1833
|
-
el.style.fontFamily = processFontFamily(fontValue);
|
|
1834
|
-
},
|
|
1835
|
-
textAlign: (el, value) => {
|
|
1836
|
-
el.style.textAlign = String(value);
|
|
1837
|
-
},
|
|
1838
|
-
lineHeight: (el, value) => {
|
|
1839
|
-
el.style.lineHeight = String(value);
|
|
1840
|
-
},
|
|
1841
|
-
fontStyle: (el, value) => {
|
|
1842
|
-
el.style.fontStyle = String(value);
|
|
1843
|
-
},
|
|
1844
|
-
textTransform: (el, value) => {
|
|
1845
|
-
el.style.textTransform = String(value);
|
|
1846
|
-
}
|
|
1847
|
-
};
|
|
1848
|
-
var GoogleFonts = {
|
|
1849
|
-
preload: loadGoogleFont,
|
|
1850
|
-
isLoaded: (fontName) => loadedGoogleFonts.has(fontName.trim()),
|
|
1851
|
-
getLoadedFonts: () => Array.from(loadedGoogleFonts),
|
|
1852
|
-
popular: [
|
|
1853
|
-
"Roboto",
|
|
1854
|
-
"Open Sans",
|
|
1855
|
-
"Lato",
|
|
1856
|
-
"Montserrat",
|
|
1857
|
-
"Poppins",
|
|
1858
|
-
"Inter",
|
|
1859
|
-
"Nunito",
|
|
1860
|
-
"Playfair Display",
|
|
1861
|
-
"Merriweather",
|
|
1862
|
-
"Source Code Pro",
|
|
1863
|
-
"Fira Code",
|
|
1864
|
-
"JetBrains Mono",
|
|
1865
|
-
"Raleway",
|
|
1866
|
-
"Ubuntu",
|
|
1867
|
-
"Oswald",
|
|
1868
|
-
"Quicksand",
|
|
1869
|
-
"Work Sans",
|
|
1870
|
-
"Rubik",
|
|
1871
|
-
"Karla",
|
|
1872
|
-
"DM Sans"
|
|
1873
|
-
]
|
|
1874
|
-
};
|
|
1875
|
-
|
|
1876
|
-
// src/dom/applicators/layout.ts
|
|
1877
|
-
function mapAlignmentValue(value) {
|
|
1878
|
-
const v = String(value).toLowerCase();
|
|
1879
|
-
switch (v) {
|
|
1880
|
-
case "top":
|
|
1881
|
-
case "start":
|
|
1882
|
-
case "leading":
|
|
1883
|
-
case "left":
|
|
1884
|
-
return "flex-start";
|
|
1885
|
-
case "bottom":
|
|
1886
|
-
case "end":
|
|
1887
|
-
case "trailing":
|
|
1888
|
-
case "right":
|
|
1889
|
-
return "flex-end";
|
|
1890
|
-
case "center":
|
|
1891
|
-
return "center";
|
|
1892
|
-
case "spacebetween":
|
|
1893
|
-
case "space-between":
|
|
1894
|
-
return "space-between";
|
|
1895
|
-
case "spacearound":
|
|
1896
|
-
case "space-around":
|
|
1897
|
-
return "space-around";
|
|
1898
|
-
case "spaceevenly":
|
|
1899
|
-
case "space-evenly":
|
|
1900
|
-
return "space-evenly";
|
|
1901
|
-
default:
|
|
1902
|
-
return v;
|
|
1903
|
-
}
|
|
1904
|
-
}
|
|
1905
|
-
var layoutHandlers = {
|
|
1906
|
-
verticalAlignment: (el, value) => {
|
|
1907
|
-
const val = mapAlignmentValue(String(value));
|
|
1908
|
-
const display = el.style.display || getComputedStyle(el).display;
|
|
1909
|
-
const flexDirection = el.style.flexDirection || getComputedStyle(el).flexDirection;
|
|
1910
|
-
if (display === "grid") {
|
|
1911
|
-
el.style.alignItems = val;
|
|
1912
|
-
} else if (flexDirection === "column" || flexDirection === "column-reverse") {
|
|
1913
|
-
el.style.justifyContent = val;
|
|
1914
|
-
} else {
|
|
1915
|
-
el.style.alignItems = val;
|
|
1916
|
-
}
|
|
1917
|
-
},
|
|
1918
|
-
horizontalAlignment: (el, value) => {
|
|
1919
|
-
const val = mapAlignmentValue(String(value));
|
|
1920
|
-
const display = el.style.display || getComputedStyle(el).display;
|
|
1921
|
-
const flexDirection = el.style.flexDirection || getComputedStyle(el).flexDirection;
|
|
1922
|
-
if (display === "grid") {
|
|
1923
|
-
el.style.justifyItems = val;
|
|
1924
|
-
} else if (flexDirection === "column" || flexDirection === "column-reverse") {
|
|
1925
|
-
el.style.alignItems = val;
|
|
1926
|
-
} else if (flexDirection === "row" || flexDirection === "row-reverse") {
|
|
1927
|
-
el.style.justifyContent = val;
|
|
1928
|
-
if (val !== "flex-start" && el.style.overflow !== "auto" && el.style.overflowX !== "auto") {
|
|
1929
|
-
el.style.width = "100%";
|
|
1930
|
-
}
|
|
1931
|
-
} else {
|
|
1932
|
-
el.style.justifyContent = val;
|
|
1933
|
-
}
|
|
1934
|
-
},
|
|
1935
|
-
horizontalAlign: (el, value) => {
|
|
1936
|
-
el.style.justifyContent = mapAlignmentValue(String(value));
|
|
1937
|
-
},
|
|
1938
|
-
verticalAlign: (el, value) => {
|
|
1939
|
-
el.style.alignItems = mapAlignmentValue(String(value));
|
|
1940
|
-
},
|
|
1941
|
-
gap: (el, value) => {
|
|
1942
|
-
el.style.gap = typeof value === "number" ? `${value}px` : String(value);
|
|
1943
|
-
},
|
|
1944
|
-
weight: (el, value) => {
|
|
1945
|
-
el.style.flex = String(value);
|
|
1946
|
-
el.dataset.hypenFlex = "true";
|
|
1947
|
-
},
|
|
1948
|
-
flex: (el, value) => {
|
|
1949
|
-
el.style.flex = String(value);
|
|
1950
|
-
el.dataset.hypenFlex = "true";
|
|
1951
|
-
},
|
|
1952
|
-
flexGrow: (el, value) => {
|
|
1953
|
-
el.style.flexGrow = String(value);
|
|
1954
|
-
},
|
|
1955
|
-
flexShrink: (el, value) => {
|
|
1956
|
-
el.style.flexShrink = String(value);
|
|
1957
|
-
},
|
|
1958
|
-
cursor: (el, value) => {
|
|
1959
|
-
el.style.cursor = String(value);
|
|
1960
|
-
},
|
|
1961
|
-
overflow: (el, value) => {
|
|
1962
|
-
el.style.overflow = String(value);
|
|
1963
|
-
},
|
|
1964
|
-
scrollable: (el, value) => {
|
|
1965
|
-
if (value === true || value === "true") {
|
|
1966
|
-
el.style.overflow = "auto";
|
|
1967
|
-
} else if (value === false || value === "false") {
|
|
1968
|
-
el.style.overflow = "hidden";
|
|
1969
|
-
} else if (value === "vertical") {
|
|
1970
|
-
el.style.overflowX = "hidden";
|
|
1971
|
-
el.style.overflowY = "auto";
|
|
1972
|
-
} else if (value === "horizontal") {
|
|
1973
|
-
el.style.overflowX = "auto";
|
|
1974
|
-
el.style.overflowY = "hidden";
|
|
1975
|
-
} else if (value === "both") {
|
|
1976
|
-
el.style.overflow = "auto";
|
|
1977
|
-
} else {
|
|
1978
|
-
el.style.overflow = String(value);
|
|
1979
|
-
}
|
|
1980
|
-
}
|
|
1981
|
-
};
|
|
1982
|
-
|
|
1983
|
-
// src/dom/element-data.ts
|
|
1984
|
-
import { getElementDisposables } from "@hypen-space/core/disposable";
|
|
1985
|
-
var elementDataMap = new WeakMap;
|
|
1986
|
-
function getHypenData(element) {
|
|
1987
|
-
let data = elementDataMap.get(element);
|
|
1988
|
-
if (!data) {
|
|
1989
|
-
data = {};
|
|
1990
|
-
elementDataMap.set(element, data);
|
|
1991
|
-
}
|
|
1992
|
-
return data;
|
|
1993
|
-
}
|
|
1994
|
-
function hasHypenData(element) {
|
|
1995
|
-
return elementDataMap.has(element);
|
|
1996
|
-
}
|
|
1997
|
-
function clearHypenData(element) {
|
|
1998
|
-
elementDataMap.delete(element);
|
|
1999
|
-
}
|
|
2000
|
-
function getEngine(element) {
|
|
2001
|
-
return getHypenData(element).engine;
|
|
2002
|
-
}
|
|
2003
|
-
function setEngine(element, engine) {
|
|
2004
|
-
getHypenData(element).engine = engine;
|
|
2005
|
-
}
|
|
2006
|
-
function findEngine(element) {
|
|
2007
|
-
let current = element;
|
|
2008
|
-
while (current) {
|
|
2009
|
-
const engine = getEngine(current);
|
|
2010
|
-
if (engine)
|
|
2011
|
-
return engine;
|
|
2012
|
-
current = current.parentElement;
|
|
2013
|
-
}
|
|
2014
|
-
return;
|
|
2015
|
-
}
|
|
2016
|
-
function getRegisteredEvents(element) {
|
|
2017
|
-
const data = getHypenData(element);
|
|
2018
|
-
if (!data.registeredEvents) {
|
|
2019
|
-
data.registeredEvents = new Set;
|
|
2020
|
-
}
|
|
2021
|
-
return data.registeredEvents;
|
|
2022
|
-
}
|
|
2023
|
-
function isEventRegistered(element, eventKey) {
|
|
2024
|
-
return getRegisteredEvents(element).has(eventKey);
|
|
2025
|
-
}
|
|
2026
|
-
function registerEvent(element, eventKey) {
|
|
2027
|
-
getRegisteredEvents(element).add(eventKey);
|
|
2028
|
-
}
|
|
2029
|
-
function unregisterEvent(element, eventKey) {
|
|
2030
|
-
getRegisteredEvents(element).delete(eventKey);
|
|
2031
|
-
}
|
|
2032
|
-
function getKeyTarget(element) {
|
|
2033
|
-
return getHypenData(element).keyTarget;
|
|
2034
|
-
}
|
|
2035
|
-
function setKeyTarget(element, key) {
|
|
2036
|
-
getHypenData(element).keyTarget = key;
|
|
2037
|
-
}
|
|
2038
|
-
function getMeta(element, key) {
|
|
2039
|
-
return getHypenData(element).meta?.[key];
|
|
2040
|
-
}
|
|
2041
|
-
function setMeta(element, key, value) {
|
|
2042
|
-
const data = getHypenData(element);
|
|
2043
|
-
if (!data.meta) {
|
|
2044
|
-
data.meta = {};
|
|
2045
|
-
}
|
|
2046
|
-
data.meta[key] = value;
|
|
2047
|
-
}
|
|
2048
|
-
function disposeHypenElement(element) {
|
|
2049
|
-
try {
|
|
2050
|
-
const disposables = getElementDisposables(element);
|
|
2051
|
-
disposables.dispose();
|
|
2052
|
-
} catch {}
|
|
2053
|
-
clearHypenData(element);
|
|
2054
|
-
}
|
|
2055
|
-
var HYPEN_ENGINE_SYMBOL = Symbol.for("hypen.engine");
|
|
2056
|
-
var REGISTERED_EVENTS_SYMBOL = Symbol.for("hypen.registeredEvents");
|
|
2057
|
-
var KEY_TARGET_SYMBOL = Symbol.for("hypen.keyTarget");
|
|
2058
|
-
function getLegacyEngine(element) {
|
|
2059
|
-
const engine = getEngine(element);
|
|
2060
|
-
if (engine)
|
|
2061
|
-
return engine;
|
|
2062
|
-
return element[HYPEN_ENGINE_SYMBOL] ?? element.__hypenEngine;
|
|
2063
|
-
}
|
|
2064
|
-
function setLegacyEngine(element, engine) {
|
|
2065
|
-
setEngine(element, engine);
|
|
2066
|
-
element.__hypenEngine = engine;
|
|
2067
|
-
}
|
|
2068
|
-
|
|
2069
|
-
// src/dom/applicators/events.ts
|
|
2070
|
-
import {
|
|
2071
|
-
getElementDisposables as getElementDisposables2,
|
|
2072
|
-
disposableListener,
|
|
2073
|
-
disposableTimeout
|
|
2074
|
-
} from "@hypen-space/core/disposable";
|
|
2075
|
-
import { frameworkLoggers as frameworkLoggers3 } from "@hypen-space/core/logger";
|
|
2076
|
-
var log3 = frameworkLoggers3.events;
|
|
2077
|
-
function toPlainObject(value) {
|
|
2078
|
-
if (value instanceof Map) {
|
|
2079
|
-
const obj = {};
|
|
2080
|
-
for (const [key, val] of value.entries()) {
|
|
2081
|
-
obj[key] = toPlainObject(val);
|
|
2082
|
-
}
|
|
2083
|
-
return obj;
|
|
2084
|
-
}
|
|
2085
|
-
if (Array.isArray(value)) {
|
|
2086
|
-
return value.map((item) => toPlainObject(item));
|
|
2087
|
-
}
|
|
2088
|
-
if (value && typeof value === "object") {
|
|
2089
|
-
const obj = {};
|
|
2090
|
-
for (const [key, val] of Object.entries(value)) {
|
|
2091
|
-
obj[key] = toPlainObject(val);
|
|
2092
|
-
}
|
|
2093
|
-
return obj;
|
|
2094
|
-
}
|
|
2095
|
-
return value;
|
|
2096
|
-
}
|
|
2097
|
-
function extractActionDetails(value) {
|
|
2098
|
-
if (typeof value === "string") {
|
|
2099
|
-
if (!value.startsWith("@")) {
|
|
2100
|
-
return { actionName: null, payload: {} };
|
|
2101
|
-
}
|
|
2102
|
-
let actionName = value.substring(1);
|
|
2103
|
-
if (actionName.startsWith("actions.")) {
|
|
2104
|
-
actionName = actionName.substring(8);
|
|
2105
|
-
}
|
|
2106
|
-
return { actionName, payload: {} };
|
|
2107
|
-
}
|
|
2108
|
-
if (value && typeof value === "object") {
|
|
2109
|
-
const plain = toPlainObject(value);
|
|
2110
|
-
const payload = {};
|
|
2111
|
-
let actionName = null;
|
|
2112
|
-
if (plain && typeof plain === "object") {
|
|
2113
|
-
const actionValue = plain["0"];
|
|
2114
|
-
if (typeof actionValue === "string" && actionValue.startsWith("@")) {
|
|
2115
|
-
actionName = actionValue.substring(1);
|
|
2116
|
-
if (actionName.startsWith("actions.")) {
|
|
2117
|
-
actionName = actionName.substring(8);
|
|
141
|
+
if (this.container) {
|
|
142
|
+
this.container.innerHTML = "";
|
|
143
|
+
this.container = null;
|
|
2118
144
|
}
|
|
2119
|
-
|
|
2120
|
-
|
|
2121
|
-
|
|
2122
|
-
|
|
2123
|
-
|
|
2124
|
-
|
|
2125
|
-
|
|
2126
|
-
|
|
2127
|
-
|
|
2128
|
-
|
|
145
|
+
this.renderer = null;
|
|
146
|
+
log.debug("Unmounted");
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Get the current module instance
|
|
150
|
+
*/
|
|
151
|
+
getModuleInstance() {
|
|
152
|
+
return this.moduleInstance;
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Get the current state
|
|
156
|
+
*/
|
|
157
|
+
getState() {
|
|
158
|
+
return this.moduleInstance?.getState() ?? null;
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Get the router instance
|
|
162
|
+
*/
|
|
163
|
+
getRouter() {
|
|
164
|
+
return this.router;
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Get the global context
|
|
168
|
+
*/
|
|
169
|
+
getGlobalContext() {
|
|
170
|
+
return this.globalContext;
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Enable or disable debug heatmap mode
|
|
174
|
+
*/
|
|
175
|
+
setDebugHeatmap(enabled) {
|
|
176
|
+
if (this.renderer) {
|
|
177
|
+
this.renderer.setDebugConfig({ enabled, showHeatmap: enabled });
|
|
178
|
+
log.debug(`Debug heatmap ${enabled ? "enabled" : "disabled"}`);
|
|
2129
179
|
}
|
|
2130
|
-
}
|
|
2131
|
-
}
|
|
2132
|
-
return { actionName, payload };
|
|
2133
|
-
}
|
|
2134
|
-
return { actionName: null, payload: {} };
|
|
2135
|
-
}
|
|
2136
|
-
function extractEventData(event, element) {
|
|
2137
|
-
const data = {
|
|
2138
|
-
type: event.type,
|
|
2139
|
-
timestamp: Date.now()
|
|
2140
|
-
};
|
|
2141
|
-
if (event instanceof MouseEvent) {
|
|
2142
|
-
data.clientX = event.clientX;
|
|
2143
|
-
data.clientY = event.clientY;
|
|
2144
|
-
data.button = event.button;
|
|
2145
|
-
}
|
|
2146
|
-
if (event instanceof KeyboardEvent) {
|
|
2147
|
-
data.key = event.key;
|
|
2148
|
-
data.code = event.code;
|
|
2149
|
-
data.ctrlKey = event.ctrlKey;
|
|
2150
|
-
data.shiftKey = event.shiftKey;
|
|
2151
|
-
data.altKey = event.altKey;
|
|
2152
|
-
data.metaKey = event.metaKey;
|
|
2153
|
-
}
|
|
2154
|
-
if (element instanceof HTMLInputElement || element instanceof HTMLTextAreaElement) {
|
|
2155
|
-
data.value = element.value;
|
|
2156
|
-
}
|
|
2157
|
-
if (element instanceof HTMLSelectElement) {
|
|
2158
|
-
data.value = element.value;
|
|
2159
|
-
data.selectedIndex = element.selectedIndex;
|
|
2160
|
-
}
|
|
2161
|
-
if (event.type === "submit" && element instanceof HTMLFormElement) {
|
|
2162
|
-
data.formData = new FormData(element);
|
|
2163
|
-
}
|
|
2164
|
-
return data;
|
|
2165
|
-
}
|
|
2166
|
-
function createEventHandler(eventType, options = {}) {
|
|
2167
|
-
return (element, value) => {
|
|
2168
|
-
const { actionName, payload: customPayload } = extractActionDetails(value);
|
|
2169
|
-
if (!actionName) {
|
|
2170
|
-
log3.warn(`${eventType} requires an action reference starting with @, got:`, value);
|
|
2171
|
-
return;
|
|
2172
|
-
}
|
|
2173
|
-
const disposables = getElementDisposables2(element);
|
|
2174
|
-
const eventKey = `${eventType}:${actionName}`;
|
|
2175
|
-
if (getRegisteredEvents(element).has(eventKey)) {
|
|
2176
|
-
return;
|
|
2177
180
|
}
|
|
2178
|
-
|
|
2179
|
-
|
|
2180
|
-
|
|
2181
|
-
|
|
2182
|
-
|
|
2183
|
-
|
|
2184
|
-
|
|
2185
|
-
throttleTimer = disposableTimeout(() => {
|
|
2186
|
-
throttleTimer = null;
|
|
2187
|
-
}, options.throttleMs);
|
|
2188
|
-
}
|
|
2189
|
-
if (options.preventDefault) {
|
|
2190
|
-
event.preventDefault();
|
|
2191
|
-
}
|
|
2192
|
-
const payload = Object.keys(customPayload).length > 0 ? { ...customPayload } : options.extractPayload ? options.extractPayload(event, element) : extractEventData(event, element);
|
|
2193
|
-
const engine = getEngine(element);
|
|
2194
|
-
if (engine) {
|
|
2195
|
-
try {
|
|
2196
|
-
engine.dispatchAction(actionName, payload);
|
|
2197
|
-
} catch (err) {
|
|
2198
|
-
log3.error(`Error dispatching action "${actionName}":`, err);
|
|
181
|
+
/**
|
|
182
|
+
* Reset debug tracking for all elements
|
|
183
|
+
*/
|
|
184
|
+
resetDebugTracking() {
|
|
185
|
+
if (this.renderer) {
|
|
186
|
+
this.renderer.resetDebugTracking();
|
|
187
|
+
log.debug("Debug tracking reset");
|
|
2199
188
|
}
|
|
2200
|
-
}
|
|
2201
|
-
};
|
|
2202
|
-
disposables.add(disposableListener(element, eventType, listener, {
|
|
2203
|
-
passive: options.passive
|
|
2204
|
-
}));
|
|
2205
|
-
disposables.addCallback(() => {
|
|
2206
|
-
unregisterEvent(element, eventKey);
|
|
2207
|
-
if (throttleTimer) {
|
|
2208
|
-
throttleTimer.dispose();
|
|
2209
|
-
}
|
|
2210
|
-
});
|
|
2211
|
-
};
|
|
2212
|
-
}
|
|
2213
|
-
function createKeyHandler(defaultKey = "Enter") {
|
|
2214
|
-
return (element, value) => {
|
|
2215
|
-
const { actionName, payload: customPayload } = extractActionDetails(value);
|
|
2216
|
-
if (!actionName) {
|
|
2217
|
-
log3.warn(`onKey requires an action reference starting with @, got:`, value);
|
|
2218
|
-
return;
|
|
2219
189
|
}
|
|
2220
|
-
|
|
2221
|
-
|
|
2222
|
-
|
|
2223
|
-
|
|
2224
|
-
|
|
2225
|
-
|
|
2226
|
-
|
|
2227
|
-
|
|
2228
|
-
|
|
2229
|
-
|
|
2230
|
-
|
|
2231
|
-
|
|
2232
|
-
|
|
2233
|
-
event.preventDefault();
|
|
2234
|
-
const target = event.target;
|
|
2235
|
-
const payload = Object.keys(customPayload).length > 0 ? { ...customPayload } : {
|
|
2236
|
-
type: event.type,
|
|
2237
|
-
timestamp: Date.now(),
|
|
2238
|
-
key: keyEvent.key,
|
|
2239
|
-
code: keyEvent.code,
|
|
2240
|
-
value: target.value,
|
|
2241
|
-
input: target.value,
|
|
2242
|
-
ctrlKey: keyEvent.ctrlKey,
|
|
2243
|
-
shiftKey: keyEvent.shiftKey,
|
|
2244
|
-
altKey: keyEvent.altKey,
|
|
2245
|
-
metaKey: keyEvent.metaKey
|
|
2246
|
-
};
|
|
2247
|
-
const engine = getEngine(element);
|
|
2248
|
-
if (engine) {
|
|
2249
|
-
engine.dispatchAction(actionName, payload);
|
|
2250
|
-
}
|
|
2251
|
-
};
|
|
2252
|
-
disposables.add(disposableListener(element, "keydown", listener));
|
|
2253
|
-
disposables.addCallback(() => {
|
|
2254
|
-
unregisterEvent(element, eventKey);
|
|
2255
|
-
});
|
|
2256
|
-
};
|
|
2257
|
-
}
|
|
2258
|
-
function createLongClickHandler(thresholdMs = 500) {
|
|
2259
|
-
return (element, value) => {
|
|
2260
|
-
const { actionName, payload: customPayload } = extractActionDetails(value);
|
|
2261
|
-
if (!actionName) {
|
|
2262
|
-
log3.warn(`onLongClick requires an action reference starting with @, got:`, value);
|
|
2263
|
-
return;
|
|
2264
|
-
}
|
|
2265
|
-
const disposables = getElementDisposables2(element);
|
|
2266
|
-
const eventKey = `longclick:${actionName}`;
|
|
2267
|
-
if (getRegisteredEvents(element).has(eventKey)) {
|
|
2268
|
-
return;
|
|
2269
|
-
}
|
|
2270
|
-
registerEvent(element, eventKey);
|
|
2271
|
-
let longClickTimer = null;
|
|
2272
|
-
const downListener = (event) => {
|
|
2273
|
-
const pointerEvent = event;
|
|
2274
|
-
longClickTimer = disposableTimeout(() => {
|
|
2275
|
-
const payload = Object.keys(customPayload).length > 0 ? { ...customPayload } : {
|
|
2276
|
-
type: "longclick",
|
|
2277
|
-
timestamp: Date.now(),
|
|
2278
|
-
clientX: pointerEvent.clientX,
|
|
2279
|
-
clientY: pointerEvent.clientY
|
|
2280
|
-
};
|
|
2281
|
-
const engine = getEngine(element);
|
|
2282
|
-
if (engine) {
|
|
2283
|
-
engine.dispatchAction(actionName, payload);
|
|
190
|
+
/**
|
|
191
|
+
* Get debug statistics
|
|
192
|
+
*/
|
|
193
|
+
getDebugStats() {
|
|
194
|
+
return this.renderer?.getDebugStats() || null;
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Render a lazy route component into a specific route element
|
|
198
|
+
* This is called by the Router when a route becomes active
|
|
199
|
+
*/
|
|
200
|
+
async renderLazyRoute(routePath, componentName, routeElement) {
|
|
201
|
+
if (!this.engine || !this.renderer) {
|
|
202
|
+
throw new Error("Engine not initialized");
|
|
2284
203
|
}
|
|
2285
|
-
|
|
2286
|
-
|
|
2287
|
-
|
|
2288
|
-
|
|
2289
|
-
if (longClickTimer) {
|
|
2290
|
-
longClickTimer.dispose();
|
|
2291
|
-
longClickTimer = null;
|
|
2292
|
-
}
|
|
2293
|
-
};
|
|
2294
|
-
disposables.add(disposableListener(element, "pointerdown", downListener));
|
|
2295
|
-
disposables.add(disposableListener(element, "pointerup", cancelListener));
|
|
2296
|
-
disposables.add(disposableListener(element, "pointerleave", cancelListener));
|
|
2297
|
-
disposables.addCallback(() => {
|
|
2298
|
-
unregisterEvent(element, eventKey);
|
|
2299
|
-
cancelListener();
|
|
2300
|
-
});
|
|
2301
|
-
};
|
|
2302
|
-
}
|
|
2303
|
-
var inputPayload = (event, element) => {
|
|
2304
|
-
const target = element;
|
|
2305
|
-
return {
|
|
2306
|
-
type: event.type,
|
|
2307
|
-
timestamp: Date.now(),
|
|
2308
|
-
value: target.value,
|
|
2309
|
-
input: target.value
|
|
2310
|
-
};
|
|
2311
|
-
};
|
|
2312
|
-
var scrollPayload = (_event, element) => {
|
|
2313
|
-
const scrollTop = element.scrollTop;
|
|
2314
|
-
const scrollHeight = element.scrollHeight;
|
|
2315
|
-
const clientHeight = element.clientHeight;
|
|
2316
|
-
const scrollPercentage = scrollHeight - clientHeight > 0 ? scrollTop / (scrollHeight - clientHeight) * 100 : 0;
|
|
2317
|
-
const nearBottom = scrollHeight - scrollTop - clientHeight < 100 || scrollPercentage > 90;
|
|
2318
|
-
return {
|
|
2319
|
-
type: "scroll",
|
|
2320
|
-
timestamp: Date.now(),
|
|
2321
|
-
scrollTop,
|
|
2322
|
-
scrollLeft: element.scrollLeft,
|
|
2323
|
-
scrollHeight,
|
|
2324
|
-
scrollWidth: element.scrollWidth,
|
|
2325
|
-
clientHeight,
|
|
2326
|
-
clientWidth: element.clientWidth,
|
|
2327
|
-
scrollPercentage: Math.round(scrollPercentage),
|
|
2328
|
-
nearBottom,
|
|
2329
|
-
atBottom: scrollHeight - scrollTop === clientHeight,
|
|
2330
|
-
atTop: scrollTop === 0
|
|
2331
|
-
};
|
|
2332
|
-
};
|
|
2333
|
-
var focusPayload = (event, element) => ({
|
|
2334
|
-
type: event.type,
|
|
2335
|
-
timestamp: Date.now(),
|
|
2336
|
-
value: element.value ?? undefined
|
|
2337
|
-
});
|
|
2338
|
-
var mousePayload = (event, _element) => {
|
|
2339
|
-
const mouseEvent = event;
|
|
2340
|
-
return {
|
|
2341
|
-
type: event.type,
|
|
2342
|
-
timestamp: Date.now(),
|
|
2343
|
-
clientX: mouseEvent.clientX,
|
|
2344
|
-
clientY: mouseEvent.clientY
|
|
2345
|
-
};
|
|
2346
|
-
};
|
|
2347
|
-
var eventHandlers = {
|
|
2348
|
-
onClick: createEventHandler("click"),
|
|
2349
|
-
onPress: createEventHandler("click"),
|
|
2350
|
-
onChange: createEventHandler("change"),
|
|
2351
|
-
onSubmit: createEventHandler("submit", { preventDefault: true }),
|
|
2352
|
-
onInput: createEventHandler("input", { extractPayload: inputPayload }),
|
|
2353
|
-
onKey: createKeyHandler("Enter"),
|
|
2354
|
-
"onKey.key": (element, value) => {
|
|
2355
|
-
setKeyTarget(element, String(value));
|
|
2356
|
-
},
|
|
2357
|
-
"onKey.action": createKeyHandler("Enter"),
|
|
2358
|
-
onScroll: createEventHandler("scroll", {
|
|
2359
|
-
throttleMs: 100,
|
|
2360
|
-
passive: true,
|
|
2361
|
-
extractPayload: scrollPayload
|
|
2362
|
-
}),
|
|
2363
|
-
onLongClick: createLongClickHandler(500),
|
|
2364
|
-
onLongPress: createLongClickHandler(500),
|
|
2365
|
-
onFocus: createEventHandler("focus", { extractPayload: focusPayload }),
|
|
2366
|
-
onBlur: createEventHandler("blur", { extractPayload: focusPayload }),
|
|
2367
|
-
onMouseEnter: createEventHandler("mouseenter", { extractPayload: mousePayload }),
|
|
2368
|
-
onMouseLeave: createEventHandler("mouseleave", { extractPayload: mousePayload }),
|
|
2369
|
-
bind: (element, value) => {
|
|
2370
|
-
const bindPath = typeof value === "string" ? value : null;
|
|
2371
|
-
if (!bindPath)
|
|
2372
|
-
return;
|
|
2373
|
-
const disposables = getElementDisposables2(element);
|
|
2374
|
-
const eventKey = `bind:${bindPath}`;
|
|
2375
|
-
if (getRegisteredEvents(element).has(eventKey))
|
|
2376
|
-
return;
|
|
2377
|
-
registerEvent(element, eventKey);
|
|
2378
|
-
const hypenType = element.dataset?.hypenType;
|
|
2379
|
-
if (hypenType === "checkbox" || hypenType === "switch") {
|
|
2380
|
-
const input = element.querySelector('input[type="checkbox"]');
|
|
2381
|
-
if (!input)
|
|
2382
|
-
return;
|
|
2383
|
-
const listener = () => {
|
|
2384
|
-
const engine = getEngine(element);
|
|
2385
|
-
if (engine) {
|
|
2386
|
-
engine.dispatchAction("__hypen_bind", {
|
|
2387
|
-
path: bindPath,
|
|
2388
|
-
value: input.checked
|
|
2389
|
-
});
|
|
204
|
+
// Get the component from the loader
|
|
205
|
+
const component = componentLoader.get(componentName);
|
|
206
|
+
if (!component) {
|
|
207
|
+
throw new Error(`Component ${componentName} not found`);
|
|
2390
208
|
}
|
|
2391
|
-
|
|
2392
|
-
|
|
2393
|
-
|
|
2394
|
-
|
|
2395
|
-
const engine = getEngine(element);
|
|
2396
|
-
if (engine) {
|
|
2397
|
-
engine.dispatchAction("__hypen_bind", {
|
|
2398
|
-
path: bindPath,
|
|
2399
|
-
value: element.value
|
|
2400
|
-
});
|
|
209
|
+
// Get the component template
|
|
210
|
+
const template = component.template;
|
|
211
|
+
if (!template) {
|
|
212
|
+
throw new Error(`Component ${componentName} has no template`);
|
|
2401
213
|
}
|
|
2402
|
-
|
|
2403
|
-
|
|
2404
|
-
|
|
2405
|
-
|
|
2406
|
-
|
|
2407
|
-
|
|
2408
|
-
|
|
2409
|
-
|
|
2410
|
-
|
|
2411
|
-
|
|
214
|
+
// Create module instance for this component if it has state
|
|
215
|
+
if (component.module && !this.moduleInstances.has(componentName)) {
|
|
216
|
+
const moduleId = this.extractModuleId(componentName, template);
|
|
217
|
+
const moduleInstance = new HypenModuleInstance(this.engine, component.module, this.router, this.globalContext);
|
|
218
|
+
this.globalContext.registerModule(moduleId, moduleInstance);
|
|
219
|
+
this.moduleInstances.set(componentName, moduleInstance);
|
|
220
|
+
// Listen to state changes
|
|
221
|
+
moduleInstance.onStateChange(() => {
|
|
222
|
+
const mergedState = this.getMergedState();
|
|
223
|
+
log.debug(`Lazy component ${componentName} state changed:`, mergedState);
|
|
224
|
+
this.renderer.updateState(mergedState);
|
|
225
|
+
});
|
|
2412
226
|
}
|
|
2413
|
-
|
|
2414
|
-
|
|
2415
|
-
|
|
2416
|
-
|
|
2417
|
-
|
|
2418
|
-
|
|
2419
|
-
}
|
|
2420
|
-
disposables.addCallback(() => unregisterEvent(element, eventKey));
|
|
2421
|
-
}
|
|
2422
|
-
};
|
|
2423
|
-
|
|
2424
|
-
// src/dom/applicators/typography.ts
|
|
2425
|
-
var typographyHandlers = {
|
|
2426
|
-
textAlign: (el, value) => {
|
|
2427
|
-
el.style.textAlign = String(value);
|
|
2428
|
-
},
|
|
2429
|
-
textTransform: (el, value) => {
|
|
2430
|
-
el.style.textTransform = String(value);
|
|
2431
|
-
},
|
|
2432
|
-
textDecoration: (el, value) => {
|
|
2433
|
-
el.style.textDecoration = String(value);
|
|
2434
|
-
},
|
|
2435
|
-
textDecorationColor: (el, value) => {
|
|
2436
|
-
el.style.textDecorationColor = String(value);
|
|
2437
|
-
},
|
|
2438
|
-
textDecorationStyle: (el, value) => {
|
|
2439
|
-
el.style.textDecorationStyle = String(value);
|
|
2440
|
-
},
|
|
2441
|
-
textDecorationThickness: (el, value) => {
|
|
2442
|
-
el.style.textDecorationThickness = typeof value === "number" ? `${value}px` : String(value);
|
|
2443
|
-
},
|
|
2444
|
-
letterSpacing: (el, value) => {
|
|
2445
|
-
el.style.letterSpacing = typeof value === "number" ? `${value}px` : String(value);
|
|
2446
|
-
},
|
|
2447
|
-
wordSpacing: (el, value) => {
|
|
2448
|
-
el.style.wordSpacing = typeof value === "number" ? `${value}px` : String(value);
|
|
2449
|
-
},
|
|
2450
|
-
lineHeight: (el, value) => {
|
|
2451
|
-
el.style.lineHeight = String(value);
|
|
2452
|
-
},
|
|
2453
|
-
textIndent: (el, value) => {
|
|
2454
|
-
el.style.textIndent = typeof value === "number" ? `${value}px` : String(value);
|
|
2455
|
-
},
|
|
2456
|
-
textOverflow: (el, value) => {
|
|
2457
|
-
el.style.textOverflow = String(value);
|
|
2458
|
-
},
|
|
2459
|
-
whiteSpace: (el, value) => {
|
|
2460
|
-
el.style.whiteSpace = String(value);
|
|
2461
|
-
},
|
|
2462
|
-
wordBreak: (el, value) => {
|
|
2463
|
-
el.style.wordBreak = String(value);
|
|
2464
|
-
},
|
|
2465
|
-
verticalAlign: (el, value) => {
|
|
2466
|
-
el.style.verticalAlign = String(value);
|
|
2467
|
-
},
|
|
2468
|
-
fontVariant: (el, value) => {
|
|
2469
|
-
el.style.fontVariant = String(value);
|
|
2470
|
-
},
|
|
2471
|
-
fontStretch: (el, value) => {
|
|
2472
|
-
el.style.fontStretch = String(value);
|
|
2473
|
-
},
|
|
2474
|
-
fontStyle: (el, value) => {
|
|
2475
|
-
el.style.fontStyle = String(value);
|
|
2476
|
-
},
|
|
2477
|
-
writingMode: (el, value) => {
|
|
2478
|
-
el.style.writingMode = String(value);
|
|
2479
|
-
},
|
|
2480
|
-
maxLines: (el, value) => {
|
|
2481
|
-
const lines = typeof value === "number" ? value : parseInt(String(value), 10);
|
|
2482
|
-
if (!isNaN(lines) && lines > 0) {
|
|
2483
|
-
el.style.display = "-webkit-box";
|
|
2484
|
-
el.style.setProperty("-webkit-line-clamp", String(lines));
|
|
2485
|
-
el.style.setProperty("-webkit-box-orient", "vertical");
|
|
2486
|
-
el.style.overflow = "hidden";
|
|
2487
|
-
}
|
|
2488
|
-
}
|
|
2489
|
-
};
|
|
2490
|
-
|
|
2491
|
-
// src/dom/applicators/transform.ts
|
|
2492
|
-
var transformHandlers = {
|
|
2493
|
-
transform: (el, value) => {
|
|
2494
|
-
el.style.transform = String(value);
|
|
2495
|
-
},
|
|
2496
|
-
transformOrigin: (el, value) => {
|
|
2497
|
-
el.style.transformOrigin = String(value);
|
|
2498
|
-
},
|
|
2499
|
-
translateX: (el, value) => {
|
|
2500
|
-
const current = el.style.transform || "";
|
|
2501
|
-
const val = typeof value === "number" ? `${value}px` : String(value);
|
|
2502
|
-
el.style.transform = current ? `${current} translateX(${val})` : `translateX(${val})`;
|
|
2503
|
-
},
|
|
2504
|
-
translateY: (el, value) => {
|
|
2505
|
-
const current = el.style.transform || "";
|
|
2506
|
-
const val = typeof value === "number" ? `${value}px` : String(value);
|
|
2507
|
-
el.style.transform = current ? `${current} translateY(${val})` : `translateY(${val})`;
|
|
2508
|
-
},
|
|
2509
|
-
translateZ: (el, value) => {
|
|
2510
|
-
const current = el.style.transform || "";
|
|
2511
|
-
const val = typeof value === "number" ? `${value}px` : String(value);
|
|
2512
|
-
el.style.transform = current ? `${current} translateZ(${val})` : `translateZ(${val})`;
|
|
2513
|
-
},
|
|
2514
|
-
rotate: (el, value) => {
|
|
2515
|
-
const current = el.style.transform || "";
|
|
2516
|
-
const val = String(value);
|
|
2517
|
-
el.style.transform = current ? `${current} rotate(${val})` : `rotate(${val})`;
|
|
2518
|
-
},
|
|
2519
|
-
rotateX: (el, value) => {
|
|
2520
|
-
const current = el.style.transform || "";
|
|
2521
|
-
const val = String(value);
|
|
2522
|
-
el.style.transform = current ? `${current} rotateX(${val})` : `rotateX(${val})`;
|
|
2523
|
-
},
|
|
2524
|
-
rotateY: (el, value) => {
|
|
2525
|
-
const current = el.style.transform || "";
|
|
2526
|
-
const val = String(value);
|
|
2527
|
-
el.style.transform = current ? `${current} rotateY(${val})` : `rotateY(${val})`;
|
|
2528
|
-
},
|
|
2529
|
-
rotateZ: (el, value) => {
|
|
2530
|
-
const current = el.style.transform || "";
|
|
2531
|
-
const val = String(value);
|
|
2532
|
-
el.style.transform = current ? `${current} rotateZ(${val})` : `rotateZ(${val})`;
|
|
2533
|
-
},
|
|
2534
|
-
scale: (el, value) => {
|
|
2535
|
-
const current = el.style.transform || "";
|
|
2536
|
-
el.style.transform = current ? `${current} scale(${value})` : `scale(${value})`;
|
|
2537
|
-
},
|
|
2538
|
-
scaleX: (el, value) => {
|
|
2539
|
-
const current = el.style.transform || "";
|
|
2540
|
-
el.style.transform = current ? `${current} scaleX(${value})` : `scaleX(${value})`;
|
|
2541
|
-
},
|
|
2542
|
-
scaleY: (el, value) => {
|
|
2543
|
-
const current = el.style.transform || "";
|
|
2544
|
-
el.style.transform = current ? `${current} scaleY(${value})` : `scaleY(${value})`;
|
|
2545
|
-
},
|
|
2546
|
-
skew: (el, value) => {
|
|
2547
|
-
const current = el.style.transform || "";
|
|
2548
|
-
el.style.transform = current ? `${current} skew(${value})` : `skew(${value})`;
|
|
2549
|
-
},
|
|
2550
|
-
skewX: (el, value) => {
|
|
2551
|
-
const current = el.style.transform || "";
|
|
2552
|
-
el.style.transform = current ? `${current} skewX(${value})` : `skewX(${value})`;
|
|
2553
|
-
},
|
|
2554
|
-
skewY: (el, value) => {
|
|
2555
|
-
const current = el.style.transform || "";
|
|
2556
|
-
el.style.transform = current ? `${current} skewY(${value})` : `skewY(${value})`;
|
|
2557
|
-
},
|
|
2558
|
-
perspective: (el, value) => {
|
|
2559
|
-
el.style.perspective = typeof value === "number" ? `${value}px` : String(value);
|
|
2560
|
-
}
|
|
2561
|
-
};
|
|
2562
|
-
|
|
2563
|
-
// src/dom/applicators/effects.ts
|
|
2564
|
-
var effectsHandlers = {
|
|
2565
|
-
boxShadow: (el, value) => {
|
|
2566
|
-
if (typeof value === "string") {
|
|
2567
|
-
el.style.boxShadow = value;
|
|
2568
|
-
} else if (typeof value === "object" && value !== null) {
|
|
2569
|
-
const obj = value;
|
|
2570
|
-
const x = typeof obj.x === "number" ? `${obj.x}px` : obj.x ?? obj.offsetX ?? "0px";
|
|
2571
|
-
const y = typeof obj.y === "number" ? `${obj.y}px` : obj.y ?? obj.offsetY ?? "0px";
|
|
2572
|
-
const blur = typeof obj.blur === "number" ? `${obj.blur}px` : obj.blur ?? obj.radius ?? "0px";
|
|
2573
|
-
const spread = typeof obj.spread === "number" ? `${obj.spread}px` : obj.spread ?? "0px";
|
|
2574
|
-
const color = obj.color ?? "rgba(0,0,0,0.2)";
|
|
2575
|
-
const inset = obj.inset ? "inset " : "";
|
|
2576
|
-
el.style.boxShadow = `${inset}${x} ${y} ${blur} ${spread} ${color}`;
|
|
2577
|
-
} else if (typeof value === "number") {
|
|
2578
|
-
el.style.boxShadow = `0 ${value}px ${value * 2}px rgba(0,0,0,0.2)`;
|
|
2579
|
-
}
|
|
2580
|
-
},
|
|
2581
|
-
shadow: (el, value) => {
|
|
2582
|
-
if (typeof value === "object" && value !== null) {
|
|
2583
|
-
const obj = value;
|
|
2584
|
-
const x = typeof obj.x === "number" ? `${obj.x}px` : obj.x ?? obj.offsetX ?? "0px";
|
|
2585
|
-
const y = typeof obj.y === "number" ? `${obj.y}px` : obj.y ?? obj.offsetY ?? "0px";
|
|
2586
|
-
const blur = typeof obj.blur === "number" ? `${obj.blur}px` : obj.blur ?? obj.radius ?? "4px";
|
|
2587
|
-
const color = obj.color ?? "rgba(0,0,0,0.2)";
|
|
2588
|
-
el.style.boxShadow = `${x} ${y} ${blur} ${color}`;
|
|
2589
|
-
} else if (typeof value === "number") {
|
|
2590
|
-
el.style.boxShadow = `0 ${value}px ${value * 2}px rgba(0,0,0,0.2)`;
|
|
2591
|
-
} else {
|
|
2592
|
-
el.style.boxShadow = String(value);
|
|
2593
|
-
}
|
|
2594
|
-
},
|
|
2595
|
-
elevation: (el, value) => {
|
|
2596
|
-
const level = typeof value === "number" ? value : parseInt(String(value), 10);
|
|
2597
|
-
if (!isNaN(level) && level >= 0) {
|
|
2598
|
-
const y = level * 0.5;
|
|
2599
|
-
const blur = level * 1.5;
|
|
2600
|
-
const opacity = Math.min(0.1 + level * 0.02, 0.4);
|
|
2601
|
-
el.style.boxShadow = `0 ${y}px ${blur}px rgba(0,0,0,${opacity})`;
|
|
2602
|
-
}
|
|
2603
|
-
},
|
|
2604
|
-
textShadow: (el, value) => {
|
|
2605
|
-
el.style.textShadow = String(value);
|
|
2606
|
-
},
|
|
2607
|
-
filter: (el, value) => {
|
|
2608
|
-
el.style.filter = String(value);
|
|
2609
|
-
},
|
|
2610
|
-
backdropFilter: (el, value) => {
|
|
2611
|
-
el.style.backdropFilter = String(value);
|
|
2612
|
-
},
|
|
2613
|
-
blur: (el, value) => {
|
|
2614
|
-
const val = typeof value === "number" ? `${value}px` : String(value);
|
|
2615
|
-
const current = el.style.filter || "";
|
|
2616
|
-
el.style.filter = current ? `${current} blur(${val})` : `blur(${val})`;
|
|
2617
|
-
},
|
|
2618
|
-
brightness: (el, value) => {
|
|
2619
|
-
const current = el.style.filter || "";
|
|
2620
|
-
el.style.filter = current ? `${current} brightness(${value})` : `brightness(${value})`;
|
|
2621
|
-
},
|
|
2622
|
-
contrast: (el, value) => {
|
|
2623
|
-
const current = el.style.filter || "";
|
|
2624
|
-
el.style.filter = current ? `${current} contrast(${value})` : `contrast(${value})`;
|
|
2625
|
-
},
|
|
2626
|
-
grayscale: (el, value) => {
|
|
2627
|
-
const current = el.style.filter || "";
|
|
2628
|
-
el.style.filter = current ? `${current} grayscale(${value})` : `grayscale(${value})`;
|
|
2629
|
-
},
|
|
2630
|
-
hueRotate: (el, value) => {
|
|
2631
|
-
const val = String(value);
|
|
2632
|
-
const current = el.style.filter || "";
|
|
2633
|
-
el.style.filter = current ? `${current} hue-rotate(${val})` : `hue-rotate(${val})`;
|
|
2634
|
-
},
|
|
2635
|
-
invert: (el, value) => {
|
|
2636
|
-
const current = el.style.filter || "";
|
|
2637
|
-
el.style.filter = current ? `${current} invert(${value})` : `invert(${value})`;
|
|
2638
|
-
},
|
|
2639
|
-
saturate: (el, value) => {
|
|
2640
|
-
const current = el.style.filter || "";
|
|
2641
|
-
el.style.filter = current ? `${current} saturate(${value})` : `saturate(${value})`;
|
|
2642
|
-
},
|
|
2643
|
-
sepia: (el, value) => {
|
|
2644
|
-
const current = el.style.filter || "";
|
|
2645
|
-
el.style.filter = current ? `${current} sepia(${value})` : `sepia(${value})`;
|
|
2646
|
-
},
|
|
2647
|
-
dropShadow: (el, value) => {
|
|
2648
|
-
const current = el.style.filter || "";
|
|
2649
|
-
el.style.filter = current ? `${current} drop-shadow(${value})` : `drop-shadow(${value})`;
|
|
2650
|
-
},
|
|
2651
|
-
mixBlendMode: (el, value) => {
|
|
2652
|
-
el.style.mixBlendMode = String(value);
|
|
2653
|
-
},
|
|
2654
|
-
backgroundBlendMode: (el, value) => {
|
|
2655
|
-
el.style.backgroundBlendMode = String(value);
|
|
2656
|
-
},
|
|
2657
|
-
clipPath: (el, value) => {
|
|
2658
|
-
el.style.clipPath = String(value);
|
|
2659
|
-
},
|
|
2660
|
-
mask: (el, value) => {
|
|
2661
|
-
el.style.mask = String(value);
|
|
2662
|
-
},
|
|
2663
|
-
maskImage: (el, value) => {
|
|
2664
|
-
el.style.maskImage = String(value);
|
|
2665
|
-
}
|
|
2666
|
-
};
|
|
2667
|
-
|
|
2668
|
-
// src/dom/applicators/advanced-layout.ts
|
|
2669
|
-
var advancedLayoutHandlers = {
|
|
2670
|
-
flexDirection: (el, value) => {
|
|
2671
|
-
el.style.flexDirection = String(value);
|
|
2672
|
-
},
|
|
2673
|
-
flexWrap: (el, value) => {
|
|
2674
|
-
el.style.flexWrap = String(value);
|
|
2675
|
-
},
|
|
2676
|
-
flexBasis: (el, value) => {
|
|
2677
|
-
el.style.flexBasis = typeof value === "number" ? `${value}px` : String(value);
|
|
2678
|
-
},
|
|
2679
|
-
alignContent: (el, value) => {
|
|
2680
|
-
el.style.alignContent = String(value);
|
|
2681
|
-
},
|
|
2682
|
-
order: (el, value) => {
|
|
2683
|
-
el.style.order = String(value);
|
|
2684
|
-
},
|
|
2685
|
-
gridTemplateColumns: (el, value) => {
|
|
2686
|
-
el.style.gridTemplateColumns = String(value);
|
|
2687
|
-
},
|
|
2688
|
-
gridTemplateRows: (el, value) => {
|
|
2689
|
-
el.style.gridTemplateRows = String(value);
|
|
2690
|
-
},
|
|
2691
|
-
gridColumns: (el, value) => {
|
|
2692
|
-
if (typeof value === "number") {
|
|
2693
|
-
el.style.gridTemplateColumns = `repeat(${value}, 1fr)`;
|
|
2694
|
-
} else {
|
|
2695
|
-
el.style.gridTemplateColumns = String(value);
|
|
2696
|
-
}
|
|
2697
|
-
},
|
|
2698
|
-
gridRows: (el, value) => {
|
|
2699
|
-
if (typeof value === "number") {
|
|
2700
|
-
el.style.gridTemplateRows = `repeat(${value}, 1fr)`;
|
|
2701
|
-
} else {
|
|
2702
|
-
el.style.gridTemplateRows = String(value);
|
|
2703
|
-
}
|
|
2704
|
-
},
|
|
2705
|
-
gridTemplateAreas: (el, value) => {
|
|
2706
|
-
el.style.gridTemplateAreas = String(value);
|
|
2707
|
-
},
|
|
2708
|
-
gridColumn: (el, value) => {
|
|
2709
|
-
el.style.gridColumn = String(value);
|
|
2710
|
-
},
|
|
2711
|
-
gridRow: (el, value) => {
|
|
2712
|
-
el.style.gridRow = String(value);
|
|
2713
|
-
},
|
|
2714
|
-
gridArea: (el, value) => {
|
|
2715
|
-
el.style.gridArea = String(value);
|
|
2716
|
-
},
|
|
2717
|
-
gridAutoFlow: (el, value) => {
|
|
2718
|
-
el.style.gridAutoFlow = String(value);
|
|
2719
|
-
},
|
|
2720
|
-
gridAutoColumns: (el, value) => {
|
|
2721
|
-
el.style.gridAutoColumns = String(value);
|
|
2722
|
-
},
|
|
2723
|
-
gridAutoRows: (el, value) => {
|
|
2724
|
-
el.style.gridAutoRows = String(value);
|
|
2725
|
-
},
|
|
2726
|
-
rowGap: (el, value) => {
|
|
2727
|
-
el.style.rowGap = typeof value === "number" ? `${value}px` : String(value);
|
|
2728
|
-
},
|
|
2729
|
-
columnGap: (el, value) => {
|
|
2730
|
-
el.style.columnGap = typeof value === "number" ? `${value}px` : String(value);
|
|
2731
|
-
},
|
|
2732
|
-
placeItems: (el, value) => {
|
|
2733
|
-
el.style.placeItems = String(value);
|
|
2734
|
-
},
|
|
2735
|
-
placeContent: (el, value) => {
|
|
2736
|
-
el.style.placeContent = String(value);
|
|
2737
|
-
},
|
|
2738
|
-
placeSelf: (el, value) => {
|
|
2739
|
-
el.style.placeSelf = String(value);
|
|
2740
|
-
},
|
|
2741
|
-
position: (el, value) => {
|
|
2742
|
-
el.style.position = String(value);
|
|
2743
|
-
},
|
|
2744
|
-
top: (el, value) => {
|
|
2745
|
-
el.style.top = typeof value === "number" ? `${value}px` : String(value);
|
|
2746
|
-
},
|
|
2747
|
-
right: (el, value) => {
|
|
2748
|
-
el.style.right = typeof value === "number" ? `${value}px` : String(value);
|
|
2749
|
-
},
|
|
2750
|
-
bottom: (el, value) => {
|
|
2751
|
-
el.style.bottom = typeof value === "number" ? `${value}px` : String(value);
|
|
2752
|
-
},
|
|
2753
|
-
left: (el, value) => {
|
|
2754
|
-
el.style.left = typeof value === "number" ? `${value}px` : String(value);
|
|
2755
|
-
},
|
|
2756
|
-
inset: (el, value) => {
|
|
2757
|
-
el.style.inset = typeof value === "number" ? `${value}px` : String(value);
|
|
2758
|
-
},
|
|
2759
|
-
zIndex: (el, value) => {
|
|
2760
|
-
el.style.zIndex = String(value);
|
|
2761
|
-
}
|
|
2762
|
-
};
|
|
2763
|
-
|
|
2764
|
-
// src/dom/applicators/background.ts
|
|
2765
|
-
var backgroundHandlers = {
|
|
2766
|
-
backgroundImage: (el, value) => {
|
|
2767
|
-
el.style.backgroundImage = String(value);
|
|
2768
|
-
},
|
|
2769
|
-
backgroundSize: (el, value) => {
|
|
2770
|
-
el.style.backgroundSize = String(value);
|
|
2771
|
-
},
|
|
2772
|
-
backgroundPosition: (el, value) => {
|
|
2773
|
-
el.style.backgroundPosition = String(value);
|
|
2774
|
-
},
|
|
2775
|
-
backgroundRepeat: (el, value) => {
|
|
2776
|
-
el.style.backgroundRepeat = String(value);
|
|
2777
|
-
},
|
|
2778
|
-
backgroundAttachment: (el, value) => {
|
|
2779
|
-
el.style.backgroundAttachment = String(value);
|
|
2780
|
-
},
|
|
2781
|
-
backgroundClip: (el, value) => {
|
|
2782
|
-
el.style.backgroundClip = String(value);
|
|
2783
|
-
},
|
|
2784
|
-
backgroundOrigin: (el, value) => {
|
|
2785
|
-
el.style.backgroundOrigin = String(value);
|
|
2786
|
-
},
|
|
2787
|
-
linearGradient: (el, value) => {
|
|
2788
|
-
el.style.backgroundImage = `linear-gradient(${value})`;
|
|
2789
|
-
},
|
|
2790
|
-
radialGradient: (el, value) => {
|
|
2791
|
-
el.style.backgroundImage = `radial-gradient(${value})`;
|
|
2792
|
-
},
|
|
2793
|
-
conicGradient: (el, value) => {
|
|
2794
|
-
el.style.backgroundImage = `conic-gradient(${value})`;
|
|
2795
|
-
}
|
|
2796
|
-
};
|
|
2797
|
-
|
|
2798
|
-
// src/dom/applicators/display.ts
|
|
2799
|
-
var displayHandlers = {
|
|
2800
|
-
display: (el, value) => {
|
|
2801
|
-
el.style.display = String(value);
|
|
2802
|
-
},
|
|
2803
|
-
visibility: (el, value) => {
|
|
2804
|
-
el.style.visibility = String(value);
|
|
2805
|
-
},
|
|
2806
|
-
overflowX: (el, value) => {
|
|
2807
|
-
el.style.overflowX = String(value);
|
|
2808
|
-
},
|
|
2809
|
-
overflowY: (el, value) => {
|
|
2810
|
-
el.style.overflowY = String(value);
|
|
2811
|
-
},
|
|
2812
|
-
pointerEvents: (el, value) => {
|
|
2813
|
-
el.style.pointerEvents = String(value);
|
|
2814
|
-
},
|
|
2815
|
-
userSelect: (el, value) => {
|
|
2816
|
-
el.style.userSelect = String(value);
|
|
2817
|
-
},
|
|
2818
|
-
resize: (el, value) => {
|
|
2819
|
-
el.style.resize = String(value);
|
|
2820
|
-
},
|
|
2821
|
-
boxSizing: (el, value) => {
|
|
2822
|
-
el.style.boxSizing = String(value);
|
|
2823
|
-
},
|
|
2824
|
-
aspectRatio: (el, value) => {
|
|
2825
|
-
el.style.aspectRatio = String(value);
|
|
2826
|
-
},
|
|
2827
|
-
objectFit: (el, value) => {
|
|
2828
|
-
el.style.objectFit = String(value);
|
|
2829
|
-
},
|
|
2830
|
-
objectPosition: (el, value) => {
|
|
2831
|
-
el.style.objectPosition = String(value);
|
|
2832
|
-
}
|
|
2833
|
-
};
|
|
2834
|
-
|
|
2835
|
-
// src/dom/applicators/transition.ts
|
|
2836
|
-
var transitionHandlers = {
|
|
2837
|
-
transition: (el, value) => {
|
|
2838
|
-
el.style.transition = String(value);
|
|
2839
|
-
},
|
|
2840
|
-
transitionProperty: (el, value) => {
|
|
2841
|
-
el.style.transitionProperty = String(value);
|
|
2842
|
-
},
|
|
2843
|
-
transitionDuration: (el, value) => {
|
|
2844
|
-
el.style.transitionDuration = String(value);
|
|
2845
|
-
},
|
|
2846
|
-
transitionTimingFunction: (el, value) => {
|
|
2847
|
-
el.style.transitionTimingFunction = String(value);
|
|
2848
|
-
},
|
|
2849
|
-
transitionDelay: (el, value) => {
|
|
2850
|
-
el.style.transitionDelay = String(value);
|
|
2851
|
-
},
|
|
2852
|
-
animation: (el, value) => {
|
|
2853
|
-
el.style.animation = String(value);
|
|
2854
|
-
},
|
|
2855
|
-
animationName: (el, value) => {
|
|
2856
|
-
el.style.animationName = String(value);
|
|
2857
|
-
},
|
|
2858
|
-
animationDuration: (el, value) => {
|
|
2859
|
-
el.style.animationDuration = String(value);
|
|
2860
|
-
},
|
|
2861
|
-
animationTimingFunction: (el, value) => {
|
|
2862
|
-
el.style.animationTimingFunction = String(value);
|
|
2863
|
-
},
|
|
2864
|
-
animationDelay: (el, value) => {
|
|
2865
|
-
el.style.animationDelay = String(value);
|
|
2866
|
-
},
|
|
2867
|
-
animationIterationCount: (el, value) => {
|
|
2868
|
-
el.style.animationIterationCount = String(value);
|
|
2869
|
-
},
|
|
2870
|
-
animationDirection: (el, value) => {
|
|
2871
|
-
el.style.animationDirection = String(value);
|
|
2872
|
-
},
|
|
2873
|
-
animationFillMode: (el, value) => {
|
|
2874
|
-
el.style.animationFillMode = String(value);
|
|
2875
|
-
},
|
|
2876
|
-
animationPlayState: (el, value) => {
|
|
2877
|
-
el.style.animationPlayState = String(value);
|
|
2878
|
-
}
|
|
2879
|
-
};
|
|
2880
|
-
|
|
2881
|
-
// src/dom/applicators/index.ts
|
|
2882
|
-
var BREAKPOINTS = {
|
|
2883
|
-
sm: "640px",
|
|
2884
|
-
md: "768px",
|
|
2885
|
-
lg: "1024px",
|
|
2886
|
-
xl: "1280px",
|
|
2887
|
-
"2xl": "1536px"
|
|
2888
|
-
};
|
|
2889
|
-
var variantStyleSheet = null;
|
|
2890
|
-
var insertedRules = new Set;
|
|
2891
|
-
function getVariantStyleSheet() {
|
|
2892
|
-
if (!variantStyleSheet) {
|
|
2893
|
-
const style = document.createElement("style");
|
|
2894
|
-
style.id = "hypen-variants";
|
|
2895
|
-
document.head.appendChild(style);
|
|
2896
|
-
variantStyleSheet = style.sheet;
|
|
2897
|
-
}
|
|
2898
|
-
return variantStyleSheet;
|
|
2899
|
-
}
|
|
2900
|
-
function hashValue(value) {
|
|
2901
|
-
return String(value).replace(/[^a-zA-Z0-9]/g, "").slice(0, 8);
|
|
2902
|
-
}
|
|
2903
|
-
|
|
2904
|
-
class ApplicatorRegistry {
|
|
2905
|
-
handlers = new Map;
|
|
2906
|
-
elementState = new WeakMap;
|
|
2907
|
-
constructor() {
|
|
2908
|
-
this.registerDefaults();
|
|
2909
|
-
}
|
|
2910
|
-
register(name, handler) {
|
|
2911
|
-
this.handlers.set(name, handler);
|
|
2912
|
-
}
|
|
2913
|
-
apply(element, name, value) {
|
|
2914
|
-
const { handlerName, argKey, aggregate, fallbackName } = this.parseApplicatorName(name);
|
|
2915
|
-
const handler = this.handlers.get(handlerName);
|
|
2916
|
-
const state = this.getElementState(element);
|
|
2917
|
-
const previous = state.get(handlerName);
|
|
2918
|
-
if (aggregate && argKey !== null) {
|
|
2919
|
-
const merged = this.mergeAggregateState(previous, argKey, this.normalizeValue(value));
|
|
2920
|
-
state.set(handlerName, merged);
|
|
2921
|
-
if (handler) {
|
|
2922
|
-
handler(element, merged);
|
|
2923
|
-
} else {
|
|
2924
|
-
this.setStyleProperty(element, fallbackName, value);
|
|
2925
|
-
}
|
|
2926
|
-
return;
|
|
2927
|
-
}
|
|
2928
|
-
if (handler) {
|
|
2929
|
-
if (this.isEventApplicator(handlerName)) {
|
|
2930
|
-
const normalizedValue = this.normalizeEventValue(previous, value);
|
|
2931
|
-
state.set(handlerName, normalizedValue);
|
|
2932
|
-
handler(element, normalizedValue);
|
|
2933
|
-
} else {
|
|
2934
|
-
state.set(handlerName, value);
|
|
2935
|
-
handler(element, value);
|
|
2936
|
-
}
|
|
2937
|
-
} else {
|
|
2938
|
-
this.setStyleProperty(element, handlerName, value);
|
|
2939
|
-
}
|
|
2940
|
-
}
|
|
2941
|
-
parseApplicatorName(name) {
|
|
2942
|
-
const dotIndex = name.indexOf(".");
|
|
2943
|
-
if (dotIndex === -1) {
|
|
2944
|
-
return { handlerName: name, argKey: null, aggregate: false, fallbackName: name };
|
|
2945
|
-
}
|
|
2946
|
-
const baseName = name.substring(0, dotIndex);
|
|
2947
|
-
const argKey = name.substring(dotIndex + 1);
|
|
2948
|
-
if (this.handlers.has(baseName) && this.isEventApplicator(baseName)) {
|
|
2949
|
-
return { handlerName: baseName, argKey, aggregate: true, fallbackName: name };
|
|
2950
|
-
}
|
|
2951
|
-
if (/^\d+$/.test(argKey)) {
|
|
2952
|
-
return { handlerName: baseName, argKey: null, aggregate: false, fallbackName: baseName };
|
|
2953
|
-
}
|
|
2954
|
-
return { handlerName: name, argKey: null, aggregate: false, fallbackName: name };
|
|
2955
|
-
}
|
|
2956
|
-
getElementState(element) {
|
|
2957
|
-
let state = this.elementState.get(element);
|
|
2958
|
-
if (!state) {
|
|
2959
|
-
state = new Map;
|
|
2960
|
-
this.elementState.set(element, state);
|
|
2961
|
-
}
|
|
2962
|
-
return state;
|
|
2963
|
-
}
|
|
2964
|
-
mergeAggregateState(previous, argKey, value) {
|
|
2965
|
-
const base = this.cloneAggregateState(previous);
|
|
2966
|
-
if (value === undefined) {
|
|
2967
|
-
delete base[argKey];
|
|
2968
|
-
} else {
|
|
2969
|
-
base[argKey] = value;
|
|
2970
|
-
}
|
|
2971
|
-
return base;
|
|
2972
|
-
}
|
|
2973
|
-
cloneAggregateState(previous) {
|
|
2974
|
-
if (previous && typeof previous === "object" && !Array.isArray(previous)) {
|
|
2975
|
-
return { ...previous };
|
|
2976
|
-
}
|
|
2977
|
-
if (typeof previous === "string") {
|
|
2978
|
-
return { "0": previous };
|
|
2979
|
-
}
|
|
2980
|
-
return {};
|
|
2981
|
-
}
|
|
2982
|
-
normalizeEventValue(previous, value) {
|
|
2983
|
-
const normalizedInput = this.normalizeValue(value);
|
|
2984
|
-
const base = this.cloneAggregateState(previous);
|
|
2985
|
-
if (normalizedInput && typeof normalizedInput === "object" && !Array.isArray(normalizedInput)) {
|
|
2986
|
-
const next = { ...base, ...normalizedInput };
|
|
2987
|
-
if (!Object.prototype.hasOwnProperty.call(next, "0") && base["0"] !== undefined) {
|
|
2988
|
-
next["0"] = base["0"];
|
|
2989
|
-
}
|
|
2990
|
-
return next;
|
|
2991
|
-
}
|
|
2992
|
-
if (normalizedInput !== undefined) {
|
|
2993
|
-
base["0"] = normalizedInput;
|
|
2994
|
-
}
|
|
2995
|
-
return base;
|
|
2996
|
-
}
|
|
2997
|
-
normalizeValue(value) {
|
|
2998
|
-
if (value instanceof Map) {
|
|
2999
|
-
const obj = {};
|
|
3000
|
-
for (const [key, val] of value.entries()) {
|
|
3001
|
-
obj[key] = this.normalizeValue(val);
|
|
3002
|
-
}
|
|
3003
|
-
return obj;
|
|
3004
|
-
}
|
|
3005
|
-
if (Array.isArray(value)) {
|
|
3006
|
-
return value.map((item) => this.normalizeValue(item));
|
|
3007
|
-
}
|
|
3008
|
-
if (value && typeof value === "object") {
|
|
3009
|
-
const obj = {};
|
|
3010
|
-
for (const [key, val] of Object.entries(value)) {
|
|
3011
|
-
obj[key] = this.normalizeValue(val);
|
|
3012
|
-
}
|
|
3013
|
-
return obj;
|
|
3014
|
-
}
|
|
3015
|
-
return value;
|
|
3016
|
-
}
|
|
3017
|
-
isEventApplicator(name) {
|
|
3018
|
-
return /^on[A-Z]/.test(name);
|
|
3019
|
-
}
|
|
3020
|
-
applyAll(element, applicators) {
|
|
3021
|
-
const grouped = new Map;
|
|
3022
|
-
for (const [name, value] of Object.entries(applicators)) {
|
|
3023
|
-
const dotIndex = name.indexOf(".");
|
|
3024
|
-
const baseName = dotIndex !== -1 ? name.substring(0, dotIndex) : name;
|
|
3025
|
-
const argKey = dotIndex !== -1 ? name.substring(dotIndex + 1) : null;
|
|
3026
|
-
if (!grouped.has(baseName)) {
|
|
3027
|
-
grouped.set(baseName, {});
|
|
3028
|
-
}
|
|
3029
|
-
const args = grouped.get(baseName);
|
|
3030
|
-
if (argKey !== null) {
|
|
3031
|
-
args[argKey] = value;
|
|
3032
|
-
} else {
|
|
3033
|
-
args["__value"] = value;
|
|
3034
|
-
}
|
|
3035
|
-
}
|
|
3036
|
-
for (const [baseName, args] of grouped.entries()) {
|
|
3037
|
-
if (Object.keys(args).length === 1) {
|
|
3038
|
-
if ("__value" in args) {
|
|
3039
|
-
this.apply(element, baseName, args["__value"]);
|
|
3040
|
-
} else if ("0" in args) {
|
|
3041
|
-
this.apply(element, baseName, args["0"]);
|
|
3042
|
-
} else {
|
|
3043
|
-
this.apply(element, baseName, args);
|
|
227
|
+
// Wait a tick for module instance to initialize and fetch data
|
|
228
|
+
await new Promise((resolve) => setTimeout(resolve, 50));
|
|
229
|
+
// Get the route element's node ID from the renderer
|
|
230
|
+
const routeNodeId = routeElement.dataset.hypenId;
|
|
231
|
+
if (!routeNodeId) {
|
|
232
|
+
throw new Error(`Route element is missing data-hypen-id attribute`);
|
|
3044
233
|
}
|
|
3045
|
-
|
|
3046
|
-
this.
|
|
3047
|
-
|
|
234
|
+
// Get the current merged state
|
|
235
|
+
const mergedState = this.getMergedState();
|
|
236
|
+
// Render into the Route element
|
|
237
|
+
this.engine.renderInto(template, routeNodeId, mergedState);
|
|
238
|
+
// Ensure freshly created text nodes are interpolated with current state
|
|
239
|
+
this.renderer.updateState(mergedState);
|
|
3048
240
|
}
|
|
3049
|
-
|
|
3050
|
-
|
|
3051
|
-
|
|
3052
|
-
|
|
3053
|
-
|
|
3054
|
-
|
|
3055
|
-
|
|
3056
|
-
|
|
3057
|
-
|
|
3058
|
-
const cssName2 = this.toKebabCase(prop);
|
|
3059
|
-
const cssValue = this.formatCssValue(cssName2, value);
|
|
3060
|
-
const className = `hypen-${cssName2.replace(/[^a-zA-Z0-9-]/g, "")}-${breakpoint}-${hashValue(value)}`;
|
|
3061
|
-
const ruleKey = `${className}:${cssValue}`;
|
|
3062
|
-
if (!insertedRules.has(ruleKey)) {
|
|
3063
|
-
const sheet = getVariantStyleSheet();
|
|
3064
|
-
sheet.insertRule(`@media (min-width: ${minWidth}) { .${className} { ${cssName2}: ${cssValue}; } }`, sheet.cssRules.length);
|
|
3065
|
-
insertedRules.add(ruleKey);
|
|
241
|
+
/**
|
|
242
|
+
* Extract module ID from component name or .id() applicator
|
|
243
|
+
*/
|
|
244
|
+
extractModuleId(componentName, template) {
|
|
245
|
+
// Look for .id("CustomName") or .id('CustomName') in the template
|
|
246
|
+
const idMatch = template.match(/\.id\(["']([^"']+)["']\)/);
|
|
247
|
+
const matchedId = idMatch?.[1];
|
|
248
|
+
if (matchedId) {
|
|
249
|
+
return matchedId;
|
|
3066
250
|
}
|
|
3067
|
-
|
|
3068
|
-
|
|
3069
|
-
|
|
3070
|
-
|
|
3071
|
-
|
|
3072
|
-
|
|
3073
|
-
|
|
3074
|
-
|
|
3075
|
-
|
|
3076
|
-
|
|
3077
|
-
|
|
3078
|
-
|
|
3079
|
-
|
|
3080
|
-
|
|
3081
|
-
|
|
3082
|
-
|
|
3083
|
-
|
|
251
|
+
// Default to component name
|
|
252
|
+
return componentName;
|
|
253
|
+
}
|
|
254
|
+
/**
|
|
255
|
+
* Create module instances for all components that have state
|
|
256
|
+
*/
|
|
257
|
+
createNestedModuleInstances() {
|
|
258
|
+
// Create built-in Router module instance
|
|
259
|
+
if (Router && !this.moduleInstances.has("Router")) {
|
|
260
|
+
const routerInstance = new HypenModuleInstance(this.engine, Router, this.router, this.globalContext);
|
|
261
|
+
this.globalContext.registerModule("Router", routerInstance);
|
|
262
|
+
this.moduleInstances.set("Router", routerInstance);
|
|
263
|
+
routerInstance.onStateChange(() => {
|
|
264
|
+
const mergedState = this.getMergedState();
|
|
265
|
+
log.debug("Router state changed:", mergedState);
|
|
266
|
+
this.renderer.updateState(mergedState);
|
|
267
|
+
});
|
|
3084
268
|
}
|
|
3085
|
-
|
|
3086
|
-
|
|
3087
|
-
|
|
3088
|
-
|
|
3089
|
-
|
|
3090
|
-
|
|
3091
|
-
|
|
3092
|
-
|
|
3093
|
-
|
|
3094
|
-
|
|
3095
|
-
|
|
3096
|
-
|
|
3097
|
-
|
|
3098
|
-
|
|
3099
|
-
|
|
3100
|
-
|
|
3101
|
-
|
|
3102
|
-
|
|
3103
|
-
|
|
3104
|
-
|
|
3105
|
-
|
|
3106
|
-
|
|
3107
|
-
"flex",
|
|
3108
|
-
"flex-grow",
|
|
3109
|
-
"flex-shrink",
|
|
3110
|
-
"order"
|
|
3111
|
-
];
|
|
3112
|
-
return !unitless.includes(prop);
|
|
3113
|
-
}
|
|
3114
|
-
registerDefaults() {
|
|
3115
|
-
this.register("padding", paddingHandler);
|
|
3116
|
-
this.register("paddingTop", paddingTopHandler);
|
|
3117
|
-
this.register("paddingBottom", paddingBottomHandler);
|
|
3118
|
-
this.register("paddingLeft", paddingLeftHandler);
|
|
3119
|
-
this.register("paddingRight", paddingRightHandler);
|
|
3120
|
-
this.register("paddingHorizontal", paddingHorizontalHandler);
|
|
3121
|
-
this.register("paddingVertical", paddingVerticalHandler);
|
|
3122
|
-
this.register("margin", marginHandler);
|
|
3123
|
-
this.register("marginTop", marginTopHandler);
|
|
3124
|
-
this.register("marginBottom", marginBottomHandler);
|
|
3125
|
-
this.register("marginLeft", marginLeftHandler);
|
|
3126
|
-
this.register("marginRight", marginRightHandler);
|
|
3127
|
-
this.register("marginHorizontal", marginHorizontalHandler);
|
|
3128
|
-
this.register("marginVertical", marginVerticalHandler);
|
|
3129
|
-
for (const [name, handler] of Object.entries(colorHandlers)) {
|
|
3130
|
-
this.register(name, handler);
|
|
3131
|
-
}
|
|
3132
|
-
for (const [name, handler] of Object.entries(borderHandlers)) {
|
|
3133
|
-
this.register(name, handler);
|
|
3134
|
-
}
|
|
3135
|
-
for (const [name, handler] of Object.entries(sizeHandlers)) {
|
|
3136
|
-
this.register(name, handler);
|
|
3137
|
-
}
|
|
3138
|
-
for (const [name, handler] of Object.entries(fontHandlers)) {
|
|
3139
|
-
this.register(name, handler);
|
|
3140
|
-
}
|
|
3141
|
-
for (const [name, handler] of Object.entries(layoutHandlers)) {
|
|
3142
|
-
this.register(name, handler);
|
|
3143
|
-
}
|
|
3144
|
-
for (const [name, handler] of Object.entries(eventHandlers)) {
|
|
3145
|
-
this.register(name, handler);
|
|
3146
|
-
}
|
|
3147
|
-
for (const [name, handler] of Object.entries(typographyHandlers)) {
|
|
3148
|
-
this.register(name, handler);
|
|
3149
|
-
}
|
|
3150
|
-
for (const [name, handler] of Object.entries(transformHandlers)) {
|
|
3151
|
-
this.register(name, handler);
|
|
3152
|
-
}
|
|
3153
|
-
for (const [name, handler] of Object.entries(effectsHandlers)) {
|
|
3154
|
-
this.register(name, handler);
|
|
3155
|
-
}
|
|
3156
|
-
for (const [name, handler] of Object.entries(advancedLayoutHandlers)) {
|
|
3157
|
-
this.register(name, handler);
|
|
3158
|
-
}
|
|
3159
|
-
for (const [name, handler] of Object.entries(backgroundHandlers)) {
|
|
3160
|
-
this.register(name, handler);
|
|
3161
|
-
}
|
|
3162
|
-
for (const [name, handler] of Object.entries(displayHandlers)) {
|
|
3163
|
-
this.register(name, handler);
|
|
3164
|
-
}
|
|
3165
|
-
for (const [name, handler] of Object.entries(transitionHandlers)) {
|
|
3166
|
-
this.register(name, handler);
|
|
3167
|
-
}
|
|
3168
|
-
}
|
|
3169
|
-
}
|
|
3170
|
-
|
|
3171
|
-
// src/dom/canvas/index.ts
|
|
3172
|
-
var canvasHandler = {
|
|
3173
|
-
create() {
|
|
3174
|
-
const el = document.createElement("canvas");
|
|
3175
|
-
el.dataset.hypenType = "canvas";
|
|
3176
|
-
return el;
|
|
3177
|
-
},
|
|
3178
|
-
applyProps(el, props) {
|
|
3179
|
-
const canvas = el;
|
|
3180
|
-
if (props.width !== undefined) {
|
|
3181
|
-
canvas.width = Number(props.width);
|
|
3182
|
-
}
|
|
3183
|
-
if (props.height !== undefined) {
|
|
3184
|
-
canvas.height = Number(props.height);
|
|
3185
|
-
}
|
|
3186
|
-
}
|
|
3187
|
-
};
|
|
3188
|
-
var canvasApplicators = {
|
|
3189
|
-
fillStyle: (el, value) => {
|
|
3190
|
-
const canvas = el;
|
|
3191
|
-
const ctx = canvas.getContext("2d");
|
|
3192
|
-
if (ctx) {
|
|
3193
|
-
ctx.fillStyle = String(value);
|
|
3194
|
-
}
|
|
3195
|
-
},
|
|
3196
|
-
strokeStyle: (el, value) => {
|
|
3197
|
-
const canvas = el;
|
|
3198
|
-
const ctx = canvas.getContext("2d");
|
|
3199
|
-
if (ctx) {
|
|
3200
|
-
ctx.strokeStyle = String(value);
|
|
3201
|
-
}
|
|
3202
|
-
},
|
|
3203
|
-
lineWidth: (el, value) => {
|
|
3204
|
-
const canvas = el;
|
|
3205
|
-
const ctx = canvas.getContext("2d");
|
|
3206
|
-
if (ctx) {
|
|
3207
|
-
ctx.lineWidth = Number(value);
|
|
3208
|
-
}
|
|
3209
|
-
}
|
|
3210
|
-
};
|
|
3211
|
-
|
|
3212
|
-
// src/dom/debug.ts
|
|
3213
|
-
import { frameworkLoggers as frameworkLoggers4 } from "@hypen-space/core/logger";
|
|
3214
|
-
var log4 = frameworkLoggers4.debug;
|
|
3215
|
-
var defaultDebugConfig = {
|
|
3216
|
-
enabled: false,
|
|
3217
|
-
showHeatmap: true,
|
|
3218
|
-
heatmapIncrement: 5,
|
|
3219
|
-
maxOpacity: 0.8,
|
|
3220
|
-
fadeOutDuration: 2000
|
|
3221
|
-
};
|
|
3222
|
-
|
|
3223
|
-
class RerenderTracker {
|
|
3224
|
-
renderCounts = new Map;
|
|
3225
|
-
overlays = new Map;
|
|
3226
|
-
config;
|
|
3227
|
-
constructor(config = defaultDebugConfig) {
|
|
3228
|
-
this.config = config;
|
|
3229
|
-
}
|
|
3230
|
-
setConfig(config) {
|
|
3231
|
-
this.config = { ...this.config, ...config };
|
|
3232
|
-
if (!this.config.enabled) {
|
|
3233
|
-
this.cleanup();
|
|
3234
|
-
}
|
|
3235
|
-
}
|
|
3236
|
-
trackRerender(id, element, patchType) {
|
|
3237
|
-
if (!this.config.enabled || !this.config.showHeatmap) {
|
|
3238
|
-
return;
|
|
3239
|
-
}
|
|
3240
|
-
log4.debug(`Tracking re-render: ${id} - ${patchType}`);
|
|
3241
|
-
const currentCount = this.renderCounts.get(id) || 0;
|
|
3242
|
-
const newCount = currentCount + 1;
|
|
3243
|
-
this.renderCounts.set(id, newCount);
|
|
3244
|
-
this.updateHeatmap(id, element, newCount, patchType);
|
|
3245
|
-
}
|
|
3246
|
-
updateHeatmap(id, element, renderCount, patchType) {
|
|
3247
|
-
const opacity = Math.min(renderCount * this.config.heatmapIncrement / 100, this.config.maxOpacity);
|
|
3248
|
-
log4.debug(`Updating heatmap for ${id}, count: ${renderCount}, opacity: ${opacity}`);
|
|
3249
|
-
const isInline = window.getComputedStyle(element).display.includes("inline");
|
|
3250
|
-
if (isInline || element.tagName === "SPAN") {
|
|
3251
|
-
if (!element.dataset.hypenDebugOriginalBg) {
|
|
3252
|
-
element.dataset.hypenDebugOriginalBg = element.style.backgroundColor || "";
|
|
3253
|
-
element.dataset.hypenDebugOriginalOutline = element.style.outline || "";
|
|
3254
|
-
element.dataset.hypenDebugOriginalPosition = element.style.position || "";
|
|
3255
|
-
}
|
|
3256
|
-
element.style.backgroundColor = `rgba(255, 0, 0, ${Math.max(opacity, 0.15)})`;
|
|
3257
|
-
element.style.outline = `2px solid rgba(255, 0, 0, ${Math.max(opacity + 0.2, 0.3)})`;
|
|
3258
|
-
element.style.outlineOffset = "2px";
|
|
3259
|
-
element.style.position = "relative";
|
|
3260
|
-
element.setAttribute("data-hypen-renders", `${renderCount}× ${patchType}`);
|
|
3261
|
-
if (!document.getElementById("hypen-debug-styles")) {
|
|
3262
|
-
const style = document.createElement("style");
|
|
3263
|
-
style.id = "hypen-debug-styles";
|
|
3264
|
-
style.textContent = `
|
|
3265
|
-
[data-hypen-renders]::before {
|
|
3266
|
-
content: attr(data-hypen-renders);
|
|
3267
|
-
position: absolute;
|
|
3268
|
-
top: -18px;
|
|
3269
|
-
left: 0;
|
|
3270
|
-
background: rgba(255, 0, 0, 0.9);
|
|
3271
|
-
color: white;
|
|
3272
|
-
padding: 2px 6px;
|
|
3273
|
-
font-size: 10px;
|
|
3274
|
-
font-family: 'Courier New', monospace;
|
|
3275
|
-
font-weight: bold;
|
|
3276
|
-
border-radius: 3px;
|
|
3277
|
-
z-index: 999999;
|
|
3278
|
-
pointer-events: none;
|
|
3279
|
-
white-space: nowrap;
|
|
3280
|
-
text-shadow: none;
|
|
3281
|
-
}
|
|
3282
|
-
`;
|
|
3283
|
-
document.head.appendChild(style);
|
|
3284
|
-
}
|
|
3285
|
-
this.overlays.set(id, element);
|
|
3286
|
-
if (this.config.fadeOutDuration > 0) {
|
|
3287
|
-
setTimeout(() => {
|
|
3288
|
-
const originalBg = element.dataset.hypenDebugOriginalBg || "";
|
|
3289
|
-
const originalOutline = element.dataset.hypenDebugOriginalOutline || "";
|
|
3290
|
-
element.style.backgroundColor = originalBg;
|
|
3291
|
-
element.style.outline = originalOutline;
|
|
3292
|
-
element.style.opacity = "1";
|
|
3293
|
-
}, this.config.fadeOutDuration);
|
|
3294
|
-
}
|
|
3295
|
-
} else {
|
|
3296
|
-
let overlay = this.overlays.get(id);
|
|
3297
|
-
if (!overlay) {
|
|
3298
|
-
overlay = document.createElement("div");
|
|
3299
|
-
overlay.className = "hypen-debug-overlay";
|
|
3300
|
-
overlay.style.cssText = `
|
|
3301
|
-
position: absolute;
|
|
3302
|
-
top: 0;
|
|
3303
|
-
left: 0;
|
|
3304
|
-
right: 0;
|
|
3305
|
-
bottom: 0;
|
|
3306
|
-
pointer-events: none;
|
|
3307
|
-
z-index: 999999 !important;
|
|
3308
|
-
transition: opacity ${this.config.fadeOutDuration}ms ease-out;
|
|
3309
|
-
border: 2px solid rgba(255, 0, 0, 0.7) !important;
|
|
3310
|
-
box-sizing: border-box;
|
|
3311
|
-
font-size: 11px;
|
|
3312
|
-
color: white;
|
|
3313
|
-
text-shadow: 0 0 3px black, 0 0 5px black;
|
|
3314
|
-
padding: 4px;
|
|
3315
|
-
font-family: 'Courier New', monospace;
|
|
3316
|
-
font-weight: bold;
|
|
3317
|
-
display: block !important;
|
|
3318
|
-
visibility: visible !important;
|
|
3319
|
-
`;
|
|
3320
|
-
const currentPosition = window.getComputedStyle(element).position;
|
|
3321
|
-
if (currentPosition === "static") {
|
|
3322
|
-
element.style.position = "relative";
|
|
269
|
+
// Get all registered components
|
|
270
|
+
const componentNames = componentLoader.getNames();
|
|
271
|
+
for (const name of componentNames) {
|
|
272
|
+
// Skip if already created
|
|
273
|
+
if (this.moduleInstances.has(name)) {
|
|
274
|
+
continue;
|
|
275
|
+
}
|
|
276
|
+
const comp = componentLoader.get(name);
|
|
277
|
+
if (!comp || !comp.module) {
|
|
278
|
+
continue;
|
|
279
|
+
}
|
|
280
|
+
// Create module instance
|
|
281
|
+
log.debug(`Creating nested module instance for: ${name}`);
|
|
282
|
+
const moduleInstance = new HypenModuleInstance(this.engine, comp.module, this.router, this.globalContext);
|
|
283
|
+
this.globalContext.registerModule(name, moduleInstance);
|
|
284
|
+
this.moduleInstances.set(name, moduleInstance);
|
|
285
|
+
// Connect state changes to renderer
|
|
286
|
+
moduleInstance.onStateChange(() => {
|
|
287
|
+
const mergedState = this.getMergedState();
|
|
288
|
+
log.debug(`Nested component ${name} state changed:`, mergedState);
|
|
289
|
+
this.renderer.updateState(mergedState);
|
|
290
|
+
});
|
|
3323
291
|
}
|
|
3324
|
-
element.appendChild(overlay);
|
|
3325
|
-
this.overlays.set(id, overlay);
|
|
3326
|
-
}
|
|
3327
|
-
overlay.style.backgroundColor = `rgba(255, 0, 0, ${Math.max(opacity, 0.15)})`;
|
|
3328
|
-
overlay.style.opacity = "1";
|
|
3329
|
-
overlay.textContent = `${renderCount}× ${patchType}`;
|
|
3330
|
-
if (this.config.fadeOutDuration > 0) {
|
|
3331
|
-
setTimeout(() => {
|
|
3332
|
-
if (overlay) {
|
|
3333
|
-
overlay.style.opacity = "0.2";
|
|
3334
|
-
}
|
|
3335
|
-
}, this.config.fadeOutDuration);
|
|
3336
|
-
}
|
|
3337
|
-
}
|
|
3338
|
-
}
|
|
3339
|
-
reset(id) {
|
|
3340
|
-
this.renderCounts.delete(id);
|
|
3341
|
-
const overlay = this.overlays.get(id);
|
|
3342
|
-
if (overlay) {
|
|
3343
|
-
overlay.remove();
|
|
3344
|
-
this.overlays.delete(id);
|
|
3345
|
-
}
|
|
3346
|
-
}
|
|
3347
|
-
resetAll() {
|
|
3348
|
-
this.renderCounts.clear();
|
|
3349
|
-
for (const overlay of this.overlays.values()) {
|
|
3350
|
-
overlay.remove();
|
|
3351
|
-
}
|
|
3352
|
-
this.overlays.clear();
|
|
3353
|
-
}
|
|
3354
|
-
getRenderCount(id) {
|
|
3355
|
-
return this.renderCounts.get(id) || 0;
|
|
3356
|
-
}
|
|
3357
|
-
cleanup() {
|
|
3358
|
-
for (const overlay of this.overlays.values()) {
|
|
3359
|
-
overlay.remove();
|
|
3360
292
|
}
|
|
3361
|
-
|
|
3362
|
-
|
|
3363
|
-
|
|
3364
|
-
|
|
3365
|
-
|
|
3366
|
-
|
|
3367
|
-
|
|
3368
|
-
|
|
3369
|
-
|
|
3370
|
-
avgRerenders: Math.round(avgRerenders * 100) / 100
|
|
3371
|
-
};
|
|
3372
|
-
}
|
|
3373
|
-
}
|
|
3374
|
-
|
|
3375
|
-
// src/dom/renderer.ts
|
|
3376
|
-
import { frameworkLoggers as frameworkLoggers5 } from "@hypen-space/core/logger";
|
|
3377
|
-
var log5 = frameworkLoggers5.renderer;
|
|
3378
|
-
|
|
3379
|
-
class DOMRenderer {
|
|
3380
|
-
container;
|
|
3381
|
-
nodes = new Map;
|
|
3382
|
-
rootId = null;
|
|
3383
|
-
components;
|
|
3384
|
-
applicators;
|
|
3385
|
-
engine;
|
|
3386
|
-
currentState = {};
|
|
3387
|
-
router = null;
|
|
3388
|
-
globalContext = null;
|
|
3389
|
-
componentInstances = new Map;
|
|
3390
|
-
debugTracker;
|
|
3391
|
-
constructor(container, engine, debugConfig) {
|
|
3392
|
-
this.container = container;
|
|
3393
|
-
this.engine = engine;
|
|
3394
|
-
this.components = new ComponentRegistry;
|
|
3395
|
-
this.applicators = new ApplicatorRegistry;
|
|
3396
|
-
this.debugTracker = new RerenderTracker({ ...defaultDebugConfig, ...debugConfig });
|
|
3397
|
-
this.components.register("canvas", canvasHandler);
|
|
3398
|
-
for (const [name, handler] of Object.entries(canvasApplicators)) {
|
|
3399
|
-
this.applicators.register(name, handler);
|
|
3400
|
-
}
|
|
3401
|
-
}
|
|
3402
|
-
setContext(router, globalContext) {
|
|
3403
|
-
this.router = router;
|
|
3404
|
-
this.globalContext = globalContext;
|
|
3405
|
-
}
|
|
3406
|
-
applyPatches(patches) {
|
|
3407
|
-
for (const patch of patches) {
|
|
3408
|
-
this.applyPatch(patch);
|
|
3409
|
-
}
|
|
3410
|
-
}
|
|
3411
|
-
updateState(state) {
|
|
3412
|
-
log5.debug("Updating state:", state);
|
|
3413
|
-
this.currentState = state;
|
|
3414
|
-
this.interpolateAllText();
|
|
3415
|
-
}
|
|
3416
|
-
mergeComponentState(componentState) {
|
|
3417
|
-
this.currentState = { ...this.currentState, ...componentState };
|
|
3418
|
-
log5.debug("Merged state:", this.currentState);
|
|
3419
|
-
this.interpolateAllText();
|
|
3420
|
-
}
|
|
3421
|
-
interpolateAllText() {
|
|
3422
|
-
for (const [id, element] of this.nodes.entries()) {
|
|
3423
|
-
if (element.dataset.hypenType === "text" && element.dataset.textTemplate) {
|
|
3424
|
-
const template = element.dataset.textTemplate;
|
|
3425
|
-
const interpolated = this.interpolateText(template, this.currentState);
|
|
3426
|
-
const currentText = element.textContent;
|
|
3427
|
-
if (currentText !== interpolated) {
|
|
3428
|
-
this.debugTracker.trackRerender(id, element, "interpolate");
|
|
293
|
+
/**
|
|
294
|
+
* Get merged state from all module instances
|
|
295
|
+
*/
|
|
296
|
+
getMergedState() {
|
|
297
|
+
const merged = {};
|
|
298
|
+
// Include main module state
|
|
299
|
+
if (this.moduleInstance) {
|
|
300
|
+
const mainState = this.moduleInstance.getState();
|
|
301
|
+
Object.assign(merged, mainState);
|
|
3429
302
|
}
|
|
3430
|
-
|
|
3431
|
-
|
|
3432
|
-
|
|
3433
|
-
|
|
3434
|
-
|
|
3435
|
-
|
|
3436
|
-
|
|
3437
|
-
|
|
3438
|
-
|
|
3439
|
-
|
|
3440
|
-
|
|
3441
|
-
|
|
3442
|
-
|
|
3443
|
-
|
|
3444
|
-
|
|
3445
|
-
|
|
3446
|
-
|
|
3447
|
-
|
|
3448
|
-
|
|
3449
|
-
|
|
3450
|
-
|
|
3451
|
-
|
|
3452
|
-
|
|
3453
|
-
|
|
3454
|
-
|
|
3455
|
-
|
|
3456
|
-
|
|
3457
|
-
|
|
3458
|
-
|
|
3459
|
-
|
|
3460
|
-
this.
|
|
3461
|
-
|
|
3462
|
-
|
|
3463
|
-
|
|
3464
|
-
|
|
3465
|
-
|
|
3466
|
-
|
|
3467
|
-
|
|
3468
|
-
|
|
3469
|
-
|
|
3470
|
-
|
|
3471
|
-
|
|
3472
|
-
|
|
3473
|
-
|
|
3474
|
-
|
|
3475
|
-
|
|
3476
|
-
|
|
3477
|
-
|
|
3478
|
-
|
|
3479
|
-
|
|
3480
|
-
|
|
3481
|
-
|
|
3482
|
-
|
|
3483
|
-
|
|
3484
|
-
|
|
3485
|
-
|
|
3486
|
-
|
|
3487
|
-
|
|
3488
|
-
|
|
3489
|
-
|
|
3490
|
-
element.dataset.hypenId = id;
|
|
3491
|
-
setEngine(element, this.engine);
|
|
3492
|
-
this.applicators.applyAll(element, propsObj);
|
|
3493
|
-
this.nodes.set(id, element);
|
|
3494
|
-
this.debugTracker.trackRerender(id, element, `create:${elementType}`);
|
|
3495
|
-
if (!this.rootId) {
|
|
3496
|
-
this.rootId = id;
|
|
3497
|
-
if (!this.container.contains(element)) {
|
|
3498
|
-
this.container.appendChild(element);
|
|
3499
|
-
}
|
|
3500
|
-
}
|
|
3501
|
-
}
|
|
3502
|
-
onSetProp(id, name, value) {
|
|
3503
|
-
const element = this.nodes.get(id);
|
|
3504
|
-
if (!element)
|
|
3505
|
-
return;
|
|
3506
|
-
this.debugTracker.trackRerender(id, element, `setProp:${name}`);
|
|
3507
|
-
if (name === "0" || name === "text") {
|
|
3508
|
-
const elementType = element.dataset.hypenType;
|
|
3509
|
-
if (elementType === "input") {
|
|
3510
|
-
const inputEl = element;
|
|
3511
|
-
inputEl.value = String(value);
|
|
3512
|
-
log5.debug(`Updated input value: "${value}"`);
|
|
3513
|
-
return;
|
|
3514
|
-
}
|
|
3515
|
-
const nextText = String(value);
|
|
3516
|
-
element.textContent = nextText;
|
|
3517
|
-
const currentTemplate = element.dataset.textTemplate;
|
|
3518
|
-
const nextLooksLikeTemplate = nextText.includes("${");
|
|
3519
|
-
const currentLooksLikeTemplate = typeof currentTemplate === "string" && currentTemplate.includes("${");
|
|
3520
|
-
if (nextLooksLikeTemplate) {
|
|
3521
|
-
element.dataset.textTemplate = nextText;
|
|
3522
|
-
} else if (currentTemplate === undefined) {
|
|
3523
|
-
element.dataset.textTemplate = nextText;
|
|
3524
|
-
} else if (!currentLooksLikeTemplate) {
|
|
3525
|
-
element.dataset.textTemplate = nextText;
|
|
3526
|
-
}
|
|
3527
|
-
log5.debug(`Updated text content: "${value}"`);
|
|
3528
|
-
return;
|
|
3529
|
-
}
|
|
3530
|
-
this.applicators.apply(element, name, value);
|
|
3531
|
-
}
|
|
3532
|
-
onRemoveProp(id, name) {
|
|
3533
|
-
const element = this.nodes.get(id);
|
|
3534
|
-
if (!element)
|
|
3535
|
-
return;
|
|
3536
|
-
this.debugTracker.trackRerender(id, element, `removeProp:${name}`);
|
|
3537
|
-
this.applicators.apply(element, name, undefined);
|
|
3538
|
-
}
|
|
3539
|
-
onSetText(id, text) {
|
|
3540
|
-
const element = this.nodes.get(id);
|
|
3541
|
-
if (!element)
|
|
3542
|
-
return;
|
|
3543
|
-
this.debugTracker.trackRerender(id, element, "setText");
|
|
3544
|
-
element.textContent = text;
|
|
3545
|
-
}
|
|
3546
|
-
onInsert(parentId, id, beforeId) {
|
|
3547
|
-
const parent = parentId === "root" ? this.container : this.nodes.get(parentId);
|
|
3548
|
-
const child = this.nodes.get(id);
|
|
3549
|
-
log5.debug(`Inserting ${id} into ${parentId}`, {
|
|
3550
|
-
parent: parent ? `${parent.tagName}#${parent.id || "no-id"}` : "null",
|
|
3551
|
-
child: child ? `${child.tagName}#${child.id || "no-id"}` : "null",
|
|
3552
|
-
childText: child?.textContent?.substring(0, 20)
|
|
3553
|
-
});
|
|
3554
|
-
if (!parent || !child)
|
|
3555
|
-
return;
|
|
3556
|
-
if (parentId === "root") {
|
|
3557
|
-
this.rootId = id;
|
|
3558
|
-
}
|
|
3559
|
-
if (beforeId) {
|
|
3560
|
-
const before = this.nodes.get(beforeId);
|
|
3561
|
-
if (before && before.parentNode === parent) {
|
|
3562
|
-
parent.insertBefore(child, before);
|
|
3563
|
-
} else if (!parent.contains(child)) {
|
|
3564
|
-
parent.appendChild(child);
|
|
3565
|
-
}
|
|
3566
|
-
} else {
|
|
3567
|
-
if (!parent.contains(child)) {
|
|
3568
|
-
parent.appendChild(child);
|
|
3569
|
-
}
|
|
3570
|
-
}
|
|
3571
|
-
}
|
|
3572
|
-
onMove(parentId, id, beforeId) {
|
|
3573
|
-
this.onInsert(parentId, id, beforeId);
|
|
3574
|
-
}
|
|
3575
|
-
onRemove(id) {
|
|
3576
|
-
const element = this.nodes.get(id);
|
|
3577
|
-
if (!element)
|
|
3578
|
-
return;
|
|
3579
|
-
disposeHypenElement(element);
|
|
3580
|
-
if (element.parentNode) {
|
|
3581
|
-
element.parentNode.removeChild(element);
|
|
3582
|
-
}
|
|
3583
|
-
this.nodes.delete(id);
|
|
3584
|
-
if (this.rootId === id) {
|
|
3585
|
-
this.rootId = null;
|
|
3586
|
-
}
|
|
3587
|
-
}
|
|
3588
|
-
getNode(id) {
|
|
3589
|
-
return this.nodes.get(id);
|
|
3590
|
-
}
|
|
3591
|
-
clear() {
|
|
3592
|
-
for (const element of this.nodes.values()) {
|
|
3593
|
-
disposeHypenElement(element);
|
|
3594
|
-
}
|
|
3595
|
-
this.container.innerHTML = "";
|
|
3596
|
-
this.nodes.clear();
|
|
3597
|
-
this.rootId = null;
|
|
3598
|
-
}
|
|
3599
|
-
getComponentRegistry() {
|
|
3600
|
-
return this.components;
|
|
3601
|
-
}
|
|
3602
|
-
getApplicatorRegistry() {
|
|
3603
|
-
return this.applicators;
|
|
3604
|
-
}
|
|
3605
|
-
setDebugConfig(config) {
|
|
3606
|
-
this.debugTracker.setConfig(config);
|
|
3607
|
-
}
|
|
3608
|
-
resetDebugTracking() {
|
|
3609
|
-
this.debugTracker.resetAll();
|
|
3610
|
-
}
|
|
3611
|
-
getDebugStats() {
|
|
3612
|
-
return this.debugTracker.getStats();
|
|
3613
|
-
}
|
|
3614
|
-
}
|
|
3615
|
-
|
|
3616
|
-
// src/hypen.ts
|
|
3617
|
-
import { Engine } from "@hypen-space/core/engine/browser";
|
|
3618
|
-
import { HypenModuleInstance } from "@hypen-space/core/app";
|
|
3619
|
-
import { HypenRouter } from "@hypen-space/core/router";
|
|
3620
|
-
import { HypenGlobalContext } from "@hypen-space/core/context";
|
|
3621
|
-
import { componentLoader } from "@hypen-space/core/loader";
|
|
3622
|
-
import { Router, Route, Link } from "@hypen-space/core/components";
|
|
3623
|
-
import { frameworkLoggers as frameworkLoggers6, setDebugMode } from "@hypen-space/core/logger";
|
|
3624
|
-
var log6 = frameworkLoggers6.hypen;
|
|
3625
|
-
|
|
3626
|
-
class Hypen {
|
|
3627
|
-
engine = null;
|
|
3628
|
-
renderer = null;
|
|
3629
|
-
moduleInstance = null;
|
|
3630
|
-
container = null;
|
|
3631
|
-
config;
|
|
3632
|
-
router;
|
|
3633
|
-
globalContext;
|
|
3634
|
-
moduleInstances = new Map;
|
|
3635
|
-
constructor(config = {}) {
|
|
3636
|
-
this.config = {
|
|
3637
|
-
componentsDir: "./src/components",
|
|
3638
|
-
debug: false,
|
|
3639
|
-
...config
|
|
3640
|
-
};
|
|
3641
|
-
if (this.config.debug) {
|
|
3642
|
-
setDebugMode(true);
|
|
3643
|
-
}
|
|
3644
|
-
this.router = new HypenRouter;
|
|
3645
|
-
this.globalContext = new HypenGlobalContext;
|
|
3646
|
-
componentLoader.register("Router", Router, "");
|
|
3647
|
-
componentLoader.register("Route", Route, "");
|
|
3648
|
-
componentLoader.register("Link", Link, "");
|
|
3649
|
-
this.globalContext.__hypenEngine = this;
|
|
3650
|
-
}
|
|
3651
|
-
async init() {
|
|
3652
|
-
log6.debug("Initializing...");
|
|
3653
|
-
this.engine = new Engine;
|
|
3654
|
-
await this.engine.init({
|
|
3655
|
-
wasmUrl: this.config.wasmUrl,
|
|
3656
|
-
jsUrl: this.config.jsUrl
|
|
3657
|
-
});
|
|
3658
|
-
log6.debug("Engine initialized");
|
|
3659
|
-
}
|
|
3660
|
-
async loadComponents(componentsDir) {
|
|
3661
|
-
const dir = componentsDir || this.config.componentsDir;
|
|
3662
|
-
log6.debug(`Loading components from ${dir}...`);
|
|
3663
|
-
await componentLoader.loadFromComponentsDir(dir);
|
|
3664
|
-
log6.debug(`Loaded ${componentLoader.getNames().length} components`);
|
|
3665
|
-
}
|
|
3666
|
-
async render(componentName, containerSelector) {
|
|
3667
|
-
if (!this.engine) {
|
|
3668
|
-
throw new Error("[Hypen] Engine not initialized. Call init() first.");
|
|
3669
|
-
}
|
|
3670
|
-
if (typeof containerSelector === "string") {
|
|
3671
|
-
const element = document.querySelector(containerSelector);
|
|
3672
|
-
if (!element) {
|
|
3673
|
-
throw new Error(`[Hypen] Container not found: ${containerSelector}`);
|
|
3674
|
-
}
|
|
3675
|
-
this.container = element;
|
|
3676
|
-
} else {
|
|
3677
|
-
this.container = containerSelector;
|
|
3678
|
-
}
|
|
3679
|
-
const component = componentLoader.get(componentName);
|
|
3680
|
-
if (!component) {
|
|
3681
|
-
throw new Error(`[Hypen] Component "${componentName}" not found. Available: ${componentLoader.getNames().join(", ")}`);
|
|
3682
|
-
}
|
|
3683
|
-
log6.debug(`Rendering ${componentName} to`, this.container);
|
|
3684
|
-
this.renderer = new DOMRenderer(this.container, this.engine, {
|
|
3685
|
-
enabled: this.config.debugHeatmap || false,
|
|
3686
|
-
showHeatmap: this.config.debugHeatmap || false,
|
|
3687
|
-
heatmapIncrement: this.config.heatmapIncrement || 5,
|
|
3688
|
-
fadeOutDuration: this.config.heatmapFadeOut || 2000,
|
|
3689
|
-
maxOpacity: 0.8
|
|
3690
|
-
});
|
|
3691
|
-
this.engine.setRenderCallback((patches) => {
|
|
3692
|
-
log6.debug(`Applying ${patches.length} patches`);
|
|
3693
|
-
this.renderer.applyPatches(patches);
|
|
3694
|
-
});
|
|
3695
|
-
this.renderer.setContext(this.router, this.globalContext);
|
|
3696
|
-
const moduleId = this.extractModuleId(componentName, component.template);
|
|
3697
|
-
this.moduleInstance = new HypenModuleInstance(this.engine, component.module, this.router, this.globalContext);
|
|
3698
|
-
this.globalContext.registerModule(moduleId, this.moduleInstance);
|
|
3699
|
-
this.moduleInstances.set(moduleId, this.moduleInstance);
|
|
3700
|
-
this.moduleInstance.onStateChange(() => {
|
|
3701
|
-
const mergedState = this.getMergedState();
|
|
3702
|
-
log6.debug(`State changed, merged state:`, mergedState);
|
|
3703
|
-
this.renderer.updateState(mergedState);
|
|
3704
|
-
});
|
|
3705
|
-
this.setupComponentResolver();
|
|
3706
|
-
this.createNestedModuleInstances();
|
|
3707
|
-
this.engine.renderSource(component.template);
|
|
3708
|
-
this.renderer.updateState(this.getMergedState());
|
|
3709
|
-
log6.debug(`${componentName} rendered successfully`);
|
|
3710
|
-
}
|
|
3711
|
-
async unmount() {
|
|
3712
|
-
log6.debug("Unmounting...");
|
|
3713
|
-
if (this.moduleInstance) {
|
|
3714
|
-
await this.moduleInstance.destroy();
|
|
3715
|
-
this.moduleInstance = null;
|
|
3716
|
-
}
|
|
3717
|
-
if (this.container) {
|
|
3718
|
-
this.container.innerHTML = "";
|
|
3719
|
-
this.container = null;
|
|
3720
|
-
}
|
|
3721
|
-
this.renderer = null;
|
|
3722
|
-
log6.debug("Unmounted");
|
|
3723
|
-
}
|
|
3724
|
-
getModuleInstance() {
|
|
3725
|
-
return this.moduleInstance;
|
|
3726
|
-
}
|
|
3727
|
-
getState() {
|
|
3728
|
-
return this.moduleInstance?.getState() ?? null;
|
|
3729
|
-
}
|
|
3730
|
-
getRouter() {
|
|
3731
|
-
return this.router;
|
|
3732
|
-
}
|
|
3733
|
-
getGlobalContext() {
|
|
3734
|
-
return this.globalContext;
|
|
3735
|
-
}
|
|
3736
|
-
setDebugHeatmap(enabled) {
|
|
3737
|
-
if (this.renderer) {
|
|
3738
|
-
this.renderer.setDebugConfig({ enabled, showHeatmap: enabled });
|
|
3739
|
-
log6.debug(`Debug heatmap ${enabled ? "enabled" : "disabled"}`);
|
|
3740
|
-
}
|
|
3741
|
-
}
|
|
3742
|
-
resetDebugTracking() {
|
|
3743
|
-
if (this.renderer) {
|
|
3744
|
-
this.renderer.resetDebugTracking();
|
|
3745
|
-
log6.debug("Debug tracking reset");
|
|
3746
|
-
}
|
|
3747
|
-
}
|
|
3748
|
-
getDebugStats() {
|
|
3749
|
-
return this.renderer?.getDebugStats() || null;
|
|
3750
|
-
}
|
|
3751
|
-
async renderLazyRoute(routePath, componentName, routeElement) {
|
|
3752
|
-
if (!this.engine || !this.renderer) {
|
|
3753
|
-
throw new Error("Engine not initialized");
|
|
3754
|
-
}
|
|
3755
|
-
const component = componentLoader.get(componentName);
|
|
3756
|
-
if (!component) {
|
|
3757
|
-
throw new Error(`Component ${componentName} not found`);
|
|
3758
|
-
}
|
|
3759
|
-
const template = component.template;
|
|
3760
|
-
if (!template) {
|
|
3761
|
-
throw new Error(`Component ${componentName} has no template`);
|
|
3762
|
-
}
|
|
3763
|
-
if (component.module && !this.moduleInstances.has(componentName)) {
|
|
3764
|
-
const moduleId = this.extractModuleId(componentName, template);
|
|
3765
|
-
const moduleInstance = new HypenModuleInstance(this.engine, component.module, this.router, this.globalContext);
|
|
3766
|
-
this.globalContext.registerModule(moduleId, moduleInstance);
|
|
3767
|
-
this.moduleInstances.set(componentName, moduleInstance);
|
|
3768
|
-
moduleInstance.onStateChange(() => {
|
|
3769
|
-
const mergedState2 = this.getMergedState();
|
|
3770
|
-
log6.debug(`Lazy component ${componentName} state changed:`, mergedState2);
|
|
3771
|
-
this.renderer.updateState(mergedState2);
|
|
3772
|
-
});
|
|
3773
|
-
}
|
|
3774
|
-
await new Promise((resolve) => setTimeout(resolve, 50));
|
|
3775
|
-
const routeNodeId = routeElement.dataset.hypenId;
|
|
3776
|
-
if (!routeNodeId) {
|
|
3777
|
-
throw new Error(`Route element is missing data-hypen-id attribute`);
|
|
3778
|
-
}
|
|
3779
|
-
const mergedState = this.getMergedState();
|
|
3780
|
-
this.engine.renderInto(template, routeNodeId, mergedState);
|
|
3781
|
-
this.renderer.updateState(mergedState);
|
|
3782
|
-
}
|
|
3783
|
-
extractModuleId(componentName, template) {
|
|
3784
|
-
const idMatch = template.match(/\.id\(["']([^"']+)["']\)/);
|
|
3785
|
-
const matchedId = idMatch?.[1];
|
|
3786
|
-
if (matchedId) {
|
|
3787
|
-
return matchedId;
|
|
3788
|
-
}
|
|
3789
|
-
return componentName;
|
|
3790
|
-
}
|
|
3791
|
-
createNestedModuleInstances() {
|
|
3792
|
-
if (Router && !this.moduleInstances.has("Router")) {
|
|
3793
|
-
const routerInstance = new HypenModuleInstance(this.engine, Router, this.router, this.globalContext);
|
|
3794
|
-
this.globalContext.registerModule("Router", routerInstance);
|
|
3795
|
-
this.moduleInstances.set("Router", routerInstance);
|
|
3796
|
-
routerInstance.onStateChange(() => {
|
|
3797
|
-
const mergedState = this.getMergedState();
|
|
3798
|
-
log6.debug("Router state changed:", mergedState);
|
|
3799
|
-
this.renderer.updateState(mergedState);
|
|
3800
|
-
});
|
|
3801
|
-
}
|
|
3802
|
-
const componentNames = componentLoader.getNames();
|
|
3803
|
-
for (const name of componentNames) {
|
|
3804
|
-
if (this.moduleInstances.has(name)) {
|
|
3805
|
-
continue;
|
|
3806
|
-
}
|
|
3807
|
-
const comp = componentLoader.get(name);
|
|
3808
|
-
if (!comp || !comp.module) {
|
|
3809
|
-
continue;
|
|
3810
|
-
}
|
|
3811
|
-
log6.debug(`Creating nested module instance for: ${name}`);
|
|
3812
|
-
const moduleInstance = new HypenModuleInstance(this.engine, comp.module, this.router, this.globalContext);
|
|
3813
|
-
this.globalContext.registerModule(name, moduleInstance);
|
|
3814
|
-
this.moduleInstances.set(name, moduleInstance);
|
|
3815
|
-
moduleInstance.onStateChange(() => {
|
|
3816
|
-
const mergedState = this.getMergedState();
|
|
3817
|
-
log6.debug(`Nested component ${name} state changed:`, mergedState);
|
|
3818
|
-
this.renderer.updateState(mergedState);
|
|
3819
|
-
});
|
|
3820
|
-
}
|
|
3821
|
-
}
|
|
3822
|
-
getMergedState() {
|
|
3823
|
-
const merged = {};
|
|
3824
|
-
if (this.moduleInstance) {
|
|
3825
|
-
const mainState = this.moduleInstance.getState();
|
|
3826
|
-
Object.assign(merged, mainState);
|
|
3827
|
-
}
|
|
3828
|
-
for (const [name, instance] of this.moduleInstances.entries()) {
|
|
3829
|
-
const nestedState = instance.getState();
|
|
3830
|
-
Object.assign(merged, nestedState);
|
|
303
|
+
// Include all nested component states
|
|
304
|
+
for (const [name, instance] of this.moduleInstances.entries()) {
|
|
305
|
+
const nestedState = instance.getState();
|
|
306
|
+
Object.assign(merged, nestedState);
|
|
307
|
+
}
|
|
308
|
+
return merged;
|
|
309
|
+
}
|
|
310
|
+
/**
|
|
311
|
+
* Set up component resolver for the engine
|
|
312
|
+
*/
|
|
313
|
+
setupComponentResolver() {
|
|
314
|
+
if (!this.engine)
|
|
315
|
+
return;
|
|
316
|
+
// List of built-in DOM elements that should NOT be resolved
|
|
317
|
+
const builtInElements = new Set([
|
|
318
|
+
"Column",
|
|
319
|
+
"Row",
|
|
320
|
+
"Text",
|
|
321
|
+
"Button",
|
|
322
|
+
"Image",
|
|
323
|
+
"Input",
|
|
324
|
+
"Container",
|
|
325
|
+
"Box",
|
|
326
|
+
"Center",
|
|
327
|
+
"List",
|
|
328
|
+
"Canvas",
|
|
329
|
+
"Spacer",
|
|
330
|
+
"Divider",
|
|
331
|
+
"ScrollView",
|
|
332
|
+
]);
|
|
333
|
+
this.engine.setComponentResolver((componentName, contextPath) => {
|
|
334
|
+
// Don't try to resolve built-in DOM elements
|
|
335
|
+
if (builtInElements.has(componentName)) {
|
|
336
|
+
return null;
|
|
337
|
+
}
|
|
338
|
+
log.debug(`Resolving component: ${componentName} (context: ${contextPath})`);
|
|
339
|
+
// Check if component is registered
|
|
340
|
+
const componentDef = componentLoader.get(componentName);
|
|
341
|
+
if (!componentDef) {
|
|
342
|
+
log.debug(`Component not found: ${componentName}`);
|
|
343
|
+
return null;
|
|
344
|
+
}
|
|
345
|
+
// Router is passthrough, Route is lazy
|
|
346
|
+
const isPassthrough = componentName === "Router";
|
|
347
|
+
const isLazy = componentName === "Route";
|
|
348
|
+
const resolved = {
|
|
349
|
+
source: componentDef.template,
|
|
350
|
+
path: componentDef.path || componentName,
|
|
351
|
+
passthrough: isPassthrough,
|
|
352
|
+
lazy: isLazy,
|
|
353
|
+
};
|
|
354
|
+
const flags = [];
|
|
355
|
+
if (isPassthrough)
|
|
356
|
+
flags.push("passthrough");
|
|
357
|
+
if (isLazy)
|
|
358
|
+
flags.push("lazy");
|
|
359
|
+
const flagStr = flags.length > 0 ? ` (${flags.join(", ")})` : "";
|
|
360
|
+
log.debug(`Resolved ${componentName} -> ${resolved.path}${flagStr}`);
|
|
361
|
+
return resolved;
|
|
362
|
+
});
|
|
3831
363
|
}
|
|
3832
|
-
return merged;
|
|
3833
|
-
}
|
|
3834
|
-
setupComponentResolver() {
|
|
3835
|
-
if (!this.engine)
|
|
3836
|
-
return;
|
|
3837
|
-
const builtInElements = new Set([
|
|
3838
|
-
"Column",
|
|
3839
|
-
"Row",
|
|
3840
|
-
"Text",
|
|
3841
|
-
"Button",
|
|
3842
|
-
"Image",
|
|
3843
|
-
"Input",
|
|
3844
|
-
"Container",
|
|
3845
|
-
"Box",
|
|
3846
|
-
"Center",
|
|
3847
|
-
"List",
|
|
3848
|
-
"Canvas",
|
|
3849
|
-
"Spacer",
|
|
3850
|
-
"Divider",
|
|
3851
|
-
"ScrollView"
|
|
3852
|
-
]);
|
|
3853
|
-
this.engine.setComponentResolver((componentName, contextPath) => {
|
|
3854
|
-
if (builtInElements.has(componentName)) {
|
|
3855
|
-
return null;
|
|
3856
|
-
}
|
|
3857
|
-
log6.debug(`Resolving component: ${componentName} (context: ${contextPath})`);
|
|
3858
|
-
const componentDef = componentLoader.get(componentName);
|
|
3859
|
-
if (!componentDef) {
|
|
3860
|
-
log6.debug(`Component not found: ${componentName}`);
|
|
3861
|
-
return null;
|
|
3862
|
-
}
|
|
3863
|
-
const isPassthrough = componentName === "Router";
|
|
3864
|
-
const isLazy = componentName === "Route";
|
|
3865
|
-
const resolved = {
|
|
3866
|
-
source: componentDef.template,
|
|
3867
|
-
path: componentDef.path || componentName,
|
|
3868
|
-
passthrough: isPassthrough,
|
|
3869
|
-
lazy: isLazy
|
|
3870
|
-
};
|
|
3871
|
-
const flags = [];
|
|
3872
|
-
if (isPassthrough)
|
|
3873
|
-
flags.push("passthrough");
|
|
3874
|
-
if (isLazy)
|
|
3875
|
-
flags.push("lazy");
|
|
3876
|
-
const flagStr = flags.length > 0 ? ` (${flags.join(", ")})` : "";
|
|
3877
|
-
log6.debug(`Resolved ${componentName} -> ${resolved.path}${flagStr}`);
|
|
3878
|
-
return resolved;
|
|
3879
|
-
});
|
|
3880
|
-
}
|
|
3881
|
-
}
|
|
3882
|
-
async function render(componentName, containerSelector, config) {
|
|
3883
|
-
const hypen = new Hypen(config);
|
|
3884
|
-
await hypen.init();
|
|
3885
|
-
await hypen.loadComponents();
|
|
3886
|
-
await hypen.render(componentName, containerSelector);
|
|
3887
|
-
return hypen;
|
|
3888
364
|
}
|
|
3889
|
-
|
|
3890
|
-
|
|
3891
|
-
|
|
3892
|
-
|
|
3893
|
-
|
|
3894
|
-
|
|
3895
|
-
|
|
3896
|
-
|
|
365
|
+
/**
|
|
366
|
+
* Quick render function (like ReactDOM.render)
|
|
367
|
+
*
|
|
368
|
+
* @example
|
|
369
|
+
* ```typescript
|
|
370
|
+
* import { render } from "@hypen-space/web/client";
|
|
371
|
+
*
|
|
372
|
+
* await render("HomePage", "#app");
|
|
373
|
+
* ```
|
|
374
|
+
*/
|
|
375
|
+
export async function render(componentName, containerSelector, config) {
|
|
376
|
+
const hypen = new Hypen(config);
|
|
377
|
+
await hypen.init();
|
|
378
|
+
await hypen.loadComponents();
|
|
379
|
+
await hypen.render(componentName, containerSelector);
|
|
380
|
+
return hypen;
|
|
381
|
+
}
|
|
382
|
+
/**
|
|
383
|
+
* Render with explicit component loading
|
|
384
|
+
*
|
|
385
|
+
* @example
|
|
386
|
+
* ```typescript
|
|
387
|
+
* import { renderWithComponents } from "@hypen-space/web/client";
|
|
388
|
+
* import HomePage from "./components/HomePage/component";
|
|
389
|
+
* import homePageTemplate from "./components/HomePage/component.hypen";
|
|
390
|
+
*
|
|
391
|
+
* await renderWithComponents(
|
|
392
|
+
* { HomePage: { module: HomePage, template: homePageTemplate } },
|
|
393
|
+
* "HomePage",
|
|
394
|
+
* "#app"
|
|
395
|
+
* );
|
|
396
|
+
* ```
|
|
397
|
+
*/
|
|
398
|
+
export async function renderWithComponents(components, componentName, containerSelector, config) {
|
|
399
|
+
const hypen = new Hypen(config);
|
|
400
|
+
await hypen.init();
|
|
401
|
+
// Register components manually
|
|
402
|
+
for (const [name, { module, template }] of Object.entries(components)) {
|
|
403
|
+
let processedTemplate = template;
|
|
404
|
+
// If template starts with "module ComponentName {", extract just the children
|
|
405
|
+
const moduleMatch = template.match(/^\s*module\s+\w+\s*\{([\s\S]*)\}\s*$/);
|
|
406
|
+
if (moduleMatch && moduleMatch[1]) {
|
|
407
|
+
processedTemplate = moduleMatch[1].trim();
|
|
408
|
+
}
|
|
409
|
+
componentLoader.register(name, module, processedTemplate);
|
|
3897
410
|
}
|
|
3898
|
-
|
|
3899
|
-
|
|
3900
|
-
await hypen.render(componentName, containerSelector);
|
|
3901
|
-
return hypen;
|
|
411
|
+
await hypen.render(componentName, containerSelector);
|
|
412
|
+
return hypen;
|
|
3902
413
|
}
|
|
3903
|
-
|
|
3904
|
-
renderWithComponents,
|
|
3905
|
-
render,
|
|
3906
|
-
Hypen
|
|
3907
|
-
};
|
|
3908
|
-
|
|
3909
|
-
//# debugId=3DCF8179C4B1004C64756E2164756E21
|
|
414
|
+
//# sourceMappingURL=hypen.js.map
|