pdfjs-reader-core 0.2.16 → 0.3.0

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.js CHANGED
@@ -177,6 +177,122 @@ function clearDocumentCache(url) {
177
177
  documentCache.clear();
178
178
  }
179
179
  }
180
+ function loadDocumentWithCallbacks(options) {
181
+ const {
182
+ src,
183
+ workerSrc,
184
+ password,
185
+ onProgress,
186
+ onDocumentReady,
187
+ onFirstPageReady,
188
+ enableRangeRequests = true,
189
+ enableStreaming = true,
190
+ cacheDocument = true,
191
+ signal
192
+ } = options;
193
+ const abortController = new AbortController();
194
+ if (signal) {
195
+ signal.addEventListener("abort", () => abortController.abort());
196
+ }
197
+ const promise = (async () => {
198
+ if (abortController.signal.aborted) {
199
+ throw new DOMException("Aborted", "AbortError");
200
+ }
201
+ await initializePDFJS({ workerSrc });
202
+ if (abortController.signal.aborted) {
203
+ throw new DOMException("Aborted", "AbortError");
204
+ }
205
+ const cacheKey = typeof src === "string" ? src : null;
206
+ if (cacheKey && cacheDocument && documentCache.has(cacheKey)) {
207
+ const cachedDoc = documentCache.get(cacheKey);
208
+ try {
209
+ const numPages2 = cachedDoc.numPages;
210
+ const isDestroyed = cachedDoc._transport?.destroyed || cachedDoc.destroyed;
211
+ if (numPages2 > 0 && !isDestroyed) {
212
+ onDocumentReady?.(cachedDoc, numPages2);
213
+ if (onFirstPageReady && numPages2 > 0) {
214
+ try {
215
+ const firstPage = await cachedDoc.getPage(1);
216
+ if (!abortController.signal.aborted) {
217
+ onFirstPageReady(firstPage);
218
+ }
219
+ } catch {
220
+ }
221
+ }
222
+ return {
223
+ document: cachedDoc,
224
+ numPages: numPages2
225
+ };
226
+ }
227
+ documentCache.delete(cacheKey);
228
+ } catch {
229
+ documentCache.delete(cacheKey);
230
+ }
231
+ }
232
+ const loadingParams = {
233
+ password,
234
+ isEvalSupported: false,
235
+ useSystemFonts: true,
236
+ disableRange: !enableRangeRequests,
237
+ disableStream: !enableStreaming,
238
+ disableAutoFetch: true
239
+ };
240
+ if (typeof src === "string") {
241
+ loadingParams.url = src;
242
+ } else {
243
+ loadingParams.data = src;
244
+ }
245
+ const loadingTask = pdfjsLib.getDocument(loadingParams);
246
+ const abortHandler = () => {
247
+ loadingTask.destroy();
248
+ };
249
+ abortController.signal.addEventListener("abort", abortHandler);
250
+ if (onProgress) {
251
+ loadingTask.onProgress = ({ loaded, total }) => {
252
+ if (!abortController.signal.aborted) {
253
+ onProgress({ loaded, total });
254
+ }
255
+ };
256
+ }
257
+ let document2;
258
+ try {
259
+ document2 = await loadingTask.promise;
260
+ } catch (error) {
261
+ abortController.signal.removeEventListener("abort", abortHandler);
262
+ if (abortController.signal.aborted) {
263
+ throw new DOMException("Aborted", "AbortError");
264
+ }
265
+ throw error;
266
+ }
267
+ abortController.signal.removeEventListener("abort", abortHandler);
268
+ if (abortController.signal.aborted) {
269
+ document2.destroy();
270
+ throw new DOMException("Aborted", "AbortError");
271
+ }
272
+ const numPages = document2.numPages;
273
+ onDocumentReady?.(document2, numPages);
274
+ if (onFirstPageReady && numPages > 0) {
275
+ try {
276
+ const firstPage = await document2.getPage(1);
277
+ if (!abortController.signal.aborted) {
278
+ onFirstPageReady(firstPage);
279
+ }
280
+ } catch {
281
+ }
282
+ }
283
+ if (cacheKey && cacheDocument) {
284
+ documentCache.set(cacheKey, document2);
285
+ }
286
+ return {
287
+ document: document2,
288
+ numPages
289
+ };
290
+ })();
291
+ return {
292
+ promise,
293
+ cancel: () => abortController.abort()
294
+ };
295
+ }
180
296
  var documentCache;
181
297
  var init_document_loader = __esm({
182
298
  "src/utils/document-loader.ts"() {
@@ -381,14 +497,18 @@ function createViewerStore(initialOverrides = {}) {
381
497
  isLoading: false,
382
498
  loadingProgress: null,
383
499
  error: null,
384
- currentPage: 1
500
+ currentPage: 1,
501
+ documentLoadingState: "ready"
385
502
  });
386
503
  } else {
387
504
  set({
388
505
  document: null,
389
506
  numPages: 0,
390
507
  isLoading: false,
391
- loadingProgress: null
508
+ loadingProgress: null,
509
+ documentLoadingState: "idle",
510
+ firstPageReady: false,
511
+ streamingProgress: null
392
512
  });
393
513
  }
394
514
  },
@@ -402,7 +522,17 @@ function createViewerStore(initialOverrides = {}) {
402
522
  set({ loadingProgress: progress });
403
523
  },
404
524
  setError: (error) => {
405
- set({ error, isLoading: false, loadingProgress: null });
525
+ set({ error, isLoading: false, loadingProgress: null, documentLoadingState: error ? "error" : "idle" });
526
+ },
527
+ // Progressive loading actions
528
+ setDocumentLoadingState: (documentLoadingState) => {
529
+ set({ documentLoadingState });
530
+ },
531
+ setFirstPageReady: (firstPageReady) => {
532
+ set({ firstPageReady });
533
+ },
534
+ setStreamingProgress: (streamingProgress) => {
535
+ set({ streamingProgress });
406
536
  },
407
537
  // Navigation actions
408
538
  setCurrentPage: (page) => {
@@ -551,6 +681,10 @@ var init_viewer_store = __esm({
551
681
  isLoading: false,
552
682
  loadingProgress: null,
553
683
  error: null,
684
+ // Progressive loading state
685
+ documentLoadingState: "idle",
686
+ firstPageReady: false,
687
+ streamingProgress: null,
554
688
  // Navigation state
555
689
  currentPage: 1,
556
690
  scale: 1,
@@ -1626,6 +1760,85 @@ var init_coordinates = __esm({
1626
1760
  }
1627
1761
  });
1628
1762
 
1763
+ // src/utils/page-turn-sound.ts
1764
+ function getAudioContext() {
1765
+ if (typeof window === "undefined") return null;
1766
+ if (!audioContext) {
1767
+ try {
1768
+ audioContext = new (window.AudioContext || window.webkitAudioContext)();
1769
+ } catch {
1770
+ return null;
1771
+ }
1772
+ }
1773
+ return audioContext;
1774
+ }
1775
+ function playPageTurnSound(volume = 0.3) {
1776
+ const ctx = getAudioContext();
1777
+ if (!ctx) return;
1778
+ if (ctx.state === "suspended") {
1779
+ ctx.resume();
1780
+ }
1781
+ const now = ctx.currentTime;
1782
+ const duration = 0.35;
1783
+ const bufferSize = Math.floor(ctx.sampleRate * duration);
1784
+ const noiseBuffer = ctx.createBuffer(1, bufferSize, ctx.sampleRate);
1785
+ const data = noiseBuffer.getChannelData(0);
1786
+ for (let i = 0; i < bufferSize; i++) {
1787
+ data[i] = Math.random() * 2 - 1;
1788
+ }
1789
+ const noiseSource = ctx.createBufferSource();
1790
+ noiseSource.buffer = noiseBuffer;
1791
+ const bandpass = ctx.createBiquadFilter();
1792
+ bandpass.type = "bandpass";
1793
+ bandpass.frequency.setValueAtTime(3e3, now);
1794
+ bandpass.frequency.exponentialRampToValueAtTime(800, now + duration * 0.6);
1795
+ bandpass.Q.setValueAtTime(0.8, now);
1796
+ const highpass = ctx.createBiquadFilter();
1797
+ highpass.type = "highpass";
1798
+ highpass.frequency.setValueAtTime(400, now);
1799
+ highpass.frequency.linearRampToValueAtTime(200, now + duration);
1800
+ const envelope = ctx.createGain();
1801
+ envelope.gain.setValueAtTime(0, now);
1802
+ envelope.gain.linearRampToValueAtTime(volume * 0.6, now + 0.02);
1803
+ envelope.gain.setValueAtTime(volume * 0.6, now + 0.05);
1804
+ envelope.gain.linearRampToValueAtTime(volume, now + duration * 0.3);
1805
+ envelope.gain.exponentialRampToValueAtTime(1e-3, now + duration);
1806
+ const snapBuffer = ctx.createBuffer(1, Math.floor(ctx.sampleRate * 0.08), ctx.sampleRate);
1807
+ const snapData = snapBuffer.getChannelData(0);
1808
+ for (let i = 0; i < snapData.length; i++) {
1809
+ snapData[i] = Math.random() * 2 - 1;
1810
+ }
1811
+ const snapSource = ctx.createBufferSource();
1812
+ snapSource.buffer = snapBuffer;
1813
+ const snapFilter = ctx.createBiquadFilter();
1814
+ snapFilter.type = "bandpass";
1815
+ snapFilter.frequency.setValueAtTime(2e3, now);
1816
+ snapFilter.Q.setValueAtTime(1.5, now);
1817
+ const snapEnvelope = ctx.createGain();
1818
+ snapEnvelope.gain.setValueAtTime(0, now);
1819
+ snapEnvelope.gain.setValueAtTime(0, now + duration * 0.7);
1820
+ snapEnvelope.gain.linearRampToValueAtTime(volume * 0.8, now + duration * 0.75);
1821
+ snapEnvelope.gain.exponentialRampToValueAtTime(1e-3, now + duration);
1822
+ noiseSource.connect(bandpass);
1823
+ bandpass.connect(highpass);
1824
+ highpass.connect(envelope);
1825
+ envelope.connect(ctx.destination);
1826
+ snapSource.connect(snapFilter);
1827
+ snapFilter.connect(snapEnvelope);
1828
+ snapEnvelope.connect(ctx.destination);
1829
+ noiseSource.start(now);
1830
+ noiseSource.stop(now + duration);
1831
+ snapSource.start(now);
1832
+ snapSource.stop(now + duration);
1833
+ }
1834
+ var audioContext;
1835
+ var init_page_turn_sound = __esm({
1836
+ "src/utils/page-turn-sound.ts"() {
1837
+ "use strict";
1838
+ audioContext = null;
1839
+ }
1840
+ });
1841
+
1629
1842
  // src/utils/index.ts
1630
1843
  var init_utils = __esm({
1631
1844
  "src/utils/index.ts"() {
@@ -1640,6 +1853,7 @@ var init_utils = __esm({
1640
1853
  init_agent_api();
1641
1854
  init_text_search();
1642
1855
  init_coordinates();
1856
+ init_page_turn_sound();
1643
1857
  }
1644
1858
  });
1645
1859
 
@@ -7771,10 +7985,57 @@ var init_PDFLoadingScreen = __esm({
7771
7985
  totalBytes,
7772
7986
  phase = "fetching",
7773
7987
  documentName,
7774
- className
7988
+ className,
7989
+ compact = false,
7990
+ showStreamingProgress = false
7775
7991
  }) {
7776
7992
  const hasProgress = progress !== void 0 && progress >= 0;
7777
7993
  const hasBytes = bytesLoaded !== void 0 && totalBytes !== void 0 && totalBytes > 0;
7994
+ if (compact || showStreamingProgress) {
7995
+ return /* @__PURE__ */ jsxs16(
7996
+ "div",
7997
+ {
7998
+ className: cn(
7999
+ "pdf-loading-compact",
8000
+ "flex items-center gap-3 px-4 py-3 bg-gray-800 text-white rounded-lg shadow-lg",
8001
+ className
8002
+ ),
8003
+ role: "status",
8004
+ "aria-live": "polite",
8005
+ children: [
8006
+ /* @__PURE__ */ jsx19(
8007
+ "div",
8008
+ {
8009
+ style: {
8010
+ width: 20,
8011
+ height: 20,
8012
+ border: "2px solid rgba(255,255,255,0.3)",
8013
+ borderTopColor: "#fff",
8014
+ borderRadius: "50%",
8015
+ animation: "spin 0.8s linear infinite"
8016
+ }
8017
+ }
8018
+ ),
8019
+ /* @__PURE__ */ jsx19("span", { className: "text-sm font-medium", children: phaseMessages[phase] }),
8020
+ hasProgress && /* @__PURE__ */ jsxs16("span", { className: "text-sm text-white/70", children: [
8021
+ Math.round(progress),
8022
+ "%"
8023
+ ] }),
8024
+ hasBytes && /* @__PURE__ */ jsxs16("span", { className: "text-xs text-white/50 font-mono", children: [
8025
+ formatBytes(bytesLoaded),
8026
+ " / ",
8027
+ formatBytes(totalBytes)
8028
+ ] }),
8029
+ /* @__PURE__ */ jsx19("style", { children: `
8030
+ @keyframes spin {
8031
+ 0% { transform: rotate(0deg); }
8032
+ 100% { transform: rotate(360deg); }
8033
+ }
8034
+ ` })
8035
+ ]
8036
+ }
8037
+ );
8038
+ }
7778
8039
  return /* @__PURE__ */ jsx19(
7779
8040
  "div",
7780
8041
  {
@@ -8007,9 +8268,117 @@ var init_PDFLoadingScreen2 = __esm({
8007
8268
  }
8008
8269
  });
8009
8270
 
8010
- // src/components/SelectionToolbar/SelectionToolbar.tsx
8011
- import { memo as memo19, useEffect as useEffect17, useState as useState16, useCallback as useCallback27, useRef as useRef14 } from "react";
8271
+ // src/components/PDFViewer/PageSkeleton.tsx
8272
+ import { memo as memo19 } from "react";
8012
8273
  import { jsx as jsx20, jsxs as jsxs17 } from "react/jsx-runtime";
8274
+ var PageSkeleton, DEFAULT_PAGE_WIDTH, DEFAULT_PAGE_HEIGHT;
8275
+ var init_PageSkeleton = __esm({
8276
+ "src/components/PDFViewer/PageSkeleton.tsx"() {
8277
+ "use strict";
8278
+ init_utils();
8279
+ PageSkeleton = memo19(function PageSkeleton2({
8280
+ pageNumber,
8281
+ width,
8282
+ height,
8283
+ className,
8284
+ isFirstPage = false
8285
+ }) {
8286
+ return /* @__PURE__ */ jsxs17(
8287
+ "div",
8288
+ {
8289
+ className: cn(
8290
+ "pdf-page-skeleton",
8291
+ "relative bg-white shadow-lg overflow-hidden",
8292
+ "flex items-center justify-center",
8293
+ className
8294
+ ),
8295
+ style: {
8296
+ width,
8297
+ height,
8298
+ minWidth: width,
8299
+ minHeight: height
8300
+ },
8301
+ "data-page-number": pageNumber,
8302
+ role: "img",
8303
+ "aria-label": `Loading page ${pageNumber}`,
8304
+ children: [
8305
+ /* @__PURE__ */ jsx20(
8306
+ "div",
8307
+ {
8308
+ className: "absolute inset-0 pdf-skeleton-shimmer",
8309
+ style: {
8310
+ background: "linear-gradient(90deg, #f0f0f0 25%, #e8e8e8 50%, #f0f0f0 75%)",
8311
+ backgroundSize: "200% 100%",
8312
+ animation: "shimmer 1.5s infinite linear"
8313
+ }
8314
+ }
8315
+ ),
8316
+ /* @__PURE__ */ jsxs17("div", { className: "absolute inset-0 p-6 flex flex-col", style: { opacity: 0.4 }, children: [
8317
+ /* @__PURE__ */ jsx20(
8318
+ "div",
8319
+ {
8320
+ className: "rounded",
8321
+ style: {
8322
+ width: "60%",
8323
+ height: 12,
8324
+ background: "#e0e0e0",
8325
+ marginBottom: 16
8326
+ }
8327
+ }
8328
+ ),
8329
+ [...Array(Math.min(12, Math.floor(height / 40)))].map((_, i) => /* @__PURE__ */ jsx20(
8330
+ "div",
8331
+ {
8332
+ className: "rounded",
8333
+ style: {
8334
+ width: `${75 + Math.sin(i * 0.7) * 20}%`,
8335
+ height: 8,
8336
+ background: "#e0e0e0",
8337
+ marginBottom: 12
8338
+ }
8339
+ },
8340
+ i
8341
+ ))
8342
+ ] }),
8343
+ /* @__PURE__ */ jsxs17("div", { className: "relative z-10 flex flex-col items-center gap-3 p-6 rounded-lg bg-white/90 shadow-sm", children: [
8344
+ /* @__PURE__ */ jsx20(
8345
+ "div",
8346
+ {
8347
+ className: "pdf-skeleton-spinner",
8348
+ style: {
8349
+ width: 32,
8350
+ height: 32,
8351
+ border: "3px solid #e5e7eb",
8352
+ borderTopColor: "#3b82f6",
8353
+ borderRadius: "50%",
8354
+ animation: "spin 0.8s linear infinite"
8355
+ }
8356
+ }
8357
+ ),
8358
+ /* @__PURE__ */ jsx20("div", { className: "text-sm text-gray-500 font-medium", children: isFirstPage ? "Loading document..." : `Loading page ${pageNumber}` })
8359
+ ] }),
8360
+ /* @__PURE__ */ jsx20("style", { children: `
8361
+ @keyframes shimmer {
8362
+ 0% { background-position: 200% 0; }
8363
+ 100% { background-position: -200% 0; }
8364
+ }
8365
+ @keyframes spin {
8366
+ 0% { transform: rotate(0deg); }
8367
+ 100% { transform: rotate(360deg); }
8368
+ }
8369
+ ` })
8370
+ ]
8371
+ }
8372
+ );
8373
+ });
8374
+ DEFAULT_PAGE_WIDTH = 612;
8375
+ DEFAULT_PAGE_HEIGHT = 792;
8376
+ }
8377
+ });
8378
+
8379
+ // src/components/SelectionToolbar/SelectionToolbar.tsx
8380
+ import { memo as memo20, useEffect as useEffect17, useState as useState16, useCallback as useCallback27, useRef as useRef14 } from "react";
8381
+ import { jsx as jsx21, jsxs as jsxs18 } from "react/jsx-runtime";
8013
8382
  function calculatePosition(selection) {
8014
8383
  if (!selection || selection.rects.length === 0) {
8015
8384
  return { top: 0, left: 0, visible: false };
@@ -8036,7 +8405,7 @@ var init_SelectionToolbar = __esm({
8036
8405
  { color: "pink", bg: "bg-pink-300", hoverBg: "hover:bg-pink-400", ringColor: "ring-pink-400" },
8037
8406
  { color: "orange", bg: "bg-orange-300", hoverBg: "hover:bg-orange-400", ringColor: "ring-orange-400" }
8038
8407
  ];
8039
- SelectionToolbar = memo19(function SelectionToolbar2({
8408
+ SelectionToolbar = memo20(function SelectionToolbar2({
8040
8409
  selection,
8041
8410
  onCreateHighlight,
8042
8411
  onCopy,
@@ -8085,7 +8454,7 @@ var init_SelectionToolbar = __esm({
8085
8454
  if (!position.visible || !selection?.text) {
8086
8455
  return null;
8087
8456
  }
8088
- return /* @__PURE__ */ jsxs17(
8457
+ return /* @__PURE__ */ jsxs18(
8089
8458
  "div",
8090
8459
  {
8091
8460
  ref: toolbarRef,
@@ -8109,7 +8478,7 @@ var init_SelectionToolbar = __esm({
8109
8478
  e.stopPropagation();
8110
8479
  },
8111
8480
  children: [
8112
- HIGHLIGHT_COLOR_BUTTONS.map((btn) => /* @__PURE__ */ jsx20(
8481
+ HIGHLIGHT_COLOR_BUTTONS.map((btn) => /* @__PURE__ */ jsx21(
8113
8482
  "button",
8114
8483
  {
8115
8484
  onClick: () => handleColorClick(btn.color),
@@ -8126,7 +8495,7 @@ var init_SelectionToolbar = __esm({
8126
8495
  ),
8127
8496
  title: `Highlight ${btn.color}`,
8128
8497
  "aria-label": `Highlight with ${btn.color}`,
8129
- children: /* @__PURE__ */ jsx20("svg", { className: "w-4 h-4 text-gray-700", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx20(
8498
+ children: /* @__PURE__ */ jsx21("svg", { className: "w-4 h-4 text-gray-700", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx21(
8130
8499
  "path",
8131
8500
  {
8132
8501
  strokeLinecap: "round",
@@ -8138,8 +8507,8 @@ var init_SelectionToolbar = __esm({
8138
8507
  },
8139
8508
  btn.color
8140
8509
  )),
8141
- /* @__PURE__ */ jsx20("div", { className: "w-px h-6 bg-gray-300 dark:bg-gray-600 mx-1" }),
8142
- /* @__PURE__ */ jsx20(
8510
+ /* @__PURE__ */ jsx21("div", { className: "w-px h-6 bg-gray-300 dark:bg-gray-600 mx-1" }),
8511
+ /* @__PURE__ */ jsx21(
8143
8512
  "button",
8144
8513
  {
8145
8514
  onClick: handleCopy,
@@ -8151,7 +8520,7 @@ var init_SelectionToolbar = __esm({
8151
8520
  ),
8152
8521
  title: "Copy text",
8153
8522
  "aria-label": "Copy selected text",
8154
- children: /* @__PURE__ */ jsx20("svg", { className: "w-5 h-5", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx20(
8523
+ children: /* @__PURE__ */ jsx21("svg", { className: "w-5 h-5", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx21(
8155
8524
  "path",
8156
8525
  {
8157
8526
  strokeLinecap: "round",
@@ -8178,8 +8547,8 @@ var init_SelectionToolbar2 = __esm({
8178
8547
  });
8179
8548
 
8180
8549
  // src/components/HighlightPopover/HighlightPopover.tsx
8181
- import { memo as memo20, useCallback as useCallback28, useState as useState17, useRef as useRef15, useEffect as useEffect18 } from "react";
8182
- import { jsx as jsx21, jsxs as jsxs18 } from "react/jsx-runtime";
8550
+ import { memo as memo21, useCallback as useCallback28, useState as useState17, useRef as useRef15, useEffect as useEffect18 } from "react";
8551
+ import { jsx as jsx22, jsxs as jsxs19 } from "react/jsx-runtime";
8183
8552
  function calculatePopoverPosition(highlight, scale, pageElement) {
8184
8553
  if (!pageElement || !highlight.rects.length) {
8185
8554
  return { top: 0, left: 0, visible: false };
@@ -8205,7 +8574,7 @@ var init_HighlightPopover = __esm({
8205
8574
  { color: "pink", bg: "bg-pink-300", hoverBg: "hover:bg-pink-400", borderColor: "border-pink-400" },
8206
8575
  { color: "orange", bg: "bg-orange-300", hoverBg: "hover:bg-orange-400", borderColor: "border-orange-400" }
8207
8576
  ];
8208
- HighlightPopover = memo20(function HighlightPopover2({
8577
+ HighlightPopover = memo21(function HighlightPopover2({
8209
8578
  highlight,
8210
8579
  scale,
8211
8580
  pageElement,
@@ -8316,7 +8685,7 @@ var init_HighlightPopover = __esm({
8316
8685
  if (!highlight || !position.visible) {
8317
8686
  return null;
8318
8687
  }
8319
- return /* @__PURE__ */ jsxs18(
8688
+ return /* @__PURE__ */ jsxs19(
8320
8689
  "div",
8321
8690
  {
8322
8691
  ref: popoverRef,
@@ -8336,8 +8705,8 @@ var init_HighlightPopover = __esm({
8336
8705
  width: 280
8337
8706
  },
8338
8707
  children: [
8339
- /* @__PURE__ */ jsxs18("div", { className: "flex items-center justify-between p-2 border-b border-gray-200 dark:border-gray-700", children: [
8340
- /* @__PURE__ */ jsx21("div", { className: "flex items-center gap-1", children: HIGHLIGHT_COLOR_OPTIONS.map((opt) => /* @__PURE__ */ jsx21(
8708
+ /* @__PURE__ */ jsxs19("div", { className: "flex items-center justify-between p-2 border-b border-gray-200 dark:border-gray-700", children: [
8709
+ /* @__PURE__ */ jsx22("div", { className: "flex items-center gap-1", children: HIGHLIGHT_COLOR_OPTIONS.map((opt) => /* @__PURE__ */ jsx22(
8341
8710
  "button",
8342
8711
  {
8343
8712
  onClick: () => handleColorClick(opt.color),
@@ -8355,7 +8724,7 @@ var init_HighlightPopover = __esm({
8355
8724
  },
8356
8725
  opt.color
8357
8726
  )) }),
8358
- /* @__PURE__ */ jsx21(
8727
+ /* @__PURE__ */ jsx22(
8359
8728
  "button",
8360
8729
  {
8361
8730
  onClick: handleDeleteClick,
@@ -8367,7 +8736,7 @@ var init_HighlightPopover = __esm({
8367
8736
  ),
8368
8737
  title: "Delete highlight",
8369
8738
  "aria-label": "Delete highlight",
8370
- children: /* @__PURE__ */ jsx21("svg", { className: "w-4 h-4", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx21(
8739
+ children: /* @__PURE__ */ jsx22("svg", { className: "w-4 h-4", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx22(
8371
8740
  "path",
8372
8741
  {
8373
8742
  strokeLinecap: "round",
@@ -8379,8 +8748,8 @@ var init_HighlightPopover = __esm({
8379
8748
  }
8380
8749
  )
8381
8750
  ] }),
8382
- /* @__PURE__ */ jsx21("div", { className: "p-2", children: isEditingComment ? /* @__PURE__ */ jsxs18("div", { className: "space-y-2", children: [
8383
- /* @__PURE__ */ jsx21(
8751
+ /* @__PURE__ */ jsx22("div", { className: "p-2", children: isEditingComment ? /* @__PURE__ */ jsxs19("div", { className: "space-y-2", children: [
8752
+ /* @__PURE__ */ jsx22(
8384
8753
  "textarea",
8385
8754
  {
8386
8755
  ref: textareaRef,
@@ -8399,8 +8768,8 @@ var init_HighlightPopover = __esm({
8399
8768
  rows: 3
8400
8769
  }
8401
8770
  ),
8402
- /* @__PURE__ */ jsxs18("div", { className: "flex justify-end gap-2", children: [
8403
- /* @__PURE__ */ jsx21(
8771
+ /* @__PURE__ */ jsxs19("div", { className: "flex justify-end gap-2", children: [
8772
+ /* @__PURE__ */ jsx22(
8404
8773
  "button",
8405
8774
  {
8406
8775
  onClick: () => {
@@ -8416,7 +8785,7 @@ var init_HighlightPopover = __esm({
8416
8785
  children: "Cancel"
8417
8786
  }
8418
8787
  ),
8419
- /* @__PURE__ */ jsx21(
8788
+ /* @__PURE__ */ jsx22(
8420
8789
  "button",
8421
8790
  {
8422
8791
  onClick: handleSaveComment,
@@ -8430,14 +8799,14 @@ var init_HighlightPopover = __esm({
8430
8799
  }
8431
8800
  )
8432
8801
  ] })
8433
- ] }) : /* @__PURE__ */ jsxs18("div", { className: "space-y-2", children: [
8434
- /* @__PURE__ */ jsxs18("p", { className: "text-xs text-gray-500 dark:text-gray-400 line-clamp-2", children: [
8802
+ ] }) : /* @__PURE__ */ jsxs19("div", { className: "space-y-2", children: [
8803
+ /* @__PURE__ */ jsxs19("p", { className: "text-xs text-gray-500 dark:text-gray-400 line-clamp-2", children: [
8435
8804
  "\u201C",
8436
8805
  highlight.text.slice(0, 100),
8437
8806
  highlight.text.length > 100 ? "..." : "",
8438
8807
  "\u201D"
8439
8808
  ] }),
8440
- highlight.comment ? /* @__PURE__ */ jsx21(
8809
+ highlight.comment ? /* @__PURE__ */ jsx22(
8441
8810
  "button",
8442
8811
  {
8443
8812
  onClick: () => setIsEditingComment(true),
@@ -8450,7 +8819,7 @@ var init_HighlightPopover = __esm({
8450
8819
  ),
8451
8820
  children: highlight.comment
8452
8821
  }
8453
- ) : /* @__PURE__ */ jsx21(
8822
+ ) : /* @__PURE__ */ jsx22(
8454
8823
  "button",
8455
8824
  {
8456
8825
  onClick: () => setIsEditingComment(true),
@@ -8463,7 +8832,7 @@ var init_HighlightPopover = __esm({
8463
8832
  children: "+ Add a note..."
8464
8833
  }
8465
8834
  ),
8466
- /* @__PURE__ */ jsxs18(
8835
+ /* @__PURE__ */ jsxs19(
8467
8836
  "button",
8468
8837
  {
8469
8838
  onClick: handleCopyClick,
@@ -8474,7 +8843,7 @@ var init_HighlightPopover = __esm({
8474
8843
  "focus:outline-none focus:ring-2 focus:ring-blue-500"
8475
8844
  ),
8476
8845
  children: [
8477
- /* @__PURE__ */ jsx21("svg", { className: "w-4 h-4", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx21(
8846
+ /* @__PURE__ */ jsx22("svg", { className: "w-4 h-4", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx22(
8478
8847
  "path",
8479
8848
  {
8480
8849
  strokeLinecap: "round",
@@ -8504,20 +8873,21 @@ var init_HighlightPopover2 = __esm({
8504
8873
  });
8505
8874
 
8506
8875
  // src/components/PDFViewer/DocumentContainer.tsx
8507
- import { memo as memo21, useEffect as useEffect19, useState as useState18, useRef as useRef16, useCallback as useCallback29 } from "react";
8508
- import { jsx as jsx22, jsxs as jsxs19 } from "react/jsx-runtime";
8876
+ import { memo as memo22, useEffect as useEffect19, useState as useState18, useRef as useRef16, useCallback as useCallback29 } from "react";
8877
+ import { jsx as jsx23, jsxs as jsxs20 } from "react/jsx-runtime";
8509
8878
  var DocumentContainer;
8510
8879
  var init_DocumentContainer = __esm({
8511
8880
  "src/components/PDFViewer/DocumentContainer.tsx"() {
8512
8881
  "use strict";
8513
8882
  init_PDFPage2();
8514
8883
  init_PDFLoadingScreen2();
8884
+ init_PageSkeleton();
8515
8885
  init_hooks();
8516
8886
  init_useHighlights();
8517
8887
  init_SelectionToolbar2();
8518
8888
  init_HighlightPopover2();
8519
8889
  init_utils();
8520
- DocumentContainer = memo21(function DocumentContainer2({
8890
+ DocumentContainer = memo22(function DocumentContainer2({
8521
8891
  className,
8522
8892
  enableTouchGestures = true
8523
8893
  }) {
@@ -8536,10 +8906,12 @@ var init_DocumentContainer = __esm({
8536
8906
  const { viewerStore } = usePDFViewerStores();
8537
8907
  const [currentPageObj, setCurrentPageObj] = useState18(null);
8538
8908
  const [isLoadingPage, setIsLoadingPage] = useState18(false);
8909
+ const [pageLoadError, setPageLoadError] = useState18(null);
8539
8910
  const containerRef = useRef16(null);
8540
8911
  const documentRef = useRef16(null);
8541
8912
  const baseScaleRef = useRef16(scale);
8542
8913
  const isTouchDevice = useIsTouchDevice();
8914
+ const documentLoadingState = useViewerStore((s) => s.documentLoadingState);
8543
8915
  const { selection, clearSelection, copySelection } = useTextSelection();
8544
8916
  const handlePinchZoom = useCallback29(
8545
8917
  (pinchScale) => {
@@ -8585,16 +8957,19 @@ var init_DocumentContainer = __esm({
8585
8957
  if (document2 !== documentRef.current) {
8586
8958
  documentRef.current = document2;
8587
8959
  setCurrentPageObj(null);
8960
+ setPageLoadError(null);
8588
8961
  }
8589
8962
  }, [document2]);
8590
8963
  useEffect19(() => {
8591
8964
  if (!document2) {
8592
8965
  setCurrentPageObj(null);
8966
+ setPageLoadError(null);
8593
8967
  return;
8594
8968
  }
8595
8969
  let cancelled = false;
8596
8970
  const loadPage = async () => {
8597
8971
  setIsLoadingPage(true);
8972
+ setPageLoadError(null);
8598
8973
  try {
8599
8974
  const page = await document2.getPage(currentPage);
8600
8975
  if (!cancelled && document2 === documentRef.current) {
@@ -8611,6 +8986,7 @@ var init_DocumentContainer = __esm({
8611
8986
  const isDocumentDestroyed = errorMessage.includes("destroyed") || errorMessage.includes("sendWithStream") || errorMessage.includes("sendWithPromise") || errorMessage.includes("Cannot read properties of null");
8612
8987
  if (!isDocumentDestroyed) {
8613
8988
  console.error("Error loading page:", error);
8989
+ setPageLoadError(error instanceof Error ? error : new Error(errorMessage));
8614
8990
  }
8615
8991
  }
8616
8992
  } finally {
@@ -8668,7 +9044,7 @@ var init_DocumentContainer = __esm({
8668
9044
  sepia: "bg-amber-50"
8669
9045
  };
8670
9046
  if (!document2) {
8671
- return /* @__PURE__ */ jsx22(
9047
+ return /* @__PURE__ */ jsx23(
8672
9048
  "div",
8673
9049
  {
8674
9050
  className: cn(
@@ -8677,11 +9053,53 @@ var init_DocumentContainer = __esm({
8677
9053
  themeStyles[theme],
8678
9054
  className
8679
9055
  ),
8680
- children: /* @__PURE__ */ jsx22(PDFLoadingScreen, { phase: isLoading ? "fetching" : "initializing" })
9056
+ children: /* @__PURE__ */ jsx23(PDFLoadingScreen, { phase: isLoading ? "fetching" : "initializing" })
8681
9057
  }
8682
9058
  );
8683
9059
  }
8684
- return /* @__PURE__ */ jsxs19(
9060
+ const renderPageContent = () => {
9061
+ if (pageLoadError && !currentPageObj) {
9062
+ return /* @__PURE__ */ jsxs20(
9063
+ "div",
9064
+ {
9065
+ className: "relative bg-white shadow-lg flex flex-col items-center justify-center gap-2 text-gray-500",
9066
+ style: {
9067
+ width: DEFAULT_PAGE_WIDTH * scale,
9068
+ height: DEFAULT_PAGE_HEIGHT * scale
9069
+ },
9070
+ "data-page-number": currentPage,
9071
+ children: [
9072
+ /* @__PURE__ */ jsx23("svg", { className: "w-8 h-8 text-red-400", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx23("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z" }) }),
9073
+ /* @__PURE__ */ jsxs20("span", { className: "text-sm", children: [
9074
+ "Failed to load page ",
9075
+ currentPage
9076
+ ] })
9077
+ ]
9078
+ }
9079
+ );
9080
+ }
9081
+ if (isLoadingPage && !currentPageObj) {
9082
+ return /* @__PURE__ */ jsx23(
9083
+ PageSkeleton,
9084
+ {
9085
+ pageNumber: currentPage,
9086
+ width: Math.floor(DEFAULT_PAGE_WIDTH * scale),
9087
+ height: Math.floor(DEFAULT_PAGE_HEIGHT * scale),
9088
+ isFirstPage: currentPage === 1 && documentLoadingState !== "ready"
9089
+ }
9090
+ );
9091
+ }
9092
+ return /* @__PURE__ */ jsx23(
9093
+ PDFPage,
9094
+ {
9095
+ pageNumber: currentPage,
9096
+ page: currentPageObj,
9097
+ scale,
9098
+ rotation
9099
+ }
9100
+ );
9101
+ };
9102
+ return /* @__PURE__ */ jsxs20(
8685
9103
  "div",
8686
9104
  {
8687
9105
  ref: setContainerRef,
@@ -8694,16 +9112,8 @@ var init_DocumentContainer = __esm({
8694
9112
  className
8695
9113
  ),
8696
9114
  children: [
8697
- /* @__PURE__ */ jsx22(
8698
- PDFPage,
8699
- {
8700
- pageNumber: currentPage,
8701
- page: currentPageObj,
8702
- scale,
8703
- rotation
8704
- }
8705
- ),
8706
- /* @__PURE__ */ jsx22(
9115
+ renderPageContent(),
9116
+ /* @__PURE__ */ jsx23(
8707
9117
  SelectionToolbar,
8708
9118
  {
8709
9119
  selection,
@@ -8712,7 +9122,7 @@ var init_DocumentContainer = __esm({
8712
9122
  activeColor
8713
9123
  }
8714
9124
  ),
8715
- /* @__PURE__ */ jsx22(
9125
+ /* @__PURE__ */ jsx23(
8716
9126
  HighlightPopover,
8717
9127
  {
8718
9128
  highlight: selectedHighlight,
@@ -8723,8 +9133,7 @@ var init_DocumentContainer = __esm({
8723
9133
  onDelete: deleteHighlight,
8724
9134
  onClose: handleClosePopover
8725
9135
  }
8726
- ),
8727
- isLoadingPage && !currentPageObj && /* @__PURE__ */ jsx22("div", { className: "fixed bottom-4 right-4 px-3 py-2 bg-black/75 text-white text-sm rounded-lg", children: "Loading..." })
9136
+ )
8728
9137
  ]
8729
9138
  }
8730
9139
  );
@@ -8733,22 +9142,23 @@ var init_DocumentContainer = __esm({
8733
9142
  });
8734
9143
 
8735
9144
  // src/components/PDFViewer/VirtualizedDocumentContainer.tsx
8736
- import { memo as memo22, useEffect as useEffect20, useState as useState19, useRef as useRef17, useCallback as useCallback30 } from "react";
8737
- import { jsx as jsx23, jsxs as jsxs20 } from "react/jsx-runtime";
8738
- var DEFAULT_PAGE_WIDTH, DEFAULT_PAGE_HEIGHT, VirtualizedDocumentContainer;
9145
+ import { memo as memo23, useEffect as useEffect20, useState as useState19, useRef as useRef17, useCallback as useCallback30 } from "react";
9146
+ import { jsx as jsx24, jsxs as jsxs21 } from "react/jsx-runtime";
9147
+ var DEFAULT_PAGE_WIDTH2, DEFAULT_PAGE_HEIGHT2, VirtualizedDocumentContainer;
8739
9148
  var init_VirtualizedDocumentContainer = __esm({
8740
9149
  "src/components/PDFViewer/VirtualizedDocumentContainer.tsx"() {
8741
9150
  "use strict";
8742
9151
  init_PDFPage2();
8743
9152
  init_PDFLoadingScreen2();
9153
+ init_PageSkeleton();
8744
9154
  init_hooks();
8745
9155
  init_useHighlights();
8746
9156
  init_SelectionToolbar2();
8747
9157
  init_HighlightPopover2();
8748
9158
  init_utils();
8749
- DEFAULT_PAGE_WIDTH = 612;
8750
- DEFAULT_PAGE_HEIGHT = 792;
8751
- VirtualizedDocumentContainer = memo22(function VirtualizedDocumentContainer2({
9159
+ DEFAULT_PAGE_WIDTH2 = 612;
9160
+ DEFAULT_PAGE_HEIGHT2 = 792;
9161
+ VirtualizedDocumentContainer = memo23(function VirtualizedDocumentContainer2({
8752
9162
  overscan = 2,
8753
9163
  pageGap = 16,
8754
9164
  enableTouchGestures = true,
@@ -8814,7 +9224,7 @@ var init_VirtualizedDocumentContainer = __esm({
8814
9224
  dimensions = { width: viewport.width, height: viewport.height };
8815
9225
  pageDimensionsCache.current.set(i, dimensions);
8816
9226
  } catch {
8817
- dimensions = { width: DEFAULT_PAGE_WIDTH, height: DEFAULT_PAGE_HEIGHT };
9227
+ dimensions = { width: DEFAULT_PAGE_WIDTH2, height: DEFAULT_PAGE_HEIGHT2 };
8818
9228
  }
8819
9229
  }
8820
9230
  const scaledHeight = Math.floor(dimensions.height * scale);
@@ -9021,7 +9431,7 @@ var init_VirtualizedDocumentContainer = __esm({
9021
9431
  sepia: "bg-amber-50"
9022
9432
  };
9023
9433
  if (!document2) {
9024
- return /* @__PURE__ */ jsx23(
9434
+ return /* @__PURE__ */ jsx24(
9025
9435
  "div",
9026
9436
  {
9027
9437
  className: cn(
@@ -9030,11 +9440,11 @@ var init_VirtualizedDocumentContainer = __esm({
9030
9440
  themeStyles[theme],
9031
9441
  className
9032
9442
  ),
9033
- children: /* @__PURE__ */ jsx23(PDFLoadingScreen, { phase: isLoading ? "fetching" : "initializing" })
9443
+ children: /* @__PURE__ */ jsx24(PDFLoadingScreen, { phase: isLoading ? "fetching" : "initializing" })
9034
9444
  }
9035
9445
  );
9036
9446
  }
9037
- return /* @__PURE__ */ jsxs20(
9447
+ return /* @__PURE__ */ jsxs21(
9038
9448
  "div",
9039
9449
  {
9040
9450
  ref: containerRef,
@@ -9045,7 +9455,7 @@ var init_VirtualizedDocumentContainer = __esm({
9045
9455
  className
9046
9456
  ),
9047
9457
  children: [
9048
- /* @__PURE__ */ jsx23(
9458
+ /* @__PURE__ */ jsx24(
9049
9459
  "div",
9050
9460
  {
9051
9461
  ref: setContainerRef,
@@ -9054,7 +9464,7 @@ var init_VirtualizedDocumentContainer = __esm({
9054
9464
  // Smooth scrolling on iOS
9055
9465
  WebkitOverflowScrolling: "touch"
9056
9466
  },
9057
- children: /* @__PURE__ */ jsx23(
9467
+ children: /* @__PURE__ */ jsx24(
9058
9468
  "div",
9059
9469
  {
9060
9470
  className: "relative mx-auto",
@@ -9065,8 +9475,9 @@ var init_VirtualizedDocumentContainer = __esm({
9065
9475
  children: pageInfos.filter((info) => visiblePages.includes(info.pageNumber)).map((info) => {
9066
9476
  const page = pageObjects.get(info.pageNumber);
9067
9477
  const dimensions = pageDimensionsCache.current.get(info.pageNumber);
9068
- const scaledWidth = dimensions ? Math.floor(dimensions.width * scale) : Math.floor(DEFAULT_PAGE_WIDTH * scale);
9069
- return /* @__PURE__ */ jsx23(
9478
+ const scaledWidth = dimensions ? Math.floor(dimensions.width * scale) : Math.floor(DEFAULT_PAGE_WIDTH2 * scale);
9479
+ const scaledHeight = dimensions ? Math.floor(dimensions.height * scale) : Math.floor(DEFAULT_PAGE_HEIGHT2 * scale);
9480
+ return /* @__PURE__ */ jsx24(
9070
9481
  "div",
9071
9482
  {
9072
9483
  className: "absolute left-1/2 -translate-x-1/2",
@@ -9074,14 +9485,22 @@ var init_VirtualizedDocumentContainer = __esm({
9074
9485
  top: info.top,
9075
9486
  width: scaledWidth
9076
9487
  },
9077
- children: /* @__PURE__ */ jsx23(
9488
+ children: page ? /* @__PURE__ */ jsx24(
9078
9489
  PDFPage,
9079
9490
  {
9080
9491
  pageNumber: info.pageNumber,
9081
- page: page || null,
9492
+ page,
9082
9493
  scale,
9083
9494
  rotation
9084
9495
  }
9496
+ ) : /* @__PURE__ */ jsx24(
9497
+ PageSkeleton,
9498
+ {
9499
+ pageNumber: info.pageNumber,
9500
+ width: scaledWidth,
9501
+ height: scaledHeight,
9502
+ isFirstPage: info.pageNumber === 1
9503
+ }
9085
9504
  )
9086
9505
  },
9087
9506
  info.pageNumber
@@ -9091,7 +9510,7 @@ var init_VirtualizedDocumentContainer = __esm({
9091
9510
  )
9092
9511
  }
9093
9512
  ),
9094
- /* @__PURE__ */ jsx23(
9513
+ /* @__PURE__ */ jsx24(
9095
9514
  SelectionToolbar,
9096
9515
  {
9097
9516
  selection,
@@ -9100,7 +9519,7 @@ var init_VirtualizedDocumentContainer = __esm({
9100
9519
  activeColor
9101
9520
  }
9102
9521
  ),
9103
- /* @__PURE__ */ jsx23(
9522
+ /* @__PURE__ */ jsx24(
9104
9523
  HighlightPopover,
9105
9524
  {
9106
9525
  highlight: selectedHighlight,
@@ -9120,15 +9539,15 @@ var init_VirtualizedDocumentContainer = __esm({
9120
9539
  });
9121
9540
 
9122
9541
  // src/components/PDFViewer/ContinuousScrollContainer.tsx
9123
- import { memo as memo23 } from "react";
9124
- import { jsx as jsx24 } from "react/jsx-runtime";
9542
+ import { memo as memo24 } from "react";
9543
+ import { jsx as jsx25 } from "react/jsx-runtime";
9125
9544
  var ContinuousScrollContainer;
9126
9545
  var init_ContinuousScrollContainer = __esm({
9127
9546
  "src/components/PDFViewer/ContinuousScrollContainer.tsx"() {
9128
9547
  "use strict";
9129
9548
  init_VirtualizedDocumentContainer();
9130
- ContinuousScrollContainer = memo23(function ContinuousScrollContainer2(props) {
9131
- return /* @__PURE__ */ jsx24(
9549
+ ContinuousScrollContainer = memo24(function ContinuousScrollContainer2(props) {
9550
+ return /* @__PURE__ */ jsx25(
9132
9551
  VirtualizedDocumentContainer,
9133
9552
  {
9134
9553
  overscan: 3,
@@ -9141,8 +9560,8 @@ var init_ContinuousScrollContainer = __esm({
9141
9560
  });
9142
9561
 
9143
9562
  // src/components/PDFViewer/DualPageContainer.tsx
9144
- import { memo as memo24, useEffect as useEffect21, useState as useState20, useRef as useRef18, useCallback as useCallback31 } from "react";
9145
- import { jsx as jsx25, jsxs as jsxs21 } from "react/jsx-runtime";
9563
+ import { memo as memo25, useEffect as useEffect21, useState as useState20, useRef as useRef18, useCallback as useCallback31 } from "react";
9564
+ import { jsx as jsx26, jsxs as jsxs22 } from "react/jsx-runtime";
9146
9565
  var DualPageContainer;
9147
9566
  var init_DualPageContainer = __esm({
9148
9567
  "src/components/PDFViewer/DualPageContainer.tsx"() {
@@ -9154,7 +9573,7 @@ var init_DualPageContainer = __esm({
9154
9573
  init_SelectionToolbar2();
9155
9574
  init_HighlightPopover2();
9156
9575
  init_utils();
9157
- DualPageContainer = memo24(function DualPageContainer2({
9576
+ DualPageContainer = memo25(function DualPageContainer2({
9158
9577
  showCover = true,
9159
9578
  bookSpread = true,
9160
9579
  pageGap = 4,
@@ -9364,7 +9783,7 @@ var init_DualPageContainer = __esm({
9364
9783
  };
9365
9784
  const spread = getSpreadPages(currentPage);
9366
9785
  if (!document2) {
9367
- return /* @__PURE__ */ jsx25(
9786
+ return /* @__PURE__ */ jsx26(
9368
9787
  "div",
9369
9788
  {
9370
9789
  className: cn(
@@ -9373,11 +9792,11 @@ var init_DualPageContainer = __esm({
9373
9792
  themeStyles[theme],
9374
9793
  className
9375
9794
  ),
9376
- children: /* @__PURE__ */ jsx25(PDFLoadingScreen, { phase: isDocumentLoading ? "fetching" : "initializing" })
9795
+ children: /* @__PURE__ */ jsx26(PDFLoadingScreen, { phase: isDocumentLoading ? "fetching" : "initializing" })
9377
9796
  }
9378
9797
  );
9379
9798
  }
9380
- return /* @__PURE__ */ jsxs21(
9799
+ return /* @__PURE__ */ jsxs22(
9381
9800
  "div",
9382
9801
  {
9383
9802
  ref: setContainerRef,
@@ -9390,13 +9809,13 @@ var init_DualPageContainer = __esm({
9390
9809
  className
9391
9810
  ),
9392
9811
  children: [
9393
- /* @__PURE__ */ jsxs21(
9812
+ /* @__PURE__ */ jsxs22(
9394
9813
  "div",
9395
9814
  {
9396
9815
  className: "flex items-center",
9397
9816
  style: { gap: pageGap },
9398
9817
  children: [
9399
- spread.left && /* @__PURE__ */ jsx25(
9818
+ spread.left && /* @__PURE__ */ jsx26(
9400
9819
  PDFPage,
9401
9820
  {
9402
9821
  pageNumber: spread.left,
@@ -9405,14 +9824,14 @@ var init_DualPageContainer = __esm({
9405
9824
  rotation
9406
9825
  }
9407
9826
  ),
9408
- spread.left && spread.right && /* @__PURE__ */ jsx25(
9827
+ spread.left && spread.right && /* @__PURE__ */ jsx26(
9409
9828
  "div",
9410
9829
  {
9411
9830
  className: "w-px h-full bg-gray-300 dark:bg-gray-600 opacity-50",
9412
9831
  style: { minHeight: "100%" }
9413
9832
  }
9414
9833
  ),
9415
- spread.right && /* @__PURE__ */ jsx25(
9834
+ spread.right && /* @__PURE__ */ jsx26(
9416
9835
  PDFPage,
9417
9836
  {
9418
9837
  pageNumber: spread.right,
@@ -9421,7 +9840,7 @@ var init_DualPageContainer = __esm({
9421
9840
  rotation
9422
9841
  }
9423
9842
  ),
9424
- (!spread.left || !spread.right) && /* @__PURE__ */ jsx25(
9843
+ (!spread.left || !spread.right) && /* @__PURE__ */ jsx26(
9425
9844
  "div",
9426
9845
  {
9427
9846
  className: "flex items-center justify-center",
@@ -9434,7 +9853,7 @@ var init_DualPageContainer = __esm({
9434
9853
  ]
9435
9854
  }
9436
9855
  ),
9437
- /* @__PURE__ */ jsx25(
9856
+ /* @__PURE__ */ jsx26(
9438
9857
  SelectionToolbar,
9439
9858
  {
9440
9859
  selection,
@@ -9443,7 +9862,7 @@ var init_DualPageContainer = __esm({
9443
9862
  activeColor
9444
9863
  }
9445
9864
  ),
9446
- /* @__PURE__ */ jsx25(
9865
+ /* @__PURE__ */ jsx26(
9447
9866
  HighlightPopover,
9448
9867
  {
9449
9868
  highlight: selectedHighlight,
@@ -9455,7 +9874,202 @@ var init_DualPageContainer = __esm({
9455
9874
  onClose: () => selectHighlight(null)
9456
9875
  }
9457
9876
  ),
9458
- isLoading && /* @__PURE__ */ jsx25("div", { className: "fixed bottom-4 right-4 px-3 py-2 bg-black/75 text-white text-sm rounded-lg", children: "Loading..." })
9877
+ isLoading && /* @__PURE__ */ jsx26("div", { className: "fixed bottom-4 right-4 px-3 py-2 bg-black/75 text-white text-sm rounded-lg", children: "Loading..." })
9878
+ ]
9879
+ }
9880
+ );
9881
+ });
9882
+ }
9883
+ });
9884
+
9885
+ // src/components/PDFViewer/BookModeContainer.tsx
9886
+ import React, { memo as memo26, useEffect as useEffect22, useState as useState21, useRef as useRef19, useCallback as useCallback32 } from "react";
9887
+ import HTMLFlipBook from "react-pageflip";
9888
+ import { jsx as jsx27, jsxs as jsxs23 } from "react/jsx-runtime";
9889
+ var BookPage, BookModeContainer;
9890
+ var init_BookModeContainer = __esm({
9891
+ "src/components/PDFViewer/BookModeContainer.tsx"() {
9892
+ "use strict";
9893
+ init_PDFPage2();
9894
+ init_PDFLoadingScreen2();
9895
+ init_hooks();
9896
+ init_utils();
9897
+ BookPage = React.forwardRef(function BookPage2({ pageNumber, page, scale, rotation, width, height }, ref) {
9898
+ return /* @__PURE__ */ jsx27("div", { ref, className: "book-page", "data-page-number": pageNumber, children: /* @__PURE__ */ jsx27("div", { style: { width, height, overflow: "hidden" }, children: /* @__PURE__ */ jsx27(
9899
+ PDFPage,
9900
+ {
9901
+ pageNumber,
9902
+ page,
9903
+ scale,
9904
+ rotation,
9905
+ showTextLayer: false,
9906
+ showAnnotationLayer: false,
9907
+ showHighlightLayer: false
9908
+ }
9909
+ ) }) });
9910
+ });
9911
+ BookModeContainer = memo26(function BookModeContainer2({
9912
+ className,
9913
+ flippingTime = 800,
9914
+ drawShadow = true,
9915
+ maxShadowOpacity = 0.7
9916
+ }) {
9917
+ const {
9918
+ document: document2,
9919
+ currentPage,
9920
+ numPages,
9921
+ scale,
9922
+ rotation,
9923
+ theme,
9924
+ isLoading,
9925
+ goToPage
9926
+ } = usePDFViewer();
9927
+ const scrollToPageRequest = useViewerStore((s) => s.scrollToPageRequest);
9928
+ const { viewerStore } = usePDFViewerStores();
9929
+ const [pages, setPages] = useState21([]);
9930
+ const [pageDims, setPageDims] = useState21({ width: 612, height: 792 });
9931
+ const [isLoadingPages, setIsLoadingPages] = useState21(false);
9932
+ const flipBookRef = useRef19(null);
9933
+ const isSyncingRef = useRef19(false);
9934
+ useEffect22(() => {
9935
+ if (!document2) {
9936
+ setPages([]);
9937
+ return;
9938
+ }
9939
+ let cancelled = false;
9940
+ const loadAllPages = async () => {
9941
+ setIsLoadingPages(true);
9942
+ try {
9943
+ const pagePromises = [];
9944
+ for (let i = 1; i <= numPages; i++) {
9945
+ pagePromises.push(document2.getPage(i));
9946
+ }
9947
+ const results = await Promise.allSettled(pagePromises);
9948
+ if (!cancelled) {
9949
+ const loaded = results.map((r) => r.status === "fulfilled" ? r.value : null);
9950
+ setPages(loaded);
9951
+ const firstPage = loaded[0];
9952
+ if (firstPage) {
9953
+ const vp = firstPage.getViewport({ scale, rotation });
9954
+ setPageDims({ width: Math.floor(vp.width), height: Math.floor(vp.height) });
9955
+ }
9956
+ }
9957
+ } catch {
9958
+ } finally {
9959
+ if (!cancelled) setIsLoadingPages(false);
9960
+ }
9961
+ };
9962
+ loadAllPages();
9963
+ return () => {
9964
+ cancelled = true;
9965
+ };
9966
+ }, [document2, numPages, scale, rotation]);
9967
+ useEffect22(() => {
9968
+ if (pages[0]) {
9969
+ const vp = pages[0].getViewport({ scale, rotation });
9970
+ setPageDims({ width: Math.floor(vp.width), height: Math.floor(vp.height) });
9971
+ }
9972
+ }, [pages, scale, rotation]);
9973
+ useEffect22(() => {
9974
+ const pageFlip = flipBookRef.current?.pageFlip();
9975
+ if (!pageFlip) return;
9976
+ const flipBookPage = pageFlip.getCurrentPageIndex();
9977
+ const targetIndex = currentPage - 1;
9978
+ if (flipBookPage !== targetIndex) {
9979
+ isSyncingRef.current = true;
9980
+ pageFlip.turnToPage(targetIndex);
9981
+ setTimeout(() => {
9982
+ isSyncingRef.current = false;
9983
+ }, 100);
9984
+ }
9985
+ }, [currentPage]);
9986
+ useEffect22(() => {
9987
+ if (scrollToPageRequest) {
9988
+ requestAnimationFrame(() => {
9989
+ viewerStore.getState().completeScrollRequest(scrollToPageRequest.requestId);
9990
+ });
9991
+ }
9992
+ }, [scrollToPageRequest, viewerStore]);
9993
+ const handleFlip = useCallback32((e) => {
9994
+ if (isSyncingRef.current) return;
9995
+ const newPage = e.data + 1;
9996
+ if (newPage !== currentPage && newPage >= 1 && newPage <= numPages) {
9997
+ goToPage(newPage);
9998
+ }
9999
+ }, [currentPage, numPages, goToPage]);
10000
+ const themeStyles = {
10001
+ light: "bg-gray-100",
10002
+ dark: "bg-gray-900",
10003
+ sepia: "bg-amber-50"
10004
+ };
10005
+ const themeClass = theme === "dark" ? "dark" : theme === "sepia" ? "sepia" : "";
10006
+ if (!document2) {
10007
+ return /* @__PURE__ */ jsx27("div", { className: cn("document-container", "flex-1", themeStyles[theme], className), children: /* @__PURE__ */ jsx27(PDFLoadingScreen, { phase: isLoading ? "fetching" : "initializing" }) });
10008
+ }
10009
+ if (isLoadingPages || pages.length === 0) {
10010
+ return /* @__PURE__ */ jsx27("div", { className: cn("document-container", "flex-1", themeStyles[theme], className), children: /* @__PURE__ */ jsx27(PDFLoadingScreen, { phase: "rendering" }) });
10011
+ }
10012
+ return /* @__PURE__ */ jsxs23(
10013
+ "div",
10014
+ {
10015
+ className: cn(
10016
+ "book-mode-container",
10017
+ "flex-1 overflow-hidden",
10018
+ "flex items-center justify-center",
10019
+ themeStyles[theme],
10020
+ themeClass,
10021
+ className
10022
+ ),
10023
+ style: { userSelect: "none", WebkitUserSelect: "none" },
10024
+ children: [
10025
+ /* @__PURE__ */ jsx27(
10026
+ HTMLFlipBook,
10027
+ {
10028
+ ref: flipBookRef,
10029
+ width: pageDims.width,
10030
+ height: pageDims.height,
10031
+ size: "stretch",
10032
+ minWidth: 300,
10033
+ maxWidth: pageDims.width,
10034
+ minHeight: 400,
10035
+ maxHeight: pageDims.height,
10036
+ drawShadow,
10037
+ maxShadowOpacity,
10038
+ flippingTime,
10039
+ usePortrait: true,
10040
+ startPage: currentPage - 1,
10041
+ showCover: false,
10042
+ mobileScrollSupport: false,
10043
+ swipeDistance: 30,
10044
+ showPageCorners: true,
10045
+ useMouseEvents: true,
10046
+ clickEventForward: false,
10047
+ onFlip: handleFlip,
10048
+ className: "book-flipbook",
10049
+ style: {},
10050
+ startZIndex: 0,
10051
+ autoSize: true,
10052
+ renderOnlyPageLengthChange: false,
10053
+ disableFlipByClick: false,
10054
+ children: pages.map((page, index) => /* @__PURE__ */ jsx27(
10055
+ BookPage,
10056
+ {
10057
+ pageNumber: index + 1,
10058
+ page,
10059
+ scale,
10060
+ rotation,
10061
+ width: pageDims.width,
10062
+ height: pageDims.height
10063
+ },
10064
+ index
10065
+ ))
10066
+ }
10067
+ ),
10068
+ /* @__PURE__ */ jsxs23("div", { className: "book-page-indicator", children: [
10069
+ currentPage,
10070
+ " / ",
10071
+ numPages
10072
+ ] })
9459
10073
  ]
9460
10074
  }
9461
10075
  );
@@ -9464,15 +10078,15 @@ var init_DualPageContainer = __esm({
9464
10078
  });
9465
10079
 
9466
10080
  // src/components/FloatingZoomControls/FloatingZoomControls.tsx
9467
- import { memo as memo25, useCallback as useCallback32 } from "react";
9468
- import { jsx as jsx26, jsxs as jsxs22 } from "react/jsx-runtime";
10081
+ import { memo as memo27, useCallback as useCallback33 } from "react";
10082
+ import { jsx as jsx28, jsxs as jsxs24 } from "react/jsx-runtime";
9469
10083
  var FloatingZoomControls;
9470
10084
  var init_FloatingZoomControls = __esm({
9471
10085
  "src/components/FloatingZoomControls/FloatingZoomControls.tsx"() {
9472
10086
  "use strict";
9473
10087
  init_hooks();
9474
10088
  init_utils();
9475
- FloatingZoomControls = memo25(function FloatingZoomControls2({
10089
+ FloatingZoomControls = memo27(function FloatingZoomControls2({
9476
10090
  position = "bottom-right",
9477
10091
  className,
9478
10092
  showFitToWidth = true,
@@ -9482,20 +10096,20 @@ var init_FloatingZoomControls = __esm({
9482
10096
  const { viewerStore } = usePDFViewerStores();
9483
10097
  const scale = useViewerStore((s) => s.scale);
9484
10098
  const document2 = useViewerStore((s) => s.document);
9485
- const handleZoomIn = useCallback32(() => {
10099
+ const handleZoomIn = useCallback33(() => {
9486
10100
  const currentScale = viewerStore.getState().scale;
9487
10101
  const newScale = Math.min(4, currentScale + 0.05);
9488
10102
  viewerStore.getState().setScale(newScale);
9489
10103
  }, [viewerStore]);
9490
- const handleZoomOut = useCallback32(() => {
10104
+ const handleZoomOut = useCallback33(() => {
9491
10105
  const currentScale = viewerStore.getState().scale;
9492
10106
  const newScale = Math.max(0.1, currentScale - 0.05);
9493
10107
  viewerStore.getState().setScale(newScale);
9494
10108
  }, [viewerStore]);
9495
- const handleFitToWidth = useCallback32(() => {
10109
+ const handleFitToWidth = useCallback33(() => {
9496
10110
  viewerStore.getState().setScale(1);
9497
10111
  }, [viewerStore]);
9498
- const handleFitToPage = useCallback32(() => {
10112
+ const handleFitToPage = useCallback33(() => {
9499
10113
  viewerStore.getState().setScale(0.75);
9500
10114
  }, [viewerStore]);
9501
10115
  if (!document2) return null;
@@ -9506,7 +10120,7 @@ var init_FloatingZoomControls = __esm({
9506
10120
  "top-left": "top-4 left-4"
9507
10121
  };
9508
10122
  const zoomPercentage = Math.round(scale * 100);
9509
- return /* @__PURE__ */ jsxs22(
10123
+ return /* @__PURE__ */ jsxs24(
9510
10124
  "div",
9511
10125
  {
9512
10126
  className: cn(
@@ -9518,7 +10132,7 @@ var init_FloatingZoomControls = __esm({
9518
10132
  className
9519
10133
  ),
9520
10134
  children: [
9521
- /* @__PURE__ */ jsx26(
10135
+ /* @__PURE__ */ jsx28(
9522
10136
  "button",
9523
10137
  {
9524
10138
  onClick: handleZoomOut,
@@ -9532,14 +10146,14 @@ var init_FloatingZoomControls = __esm({
9532
10146
  disabled: scale <= 0.25,
9533
10147
  title: "Zoom Out",
9534
10148
  "aria-label": "Zoom Out",
9535
- children: /* @__PURE__ */ jsx26("svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx26("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M20 12H4" }) })
10149
+ children: /* @__PURE__ */ jsx28("svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx28("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M20 12H4" }) })
9536
10150
  }
9537
10151
  ),
9538
- showZoomLevel && /* @__PURE__ */ jsxs22("span", { className: "min-w-[48px] text-center text-sm font-medium text-gray-700 dark:text-gray-300", children: [
10152
+ showZoomLevel && /* @__PURE__ */ jsxs24("span", { className: "min-w-[48px] text-center text-sm font-medium text-gray-700 dark:text-gray-300", children: [
9539
10153
  zoomPercentage,
9540
10154
  "%"
9541
10155
  ] }),
9542
- /* @__PURE__ */ jsx26(
10156
+ /* @__PURE__ */ jsx28(
9543
10157
  "button",
9544
10158
  {
9545
10159
  onClick: handleZoomIn,
@@ -9553,11 +10167,11 @@ var init_FloatingZoomControls = __esm({
9553
10167
  disabled: scale >= 4,
9554
10168
  title: "Zoom In",
9555
10169
  "aria-label": "Zoom In",
9556
- children: /* @__PURE__ */ jsx26("svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx26("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M12 4v16m8-8H4" }) })
10170
+ children: /* @__PURE__ */ jsx28("svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx28("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M12 4v16m8-8H4" }) })
9557
10171
  }
9558
10172
  ),
9559
- (showFitToWidth || showFitToPage) && /* @__PURE__ */ jsx26("div", { className: "w-px h-6 bg-gray-200 dark:bg-gray-700 mx-1" }),
9560
- showFitToWidth && /* @__PURE__ */ jsx26(
10173
+ (showFitToWidth || showFitToPage) && /* @__PURE__ */ jsx28("div", { className: "w-px h-6 bg-gray-200 dark:bg-gray-700 mx-1" }),
10174
+ showFitToWidth && /* @__PURE__ */ jsx28(
9561
10175
  "button",
9562
10176
  {
9563
10177
  onClick: handleFitToWidth,
@@ -9569,10 +10183,10 @@ var init_FloatingZoomControls = __esm({
9569
10183
  ),
9570
10184
  title: "Fit to Width",
9571
10185
  "aria-label": "Fit to Width",
9572
- children: /* @__PURE__ */ jsx26("svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx26("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M4 8V4m0 0h4M4 4l5 5m11-1V4m0 0h-4m4 0l-5 5M4 16v4m0 0h4m-4 0l5-5m11 5l-5-5m5 5v-4m0 4h-4" }) })
10186
+ children: /* @__PURE__ */ jsx28("svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx28("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M4 8V4m0 0h4M4 4l5 5m11-1V4m0 0h-4m4 0l-5 5M4 16v4m0 0h4m-4 0l5-5m11 5l-5-5m5 5v-4m0 4h-4" }) })
9573
10187
  }
9574
10188
  ),
9575
- showFitToPage && /* @__PURE__ */ jsx26(
10189
+ showFitToPage && /* @__PURE__ */ jsx28(
9576
10190
  "button",
9577
10191
  {
9578
10192
  onClick: handleFitToPage,
@@ -9584,7 +10198,7 @@ var init_FloatingZoomControls = __esm({
9584
10198
  ),
9585
10199
  title: "Fit to Page",
9586
10200
  "aria-label": "Fit to Page",
9587
- children: /* @__PURE__ */ jsx26("svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx26("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" }) })
10201
+ children: /* @__PURE__ */ jsx28("svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx28("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" }) })
9588
10202
  }
9589
10203
  )
9590
10204
  ]
@@ -9608,14 +10222,14 @@ __export(PDFViewerClient_exports, {
9608
10222
  PDFViewerClient: () => PDFViewerClient
9609
10223
  });
9610
10224
  import {
9611
- useEffect as useEffect22,
9612
- useCallback as useCallback33,
9613
- memo as memo26,
9614
- useRef as useRef19,
9615
- useState as useState21,
10225
+ useEffect as useEffect23,
10226
+ useCallback as useCallback34,
10227
+ memo as memo28,
10228
+ useRef as useRef20,
10229
+ useState as useState22,
9616
10230
  forwardRef
9617
10231
  } from "react";
9618
- import { jsx as jsx27, jsxs as jsxs23 } from "react/jsx-runtime";
10232
+ import { jsx as jsx29, jsxs as jsxs25 } from "react/jsx-runtime";
9619
10233
  function getSrcIdentifier(src) {
9620
10234
  if (typeof src === "string") {
9621
10235
  return src;
@@ -9667,10 +10281,11 @@ var init_PDFViewerClient = __esm({
9667
10281
  init_DocumentContainer();
9668
10282
  init_ContinuousScrollContainer();
9669
10283
  init_DualPageContainer();
10284
+ init_BookModeContainer();
9670
10285
  init_FloatingZoomControls2();
9671
10286
  init_PDFLoadingScreen2();
9672
10287
  init_utils();
9673
- PDFViewerInner = memo26(function PDFViewerInner2({
10288
+ PDFViewerInner = memo28(function PDFViewerInner2({
9674
10289
  src,
9675
10290
  initialPage = 1,
9676
10291
  page: controlledPage,
@@ -9697,19 +10312,19 @@ var init_PDFViewerClient = __esm({
9697
10312
  onReady
9698
10313
  }) {
9699
10314
  const { viewerStore, annotationStore, searchStore } = usePDFViewerStores();
9700
- const mountedRef = useRef19(true);
9701
- const [, setLoadState] = useState21("idle");
9702
- const onDocumentLoadRef = useRef19(onDocumentLoad);
9703
- const onErrorRef = useRef19(onError);
9704
- const onPageChangeRef = useRef19(onPageChange);
9705
- const onScaleChangeRef = useRef19(onScaleChange);
9706
- const onZoomChangeRef = useRef19(onZoomChange);
9707
- const onPageRenderStartRef = useRef19(onPageRenderStart);
9708
- const onPageRenderCompleteRef = useRef19(onPageRenderComplete);
9709
- const onHighlightAddedRef = useRef19(onHighlightAdded);
9710
- const onHighlightRemovedRef = useRef19(onHighlightRemoved);
9711
- const onAnnotationAddedRef = useRef19(onAnnotationAdded);
9712
- const onReadyRef = useRef19(onReady);
10315
+ const mountedRef = useRef20(true);
10316
+ const [, setLoadState] = useState22("idle");
10317
+ const onDocumentLoadRef = useRef20(onDocumentLoad);
10318
+ const onErrorRef = useRef20(onError);
10319
+ const onPageChangeRef = useRef20(onPageChange);
10320
+ const onScaleChangeRef = useRef20(onScaleChange);
10321
+ const onZoomChangeRef = useRef20(onZoomChange);
10322
+ const onPageRenderStartRef = useRef20(onPageRenderStart);
10323
+ const onPageRenderCompleteRef = useRef20(onPageRenderComplete);
10324
+ const onHighlightAddedRef = useRef20(onHighlightAdded);
10325
+ const onHighlightRemovedRef = useRef20(onHighlightRemoved);
10326
+ const onAnnotationAddedRef = useRef20(onAnnotationAdded);
10327
+ const onReadyRef = useRef20(onReady);
9713
10328
  onDocumentLoadRef.current = onDocumentLoad;
9714
10329
  onErrorRef.current = onError;
9715
10330
  onPageChangeRef.current = onPageChange;
@@ -9722,8 +10337,8 @@ var init_PDFViewerClient = __esm({
9722
10337
  onAnnotationAddedRef.current = onAnnotationAdded;
9723
10338
  onReadyRef.current = onReady;
9724
10339
  const isControlled = controlledPage !== void 0;
9725
- const prevControlledPageRef = useRef19(controlledPage);
9726
- const srcIdRef = useRef19(null);
10340
+ const prevControlledPageRef = useRef20(controlledPage);
10341
+ const srcIdRef = useRef20(null);
9727
10342
  const currentPage = useViewerStore((s) => s.currentPage);
9728
10343
  const scale = useViewerStore((s) => s.scale);
9729
10344
  const theme = useViewerStore((s) => s.theme);
@@ -9731,9 +10346,10 @@ var init_PDFViewerClient = __esm({
9731
10346
  const loadingProgress = useViewerStore((s) => s.loadingProgress);
9732
10347
  const error = useViewerStore((s) => s.error);
9733
10348
  const sidebarOpen = useViewerStore((s) => s.sidebarOpen);
10349
+ const streamingProgress = useViewerStore((s) => s.streamingProgress);
9734
10350
  const srcId = getSrcIdentifier(src);
9735
- const handleRef = useRef19(null);
9736
- useEffect22(() => {
10351
+ const handleRef = useRef20(null);
10352
+ useEffect23(() => {
9737
10353
  const handle = {
9738
10354
  // ==================== Text Highlighting ====================
9739
10355
  highlightText: async (text, options) => {
@@ -10151,14 +10767,14 @@ var init_PDFViewerClient = __esm({
10151
10767
  handleRef.current = handle;
10152
10768
  onReadyRef.current?.(handle);
10153
10769
  }, [viewerStore, annotationStore, searchStore]);
10154
- const handleRetry = useCallback33(() => {
10770
+ const handleRetry = useCallback34(() => {
10155
10771
  srcIdRef.current = null;
10156
10772
  viewerStore.getState().setError(null);
10157
10773
  setLoadState("idle");
10158
10774
  }, [viewerStore]);
10159
- const abortControllerRef = useRef19(null);
10160
- const currentSrcRef = useRef19(null);
10161
- useEffect22(() => {
10775
+ const abortControllerRef = useRef20(null);
10776
+ const currentSrcRef = useRef20(null);
10777
+ useEffect23(() => {
10162
10778
  mountedRef.current = true;
10163
10779
  return () => {
10164
10780
  mountedRef.current = false;
@@ -10183,7 +10799,8 @@ var init_PDFViewerClient = __esm({
10183
10799
  viewerStore.getState().setError(null);
10184
10800
  };
10185
10801
  }, [viewerStore]);
10186
- useEffect22(() => {
10802
+ const cancelLoaderRef = useRef20(null);
10803
+ useEffect23(() => {
10187
10804
  if (srcIdRef.current === srcId && viewerStore.getState().document) {
10188
10805
  return;
10189
10806
  }
@@ -10193,6 +10810,10 @@ var init_PDFViewerClient = __esm({
10193
10810
  if (abortControllerRef.current) {
10194
10811
  abortControllerRef.current.abort();
10195
10812
  }
10813
+ if (cancelLoaderRef.current) {
10814
+ cancelLoaderRef.current();
10815
+ cancelLoaderRef.current = null;
10816
+ }
10196
10817
  const abortController = new AbortController();
10197
10818
  abortControllerRef.current = abortController;
10198
10819
  const currentDoc = viewerStore.getState().document;
@@ -10205,100 +10826,130 @@ var init_PDFViewerClient = __esm({
10205
10826
  viewerStore.setState({
10206
10827
  document: null,
10207
10828
  isLoading: true,
10208
- loadingProgress: { phase: "fetching" },
10209
- error: null
10829
+ loadingProgress: { phase: "initializing" },
10830
+ error: null,
10831
+ documentLoadingState: "initializing",
10832
+ firstPageReady: false,
10833
+ streamingProgress: null
10210
10834
  });
10211
10835
  setLoadState("loading");
10212
10836
  let lastProgressUpdate = 0;
10213
10837
  let lastPercent = -1;
10214
10838
  const PROGRESS_THROTTLE_MS = 100;
10215
10839
  const PROGRESS_MIN_CHANGE = 5;
10216
- const loadDoc = async () => {
10217
- if (!mountedRef.current || abortController.signal.aborted) return;
10218
- try {
10219
- const { document: document2, numPages } = await loadDocument({
10220
- src,
10221
- workerSrc,
10222
- signal: abortController.signal,
10223
- onProgress: ({ loaded, total }) => {
10224
- if (!mountedRef.current || srcIdRef.current !== loadId || abortController.signal.aborted) {
10225
- return;
10226
- }
10227
- const now = Date.now();
10228
- const percent = total > 0 ? Math.round(loaded / total * 100) : 0;
10229
- const timePassed = now - lastProgressUpdate >= PROGRESS_THROTTLE_MS;
10230
- const percentChanged = Math.abs(percent - lastPercent) >= PROGRESS_MIN_CHANGE;
10231
- const isComplete = percent >= 100;
10232
- if (timePassed && percentChanged || isComplete) {
10233
- lastProgressUpdate = now;
10234
- lastPercent = percent;
10235
- viewerStore.getState().setLoadingProgress({
10236
- phase: "fetching",
10237
- percent,
10238
- bytesLoaded: loaded,
10239
- totalBytes: total
10240
- });
10241
- }
10242
- }
10243
- });
10244
- if (mountedRef.current && srcIdRef.current === loadId && !abortController.signal.aborted) {
10245
- viewerStore.getState().setDocument(document2);
10246
- setLoadState("loaded");
10247
- if (initialPage !== 1 || typeof initialScale === "number" || initialScale === "page-fit") {
10248
- const updates = {};
10249
- if (initialPage !== 1) {
10250
- updates.currentPage = Math.max(1, Math.min(initialPage, numPages));
10251
- }
10252
- if (typeof initialScale === "number") {
10253
- updates.scale = initialScale;
10254
- } else if (initialScale === "page-fit") {
10255
- updates.scale = 0.75;
10256
- }
10257
- if (Object.keys(updates).length > 0) {
10258
- viewerStore.setState(updates);
10259
- }
10260
- }
10261
- onDocumentLoadRef.current?.({ document: document2, numPages });
10262
- } else {
10263
- document2.destroy();
10840
+ const { promise, cancel } = loadDocumentWithCallbacks({
10841
+ src,
10842
+ workerSrc,
10843
+ signal: abortController.signal,
10844
+ onProgress: ({ loaded, total }) => {
10845
+ if (!mountedRef.current || srcIdRef.current !== loadId || abortController.signal.aborted) {
10846
+ return;
10264
10847
  }
10265
- } catch (err) {
10266
- if (err instanceof DOMException && err.name === "AbortError") {
10848
+ const now = Date.now();
10849
+ const percent = total > 0 ? Math.round(loaded / total * 100) : 0;
10850
+ const timePassed = now - lastProgressUpdate >= PROGRESS_THROTTLE_MS;
10851
+ const percentChanged = Math.abs(percent - lastPercent) >= PROGRESS_MIN_CHANGE;
10852
+ const isComplete = percent >= 100;
10853
+ if (timePassed && percentChanged || isComplete) {
10854
+ lastProgressUpdate = now;
10855
+ lastPercent = percent;
10856
+ viewerStore.setState({
10857
+ loadingProgress: {
10858
+ phase: "fetching",
10859
+ percent,
10860
+ bytesLoaded: loaded,
10861
+ totalBytes: total
10862
+ },
10863
+ streamingProgress: { loaded, total },
10864
+ documentLoadingState: "loading"
10865
+ });
10866
+ }
10867
+ },
10868
+ onDocumentReady: (document2, numPages) => {
10869
+ if (!mountedRef.current || srcIdRef.current !== loadId || abortController.signal.aborted) {
10267
10870
  return;
10268
10871
  }
10269
- const errorMessage = err instanceof Error ? err.message : String(err);
10270
- if (abortController.signal.aborted || errorMessage.includes("network error") || errorMessage.includes("aborted")) {
10872
+ viewerStore.setState({
10873
+ document: document2,
10874
+ numPages,
10875
+ loadingProgress: { phase: "parsing" },
10876
+ documentLoadingState: "loading"
10877
+ });
10878
+ },
10879
+ onFirstPageReady: () => {
10880
+ if (!mountedRef.current || srcIdRef.current !== loadId || abortController.signal.aborted) {
10271
10881
  return;
10272
10882
  }
10273
- if (mountedRef.current && srcIdRef.current === loadId) {
10274
- const error2 = err instanceof Error ? err : new Error("Failed to load document");
10275
- viewerStore.getState().setError(error2);
10276
- setLoadState("error");
10277
- onErrorRef.current?.(error2);
10883
+ viewerStore.setState({
10884
+ isLoading: false,
10885
+ firstPageReady: true,
10886
+ loadingProgress: null,
10887
+ documentLoadingState: "ready"
10888
+ });
10889
+ setLoadState("loaded");
10890
+ }
10891
+ });
10892
+ cancelLoaderRef.current = cancel;
10893
+ promise.then(({ document: document2, numPages }) => {
10894
+ if (mountedRef.current && srcIdRef.current === loadId && !abortController.signal.aborted) {
10895
+ if (!viewerStore.getState().document) {
10896
+ viewerStore.getState().setDocument(document2);
10897
+ }
10898
+ if (initialPage !== 1 || typeof initialScale === "number" || initialScale === "page-fit") {
10899
+ const updates = {};
10900
+ if (initialPage !== 1) {
10901
+ updates.currentPage = Math.max(1, Math.min(initialPage, numPages));
10902
+ }
10903
+ if (typeof initialScale === "number") {
10904
+ updates.scale = initialScale;
10905
+ } else if (initialScale === "page-fit") {
10906
+ updates.scale = 0.75;
10907
+ }
10908
+ if (Object.keys(updates).length > 0) {
10909
+ viewerStore.setState(updates);
10910
+ }
10278
10911
  }
10912
+ onDocumentLoadRef.current?.({ document: document2, numPages });
10279
10913
  }
10280
- };
10281
- loadDoc();
10914
+ }).catch((err) => {
10915
+ if (err instanceof DOMException && err.name === "AbortError") {
10916
+ return;
10917
+ }
10918
+ const errorMessage = err instanceof Error ? err.message : String(err);
10919
+ if (abortController.signal.aborted || errorMessage.includes("network error") || errorMessage.includes("aborted")) {
10920
+ return;
10921
+ }
10922
+ if (mountedRef.current && srcIdRef.current === loadId) {
10923
+ const error2 = err instanceof Error ? err : new Error("Failed to load document");
10924
+ viewerStore.getState().setError(error2);
10925
+ setLoadState("error");
10926
+ onErrorRef.current?.(error2);
10927
+ }
10928
+ });
10282
10929
  return () => {
10283
10930
  abortController.abort();
10931
+ if (cancelLoaderRef.current) {
10932
+ cancelLoaderRef.current();
10933
+ cancelLoaderRef.current = null;
10934
+ }
10284
10935
  };
10285
10936
  }, [srcId, src, workerSrc, initialPage, initialScale, viewerStore]);
10286
- const prevPageRef = useRef19(currentPage);
10287
- useEffect22(() => {
10937
+ const prevPageRef = useRef20(currentPage);
10938
+ useEffect23(() => {
10288
10939
  if (prevPageRef.current !== currentPage) {
10289
10940
  prevPageRef.current = currentPage;
10290
10941
  onPageChangeRef.current?.(currentPage);
10291
10942
  }
10292
10943
  }, [currentPage]);
10293
- const prevScaleRef = useRef19(scale);
10294
- useEffect22(() => {
10944
+ const prevScaleRef = useRef20(scale);
10945
+ useEffect23(() => {
10295
10946
  if (prevScaleRef.current !== scale) {
10296
10947
  prevScaleRef.current = scale;
10297
10948
  onScaleChangeRef.current?.(scale);
10298
10949
  onZoomChangeRef.current?.(scale);
10299
10950
  }
10300
10951
  }, [scale]);
10301
- useEffect22(() => {
10952
+ useEffect23(() => {
10302
10953
  if (!isControlled || controlledPage === void 0) return;
10303
10954
  if (prevControlledPageRef.current === controlledPage) return;
10304
10955
  prevControlledPageRef.current = controlledPage;
@@ -10311,7 +10962,7 @@ var init_PDFViewerClient = __esm({
10311
10962
  if (error) {
10312
10963
  if (errorComponent) {
10313
10964
  const errorContent = typeof errorComponent === "function" ? errorComponent(error, handleRetry) : errorComponent;
10314
- return /* @__PURE__ */ jsx27(
10965
+ return /* @__PURE__ */ jsx29(
10315
10966
  "div",
10316
10967
  {
10317
10968
  className: cn(
@@ -10325,7 +10976,7 @@ var init_PDFViewerClient = __esm({
10325
10976
  }
10326
10977
  );
10327
10978
  }
10328
- return /* @__PURE__ */ jsx27(
10979
+ return /* @__PURE__ */ jsx29(
10329
10980
  "div",
10330
10981
  {
10331
10982
  className: cn(
@@ -10335,10 +10986,10 @@ var init_PDFViewerClient = __esm({
10335
10986
  themeClass,
10336
10987
  className
10337
10988
  ),
10338
- children: /* @__PURE__ */ jsx27("div", { className: "flex-1 flex items-center justify-center", children: /* @__PURE__ */ jsxs23("div", { className: "text-center p-8", children: [
10339
- /* @__PURE__ */ jsx27("div", { className: "text-red-500 text-lg font-semibold mb-2", children: "Failed to load PDF" }),
10340
- /* @__PURE__ */ jsx27("div", { className: "text-gray-500 text-sm", children: error.message }),
10341
- /* @__PURE__ */ jsx27(
10989
+ children: /* @__PURE__ */ jsx29("div", { className: "flex-1 flex items-center justify-center", children: /* @__PURE__ */ jsxs25("div", { className: "text-center p-8", children: [
10990
+ /* @__PURE__ */ jsx29("div", { className: "text-red-500 text-lg font-semibold mb-2", children: "Failed to load PDF" }),
10991
+ /* @__PURE__ */ jsx29("div", { className: "text-gray-500 text-sm", children: error.message }),
10992
+ /* @__PURE__ */ jsx29(
10342
10993
  "button",
10343
10994
  {
10344
10995
  onClick: handleRetry,
@@ -10353,15 +11004,17 @@ var init_PDFViewerClient = __esm({
10353
11004
  const renderContainer = () => {
10354
11005
  switch (viewMode) {
10355
11006
  case "continuous":
10356
- return /* @__PURE__ */ jsx27(ContinuousScrollContainer, {});
11007
+ return /* @__PURE__ */ jsx29(ContinuousScrollContainer, {});
10357
11008
  case "dual":
10358
- return /* @__PURE__ */ jsx27(DualPageContainer, {});
11009
+ return /* @__PURE__ */ jsx29(DualPageContainer, {});
11010
+ case "book":
11011
+ return /* @__PURE__ */ jsx29(BookModeContainer, {});
10359
11012
  case "single":
10360
11013
  default:
10361
- return /* @__PURE__ */ jsx27(DocumentContainer, {});
11014
+ return /* @__PURE__ */ jsx29(DocumentContainer, {});
10362
11015
  }
10363
11016
  };
10364
- return /* @__PURE__ */ jsxs23(
11017
+ return /* @__PURE__ */ jsxs25(
10365
11018
  "div",
10366
11019
  {
10367
11020
  className: cn(
@@ -10373,14 +11026,14 @@ var init_PDFViewerClient = __esm({
10373
11026
  className
10374
11027
  ),
10375
11028
  children: [
10376
- showToolbar && /* @__PURE__ */ jsx27(Toolbar, {}),
10377
- showAnnotationToolbar && /* @__PURE__ */ jsx27(AnnotationToolbar, {}),
10378
- /* @__PURE__ */ jsxs23("div", { className: "flex flex-1 overflow-hidden", children: [
10379
- showSidebar && sidebarOpen && /* @__PURE__ */ jsx27(Sidebar, {}),
11029
+ showToolbar && /* @__PURE__ */ jsx29(Toolbar, {}),
11030
+ showAnnotationToolbar && /* @__PURE__ */ jsx29(AnnotationToolbar, {}),
11031
+ /* @__PURE__ */ jsxs25("div", { className: "flex flex-1 overflow-hidden", children: [
11032
+ showSidebar && sidebarOpen && /* @__PURE__ */ jsx29(Sidebar, {}),
10380
11033
  renderContainer()
10381
11034
  ] }),
10382
- showFloatingZoom && /* @__PURE__ */ jsx27(FloatingZoomControls, { position: "bottom-right" }),
10383
- isLoading && /* @__PURE__ */ jsx27("div", { className: "absolute inset-0 z-50", children: loadingComponent ?? /* @__PURE__ */ jsx27(
11035
+ showFloatingZoom && /* @__PURE__ */ jsx29(FloatingZoomControls, { position: "bottom-right" }),
11036
+ isLoading && /* @__PURE__ */ jsx29("div", { className: "absolute inset-0 z-50", children: loadingComponent ?? /* @__PURE__ */ jsx29(
10384
11037
  PDFLoadingScreen,
10385
11038
  {
10386
11039
  phase: loadingProgress?.phase ?? "fetching",
@@ -10388,15 +11041,23 @@ var init_PDFViewerClient = __esm({
10388
11041
  bytesLoaded: loadingProgress?.bytesLoaded,
10389
11042
  totalBytes: loadingProgress?.totalBytes
10390
11043
  }
10391
- ) })
11044
+ ) }),
11045
+ !isLoading && streamingProgress && streamingProgress.total > 0 && streamingProgress.loaded < streamingProgress.total && /* @__PURE__ */ jsxs25("div", { className: "absolute bottom-20 right-4 z-40 px-3 py-2 bg-gray-900/80 text-white text-xs rounded-lg shadow-lg flex items-center gap-2", children: [
11046
+ /* @__PURE__ */ jsx29("div", { className: "w-3 h-3 border-2 border-white/30 border-t-white rounded-full animate-spin" }),
11047
+ /* @__PURE__ */ jsx29("span", { children: "Loading pages..." }),
11048
+ /* @__PURE__ */ jsxs25("span", { className: "text-white/60", children: [
11049
+ Math.round(streamingProgress.loaded / streamingProgress.total * 100),
11050
+ "%"
11051
+ ] })
11052
+ ] })
10392
11053
  ]
10393
11054
  }
10394
11055
  );
10395
11056
  });
10396
11057
  PDFViewerInnerWithRef = forwardRef(
10397
11058
  function PDFViewerInnerWithRef2(props, ref) {
10398
- const handleRef = useRef19(null);
10399
- const handleReady = useCallback33((handle) => {
11059
+ const handleRef = useRef20(null);
11060
+ const handleReady = useCallback34((handle) => {
10400
11061
  handleRef.current = handle;
10401
11062
  if (typeof ref === "function") {
10402
11063
  ref(handle);
@@ -10404,17 +11065,17 @@ var init_PDFViewerClient = __esm({
10404
11065
  ref.current = handle;
10405
11066
  }
10406
11067
  }, [ref]);
10407
- return /* @__PURE__ */ jsx27(PDFViewerInner, { ...props, onReady: handleReady });
11068
+ return /* @__PURE__ */ jsx29(PDFViewerInner, { ...props, onReady: handleReady });
10408
11069
  }
10409
11070
  );
10410
- PDFViewerClient = memo26(
11071
+ PDFViewerClient = memo28(
10411
11072
  forwardRef(function PDFViewerClient2(props, ref) {
10412
- return /* @__PURE__ */ jsx27(
11073
+ return /* @__PURE__ */ jsx29(
10413
11074
  PDFViewerProvider,
10414
11075
  {
10415
11076
  theme: props.theme,
10416
11077
  defaultSidebarPanel: props.defaultSidebarPanel,
10417
- children: /* @__PURE__ */ jsx27(PDFViewerInnerWithRef, { ref, ...props })
11078
+ children: /* @__PURE__ */ jsx29(PDFViewerInnerWithRef, { ref, ...props })
10418
11079
  }
10419
11080
  );
10420
11081
  })
@@ -10423,8 +11084,8 @@ var init_PDFViewerClient = __esm({
10423
11084
  });
10424
11085
 
10425
11086
  // src/components/PDFViewer/PDFViewer.tsx
10426
- import { lazy, Suspense, memo as memo27 } from "react";
10427
- import { jsx as jsx28, jsxs as jsxs24 } from "react/jsx-runtime";
11087
+ import { lazy, Suspense, memo as memo29 } from "react";
11088
+ import { jsx as jsx30, jsxs as jsxs26 } from "react/jsx-runtime";
10428
11089
  var PDFViewerClient3, PDFViewerLoading, PDFViewer;
10429
11090
  var init_PDFViewer = __esm({
10430
11091
  "src/components/PDFViewer/PDFViewer.tsx"() {
@@ -10433,10 +11094,10 @@ var init_PDFViewer = __esm({
10433
11094
  PDFViewerClient3 = lazy(
10434
11095
  () => Promise.resolve().then(() => (init_PDFViewerClient(), PDFViewerClient_exports)).then((mod) => ({ default: mod.PDFViewerClient }))
10435
11096
  );
10436
- PDFViewerLoading = memo27(function PDFViewerLoading2({
11097
+ PDFViewerLoading = memo29(function PDFViewerLoading2({
10437
11098
  className
10438
11099
  }) {
10439
- return /* @__PURE__ */ jsx28(
11100
+ return /* @__PURE__ */ jsx30(
10440
11101
  "div",
10441
11102
  {
10442
11103
  className: cn(
@@ -10445,18 +11106,18 @@ var init_PDFViewer = __esm({
10445
11106
  "bg-white dark:bg-gray-900",
10446
11107
  className
10447
11108
  ),
10448
- children: /* @__PURE__ */ jsx28("div", { className: "flex-1 flex items-center justify-center", children: /* @__PURE__ */ jsxs24("div", { className: "flex flex-col items-center", children: [
10449
- /* @__PURE__ */ jsx28("div", { className: "w-8 h-8 border-4 border-blue-500 border-t-transparent rounded-full animate-spin" }),
10450
- /* @__PURE__ */ jsx28("div", { className: "mt-2 text-sm text-gray-500", children: "Loading PDF viewer..." })
11109
+ children: /* @__PURE__ */ jsx30("div", { className: "flex-1 flex items-center justify-center", children: /* @__PURE__ */ jsxs26("div", { className: "flex flex-col items-center", children: [
11110
+ /* @__PURE__ */ jsx30("div", { className: "w-8 h-8 border-4 border-blue-500 border-t-transparent rounded-full animate-spin" }),
11111
+ /* @__PURE__ */ jsx30("div", { className: "mt-2 text-sm text-gray-500", children: "Loading PDF viewer..." })
10451
11112
  ] }) })
10452
11113
  }
10453
11114
  );
10454
11115
  });
10455
- PDFViewer = memo27(function PDFViewer2(props) {
11116
+ PDFViewer = memo29(function PDFViewer2(props) {
10456
11117
  if (typeof window === "undefined") {
10457
- return /* @__PURE__ */ jsx28(PDFViewerLoading, { className: props.className });
11118
+ return /* @__PURE__ */ jsx30(PDFViewerLoading, { className: props.className });
10458
11119
  }
10459
- return /* @__PURE__ */ jsx28(Suspense, { fallback: /* @__PURE__ */ jsx28(PDFViewerLoading, { className: props.className }), children: /* @__PURE__ */ jsx28(PDFViewerClient3, { ...props }) });
11120
+ return /* @__PURE__ */ jsx30(Suspense, { fallback: /* @__PURE__ */ jsx30(PDFViewerLoading, { className: props.className }), children: /* @__PURE__ */ jsx30(PDFViewerClient3, { ...props }) });
10460
11121
  });
10461
11122
  }
10462
11123
  });
@@ -10471,6 +11132,7 @@ var init_PDFViewer2 = __esm({
10471
11132
  init_VirtualizedDocumentContainer();
10472
11133
  init_ContinuousScrollContainer();
10473
11134
  init_DualPageContainer();
11135
+ init_BookModeContainer();
10474
11136
  }
10475
11137
  });
10476
11138
 
@@ -10485,8 +11147,8 @@ init_AnnotationToolbar2();
10485
11147
 
10486
11148
  // src/components/Annotations/StickyNote.tsx
10487
11149
  init_utils();
10488
- import { memo as memo28, useState as useState22, useRef as useRef20, useEffect as useEffect23, useCallback as useCallback34 } from "react";
10489
- import { jsx as jsx29, jsxs as jsxs25 } from "react/jsx-runtime";
11150
+ import { memo as memo30, useState as useState23, useRef as useRef21, useEffect as useEffect24, useCallback as useCallback35 } from "react";
11151
+ import { jsx as jsx31, jsxs as jsxs27 } from "react/jsx-runtime";
10490
11152
  var NOTE_COLORS = [
10491
11153
  "#fef08a",
10492
11154
  // yellow
@@ -10499,7 +11161,7 @@ var NOTE_COLORS = [
10499
11161
  "#fed7aa"
10500
11162
  // orange
10501
11163
  ];
10502
- var StickyNote = memo28(function StickyNote2({
11164
+ var StickyNote = memo30(function StickyNote2({
10503
11165
  note,
10504
11166
  scale,
10505
11167
  isSelected,
@@ -10512,37 +11174,37 @@ var StickyNote = memo28(function StickyNote2({
10512
11174
  onDragStart,
10513
11175
  className
10514
11176
  }) {
10515
- const [isExpanded, setIsExpanded] = useState22(false);
10516
- const [localContent, setLocalContent] = useState22(note.content);
10517
- const textareaRef = useRef20(null);
10518
- const noteRef = useRef20(null);
10519
- useEffect23(() => {
11177
+ const [isExpanded, setIsExpanded] = useState23(false);
11178
+ const [localContent, setLocalContent] = useState23(note.content);
11179
+ const textareaRef = useRef21(null);
11180
+ const noteRef = useRef21(null);
11181
+ useEffect24(() => {
10520
11182
  setLocalContent(note.content);
10521
11183
  }, [note.content]);
10522
- useEffect23(() => {
11184
+ useEffect24(() => {
10523
11185
  if (isEditing && textareaRef.current) {
10524
11186
  textareaRef.current.focus();
10525
11187
  textareaRef.current.select();
10526
11188
  }
10527
11189
  }, [isEditing]);
10528
- const handleClick = useCallback34((e) => {
11190
+ const handleClick = useCallback35((e) => {
10529
11191
  e.stopPropagation();
10530
11192
  onSelect?.();
10531
11193
  if (!isExpanded) {
10532
11194
  setIsExpanded(true);
10533
11195
  }
10534
11196
  }, [isExpanded, onSelect]);
10535
- const handleDoubleClick = useCallback34((e) => {
11197
+ const handleDoubleClick = useCallback35((e) => {
10536
11198
  e.stopPropagation();
10537
11199
  onStartEdit?.();
10538
11200
  }, [onStartEdit]);
10539
- const handleBlur = useCallback34(() => {
11201
+ const handleBlur = useCallback35(() => {
10540
11202
  if (isEditing && localContent !== note.content) {
10541
11203
  onUpdate?.({ content: localContent });
10542
11204
  }
10543
11205
  onEndEdit?.();
10544
11206
  }, [isEditing, localContent, note.content, onUpdate, onEndEdit]);
10545
- const handleKeyDown = useCallback34((e) => {
11207
+ const handleKeyDown = useCallback35((e) => {
10546
11208
  if (e.key === "Escape") {
10547
11209
  setLocalContent(note.content);
10548
11210
  onEndEdit?.();
@@ -10550,16 +11212,16 @@ var StickyNote = memo28(function StickyNote2({
10550
11212
  handleBlur();
10551
11213
  }
10552
11214
  }, [note.content, onEndEdit, handleBlur]);
10553
- const handleColorChange = useCallback34((color) => {
11215
+ const handleColorChange = useCallback35((color) => {
10554
11216
  onUpdate?.({ color });
10555
11217
  }, [onUpdate]);
10556
- const handleCollapse = useCallback34((e) => {
11218
+ const handleCollapse = useCallback35((e) => {
10557
11219
  e.stopPropagation();
10558
11220
  setIsExpanded(false);
10559
11221
  onEndEdit?.();
10560
11222
  }, [onEndEdit]);
10561
11223
  if (!isExpanded) {
10562
- return /* @__PURE__ */ jsx29(
11224
+ return /* @__PURE__ */ jsx31(
10563
11225
  "div",
10564
11226
  {
10565
11227
  ref: noteRef,
@@ -10580,14 +11242,14 @@ var StickyNote = memo28(function StickyNote2({
10580
11242
  onMouseDown: onDragStart,
10581
11243
  onTouchStart: onDragStart,
10582
11244
  title: note.content || "Empty note",
10583
- children: /* @__PURE__ */ jsx29(
11245
+ children: /* @__PURE__ */ jsx31(
10584
11246
  "svg",
10585
11247
  {
10586
11248
  className: "w-4 h-4 opacity-70",
10587
11249
  fill: "currentColor",
10588
11250
  viewBox: "0 0 20 20",
10589
11251
  style: { color: "#333" },
10590
- children: /* @__PURE__ */ jsx29(
11252
+ children: /* @__PURE__ */ jsx31(
10591
11253
  "path",
10592
11254
  {
10593
11255
  fillRule: "evenodd",
@@ -10600,7 +11262,7 @@ var StickyNote = memo28(function StickyNote2({
10600
11262
  }
10601
11263
  );
10602
11264
  }
10603
- return /* @__PURE__ */ jsxs25(
11265
+ return /* @__PURE__ */ jsxs27(
10604
11266
  "div",
10605
11267
  {
10606
11268
  ref: noteRef,
@@ -10618,14 +11280,14 @@ var StickyNote = memo28(function StickyNote2({
10618
11280
  },
10619
11281
  onClick: handleClick,
10620
11282
  children: [
10621
- /* @__PURE__ */ jsxs25(
11283
+ /* @__PURE__ */ jsxs27(
10622
11284
  "div",
10623
11285
  {
10624
11286
  className: "flex items-center justify-between px-2 py-1 border-b border-black/10 cursor-move",
10625
11287
  onMouseDown: onDragStart,
10626
11288
  onTouchStart: onDragStart,
10627
11289
  children: [
10628
- /* @__PURE__ */ jsx29("div", { className: "flex gap-1", children: NOTE_COLORS.map((color) => /* @__PURE__ */ jsx29(
11290
+ /* @__PURE__ */ jsx31("div", { className: "flex gap-1", children: NOTE_COLORS.map((color) => /* @__PURE__ */ jsx31(
10629
11291
  "button",
10630
11292
  {
10631
11293
  className: cn(
@@ -10642,8 +11304,8 @@ var StickyNote = memo28(function StickyNote2({
10642
11304
  },
10643
11305
  color
10644
11306
  )) }),
10645
- /* @__PURE__ */ jsxs25("div", { className: "flex gap-1", children: [
10646
- /* @__PURE__ */ jsx29(
11307
+ /* @__PURE__ */ jsxs27("div", { className: "flex gap-1", children: [
11308
+ /* @__PURE__ */ jsx31(
10647
11309
  "button",
10648
11310
  {
10649
11311
  className: "p-0.5 hover:bg-black/10 rounded",
@@ -10652,23 +11314,23 @@ var StickyNote = memo28(function StickyNote2({
10652
11314
  onDelete?.();
10653
11315
  },
10654
11316
  title: "Delete note",
10655
- children: /* @__PURE__ */ jsx29("svg", { className: "w-3.5 h-3.5 text-gray-600", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx29("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" }) })
11317
+ children: /* @__PURE__ */ jsx31("svg", { className: "w-3.5 h-3.5 text-gray-600", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx31("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" }) })
10656
11318
  }
10657
11319
  ),
10658
- /* @__PURE__ */ jsx29(
11320
+ /* @__PURE__ */ jsx31(
10659
11321
  "button",
10660
11322
  {
10661
11323
  className: "p-0.5 hover:bg-black/10 rounded",
10662
11324
  onClick: handleCollapse,
10663
11325
  title: "Collapse note",
10664
- children: /* @__PURE__ */ jsx29("svg", { className: "w-3.5 h-3.5 text-gray-600", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx29("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M6 18L18 6M6 6l12 12" }) })
11326
+ children: /* @__PURE__ */ jsx31("svg", { className: "w-3.5 h-3.5 text-gray-600", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx31("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M6 18L18 6M6 6l12 12" }) })
10665
11327
  }
10666
11328
  )
10667
11329
  ] })
10668
11330
  ]
10669
11331
  }
10670
11332
  ),
10671
- /* @__PURE__ */ jsx29("div", { className: "p-2", children: isEditing ? /* @__PURE__ */ jsx29(
11333
+ /* @__PURE__ */ jsx31("div", { className: "p-2", children: isEditing ? /* @__PURE__ */ jsx31(
10672
11334
  "textarea",
10673
11335
  {
10674
11336
  ref: textareaRef,
@@ -10683,7 +11345,7 @@ var StickyNote = memo28(function StickyNote2({
10683
11345
  onKeyDown: handleKeyDown,
10684
11346
  placeholder: "Enter note..."
10685
11347
  }
10686
- ) : /* @__PURE__ */ jsx29(
11348
+ ) : /* @__PURE__ */ jsx31(
10687
11349
  "div",
10688
11350
  {
10689
11351
  className: cn(
@@ -10694,7 +11356,7 @@ var StickyNote = memo28(function StickyNote2({
10694
11356
  children: note.content || "Double-click to edit..."
10695
11357
  }
10696
11358
  ) }),
10697
- /* @__PURE__ */ jsx29("div", { className: "px-2 pb-1 text-[10px] text-gray-500", children: new Date(note.updatedAt).toLocaleDateString() })
11359
+ /* @__PURE__ */ jsx31("div", { className: "px-2 pb-1 text-[10px] text-gray-500", children: new Date(note.updatedAt).toLocaleDateString() })
10698
11360
  ]
10699
11361
  }
10700
11362
  );
@@ -10702,8 +11364,8 @@ var StickyNote = memo28(function StickyNote2({
10702
11364
 
10703
11365
  // src/components/Annotations/DrawingCanvas.tsx
10704
11366
  init_utils();
10705
- import { memo as memo29, useRef as useRef21, useCallback as useCallback35, useState as useState23 } from "react";
10706
- import { jsx as jsx30 } from "react/jsx-runtime";
11367
+ import { memo as memo31, useRef as useRef22, useCallback as useCallback36, useState as useState24 } from "react";
11368
+ import { jsx as jsx32 } from "react/jsx-runtime";
10707
11369
  function pointsToSvgPath(points) {
10708
11370
  if (points.length === 0) return "";
10709
11371
  if (points.length === 1) {
@@ -10741,7 +11403,7 @@ function simplifyPath(points, tolerance = 1) {
10741
11403
  result.push(points[points.length - 1]);
10742
11404
  return result;
10743
11405
  }
10744
- var DrawingCanvas = memo29(function DrawingCanvas2({
11406
+ var DrawingCanvas = memo31(function DrawingCanvas2({
10745
11407
  width,
10746
11408
  height,
10747
11409
  scale,
@@ -10751,10 +11413,10 @@ var DrawingCanvas = memo29(function DrawingCanvas2({
10751
11413
  onDrawingComplete,
10752
11414
  className
10753
11415
  }) {
10754
- const svgRef = useRef21(null);
10755
- const [isDrawing, setIsDrawing] = useState23(false);
10756
- const [currentPath, setCurrentPath] = useState23([]);
10757
- const getPoint = useCallback35((e) => {
11416
+ const svgRef = useRef22(null);
11417
+ const [isDrawing, setIsDrawing] = useState24(false);
11418
+ const [currentPath, setCurrentPath] = useState24([]);
11419
+ const getPoint = useCallback36((e) => {
10758
11420
  if (!svgRef.current) return null;
10759
11421
  const svg = svgRef.current;
10760
11422
  const rect = svg.getBoundingClientRect();
@@ -10774,7 +11436,7 @@ var DrawingCanvas = memo29(function DrawingCanvas2({
10774
11436
  y: (clientY - rect.top) / scale
10775
11437
  };
10776
11438
  }, [scale]);
10777
- const handleStart = useCallback35((e) => {
11439
+ const handleStart = useCallback36((e) => {
10778
11440
  if (!isActive) return;
10779
11441
  const point = getPoint(e);
10780
11442
  if (point) {
@@ -10782,14 +11444,14 @@ var DrawingCanvas = memo29(function DrawingCanvas2({
10782
11444
  setCurrentPath([point]);
10783
11445
  }
10784
11446
  }, [isActive, getPoint]);
10785
- const handleMove = useCallback35((e) => {
11447
+ const handleMove = useCallback36((e) => {
10786
11448
  if (!isDrawing || !isActive) return;
10787
11449
  const point = getPoint(e);
10788
11450
  if (point) {
10789
11451
  setCurrentPath((prev) => [...prev, point]);
10790
11452
  }
10791
11453
  }, [isDrawing, isActive, getPoint]);
10792
- const handleEnd = useCallback35(() => {
11454
+ const handleEnd = useCallback36(() => {
10793
11455
  if (!isDrawing) return;
10794
11456
  setIsDrawing(false);
10795
11457
  if (currentPath.length >= 2) {
@@ -10798,7 +11460,7 @@ var DrawingCanvas = memo29(function DrawingCanvas2({
10798
11460
  }
10799
11461
  setCurrentPath([]);
10800
11462
  }, [isDrawing, currentPath, onDrawingComplete]);
10801
- return /* @__PURE__ */ jsx30(
11463
+ return /* @__PURE__ */ jsx32(
10802
11464
  "svg",
10803
11465
  {
10804
11466
  ref: svgRef,
@@ -10818,7 +11480,7 @@ var DrawingCanvas = memo29(function DrawingCanvas2({
10818
11480
  onTouchStart: handleStart,
10819
11481
  onTouchMove: handleMove,
10820
11482
  onTouchEnd: handleEnd,
10821
- children: isDrawing && currentPath.length > 0 && /* @__PURE__ */ jsx30(
11483
+ children: isDrawing && currentPath.length > 0 && /* @__PURE__ */ jsx32(
10822
11484
  "path",
10823
11485
  {
10824
11486
  d: pointsToSvgPath(currentPath),
@@ -10836,9 +11498,9 @@ var DrawingCanvas = memo29(function DrawingCanvas2({
10836
11498
 
10837
11499
  // src/components/Annotations/ShapeRenderer.tsx
10838
11500
  init_utils();
10839
- import { memo as memo30, useCallback as useCallback36, useState as useState24, useRef as useRef22 } from "react";
10840
- import { jsx as jsx31, jsxs as jsxs26 } from "react/jsx-runtime";
10841
- var ShapeRenderer = memo30(function ShapeRenderer2({
11501
+ import { memo as memo32, useCallback as useCallback37, useState as useState25, useRef as useRef23 } from "react";
11502
+ import { jsx as jsx33, jsxs as jsxs28 } from "react/jsx-runtime";
11503
+ var ShapeRenderer = memo32(function ShapeRenderer2({
10842
11504
  shape,
10843
11505
  scale,
10844
11506
  isSelected,
@@ -10848,18 +11510,18 @@ var ShapeRenderer = memo30(function ShapeRenderer2({
10848
11510
  onDelete: _onDelete,
10849
11511
  className
10850
11512
  }) {
10851
- const [_isDragging, setIsDragging] = useState24(false);
10852
- const [_isResizing, setIsResizing] = useState24(false);
10853
- const [activeHandle, setActiveHandle] = useState24(null);
10854
- const startPosRef = useRef22({ x: 0, y: 0 });
10855
- const startShapeRef = useRef22({ x: 0, y: 0, width: 0, height: 0 });
11513
+ const [_isDragging, setIsDragging] = useState25(false);
11514
+ const [_isResizing, setIsResizing] = useState25(false);
11515
+ const [activeHandle, setActiveHandle] = useState25(null);
11516
+ const startPosRef = useRef23({ x: 0, y: 0 });
11517
+ const startShapeRef = useRef23({ x: 0, y: 0, width: 0, height: 0 });
10856
11518
  const { shapeType, x, y, width, height, color, strokeWidth, id: _id } = shape;
10857
11519
  const scaledX = x * scale;
10858
11520
  const scaledY = y * scale;
10859
11521
  const scaledWidth = width * scale;
10860
11522
  const scaledHeight = height * scale;
10861
11523
  const scaledStroke = strokeWidth * scale;
10862
- const getResizeHandles = useCallback36(() => {
11524
+ const getResizeHandles = useCallback37(() => {
10863
11525
  const handleSize = 8;
10864
11526
  const half = handleSize / 2;
10865
11527
  return [
@@ -10873,7 +11535,7 @@ var ShapeRenderer = memo30(function ShapeRenderer2({
10873
11535
  { position: "w", cursor: "ew-resize", x: scaledX - half, y: scaledY + scaledHeight / 2 - half }
10874
11536
  ];
10875
11537
  }, [scaledX, scaledY, scaledWidth, scaledHeight]);
10876
- const handleMouseDown = useCallback36((e, handle) => {
11538
+ const handleMouseDown = useCallback37((e, handle) => {
10877
11539
  e.stopPropagation();
10878
11540
  onSelect?.();
10879
11541
  if (!isEditing) return;
@@ -10949,7 +11611,7 @@ var ShapeRenderer = memo30(function ShapeRenderer2({
10949
11611
  document.addEventListener("mousemove", handleMouseMove);
10950
11612
  document.addEventListener("mouseup", handleMouseUp);
10951
11613
  }, [isEditing, x, y, width, height, scale, onSelect, onUpdate]);
10952
- const renderShape2 = useCallback36(() => {
11614
+ const renderShape2 = useCallback37(() => {
10953
11615
  const commonProps = {
10954
11616
  stroke: color,
10955
11617
  strokeWidth: scaledStroke,
@@ -10961,7 +11623,7 @@ var ShapeRenderer = memo30(function ShapeRenderer2({
10961
11623
  };
10962
11624
  switch (shapeType) {
10963
11625
  case "rect":
10964
- return /* @__PURE__ */ jsx31(
11626
+ return /* @__PURE__ */ jsx33(
10965
11627
  "rect",
10966
11628
  {
10967
11629
  x: scaledX,
@@ -10972,7 +11634,7 @@ var ShapeRenderer = memo30(function ShapeRenderer2({
10972
11634
  }
10973
11635
  );
10974
11636
  case "circle":
10975
- return /* @__PURE__ */ jsx31(
11637
+ return /* @__PURE__ */ jsx33(
10976
11638
  "ellipse",
10977
11639
  {
10978
11640
  cx: scaledX + scaledWidth / 2,
@@ -10983,7 +11645,7 @@ var ShapeRenderer = memo30(function ShapeRenderer2({
10983
11645
  }
10984
11646
  );
10985
11647
  case "line":
10986
- return /* @__PURE__ */ jsx31(
11648
+ return /* @__PURE__ */ jsx33(
10987
11649
  "line",
10988
11650
  {
10989
11651
  x1: scaledX,
@@ -11003,22 +11665,22 @@ var ShapeRenderer = memo30(function ShapeRenderer2({
11003
11665
  const arrow1Y = endY - arrowLength * Math.sin(angle - arrowAngle);
11004
11666
  const arrow2X = endX - arrowLength * Math.cos(angle + arrowAngle);
11005
11667
  const arrow2Y = endY - arrowLength * Math.sin(angle + arrowAngle);
11006
- return /* @__PURE__ */ jsxs26("g", { children: [
11007
- /* @__PURE__ */ jsx31("line", { x1: scaledX, y1: scaledY, x2: endX, y2: endY, ...commonProps }),
11008
- /* @__PURE__ */ jsx31("line", { x1: endX, y1: endY, x2: arrow1X, y2: arrow1Y, ...commonProps }),
11009
- /* @__PURE__ */ jsx31("line", { x1: endX, y1: endY, x2: arrow2X, y2: arrow2Y, ...commonProps })
11668
+ return /* @__PURE__ */ jsxs28("g", { children: [
11669
+ /* @__PURE__ */ jsx33("line", { x1: scaledX, y1: scaledY, x2: endX, y2: endY, ...commonProps }),
11670
+ /* @__PURE__ */ jsx33("line", { x1: endX, y1: endY, x2: arrow1X, y2: arrow1Y, ...commonProps }),
11671
+ /* @__PURE__ */ jsx33("line", { x1: endX, y1: endY, x2: arrow2X, y2: arrow2Y, ...commonProps })
11010
11672
  ] });
11011
11673
  default:
11012
11674
  return null;
11013
11675
  }
11014
11676
  }, [shapeType, scaledX, scaledY, scaledWidth, scaledHeight, color, scaledStroke, isSelected]);
11015
- return /* @__PURE__ */ jsxs26(
11677
+ return /* @__PURE__ */ jsxs28(
11016
11678
  "g",
11017
11679
  {
11018
11680
  className: cn("shape-renderer", className),
11019
11681
  onMouseDown: (e) => handleMouseDown(e),
11020
11682
  children: [
11021
- /* @__PURE__ */ jsx31(
11683
+ /* @__PURE__ */ jsx33(
11022
11684
  "rect",
11023
11685
  {
11024
11686
  x: scaledX - 5,
@@ -11031,7 +11693,7 @@ var ShapeRenderer = memo30(function ShapeRenderer2({
11031
11693
  }
11032
11694
  ),
11033
11695
  renderShape2(),
11034
- isSelected && /* @__PURE__ */ jsx31(
11696
+ isSelected && /* @__PURE__ */ jsx33(
11035
11697
  "rect",
11036
11698
  {
11037
11699
  x: scaledX - 2,
@@ -11044,7 +11706,7 @@ var ShapeRenderer = memo30(function ShapeRenderer2({
11044
11706
  strokeDasharray: "4 2"
11045
11707
  }
11046
11708
  ),
11047
- isSelected && isEditing && getResizeHandles().map((handle) => /* @__PURE__ */ jsx31(
11709
+ isSelected && isEditing && getResizeHandles().map((handle) => /* @__PURE__ */ jsx33(
11048
11710
  "rect",
11049
11711
  {
11050
11712
  x: handle.x,
@@ -11064,7 +11726,7 @@ var ShapeRenderer = memo30(function ShapeRenderer2({
11064
11726
  }
11065
11727
  );
11066
11728
  });
11067
- var ShapePreview = memo30(function ShapePreview2({
11729
+ var ShapePreview = memo32(function ShapePreview2({
11068
11730
  shapeType,
11069
11731
  startPoint,
11070
11732
  endPoint,
@@ -11085,9 +11747,9 @@ var ShapePreview = memo30(function ShapePreview2({
11085
11747
  };
11086
11748
  switch (shapeType) {
11087
11749
  case "rect":
11088
- return /* @__PURE__ */ jsx31("rect", { x, y, width, height, ...commonProps });
11750
+ return /* @__PURE__ */ jsx33("rect", { x, y, width, height, ...commonProps });
11089
11751
  case "circle":
11090
- return /* @__PURE__ */ jsx31(
11752
+ return /* @__PURE__ */ jsx33(
11091
11753
  "ellipse",
11092
11754
  {
11093
11755
  cx: x + width / 2,
@@ -11098,7 +11760,7 @@ var ShapePreview = memo30(function ShapePreview2({
11098
11760
  }
11099
11761
  );
11100
11762
  case "line":
11101
- return /* @__PURE__ */ jsx31(
11763
+ return /* @__PURE__ */ jsx33(
11102
11764
  "line",
11103
11765
  {
11104
11766
  x1: startPoint.x * scale,
@@ -11120,8 +11782,8 @@ var ShapePreview = memo30(function ShapePreview2({
11120
11782
  const arrow1Y = endY - arrowLength * Math.sin(angle - arrowAngle);
11121
11783
  const arrow2X = endX - arrowLength * Math.cos(angle + arrowAngle);
11122
11784
  const arrow2Y = endY - arrowLength * Math.sin(angle + arrowAngle);
11123
- return /* @__PURE__ */ jsxs26("g", { children: [
11124
- /* @__PURE__ */ jsx31(
11785
+ return /* @__PURE__ */ jsxs28("g", { children: [
11786
+ /* @__PURE__ */ jsx33(
11125
11787
  "line",
11126
11788
  {
11127
11789
  x1: startPoint.x * scale,
@@ -11131,8 +11793,8 @@ var ShapePreview = memo30(function ShapePreview2({
11131
11793
  ...commonProps
11132
11794
  }
11133
11795
  ),
11134
- /* @__PURE__ */ jsx31("line", { x1: endX, y1: endY, x2: arrow1X, y2: arrow1Y, ...commonProps }),
11135
- /* @__PURE__ */ jsx31("line", { x1: endX, y1: endY, x2: arrow2X, y2: arrow2Y, ...commonProps })
11796
+ /* @__PURE__ */ jsx33("line", { x1: endX, y1: endY, x2: arrow1X, y2: arrow1Y, ...commonProps }),
11797
+ /* @__PURE__ */ jsx33("line", { x1: endX, y1: endY, x2: arrow2X, y2: arrow2Y, ...commonProps })
11136
11798
  ] });
11137
11799
  default:
11138
11800
  return null;
@@ -11141,9 +11803,9 @@ var ShapePreview = memo30(function ShapePreview2({
11141
11803
 
11142
11804
  // src/components/Annotations/QuickNoteButton.tsx
11143
11805
  init_utils();
11144
- import { memo as memo31, useCallback as useCallback37, useState as useState25 } from "react";
11145
- import { jsx as jsx32 } from "react/jsx-runtime";
11146
- var QuickNoteButton = memo31(function QuickNoteButton2({
11806
+ import { memo as memo33, useCallback as useCallback38, useState as useState26 } from "react";
11807
+ import { jsx as jsx34 } from "react/jsx-runtime";
11808
+ var QuickNoteButton = memo33(function QuickNoteButton2({
11147
11809
  pageNumber,
11148
11810
  scale,
11149
11811
  position = "top-right",
@@ -11151,8 +11813,8 @@ var QuickNoteButton = memo31(function QuickNoteButton2({
11151
11813
  className,
11152
11814
  visible = true
11153
11815
  }) {
11154
- const [isHovered, setIsHovered] = useState25(false);
11155
- const handleClick = useCallback37(
11816
+ const [isHovered, setIsHovered] = useState26(false);
11817
+ const handleClick = useCallback38(
11156
11818
  (e) => {
11157
11819
  e.stopPropagation();
11158
11820
  const x = position === "top-right" ? 80 : 80;
@@ -11164,7 +11826,7 @@ var QuickNoteButton = memo31(function QuickNoteButton2({
11164
11826
  if (!visible) {
11165
11827
  return null;
11166
11828
  }
11167
- return /* @__PURE__ */ jsx32(
11829
+ return /* @__PURE__ */ jsx34(
11168
11830
  "button",
11169
11831
  {
11170
11832
  onClick: handleClick,
@@ -11186,7 +11848,7 @@ var QuickNoteButton = memo31(function QuickNoteButton2({
11186
11848
  ),
11187
11849
  title: "Add quick note",
11188
11850
  "aria-label": "Add quick note",
11189
- children: /* @__PURE__ */ jsx32(
11851
+ children: /* @__PURE__ */ jsx34(
11190
11852
  "svg",
11191
11853
  {
11192
11854
  className: "w-4 h-4 text-yellow-900",
@@ -11194,7 +11856,7 @@ var QuickNoteButton = memo31(function QuickNoteButton2({
11194
11856
  viewBox: "0 0 24 24",
11195
11857
  stroke: "currentColor",
11196
11858
  strokeWidth: 2,
11197
- children: /* @__PURE__ */ jsx32("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M12 4v16m8-8H4" })
11859
+ children: /* @__PURE__ */ jsx34("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M12 4v16m8-8H4" })
11198
11860
  }
11199
11861
  )
11200
11862
  }
@@ -11203,9 +11865,9 @@ var QuickNoteButton = memo31(function QuickNoteButton2({
11203
11865
 
11204
11866
  // src/components/Annotations/QuickNotePopover.tsx
11205
11867
  init_utils();
11206
- import { memo as memo32, useCallback as useCallback38, useState as useState26, useRef as useRef23, useEffect as useEffect24 } from "react";
11207
- import { jsx as jsx33, jsxs as jsxs27 } from "react/jsx-runtime";
11208
- var QuickNotePopover = memo32(function QuickNotePopover2({
11868
+ import { memo as memo34, useCallback as useCallback39, useState as useState27, useRef as useRef24, useEffect as useEffect25 } from "react";
11869
+ import { jsx as jsx35, jsxs as jsxs29 } from "react/jsx-runtime";
11870
+ var QuickNotePopover = memo34(function QuickNotePopover2({
11209
11871
  visible,
11210
11872
  position,
11211
11873
  initialContent = "",
@@ -11214,21 +11876,21 @@ var QuickNotePopover = memo32(function QuickNotePopover2({
11214
11876
  onCancel,
11215
11877
  className
11216
11878
  }) {
11217
- const [content, setContent] = useState26(initialContent);
11218
- const textareaRef = useRef23(null);
11219
- const popoverRef = useRef23(null);
11220
- const [adjustedPosition, setAdjustedPosition] = useState26(position);
11221
- useEffect24(() => {
11879
+ const [content, setContent] = useState27(initialContent);
11880
+ const textareaRef = useRef24(null);
11881
+ const popoverRef = useRef24(null);
11882
+ const [adjustedPosition, setAdjustedPosition] = useState27(position);
11883
+ useEffect25(() => {
11222
11884
  if (visible && textareaRef.current) {
11223
11885
  textareaRef.current.focus();
11224
11886
  }
11225
11887
  }, [visible]);
11226
- useEffect24(() => {
11888
+ useEffect25(() => {
11227
11889
  if (visible) {
11228
11890
  setContent(initialContent);
11229
11891
  }
11230
11892
  }, [visible, initialContent]);
11231
- useEffect24(() => {
11893
+ useEffect25(() => {
11232
11894
  if (!visible || !popoverRef.current) return;
11233
11895
  const rect = popoverRef.current.getBoundingClientRect();
11234
11896
  const padding = 10;
@@ -11247,14 +11909,14 @@ var QuickNotePopover = memo32(function QuickNotePopover2({
11247
11909
  }
11248
11910
  setAdjustedPosition({ x, y });
11249
11911
  }, [position, visible]);
11250
- const handleSave = useCallback38(() => {
11912
+ const handleSave = useCallback39(() => {
11251
11913
  if (content.trim()) {
11252
11914
  onSave(content.trim());
11253
11915
  } else {
11254
11916
  onCancel();
11255
11917
  }
11256
11918
  }, [content, onSave, onCancel]);
11257
- const handleKeyDown = useCallback38(
11919
+ const handleKeyDown = useCallback39(
11258
11920
  (e) => {
11259
11921
  if (e.key === "Enter" && (e.ctrlKey || e.metaKey)) {
11260
11922
  e.preventDefault();
@@ -11269,7 +11931,7 @@ var QuickNotePopover = memo32(function QuickNotePopover2({
11269
11931
  if (!visible) {
11270
11932
  return null;
11271
11933
  }
11272
- return /* @__PURE__ */ jsxs27(
11934
+ return /* @__PURE__ */ jsxs29(
11273
11935
  "div",
11274
11936
  {
11275
11937
  ref: popoverRef,
@@ -11288,15 +11950,15 @@ var QuickNotePopover = memo32(function QuickNotePopover2({
11288
11950
  top: adjustedPosition.y
11289
11951
  },
11290
11952
  children: [
11291
- agentLastStatement && /* @__PURE__ */ jsx33("div", { className: "mb-2 p-2 bg-blue-50 dark:bg-blue-900/50 rounded text-xs text-blue-600 dark:text-blue-300 border border-blue-100 dark:border-blue-800", children: /* @__PURE__ */ jsxs27("div", { className: "flex items-start gap-1", children: [
11292
- /* @__PURE__ */ jsx33("svg", { className: "w-3 h-3 mt-0.5 flex-shrink-0", fill: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx33("path", { d: "M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z" }) }),
11293
- /* @__PURE__ */ jsxs27("span", { className: "line-clamp-2", children: [
11953
+ agentLastStatement && /* @__PURE__ */ jsx35("div", { className: "mb-2 p-2 bg-blue-50 dark:bg-blue-900/50 rounded text-xs text-blue-600 dark:text-blue-300 border border-blue-100 dark:border-blue-800", children: /* @__PURE__ */ jsxs29("div", { className: "flex items-start gap-1", children: [
11954
+ /* @__PURE__ */ jsx35("svg", { className: "w-3 h-3 mt-0.5 flex-shrink-0", fill: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx35("path", { d: "M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z" }) }),
11955
+ /* @__PURE__ */ jsxs29("span", { className: "line-clamp-2", children: [
11294
11956
  "AI discussed: \u201C",
11295
11957
  agentLastStatement,
11296
11958
  "\u201D"
11297
11959
  ] })
11298
11960
  ] }) }),
11299
- /* @__PURE__ */ jsx33(
11961
+ /* @__PURE__ */ jsx35(
11300
11962
  "textarea",
11301
11963
  {
11302
11964
  ref: textareaRef,
@@ -11315,13 +11977,13 @@ var QuickNotePopover = memo32(function QuickNotePopover2({
11315
11977
  )
11316
11978
  }
11317
11979
  ),
11318
- /* @__PURE__ */ jsxs27("div", { className: "flex items-center justify-between mt-2", children: [
11319
- /* @__PURE__ */ jsxs27("span", { className: "text-xs text-gray-500 dark:text-gray-400", children: [
11980
+ /* @__PURE__ */ jsxs29("div", { className: "flex items-center justify-between mt-2", children: [
11981
+ /* @__PURE__ */ jsxs29("span", { className: "text-xs text-gray-500 dark:text-gray-400", children: [
11320
11982
  navigator.platform.includes("Mac") ? "\u2318" : "Ctrl",
11321
11983
  "+Enter to save"
11322
11984
  ] }),
11323
- /* @__PURE__ */ jsxs27("div", { className: "flex gap-2", children: [
11324
- /* @__PURE__ */ jsx33(
11985
+ /* @__PURE__ */ jsxs29("div", { className: "flex gap-2", children: [
11986
+ /* @__PURE__ */ jsx35(
11325
11987
  "button",
11326
11988
  {
11327
11989
  onClick: onCancel,
@@ -11334,7 +11996,7 @@ var QuickNotePopover = memo32(function QuickNotePopover2({
11334
11996
  children: "Cancel"
11335
11997
  }
11336
11998
  ),
11337
- /* @__PURE__ */ jsx33(
11999
+ /* @__PURE__ */ jsx35(
11338
12000
  "button",
11339
12001
  {
11340
12002
  onClick: handleSave,
@@ -11358,9 +12020,9 @@ var QuickNotePopover = memo32(function QuickNotePopover2({
11358
12020
 
11359
12021
  // src/components/AskAbout/AskAboutOverlay.tsx
11360
12022
  init_utils();
11361
- import { memo as memo33 } from "react";
11362
- import { jsx as jsx34, jsxs as jsxs28 } from "react/jsx-runtime";
11363
- var AskAboutOverlay = memo33(function AskAboutOverlay2({
12023
+ import { memo as memo35 } from "react";
12024
+ import { jsx as jsx36, jsxs as jsxs30 } from "react/jsx-runtime";
12025
+ var AskAboutOverlay = memo35(function AskAboutOverlay2({
11364
12026
  visible,
11365
12027
  progress,
11366
12028
  position,
@@ -11374,7 +12036,7 @@ var AskAboutOverlay = memo33(function AskAboutOverlay2({
11374
12036
  const radius = (size - strokeWidth) / 2;
11375
12037
  const circumference = 2 * Math.PI * radius;
11376
12038
  const strokeDashoffset = circumference * (1 - progress);
11377
- return /* @__PURE__ */ jsxs28(
12039
+ return /* @__PURE__ */ jsxs30(
11378
12040
  "div",
11379
12041
  {
11380
12042
  className: cn(
@@ -11387,7 +12049,7 @@ var AskAboutOverlay = memo33(function AskAboutOverlay2({
11387
12049
  top: position.y - size / 2
11388
12050
  },
11389
12051
  children: [
11390
- /* @__PURE__ */ jsxs28(
12052
+ /* @__PURE__ */ jsxs30(
11391
12053
  "svg",
11392
12054
  {
11393
12055
  width: size,
@@ -11395,7 +12057,7 @@ var AskAboutOverlay = memo33(function AskAboutOverlay2({
11395
12057
  viewBox: `0 0 ${size} ${size}`,
11396
12058
  className: "transform -rotate-90",
11397
12059
  children: [
11398
- /* @__PURE__ */ jsx34(
12060
+ /* @__PURE__ */ jsx36(
11399
12061
  "circle",
11400
12062
  {
11401
12063
  cx: size / 2,
@@ -11406,7 +12068,7 @@ var AskAboutOverlay = memo33(function AskAboutOverlay2({
11406
12068
  strokeWidth
11407
12069
  }
11408
12070
  ),
11409
- /* @__PURE__ */ jsx34(
12071
+ /* @__PURE__ */ jsx36(
11410
12072
  "circle",
11411
12073
  {
11412
12074
  cx: size / 2,
@@ -11424,12 +12086,12 @@ var AskAboutOverlay = memo33(function AskAboutOverlay2({
11424
12086
  ]
11425
12087
  }
11426
12088
  ),
11427
- /* @__PURE__ */ jsx34(
12089
+ /* @__PURE__ */ jsx36(
11428
12090
  "div",
11429
12091
  {
11430
12092
  className: "absolute inset-0 flex items-center justify-center",
11431
12093
  style: { color: progress >= 1 ? "#22c55e" : "white" },
11432
- children: progress >= 1 ? /* @__PURE__ */ jsx34(
12094
+ children: progress >= 1 ? /* @__PURE__ */ jsx36(
11433
12095
  "svg",
11434
12096
  {
11435
12097
  width: "24",
@@ -11440,9 +12102,9 @@ var AskAboutOverlay = memo33(function AskAboutOverlay2({
11440
12102
  strokeWidth: "2",
11441
12103
  strokeLinecap: "round",
11442
12104
  strokeLinejoin: "round",
11443
- children: /* @__PURE__ */ jsx34("polyline", { points: "20 6 9 17 4 12" })
12105
+ children: /* @__PURE__ */ jsx36("polyline", { points: "20 6 9 17 4 12" })
11444
12106
  }
11445
- ) : /* @__PURE__ */ jsxs28(
12107
+ ) : /* @__PURE__ */ jsxs30(
11446
12108
  "svg",
11447
12109
  {
11448
12110
  width: "20",
@@ -11454,9 +12116,9 @@ var AskAboutOverlay = memo33(function AskAboutOverlay2({
11454
12116
  strokeLinecap: "round",
11455
12117
  strokeLinejoin: "round",
11456
12118
  children: [
11457
- /* @__PURE__ */ jsx34("circle", { cx: "12", cy: "12", r: "10" }),
11458
- /* @__PURE__ */ jsx34("path", { d: "M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3" }),
11459
- /* @__PURE__ */ jsx34("line", { x1: "12", y1: "17", x2: "12.01", y2: "17" })
12119
+ /* @__PURE__ */ jsx36("circle", { cx: "12", cy: "12", r: "10" }),
12120
+ /* @__PURE__ */ jsx36("path", { d: "M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3" }),
12121
+ /* @__PURE__ */ jsx36("line", { x1: "12", y1: "17", x2: "12.01", y2: "17" })
11460
12122
  ]
11461
12123
  }
11462
12124
  )
@@ -11469,9 +12131,9 @@ var AskAboutOverlay = memo33(function AskAboutOverlay2({
11469
12131
 
11470
12132
  // src/components/AskAbout/AskAboutTrigger.tsx
11471
12133
  init_utils();
11472
- import { memo as memo34, useCallback as useCallback39, useState as useState27, useRef as useRef24, useEffect as useEffect25 } from "react";
11473
- import { jsx as jsx35, jsxs as jsxs29 } from "react/jsx-runtime";
11474
- var AskAboutTrigger = memo34(function AskAboutTrigger2({
12134
+ import { memo as memo36, useCallback as useCallback40, useState as useState28, useRef as useRef25, useEffect as useEffect26 } from "react";
12135
+ import { jsx as jsx37, jsxs as jsxs31 } from "react/jsx-runtime";
12136
+ var AskAboutTrigger = memo36(function AskAboutTrigger2({
11475
12137
  position,
11476
12138
  onConfirm,
11477
12139
  onCancel,
@@ -11479,9 +12141,9 @@ var AskAboutTrigger = memo34(function AskAboutTrigger2({
11479
12141
  autoHideDelay = 5e3,
11480
12142
  className
11481
12143
  }) {
11482
- const [adjustedPosition, setAdjustedPosition] = useState27(position);
11483
- const triggerRef = useRef24(null);
11484
- useEffect25(() => {
12144
+ const [adjustedPosition, setAdjustedPosition] = useState28(position);
12145
+ const triggerRef = useRef25(null);
12146
+ useEffect26(() => {
11485
12147
  if (!visible || !triggerRef.current) return;
11486
12148
  const rect = triggerRef.current.getBoundingClientRect();
11487
12149
  const padding = 10;
@@ -11497,19 +12159,19 @@ var AskAboutTrigger = memo34(function AskAboutTrigger2({
11497
12159
  }
11498
12160
  setAdjustedPosition({ x, y });
11499
12161
  }, [position, visible]);
11500
- useEffect25(() => {
12162
+ useEffect26(() => {
11501
12163
  if (!visible || autoHideDelay === 0) return;
11502
12164
  const timer = setTimeout(onCancel, autoHideDelay);
11503
12165
  return () => clearTimeout(timer);
11504
12166
  }, [visible, autoHideDelay, onCancel]);
11505
- const handleConfirm = useCallback39(
12167
+ const handleConfirm = useCallback40(
11506
12168
  (e) => {
11507
12169
  e.stopPropagation();
11508
12170
  onConfirm();
11509
12171
  },
11510
12172
  [onConfirm]
11511
12173
  );
11512
- const handleCancel = useCallback39(
12174
+ const handleCancel = useCallback40(
11513
12175
  (e) => {
11514
12176
  e.stopPropagation();
11515
12177
  onCancel();
@@ -11519,7 +12181,7 @@ var AskAboutTrigger = memo34(function AskAboutTrigger2({
11519
12181
  if (!visible) {
11520
12182
  return null;
11521
12183
  }
11522
- return /* @__PURE__ */ jsxs29(
12184
+ return /* @__PURE__ */ jsxs31(
11523
12185
  "div",
11524
12186
  {
11525
12187
  ref: triggerRef,
@@ -11538,8 +12200,8 @@ var AskAboutTrigger = memo34(function AskAboutTrigger2({
11538
12200
  transform: "translate(-50%, 0)"
11539
12201
  },
11540
12202
  children: [
11541
- /* @__PURE__ */ jsx35("span", { className: "text-sm text-gray-600 dark:text-gray-300 px-2", children: "Ask about this?" }),
11542
- /* @__PURE__ */ jsx35(
12203
+ /* @__PURE__ */ jsx37("span", { className: "text-sm text-gray-600 dark:text-gray-300 px-2", children: "Ask about this?" }),
12204
+ /* @__PURE__ */ jsx37(
11543
12205
  "button",
11544
12206
  {
11545
12207
  onClick: handleConfirm,
@@ -11552,7 +12214,7 @@ var AskAboutTrigger = memo34(function AskAboutTrigger2({
11552
12214
  children: "Ask"
11553
12215
  }
11554
12216
  ),
11555
- /* @__PURE__ */ jsx35(
12217
+ /* @__PURE__ */ jsx37(
11556
12218
  "button",
11557
12219
  {
11558
12220
  onClick: handleCancel,
@@ -11574,9 +12236,9 @@ var AskAboutTrigger = memo34(function AskAboutTrigger2({
11574
12236
  // src/components/Minimap/Minimap.tsx
11575
12237
  init_hooks();
11576
12238
  init_utils();
11577
- import { memo as memo35, useMemo as useMemo14, useCallback as useCallback40 } from "react";
11578
- import { Fragment as Fragment3, jsx as jsx36, jsxs as jsxs30 } from "react/jsx-runtime";
11579
- var PageIndicator = memo35(function PageIndicator2({
12239
+ import { memo as memo37, useMemo as useMemo14, useCallback as useCallback41 } from "react";
12240
+ import { Fragment as Fragment3, jsx as jsx38, jsxs as jsxs32 } from "react/jsx-runtime";
12241
+ var PageIndicator = memo37(function PageIndicator2({
11580
12242
  pageNumber,
11581
12243
  status,
11582
12244
  isBookmarked,
@@ -11590,7 +12252,7 @@ var PageIndicator = memo35(function PageIndicator2({
11590
12252
  if (status === "visited") return "bg-green-400";
11591
12253
  return "bg-gray-200 dark:bg-gray-700";
11592
12254
  };
11593
- return /* @__PURE__ */ jsxs30(
12255
+ return /* @__PURE__ */ jsxs32(
11594
12256
  "button",
11595
12257
  {
11596
12258
  onClick,
@@ -11606,13 +12268,13 @@ var PageIndicator = memo35(function PageIndicator2({
11606
12268
  title: `Page ${pageNumber}${isBookmarked ? " (bookmarked)" : ""}`,
11607
12269
  "aria-label": `Go to page ${pageNumber}`,
11608
12270
  children: [
11609
- isBookmarked && !compact && /* @__PURE__ */ jsx36("div", { className: "absolute -top-1 -right-1 w-2 h-2 bg-yellow-500 rounded-full border border-white" }),
11610
- showNumber && !compact && /* @__PURE__ */ jsx36("span", { className: "absolute inset-0 flex items-center justify-center text-[8px] font-medium text-white", children: pageNumber })
12271
+ isBookmarked && !compact && /* @__PURE__ */ jsx38("div", { className: "absolute -top-1 -right-1 w-2 h-2 bg-yellow-500 rounded-full border border-white" }),
12272
+ showNumber && !compact && /* @__PURE__ */ jsx38("span", { className: "absolute inset-0 flex items-center justify-center text-[8px] font-medium text-white", children: pageNumber })
11611
12273
  ]
11612
12274
  }
11613
12275
  );
11614
12276
  });
11615
- var Minimap = memo35(function Minimap2({
12277
+ var Minimap = memo37(function Minimap2({
11616
12278
  variant = "sidebar",
11617
12279
  floatingPosition = "right",
11618
12280
  maxHeight = 300,
@@ -11629,14 +12291,14 @@ var Minimap = memo35(function Minimap2({
11629
12291
  return new Set(bookmarks.map((b) => b.pageNumber));
11630
12292
  }, [bookmarks]);
11631
12293
  const compact = numPages > 50;
11632
- const handlePageClick = useCallback40(
12294
+ const handlePageClick = useCallback41(
11633
12295
  (pageNumber) => {
11634
12296
  goToPage(pageNumber);
11635
12297
  onPageClick?.(pageNumber);
11636
12298
  },
11637
12299
  [goToPage, onPageClick]
11638
12300
  );
11639
- const getPageStatus = useCallback40(
12301
+ const getPageStatus = useCallback41(
11640
12302
  (pageNumber) => {
11641
12303
  if (pageNumber === currentPage) return "current";
11642
12304
  if (bookmarkedPages.has(pageNumber)) return "bookmarked";
@@ -11649,7 +12311,7 @@ var Minimap = memo35(function Minimap2({
11649
12311
  const pages = [];
11650
12312
  for (let i = 1; i <= numPages; i++) {
11651
12313
  pages.push(
11652
- /* @__PURE__ */ jsx36(
12314
+ /* @__PURE__ */ jsx38(
11653
12315
  PageIndicator,
11654
12316
  {
11655
12317
  pageNumber: i,
@@ -11670,16 +12332,16 @@ var Minimap = memo35(function Minimap2({
11670
12332
  if (numPages === 0) {
11671
12333
  return null;
11672
12334
  }
11673
- const content = /* @__PURE__ */ jsxs30(Fragment3, { children: [
11674
- /* @__PURE__ */ jsxs30("div", { className: "mb-3", children: [
11675
- /* @__PURE__ */ jsxs30("div", { className: "flex items-center justify-between text-xs text-gray-500 dark:text-gray-400 mb-1", children: [
11676
- /* @__PURE__ */ jsx36("span", { children: "Progress" }),
11677
- /* @__PURE__ */ jsxs30("span", { children: [
12335
+ const content = /* @__PURE__ */ jsxs32(Fragment3, { children: [
12336
+ /* @__PURE__ */ jsxs32("div", { className: "mb-3", children: [
12337
+ /* @__PURE__ */ jsxs32("div", { className: "flex items-center justify-between text-xs text-gray-500 dark:text-gray-400 mb-1", children: [
12338
+ /* @__PURE__ */ jsx38("span", { children: "Progress" }),
12339
+ /* @__PURE__ */ jsxs32("span", { children: [
11678
12340
  progressPercentage,
11679
12341
  "%"
11680
12342
  ] })
11681
12343
  ] }),
11682
- /* @__PURE__ */ jsx36("div", { className: "h-1.5 bg-gray-200 dark:bg-gray-700 rounded-full overflow-hidden", children: /* @__PURE__ */ jsx36(
12344
+ /* @__PURE__ */ jsx38("div", { className: "h-1.5 bg-gray-200 dark:bg-gray-700 rounded-full overflow-hidden", children: /* @__PURE__ */ jsx38(
11683
12345
  "div",
11684
12346
  {
11685
12347
  className: "h-full bg-green-500 rounded-full transition-all duration-300",
@@ -11687,7 +12349,7 @@ var Minimap = memo35(function Minimap2({
11687
12349
  }
11688
12350
  ) })
11689
12351
  ] }),
11690
- /* @__PURE__ */ jsx36(
12352
+ /* @__PURE__ */ jsx38(
11691
12353
  "div",
11692
12354
  {
11693
12355
  className: cn(
@@ -11698,21 +12360,21 @@ var Minimap = memo35(function Minimap2({
11698
12360
  children: pageIndicators
11699
12361
  }
11700
12362
  ),
11701
- /* @__PURE__ */ jsx36("div", { className: "mt-3 pt-2 border-t border-gray-200 dark:border-gray-700", children: /* @__PURE__ */ jsxs30("div", { className: "flex flex-wrap gap-3 text-xs text-gray-500 dark:text-gray-400", children: [
11702
- /* @__PURE__ */ jsxs30("div", { className: "flex items-center gap-1", children: [
11703
- /* @__PURE__ */ jsx36("div", { className: "w-2 h-2 rounded-sm bg-blue-500" }),
11704
- /* @__PURE__ */ jsx36("span", { children: "Current" })
12363
+ /* @__PURE__ */ jsx38("div", { className: "mt-3 pt-2 border-t border-gray-200 dark:border-gray-700", children: /* @__PURE__ */ jsxs32("div", { className: "flex flex-wrap gap-3 text-xs text-gray-500 dark:text-gray-400", children: [
12364
+ /* @__PURE__ */ jsxs32("div", { className: "flex items-center gap-1", children: [
12365
+ /* @__PURE__ */ jsx38("div", { className: "w-2 h-2 rounded-sm bg-blue-500" }),
12366
+ /* @__PURE__ */ jsx38("span", { children: "Current" })
11705
12367
  ] }),
11706
- /* @__PURE__ */ jsxs30("div", { className: "flex items-center gap-1", children: [
11707
- /* @__PURE__ */ jsx36("div", { className: "w-2 h-2 rounded-sm bg-green-400" }),
11708
- /* @__PURE__ */ jsx36("span", { children: "Visited" })
12368
+ /* @__PURE__ */ jsxs32("div", { className: "flex items-center gap-1", children: [
12369
+ /* @__PURE__ */ jsx38("div", { className: "w-2 h-2 rounded-sm bg-green-400" }),
12370
+ /* @__PURE__ */ jsx38("span", { children: "Visited" })
11709
12371
  ] }),
11710
- /* @__PURE__ */ jsxs30("div", { className: "flex items-center gap-1", children: [
11711
- /* @__PURE__ */ jsx36("div", { className: "w-2 h-2 rounded-sm bg-yellow-400" }),
11712
- /* @__PURE__ */ jsx36("span", { children: "Bookmarked" })
12372
+ /* @__PURE__ */ jsxs32("div", { className: "flex items-center gap-1", children: [
12373
+ /* @__PURE__ */ jsx38("div", { className: "w-2 h-2 rounded-sm bg-yellow-400" }),
12374
+ /* @__PURE__ */ jsx38("span", { children: "Bookmarked" })
11713
12375
  ] })
11714
12376
  ] }) }),
11715
- /* @__PURE__ */ jsxs30("div", { className: "mt-2 text-xs text-gray-500 dark:text-gray-400", children: [
12377
+ /* @__PURE__ */ jsxs32("div", { className: "mt-2 text-xs text-gray-500 dark:text-gray-400", children: [
11716
12378
  visitedCount,
11717
12379
  " of ",
11718
12380
  numPages,
@@ -11720,7 +12382,7 @@ var Minimap = memo35(function Minimap2({
11720
12382
  ] })
11721
12383
  ] });
11722
12384
  if (variant === "floating") {
11723
- return /* @__PURE__ */ jsxs30(
12385
+ return /* @__PURE__ */ jsxs32(
11724
12386
  "div",
11725
12387
  {
11726
12388
  className: cn(
@@ -11736,13 +12398,13 @@ var Minimap = memo35(function Minimap2({
11736
12398
  ),
11737
12399
  style: { maxHeight },
11738
12400
  children: [
11739
- /* @__PURE__ */ jsx36("h3", { className: "text-sm font-semibold text-gray-700 dark:text-gray-200 mb-2", children: "Reading Progress" }),
12401
+ /* @__PURE__ */ jsx38("h3", { className: "text-sm font-semibold text-gray-700 dark:text-gray-200 mb-2", children: "Reading Progress" }),
11740
12402
  content
11741
12403
  ]
11742
12404
  }
11743
12405
  );
11744
12406
  }
11745
- return /* @__PURE__ */ jsx36(
12407
+ return /* @__PURE__ */ jsx38(
11746
12408
  "div",
11747
12409
  {
11748
12410
  className: cn(
@@ -11762,11 +12424,11 @@ init_FloatingZoomControls2();
11762
12424
  // src/components/PDFThumbnailNav/PDFThumbnailNav.tsx
11763
12425
  init_hooks();
11764
12426
  init_utils();
11765
- import { memo as memo36, useEffect as useEffect26, useState as useState28, useRef as useRef25, useCallback as useCallback41 } from "react";
11766
- import { jsx as jsx37, jsxs as jsxs31 } from "react/jsx-runtime";
12427
+ import { memo as memo38, useEffect as useEffect27, useState as useState29, useRef as useRef26, useCallback as useCallback42 } from "react";
12428
+ import { jsx as jsx39, jsxs as jsxs33 } from "react/jsx-runtime";
11767
12429
  var DEFAULT_WIDTH = 612;
11768
12430
  var DEFAULT_HEIGHT = 792;
11769
- var PDFThumbnailNav = memo36(function PDFThumbnailNav2({
12431
+ var PDFThumbnailNav = memo38(function PDFThumbnailNav2({
11770
12432
  thumbnailScale = 0.15,
11771
12433
  orientation = "vertical",
11772
12434
  maxVisible = 10,
@@ -11777,14 +12439,14 @@ var PDFThumbnailNav = memo36(function PDFThumbnailNav2({
11777
12439
  }) {
11778
12440
  const { document: document2, numPages, currentPage } = usePDFViewer();
11779
12441
  const { viewerStore } = usePDFViewerStores();
11780
- const containerRef = useRef25(null);
11781
- const [thumbnails, setThumbnails] = useState28(/* @__PURE__ */ new Map());
11782
- const [visibleRange, setVisibleRange] = useState28({ start: 1, end: maxVisible });
11783
- const renderQueueRef = useRef25(/* @__PURE__ */ new Set());
11784
- const pageCache = useRef25(/* @__PURE__ */ new Map());
12442
+ const containerRef = useRef26(null);
12443
+ const [thumbnails, setThumbnails] = useState29(/* @__PURE__ */ new Map());
12444
+ const [visibleRange, setVisibleRange] = useState29({ start: 1, end: maxVisible });
12445
+ const renderQueueRef = useRef26(/* @__PURE__ */ new Set());
12446
+ const pageCache = useRef26(/* @__PURE__ */ new Map());
11785
12447
  const thumbnailWidth = Math.floor(DEFAULT_WIDTH * thumbnailScale);
11786
12448
  const thumbnailHeight = Math.floor(DEFAULT_HEIGHT * thumbnailScale);
11787
- const updateVisibleRange = useCallback41(() => {
12449
+ const updateVisibleRange = useCallback42(() => {
11788
12450
  if (!containerRef.current || numPages === 0) return;
11789
12451
  const container = containerRef.current;
11790
12452
  const isHorizontal2 = orientation === "horizontal";
@@ -11796,7 +12458,7 @@ var PDFThumbnailNav = memo36(function PDFThumbnailNav2({
11796
12458
  const lastVisible = Math.min(numPages, firstVisible + visibleCount);
11797
12459
  setVisibleRange({ start: firstVisible, end: lastVisible });
11798
12460
  }, [numPages, orientation, thumbnailWidth, thumbnailHeight, gap]);
11799
- useEffect26(() => {
12461
+ useEffect27(() => {
11800
12462
  const container = containerRef.current;
11801
12463
  if (!container) return;
11802
12464
  const handleScroll = () => {
@@ -11806,7 +12468,7 @@ var PDFThumbnailNav = memo36(function PDFThumbnailNav2({
11806
12468
  updateVisibleRange();
11807
12469
  return () => container.removeEventListener("scroll", handleScroll);
11808
12470
  }, [updateVisibleRange]);
11809
- useEffect26(() => {
12471
+ useEffect27(() => {
11810
12472
  if (!document2) {
11811
12473
  setThumbnails(/* @__PURE__ */ new Map());
11812
12474
  pageCache.current.clear();
@@ -11861,7 +12523,7 @@ var PDFThumbnailNav = memo36(function PDFThumbnailNav2({
11861
12523
  };
11862
12524
  renderThumbnails();
11863
12525
  }, [document2, visibleRange, thumbnailScale, thumbnails]);
11864
- useEffect26(() => {
12526
+ useEffect27(() => {
11865
12527
  if (!containerRef.current || numPages === 0) return;
11866
12528
  const container = containerRef.current;
11867
12529
  const isHorizontal2 = orientation === "horizontal";
@@ -11877,12 +12539,12 @@ var PDFThumbnailNav = memo36(function PDFThumbnailNav2({
11877
12539
  });
11878
12540
  }
11879
12541
  }, [currentPage, numPages, orientation, thumbnailWidth, thumbnailHeight, gap]);
11880
- const handleThumbnailClick = useCallback41((pageNum) => {
12542
+ const handleThumbnailClick = useCallback42((pageNum) => {
11881
12543
  onThumbnailClick?.(pageNum);
11882
12544
  viewerStore.getState().requestScrollToPage(pageNum, "smooth");
11883
12545
  }, [onThumbnailClick, viewerStore]);
11884
12546
  if (!document2 || numPages === 0) {
11885
- return /* @__PURE__ */ jsx37(
12547
+ return /* @__PURE__ */ jsx39(
11886
12548
  "div",
11887
12549
  {
11888
12550
  className: cn(
@@ -11903,7 +12565,7 @@ var PDFThumbnailNav = memo36(function PDFThumbnailNav2({
11903
12565
  }
11904
12566
  const isHorizontal = orientation === "horizontal";
11905
12567
  const totalSize = numPages * ((isHorizontal ? thumbnailWidth : thumbnailHeight) + gap) - gap;
11906
- return /* @__PURE__ */ jsx37(
12568
+ return /* @__PURE__ */ jsx39(
11907
12569
  "div",
11908
12570
  {
11909
12571
  ref: containerRef,
@@ -11917,7 +12579,7 @@ var PDFThumbnailNav = memo36(function PDFThumbnailNav2({
11917
12579
  style: {
11918
12580
  ...isHorizontal ? { overflowX: "auto", overflowY: "hidden" } : { overflowX: "hidden", overflowY: "auto" }
11919
12581
  },
11920
- children: /* @__PURE__ */ jsx37(
12582
+ children: /* @__PURE__ */ jsx39(
11921
12583
  "div",
11922
12584
  {
11923
12585
  className: cn(
@@ -11934,7 +12596,7 @@ var PDFThumbnailNav = memo36(function PDFThumbnailNav2({
11934
12596
  const thumbnail = thumbnails.get(pageNum);
11935
12597
  const isActive = pageNum === currentPage;
11936
12598
  const isVisible = pageNum >= visibleRange.start && pageNum <= visibleRange.end;
11937
- return /* @__PURE__ */ jsxs31(
12599
+ return /* @__PURE__ */ jsxs33(
11938
12600
  "div",
11939
12601
  {
11940
12602
  className: cn(
@@ -11959,7 +12621,7 @@ var PDFThumbnailNav = memo36(function PDFThumbnailNav2({
11959
12621
  }
11960
12622
  },
11961
12623
  children: [
11962
- /* @__PURE__ */ jsx37(
12624
+ /* @__PURE__ */ jsx39(
11963
12625
  "div",
11964
12626
  {
11965
12627
  className: "relative bg-white dark:bg-gray-700",
@@ -11967,7 +12629,7 @@ var PDFThumbnailNav = memo36(function PDFThumbnailNav2({
11967
12629
  width: thumbnailWidth,
11968
12630
  height: thumbnailHeight
11969
12631
  },
11970
- children: isVisible && thumbnail?.canvas ? /* @__PURE__ */ jsx37(
12632
+ children: isVisible && thumbnail?.canvas ? /* @__PURE__ */ jsx39(
11971
12633
  "img",
11972
12634
  {
11973
12635
  src: thumbnail.canvas.toDataURL(),
@@ -11975,10 +12637,10 @@ var PDFThumbnailNav = memo36(function PDFThumbnailNav2({
11975
12637
  className: "w-full h-full object-contain",
11976
12638
  loading: "lazy"
11977
12639
  }
11978
- ) : /* @__PURE__ */ jsx37("div", { className: "absolute inset-0 flex items-center justify-center text-gray-400 dark:text-gray-500 text-xs", children: pageNum })
12640
+ ) : /* @__PURE__ */ jsx39("div", { className: "absolute inset-0 flex items-center justify-center text-gray-400 dark:text-gray-500 text-xs", children: pageNum })
11979
12641
  }
11980
12642
  ),
11981
- showPageNumbers && /* @__PURE__ */ jsx37(
12643
+ showPageNumbers && /* @__PURE__ */ jsx39(
11982
12644
  "div",
11983
12645
  {
11984
12646
  className: cn(
@@ -12003,7 +12665,7 @@ var PDFThumbnailNav = memo36(function PDFThumbnailNav2({
12003
12665
  // src/components/ErrorBoundary/PDFErrorBoundary.tsx
12004
12666
  init_utils();
12005
12667
  import { Component } from "react";
12006
- import { jsx as jsx38, jsxs as jsxs32 } from "react/jsx-runtime";
12668
+ import { jsx as jsx40, jsxs as jsxs34 } from "react/jsx-runtime";
12007
12669
  var PDFErrorBoundary = class extends Component {
12008
12670
  constructor(props) {
12009
12671
  super(props);
@@ -12031,7 +12693,7 @@ var PDFErrorBoundary = class extends Component {
12031
12693
  return fallback;
12032
12694
  }
12033
12695
  if (showDefaultUI) {
12034
- return /* @__PURE__ */ jsx38(
12696
+ return /* @__PURE__ */ jsx40(
12035
12697
  DefaultErrorUI,
12036
12698
  {
12037
12699
  error,
@@ -12050,7 +12712,7 @@ function DefaultErrorUI({ error, onReset, className }) {
12050
12712
  const isNetworkError = error.message.includes("fetch") || error.message.includes("network") || error.message.includes("Failed to load");
12051
12713
  let title = "Something went wrong";
12052
12714
  let description = error.message;
12053
- let icon = /* @__PURE__ */ jsx38("svg", { className: "w-12 h-12 text-red-500", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx38(
12715
+ let icon = /* @__PURE__ */ jsx40("svg", { className: "w-12 h-12 text-red-500", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx40(
12054
12716
  "path",
12055
12717
  {
12056
12718
  strokeLinecap: "round",
@@ -12062,7 +12724,7 @@ function DefaultErrorUI({ error, onReset, className }) {
12062
12724
  if (isPDFError) {
12063
12725
  title = "Unable to load PDF";
12064
12726
  description = "The PDF file could not be loaded. It may be corrupted or in an unsupported format.";
12065
- icon = /* @__PURE__ */ jsx38("svg", { className: "w-12 h-12 text-red-500", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx38(
12727
+ icon = /* @__PURE__ */ jsx40("svg", { className: "w-12 h-12 text-red-500", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx40(
12066
12728
  "path",
12067
12729
  {
12068
12730
  strokeLinecap: "round",
@@ -12074,7 +12736,7 @@ function DefaultErrorUI({ error, onReset, className }) {
12074
12736
  } else if (isNetworkError) {
12075
12737
  title = "Network error";
12076
12738
  description = "Unable to fetch the PDF file. Please check your internet connection and try again.";
12077
- icon = /* @__PURE__ */ jsx38("svg", { className: "w-12 h-12 text-red-500", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx38(
12739
+ icon = /* @__PURE__ */ jsx40("svg", { className: "w-12 h-12 text-red-500", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx40(
12078
12740
  "path",
12079
12741
  {
12080
12742
  strokeLinecap: "round",
@@ -12084,7 +12746,7 @@ function DefaultErrorUI({ error, onReset, className }) {
12084
12746
  }
12085
12747
  ) });
12086
12748
  }
12087
- return /* @__PURE__ */ jsxs32(
12749
+ return /* @__PURE__ */ jsxs34(
12088
12750
  "div",
12089
12751
  {
12090
12752
  className: cn(
@@ -12097,14 +12759,14 @@ function DefaultErrorUI({ error, onReset, className }) {
12097
12759
  ),
12098
12760
  children: [
12099
12761
  icon,
12100
- /* @__PURE__ */ jsx38("h2", { className: "mt-4 text-xl font-semibold text-gray-900 dark:text-gray-100", children: title }),
12101
- /* @__PURE__ */ jsx38("p", { className: "mt-2 text-sm text-gray-600 dark:text-gray-400 max-w-md", children: description }),
12102
- /* @__PURE__ */ jsxs32("details", { className: "mt-4 text-left max-w-md w-full", children: [
12103
- /* @__PURE__ */ jsx38("summary", { className: "cursor-pointer text-sm text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-200", children: "Technical details" }),
12104
- /* @__PURE__ */ jsx38("pre", { className: "mt-2 p-2 bg-gray-100 dark:bg-gray-800 rounded text-xs overflow-auto", children: error.stack || error.message })
12762
+ /* @__PURE__ */ jsx40("h2", { className: "mt-4 text-xl font-semibold text-gray-900 dark:text-gray-100", children: title }),
12763
+ /* @__PURE__ */ jsx40("p", { className: "mt-2 text-sm text-gray-600 dark:text-gray-400 max-w-md", children: description }),
12764
+ /* @__PURE__ */ jsxs34("details", { className: "mt-4 text-left max-w-md w-full", children: [
12765
+ /* @__PURE__ */ jsx40("summary", { className: "cursor-pointer text-sm text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-200", children: "Technical details" }),
12766
+ /* @__PURE__ */ jsx40("pre", { className: "mt-2 p-2 bg-gray-100 dark:bg-gray-800 rounded text-xs overflow-auto", children: error.stack || error.message })
12105
12767
  ] }),
12106
- /* @__PURE__ */ jsxs32("div", { className: "mt-6 flex gap-3", children: [
12107
- /* @__PURE__ */ jsx38(
12768
+ /* @__PURE__ */ jsxs34("div", { className: "mt-6 flex gap-3", children: [
12769
+ /* @__PURE__ */ jsx40(
12108
12770
  "button",
12109
12771
  {
12110
12772
  onClick: onReset,
@@ -12118,7 +12780,7 @@ function DefaultErrorUI({ error, onReset, className }) {
12118
12780
  children: "Try again"
12119
12781
  }
12120
12782
  ),
12121
- /* @__PURE__ */ jsx38(
12783
+ /* @__PURE__ */ jsx40(
12122
12784
  "button",
12123
12785
  {
12124
12786
  onClick: () => window.location.reload(),
@@ -12138,7 +12800,7 @@ function DefaultErrorUI({ error, onReset, className }) {
12138
12800
  );
12139
12801
  }
12140
12802
  function withErrorBoundary({ component, ...props }) {
12141
- return /* @__PURE__ */ jsx38(PDFErrorBoundary, { ...props, children: component });
12803
+ return /* @__PURE__ */ jsx40(PDFErrorBoundary, { ...props, children: component });
12142
12804
  }
12143
12805
 
12144
12806
  // src/components/index.ts
@@ -12158,6 +12820,7 @@ export {
12158
12820
  AnnotationToolbar,
12159
12821
  AskAboutOverlay,
12160
12822
  AskAboutTrigger,
12823
+ BookModeContainer,
12161
12824
  BookmarksPanel,
12162
12825
  CanvasLayer,
12163
12826
  ContinuousScrollContainer,
@@ -12236,6 +12899,7 @@ export {
12236
12899
  isPDFJSInitialized,
12237
12900
  isPointInRect,
12238
12901
  loadDocument,
12902
+ loadDocumentWithCallbacks,
12239
12903
  loadHighlights,
12240
12904
  loadStudentData,
12241
12905
  mergeAdjacentRects,
@@ -12244,6 +12908,7 @@ export {
12244
12908
  pdfjsLib,
12245
12909
  percentToPDF,
12246
12910
  percentToViewport,
12911
+ playPageTurnSound,
12247
12912
  quickViewer,
12248
12913
  removeRotation,
12249
12914
  saveHighlights,