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.cjs
CHANGED
|
@@ -38894,6 +38894,38 @@ var FORMATS = [
|
|
|
38894
38894
|
var ExportModal = ({ formats, title, onClose }) => {
|
|
38895
38895
|
const available = FORMATS.filter((f) => formats[f.key]);
|
|
38896
38896
|
const filename = title.replace(/[^a-z0-9]/gi, "-").toLowerCase();
|
|
38897
|
+
const [downloadingKey, setDownloadingKey] = (0, import_react74.useState)(null);
|
|
38898
|
+
const buildDownloadHref = (url, ext) => {
|
|
38899
|
+
const downloadName = `${filename}${ext}`;
|
|
38900
|
+
return `/api/download?url=${encodeURIComponent(url)}&filename=${encodeURIComponent(downloadName)}`;
|
|
38901
|
+
};
|
|
38902
|
+
const handleDownload = async (fmtKey, url, ext) => {
|
|
38903
|
+
if (downloadingKey) {
|
|
38904
|
+
return;
|
|
38905
|
+
}
|
|
38906
|
+
const downloadHref = buildDownloadHref(url, ext);
|
|
38907
|
+
const downloadName = `${filename}${ext}`;
|
|
38908
|
+
try {
|
|
38909
|
+
setDownloadingKey(fmtKey);
|
|
38910
|
+
const response = await fetch(downloadHref);
|
|
38911
|
+
if (!response.ok) {
|
|
38912
|
+
throw new Error(`Download failed with status ${response.status}`);
|
|
38913
|
+
}
|
|
38914
|
+
const blob = await response.blob();
|
|
38915
|
+
const objectUrl = window.URL.createObjectURL(blob);
|
|
38916
|
+
const anchor = document.createElement("a");
|
|
38917
|
+
anchor.href = objectUrl;
|
|
38918
|
+
anchor.download = downloadName;
|
|
38919
|
+
document.body.appendChild(anchor);
|
|
38920
|
+
anchor.click();
|
|
38921
|
+
anchor.remove();
|
|
38922
|
+
window.URL.revokeObjectURL(objectUrl);
|
|
38923
|
+
} catch {
|
|
38924
|
+
window.open(downloadHref, "_blank", "noopener,noreferrer");
|
|
38925
|
+
} finally {
|
|
38926
|
+
setDownloadingKey(null);
|
|
38927
|
+
}
|
|
38928
|
+
};
|
|
38897
38929
|
return /* @__PURE__ */ (0, import_jsx_runtime146.jsxs)("div", { className: "fixed inset-0 z-50 flex items-center justify-center p-4", children: [
|
|
38898
38930
|
/* @__PURE__ */ (0, import_jsx_runtime146.jsx)("div", { className: "absolute inset-0 bg-black/70 backdrop-blur-sm", onClick: onClose }),
|
|
38899
38931
|
/* @__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: [
|
|
@@ -38916,22 +38948,23 @@ var ExportModal = ({ formats, title, onClose }) => {
|
|
|
38916
38948
|
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
38949
|
available.map((fmt) => {
|
|
38918
38950
|
const url = formats[fmt.key];
|
|
38919
|
-
const
|
|
38951
|
+
const isDownloading = downloadingKey === fmt.key;
|
|
38920
38952
|
return /* @__PURE__ */ (0, import_jsx_runtime146.jsxs)(
|
|
38921
|
-
"
|
|
38953
|
+
"button",
|
|
38922
38954
|
{
|
|
38923
|
-
|
|
38924
|
-
|
|
38955
|
+
type: "button",
|
|
38956
|
+
disabled: Boolean(downloadingKey),
|
|
38957
|
+
onClick: () => handleDownload(fmt.key, url, fmt.ext),
|
|
38925
38958
|
className: cn(
|
|
38926
|
-
"flex items-center gap-3.5 p-3.5 rounded-xl border transition-all",
|
|
38927
|
-
"hover:brightness-110
|
|
38959
|
+
"flex w-full items-center gap-3.5 p-3.5 rounded-xl border transition-all text-left",
|
|
38960
|
+
"hover:brightness-110 disabled:opacity-60 disabled:cursor-not-allowed",
|
|
38928
38961
|
fmt.accent.bg
|
|
38929
38962
|
),
|
|
38930
38963
|
children: [
|
|
38931
38964
|
/* @__PURE__ */ (0, import_jsx_runtime146.jsx)("span", { className: "text-xl flex-shrink-0", children: fmt.emoji }),
|
|
38932
38965
|
/* @__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 })
|
|
38966
|
+
/* @__PURE__ */ (0, import_jsx_runtime146.jsx)("p", { className: cn("text-sm font-semibold", fmt.accent.text), children: isDownloading ? `Downloading ${fmt.label}...` : fmt.label }),
|
|
38967
|
+
/* @__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
38968
|
] }),
|
|
38936
38969
|
/* @__PURE__ */ (0, import_jsx_runtime146.jsx)("span", { className: cn("flex-shrink-0 transition-colors", fmt.accent.text), children: /* @__PURE__ */ (0, import_jsx_runtime146.jsx)(DownloadIcon, {}) })
|
|
38937
38970
|
]
|
|
@@ -39000,6 +39033,12 @@ var PresentationJobCard = ({
|
|
|
39000
39033
|
iframeRef.current?.contentWindow?.postMessage({ type: "goToSlide", slide: pendingSlide }, "*");
|
|
39001
39034
|
setPendingSlide(null);
|
|
39002
39035
|
}, [iframeReady, pendingSlide]);
|
|
39036
|
+
const sendSlideCommand = (command) => {
|
|
39037
|
+
if (!iframeReady) {
|
|
39038
|
+
return;
|
|
39039
|
+
}
|
|
39040
|
+
iframeRef.current?.contentWindow?.postMessage({ type: command }, "*");
|
|
39041
|
+
};
|
|
39003
39042
|
const goToSlide = (n) => {
|
|
39004
39043
|
const total2 = slideCount || 1;
|
|
39005
39044
|
const target = (n - 1 + total2) % total2 + 1;
|
|
@@ -39139,8 +39178,14 @@ var PresentationJobCard = ({
|
|
|
39139
39178
|
/* @__PURE__ */ (0, import_jsx_runtime146.jsx)(
|
|
39140
39179
|
"button",
|
|
39141
39180
|
{
|
|
39142
|
-
onClick: () =>
|
|
39143
|
-
|
|
39181
|
+
onClick: () => {
|
|
39182
|
+
if (slideCount > 1) {
|
|
39183
|
+
goToSlide(currentSlide - 1);
|
|
39184
|
+
return;
|
|
39185
|
+
}
|
|
39186
|
+
sendSlideCommand("prevSlide");
|
|
39187
|
+
},
|
|
39188
|
+
disabled: !formats.html_url,
|
|
39144
39189
|
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
39190
|
"aria-label": "Previous slide",
|
|
39146
39191
|
children: /* @__PURE__ */ (0, import_jsx_runtime146.jsx)(ChevronLeft2, {})
|
|
@@ -39154,8 +39199,14 @@ var PresentationJobCard = ({
|
|
|
39154
39199
|
/* @__PURE__ */ (0, import_jsx_runtime146.jsx)(
|
|
39155
39200
|
"button",
|
|
39156
39201
|
{
|
|
39157
|
-
onClick: () =>
|
|
39158
|
-
|
|
39202
|
+
onClick: () => {
|
|
39203
|
+
if (slideCount > 1) {
|
|
39204
|
+
goToSlide(currentSlide + 1);
|
|
39205
|
+
return;
|
|
39206
|
+
}
|
|
39207
|
+
sendSlideCommand("nextSlide");
|
|
39208
|
+
},
|
|
39209
|
+
disabled: !formats.html_url,
|
|
39159
39210
|
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
39211
|
"aria-label": "Next slide",
|
|
39161
39212
|
children: /* @__PURE__ */ (0, import_jsx_runtime146.jsx)(ChevronRight2, {})
|