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