@sia.soul/sia-react-ui 0.1.28 → 0.1.29
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/dist/{chunk-NEYUBLLB.js → chunk-I5KAI6FC.js} +385 -95
- package/dist/{core-CTe-Sfl1.d.cts → core-C_aAA7OF.d.cts} +130 -75
- package/dist/{core-DlvCqFU7.d.ts → core-CuszFlw9.d.ts} +130 -75
- package/dist/core.cjs +372 -73
- package/dist/core.css +231 -3
- package/dist/core.d.cts +1 -1
- package/dist/core.d.ts +1 -1
- package/dist/core.js +1 -1
- package/dist/index.cjs +383 -97
- package/dist/index.css +231 -3
- package/dist/index.d.cts +8 -8
- package/dist/index.d.ts +8 -8
- package/dist/index.js +21 -25
- package/package.json +1 -1
|
@@ -910,137 +910,427 @@ function Image({ fallback, placeholder, preview = true, rootClassName = "", clas
|
|
|
910
910
|
}
|
|
911
911
|
|
|
912
912
|
// src/components/Upload.tsx
|
|
913
|
-
import {
|
|
914
|
-
|
|
913
|
+
import { forwardRef, useEffect as useEffect3, useImperativeHandle, useRef as useRef5, useState as useState6 } from "react";
|
|
914
|
+
|
|
915
|
+
// src/components/uploadFiles.ts
|
|
916
|
+
function acceptsUploadFile(file, accept) {
|
|
917
|
+
if (!accept?.trim()) return true;
|
|
918
|
+
return accept.split(",").some((part) => {
|
|
919
|
+
const rule = part.trim().toLowerCase();
|
|
920
|
+
const type = file.type.toLowerCase();
|
|
921
|
+
return rule.startsWith(".") ? file.name.toLowerCase().endsWith(rule) : rule.endsWith("/*") ? type.startsWith(rule.slice(0, -1)) : type === rule;
|
|
922
|
+
});
|
|
923
|
+
}
|
|
924
|
+
function includeUploadPath(path, recursive) {
|
|
925
|
+
return recursive || path.split("/").filter(Boolean).length <= 2;
|
|
926
|
+
}
|
|
927
|
+
async function readUploadEntries(entries, recursive) {
|
|
928
|
+
const files = [];
|
|
929
|
+
async function visit(entry, path, depth) {
|
|
930
|
+
if (entry.isFile) {
|
|
931
|
+
const file = await new Promise((resolve, reject) => entry.file(resolve, reject));
|
|
932
|
+
files.push({ file, path });
|
|
933
|
+
} else if (entry.isDirectory && (recursive || depth === 0)) {
|
|
934
|
+
const reader = entry.createReader();
|
|
935
|
+
while (true) {
|
|
936
|
+
const batch = await new Promise((resolve, reject) => reader.readEntries(resolve, reject));
|
|
937
|
+
if (!batch.length) break;
|
|
938
|
+
for (const child of batch) await visit(child, `${path}/${child.name}`, depth + 1);
|
|
939
|
+
}
|
|
940
|
+
}
|
|
941
|
+
}
|
|
942
|
+
for (const entry of entries) await visit(entry, entry.name, 0);
|
|
943
|
+
return files;
|
|
944
|
+
}
|
|
945
|
+
|
|
946
|
+
// src/components/uploadRequest.ts
|
|
947
|
+
function sendUploadRequest(config, options) {
|
|
948
|
+
const xhr = new XMLHttpRequest();
|
|
949
|
+
const abort = () => xhr.abort();
|
|
950
|
+
const cleanup = () => options.signal.removeEventListener("abort", abort);
|
|
951
|
+
xhr.open(config.method ?? "POST", config.action, true);
|
|
952
|
+
xhr.withCredentials = config.withCredentials ?? false;
|
|
953
|
+
xhr.timeout = config.timeout ?? 0;
|
|
954
|
+
for (const [name, value] of Object.entries(config.headers ?? {})) xhr.setRequestHeader(name, value);
|
|
955
|
+
xhr.upload.onprogress = (event) => {
|
|
956
|
+
if (event.lengthComputable) options.onProgress(event.loaded / event.total * 100);
|
|
957
|
+
};
|
|
958
|
+
xhr.onload = () => {
|
|
959
|
+
cleanup();
|
|
960
|
+
if (xhr.status < 200 || xhr.status >= 300) {
|
|
961
|
+
options.onError(new Error(`\u4E0A\u4F20\u5931\u8D25\uFF1AHTTP ${xhr.status}`));
|
|
962
|
+
return;
|
|
963
|
+
}
|
|
964
|
+
let response = xhr.responseText;
|
|
965
|
+
try {
|
|
966
|
+
response = JSON.parse(xhr.responseText);
|
|
967
|
+
} catch {
|
|
968
|
+
}
|
|
969
|
+
options.onSuccess(response, config.url);
|
|
970
|
+
};
|
|
971
|
+
xhr.onerror = () => {
|
|
972
|
+
cleanup();
|
|
973
|
+
options.onError(new Error("\u4E0A\u4F20\u7F51\u7EDC\u9519\u8BEF\uFF0C\u8BF7\u68C0\u67E5\u8FDE\u63A5\u4E0E\u8DE8\u57DF\u914D\u7F6E"));
|
|
974
|
+
};
|
|
975
|
+
xhr.ontimeout = () => {
|
|
976
|
+
cleanup();
|
|
977
|
+
options.onError(new Error("\u4E0A\u4F20\u8D85\u65F6"));
|
|
978
|
+
};
|
|
979
|
+
xhr.onabort = cleanup;
|
|
980
|
+
options.signal.addEventListener("abort", abort, { once: true });
|
|
981
|
+
if (options.signal.aborted) {
|
|
982
|
+
cleanup();
|
|
983
|
+
return { abort };
|
|
984
|
+
}
|
|
985
|
+
try {
|
|
986
|
+
if (config.body === "file") xhr.send(options.file);
|
|
987
|
+
else {
|
|
988
|
+
const body = new FormData();
|
|
989
|
+
for (const [name, value] of Object.entries(config.data ?? {})) body.append(name, value);
|
|
990
|
+
body.append(config.name ?? "file", options.file, options.filename);
|
|
991
|
+
xhr.send(body);
|
|
992
|
+
}
|
|
993
|
+
} catch (error) {
|
|
994
|
+
cleanup();
|
|
995
|
+
throw error;
|
|
996
|
+
}
|
|
997
|
+
return { abort };
|
|
998
|
+
}
|
|
999
|
+
|
|
1000
|
+
// src/components/Upload.tsx
|
|
1001
|
+
import { Fragment as Fragment4, jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
915
1002
|
var LIST_IGNORE = /* @__PURE__ */ Symbol("SIA_UPLOAD_LIST_IGNORE");
|
|
916
|
-
function
|
|
1003
|
+
function useThumbnail(file) {
|
|
1004
|
+
const [local, setLocal] = useState6();
|
|
1005
|
+
useEffect3(() => {
|
|
1006
|
+
if (!file?.thumbUrl && file?.originFileObj?.type.startsWith("image/")) {
|
|
1007
|
+
const url = URL.createObjectURL(file.originFileObj);
|
|
1008
|
+
setLocal(url);
|
|
1009
|
+
return () => URL.revokeObjectURL(url);
|
|
1010
|
+
}
|
|
1011
|
+
setLocal(void 0);
|
|
1012
|
+
}, [file?.originFileObj, file?.thumbUrl]);
|
|
1013
|
+
return file?.thumbUrl || local || (file?.type?.startsWith("image/") || /\.(png|jpe?g|gif|webp|avif|svg)(\?|$)/i.test(file?.url ?? "") ? file?.url : void 0);
|
|
1014
|
+
}
|
|
1015
|
+
function UploadItem({ file, files, props, actions }) {
|
|
1016
|
+
const source = useThumbnail(file);
|
|
1017
|
+
const [failed, setFailed] = useState6(false);
|
|
1018
|
+
useEffect3(() => setFailed(false), [source]);
|
|
1019
|
+
const node = /* @__PURE__ */ jsxs7("div", { className: `sia-upload__item sia-upload__item--${file.status ?? "ready"}`, children: [
|
|
1020
|
+
props.listType !== "text" ? /* @__PURE__ */ jsx7(Button, { variant: "text", className: "sia-upload__thumbnail", "aria-label": `\u9884\u89C8 ${file.name}`, onClick: actions.preview, disabled: !source && !props.onPreview, children: source && !failed ? /* @__PURE__ */ jsx7("img", { src: source, alt: file.name, onError: () => setFailed(true) }) : /* @__PURE__ */ jsx7(Icon, { name: file.type?.startsWith("image/") ? "image" : "file", size: 28 }) }) : /* @__PURE__ */ jsx7(Icon, { name: file.status === "done" ? "circle-check" : "file", size: 16 }),
|
|
1021
|
+
/* @__PURE__ */ jsx7("span", { className: "sia-upload__name", ...withTitleTooltip({ title: file.relativePath || file.name }), children: file.url ? /* @__PURE__ */ jsx7("a", { href: file.url, target: "_blank", rel: "noreferrer", children: file.name }) : file.name }),
|
|
1022
|
+
/* @__PURE__ */ jsx7(Button, { variant: "text", className: "sia-upload__remove", disabled: props.disabled, "aria-label": `\u79FB\u9664 ${file.name}`, onClick: () => void actions.remove(), children: /* @__PURE__ */ jsx7(Icon, { name: "close", size: 14 }) }),
|
|
1023
|
+
file.status === "uploading" && /* @__PURE__ */ jsxs7("div", { className: "sia-upload__uploading", children: [
|
|
1024
|
+
/* @__PURE__ */ jsxs7("span", { children: [
|
|
1025
|
+
"\u4E0A\u4F20\u4E2D ",
|
|
1026
|
+
Math.round(file.percent ?? 0),
|
|
1027
|
+
"%"
|
|
1028
|
+
] }),
|
|
1029
|
+
/* @__PURE__ */ jsx7("span", { className: "sia-upload__progress", role: "progressbar", "aria-label": `${file.name} \u4E0A\u4F20\u8FDB\u5EA6`, "aria-valuemin": 0, "aria-valuemax": 100, "aria-valuenow": file.percent ?? 0, children: /* @__PURE__ */ jsx7("span", { style: { width: `${file.percent ?? 0}%` } }) })
|
|
1030
|
+
] }),
|
|
1031
|
+
file.status === "error" && /* @__PURE__ */ jsx7("span", { className: "sia-upload__error", children: "\u4E0A\u4F20\u5931\u8D25" })
|
|
1032
|
+
] });
|
|
1033
|
+
return /* @__PURE__ */ jsx7(Fragment4, { children: props.itemRender ? props.itemRender(node, file, files, actions) : node });
|
|
1034
|
+
}
|
|
1035
|
+
var UploadRoot = forwardRef(function UploadRoot2({
|
|
917
1036
|
accept,
|
|
918
1037
|
multiple = false,
|
|
919
1038
|
directory = false,
|
|
1039
|
+
recursive = true,
|
|
1040
|
+
pastable = false,
|
|
920
1041
|
disabled = false,
|
|
1042
|
+
autoUpload = true,
|
|
921
1043
|
maxCount: maxCount2,
|
|
922
1044
|
fileList,
|
|
923
1045
|
defaultFileList = [],
|
|
924
1046
|
listType = "text",
|
|
925
1047
|
showUploadList = true,
|
|
926
1048
|
beforeUpload,
|
|
1049
|
+
request,
|
|
927
1050
|
customRequest,
|
|
928
1051
|
onChange,
|
|
929
1052
|
onRemove,
|
|
1053
|
+
onReject,
|
|
1054
|
+
onReadError,
|
|
1055
|
+
onPreview,
|
|
1056
|
+
itemRender,
|
|
930
1057
|
children,
|
|
931
1058
|
className = "",
|
|
932
1059
|
onDragOver,
|
|
1060
|
+
onDragLeave,
|
|
933
1061
|
onDrop,
|
|
1062
|
+
onPaste,
|
|
1063
|
+
tabIndex,
|
|
934
1064
|
...props
|
|
935
|
-
}) {
|
|
1065
|
+
}, ref) {
|
|
936
1066
|
const inputRef = useRef5(null);
|
|
937
|
-
const
|
|
938
|
-
const
|
|
939
|
-
const
|
|
1067
|
+
const [internalFiles, setInternalFiles] = useState6(defaultFileList);
|
|
1068
|
+
const files = fileList ?? internalFiles;
|
|
1069
|
+
const filesRef = useRef5(files);
|
|
940
1070
|
filesRef.current = files;
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
1071
|
+
const tasks = useRef5(/* @__PURE__ */ new Map());
|
|
1072
|
+
const mounted = useRef5(true);
|
|
1073
|
+
const [dragging, setDragging] = useState6(false);
|
|
1074
|
+
const [preview, setPreview] = useState6();
|
|
1075
|
+
const previewSource = useThumbnail(preview);
|
|
1076
|
+
const limit = maxCount2 === void 0 || !Number.isFinite(maxCount2) ? Infinity : Math.max(0, Math.floor(maxCount2));
|
|
1077
|
+
const full = files.length >= limit;
|
|
1078
|
+
const current = useRef5({ disabled, directory, recursive });
|
|
1079
|
+
current.current = { disabled, directory, recursive };
|
|
1080
|
+
function cancel(uid) {
|
|
1081
|
+
const task = tasks.current.get(uid);
|
|
1082
|
+
tasks.current.delete(uid);
|
|
1083
|
+
task?.controller.abort();
|
|
1084
|
+
try {
|
|
1085
|
+
task?.handle?.abort?.();
|
|
1086
|
+
} catch {
|
|
953
1087
|
}
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
1088
|
+
task?.finish();
|
|
1089
|
+
}
|
|
1090
|
+
useEffect3(() => {
|
|
1091
|
+
mounted.current = true;
|
|
1092
|
+
return () => {
|
|
1093
|
+
mounted.current = false;
|
|
1094
|
+
[...tasks.current.keys()].forEach(cancel);
|
|
1095
|
+
};
|
|
1096
|
+
}, []);
|
|
1097
|
+
useEffect3(() => {
|
|
1098
|
+
for (const uid of tasks.current.keys()) if (!files.some((file) => file.uid === uid)) cancel(uid);
|
|
1099
|
+
if (preview && !files.some((file) => file.uid === preview.uid)) setPreview(void 0);
|
|
1100
|
+
}, [files, preview]);
|
|
1101
|
+
function emit(file, next, event) {
|
|
1102
|
+
if (!mounted.current) return;
|
|
1103
|
+
filesRef.current = next;
|
|
1104
|
+
if (fileList === void 0) setInternalFiles(next);
|
|
1105
|
+
onChange?.({ file, fileList: next, event });
|
|
1106
|
+
}
|
|
1107
|
+
function start(file) {
|
|
1108
|
+
if (current.current.disabled || !mounted.current || file.status === "done" || !file.originFileObj) return Promise.resolve();
|
|
1109
|
+
const existing = tasks.current.get(file.uid);
|
|
1110
|
+
if (existing) return existing.done;
|
|
1111
|
+
let finish = () => {
|
|
1112
|
+
};
|
|
1113
|
+
const done = new Promise((resolve) => {
|
|
1114
|
+
finish = resolve;
|
|
1115
|
+
});
|
|
1116
|
+
const task = { controller: new AbortController(), done, finish };
|
|
1117
|
+
tasks.current.set(file.uid, task);
|
|
1118
|
+
const active = () => mounted.current && tasks.current.get(file.uid) === task && !task.controller.signal.aborted && filesRef.current.some((entry) => entry.uid === file.uid);
|
|
1119
|
+
const update = (patch, event) => {
|
|
1120
|
+
if (!active()) return;
|
|
1121
|
+
const next = { ...filesRef.current.find((entry) => entry.uid === file.uid), ...patch };
|
|
1122
|
+
emit(next, filesRef.current.map((entry) => entry.uid === file.uid ? next : entry), event);
|
|
1123
|
+
};
|
|
1124
|
+
const settle = () => {
|
|
1125
|
+
if (tasks.current.get(file.uid) === task) tasks.current.delete(file.uid);
|
|
1126
|
+
finish();
|
|
1127
|
+
};
|
|
1128
|
+
const options = {
|
|
1129
|
+
file: file.originFileObj,
|
|
1130
|
+
filename: file.name,
|
|
1131
|
+
uploadFile: file,
|
|
1132
|
+
relativePath: file.relativePath || file.name,
|
|
1133
|
+
signal: task.controller.signal,
|
|
961
1134
|
onProgress: (percent) => {
|
|
962
|
-
|
|
963
|
-
const progressList = filesRef.current.map((entry) => entry.uid === item.uid ? progressing : entry);
|
|
964
|
-
emit(progressing, progressList);
|
|
1135
|
+
if (Number.isFinite(percent)) update({ percent: Math.max(0, Math.min(100, percent)) }, "progress");
|
|
965
1136
|
},
|
|
966
|
-
onSuccess: (response) => {
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
1137
|
+
onSuccess: (response, url) => {
|
|
1138
|
+
if (!active()) return;
|
|
1139
|
+
update({ status: "done", percent: 100, response, ...url ? { url } : {} }, "success");
|
|
1140
|
+
settle();
|
|
970
1141
|
},
|
|
971
1142
|
onError: (error) => {
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
1143
|
+
if (!active()) return;
|
|
1144
|
+
update({ status: "error", error }, "error");
|
|
1145
|
+
settle();
|
|
975
1146
|
}
|
|
976
1147
|
};
|
|
977
|
-
|
|
978
|
-
|
|
1148
|
+
update({ status: "uploading", percent: 0, error: void 0 }, "start");
|
|
1149
|
+
void (async () => {
|
|
1150
|
+
try {
|
|
1151
|
+
if (!active()) return;
|
|
1152
|
+
const result = await beforeUpload?.(options.file, filesRef.current.flatMap((entry) => entry.originFileObj ? [entry.originFileObj] : []));
|
|
1153
|
+
if (!active()) return;
|
|
1154
|
+
if (result === LIST_IGNORE) {
|
|
1155
|
+
settle();
|
|
1156
|
+
emit(file, filesRef.current.filter((entry) => entry.uid !== file.uid), "remove");
|
|
1157
|
+
return;
|
|
1158
|
+
}
|
|
1159
|
+
if (result === false || !customRequest && !request) {
|
|
1160
|
+
update({ status: "ready" }, "cancel");
|
|
1161
|
+
settle();
|
|
1162
|
+
return;
|
|
1163
|
+
}
|
|
1164
|
+
if (result instanceof File) {
|
|
1165
|
+
options.file = result;
|
|
1166
|
+
options.filename = result.name;
|
|
1167
|
+
}
|
|
1168
|
+
if (customRequest) task.handle = await customRequest(options) || void 0;
|
|
1169
|
+
else {
|
|
1170
|
+
const config = typeof request === "function" ? await request({ ...file, originFileObj: options.file, name: options.filename }, task.controller.signal) : request;
|
|
1171
|
+
if (active()) task.handle = sendUploadRequest(config, options);
|
|
1172
|
+
}
|
|
1173
|
+
if (task.controller.signal.aborted) task.handle?.abort?.();
|
|
1174
|
+
} catch (error) {
|
|
1175
|
+
options.onError(error);
|
|
1176
|
+
}
|
|
1177
|
+
})();
|
|
1178
|
+
return done;
|
|
979
1179
|
}
|
|
980
|
-
function
|
|
981
|
-
const
|
|
982
|
-
|
|
983
|
-
|
|
1180
|
+
function abort(uid) {
|
|
1181
|
+
const ids = uid ? [uid] : [...tasks.current.keys()];
|
|
1182
|
+
for (const id of ids) {
|
|
1183
|
+
if (!tasks.current.has(id)) continue;
|
|
1184
|
+
cancel(id);
|
|
1185
|
+
const file = filesRef.current.find((entry) => entry.uid === id);
|
|
1186
|
+
if (file) {
|
|
1187
|
+
const next = { ...file, status: "ready", percent: 0 };
|
|
1188
|
+
emit(next, filesRef.current.map((entry) => entry.uid === id ? next : entry), "cancel");
|
|
1189
|
+
}
|
|
1190
|
+
}
|
|
1191
|
+
}
|
|
1192
|
+
async function remove(uid) {
|
|
1193
|
+
if (current.current.disabled) return;
|
|
1194
|
+
const file = filesRef.current.find((entry) => entry.uid === uid);
|
|
1195
|
+
if (!file) return;
|
|
1196
|
+
try {
|
|
1197
|
+
if (await onRemove?.(file) === false || !mounted.current || current.current.disabled) return;
|
|
1198
|
+
cancel(uid);
|
|
1199
|
+
emit(file, filesRef.current.filter((entry) => entry.uid !== uid), "remove");
|
|
1200
|
+
} catch {
|
|
1201
|
+
}
|
|
1202
|
+
}
|
|
1203
|
+
useImperativeHandle(ref, () => ({
|
|
1204
|
+
upload: async (uid) => {
|
|
1205
|
+
await Promise.all(filesRef.current.filter((file) => (!uid || file.uid === uid) && file.status !== "done").map(start));
|
|
1206
|
+
},
|
|
1207
|
+
abort,
|
|
1208
|
+
remove
|
|
1209
|
+
}));
|
|
1210
|
+
function ingest(entries) {
|
|
1211
|
+
if (current.current.disabled || !mounted.current) return;
|
|
1212
|
+
const filtered = directory ? entries.filter((entry) => includeUploadPath(entry.path, recursive)) : entries;
|
|
1213
|
+
const selected = multiple || directory ? filtered : filtered.slice(0, 1);
|
|
1214
|
+
const added = [];
|
|
1215
|
+
for (const { file, path } of selected) {
|
|
1216
|
+
if (!acceptsUploadFile(file, accept)) {
|
|
1217
|
+
onReject?.({ file, reason: "accept" });
|
|
1218
|
+
continue;
|
|
1219
|
+
}
|
|
1220
|
+
if (filesRef.current.length >= limit) {
|
|
1221
|
+
onReject?.({ file, reason: "max-count" });
|
|
1222
|
+
continue;
|
|
1223
|
+
}
|
|
1224
|
+
const item = { uid: `upload-${Date.now()}-${Math.random().toString(36).slice(2)}`, name: file.name, size: file.size, type: file.type, relativePath: path, originFileObj: file, status: "ready", percent: 0 };
|
|
1225
|
+
emit(item, [...filesRef.current, item], "add");
|
|
1226
|
+
added.push(item);
|
|
1227
|
+
}
|
|
1228
|
+
if (autoUpload) added.forEach((file) => {
|
|
1229
|
+
void start(file);
|
|
1230
|
+
});
|
|
984
1231
|
}
|
|
985
|
-
function handleDrop(event) {
|
|
1232
|
+
async function handleDrop(event) {
|
|
986
1233
|
onDrop?.(event);
|
|
987
|
-
|
|
1234
|
+
setDragging(false);
|
|
1235
|
+
if (event.defaultPrevented) return;
|
|
988
1236
|
event.preventDefault();
|
|
989
|
-
|
|
990
|
-
|
|
1237
|
+
if (disabled) return;
|
|
1238
|
+
const fallback = [...event.dataTransfer.files].map((file) => ({ file, path: file.webkitRelativePath || file.name }));
|
|
1239
|
+
const entries = [...event.dataTransfer.items].map((item) => item.webkitGetAsEntry?.()).filter((entry) => !!entry);
|
|
1240
|
+
try {
|
|
1241
|
+
if (entries.length) ingest(await readUploadEntries(entries.filter((entry) => directory || !entry.isDirectory), recursive));
|
|
1242
|
+
else ingest(fallback);
|
|
1243
|
+
} catch (error) {
|
|
1244
|
+
if (mounted.current) onReadError?.(error);
|
|
1245
|
+
}
|
|
991
1246
|
}
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
1247
|
+
function handlePaste(event) {
|
|
1248
|
+
onPaste?.(event);
|
|
1249
|
+
if (event.defaultPrevented || disabled || !pastable) return;
|
|
1250
|
+
const selected = [...event.clipboardData.files];
|
|
1251
|
+
if (!selected.length) return;
|
|
1252
|
+
event.preventDefault();
|
|
1253
|
+
ingest(selected.map((file) => ({ file, path: file.name })));
|
|
996
1254
|
}
|
|
1255
|
+
const trigger = !(listType === "picture-card" && full) && /* @__PURE__ */ jsx7("div", { className: "sia-upload__trigger", children: /* @__PURE__ */ jsx7(Button, { className: "sia-upload__choose", disabled: disabled || full, onClick: () => inputRef.current?.click(), children: children ?? (listType === "picture-card" ? /* @__PURE__ */ jsxs7(Fragment4, { children: [
|
|
1256
|
+
/* @__PURE__ */ jsx7(Icon, { name: "plus", size: 24 }),
|
|
1257
|
+
/* @__PURE__ */ jsx7("span", { children: "\u4E0A\u4F20\u56FE\u7247" })
|
|
1258
|
+
] }) : /* @__PURE__ */ jsxs7(Fragment4, { children: [
|
|
1259
|
+
/* @__PURE__ */ jsx7(Icon, { name: "upload", size: 16 }),
|
|
1260
|
+
directory ? "\u9009\u62E9\u6587\u4EF6\u5939" : "\u9009\u62E9\u6587\u4EF6"
|
|
1261
|
+
] })) }) });
|
|
997
1262
|
return /* @__PURE__ */ jsxs7(
|
|
998
1263
|
"div",
|
|
999
1264
|
{
|
|
1000
|
-
|
|
1265
|
+
...withTitleTooltip(props),
|
|
1266
|
+
className: `sia-upload sia-upload--${listType}${dragging ? " is-dragging" : ""}${disabled ? " is-disabled" : ""} ${className}`.trim(),
|
|
1267
|
+
tabIndex: tabIndex ?? (pastable && !disabled ? 0 : void 0),
|
|
1268
|
+
onPaste: handlePaste,
|
|
1001
1269
|
onDragOver: (event) => {
|
|
1002
1270
|
onDragOver?.(event);
|
|
1003
|
-
if (!event.defaultPrevented
|
|
1271
|
+
if (!event.defaultPrevented) {
|
|
1272
|
+
event.preventDefault();
|
|
1273
|
+
if (!disabled) setDragging(true);
|
|
1274
|
+
}
|
|
1004
1275
|
},
|
|
1005
|
-
|
|
1006
|
-
|
|
1276
|
+
onDragLeave: (event) => {
|
|
1277
|
+
onDragLeave?.(event);
|
|
1278
|
+
if (!event.currentTarget.contains(event.relatedTarget)) setDragging(false);
|
|
1279
|
+
},
|
|
1280
|
+
onDrop: (event) => void handleDrop(event),
|
|
1007
1281
|
children: [
|
|
1008
1282
|
/* @__PURE__ */ jsx7(
|
|
1009
1283
|
"input",
|
|
1010
1284
|
{
|
|
1011
1285
|
ref: inputRef,
|
|
1012
|
-
id,
|
|
1013
1286
|
className: "sia-upload__input",
|
|
1014
1287
|
type: "file",
|
|
1015
1288
|
accept,
|
|
1016
|
-
multiple,
|
|
1017
|
-
disabled,
|
|
1018
|
-
...
|
|
1019
|
-
onChange:
|
|
1289
|
+
multiple: multiple || directory,
|
|
1290
|
+
disabled: disabled || full,
|
|
1291
|
+
...directory ? { webkitdirectory: "", directory: "" } : {},
|
|
1292
|
+
onChange: (event) => {
|
|
1293
|
+
ingest([...event.currentTarget.files ?? []].map((file) => ({ file, path: file.webkitRelativePath || file.name })));
|
|
1294
|
+
event.currentTarget.value = "";
|
|
1295
|
+
}
|
|
1020
1296
|
}
|
|
1021
1297
|
),
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
/* @__PURE__ */ jsx7(
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1298
|
+
listType !== "picture-card" && trigger,
|
|
1299
|
+
/* @__PURE__ */ jsxs7("div", { className: "sia-upload__list", children: [
|
|
1300
|
+
showUploadList && files.map((file) => /* @__PURE__ */ jsx7(UploadItem, { file, files, props: { listType, disabled, itemRender, onPreview }, actions: {
|
|
1301
|
+
upload: () => start(file),
|
|
1302
|
+
abort: () => abort(file.uid),
|
|
1303
|
+
remove: () => remove(file.uid),
|
|
1304
|
+
preview: () => {
|
|
1305
|
+
if (onPreview) onPreview(file);
|
|
1306
|
+
else setPreview(file);
|
|
1307
|
+
}
|
|
1308
|
+
} }, file.uid)),
|
|
1309
|
+
listType === "picture-card" && trigger
|
|
1310
|
+
] }),
|
|
1311
|
+
/* @__PURE__ */ jsx7(ImagePreview, { open: !!preview && !!(preview.url || previewSource), src: preview?.url || previewSource, alt: preview?.name, onOpenChange: (open) => {
|
|
1312
|
+
if (!open) setPreview(void 0);
|
|
1313
|
+
} })
|
|
1029
1314
|
]
|
|
1030
1315
|
}
|
|
1031
1316
|
);
|
|
1032
|
-
}
|
|
1033
|
-
|
|
1034
|
-
return /* @__PURE__ */ jsx7(UploadRoot, { ...props, className: `sia-upload-dragger ${className}`.trim(), children: children ?? /* @__PURE__ */ jsxs7("
|
|
1035
|
-
/* @__PURE__ */ jsx7(Icon, { name: "upload", size:
|
|
1036
|
-
/* @__PURE__ */
|
|
1037
|
-
|
|
1317
|
+
});
|
|
1318
|
+
var UploadDragger = forwardRef(function UploadDragger2({ hint = "\u652F\u6301\u5355\u4E2A\u6216\u6279\u91CF\u4E0A\u4F20", children, className = "", ...props }, ref) {
|
|
1319
|
+
return /* @__PURE__ */ jsx7(UploadRoot, { ...props, ref, className: `sia-upload-dragger ${className}`.trim(), children: children ?? /* @__PURE__ */ jsxs7("span", { className: "sia-upload-dragger__content", children: [
|
|
1320
|
+
/* @__PURE__ */ jsx7(Icon, { name: "upload", size: 32 }),
|
|
1321
|
+
/* @__PURE__ */ jsxs7("strong", { children: [
|
|
1322
|
+
"\u70B9\u51FB\u6216\u62D6\u62FD",
|
|
1323
|
+
props.directory ? "\u6587\u4EF6\u5939" : "\u6587\u4EF6",
|
|
1324
|
+
"\u5230\u6B64\u533A\u57DF\u4E0A\u4F20"
|
|
1325
|
+
] }),
|
|
1326
|
+
/* @__PURE__ */ jsx7("span", { children: hint }),
|
|
1327
|
+
props.pastable && /* @__PURE__ */ jsx7("span", { children: "\u805A\u7126\u6B64\u533A\u57DF\u540E\u6309 Ctrl / \u2318 + V \u7C98\u8D34\u6587\u4EF6\u6216\u622A\u56FE" })
|
|
1038
1328
|
] }) });
|
|
1039
|
-
}
|
|
1329
|
+
});
|
|
1040
1330
|
var Upload = Object.assign(UploadRoot, {
|
|
1041
|
-
/**
|
|
1331
|
+
/** 可点击、键盘操作和拖拽的上传区域,ref 支持手动上传、取消及移除。 */
|
|
1042
1332
|
Dragger: UploadDragger,
|
|
1043
|
-
/** beforeUpload
|
|
1333
|
+
/** beforeUpload 返回时移除该文件,不进行上传。 */
|
|
1044
1334
|
LIST_IGNORE
|
|
1045
1335
|
});
|
|
1046
1336
|
|
|
@@ -1150,11 +1440,11 @@ var message = {
|
|
|
1150
1440
|
};
|
|
1151
1441
|
|
|
1152
1442
|
// src/components/Breadcrumb.tsx
|
|
1153
|
-
import { Fragment as
|
|
1443
|
+
import { Fragment as Fragment5, jsx as jsx9, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
1154
1444
|
function Breadcrumb({ items, separator = "/", itemRender, className = "", ...props }) {
|
|
1155
1445
|
return /* @__PURE__ */ jsx9("nav", { "aria-label": "\u9762\u5305\u5C51\u5BFC\u822A", ...withTitleTooltip(props), className: `sia-breadcrumb ${className}`.trim(), children: /* @__PURE__ */ jsx9("ol", { className: "sia-breadcrumb__list", children: items.map((item, index) => {
|
|
1156
1446
|
const current = index === items.length - 1;
|
|
1157
|
-
const content = /* @__PURE__ */ jsxs9(
|
|
1447
|
+
const content = /* @__PURE__ */ jsxs9(Fragment5, { children: [
|
|
1158
1448
|
item.icon ? /* @__PURE__ */ jsx9("span", { className: "sia-breadcrumb__icon", "aria-hidden": "true", children: item.icon }) : null,
|
|
1159
1449
|
/* @__PURE__ */ jsx9("span", { className: "sia-breadcrumb__title", children: item.title })
|
|
1160
1450
|
] });
|
|
@@ -1171,8 +1461,8 @@ function Breadcrumb({ items, separator = "/", itemRender, className = "", ...pro
|
|
|
1171
1461
|
}
|
|
1172
1462
|
|
|
1173
1463
|
// src/components/Typography.tsx
|
|
1174
|
-
import { useEffect as
|
|
1175
|
-
import { Fragment as
|
|
1464
|
+
import { useEffect as useEffect4, useLayoutEffect as useLayoutEffect3, useRef as useRef6, useState as useState7 } from "react";
|
|
1465
|
+
import { Fragment as Fragment6, jsx as jsx10, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
1176
1466
|
function TypographyContent({
|
|
1177
1467
|
as: Tag2 = "span",
|
|
1178
1468
|
type,
|
|
@@ -1194,22 +1484,22 @@ function TypographyContent({
|
|
|
1194
1484
|
const contentRef = useRef6(null);
|
|
1195
1485
|
const editRef = useRef6(null);
|
|
1196
1486
|
const timer = useRef6();
|
|
1197
|
-
const [localText, setLocalText] =
|
|
1198
|
-
const [draft, setDraft] =
|
|
1199
|
-
const [editing, setEditing] =
|
|
1200
|
-
const [copied, setCopied] =
|
|
1201
|
-
const [copyError, setCopyError] =
|
|
1202
|
-
const [expanded, setExpanded] =
|
|
1203
|
-
const [overflow, setOverflow] =
|
|
1487
|
+
const [localText, setLocalText] = useState7();
|
|
1488
|
+
const [draft, setDraft] = useState7("");
|
|
1489
|
+
const [editing, setEditing] = useState7(false);
|
|
1490
|
+
const [copied, setCopied] = useState7(false);
|
|
1491
|
+
const [copyError, setCopyError] = useState7(false);
|
|
1492
|
+
const [expanded, setExpanded] = useState7(false);
|
|
1493
|
+
const [overflow, setOverflow] = useState7(false);
|
|
1204
1494
|
const editConfig = typeof editable === "object" ? editable : void 0;
|
|
1205
1495
|
const content = editConfig?.text ?? localText ?? children;
|
|
1206
1496
|
const requestedRows = typeof ellipsis === "object" ? ellipsis.rows ?? 1 : 1;
|
|
1207
1497
|
const rows = Number.isFinite(requestedRows) ? Math.max(1, Math.floor(requestedRows)) : 1;
|
|
1208
1498
|
const expandable = typeof ellipsis === "object" && ellipsis.expandable;
|
|
1209
|
-
|
|
1499
|
+
useEffect4(() => {
|
|
1210
1500
|
setLocalText(void 0);
|
|
1211
1501
|
}, [children]);
|
|
1212
|
-
|
|
1502
|
+
useEffect4(() => () => clearTimeout(timer.current), []);
|
|
1213
1503
|
useLayoutEffect3(() => {
|
|
1214
1504
|
const element = contentRef.current;
|
|
1215
1505
|
if (!element || !ellipsis || editing || expanded) return;
|
|
@@ -1275,7 +1565,7 @@ function TypographyContent({
|
|
|
1275
1565
|
/* @__PURE__ */ jsx10(Button, { size: "small", onClick: () => finish(false), children: "\u53D6\u6D88" }),
|
|
1276
1566
|
/* @__PURE__ */ jsx10(Button, { size: "small", variant: "primary", onClick: () => finish(true), children: "\u4FDD\u5B58" })
|
|
1277
1567
|
] })
|
|
1278
|
-
] }) : /* @__PURE__ */ jsxs10(
|
|
1568
|
+
] }) : /* @__PURE__ */ jsxs10(Fragment6, { children: [
|
|
1279
1569
|
/* @__PURE__ */ jsx10("span", { ref: contentRef, className: ellipsis && !expanded ? "sia-typography__ellipsis" : void 0, style: ellipsis && !expanded ? { "--sia-typography-rows": rows } : void 0, children: formatted }),
|
|
1280
1570
|
expandable && (overflow || expanded) ? /* @__PURE__ */ jsx10(Button, { variant: "link", size: "small", className: "sia-typography__action", "aria-expanded": expanded, disabled, onClick: () => setExpanded(!expanded), children: expanded ? "\u6536\u8D77" : "\u5C55\u5F00" }) : null,
|
|
1281
1571
|
editable ? /* @__PURE__ */ jsx10(Button, { ref: editRef, variant: "text", size: "small", className: "sia-typography__action", "aria-label": "\u7F16\u8F91\u6587\u672C", title: "\u7F16\u8F91", disabled, icon: /* @__PURE__ */ jsx10(Icon, { name: "edit", size: 14 }), onClick: () => {
|
|
@@ -1328,10 +1618,10 @@ var Typography = Object.assign(TypographyRoot, {
|
|
|
1328
1618
|
});
|
|
1329
1619
|
|
|
1330
1620
|
// src/components/FloatButton.tsx
|
|
1331
|
-
import { createContext, forwardRef, useContext, useEffect as
|
|
1621
|
+
import { createContext, forwardRef as forwardRef2, useContext, useEffect as useEffect5, useId as useId2, useRef as useRef7, useState as useState8 } from "react";
|
|
1332
1622
|
import { jsx as jsx11, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
1333
1623
|
var GroupShape = createContext(void 0);
|
|
1334
|
-
var FloatButtonRoot =
|
|
1624
|
+
var FloatButtonRoot = forwardRef2(function FloatButton({
|
|
1335
1625
|
icon,
|
|
1336
1626
|
description,
|
|
1337
1627
|
tooltip,
|
|
@@ -1384,8 +1674,8 @@ function FloatButtonGroup({
|
|
|
1384
1674
|
const [visible, setVisible] = useControllableState({ value: open, defaultValue: defaultOpen, onChange: onOpenChange });
|
|
1385
1675
|
const rootRef = useRef7(null);
|
|
1386
1676
|
const triggerRef = useRef7(null);
|
|
1387
|
-
const id =
|
|
1388
|
-
|
|
1677
|
+
const id = useId2();
|
|
1678
|
+
useEffect5(() => {
|
|
1389
1679
|
if (!trigger || !visible) return;
|
|
1390
1680
|
const close = (event) => {
|
|
1391
1681
|
if (!rootRef.current?.contains(event.target)) setVisible(false);
|
|
@@ -1439,8 +1729,8 @@ function FloatButtonGroup({
|
|
|
1439
1729
|
) });
|
|
1440
1730
|
}
|
|
1441
1731
|
function FloatButtonBackTop({ target, visibilityHeight = 400, behavior = "smooth", onClick, icon, tooltip = "\u8FD4\u56DE\u9876\u90E8", ...props }) {
|
|
1442
|
-
const [visible, setVisible] =
|
|
1443
|
-
|
|
1732
|
+
const [visible, setVisible] = useState8(false);
|
|
1733
|
+
useEffect5(() => {
|
|
1444
1734
|
const element = target ? target() : window;
|
|
1445
1735
|
if (!element) return;
|
|
1446
1736
|
const update = () => setVisible((element === window ? window.scrollY : element.scrollTop) >= visibilityHeight);
|