pxengine 0.1.82 → 0.1.84
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/index.cjs +111 -114
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +4 -9
- package/dist/index.d.ts +4 -9
- package/dist/index.mjs +111 -114
- package/dist/index.mjs.map +1 -1
- package/dist/registry.json +4 -5
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -39096,8 +39096,9 @@ var ExportModal = ({ formats, title, onClose }) => {
|
|
|
39096
39096
|
] })
|
|
39097
39097
|
] });
|
|
39098
39098
|
};
|
|
39099
|
-
var FullscreenModal = ({ url, title, slideCount, onClose }) => {
|
|
39100
|
-
const [currentSlide, setCurrentSlide] = (0, import_react75.useState)(
|
|
39099
|
+
var FullscreenModal = ({ url, title, slideCount, initialSlide = 1, onClose }) => {
|
|
39100
|
+
const [currentSlide, setCurrentSlide] = (0, import_react75.useState)(initialSlide);
|
|
39101
|
+
const [iframeReady, setIframeReady] = (0, import_react75.useState)(false);
|
|
39101
39102
|
const iframeRef = (0, import_react75.useRef)(null);
|
|
39102
39103
|
(0, import_react75.useEffect)(() => {
|
|
39103
39104
|
const onKey = (e) => {
|
|
@@ -39105,7 +39106,10 @@ var FullscreenModal = ({ url, title, slideCount, onClose }) => {
|
|
|
39105
39106
|
};
|
|
39106
39107
|
const onMsg = (e) => {
|
|
39107
39108
|
if (e.data?.type === "presentationExit") onClose();
|
|
39108
|
-
if (e.data?.type === "slideChanged")
|
|
39109
|
+
if (e.data?.type === "slideChanged") {
|
|
39110
|
+
setCurrentSlide(e.data.slide);
|
|
39111
|
+
if (!iframeReady) setIframeReady(true);
|
|
39112
|
+
}
|
|
39109
39113
|
};
|
|
39110
39114
|
document.addEventListener("keydown", onKey);
|
|
39111
39115
|
window.addEventListener("message", onMsg);
|
|
@@ -39113,14 +39117,26 @@ var FullscreenModal = ({ url, title, slideCount, onClose }) => {
|
|
|
39113
39117
|
document.removeEventListener("keydown", onKey);
|
|
39114
39118
|
window.removeEventListener("message", onMsg);
|
|
39115
39119
|
};
|
|
39116
|
-
}, [onClose]);
|
|
39120
|
+
}, [onClose, iframeReady]);
|
|
39117
39121
|
(0, import_react75.useEffect)(() => {
|
|
39118
39122
|
document.body.style.overflow = "hidden";
|
|
39119
39123
|
return () => {
|
|
39120
39124
|
document.body.style.overflow = "";
|
|
39121
39125
|
};
|
|
39122
39126
|
}, []);
|
|
39123
|
-
const
|
|
39127
|
+
const sendSlideCommand = (command) => {
|
|
39128
|
+
const iframe = iframeRef.current;
|
|
39129
|
+
if (!iframe?.contentWindow) return;
|
|
39130
|
+
const totalSlides = slideCount || 1;
|
|
39131
|
+
let newSlide = currentSlide;
|
|
39132
|
+
if (command === "nextSlide") {
|
|
39133
|
+
newSlide = currentSlide >= totalSlides ? 1 : currentSlide + 1;
|
|
39134
|
+
} else {
|
|
39135
|
+
newSlide = currentSlide <= 1 ? totalSlides : currentSlide - 1;
|
|
39136
|
+
}
|
|
39137
|
+
setCurrentSlide(newSlide);
|
|
39138
|
+
iframe.contentWindow.postMessage({ type: command }, "*");
|
|
39139
|
+
};
|
|
39124
39140
|
return /* @__PURE__ */ (0, import_jsx_runtime147.jsxs)("div", { className: "fixed inset-0 z-50 bg-black flex flex-col", children: [
|
|
39125
39141
|
/* @__PURE__ */ (0, import_jsx_runtime147.jsxs)("div", { className: "flex items-center justify-between gap-4 px-4 h-11 bg-zinc-950/90 border-b border-zinc-800/60 flex-shrink-0", children: [
|
|
39126
39142
|
/* @__PURE__ */ (0, import_jsx_runtime147.jsxs)("div", { className: "flex items-center gap-3 min-w-0", children: [
|
|
@@ -39136,8 +39152,9 @@ var FullscreenModal = ({ url, title, slideCount, onClose }) => {
|
|
|
39136
39152
|
/* @__PURE__ */ (0, import_jsx_runtime147.jsx)(
|
|
39137
39153
|
"button",
|
|
39138
39154
|
{
|
|
39139
|
-
onClick: () =>
|
|
39140
|
-
|
|
39155
|
+
onClick: () => sendSlideCommand("prevSlide"),
|
|
39156
|
+
disabled: !iframeReady,
|
|
39157
|
+
className: "w-7 h-7 rounded-full border border-zinc-700 bg-zinc-800 hover:border-indigo-500 hover:text-indigo-400 text-zinc-400 flex items-center justify-center transition-colors disabled:opacity-30 disabled:cursor-not-allowed",
|
|
39141
39158
|
"aria-label": "Previous slide",
|
|
39142
39159
|
children: /* @__PURE__ */ (0, import_jsx_runtime147.jsx)(ChevronLeft2, {})
|
|
39143
39160
|
}
|
|
@@ -39145,8 +39162,9 @@ var FullscreenModal = ({ url, title, slideCount, onClose }) => {
|
|
|
39145
39162
|
/* @__PURE__ */ (0, import_jsx_runtime147.jsx)(
|
|
39146
39163
|
"button",
|
|
39147
39164
|
{
|
|
39148
|
-
onClick: () =>
|
|
39149
|
-
|
|
39165
|
+
onClick: () => sendSlideCommand("nextSlide"),
|
|
39166
|
+
disabled: !iframeReady,
|
|
39167
|
+
className: "w-7 h-7 rounded-full border border-zinc-700 bg-zinc-800 hover:border-indigo-500 hover:text-indigo-400 text-zinc-400 flex items-center justify-center transition-colors disabled:opacity-30 disabled:cursor-not-allowed",
|
|
39150
39168
|
"aria-label": "Next slide",
|
|
39151
39169
|
children: /* @__PURE__ */ (0, import_jsx_runtime147.jsx)(ChevronRight2, {})
|
|
39152
39170
|
}
|
|
@@ -39170,7 +39188,10 @@ var FullscreenModal = ({ url, title, slideCount, onClose }) => {
|
|
|
39170
39188
|
ref: iframeRef,
|
|
39171
39189
|
src: url,
|
|
39172
39190
|
title,
|
|
39173
|
-
onLoad: () =>
|
|
39191
|
+
onLoad: () => {
|
|
39192
|
+
setIframeReady(true);
|
|
39193
|
+
iframeRef.current?.contentWindow?.postMessage({ type: "goToSlide", slide: initialSlide }, "*");
|
|
39194
|
+
},
|
|
39174
39195
|
sandbox: "allow-same-origin allow-scripts allow-fullscreen",
|
|
39175
39196
|
className: "absolute inset-0 w-full h-full border-0"
|
|
39176
39197
|
}
|
|
@@ -39201,6 +39222,7 @@ var PresentationJobCard = ({
|
|
|
39201
39222
|
const [copied, setCopied] = (0, import_react75.useState)(false);
|
|
39202
39223
|
const [currentSlide, setCurrentSlide] = (0, import_react75.useState)(1);
|
|
39203
39224
|
const [previewScale, setPreviewScale] = (0, import_react75.useState)(1);
|
|
39225
|
+
const [iframeReady, setIframeReady] = (0, import_react75.useState)(false);
|
|
39204
39226
|
const intervalRef = (0, import_react75.useRef)(null);
|
|
39205
39227
|
const previewRef = (0, import_react75.useRef)(null);
|
|
39206
39228
|
const iframeRef = (0, import_react75.useRef)(null);
|
|
@@ -39209,6 +39231,7 @@ var PresentationJobCard = ({
|
|
|
39209
39231
|
}, []);
|
|
39210
39232
|
(0, import_react75.useEffect)(() => {
|
|
39211
39233
|
updateScale();
|
|
39234
|
+
setIframeReady(false);
|
|
39212
39235
|
if (typeof ResizeObserver === "undefined") return;
|
|
39213
39236
|
const ro = new ResizeObserver(updateScale);
|
|
39214
39237
|
if (previewRef.current) ro.observe(previewRef.current);
|
|
@@ -39219,13 +39242,24 @@ var PresentationJobCard = ({
|
|
|
39219
39242
|
if (e.data?.type === "slideChanged") {
|
|
39220
39243
|
setCurrentSlide(e.data.slide);
|
|
39221
39244
|
if (e.data.total && !slideCount) setSlideCount(e.data.total);
|
|
39245
|
+
if (!iframeReady) setIframeReady(true);
|
|
39222
39246
|
}
|
|
39223
39247
|
};
|
|
39224
39248
|
window.addEventListener("message", handler);
|
|
39225
39249
|
return () => window.removeEventListener("message", handler);
|
|
39226
|
-
}, [slideCount]);
|
|
39250
|
+
}, [slideCount, iframeReady]);
|
|
39227
39251
|
const sendSlideCommand = (command) => {
|
|
39228
|
-
iframeRef.current
|
|
39252
|
+
const iframe = iframeRef.current;
|
|
39253
|
+
if (!iframe?.contentWindow) return;
|
|
39254
|
+
const totalSlides = slideCount || 1;
|
|
39255
|
+
let newSlide = currentSlide;
|
|
39256
|
+
if (command === "nextSlide") {
|
|
39257
|
+
newSlide = currentSlide >= totalSlides ? 1 : currentSlide + 1;
|
|
39258
|
+
} else {
|
|
39259
|
+
newSlide = currentSlide <= 1 ? totalSlides : currentSlide - 1;
|
|
39260
|
+
}
|
|
39261
|
+
setCurrentSlide(newSlide);
|
|
39262
|
+
iframe.contentWindow.postMessage({ type: command }, "*");
|
|
39229
39263
|
};
|
|
39230
39264
|
const isTerminal = status === "complete" || status === "failed";
|
|
39231
39265
|
const onCompleteRef = (0, import_react75.useRef)(onComplete);
|
|
@@ -39388,6 +39422,7 @@ var PresentationJobCard = ({
|
|
|
39388
39422
|
src: formats.html_url,
|
|
39389
39423
|
title,
|
|
39390
39424
|
sandbox: "allow-same-origin allow-scripts",
|
|
39425
|
+
onLoad: () => setIframeReady(true),
|
|
39391
39426
|
style: {
|
|
39392
39427
|
width: 1280,
|
|
39393
39428
|
height: 720,
|
|
@@ -39414,7 +39449,7 @@ var PresentationJobCard = ({
|
|
|
39414
39449
|
e.stopPropagation();
|
|
39415
39450
|
sendSlideCommand("prevSlide");
|
|
39416
39451
|
},
|
|
39417
|
-
disabled: !hasHtml,
|
|
39452
|
+
disabled: !hasHtml || !iframeReady,
|
|
39418
39453
|
className: "w-7 h-7 rounded-full border border-zinc-700 bg-zinc-800 hover:border-indigo-500 hover:text-indigo-400 text-zinc-400 flex items-center justify-center transition-colors disabled:opacity-30 disabled:cursor-not-allowed",
|
|
39419
39454
|
"aria-label": "Previous slide",
|
|
39420
39455
|
children: /* @__PURE__ */ (0, import_jsx_runtime147.jsx)(ChevronLeft2, {})
|
|
@@ -39432,7 +39467,7 @@ var PresentationJobCard = ({
|
|
|
39432
39467
|
e.stopPropagation();
|
|
39433
39468
|
sendSlideCommand("nextSlide");
|
|
39434
39469
|
},
|
|
39435
|
-
disabled: !hasHtml,
|
|
39470
|
+
disabled: !hasHtml || !iframeReady,
|
|
39436
39471
|
className: "w-7 h-7 rounded-full border border-zinc-700 bg-zinc-800 hover:border-indigo-500 hover:text-indigo-400 text-zinc-400 flex items-center justify-center transition-colors disabled:opacity-30 disabled:cursor-not-allowed",
|
|
39437
39472
|
"aria-label": "Next slide",
|
|
39438
39473
|
children: /* @__PURE__ */ (0, import_jsx_runtime147.jsx)(ChevronRight2, {})
|
|
@@ -39449,6 +39484,7 @@ var PresentationJobCard = ({
|
|
|
39449
39484
|
url: formats.html_url,
|
|
39450
39485
|
title,
|
|
39451
39486
|
slideCount,
|
|
39487
|
+
initialSlide: currentSlide,
|
|
39452
39488
|
onClose: () => setShowFullscreen(false)
|
|
39453
39489
|
}
|
|
39454
39490
|
)
|
|
@@ -39485,94 +39521,6 @@ var ExpandIcon2 = () => /* @__PURE__ */ (0, import_jsx_runtime148.jsxs)("svg", {
|
|
|
39485
39521
|
/* @__PURE__ */ (0, import_jsx_runtime148.jsx)("line", { x1: "21", y1: "3", x2: "14", y2: "10" }),
|
|
39486
39522
|
/* @__PURE__ */ (0, import_jsx_runtime148.jsx)("line", { x1: "3", y1: "21", x2: "10", y2: "14" })
|
|
39487
39523
|
] });
|
|
39488
|
-
var FORMATS2 = [
|
|
39489
|
-
{
|
|
39490
|
-
key: "pdf_url",
|
|
39491
|
-
label: "PDF",
|
|
39492
|
-
ext: ".pdf",
|
|
39493
|
-
emoji: "\u{1F4C4}",
|
|
39494
|
-
desc: "Professional formatted report \u2014 open in any PDF viewer",
|
|
39495
|
-
accent: { text: "text-red-400", bg: "bg-red-500/10 border-red-500/20" }
|
|
39496
|
-
},
|
|
39497
|
-
{
|
|
39498
|
-
key: "html_url",
|
|
39499
|
-
label: "HTML",
|
|
39500
|
-
ext: ".html",
|
|
39501
|
-
emoji: "\u{1F310}",
|
|
39502
|
-
desc: "Interactive web version \u2014 open in any browser",
|
|
39503
|
-
accent: { text: "text-blue-400", bg: "bg-blue-500/10 border-blue-500/20" }
|
|
39504
|
-
}
|
|
39505
|
-
];
|
|
39506
|
-
var ExportModal2 = ({ formats, title, onClose }) => {
|
|
39507
|
-
const available = FORMATS2.filter((f) => formats[f.key]);
|
|
39508
|
-
const filename = title.replace(/[^a-z0-9]/gi, "-").toLowerCase();
|
|
39509
|
-
const [downloadingKey, setDownloadingKey] = (0, import_react76.useState)(null);
|
|
39510
|
-
const handleDownload = async (fmtKey, url, ext) => {
|
|
39511
|
-
if (downloadingKey) return;
|
|
39512
|
-
const downloadName = `${filename}${ext}`;
|
|
39513
|
-
const href = `/api/download?url=${encodeURIComponent(url)}&filename=${encodeURIComponent(downloadName)}`;
|
|
39514
|
-
try {
|
|
39515
|
-
setDownloadingKey(fmtKey);
|
|
39516
|
-
const response = await fetch(href);
|
|
39517
|
-
if (!response.ok) throw new Error(`status ${response.status}`);
|
|
39518
|
-
const blob = await response.blob();
|
|
39519
|
-
const objectUrl = window.URL.createObjectURL(blob);
|
|
39520
|
-
const anchor = document.createElement("a");
|
|
39521
|
-
anchor.href = objectUrl;
|
|
39522
|
-
anchor.download = downloadName;
|
|
39523
|
-
document.body.appendChild(anchor);
|
|
39524
|
-
anchor.click();
|
|
39525
|
-
anchor.remove();
|
|
39526
|
-
window.URL.revokeObjectURL(objectUrl);
|
|
39527
|
-
} catch {
|
|
39528
|
-
window.open(href, "_blank", "noopener,noreferrer");
|
|
39529
|
-
} finally {
|
|
39530
|
-
setDownloadingKey(null);
|
|
39531
|
-
}
|
|
39532
|
-
};
|
|
39533
|
-
return /* @__PURE__ */ (0, import_jsx_runtime148.jsxs)("div", { className: "fixed inset-0 z-50 flex items-center justify-center p-4", children: [
|
|
39534
|
-
/* @__PURE__ */ (0, import_jsx_runtime148.jsx)("div", { className: "absolute inset-0 bg-black/70 backdrop-blur-sm", onClick: onClose }),
|
|
39535
|
-
/* @__PURE__ */ (0, import_jsx_runtime148.jsxs)("div", { className: "relative z-10 bg-zinc-900 border border-zinc-800 rounded-2xl w-full max-w-sm p-6 shadow-2xl", children: [
|
|
39536
|
-
/* @__PURE__ */ (0, import_jsx_runtime148.jsxs)("div", { className: "flex items-start justify-between mb-5", children: [
|
|
39537
|
-
/* @__PURE__ */ (0, import_jsx_runtime148.jsxs)("div", { className: "min-w-0 pr-3", children: [
|
|
39538
|
-
/* @__PURE__ */ (0, import_jsx_runtime148.jsx)("h3", { className: "text-sm font-semibold text-zinc-100", children: "Download Report" }),
|
|
39539
|
-
/* @__PURE__ */ (0, import_jsx_runtime148.jsx)("p", { className: "text-xs text-zinc-500 mt-0.5 truncate", children: title })
|
|
39540
|
-
] }),
|
|
39541
|
-
/* @__PURE__ */ (0, import_jsx_runtime148.jsx)("button", { onClick: onClose, className: "text-zinc-500 hover:text-zinc-200 transition-colors flex-shrink-0 mt-0.5", children: /* @__PURE__ */ (0, import_jsx_runtime148.jsx)(CloseIcon2, {}) })
|
|
39542
|
-
] }),
|
|
39543
|
-
/* @__PURE__ */ (0, import_jsx_runtime148.jsxs)("div", { className: "space-y-2.5", children: [
|
|
39544
|
-
available.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime148.jsx)("p", { className: "text-sm text-zinc-500 text-center py-6", children: "No formats available yet" }),
|
|
39545
|
-
available.map((fmt) => {
|
|
39546
|
-
const url = formats[fmt.key];
|
|
39547
|
-
const isDownloading = downloadingKey === fmt.key;
|
|
39548
|
-
return /* @__PURE__ */ (0, import_jsx_runtime148.jsxs)(
|
|
39549
|
-
"button",
|
|
39550
|
-
{
|
|
39551
|
-
type: "button",
|
|
39552
|
-
disabled: Boolean(downloadingKey),
|
|
39553
|
-
onClick: () => handleDownload(fmt.key, url, fmt.ext),
|
|
39554
|
-
className: cn(
|
|
39555
|
-
"flex w-full items-center gap-3.5 p-3.5 rounded-xl border transition-all text-left",
|
|
39556
|
-
"hover:brightness-110 disabled:opacity-60 disabled:cursor-not-allowed",
|
|
39557
|
-
fmt.accent.bg
|
|
39558
|
-
),
|
|
39559
|
-
children: [
|
|
39560
|
-
/* @__PURE__ */ (0, import_jsx_runtime148.jsx)("span", { className: "text-xl flex-shrink-0", children: fmt.emoji }),
|
|
39561
|
-
/* @__PURE__ */ (0, import_jsx_runtime148.jsxs)("div", { className: "flex-1 min-w-0", children: [
|
|
39562
|
-
/* @__PURE__ */ (0, import_jsx_runtime148.jsx)("p", { className: cn("text-sm font-semibold", fmt.accent.text), children: isDownloading ? `Downloading ${fmt.label}...` : fmt.label }),
|
|
39563
|
-
/* @__PURE__ */ (0, import_jsx_runtime148.jsx)("p", { className: "text-xs text-zinc-500 mt-0.5 leading-relaxed", children: isDownloading ? "Please wait while the file is being prepared." : fmt.desc })
|
|
39564
|
-
] }),
|
|
39565
|
-
/* @__PURE__ */ (0, import_jsx_runtime148.jsx)("span", { className: cn("flex-shrink-0", fmt.accent.text), children: /* @__PURE__ */ (0, import_jsx_runtime148.jsx)(DownloadIcon2, {}) })
|
|
39566
|
-
]
|
|
39567
|
-
},
|
|
39568
|
-
fmt.key
|
|
39569
|
-
);
|
|
39570
|
-
})
|
|
39571
|
-
] }),
|
|
39572
|
-
/* @__PURE__ */ (0, import_jsx_runtime148.jsx)("p", { className: "text-xs text-zinc-600 mt-4 text-center", children: "Download links expire in 7 days" })
|
|
39573
|
-
] })
|
|
39574
|
-
] });
|
|
39575
|
-
};
|
|
39576
39524
|
var FullscreenPreviewModal = ({ url, title, onClose }) => {
|
|
39577
39525
|
(0, import_react76.useEffect)(() => {
|
|
39578
39526
|
const onKey = (e) => {
|
|
@@ -39627,7 +39575,7 @@ var ResearchReportJobCard = ({
|
|
|
39627
39575
|
word_count: initialWordCount,
|
|
39628
39576
|
executive_summary: initialSummary,
|
|
39629
39577
|
key_findings: _initialFindings,
|
|
39630
|
-
|
|
39578
|
+
html_url: initialHtmlUrl,
|
|
39631
39579
|
theme: initialTheme,
|
|
39632
39580
|
error: initialError,
|
|
39633
39581
|
pollUrl,
|
|
@@ -39643,10 +39591,9 @@ var ResearchReportJobCard = ({
|
|
|
39643
39591
|
const [sourceCount, setSourceCount] = (0, import_react76.useState)(initialSourceCount ?? 0);
|
|
39644
39592
|
const [wordCount, setWordCount] = (0, import_react76.useState)(initialWordCount ?? 0);
|
|
39645
39593
|
const [summary, setSummary] = (0, import_react76.useState)(initialSummary || "");
|
|
39646
|
-
const [
|
|
39594
|
+
const [htmlUrl, setHtmlUrl] = (0, import_react76.useState)(initialHtmlUrl || "");
|
|
39647
39595
|
const [theme, setTheme] = (0, import_react76.useState)(initialTheme || DEFAULT_THEME);
|
|
39648
39596
|
const [error, setError] = (0, import_react76.useState)(initialError);
|
|
39649
|
-
const [showExport, setShowExport] = (0, import_react76.useState)(false);
|
|
39650
39597
|
const [showPreview, setShowPreview] = (0, import_react76.useState)(false);
|
|
39651
39598
|
const [previewScale, setPreviewScale] = (0, import_react76.useState)(1);
|
|
39652
39599
|
const previewRef = (0, import_react76.useRef)(null);
|
|
@@ -39656,9 +39603,39 @@ var ResearchReportJobCard = ({
|
|
|
39656
39603
|
const hasNotifiedRef = (0, import_react76.useRef)(false);
|
|
39657
39604
|
onCompleteRef.current = onComplete;
|
|
39658
39605
|
onFailedRef.current = onFailed;
|
|
39606
|
+
(0, import_react76.useEffect)(() => {
|
|
39607
|
+
setStatus(initialStatus);
|
|
39608
|
+
}, [initialStatus]);
|
|
39609
|
+
(0, import_react76.useEffect)(() => {
|
|
39610
|
+
if (initialTitle) setTitle(initialTitle);
|
|
39611
|
+
}, [initialTitle]);
|
|
39612
|
+
(0, import_react76.useEffect)(() => {
|
|
39613
|
+
if (initialHtmlUrl) setHtmlUrl(initialHtmlUrl);
|
|
39614
|
+
}, [initialHtmlUrl]);
|
|
39615
|
+
(0, import_react76.useEffect)(() => {
|
|
39616
|
+
if (initialDepth) setDepth(initialDepth);
|
|
39617
|
+
}, [initialDepth]);
|
|
39618
|
+
(0, import_react76.useEffect)(() => {
|
|
39619
|
+
if (initialSectionCount !== void 0) setSectionCount(initialSectionCount);
|
|
39620
|
+
}, [initialSectionCount]);
|
|
39621
|
+
(0, import_react76.useEffect)(() => {
|
|
39622
|
+
if (initialSourceCount !== void 0) setSourceCount(initialSourceCount);
|
|
39623
|
+
}, [initialSourceCount]);
|
|
39624
|
+
(0, import_react76.useEffect)(() => {
|
|
39625
|
+
if (initialWordCount !== void 0) setWordCount(initialWordCount);
|
|
39626
|
+
}, [initialWordCount]);
|
|
39627
|
+
(0, import_react76.useEffect)(() => {
|
|
39628
|
+
if (initialSummary) setSummary(initialSummary);
|
|
39629
|
+
}, [initialSummary]);
|
|
39630
|
+
(0, import_react76.useEffect)(() => {
|
|
39631
|
+
if (initialTheme) setTheme(initialTheme);
|
|
39632
|
+
}, [initialTheme]);
|
|
39633
|
+
(0, import_react76.useEffect)(() => {
|
|
39634
|
+
if (initialError) setError(initialError);
|
|
39635
|
+
}, [initialError]);
|
|
39659
39636
|
const isTerminal = status === "complete" || status === "failed";
|
|
39660
39637
|
const primaryColor = theme?.primary || DEFAULT_THEME.primary;
|
|
39661
|
-
const hasHTML = Boolean(
|
|
39638
|
+
const hasHTML = Boolean(htmlUrl);
|
|
39662
39639
|
const updateScale = (0, import_react76.useCallback)(() => {
|
|
39663
39640
|
if (previewRef.current) {
|
|
39664
39641
|
setPreviewScale(previewRef.current.offsetWidth / 800);
|
|
@@ -39670,7 +39647,7 @@ var ResearchReportJobCard = ({
|
|
|
39670
39647
|
const ro = new ResizeObserver(updateScale);
|
|
39671
39648
|
if (previewRef.current) ro.observe(previewRef.current);
|
|
39672
39649
|
return () => ro.disconnect();
|
|
39673
|
-
}, [updateScale,
|
|
39650
|
+
}, [updateScale, htmlUrl]);
|
|
39674
39651
|
(0, import_react76.useEffect)(() => {
|
|
39675
39652
|
if (isTerminal || !pollUrl) return;
|
|
39676
39653
|
const poll = async () => {
|
|
@@ -39692,7 +39669,7 @@ var ResearchReportJobCard = ({
|
|
|
39692
39669
|
setSourceCount(output.source_count || 0);
|
|
39693
39670
|
setWordCount(output.word_count || 0);
|
|
39694
39671
|
setSummary(output.executive_summary || "");
|
|
39695
|
-
|
|
39672
|
+
setHtmlUrl(output.html_url || "");
|
|
39696
39673
|
if (output.theme) {
|
|
39697
39674
|
setTheme(output.theme);
|
|
39698
39675
|
}
|
|
@@ -39753,6 +39730,26 @@ var ResearchReportJobCard = ({
|
|
|
39753
39730
|
] })
|
|
39754
39731
|
] }) }) });
|
|
39755
39732
|
}
|
|
39733
|
+
const handleDownload = async () => {
|
|
39734
|
+
if (!htmlUrl) return;
|
|
39735
|
+
const filename = `${title.replace(/[^a-z0-9]/gi, "-").toLowerCase()}.html`;
|
|
39736
|
+
const href = `/api/download?url=${encodeURIComponent(htmlUrl)}&filename=${encodeURIComponent(filename)}`;
|
|
39737
|
+
try {
|
|
39738
|
+
const response = await fetch(href);
|
|
39739
|
+
if (!response.ok) throw new Error(`status ${response.status}`);
|
|
39740
|
+
const blob = await response.blob();
|
|
39741
|
+
const objectUrl = window.URL.createObjectURL(blob);
|
|
39742
|
+
const anchor = document.createElement("a");
|
|
39743
|
+
anchor.href = objectUrl;
|
|
39744
|
+
anchor.download = filename;
|
|
39745
|
+
document.body.appendChild(anchor);
|
|
39746
|
+
anchor.click();
|
|
39747
|
+
anchor.remove();
|
|
39748
|
+
window.URL.revokeObjectURL(objectUrl);
|
|
39749
|
+
} catch {
|
|
39750
|
+
window.open(htmlUrl, "_blank", "noopener,noreferrer");
|
|
39751
|
+
}
|
|
39752
|
+
};
|
|
39756
39753
|
return /* @__PURE__ */ (0, import_jsx_runtime148.jsxs)(import_jsx_runtime148.Fragment, { children: [
|
|
39757
39754
|
/* @__PURE__ */ (0, import_jsx_runtime148.jsx)("div", { className: cn("w-full", className), children: /* @__PURE__ */ (0, import_jsx_runtime148.jsxs)("div", { className: "bg-zinc-900 border border-zinc-800 rounded-2xl overflow-hidden", children: [
|
|
39758
39755
|
/* @__PURE__ */ (0, import_jsx_runtime148.jsx)(
|
|
@@ -39806,14 +39803,15 @@ var ResearchReportJobCard = ({
|
|
|
39806
39803
|
/* @__PURE__ */ (0, import_jsx_runtime148.jsxs)(
|
|
39807
39804
|
"button",
|
|
39808
39805
|
{
|
|
39809
|
-
onClick:
|
|
39810
|
-
|
|
39806
|
+
onClick: handleDownload,
|
|
39807
|
+
disabled: !hasHTML,
|
|
39808
|
+
className: "flex items-center gap-1.5 px-2.5 h-7 text-white text-xs font-medium rounded-lg transition-colors disabled:opacity-50 disabled:cursor-not-allowed",
|
|
39811
39809
|
style: { backgroundColor: primaryColor },
|
|
39812
39810
|
onMouseEnter: (e) => e.currentTarget.style.filter = "brightness(1.15)",
|
|
39813
39811
|
onMouseLeave: (e) => e.currentTarget.style.filter = "brightness(1)",
|
|
39814
39812
|
children: [
|
|
39815
39813
|
/* @__PURE__ */ (0, import_jsx_runtime148.jsx)(DownloadIcon2, {}),
|
|
39816
|
-
/* @__PURE__ */ (0, import_jsx_runtime148.jsx)("span", { children: "
|
|
39814
|
+
/* @__PURE__ */ (0, import_jsx_runtime148.jsx)("span", { children: "Download" })
|
|
39817
39815
|
]
|
|
39818
39816
|
}
|
|
39819
39817
|
)
|
|
@@ -39831,7 +39829,7 @@ var ResearchReportJobCard = ({
|
|
|
39831
39829
|
/* @__PURE__ */ (0, import_jsx_runtime148.jsx)(
|
|
39832
39830
|
"iframe",
|
|
39833
39831
|
{
|
|
39834
|
-
src:
|
|
39832
|
+
src: htmlUrl,
|
|
39835
39833
|
title,
|
|
39836
39834
|
sandbox: "allow-same-origin",
|
|
39837
39835
|
style: {
|
|
@@ -39855,11 +39853,10 @@ var ResearchReportJobCard = ({
|
|
|
39855
39853
|
!hasHTML && summary && /* @__PURE__ */ (0, import_jsx_runtime148.jsx)("div", { className: "mt-4 pt-4 border-t border-zinc-800/60", children: /* @__PURE__ */ (0, import_jsx_runtime148.jsx)("p", { className: "text-sm text-zinc-400 leading-relaxed line-clamp-3", children: summary }) })
|
|
39856
39854
|
] })
|
|
39857
39855
|
] }) }),
|
|
39858
|
-
showExport && /* @__PURE__ */ (0, import_jsx_runtime148.jsx)(ExportModal2, { formats, title, onClose: () => setShowExport(false) }),
|
|
39859
39856
|
showPreview && hasHTML && /* @__PURE__ */ (0, import_jsx_runtime148.jsx)(
|
|
39860
39857
|
FullscreenPreviewModal,
|
|
39861
39858
|
{
|
|
39862
|
-
url:
|
|
39859
|
+
url: htmlUrl,
|
|
39863
39860
|
title,
|
|
39864
39861
|
onClose: () => setShowPreview(false)
|
|
39865
39862
|
}
|