@papyrus-sdk/ui-react-native 0.2.28 → 0.2.30

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.mjs CHANGED
@@ -25757,12 +25757,17 @@ var shouldEnableViewerScrollForPageScrub = ({
25757
25757
  isScrubbing
25758
25758
  }) => viewerScrollEnabled && !isScrubbing;
25759
25759
  var resolvePageScrubberTouchPolicy = () => ({
25760
- responderTarget: "pill",
25760
+ responderTarget: "track",
25761
25761
  claimOnStart: true,
25762
25762
  captureOnStart: true,
25763
25763
  captureOnMove: true,
25764
25764
  childConsumesTouch: false
25765
25765
  });
25766
+ var resolvePageScrubberOverlayStyle = () => ({
25767
+ zIndex: 30,
25768
+ elevation: 30
25769
+ });
25770
+ var resolvePageScrubberPointerEvents = () => "box-only";
25766
25771
  var resolvePageScrubberReleaseAction = ({
25767
25772
  hasMoved,
25768
25773
  pendingPage
@@ -25826,6 +25831,23 @@ var resolvePageScrubberPage = ({
25826
25831
  Math.min(pageCount, Math.round(ratio * (pageCount - 1)) + 1)
25827
25832
  );
25828
25833
  };
25834
+ var isPageScrubberTrackYTrusted = (trackY, windowHeight) => Number.isFinite(trackY) && Number.isFinite(windowHeight) && trackY >= 0 && trackY <= windowHeight;
25835
+ var resolvePageScrubberGesturePosition = ({
25836
+ moveY,
25837
+ dy,
25838
+ trackY,
25839
+ windowHeight,
25840
+ trackHeight,
25841
+ thumbHeight,
25842
+ startThumbTop
25843
+ }) => {
25844
+ if (isPageScrubberTrackYTrusted(trackY, windowHeight)) {
25845
+ return moveY - trackY;
25846
+ }
25847
+ const travel = Math.max(0, trackHeight - thumbHeight);
25848
+ const nextThumbTop = Math.max(0, Math.min(travel, startThumbTop + dy));
25849
+ return nextThumbTop + thumbHeight / 2;
25850
+ };
25829
25851
 
25830
25852
  // components/viewerNavigation.ts
25831
25853
  var resolveViewerScrollTarget = (pageIndex, isDouble) => ({
@@ -25880,6 +25902,15 @@ var resolvePositiveInt = (value, fallback, min, max) => {
25880
25902
  const rounded = Math.round(value);
25881
25903
  return Math.max(min, Math.min(max, rounded));
25882
25904
  };
25905
+ var scrollViewerListToOffset = (list, offset, animated) => {
25906
+ if (list === null) return;
25907
+ const nativeScrollRef = list.getNativeScrollRef?.();
25908
+ if (nativeScrollRef?.scrollTo) {
25909
+ nativeScrollRef.scrollTo({ y: offset, animated });
25910
+ return;
25911
+ }
25912
+ list.scrollToOffset?.({ offset, animated });
25913
+ };
25883
25914
  var Viewer = ({
25884
25915
  engine,
25885
25916
  virtualWindowSize,
@@ -25952,6 +25983,7 @@ var Viewer = ({
25952
25983
  const pendingScrollTimeoutRef = useRef4(
25953
25984
  null
25954
25985
  );
25986
+ const pendingScrollFrameRef = useRef4(null);
25955
25987
  const pendingChromeShowTimeoutRef = useRef4(null);
25956
25988
  const chromeVisibleRef = useRef4(mobileChromeVisible);
25957
25989
  const lastScrollOffsetYRef = useRef4(0);
@@ -25959,6 +25991,7 @@ var Viewer = ({
25959
25991
  const scrollUpAccumRef = useRef4(0);
25960
25992
  const [layoutRevision, setLayoutRevision] = useState4(0);
25961
25993
  const [selectionDragActive, setSelectionDragActive] = useState4(false);
25994
+ const [programmaticScrollActive, setProgrammaticScrollActive] = useState4(false);
25962
25995
  const selectionDragActiveRef = useRef4(false);
25963
25996
  const [gestureScrollLockActive, setGestureScrollLockActive] = useState4(false);
25964
25997
  const gestureScrollLockActiveRef = useRef4(false);
@@ -26053,6 +26086,7 @@ var Viewer = ({
26053
26086
  pendingScrollTargetRef.current = null;
26054
26087
  pendingScrollAttemptsRef.current = 0;
26055
26088
  clearPendingScrollRetry();
26089
+ setProgrammaticScrollActive(false);
26056
26090
  }, [clearPendingScrollRetry]);
26057
26091
  const clearPendingChromeShow = useCallback3(() => {
26058
26092
  if (pendingChromeShowTimeoutRef.current) {
@@ -26107,6 +26141,10 @@ var Viewer = ({
26107
26141
  cancelAnimationFrame(pinchAnchorRestoreFrameRef.current);
26108
26142
  }
26109
26143
  clearPendingScrollRetry();
26144
+ if (pendingScrollFrameRef.current !== null) {
26145
+ cancelAnimationFrame(pendingScrollFrameRef.current);
26146
+ pendingScrollFrameRef.current = null;
26147
+ }
26110
26148
  clearPendingChromeShow();
26111
26149
  },
26112
26150
  [clearPendingChromeShow, clearPendingScrollRetry]
@@ -26960,12 +26998,20 @@ var Viewer = ({
26960
26998
  (animated) => {
26961
26999
  const target = pendingScrollTargetRef.current;
26962
27000
  if (target === null || listRef.current === null) return;
26963
- listRef.current.scrollToOffset({
26964
- offset: Math.max(0, getFallbackOffsetForIndex(target.listIndex)),
26965
- animated
27001
+ setViewerScrollEnabledNative(true);
27002
+ if (pendingScrollFrameRef.current !== null) {
27003
+ cancelAnimationFrame(pendingScrollFrameRef.current);
27004
+ }
27005
+ pendingScrollFrameRef.current = requestAnimationFrame(() => {
27006
+ pendingScrollFrameRef.current = null;
27007
+ const nextTarget = pendingScrollTargetRef.current;
27008
+ const list = listRef.current;
27009
+ if (nextTarget === null || list === null) return;
27010
+ const offset = getFallbackOffsetForIndex(nextTarget.listIndex);
27011
+ scrollViewerListToOffset(list, offset, animated);
26966
27012
  });
26967
27013
  },
26968
- [getFallbackOffsetForIndex]
27014
+ [getFallbackOffsetForIndex, setViewerScrollEnabledNative]
26969
27015
  );
26970
27016
  const restoreOrientationScrollOffset = useCallback3(() => {
26971
27017
  if (pendingOrientationRestoreWidthRef.current !== windowWidth || pageCount <= 0 || isSingle || isWebView) {
@@ -27064,6 +27110,7 @@ var Viewer = ({
27064
27110
  const target = resolveViewerScrollTarget(scrollToPageSignal, isDouble);
27065
27111
  pendingScrollTargetRef.current = target;
27066
27112
  pendingScrollAttemptsRef.current = 0;
27113
+ setProgrammaticScrollActive(true);
27067
27114
  clearPendingScrollRetry();
27068
27115
  setDocumentStateTracked(
27069
27116
  {
@@ -27319,6 +27366,89 @@ var Viewer = ({
27319
27366
  windowWidth
27320
27367
  ]
27321
27368
  );
27369
+ const continuousList = /* @__PURE__ */ jsx6(
27370
+ FlatList,
27371
+ {
27372
+ ref: listRef,
27373
+ nestedScrollEnabled: true,
27374
+ data: isDouble ? rows : pages,
27375
+ style: { width: documentSurfaceWidth },
27376
+ initialNumToRender: FLATLIST_INITIAL_NUM_TO_RENDER,
27377
+ windowSize: resolvedWindowSize,
27378
+ maxToRenderPerBatch: resolvedMaxToRenderPerBatch,
27379
+ updateCellsBatchingPeriod: FLATLIST_UPDATE_CELLS_BATCHING_PERIOD,
27380
+ removeClippedSubviews: resolvedRemoveClippedSubviews,
27381
+ getItemLayout,
27382
+ keyExtractor,
27383
+ contentContainerStyle: styles4.listContent,
27384
+ renderItem,
27385
+ onViewableItemsChanged,
27386
+ viewabilityConfig: { itemVisiblePercentThreshold: 60 },
27387
+ scrollEnabled: pageScrubResolvedScrollEnabled || programmaticScrollActive,
27388
+ onLayout: () => {
27389
+ captureViewerFrame(listRef.current);
27390
+ restoreOrientationScrollOffset();
27391
+ scrollToPendingTarget(false);
27392
+ },
27393
+ onContentSizeChange: (_, height) => {
27394
+ viewerContentHeightRef.current = height;
27395
+ scrollToPendingTarget(false);
27396
+ },
27397
+ onScrollToIndexFailed: ({ index, averageItemLength }) => {
27398
+ const dataLength = isDouble ? rows.length : pages.length;
27399
+ if (index < 0 || index >= dataLength) return;
27400
+ const existingTarget = pendingScrollTargetRef.current;
27401
+ pendingScrollTargetRef.current = isDouble ? existingTarget?.listIndex === index ? existingTarget : resolveViewerScrollTarget(rows[index]?.left ?? index * 2, true) : resolveViewerScrollTarget(index, false);
27402
+ const offset = Math.max(0, getFallbackOffsetForIndex(index));
27403
+ scrollViewerListToOffset(listRef.current, offset, false);
27404
+ if (!isDouble) {
27405
+ ensurePageDimensions(index);
27406
+ } else {
27407
+ const row = rows[index];
27408
+ if (row) {
27409
+ ensurePageDimensions(row.left);
27410
+ if (row.right !== null) {
27411
+ ensurePageDimensions(row.right);
27412
+ }
27413
+ }
27414
+ }
27415
+ scheduleScrollRetry("onScrollToIndexFailed");
27416
+ if (perfEnabled) {
27417
+ logPerfEvent("Viewer", "scrollToIndexFailed", {
27418
+ index,
27419
+ averageItemLength,
27420
+ fallbackOffset: offset,
27421
+ fallbackSource: "cached-item-layout",
27422
+ itemCount: dataLength,
27423
+ retryAttempt: pendingScrollAttemptsRef.current
27424
+ });
27425
+ }
27426
+ },
27427
+ onScroll: (event) => handleViewerScroll(event, "continuous"),
27428
+ onScrollBeginDrag: perfEnabled ? () => {
27429
+ scrollMonitorRef.current.begin("continuous.beginDrag");
27430
+ } : void 0,
27431
+ onMomentumScrollBegin: perfEnabled ? () => {
27432
+ scrollMonitorRef.current.begin("continuous.momentumBegin");
27433
+ } : void 0,
27434
+ onScrollEndDrag: perfEnabled ? () => {
27435
+ scrollMonitorRef.current.end("continuous.endDrag");
27436
+ endViewerScroll("continuous.endDrag");
27437
+ sampleMemory("Viewer", "continuous.endDrag", {
27438
+ pageCount
27439
+ });
27440
+ } : void 0,
27441
+ onMomentumScrollEnd: perfEnabled ? () => {
27442
+ scrollMonitorRef.current.end("continuous.momentumEnd");
27443
+ endViewerScroll("continuous.momentumEnd");
27444
+ sampleMemory("Viewer", "continuous.momentumEnd", {
27445
+ pageCount
27446
+ });
27447
+ } : void 0,
27448
+ scrollEventThrottle: 16,
27449
+ showsVerticalScrollIndicator: false
27450
+ }
27451
+ );
27322
27452
  if (isWebView) {
27323
27453
  return /* @__PURE__ */ jsx6(View4, { style: [styles4.container, isDark && styles4.containerDark], children: /* @__PURE__ */ jsx6(
27324
27454
  WebViewViewer_default,
@@ -27353,6 +27483,7 @@ var Viewer = ({
27353
27483
  {
27354
27484
  ref: horizontalScrollRef,
27355
27485
  horizontal: true,
27486
+ nestedScrollEnabled: true,
27356
27487
  scrollEnabled: !gestureScrollLockActive && !pageScrubActive && documentSurfaceWidth > windowWidth,
27357
27488
  showsHorizontalScrollIndicator: false,
27358
27489
  onScroll: (event) => {
@@ -27437,101 +27568,21 @@ var Viewer = ({
27437
27568
  ]
27438
27569
  }
27439
27570
  ],
27440
- children: /* @__PURE__ */ jsx6(
27571
+ children: documentSurfaceWidth > windowWidth + 1 ? /* @__PURE__ */ jsx6(
27441
27572
  ScrollView,
27442
27573
  {
27443
27574
  ref: horizontalScrollRef,
27444
27575
  horizontal: true,
27445
- scrollEnabled: !gestureScrollLockActive && !pageScrubActive && documentSurfaceWidth > windowWidth,
27576
+ nestedScrollEnabled: true,
27577
+ scrollEnabled: !gestureScrollLockActive && !pageScrubActive,
27446
27578
  showsHorizontalScrollIndicator: false,
27447
27579
  onScroll: (event) => {
27448
27580
  horizontalScrollOffsetRef.current = event.nativeEvent.contentOffset?.x ?? 0;
27449
27581
  },
27450
27582
  scrollEventThrottle: 16,
27451
- children: /* @__PURE__ */ jsx6(
27452
- FlatList,
27453
- {
27454
- ref: listRef,
27455
- data: isDouble ? rows : pages,
27456
- style: { width: documentSurfaceWidth },
27457
- initialNumToRender: FLATLIST_INITIAL_NUM_TO_RENDER,
27458
- windowSize: resolvedWindowSize,
27459
- maxToRenderPerBatch: resolvedMaxToRenderPerBatch,
27460
- updateCellsBatchingPeriod: FLATLIST_UPDATE_CELLS_BATCHING_PERIOD,
27461
- removeClippedSubviews: resolvedRemoveClippedSubviews,
27462
- getItemLayout,
27463
- keyExtractor,
27464
- contentContainerStyle: styles4.listContent,
27465
- renderItem,
27466
- onViewableItemsChanged,
27467
- viewabilityConfig: { itemVisiblePercentThreshold: 60 },
27468
- scrollEnabled: pageScrubResolvedScrollEnabled,
27469
- onLayout: () => {
27470
- captureViewerFrame(listRef.current);
27471
- restoreOrientationScrollOffset();
27472
- scrollToPendingTarget(false);
27473
- },
27474
- onContentSizeChange: (_, height) => {
27475
- viewerContentHeightRef.current = height;
27476
- scrollToPendingTarget(false);
27477
- },
27478
- onScrollToIndexFailed: ({ index, averageItemLength }) => {
27479
- const dataLength = isDouble ? rows.length : pages.length;
27480
- if (index < 0 || index >= dataLength) return;
27481
- const existingTarget = pendingScrollTargetRef.current;
27482
- pendingScrollTargetRef.current = isDouble ? existingTarget?.listIndex === index ? existingTarget : resolveViewerScrollTarget(rows[index]?.left ?? index * 2, true) : resolveViewerScrollTarget(index, false);
27483
- const offset = Math.max(0, getFallbackOffsetForIndex(index));
27484
- listRef.current?.scrollToOffset({ offset, animated: false });
27485
- if (!isDouble) {
27486
- ensurePageDimensions(index);
27487
- } else {
27488
- const row = rows[index];
27489
- if (row) {
27490
- ensurePageDimensions(row.left);
27491
- if (row.right !== null) {
27492
- ensurePageDimensions(row.right);
27493
- }
27494
- }
27495
- }
27496
- scheduleScrollRetry("onScrollToIndexFailed");
27497
- if (perfEnabled) {
27498
- logPerfEvent("Viewer", "scrollToIndexFailed", {
27499
- index,
27500
- averageItemLength,
27501
- fallbackOffset: offset,
27502
- fallbackSource: "cached-item-layout",
27503
- itemCount: dataLength,
27504
- retryAttempt: pendingScrollAttemptsRef.current
27505
- });
27506
- }
27507
- },
27508
- onScroll: (event) => handleViewerScroll(event, "continuous"),
27509
- onScrollBeginDrag: perfEnabled ? () => {
27510
- scrollMonitorRef.current.begin("continuous.beginDrag");
27511
- } : void 0,
27512
- onMomentumScrollBegin: perfEnabled ? () => {
27513
- scrollMonitorRef.current.begin("continuous.momentumBegin");
27514
- } : void 0,
27515
- onScrollEndDrag: perfEnabled ? () => {
27516
- scrollMonitorRef.current.end("continuous.endDrag");
27517
- endViewerScroll("continuous.endDrag");
27518
- sampleMemory("Viewer", "continuous.endDrag", {
27519
- pageCount
27520
- });
27521
- } : void 0,
27522
- onMomentumScrollEnd: perfEnabled ? () => {
27523
- scrollMonitorRef.current.end("continuous.momentumEnd");
27524
- endViewerScroll("continuous.momentumEnd");
27525
- sampleMemory("Viewer", "continuous.momentumEnd", {
27526
- pageCount
27527
- });
27528
- } : void 0,
27529
- scrollEventThrottle: 16,
27530
- showsVerticalScrollIndicator: false
27531
- }
27532
- )
27583
+ children: continuousList
27533
27584
  }
27534
- )
27585
+ ) : continuousList
27535
27586
  }
27536
27587
  ) }) });
27537
27588
  };
@@ -31965,6 +32016,8 @@ function ProgressPill({
31965
32016
  const isDark = uiTheme === "dark";
31966
32017
  const offsets = resolveMobileChromeOffsets(usePapyrusSafeAreaInsets());
31967
32018
  const { height: windowHeight } = useWindowDimensions7();
32019
+ const windowHeightRef = useRef9(windowHeight);
32020
+ windowHeightRef.current = windowHeight;
31968
32021
  const trackHeight = Math.max(
31969
32022
  180,
31970
32023
  Math.min(520, windowHeight - offsets.progress - offsets.bottom - 132)
@@ -32015,6 +32068,7 @@ function ProgressPill({
32015
32068
  const thumbTopRef = useRef9(new Animated3.Value(thumbTop));
32016
32069
  const thumbTopSnapshotRef = useRef9(thumbTop);
32017
32070
  thumbTopSnapshotRef.current = thumbTop;
32071
+ const scrubStartThumbTopRef = useRef9(0);
32018
32072
  const scrubberMetricsRef = useRef9({ trackHeight, thumbHeight, pageCount });
32019
32073
  scrubberMetricsRef.current = { trackHeight, thumbHeight, pageCount };
32020
32074
  useEffect11(() => {
@@ -32082,6 +32136,7 @@ function ProgressPill({
32082
32136
  onScrubbingChangeRef.current?.(true);
32083
32137
  hasMovedRef.current = false;
32084
32138
  longPressTriggeredRef.current = false;
32139
+ scrubStartThumbTopRef.current = thumbTopSnapshotRef.current;
32085
32140
  scrubNavigationControllerRef.current.begin();
32086
32141
  pendingReleasedScrubPageRef.current = null;
32087
32142
  setScrubPreviewPage(currentPageRef.current);
@@ -32103,7 +32158,18 @@ function ProgressPill({
32103
32158
  clearTimeout(longPressTimerRef.current);
32104
32159
  longPressTimerRef.current = null;
32105
32160
  }
32106
- scrubToPositionRef.current(gestureState.moveY - trackYRef.current);
32161
+ const { trackHeight: trackHeight2, thumbHeight: thumbHeight2 } = scrubberMetricsRef.current;
32162
+ scrubToPositionRef.current(
32163
+ resolvePageScrubberGesturePosition({
32164
+ moveY: gestureState.moveY,
32165
+ dy: gestureState.dy,
32166
+ trackY: trackYRef.current,
32167
+ windowHeight: windowHeightRef.current,
32168
+ trackHeight: trackHeight2,
32169
+ thumbHeight: thumbHeight2,
32170
+ startThumbTop: scrubStartThumbTopRef.current
32171
+ })
32172
+ );
32107
32173
  },
32108
32174
  onPanResponderRelease: () => {
32109
32175
  if (longPressTimerRef.current !== null) {
@@ -32157,6 +32223,7 @@ function ProgressPill({
32157
32223
  pointerEvents: "box-none",
32158
32224
  style: [
32159
32225
  styles17.frame,
32226
+ resolvePageScrubberOverlayStyle(),
32160
32227
  {
32161
32228
  top: offsets.progress,
32162
32229
  right: offsets.right
@@ -32166,6 +32233,7 @@ function ProgressPill({
32166
32233
  View17,
32167
32234
  {
32168
32235
  ref: scrubberRef,
32236
+ pointerEvents: resolvePageScrubberPointerEvents(),
32169
32237
  style: [styles17.scrubber, { height: trackHeight }],
32170
32238
  ...scrubberPanHandlers,
32171
32239
  onLayout: () => {
@@ -32932,6 +33000,7 @@ export {
32932
33000
  BottomBar_default as BottomBar,
32933
33001
  CoverPreview_default as CoverPreview,
32934
33002
  DocumentActionsSheet,
33003
+ IconPageNav,
32935
33004
  InfoSheet,
32936
33005
  MOBILE_CHROME_METRICS,
32937
33006
  MobilePerfProvider,