@page-speed/lightbox 0.1.7 → 0.1.9

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.5_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.7_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,
@@ -18079,6 +18079,7 @@ __export(dist_exports, {
18079
18079
  calculateScaleForPageFit: () => calculateScaleForPageFit,
18080
18080
  createProgressiveFetchHandler: () => createProgressiveFetchHandler,
18081
18081
  downloadPDF: () => downloadPDF,
18082
+ extractPDFFilename: () => extractPDFFilename,
18082
18083
  extractPageText: () => extractPageText,
18083
18084
  formatFileSize: () => formatFileSize,
18084
18085
  getOptimalRangeHeader: () => getOptimalRangeHeader,
@@ -18336,6 +18337,9 @@ function useSearch(pdfDoc) {
18336
18337
  prevResult
18337
18338
  };
18338
18339
  }
18340
+ function cn2(...classes) {
18341
+ return classes.filter(Boolean).join(" ");
18342
+ }
18339
18343
  function PDFCanvas({
18340
18344
  pdfDoc,
18341
18345
  pageNumber,
@@ -18359,7 +18363,79 @@ function PDFCanvas({
18359
18363
  render();
18360
18364
  }
18361
18365
  }, [pdfDoc, pageNumber, scale, onRender]);
18362
- return /* @__PURE__ */ jsx4("div", { ref: containerRef, className: PDFViewer_default.canvas });
18366
+ return /* @__PURE__ */ jsx4(
18367
+ "div",
18368
+ {
18369
+ ref: containerRef,
18370
+ className: cn2(
18371
+ "flex-1 overflow-auto",
18372
+ "flex items-center justify-center",
18373
+ "p-4 min-h-0"
18374
+ ),
18375
+ "data-pdf-viewer": "canvas"
18376
+ }
18377
+ );
18378
+ }
18379
+ async function isLinearizedPDF(url) {
18380
+ try {
18381
+ const response = await fetch(url, { headers: { Range: "bytes=0-1024" } });
18382
+ const buffer = await response.arrayBuffer();
18383
+ const view = new Uint8Array(buffer);
18384
+ const text = new TextDecoder().decode(view);
18385
+ return text.includes("Linearized");
18386
+ } catch {
18387
+ return false;
18388
+ }
18389
+ }
18390
+ function extractPDFFilename(url, fallbackName) {
18391
+ try {
18392
+ const urlObj = new URL(url, window.location.origin);
18393
+ const pathname = urlObj.pathname;
18394
+ const segments = pathname.split("/").filter(Boolean);
18395
+ const lastSegment = segments[segments.length - 1] || "";
18396
+ if (lastSegment && lastSegment.includes(".")) {
18397
+ if (lastSegment.toLowerCase().endsWith(".pdf")) {
18398
+ return lastSegment;
18399
+ }
18400
+ const nameWithoutExt = lastSegment.substring(0, lastSegment.lastIndexOf("."));
18401
+ return `${nameWithoutExt}.pdf`;
18402
+ }
18403
+ if (lastSegment) {
18404
+ return `${lastSegment}.pdf`;
18405
+ }
18406
+ } catch {
18407
+ }
18408
+ const name = fallbackName || "document";
18409
+ return name.toLowerCase().endsWith(".pdf") ? name : `${name}.pdf`;
18410
+ }
18411
+ function downloadPDF(url, filename) {
18412
+ const link = document.createElement("a");
18413
+ link.href = url;
18414
+ link.download = filename || extractPDFFilename(url);
18415
+ document.body.appendChild(link);
18416
+ link.click();
18417
+ document.body.removeChild(link);
18418
+ }
18419
+ function calculateScaleForPageFit(pageWidth, pageHeight, containerWidth, containerHeight) {
18420
+ const widthRatio = containerWidth / pageWidth;
18421
+ const heightRatio = containerHeight / pageHeight;
18422
+ return Math.min(widthRatio, heightRatio);
18423
+ }
18424
+ function formatFileSize(bytes) {
18425
+ if (bytes === 0) return "0 Bytes";
18426
+ const k = 1024;
18427
+ const sizes = ["Bytes", "KB", "MB", "GB"];
18428
+ const i = Math.floor(Math.log(bytes) / Math.log(k));
18429
+ return Math.round(bytes / Math.pow(k, i) * 100) / 100 + " " + sizes[i];
18430
+ }
18431
+ async function extractPageText(pdfDoc, pageNumber) {
18432
+ try {
18433
+ const page = await pdfDoc.getPage(pageNumber);
18434
+ const textContent = await page.getTextContent();
18435
+ return textContent.items.filter((item) => "str" in item).map((item) => item.str).join(" ");
18436
+ } catch {
18437
+ return "";
18438
+ }
18363
18439
  }
18364
18440
  function PDFControls({
18365
18441
  pageState,
@@ -18372,93 +18448,151 @@ function PDFControls({
18372
18448
  url
18373
18449
  }) {
18374
18450
  if (!pdfDocument) return null;
18375
- return /* @__PURE__ */ jsxs("div", { className: PDFViewer_default.controls, children: [
18376
- /* @__PURE__ */ jsx22(
18377
- "button",
18378
- {
18379
- onClick: pageState.prevPage,
18380
- disabled: !pageState.canPrev,
18381
- title: "Previous page",
18382
- children: "<"
18383
- }
18384
- ),
18385
- /* @__PURE__ */ jsx22(
18386
- "input",
18387
- {
18388
- type: "number",
18389
- min: "1",
18390
- max: pdfDocument.numPages,
18391
- value: pageState.currentPage,
18392
- onChange: (e) => pageState.goToPage(parseInt(e.target.value, 10) || 1),
18393
- className: PDFViewer_default.pageInput
18394
- }
18395
- ),
18396
- /* @__PURE__ */ jsxs("span", { className: PDFViewer_default.pageTotal, children: [
18397
- "of ",
18398
- pdfDocument.numPages
18399
- ] }),
18400
- /* @__PURE__ */ jsx22(
18401
- "button",
18402
- {
18403
- onClick: pageState.nextPage,
18404
- disabled: !pageState.canNext,
18405
- title: "Next page",
18406
- children: ">"
18407
- }
18408
- ),
18409
- /* @__PURE__ */ jsx22(
18410
- "button",
18411
- {
18412
- onClick: zoom.zoomOut,
18413
- disabled: !zoom.canZoomOut,
18414
- title: "Zoom out",
18415
- children: "-"
18416
- }
18417
- ),
18418
- /* @__PURE__ */ jsxs("span", { className: PDFViewer_default.zoomLevel, children: [
18419
- Math.round(zoom.zoomLevel * 100),
18420
- "%"
18421
- ] }),
18422
- /* @__PURE__ */ jsx22(
18423
- "button",
18424
- {
18425
- onClick: zoom.zoomIn,
18426
- disabled: !zoom.canZoomIn,
18427
- title: "Zoom in",
18428
- children: "+"
18429
- }
18430
- ),
18431
- /* @__PURE__ */ jsx22(
18432
- "input",
18433
- {
18434
- type: "text",
18435
- placeholder: "Search...",
18436
- value: search.query,
18437
- onChange: (e) => search.search(e.target.value),
18438
- className: PDFViewer_default.searchInput
18439
- }
18440
- ),
18441
- search.results.length > 0 && /* @__PURE__ */ jsxs("span", { className: PDFViewer_default.searchResults, children: [
18442
- search.results.length,
18443
- " results"
18444
- ] }),
18445
- enableDownload && /* @__PURE__ */ jsx22("a", { href: url, download: true, className: PDFViewer_default.button, title: "Download", children: "Download" }),
18446
- enablePrint && /* @__PURE__ */ jsx22("button", { onClick: () => window.print(), title: "Print", children: "Print" }),
18447
- enableFullscreen && typeof document !== "undefined" && /* @__PURE__ */ jsx22(
18448
- "button",
18449
- {
18450
- onClick: () => {
18451
- if (document.fullscreenElement) {
18452
- document.exitFullscreen();
18453
- } else {
18454
- document.documentElement?.requestFullscreen();
18455
- }
18456
- },
18457
- title: "Fullscreen",
18458
- children: "Fullscreen"
18459
- }
18460
- )
18461
- ] });
18451
+ return /* @__PURE__ */ jsxs(
18452
+ "div",
18453
+ {
18454
+ className: cn2(
18455
+ "flex items-center gap-2",
18456
+ "px-3 py-2",
18457
+ "bg-background border-b border-border",
18458
+ "overflow-x-auto flex-wrap",
18459
+ "flex-shrink-0 z-10"
18460
+ ),
18461
+ "data-pdf-viewer": "controls",
18462
+ children: [
18463
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1", children: [
18464
+ /* @__PURE__ */ jsx22(
18465
+ IconButton,
18466
+ {
18467
+ onClick: pageState.prevPage,
18468
+ disabled: !pageState.canPrev,
18469
+ title: "Previous page",
18470
+ children: /* @__PURE__ */ jsx22(ChevronLeftIcon, {})
18471
+ }
18472
+ ),
18473
+ /* @__PURE__ */ jsx22(
18474
+ "input",
18475
+ {
18476
+ type: "number",
18477
+ min: "1",
18478
+ max: pdfDocument.numPages,
18479
+ value: pageState.currentPage,
18480
+ onChange: (e) => pageState.goToPage(parseInt(e.target.value, 10) || 1),
18481
+ className: cn2(
18482
+ "w-14 h-8 px-2",
18483
+ "text-center text-sm font-medium",
18484
+ "bg-background border border-input rounded-md",
18485
+ "focus:outline-none focus:ring-2 focus:ring-ring"
18486
+ )
18487
+ }
18488
+ ),
18489
+ /* @__PURE__ */ jsxs("span", { className: "text-sm text-muted-foreground whitespace-nowrap", children: [
18490
+ "of ",
18491
+ pdfDocument.numPages
18492
+ ] }),
18493
+ /* @__PURE__ */ jsx22(
18494
+ IconButton,
18495
+ {
18496
+ onClick: pageState.nextPage,
18497
+ disabled: !pageState.canNext,
18498
+ title: "Next page",
18499
+ children: /* @__PURE__ */ jsx22(ChevronRightIcon, {})
18500
+ }
18501
+ )
18502
+ ] }),
18503
+ /* @__PURE__ */ jsx22("div", { className: "w-px h-6 bg-border mx-1" }),
18504
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1", children: [
18505
+ /* @__PURE__ */ jsx22(
18506
+ IconButton,
18507
+ {
18508
+ onClick: zoom.zoomOut,
18509
+ disabled: !zoom.canZoomOut,
18510
+ title: "Zoom out",
18511
+ children: /* @__PURE__ */ jsx22(MinusIcon, {})
18512
+ }
18513
+ ),
18514
+ /* @__PURE__ */ jsxs("span", { className: "text-sm font-medium text-foreground min-w-[3.5rem] text-center", children: [
18515
+ Math.round(zoom.zoomLevel * 100),
18516
+ "%"
18517
+ ] }),
18518
+ /* @__PURE__ */ jsx22(
18519
+ IconButton,
18520
+ {
18521
+ onClick: zoom.zoomIn,
18522
+ disabled: !zoom.canZoomIn,
18523
+ title: "Zoom in",
18524
+ children: /* @__PURE__ */ jsx22(PlusIcon, {})
18525
+ }
18526
+ )
18527
+ ] }),
18528
+ /* @__PURE__ */ jsx22("div", { className: "w-px h-6 bg-border mx-1" }),
18529
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
18530
+ /* @__PURE__ */ jsxs("div", { className: "relative", children: [
18531
+ /* @__PURE__ */ jsx22(
18532
+ "input",
18533
+ {
18534
+ type: "text",
18535
+ placeholder: "Search...",
18536
+ value: search.query,
18537
+ onChange: (e) => search.search(e.target.value),
18538
+ className: cn2(
18539
+ "h-8 pl-8 pr-3 w-32",
18540
+ "text-sm",
18541
+ "bg-background border border-input rounded-md",
18542
+ "placeholder:text-muted-foreground",
18543
+ "focus:outline-none focus:ring-2 focus:ring-ring"
18544
+ )
18545
+ }
18546
+ ),
18547
+ /* @__PURE__ */ jsx22("div", { className: "absolute left-2.5 top-1/2 -translate-y-1/2 text-muted-foreground", children: /* @__PURE__ */ jsx22(SearchIcon, {}) })
18548
+ ] }),
18549
+ search.results.length > 0 && /* @__PURE__ */ jsxs("span", { className: "text-xs text-muted-foreground whitespace-nowrap", children: [
18550
+ search.results.length,
18551
+ " results"
18552
+ ] })
18553
+ ] }),
18554
+ /* @__PURE__ */ jsx22("div", { className: "flex-1" }),
18555
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
18556
+ enableDownload && /* @__PURE__ */ jsxs(
18557
+ ActionButton,
18558
+ {
18559
+ onClick: () => downloadPDF(url),
18560
+ title: "Download",
18561
+ children: [
18562
+ /* @__PURE__ */ jsx22(DownloadIcon, {}),
18563
+ /* @__PURE__ */ jsx22("span", { children: "Download" })
18564
+ ]
18565
+ }
18566
+ ),
18567
+ enablePrint && /* @__PURE__ */ jsxs(
18568
+ ActionButton,
18569
+ {
18570
+ onClick: () => window.print(),
18571
+ title: "Print",
18572
+ children: [
18573
+ /* @__PURE__ */ jsx22(PrintIcon, {}),
18574
+ /* @__PURE__ */ jsx22("span", { children: "Print" })
18575
+ ]
18576
+ }
18577
+ ),
18578
+ enableFullscreen && typeof document !== "undefined" && /* @__PURE__ */ jsx22(
18579
+ IconButton,
18580
+ {
18581
+ onClick: () => {
18582
+ if (document.fullscreenElement) {
18583
+ document.exitFullscreen();
18584
+ } else {
18585
+ document.documentElement?.requestFullscreen();
18586
+ }
18587
+ },
18588
+ title: "Fullscreen",
18589
+ children: /* @__PURE__ */ jsx22(FullscreenIcon, {})
18590
+ }
18591
+ )
18592
+ ] })
18593
+ ]
18594
+ }
18595
+ );
18462
18596
  }
18463
18597
  function PDFThumbnails({
18464
18598
  pdfDoc,
@@ -18496,32 +18630,55 @@ function PDFThumbnails({
18496
18630
  };
18497
18631
  generateThumbnails();
18498
18632
  }, [pdfDoc, numPages]);
18499
- return /* @__PURE__ */ jsx32("div", { className: PDFViewer_default.thumbnails, children: thumbnails.map((thumb, idx) => /* @__PURE__ */ jsxs2(
18633
+ return /* @__PURE__ */ jsx32(
18500
18634
  "div",
18501
18635
  {
18502
- className: `${PDFViewer_default.thumbnail} ${idx + 1 === currentPage ? PDFViewer_default.active : ""}`,
18503
- onClick: () => onSelectPage(idx + 1),
18504
- children: [
18505
- /* @__PURE__ */ jsx32(
18506
- "canvas",
18507
- {
18508
- width: thumb.width,
18509
- height: thumb.height,
18510
- ref: (el) => {
18511
- if (el && thumb) {
18512
- const ctx = el.getContext("2d");
18513
- if (ctx) {
18514
- ctx.drawImage(thumb, 0, 0);
18515
- }
18516
- }
18517
- }
18518
- }
18519
- ),
18520
- /* @__PURE__ */ jsx32("span", { className: PDFViewer_default.pageNumber, children: idx + 1 })
18521
- ]
18522
- },
18523
- idx
18524
- )) });
18636
+ className: cn2(
18637
+ "w-32 flex-shrink-0",
18638
+ "overflow-y-auto",
18639
+ "bg-muted/50 border-r border-border",
18640
+ "p-2 space-y-2"
18641
+ ),
18642
+ "data-pdf-viewer": "thumbnails",
18643
+ children: thumbnails.map((thumb, idx) => /* @__PURE__ */ jsxs2(
18644
+ "div",
18645
+ {
18646
+ className: cn2(
18647
+ "cursor-pointer rounded-md overflow-hidden",
18648
+ "border-2 transition-colors duration-150",
18649
+ idx + 1 === currentPage ? "border-primary ring-2 ring-primary/20" : "border-transparent hover:border-muted-foreground/30"
18650
+ ),
18651
+ onClick: () => onSelectPage(idx + 1),
18652
+ "data-pdf-viewer": "thumbnail",
18653
+ "data-active": idx + 1 === currentPage,
18654
+ children: [
18655
+ /* @__PURE__ */ jsx32(
18656
+ "canvas",
18657
+ {
18658
+ width: thumb.width,
18659
+ height: thumb.height,
18660
+ ref: (el) => {
18661
+ if (el && thumb) {
18662
+ const ctx = el.getContext("2d");
18663
+ if (ctx) {
18664
+ ctx.drawImage(thumb, 0, 0);
18665
+ }
18666
+ }
18667
+ },
18668
+ className: "w-full h-auto"
18669
+ }
18670
+ ),
18671
+ /* @__PURE__ */ jsx32("span", { className: cn2(
18672
+ "block text-center text-xs py-1",
18673
+ "text-muted-foreground",
18674
+ idx + 1 === currentPage && "text-primary font-medium"
18675
+ ), children: idx + 1 })
18676
+ ]
18677
+ },
18678
+ idx
18679
+ ))
18680
+ }
18681
+ );
18525
18682
  }
18526
18683
  function PDFViewer({
18527
18684
  url,
@@ -18569,19 +18726,48 @@ function PDFViewer({
18569
18726
  }
18570
18727
  }, [search.results, onSearchResults]);
18571
18728
  if (error) {
18572
- return /* @__PURE__ */ jsx42("div", { className: PDFViewer_default.error, style: { height, width }, children: /* @__PURE__ */ jsxs3("p", { children: [
18573
- "Failed to load PDF: ",
18574
- error.message
18575
- ] }) });
18729
+ return /* @__PURE__ */ jsx42(
18730
+ "div",
18731
+ {
18732
+ className: cn2(
18733
+ "flex items-center justify-center",
18734
+ "bg-background rounded-lg",
18735
+ className
18736
+ ),
18737
+ style: { height, width },
18738
+ children: /* @__PURE__ */ jsxs3("p", { className: "text-destructive text-base", children: [
18739
+ "Failed to load PDF: ",
18740
+ error.message
18741
+ ] })
18742
+ }
18743
+ );
18576
18744
  }
18577
18745
  if (loading) {
18578
- return /* @__PURE__ */ jsx42("div", { className: PDFViewer_default.loading, style: { height, width }, children: /* @__PURE__ */ jsx42("p", { children: "Loading PDF..." }) });
18746
+ return /* @__PURE__ */ jsx42(
18747
+ "div",
18748
+ {
18749
+ className: cn2(
18750
+ "flex items-center justify-center",
18751
+ "bg-background rounded-lg",
18752
+ className
18753
+ ),
18754
+ style: { height, width },
18755
+ children: /* @__PURE__ */ jsx42("p", { className: "text-muted-foreground text-base", children: "Loading PDF..." })
18756
+ }
18757
+ );
18579
18758
  }
18580
18759
  return /* @__PURE__ */ jsxs3(
18581
18760
  "div",
18582
18761
  {
18583
- className: `${PDFViewer_default.viewer} ${className || ""}`,
18762
+ className: cn2(
18763
+ "flex flex-col",
18764
+ "bg-muted/30 rounded-lg overflow-hidden",
18765
+ "shadow-sm border border-border",
18766
+ "font-sans",
18767
+ className
18768
+ ),
18584
18769
  style: { height, width, ...style },
18770
+ "data-pdf-viewer": "root",
18585
18771
  children: [
18586
18772
  showControls && /* @__PURE__ */ jsx42(
18587
18773
  PDFControls,
@@ -18596,7 +18782,7 @@ function PDFViewer({
18596
18782
  url
18597
18783
  }
18598
18784
  ),
18599
- /* @__PURE__ */ jsxs3("div", { className: PDFViewer_default.content, children: [
18785
+ /* @__PURE__ */ jsxs3("div", { className: "flex flex-1 overflow-hidden min-h-0", "data-pdf-viewer": "content", children: [
18600
18786
  showThumbnails && document2 && /* @__PURE__ */ jsx42(
18601
18787
  PDFThumbnails,
18602
18788
  {
@@ -18620,46 +18806,6 @@ function PDFViewer({
18620
18806
  }
18621
18807
  );
18622
18808
  }
18623
- async function isLinearizedPDF(url) {
18624
- try {
18625
- const response = await fetch(url, { headers: { Range: "bytes=0-1024" } });
18626
- const buffer = await response.arrayBuffer();
18627
- const view = new Uint8Array(buffer);
18628
- const text = new TextDecoder().decode(view);
18629
- return text.includes("Linearized");
18630
- } catch {
18631
- return false;
18632
- }
18633
- }
18634
- function downloadPDF(url, filename) {
18635
- const link = document.createElement("a");
18636
- link.href = url;
18637
- link.download = filename || "document.pdf";
18638
- document.body.appendChild(link);
18639
- link.click();
18640
- document.body.removeChild(link);
18641
- }
18642
- function calculateScaleForPageFit(pageWidth, pageHeight, containerWidth, containerHeight) {
18643
- const widthRatio = containerWidth / pageWidth;
18644
- const heightRatio = containerHeight / pageHeight;
18645
- return Math.min(widthRatio, heightRatio);
18646
- }
18647
- function formatFileSize(bytes) {
18648
- if (bytes === 0) return "0 Bytes";
18649
- const k = 1024;
18650
- const sizes = ["Bytes", "KB", "MB", "GB"];
18651
- const i = Math.floor(Math.log(bytes) / Math.log(k));
18652
- return Math.round(bytes / Math.pow(k, i) * 100) / 100 + " " + sizes[i];
18653
- }
18654
- async function extractPageText(pdfDoc, pageNumber) {
18655
- try {
18656
- const page = await pdfDoc.getPage(pageNumber);
18657
- const textContent = await page.getTextContent();
18658
- return textContent.items.filter((item) => "str" in item).map((item) => item.str).join(" ");
18659
- } catch {
18660
- return "";
18661
- }
18662
- }
18663
18809
  function getOptimalRangeHeader(fileSize) {
18664
18810
  const chunkSize = Math.min(65536, Math.ceil(fileSize * 0.1));
18665
18811
  return {
@@ -18684,33 +18830,80 @@ function createProgressiveFetchHandler(onProgress) {
18684
18830
  return response.arrayBuffer();
18685
18831
  };
18686
18832
  }
18687
- var DEFAULT_SCALE, CACHE_SIZE, MIN_ZOOM, MAX_ZOOM, ZOOM_STEP, PDFViewer_default, linearizedPDFConfig;
18833
+ var DEFAULT_SCALE, CACHE_SIZE, MIN_ZOOM, MAX_ZOOM, ZOOM_STEP, ChevronLeftIcon, ChevronRightIcon, MinusIcon, PlusIcon, DownloadIcon, PrintIcon, FullscreenIcon, SearchIcon, IconButton, ActionButton, linearizedPDFConfig;
18688
18834
  var init_dist = __esm({
18689
- "node_modules/.pnpm/@page-speed+pdf-viewer@0.1.5_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@page-speed/pdf-viewer/dist/index.js"() {
18835
+ "node_modules/.pnpm/@page-speed+pdf-viewer@0.1.7_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@page-speed/pdf-viewer/dist/index.js"() {
18690
18836
  "use client";
18691
18837
  DEFAULT_SCALE = 1.5;
18692
18838
  CACHE_SIZE = 50 * 1024 * 1024;
18693
18839
  MIN_ZOOM = 0.5;
18694
18840
  MAX_ZOOM = 3;
18695
18841
  ZOOM_STEP = 0.25;
18696
- PDFViewer_default = {
18697
- viewer: "PDFViewer_viewer",
18698
- controls: "PDFViewer_controls",
18699
- pageInput: "PDFViewer_pageInput",
18700
- pageTotal: "PDFViewer_pageTotal",
18701
- zoomLevel: "PDFViewer_zoomLevel",
18702
- searchInput: "PDFViewer_searchInput",
18703
- searchResults: "PDFViewer_searchResults",
18704
- button: "PDFViewer_button",
18705
- content: "PDFViewer_content",
18706
- canvas: "PDFViewer_canvas",
18707
- thumbnails: "PDFViewer_thumbnails",
18708
- thumbnail: "PDFViewer_thumbnail",
18709
- active: "PDFViewer_active",
18710
- pageNumber: "PDFViewer_pageNumber",
18711
- loading: "PDFViewer_loading",
18712
- error: "PDFViewer_error"
18713
- };
18842
+ ChevronLeftIcon = () => /* @__PURE__ */ jsx22("svg", { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx22("path", { d: "M15 18l-6-6 6-6" }) });
18843
+ ChevronRightIcon = () => /* @__PURE__ */ jsx22("svg", { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx22("path", { d: "M9 18l6-6-6-6" }) });
18844
+ MinusIcon = () => /* @__PURE__ */ jsx22("svg", { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx22("path", { d: "M5 12h14" }) });
18845
+ PlusIcon = () => /* @__PURE__ */ jsx22("svg", { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx22("path", { d: "M12 5v14M5 12h14" }) });
18846
+ DownloadIcon = () => /* @__PURE__ */ jsx22("svg", { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx22("path", { d: "M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4M7 10l5 5 5-5M12 15V3" }) });
18847
+ PrintIcon = () => /* @__PURE__ */ jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
18848
+ /* @__PURE__ */ jsx22("polyline", { points: "6 9 6 2 18 2 18 9" }),
18849
+ /* @__PURE__ */ jsx22("path", { d: "M6 18H4a2 2 0 0 1-2-2v-5a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2v5a2 2 0 0 1-2 2h-2" }),
18850
+ /* @__PURE__ */ jsx22("rect", { x: "6", y: "14", width: "12", height: "8" })
18851
+ ] });
18852
+ FullscreenIcon = () => /* @__PURE__ */ jsx22("svg", { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx22("path", { d: "M8 3H5a2 2 0 0 0-2 2v3m18 0V5a2 2 0 0 0-2-2h-3m0 18h3a2 2 0 0 0 2-2v-3M3 16v3a2 2 0 0 0 2 2h3" }) });
18853
+ SearchIcon = () => /* @__PURE__ */ jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
18854
+ /* @__PURE__ */ jsx22("circle", { cx: "11", cy: "11", r: "8" }),
18855
+ /* @__PURE__ */ jsx22("path", { d: "M21 21l-4.35-4.35" })
18856
+ ] });
18857
+ IconButton = ({
18858
+ onClick,
18859
+ disabled,
18860
+ title,
18861
+ children,
18862
+ className
18863
+ }) => /* @__PURE__ */ jsx22(
18864
+ "button",
18865
+ {
18866
+ type: "button",
18867
+ onClick,
18868
+ disabled,
18869
+ title,
18870
+ className: cn2(
18871
+ "inline-flex items-center justify-center",
18872
+ "h-8 w-8 rounded-md",
18873
+ "bg-secondary text-secondary-foreground",
18874
+ "hover:bg-secondary/80",
18875
+ "transition-colors duration-150",
18876
+ "disabled:opacity-50 disabled:pointer-events-none",
18877
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
18878
+ className
18879
+ ),
18880
+ children
18881
+ }
18882
+ );
18883
+ ActionButton = ({
18884
+ onClick,
18885
+ title,
18886
+ children,
18887
+ className
18888
+ }) => /* @__PURE__ */ jsx22(
18889
+ "button",
18890
+ {
18891
+ type: "button",
18892
+ onClick,
18893
+ title,
18894
+ className: cn2(
18895
+ "inline-flex items-center justify-center gap-1.5",
18896
+ "h-8 px-3 rounded-md",
18897
+ "bg-primary text-primary-foreground",
18898
+ "hover:bg-primary/90",
18899
+ "text-sm font-medium",
18900
+ "transition-colors duration-150",
18901
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
18902
+ className
18903
+ ),
18904
+ children
18905
+ }
18906
+ );
18714
18907
  linearizedPDFConfig = {
18715
18908
  rangeChunkSize: 65536,
18716
18909
  // 64 KB chunks for streaming
@@ -22639,7 +22832,7 @@ var DEFAULT_CONTROLS = {
22639
22832
  function mergeControls(overrides) {
22640
22833
  return { ...DEFAULT_CONTROLS, ...overrides || {} };
22641
22834
  }
22642
- var IconButton = ({
22835
+ var IconButton2 = ({
22643
22836
  onClick,
22644
22837
  disabled,
22645
22838
  ariaLabel,
@@ -22668,8 +22861,8 @@ var IconButton = ({
22668
22861
  var ArrowLeftIcon = () => /* @__PURE__ */ jsx8("svg", { xmlns: "http://www.w3.org/2000/svg", width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx8("path", { d: "M19 12H5M12 19l-7-7 7-7" }) });
22669
22862
  var ArrowRightIcon = () => /* @__PURE__ */ jsx8("svg", { xmlns: "http://www.w3.org/2000/svg", width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx8("path", { d: "M5 12h14M12 5l7 7-7 7" }) });
22670
22863
  var CloseIcon = () => /* @__PURE__ */ jsx8("svg", { xmlns: "http://www.w3.org/2000/svg", width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx8("path", { d: "M18 6L6 18M6 6l12 12" }) });
22671
- var FullscreenIcon = () => /* @__PURE__ */ jsx8("svg", { xmlns: "http://www.w3.org/2000/svg", width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx8("path", { d: "M8 3H5a2 2 0 0 0-2 2v3m18 0V5a2 2 0 0 0-2-2h-3m0 18h3a2 2 0 0 0 2-2v-3M3 16v3a2 2 0 0 0 2 2h3" }) });
22672
- var DownloadIcon = () => /* @__PURE__ */ jsx8("svg", { xmlns: "http://www.w3.org/2000/svg", width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx8("path", { d: "M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4M7 10l5 5 5-5M12 15V3" }) });
22864
+ var FullscreenIcon2 = () => /* @__PURE__ */ jsx8("svg", { xmlns: "http://www.w3.org/2000/svg", width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx8("path", { d: "M8 3H5a2 2 0 0 0-2 2v3m18 0V5a2 2 0 0 0-2-2h-3m0 18h3a2 2 0 0 0 2-2v-3M3 16v3a2 2 0 0 0 2 2h3" }) });
22865
+ var DownloadIcon2 = () => /* @__PURE__ */ jsx8("svg", { xmlns: "http://www.w3.org/2000/svg", width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx8("path", { d: "M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4M7 10l5 5 5-5M12 15V3" }) });
22673
22866
  var ShareIcon = () => /* @__PURE__ */ jsx8("svg", { xmlns: "http://www.w3.org/2000/svg", width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx8("path", { d: "M4 12v8a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-8M16 6l-4-4-4 4M12 2v13" }) });
22674
22867
  function LightboxChrome({
22675
22868
  currentIndex,
@@ -22739,10 +22932,56 @@ function LightboxChrome({
22739
22932
  try {
22740
22933
  const response = await fetch(currentItem.src);
22741
22934
  const blob = await response.blob();
22935
+ const getFileExtension = () => {
22936
+ const contentType = response.headers.get("Content-Type");
22937
+ if (contentType) {
22938
+ const mimeToExt = {
22939
+ "application/pdf": ".pdf",
22940
+ "image/jpeg": ".jpg",
22941
+ "image/jpg": ".jpg",
22942
+ "image/png": ".png",
22943
+ "image/gif": ".gif",
22944
+ "image/webp": ".webp",
22945
+ "image/svg+xml": ".svg",
22946
+ "video/mp4": ".mp4",
22947
+ "video/webm": ".webm",
22948
+ "video/quicktime": ".mov"
22949
+ };
22950
+ const baseMime = contentType.split(";")[0].trim().toLowerCase();
22951
+ if (mimeToExt[baseMime]) {
22952
+ return mimeToExt[baseMime];
22953
+ }
22954
+ }
22955
+ try {
22956
+ const urlObj = new URL(currentItem.src, window.location.origin);
22957
+ const pathname = urlObj.pathname;
22958
+ const lastDotIndex = pathname.lastIndexOf(".");
22959
+ if (lastDotIndex > pathname.lastIndexOf("/")) {
22960
+ const ext = pathname.substring(lastDotIndex).toLowerCase();
22961
+ if (ext.length >= 2 && ext.length <= 6) {
22962
+ return ext;
22963
+ }
22964
+ }
22965
+ } catch {
22966
+ }
22967
+ const typeToExt = {
22968
+ "pdf": ".pdf",
22969
+ "image": ".jpg",
22970
+ "video": ".mp4"
22971
+ };
22972
+ if (currentItem.type && typeToExt[currentItem.type]) {
22973
+ return typeToExt[currentItem.type];
22974
+ }
22975
+ return "";
22976
+ };
22977
+ const baseName = currentItem.title || "download";
22978
+ const extension = getFileExtension();
22979
+ const hasExtension = baseName.includes(".") && baseName.lastIndexOf(".") > baseName.length - 6;
22980
+ const filename = hasExtension ? baseName : `${baseName}${extension}`;
22742
22981
  const url = window.URL.createObjectURL(blob);
22743
22982
  const link = document.createElement("a");
22744
22983
  link.href = url;
22745
- link.download = currentItem.title || "download";
22984
+ link.download = filename;
22746
22985
  document.body.appendChild(link);
22747
22986
  link.click();
22748
22987
  document.body.removeChild(link);
@@ -22761,23 +23000,23 @@ function LightboxChrome({
22761
23000
  className
22762
23001
  ), children: [
22763
23002
  resolved.navigation && /* @__PURE__ */ jsxs4("div", { className: "flex items-center gap-2", children: [
22764
- /* @__PURE__ */ jsx8(IconButton, { onClick: onPrev, disabled: !canPrev, ariaLabel: "Previous item", children: /* @__PURE__ */ jsx8(ArrowLeftIcon, {}) }),
22765
- /* @__PURE__ */ jsx8(IconButton, { onClick: onNext, disabled: !canNext, ariaLabel: "Next item", children: /* @__PURE__ */ jsx8(ArrowRightIcon, {}) })
23003
+ /* @__PURE__ */ jsx8(IconButton2, { onClick: onPrev, disabled: !canPrev, ariaLabel: "Previous item", children: /* @__PURE__ */ jsx8(ArrowLeftIcon, {}) }),
23004
+ /* @__PURE__ */ jsx8(IconButton2, { onClick: onNext, disabled: !canNext, ariaLabel: "Next item", children: /* @__PURE__ */ jsx8(ArrowRightIcon, {}) })
22766
23005
  ] }),
22767
23006
  /* @__PURE__ */ jsx8("div", { className: "flex flex-col", children: resolved.captions && currentItem && /* @__PURE__ */ jsxs4(Fragment, { children: [
22768
23007
  currentItem.title && /* @__PURE__ */ jsx8("div", { className: "text-sm font-semibold", children: currentItem.title }),
22769
23008
  currentItem.caption && /* @__PURE__ */ jsx8("div", { className: "text-xs text-white/70", children: currentItem.caption })
22770
23009
  ] }) }),
22771
23010
  /* @__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, {}) }),
23011
+ resolved.share && "share" in navigator && /* @__PURE__ */ jsx8(IconButton2, { onClick: handleShare, ariaLabel: "Share", children: /* @__PURE__ */ jsx8(ShareIcon, {}) }),
23012
+ resolved.fullscreen && /* @__PURE__ */ jsx8(IconButton2, { onClick: handleFullscreen, ariaLabel: isFullscreen ? "Exit fullscreen" : "Fullscreen", children: /* @__PURE__ */ jsx8(FullscreenIcon2, {}) }),
23013
+ resolved.download && currentItem?.src && /* @__PURE__ */ jsx8(IconButton2, { onClick: handleDownload, ariaLabel: "Download", children: /* @__PURE__ */ jsx8(DownloadIcon2, {}) }),
22775
23014
  resolved.counter && totalItems > 0 && /* @__PURE__ */ jsxs4("span", { className: "text-xs text-white/70", children: [
22776
23015
  currentIndex + 1,
22777
23016
  " / ",
22778
23017
  totalItems
22779
23018
  ] }),
22780
- resolved.closeButton && /* @__PURE__ */ jsx8(IconButton, { onClick: onClose, ariaLabel: "Close lightbox", children: /* @__PURE__ */ jsx8(CloseIcon, {}) })
23019
+ resolved.closeButton && /* @__PURE__ */ jsx8(IconButton2, { onClick: onClose, ariaLabel: "Close lightbox", children: /* @__PURE__ */ jsx8(CloseIcon, {}) })
22781
23020
  ] })
22782
23021
  ] });
22783
23022
  }
@@ -22787,14 +23026,14 @@ function LightboxChrome({
22787
23026
  "flex items-center gap-2",
22788
23027
  className
22789
23028
  ), children: [
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, {}) }),
22793
- resolved.closeButton && /* @__PURE__ */ jsx8(IconButton, { onClick: onClose, ariaLabel: "Close lightbox", children: /* @__PURE__ */ jsx8(CloseIcon, {}) })
23029
+ resolved.share && "share" in navigator && /* @__PURE__ */ jsx8(IconButton2, { onClick: handleShare, ariaLabel: "Share", children: /* @__PURE__ */ jsx8(ShareIcon, {}) }),
23030
+ resolved.fullscreen && /* @__PURE__ */ jsx8(IconButton2, { onClick: handleFullscreen, ariaLabel: isFullscreen ? "Exit fullscreen" : "Fullscreen", children: /* @__PURE__ */ jsx8(FullscreenIcon2, {}) }),
23031
+ resolved.download && currentItem?.src && /* @__PURE__ */ jsx8(IconButton2, { onClick: handleDownload, ariaLabel: "Download", children: /* @__PURE__ */ jsx8(DownloadIcon2, {}) }),
23032
+ resolved.closeButton && /* @__PURE__ */ jsx8(IconButton2, { onClick: onClose, ariaLabel: "Close lightbox", children: /* @__PURE__ */ jsx8(CloseIcon, {}) })
22794
23033
  ] }),
22795
23034
  resolved.navigation && /* @__PURE__ */ jsxs4("div", { className: "fixed bottom-6 right-6 z-50 flex items-center gap-3", children: [
22796
- /* @__PURE__ */ jsx8(IconButton, { onClick: onPrev, disabled: !canPrev, ariaLabel: "Previous item", children: /* @__PURE__ */ jsx8(ArrowLeftIcon, {}) }),
22797
- /* @__PURE__ */ jsx8(IconButton, { onClick: onNext, disabled: !canNext, ariaLabel: "Next item", children: /* @__PURE__ */ jsx8(ArrowRightIcon, {}) })
23035
+ /* @__PURE__ */ jsx8(IconButton2, { onClick: onPrev, disabled: !canPrev, ariaLabel: "Previous item", children: /* @__PURE__ */ jsx8(ArrowLeftIcon, {}) }),
23036
+ /* @__PURE__ */ jsx8(IconButton2, { onClick: onNext, disabled: !canNext, ariaLabel: "Next item", children: /* @__PURE__ */ jsx8(ArrowRightIcon, {}) })
22798
23037
  ] }),
22799
23038
  resolved.captions && currentItem && (currentItem.title || currentItem.caption) && /* @__PURE__ */ jsxs4("div", { className: cn(
22800
23039
  "fixed bottom-6 left-6 z-50",