pxengine 0.1.74 → 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 +63 -12
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +63 -12
- 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
|
]
|
|
@@ -38678,6 +38711,12 @@ var PresentationJobCard = ({
|
|
|
38678
38711
|
iframeRef.current?.contentWindow?.postMessage({ type: "goToSlide", slide: pendingSlide }, "*");
|
|
38679
38712
|
setPendingSlide(null);
|
|
38680
38713
|
}, [iframeReady, pendingSlide]);
|
|
38714
|
+
const sendSlideCommand = (command) => {
|
|
38715
|
+
if (!iframeReady) {
|
|
38716
|
+
return;
|
|
38717
|
+
}
|
|
38718
|
+
iframeRef.current?.contentWindow?.postMessage({ type: command }, "*");
|
|
38719
|
+
};
|
|
38681
38720
|
const goToSlide = (n) => {
|
|
38682
38721
|
const total2 = slideCount || 1;
|
|
38683
38722
|
const target = (n - 1 + total2) % total2 + 1;
|
|
@@ -38817,8 +38856,14 @@ var PresentationJobCard = ({
|
|
|
38817
38856
|
/* @__PURE__ */ jsx146(
|
|
38818
38857
|
"button",
|
|
38819
38858
|
{
|
|
38820
|
-
onClick: () =>
|
|
38821
|
-
|
|
38859
|
+
onClick: () => {
|
|
38860
|
+
if (slideCount > 1) {
|
|
38861
|
+
goToSlide(currentSlide - 1);
|
|
38862
|
+
return;
|
|
38863
|
+
}
|
|
38864
|
+
sendSlideCommand("prevSlide");
|
|
38865
|
+
},
|
|
38866
|
+
disabled: !formats.html_url,
|
|
38822
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",
|
|
38823
38868
|
"aria-label": "Previous slide",
|
|
38824
38869
|
children: /* @__PURE__ */ jsx146(ChevronLeft2, {})
|
|
@@ -38832,8 +38877,14 @@ var PresentationJobCard = ({
|
|
|
38832
38877
|
/* @__PURE__ */ jsx146(
|
|
38833
38878
|
"button",
|
|
38834
38879
|
{
|
|
38835
|
-
onClick: () =>
|
|
38836
|
-
|
|
38880
|
+
onClick: () => {
|
|
38881
|
+
if (slideCount > 1) {
|
|
38882
|
+
goToSlide(currentSlide + 1);
|
|
38883
|
+
return;
|
|
38884
|
+
}
|
|
38885
|
+
sendSlideCommand("nextSlide");
|
|
38886
|
+
},
|
|
38887
|
+
disabled: !formats.html_url,
|
|
38837
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",
|
|
38838
38889
|
"aria-label": "Next slide",
|
|
38839
38890
|
children: /* @__PURE__ */ jsx146(ChevronRight2, {})
|