@qorejs/qore 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +1193 -0
- package/dist/index.js.map +1 -0
- package/package.json +76 -0
- package/src/component.ts +26 -0
- package/src/error.ts +144 -0
- package/src/index.ts +95 -0
- package/src/render.ts +286 -0
- package/src/signal.ts +213 -0
- package/src/ssr.ts +341 -0
- package/src/stream.ts +432 -0
- package/src/utils.ts +116 -0
- package/src/virtual-list.ts +405 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,1193 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
3
|
+
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
4
|
+
let activeEffect = null;
|
|
5
|
+
let batchDepth = 0;
|
|
6
|
+
const pendingEffects = /* @__PURE__ */ new Set();
|
|
7
|
+
class EffectNode {
|
|
8
|
+
constructor(fn) {
|
|
9
|
+
__publicField(this, "deps", /* @__PURE__ */ new Set());
|
|
10
|
+
__publicField(this, "fn");
|
|
11
|
+
__publicField(this, "cleanup");
|
|
12
|
+
this.fn = fn;
|
|
13
|
+
}
|
|
14
|
+
run() {
|
|
15
|
+
for (const dep of this.deps) {
|
|
16
|
+
dep.subs.delete(this);
|
|
17
|
+
}
|
|
18
|
+
this.deps.clear();
|
|
19
|
+
if (this.cleanup) {
|
|
20
|
+
this.cleanup();
|
|
21
|
+
this.cleanup = void 0;
|
|
22
|
+
}
|
|
23
|
+
const prevEffect = activeEffect;
|
|
24
|
+
activeEffect = this;
|
|
25
|
+
try {
|
|
26
|
+
const result = this.fn();
|
|
27
|
+
if (typeof result === "function") {
|
|
28
|
+
this.cleanup = result;
|
|
29
|
+
}
|
|
30
|
+
} finally {
|
|
31
|
+
activeEffect = prevEffect;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
class SignalNode {
|
|
36
|
+
constructor(initial) {
|
|
37
|
+
__publicField(this, "value");
|
|
38
|
+
__publicField(this, "subs", /* @__PURE__ */ new Set());
|
|
39
|
+
this.value = initial;
|
|
40
|
+
}
|
|
41
|
+
get() {
|
|
42
|
+
if (activeEffect) {
|
|
43
|
+
this.subs.add(activeEffect);
|
|
44
|
+
activeEffect.deps.add(this);
|
|
45
|
+
}
|
|
46
|
+
return this.value;
|
|
47
|
+
}
|
|
48
|
+
set(newValue) {
|
|
49
|
+
if (this.value === newValue) return;
|
|
50
|
+
this.value = newValue;
|
|
51
|
+
this.notify();
|
|
52
|
+
}
|
|
53
|
+
notify() {
|
|
54
|
+
const effectsToRun = Array.from(this.subs);
|
|
55
|
+
if (batchDepth > 0) {
|
|
56
|
+
effectsToRun.forEach((sub) => pendingEffects.add(sub));
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
for (const effect2 of effectsToRun) {
|
|
60
|
+
effect2.run();
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
function signal(initial) {
|
|
65
|
+
const node = new SignalNode(initial);
|
|
66
|
+
const sig = (value) => {
|
|
67
|
+
if (value !== void 0) {
|
|
68
|
+
node.set(value);
|
|
69
|
+
return value;
|
|
70
|
+
}
|
|
71
|
+
return node.get();
|
|
72
|
+
};
|
|
73
|
+
sig.peek = () => {
|
|
74
|
+
const prev = activeEffect;
|
|
75
|
+
activeEffect = null;
|
|
76
|
+
try {
|
|
77
|
+
return node.get();
|
|
78
|
+
} finally {
|
|
79
|
+
activeEffect = prev;
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
return sig;
|
|
83
|
+
}
|
|
84
|
+
function computed(fn) {
|
|
85
|
+
let value;
|
|
86
|
+
let depsVersion = 0;
|
|
87
|
+
let lastReadVersion = 0;
|
|
88
|
+
const subs = /* @__PURE__ */ new Set();
|
|
89
|
+
const effectNode = new EffectNode(() => {
|
|
90
|
+
depsVersion++;
|
|
91
|
+
for (const sub of subs) {
|
|
92
|
+
if (batchDepth > 0) {
|
|
93
|
+
pendingEffects.add(sub);
|
|
94
|
+
} else {
|
|
95
|
+
sub.run();
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
const prevEffect = activeEffect;
|
|
100
|
+
activeEffect = effectNode;
|
|
101
|
+
try {
|
|
102
|
+
value = fn();
|
|
103
|
+
} finally {
|
|
104
|
+
activeEffect = prevEffect;
|
|
105
|
+
}
|
|
106
|
+
lastReadVersion = depsVersion;
|
|
107
|
+
const sig = (val) => {
|
|
108
|
+
if (val !== void 0) {
|
|
109
|
+
throw new Error("Computed signals are read-only");
|
|
110
|
+
}
|
|
111
|
+
if (activeEffect) {
|
|
112
|
+
subs.add(activeEffect);
|
|
113
|
+
}
|
|
114
|
+
if (depsVersion > lastReadVersion) {
|
|
115
|
+
const prev = activeEffect;
|
|
116
|
+
activeEffect = effectNode;
|
|
117
|
+
try {
|
|
118
|
+
value = fn();
|
|
119
|
+
} finally {
|
|
120
|
+
activeEffect = prev;
|
|
121
|
+
}
|
|
122
|
+
lastReadVersion = depsVersion;
|
|
123
|
+
}
|
|
124
|
+
return value;
|
|
125
|
+
};
|
|
126
|
+
sig.peek = () => {
|
|
127
|
+
if (depsVersion > lastReadVersion) {
|
|
128
|
+
const prev = activeEffect;
|
|
129
|
+
activeEffect = null;
|
|
130
|
+
try {
|
|
131
|
+
value = fn();
|
|
132
|
+
} finally {
|
|
133
|
+
activeEffect = prev;
|
|
134
|
+
}
|
|
135
|
+
lastReadVersion = depsVersion;
|
|
136
|
+
}
|
|
137
|
+
return value;
|
|
138
|
+
};
|
|
139
|
+
return sig;
|
|
140
|
+
}
|
|
141
|
+
function effect(fn) {
|
|
142
|
+
const node = new EffectNode(fn);
|
|
143
|
+
node.run();
|
|
144
|
+
return () => {
|
|
145
|
+
if (node.cleanup) {
|
|
146
|
+
node.cleanup();
|
|
147
|
+
node.cleanup = void 0;
|
|
148
|
+
}
|
|
149
|
+
for (const dep of node.deps) {
|
|
150
|
+
dep.subs.delete(node);
|
|
151
|
+
}
|
|
152
|
+
node.deps.clear();
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
function batch(fn) {
|
|
156
|
+
batchDepth++;
|
|
157
|
+
try {
|
|
158
|
+
return fn();
|
|
159
|
+
} finally {
|
|
160
|
+
batchDepth--;
|
|
161
|
+
if (batchDepth === 0) {
|
|
162
|
+
const effects = Array.from(pendingEffects);
|
|
163
|
+
pendingEffects.clear();
|
|
164
|
+
for (const eff of effects) {
|
|
165
|
+
eff.run();
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
function Portal({ children, target }) {
|
|
171
|
+
const container = typeof target === "string" ? document.querySelector(target) : target;
|
|
172
|
+
if (!container) {
|
|
173
|
+
console.warn("Portal target not found:", String(target));
|
|
174
|
+
return null;
|
|
175
|
+
}
|
|
176
|
+
const renderToPortal = () => {
|
|
177
|
+
container.innerHTML = "";
|
|
178
|
+
const vnode = typeof children === "function" ? children() : children;
|
|
179
|
+
if (Array.isArray(vnode)) {
|
|
180
|
+
vnode.forEach((node) => {
|
|
181
|
+
if (node instanceof Node) {
|
|
182
|
+
container.appendChild(node);
|
|
183
|
+
} else if (typeof node === "string" || typeof node === "number") {
|
|
184
|
+
container.appendChild(document.createTextNode(String(node)));
|
|
185
|
+
}
|
|
186
|
+
});
|
|
187
|
+
} else if (vnode instanceof Node) {
|
|
188
|
+
container.appendChild(vnode);
|
|
189
|
+
} else if (vnode != null) {
|
|
190
|
+
container.appendChild(document.createTextNode(String(vnode)));
|
|
191
|
+
}
|
|
192
|
+
};
|
|
193
|
+
if (typeof children === "function") {
|
|
194
|
+
effect(renderToPortal);
|
|
195
|
+
} else {
|
|
196
|
+
renderToPortal();
|
|
197
|
+
}
|
|
198
|
+
return null;
|
|
199
|
+
}
|
|
200
|
+
function h(type, props = null, ...children) {
|
|
201
|
+
if (typeof type === "function") {
|
|
202
|
+
return type({ ...props, children: children.length > 0 ? children.flat() : void 0 });
|
|
203
|
+
}
|
|
204
|
+
const el = document.createElement(type);
|
|
205
|
+
if (props) {
|
|
206
|
+
for (const [key, value] of Object.entries(props)) {
|
|
207
|
+
if (key.startsWith("on") && typeof value === "function") {
|
|
208
|
+
el.addEventListener(key.slice(2).toLowerCase(), value);
|
|
209
|
+
} else if (key === "className") {
|
|
210
|
+
el.className = value;
|
|
211
|
+
} else if (key === "style" && typeof value === "object") {
|
|
212
|
+
Object.assign(el.style, value);
|
|
213
|
+
} else if (key === "ref" && typeof value === "function") {
|
|
214
|
+
value(el);
|
|
215
|
+
} else if (typeof value !== "function") {
|
|
216
|
+
el.setAttribute(key, value);
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
const flatChildren = children.flat(Infinity);
|
|
221
|
+
for (const child of flatChildren) {
|
|
222
|
+
if (child != null) {
|
|
223
|
+
if (typeof child === "string" || typeof child === "number") {
|
|
224
|
+
el.appendChild(document.createTextNode(String(child)));
|
|
225
|
+
} else if (child instanceof Node) {
|
|
226
|
+
el.appendChild(child);
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
return el;
|
|
231
|
+
}
|
|
232
|
+
function text(signalOrValue) {
|
|
233
|
+
const node = document.createTextNode("");
|
|
234
|
+
if (typeof signalOrValue === "function") {
|
|
235
|
+
effect(() => {
|
|
236
|
+
node.textContent = String(signalOrValue());
|
|
237
|
+
});
|
|
238
|
+
} else {
|
|
239
|
+
node.textContent = String(signalOrValue);
|
|
240
|
+
}
|
|
241
|
+
return node;
|
|
242
|
+
}
|
|
243
|
+
function render(root, fn) {
|
|
244
|
+
let cleanup;
|
|
245
|
+
const run = () => {
|
|
246
|
+
cleanup == null ? void 0 : cleanup();
|
|
247
|
+
root.innerHTML = "";
|
|
248
|
+
const vnode = fn();
|
|
249
|
+
if (vnode instanceof Node) {
|
|
250
|
+
root.appendChild(vnode);
|
|
251
|
+
} else {
|
|
252
|
+
root.appendChild(document.createTextNode(String(vnode)));
|
|
253
|
+
}
|
|
254
|
+
};
|
|
255
|
+
const stop = effect(run);
|
|
256
|
+
cleanup = stop;
|
|
257
|
+
return stop;
|
|
258
|
+
}
|
|
259
|
+
function show(condition, fn) {
|
|
260
|
+
return condition() ? fn() : null;
|
|
261
|
+
}
|
|
262
|
+
function For(items, fn) {
|
|
263
|
+
const list = items();
|
|
264
|
+
return list.map((item, i) => fn(item, () => i));
|
|
265
|
+
}
|
|
266
|
+
const Fragment = ({ children }) => children;
|
|
267
|
+
const tag = (name) => (props = null, ...children) => h(name, props, ...children);
|
|
268
|
+
const div = tag("div");
|
|
269
|
+
const span = tag("span");
|
|
270
|
+
const button = tag("button");
|
|
271
|
+
const input = tag("input");
|
|
272
|
+
const p = tag("p");
|
|
273
|
+
const h1 = tag("h1");
|
|
274
|
+
const h2 = tag("h2");
|
|
275
|
+
const h3 = tag("h3");
|
|
276
|
+
function renderToString$1(vnode) {
|
|
277
|
+
if (vnode == null) return "";
|
|
278
|
+
if (typeof vnode === "string" || typeof vnode === "number") {
|
|
279
|
+
return String(vnode);
|
|
280
|
+
}
|
|
281
|
+
if (Array.isArray(vnode)) {
|
|
282
|
+
return vnode.map((v) => renderToString$1(v)).join("");
|
|
283
|
+
}
|
|
284
|
+
if (typeof vnode === "function") {
|
|
285
|
+
return renderToString$1(vnode());
|
|
286
|
+
}
|
|
287
|
+
if (typeof vnode === "object" && "nodeType" in vnode) {
|
|
288
|
+
const node = vnode;
|
|
289
|
+
if (node.nodeType === 1) {
|
|
290
|
+
return node.outerHTML || "";
|
|
291
|
+
}
|
|
292
|
+
return node.textContent || "";
|
|
293
|
+
}
|
|
294
|
+
if (typeof vnode === "object") {
|
|
295
|
+
return "";
|
|
296
|
+
}
|
|
297
|
+
return String(vnode);
|
|
298
|
+
}
|
|
299
|
+
function renderToStream$1(root, fn, options) {
|
|
300
|
+
const { chunkSize = 1e3, onChunk } = options || {};
|
|
301
|
+
let aborted = false;
|
|
302
|
+
const processChunk = (html2) => {
|
|
303
|
+
if (aborted) return;
|
|
304
|
+
root.write(html2);
|
|
305
|
+
onChunk == null ? void 0 : onChunk(html2);
|
|
306
|
+
};
|
|
307
|
+
const vnode = fn();
|
|
308
|
+
const html = renderToString$1(vnode);
|
|
309
|
+
if (html.length <= chunkSize) {
|
|
310
|
+
processChunk(html);
|
|
311
|
+
} else {
|
|
312
|
+
for (let i = 0; i < html.length; i += chunkSize) {
|
|
313
|
+
if (aborted) break;
|
|
314
|
+
processChunk(html.slice(i, i + chunkSize));
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
return {
|
|
318
|
+
abort: () => {
|
|
319
|
+
aborted = true;
|
|
320
|
+
}
|
|
321
|
+
};
|
|
322
|
+
}
|
|
323
|
+
async function renderAsync(vnode) {
|
|
324
|
+
const resolved = await vnode;
|
|
325
|
+
if (resolved == null) return "";
|
|
326
|
+
if (typeof resolved === "string" || typeof resolved === "number") {
|
|
327
|
+
return String(resolved);
|
|
328
|
+
}
|
|
329
|
+
if (Array.isArray(resolved)) {
|
|
330
|
+
const results = await Promise.all(resolved.map((v) => renderAsync(v)));
|
|
331
|
+
return results.join("");
|
|
332
|
+
}
|
|
333
|
+
if (resolved instanceof Node) {
|
|
334
|
+
return resolved instanceof Element ? resolved.outerHTML : resolved.textContent || "";
|
|
335
|
+
}
|
|
336
|
+
if (typeof resolved === "function") {
|
|
337
|
+
return renderAsync(resolved());
|
|
338
|
+
}
|
|
339
|
+
return "";
|
|
340
|
+
}
|
|
341
|
+
async function renderToStreamAsync(renderer, fn) {
|
|
342
|
+
try {
|
|
343
|
+
const vnode = await fn();
|
|
344
|
+
const html = await renderAsync(vnode);
|
|
345
|
+
renderer.write(html);
|
|
346
|
+
renderer.end();
|
|
347
|
+
} catch (err) {
|
|
348
|
+
renderer.fail(err);
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
function stream(fn, options) {
|
|
352
|
+
const { container, parseMarkdown = false, onComplete, onError } = options;
|
|
353
|
+
let aborted = false;
|
|
354
|
+
let content = "";
|
|
355
|
+
container.innerHTML = "";
|
|
356
|
+
const output = document.createElement("div");
|
|
357
|
+
output.className = "stream-output";
|
|
358
|
+
container.appendChild(output);
|
|
359
|
+
const update = () => {
|
|
360
|
+
output.innerHTML = parseMarkdown ? doParseMarkdown(content) : content;
|
|
361
|
+
};
|
|
362
|
+
const write = (chunk) => {
|
|
363
|
+
if (aborted) return;
|
|
364
|
+
content += chunk;
|
|
365
|
+
update();
|
|
366
|
+
};
|
|
367
|
+
write.clear = () => {
|
|
368
|
+
content = "";
|
|
369
|
+
update();
|
|
370
|
+
};
|
|
371
|
+
write.done = () => {
|
|
372
|
+
if (!aborted) onComplete == null ? void 0 : onComplete();
|
|
373
|
+
};
|
|
374
|
+
Promise.resolve().then(() => fn(write)).catch((err) => {
|
|
375
|
+
if (!aborted) onError == null ? void 0 : onError(err);
|
|
376
|
+
});
|
|
377
|
+
return {
|
|
378
|
+
abort: () => {
|
|
379
|
+
aborted = true;
|
|
380
|
+
}
|
|
381
|
+
};
|
|
382
|
+
}
|
|
383
|
+
function doParseMarkdown(text2) {
|
|
384
|
+
return text2.replace(/^### (.*$)/gim, "<h3>$1</h3>").replace(/^## (.*$)/gim, "<h2>$1</h2>").replace(/^# (.*$)/gim, "<h1>$1</h1>").replace(/\*\*(.*)\*\*/gim, "<strong>$1</strong>").replace(/\*(.*)\*/gim, "<em>$1</em>").replace(/`([^`]+)`/gim, "<code>$1</code>").replace(/\n/gim, "<br>");
|
|
385
|
+
}
|
|
386
|
+
function streamText(text2, options) {
|
|
387
|
+
const { container, speed = 30, onComplete } = options;
|
|
388
|
+
return stream(async (write) => {
|
|
389
|
+
for (let i = 0; i < text2.length; i++) {
|
|
390
|
+
await new Promise((r) => setTimeout(r, speed));
|
|
391
|
+
write(text2[i]);
|
|
392
|
+
}
|
|
393
|
+
write.done();
|
|
394
|
+
}, { container, onComplete });
|
|
395
|
+
}
|
|
396
|
+
class StreamRenderer {
|
|
397
|
+
constructor() {
|
|
398
|
+
__publicField(this, "chunks", []);
|
|
399
|
+
__publicField(this, "callbacks", []);
|
|
400
|
+
__publicField(this, "resolved", false);
|
|
401
|
+
__publicField(this, "error", null);
|
|
402
|
+
}
|
|
403
|
+
/**
|
|
404
|
+
* Write an HTML chunk
|
|
405
|
+
*/
|
|
406
|
+
write(chunk) {
|
|
407
|
+
this.chunks.push(chunk);
|
|
408
|
+
this.callbacks.forEach((cb) => cb(chunk));
|
|
409
|
+
}
|
|
410
|
+
/**
|
|
411
|
+
* Complete stream rendering
|
|
412
|
+
*/
|
|
413
|
+
end() {
|
|
414
|
+
this.resolved = true;
|
|
415
|
+
}
|
|
416
|
+
/**
|
|
417
|
+
* Throw error
|
|
418
|
+
*/
|
|
419
|
+
fail(err) {
|
|
420
|
+
this.error = err;
|
|
421
|
+
this.resolved = true;
|
|
422
|
+
}
|
|
423
|
+
/**
|
|
424
|
+
* Subscribe to stream output
|
|
425
|
+
*/
|
|
426
|
+
subscribe(callback) {
|
|
427
|
+
this.callbacks.push(callback);
|
|
428
|
+
this.chunks.forEach((chunk) => callback(chunk));
|
|
429
|
+
return () => {
|
|
430
|
+
const idx = this.callbacks.indexOf(callback);
|
|
431
|
+
if (idx !== -1) this.callbacks.splice(idx, 1);
|
|
432
|
+
};
|
|
433
|
+
}
|
|
434
|
+
/**
|
|
435
|
+
* Get complete HTML
|
|
436
|
+
*/
|
|
437
|
+
getHTML() {
|
|
438
|
+
return this.chunks.join("");
|
|
439
|
+
}
|
|
440
|
+
/**
|
|
441
|
+
* Async iterator - for use with for await...of
|
|
442
|
+
*/
|
|
443
|
+
async *[Symbol.asyncIterator]() {
|
|
444
|
+
let index = 0;
|
|
445
|
+
while (index < this.chunks.length || !this.resolved) {
|
|
446
|
+
if (index < this.chunks.length) {
|
|
447
|
+
yield this.chunks[index++];
|
|
448
|
+
} else {
|
|
449
|
+
await new Promise((resolve) => {
|
|
450
|
+
const check = () => {
|
|
451
|
+
if (index < this.chunks.length || this.resolved) {
|
|
452
|
+
resolve(void 0);
|
|
453
|
+
} else {
|
|
454
|
+
setTimeout(check, 10);
|
|
455
|
+
}
|
|
456
|
+
};
|
|
457
|
+
check();
|
|
458
|
+
});
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
if (this.error) {
|
|
462
|
+
throw this.error;
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
function createStreamHTML() {
|
|
467
|
+
const renderer = new StreamRenderer();
|
|
468
|
+
return {
|
|
469
|
+
renderer,
|
|
470
|
+
html: () => renderer.getHTML(),
|
|
471
|
+
stream: () => renderer[Symbol.asyncIterator]()
|
|
472
|
+
};
|
|
473
|
+
}
|
|
474
|
+
function Suspense({ fallback, children, onError }) {
|
|
475
|
+
const state = signal("pending");
|
|
476
|
+
const errorSig = signal(null);
|
|
477
|
+
return () => {
|
|
478
|
+
const s = state();
|
|
479
|
+
const err = errorSig();
|
|
480
|
+
if (s === "error") {
|
|
481
|
+
onError == null ? void 0 : onError(err);
|
|
482
|
+
return fallback;
|
|
483
|
+
}
|
|
484
|
+
if (s === "pending") {
|
|
485
|
+
return fallback;
|
|
486
|
+
}
|
|
487
|
+
return children();
|
|
488
|
+
};
|
|
489
|
+
}
|
|
490
|
+
function createSuspense({ fallback, children, onError }) {
|
|
491
|
+
const state = signal("pending");
|
|
492
|
+
const errorSig = signal(null);
|
|
493
|
+
const component = () => {
|
|
494
|
+
const s = state();
|
|
495
|
+
const err = errorSig();
|
|
496
|
+
if (s === "error") {
|
|
497
|
+
onError == null ? void 0 : onError(err);
|
|
498
|
+
return fallback;
|
|
499
|
+
}
|
|
500
|
+
if (s === "pending") {
|
|
501
|
+
return fallback;
|
|
502
|
+
}
|
|
503
|
+
return children();
|
|
504
|
+
};
|
|
505
|
+
return {
|
|
506
|
+
component,
|
|
507
|
+
setState: (newState, error) => {
|
|
508
|
+
state(newState);
|
|
509
|
+
if (error) errorSig(error);
|
|
510
|
+
},
|
|
511
|
+
getState: () => state()
|
|
512
|
+
};
|
|
513
|
+
}
|
|
514
|
+
function lazy(importFn) {
|
|
515
|
+
let loadedComponent = null;
|
|
516
|
+
let loadPromise = null;
|
|
517
|
+
const load = async () => {
|
|
518
|
+
if (loadedComponent) return loadedComponent;
|
|
519
|
+
if (loadPromise) return loadPromise;
|
|
520
|
+
loadPromise = importFn().then((mod) => {
|
|
521
|
+
loadedComponent = mod.default;
|
|
522
|
+
return loadedComponent;
|
|
523
|
+
});
|
|
524
|
+
return loadPromise;
|
|
525
|
+
};
|
|
526
|
+
return () => {
|
|
527
|
+
return {
|
|
528
|
+
load,
|
|
529
|
+
component: loadedComponent
|
|
530
|
+
};
|
|
531
|
+
};
|
|
532
|
+
}
|
|
533
|
+
function asyncComponent(importFn, fallback) {
|
|
534
|
+
const lazyFactory = lazy(importFn);
|
|
535
|
+
const state = signal("pending");
|
|
536
|
+
const component = signal(null);
|
|
537
|
+
lazyFactory().load().then((comp) => {
|
|
538
|
+
component(comp);
|
|
539
|
+
state("resolved");
|
|
540
|
+
}).catch((err) => {
|
|
541
|
+
console.error("Async component load failed:", err);
|
|
542
|
+
state("error");
|
|
543
|
+
});
|
|
544
|
+
return () => {
|
|
545
|
+
if (state() === "pending") {
|
|
546
|
+
return fallback;
|
|
547
|
+
}
|
|
548
|
+
if (state() === "error") {
|
|
549
|
+
return fallback;
|
|
550
|
+
}
|
|
551
|
+
const comp = component();
|
|
552
|
+
return comp ? comp() : fallback;
|
|
553
|
+
};
|
|
554
|
+
}
|
|
555
|
+
function createUpdate(id, html, type = "replace") {
|
|
556
|
+
return { id, html, type };
|
|
557
|
+
}
|
|
558
|
+
function applyUpdate(container, update) {
|
|
559
|
+
const { id, html, type } = update;
|
|
560
|
+
const element = container.querySelector(`[data-stream-id="${id}"]`);
|
|
561
|
+
switch (type) {
|
|
562
|
+
case "replace":
|
|
563
|
+
if (element) {
|
|
564
|
+
element.outerHTML = html;
|
|
565
|
+
} else {
|
|
566
|
+
const temp = document.createElement("div");
|
|
567
|
+
temp.innerHTML = html;
|
|
568
|
+
const newEl = temp.firstElementChild;
|
|
569
|
+
if (newEl) {
|
|
570
|
+
newEl.setAttribute("data-stream-id", id);
|
|
571
|
+
container.appendChild(newEl);
|
|
572
|
+
}
|
|
573
|
+
}
|
|
574
|
+
break;
|
|
575
|
+
case "append":
|
|
576
|
+
if (element) {
|
|
577
|
+
element.insertAdjacentHTML("beforeend", html);
|
|
578
|
+
}
|
|
579
|
+
break;
|
|
580
|
+
case "prepend":
|
|
581
|
+
if (element) {
|
|
582
|
+
element.insertAdjacentHTML("afterbegin", html);
|
|
583
|
+
}
|
|
584
|
+
break;
|
|
585
|
+
case "remove":
|
|
586
|
+
if (element) {
|
|
587
|
+
element.remove();
|
|
588
|
+
}
|
|
589
|
+
break;
|
|
590
|
+
}
|
|
591
|
+
}
|
|
592
|
+
function renderToStream(container, stream2) {
|
|
593
|
+
let aborted = false;
|
|
594
|
+
(async () => {
|
|
595
|
+
try {
|
|
596
|
+
for await (const chunk of stream2) {
|
|
597
|
+
if (aborted) break;
|
|
598
|
+
try {
|
|
599
|
+
const update = JSON.parse(chunk);
|
|
600
|
+
applyUpdate(container, update);
|
|
601
|
+
} catch {
|
|
602
|
+
container.insertAdjacentHTML("beforeend", chunk);
|
|
603
|
+
}
|
|
604
|
+
}
|
|
605
|
+
} catch (err) {
|
|
606
|
+
console.error("Stream rendering error:", err);
|
|
607
|
+
}
|
|
608
|
+
})();
|
|
609
|
+
return {
|
|
610
|
+
abort: () => {
|
|
611
|
+
aborted = true;
|
|
612
|
+
}
|
|
613
|
+
};
|
|
614
|
+
}
|
|
615
|
+
function escapeHtml(str) {
|
|
616
|
+
return str.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
617
|
+
}
|
|
618
|
+
function renderToString(vnode) {
|
|
619
|
+
if (vnode == null || vnode === false) return "";
|
|
620
|
+
if (typeof vnode === "string") {
|
|
621
|
+
return escapeHtml(vnode);
|
|
622
|
+
}
|
|
623
|
+
if (typeof vnode === "number") {
|
|
624
|
+
return String(vnode);
|
|
625
|
+
}
|
|
626
|
+
if (Array.isArray(vnode)) {
|
|
627
|
+
return vnode.map((v) => renderToString(v)).join("");
|
|
628
|
+
}
|
|
629
|
+
if (typeof vnode === "function") {
|
|
630
|
+
try {
|
|
631
|
+
const result = vnode();
|
|
632
|
+
return renderToString(result);
|
|
633
|
+
} catch (err) {
|
|
634
|
+
console.error("Component render error:", err);
|
|
635
|
+
return "<!-- Error -->";
|
|
636
|
+
}
|
|
637
|
+
}
|
|
638
|
+
return "";
|
|
639
|
+
}
|
|
640
|
+
function renderComponentToString(component) {
|
|
641
|
+
return renderToString(component());
|
|
642
|
+
}
|
|
643
|
+
function createPrefetchContext() {
|
|
644
|
+
const promises = [];
|
|
645
|
+
const errors = [];
|
|
646
|
+
return {
|
|
647
|
+
promises,
|
|
648
|
+
errors,
|
|
649
|
+
add: (promise) => {
|
|
650
|
+
promises.push(
|
|
651
|
+
promise.catch((err) => {
|
|
652
|
+
errors.push(err);
|
|
653
|
+
return null;
|
|
654
|
+
})
|
|
655
|
+
);
|
|
656
|
+
},
|
|
657
|
+
waitAll: async () => {
|
|
658
|
+
await Promise.all(promises);
|
|
659
|
+
}
|
|
660
|
+
};
|
|
661
|
+
}
|
|
662
|
+
async function prefetchAndRender(prefetchFn, renderFn) {
|
|
663
|
+
const ctx = createPrefetchContext();
|
|
664
|
+
ctx.add(prefetchFn());
|
|
665
|
+
await ctx.waitAll();
|
|
666
|
+
if (ctx.errors.length > 0) {
|
|
667
|
+
console.error("Prefetch errors:", ctx.errors);
|
|
668
|
+
return "<!-- Prefetch Error -->";
|
|
669
|
+
}
|
|
670
|
+
const data = await ctx.promises[0];
|
|
671
|
+
const component = renderFn(data);
|
|
672
|
+
return renderToString(component());
|
|
673
|
+
}
|
|
674
|
+
async function renderWithSuspense(component, options) {
|
|
675
|
+
const { fallback = "<!-- Loading -->", timeoutMs = 3e4 } = options || {};
|
|
676
|
+
const timeout = new Promise((_, reject) => {
|
|
677
|
+
setTimeout(() => reject(new Error("SSR timeout")), timeoutMs);
|
|
678
|
+
});
|
|
679
|
+
const render2 = Promise.resolve().then(() => {
|
|
680
|
+
try {
|
|
681
|
+
return renderToString(component());
|
|
682
|
+
} catch (err) {
|
|
683
|
+
console.error("Suspense render error:", err);
|
|
684
|
+
return fallback;
|
|
685
|
+
}
|
|
686
|
+
});
|
|
687
|
+
try {
|
|
688
|
+
return await Promise.race([render2, timeout]);
|
|
689
|
+
} catch (err) {
|
|
690
|
+
console.error("Suspense timeout:", err);
|
|
691
|
+
return fallback;
|
|
692
|
+
}
|
|
693
|
+
}
|
|
694
|
+
async function renderSSR(component, options) {
|
|
695
|
+
const { includeState = false, state, timeoutMs } = options || {};
|
|
696
|
+
const errors = [];
|
|
697
|
+
let html;
|
|
698
|
+
try {
|
|
699
|
+
html = await renderWithSuspense(component, { timeoutMs });
|
|
700
|
+
} catch (err) {
|
|
701
|
+
errors.push(err);
|
|
702
|
+
html = "<!-- SSR Error -->";
|
|
703
|
+
}
|
|
704
|
+
const result = {
|
|
705
|
+
html,
|
|
706
|
+
errors
|
|
707
|
+
};
|
|
708
|
+
if (includeState && state) {
|
|
709
|
+
result.state = `<script>window.__QORE_STATE__ = ${JSON.stringify(state)}<\/script>`;
|
|
710
|
+
}
|
|
711
|
+
return result;
|
|
712
|
+
}
|
|
713
|
+
function VirtualList(props) {
|
|
714
|
+
const {
|
|
715
|
+
items,
|
|
716
|
+
itemHeight,
|
|
717
|
+
containerHeight,
|
|
718
|
+
renderItem,
|
|
719
|
+
overscan = 5,
|
|
720
|
+
onScroll,
|
|
721
|
+
onRangeChange,
|
|
722
|
+
className = "virtual-list",
|
|
723
|
+
getKey = (item, index) => index
|
|
724
|
+
} = props;
|
|
725
|
+
const isDynamicHeight = typeof itemHeight === "function";
|
|
726
|
+
const scrollTop = signal(0);
|
|
727
|
+
const totalHeight = computed(() => {
|
|
728
|
+
if (!isDynamicHeight) {
|
|
729
|
+
return items.length * itemHeight;
|
|
730
|
+
}
|
|
731
|
+
let height = 0;
|
|
732
|
+
for (let i = 0; i < items.length; i++) {
|
|
733
|
+
height += itemHeight(items[i], i);
|
|
734
|
+
}
|
|
735
|
+
return height;
|
|
736
|
+
});
|
|
737
|
+
const getItemHeight = (index) => {
|
|
738
|
+
if (!isDynamicHeight) {
|
|
739
|
+
return itemHeight;
|
|
740
|
+
}
|
|
741
|
+
return itemHeight(items[index], index);
|
|
742
|
+
};
|
|
743
|
+
const getItemOffset = (index) => {
|
|
744
|
+
if (!isDynamicHeight) {
|
|
745
|
+
return index * itemHeight;
|
|
746
|
+
}
|
|
747
|
+
let offset = 0;
|
|
748
|
+
for (let i = 0; i < index; i++) {
|
|
749
|
+
offset += getItemHeight(i);
|
|
750
|
+
}
|
|
751
|
+
return offset;
|
|
752
|
+
};
|
|
753
|
+
const findStartIndex = (scrollPos) => {
|
|
754
|
+
if (!isDynamicHeight) {
|
|
755
|
+
return Math.max(0, Math.floor(scrollPos / itemHeight));
|
|
756
|
+
}
|
|
757
|
+
let offset = 0;
|
|
758
|
+
for (let i = 0; i < items.length; i++) {
|
|
759
|
+
const height = getItemHeight(i);
|
|
760
|
+
if (offset + height > scrollPos) {
|
|
761
|
+
return i;
|
|
762
|
+
}
|
|
763
|
+
offset += height;
|
|
764
|
+
}
|
|
765
|
+
return items.length - 1;
|
|
766
|
+
};
|
|
767
|
+
const findEndIndex = (startIndex, scrollPos) => {
|
|
768
|
+
const viewportEnd = scrollPos + containerHeight;
|
|
769
|
+
if (!isDynamicHeight) {
|
|
770
|
+
return Math.min(
|
|
771
|
+
items.length - 1,
|
|
772
|
+
Math.ceil(viewportEnd / itemHeight)
|
|
773
|
+
);
|
|
774
|
+
}
|
|
775
|
+
let offset = getItemOffset(startIndex);
|
|
776
|
+
for (let i = startIndex; i < items.length; i++) {
|
|
777
|
+
const height = getItemHeight(i);
|
|
778
|
+
if (offset > viewportEnd) {
|
|
779
|
+
return i;
|
|
780
|
+
}
|
|
781
|
+
offset += height;
|
|
782
|
+
}
|
|
783
|
+
return items.length - 1;
|
|
784
|
+
};
|
|
785
|
+
const visibleRange = computed(() => {
|
|
786
|
+
const scrollPos = scrollTop();
|
|
787
|
+
let startIndex = findStartIndex(scrollPos);
|
|
788
|
+
let endIndex = findEndIndex(startIndex, scrollPos);
|
|
789
|
+
startIndex = Math.max(0, startIndex - overscan);
|
|
790
|
+
endIndex = Math.min(items.length - 1, endIndex + overscan);
|
|
791
|
+
return { startIndex, endIndex };
|
|
792
|
+
});
|
|
793
|
+
effect(() => {
|
|
794
|
+
const { startIndex, endIndex } = visibleRange();
|
|
795
|
+
onRangeChange == null ? void 0 : onRangeChange(startIndex, endIndex);
|
|
796
|
+
});
|
|
797
|
+
const handleScroll = (e) => {
|
|
798
|
+
const target = e.target;
|
|
799
|
+
const newScrollTop = target.scrollTop;
|
|
800
|
+
scrollTop(newScrollTop);
|
|
801
|
+
onScroll == null ? void 0 : onScroll(newScrollTop);
|
|
802
|
+
};
|
|
803
|
+
return () => {
|
|
804
|
+
const { startIndex, endIndex } = visibleRange();
|
|
805
|
+
const visibleItems = items.slice(startIndex, endIndex + 1);
|
|
806
|
+
const topSpacerHeight = getItemOffset(startIndex);
|
|
807
|
+
const bottomSpacerHeight = totalHeight() - getItemOffset(endIndex + 1);
|
|
808
|
+
return h("div", {
|
|
809
|
+
class: className,
|
|
810
|
+
style: {
|
|
811
|
+
height: containerHeight + "px",
|
|
812
|
+
overflowY: "auto",
|
|
813
|
+
position: "relative"
|
|
814
|
+
},
|
|
815
|
+
onscroll: handleScroll
|
|
816
|
+
}, [
|
|
817
|
+
// Top spacer
|
|
818
|
+
h("div", {
|
|
819
|
+
style: {
|
|
820
|
+
height: topSpacerHeight + "px",
|
|
821
|
+
flexShrink: 0
|
|
822
|
+
}
|
|
823
|
+
}),
|
|
824
|
+
// Visible items
|
|
825
|
+
...visibleItems.map((item, i) => {
|
|
826
|
+
const index = startIndex + i;
|
|
827
|
+
const key = getKey(item, index);
|
|
828
|
+
const height = getItemHeight(index);
|
|
829
|
+
return h("div", {
|
|
830
|
+
key,
|
|
831
|
+
"data-index": index,
|
|
832
|
+
style: {
|
|
833
|
+
height: height + "px",
|
|
834
|
+
flexShrink: 0
|
|
835
|
+
}
|
|
836
|
+
}, [
|
|
837
|
+
renderItem(item, index)
|
|
838
|
+
]);
|
|
839
|
+
}),
|
|
840
|
+
// Bottom spacer
|
|
841
|
+
h("div", {
|
|
842
|
+
style: {
|
|
843
|
+
height: Math.max(0, bottomSpacerHeight) + "px",
|
|
844
|
+
flexShrink: 0
|
|
845
|
+
}
|
|
846
|
+
})
|
|
847
|
+
]);
|
|
848
|
+
};
|
|
849
|
+
}
|
|
850
|
+
function InfiniteList(props) {
|
|
851
|
+
const {
|
|
852
|
+
items,
|
|
853
|
+
itemHeight,
|
|
854
|
+
containerHeight,
|
|
855
|
+
renderItem,
|
|
856
|
+
onLoadMore,
|
|
857
|
+
hasMore,
|
|
858
|
+
loading = false,
|
|
859
|
+
loadingComponent = h("div", { class: "loading" }, "Loading..."),
|
|
860
|
+
endComponent = h("div", { class: "end" }, "No more items"),
|
|
861
|
+
...listProps
|
|
862
|
+
} = props;
|
|
863
|
+
const isLoading = signal(loading);
|
|
864
|
+
const nearEnd = signal(false);
|
|
865
|
+
effect(() => {
|
|
866
|
+
if (nearEnd() && hasMore && !isLoading()) {
|
|
867
|
+
isLoading(true);
|
|
868
|
+
onLoadMore().finally(() => {
|
|
869
|
+
isLoading(false);
|
|
870
|
+
});
|
|
871
|
+
}
|
|
872
|
+
});
|
|
873
|
+
return () => {
|
|
874
|
+
const allItems = [...items];
|
|
875
|
+
if (isLoading()) {
|
|
876
|
+
allItems.push({ __loading: true });
|
|
877
|
+
}
|
|
878
|
+
if (!hasMore && !isLoading()) {
|
|
879
|
+
allItems.push({ __end: true });
|
|
880
|
+
}
|
|
881
|
+
const augmentedRenderItem = (item, index) => {
|
|
882
|
+
if (item.__loading) {
|
|
883
|
+
return loadingComponent;
|
|
884
|
+
}
|
|
885
|
+
if (item.__end) {
|
|
886
|
+
return endComponent;
|
|
887
|
+
}
|
|
888
|
+
return renderItem(item, index);
|
|
889
|
+
};
|
|
890
|
+
return h(VirtualList, {
|
|
891
|
+
...listProps,
|
|
892
|
+
items: allItems,
|
|
893
|
+
itemHeight,
|
|
894
|
+
containerHeight,
|
|
895
|
+
renderItem: augmentedRenderItem,
|
|
896
|
+
onRangeChange: (start, end) => {
|
|
897
|
+
var _a;
|
|
898
|
+
const threshold = Math.floor(allItems.length * 0.8);
|
|
899
|
+
nearEnd(end >= threshold);
|
|
900
|
+
(_a = listProps.onRangeChange) == null ? void 0 : _a.call(listProps, start, end);
|
|
901
|
+
}
|
|
902
|
+
});
|
|
903
|
+
};
|
|
904
|
+
}
|
|
905
|
+
function FixedVirtualList(props) {
|
|
906
|
+
return VirtualList(props);
|
|
907
|
+
}
|
|
908
|
+
function VirtualGrid(props) {
|
|
909
|
+
const {
|
|
910
|
+
items,
|
|
911
|
+
itemWidth,
|
|
912
|
+
itemHeight,
|
|
913
|
+
containerWidth,
|
|
914
|
+
containerHeight,
|
|
915
|
+
renderItem,
|
|
916
|
+
gap = 0,
|
|
917
|
+
overscan = 2,
|
|
918
|
+
className = "virtual-grid"
|
|
919
|
+
} = props;
|
|
920
|
+
const columns = Math.floor(containerWidth / (itemWidth + gap));
|
|
921
|
+
const rows = Math.ceil(items.length / columns);
|
|
922
|
+
const scrollTop = signal(0);
|
|
923
|
+
const visibleRange = computed(() => {
|
|
924
|
+
const scrollPos = scrollTop();
|
|
925
|
+
const startRow = Math.max(0, Math.floor(scrollPos / itemHeight) - overscan);
|
|
926
|
+
const endRow = Math.min(rows - 1, Math.ceil((scrollPos + containerHeight) / itemHeight) + overscan);
|
|
927
|
+
return {
|
|
928
|
+
startRow,
|
|
929
|
+
endRow,
|
|
930
|
+
startIndex: startRow * columns,
|
|
931
|
+
endIndex: Math.min(items.length - 1, (endRow + 1) * columns - 1)
|
|
932
|
+
};
|
|
933
|
+
});
|
|
934
|
+
const handleScroll = (e) => {
|
|
935
|
+
const target = e.target;
|
|
936
|
+
scrollTop(target.scrollTop);
|
|
937
|
+
};
|
|
938
|
+
return () => {
|
|
939
|
+
const { startRow, startIndex, endIndex } = visibleRange();
|
|
940
|
+
const visibleItems = items.slice(startIndex, endIndex + 1);
|
|
941
|
+
const topSpacerHeight = startRow * itemHeight;
|
|
942
|
+
const bottomSpacerHeight = (rows - startRow - Math.ceil(visibleItems.length / columns)) * itemHeight;
|
|
943
|
+
return h("div", {
|
|
944
|
+
class: className,
|
|
945
|
+
style: {
|
|
946
|
+
width: containerWidth + "px",
|
|
947
|
+
height: containerHeight + "px",
|
|
948
|
+
overflowY: "auto",
|
|
949
|
+
position: "relative"
|
|
950
|
+
},
|
|
951
|
+
onscroll: handleScroll
|
|
952
|
+
}, [
|
|
953
|
+
h("div", {
|
|
954
|
+
style: {
|
|
955
|
+
height: topSpacerHeight + "px"
|
|
956
|
+
}
|
|
957
|
+
}),
|
|
958
|
+
h("div", {
|
|
959
|
+
style: {
|
|
960
|
+
display: "flex",
|
|
961
|
+
flexWrap: "wrap",
|
|
962
|
+
gap: gap + "px"
|
|
963
|
+
}
|
|
964
|
+
}, [
|
|
965
|
+
...visibleItems.map((item, i) => {
|
|
966
|
+
const index = startIndex + i;
|
|
967
|
+
return h("div", {
|
|
968
|
+
key: index,
|
|
969
|
+
"data-index": index,
|
|
970
|
+
style: {
|
|
971
|
+
width: itemWidth + "px",
|
|
972
|
+
height: itemHeight + "px",
|
|
973
|
+
flexShrink: 0
|
|
974
|
+
}
|
|
975
|
+
}, [
|
|
976
|
+
renderItem(item, index)
|
|
977
|
+
]);
|
|
978
|
+
})
|
|
979
|
+
]),
|
|
980
|
+
h("div", {
|
|
981
|
+
style: {
|
|
982
|
+
height: Math.max(0, bottomSpacerHeight) + "px"
|
|
983
|
+
}
|
|
984
|
+
})
|
|
985
|
+
]);
|
|
986
|
+
};
|
|
987
|
+
}
|
|
988
|
+
function createErrorBoundary() {
|
|
989
|
+
const state = signal({ hasError: false, error: null });
|
|
990
|
+
const handleError = (error) => {
|
|
991
|
+
state({ hasError: true, error });
|
|
992
|
+
};
|
|
993
|
+
const reset = () => {
|
|
994
|
+
state({ hasError: false, error: null });
|
|
995
|
+
};
|
|
996
|
+
return {
|
|
997
|
+
state,
|
|
998
|
+
handleError,
|
|
999
|
+
reset,
|
|
1000
|
+
hasError: () => state().hasError,
|
|
1001
|
+
error: () => state().error
|
|
1002
|
+
};
|
|
1003
|
+
}
|
|
1004
|
+
function setupGlobalErrorHandler(onError) {
|
|
1005
|
+
const handler = (event) => {
|
|
1006
|
+
const error = event instanceof ErrorEvent ? event.error || new Error(event.message) : event.reason || new Error("Unhandled promise rejection");
|
|
1007
|
+
onError(error);
|
|
1008
|
+
};
|
|
1009
|
+
window.addEventListener("error", handler);
|
|
1010
|
+
window.addEventListener("unhandledrejection", handler);
|
|
1011
|
+
return () => {
|
|
1012
|
+
window.removeEventListener("error", handler);
|
|
1013
|
+
window.removeEventListener("unhandledrejection", handler);
|
|
1014
|
+
};
|
|
1015
|
+
}
|
|
1016
|
+
async function tryCatch(fn, onError) {
|
|
1017
|
+
try {
|
|
1018
|
+
return await fn();
|
|
1019
|
+
} catch (error) {
|
|
1020
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
1021
|
+
onError == null ? void 0 : onError(err);
|
|
1022
|
+
return null;
|
|
1023
|
+
}
|
|
1024
|
+
}
|
|
1025
|
+
async function retry(fn, options = {}) {
|
|
1026
|
+
const {
|
|
1027
|
+
maxRetries = 3,
|
|
1028
|
+
delay = 1e3,
|
|
1029
|
+
backoff = 2,
|
|
1030
|
+
onError
|
|
1031
|
+
} = options;
|
|
1032
|
+
let lastError = null;
|
|
1033
|
+
let currentDelay = delay;
|
|
1034
|
+
for (let attempt = 1; attempt <= maxRetries; attempt++) {
|
|
1035
|
+
try {
|
|
1036
|
+
return await fn();
|
|
1037
|
+
} catch (error) {
|
|
1038
|
+
lastError = error instanceof Error ? error : new Error(String(error));
|
|
1039
|
+
onError == null ? void 0 : onError(lastError, attempt);
|
|
1040
|
+
if (attempt < maxRetries) {
|
|
1041
|
+
await new Promise((resolve) => setTimeout(resolve, currentDelay));
|
|
1042
|
+
currentDelay *= backoff;
|
|
1043
|
+
}
|
|
1044
|
+
}
|
|
1045
|
+
}
|
|
1046
|
+
throw lastError;
|
|
1047
|
+
}
|
|
1048
|
+
function withErrorBoundary(Component, options = {}) {
|
|
1049
|
+
return (props) => {
|
|
1050
|
+
var _a;
|
|
1051
|
+
const boundary = createErrorBoundary();
|
|
1052
|
+
try {
|
|
1053
|
+
return Component(props);
|
|
1054
|
+
} catch (error) {
|
|
1055
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
1056
|
+
boundary.handleError(err);
|
|
1057
|
+
(_a = options.onError) == null ? void 0 : _a.call(options, err);
|
|
1058
|
+
if (options.fallback) {
|
|
1059
|
+
return options.fallback(err, boundary.reset);
|
|
1060
|
+
}
|
|
1061
|
+
return null;
|
|
1062
|
+
}
|
|
1063
|
+
};
|
|
1064
|
+
}
|
|
1065
|
+
function debounce(fn, delay) {
|
|
1066
|
+
let timer = null;
|
|
1067
|
+
return (...args) => {
|
|
1068
|
+
if (timer) clearTimeout(timer);
|
|
1069
|
+
timer = setTimeout(() => fn(...args), delay);
|
|
1070
|
+
};
|
|
1071
|
+
}
|
|
1072
|
+
function throttle(fn, interval) {
|
|
1073
|
+
let last = 0;
|
|
1074
|
+
return (...args) => {
|
|
1075
|
+
const now = Date.now();
|
|
1076
|
+
if (now - last >= interval) {
|
|
1077
|
+
last = now;
|
|
1078
|
+
fn(...args);
|
|
1079
|
+
}
|
|
1080
|
+
};
|
|
1081
|
+
}
|
|
1082
|
+
function cx(...classes) {
|
|
1083
|
+
const result = [];
|
|
1084
|
+
for (const cls of classes) {
|
|
1085
|
+
if (!cls) continue;
|
|
1086
|
+
if (typeof cls === "string") {
|
|
1087
|
+
result.push(cls);
|
|
1088
|
+
} else if (typeof cls === "object") {
|
|
1089
|
+
for (const [key, value] of Object.entries(cls)) {
|
|
1090
|
+
if (value) result.push(key);
|
|
1091
|
+
}
|
|
1092
|
+
}
|
|
1093
|
+
}
|
|
1094
|
+
return result.join(" ");
|
|
1095
|
+
}
|
|
1096
|
+
function style(...styles) {
|
|
1097
|
+
const result = {};
|
|
1098
|
+
for (const s of styles) {
|
|
1099
|
+
if (!s) continue;
|
|
1100
|
+
Object.assign(result, s);
|
|
1101
|
+
}
|
|
1102
|
+
return result;
|
|
1103
|
+
}
|
|
1104
|
+
function on(el, type, handler, options) {
|
|
1105
|
+
el.addEventListener(type, handler, options);
|
|
1106
|
+
return () => el.removeEventListener(type, handler, options);
|
|
1107
|
+
}
|
|
1108
|
+
const onEvent = {
|
|
1109
|
+
click: (handler) => ({ onClick: handler }),
|
|
1110
|
+
change: (handler) => ({ onChange: handler }),
|
|
1111
|
+
input: (handler) => ({ onInput: handler }),
|
|
1112
|
+
submit: (handler) => ({ onSubmit: handler }),
|
|
1113
|
+
keydown: (handler) => ({ onKeyDown: handler }),
|
|
1114
|
+
keyup: (handler) => ({ onKeyUp: handler }),
|
|
1115
|
+
focus: (handler) => ({ onFocus: handler }),
|
|
1116
|
+
blur: (handler) => ({ onBlur: handler }),
|
|
1117
|
+
mouseenter: (handler) => ({ onMouseEnter: handler }),
|
|
1118
|
+
mouseleave: (handler) => ({ onMouseLeave: handler })
|
|
1119
|
+
};
|
|
1120
|
+
function preventDefault(handler) {
|
|
1121
|
+
return (e) => {
|
|
1122
|
+
e.preventDefault();
|
|
1123
|
+
handler(e);
|
|
1124
|
+
};
|
|
1125
|
+
}
|
|
1126
|
+
function stopPropagation(handler) {
|
|
1127
|
+
return (e) => {
|
|
1128
|
+
e.stopPropagation();
|
|
1129
|
+
handler(e);
|
|
1130
|
+
};
|
|
1131
|
+
}
|
|
1132
|
+
function sleep(ms) {
|
|
1133
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
1134
|
+
}
|
|
1135
|
+
export {
|
|
1136
|
+
FixedVirtualList,
|
|
1137
|
+
For,
|
|
1138
|
+
Fragment,
|
|
1139
|
+
InfiniteList,
|
|
1140
|
+
Portal,
|
|
1141
|
+
StreamRenderer,
|
|
1142
|
+
Suspense,
|
|
1143
|
+
VirtualGrid,
|
|
1144
|
+
VirtualList,
|
|
1145
|
+
applyUpdate,
|
|
1146
|
+
asyncComponent,
|
|
1147
|
+
batch,
|
|
1148
|
+
button,
|
|
1149
|
+
computed,
|
|
1150
|
+
createErrorBoundary,
|
|
1151
|
+
createPrefetchContext,
|
|
1152
|
+
createStreamHTML,
|
|
1153
|
+
createSuspense,
|
|
1154
|
+
createUpdate,
|
|
1155
|
+
cx,
|
|
1156
|
+
debounce,
|
|
1157
|
+
div,
|
|
1158
|
+
effect,
|
|
1159
|
+
h,
|
|
1160
|
+
h1,
|
|
1161
|
+
h2,
|
|
1162
|
+
h3,
|
|
1163
|
+
input,
|
|
1164
|
+
lazy,
|
|
1165
|
+
on,
|
|
1166
|
+
onEvent,
|
|
1167
|
+
p,
|
|
1168
|
+
prefetchAndRender,
|
|
1169
|
+
preventDefault,
|
|
1170
|
+
render,
|
|
1171
|
+
renderAsync,
|
|
1172
|
+
renderComponentToString,
|
|
1173
|
+
renderSSR,
|
|
1174
|
+
renderToStreamAsync,
|
|
1175
|
+
renderToStream$1 as renderToStreamDOM,
|
|
1176
|
+
renderToStream as renderToStreamIncremental,
|
|
1177
|
+
renderToString$1 as renderToString,
|
|
1178
|
+
retry,
|
|
1179
|
+
setupGlobalErrorHandler,
|
|
1180
|
+
show,
|
|
1181
|
+
signal,
|
|
1182
|
+
sleep,
|
|
1183
|
+
span,
|
|
1184
|
+
stopPropagation,
|
|
1185
|
+
stream,
|
|
1186
|
+
streamText,
|
|
1187
|
+
style,
|
|
1188
|
+
text,
|
|
1189
|
+
throttle,
|
|
1190
|
+
tryCatch,
|
|
1191
|
+
withErrorBoundary
|
|
1192
|
+
};
|
|
1193
|
+
//# sourceMappingURL=index.js.map
|