@page-speed/lightbox 0.1.4 → 0.1.6

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.
@@ -18069,7 +18069,7 @@ var require_pdf = __commonJS({
18069
18069
  }
18070
18070
  });
18071
18071
 
18072
- // node_modules/.pnpm/@page-speed+pdf-viewer@0.1.2_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@page-speed/pdf-viewer/dist/index.js
18072
+ // node_modules/.pnpm/@page-speed+pdf-viewer@0.1.4_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@page-speed/pdf-viewer/dist/index.js
18073
18073
  var dist_exports = {};
18074
18074
  __export(dist_exports, {
18075
18075
  PDFCanvas: () => PDFCanvas,
@@ -18102,7 +18102,7 @@ import { jsx as jsx22, jsxs } from "react/jsx-runtime";
18102
18102
  import { useEffect as useEffect32, useState as useState7 } from "react";
18103
18103
  import { jsx as jsx32, jsxs as jsxs2 } from "react/jsx-runtime";
18104
18104
  import { jsx as jsx42, jsxs as jsxs3 } from "react/jsx-runtime";
18105
- function usePDFDocument(url, onError) {
18105
+ function usePDFDocument(url, onError, withCredentials = false) {
18106
18106
  const [document2, setDocument] = useState5(null);
18107
18107
  const [loading, setLoading] = useState5(true);
18108
18108
  const [error, setError] = useState5(null);
@@ -18122,7 +18122,7 @@ function usePDFDocument(url, onError) {
18122
18122
  }
18123
18123
  const loadingTask = pdfjsLib.getDocument({
18124
18124
  url,
18125
- withCredentials: true,
18125
+ withCredentials,
18126
18126
  rangeChunkSize: 65536
18127
18127
  // For linearized PDFs
18128
18128
  });
@@ -18154,7 +18154,7 @@ function usePDFDocument(url, onError) {
18154
18154
  }
18155
18155
  };
18156
18156
  loadPDF();
18157
- }, [url, onError]);
18157
+ }, [url, onError, withCredentials]);
18158
18158
  return { document: document2, pdfDoc, loading, error };
18159
18159
  }
18160
18160
  function usePageState({
@@ -18544,9 +18544,10 @@ function PDFViewer({
18544
18544
  enablePrint = true,
18545
18545
  enableFullscreen = true,
18546
18546
  initialPage = 1,
18547
- initialZoom = "auto"
18547
+ initialZoom = "auto",
18548
+ withCredentials = false
18548
18549
  } = config;
18549
- const { document: document2, pdfDoc, loading, error } = usePDFDocument(url, onError);
18550
+ const { document: document2, pdfDoc, loading, error } = usePDFDocument(url, onError, withCredentials);
18550
18551
  const pageState = usePageState({
18551
18552
  totalPages: document2?.numPages || 0,
18552
18553
  initialPage
@@ -18685,7 +18686,7 @@ function createProgressiveFetchHandler(onProgress) {
18685
18686
  }
18686
18687
  var DEFAULT_SCALE, CACHE_SIZE, MIN_ZOOM, MAX_ZOOM, ZOOM_STEP, PDFViewer_default, linearizedPDFConfig;
18687
18688
  var init_dist = __esm({
18688
- "node_modules/.pnpm/@page-speed+pdf-viewer@0.1.2_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@page-speed/pdf-viewer/dist/index.js"() {
18689
+ "node_modules/.pnpm/@page-speed+pdf-viewer@0.1.4_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@page-speed/pdf-viewer/dist/index.js"() {
18689
18690
  "use client";
18690
18691
  DEFAULT_SCALE = 1.5;
18691
18692
  CACHE_SIZE = 50 * 1024 * 1024;
@@ -22558,13 +22559,29 @@ function loadPDFViewer() {
22558
22559
  }
22559
22560
  var LazyPDFViewer = React.lazy(loadPDFViewer);
22560
22561
  var AnyPDFViewer = LazyPDFViewer;
22561
- function PDFRenderer({ item }) {
22562
+ function PDFRenderer({ item, layout }) {
22562
22563
  if (!item.src) return null;
22563
- return /* @__PURE__ */ jsx5("div", { className: "w-full h-full flex items-center justify-center p-4", children: /* @__PURE__ */ jsx5(
22564
+ const config = {
22565
+ showControls: true,
22566
+ enableDownload: true,
22567
+ enablePrint: true,
22568
+ enableFullscreen: true,
22569
+ initialZoom: layout === "inline" ? "page-width" : 1.5
22570
+ };
22571
+ return /* @__PURE__ */ jsx5("div", { className: "w-full h-full flex items-center justify-center", children: /* @__PURE__ */ jsx5(
22564
22572
  Suspense,
22565
22573
  {
22566
22574
  fallback: /* @__PURE__ */ jsx5("div", { className: "flex items-center justify-center text-neutral-500 text-sm", children: "Loading document..." }),
22567
- children: /* @__PURE__ */ jsx5(AnyPDFViewer, { url: item.src })
22575
+ children: /* @__PURE__ */ jsx5(
22576
+ AnyPDFViewer,
22577
+ {
22578
+ url: item.src,
22579
+ config,
22580
+ height: "100%",
22581
+ width: "100%",
22582
+ title: item.title
22583
+ }
22584
+ )
22568
22585
  }
22569
22586
  ) });
22570
22587
  }
@@ -22603,6 +22620,7 @@ function LightboxContent({ item, layout, optixFlowConfig }) {
22603
22620
  }
22604
22621
 
22605
22622
  // src/components/LightboxChrome.tsx
22623
+ import React2 from "react";
22606
22624
  import { Fragment, jsx as jsx8, jsxs as jsxs4 } from "react/jsx-runtime";
22607
22625
  var DEFAULT_CONTROLS = {
22608
22626
  navigation: true,
@@ -22667,6 +22685,73 @@ function LightboxChrome({
22667
22685
  variant = "floating"
22668
22686
  }) {
22669
22687
  const resolved = mergeControls(controls);
22688
+ const [isFullscreen, setIsFullscreen] = React2.useState(false);
22689
+ const handleFullscreen = React2.useCallback(() => {
22690
+ if (!document.fullscreenElement) {
22691
+ document.documentElement.requestFullscreen().then(() => {
22692
+ setIsFullscreen(true);
22693
+ }).catch((err) => {
22694
+ console.error("Failed to enter fullscreen:", err);
22695
+ });
22696
+ } else {
22697
+ document.exitFullscreen().then(() => {
22698
+ setIsFullscreen(false);
22699
+ }).catch((err) => {
22700
+ console.error("Failed to exit fullscreen:", err);
22701
+ });
22702
+ }
22703
+ }, []);
22704
+ React2.useEffect(() => {
22705
+ const handleFullscreenChange = () => {
22706
+ setIsFullscreen(!!document.fullscreenElement);
22707
+ };
22708
+ document.addEventListener("fullscreenchange", handleFullscreenChange);
22709
+ return () => {
22710
+ document.removeEventListener("fullscreenchange", handleFullscreenChange);
22711
+ };
22712
+ }, []);
22713
+ const handleShare = React2.useCallback(async () => {
22714
+ if (!currentItem) return;
22715
+ const shareData = {
22716
+ title: currentItem.title || "Shared item",
22717
+ text: currentItem.caption || "",
22718
+ url: window.location.href
22719
+ };
22720
+ if (navigator.share) {
22721
+ try {
22722
+ await navigator.share(shareData);
22723
+ } catch (err) {
22724
+ if (err instanceof Error && err.name !== "AbortError") {
22725
+ console.error("Error sharing:", err);
22726
+ }
22727
+ }
22728
+ } else {
22729
+ try {
22730
+ await navigator.clipboard.writeText(window.location.href);
22731
+ console.log("Link copied to clipboard");
22732
+ } catch (err) {
22733
+ console.error("Failed to copy to clipboard:", err);
22734
+ }
22735
+ }
22736
+ }, [currentItem]);
22737
+ const handleDownload = React2.useCallback(async () => {
22738
+ if (!currentItem?.src) return;
22739
+ try {
22740
+ const response = await fetch(currentItem.src);
22741
+ const blob = await response.blob();
22742
+ const url = window.URL.createObjectURL(blob);
22743
+ const link = document.createElement("a");
22744
+ link.href = url;
22745
+ link.download = currentItem.title || "download";
22746
+ document.body.appendChild(link);
22747
+ link.click();
22748
+ document.body.removeChild(link);
22749
+ window.URL.revokeObjectURL(url);
22750
+ } catch (err) {
22751
+ console.error("Download failed:", err);
22752
+ window.open(currentItem.src, "_blank");
22753
+ }
22754
+ }, [currentItem]);
22670
22755
  if (variant === "toolbar") {
22671
22756
  return /* @__PURE__ */ jsxs4("div", { className: cn(
22672
22757
  "flex items-center justify-between",
@@ -22684,6 +22769,9 @@ function LightboxChrome({
22684
22769
  currentItem.caption && /* @__PURE__ */ jsx8("div", { className: "text-xs text-white/70", children: currentItem.caption })
22685
22770
  ] }) }),
22686
22771
  /* @__PURE__ */ jsxs4("div", { className: "flex items-center gap-2", children: [
22772
+ resolved.share && "share" in navigator && /* @__PURE__ */ jsx8(IconButton, { onClick: handleShare, ariaLabel: "Share", children: /* @__PURE__ */ jsx8(ShareIcon, {}) }),
22773
+ resolved.fullscreen && /* @__PURE__ */ jsx8(IconButton, { onClick: handleFullscreen, ariaLabel: isFullscreen ? "Exit fullscreen" : "Fullscreen", children: /* @__PURE__ */ jsx8(FullscreenIcon, {}) }),
22774
+ resolved.download && currentItem?.src && /* @__PURE__ */ jsx8(IconButton, { onClick: handleDownload, ariaLabel: "Download", children: /* @__PURE__ */ jsx8(DownloadIcon, {}) }),
22687
22775
  resolved.counter && totalItems > 0 && /* @__PURE__ */ jsxs4("span", { className: "text-xs text-white/70", children: [
22688
22776
  currentIndex + 1,
22689
22777
  " / ",
@@ -22699,9 +22787,9 @@ function LightboxChrome({
22699
22787
  "flex items-center gap-2",
22700
22788
  className
22701
22789
  ), children: [
22702
- resolved.share && /* @__PURE__ */ jsx8(IconButton, { ariaLabel: "Share", children: /* @__PURE__ */ jsx8(ShareIcon, {}) }),
22703
- resolved.fullscreen && /* @__PURE__ */ jsx8(IconButton, { ariaLabel: "Fullscreen", children: /* @__PURE__ */ jsx8(FullscreenIcon, {}) }),
22704
- resolved.download && /* @__PURE__ */ jsx8(IconButton, { ariaLabel: "Download", children: /* @__PURE__ */ jsx8(DownloadIcon, {}) }),
22790
+ resolved.share && "share" in navigator && /* @__PURE__ */ jsx8(IconButton, { onClick: handleShare, ariaLabel: "Share", children: /* @__PURE__ */ jsx8(ShareIcon, {}) }),
22791
+ resolved.fullscreen && /* @__PURE__ */ jsx8(IconButton, { onClick: handleFullscreen, ariaLabel: isFullscreen ? "Exit fullscreen" : "Fullscreen", children: /* @__PURE__ */ jsx8(FullscreenIcon, {}) }),
22792
+ resolved.download && currentItem?.src && /* @__PURE__ */ jsx8(IconButton, { onClick: handleDownload, ariaLabel: "Download", children: /* @__PURE__ */ jsx8(DownloadIcon, {}) }),
22705
22793
  resolved.closeButton && /* @__PURE__ */ jsx8(IconButton, { onClick: onClose, ariaLabel: "Close lightbox", children: /* @__PURE__ */ jsx8(CloseIcon, {}) })
22706
22794
  ] }),
22707
22795
  resolved.navigation && /* @__PURE__ */ jsxs4("div", { className: "fixed bottom-6 right-6 z-50 flex items-center gap-3", children: [
package/dist/index.cjs CHANGED
@@ -18065,7 +18065,7 @@ var require_pdf = __commonJS({
18065
18065
  }
18066
18066
  });
18067
18067
 
18068
- // node_modules/.pnpm/@page-speed+pdf-viewer@0.1.2_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@page-speed/pdf-viewer/dist/index.js
18068
+ // node_modules/.pnpm/@page-speed+pdf-viewer@0.1.4_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@page-speed/pdf-viewer/dist/index.js
18069
18069
  var dist_exports = {};
18070
18070
  __export(dist_exports, {
18071
18071
  PDFCanvas: () => PDFCanvas,
@@ -18086,7 +18086,7 @@ __export(dist_exports, {
18086
18086
  useSearch: () => useSearch,
18087
18087
  useZoom: () => useZoom
18088
18088
  });
18089
- function usePDFDocument(url, onError) {
18089
+ function usePDFDocument(url, onError, withCredentials = false) {
18090
18090
  const [document2, setDocument] = (0, import_react9.useState)(null);
18091
18091
  const [loading, setLoading] = (0, import_react9.useState)(true);
18092
18092
  const [error, setError] = (0, import_react9.useState)(null);
@@ -18106,7 +18106,7 @@ function usePDFDocument(url, onError) {
18106
18106
  }
18107
18107
  const loadingTask = pdfjsLib.getDocument({
18108
18108
  url,
18109
- withCredentials: true,
18109
+ withCredentials,
18110
18110
  rangeChunkSize: 65536
18111
18111
  // For linearized PDFs
18112
18112
  });
@@ -18138,7 +18138,7 @@ function usePDFDocument(url, onError) {
18138
18138
  }
18139
18139
  };
18140
18140
  loadPDF();
18141
- }, [url, onError]);
18141
+ }, [url, onError, withCredentials]);
18142
18142
  return { document: document2, pdfDoc, loading, error };
18143
18143
  }
18144
18144
  function usePageState({
@@ -18528,9 +18528,10 @@ function PDFViewer({
18528
18528
  enablePrint = true,
18529
18529
  enableFullscreen = true,
18530
18530
  initialPage = 1,
18531
- initialZoom = "auto"
18531
+ initialZoom = "auto",
18532
+ withCredentials = false
18532
18533
  } = config;
18533
- const { document: document2, pdfDoc, loading, error } = usePDFDocument(url, onError);
18534
+ const { document: document2, pdfDoc, loading, error } = usePDFDocument(url, onError, withCredentials);
18534
18535
  const pageState = usePageState({
18535
18536
  totalPages: document2?.numPages || 0,
18536
18537
  initialPage
@@ -18669,7 +18670,7 @@ function createProgressiveFetchHandler(onProgress) {
18669
18670
  }
18670
18671
  var import_react8, import_react9, import_react10, import_react11, import_react12, import_react13, import_react14, import_jsx_runtime5, import_jsx_runtime6, import_react15, import_jsx_runtime7, import_jsx_runtime8, DEFAULT_SCALE, CACHE_SIZE, MIN_ZOOM, MAX_ZOOM, ZOOM_STEP, PDFViewer_default, linearizedPDFConfig;
18671
18672
  var init_dist = __esm({
18672
- "node_modules/.pnpm/@page-speed+pdf-viewer@0.1.2_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@page-speed/pdf-viewer/dist/index.js"() {
18673
+ "node_modules/.pnpm/@page-speed+pdf-viewer@0.1.4_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@page-speed/pdf-viewer/dist/index.js"() {
18673
18674
  "use client";
18674
18675
  import_react8 = require("react");
18675
18676
  import_react9 = require("react");
@@ -18740,7 +18741,7 @@ __export(index_exports, {
18740
18741
  module.exports = __toCommonJS(index_exports);
18741
18742
 
18742
18743
  // src/components/Lightbox.tsx
18743
- var import_react17 = require("react");
18744
+ var import_react18 = require("react");
18744
18745
  var import_react_dom = require("react-dom");
18745
18746
 
18746
18747
  // src/hooks/useGalleryState.ts
@@ -22572,13 +22573,29 @@ function loadPDFViewer() {
22572
22573
  }
22573
22574
  var LazyPDFViewer = import_react16.default.lazy(loadPDFViewer);
22574
22575
  var AnyPDFViewer = LazyPDFViewer;
22575
- function PDFRenderer({ item }) {
22576
+ function PDFRenderer({ item, layout }) {
22576
22577
  if (!item.src) return null;
22577
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "w-full h-full flex items-center justify-center p-4", children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
22578
+ const config = {
22579
+ showControls: true,
22580
+ enableDownload: true,
22581
+ enablePrint: true,
22582
+ enableFullscreen: true,
22583
+ initialZoom: layout === "inline" ? "page-width" : 1.5
22584
+ };
22585
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "w-full h-full flex items-center justify-center", children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
22578
22586
  import_react16.Suspense,
22579
22587
  {
22580
22588
  fallback: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "flex items-center justify-center text-neutral-500 text-sm", children: "Loading document..." }),
22581
- children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(AnyPDFViewer, { url: item.src })
22589
+ children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
22590
+ AnyPDFViewer,
22591
+ {
22592
+ url: item.src,
22593
+ config,
22594
+ height: "100%",
22595
+ width: "100%",
22596
+ title: item.title
22597
+ }
22598
+ )
22582
22599
  }
22583
22600
  ) });
22584
22601
  }
@@ -22617,6 +22634,7 @@ function LightboxContent({ item, layout, optixFlowConfig }) {
22617
22634
  }
22618
22635
 
22619
22636
  // src/components/LightboxChrome.tsx
22637
+ var import_react17 = __toESM(require("react"));
22620
22638
  var import_jsx_runtime12 = require("react/jsx-runtime");
22621
22639
  var DEFAULT_CONTROLS = {
22622
22640
  navigation: true,
@@ -22681,6 +22699,73 @@ function LightboxChrome({
22681
22699
  variant = "floating"
22682
22700
  }) {
22683
22701
  const resolved = mergeControls(controls);
22702
+ const [isFullscreen, setIsFullscreen] = import_react17.default.useState(false);
22703
+ const handleFullscreen = import_react17.default.useCallback(() => {
22704
+ if (!document.fullscreenElement) {
22705
+ document.documentElement.requestFullscreen().then(() => {
22706
+ setIsFullscreen(true);
22707
+ }).catch((err) => {
22708
+ console.error("Failed to enter fullscreen:", err);
22709
+ });
22710
+ } else {
22711
+ document.exitFullscreen().then(() => {
22712
+ setIsFullscreen(false);
22713
+ }).catch((err) => {
22714
+ console.error("Failed to exit fullscreen:", err);
22715
+ });
22716
+ }
22717
+ }, []);
22718
+ import_react17.default.useEffect(() => {
22719
+ const handleFullscreenChange = () => {
22720
+ setIsFullscreen(!!document.fullscreenElement);
22721
+ };
22722
+ document.addEventListener("fullscreenchange", handleFullscreenChange);
22723
+ return () => {
22724
+ document.removeEventListener("fullscreenchange", handleFullscreenChange);
22725
+ };
22726
+ }, []);
22727
+ const handleShare = import_react17.default.useCallback(async () => {
22728
+ if (!currentItem) return;
22729
+ const shareData = {
22730
+ title: currentItem.title || "Shared item",
22731
+ text: currentItem.caption || "",
22732
+ url: window.location.href
22733
+ };
22734
+ if (navigator.share) {
22735
+ try {
22736
+ await navigator.share(shareData);
22737
+ } catch (err) {
22738
+ if (err instanceof Error && err.name !== "AbortError") {
22739
+ console.error("Error sharing:", err);
22740
+ }
22741
+ }
22742
+ } else {
22743
+ try {
22744
+ await navigator.clipboard.writeText(window.location.href);
22745
+ console.log("Link copied to clipboard");
22746
+ } catch (err) {
22747
+ console.error("Failed to copy to clipboard:", err);
22748
+ }
22749
+ }
22750
+ }, [currentItem]);
22751
+ const handleDownload = import_react17.default.useCallback(async () => {
22752
+ if (!currentItem?.src) return;
22753
+ try {
22754
+ const response = await fetch(currentItem.src);
22755
+ const blob = await response.blob();
22756
+ const url = window.URL.createObjectURL(blob);
22757
+ const link = document.createElement("a");
22758
+ link.href = url;
22759
+ link.download = currentItem.title || "download";
22760
+ document.body.appendChild(link);
22761
+ link.click();
22762
+ document.body.removeChild(link);
22763
+ window.URL.revokeObjectURL(url);
22764
+ } catch (err) {
22765
+ console.error("Download failed:", err);
22766
+ window.open(currentItem.src, "_blank");
22767
+ }
22768
+ }, [currentItem]);
22684
22769
  if (variant === "toolbar") {
22685
22770
  return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: cn(
22686
22771
  "flex items-center justify-between",
@@ -22698,6 +22783,9 @@ function LightboxChrome({
22698
22783
  currentItem.caption && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "text-xs text-white/70", children: currentItem.caption })
22699
22784
  ] }) }),
22700
22785
  /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "flex items-center gap-2", children: [
22786
+ resolved.share && "share" in navigator && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(IconButton, { onClick: handleShare, ariaLabel: "Share", children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(ShareIcon, {}) }),
22787
+ resolved.fullscreen && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(IconButton, { onClick: handleFullscreen, ariaLabel: isFullscreen ? "Exit fullscreen" : "Fullscreen", children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(FullscreenIcon, {}) }),
22788
+ resolved.download && currentItem?.src && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(IconButton, { onClick: handleDownload, ariaLabel: "Download", children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(DownloadIcon, {}) }),
22701
22789
  resolved.counter && totalItems > 0 && /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("span", { className: "text-xs text-white/70", children: [
22702
22790
  currentIndex + 1,
22703
22791
  " / ",
@@ -22713,9 +22801,9 @@ function LightboxChrome({
22713
22801
  "flex items-center gap-2",
22714
22802
  className
22715
22803
  ), children: [
22716
- resolved.share && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(IconButton, { ariaLabel: "Share", children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(ShareIcon, {}) }),
22717
- resolved.fullscreen && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(IconButton, { ariaLabel: "Fullscreen", children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(FullscreenIcon, {}) }),
22718
- resolved.download && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(IconButton, { ariaLabel: "Download", children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(DownloadIcon, {}) }),
22804
+ resolved.share && "share" in navigator && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(IconButton, { onClick: handleShare, ariaLabel: "Share", children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(ShareIcon, {}) }),
22805
+ resolved.fullscreen && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(IconButton, { onClick: handleFullscreen, ariaLabel: isFullscreen ? "Exit fullscreen" : "Fullscreen", children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(FullscreenIcon, {}) }),
22806
+ resolved.download && currentItem?.src && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(IconButton, { onClick: handleDownload, ariaLabel: "Download", children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(DownloadIcon, {}) }),
22719
22807
  resolved.closeButton && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(IconButton, { onClick: onClose, ariaLabel: "Close lightbox", children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(CloseIcon, {}) })
22720
22808
  ] }),
22721
22809
  resolved.navigation && /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "fixed bottom-6 right-6 z-50 flex items-center gap-3", children: [
@@ -22960,18 +23048,18 @@ function Lightbox(props) {
22960
23048
  onSelect: props.onSelect
22961
23049
  });
22962
23050
  const { breakpoint } = useResponsiveness();
22963
- const layout = (0, import_react17.useMemo)(() => {
23051
+ const layout = (0, import_react18.useMemo)(() => {
22964
23052
  if (props.layout) return props.layout;
22965
23053
  if (breakpoint === "mobile") return "fullscreen";
22966
23054
  if (breakpoint === "tablet") return "vertical-split";
22967
23055
  return "horizontal";
22968
23056
  }, [props.layout, breakpoint]);
22969
- const didCloseRef = (0, import_react17.useRef)(false);
22970
- const [isMounted, setIsMounted] = (0, import_react17.useState)(false);
22971
- (0, import_react17.useEffect)(() => {
23057
+ const didCloseRef = (0, import_react18.useRef)(false);
23058
+ const [isMounted, setIsMounted] = (0, import_react18.useState)(false);
23059
+ (0, import_react18.useEffect)(() => {
22972
23060
  setIsMounted(true);
22973
23061
  }, []);
22974
- (0, import_react17.useEffect)(() => {
23062
+ (0, import_react18.useEffect)(() => {
22975
23063
  props.onOpen?.();
22976
23064
  if (props.disableScroll === false) {
22977
23065
  return;
@@ -22985,17 +23073,17 @@ function Lightbox(props) {
22985
23073
  document.body.style.overflow = previousOverflow;
22986
23074
  };
22987
23075
  }, [props.disableScroll, props.onOpen]);
22988
- const handleClose = (0, import_react17.useCallback)(() => {
23076
+ const handleClose = (0, import_react18.useCallback)(() => {
22989
23077
  if (didCloseRef.current) return;
22990
23078
  didCloseRef.current = true;
22991
23079
  props.onClose?.();
22992
23080
  }, [props.onClose]);
22993
- const handleNext = (0, import_react17.useCallback)(() => {
23081
+ const handleNext = (0, import_react18.useCallback)(() => {
22994
23082
  if (!gallery.canNext) return;
22995
23083
  gallery.next();
22996
23084
  props.onNext?.();
22997
23085
  }, [gallery, props.onNext]);
22998
- const handlePrev = (0, import_react17.useCallback)(() => {
23086
+ const handlePrev = (0, import_react18.useCallback)(() => {
22999
23087
  if (!gallery.canPrev) return;
23000
23088
  gallery.prev();
23001
23089
  props.onPrev?.();
@@ -23087,28 +23175,28 @@ function Lightbox(props) {
23087
23175
  }
23088
23176
 
23089
23177
  // src/hooks/useLightboxState.ts
23090
- var import_react18 = require("react");
23178
+ var import_react19 = require("react");
23091
23179
  function useLightboxState({
23092
23180
  onOpen,
23093
23181
  onClose,
23094
23182
  disableScroll = true
23095
23183
  }) {
23096
- const [isOpen, setIsOpen] = (0, import_react18.useState)(false);
23097
- const open = (0, import_react18.useCallback)(() => {
23184
+ const [isOpen, setIsOpen] = (0, import_react19.useState)(false);
23185
+ const open = (0, import_react19.useCallback)(() => {
23098
23186
  setIsOpen(true);
23099
23187
  onOpen?.();
23100
23188
  if (disableScroll) {
23101
23189
  document.body.style.overflow = "hidden";
23102
23190
  }
23103
23191
  }, [onOpen, disableScroll]);
23104
- const close = (0, import_react18.useCallback)(() => {
23192
+ const close = (0, import_react19.useCallback)(() => {
23105
23193
  setIsOpen(false);
23106
23194
  onClose?.();
23107
23195
  if (disableScroll) {
23108
23196
  document.body.style.overflow = "";
23109
23197
  }
23110
23198
  }, [onClose, disableScroll]);
23111
- (0, import_react18.useEffect)(() => {
23199
+ (0, import_react19.useEffect)(() => {
23112
23200
  return () => {
23113
23201
  if (disableScroll) {
23114
23202
  document.body.style.overflow = "";
package/dist/index.js CHANGED
@@ -18069,7 +18069,7 @@ var require_pdf = __commonJS({
18069
18069
  }
18070
18070
  });
18071
18071
 
18072
- // node_modules/.pnpm/@page-speed+pdf-viewer@0.1.2_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@page-speed/pdf-viewer/dist/index.js
18072
+ // node_modules/.pnpm/@page-speed+pdf-viewer@0.1.4_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@page-speed/pdf-viewer/dist/index.js
18073
18073
  var dist_exports = {};
18074
18074
  __export(dist_exports, {
18075
18075
  PDFCanvas: () => PDFCanvas,
@@ -18102,7 +18102,7 @@ import { jsx as jsx22, jsxs } from "react/jsx-runtime";
18102
18102
  import { useEffect as useEffect32, useState as useState7 } from "react";
18103
18103
  import { jsx as jsx32, jsxs as jsxs2 } from "react/jsx-runtime";
18104
18104
  import { jsx as jsx42, jsxs as jsxs3 } from "react/jsx-runtime";
18105
- function usePDFDocument(url, onError) {
18105
+ function usePDFDocument(url, onError, withCredentials = false) {
18106
18106
  const [document2, setDocument] = useState5(null);
18107
18107
  const [loading, setLoading] = useState5(true);
18108
18108
  const [error, setError] = useState5(null);
@@ -18122,7 +18122,7 @@ function usePDFDocument(url, onError) {
18122
18122
  }
18123
18123
  const loadingTask = pdfjsLib.getDocument({
18124
18124
  url,
18125
- withCredentials: true,
18125
+ withCredentials,
18126
18126
  rangeChunkSize: 65536
18127
18127
  // For linearized PDFs
18128
18128
  });
@@ -18154,7 +18154,7 @@ function usePDFDocument(url, onError) {
18154
18154
  }
18155
18155
  };
18156
18156
  loadPDF();
18157
- }, [url, onError]);
18157
+ }, [url, onError, withCredentials]);
18158
18158
  return { document: document2, pdfDoc, loading, error };
18159
18159
  }
18160
18160
  function usePageState({
@@ -18544,9 +18544,10 @@ function PDFViewer({
18544
18544
  enablePrint = true,
18545
18545
  enableFullscreen = true,
18546
18546
  initialPage = 1,
18547
- initialZoom = "auto"
18547
+ initialZoom = "auto",
18548
+ withCredentials = false
18548
18549
  } = config;
18549
- const { document: document2, pdfDoc, loading, error } = usePDFDocument(url, onError);
18550
+ const { document: document2, pdfDoc, loading, error } = usePDFDocument(url, onError, withCredentials);
18550
18551
  const pageState = usePageState({
18551
18552
  totalPages: document2?.numPages || 0,
18552
18553
  initialPage
@@ -18685,7 +18686,7 @@ function createProgressiveFetchHandler(onProgress) {
18685
18686
  }
18686
18687
  var DEFAULT_SCALE, CACHE_SIZE, MIN_ZOOM, MAX_ZOOM, ZOOM_STEP, PDFViewer_default, linearizedPDFConfig;
18687
18688
  var init_dist = __esm({
18688
- "node_modules/.pnpm/@page-speed+pdf-viewer@0.1.2_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@page-speed/pdf-viewer/dist/index.js"() {
18689
+ "node_modules/.pnpm/@page-speed+pdf-viewer@0.1.4_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@page-speed/pdf-viewer/dist/index.js"() {
18689
18690
  "use client";
18690
18691
  DEFAULT_SCALE = 1.5;
18691
18692
  CACHE_SIZE = 50 * 1024 * 1024;
@@ -22558,13 +22559,29 @@ function loadPDFViewer() {
22558
22559
  }
22559
22560
  var LazyPDFViewer = React.lazy(loadPDFViewer);
22560
22561
  var AnyPDFViewer = LazyPDFViewer;
22561
- function PDFRenderer({ item }) {
22562
+ function PDFRenderer({ item, layout }) {
22562
22563
  if (!item.src) return null;
22563
- return /* @__PURE__ */ jsx5("div", { className: "w-full h-full flex items-center justify-center p-4", children: /* @__PURE__ */ jsx5(
22564
+ const config = {
22565
+ showControls: true,
22566
+ enableDownload: true,
22567
+ enablePrint: true,
22568
+ enableFullscreen: true,
22569
+ initialZoom: layout === "inline" ? "page-width" : 1.5
22570
+ };
22571
+ return /* @__PURE__ */ jsx5("div", { className: "w-full h-full flex items-center justify-center", children: /* @__PURE__ */ jsx5(
22564
22572
  Suspense,
22565
22573
  {
22566
22574
  fallback: /* @__PURE__ */ jsx5("div", { className: "flex items-center justify-center text-neutral-500 text-sm", children: "Loading document..." }),
22567
- children: /* @__PURE__ */ jsx5(AnyPDFViewer, { url: item.src })
22575
+ children: /* @__PURE__ */ jsx5(
22576
+ AnyPDFViewer,
22577
+ {
22578
+ url: item.src,
22579
+ config,
22580
+ height: "100%",
22581
+ width: "100%",
22582
+ title: item.title
22583
+ }
22584
+ )
22568
22585
  }
22569
22586
  ) });
22570
22587
  }
@@ -22603,6 +22620,7 @@ function LightboxContent({ item, layout, optixFlowConfig }) {
22603
22620
  }
22604
22621
 
22605
22622
  // src/components/LightboxChrome.tsx
22623
+ import React2 from "react";
22606
22624
  import { Fragment, jsx as jsx8, jsxs as jsxs4 } from "react/jsx-runtime";
22607
22625
  var DEFAULT_CONTROLS = {
22608
22626
  navigation: true,
@@ -22667,6 +22685,73 @@ function LightboxChrome({
22667
22685
  variant = "floating"
22668
22686
  }) {
22669
22687
  const resolved = mergeControls(controls);
22688
+ const [isFullscreen, setIsFullscreen] = React2.useState(false);
22689
+ const handleFullscreen = React2.useCallback(() => {
22690
+ if (!document.fullscreenElement) {
22691
+ document.documentElement.requestFullscreen().then(() => {
22692
+ setIsFullscreen(true);
22693
+ }).catch((err) => {
22694
+ console.error("Failed to enter fullscreen:", err);
22695
+ });
22696
+ } else {
22697
+ document.exitFullscreen().then(() => {
22698
+ setIsFullscreen(false);
22699
+ }).catch((err) => {
22700
+ console.error("Failed to exit fullscreen:", err);
22701
+ });
22702
+ }
22703
+ }, []);
22704
+ React2.useEffect(() => {
22705
+ const handleFullscreenChange = () => {
22706
+ setIsFullscreen(!!document.fullscreenElement);
22707
+ };
22708
+ document.addEventListener("fullscreenchange", handleFullscreenChange);
22709
+ return () => {
22710
+ document.removeEventListener("fullscreenchange", handleFullscreenChange);
22711
+ };
22712
+ }, []);
22713
+ const handleShare = React2.useCallback(async () => {
22714
+ if (!currentItem) return;
22715
+ const shareData = {
22716
+ title: currentItem.title || "Shared item",
22717
+ text: currentItem.caption || "",
22718
+ url: window.location.href
22719
+ };
22720
+ if (navigator.share) {
22721
+ try {
22722
+ await navigator.share(shareData);
22723
+ } catch (err) {
22724
+ if (err instanceof Error && err.name !== "AbortError") {
22725
+ console.error("Error sharing:", err);
22726
+ }
22727
+ }
22728
+ } else {
22729
+ try {
22730
+ await navigator.clipboard.writeText(window.location.href);
22731
+ console.log("Link copied to clipboard");
22732
+ } catch (err) {
22733
+ console.error("Failed to copy to clipboard:", err);
22734
+ }
22735
+ }
22736
+ }, [currentItem]);
22737
+ const handleDownload = React2.useCallback(async () => {
22738
+ if (!currentItem?.src) return;
22739
+ try {
22740
+ const response = await fetch(currentItem.src);
22741
+ const blob = await response.blob();
22742
+ const url = window.URL.createObjectURL(blob);
22743
+ const link = document.createElement("a");
22744
+ link.href = url;
22745
+ link.download = currentItem.title || "download";
22746
+ document.body.appendChild(link);
22747
+ link.click();
22748
+ document.body.removeChild(link);
22749
+ window.URL.revokeObjectURL(url);
22750
+ } catch (err) {
22751
+ console.error("Download failed:", err);
22752
+ window.open(currentItem.src, "_blank");
22753
+ }
22754
+ }, [currentItem]);
22670
22755
  if (variant === "toolbar") {
22671
22756
  return /* @__PURE__ */ jsxs4("div", { className: cn(
22672
22757
  "flex items-center justify-between",
@@ -22684,6 +22769,9 @@ function LightboxChrome({
22684
22769
  currentItem.caption && /* @__PURE__ */ jsx8("div", { className: "text-xs text-white/70", children: currentItem.caption })
22685
22770
  ] }) }),
22686
22771
  /* @__PURE__ */ jsxs4("div", { className: "flex items-center gap-2", children: [
22772
+ resolved.share && "share" in navigator && /* @__PURE__ */ jsx8(IconButton, { onClick: handleShare, ariaLabel: "Share", children: /* @__PURE__ */ jsx8(ShareIcon, {}) }),
22773
+ resolved.fullscreen && /* @__PURE__ */ jsx8(IconButton, { onClick: handleFullscreen, ariaLabel: isFullscreen ? "Exit fullscreen" : "Fullscreen", children: /* @__PURE__ */ jsx8(FullscreenIcon, {}) }),
22774
+ resolved.download && currentItem?.src && /* @__PURE__ */ jsx8(IconButton, { onClick: handleDownload, ariaLabel: "Download", children: /* @__PURE__ */ jsx8(DownloadIcon, {}) }),
22687
22775
  resolved.counter && totalItems > 0 && /* @__PURE__ */ jsxs4("span", { className: "text-xs text-white/70", children: [
22688
22776
  currentIndex + 1,
22689
22777
  " / ",
@@ -22699,9 +22787,9 @@ function LightboxChrome({
22699
22787
  "flex items-center gap-2",
22700
22788
  className
22701
22789
  ), children: [
22702
- resolved.share && /* @__PURE__ */ jsx8(IconButton, { ariaLabel: "Share", children: /* @__PURE__ */ jsx8(ShareIcon, {}) }),
22703
- resolved.fullscreen && /* @__PURE__ */ jsx8(IconButton, { ariaLabel: "Fullscreen", children: /* @__PURE__ */ jsx8(FullscreenIcon, {}) }),
22704
- resolved.download && /* @__PURE__ */ jsx8(IconButton, { ariaLabel: "Download", children: /* @__PURE__ */ jsx8(DownloadIcon, {}) }),
22790
+ resolved.share && "share" in navigator && /* @__PURE__ */ jsx8(IconButton, { onClick: handleShare, ariaLabel: "Share", children: /* @__PURE__ */ jsx8(ShareIcon, {}) }),
22791
+ resolved.fullscreen && /* @__PURE__ */ jsx8(IconButton, { onClick: handleFullscreen, ariaLabel: isFullscreen ? "Exit fullscreen" : "Fullscreen", children: /* @__PURE__ */ jsx8(FullscreenIcon, {}) }),
22792
+ resolved.download && currentItem?.src && /* @__PURE__ */ jsx8(IconButton, { onClick: handleDownload, ariaLabel: "Download", children: /* @__PURE__ */ jsx8(DownloadIcon, {}) }),
22705
22793
  resolved.closeButton && /* @__PURE__ */ jsx8(IconButton, { onClick: onClose, ariaLabel: "Close lightbox", children: /* @__PURE__ */ jsx8(CloseIcon, {}) })
22706
22794
  ] }),
22707
22795
  resolved.navigation && /* @__PURE__ */ jsxs4("div", { className: "fixed bottom-6 right-6 z-50 flex items-center gap-3", children: [
@@ -7,5 +7,5 @@ interface PDFRendererProps {
7
7
  * Thin wrapper around @page-speed/pdf-viewer, loaded lazily so that the
8
8
  * heavy PDF runtime is only fetched when a PDF item is actually viewed.
9
9
  */
10
- export declare function PDFRenderer({ item }: PDFRendererProps): import("react/jsx-runtime").JSX.Element | null;
10
+ export declare function PDFRenderer({ item, layout }: PDFRendererProps): import("react/jsx-runtime").JSX.Element | null;
11
11
  export {};
@@ -18069,7 +18069,7 @@ var require_pdf = __commonJS({
18069
18069
  }
18070
18070
  });
18071
18071
 
18072
- // node_modules/.pnpm/@page-speed+pdf-viewer@0.1.2_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@page-speed/pdf-viewer/dist/index.js
18072
+ // node_modules/.pnpm/@page-speed+pdf-viewer@0.1.4_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@page-speed/pdf-viewer/dist/index.js
18073
18073
  var dist_exports = {};
18074
18074
  __export(dist_exports, {
18075
18075
  PDFCanvas: () => PDFCanvas,
@@ -18102,7 +18102,7 @@ import { jsx as jsx22, jsxs } from "react/jsx-runtime";
18102
18102
  import { useEffect as useEffect32, useState as useState7 } from "react";
18103
18103
  import { jsx as jsx32, jsxs as jsxs2 } from "react/jsx-runtime";
18104
18104
  import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
18105
- function usePDFDocument(url, onError) {
18105
+ function usePDFDocument(url, onError, withCredentials = false) {
18106
18106
  const [document2, setDocument] = useState3(null);
18107
18107
  const [loading, setLoading] = useState3(true);
18108
18108
  const [error, setError] = useState3(null);
@@ -18122,7 +18122,7 @@ function usePDFDocument(url, onError) {
18122
18122
  }
18123
18123
  const loadingTask = pdfjsLib.getDocument({
18124
18124
  url,
18125
- withCredentials: true,
18125
+ withCredentials,
18126
18126
  rangeChunkSize: 65536
18127
18127
  // For linearized PDFs
18128
18128
  });
@@ -18154,7 +18154,7 @@ function usePDFDocument(url, onError) {
18154
18154
  }
18155
18155
  };
18156
18156
  loadPDF();
18157
- }, [url, onError]);
18157
+ }, [url, onError, withCredentials]);
18158
18158
  return { document: document2, pdfDoc, loading, error };
18159
18159
  }
18160
18160
  function usePageState({
@@ -18544,9 +18544,10 @@ function PDFViewer({
18544
18544
  enablePrint = true,
18545
18545
  enableFullscreen = true,
18546
18546
  initialPage = 1,
18547
- initialZoom = "auto"
18547
+ initialZoom = "auto",
18548
+ withCredentials = false
18548
18549
  } = config;
18549
- const { document: document2, pdfDoc, loading, error } = usePDFDocument(url, onError);
18550
+ const { document: document2, pdfDoc, loading, error } = usePDFDocument(url, onError, withCredentials);
18550
18551
  const pageState = usePageState({
18551
18552
  totalPages: document2?.numPages || 0,
18552
18553
  initialPage
@@ -18685,7 +18686,7 @@ function createProgressiveFetchHandler(onProgress) {
18685
18686
  }
18686
18687
  var DEFAULT_SCALE, CACHE_SIZE, MIN_ZOOM, MAX_ZOOM, ZOOM_STEP, PDFViewer_default, linearizedPDFConfig;
18687
18688
  var init_dist = __esm({
18688
- "node_modules/.pnpm/@page-speed+pdf-viewer@0.1.2_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@page-speed/pdf-viewer/dist/index.js"() {
18689
+ "node_modules/.pnpm/@page-speed+pdf-viewer@0.1.4_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@page-speed/pdf-viewer/dist/index.js"() {
18689
18690
  "use client";
18690
18691
  DEFAULT_SCALE = 1.5;
18691
18692
  CACHE_SIZE = 50 * 1024 * 1024;
@@ -19414,13 +19415,29 @@ function loadPDFViewer() {
19414
19415
  }
19415
19416
  var LazyPDFViewer = React.lazy(loadPDFViewer);
19416
19417
  var AnyPDFViewer = LazyPDFViewer;
19417
- function PDFRenderer({ item }) {
19418
+ function PDFRenderer({ item, layout }) {
19418
19419
  if (!item.src) return null;
19419
- return /* @__PURE__ */ jsx5("div", { className: "w-full h-full flex items-center justify-center p-4", children: /* @__PURE__ */ jsx5(
19420
+ const config = {
19421
+ showControls: true,
19422
+ enableDownload: true,
19423
+ enablePrint: true,
19424
+ enableFullscreen: true,
19425
+ initialZoom: layout === "inline" ? "page-width" : 1.5
19426
+ };
19427
+ return /* @__PURE__ */ jsx5("div", { className: "w-full h-full flex items-center justify-center", children: /* @__PURE__ */ jsx5(
19420
19428
  Suspense,
19421
19429
  {
19422
19430
  fallback: /* @__PURE__ */ jsx5("div", { className: "flex items-center justify-center text-neutral-500 text-sm", children: "Loading document..." }),
19423
- children: /* @__PURE__ */ jsx5(AnyPDFViewer, { url: item.src })
19431
+ children: /* @__PURE__ */ jsx5(
19432
+ AnyPDFViewer,
19433
+ {
19434
+ url: item.src,
19435
+ config,
19436
+ height: "100%",
19437
+ width: "100%",
19438
+ title: item.title
19439
+ }
19440
+ )
19424
19441
  }
19425
19442
  ) });
19426
19443
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@page-speed/lightbox",
3
- "version": "0.1.4",
3
+ "version": "0.1.6",
4
4
  "description": "High-performance, feature-rich lightbox for OpenSite platform",
5
5
  "main": "dist/index.cjs",
6
6
  "module": "dist/index.js",
@@ -80,7 +80,7 @@
80
80
  },
81
81
  "dependencies": {
82
82
  "@page-speed/img": "^0.4.3",
83
- "@page-speed/pdf-viewer": "0.1.2",
83
+ "@page-speed/pdf-viewer": "0.1.4",
84
84
  "clsx": "^2.1.1",
85
85
  "tailwind-merge": "^3.4.0"
86
86
  }