weifuwu 0.74.0 → 0.76.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 +20 -20
- package/dist/ai/types.d.ts +3 -1
- package/dist/components/AiChat/AiChat.d.ts +5 -1
- package/dist/components/ApprovalCard/ApprovalCard.d.ts +5 -2
- package/dist/components/Button/Button.d.ts +2 -0
- package/dist/components/CitationCard/CitationCard.d.ts +38 -0
- package/dist/components/Command/Command.d.ts +1 -1
- package/dist/components/JsonSchemaForm/JsonSchemaForm.d.ts +48 -0
- package/dist/components/ReasoningBlock/ReasoningBlock.d.ts +25 -0
- package/dist/components/Select/Select.d.ts +11 -1
- package/dist/components/SessionList/SessionList.d.ts +42 -0
- package/dist/components/TreeSelect/TreeSelect.d.ts +3 -2
- package/dist/components/index.d.ts +10 -2
- package/dist/components/index.js +14 -14
- package/dist/components/style.css +608 -20
- package/dist/index.d.ts +0 -2
- package/dist/index.js +141 -433
- package/dist/layout/weifuwu-layout.css +9 -0
- package/dist/test/client/setup.d.ts +12 -0
- package/dist/ui/index.d.ts +3 -3
- package/dist/ui-dom/Confirm.d.ts +5 -41
- package/dist/ui-dom/Notification.d.ts +8 -70
- package/dist/ui-dom/Toast.d.ts +8 -43
- package/dist/ui-dom/ai.d.ts +1 -1
- package/dist/ui-dom/browser.d.ts +1 -1
- package/dist/ui-dom/focus-trap.d.ts +1 -1
- package/dist/ui-dom/hooks/chat.d.ts +11 -0
- package/dist/ui-dom/hooks/events.d.ts +30 -0
- package/dist/ui-dom/hooks/external.d.ts +20 -0
- package/dist/ui-dom/hooks/index.d.ts +31 -0
- package/dist/ui-dom/hooks/input.d.ts +33 -0
- package/dist/ui-dom/hooks/media.d.ts +17 -0
- package/dist/ui-dom/hooks/popup.d.ts +37 -0
- package/dist/ui-dom/hooks/stable.d.ts +39 -0
- package/dist/ui-dom/hooks/test/hooks.test.d.ts +1 -0
- package/dist/ui-dom/hooks/types.d.ts +78 -0
- package/dist/ui-dom/index.d.ts +19 -17
- package/dist/ui-dom/index.js +12 -10
- package/dist/ui-dom/jsx-runtime.js +1 -1
- package/dist/ui-dom/middleware/api.d.ts +3 -3
- package/dist/ui-dom/middleware/auth.d.ts +1 -1
- package/dist/ui-dom/motion.d.ts +1 -1
- package/dist/ui-dom/popup.d.ts +1 -1
- package/dist/ui-dom/scroll-lock.d.ts +1 -1
- package/dist/ui-dom/store.d.ts +24 -0
- package/dist/ui-dom/testing.d.ts +74 -0
- package/dist/ui-dom/testing.js +1 -0
- package/dist/ui-dom/testing.test.d.ts +1 -0
- package/dist/ui-dom/types.d.ts +34 -17
- package/dist/ui-dom/use-chat.d.ts +19 -14
- package/dist/ui-dom/vdom/build.d.ts +34 -0
- package/dist/ui-dom/vdom/diff.d.ts +34 -0
- package/dist/ui-dom/vdom/hydration.d.ts +17 -0
- package/dist/ui-dom/vdom/index.d.ts +23 -0
- package/dist/ui-dom/vdom/mount.d.ts +49 -0
- package/dist/ui-dom/vdom/registry.d.ts +27 -0
- package/dist/ui-dom/vdom/render.d.ts +13 -0
- package/dist/ui-dom/vdom/scheduler.d.ts +13 -0
- package/dist/ui-dom/vdom/serve.d.ts +30 -0
- package/dist/ui-dom/vdom/ssr.d.ts +44 -0
- package/dist/ui-dom/vnode.d.ts +11 -44
- package/dist/user/token.d.ts +1 -1
- package/docs/compat-three-library.md +1 -1
- package/docs/components-map.md +19 -2
- package/docs/components.md +9 -4
- package/docs/custom-components.md +19 -14
- package/docs/data.md +16 -33
- package/docs/environment.md +1 -1
- package/docs/frontend-middleware.md +65 -79
- package/docs/frontend-ui-dom.md +4 -2
- package/docs/frontend.md +35 -38
- package/docs/layout.md +2 -2
- package/docs/realtime.md +23 -28
- package/docs/saas.md +8 -6
- package/package.json +5 -1
- package/dist/ui/ssr-page.d.ts +0 -41
- package/dist/ui/ssr.d.ts +0 -35
- package/dist/ui-dom/diff.d.ts +0 -28
- package/dist/ui-dom/hydration.d.ts +0 -13
- package/dist/ui-dom/reactive.d.ts +0 -6
- package/dist/ui-dom/registry.d.ts +0 -39
- package/dist/ui-dom/render.d.ts +0 -46
- package/dist/ui-dom/route-match.d.ts +0 -22
- package/dist/ui-dom/serve.d.ts +0 -28
- package/dist/ui-dom/ssr.d.ts +0 -56
- package/dist/ui-dom/ui.d.ts +0 -78
package/dist/index.d.ts
CHANGED
|
@@ -31,8 +31,6 @@ export type { Ai, ApprovalRequest } from './ai/contracts.ts';
|
|
|
31
31
|
export type { AiOptions, AiInjected, AiClient, AiClientModule, ChatResponse, AgentConfig, AgentTool, AgentRunner, ToolContext, AgentRunResult, AgentStep, WfEmitter, } from './ai/index.ts';
|
|
32
32
|
export type { WfStreamEvent, WfMessageStart, WfToken, WfUsage, WfDone, WfError, WfErrorCode, WfToolCall, WfToolResult, WfToolProgress, WfStep, WfApprovalRequest, WfApprovalResponse, WfApprovalDecision, ChatMessage, ChatParams, MessageRole, ToolCall, ToolDefinition, } from './ai/types.ts';
|
|
33
33
|
export { ui } from './ui/index.ts';
|
|
34
|
-
export { uiSsr } from './ui/ssr-page.ts';
|
|
35
|
-
export type { UiSsrOptions } from './ui/ssr-page.ts';
|
|
36
34
|
export type { GraphQLOptions, GraphQLHandler } from './graphql.ts';
|
|
37
35
|
export { postgres, MIGRATIONS_TABLE } from './postgres/index.ts';
|
|
38
36
|
export type { PostgresOptions, PostgresClient, PostgresInjected } from './postgres/types.ts';
|
package/dist/index.js
CHANGED
|
@@ -3540,7 +3540,7 @@ function createAgent(client, config) {
|
|
|
3540
3540
|
if (signal?.aborted) return;
|
|
3541
3541
|
if (!finish.toolCalls?.length) {
|
|
3542
3542
|
emit("wf:usage", usage);
|
|
3543
|
-
emit("wf:done", { content: finish.content, usage });
|
|
3543
|
+
emit("wf:done", { content: finish.content, usage, reasoning: finish.reasoning_content });
|
|
3544
3544
|
return;
|
|
3545
3545
|
}
|
|
3546
3546
|
all.push({
|
|
@@ -3638,318 +3638,27 @@ var HtmlSafe = class {
|
|
|
3638
3638
|
};
|
|
3639
3639
|
|
|
3640
3640
|
// src/ui-dom/vnode.ts
|
|
3641
|
-
var ASYNC_MARK = "__wfAsyncComponent";
|
|
3642
|
-
function isAsyncComponent(type) {
|
|
3643
|
-
return typeof type === "function" && type?.[ASYNC_MARK] === true;
|
|
3644
|
-
}
|
|
3645
3641
|
var Fragment = /* @__PURE__ */ Symbol("Fragment");
|
|
3646
3642
|
var Portal = /* @__PURE__ */ Symbol("Portal");
|
|
3647
3643
|
|
|
3648
|
-
// src/ui-dom/
|
|
3649
|
-
var
|
|
3650
|
-
|
|
3651
|
-
if (_enabled !== null) return _enabled;
|
|
3652
|
-
_enabled = typeof process !== "undefined" && process.env?.UI_DEBUG === "1" || globalThis.__UI_DEBUG === true || typeof localStorage !== "undefined" && localStorage.getItem("__UI_DEBUG") === "1";
|
|
3653
|
-
return _enabled;
|
|
3654
|
-
}
|
|
3655
|
-
var _depth = 0;
|
|
3656
|
-
var counters = /* @__PURE__ */ new Map();
|
|
3657
|
-
function uiLog(label, msg, opts) {
|
|
3658
|
-
if (!uiDebugEnabled()) return;
|
|
3659
|
-
const n = (counters.get(label) ?? 0) + 1;
|
|
3660
|
-
counters.set(label, n);
|
|
3661
|
-
const first = 10;
|
|
3662
|
-
const every = opts?.throttle ?? 100;
|
|
3663
|
-
if (n > first && n % every !== 0) return;
|
|
3664
|
-
const d = opts?.depth !== void 0 ? opts.depth : _depth;
|
|
3665
|
-
const indent = " ".repeat(Math.min(d, 30));
|
|
3666
|
-
console.log(`[ui-debug] ${indent}${label}#${n} ${msg}`);
|
|
3667
|
-
}
|
|
3668
|
-
|
|
3669
|
-
// src/ui-dom/reactive.ts
|
|
3670
|
-
function createReactiveState(dirty) {
|
|
3671
|
-
const _debugSets = /* @__PURE__ */ new Map();
|
|
3672
|
-
const _dbg = (key, label) => {
|
|
3673
|
-
const n = (_debugSets.get(key) ?? 0) + 1;
|
|
3674
|
-
_debugSets.set(key, n);
|
|
3675
|
-
if (n <= 5 || n % 100 === 0) uiLog(label, key + " count=" + n, { throttle: 100 });
|
|
3676
|
-
};
|
|
3677
|
-
const proxyCache = /* @__PURE__ */ new WeakMap();
|
|
3678
|
-
const watchers = /* @__PURE__ */ new Set();
|
|
3679
|
-
const reactive = (target) => {
|
|
3680
|
-
if (target === null || typeof target !== "object") return target;
|
|
3681
|
-
if (target instanceof Set || target instanceof Map) {
|
|
3682
|
-
if (proxyCache.has(target)) return proxyCache.get(target);
|
|
3683
|
-
const MUTATING = target instanceof Set ? /* @__PURE__ */ new Set(["add", "delete", "clear"]) : /* @__PURE__ */ new Set(["set", "delete", "clear"]);
|
|
3684
|
-
const proxy2 = new Proxy(target, {
|
|
3685
|
-
get(t, prop) {
|
|
3686
|
-
const v = Reflect.get(t, prop);
|
|
3687
|
-
if (typeof v === "function") {
|
|
3688
|
-
if (!MUTATING.has(String(prop))) return v.bind(t);
|
|
3689
|
-
return (...args) => {
|
|
3690
|
-
const result = v.apply(t, args);
|
|
3691
|
-
dirty();
|
|
3692
|
-
for (const w of watchers) w();
|
|
3693
|
-
return result;
|
|
3694
|
-
};
|
|
3695
|
-
}
|
|
3696
|
-
return v;
|
|
3697
|
-
},
|
|
3698
|
-
set(t, key, value) {
|
|
3699
|
-
Reflect.set(t, key, value);
|
|
3700
|
-
_dbg(String(key), "set");
|
|
3701
|
-
dirty();
|
|
3702
|
-
for (const w of watchers) w();
|
|
3703
|
-
return true;
|
|
3704
|
-
}
|
|
3705
|
-
});
|
|
3706
|
-
proxyCache.set(target, proxy2);
|
|
3707
|
-
return proxy2;
|
|
3708
|
-
}
|
|
3709
|
-
if (target instanceof Date || target instanceof RegExp) return target;
|
|
3710
|
-
if (proxyCache.has(target)) return proxyCache.get(target);
|
|
3711
|
-
const proxy = new Proxy(target, {
|
|
3712
|
-
set(target2, key, value) {
|
|
3713
|
-
const old = Reflect.get(target2, key);
|
|
3714
|
-
if (old === value) return true;
|
|
3715
|
-
Reflect.set(target2, key, value);
|
|
3716
|
-
dirty();
|
|
3717
|
-
for (const w of watchers) w();
|
|
3718
|
-
return true;
|
|
3719
|
-
},
|
|
3720
|
-
get(target2, key) {
|
|
3721
|
-
const value = Reflect.get(target2, key);
|
|
3722
|
-
if (typeof value === "object" && value !== null) return reactive(value);
|
|
3723
|
-
return value;
|
|
3724
|
-
},
|
|
3725
|
-
deleteProperty(target2, key) {
|
|
3726
|
-
if (Reflect.has(target2, key)) {
|
|
3727
|
-
Reflect.deleteProperty(target2, key);
|
|
3728
|
-
dirty();
|
|
3729
|
-
for (const w of watchers) w();
|
|
3730
|
-
}
|
|
3731
|
-
return true;
|
|
3732
|
-
}
|
|
3733
|
-
});
|
|
3734
|
-
proxyCache.set(target, proxy);
|
|
3735
|
-
return proxy;
|
|
3736
|
-
};
|
|
3737
|
-
const root = reactive({});
|
|
3738
|
-
Object.defineProperty(root, "__watch", {
|
|
3739
|
-
value: (cb) => {
|
|
3740
|
-
watchers.add(cb);
|
|
3741
|
-
return () => {
|
|
3742
|
-
watchers.delete(cb);
|
|
3743
|
-
};
|
|
3744
|
-
},
|
|
3745
|
-
writable: false,
|
|
3746
|
-
enumerable: false
|
|
3747
|
-
});
|
|
3748
|
-
return root;
|
|
3749
|
-
}
|
|
3750
|
-
|
|
3751
|
-
// src/ui/ssr.ts
|
|
3644
|
+
// src/ui-dom/vdom/ssr.ts
|
|
3645
|
+
var VOID_TAGS = /* @__PURE__ */ new Set(["area", "base", "br", "col", "embed", "hr", "img", "input", "link", "meta", "param", "source", "track", "wbr"]);
|
|
3646
|
+
var SVG_TAGS = /* @__PURE__ */ new Set(["svg", "path", "circle", "rect", "line", "polyline", "polygon", "g", "text", "defs", "use", "clipPath"]);
|
|
3752
3647
|
function escape(s) {
|
|
3753
3648
|
return s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
3754
3649
|
}
|
|
3755
|
-
var VOID_TAGS = /* @__PURE__ */ new Set([
|
|
3756
|
-
"area",
|
|
3757
|
-
"base",
|
|
3758
|
-
"br",
|
|
3759
|
-
"col",
|
|
3760
|
-
"embed",
|
|
3761
|
-
"hr",
|
|
3762
|
-
"img",
|
|
3763
|
-
"input",
|
|
3764
|
-
"link",
|
|
3765
|
-
"meta",
|
|
3766
|
-
"param",
|
|
3767
|
-
"source",
|
|
3768
|
-
"track",
|
|
3769
|
-
"wbr"
|
|
3770
|
-
]);
|
|
3771
3650
|
function classToString(v) {
|
|
3772
3651
|
if (typeof v === "string") return v;
|
|
3773
3652
|
if (Array.isArray(v)) return v.filter(Boolean).join(" ");
|
|
3774
|
-
if (v && typeof v === "object")
|
|
3775
|
-
return Object.entries(v).filter(([, b]) => b).map(([k]) => k).join(" ");
|
|
3776
|
-
}
|
|
3653
|
+
if (v && typeof v === "object") return Object.entries(v).filter(([, on]) => on).map(([k]) => k).join(" ");
|
|
3777
3654
|
return "";
|
|
3778
3655
|
}
|
|
3779
3656
|
function styleToString(v) {
|
|
3780
|
-
|
|
3781
|
-
|
|
3782
|
-
|
|
3783
|
-
|
|
3784
|
-
|
|
3785
|
-
}
|
|
3786
|
-
function createSsrContext(serverCtx, dataStore) {
|
|
3787
|
-
const usedIds = /* @__PURE__ */ new Set();
|
|
3788
|
-
const ui2 = {
|
|
3789
|
-
$: () => createReactiveState(() => {
|
|
3790
|
-
}),
|
|
3791
|
-
dirty: () => {
|
|
3792
|
-
},
|
|
3793
|
-
render: () => {
|
|
3794
|
-
},
|
|
3795
|
-
selfId: (name) => {
|
|
3796
|
-
if (usedIds.has(name)) throw new Error(`[weifuwu] Duplicate component ID: "${name}"`);
|
|
3797
|
-
usedIds.add(name);
|
|
3798
|
-
},
|
|
3799
|
-
useMedia: () => {
|
|
3800
|
-
},
|
|
3801
|
-
useBreakpoint: () => {
|
|
3802
|
-
},
|
|
3803
|
-
usePopupPosition: () => ({ top: 0, left: 0, refresh: () => {
|
|
3804
|
-
} }),
|
|
3805
|
-
// 新原语族:SSR 确定性 no-op(不启动监听/会话/取数;组件挂载不崩即契约)
|
|
3806
|
-
useHoverCapable: () => false,
|
|
3807
|
-
useVisualViewport: () => ({ height: 0, offsetTop: 0, keyboardOpen: false }),
|
|
3808
|
-
useLongPress: () => ({}),
|
|
3809
|
-
useInView: () => ({ isIn: false, ready: false, observe: () => {
|
|
3810
|
-
}, refresh: () => {
|
|
3811
|
-
}, disconnect: () => {
|
|
3812
|
-
} }),
|
|
3813
|
-
useScrollPosition: () => ({ y: 0, refresh: () => {
|
|
3814
|
-
} }),
|
|
3815
|
-
useStableRef: (init) => (el) => {
|
|
3816
|
-
if (el) init?.(el);
|
|
3817
|
-
},
|
|
3818
|
-
useGlobalKey: () => () => {
|
|
3819
|
-
},
|
|
3820
|
-
useReducedMotion: () => false,
|
|
3821
|
-
useAnimationEnd: () => () => {
|
|
3822
|
-
},
|
|
3823
|
-
useTween: (target) => {
|
|
3824
|
-
const handle = { value: target, reset: (to) => {
|
|
3825
|
-
handle.value = to;
|
|
3826
|
-
} };
|
|
3827
|
-
return handle;
|
|
3828
|
-
},
|
|
3829
|
-
useDrag: () => ({ onPointerDown: () => {
|
|
3830
|
-
} }),
|
|
3831
|
-
useDragDrop: () => ({ dropProps: {}, dragProps: {} }),
|
|
3832
|
-
useControlled: (options) => ({
|
|
3833
|
-
value: options.value,
|
|
3834
|
-
setValue: (v) => {
|
|
3835
|
-
options.onChange?.(v);
|
|
3836
|
-
},
|
|
3837
|
-
controlled: options.value !== void 0
|
|
3838
|
-
}),
|
|
3839
|
-
useControlledInput: (options) => ({
|
|
3840
|
-
value: options.value,
|
|
3841
|
-
setValue: (v) => {
|
|
3842
|
-
options.onChange?.(v);
|
|
3843
|
-
},
|
|
3844
|
-
controlled: options.value !== void 0,
|
|
3845
|
-
keyword: "",
|
|
3846
|
-
setKeyword: () => {
|
|
3847
|
-
},
|
|
3848
|
-
selectedLabel: "",
|
|
3849
|
-
setSelectedLabel: () => {
|
|
3850
|
-
}
|
|
3851
|
-
}),
|
|
3852
|
-
useOpen: (options) => ({
|
|
3853
|
-
get open() {
|
|
3854
|
-
return !!options.open;
|
|
3855
|
-
},
|
|
3856
|
-
setOpen: (v) => {
|
|
3857
|
-
options.onOpenChange?.(v);
|
|
3858
|
-
},
|
|
3859
|
-
triggerProps: {}
|
|
3860
|
-
}),
|
|
3861
|
-
useAsync: () => ({ data: void 0, loading: true, error: void 0, reload: () => {
|
|
3862
|
-
} }),
|
|
3863
|
-
usePopup: () => ({
|
|
3864
|
-
open: false,
|
|
3865
|
-
setOpen: () => {
|
|
3866
|
-
},
|
|
3867
|
-
wrapProps: {},
|
|
3868
|
-
portal: () => null,
|
|
3869
|
-
refresh: () => {
|
|
3870
|
-
}
|
|
3871
|
-
}),
|
|
3872
|
-
usePresence: () => ({
|
|
3873
|
-
phase: "closed",
|
|
3874
|
-
ref: () => {
|
|
3875
|
-
},
|
|
3876
|
-
sync: (open2) => open2 ? "open" : "closed"
|
|
3877
|
-
}),
|
|
3878
|
-
useDialog: () => ({
|
|
3879
|
-
phase: "closed",
|
|
3880
|
-
rootRef: () => {
|
|
3881
|
-
},
|
|
3882
|
-
panelRef: () => {
|
|
3883
|
-
},
|
|
3884
|
-
sync: (open2) => open2 ? "open" : "closed"
|
|
3885
|
-
}),
|
|
3886
|
-
// SSR 确定性空态:会话不启动(无事件/无网络),仅保证挂载不崩
|
|
3887
|
-
useChat: () => ({
|
|
3888
|
-
messages: [],
|
|
3889
|
-
input: "",
|
|
3890
|
-
streaming: false,
|
|
3891
|
-
error: null,
|
|
3892
|
-
usage: null,
|
|
3893
|
-
step: null,
|
|
3894
|
-
send: () => {
|
|
3895
|
-
},
|
|
3896
|
-
stop: () => {
|
|
3897
|
-
},
|
|
3898
|
-
retry: () => {
|
|
3899
|
-
},
|
|
3900
|
-
clear: () => {
|
|
3901
|
-
},
|
|
3902
|
-
approve: async () => {
|
|
3903
|
-
},
|
|
3904
|
-
dispose: () => {
|
|
3905
|
-
}
|
|
3906
|
-
})
|
|
3907
|
-
};
|
|
3908
|
-
const browser = {
|
|
3909
|
-
activeElement: () => null,
|
|
3910
|
-
byId: () => null,
|
|
3911
|
-
query: () => null,
|
|
3912
|
-
createElement: () => null,
|
|
3913
|
-
bodyAppend: () => {
|
|
3914
|
-
},
|
|
3915
|
-
bodyRemove: () => {
|
|
3916
|
-
},
|
|
3917
|
-
copyText: async () => false,
|
|
3918
|
-
execCommand: () => false,
|
|
3919
|
-
selectionText: () => null,
|
|
3920
|
-
getSelection: () => null,
|
|
3921
|
-
queryCommandState: () => false,
|
|
3922
|
-
queryCommandValue: () => "",
|
|
3923
|
-
viewportHeight: () => 0,
|
|
3924
|
-
scrollTop: () => 0,
|
|
3925
|
-
hash: () => "",
|
|
3926
|
-
setHash: () => {
|
|
3927
|
-
},
|
|
3928
|
-
timeout: () => 0,
|
|
3929
|
-
rootElement: () => null,
|
|
3930
|
-
storageGet: () => null,
|
|
3931
|
-
storageSet: () => {
|
|
3932
|
-
}
|
|
3933
|
-
};
|
|
3934
|
-
const ctx = Object.create(serverCtx ?? {});
|
|
3935
|
-
ctx.ui = ui2;
|
|
3936
|
-
ctx.browser = browser;
|
|
3937
|
-
ctx.data = {
|
|
3938
|
-
async get(key, fetcher) {
|
|
3939
|
-
if (dataStore.has(key)) return dataStore.get(key);
|
|
3940
|
-
if (!fetcher) return void 0;
|
|
3941
|
-
const val = await fetcher();
|
|
3942
|
-
dataStore.set(key, val);
|
|
3943
|
-
return val;
|
|
3944
|
-
},
|
|
3945
|
-
set(key, val) {
|
|
3946
|
-
dataStore.set(key, val);
|
|
3947
|
-
},
|
|
3948
|
-
has(key) {
|
|
3949
|
-
return dataStore.has(key);
|
|
3950
|
-
}
|
|
3951
|
-
};
|
|
3952
|
-
return ctx;
|
|
3657
|
+
return Object.entries(v).filter(([, val]) => val != null).map(([k, val]) => {
|
|
3658
|
+
const key = k.replace(/[A-Z]/g, (m) => "-" + m.toLowerCase());
|
|
3659
|
+
const value = typeof val === "number" && val !== 0 ? `${val}px` : String(val);
|
|
3660
|
+
return `${key}:${value}`;
|
|
3661
|
+
}).join(";");
|
|
3953
3662
|
}
|
|
3954
3663
|
async function renderSsr(input, ctx) {
|
|
3955
3664
|
if (input == null || typeof input === "boolean") return "";
|
|
@@ -3960,37 +3669,13 @@ async function renderSsr(input, ctx) {
|
|
|
3960
3669
|
return s;
|
|
3961
3670
|
}
|
|
3962
3671
|
const vnode = input;
|
|
3963
|
-
if (vnode.type === Portal) return renderSsr(vnode.props?.children, ctx);
|
|
3964
|
-
if (vnode.type === Fragment) return renderSsr(vnode.props?.children, ctx);
|
|
3672
|
+
if (vnode.type === Portal || vnode.type === Fragment) return renderSsr(vnode.props?.children, ctx);
|
|
3965
3673
|
if (typeof vnode.type === "function") {
|
|
3966
|
-
const Comp = vnode.type;
|
|
3967
|
-
if (isAsyncComponent(vnode.type)) {
|
|
3968
|
-
const def = await vnode.type({}, ctx);
|
|
3969
|
-
if (typeof def !== "function") {
|
|
3970
|
-
throw new Error(
|
|
3971
|
-
`asyncComponent factory <${vnode.type.name || "anonymous"}> must return a Component (initProps, ctx) => (props) => VNode.`
|
|
3972
|
-
);
|
|
3973
|
-
}
|
|
3974
|
-
const childCtx2 = Object.create(ctx);
|
|
3975
|
-
const renderFn2 = def(vnode.props ?? {}, childCtx2);
|
|
3976
|
-
if (typeof renderFn2 !== "function") {
|
|
3977
|
-
throw new Error(
|
|
3978
|
-
`Component ${Comp.name || "anonymous"} must return a render function. Use (init_props, ctx) => (props) => VNode pattern.`
|
|
3979
|
-
);
|
|
3980
|
-
}
|
|
3981
|
-
return renderSsr(renderFn2(vnode.props ?? {}), childCtx2);
|
|
3982
|
-
}
|
|
3983
3674
|
const childCtx = Object.create(ctx);
|
|
3984
|
-
|
|
3985
|
-
try {
|
|
3986
|
-
renderFn = Comp(vnode.props ?? {}, childCtx);
|
|
3987
|
-
} catch (e) {
|
|
3988
|
-
throw e;
|
|
3989
|
-
}
|
|
3990
|
-
if (renderFn instanceof Promise) renderFn = await renderFn;
|
|
3675
|
+
const renderFn = await vnode.type(vnode.props ?? {}, childCtx);
|
|
3991
3676
|
if (typeof renderFn !== "function") {
|
|
3992
3677
|
throw new Error(
|
|
3993
|
-
`Component ${
|
|
3678
|
+
`Component ${vnode.type.name || "anonymous"} must return a render function. Use (init_props, ctx) => (props) => VNode pattern.`
|
|
3994
3679
|
);
|
|
3995
3680
|
}
|
|
3996
3681
|
return renderSsr(renderFn(vnode.props ?? {}), childCtx);
|
|
@@ -4016,6 +3701,10 @@ async function renderSsr(input, ctx) {
|
|
|
4016
3701
|
attrs.push(` style="${escape(styleToString(value))}"`);
|
|
4017
3702
|
continue;
|
|
4018
3703
|
}
|
|
3704
|
+
if (key === "draggable" || key === "contenteditable" || key === "spellcheck") {
|
|
3705
|
+
attrs.push(` ${key}="${value ? "true" : "false"}"`);
|
|
3706
|
+
continue;
|
|
3707
|
+
}
|
|
4019
3708
|
if (value === true) {
|
|
4020
3709
|
attrs.push(` ${key}`);
|
|
4021
3710
|
continue;
|
|
@@ -4024,21 +3713,140 @@ async function renderSsr(input, ctx) {
|
|
|
4024
3713
|
attrs.push(` ${key}="${escape(String(value))}"`);
|
|
4025
3714
|
}
|
|
4026
3715
|
const attrStr = attrs.join("");
|
|
3716
|
+
const svgWrap = SVG_TAGS.has(tag);
|
|
4027
3717
|
if (VOID_TAGS.has(tag)) return `<${tag}${attrStr}>`;
|
|
4028
3718
|
if (innerHTML !== void 0) return `<${tag}${attrStr}>${innerHTML}</${tag}>`;
|
|
4029
3719
|
const children = await renderSsr(props.children, ctx);
|
|
3720
|
+
if (svgWrap) return `<${tag}${attrStr}>${children}</${tag}>`;
|
|
4030
3721
|
return `<${tag}${attrStr}>${children}</${tag}>`;
|
|
4031
3722
|
}
|
|
4032
|
-
|
|
4033
|
-
const
|
|
4034
|
-
|
|
4035
|
-
const
|
|
4036
|
-
return
|
|
3723
|
+
function createSsrUi() {
|
|
3724
|
+
const noop = () => () => {
|
|
3725
|
+
};
|
|
3726
|
+
const noopReturn = () => ({});
|
|
3727
|
+
return {
|
|
3728
|
+
_selfId: "_wf_root",
|
|
3729
|
+
render: () => {
|
|
3730
|
+
},
|
|
3731
|
+
dirty: () => {
|
|
3732
|
+
},
|
|
3733
|
+
$: () => ({}),
|
|
3734
|
+
selfId: () => {
|
|
3735
|
+
},
|
|
3736
|
+
bumpCtxVersion: () => {
|
|
3737
|
+
},
|
|
3738
|
+
setMounting: () => {
|
|
3739
|
+
},
|
|
3740
|
+
endMounting: () => {
|
|
3741
|
+
},
|
|
3742
|
+
// hooks no-op(组件 SSR 安全——不注册监听/定时器)
|
|
3743
|
+
useChat: () => ({ messages: [], input: "", streaming: false, error: null, usage: null, step: null, send: () => {
|
|
3744
|
+
}, stop: () => {
|
|
3745
|
+
}, retry: () => {
|
|
3746
|
+
}, clear: () => {
|
|
3747
|
+
}, approve: () => {
|
|
3748
|
+
}, subscribe: () => () => {
|
|
3749
|
+
} }),
|
|
3750
|
+
useExternal: (store) => store,
|
|
3751
|
+
useMedia: noop,
|
|
3752
|
+
useBreakpoint: noop,
|
|
3753
|
+
usePopupPosition: () => ({ top: 0, left: 0, refresh: () => {
|
|
3754
|
+
} }),
|
|
3755
|
+
useHoverCapable: () => false,
|
|
3756
|
+
useStableRef: (init) => (el) => {
|
|
3757
|
+
if (el) init?.(el);
|
|
3758
|
+
},
|
|
3759
|
+
useVisualViewport: () => ({ height: 0, offsetTop: 0, keyboardOpen: false }),
|
|
3760
|
+
usePopup: () => ({ open: false, setOpen: () => {
|
|
3761
|
+
}, wrapProps: {}, portal: () => null, refresh: () => {
|
|
3762
|
+
} }),
|
|
3763
|
+
useLongPress: noopReturn,
|
|
3764
|
+
useInView: () => ({ isIn: false, ready: false, observe: () => {
|
|
3765
|
+
}, refresh: () => {
|
|
3766
|
+
}, disconnect: () => {
|
|
3767
|
+
} }),
|
|
3768
|
+
useScrollPosition: () => ({ y: 0, refresh: () => {
|
|
3769
|
+
} }),
|
|
3770
|
+
useAsync: () => ({ data: void 0, loading: true, error: void 0, reload: () => {
|
|
3771
|
+
} }),
|
|
3772
|
+
useControlled: () => ({ value: void 0, setValue: () => {
|
|
3773
|
+
}, controlled: false }),
|
|
3774
|
+
useControlledInput: () => ({ value: void 0, setValue: () => {
|
|
3775
|
+
}, keyword: "", setKeyword: () => {
|
|
3776
|
+
}, selectedLabel: "", setSelectedLabel: () => {
|
|
3777
|
+
}, controlled: false }),
|
|
3778
|
+
useOpen: () => ({ open: false, setOpen: () => {
|
|
3779
|
+
}, triggerProps: {} }),
|
|
3780
|
+
usePresence: () => ({ phase: "closed", ref: () => {
|
|
3781
|
+
}, sync: () => "closed" }),
|
|
3782
|
+
useDialog: () => ({ phase: "closed", rootRef: () => {
|
|
3783
|
+
}, panelRef: () => {
|
|
3784
|
+
}, sync: (open2) => open2 ? "open" : "closed" }),
|
|
3785
|
+
useGlobalKey: () => () => {
|
|
3786
|
+
},
|
|
3787
|
+
useDrag: noopReturn,
|
|
3788
|
+
useDragDrop: () => ({ dropProps: {}, dragProps: {} }),
|
|
3789
|
+
useReducedMotion: () => true,
|
|
3790
|
+
// SSR 无动画——组件直落终值
|
|
3791
|
+
useAnimationEnd: () => () => {
|
|
3792
|
+
},
|
|
3793
|
+
useTween: (t) => {
|
|
3794
|
+
let v = t;
|
|
3795
|
+
return {
|
|
3796
|
+
get value() {
|
|
3797
|
+
return v;
|
|
3798
|
+
},
|
|
3799
|
+
set value(n) {
|
|
3800
|
+
v = n;
|
|
3801
|
+
},
|
|
3802
|
+
reset: (n) => {
|
|
3803
|
+
if (n !== void 0) v = n;
|
|
3804
|
+
return v;
|
|
3805
|
+
}
|
|
3806
|
+
};
|
|
3807
|
+
}
|
|
3808
|
+
};
|
|
3809
|
+
}
|
|
3810
|
+
function createSsrContext(serverCtx, dataStore) {
|
|
3811
|
+
const ctx = {
|
|
3812
|
+
...serverCtx,
|
|
3813
|
+
ui: createSsrUi(),
|
|
3814
|
+
browser: void 0
|
|
3815
|
+
};
|
|
3816
|
+
const dataCache = /* @__PURE__ */ new Map();
|
|
3817
|
+
ctx.data = {
|
|
3818
|
+
async get(key, fetcher) {
|
|
3819
|
+
const entry = dataCache.get(key);
|
|
3820
|
+
if (entry && "value" in entry) return entry.value;
|
|
3821
|
+
if (entry?.promise) return entry.promise;
|
|
3822
|
+
if (!fetcher) return void 0;
|
|
3823
|
+
const promise = Promise.resolve().then(() => fetcher()).then((val) => {
|
|
3824
|
+
dataCache.set(key, { value: val });
|
|
3825
|
+
dataStore.set(key, val);
|
|
3826
|
+
return val;
|
|
3827
|
+
});
|
|
3828
|
+
dataCache.set(key, { promise });
|
|
3829
|
+
return promise;
|
|
3830
|
+
},
|
|
3831
|
+
set(key, value) {
|
|
3832
|
+
dataCache.set(key, { value });
|
|
3833
|
+
dataStore.set(key, value);
|
|
3834
|
+
},
|
|
3835
|
+
has(key) {
|
|
3836
|
+
return dataCache.has(key);
|
|
3837
|
+
}
|
|
3838
|
+
};
|
|
3839
|
+
return ctx;
|
|
4037
3840
|
}
|
|
4038
3841
|
function serializeData(data) {
|
|
4039
3842
|
const json = JSON.stringify(Object.fromEntries(data)).replace(/</g, "\\u003c");
|
|
4040
3843
|
return `<script>window.__DATA__=${json};</script>`;
|
|
4041
3844
|
}
|
|
3845
|
+
async function ssrToString(Comp, props, serverCtx, opts = {}) {
|
|
3846
|
+
const dataStore = opts.data ?? /* @__PURE__ */ new Map();
|
|
3847
|
+
const ctx = createSsrContext(serverCtx, dataStore);
|
|
3848
|
+
return renderSsr({ type: Comp, props: props ?? {}, key: void 0 }, ctx);
|
|
3849
|
+
}
|
|
4042
3850
|
|
|
4043
3851
|
// src/ui/index.ts
|
|
4044
3852
|
function escape2(s) {
|
|
@@ -4186,105 +3994,6 @@ function ui() {
|
|
|
4186
3994
|
};
|
|
4187
3995
|
}
|
|
4188
3996
|
|
|
4189
|
-
// src/ui-dom/route-match.ts
|
|
4190
|
-
function joinPaths(a, b) {
|
|
4191
|
-
if (!b || b === "/") return a || "/";
|
|
4192
|
-
const left = a.endsWith("/") ? a.slice(0, -1) : a;
|
|
4193
|
-
const right = b.startsWith("/") ? b : "/" + b;
|
|
4194
|
-
return left + right;
|
|
4195
|
-
}
|
|
4196
|
-
function compilePath(path) {
|
|
4197
|
-
const keys = [];
|
|
4198
|
-
const reStr = path.replace(/:(\w+)/g, (_, key) => {
|
|
4199
|
-
keys.push(key);
|
|
4200
|
-
return "([^/]+)";
|
|
4201
|
-
}).replace(/\*/g, ".*");
|
|
4202
|
-
return { re: new RegExp(`^${reStr}$`), keys };
|
|
4203
|
-
}
|
|
4204
|
-
function flattenRoutes(routes, basePath = "", chain = []) {
|
|
4205
|
-
const result = [];
|
|
4206
|
-
for (const route of routes) {
|
|
4207
|
-
const fullPath = joinPaths(basePath, route.path);
|
|
4208
|
-
const { re, keys } = compilePath(fullPath);
|
|
4209
|
-
const fullChain = [...chain, route];
|
|
4210
|
-
result.push({ re, keys, def: route, chain: fullChain });
|
|
4211
|
-
if (route.children) {
|
|
4212
|
-
result.push(...flattenRoutes(route.children, fullPath, fullChain));
|
|
4213
|
-
}
|
|
4214
|
-
}
|
|
4215
|
-
return result;
|
|
4216
|
-
}
|
|
4217
|
-
function matchRoute(path, routes) {
|
|
4218
|
-
let best = null;
|
|
4219
|
-
for (const fr of routes) {
|
|
4220
|
-
if (path.match(fr.re)) {
|
|
4221
|
-
if (!best || fr.chain.length > best.chain.length) best = fr;
|
|
4222
|
-
}
|
|
4223
|
-
}
|
|
4224
|
-
return best;
|
|
4225
|
-
}
|
|
4226
|
-
function extractParams(path, match) {
|
|
4227
|
-
const params = {};
|
|
4228
|
-
const m = path.match(match.re);
|
|
4229
|
-
if (m) {
|
|
4230
|
-
for (let i = 0; i < match.keys.length; i++) {
|
|
4231
|
-
params[match.keys[i]] = safeDecode(m[i + 1]);
|
|
4232
|
-
}
|
|
4233
|
-
}
|
|
4234
|
-
return params;
|
|
4235
|
-
}
|
|
4236
|
-
function safeDecode(s) {
|
|
4237
|
-
try {
|
|
4238
|
-
return decodeURIComponent(s);
|
|
4239
|
-
} catch {
|
|
4240
|
-
return s;
|
|
4241
|
-
}
|
|
4242
|
-
}
|
|
4243
|
-
|
|
4244
|
-
// src/ui/ssr-page.ts
|
|
4245
|
-
var DEFAULT_TEMPLATE = (p) => `<!DOCTYPE html>
|
|
4246
|
-
<html lang="zh-CN">
|
|
4247
|
-
<head>
|
|
4248
|
-
<meta charset="UTF-8">
|
|
4249
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
4250
|
-
<title>${escapeHtml(p.title)}</title>
|
|
4251
|
-
${(p.styles ?? []).map((s) => `<link rel="stylesheet" href="${escapeHtml(s)}">`).join("\n ")}
|
|
4252
|
-
</head>
|
|
4253
|
-
<body>
|
|
4254
|
-
<div id="root">${p.html}</div>
|
|
4255
|
-
${p.dataScript}
|
|
4256
|
-
${p.bundle ? `<script src="${escapeHtml(p.bundle)}"></script>` : ""}
|
|
4257
|
-
</body>
|
|
4258
|
-
</html>`;
|
|
4259
|
-
function escapeHtml(s) {
|
|
4260
|
-
return s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
4261
|
-
}
|
|
4262
|
-
function uiSsr(opts) {
|
|
4263
|
-
const flatRoutes = flattenRoutes(opts.routes);
|
|
4264
|
-
const template = opts.template ?? DEFAULT_TEMPLATE;
|
|
4265
|
-
return async (req, ctx, next) => {
|
|
4266
|
-
if (req.method !== "GET") return next(req, ctx);
|
|
4267
|
-
const url = new URL(req.url);
|
|
4268
|
-
const match = matchRoute(url.pathname, flatRoutes);
|
|
4269
|
-
if (!match) return next(req, ctx);
|
|
4270
|
-
const params = extractParams(url.pathname, match);
|
|
4271
|
-
const def = match.chain[match.chain.length - 1] ?? match.def;
|
|
4272
|
-
const pageCtx = Object.assign(Object.create(ctx), {
|
|
4273
|
-
params,
|
|
4274
|
-
route: { path: url.pathname, params, query: Object.fromEntries(url.searchParams) }
|
|
4275
|
-
});
|
|
4276
|
-
if (!def.component) return next(req, ctx);
|
|
4277
|
-
const data = /* @__PURE__ */ new Map();
|
|
4278
|
-
const html = await ssrToString(def.component, {}, pageCtx, { data });
|
|
4279
|
-
const title = opts.title ? opts.title({ params, def }) : def.title || "weifuwu";
|
|
4280
|
-
const dataScript = new HtmlSafe(serializeData(data)).toString();
|
|
4281
|
-
const body = template({ html: html.toString(), dataScript, title, bundle: opts.bundle, styles: opts.styles });
|
|
4282
|
-
return new Response(body, {
|
|
4283
|
-
headers: { "Content-Type": "text/html; charset=utf-8" }
|
|
4284
|
-
});
|
|
4285
|
-
};
|
|
4286
|
-
}
|
|
4287
|
-
|
|
4288
3997
|
// src/db/postgres/connection.ts
|
|
4289
3998
|
import net3 from "node:net";
|
|
4290
3999
|
import crypto2 from "node:crypto";
|
|
@@ -8341,7 +8050,6 @@ export {
|
|
|
8341
8050
|
serverError,
|
|
8342
8051
|
tooManyRequests,
|
|
8343
8052
|
ui,
|
|
8344
|
-
uiSsr,
|
|
8345
8053
|
unauthorized,
|
|
8346
8054
|
unprocessable,
|
|
8347
8055
|
userSystem,
|
|
@@ -852,6 +852,15 @@ body.wf-dragging {
|
|
|
852
852
|
max-width: min(var(--wf-popup-max, 480px), calc(100vw - 32px));
|
|
853
853
|
box-sizing: border-box;
|
|
854
854
|
}
|
|
855
|
+
|
|
856
|
+
/* usePopup mask 模式遮罩:全屏 fixed,z-index 低于面板(overlay=80 < popover=120),
|
|
857
|
+
* 模态语义阻断页面交互;点击遮罩关闭(maskClosable 门控在组件层) */
|
|
858
|
+
.wf-popup-mask {
|
|
859
|
+
position: fixed;
|
|
860
|
+
inset: 0;
|
|
861
|
+
z-index: var(--wf-z-overlay);
|
|
862
|
+
background: var(--wf-overlay);
|
|
863
|
+
}
|
|
855
864
|
}
|
|
856
865
|
|
|
857
866
|
@layer layout {
|