@adoptai/genui-components 0.1.67 → 0.1.68

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/resolver.cjs CHANGED
@@ -1292,13 +1292,74 @@ var init_FlowGraph = __esm({
1292
1292
  renderSeq = 0;
1293
1293
  }
1294
1294
  });
1295
+ function resolvePdfWorkerSrc(pdfjs2) {
1296
+ const override = typeof window !== "undefined" ? window.__GENUI_PDF_WORKER_SRC__ : void 0;
1297
+ const current = pdfjs2.GlobalWorkerOptions.workerSrc;
1298
+ const isConfigured = !!current && current !== "pdf.worker.mjs";
1299
+ if (override) {
1300
+ pdfjs2.GlobalWorkerOptions.workerSrc = override;
1301
+ } else if (!isConfigured) {
1302
+ pdfjs2.GlobalWorkerOptions.workerSrc = `https://cdn.jsdelivr.net/npm/pdfjs-dist@${pdfjs2.version}/build/pdf.worker.min.mjs`;
1303
+ }
1304
+ return pdfjs2.GlobalWorkerOptions.workerSrc;
1305
+ }
1306
+ function probePdfWorker() {
1307
+ if (probe) return probe;
1308
+ probe = (async () => {
1309
+ if (typeof window === "undefined") return false;
1310
+ try {
1311
+ const { pdfjs: pdfjs2 } = await import('react-pdf');
1312
+ resolvePdfWorkerSrc(pdfjs2);
1313
+ const task = pdfjs2.getDocument({ data: new TextEncoder().encode(TINY_PDF) });
1314
+ const doc = await Promise.race([
1315
+ task.promise,
1316
+ new Promise(
1317
+ (_, reject) => setTimeout(() => reject(new Error("pdf worker probe timed out")), PROBE_TIMEOUT_MS)
1318
+ )
1319
+ ]);
1320
+ await doc.destroy();
1321
+ return true;
1322
+ } catch (e) {
1323
+ probe = null;
1324
+ return false;
1325
+ }
1326
+ })();
1327
+ return probe;
1328
+ }
1329
+ function usePdfWorkerReady(enabled) {
1330
+ const [ready, setReady] = React45.useState(null);
1331
+ React45.useEffect(() => {
1332
+ if (!enabled) return;
1333
+ let cancelled = false;
1334
+ probePdfWorker().then((ok) => {
1335
+ if (!cancelled) setReady(ok);
1336
+ });
1337
+ return () => {
1338
+ cancelled = true;
1339
+ };
1340
+ }, [enabled]);
1341
+ return enabled ? ready : null;
1342
+ }
1343
+ var TINY_PDF, PROBE_TIMEOUT_MS, probe;
1344
+ var init_pdfWorkerProbe = __esm({
1345
+ "src/shared/viewers/pdfWorkerProbe.ts"() {
1346
+ "use client";
1347
+ TINY_PDF = `%PDF-1.1
1348
+ 1 0 obj<</Type/Catalog/Pages 2 0 R>>endobj
1349
+ 2 0 obj<</Type/Pages/Kids[3 0 R]/Count 1>>endobj
1350
+ 3 0 obj<</Type/Page/Parent 2 0 R/MediaBox[0 0 3 3]>>endobj
1351
+ trailer<</Root 1 0 R>>`;
1352
+ PROBE_TIMEOUT_MS = 5e3;
1353
+ probe = null;
1354
+ }
1355
+ });
1295
1356
 
1296
1357
  // src/composites/document-preview/PdfViewer.tsx
1297
1358
  var PdfViewer_exports = {};
1298
1359
  __export(PdfViewer_exports, {
1299
1360
  PdfViewer: () => PdfViewer
1300
1361
  });
1301
- function PdfViewer({ url, base64, onLoadSuccess }) {
1362
+ function PdfViewer({ url, base64, onLoadSuccess, onLoadError }) {
1302
1363
  const { BORDER: BORDER3, MUTED: MUTED2, SURFACE: SURFACE2 } = useTheme();
1303
1364
  const [numPages, setNumPages] = React45.useState(0);
1304
1365
  const [currentPage, setCurrentPage] = React45.useState(1);
@@ -1378,23 +1439,34 @@ function PdfViewer({ url, base64, onLoadSuccess }) {
1378
1439
  ] }),
1379
1440
  /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { overflow: "auto", width: "100%", display: "flex", justifyContent: "center", padding: "16px" }, children: [
1380
1441
  loading && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { display: "flex", alignItems: "center", justifyContent: "center", height: "200px", color: MUTED2, fontSize: "13px" }, children: "Loading PDF..." }),
1381
- /* @__PURE__ */ jsxRuntime.jsx(reactPdf.Document, { file: base64 ? `data:application/pdf;base64,${base64}` : url, onLoadSuccess: handleLoad, loading: "", children: /* @__PURE__ */ jsxRuntime.jsx(
1382
- reactPdf.Page,
1442
+ /* @__PURE__ */ jsxRuntime.jsx(
1443
+ reactPdf.Document,
1383
1444
  {
1384
- pageNumber: currentPage,
1385
- width: 540,
1386
- renderTextLayer: true,
1387
- renderAnnotationLayer: true
1445
+ file: base64 ? `data:application/pdf;base64,${base64}` : url,
1446
+ onLoadSuccess: handleLoad,
1447
+ onLoadError,
1448
+ loading: "",
1449
+ error: "",
1450
+ children: /* @__PURE__ */ jsxRuntime.jsx(
1451
+ reactPdf.Page,
1452
+ {
1453
+ pageNumber: currentPage,
1454
+ width: 540,
1455
+ renderTextLayer: true,
1456
+ renderAnnotationLayer: true
1457
+ }
1458
+ )
1388
1459
  }
1389
- ) })
1460
+ )
1390
1461
  ] })
1391
1462
  ] });
1392
1463
  }
1393
1464
  var init_PdfViewer = __esm({
1394
1465
  "src/composites/document-preview/PdfViewer.tsx"() {
1395
1466
  "use client";
1467
+ init_pdfWorkerProbe();
1396
1468
  init_ThemeContext();
1397
- reactPdf.pdfjs.GlobalWorkerOptions.workerSrc = `https://unpkg.com/pdfjs-dist@${reactPdf.pdfjs.version}/build/pdf.worker.min.mjs`;
1469
+ resolvePdfWorkerSrc(reactPdf.pdfjs);
1398
1470
  }
1399
1471
  });
1400
1472
 
@@ -9020,6 +9092,7 @@ function useFullscreen(ref) {
9020
9092
  // src/composites/document-preview/resolver.tsx
9021
9093
  init_theme();
9022
9094
  init_ThemeContext();
9095
+ init_pdfWorkerProbe();
9023
9096
  var PdfViewer2 = React45__default.default.lazy(
9024
9097
  () => Promise.resolve().then(() => (init_PdfViewer(), PdfViewer_exports)).then((m) => ({ default: m.PdfViewer }))
9025
9098
  );
@@ -9083,8 +9156,14 @@ function DocumentPreviewResolver(p) {
9083
9156
  const totalPages = ((_c = p.pages) != null ? _c : []).length;
9084
9157
  const page = p.pages[currentPage];
9085
9158
  const pageHighlights = ((_d = p.highlights) != null ? _d : []).filter((h) => h.pageIndex === currentPage);
9159
+ const [pdfFailed, setPdfFailed] = React45.useState(false);
9160
+ const pdfWorkerReady = usePdfWorkerReady(hasRealFile && isPdf);
9161
+ const pdfReady = pdfFailed ? false : pdfWorkerReady;
9162
+ const showPdfViewer = hasRealFile && isPdf && pdfReady === true;
9163
+ const pdfPending = hasRealFile && isPdf && pdfReady === null;
9086
9164
  const handlePdfLoad = React45.useCallback(() => {
9087
9165
  }, []);
9166
+ const handlePdfError = React45.useCallback(() => setPdfFailed(true), []);
9088
9167
  const handleExcelLoad = React45.useCallback(() => {
9089
9168
  }, []);
9090
9169
  return /* @__PURE__ */ jsxRuntime.jsx(ComponentActions, { filename: (_e = p.title) != null ? _e : "document-preview", children: /* @__PURE__ */ jsxRuntime.jsxs(
@@ -9178,7 +9257,7 @@ function DocumentPreviewResolver(p) {
9178
9257
  children: pg.label
9179
9258
  },
9180
9259
  i
9181
- )) }) : !hasRealFile && totalPages > 1 && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", alignItems: "center", gap: "8px", padding: "6px 14px", borderLeft: `1px solid ${BORDER3}`, borderRight: `1px solid ${BORDER3}`, background: SURFACE2 }, children: [
9260
+ )) }) : (!hasRealFile || pdfReady === false) && totalPages > 1 && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", alignItems: "center", gap: "8px", padding: "6px 14px", borderLeft: `1px solid ${BORDER3}`, borderRight: `1px solid ${BORDER3}`, background: SURFACE2 }, children: [
9182
9261
  /* @__PURE__ */ jsxRuntime.jsx("button", { onClick: () => setCurrentPage(Math.max(0, currentPage - 1)), disabled: currentPage === 0, style: { border: `1px solid ${BORDER3}`, borderRadius: "4px", padding: "2px 8px", background: SURFACE2, cursor: "pointer", fontSize: "12px", color: currentPage === 0 ? BORDER3 : MUTED2 }, children: "\u2190" }),
9183
9262
  /* @__PURE__ */ jsxRuntime.jsxs("span", { style: { fontSize: "12px", color: MUTED2 }, children: [
9184
9263
  currentPage + 1,
@@ -9198,7 +9277,7 @@ function DocumentPreviewResolver(p) {
9198
9277
  display: "flex",
9199
9278
  flexDirection: "column"
9200
9279
  }, children: [
9201
- hasRealFile && isPdf ? /* @__PURE__ */ jsxRuntime.jsx(React45.Suspense, { fallback: null, children: /* @__PURE__ */ jsxRuntime.jsx(PdfViewer2, { url: (_q = p.source) == null ? void 0 : _q.url, base64: (_r = p.source) == null ? void 0 : _r.base64, onLoadSuccess: handlePdfLoad }) }) : hasRealFile && isExcel ? /* @__PURE__ */ jsxRuntime.jsx(React45.Suspense, { fallback: null, children: /* @__PURE__ */ jsxRuntime.jsx(ExcelViewer2, { url: (_s = p.source) == null ? void 0 : _s.url, base64: (_t = p.source) == null ? void 0 : _t.base64, onLoadSuccess: handleExcelLoad }) }) : (page == null ? void 0 : page.imageUrl) ? /* @__PURE__ */ jsxRuntime.jsx("div", { style: { padding: "20px" }, children: /* @__PURE__ */ jsxRuntime.jsx("img", { src: page.imageUrl, alt: page.label, style: { maxWidth: "100%", borderRadius: "4px" } }) }) : (page == null ? void 0 : page.content) ? /* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontFamily: "var(--font-sans, system-ui)", fontSize: "13px", color: "var(--foreground)", lineHeight: 1.6, margin: 0, padding: "20px" }, children: /* @__PURE__ */ jsxRuntime.jsx(Markdown, { content: page.content }) }) : /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", alignItems: "center", justifyContent: "center", height: "120px", color: MUTED2, fontSize: "13px" }, children: [
9280
+ showPdfViewer ? /* @__PURE__ */ jsxRuntime.jsx(React45.Suspense, { fallback: null, children: /* @__PURE__ */ jsxRuntime.jsx(PdfViewer2, { url: (_q = p.source) == null ? void 0 : _q.url, base64: (_r = p.source) == null ? void 0 : _r.base64, onLoadSuccess: handlePdfLoad, onLoadError: handlePdfError }) }) : pdfPending ? /* @__PURE__ */ jsxRuntime.jsx("div", { style: { display: "flex", alignItems: "center", justifyContent: "center", height: "200px", color: MUTED2, fontSize: "13px" }, children: "Loading preview\u2026" }) : hasRealFile && isExcel ? /* @__PURE__ */ jsxRuntime.jsx(React45.Suspense, { fallback: null, children: /* @__PURE__ */ jsxRuntime.jsx(ExcelViewer2, { url: (_s = p.source) == null ? void 0 : _s.url, base64: (_t = p.source) == null ? void 0 : _t.base64, onLoadSuccess: handleExcelLoad }) }) : (page == null ? void 0 : page.imageUrl) ? /* @__PURE__ */ jsxRuntime.jsx("div", { style: { padding: "20px" }, children: /* @__PURE__ */ jsxRuntime.jsx("img", { src: page.imageUrl, alt: page.label, style: { maxWidth: "100%", borderRadius: "4px" } }) }) : (page == null ? void 0 : page.content) ? /* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontFamily: "var(--font-sans, system-ui)", fontSize: "13px", color: "var(--foreground)", lineHeight: 1.6, margin: 0, padding: "20px" }, children: /* @__PURE__ */ jsxRuntime.jsx(Markdown, { content: page.content }) }) : /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", alignItems: "center", justifyContent: "center", height: "120px", color: MUTED2, fontSize: "13px" }, children: [
9202
9281
  "No content available for ",
9203
9282
  (_u = page == null ? void 0 : page.label) != null ? _u : "this page"
9204
9283
  ] }),
@@ -11777,6 +11856,7 @@ function isExpirySoon(expiresAt) {
11777
11856
 
11778
11857
  // src/shared/viewers/PreviewHost.tsx
11779
11858
  init_ThemeContext();
11859
+ init_pdfWorkerProbe();
11780
11860
  var PdfViewer3 = React45.lazy(
11781
11861
  () => Promise.resolve().then(() => (init_PdfViewer(), PdfViewer_exports)).then((m) => ({ default: m.PdfViewer }))
11782
11862
  );
@@ -11788,6 +11868,19 @@ var TextViewer2 = React45.lazy(() => Promise.resolve().then(() => (init_TextView
11788
11868
  var DocxViewer2 = React45.lazy(() => Promise.resolve().then(() => (init_DocxViewer(), DocxViewer_exports)).then((m) => ({ default: m.DocxViewer })));
11789
11869
  var PEEK_ROWS = 20;
11790
11870
  var PEEK_LINES = 40;
11871
+ function GatedPdfViewer({ source }) {
11872
+ const { MUTED: MUTED2 } = useTheme();
11873
+ const [failed, setFailed] = React45.useState(false);
11874
+ const workerReady = usePdfWorkerReady(true);
11875
+ const ready = failed ? false : workerReady;
11876
+ if (ready === null) {
11877
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { style: { padding: "24px", color: MUTED2, fontSize: "13px", textAlign: "center" }, children: "Loading preview\u2026" });
11878
+ }
11879
+ if (ready === false) {
11880
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { style: { padding: "24px", color: MUTED2, fontSize: "13px", textAlign: "center" }, children: "Preview unavailable \u2014 download the file to view it." });
11881
+ }
11882
+ return /* @__PURE__ */ jsxRuntime.jsx(PdfViewer3, { url: source.url, base64: source.base64, onLoadError: () => setFailed(true) });
11883
+ }
11791
11884
  function PreviewHost({ kind, source, mode = "full" }) {
11792
11885
  const { MUTED: MUTED2 } = useTheme();
11793
11886
  const peek = mode === "peek";
@@ -11795,7 +11888,7 @@ function PreviewHost({ kind, source, mode = "full" }) {
11795
11888
  let viewer = null;
11796
11889
  switch (kind) {
11797
11890
  case "pdf":
11798
- viewer = /* @__PURE__ */ jsxRuntime.jsx(PdfViewer3, { url: source.url, base64: source.base64 });
11891
+ viewer = /* @__PURE__ */ jsxRuntime.jsx(GatedPdfViewer, { source });
11799
11892
  break;
11800
11893
  case "excel":
11801
11894
  viewer = /* @__PURE__ */ jsxRuntime.jsx(ExcelViewer3, { url: source.url, base64: source.base64 });