@papyrus-sdk/ui-react-native 0.2.32 → 0.2.34

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -23388,6 +23388,42 @@ var resolvePdfAnchoredScrollY = ({
23388
23388
  });
23389
23389
  };
23390
23390
  var resolvePdfAnchoredScrollX = (input) => resolveAnchoredHorizontalSurfaceOffset(input);
23391
+ var resolvePdfPageAnchoredScrollX = ({
23392
+ focalViewportX,
23393
+ startSurfaceScrollX,
23394
+ viewportWidth,
23395
+ endSurfaceWidth,
23396
+ startPageOffsetX,
23397
+ endPageOffsetX,
23398
+ startPageFrameWidth,
23399
+ endPageFrameWidth,
23400
+ startPageWidth,
23401
+ endPageWidth
23402
+ }) => {
23403
+ const safeStartPageWidth = Number.isFinite(startPageWidth) && startPageWidth > 0 ? startPageWidth : 0;
23404
+ const safeEndPageWidth = Number.isFinite(endPageWidth) && endPageWidth > 0 ? endPageWidth : 0;
23405
+ if (safeStartPageWidth === 0 || safeEndPageWidth === 0) return 0;
23406
+ const safeFocalX = Number.isFinite(focalViewportX) ? focalViewportX : 0;
23407
+ const safeStartScrollX = Number.isFinite(startSurfaceScrollX) ? startSurfaceScrollX : 0;
23408
+ const safeStartOffsetX = Number.isFinite(startPageOffsetX) ? startPageOffsetX : 0;
23409
+ const safeEndOffsetX = Number.isFinite(endPageOffsetX) ? endPageOffsetX : 0;
23410
+ const startInset = resolveCenteredContentInset({
23411
+ viewportLength: startPageFrameWidth,
23412
+ contentLength: safeStartPageWidth
23413
+ });
23414
+ const endInset = resolveCenteredContentInset({
23415
+ viewportLength: endPageFrameWidth,
23416
+ contentLength: safeEndPageWidth
23417
+ });
23418
+ const startPageContentX = safeFocalX + safeStartScrollX - safeStartOffsetX - startInset;
23419
+ const scaledPageContentX = startPageContentX / safeStartPageWidth * safeEndPageWidth;
23420
+ const targetContentX = safeEndOffsetX + endInset + scaledPageContentX;
23421
+ return resolveClampedScrollOffset(
23422
+ targetContentX - safeFocalX,
23423
+ endSurfaceWidth,
23424
+ viewportWidth
23425
+ );
23426
+ };
23391
23427
  var resolvePdfSurfaceWidth = (input) => resolveDocumentSurfaceWidth(input);
23392
23428
  var resolvePdfGlobalScrollX = ({
23393
23429
  startSurfaceScrollX,
@@ -23422,10 +23458,57 @@ var buildCommentTapGestureDeps = ({
23422
23458
  ];
23423
23459
 
23424
23460
  // components/pdfPageMetrics.ts
23461
+ var resolvePdfDoublePageContentWidth = ({
23462
+ currentPage,
23463
+ pageCount,
23464
+ columnGap,
23465
+ getPageWidthForZoom
23466
+ }) => {
23467
+ const safePageCount = Number.isFinite(pageCount) ? Math.trunc(pageCount) : 0;
23468
+ if (safePageCount <= 0) return 0;
23469
+ const safeCurrentPage = Number.isFinite(currentPage) ? Math.trunc(currentPage) : 1;
23470
+ const pageIndex = Math.max(
23471
+ 0,
23472
+ Math.min(safePageCount - 1, safeCurrentPage - 1)
23473
+ );
23474
+ const leftPageIndex = Math.floor(pageIndex / 2) * 2;
23475
+ const rightPageIndex = leftPageIndex + 1;
23476
+ const resolvePageWidth = (index) => {
23477
+ const width = getPageWidthForZoom(index);
23478
+ return Number.isFinite(width) && width > 0 ? width : 0;
23479
+ };
23480
+ const leftPageWidth = resolvePageWidth(leftPageIndex);
23481
+ const rightPageWidth = rightPageIndex < safePageCount ? resolvePageWidth(rightPageIndex) : leftPageWidth;
23482
+ const safeColumnGap = Number.isFinite(columnGap) && columnGap > 0 ? columnGap : 0;
23483
+ return leftPageWidth + rightPageWidth + safeColumnGap;
23484
+ };
23485
+ var resolveMaxPageWidth = (maxPageWidth) => typeof maxPageWidth === "number" && Number.isFinite(maxPageWidth) && maxPageWidth > 0 ? maxPageWidth : void 0;
23486
+ var resolvePdfFitPageHeight = (viewportHeight, verticalInset) => {
23487
+ if (!Number.isFinite(viewportHeight) || viewportHeight <= 0 || !Number.isFinite(verticalInset) || verticalInset < 0) {
23488
+ return void 0;
23489
+ }
23490
+ return Math.max(1, viewportHeight - verticalInset * 2);
23491
+ };
23425
23492
  var resolvePdfBasePageWidth = ({
23426
23493
  viewportWidth,
23427
- horizontalPadding
23428
- }) => Math.max(0, viewportWidth - horizontalPadding * 2);
23494
+ horizontalPadding,
23495
+ maxPageWidth,
23496
+ maxPageHeight,
23497
+ pageAspectRatio
23498
+ }) => {
23499
+ const availablePageWidth = Math.max(
23500
+ 0,
23501
+ viewportWidth - horizontalPadding * 2
23502
+ );
23503
+ const resolvedMaxPageWidth = resolveMaxPageWidth(maxPageWidth);
23504
+ const hasValidPageHeight = typeof maxPageHeight === "number" && Number.isFinite(maxPageHeight) && maxPageHeight > 0 && typeof pageAspectRatio === "number" && Number.isFinite(pageAspectRatio) && pageAspectRatio > 0;
23505
+ const widthForMaxHeight = hasValidPageHeight ? maxPageHeight * pageAspectRatio : Number.POSITIVE_INFINITY;
23506
+ return Math.min(
23507
+ availablePageWidth,
23508
+ resolvedMaxPageWidth ?? Number.POSITIVE_INFINITY,
23509
+ widthForMaxHeight
23510
+ );
23511
+ };
23429
23512
 
23430
23513
  // components/selectionContentInteraction.ts
23431
23514
  var shouldDismissSelectionOnContentInteraction = ({
@@ -23512,6 +23595,8 @@ var PageRenderer = ({
23512
23595
  pageAspectRatio,
23513
23596
  PageViewComponent = import_engine_native.PapyrusPageView,
23514
23597
  availableWidth,
23598
+ maxPageWidth,
23599
+ maxPageHeight,
23515
23600
  pageViewportWidth: providedPageViewportWidth,
23516
23601
  horizontalPadding = 16,
23517
23602
  spacing = 24,
@@ -24615,7 +24700,10 @@ var PageRenderer = ({
24615
24700
  const containerWidth = availableWidth ?? windowWidth;
24616
24701
  const baseWidth = resolvePdfBasePageWidth({
24617
24702
  viewportWidth: containerWidth,
24618
- horizontalPadding
24703
+ horizontalPadding,
24704
+ maxPageWidth,
24705
+ maxPageHeight,
24706
+ pageAspectRatio: aspectRatio
24619
24707
  });
24620
24708
  const pageWidth = isNative ? baseWidth * zoom : baseWidth;
24621
24709
  const pageHeight = pageWidth / aspectRatio;
@@ -25355,7 +25443,7 @@ var styles = import_react_native.StyleSheet.create({
25355
25443
  borderRadius: 3
25356
25444
  }
25357
25445
  });
25358
- var arePageRendererPropsEqual = (previous, next) => previous.engine === next.engine && previous.pageIndex === next.pageIndex && previous.scale === next.scale && previous.PageViewComponent === next.PageViewComponent && previous.availableWidth === next.availableWidth && previous.pageViewportWidth === next.pageViewportWidth && previous.horizontalPadding === next.horizontalPadding && previous.spacing === next.spacing && previous.onSelectionDragActiveChange === next.onSelectionDragActiveChange && previous.gestureScrollLockActive === next.gestureScrollLockActive && previous.lastPinchEndedAt === next.lastPinchEndedAt && previous.requestSelectionVerticalAutoscroll === next.requestSelectionVerticalAutoscroll;
25446
+ var arePageRendererPropsEqual = (previous, next) => previous.engine === next.engine && previous.pageIndex === next.pageIndex && previous.scale === next.scale && previous.PageViewComponent === next.PageViewComponent && previous.availableWidth === next.availableWidth && previous.maxPageWidth === next.maxPageWidth && previous.maxPageHeight === next.maxPageHeight && previous.pageViewportWidth === next.pageViewportWidth && previous.horizontalPadding === next.horizontalPadding && previous.spacing === next.spacing && previous.onSelectionDragActiveChange === next.onSelectionDragActiveChange && previous.gestureScrollLockActive === next.gestureScrollLockActive && previous.lastPinchEndedAt === next.lastPinchEndedAt && previous.requestSelectionVerticalAutoscroll === next.requestSelectionVerticalAutoscroll;
25359
25447
  var PageRenderer_default = (0, import_react2.memo)(PageRenderer, arePageRendererPropsEqual);
25360
25448
 
25361
25449
  // components/WebViewViewer.tsx
@@ -25428,6 +25516,7 @@ var resolveRuntimeSource = (asset) => {
25428
25516
  };
25429
25517
  var WebViewViewer = ({
25430
25518
  engine,
25519
+ maxPageWidth,
25431
25520
  onScrollOffset,
25432
25521
  onTap
25433
25522
  }) => {
@@ -25546,6 +25635,12 @@ var WebViewViewer = ({
25546
25635
  }
25547
25636
  return void 0;
25548
25637
  }, []);
25638
+ const resolvedMaxPageWidth = resolveMaxPageWidth(maxPageWidth);
25639
+ const cappedWebViewStyle = resolvedMaxPageWidth ? {
25640
+ width: "100%",
25641
+ maxWidth: resolvedMaxPageWidth,
25642
+ alignSelf: "center"
25643
+ } : void 0;
25549
25644
  return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_react_native2.View, { style: styles2.container, children: [
25550
25645
  /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
25551
25646
  import_react_native_webview.default,
@@ -25566,7 +25661,7 @@ var WebViewViewer = ({
25566
25661
  allowFileAccessFromFileURLs: true,
25567
25662
  allowUniversalAccessFromFileURLs: true,
25568
25663
  allowingReadAccessToURL,
25569
- style: styles2.webview
25664
+ style: [styles2.webview, cappedWebViewStyle]
25570
25665
  }
25571
25666
  ),
25572
25667
  /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
@@ -25639,7 +25734,8 @@ var getDedicatedAndroidPdfEngineId = (engine) => {
25639
25734
  return typeof engineId === "string" && engineId.length > 0 ? engineId : null;
25640
25735
  };
25641
25736
  function DedicatedAndroidPdfViewer({
25642
- engine
25737
+ engine,
25738
+ maxPageWidth
25643
25739
  }) {
25644
25740
  const pageTheme = (0, import_core3.useViewerStore)((state) => state.pageTheme);
25645
25741
  const zoom = (0, import_core3.useViewerStore)((state) => state.zoom);
@@ -25662,6 +25758,12 @@ function DedicatedAndroidPdfViewer({
25662
25758
  const addAnnotation = (0, import_core3.useViewerStore)((state) => state.addAnnotation);
25663
25759
  const setSelectedAnnotation = (0, import_core3.useViewerStore)((state) => state.setSelectedAnnotation);
25664
25760
  const engineId = getDedicatedAndroidPdfEngineId(engine);
25761
+ const resolvedMaxPageWidth = resolveMaxPageWidth(maxPageWidth);
25762
+ const cappedViewerStyle = resolvedMaxPageWidth ? {
25763
+ width: "100%",
25764
+ maxWidth: resolvedMaxPageWidth,
25765
+ alignSelf: "center"
25766
+ } : void 0;
25665
25767
  const [selection, setSelection] = (0, import_react4.useState)(null);
25666
25768
  const selectionRef = (0, import_react4.useRef)(null);
25667
25769
  const lastVisiblePagesKeyRef = (0, import_react4.useRef)("");
@@ -25763,7 +25865,7 @@ function DedicatedAndroidPdfViewer({
25763
25865
  /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
25764
25866
  import_engine_native2.PapyrusPdfDocumentView,
25765
25867
  {
25766
- style: styles3.viewer,
25868
+ style: [styles3.viewer, cappedViewerStyle],
25767
25869
  engineId,
25768
25870
  pageTheme,
25769
25871
  zoom,
@@ -25943,11 +26045,12 @@ var styles3 = import_react_native3.StyleSheet.create({
25943
26045
 
25944
26046
  // components/nativePdfViewerMode.ts
25945
26047
  var shouldUseNativePdfViewer = ({
26048
+ platform,
25946
26049
  viewerMode,
25947
26050
  pageCount,
25948
26051
  isWebView,
25949
26052
  nativeEngineId
25950
- }) => viewerMode === "native" && pageCount > 0 && !isWebView && !!nativeEngineId;
26053
+ }) => platform === "android" && viewerMode === "native" && pageCount > 0 && !isWebView && !!nativeEngineId;
25951
26054
 
25952
26055
  // perf/pinchPerfSession.ts
25953
26056
  var PINCH_EPSILON = 1e-3;
@@ -26209,6 +26312,14 @@ var resolveViewerScrollTarget = (pageIndex, isDouble) => ({
26209
26312
  var pageContainsScrollTarget = (row, pageIndex) => row.left === pageIndex || row.right === pageIndex;
26210
26313
 
26211
26314
  // components/viewerPerformance.ts
26315
+ var hasViewerViewportGeometryChanged = ({
26316
+ previous,
26317
+ next
26318
+ }) => {
26319
+ if (!previous) return false;
26320
+ if (previous.width !== next.width) return true;
26321
+ return typeof previous.pageFitHeight === "number" && typeof next.pageFitHeight === "number" && previous.pageFitHeight !== next.pageFitHeight;
26322
+ };
26212
26323
  var resolveOrientationScrollOffset = ({
26213
26324
  currentPage,
26214
26325
  pageCount,
@@ -26265,6 +26376,8 @@ var scrollViewerListToOffset = (list, offset, animated) => {
26265
26376
  };
26266
26377
  var Viewer = ({
26267
26378
  engine,
26379
+ maxPageWidth,
26380
+ fitPageToViewportHeight = false,
26268
26381
  virtualWindowSize,
26269
26382
  maxToRenderPerBatch,
26270
26383
  removeClippedSubviews,
@@ -26306,6 +26419,7 @@ var Viewer = ({
26306
26419
  }, [mobilePerf, resolvedViewerMode]);
26307
26420
  const nativeEngineId = getDedicatedAndroidPdfEngineId(engine);
26308
26421
  const isNativePdfViewer = shouldUseNativePdfViewer({
26422
+ platform: import_react_native4.Platform.OS,
26309
26423
  viewerMode: resolvedViewerMode,
26310
26424
  pageCount,
26311
26425
  isWebView,
@@ -26325,8 +26439,8 @@ var Viewer = ({
26325
26439
  const scrollPerfSession = (0, import_react5.useMemo)(() => createScrollPerfSession(), []);
26326
26440
  const dimensionsCacheRef = (0, import_react5.useRef)(/* @__PURE__ */ new Map());
26327
26441
  const dimensionsPendingRef = (0, import_react5.useRef)(/* @__PURE__ */ new Set());
26328
- const previousWindowWidthRef = (0, import_react5.useRef)(null);
26329
- const pendingOrientationRestoreWidthRef = (0, import_react5.useRef)(null);
26442
+ const previousViewportGeometryRef = (0, import_react5.useRef)(null);
26443
+ const pendingOrientationRestoreRef = (0, import_react5.useRef)(false);
26330
26444
  const layoutRefreshTimeoutRef = (0, import_react5.useRef)(
26331
26445
  null
26332
26446
  );
@@ -26373,6 +26487,7 @@ var Viewer = ({
26373
26487
  const committedPinchGestureIdRef = (0, import_react5.useRef)(null);
26374
26488
  const pinchAnchorRestoreFrameRef = (0, import_react5.useRef)(null);
26375
26489
  const viewerFrameRef = (0, import_react5.useRef)({ y: 0, height: 0 });
26490
+ const [viewerViewportHeight, setViewerViewportHeight] = (0, import_react5.useState)(0);
26376
26491
  const viewerContentHeightRef = (0, import_react5.useRef)(0);
26377
26492
  const listLayoutMetricsRef = (0, import_react5.useRef)(null);
26378
26493
  const resolvedWindowSize = (0, import_react5.useMemo)(
@@ -26661,16 +26776,27 @@ var Viewer = ({
26661
26776
  const columnGap = 12;
26662
26777
  const horizontalPadding = 16;
26663
26778
  const columnWidth = isDouble ? (windowWidth - horizontalPadding * 2 - columnGap) / 2 : windowWidth;
26779
+ const pageFitHeight = fitPageToViewportHeight ? resolvePdfFitPageHeight(viewerViewportHeight, LIST_TOP_PADDING) : void 0;
26664
26780
  const getPageWidthForZoom = (0, import_react5.useCallback)(
26665
26781
  (pageIndex, zoomValue) => {
26666
26782
  const safeZoom = Math.max(zoomValue, 0.25);
26667
26783
  const baseWidth = resolvePdfBasePageWidth({
26668
26784
  viewportWidth: isDouble ? columnWidth : windowWidth,
26669
- horizontalPadding: isDouble ? 8 : 16
26785
+ horizontalPadding: isDouble ? 8 : 16,
26786
+ maxPageWidth,
26787
+ maxPageHeight: pageFitHeight,
26788
+ pageAspectRatio: getPageAspectRatio(pageIndex)
26670
26789
  });
26671
26790
  return baseWidth * safeZoom;
26672
26791
  },
26673
- [columnWidth, isDouble, windowWidth]
26792
+ [
26793
+ columnWidth,
26794
+ getPageAspectRatio,
26795
+ isDouble,
26796
+ maxPageWidth,
26797
+ pageFitHeight,
26798
+ windowWidth
26799
+ ]
26674
26800
  );
26675
26801
  const getPageHeightForZoom = (0, import_react5.useCallback)(
26676
26802
  (pageIndex, zoomValue) => getPageWidthForZoom(pageIndex, zoomValue) / getPageAspectRatio(pageIndex),
@@ -26696,8 +26822,12 @@ var Viewer = ({
26696
26822
  );
26697
26823
  const documentSurfaceWidth = (0, import_react5.useMemo)(() => {
26698
26824
  if (isDouble) {
26699
- const leftPageWidth = getPageWidthForZoom(0, zoom);
26700
- const doubleContentWidth = leftPageWidth * 2 + columnGap;
26825
+ const doubleContentWidth = resolvePdfDoublePageContentWidth({
26826
+ currentPage,
26827
+ pageCount,
26828
+ columnGap,
26829
+ getPageWidthForZoom: (pageIndex) => getPageWidthForZoom(pageIndex, zoom)
26830
+ });
26701
26831
  return resolvePdfSurfaceWidth({
26702
26832
  viewportWidth: windowWidth,
26703
26833
  contentWidth: doubleContentWidth,
@@ -26715,6 +26845,8 @@ var Viewer = ({
26715
26845
  getPageWidthForZoom,
26716
26846
  horizontalPadding,
26717
26847
  isDouble,
26848
+ layoutRevision,
26849
+ pageCount,
26718
26850
  windowWidth,
26719
26851
  zoom
26720
26852
  ]);
@@ -27036,6 +27168,18 @@ var Viewer = ({
27036
27168
  horizontalPadding: pageHorizontalPadding,
27037
27169
  viewportOffsetX
27038
27170
  } = getPageViewportMetrics(anchorPageIndex);
27171
+ const availablePageWidth = Math.max(
27172
+ 0,
27173
+ pageViewportWidth - pageHorizontalPadding * 2
27174
+ );
27175
+ const basePageWidth = resolvePdfBasePageWidth({
27176
+ viewportWidth: pageViewportWidth,
27177
+ horizontalPadding: pageHorizontalPadding,
27178
+ maxPageWidth,
27179
+ maxPageHeight: pageFitHeight,
27180
+ pageAspectRatio: getPageAspectRatio(anchorPageIndex)
27181
+ });
27182
+ const startPageWidth = getPageWidthForZoom(anchorPageIndex, startZoom);
27039
27183
  const pageViewportContentWidth = Math.max(
27040
27184
  0,
27041
27185
  pageViewportWidth - pageHorizontalPadding * 2
@@ -27051,6 +27195,13 @@ var Viewer = ({
27051
27195
  usePageVerticalAnchor,
27052
27196
  startSurfaceScrollX: pinchStartSurfaceScrollXRef.current,
27053
27197
  startSurfaceWidth,
27198
+ usePageHorizontalAnchor: basePageWidth < availablePageWidth,
27199
+ startPageOffsetX: viewportOffsetX,
27200
+ startPageFrameWidth: isDouble ? Math.max(
27201
+ pageViewportWidth,
27202
+ startPageWidth + pageHorizontalPadding * 2
27203
+ ) : startSurfaceWidth,
27204
+ startPageWidth,
27054
27205
  pageViewportWidth,
27055
27206
  pageHorizontalPadding,
27056
27207
  pageViewportContentOffsetX: Math.max(
@@ -27089,8 +27240,13 @@ var Viewer = ({
27089
27240
  engine,
27090
27241
  documentSurfaceWidth,
27091
27242
  getPageLayoutForZoom,
27243
+ getPageWidthForZoom,
27092
27244
  getPageViewportMetrics,
27093
27245
  handleGestureScrollLockChange,
27246
+ isDouble,
27247
+ maxPageWidth,
27248
+ pageFitHeight,
27249
+ getPageAspectRatio,
27094
27250
  perfEnabled,
27095
27251
  pinchPerfMachine,
27096
27252
  resetViewerPinchPreview,
@@ -27175,7 +27331,7 @@ var Viewer = ({
27175
27331
  pageHeight: endPageHeight,
27176
27332
  totalContentHeight: endContentHeight
27177
27333
  } = getPageLayoutForZoom(pendingRestore.pageIndex, zoom);
27178
- const viewerViewportHeight = viewerFrameRef.current.height;
27334
+ const viewerViewportHeight2 = viewerFrameRef.current.height;
27179
27335
  const nextScrollY = resolvePdfAnchoredScrollY({
27180
27336
  mode: pendingRestore.usePageVerticalAnchor ? "page" : "document",
27181
27337
  focalY: pendingRestore.focalY,
@@ -27186,7 +27342,7 @@ var Viewer = ({
27186
27342
  endPageOffsetY,
27187
27343
  endPageHeight,
27188
27344
  endContentHeight,
27189
- viewportHeight: viewerViewportHeight
27345
+ viewportHeight: viewerViewportHeight2
27190
27346
  });
27191
27347
  if (isSingle) {
27192
27348
  listRef.current?.scrollTo?.({
@@ -27205,7 +27361,25 @@ var Viewer = ({
27205
27361
  0,
27206
27362
  pendingRestore.pageViewportWidth - pendingRestore.pageHorizontalPadding * 2
27207
27363
  );
27208
- const nextOffsetX = resolvePdfAnchoredScrollX({
27364
+ const nextPageWidth = getPageWidthForZoom(
27365
+ pendingRestore.pageIndex,
27366
+ pendingRestore.finalZoom
27367
+ );
27368
+ const nextOffsetX = pendingRestore.usePageHorizontalAnchor ? resolvePdfPageAnchoredScrollX({
27369
+ focalViewportX: pinchFocalPointRef.current.x,
27370
+ startSurfaceScrollX: pendingRestore.startSurfaceScrollX,
27371
+ viewportWidth: windowWidth,
27372
+ endSurfaceWidth,
27373
+ startPageOffsetX: pendingRestore.startPageOffsetX,
27374
+ endPageOffsetX: pendingRestore.startPageOffsetX,
27375
+ startPageFrameWidth: pendingRestore.startPageFrameWidth,
27376
+ endPageFrameWidth: isDouble ? Math.max(
27377
+ pendingRestore.pageViewportWidth,
27378
+ nextPageWidth + pendingRestore.pageHorizontalPadding * 2
27379
+ ) : endSurfaceWidth,
27380
+ startPageWidth: pendingRestore.startPageWidth,
27381
+ endPageWidth: nextPageWidth
27382
+ }) : resolvePdfAnchoredScrollX({
27209
27383
  focalViewportX: pendingRestore.pageViewportContentOffsetX,
27210
27384
  startSurfaceScrollX: pendingRestore.startSurfaceScrollX,
27211
27385
  startSurfaceWidth: pendingRestore.startSurfaceWidth,
@@ -27233,9 +27407,12 @@ var Viewer = ({
27233
27407
  }, [
27234
27408
  documentSurfaceWidth,
27235
27409
  getPageLayoutForZoom,
27410
+ getPageWidthForZoom,
27411
+ isDouble,
27236
27412
  isSingle,
27237
27413
  perfEnabled,
27238
27414
  scrollHorizontalSurfaceTo,
27415
+ windowWidth,
27239
27416
  zoom
27240
27417
  ]);
27241
27418
  (0, import_react5.useEffect)(() => {
@@ -27296,7 +27473,10 @@ var Viewer = ({
27296
27473
  if (isDouble) {
27297
27474
  const pageWidth2 = resolvePdfBasePageWidth({
27298
27475
  viewportWidth: columnWidth,
27299
- horizontalPadding: 8
27476
+ horizontalPadding: 8,
27477
+ maxPageWidth,
27478
+ maxPageHeight: pageFitHeight,
27479
+ pageAspectRatio: DEFAULT_PAGE_ASPECT_RATIO
27300
27480
  });
27301
27481
  return (0, import_core4.createPageLayoutMetrics)({
27302
27482
  itemCount: rows.length,
@@ -27306,16 +27486,37 @@ var Viewer = ({
27306
27486
  estimatedLength: pageWidth2 / DEFAULT_PAGE_ASPECT_RATIO + DOUBLE_PAGE_SPACING,
27307
27487
  getBaseItemLength: (index) => {
27308
27488
  const row = rows[index];
27309
- if (!row) return pageWidth2 / DEFAULT_PAGE_ASPECT_RATIO + DOUBLE_PAGE_SPACING;
27310
- const leftHeight = pageWidth2 / getPageAspectRatio(row.left);
27311
- const rightHeight = row.right === null ? leftHeight : pageWidth2 / getPageAspectRatio(row.right);
27489
+ if (!row) {
27490
+ return pageWidth2 / DEFAULT_PAGE_ASPECT_RATIO + DOUBLE_PAGE_SPACING;
27491
+ }
27492
+ const leftAspectRatio = getPageAspectRatio(row.left);
27493
+ const leftPageWidth = resolvePdfBasePageWidth({
27494
+ viewportWidth: columnWidth,
27495
+ horizontalPadding: 8,
27496
+ maxPageWidth,
27497
+ maxPageHeight: pageFitHeight,
27498
+ pageAspectRatio: leftAspectRatio
27499
+ });
27500
+ const leftHeight = leftPageWidth / leftAspectRatio;
27501
+ const rightAspectRatio = row.right === null ? leftAspectRatio : getPageAspectRatio(row.right);
27502
+ const rightPageWidth = row.right === null ? leftPageWidth : resolvePdfBasePageWidth({
27503
+ viewportWidth: columnWidth,
27504
+ horizontalPadding: 8,
27505
+ maxPageWidth,
27506
+ maxPageHeight: pageFitHeight,
27507
+ pageAspectRatio: rightAspectRatio
27508
+ });
27509
+ const rightHeight = rightPageWidth / rightAspectRatio;
27312
27510
  return Math.max(leftHeight, rightHeight) + DOUBLE_PAGE_SPACING;
27313
27511
  }
27314
27512
  });
27315
27513
  }
27316
27514
  const pageWidth = resolvePdfBasePageWidth({
27317
27515
  viewportWidth: windowWidth,
27318
- horizontalPadding: 16
27516
+ horizontalPadding: 16,
27517
+ maxPageWidth,
27518
+ maxPageHeight: pageFitHeight,
27519
+ pageAspectRatio: DEFAULT_PAGE_ASPECT_RATIO
27319
27520
  });
27320
27521
  return (0, import_core4.createPageLayoutMetrics)({
27321
27522
  itemCount: pageCount,
@@ -27323,13 +27524,25 @@ var Viewer = ({
27323
27524
  topPadding: LIST_TOP_PADDING,
27324
27525
  bottomPadding: LIST_BOTTOM_PADDING,
27325
27526
  estimatedLength: pageWidth / DEFAULT_PAGE_ASPECT_RATIO + CONTINUOUS_PAGE_SPACING,
27326
- getBaseItemLength: (index) => pageWidth / getPageAspectRatio(index) + CONTINUOUS_PAGE_SPACING
27527
+ getBaseItemLength: (index) => {
27528
+ const aspectRatio = getPageAspectRatio(index);
27529
+ const fittedPageWidth = resolvePdfBasePageWidth({
27530
+ viewportWidth: windowWidth,
27531
+ horizontalPadding: 16,
27532
+ maxPageWidth,
27533
+ maxPageHeight: pageFitHeight,
27534
+ pageAspectRatio: aspectRatio
27535
+ });
27536
+ return fittedPageWidth / aspectRatio + CONTINUOUS_PAGE_SPACING;
27537
+ }
27327
27538
  });
27328
27539
  }, [
27329
27540
  columnWidth,
27330
27541
  getPageAspectRatio,
27331
27542
  isDouble,
27332
27543
  layoutRevision,
27544
+ maxPageWidth,
27545
+ pageFitHeight,
27333
27546
  pageCount,
27334
27547
  rows,
27335
27548
  windowWidth
@@ -27366,7 +27579,7 @@ var Viewer = ({
27366
27579
  [getFallbackOffsetForIndex, setViewerScrollEnabledNative]
27367
27580
  );
27368
27581
  const restoreOrientationScrollOffset = (0, import_react5.useCallback)(() => {
27369
- if (pendingOrientationRestoreWidthRef.current !== windowWidth || pageCount <= 0 || isSingle || isWebView) {
27582
+ if (!pendingOrientationRestoreRef.current || fitPageToViewportHeight && pageFitHeight === void 0 || pageCount <= 0 || isSingle || isWebView) {
27370
27583
  return;
27371
27584
  }
27372
27585
  const offset = resolveOrientationScrollOffset({
@@ -27377,24 +27590,30 @@ var Viewer = ({
27377
27590
  });
27378
27591
  listRef.current?.scrollToOffset({ offset, animated: false });
27379
27592
  lastScrollOffsetYRef.current = offset;
27380
- pendingOrientationRestoreWidthRef.current = null;
27593
+ pendingOrientationRestoreRef.current = false;
27381
27594
  }, [
27382
27595
  currentPage,
27596
+ fitPageToViewportHeight,
27383
27597
  isDouble,
27384
27598
  isSingle,
27385
27599
  isWebView,
27386
27600
  pageCount,
27601
+ pageFitHeight,
27387
27602
  scaledListLayoutMetrics,
27388
27603
  windowWidth
27389
27604
  ]);
27390
27605
  (0, import_react5.useEffect)(() => {
27391
- const previousWindowWidth = previousWindowWidthRef.current;
27392
- previousWindowWidthRef.current = windowWidth;
27393
- if (previousWindowWidth !== null && previousWindowWidth !== windowWidth) {
27394
- pendingOrientationRestoreWidthRef.current = windowWidth;
27606
+ const nextGeometry = { width: windowWidth, pageFitHeight };
27607
+ const previousGeometry = previousViewportGeometryRef.current;
27608
+ previousViewportGeometryRef.current = nextGeometry;
27609
+ if (hasViewerViewportGeometryChanged({
27610
+ previous: previousGeometry,
27611
+ next: nextGeometry
27612
+ })) {
27613
+ pendingOrientationRestoreRef.current = true;
27395
27614
  }
27396
27615
  restoreOrientationScrollOffset();
27397
- }, [restoreOrientationScrollOffset, windowWidth]);
27616
+ }, [pageFitHeight, restoreOrientationScrollOffset, windowWidth]);
27398
27617
  (0, import_react5.useEffect)(() => {
27399
27618
  if (pendingScrollTargetRef.current !== null) {
27400
27619
  scrollToPendingTarget(false);
@@ -27646,6 +27865,8 @@ var Viewer = ({
27646
27865
  pageIndex: row.left,
27647
27866
  pageAspectRatio: getPageAspectRatio(row.left),
27648
27867
  availableWidth: columnWidth,
27868
+ maxPageWidth,
27869
+ maxPageHeight: pageFitHeight,
27649
27870
  horizontalPadding: 8,
27650
27871
  pageViewportWidth: columnWidth,
27651
27872
  spacing: DOUBLE_PAGE_SPACING,
@@ -27666,6 +27887,8 @@ var Viewer = ({
27666
27887
  pageIndex: row.right,
27667
27888
  pageAspectRatio: getPageAspectRatio(row.right),
27668
27889
  availableWidth: columnWidth,
27890
+ maxPageWidth,
27891
+ maxPageHeight: pageFitHeight,
27669
27892
  horizontalPadding: 8,
27670
27893
  pageViewportWidth: columnWidth,
27671
27894
  spacing: DOUBLE_PAGE_SPACING,
@@ -27690,6 +27913,8 @@ var Viewer = ({
27690
27913
  pageIndex: item,
27691
27914
  pageAspectRatio: getPageAspectRatio(item),
27692
27915
  availableWidth: windowWidth,
27916
+ maxPageWidth,
27917
+ maxPageHeight: pageFitHeight,
27693
27918
  pageViewportWidth: documentSurfaceWidth,
27694
27919
  spacing: CONTINUOUS_PAGE_SPACING,
27695
27920
  onSelectionDragActiveChange: setSelectionDragActive,
@@ -27715,6 +27940,8 @@ var Viewer = ({
27715
27940
  horizontalPadding,
27716
27941
  isDouble,
27717
27942
  lastPinchEndedAt,
27943
+ maxPageWidth,
27944
+ pageFitHeight,
27718
27945
  windowWidth
27719
27946
  ]
27720
27947
  );
@@ -27737,7 +27964,13 @@ var Viewer = ({
27737
27964
  onViewableItemsChanged,
27738
27965
  viewabilityConfig: { itemVisiblePercentThreshold: 60 },
27739
27966
  scrollEnabled: pageScrubResolvedScrollEnabled || programmaticScrollActive,
27740
- onLayout: () => {
27967
+ onLayout: (event) => {
27968
+ const nextHeight = event.nativeEvent.layout.height;
27969
+ if (fitPageToViewportHeight) {
27970
+ setViewerViewportHeight(
27971
+ (currentHeight) => currentHeight === nextHeight ? currentHeight : nextHeight
27972
+ );
27973
+ }
27741
27974
  captureViewerFrame(listRef.current);
27742
27975
  restoreOrientationScrollOffset();
27743
27976
  scrollToPendingTarget(false);
@@ -27806,13 +28039,14 @@ var Viewer = ({
27806
28039
  WebViewViewer_default,
27807
28040
  {
27808
28041
  engine,
28042
+ maxPageWidth,
27809
28043
  onScrollOffset: handleWebViewScroll,
27810
28044
  onTap: handleWebViewTap
27811
28045
  }
27812
28046
  ) });
27813
28047
  }
27814
28048
  if (isNativePdfViewer) {
27815
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_react_native4.View, { style: [styles4.container, isDark && styles4.containerDark], children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(DedicatedAndroidPdfViewer, { engine }) });
28049
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_react_native4.View, { style: [styles4.container, isDark && styles4.containerDark], children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(DedicatedAndroidPdfViewer, { engine, maxPageWidth }) });
27816
28050
  }
27817
28051
  if (isSingle) {
27818
28052
  return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_react_native4.View, { style: [styles4.container, isDark && styles4.containerDark], children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_react_native_gesture_handler2.GestureDetector, { gesture: viewerPinchGesture, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
@@ -27853,7 +28087,15 @@ var Viewer = ({
27853
28087
  contentContainerStyle: styles4.singleContent,
27854
28088
  showsVerticalScrollIndicator: false,
27855
28089
  scrollEnabled: pageScrubResolvedScrollEnabled,
27856
- onLayout: () => captureViewerFrame(listRef.current),
28090
+ onLayout: (event) => {
28091
+ const nextHeight = event.nativeEvent.layout.height;
28092
+ if (fitPageToViewportHeight) {
28093
+ setViewerViewportHeight(
28094
+ (currentHeight) => currentHeight === nextHeight ? currentHeight : nextHeight
28095
+ );
28096
+ }
28097
+ captureViewerFrame(listRef.current);
28098
+ },
27857
28099
  onContentSizeChange: (_, height) => {
27858
28100
  viewerContentHeightRef.current = height;
27859
28101
  },
@@ -27886,6 +28128,8 @@ var Viewer = ({
27886
28128
  Math.max(0, currentPage - 1)
27887
28129
  ),
27888
28130
  availableWidth: windowWidth,
28131
+ maxPageWidth,
28132
+ maxPageHeight: pageFitHeight,
27889
28133
  pageViewportWidth: documentSurfaceWidth,
27890
28134
  spacing: 32,
27891
28135
  onSelectionDragActiveChange: setSelectionDragActive,
@@ -28018,6 +28262,9 @@ var import_react7 = __toESM(require("react"));
28018
28262
  var import_react_native5 = require("react-native");
28019
28263
 
28020
28264
  // components/nativeSheetLayout.ts
28265
+ var FLOATING_SHEET_MIN_WINDOW_WIDTH = 600;
28266
+ var FLOATING_SHEET_HORIZONTAL_GUTTER = 32;
28267
+ var FLOATING_SHEET_MAX_WIDTH = 640;
28021
28268
  var getNativeSheetSizeStyle = (maxHeight) => {
28022
28269
  if (!maxHeight) return null;
28023
28270
  return {
@@ -28025,6 +28272,32 @@ var getNativeSheetSizeStyle = (maxHeight) => {
28025
28272
  ...typeof maxHeight === "number" ? { height: maxHeight } : {}
28026
28273
  };
28027
28274
  };
28275
+ var getNativeSheetWidth = (windowWidth) => {
28276
+ if (!Number.isFinite(windowWidth) || windowWidth <= 0) return 0;
28277
+ if (windowWidth < FLOATING_SHEET_MIN_WINDOW_WIDTH) return windowWidth;
28278
+ return Math.min(
28279
+ FLOATING_SHEET_MAX_WIDTH,
28280
+ windowWidth - FLOATING_SHEET_HORIZONTAL_GUTTER * 2
28281
+ );
28282
+ };
28283
+ var getNativeSheetLayoutStyles = (windowWidth) => {
28284
+ if (!Number.isFinite(windowWidth) || windowWidth < FLOATING_SHEET_MIN_WINDOW_WIDTH) {
28285
+ return null;
28286
+ }
28287
+ return {
28288
+ root: {
28289
+ justifyContent: "center",
28290
+ paddingHorizontal: FLOATING_SHEET_HORIZONTAL_GUTTER,
28291
+ paddingVertical: 24
28292
+ },
28293
+ sheet: {
28294
+ width: getNativeSheetWidth(windowWidth),
28295
+ alignSelf: "center",
28296
+ borderRadius: 24,
28297
+ borderBottomWidth: 1
28298
+ }
28299
+ };
28300
+ };
28028
28301
 
28029
28302
  // components/PapyrusSafeArea.tsx
28030
28303
  var import_react6 = __toESM(require("react"));
@@ -28101,7 +28374,8 @@ function NativeSheet({
28101
28374
  }) {
28102
28375
  const insets = usePapyrusSafeAreaInsets();
28103
28376
  const palette = getNativeSheetPalette(Boolean(isDark));
28104
- const { height: windowHeight } = (0, import_react_native5.useWindowDimensions)();
28377
+ const { height: windowHeight, width: windowWidth } = (0, import_react_native5.useWindowDimensions)();
28378
+ const tabletLayout = getNativeSheetLayoutStyles(windowWidth);
28105
28379
  const [rendered, setRendered] = (0, import_react7.useState)(visible);
28106
28380
  const renderedRef = (0, import_react7.useRef)(visible);
28107
28381
  const motion = (0, import_react7.useRef)(new import_react_native5.Animated.Value(visible ? 0 : 1)).current;
@@ -28156,7 +28430,7 @@ function NativeSheet({
28156
28430
  transparent: true,
28157
28431
  visible: rendered,
28158
28432
  onRequestClose: onClose,
28159
- children: /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_react_native5.View, { style: styles5.root, children: [
28433
+ children: /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_react_native5.View, { style: [styles5.root, tabletLayout?.root], children: [
28160
28434
  /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_react_native5.Animated.View, { style: [styles5.backdrop, { opacity: backdropOpacity }], children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
28161
28435
  import_react_native5.Pressable,
28162
28436
  {
@@ -28171,12 +28445,14 @@ function NativeSheet({
28171
28445
  {
28172
28446
  style: [
28173
28447
  styles5.sheet,
28448
+ tabletLayout?.sheet,
28174
28449
  isDark && styles5.sheetDark,
28175
28450
  getNativeSheetSizeStyle(maxHeight),
28176
28451
  { paddingBottom: insets.bottom },
28177
28452
  {
28178
28453
  backgroundColor: palette.backgroundColor,
28179
- borderTopColor: palette.borderColor
28454
+ borderTopColor: palette.borderColor,
28455
+ borderBottomColor: palette.borderColor
28180
28456
  },
28181
28457
  sheetStyle,
28182
28458
  {
@@ -28232,7 +28508,8 @@ function NativeSheetFlatList(props) {
28232
28508
  var styles5 = import_react_native5.StyleSheet.create({
28233
28509
  root: {
28234
28510
  flex: 1,
28235
- justifyContent: "flex-end"
28511
+ justifyContent: "flex-end",
28512
+ alignItems: "center"
28236
28513
  },
28237
28514
  backdrop: {
28238
28515
  ...import_react_native5.StyleSheet.absoluteFillObject,
@@ -28245,6 +28522,7 @@ var styles5 = import_react_native5.StyleSheet.create({
28245
28522
  borderTopRightRadius: 24,
28246
28523
  borderTopWidth: 1,
28247
28524
  borderTopColor: "#e5e7eb",
28525
+ borderBottomColor: "#e5e7eb",
28248
28526
  backgroundColor: "#ffffff"
28249
28527
  },
28250
28528
  sheetDark: {
@@ -29822,6 +30100,14 @@ var import_core7 = require("@papyrus-sdk/core");
29822
30100
  var import_engine_native3 = require("@papyrus-sdk/engine-native");
29823
30101
 
29824
30102
  // components/rightSheetLayout.ts
30103
+ var getRightSheetThumbnailLayout = (sheetWidth) => {
30104
+ const availableWidth = Number.isFinite(sheetWidth) ? Math.max(0, sheetWidth - 32) : 0;
30105
+ const cardWidth = Math.max(0, (availableWidth - 12) / 2);
30106
+ return {
30107
+ cardWidth,
30108
+ frameWidth: Math.max(0, cardWidth - 16)
30109
+ };
30110
+ };
29825
30111
  var resolveRightSheetHeight = ({
29826
30112
  windowHeight,
29827
30113
  showingNotes
@@ -30023,6 +30309,7 @@ var RightSheet = ({
30023
30309
  locale,
30024
30310
  accentColor
30025
30311
  } = (0, import_core7.useViewerStore)();
30312
+ const { height: windowHeight, width: windowWidth } = (0, import_react_native9.useWindowDimensions)();
30026
30313
  const [pagesMode, setPagesMode] = (0, import_react11.useState)(
30027
30314
  documentType === "pdf" || documentType === "comic" ? "thumbnails" : "summary"
30028
30315
  );
@@ -30036,14 +30323,11 @@ var RightSheet = ({
30036
30323
  const t = getStrings(locale);
30037
30324
  const showingNotes = sidebarRightTab === "annotations";
30038
30325
  const sheetHeight = resolveRightSheetHeight({
30039
- windowHeight: import_react_native9.Dimensions.get("window").height,
30326
+ windowHeight,
30040
30327
  showingNotes
30041
30328
  });
30042
- const windowWidth = import_react_native9.Dimensions.get("window").width;
30043
- const gridGutter = 12;
30044
- const gridPadding = 16;
30045
- const cardWidth = (windowWidth - gridPadding * 2 - gridGutter) / 2;
30046
- const frameWidth = cardWidth - 16;
30329
+ const sheetWidth = getNativeSheetWidth(windowWidth);
30330
+ const { cardWidth, frameWidth } = getRightSheetThumbnailLayout(sheetWidth);
30047
30331
  const renderTarget = engine.getRenderTargetType?.();
30048
30332
  const hasNativePageView = Boolean(
30049
30333
  import_react_native9.UIManager.getViewManagerConfig?.("PapyrusPageView")
@@ -30471,7 +30755,9 @@ var RightSheet = ({
30471
30755
  ] }),
30472
30756
  /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_react_native9.Text, { style: [styles9.noteType, { color: accentColor }], children: getAnnotationKindLabel(ann.type, locale) }),
30473
30757
  ann.content ? (() => {
30474
- const parts = resolveNoteQuoteParts(ann.content ?? "");
30758
+ const parts = resolveNoteQuoteParts(
30759
+ ann.content ?? ""
30760
+ );
30475
30761
  return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_react_native9.View, { style: styles9.noteQuoteRow, children: [
30476
30762
  /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
30477
30763
  import_react_native9.View,
@@ -31245,6 +31531,11 @@ var BottomBar_default = BottomBar;
31245
31531
  // components/SettingsSheet.tsx
31246
31532
  var import_react_native12 = require("react-native");
31247
31533
  var import_core10 = require("@papyrus-sdk/core");
31534
+
31535
+ // components/settingsSheetLayout.ts
31536
+ var getSettingsSheetMaxHeight = (windowHeight) => Math.min(640, Math.max(0, windowHeight) * 0.72);
31537
+
31538
+ // components/SettingsSheet.tsx
31248
31539
  var import_jsx_runtime15 = require("react/jsx-runtime");
31249
31540
  var PAGE_THEME_OPTIONS = [
31250
31541
  { value: "normal", labelKey: "themeOriginal" },
@@ -31289,7 +31580,8 @@ var SettingsSheet = ({
31289
31580
  const isPaged = viewMode === "single";
31290
31581
  const isDouble = viewMode === "double";
31291
31582
  const t = getStrings(locale);
31292
- const sheetMaxHeight = Math.min(640, import_react_native12.Dimensions.get("window").height * 0.72);
31583
+ const { height: windowHeight } = (0, import_react_native12.useWindowDimensions)();
31584
+ const sheetMaxHeight = getSettingsSheetMaxHeight(windowHeight);
31293
31585
  const handleTransition = (mode) => {
31294
31586
  if (mode === "paged") {
31295
31587
  setDocumentState({ viewMode: "single" });
@@ -32739,6 +33031,25 @@ var styles17 = import_react_native17.StyleSheet.create({
32739
33031
  var import_react15 = __toESM(require("react"));
32740
33032
  var import_react_native18 = require("react-native");
32741
33033
  var import_core15 = require("@papyrus-sdk/core");
33034
+
33035
+ // components/searchOverlayLayout.ts
33036
+ var getSearchOverlayLayout = (windowWidth) => {
33037
+ if (!Number.isFinite(windowWidth) || windowWidth <= 0) {
33038
+ return { frame: { paddingHorizontal: 12 }, card: null };
33039
+ }
33040
+ if (windowWidth < 768) {
33041
+ return { frame: { paddingHorizontal: 12 }, card: null };
33042
+ }
33043
+ return {
33044
+ frame: { paddingHorizontal: 24 },
33045
+ card: {
33046
+ width: Math.min(640, windowWidth - 48),
33047
+ alignSelf: "center"
33048
+ }
33049
+ };
33050
+ };
33051
+
33052
+ // components/SearchOverlay.tsx
32742
33053
  var import_jsx_runtime21 = require("react/jsx-runtime");
32743
33054
  function SearchOverlay({
32744
33055
  engine,
@@ -32764,6 +33075,8 @@ function SearchOverlay({
32764
33075
  const [isSearching, setIsSearching] = (0, import_react15.useState)(false);
32765
33076
  const searchRequestIdRef = import_react15.default.useRef(0);
32766
33077
  const isDark = uiTheme === "dark";
33078
+ const { width: windowWidth } = (0, import_react_native18.useWindowDimensions)();
33079
+ const overlayLayout = getSearchOverlayLayout(windowWidth);
32767
33080
  const offsets = resolveMobileChromeOffsets(usePapyrusSafeAreaInsets());
32768
33081
  const t = getStrings(locale);
32769
33082
  const searchService = (0, import_react15.useMemo)(() => new import_core15.SearchService(engine), [engine]);
@@ -32799,110 +33112,125 @@ function SearchOverlay({
32799
33112
  onClose();
32800
33113
  };
32801
33114
  if (!visible) return null;
32802
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_react_native18.View, { pointerEvents: "box-none", style: [styles18.frame, { bottom: offsets.search, paddingLeft: offsets.left, paddingRight: offsets.right }], children: /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
33115
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
32803
33116
  import_react_native18.View,
32804
33117
  {
32805
- style: [styles18.card, isDark && styles18.cardDark],
32806
- testID: "papyrus-search-overlay",
32807
- children: [
32808
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_react_native18.View, { style: styles18.inputRow, children: [
32809
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_react_native18.View, { style: [styles18.searchInputWrap, isDark && styles18.searchInputWrapDark], children: [
32810
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(IconSearch, { size: 16, color: isDark ? "#cbd5e1" : "#64748b" }),
32811
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
32812
- import_react_native18.TextInput,
32813
- {
32814
- value: draft,
32815
- onChangeText: setDraft,
32816
- placeholder: t.searchPlaceholder,
32817
- placeholderTextColor: isDark ? "#94a3b8" : "#6b7280",
32818
- style: [styles18.input, isDark && styles18.inputDark],
32819
- autoFocus: true,
32820
- returnKeyType: "search",
32821
- onSubmitEditing: handleSubmit,
32822
- accessibilityLabel: "Search text",
32823
- testID: "papyrus-search-input"
32824
- }
32825
- )
32826
- ] }),
32827
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
32828
- import_react_native18.Pressable,
32829
- {
32830
- onPress: handleClose,
32831
- style: [styles18.closeButton, isDark && styles18.closeButtonDark],
32832
- accessibilityLabel: "Close search",
32833
- children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_react_native18.Text, { style: [styles18.closeText, isDark && styles18.closeTextDark], children: t.cancel })
32834
- }
32835
- )
32836
- ] }),
32837
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_react_native18.View, { style: styles18.metaRow, children: [
32838
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
32839
- import_react_native18.Pressable,
32840
- {
32841
- onPress: prevSearchResult,
32842
- disabled: searchResults.length === 0,
32843
- style: [
32844
- styles18.navButton,
32845
- isDark && styles18.navButtonDark,
32846
- searchResults.length === 0 && styles18.navButtonDisabled
32847
- ],
32848
- accessibilityLabel: "Previous result",
32849
- children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(IconChevronLeft, { size: 16, color: isDark ? "#e5e7eb" : "#111827" })
32850
- }
32851
- ),
32852
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_react_native18.Text, { style: [styles18.metaText, isDark && styles18.metaTextDark], children: isSearching ? t.searching : `${currentCount}/${searchResults.length} ${targetLabel}` }),
32853
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
32854
- import_react_native18.Pressable,
32855
- {
32856
- onPress: nextSearchResult,
32857
- disabled: searchResults.length === 0,
32858
- style: [
32859
- styles18.navButton,
32860
- isDark && styles18.navButtonDark,
32861
- searchResults.length === 0 && styles18.navButtonDisabled
32862
- ],
32863
- accessibilityLabel: "Next result",
32864
- children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(IconChevronRight, { size: 16, color: isDark ? "#e5e7eb" : "#111827" })
32865
- }
32866
- )
32867
- ] }),
32868
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_react_native18.View, { style: styles18.actionsRow, children: [
32869
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
32870
- import_react_native18.Pressable,
32871
- {
32872
- onPress: handleSubmit,
32873
- style: [styles18.primaryAction, { backgroundColor: accentColor }],
32874
- accessibilityLabel: "Run search",
32875
- testID: "papyrus-search-run",
32876
- children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_react_native18.Text, { style: styles18.primaryActionText, children: t.searchGo })
32877
- }
32878
- ),
32879
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
32880
- import_react_native18.Pressable,
32881
- {
32882
- onPress: onOpenResults,
32883
- disabled: searchResults.length === 0,
32884
- style: [
32885
- styles18.secondaryAction,
32886
- isDark && styles18.secondaryActionDark,
32887
- searchResults.length === 0 && styles18.navButtonDisabled
32888
- ],
32889
- accessibilityLabel: "Open all results",
32890
- children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
32891
- import_react_native18.Text,
33118
+ pointerEvents: "box-none",
33119
+ style: [
33120
+ styles18.frame,
33121
+ overlayLayout.frame,
33122
+ {
33123
+ bottom: offsets.search,
33124
+ paddingLeft: Math.max(overlayLayout.frame.paddingHorizontal, offsets.left),
33125
+ paddingRight: Math.max(overlayLayout.frame.paddingHorizontal, offsets.right)
33126
+ }
33127
+ ],
33128
+ children: /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
33129
+ import_react_native18.View,
33130
+ {
33131
+ style: [styles18.card, overlayLayout.card, isDark && styles18.cardDark],
33132
+ testID: "papyrus-search-overlay",
33133
+ children: [
33134
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_react_native18.View, { style: styles18.inputRow, children: [
33135
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_react_native18.View, { style: [styles18.searchInputWrap, isDark && styles18.searchInputWrapDark], children: [
33136
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(IconSearch, { size: 16, color: isDark ? "#cbd5e1" : "#64748b" }),
33137
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
33138
+ import_react_native18.TextInput,
33139
+ {
33140
+ value: draft,
33141
+ onChangeText: setDraft,
33142
+ placeholder: t.searchPlaceholder,
33143
+ placeholderTextColor: isDark ? "#94a3b8" : "#6b7280",
33144
+ style: [styles18.input, isDark && styles18.inputDark],
33145
+ autoFocus: true,
33146
+ returnKeyType: "search",
33147
+ onSubmitEditing: handleSubmit,
33148
+ accessibilityLabel: "Search text",
33149
+ testID: "papyrus-search-input"
33150
+ }
33151
+ )
33152
+ ] }),
33153
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
33154
+ import_react_native18.Pressable,
32892
33155
  {
33156
+ onPress: handleClose,
33157
+ style: [styles18.closeButton, isDark && styles18.closeButtonDark],
33158
+ accessibilityLabel: "Close search",
33159
+ children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_react_native18.Text, { style: [styles18.closeText, isDark && styles18.closeTextDark], children: t.cancel })
33160
+ }
33161
+ )
33162
+ ] }),
33163
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_react_native18.View, { style: styles18.metaRow, children: [
33164
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
33165
+ import_react_native18.Pressable,
33166
+ {
33167
+ onPress: prevSearchResult,
33168
+ disabled: searchResults.length === 0,
33169
+ style: [
33170
+ styles18.navButton,
33171
+ isDark && styles18.navButtonDark,
33172
+ searchResults.length === 0 && styles18.navButtonDisabled
33173
+ ],
33174
+ accessibilityLabel: "Previous result",
33175
+ children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(IconChevronLeft, { size: 16, color: isDark ? "#e5e7eb" : "#111827" })
33176
+ }
33177
+ ),
33178
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_react_native18.Text, { style: [styles18.metaText, isDark && styles18.metaTextDark], children: isSearching ? t.searching : `${currentCount}/${searchResults.length} ${targetLabel}` }),
33179
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
33180
+ import_react_native18.Pressable,
33181
+ {
33182
+ onPress: nextSearchResult,
33183
+ disabled: searchResults.length === 0,
32893
33184
  style: [
32894
- styles18.secondaryActionText,
32895
- isDark && styles18.secondaryActionTextDark
33185
+ styles18.navButton,
33186
+ isDark && styles18.navButtonDark,
33187
+ searchResults.length === 0 && styles18.navButtonDisabled
32896
33188
  ],
32897
- children: t.allResults
33189
+ accessibilityLabel: "Next result",
33190
+ children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(IconChevronRight, { size: 16, color: isDark ? "#e5e7eb" : "#111827" })
32898
33191
  }
32899
33192
  )
32900
- }
32901
- )
32902
- ] })
32903
- ]
33193
+ ] }),
33194
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_react_native18.View, { style: styles18.actionsRow, children: [
33195
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
33196
+ import_react_native18.Pressable,
33197
+ {
33198
+ onPress: handleSubmit,
33199
+ style: [styles18.primaryAction, { backgroundColor: accentColor }],
33200
+ accessibilityLabel: "Run search",
33201
+ testID: "papyrus-search-run",
33202
+ children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_react_native18.Text, { style: styles18.primaryActionText, children: t.searchGo })
33203
+ }
33204
+ ),
33205
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
33206
+ import_react_native18.Pressable,
33207
+ {
33208
+ onPress: onOpenResults,
33209
+ disabled: searchResults.length === 0,
33210
+ style: [
33211
+ styles18.secondaryAction,
33212
+ isDark && styles18.secondaryActionDark,
33213
+ searchResults.length === 0 && styles18.navButtonDisabled
33214
+ ],
33215
+ accessibilityLabel: "Open all results",
33216
+ children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
33217
+ import_react_native18.Text,
33218
+ {
33219
+ style: [
33220
+ styles18.secondaryActionText,
33221
+ isDark && styles18.secondaryActionTextDark
33222
+ ],
33223
+ children: t.allResults
33224
+ }
33225
+ )
33226
+ }
33227
+ )
33228
+ ] })
33229
+ ]
33230
+ }
33231
+ )
32904
33232
  }
32905
- ) });
33233
+ );
32906
33234
  }
32907
33235
  var styles18 = import_react_native18.StyleSheet.create({
32908
33236
  frame: {