@ai-matrx/media 0.4.5 → 0.5.1
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/CHANGELOG.md +36 -0
- package/dist/core.cjs +18 -6
- package/dist/core.cjs.map +1 -1
- package/dist/core.d.cts +4 -0
- package/dist/core.d.ts +4 -0
- package/dist/core.js +18 -6
- package/dist/core.js.map +1 -1
- package/dist/react.cjs +47 -27
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +1 -11
- package/dist/react.d.ts +1 -11
- package/dist/react.js +45 -25
- package/dist/react.js.map +1 -1
- package/dist/viewers.cjs +75 -266
- package/dist/viewers.cjs.map +1 -1
- package/dist/viewers.js +73 -264
- package/dist/viewers.js.map +1 -1
- package/package.json +3 -2
package/dist/viewers.cjs
CHANGED
|
@@ -47,7 +47,7 @@ __export(viewers_exports, {
|
|
|
47
47
|
module.exports = __toCommonJS(viewers_exports);
|
|
48
48
|
|
|
49
49
|
// src/viewers/media-file-viewer.tsx
|
|
50
|
-
var
|
|
50
|
+
var import_react11 = require("react");
|
|
51
51
|
|
|
52
52
|
// src/viewers/registry.ts
|
|
53
53
|
var VIEWER_SLOT = /* @__PURE__ */ Symbol.for("ai-matrx.media.viewer-registry");
|
|
@@ -161,13 +161,6 @@ function DownloadIcon(props) {
|
|
|
161
161
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "m7 10 5 5 5-5" })
|
|
162
162
|
] });
|
|
163
163
|
}
|
|
164
|
-
function ExternalLinkIcon(props) {
|
|
165
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", { ...svgProps(props), children: [
|
|
166
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M15 3h6v6" }),
|
|
167
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M10 14 21 3" }),
|
|
168
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6" })
|
|
169
|
-
] });
|
|
170
|
-
}
|
|
171
164
|
function FileIcon(props) {
|
|
172
165
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", { ...svgProps(props), children: [
|
|
173
166
|
/* @__PURE__ */ (0, import_jsx_runtime.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" }),
|
|
@@ -280,12 +273,6 @@ function VideoIcon(props) {
|
|
|
280
273
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("rect", { x: "2", y: "6", width: "14", height: "12", rx: "2" })
|
|
281
274
|
] });
|
|
282
275
|
}
|
|
283
|
-
function XIcon(props) {
|
|
284
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", { ...svgProps(props), children: [
|
|
285
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M18 6 6 18" }),
|
|
286
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "m6 6 12 12" })
|
|
287
|
-
] });
|
|
288
|
-
}
|
|
289
276
|
function AlertCircleIcon(props) {
|
|
290
277
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", { ...svgProps(props), children: [
|
|
291
278
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("circle", { cx: "12", cy: "12", r: "10" }),
|
|
@@ -293,12 +280,6 @@ function AlertCircleIcon(props) {
|
|
|
293
280
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("line", { x1: "12", x2: "12.01", y1: "16", y2: "16" })
|
|
294
281
|
] });
|
|
295
282
|
}
|
|
296
|
-
function CheckCircle2Icon(props) {
|
|
297
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", { ...svgProps(props), children: [
|
|
298
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M21.801 10A10 10 0 1 1 17 3.335" }),
|
|
299
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "m9 11 3 3L22 4" })
|
|
300
|
-
] });
|
|
301
|
-
}
|
|
302
283
|
function GlobeIcon(props) {
|
|
303
284
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", { ...svgProps(props), children: [
|
|
304
285
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("circle", { cx: "12", cy: "12", r: "10" }),
|
|
@@ -1013,181 +994,9 @@ function FileIcon2({
|
|
|
1013
994
|
);
|
|
1014
995
|
}
|
|
1015
996
|
|
|
1016
|
-
// src/react/upload-progress-list.tsx
|
|
1017
|
-
var import_react8 = require("react");
|
|
1018
|
-
var import_jsx_runtime5 = require("react/jsx-runtime");
|
|
1019
|
-
var AUTO_DISMISS_MS = 1e4;
|
|
1020
|
-
function formatFileSize(bytes) {
|
|
1021
|
-
if (bytes == null || !Number.isFinite(bytes) || bytes < 0) return "\u2014";
|
|
1022
|
-
if (bytes < 1024) return `${bytes} B`;
|
|
1023
|
-
const units = ["KB", "MB", "GB", "TB"];
|
|
1024
|
-
let value = bytes;
|
|
1025
|
-
let unit = -1;
|
|
1026
|
-
do {
|
|
1027
|
-
value /= 1024;
|
|
1028
|
-
unit += 1;
|
|
1029
|
-
} while (value >= 1024 && unit < units.length - 1);
|
|
1030
|
-
return `${value >= 10 ? Math.round(value) : value.toFixed(1)} ${units[unit] ?? "TB"}`;
|
|
1031
|
-
}
|
|
1032
|
-
function UploadProgressListImpl({
|
|
1033
|
-
uploads,
|
|
1034
|
-
onDismiss,
|
|
1035
|
-
onOpenFile,
|
|
1036
|
-
className
|
|
1037
|
-
}) {
|
|
1038
|
-
const [hovered, setHovered] = (0, import_react8.useState)(false);
|
|
1039
|
-
const activeCount = uploads.filter((u) => u.status === "uploading").length;
|
|
1040
|
-
const successCount = uploads.filter((u) => u.status === "success").length;
|
|
1041
|
-
const errorCount = uploads.filter((u) => u.status === "error").length;
|
|
1042
|
-
const timersRef = (0, import_react8.useRef)(
|
|
1043
|
-
/* @__PURE__ */ new Map()
|
|
1044
|
-
);
|
|
1045
|
-
const onDismissRef = (0, import_react8.useRef)(onDismiss);
|
|
1046
|
-
onDismissRef.current = onDismiss;
|
|
1047
|
-
(0, import_react8.useEffect)(() => {
|
|
1048
|
-
const timers = timersRef.current;
|
|
1049
|
-
if (hovered) {
|
|
1050
|
-
timers.forEach((t) => clearTimeout(t));
|
|
1051
|
-
timers.clear();
|
|
1052
|
-
return;
|
|
1053
|
-
}
|
|
1054
|
-
for (const u of uploads) {
|
|
1055
|
-
if (u.status !== "success") continue;
|
|
1056
|
-
if (timers.has(u.id)) continue;
|
|
1057
|
-
const elapsed = u.completedAt ? Date.now() - u.completedAt : 0;
|
|
1058
|
-
const remaining = Math.max(0, AUTO_DISMISS_MS - elapsed);
|
|
1059
|
-
const handle = setTimeout(() => {
|
|
1060
|
-
timers.delete(u.id);
|
|
1061
|
-
onDismissRef.current(u.id);
|
|
1062
|
-
}, remaining);
|
|
1063
|
-
timers.set(u.id, handle);
|
|
1064
|
-
}
|
|
1065
|
-
const liveSuccessIds = new Set(
|
|
1066
|
-
uploads.filter((u) => u.status === "success").map((u) => u.id)
|
|
1067
|
-
);
|
|
1068
|
-
for (const [id, handle] of timers) {
|
|
1069
|
-
if (!liveSuccessIds.has(id)) {
|
|
1070
|
-
clearTimeout(handle);
|
|
1071
|
-
timers.delete(id);
|
|
1072
|
-
}
|
|
1073
|
-
}
|
|
1074
|
-
}, [uploads, hovered]);
|
|
1075
|
-
(0, import_react8.useEffect)(() => {
|
|
1076
|
-
const timers = timersRef.current;
|
|
1077
|
-
return () => {
|
|
1078
|
-
timers.forEach((t) => clearTimeout(t));
|
|
1079
|
-
timers.clear();
|
|
1080
|
-
};
|
|
1081
|
-
}, []);
|
|
1082
|
-
if (uploads.length === 0) return null;
|
|
1083
|
-
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"}`;
|
|
1084
|
-
const completedIds = uploads.filter((u) => u.status === "success" || u.status === "error").map((u) => u.id);
|
|
1085
|
-
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
1086
|
-
"div",
|
|
1087
|
-
{
|
|
1088
|
-
className: cn(
|
|
1089
|
-
"overflow-hidden rounded-lg border bg-background/95 shadow-lg backdrop-blur",
|
|
1090
|
-
className
|
|
1091
|
-
),
|
|
1092
|
-
onMouseEnter: () => setHovered(true),
|
|
1093
|
-
onMouseLeave: () => setHovered(false),
|
|
1094
|
-
"aria-label": "Uploads",
|
|
1095
|
-
children: [
|
|
1096
|
-
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "flex items-center justify-between gap-2 border-b bg-muted/40 px-3 py-1.5", children: [
|
|
1097
|
-
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "truncate text-xs font-medium text-foreground", children: headerLabel }),
|
|
1098
|
-
completedIds.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1099
|
-
"button",
|
|
1100
|
-
{
|
|
1101
|
-
type: "button",
|
|
1102
|
-
onClick: () => {
|
|
1103
|
-
for (const id of completedIds) onDismiss(id);
|
|
1104
|
-
},
|
|
1105
|
-
className: "shrink-0 rounded px-1.5 py-0.5 text-[11px] text-muted-foreground hover:bg-accent hover:text-foreground",
|
|
1106
|
-
children: "Clear"
|
|
1107
|
-
}
|
|
1108
|
-
) : null
|
|
1109
|
-
] }),
|
|
1110
|
-
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("ul", { className: "max-h-72 space-y-1 overflow-y-auto p-2", children: uploads.map((u) => {
|
|
1111
|
-
const percent = u.fileSize > 0 ? Math.min(100, Math.round(u.bytesUploaded / u.fileSize * 100)) : 0;
|
|
1112
|
-
const done = u.status === "success";
|
|
1113
|
-
const failed = u.status === "error";
|
|
1114
|
-
const canOpen = done && !!u.fileId && !!onOpenFile;
|
|
1115
|
-
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
1116
|
-
"li",
|
|
1117
|
-
{
|
|
1118
|
-
className: cn(
|
|
1119
|
-
"flex items-center gap-2 rounded-md px-2 py-1.5 text-xs",
|
|
1120
|
-
canOpen && "cursor-pointer hover:bg-accent/60"
|
|
1121
|
-
),
|
|
1122
|
-
onClick: canOpen ? () => onOpenFile(u.fileId) : void 0,
|
|
1123
|
-
children: [
|
|
1124
|
-
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(FileIcon2, { fileName: u.fileName, size: 18, className: "shrink-0" }),
|
|
1125
|
-
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "min-w-0 flex-1", children: [
|
|
1126
|
-
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "flex items-center justify-between gap-2", children: [
|
|
1127
|
-
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "truncate font-medium text-foreground", children: u.fileName }),
|
|
1128
|
-
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "shrink-0 tabular-nums text-muted-foreground", children: failed ? "Failed" : done ? "Done" : `${percent}%` })
|
|
1129
|
-
] }),
|
|
1130
|
-
done ? null : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "mt-1 h-1 w-full rounded bg-muted", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1131
|
-
"div",
|
|
1132
|
-
{
|
|
1133
|
-
className: cn(
|
|
1134
|
-
"h-1 rounded transition-all",
|
|
1135
|
-
failed ? "bg-destructive" : "bg-primary"
|
|
1136
|
-
),
|
|
1137
|
-
style: { width: failed ? "100%" : `${percent}%` }
|
|
1138
|
-
}
|
|
1139
|
-
) }),
|
|
1140
|
-
failed && u.error ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "mt-0.5 truncate text-[10px] text-destructive", children: u.error }) : !done ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("p", { className: "mt-0.5 text-[10px] text-muted-foreground", children: [
|
|
1141
|
-
formatFileSize(u.bytesUploaded),
|
|
1142
|
-
" /",
|
|
1143
|
-
" ",
|
|
1144
|
-
formatFileSize(u.fileSize)
|
|
1145
|
-
] }) : null
|
|
1146
|
-
] }),
|
|
1147
|
-
canOpen ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { className: "flex shrink-0 items-center gap-1 rounded px-1.5 py-0.5 text-[11px] font-medium text-primary", children: [
|
|
1148
|
-
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(ExternalLinkIcon, { className: "h-3 w-3", width: 12, height: 12 }),
|
|
1149
|
-
"Open"
|
|
1150
|
-
] }) : done ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1151
|
-
CheckCircle2Icon,
|
|
1152
|
-
{
|
|
1153
|
-
className: "h-4 w-4 shrink-0 text-emerald-500",
|
|
1154
|
-
width: 16,
|
|
1155
|
-
height: 16
|
|
1156
|
-
}
|
|
1157
|
-
) : failed ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1158
|
-
AlertCircleIcon,
|
|
1159
|
-
{
|
|
1160
|
-
className: "h-4 w-4 shrink-0 text-destructive",
|
|
1161
|
-
width: 16,
|
|
1162
|
-
height: 16
|
|
1163
|
-
}
|
|
1164
|
-
) : null,
|
|
1165
|
-
done || failed ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1166
|
-
"button",
|
|
1167
|
-
{
|
|
1168
|
-
type: "button",
|
|
1169
|
-
onClick: (e) => {
|
|
1170
|
-
e.stopPropagation();
|
|
1171
|
-
onDismiss(u.id);
|
|
1172
|
-
},
|
|
1173
|
-
"aria-label": "Dismiss",
|
|
1174
|
-
className: "flex h-5 w-5 shrink-0 items-center justify-center rounded text-muted-foreground hover:bg-accent hover:text-foreground",
|
|
1175
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(XIcon, { className: "h-3 w-3", width: 12, height: 12 })
|
|
1176
|
-
}
|
|
1177
|
-
) : null
|
|
1178
|
-
]
|
|
1179
|
-
},
|
|
1180
|
-
u.id
|
|
1181
|
-
);
|
|
1182
|
-
}) })
|
|
1183
|
-
]
|
|
1184
|
-
}
|
|
1185
|
-
);
|
|
1186
|
-
}
|
|
1187
|
-
var UploadProgressList = (0, import_react8.memo)(UploadProgressListImpl);
|
|
1188
|
-
|
|
1189
997
|
// src/viewers/generic-viewer.tsx
|
|
1190
|
-
var
|
|
998
|
+
var import_format = require("@ai-matrx/kit/format");
|
|
999
|
+
var import_jsx_runtime5 = require("react/jsx-runtime");
|
|
1191
1000
|
function GenericViewer({
|
|
1192
1001
|
fileName,
|
|
1193
1002
|
fileSize,
|
|
@@ -1201,7 +1010,7 @@ function GenericViewer({
|
|
|
1201
1010
|
const viewAsTextBusy = generic?.viewAsTextBusy ?? false;
|
|
1202
1011
|
const hasViewAsText = typeof onViewAsText === "function";
|
|
1203
1012
|
const hasDownload = typeof onDownload === "function";
|
|
1204
|
-
return /* @__PURE__ */ (0,
|
|
1013
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
1205
1014
|
"div",
|
|
1206
1015
|
{
|
|
1207
1016
|
className: cn(
|
|
@@ -1209,14 +1018,14 @@ function GenericViewer({
|
|
|
1209
1018
|
className
|
|
1210
1019
|
),
|
|
1211
1020
|
children: [
|
|
1212
|
-
/* @__PURE__ */ (0,
|
|
1213
|
-
/* @__PURE__ */ (0,
|
|
1214
|
-
/* @__PURE__ */ (0,
|
|
1215
|
-
/* @__PURE__ */ (0,
|
|
1021
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(FileIcon2, { fileName, size: 48 }),
|
|
1022
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { children: [
|
|
1023
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "max-w-md truncate text-sm font-medium", children: fileName }),
|
|
1024
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "text-xs text-muted-foreground", children: (0, import_format.formatFileSize)(fileSize ?? null) })
|
|
1216
1025
|
] }),
|
|
1217
|
-
/* @__PURE__ */ (0,
|
|
1218
|
-
/* @__PURE__ */ (0,
|
|
1219
|
-
onViewAsText && viewAsTextPrimary ? /* @__PURE__ */ (0,
|
|
1026
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "max-w-sm text-sm text-muted-foreground", children: generic?.message ?? (hasViewAsText ? "No built-in previewer for this file type." : "This file type can't be previewed here.") }),
|
|
1027
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "flex flex-wrap items-center justify-center gap-2", children: [
|
|
1028
|
+
onViewAsText && viewAsTextPrimary ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1220
1029
|
ViewAsTextButton,
|
|
1221
1030
|
{
|
|
1222
1031
|
onClick: onViewAsText,
|
|
@@ -1225,7 +1034,7 @@ function GenericViewer({
|
|
|
1225
1034
|
variant: "primary"
|
|
1226
1035
|
}
|
|
1227
1036
|
) : null,
|
|
1228
|
-
onDownload ? /* @__PURE__ */ (0,
|
|
1037
|
+
onDownload ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
1229
1038
|
"button",
|
|
1230
1039
|
{
|
|
1231
1040
|
type: "button",
|
|
@@ -1235,12 +1044,12 @@ function GenericViewer({
|
|
|
1235
1044
|
hasViewAsText && viewAsTextPrimary ? "border border-input bg-background text-foreground hover:bg-accent hover:text-accent-foreground" : "bg-primary text-primary-foreground hover:bg-primary/90"
|
|
1236
1045
|
),
|
|
1237
1046
|
children: [
|
|
1238
|
-
/* @__PURE__ */ (0,
|
|
1047
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(DownloadIcon, { className: "h-4 w-4" }),
|
|
1239
1048
|
"Download"
|
|
1240
1049
|
]
|
|
1241
1050
|
}
|
|
1242
1051
|
) : null,
|
|
1243
|
-
onViewAsText && !viewAsTextPrimary ? /* @__PURE__ */ (0,
|
|
1052
|
+
onViewAsText && !viewAsTextPrimary ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1244
1053
|
ViewAsTextButton,
|
|
1245
1054
|
{
|
|
1246
1055
|
onClick: onViewAsText,
|
|
@@ -1250,7 +1059,7 @@ function GenericViewer({
|
|
|
1250
1059
|
}
|
|
1251
1060
|
) : null
|
|
1252
1061
|
] }),
|
|
1253
|
-
!hasDownload && !hasViewAsText ? /* @__PURE__ */ (0,
|
|
1062
|
+
!hasDownload && !hasViewAsText ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "max-w-sm text-[11px] text-muted-foreground/70", children: "Download it from the file's actions menu to open it in another application." }) : null
|
|
1254
1063
|
]
|
|
1255
1064
|
}
|
|
1256
1065
|
);
|
|
@@ -1261,7 +1070,7 @@ function ViewAsTextButton({
|
|
|
1261
1070
|
busy,
|
|
1262
1071
|
variant
|
|
1263
1072
|
}) {
|
|
1264
|
-
return /* @__PURE__ */ (0,
|
|
1073
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
1265
1074
|
"button",
|
|
1266
1075
|
{
|
|
1267
1076
|
type: "button",
|
|
@@ -1273,7 +1082,7 @@ function ViewAsTextButton({
|
|
|
1273
1082
|
variant === "primary" ? "bg-primary text-primary-foreground hover:bg-primary/90" : "border border-input bg-background text-foreground hover:bg-accent hover:text-accent-foreground"
|
|
1274
1083
|
),
|
|
1275
1084
|
children: [
|
|
1276
|
-
busy ? /* @__PURE__ */ (0,
|
|
1085
|
+
busy ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(SpinnerIcon, { className: "h-4 w-4 animate-spin" }) : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(FileTextIcon, { className: "h-4 w-4" }),
|
|
1277
1086
|
label
|
|
1278
1087
|
]
|
|
1279
1088
|
}
|
|
@@ -1281,13 +1090,13 @@ function ViewAsTextButton({
|
|
|
1281
1090
|
}
|
|
1282
1091
|
|
|
1283
1092
|
// src/viewers/html-viewer.tsx
|
|
1284
|
-
var
|
|
1093
|
+
var import_react9 = require("react");
|
|
1285
1094
|
|
|
1286
1095
|
// src/viewers/markup-chrome.tsx
|
|
1287
|
-
var
|
|
1288
|
-
var
|
|
1096
|
+
var import_react8 = require("react");
|
|
1097
|
+
var import_jsx_runtime6 = require("react/jsx-runtime");
|
|
1289
1098
|
function useMarkupMode(controls) {
|
|
1290
|
-
const [localMode, setLocalMode] = (0,
|
|
1099
|
+
const [localMode, setLocalMode] = (0, import_react8.useState)("rendered");
|
|
1291
1100
|
const controlled = controls?.mode !== void 0;
|
|
1292
1101
|
return {
|
|
1293
1102
|
mode: controls?.mode ?? localMode,
|
|
@@ -1302,23 +1111,23 @@ function MarkupModeToggle({
|
|
|
1302
1111
|
renderedIcon = "image",
|
|
1303
1112
|
className
|
|
1304
1113
|
}) {
|
|
1305
|
-
return /* @__PURE__ */ (0,
|
|
1306
|
-
/* @__PURE__ */ (0,
|
|
1114
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: cn("flex items-center gap-0.5", className), children: [
|
|
1115
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1307
1116
|
ToggleButton,
|
|
1308
1117
|
{
|
|
1309
1118
|
active: mode === "rendered",
|
|
1310
1119
|
onClick: () => onChange("rendered"),
|
|
1311
1120
|
label: renderedLabel,
|
|
1312
|
-
icon: renderedIcon === "globe" ? /* @__PURE__ */ (0,
|
|
1121
|
+
icon: renderedIcon === "globe" ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(GlobeIcon, { className: "h-3.5 w-3.5" }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(ImageIcon, { className: "h-3.5 w-3.5" })
|
|
1313
1122
|
}
|
|
1314
1123
|
),
|
|
1315
|
-
/* @__PURE__ */ (0,
|
|
1124
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1316
1125
|
ToggleButton,
|
|
1317
1126
|
{
|
|
1318
1127
|
active: mode === "source",
|
|
1319
1128
|
onClick: () => onChange("source"),
|
|
1320
1129
|
label: "Source",
|
|
1321
|
-
icon: /* @__PURE__ */ (0,
|
|
1130
|
+
icon: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(CodeIcon, { className: "h-3.5 w-3.5" })
|
|
1322
1131
|
}
|
|
1323
1132
|
)
|
|
1324
1133
|
] });
|
|
@@ -1329,7 +1138,7 @@ function ToggleButton({
|
|
|
1329
1138
|
icon,
|
|
1330
1139
|
label
|
|
1331
1140
|
}) {
|
|
1332
|
-
return /* @__PURE__ */ (0,
|
|
1141
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
|
|
1333
1142
|
"button",
|
|
1334
1143
|
{
|
|
1335
1144
|
type: "button",
|
|
@@ -1341,14 +1150,14 @@ function ToggleButton({
|
|
|
1341
1150
|
),
|
|
1342
1151
|
children: [
|
|
1343
1152
|
icon,
|
|
1344
|
-
/* @__PURE__ */ (0,
|
|
1153
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: label })
|
|
1345
1154
|
]
|
|
1346
1155
|
}
|
|
1347
1156
|
);
|
|
1348
1157
|
}
|
|
1349
1158
|
|
|
1350
1159
|
// src/viewers/html-viewer.tsx
|
|
1351
|
-
var
|
|
1160
|
+
var import_jsx_runtime7 = require("react/jsx-runtime");
|
|
1352
1161
|
var VIEWPORT_WIDTH = {
|
|
1353
1162
|
mobile: 390,
|
|
1354
1163
|
tablet: 768,
|
|
@@ -1357,10 +1166,10 @@ var VIEWPORT_WIDTH = {
|
|
|
1357
1166
|
function HtmlViewer(props) {
|
|
1358
1167
|
const { className, fileName, markupControls } = props;
|
|
1359
1168
|
const { mode, setMode, controlled } = useMarkupMode(markupControls);
|
|
1360
|
-
return /* @__PURE__ */ (0,
|
|
1361
|
-
controlled ? null : /* @__PURE__ */ (0,
|
|
1362
|
-
/* @__PURE__ */ (0,
|
|
1363
|
-
/* @__PURE__ */ (0,
|
|
1169
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: cn("flex h-full w-full flex-col", className), children: [
|
|
1170
|
+
controlled ? null : /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex shrink-0 items-center justify-between gap-2 border-b border-border/60 bg-background px-3 py-1.5 text-xs", children: [
|
|
1171
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "truncate font-medium text-foreground", children: fileName }),
|
|
1172
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1364
1173
|
MarkupModeToggle,
|
|
1365
1174
|
{
|
|
1366
1175
|
mode,
|
|
@@ -1370,19 +1179,19 @@ function HtmlViewer(props) {
|
|
|
1370
1179
|
}
|
|
1371
1180
|
)
|
|
1372
1181
|
] }),
|
|
1373
|
-
/* @__PURE__ */ (0,
|
|
1182
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "relative min-h-0 flex-1", children: mode === "rendered" ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(HtmlRenderedView, { ...props }) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(HtmlSourceView, { ...props }) })
|
|
1374
1183
|
] });
|
|
1375
1184
|
}
|
|
1376
1185
|
function HtmlRenderedView({ source, fileName, markupControls }) {
|
|
1377
1186
|
const { url, unavailable } = useViewerDisplayUrl(source);
|
|
1378
1187
|
const viewport = markupControls?.viewport ?? "auto";
|
|
1379
1188
|
const reloadKey = markupControls?.reloadKey ?? 0;
|
|
1380
|
-
const [errored, setErrored] = (0,
|
|
1381
|
-
(0,
|
|
1189
|
+
const [errored, setErrored] = (0, import_react9.useState)(false);
|
|
1190
|
+
(0, import_react9.useEffect)(() => {
|
|
1382
1191
|
setErrored(false);
|
|
1383
1192
|
}, [reloadKey, url]);
|
|
1384
1193
|
if (unavailable) {
|
|
1385
|
-
return /* @__PURE__ */ (0,
|
|
1194
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1386
1195
|
ViewerError,
|
|
1387
1196
|
{
|
|
1388
1197
|
title: "This page isn't available",
|
|
@@ -1390,18 +1199,18 @@ function HtmlRenderedView({ source, fileName, markupControls }) {
|
|
|
1390
1199
|
}
|
|
1391
1200
|
);
|
|
1392
1201
|
}
|
|
1393
|
-
if (!url) return /* @__PURE__ */ (0,
|
|
1394
|
-
if (errored) return /* @__PURE__ */ (0,
|
|
1202
|
+
if (!url) return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ViewerSkeleton, {});
|
|
1203
|
+
if (errored) return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ViewerError, { title: "Preview unavailable" });
|
|
1395
1204
|
const constrained = viewport !== "auto";
|
|
1396
1205
|
const width = constrained ? VIEWPORT_WIDTH[viewport] : void 0;
|
|
1397
|
-
return /* @__PURE__ */ (0,
|
|
1206
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1398
1207
|
"div",
|
|
1399
1208
|
{
|
|
1400
1209
|
className: cn(
|
|
1401
1210
|
"h-full w-full overflow-auto bg-muted/10",
|
|
1402
1211
|
constrained && "flex items-start justify-center"
|
|
1403
1212
|
),
|
|
1404
|
-
children: /* @__PURE__ */ (0,
|
|
1213
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1405
1214
|
"div",
|
|
1406
1215
|
{
|
|
1407
1216
|
className: cn(
|
|
@@ -1409,7 +1218,7 @@ function HtmlRenderedView({ source, fileName, markupControls }) {
|
|
|
1409
1218
|
constrained ? "my-4 overflow-hidden rounded-md border border-border/60 shadow-lg" : "w-full"
|
|
1410
1219
|
),
|
|
1411
1220
|
style: constrained ? { width } : void 0,
|
|
1412
|
-
children: /* @__PURE__ */ (0,
|
|
1221
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1413
1222
|
"iframe",
|
|
1414
1223
|
{
|
|
1415
1224
|
src: url,
|
|
@@ -1428,13 +1237,13 @@ function HtmlRenderedView({ source, fileName, markupControls }) {
|
|
|
1428
1237
|
}
|
|
1429
1238
|
function HtmlSourceView({ source, maxBytes = 1024 * 1024 }) {
|
|
1430
1239
|
const { text, error, loading } = useViewerText(source, maxBytes);
|
|
1431
|
-
if (error) return /* @__PURE__ */ (0,
|
|
1432
|
-
if (loading || text === null) return /* @__PURE__ */ (0,
|
|
1433
|
-
return /* @__PURE__ */ (0,
|
|
1240
|
+
if (error) return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ViewerError, { title: "Couldn't load source", message: error });
|
|
1241
|
+
if (loading || text === null) return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ViewerSkeleton, {});
|
|
1242
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("pre", { className: "h-full w-full overflow-auto bg-muted/10 p-4 font-mono text-xs leading-relaxed break-all whitespace-pre-wrap", children: text });
|
|
1434
1243
|
}
|
|
1435
1244
|
|
|
1436
1245
|
// src/viewers/svg-viewer.tsx
|
|
1437
|
-
var
|
|
1246
|
+
var import_react10 = require("react");
|
|
1438
1247
|
|
|
1439
1248
|
// src/viewers/transparency-grid.ts
|
|
1440
1249
|
var TRANSPARENCY_GRID_STYLE = {
|
|
@@ -1444,11 +1253,11 @@ var TRANSPARENCY_GRID_STYLE = {
|
|
|
1444
1253
|
};
|
|
1445
1254
|
|
|
1446
1255
|
// src/viewers/svg-viewer.tsx
|
|
1447
|
-
var
|
|
1256
|
+
var import_jsx_runtime8 = require("react/jsx-runtime");
|
|
1448
1257
|
function SvgViewer(props) {
|
|
1449
1258
|
const { className, markupControls } = props;
|
|
1450
1259
|
const { mode, setMode, controlled } = useMarkupMode(markupControls);
|
|
1451
|
-
return /* @__PURE__ */ (0,
|
|
1260
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
1452
1261
|
"div",
|
|
1453
1262
|
{
|
|
1454
1263
|
className: cn(
|
|
@@ -1456,7 +1265,7 @@ function SvgViewer(props) {
|
|
|
1456
1265
|
className
|
|
1457
1266
|
),
|
|
1458
1267
|
children: [
|
|
1459
|
-
controlled ? null : /* @__PURE__ */ (0,
|
|
1268
|
+
controlled ? null : /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
1460
1269
|
MarkupModeToggle,
|
|
1461
1270
|
{
|
|
1462
1271
|
mode,
|
|
@@ -1464,15 +1273,15 @@ function SvgViewer(props) {
|
|
|
1464
1273
|
className: "absolute top-3 right-3 z-10 rounded-md border border-border bg-background/95 p-0.5 shadow-sm backdrop-blur-sm"
|
|
1465
1274
|
}
|
|
1466
1275
|
),
|
|
1467
|
-
mode === "rendered" ? /* @__PURE__ */ (0,
|
|
1276
|
+
mode === "rendered" ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(SvgRenderedView, { ...props }) : /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(SvgSourceView, { ...props })
|
|
1468
1277
|
]
|
|
1469
1278
|
}
|
|
1470
1279
|
);
|
|
1471
1280
|
}
|
|
1472
1281
|
function SvgRenderedView({ source, fileName }) {
|
|
1473
1282
|
const fromClient = useMediaBlob(source.kind === "ref" ? source.ref : null);
|
|
1474
|
-
const [normalizedUrl, setNormalizedUrl] = (0,
|
|
1475
|
-
(0,
|
|
1283
|
+
const [normalizedUrl, setNormalizedUrl] = (0, import_react10.useState)(null);
|
|
1284
|
+
(0, import_react10.useEffect)(() => {
|
|
1476
1285
|
const blob = fromClient.blob;
|
|
1477
1286
|
if (!blob || blob.type === "image/svg+xml") {
|
|
1478
1287
|
setNormalizedUrl(null);
|
|
@@ -1487,7 +1296,7 @@ function SvgRenderedView({ source, fileName }) {
|
|
|
1487
1296
|
const loading = source.kind === "ref" && fromClient.loading;
|
|
1488
1297
|
const error = source.kind === "ref" ? fromClient.error : null;
|
|
1489
1298
|
if (error) {
|
|
1490
|
-
return /* @__PURE__ */ (0,
|
|
1299
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
1491
1300
|
ViewerError,
|
|
1492
1301
|
{
|
|
1493
1302
|
title: "SVG could not be rendered",
|
|
@@ -1496,13 +1305,13 @@ function SvgRenderedView({ source, fileName }) {
|
|
|
1496
1305
|
}
|
|
1497
1306
|
);
|
|
1498
1307
|
}
|
|
1499
|
-
if (loading || !url) return /* @__PURE__ */ (0,
|
|
1500
|
-
return /* @__PURE__ */ (0,
|
|
1308
|
+
if (loading || !url) return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(ViewerSkeleton, { className: "flex-1" });
|
|
1309
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
1501
1310
|
"div",
|
|
1502
1311
|
{
|
|
1503
1312
|
className: "flex flex-1 items-center justify-center overflow-auto p-4",
|
|
1504
1313
|
style: TRANSPARENCY_GRID_STYLE,
|
|
1505
|
-
children: /* @__PURE__ */ (0,
|
|
1314
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
1506
1315
|
"img",
|
|
1507
1316
|
{
|
|
1508
1317
|
src: url,
|
|
@@ -1515,40 +1324,40 @@ function SvgRenderedView({ source, fileName }) {
|
|
|
1515
1324
|
}
|
|
1516
1325
|
function SvgSourceView({ source, maxBytes = 1024 * 1024 }) {
|
|
1517
1326
|
const { text, error, loading } = useViewerText(source, maxBytes);
|
|
1518
|
-
if (error) return /* @__PURE__ */ (0,
|
|
1519
|
-
if (loading || text === null) return /* @__PURE__ */ (0,
|
|
1520
|
-
return /* @__PURE__ */ (0,
|
|
1327
|
+
if (error) return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(ViewerError, { title: "Could not load source", message: error });
|
|
1328
|
+
if (loading || text === null) return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(ViewerSkeleton, { className: "flex-1" });
|
|
1329
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("pre", { className: "m-0 flex-1 overflow-auto bg-muted/20 px-4 py-3 font-mono text-xs leading-relaxed break-words whitespace-pre-wrap text-foreground", children: text });
|
|
1521
1330
|
}
|
|
1522
1331
|
|
|
1523
1332
|
// src/viewers/text-viewer.tsx
|
|
1524
|
-
var
|
|
1333
|
+
var import_jsx_runtime9 = require("react/jsx-runtime");
|
|
1525
1334
|
function TextViewer({
|
|
1526
1335
|
source,
|
|
1527
1336
|
className,
|
|
1528
1337
|
maxBytes = 1024 * 1024
|
|
1529
1338
|
}) {
|
|
1530
1339
|
const { text, error, loading, truncated } = useViewerText(source, maxBytes);
|
|
1531
|
-
if (error) return /* @__PURE__ */ (0,
|
|
1340
|
+
if (error) return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(ViewerError, { message: error, className });
|
|
1532
1341
|
if (loading || text === null) {
|
|
1533
|
-
return /* @__PURE__ */ (0,
|
|
1342
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(ViewerSkeleton, { tone: "plain", className });
|
|
1534
1343
|
}
|
|
1535
|
-
return /* @__PURE__ */ (0,
|
|
1344
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
|
|
1536
1345
|
"div",
|
|
1537
1346
|
{
|
|
1538
1347
|
className: cn("flex h-full w-full flex-col overflow-hidden", className),
|
|
1539
1348
|
children: [
|
|
1540
|
-
/* @__PURE__ */ (0,
|
|
1541
|
-
/* @__PURE__ */ (0,
|
|
1542
|
-
/* @__PURE__ */ (0,
|
|
1349
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(ViewerToolbar, { children: [
|
|
1350
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "text-muted-foreground", children: truncated ? `Preview ${truncationNote(maxBytes)}.` : `${text.length.toLocaleString()} characters` }),
|
|
1351
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(ViewerCopyButton, { text })
|
|
1543
1352
|
] }),
|
|
1544
|
-
/* @__PURE__ */ (0,
|
|
1353
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("pre", { className: "flex-1 overflow-auto bg-background p-3 font-mono text-xs leading-5 break-words whitespace-pre-wrap", children: text })
|
|
1545
1354
|
]
|
|
1546
1355
|
}
|
|
1547
1356
|
);
|
|
1548
1357
|
}
|
|
1549
1358
|
|
|
1550
1359
|
// src/viewers/unavailable-viewer.tsx
|
|
1551
|
-
var
|
|
1360
|
+
var import_jsx_runtime10 = require("react/jsx-runtime");
|
|
1552
1361
|
var ENGINE_FOR_KIND = {
|
|
1553
1362
|
pdf: "a PDF engine (e.g. PDF.js / react-pdf)",
|
|
1554
1363
|
markdown: "a Markdown renderer",
|
|
@@ -1565,22 +1374,22 @@ function MediaViewerUnavailable({
|
|
|
1565
1374
|
}) {
|
|
1566
1375
|
const engine = ENGINE_FOR_KIND[kind] ?? `a "${kind}" viewer`;
|
|
1567
1376
|
const generic = props.generic;
|
|
1568
|
-
return /* @__PURE__ */ (0,
|
|
1569
|
-
/* @__PURE__ */ (0,
|
|
1377
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: cn("flex h-full w-full flex-col", props.className), children: [
|
|
1378
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "shrink-0 border-b border-amber-500/30 bg-amber-500/10 px-3 py-2 text-center text-xs text-amber-700 dark:text-amber-300", children: [
|
|
1570
1379
|
"No ",
|
|
1571
1380
|
kind,
|
|
1572
1381
|
" viewer is registered in this app, so this file can't be displayed here. An app developer registers ",
|
|
1573
1382
|
engine,
|
|
1574
1383
|
" with",
|
|
1575
1384
|
" ",
|
|
1576
|
-
/* @__PURE__ */ (0,
|
|
1385
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("code", { className: "font-mono", children: [
|
|
1577
1386
|
'registerMediaViewer("',
|
|
1578
1387
|
kind,
|
|
1579
1388
|
'", \u2026)'
|
|
1580
1389
|
] }),
|
|
1581
1390
|
"."
|
|
1582
1391
|
] }),
|
|
1583
|
-
/* @__PURE__ */ (0,
|
|
1392
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "min-h-0 flex-1", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
1584
1393
|
GenericViewer,
|
|
1585
1394
|
{
|
|
1586
1395
|
...props,
|
|
@@ -1648,7 +1457,7 @@ function getPreviewKind(fileName, mimeType) {
|
|
|
1648
1457
|
}
|
|
1649
1458
|
|
|
1650
1459
|
// src/viewers/media-file-viewer.tsx
|
|
1651
|
-
var
|
|
1460
|
+
var import_jsx_runtime11 = require("react/jsx-runtime");
|
|
1652
1461
|
var BUILT_IN = {
|
|
1653
1462
|
text: TextViewer,
|
|
1654
1463
|
code: CodeViewer,
|
|
@@ -1662,7 +1471,7 @@ function MediaFileViewer({
|
|
|
1662
1471
|
}) {
|
|
1663
1472
|
const kind = previewKind ?? getPreviewKind(props.fileName, props.mimeType ?? null);
|
|
1664
1473
|
const viewer = getMediaViewer(kind) ?? BUILT_IN[kind];
|
|
1665
|
-
if (viewer) return (0,
|
|
1666
|
-
return /* @__PURE__ */ (0,
|
|
1474
|
+
if (viewer) return (0, import_react11.createElement)(viewer, props);
|
|
1475
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(MediaViewerUnavailable, { ...props, kind });
|
|
1667
1476
|
}
|
|
1668
1477
|
//# sourceMappingURL=viewers.cjs.map
|