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.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 dlName = `${filename}${fmt.ext}`;
38629
+ const isDownloading = downloadingKey === fmt.key;
38598
38630
  return /* @__PURE__ */ jsxs108(
38599
- "a",
38631
+ "button",
38600
38632
  {
38601
- href: url,
38602
- download: dlName,
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 cursor-pointer no-underline group",
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: () => goToSlide(currentSlide - 1),
38821
- disabled: total <= 1,
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: () => goToSlide(currentSlide + 1),
38836
- disabled: total <= 1,
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, {})