weifuwu 0.79.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.
Files changed (47) hide show
  1. package/README.md +7 -6
  2. package/dist/ai/client.d.ts +1 -1
  3. package/dist/ai/sse.d.ts +1 -1
  4. package/dist/ai/types.d.ts +2 -2
  5. package/dist/components/ChatInput/ChatInput.d.ts +10 -0
  6. package/dist/components/Input/Input.d.ts +2 -0
  7. package/dist/components/index.js +10 -10
  8. package/dist/index.js +156 -157
  9. package/dist/ui-dom/ai.d.ts +1 -1
  10. package/dist/ui-dom/context.d.ts +32 -0
  11. package/dist/ui-dom/index.d.ts +9 -9
  12. package/dist/ui-dom/index.js +10 -10
  13. package/dist/ui-dom/jsx-runtime.js +1 -1
  14. package/dist/ui-dom/{vdom → middleware}/serve.d.ts +5 -8
  15. package/dist/ui-dom/testing.js +1 -1
  16. package/dist/ui-dom/use-chat.d.ts +1 -1
  17. package/dist/ui-dom/{vdom → vdom2}/audit.d.ts +5 -5
  18. package/dist/ui-dom/{vdom → vdom2}/build.d.ts +5 -5
  19. package/dist/ui-dom/vdom2/ctx.d.ts +32 -0
  20. package/dist/ui-dom/vdom2/hydrate.d.ts +13 -0
  21. package/dist/ui-dom/vdom2/index.d.ts +13 -0
  22. package/dist/ui-dom/vdom2/kind.d.ts +35 -0
  23. package/dist/ui-dom/vdom2/mount.d.ts +63 -0
  24. package/dist/ui-dom/vdom2/patch.d.ts +47 -0
  25. package/dist/ui-dom/vdom2/render.d.ts +19 -0
  26. package/dist/ui-dom/vdom2/ssr.d.ts +32 -0
  27. package/dist/ui-dom/vdom2/trace.d.ts +52 -0
  28. package/dist/ui-dom/{vdom → vdom2}/transform.d.ts +9 -3
  29. package/dist/ui-dom/vdom2/transitions.d.ts +23 -0
  30. package/dist/ui-dom/vdom2/x2html.d.ts +23 -0
  31. package/dist/ui-dom/vnode.d.ts +63 -70
  32. package/docs/ai-contract.md +418 -0
  33. package/docs/components-map.md +4 -4
  34. package/docs/frontend-ui-dom.md +2 -2
  35. package/docs/frontend.md +2 -2
  36. package/docs/layout.md +1 -1
  37. package/docs/mobile.md +1 -1
  38. package/docs/saas.md +2 -2
  39. package/docs/style-guide.md +182 -0
  40. package/package.json +1 -1
  41. package/dist/ui-dom/vdom/diff.d.ts +0 -29
  42. package/dist/ui-dom/vdom/hydration.d.ts +0 -17
  43. package/dist/ui-dom/vdom/index.d.ts +0 -23
  44. package/dist/ui-dom/vdom/mount.d.ts +0 -58
  45. package/dist/ui-dom/vdom/render.d.ts +0 -17
  46. package/dist/ui-dom/vdom/ssr.d.ts +0 -44
  47. /package/dist/ui-dom/{vdom → vdom2}/registry.d.ts +0 -0
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 base = prefix === "/" ? "" : prefix.replace(/\/$/, "");
656
+ const base2 = prefix === "/" ? "" : prefix.replace(/\/$/, "");
657
657
  const mountMw = (req, ctx, next) => {
658
- ctx.mountPath = (ctx.mountPath || "") + base;
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, base + path, [...allExtra, ...middlewares, handler]);
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(base + path, ...allExtra, ...middlewares, handler);
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/vdom/transform.ts
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";
@@ -3106,24 +3162,19 @@ function holeMarkup(opts) {
3106
3162
  if (opts.fid != null) parts.push(`fid=${quoteIfNeeded(opts.fid)}`);
3107
3163
  return `wf-hole: ${parts.join(" ")}`;
3108
3164
  }
3109
- function isInvalidVNodeType(t) {
3110
- return typeof t !== "string" && typeof t !== "function" && t !== Fragment && t !== Portal;
3111
- }
3112
3165
  function ensureArrayKeys(children) {
3113
3166
  for (let i = 0; i < children.length; i++) {
3114
3167
  const c = children[i];
3115
3168
  if (c != null && typeof c === "object" && !Array.isArray(c)) {
3116
3169
  const v = c;
3117
- if (v.key === void 0) v.key = String(i);
3170
+ if (v.key === null) v.key = String(i);
3118
3171
  else v.key = String(v.key);
3119
3172
  }
3120
3173
  }
3121
3174
  }
3122
3175
  var ENUMERATED_VALUE_BASED = /* @__PURE__ */ new Set(["draggable", "contenteditable", "spellcheck", "translate"]);
3123
3176
 
3124
- // src/ui-dom/vdom/ssr.ts
3125
- var VOID_TAGS = /* @__PURE__ */ new Set(["area", "base", "br", "col", "embed", "hr", "img", "input", "link", "meta", "param", "source", "track", "wbr"]);
3126
- 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
3127
3178
  function escape(s) {
3128
3179
  return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
3129
3180
  }
@@ -3134,61 +3185,71 @@ function classToString(v) {
3134
3185
  return "";
3135
3186
  }
3136
3187
  function styleToString(v) {
3137
- return Object.entries(v).filter(([, val]) => val != null).map(([k, val]) => {
3138
- const key = k.replace(/[A-Z]/g, (m) => "-" + m.toLowerCase());
3139
- const value = typeof val === "number" && val !== 0 ? `${val}px` : String(val);
3140
- return `${key}:${value}`;
3141
- }).join(";");
3142
- }
3143
- async function renderSsr(input, ctx) {
3144
- if (input == null || typeof input === "boolean") return "";
3145
- if (typeof input === "string" || typeof input === "number") return escape(String(input));
3146
- if (Array.isArray(input)) {
3147
- ensureArrayKeys(input);
3148
- const fidBase = ctx._fidPath;
3149
- const parts = await Promise.all(input.map(async (c, i) => {
3150
- const childFid = fidBase != null ? `${fidBase}-${i}` : String(i);
3151
- if (c == null || typeof c === "boolean") return Promise.resolve(`<!--${holeMarkup({ type: "hole", value: c })}-->`);
3152
- if (Array.isArray(c)) {
3153
- const inner = await renderSsr(c, { ...ctx, _fidPath: childFid });
3154
- return `<!--${holeMarkup({ type: "fragment-start", key: String(i), fid: childFid })}-->${inner}<!--${holeMarkup({ type: "fragment-end", key: String(i), fid: childFid })}-->`;
3155
- }
3156
- return renderSsr(c, ctx);
3157
- }));
3158
- return parts.join("");
3159
- }
3160
- const vnode = input;
3161
- if (isInvalidVNodeType(vnode.type)) {
3162
- console.warn(`[weifuwu] children \u9879\u975E\u6CD5\uFF1Atype=${String(vnode.type)}\uFF08${typeof vnode.type}\uFF09\u2014\u2014\u5DF2\u5360\u4F4D\uFF08wf-hole\uFF09`);
3163
- return `<!--${holeMarkup({ type: "hole", value: input })}-->`;
3164
- }
3165
- if (vnode.type === Portal || vnode.type === Fragment) return renderSsr(vnode.props?.children, ctx);
3166
- if (typeof vnode.type === "function") {
3167
- const childCtx = Object.create(ctx);
3168
- delete childCtx._fidPath;
3169
- const renderFn = await vnode.type(vnode.props ?? {}, childCtx);
3170
- if (typeof renderFn !== "function") {
3171
- throw new Error(
3172
- `Component ${vnode.type.name || "anonymous"} must return a render function. Use (init_props, ctx) => (props) => VNode pattern.`
3173
- );
3174
- }
3175
- const out = await renderFn(vnode.props ?? {});
3176
- if (vnode.key != null && out != null && typeof out === "object") {
3177
- if (Array.isArray(out)) {
3178
- for (const c of out) {
3179
- if (c != null && typeof c === "object" && !Array.isArray(c)) c.key = vnode.key;
3180
- }
3181
- } else {
3182
- ;
3183
- out.key = vnode.key;
3184
- }
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;
3185
3243
  }
3186
- return renderSsr(out, childCtx);
3187
3244
  }
3245
+ return x2html(out, childCtx);
3246
+ }
3247
+ async function nativeToHtml(v, ctx) {
3248
+ const vnode = v;
3188
3249
  const tag = vnode.type;
3189
3250
  const props = vnode.props ?? {};
3190
3251
  const attrs = [];
3191
- let innerHTML;
3252
+ let innerHTML = null;
3192
3253
  if (vnode.key != null) attrs.push(` data-wf-key="${escape(String(vnode.key))}"`);
3193
3254
  for (const [key, value] of Object.entries(props)) {
3194
3255
  if (key === "children" || key === "key") continue;
@@ -3221,98 +3282,39 @@ async function renderSsr(input, ctx) {
3221
3282
  const attrStr = attrs.join("");
3222
3283
  const svgWrap = SVG_TAGS.has(tag);
3223
3284
  if (VOID_TAGS.has(tag)) return `<${tag}${attrStr}>`;
3224
- if (innerHTML !== void 0) return `<${tag}${attrStr}>${innerHTML}</${tag}>`;
3225
- const children = await renderSsr(props.children, ctx);
3285
+ if (innerHTML !== null) return `<${tag}${attrStr}>${innerHTML}</${tag}>`;
3286
+ const children = await x2html(props.children, ctx);
3226
3287
  if (svgWrap) return `<${tag}${attrStr}>${children}</${tag}>`;
3227
3288
  return `<${tag}${attrStr}>${children}</${tag}>`;
3228
3289
  }
3229
- function createSsrUi() {
3230
- const noop = () => () => {
3231
- };
3232
- const noopReturn = () => ({});
3233
- return {
3234
- _selfId: "_wf_root",
3235
- render: () => {
3236
- },
3237
- selfId: () => {
3238
- },
3239
- bumpCtxVersion: () => {
3240
- },
3241
- setMounting: () => {
3242
- },
3243
- endMounting: () => {
3244
- },
3245
- onUnmount: () => void 0,
3246
- // hooks no-op(组件 SSR 安全——不注册监听/定时器)
3247
- useChat: () => ({ messages: [], input: "", streaming: false, error: null, usage: null, step: null, send: () => {
3248
- }, stop: () => {
3249
- }, retry: () => {
3250
- }, clear: () => {
3251
- }, approve: () => {
3252
- }, subscribe: () => () => {
3253
- } }),
3254
- useExternal: (store) => store,
3255
- useMedia: noop,
3256
- useBreakpoint: noop,
3257
- usePopupPosition: () => ({ top: 0, left: 0, refresh: () => {
3258
- } }),
3259
- useHoverCapable: () => false,
3260
- useStableRef: (init) => (el) => {
3261
- if (el) init?.(el);
3262
- },
3263
- useVisualViewport: () => ({ height: 0, offsetTop: 0, keyboardOpen: false }),
3264
- usePopup: () => ({ open: false, setOpen: () => {
3265
- }, phase: "closed", sync: (open2) => open2 ? "open" : "closed", wrapProps: {}, portal: (content) => content, refresh: () => {
3266
- } }),
3267
- useLongPress: noopReturn,
3268
- useInView: () => ({ isIn: false, ready: false, observe: () => {
3269
- }, refresh: () => {
3270
- }, disconnect: () => {
3271
- } }),
3272
- useScrollPosition: () => ({ y: 0, refresh: () => {
3273
- } }),
3274
- useAsync: () => ({ data: void 0, loading: true, error: void 0, reload: () => {
3275
- } }),
3276
- useControlled: () => ({ value: void 0, setValue: () => {
3277
- }, controlled: false }),
3278
- useControlledInput: () => ({ value: void 0, setValue: () => {
3279
- }, keyword: "", setKeyword: () => {
3280
- }, selectedLabel: "", setSelectedLabel: () => {
3281
- }, controlled: false }),
3282
- useOpen: () => ({ open: false, setOpen: () => {
3283
- }, triggerProps: {} }),
3284
- usePresence: () => ({ phase: "closed", ref: () => {
3285
- }, sync: () => "closed" }),
3286
- useGlobalKey: () => () => {
3287
- },
3288
- useDrag: noopReturn,
3289
- useDragDrop: () => ({ dropProps: {}, dragProps: {} }),
3290
- useReducedMotion: () => true,
3291
- // SSR 无动画——组件直落终值
3292
- useAnimationEnd: () => () => {
3293
- },
3294
- useTween: (t) => {
3295
- let v = t;
3296
- return {
3297
- get value() {
3298
- return v;
3299
- },
3300
- set value(n) {
3301
- v = n;
3302
- },
3303
- reset: (n) => {
3304
- if (n !== void 0) v = n;
3305
- return v;
3306
- }
3307
- };
3308
- }
3309
- };
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>`;
3310
3304
  }
3311
3305
  function createSsrContext(serverCtx, dataStore) {
3312
3306
  const ctx = {
3313
3307
  ...serverCtx,
3314
- ui: createSsrUi(),
3315
- browser: void 0
3308
+ browser: null,
3309
+ __registry: null,
3310
+ ui: {
3311
+ _rootVNodeId: null,
3312
+ render: () => Promise.resolve(),
3313
+ setMounting: () => {
3314
+ },
3315
+ endMounting: () => {
3316
+ }
3317
+ }
3316
3318
  };
3317
3319
  const dataCache = /* @__PURE__ */ new Map();
3318
3320
  ctx.data = {
@@ -3339,14 +3341,11 @@ function createSsrContext(serverCtx, dataStore) {
3339
3341
  };
3340
3342
  return ctx;
3341
3343
  }
3342
- function serializeData(data) {
3343
- const json = JSON.stringify(Object.fromEntries(data)).replace(/</g, "\\u003c");
3344
- return `<script>window.__DATA__=${json};</script>`;
3345
- }
3346
3344
  async function ssrToString(Comp, props, serverCtx, opts = {}) {
3347
3345
  const dataStore = opts.data ?? /* @__PURE__ */ new Map();
3348
- const ctx = createSsrContext(serverCtx, dataStore);
3349
- return renderSsr({ type: Comp, props: props ?? {}, key: void 0 }, ctx);
3346
+ const ctx = createSsrContext(serverCtx ?? {}, dataStore);
3347
+ const vnode = createVNode(Comp, props ?? {});
3348
+ return x2html(vnode, ctx);
3350
3349
  }
3351
3350
 
3352
3351
  // src/ui/index.ts
@@ -4780,8 +4779,8 @@ function compileSelect(q) {
4780
4779
  if (q.where) sql += ` WHERE ${compileWhere(q.where, params)}`;
4781
4780
  for (const s of q.sub ?? []) {
4782
4781
  const sub = compileSelect(s.query);
4783
- const base = params.length + 1;
4784
- const subSql = sub.sql.replace(/\$(\d+)/g, (_m, n) => `$${base + Number(n) - 1}`);
4782
+ const base2 = params.length + 1;
4783
+ const subSql = sub.sql.replace(/\$(\d+)/g, (_m, n) => `$${base2 + Number(n) - 1}`);
4785
4784
  params.push(...sub.params);
4786
4785
  const op = s.type === "exists" ? s.not ? "NOT EXISTS" : "EXISTS" : s.not ? "NOT IN" : "IN";
4787
4786
  if (s.type === "exists") {
@@ -4865,8 +4864,8 @@ function isColOps(v) {
4865
4864
  return typeof v === "object" && v !== null && !Array.isArray(v) && !isRaw(v);
4866
4865
  }
4867
4866
  function interpRaw(raw, params) {
4868
- const base = params.length;
4869
- const out = raw.__raw.replace(/\$(\d+)/g, (_m, n) => `$${base + Number(n)}`);
4867
+ const base2 = params.length;
4868
+ const out = raw.__raw.replace(/\$(\d+)/g, (_m, n) => `$${base2 + Number(n)}`);
4870
4869
  params.push(...raw.params);
4871
4870
  return out;
4872
4871
  }
@@ -1,5 +1,5 @@
1
1
  /**
2
- * weifuwu/ui-dom AI 解码器 — 消费 wf: 协议(design/ai-contract.md)
2
+ * weifuwu/ui-dom AI 解码器 — 消费 wf: 协议(docs/ai-contract.md)
3
3
  *
4
4
  * 协议的前端参考实现:POST → 解析 SSE → 按事件名分发回调。
5
5
  *
@@ -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';
@@ -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 './vdom/serve.ts';
26
- export type { UIServeOptions, UIServeHandle } from './vdom/serve.ts';
27
- export { patchValue } from './vdom/diff.ts';
28
- export { hydrateVNode } from './vdom/hydration.ts';
29
- export { ssrPage, ssrToString, serializeData } from './vdom/ssr.ts';
30
- export { mountRoot, createVdomContext, mountCommand, unmountCommand, createCommandContainer } from './vdom/mount.ts';
31
- export { buildVNode } from './vdom/build.ts';
32
- export { renderValue } from './vdom/render.ts';
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';