weifuwu 0.38.2 → 0.40.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 +96 -66
- package/dist/client/app.d.ts +2 -6
- package/dist/client/error-boundary.d.ts +2 -2
- package/dist/client/index.d.ts +3 -1
- package/dist/client/index.js +350 -147
- package/dist/client/locale/en_US.d.ts +15 -0
- package/dist/client/locale/zh_CN.d.ts +15 -0
- package/dist/client/popup.d.ts +19 -0
- package/dist/client/render.d.ts +3 -3
- package/dist/client/router.d.ts +1 -1
- package/dist/client/types.d.ts +11 -5
- package/dist/client/vnode.d.ts +11 -2
- package/dist/components/Chart/Chart.d.ts +15 -0
- package/dist/components/Chart/chart-utils.d.ts +53 -0
- package/dist/components/DatePicker/DatePicker.d.ts +18 -0
- package/dist/components/DatePicker/calendar-utils.d.ts +30 -0
- package/dist/components/Dropdown/Dropdown.d.ts +3 -0
- package/dist/components/Editor/Editor.d.ts +13 -0
- package/dist/components/Editor/tools/format.d.ts +10 -0
- package/dist/components/Editor/tools/table.d.ts +7 -0
- package/dist/components/Editor/tools/toolbar.d.ts +9 -0
- package/dist/components/Editor/tools/types.d.ts +15 -0
- package/dist/components/FileUpload/FileUpload.d.ts +3 -0
- package/dist/components/Img/Img.d.ts +0 -2
- package/dist/components/InView/InView.d.ts +2 -17
- package/dist/components/Popover/Popover.d.ts +2 -12
- package/dist/components/Skeleton/Skeleton.d.ts +0 -8
- package/dist/components/Tooltip/Tooltip.d.ts +5 -1
- package/dist/components/index.d.ts +6 -0
- package/dist/components/index.js +1603 -343
- package/dist/components/style.css +734 -153
- package/dist/layout/weifuwu-layout.css +14 -0
- package/package.json +2 -2
package/dist/client/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
// src/client/vnode.ts
|
|
2
2
|
var Fragment = /* @__PURE__ */ Symbol("Fragment");
|
|
3
|
+
var Portal = /* @__PURE__ */ Symbol("Portal");
|
|
3
4
|
function jsx(type, props, key) {
|
|
4
5
|
return {
|
|
5
6
|
type,
|
|
@@ -27,60 +28,17 @@ function normalizeProps(props) {
|
|
|
27
28
|
}
|
|
28
29
|
return result;
|
|
29
30
|
}
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
if (val === null || typeof val !== "object") return val;
|
|
36
|
-
if (val instanceof Node) return val;
|
|
37
|
-
if (typeof Blob !== "undefined" && val instanceof Blob) return val;
|
|
38
|
-
if (wrappedCache.has(val)) return wrappedCache.get(val);
|
|
39
|
-
const handler = Array.isArray(val) ? {
|
|
40
|
-
get(target, key, receiver) {
|
|
41
|
-
const v = Reflect.get(target, key, receiver);
|
|
42
|
-
if (typeof key === "string" && mutationMethods.includes(key) && typeof v === "function") {
|
|
43
|
-
return function(...args) {
|
|
44
|
-
const r = v.apply(target, args);
|
|
45
|
-
dirty();
|
|
46
|
-
return r;
|
|
47
|
-
};
|
|
48
|
-
}
|
|
49
|
-
return wrapDeep(v, dirty);
|
|
50
|
-
},
|
|
51
|
-
set(target, key, v) {
|
|
52
|
-
Reflect.set(target, key, wrapDeep(v, dirty));
|
|
53
|
-
dirty();
|
|
54
|
-
return true;
|
|
55
|
-
}
|
|
56
|
-
} : {
|
|
57
|
-
get(_target, key, receiver) {
|
|
58
|
-
const v = Reflect.get(_target, key, receiver);
|
|
59
|
-
return wrapDeep(v, dirty);
|
|
60
|
-
},
|
|
61
|
-
set(target, key, v) {
|
|
62
|
-
Reflect.set(target, key, wrapDeep(v, dirty));
|
|
63
|
-
dirty();
|
|
64
|
-
return true;
|
|
65
|
-
}
|
|
31
|
+
function createPortal(children, portalKey) {
|
|
32
|
+
return {
|
|
33
|
+
type: Portal,
|
|
34
|
+
props: { children, portalKey },
|
|
35
|
+
key: portalKey ?? void 0
|
|
66
36
|
};
|
|
67
|
-
const proxy = new Proxy(val, handler);
|
|
68
|
-
wrappedCache.set(val, proxy);
|
|
69
|
-
return proxy;
|
|
70
|
-
}
|
|
71
|
-
function createComponentProxy(target, dirty) {
|
|
72
|
-
return new Proxy(target, {
|
|
73
|
-
set(t, k, v) {
|
|
74
|
-
if (t[k] === v) return true;
|
|
75
|
-
t[k] = wrapDeep(v, dirty);
|
|
76
|
-
dirty();
|
|
77
|
-
return true;
|
|
78
|
-
},
|
|
79
|
-
get(t, k) {
|
|
80
|
-
return wrapDeep(t[k], dirty);
|
|
81
|
-
}
|
|
82
|
-
});
|
|
83
37
|
}
|
|
38
|
+
|
|
39
|
+
// src/client/render.ts
|
|
40
|
+
var SVG_NS = "http://www.w3.org/2000/svg";
|
|
41
|
+
var SVG_TAGS = /* @__PURE__ */ new Set(["svg", "path", "circle", "line", "rect", "text", "g", "polyline", "polygon", "ellipse", "defs", "use", "clipPath", "mask", "linearGradient", "radialGradient", "stop", "tspan"]);
|
|
84
42
|
function render(input, ctx) {
|
|
85
43
|
return renderValue(input, ctx);
|
|
86
44
|
}
|
|
@@ -89,6 +47,9 @@ function renderValue(v, ctx) {
|
|
|
89
47
|
if (typeof v === "string" || typeof v === "number") return document.createTextNode(String(v));
|
|
90
48
|
if (Array.isArray(v)) return renderArray(v, ctx);
|
|
91
49
|
const vnode = v;
|
|
50
|
+
if (vnode.type === Portal) {
|
|
51
|
+
return renderPortal(vnode, ctx);
|
|
52
|
+
}
|
|
92
53
|
if (vnode.type === Fragment) {
|
|
93
54
|
const frag = document.createDocumentFragment();
|
|
94
55
|
forEach(vnode.props?.children, (child) => frag.appendChild(renderValue(child, ctx)));
|
|
@@ -97,19 +58,30 @@ function renderValue(v, ctx) {
|
|
|
97
58
|
if (typeof vnode.type === "function") {
|
|
98
59
|
return renderComponent(vnode.type, vnode.props, vnode, ctx);
|
|
99
60
|
}
|
|
100
|
-
const
|
|
61
|
+
const tag = vnode.type;
|
|
62
|
+
const el = SVG_TAGS.has(tag) ? document.createElementNS(SVG_NS, tag) : document.createElement(tag);
|
|
101
63
|
vnode.el = el;
|
|
64
|
+
let selectValue;
|
|
102
65
|
for (const [key, value] of Object.entries(vnode.props ?? {})) {
|
|
103
|
-
if (key === "children" || key === "key" || key === "
|
|
66
|
+
if (key === "children" || key === "key" || key === "value" || key === "innerHTML") continue;
|
|
104
67
|
setProp(el, key, value);
|
|
105
68
|
}
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
69
|
+
if ("value" in (vnode.props ?? {}) && el instanceof HTMLSelectElement) {
|
|
70
|
+
selectValue = vnode.props.value;
|
|
71
|
+
} else if ("value" in (vnode.props ?? {})) {
|
|
72
|
+
setProp(el, "value", vnode.props.value);
|
|
109
73
|
}
|
|
110
|
-
if (vnode.props
|
|
111
|
-
|
|
112
|
-
|
|
74
|
+
if ("innerHTML" in (vnode.props ?? {})) {
|
|
75
|
+
el.innerHTML = String(vnode.props.innerHTML ?? "");
|
|
76
|
+
} else {
|
|
77
|
+
const flatChildren = flattenChildren(vnode.props?.children);
|
|
78
|
+
for (const child of flatChildren) {
|
|
79
|
+
el.appendChild(renderValue(child, ctx));
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
if (selectValue !== void 0) {
|
|
83
|
+
;
|
|
84
|
+
el.value = String(selectValue);
|
|
113
85
|
}
|
|
114
86
|
return el;
|
|
115
87
|
}
|
|
@@ -117,12 +89,34 @@ function renderComponent(Comp, props, vnode, ctx) {
|
|
|
117
89
|
const prev$ = vnode._$;
|
|
118
90
|
if (!prev$) vnode._$ = {};
|
|
119
91
|
ctx.ui = ctx.ui ?? {};
|
|
120
|
-
ctx.ui.ready = !!prev$;
|
|
121
92
|
const _target = vnode._$;
|
|
122
|
-
|
|
93
|
+
_target._hooks = { mount: [], unmount: [], update: [] };
|
|
94
|
+
ctx.ui.onmount = (fn) => {
|
|
95
|
+
_target._hooks.mount = [fn];
|
|
96
|
+
};
|
|
97
|
+
ctx.ui.onunmount = (fn) => {
|
|
98
|
+
_target._hooks.unmount = [fn];
|
|
99
|
+
};
|
|
100
|
+
ctx.ui.onupdate = (fn) => {
|
|
101
|
+
_target._hooks.update = [fn];
|
|
102
|
+
};
|
|
103
|
+
ctx.ui.onmounted = (fn) => {
|
|
104
|
+
_target._onmounted = fn;
|
|
105
|
+
};
|
|
123
106
|
let childVNode;
|
|
124
107
|
try {
|
|
125
108
|
childVNode = Comp(props, ctx);
|
|
109
|
+
if (typeof childVNode !== "function") {
|
|
110
|
+
throw new Error(
|
|
111
|
+
`Component ${Comp.name || "anonymous"} must return a render function. Use (init_props, ctx) => (props) => VNode pattern.`
|
|
112
|
+
);
|
|
113
|
+
}
|
|
114
|
+
vnode._render = childVNode;
|
|
115
|
+
childVNode = childVNode(props);
|
|
116
|
+
if (!prev$) {
|
|
117
|
+
const mh = _target._hooks?.mount;
|
|
118
|
+
if (mh && mh[0]) mh[0]();
|
|
119
|
+
}
|
|
126
120
|
} catch (e) {
|
|
127
121
|
const errHandler = ctx.ui?._errorHandler;
|
|
128
122
|
if (errHandler) {
|
|
@@ -138,13 +132,53 @@ function renderComponent(Comp, props, vnode, ctx) {
|
|
|
138
132
|
return document.createTextNode("");
|
|
139
133
|
}
|
|
140
134
|
vnode._child = childVNode;
|
|
141
|
-
|
|
135
|
+
const rootNode = renderValue(childVNode, ctx);
|
|
136
|
+
if (_target._onmounted && !prev$) {
|
|
137
|
+
const cleanup = _target._onmounted(rootNode);
|
|
138
|
+
if (typeof cleanup === "function") vnode._cleanup = cleanup;
|
|
139
|
+
}
|
|
140
|
+
return rootNode;
|
|
142
141
|
}
|
|
143
142
|
function renderArray(arr, ctx) {
|
|
144
143
|
const frag = document.createDocumentFragment();
|
|
145
144
|
for (const item of arr) frag.appendChild(renderValue(item, ctx));
|
|
146
145
|
return frag;
|
|
147
146
|
}
|
|
147
|
+
function ensurePortalContainer() {
|
|
148
|
+
let c = document.getElementById("__wf_portal");
|
|
149
|
+
if (!c) {
|
|
150
|
+
c = document.createElement("div");
|
|
151
|
+
c.id = "__wf_portal";
|
|
152
|
+
c.style.cssText = "position:fixed;inset:0;pointer-events:none;z-index:9999";
|
|
153
|
+
document.body.appendChild(c);
|
|
154
|
+
}
|
|
155
|
+
return c;
|
|
156
|
+
}
|
|
157
|
+
function renderPortal(vnode, ctx) {
|
|
158
|
+
const container = ensurePortalContainer();
|
|
159
|
+
const sub = document.createElement("div");
|
|
160
|
+
sub.style.pointerEvents = "auto";
|
|
161
|
+
container.appendChild(sub);
|
|
162
|
+
vnode._portalEl = sub;
|
|
163
|
+
const children = normalize(vnode.props?.children);
|
|
164
|
+
vnode._child = children;
|
|
165
|
+
for (const child of children) {
|
|
166
|
+
sub.appendChild(renderValue(child, ctx));
|
|
167
|
+
}
|
|
168
|
+
const placeholder = document.createTextNode("");
|
|
169
|
+
vnode.el = placeholder;
|
|
170
|
+
return placeholder;
|
|
171
|
+
}
|
|
172
|
+
function patchPortal(_parent, oldNode, oldV, newV, ctx) {
|
|
173
|
+
const sub = oldV._portalEl;
|
|
174
|
+
newV._portalEl = sub;
|
|
175
|
+
if (!sub) return renderPortal(newV, ctx);
|
|
176
|
+
const newChildren = normalize(newV.props?.children);
|
|
177
|
+
const oldChildren = oldV._child || [];
|
|
178
|
+
newV._child = newChildren;
|
|
179
|
+
patchSimpleChildren(sub, oldChildren, newChildren, ctx);
|
|
180
|
+
return oldNode ?? document.createTextNode("");
|
|
181
|
+
}
|
|
148
182
|
function forEach(children, fn) {
|
|
149
183
|
if (children == null) return;
|
|
150
184
|
if (Array.isArray(children)) {
|
|
@@ -168,12 +202,17 @@ function flattenChildren(children) {
|
|
|
168
202
|
}
|
|
169
203
|
function setProp(el, key, value) {
|
|
170
204
|
if (key === "class" || key === "className") {
|
|
171
|
-
el.
|
|
205
|
+
if (el instanceof SVGElement) el.setAttribute("class", String(value ?? ""));
|
|
206
|
+
else el.className = String(value ?? "");
|
|
172
207
|
} else if (key === "style" && typeof value === "object" && value !== null) {
|
|
173
|
-
|
|
208
|
+
const st = el.style;
|
|
209
|
+
for (const sk of Object.keys(value)) {
|
|
210
|
+
const sv = value[sk];
|
|
211
|
+
if (sv != null) st[sk] = typeof sv === "number" ? sv + "px" : String(sv);
|
|
212
|
+
}
|
|
174
213
|
} else if (key.startsWith("on") && typeof value === "function") {
|
|
175
214
|
el.addEventListener(key.slice(2).toLowerCase(), value);
|
|
176
|
-
} else if (key === "value" && (el instanceof HTMLInputElement || el instanceof HTMLTextAreaElement)) {
|
|
215
|
+
} else if (key === "value" && (el instanceof HTMLInputElement || el instanceof HTMLTextAreaElement || el instanceof HTMLSelectElement)) {
|
|
177
216
|
;
|
|
178
217
|
el.value = String(value ?? "");
|
|
179
218
|
} else if (value === true) {
|
|
@@ -221,13 +260,61 @@ function patchValue(parent, oldNode, oldInput, newInput, ctx) {
|
|
|
221
260
|
if (typeof newV.type === "function") {
|
|
222
261
|
const comp = newV.type;
|
|
223
262
|
if (oldV._$) newV._$ = oldV._$;
|
|
263
|
+
if (!newV._$) newV._$ = {};
|
|
224
264
|
ctx.ui = ctx.ui ?? {};
|
|
225
|
-
ctx.ui.ready = !!newV._$;
|
|
226
265
|
const _tgt = newV._$;
|
|
227
|
-
|
|
228
|
-
|
|
266
|
+
if (oldV._render) newV._render = oldV._render;
|
|
267
|
+
if (oldV._cleanup) newV._cleanup = oldV._cleanup;
|
|
268
|
+
if (_tgt._hooks) {
|
|
269
|
+
;
|
|
270
|
+
ctx.ui.onmount = (fn) => {
|
|
271
|
+
_tgt._hooks.mount = [fn];
|
|
272
|
+
};
|
|
273
|
+
ctx.ui.onunmount = (fn) => {
|
|
274
|
+
_tgt._hooks.unmount = [fn];
|
|
275
|
+
};
|
|
276
|
+
ctx.ui.onupdate = (fn) => {
|
|
277
|
+
_tgt._hooks.update = [fn];
|
|
278
|
+
};
|
|
279
|
+
}
|
|
280
|
+
if (_tgt._onmounted) {
|
|
281
|
+
;
|
|
282
|
+
ctx.ui.onmounted = (fn) => {
|
|
283
|
+
_tgt._onmounted = fn;
|
|
284
|
+
};
|
|
285
|
+
}
|
|
286
|
+
if (oldV._$) {
|
|
287
|
+
const uh = _tgt._hooks?.update;
|
|
288
|
+
if (uh && uh[0]) uh[0](oldV.props);
|
|
289
|
+
}
|
|
290
|
+
let childNew;
|
|
291
|
+
try {
|
|
292
|
+
if (typeof newV._render === "function") {
|
|
293
|
+
childNew = newV._render(newV.props);
|
|
294
|
+
} else {
|
|
295
|
+
childNew = comp(newV.props, ctx);
|
|
296
|
+
if (typeof childNew === "function") {
|
|
297
|
+
newV._render = childNew;
|
|
298
|
+
childNew = childNew(newV.props);
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
} catch (e) {
|
|
302
|
+
const errHandler = ctx.ui?._errorHandler;
|
|
303
|
+
if (errHandler) {
|
|
304
|
+
errHandler(e);
|
|
305
|
+
childNew = null;
|
|
306
|
+
} else {
|
|
307
|
+
console.error("Component render error:", e);
|
|
308
|
+
childNew = null;
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
const _prevChild = oldV._child;
|
|
229
312
|
newV._child = childNew;
|
|
230
|
-
|
|
313
|
+
if (childNew == null && _tgt._hooks?.unmount?.length) {
|
|
314
|
+
_tgt._hooks.unmount[0]?.();
|
|
315
|
+
_tgt._hooks.unmount = [];
|
|
316
|
+
}
|
|
317
|
+
return patchValue(parent, oldNode, _prevChild, childNew, ctx);
|
|
231
318
|
}
|
|
232
319
|
if (newV.type === Fragment) {
|
|
233
320
|
patchChildren(parent, oldV, newV, ctx);
|
|
@@ -237,7 +324,6 @@ function patchValue(parent, oldNode, oldInput, newInput, ctx) {
|
|
|
237
324
|
if (oldNode && oldNode.nodeType === 1) {
|
|
238
325
|
patchProps(oldNode, oldV.props, newV.props);
|
|
239
326
|
patchChildren(oldNode, oldV, newV, ctx);
|
|
240
|
-
if (oldV._cleanup) newV._cleanup = oldV._cleanup;
|
|
241
327
|
} else if (oldNode) {
|
|
242
328
|
callRefCleanup(oldInput);
|
|
243
329
|
const node = renderValue(newInput, ctx);
|
|
@@ -246,6 +332,9 @@ function patchValue(parent, oldNode, oldInput, newInput, ctx) {
|
|
|
246
332
|
}
|
|
247
333
|
return oldNode;
|
|
248
334
|
}
|
|
335
|
+
if (newV.type === Portal) {
|
|
336
|
+
return patchPortal(parent, oldNode, oldV, newV, ctx);
|
|
337
|
+
}
|
|
249
338
|
if (Array.isArray(newInput)) {
|
|
250
339
|
const oldArr = Array.isArray(oldInput) ? oldInput : [];
|
|
251
340
|
patchSimpleChildren(parent, oldArr, newInput, ctx);
|
|
@@ -260,17 +349,18 @@ function typeOf(input) {
|
|
|
260
349
|
const v = input;
|
|
261
350
|
if (typeof v.type === "function") return `fn:${v.type.name || "anon"}`;
|
|
262
351
|
if (v.type === Fragment) return "fragment";
|
|
352
|
+
if (v.type === Portal) return "portal";
|
|
263
353
|
if (typeof v.type === "string") return "tag:" + v.type;
|
|
264
354
|
return "unknown";
|
|
265
355
|
}
|
|
266
356
|
function patchProps(el, oldProps, newProps) {
|
|
267
|
-
const oldKeys = oldProps ? Object.keys(oldProps).filter((k) => k !== "children" && k !== "key" && k !== "
|
|
268
|
-
const newKeys = newProps ? Object.keys(newProps).filter((k) => k !== "children" && k !== "key" && k !== "
|
|
357
|
+
const oldKeys = oldProps ? Object.keys(oldProps).filter((k) => k !== "children" && k !== "key" && k !== "innerHTML") : [];
|
|
358
|
+
const newKeys = newProps ? Object.keys(newProps).filter((k) => k !== "children" && k !== "key" && k !== "innerHTML") : [];
|
|
269
359
|
for (const key of oldKeys) {
|
|
270
360
|
if (!newKeys.includes(key)) {
|
|
271
361
|
if (key.startsWith("on") && typeof oldProps[key] === "function") {
|
|
272
362
|
el.removeEventListener(key.slice(2).toLowerCase(), oldProps[key]);
|
|
273
|
-
} else if (key === "value" && (el instanceof HTMLInputElement || el instanceof HTMLTextAreaElement)) {
|
|
363
|
+
} else if (key === "value" && (el instanceof HTMLInputElement || el instanceof HTMLTextAreaElement || el instanceof HTMLSelectElement)) {
|
|
274
364
|
;
|
|
275
365
|
el.value = "";
|
|
276
366
|
} else {
|
|
@@ -281,16 +371,23 @@ function patchProps(el, oldProps, newProps) {
|
|
|
281
371
|
for (const key of newKeys) {
|
|
282
372
|
const oldVal = oldProps?.[key];
|
|
283
373
|
const newVal = newProps?.[key];
|
|
284
|
-
if (
|
|
374
|
+
if (key === "innerHTML") {
|
|
375
|
+
if (newVal !== oldVal) el.innerHTML = String(newVal ?? "");
|
|
376
|
+
} else if (newVal !== oldVal) {
|
|
285
377
|
if (key === "class" || key === "className") {
|
|
286
|
-
el.
|
|
378
|
+
if (el instanceof SVGElement) el.setAttribute("class", String(newVal ?? ""));
|
|
379
|
+
else el.className = String(newVal ?? "");
|
|
287
380
|
} else if (key === "style" && typeof newVal === "object") {
|
|
288
|
-
|
|
381
|
+
const st = el.style;
|
|
382
|
+
for (const sk of Object.keys(newVal)) {
|
|
383
|
+
const sv = newVal[sk];
|
|
384
|
+
if (sv != null) st[sk] = typeof sv === "number" ? sv + "px" : String(sv);
|
|
385
|
+
}
|
|
289
386
|
} else if (key.startsWith("on") && typeof newVal === "function") {
|
|
290
387
|
const eventName = key.slice(2).toLowerCase();
|
|
291
388
|
if (typeof oldVal === "function") el.removeEventListener(eventName, oldVal);
|
|
292
389
|
el.addEventListener(eventName, newVal);
|
|
293
|
-
} else if (key === "value" && (el instanceof HTMLInputElement || el instanceof HTMLTextAreaElement)) {
|
|
390
|
+
} else if (key === "value" && (el instanceof HTMLInputElement || el instanceof HTMLTextAreaElement || el instanceof HTMLSelectElement)) {
|
|
294
391
|
;
|
|
295
392
|
el.value = String(newVal ?? "");
|
|
296
393
|
} else if (newVal === true) {
|
|
@@ -298,7 +395,7 @@ function patchProps(el, oldProps, newProps) {
|
|
|
298
395
|
} else if (newVal != null && newVal !== false) {
|
|
299
396
|
el.setAttribute(key, String(newVal));
|
|
300
397
|
} else {
|
|
301
|
-
if (key === "value" && (el instanceof HTMLInputElement || el instanceof HTMLTextAreaElement)) {
|
|
398
|
+
if (key === "value" && (el instanceof HTMLInputElement || el instanceof HTMLTextAreaElement || el instanceof HTMLSelectElement)) {
|
|
302
399
|
;
|
|
303
400
|
el.value = "";
|
|
304
401
|
} else {
|
|
@@ -405,15 +502,46 @@ function runRefCleanup(vnode) {
|
|
|
405
502
|
vnode._cleanup();
|
|
406
503
|
vnode._cleanup = void 0;
|
|
407
504
|
}
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
505
|
+
}
|
|
506
|
+
function cleanupPortalChildren(vnode) {
|
|
507
|
+
const child = vnode._child;
|
|
508
|
+
if (child == null) return;
|
|
509
|
+
if (Array.isArray(child)) {
|
|
510
|
+
for (const c of child) {
|
|
511
|
+
if (c && typeof c === "object") callRefCleanup(c);
|
|
411
512
|
}
|
|
412
|
-
})
|
|
513
|
+
} else if (typeof child === "object") {
|
|
514
|
+
callRefCleanup(child);
|
|
515
|
+
}
|
|
413
516
|
}
|
|
414
517
|
function callRefCleanup(input) {
|
|
415
518
|
if (input == null || typeof input !== "object") return;
|
|
416
519
|
const vnode = input;
|
|
520
|
+
if (vnode._child != null) {
|
|
521
|
+
if (Array.isArray(vnode._child)) {
|
|
522
|
+
for (const child of vnode._child) {
|
|
523
|
+
if (child && typeof child === "object") callRefCleanup(child);
|
|
524
|
+
}
|
|
525
|
+
} else {
|
|
526
|
+
callRefCleanup(vnode._child);
|
|
527
|
+
}
|
|
528
|
+
vnode._child = void 0;
|
|
529
|
+
}
|
|
530
|
+
if (vnode.props?.children && typeof vnode.type === "string") {
|
|
531
|
+
const children = Array.isArray(vnode.props.children) ? vnode.props.children : [vnode.props.children];
|
|
532
|
+
for (const child of children) {
|
|
533
|
+
if (child && typeof child === "object") callRefCleanup(child);
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
if (vnode._$ && vnode._$._hooks?.unmount) {
|
|
537
|
+
vnode._$._hooks.unmount[0]?.();
|
|
538
|
+
vnode._$._hooks.unmount = [];
|
|
539
|
+
}
|
|
540
|
+
if (vnode._portalEl) {
|
|
541
|
+
cleanupPortalChildren(vnode);
|
|
542
|
+
vnode._portalEl.remove();
|
|
543
|
+
vnode._portalEl = void 0;
|
|
544
|
+
}
|
|
417
545
|
if (vnode._cleanup) runRefCleanup(vnode);
|
|
418
546
|
}
|
|
419
547
|
|
|
@@ -518,18 +646,20 @@ function router(opts) {
|
|
|
518
646
|
};
|
|
519
647
|
}
|
|
520
648
|
function RouteView(_props, ctx) {
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
649
|
+
return () => {
|
|
650
|
+
const route = ctx.route;
|
|
651
|
+
if (!route?.chain?.length) return null;
|
|
652
|
+
const ctxAny = ctx;
|
|
653
|
+
const depth = layoutDepth.get(ctxAny) ?? 0;
|
|
654
|
+
if (depth >= route.chain.length) return null;
|
|
655
|
+
const def = route.chain[depth];
|
|
656
|
+
const Comp = def.layout ?? def.component;
|
|
657
|
+
if (!Comp) return null;
|
|
658
|
+
if (def.layout) {
|
|
659
|
+
layoutDepth.set(ctxAny, depth + 1);
|
|
660
|
+
}
|
|
661
|
+
return { type: Comp, props: {}, key: void 0 };
|
|
662
|
+
};
|
|
533
663
|
}
|
|
534
664
|
|
|
535
665
|
// src/client/app.ts
|
|
@@ -558,43 +688,41 @@ function createApp() {
|
|
|
558
688
|
container = el;
|
|
559
689
|
container.innerHTML = "";
|
|
560
690
|
let _dirty = false;
|
|
561
|
-
|
|
562
|
-
|
|
691
|
+
let _rendering = false;
|
|
692
|
+
const doRender = () => {
|
|
693
|
+
if (_rendering || !container || !rootComponent || !oldVNode) return;
|
|
694
|
+
_rendering = true;
|
|
695
|
+
layoutDepth.delete(ctx);
|
|
696
|
+
const newVNode = wrapComponent(rootComponent, ctx);
|
|
697
|
+
const oldNode = container.firstChild;
|
|
698
|
+
if (oldNode) {
|
|
699
|
+
patchValue(container, oldNode, oldVNode, newVNode, ctx);
|
|
700
|
+
}
|
|
701
|
+
oldVNode = newVNode;
|
|
702
|
+
_rendering = false;
|
|
703
|
+
};
|
|
704
|
+
const scheduleRender = () => {
|
|
705
|
+
if (_dirty || _rendering) return;
|
|
563
706
|
_dirty = true;
|
|
564
707
|
queueMicrotask(() => {
|
|
565
708
|
if (!_dirty) return;
|
|
566
709
|
_dirty = false;
|
|
567
|
-
|
|
710
|
+
doRender();
|
|
568
711
|
});
|
|
569
|
-
}
|
|
570
|
-
;
|
|
712
|
+
};
|
|
571
713
|
ctx.ui = {
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
if (oldNode) {
|
|
579
|
-
patchValue(container, oldNode, oldVNode, newVNode, ctx);
|
|
580
|
-
}
|
|
581
|
-
oldVNode = newVNode;
|
|
582
|
-
},
|
|
583
|
-
/** 极少需要:仅当绕过 Proxy 直接操作底层对象时使用 */
|
|
584
|
-
dirty: () => {
|
|
585
|
-
scheduleRender();
|
|
586
|
-
},
|
|
587
|
-
/**
|
|
588
|
-
* 组件级 $ — 在 renderComponent 中被覆盖为每个组件独立的 Proxy。
|
|
589
|
-
* 这里保留占位,组件实际使用 ctx.ui.$ 时拿到的是 vnode._$ 上的 Proxy。
|
|
590
|
-
*/
|
|
591
|
-
$: {},
|
|
592
|
-
ready: false
|
|
714
|
+
/** 立即同步渲染 */
|
|
715
|
+
render: doRender,
|
|
716
|
+
/** 标记脏状态,下个微任务批量渲染 */
|
|
717
|
+
dirty: scheduleRender,
|
|
718
|
+
/** 创建响应式状态容器:$.x = val 自动触发 dirty()(仅事件/timer 中生效) */
|
|
719
|
+
$: () => createReactiveState(scheduleRender)
|
|
593
720
|
};
|
|
721
|
+
_rendering = true;
|
|
594
722
|
oldVNode = wrapComponent(RootComponent, ctx);
|
|
595
723
|
const node = render(oldVNode, ctx);
|
|
596
724
|
if (node instanceof Node) container.appendChild(node);
|
|
597
|
-
|
|
725
|
+
_rendering = false;
|
|
598
726
|
rendered = true;
|
|
599
727
|
},
|
|
600
728
|
destroy() {
|
|
@@ -608,6 +736,20 @@ function createApp() {
|
|
|
608
736
|
function wrapComponent(Comp, _ctx) {
|
|
609
737
|
return { type: Comp, props: {}, key: void 0 };
|
|
610
738
|
}
|
|
739
|
+
function createReactiveState(dirty) {
|
|
740
|
+
return new Proxy({}, {
|
|
741
|
+
set(target, key, value) {
|
|
742
|
+
const old = Reflect.get(target, key);
|
|
743
|
+
if (old === value) return true;
|
|
744
|
+
Reflect.set(target, key, value);
|
|
745
|
+
dirty();
|
|
746
|
+
return true;
|
|
747
|
+
},
|
|
748
|
+
get(target, key) {
|
|
749
|
+
return Reflect.get(target, key);
|
|
750
|
+
}
|
|
751
|
+
});
|
|
752
|
+
}
|
|
611
753
|
|
|
612
754
|
// src/client/types.ts
|
|
613
755
|
function extendCtx(ctx, fields) {
|
|
@@ -872,31 +1014,32 @@ function auth(options) {
|
|
|
872
1014
|
|
|
873
1015
|
// src/client/error-boundary.ts
|
|
874
1016
|
function ErrorBoundary(props, ctx) {
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
1017
|
+
let error = null;
|
|
1018
|
+
return (props2) => {
|
|
1019
|
+
if (error) {
|
|
1020
|
+
const fb = props2.fallback;
|
|
1021
|
+
if (typeof fb === "function") {
|
|
1022
|
+
return fb({ error });
|
|
1023
|
+
}
|
|
1024
|
+
return fb ?? null;
|
|
881
1025
|
}
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
return fb
|
|
1026
|
+
;
|
|
1027
|
+
ctx.ui._errorHandler = (err) => {
|
|
1028
|
+
error = err;
|
|
1029
|
+
ctx.ui.render();
|
|
1030
|
+
};
|
|
1031
|
+
const children = props2.children;
|
|
1032
|
+
try {
|
|
1033
|
+
return children ?? null;
|
|
1034
|
+
} catch (e) {
|
|
1035
|
+
error = e;
|
|
1036
|
+
const fb = props2.fallback;
|
|
1037
|
+
if (typeof fb === "function") {
|
|
1038
|
+
return fb({ error: e });
|
|
1039
|
+
}
|
|
1040
|
+
return fb ?? null;
|
|
897
1041
|
}
|
|
898
|
-
|
|
899
|
-
}
|
|
1042
|
+
};
|
|
900
1043
|
}
|
|
901
1044
|
|
|
902
1045
|
// src/client/locale/zh_CN.ts
|
|
@@ -914,7 +1057,22 @@ var zhCN = {
|
|
|
914
1057
|
Switch: { ariaLabel: "\u5207\u6362" },
|
|
915
1058
|
Breadcrumb: { ariaLabel: "\u9762\u5305\u5C51" },
|
|
916
1059
|
Modal: { ariaLabel: "\u5F39\u7A97" },
|
|
917
|
-
Drawer: { ariaLabel: "\u4FA7\u8FB9\u9762\u677F" }
|
|
1060
|
+
Drawer: { ariaLabel: "\u4FA7\u8FB9\u9762\u677F" },
|
|
1061
|
+
DatePicker: {
|
|
1062
|
+
w0: "\u65E5",
|
|
1063
|
+
w1: "\u4E00",
|
|
1064
|
+
w2: "\u4E8C",
|
|
1065
|
+
w3: "\u4E09",
|
|
1066
|
+
w4: "\u56DB",
|
|
1067
|
+
w5: "\u4E94",
|
|
1068
|
+
w6: "\u516D",
|
|
1069
|
+
hour: "\u65F6",
|
|
1070
|
+
minute: "\u5206",
|
|
1071
|
+
time: "\u65F6\u95F4",
|
|
1072
|
+
confirm: "\u786E\u5B9A",
|
|
1073
|
+
cancel: "\u53D6\u6D88",
|
|
1074
|
+
placeholder: "\u9009\u62E9\u65E5\u671F"
|
|
1075
|
+
}
|
|
918
1076
|
}
|
|
919
1077
|
};
|
|
920
1078
|
|
|
@@ -933,7 +1091,22 @@ var enUS = {
|
|
|
933
1091
|
Switch: { ariaLabel: "Toggle" },
|
|
934
1092
|
Breadcrumb: { ariaLabel: "Breadcrumb" },
|
|
935
1093
|
Modal: { ariaLabel: "Dialog" },
|
|
936
|
-
Drawer: { ariaLabel: "Panel" }
|
|
1094
|
+
Drawer: { ariaLabel: "Panel" },
|
|
1095
|
+
DatePicker: {
|
|
1096
|
+
w0: "Su",
|
|
1097
|
+
w1: "Mo",
|
|
1098
|
+
w2: "Tu",
|
|
1099
|
+
w3: "We",
|
|
1100
|
+
w4: "Th",
|
|
1101
|
+
w5: "Fr",
|
|
1102
|
+
w6: "Sa",
|
|
1103
|
+
hour: "Hour",
|
|
1104
|
+
minute: "Min",
|
|
1105
|
+
time: "Time",
|
|
1106
|
+
confirm: "OK",
|
|
1107
|
+
cancel: "Cancel",
|
|
1108
|
+
placeholder: "Pick a date"
|
|
1109
|
+
}
|
|
937
1110
|
}
|
|
938
1111
|
};
|
|
939
1112
|
|
|
@@ -1060,6 +1233,33 @@ function trapFocus(container) {
|
|
|
1060
1233
|
};
|
|
1061
1234
|
}
|
|
1062
1235
|
|
|
1236
|
+
// src/client/popup.ts
|
|
1237
|
+
function computeFixedPos(el, placement = "bottom", gap = 6, center = true) {
|
|
1238
|
+
const rect = el.getBoundingClientRect();
|
|
1239
|
+
switch (placement) {
|
|
1240
|
+
case "bottom":
|
|
1241
|
+
return {
|
|
1242
|
+
top: rect.bottom + gap,
|
|
1243
|
+
left: center ? rect.left + rect.width / 2 : rect.left
|
|
1244
|
+
};
|
|
1245
|
+
case "top":
|
|
1246
|
+
return {
|
|
1247
|
+
top: rect.top - gap,
|
|
1248
|
+
left: center ? rect.left + rect.width / 2 : rect.left
|
|
1249
|
+
};
|
|
1250
|
+
case "left":
|
|
1251
|
+
return {
|
|
1252
|
+
top: center ? rect.top + rect.height / 2 : rect.top,
|
|
1253
|
+
left: rect.left - gap
|
|
1254
|
+
};
|
|
1255
|
+
case "right":
|
|
1256
|
+
return {
|
|
1257
|
+
top: center ? rect.top + rect.height / 2 : rect.top,
|
|
1258
|
+
left: rect.right + gap
|
|
1259
|
+
};
|
|
1260
|
+
}
|
|
1261
|
+
}
|
|
1262
|
+
|
|
1063
1263
|
// src/client/confirm.ts
|
|
1064
1264
|
function createConfirmModal(message, options) {
|
|
1065
1265
|
return new Promise((resolve) => {
|
|
@@ -1135,11 +1335,14 @@ export {
|
|
|
1135
1335
|
ApiError,
|
|
1136
1336
|
ErrorBoundary,
|
|
1137
1337
|
Fragment,
|
|
1338
|
+
Portal,
|
|
1138
1339
|
RouteView,
|
|
1139
1340
|
api,
|
|
1140
1341
|
auth,
|
|
1342
|
+
computeFixedPos,
|
|
1141
1343
|
confirm,
|
|
1142
1344
|
createApp,
|
|
1345
|
+
createPortal,
|
|
1143
1346
|
enUS,
|
|
1144
1347
|
extendCtx,
|
|
1145
1348
|
h,
|