@turinhub/atomix-common-ui 0.3.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (161) hide show
  1. package/README.md +50 -17
  2. package/dist/AuthPanel-C_2JBE7t.cjs +2 -0
  3. package/dist/AuthPanel-C_2JBE7t.cjs.map +1 -0
  4. package/dist/AuthPanel-D2HFX8eN.js +656 -0
  5. package/dist/AuthPanel-D2HFX8eN.js.map +1 -0
  6. package/dist/PDFSidebar-BBtucLK6.js +232 -0
  7. package/dist/PDFSidebar-BBtucLK6.js.map +1 -0
  8. package/dist/PDFSidebar-Di0D-yPS.cjs +2 -0
  9. package/dist/PDFSidebar-Di0D-yPS.cjs.map +1 -0
  10. package/dist/auth.cjs +2 -0
  11. package/dist/auth.cjs.map +1 -0
  12. package/dist/auth.d.ts +11 -0
  13. package/dist/auth.d.ts.map +1 -0
  14. package/dist/auth.js +9 -0
  15. package/dist/auth.js.map +1 -0
  16. package/dist/component-types.cjs +2 -0
  17. package/dist/component-types.cjs.map +1 -0
  18. package/dist/component-types.d.ts +2 -0
  19. package/dist/component-types.d.ts.map +1 -0
  20. package/dist/component-types.js +2 -0
  21. package/dist/component-types.js.map +1 -0
  22. package/dist/components/AuthLoginPanel.d.ts +55 -0
  23. package/dist/components/AuthLoginPanel.d.ts.map +1 -0
  24. package/dist/components/AuthPageShell.d.ts +11 -0
  25. package/dist/components/AuthPageShell.d.ts.map +1 -0
  26. package/dist/components/AuthPanel.d.ts +20 -0
  27. package/dist/components/AuthPanel.d.ts.map +1 -0
  28. package/dist/components/AuthRegisterPanel.d.ts +34 -0
  29. package/dist/components/AuthRegisterPanel.d.ts.map +1 -0
  30. package/dist/components/AuthVisualCarousel.d.ts +20 -0
  31. package/dist/components/AuthVisualCarousel.d.ts.map +1 -0
  32. package/dist/components/DataTable.d.ts +2 -2
  33. package/dist/components/DataTable.d.ts.map +1 -1
  34. package/dist/components/ImageReader.d.ts +44 -0
  35. package/dist/components/ImageReader.d.ts.map +1 -0
  36. package/dist/components/MarkdownReader.d.ts +26 -0
  37. package/dist/components/MarkdownReader.d.ts.map +1 -0
  38. package/dist/components/PDFReader.d.ts +2 -2
  39. package/dist/components/PDFReader.d.ts.map +1 -1
  40. package/dist/components/PDFSidebar.d.ts +1 -1
  41. package/dist/components/PDFSidebar.d.ts.map +1 -1
  42. package/dist/components/SimplePDFReader.d.ts +1 -1
  43. package/dist/components/VideoReader.d.ts +39 -0
  44. package/dist/components/VideoReader.d.ts.map +1 -0
  45. package/dist/components/media-utils.d.ts +9 -0
  46. package/dist/components/media-utils.d.ts.map +1 -0
  47. package/dist/data-table.cjs +2 -0
  48. package/dist/data-table.cjs.map +1 -0
  49. package/dist/data-table.d.ts +3 -0
  50. package/dist/data-table.d.ts.map +1 -0
  51. package/dist/data-table.js +169 -0
  52. package/dist/data-table.js.map +1 -0
  53. package/dist/delete-confirm-dialog.cjs +2 -0
  54. package/dist/delete-confirm-dialog.cjs.map +1 -0
  55. package/dist/delete-confirm-dialog.d.ts +3 -0
  56. package/dist/delete-confirm-dialog.d.ts.map +1 -0
  57. package/dist/delete-confirm-dialog.js +109 -0
  58. package/dist/delete-confirm-dialog.js.map +1 -0
  59. package/dist/file-upload.cjs +2 -0
  60. package/dist/file-upload.cjs.map +1 -0
  61. package/dist/file-upload.d.ts +3 -0
  62. package/dist/file-upload.d.ts.map +1 -0
  63. package/dist/file-upload.js +354 -0
  64. package/dist/file-upload.js.map +1 -0
  65. package/dist/image-reader.cjs +2 -0
  66. package/dist/image-reader.cjs.map +1 -0
  67. package/dist/image-reader.d.ts +3 -0
  68. package/dist/image-reader.d.ts.map +1 -0
  69. package/dist/image-reader.js +214 -0
  70. package/dist/image-reader.js.map +1 -0
  71. package/dist/index.cjs +2 -0
  72. package/dist/index.cjs.map +1 -0
  73. package/dist/index.d.ts +10 -20
  74. package/dist/index.d.ts.map +1 -1
  75. package/dist/index.js +8 -12
  76. package/dist/index.js.map +1 -1
  77. package/dist/jsx-runtime-B4hRZ52C.js +283 -0
  78. package/dist/jsx-runtime-B4hRZ52C.js.map +1 -0
  79. package/dist/jsx-runtime-BB_1_6y_.cjs +23 -0
  80. package/dist/jsx-runtime-BB_1_6y_.cjs.map +1 -0
  81. package/dist/markdown-reader.cjs +2 -0
  82. package/dist/markdown-reader.cjs.map +1 -0
  83. package/dist/markdown-reader.d.ts +3 -0
  84. package/dist/markdown-reader.d.ts.map +1 -0
  85. package/dist/markdown-reader.js +145 -0
  86. package/dist/markdown-reader.js.map +1 -0
  87. package/dist/media-utils-5UPuocc1.js +23 -0
  88. package/dist/media-utils-5UPuocc1.js.map +1 -0
  89. package/dist/media-utils-X1dDYP9W.cjs +2 -0
  90. package/dist/media-utils-X1dDYP9W.cjs.map +1 -0
  91. package/dist/pdf-reader.cjs +2 -0
  92. package/dist/pdf-reader.cjs.map +1 -0
  93. package/dist/pdf-reader.d.ts +3 -0
  94. package/dist/pdf-reader.d.ts.map +1 -0
  95. package/dist/pdf-reader.js +427 -0
  96. package/dist/pdf-reader.js.map +1 -0
  97. package/dist/pdf-sidebar.cjs +2 -0
  98. package/dist/pdf-sidebar.cjs.map +1 -0
  99. package/dist/pdf-sidebar.d.ts +3 -0
  100. package/dist/pdf-sidebar.d.ts.map +1 -0
  101. package/dist/pdf-sidebar.js +5 -0
  102. package/dist/pdf-sidebar.js.map +1 -0
  103. package/dist/simple-pdf-reader.cjs +2 -0
  104. package/dist/simple-pdf-reader.cjs.map +1 -0
  105. package/dist/simple-pdf-reader.d.ts +3 -0
  106. package/dist/simple-pdf-reader.d.ts.map +1 -0
  107. package/dist/simple-pdf-reader.js +268 -0
  108. package/dist/simple-pdf-reader.js.map +1 -0
  109. package/dist/table-header.cjs +2 -0
  110. package/dist/table-header.cjs.map +1 -0
  111. package/dist/table-header.d.ts +3 -0
  112. package/dist/table-header.d.ts.map +1 -0
  113. package/dist/table-header.js +63 -0
  114. package/dist/table-header.js.map +1 -0
  115. package/dist/table-pagination.cjs +2 -0
  116. package/dist/table-pagination.cjs.map +1 -0
  117. package/dist/table-pagination.d.ts +3 -0
  118. package/dist/table-pagination.d.ts.map +1 -0
  119. package/dist/table-pagination.js +172 -0
  120. package/dist/table-pagination.js.map +1 -0
  121. package/dist/theme-switcher-content.cjs +2 -0
  122. package/dist/theme-switcher-content.cjs.map +1 -0
  123. package/dist/theme-switcher-content.d.ts +3 -0
  124. package/dist/theme-switcher-content.d.ts.map +1 -0
  125. package/dist/theme-switcher-content.js +103 -0
  126. package/dist/theme-switcher-content.js.map +1 -0
  127. package/dist/theme-switcher.cjs +2 -0
  128. package/dist/theme-switcher.cjs.map +1 -0
  129. package/dist/theme-switcher.d.ts +3 -0
  130. package/dist/theme-switcher.d.ts.map +1 -0
  131. package/dist/theme-switcher.js +140 -0
  132. package/dist/theme-switcher.js.map +1 -0
  133. package/dist/types/component-types.d.ts +1 -0
  134. package/dist/types/component-types.d.ts.map +1 -1
  135. package/dist/utils-B6yFEsav.js +9 -0
  136. package/dist/utils-B6yFEsav.js.map +1 -0
  137. package/dist/utils-IjLH3w2e.cjs +2 -0
  138. package/dist/utils-IjLH3w2e.cjs.map +1 -0
  139. package/dist/utils.cjs +2 -0
  140. package/dist/utils.cjs.map +1 -0
  141. package/dist/utils.d.ts +2 -0
  142. package/dist/utils.d.ts.map +1 -0
  143. package/dist/utils.js +5 -0
  144. package/dist/utils.js.map +1 -0
  145. package/dist/video-reader.cjs +2 -0
  146. package/dist/video-reader.cjs.map +1 -0
  147. package/dist/video-reader.d.ts +3 -0
  148. package/dist/video-reader.d.ts.map +1 -0
  149. package/dist/video-reader.js +158 -0
  150. package/dist/video-reader.js.map +1 -0
  151. package/package.json +191 -3
  152. package/dist/index-DJdfLA8M.js +0 -2140
  153. package/dist/index-DJdfLA8M.js.map +0 -1
  154. package/dist/index-DUxYhmkV.js +0 -18821
  155. package/dist/index-DUxYhmkV.js.map +0 -1
  156. package/dist/index-miejqTjn.cjs +0 -13
  157. package/dist/index-miejqTjn.cjs.map +0 -1
  158. package/dist/index-tIca-Q_M.cjs +0 -23
  159. package/dist/index-tIca-Q_M.cjs.map +0 -1
  160. package/dist/index.c.js +0 -2
  161. package/dist/index.c.js.map +0 -1
@@ -0,0 +1,354 @@
1
+ import { j as e } from "./jsx-runtime-B4hRZ52C.js";
2
+ import { UploadCloud as fs, FileText as hs, X as ps, Loader2 as gs, CheckCircle2 as js, XCircle as ys } from "lucide-react";
3
+ import { useState as V, useRef as vs, useEffect as Ns } from "react";
4
+ import { c as R } from "./utils-B6yFEsav.js";
5
+ const bs = (r) => r < 1024 ? `${r} B` : r < 1024 * 1024 ? `${(r / 1024).toFixed(1)} KB` : r < 1024 * 1024 * 1024 ? `${(r / 1024 / 1024).toFixed(1)} MB` : `${(r / 1024 / 1024 / 1024).toFixed(1)} GB`, q = (r) => `${r.name}-${r.size}-${r.lastModified}-${Math.random().toString(36).slice(2)}`, ws = (r) => {
6
+ const o = r.lastIndexOf(".");
7
+ return o > -1 ? r.slice(o).toLowerCase() : "";
8
+ }, ks = (r, o) => {
9
+ if (!o) return !0;
10
+ const u = r.type.toLowerCase(), j = ws(r.name);
11
+ return o.split(",").map((d) => d.trim().toLowerCase()).filter(Boolean).some((d) => d.startsWith(".") ? j === d : d.endsWith("/*") ? u.startsWith(d.slice(0, -1)) : u === d);
12
+ }, Cs = (r, o) => r instanceof Error && r.message ? r.message : typeof r == "string" && r ? r : o;
13
+ function Is({
14
+ components: r,
15
+ title: o = "文件上传",
16
+ description: u = "选择文件后开始上传,支持 Tale SDK 的直接上传和预签名上传流程。",
17
+ helperText: j,
18
+ accept: d,
19
+ multiple: N = !1,
20
+ maxFiles: J,
21
+ maxSize: b,
22
+ disabled: c = !1,
23
+ autoUpload: Q = !1,
24
+ showUploadButton: Y,
25
+ showResetButton: w = !0,
26
+ selectLabel: Z = "选择文件",
27
+ uploadLabel: S = "开始上传",
28
+ retryLabel: _ = "重试",
29
+ resetLabel: T = "清空",
30
+ emptyLabel: U = "尚未选择文件",
31
+ dropzoneLabel: ss = "拖拽文件到这里,或点击选择",
32
+ dropzoneDescription: K = "上传前会先完成文件校验,上传逻辑由业务侧注入。",
33
+ uploadingText: es = "上传中",
34
+ successText: rs = "上传完成",
35
+ errorText: W = "上传失败",
36
+ className: ts,
37
+ dropzoneClassName: ns,
38
+ listClassName: as,
39
+ formatFileSize: A = bs,
40
+ validateFile: k,
41
+ onFilesChange: y,
42
+ onUpload: m,
43
+ onUploadComplete: C,
44
+ onUploadError: $
45
+ }) {
46
+ const [l, D] = V([]), [is, M] = V(!1), p = vs(null), E = Y ?? !!m, v = N ? J : 1, L = l.some((s) => s.status === "ready"), g = l.some((s) => s.status === "uploading");
47
+ if (Ns(() => {
48
+ y == null || y(l);
49
+ }, [l, y]), !r)
50
+ return /* @__PURE__ */ e.jsx("div", { className: "p-4 text-center text-destructive", children: "错误:请通过 components prop 注入 UI 组件" });
51
+ const {
52
+ Card: cs,
53
+ CardHeader: O,
54
+ CardTitle: I,
55
+ CardDescription: B,
56
+ CardContent: os,
57
+ CardFooter: P,
58
+ Button: f
59
+ } = r, h = (s) => {
60
+ D((t) => s(t));
61
+ }, X = (s, t) => b && s.size > b ? `文件不能超过 ${A(b)}` : ks(s, d) ? k == null ? void 0 : k(s, t) : "文件类型不符合要求", ds = (s, t) => {
62
+ const i = N ? [...t] : [], a = v === void 0 ? s.length : Math.max(v - i.length, 0);
63
+ return s.slice(0, a).forEach((n) => {
64
+ const x = X(n, i);
65
+ i.push({
66
+ id: q(n),
67
+ file: n,
68
+ name: n.name,
69
+ size: n.size,
70
+ type: n.type,
71
+ status: x ? "error" : "ready",
72
+ progress: 0,
73
+ error: x
74
+ });
75
+ }), v !== void 0 && s.length > a && s.slice(a).forEach((n) => {
76
+ i.push({
77
+ id: q(n),
78
+ file: n,
79
+ name: n.name,
80
+ size: n.size,
81
+ type: n.type,
82
+ status: "error",
83
+ progress: 0,
84
+ error: `最多只能选择 ${v} 个文件`
85
+ });
86
+ }), i;
87
+ }, F = async (s) => {
88
+ if (!m || s.status === "uploading") return;
89
+ h(
90
+ (i) => i.map(
91
+ (a) => a.id === s.id ? { ...a, status: "uploading", progress: a.progress || 5 } : a
92
+ )
93
+ );
94
+ const t = (i) => {
95
+ h(
96
+ (a) => a.map(
97
+ (n) => n.id === s.id ? {
98
+ ...n,
99
+ progress: Math.max(0, Math.min(100, Math.round(i)))
100
+ } : n
101
+ )
102
+ );
103
+ };
104
+ try {
105
+ const i = await m(s, { setProgress: t }), a = {
106
+ ...s,
107
+ status: "success",
108
+ progress: 100,
109
+ error: void 0,
110
+ result: i
111
+ };
112
+ h(
113
+ (n) => n.map(
114
+ (x) => x.id === s.id ? a : x
115
+ )
116
+ ), C == null || C(a);
117
+ } catch (i) {
118
+ const a = {
119
+ ...s,
120
+ status: "error",
121
+ progress: 0,
122
+ error: Cs(i, W)
123
+ };
124
+ h(
125
+ (n) => n.map(
126
+ (x) => x.id === s.id ? a : x
127
+ )
128
+ ), $ == null || $(a, i);
129
+ }
130
+ }, z = async () => {
131
+ const s = l.filter((t) => t.status === "ready");
132
+ for (const t of s)
133
+ await F(t);
134
+ }, G = (s) => {
135
+ if (!s || c) return;
136
+ const t = Array.from(s);
137
+ h((i) => {
138
+ const a = ds(t, i);
139
+ return Q && m && a.filter((n) => n.status === "ready").forEach((n) => {
140
+ window.setTimeout(() => F(n), 0);
141
+ }), a;
142
+ }), p.current && (p.current.value = "");
143
+ }, ls = (s) => {
144
+ s.preventDefault(), M(!1), G(s.dataTransfer.files);
145
+ }, us = (s) => {
146
+ h(
147
+ (t) => t.filter((i) => i.id !== s)
148
+ );
149
+ }, xs = (s) => {
150
+ const t = X(
151
+ s.file,
152
+ l.filter((i) => i.id !== s.id)
153
+ );
154
+ if (t) {
155
+ h(
156
+ (i) => i.map(
157
+ (a) => a.id === s.id ? { ...a, error: t } : a
158
+ )
159
+ );
160
+ return;
161
+ }
162
+ F({ ...s, status: "ready", error: void 0, progress: 0 });
163
+ }, ms = (s) => s.status === "uploading" ? /* @__PURE__ */ e.jsxs("span", { className: "inline-flex items-center gap-1 text-xs font-medium text-blue-600 dark:text-blue-300", children: [
164
+ /* @__PURE__ */ e.jsx(gs, { className: "h-3.5 w-3.5 animate-spin" }),
165
+ es
166
+ ] }) : s.status === "success" ? /* @__PURE__ */ e.jsxs("span", { className: "inline-flex items-center gap-1 text-xs font-medium text-emerald-600 dark:text-emerald-300", children: [
167
+ /* @__PURE__ */ e.jsx(js, { className: "h-3.5 w-3.5" }),
168
+ rs
169
+ ] }) : s.status === "error" ? /* @__PURE__ */ e.jsxs("span", { className: "inline-flex items-center gap-1 text-xs font-medium text-destructive", children: [
170
+ /* @__PURE__ */ e.jsx(ys, { className: "h-3.5 w-3.5" }),
171
+ W
172
+ ] }) : /* @__PURE__ */ e.jsx("span", { className: "text-xs text-muted-foreground", children: "待上传" }), H = /* @__PURE__ */ e.jsxs(e.Fragment, { children: [
173
+ o && I && /* @__PURE__ */ e.jsx(I, { children: o }),
174
+ o && !I && /* @__PURE__ */ e.jsx("div", { className: "text-lg font-semibold leading-none tracking-tight", children: o }),
175
+ u && B && /* @__PURE__ */ e.jsx(B, { children: u }),
176
+ u && !B && /* @__PURE__ */ e.jsx("div", { className: "text-sm text-muted-foreground", children: u })
177
+ ] });
178
+ return /* @__PURE__ */ e.jsxs(cs, { className: R("overflow-hidden", ts), children: [
179
+ O && (o || u) ? /* @__PURE__ */ e.jsx(O, { children: H }) : (o || u) && /* @__PURE__ */ e.jsx("div", { className: "space-y-1.5 p-6", children: H }),
180
+ /* @__PURE__ */ e.jsxs(os, { className: "space-y-4", children: [
181
+ /* @__PURE__ */ e.jsx(
182
+ "input",
183
+ {
184
+ ref: p,
185
+ type: "file",
186
+ accept: d,
187
+ multiple: N,
188
+ className: "sr-only",
189
+ onChange: (s) => G(s.target.files),
190
+ disabled: c
191
+ }
192
+ ),
193
+ /* @__PURE__ */ e.jsxs(
194
+ "div",
195
+ {
196
+ role: "button",
197
+ tabIndex: c ? -1 : 0,
198
+ "aria-disabled": c,
199
+ className: R(
200
+ "flex min-h-40 cursor-pointer flex-col items-center justify-center rounded-lg border border-dashed border-muted-foreground/30 bg-muted/20 px-6 py-8 text-center transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring",
201
+ is && "border-primary bg-primary/5",
202
+ c && "cursor-not-allowed opacity-60",
203
+ ns
204
+ ),
205
+ onClick: () => {
206
+ var s;
207
+ c || (s = p.current) == null || s.click();
208
+ },
209
+ onKeyDown: (s) => {
210
+ var t;
211
+ !c && (s.key === "Enter" || s.key === " ") && (s.preventDefault(), (t = p.current) == null || t.click());
212
+ },
213
+ onDragOver: (s) => {
214
+ s.preventDefault(), c || M(!0);
215
+ },
216
+ onDragLeave: () => M(!1),
217
+ onDrop: ls,
218
+ children: [
219
+ /* @__PURE__ */ e.jsx("div", { className: "mb-3 rounded-full bg-primary/10 p-3 text-primary", children: /* @__PURE__ */ e.jsx(fs, { className: "h-6 w-6" }) }),
220
+ /* @__PURE__ */ e.jsx("div", { className: "text-sm font-medium", children: ss }),
221
+ K && /* @__PURE__ */ e.jsx("div", { className: "mt-1 max-w-md text-sm text-muted-foreground", children: K }),
222
+ /* @__PURE__ */ e.jsx(
223
+ f,
224
+ {
225
+ type: "button",
226
+ size: "sm",
227
+ variant: "secondary",
228
+ className: "mt-4",
229
+ disabled: c,
230
+ onClick: (s) => {
231
+ var t;
232
+ s.stopPropagation(), (t = p.current) == null || t.click();
233
+ },
234
+ children: Z
235
+ }
236
+ )
237
+ ]
238
+ }
239
+ ),
240
+ j && /* @__PURE__ */ e.jsx("div", { className: "text-sm text-muted-foreground", children: j }),
241
+ /* @__PURE__ */ e.jsx("div", { className: R("space-y-3", as), children: l.length === 0 ? /* @__PURE__ */ e.jsx("div", { className: "rounded-md border border-dashed px-4 py-3 text-sm text-muted-foreground", children: U }) : l.map((s) => /* @__PURE__ */ e.jsx(
242
+ "div",
243
+ {
244
+ className: "rounded-lg border bg-background px-4 py-3",
245
+ children: /* @__PURE__ */ e.jsxs("div", { className: "flex items-start gap-3", children: [
246
+ /* @__PURE__ */ e.jsx("div", { className: "mt-0.5 rounded-md bg-muted p-2 text-muted-foreground", children: /* @__PURE__ */ e.jsx(hs, { className: "h-4 w-4" }) }),
247
+ /* @__PURE__ */ e.jsxs("div", { className: "min-w-0 flex-1 space-y-2", children: [
248
+ /* @__PURE__ */ e.jsxs("div", { className: "flex flex-wrap items-start justify-between gap-2", children: [
249
+ /* @__PURE__ */ e.jsxs("div", { className: "min-w-0", children: [
250
+ /* @__PURE__ */ e.jsx("div", { className: "truncate text-sm font-medium", children: s.name }),
251
+ /* @__PURE__ */ e.jsxs("div", { className: "text-xs text-muted-foreground", children: [
252
+ A(s.size),
253
+ s.type ? ` · ${s.type}` : ""
254
+ ] })
255
+ ] }),
256
+ ms(s)
257
+ ] }),
258
+ s.status === "uploading" && /* @__PURE__ */ e.jsx(
259
+ "div",
260
+ {
261
+ className: "h-2 overflow-hidden rounded-full bg-muted",
262
+ "aria-label": `${s.name} 上传进度`,
263
+ role: "progressbar",
264
+ "aria-valuenow": s.progress,
265
+ "aria-valuemin": 0,
266
+ "aria-valuemax": 100,
267
+ children: /* @__PURE__ */ e.jsx(
268
+ "div",
269
+ {
270
+ className: "h-full rounded-full bg-primary transition-all",
271
+ style: { width: `${s.progress}%` }
272
+ }
273
+ )
274
+ }
275
+ ),
276
+ s.error && /* @__PURE__ */ e.jsx("div", { className: "text-xs text-destructive", children: s.error })
277
+ ] }),
278
+ /* @__PURE__ */ e.jsxs("div", { className: "flex shrink-0 items-center gap-1", children: [
279
+ s.status === "error" && m && /* @__PURE__ */ e.jsx(
280
+ f,
281
+ {
282
+ type: "button",
283
+ variant: "ghost",
284
+ size: "sm",
285
+ disabled: c || g,
286
+ onClick: () => xs(s),
287
+ children: _
288
+ }
289
+ ),
290
+ /* @__PURE__ */ e.jsx(
291
+ f,
292
+ {
293
+ type: "button",
294
+ variant: "ghost",
295
+ size: "icon",
296
+ "aria-label": `移除 ${s.name}`,
297
+ disabled: c || s.status === "uploading",
298
+ onClick: () => us(s.id),
299
+ children: /* @__PURE__ */ e.jsx(ps, { className: "h-4 w-4" })
300
+ }
301
+ )
302
+ ] })
303
+ ] })
304
+ },
305
+ s.id
306
+ )) })
307
+ ] }),
308
+ (E || w) && (P ? /* @__PURE__ */ e.jsxs(P, { className: "justify-end gap-2", children: [
309
+ w && /* @__PURE__ */ e.jsx(
310
+ f,
311
+ {
312
+ type: "button",
313
+ variant: "outline",
314
+ disabled: c || g || l.length === 0,
315
+ onClick: () => D([]),
316
+ children: T
317
+ }
318
+ ),
319
+ E && /* @__PURE__ */ e.jsx(
320
+ f,
321
+ {
322
+ type: "button",
323
+ disabled: c || g || !L || !m,
324
+ onClick: z,
325
+ children: S
326
+ }
327
+ )
328
+ ] }) : /* @__PURE__ */ e.jsxs("div", { className: "flex justify-end gap-2 p-6 pt-0", children: [
329
+ w && /* @__PURE__ */ e.jsx(
330
+ f,
331
+ {
332
+ type: "button",
333
+ variant: "outline",
334
+ disabled: c || g || l.length === 0,
335
+ onClick: () => D([]),
336
+ children: T
337
+ }
338
+ ),
339
+ E && /* @__PURE__ */ e.jsx(
340
+ f,
341
+ {
342
+ type: "button",
343
+ disabled: c || g || !L || !m,
344
+ onClick: z,
345
+ children: S
346
+ }
347
+ )
348
+ ] }))
349
+ ] });
350
+ }
351
+ export {
352
+ Is as FileUpload
353
+ };
354
+ //# sourceMappingURL=file-upload.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-upload.js","sources":["../src/components/FileUpload.tsx"],"sourcesContent":["import {\n CheckCircle2,\n FileText,\n Loader2,\n UploadCloud,\n X,\n XCircle,\n} from 'lucide-react';\nimport { useEffect, useRef, useState } from 'react';\nimport type { DragEvent, HTMLAttributes, ReactNode } from 'react';\n\nimport { cn } from '../lib/utils';\nimport type {\n ButtonComponent,\n CardComponent,\n UIComponent,\n} from '../types/component-types';\n\nexport type FileUploadStatus = 'ready' | 'uploading' | 'success' | 'error';\n\nexport interface FileUploadItem<TResult = unknown> {\n id: string;\n file: File;\n name: string;\n size: number;\n type: string;\n status: FileUploadStatus;\n progress: number;\n error?: string;\n result?: TResult;\n}\n\nexport interface FileUploadHelpers {\n setProgress: (progress: number) => void;\n}\n\nexport interface FileUploadUIComponents {\n Card: CardComponent;\n CardHeader?: UIComponent<HTMLAttributes<HTMLDivElement>>;\n CardTitle?: UIComponent<HTMLAttributes<HTMLDivElement>>;\n CardDescription?: UIComponent<HTMLAttributes<HTMLDivElement>>;\n CardContent: UIComponent<HTMLAttributes<HTMLDivElement>>;\n CardFooter?: UIComponent<HTMLAttributes<HTMLDivElement>>;\n Button: ButtonComponent;\n}\n\nexport interface FileUploadProps<TResult = unknown> {\n components?: FileUploadUIComponents;\n title?: ReactNode;\n description?: ReactNode;\n helperText?: ReactNode;\n accept?: string;\n multiple?: boolean;\n maxFiles?: number;\n maxSize?: number;\n disabled?: boolean;\n autoUpload?: boolean;\n showUploadButton?: boolean;\n showResetButton?: boolean;\n selectLabel?: string;\n uploadLabel?: string;\n retryLabel?: string;\n resetLabel?: string;\n emptyLabel?: ReactNode;\n dropzoneLabel?: ReactNode;\n dropzoneDescription?: ReactNode;\n uploadingText?: string;\n successText?: string;\n errorText?: string;\n className?: string;\n dropzoneClassName?: string;\n listClassName?: string;\n formatFileSize?: (size: number) => string;\n validateFile?: (\n file: File,\n currentItems: FileUploadItem<TResult>[]\n ) => string | undefined;\n onFilesChange?: (items: FileUploadItem<TResult>[]) => void;\n onUpload?: (\n item: FileUploadItem<TResult>,\n helpers: FileUploadHelpers\n ) => Promise<TResult> | TResult;\n onUploadComplete?: (item: FileUploadItem<TResult>) => void;\n onUploadError?: (item: FileUploadItem<TResult>, error: unknown) => void;\n}\n\nconst defaultFormatFileSize = (size: number) => {\n if (size < 1024) return `${size} B`;\n if (size < 1024 * 1024) return `${(size / 1024).toFixed(1)} KB`;\n if (size < 1024 * 1024 * 1024) {\n return `${(size / 1024 / 1024).toFixed(1)} MB`;\n }\n return `${(size / 1024 / 1024 / 1024).toFixed(1)} GB`;\n};\n\nconst createFileId = (file: File) =>\n `${file.name}-${file.size}-${file.lastModified}-${Math.random()\n .toString(36)\n .slice(2)}`;\n\nconst getFileExtension = (fileName: string) => {\n const index = fileName.lastIndexOf('.');\n return index > -1 ? fileName.slice(index).toLowerCase() : '';\n};\n\nconst matchesAccept = (file: File, accept?: string) => {\n if (!accept) return true;\n\n const fileType = file.type.toLowerCase();\n const fileExtension = getFileExtension(file.name);\n\n return accept\n .split(',')\n .map((item) => item.trim().toLowerCase())\n .filter(Boolean)\n .some((rule) => {\n if (rule.startsWith('.')) {\n return fileExtension === rule;\n }\n if (rule.endsWith('/*')) {\n return fileType.startsWith(rule.slice(0, -1));\n }\n return fileType === rule;\n });\n};\n\nconst getErrorMessage = (error: unknown, fallback: string) => {\n if (error instanceof Error && error.message) {\n return error.message;\n }\n if (typeof error === 'string' && error) {\n return error;\n }\n return fallback;\n};\n\nexport function FileUpload<TResult = unknown>({\n components,\n title = '文件上传',\n description = '选择文件后开始上传,支持 Tale SDK 的直接上传和预签名上传流程。',\n helperText,\n accept,\n multiple = false,\n maxFiles,\n maxSize,\n disabled = false,\n autoUpload = false,\n showUploadButton,\n showResetButton = true,\n selectLabel = '选择文件',\n uploadLabel = '开始上传',\n retryLabel = '重试',\n resetLabel = '清空',\n emptyLabel = '尚未选择文件',\n dropzoneLabel = '拖拽文件到这里,或点击选择',\n dropzoneDescription = '上传前会先完成文件校验,上传逻辑由业务侧注入。',\n uploadingText = '上传中',\n successText = '上传完成',\n errorText = '上传失败',\n className,\n dropzoneClassName,\n listClassName,\n formatFileSize = defaultFormatFileSize,\n validateFile,\n onFilesChange,\n onUpload,\n onUploadComplete,\n onUploadError,\n}: FileUploadProps<TResult>) {\n const [items, setItems] = useState<FileUploadItem<TResult>[]>([]);\n const [isDragging, setIsDragging] = useState(false);\n const inputRef = useRef<HTMLInputElement>(null);\n const shouldShowUploadButton = showUploadButton ?? Boolean(onUpload);\n const resolvedMaxFiles = multiple ? maxFiles : 1;\n const hasUploadableItems = items.some((item) => item.status === 'ready');\n const isUploading = items.some((item) => item.status === 'uploading');\n\n useEffect(() => {\n onFilesChange?.(items);\n }, [items, onFilesChange]);\n\n if (!components) {\n return (\n <div className=\"p-4 text-center text-destructive\">\n 错误:请通过 components prop 注入 UI 组件\n </div>\n );\n }\n\n const {\n Card,\n CardHeader,\n CardTitle,\n CardDescription,\n CardContent,\n CardFooter,\n Button,\n } = components;\n\n const updateItems = (\n updater: (\n currentItems: FileUploadItem<TResult>[]\n ) => FileUploadItem<TResult>[]\n ) => {\n setItems((currentItems) => updater(currentItems));\n };\n\n const getValidationError = (\n file: File,\n currentItems: FileUploadItem<TResult>[]\n ) => {\n if (maxSize && file.size > maxSize) {\n return `文件不能超过 ${formatFileSize(maxSize)}`;\n }\n if (!matchesAccept(file, accept)) {\n return '文件类型不符合要求';\n }\n return validateFile?.(file, currentItems);\n };\n\n const createItemsFromFiles = (\n files: File[],\n currentItems: FileUploadItem<TResult>[]\n ) => {\n const nextItems = multiple ? [...currentItems] : [];\n const remainingSlots =\n resolvedMaxFiles === undefined\n ? files.length\n : Math.max(resolvedMaxFiles - nextItems.length, 0);\n\n files.slice(0, remainingSlots).forEach((file) => {\n const error = getValidationError(file, nextItems);\n nextItems.push({\n id: createFileId(file),\n file,\n name: file.name,\n size: file.size,\n type: file.type,\n status: error ? 'error' : 'ready',\n progress: 0,\n error,\n });\n });\n\n if (resolvedMaxFiles !== undefined && files.length > remainingSlots) {\n files.slice(remainingSlots).forEach((file) => {\n nextItems.push({\n id: createFileId(file),\n file,\n name: file.name,\n size: file.size,\n type: file.type,\n status: 'error',\n progress: 0,\n error: `最多只能选择 ${resolvedMaxFiles} 个文件`,\n });\n });\n }\n\n return nextItems;\n };\n\n const uploadItem = async (targetItem: FileUploadItem<TResult>) => {\n if (!onUpload || targetItem.status === 'uploading') return;\n\n updateItems((currentItems) =>\n currentItems.map((item) =>\n item.id === targetItem.id\n ? { ...item, status: 'uploading', progress: item.progress || 5 }\n : item\n )\n );\n\n const setProgress = (progress: number) => {\n updateItems((currentItems) =>\n currentItems.map((item) =>\n item.id === targetItem.id\n ? {\n ...item,\n progress: Math.max(0, Math.min(100, Math.round(progress))),\n }\n : item\n )\n );\n };\n\n try {\n const result = await onUpload(targetItem, { setProgress });\n const completedItem = {\n ...targetItem,\n status: 'success' as const,\n progress: 100,\n error: undefined,\n result,\n };\n updateItems((currentItems) =>\n currentItems.map((item) =>\n item.id === targetItem.id ? completedItem : item\n )\n );\n onUploadComplete?.(completedItem);\n } catch (error) {\n const failedItem = {\n ...targetItem,\n status: 'error' as const,\n progress: 0,\n error: getErrorMessage(error, errorText),\n };\n updateItems((currentItems) =>\n currentItems.map((item) =>\n item.id === targetItem.id ? failedItem : item\n )\n );\n onUploadError?.(failedItem, error);\n }\n };\n\n const uploadReadyItems = async () => {\n const readyItems = items.filter((item) => item.status === 'ready');\n for (const item of readyItems) {\n await uploadItem(item);\n }\n };\n\n const handleFiles = (fileList: FileList | null) => {\n if (!fileList || disabled) return;\n const files = Array.from(fileList);\n updateItems((currentItems) => {\n const nextItems = createItemsFromFiles(files, currentItems);\n if (autoUpload && onUpload) {\n nextItems\n .filter((item) => item.status === 'ready')\n .forEach((item) => {\n window.setTimeout(() => uploadItem(item), 0);\n });\n }\n return nextItems;\n });\n if (inputRef.current) {\n inputRef.current.value = '';\n }\n };\n\n const handleDrop = (event: DragEvent<HTMLDivElement>) => {\n event.preventDefault();\n setIsDragging(false);\n handleFiles(event.dataTransfer.files);\n };\n\n const handleRemove = (id: string) => {\n updateItems((currentItems) =>\n currentItems.filter((item) => item.id !== id)\n );\n };\n\n const handleRetry = (item: FileUploadItem<TResult>) => {\n const error = getValidationError(\n item.file,\n items.filter((currentItem) => currentItem.id !== item.id)\n );\n if (error) {\n updateItems((currentItems) =>\n currentItems.map((currentItem) =>\n currentItem.id === item.id ? { ...currentItem, error } : currentItem\n )\n );\n return;\n }\n uploadItem({ ...item, status: 'ready', error: undefined, progress: 0 });\n };\n\n const renderStatus = (item: FileUploadItem<TResult>) => {\n if (item.status === 'uploading') {\n return (\n <span className=\"inline-flex items-center gap-1 text-xs font-medium text-blue-600 dark:text-blue-300\">\n <Loader2 className=\"h-3.5 w-3.5 animate-spin\" />\n {uploadingText}\n </span>\n );\n }\n if (item.status === 'success') {\n return (\n <span className=\"inline-flex items-center gap-1 text-xs font-medium text-emerald-600 dark:text-emerald-300\">\n <CheckCircle2 className=\"h-3.5 w-3.5\" />\n {successText}\n </span>\n );\n }\n if (item.status === 'error') {\n return (\n <span className=\"inline-flex items-center gap-1 text-xs font-medium text-destructive\">\n <XCircle className=\"h-3.5 w-3.5\" />\n {errorText}\n </span>\n );\n }\n return <span className=\"text-xs text-muted-foreground\">待上传</span>;\n };\n\n const header = (\n <>\n {title && CardTitle && <CardTitle>{title}</CardTitle>}\n {title && !CardTitle && (\n <div className=\"text-lg font-semibold leading-none tracking-tight\">\n {title}\n </div>\n )}\n {description && CardDescription && (\n <CardDescription>{description}</CardDescription>\n )}\n {description && !CardDescription && (\n <div className=\"text-sm text-muted-foreground\">{description}</div>\n )}\n </>\n );\n\n return (\n <Card className={cn('overflow-hidden', className)}>\n {CardHeader && (title || description) ? (\n <CardHeader>{header}</CardHeader>\n ) : (\n (title || description) && (\n <div className=\"space-y-1.5 p-6\">{header}</div>\n )\n )}\n <CardContent className=\"space-y-4\">\n <input\n ref={inputRef}\n type=\"file\"\n accept={accept}\n multiple={multiple}\n className=\"sr-only\"\n onChange={(event) => handleFiles(event.target.files)}\n disabled={disabled}\n />\n <div\n role=\"button\"\n tabIndex={disabled ? -1 : 0}\n aria-disabled={disabled}\n className={cn(\n 'flex min-h-40 cursor-pointer flex-col items-center justify-center rounded-lg border border-dashed border-muted-foreground/30 bg-muted/20 px-6 py-8 text-center transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring',\n isDragging && 'border-primary bg-primary/5',\n disabled && 'cursor-not-allowed opacity-60',\n dropzoneClassName\n )}\n onClick={() => {\n if (!disabled) {\n inputRef.current?.click();\n }\n }}\n onKeyDown={(event) => {\n if (!disabled && (event.key === 'Enter' || event.key === ' ')) {\n event.preventDefault();\n inputRef.current?.click();\n }\n }}\n onDragOver={(event) => {\n event.preventDefault();\n if (!disabled) {\n setIsDragging(true);\n }\n }}\n onDragLeave={() => setIsDragging(false)}\n onDrop={handleDrop}\n >\n <div className=\"mb-3 rounded-full bg-primary/10 p-3 text-primary\">\n <UploadCloud className=\"h-6 w-6\" />\n </div>\n <div className=\"text-sm font-medium\">{dropzoneLabel}</div>\n {dropzoneDescription && (\n <div className=\"mt-1 max-w-md text-sm text-muted-foreground\">\n {dropzoneDescription}\n </div>\n )}\n <Button\n type=\"button\"\n size=\"sm\"\n variant=\"secondary\"\n className=\"mt-4\"\n disabled={disabled}\n onClick={(event) => {\n event.stopPropagation();\n inputRef.current?.click();\n }}\n >\n {selectLabel}\n </Button>\n </div>\n\n {helperText && (\n <div className=\"text-sm text-muted-foreground\">{helperText}</div>\n )}\n\n <div className={cn('space-y-3', listClassName)}>\n {items.length === 0 ? (\n <div className=\"rounded-md border border-dashed px-4 py-3 text-sm text-muted-foreground\">\n {emptyLabel}\n </div>\n ) : (\n items.map((item) => (\n <div\n key={item.id}\n className=\"rounded-lg border bg-background px-4 py-3\"\n >\n <div className=\"flex items-start gap-3\">\n <div className=\"mt-0.5 rounded-md bg-muted p-2 text-muted-foreground\">\n <FileText className=\"h-4 w-4\" />\n </div>\n <div className=\"min-w-0 flex-1 space-y-2\">\n <div className=\"flex flex-wrap items-start justify-between gap-2\">\n <div className=\"min-w-0\">\n <div className=\"truncate text-sm font-medium\">\n {item.name}\n </div>\n <div className=\"text-xs text-muted-foreground\">\n {formatFileSize(item.size)}\n {item.type ? ` · ${item.type}` : ''}\n </div>\n </div>\n {renderStatus(item)}\n </div>\n {item.status === 'uploading' && (\n <div\n className=\"h-2 overflow-hidden rounded-full bg-muted\"\n aria-label={`${item.name} 上传进度`}\n role=\"progressbar\"\n aria-valuenow={item.progress}\n aria-valuemin={0}\n aria-valuemax={100}\n >\n <div\n className=\"h-full rounded-full bg-primary transition-all\"\n style={{ width: `${item.progress}%` }}\n />\n </div>\n )}\n {item.error && (\n <div className=\"text-xs text-destructive\">\n {item.error}\n </div>\n )}\n </div>\n <div className=\"flex shrink-0 items-center gap-1\">\n {item.status === 'error' && onUpload && (\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n disabled={disabled || isUploading}\n onClick={() => handleRetry(item)}\n >\n {retryLabel}\n </Button>\n )}\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon\"\n aria-label={`移除 ${item.name}`}\n disabled={disabled || item.status === 'uploading'}\n onClick={() => handleRemove(item.id)}\n >\n <X className=\"h-4 w-4\" />\n </Button>\n </div>\n </div>\n </div>\n ))\n )}\n </div>\n </CardContent>\n {(shouldShowUploadButton || showResetButton) &&\n (CardFooter ? (\n <CardFooter className=\"justify-end gap-2\">\n {showResetButton && (\n <Button\n type=\"button\"\n variant=\"outline\"\n disabled={disabled || isUploading || items.length === 0}\n onClick={() => setItems([])}\n >\n {resetLabel}\n </Button>\n )}\n {shouldShowUploadButton && (\n <Button\n type=\"button\"\n disabled={\n disabled || isUploading || !hasUploadableItems || !onUpload\n }\n onClick={uploadReadyItems}\n >\n {uploadLabel}\n </Button>\n )}\n </CardFooter>\n ) : (\n <div className=\"flex justify-end gap-2 p-6 pt-0\">\n {showResetButton && (\n <Button\n type=\"button\"\n variant=\"outline\"\n disabled={disabled || isUploading || items.length === 0}\n onClick={() => setItems([])}\n >\n {resetLabel}\n </Button>\n )}\n {shouldShowUploadButton && (\n <Button\n type=\"button\"\n disabled={\n disabled || isUploading || !hasUploadableItems || !onUpload\n }\n onClick={uploadReadyItems}\n >\n {uploadLabel}\n </Button>\n )}\n </div>\n ))}\n </Card>\n );\n}\n"],"names":["defaultFormatFileSize","size","createFileId","file","getFileExtension","fileName","index","matchesAccept","accept","fileType","fileExtension","item","rule","getErrorMessage","error","fallback","FileUpload","components","title","description","helperText","multiple","maxFiles","maxSize","disabled","autoUpload","showUploadButton","showResetButton","selectLabel","uploadLabel","retryLabel","resetLabel","emptyLabel","dropzoneLabel","dropzoneDescription","uploadingText","successText","errorText","className","dropzoneClassName","listClassName","formatFileSize","validateFile","onFilesChange","onUpload","onUploadComplete","onUploadError","items","setItems","useState","isDragging","setIsDragging","inputRef","useRef","shouldShowUploadButton","resolvedMaxFiles","hasUploadableItems","isUploading","useEffect","jsx","Card","CardHeader","CardTitle","CardDescription","CardContent","CardFooter","Button","updateItems","updater","currentItems","getValidationError","createItemsFromFiles","files","nextItems","remainingSlots","uploadItem","targetItem","setProgress","progress","result","completedItem","failedItem","uploadReadyItems","readyItems","handleFiles","fileList","handleDrop","event","handleRemove","id","handleRetry","currentItem","renderStatus","jsxs","Loader2","CheckCircle2","XCircle","header","Fragment","cn","_a","UploadCloud","FileText","X"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./jsx-runtime-BB_1_6y_.cjs"),u=require("lucide-react"),r=require("react"),I=require("./utils-IjLH3w2e.cjs"),$=require("./media-utils-X1dDYP9W.cjs"),z=["jpg","jpeg","png","gif","webp","svg","bmp","avif","ico"],L=["image/jpeg","image/png","image/gif","image/webp","image/svg+xml","image/bmp","image/avif","image/x-icon","image/vnd.microsoft.icon"],pe=s=>s?s instanceof Error?s:new Error(s):null,je=(s,c,a)=>Math.min(Math.max(s,c),a);function Ee({src:s,alt:c="",fileName:a,mimeType:d,components:B,loading:F=!1,error:X,className:M,containerClassName:Y,imageClassName:Z,toolbarClassName:H,loadingText:J="正在加载图片...",errorText:S="图片加载失败",unsupportedText:K="暂不支持该图片格式",showToolbar:Q=!0,showOpenInNewTab:V=!0,objectFit:W="contain",initialScale:C=1,minScale:p=.25,maxScale:j=4,scaleStep:P=.25,scale:E,onScaleChange:l,rotation:f,onRotationChange:m,allowUnsupportedFormat:ee=!1,supportedExtensions:te=z,supportedMimeTypes:se=L,onLoad:g,onError:R,style:ne,...re}){const{Card:_,CardContent:y,Button:O,Skeleton:b}=B||{},[ie,oe]=r.useState(C),[ae,xe]=r.useState(0),[ue,h]=r.useState(!0),[le,v]=r.useState(null),o=E??ie,w=f??ae,i=pe(X)||le,k=ee||$.isSupportedMediaSource({src:s,fileName:a,mimeType:d,supportedExtensions:te,supportedMimeTypes:se}),q=F||ue&&!i,T=r.useCallback(t=>{const n=je(t,p,j);E===void 0&&oe(n),l==null||l(n)},[E,j,p,l]),U=r.useCallback(t=>{const n=(t%360+360)%360;f===void 0&&xe(n),m==null||m(n)},[f,m]),me=r.useMemo(()=>{const t=$.getMediaExtension(s,a);return t?t.toUpperCase():d||"图片"},[a,d,s]);r.useEffect(()=>{h(!0),v(null)},[s]);const x=(t,n,D,G)=>{const de="inline-flex h-8 w-8 items-center justify-center rounded-md border border-input bg-background text-foreground shadow-sm transition-colors hover:bg-accent hover:text-accent-foreground disabled:pointer-events-none disabled:opacity-50";return O?e.jsxRuntimeExports.jsx(O,{"aria-label":t,className:"h-8 w-8",disabled:G,onClick:D,size:"icon",title:t,type:"button",variant:"outline",children:n}):e.jsxRuntimeExports.jsx("button",{"aria-label":t,className:de,disabled:G,onClick:D,title:t,type:"button",children:n})},ce=()=>e.jsxRuntimeExports.jsx("div",{className:"w-full space-y-3 p-4",role:"status","aria-live":"polite",children:b?e.jsxRuntimeExports.jsxs(e.jsxRuntimeExports.Fragment,{children:[e.jsxRuntimeExports.jsx(b,{className:"h-4 w-32"}),e.jsxRuntimeExports.jsx(b,{className:"h-80 w-full"})]}):e.jsxRuntimeExports.jsx("p",{className:"text-sm text-muted-foreground",children:J})}),A=t=>e.jsxRuntimeExports.jsxs("div",{className:"p-4 text-center text-sm text-destructive",role:"alert",children:[e.jsxRuntimeExports.jsx("p",{className:"font-medium",children:t||S}),i!=null&&i.message?e.jsxRuntimeExports.jsx("p",{className:"mt-1 opacity-80",children:i.message}):null]}),N=e.jsxRuntimeExports.jsxs("div",{className:I.cn("flex h-full min-h-[360px] flex-col overflow-hidden rounded-md border bg-background",Y),children:[Q?e.jsxRuntimeExports.jsxs("div",{className:I.cn("flex flex-wrap items-center justify-between gap-2 border-b px-3 py-2",H),children:[e.jsxRuntimeExports.jsx("span",{className:"text-xs font-medium text-muted-foreground",children:me}),e.jsxRuntimeExports.jsxs("div",{className:"flex items-center gap-1",children:[x("缩小",e.jsxRuntimeExports.jsx(u.ZoomOut,{className:"h-4 w-4"}),()=>T(o-P),o<=p),e.jsxRuntimeExports.jsxs("span",{className:"min-w-14 text-center text-xs text-muted-foreground",children:[Math.round(o*100),"%"]}),x("放大",e.jsxRuntimeExports.jsx(u.ZoomIn,{className:"h-4 w-4"}),()=>T(o+P),o>=j),x("向左旋转",e.jsxRuntimeExports.jsx(u.RotateCcw,{className:"h-4 w-4"}),()=>U(w-90)),x("向右旋转",e.jsxRuntimeExports.jsx(u.RotateCw,{className:"h-4 w-4"}),()=>U(w+90)),V?x("新窗口打开",e.jsxRuntimeExports.jsx(u.ExternalLink,{className:"h-4 w-4"}),()=>window.open(s,"_blank","noreferrer")):null]})]}):null,e.jsxRuntimeExports.jsxs("div",{className:"relative flex min-h-0 flex-1 items-center justify-center overflow-auto bg-muted/20 p-4",children:[k?i?A():null:A(K),k&&!i?e.jsxRuntimeExports.jsxs(e.jsxRuntimeExports.Fragment,{children:[q?ce():null,e.jsxRuntimeExports.jsx("img",{...re,alt:c,className:I.cn("max-h-full max-w-full transition-transform",q?"invisible absolute":"visible",Z),onError:()=>{const t=new Error(S);h(!1),v(t),R==null||R(t)},onLoad:()=>{h(!1),v(null),g==null||g()},src:s,style:{objectFit:W,transform:`scale(${o}) rotate(${w}deg)`,transformOrigin:"center center",...ne}})]}):null]})]});return _?e.jsxRuntimeExports.jsx(_,{className:M,children:y?e.jsxRuntimeExports.jsx(y,{children:N}):N}):e.jsxRuntimeExports.jsx("div",{className:M,children:N})}exports.ImageReader=Ee;exports.SUPPORTED_IMAGE_EXTENSIONS=z;exports.SUPPORTED_IMAGE_MIME_TYPES=L;
2
+ //# sourceMappingURL=image-reader.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"image-reader.cjs","sources":["../src/components/ImageReader.tsx"],"sourcesContent":["import {\n ExternalLink as ExternalLinkIcon,\n RotateCcw as RotateCcwIcon,\n RotateCw as RotateCwIcon,\n ZoomIn as ZoomInIcon,\n ZoomOut as ZoomOutIcon,\n} from 'lucide-react';\nimport { useCallback, useEffect, useMemo, useState } from 'react';\nimport type { HTMLAttributes, ImgHTMLAttributes, ReactNode } from 'react';\n\nimport { cn } from '../lib/utils';\nimport type {\n ButtonComponent,\n CardComponent,\n SkeletonComponent,\n UIComponent,\n} from '../types/component-types';\n\nimport { getMediaExtension, isSupportedMediaSource } from './media-utils';\n\nexport const SUPPORTED_IMAGE_EXTENSIONS = [\n 'jpg',\n 'jpeg',\n 'png',\n 'gif',\n 'webp',\n 'svg',\n 'bmp',\n 'avif',\n 'ico',\n] as const;\n\nexport const SUPPORTED_IMAGE_MIME_TYPES = [\n 'image/jpeg',\n 'image/png',\n 'image/gif',\n 'image/webp',\n 'image/svg+xml',\n 'image/bmp',\n 'image/avif',\n 'image/x-icon',\n 'image/vnd.microsoft.icon',\n] as const;\n\nexport interface ImageReaderUIComponents {\n Card?: CardComponent;\n CardContent?: UIComponent<HTMLAttributes<HTMLDivElement>>;\n Button?: ButtonComponent;\n Skeleton?: SkeletonComponent;\n}\n\nexport interface ImageReaderProps\n extends Omit<\n ImgHTMLAttributes<HTMLImageElement>,\n | 'alt'\n | 'children'\n | 'className'\n | 'loading'\n | 'onError'\n | 'onLoad'\n | 'src'\n > {\n src: string;\n alt?: string;\n fileName?: string;\n mimeType?: string;\n components?: ImageReaderUIComponents;\n loading?: boolean;\n error?: Error | string | null;\n className?: string;\n containerClassName?: string;\n imageClassName?: string;\n toolbarClassName?: string;\n loadingText?: string;\n errorText?: string;\n unsupportedText?: string;\n showToolbar?: boolean;\n showOpenInNewTab?: boolean;\n objectFit?: 'contain' | 'cover' | 'fill' | 'none' | 'scale-down';\n initialScale?: number;\n minScale?: number;\n maxScale?: number;\n scaleStep?: number;\n scale?: number;\n onScaleChange?: (scale: number) => void;\n rotation?: number;\n onRotationChange?: (rotation: number) => void;\n allowUnsupportedFormat?: boolean;\n supportedExtensions?: readonly string[];\n supportedMimeTypes?: readonly string[];\n onLoad?: () => void;\n onError?: (error: Error) => void;\n}\n\nconst normalizeError = (error: Error | string | null | undefined) => {\n if (!error) return null;\n return error instanceof Error ? error : new Error(error);\n};\n\nconst clamp = (value: number, min: number, max: number) =>\n Math.min(Math.max(value, min), max);\n\nexport function ImageReader({\n src,\n alt = '',\n fileName,\n mimeType,\n components,\n loading = false,\n error,\n className,\n containerClassName,\n imageClassName,\n toolbarClassName,\n loadingText = '正在加载图片...',\n errorText = '图片加载失败',\n unsupportedText = '暂不支持该图片格式',\n showToolbar = true,\n showOpenInNewTab = true,\n objectFit = 'contain',\n initialScale = 1,\n minScale = 0.25,\n maxScale = 4,\n scaleStep = 0.25,\n scale: controlledScale,\n onScaleChange,\n rotation: controlledRotation,\n onRotationChange,\n allowUnsupportedFormat = false,\n supportedExtensions = SUPPORTED_IMAGE_EXTENSIONS,\n supportedMimeTypes = SUPPORTED_IMAGE_MIME_TYPES,\n onLoad,\n onError,\n style,\n ...imageProps\n}: ImageReaderProps) {\n const { Card, CardContent, Button, Skeleton } = components || {};\n const [internalScale, setInternalScale] = useState(initialScale);\n const [internalRotation, setInternalRotation] = useState(0);\n const [isImageLoading, setIsImageLoading] = useState(true);\n const [imageError, setImageError] = useState<Error | null>(null);\n\n const scale = controlledScale ?? internalScale;\n const rotation = controlledRotation ?? internalRotation;\n const displayedError = normalizeError(error) || imageError;\n const isSupported =\n allowUnsupportedFormat ||\n isSupportedMediaSource({\n src,\n fileName,\n mimeType,\n supportedExtensions,\n supportedMimeTypes,\n });\n const isLoading = loading || (isImageLoading && !displayedError);\n\n const setNextScale = useCallback(\n (nextScale: number) => {\n const clampedScale = clamp(nextScale, minScale, maxScale);\n if (controlledScale === undefined) {\n setInternalScale(clampedScale);\n }\n onScaleChange?.(clampedScale);\n },\n [controlledScale, maxScale, minScale, onScaleChange]\n );\n\n const setNextRotation = useCallback(\n (nextRotation: number) => {\n const normalizedRotation = ((nextRotation % 360) + 360) % 360;\n if (controlledRotation === undefined) {\n setInternalRotation(normalizedRotation);\n }\n onRotationChange?.(normalizedRotation);\n },\n [controlledRotation, onRotationChange]\n );\n\n const formatLabel = useMemo(() => {\n const extension = getMediaExtension(src, fileName);\n return extension ? extension.toUpperCase() : mimeType || '图片';\n }, [fileName, mimeType, src]);\n\n useEffect(() => {\n setIsImageLoading(true);\n setImageError(null);\n }, [src]);\n\n const renderButton = (\n label: string,\n icon: ReactNode,\n onClick: () => void,\n disabled?: boolean\n ) => {\n const buttonClassName =\n 'inline-flex h-8 w-8 items-center justify-center rounded-md border border-input bg-background text-foreground shadow-sm transition-colors hover:bg-accent hover:text-accent-foreground disabled:pointer-events-none disabled:opacity-50';\n\n if (Button) {\n return (\n <Button\n aria-label={label}\n className=\"h-8 w-8\"\n disabled={disabled}\n onClick={onClick}\n size=\"icon\"\n title={label}\n type=\"button\"\n variant=\"outline\"\n >\n {icon}\n </Button>\n );\n }\n\n return (\n <button\n aria-label={label}\n className={buttonClassName}\n disabled={disabled}\n onClick={onClick}\n title={label}\n type=\"button\"\n >\n {icon}\n </button>\n );\n };\n\n const renderLoading = () => (\n <div className=\"w-full space-y-3 p-4\" role=\"status\" aria-live=\"polite\">\n {Skeleton ? (\n <>\n <Skeleton className=\"h-4 w-32\" />\n <Skeleton className=\"h-80 w-full\" />\n </>\n ) : (\n <p className=\"text-sm text-muted-foreground\">{loadingText}</p>\n )}\n </div>\n );\n\n const renderError = (message?: string) => (\n <div className=\"p-4 text-center text-sm text-destructive\" role=\"alert\">\n <p className=\"font-medium\">{message || errorText}</p>\n {displayedError?.message ? (\n <p className=\"mt-1 opacity-80\">{displayedError.message}</p>\n ) : null}\n </div>\n );\n\n const body = (\n <div\n className={cn(\n 'flex h-full min-h-[360px] flex-col overflow-hidden rounded-md border bg-background',\n containerClassName\n )}\n >\n {showToolbar ? (\n <div\n className={cn(\n 'flex flex-wrap items-center justify-between gap-2 border-b px-3 py-2',\n toolbarClassName\n )}\n >\n <span className=\"text-xs font-medium text-muted-foreground\">\n {formatLabel}\n </span>\n <div className=\"flex items-center gap-1\">\n {renderButton(\n '缩小',\n <ZoomOutIcon className=\"h-4 w-4\" />,\n () => setNextScale(scale - scaleStep),\n scale <= minScale\n )}\n <span className=\"min-w-14 text-center text-xs text-muted-foreground\">\n {Math.round(scale * 100)}%\n </span>\n {renderButton(\n '放大',\n <ZoomInIcon className=\"h-4 w-4\" />,\n () => setNextScale(scale + scaleStep),\n scale >= maxScale\n )}\n {renderButton(\n '向左旋转',\n <RotateCcwIcon className=\"h-4 w-4\" />,\n () => setNextRotation(rotation - 90)\n )}\n {renderButton(\n '向右旋转',\n <RotateCwIcon className=\"h-4 w-4\" />,\n () => setNextRotation(rotation + 90)\n )}\n {showOpenInNewTab\n ? renderButton(\n '新窗口打开',\n <ExternalLinkIcon className=\"h-4 w-4\" />,\n () => window.open(src, '_blank', 'noreferrer')\n )\n : null}\n </div>\n </div>\n ) : null}\n <div className=\"relative flex min-h-0 flex-1 items-center justify-center overflow-auto bg-muted/20 p-4\">\n {!isSupported\n ? renderError(unsupportedText)\n : displayedError\n ? renderError()\n : null}\n {isSupported && !displayedError ? (\n <>\n {isLoading ? renderLoading() : null}\n <img\n {...imageProps}\n alt={alt}\n className={cn(\n 'max-h-full max-w-full transition-transform',\n isLoading ? 'invisible absolute' : 'visible',\n imageClassName\n )}\n onError={() => {\n const nextError = new Error(errorText);\n setIsImageLoading(false);\n setImageError(nextError);\n onError?.(nextError);\n }}\n onLoad={() => {\n setIsImageLoading(false);\n setImageError(null);\n onLoad?.();\n }}\n src={src}\n style={{\n objectFit,\n transform: `scale(${scale}) rotate(${rotation}deg)`,\n transformOrigin: 'center center',\n ...style,\n }}\n />\n </>\n ) : null}\n </div>\n </div>\n );\n\n if (Card) {\n return (\n <Card className={className}>\n {CardContent ? <CardContent>{body}</CardContent> : body}\n </Card>\n );\n }\n\n return <div className={className}>{body}</div>;\n}\n"],"names":["SUPPORTED_IMAGE_EXTENSIONS","SUPPORTED_IMAGE_MIME_TYPES","normalizeError","error","clamp","value","min","max","ImageReader","src","alt","fileName","mimeType","components","loading","className","containerClassName","imageClassName","toolbarClassName","loadingText","errorText","unsupportedText","showToolbar","showOpenInNewTab","objectFit","initialScale","minScale","maxScale","scaleStep","controlledScale","onScaleChange","controlledRotation","onRotationChange","allowUnsupportedFormat","supportedExtensions","supportedMimeTypes","onLoad","onError","style","imageProps","Card","CardContent","Button","Skeleton","internalScale","setInternalScale","useState","internalRotation","setInternalRotation","isImageLoading","setIsImageLoading","imageError","setImageError","scale","rotation","displayedError","isSupported","isSupportedMediaSource","isLoading","setNextScale","useCallback","nextScale","clampedScale","setNextRotation","nextRotation","normalizedRotation","formatLabel","useMemo","extension","getMediaExtension","useEffect","renderButton","label","icon","onClick","disabled","buttonClassName","jsx","renderLoading","jsxs","Fragment","renderError","message","body","cn","ZoomOutIcon","ZoomInIcon","RotateCcwIcon","RotateCwIcon","ExternalLinkIcon","nextError"],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export { ImageReader, SUPPORTED_IMAGE_EXTENSIONS, SUPPORTED_IMAGE_MIME_TYPES, } from './components/ImageReader';
2
+ export type { ImageReaderProps, ImageReaderUIComponents, } from './components/ImageReader';
3
+ //# sourceMappingURL=image-reader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"image-reader.d.ts","sourceRoot":"","sources":["../src/image-reader.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,WAAW,EACX,0BAA0B,EAC1B,0BAA0B,GAC3B,MAAM,0BAA0B,CAAC;AAClC,YAAY,EACV,gBAAgB,EAChB,uBAAuB,GACxB,MAAM,0BAA0B,CAAC"}