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.cjs CHANGED
@@ -200,6 +200,122 @@ function clearDocumentCache(url) {
200
200
  documentCache.clear();
201
201
  }
202
202
  }
203
+ function loadDocumentWithCallbacks(options) {
204
+ const {
205
+ src,
206
+ workerSrc,
207
+ password,
208
+ onProgress,
209
+ onDocumentReady,
210
+ onFirstPageReady,
211
+ enableRangeRequests = true,
212
+ enableStreaming = true,
213
+ cacheDocument = true,
214
+ signal
215
+ } = options;
216
+ const abortController = new AbortController();
217
+ if (signal) {
218
+ signal.addEventListener("abort", () => abortController.abort());
219
+ }
220
+ const promise = (async () => {
221
+ if (abortController.signal.aborted) {
222
+ throw new DOMException("Aborted", "AbortError");
223
+ }
224
+ await initializePDFJS({ workerSrc });
225
+ if (abortController.signal.aborted) {
226
+ throw new DOMException("Aborted", "AbortError");
227
+ }
228
+ const cacheKey = typeof src === "string" ? src : null;
229
+ if (cacheKey && cacheDocument && documentCache.has(cacheKey)) {
230
+ const cachedDoc = documentCache.get(cacheKey);
231
+ try {
232
+ const numPages2 = cachedDoc.numPages;
233
+ const isDestroyed = cachedDoc._transport?.destroyed || cachedDoc.destroyed;
234
+ if (numPages2 > 0 && !isDestroyed) {
235
+ onDocumentReady?.(cachedDoc, numPages2);
236
+ if (onFirstPageReady && numPages2 > 0) {
237
+ try {
238
+ const firstPage = await cachedDoc.getPage(1);
239
+ if (!abortController.signal.aborted) {
240
+ onFirstPageReady(firstPage);
241
+ }
242
+ } catch {
243
+ }
244
+ }
245
+ return {
246
+ document: cachedDoc,
247
+ numPages: numPages2
248
+ };
249
+ }
250
+ documentCache.delete(cacheKey);
251
+ } catch {
252
+ documentCache.delete(cacheKey);
253
+ }
254
+ }
255
+ const loadingParams = {
256
+ password,
257
+ isEvalSupported: false,
258
+ useSystemFonts: true,
259
+ disableRange: !enableRangeRequests,
260
+ disableStream: !enableStreaming,
261
+ disableAutoFetch: true
262
+ };
263
+ if (typeof src === "string") {
264
+ loadingParams.url = src;
265
+ } else {
266
+ loadingParams.data = src;
267
+ }
268
+ const loadingTask = pdfjsLib.getDocument(loadingParams);
269
+ const abortHandler = () => {
270
+ loadingTask.destroy();
271
+ };
272
+ abortController.signal.addEventListener("abort", abortHandler);
273
+ if (onProgress) {
274
+ loadingTask.onProgress = ({ loaded, total }) => {
275
+ if (!abortController.signal.aborted) {
276
+ onProgress({ loaded, total });
277
+ }
278
+ };
279
+ }
280
+ let document2;
281
+ try {
282
+ document2 = await loadingTask.promise;
283
+ } catch (error) {
284
+ abortController.signal.removeEventListener("abort", abortHandler);
285
+ if (abortController.signal.aborted) {
286
+ throw new DOMException("Aborted", "AbortError");
287
+ }
288
+ throw error;
289
+ }
290
+ abortController.signal.removeEventListener("abort", abortHandler);
291
+ if (abortController.signal.aborted) {
292
+ document2.destroy();
293
+ throw new DOMException("Aborted", "AbortError");
294
+ }
295
+ const numPages = document2.numPages;
296
+ onDocumentReady?.(document2, numPages);
297
+ if (onFirstPageReady && numPages > 0) {
298
+ try {
299
+ const firstPage = await document2.getPage(1);
300
+ if (!abortController.signal.aborted) {
301
+ onFirstPageReady(firstPage);
302
+ }
303
+ } catch {
304
+ }
305
+ }
306
+ if (cacheKey && cacheDocument) {
307
+ documentCache.set(cacheKey, document2);
308
+ }
309
+ return {
310
+ document: document2,
311
+ numPages
312
+ };
313
+ })();
314
+ return {
315
+ promise,
316
+ cancel: () => abortController.abort()
317
+ };
318
+ }
203
319
  var documentCache;
204
320
  var init_document_loader = __esm({
205
321
  "src/utils/document-loader.ts"() {
@@ -403,14 +519,18 @@ function createViewerStore(initialOverrides = {}) {
403
519
  isLoading: false,
404
520
  loadingProgress: null,
405
521
  error: null,
406
- currentPage: 1
522
+ currentPage: 1,
523
+ documentLoadingState: "ready"
407
524
  });
408
525
  } else {
409
526
  set({
410
527
  document: null,
411
528
  numPages: 0,
412
529
  isLoading: false,
413
- loadingProgress: null
530
+ loadingProgress: null,
531
+ documentLoadingState: "idle",
532
+ firstPageReady: false,
533
+ streamingProgress: null
414
534
  });
415
535
  }
416
536
  },
@@ -424,7 +544,17 @@ function createViewerStore(initialOverrides = {}) {
424
544
  set({ loadingProgress: progress });
425
545
  },
426
546
  setError: (error) => {
427
- set({ error, isLoading: false, loadingProgress: null });
547
+ set({ error, isLoading: false, loadingProgress: null, documentLoadingState: error ? "error" : "idle" });
548
+ },
549
+ // Progressive loading actions
550
+ setDocumentLoadingState: (documentLoadingState) => {
551
+ set({ documentLoadingState });
552
+ },
553
+ setFirstPageReady: (firstPageReady) => {
554
+ set({ firstPageReady });
555
+ },
556
+ setStreamingProgress: (streamingProgress) => {
557
+ set({ streamingProgress });
428
558
  },
429
559
  // Navigation actions
430
560
  setCurrentPage: (page) => {
@@ -574,6 +704,10 @@ var init_viewer_store = __esm({
574
704
  isLoading: false,
575
705
  loadingProgress: null,
576
706
  error: null,
707
+ // Progressive loading state
708
+ documentLoadingState: "idle",
709
+ firstPageReady: false,
710
+ streamingProgress: null,
577
711
  // Navigation state
578
712
  currentPage: 1,
579
713
  scale: 1,
@@ -1650,6 +1784,85 @@ var init_coordinates = __esm({
1650
1784
  }
1651
1785
  });
1652
1786
 
1787
+ // src/utils/page-turn-sound.ts
1788
+ function getAudioContext() {
1789
+ if (typeof window === "undefined") return null;
1790
+ if (!audioContext) {
1791
+ try {
1792
+ audioContext = new (window.AudioContext || window.webkitAudioContext)();
1793
+ } catch {
1794
+ return null;
1795
+ }
1796
+ }
1797
+ return audioContext;
1798
+ }
1799
+ function playPageTurnSound(volume = 0.3) {
1800
+ const ctx = getAudioContext();
1801
+ if (!ctx) return;
1802
+ if (ctx.state === "suspended") {
1803
+ ctx.resume();
1804
+ }
1805
+ const now = ctx.currentTime;
1806
+ const duration = 0.35;
1807
+ const bufferSize = Math.floor(ctx.sampleRate * duration);
1808
+ const noiseBuffer = ctx.createBuffer(1, bufferSize, ctx.sampleRate);
1809
+ const data = noiseBuffer.getChannelData(0);
1810
+ for (let i = 0; i < bufferSize; i++) {
1811
+ data[i] = Math.random() * 2 - 1;
1812
+ }
1813
+ const noiseSource = ctx.createBufferSource();
1814
+ noiseSource.buffer = noiseBuffer;
1815
+ const bandpass = ctx.createBiquadFilter();
1816
+ bandpass.type = "bandpass";
1817
+ bandpass.frequency.setValueAtTime(3e3, now);
1818
+ bandpass.frequency.exponentialRampToValueAtTime(800, now + duration * 0.6);
1819
+ bandpass.Q.setValueAtTime(0.8, now);
1820
+ const highpass = ctx.createBiquadFilter();
1821
+ highpass.type = "highpass";
1822
+ highpass.frequency.setValueAtTime(400, now);
1823
+ highpass.frequency.linearRampToValueAtTime(200, now + duration);
1824
+ const envelope = ctx.createGain();
1825
+ envelope.gain.setValueAtTime(0, now);
1826
+ envelope.gain.linearRampToValueAtTime(volume * 0.6, now + 0.02);
1827
+ envelope.gain.setValueAtTime(volume * 0.6, now + 0.05);
1828
+ envelope.gain.linearRampToValueAtTime(volume, now + duration * 0.3);
1829
+ envelope.gain.exponentialRampToValueAtTime(1e-3, now + duration);
1830
+ const snapBuffer = ctx.createBuffer(1, Math.floor(ctx.sampleRate * 0.08), ctx.sampleRate);
1831
+ const snapData = snapBuffer.getChannelData(0);
1832
+ for (let i = 0; i < snapData.length; i++) {
1833
+ snapData[i] = Math.random() * 2 - 1;
1834
+ }
1835
+ const snapSource = ctx.createBufferSource();
1836
+ snapSource.buffer = snapBuffer;
1837
+ const snapFilter = ctx.createBiquadFilter();
1838
+ snapFilter.type = "bandpass";
1839
+ snapFilter.frequency.setValueAtTime(2e3, now);
1840
+ snapFilter.Q.setValueAtTime(1.5, now);
1841
+ const snapEnvelope = ctx.createGain();
1842
+ snapEnvelope.gain.setValueAtTime(0, now);
1843
+ snapEnvelope.gain.setValueAtTime(0, now + duration * 0.7);
1844
+ snapEnvelope.gain.linearRampToValueAtTime(volume * 0.8, now + duration * 0.75);
1845
+ snapEnvelope.gain.exponentialRampToValueAtTime(1e-3, now + duration);
1846
+ noiseSource.connect(bandpass);
1847
+ bandpass.connect(highpass);
1848
+ highpass.connect(envelope);
1849
+ envelope.connect(ctx.destination);
1850
+ snapSource.connect(snapFilter);
1851
+ snapFilter.connect(snapEnvelope);
1852
+ snapEnvelope.connect(ctx.destination);
1853
+ noiseSource.start(now);
1854
+ noiseSource.stop(now + duration);
1855
+ snapSource.start(now);
1856
+ snapSource.stop(now + duration);
1857
+ }
1858
+ var audioContext;
1859
+ var init_page_turn_sound = __esm({
1860
+ "src/utils/page-turn-sound.ts"() {
1861
+ "use strict";
1862
+ audioContext = null;
1863
+ }
1864
+ });
1865
+
1653
1866
  // src/utils/index.ts
1654
1867
  var init_utils = __esm({
1655
1868
  "src/utils/index.ts"() {
@@ -1664,6 +1877,7 @@ var init_utils = __esm({
1664
1877
  init_agent_api();
1665
1878
  init_text_search();
1666
1879
  init_coordinates();
1880
+ init_page_turn_sound();
1667
1881
  }
1668
1882
  });
1669
1883
 
@@ -7808,10 +8022,57 @@ var init_PDFLoadingScreen = __esm({
7808
8022
  totalBytes,
7809
8023
  phase = "fetching",
7810
8024
  documentName,
7811
- className
8025
+ className,
8026
+ compact = false,
8027
+ showStreamingProgress = false
7812
8028
  }) {
7813
8029
  const hasProgress = progress !== void 0 && progress >= 0;
7814
8030
  const hasBytes = bytesLoaded !== void 0 && totalBytes !== void 0 && totalBytes > 0;
8031
+ if (compact || showStreamingProgress) {
8032
+ return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(
8033
+ "div",
8034
+ {
8035
+ className: cn(
8036
+ "pdf-loading-compact",
8037
+ "flex items-center gap-3 px-4 py-3 bg-gray-800 text-white rounded-lg shadow-lg",
8038
+ className
8039
+ ),
8040
+ role: "status",
8041
+ "aria-live": "polite",
8042
+ children: [
8043
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
8044
+ "div",
8045
+ {
8046
+ style: {
8047
+ width: 20,
8048
+ height: 20,
8049
+ border: "2px solid rgba(255,255,255,0.3)",
8050
+ borderTopColor: "#fff",
8051
+ borderRadius: "50%",
8052
+ animation: "spin 0.8s linear infinite"
8053
+ }
8054
+ }
8055
+ ),
8056
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "text-sm font-medium", children: phaseMessages[phase] }),
8057
+ hasProgress && /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("span", { className: "text-sm text-white/70", children: [
8058
+ Math.round(progress),
8059
+ "%"
8060
+ ] }),
8061
+ hasBytes && /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("span", { className: "text-xs text-white/50 font-mono", children: [
8062
+ formatBytes(bytesLoaded),
8063
+ " / ",
8064
+ formatBytes(totalBytes)
8065
+ ] }),
8066
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("style", { children: `
8067
+ @keyframes spin {
8068
+ 0% { transform: rotate(0deg); }
8069
+ 100% { transform: rotate(360deg); }
8070
+ }
8071
+ ` })
8072
+ ]
8073
+ }
8074
+ );
8075
+ }
7815
8076
  return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
7816
8077
  "div",
7817
8078
  {
@@ -8044,6 +8305,114 @@ var init_PDFLoadingScreen2 = __esm({
8044
8305
  }
8045
8306
  });
8046
8307
 
8308
+ // src/components/PDFViewer/PageSkeleton.tsx
8309
+ var import_react34, import_jsx_runtime20, PageSkeleton, DEFAULT_PAGE_WIDTH, DEFAULT_PAGE_HEIGHT;
8310
+ var init_PageSkeleton = __esm({
8311
+ "src/components/PDFViewer/PageSkeleton.tsx"() {
8312
+ "use strict";
8313
+ import_react34 = require("react");
8314
+ init_utils();
8315
+ import_jsx_runtime20 = require("react/jsx-runtime");
8316
+ PageSkeleton = (0, import_react34.memo)(function PageSkeleton2({
8317
+ pageNumber,
8318
+ width,
8319
+ height,
8320
+ className,
8321
+ isFirstPage = false
8322
+ }) {
8323
+ return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
8324
+ "div",
8325
+ {
8326
+ className: cn(
8327
+ "pdf-page-skeleton",
8328
+ "relative bg-white shadow-lg overflow-hidden",
8329
+ "flex items-center justify-center",
8330
+ className
8331
+ ),
8332
+ style: {
8333
+ width,
8334
+ height,
8335
+ minWidth: width,
8336
+ minHeight: height
8337
+ },
8338
+ "data-page-number": pageNumber,
8339
+ role: "img",
8340
+ "aria-label": `Loading page ${pageNumber}`,
8341
+ children: [
8342
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
8343
+ "div",
8344
+ {
8345
+ className: "absolute inset-0 pdf-skeleton-shimmer",
8346
+ style: {
8347
+ background: "linear-gradient(90deg, #f0f0f0 25%, #e8e8e8 50%, #f0f0f0 75%)",
8348
+ backgroundSize: "200% 100%",
8349
+ animation: "shimmer 1.5s infinite linear"
8350
+ }
8351
+ }
8352
+ ),
8353
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "absolute inset-0 p-6 flex flex-col", style: { opacity: 0.4 }, children: [
8354
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
8355
+ "div",
8356
+ {
8357
+ className: "rounded",
8358
+ style: {
8359
+ width: "60%",
8360
+ height: 12,
8361
+ background: "#e0e0e0",
8362
+ marginBottom: 16
8363
+ }
8364
+ }
8365
+ ),
8366
+ [...Array(Math.min(12, Math.floor(height / 40)))].map((_, i) => /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
8367
+ "div",
8368
+ {
8369
+ className: "rounded",
8370
+ style: {
8371
+ width: `${75 + Math.sin(i * 0.7) * 20}%`,
8372
+ height: 8,
8373
+ background: "#e0e0e0",
8374
+ marginBottom: 12
8375
+ }
8376
+ },
8377
+ i
8378
+ ))
8379
+ ] }),
8380
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "relative z-10 flex flex-col items-center gap-3 p-6 rounded-lg bg-white/90 shadow-sm", children: [
8381
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
8382
+ "div",
8383
+ {
8384
+ className: "pdf-skeleton-spinner",
8385
+ style: {
8386
+ width: 32,
8387
+ height: 32,
8388
+ border: "3px solid #e5e7eb",
8389
+ borderTopColor: "#3b82f6",
8390
+ borderRadius: "50%",
8391
+ animation: "spin 0.8s linear infinite"
8392
+ }
8393
+ }
8394
+ ),
8395
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { className: "text-sm text-gray-500 font-medium", children: isFirstPage ? "Loading document..." : `Loading page ${pageNumber}` })
8396
+ ] }),
8397
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("style", { children: `
8398
+ @keyframes shimmer {
8399
+ 0% { background-position: 200% 0; }
8400
+ 100% { background-position: -200% 0; }
8401
+ }
8402
+ @keyframes spin {
8403
+ 0% { transform: rotate(0deg); }
8404
+ 100% { transform: rotate(360deg); }
8405
+ }
8406
+ ` })
8407
+ ]
8408
+ }
8409
+ );
8410
+ });
8411
+ DEFAULT_PAGE_WIDTH = 612;
8412
+ DEFAULT_PAGE_HEIGHT = 792;
8413
+ }
8414
+ });
8415
+
8047
8416
  // src/components/SelectionToolbar/SelectionToolbar.tsx
8048
8417
  function calculatePosition(selection) {
8049
8418
  if (!selection || selection.rects.length === 0) {
@@ -8059,13 +8428,13 @@ function calculatePosition(selection) {
8059
8428
  const left = firstRect.left + firstRect.width / 2;
8060
8429
  return { top, left, visible: true };
8061
8430
  }
8062
- var import_react34, import_jsx_runtime20, HIGHLIGHT_COLOR_BUTTONS, SelectionToolbar;
8431
+ var import_react35, import_jsx_runtime21, HIGHLIGHT_COLOR_BUTTONS, SelectionToolbar;
8063
8432
  var init_SelectionToolbar = __esm({
8064
8433
  "src/components/SelectionToolbar/SelectionToolbar.tsx"() {
8065
8434
  "use strict";
8066
- import_react34 = require("react");
8435
+ import_react35 = require("react");
8067
8436
  init_utils();
8068
- import_jsx_runtime20 = require("react/jsx-runtime");
8437
+ import_jsx_runtime21 = require("react/jsx-runtime");
8069
8438
  HIGHLIGHT_COLOR_BUTTONS = [
8070
8439
  { color: "yellow", bg: "bg-yellow-300", hoverBg: "hover:bg-yellow-400", ringColor: "ring-yellow-400" },
8071
8440
  { color: "green", bg: "bg-green-300", hoverBg: "hover:bg-green-400", ringColor: "ring-green-400" },
@@ -8073,16 +8442,16 @@ var init_SelectionToolbar = __esm({
8073
8442
  { color: "pink", bg: "bg-pink-300", hoverBg: "hover:bg-pink-400", ringColor: "ring-pink-400" },
8074
8443
  { color: "orange", bg: "bg-orange-300", hoverBg: "hover:bg-orange-400", ringColor: "ring-orange-400" }
8075
8444
  ];
8076
- SelectionToolbar = (0, import_react34.memo)(function SelectionToolbar2({
8445
+ SelectionToolbar = (0, import_react35.memo)(function SelectionToolbar2({
8077
8446
  selection,
8078
8447
  onCreateHighlight,
8079
8448
  onCopy,
8080
8449
  activeColor = "yellow",
8081
8450
  className
8082
8451
  }) {
8083
- const [position, setPosition] = (0, import_react34.useState)({ top: 0, left: 0, visible: false });
8084
- const toolbarRef = (0, import_react34.useRef)(null);
8085
- (0, import_react34.useEffect)(() => {
8452
+ const [position, setPosition] = (0, import_react35.useState)({ top: 0, left: 0, visible: false });
8453
+ const toolbarRef = (0, import_react35.useRef)(null);
8454
+ (0, import_react35.useEffect)(() => {
8086
8455
  if (selection && selection.text && selection.rects.length > 0) {
8087
8456
  const newPosition = calculatePosition(selection);
8088
8457
  if (toolbarRef.current && newPosition.visible) {
@@ -8110,19 +8479,19 @@ var init_SelectionToolbar = __esm({
8110
8479
  setPosition({ top: 0, left: 0, visible: false });
8111
8480
  }
8112
8481
  }, [selection]);
8113
- const handleColorClick = (0, import_react34.useCallback)(
8482
+ const handleColorClick = (0, import_react35.useCallback)(
8114
8483
  (color) => {
8115
8484
  onCreateHighlight(color);
8116
8485
  },
8117
8486
  [onCreateHighlight]
8118
8487
  );
8119
- const handleCopy = (0, import_react34.useCallback)(() => {
8488
+ const handleCopy = (0, import_react35.useCallback)(() => {
8120
8489
  onCopy?.();
8121
8490
  }, [onCopy]);
8122
8491
  if (!position.visible || !selection?.text) {
8123
8492
  return null;
8124
8493
  }
8125
- return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
8494
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
8126
8495
  "div",
8127
8496
  {
8128
8497
  ref: toolbarRef,
@@ -8146,7 +8515,7 @@ var init_SelectionToolbar = __esm({
8146
8515
  e.stopPropagation();
8147
8516
  },
8148
8517
  children: [
8149
- HIGHLIGHT_COLOR_BUTTONS.map((btn) => /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
8518
+ HIGHLIGHT_COLOR_BUTTONS.map((btn) => /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
8150
8519
  "button",
8151
8520
  {
8152
8521
  onClick: () => handleColorClick(btn.color),
@@ -8163,7 +8532,7 @@ var init_SelectionToolbar = __esm({
8163
8532
  ),
8164
8533
  title: `Highlight ${btn.color}`,
8165
8534
  "aria-label": `Highlight with ${btn.color}`,
8166
- children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("svg", { className: "w-4 h-4 text-gray-700", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
8535
+ children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("svg", { className: "w-4 h-4 text-gray-700", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
8167
8536
  "path",
8168
8537
  {
8169
8538
  strokeLinecap: "round",
@@ -8175,8 +8544,8 @@ var init_SelectionToolbar = __esm({
8175
8544
  },
8176
8545
  btn.color
8177
8546
  )),
8178
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { className: "w-px h-6 bg-gray-300 dark:bg-gray-600 mx-1" }),
8179
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
8547
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "w-px h-6 bg-gray-300 dark:bg-gray-600 mx-1" }),
8548
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
8180
8549
  "button",
8181
8550
  {
8182
8551
  onClick: handleCopy,
@@ -8188,7 +8557,7 @@ var init_SelectionToolbar = __esm({
8188
8557
  ),
8189
8558
  title: "Copy text",
8190
8559
  "aria-label": "Copy selected text",
8191
- children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("svg", { className: "w-5 h-5", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
8560
+ children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("svg", { className: "w-5 h-5", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
8192
8561
  "path",
8193
8562
  {
8194
8563
  strokeLinecap: "round",
@@ -8228,13 +8597,13 @@ function calculatePopoverPosition(highlight, scale, pageElement) {
8228
8597
  const left = scaledLeft + scaledWidth / 2;
8229
8598
  return { top, left, visible: true };
8230
8599
  }
8231
- var import_react35, import_jsx_runtime21, HIGHLIGHT_COLOR_OPTIONS, HighlightPopover;
8600
+ var import_react36, import_jsx_runtime22, HIGHLIGHT_COLOR_OPTIONS, HighlightPopover;
8232
8601
  var init_HighlightPopover = __esm({
8233
8602
  "src/components/HighlightPopover/HighlightPopover.tsx"() {
8234
8603
  "use strict";
8235
- import_react35 = require("react");
8604
+ import_react36 = require("react");
8236
8605
  init_utils();
8237
- import_jsx_runtime21 = require("react/jsx-runtime");
8606
+ import_jsx_runtime22 = require("react/jsx-runtime");
8238
8607
  HIGHLIGHT_COLOR_OPTIONS = [
8239
8608
  { color: "yellow", bg: "bg-yellow-300", hoverBg: "hover:bg-yellow-400", borderColor: "border-yellow-400" },
8240
8609
  { color: "green", bg: "bg-green-300", hoverBg: "hover:bg-green-400", borderColor: "border-green-400" },
@@ -8242,7 +8611,7 @@ var init_HighlightPopover = __esm({
8242
8611
  { color: "pink", bg: "bg-pink-300", hoverBg: "hover:bg-pink-400", borderColor: "border-pink-400" },
8243
8612
  { color: "orange", bg: "bg-orange-300", hoverBg: "hover:bg-orange-400", borderColor: "border-orange-400" }
8244
8613
  ];
8245
- HighlightPopover = (0, import_react35.memo)(function HighlightPopover2({
8614
+ HighlightPopover = (0, import_react36.memo)(function HighlightPopover2({
8246
8615
  highlight,
8247
8616
  scale,
8248
8617
  pageElement,
@@ -8253,16 +8622,16 @@ var init_HighlightPopover = __esm({
8253
8622
  onClose,
8254
8623
  className
8255
8624
  }) {
8256
- const [isEditingComment, setIsEditingComment] = (0, import_react35.useState)(false);
8257
- const [comment, setComment] = (0, import_react35.useState)(highlight?.comment ?? "");
8258
- const [position, setPosition] = (0, import_react35.useState)({ top: 0, left: 0, visible: false });
8259
- const popoverRef = (0, import_react35.useRef)(null);
8260
- const textareaRef = (0, import_react35.useRef)(null);
8261
- (0, import_react35.useEffect)(() => {
8625
+ const [isEditingComment, setIsEditingComment] = (0, import_react36.useState)(false);
8626
+ const [comment, setComment] = (0, import_react36.useState)(highlight?.comment ?? "");
8627
+ const [position, setPosition] = (0, import_react36.useState)({ top: 0, left: 0, visible: false });
8628
+ const popoverRef = (0, import_react36.useRef)(null);
8629
+ const textareaRef = (0, import_react36.useRef)(null);
8630
+ (0, import_react36.useEffect)(() => {
8262
8631
  setComment(highlight?.comment ?? "");
8263
8632
  setIsEditingComment(false);
8264
8633
  }, [highlight?.id, highlight?.comment]);
8265
- (0, import_react35.useEffect)(() => {
8634
+ (0, import_react36.useEffect)(() => {
8266
8635
  if (highlight && pageElement) {
8267
8636
  const newPosition = calculatePopoverPosition(highlight, scale, pageElement);
8268
8637
  if (newPosition.visible && popoverRef.current) {
@@ -8292,12 +8661,12 @@ var init_HighlightPopover = __esm({
8292
8661
  setPosition({ top: 0, left: 0, visible: false });
8293
8662
  }
8294
8663
  }, [highlight, pageElement, scale, isEditingComment]);
8295
- (0, import_react35.useEffect)(() => {
8664
+ (0, import_react36.useEffect)(() => {
8296
8665
  if (isEditingComment && textareaRef.current) {
8297
8666
  textareaRef.current.focus();
8298
8667
  }
8299
8668
  }, [isEditingComment]);
8300
- (0, import_react35.useEffect)(() => {
8669
+ (0, import_react36.useEffect)(() => {
8301
8670
  function handleClickOutside(event) {
8302
8671
  if (popoverRef.current && !popoverRef.current.contains(event.target)) {
8303
8672
  onClose();
@@ -8308,7 +8677,7 @@ var init_HighlightPopover = __esm({
8308
8677
  return () => document.removeEventListener("mousedown", handleClickOutside);
8309
8678
  }
8310
8679
  }, [position.visible, onClose]);
8311
- (0, import_react35.useEffect)(() => {
8680
+ (0, import_react36.useEffect)(() => {
8312
8681
  function handleKeyDown(event) {
8313
8682
  if (event.key === "Escape") {
8314
8683
  if (isEditingComment) {
@@ -8324,7 +8693,7 @@ var init_HighlightPopover = __esm({
8324
8693
  return () => document.removeEventListener("keydown", handleKeyDown);
8325
8694
  }
8326
8695
  }, [position.visible, isEditingComment, highlight?.comment, onClose]);
8327
- const handleColorClick = (0, import_react35.useCallback)(
8696
+ const handleColorClick = (0, import_react36.useCallback)(
8328
8697
  (color) => {
8329
8698
  if (highlight) {
8330
8699
  onColorChange(highlight.id, color);
@@ -8332,19 +8701,19 @@ var init_HighlightPopover = __esm({
8332
8701
  },
8333
8702
  [highlight, onColorChange]
8334
8703
  );
8335
- const handleSaveComment = (0, import_react35.useCallback)(() => {
8704
+ const handleSaveComment = (0, import_react36.useCallback)(() => {
8336
8705
  if (highlight) {
8337
8706
  onCommentChange(highlight.id, comment.trim());
8338
8707
  setIsEditingComment(false);
8339
8708
  }
8340
8709
  }, [highlight, comment, onCommentChange]);
8341
- const handleDeleteClick = (0, import_react35.useCallback)(() => {
8710
+ const handleDeleteClick = (0, import_react36.useCallback)(() => {
8342
8711
  if (highlight) {
8343
8712
  onDelete(highlight.id);
8344
8713
  onClose();
8345
8714
  }
8346
8715
  }, [highlight, onDelete, onClose]);
8347
- const handleCopyClick = (0, import_react35.useCallback)(() => {
8716
+ const handleCopyClick = (0, import_react36.useCallback)(() => {
8348
8717
  if (highlight?.text) {
8349
8718
  navigator.clipboard.writeText(highlight.text);
8350
8719
  onCopy?.(highlight.text);
@@ -8353,7 +8722,7 @@ var init_HighlightPopover = __esm({
8353
8722
  if (!highlight || !position.visible) {
8354
8723
  return null;
8355
8724
  }
8356
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
8725
+ return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
8357
8726
  "div",
8358
8727
  {
8359
8728
  ref: popoverRef,
@@ -8373,8 +8742,8 @@ var init_HighlightPopover = __esm({
8373
8742
  width: 280
8374
8743
  },
8375
8744
  children: [
8376
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "flex items-center justify-between p-2 border-b border-gray-200 dark:border-gray-700", children: [
8377
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "flex items-center gap-1", children: HIGHLIGHT_COLOR_OPTIONS.map((opt) => /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
8745
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "flex items-center justify-between p-2 border-b border-gray-200 dark:border-gray-700", children: [
8746
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { className: "flex items-center gap-1", children: HIGHLIGHT_COLOR_OPTIONS.map((opt) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
8378
8747
  "button",
8379
8748
  {
8380
8749
  onClick: () => handleColorClick(opt.color),
@@ -8392,7 +8761,7 @@ var init_HighlightPopover = __esm({
8392
8761
  },
8393
8762
  opt.color
8394
8763
  )) }),
8395
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
8764
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
8396
8765
  "button",
8397
8766
  {
8398
8767
  onClick: handleDeleteClick,
@@ -8404,7 +8773,7 @@ var init_HighlightPopover = __esm({
8404
8773
  ),
8405
8774
  title: "Delete highlight",
8406
8775
  "aria-label": "Delete highlight",
8407
- children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("svg", { className: "w-4 h-4", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
8776
+ children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("svg", { className: "w-4 h-4", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
8408
8777
  "path",
8409
8778
  {
8410
8779
  strokeLinecap: "round",
@@ -8416,8 +8785,8 @@ var init_HighlightPopover = __esm({
8416
8785
  }
8417
8786
  )
8418
8787
  ] }),
8419
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "p-2", children: isEditingComment ? /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "space-y-2", children: [
8420
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
8788
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { className: "p-2", children: isEditingComment ? /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "space-y-2", children: [
8789
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
8421
8790
  "textarea",
8422
8791
  {
8423
8792
  ref: textareaRef,
@@ -8436,8 +8805,8 @@ var init_HighlightPopover = __esm({
8436
8805
  rows: 3
8437
8806
  }
8438
8807
  ),
8439
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "flex justify-end gap-2", children: [
8440
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
8808
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "flex justify-end gap-2", children: [
8809
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
8441
8810
  "button",
8442
8811
  {
8443
8812
  onClick: () => {
@@ -8453,7 +8822,7 @@ var init_HighlightPopover = __esm({
8453
8822
  children: "Cancel"
8454
8823
  }
8455
8824
  ),
8456
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
8825
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
8457
8826
  "button",
8458
8827
  {
8459
8828
  onClick: handleSaveComment,
@@ -8467,14 +8836,14 @@ var init_HighlightPopover = __esm({
8467
8836
  }
8468
8837
  )
8469
8838
  ] })
8470
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "space-y-2", children: [
8471
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("p", { className: "text-xs text-gray-500 dark:text-gray-400 line-clamp-2", children: [
8839
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "space-y-2", children: [
8840
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("p", { className: "text-xs text-gray-500 dark:text-gray-400 line-clamp-2", children: [
8472
8841
  "\u201C",
8473
8842
  highlight.text.slice(0, 100),
8474
8843
  highlight.text.length > 100 ? "..." : "",
8475
8844
  "\u201D"
8476
8845
  ] }),
8477
- highlight.comment ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
8846
+ highlight.comment ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
8478
8847
  "button",
8479
8848
  {
8480
8849
  onClick: () => setIsEditingComment(true),
@@ -8487,7 +8856,7 @@ var init_HighlightPopover = __esm({
8487
8856
  ),
8488
8857
  children: highlight.comment
8489
8858
  }
8490
- ) : /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
8859
+ ) : /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
8491
8860
  "button",
8492
8861
  {
8493
8862
  onClick: () => setIsEditingComment(true),
@@ -8500,7 +8869,7 @@ var init_HighlightPopover = __esm({
8500
8869
  children: "+ Add a note..."
8501
8870
  }
8502
8871
  ),
8503
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
8872
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
8504
8873
  "button",
8505
8874
  {
8506
8875
  onClick: handleCopyClick,
@@ -8511,7 +8880,7 @@ var init_HighlightPopover = __esm({
8511
8880
  "focus:outline-none focus:ring-2 focus:ring-blue-500"
8512
8881
  ),
8513
8882
  children: [
8514
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("svg", { className: "w-4 h-4", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
8883
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("svg", { className: "w-4 h-4", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
8515
8884
  "path",
8516
8885
  {
8517
8886
  strokeLinecap: "round",
@@ -8541,20 +8910,21 @@ var init_HighlightPopover2 = __esm({
8541
8910
  });
8542
8911
 
8543
8912
  // src/components/PDFViewer/DocumentContainer.tsx
8544
- var import_react36, import_jsx_runtime22, DocumentContainer;
8913
+ var import_react37, import_jsx_runtime23, DocumentContainer;
8545
8914
  var init_DocumentContainer = __esm({
8546
8915
  "src/components/PDFViewer/DocumentContainer.tsx"() {
8547
8916
  "use strict";
8548
- import_react36 = require("react");
8917
+ import_react37 = require("react");
8549
8918
  init_PDFPage2();
8550
8919
  init_PDFLoadingScreen2();
8920
+ init_PageSkeleton();
8551
8921
  init_hooks();
8552
8922
  init_useHighlights();
8553
8923
  init_SelectionToolbar2();
8554
8924
  init_HighlightPopover2();
8555
8925
  init_utils();
8556
- import_jsx_runtime22 = require("react/jsx-runtime");
8557
- DocumentContainer = (0, import_react36.memo)(function DocumentContainer2({
8926
+ import_jsx_runtime23 = require("react/jsx-runtime");
8927
+ DocumentContainer = (0, import_react37.memo)(function DocumentContainer2({
8558
8928
  className,
8559
8929
  enableTouchGestures = true
8560
8930
  }) {
@@ -8571,34 +8941,36 @@ var init_DocumentContainer = __esm({
8571
8941
  } = usePDFViewer();
8572
8942
  const scrollToPageRequest = useViewerStore((s) => s.scrollToPageRequest);
8573
8943
  const { viewerStore } = usePDFViewerStores();
8574
- const [currentPageObj, setCurrentPageObj] = (0, import_react36.useState)(null);
8575
- const [isLoadingPage, setIsLoadingPage] = (0, import_react36.useState)(false);
8576
- const containerRef = (0, import_react36.useRef)(null);
8577
- const documentRef = (0, import_react36.useRef)(null);
8578
- const baseScaleRef = (0, import_react36.useRef)(scale);
8944
+ const [currentPageObj, setCurrentPageObj] = (0, import_react37.useState)(null);
8945
+ const [isLoadingPage, setIsLoadingPage] = (0, import_react37.useState)(false);
8946
+ const [pageLoadError, setPageLoadError] = (0, import_react37.useState)(null);
8947
+ const containerRef = (0, import_react37.useRef)(null);
8948
+ const documentRef = (0, import_react37.useRef)(null);
8949
+ const baseScaleRef = (0, import_react37.useRef)(scale);
8579
8950
  const isTouchDevice = useIsTouchDevice();
8951
+ const documentLoadingState = useViewerStore((s) => s.documentLoadingState);
8580
8952
  const { selection, clearSelection, copySelection } = useTextSelection();
8581
- const handlePinchZoom = (0, import_react36.useCallback)(
8953
+ const handlePinchZoom = (0, import_react37.useCallback)(
8582
8954
  (pinchScale) => {
8583
8955
  const newScale = Math.max(0.25, Math.min(4, baseScaleRef.current * pinchScale));
8584
8956
  setScale(newScale);
8585
8957
  },
8586
8958
  [setScale]
8587
8959
  );
8588
- const handleSwipeLeft = (0, import_react36.useCallback)(() => {
8960
+ const handleSwipeLeft = (0, import_react37.useCallback)(() => {
8589
8961
  nextPage();
8590
8962
  }, [nextPage]);
8591
- const handleSwipeRight = (0, import_react36.useCallback)(() => {
8963
+ const handleSwipeRight = (0, import_react37.useCallback)(() => {
8592
8964
  previousPage();
8593
8965
  }, [previousPage]);
8594
- const handleDoubleTap = (0, import_react36.useCallback)(
8966
+ const handleDoubleTap = (0, import_react37.useCallback)(
8595
8967
  (_position) => {
8596
8968
  const newScale = scale < 1.5 ? 2 : 1;
8597
8969
  setScale(newScale);
8598
8970
  },
8599
8971
  [scale, setScale]
8600
8972
  );
8601
- (0, import_react36.useEffect)(() => {
8973
+ (0, import_react37.useEffect)(() => {
8602
8974
  baseScaleRef.current = scale;
8603
8975
  }, [scale]);
8604
8976
  const { ref: touchRef } = useTouchGestures({
@@ -8618,20 +8990,23 @@ var init_DocumentContainer = __esm({
8618
8990
  selectHighlight,
8619
8991
  activeColor
8620
8992
  } = useHighlights();
8621
- (0, import_react36.useEffect)(() => {
8993
+ (0, import_react37.useEffect)(() => {
8622
8994
  if (document2 !== documentRef.current) {
8623
8995
  documentRef.current = document2;
8624
8996
  setCurrentPageObj(null);
8997
+ setPageLoadError(null);
8625
8998
  }
8626
8999
  }, [document2]);
8627
- (0, import_react36.useEffect)(() => {
9000
+ (0, import_react37.useEffect)(() => {
8628
9001
  if (!document2) {
8629
9002
  setCurrentPageObj(null);
9003
+ setPageLoadError(null);
8630
9004
  return;
8631
9005
  }
8632
9006
  let cancelled = false;
8633
9007
  const loadPage = async () => {
8634
9008
  setIsLoadingPage(true);
9009
+ setPageLoadError(null);
8635
9010
  try {
8636
9011
  const page = await document2.getPage(currentPage);
8637
9012
  if (!cancelled && document2 === documentRef.current) {
@@ -8648,6 +9023,7 @@ var init_DocumentContainer = __esm({
8648
9023
  const isDocumentDestroyed = errorMessage.includes("destroyed") || errorMessage.includes("sendWithStream") || errorMessage.includes("sendWithPromise") || errorMessage.includes("Cannot read properties of null");
8649
9024
  if (!isDocumentDestroyed) {
8650
9025
  console.error("Error loading page:", error);
9026
+ setPageLoadError(error instanceof Error ? error : new Error(errorMessage));
8651
9027
  }
8652
9028
  }
8653
9029
  } finally {
@@ -8661,10 +9037,10 @@ var init_DocumentContainer = __esm({
8661
9037
  cancelled = true;
8662
9038
  };
8663
9039
  }, [document2, currentPage, scrollToPageRequest, viewerStore]);
8664
- const getPageElement = (0, import_react36.useCallback)(() => {
9040
+ const getPageElement = (0, import_react37.useCallback)(() => {
8665
9041
  return containerRef.current?.querySelector(`[data-page-number="${currentPage}"]`);
8666
9042
  }, [currentPage]);
8667
- const handleCreateHighlight = (0, import_react36.useCallback)(
9043
+ const handleCreateHighlight = (0, import_react37.useCallback)(
8668
9044
  (color) => {
8669
9045
  if (!selection) return;
8670
9046
  const pageElement = getPageElement();
@@ -8674,25 +9050,25 @@ var init_DocumentContainer = __esm({
8674
9050
  },
8675
9051
  [selection, getPageElement, createHighlightFromSelection, scale, clearSelection]
8676
9052
  );
8677
- const handleCopySelection = (0, import_react36.useCallback)(() => {
9053
+ const handleCopySelection = (0, import_react37.useCallback)(() => {
8678
9054
  copySelection();
8679
9055
  }, [copySelection]);
8680
- const handleColorChange = (0, import_react36.useCallback)(
9056
+ const handleColorChange = (0, import_react37.useCallback)(
8681
9057
  (id, color) => {
8682
9058
  updateHighlight(id, { color });
8683
9059
  },
8684
9060
  [updateHighlight]
8685
9061
  );
8686
- const handleCommentChange = (0, import_react36.useCallback)(
9062
+ const handleCommentChange = (0, import_react37.useCallback)(
8687
9063
  (id, comment) => {
8688
9064
  updateHighlight(id, { comment: comment || void 0 });
8689
9065
  },
8690
9066
  [updateHighlight]
8691
9067
  );
8692
- const handleClosePopover = (0, import_react36.useCallback)(() => {
9068
+ const handleClosePopover = (0, import_react37.useCallback)(() => {
8693
9069
  selectHighlight(null);
8694
9070
  }, [selectHighlight]);
8695
- const setContainerRef = (0, import_react36.useCallback)(
9071
+ const setContainerRef = (0, import_react37.useCallback)(
8696
9072
  (element) => {
8697
9073
  containerRef.current = element;
8698
9074
  touchRef(element);
@@ -8705,7 +9081,7 @@ var init_DocumentContainer = __esm({
8705
9081
  sepia: "bg-amber-50"
8706
9082
  };
8707
9083
  if (!document2) {
8708
- return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
9084
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
8709
9085
  "div",
8710
9086
  {
8711
9087
  className: cn(
@@ -8714,11 +9090,53 @@ var init_DocumentContainer = __esm({
8714
9090
  themeStyles[theme],
8715
9091
  className
8716
9092
  ),
8717
- children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(PDFLoadingScreen, { phase: isLoading ? "fetching" : "initializing" })
9093
+ children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(PDFLoadingScreen, { phase: isLoading ? "fetching" : "initializing" })
8718
9094
  }
8719
9095
  );
8720
9096
  }
8721
- return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
9097
+ const renderPageContent = () => {
9098
+ if (pageLoadError && !currentPageObj) {
9099
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
9100
+ "div",
9101
+ {
9102
+ className: "relative bg-white shadow-lg flex flex-col items-center justify-center gap-2 text-gray-500",
9103
+ style: {
9104
+ width: DEFAULT_PAGE_WIDTH * scale,
9105
+ height: DEFAULT_PAGE_HEIGHT * scale
9106
+ },
9107
+ "data-page-number": currentPage,
9108
+ children: [
9109
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("svg", { className: "w-8 h-8 text-red-400", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("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" }) }),
9110
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("span", { className: "text-sm", children: [
9111
+ "Failed to load page ",
9112
+ currentPage
9113
+ ] })
9114
+ ]
9115
+ }
9116
+ );
9117
+ }
9118
+ if (isLoadingPage && !currentPageObj) {
9119
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
9120
+ PageSkeleton,
9121
+ {
9122
+ pageNumber: currentPage,
9123
+ width: Math.floor(DEFAULT_PAGE_WIDTH * scale),
9124
+ height: Math.floor(DEFAULT_PAGE_HEIGHT * scale),
9125
+ isFirstPage: currentPage === 1 && documentLoadingState !== "ready"
9126
+ }
9127
+ );
9128
+ }
9129
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
9130
+ PDFPage,
9131
+ {
9132
+ pageNumber: currentPage,
9133
+ page: currentPageObj,
9134
+ scale,
9135
+ rotation
9136
+ }
9137
+ );
9138
+ };
9139
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
8722
9140
  "div",
8723
9141
  {
8724
9142
  ref: setContainerRef,
@@ -8731,16 +9149,8 @@ var init_DocumentContainer = __esm({
8731
9149
  className
8732
9150
  ),
8733
9151
  children: [
8734
- /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
8735
- PDFPage,
8736
- {
8737
- pageNumber: currentPage,
8738
- page: currentPageObj,
8739
- scale,
8740
- rotation
8741
- }
8742
- ),
8743
- /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
9152
+ renderPageContent(),
9153
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
8744
9154
  SelectionToolbar,
8745
9155
  {
8746
9156
  selection,
@@ -8749,7 +9159,7 @@ var init_DocumentContainer = __esm({
8749
9159
  activeColor
8750
9160
  }
8751
9161
  ),
8752
- /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
9162
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
8753
9163
  HighlightPopover,
8754
9164
  {
8755
9165
  highlight: selectedHighlight,
@@ -8760,8 +9170,7 @@ var init_DocumentContainer = __esm({
8760
9170
  onDelete: deleteHighlight,
8761
9171
  onClose: handleClosePopover
8762
9172
  }
8763
- ),
8764
- isLoadingPage && !currentPageObj && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { className: "fixed bottom-4 right-4 px-3 py-2 bg-black/75 text-white text-sm rounded-lg", children: "Loading..." })
9173
+ )
8765
9174
  ]
8766
9175
  }
8767
9176
  );
@@ -8770,22 +9179,23 @@ var init_DocumentContainer = __esm({
8770
9179
  });
8771
9180
 
8772
9181
  // src/components/PDFViewer/VirtualizedDocumentContainer.tsx
8773
- var import_react37, import_jsx_runtime23, DEFAULT_PAGE_WIDTH, DEFAULT_PAGE_HEIGHT, VirtualizedDocumentContainer;
9182
+ var import_react38, import_jsx_runtime24, DEFAULT_PAGE_WIDTH2, DEFAULT_PAGE_HEIGHT2, VirtualizedDocumentContainer;
8774
9183
  var init_VirtualizedDocumentContainer = __esm({
8775
9184
  "src/components/PDFViewer/VirtualizedDocumentContainer.tsx"() {
8776
9185
  "use strict";
8777
- import_react37 = require("react");
9186
+ import_react38 = require("react");
8778
9187
  init_PDFPage2();
8779
9188
  init_PDFLoadingScreen2();
9189
+ init_PageSkeleton();
8780
9190
  init_hooks();
8781
9191
  init_useHighlights();
8782
9192
  init_SelectionToolbar2();
8783
9193
  init_HighlightPopover2();
8784
9194
  init_utils();
8785
- import_jsx_runtime23 = require("react/jsx-runtime");
8786
- DEFAULT_PAGE_WIDTH = 612;
8787
- DEFAULT_PAGE_HEIGHT = 792;
8788
- VirtualizedDocumentContainer = (0, import_react37.memo)(function VirtualizedDocumentContainer2({
9195
+ import_jsx_runtime24 = require("react/jsx-runtime");
9196
+ DEFAULT_PAGE_WIDTH2 = 612;
9197
+ DEFAULT_PAGE_HEIGHT2 = 792;
9198
+ VirtualizedDocumentContainer = (0, import_react38.memo)(function VirtualizedDocumentContainer2({
8789
9199
  overscan = 2,
8790
9200
  pageGap = 16,
8791
9201
  enableTouchGestures = true,
@@ -8806,17 +9216,17 @@ var init_VirtualizedDocumentContainer = __esm({
8806
9216
  } = usePDFViewer();
8807
9217
  const scrollToPageRequest = useViewerStore((s) => s.scrollToPageRequest);
8808
9218
  const { viewerStore } = usePDFViewerStores();
8809
- const containerRef = (0, import_react37.useRef)(null);
8810
- const scrollContainerRef = (0, import_react37.useRef)(null);
8811
- const documentRef = (0, import_react37.useRef)(null);
8812
- const pageCache = (0, import_react37.useRef)(/* @__PURE__ */ new Map());
8813
- const pageDimensionsCache = (0, import_react37.useRef)(/* @__PURE__ */ new Map());
8814
- const baseScaleRef = (0, import_react37.useRef)(scale);
9219
+ const containerRef = (0, import_react38.useRef)(null);
9220
+ const scrollContainerRef = (0, import_react38.useRef)(null);
9221
+ const documentRef = (0, import_react38.useRef)(null);
9222
+ const pageCache = (0, import_react38.useRef)(/* @__PURE__ */ new Map());
9223
+ const pageDimensionsCache = (0, import_react38.useRef)(/* @__PURE__ */ new Map());
9224
+ const baseScaleRef = (0, import_react38.useRef)(scale);
8815
9225
  const isTouchDevice = useIsTouchDevice();
8816
- const [visiblePages, setVisiblePages] = (0, import_react37.useState)([1]);
8817
- const [pageObjects, setPageObjects] = (0, import_react37.useState)(/* @__PURE__ */ new Map());
8818
- const [totalHeight, setTotalHeight] = (0, import_react37.useState)(0);
8819
- const [pageInfos, setPageInfos] = (0, import_react37.useState)([]);
9226
+ const [visiblePages, setVisiblePages] = (0, import_react38.useState)([1]);
9227
+ const [pageObjects, setPageObjects] = (0, import_react38.useState)(/* @__PURE__ */ new Map());
9228
+ const [totalHeight, setTotalHeight] = (0, import_react38.useState)(0);
9229
+ const [pageInfos, setPageInfos] = (0, import_react38.useState)([]);
8820
9230
  const { selection, clearSelection, copySelection } = useTextSelection();
8821
9231
  const {
8822
9232
  createHighlightFromSelection,
@@ -8826,7 +9236,7 @@ var init_VirtualizedDocumentContainer = __esm({
8826
9236
  selectHighlight,
8827
9237
  activeColor
8828
9238
  } = useHighlights();
8829
- (0, import_react37.useEffect)(() => {
9239
+ (0, import_react38.useEffect)(() => {
8830
9240
  if (document2 !== documentRef.current) {
8831
9241
  documentRef.current = document2;
8832
9242
  pageCache.current.clear();
@@ -8834,7 +9244,7 @@ var init_VirtualizedDocumentContainer = __esm({
8834
9244
  setPageObjects(/* @__PURE__ */ new Map());
8835
9245
  }
8836
9246
  }, [document2]);
8837
- (0, import_react37.useEffect)(() => {
9247
+ (0, import_react38.useEffect)(() => {
8838
9248
  if (!document2 || numPages === 0) return;
8839
9249
  const calculatePageInfos = async () => {
8840
9250
  const infos = [];
@@ -8851,7 +9261,7 @@ var init_VirtualizedDocumentContainer = __esm({
8851
9261
  dimensions = { width: viewport.width, height: viewport.height };
8852
9262
  pageDimensionsCache.current.set(i, dimensions);
8853
9263
  } catch {
8854
- dimensions = { width: DEFAULT_PAGE_WIDTH, height: DEFAULT_PAGE_HEIGHT };
9264
+ dimensions = { width: DEFAULT_PAGE_WIDTH2, height: DEFAULT_PAGE_HEIGHT2 };
8855
9265
  }
8856
9266
  }
8857
9267
  const scaledHeight = Math.floor(dimensions.height * scale);
@@ -8867,7 +9277,7 @@ var init_VirtualizedDocumentContainer = __esm({
8867
9277
  };
8868
9278
  calculatePageInfos();
8869
9279
  }, [document2, numPages, scale, rotation, pageGap]);
8870
- const updateVisiblePages = (0, import_react37.useCallback)(() => {
9280
+ const updateVisiblePages = (0, import_react38.useCallback)(() => {
8871
9281
  if (!scrollContainerRef.current || pageInfos.length === 0) return;
8872
9282
  const container = scrollContainerRef.current;
8873
9283
  const scrollTop = container.scrollTop;
@@ -8899,7 +9309,7 @@ var init_VirtualizedDocumentContainer = __esm({
8899
9309
  goToPage(firstVisiblePage);
8900
9310
  }
8901
9311
  }, [pageInfos, overscan, currentPage, goToPage]);
8902
- (0, import_react37.useEffect)(() => {
9312
+ (0, import_react38.useEffect)(() => {
8903
9313
  const container = scrollContainerRef.current;
8904
9314
  if (!container) return;
8905
9315
  const handleScroll = () => {
@@ -8909,7 +9319,7 @@ var init_VirtualizedDocumentContainer = __esm({
8909
9319
  updateVisiblePages();
8910
9320
  return () => container.removeEventListener("scroll", handleScroll);
8911
9321
  }, [updateVisiblePages]);
8912
- (0, import_react37.useEffect)(() => {
9322
+ (0, import_react38.useEffect)(() => {
8913
9323
  if (!document2) return;
8914
9324
  const loadPages = async () => {
8915
9325
  const newPageObjects = new Map(pageObjects);
@@ -8946,7 +9356,7 @@ var init_VirtualizedDocumentContainer = __esm({
8946
9356
  };
8947
9357
  loadPages();
8948
9358
  }, [document2, visiblePages, pageObjects]);
8949
- (0, import_react37.useEffect)(() => {
9359
+ (0, import_react38.useEffect)(() => {
8950
9360
  if (!scrollToPageRequest || !scrollContainerRef.current || pageInfos.length === 0) return;
8951
9361
  const { page, requestId, behavior } = scrollToPageRequest;
8952
9362
  const pageInfo = pageInfos.find((p) => p.pageNumber === page);
@@ -8984,7 +9394,7 @@ var init_VirtualizedDocumentContainer = __esm({
8984
9394
  handleScrollEnd();
8985
9395
  }
8986
9396
  }, [scrollToPageRequest, pageInfos, pageGap, viewerStore]);
8987
- (0, import_react37.useEffect)(() => {
9397
+ (0, import_react38.useEffect)(() => {
8988
9398
  if (scrollToPageRequest) return;
8989
9399
  if (!scrollContainerRef.current || pageInfos.length === 0) return;
8990
9400
  const pageInfo = pageInfos.find((p) => p.pageNumber === currentPage);
@@ -9001,14 +9411,14 @@ var init_VirtualizedDocumentContainer = __esm({
9001
9411
  }
9002
9412
  }
9003
9413
  }, [currentPage, pageInfos, pageGap, scrollToPageRequest]);
9004
- const handlePinchZoom = (0, import_react37.useCallback)(
9414
+ const handlePinchZoom = (0, import_react38.useCallback)(
9005
9415
  (pinchScale) => {
9006
9416
  const newScale = Math.max(0.25, Math.min(4, baseScaleRef.current * pinchScale));
9007
9417
  setScale(newScale);
9008
9418
  },
9009
9419
  [setScale]
9010
9420
  );
9011
- (0, import_react37.useEffect)(() => {
9421
+ (0, import_react38.useEffect)(() => {
9012
9422
  baseScaleRef.current = scale;
9013
9423
  }, [scale]);
9014
9424
  const { ref: touchRef } = useTouchGestures({
@@ -9017,20 +9427,20 @@ var init_VirtualizedDocumentContainer = __esm({
9017
9427
  onSwipeRight: previousPage,
9018
9428
  enabled: enableTouchGestures && isTouchDevice
9019
9429
  });
9020
- const setContainerRef = (0, import_react37.useCallback)(
9430
+ const setContainerRef = (0, import_react38.useCallback)(
9021
9431
  (element) => {
9022
9432
  scrollContainerRef.current = element;
9023
9433
  touchRef(element);
9024
9434
  },
9025
9435
  [touchRef]
9026
9436
  );
9027
- const getPageElement = (0, import_react37.useCallback)(
9437
+ const getPageElement = (0, import_react38.useCallback)(
9028
9438
  (pageNumber) => {
9029
9439
  return containerRef.current?.querySelector(`[data-page-number="${pageNumber}"]`);
9030
9440
  },
9031
9441
  []
9032
9442
  );
9033
- const handleCreateHighlight = (0, import_react37.useCallback)(
9443
+ const handleCreateHighlight = (0, import_react38.useCallback)(
9034
9444
  (color) => {
9035
9445
  if (!selection) return;
9036
9446
  const pageElement = getPageElement(selection.pageNumber);
@@ -9040,13 +9450,13 @@ var init_VirtualizedDocumentContainer = __esm({
9040
9450
  },
9041
9451
  [selection, getPageElement, createHighlightFromSelection, scale, clearSelection]
9042
9452
  );
9043
- const handleColorChange = (0, import_react37.useCallback)(
9453
+ const handleColorChange = (0, import_react38.useCallback)(
9044
9454
  (id, color) => {
9045
9455
  updateHighlight(id, { color });
9046
9456
  },
9047
9457
  [updateHighlight]
9048
9458
  );
9049
- const handleCommentChange = (0, import_react37.useCallback)(
9459
+ const handleCommentChange = (0, import_react38.useCallback)(
9050
9460
  (id, comment) => {
9051
9461
  updateHighlight(id, { comment: comment || void 0 });
9052
9462
  },
@@ -9058,7 +9468,7 @@ var init_VirtualizedDocumentContainer = __esm({
9058
9468
  sepia: "bg-amber-50"
9059
9469
  };
9060
9470
  if (!document2) {
9061
- return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
9471
+ return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
9062
9472
  "div",
9063
9473
  {
9064
9474
  className: cn(
@@ -9067,11 +9477,11 @@ var init_VirtualizedDocumentContainer = __esm({
9067
9477
  themeStyles[theme],
9068
9478
  className
9069
9479
  ),
9070
- children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(PDFLoadingScreen, { phase: isLoading ? "fetching" : "initializing" })
9480
+ children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(PDFLoadingScreen, { phase: isLoading ? "fetching" : "initializing" })
9071
9481
  }
9072
9482
  );
9073
9483
  }
9074
- return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
9484
+ return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
9075
9485
  "div",
9076
9486
  {
9077
9487
  ref: containerRef,
@@ -9082,7 +9492,7 @@ var init_VirtualizedDocumentContainer = __esm({
9082
9492
  className
9083
9493
  ),
9084
9494
  children: [
9085
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
9495
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
9086
9496
  "div",
9087
9497
  {
9088
9498
  ref: setContainerRef,
@@ -9091,7 +9501,7 @@ var init_VirtualizedDocumentContainer = __esm({
9091
9501
  // Smooth scrolling on iOS
9092
9502
  WebkitOverflowScrolling: "touch"
9093
9503
  },
9094
- children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
9504
+ children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
9095
9505
  "div",
9096
9506
  {
9097
9507
  className: "relative mx-auto",
@@ -9102,8 +9512,9 @@ var init_VirtualizedDocumentContainer = __esm({
9102
9512
  children: pageInfos.filter((info) => visiblePages.includes(info.pageNumber)).map((info) => {
9103
9513
  const page = pageObjects.get(info.pageNumber);
9104
9514
  const dimensions = pageDimensionsCache.current.get(info.pageNumber);
9105
- const scaledWidth = dimensions ? Math.floor(dimensions.width * scale) : Math.floor(DEFAULT_PAGE_WIDTH * scale);
9106
- return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
9515
+ const scaledWidth = dimensions ? Math.floor(dimensions.width * scale) : Math.floor(DEFAULT_PAGE_WIDTH2 * scale);
9516
+ const scaledHeight = dimensions ? Math.floor(dimensions.height * scale) : Math.floor(DEFAULT_PAGE_HEIGHT2 * scale);
9517
+ return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
9107
9518
  "div",
9108
9519
  {
9109
9520
  className: "absolute left-1/2 -translate-x-1/2",
@@ -9111,14 +9522,22 @@ var init_VirtualizedDocumentContainer = __esm({
9111
9522
  top: info.top,
9112
9523
  width: scaledWidth
9113
9524
  },
9114
- children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
9525
+ children: page ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
9115
9526
  PDFPage,
9116
9527
  {
9117
9528
  pageNumber: info.pageNumber,
9118
- page: page || null,
9529
+ page,
9119
9530
  scale,
9120
9531
  rotation
9121
9532
  }
9533
+ ) : /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
9534
+ PageSkeleton,
9535
+ {
9536
+ pageNumber: info.pageNumber,
9537
+ width: scaledWidth,
9538
+ height: scaledHeight,
9539
+ isFirstPage: info.pageNumber === 1
9540
+ }
9122
9541
  )
9123
9542
  },
9124
9543
  info.pageNumber
@@ -9128,7 +9547,7 @@ var init_VirtualizedDocumentContainer = __esm({
9128
9547
  )
9129
9548
  }
9130
9549
  ),
9131
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
9550
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
9132
9551
  SelectionToolbar,
9133
9552
  {
9134
9553
  selection,
@@ -9137,7 +9556,7 @@ var init_VirtualizedDocumentContainer = __esm({
9137
9556
  activeColor
9138
9557
  }
9139
9558
  ),
9140
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
9559
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
9141
9560
  HighlightPopover,
9142
9561
  {
9143
9562
  highlight: selectedHighlight,
@@ -9157,15 +9576,15 @@ var init_VirtualizedDocumentContainer = __esm({
9157
9576
  });
9158
9577
 
9159
9578
  // src/components/PDFViewer/ContinuousScrollContainer.tsx
9160
- var import_react38, import_jsx_runtime24, ContinuousScrollContainer;
9579
+ var import_react39, import_jsx_runtime25, ContinuousScrollContainer;
9161
9580
  var init_ContinuousScrollContainer = __esm({
9162
9581
  "src/components/PDFViewer/ContinuousScrollContainer.tsx"() {
9163
9582
  "use strict";
9164
- import_react38 = require("react");
9583
+ import_react39 = require("react");
9165
9584
  init_VirtualizedDocumentContainer();
9166
- import_jsx_runtime24 = require("react/jsx-runtime");
9167
- ContinuousScrollContainer = (0, import_react38.memo)(function ContinuousScrollContainer2(props) {
9168
- return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
9585
+ import_jsx_runtime25 = require("react/jsx-runtime");
9586
+ ContinuousScrollContainer = (0, import_react39.memo)(function ContinuousScrollContainer2(props) {
9587
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
9169
9588
  VirtualizedDocumentContainer,
9170
9589
  {
9171
9590
  overscan: 3,
@@ -9178,11 +9597,11 @@ var init_ContinuousScrollContainer = __esm({
9178
9597
  });
9179
9598
 
9180
9599
  // src/components/PDFViewer/DualPageContainer.tsx
9181
- var import_react39, import_jsx_runtime25, DualPageContainer;
9600
+ var import_react40, import_jsx_runtime26, DualPageContainer;
9182
9601
  var init_DualPageContainer = __esm({
9183
9602
  "src/components/PDFViewer/DualPageContainer.tsx"() {
9184
9603
  "use strict";
9185
- import_react39 = require("react");
9604
+ import_react40 = require("react");
9186
9605
  init_PDFPage2();
9187
9606
  init_PDFLoadingScreen2();
9188
9607
  init_hooks();
@@ -9190,8 +9609,8 @@ var init_DualPageContainer = __esm({
9190
9609
  init_SelectionToolbar2();
9191
9610
  init_HighlightPopover2();
9192
9611
  init_utils();
9193
- import_jsx_runtime25 = require("react/jsx-runtime");
9194
- DualPageContainer = (0, import_react39.memo)(function DualPageContainer2({
9612
+ import_jsx_runtime26 = require("react/jsx-runtime");
9613
+ DualPageContainer = (0, import_react40.memo)(function DualPageContainer2({
9195
9614
  showCover = true,
9196
9615
  bookSpread = true,
9197
9616
  pageGap = 4,
@@ -9211,13 +9630,13 @@ var init_DualPageContainer = __esm({
9211
9630
  } = usePDFViewer();
9212
9631
  const scrollToPageRequest = useViewerStore((s) => s.scrollToPageRequest);
9213
9632
  const { viewerStore } = usePDFViewerStores();
9214
- const containerRef = (0, import_react39.useRef)(null);
9215
- const documentRef = (0, import_react39.useRef)(null);
9216
- const baseScaleRef = (0, import_react39.useRef)(scale);
9633
+ const containerRef = (0, import_react40.useRef)(null);
9634
+ const documentRef = (0, import_react40.useRef)(null);
9635
+ const baseScaleRef = (0, import_react40.useRef)(scale);
9217
9636
  const isTouchDevice = useIsTouchDevice();
9218
- const [leftPage, setLeftPage] = (0, import_react39.useState)(null);
9219
- const [rightPage, setRightPage] = (0, import_react39.useState)(null);
9220
- const [isLoading, setIsLoading] = (0, import_react39.useState)(false);
9637
+ const [leftPage, setLeftPage] = (0, import_react40.useState)(null);
9638
+ const [rightPage, setRightPage] = (0, import_react40.useState)(null);
9639
+ const [isLoading, setIsLoading] = (0, import_react40.useState)(false);
9221
9640
  const { selection, clearSelection, copySelection } = useTextSelection();
9222
9641
  const {
9223
9642
  createHighlightFromSelection,
@@ -9227,7 +9646,7 @@ var init_DualPageContainer = __esm({
9227
9646
  selectHighlight,
9228
9647
  activeColor
9229
9648
  } = useHighlights();
9230
- const getSpreadPages = (0, import_react39.useCallback)(
9649
+ const getSpreadPages = (0, import_react40.useCallback)(
9231
9650
  (page) => {
9232
9651
  if (showCover && page === 1) {
9233
9652
  return { left: null, right: 1 };
@@ -9271,14 +9690,14 @@ var init_DualPageContainer = __esm({
9271
9690
  },
9272
9691
  [showCover, bookSpread, numPages]
9273
9692
  );
9274
- (0, import_react39.useEffect)(() => {
9693
+ (0, import_react40.useEffect)(() => {
9275
9694
  if (document2 !== documentRef.current) {
9276
9695
  documentRef.current = document2;
9277
9696
  setLeftPage(null);
9278
9697
  setRightPage(null);
9279
9698
  }
9280
9699
  }, [document2]);
9281
- (0, import_react39.useEffect)(() => {
9700
+ (0, import_react40.useEffect)(() => {
9282
9701
  if (!document2) {
9283
9702
  setLeftPage(null);
9284
9703
  setRightPage(null);
@@ -9324,7 +9743,7 @@ var init_DualPageContainer = __esm({
9324
9743
  cancelled = true;
9325
9744
  };
9326
9745
  }, [document2, currentPage, getSpreadPages, scrollToPageRequest, viewerStore]);
9327
- const goToPreviousSpread = (0, import_react39.useCallback)(() => {
9746
+ const goToPreviousSpread = (0, import_react40.useCallback)(() => {
9328
9747
  const spread2 = getSpreadPages(currentPage);
9329
9748
  const leftmostPage = spread2.left || spread2.right || currentPage;
9330
9749
  if (showCover && leftmostPage === 2) {
@@ -9336,21 +9755,21 @@ var init_DualPageContainer = __esm({
9336
9755
  goToPage(newPage);
9337
9756
  }
9338
9757
  }, [currentPage, showCover, getSpreadPages, goToPage]);
9339
- const goToNextSpread = (0, import_react39.useCallback)(() => {
9758
+ const goToNextSpread = (0, import_react40.useCallback)(() => {
9340
9759
  const spread2 = getSpreadPages(currentPage);
9341
9760
  const rightmostPage = spread2.right || spread2.left || currentPage;
9342
9761
  if (rightmostPage < numPages) {
9343
9762
  goToPage(Math.min(numPages, rightmostPage + 1));
9344
9763
  }
9345
9764
  }, [currentPage, numPages, getSpreadPages, goToPage]);
9346
- const handlePinchZoom = (0, import_react39.useCallback)(
9765
+ const handlePinchZoom = (0, import_react40.useCallback)(
9347
9766
  (pinchScale) => {
9348
9767
  const newScale = Math.max(0.25, Math.min(4, baseScaleRef.current * pinchScale));
9349
9768
  setScale(newScale);
9350
9769
  },
9351
9770
  [setScale]
9352
9771
  );
9353
- (0, import_react39.useEffect)(() => {
9772
+ (0, import_react40.useEffect)(() => {
9354
9773
  baseScaleRef.current = scale;
9355
9774
  }, [scale]);
9356
9775
  const { ref: touchRef } = useTouchGestures({
@@ -9359,20 +9778,20 @@ var init_DualPageContainer = __esm({
9359
9778
  onSwipeRight: goToPreviousSpread,
9360
9779
  enabled: enableTouchGestures && isTouchDevice
9361
9780
  });
9362
- const setContainerRef = (0, import_react39.useCallback)(
9781
+ const setContainerRef = (0, import_react40.useCallback)(
9363
9782
  (element) => {
9364
9783
  containerRef.current = element;
9365
9784
  touchRef(element);
9366
9785
  },
9367
9786
  [touchRef]
9368
9787
  );
9369
- const getPageElement = (0, import_react39.useCallback)(
9788
+ const getPageElement = (0, import_react40.useCallback)(
9370
9789
  (pageNumber) => {
9371
9790
  return containerRef.current?.querySelector(`[data-page-number="${pageNumber}"]`);
9372
9791
  },
9373
9792
  []
9374
9793
  );
9375
- const handleCreateHighlight = (0, import_react39.useCallback)(
9794
+ const handleCreateHighlight = (0, import_react40.useCallback)(
9376
9795
  (color) => {
9377
9796
  if (!selection) return;
9378
9797
  const pageElement = getPageElement(selection.pageNumber);
@@ -9382,13 +9801,13 @@ var init_DualPageContainer = __esm({
9382
9801
  },
9383
9802
  [selection, getPageElement, createHighlightFromSelection, scale, clearSelection]
9384
9803
  );
9385
- const handleColorChange = (0, import_react39.useCallback)(
9804
+ const handleColorChange = (0, import_react40.useCallback)(
9386
9805
  (id, color) => {
9387
9806
  updateHighlight(id, { color });
9388
9807
  },
9389
9808
  [updateHighlight]
9390
9809
  );
9391
- const handleCommentChange = (0, import_react39.useCallback)(
9810
+ const handleCommentChange = (0, import_react40.useCallback)(
9392
9811
  (id, comment) => {
9393
9812
  updateHighlight(id, { comment: comment || void 0 });
9394
9813
  },
@@ -9401,7 +9820,7 @@ var init_DualPageContainer = __esm({
9401
9820
  };
9402
9821
  const spread = getSpreadPages(currentPage);
9403
9822
  if (!document2) {
9404
- return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
9823
+ return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
9405
9824
  "div",
9406
9825
  {
9407
9826
  className: cn(
@@ -9410,11 +9829,11 @@ var init_DualPageContainer = __esm({
9410
9829
  themeStyles[theme],
9411
9830
  className
9412
9831
  ),
9413
- children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(PDFLoadingScreen, { phase: isDocumentLoading ? "fetching" : "initializing" })
9832
+ children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(PDFLoadingScreen, { phase: isDocumentLoading ? "fetching" : "initializing" })
9414
9833
  }
9415
9834
  );
9416
9835
  }
9417
- return /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
9836
+ return /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(
9418
9837
  "div",
9419
9838
  {
9420
9839
  ref: setContainerRef,
@@ -9427,13 +9846,13 @@ var init_DualPageContainer = __esm({
9427
9846
  className
9428
9847
  ),
9429
9848
  children: [
9430
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
9849
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(
9431
9850
  "div",
9432
9851
  {
9433
9852
  className: "flex items-center",
9434
9853
  style: { gap: pageGap },
9435
9854
  children: [
9436
- spread.left && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
9855
+ spread.left && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
9437
9856
  PDFPage,
9438
9857
  {
9439
9858
  pageNumber: spread.left,
@@ -9442,14 +9861,14 @@ var init_DualPageContainer = __esm({
9442
9861
  rotation
9443
9862
  }
9444
9863
  ),
9445
- spread.left && spread.right && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
9864
+ spread.left && spread.right && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
9446
9865
  "div",
9447
9866
  {
9448
9867
  className: "w-px h-full bg-gray-300 dark:bg-gray-600 opacity-50",
9449
9868
  style: { minHeight: "100%" }
9450
9869
  }
9451
9870
  ),
9452
- spread.right && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
9871
+ spread.right && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
9453
9872
  PDFPage,
9454
9873
  {
9455
9874
  pageNumber: spread.right,
@@ -9458,7 +9877,7 @@ var init_DualPageContainer = __esm({
9458
9877
  rotation
9459
9878
  }
9460
9879
  ),
9461
- (!spread.left || !spread.right) && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
9880
+ (!spread.left || !spread.right) && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
9462
9881
  "div",
9463
9882
  {
9464
9883
  className: "flex items-center justify-center",
@@ -9471,7 +9890,7 @@ var init_DualPageContainer = __esm({
9471
9890
  ]
9472
9891
  }
9473
9892
  ),
9474
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
9893
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
9475
9894
  SelectionToolbar,
9476
9895
  {
9477
9896
  selection,
@@ -9480,7 +9899,7 @@ var init_DualPageContainer = __esm({
9480
9899
  activeColor
9481
9900
  }
9482
9901
  ),
9483
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
9902
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
9484
9903
  HighlightPopover,
9485
9904
  {
9486
9905
  highlight: selectedHighlight,
@@ -9492,7 +9911,202 @@ var init_DualPageContainer = __esm({
9492
9911
  onClose: () => selectHighlight(null)
9493
9912
  }
9494
9913
  ),
9495
- isLoading && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "fixed bottom-4 right-4 px-3 py-2 bg-black/75 text-white text-sm rounded-lg", children: "Loading..." })
9914
+ isLoading && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { className: "fixed bottom-4 right-4 px-3 py-2 bg-black/75 text-white text-sm rounded-lg", children: "Loading..." })
9915
+ ]
9916
+ }
9917
+ );
9918
+ });
9919
+ }
9920
+ });
9921
+
9922
+ // src/components/PDFViewer/BookModeContainer.tsx
9923
+ var import_react41, import_react_pageflip, import_jsx_runtime27, BookPage, BookModeContainer;
9924
+ var init_BookModeContainer = __esm({
9925
+ "src/components/PDFViewer/BookModeContainer.tsx"() {
9926
+ "use strict";
9927
+ import_react41 = __toESM(require("react"), 1);
9928
+ import_react_pageflip = __toESM(require("react-pageflip"), 1);
9929
+ init_PDFPage2();
9930
+ init_PDFLoadingScreen2();
9931
+ init_hooks();
9932
+ init_utils();
9933
+ import_jsx_runtime27 = require("react/jsx-runtime");
9934
+ BookPage = import_react41.default.forwardRef(function BookPage2({ pageNumber, page, scale, rotation, width, height }, ref) {
9935
+ return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { ref, className: "book-page", "data-page-number": pageNumber, children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { style: { width, height, overflow: "hidden" }, children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
9936
+ PDFPage,
9937
+ {
9938
+ pageNumber,
9939
+ page,
9940
+ scale,
9941
+ rotation,
9942
+ showTextLayer: false,
9943
+ showAnnotationLayer: false,
9944
+ showHighlightLayer: false
9945
+ }
9946
+ ) }) });
9947
+ });
9948
+ BookModeContainer = (0, import_react41.memo)(function BookModeContainer2({
9949
+ className,
9950
+ flippingTime = 800,
9951
+ drawShadow = true,
9952
+ maxShadowOpacity = 0.7
9953
+ }) {
9954
+ const {
9955
+ document: document2,
9956
+ currentPage,
9957
+ numPages,
9958
+ scale,
9959
+ rotation,
9960
+ theme,
9961
+ isLoading,
9962
+ goToPage
9963
+ } = usePDFViewer();
9964
+ const scrollToPageRequest = useViewerStore((s) => s.scrollToPageRequest);
9965
+ const { viewerStore } = usePDFViewerStores();
9966
+ const [pages, setPages] = (0, import_react41.useState)([]);
9967
+ const [pageDims, setPageDims] = (0, import_react41.useState)({ width: 612, height: 792 });
9968
+ const [isLoadingPages, setIsLoadingPages] = (0, import_react41.useState)(false);
9969
+ const flipBookRef = (0, import_react41.useRef)(null);
9970
+ const isSyncingRef = (0, import_react41.useRef)(false);
9971
+ (0, import_react41.useEffect)(() => {
9972
+ if (!document2) {
9973
+ setPages([]);
9974
+ return;
9975
+ }
9976
+ let cancelled = false;
9977
+ const loadAllPages = async () => {
9978
+ setIsLoadingPages(true);
9979
+ try {
9980
+ const pagePromises = [];
9981
+ for (let i = 1; i <= numPages; i++) {
9982
+ pagePromises.push(document2.getPage(i));
9983
+ }
9984
+ const results = await Promise.allSettled(pagePromises);
9985
+ if (!cancelled) {
9986
+ const loaded = results.map((r) => r.status === "fulfilled" ? r.value : null);
9987
+ setPages(loaded);
9988
+ const firstPage = loaded[0];
9989
+ if (firstPage) {
9990
+ const vp = firstPage.getViewport({ scale, rotation });
9991
+ setPageDims({ width: Math.floor(vp.width), height: Math.floor(vp.height) });
9992
+ }
9993
+ }
9994
+ } catch {
9995
+ } finally {
9996
+ if (!cancelled) setIsLoadingPages(false);
9997
+ }
9998
+ };
9999
+ loadAllPages();
10000
+ return () => {
10001
+ cancelled = true;
10002
+ };
10003
+ }, [document2, numPages, scale, rotation]);
10004
+ (0, import_react41.useEffect)(() => {
10005
+ if (pages[0]) {
10006
+ const vp = pages[0].getViewport({ scale, rotation });
10007
+ setPageDims({ width: Math.floor(vp.width), height: Math.floor(vp.height) });
10008
+ }
10009
+ }, [pages, scale, rotation]);
10010
+ (0, import_react41.useEffect)(() => {
10011
+ const pageFlip = flipBookRef.current?.pageFlip();
10012
+ if (!pageFlip) return;
10013
+ const flipBookPage = pageFlip.getCurrentPageIndex();
10014
+ const targetIndex = currentPage - 1;
10015
+ if (flipBookPage !== targetIndex) {
10016
+ isSyncingRef.current = true;
10017
+ pageFlip.turnToPage(targetIndex);
10018
+ setTimeout(() => {
10019
+ isSyncingRef.current = false;
10020
+ }, 100);
10021
+ }
10022
+ }, [currentPage]);
10023
+ (0, import_react41.useEffect)(() => {
10024
+ if (scrollToPageRequest) {
10025
+ requestAnimationFrame(() => {
10026
+ viewerStore.getState().completeScrollRequest(scrollToPageRequest.requestId);
10027
+ });
10028
+ }
10029
+ }, [scrollToPageRequest, viewerStore]);
10030
+ const handleFlip = (0, import_react41.useCallback)((e) => {
10031
+ if (isSyncingRef.current) return;
10032
+ const newPage = e.data + 1;
10033
+ if (newPage !== currentPage && newPage >= 1 && newPage <= numPages) {
10034
+ goToPage(newPage);
10035
+ }
10036
+ }, [currentPage, numPages, goToPage]);
10037
+ const themeStyles = {
10038
+ light: "bg-gray-100",
10039
+ dark: "bg-gray-900",
10040
+ sepia: "bg-amber-50"
10041
+ };
10042
+ const themeClass = theme === "dark" ? "dark" : theme === "sepia" ? "sepia" : "";
10043
+ if (!document2) {
10044
+ return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { className: cn("document-container", "flex-1", themeStyles[theme], className), children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(PDFLoadingScreen, { phase: isLoading ? "fetching" : "initializing" }) });
10045
+ }
10046
+ if (isLoadingPages || pages.length === 0) {
10047
+ return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { className: cn("document-container", "flex-1", themeStyles[theme], className), children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(PDFLoadingScreen, { phase: "rendering" }) });
10048
+ }
10049
+ return /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(
10050
+ "div",
10051
+ {
10052
+ className: cn(
10053
+ "book-mode-container",
10054
+ "flex-1 overflow-hidden",
10055
+ "flex items-center justify-center",
10056
+ themeStyles[theme],
10057
+ themeClass,
10058
+ className
10059
+ ),
10060
+ style: { userSelect: "none", WebkitUserSelect: "none" },
10061
+ children: [
10062
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
10063
+ import_react_pageflip.default,
10064
+ {
10065
+ ref: flipBookRef,
10066
+ width: pageDims.width,
10067
+ height: pageDims.height,
10068
+ size: "stretch",
10069
+ minWidth: 300,
10070
+ maxWidth: pageDims.width,
10071
+ minHeight: 400,
10072
+ maxHeight: pageDims.height,
10073
+ drawShadow,
10074
+ maxShadowOpacity,
10075
+ flippingTime,
10076
+ usePortrait: true,
10077
+ startPage: currentPage - 1,
10078
+ showCover: false,
10079
+ mobileScrollSupport: false,
10080
+ swipeDistance: 30,
10081
+ showPageCorners: true,
10082
+ useMouseEvents: true,
10083
+ clickEventForward: false,
10084
+ onFlip: handleFlip,
10085
+ className: "book-flipbook",
10086
+ style: {},
10087
+ startZIndex: 0,
10088
+ autoSize: true,
10089
+ renderOnlyPageLengthChange: false,
10090
+ disableFlipByClick: false,
10091
+ children: pages.map((page, index) => /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
10092
+ BookPage,
10093
+ {
10094
+ pageNumber: index + 1,
10095
+ page,
10096
+ scale,
10097
+ rotation,
10098
+ width: pageDims.width,
10099
+ height: pageDims.height
10100
+ },
10101
+ index
10102
+ ))
10103
+ }
10104
+ ),
10105
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "book-page-indicator", children: [
10106
+ currentPage,
10107
+ " / ",
10108
+ numPages
10109
+ ] })
9496
10110
  ]
9497
10111
  }
9498
10112
  );
@@ -9501,15 +10115,15 @@ var init_DualPageContainer = __esm({
9501
10115
  });
9502
10116
 
9503
10117
  // src/components/FloatingZoomControls/FloatingZoomControls.tsx
9504
- var import_react40, import_jsx_runtime26, FloatingZoomControls;
10118
+ var import_react42, import_jsx_runtime28, FloatingZoomControls;
9505
10119
  var init_FloatingZoomControls = __esm({
9506
10120
  "src/components/FloatingZoomControls/FloatingZoomControls.tsx"() {
9507
10121
  "use strict";
9508
- import_react40 = require("react");
10122
+ import_react42 = require("react");
9509
10123
  init_hooks();
9510
10124
  init_utils();
9511
- import_jsx_runtime26 = require("react/jsx-runtime");
9512
- FloatingZoomControls = (0, import_react40.memo)(function FloatingZoomControls2({
10125
+ import_jsx_runtime28 = require("react/jsx-runtime");
10126
+ FloatingZoomControls = (0, import_react42.memo)(function FloatingZoomControls2({
9513
10127
  position = "bottom-right",
9514
10128
  className,
9515
10129
  showFitToWidth = true,
@@ -9519,20 +10133,20 @@ var init_FloatingZoomControls = __esm({
9519
10133
  const { viewerStore } = usePDFViewerStores();
9520
10134
  const scale = useViewerStore((s) => s.scale);
9521
10135
  const document2 = useViewerStore((s) => s.document);
9522
- const handleZoomIn = (0, import_react40.useCallback)(() => {
10136
+ const handleZoomIn = (0, import_react42.useCallback)(() => {
9523
10137
  const currentScale = viewerStore.getState().scale;
9524
10138
  const newScale = Math.min(4, currentScale + 0.05);
9525
10139
  viewerStore.getState().setScale(newScale);
9526
10140
  }, [viewerStore]);
9527
- const handleZoomOut = (0, import_react40.useCallback)(() => {
10141
+ const handleZoomOut = (0, import_react42.useCallback)(() => {
9528
10142
  const currentScale = viewerStore.getState().scale;
9529
10143
  const newScale = Math.max(0.1, currentScale - 0.05);
9530
10144
  viewerStore.getState().setScale(newScale);
9531
10145
  }, [viewerStore]);
9532
- const handleFitToWidth = (0, import_react40.useCallback)(() => {
10146
+ const handleFitToWidth = (0, import_react42.useCallback)(() => {
9533
10147
  viewerStore.getState().setScale(1);
9534
10148
  }, [viewerStore]);
9535
- const handleFitToPage = (0, import_react40.useCallback)(() => {
10149
+ const handleFitToPage = (0, import_react42.useCallback)(() => {
9536
10150
  viewerStore.getState().setScale(0.75);
9537
10151
  }, [viewerStore]);
9538
10152
  if (!document2) return null;
@@ -9543,7 +10157,7 @@ var init_FloatingZoomControls = __esm({
9543
10157
  "top-left": "top-4 left-4"
9544
10158
  };
9545
10159
  const zoomPercentage = Math.round(scale * 100);
9546
- return /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(
10160
+ return /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(
9547
10161
  "div",
9548
10162
  {
9549
10163
  className: cn(
@@ -9555,7 +10169,7 @@ var init_FloatingZoomControls = __esm({
9555
10169
  className
9556
10170
  ),
9557
10171
  children: [
9558
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
10172
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
9559
10173
  "button",
9560
10174
  {
9561
10175
  onClick: handleZoomOut,
@@ -9569,14 +10183,14 @@ var init_FloatingZoomControls = __esm({
9569
10183
  disabled: scale <= 0.25,
9570
10184
  title: "Zoom Out",
9571
10185
  "aria-label": "Zoom Out",
9572
- children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M20 12H4" }) })
10186
+ children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M20 12H4" }) })
9573
10187
  }
9574
10188
  ),
9575
- showZoomLevel && /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("span", { className: "min-w-[48px] text-center text-sm font-medium text-gray-700 dark:text-gray-300", children: [
10189
+ showZoomLevel && /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("span", { className: "min-w-[48px] text-center text-sm font-medium text-gray-700 dark:text-gray-300", children: [
9576
10190
  zoomPercentage,
9577
10191
  "%"
9578
10192
  ] }),
9579
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
10193
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
9580
10194
  "button",
9581
10195
  {
9582
10196
  onClick: handleZoomIn,
@@ -9590,11 +10204,11 @@ var init_FloatingZoomControls = __esm({
9590
10204
  disabled: scale >= 4,
9591
10205
  title: "Zoom In",
9592
10206
  "aria-label": "Zoom In",
9593
- children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M12 4v16m8-8H4" }) })
10207
+ children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M12 4v16m8-8H4" }) })
9594
10208
  }
9595
10209
  ),
9596
- (showFitToWidth || showFitToPage) && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { className: "w-px h-6 bg-gray-200 dark:bg-gray-700 mx-1" }),
9597
- showFitToWidth && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
10210
+ (showFitToWidth || showFitToPage) && /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { className: "w-px h-6 bg-gray-200 dark:bg-gray-700 mx-1" }),
10211
+ showFitToWidth && /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
9598
10212
  "button",
9599
10213
  {
9600
10214
  onClick: handleFitToWidth,
@@ -9606,10 +10220,10 @@ var init_FloatingZoomControls = __esm({
9606
10220
  ),
9607
10221
  title: "Fit to Width",
9608
10222
  "aria-label": "Fit to Width",
9609
- children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("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" }) })
10223
+ children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("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" }) })
9610
10224
  }
9611
10225
  ),
9612
- showFitToPage && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
10226
+ showFitToPage && /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
9613
10227
  "button",
9614
10228
  {
9615
10229
  onClick: handleFitToPage,
@@ -9621,7 +10235,7 @@ var init_FloatingZoomControls = __esm({
9621
10235
  ),
9622
10236
  title: "Fit to Page",
9623
10237
  "aria-label": "Fit to Page",
9624
- children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("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" }) })
10238
+ children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("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" }) })
9625
10239
  }
9626
10240
  )
9627
10241
  ]
@@ -9683,11 +10297,11 @@ function calculateMatchRects3(textItems, startOffset, length, viewport) {
9683
10297
  }
9684
10298
  return rects;
9685
10299
  }
9686
- var import_react41, import_jsx_runtime27, PDFViewerInner, PDFViewerInnerWithRef, PDFViewerClient;
10300
+ var import_react43, import_jsx_runtime29, PDFViewerInner, PDFViewerInnerWithRef, PDFViewerClient;
9687
10301
  var init_PDFViewerClient = __esm({
9688
10302
  "src/components/PDFViewer/PDFViewerClient.tsx"() {
9689
10303
  "use strict";
9690
- import_react41 = require("react");
10304
+ import_react43 = require("react");
9691
10305
  init_hooks();
9692
10306
  init_utils();
9693
10307
  init_Toolbar2();
@@ -9696,11 +10310,12 @@ var init_PDFViewerClient = __esm({
9696
10310
  init_DocumentContainer();
9697
10311
  init_ContinuousScrollContainer();
9698
10312
  init_DualPageContainer();
10313
+ init_BookModeContainer();
9699
10314
  init_FloatingZoomControls2();
9700
10315
  init_PDFLoadingScreen2();
9701
10316
  init_utils();
9702
- import_jsx_runtime27 = require("react/jsx-runtime");
9703
- PDFViewerInner = (0, import_react41.memo)(function PDFViewerInner2({
10317
+ import_jsx_runtime29 = require("react/jsx-runtime");
10318
+ PDFViewerInner = (0, import_react43.memo)(function PDFViewerInner2({
9704
10319
  src,
9705
10320
  initialPage = 1,
9706
10321
  page: controlledPage,
@@ -9727,19 +10342,19 @@ var init_PDFViewerClient = __esm({
9727
10342
  onReady
9728
10343
  }) {
9729
10344
  const { viewerStore, annotationStore, searchStore } = usePDFViewerStores();
9730
- const mountedRef = (0, import_react41.useRef)(true);
9731
- const [, setLoadState] = (0, import_react41.useState)("idle");
9732
- const onDocumentLoadRef = (0, import_react41.useRef)(onDocumentLoad);
9733
- const onErrorRef = (0, import_react41.useRef)(onError);
9734
- const onPageChangeRef = (0, import_react41.useRef)(onPageChange);
9735
- const onScaleChangeRef = (0, import_react41.useRef)(onScaleChange);
9736
- const onZoomChangeRef = (0, import_react41.useRef)(onZoomChange);
9737
- const onPageRenderStartRef = (0, import_react41.useRef)(onPageRenderStart);
9738
- const onPageRenderCompleteRef = (0, import_react41.useRef)(onPageRenderComplete);
9739
- const onHighlightAddedRef = (0, import_react41.useRef)(onHighlightAdded);
9740
- const onHighlightRemovedRef = (0, import_react41.useRef)(onHighlightRemoved);
9741
- const onAnnotationAddedRef = (0, import_react41.useRef)(onAnnotationAdded);
9742
- const onReadyRef = (0, import_react41.useRef)(onReady);
10345
+ const mountedRef = (0, import_react43.useRef)(true);
10346
+ const [, setLoadState] = (0, import_react43.useState)("idle");
10347
+ const onDocumentLoadRef = (0, import_react43.useRef)(onDocumentLoad);
10348
+ const onErrorRef = (0, import_react43.useRef)(onError);
10349
+ const onPageChangeRef = (0, import_react43.useRef)(onPageChange);
10350
+ const onScaleChangeRef = (0, import_react43.useRef)(onScaleChange);
10351
+ const onZoomChangeRef = (0, import_react43.useRef)(onZoomChange);
10352
+ const onPageRenderStartRef = (0, import_react43.useRef)(onPageRenderStart);
10353
+ const onPageRenderCompleteRef = (0, import_react43.useRef)(onPageRenderComplete);
10354
+ const onHighlightAddedRef = (0, import_react43.useRef)(onHighlightAdded);
10355
+ const onHighlightRemovedRef = (0, import_react43.useRef)(onHighlightRemoved);
10356
+ const onAnnotationAddedRef = (0, import_react43.useRef)(onAnnotationAdded);
10357
+ const onReadyRef = (0, import_react43.useRef)(onReady);
9743
10358
  onDocumentLoadRef.current = onDocumentLoad;
9744
10359
  onErrorRef.current = onError;
9745
10360
  onPageChangeRef.current = onPageChange;
@@ -9752,8 +10367,8 @@ var init_PDFViewerClient = __esm({
9752
10367
  onAnnotationAddedRef.current = onAnnotationAdded;
9753
10368
  onReadyRef.current = onReady;
9754
10369
  const isControlled = controlledPage !== void 0;
9755
- const prevControlledPageRef = (0, import_react41.useRef)(controlledPage);
9756
- const srcIdRef = (0, import_react41.useRef)(null);
10370
+ const prevControlledPageRef = (0, import_react43.useRef)(controlledPage);
10371
+ const srcIdRef = (0, import_react43.useRef)(null);
9757
10372
  const currentPage = useViewerStore((s) => s.currentPage);
9758
10373
  const scale = useViewerStore((s) => s.scale);
9759
10374
  const theme = useViewerStore((s) => s.theme);
@@ -9761,9 +10376,10 @@ var init_PDFViewerClient = __esm({
9761
10376
  const loadingProgress = useViewerStore((s) => s.loadingProgress);
9762
10377
  const error = useViewerStore((s) => s.error);
9763
10378
  const sidebarOpen = useViewerStore((s) => s.sidebarOpen);
10379
+ const streamingProgress = useViewerStore((s) => s.streamingProgress);
9764
10380
  const srcId = getSrcIdentifier(src);
9765
- const handleRef = (0, import_react41.useRef)(null);
9766
- (0, import_react41.useEffect)(() => {
10381
+ const handleRef = (0, import_react43.useRef)(null);
10382
+ (0, import_react43.useEffect)(() => {
9767
10383
  const handle = {
9768
10384
  // ==================== Text Highlighting ====================
9769
10385
  highlightText: async (text, options) => {
@@ -10181,14 +10797,14 @@ var init_PDFViewerClient = __esm({
10181
10797
  handleRef.current = handle;
10182
10798
  onReadyRef.current?.(handle);
10183
10799
  }, [viewerStore, annotationStore, searchStore]);
10184
- const handleRetry = (0, import_react41.useCallback)(() => {
10800
+ const handleRetry = (0, import_react43.useCallback)(() => {
10185
10801
  srcIdRef.current = null;
10186
10802
  viewerStore.getState().setError(null);
10187
10803
  setLoadState("idle");
10188
10804
  }, [viewerStore]);
10189
- const abortControllerRef = (0, import_react41.useRef)(null);
10190
- const currentSrcRef = (0, import_react41.useRef)(null);
10191
- (0, import_react41.useEffect)(() => {
10805
+ const abortControllerRef = (0, import_react43.useRef)(null);
10806
+ const currentSrcRef = (0, import_react43.useRef)(null);
10807
+ (0, import_react43.useEffect)(() => {
10192
10808
  mountedRef.current = true;
10193
10809
  return () => {
10194
10810
  mountedRef.current = false;
@@ -10213,7 +10829,8 @@ var init_PDFViewerClient = __esm({
10213
10829
  viewerStore.getState().setError(null);
10214
10830
  };
10215
10831
  }, [viewerStore]);
10216
- (0, import_react41.useEffect)(() => {
10832
+ const cancelLoaderRef = (0, import_react43.useRef)(null);
10833
+ (0, import_react43.useEffect)(() => {
10217
10834
  if (srcIdRef.current === srcId && viewerStore.getState().document) {
10218
10835
  return;
10219
10836
  }
@@ -10223,6 +10840,10 @@ var init_PDFViewerClient = __esm({
10223
10840
  if (abortControllerRef.current) {
10224
10841
  abortControllerRef.current.abort();
10225
10842
  }
10843
+ if (cancelLoaderRef.current) {
10844
+ cancelLoaderRef.current();
10845
+ cancelLoaderRef.current = null;
10846
+ }
10226
10847
  const abortController = new AbortController();
10227
10848
  abortControllerRef.current = abortController;
10228
10849
  const currentDoc = viewerStore.getState().document;
@@ -10235,100 +10856,130 @@ var init_PDFViewerClient = __esm({
10235
10856
  viewerStore.setState({
10236
10857
  document: null,
10237
10858
  isLoading: true,
10238
- loadingProgress: { phase: "fetching" },
10239
- error: null
10859
+ loadingProgress: { phase: "initializing" },
10860
+ error: null,
10861
+ documentLoadingState: "initializing",
10862
+ firstPageReady: false,
10863
+ streamingProgress: null
10240
10864
  });
10241
10865
  setLoadState("loading");
10242
10866
  let lastProgressUpdate = 0;
10243
10867
  let lastPercent = -1;
10244
10868
  const PROGRESS_THROTTLE_MS = 100;
10245
10869
  const PROGRESS_MIN_CHANGE = 5;
10246
- const loadDoc = async () => {
10247
- if (!mountedRef.current || abortController.signal.aborted) return;
10248
- try {
10249
- const { document: document2, numPages } = await loadDocument({
10250
- src,
10251
- workerSrc,
10252
- signal: abortController.signal,
10253
- onProgress: ({ loaded, total }) => {
10254
- if (!mountedRef.current || srcIdRef.current !== loadId || abortController.signal.aborted) {
10255
- return;
10256
- }
10257
- const now = Date.now();
10258
- const percent = total > 0 ? Math.round(loaded / total * 100) : 0;
10259
- const timePassed = now - lastProgressUpdate >= PROGRESS_THROTTLE_MS;
10260
- const percentChanged = Math.abs(percent - lastPercent) >= PROGRESS_MIN_CHANGE;
10261
- const isComplete = percent >= 100;
10262
- if (timePassed && percentChanged || isComplete) {
10263
- lastProgressUpdate = now;
10264
- lastPercent = percent;
10265
- viewerStore.getState().setLoadingProgress({
10266
- phase: "fetching",
10267
- percent,
10268
- bytesLoaded: loaded,
10269
- totalBytes: total
10270
- });
10271
- }
10272
- }
10273
- });
10274
- if (mountedRef.current && srcIdRef.current === loadId && !abortController.signal.aborted) {
10275
- viewerStore.getState().setDocument(document2);
10276
- setLoadState("loaded");
10277
- if (initialPage !== 1 || typeof initialScale === "number" || initialScale === "page-fit") {
10278
- const updates = {};
10279
- if (initialPage !== 1) {
10280
- updates.currentPage = Math.max(1, Math.min(initialPage, numPages));
10281
- }
10282
- if (typeof initialScale === "number") {
10283
- updates.scale = initialScale;
10284
- } else if (initialScale === "page-fit") {
10285
- updates.scale = 0.75;
10286
- }
10287
- if (Object.keys(updates).length > 0) {
10288
- viewerStore.setState(updates);
10289
- }
10290
- }
10291
- onDocumentLoadRef.current?.({ document: document2, numPages });
10292
- } else {
10293
- document2.destroy();
10870
+ const { promise, cancel } = loadDocumentWithCallbacks({
10871
+ src,
10872
+ workerSrc,
10873
+ signal: abortController.signal,
10874
+ onProgress: ({ loaded, total }) => {
10875
+ if (!mountedRef.current || srcIdRef.current !== loadId || abortController.signal.aborted) {
10876
+ return;
10294
10877
  }
10295
- } catch (err) {
10296
- if (err instanceof DOMException && err.name === "AbortError") {
10878
+ const now = Date.now();
10879
+ const percent = total > 0 ? Math.round(loaded / total * 100) : 0;
10880
+ const timePassed = now - lastProgressUpdate >= PROGRESS_THROTTLE_MS;
10881
+ const percentChanged = Math.abs(percent - lastPercent) >= PROGRESS_MIN_CHANGE;
10882
+ const isComplete = percent >= 100;
10883
+ if (timePassed && percentChanged || isComplete) {
10884
+ lastProgressUpdate = now;
10885
+ lastPercent = percent;
10886
+ viewerStore.setState({
10887
+ loadingProgress: {
10888
+ phase: "fetching",
10889
+ percent,
10890
+ bytesLoaded: loaded,
10891
+ totalBytes: total
10892
+ },
10893
+ streamingProgress: { loaded, total },
10894
+ documentLoadingState: "loading"
10895
+ });
10896
+ }
10897
+ },
10898
+ onDocumentReady: (document2, numPages) => {
10899
+ if (!mountedRef.current || srcIdRef.current !== loadId || abortController.signal.aborted) {
10297
10900
  return;
10298
10901
  }
10299
- const errorMessage = err instanceof Error ? err.message : String(err);
10300
- if (abortController.signal.aborted || errorMessage.includes("network error") || errorMessage.includes("aborted")) {
10902
+ viewerStore.setState({
10903
+ document: document2,
10904
+ numPages,
10905
+ loadingProgress: { phase: "parsing" },
10906
+ documentLoadingState: "loading"
10907
+ });
10908
+ },
10909
+ onFirstPageReady: () => {
10910
+ if (!mountedRef.current || srcIdRef.current !== loadId || abortController.signal.aborted) {
10301
10911
  return;
10302
10912
  }
10303
- if (mountedRef.current && srcIdRef.current === loadId) {
10304
- const error2 = err instanceof Error ? err : new Error("Failed to load document");
10305
- viewerStore.getState().setError(error2);
10306
- setLoadState("error");
10307
- onErrorRef.current?.(error2);
10913
+ viewerStore.setState({
10914
+ isLoading: false,
10915
+ firstPageReady: true,
10916
+ loadingProgress: null,
10917
+ documentLoadingState: "ready"
10918
+ });
10919
+ setLoadState("loaded");
10920
+ }
10921
+ });
10922
+ cancelLoaderRef.current = cancel;
10923
+ promise.then(({ document: document2, numPages }) => {
10924
+ if (mountedRef.current && srcIdRef.current === loadId && !abortController.signal.aborted) {
10925
+ if (!viewerStore.getState().document) {
10926
+ viewerStore.getState().setDocument(document2);
10927
+ }
10928
+ if (initialPage !== 1 || typeof initialScale === "number" || initialScale === "page-fit") {
10929
+ const updates = {};
10930
+ if (initialPage !== 1) {
10931
+ updates.currentPage = Math.max(1, Math.min(initialPage, numPages));
10932
+ }
10933
+ if (typeof initialScale === "number") {
10934
+ updates.scale = initialScale;
10935
+ } else if (initialScale === "page-fit") {
10936
+ updates.scale = 0.75;
10937
+ }
10938
+ if (Object.keys(updates).length > 0) {
10939
+ viewerStore.setState(updates);
10940
+ }
10308
10941
  }
10942
+ onDocumentLoadRef.current?.({ document: document2, numPages });
10309
10943
  }
10310
- };
10311
- loadDoc();
10944
+ }).catch((err) => {
10945
+ if (err instanceof DOMException && err.name === "AbortError") {
10946
+ return;
10947
+ }
10948
+ const errorMessage = err instanceof Error ? err.message : String(err);
10949
+ if (abortController.signal.aborted || errorMessage.includes("network error") || errorMessage.includes("aborted")) {
10950
+ return;
10951
+ }
10952
+ if (mountedRef.current && srcIdRef.current === loadId) {
10953
+ const error2 = err instanceof Error ? err : new Error("Failed to load document");
10954
+ viewerStore.getState().setError(error2);
10955
+ setLoadState("error");
10956
+ onErrorRef.current?.(error2);
10957
+ }
10958
+ });
10312
10959
  return () => {
10313
10960
  abortController.abort();
10961
+ if (cancelLoaderRef.current) {
10962
+ cancelLoaderRef.current();
10963
+ cancelLoaderRef.current = null;
10964
+ }
10314
10965
  };
10315
10966
  }, [srcId, src, workerSrc, initialPage, initialScale, viewerStore]);
10316
- const prevPageRef = (0, import_react41.useRef)(currentPage);
10317
- (0, import_react41.useEffect)(() => {
10967
+ const prevPageRef = (0, import_react43.useRef)(currentPage);
10968
+ (0, import_react43.useEffect)(() => {
10318
10969
  if (prevPageRef.current !== currentPage) {
10319
10970
  prevPageRef.current = currentPage;
10320
10971
  onPageChangeRef.current?.(currentPage);
10321
10972
  }
10322
10973
  }, [currentPage]);
10323
- const prevScaleRef = (0, import_react41.useRef)(scale);
10324
- (0, import_react41.useEffect)(() => {
10974
+ const prevScaleRef = (0, import_react43.useRef)(scale);
10975
+ (0, import_react43.useEffect)(() => {
10325
10976
  if (prevScaleRef.current !== scale) {
10326
10977
  prevScaleRef.current = scale;
10327
10978
  onScaleChangeRef.current?.(scale);
10328
10979
  onZoomChangeRef.current?.(scale);
10329
10980
  }
10330
10981
  }, [scale]);
10331
- (0, import_react41.useEffect)(() => {
10982
+ (0, import_react43.useEffect)(() => {
10332
10983
  if (!isControlled || controlledPage === void 0) return;
10333
10984
  if (prevControlledPageRef.current === controlledPage) return;
10334
10985
  prevControlledPageRef.current = controlledPage;
@@ -10341,7 +10992,7 @@ var init_PDFViewerClient = __esm({
10341
10992
  if (error) {
10342
10993
  if (errorComponent) {
10343
10994
  const errorContent = typeof errorComponent === "function" ? errorComponent(error, handleRetry) : errorComponent;
10344
- return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
10995
+ return /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
10345
10996
  "div",
10346
10997
  {
10347
10998
  className: cn(
@@ -10355,7 +11006,7 @@ var init_PDFViewerClient = __esm({
10355
11006
  }
10356
11007
  );
10357
11008
  }
10358
- return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
11009
+ return /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
10359
11010
  "div",
10360
11011
  {
10361
11012
  className: cn(
@@ -10365,10 +11016,10 @@ var init_PDFViewerClient = __esm({
10365
11016
  themeClass,
10366
11017
  className
10367
11018
  ),
10368
- children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { className: "flex-1 flex items-center justify-center", children: /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "text-center p-8", children: [
10369
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { className: "text-red-500 text-lg font-semibold mb-2", children: "Failed to load PDF" }),
10370
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { className: "text-gray-500 text-sm", children: error.message }),
10371
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
11019
+ children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { className: "flex-1 flex items-center justify-center", children: /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: "text-center p-8", children: [
11020
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { className: "text-red-500 text-lg font-semibold mb-2", children: "Failed to load PDF" }),
11021
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { className: "text-gray-500 text-sm", children: error.message }),
11022
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
10372
11023
  "button",
10373
11024
  {
10374
11025
  onClick: handleRetry,
@@ -10383,15 +11034,17 @@ var init_PDFViewerClient = __esm({
10383
11034
  const renderContainer = () => {
10384
11035
  switch (viewMode) {
10385
11036
  case "continuous":
10386
- return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(ContinuousScrollContainer, {});
11037
+ return /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(ContinuousScrollContainer, {});
10387
11038
  case "dual":
10388
- return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(DualPageContainer, {});
11039
+ return /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(DualPageContainer, {});
11040
+ case "book":
11041
+ return /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(BookModeContainer, {});
10389
11042
  case "single":
10390
11043
  default:
10391
- return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(DocumentContainer, {});
11044
+ return /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(DocumentContainer, {});
10392
11045
  }
10393
11046
  };
10394
- return /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(
11047
+ return /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(
10395
11048
  "div",
10396
11049
  {
10397
11050
  className: cn(
@@ -10403,14 +11056,14 @@ var init_PDFViewerClient = __esm({
10403
11056
  className
10404
11057
  ),
10405
11058
  children: [
10406
- showToolbar && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(Toolbar, {}),
10407
- showAnnotationToolbar && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(AnnotationToolbar, {}),
10408
- /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex flex-1 overflow-hidden", children: [
10409
- showSidebar && sidebarOpen && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(Sidebar, {}),
11059
+ showToolbar && /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(Toolbar, {}),
11060
+ showAnnotationToolbar && /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(AnnotationToolbar, {}),
11061
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: "flex flex-1 overflow-hidden", children: [
11062
+ showSidebar && sidebarOpen && /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(Sidebar, {}),
10410
11063
  renderContainer()
10411
11064
  ] }),
10412
- showFloatingZoom && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(FloatingZoomControls, { position: "bottom-right" }),
10413
- isLoading && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { className: "absolute inset-0 z-50", children: loadingComponent ?? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
11065
+ showFloatingZoom && /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(FloatingZoomControls, { position: "bottom-right" }),
11066
+ isLoading && /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { className: "absolute inset-0 z-50", children: loadingComponent ?? /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
10414
11067
  PDFLoadingScreen,
10415
11068
  {
10416
11069
  phase: loadingProgress?.phase ?? "fetching",
@@ -10418,15 +11071,23 @@ var init_PDFViewerClient = __esm({
10418
11071
  bytesLoaded: loadingProgress?.bytesLoaded,
10419
11072
  totalBytes: loadingProgress?.totalBytes
10420
11073
  }
10421
- ) })
11074
+ ) }),
11075
+ !isLoading && streamingProgress && streamingProgress.total > 0 && streamingProgress.loaded < streamingProgress.total && /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("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: [
11076
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { className: "w-3 h-3 border-2 border-white/30 border-t-white rounded-full animate-spin" }),
11077
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { children: "Loading pages..." }),
11078
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("span", { className: "text-white/60", children: [
11079
+ Math.round(streamingProgress.loaded / streamingProgress.total * 100),
11080
+ "%"
11081
+ ] })
11082
+ ] })
10422
11083
  ]
10423
11084
  }
10424
11085
  );
10425
11086
  });
10426
- PDFViewerInnerWithRef = (0, import_react41.forwardRef)(
11087
+ PDFViewerInnerWithRef = (0, import_react43.forwardRef)(
10427
11088
  function PDFViewerInnerWithRef2(props, ref) {
10428
- const handleRef = (0, import_react41.useRef)(null);
10429
- const handleReady = (0, import_react41.useCallback)((handle) => {
11089
+ const handleRef = (0, import_react43.useRef)(null);
11090
+ const handleReady = (0, import_react43.useCallback)((handle) => {
10430
11091
  handleRef.current = handle;
10431
11092
  if (typeof ref === "function") {
10432
11093
  ref(handle);
@@ -10434,17 +11095,17 @@ var init_PDFViewerClient = __esm({
10434
11095
  ref.current = handle;
10435
11096
  }
10436
11097
  }, [ref]);
10437
- return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(PDFViewerInner, { ...props, onReady: handleReady });
11098
+ return /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(PDFViewerInner, { ...props, onReady: handleReady });
10438
11099
  }
10439
11100
  );
10440
- PDFViewerClient = (0, import_react41.memo)(
10441
- (0, import_react41.forwardRef)(function PDFViewerClient2(props, ref) {
10442
- return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
11101
+ PDFViewerClient = (0, import_react43.memo)(
11102
+ (0, import_react43.forwardRef)(function PDFViewerClient2(props, ref) {
11103
+ return /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
10443
11104
  PDFViewerProvider,
10444
11105
  {
10445
11106
  theme: props.theme,
10446
11107
  defaultSidebarPanel: props.defaultSidebarPanel,
10447
- children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(PDFViewerInnerWithRef, { ref, ...props })
11108
+ children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(PDFViewerInnerWithRef, { ref, ...props })
10448
11109
  }
10449
11110
  );
10450
11111
  })
@@ -10453,20 +11114,20 @@ var init_PDFViewerClient = __esm({
10453
11114
  });
10454
11115
 
10455
11116
  // src/components/PDFViewer/PDFViewer.tsx
10456
- var import_react42, import_jsx_runtime28, PDFViewerClient3, PDFViewerLoading, PDFViewer;
11117
+ var import_react44, import_jsx_runtime30, PDFViewerClient3, PDFViewerLoading, PDFViewer;
10457
11118
  var init_PDFViewer = __esm({
10458
11119
  "src/components/PDFViewer/PDFViewer.tsx"() {
10459
11120
  "use strict";
10460
- import_react42 = require("react");
11121
+ import_react44 = require("react");
10461
11122
  init_utils();
10462
- import_jsx_runtime28 = require("react/jsx-runtime");
10463
- PDFViewerClient3 = (0, import_react42.lazy)(
11123
+ import_jsx_runtime30 = require("react/jsx-runtime");
11124
+ PDFViewerClient3 = (0, import_react44.lazy)(
10464
11125
  () => Promise.resolve().then(() => (init_PDFViewerClient(), PDFViewerClient_exports)).then((mod) => ({ default: mod.PDFViewerClient }))
10465
11126
  );
10466
- PDFViewerLoading = (0, import_react42.memo)(function PDFViewerLoading2({
11127
+ PDFViewerLoading = (0, import_react44.memo)(function PDFViewerLoading2({
10467
11128
  className
10468
11129
  }) {
10469
- return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
11130
+ return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
10470
11131
  "div",
10471
11132
  {
10472
11133
  className: cn(
@@ -10475,18 +11136,18 @@ var init_PDFViewer = __esm({
10475
11136
  "bg-white dark:bg-gray-900",
10476
11137
  className
10477
11138
  ),
10478
- children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { className: "flex-1 flex items-center justify-center", children: /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "flex flex-col items-center", children: [
10479
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { className: "w-8 h-8 border-4 border-blue-500 border-t-transparent rounded-full animate-spin" }),
10480
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { className: "mt-2 text-sm text-gray-500", children: "Loading PDF viewer..." })
11139
+ children: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("div", { className: "flex-1 flex items-center justify-center", children: /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "flex flex-col items-center", children: [
11140
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("div", { className: "w-8 h-8 border-4 border-blue-500 border-t-transparent rounded-full animate-spin" }),
11141
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("div", { className: "mt-2 text-sm text-gray-500", children: "Loading PDF viewer..." })
10481
11142
  ] }) })
10482
11143
  }
10483
11144
  );
10484
11145
  });
10485
- PDFViewer = (0, import_react42.memo)(function PDFViewer2(props) {
11146
+ PDFViewer = (0, import_react44.memo)(function PDFViewer2(props) {
10486
11147
  if (typeof window === "undefined") {
10487
- return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(PDFViewerLoading, { className: props.className });
11148
+ return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(PDFViewerLoading, { className: props.className });
10488
11149
  }
10489
- return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_react42.Suspense, { fallback: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(PDFViewerLoading, { className: props.className }), children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(PDFViewerClient3, { ...props }) });
11150
+ return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(import_react44.Suspense, { fallback: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(PDFViewerLoading, { className: props.className }), children: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(PDFViewerClient3, { ...props }) });
10490
11151
  });
10491
11152
  }
10492
11153
  });
@@ -10501,6 +11162,7 @@ var init_PDFViewer2 = __esm({
10501
11162
  init_VirtualizedDocumentContainer();
10502
11163
  init_ContinuousScrollContainer();
10503
11164
  init_DualPageContainer();
11165
+ init_BookModeContainer();
10504
11166
  }
10505
11167
  });
10506
11168
 
@@ -10511,6 +11173,7 @@ __export(index_exports, {
10511
11173
  AnnotationToolbar: () => AnnotationToolbar,
10512
11174
  AskAboutOverlay: () => AskAboutOverlay,
10513
11175
  AskAboutTrigger: () => AskAboutTrigger,
11176
+ BookModeContainer: () => BookModeContainer,
10514
11177
  BookmarksPanel: () => BookmarksPanel,
10515
11178
  CanvasLayer: () => CanvasLayer,
10516
11179
  ContinuousScrollContainer: () => ContinuousScrollContainer,
@@ -10589,6 +11252,7 @@ __export(index_exports, {
10589
11252
  isPDFJSInitialized: () => isPDFJSInitialized,
10590
11253
  isPointInRect: () => isPointInRect,
10591
11254
  loadDocument: () => loadDocument,
11255
+ loadDocumentWithCallbacks: () => loadDocumentWithCallbacks,
10592
11256
  loadHighlights: () => loadHighlights,
10593
11257
  loadStudentData: () => loadStudentData,
10594
11258
  mergeAdjacentRects: () => mergeAdjacentRects,
@@ -10597,6 +11261,7 @@ __export(index_exports, {
10597
11261
  pdfjsLib: () => pdfjsLib,
10598
11262
  percentToPDF: () => percentToPDF,
10599
11263
  percentToViewport: () => percentToViewport,
11264
+ playPageTurnSound: () => playPageTurnSound,
10600
11265
  quickViewer: () => quickViewer,
10601
11266
  removeRotation: () => removeRotation,
10602
11267
  saveHighlights: () => saveHighlights,
@@ -10639,9 +11304,9 @@ init_HighlightPopover2();
10639
11304
  init_AnnotationToolbar2();
10640
11305
 
10641
11306
  // src/components/Annotations/StickyNote.tsx
10642
- var import_react43 = require("react");
11307
+ var import_react45 = require("react");
10643
11308
  init_utils();
10644
- var import_jsx_runtime29 = require("react/jsx-runtime");
11309
+ var import_jsx_runtime31 = require("react/jsx-runtime");
10645
11310
  var NOTE_COLORS = [
10646
11311
  "#fef08a",
10647
11312
  // yellow
@@ -10654,7 +11319,7 @@ var NOTE_COLORS = [
10654
11319
  "#fed7aa"
10655
11320
  // orange
10656
11321
  ];
10657
- var StickyNote = (0, import_react43.memo)(function StickyNote2({
11322
+ var StickyNote = (0, import_react45.memo)(function StickyNote2({
10658
11323
  note,
10659
11324
  scale,
10660
11325
  isSelected,
@@ -10667,37 +11332,37 @@ var StickyNote = (0, import_react43.memo)(function StickyNote2({
10667
11332
  onDragStart,
10668
11333
  className
10669
11334
  }) {
10670
- const [isExpanded, setIsExpanded] = (0, import_react43.useState)(false);
10671
- const [localContent, setLocalContent] = (0, import_react43.useState)(note.content);
10672
- const textareaRef = (0, import_react43.useRef)(null);
10673
- const noteRef = (0, import_react43.useRef)(null);
10674
- (0, import_react43.useEffect)(() => {
11335
+ const [isExpanded, setIsExpanded] = (0, import_react45.useState)(false);
11336
+ const [localContent, setLocalContent] = (0, import_react45.useState)(note.content);
11337
+ const textareaRef = (0, import_react45.useRef)(null);
11338
+ const noteRef = (0, import_react45.useRef)(null);
11339
+ (0, import_react45.useEffect)(() => {
10675
11340
  setLocalContent(note.content);
10676
11341
  }, [note.content]);
10677
- (0, import_react43.useEffect)(() => {
11342
+ (0, import_react45.useEffect)(() => {
10678
11343
  if (isEditing && textareaRef.current) {
10679
11344
  textareaRef.current.focus();
10680
11345
  textareaRef.current.select();
10681
11346
  }
10682
11347
  }, [isEditing]);
10683
- const handleClick = (0, import_react43.useCallback)((e) => {
11348
+ const handleClick = (0, import_react45.useCallback)((e) => {
10684
11349
  e.stopPropagation();
10685
11350
  onSelect?.();
10686
11351
  if (!isExpanded) {
10687
11352
  setIsExpanded(true);
10688
11353
  }
10689
11354
  }, [isExpanded, onSelect]);
10690
- const handleDoubleClick = (0, import_react43.useCallback)((e) => {
11355
+ const handleDoubleClick = (0, import_react45.useCallback)((e) => {
10691
11356
  e.stopPropagation();
10692
11357
  onStartEdit?.();
10693
11358
  }, [onStartEdit]);
10694
- const handleBlur = (0, import_react43.useCallback)(() => {
11359
+ const handleBlur = (0, import_react45.useCallback)(() => {
10695
11360
  if (isEditing && localContent !== note.content) {
10696
11361
  onUpdate?.({ content: localContent });
10697
11362
  }
10698
11363
  onEndEdit?.();
10699
11364
  }, [isEditing, localContent, note.content, onUpdate, onEndEdit]);
10700
- const handleKeyDown = (0, import_react43.useCallback)((e) => {
11365
+ const handleKeyDown = (0, import_react45.useCallback)((e) => {
10701
11366
  if (e.key === "Escape") {
10702
11367
  setLocalContent(note.content);
10703
11368
  onEndEdit?.();
@@ -10705,16 +11370,16 @@ var StickyNote = (0, import_react43.memo)(function StickyNote2({
10705
11370
  handleBlur();
10706
11371
  }
10707
11372
  }, [note.content, onEndEdit, handleBlur]);
10708
- const handleColorChange = (0, import_react43.useCallback)((color) => {
11373
+ const handleColorChange = (0, import_react45.useCallback)((color) => {
10709
11374
  onUpdate?.({ color });
10710
11375
  }, [onUpdate]);
10711
- const handleCollapse = (0, import_react43.useCallback)((e) => {
11376
+ const handleCollapse = (0, import_react45.useCallback)((e) => {
10712
11377
  e.stopPropagation();
10713
11378
  setIsExpanded(false);
10714
11379
  onEndEdit?.();
10715
11380
  }, [onEndEdit]);
10716
11381
  if (!isExpanded) {
10717
- return /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
11382
+ return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
10718
11383
  "div",
10719
11384
  {
10720
11385
  ref: noteRef,
@@ -10735,14 +11400,14 @@ var StickyNote = (0, import_react43.memo)(function StickyNote2({
10735
11400
  onMouseDown: onDragStart,
10736
11401
  onTouchStart: onDragStart,
10737
11402
  title: note.content || "Empty note",
10738
- children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
11403
+ children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
10739
11404
  "svg",
10740
11405
  {
10741
11406
  className: "w-4 h-4 opacity-70",
10742
11407
  fill: "currentColor",
10743
11408
  viewBox: "0 0 20 20",
10744
11409
  style: { color: "#333" },
10745
- children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
11410
+ children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
10746
11411
  "path",
10747
11412
  {
10748
11413
  fillRule: "evenodd",
@@ -10755,7 +11420,7 @@ var StickyNote = (0, import_react43.memo)(function StickyNote2({
10755
11420
  }
10756
11421
  );
10757
11422
  }
10758
- return /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(
11423
+ return /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(
10759
11424
  "div",
10760
11425
  {
10761
11426
  ref: noteRef,
@@ -10773,14 +11438,14 @@ var StickyNote = (0, import_react43.memo)(function StickyNote2({
10773
11438
  },
10774
11439
  onClick: handleClick,
10775
11440
  children: [
10776
- /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(
11441
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(
10777
11442
  "div",
10778
11443
  {
10779
11444
  className: "flex items-center justify-between px-2 py-1 border-b border-black/10 cursor-move",
10780
11445
  onMouseDown: onDragStart,
10781
11446
  onTouchStart: onDragStart,
10782
11447
  children: [
10783
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { className: "flex gap-1", children: NOTE_COLORS.map((color) => /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
11448
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: "flex gap-1", children: NOTE_COLORS.map((color) => /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
10784
11449
  "button",
10785
11450
  {
10786
11451
  className: cn(
@@ -10797,8 +11462,8 @@ var StickyNote = (0, import_react43.memo)(function StickyNote2({
10797
11462
  },
10798
11463
  color
10799
11464
  )) }),
10800
- /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: "flex gap-1", children: [
10801
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
11465
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { className: "flex gap-1", children: [
11466
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
10802
11467
  "button",
10803
11468
  {
10804
11469
  className: "p-0.5 hover:bg-black/10 rounded",
@@ -10807,23 +11472,23 @@ var StickyNote = (0, import_react43.memo)(function StickyNote2({
10807
11472
  onDelete?.();
10808
11473
  },
10809
11474
  title: "Delete note",
10810
- children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("svg", { className: "w-3.5 h-3.5 text-gray-600", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("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" }) })
11475
+ children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("svg", { className: "w-3.5 h-3.5 text-gray-600", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("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" }) })
10811
11476
  }
10812
11477
  ),
10813
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
11478
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
10814
11479
  "button",
10815
11480
  {
10816
11481
  className: "p-0.5 hover:bg-black/10 rounded",
10817
11482
  onClick: handleCollapse,
10818
11483
  title: "Collapse note",
10819
- children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("svg", { className: "w-3.5 h-3.5 text-gray-600", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M6 18L18 6M6 6l12 12" }) })
11484
+ children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("svg", { className: "w-3.5 h-3.5 text-gray-600", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M6 18L18 6M6 6l12 12" }) })
10820
11485
  }
10821
11486
  )
10822
11487
  ] })
10823
11488
  ]
10824
11489
  }
10825
11490
  ),
10826
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { className: "p-2", children: isEditing ? /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
11491
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: "p-2", children: isEditing ? /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
10827
11492
  "textarea",
10828
11493
  {
10829
11494
  ref: textareaRef,
@@ -10838,7 +11503,7 @@ var StickyNote = (0, import_react43.memo)(function StickyNote2({
10838
11503
  onKeyDown: handleKeyDown,
10839
11504
  placeholder: "Enter note..."
10840
11505
  }
10841
- ) : /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
11506
+ ) : /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
10842
11507
  "div",
10843
11508
  {
10844
11509
  className: cn(
@@ -10849,16 +11514,16 @@ var StickyNote = (0, import_react43.memo)(function StickyNote2({
10849
11514
  children: note.content || "Double-click to edit..."
10850
11515
  }
10851
11516
  ) }),
10852
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { className: "px-2 pb-1 text-[10px] text-gray-500", children: new Date(note.updatedAt).toLocaleDateString() })
11517
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: "px-2 pb-1 text-[10px] text-gray-500", children: new Date(note.updatedAt).toLocaleDateString() })
10853
11518
  ]
10854
11519
  }
10855
11520
  );
10856
11521
  });
10857
11522
 
10858
11523
  // src/components/Annotations/DrawingCanvas.tsx
10859
- var import_react44 = require("react");
11524
+ var import_react46 = require("react");
10860
11525
  init_utils();
10861
- var import_jsx_runtime30 = require("react/jsx-runtime");
11526
+ var import_jsx_runtime32 = require("react/jsx-runtime");
10862
11527
  function pointsToSvgPath(points) {
10863
11528
  if (points.length === 0) return "";
10864
11529
  if (points.length === 1) {
@@ -10896,7 +11561,7 @@ function simplifyPath(points, tolerance = 1) {
10896
11561
  result.push(points[points.length - 1]);
10897
11562
  return result;
10898
11563
  }
10899
- var DrawingCanvas = (0, import_react44.memo)(function DrawingCanvas2({
11564
+ var DrawingCanvas = (0, import_react46.memo)(function DrawingCanvas2({
10900
11565
  width,
10901
11566
  height,
10902
11567
  scale,
@@ -10906,10 +11571,10 @@ var DrawingCanvas = (0, import_react44.memo)(function DrawingCanvas2({
10906
11571
  onDrawingComplete,
10907
11572
  className
10908
11573
  }) {
10909
- const svgRef = (0, import_react44.useRef)(null);
10910
- const [isDrawing, setIsDrawing] = (0, import_react44.useState)(false);
10911
- const [currentPath, setCurrentPath] = (0, import_react44.useState)([]);
10912
- const getPoint = (0, import_react44.useCallback)((e) => {
11574
+ const svgRef = (0, import_react46.useRef)(null);
11575
+ const [isDrawing, setIsDrawing] = (0, import_react46.useState)(false);
11576
+ const [currentPath, setCurrentPath] = (0, import_react46.useState)([]);
11577
+ const getPoint = (0, import_react46.useCallback)((e) => {
10913
11578
  if (!svgRef.current) return null;
10914
11579
  const svg = svgRef.current;
10915
11580
  const rect = svg.getBoundingClientRect();
@@ -10929,7 +11594,7 @@ var DrawingCanvas = (0, import_react44.memo)(function DrawingCanvas2({
10929
11594
  y: (clientY - rect.top) / scale
10930
11595
  };
10931
11596
  }, [scale]);
10932
- const handleStart = (0, import_react44.useCallback)((e) => {
11597
+ const handleStart = (0, import_react46.useCallback)((e) => {
10933
11598
  if (!isActive) return;
10934
11599
  const point = getPoint(e);
10935
11600
  if (point) {
@@ -10937,14 +11602,14 @@ var DrawingCanvas = (0, import_react44.memo)(function DrawingCanvas2({
10937
11602
  setCurrentPath([point]);
10938
11603
  }
10939
11604
  }, [isActive, getPoint]);
10940
- const handleMove = (0, import_react44.useCallback)((e) => {
11605
+ const handleMove = (0, import_react46.useCallback)((e) => {
10941
11606
  if (!isDrawing || !isActive) return;
10942
11607
  const point = getPoint(e);
10943
11608
  if (point) {
10944
11609
  setCurrentPath((prev) => [...prev, point]);
10945
11610
  }
10946
11611
  }, [isDrawing, isActive, getPoint]);
10947
- const handleEnd = (0, import_react44.useCallback)(() => {
11612
+ const handleEnd = (0, import_react46.useCallback)(() => {
10948
11613
  if (!isDrawing) return;
10949
11614
  setIsDrawing(false);
10950
11615
  if (currentPath.length >= 2) {
@@ -10953,7 +11618,7 @@ var DrawingCanvas = (0, import_react44.memo)(function DrawingCanvas2({
10953
11618
  }
10954
11619
  setCurrentPath([]);
10955
11620
  }, [isDrawing, currentPath, onDrawingComplete]);
10956
- return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
11621
+ return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
10957
11622
  "svg",
10958
11623
  {
10959
11624
  ref: svgRef,
@@ -10973,7 +11638,7 @@ var DrawingCanvas = (0, import_react44.memo)(function DrawingCanvas2({
10973
11638
  onTouchStart: handleStart,
10974
11639
  onTouchMove: handleMove,
10975
11640
  onTouchEnd: handleEnd,
10976
- children: isDrawing && currentPath.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
11641
+ children: isDrawing && currentPath.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
10977
11642
  "path",
10978
11643
  {
10979
11644
  d: pointsToSvgPath(currentPath),
@@ -10990,10 +11655,10 @@ var DrawingCanvas = (0, import_react44.memo)(function DrawingCanvas2({
10990
11655
  });
10991
11656
 
10992
11657
  // src/components/Annotations/ShapeRenderer.tsx
10993
- var import_react45 = require("react");
11658
+ var import_react47 = require("react");
10994
11659
  init_utils();
10995
- var import_jsx_runtime31 = require("react/jsx-runtime");
10996
- var ShapeRenderer = (0, import_react45.memo)(function ShapeRenderer2({
11660
+ var import_jsx_runtime33 = require("react/jsx-runtime");
11661
+ var ShapeRenderer = (0, import_react47.memo)(function ShapeRenderer2({
10997
11662
  shape,
10998
11663
  scale,
10999
11664
  isSelected,
@@ -11003,18 +11668,18 @@ var ShapeRenderer = (0, import_react45.memo)(function ShapeRenderer2({
11003
11668
  onDelete: _onDelete,
11004
11669
  className
11005
11670
  }) {
11006
- const [_isDragging, setIsDragging] = (0, import_react45.useState)(false);
11007
- const [_isResizing, setIsResizing] = (0, import_react45.useState)(false);
11008
- const [activeHandle, setActiveHandle] = (0, import_react45.useState)(null);
11009
- const startPosRef = (0, import_react45.useRef)({ x: 0, y: 0 });
11010
- const startShapeRef = (0, import_react45.useRef)({ x: 0, y: 0, width: 0, height: 0 });
11671
+ const [_isDragging, setIsDragging] = (0, import_react47.useState)(false);
11672
+ const [_isResizing, setIsResizing] = (0, import_react47.useState)(false);
11673
+ const [activeHandle, setActiveHandle] = (0, import_react47.useState)(null);
11674
+ const startPosRef = (0, import_react47.useRef)({ x: 0, y: 0 });
11675
+ const startShapeRef = (0, import_react47.useRef)({ x: 0, y: 0, width: 0, height: 0 });
11011
11676
  const { shapeType, x, y, width, height, color, strokeWidth, id: _id } = shape;
11012
11677
  const scaledX = x * scale;
11013
11678
  const scaledY = y * scale;
11014
11679
  const scaledWidth = width * scale;
11015
11680
  const scaledHeight = height * scale;
11016
11681
  const scaledStroke = strokeWidth * scale;
11017
- const getResizeHandles = (0, import_react45.useCallback)(() => {
11682
+ const getResizeHandles = (0, import_react47.useCallback)(() => {
11018
11683
  const handleSize = 8;
11019
11684
  const half = handleSize / 2;
11020
11685
  return [
@@ -11028,7 +11693,7 @@ var ShapeRenderer = (0, import_react45.memo)(function ShapeRenderer2({
11028
11693
  { position: "w", cursor: "ew-resize", x: scaledX - half, y: scaledY + scaledHeight / 2 - half }
11029
11694
  ];
11030
11695
  }, [scaledX, scaledY, scaledWidth, scaledHeight]);
11031
- const handleMouseDown = (0, import_react45.useCallback)((e, handle) => {
11696
+ const handleMouseDown = (0, import_react47.useCallback)((e, handle) => {
11032
11697
  e.stopPropagation();
11033
11698
  onSelect?.();
11034
11699
  if (!isEditing) return;
@@ -11104,7 +11769,7 @@ var ShapeRenderer = (0, import_react45.memo)(function ShapeRenderer2({
11104
11769
  document.addEventListener("mousemove", handleMouseMove);
11105
11770
  document.addEventListener("mouseup", handleMouseUp);
11106
11771
  }, [isEditing, x, y, width, height, scale, onSelect, onUpdate]);
11107
- const renderShape2 = (0, import_react45.useCallback)(() => {
11772
+ const renderShape2 = (0, import_react47.useCallback)(() => {
11108
11773
  const commonProps = {
11109
11774
  stroke: color,
11110
11775
  strokeWidth: scaledStroke,
@@ -11116,7 +11781,7 @@ var ShapeRenderer = (0, import_react45.memo)(function ShapeRenderer2({
11116
11781
  };
11117
11782
  switch (shapeType) {
11118
11783
  case "rect":
11119
- return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
11784
+ return /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
11120
11785
  "rect",
11121
11786
  {
11122
11787
  x: scaledX,
@@ -11127,7 +11792,7 @@ var ShapeRenderer = (0, import_react45.memo)(function ShapeRenderer2({
11127
11792
  }
11128
11793
  );
11129
11794
  case "circle":
11130
- return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
11795
+ return /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
11131
11796
  "ellipse",
11132
11797
  {
11133
11798
  cx: scaledX + scaledWidth / 2,
@@ -11138,7 +11803,7 @@ var ShapeRenderer = (0, import_react45.memo)(function ShapeRenderer2({
11138
11803
  }
11139
11804
  );
11140
11805
  case "line":
11141
- return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
11806
+ return /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
11142
11807
  "line",
11143
11808
  {
11144
11809
  x1: scaledX,
@@ -11158,22 +11823,22 @@ var ShapeRenderer = (0, import_react45.memo)(function ShapeRenderer2({
11158
11823
  const arrow1Y = endY - arrowLength * Math.sin(angle - arrowAngle);
11159
11824
  const arrow2X = endX - arrowLength * Math.cos(angle + arrowAngle);
11160
11825
  const arrow2Y = endY - arrowLength * Math.sin(angle + arrowAngle);
11161
- return /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("g", { children: [
11162
- /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("line", { x1: scaledX, y1: scaledY, x2: endX, y2: endY, ...commonProps }),
11163
- /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("line", { x1: endX, y1: endY, x2: arrow1X, y2: arrow1Y, ...commonProps }),
11164
- /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("line", { x1: endX, y1: endY, x2: arrow2X, y2: arrow2Y, ...commonProps })
11826
+ return /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("g", { children: [
11827
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("line", { x1: scaledX, y1: scaledY, x2: endX, y2: endY, ...commonProps }),
11828
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("line", { x1: endX, y1: endY, x2: arrow1X, y2: arrow1Y, ...commonProps }),
11829
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("line", { x1: endX, y1: endY, x2: arrow2X, y2: arrow2Y, ...commonProps })
11165
11830
  ] });
11166
11831
  default:
11167
11832
  return null;
11168
11833
  }
11169
11834
  }, [shapeType, scaledX, scaledY, scaledWidth, scaledHeight, color, scaledStroke, isSelected]);
11170
- return /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(
11835
+ return /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(
11171
11836
  "g",
11172
11837
  {
11173
11838
  className: cn("shape-renderer", className),
11174
11839
  onMouseDown: (e) => handleMouseDown(e),
11175
11840
  children: [
11176
- /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
11841
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
11177
11842
  "rect",
11178
11843
  {
11179
11844
  x: scaledX - 5,
@@ -11186,7 +11851,7 @@ var ShapeRenderer = (0, import_react45.memo)(function ShapeRenderer2({
11186
11851
  }
11187
11852
  ),
11188
11853
  renderShape2(),
11189
- isSelected && /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
11854
+ isSelected && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
11190
11855
  "rect",
11191
11856
  {
11192
11857
  x: scaledX - 2,
@@ -11199,7 +11864,7 @@ var ShapeRenderer = (0, import_react45.memo)(function ShapeRenderer2({
11199
11864
  strokeDasharray: "4 2"
11200
11865
  }
11201
11866
  ),
11202
- isSelected && isEditing && getResizeHandles().map((handle) => /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
11867
+ isSelected && isEditing && getResizeHandles().map((handle) => /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
11203
11868
  "rect",
11204
11869
  {
11205
11870
  x: handle.x,
@@ -11219,7 +11884,7 @@ var ShapeRenderer = (0, import_react45.memo)(function ShapeRenderer2({
11219
11884
  }
11220
11885
  );
11221
11886
  });
11222
- var ShapePreview = (0, import_react45.memo)(function ShapePreview2({
11887
+ var ShapePreview = (0, import_react47.memo)(function ShapePreview2({
11223
11888
  shapeType,
11224
11889
  startPoint,
11225
11890
  endPoint,
@@ -11240,9 +11905,9 @@ var ShapePreview = (0, import_react45.memo)(function ShapePreview2({
11240
11905
  };
11241
11906
  switch (shapeType) {
11242
11907
  case "rect":
11243
- return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("rect", { x, y, width, height, ...commonProps });
11908
+ return /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("rect", { x, y, width, height, ...commonProps });
11244
11909
  case "circle":
11245
- return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
11910
+ return /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
11246
11911
  "ellipse",
11247
11912
  {
11248
11913
  cx: x + width / 2,
@@ -11253,7 +11918,7 @@ var ShapePreview = (0, import_react45.memo)(function ShapePreview2({
11253
11918
  }
11254
11919
  );
11255
11920
  case "line":
11256
- return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
11921
+ return /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
11257
11922
  "line",
11258
11923
  {
11259
11924
  x1: startPoint.x * scale,
@@ -11275,8 +11940,8 @@ var ShapePreview = (0, import_react45.memo)(function ShapePreview2({
11275
11940
  const arrow1Y = endY - arrowLength * Math.sin(angle - arrowAngle);
11276
11941
  const arrow2X = endX - arrowLength * Math.cos(angle + arrowAngle);
11277
11942
  const arrow2Y = endY - arrowLength * Math.sin(angle + arrowAngle);
11278
- return /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("g", { children: [
11279
- /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
11943
+ return /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("g", { children: [
11944
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
11280
11945
  "line",
11281
11946
  {
11282
11947
  x1: startPoint.x * scale,
@@ -11286,8 +11951,8 @@ var ShapePreview = (0, import_react45.memo)(function ShapePreview2({
11286
11951
  ...commonProps
11287
11952
  }
11288
11953
  ),
11289
- /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("line", { x1: endX, y1: endY, x2: arrow1X, y2: arrow1Y, ...commonProps }),
11290
- /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("line", { x1: endX, y1: endY, x2: arrow2X, y2: arrow2Y, ...commonProps })
11954
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("line", { x1: endX, y1: endY, x2: arrow1X, y2: arrow1Y, ...commonProps }),
11955
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("line", { x1: endX, y1: endY, x2: arrow2X, y2: arrow2Y, ...commonProps })
11291
11956
  ] });
11292
11957
  default:
11293
11958
  return null;
@@ -11295,10 +11960,10 @@ var ShapePreview = (0, import_react45.memo)(function ShapePreview2({
11295
11960
  });
11296
11961
 
11297
11962
  // src/components/Annotations/QuickNoteButton.tsx
11298
- var import_react46 = require("react");
11963
+ var import_react48 = require("react");
11299
11964
  init_utils();
11300
- var import_jsx_runtime32 = require("react/jsx-runtime");
11301
- var QuickNoteButton = (0, import_react46.memo)(function QuickNoteButton2({
11965
+ var import_jsx_runtime34 = require("react/jsx-runtime");
11966
+ var QuickNoteButton = (0, import_react48.memo)(function QuickNoteButton2({
11302
11967
  pageNumber,
11303
11968
  scale,
11304
11969
  position = "top-right",
@@ -11306,8 +11971,8 @@ var QuickNoteButton = (0, import_react46.memo)(function QuickNoteButton2({
11306
11971
  className,
11307
11972
  visible = true
11308
11973
  }) {
11309
- const [isHovered, setIsHovered] = (0, import_react46.useState)(false);
11310
- const handleClick = (0, import_react46.useCallback)(
11974
+ const [isHovered, setIsHovered] = (0, import_react48.useState)(false);
11975
+ const handleClick = (0, import_react48.useCallback)(
11311
11976
  (e) => {
11312
11977
  e.stopPropagation();
11313
11978
  const x = position === "top-right" ? 80 : 80;
@@ -11319,7 +11984,7 @@ var QuickNoteButton = (0, import_react46.memo)(function QuickNoteButton2({
11319
11984
  if (!visible) {
11320
11985
  return null;
11321
11986
  }
11322
- return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
11987
+ return /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
11323
11988
  "button",
11324
11989
  {
11325
11990
  onClick: handleClick,
@@ -11341,7 +12006,7 @@ var QuickNoteButton = (0, import_react46.memo)(function QuickNoteButton2({
11341
12006
  ),
11342
12007
  title: "Add quick note",
11343
12008
  "aria-label": "Add quick note",
11344
- children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
12009
+ children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
11345
12010
  "svg",
11346
12011
  {
11347
12012
  className: "w-4 h-4 text-yellow-900",
@@ -11349,7 +12014,7 @@ var QuickNoteButton = (0, import_react46.memo)(function QuickNoteButton2({
11349
12014
  viewBox: "0 0 24 24",
11350
12015
  stroke: "currentColor",
11351
12016
  strokeWidth: 2,
11352
- children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M12 4v16m8-8H4" })
12017
+ children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M12 4v16m8-8H4" })
11353
12018
  }
11354
12019
  )
11355
12020
  }
@@ -11357,10 +12022,10 @@ var QuickNoteButton = (0, import_react46.memo)(function QuickNoteButton2({
11357
12022
  });
11358
12023
 
11359
12024
  // src/components/Annotations/QuickNotePopover.tsx
11360
- var import_react47 = require("react");
12025
+ var import_react49 = require("react");
11361
12026
  init_utils();
11362
- var import_jsx_runtime33 = require("react/jsx-runtime");
11363
- var QuickNotePopover = (0, import_react47.memo)(function QuickNotePopover2({
12027
+ var import_jsx_runtime35 = require("react/jsx-runtime");
12028
+ var QuickNotePopover = (0, import_react49.memo)(function QuickNotePopover2({
11364
12029
  visible,
11365
12030
  position,
11366
12031
  initialContent = "",
@@ -11369,21 +12034,21 @@ var QuickNotePopover = (0, import_react47.memo)(function QuickNotePopover2({
11369
12034
  onCancel,
11370
12035
  className
11371
12036
  }) {
11372
- const [content, setContent] = (0, import_react47.useState)(initialContent);
11373
- const textareaRef = (0, import_react47.useRef)(null);
11374
- const popoverRef = (0, import_react47.useRef)(null);
11375
- const [adjustedPosition, setAdjustedPosition] = (0, import_react47.useState)(position);
11376
- (0, import_react47.useEffect)(() => {
12037
+ const [content, setContent] = (0, import_react49.useState)(initialContent);
12038
+ const textareaRef = (0, import_react49.useRef)(null);
12039
+ const popoverRef = (0, import_react49.useRef)(null);
12040
+ const [adjustedPosition, setAdjustedPosition] = (0, import_react49.useState)(position);
12041
+ (0, import_react49.useEffect)(() => {
11377
12042
  if (visible && textareaRef.current) {
11378
12043
  textareaRef.current.focus();
11379
12044
  }
11380
12045
  }, [visible]);
11381
- (0, import_react47.useEffect)(() => {
12046
+ (0, import_react49.useEffect)(() => {
11382
12047
  if (visible) {
11383
12048
  setContent(initialContent);
11384
12049
  }
11385
12050
  }, [visible, initialContent]);
11386
- (0, import_react47.useEffect)(() => {
12051
+ (0, import_react49.useEffect)(() => {
11387
12052
  if (!visible || !popoverRef.current) return;
11388
12053
  const rect = popoverRef.current.getBoundingClientRect();
11389
12054
  const padding = 10;
@@ -11402,14 +12067,14 @@ var QuickNotePopover = (0, import_react47.memo)(function QuickNotePopover2({
11402
12067
  }
11403
12068
  setAdjustedPosition({ x, y });
11404
12069
  }, [position, visible]);
11405
- const handleSave = (0, import_react47.useCallback)(() => {
12070
+ const handleSave = (0, import_react49.useCallback)(() => {
11406
12071
  if (content.trim()) {
11407
12072
  onSave(content.trim());
11408
12073
  } else {
11409
12074
  onCancel();
11410
12075
  }
11411
12076
  }, [content, onSave, onCancel]);
11412
- const handleKeyDown = (0, import_react47.useCallback)(
12077
+ const handleKeyDown = (0, import_react49.useCallback)(
11413
12078
  (e) => {
11414
12079
  if (e.key === "Enter" && (e.ctrlKey || e.metaKey)) {
11415
12080
  e.preventDefault();
@@ -11424,7 +12089,7 @@ var QuickNotePopover = (0, import_react47.memo)(function QuickNotePopover2({
11424
12089
  if (!visible) {
11425
12090
  return null;
11426
12091
  }
11427
- return /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(
12092
+ return /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)(
11428
12093
  "div",
11429
12094
  {
11430
12095
  ref: popoverRef,
@@ -11443,15 +12108,15 @@ var QuickNotePopover = (0, import_react47.memo)(function QuickNotePopover2({
11443
12108
  top: adjustedPosition.y
11444
12109
  },
11445
12110
  children: [
11446
- agentLastStatement && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("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__ */ (0, import_jsx_runtime33.jsxs)("div", { className: "flex items-start gap-1", children: [
11447
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("svg", { className: "w-3 h-3 mt-0.5 flex-shrink-0", fill: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("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" }) }),
11448
- /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("span", { className: "line-clamp-2", children: [
12111
+ agentLastStatement && /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("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__ */ (0, import_jsx_runtime35.jsxs)("div", { className: "flex items-start gap-1", children: [
12112
+ /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("svg", { className: "w-3 h-3 mt-0.5 flex-shrink-0", fill: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("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" }) }),
12113
+ /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("span", { className: "line-clamp-2", children: [
11449
12114
  "AI discussed: \u201C",
11450
12115
  agentLastStatement,
11451
12116
  "\u201D"
11452
12117
  ] })
11453
12118
  ] }) }),
11454
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
12119
+ /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
11455
12120
  "textarea",
11456
12121
  {
11457
12122
  ref: textareaRef,
@@ -11470,13 +12135,13 @@ var QuickNotePopover = (0, import_react47.memo)(function QuickNotePopover2({
11470
12135
  )
11471
12136
  }
11472
12137
  ),
11473
- /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("div", { className: "flex items-center justify-between mt-2", children: [
11474
- /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("span", { className: "text-xs text-gray-500 dark:text-gray-400", children: [
12138
+ /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("div", { className: "flex items-center justify-between mt-2", children: [
12139
+ /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("span", { className: "text-xs text-gray-500 dark:text-gray-400", children: [
11475
12140
  navigator.platform.includes("Mac") ? "\u2318" : "Ctrl",
11476
12141
  "+Enter to save"
11477
12142
  ] }),
11478
- /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("div", { className: "flex gap-2", children: [
11479
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
12143
+ /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("div", { className: "flex gap-2", children: [
12144
+ /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
11480
12145
  "button",
11481
12146
  {
11482
12147
  onClick: onCancel,
@@ -11489,7 +12154,7 @@ var QuickNotePopover = (0, import_react47.memo)(function QuickNotePopover2({
11489
12154
  children: "Cancel"
11490
12155
  }
11491
12156
  ),
11492
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
12157
+ /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
11493
12158
  "button",
11494
12159
  {
11495
12160
  onClick: handleSave,
@@ -11512,10 +12177,10 @@ var QuickNotePopover = (0, import_react47.memo)(function QuickNotePopover2({
11512
12177
  });
11513
12178
 
11514
12179
  // src/components/AskAbout/AskAboutOverlay.tsx
11515
- var import_react48 = require("react");
12180
+ var import_react50 = require("react");
11516
12181
  init_utils();
11517
- var import_jsx_runtime34 = require("react/jsx-runtime");
11518
- var AskAboutOverlay = (0, import_react48.memo)(function AskAboutOverlay2({
12182
+ var import_jsx_runtime36 = require("react/jsx-runtime");
12183
+ var AskAboutOverlay = (0, import_react50.memo)(function AskAboutOverlay2({
11519
12184
  visible,
11520
12185
  progress,
11521
12186
  position,
@@ -11529,7 +12194,7 @@ var AskAboutOverlay = (0, import_react48.memo)(function AskAboutOverlay2({
11529
12194
  const radius = (size - strokeWidth) / 2;
11530
12195
  const circumference = 2 * Math.PI * radius;
11531
12196
  const strokeDashoffset = circumference * (1 - progress);
11532
- return /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(
12197
+ return /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(
11533
12198
  "div",
11534
12199
  {
11535
12200
  className: cn(
@@ -11542,7 +12207,7 @@ var AskAboutOverlay = (0, import_react48.memo)(function AskAboutOverlay2({
11542
12207
  top: position.y - size / 2
11543
12208
  },
11544
12209
  children: [
11545
- /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(
12210
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(
11546
12211
  "svg",
11547
12212
  {
11548
12213
  width: size,
@@ -11550,7 +12215,7 @@ var AskAboutOverlay = (0, import_react48.memo)(function AskAboutOverlay2({
11550
12215
  viewBox: `0 0 ${size} ${size}`,
11551
12216
  className: "transform -rotate-90",
11552
12217
  children: [
11553
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
12218
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
11554
12219
  "circle",
11555
12220
  {
11556
12221
  cx: size / 2,
@@ -11561,7 +12226,7 @@ var AskAboutOverlay = (0, import_react48.memo)(function AskAboutOverlay2({
11561
12226
  strokeWidth
11562
12227
  }
11563
12228
  ),
11564
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
12229
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
11565
12230
  "circle",
11566
12231
  {
11567
12232
  cx: size / 2,
@@ -11579,12 +12244,12 @@ var AskAboutOverlay = (0, import_react48.memo)(function AskAboutOverlay2({
11579
12244
  ]
11580
12245
  }
11581
12246
  ),
11582
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
12247
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
11583
12248
  "div",
11584
12249
  {
11585
12250
  className: "absolute inset-0 flex items-center justify-center",
11586
12251
  style: { color: progress >= 1 ? "#22c55e" : "white" },
11587
- children: progress >= 1 ? /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
12252
+ children: progress >= 1 ? /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
11588
12253
  "svg",
11589
12254
  {
11590
12255
  width: "24",
@@ -11595,9 +12260,9 @@ var AskAboutOverlay = (0, import_react48.memo)(function AskAboutOverlay2({
11595
12260
  strokeWidth: "2",
11596
12261
  strokeLinecap: "round",
11597
12262
  strokeLinejoin: "round",
11598
- children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("polyline", { points: "20 6 9 17 4 12" })
12263
+ children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("polyline", { points: "20 6 9 17 4 12" })
11599
12264
  }
11600
- ) : /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(
12265
+ ) : /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(
11601
12266
  "svg",
11602
12267
  {
11603
12268
  width: "20",
@@ -11609,9 +12274,9 @@ var AskAboutOverlay = (0, import_react48.memo)(function AskAboutOverlay2({
11609
12274
  strokeLinecap: "round",
11610
12275
  strokeLinejoin: "round",
11611
12276
  children: [
11612
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("circle", { cx: "12", cy: "12", r: "10" }),
11613
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("path", { d: "M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3" }),
11614
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("line", { x1: "12", y1: "17", x2: "12.01", y2: "17" })
12277
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("circle", { cx: "12", cy: "12", r: "10" }),
12278
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("path", { d: "M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3" }),
12279
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("line", { x1: "12", y1: "17", x2: "12.01", y2: "17" })
11615
12280
  ]
11616
12281
  }
11617
12282
  )
@@ -11623,10 +12288,10 @@ var AskAboutOverlay = (0, import_react48.memo)(function AskAboutOverlay2({
11623
12288
  });
11624
12289
 
11625
12290
  // src/components/AskAbout/AskAboutTrigger.tsx
11626
- var import_react49 = require("react");
12291
+ var import_react51 = require("react");
11627
12292
  init_utils();
11628
- var import_jsx_runtime35 = require("react/jsx-runtime");
11629
- var AskAboutTrigger = (0, import_react49.memo)(function AskAboutTrigger2({
12293
+ var import_jsx_runtime37 = require("react/jsx-runtime");
12294
+ var AskAboutTrigger = (0, import_react51.memo)(function AskAboutTrigger2({
11630
12295
  position,
11631
12296
  onConfirm,
11632
12297
  onCancel,
@@ -11634,9 +12299,9 @@ var AskAboutTrigger = (0, import_react49.memo)(function AskAboutTrigger2({
11634
12299
  autoHideDelay = 5e3,
11635
12300
  className
11636
12301
  }) {
11637
- const [adjustedPosition, setAdjustedPosition] = (0, import_react49.useState)(position);
11638
- const triggerRef = (0, import_react49.useRef)(null);
11639
- (0, import_react49.useEffect)(() => {
12302
+ const [adjustedPosition, setAdjustedPosition] = (0, import_react51.useState)(position);
12303
+ const triggerRef = (0, import_react51.useRef)(null);
12304
+ (0, import_react51.useEffect)(() => {
11640
12305
  if (!visible || !triggerRef.current) return;
11641
12306
  const rect = triggerRef.current.getBoundingClientRect();
11642
12307
  const padding = 10;
@@ -11652,19 +12317,19 @@ var AskAboutTrigger = (0, import_react49.memo)(function AskAboutTrigger2({
11652
12317
  }
11653
12318
  setAdjustedPosition({ x, y });
11654
12319
  }, [position, visible]);
11655
- (0, import_react49.useEffect)(() => {
12320
+ (0, import_react51.useEffect)(() => {
11656
12321
  if (!visible || autoHideDelay === 0) return;
11657
12322
  const timer = setTimeout(onCancel, autoHideDelay);
11658
12323
  return () => clearTimeout(timer);
11659
12324
  }, [visible, autoHideDelay, onCancel]);
11660
- const handleConfirm = (0, import_react49.useCallback)(
12325
+ const handleConfirm = (0, import_react51.useCallback)(
11661
12326
  (e) => {
11662
12327
  e.stopPropagation();
11663
12328
  onConfirm();
11664
12329
  },
11665
12330
  [onConfirm]
11666
12331
  );
11667
- const handleCancel = (0, import_react49.useCallback)(
12332
+ const handleCancel = (0, import_react51.useCallback)(
11668
12333
  (e) => {
11669
12334
  e.stopPropagation();
11670
12335
  onCancel();
@@ -11674,7 +12339,7 @@ var AskAboutTrigger = (0, import_react49.memo)(function AskAboutTrigger2({
11674
12339
  if (!visible) {
11675
12340
  return null;
11676
12341
  }
11677
- return /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)(
12342
+ return /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)(
11678
12343
  "div",
11679
12344
  {
11680
12345
  ref: triggerRef,
@@ -11693,8 +12358,8 @@ var AskAboutTrigger = (0, import_react49.memo)(function AskAboutTrigger2({
11693
12358
  transform: "translate(-50%, 0)"
11694
12359
  },
11695
12360
  children: [
11696
- /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("span", { className: "text-sm text-gray-600 dark:text-gray-300 px-2", children: "Ask about this?" }),
11697
- /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
12361
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("span", { className: "text-sm text-gray-600 dark:text-gray-300 px-2", children: "Ask about this?" }),
12362
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
11698
12363
  "button",
11699
12364
  {
11700
12365
  onClick: handleConfirm,
@@ -11707,7 +12372,7 @@ var AskAboutTrigger = (0, import_react49.memo)(function AskAboutTrigger2({
11707
12372
  children: "Ask"
11708
12373
  }
11709
12374
  ),
11710
- /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
12375
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
11711
12376
  "button",
11712
12377
  {
11713
12378
  onClick: handleCancel,
@@ -11727,11 +12392,11 @@ var AskAboutTrigger = (0, import_react49.memo)(function AskAboutTrigger2({
11727
12392
  });
11728
12393
 
11729
12394
  // src/components/Minimap/Minimap.tsx
11730
- var import_react50 = require("react");
12395
+ var import_react52 = require("react");
11731
12396
  init_hooks();
11732
12397
  init_utils();
11733
- var import_jsx_runtime36 = require("react/jsx-runtime");
11734
- var PageIndicator = (0, import_react50.memo)(function PageIndicator2({
12398
+ var import_jsx_runtime38 = require("react/jsx-runtime");
12399
+ var PageIndicator = (0, import_react52.memo)(function PageIndicator2({
11735
12400
  pageNumber,
11736
12401
  status,
11737
12402
  isBookmarked,
@@ -11745,7 +12410,7 @@ var PageIndicator = (0, import_react50.memo)(function PageIndicator2({
11745
12410
  if (status === "visited") return "bg-green-400";
11746
12411
  return "bg-gray-200 dark:bg-gray-700";
11747
12412
  };
11748
- return /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(
12413
+ return /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)(
11749
12414
  "button",
11750
12415
  {
11751
12416
  onClick,
@@ -11761,13 +12426,13 @@ var PageIndicator = (0, import_react50.memo)(function PageIndicator2({
11761
12426
  title: `Page ${pageNumber}${isBookmarked ? " (bookmarked)" : ""}`,
11762
12427
  "aria-label": `Go to page ${pageNumber}`,
11763
12428
  children: [
11764
- isBookmarked && !compact && /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("div", { className: "absolute -top-1 -right-1 w-2 h-2 bg-yellow-500 rounded-full border border-white" }),
11765
- showNumber && !compact && /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("span", { className: "absolute inset-0 flex items-center justify-center text-[8px] font-medium text-white", children: pageNumber })
12429
+ isBookmarked && !compact && /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("div", { className: "absolute -top-1 -right-1 w-2 h-2 bg-yellow-500 rounded-full border border-white" }),
12430
+ showNumber && !compact && /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("span", { className: "absolute inset-0 flex items-center justify-center text-[8px] font-medium text-white", children: pageNumber })
11766
12431
  ]
11767
12432
  }
11768
12433
  );
11769
12434
  });
11770
- var Minimap = (0, import_react50.memo)(function Minimap2({
12435
+ var Minimap = (0, import_react52.memo)(function Minimap2({
11771
12436
  variant = "sidebar",
11772
12437
  floatingPosition = "right",
11773
12438
  maxHeight = 300,
@@ -11780,18 +12445,18 @@ var Minimap = (0, import_react50.memo)(function Minimap2({
11780
12445
  const currentPage = useViewerStore((s) => s.currentPage);
11781
12446
  const numPages = useViewerStore((s) => s.numPages);
11782
12447
  const goToPage = useViewerStore((s) => s.goToPage);
11783
- const bookmarkedPages = (0, import_react50.useMemo)(() => {
12448
+ const bookmarkedPages = (0, import_react52.useMemo)(() => {
11784
12449
  return new Set(bookmarks.map((b) => b.pageNumber));
11785
12450
  }, [bookmarks]);
11786
12451
  const compact = numPages > 50;
11787
- const handlePageClick = (0, import_react50.useCallback)(
12452
+ const handlePageClick = (0, import_react52.useCallback)(
11788
12453
  (pageNumber) => {
11789
12454
  goToPage(pageNumber);
11790
12455
  onPageClick?.(pageNumber);
11791
12456
  },
11792
12457
  [goToPage, onPageClick]
11793
12458
  );
11794
- const getPageStatus = (0, import_react50.useCallback)(
12459
+ const getPageStatus = (0, import_react52.useCallback)(
11795
12460
  (pageNumber) => {
11796
12461
  if (pageNumber === currentPage) return "current";
11797
12462
  if (bookmarkedPages.has(pageNumber)) return "bookmarked";
@@ -11800,11 +12465,11 @@ var Minimap = (0, import_react50.memo)(function Minimap2({
11800
12465
  },
11801
12466
  [currentPage, visitedPages, bookmarkedPages]
11802
12467
  );
11803
- const pageIndicators = (0, import_react50.useMemo)(() => {
12468
+ const pageIndicators = (0, import_react52.useMemo)(() => {
11804
12469
  const pages = [];
11805
12470
  for (let i = 1; i <= numPages; i++) {
11806
12471
  pages.push(
11807
- /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
12472
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
11808
12473
  PageIndicator,
11809
12474
  {
11810
12475
  pageNumber: i,
@@ -11825,16 +12490,16 @@ var Minimap = (0, import_react50.memo)(function Minimap2({
11825
12490
  if (numPages === 0) {
11826
12491
  return null;
11827
12492
  }
11828
- const content = /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(import_jsx_runtime36.Fragment, { children: [
11829
- /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("div", { className: "mb-3", children: [
11830
- /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("div", { className: "flex items-center justify-between text-xs text-gray-500 dark:text-gray-400 mb-1", children: [
11831
- /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("span", { children: "Progress" }),
11832
- /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("span", { children: [
12493
+ const content = /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)(import_jsx_runtime38.Fragment, { children: [
12494
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("div", { className: "mb-3", children: [
12495
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("div", { className: "flex items-center justify-between text-xs text-gray-500 dark:text-gray-400 mb-1", children: [
12496
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("span", { children: "Progress" }),
12497
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("span", { children: [
11833
12498
  progressPercentage,
11834
12499
  "%"
11835
12500
  ] })
11836
12501
  ] }),
11837
- /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("div", { className: "h-1.5 bg-gray-200 dark:bg-gray-700 rounded-full overflow-hidden", children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
12502
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("div", { className: "h-1.5 bg-gray-200 dark:bg-gray-700 rounded-full overflow-hidden", children: /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
11838
12503
  "div",
11839
12504
  {
11840
12505
  className: "h-full bg-green-500 rounded-full transition-all duration-300",
@@ -11842,7 +12507,7 @@ var Minimap = (0, import_react50.memo)(function Minimap2({
11842
12507
  }
11843
12508
  ) })
11844
12509
  ] }),
11845
- /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
12510
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
11846
12511
  "div",
11847
12512
  {
11848
12513
  className: cn(
@@ -11853,21 +12518,21 @@ var Minimap = (0, import_react50.memo)(function Minimap2({
11853
12518
  children: pageIndicators
11854
12519
  }
11855
12520
  ),
11856
- /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("div", { className: "mt-3 pt-2 border-t border-gray-200 dark:border-gray-700", children: /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("div", { className: "flex flex-wrap gap-3 text-xs text-gray-500 dark:text-gray-400", children: [
11857
- /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("div", { className: "flex items-center gap-1", children: [
11858
- /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("div", { className: "w-2 h-2 rounded-sm bg-blue-500" }),
11859
- /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("span", { children: "Current" })
12521
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("div", { className: "mt-3 pt-2 border-t border-gray-200 dark:border-gray-700", children: /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("div", { className: "flex flex-wrap gap-3 text-xs text-gray-500 dark:text-gray-400", children: [
12522
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("div", { className: "flex items-center gap-1", children: [
12523
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("div", { className: "w-2 h-2 rounded-sm bg-blue-500" }),
12524
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("span", { children: "Current" })
11860
12525
  ] }),
11861
- /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("div", { className: "flex items-center gap-1", children: [
11862
- /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("div", { className: "w-2 h-2 rounded-sm bg-green-400" }),
11863
- /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("span", { children: "Visited" })
12526
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("div", { className: "flex items-center gap-1", children: [
12527
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("div", { className: "w-2 h-2 rounded-sm bg-green-400" }),
12528
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("span", { children: "Visited" })
11864
12529
  ] }),
11865
- /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("div", { className: "flex items-center gap-1", children: [
11866
- /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("div", { className: "w-2 h-2 rounded-sm bg-yellow-400" }),
11867
- /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("span", { children: "Bookmarked" })
12530
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("div", { className: "flex items-center gap-1", children: [
12531
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("div", { className: "w-2 h-2 rounded-sm bg-yellow-400" }),
12532
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("span", { children: "Bookmarked" })
11868
12533
  ] })
11869
12534
  ] }) }),
11870
- /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("div", { className: "mt-2 text-xs text-gray-500 dark:text-gray-400", children: [
12535
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("div", { className: "mt-2 text-xs text-gray-500 dark:text-gray-400", children: [
11871
12536
  visitedCount,
11872
12537
  " of ",
11873
12538
  numPages,
@@ -11875,7 +12540,7 @@ var Minimap = (0, import_react50.memo)(function Minimap2({
11875
12540
  ] })
11876
12541
  ] });
11877
12542
  if (variant === "floating") {
11878
- return /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(
12543
+ return /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)(
11879
12544
  "div",
11880
12545
  {
11881
12546
  className: cn(
@@ -11891,13 +12556,13 @@ var Minimap = (0, import_react50.memo)(function Minimap2({
11891
12556
  ),
11892
12557
  style: { maxHeight },
11893
12558
  children: [
11894
- /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("h3", { className: "text-sm font-semibold text-gray-700 dark:text-gray-200 mb-2", children: "Reading Progress" }),
12559
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("h3", { className: "text-sm font-semibold text-gray-700 dark:text-gray-200 mb-2", children: "Reading Progress" }),
11895
12560
  content
11896
12561
  ]
11897
12562
  }
11898
12563
  );
11899
12564
  }
11900
- return /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
12565
+ return /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
11901
12566
  "div",
11902
12567
  {
11903
12568
  className: cn(
@@ -11915,13 +12580,13 @@ var Minimap = (0, import_react50.memo)(function Minimap2({
11915
12580
  init_FloatingZoomControls2();
11916
12581
 
11917
12582
  // src/components/PDFThumbnailNav/PDFThumbnailNav.tsx
11918
- var import_react51 = require("react");
12583
+ var import_react53 = require("react");
11919
12584
  init_hooks();
11920
12585
  init_utils();
11921
- var import_jsx_runtime37 = require("react/jsx-runtime");
12586
+ var import_jsx_runtime39 = require("react/jsx-runtime");
11922
12587
  var DEFAULT_WIDTH = 612;
11923
12588
  var DEFAULT_HEIGHT = 792;
11924
- var PDFThumbnailNav = (0, import_react51.memo)(function PDFThumbnailNav2({
12589
+ var PDFThumbnailNav = (0, import_react53.memo)(function PDFThumbnailNav2({
11925
12590
  thumbnailScale = 0.15,
11926
12591
  orientation = "vertical",
11927
12592
  maxVisible = 10,
@@ -11932,14 +12597,14 @@ var PDFThumbnailNav = (0, import_react51.memo)(function PDFThumbnailNav2({
11932
12597
  }) {
11933
12598
  const { document: document2, numPages, currentPage } = usePDFViewer();
11934
12599
  const { viewerStore } = usePDFViewerStores();
11935
- const containerRef = (0, import_react51.useRef)(null);
11936
- const [thumbnails, setThumbnails] = (0, import_react51.useState)(/* @__PURE__ */ new Map());
11937
- const [visibleRange, setVisibleRange] = (0, import_react51.useState)({ start: 1, end: maxVisible });
11938
- const renderQueueRef = (0, import_react51.useRef)(/* @__PURE__ */ new Set());
11939
- const pageCache = (0, import_react51.useRef)(/* @__PURE__ */ new Map());
12600
+ const containerRef = (0, import_react53.useRef)(null);
12601
+ const [thumbnails, setThumbnails] = (0, import_react53.useState)(/* @__PURE__ */ new Map());
12602
+ const [visibleRange, setVisibleRange] = (0, import_react53.useState)({ start: 1, end: maxVisible });
12603
+ const renderQueueRef = (0, import_react53.useRef)(/* @__PURE__ */ new Set());
12604
+ const pageCache = (0, import_react53.useRef)(/* @__PURE__ */ new Map());
11940
12605
  const thumbnailWidth = Math.floor(DEFAULT_WIDTH * thumbnailScale);
11941
12606
  const thumbnailHeight = Math.floor(DEFAULT_HEIGHT * thumbnailScale);
11942
- const updateVisibleRange = (0, import_react51.useCallback)(() => {
12607
+ const updateVisibleRange = (0, import_react53.useCallback)(() => {
11943
12608
  if (!containerRef.current || numPages === 0) return;
11944
12609
  const container = containerRef.current;
11945
12610
  const isHorizontal2 = orientation === "horizontal";
@@ -11951,7 +12616,7 @@ var PDFThumbnailNav = (0, import_react51.memo)(function PDFThumbnailNav2({
11951
12616
  const lastVisible = Math.min(numPages, firstVisible + visibleCount);
11952
12617
  setVisibleRange({ start: firstVisible, end: lastVisible });
11953
12618
  }, [numPages, orientation, thumbnailWidth, thumbnailHeight, gap]);
11954
- (0, import_react51.useEffect)(() => {
12619
+ (0, import_react53.useEffect)(() => {
11955
12620
  const container = containerRef.current;
11956
12621
  if (!container) return;
11957
12622
  const handleScroll = () => {
@@ -11961,7 +12626,7 @@ var PDFThumbnailNav = (0, import_react51.memo)(function PDFThumbnailNav2({
11961
12626
  updateVisibleRange();
11962
12627
  return () => container.removeEventListener("scroll", handleScroll);
11963
12628
  }, [updateVisibleRange]);
11964
- (0, import_react51.useEffect)(() => {
12629
+ (0, import_react53.useEffect)(() => {
11965
12630
  if (!document2) {
11966
12631
  setThumbnails(/* @__PURE__ */ new Map());
11967
12632
  pageCache.current.clear();
@@ -12016,7 +12681,7 @@ var PDFThumbnailNav = (0, import_react51.memo)(function PDFThumbnailNav2({
12016
12681
  };
12017
12682
  renderThumbnails();
12018
12683
  }, [document2, visibleRange, thumbnailScale, thumbnails]);
12019
- (0, import_react51.useEffect)(() => {
12684
+ (0, import_react53.useEffect)(() => {
12020
12685
  if (!containerRef.current || numPages === 0) return;
12021
12686
  const container = containerRef.current;
12022
12687
  const isHorizontal2 = orientation === "horizontal";
@@ -12032,12 +12697,12 @@ var PDFThumbnailNav = (0, import_react51.memo)(function PDFThumbnailNav2({
12032
12697
  });
12033
12698
  }
12034
12699
  }, [currentPage, numPages, orientation, thumbnailWidth, thumbnailHeight, gap]);
12035
- const handleThumbnailClick = (0, import_react51.useCallback)((pageNum) => {
12700
+ const handleThumbnailClick = (0, import_react53.useCallback)((pageNum) => {
12036
12701
  onThumbnailClick?.(pageNum);
12037
12702
  viewerStore.getState().requestScrollToPage(pageNum, "smooth");
12038
12703
  }, [onThumbnailClick, viewerStore]);
12039
12704
  if (!document2 || numPages === 0) {
12040
- return /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
12705
+ return /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
12041
12706
  "div",
12042
12707
  {
12043
12708
  className: cn(
@@ -12058,7 +12723,7 @@ var PDFThumbnailNav = (0, import_react51.memo)(function PDFThumbnailNav2({
12058
12723
  }
12059
12724
  const isHorizontal = orientation === "horizontal";
12060
12725
  const totalSize = numPages * ((isHorizontal ? thumbnailWidth : thumbnailHeight) + gap) - gap;
12061
- return /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
12726
+ return /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
12062
12727
  "div",
12063
12728
  {
12064
12729
  ref: containerRef,
@@ -12072,7 +12737,7 @@ var PDFThumbnailNav = (0, import_react51.memo)(function PDFThumbnailNav2({
12072
12737
  style: {
12073
12738
  ...isHorizontal ? { overflowX: "auto", overflowY: "hidden" } : { overflowX: "hidden", overflowY: "auto" }
12074
12739
  },
12075
- children: /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
12740
+ children: /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
12076
12741
  "div",
12077
12742
  {
12078
12743
  className: cn(
@@ -12089,7 +12754,7 @@ var PDFThumbnailNav = (0, import_react51.memo)(function PDFThumbnailNav2({
12089
12754
  const thumbnail = thumbnails.get(pageNum);
12090
12755
  const isActive = pageNum === currentPage;
12091
12756
  const isVisible = pageNum >= visibleRange.start && pageNum <= visibleRange.end;
12092
- return /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)(
12757
+ return /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)(
12093
12758
  "div",
12094
12759
  {
12095
12760
  className: cn(
@@ -12114,7 +12779,7 @@ var PDFThumbnailNav = (0, import_react51.memo)(function PDFThumbnailNav2({
12114
12779
  }
12115
12780
  },
12116
12781
  children: [
12117
- /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
12782
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
12118
12783
  "div",
12119
12784
  {
12120
12785
  className: "relative bg-white dark:bg-gray-700",
@@ -12122,7 +12787,7 @@ var PDFThumbnailNav = (0, import_react51.memo)(function PDFThumbnailNav2({
12122
12787
  width: thumbnailWidth,
12123
12788
  height: thumbnailHeight
12124
12789
  },
12125
- children: isVisible && thumbnail?.canvas ? /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
12790
+ children: isVisible && thumbnail?.canvas ? /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
12126
12791
  "img",
12127
12792
  {
12128
12793
  src: thumbnail.canvas.toDataURL(),
@@ -12130,10 +12795,10 @@ var PDFThumbnailNav = (0, import_react51.memo)(function PDFThumbnailNav2({
12130
12795
  className: "w-full h-full object-contain",
12131
12796
  loading: "lazy"
12132
12797
  }
12133
- ) : /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("div", { className: "absolute inset-0 flex items-center justify-center text-gray-400 dark:text-gray-500 text-xs", children: pageNum })
12798
+ ) : /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("div", { className: "absolute inset-0 flex items-center justify-center text-gray-400 dark:text-gray-500 text-xs", children: pageNum })
12134
12799
  }
12135
12800
  ),
12136
- showPageNumbers && /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
12801
+ showPageNumbers && /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
12137
12802
  "div",
12138
12803
  {
12139
12804
  className: cn(
@@ -12156,10 +12821,10 @@ var PDFThumbnailNav = (0, import_react51.memo)(function PDFThumbnailNav2({
12156
12821
  });
12157
12822
 
12158
12823
  // src/components/ErrorBoundary/PDFErrorBoundary.tsx
12159
- var import_react52 = require("react");
12824
+ var import_react54 = require("react");
12160
12825
  init_utils();
12161
- var import_jsx_runtime38 = require("react/jsx-runtime");
12162
- var PDFErrorBoundary = class extends import_react52.Component {
12826
+ var import_jsx_runtime40 = require("react/jsx-runtime");
12827
+ var PDFErrorBoundary = class extends import_react54.Component {
12163
12828
  constructor(props) {
12164
12829
  super(props);
12165
12830
  this.handleReset = () => {
@@ -12186,7 +12851,7 @@ var PDFErrorBoundary = class extends import_react52.Component {
12186
12851
  return fallback;
12187
12852
  }
12188
12853
  if (showDefaultUI) {
12189
- return /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
12854
+ return /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
12190
12855
  DefaultErrorUI,
12191
12856
  {
12192
12857
  error,
@@ -12205,7 +12870,7 @@ function DefaultErrorUI({ error, onReset, className }) {
12205
12870
  const isNetworkError = error.message.includes("fetch") || error.message.includes("network") || error.message.includes("Failed to load");
12206
12871
  let title = "Something went wrong";
12207
12872
  let description = error.message;
12208
- let icon = /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("svg", { className: "w-12 h-12 text-red-500", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
12873
+ let icon = /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("svg", { className: "w-12 h-12 text-red-500", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
12209
12874
  "path",
12210
12875
  {
12211
12876
  strokeLinecap: "round",
@@ -12217,7 +12882,7 @@ function DefaultErrorUI({ error, onReset, className }) {
12217
12882
  if (isPDFError) {
12218
12883
  title = "Unable to load PDF";
12219
12884
  description = "The PDF file could not be loaded. It may be corrupted or in an unsupported format.";
12220
- icon = /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("svg", { className: "w-12 h-12 text-red-500", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
12885
+ icon = /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("svg", { className: "w-12 h-12 text-red-500", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
12221
12886
  "path",
12222
12887
  {
12223
12888
  strokeLinecap: "round",
@@ -12229,7 +12894,7 @@ function DefaultErrorUI({ error, onReset, className }) {
12229
12894
  } else if (isNetworkError) {
12230
12895
  title = "Network error";
12231
12896
  description = "Unable to fetch the PDF file. Please check your internet connection and try again.";
12232
- icon = /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("svg", { className: "w-12 h-12 text-red-500", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
12897
+ icon = /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("svg", { className: "w-12 h-12 text-red-500", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
12233
12898
  "path",
12234
12899
  {
12235
12900
  strokeLinecap: "round",
@@ -12239,7 +12904,7 @@ function DefaultErrorUI({ error, onReset, className }) {
12239
12904
  }
12240
12905
  ) });
12241
12906
  }
12242
- return /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)(
12907
+ return /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(
12243
12908
  "div",
12244
12909
  {
12245
12910
  className: cn(
@@ -12252,14 +12917,14 @@ function DefaultErrorUI({ error, onReset, className }) {
12252
12917
  ),
12253
12918
  children: [
12254
12919
  icon,
12255
- /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("h2", { className: "mt-4 text-xl font-semibold text-gray-900 dark:text-gray-100", children: title }),
12256
- /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("p", { className: "mt-2 text-sm text-gray-600 dark:text-gray-400 max-w-md", children: description }),
12257
- /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("details", { className: "mt-4 text-left max-w-md w-full", children: [
12258
- /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("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" }),
12259
- /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("pre", { className: "mt-2 p-2 bg-gray-100 dark:bg-gray-800 rounded text-xs overflow-auto", children: error.stack || error.message })
12920
+ /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("h2", { className: "mt-4 text-xl font-semibold text-gray-900 dark:text-gray-100", children: title }),
12921
+ /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("p", { className: "mt-2 text-sm text-gray-600 dark:text-gray-400 max-w-md", children: description }),
12922
+ /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("details", { className: "mt-4 text-left max-w-md w-full", children: [
12923
+ /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("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" }),
12924
+ /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("pre", { className: "mt-2 p-2 bg-gray-100 dark:bg-gray-800 rounded text-xs overflow-auto", children: error.stack || error.message })
12260
12925
  ] }),
12261
- /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("div", { className: "mt-6 flex gap-3", children: [
12262
- /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
12926
+ /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("div", { className: "mt-6 flex gap-3", children: [
12927
+ /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
12263
12928
  "button",
12264
12929
  {
12265
12930
  onClick: onReset,
@@ -12273,7 +12938,7 @@ function DefaultErrorUI({ error, onReset, className }) {
12273
12938
  children: "Try again"
12274
12939
  }
12275
12940
  ),
12276
- /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
12941
+ /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
12277
12942
  "button",
12278
12943
  {
12279
12944
  onClick: () => window.location.reload(),
@@ -12293,7 +12958,7 @@ function DefaultErrorUI({ error, onReset, className }) {
12293
12958
  );
12294
12959
  }
12295
12960
  function withErrorBoundary({ component, ...props }) {
12296
- return /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(PDFErrorBoundary, { ...props, children: component });
12961
+ return /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(PDFErrorBoundary, { ...props, children: component });
12297
12962
  }
12298
12963
 
12299
12964
  // src/components/index.ts
@@ -12314,6 +12979,7 @@ init_utils();
12314
12979
  AnnotationToolbar,
12315
12980
  AskAboutOverlay,
12316
12981
  AskAboutTrigger,
12982
+ BookModeContainer,
12317
12983
  BookmarksPanel,
12318
12984
  CanvasLayer,
12319
12985
  ContinuousScrollContainer,
@@ -12392,6 +13058,7 @@ init_utils();
12392
13058
  isPDFJSInitialized,
12393
13059
  isPointInRect,
12394
13060
  loadDocument,
13061
+ loadDocumentWithCallbacks,
12395
13062
  loadHighlights,
12396
13063
  loadStudentData,
12397
13064
  mergeAdjacentRects,
@@ -12400,6 +13067,7 @@ init_utils();
12400
13067
  pdfjsLib,
12401
13068
  percentToPDF,
12402
13069
  percentToViewport,
13070
+ playPageTurnSound,
12403
13071
  quickViewer,
12404
13072
  removeRotation,
12405
13073
  saveHighlights,