@adoptai/genui-components 0.1.67 → 0.1.69

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (32) hide show
  1. package/dist/composites/document-preview/PdfViewer.d.ts +2 -1
  2. package/dist/composites/document-preview/PdfViewer.d.ts.map +1 -1
  3. package/dist/composites/document-preview/resolver.cjs +90 -11
  4. package/dist/composites/document-preview/resolver.cjs.map +1 -1
  5. package/dist/composites/document-preview/resolver.d.ts.map +1 -1
  6. package/dist/composites/document-preview/resolver.js +90 -11
  7. package/dist/composites/document-preview/resolver.js.map +1 -1
  8. package/dist/composites/download-card/resolver.cjs +244 -69
  9. package/dist/composites/download-card/resolver.cjs.map +1 -1
  10. package/dist/composites/download-card/resolver.js +189 -14
  11. package/dist/composites/download-card/resolver.js.map +1 -1
  12. package/dist/index.cjs +472 -289
  13. package/dist/index.cjs.map +1 -1
  14. package/dist/index.js +265 -82
  15. package/dist/index.js.map +1 -1
  16. package/dist/renderer.cjs +404 -221
  17. package/dist/renderer.cjs.map +1 -1
  18. package/dist/renderer.js +259 -76
  19. package/dist/renderer.js.map +1 -1
  20. package/dist/resolver.cjs +403 -220
  21. package/dist/resolver.cjs.map +1 -1
  22. package/dist/resolver.js +259 -76
  23. package/dist/resolver.js.map +1 -1
  24. package/dist/shared/fileType.d.ts +1 -1
  25. package/dist/shared/fileType.d.ts.map +1 -1
  26. package/dist/shared/viewers/HtmlViewer.d.ts +12 -0
  27. package/dist/shared/viewers/HtmlViewer.d.ts.map +1 -0
  28. package/dist/shared/viewers/PreviewHost.d.ts.map +1 -1
  29. package/dist/shared/viewers/pdfWorkerProbe.d.ts +31 -0
  30. package/dist/shared/viewers/pdfWorkerProbe.d.ts.map +1 -0
  31. package/dist/tool-definitions.json +2 -2
  32. package/package.json +1 -1
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
  'use strict';
3
3
 
4
- var React10 = require('react');
4
+ var React11 = require('react');
5
5
  var jsxRuntime = require('react/jsx-runtime');
6
6
  var reactPdf = require('react-pdf');
7
7
  require('react-pdf/dist/Page/AnnotationLayer.css');
@@ -32,7 +32,7 @@ function _interopNamespace(e) {
32
32
  return Object.freeze(n);
33
33
  }
34
34
 
35
- var React10__default = /*#__PURE__*/_interopDefault(React10);
35
+ var React11__default = /*#__PURE__*/_interopDefault(React11);
36
36
  var XLSX__namespace = /*#__PURE__*/_interopNamespace(XLSX);
37
37
  var Papa__default = /*#__PURE__*/_interopDefault(Papa);
38
38
  var mammoth__namespace = /*#__PURE__*/_interopNamespace(mammoth);
@@ -106,7 +106,7 @@ var init_theme = __esm({
106
106
  }
107
107
  });
108
108
  function useTheme() {
109
- return React10.useContext(GenUIThemeContext);
109
+ return React11.useContext(GenUIThemeContext);
110
110
  }
111
111
  var DEFAULT_TOKENS, GenUIThemeContext;
112
112
  var init_ThemeContext = __esm({
@@ -128,7 +128,7 @@ var init_ThemeContext = __esm({
128
128
  SECONDARY,
129
129
  CHART_PALETTE: [...CHART_PALETTE]
130
130
  };
131
- GenUIThemeContext = React10.createContext(DEFAULT_TOKENS);
131
+ GenUIThemeContext = React11.createContext(DEFAULT_TOKENS);
132
132
  }
133
133
  });
134
134
  function renderInline(text) {
@@ -470,23 +470,83 @@ var init_Markdown = __esm({
470
470
  init_theme();
471
471
  }
472
472
  });
473
+ function resolvePdfWorkerSrc(pdfjs2) {
474
+ const override = typeof window !== "undefined" ? window.__GENUI_PDF_WORKER_SRC__ : void 0;
475
+ const current = pdfjs2.GlobalWorkerOptions.workerSrc;
476
+ const isConfigured = !!current && current !== "pdf.worker.mjs";
477
+ if (override) {
478
+ pdfjs2.GlobalWorkerOptions.workerSrc = override;
479
+ } else if (!isConfigured) {
480
+ pdfjs2.GlobalWorkerOptions.workerSrc = `https://cdn.jsdelivr.net/npm/pdfjs-dist@${pdfjs2.version}/build/pdf.worker.min.mjs`;
481
+ }
482
+ return pdfjs2.GlobalWorkerOptions.workerSrc;
483
+ }
484
+ function probePdfWorker() {
485
+ if (probe) return probe;
486
+ probe = (async () => {
487
+ if (typeof window === "undefined") return false;
488
+ try {
489
+ const { pdfjs: pdfjs2 } = await import('react-pdf');
490
+ resolvePdfWorkerSrc(pdfjs2);
491
+ const task = pdfjs2.getDocument({ data: new TextEncoder().encode(TINY_PDF) });
492
+ const doc = await Promise.race([
493
+ task.promise,
494
+ new Promise(
495
+ (_, reject) => setTimeout(() => reject(new Error("pdf worker probe timed out")), PROBE_TIMEOUT_MS)
496
+ )
497
+ ]);
498
+ await doc.destroy();
499
+ return true;
500
+ } catch (e) {
501
+ probe = null;
502
+ return false;
503
+ }
504
+ })();
505
+ return probe;
506
+ }
507
+ function usePdfWorkerReady(enabled) {
508
+ const [ready, setReady] = React11.useState(null);
509
+ React11.useEffect(() => {
510
+ let cancelled = false;
511
+ probePdfWorker().then((ok) => {
512
+ if (!cancelled) setReady(ok);
513
+ });
514
+ return () => {
515
+ cancelled = true;
516
+ };
517
+ }, [enabled]);
518
+ return ready ;
519
+ }
520
+ var TINY_PDF, PROBE_TIMEOUT_MS, probe;
521
+ var init_pdfWorkerProbe = __esm({
522
+ "src/shared/viewers/pdfWorkerProbe.ts"() {
523
+ "use client";
524
+ TINY_PDF = `%PDF-1.1
525
+ 1 0 obj<</Type/Catalog/Pages 2 0 R>>endobj
526
+ 2 0 obj<</Type/Pages/Kids[3 0 R]/Count 1>>endobj
527
+ 3 0 obj<</Type/Page/Parent 2 0 R/MediaBox[0 0 3 3]>>endobj
528
+ trailer<</Root 1 0 R>>`;
529
+ PROBE_TIMEOUT_MS = 5e3;
530
+ probe = null;
531
+ }
532
+ });
473
533
 
474
534
  // src/composites/document-preview/PdfViewer.tsx
475
535
  var PdfViewer_exports = {};
476
536
  __export(PdfViewer_exports, {
477
537
  PdfViewer: () => PdfViewer
478
538
  });
479
- function PdfViewer({ url, base64, onLoadSuccess }) {
539
+ function PdfViewer({ url, base64, onLoadSuccess, onLoadError }) {
480
540
  const { BORDER: BORDER2, MUTED: MUTED2, SURFACE: SURFACE2 } = useTheme();
481
- const [numPages, setNumPages] = React10.useState(0);
482
- const [currentPage, setCurrentPage] = React10.useState(1);
483
- const [loading, setLoading] = React10.useState(true);
484
- const handleLoad = React10.useCallback(({ numPages: n }) => {
541
+ const [numPages, setNumPages] = React11.useState(0);
542
+ const [currentPage, setCurrentPage] = React11.useState(1);
543
+ const [loading, setLoading] = React11.useState(true);
544
+ const handleLoad = React11.useCallback(({ numPages: n }) => {
485
545
  setNumPages(n);
486
546
  setLoading(false);
487
547
  onLoadSuccess == null ? void 0 : onLoadSuccess(n);
488
548
  }, [onLoadSuccess]);
489
- React10.useEffect(() => {
549
+ React11.useEffect(() => {
490
550
  if (numPages <= 1) return;
491
551
  const handler = (e) => {
492
552
  var _a;
@@ -556,23 +616,34 @@ function PdfViewer({ url, base64, onLoadSuccess }) {
556
616
  ] }),
557
617
  /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { overflow: "auto", width: "100%", display: "flex", justifyContent: "center", padding: "16px" }, children: [
558
618
  loading && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { display: "flex", alignItems: "center", justifyContent: "center", height: "200px", color: MUTED2, fontSize: "13px" }, children: "Loading PDF..." }),
559
- /* @__PURE__ */ jsxRuntime.jsx(reactPdf.Document, { file: base64 ? `data:application/pdf;base64,${base64}` : url, onLoadSuccess: handleLoad, loading: "", children: /* @__PURE__ */ jsxRuntime.jsx(
560
- reactPdf.Page,
619
+ /* @__PURE__ */ jsxRuntime.jsx(
620
+ reactPdf.Document,
561
621
  {
562
- pageNumber: currentPage,
563
- width: 540,
564
- renderTextLayer: true,
565
- renderAnnotationLayer: true
622
+ file: base64 ? `data:application/pdf;base64,${base64}` : url,
623
+ onLoadSuccess: handleLoad,
624
+ onLoadError,
625
+ loading: "",
626
+ error: "",
627
+ children: /* @__PURE__ */ jsxRuntime.jsx(
628
+ reactPdf.Page,
629
+ {
630
+ pageNumber: currentPage,
631
+ width: 540,
632
+ renderTextLayer: true,
633
+ renderAnnotationLayer: true
634
+ }
635
+ )
566
636
  }
567
- ) })
637
+ )
568
638
  ] })
569
639
  ] });
570
640
  }
571
641
  var init_PdfViewer = __esm({
572
642
  "src/composites/document-preview/PdfViewer.tsx"() {
573
643
  "use client";
644
+ init_pdfWorkerProbe();
574
645
  init_ThemeContext();
575
- reactPdf.pdfjs.GlobalWorkerOptions.workerSrc = `https://unpkg.com/pdfjs-dist@${reactPdf.pdfjs.version}/build/pdf.worker.min.mjs`;
646
+ resolvePdfWorkerSrc(reactPdf.pdfjs);
576
647
  }
577
648
  });
578
649
 
@@ -583,13 +654,13 @@ __export(ExcelViewer_exports, {
583
654
  });
584
655
  function ExcelViewer({ url, base64, onLoadSuccess }) {
585
656
  const { BORDER: BORDER2, MUTED: MUTED2, PAPER: PAPER2, SURFACE: SURFACE2 } = useTheme();
586
- const [sheetNames, setSheetNames] = React10.useState([]);
587
- const [activeSheet, setActiveSheet] = React10.useState(0);
588
- const [data, setData] = React10.useState([]);
589
- const [loading, setLoading] = React10.useState(true);
590
- const [error, setError] = React10.useState(null);
591
- const wbRef = React10.useRef(null);
592
- React10.useEffect(() => {
657
+ const [sheetNames, setSheetNames] = React11.useState([]);
658
+ const [activeSheet, setActiveSheet] = React11.useState(0);
659
+ const [data, setData] = React11.useState([]);
660
+ const [loading, setLoading] = React11.useState(true);
661
+ const [error, setError] = React11.useState(null);
662
+ const wbRef = React11.useRef(null);
663
+ React11.useEffect(() => {
593
664
  let cancelled = false;
594
665
  setLoading(true);
595
666
  setError(null);
@@ -647,7 +718,7 @@ function ExcelViewer({ url, base64, onLoadSuccess }) {
647
718
  const rows = XLSX__namespace.utils.sheet_to_json(wbRef.current.Sheets[wbRef.current.SheetNames[idx]], { header: 1 });
648
719
  setData(rows);
649
720
  };
650
- React10.useEffect(() => {
721
+ React11.useEffect(() => {
651
722
  if (sheetNames.length <= 1) return;
652
723
  const handler = (e) => {
653
724
  var _a;
@@ -773,10 +844,10 @@ __export(CsvViewer_exports, {
773
844
  });
774
845
  function CsvViewer({ url, base64, delimiter, maxRows }) {
775
846
  const { BORDER: BORDER2, MUTED: MUTED2, PAPER: PAPER2 } = useTheme();
776
- const [rows, setRows] = React10.useState([]);
777
- const [loading, setLoading] = React10.useState(true);
778
- const [error, setError] = React10.useState(null);
779
- React10.useEffect(() => {
847
+ const [rows, setRows] = React11.useState([]);
848
+ const [loading, setLoading] = React11.useState(true);
849
+ const [error, setError] = React11.useState(null);
850
+ React11.useEffect(() => {
780
851
  let cancelled = false;
781
852
  setLoading(true);
782
853
  setError(null);
@@ -895,10 +966,10 @@ __export(TextViewer_exports, {
895
966
  });
896
967
  function TextViewer({ url, base64, markdown = false, maxLines }) {
897
968
  const { MUTED: MUTED2 } = useTheme();
898
- const [text, setText] = React10.useState("");
899
- const [loading, setLoading] = React10.useState(true);
900
- const [error, setError] = React10.useState(null);
901
- React10.useEffect(() => {
969
+ const [text, setText] = React11.useState("");
970
+ const [loading, setLoading] = React11.useState(true);
971
+ const [error, setError] = React11.useState(null);
972
+ React11.useEffect(() => {
902
973
  let cancelled = false;
903
974
  setLoading(true);
904
975
  setError(null);
@@ -996,10 +1067,10 @@ function sanitize(html) {
996
1067
  }
997
1068
  function DocxViewer({ url, base64 }) {
998
1069
  const { MUTED: MUTED2, BORDER: BORDER2, SURFACE: SURFACE2 } = useTheme();
999
- const [html, setHtml] = React10.useState("");
1000
- const [loading, setLoading] = React10.useState(true);
1001
- const [error, setError] = React10.useState(null);
1002
- React10.useEffect(() => {
1070
+ const [html, setHtml] = React11.useState("");
1071
+ const [loading, setLoading] = React11.useState(true);
1072
+ const [error, setError] = React11.useState(null);
1073
+ React11.useEffect(() => {
1003
1074
  let cancelled = false;
1004
1075
  setLoading(true);
1005
1076
  setError(null);
@@ -1079,6 +1150,89 @@ var init_DocxViewer = __esm({
1079
1150
  }
1080
1151
  });
1081
1152
 
1153
+ // src/shared/viewers/HtmlViewer.tsx
1154
+ var HtmlViewer_exports = {};
1155
+ __export(HtmlViewer_exports, {
1156
+ HtmlViewer: () => HtmlViewer
1157
+ });
1158
+ function HtmlViewer({ url, base64, height = 480 }) {
1159
+ const { MUTED: MUTED2 } = useTheme();
1160
+ const [html, setHtml] = React11.useState("");
1161
+ const [loading, setLoading] = React11.useState(true);
1162
+ const [error, setError] = React11.useState(null);
1163
+ React11.useEffect(() => {
1164
+ let cancelled = false;
1165
+ setLoading(true);
1166
+ setError(null);
1167
+ if (base64) {
1168
+ try {
1169
+ if (!cancelled) {
1170
+ setHtml(base64ToText(base64));
1171
+ setLoading(false);
1172
+ }
1173
+ } catch (e) {
1174
+ if (!cancelled) {
1175
+ setError(e instanceof Error ? e.message : "Failed to decode HTML");
1176
+ setLoading(false);
1177
+ }
1178
+ }
1179
+ return () => {
1180
+ cancelled = true;
1181
+ };
1182
+ }
1183
+ if (!url) {
1184
+ setError("No file source provided");
1185
+ setLoading(false);
1186
+ return () => {
1187
+ cancelled = true;
1188
+ };
1189
+ }
1190
+ fetch(url).then((r) => {
1191
+ if (!r.ok) throw new Error(`Failed to fetch: ${r.status}`);
1192
+ return r.text();
1193
+ }).then((t) => {
1194
+ if (cancelled) return;
1195
+ setHtml(t);
1196
+ setLoading(false);
1197
+ }).catch((e) => {
1198
+ if (cancelled) return;
1199
+ setError(e.message);
1200
+ setLoading(false);
1201
+ });
1202
+ return () => {
1203
+ cancelled = true;
1204
+ };
1205
+ }, [url, base64]);
1206
+ if (loading) {
1207
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { style: { padding: "24px", color: MUTED2, fontSize: "13px", textAlign: "center" }, children: "Loading\u2026" });
1208
+ }
1209
+ if (error) {
1210
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { style: { padding: "24px", color: "#dc2626", fontSize: "13px", textAlign: "center" }, children: error });
1211
+ }
1212
+ return /* @__PURE__ */ jsxRuntime.jsx(
1213
+ "iframe",
1214
+ {
1215
+ title: "HTML preview",
1216
+ sandbox: "",
1217
+ srcDoc: html,
1218
+ style: {
1219
+ width: "100%",
1220
+ height: `${height}px`,
1221
+ border: "none",
1222
+ background: "white",
1223
+ display: "block"
1224
+ }
1225
+ }
1226
+ );
1227
+ }
1228
+ var init_HtmlViewer = __esm({
1229
+ "src/shared/viewers/HtmlViewer.tsx"() {
1230
+ "use client";
1231
+ init_ThemeContext();
1232
+ init_decode();
1233
+ }
1234
+ });
1235
+
1082
1236
  // src/shared/ColumnSettingsPanel.tsx
1083
1237
  init_ThemeContext();
1084
1238
  function ColumnSettingsPanel({ columns, hidden, onToggle, onShowAll, onHideAll }) {
@@ -1130,16 +1284,16 @@ var DOT_COLOR = "#aaaaaa";
1130
1284
  var DOT_HOVER = "#555555";
1131
1285
  function ComponentActions({ children, onDownloadCSV, columnConfig, filename = "component" }) {
1132
1286
  const { BORDER: BORDER2, MUTED: MUTED2, SURFACE: SURFACE2, SURFACE_MUTED: SURFACE_MUTED2 } = useTheme();
1133
- const [open, setOpen] = React10.useState(false);
1134
- const [view, setView] = React10.useState("main");
1135
- const contentRef = React10.useRef(null);
1136
- const menuRef = React10.useRef(null);
1137
- const btnRef = React10.useRef(null);
1138
- const close = React10.useCallback(() => {
1287
+ const [open, setOpen] = React11.useState(false);
1288
+ const [view, setView] = React11.useState("main");
1289
+ const contentRef = React11.useRef(null);
1290
+ const menuRef = React11.useRef(null);
1291
+ const btnRef = React11.useRef(null);
1292
+ const close = React11.useCallback(() => {
1139
1293
  setOpen(false);
1140
1294
  setView("main");
1141
1295
  }, []);
1142
- React10.useEffect(() => {
1296
+ React11.useEffect(() => {
1143
1297
  if (!open) return;
1144
1298
  const handler = (e) => {
1145
1299
  var _a, _b;
@@ -1150,7 +1304,7 @@ function ComponentActions({ children, onDownloadCSV, columnConfig, filename = "c
1150
1304
  document.addEventListener("mousedown", handler);
1151
1305
  return () => document.removeEventListener("mousedown", handler);
1152
1306
  }, [open, close]);
1153
- const handleDownloadPNG = React10.useCallback(async () => {
1307
+ const handleDownloadPNG = React11.useCallback(async () => {
1154
1308
  if (!contentRef.current) return;
1155
1309
  try {
1156
1310
  const url = await htmlToImage.toPng(contentRef.current, { backgroundColor: "white", pixelRatio: 2 });
@@ -1162,7 +1316,7 @@ function ComponentActions({ children, onDownloadCSV, columnConfig, filename = "c
1162
1316
  }
1163
1317
  close();
1164
1318
  }, [filename, close]);
1165
- const handleCSV = React10.useCallback(() => {
1319
+ const handleCSV = React11.useCallback(() => {
1166
1320
  onDownloadCSV == null ? void 0 : onDownloadCSV();
1167
1321
  close();
1168
1322
  }, [onDownloadCSV, close]);
@@ -1284,7 +1438,7 @@ init_theme();
1284
1438
  var FAMILIES = [
1285
1439
  { exts: ["csv", "tsv", "xls", "xlsx", "numbers"], fg: SEMANTIC.success.color, bg: SEMANTIC.success.bg },
1286
1440
  { exts: ["pdf"], fg: SEMANTIC.error.color, bg: SEMANTIC.error.bg },
1287
- { exts: ["doc", "docx", "txt", "md", "rtf", "pages"], fg: SEMANTIC.info.color, bg: SEMANTIC.info.bg },
1441
+ { exts: ["doc", "docx", "txt", "md", "rtf", "pages", "html", "htm"], fg: SEMANTIC.info.color, bg: SEMANTIC.info.bg },
1288
1442
  { exts: ["json", "yaml", "yml", "xml", "toml"], fg: SEMANTIC.purple.color, bg: SEMANTIC.purple.bg },
1289
1443
  { exts: ["zip", "tar", "gz", "rar", "7z"], fg: SEMANTIC.warning.color, bg: SEMANTIC.warning.bg },
1290
1444
  { exts: ["png", "jpg", "jpeg", "gif", "svg", "webp", "bmp"], fg: SEMANTIC.info.color, bg: SEMANTIC.info.bg }
@@ -1311,7 +1465,9 @@ var PREVIEW_EXTS = {
1311
1465
  txt: "text",
1312
1466
  log: "text",
1313
1467
  text: "text",
1314
- docx: "docx"
1468
+ docx: "docx",
1469
+ html: "html",
1470
+ htm: "html"
1315
1471
  };
1316
1472
  function extOf(fileType, filename) {
1317
1473
  var _a;
@@ -1322,6 +1478,7 @@ function extOf(fileType, filename) {
1322
1478
  if (mime.includes("csv")) return "csv";
1323
1479
  if (mime.includes("markdown")) return "md";
1324
1480
  if (mime.includes("wordprocessing") || mime.includes("msword")) return "docx";
1481
+ if (mime.includes("html")) return "html";
1325
1482
  if (mime.startsWith("text/")) return "txt";
1326
1483
  } else if (fileType) {
1327
1484
  const t = fileType.toLowerCase().replace(/[^a-z0-9]/g, "");
@@ -1355,17 +1512,32 @@ function isExpirySoon(expiresAt) {
1355
1512
 
1356
1513
  // src/shared/viewers/PreviewHost.tsx
1357
1514
  init_ThemeContext();
1358
- var PdfViewer2 = React10.lazy(
1515
+ init_pdfWorkerProbe();
1516
+ var PdfViewer2 = React11.lazy(
1359
1517
  () => Promise.resolve().then(() => (init_PdfViewer(), PdfViewer_exports)).then((m) => ({ default: m.PdfViewer }))
1360
1518
  );
1361
- var ExcelViewer2 = React10.lazy(
1519
+ var ExcelViewer2 = React11.lazy(
1362
1520
  () => Promise.resolve().then(() => (init_ExcelViewer(), ExcelViewer_exports)).then((m) => ({ default: m.ExcelViewer }))
1363
1521
  );
1364
- var CsvViewer2 = React10.lazy(() => Promise.resolve().then(() => (init_CsvViewer(), CsvViewer_exports)).then((m) => ({ default: m.CsvViewer })));
1365
- var TextViewer2 = React10.lazy(() => Promise.resolve().then(() => (init_TextViewer(), TextViewer_exports)).then((m) => ({ default: m.TextViewer })));
1366
- var DocxViewer2 = React10.lazy(() => Promise.resolve().then(() => (init_DocxViewer(), DocxViewer_exports)).then((m) => ({ default: m.DocxViewer })));
1522
+ var CsvViewer2 = React11.lazy(() => Promise.resolve().then(() => (init_CsvViewer(), CsvViewer_exports)).then((m) => ({ default: m.CsvViewer })));
1523
+ var TextViewer2 = React11.lazy(() => Promise.resolve().then(() => (init_TextViewer(), TextViewer_exports)).then((m) => ({ default: m.TextViewer })));
1524
+ var DocxViewer2 = React11.lazy(() => Promise.resolve().then(() => (init_DocxViewer(), DocxViewer_exports)).then((m) => ({ default: m.DocxViewer })));
1525
+ var HtmlViewer2 = React11.lazy(() => Promise.resolve().then(() => (init_HtmlViewer(), HtmlViewer_exports)).then((m) => ({ default: m.HtmlViewer })));
1367
1526
  var PEEK_ROWS = 20;
1368
1527
  var PEEK_LINES = 40;
1528
+ function GatedPdfViewer({ source }) {
1529
+ const { MUTED: MUTED2 } = useTheme();
1530
+ const [failed, setFailed] = React11.useState(false);
1531
+ const workerReady = usePdfWorkerReady(true);
1532
+ const ready = failed ? false : workerReady;
1533
+ if (ready === null) {
1534
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { style: { padding: "24px", color: MUTED2, fontSize: "13px", textAlign: "center" }, children: "Loading preview\u2026" });
1535
+ }
1536
+ if (ready === false) {
1537
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { style: { padding: "24px", color: MUTED2, fontSize: "13px", textAlign: "center" }, children: "Preview unavailable \u2014 download the file to view it." });
1538
+ }
1539
+ return /* @__PURE__ */ jsxRuntime.jsx(PdfViewer2, { url: source.url, base64: source.base64, onLoadError: () => setFailed(true) });
1540
+ }
1369
1541
  function PreviewHost({ kind, source, mode = "full" }) {
1370
1542
  const { MUTED: MUTED2 } = useTheme();
1371
1543
  const peek = mode === "peek";
@@ -1373,7 +1545,7 @@ function PreviewHost({ kind, source, mode = "full" }) {
1373
1545
  let viewer = null;
1374
1546
  switch (kind) {
1375
1547
  case "pdf":
1376
- viewer = /* @__PURE__ */ jsxRuntime.jsx(PdfViewer2, { url: source.url, base64: source.base64 });
1548
+ viewer = /* @__PURE__ */ jsxRuntime.jsx(GatedPdfViewer, { source });
1377
1549
  break;
1378
1550
  case "excel":
1379
1551
  viewer = /* @__PURE__ */ jsxRuntime.jsx(ExcelViewer2, { url: source.url, base64: source.base64 });
@@ -1390,10 +1562,13 @@ function PreviewHost({ kind, source, mode = "full" }) {
1390
1562
  case "docx":
1391
1563
  viewer = /* @__PURE__ */ jsxRuntime.jsx(DocxViewer2, { url: source.url, base64: source.base64 });
1392
1564
  break;
1565
+ case "html":
1566
+ viewer = /* @__PURE__ */ jsxRuntime.jsx(HtmlViewer2, { url: source.url, base64: source.base64, height: peek ? 240 : 480 });
1567
+ break;
1393
1568
  default:
1394
1569
  return null;
1395
1570
  }
1396
- return /* @__PURE__ */ jsxRuntime.jsx(React10.Suspense, { fallback, children: viewer });
1571
+ return /* @__PURE__ */ jsxRuntime.jsx(React11.Suspense, { fallback, children: viewer });
1397
1572
  }
1398
1573
 
1399
1574
  // src/shared/PreviewModal.tsx
@@ -1409,7 +1584,7 @@ function PreviewModal({
1409
1584
  onDownload
1410
1585
  }) {
1411
1586
  const { BORDER: BORDER2, MUTED: MUTED2, ACCENT: ACCENT2, SURFACE: SURFACE2, FOREGROUND: FOREGROUND2, SCRIM: SCRIM2 } = useTheme();
1412
- React10.useEffect(() => {
1587
+ React11.useEffect(() => {
1413
1588
  if (!open) return;
1414
1589
  const onKey = (e) => {
1415
1590
  if (e.key === "Escape") onClose();
@@ -1586,17 +1761,17 @@ function FileCard({
1586
1761
  previewDisabled = false
1587
1762
  }) {
1588
1763
  const { BORDER: BORDER2, MUTED: MUTED2, ACCENT: ACCENT2, SURFACE: SURFACE2, SURFACE_MUTED: SURFACE_MUTED2, SHADOW: SHADOW2 } = useTheme();
1589
- const [cardHover, setCardHover] = React10.useState(false);
1590
- const [btnHover, setBtnHover] = React10.useState(false);
1591
- const [pvHover, setPvHover] = React10.useState(false);
1764
+ const [cardHover, setCardHover] = React11.useState(false);
1765
+ const [btnHover, setBtnHover] = React11.useState(false);
1766
+ const [pvHover, setPvHover] = React11.useState(false);
1592
1767
  const previewKind = previewKindFor(fileType, filename);
1593
1768
  const canPreview = !previewDisabled && previewKind !== null && (!!previewUrl || !!fetchPreviewBlob);
1594
- const [peekOpen, setPeekOpen] = React10.useState(false);
1595
- const [modalOpen, setModalOpen] = React10.useState(false);
1596
- const [source, setSource] = React10.useState(previewUrl ? { url: previewUrl } : null);
1597
- const [pvLoading, setPvLoading] = React10.useState(false);
1598
- const [pvError, setPvError] = React10.useState(null);
1599
- const ensureSource = React10.useCallback(async () => {
1769
+ const [peekOpen, setPeekOpen] = React11.useState(false);
1770
+ const [modalOpen, setModalOpen] = React11.useState(false);
1771
+ const [source, setSource] = React11.useState(previewUrl ? { url: previewUrl } : null);
1772
+ const [pvLoading, setPvLoading] = React11.useState(false);
1773
+ const [pvError, setPvError] = React11.useState(null);
1774
+ const ensureSource = React11.useCallback(async () => {
1600
1775
  if (source) return source;
1601
1776
  if (previewUrl) {
1602
1777
  const s = { url: previewUrl };
@@ -1618,7 +1793,7 @@ function FileCard({
1618
1793
  setPvLoading(false);
1619
1794
  }
1620
1795
  }, [source, previewUrl, fetchPreviewBlob]);
1621
- const togglePeek = React10.useCallback(async () => {
1796
+ const togglePeek = React11.useCallback(async () => {
1622
1797
  if (peekOpen) {
1623
1798
  setPeekOpen(false);
1624
1799
  return;
@@ -1626,7 +1801,7 @@ function FileCard({
1626
1801
  setPeekOpen(true);
1627
1802
  await ensureSource();
1628
1803
  }, [peekOpen, ensureSource]);
1629
- const openModal = React10.useCallback(async () => {
1804
+ const openModal = React11.useCallback(async () => {
1630
1805
  const s = await ensureSource();
1631
1806
  if (s) setModalOpen(true);
1632
1807
  }, [ensureSource]);
@@ -1741,7 +1916,7 @@ function FileCard({
1741
1916
  whiteSpace: "nowrap"
1742
1917
  },
1743
1918
  children: [
1744
- metaTokens.map((t, i) => /* @__PURE__ */ jsxRuntime.jsxs(React10__default.default.Fragment, { children: [
1919
+ metaTokens.map((t, i) => /* @__PURE__ */ jsxRuntime.jsxs(React11__default.default.Fragment, { children: [
1745
1920
  i > 0 && /* @__PURE__ */ jsxRuntime.jsx("span", { style: { color: MUTED2 }, children: "\xB7" }),
1746
1921
  /* @__PURE__ */ jsxRuntime.jsx("span", { children: t })
1747
1922
  ] }, i)),