@ai-matrx/media 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/react.js ADDED
@@ -0,0 +1,2120 @@
1
+ "use client";
2
+
3
+ // src/react/cn.ts
4
+ import { twMerge } from "tailwind-merge";
5
+ function cn(...inputs) {
6
+ return twMerge(inputs.filter(Boolean).join(" "));
7
+ }
8
+
9
+ // src/react/icons.tsx
10
+ import { jsx, jsxs } from "react/jsx-runtime";
11
+ function svgProps(props) {
12
+ return {
13
+ xmlns: "http://www.w3.org/2000/svg",
14
+ viewBox: "0 0 24 24",
15
+ width: 24,
16
+ height: 24,
17
+ fill: "none",
18
+ stroke: "currentColor",
19
+ strokeWidth: 2,
20
+ strokeLinecap: "round",
21
+ strokeLinejoin: "round",
22
+ "aria-hidden": true,
23
+ ...props
24
+ };
25
+ }
26
+ function ArchiveIcon(props) {
27
+ return /* @__PURE__ */ jsxs("svg", { ...svgProps(props), children: [
28
+ /* @__PURE__ */ jsx("rect", { width: "20", height: "5", x: "2", y: "3", rx: "1" }),
29
+ /* @__PURE__ */ jsx("path", { d: "M4 8v11a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8" }),
30
+ /* @__PURE__ */ jsx("path", { d: "M10 12h4" })
31
+ ] });
32
+ }
33
+ function BracesIcon(props) {
34
+ return /* @__PURE__ */ jsxs("svg", { ...svgProps(props), children: [
35
+ /* @__PURE__ */ jsx("path", { d: "M8 3H7a2 2 0 0 0-2 2v5a2 2 0 0 1-2 2 2 2 0 0 1 2 2v5c0 1.1.9 2 2 2h1" }),
36
+ /* @__PURE__ */ jsx("path", { d: "M16 21h1a2 2 0 0 0 2-2v-5c0-1.1.9-2 2-2a2 2 0 0 1-2-2V5a2 2 0 0 0-2-2h-1" })
37
+ ] });
38
+ }
39
+ function CheckIcon(props) {
40
+ return /* @__PURE__ */ jsx("svg", { ...svgProps(props), children: /* @__PURE__ */ jsx("path", { d: "M20 6 9 17l-5-5" }) });
41
+ }
42
+ function CodeIcon(props) {
43
+ return /* @__PURE__ */ jsxs("svg", { ...svgProps(props), children: [
44
+ /* @__PURE__ */ jsx("path", { d: "m16 18 6-6-6-6" }),
45
+ /* @__PURE__ */ jsx("path", { d: "m8 6-6 6 6 6" })
46
+ ] });
47
+ }
48
+ function CopyIcon(props) {
49
+ return /* @__PURE__ */ jsxs("svg", { ...svgProps(props), children: [
50
+ /* @__PURE__ */ jsx("rect", { width: "14", height: "14", x: "8", y: "8", rx: "2", ry: "2" }),
51
+ /* @__PURE__ */ jsx("path", { d: "M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2" })
52
+ ] });
53
+ }
54
+ function DatabaseIcon(props) {
55
+ return /* @__PURE__ */ jsxs("svg", { ...svgProps(props), children: [
56
+ /* @__PURE__ */ jsx("ellipse", { cx: "12", cy: "5", rx: "9", ry: "3" }),
57
+ /* @__PURE__ */ jsx("path", { d: "M3 5V19A9 3 0 0 0 21 19V5" }),
58
+ /* @__PURE__ */ jsx("path", { d: "M3 12A9 3 0 0 0 21 12" })
59
+ ] });
60
+ }
61
+ function DownloadIcon(props) {
62
+ return /* @__PURE__ */ jsxs("svg", { ...svgProps(props), children: [
63
+ /* @__PURE__ */ jsx("path", { d: "M12 15V3" }),
64
+ /* @__PURE__ */ jsx("path", { d: "M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" }),
65
+ /* @__PURE__ */ jsx("path", { d: "m7 10 5 5 5-5" })
66
+ ] });
67
+ }
68
+ function ExternalLinkIcon(props) {
69
+ return /* @__PURE__ */ jsxs("svg", { ...svgProps(props), children: [
70
+ /* @__PURE__ */ jsx("path", { d: "M15 3h6v6" }),
71
+ /* @__PURE__ */ jsx("path", { d: "M10 14 21 3" }),
72
+ /* @__PURE__ */ jsx("path", { d: "M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6" })
73
+ ] });
74
+ }
75
+ function FileIcon(props) {
76
+ return /* @__PURE__ */ jsxs("svg", { ...svgProps(props), children: [
77
+ /* @__PURE__ */ jsx("path", { d: "M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z" }),
78
+ /* @__PURE__ */ jsx("path", { d: "M14 2v5a1 1 0 0 0 1 1h5" })
79
+ ] });
80
+ }
81
+ function FileAudioIcon(props) {
82
+ return /* @__PURE__ */ jsxs("svg", { ...svgProps(props), children: [
83
+ /* @__PURE__ */ jsx("path", { d: "M4 6.835V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.706.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2h-.343" }),
84
+ /* @__PURE__ */ jsx("path", { d: "M14 2v5a1 1 0 0 0 1 1h5" }),
85
+ /* @__PURE__ */ jsx("path", { d: "M2 19a2 2 0 0 1 4 0v1a2 2 0 0 1-4 0v-4a6 6 0 0 1 12 0v4a2 2 0 0 1-4 0v-1a2 2 0 0 1 4 0" })
86
+ ] });
87
+ }
88
+ function FileCodeIcon(props) {
89
+ return /* @__PURE__ */ jsxs("svg", { ...svgProps(props), children: [
90
+ /* @__PURE__ */ jsx("path", { d: "M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z" }),
91
+ /* @__PURE__ */ jsx("path", { d: "M14 2v5a1 1 0 0 0 1 1h5" }),
92
+ /* @__PURE__ */ jsx("path", { d: "M10 12.5 8 15l2 2.5" }),
93
+ /* @__PURE__ */ jsx("path", { d: "m14 12.5 2 2.5-2 2.5" })
94
+ ] });
95
+ }
96
+ function FileJsonIcon(props) {
97
+ return /* @__PURE__ */ jsxs("svg", { ...svgProps(props), children: [
98
+ /* @__PURE__ */ jsx("path", { d: "M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z" }),
99
+ /* @__PURE__ */ jsx("path", { d: "M14 2v5a1 1 0 0 0 1 1h5" }),
100
+ /* @__PURE__ */ jsx("path", { d: "M10 12a1 1 0 0 0-1 1v1a1 1 0 0 1-1 1 1 1 0 0 1 1 1v1a1 1 0 0 0 1 1" }),
101
+ /* @__PURE__ */ jsx("path", { d: "M14 18a1 1 0 0 0 1-1v-1a1 1 0 0 1 1-1 1 1 0 0 1-1-1v-1a1 1 0 0 0-1-1" })
102
+ ] });
103
+ }
104
+ function FileSpreadsheetIcon(props) {
105
+ return /* @__PURE__ */ jsxs("svg", { ...svgProps(props), children: [
106
+ /* @__PURE__ */ jsx("path", { d: "M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z" }),
107
+ /* @__PURE__ */ jsx("path", { d: "M14 2v5a1 1 0 0 0 1 1h5" }),
108
+ /* @__PURE__ */ jsx("path", { d: "M8 13h2" }),
109
+ /* @__PURE__ */ jsx("path", { d: "M14 13h2" }),
110
+ /* @__PURE__ */ jsx("path", { d: "M8 17h2" }),
111
+ /* @__PURE__ */ jsx("path", { d: "M14 17h2" })
112
+ ] });
113
+ }
114
+ function FileTextIcon(props) {
115
+ return /* @__PURE__ */ jsxs("svg", { ...svgProps(props), children: [
116
+ /* @__PURE__ */ jsx("path", { d: "M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z" }),
117
+ /* @__PURE__ */ jsx("path", { d: "M14 2v5a1 1 0 0 0 1 1h5" }),
118
+ /* @__PURE__ */ jsx("path", { d: "M10 9H8" }),
119
+ /* @__PURE__ */ jsx("path", { d: "M16 13H8" }),
120
+ /* @__PURE__ */ jsx("path", { d: "M16 17H8" })
121
+ ] });
122
+ }
123
+ function FileTypeIcon(props) {
124
+ return /* @__PURE__ */ jsxs("svg", { ...svgProps(props), children: [
125
+ /* @__PURE__ */ jsx("path", { d: "M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z" }),
126
+ /* @__PURE__ */ jsx("path", { d: "M14 2v5a1 1 0 0 0 1 1h5" }),
127
+ /* @__PURE__ */ jsx("path", { d: "M11 18h2" }),
128
+ /* @__PURE__ */ jsx("path", { d: "M12 12v6" }),
129
+ /* @__PURE__ */ jsx("path", { d: "M9 13v-.5a.5.5 0 0 1 .5-.5h5a.5.5 0 0 1 .5.5v.5" })
130
+ ] });
131
+ }
132
+ function FileVideoIcon(props) {
133
+ return /* @__PURE__ */ jsxs("svg", { ...svgProps(props), children: [
134
+ /* @__PURE__ */ jsx("path", { d: "M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z" }),
135
+ /* @__PURE__ */ jsx("path", { d: "M14 2v5a1 1 0 0 0 1 1h5" }),
136
+ /* @__PURE__ */ jsx("path", { d: "M15.033 13.44a.647.647 0 0 1 0 1.12l-4.065 2.352a.645.645 0 0 1-.968-.56v-4.704a.645.645 0 0 1 .967-.56z" })
137
+ ] });
138
+ }
139
+ function FolderIcon(props) {
140
+ return /* @__PURE__ */ jsx("svg", { ...svgProps(props), children: /* @__PURE__ */ jsx("path", { d: "M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z" }) });
141
+ }
142
+ function FolderOpenIcon(props) {
143
+ return /* @__PURE__ */ jsx("svg", { ...svgProps(props), children: /* @__PURE__ */ jsx("path", { d: "m6 14 1.5-2.9A2 2 0 0 1 9.24 10H20a2 2 0 0 1 1.94 2.5l-1.54 6a2 2 0 0 1-1.95 1.5H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h3.9a2 2 0 0 1 1.69.9l.81 1.2a2 2 0 0 0 1.67.9H18a2 2 0 0 1 2 2v2" }) });
144
+ }
145
+ function ImageIcon(props) {
146
+ return /* @__PURE__ */ jsxs("svg", { ...svgProps(props), children: [
147
+ /* @__PURE__ */ jsx("rect", { width: "18", height: "18", x: "3", y: "3", rx: "2", ry: "2" }),
148
+ /* @__PURE__ */ jsx("circle", { cx: "9", cy: "9", r: "2" }),
149
+ /* @__PURE__ */ jsx("path", { d: "m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21" })
150
+ ] });
151
+ }
152
+ function ImageOffIcon(props) {
153
+ return /* @__PURE__ */ jsxs("svg", { ...svgProps(props), children: [
154
+ /* @__PURE__ */ jsx("line", { x1: "2", x2: "22", y1: "2", y2: "22" }),
155
+ /* @__PURE__ */ jsx("path", { d: "M10.41 10.41a2 2 0 1 1-2.83-2.83" }),
156
+ /* @__PURE__ */ jsx("line", { x1: "13.5", x2: "6", y1: "13.5", y2: "21" }),
157
+ /* @__PURE__ */ jsx("line", { x1: "18", x2: "21", y1: "12", y2: "15" }),
158
+ /* @__PURE__ */ jsx("path", { d: "M3.59 3.59A1.99 1.99 0 0 0 3 5v14a2 2 0 0 0 2 2h14c.55 0 1.052-.22 1.41-.59" }),
159
+ /* @__PURE__ */ jsx("path", { d: "M21 15V5a2 2 0 0 0-2-2H9" })
160
+ ] });
161
+ }
162
+ function MusicIcon(props) {
163
+ return /* @__PURE__ */ jsxs("svg", { ...svgProps(props), children: [
164
+ /* @__PURE__ */ jsx("path", { d: "M9 18V5l12-2v13" }),
165
+ /* @__PURE__ */ jsx("circle", { cx: "6", cy: "18", r: "3" }),
166
+ /* @__PURE__ */ jsx("circle", { cx: "18", cy: "16", r: "3" })
167
+ ] });
168
+ }
169
+ function PackageBoxIcon(props) {
170
+ return /* @__PURE__ */ jsxs("svg", { ...svgProps(props), children: [
171
+ /* @__PURE__ */ jsx("path", { d: "M11 21.73a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73z" }),
172
+ /* @__PURE__ */ jsx("path", { d: "M12 22V12" }),
173
+ /* @__PURE__ */ jsx("polyline", { points: "3.29 7 12 12 20.71 7" }),
174
+ /* @__PURE__ */ jsx("path", { d: "m7.5 4.27 9 5.15" })
175
+ ] });
176
+ }
177
+ function PenToolIcon(props) {
178
+ return /* @__PURE__ */ jsxs("svg", { ...svgProps(props), children: [
179
+ /* @__PURE__ */ jsx("path", { d: "M15.707 21.293a1 1 0 0 1-1.414 0l-1.586-1.586a1 1 0 0 1 0-1.414l5.586-5.586a1 1 0 0 1 1.414 0l1.586 1.586a1 1 0 0 1 0 1.414z" }),
180
+ /* @__PURE__ */ jsx("path", { d: "m18 13-1.375-6.874a1 1 0 0 0-.746-.776L3.235 2.028a1 1 0 0 0-1.207 1.207L5.35 15.879a1 1 0 0 0 .776.746L13 18" }),
181
+ /* @__PURE__ */ jsx("path", { d: "m2.3 2.3 7.286 7.286" }),
182
+ /* @__PURE__ */ jsx("circle", { cx: "11", cy: "11", r: "2" })
183
+ ] });
184
+ }
185
+ function Share2Icon(props) {
186
+ return /* @__PURE__ */ jsxs("svg", { ...svgProps(props), children: [
187
+ /* @__PURE__ */ jsx("circle", { cx: "18", cy: "5", r: "3" }),
188
+ /* @__PURE__ */ jsx("circle", { cx: "6", cy: "12", r: "3" }),
189
+ /* @__PURE__ */ jsx("circle", { cx: "18", cy: "19", r: "3" }),
190
+ /* @__PURE__ */ jsx("line", { x1: "8.59", x2: "15.42", y1: "13.51", y2: "17.49" }),
191
+ /* @__PURE__ */ jsx("line", { x1: "15.41", x2: "8.59", y1: "6.51", y2: "10.49" })
192
+ ] });
193
+ }
194
+ function SubtitlesIcon(props) {
195
+ return /* @__PURE__ */ jsxs("svg", { ...svgProps(props), children: [
196
+ /* @__PURE__ */ jsx("rect", { width: "18", height: "14", x: "3", y: "5", rx: "2", ry: "2" }),
197
+ /* @__PURE__ */ jsx("path", { d: "M7 15h4M15 15h2M7 11h2M13 11h4" })
198
+ ] });
199
+ }
200
+ function UploadIcon(props) {
201
+ return /* @__PURE__ */ jsxs("svg", { ...svgProps(props), children: [
202
+ /* @__PURE__ */ jsx("path", { d: "M12 3v12" }),
203
+ /* @__PURE__ */ jsx("path", { d: "m17 8-5-5-5 5" }),
204
+ /* @__PURE__ */ jsx("path", { d: "M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" })
205
+ ] });
206
+ }
207
+ function VideoIcon(props) {
208
+ return /* @__PURE__ */ jsxs("svg", { ...svgProps(props), children: [
209
+ /* @__PURE__ */ jsx("path", { d: "m16 13 5.223 3.482a.5.5 0 0 0 .777-.416V7.87a.5.5 0 0 0-.752-.432L16 10.5" }),
210
+ /* @__PURE__ */ jsx("rect", { x: "2", y: "6", width: "14", height: "12", rx: "2" })
211
+ ] });
212
+ }
213
+ function VideoOffIcon(props) {
214
+ return /* @__PURE__ */ jsxs("svg", { ...svgProps(props), children: [
215
+ /* @__PURE__ */ jsx("path", { d: "M10.66 6H14a2 2 0 0 1 2 2v2.5l5.248-3.062A.5.5 0 0 1 22 7.87v8.196" }),
216
+ /* @__PURE__ */ jsx("path", { d: "M16 16a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h2" }),
217
+ /* @__PURE__ */ jsx("path", { d: "m2 2 20 20" })
218
+ ] });
219
+ }
220
+ function VolumeXIcon(props) {
221
+ return /* @__PURE__ */ jsxs("svg", { ...svgProps(props), children: [
222
+ /* @__PURE__ */ jsx("path", { d: "M11 4.702a.705.705 0 0 0-1.203-.498L6.413 7.587A1.4 1.4 0 0 1 5.416 8H3a1 1 0 0 0-1 1v6a1 1 0 0 0 1 1h2.416a1.4 1.4 0 0 1 .997.413l3.383 3.384A.705.705 0 0 0 11 19.298z" }),
223
+ /* @__PURE__ */ jsx("line", { x1: "22", x2: "16", y1: "9", y2: "15" }),
224
+ /* @__PURE__ */ jsx("line", { x1: "16", x2: "22", y1: "9", y2: "15" })
225
+ ] });
226
+ }
227
+ function XIcon(props) {
228
+ return /* @__PURE__ */ jsxs("svg", { ...svgProps(props), children: [
229
+ /* @__PURE__ */ jsx("path", { d: "M18 6 6 18" }),
230
+ /* @__PURE__ */ jsx("path", { d: "m6 6 12 12" })
231
+ ] });
232
+ }
233
+ function AlertCircleIcon(props) {
234
+ return /* @__PURE__ */ jsxs("svg", { ...svgProps(props), children: [
235
+ /* @__PURE__ */ jsx("circle", { cx: "12", cy: "12", r: "10" }),
236
+ /* @__PURE__ */ jsx("line", { x1: "12", x2: "12", y1: "8", y2: "12" }),
237
+ /* @__PURE__ */ jsx("line", { x1: "12", x2: "12.01", y1: "16", y2: "16" })
238
+ ] });
239
+ }
240
+ function CheckCircle2Icon(props) {
241
+ return /* @__PURE__ */ jsxs("svg", { ...svgProps(props), children: [
242
+ /* @__PURE__ */ jsx("path", { d: "M21.801 10A10 10 0 1 1 17 3.335" }),
243
+ /* @__PURE__ */ jsx("path", { d: "m9 11 3 3L22 4" })
244
+ ] });
245
+ }
246
+
247
+ // src/core/file-kind.ts
248
+ var ROWS = [
249
+ [["jpg", "jpeg", "png", "gif", "webp", "avif", "heic", "heif", "bmp", "tif", "tiff", "ico"], "IMAGE", "text-emerald-500", "image", "Image"],
250
+ [["svg"], "IMAGE", "text-amber-500", "pen-tool", "SVG image"],
251
+ [["mp4", "mov", "webm", "mkv", "avi", "m4v"], "VIDEO", "text-purple-500", "video", "Video"],
252
+ [["mp3", "wav", "ogg", "m4a", "aac", "flac", "opus"], "AUDIO", "text-pink-500", "music", "Audio"],
253
+ [["pdf"], "DOCUMENT", "text-red-500", "file-type", "PDF Document"],
254
+ [["md", "markdown", "mdx", "rst", "adoc", "asciidoc", "org"], "DOCUMENT", "text-slate-400", "file-text", "Markdown"],
255
+ [["txt", "text", "asc", "me", "log", "out", "err"], "DOCUMENT", "text-muted-foreground", "file-text", "Text"],
256
+ [["dockerfile", "containerfile", "lua"], "CODE", "text-blue-500", "code", "Code"],
257
+ [["mk", "make", "swift", "ml", "mli", "fs", "fsi", "fsx", "svelte"], "CODE", "text-orange-500", "code", "Code"],
258
+ [["diff", "patch", "pem", "csr", "crt", "cer", "der", "key", "pub", "p7b", "p7c", "pfx", "p12"], "CODE", "text-amber-500", "file-text", "Text"],
259
+ [["ini", "cfg", "conf", "config", "properties", "prefs"], "CODE", "text-amber-400", "braces", "Config"],
260
+ [["tex", "latex", "ltx", "sty", "cls", "bib"], "CODE", "text-emerald-500", "file-text", "LaTeX"],
261
+ [["srt", "vtt"], "SUBTITLES", "text-cyan-500", "subtitles", "Subtitles"],
262
+ [["js", "mjs", "cjs", "jsx"], "CODE", "text-yellow-500", "file-code", "JavaScript"],
263
+ [["ts", "tsx"], "CODE", "text-blue-500", "file-code", "TypeScript"],
264
+ [["py", "clj", "cljs", "cljc", "edn", "vue", "styl", "stylus"], "CODE", "text-emerald-500", "code", "Code"],
265
+ [["rb", "rbw", "rake", "ru", "gemspec", "scala", "sbt"], "CODE", "text-red-500", "code", "Code"],
266
+ [["go", "dart"], "CODE", "text-cyan-500", "code", "Code"],
267
+ [["rs"], "CODE", "text-orange-600", "code", "Rust"],
268
+ [["java"], "CODE", "text-red-600", "code", "Java"],
269
+ [["c", "h"], "CODE", "text-blue-600", "code", "C"],
270
+ [["cpp", "cc", "cxx", "hpp"], "CODE", "text-blue-700", "code", "C++"],
271
+ [["cs"], "CODE", "text-purple-600", "code", "C#"],
272
+ [["html", "htm", "kt", "kts"], "CODE", "text-orange-400", "code", "Code"],
273
+ [["css"], "CODE", "text-sky-400", "code", "CSS"],
274
+ [["scss"], "CODE", "text-pink-400", "code", "SCSS"],
275
+ [["sh", "bash", "zsh", "fish", "ksh", "ash", "bat", "cmd", "twig", "jinja", "j2", "njk"], "CODE", "text-emerald-400", "code", "Script"],
276
+ [["sql"], "CODE", "text-amber-400", "code", "SQL"],
277
+ [["pl", "pm"], "CODE", "text-indigo-400", "code", "Perl"],
278
+ [["r", "rmd", "proto", "ps1", "psm1", "psd1", "less"], "CODE", "text-blue-400", "code", "Code"],
279
+ [["ex", "exs"], "CODE", "text-purple-400", "code", "Elixir"],
280
+ [["erl", "hrl"], "CODE", "text-rose-500", "code", "Erlang"],
281
+ [["hs", "lhs"], "CODE", "text-violet-500", "code", "Haskell"],
282
+ [["zig"], "CODE", "text-yellow-500", "code", "Zig"],
283
+ [["nim", "nims"], "CODE", "text-yellow-400", "code", "Nim"],
284
+ [["jl"], "CODE", "text-purple-500", "code", "Julia"],
285
+ [["astro"], "CODE", "text-fuchsia-500", "code", "Astro"],
286
+ [["graphql", "gql", "graphqls"], "CODE", "text-pink-500", "code", "GraphQL"],
287
+ [["sol"], "CODE", "text-slate-400", "code", "Solidity"],
288
+ [["php", "phtml", "phps"], "CODE", "text-indigo-500", "code", "PHP"],
289
+ [["hbs", "handlebars", "mustache", "ejs", "liquid"], "CODE", "text-amber-500", "code", "Template"],
290
+ [["json", "jsonc", "json5", "har", "geojson", "topojson"], "DATA", "text-amber-500", "file-json", "JSON"],
291
+ [["yaml", "yml", "toml"], "CODE", "text-amber-500", "braces", "Config"],
292
+ [["xml"], "DATA", "text-amber-500", "braces", "XML"],
293
+ [["csv", "tsv"], "DATA", "text-orange-500", "file-spreadsheet", "Spreadsheet data"],
294
+ [["sqlite", "sqlite3", "db"], "DATA", "text-blue-400", "database", "Database"],
295
+ [["ttl", "n3", "nt", "nq", "trig"], "DATA", "text-fuchsia-400", "braces", "RDF data"],
296
+ [["xlsx", "xls"], "DOCUMENT", "text-emerald-600", "file-spreadsheet", "Excel workbook"],
297
+ [["doc", "docx"], "DOCUMENT", "text-blue-500", "file-text", "Word document"],
298
+ [["ppt", "pptx"], "DOCUMENT", "text-orange-600", "file-type", "Presentation"],
299
+ [["ipynb"], "NOTEBOOK", "text-orange-400", "file-json", "Notebook"],
300
+ [["epub"], "EBOOK", "text-indigo-500", "file-text", "eBook"],
301
+ [["eml"], "EMAIL", "text-blue-400", "file-text", "Email"],
302
+ [["glb", "gltf", "stl", "obj", "fbx"], "MODEL_3D", "text-violet-400", "package", "3D model"],
303
+ [["zip", "rar", "7z"], "ARCHIVE", "text-amber-600", "archive", "Archive"],
304
+ [["tar", "gz", "tgz"], "ARCHIVE", "text-amber-600", "package", "Archive"]
305
+ ];
306
+ var BY_EXTENSION = /* @__PURE__ */ new Map();
307
+ for (const [extensions, category, colorClass, icon, displayName] of ROWS) {
308
+ for (const ext of extensions) {
309
+ BY_EXTENSION.set(ext, { category, colorClass, icon, displayName });
310
+ }
311
+ }
312
+ var UNKNOWN_DETAILS = {
313
+ category: "UNKNOWN",
314
+ displayName: "File",
315
+ colorClass: "text-muted-foreground",
316
+ icon: "file"
317
+ };
318
+ var ASSUMED_TEXT_DETAILS = {
319
+ category: "DOCUMENT",
320
+ displayName: "Text",
321
+ colorClass: "text-muted-foreground",
322
+ icon: "file-text"
323
+ };
324
+ var FOLDER_DETAILS = {
325
+ category: "FOLDER",
326
+ displayName: "Folder",
327
+ colorClass: "text-sky-500",
328
+ icon: "folder"
329
+ };
330
+ var IMAGE_DETAILS = BY_EXTENSION.get("png");
331
+ var VIDEO_DETAILS = BY_EXTENSION.get("mp4");
332
+ var AUDIO_DETAILS = BY_EXTENSION.get("mp3");
333
+ var PDF_DETAILS = BY_EXTENSION.get("pdf");
334
+ var SVG_DETAILS = BY_EXTENSION.get("svg");
335
+ function basenameOf(path) {
336
+ const idx = Math.max(path.lastIndexOf("/"), path.lastIndexOf("\\"));
337
+ return idx >= 0 ? path.slice(idx + 1) : path;
338
+ }
339
+ function extOf(name) {
340
+ const idx = name.lastIndexOf(".");
341
+ if (idx <= 0 || idx === name.length - 1) return null;
342
+ return name.slice(idx + 1).toLowerCase();
343
+ }
344
+ function dotfileLooksLikeText(filename) {
345
+ const name = basenameOf(filename);
346
+ if (!name.startsWith(".")) return false;
347
+ for (let i = 1; i < name.length; i++) {
348
+ const c = name.charCodeAt(i);
349
+ if (c >= 48 && c <= 57 || c >= 65 && c <= 90 || c >= 97 && c <= 122 || c === 95 || c === 45) {
350
+ return true;
351
+ }
352
+ }
353
+ return false;
354
+ }
355
+ function canonicalMimeBase(raw) {
356
+ return raw.split(";")[0]?.trim().toLowerCase() ?? raw;
357
+ }
358
+ function getFileKindDetails(fileName, mimeType) {
359
+ const name = basenameOf(fileName);
360
+ const lower = name.toLowerCase();
361
+ const ext = lower === "dockerfile" || lower === "containerfile" ? lower : extOf(name);
362
+ const fromExt = ext ? BY_EXTENSION.get(ext) : void 0;
363
+ const mime = mimeType ? canonicalMimeBase(mimeType) : null;
364
+ if (mime) {
365
+ if (mime === "image/svg+xml") return fromExt ?? SVG_DETAILS;
366
+ if (mime.startsWith("image/")) return fromExt?.category === "IMAGE" ? fromExt : IMAGE_DETAILS;
367
+ if (mime.startsWith("video/")) return fromExt?.category === "VIDEO" ? fromExt : VIDEO_DETAILS;
368
+ if (mime.startsWith("audio/")) return fromExt?.category === "AUDIO" ? fromExt : AUDIO_DETAILS;
369
+ if (mime === "application/pdf") return PDF_DETAILS;
370
+ }
371
+ if (fromExt) return fromExt;
372
+ if (dotfileLooksLikeText(fileName)) return ASSUMED_TEXT_DETAILS;
373
+ return UNKNOWN_DETAILS;
374
+ }
375
+ function getFolderKindDetails(open = false) {
376
+ return open ? { ...FOLDER_DETAILS, icon: "folder-open" } : FOLDER_DETAILS;
377
+ }
378
+
379
+ // src/react/file-icon.tsx
380
+ import { jsx as jsx2 } from "react/jsx-runtime";
381
+ var ICONS = {
382
+ image: ImageIcon,
383
+ "pen-tool": PenToolIcon,
384
+ video: VideoIcon,
385
+ music: MusicIcon,
386
+ "file-type": FileTypeIcon,
387
+ "file-text": FileTextIcon,
388
+ code: CodeIcon,
389
+ braces: BracesIcon,
390
+ subtitles: SubtitlesIcon,
391
+ "file-code": FileCodeIcon,
392
+ "file-json": FileJsonIcon,
393
+ "file-spreadsheet": FileSpreadsheetIcon,
394
+ database: DatabaseIcon,
395
+ package: PackageBoxIcon,
396
+ archive: ArchiveIcon,
397
+ folder: FolderIcon,
398
+ "folder-open": FolderOpenIcon,
399
+ file: FileIcon,
400
+ "file-audio": FileAudioIcon,
401
+ "file-video": FileVideoIcon
402
+ };
403
+ function FileIcon2({
404
+ fileName,
405
+ mimeType = null,
406
+ isFolder,
407
+ open,
408
+ colorClass,
409
+ className,
410
+ size = 16
411
+ }) {
412
+ const details = isFolder ? getFolderKindDetails(open) : getFileKindDetails(fileName ?? "", mimeType);
413
+ const Icon = ICONS[details.icon];
414
+ const style = {
415
+ width: `${size}px`,
416
+ height: `${size}px`,
417
+ minWidth: `${size}px`
418
+ };
419
+ return /* @__PURE__ */ jsx2(
420
+ Icon,
421
+ {
422
+ style,
423
+ className: cn("shrink-0", colorClass ?? details.colorClass, className),
424
+ "aria-hidden": "true"
425
+ }
426
+ );
427
+ }
428
+
429
+ // src/react/inline-media-ref.tsx
430
+ import {
431
+ useCallback,
432
+ useMemo as useMemo2,
433
+ useRef as useRef2,
434
+ useState as useState3
435
+ } from "react";
436
+
437
+ // src/core/context.ts
438
+ import {
439
+ createContext,
440
+ createElement,
441
+ useContext
442
+ } from "react";
443
+ var CLIENT_SLOT = /* @__PURE__ */ Symbol.for("ai-matrx.media.client-context");
444
+ var PORTS_SLOT = /* @__PURE__ */ Symbol.for("ai-matrx.media.host-ports-context");
445
+ function clientContext() {
446
+ const host = globalThis;
447
+ host[CLIENT_SLOT] ??= createContext(null);
448
+ return host[CLIENT_SLOT];
449
+ }
450
+ var INERT_PORTS = {};
451
+ function portsContext() {
452
+ const host = globalThis;
453
+ host[PORTS_SLOT] ??= createContext(INERT_PORTS);
454
+ return host[PORTS_SLOT];
455
+ }
456
+ function useMediaClient() {
457
+ const client = useContext(clientContext());
458
+ if (!client) {
459
+ throw new Error(
460
+ "@ai-matrx/media: no MediaClient. Mount <MediaProvider client={...}> above every media surface (canonically wired to @ai-matrx/data/files)."
461
+ );
462
+ }
463
+ return client;
464
+ }
465
+ function useMediaHostPorts() {
466
+ return useContext(portsContext());
467
+ }
468
+
469
+ // src/core/use-media-blob.ts
470
+ import { useEffect, useState } from "react";
471
+
472
+ // src/core/ref-key.ts
473
+ function stableRefKey(ref) {
474
+ if (!ref) return "<none>";
475
+ if (typeof ref === "string") return `s:${ref}`;
476
+ if (ref.file_id) return `id:${ref.file_id}:${ref.mime_type ?? ""}`;
477
+ if (ref.url) return `url:${ref.url}:${ref.mime_type ?? ""}`;
478
+ return "<empty-ref>";
479
+ }
480
+
481
+ // src/core/use-media-blob.ts
482
+ function useMediaBlob(ref) {
483
+ const client = useMediaClient();
484
+ const refKey = stableRefKey(ref);
485
+ const [state, setState] = useState({ url: null, blob: null, loading: !!ref, error: null });
486
+ const [retryToken, setRetryToken] = useState(0);
487
+ useEffect(() => {
488
+ if (!ref) {
489
+ setState({ url: null, blob: null, loading: false, error: null });
490
+ return void 0;
491
+ }
492
+ let cancelled = false;
493
+ let release = null;
494
+ setState({ url: null, blob: null, loading: true, error: null });
495
+ client.getBlob(ref).then(
496
+ (handle) => {
497
+ if (cancelled) {
498
+ handle.release();
499
+ return;
500
+ }
501
+ release = handle.release;
502
+ setState({ url: handle.url, blob: handle.blob, loading: false, error: null });
503
+ },
504
+ (err) => {
505
+ if (cancelled) return;
506
+ const message = err instanceof Error ? err.message : String(err ?? "Failed to load file");
507
+ setState({ url: null, blob: null, loading: false, error: message });
508
+ }
509
+ );
510
+ return () => {
511
+ cancelled = true;
512
+ release?.();
513
+ };
514
+ }, [client, refKey, retryToken]);
515
+ return {
516
+ ...state,
517
+ retry: () => setRetryToken((t) => t + 1)
518
+ };
519
+ }
520
+
521
+ // src/core/use-media-load-recovery.ts
522
+ import { useEffect as useEffect2, useRef, useState as useState2 } from "react";
523
+
524
+ // src/types.ts
525
+ function mintDurableSrc(url) {
526
+ return url;
527
+ }
528
+
529
+ // src/core/use-media-load-recovery.ts
530
+ function useMediaLoadRecovery(src, options) {
531
+ const client = useMediaClient();
532
+ const recoverable = options?.recoverable !== false;
533
+ const onTerminal = options?.onTerminal;
534
+ const [result, setResult] = useState2({ source: src, retryKey: 0, failed: false });
535
+ const attemptRef = useRef(0);
536
+ useEffect2(() => {
537
+ attemptRef.current = 0;
538
+ }, [src]);
539
+ const onLoadError = (event) => {
540
+ if (!src || !recoverable) {
541
+ setResult({ source: src, retryKey: 0, failed: true });
542
+ onTerminal?.(event);
543
+ return;
544
+ }
545
+ attemptRef.current += 1;
546
+ const attempt = attemptRef.current;
547
+ client.recoverLoadError(mintDurableSrc(src), attempt).then(
548
+ (verdict) => {
549
+ if (verdict === "retry") {
550
+ setResult((current) => ({
551
+ source: src,
552
+ retryKey: current.source === src ? current.retryKey + 1 : 1,
553
+ failed: false
554
+ }));
555
+ } else {
556
+ setResult({ source: src, retryKey: 0, failed: true });
557
+ onTerminal?.(event);
558
+ }
559
+ },
560
+ () => {
561
+ setResult({ source: src, retryKey: 0, failed: true });
562
+ onTerminal?.(event);
563
+ }
564
+ );
565
+ };
566
+ return {
567
+ retryKey: result.source === src ? result.retryKey : 0,
568
+ onLoadError,
569
+ failed: result.source === src ? result.failed : false
570
+ };
571
+ }
572
+
573
+ // src/core/use-media-resolution.ts
574
+ import { useMemo } from "react";
575
+ function useMediaResolution(ref) {
576
+ const client = useMediaClient();
577
+ const refKey = stableRefKey(ref);
578
+ return useMemo(() => {
579
+ if (!ref) return { resolution: null, status: "empty", reason: null };
580
+ try {
581
+ const resolution = client.resolve(ref);
582
+ if (!resolution) return { resolution: null, status: "empty", reason: null };
583
+ return { resolution, status: "ready", reason: null };
584
+ } catch (err) {
585
+ return {
586
+ resolution: null,
587
+ status: "unavailable",
588
+ reason: client.classifyError(err)
589
+ };
590
+ }
591
+ }, [client, refKey]);
592
+ }
593
+
594
+ // src/react/inline-media-ref.tsx
595
+ import { Fragment, jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
596
+ var SIZE_PX = {
597
+ xs: 24,
598
+ sm: 32,
599
+ md: 64,
600
+ lg: 128,
601
+ xl: 256
602
+ };
603
+ var ROUNDED_CLASS = {
604
+ none: "",
605
+ sm: "rounded-sm",
606
+ md: "rounded-md",
607
+ lg: "rounded-lg",
608
+ full: "rounded-full"
609
+ };
610
+ function resolveDimensions(size) {
611
+ if (typeof size === "object") return size;
612
+ if (size === "fill") return "fill";
613
+ const px = SIZE_PX[size];
614
+ return { width: px, height: px };
615
+ }
616
+ function inferElementType(ref, resolutionKind, override) {
617
+ if (override) return override;
618
+ if (ref && typeof ref === "object" && ref.mime_type) {
619
+ if (ref.mime_type.startsWith("video/")) return "video";
620
+ if (ref.mime_type.startsWith("audio/")) return "audio";
621
+ }
622
+ if (resolutionKind === "video") return "video";
623
+ if (resolutionKind === "audio") return "audio";
624
+ return "img";
625
+ }
626
+ function prettifyUrl(url) {
627
+ try {
628
+ const u = new URL(url);
629
+ const tail = `${u.pathname}${u.search}`;
630
+ return { host: u.host, tail: tail === "/" ? "" : tail };
631
+ } catch {
632
+ return { host: null, tail: url };
633
+ }
634
+ }
635
+ var INERT_PLAYBACK = {
636
+ useMediaElementSink(forward) {
637
+ return useCallback(
638
+ (node) => {
639
+ if (!forward) return;
640
+ if (typeof forward === "function") forward(node);
641
+ else forward.current = node;
642
+ },
643
+ [forward]
644
+ );
645
+ },
646
+ usePlaybackSession() {
647
+ }
648
+ };
649
+ function FallbackVisual({
650
+ kind,
651
+ dimensions,
652
+ rounded,
653
+ border,
654
+ className,
655
+ icon
656
+ }) {
657
+ const isFill = dimensions === "fill";
658
+ const wrapperCls = cn(
659
+ "flex items-center justify-center bg-muted/60 text-muted-foreground",
660
+ ROUNDED_CLASS[rounded],
661
+ border === "subtle" && "border border-border",
662
+ kind === "skeleton" && "animate-pulse",
663
+ isFill && "w-full h-full",
664
+ className
665
+ );
666
+ return /* @__PURE__ */ jsx3(
667
+ "div",
668
+ {
669
+ className: wrapperCls,
670
+ style: isFill ? void 0 : { width: dimensions.width, height: dimensions.height },
671
+ "aria-hidden": kind === "skeleton",
672
+ children: kind === "icon" ? icon : null
673
+ }
674
+ );
675
+ }
676
+ function InformativeErrorFallback({
677
+ url,
678
+ alt,
679
+ elementType,
680
+ mediaRef,
681
+ dimensions,
682
+ rounded,
683
+ className
684
+ }) {
685
+ const shortAxis = dimensions === "fill" ? Number.POSITIVE_INFINITY : Math.min(dimensions.width, dimensions.height);
686
+ const isCompact = dimensions !== "fill" && shortAxis < 64;
687
+ const isMidsize = shortAxis < 140;
688
+ const fileId = mediaRef && typeof mediaRef === "object" && "file_id" in mediaRef ? mediaRef.file_id ?? null : null;
689
+ const FailIcon = elementType === "video" ? VideoOffIcon : elementType === "audio" ? VolumeXIcon : ImageOffIcon;
690
+ const tooltip = [
691
+ `Failed to load ${elementType}`,
692
+ alt && `alt: ${alt}`,
693
+ `url: ${url}`,
694
+ fileId && `file_id: ${fileId}`
695
+ ].filter(Boolean).join("\n");
696
+ if (isCompact) {
697
+ return /* @__PURE__ */ jsx3(
698
+ "div",
699
+ {
700
+ className: cn(
701
+ "flex items-center justify-center bg-destructive/5 text-destructive border border-destructive/40 border-dashed",
702
+ ROUNDED_CLASS[rounded],
703
+ className
704
+ ),
705
+ style: { width: dimensions.width, height: dimensions.height },
706
+ role: "img",
707
+ "aria-label": `Failed to load ${elementType}${alt ? `: ${alt}` : ""}`,
708
+ title: tooltip,
709
+ children: /* @__PURE__ */ jsx3(FailIcon, { className: "h-1/2 w-1/2 max-h-5 max-w-5" })
710
+ }
711
+ );
712
+ }
713
+ return /* @__PURE__ */ jsx3(
714
+ InformativeErrorPanel,
715
+ {
716
+ url,
717
+ alt,
718
+ elementType,
719
+ fileId,
720
+ dimensions,
721
+ rounded,
722
+ className,
723
+ compact: isMidsize,
724
+ icon: /* @__PURE__ */ jsx3(FailIcon, { className: "h-3.5 w-3.5 shrink-0" }),
725
+ tooltip
726
+ }
727
+ );
728
+ }
729
+ function InformativeErrorPanel({
730
+ url,
731
+ alt,
732
+ elementType,
733
+ fileId,
734
+ dimensions,
735
+ rounded,
736
+ className,
737
+ compact,
738
+ icon,
739
+ tooltip
740
+ }) {
741
+ const [copied, setCopied] = useState3(false);
742
+ const isFill = dimensions === "fill";
743
+ const { host, tail } = prettifyUrl(url);
744
+ const handleCopy = useCallback(
745
+ (event) => {
746
+ event.stopPropagation();
747
+ event.preventDefault();
748
+ navigator.clipboard?.writeText(url).then(() => {
749
+ setCopied(true);
750
+ setTimeout(() => setCopied(false), 1500);
751
+ }).catch(() => {
752
+ });
753
+ },
754
+ [url]
755
+ );
756
+ return /* @__PURE__ */ jsxs2(
757
+ "div",
758
+ {
759
+ className: cn(
760
+ "flex flex-col bg-destructive/5 text-foreground border border-destructive/40 border-dashed overflow-hidden",
761
+ ROUNDED_CLASS[rounded],
762
+ compact ? "p-1.5 gap-0.5" : "p-2 gap-1",
763
+ isFill ? "w-full h-full" : "",
764
+ className
765
+ ),
766
+ style: isFill ? void 0 : { width: dimensions.width, height: dimensions.height },
767
+ role: "img",
768
+ "aria-label": `Failed to load ${elementType}${alt ? `: ${alt}` : ""}`,
769
+ title: tooltip,
770
+ children: [
771
+ /* @__PURE__ */ jsxs2(
772
+ "div",
773
+ {
774
+ className: cn(
775
+ "flex items-center gap-1.5 text-destructive font-medium leading-tight",
776
+ compact ? "text-[10px]" : "text-xs"
777
+ ),
778
+ children: [
779
+ icon,
780
+ /* @__PURE__ */ jsx3("span", { className: "truncate", children: elementType === "img" ? "Image failed to load" : elementType === "video" ? "Video failed to load" : "Audio failed to load" })
781
+ ]
782
+ }
783
+ ),
784
+ alt && !compact && /* @__PURE__ */ jsx3(
785
+ "div",
786
+ {
787
+ className: "text-[11px] text-muted-foreground italic line-clamp-1",
788
+ title: alt,
789
+ children: alt
790
+ }
791
+ ),
792
+ /* @__PURE__ */ jsxs2(
793
+ "div",
794
+ {
795
+ className: cn(
796
+ "flex items-end gap-1 mt-auto min-w-0",
797
+ compact ? "text-[9px]" : "text-[10px]"
798
+ ),
799
+ children: [
800
+ /* @__PURE__ */ jsx3("div", { className: "font-mono text-muted-foreground truncate flex-1 min-w-0", children: host ? /* @__PURE__ */ jsxs2(Fragment, { children: [
801
+ /* @__PURE__ */ jsx3("span", { className: "text-foreground/80", children: host }),
802
+ tail && /* @__PURE__ */ jsx3("span", { className: "opacity-70", children: tail })
803
+ ] }) : /* @__PURE__ */ jsx3("span", { children: tail }) }),
804
+ /* @__PURE__ */ jsx3(
805
+ "button",
806
+ {
807
+ type: "button",
808
+ onClick: handleCopy,
809
+ className: cn(
810
+ "shrink-0 p-0.5 rounded text-muted-foreground hover:bg-destructive/10 hover:text-destructive transition-colors focus:outline-none focus:ring-1 focus:ring-destructive/40",
811
+ copied && "text-emerald-600 dark:text-emerald-500"
812
+ ),
813
+ "aria-label": copied ? "URL copied" : "Copy URL",
814
+ title: copied ? "URL copied" : "Copy URL",
815
+ children: copied ? /* @__PURE__ */ jsx3(CheckIcon, { className: "h-3 w-3", width: 12, height: 12 }) : /* @__PURE__ */ jsx3(CopyIcon, { className: "h-3 w-3", width: 12, height: 12 })
816
+ }
817
+ )
818
+ ]
819
+ }
820
+ ),
821
+ fileId && !compact && /* @__PURE__ */ jsx3("div", { className: "text-[9px] font-mono text-muted-foreground/70 truncate", children: fileId })
822
+ ]
823
+ }
824
+ );
825
+ }
826
+ function InlineMediaRef({
827
+ ref: mediaRef,
828
+ size = "md",
829
+ fit = "cover",
830
+ fallback = "icon",
831
+ fallbackIcon,
832
+ errorFallback = "info",
833
+ alt = "",
834
+ as,
835
+ controls = true,
836
+ autoPlay,
837
+ loop,
838
+ muted,
839
+ playsInline,
840
+ preload,
841
+ controlsList,
842
+ rounded = "md",
843
+ onClick,
844
+ onError,
845
+ onLoad,
846
+ mediaElementRef,
847
+ crossOrigin,
848
+ border = "none",
849
+ className
850
+ }) {
851
+ const ports = useMediaHostPorts();
852
+ const { resolution, status, reason } = useMediaResolution(mediaRef);
853
+ const elementType = inferElementType(mediaRef, resolution?.kind, as);
854
+ const needsBlob = Boolean(
855
+ resolution && (resolution.transport === "blob" || crossOrigin && resolution.isCdn !== true)
856
+ );
857
+ const blob = useMediaBlob(needsBlob ? mediaRef : null);
858
+ const url = needsBlob ? blob.url : resolution?.src ?? null;
859
+ const recovery = useMediaLoadRecovery(url, {
860
+ recoverable: !needsBlob && resolution?.recoverable !== false,
861
+ onTerminal: (event) => onError?.(
862
+ event
863
+ )
864
+ });
865
+ const playback = ports.playbackSession ?? INERT_PLAYBACK;
866
+ const sessionElRef = useRef2(null);
867
+ const [isMediaPlaying, setIsMediaPlaying] = useState3(false);
868
+ const portSinkRef = playback.useMediaElementSink(
869
+ mediaElementRef
870
+ );
871
+ const sinkRef = (node) => {
872
+ sessionElRef.current = node;
873
+ portSinkRef(node);
874
+ };
875
+ const trackKey = useMemo2(() => {
876
+ if (mediaRef && typeof mediaRef === "object" && mediaRef.file_id) {
877
+ return mediaRef.file_id;
878
+ }
879
+ return typeof mediaRef === "string" ? mediaRef : void 0;
880
+ }, [mediaRef]);
881
+ playback.usePlaybackSession(
882
+ {
883
+ isPlaying: isMediaPlaying,
884
+ source: "file-media",
885
+ label: alt || "Media file",
886
+ trackKey
887
+ },
888
+ sessionElRef
889
+ );
890
+ const mediaSessionEvents = {
891
+ onPlay: () => setIsMediaPlaying(true),
892
+ onPause: () => setIsMediaPlaying(false),
893
+ onEnded: () => setIsMediaPlaying(false)
894
+ };
895
+ const mediaResolutionError = status === "unavailable" ? reason ?? "unknown" : blob.error ?? null;
896
+ const dimensions = resolveDimensions(size);
897
+ const isFill = dimensions === "fill";
898
+ const hasLoadError = recovery.failed;
899
+ const handleLoadError = recovery.onLoadError;
900
+ const defaultIcon = elementType === "video" ? /* @__PURE__ */ jsx3(FileVideoIcon, { className: "h-1/2 w-1/2" }) : elementType === "audio" ? /* @__PURE__ */ jsx3(FileAudioIcon, { className: "h-1/2 w-1/2" }) : mediaRef ? /* @__PURE__ */ jsx3(ImageIcon, { className: "h-1/2 w-1/2" }) : /* @__PURE__ */ jsx3(FileIcon, { className: "h-1/2 w-1/2" });
901
+ const unresolvedDisplayUrl = mediaRef && typeof mediaRef === "object" && mediaRef.file_id ? `file:${mediaRef.file_id}` : "unresolved-media";
902
+ if (!url) {
903
+ if (mediaResolutionError) {
904
+ if (errorFallback === null) return null;
905
+ if (errorFallback === "info") {
906
+ return /* @__PURE__ */ jsx3(
907
+ InformativeErrorFallback,
908
+ {
909
+ url: unresolvedDisplayUrl,
910
+ alt,
911
+ elementType,
912
+ mediaRef,
913
+ dimensions,
914
+ rounded,
915
+ className
916
+ }
917
+ );
918
+ }
919
+ return /* @__PURE__ */ jsx3(
920
+ FallbackVisual,
921
+ {
922
+ kind: errorFallback,
923
+ dimensions,
924
+ rounded,
925
+ border,
926
+ className,
927
+ icon: fallbackIcon ?? defaultIcon
928
+ }
929
+ );
930
+ }
931
+ if (needsBlob && blob.loading) {
932
+ return /* @__PURE__ */ jsx3(
933
+ FallbackVisual,
934
+ {
935
+ kind: "skeleton",
936
+ dimensions,
937
+ rounded,
938
+ border,
939
+ className,
940
+ icon: null
941
+ }
942
+ );
943
+ }
944
+ if (!fallback) return null;
945
+ return /* @__PURE__ */ jsx3(
946
+ FallbackVisual,
947
+ {
948
+ kind: fallback,
949
+ dimensions,
950
+ rounded,
951
+ border,
952
+ className,
953
+ icon: fallbackIcon ?? defaultIcon
954
+ }
955
+ );
956
+ }
957
+ if (hasLoadError) {
958
+ if (errorFallback === null) return null;
959
+ if (errorFallback === "info") {
960
+ return /* @__PURE__ */ jsx3(
961
+ InformativeErrorFallback,
962
+ {
963
+ url,
964
+ alt,
965
+ elementType,
966
+ mediaRef,
967
+ dimensions,
968
+ rounded,
969
+ className
970
+ }
971
+ );
972
+ }
973
+ return /* @__PURE__ */ jsx3(
974
+ FallbackVisual,
975
+ {
976
+ kind: errorFallback,
977
+ dimensions,
978
+ rounded,
979
+ border,
980
+ className,
981
+ icon: fallbackIcon ?? defaultIcon
982
+ }
983
+ );
984
+ }
985
+ const interactiveProps = onClick ? {
986
+ onClick,
987
+ onKeyDown: (event) => {
988
+ if (event.key === "Enter" || event.key === " ") {
989
+ event.preventDefault();
990
+ onClick(event);
991
+ }
992
+ },
993
+ role: "button",
994
+ tabIndex: 0,
995
+ className: cn(
996
+ "cursor-pointer",
997
+ "focus:outline-none focus:ring-2 focus:ring-primary/50"
998
+ )
999
+ } : {};
1000
+ const baseCls = cn(
1001
+ "block",
1002
+ isFill && "w-full h-full",
1003
+ ROUNDED_CLASS[rounded],
1004
+ border === "subtle" && "border border-border",
1005
+ onClick && "cursor-pointer",
1006
+ interactiveProps.className,
1007
+ className
1008
+ );
1009
+ const objectFitClass = fit === "cover" ? "object-cover" : fit === "contain" ? "object-contain" : "object-fill";
1010
+ const sizeAttrs = isFill ? {} : { width: dimensions.width, height: dimensions.height };
1011
+ if (elementType === "video") {
1012
+ return /* @__PURE__ */ jsx3(
1013
+ "video",
1014
+ {
1015
+ ref: sinkRef,
1016
+ src: url,
1017
+ ...sizeAttrs,
1018
+ className: cn(baseCls, objectFitClass),
1019
+ controls,
1020
+ autoPlay,
1021
+ loop,
1022
+ muted,
1023
+ playsInline,
1024
+ preload,
1025
+ controlsList,
1026
+ onLoadedData: onLoad,
1027
+ onError: handleLoadError,
1028
+ crossOrigin,
1029
+ ...mediaSessionEvents,
1030
+ ...interactiveProps
1031
+ },
1032
+ recovery.retryKey
1033
+ );
1034
+ }
1035
+ if (elementType === "audio") {
1036
+ return /* @__PURE__ */ jsx3(
1037
+ "audio",
1038
+ {
1039
+ ref: sinkRef,
1040
+ src: url,
1041
+ className: cn(baseCls),
1042
+ controls,
1043
+ autoPlay,
1044
+ loop,
1045
+ muted,
1046
+ preload,
1047
+ ...mediaSessionEvents,
1048
+ onLoadedData: onLoad,
1049
+ onError: handleLoadError,
1050
+ crossOrigin,
1051
+ ...interactiveProps
1052
+ },
1053
+ recovery.retryKey
1054
+ );
1055
+ }
1056
+ const needsPlainImg = !!onLoad || !!mediaElementRef || !!crossOrigin;
1057
+ const isCdnUrl = resolution?.isCdn ?? (url.startsWith("https://cdn.") || url.includes("/cdn/"));
1058
+ const HostImage = ports.ImageComponent;
1059
+ if (HostImage && isCdnUrl && !isFill && !needsPlainImg && !needsBlob) {
1060
+ return /* @__PURE__ */ jsx3(
1061
+ HostImage,
1062
+ {
1063
+ src: url,
1064
+ alt,
1065
+ width: dimensions.width,
1066
+ height: dimensions.height,
1067
+ className: cn(baseCls, objectFitClass),
1068
+ onError: handleLoadError,
1069
+ ...interactiveProps
1070
+ },
1071
+ recovery.retryKey
1072
+ );
1073
+ }
1074
+ return /* @__PURE__ */ jsx3(
1075
+ "img",
1076
+ {
1077
+ ref: mediaElementRef,
1078
+ src: url,
1079
+ alt,
1080
+ ...sizeAttrs,
1081
+ className: cn(baseCls, objectFitClass),
1082
+ onLoad,
1083
+ onError: handleLoadError,
1084
+ crossOrigin,
1085
+ ...interactiveProps
1086
+ },
1087
+ recovery.retryKey
1088
+ );
1089
+ }
1090
+
1091
+ // src/react/media-thumbnail.tsx
1092
+ import { useEffect as useEffect3, useRef as useRef3 } from "react";
1093
+
1094
+ // src/core/use-thumbnail-source.ts
1095
+ import { useMemo as useMemo3 } from "react";
1096
+ function useThumbnailSource(ref, options = {}) {
1097
+ const { thumbnailUrl, allowSourceFallback = true } = options;
1098
+ const client = useMediaClient();
1099
+ const { resolution } = useMediaResolution(ref);
1100
+ const explicitThumb = useMemo3(() => {
1101
+ if (!thumbnailUrl) return null;
1102
+ try {
1103
+ return client.resolve(thumbnailUrl);
1104
+ } catch {
1105
+ return null;
1106
+ }
1107
+ }, [client, thumbnailUrl]);
1108
+ const needsBlob = allowSourceFallback && !explicitThumb && !resolution?.thumbnailSrc && resolution?.transport === "blob";
1109
+ const blob = useMediaBlob(needsBlob ? ref : null);
1110
+ if (explicitThumb) {
1111
+ return {
1112
+ src: explicitThumb.src,
1113
+ mode: "thumbnail",
1114
+ loading: false,
1115
+ resolution,
1116
+ recoverable: explicitThumb.recoverable !== false
1117
+ };
1118
+ }
1119
+ if (resolution?.thumbnailSrc) {
1120
+ return {
1121
+ src: resolution.thumbnailSrc,
1122
+ mode: "thumbnail",
1123
+ loading: false,
1124
+ resolution,
1125
+ recoverable: resolution.recoverable !== false
1126
+ };
1127
+ }
1128
+ if (allowSourceFallback && resolution) {
1129
+ if (needsBlob) {
1130
+ return {
1131
+ src: blob.url,
1132
+ mode: blob.url ? resolution.kind === "video" ? "live-video-poster" : "live-image" : "icon",
1133
+ loading: blob.loading,
1134
+ resolution,
1135
+ recoverable: false
1136
+ };
1137
+ }
1138
+ if (resolution.kind === "image") {
1139
+ return {
1140
+ src: resolution.src,
1141
+ mode: "live-image",
1142
+ loading: false,
1143
+ resolution,
1144
+ recoverable: resolution.recoverable !== false
1145
+ };
1146
+ }
1147
+ if (resolution.kind === "video") {
1148
+ return {
1149
+ src: resolution.src,
1150
+ mode: "live-video-poster",
1151
+ loading: false,
1152
+ resolution,
1153
+ recoverable: resolution.recoverable !== false
1154
+ };
1155
+ }
1156
+ }
1157
+ return {
1158
+ src: null,
1159
+ mode: "icon",
1160
+ loading: false,
1161
+ resolution,
1162
+ recoverable: false
1163
+ };
1164
+ }
1165
+
1166
+ // src/react/media-thumbnail.tsx
1167
+ import { Fragment as Fragment2, jsx as jsx4 } from "react/jsx-runtime";
1168
+ function MediaThumbnail({
1169
+ mediaRef,
1170
+ fileName,
1171
+ mimeType = null,
1172
+ thumbnailUrl,
1173
+ iconSize = 48,
1174
+ className,
1175
+ rounded,
1176
+ allowSourceFallback = true
1177
+ }) {
1178
+ const source = useThumbnailSource(mediaRef, {
1179
+ thumbnailUrl,
1180
+ allowSourceFallback
1181
+ });
1182
+ const fallback = /* @__PURE__ */ jsx4("div", { className: "flex h-full w-full items-center justify-center bg-muted/40", children: /* @__PURE__ */ jsx4(FileIcon2, { fileName, mimeType, size: iconSize }) });
1183
+ let body = source.loading ? /* @__PURE__ */ jsx4("div", { className: "h-full w-full animate-pulse bg-muted" }) : fallback;
1184
+ if (source.src) {
1185
+ if (source.mode === "live-video-poster") {
1186
+ body = /* @__PURE__ */ jsx4(
1187
+ VideoPosterThumb,
1188
+ {
1189
+ url: source.src,
1190
+ recoverable: source.recoverable,
1191
+ fallback
1192
+ }
1193
+ );
1194
+ } else {
1195
+ body = /* @__PURE__ */ jsx4(
1196
+ ImageThumb,
1197
+ {
1198
+ url: source.src,
1199
+ alt: fileName,
1200
+ recoverable: source.recoverable,
1201
+ fallback
1202
+ }
1203
+ );
1204
+ }
1205
+ }
1206
+ return /* @__PURE__ */ jsx4(
1207
+ "div",
1208
+ {
1209
+ className: cn("relative overflow-hidden bg-muted/40", rounded, className),
1210
+ children: body
1211
+ }
1212
+ );
1213
+ }
1214
+ function ImageThumb({
1215
+ url,
1216
+ alt,
1217
+ recoverable,
1218
+ fallback
1219
+ }) {
1220
+ const { retryKey, onLoadError, failed } = useMediaLoadRecovery(url, {
1221
+ recoverable
1222
+ });
1223
+ if (failed) return /* @__PURE__ */ jsx4(Fragment2, { children: fallback });
1224
+ return /* @__PURE__ */ jsx4(
1225
+ "img",
1226
+ {
1227
+ src: url,
1228
+ alt,
1229
+ loading: "lazy",
1230
+ className: "h-full w-full object-cover",
1231
+ onError: onLoadError
1232
+ },
1233
+ retryKey
1234
+ );
1235
+ }
1236
+ function VideoPosterThumb({
1237
+ url,
1238
+ recoverable,
1239
+ fallback
1240
+ }) {
1241
+ const { retryKey, onLoadError, failed } = useMediaLoadRecovery(url, {
1242
+ recoverable
1243
+ });
1244
+ const ref = useRef3(null);
1245
+ useEffect3(() => {
1246
+ const v = ref.current;
1247
+ if (!v) return void 0;
1248
+ const onMeta = () => {
1249
+ try {
1250
+ v.currentTime = 0;
1251
+ } catch {
1252
+ }
1253
+ };
1254
+ v.addEventListener("loadedmetadata", onMeta);
1255
+ return () => v.removeEventListener("loadedmetadata", onMeta);
1256
+ }, []);
1257
+ if (failed) return /* @__PURE__ */ jsx4(Fragment2, { children: fallback });
1258
+ return /* @__PURE__ */ jsx4(
1259
+ "video",
1260
+ {
1261
+ ref,
1262
+ src: url,
1263
+ className: "h-full w-full object-cover pointer-events-none",
1264
+ preload: "metadata",
1265
+ muted: true,
1266
+ playsInline: true,
1267
+ onError: onLoadError
1268
+ },
1269
+ retryKey
1270
+ );
1271
+ }
1272
+
1273
+ // src/react/use-media-dropzone.ts
1274
+ import {
1275
+ useCallback as useCallback2,
1276
+ useEffect as useEffect4,
1277
+ useMemo as useMemo4,
1278
+ useRef as useRef4,
1279
+ useState as useState4
1280
+ } from "react";
1281
+ function matchesAccept(file, accept) {
1282
+ if (!accept || accept.length === 0) return true;
1283
+ const name = file.name.toLowerCase();
1284
+ const mime = file.type.toLowerCase();
1285
+ return accept.some((pattern) => {
1286
+ const p = pattern.trim().toLowerCase();
1287
+ if (!p) return false;
1288
+ if (p.startsWith(".")) return name.endsWith(p);
1289
+ if (p.endsWith("/*")) return mime.startsWith(p.slice(0, -1));
1290
+ return mime === p;
1291
+ });
1292
+ }
1293
+ function useMediaDropzone(options) {
1294
+ const {
1295
+ onFiles,
1296
+ accept,
1297
+ maxSize,
1298
+ onRejected,
1299
+ enablePaste = true,
1300
+ pickerEventName,
1301
+ disabled = false,
1302
+ multiple = true
1303
+ } = options;
1304
+ const [isDragActive, setIsDragActive] = useState4(false);
1305
+ const [pasteHighlight, setPasteHighlight] = useState4(false);
1306
+ const dragDepth = useRef4(0);
1307
+ const inputRef = useRef4(null);
1308
+ const onFilesRef = useRef4(onFiles);
1309
+ onFilesRef.current = onFiles;
1310
+ const onRejectedRef = useRef4(onRejected);
1311
+ onRejectedRef.current = onRejected;
1312
+ const acceptKey = accept?.join(",") ?? "";
1313
+ const filterFiles = useCallback2(
1314
+ (files) => {
1315
+ const accepted = [];
1316
+ const rejected = [];
1317
+ for (const file of files) {
1318
+ if (!matchesAccept(file, acceptKey ? acceptKey.split(",") : void 0)) {
1319
+ rejected.push({ file, reason: "type" });
1320
+ } else if (maxSize != null && file.size > maxSize) {
1321
+ rejected.push({ file, reason: "size" });
1322
+ } else {
1323
+ accepted.push(file);
1324
+ }
1325
+ }
1326
+ if (rejected.length) onRejectedRef.current?.(rejected);
1327
+ return accepted;
1328
+ },
1329
+ [acceptKey, maxSize]
1330
+ );
1331
+ const emit = useCallback2(
1332
+ (files) => {
1333
+ const accepted = filterFiles(files);
1334
+ if (accepted.length) onFilesRef.current(accepted);
1335
+ },
1336
+ [filterFiles]
1337
+ );
1338
+ const openPicker = useCallback2(() => {
1339
+ if (!disabled) inputRef.current?.click();
1340
+ }, [disabled]);
1341
+ useEffect4(() => {
1342
+ if (!pickerEventName || typeof window === "undefined") return void 0;
1343
+ const handler = () => openPicker();
1344
+ window.addEventListener(pickerEventName, handler);
1345
+ return () => window.removeEventListener(pickerEventName, handler);
1346
+ }, [openPicker, pickerEventName]);
1347
+ useEffect4(() => {
1348
+ if (!enablePaste || disabled || typeof window === "undefined") {
1349
+ return void 0;
1350
+ }
1351
+ const handler = (event) => {
1352
+ if (!event.clipboardData?.items) return;
1353
+ const images = [];
1354
+ for (const item of Array.from(event.clipboardData.items)) {
1355
+ if (item.type.startsWith("image/")) {
1356
+ const blob = item.getAsFile();
1357
+ if (!blob) continue;
1358
+ const ext = blob.type.split("/")[1] ?? "png";
1359
+ const name = `pasted-${Date.now()}.${ext}`;
1360
+ images.push(new File([blob], name, { type: blob.type }));
1361
+ }
1362
+ }
1363
+ if (images.length > 0) {
1364
+ event.preventDefault();
1365
+ setPasteHighlight(true);
1366
+ setTimeout(() => setPasteHighlight(false), 400);
1367
+ emit(images);
1368
+ }
1369
+ };
1370
+ window.addEventListener("paste", handler);
1371
+ return () => window.removeEventListener("paste", handler);
1372
+ }, [enablePaste, disabled, emit]);
1373
+ const getRootProps = useCallback2(
1374
+ () => ({
1375
+ onDragEnter: (event) => {
1376
+ if (disabled) return;
1377
+ event.preventDefault();
1378
+ dragDepth.current += 1;
1379
+ setIsDragActive(true);
1380
+ },
1381
+ onDragOver: (event) => {
1382
+ if (disabled) return;
1383
+ event.preventDefault();
1384
+ },
1385
+ onDragLeave: (event) => {
1386
+ if (disabled) return;
1387
+ event.preventDefault();
1388
+ dragDepth.current = Math.max(0, dragDepth.current - 1);
1389
+ if (dragDepth.current === 0) setIsDragActive(false);
1390
+ },
1391
+ onDrop: (event) => {
1392
+ if (disabled) return;
1393
+ event.preventDefault();
1394
+ dragDepth.current = 0;
1395
+ setIsDragActive(false);
1396
+ const files = Array.from(event.dataTransfer?.files ?? []);
1397
+ if (files.length) emit(multiple ? files : files.slice(0, 1));
1398
+ }
1399
+ }),
1400
+ [disabled, emit, multiple]
1401
+ );
1402
+ const inputAccept = useMemo4(
1403
+ () => acceptKey.length ? acceptKey : void 0,
1404
+ [acceptKey]
1405
+ );
1406
+ const getInputProps = useCallback2(
1407
+ () => ({
1408
+ ref: (node) => {
1409
+ inputRef.current = node;
1410
+ },
1411
+ type: "file",
1412
+ multiple,
1413
+ accept: inputAccept,
1414
+ tabIndex: -1,
1415
+ style: { display: "none" },
1416
+ onChange: (event) => {
1417
+ const files = Array.from(event.target.files ?? []);
1418
+ event.target.value = "";
1419
+ if (files.length) emit(files);
1420
+ }
1421
+ }),
1422
+ [emit, inputAccept, multiple]
1423
+ );
1424
+ return { getRootProps, getInputProps, isDragActive, pasteHighlight, openPicker };
1425
+ }
1426
+
1427
+ // src/react/file-upload-dropzone.tsx
1428
+ import { useCallback as useCallback4 } from "react";
1429
+
1430
+ // src/core/use-media-upload.ts
1431
+ import { useCallback as useCallback3, useRef as useRef5, useState as useState5 } from "react";
1432
+ var entrySeq = 0;
1433
+ function useMediaUpload() {
1434
+ const client = useMediaClient();
1435
+ const [uploading, setUploading] = useState5(false);
1436
+ const [progress, setProgress] = useState5(null);
1437
+ const [result, setResult] = useState5(null);
1438
+ const [error, setError] = useState5(null);
1439
+ const [entries, setEntries] = useState5([]);
1440
+ const activeCount = useRef5(0);
1441
+ const patchEntry = useCallback3(
1442
+ (id, patch) => {
1443
+ setEntries(
1444
+ (current) => current.map((e) => e.id === id ? { ...e, ...patch } : e)
1445
+ );
1446
+ },
1447
+ []
1448
+ );
1449
+ const upload = useCallback3(
1450
+ async (file, opts = {}) => {
1451
+ const id = `up-${++entrySeq}`;
1452
+ const fileName = opts.fileName ?? (file instanceof File ? file.name : "file");
1453
+ setEntries((current) => [
1454
+ ...current,
1455
+ {
1456
+ id,
1457
+ fileName,
1458
+ fileSize: file.size,
1459
+ bytesUploaded: 0,
1460
+ status: "uploading",
1461
+ error: null,
1462
+ fileId: null,
1463
+ completedAt: null
1464
+ }
1465
+ ]);
1466
+ activeCount.current += 1;
1467
+ setUploading(true);
1468
+ setError(null);
1469
+ setProgress(null);
1470
+ try {
1471
+ const uploaded = await client.upload(file, {
1472
+ ...opts,
1473
+ onProgress: (loaded, total) => {
1474
+ setProgress({ loaded, total, ratio: total > 0 ? loaded / total : 0 });
1475
+ patchEntry(id, { bytesUploaded: loaded });
1476
+ opts.onProgress?.(loaded, total);
1477
+ }
1478
+ });
1479
+ setResult(uploaded);
1480
+ patchEntry(id, {
1481
+ status: "success",
1482
+ fileId: uploaded.fileId,
1483
+ bytesUploaded: file.size,
1484
+ completedAt: Date.now()
1485
+ });
1486
+ return uploaded;
1487
+ } catch (err) {
1488
+ const e = err instanceof Error ? err : new Error(String(err));
1489
+ setError(e);
1490
+ patchEntry(id, {
1491
+ status: "error",
1492
+ error: e.message,
1493
+ completedAt: Date.now()
1494
+ });
1495
+ throw e;
1496
+ } finally {
1497
+ activeCount.current -= 1;
1498
+ if (activeCount.current <= 0) setUploading(false);
1499
+ }
1500
+ },
1501
+ [client, patchEntry]
1502
+ );
1503
+ const uploadMany = useCallback3(
1504
+ async (files, opts = {}) => {
1505
+ if (client.uploadMany) {
1506
+ activeCount.current += 1;
1507
+ setUploading(true);
1508
+ try {
1509
+ return await client.uploadMany(files, opts);
1510
+ } finally {
1511
+ activeCount.current -= 1;
1512
+ if (activeCount.current <= 0) setUploading(false);
1513
+ }
1514
+ }
1515
+ const uploaded = [];
1516
+ const failed = [];
1517
+ for (const file of files) {
1518
+ try {
1519
+ const one = await upload(file, opts);
1520
+ uploaded.push(one.fileId);
1521
+ } catch (err) {
1522
+ failed.push({
1523
+ name: file.name,
1524
+ error: err instanceof Error ? err.message : String(err)
1525
+ });
1526
+ }
1527
+ }
1528
+ return { uploaded, failed, cancelled: false };
1529
+ },
1530
+ [client, upload]
1531
+ );
1532
+ const clearEntry = useCallback3((id) => {
1533
+ setEntries((current) => current.filter((e) => e.id !== id));
1534
+ }, []);
1535
+ const reset = useCallback3(() => {
1536
+ setResult(null);
1537
+ setError(null);
1538
+ setProgress(null);
1539
+ setEntries([]);
1540
+ }, []);
1541
+ return {
1542
+ upload,
1543
+ uploadMany,
1544
+ uploading,
1545
+ progress,
1546
+ result,
1547
+ error,
1548
+ entries,
1549
+ clearEntry,
1550
+ reset
1551
+ };
1552
+ }
1553
+
1554
+ // src/react/upload-progress-list.tsx
1555
+ import { memo, useEffect as useEffect5, useRef as useRef6, useState as useState6 } from "react";
1556
+ import { jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
1557
+ var AUTO_DISMISS_MS = 1e4;
1558
+ function formatFileSize(bytes) {
1559
+ if (!Number.isFinite(bytes) || bytes < 0) return "0 B";
1560
+ if (bytes < 1024) return `${bytes} B`;
1561
+ const units = ["KB", "MB", "GB", "TB"];
1562
+ let value = bytes;
1563
+ let unit = -1;
1564
+ do {
1565
+ value /= 1024;
1566
+ unit += 1;
1567
+ } while (value >= 1024 && unit < units.length - 1);
1568
+ return `${value >= 10 ? Math.round(value) : value.toFixed(1)} ${units[unit] ?? "TB"}`;
1569
+ }
1570
+ function UploadProgressListImpl({
1571
+ uploads,
1572
+ onDismiss,
1573
+ onOpenFile,
1574
+ className
1575
+ }) {
1576
+ const [hovered, setHovered] = useState6(false);
1577
+ const activeCount = uploads.filter((u) => u.status === "uploading").length;
1578
+ const successCount = uploads.filter((u) => u.status === "success").length;
1579
+ const errorCount = uploads.filter((u) => u.status === "error").length;
1580
+ const timersRef = useRef6(
1581
+ /* @__PURE__ */ new Map()
1582
+ );
1583
+ const onDismissRef = useRef6(onDismiss);
1584
+ onDismissRef.current = onDismiss;
1585
+ useEffect5(() => {
1586
+ const timers = timersRef.current;
1587
+ if (hovered) {
1588
+ timers.forEach((t) => clearTimeout(t));
1589
+ timers.clear();
1590
+ return;
1591
+ }
1592
+ for (const u of uploads) {
1593
+ if (u.status !== "success") continue;
1594
+ if (timers.has(u.id)) continue;
1595
+ const elapsed = u.completedAt ? Date.now() - u.completedAt : 0;
1596
+ const remaining = Math.max(0, AUTO_DISMISS_MS - elapsed);
1597
+ const handle = setTimeout(() => {
1598
+ timers.delete(u.id);
1599
+ onDismissRef.current(u.id);
1600
+ }, remaining);
1601
+ timers.set(u.id, handle);
1602
+ }
1603
+ const liveSuccessIds = new Set(
1604
+ uploads.filter((u) => u.status === "success").map((u) => u.id)
1605
+ );
1606
+ for (const [id, handle] of timers) {
1607
+ if (!liveSuccessIds.has(id)) {
1608
+ clearTimeout(handle);
1609
+ timers.delete(id);
1610
+ }
1611
+ }
1612
+ }, [uploads, hovered]);
1613
+ useEffect5(() => {
1614
+ const timers = timersRef.current;
1615
+ return () => {
1616
+ timers.forEach((t) => clearTimeout(t));
1617
+ timers.clear();
1618
+ };
1619
+ }, []);
1620
+ if (uploads.length === 0) return null;
1621
+ const headerLabel = activeCount > 0 ? `Uploading ${activeCount} file${activeCount === 1 ? "" : "s"}\u2026` : errorCount > 0 && successCount === 0 ? `${errorCount} upload${errorCount === 1 ? "" : "s"} failed` : `Uploaded ${successCount} file${successCount === 1 ? "" : "s"}`;
1622
+ const completedIds = uploads.filter((u) => u.status === "success" || u.status === "error").map((u) => u.id);
1623
+ return /* @__PURE__ */ jsxs3(
1624
+ "div",
1625
+ {
1626
+ className: cn(
1627
+ "overflow-hidden rounded-lg border bg-background/95 shadow-lg backdrop-blur",
1628
+ className
1629
+ ),
1630
+ onMouseEnter: () => setHovered(true),
1631
+ onMouseLeave: () => setHovered(false),
1632
+ "aria-label": "Uploads",
1633
+ children: [
1634
+ /* @__PURE__ */ jsxs3("div", { className: "flex items-center justify-between gap-2 border-b bg-muted/40 px-3 py-1.5", children: [
1635
+ /* @__PURE__ */ jsx5("span", { className: "truncate text-xs font-medium text-foreground", children: headerLabel }),
1636
+ completedIds.length > 0 ? /* @__PURE__ */ jsx5(
1637
+ "button",
1638
+ {
1639
+ type: "button",
1640
+ onClick: () => {
1641
+ for (const id of completedIds) onDismiss(id);
1642
+ },
1643
+ className: "shrink-0 rounded px-1.5 py-0.5 text-[11px] text-muted-foreground hover:bg-accent hover:text-foreground",
1644
+ children: "Clear"
1645
+ }
1646
+ ) : null
1647
+ ] }),
1648
+ /* @__PURE__ */ jsx5("ul", { className: "max-h-72 space-y-1 overflow-y-auto p-2", children: uploads.map((u) => {
1649
+ const percent = u.fileSize > 0 ? Math.min(100, Math.round(u.bytesUploaded / u.fileSize * 100)) : 0;
1650
+ const done = u.status === "success";
1651
+ const failed = u.status === "error";
1652
+ const canOpen = done && !!u.fileId && !!onOpenFile;
1653
+ return /* @__PURE__ */ jsxs3(
1654
+ "li",
1655
+ {
1656
+ className: cn(
1657
+ "flex items-center gap-2 rounded-md px-2 py-1.5 text-xs",
1658
+ canOpen && "cursor-pointer hover:bg-accent/60"
1659
+ ),
1660
+ onClick: canOpen ? () => onOpenFile(u.fileId) : void 0,
1661
+ children: [
1662
+ /* @__PURE__ */ jsx5(FileIcon2, { fileName: u.fileName, size: 18, className: "shrink-0" }),
1663
+ /* @__PURE__ */ jsxs3("div", { className: "min-w-0 flex-1", children: [
1664
+ /* @__PURE__ */ jsxs3("div", { className: "flex items-center justify-between gap-2", children: [
1665
+ /* @__PURE__ */ jsx5("span", { className: "truncate font-medium text-foreground", children: u.fileName }),
1666
+ /* @__PURE__ */ jsx5("span", { className: "shrink-0 tabular-nums text-muted-foreground", children: failed ? "Failed" : done ? "Done" : `${percent}%` })
1667
+ ] }),
1668
+ done ? null : /* @__PURE__ */ jsx5("div", { className: "mt-1 h-1 w-full rounded bg-muted", children: /* @__PURE__ */ jsx5(
1669
+ "div",
1670
+ {
1671
+ className: cn(
1672
+ "h-1 rounded transition-all",
1673
+ failed ? "bg-destructive" : "bg-primary"
1674
+ ),
1675
+ style: { width: failed ? "100%" : `${percent}%` }
1676
+ }
1677
+ ) }),
1678
+ failed && u.error ? /* @__PURE__ */ jsx5("p", { className: "mt-0.5 truncate text-[10px] text-destructive", children: u.error }) : !done ? /* @__PURE__ */ jsxs3("p", { className: "mt-0.5 text-[10px] text-muted-foreground", children: [
1679
+ formatFileSize(u.bytesUploaded),
1680
+ " /",
1681
+ " ",
1682
+ formatFileSize(u.fileSize)
1683
+ ] }) : null
1684
+ ] }),
1685
+ canOpen ? /* @__PURE__ */ jsxs3("span", { className: "flex shrink-0 items-center gap-1 rounded px-1.5 py-0.5 text-[11px] font-medium text-primary", children: [
1686
+ /* @__PURE__ */ jsx5(ExternalLinkIcon, { className: "h-3 w-3", width: 12, height: 12 }),
1687
+ "Open"
1688
+ ] }) : done ? /* @__PURE__ */ jsx5(
1689
+ CheckCircle2Icon,
1690
+ {
1691
+ className: "h-4 w-4 shrink-0 text-emerald-500",
1692
+ width: 16,
1693
+ height: 16
1694
+ }
1695
+ ) : failed ? /* @__PURE__ */ jsx5(
1696
+ AlertCircleIcon,
1697
+ {
1698
+ className: "h-4 w-4 shrink-0 text-destructive",
1699
+ width: 16,
1700
+ height: 16
1701
+ }
1702
+ ) : null,
1703
+ done || failed ? /* @__PURE__ */ jsx5(
1704
+ "button",
1705
+ {
1706
+ type: "button",
1707
+ onClick: (e) => {
1708
+ e.stopPropagation();
1709
+ onDismiss(u.id);
1710
+ },
1711
+ "aria-label": "Dismiss",
1712
+ className: "flex h-5 w-5 shrink-0 items-center justify-center rounded text-muted-foreground hover:bg-accent hover:text-foreground",
1713
+ children: /* @__PURE__ */ jsx5(XIcon, { className: "h-3 w-3", width: 12, height: 12 })
1714
+ }
1715
+ ) : null
1716
+ ]
1717
+ },
1718
+ u.id
1719
+ );
1720
+ }) })
1721
+ ]
1722
+ }
1723
+ );
1724
+ }
1725
+ var UploadProgressList = memo(UploadProgressListImpl);
1726
+
1727
+ // src/react/file-upload-dropzone.tsx
1728
+ import { jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
1729
+ function FileUploadDropzone({
1730
+ uploadOptions,
1731
+ accept,
1732
+ maxSize,
1733
+ enablePaste = true,
1734
+ mode = "overlay",
1735
+ children,
1736
+ className,
1737
+ actions,
1738
+ onUploadStart,
1739
+ onUploaded,
1740
+ onError,
1741
+ onOpenFile,
1742
+ pickerEventName
1743
+ }) {
1744
+ const { uploadMany, entries, clearEntry } = useMediaUpload();
1745
+ const handleUpload = useCallback4(
1746
+ async (files) => {
1747
+ if (!files.length) return;
1748
+ try {
1749
+ onUploadStart?.(files);
1750
+ const { uploaded, failed } = await uploadMany(files, uploadOptions);
1751
+ if (uploaded.length && onUploaded) onUploaded(uploaded);
1752
+ if (failed.length && onError) {
1753
+ const message = failed.map((f) => `${f.name}: ${f.error}`).join("; ");
1754
+ onError(message);
1755
+ }
1756
+ } catch (err) {
1757
+ onError?.(err instanceof Error ? err.message : String(err));
1758
+ }
1759
+ },
1760
+ [uploadMany, uploadOptions, onUploadStart, onUploaded, onError]
1761
+ );
1762
+ const {
1763
+ getRootProps,
1764
+ getInputProps,
1765
+ isDragActive,
1766
+ pasteHighlight,
1767
+ openPicker
1768
+ } = useMediaDropzone({
1769
+ onFiles: (files) => void handleUpload(files),
1770
+ accept,
1771
+ maxSize,
1772
+ enablePaste,
1773
+ pickerEventName
1774
+ });
1775
+ const highlighted = isDragActive || pasteHighlight;
1776
+ const renderedChildren = typeof children === "function" ? children({ openLocalPicker: openPicker, uploadFiles: handleUpload }) : children;
1777
+ if (mode === "inline") {
1778
+ return /* @__PURE__ */ jsxs4(
1779
+ "div",
1780
+ {
1781
+ ...getRootProps(),
1782
+ className: cn(
1783
+ "flex flex-col items-center justify-center gap-3 rounded-md border-2 border-dashed p-6",
1784
+ "text-sm text-muted-foreground",
1785
+ highlighted ? "border-primary bg-primary/5" : "border-border",
1786
+ className
1787
+ ),
1788
+ children: [
1789
+ /* @__PURE__ */ jsx6("input", { ...getInputProps() }),
1790
+ /* @__PURE__ */ jsx6(UploadIcon, { className: "h-8 w-8", width: 32, height: 32, "aria-hidden": "true" }),
1791
+ /* @__PURE__ */ jsxs4("div", { className: "text-center", children: [
1792
+ /* @__PURE__ */ jsx6("p", { children: "Drag & drop files here." }),
1793
+ enablePaste ? /* @__PURE__ */ jsx6("p", { className: "text-xs mt-1 opacity-75", children: "You can also paste an image with \u2318V." }) : null
1794
+ ] }),
1795
+ /* @__PURE__ */ jsx6(
1796
+ "button",
1797
+ {
1798
+ type: "button",
1799
+ onClick: openPicker,
1800
+ className: "rounded-md border px-3 py-1.5 text-xs font-medium text-foreground hover:bg-accent",
1801
+ children: "Browse files"
1802
+ }
1803
+ ),
1804
+ actions,
1805
+ entries.length > 0 ? /* @__PURE__ */ jsx6(
1806
+ UploadProgressList,
1807
+ {
1808
+ uploads: entries,
1809
+ onDismiss: clearEntry,
1810
+ onOpenFile,
1811
+ className: "w-full"
1812
+ }
1813
+ ) : null
1814
+ ]
1815
+ }
1816
+ );
1817
+ }
1818
+ return /* @__PURE__ */ jsxs4(
1819
+ "div",
1820
+ {
1821
+ ...getRootProps(),
1822
+ className: cn("relative h-full w-full", className),
1823
+ "data-drop-active": highlighted ? "true" : void 0,
1824
+ children: [
1825
+ /* @__PURE__ */ jsx6("input", { ...getInputProps() }),
1826
+ renderedChildren,
1827
+ highlighted ? /* @__PURE__ */ jsx6(
1828
+ "div",
1829
+ {
1830
+ className: "pointer-events-none absolute inset-0 z-10 flex items-center justify-center rounded-md border-2 border-dashed border-primary bg-primary/10",
1831
+ "aria-live": "polite",
1832
+ children: /* @__PURE__ */ jsxs4("div", { className: "flex flex-col items-center gap-2 text-primary", children: [
1833
+ /* @__PURE__ */ jsx6(UploadIcon, { className: "h-10 w-10", width: 40, height: 40, "aria-hidden": "true" }),
1834
+ /* @__PURE__ */ jsx6("span", { className: "font-medium", children: "Drop to upload" })
1835
+ ] })
1836
+ }
1837
+ ) : null,
1838
+ entries.length > 0 ? /* @__PURE__ */ jsx6("div", { className: "absolute bottom-3 right-3 z-20 w-80 max-w-[90%]", children: /* @__PURE__ */ jsx6(
1839
+ UploadProgressList,
1840
+ {
1841
+ uploads: entries,
1842
+ onDismiss: clearEntry,
1843
+ onOpenFile
1844
+ }
1845
+ ) }) : null
1846
+ ]
1847
+ }
1848
+ );
1849
+ }
1850
+
1851
+ // src/react/media-action-toolbar.tsx
1852
+ import { useState as useState8 } from "react";
1853
+
1854
+ // src/core/use-media-actions.ts
1855
+ import { useCallback as useCallback5, useMemo as useMemo5, useState as useState7 } from "react";
1856
+ function useMediaActions(ref, options = {}) {
1857
+ const ports = useMediaHostPorts();
1858
+ const { resolution } = useMediaResolution(ref);
1859
+ const [busy, setBusy] = useState7(null);
1860
+ const [lastError, setLastError] = useState7(null);
1861
+ const actions = ports.actions;
1862
+ const { fileName, alt } = options;
1863
+ const context = useMemo5(() => {
1864
+ if (!ref) return null;
1865
+ return { ref, resolution, fileName, alt };
1866
+ }, [ref, resolution, fileName, alt]);
1867
+ const isAvailable = useCallback5(
1868
+ (kind) => {
1869
+ if (!context || !actions) return false;
1870
+ if (kind === "share") return Boolean(actions.share || actions.SharePopover);
1871
+ return Boolean(actions[kind]);
1872
+ },
1873
+ [context, actions]
1874
+ );
1875
+ const run = useCallback5(
1876
+ async (kind) => {
1877
+ if (!context || !actions) return;
1878
+ const handler = actions[kind];
1879
+ if (!handler) return;
1880
+ setBusy(kind);
1881
+ setLastError(null);
1882
+ try {
1883
+ await handler(context);
1884
+ } catch (err) {
1885
+ setLastError({
1886
+ kind,
1887
+ message: err instanceof Error ? err.message : String(err)
1888
+ });
1889
+ } finally {
1890
+ setBusy(null);
1891
+ }
1892
+ },
1893
+ [context, actions]
1894
+ );
1895
+ return {
1896
+ context,
1897
+ isAvailable,
1898
+ run,
1899
+ busy,
1900
+ lastError,
1901
+ SharePopover: actions?.SharePopover ?? null
1902
+ };
1903
+ }
1904
+
1905
+ // src/react/media-action-toolbar.tsx
1906
+ import { jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
1907
+ var ACTION_META = {
1908
+ share: { label: "Share", Icon: Share2Icon },
1909
+ download: { label: "Download", Icon: DownloadIcon },
1910
+ copy: { label: "Copy", Icon: CopyIcon },
1911
+ open: { label: "Open", Icon: ExternalLinkIcon }
1912
+ };
1913
+ var DEFAULT_ORDER = ["share", "download", "copy", "open"];
1914
+ function MediaActionToolbar({
1915
+ mediaRef,
1916
+ fileName,
1917
+ alt,
1918
+ actions = DEFAULT_ORDER,
1919
+ hideUnavailable = false,
1920
+ className,
1921
+ buttonClassName
1922
+ }) {
1923
+ const state = useMediaActions(mediaRef, { fileName, alt });
1924
+ const [shareOpen, setShareOpen] = useState8(false);
1925
+ const SharePopover = state.SharePopover;
1926
+ const visible = hideUnavailable ? actions.filter((kind) => state.isAvailable(kind)) : actions;
1927
+ if (visible.length === 0) return null;
1928
+ return /* @__PURE__ */ jsxs5("div", { className: cn("relative inline-flex items-center gap-1", className), children: [
1929
+ visible.map((kind) => {
1930
+ const { label, Icon } = ACTION_META[kind];
1931
+ const available = state.isAvailable(kind);
1932
+ const busy = state.busy === kind;
1933
+ return /* @__PURE__ */ jsx7(
1934
+ "button",
1935
+ {
1936
+ type: "button",
1937
+ "aria-label": label,
1938
+ title: label,
1939
+ disabled: !available || busy,
1940
+ onClick: () => {
1941
+ if (kind === "share" && SharePopover) {
1942
+ setShareOpen((open) => !open);
1943
+ return;
1944
+ }
1945
+ void state.run(kind);
1946
+ },
1947
+ className: cn(
1948
+ "inline-flex h-8 w-8 items-center justify-center rounded-md text-muted-foreground transition-colors",
1949
+ available ? "hover:bg-accent hover:text-foreground" : "opacity-40 cursor-not-allowed",
1950
+ busy && "animate-pulse",
1951
+ buttonClassName
1952
+ ),
1953
+ children: /* @__PURE__ */ jsx7(Icon, { className: "h-4 w-4", width: 16, height: 16 })
1954
+ },
1955
+ kind
1956
+ );
1957
+ }),
1958
+ state.lastError ? /* @__PURE__ */ jsxs5(
1959
+ "span",
1960
+ {
1961
+ role: "status",
1962
+ className: "ml-1 max-w-48 truncate text-[11px] text-destructive",
1963
+ title: state.lastError.message,
1964
+ children: [
1965
+ ACTION_META[state.lastError.kind].label,
1966
+ " failed"
1967
+ ]
1968
+ }
1969
+ ) : null,
1970
+ shareOpen && SharePopover && state.context ? /* @__PURE__ */ jsx7("div", { className: "absolute right-0 top-full z-30 mt-1", children: /* @__PURE__ */ jsx7(
1971
+ SharePopover,
1972
+ {
1973
+ context: state.context,
1974
+ onClose: () => setShareOpen(false)
1975
+ }
1976
+ ) }) : null
1977
+ ] });
1978
+ }
1979
+
1980
+ // src/react/media-lightbox.tsx
1981
+ import { useEffect as useEffect6 } from "react";
1982
+ import { jsx as jsx8, jsxs as jsxs6 } from "react/jsx-runtime";
1983
+ function MediaLightbox({
1984
+ open,
1985
+ onClose,
1986
+ mediaRef,
1987
+ fileName,
1988
+ alt,
1989
+ as,
1990
+ actions,
1991
+ hideUnavailableActions = false,
1992
+ headerExtra,
1993
+ className
1994
+ }) {
1995
+ useEffect6(() => {
1996
+ if (!open || typeof window === "undefined") return void 0;
1997
+ const handler = (event) => {
1998
+ if (event.key === "Escape") {
1999
+ event.stopPropagation();
2000
+ onClose();
2001
+ }
2002
+ };
2003
+ window.addEventListener("keydown", handler);
2004
+ return () => window.removeEventListener("keydown", handler);
2005
+ }, [open, onClose]);
2006
+ if (!open) return null;
2007
+ return /* @__PURE__ */ jsxs6(
2008
+ "div",
2009
+ {
2010
+ role: "dialog",
2011
+ "aria-modal": "true",
2012
+ "aria-label": fileName ?? alt ?? "Media viewer",
2013
+ className: cn(
2014
+ "fixed inset-0 z-50 flex flex-col bg-black/80 backdrop-blur-sm",
2015
+ className
2016
+ ),
2017
+ onClick: onClose,
2018
+ children: [
2019
+ /* @__PURE__ */ jsxs6(
2020
+ "div",
2021
+ {
2022
+ className: "flex items-center justify-between gap-2 p-3",
2023
+ onClick: (event) => event.stopPropagation(),
2024
+ children: [
2025
+ /* @__PURE__ */ jsxs6("div", { className: "flex min-w-0 items-center gap-2", children: [
2026
+ /* @__PURE__ */ jsx8("span", { className: "truncate text-sm font-medium text-white/90", children: fileName ?? alt ?? "" }),
2027
+ headerExtra
2028
+ ] }),
2029
+ /* @__PURE__ */ jsxs6("div", { className: "flex items-center gap-1", children: [
2030
+ /* @__PURE__ */ jsx8(
2031
+ MediaActionToolbar,
2032
+ {
2033
+ mediaRef,
2034
+ fileName,
2035
+ alt,
2036
+ actions,
2037
+ hideUnavailable: hideUnavailableActions,
2038
+ buttonClassName: "text-white/80 hover:bg-white/10 hover:text-white"
2039
+ }
2040
+ ),
2041
+ /* @__PURE__ */ jsx8(
2042
+ "button",
2043
+ {
2044
+ type: "button",
2045
+ "aria-label": "Close",
2046
+ onClick: onClose,
2047
+ className: "inline-flex h-8 w-8 items-center justify-center rounded-md text-white/80 transition-colors hover:bg-white/10 hover:text-white",
2048
+ children: /* @__PURE__ */ jsx8(XIcon, { className: "h-4 w-4", width: 16, height: 16 })
2049
+ }
2050
+ )
2051
+ ] })
2052
+ ]
2053
+ }
2054
+ ),
2055
+ /* @__PURE__ */ jsx8(
2056
+ "div",
2057
+ {
2058
+ className: "flex min-h-0 flex-1 items-center justify-center p-4",
2059
+ onClick: (event) => event.stopPropagation(),
2060
+ children: /* @__PURE__ */ jsx8("div", { className: "h-full w-full", children: /* @__PURE__ */ jsx8(
2061
+ InlineMediaRef,
2062
+ {
2063
+ ref: mediaRef,
2064
+ size: "fill",
2065
+ fit: "contain",
2066
+ rounded: "none",
2067
+ alt: alt ?? fileName ?? "",
2068
+ as
2069
+ }
2070
+ ) })
2071
+ }
2072
+ )
2073
+ ]
2074
+ }
2075
+ );
2076
+ }
2077
+ export {
2078
+ AlertCircleIcon,
2079
+ ArchiveIcon,
2080
+ BracesIcon,
2081
+ CheckCircle2Icon,
2082
+ CheckIcon,
2083
+ CodeIcon,
2084
+ CopyIcon,
2085
+ DatabaseIcon,
2086
+ DownloadIcon,
2087
+ ExternalLinkIcon,
2088
+ FileAudioIcon,
2089
+ FileCodeIcon,
2090
+ FileIcon2 as FileIcon,
2091
+ FileJsonIcon,
2092
+ FileSpreadsheetIcon,
2093
+ FileTextIcon,
2094
+ FileTypeIcon,
2095
+ FileUploadDropzone,
2096
+ FileVideoIcon,
2097
+ FolderIcon,
2098
+ FolderOpenIcon,
2099
+ ImageIcon,
2100
+ ImageOffIcon,
2101
+ InlineMediaRef,
2102
+ MediaActionToolbar,
2103
+ MediaLightbox,
2104
+ MediaThumbnail,
2105
+ MusicIcon,
2106
+ PackageBoxIcon,
2107
+ PenToolIcon,
2108
+ Share2Icon,
2109
+ SubtitlesIcon,
2110
+ UploadIcon,
2111
+ UploadProgressList,
2112
+ VideoIcon,
2113
+ VideoOffIcon,
2114
+ VolumeXIcon,
2115
+ XIcon,
2116
+ cn,
2117
+ formatFileSize,
2118
+ useMediaDropzone
2119
+ };
2120
+ //# sourceMappingURL=react.js.map