pxengine 0.1.74 → 0.1.76
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 +259 -125
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +6 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.mjs +260 -126
- package/dist/index.mjs.map +1 -1
- package/dist/registry.json +6 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -38864,23 +38864,26 @@ var CloseIcon = () => /* @__PURE__ */ (0, import_jsx_runtime146.jsxs)("svg", { w
|
|
|
38864
38864
|
] });
|
|
38865
38865
|
var ChevronLeft2 = () => /* @__PURE__ */ (0, import_jsx_runtime146.jsx)("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ (0, import_jsx_runtime146.jsx)("polyline", { points: "15 18 9 12 15 6" }) });
|
|
38866
38866
|
var ChevronRight2 = () => /* @__PURE__ */ (0, import_jsx_runtime146.jsx)("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ (0, import_jsx_runtime146.jsx)("polyline", { points: "9 18 15 12 9 6" }) });
|
|
38867
|
+
var ExpandIcon = () => /* @__PURE__ */ (0, import_jsx_runtime146.jsxs)("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.2", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
38868
|
+
/* @__PURE__ */ (0, import_jsx_runtime146.jsx)("polyline", { points: "15 3 21 3 21 9" }),
|
|
38869
|
+
/* @__PURE__ */ (0, import_jsx_runtime146.jsx)("polyline", { points: "9 21 3 21 3 15" }),
|
|
38870
|
+
/* @__PURE__ */ (0, import_jsx_runtime146.jsx)("line", { x1: "21", y1: "3", x2: "14", y2: "10" }),
|
|
38871
|
+
/* @__PURE__ */ (0, import_jsx_runtime146.jsx)("line", { x1: "3", y1: "21", x2: "10", y2: "14" })
|
|
38872
|
+
] });
|
|
38873
|
+
var ShareIcon = () => /* @__PURE__ */ (0, import_jsx_runtime146.jsxs)("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.2", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
38874
|
+
/* @__PURE__ */ (0, import_jsx_runtime146.jsx)("path", { d: "M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71" }),
|
|
38875
|
+
/* @__PURE__ */ (0, import_jsx_runtime146.jsx)("path", { d: "M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71" })
|
|
38876
|
+
] });
|
|
38877
|
+
var CheckIcon = () => /* @__PURE__ */ (0, import_jsx_runtime146.jsx)("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ (0, import_jsx_runtime146.jsx)("polyline", { points: "20 6 9 17 4 12" }) });
|
|
38867
38878
|
var Skel = ({ className, style }) => /* @__PURE__ */ (0, import_jsx_runtime146.jsx)("div", { className: cn("animate-pulse rounded-md bg-zinc-800/60", className), style });
|
|
38868
38879
|
var FORMATS = [
|
|
38869
|
-
{
|
|
38870
|
-
key: "pptx_url",
|
|
38871
|
-
label: "PowerPoint",
|
|
38872
|
-
ext: ".pptx",
|
|
38873
|
-
emoji: "\u{1F4CA}",
|
|
38874
|
-
desc: "Editable slides \u2014 open in Microsoft PowerPoint or Google Slides",
|
|
38875
|
-
accent: { text: "text-orange-400", bg: "bg-orange-500/10 border-orange-500/20", pill: "bg-orange-500/15 text-orange-400 border-orange-500/25" }
|
|
38876
|
-
},
|
|
38877
38880
|
{
|
|
38878
38881
|
key: "pdf_url",
|
|
38879
38882
|
label: "PDF",
|
|
38880
38883
|
ext: ".pdf",
|
|
38881
38884
|
emoji: "\u{1F4C4}",
|
|
38882
38885
|
desc: "Print-ready, fixed layout \u2014 open in any PDF viewer",
|
|
38883
|
-
accent: { text: "text-red-400", bg: "bg-red-500/10 border-red-500/20"
|
|
38886
|
+
accent: { text: "text-red-400", bg: "bg-red-500/10 border-red-500/20" }
|
|
38884
38887
|
},
|
|
38885
38888
|
{
|
|
38886
38889
|
key: "html_url",
|
|
@@ -38888,12 +38891,36 @@ var FORMATS = [
|
|
|
38888
38891
|
ext: ".html",
|
|
38889
38892
|
emoji: "\u{1F310}",
|
|
38890
38893
|
desc: "Interactive web presentation \u2014 download and open in browser",
|
|
38891
|
-
accent: { text: "text-indigo-400", bg: "bg-indigo-500/10 border-indigo-500/20"
|
|
38894
|
+
accent: { text: "text-indigo-400", bg: "bg-indigo-500/10 border-indigo-500/20" }
|
|
38892
38895
|
}
|
|
38893
38896
|
];
|
|
38894
38897
|
var ExportModal = ({ formats, title, onClose }) => {
|
|
38895
38898
|
const available = FORMATS.filter((f) => formats[f.key]);
|
|
38896
38899
|
const filename = title.replace(/[^a-z0-9]/gi, "-").toLowerCase();
|
|
38900
|
+
const [downloadingKey, setDownloadingKey] = (0, import_react74.useState)(null);
|
|
38901
|
+
const handleDownload = async (fmtKey, url, ext) => {
|
|
38902
|
+
if (downloadingKey) return;
|
|
38903
|
+
const downloadName = `${filename}${ext}`;
|
|
38904
|
+
const href = `/api/download?url=${encodeURIComponent(url)}&filename=${encodeURIComponent(downloadName)}`;
|
|
38905
|
+
try {
|
|
38906
|
+
setDownloadingKey(fmtKey);
|
|
38907
|
+
const response = await fetch(href);
|
|
38908
|
+
if (!response.ok) throw new Error(`status ${response.status}`);
|
|
38909
|
+
const blob = await response.blob();
|
|
38910
|
+
const objectUrl = window.URL.createObjectURL(blob);
|
|
38911
|
+
const anchor = document.createElement("a");
|
|
38912
|
+
anchor.href = objectUrl;
|
|
38913
|
+
anchor.download = downloadName;
|
|
38914
|
+
document.body.appendChild(anchor);
|
|
38915
|
+
anchor.click();
|
|
38916
|
+
anchor.remove();
|
|
38917
|
+
window.URL.revokeObjectURL(objectUrl);
|
|
38918
|
+
} catch {
|
|
38919
|
+
window.open(href, "_blank", "noopener,noreferrer");
|
|
38920
|
+
} finally {
|
|
38921
|
+
setDownloadingKey(null);
|
|
38922
|
+
}
|
|
38923
|
+
};
|
|
38897
38924
|
return /* @__PURE__ */ (0, import_jsx_runtime146.jsxs)("div", { className: "fixed inset-0 z-50 flex items-center justify-center p-4", children: [
|
|
38898
38925
|
/* @__PURE__ */ (0, import_jsx_runtime146.jsx)("div", { className: "absolute inset-0 bg-black/70 backdrop-blur-sm", onClick: onClose }),
|
|
38899
38926
|
/* @__PURE__ */ (0, import_jsx_runtime146.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: [
|
|
@@ -38902,38 +38929,31 @@ var ExportModal = ({ formats, title, onClose }) => {
|
|
|
38902
38929
|
/* @__PURE__ */ (0, import_jsx_runtime146.jsx)("h3", { className: "text-sm font-semibold text-zinc-100", children: "Export Presentation" }),
|
|
38903
38930
|
/* @__PURE__ */ (0, import_jsx_runtime146.jsx)("p", { className: "text-xs text-zinc-500 mt-0.5 truncate", children: title })
|
|
38904
38931
|
] }),
|
|
38905
|
-
/* @__PURE__ */ (0, import_jsx_runtime146.jsx)(
|
|
38906
|
-
"button",
|
|
38907
|
-
{
|
|
38908
|
-
onClick: onClose,
|
|
38909
|
-
className: "text-zinc-500 hover:text-zinc-200 transition-colors flex-shrink-0 mt-0.5",
|
|
38910
|
-
"aria-label": "Close",
|
|
38911
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime146.jsx)(CloseIcon, {})
|
|
38912
|
-
}
|
|
38913
|
-
)
|
|
38932
|
+
/* @__PURE__ */ (0, import_jsx_runtime146.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_runtime146.jsx)(CloseIcon, {}) })
|
|
38914
38933
|
] }),
|
|
38915
38934
|
/* @__PURE__ */ (0, import_jsx_runtime146.jsxs)("div", { className: "space-y-2.5", children: [
|
|
38916
38935
|
available.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime146.jsx)("p", { className: "text-sm text-zinc-500 text-center py-6", children: "No formats available yet" }),
|
|
38917
38936
|
available.map((fmt) => {
|
|
38918
38937
|
const url = formats[fmt.key];
|
|
38919
|
-
const
|
|
38938
|
+
const isDownloading = downloadingKey === fmt.key;
|
|
38920
38939
|
return /* @__PURE__ */ (0, import_jsx_runtime146.jsxs)(
|
|
38921
|
-
"
|
|
38940
|
+
"button",
|
|
38922
38941
|
{
|
|
38923
|
-
|
|
38924
|
-
|
|
38942
|
+
type: "button",
|
|
38943
|
+
disabled: Boolean(downloadingKey),
|
|
38944
|
+
onClick: () => handleDownload(fmt.key, url, fmt.ext),
|
|
38925
38945
|
className: cn(
|
|
38926
|
-
"flex items-center gap-3.5 p-3.5 rounded-xl border transition-all",
|
|
38927
|
-
"hover:brightness-110
|
|
38946
|
+
"flex w-full items-center gap-3.5 p-3.5 rounded-xl border transition-all text-left",
|
|
38947
|
+
"hover:brightness-110 disabled:opacity-60 disabled:cursor-not-allowed",
|
|
38928
38948
|
fmt.accent.bg
|
|
38929
38949
|
),
|
|
38930
38950
|
children: [
|
|
38931
38951
|
/* @__PURE__ */ (0, import_jsx_runtime146.jsx)("span", { className: "text-xl flex-shrink-0", children: fmt.emoji }),
|
|
38932
38952
|
/* @__PURE__ */ (0, import_jsx_runtime146.jsxs)("div", { className: "flex-1 min-w-0", children: [
|
|
38933
|
-
/* @__PURE__ */ (0, import_jsx_runtime146.jsx)("p", { className: cn("text-sm font-semibold", fmt.accent.text), children: fmt.label }),
|
|
38934
|
-
/* @__PURE__ */ (0, import_jsx_runtime146.jsx)("p", { className: "text-xs text-zinc-500 mt-0.5 leading-relaxed", children: fmt.desc })
|
|
38953
|
+
/* @__PURE__ */ (0, import_jsx_runtime146.jsx)("p", { className: cn("text-sm font-semibold", fmt.accent.text), children: isDownloading ? `Downloading ${fmt.label}...` : fmt.label }),
|
|
38954
|
+
/* @__PURE__ */ (0, import_jsx_runtime146.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 })
|
|
38935
38955
|
] }),
|
|
38936
|
-
/* @__PURE__ */ (0, import_jsx_runtime146.jsx)("span", { className: cn("flex-shrink-0
|
|
38956
|
+
/* @__PURE__ */ (0, import_jsx_runtime146.jsx)("span", { className: cn("flex-shrink-0", fmt.accent.text), children: /* @__PURE__ */ (0, import_jsx_runtime146.jsx)(DownloadIcon, {}) })
|
|
38937
38957
|
]
|
|
38938
38958
|
},
|
|
38939
38959
|
fmt.key
|
|
@@ -38944,6 +38964,87 @@ var ExportModal = ({ formats, title, onClose }) => {
|
|
|
38944
38964
|
] })
|
|
38945
38965
|
] });
|
|
38946
38966
|
};
|
|
38967
|
+
var FullscreenModal = ({ url, title, slideCount, onClose }) => {
|
|
38968
|
+
const [currentSlide, setCurrentSlide] = (0, import_react74.useState)(1);
|
|
38969
|
+
const iframeRef = (0, import_react74.useRef)(null);
|
|
38970
|
+
(0, import_react74.useEffect)(() => {
|
|
38971
|
+
const onKey = (e) => {
|
|
38972
|
+
if (e.key === "Escape") onClose();
|
|
38973
|
+
};
|
|
38974
|
+
const onMsg = (e) => {
|
|
38975
|
+
if (e.data?.type === "presentationExit") onClose();
|
|
38976
|
+
if (e.data?.type === "slideChanged") setCurrentSlide(e.data.slide);
|
|
38977
|
+
};
|
|
38978
|
+
document.addEventListener("keydown", onKey);
|
|
38979
|
+
window.addEventListener("message", onMsg);
|
|
38980
|
+
return () => {
|
|
38981
|
+
document.removeEventListener("keydown", onKey);
|
|
38982
|
+
window.removeEventListener("message", onMsg);
|
|
38983
|
+
};
|
|
38984
|
+
}, [onClose]);
|
|
38985
|
+
(0, import_react74.useEffect)(() => {
|
|
38986
|
+
document.body.style.overflow = "hidden";
|
|
38987
|
+
return () => {
|
|
38988
|
+
document.body.style.overflow = "";
|
|
38989
|
+
};
|
|
38990
|
+
}, []);
|
|
38991
|
+
const send = (type) => iframeRef.current?.contentWindow?.postMessage({ type }, "*");
|
|
38992
|
+
return /* @__PURE__ */ (0, import_jsx_runtime146.jsxs)("div", { className: "fixed inset-0 z-50 bg-black flex flex-col", children: [
|
|
38993
|
+
/* @__PURE__ */ (0, import_jsx_runtime146.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: [
|
|
38994
|
+
/* @__PURE__ */ (0, import_jsx_runtime146.jsxs)("div", { className: "flex items-center gap-3 min-w-0", children: [
|
|
38995
|
+
/* @__PURE__ */ (0, import_jsx_runtime146.jsx)("span", { className: "text-indigo-400 flex-shrink-0", children: /* @__PURE__ */ (0, import_jsx_runtime146.jsx)(SlidesIcon, {}) }),
|
|
38996
|
+
/* @__PURE__ */ (0, import_jsx_runtime146.jsx)("span", { className: "text-sm font-medium text-zinc-300 truncate", children: title }),
|
|
38997
|
+
slideCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime146.jsxs)("span", { className: "text-xs text-zinc-600 flex-shrink-0", children: [
|
|
38998
|
+
currentSlide,
|
|
38999
|
+
" / ",
|
|
39000
|
+
slideCount
|
|
39001
|
+
] })
|
|
39002
|
+
] }),
|
|
39003
|
+
/* @__PURE__ */ (0, import_jsx_runtime146.jsxs)("div", { className: "flex items-center gap-2 flex-shrink-0", children: [
|
|
39004
|
+
/* @__PURE__ */ (0, import_jsx_runtime146.jsx)(
|
|
39005
|
+
"button",
|
|
39006
|
+
{
|
|
39007
|
+
onClick: () => send("prevSlide"),
|
|
39008
|
+
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",
|
|
39009
|
+
"aria-label": "Previous slide",
|
|
39010
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime146.jsx)(ChevronLeft2, {})
|
|
39011
|
+
}
|
|
39012
|
+
),
|
|
39013
|
+
/* @__PURE__ */ (0, import_jsx_runtime146.jsx)(
|
|
39014
|
+
"button",
|
|
39015
|
+
{
|
|
39016
|
+
onClick: () => send("nextSlide"),
|
|
39017
|
+
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",
|
|
39018
|
+
"aria-label": "Next slide",
|
|
39019
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime146.jsx)(ChevronRight2, {})
|
|
39020
|
+
}
|
|
39021
|
+
),
|
|
39022
|
+
/* @__PURE__ */ (0, import_jsx_runtime146.jsxs)(
|
|
39023
|
+
"button",
|
|
39024
|
+
{
|
|
39025
|
+
onClick: onClose,
|
|
39026
|
+
className: "flex items-center gap-1.5 px-3 h-7 rounded-lg border border-zinc-700 bg-zinc-800 hover:border-zinc-500 text-zinc-400 hover:text-zinc-200 text-xs transition-colors",
|
|
39027
|
+
children: [
|
|
39028
|
+
/* @__PURE__ */ (0, import_jsx_runtime146.jsx)(CloseIcon, {}),
|
|
39029
|
+
/* @__PURE__ */ (0, import_jsx_runtime146.jsx)("span", { children: "ESC" })
|
|
39030
|
+
]
|
|
39031
|
+
}
|
|
39032
|
+
)
|
|
39033
|
+
] })
|
|
39034
|
+
] }),
|
|
39035
|
+
/* @__PURE__ */ (0, import_jsx_runtime146.jsx)("div", { className: "flex-1 relative", children: /* @__PURE__ */ (0, import_jsx_runtime146.jsx)(
|
|
39036
|
+
"iframe",
|
|
39037
|
+
{
|
|
39038
|
+
ref: iframeRef,
|
|
39039
|
+
src: url,
|
|
39040
|
+
title,
|
|
39041
|
+
onLoad: () => iframeRef.current?.contentWindow?.postMessage({ type: "goToSlide", slide: currentSlide }, "*"),
|
|
39042
|
+
sandbox: "allow-same-origin allow-scripts allow-fullscreen",
|
|
39043
|
+
className: "absolute inset-0 w-full h-full border-0"
|
|
39044
|
+
}
|
|
39045
|
+
) })
|
|
39046
|
+
] });
|
|
39047
|
+
};
|
|
38947
39048
|
var PresentationJobCard = ({
|
|
38948
39049
|
job_id: _job_id,
|
|
38949
39050
|
title: initialTitle,
|
|
@@ -38952,6 +39053,7 @@ var PresentationJobCard = ({
|
|
|
38952
39053
|
formats: initialFormats = {},
|
|
38953
39054
|
error: initialError,
|
|
38954
39055
|
pollUrl,
|
|
39056
|
+
shareUrl,
|
|
38955
39057
|
className
|
|
38956
39058
|
}) => {
|
|
38957
39059
|
const [status, setStatus] = (0, import_react74.useState)(initialStatus);
|
|
@@ -38959,7 +39061,9 @@ var PresentationJobCard = ({
|
|
|
38959
39061
|
const [slideCount, setSlideCount] = (0, import_react74.useState)(initialSlideCount ?? 0);
|
|
38960
39062
|
const [formats, setFormats] = (0, import_react74.useState)(initialFormats);
|
|
38961
39063
|
const [error, setError] = (0, import_react74.useState)(initialError);
|
|
38962
|
-
const [
|
|
39064
|
+
const [showExport, setShowExport] = (0, import_react74.useState)(false);
|
|
39065
|
+
const [showFullscreen, setShowFullscreen] = (0, import_react74.useState)(false);
|
|
39066
|
+
const [copied, setCopied] = (0, import_react74.useState)(false);
|
|
38963
39067
|
const [currentSlide, setCurrentSlide] = (0, import_react74.useState)(1);
|
|
38964
39068
|
const [previewScale, setPreviewScale] = (0, import_react74.useState)(1);
|
|
38965
39069
|
const [iframeReady, setIframeReady] = (0, import_react74.useState)(false);
|
|
@@ -38968,9 +39072,7 @@ var PresentationJobCard = ({
|
|
|
38968
39072
|
const previewRef = (0, import_react74.useRef)(null);
|
|
38969
39073
|
const iframeRef = (0, import_react74.useRef)(null);
|
|
38970
39074
|
const updateScale = (0, import_react74.useCallback)(() => {
|
|
38971
|
-
if (previewRef.current)
|
|
38972
|
-
setPreviewScale(previewRef.current.offsetWidth / 1280);
|
|
38973
|
-
}
|
|
39075
|
+
if (previewRef.current) setPreviewScale(previewRef.current.offsetWidth / 1280);
|
|
38974
39076
|
}, []);
|
|
38975
39077
|
(0, import_react74.useEffect)(() => {
|
|
38976
39078
|
updateScale();
|
|
@@ -38987,9 +39089,7 @@ var PresentationJobCard = ({
|
|
|
38987
39089
|
const handler = (e) => {
|
|
38988
39090
|
if (e.data?.type === "slideChanged") {
|
|
38989
39091
|
setCurrentSlide(e.data.slide);
|
|
38990
|
-
if (e.data.total && !slideCount)
|
|
38991
|
-
setSlideCount(e.data.total);
|
|
38992
|
-
}
|
|
39092
|
+
if (e.data.total && !slideCount) setSlideCount(e.data.total);
|
|
38993
39093
|
}
|
|
38994
39094
|
};
|
|
38995
39095
|
window.addEventListener("message", handler);
|
|
@@ -39000,6 +39100,10 @@ var PresentationJobCard = ({
|
|
|
39000
39100
|
iframeRef.current?.contentWindow?.postMessage({ type: "goToSlide", slide: pendingSlide }, "*");
|
|
39001
39101
|
setPendingSlide(null);
|
|
39002
39102
|
}, [iframeReady, pendingSlide]);
|
|
39103
|
+
const sendSlideCommand = (command) => {
|
|
39104
|
+
if (!iframeReady) return;
|
|
39105
|
+
iframeRef.current?.contentWindow?.postMessage({ type: command }, "*");
|
|
39106
|
+
};
|
|
39003
39107
|
const goToSlide = (n) => {
|
|
39004
39108
|
const total2 = slideCount || 1;
|
|
39005
39109
|
const target = (n - 1 + total2) % total2 + 1;
|
|
@@ -39025,9 +39129,7 @@ var PresentationJobCard = ({
|
|
|
39025
39129
|
if (data.output.slide_count) setSlideCount(data.output.slide_count);
|
|
39026
39130
|
if (data.output.formats) setFormats(data.output.formats);
|
|
39027
39131
|
}
|
|
39028
|
-
if (newStatus === "failed" && data.error)
|
|
39029
|
-
setError(data.error);
|
|
39030
|
-
}
|
|
39132
|
+
if (newStatus === "failed" && data.error) setError(data.error);
|
|
39031
39133
|
} catch {
|
|
39032
39134
|
}
|
|
39033
39135
|
};
|
|
@@ -39043,6 +39145,17 @@ var PresentationJobCard = ({
|
|
|
39043
39145
|
intervalRef.current = null;
|
|
39044
39146
|
}
|
|
39045
39147
|
}, [isTerminal]);
|
|
39148
|
+
const handleShare = async () => {
|
|
39149
|
+
const link = shareUrl ?? formats.html_url;
|
|
39150
|
+
if (!link) return;
|
|
39151
|
+
try {
|
|
39152
|
+
await navigator.clipboard.writeText(link);
|
|
39153
|
+
setCopied(true);
|
|
39154
|
+
setTimeout(() => setCopied(false), 2e3);
|
|
39155
|
+
} catch {
|
|
39156
|
+
window.open(link, "_blank", "noopener,noreferrer");
|
|
39157
|
+
}
|
|
39158
|
+
};
|
|
39046
39159
|
if (status === "pending" || status === "running") {
|
|
39047
39160
|
return /* @__PURE__ */ (0, import_jsx_runtime146.jsx)("div", { className: cn("w-full", className), children: /* @__PURE__ */ (0, import_jsx_runtime146.jsxs)("div", { className: "bg-zinc-900 border border-zinc-800 rounded-2xl p-5", children: [
|
|
39048
39161
|
/* @__PURE__ */ (0, import_jsx_runtime146.jsxs)("div", { className: "flex items-center gap-3 mb-5", children: [
|
|
@@ -39068,8 +39181,8 @@ var PresentationJobCard = ({
|
|
|
39068
39181
|
] })
|
|
39069
39182
|
] }) }) });
|
|
39070
39183
|
}
|
|
39071
|
-
const availablePills = FORMATS.filter((f) => formats[f.key]);
|
|
39072
39184
|
const total = slideCount || 1;
|
|
39185
|
+
const hasHtml = Boolean(formats.html_url);
|
|
39073
39186
|
return /* @__PURE__ */ (0, import_jsx_runtime146.jsxs)(import_jsx_runtime146.Fragment, { children: [
|
|
39074
39187
|
/* @__PURE__ */ (0, import_jsx_runtime146.jsx)("div", { className: cn("w-full", className), children: /* @__PURE__ */ (0, import_jsx_runtime146.jsxs)("div", { className: "bg-zinc-900 border border-zinc-800 rounded-2xl overflow-hidden", children: [
|
|
39075
39188
|
/* @__PURE__ */ (0, import_jsx_runtime146.jsx)("div", { className: "h-[3px] bg-gradient-to-r from-indigo-600 via-violet-500 to-purple-600" }),
|
|
@@ -39083,106 +39196,127 @@ var PresentationJobCard = ({
|
|
|
39083
39196
|
" \xB7 Ready to export"
|
|
39084
39197
|
] })
|
|
39085
39198
|
] }),
|
|
39086
|
-
/* @__PURE__ */ (0, import_jsx_runtime146.jsxs)(
|
|
39087
|
-
|
|
39088
|
-
|
|
39089
|
-
|
|
39090
|
-
|
|
39091
|
-
|
|
39092
|
-
|
|
39093
|
-
|
|
39094
|
-
|
|
39095
|
-
|
|
39096
|
-
|
|
39199
|
+
/* @__PURE__ */ (0, import_jsx_runtime146.jsxs)("div", { className: "flex items-center gap-1.5 flex-shrink-0", children: [
|
|
39200
|
+
/* @__PURE__ */ (0, import_jsx_runtime146.jsx)(
|
|
39201
|
+
"button",
|
|
39202
|
+
{
|
|
39203
|
+
onClick: handleShare,
|
|
39204
|
+
disabled: !hasHtml,
|
|
39205
|
+
title: copied ? "Copied!" : "Copy shareable link",
|
|
39206
|
+
className: cn(
|
|
39207
|
+
"w-7 h-7 rounded-lg border flex items-center justify-center transition-all",
|
|
39208
|
+
copied ? "border-green-500/40 bg-green-500/10 text-green-400" : "border-zinc-700 bg-zinc-800 text-zinc-400 hover:border-zinc-500 hover:text-zinc-200",
|
|
39209
|
+
"disabled:opacity-30 disabled:cursor-not-allowed"
|
|
39210
|
+
),
|
|
39211
|
+
children: copied ? /* @__PURE__ */ (0, import_jsx_runtime146.jsx)(CheckIcon, {}) : /* @__PURE__ */ (0, import_jsx_runtime146.jsx)(ShareIcon, {})
|
|
39212
|
+
}
|
|
39213
|
+
),
|
|
39214
|
+
/* @__PURE__ */ (0, import_jsx_runtime146.jsxs)(
|
|
39215
|
+
"button",
|
|
39216
|
+
{
|
|
39217
|
+
onClick: () => setShowFullscreen(true),
|
|
39218
|
+
disabled: !hasHtml,
|
|
39219
|
+
title: "Open fullscreen preview",
|
|
39220
|
+
className: "flex items-center gap-1.5 px-2.5 h-7 rounded-lg border border-zinc-700 bg-zinc-800 hover:border-zinc-500 text-zinc-400 hover:text-zinc-200 text-xs font-medium transition-colors disabled:opacity-30 disabled:cursor-not-allowed",
|
|
39221
|
+
children: [
|
|
39222
|
+
/* @__PURE__ */ (0, import_jsx_runtime146.jsx)(ExpandIcon, {}),
|
|
39223
|
+
/* @__PURE__ */ (0, import_jsx_runtime146.jsx)("span", { children: "Preview" })
|
|
39224
|
+
]
|
|
39225
|
+
}
|
|
39226
|
+
),
|
|
39227
|
+
/* @__PURE__ */ (0, import_jsx_runtime146.jsxs)(
|
|
39228
|
+
"button",
|
|
39229
|
+
{
|
|
39230
|
+
onClick: () => setShowExport(true),
|
|
39231
|
+
className: "flex items-center gap-1.5 px-2.5 h-7 bg-indigo-600 hover:bg-indigo-500 active:bg-indigo-700 text-white text-xs font-medium rounded-lg transition-colors",
|
|
39232
|
+
children: [
|
|
39233
|
+
/* @__PURE__ */ (0, import_jsx_runtime146.jsx)(DownloadIcon, {}),
|
|
39234
|
+
/* @__PURE__ */ (0, import_jsx_runtime146.jsx)("span", { children: "Export" })
|
|
39235
|
+
]
|
|
39236
|
+
}
|
|
39237
|
+
)
|
|
39238
|
+
] })
|
|
39097
39239
|
] }),
|
|
39098
|
-
|
|
39099
|
-
/* @__PURE__ */ (0, import_jsx_runtime146.
|
|
39240
|
+
hasHtml && /* @__PURE__ */ (0, import_jsx_runtime146.jsxs)("div", { className: "mt-4", children: [
|
|
39241
|
+
/* @__PURE__ */ (0, import_jsx_runtime146.jsxs)(
|
|
39100
39242
|
"div",
|
|
39101
39243
|
{
|
|
39102
39244
|
ref: previewRef,
|
|
39103
|
-
|
|
39245
|
+
onClick: () => setShowFullscreen(true),
|
|
39246
|
+
className: "group relative overflow-hidden rounded-xl bg-zinc-950 border border-zinc-800/50 cursor-pointer",
|
|
39104
39247
|
style: { height: Math.round(previewScale * 720) },
|
|
39105
|
-
|
|
39106
|
-
|
|
39107
|
-
|
|
39108
|
-
|
|
39109
|
-
|
|
39110
|
-
|
|
39111
|
-
|
|
39112
|
-
|
|
39113
|
-
|
|
39114
|
-
|
|
39115
|
-
|
|
39116
|
-
|
|
39117
|
-
|
|
39118
|
-
|
|
39119
|
-
|
|
39120
|
-
|
|
39248
|
+
title: "Click to open fullscreen",
|
|
39249
|
+
children: [
|
|
39250
|
+
/* @__PURE__ */ (0, import_jsx_runtime146.jsx)(
|
|
39251
|
+
"iframe",
|
|
39252
|
+
{
|
|
39253
|
+
ref: iframeRef,
|
|
39254
|
+
src: formats.html_url,
|
|
39255
|
+
title,
|
|
39256
|
+
onLoad: () => setIframeReady(true),
|
|
39257
|
+
sandbox: "allow-same-origin allow-scripts",
|
|
39258
|
+
style: {
|
|
39259
|
+
width: 1280,
|
|
39260
|
+
height: 720,
|
|
39261
|
+
transform: `scale(${previewScale})`,
|
|
39262
|
+
transformOrigin: "top left",
|
|
39263
|
+
border: "none",
|
|
39264
|
+
pointerEvents: "none",
|
|
39265
|
+
display: "block"
|
|
39266
|
+
}
|
|
39121
39267
|
}
|
|
39122
|
-
|
|
39123
|
-
|
|
39268
|
+
),
|
|
39269
|
+
/* @__PURE__ */ (0, import_jsx_runtime146.jsx)("div", { className: "absolute inset-0 flex items-center justify-center bg-black/0 group-hover:bg-black/30 transition-colors", children: /* @__PURE__ */ (0, import_jsx_runtime146.jsxs)("span", { className: "opacity-0 group-hover:opacity-100 transition-opacity flex items-center gap-2 bg-zinc-900/80 backdrop-blur-sm border border-zinc-700 rounded-lg px-3 py-1.5 text-xs text-zinc-200 font-medium", children: [
|
|
39270
|
+
/* @__PURE__ */ (0, import_jsx_runtime146.jsx)(ExpandIcon, {}),
|
|
39271
|
+
"Open fullscreen"
|
|
39272
|
+
] }) })
|
|
39273
|
+
]
|
|
39124
39274
|
}
|
|
39125
39275
|
),
|
|
39126
|
-
/* @__PURE__ */ (0, import_jsx_runtime146.jsxs)("div", { className: "flex items-center
|
|
39127
|
-
/* @__PURE__ */ (0, import_jsx_runtime146.jsx)(
|
|
39128
|
-
"
|
|
39276
|
+
/* @__PURE__ */ (0, import_jsx_runtime146.jsxs)("div", { className: "flex items-center gap-2 mt-3", children: [
|
|
39277
|
+
/* @__PURE__ */ (0, import_jsx_runtime146.jsx)(
|
|
39278
|
+
"button",
|
|
39129
39279
|
{
|
|
39130
|
-
|
|
39131
|
-
|
|
39132
|
-
|
|
39133
|
-
|
|
39134
|
-
|
|
39135
|
-
|
|
39136
|
-
|
|
39137
|
-
|
|
39138
|
-
|
|
39139
|
-
/* @__PURE__ */ (0, import_jsx_runtime146.jsx)(
|
|
39140
|
-
"button",
|
|
39141
|
-
{
|
|
39142
|
-
onClick: () => goToSlide(currentSlide - 1),
|
|
39143
|
-
disabled: total <= 1,
|
|
39144
|
-
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",
|
|
39145
|
-
"aria-label": "Previous slide",
|
|
39146
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime146.jsx)(ChevronLeft2, {})
|
|
39147
|
-
}
|
|
39148
|
-
),
|
|
39149
|
-
/* @__PURE__ */ (0, import_jsx_runtime146.jsxs)("span", { className: "text-xs text-zinc-500 font-medium tabular-nums min-w-[3rem] text-center", children: [
|
|
39150
|
-
currentSlide,
|
|
39151
|
-
" / ",
|
|
39152
|
-
total
|
|
39153
|
-
] }),
|
|
39154
|
-
/* @__PURE__ */ (0, import_jsx_runtime146.jsx)(
|
|
39155
|
-
"button",
|
|
39156
|
-
{
|
|
39157
|
-
onClick: () => goToSlide(currentSlide + 1),
|
|
39158
|
-
disabled: total <= 1,
|
|
39159
|
-
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",
|
|
39160
|
-
"aria-label": "Next slide",
|
|
39161
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime146.jsx)(ChevronRight2, {})
|
|
39162
|
-
}
|
|
39163
|
-
)
|
|
39164
|
-
] })
|
|
39165
|
-
] })
|
|
39166
|
-
] }),
|
|
39167
|
-
!formats.html_url && availablePills.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime146.jsx)("div", { className: "flex items-center gap-2 mt-4", children: availablePills.map((fmt) => /* @__PURE__ */ (0, import_jsx_runtime146.jsx)(
|
|
39168
|
-
"span",
|
|
39169
|
-
{
|
|
39170
|
-
className: cn(
|
|
39171
|
-
"text-xs px-2.5 py-0.5 rounded-md border font-medium",
|
|
39172
|
-
fmt.accent.pill
|
|
39280
|
+
onClick: (e) => {
|
|
39281
|
+
e.stopPropagation();
|
|
39282
|
+
slideCount > 1 ? goToSlide(currentSlide - 1) : sendSlideCommand("prevSlide");
|
|
39283
|
+
},
|
|
39284
|
+
disabled: !hasHtml,
|
|
39285
|
+
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",
|
|
39286
|
+
"aria-label": "Previous slide",
|
|
39287
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime146.jsx)(ChevronLeft2, {})
|
|
39288
|
+
}
|
|
39173
39289
|
),
|
|
39174
|
-
children:
|
|
39175
|
-
|
|
39176
|
-
|
|
39177
|
-
|
|
39290
|
+
/* @__PURE__ */ (0, import_jsx_runtime146.jsxs)("span", { className: "text-xs text-zinc-500 font-medium tabular-nums min-w-[3rem] text-center", children: [
|
|
39291
|
+
currentSlide,
|
|
39292
|
+
" / ",
|
|
39293
|
+
total
|
|
39294
|
+
] }),
|
|
39295
|
+
/* @__PURE__ */ (0, import_jsx_runtime146.jsx)(
|
|
39296
|
+
"button",
|
|
39297
|
+
{
|
|
39298
|
+
onClick: (e) => {
|
|
39299
|
+
e.stopPropagation();
|
|
39300
|
+
slideCount > 1 ? goToSlide(currentSlide + 1) : sendSlideCommand("nextSlide");
|
|
39301
|
+
},
|
|
39302
|
+
disabled: !hasHtml,
|
|
39303
|
+
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",
|
|
39304
|
+
"aria-label": "Next slide",
|
|
39305
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime146.jsx)(ChevronRight2, {})
|
|
39306
|
+
}
|
|
39307
|
+
)
|
|
39308
|
+
] })
|
|
39309
|
+
] })
|
|
39178
39310
|
] })
|
|
39179
39311
|
] }) }),
|
|
39180
|
-
|
|
39181
|
-
|
|
39312
|
+
showExport && /* @__PURE__ */ (0, import_jsx_runtime146.jsx)(ExportModal, { formats, title, onClose: () => setShowExport(false) }),
|
|
39313
|
+
showFullscreen && hasHtml && /* @__PURE__ */ (0, import_jsx_runtime146.jsx)(
|
|
39314
|
+
FullscreenModal,
|
|
39182
39315
|
{
|
|
39183
|
-
formats,
|
|
39316
|
+
url: formats.html_url,
|
|
39184
39317
|
title,
|
|
39185
|
-
|
|
39318
|
+
slideCount,
|
|
39319
|
+
onClose: () => setShowFullscreen(false)
|
|
39186
39320
|
}
|
|
39187
39321
|
)
|
|
39188
39322
|
] });
|