weifuwu 0.78.0 → 0.80.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/README.md +12 -11
- package/dist/ai/client.d.ts +1 -1
- package/dist/ai/sse.d.ts +1 -1
- package/dist/ai/types.d.ts +2 -2
- package/dist/components/AlertGroup/AlertGroup.d.ts +1 -1
- package/dist/components/Anchor/Anchor.d.ts +1 -1
- package/dist/components/AuthPage/AuthPage.d.ts +36 -0
- package/dist/components/AutoComplete/AutoComplete.d.ts +3 -1
- package/dist/components/AvatarGroup/AvatarGroup.d.ts +1 -1
- package/dist/components/Calendar/Calendar.d.ts +1 -1
- package/dist/components/Carousel/Carousel.d.ts +1 -1
- package/dist/components/Cascader/Cascader.d.ts +1 -1
- package/dist/components/ChatInput/ChatInput.d.ts +61 -0
- package/dist/components/ColorPicker/ColorPicker.d.ts +1 -1
- package/dist/components/DatePicker/DatePicker.d.ts +2 -0
- package/dist/components/FloatButton/FloatButton.d.ts +1 -1
- package/dist/components/Grid/Grid.d.ts +1 -1
- package/dist/components/Input/Input.d.ts +2 -0
- package/dist/components/InputNumber/InputNumber.d.ts +1 -1
- package/dist/components/JSONViewer/JSONViewer.d.ts +1 -1
- package/dist/components/Link/Link.d.ts +1 -1
- package/dist/components/LogViewer/LogViewer.d.ts +1 -1
- package/dist/components/Markdown/parser.d.ts +1 -1
- package/dist/components/Mentions/Mentions.d.ts +1 -1
- package/dist/components/Menu/Menu.d.ts +1 -1
- package/dist/components/Menubar/Menubar.d.ts +1 -1
- package/dist/components/MessageBubble/MessageBubble.d.ts +1 -1
- package/dist/components/NavMenu/NavMenu.d.ts +1 -1
- package/dist/components/Popconfirm/Popconfirm.d.ts +1 -1
- package/dist/components/Result/Result.d.ts +1 -1
- package/dist/components/Scrollbar/Scrollbar.d.ts +1 -1
- package/dist/components/SearchInput/SearchInput.d.ts +1 -0
- package/dist/components/Slider/Slider.d.ts +1 -0
- package/dist/components/TagsInput/TagsInput.d.ts +1 -1
- package/dist/components/Timeline/Timeline.d.ts +1 -1
- package/dist/components/Transfer/Transfer.d.ts +1 -1
- package/dist/components/TreeSelect/TreeSelect.d.ts +2 -0
- package/dist/components/VirtualList/VirtualList.d.ts +3 -1
- package/dist/components/VirtualTable/VirtualTable.d.ts +1 -1
- package/dist/components/Watermark/Watermark.d.ts +1 -1
- package/dist/components/index.d.ts +4 -0
- package/dist/components/index.js +12 -12
- package/dist/components/style.css +77 -23
- package/dist/index.js +166 -149
- package/dist/ui-dom/ai.d.ts +1 -1
- package/dist/ui-dom/context.d.ts +32 -0
- package/dist/ui-dom/index.d.ts +9 -9
- package/dist/ui-dom/index.js +11 -11
- package/dist/ui-dom/jsx-runtime.js +1 -1
- package/dist/ui-dom/{vdom → middleware}/serve.d.ts +5 -8
- package/dist/ui-dom/testing.js +1 -1
- package/dist/ui-dom/use-chat.d.ts +1 -1
- package/dist/ui-dom/{vdom → vdom2}/audit.d.ts +5 -5
- package/dist/ui-dom/{vdom → vdom2}/build.d.ts +5 -5
- package/dist/ui-dom/vdom2/ctx.d.ts +32 -0
- package/dist/ui-dom/vdom2/hydrate.d.ts +13 -0
- package/dist/ui-dom/vdom2/index.d.ts +13 -0
- package/dist/ui-dom/vdom2/kind.d.ts +35 -0
- package/dist/ui-dom/vdom2/mount.d.ts +63 -0
- package/dist/ui-dom/vdom2/patch.d.ts +47 -0
- package/dist/ui-dom/vdom2/render.d.ts +19 -0
- package/dist/ui-dom/vdom2/ssr.d.ts +32 -0
- package/dist/ui-dom/vdom2/trace.d.ts +52 -0
- package/dist/ui-dom/{vdom → vdom2}/transform.d.ts +22 -1
- package/dist/ui-dom/vdom2/transitions.d.ts +23 -0
- package/dist/ui-dom/vdom2/x2html.d.ts +23 -0
- package/dist/ui-dom/vnode.d.ts +64 -67
- package/docs/ai-contract.md +418 -0
- package/docs/components-map.md +7 -5
- package/docs/components.md +6 -3
- package/docs/frontend-ui-dom.md +2 -2
- package/docs/frontend.md +2 -2
- package/docs/layout.md +1 -1
- package/docs/mobile.md +1 -1
- package/docs/saas.md +2 -2
- package/docs/style-guide.md +182 -0
- package/package.json +1 -1
- package/dist/ui-dom/vdom/diff.d.ts +0 -33
- package/dist/ui-dom/vdom/hydration.d.ts +0 -17
- package/dist/ui-dom/vdom/index.d.ts +0 -23
- package/dist/ui-dom/vdom/mount.d.ts +0 -58
- package/dist/ui-dom/vdom/render.d.ts +0 -17
- package/dist/ui-dom/vdom/ssr.d.ts +0 -44
- /package/dist/ui-dom/{vdom → vdom2}/registry.d.ts +0 -0
|
@@ -1783,29 +1783,6 @@ body.wf-dragging {
|
|
|
1783
1783
|
padding: var(--wf-space-sm);
|
|
1784
1784
|
}
|
|
1785
1785
|
|
|
1786
|
-
.wf-aichat-inputbar {
|
|
1787
|
-
display: flex;
|
|
1788
|
-
gap: var(--wf-gap-sm);
|
|
1789
|
-
align-items: center;
|
|
1790
|
-
}
|
|
1791
|
-
|
|
1792
|
-
.wf-aichat-input {
|
|
1793
|
-
flex: 1;
|
|
1794
|
-
min-width: 0;
|
|
1795
|
-
height: var(--wf-control-height);
|
|
1796
|
-
padding: var(--wf-control-pad-y) var(--wf-space-md);
|
|
1797
|
-
border: 1px solid var(--wf-color-border);
|
|
1798
|
-
border-radius: var(--wf-radius);
|
|
1799
|
-
font-family: var(--wf-font-sans);
|
|
1800
|
-
font-size: var(--wf-font-size-sm);
|
|
1801
|
-
color: var(--wf-color-text);
|
|
1802
|
-
background: var(--wf-color-bg);
|
|
1803
|
-
}
|
|
1804
|
-
|
|
1805
|
-
.wf-aichat-input:focus {
|
|
1806
|
-
outline: none;
|
|
1807
|
-
border-color: var(--wf-color-primary);
|
|
1808
|
-
}
|
|
1809
1786
|
|
|
1810
1787
|
/* weifuwu/components — Alert */
|
|
1811
1788
|
|
|
@@ -2130,6 +2107,10 @@ body.wf-dragging {
|
|
|
2130
2107
|
color: var(--wf-color-primary-text);
|
|
2131
2108
|
}
|
|
2132
2109
|
|
|
2110
|
+
/* error(F2 状态矩阵) */
|
|
2111
|
+
.wf-autocomplete-input--err { border-color: var(--wf-color-error); }
|
|
2112
|
+
.wf-autocomplete-input--err:focus { box-shadow: 0 0 0 2px var(--wf-color-error-bg), 0 0 0 1px var(--wf-color-error); }
|
|
2113
|
+
|
|
2133
2114
|
/* weifuwu/components — Avatar */
|
|
2134
2115
|
|
|
2135
2116
|
.wf-avatar {
|
|
@@ -2853,6 +2834,12 @@ body.wf-dragging {
|
|
|
2853
2834
|
text-align: center;
|
|
2854
2835
|
}
|
|
2855
2836
|
|
|
2837
|
+
/* 键盘高亮(R43 W1):与 hover 同视觉,但独立 class(键盘导航可见性) */
|
|
2838
|
+
.wf-cascader-opt--hl {
|
|
2839
|
+
background: var(--wf-color-primary-bg);
|
|
2840
|
+
color: var(--wf-color-primary-text);
|
|
2841
|
+
}
|
|
2842
|
+
|
|
2856
2843
|
/* weifuwu/components — Chart */
|
|
2857
2844
|
|
|
2858
2845
|
.wf-chart {
|
|
@@ -2921,6 +2908,43 @@ body.wf-dragging {
|
|
|
2921
2908
|
opacity: 0.8;
|
|
2922
2909
|
}
|
|
2923
2910
|
|
|
2911
|
+
/* weifuwu/components — ChatInput(独立聊天输入条——从 AiChat 输入条抽取) */
|
|
2912
|
+
|
|
2913
|
+
.wf-chat-inputbar {
|
|
2914
|
+
display: flex;
|
|
2915
|
+
gap: var(--wf-gap-sm);
|
|
2916
|
+
align-items: center;
|
|
2917
|
+
}
|
|
2918
|
+
|
|
2919
|
+
.wf-chat-input {
|
|
2920
|
+
flex: 1;
|
|
2921
|
+
min-width: 0;
|
|
2922
|
+
height: var(--wf-control-height);
|
|
2923
|
+
padding: var(--wf-control-pad-y) var(--wf-space-md);
|
|
2924
|
+
border: 1px solid var(--wf-color-border);
|
|
2925
|
+
border-radius: var(--wf-radius);
|
|
2926
|
+
font-family: var(--wf-font-sans);
|
|
2927
|
+
font-size: var(--wf-font-size-sm);
|
|
2928
|
+
color: var(--wf-color-text);
|
|
2929
|
+
background: var(--wf-color-bg);
|
|
2930
|
+
}
|
|
2931
|
+
|
|
2932
|
+
.wf-chat-input:focus {
|
|
2933
|
+
outline: none;
|
|
2934
|
+
border-color: var(--wf-color-primary);
|
|
2935
|
+
}
|
|
2936
|
+
|
|
2937
|
+
.wf-chat-input:hover:not(:disabled) {
|
|
2938
|
+
border-color: var(--wf-color-primary-muted, var(--wf-color-primary));
|
|
2939
|
+
}
|
|
2940
|
+
|
|
2941
|
+
/* 多行 textarea:自适应高度(行数由内容撑开) */
|
|
2942
|
+
.wf-chat-inputbar textarea.wf-chat-input {
|
|
2943
|
+
height: auto;
|
|
2944
|
+
min-height: var(--wf-control-height);
|
|
2945
|
+
line-height: 1.5;
|
|
2946
|
+
}
|
|
2947
|
+
|
|
2924
2948
|
/* weifuwu/components — Checkbox */
|
|
2925
2949
|
|
|
2926
2950
|
.wf-checkbox {
|
|
@@ -3970,6 +3994,10 @@ body.wf-dragging {
|
|
|
3970
3994
|
overflow-x: auto;
|
|
3971
3995
|
}
|
|
3972
3996
|
|
|
3997
|
+
/* error(F2 状态矩阵) */
|
|
3998
|
+
.wf-datepicker-input--err { border-color: var(--wf-color-error); }
|
|
3999
|
+
.wf-datepicker-input--err:focus { box-shadow: 0 0 0 2px var(--wf-color-error-bg), 0 0 0 1px var(--wf-color-error); }
|
|
4000
|
+
|
|
3973
4001
|
/* weifuwu/components — Descriptions */
|
|
3974
4002
|
|
|
3975
4003
|
.wf-descriptions {
|
|
@@ -4379,6 +4407,12 @@ body.wf-dragging {
|
|
|
4379
4407
|
to { opacity: 1; }
|
|
4380
4408
|
}
|
|
4381
4409
|
|
|
4410
|
+
/* 键盘高亮(R43 W1):菜单方向键导航可见性 */
|
|
4411
|
+
.wf-dropdown-item--hl {
|
|
4412
|
+
background: var(--wf-color-primary-bg);
|
|
4413
|
+
color: var(--wf-color-primary-text);
|
|
4414
|
+
}
|
|
4415
|
+
|
|
4382
4416
|
/* weifuwu/components — Editor */
|
|
4383
4417
|
|
|
4384
4418
|
.wf-editor { position: relative;
|
|
@@ -7805,6 +7839,10 @@ body.wf-dragging {
|
|
|
7805
7839
|
color: var(--wf-color-text);
|
|
7806
7840
|
}
|
|
7807
7841
|
|
|
7842
|
+
/* disabled(F2 状态矩阵) */
|
|
7843
|
+
.wf-search-input--dis { opacity: 0.5; cursor: not-allowed; }
|
|
7844
|
+
.wf-search-input:disabled { cursor: not-allowed; }
|
|
7845
|
+
|
|
7808
7846
|
/* weifuwu/components — SegmentedControl */
|
|
7809
7847
|
|
|
7810
7848
|
.wf-segmented {
|
|
@@ -8372,6 +8410,10 @@ body.wf-dragging {
|
|
|
8372
8410
|
text-align: center;
|
|
8373
8411
|
}
|
|
8374
8412
|
|
|
8413
|
+
/* disabled(F2 状态矩阵) */
|
|
8414
|
+
.wf-slider-input--dis { opacity: 0.5; cursor: not-allowed; }
|
|
8415
|
+
.wf-slider-input:disabled { cursor: not-allowed; }
|
|
8416
|
+
|
|
8375
8417
|
/* weifuwu/components — Space 间距容器 */
|
|
8376
8418
|
|
|
8377
8419
|
.wf-space {
|
|
@@ -9936,6 +9978,11 @@ body.wf-dragging {
|
|
|
9936
9978
|
overflow: auto;
|
|
9937
9979
|
}
|
|
9938
9980
|
|
|
9981
|
+
/* disabled / error(F2 状态矩阵) */
|
|
9982
|
+
.wf-treeselect-trigger--dis { opacity: 0.5; cursor: not-allowed; background: var(--wf-color-fill); }
|
|
9983
|
+
.wf-treeselect-trigger--err { border-color: var(--wf-color-error); }
|
|
9984
|
+
.wf-treeselect-trigger--err:focus-visible { box-shadow: 0 0 0 2px var(--wf-color-error-bg), 0 0 0 1px var(--wf-color-error); }
|
|
9985
|
+
|
|
9939
9986
|
/* weifuwu/components — Typography */
|
|
9940
9987
|
|
|
9941
9988
|
.wf-title {
|
|
@@ -10028,6 +10075,13 @@ body.wf-dragging {
|
|
|
10028
10075
|
box-sizing: border-box;
|
|
10029
10076
|
}
|
|
10030
10077
|
|
|
10078
|
+
/* 空态(F2 状态矩阵) */
|
|
10079
|
+
.wf-virtual-list--empty {
|
|
10080
|
+
display: flex; align-items: center; justify-content: center;
|
|
10081
|
+
color: var(--wf-color-text-tertiary);
|
|
10082
|
+
font-size: var(--wf-font-size-sm);
|
|
10083
|
+
}
|
|
10084
|
+
|
|
10031
10085
|
/* weifuwu/components — VirtualTable(固定表头 + 虚拟滚动表体) */
|
|
10032
10086
|
|
|
10033
10087
|
.wf-virtual-table {
|
package/dist/index.js
CHANGED
|
@@ -653,9 +653,9 @@ var Router = class _Router {
|
|
|
653
653
|
}
|
|
654
654
|
// ── Private: Mount ─────────────────────────────────────────
|
|
655
655
|
_mountRouter(prefix, sub, extraMws = []) {
|
|
656
|
-
const
|
|
656
|
+
const base2 = prefix === "/" ? "" : prefix.replace(/\/$/, "");
|
|
657
657
|
const mountMw = (req, ctx, next) => {
|
|
658
|
-
ctx.mountPath = (ctx.mountPath || "") +
|
|
658
|
+
ctx.mountPath = (ctx.mountPath || "") + base2;
|
|
659
659
|
return next(req, ctx);
|
|
660
660
|
};
|
|
661
661
|
const allExtra = extraMws.length === 0 && sub.globalMws.length === 0 ? [mountMw] : [mountMw, ...extraMws, ...sub.globalMws];
|
|
@@ -665,12 +665,12 @@ var Router = class _Router {
|
|
|
665
665
|
const routes = [];
|
|
666
666
|
this._collect(sub.root, "", routes);
|
|
667
667
|
for (const { method, path, handler, middlewares } of routes) {
|
|
668
|
-
this._routeImpl(method,
|
|
668
|
+
this._routeImpl(method, base2 + path, [...allExtra, ...middlewares, handler]);
|
|
669
669
|
}
|
|
670
670
|
const wsRoutes = [];
|
|
671
671
|
this._collectWs(sub.wsRoot, "", wsRoutes);
|
|
672
672
|
for (const { path, handler, middlewares } of wsRoutes) {
|
|
673
|
-
this.ws(
|
|
673
|
+
this.ws(base2 + path, ...allExtra, ...middlewares, handler);
|
|
674
674
|
}
|
|
675
675
|
}
|
|
676
676
|
_collect(node, prefix, result) {
|
|
@@ -3077,8 +3077,64 @@ var HtmlSafe = class {
|
|
|
3077
3077
|
// src/ui-dom/vnode.ts
|
|
3078
3078
|
var Fragment = /* @__PURE__ */ Symbol("Fragment");
|
|
3079
3079
|
var Portal = /* @__PURE__ */ Symbol("Portal");
|
|
3080
|
+
function isFrag(v) {
|
|
3081
|
+
return v != null && typeof v === "object" && v.type === Fragment;
|
|
3082
|
+
}
|
|
3083
|
+
function isComp(v) {
|
|
3084
|
+
return v != null && typeof v === "object" && typeof v.type === "function";
|
|
3085
|
+
}
|
|
3086
|
+
function isPortal(v) {
|
|
3087
|
+
return v != null && typeof v === "object" && v.type === Portal;
|
|
3088
|
+
}
|
|
3089
|
+
function base(type, props, key = null) {
|
|
3090
|
+
return {
|
|
3091
|
+
type,
|
|
3092
|
+
props,
|
|
3093
|
+
key,
|
|
3094
|
+
_child: null,
|
|
3095
|
+
_parentNode: null,
|
|
3096
|
+
_refNode: null,
|
|
3097
|
+
_id: null,
|
|
3098
|
+
_customId: null,
|
|
3099
|
+
_parentVNode: null,
|
|
3100
|
+
_ctxVersion: null
|
|
3101
|
+
};
|
|
3102
|
+
}
|
|
3103
|
+
function createVNode(type, props, key = null) {
|
|
3104
|
+
if (type === Fragment) {
|
|
3105
|
+
const v2 = { ...base(type, props, key), type };
|
|
3106
|
+
return v2;
|
|
3107
|
+
}
|
|
3108
|
+
if (type === Portal) {
|
|
3109
|
+
const v2 = { ...base(type, props, key), type, _remoteEl: null, _placement: "remote" };
|
|
3110
|
+
return v2;
|
|
3111
|
+
}
|
|
3112
|
+
if (typeof type === "function") {
|
|
3113
|
+
const v2 = { ...base(type, props, key), type, _render: null, _outputChild: null };
|
|
3114
|
+
return v2;
|
|
3115
|
+
}
|
|
3116
|
+
const v = { ...base(type, props, key), type, el: null };
|
|
3117
|
+
return v;
|
|
3118
|
+
}
|
|
3119
|
+
|
|
3120
|
+
// src/ui-dom/vdom2/kind.ts
|
|
3121
|
+
function classifyKind(v) {
|
|
3122
|
+
if (v == null || typeof v === "boolean") return "hole";
|
|
3123
|
+
if (typeof v === "string" || typeof v === "number") return "text";
|
|
3124
|
+
if (Array.isArray(v)) return "arr";
|
|
3125
|
+
const vn = v;
|
|
3126
|
+
if (isFrag(vn)) return "frag";
|
|
3127
|
+
if (isPortal(vn)) return "portal";
|
|
3128
|
+
if (isComp(vn)) return "comp";
|
|
3129
|
+
return "native";
|
|
3130
|
+
}
|
|
3131
|
+
|
|
3132
|
+
// src/ui-dom/vdom2/ctx.ts
|
|
3133
|
+
function componentName(type) {
|
|
3134
|
+
return typeof type === "function" ? type.name || "anonymous" : "anonymous";
|
|
3135
|
+
}
|
|
3080
3136
|
|
|
3081
|
-
// src/ui-dom/
|
|
3137
|
+
// src/ui-dom/vdom2/transform.ts
|
|
3082
3138
|
function holeDetail(v) {
|
|
3083
3139
|
if (v === false) return "false";
|
|
3084
3140
|
if (v === null) return "null";
|
|
@@ -3095,24 +3151,30 @@ function holeDetail(v) {
|
|
|
3095
3151
|
}
|
|
3096
3152
|
return `bad-vnode type=${typeof v}`;
|
|
3097
3153
|
}
|
|
3098
|
-
function
|
|
3099
|
-
return
|
|
3154
|
+
function quoteIfNeeded(s) {
|
|
3155
|
+
return /[\s"=]/.test(s) ? `"${s.replace(/"/g, "'")}"` : s;
|
|
3156
|
+
}
|
|
3157
|
+
function holeMarkup(opts) {
|
|
3158
|
+
const parts = [`type=${opts.type}`];
|
|
3159
|
+
if (opts.value !== void 0) parts.push(`value=${quoteIfNeeded(holeDetail(opts.value))}`);
|
|
3160
|
+
if (opts.key != null) parts.push(`key=${quoteIfNeeded(opts.key)}`);
|
|
3161
|
+
if (opts.id != null) parts.push(`id=${quoteIfNeeded(opts.id)}`);
|
|
3162
|
+
if (opts.fid != null) parts.push(`fid=${quoteIfNeeded(opts.fid)}`);
|
|
3163
|
+
return `wf-hole: ${parts.join(" ")}`;
|
|
3100
3164
|
}
|
|
3101
3165
|
function ensureArrayKeys(children) {
|
|
3102
3166
|
for (let i = 0; i < children.length; i++) {
|
|
3103
3167
|
const c = children[i];
|
|
3104
3168
|
if (c != null && typeof c === "object" && !Array.isArray(c)) {
|
|
3105
3169
|
const v = c;
|
|
3106
|
-
if (v.key ===
|
|
3170
|
+
if (v.key === null) v.key = String(i);
|
|
3107
3171
|
else v.key = String(v.key);
|
|
3108
3172
|
}
|
|
3109
3173
|
}
|
|
3110
3174
|
}
|
|
3111
3175
|
var ENUMERATED_VALUE_BASED = /* @__PURE__ */ new Set(["draggable", "contenteditable", "spellcheck", "translate"]);
|
|
3112
3176
|
|
|
3113
|
-
// src/ui-dom/
|
|
3114
|
-
var VOID_TAGS = /* @__PURE__ */ new Set(["area", "base", "br", "col", "embed", "hr", "img", "input", "link", "meta", "param", "source", "track", "wbr"]);
|
|
3115
|
-
var SVG_TAGS = /* @__PURE__ */ new Set(["svg", "path", "circle", "rect", "line", "polyline", "polygon", "g", "text", "defs", "use", "clipPath"]);
|
|
3177
|
+
// src/ui-dom/vdom2/x2html.ts
|
|
3116
3178
|
function escape(s) {
|
|
3117
3179
|
return s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
3118
3180
|
}
|
|
@@ -3123,54 +3185,71 @@ function classToString(v) {
|
|
|
3123
3185
|
return "";
|
|
3124
3186
|
}
|
|
3125
3187
|
function styleToString(v) {
|
|
3126
|
-
return Object.entries(v).filter(([, val]) => val != null).map(([k, val]) => {
|
|
3127
|
-
|
|
3128
|
-
|
|
3129
|
-
|
|
3130
|
-
|
|
3131
|
-
|
|
3132
|
-
|
|
3133
|
-
|
|
3134
|
-
|
|
3135
|
-
|
|
3136
|
-
|
|
3137
|
-
|
|
3138
|
-
|
|
3139
|
-
|
|
3140
|
-
|
|
3141
|
-
|
|
3142
|
-
|
|
3143
|
-
const
|
|
3144
|
-
|
|
3145
|
-
|
|
3146
|
-
|
|
3147
|
-
|
|
3148
|
-
|
|
3149
|
-
|
|
3150
|
-
|
|
3151
|
-
|
|
3152
|
-
|
|
3153
|
-
|
|
3154
|
-
|
|
3155
|
-
|
|
3156
|
-
|
|
3157
|
-
|
|
3158
|
-
|
|
3159
|
-
|
|
3160
|
-
|
|
3161
|
-
|
|
3162
|
-
|
|
3163
|
-
|
|
3164
|
-
|
|
3165
|
-
|
|
3166
|
-
|
|
3188
|
+
return Object.entries(v).filter(([, val]) => val != null && val !== false).map(([k, val]) => `${k}:${typeof val === "number" ? val : String(val)}`).join(";");
|
|
3189
|
+
}
|
|
3190
|
+
var VOID_TAGS = /* @__PURE__ */ new Set(["area", "base", "br", "col", "embed", "hr", "img", "input", "link", "meta", "param", "source", "track", "wbr"]);
|
|
3191
|
+
var SVG_TAGS = /* @__PURE__ */ new Set(["svg", "path", "circle", "rect", "line", "polyline", "polygon", "g", "text", "defs", "use", "clipPath"]);
|
|
3192
|
+
async function x2html(input, ctx) {
|
|
3193
|
+
return TO_HTML[classifyKind(input)](input, ctx);
|
|
3194
|
+
}
|
|
3195
|
+
async function holeToHtml(v, ctx) {
|
|
3196
|
+
return "";
|
|
3197
|
+
}
|
|
3198
|
+
async function textToHtml(v, ctx) {
|
|
3199
|
+
return escape(String(v));
|
|
3200
|
+
}
|
|
3201
|
+
async function arrToHtml(v, ctx) {
|
|
3202
|
+
const arr = v;
|
|
3203
|
+
ensureArrayKeys(arr);
|
|
3204
|
+
const fidBase = ctx._fidPath;
|
|
3205
|
+
const parts = await Promise.all(arr.map(async (c, i) => {
|
|
3206
|
+
const childFid = fidBase != null ? `${fidBase}-${i}` : String(i);
|
|
3207
|
+
if (c == null || typeof c === "boolean") return `<!--${holeMarkup({ type: "hole", value: c, key: null, id: null, fid: null })}-->`;
|
|
3208
|
+
if (Array.isArray(c)) {
|
|
3209
|
+
const inner = await x2html(c, { ...ctx, _fidPath: childFid });
|
|
3210
|
+
return `<!--${holeMarkup({ type: "fragment-start", key: String(i), id: null, fid: childFid })}-->${inner}<!--${holeMarkup({ type: "fragment-end", key: String(i), id: null, fid: childFid })}-->`;
|
|
3211
|
+
}
|
|
3212
|
+
return x2html(c, ctx);
|
|
3213
|
+
}));
|
|
3214
|
+
return parts.join("");
|
|
3215
|
+
}
|
|
3216
|
+
async function fragToHtml(v, ctx) {
|
|
3217
|
+
const vnode = v;
|
|
3218
|
+
const fid = ctx._fidPath ?? null;
|
|
3219
|
+
const inner = await x2html(vnode.props?.children, { ...ctx, _fidPath: fid ?? void 0 });
|
|
3220
|
+
return `<!--${holeMarkup({ type: "fragment-start", key: null, id: null, fid })}-->${inner}<!--${holeMarkup({ type: "fragment-end", key: null, id: null, fid })}-->`;
|
|
3221
|
+
}
|
|
3222
|
+
async function portalToHtml(v, ctx) {
|
|
3223
|
+
const vnode = v;
|
|
3224
|
+
return x2html(vnode.props?.children, ctx);
|
|
3225
|
+
}
|
|
3226
|
+
async function compToHtml(v, ctx) {
|
|
3227
|
+
const vnode = v;
|
|
3228
|
+
const childCtx = Object.create(ctx);
|
|
3229
|
+
delete childCtx._fidPath;
|
|
3230
|
+
const renderFn = await vnode.type(vnode.props ?? {}, childCtx);
|
|
3231
|
+
if (typeof renderFn !== "function") {
|
|
3232
|
+
throw new Error(
|
|
3233
|
+
`Component ${componentName(vnode.type)} must return a render function. Use (init_props, ctx) => (props) => VNode pattern.`
|
|
3234
|
+
);
|
|
3235
|
+
}
|
|
3236
|
+
const out = await renderFn(vnode.props ?? {});
|
|
3237
|
+
if (vnode.key != null && out != null && typeof out === "object") {
|
|
3238
|
+
if (Array.isArray(out)) {
|
|
3239
|
+
for (const c of out) if (c != null && typeof c === "object" && !Array.isArray(c)) c.key = vnode.key;
|
|
3240
|
+
} else {
|
|
3241
|
+
;
|
|
3242
|
+
out.key = vnode.key;
|
|
3167
3243
|
}
|
|
3168
|
-
return renderSsr(out, childCtx);
|
|
3169
3244
|
}
|
|
3245
|
+
return x2html(out, childCtx);
|
|
3246
|
+
}
|
|
3247
|
+
async function nativeToHtml(v, ctx) {
|
|
3248
|
+
const vnode = v;
|
|
3170
3249
|
const tag = vnode.type;
|
|
3171
3250
|
const props = vnode.props ?? {};
|
|
3172
3251
|
const attrs = [];
|
|
3173
|
-
let innerHTML;
|
|
3252
|
+
let innerHTML = null;
|
|
3174
3253
|
if (vnode.key != null) attrs.push(` data-wf-key="${escape(String(vnode.key))}"`);
|
|
3175
3254
|
for (const [key, value] of Object.entries(props)) {
|
|
3176
3255
|
if (key === "children" || key === "key") continue;
|
|
@@ -3203,98 +3282,39 @@ async function renderSsr(input, ctx) {
|
|
|
3203
3282
|
const attrStr = attrs.join("");
|
|
3204
3283
|
const svgWrap = SVG_TAGS.has(tag);
|
|
3205
3284
|
if (VOID_TAGS.has(tag)) return `<${tag}${attrStr}>`;
|
|
3206
|
-
if (innerHTML !==
|
|
3207
|
-
const children = await
|
|
3285
|
+
if (innerHTML !== null) return `<${tag}${attrStr}>${innerHTML}</${tag}>`;
|
|
3286
|
+
const children = await x2html(props.children, ctx);
|
|
3208
3287
|
if (svgWrap) return `<${tag}${attrStr}>${children}</${tag}>`;
|
|
3209
3288
|
return `<${tag}${attrStr}>${children}</${tag}>`;
|
|
3210
3289
|
}
|
|
3211
|
-
|
|
3212
|
-
|
|
3213
|
-
|
|
3214
|
-
|
|
3215
|
-
|
|
3216
|
-
|
|
3217
|
-
|
|
3218
|
-
|
|
3219
|
-
|
|
3220
|
-
|
|
3221
|
-
|
|
3222
|
-
|
|
3223
|
-
|
|
3224
|
-
|
|
3225
|
-
endMounting: () => {
|
|
3226
|
-
},
|
|
3227
|
-
onUnmount: () => void 0,
|
|
3228
|
-
// hooks no-op(组件 SSR 安全——不注册监听/定时器)
|
|
3229
|
-
useChat: () => ({ messages: [], input: "", streaming: false, error: null, usage: null, step: null, send: () => {
|
|
3230
|
-
}, stop: () => {
|
|
3231
|
-
}, retry: () => {
|
|
3232
|
-
}, clear: () => {
|
|
3233
|
-
}, approve: () => {
|
|
3234
|
-
}, subscribe: () => () => {
|
|
3235
|
-
} }),
|
|
3236
|
-
useExternal: (store) => store,
|
|
3237
|
-
useMedia: noop,
|
|
3238
|
-
useBreakpoint: noop,
|
|
3239
|
-
usePopupPosition: () => ({ top: 0, left: 0, refresh: () => {
|
|
3240
|
-
} }),
|
|
3241
|
-
useHoverCapable: () => false,
|
|
3242
|
-
useStableRef: (init) => (el) => {
|
|
3243
|
-
if (el) init?.(el);
|
|
3244
|
-
},
|
|
3245
|
-
useVisualViewport: () => ({ height: 0, offsetTop: 0, keyboardOpen: false }),
|
|
3246
|
-
usePopup: () => ({ open: false, setOpen: () => {
|
|
3247
|
-
}, phase: "closed", sync: (open2) => open2 ? "open" : "closed", wrapProps: {}, portal: (content) => content, refresh: () => {
|
|
3248
|
-
} }),
|
|
3249
|
-
useLongPress: noopReturn,
|
|
3250
|
-
useInView: () => ({ isIn: false, ready: false, observe: () => {
|
|
3251
|
-
}, refresh: () => {
|
|
3252
|
-
}, disconnect: () => {
|
|
3253
|
-
} }),
|
|
3254
|
-
useScrollPosition: () => ({ y: 0, refresh: () => {
|
|
3255
|
-
} }),
|
|
3256
|
-
useAsync: () => ({ data: void 0, loading: true, error: void 0, reload: () => {
|
|
3257
|
-
} }),
|
|
3258
|
-
useControlled: () => ({ value: void 0, setValue: () => {
|
|
3259
|
-
}, controlled: false }),
|
|
3260
|
-
useControlledInput: () => ({ value: void 0, setValue: () => {
|
|
3261
|
-
}, keyword: "", setKeyword: () => {
|
|
3262
|
-
}, selectedLabel: "", setSelectedLabel: () => {
|
|
3263
|
-
}, controlled: false }),
|
|
3264
|
-
useOpen: () => ({ open: false, setOpen: () => {
|
|
3265
|
-
}, triggerProps: {} }),
|
|
3266
|
-
usePresence: () => ({ phase: "closed", ref: () => {
|
|
3267
|
-
}, sync: () => "closed" }),
|
|
3268
|
-
useGlobalKey: () => () => {
|
|
3269
|
-
},
|
|
3270
|
-
useDrag: noopReturn,
|
|
3271
|
-
useDragDrop: () => ({ dropProps: {}, dragProps: {} }),
|
|
3272
|
-
useReducedMotion: () => true,
|
|
3273
|
-
// SSR 无动画——组件直落终值
|
|
3274
|
-
useAnimationEnd: () => () => {
|
|
3275
|
-
},
|
|
3276
|
-
useTween: (t) => {
|
|
3277
|
-
let v = t;
|
|
3278
|
-
return {
|
|
3279
|
-
get value() {
|
|
3280
|
-
return v;
|
|
3281
|
-
},
|
|
3282
|
-
set value(n) {
|
|
3283
|
-
v = n;
|
|
3284
|
-
},
|
|
3285
|
-
reset: (n) => {
|
|
3286
|
-
if (n !== void 0) v = n;
|
|
3287
|
-
return v;
|
|
3288
|
-
}
|
|
3289
|
-
};
|
|
3290
|
-
}
|
|
3291
|
-
};
|
|
3290
|
+
var TO_HTML = {
|
|
3291
|
+
hole: holeToHtml,
|
|
3292
|
+
text: textToHtml,
|
|
3293
|
+
arr: arrToHtml,
|
|
3294
|
+
portal: portalToHtml,
|
|
3295
|
+
frag: fragToHtml,
|
|
3296
|
+
comp: compToHtml,
|
|
3297
|
+
native: nativeToHtml
|
|
3298
|
+
};
|
|
3299
|
+
|
|
3300
|
+
// src/ui-dom/vdom2/ssr.ts
|
|
3301
|
+
function serializeData(data) {
|
|
3302
|
+
const json = JSON.stringify(Object.fromEntries(data)).replace(/</g, "\\u003c");
|
|
3303
|
+
return `<script>window.__DATA__=${json};</script>`;
|
|
3292
3304
|
}
|
|
3293
3305
|
function createSsrContext(serverCtx, dataStore) {
|
|
3294
3306
|
const ctx = {
|
|
3295
3307
|
...serverCtx,
|
|
3296
|
-
|
|
3297
|
-
|
|
3308
|
+
browser: null,
|
|
3309
|
+
__registry: null,
|
|
3310
|
+
ui: {
|
|
3311
|
+
_rootVNodeId: null,
|
|
3312
|
+
render: () => Promise.resolve(),
|
|
3313
|
+
setMounting: () => {
|
|
3314
|
+
},
|
|
3315
|
+
endMounting: () => {
|
|
3316
|
+
}
|
|
3317
|
+
}
|
|
3298
3318
|
};
|
|
3299
3319
|
const dataCache = /* @__PURE__ */ new Map();
|
|
3300
3320
|
ctx.data = {
|
|
@@ -3321,14 +3341,11 @@ function createSsrContext(serverCtx, dataStore) {
|
|
|
3321
3341
|
};
|
|
3322
3342
|
return ctx;
|
|
3323
3343
|
}
|
|
3324
|
-
function serializeData(data) {
|
|
3325
|
-
const json = JSON.stringify(Object.fromEntries(data)).replace(/</g, "\\u003c");
|
|
3326
|
-
return `<script>window.__DATA__=${json};</script>`;
|
|
3327
|
-
}
|
|
3328
3344
|
async function ssrToString(Comp, props, serverCtx, opts = {}) {
|
|
3329
3345
|
const dataStore = opts.data ?? /* @__PURE__ */ new Map();
|
|
3330
|
-
const ctx = createSsrContext(serverCtx, dataStore);
|
|
3331
|
-
|
|
3346
|
+
const ctx = createSsrContext(serverCtx ?? {}, dataStore);
|
|
3347
|
+
const vnode = createVNode(Comp, props ?? {});
|
|
3348
|
+
return x2html(vnode, ctx);
|
|
3332
3349
|
}
|
|
3333
3350
|
|
|
3334
3351
|
// src/ui/index.ts
|
|
@@ -4762,8 +4779,8 @@ function compileSelect(q) {
|
|
|
4762
4779
|
if (q.where) sql += ` WHERE ${compileWhere(q.where, params)}`;
|
|
4763
4780
|
for (const s of q.sub ?? []) {
|
|
4764
4781
|
const sub = compileSelect(s.query);
|
|
4765
|
-
const
|
|
4766
|
-
const subSql = sub.sql.replace(/\$(\d+)/g, (_m, n) => `$${
|
|
4782
|
+
const base2 = params.length + 1;
|
|
4783
|
+
const subSql = sub.sql.replace(/\$(\d+)/g, (_m, n) => `$${base2 + Number(n) - 1}`);
|
|
4767
4784
|
params.push(...sub.params);
|
|
4768
4785
|
const op = s.type === "exists" ? s.not ? "NOT EXISTS" : "EXISTS" : s.not ? "NOT IN" : "IN";
|
|
4769
4786
|
if (s.type === "exists") {
|
|
@@ -4847,8 +4864,8 @@ function isColOps(v) {
|
|
|
4847
4864
|
return typeof v === "object" && v !== null && !Array.isArray(v) && !isRaw(v);
|
|
4848
4865
|
}
|
|
4849
4866
|
function interpRaw(raw, params) {
|
|
4850
|
-
const
|
|
4851
|
-
const out = raw.__raw.replace(/\$(\d+)/g, (_m, n) => `$${
|
|
4867
|
+
const base2 = params.length;
|
|
4868
|
+
const out = raw.__raw.replace(/\$(\d+)/g, (_m, n) => `$${base2 + Number(n)}`);
|
|
4852
4869
|
params.push(...raw.params);
|
|
4853
4870
|
return out;
|
|
4854
4871
|
}
|
package/dist/ui-dom/ai.d.ts
CHANGED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ui-dom/context — ctx 组装层(vdom2 纯引擎之上)
|
|
3
|
+
*
|
|
4
|
+
* 分层(vdom2 方案):vdom2/ = 纯渲染引擎(改 vdom 不影响其他);
|
|
5
|
+
* 本文件 = **context/hooks/中间件的组装**(改 hooks/ctx 不动 vdom 引擎):
|
|
6
|
+
* - createVdomContext:组装完整 ctx.ui(render/selfId/onUnmount/bumpCtxVersion +
|
|
7
|
+
* hooks 薄转发 + popup tracker + media registry)
|
|
8
|
+
* - mountRoot:组装入口(context + vdom2 纯引擎挂载)
|
|
9
|
+
*
|
|
10
|
+
* hooks 实现已在 src/ui-dom/hooks/(独立模块)——此处仅组装 HookEnv + 转发。
|
|
11
|
+
*/
|
|
12
|
+
import { type Registry, type Renderer, type MountHandle } from './vdom2/mount.ts';
|
|
13
|
+
import type { BrowserEnv } from './types.ts';
|
|
14
|
+
export interface MountOptions {
|
|
15
|
+
browser: BrowserEnv;
|
|
16
|
+
root: HTMLElement;
|
|
17
|
+
registry?: Registry;
|
|
18
|
+
renderer?: Renderer;
|
|
19
|
+
onError?: (e: unknown) => void;
|
|
20
|
+
}
|
|
21
|
+
export interface VdomContext {
|
|
22
|
+
ctx: any;
|
|
23
|
+
registry: Registry;
|
|
24
|
+
renderer: Renderer;
|
|
25
|
+
rootUi: any;
|
|
26
|
+
destroyPopupListeners: () => void;
|
|
27
|
+
}
|
|
28
|
+
/** 组装 vdom 渲染上下文(ctx.ui 完整能力 + hooks 转发 + popup tracker) */
|
|
29
|
+
export declare function createVdomContext(opts: MountOptions): VdomContext;
|
|
30
|
+
/** 组装入口:createVdomContext + vdom2 纯引擎挂载 */
|
|
31
|
+
export declare function mountRoot(opts: MountOptions): MountHandle;
|
|
32
|
+
export { mountCommand, unmountCommand, createCommandContainer } from './vdom2/mount.ts';
|
package/dist/ui-dom/index.d.ts
CHANGED
|
@@ -22,14 +22,14 @@ export type { AuthClient, AuthInjected } from './middleware/auth.ts';
|
|
|
22
22
|
export { ws } from './middleware/ws.ts';
|
|
23
23
|
export type { WsClient, WsInjected } from './middleware/ws.ts';
|
|
24
24
|
export type { UIRequest, UIResponse, UIHandler, UIMiddleware, UIRouteDef, WfuiContext, } from './types.ts';
|
|
25
|
-
export { uiServe } from './
|
|
26
|
-
export type { UIServeOptions, UIServeHandle } from './
|
|
27
|
-
export { patchValue } from './
|
|
28
|
-
export { hydrateVNode } from './
|
|
29
|
-
export { ssrPage, ssrToString, serializeData } from './
|
|
30
|
-
export {
|
|
31
|
-
export {
|
|
32
|
-
export {
|
|
33
|
-
export { createRenderer, type Renderer } from './vdom/mount.ts';
|
|
25
|
+
export { uiServe } from './middleware/serve.ts';
|
|
26
|
+
export type { UIServeOptions, UIServeHandle } from './middleware/serve.ts';
|
|
27
|
+
export { patchValue } from './vdom2/patch.ts';
|
|
28
|
+
export { hydrateVNode } from './vdom2/hydrate.ts';
|
|
29
|
+
export { ssrPage, ssrToString, serializeData, createSsrContext } from './vdom2/ssr.ts';
|
|
30
|
+
export { buildVNode } from './vdom2/build.ts';
|
|
31
|
+
export { renderValue } from './vdom2/render.ts';
|
|
32
|
+
export { createRenderer, type Renderer } from './vdom2/mount.ts';
|
|
34
33
|
export { createStore } from './store.ts';
|
|
34
|
+
export { createVdomContext, mountRoot } from './context.ts';
|
|
35
35
|
export type { ExternalStore } from './store.ts';
|