weifuwu 0.34.0 → 0.35.1
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/README.md +20 -14
- package/dist/client/app.d.ts +7 -0
- package/dist/client/error-boundary.d.ts +23 -0
- package/dist/client/index.d.ts +2 -0
- package/dist/client/index.js +202 -96
- package/dist/client/router.d.ts +1 -0
- package/dist/client/vnode.d.ts +2 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -315,28 +315,34 @@ esbuild.build({
|
|
|
315
315
|
})
|
|
316
316
|
```
|
|
317
317
|
|
|
318
|
-
### 状态管理
|
|
318
|
+
### 状态管理 — 深度 Proxy
|
|
319
|
+
|
|
320
|
+
`ctx.ui.$` 是**深度 Proxy**:任何属性/数组/对象层面的写入自动触发渲染,无需手动调用。
|
|
319
321
|
|
|
320
322
|
```tsx
|
|
321
|
-
const $ = ctx.ui.$
|
|
323
|
+
const $ = ctx.ui.$
|
|
324
|
+
|
|
325
|
+
// 顶层属性赋值
|
|
326
|
+
$.count = 0 // → 自动渲染
|
|
327
|
+
$.user = { name: 'alice' } // → 新值自动深度包装
|
|
322
328
|
|
|
323
|
-
|
|
324
|
-
$.items
|
|
325
|
-
$.items.
|
|
329
|
+
// 数组突变
|
|
330
|
+
$.items.push(newItem) // → 自动渲染
|
|
331
|
+
$.items.pop() // → 自动渲染
|
|
332
|
+
$.items.splice(i, 1) // → 自动渲染
|
|
326
333
|
|
|
327
|
-
//
|
|
328
|
-
|
|
329
|
-
|
|
334
|
+
// 对象属性突变(数组内部也支持)
|
|
335
|
+
$.items[0].done = true // → 自动渲染
|
|
336
|
+
$.msgs[idx].content += event.text // → 自动渲染
|
|
337
|
+
|
|
338
|
+
// 不可变更新(同样支持)
|
|
339
|
+
$.items = [...$.items, newItem]
|
|
330
340
|
```
|
|
331
341
|
|
|
332
342
|
| API | 说明 |
|
|
333
343
|
|------|------|
|
|
334
|
-
| `ctx.ui.$` |
|
|
335
|
-
| `ctx.ui.dirty()` |
|
|
336
|
-
| `ctx.ui.render()` | 同步立即渲染 |
|
|
337
|
-
|
|
338
|
-
**原理**:`ctx.ui.$` 是 Proxy 对象,任何属性赋值(`$.x = val`)自动调用 `queueMicrotask(render)`。\
|
|
339
|
-
多次赋值在同一个微任务内合并为一次渲染。
|
|
344
|
+
| `ctx.ui.$` | 深度 Proxy 对象,所有写入自动触发渲染 |
|
|
345
|
+
| `ctx.ui.dirty()` | ⚠ 极少需要 — 仅当绕过 Proxy 直接操作底层对象时 |
|
|
340
346
|
|
|
341
347
|
### JSX 运行时
|
|
342
348
|
|
package/dist/client/app.d.ts
CHANGED
|
@@ -7,6 +7,13 @@
|
|
|
7
7
|
* ctx.ui.render() 触发组件重渲染
|
|
8
8
|
* ctx.ui.$ 持久化组件状态(由渲染器管理)
|
|
9
9
|
* ctx.ui.ready 首次执行标记(由渲染器管理)
|
|
10
|
+
*
|
|
11
|
+
* ctx.ui.$ 是深度 Proxy:
|
|
12
|
+
* $.x = val → 自动渲染(顶层属性赋值)
|
|
13
|
+
* $.items.push(val) → 自动渲染(数组突变方法)
|
|
14
|
+
* $.items[0].x = val → 自动渲染(对象属性突变)
|
|
15
|
+
* $.items.push({x: 1}) → 新对象自动深度包装
|
|
16
|
+
* ctx.ui.dirty() → 极少需要(仅当绕过 Proxy 直接操作底层对象)
|
|
10
17
|
*/
|
|
11
18
|
import type { WfuiContext, AppMiddleware } from './types.ts';
|
|
12
19
|
import type { Component } from './vnode.ts';
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ErrorBoundary — 错误边界组件
|
|
3
|
+
*
|
|
4
|
+
* 捕获子组件渲染时的错误,展示 fallback 替代崩溃白屏。
|
|
5
|
+
*
|
|
6
|
+
* ```tsx
|
|
7
|
+
* <ErrorBoundary fallback={<p>出错了</p>}>
|
|
8
|
+
* <UserProfile />
|
|
9
|
+
* </ErrorBoundary>
|
|
10
|
+
* ```
|
|
11
|
+
*
|
|
12
|
+
* 基于 ctx.ui._errorHandler 机制:在渲染子组件前注入错误处理器,
|
|
13
|
+
* 子组件 render 抛错时设置 $.error → 重新渲染 fallback。
|
|
14
|
+
*/
|
|
15
|
+
import type { WfuiContext } from './types.ts';
|
|
16
|
+
import type { VNode } from './vnode.ts';
|
|
17
|
+
export interface ErrorBoundaryProps {
|
|
18
|
+
fallback?: VNode | ((props: {
|
|
19
|
+
error: unknown;
|
|
20
|
+
}) => VNode) | null;
|
|
21
|
+
children?: any;
|
|
22
|
+
}
|
|
23
|
+
export declare function ErrorBoundary(props: ErrorBoundaryProps, ctx: WfuiContext): VNode | null;
|
package/dist/client/index.d.ts
CHANGED
|
@@ -27,3 +27,5 @@ export { ApiError } from './middleware/api.ts';
|
|
|
27
27
|
export type { AuthClient, AuthOptions } from './middleware/auth.ts';
|
|
28
28
|
export { extendCtx } from './types.ts';
|
|
29
29
|
export type { WfuiContext, AppMiddleware, RouteDef } from './types.ts';
|
|
30
|
+
export { ErrorBoundary } from './error-boundary.ts';
|
|
31
|
+
export type { ErrorBoundaryProps } from './error-boundary.ts';
|
package/dist/client/index.js
CHANGED
|
@@ -11,7 +11,13 @@ var jsxs = jsx;
|
|
|
11
11
|
function jsxDEV(type, props, key) {
|
|
12
12
|
return jsx(type, props, key);
|
|
13
13
|
}
|
|
14
|
-
|
|
14
|
+
function h(type, props, ...children) {
|
|
15
|
+
const p = normalizeProps(props ?? {});
|
|
16
|
+
if (children.length > 0) {
|
|
17
|
+
p.children = children.length === 1 ? children[0] : children;
|
|
18
|
+
}
|
|
19
|
+
return { type, props: p, key: props?.key ?? void 0 };
|
|
20
|
+
}
|
|
15
21
|
function normalizeProps(props) {
|
|
16
22
|
if (!props) return {};
|
|
17
23
|
const result = {};
|
|
@@ -59,7 +65,19 @@ function renderComponent(Comp, props, vnode, ctx) {
|
|
|
59
65
|
if (!prev$) vnode._$ = {};
|
|
60
66
|
ctx.ui = ctx.ui ?? {};
|
|
61
67
|
ctx.ui.ready = !!prev$;
|
|
62
|
-
|
|
68
|
+
let childVNode;
|
|
69
|
+
try {
|
|
70
|
+
childVNode = Comp(props, ctx);
|
|
71
|
+
} catch (e) {
|
|
72
|
+
const errHandler = ctx.ui?._errorHandler;
|
|
73
|
+
if (errHandler) {
|
|
74
|
+
errHandler(e);
|
|
75
|
+
childVNode = null;
|
|
76
|
+
} else {
|
|
77
|
+
console.error("Component render error:", e);
|
|
78
|
+
childVNode = null;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
63
81
|
if (childVNode == null) {
|
|
64
82
|
vnode._child = null;
|
|
65
83
|
return document.createTextNode("");
|
|
@@ -150,11 +168,9 @@ function patchValue(parent, oldNode, oldInput, newInput, ctx) {
|
|
|
150
168
|
if (oldV._$) newV._$ = oldV._$;
|
|
151
169
|
ctx.ui = ctx.ui ?? {};
|
|
152
170
|
ctx.ui.ready = !!newV._$;
|
|
153
|
-
const childOld = oldV._child != null ? oldV._child : comp(oldV.props, ctx);
|
|
154
|
-
ctx.ui.ready = !!newV._$;
|
|
155
171
|
const childNew = comp(newV.props, ctx);
|
|
156
172
|
newV._child = childNew;
|
|
157
|
-
return patchValue(parent, oldNode,
|
|
173
|
+
return patchValue(parent, oldNode, oldV._child, childNew, ctx);
|
|
158
174
|
}
|
|
159
175
|
if (newV.type === Fragment) {
|
|
160
176
|
patchChildren(parent, oldV, newV, ctx);
|
|
@@ -330,88 +346,6 @@ function callRef(input, el) {
|
|
|
330
346
|
forEach(vnode.props?.children, (child) => callRef(child, el));
|
|
331
347
|
}
|
|
332
348
|
|
|
333
|
-
// src/client/app.ts
|
|
334
|
-
function createApp() {
|
|
335
|
-
const middlewares = [];
|
|
336
|
-
let ctx = {};
|
|
337
|
-
let container = null;
|
|
338
|
-
let rootComponent = null;
|
|
339
|
-
let oldVNode = null;
|
|
340
|
-
let rendered = false;
|
|
341
|
-
const app = {
|
|
342
|
-
get ctx() {
|
|
343
|
-
return ctx;
|
|
344
|
-
},
|
|
345
|
-
use(mw) {
|
|
346
|
-
middlewares.push(mw);
|
|
347
|
-
return app;
|
|
348
|
-
},
|
|
349
|
-
async mount(rootSelector, RootComponent) {
|
|
350
|
-
rootComponent = RootComponent;
|
|
351
|
-
for (const mw of middlewares) {
|
|
352
|
-
ctx = await mw(ctx);
|
|
353
|
-
}
|
|
354
|
-
const el = typeof rootSelector === "string" ? document.querySelector(rootSelector) : rootSelector;
|
|
355
|
-
if (!el) throw new Error(`mount target not found: ${rootSelector}`);
|
|
356
|
-
container = el;
|
|
357
|
-
container.innerHTML = "";
|
|
358
|
-
let _dirty = false;
|
|
359
|
-
const $target = {};
|
|
360
|
-
ctx.ui = {
|
|
361
|
-
render: () => {
|
|
362
|
-
if (!container || !rootComponent || !oldVNode) return;
|
|
363
|
-
_dirty = false;
|
|
364
|
-
ctx._rvDepth = 0;
|
|
365
|
-
const newVNode = wrapComponent(rootComponent, ctx);
|
|
366
|
-
const oldNode = container.firstChild;
|
|
367
|
-
if (oldNode) {
|
|
368
|
-
patchValue(container, oldNode, oldVNode, newVNode, ctx);
|
|
369
|
-
}
|
|
370
|
-
oldVNode = newVNode;
|
|
371
|
-
},
|
|
372
|
-
/** 显式标记脏(用于嵌套突变如 push、arr[i].x +=) */
|
|
373
|
-
dirty: () => {
|
|
374
|
-
if (_dirty) return;
|
|
375
|
-
_dirty = true;
|
|
376
|
-
queueMicrotask(() => {
|
|
377
|
-
if (!_dirty) return;
|
|
378
|
-
_dirty = false;
|
|
379
|
-
ctx.ui.render();
|
|
380
|
-
});
|
|
381
|
-
},
|
|
382
|
-
$: new Proxy($target, {
|
|
383
|
-
set(_target, key, val) {
|
|
384
|
-
_target[key] = val;
|
|
385
|
-
if (!_dirty) {
|
|
386
|
-
_dirty = true;
|
|
387
|
-
queueMicrotask(() => {
|
|
388
|
-
if (!_dirty) return;
|
|
389
|
-
_dirty = false;
|
|
390
|
-
ctx.ui.render();
|
|
391
|
-
});
|
|
392
|
-
}
|
|
393
|
-
return true;
|
|
394
|
-
}
|
|
395
|
-
}),
|
|
396
|
-
ready: false
|
|
397
|
-
};
|
|
398
|
-
oldVNode = wrapComponent(RootComponent, ctx);
|
|
399
|
-
const node = render(oldVNode, ctx);
|
|
400
|
-
if (node instanceof Node) container.appendChild(node);
|
|
401
|
-
rendered = true;
|
|
402
|
-
},
|
|
403
|
-
destroy() {
|
|
404
|
-
if (container) container.innerHTML = "";
|
|
405
|
-
container = null;
|
|
406
|
-
ctx = {};
|
|
407
|
-
}
|
|
408
|
-
};
|
|
409
|
-
return app;
|
|
410
|
-
}
|
|
411
|
-
function wrapComponent(Comp, _ctx) {
|
|
412
|
-
return { type: Comp, props: {}, key: void 0 };
|
|
413
|
-
}
|
|
414
|
-
|
|
415
349
|
// src/client/router.ts
|
|
416
350
|
function flattenRoutes(routes, basePath = "", chain = []) {
|
|
417
351
|
const result = [];
|
|
@@ -426,6 +360,7 @@ function flattenRoutes(routes, basePath = "", chain = []) {
|
|
|
426
360
|
}
|
|
427
361
|
return result;
|
|
428
362
|
}
|
|
363
|
+
var layoutDepth = /* @__PURE__ */ new WeakMap();
|
|
429
364
|
function joinPaths(a, b) {
|
|
430
365
|
if (!b || b === "/") return a || "/";
|
|
431
366
|
const left = a.endsWith("/") ? a.slice(0, -1) : a;
|
|
@@ -451,6 +386,14 @@ function matchRoute(path, routes) {
|
|
|
451
386
|
}
|
|
452
387
|
function router(opts) {
|
|
453
388
|
const flatRoutes = flattenRoutes(opts.routes);
|
|
389
|
+
const mode = opts.mode || "history";
|
|
390
|
+
function getPath() {
|
|
391
|
+
if (mode === "hash") {
|
|
392
|
+
const hash = window.location.hash.replace(/^#/, "") || "/";
|
|
393
|
+
return hash;
|
|
394
|
+
}
|
|
395
|
+
return window.location.pathname;
|
|
396
|
+
}
|
|
454
397
|
function resolve(path) {
|
|
455
398
|
const match = matchRoute(path, flatRoutes);
|
|
456
399
|
if (match) {
|
|
@@ -471,20 +414,30 @@ function router(opts) {
|
|
|
471
414
|
return { path, params: {}, query: {}, chain: [] };
|
|
472
415
|
}
|
|
473
416
|
return (ctx) => {
|
|
474
|
-
const resolved = resolve(
|
|
417
|
+
const resolved = resolve(getPath());
|
|
475
418
|
ctx.route = resolved;
|
|
476
419
|
if (!ctx.app) ctx.app = {};
|
|
477
420
|
ctx.app.navigate = (path) => {
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
421
|
+
if (mode === "hash") {
|
|
422
|
+
window.location.hash = "#" + path;
|
|
423
|
+
const resolved2 = resolve(path);
|
|
424
|
+
ctx.route = resolved2;
|
|
425
|
+
} else {
|
|
426
|
+
window.history.pushState({}, "", path);
|
|
427
|
+
const resolved2 = resolve(path);
|
|
428
|
+
ctx.route = resolved2;
|
|
429
|
+
}
|
|
481
430
|
ctx.ui?.render();
|
|
482
431
|
};
|
|
483
|
-
|
|
484
|
-
const resolved2 = resolve(
|
|
432
|
+
const onPop = () => {
|
|
433
|
+
const resolved2 = resolve(getPath());
|
|
485
434
|
ctx.route = resolved2;
|
|
486
435
|
ctx.ui?.render();
|
|
487
|
-
}
|
|
436
|
+
};
|
|
437
|
+
window.addEventListener("popstate", onPop);
|
|
438
|
+
if (mode === "hash") {
|
|
439
|
+
window.addEventListener("hashchange", onPop);
|
|
440
|
+
}
|
|
488
441
|
return ctx;
|
|
489
442
|
};
|
|
490
443
|
}
|
|
@@ -492,12 +445,135 @@ function RouteView(_props, ctx) {
|
|
|
492
445
|
const route = ctx.route;
|
|
493
446
|
if (!route?.chain?.length) return null;
|
|
494
447
|
const ctxAny = ctx;
|
|
495
|
-
const depth = ctxAny
|
|
448
|
+
const depth = layoutDepth.get(ctxAny) ?? 0;
|
|
496
449
|
if (depth >= route.chain.length) return null;
|
|
497
450
|
const def = route.chain[depth];
|
|
498
451
|
const Comp = def.layout ?? def.component;
|
|
499
452
|
if (!Comp) return null;
|
|
500
|
-
if (def.layout)
|
|
453
|
+
if (def.layout) {
|
|
454
|
+
layoutDepth.set(ctxAny, depth + 1);
|
|
455
|
+
}
|
|
456
|
+
return { type: Comp, props: {}, key: void 0 };
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
// src/client/app.ts
|
|
460
|
+
var mutationMethods = ["push", "pop", "splice", "shift", "unshift", "sort", "reverse"];
|
|
461
|
+
var wrappedCache = /* @__PURE__ */ new WeakMap();
|
|
462
|
+
function wrapDeep(val, dirty) {
|
|
463
|
+
if (val === null || typeof val !== "object") return val;
|
|
464
|
+
if (val instanceof Node) return val;
|
|
465
|
+
if (wrappedCache.has(val)) return wrappedCache.get(val);
|
|
466
|
+
let proxy;
|
|
467
|
+
if (Array.isArray(val)) {
|
|
468
|
+
proxy = new Proxy(val, {
|
|
469
|
+
get(target, key, receiver) {
|
|
470
|
+
const v = Reflect.get(target, key, receiver);
|
|
471
|
+
if (typeof key === "string" && mutationMethods.includes(key) && typeof v === "function") {
|
|
472
|
+
return function(...args) {
|
|
473
|
+
const r = v.apply(target, args);
|
|
474
|
+
dirty();
|
|
475
|
+
return r;
|
|
476
|
+
};
|
|
477
|
+
}
|
|
478
|
+
return wrapDeep(v, dirty);
|
|
479
|
+
},
|
|
480
|
+
set(target, key, val2) {
|
|
481
|
+
target[key] = wrapDeep(val2, dirty);
|
|
482
|
+
dirty();
|
|
483
|
+
return true;
|
|
484
|
+
}
|
|
485
|
+
});
|
|
486
|
+
} else {
|
|
487
|
+
proxy = new Proxy(val, {
|
|
488
|
+
get(_target, key, receiver) {
|
|
489
|
+
const v = Reflect.get(_target, key, receiver);
|
|
490
|
+
return wrapDeep(v, dirty);
|
|
491
|
+
},
|
|
492
|
+
set(target, key, val2) {
|
|
493
|
+
target[key] = wrapDeep(val2, dirty);
|
|
494
|
+
dirty();
|
|
495
|
+
return true;
|
|
496
|
+
}
|
|
497
|
+
});
|
|
498
|
+
}
|
|
499
|
+
wrappedCache.set(val, proxy);
|
|
500
|
+
return proxy;
|
|
501
|
+
}
|
|
502
|
+
function createApp() {
|
|
503
|
+
const middlewares = [];
|
|
504
|
+
let ctx = {};
|
|
505
|
+
let container = null;
|
|
506
|
+
let rootComponent = null;
|
|
507
|
+
let oldVNode = null;
|
|
508
|
+
let rendered = false;
|
|
509
|
+
const app = {
|
|
510
|
+
get ctx() {
|
|
511
|
+
return ctx;
|
|
512
|
+
},
|
|
513
|
+
use(mw) {
|
|
514
|
+
middlewares.push(mw);
|
|
515
|
+
return app;
|
|
516
|
+
},
|
|
517
|
+
async mount(rootSelector, RootComponent) {
|
|
518
|
+
rootComponent = RootComponent;
|
|
519
|
+
for (const mw of middlewares) {
|
|
520
|
+
ctx = await mw(ctx);
|
|
521
|
+
}
|
|
522
|
+
const el = typeof rootSelector === "string" ? document.querySelector(rootSelector) : rootSelector;
|
|
523
|
+
if (!el) throw new Error(`mount target not found: ${rootSelector}`);
|
|
524
|
+
container = el;
|
|
525
|
+
container.innerHTML = "";
|
|
526
|
+
let _dirty = false;
|
|
527
|
+
function scheduleRender() {
|
|
528
|
+
if (_dirty) return;
|
|
529
|
+
_dirty = true;
|
|
530
|
+
queueMicrotask(() => {
|
|
531
|
+
if (!_dirty) return;
|
|
532
|
+
_dirty = false;
|
|
533
|
+
ctx.ui.render();
|
|
534
|
+
});
|
|
535
|
+
}
|
|
536
|
+
const $target = {};
|
|
537
|
+
ctx.ui = {
|
|
538
|
+
render: () => {
|
|
539
|
+
if (!container || !rootComponent || !oldVNode) return;
|
|
540
|
+
_dirty = false;
|
|
541
|
+
layoutDepth.delete(ctx);
|
|
542
|
+
const newVNode = wrapComponent(rootComponent, ctx);
|
|
543
|
+
const oldNode = container.firstChild;
|
|
544
|
+
if (oldNode) {
|
|
545
|
+
patchValue(container, oldNode, oldVNode, newVNode, ctx);
|
|
546
|
+
}
|
|
547
|
+
oldVNode = newVNode;
|
|
548
|
+
},
|
|
549
|
+
/** 极少需要:仅当绕过 Proxy 直接操作底层对象时使用 */
|
|
550
|
+
dirty: () => {
|
|
551
|
+
scheduleRender();
|
|
552
|
+
},
|
|
553
|
+
$: new Proxy($target, {
|
|
554
|
+
set(_target, key, val) {
|
|
555
|
+
_target[key] = wrapDeep(val, scheduleRender);
|
|
556
|
+
scheduleRender();
|
|
557
|
+
return true;
|
|
558
|
+
}
|
|
559
|
+
}),
|
|
560
|
+
ready: false
|
|
561
|
+
};
|
|
562
|
+
oldVNode = wrapComponent(RootComponent, ctx);
|
|
563
|
+
const node = render(oldVNode, ctx);
|
|
564
|
+
if (node instanceof Node) container.appendChild(node);
|
|
565
|
+
_dirty = false;
|
|
566
|
+
rendered = true;
|
|
567
|
+
},
|
|
568
|
+
destroy() {
|
|
569
|
+
if (container) container.innerHTML = "";
|
|
570
|
+
container = null;
|
|
571
|
+
ctx = {};
|
|
572
|
+
}
|
|
573
|
+
};
|
|
574
|
+
return app;
|
|
575
|
+
}
|
|
576
|
+
function wrapComponent(Comp, _ctx) {
|
|
501
577
|
return { type: Comp, props: {}, key: void 0 };
|
|
502
578
|
}
|
|
503
579
|
|
|
@@ -761,8 +837,38 @@ function auth(options) {
|
|
|
761
837
|
return extendCtx(ctx, { auth: authClient });
|
|
762
838
|
};
|
|
763
839
|
}
|
|
840
|
+
|
|
841
|
+
// src/client/error-boundary.ts
|
|
842
|
+
function ErrorBoundary(props, ctx) {
|
|
843
|
+
const $ = ctx.ui.$;
|
|
844
|
+
if (!("error" in $)) $.error = null;
|
|
845
|
+
if ($.error) {
|
|
846
|
+
const fb = props.fallback;
|
|
847
|
+
if (typeof fb === "function") {
|
|
848
|
+
return fb({ error: $.error });
|
|
849
|
+
}
|
|
850
|
+
return fb ?? null;
|
|
851
|
+
}
|
|
852
|
+
;
|
|
853
|
+
ctx.ui._errorHandler = (err) => {
|
|
854
|
+
$.error = err;
|
|
855
|
+
ctx.ui.dirty();
|
|
856
|
+
};
|
|
857
|
+
try {
|
|
858
|
+
const result = props.children;
|
|
859
|
+
return result ?? null;
|
|
860
|
+
} catch (e) {
|
|
861
|
+
$.error = e;
|
|
862
|
+
const fb = props.fallback;
|
|
863
|
+
if (typeof fb === "function") {
|
|
864
|
+
return fb({ error: e });
|
|
865
|
+
}
|
|
866
|
+
return fb ?? null;
|
|
867
|
+
}
|
|
868
|
+
}
|
|
764
869
|
export {
|
|
765
870
|
ApiError,
|
|
871
|
+
ErrorBoundary,
|
|
766
872
|
Fragment,
|
|
767
873
|
RouteView,
|
|
768
874
|
api,
|
package/dist/client/router.d.ts
CHANGED
|
@@ -9,5 +9,6 @@ export interface RouterOptions {
|
|
|
9
9
|
routes: RouteDef[];
|
|
10
10
|
notFound?: (props: any, ctx: WfuiContext) => any;
|
|
11
11
|
}
|
|
12
|
+
export declare const layoutDepth: WeakMap<any, number>;
|
|
12
13
|
export declare function router(opts: RouterOptions): AppMiddleware;
|
|
13
14
|
export declare function RouteView(_props: {}, ctx: WfuiContext): any;
|
package/dist/client/vnode.d.ts
CHANGED
|
@@ -32,7 +32,8 @@ declare global {
|
|
|
32
32
|
export declare function jsx(type: VNodeType, props: Record<string, any> | null, key?: string | null): VNode;
|
|
33
33
|
export declare const jsxs: typeof jsx;
|
|
34
34
|
export declare function jsxDEV(type: VNodeType, props: Record<string, any> | null, key?: string | null): VNode;
|
|
35
|
-
|
|
35
|
+
/** `h`(hyperscript)支持 variadic children: `h('div', {class:'x'}, child1, child2)` */
|
|
36
|
+
export declare function h(type: VNodeType, props: Record<string, any> | null, ...children: any[]): VNode;
|
|
36
37
|
export declare function isNative(vnode: VNode): boolean;
|
|
37
38
|
export declare function isComponent(vnode: VNode): boolean;
|
|
38
39
|
export declare function isFragment(vnode: VNode): boolean;
|