weifuwu 0.36.2 → 0.38.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 +141 -3
- package/dist/client/app.d.ts +4 -7
- package/dist/client/confirm.d.ts +26 -0
- package/dist/client/focus-trap.d.ts +4 -0
- package/dist/client/i18n.d.ts +27 -0
- package/dist/client/index.d.ts +8 -0
- package/dist/client/index.js +322 -60
- package/dist/client/locale/en_US.d.ts +34 -0
- package/dist/client/locale/zh_CN.d.ts +34 -0
- package/dist/client/scroll-lock.d.ts +5 -0
- package/dist/components/Accordion/Accordion.d.ts +11 -0
- package/dist/components/Alert/Alert.d.ts +9 -0
- package/dist/components/Avatar/Avatar.d.ts +7 -0
- package/dist/components/Badge/Badge.d.ts +8 -0
- package/dist/components/Breadcrumb/Breadcrumb.d.ts +9 -0
- package/dist/components/Button/Button.d.ts +12 -0
- package/dist/components/Card/Card.d.ts +9 -0
- package/dist/components/Checkbox/Checkbox.d.ts +8 -0
- package/dist/components/Divider/Divider.d.ts +6 -0
- package/dist/components/Drawer/Drawer.d.ts +14 -0
- package/dist/components/Dropdown/Dropdown.d.ts +14 -0
- package/dist/components/EmptyState/EmptyState.d.ts +8 -0
- package/dist/components/Field/Field.d.ts +9 -0
- package/dist/components/FileUpload/FileUpload.d.ts +13 -0
- package/dist/components/Form/Form.d.ts +6 -0
- package/dist/components/Img/Img.d.ts +17 -0
- package/dist/components/Input/Input.d.ts +14 -0
- package/dist/components/Loading/Loading.d.ts +5 -0
- package/dist/components/Modal/Modal.d.ts +12 -0
- package/dist/components/PageHeader/PageHeader.d.ts +7 -0
- package/dist/components/Pagination/Pagination.d.ts +8 -0
- package/dist/components/Popover/Popover.d.ts +26 -0
- package/dist/components/ProgressBar/ProgressBar.d.ts +8 -0
- package/dist/components/RadioGroup/RadioGroup.d.ts +14 -0
- package/dist/components/SearchInput/SearchInput.d.ts +8 -0
- package/dist/components/Select/Select.d.ts +18 -0
- package/dist/components/Skeleton/Skeleton.d.ts +21 -0
- package/dist/components/Slider/Slider.d.ts +10 -0
- package/dist/components/StatCard/StatCard.d.ts +9 -0
- package/dist/components/Steps/Steps.d.ts +12 -0
- package/dist/components/Switch/Switch.d.ts +8 -0
- package/dist/components/Table/Table.d.ts +13 -0
- package/dist/components/Tabs/Tabs.d.ts +12 -0
- package/dist/components/Tag/Tag.d.ts +8 -0
- package/dist/components/Textarea/Textarea.d.ts +13 -0
- package/dist/components/Toast/Toast.d.ts +12 -0
- package/dist/components/Tooltip/Tooltip.d.ts +9 -0
- package/dist/components/index.d.ts +81 -0
- package/dist/components/index.js +1064 -0
- package/dist/components/style.css +2005 -0
- package/package.json +7 -2
package/dist/client/index.js
CHANGED
|
@@ -29,6 +29,58 @@ function normalizeProps(props) {
|
|
|
29
29
|
}
|
|
30
30
|
|
|
31
31
|
// src/client/render.ts
|
|
32
|
+
var mutationMethods = ["push", "pop", "splice", "shift", "unshift", "sort", "reverse"];
|
|
33
|
+
var wrappedCache = /* @__PURE__ */ new WeakMap();
|
|
34
|
+
function wrapDeep(val, dirty) {
|
|
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
|
+
}
|
|
66
|
+
};
|
|
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
|
+
}
|
|
32
84
|
function render(input, ctx) {
|
|
33
85
|
return renderValue(input, ctx);
|
|
34
86
|
}
|
|
@@ -66,6 +118,8 @@ function renderComponent(Comp, props, vnode, ctx) {
|
|
|
66
118
|
if (!prev$) vnode._$ = {};
|
|
67
119
|
ctx.ui = ctx.ui ?? {};
|
|
68
120
|
ctx.ui.ready = !!prev$;
|
|
121
|
+
const _target = vnode._$;
|
|
122
|
+
ctx.ui.$ = createComponentProxy(_target, () => ctx.ui?.dirty?.());
|
|
69
123
|
let childVNode;
|
|
70
124
|
try {
|
|
71
125
|
childVNode = Comp(props, ctx);
|
|
@@ -169,6 +223,8 @@ function patchValue(parent, oldNode, oldInput, newInput, ctx) {
|
|
|
169
223
|
if (oldV._$) newV._$ = oldV._$;
|
|
170
224
|
ctx.ui = ctx.ui ?? {};
|
|
171
225
|
ctx.ui.ready = !!newV._$;
|
|
226
|
+
const _tgt = newV._$;
|
|
227
|
+
ctx.ui.$ = createComponentProxy(_tgt, () => ctx.ui?.dirty?.());
|
|
172
228
|
const childNew = comp(newV.props, ctx);
|
|
173
229
|
newV._child = childNew;
|
|
174
230
|
return patchValue(parent, oldNode, oldV._child, childNew, ctx);
|
|
@@ -211,7 +267,9 @@ function patchProps(el, oldProps, newProps) {
|
|
|
211
267
|
const newKeys = newProps ? Object.keys(newProps).filter((k) => k !== "children" && k !== "key" && k !== "ref") : [];
|
|
212
268
|
for (const key of oldKeys) {
|
|
213
269
|
if (!newKeys.includes(key)) {
|
|
214
|
-
if (key
|
|
270
|
+
if (key.startsWith("on") && typeof oldProps[key] === "function") {
|
|
271
|
+
el.removeEventListener(key.slice(2).toLowerCase(), oldProps[key]);
|
|
272
|
+
} else if (key === "value" && (el instanceof HTMLInputElement || el instanceof HTMLTextAreaElement)) {
|
|
215
273
|
;
|
|
216
274
|
el.value = "";
|
|
217
275
|
} else {
|
|
@@ -277,6 +335,14 @@ function normalize(children) {
|
|
|
277
335
|
return result;
|
|
278
336
|
}
|
|
279
337
|
function patchSimpleChildren(parent, oldChildren, newChildren, ctx) {
|
|
338
|
+
for (let i = oldChildren.length - 1; i >= newChildren.length; i--) {
|
|
339
|
+
const oldChild = oldChildren[i];
|
|
340
|
+
const node = parent.childNodes[i];
|
|
341
|
+
if (node) {
|
|
342
|
+
callRefCleanup(oldChild);
|
|
343
|
+
node.remove();
|
|
344
|
+
}
|
|
345
|
+
}
|
|
280
346
|
const max = Math.max(oldChildren.length, newChildren.length);
|
|
281
347
|
for (let i = 0; i < max; i++) {
|
|
282
348
|
const oldChild = oldChildren[i];
|
|
@@ -285,12 +351,7 @@ function patchSimpleChildren(parent, oldChildren, newChildren, ctx) {
|
|
|
285
351
|
if (oldChild === void 0 && newChild !== void 0) {
|
|
286
352
|
const node = renderValue(newChild, ctx);
|
|
287
353
|
parent.appendChild(node);
|
|
288
|
-
} else if (newChild
|
|
289
|
-
if (existingNode) {
|
|
290
|
-
callRefCleanup(oldChild);
|
|
291
|
-
existingNode.remove();
|
|
292
|
-
}
|
|
293
|
-
} else {
|
|
354
|
+
} else if (oldChild !== void 0 && newChild !== void 0) {
|
|
294
355
|
patchValue(parent, existingNode, oldChild, newChild, ctx);
|
|
295
356
|
}
|
|
296
357
|
}
|
|
@@ -413,18 +474,21 @@ function router(opts) {
|
|
|
413
474
|
params[match.keys[i]] = decodeURIComponent(m[i + 1]);
|
|
414
475
|
}
|
|
415
476
|
}
|
|
477
|
+
const last = match.chain[match.chain.length - 1];
|
|
416
478
|
return {
|
|
417
479
|
path: match.def.path,
|
|
418
480
|
params,
|
|
419
481
|
query: Object.fromEntries(new URLSearchParams(window.location.search)),
|
|
420
|
-
chain: match.chain
|
|
482
|
+
chain: match.chain,
|
|
483
|
+
title: last?.title ?? ""
|
|
421
484
|
};
|
|
422
485
|
}
|
|
423
|
-
return { path, params: {}, query: {}, chain: [] };
|
|
486
|
+
return { path, params: {}, query: {}, chain: [], title: "" };
|
|
424
487
|
}
|
|
425
488
|
return (ctx) => {
|
|
426
489
|
const resolved = resolve(getPath());
|
|
427
490
|
ctx.route = resolved;
|
|
491
|
+
if (resolved.title) document.title = resolved.title;
|
|
428
492
|
if (!ctx.app) ctx.app = {};
|
|
429
493
|
ctx.app.navigate = (path) => {
|
|
430
494
|
if (mode === "hash") {
|
|
@@ -436,11 +500,13 @@ function router(opts) {
|
|
|
436
500
|
const resolved2 = resolve(path);
|
|
437
501
|
ctx.route = resolved2;
|
|
438
502
|
}
|
|
503
|
+
if (ctx.route?.title) document.title = ctx.route.title;
|
|
439
504
|
ctx.ui?.render();
|
|
440
505
|
};
|
|
441
506
|
const onPop = () => {
|
|
442
507
|
const resolved2 = resolve(getPath());
|
|
443
508
|
ctx.route = resolved2;
|
|
509
|
+
if (ctx.route?.title) document.title = ctx.route.title;
|
|
444
510
|
ctx.ui?.render();
|
|
445
511
|
};
|
|
446
512
|
window.addEventListener("popstate", onPop);
|
|
@@ -466,48 +532,6 @@ function RouteView(_props, ctx) {
|
|
|
466
532
|
}
|
|
467
533
|
|
|
468
534
|
// src/client/app.ts
|
|
469
|
-
var mutationMethods = ["push", "pop", "splice", "shift", "unshift", "sort", "reverse"];
|
|
470
|
-
var wrappedCache = /* @__PURE__ */ new WeakMap();
|
|
471
|
-
function wrapDeep(val, dirty) {
|
|
472
|
-
if (val === null || typeof val !== "object") return val;
|
|
473
|
-
if (val instanceof Node) return val;
|
|
474
|
-
if (wrappedCache.has(val)) return wrappedCache.get(val);
|
|
475
|
-
let proxy;
|
|
476
|
-
if (Array.isArray(val)) {
|
|
477
|
-
proxy = new Proxy(val, {
|
|
478
|
-
get(target, key, receiver) {
|
|
479
|
-
const v = Reflect.get(target, key, receiver);
|
|
480
|
-
if (typeof key === "string" && mutationMethods.includes(key) && typeof v === "function") {
|
|
481
|
-
return function(...args) {
|
|
482
|
-
const r = v.apply(target, args);
|
|
483
|
-
dirty();
|
|
484
|
-
return r;
|
|
485
|
-
};
|
|
486
|
-
}
|
|
487
|
-
return wrapDeep(v, dirty);
|
|
488
|
-
},
|
|
489
|
-
set(target, key, val2) {
|
|
490
|
-
target[key] = wrapDeep(val2, dirty);
|
|
491
|
-
dirty();
|
|
492
|
-
return true;
|
|
493
|
-
}
|
|
494
|
-
});
|
|
495
|
-
} else {
|
|
496
|
-
proxy = new Proxy(val, {
|
|
497
|
-
get(_target, key, receiver) {
|
|
498
|
-
const v = Reflect.get(_target, key, receiver);
|
|
499
|
-
return wrapDeep(v, dirty);
|
|
500
|
-
},
|
|
501
|
-
set(target, key, val2) {
|
|
502
|
-
target[key] = wrapDeep(val2, dirty);
|
|
503
|
-
dirty();
|
|
504
|
-
return true;
|
|
505
|
-
}
|
|
506
|
-
});
|
|
507
|
-
}
|
|
508
|
-
wrappedCache.set(val, proxy);
|
|
509
|
-
return proxy;
|
|
510
|
-
}
|
|
511
535
|
function createApp() {
|
|
512
536
|
const middlewares = [];
|
|
513
537
|
let ctx = {};
|
|
@@ -542,7 +566,7 @@ function createApp() {
|
|
|
542
566
|
ctx.ui.render();
|
|
543
567
|
});
|
|
544
568
|
}
|
|
545
|
-
|
|
569
|
+
;
|
|
546
570
|
ctx.ui = {
|
|
547
571
|
render: () => {
|
|
548
572
|
if (!container || !rootComponent || !oldVNode) return;
|
|
@@ -559,13 +583,11 @@ function createApp() {
|
|
|
559
583
|
dirty: () => {
|
|
560
584
|
scheduleRender();
|
|
561
585
|
},
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
}
|
|
568
|
-
}),
|
|
586
|
+
/**
|
|
587
|
+
* 组件级 $ — 在 renderComponent 中被覆盖为每个组件独立的 Proxy。
|
|
588
|
+
* 这里保留占位,组件实际使用 ctx.ui.$ 时拿到的是 vnode._$ 上的 Proxy。
|
|
589
|
+
*/
|
|
590
|
+
$: {},
|
|
569
591
|
ready: false
|
|
570
592
|
};
|
|
571
593
|
oldVNode = wrapComponent(RootComponent, ctx);
|
|
@@ -875,6 +897,239 @@ function ErrorBoundary(props, ctx) {
|
|
|
875
897
|
return fb ?? null;
|
|
876
898
|
}
|
|
877
899
|
}
|
|
900
|
+
|
|
901
|
+
// src/client/locale/zh_CN.ts
|
|
902
|
+
var zhCN = {
|
|
903
|
+
components: {
|
|
904
|
+
Button: { loading: "\u52A0\u8F7D\u4E2D..." },
|
|
905
|
+
FileUpload: {
|
|
906
|
+
placeholder: "\u70B9\u51FB\u6216\u62D6\u62FD\u4E0A\u4F20\u6587\u4EF6",
|
|
907
|
+
supportedFormats: "\u652F\u6301\u683C\u5F0F: ",
|
|
908
|
+
maxSize: "\u6700\u5927 ",
|
|
909
|
+
remove: "\u5220\u9664"
|
|
910
|
+
},
|
|
911
|
+
Pagination: { ariaLabel: "\u5206\u9875" },
|
|
912
|
+
ProgressBar: { ariaLabel: "\u8FDB\u5EA6" },
|
|
913
|
+
Switch: { ariaLabel: "\u5207\u6362" },
|
|
914
|
+
Breadcrumb: { ariaLabel: "\u9762\u5305\u5C51" },
|
|
915
|
+
Modal: { ariaLabel: "\u5F39\u7A97" },
|
|
916
|
+
Drawer: { ariaLabel: "\u4FA7\u8FB9\u9762\u677F" }
|
|
917
|
+
}
|
|
918
|
+
};
|
|
919
|
+
|
|
920
|
+
// src/client/locale/en_US.ts
|
|
921
|
+
var enUS = {
|
|
922
|
+
components: {
|
|
923
|
+
Button: { loading: "Loading..." },
|
|
924
|
+
FileUpload: {
|
|
925
|
+
placeholder: "Click or drag to upload",
|
|
926
|
+
supportedFormats: "Supported formats: ",
|
|
927
|
+
maxSize: "Max size: ",
|
|
928
|
+
remove: "Remove"
|
|
929
|
+
},
|
|
930
|
+
Pagination: { ariaLabel: "Pagination" },
|
|
931
|
+
ProgressBar: { ariaLabel: "Progress" },
|
|
932
|
+
Switch: { ariaLabel: "Toggle" },
|
|
933
|
+
Breadcrumb: { ariaLabel: "Breadcrumb" },
|
|
934
|
+
Modal: { ariaLabel: "Dialog" },
|
|
935
|
+
Drawer: { ariaLabel: "Panel" }
|
|
936
|
+
}
|
|
937
|
+
};
|
|
938
|
+
|
|
939
|
+
// src/client/i18n.ts
|
|
940
|
+
var LOCALE_PACKAGES = {
|
|
941
|
+
"zh-CN": zhCN,
|
|
942
|
+
"en-US": enUS
|
|
943
|
+
};
|
|
944
|
+
function resolveLang(locale) {
|
|
945
|
+
if (LOCALE_PACKAGES[locale]) return locale;
|
|
946
|
+
const prefix = locale.split("-")[0];
|
|
947
|
+
const match = Object.keys(LOCALE_PACKAGES).find((k) => k.startsWith(prefix));
|
|
948
|
+
return match ?? "zh-CN";
|
|
949
|
+
}
|
|
950
|
+
function i18n(opts = {}) {
|
|
951
|
+
const { locale: raw = "zh-CN", messages = {}, components = {} } = opts;
|
|
952
|
+
const lang = resolveLang(raw);
|
|
953
|
+
const pkg = LOCALE_PACKAGES[lang];
|
|
954
|
+
let merged = mergeLocales(pkg, messages, components);
|
|
955
|
+
const state = {
|
|
956
|
+
locale: lang,
|
|
957
|
+
t: (key, fallback) => merged.messages?.[key] ?? fallback ?? key,
|
|
958
|
+
setLocale: () => {
|
|
959
|
+
},
|
|
960
|
+
components: merged.components
|
|
961
|
+
};
|
|
962
|
+
return (ctx) => {
|
|
963
|
+
;
|
|
964
|
+
ctx.i18n = state;
|
|
965
|
+
state.setLocale = (raw2) => {
|
|
966
|
+
const lang2 = resolveLang(raw2);
|
|
967
|
+
const pkg2 = LOCALE_PACKAGES[lang2];
|
|
968
|
+
if (!pkg2) return;
|
|
969
|
+
merged = mergeLocales(pkg2, messages, components);
|
|
970
|
+
state.locale = lang2;
|
|
971
|
+
state.components = merged.components;
|
|
972
|
+
ctx?.ui?.render();
|
|
973
|
+
};
|
|
974
|
+
return ctx;
|
|
975
|
+
};
|
|
976
|
+
}
|
|
977
|
+
function mergeLocales(pkg, userMessages, userComponents) {
|
|
978
|
+
return {
|
|
979
|
+
messages: { ...pkg?.messages, ...userMessages },
|
|
980
|
+
components: deepMerge(pkg?.components ?? {}, userComponents)
|
|
981
|
+
};
|
|
982
|
+
}
|
|
983
|
+
function deepMerge(a, b) {
|
|
984
|
+
const result = { ...a };
|
|
985
|
+
for (const key of Object.keys(b)) {
|
|
986
|
+
if (typeof b[key] === "object" && b[key] !== null && typeof result[key] === "object") {
|
|
987
|
+
result[key] = { ...result[key], ...b[key] };
|
|
988
|
+
} else {
|
|
989
|
+
result[key] = b[key];
|
|
990
|
+
}
|
|
991
|
+
}
|
|
992
|
+
return result;
|
|
993
|
+
}
|
|
994
|
+
|
|
995
|
+
// src/client/scroll-lock.ts
|
|
996
|
+
var lockedCount = 0;
|
|
997
|
+
var originalOverflow = "";
|
|
998
|
+
var originalPosition = "";
|
|
999
|
+
var originalTop = "";
|
|
1000
|
+
var originalWidth = "";
|
|
1001
|
+
var scrollY = 0;
|
|
1002
|
+
function canLock() {
|
|
1003
|
+
return typeof window !== "undefined" && typeof document !== "undefined";
|
|
1004
|
+
}
|
|
1005
|
+
function lockScroll() {
|
|
1006
|
+
lockedCount++;
|
|
1007
|
+
if (lockedCount > 1) return;
|
|
1008
|
+
if (!canLock()) return;
|
|
1009
|
+
scrollY = window.scrollY;
|
|
1010
|
+
const body = document.body;
|
|
1011
|
+
originalOverflow = body.style.overflow;
|
|
1012
|
+
originalPosition = body.style.position;
|
|
1013
|
+
originalTop = body.style.top;
|
|
1014
|
+
originalWidth = body.style.width;
|
|
1015
|
+
body.style.overflow = "hidden";
|
|
1016
|
+
const isIOS = /iPhone|iPad|iPod/.test(navigator.platform) || /Mac/.test(navigator.platform) && "ontouchend" in document;
|
|
1017
|
+
if (isIOS) {
|
|
1018
|
+
body.style.position = "fixed";
|
|
1019
|
+
body.style.top = `-${scrollY}px`;
|
|
1020
|
+
body.style.width = "100%";
|
|
1021
|
+
}
|
|
1022
|
+
}
|
|
1023
|
+
function unlockScroll() {
|
|
1024
|
+
lockedCount--;
|
|
1025
|
+
if (lockedCount > 0) return;
|
|
1026
|
+
if (!canLock()) return;
|
|
1027
|
+
const body = document.body;
|
|
1028
|
+
body.style.overflow = originalOverflow;
|
|
1029
|
+
body.style.position = originalPosition;
|
|
1030
|
+
body.style.top = originalTop;
|
|
1031
|
+
body.style.width = originalWidth;
|
|
1032
|
+
if (scrollY > 0) window.scrollTo(0, scrollY);
|
|
1033
|
+
}
|
|
1034
|
+
|
|
1035
|
+
// src/client/focus-trap.ts
|
|
1036
|
+
var FOCUSABLE = 'a[href], button:not([disabled]), input:not([disabled]), textarea:not([disabled]), select:not([disabled]), [tabindex]:not([tabindex="-1"])';
|
|
1037
|
+
function trapFocus(container) {
|
|
1038
|
+
const focusable = container.querySelectorAll(FOCUSABLE);
|
|
1039
|
+
if (focusable.length === 0) return () => {
|
|
1040
|
+
};
|
|
1041
|
+
const first = focusable[0];
|
|
1042
|
+
const last = focusable[focusable.length - 1];
|
|
1043
|
+
const handler = (e) => {
|
|
1044
|
+
if (e.key !== "Tab") return;
|
|
1045
|
+
if (e.shiftKey && document.activeElement === first) {
|
|
1046
|
+
e.preventDefault();
|
|
1047
|
+
last.focus();
|
|
1048
|
+
} else if (!e.shiftKey && document.activeElement === last) {
|
|
1049
|
+
e.preventDefault();
|
|
1050
|
+
first.focus();
|
|
1051
|
+
}
|
|
1052
|
+
};
|
|
1053
|
+
const prevFocused = document.activeElement;
|
|
1054
|
+
first.focus();
|
|
1055
|
+
container.addEventListener("keydown", handler);
|
|
1056
|
+
return () => {
|
|
1057
|
+
container.removeEventListener("keydown", handler);
|
|
1058
|
+
prevFocused?.focus();
|
|
1059
|
+
};
|
|
1060
|
+
}
|
|
1061
|
+
|
|
1062
|
+
// src/client/confirm.ts
|
|
1063
|
+
function createConfirmModal(message, options) {
|
|
1064
|
+
return new Promise((resolve) => {
|
|
1065
|
+
const {
|
|
1066
|
+
title = "\u786E\u8BA4\u64CD\u4F5C",
|
|
1067
|
+
confirmText = "\u786E\u5B9A",
|
|
1068
|
+
cancelText = "\u53D6\u6D88",
|
|
1069
|
+
variant = "primary"
|
|
1070
|
+
} = options;
|
|
1071
|
+
const overlay = document.createElement("div");
|
|
1072
|
+
overlay.className = "wf-modal";
|
|
1073
|
+
overlay.style.cssText = "position:fixed;inset:0;z-index:10000;display:flex;align-items:center;justify-content:center";
|
|
1074
|
+
const bg = document.createElement("div");
|
|
1075
|
+
bg.style.cssText = "position:fixed;inset:0;background:rgba(0,0,0,0.4);z-index:-1";
|
|
1076
|
+
const box = document.createElement("div");
|
|
1077
|
+
box.style.cssText = `background:var(--wf-color-bg,#fff);border-radius:var(--wf-radius-md,8px);box-shadow:var(--wf-shadow-lg,0 4px 24px rgba(0,0,0,0.12));min-width:360px;max-width:90vw;z-index:1`;
|
|
1078
|
+
if (title) {
|
|
1079
|
+
const header = document.createElement("div");
|
|
1080
|
+
header.style.cssText = "display:flex;align-items:center;justify-content:space-between;padding:16px 20px;border-bottom:1px solid var(--wf-color-border,#e5e7eb);font-family:var(--wf-font-sans);font-size:var(--wf-font-size-lg);font-weight:var(--wf-font-weight-semibold);color:var(--wf-color-text);line-height:1.4";
|
|
1081
|
+
header.textContent = title;
|
|
1082
|
+
box.appendChild(header);
|
|
1083
|
+
}
|
|
1084
|
+
const body = document.createElement("div");
|
|
1085
|
+
body.style.cssText = "padding:20px;font-family:var(--wf-font-sans);font-size:var(--wf-font-size-sm);color:var(--wf-color-text);line-height:var(--wf-line-height-normal)";
|
|
1086
|
+
body.textContent = message;
|
|
1087
|
+
box.appendChild(body);
|
|
1088
|
+
const footer = document.createElement("div");
|
|
1089
|
+
footer.style.cssText = "display:flex;align-items:center;justify-content:flex-end;gap:8px;padding:12px 20px;border-top:1px solid var(--wf-color-border,#e5e7eb)";
|
|
1090
|
+
const cancelBtn = document.createElement("button");
|
|
1091
|
+
cancelBtn.className = "wf-btn wf-btn--secondary wf-btn--md";
|
|
1092
|
+
cancelBtn.textContent = cancelText;
|
|
1093
|
+
const confirmBtn = document.createElement("button");
|
|
1094
|
+
confirmBtn.className = `wf-btn wf-btn--${variant} wf-btn--md`;
|
|
1095
|
+
confirmBtn.textContent = confirmText;
|
|
1096
|
+
footer.appendChild(cancelBtn);
|
|
1097
|
+
footer.appendChild(confirmBtn);
|
|
1098
|
+
box.appendChild(footer);
|
|
1099
|
+
overlay.appendChild(bg);
|
|
1100
|
+
overlay.appendChild(box);
|
|
1101
|
+
document.body.appendChild(overlay);
|
|
1102
|
+
lockScroll();
|
|
1103
|
+
const close = (result) => {
|
|
1104
|
+
unlockScroll();
|
|
1105
|
+
overlay.remove();
|
|
1106
|
+
resolve(result);
|
|
1107
|
+
};
|
|
1108
|
+
const onKeyDown = (e) => {
|
|
1109
|
+
if (e.key === "Escape") close(false);
|
|
1110
|
+
};
|
|
1111
|
+
document.addEventListener("keydown", onKeyDown);
|
|
1112
|
+
cancelBtn.onclick = () => {
|
|
1113
|
+
document.removeEventListener("keydown", onKeyDown);
|
|
1114
|
+
close(false);
|
|
1115
|
+
};
|
|
1116
|
+
confirmBtn.onclick = () => {
|
|
1117
|
+
document.removeEventListener("keydown", onKeyDown);
|
|
1118
|
+
close(true);
|
|
1119
|
+
};
|
|
1120
|
+
bg.onclick = () => {
|
|
1121
|
+
document.removeEventListener("keydown", onKeyDown);
|
|
1122
|
+
close(false);
|
|
1123
|
+
};
|
|
1124
|
+
});
|
|
1125
|
+
}
|
|
1126
|
+
function confirm() {
|
|
1127
|
+
return (ctx) => {
|
|
1128
|
+
;
|
|
1129
|
+
ctx.confirm = (message, options) => createConfirmModal(message, options ?? {});
|
|
1130
|
+
return ctx;
|
|
1131
|
+
};
|
|
1132
|
+
}
|
|
878
1133
|
export {
|
|
879
1134
|
ApiError,
|
|
880
1135
|
ErrorBoundary,
|
|
@@ -882,12 +1137,19 @@ export {
|
|
|
882
1137
|
RouteView,
|
|
883
1138
|
api,
|
|
884
1139
|
auth,
|
|
1140
|
+
confirm,
|
|
885
1141
|
createApp,
|
|
1142
|
+
enUS,
|
|
886
1143
|
extendCtx,
|
|
887
1144
|
h,
|
|
1145
|
+
i18n,
|
|
888
1146
|
jsx,
|
|
889
1147
|
jsxDEV,
|
|
890
1148
|
jsxs,
|
|
1149
|
+
lockScroll,
|
|
891
1150
|
router,
|
|
892
|
-
|
|
1151
|
+
trapFocus,
|
|
1152
|
+
unlockScroll,
|
|
1153
|
+
ws,
|
|
1154
|
+
zhCN
|
|
893
1155
|
};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* weifuwu i18n — 英文组件文案
|
|
3
|
+
*/
|
|
4
|
+
export declare const enUS: {
|
|
5
|
+
components: {
|
|
6
|
+
Button: {
|
|
7
|
+
loading: string;
|
|
8
|
+
};
|
|
9
|
+
FileUpload: {
|
|
10
|
+
placeholder: string;
|
|
11
|
+
supportedFormats: string;
|
|
12
|
+
maxSize: string;
|
|
13
|
+
remove: string;
|
|
14
|
+
};
|
|
15
|
+
Pagination: {
|
|
16
|
+
ariaLabel: string;
|
|
17
|
+
};
|
|
18
|
+
ProgressBar: {
|
|
19
|
+
ariaLabel: string;
|
|
20
|
+
};
|
|
21
|
+
Switch: {
|
|
22
|
+
ariaLabel: string;
|
|
23
|
+
};
|
|
24
|
+
Breadcrumb: {
|
|
25
|
+
ariaLabel: string;
|
|
26
|
+
};
|
|
27
|
+
Modal: {
|
|
28
|
+
ariaLabel: string;
|
|
29
|
+
};
|
|
30
|
+
Drawer: {
|
|
31
|
+
ariaLabel: string;
|
|
32
|
+
};
|
|
33
|
+
};
|
|
34
|
+
};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* weifuwu i18n — 中文组件文案(缺省值)
|
|
3
|
+
*/
|
|
4
|
+
export declare const zhCN: {
|
|
5
|
+
components: {
|
|
6
|
+
Button: {
|
|
7
|
+
loading: string;
|
|
8
|
+
};
|
|
9
|
+
FileUpload: {
|
|
10
|
+
placeholder: string;
|
|
11
|
+
supportedFormats: string;
|
|
12
|
+
maxSize: string;
|
|
13
|
+
remove: string;
|
|
14
|
+
};
|
|
15
|
+
Pagination: {
|
|
16
|
+
ariaLabel: string;
|
|
17
|
+
};
|
|
18
|
+
ProgressBar: {
|
|
19
|
+
ariaLabel: string;
|
|
20
|
+
};
|
|
21
|
+
Switch: {
|
|
22
|
+
ariaLabel: string;
|
|
23
|
+
};
|
|
24
|
+
Breadcrumb: {
|
|
25
|
+
ariaLabel: string;
|
|
26
|
+
};
|
|
27
|
+
Modal: {
|
|
28
|
+
ariaLabel: string;
|
|
29
|
+
};
|
|
30
|
+
Drawer: {
|
|
31
|
+
ariaLabel: string;
|
|
32
|
+
};
|
|
33
|
+
};
|
|
34
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Component } from '../../client/vnode.ts';
|
|
2
|
+
export interface AccordionItem {
|
|
3
|
+
key: string;
|
|
4
|
+
title: string;
|
|
5
|
+
content?: any;
|
|
6
|
+
}
|
|
7
|
+
export interface AccordionProps {
|
|
8
|
+
items?: AccordionItem[];
|
|
9
|
+
multiple?: boolean;
|
|
10
|
+
}
|
|
11
|
+
export declare const Accordion: Component<AccordionProps>;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { Component } from '../../client/vnode.ts';
|
|
2
|
+
export type AlertVariant = 'info' | 'success' | 'warning' | 'error';
|
|
3
|
+
export interface AlertProps {
|
|
4
|
+
variant?: AlertVariant;
|
|
5
|
+
closable?: boolean;
|
|
6
|
+
onClose?: () => void;
|
|
7
|
+
children?: any;
|
|
8
|
+
}
|
|
9
|
+
export declare const Alert: Component<AlertProps>;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { Component } from '../../client/vnode.ts';
|
|
2
|
+
export type BadgeVariant = 'default' | 'primary' | 'success' | 'warning' | 'danger' | 'info';
|
|
3
|
+
export interface BadgeProps {
|
|
4
|
+
variant?: BadgeVariant;
|
|
5
|
+
dot?: boolean;
|
|
6
|
+
children?: any;
|
|
7
|
+
}
|
|
8
|
+
export declare const Badge: Component<BadgeProps>;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { Component } from '../../client/vnode.ts';
|
|
2
|
+
export interface ButtonProps {
|
|
3
|
+
variant?: 'primary' | 'secondary' | 'ghost' | 'danger';
|
|
4
|
+
size?: 'sm' | 'md' | 'lg';
|
|
5
|
+
block?: boolean;
|
|
6
|
+
loading?: boolean;
|
|
7
|
+
disabled?: boolean;
|
|
8
|
+
type?: 'button' | 'submit';
|
|
9
|
+
onClick?: (e: MouseEvent) => void;
|
|
10
|
+
children?: any;
|
|
11
|
+
}
|
|
12
|
+
export declare const Button: Component<ButtonProps>;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { Component } from '../../client/vnode.ts';
|
|
2
|
+
export interface CardProps {
|
|
3
|
+
variant?: 'default' | 'outlined';
|
|
4
|
+
padding?: 'sm' | 'md' | 'lg';
|
|
5
|
+
clickable?: boolean;
|
|
6
|
+
onClick?: () => void;
|
|
7
|
+
children?: any;
|
|
8
|
+
}
|
|
9
|
+
export declare const Card: Component<CardProps>;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* weifuwu/components — Drawer
|
|
3
|
+
*/
|
|
4
|
+
import type { Component } from '../../client/vnode.ts';
|
|
5
|
+
export type DrawerPosition = 'left' | 'right';
|
|
6
|
+
export interface DrawerProps {
|
|
7
|
+
open?: boolean;
|
|
8
|
+
title?: string;
|
|
9
|
+
position?: DrawerPosition;
|
|
10
|
+
onClose?: () => void;
|
|
11
|
+
children?: any;
|
|
12
|
+
footer?: any;
|
|
13
|
+
}
|
|
14
|
+
export declare const Drawer: Component<DrawerProps>;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { Component } from '../../client/vnode.ts';
|
|
2
|
+
export interface DropdownItem {
|
|
3
|
+
label: string;
|
|
4
|
+
value?: string;
|
|
5
|
+
disabled?: boolean;
|
|
6
|
+
variant?: 'default' | 'danger';
|
|
7
|
+
onClick?: () => void;
|
|
8
|
+
}
|
|
9
|
+
export interface DropdownProps {
|
|
10
|
+
trigger: any;
|
|
11
|
+
items?: DropdownItem[];
|
|
12
|
+
open?: boolean;
|
|
13
|
+
}
|
|
14
|
+
export declare const Dropdown: Component<DropdownProps>;
|