@sia.soul/sia-react-ui 0.1.28 → 0.1.30
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-KT7DIBXX.js} +389 -95
- package/dist/{core-CTe-Sfl1.d.cts → core-B687rqFa.d.cts} +141 -81
- package/dist/{core-DlvCqFU7.d.ts → core-BwuvPHYM.d.ts} +141 -81
- package/dist/core.cjs +376 -73
- package/dist/core.css +261 -12
- package/dist/core.d.cts +1 -1
- package/dist/core.d.ts +1 -1
- package/dist/core.js +1 -1
- package/dist/index.cjs +388 -98
- package/dist/index.css +261 -12
- package/dist/index.d.cts +15 -10
- package/dist/index.d.ts +15 -10
- package/dist/index.js +22 -26
- package/package.json +1 -1
package/dist/core.cjs
CHANGED
|
@@ -1761,6 +1761,7 @@ function Card({
|
|
|
1761
1761
|
// src/components/Tag.tsx
|
|
1762
1762
|
var import_jsx_runtime10 = require("react/jsx-runtime");
|
|
1763
1763
|
function Tag({
|
|
1764
|
+
color,
|
|
1764
1765
|
status = "default",
|
|
1765
1766
|
compact = false,
|
|
1766
1767
|
variant = "soft",
|
|
@@ -1771,13 +1772,16 @@ function Tag({
|
|
|
1771
1772
|
onClose,
|
|
1772
1773
|
className = "",
|
|
1773
1774
|
children,
|
|
1775
|
+
style,
|
|
1774
1776
|
...props
|
|
1775
1777
|
}) {
|
|
1778
|
+
const customColor = color?.trim() ? variant === "outlined" ? { borderColor: color, color, backgroundColor: "transparent" } : variant === "filled" ? { backgroundColor: color, color: "#fff", borderColor: "transparent" } : { color, backgroundColor: `color-mix(in srgb, ${color} 10%, transparent)`, borderColor: `color-mix(in srgb, ${color} 35%, transparent)` } : void 0;
|
|
1776
1779
|
return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
|
|
1777
1780
|
"span",
|
|
1778
1781
|
{
|
|
1779
1782
|
className: `sia-tag${closable && closeOnHover ? " sia-tag--close-on-hover" : ""} sia-tag--${status} sia-tag--${variant}${compact ? " sia-tag--compact" : ""}${disabled ? " sia-tag--disabled" : ""} ${className}`.trim(),
|
|
1780
1783
|
"aria-disabled": disabled || void 0,
|
|
1784
|
+
style: customColor ? { ...customColor, ...style } : style,
|
|
1781
1785
|
...withTitleTooltip(props),
|
|
1782
1786
|
children: [
|
|
1783
1787
|
icon ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "sia-tag__icon", children: icon }) : null,
|
|
@@ -2488,6 +2492,15 @@ function Collapse({ items, activeKey, defaultActiveKey = [], accordion = false,
|
|
|
2488
2492
|
] }, item.key);
|
|
2489
2493
|
}) });
|
|
2490
2494
|
}
|
|
2495
|
+
function ImagePreview({ open, src, alt = "", onOpenChange }) {
|
|
2496
|
+
const previewRef = (0, import_react15.useRef)(null);
|
|
2497
|
+
useOverlayLifecycle(open, previewRef, () => onOpenChange(false));
|
|
2498
|
+
if (!open || !src || typeof document === "undefined") return null;
|
|
2499
|
+
return (0, import_react_dom5.createPortal)(/* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { ref: previewRef, className: "sia-image-preview", role: "dialog", "aria-modal": "true", "aria-label": "\u56FE\u7247\u9884\u89C8", tabIndex: -1, onClick: () => onOpenChange(false), children: [
|
|
2500
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("button", { type: "button", "aria-label": "\u5173\u95ED\u9884\u89C8", onClick: () => onOpenChange(false), children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Icon, { name: "close" }) }),
|
|
2501
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("img", { src, alt, onClick: (event) => event.stopPropagation() })
|
|
2502
|
+
] }), document.body);
|
|
2503
|
+
}
|
|
2491
2504
|
|
|
2492
2505
|
// src/components/FloatingPlaceholder.tsx
|
|
2493
2506
|
var import_jsx_runtime16 = require("react/jsx-runtime");
|
|
@@ -3930,136 +3943,426 @@ var Select = (0, import_react22.forwardRef)(function Select2({
|
|
|
3930
3943
|
|
|
3931
3944
|
// src/components/Upload.tsx
|
|
3932
3945
|
var import_react23 = require("react");
|
|
3946
|
+
|
|
3947
|
+
// src/components/uploadFiles.ts
|
|
3948
|
+
function acceptsUploadFile(file, accept) {
|
|
3949
|
+
if (!accept?.trim()) return true;
|
|
3950
|
+
return accept.split(",").some((part) => {
|
|
3951
|
+
const rule = part.trim().toLowerCase();
|
|
3952
|
+
const type = file.type.toLowerCase();
|
|
3953
|
+
return rule.startsWith(".") ? file.name.toLowerCase().endsWith(rule) : rule.endsWith("/*") ? type.startsWith(rule.slice(0, -1)) : type === rule;
|
|
3954
|
+
});
|
|
3955
|
+
}
|
|
3956
|
+
function includeUploadPath(path, recursive) {
|
|
3957
|
+
return recursive || path.split("/").filter(Boolean).length <= 2;
|
|
3958
|
+
}
|
|
3959
|
+
async function readUploadEntries(entries, recursive) {
|
|
3960
|
+
const files = [];
|
|
3961
|
+
async function visit(entry, path, depth) {
|
|
3962
|
+
if (entry.isFile) {
|
|
3963
|
+
const file = await new Promise((resolve, reject) => entry.file(resolve, reject));
|
|
3964
|
+
files.push({ file, path });
|
|
3965
|
+
} else if (entry.isDirectory && (recursive || depth === 0)) {
|
|
3966
|
+
const reader = entry.createReader();
|
|
3967
|
+
while (true) {
|
|
3968
|
+
const batch = await new Promise((resolve, reject) => reader.readEntries(resolve, reject));
|
|
3969
|
+
if (!batch.length) break;
|
|
3970
|
+
for (const child of batch) await visit(child, `${path}/${child.name}`, depth + 1);
|
|
3971
|
+
}
|
|
3972
|
+
}
|
|
3973
|
+
}
|
|
3974
|
+
for (const entry of entries) await visit(entry, entry.name, 0);
|
|
3975
|
+
return files;
|
|
3976
|
+
}
|
|
3977
|
+
|
|
3978
|
+
// src/components/uploadRequest.ts
|
|
3979
|
+
function sendUploadRequest(config, options) {
|
|
3980
|
+
const xhr = new XMLHttpRequest();
|
|
3981
|
+
const abort = () => xhr.abort();
|
|
3982
|
+
const cleanup2 = () => options.signal.removeEventListener("abort", abort);
|
|
3983
|
+
xhr.open(config.method ?? "POST", config.action, true);
|
|
3984
|
+
xhr.withCredentials = config.withCredentials ?? false;
|
|
3985
|
+
xhr.timeout = config.timeout ?? 0;
|
|
3986
|
+
for (const [name, value] of Object.entries(config.headers ?? {})) xhr.setRequestHeader(name, value);
|
|
3987
|
+
xhr.upload.onprogress = (event) => {
|
|
3988
|
+
if (event.lengthComputable) options.onProgress(event.loaded / event.total * 100);
|
|
3989
|
+
};
|
|
3990
|
+
xhr.onload = () => {
|
|
3991
|
+
cleanup2();
|
|
3992
|
+
if (xhr.status < 200 || xhr.status >= 300) {
|
|
3993
|
+
options.onError(new Error(`\u4E0A\u4F20\u5931\u8D25\uFF1AHTTP ${xhr.status}`));
|
|
3994
|
+
return;
|
|
3995
|
+
}
|
|
3996
|
+
let response = xhr.responseText;
|
|
3997
|
+
try {
|
|
3998
|
+
response = JSON.parse(xhr.responseText);
|
|
3999
|
+
} catch {
|
|
4000
|
+
}
|
|
4001
|
+
options.onSuccess(response, config.url);
|
|
4002
|
+
};
|
|
4003
|
+
xhr.onerror = () => {
|
|
4004
|
+
cleanup2();
|
|
4005
|
+
options.onError(new Error("\u4E0A\u4F20\u7F51\u7EDC\u9519\u8BEF\uFF0C\u8BF7\u68C0\u67E5\u8FDE\u63A5\u4E0E\u8DE8\u57DF\u914D\u7F6E"));
|
|
4006
|
+
};
|
|
4007
|
+
xhr.ontimeout = () => {
|
|
4008
|
+
cleanup2();
|
|
4009
|
+
options.onError(new Error("\u4E0A\u4F20\u8D85\u65F6"));
|
|
4010
|
+
};
|
|
4011
|
+
xhr.onabort = cleanup2;
|
|
4012
|
+
options.signal.addEventListener("abort", abort, { once: true });
|
|
4013
|
+
if (options.signal.aborted) {
|
|
4014
|
+
cleanup2();
|
|
4015
|
+
return { abort };
|
|
4016
|
+
}
|
|
4017
|
+
try {
|
|
4018
|
+
if (config.body === "file") xhr.send(options.file);
|
|
4019
|
+
else {
|
|
4020
|
+
const body = new FormData();
|
|
4021
|
+
for (const [name, value] of Object.entries(config.data ?? {})) body.append(name, value);
|
|
4022
|
+
body.append(config.name ?? "file", options.file, options.filename);
|
|
4023
|
+
xhr.send(body);
|
|
4024
|
+
}
|
|
4025
|
+
} catch (error) {
|
|
4026
|
+
cleanup2();
|
|
4027
|
+
throw error;
|
|
4028
|
+
}
|
|
4029
|
+
return { abort };
|
|
4030
|
+
}
|
|
4031
|
+
|
|
4032
|
+
// src/components/Upload.tsx
|
|
3933
4033
|
var import_jsx_runtime22 = require("react/jsx-runtime");
|
|
3934
4034
|
var LIST_IGNORE = /* @__PURE__ */ Symbol("SIA_UPLOAD_LIST_IGNORE");
|
|
3935
|
-
function
|
|
4035
|
+
function useThumbnail(file) {
|
|
4036
|
+
const [local, setLocal] = (0, import_react23.useState)();
|
|
4037
|
+
(0, import_react23.useEffect)(() => {
|
|
4038
|
+
if (!file?.thumbUrl && file?.originFileObj?.type.startsWith("image/")) {
|
|
4039
|
+
const url = URL.createObjectURL(file.originFileObj);
|
|
4040
|
+
setLocal(url);
|
|
4041
|
+
return () => URL.revokeObjectURL(url);
|
|
4042
|
+
}
|
|
4043
|
+
setLocal(void 0);
|
|
4044
|
+
}, [file?.originFileObj, file?.thumbUrl]);
|
|
4045
|
+
return file?.thumbUrl || local || (file?.type?.startsWith("image/") || /\.(png|jpe?g|gif|webp|avif|svg)(\?|$)/i.test(file?.url ?? "") ? file?.url : void 0);
|
|
4046
|
+
}
|
|
4047
|
+
function UploadItem({ file, files, props, actions }) {
|
|
4048
|
+
const source = useThumbnail(file);
|
|
4049
|
+
const [failed, setFailed] = (0, import_react23.useState)(false);
|
|
4050
|
+
(0, import_react23.useEffect)(() => setFailed(false), [source]);
|
|
4051
|
+
const node = /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: `sia-upload__item sia-upload__item--${file.status ?? "ready"}`, children: [
|
|
4052
|
+
props.listType !== "text" ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(Button, { variant: "text", className: "sia-upload__thumbnail", "aria-label": `\u9884\u89C8 ${file.name}`, onClick: actions.preview, disabled: !source && !props.onPreview, children: source && !failed ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("img", { src: source, alt: file.name, onError: () => setFailed(true) }) : /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(Icon, { name: file.type?.startsWith("image/") ? "image" : "file", size: 28 }) }) : /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(Icon, { name: file.status === "done" ? "circle-check" : "file", size: 16 }),
|
|
4053
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "sia-upload__name", ...withTitleTooltip({ title: file.relativePath || file.name }), children: file.url ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("a", { href: file.url, target: "_blank", rel: "noreferrer", children: file.name }) : file.name }),
|
|
4054
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(Button, { variant: "text", className: "sia-upload__remove", disabled: props.disabled, "aria-label": `\u79FB\u9664 ${file.name}`, onClick: () => void actions.remove(), children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(Icon, { name: "close", size: 14 }) }),
|
|
4055
|
+
file.status === "uploading" && /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "sia-upload__uploading", children: [
|
|
4056
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("span", { children: [
|
|
4057
|
+
"\u4E0A\u4F20\u4E2D ",
|
|
4058
|
+
Math.round(file.percent ?? 0),
|
|
4059
|
+
"%"
|
|
4060
|
+
] }),
|
|
4061
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("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__ */ (0, import_jsx_runtime22.jsx)("span", { style: { width: `${file.percent ?? 0}%` } }) })
|
|
4062
|
+
] }),
|
|
4063
|
+
file.status === "error" && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "sia-upload__error", children: "\u4E0A\u4F20\u5931\u8D25" })
|
|
4064
|
+
] });
|
|
4065
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_jsx_runtime22.Fragment, { children: props.itemRender ? props.itemRender(node, file, files, actions) : node });
|
|
4066
|
+
}
|
|
4067
|
+
var UploadRoot = (0, import_react23.forwardRef)(function UploadRoot2({
|
|
3936
4068
|
accept,
|
|
3937
4069
|
multiple = false,
|
|
3938
4070
|
directory = false,
|
|
4071
|
+
recursive = true,
|
|
4072
|
+
pastable = false,
|
|
3939
4073
|
disabled = false,
|
|
4074
|
+
autoUpload = true,
|
|
3940
4075
|
maxCount: maxCount2,
|
|
3941
4076
|
fileList,
|
|
3942
4077
|
defaultFileList = [],
|
|
3943
4078
|
listType = "text",
|
|
3944
4079
|
showUploadList = true,
|
|
3945
4080
|
beforeUpload,
|
|
4081
|
+
request,
|
|
3946
4082
|
customRequest,
|
|
3947
4083
|
onChange,
|
|
3948
4084
|
onRemove,
|
|
4085
|
+
onReject,
|
|
4086
|
+
onReadError,
|
|
4087
|
+
onPreview,
|
|
4088
|
+
itemRender,
|
|
3949
4089
|
children,
|
|
3950
4090
|
className = "",
|
|
3951
4091
|
onDragOver,
|
|
4092
|
+
onDragLeave,
|
|
3952
4093
|
onDrop,
|
|
4094
|
+
onPaste,
|
|
4095
|
+
tabIndex,
|
|
3953
4096
|
...props
|
|
3954
|
-
}) {
|
|
4097
|
+
}, ref) {
|
|
3955
4098
|
const inputRef = (0, import_react23.useRef)(null);
|
|
3956
|
-
const
|
|
3957
|
-
const
|
|
3958
|
-
const
|
|
4099
|
+
const [internalFiles, setInternalFiles] = (0, import_react23.useState)(defaultFileList);
|
|
4100
|
+
const files = fileList ?? internalFiles;
|
|
4101
|
+
const filesRef = (0, import_react23.useRef)(files);
|
|
3959
4102
|
filesRef.current = files;
|
|
3960
|
-
|
|
3961
|
-
|
|
3962
|
-
|
|
3963
|
-
|
|
3964
|
-
|
|
3965
|
-
|
|
3966
|
-
|
|
3967
|
-
|
|
3968
|
-
|
|
3969
|
-
|
|
3970
|
-
|
|
3971
|
-
|
|
4103
|
+
const tasks = (0, import_react23.useRef)(/* @__PURE__ */ new Map());
|
|
4104
|
+
const mounted = (0, import_react23.useRef)(true);
|
|
4105
|
+
const [dragging, setDragging] = (0, import_react23.useState)(false);
|
|
4106
|
+
const [preview, setPreview] = (0, import_react23.useState)();
|
|
4107
|
+
const previewSource = useThumbnail(preview);
|
|
4108
|
+
const limit = maxCount2 === void 0 || !Number.isFinite(maxCount2) ? Infinity : Math.max(0, Math.floor(maxCount2));
|
|
4109
|
+
const full = files.length >= limit;
|
|
4110
|
+
const current = (0, import_react23.useRef)({ disabled, directory, recursive });
|
|
4111
|
+
current.current = { disabled, directory, recursive };
|
|
4112
|
+
function cancel(uid) {
|
|
4113
|
+
const task = tasks.current.get(uid);
|
|
4114
|
+
tasks.current.delete(uid);
|
|
4115
|
+
task?.controller.abort();
|
|
4116
|
+
try {
|
|
4117
|
+
task?.handle?.abort?.();
|
|
4118
|
+
} catch {
|
|
3972
4119
|
}
|
|
3973
|
-
|
|
3974
|
-
|
|
3975
|
-
|
|
3976
|
-
|
|
3977
|
-
|
|
3978
|
-
|
|
3979
|
-
|
|
4120
|
+
task?.finish();
|
|
4121
|
+
}
|
|
4122
|
+
(0, import_react23.useEffect)(() => {
|
|
4123
|
+
mounted.current = true;
|
|
4124
|
+
return () => {
|
|
4125
|
+
mounted.current = false;
|
|
4126
|
+
[...tasks.current.keys()].forEach(cancel);
|
|
4127
|
+
};
|
|
4128
|
+
}, []);
|
|
4129
|
+
(0, import_react23.useEffect)(() => {
|
|
4130
|
+
for (const uid of tasks.current.keys()) if (!files.some((file) => file.uid === uid)) cancel(uid);
|
|
4131
|
+
if (preview && !files.some((file) => file.uid === preview.uid)) setPreview(void 0);
|
|
4132
|
+
}, [files, preview]);
|
|
4133
|
+
function emit(file, next, event) {
|
|
4134
|
+
if (!mounted.current) return;
|
|
4135
|
+
filesRef.current = next;
|
|
4136
|
+
if (fileList === void 0) setInternalFiles(next);
|
|
4137
|
+
onChange?.({ file, fileList: next, event });
|
|
4138
|
+
}
|
|
4139
|
+
function start(file) {
|
|
4140
|
+
if (current.current.disabled || !mounted.current || file.status === "done" || !file.originFileObj) return Promise.resolve();
|
|
4141
|
+
const existing = tasks.current.get(file.uid);
|
|
4142
|
+
if (existing) return existing.done;
|
|
4143
|
+
let finish = () => {
|
|
4144
|
+
};
|
|
4145
|
+
const done = new Promise((resolve) => {
|
|
4146
|
+
finish = resolve;
|
|
4147
|
+
});
|
|
4148
|
+
const task = { controller: new AbortController(), done, finish };
|
|
4149
|
+
tasks.current.set(file.uid, task);
|
|
4150
|
+
const active = () => mounted.current && tasks.current.get(file.uid) === task && !task.controller.signal.aborted && filesRef.current.some((entry) => entry.uid === file.uid);
|
|
4151
|
+
const update = (patch, event) => {
|
|
4152
|
+
if (!active()) return;
|
|
4153
|
+
const next = { ...filesRef.current.find((entry) => entry.uid === file.uid), ...patch };
|
|
4154
|
+
emit(next, filesRef.current.map((entry) => entry.uid === file.uid ? next : entry), event);
|
|
4155
|
+
};
|
|
4156
|
+
const settle = () => {
|
|
4157
|
+
if (tasks.current.get(file.uid) === task) tasks.current.delete(file.uid);
|
|
4158
|
+
finish();
|
|
4159
|
+
};
|
|
4160
|
+
const options = {
|
|
4161
|
+
file: file.originFileObj,
|
|
4162
|
+
filename: file.name,
|
|
4163
|
+
uploadFile: file,
|
|
4164
|
+
relativePath: file.relativePath || file.name,
|
|
4165
|
+
signal: task.controller.signal,
|
|
3980
4166
|
onProgress: (percent) => {
|
|
3981
|
-
|
|
3982
|
-
const progressList = filesRef.current.map((entry) => entry.uid === item.uid ? progressing : entry);
|
|
3983
|
-
emit(progressing, progressList);
|
|
4167
|
+
if (Number.isFinite(percent)) update({ percent: Math.max(0, Math.min(100, percent)) }, "progress");
|
|
3984
4168
|
},
|
|
3985
|
-
onSuccess: (response) => {
|
|
3986
|
-
|
|
3987
|
-
|
|
3988
|
-
|
|
4169
|
+
onSuccess: (response, url) => {
|
|
4170
|
+
if (!active()) return;
|
|
4171
|
+
update({ status: "done", percent: 100, response, ...url ? { url } : {} }, "success");
|
|
4172
|
+
settle();
|
|
3989
4173
|
},
|
|
3990
4174
|
onError: (error) => {
|
|
3991
|
-
|
|
3992
|
-
|
|
3993
|
-
|
|
4175
|
+
if (!active()) return;
|
|
4176
|
+
update({ status: "error", error }, "error");
|
|
4177
|
+
settle();
|
|
3994
4178
|
}
|
|
3995
4179
|
};
|
|
3996
|
-
|
|
3997
|
-
|
|
4180
|
+
update({ status: "uploading", percent: 0, error: void 0 }, "start");
|
|
4181
|
+
void (async () => {
|
|
4182
|
+
try {
|
|
4183
|
+
if (!active()) return;
|
|
4184
|
+
const result = await beforeUpload?.(options.file, filesRef.current.flatMap((entry) => entry.originFileObj ? [entry.originFileObj] : []));
|
|
4185
|
+
if (!active()) return;
|
|
4186
|
+
if (result === LIST_IGNORE) {
|
|
4187
|
+
settle();
|
|
4188
|
+
emit(file, filesRef.current.filter((entry) => entry.uid !== file.uid), "remove");
|
|
4189
|
+
return;
|
|
4190
|
+
}
|
|
4191
|
+
if (result === false || !customRequest && !request) {
|
|
4192
|
+
update({ status: "ready" }, "cancel");
|
|
4193
|
+
settle();
|
|
4194
|
+
return;
|
|
4195
|
+
}
|
|
4196
|
+
if (result instanceof File) {
|
|
4197
|
+
options.file = result;
|
|
4198
|
+
options.filename = result.name;
|
|
4199
|
+
}
|
|
4200
|
+
if (customRequest) task.handle = await customRequest(options) || void 0;
|
|
4201
|
+
else {
|
|
4202
|
+
const config = typeof request === "function" ? await request({ ...file, originFileObj: options.file, name: options.filename }, task.controller.signal) : request;
|
|
4203
|
+
if (active()) task.handle = sendUploadRequest(config, options);
|
|
4204
|
+
}
|
|
4205
|
+
if (task.controller.signal.aborted) task.handle?.abort?.();
|
|
4206
|
+
} catch (error) {
|
|
4207
|
+
options.onError(error);
|
|
4208
|
+
}
|
|
4209
|
+
})();
|
|
4210
|
+
return done;
|
|
3998
4211
|
}
|
|
3999
|
-
function
|
|
4000
|
-
const
|
|
4001
|
-
|
|
4002
|
-
|
|
4212
|
+
function abort(uid) {
|
|
4213
|
+
const ids = uid ? [uid] : [...tasks.current.keys()];
|
|
4214
|
+
for (const id of ids) {
|
|
4215
|
+
if (!tasks.current.has(id)) continue;
|
|
4216
|
+
cancel(id);
|
|
4217
|
+
const file = filesRef.current.find((entry) => entry.uid === id);
|
|
4218
|
+
if (file) {
|
|
4219
|
+
const next = { ...file, status: "ready", percent: 0 };
|
|
4220
|
+
emit(next, filesRef.current.map((entry) => entry.uid === id ? next : entry), "cancel");
|
|
4221
|
+
}
|
|
4222
|
+
}
|
|
4223
|
+
}
|
|
4224
|
+
async function remove(uid) {
|
|
4225
|
+
if (current.current.disabled) return;
|
|
4226
|
+
const file = filesRef.current.find((entry) => entry.uid === uid);
|
|
4227
|
+
if (!file) return;
|
|
4228
|
+
try {
|
|
4229
|
+
if (await onRemove?.(file) === false || !mounted.current || current.current.disabled) return;
|
|
4230
|
+
cancel(uid);
|
|
4231
|
+
emit(file, filesRef.current.filter((entry) => entry.uid !== uid), "remove");
|
|
4232
|
+
} catch {
|
|
4233
|
+
}
|
|
4234
|
+
}
|
|
4235
|
+
(0, import_react23.useImperativeHandle)(ref, () => ({
|
|
4236
|
+
upload: async (uid) => {
|
|
4237
|
+
await Promise.all(filesRef.current.filter((file) => (!uid || file.uid === uid) && file.status !== "done").map(start));
|
|
4238
|
+
},
|
|
4239
|
+
abort,
|
|
4240
|
+
remove
|
|
4241
|
+
}));
|
|
4242
|
+
function ingest(entries) {
|
|
4243
|
+
if (current.current.disabled || !mounted.current) return;
|
|
4244
|
+
const filtered = directory ? entries.filter((entry) => includeUploadPath(entry.path, recursive)) : entries;
|
|
4245
|
+
const selected = multiple || directory ? filtered : filtered.slice(0, 1);
|
|
4246
|
+
const added = [];
|
|
4247
|
+
for (const { file, path } of selected) {
|
|
4248
|
+
if (!acceptsUploadFile(file, accept)) {
|
|
4249
|
+
onReject?.({ file, reason: "accept" });
|
|
4250
|
+
continue;
|
|
4251
|
+
}
|
|
4252
|
+
if (filesRef.current.length >= limit) {
|
|
4253
|
+
onReject?.({ file, reason: "max-count" });
|
|
4254
|
+
continue;
|
|
4255
|
+
}
|
|
4256
|
+
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 };
|
|
4257
|
+
emit(item, [...filesRef.current, item], "add");
|
|
4258
|
+
added.push(item);
|
|
4259
|
+
}
|
|
4260
|
+
if (autoUpload) added.forEach((file) => {
|
|
4261
|
+
void start(file);
|
|
4262
|
+
});
|
|
4003
4263
|
}
|
|
4004
|
-
function handleDrop(event) {
|
|
4264
|
+
async function handleDrop(event) {
|
|
4005
4265
|
onDrop?.(event);
|
|
4006
|
-
|
|
4266
|
+
setDragging(false);
|
|
4267
|
+
if (event.defaultPrevented) return;
|
|
4007
4268
|
event.preventDefault();
|
|
4008
|
-
|
|
4009
|
-
|
|
4269
|
+
if (disabled) return;
|
|
4270
|
+
const fallback = [...event.dataTransfer.files].map((file) => ({ file, path: file.webkitRelativePath || file.name }));
|
|
4271
|
+
const entries = [...event.dataTransfer.items].map((item) => item.webkitGetAsEntry?.()).filter((entry) => !!entry);
|
|
4272
|
+
try {
|
|
4273
|
+
if (entries.length) ingest(await readUploadEntries(entries.filter((entry) => directory || !entry.isDirectory), recursive));
|
|
4274
|
+
else ingest(fallback);
|
|
4275
|
+
} catch (error) {
|
|
4276
|
+
if (mounted.current) onReadError?.(error);
|
|
4277
|
+
}
|
|
4010
4278
|
}
|
|
4011
|
-
|
|
4012
|
-
|
|
4013
|
-
|
|
4014
|
-
|
|
4279
|
+
function handlePaste(event) {
|
|
4280
|
+
onPaste?.(event);
|
|
4281
|
+
if (event.defaultPrevented || disabled || !pastable) return;
|
|
4282
|
+
const selected = [...event.clipboardData.files];
|
|
4283
|
+
if (!selected.length) return;
|
|
4284
|
+
event.preventDefault();
|
|
4285
|
+
ingest(selected.map((file) => ({ file, path: file.name })));
|
|
4015
4286
|
}
|
|
4287
|
+
const trigger = !(listType === "picture-card" && full) && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { className: "sia-upload__trigger", children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(Button, { className: "sia-upload__choose", disabled: disabled || full, onClick: () => inputRef.current?.click(), children: children ?? (listType === "picture-card" ? /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(import_jsx_runtime22.Fragment, { children: [
|
|
4288
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(Icon, { name: "plus", size: 24 }),
|
|
4289
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { children: "\u4E0A\u4F20\u56FE\u7247" })
|
|
4290
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(import_jsx_runtime22.Fragment, { children: [
|
|
4291
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(Icon, { name: "upload", size: 16 }),
|
|
4292
|
+
directory ? "\u9009\u62E9\u6587\u4EF6\u5939" : "\u9009\u62E9\u6587\u4EF6"
|
|
4293
|
+
] })) }) });
|
|
4016
4294
|
return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
|
|
4017
4295
|
"div",
|
|
4018
4296
|
{
|
|
4019
|
-
|
|
4297
|
+
...withTitleTooltip(props),
|
|
4298
|
+
className: `sia-upload sia-upload--${listType}${dragging ? " is-dragging" : ""}${disabled ? " is-disabled" : ""} ${className}`.trim(),
|
|
4299
|
+
tabIndex: tabIndex ?? (pastable && !disabled ? 0 : void 0),
|
|
4300
|
+
onPaste: handlePaste,
|
|
4020
4301
|
onDragOver: (event) => {
|
|
4021
4302
|
onDragOver?.(event);
|
|
4022
|
-
if (!event.defaultPrevented
|
|
4303
|
+
if (!event.defaultPrevented) {
|
|
4304
|
+
event.preventDefault();
|
|
4305
|
+
if (!disabled) setDragging(true);
|
|
4306
|
+
}
|
|
4023
4307
|
},
|
|
4024
|
-
|
|
4025
|
-
|
|
4308
|
+
onDragLeave: (event) => {
|
|
4309
|
+
onDragLeave?.(event);
|
|
4310
|
+
if (!event.currentTarget.contains(event.relatedTarget)) setDragging(false);
|
|
4311
|
+
},
|
|
4312
|
+
onDrop: (event) => void handleDrop(event),
|
|
4026
4313
|
children: [
|
|
4027
4314
|
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
4028
4315
|
"input",
|
|
4029
4316
|
{
|
|
4030
4317
|
ref: inputRef,
|
|
4031
|
-
id,
|
|
4032
4318
|
className: "sia-upload__input",
|
|
4033
4319
|
type: "file",
|
|
4034
4320
|
accept,
|
|
4035
|
-
multiple,
|
|
4036
|
-
disabled,
|
|
4037
|
-
...
|
|
4038
|
-
onChange:
|
|
4321
|
+
multiple: multiple || directory,
|
|
4322
|
+
disabled: disabled || full,
|
|
4323
|
+
...directory ? { webkitdirectory: "", directory: "" } : {},
|
|
4324
|
+
onChange: (event) => {
|
|
4325
|
+
ingest([...event.currentTarget.files ?? []].map((file) => ({ file, path: file.webkitRelativePath || file.name })));
|
|
4326
|
+
event.currentTarget.value = "";
|
|
4327
|
+
}
|
|
4039
4328
|
}
|
|
4040
4329
|
),
|
|
4041
|
-
|
|
4042
|
-
|
|
4043
|
-
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
4044
|
-
|
|
4045
|
-
|
|
4046
|
-
|
|
4047
|
-
|
|
4330
|
+
listType !== "picture-card" && trigger,
|
|
4331
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "sia-upload__list", children: [
|
|
4332
|
+
showUploadList && files.map((file) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(UploadItem, { file, files, props: { listType, disabled, itemRender, onPreview }, actions: {
|
|
4333
|
+
upload: () => start(file),
|
|
4334
|
+
abort: () => abort(file.uid),
|
|
4335
|
+
remove: () => remove(file.uid),
|
|
4336
|
+
preview: () => {
|
|
4337
|
+
if (onPreview) onPreview(file);
|
|
4338
|
+
else setPreview(file);
|
|
4339
|
+
}
|
|
4340
|
+
} }, file.uid)),
|
|
4341
|
+
listType === "picture-card" && trigger
|
|
4342
|
+
] }),
|
|
4343
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(ImagePreview, { open: !!preview && !!(preview.url || previewSource), src: preview?.url || previewSource, alt: preview?.name, onOpenChange: (open) => {
|
|
4344
|
+
if (!open) setPreview(void 0);
|
|
4345
|
+
} })
|
|
4048
4346
|
]
|
|
4049
4347
|
}
|
|
4050
4348
|
);
|
|
4051
|
-
}
|
|
4052
|
-
|
|
4053
|
-
return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(UploadRoot, { ...props, className: `sia-upload-dragger ${className}`.trim(), children: children ?? /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("
|
|
4054
|
-
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(Icon, { name: "upload", size:
|
|
4055
|
-
/* @__PURE__ */ (0, import_jsx_runtime22.
|
|
4056
|
-
|
|
4349
|
+
});
|
|
4350
|
+
var UploadDragger = (0, import_react23.forwardRef)(function UploadDragger2({ hint = "\u652F\u6301\u5355\u4E2A\u6216\u6279\u91CF\u4E0A\u4F20", children, className = "", ...props }, ref) {
|
|
4351
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(UploadRoot, { ...props, ref, className: `sia-upload-dragger ${className}`.trim(), children: children ?? /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("span", { className: "sia-upload-dragger__content", children: [
|
|
4352
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(Icon, { name: "upload", size: 32 }),
|
|
4353
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("strong", { children: [
|
|
4354
|
+
"\u70B9\u51FB\u6216\u62D6\u62FD",
|
|
4355
|
+
props.directory ? "\u6587\u4EF6\u5939" : "\u6587\u4EF6",
|
|
4356
|
+
"\u5230\u6B64\u533A\u57DF\u4E0A\u4F20"
|
|
4357
|
+
] }),
|
|
4358
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { children: hint }),
|
|
4359
|
+
props.pastable && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { children: "\u805A\u7126\u6B64\u533A\u57DF\u540E\u6309 Ctrl / \u2318 + V \u7C98\u8D34\u6587\u4EF6\u6216\u622A\u56FE" })
|
|
4057
4360
|
] }) });
|
|
4058
|
-
}
|
|
4361
|
+
});
|
|
4059
4362
|
var Upload = Object.assign(UploadRoot, {
|
|
4060
|
-
/**
|
|
4363
|
+
/** 可点击、键盘操作和拖拽的上传区域,ref 支持手动上传、取消及移除。 */
|
|
4061
4364
|
Dragger: UploadDragger,
|
|
4062
|
-
/** beforeUpload
|
|
4365
|
+
/** beforeUpload 返回时移除该文件,不进行上传。 */
|
|
4063
4366
|
LIST_IGNORE
|
|
4064
4367
|
});
|
|
4065
4368
|
|