pxengine 0.1.73 → 0.1.75
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 +80 -13
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +80 -13
- package/dist/index.mjs.map +1 -1
- package/dist/registry.json +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -38572,6 +38572,38 @@ var FORMATS = [
|
|
|
38572
38572
|
var ExportModal = ({ formats, title, onClose }) => {
|
|
38573
38573
|
const available = FORMATS.filter((f) => formats[f.key]);
|
|
38574
38574
|
const filename = title.replace(/[^a-z0-9]/gi, "-").toLowerCase();
|
|
38575
|
+
const [downloadingKey, setDownloadingKey] = useState10(null);
|
|
38576
|
+
const buildDownloadHref = (url, ext) => {
|
|
38577
|
+
const downloadName = `${filename}${ext}`;
|
|
38578
|
+
return `/api/download?url=${encodeURIComponent(url)}&filename=${encodeURIComponent(downloadName)}`;
|
|
38579
|
+
};
|
|
38580
|
+
const handleDownload = async (fmtKey, url, ext) => {
|
|
38581
|
+
if (downloadingKey) {
|
|
38582
|
+
return;
|
|
38583
|
+
}
|
|
38584
|
+
const downloadHref = buildDownloadHref(url, ext);
|
|
38585
|
+
const downloadName = `${filename}${ext}`;
|
|
38586
|
+
try {
|
|
38587
|
+
setDownloadingKey(fmtKey);
|
|
38588
|
+
const response = await fetch(downloadHref);
|
|
38589
|
+
if (!response.ok) {
|
|
38590
|
+
throw new Error(`Download failed with status ${response.status}`);
|
|
38591
|
+
}
|
|
38592
|
+
const blob = await response.blob();
|
|
38593
|
+
const objectUrl = window.URL.createObjectURL(blob);
|
|
38594
|
+
const anchor = document.createElement("a");
|
|
38595
|
+
anchor.href = objectUrl;
|
|
38596
|
+
anchor.download = downloadName;
|
|
38597
|
+
document.body.appendChild(anchor);
|
|
38598
|
+
anchor.click();
|
|
38599
|
+
anchor.remove();
|
|
38600
|
+
window.URL.revokeObjectURL(objectUrl);
|
|
38601
|
+
} catch {
|
|
38602
|
+
window.open(downloadHref, "_blank", "noopener,noreferrer");
|
|
38603
|
+
} finally {
|
|
38604
|
+
setDownloadingKey(null);
|
|
38605
|
+
}
|
|
38606
|
+
};
|
|
38575
38607
|
return /* @__PURE__ */ jsxs108("div", { className: "fixed inset-0 z-50 flex items-center justify-center p-4", children: [
|
|
38576
38608
|
/* @__PURE__ */ jsx146("div", { className: "absolute inset-0 bg-black/70 backdrop-blur-sm", onClick: onClose }),
|
|
38577
38609
|
/* @__PURE__ */ jsxs108("div", { className: "relative z-10 bg-zinc-900 border border-zinc-800 rounded-2xl w-full max-w-sm p-6 shadow-2xl", children: [
|
|
@@ -38594,22 +38626,23 @@ var ExportModal = ({ formats, title, onClose }) => {
|
|
|
38594
38626
|
available.length === 0 && /* @__PURE__ */ jsx146("p", { className: "text-sm text-zinc-500 text-center py-6", children: "No formats available yet" }),
|
|
38595
38627
|
available.map((fmt) => {
|
|
38596
38628
|
const url = formats[fmt.key];
|
|
38597
|
-
const
|
|
38629
|
+
const isDownloading = downloadingKey === fmt.key;
|
|
38598
38630
|
return /* @__PURE__ */ jsxs108(
|
|
38599
|
-
"
|
|
38631
|
+
"button",
|
|
38600
38632
|
{
|
|
38601
|
-
|
|
38602
|
-
|
|
38633
|
+
type: "button",
|
|
38634
|
+
disabled: Boolean(downloadingKey),
|
|
38635
|
+
onClick: () => handleDownload(fmt.key, url, fmt.ext),
|
|
38603
38636
|
className: cn(
|
|
38604
|
-
"flex items-center gap-3.5 p-3.5 rounded-xl border transition-all",
|
|
38605
|
-
"hover:brightness-110
|
|
38637
|
+
"flex w-full items-center gap-3.5 p-3.5 rounded-xl border transition-all text-left",
|
|
38638
|
+
"hover:brightness-110 disabled:opacity-60 disabled:cursor-not-allowed",
|
|
38606
38639
|
fmt.accent.bg
|
|
38607
38640
|
),
|
|
38608
38641
|
children: [
|
|
38609
38642
|
/* @__PURE__ */ jsx146("span", { className: "text-xl flex-shrink-0", children: fmt.emoji }),
|
|
38610
38643
|
/* @__PURE__ */ jsxs108("div", { className: "flex-1 min-w-0", children: [
|
|
38611
|
-
/* @__PURE__ */ jsx146("p", { className: cn("text-sm font-semibold", fmt.accent.text), children: fmt.label }),
|
|
38612
|
-
/* @__PURE__ */ jsx146("p", { className: "text-xs text-zinc-500 mt-0.5 leading-relaxed", children: fmt.desc })
|
|
38644
|
+
/* @__PURE__ */ jsx146("p", { className: cn("text-sm font-semibold", fmt.accent.text), children: isDownloading ? `Downloading ${fmt.label}...` : fmt.label }),
|
|
38645
|
+
/* @__PURE__ */ jsx146("p", { className: "text-xs text-zinc-500 mt-0.5 leading-relaxed", children: isDownloading ? "Please wait while the file is being prepared." : fmt.desc })
|
|
38613
38646
|
] }),
|
|
38614
38647
|
/* @__PURE__ */ jsx146("span", { className: cn("flex-shrink-0 transition-colors", fmt.accent.text), children: /* @__PURE__ */ jsx146(DownloadIcon, {}) })
|
|
38615
38648
|
]
|
|
@@ -38640,6 +38673,8 @@ var PresentationJobCard = ({
|
|
|
38640
38673
|
const [showModal, setShowModal] = useState10(false);
|
|
38641
38674
|
const [currentSlide, setCurrentSlide] = useState10(1);
|
|
38642
38675
|
const [previewScale, setPreviewScale] = useState10(1);
|
|
38676
|
+
const [iframeReady, setIframeReady] = useState10(false);
|
|
38677
|
+
const [pendingSlide, setPendingSlide] = useState10(null);
|
|
38643
38678
|
const intervalRef = useRef5(null);
|
|
38644
38679
|
const previewRef = useRef5(null);
|
|
38645
38680
|
const iframeRef = useRef5(null);
|
|
@@ -38655,6 +38690,10 @@ var PresentationJobCard = ({
|
|
|
38655
38690
|
if (previewRef.current) ro.observe(previewRef.current);
|
|
38656
38691
|
return () => ro.disconnect();
|
|
38657
38692
|
}, [updateScale, formats.html_url]);
|
|
38693
|
+
useEffect6(() => {
|
|
38694
|
+
setIframeReady(false);
|
|
38695
|
+
setPendingSlide(null);
|
|
38696
|
+
}, [formats.html_url]);
|
|
38658
38697
|
useEffect6(() => {
|
|
38659
38698
|
const handler = (e) => {
|
|
38660
38699
|
if (e.data?.type === "slideChanged") {
|
|
@@ -38667,11 +38706,26 @@ var PresentationJobCard = ({
|
|
|
38667
38706
|
window.addEventListener("message", handler);
|
|
38668
38707
|
return () => window.removeEventListener("message", handler);
|
|
38669
38708
|
}, [slideCount]);
|
|
38709
|
+
useEffect6(() => {
|
|
38710
|
+
if (!iframeReady || pendingSlide === null) return;
|
|
38711
|
+
iframeRef.current?.contentWindow?.postMessage({ type: "goToSlide", slide: pendingSlide }, "*");
|
|
38712
|
+
setPendingSlide(null);
|
|
38713
|
+
}, [iframeReady, pendingSlide]);
|
|
38714
|
+
const sendSlideCommand = (command) => {
|
|
38715
|
+
if (!iframeReady) {
|
|
38716
|
+
return;
|
|
38717
|
+
}
|
|
38718
|
+
iframeRef.current?.contentWindow?.postMessage({ type: command }, "*");
|
|
38719
|
+
};
|
|
38670
38720
|
const goToSlide = (n) => {
|
|
38671
38721
|
const total2 = slideCount || 1;
|
|
38672
38722
|
const target = (n - 1 + total2) % total2 + 1;
|
|
38673
38723
|
setCurrentSlide(target);
|
|
38674
|
-
|
|
38724
|
+
if (iframeReady) {
|
|
38725
|
+
iframeRef.current?.contentWindow?.postMessage({ type: "goToSlide", slide: target }, "*");
|
|
38726
|
+
return;
|
|
38727
|
+
}
|
|
38728
|
+
setPendingSlide(target);
|
|
38675
38729
|
};
|
|
38676
38730
|
const isTerminal = status === "complete" || status === "failed";
|
|
38677
38731
|
useEffect6(() => {
|
|
@@ -38771,6 +38825,7 @@ var PresentationJobCard = ({
|
|
|
38771
38825
|
ref: iframeRef,
|
|
38772
38826
|
src: formats.html_url,
|
|
38773
38827
|
title,
|
|
38828
|
+
onLoad: () => setIframeReady(true),
|
|
38774
38829
|
sandbox: "allow-same-origin allow-scripts",
|
|
38775
38830
|
style: {
|
|
38776
38831
|
width: 1280,
|
|
@@ -38801,8 +38856,14 @@ var PresentationJobCard = ({
|
|
|
38801
38856
|
/* @__PURE__ */ jsx146(
|
|
38802
38857
|
"button",
|
|
38803
38858
|
{
|
|
38804
|
-
onClick: () =>
|
|
38805
|
-
|
|
38859
|
+
onClick: () => {
|
|
38860
|
+
if (slideCount > 1) {
|
|
38861
|
+
goToSlide(currentSlide - 1);
|
|
38862
|
+
return;
|
|
38863
|
+
}
|
|
38864
|
+
sendSlideCommand("prevSlide");
|
|
38865
|
+
},
|
|
38866
|
+
disabled: !formats.html_url,
|
|
38806
38867
|
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",
|
|
38807
38868
|
"aria-label": "Previous slide",
|
|
38808
38869
|
children: /* @__PURE__ */ jsx146(ChevronLeft2, {})
|
|
@@ -38816,8 +38877,14 @@ var PresentationJobCard = ({
|
|
|
38816
38877
|
/* @__PURE__ */ jsx146(
|
|
38817
38878
|
"button",
|
|
38818
38879
|
{
|
|
38819
|
-
onClick: () =>
|
|
38820
|
-
|
|
38880
|
+
onClick: () => {
|
|
38881
|
+
if (slideCount > 1) {
|
|
38882
|
+
goToSlide(currentSlide + 1);
|
|
38883
|
+
return;
|
|
38884
|
+
}
|
|
38885
|
+
sendSlideCommand("nextSlide");
|
|
38886
|
+
},
|
|
38887
|
+
disabled: !formats.html_url,
|
|
38821
38888
|
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",
|
|
38822
38889
|
"aria-label": "Next slide",
|
|
38823
38890
|
children: /* @__PURE__ */ jsx146(ChevronRight2, {})
|