@hypen-space/web 0.4.32 → 0.4.35

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