@ai-matrx/media 0.4.4 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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 import_react12 = require("react");
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 import_jsx_runtime6 = require("react/jsx-runtime");
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, import_jsx_runtime6.jsxs)(
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, import_jsx_runtime6.jsx)(FileIcon2, { fileName, size: 48 }),
1213
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { children: [
1214
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { className: "max-w-md truncate text-sm font-medium", children: fileName }),
1215
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { className: "text-xs text-muted-foreground", children: formatFileSize(fileSize ?? null) })
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, import_jsx_runtime6.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.") }),
1218
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex flex-wrap items-center justify-center gap-2", children: [
1219
- onViewAsText && viewAsTextPrimary ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
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, import_jsx_runtime6.jsxs)(
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, import_jsx_runtime6.jsx)(DownloadIcon, { className: "h-4 w-4" }),
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, import_jsx_runtime6.jsx)(
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, import_jsx_runtime6.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
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, import_jsx_runtime6.jsxs)(
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, import_jsx_runtime6.jsx)(SpinnerIcon, { className: "h-4 w-4 animate-spin" }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(FileTextIcon, { className: "h-4 w-4" }),
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 import_react10 = require("react");
1093
+ var import_react9 = require("react");
1285
1094
 
1286
1095
  // src/viewers/markup-chrome.tsx
1287
- var import_react9 = require("react");
1288
- var import_jsx_runtime7 = require("react/jsx-runtime");
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, import_react9.useState)("rendered");
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, import_jsx_runtime7.jsxs)("div", { className: cn("flex items-center gap-0.5", className), children: [
1306
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
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, import_jsx_runtime7.jsx)(GlobeIcon, { className: "h-3.5 w-3.5" }) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ImageIcon, { className: "h-3.5 w-3.5" })
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, import_jsx_runtime7.jsx)(
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, import_jsx_runtime7.jsx)(CodeIcon, { className: "h-3.5 w-3.5" })
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, import_jsx_runtime7.jsxs)(
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, import_jsx_runtime7.jsx)("span", { children: label })
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 import_jsx_runtime8 = require("react/jsx-runtime");
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, import_jsx_runtime8.jsxs)("div", { className: cn("flex h-full w-full flex-col", className), children: [
1361
- controlled ? null : /* @__PURE__ */ (0, import_jsx_runtime8.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: [
1362
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "truncate font-medium text-foreground", children: fileName }),
1363
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
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, import_jsx_runtime8.jsx)("div", { className: "relative min-h-0 flex-1", children: mode === "rendered" ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(HtmlRenderedView, { ...props }) : /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(HtmlSourceView, { ...props }) })
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, import_react10.useState)(false);
1381
- (0, import_react10.useEffect)(() => {
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, import_jsx_runtime8.jsx)(
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, import_jsx_runtime8.jsx)(ViewerSkeleton, {});
1394
- if (errored) return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(ViewerError, { title: "Preview unavailable" });
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, import_jsx_runtime8.jsx)(
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, import_jsx_runtime8.jsx)(
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, import_jsx_runtime8.jsx)(
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, import_jsx_runtime8.jsx)(ViewerError, { title: "Couldn't load source", message: error });
1432
- if (loading || text === null) return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(ViewerSkeleton, {});
1433
- return /* @__PURE__ */ (0, import_jsx_runtime8.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 });
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 import_react11 = require("react");
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 import_jsx_runtime9 = require("react/jsx-runtime");
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, import_jsx_runtime9.jsxs)(
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, import_jsx_runtime9.jsx)(
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, import_jsx_runtime9.jsx)(SvgRenderedView, { ...props }) : /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(SvgSourceView, { ...props })
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, import_react11.useState)(null);
1475
- (0, import_react11.useEffect)(() => {
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, import_jsx_runtime9.jsx)(
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, import_jsx_runtime9.jsx)(ViewerSkeleton, { className: "flex-1" });
1500
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
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, import_jsx_runtime9.jsx)(
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, import_jsx_runtime9.jsx)(ViewerError, { title: "Could not load source", message: error });
1519
- if (loading || text === null) return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(ViewerSkeleton, { className: "flex-1" });
1520
- return /* @__PURE__ */ (0, import_jsx_runtime9.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 });
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 import_jsx_runtime10 = require("react/jsx-runtime");
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, import_jsx_runtime10.jsx)(ViewerError, { message: error, className });
1340
+ if (error) return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(ViewerError, { message: error, className });
1532
1341
  if (loading || text === null) {
1533
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(ViewerSkeleton, { tone: "plain", className });
1342
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(ViewerSkeleton, { tone: "plain", className });
1534
1343
  }
1535
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
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, import_jsx_runtime10.jsxs)(ViewerToolbar, { children: [
1541
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "text-muted-foreground", children: truncated ? `Preview ${truncationNote(maxBytes)}.` : `${text.length.toLocaleString()} characters` }),
1542
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(ViewerCopyButton, { text })
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, import_jsx_runtime10.jsx)("pre", { className: "flex-1 overflow-auto bg-background p-3 font-mono text-xs leading-5 break-words whitespace-pre-wrap", children: text })
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 import_jsx_runtime11 = require("react/jsx-runtime");
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, import_jsx_runtime11.jsxs)("div", { className: cn("flex h-full w-full flex-col", props.className), children: [
1569
- /* @__PURE__ */ (0, import_jsx_runtime11.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: [
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, import_jsx_runtime11.jsxs)("code", { className: "font-mono", children: [
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, import_jsx_runtime11.jsx)("div", { className: "min-h-0 flex-1", children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
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 import_jsx_runtime12 = require("react/jsx-runtime");
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, import_react12.createElement)(viewer, props);
1666
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(MediaViewerUnavailable, { ...props, kind });
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