elit 3.6.6 → 3.6.7

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 (153) hide show
  1. package/Cargo.lock +1 -1
  2. package/Cargo.toml +1 -1
  3. package/dist/build.cjs +421 -331
  4. package/dist/build.d.ts +1 -19
  5. package/dist/build.js +420 -330
  6. package/dist/build.mjs +420 -330
  7. package/dist/chokidar.cjs +219 -182
  8. package/dist/chokidar.d.ts +25 -10
  9. package/dist/chokidar.js +217 -182
  10. package/dist/chokidar.mjs +218 -183
  11. package/dist/cli.cjs +22439 -21563
  12. package/dist/cli.d.ts +19 -37
  13. package/dist/cli.mjs +24113 -23252
  14. package/dist/config.cjs +357 -350
  15. package/dist/config.d.ts +17 -245
  16. package/dist/config.js +520 -515
  17. package/dist/config.mjs +346 -341
  18. package/dist/contracts-BeW9k0yZ.d.ts +54 -0
  19. package/dist/contracts-D7KIS-TK.d.ts +36 -0
  20. package/dist/coverage.cjs +448 -485
  21. package/dist/coverage.d.ts +13 -62
  22. package/dist/coverage.js +447 -484
  23. package/dist/coverage.mjs +447 -484
  24. package/dist/database.cjs +819 -828
  25. package/dist/database.d.ts +8 -24
  26. package/dist/database.js +818 -829
  27. package/dist/database.mjs +818 -829
  28. package/dist/desktop-auto-render.cjs +1700 -1523
  29. package/dist/desktop-auto-render.d.ts +4 -12
  30. package/dist/desktop-auto-render.js +1695 -1518
  31. package/dist/desktop-auto-render.mjs +1696 -1519
  32. package/dist/desktop.cjs +3 -1
  33. package/dist/desktop.d.ts +4 -1
  34. package/dist/desktop.js +1 -1
  35. package/dist/desktop.mjs +1 -1
  36. package/dist/dev-build.cjs +830 -0
  37. package/dist/dev-build.d.ts +53 -0
  38. package/dist/dev-build.js +3318 -0
  39. package/dist/dev-build.mjs +797 -0
  40. package/dist/dom.cjs +717 -591
  41. package/dist/dom.d.ts +2 -17
  42. package/dist/dom.js +714 -588
  43. package/dist/dom.mjs +716 -590
  44. package/dist/el.cjs +62 -52
  45. package/dist/el.d.ts +5 -12
  46. package/dist/el.js +60 -52
  47. package/dist/el.mjs +60 -52
  48. package/dist/fs.cjs +72 -63
  49. package/dist/fs.d.ts +22 -19
  50. package/dist/fs.js +71 -62
  51. package/dist/fs.mjs +71 -62
  52. package/dist/hmr.cjs +40 -14
  53. package/dist/hmr.d.ts +11 -23
  54. package/dist/hmr.js +38 -14
  55. package/dist/hmr.mjs +38 -14
  56. package/dist/http.cjs +251 -99
  57. package/dist/http.d.ts +38 -104
  58. package/dist/http.js +249 -99
  59. package/dist/http.mjs +249 -99
  60. package/dist/https.cjs +524 -228
  61. package/dist/https.d.ts +44 -36
  62. package/dist/https.js +520 -226
  63. package/dist/https.mjs +522 -228
  64. package/dist/index.cjs +7502 -7691
  65. package/dist/index.d.ts +6 -3
  66. package/dist/index.js +7486 -7677
  67. package/dist/index.mjs +7497 -7687
  68. package/dist/mime-types.cjs +10 -4
  69. package/dist/mime-types.d.ts +8 -11
  70. package/dist/mime-types.js +9 -3
  71. package/dist/mime-types.mjs +9 -3
  72. package/dist/native.cjs +8616 -8870
  73. package/dist/native.d.ts +7 -10
  74. package/dist/native.js +8682 -8936
  75. package/dist/native.mjs +8615 -8869
  76. package/dist/path.cjs +83 -77
  77. package/dist/path.d.ts +29 -29
  78. package/dist/path.js +82 -76
  79. package/dist/path.mjs +82 -76
  80. package/dist/pm.cjs +3300 -0
  81. package/dist/pm.d.ts +256 -0
  82. package/dist/pm.js +5638 -0
  83. package/dist/pm.mjs +3196 -0
  84. package/dist/preview-build.cjs +712 -0
  85. package/dist/preview-build.d.ts +59 -0
  86. package/dist/preview-build.js +3194 -0
  87. package/dist/preview-build.mjs +676 -0
  88. package/dist/render-context.cjs +13 -2
  89. package/dist/render-context.d.ts +9 -34
  90. package/dist/render-context.js +11 -2
  91. package/dist/render-context.mjs +11 -2
  92. package/dist/router.cjs +787 -646
  93. package/dist/router.d.ts +8 -14
  94. package/dist/router.js +786 -645
  95. package/dist/router.mjs +786 -645
  96. package/dist/runtime.cjs +1 -1
  97. package/dist/runtime.js +1 -1
  98. package/dist/runtime.mjs +1 -1
  99. package/dist/server.cjs +3254 -2684
  100. package/dist/server.d.ts +47 -5
  101. package/dist/server.js +3427 -2859
  102. package/dist/server.mjs +3397 -2829
  103. package/dist/smtp-server.cjs +16 -3
  104. package/dist/smtp-server.d.ts +12 -26
  105. package/dist/smtp-server.js +18 -5
  106. package/dist/smtp-server.mjs +16 -3
  107. package/dist/state-DvEkDehk.d.ts +195 -0
  108. package/dist/state.cjs +768 -659
  109. package/dist/state.d.ts +11 -71
  110. package/dist/state.js +760 -651
  111. package/dist/state.mjs +767 -658
  112. package/dist/style.cjs +1011 -968
  113. package/dist/style.d.ts +13 -127
  114. package/dist/style.js +1009 -970
  115. package/dist/style.mjs +1011 -971
  116. package/dist/test-reporter.cjs +332 -316
  117. package/dist/test-reporter.d.ts +28 -33
  118. package/dist/test-reporter.js +328 -312
  119. package/dist/test-reporter.mjs +328 -312
  120. package/dist/test-runtime.cjs +927 -968
  121. package/dist/test-runtime.d.ts +24 -99
  122. package/dist/test-runtime.js +922 -965
  123. package/dist/test-runtime.mjs +922 -965
  124. package/dist/test.cjs +4428 -4273
  125. package/dist/test.d.ts +2 -8
  126. package/dist/test.js +4307 -4154
  127. package/dist/test.mjs +4419 -4267
  128. package/dist/types-BONVzPtp.d.ts +59 -0
  129. package/dist/types-BR4wMiVx.d.ts +32 -0
  130. package/dist/types-C4gKykuG.d.ts +23 -0
  131. package/dist/types-CIhpN1-K.d.ts +64 -0
  132. package/dist/types-Ckj8md_j.d.ts +84 -0
  133. package/dist/types-CpjQTAkX.d.ts +24 -0
  134. package/dist/types-D0LjrYjS.d.ts +14 -0
  135. package/dist/types-DAisuVr5.d.ts +75 -0
  136. package/dist/types-tJn88E1N.d.ts +242 -0
  137. package/dist/types.d.ts +50 -237
  138. package/dist/universal.cjs +1 -1
  139. package/dist/universal.d.ts +1 -7
  140. package/dist/universal.js +1 -1
  141. package/dist/universal.mjs +1 -1
  142. package/dist/websocket-XfyK23zD.d.ts +119 -0
  143. package/dist/ws.cjs +129 -108
  144. package/dist/ws.d.ts +21 -131
  145. package/dist/ws.js +128 -109
  146. package/dist/ws.mjs +128 -109
  147. package/dist/wss.cjs +757 -479
  148. package/dist/wss.d.ts +31 -28
  149. package/dist/wss.js +755 -479
  150. package/dist/wss.mjs +758 -482
  151. package/package.json +8 -1
  152. package/vendor/epaint-0.31.1/src/image.rs +418 -0
  153. package/dist/server-uMQvZAll.d.ts +0 -458
package/dist/state.mjs CHANGED
@@ -1,10 +1,14 @@
1
- // src/render-context.ts
1
+ // src/desktop/render-context/constants.ts
2
2
  var RUNTIME_TARGET_KEY = "__ELIT_RUNTIME_TARGET__";
3
3
  var CAPTURED_RENDER_KEY = "__ELIT_CAPTURED_RENDER__";
4
4
  var RUNTIME_TARGET_ENV = "ELIT_RUNTIME_TARGET";
5
+
6
+ // src/desktop/render-context/globals.ts
5
7
  function getGlobalRenderScope() {
6
8
  return globalThis;
7
9
  }
10
+
11
+ // src/desktop/render-context/runtime-target.ts
8
12
  function isRenderRuntimeTarget(value) {
9
13
  return value === "web" || value === "desktop" || value === "mobile" || value === "unknown";
10
14
  }
@@ -20,7 +24,8 @@ function detectRenderRuntimeTarget() {
20
24
  if (typeof globalScope.createWindow === "function") {
21
25
  return "desktop";
22
26
  }
23
- const argv = Array.isArray(globalScope.process?.argv) ? globalScope.process.argv.join(" ") : "";
27
+ const argvValues = globalScope.process?.argv;
28
+ const argv = Array.isArray(argvValues) ? argvValues.join(" ") : "";
24
29
  if (/\bdesktop\b/i.test(argv)) {
25
30
  return "desktop";
26
31
  }
@@ -29,6 +34,8 @@ function detectRenderRuntimeTarget() {
29
34
  }
30
35
  return "unknown";
31
36
  }
37
+
38
+ // src/desktop/render-context/captured-render.ts
32
39
  function captureRenderedVNode(rootElement, vNode, target = detectRenderRuntimeTarget()) {
33
40
  const globalScope = getGlobalRenderScope();
34
41
  globalScope[RUNTIME_TARGET_KEY] = target;
@@ -39,7 +46,7 @@ function captureRenderedVNode(rootElement, vNode, target = detectRenderRuntimeTa
39
46
  };
40
47
  }
41
48
 
42
- // src/dom.ts
49
+ // src/client/dom/helpers.ts
43
50
  function resolveElement(rootElement) {
44
51
  return typeof rootElement === "string" ? document.getElementById(rootElement.replace("#", "")) : rootElement;
45
52
  }
@@ -67,669 +74,788 @@ function resolveTextareaValue(tagName, props) {
67
74
  function hasDocumentApi() {
68
75
  return typeof document !== "undefined";
69
76
  }
70
- var DomNode = class {
71
- constructor() {
72
- this.elementCache = /* @__PURE__ */ new WeakMap();
73
- this.reactiveNodes = /* @__PURE__ */ new Map();
74
- }
75
- createElement(tagName, props = {}, children = []) {
76
- return { tagName, props, children };
77
- }
78
- renderToDOM(vNode, parent) {
79
- if (vNode == null || vNode === false) return;
80
- if (typeof vNode !== "object") {
81
- parent.appendChild(document.createTextNode(String(vNode)));
82
- return;
83
- }
84
- if (this.isState(vNode)) {
85
- const textNode = document.createTextNode(String(vNode.value ?? ""));
86
- parent.appendChild(textNode);
87
- vNode.subscribe((newValue) => {
88
- textNode.textContent = String(newValue ?? "");
89
- });
90
- return;
91
- }
92
- if (Array.isArray(vNode)) {
93
- for (const child of vNode) {
94
- this.renderToDOM(child, parent);
77
+ function isState(value) {
78
+ return value && typeof value === "object" && "value" in value && "subscribe" in value && typeof value.subscribe === "function";
79
+ }
80
+
81
+ // src/client/dom/dom-render.ts
82
+ function isSvgElement(tagName, parent) {
83
+ return tagName === "svg" || tagName[0] === "s" && tagName[1] === "v" && tagName[2] === "g" || parent.namespaceURI === "http://www.w3.org/2000/svg";
84
+ }
85
+ function applyProps(el, props, textareaValue) {
86
+ for (const key in props) {
87
+ const value = props[key];
88
+ if (value == null || value === false) continue;
89
+ const c = key.charCodeAt(0);
90
+ if (c === 99 && (key.length < 6 || key[5] === "N")) {
91
+ const classValue = Array.isArray(value) ? value.join(" ") : String(value);
92
+ if (el instanceof SVGElement) {
93
+ el.setAttribute("class", classValue);
94
+ } else {
95
+ el.className = classValue;
95
96
  }
96
- return;
97
- }
98
- const { tagName, props, children } = vNode;
99
- const textareaValue = resolveTextareaValue(tagName, props);
100
- if (!tagName) {
101
- for (const child of children) {
102
- if (shouldSkipChild(child)) continue;
103
- if (Array.isArray(child)) {
104
- for (const c of child) {
105
- !shouldSkipChild(c) && this.renderToDOM(c, parent);
106
- }
107
- } else {
108
- this.renderToDOM(child, parent);
97
+ } else if (c === 115 && key.length === 5) {
98
+ if (typeof value === "string") {
99
+ el.style.cssText = value;
100
+ } else {
101
+ const style = el.style;
102
+ for (const styleKey in value) {
103
+ style[styleKey] = value[styleKey];
109
104
  }
110
105
  }
111
- return;
112
- }
113
- const isSVG = tagName === "svg" || tagName[0] === "s" && tagName[1] === "v" && tagName[2] === "g" || parent.namespaceURI === "http://www.w3.org/2000/svg";
114
- const el = isSVG ? document.createElementNS("http://www.w3.org/2000/svg", tagName.replace("svg", "").toLowerCase() || tagName) : document.createElement(tagName);
115
- for (const key in props) {
116
- const value = props[key];
117
- if (value == null || value === false) continue;
118
- const c = key.charCodeAt(0);
119
- if (c === 99 && (key.length < 6 || key[5] === "N")) {
120
- const classValue = Array.isArray(value) ? value.join(" ") : value;
121
- isSVG ? el.setAttribute("class", classValue) : el.className = classValue;
122
- } else if (c === 115 && key.length === 5) {
123
- if (typeof value === "string") {
124
- el.style.cssText = value;
106
+ } else if (c === 111 && key.charCodeAt(1) === 110) {
107
+ el[key.toLowerCase()] = value;
108
+ } else if (c === 100 && key.length > 20) {
109
+ el.innerHTML = value.__html;
110
+ } else if (c === 114 && key === "ref") {
111
+ setTimeout(() => {
112
+ if (typeof value === "function") {
113
+ value(el);
125
114
  } else {
126
- const s = el.style;
127
- for (const k in value) s[k] = value[k];
115
+ value.current = el;
128
116
  }
129
- } else if (c === 111 && key.charCodeAt(1) === 110) {
130
- el[key.toLowerCase()] = value;
131
- } else if (c === 100 && key.length > 20) {
132
- el.innerHTML = value.__html;
133
- } else if (c === 114 && key === "ref") {
134
- setTimeout(() => {
135
- typeof value === "function" ? value(el) : value.current = el;
136
- }, 0);
137
- } else if (textareaValue !== void 0 && key === "value") {
138
- continue;
139
- } else {
140
- el.setAttribute(key, value === true ? "" : String(value));
141
- }
142
- }
143
- const renderableChildren = textareaValue === void 0 ? children : [];
144
- const len = renderableChildren.length;
145
- if (!len) {
146
- if (textareaValue !== void 0) {
147
- el.value = textareaValue;
148
- }
149
- parent.appendChild(el);
150
- return;
117
+ }, 0);
118
+ } else if (textareaValue !== void 0 && key === "value") {
119
+ continue;
120
+ } else {
121
+ el.setAttribute(key, value === true ? "" : String(value));
151
122
  }
152
- const renderChildren = (target) => {
153
- for (let i = 0; i < len; i++) {
154
- const child = renderableChildren[i];
155
- if (shouldSkipChild(child)) continue;
156
- if (Array.isArray(child)) {
157
- for (let j = 0, cLen = child.length; j < cLen; j++) {
158
- const c = child[j];
159
- !shouldSkipChild(c) && this.renderToDOM(c, target);
160
- }
161
- } else {
162
- this.renderToDOM(child, target);
123
+ }
124
+ }
125
+ function renderChildren(children, target) {
126
+ const len = children.length;
127
+ for (let i = 0; i < len; i++) {
128
+ const child = children[i];
129
+ if (shouldSkipChild(child)) continue;
130
+ if (Array.isArray(child)) {
131
+ for (let j = 0, childLen = child.length; j < childLen; j++) {
132
+ const nestedChild = child[j];
133
+ if (!shouldSkipChild(nestedChild)) {
134
+ renderToDOM(nestedChild, target);
163
135
  }
164
136
  }
165
- };
166
- if (len > 30) {
167
- const fragment = document.createDocumentFragment();
168
- renderChildren(fragment);
169
- el.appendChild(fragment);
170
137
  } else {
171
- renderChildren(el);
138
+ renderToDOM(child, target);
172
139
  }
173
- parent.appendChild(el);
174
140
  }
175
- render(rootElement, vNode) {
176
- if (!hasDocumentApi()) {
177
- const runtimeTarget = detectRenderRuntimeTarget();
178
- if (runtimeTarget === "desktop" || runtimeTarget === "mobile") {
179
- captureRenderedVNode(rootElement, vNode, runtimeTarget);
180
- return {};
181
- }
182
- throw new Error("render() requires a DOM or an Elit desktop/mobile runtime target.");
141
+ }
142
+ function renderToDOM(vNode, parent) {
143
+ if (vNode == null || vNode === false) return;
144
+ if (typeof vNode !== "object") {
145
+ parent.appendChild(document.createTextNode(String(vNode)));
146
+ return;
147
+ }
148
+ if (isState(vNode)) {
149
+ const textNode = document.createTextNode(String(vNode.value ?? ""));
150
+ parent.appendChild(textNode);
151
+ vNode.subscribe((newValue) => {
152
+ textNode.textContent = String(newValue ?? "");
153
+ });
154
+ return;
155
+ }
156
+ if (Array.isArray(vNode)) {
157
+ for (const child of vNode) {
158
+ renderToDOM(child, parent);
183
159
  }
184
- const el = ensureElement(resolveElement(rootElement), rootElement);
185
- el.innerHTML = "";
186
- if (vNode.children && vNode.children.length > 500) {
187
- const fragment = document.createDocumentFragment();
188
- this.renderToDOM(vNode, fragment);
189
- el.appendChild(fragment);
190
- } else {
191
- this.renderToDOM(vNode, el);
160
+ return;
161
+ }
162
+ const { tagName, props, children } = vNode;
163
+ const textareaValue = resolveTextareaValue(tagName, props);
164
+ if (!tagName) {
165
+ renderChildren(children, parent);
166
+ return;
167
+ }
168
+ const el = isSvgElement(tagName, parent) ? document.createElementNS("http://www.w3.org/2000/svg", tagName.replace("svg", "").toLowerCase() || tagName) : document.createElement(tagName);
169
+ applyProps(el, props, textareaValue);
170
+ const renderableChildren = textareaValue === void 0 ? children : [];
171
+ if (!renderableChildren.length) {
172
+ if (textareaValue !== void 0) {
173
+ el.value = textareaValue;
192
174
  }
193
- return el;
175
+ parent.appendChild(el);
176
+ return;
194
177
  }
195
- batchRender(rootElement, vNodes) {
196
- const el = ensureElement(resolveElement(rootElement), rootElement);
197
- const len = vNodes.length;
198
- if (len > 3e3) {
199
- const fragment = document.createDocumentFragment();
200
- let processed = 0;
201
- const chunkSize = 1500;
202
- const processChunk = () => {
203
- const end = Math.min(processed + chunkSize, len);
204
- for (let i = processed; i < end; i++) {
205
- this.renderToDOM(vNodes[i], fragment);
206
- }
207
- processed = end;
208
- if (processed >= len) {
209
- el.appendChild(fragment);
210
- } else {
211
- requestAnimationFrame(processChunk);
212
- }
213
- };
214
- processChunk();
215
- } else {
216
- const fragment = document.createDocumentFragment();
217
- for (let i = 0; i < len; i++) {
218
- this.renderToDOM(vNodes[i], fragment);
219
- }
220
- el.appendChild(fragment);
178
+ if (renderableChildren.length > 30) {
179
+ const fragment = document.createDocumentFragment();
180
+ renderChildren(renderableChildren, fragment);
181
+ el.appendChild(fragment);
182
+ } else {
183
+ renderChildren(renderableChildren, el);
184
+ }
185
+ parent.appendChild(el);
186
+ }
187
+ function render(rootElement, vNode) {
188
+ if (!hasDocumentApi()) {
189
+ const runtimeTarget = detectRenderRuntimeTarget();
190
+ if (runtimeTarget === "desktop" || runtimeTarget === "mobile") {
191
+ captureRenderedVNode(rootElement, vNode, runtimeTarget);
192
+ return {};
221
193
  }
222
- return el;
194
+ throw new Error("render() requires a DOM or an Elit desktop/mobile runtime target.");
195
+ }
196
+ const el = ensureElement(resolveElement(rootElement), rootElement);
197
+ el.innerHTML = "";
198
+ if (vNode.children && vNode.children.length > 500) {
199
+ const fragment = document.createDocumentFragment();
200
+ renderToDOM(vNode, fragment);
201
+ el.appendChild(fragment);
202
+ } else {
203
+ renderToDOM(vNode, el);
223
204
  }
224
- renderChunked(rootElement, vNodes, chunkSize = 5e3, onProgress) {
225
- const el = ensureElement(resolveElement(rootElement), rootElement);
226
- const len = vNodes.length;
227
- let index = 0;
228
- const renderChunk = () => {
229
- const end = Math.min(index + chunkSize, len);
230
- const fragment = document.createDocumentFragment();
231
- for (let i = index; i < end; i++) {
232
- this.renderToDOM(vNodes[i], fragment);
205
+ return el;
206
+ }
207
+ function batchRender(rootElement, vNodes) {
208
+ const el = ensureElement(resolveElement(rootElement), rootElement);
209
+ const len = vNodes.length;
210
+ if (len > 3e3) {
211
+ const fragment = document.createDocumentFragment();
212
+ let processed = 0;
213
+ const chunkSize = 1500;
214
+ const processChunk = () => {
215
+ const end = Math.min(processed + chunkSize, len);
216
+ for (let i = processed; i < end; i++) {
217
+ renderToDOM(vNodes[i], fragment);
233
218
  }
234
- el.appendChild(fragment);
235
- index = end;
236
- if (onProgress) onProgress(index, len);
237
- if (index < len) {
238
- requestAnimationFrame(renderChunk);
219
+ processed = end;
220
+ if (processed >= len) {
221
+ el.appendChild(fragment);
222
+ } else {
223
+ requestAnimationFrame(processChunk);
239
224
  }
240
225
  };
241
- requestAnimationFrame(renderChunk);
242
- return el;
226
+ processChunk();
227
+ } else {
228
+ const fragment = document.createDocumentFragment();
229
+ for (let i = 0; i < len; i++) {
230
+ renderToDOM(vNodes[i], fragment);
231
+ }
232
+ el.appendChild(fragment);
243
233
  }
244
- renderToHead(...vNodes) {
245
- const head = document.head;
246
- if (head) {
247
- for (const vNode of vNodes.flat()) {
248
- vNode && this.renderToDOM(vNode, head);
234
+ return el;
235
+ }
236
+ function renderChunked(rootElement, vNodes, chunkSize = 5e3, onProgress) {
237
+ const el = ensureElement(resolveElement(rootElement), rootElement);
238
+ const len = vNodes.length;
239
+ let index = 0;
240
+ const renderChunkFrame = () => {
241
+ const end = Math.min(index + chunkSize, len);
242
+ const fragment = document.createDocumentFragment();
243
+ for (let i = index; i < end; i++) {
244
+ renderToDOM(vNodes[i], fragment);
245
+ }
246
+ el.appendChild(fragment);
247
+ index = end;
248
+ if (onProgress) {
249
+ onProgress(index, len);
250
+ }
251
+ if (index < len) {
252
+ requestAnimationFrame(renderChunkFrame);
253
+ }
254
+ };
255
+ requestAnimationFrame(renderChunkFrame);
256
+ return el;
257
+ }
258
+ function renderToHead(...vNodes) {
259
+ const head = document.head;
260
+ if (head) {
261
+ for (const vNode of vNodes.flat()) {
262
+ if (vNode) {
263
+ renderToDOM(vNode, head);
249
264
  }
250
265
  }
251
- return head;
252
- }
253
- addStyle(cssText) {
254
- const el = document.createElement("style");
255
- el.textContent = cssText;
256
- return document.head.appendChild(el);
257
266
  }
258
- addMeta(attrs) {
259
- const el = document.createElement("meta");
260
- for (const k in attrs) el.setAttribute(k, attrs[k]);
261
- return document.head.appendChild(el);
267
+ return head;
268
+ }
269
+ function addStyle(cssText) {
270
+ const el = document.createElement("style");
271
+ el.textContent = cssText;
272
+ return document.head.appendChild(el);
273
+ }
274
+ function addMeta(attrs) {
275
+ const el = document.createElement("meta");
276
+ for (const key in attrs) {
277
+ el.setAttribute(key, attrs[key]);
262
278
  }
263
- addLink(attrs) {
264
- const el = document.createElement("link");
265
- for (const k in attrs) el.setAttribute(k, attrs[k]);
266
- return document.head.appendChild(el);
279
+ return document.head.appendChild(el);
280
+ }
281
+ function addLink(attrs) {
282
+ const el = document.createElement("link");
283
+ for (const key in attrs) {
284
+ el.setAttribute(key, attrs[key]);
267
285
  }
268
- setTitle(text2) {
269
- return document.title = text2;
286
+ return document.head.appendChild(el);
287
+ }
288
+ function setTitle(text2) {
289
+ return document.title = text2;
290
+ }
291
+ function cleanupUnusedElements(root, elementCache) {
292
+ const walker = document.createTreeWalker(root, NodeFilter.SHOW_ELEMENT);
293
+ const toRemove = [];
294
+ while (walker.nextNode()) {
295
+ const node = walker.currentNode;
296
+ if (node.id && node.id.startsWith("r") && !elementCache.has(node)) {
297
+ toRemove.push(node);
298
+ }
270
299
  }
271
- // Reactive State Management
272
- createState(initialValue, options = {}) {
273
- let value = initialValue;
274
- const listeners = /* @__PURE__ */ new Set();
275
- let updateTimer = null;
276
- const { throttle: throttle2 = 0, deep = false } = options;
277
- const notify = () => listeners.forEach((fn) => fn(value));
278
- const scheduleUpdate = () => {
279
- if (throttle2 > 0) {
280
- if (!updateTimer) {
281
- updateTimer = setTimeout(() => {
282
- updateTimer = null;
283
- notify();
284
- }, throttle2);
285
- }
286
- } else {
287
- notify();
288
- }
289
- };
290
- return {
291
- get value() {
292
- return value;
293
- },
294
- set value(newValue) {
295
- const changed = deep ? JSON.stringify(value) !== JSON.stringify(newValue) : value !== newValue;
296
- if (changed) {
297
- value = newValue;
298
- scheduleUpdate();
299
- }
300
- },
301
- subscribe(fn) {
302
- listeners.add(fn);
303
- return () => listeners.delete(fn);
304
- },
305
- destroy() {
306
- listeners.clear();
307
- updateTimer && clearTimeout(updateTimer);
300
+ toRemove.forEach((el) => el.remove());
301
+ return toRemove.length;
302
+ }
303
+
304
+ // src/client/dom/reactive.ts
305
+ function createReactiveChild(state, reactiveNodes, renderFn) {
306
+ const currentValue = renderFn(state.value);
307
+ if (typeof window !== "undefined" && typeof document !== "undefined") {
308
+ const entry = { node: null, renderFn };
309
+ reactiveNodes.set(state, entry);
310
+ state.subscribe(() => {
311
+ if (entry.node && entry.node.parentNode) {
312
+ const newValue = renderFn(state.value);
313
+ entry.node.textContent = String(newValue ?? "");
308
314
  }
309
- };
310
- }
311
- computed(states, computeFn) {
312
- const values = states.map((s) => s.value);
313
- const result = this.createState(computeFn(...values));
314
- states.forEach((state, index) => {
315
- state.subscribe((newValue) => {
316
- values[index] = newValue;
317
- result.value = computeFn(...values);
318
- });
319
315
  });
320
- return result;
321
316
  }
322
- effect(stateFn) {
323
- stateFn();
317
+ return currentValue;
318
+ }
319
+
320
+ // src/client/dom/string-render.ts
321
+ var SELF_CLOSING_TAGS = /* @__PURE__ */ new Set([
322
+ "area",
323
+ "base",
324
+ "br",
325
+ "col",
326
+ "embed",
327
+ "hr",
328
+ "img",
329
+ "input",
330
+ "link",
331
+ "meta",
332
+ "param",
333
+ "source",
334
+ "track",
335
+ "wbr"
336
+ ]);
337
+ function resolveStateValue(value) {
338
+ return isState(value) ? value.value : value;
339
+ }
340
+ function isReactiveWrapper(vNode) {
341
+ if (!vNode || typeof vNode !== "object" || !vNode.tagName) {
342
+ return false;
324
343
  }
325
- // Virtual scrolling helper for large lists
326
- createVirtualList(container, items, renderItem, itemHeight = 50, bufferSize = 5) {
327
- const viewportHeight = container.clientHeight;
328
- const totalHeight = items.length * itemHeight;
329
- let scrollTop = 0;
330
- const getVisibleRange = () => {
331
- const start = Math.max(0, Math.floor(scrollTop / itemHeight) - bufferSize);
332
- const end = Math.min(items.length, Math.ceil((scrollTop + viewportHeight) / itemHeight) + bufferSize);
333
- return { start, end };
334
- };
335
- const render2 = () => {
336
- const { start, end } = getVisibleRange();
337
- const wrapper = document.createElement("div");
338
- wrapper.style.cssText = `height:${totalHeight}px;position:relative`;
339
- for (let i = start; i < end; i++) {
340
- const itemEl = document.createElement("div");
341
- itemEl.style.cssText = `position:absolute;top:${i * itemHeight}px;height:${itemHeight}px;width:100%`;
342
- this.renderToDOM(renderItem(items[i], i), itemEl);
343
- wrapper.appendChild(itemEl);
344
- }
345
- container.innerHTML = "";
346
- container.appendChild(wrapper);
347
- };
348
- const scrollHandler = () => {
349
- scrollTop = container.scrollTop;
350
- requestAnimationFrame(render2);
351
- };
352
- container.addEventListener("scroll", scrollHandler);
353
- render2();
354
- return {
355
- render: render2,
356
- destroy: () => {
357
- container.removeEventListener("scroll", scrollHandler);
358
- container.innerHTML = "";
359
- }
360
- };
344
+ return vNode.tagName === "span" && vNode.props?.id && typeof vNode.props.id === "string" && /^r[a-z0-9]{9}$/.test(vNode.props.id);
345
+ }
346
+ function unwrapReactive(vNode) {
347
+ if (!isReactiveWrapper(vNode)) {
348
+ return vNode;
361
349
  }
362
- // Lazy load components
363
- lazy(loadFn) {
364
- let component = null;
365
- let loading = false;
366
- return async (...args) => {
367
- if (!component && !loading) {
368
- loading = true;
369
- component = await loadFn();
370
- loading = false;
371
- }
372
- return component ? component(...args) : { tagName: "div", props: { class: "loading" }, children: ["Loading..."] };
373
- };
350
+ const children = vNode.children;
351
+ if (!children || children.length === 0) {
352
+ return "";
374
353
  }
375
- // Memory management - cleanup unused elements
376
- cleanupUnusedElements(root) {
377
- const walker = document.createTreeWalker(root, NodeFilter.SHOW_ELEMENT);
378
- const toRemove = [];
379
- while (walker.nextNode()) {
380
- const node = walker.currentNode;
381
- if (node.id && node.id.startsWith("r") && !this.elementCache.has(node)) {
382
- toRemove.push(node);
354
+ if (children.length === 1) {
355
+ const child = children[0];
356
+ if (child && typeof child === "object" && child.tagName === "span") {
357
+ const props = child.props;
358
+ const hasNoProps = !props || Object.keys(props).length === 0;
359
+ const hasSingleStringChild = child.children && child.children.length === 1 && typeof child.children[0] === "string";
360
+ if (hasNoProps && hasSingleStringChild) {
361
+ return child.children[0];
383
362
  }
384
363
  }
385
- toRemove.forEach((el) => el.remove());
386
- return toRemove.length;
364
+ return unwrapReactive(child);
387
365
  }
388
- // Server-Side Rendering - convert VNode to HTML string
389
- renderToString(vNode, options = {}) {
390
- const { pretty = false, indent = 0 } = options;
391
- const indentStr = pretty ? " ".repeat(indent) : "";
392
- const newLine = pretty ? "\n" : "";
393
- let resolvedVNode = this.resolveStateValue(vNode);
394
- resolvedVNode = this.unwrapReactive(resolvedVNode);
395
- if (Array.isArray(resolvedVNode)) {
396
- return resolvedVNode.map((child) => this.renderToString(child, options)).join("");
366
+ return children.map((child) => unwrapReactive(child));
367
+ }
368
+ function escapeHtml(text2) {
369
+ const htmlEscapes = {
370
+ "&": "&amp;",
371
+ "<": "&lt;",
372
+ ">": "&gt;",
373
+ '"': "&quot;",
374
+ "'": "&#x27;"
375
+ };
376
+ return text2.replace(/[&<>"']/g, (char) => htmlEscapes[char]);
377
+ }
378
+ function isSelfClosingTag(tagName) {
379
+ return SELF_CLOSING_TAGS.has(tagName.toLowerCase());
380
+ }
381
+ function styleToString(style) {
382
+ if (typeof style === "string") {
383
+ return style;
384
+ }
385
+ if (typeof style === "object" && style !== null) {
386
+ const styles = [];
387
+ for (const key in style) {
388
+ const cssKey = key.replace(/([A-Z])/g, "-$1").toLowerCase();
389
+ styles.push(`${cssKey}:${style[key]}`);
397
390
  }
398
- if (typeof resolvedVNode !== "object" || resolvedVNode === null) {
399
- if (resolvedVNode === null || resolvedVNode === void 0 || resolvedVNode === false) {
400
- return "";
401
- }
402
- return this.escapeHtml(String(resolvedVNode));
391
+ return styles.join(";");
392
+ }
393
+ return "";
394
+ }
395
+ function propsToAttributes(props, tagName) {
396
+ const attrs = [];
397
+ for (const key in props) {
398
+ if (key === "children" || key === "dangerouslySetInnerHTML" || key === "ref" || tagName === "textarea" && key === "value") {
399
+ continue;
400
+ }
401
+ let value = props[key];
402
+ value = resolveStateValue(value);
403
+ if (value == null || value === false) continue;
404
+ if (key.startsWith("on") && typeof value === "function") {
405
+ continue;
403
406
  }
404
- const { tagName, props, children } = resolvedVNode;
405
- const textareaValue = resolveTextareaValue(tagName, props);
406
- const isSelfClosing = this.isSelfClosingTag(tagName);
407
- let html = `${indentStr}<${tagName}`;
408
- const attrs = this.propsToAttributes(props, tagName);
409
- if (attrs) {
410
- html += ` ${attrs}`;
407
+ if (key === "className" || key === "class") {
408
+ const className = Array.isArray(value) ? value.join(" ") : value;
409
+ if (className) {
410
+ attrs.push(`class="${escapeHtml(String(className))}"`);
411
+ }
412
+ continue;
411
413
  }
412
- if (isSelfClosing) {
413
- html += ` />${newLine}`;
414
- return html;
414
+ if (key === "style") {
415
+ const styleStr = styleToString(value);
416
+ if (styleStr) {
417
+ attrs.push(`style="${escapeHtml(styleStr)}"`);
418
+ }
419
+ continue;
415
420
  }
416
- html += ">";
417
- if (textareaValue !== void 0) {
418
- html += this.escapeHtml(textareaValue);
419
- html += `</${tagName}>${newLine}`;
420
- return html;
421
+ if (value === true) {
422
+ attrs.push(key);
423
+ continue;
421
424
  }
422
- if (props.dangerouslySetInnerHTML) {
423
- html += props.dangerouslySetInnerHTML.__html;
424
- html += `</${tagName}>${newLine}`;
425
- return html;
425
+ attrs.push(`${key}="${escapeHtml(String(value))}"`);
426
+ }
427
+ return attrs.join(" ");
428
+ }
429
+ function renderToString(vNode, options = {}) {
430
+ const { pretty = false, indent = 0 } = options;
431
+ const indentStr = pretty ? " ".repeat(indent) : "";
432
+ const newLine = pretty ? "\n" : "";
433
+ let resolvedVNode = resolveStateValue(vNode);
434
+ resolvedVNode = unwrapReactive(resolvedVNode);
435
+ if (Array.isArray(resolvedVNode)) {
436
+ return resolvedVNode.map((child) => renderToString(child, options)).join("");
437
+ }
438
+ if (typeof resolvedVNode !== "object" || resolvedVNode === null) {
439
+ if (resolvedVNode === null || resolvedVNode === void 0 || resolvedVNode === false) {
440
+ return "";
426
441
  }
427
- const isRawText = tagName === "script" || tagName === "style";
428
- if (children && children.length > 0) {
429
- const resolvedChildren = children.map((c) => {
430
- const resolved = this.resolveStateValue(c);
431
- return this.unwrapReactive(resolved);
432
- });
433
- const hasComplexChildren = resolvedChildren.some(
434
- (c) => typeof c === "object" && c !== null && !Array.isArray(c) && "tagName" in c
435
- );
436
- if (pretty && hasComplexChildren) {
437
- html += newLine;
438
- for (const child of resolvedChildren) {
439
- if (shouldSkipChild(child)) continue;
440
- if (Array.isArray(child)) {
441
- for (const c of child) {
442
- if (!shouldSkipChild(c)) {
443
- html += isRawText && typeof c === "string" ? c : this.renderToString(c, { pretty, indent: indent + 1 });
444
- }
442
+ return escapeHtml(String(resolvedVNode));
443
+ }
444
+ const { tagName, props, children } = resolvedVNode;
445
+ const textareaValue = resolveTextareaValue(tagName, props);
446
+ const selfClosing = isSelfClosingTag(tagName);
447
+ let html = `${indentStr}<${tagName}`;
448
+ const attrs = propsToAttributes(props, tagName);
449
+ if (attrs) {
450
+ html += ` ${attrs}`;
451
+ }
452
+ if (selfClosing) {
453
+ html += ` />${newLine}`;
454
+ return html;
455
+ }
456
+ html += ">";
457
+ if (textareaValue !== void 0) {
458
+ html += escapeHtml(textareaValue);
459
+ html += `</${tagName}>${newLine}`;
460
+ return html;
461
+ }
462
+ if (props.dangerouslySetInnerHTML) {
463
+ html += props.dangerouslySetInnerHTML.__html;
464
+ html += `</${tagName}>${newLine}`;
465
+ return html;
466
+ }
467
+ const isRawText = tagName === "script" || tagName === "style";
468
+ if (children && children.length > 0) {
469
+ const resolvedChildren = children.map((child) => unwrapReactive(resolveStateValue(child)));
470
+ const hasComplexChildren = resolvedChildren.some(
471
+ (child) => typeof child === "object" && child !== null && !Array.isArray(child) && "tagName" in child
472
+ );
473
+ if (pretty && hasComplexChildren) {
474
+ html += newLine;
475
+ for (const child of resolvedChildren) {
476
+ if (shouldSkipChild(child)) continue;
477
+ if (Array.isArray(child)) {
478
+ for (const nestedChild of child) {
479
+ if (!shouldSkipChild(nestedChild)) {
480
+ html += isRawText && typeof nestedChild === "string" ? nestedChild : renderToString(nestedChild, { pretty, indent: indent + 1 });
445
481
  }
446
- } else {
447
- html += isRawText && typeof child === "string" ? child : this.renderToString(child, { pretty, indent: indent + 1 });
448
482
  }
483
+ } else {
484
+ html += isRawText && typeof child === "string" ? child : renderToString(child, { pretty, indent: indent + 1 });
449
485
  }
450
- html += indentStr;
451
- } else {
452
- for (const child of resolvedChildren) {
453
- if (shouldSkipChild(child)) continue;
454
- if (Array.isArray(child)) {
455
- for (const c of child) {
456
- if (!shouldSkipChild(c)) {
457
- html += isRawText && typeof c === "string" ? c : this.renderToString(c, { pretty: false, indent: 0 });
458
- }
486
+ }
487
+ html += indentStr;
488
+ } else {
489
+ for (const child of resolvedChildren) {
490
+ if (shouldSkipChild(child)) continue;
491
+ if (Array.isArray(child)) {
492
+ for (const nestedChild of child) {
493
+ if (!shouldSkipChild(nestedChild)) {
494
+ html += isRawText && typeof nestedChild === "string" ? nestedChild : renderToString(nestedChild, { pretty: false, indent: 0 });
459
495
  }
460
- } else {
461
- html += isRawText && typeof child === "string" ? child : this.renderToString(child, { pretty: false, indent: 0 });
462
496
  }
497
+ } else {
498
+ html += isRawText && typeof child === "string" ? child : renderToString(child, { pretty: false, indent: 0 });
463
499
  }
464
500
  }
465
501
  }
466
- html += `</${tagName}>${newLine}`;
467
- return html;
468
502
  }
469
- resolveStateValue(value) {
470
- if (value && typeof value === "object" && "value" in value && "subscribe" in value) {
471
- return value.value;
503
+ html += `</${tagName}>${newLine}`;
504
+ return html;
505
+ }
506
+ function renderToHTMLDocument(vNode, options = {}) {
507
+ const {
508
+ title = "",
509
+ meta = [],
510
+ links = [],
511
+ scripts = [],
512
+ styles = [],
513
+ lang = "en",
514
+ head = "",
515
+ bodyAttrs = {},
516
+ pretty = false
517
+ } = options;
518
+ const nl = pretty ? "\n" : "";
519
+ const indent = pretty ? " " : "";
520
+ const indent2 = pretty ? " " : "";
521
+ let html = `<!DOCTYPE html>${nl}<html lang="${lang}">${nl}${indent}<head>${nl}${indent2}<meta charset="UTF-8">${nl}${indent2}<meta name="viewport" content="width=device-width, initial-scale=1.0">${nl}`;
522
+ if (title) {
523
+ html += `${indent2}<title>${escapeHtml(title)}</title>${nl}`;
524
+ }
525
+ for (const metaAttrs of meta) {
526
+ html += `${indent2}<meta`;
527
+ for (const key in metaAttrs) {
528
+ html += ` ${key}="${escapeHtml(metaAttrs[key])}"`;
472
529
  }
473
- return value;
530
+ html += `>${nl}`;
474
531
  }
475
- isReactiveWrapper(vNode) {
476
- if (!vNode || typeof vNode !== "object" || !vNode.tagName) {
477
- return false;
532
+ for (const linkAttrs of links) {
533
+ html += `${indent2}<link`;
534
+ for (const key in linkAttrs) {
535
+ html += ` ${key}="${escapeHtml(linkAttrs[key])}"`;
478
536
  }
479
- return vNode.tagName === "span" && vNode.props?.id && typeof vNode.props.id === "string" && vNode.props.id.match(/^r[a-z0-9]{9}$/);
537
+ html += `>${nl}`;
480
538
  }
481
- unwrapReactive(vNode) {
482
- if (!this.isReactiveWrapper(vNode)) {
483
- return vNode;
539
+ for (const style of styles) {
540
+ if (style.href) {
541
+ html += `${indent2}<link rel="stylesheet" href="${escapeHtml(style.href)}">${nl}`;
542
+ } else if (style.content) {
543
+ html += `${indent2}<style>${style.content}</style>${nl}`;
484
544
  }
485
- const children = vNode.children;
486
- if (!children || children.length === 0) {
487
- return "";
545
+ }
546
+ if (head) {
547
+ html += head + nl;
548
+ }
549
+ html += `${indent}</head>${nl}${indent}<body`;
550
+ for (const key in bodyAttrs) {
551
+ html += ` ${key}="${escapeHtml(bodyAttrs[key])}"`;
552
+ }
553
+ html += `>${nl}`;
554
+ html += renderToString(vNode, { pretty, indent: 2 });
555
+ for (const script of scripts) {
556
+ html += `${indent2}<script`;
557
+ if (script.type) {
558
+ html += ` type="${escapeHtml(script.type)}"`;
488
559
  }
489
- if (children.length === 1) {
490
- const child = children[0];
491
- if (child && typeof child === "object" && child.tagName === "span") {
492
- const props = child.props;
493
- const hasNoProps = !props || Object.keys(props).length === 0;
494
- const hasSingleStringChild = child.children && child.children.length === 1 && typeof child.children[0] === "string";
495
- if (hasNoProps && hasSingleStringChild) {
496
- return child.children[0];
497
- }
498
- }
499
- return this.unwrapReactive(child);
560
+ if (script.async) {
561
+ html += " async";
500
562
  }
501
- return children.map((c) => this.unwrapReactive(c));
502
- }
503
- escapeHtml(text2) {
504
- const htmlEscapes = {
505
- "&": "&amp;",
506
- "<": "&lt;",
507
- ">": "&gt;",
508
- '"': "&quot;",
509
- "'": "&#x27;"
510
- };
511
- return text2.replace(/[&<>"']/g, (char) => htmlEscapes[char]);
512
- }
513
- isSelfClosingTag(tagName) {
514
- const selfClosingTags = /* @__PURE__ */ new Set([
515
- "area",
516
- "base",
517
- "br",
518
- "col",
519
- "embed",
520
- "hr",
521
- "img",
522
- "input",
523
- "link",
524
- "meta",
525
- "param",
526
- "source",
527
- "track",
528
- "wbr"
529
- ]);
530
- return selfClosingTags.has(tagName.toLowerCase());
531
- }
532
- propsToAttributes(props, tagName) {
533
- const attrs = [];
534
- for (const key in props) {
535
- if (key === "children" || key === "dangerouslySetInnerHTML" || key === "ref" || tagName === "textarea" && key === "value") {
536
- continue;
537
- }
538
- let value = props[key];
539
- value = this.resolveStateValue(value);
540
- if (value == null || value === false) continue;
541
- if (key.startsWith("on") && typeof value === "function") {
542
- continue;
543
- }
544
- if (key === "className" || key === "class") {
545
- const className = Array.isArray(value) ? value.join(" ") : value;
546
- if (className) {
547
- attrs.push(`class="${this.escapeHtml(String(className))}"`);
548
- }
549
- continue;
550
- }
551
- if (key === "style") {
552
- const styleStr = this.styleToString(value);
553
- if (styleStr) {
554
- attrs.push(`style="${this.escapeHtml(styleStr)}"`);
563
+ if (script.defer) {
564
+ html += " defer";
565
+ }
566
+ if (script.src) {
567
+ html += ` src="${escapeHtml(script.src)}"></script>${nl}`;
568
+ } else if (script.content) {
569
+ html += `>${script.content}</script>${nl}`;
570
+ } else {
571
+ html += `></script>${nl}`;
572
+ }
573
+ }
574
+ html += `${indent}</body>${nl}</html>`;
575
+ return html;
576
+ }
577
+
578
+ // src/client/dom/json.ts
579
+ function jsonToVNode(json, reactiveNodes) {
580
+ if (isState(json)) {
581
+ return createReactiveChild(json, reactiveNodes, (value) => value);
582
+ }
583
+ if (isPrimitiveJson(json)) {
584
+ return json;
585
+ }
586
+ const { tag, attributes = {}, children } = json;
587
+ const props = {};
588
+ for (const key in attributes) {
589
+ const value = attributes[key];
590
+ if (key === "class") {
591
+ props.className = isState(value) ? value.value : value;
592
+ } else {
593
+ props[key] = isState(value) ? value.value : value;
594
+ }
595
+ }
596
+ const childrenArray = [];
597
+ if (children != null) {
598
+ if (Array.isArray(children)) {
599
+ for (const child of children) {
600
+ if (isState(child)) {
601
+ childrenArray.push(createReactiveChild(child, reactiveNodes, (value) => value));
602
+ } else {
603
+ const converted = jsonToVNode(child, reactiveNodes);
604
+ if (converted != null && converted !== false) {
605
+ childrenArray.push(converted);
606
+ }
555
607
  }
556
- continue;
557
608
  }
558
- if (value === true) {
559
- attrs.push(key);
560
- continue;
609
+ } else if (isState(children)) {
610
+ childrenArray.push(createReactiveChild(children, reactiveNodes, (value) => value));
611
+ } else if (typeof children === "object" && children !== null && "tag" in children) {
612
+ const converted = jsonToVNode(children, reactiveNodes);
613
+ if (converted != null && converted !== false) {
614
+ childrenArray.push(converted);
561
615
  }
562
- attrs.push(`${key}="${this.escapeHtml(String(value))}"`);
616
+ } else {
617
+ childrenArray.push(children);
563
618
  }
564
- return attrs.join(" ");
565
619
  }
566
- styleToString(style) {
567
- if (typeof style === "string") {
568
- return style;
569
- }
570
- if (typeof style === "object" && style !== null) {
571
- const styles = [];
572
- for (const key in style) {
573
- const cssKey = key.replace(/([A-Z])/g, "-$1").toLowerCase();
574
- styles.push(`${cssKey}:${style[key]}`);
620
+ return { tagName: tag, props, children: childrenArray };
621
+ }
622
+ function vNodeJsonToVNode(json, reactiveNodes) {
623
+ if (isState(json)) {
624
+ return createReactiveChild(json, reactiveNodes, (value) => value);
625
+ }
626
+ if (isPrimitiveJson(json)) {
627
+ return json;
628
+ }
629
+ const { tagName, props = {}, children = [] } = json;
630
+ const resolvedProps = {};
631
+ for (const key in props) {
632
+ const value = props[key];
633
+ resolvedProps[key] = isState(value) ? value.value : value;
634
+ }
635
+ const childrenArray = [];
636
+ for (const child of children) {
637
+ if (isState(child)) {
638
+ childrenArray.push(createReactiveChild(child, reactiveNodes, (value) => value));
639
+ } else {
640
+ const converted = vNodeJsonToVNode(child, reactiveNodes);
641
+ if (converted != null && converted !== false) {
642
+ childrenArray.push(converted);
575
643
  }
576
- return styles.join(";");
577
644
  }
578
- return "";
579
645
  }
580
- isState(value) {
581
- return value && typeof value === "object" && "value" in value && "subscribe" in value && typeof value.subscribe === "function";
582
- }
583
- createReactiveChild(state, renderFn) {
584
- const currentValue = renderFn(state.value);
585
- if (typeof window !== "undefined" && typeof document !== "undefined") {
586
- const entry = { node: null, renderFn };
587
- this.reactiveNodes.set(state, entry);
588
- state.subscribe(() => {
589
- if (entry.node && entry.node.parentNode) {
590
- const newValue = renderFn(state.value);
591
- entry.node.textContent = String(newValue ?? "");
592
- }
593
- });
594
- }
595
- return currentValue;
646
+ return { tagName, props: resolvedProps, children: childrenArray };
647
+ }
648
+ function renderJson(rootElement, json, reactiveNodes) {
649
+ const vNode = jsonToVNode(json, reactiveNodes);
650
+ if (!vNode || typeof vNode !== "object" || !("tagName" in vNode)) {
651
+ throw new Error("Invalid JSON structure");
596
652
  }
597
- jsonToVNode(json) {
598
- if (this.isState(json)) {
599
- return this.createReactiveChild(json, (v) => v);
600
- }
601
- if (isPrimitiveJson(json)) {
602
- return json;
603
- }
604
- const { tag, attributes = {}, children } = json;
605
- const props = {};
606
- for (const key in attributes) {
607
- const value = attributes[key];
608
- if (key === "class") {
609
- props.className = this.isState(value) ? value.value : value;
610
- } else {
611
- props[key] = this.isState(value) ? value.value : value;
653
+ return render(rootElement, vNode);
654
+ }
655
+ function renderVNode(rootElement, json, reactiveNodes) {
656
+ const vNode = vNodeJsonToVNode(json, reactiveNodes);
657
+ if (!vNode || typeof vNode !== "object" || !("tagName" in vNode)) {
658
+ throw new Error("Invalid VNode JSON structure");
659
+ }
660
+ return render(rootElement, vNode);
661
+ }
662
+ function renderJsonToString(json, reactiveNodes, options = {}) {
663
+ const vNode = jsonToVNode(json, reactiveNodes);
664
+ return renderToString(vNode, options);
665
+ }
666
+ function renderVNodeToString(json, reactiveNodes, options = {}) {
667
+ const vNode = vNodeJsonToVNode(json, reactiveNodes);
668
+ return renderToString(vNode, options);
669
+ }
670
+
671
+ // src/client/dom/state-utils.ts
672
+ function createState(initialValue, options = {}) {
673
+ let value = initialValue;
674
+ const listeners = /* @__PURE__ */ new Set();
675
+ let updateTimer = null;
676
+ const { throttle: throttle2 = 0, deep = false } = options;
677
+ const notify = () => listeners.forEach((listener) => listener(value));
678
+ const scheduleUpdate = () => {
679
+ if (throttle2 > 0) {
680
+ if (!updateTimer) {
681
+ updateTimer = setTimeout(() => {
682
+ updateTimer = null;
683
+ notify();
684
+ }, throttle2);
612
685
  }
686
+ } else {
687
+ notify();
613
688
  }
614
- const childrenArray = [];
615
- if (children != null) {
616
- if (Array.isArray(children)) {
617
- for (const child of children) {
618
- if (this.isState(child)) {
619
- childrenArray.push(this.createReactiveChild(child, (v) => v));
620
- } else {
621
- const converted = this.jsonToVNode(child);
622
- if (converted != null && converted !== false) {
623
- childrenArray.push(converted);
624
- }
625
- }
626
- }
627
- } else if (this.isState(children)) {
628
- childrenArray.push(this.createReactiveChild(children, (v) => v));
629
- } else if (typeof children === "object" && "tag" in children) {
630
- const converted = this.jsonToVNode(children);
631
- if (converted != null && converted !== false) {
632
- childrenArray.push(converted);
633
- }
634
- } else {
635
- childrenArray.push(children);
689
+ };
690
+ return {
691
+ get value() {
692
+ return value;
693
+ },
694
+ set value(newValue) {
695
+ const changed = deep ? JSON.stringify(value) !== JSON.stringify(newValue) : value !== newValue;
696
+ if (changed) {
697
+ value = newValue;
698
+ scheduleUpdate();
699
+ }
700
+ },
701
+ subscribe(fn) {
702
+ listeners.add(fn);
703
+ return () => listeners.delete(fn);
704
+ },
705
+ destroy() {
706
+ listeners.clear();
707
+ if (updateTimer) {
708
+ clearTimeout(updateTimer);
636
709
  }
637
710
  }
638
- return { tagName: tag, props, children: childrenArray };
639
- }
640
- vNodeJsonToVNode(json) {
641
- if (this.isState(json)) {
642
- return this.createReactiveChild(json, (v) => v);
643
- }
644
- if (isPrimitiveJson(json)) {
645
- return json;
711
+ };
712
+ }
713
+ function computed(states, computeFn) {
714
+ const values = states.map((state) => state.value);
715
+ const result = createState(computeFn(...values));
716
+ states.forEach((state, index) => {
717
+ state.subscribe((newValue) => {
718
+ values[index] = newValue;
719
+ result.value = computeFn(...values);
720
+ });
721
+ });
722
+ return result;
723
+ }
724
+ function effect(stateFn) {
725
+ stateFn();
726
+ }
727
+ function createVirtualList(container, items, renderItem, itemHeight = 50, bufferSize = 5) {
728
+ const viewportHeight = container.clientHeight;
729
+ const totalHeight = items.length * itemHeight;
730
+ let scrollTop = 0;
731
+ const getVisibleRange = () => {
732
+ const start = Math.max(0, Math.floor(scrollTop / itemHeight) - bufferSize);
733
+ const end = Math.min(items.length, Math.ceil((scrollTop + viewportHeight) / itemHeight) + bufferSize);
734
+ return { start, end };
735
+ };
736
+ const render3 = () => {
737
+ const { start, end } = getVisibleRange();
738
+ const wrapper = document.createElement("div");
739
+ wrapper.style.cssText = `height:${totalHeight}px;position:relative`;
740
+ for (let i = start; i < end; i++) {
741
+ const itemEl = document.createElement("div");
742
+ itemEl.style.cssText = `position:absolute;top:${i * itemHeight}px;height:${itemHeight}px;width:100%`;
743
+ renderToDOM(renderItem(items[i], i), itemEl);
744
+ wrapper.appendChild(itemEl);
646
745
  }
647
- const { tagName, props = {}, children = [] } = json;
648
- const resolvedProps = {};
649
- for (const key in props) {
650
- const value = props[key];
651
- resolvedProps[key] = this.isState(value) ? value.value : value;
746
+ container.innerHTML = "";
747
+ container.appendChild(wrapper);
748
+ };
749
+ const scrollHandler = () => {
750
+ scrollTop = container.scrollTop;
751
+ requestAnimationFrame(render3);
752
+ };
753
+ container.addEventListener("scroll", scrollHandler);
754
+ render3();
755
+ return {
756
+ render: render3,
757
+ destroy: () => {
758
+ container.removeEventListener("scroll", scrollHandler);
759
+ container.innerHTML = "";
652
760
  }
653
- const childrenArray = [];
654
- for (const child of children) {
655
- if (this.isState(child)) {
656
- childrenArray.push(this.createReactiveChild(child, (v) => v));
657
- } else {
658
- const converted = this.vNodeJsonToVNode(child);
659
- if (converted != null && converted !== false) {
660
- childrenArray.push(converted);
661
- }
662
- }
761
+ };
762
+ }
763
+ function lazy(loadFn) {
764
+ let component = null;
765
+ let loading = false;
766
+ return async (...args) => {
767
+ if (!component && !loading) {
768
+ loading = true;
769
+ component = await loadFn();
770
+ loading = false;
663
771
  }
664
- return { tagName, props: resolvedProps, children: childrenArray };
772
+ return component ? component(...args) : { tagName: "div", props: { class: "loading" }, children: ["Loading..."] };
773
+ };
774
+ }
775
+
776
+ // src/client/dom/index.ts
777
+ var DomNode = class {
778
+ constructor() {
779
+ this.elementCache = /* @__PURE__ */ new WeakMap();
780
+ this.reactiveNodes = /* @__PURE__ */ new Map();
781
+ }
782
+ createElement(tagName, props = {}, children = []) {
783
+ return { tagName, props, children };
784
+ }
785
+ renderToDOM(vNode, parent) {
786
+ return renderToDOM(vNode, parent);
787
+ }
788
+ render(rootElement, vNode) {
789
+ return render(rootElement, vNode);
790
+ }
791
+ batchRender(rootElement, vNodes) {
792
+ return batchRender(rootElement, vNodes);
793
+ }
794
+ renderChunked(rootElement, vNodes, chunkSize = 5e3, onProgress) {
795
+ return renderChunked(rootElement, vNodes, chunkSize, onProgress);
796
+ }
797
+ renderToHead(...vNodes) {
798
+ return renderToHead(...vNodes);
799
+ }
800
+ addStyle(cssText) {
801
+ return addStyle(cssText);
802
+ }
803
+ addMeta(attrs) {
804
+ return addMeta(attrs);
805
+ }
806
+ addLink(attrs) {
807
+ return addLink(attrs);
808
+ }
809
+ setTitle(text2) {
810
+ return setTitle(text2);
811
+ }
812
+ // Reactive State Management
813
+ createState(initialValue, options = {}) {
814
+ return createState(initialValue, options);
815
+ }
816
+ computed(states, computeFn) {
817
+ return computed(states, computeFn);
818
+ }
819
+ effect(stateFn) {
820
+ effect(stateFn);
821
+ }
822
+ // Virtual scrolling helper for large lists
823
+ createVirtualList(container, items, renderItem, itemHeight = 50, bufferSize = 5) {
824
+ return createVirtualList(container, items, renderItem, itemHeight, bufferSize);
825
+ }
826
+ // Lazy load components
827
+ lazy(loadFn) {
828
+ return lazy(loadFn);
829
+ }
830
+ // Memory management - cleanup unused elements
831
+ cleanupUnusedElements(root) {
832
+ return cleanupUnusedElements(root, this.elementCache);
833
+ }
834
+ // Server-Side Rendering - convert VNode to HTML string
835
+ renderToString(vNode, options = {}) {
836
+ return renderToString(vNode, options);
837
+ }
838
+ jsonToVNode(json) {
839
+ return jsonToVNode(json, this.reactiveNodes);
840
+ }
841
+ vNodeJsonToVNode(json) {
842
+ return vNodeJsonToVNode(json, this.reactiveNodes);
665
843
  }
666
844
  renderJson(rootElement, json) {
667
- const vNode = this.jsonToVNode(json);
668
- if (!vNode || typeof vNode !== "object" || !("tagName" in vNode)) {
669
- throw new Error("Invalid JSON structure");
670
- }
671
- return this.render(rootElement, vNode);
845
+ return renderJson(rootElement, json, this.reactiveNodes);
672
846
  }
673
847
  renderVNode(rootElement, json) {
674
- const vNode = this.vNodeJsonToVNode(json);
675
- if (!vNode || typeof vNode !== "object" || !("tagName" in vNode)) {
676
- throw new Error("Invalid VNode JSON structure");
677
- }
678
- return this.render(rootElement, vNode);
848
+ return renderVNode(rootElement, json, this.reactiveNodes);
679
849
  }
680
850
  renderJsonToString(json, options = {}) {
681
- const vNode = this.jsonToVNode(json);
682
- return this.renderToString(vNode, options);
851
+ return renderJsonToString(json, this.reactiveNodes, options);
683
852
  }
684
853
  renderVNodeToString(json, options = {}) {
685
- const vNode = this.vNodeJsonToVNode(json);
686
- return this.renderToString(vNode, options);
854
+ return renderVNodeToString(json, this.reactiveNodes, options);
687
855
  }
688
856
  // Generate complete HTML document as string (for SSR)
689
857
  renderToHTMLDocument(vNode, options = {}) {
690
- const { title = "", meta = [], links = [], scripts = [], styles = [], lang = "en", head = "", bodyAttrs = {}, pretty = false } = options;
691
- const nl = pretty ? "\n" : "";
692
- const indent = pretty ? " " : "";
693
- const indent2 = pretty ? " " : "";
694
- let html = `<!DOCTYPE html>${nl}<html lang="${lang}">${nl}${indent}<head>${nl}${indent2}<meta charset="UTF-8">${nl}${indent2}<meta name="viewport" content="width=device-width, initial-scale=1.0">${nl}`;
695
- if (title) html += `${indent2}<title>${this.escapeHtml(title)}</title>${nl}`;
696
- for (const m of meta) {
697
- html += `${indent2}<meta`;
698
- for (const k in m) html += ` ${k}="${this.escapeHtml(m[k])}"`;
699
- html += `>${nl}`;
700
- }
701
- for (const l of links) {
702
- html += `${indent2}<link`;
703
- for (const k in l) html += ` ${k}="${this.escapeHtml(l[k])}"`;
704
- html += `>${nl}`;
705
- }
706
- for (const s of styles) {
707
- if (s.href) {
708
- html += `${indent2}<link rel="stylesheet" href="${this.escapeHtml(s.href)}">${nl}`;
709
- } else if (s.content) {
710
- html += `${indent2}<style>${s.content}</style>${nl}`;
711
- }
712
- }
713
- if (head) html += head + nl;
714
- html += `${indent}</head>${nl}${indent}<body`;
715
- for (const k in bodyAttrs) html += ` ${k}="${this.escapeHtml(bodyAttrs[k])}"`;
716
- html += `>${nl}`;
717
- html += this.renderToString(vNode, { pretty, indent: 2 });
718
- for (const script of scripts) {
719
- html += `${indent2}<script`;
720
- if (script.type) html += ` type="${this.escapeHtml(script.type)}"`;
721
- if (script.async) html += ` async`;
722
- if (script.defer) html += ` defer`;
723
- if (script.src) {
724
- html += ` src="${this.escapeHtml(script.src)}"></script>${nl}`;
725
- } else if (script.content) {
726
- html += `>${script.content}</script>${nl}`;
727
- } else {
728
- html += `></script>${nl}`;
729
- }
730
- }
731
- html += `${indent}</body>${nl}</html>`;
732
- return html;
858
+ return renderToHTMLDocument(vNode, options);
733
859
  }
734
860
  // Expose elementCache for reactive updates
735
861
  getElementCache() {
@@ -737,20 +863,20 @@ var DomNode = class {
737
863
  }
738
864
  };
739
865
  var dom = new DomNode();
740
- var render = dom.render.bind(dom);
741
- var renderToString = dom.renderToString.bind(dom);
866
+ var render2 = dom.render.bind(dom);
867
+ var renderToString2 = dom.renderToString.bind(dom);
742
868
 
743
- // src/state.ts
744
- var ELIT_NATIVE_BINDING = /* @__PURE__ */ Symbol.for("elit.native.binding");
745
- var ELIT_INTERNAL_WS_PATH = "/__elit_ws";
746
- var createState = (initial, options) => dom.createState(initial, options);
747
- var computed = (states, fn) => dom.computed(states, fn);
748
- var effect = (fn) => dom.effect(fn);
749
- var batchRender = (container, vNodes) => dom.batchRender(container, vNodes);
750
- var renderChunked = (container, vNodes, chunkSize, onProgress) => dom.renderChunked(container, vNodes, chunkSize, onProgress);
751
- var createVirtualList = (container, items, renderItem, itemHeight, bufferSize) => dom.createVirtualList(container, items, renderItem, itemHeight, bufferSize);
752
- var lazy = (loadFn) => dom.lazy(loadFn);
869
+ // src/client/state/core.ts
870
+ var createState2 = (initial, options) => dom.createState(initial, options);
871
+ var computed2 = (states, fn) => dom.computed(states, fn);
872
+ var effect2 = (fn) => dom.effect(fn);
873
+ var batchRender2 = (container, vNodes) => dom.batchRender(container, vNodes);
874
+ var renderChunked2 = (container, vNodes, chunkSize, onProgress) => dom.renderChunked(container, vNodes, chunkSize, onProgress);
875
+ var createVirtualList2 = (container, items, renderItem, itemHeight, bufferSize) => dom.createVirtualList(container, items, renderItem, itemHeight, bufferSize);
876
+ var lazy2 = (loadFn) => dom.lazy(loadFn);
753
877
  var cleanupUnused = (root) => dom.cleanupUnusedElements(root);
878
+
879
+ // src/client/state/timing.ts
754
880
  var throttle = (fn, delay) => {
755
881
  let timer = null;
756
882
  return (...args) => {
@@ -765,10 +891,15 @@ var throttle = (fn, delay) => {
765
891
  var debounce = (fn, delay) => {
766
892
  let timer = null;
767
893
  return (...args) => {
768
- timer && clearTimeout(timer);
894
+ if (timer) {
895
+ clearTimeout(timer);
896
+ }
769
897
  timer = setTimeout(() => fn(...args), delay);
770
898
  };
771
899
  };
900
+
901
+ // src/client/state/bindings.ts
902
+ var ELIT_NATIVE_BINDING = /* @__PURE__ */ Symbol.for("elit.native.binding");
772
903
  function bindValue(state) {
773
904
  const props = {
774
905
  value: state.value,
@@ -808,6 +939,9 @@ function bindChecked(state) {
808
939
  };
809
940
  return props;
810
941
  }
942
+
943
+ // src/client/state/shared-state.ts
944
+ var ELIT_INTERNAL_WS_PATH = "/__elit_ws";
811
945
  function resolveSharedStateWebSocketUrl(wsUrl) {
812
946
  const protocol = typeof location !== "undefined" && location.protocol === "https:" ? "wss:" : "ws:";
813
947
  const origin = typeof location !== "undefined" ? `${protocol}//${location.host}` : `${protocol}//localhost`;
@@ -832,33 +966,21 @@ var SharedState = class {
832
966
  this.wsUrl = wsUrl;
833
967
  this.ws = null;
834
968
  this.pendingUpdates = [];
835
- this.localState = createState(defaultValue);
969
+ this.localState = createState2(defaultValue);
836
970
  this.previousValue = defaultValue;
837
971
  this.connect();
838
972
  }
839
- /**
840
- * Get current value
841
- */
842
973
  get value() {
843
974
  return this.localState.value;
844
975
  }
845
- /**
846
- * Set new value and sync to server
847
- */
848
976
  set value(newValue) {
849
977
  this.previousValue = this.localState.value;
850
978
  this.localState.value = newValue;
851
979
  this.sendToServer(newValue);
852
980
  }
853
- /**
854
- * Get the underlying Elit State (for reactive binding)
855
- */
856
981
  get state() {
857
982
  return this.localState;
858
983
  }
859
- /**
860
- * Subscribe to changes (returns Elit State for reactive)
861
- */
862
984
  onChange(callback) {
863
985
  return this.localState.subscribe((newValue) => {
864
986
  const oldValue = this.previousValue;
@@ -866,17 +988,13 @@ var SharedState = class {
866
988
  callback(newValue, oldValue);
867
989
  });
868
990
  }
869
- /**
870
- * Update value using a function
871
- */
872
991
  update(updater) {
873
992
  this.value = updater(this.value);
874
993
  }
875
- /**
876
- * Connect to WebSocket
877
- */
878
994
  connect() {
879
- if (typeof window === "undefined") return;
995
+ if (typeof window === "undefined") {
996
+ return;
997
+ }
880
998
  const url = resolveSharedStateWebSocketUrl(this.wsUrl);
881
999
  this.ws = new WebSocket(url);
882
1000
  this.ws.addEventListener("open", () => {
@@ -896,34 +1014,31 @@ var SharedState = class {
896
1014
  console.error("[SharedState] WebSocket error:", error);
897
1015
  });
898
1016
  }
899
- /**
900
- * Subscribe to server state
901
- */
902
1017
  subscribe() {
903
- if (!this.ws || this.ws.readyState !== WebSocket.OPEN) return;
1018
+ if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {
1019
+ return;
1020
+ }
904
1021
  this.ws.send(JSON.stringify({
905
1022
  type: "state:subscribe",
906
1023
  key: this.key
907
1024
  }));
908
1025
  }
909
- /**
910
- * Handle message from server
911
- */
912
1026
  handleMessage(data) {
913
1027
  try {
914
1028
  const msg = JSON.parse(data);
915
- if (msg.key !== this.key) return;
1029
+ if (msg.key !== this.key) {
1030
+ return;
1031
+ }
916
1032
  if (msg.type === "state:init" || msg.type === "state:update") {
917
1033
  this.localState.value = msg.value;
918
1034
  }
919
1035
  } catch (error) {
920
1036
  }
921
1037
  }
922
- /**
923
- * Send value to server
924
- */
925
1038
  sendToServer(value) {
926
- if (!this.ws) return;
1039
+ if (!this.ws) {
1040
+ return;
1041
+ }
927
1042
  if (this.ws.readyState !== WebSocket.OPEN) {
928
1043
  this.pendingUpdates.push(value);
929
1044
  return;
@@ -934,18 +1049,12 @@ var SharedState = class {
934
1049
  value
935
1050
  }));
936
1051
  }
937
- /**
938
- * Disconnect
939
- */
940
1052
  disconnect() {
941
1053
  if (this.ws) {
942
1054
  this.ws.close();
943
1055
  this.ws = null;
944
1056
  }
945
1057
  }
946
- /**
947
- * Destroy state and cleanup
948
- */
949
1058
  destroy() {
950
1059
  this.disconnect();
951
1060
  this.localState.destroy();
@@ -958,9 +1067,6 @@ var SharedStateManager = class {
958
1067
  constructor() {
959
1068
  this.states = /* @__PURE__ */ new Map();
960
1069
  }
961
- /**
962
- * Create or get a shared state
963
- */
964
1070
  create(key, defaultValue, wsUrl) {
965
1071
  if (this.states.has(key)) {
966
1072
  return this.states.get(key);
@@ -969,15 +1075,9 @@ var SharedStateManager = class {
969
1075
  this.states.set(key, state);
970
1076
  return state;
971
1077
  }
972
- /**
973
- * Get existing state
974
- */
975
1078
  get(key) {
976
1079
  return this.states.get(key);
977
1080
  }
978
- /**
979
- * Delete a state
980
- */
981
1081
  delete(key) {
982
1082
  const state = this.states.get(key);
983
1083
  if (state) {
@@ -986,17 +1086,18 @@ var SharedStateManager = class {
986
1086
  }
987
1087
  return false;
988
1088
  }
989
- /**
990
- * Clear all states
991
- */
992
1089
  clear() {
993
1090
  this.states.forEach((state) => state.destroy());
994
1091
  this.states.clear();
995
1092
  }
996
1093
  };
997
1094
  var sharedStateManager = new SharedStateManager();
1095
+
1096
+ // src/client/state/reactive-utils.ts
998
1097
  var scheduleRAFUpdate = (rafId, updateFn) => {
999
- rafId && cancelAnimationFrame(rafId);
1098
+ if (rafId) {
1099
+ cancelAnimationFrame(rafId);
1100
+ }
1000
1101
  return requestAnimationFrame(() => {
1001
1102
  updateFn();
1002
1103
  });
@@ -1020,12 +1121,16 @@ var renderToFragment = (content, isVNode) => {
1020
1121
  var updateElementProps = (element, props) => {
1021
1122
  for (const key in props) {
1022
1123
  const value = props[key];
1023
- if (key === "ref") continue;
1124
+ if (key === "ref") {
1125
+ continue;
1126
+ }
1024
1127
  if (key === "class" || key === "className") {
1025
1128
  element.className = Array.isArray(value) ? value.join(" ") : value || "";
1026
1129
  } else if (key === "style" && typeof value === "object") {
1027
- const s = element.style;
1028
- for (const k in value) s[k] = value[k];
1130
+ const style = element.style;
1131
+ for (const styleKey in value) {
1132
+ style[styleKey] = value[styleKey];
1133
+ }
1029
1134
  } else if (key.startsWith("on")) {
1030
1135
  element[key.toLowerCase()] = value;
1031
1136
  } else if (value != null && value !== false) {
@@ -1035,6 +1140,8 @@ var updateElementProps = (element, props) => {
1035
1140
  }
1036
1141
  }
1037
1142
  };
1143
+
1144
+ // src/client/state/reactive.ts
1038
1145
  var reactive = (state, renderFn) => {
1039
1146
  let rafId = null;
1040
1147
  let elementRef = null;
@@ -1044,7 +1151,9 @@ var reactive = (state, renderFn) => {
1044
1151
  const isVNodeResult = initialResult && typeof initialResult === "object" && "tagName" in initialResult;
1045
1152
  const initialIsNull = initialResult == null || initialResult === false;
1046
1153
  const updateElement = () => {
1047
- if (!elementRef && !placeholder) return;
1154
+ if (!elementRef && !placeholder) {
1155
+ return;
1156
+ }
1048
1157
  const newResult = renderFn(state.value);
1049
1158
  const resultIsNull = newResult == null || newResult === false;
1050
1159
  if (resultIsNull) {
@@ -1125,24 +1234,24 @@ var reactiveAs = (tagName, state, renderFn, props = {}) => {
1125
1234
  const initialChildren = Array.isArray(initialResult) ? initialResult : [initialResult];
1126
1235
  return { tagName, props: { ...props, ref: refCallback }, children: initialChildren };
1127
1236
  };
1128
- var text = (state) => state && state.value !== void 0 ? reactive(state, (v) => ({ tagName: "span", props: {}, children: [String(v)] })) : String(state);
1237
+ var text = (state) => state && state.value !== void 0 ? reactive(state, (value) => ({ tagName: "span", props: {}, children: [String(value)] })) : String(state);
1129
1238
  export {
1130
1239
  ELIT_NATIVE_BINDING,
1131
1240
  SharedState,
1132
- batchRender,
1241
+ batchRender2 as batchRender,
1133
1242
  bindChecked,
1134
1243
  bindValue,
1135
1244
  cleanupUnused,
1136
- computed,
1245
+ computed2 as computed,
1137
1246
  createSharedState,
1138
- createState,
1139
- createVirtualList,
1247
+ createState2 as createState,
1248
+ createVirtualList2 as createVirtualList,
1140
1249
  debounce,
1141
- effect,
1142
- lazy,
1250
+ effect2 as effect,
1251
+ lazy2 as lazy,
1143
1252
  reactive,
1144
1253
  reactiveAs,
1145
- renderChunked,
1254
+ renderChunked2 as renderChunked,
1146
1255
  sharedStateManager,
1147
1256
  text,
1148
1257
  throttle