@papyrus-sdk/ui-react-native 0.2.35-beta.10 → 0.2.35-beta.11

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
@@ -21828,6 +21828,7 @@ https://github.com/nodeca/pako/blob/main/LICENSE
21828
21828
  if (selectionSession === documentSessionId && selectionRendition === rendition) epubAnnotationRenderers.forEach(renderer => renderer.schedule());
21829
21829
  }));
21830
21830
  rendition.on('relocated', (location) => {
21831
+ if (selectionSession !== documentSessionId || selectionRendition !== rendition) return;
21831
21832
  const start = location && location.start;
21832
21833
  let index = start && Number.isInteger(start.index) ? start.index : -1;
21833
21834
  if (index < 0 && start && start.href) index = getSpineIndexByHref(start.href);
@@ -21946,10 +21947,11 @@ https://github.com/nodeca/pako/blob/main/LICENSE
21946
21947
  sendEvent('VIEWER_SCROLL', { offsetY });
21947
21948
  };
21948
21949
  const handleTouchStart = (event) => {
21949
- touchStart = getTouchPoint(event);
21950
+ touchStart = event?.touches?.length > 1 ? null : getTouchPoint(event);
21950
21951
  epubScrollDiagnostics && epubScrollDiagnostics.touchStart(event);
21951
21952
  };
21952
21953
  const handleTouchMove = (event) => {
21954
+ if (event?.touches?.length > 1) touchStart = null;
21953
21955
  epubScrollDiagnostics && epubScrollDiagnostics.touchMove(event);
21954
21956
  };
21955
21957
  const handleTouchEnd = (event) => {
@@ -21957,7 +21959,15 @@ https://github.com/nodeca/pako/blob/main/LICENSE
21957
21959
  const start = touchStart;
21958
21960
  touchStart = null;
21959
21961
  const selectedText = event?.target?.ownerDocument?.defaultView?.getSelection?.()?.toString().trim() || '';
21960
- if (!selectedText && start && end && Math.hypot(end.x - start.x, end.y - start.y) <= 12) {
21962
+ if (!selectedText && start && end && epubViewMode === 'single' && Math.abs(end.x-start.x) >= 48 && Math.abs(end.x-start.x) > Math.abs(end.y-start.y)*1.5) {
21963
+ const active = rendition;
21964
+ const interactionSession = documentSessionId;
21965
+ epubNavigationQueue = epubNavigationQueue.catch(() => {}).then(() => {
21966
+ if (active !== rendition || interactionSession !== documentSessionId) return;
21967
+ return end.x < start.x ? active.next() : active.prev();
21968
+ });
21969
+ epubNavigationQueue.catch(error => sendEvent('EPUB_NAVIGATION_ERROR', {message:String(error)}));
21970
+ } else if (!selectedText && start && end && Math.hypot(end.x - start.x, end.y - start.y) <= 12) {
21961
21971
  sendEvent('VIEWER_TAP', {});
21962
21972
  }
21963
21973
  epubScrollDiagnostics && epubScrollDiagnostics.touchEnd(event);
@@ -22002,6 +22012,8 @@ https://github.com/nodeca/pako/blob/main/LICENSE
22002
22012
  return { pageCount, outline };
22003
22013
  };
22004
22014
 
22015
+ let epubNavigationQueue = Promise.resolve();
22016
+ let epubNavigationRequest = 0;
22005
22017
  const displayEpubPage = async (pageIndex) => {
22006
22018
  if (!rendition) return;
22007
22019
  const item = spineItems[pageIndex];
@@ -22011,9 +22023,18 @@ https://github.com/nodeca/pako/blob/main/LICENSE
22011
22023
  target,
22012
22024
  pageIndex,
22013
22025
  });
22014
- await rendition.display(target);
22015
- currentPage = pageIndex + 1;
22016
- sendState();
22026
+ const activeRendition = rendition;
22027
+ const session = documentSessionId;
22028
+ const request = ++epubNavigationRequest;
22029
+ const navigation = epubNavigationQueue.catch(() => {}).then(async () => {
22030
+ if (request !== epubNavigationRequest || session !== documentSessionId || activeRendition !== rendition) return;
22031
+ await activeRendition.display(target);
22032
+ if (request !== epubNavigationRequest || session !== documentSessionId || activeRendition !== rendition) return;
22033
+ currentPage = pageIndex + 1;
22034
+ sendState();
22035
+ });
22036
+ epubNavigationQueue = navigation;
22037
+ await navigation;
22017
22038
  };
22018
22039
 
22019
22040
  const getTextContent = async (pageIndex) => {
@@ -22115,6 +22136,7 @@ https://github.com/nodeca/pako/blob/main/LICENSE
22115
22136
  };
22116
22137
 
22117
22138
  let nativeMenuSelection = null;
22139
+ let epubViewMode = "continuous";
22118
22140
 
22119
22141
  const handleCommand = async (message) => {
22120
22142
  const { id, kind, payload } = message;
@@ -22127,6 +22149,9 @@ https://github.com/nodeca/pako/blob/main/LICENSE
22127
22149
  epubAnnotations = [];
22128
22150
  annotationDocumentId = undefined;
22129
22151
  zoom = 1.0;
22152
+ epubViewMode = "continuous";
22153
+ epubNavigationRequest += 1;
22154
+ epubNavigationQueue = Promise.resolve();
22130
22155
 
22131
22156
  if (currentType === 'text') {
22132
22157
  const result = await loadText(
@@ -22181,17 +22206,23 @@ https://github.com/nodeca/pako/blob/main/LICENSE
22181
22206
  epubAnnotationRenderers.forEach(renderer => renderer.schedule());
22182
22207
  } else {
22183
22208
  const annotation = epubAnnotations.find(a => a.id === payload.annotationId);
22184
- if (!annotation) throw new Error('Annotation not available');
22209
+ if (!annotation || (annotation.anchor.documentId && annotation.anchor.documentId !== annotationDocumentId)) throw new Error('Annotation not available for this document');
22185
22210
  // Navigation uses the CFI, never a synthetic percentage/page rectangle.
22186
22211
  const navigationSession = documentSessionId;
22187
22212
  const activeRendition = rendition;
22188
22213
  // Open the confirmed chapter first, resolve its quote, then navigate its actual range.
22189
- await activeRendition.display(annotation.anchor.href);
22190
- if(navigationSession !== documentSessionId || activeRendition !== rendition)throw new Error('Stale EPUB navigation');
22191
- const contents = activeRendition.getContents().find(c => spineItems[c.sectionIndex]?.href === annotation.anchor.href);
22192
- const range = contents && window.PapyrusEpubAnnotations.resolveRange(contents,annotation.anchor);
22193
- if(!range)throw new Error('EPUB anchor unresolved');
22194
- await activeRendition.display(contents.cfiFromRange(range));
22214
+ epubNavigationRequest += 1;
22215
+ const navigation = epubNavigationQueue.catch(() => {}).then(async () => {
22216
+ if(navigationSession !== documentSessionId || activeRendition !== rendition)throw new Error('Stale EPUB navigation');
22217
+ await activeRendition.display(annotation.anchor.href);
22218
+ if(navigationSession !== documentSessionId || activeRendition !== rendition)throw new Error('Stale EPUB navigation');
22219
+ const contents = activeRendition.getContents().find(c => spineItems[c.sectionIndex]?.href === annotation.anchor.href);
22220
+ const range = contents && window.PapyrusEpubAnnotations.resolveRange(contents,annotation.anchor);
22221
+ if(!range)throw new Error('EPUB anchor unresolved');
22222
+ await activeRendition.display(contents.cfiFromRange(range));
22223
+ });
22224
+ epubNavigationQueue = navigation;
22225
+ await navigation;
22195
22226
  }
22196
22227
  sendResponse(id,true,null); return;
22197
22228
  }
@@ -22218,6 +22249,33 @@ https://github.com/nodeca/pako/blob/main/LICENSE
22218
22249
  return;
22219
22250
  }
22220
22251
 
22252
+ if (kind === 'epub-turn-page') {
22253
+ if (epubViewMode !== 'single') {sendResponse(id,true,null); return;}
22254
+ if (currentType !== 'epub' || payload.documentSessionId !== documentSessionId) throw new Error('Stale EPUB navigation');
22255
+ const active = rendition;
22256
+ epubNavigationQueue = epubNavigationQueue.catch(() => {}).then(() => {
22257
+ if (active !== rendition || payload.documentSessionId !== documentSessionId) return;
22258
+ return payload.direction < 0 ? active.prev() : active.next();
22259
+ });
22260
+ await epubNavigationQueue;
22261
+ sendResponse(id,true,null); return;
22262
+ }
22263
+
22264
+ if (kind === 'set-epub-view-mode') {
22265
+ if (currentType !== 'epub' || payload.documentSessionId !== documentSessionId) throw new Error('Stale EPUB layout session');
22266
+ epubViewMode = payload.viewMode === 'single' ? 'single' : 'continuous';
22267
+ const active = rendition;
22268
+ epubNavigationQueue = epubNavigationQueue.catch(() => {}).then(() => {
22269
+ if (active !== rendition || payload.documentSessionId !== documentSessionId) return;
22270
+ const flow = epubViewMode === 'single' ? 'paginated' : 'scrolled-continuous';
22271
+ if (active.settings.flow === flow) return;
22272
+ active.flow(flow);
22273
+ return active.q.enqueue(() => Promise.resolve());
22274
+ });
22275
+ await epubNavigationQueue;
22276
+ sendResponse(id,true,null); return;
22277
+ }
22278
+
22221
22279
  if (kind === 'set-zoom') {
22222
22280
  zoom = Math.max(0.5, Math.min(4.0, payload.zoom || 1.0));
22223
22281
  applyZoom();
@@ -25770,7 +25828,7 @@ var WebViewViewer = ({
25770
25828
  onTap
25771
25829
  }) => {
25772
25830
  const webViewRef = useRef2(null);
25773
- const { pageTheme, annotations, isLoaded, locale, annotationColor, annotationOpacity, addAnnotation, beginAnnotationDraft, setSelectedAnnotation } = useViewerStore2();
25831
+ const { pageTheme, viewMode, annotations, isLoaded, locale, annotationColor, annotationOpacity, addAnnotation, beginAnnotationDraft, setSelectedAnnotation } = useViewerStore2();
25774
25832
  const [selection, setSelection] = useState2(null);
25775
25833
  const t = getStrings(locale);
25776
25834
  const bridgeEngine = engine;
@@ -25851,6 +25909,10 @@ var WebViewViewer = ({
25851
25909
  (note !== void 0 ? beginAnnotationDraft : addAnnotation)(createContextualAnnotation({ id: `annotation-${Date.now()}-${Math.random().toString(36).slice(2)}`, anchor: selected.anchor, pageIndex: selected.pageIndex, style, color: annotationColor, opacity: annotationOpacity, note }));
25852
25910
  setSelection(null);
25853
25911
  };
25912
+ useEffect2(() => {
25913
+ if (!isLoaded) return;
25914
+ webViewRef.current?.postMessage(JSON.stringify({ id: "epub-layout", kind: "set-epub-view-mode", payload: { viewMode, documentSessionId: bridgeEngine.getWebViewDocumentSessionId?.() } }));
25915
+ }, [isLoaded, viewMode, bridgeEngine]);
25854
25916
  const sendSelectionCommand = (key) => {
25855
25917
  webViewRef.current?.postMessage(JSON.stringify({
25856
25918
  type: "epub-selection-action",
@@ -29499,7 +29561,8 @@ import {
29499
29561
  Text as Text5,
29500
29562
  Pressable as Pressable6,
29501
29563
  StyleSheet as StyleSheet11,
29502
- useWindowDimensions as useWindowDimensions4
29564
+ useWindowDimensions as useWindowDimensions4,
29565
+ Platform as Platform6
29503
29566
  } from "react-native";
29504
29567
  import { useViewerStore as useViewerStore9 } from "@papyrus-sdk/core";
29505
29568
  import Animated3, { useAnimatedStyle } from "react-native-reanimated";
@@ -30067,6 +30130,7 @@ var Topbar = ({
30067
30130
  {
30068
30131
  style: [
30069
30132
  styles11.container,
30133
+ Platform6.OS === "ios" && styles11.containerIos,
30070
30134
  isDark && styles11.containerDark,
30071
30135
  isLandscape && styles11.containerLandscape
30072
30136
  ],
@@ -30223,7 +30287,8 @@ var styles11 = StyleSheet11.create({
30223
30287
  maxWidth: MOBILE_CHROME_METRICS.maxFloatingWidth,
30224
30288
  marginTop: 10,
30225
30289
  paddingHorizontal: 14,
30226
- paddingVertical: 10,
30290
+ height: MOBILE_CHROME_METRICS.topbarHeight,
30291
+ paddingVertical: 0,
30227
30292
  backgroundColor: "rgba(255,255,255,0.88)",
30228
30293
  borderWidth: 1,
30229
30294
  borderColor: "rgba(255,255,255,0.72)",
@@ -30240,6 +30305,10 @@ var styles11 = StyleSheet11.create({
30240
30305
  backgroundColor: "rgba(15,17,21,0.88)",
30241
30306
  borderColor: "rgba(71,85,105,0.48)"
30242
30307
  },
30308
+ containerIos: {
30309
+ height: MOBILE_CHROME_METRICS.topbarHeight,
30310
+ paddingVertical: 0
30311
+ },
30243
30312
  containerLandscape: {
30244
30313
  maxWidth: void 0,
30245
30314
  marginTop: 0
@@ -31389,7 +31458,7 @@ import {
31389
31458
  } from "react";
31390
31459
  import {
31391
31460
  Image as Image2,
31392
- Platform as Platform6,
31461
+ Platform as Platform7,
31393
31462
  Pressable as Pressable8,
31394
31463
  StyleSheet as StyleSheet13,
31395
31464
  Text as Text7,
@@ -31470,7 +31539,7 @@ var PageThumbnail = ({
31470
31539
  if (!layoutReady || !useNativePreview || !shouldRenderPreview) return;
31471
31540
  const viewTag = findNodeHandle2(viewRef.current);
31472
31541
  if (!viewTag) return;
31473
- const isNative = Platform6.OS === "android" || Platform6.OS === "ios";
31542
+ const isNative = Platform7.OS === "android" || Platform7.OS === "ios";
31474
31543
  const renderScale = isNative ? 2 / Math.max(zoom, 0.5) : 2;
31475
31544
  void engine.renderPage(pageIndex, viewTag, renderScale);
31476
31545
  }, [
@@ -32395,14 +32464,14 @@ var RightSheet_default = RightSheet;
32395
32464
 
32396
32465
  // components/AnnotationEditor.tsx
32397
32466
  import { useEffect as useEffect13, useRef as useRef9, useState as useState12 } from "react";
32398
- import { AccessibilityInfo as AccessibilityInfo2, Alert as Alert3, Animated as Animated4, KeyboardAvoidingView, Modal as Modal3, Platform as Platform7, Pressable as Pressable9, ScrollView as ScrollView4, StyleSheet as StyleSheet14, Text as Text8, TextInput as TextInput2, View as View14 } from "react-native";
32467
+ import { AccessibilityInfo as AccessibilityInfo2, Alert as Alert3, Animated as Animated4, KeyboardAvoidingView, Modal as Modal3, Platform as Platform8, Pressable as Pressable9, ScrollView as ScrollView4, StyleSheet as StyleSheet14, Text as Text8, TextInput as TextInput2, View as View14 } from "react-native";
32399
32468
  import { getAnnotationEditPatch, getAnnotationMarkup as getAnnotationMarkup2, getAnnotationNote as getAnnotationNote2, getAnnotationQuote as getAnnotationQuote2, useViewerStore as useViewerStore12 } from "@papyrus-sdk/core";
32400
32469
  import { Fragment as Fragment3, jsx as jsx18, jsxs as jsxs13 } from "react/jsx-runtime";
32401
32470
  var COLORS = ["#fbbf24", "#fb7185", "#60a5fa", "#34d399", "#c084fc"];
32402
- var AnnotationEditor = () => {
32471
+ var AnnotationEditor = ({ documentId }) => {
32403
32472
  const { annotations, annotationDraft, clearAnnotationDraft, addAnnotation, selectedAnnotationId, updateAnnotation, removeAnnotation, setSelectedAnnotation, uiTheme, locale, accentColor } = useViewerStore12();
32404
32473
  const annotation = annotationDraft?.id === selectedAnnotationId ? annotationDraft : annotations.find((a) => a.id === selectedAnnotationId);
32405
- const supported = annotation && annotation.type !== "ink";
32474
+ const supported = annotation && annotation.type !== "ink" && (!documentId || !annotation.anchor?.documentId || annotation.anchor.documentId === documentId);
32406
32475
  const [editing, setEditing] = useState12(false);
32407
32476
  const [draft, setDraft] = useState12("");
32408
32477
  const [color, setColor] = useState12(COLORS[0]);
@@ -32462,12 +32531,12 @@ var AnnotationEditor = () => {
32462
32531
  const remove = () => Alert3.alert(t.deleteAnnotation, t.deleteAnnotationConfirmation, [{ text: t.cancel, style: "cancel" }, { text: t.deleteAnnotation, style: "destructive", onPress: () => deleteAnnotationAndClearSelection(annotation.id, removeAnnotation, setSelectedAnnotation) }]);
32463
32532
  const textStyle = { color: dark ? "#f9fafb" : "#111827" };
32464
32533
  const quote = getAnnotationQuote2(annotation);
32465
- return /* @__PURE__ */ jsx18(Modal3, { visible: true, transparent: true, animationType: "none", onRequestClose: close, children: /* @__PURE__ */ jsxs13(KeyboardAvoidingView, { behavior: Platform7.OS === "ios" ? "padding" : void 0, style: styles14.host, children: [
32534
+ return /* @__PURE__ */ jsx18(Modal3, { visible: true, transparent: true, animationType: "none", onRequestClose: close, children: /* @__PURE__ */ jsxs13(KeyboardAvoidingView, { behavior: Platform8.OS === "ios" ? "padding" : void 0, style: styles14.host, children: [
32466
32535
  /* @__PURE__ */ jsx18(Pressable9, { style: StyleSheet14.absoluteFill, onPress: close, accessibilityLabel: t.close }),
32467
32536
  /* @__PURE__ */ jsxs13(Animated4.View, { accessibilityViewIsModal: true, style: [styles14.card, { backgroundColor: dark ? "#17191f" : "#fff", marginBottom: Math.max(16, insets.bottom), opacity: progress, transform: [{ translateY: progress.interpolate({ inputRange: [0, 1], outputRange: [12, 0] }) }] }], children: [
32468
32537
  /* @__PURE__ */ jsxs13(View14, { style: styles14.header, children: [
32469
32538
  /* @__PURE__ */ jsx18(Text8, { style: [styles14.title, textStyle], children: editing ? t.editNote : t.annotationNote }),
32470
- /* @__PURE__ */ jsx18(Pressable9, { onPress: close, accessibilityRole: "button", accessibilityLabel: t.close, style: styles14.button, children: /* @__PURE__ */ jsx18(Text8, { style: textStyle, children: "\xD7" }) })
32539
+ /* @__PURE__ */ jsx18(Pressable9, { onPress: close, accessibilityRole: "button", accessibilityLabel: t.close, style: [styles14.button, { borderRadius: 22, backgroundColor: dark ? "#242936" : "#f1f5f9" }], children: /* @__PURE__ */ jsx18(IconClose, { size: 20, color: textStyle.color }) })
32471
32540
  ] }),
32472
32541
  /* @__PURE__ */ jsxs13(ScrollView4, { style: styles14.content, keyboardShouldPersistTaps: "handled", children: [
32473
32542
  quote ? /* @__PURE__ */ jsx18(Text8, { style: [styles14.quote, textStyle], selectable: true, children: quote }) : null,
@@ -32501,7 +32570,7 @@ var styles14 = StyleSheet14.create({ host: { flex: 1, justifyContent: "flex-end"
32501
32570
  var AnnotationEditor_default = AnnotationEditor;
32502
32571
 
32503
32572
  // components/BottomBar.tsx
32504
- import { View as View15, Pressable as Pressable10, StyleSheet as StyleSheet15, useWindowDimensions as useWindowDimensions7 } from "react-native";
32573
+ import { View as View15, Text as Text9, Pressable as Pressable10, StyleSheet as StyleSheet15, useWindowDimensions as useWindowDimensions7 } from "react-native";
32505
32574
  import { useViewerStore as useViewerStore13 } from "@papyrus-sdk/core";
32506
32575
  import Animated5, { useAnimatedStyle as useAnimatedStyle2 } from "react-native-reanimated";
32507
32576
 
@@ -32555,15 +32624,22 @@ function resolveAnnotateButtonAction(input) {
32555
32624
  }
32556
32625
 
32557
32626
  // components/BottomBar.tsx
32558
- import { jsx as jsx19, jsxs as jsxs14 } from "react/jsx-runtime";
32627
+ import { Fragment as Fragment4, jsx as jsx19, jsxs as jsxs14 } from "react/jsx-runtime";
32559
32628
  var BottomBar = ({
32560
32629
  documentType,
32561
32630
  onOpenInfo,
32562
32631
  onOpenSettings,
32563
- onOpenDestination
32632
+ onOpenDestination,
32633
+ onTurnPage,
32634
+ onNavigateToPage,
32635
+ onOpenPages
32564
32636
  }) => {
32565
32637
  const {
32566
32638
  activeMobileDestination,
32639
+ viewMode,
32640
+ comicLayoutMode,
32641
+ currentPage,
32642
+ pageCount,
32567
32643
  mobileDockVisible,
32568
32644
  setDocumentState,
32569
32645
  uiTheme,
@@ -32600,6 +32676,15 @@ var BottomBar = ({
32600
32676
  activeMobileDestination,
32601
32677
  toolDockOpen
32602
32678
  });
32679
+ const paginated = documentType !== "text" && (documentType === "comic" ? comicLayoutMode === "single" : viewMode === "single");
32680
+ if (paginated) {
32681
+ layout.leftSlots.push(...layout.rightSlots.filter((slot) => slot.key === "search"));
32682
+ layout.rightSlots = [];
32683
+ }
32684
+ const turnPage = (direction) => {
32685
+ if (onTurnPage) onTurnPage(direction);
32686
+ else onNavigateToPage?.(currentPage + direction);
32687
+ };
32603
32688
  const slotMeta = {
32604
32689
  annotate: {
32605
32690
  label: t.tools,
@@ -32725,7 +32810,15 @@ var BottomBar = ({
32725
32810
  isDark && styles15.islandDark
32726
32811
  ],
32727
32812
  testID: "papyrus-floating-bottom-dock",
32728
- children: layout.rightSlots.map((slot) => {
32813
+ children: paginated ? /* @__PURE__ */ jsxs14(Fragment4, { children: [
32814
+ /* @__PURE__ */ jsx19(Pressable10, { accessibilityRole: "button", accessibilityLabel: locale === "pt-BR" ? "P\xE1gina anterior" : "Previous page", disabled: !dockVisible || !onTurnPage && currentPage <= 1, onPress: () => turnPage(-1), style: styles15.iconOnlyItem, children: /* @__PURE__ */ jsx19(IconChevronLeft, { size: MOBILE_CHROME_METRICS.iconSize, color: iconColor(false) }) }),
32815
+ /* @__PURE__ */ jsx19(Pressable10, { accessibilityRole: "button", accessibilityLabel: locale === "pt-BR" ? "Ir para p\xE1gina" : "Go to page", onPress: onOpenPages, style: [styles15.iconOnlyItem, { minWidth: 56 }], children: /* @__PURE__ */ jsxs14(Text9, { style: { color: iconColor(false), fontWeight: "700", fontSize: 13, lineHeight: 18, includeFontPadding: false }, children: [
32816
+ currentPage,
32817
+ "/",
32818
+ pageCount
32819
+ ] }) }),
32820
+ /* @__PURE__ */ jsx19(Pressable10, { accessibilityRole: "button", accessibilityLabel: locale === "pt-BR" ? "Pr\xF3xima p\xE1gina" : "Next page", disabled: !dockVisible || !onTurnPage && currentPage >= pageCount, onPress: () => turnPage(1), style: styles15.iconOnlyItem, children: /* @__PURE__ */ jsx19(IconChevronRight, { size: MOBILE_CHROME_METRICS.iconSize, color: iconColor(false) }) })
32821
+ ] }) : layout.rightSlots.map((slot) => {
32729
32822
  const meta = slotMeta[slot.key];
32730
32823
  const Icon = meta.icon;
32731
32824
  return /* @__PURE__ */ jsx19(
@@ -32788,8 +32881,9 @@ var styles15 = StyleSheet15.create({
32788
32881
  island: {
32789
32882
  flexDirection: "row",
32790
32883
  alignItems: "center",
32791
- paddingVertical: 8,
32792
- paddingHorizontal: 10,
32884
+ height: MOBILE_CHROME_METRICS.bottomBarVisualHeight,
32885
+ paddingVertical: 0,
32886
+ paddingHorizontal: 6,
32793
32887
  backgroundColor: "rgba(255,255,255,0.9)",
32794
32888
  borderWidth: 1,
32795
32889
  borderColor: "rgba(255,255,255,0.72)",
@@ -32815,6 +32909,8 @@ var styles15 = StyleSheet15.create({
32815
32909
  borderColor: "rgba(71,85,105,0.48)"
32816
32910
  },
32817
32911
  iconOnlyItem: {
32912
+ minWidth: 44,
32913
+ height: 44,
32818
32914
  alignItems: "center",
32819
32915
  justifyContent: "center",
32820
32916
  paddingHorizontal: MOBILE_CHROME_METRICS.bottomBarItemPaddingHorizontal,
@@ -32845,9 +32941,9 @@ var BottomBar_default = BottomBar;
32845
32941
  // components/SettingsSheet.tsx
32846
32942
  import {
32847
32943
  View as View16,
32848
- Text as Text9,
32944
+ Text as Text10,
32849
32945
  Pressable as Pressable11,
32850
- Platform as Platform8,
32946
+ Platform as Platform9,
32851
32947
  StyleSheet as StyleSheet16,
32852
32948
  useWindowDimensions as useWindowDimensions8
32853
32949
  } from "react-native";
@@ -32898,7 +32994,8 @@ var SettingsSheet = ({
32898
32994
  engine,
32899
32995
  visible,
32900
32996
  onClose,
32901
- documentType = "pdf"
32997
+ documentType = "pdf",
32998
+ onOpenInfo
32902
32999
  }) => {
32903
33000
  const {
32904
33001
  viewMode,
@@ -32963,22 +33060,23 @@ var SettingsSheet = ({
32963
33060
  contentContainerStyle: styles16.sheetContent,
32964
33061
  showsVerticalScrollIndicator: false,
32965
33062
  children: [
33063
+ onOpenInfo ? /* @__PURE__ */ jsx20(Pressable11, { accessibilityRole: "button", onPress: onOpenInfo, style: { minHeight: 44, justifyContent: "center", marginBottom: 16 }, children: /* @__PURE__ */ jsx20(Text10, { style: [styles16.sectionTitle, isDark && styles16.sectionTitleDark], children: t.info }) }) : null,
32966
33064
  (documentType === "text" || documentType === "epub") && /* @__PURE__ */ jsxs15(View16, { style: styles16.section, children: [
32967
- /* @__PURE__ */ jsx20(Text9, { style: [styles16.sectionTitle, isDark && styles16.sectionTitleDark], children: locale === "pt-BR" ? "Tamanho da fonte" : "Font size" }),
33065
+ /* @__PURE__ */ jsx20(Text10, { style: [styles16.sectionTitle, isDark && styles16.sectionTitleDark], children: locale === "pt-BR" ? "Tamanho da fonte" : "Font size" }),
32968
33066
  /* @__PURE__ */ jsxs15(View16, { style: { flexDirection: "row", alignItems: "center", gap: 12 }, children: [
32969
33067
  [-0.1, 0.1].map((delta) => /* @__PURE__ */ jsx20(Pressable11, { accessibilityRole: "button", accessibilityLabel: locale === "pt-BR" ? delta < 0 ? "Diminuir fonte" : "Aumentar fonte" : delta < 0 ? "Decrease font" : "Increase font", onPress: () => {
32970
33068
  const next = Math.max(0.7, Math.min(2, zoom + delta));
32971
33069
  if (documentType === "epub") engine.setZoom(next);
32972
33070
  setDocumentState({ zoom: next });
32973
- }, style: { minWidth: 44, minHeight: 44, justifyContent: "center", alignItems: "center" }, children: /* @__PURE__ */ jsx20(Text9, { style: { fontSize: 20, color: isDark ? "#fff" : "#111" }, children: delta < 0 ? "A\u2212" : "A+" }) }, delta)),
32974
- /* @__PURE__ */ jsxs15(Text9, { style: { color: isDark ? "#fff" : "#111" }, children: [
33071
+ }, style: { minWidth: 44, minHeight: 44, justifyContent: "center", alignItems: "center" }, children: /* @__PURE__ */ jsx20(Text10, { style: { fontSize: 20, color: isDark ? "#fff" : "#111" }, children: delta < 0 ? "A\u2212" : "A+" }) }, delta)),
33072
+ /* @__PURE__ */ jsxs15(Text10, { style: { color: isDark ? "#fff" : "#111" }, children: [
32975
33073
  Math.round(zoom * 100),
32976
33074
  "%"
32977
33075
  ] })
32978
33076
  ] })
32979
33077
  ] }),
32980
33078
  documentType === "comic" && /* @__PURE__ */ jsxs15(View16, { style: styles16.section, children: [
32981
- /* @__PURE__ */ jsx20(Text9, { style: [styles16.sectionTitle, isDark && styles16.sectionTitleDark], children: t.comicMode }),
33079
+ /* @__PURE__ */ jsx20(Text10, { style: [styles16.sectionTitle, isDark && styles16.sectionTitleDark], children: t.comicMode }),
32982
33080
  /* @__PURE__ */ jsx20(View16, { style: styles16.optionRow, children: ["single", "continuous"].map((mode) => {
32983
33081
  const active = comicLayoutMode === mode;
32984
33082
  return /* @__PURE__ */ jsx20(
@@ -32986,12 +33084,12 @@ var SettingsSheet = ({
32986
33084
  {
32987
33085
  onPress: () => setDocumentState({ comicLayoutMode: mode }),
32988
33086
  style: [styles16.optionButton, isDark && styles16.optionButtonDark, active && styles16.optionButtonActive, active && { backgroundColor: accentColor }],
32989
- children: /* @__PURE__ */ jsx20(Text9, { style: [styles16.optionText, isDark && styles16.optionTextDark, active && styles16.optionTextActive], children: mode === "single" ? t.comicSingle : t.comicContinuous })
33087
+ children: /* @__PURE__ */ jsx20(Text10, { style: [styles16.optionText, isDark && styles16.optionTextDark, active && styles16.optionTextActive], children: mode === "single" ? t.comicSingle : t.comicContinuous })
32990
33088
  },
32991
33089
  mode
32992
33090
  );
32993
33091
  }) }),
32994
- /* @__PURE__ */ jsx20(Text9, { style: [styles16.sectionTitle, isDark && styles16.sectionTitleDark], children: t.comicFit }),
33092
+ /* @__PURE__ */ jsx20(Text10, { style: [styles16.sectionTitle, isDark && styles16.sectionTitleDark], children: t.comicFit }),
32995
33093
  /* @__PURE__ */ jsx20(View16, { style: styles16.optionRow, children: ["width", "page"].map((mode) => {
32996
33094
  const active = comicFitMode === mode;
32997
33095
  return /* @__PURE__ */ jsx20(
@@ -32999,12 +33097,12 @@ var SettingsSheet = ({
32999
33097
  {
33000
33098
  onPress: () => setDocumentState({ comicFitMode: mode }),
33001
33099
  style: [styles16.optionButton, isDark && styles16.optionButtonDark, active && styles16.optionButtonActive, active && { backgroundColor: accentColor }],
33002
- children: /* @__PURE__ */ jsx20(Text9, { style: [styles16.optionText, isDark && styles16.optionTextDark, active && styles16.optionTextActive], children: mode === "width" ? t.comicFitWidth : t.comicFitPage })
33100
+ children: /* @__PURE__ */ jsx20(Text10, { style: [styles16.optionText, isDark && styles16.optionTextDark, active && styles16.optionTextActive], children: mode === "width" ? t.comicFitWidth : t.comicFitPage })
33003
33101
  },
33004
33102
  mode
33005
33103
  );
33006
33104
  }) }),
33007
- /* @__PURE__ */ jsx20(Text9, { style: [styles16.sectionTitle, isDark && styles16.sectionTitleDark], children: t.comicDirection }),
33105
+ /* @__PURE__ */ jsx20(Text10, { style: [styles16.sectionTitle, isDark && styles16.sectionTitleDark], children: t.comicDirection }),
33008
33106
  /* @__PURE__ */ jsx20(View16, { style: styles16.optionRow, children: ["ltr", "rtl"].map((direction) => {
33009
33107
  const active = comicReadingDirection === direction;
33010
33108
  return /* @__PURE__ */ jsx20(
@@ -33012,7 +33110,7 @@ var SettingsSheet = ({
33012
33110
  {
33013
33111
  onPress: () => setDocumentState({ comicReadingDirection: direction }),
33014
33112
  style: [styles16.optionButton, isDark && styles16.optionButtonDark, active && styles16.optionButtonActive, active && { backgroundColor: accentColor }],
33015
- children: /* @__PURE__ */ jsx20(Text9, { style: [styles16.optionText, isDark && styles16.optionTextDark, active && styles16.optionTextActive], children: direction === "ltr" ? t.comicLtr : t.comicRtl })
33113
+ children: /* @__PURE__ */ jsx20(Text10, { style: [styles16.optionText, isDark && styles16.optionTextDark, active && styles16.optionTextActive], children: direction === "ltr" ? t.comicLtr : t.comicRtl })
33016
33114
  },
33017
33115
  direction
33018
33116
  );
@@ -33020,7 +33118,7 @@ var SettingsSheet = ({
33020
33118
  ] }),
33021
33119
  /* @__PURE__ */ jsxs15(View16, { style: styles16.section, children: [
33022
33120
  /* @__PURE__ */ jsx20(
33023
- Text9,
33121
+ Text10,
33024
33122
  {
33025
33123
  style: [styles16.sectionTitle, isDark && styles16.sectionTitleDark],
33026
33124
  children: t.appearance
@@ -33038,7 +33136,7 @@ var SettingsSheet = ({
33038
33136
  uiTheme === "light" && { backgroundColor: accentColor }
33039
33137
  ],
33040
33138
  children: /* @__PURE__ */ jsx20(
33041
- Text9,
33139
+ Text10,
33042
33140
  {
33043
33141
  style: [
33044
33142
  styles16.optionText,
@@ -33061,7 +33159,7 @@ var SettingsSheet = ({
33061
33159
  uiTheme === "dark" && { backgroundColor: accentColor }
33062
33160
  ],
33063
33161
  children: /* @__PURE__ */ jsx20(
33064
- Text9,
33162
+ Text10,
33065
33163
  {
33066
33164
  style: [
33067
33165
  styles16.optionText,
@@ -33077,7 +33175,7 @@ var SettingsSheet = ({
33077
33175
  ] }),
33078
33176
  /* @__PURE__ */ jsxs15(View16, { style: styles16.section, children: [
33079
33177
  /* @__PURE__ */ jsx20(
33080
- Text9,
33178
+ Text10,
33081
33179
  {
33082
33180
  style: [styles16.sectionTitle, isDark && styles16.sectionTitleDark],
33083
33181
  children: t.pageTheme
@@ -33098,7 +33196,7 @@ var SettingsSheet = ({
33098
33196
  children: [
33099
33197
  /* @__PURE__ */ jsx20(ThemeSwatch, { value: option.value }),
33100
33198
  /* @__PURE__ */ jsx20(
33101
- Text9,
33199
+ Text10,
33102
33200
  {
33103
33201
  style: [
33104
33202
  styles16.themeOptionLabel,
@@ -33116,7 +33214,7 @@ var SettingsSheet = ({
33116
33214
  ] }),
33117
33215
  documentType !== "comic" && documentType !== "text" && /* @__PURE__ */ jsxs15(View16, { style: styles16.section, children: [
33118
33216
  /* @__PURE__ */ jsx20(
33119
- Text9,
33217
+ Text10,
33120
33218
  {
33121
33219
  style: [styles16.sectionTitle, isDark && styles16.sectionTitleDark],
33122
33220
  children: t.pageTransition
@@ -33134,7 +33232,7 @@ var SettingsSheet = ({
33134
33232
  (!isPaged || isDouble) && { backgroundColor: accentColor }
33135
33233
  ],
33136
33234
  children: /* @__PURE__ */ jsx20(
33137
- Text9,
33235
+ Text10,
33138
33236
  {
33139
33237
  style: [
33140
33238
  styles16.optionText,
@@ -33157,7 +33255,7 @@ var SettingsSheet = ({
33157
33255
  isPaged && { backgroundColor: accentColor }
33158
33256
  ],
33159
33257
  children: /* @__PURE__ */ jsx20(
33160
- Text9,
33258
+ Text10,
33161
33259
  {
33162
33260
  style: [
33163
33261
  styles16.optionText,
@@ -33173,7 +33271,7 @@ var SettingsSheet = ({
33173
33271
  ] }),
33174
33272
  documentType !== "comic" && documentType !== "text" && /* @__PURE__ */ jsxs15(View16, { style: styles16.section, children: [
33175
33273
  /* @__PURE__ */ jsx20(
33176
- Text9,
33274
+ Text10,
33177
33275
  {
33178
33276
  style: [styles16.sectionTitle, isDark && styles16.sectionTitleDark],
33179
33277
  children: t.layout
@@ -33191,7 +33289,7 @@ var SettingsSheet = ({
33191
33289
  !isDouble && { backgroundColor: accentColor }
33192
33290
  ],
33193
33291
  children: /* @__PURE__ */ jsx20(
33194
- Text9,
33292
+ Text10,
33195
33293
  {
33196
33294
  style: [
33197
33295
  styles16.optionText,
@@ -33214,7 +33312,7 @@ var SettingsSheet = ({
33214
33312
  isDouble && { backgroundColor: accentColor }
33215
33313
  ],
33216
33314
  children: /* @__PURE__ */ jsx20(
33217
- Text9,
33315
+ Text10,
33218
33316
  {
33219
33317
  style: [
33220
33318
  styles16.optionText,
@@ -33230,7 +33328,7 @@ var SettingsSheet = ({
33230
33328
  ] }),
33231
33329
  documentType !== "comic" && documentType !== "text" && /* @__PURE__ */ jsxs15(View16, { style: styles16.section, children: [
33232
33330
  /* @__PURE__ */ jsx20(
33233
- Text9,
33331
+ Text10,
33234
33332
  {
33235
33333
  style: [styles16.sectionTitle, isDark && styles16.sectionTitleDark],
33236
33334
  children: t.rotate
@@ -33243,7 +33341,7 @@ var SettingsSheet = ({
33243
33341
  onPress: () => handleRotate("counterclockwise"),
33244
33342
  style: [styles16.optionButton, isDark && styles16.optionButtonDark],
33245
33343
  children: /* @__PURE__ */ jsx20(
33246
- Text9,
33344
+ Text10,
33247
33345
  {
33248
33346
  style: [styles16.optionText, isDark && styles16.optionTextDark],
33249
33347
  children: t.counterclockwise
@@ -33251,13 +33349,13 @@ var SettingsSheet = ({
33251
33349
  )
33252
33350
  }
33253
33351
  ),
33254
- Platform8.OS === "ios" && /* @__PURE__ */ jsx20(
33352
+ Platform9.OS === "ios" && /* @__PURE__ */ jsx20(
33255
33353
  Pressable11,
33256
33354
  {
33257
33355
  onPress: handleResetRotation,
33258
33356
  style: [styles16.optionButton, isDark && styles16.optionButtonDark],
33259
33357
  children: /* @__PURE__ */ jsx20(
33260
- Text9,
33358
+ Text10,
33261
33359
  {
33262
33360
  style: [styles16.optionText, isDark && styles16.optionTextDark],
33263
33361
  children: t.rotationOriginal
@@ -33271,7 +33369,7 @@ var SettingsSheet = ({
33271
33369
  onPress: () => handleRotate("clockwise"),
33272
33370
  style: [styles16.optionButton, isDark && styles16.optionButtonDark],
33273
33371
  children: /* @__PURE__ */ jsx20(
33274
- Text9,
33372
+ Text10,
33275
33373
  {
33276
33374
  style: [styles16.optionText, isDark && styles16.optionTextDark],
33277
33375
  children: t.clockwise
@@ -33283,7 +33381,7 @@ var SettingsSheet = ({
33283
33381
  ] }),
33284
33382
  documentType !== "text" && /* @__PURE__ */ jsxs15(View16, { style: styles16.section, children: [
33285
33383
  /* @__PURE__ */ jsx20(
33286
- Text9,
33384
+ Text10,
33287
33385
  {
33288
33386
  style: [styles16.sectionTitle, isDark && styles16.sectionTitleDark],
33289
33387
  children: t.zoom
@@ -33298,7 +33396,7 @@ var SettingsSheet = ({
33298
33396
  children: /* @__PURE__ */ jsx20(IconZoomOut, { size: 16, color: isDark ? "#e5e7eb" : "#111827" })
33299
33397
  }
33300
33398
  ),
33301
- /* @__PURE__ */ jsx20(View16, { style: styles16.zoomValue, children: /* @__PURE__ */ jsxs15(Text9, { style: [styles16.zoomText, isDark && styles16.zoomTextDark], children: [
33399
+ /* @__PURE__ */ jsx20(View16, { style: styles16.zoomValue, children: /* @__PURE__ */ jsxs15(Text10, { style: [styles16.zoomText, isDark && styles16.zoomTextDark], children: [
33302
33400
  Math.round(zoom * 100),
33303
33401
  "%"
33304
33402
  ] }) }),
@@ -33314,7 +33412,7 @@ var SettingsSheet = ({
33314
33412
  ] }),
33315
33413
  /* @__PURE__ */ jsxs15(View16, { style: styles16.section, children: [
33316
33414
  /* @__PURE__ */ jsx20(
33317
- Text9,
33415
+ Text10,
33318
33416
  {
33319
33417
  style: [styles16.sectionTitle, isDark && styles16.sectionTitleDark],
33320
33418
  children: t.language
@@ -33332,7 +33430,7 @@ var SettingsSheet = ({
33332
33430
  locale === "en" && { backgroundColor: accentColor }
33333
33431
  ],
33334
33432
  children: /* @__PURE__ */ jsx20(
33335
- Text9,
33433
+ Text10,
33336
33434
  {
33337
33435
  style: [
33338
33436
  styles16.optionText,
@@ -33355,7 +33453,7 @@ var SettingsSheet = ({
33355
33453
  locale === "pt-BR" && { backgroundColor: accentColor }
33356
33454
  ],
33357
33455
  children: /* @__PURE__ */ jsx20(
33358
- Text9,
33456
+ Text10,
33359
33457
  {
33360
33458
  style: [
33361
33459
  styles16.optionText,
@@ -33512,7 +33610,7 @@ import { useEffect as useEffect14, useMemo as useMemo8, useRef as useRef10, useS
33512
33610
  import {
33513
33611
  ActivityIndicator,
33514
33612
  StyleSheet as StyleSheet17,
33515
- Text as Text10,
33613
+ Text as Text11,
33516
33614
  UIManager as UIManager2,
33517
33615
  View as View17,
33518
33616
  findNodeHandle as findNodeHandle3
@@ -33635,12 +33733,12 @@ var CoverPreview = ({
33635
33733
  }
33636
33734
  };
33637
33735
  if (!shouldRender || !canRender) {
33638
- return /* @__PURE__ */ jsx21(View17, { style: [styles17.container, style], children: placeholder ?? /* @__PURE__ */ jsx21(View17, { style: styles17.placeholder, children: /* @__PURE__ */ jsx21(Text10, { style: styles17.placeholderText, children: "Preview" }) }) });
33736
+ return /* @__PURE__ */ jsx21(View17, { style: [styles17.container, style], children: placeholder ?? /* @__PURE__ */ jsx21(View17, { style: styles17.placeholder, children: /* @__PURE__ */ jsx21(Text11, { style: styles17.placeholderText, children: "Preview" }) }) });
33639
33737
  }
33640
33738
  return /* @__PURE__ */ jsxs16(View17, { style: [styles17.container, style], onLayout: handleLayout, children: [
33641
33739
  /* @__PURE__ */ jsx21(View17, { style: styles17.previewFrame, pointerEvents: allowInteraction ? "auto" : "none", children: isPdf ? /* @__PURE__ */ jsx21(PapyrusPageView3, { ref: viewRef, style: styles17.pageView }) : engine && /* @__PURE__ */ jsx21(WebViewViewer_default, { engine }) }),
33642
33740
  showLoading && loading && /* @__PURE__ */ jsx21(View17, { pointerEvents: "none", style: styles17.loadingOverlay, children: loadingIndicator ?? /* @__PURE__ */ jsx21(ActivityIndicator, { size: "small", color: "#2563eb" }) }),
33643
- error && /* @__PURE__ */ jsx21(View17, { pointerEvents: "none", style: styles17.errorOverlay, children: /* @__PURE__ */ jsx21(Text10, { style: styles17.errorText, children: "Preview unavailable" }) })
33741
+ error && /* @__PURE__ */ jsx21(View17, { pointerEvents: "none", style: styles17.errorOverlay, children: /* @__PURE__ */ jsx21(Text11, { style: styles17.errorText, children: "Preview unavailable" }) })
33644
33742
  ] });
33645
33743
  };
33646
33744
  var styles17 = StyleSheet17.create({
@@ -33695,7 +33793,7 @@ import { Keyboard as Keyboard2, View as View23, StyleSheet as StyleSheet24 } fro
33695
33793
  import { useViewerStore as useViewerStore21 } from "@papyrus-sdk/core";
33696
33794
 
33697
33795
  // components/DocumentActionsSheet.tsx
33698
- import { StyleSheet as StyleSheet18, Text as Text11, View as View18 } from "react-native";
33796
+ import { StyleSheet as StyleSheet18, Text as Text12, View as View18 } from "react-native";
33699
33797
  import { useViewerStore as useViewerStore15 } from "@papyrus-sdk/core";
33700
33798
  import { jsx as jsx22, jsxs as jsxs17 } from "react/jsx-runtime";
33701
33799
  function DocumentActionsSheet({
@@ -33732,7 +33830,7 @@ function DocumentActionsSheet({
33732
33830
  borderColor: palette.divider
33733
33831
  }
33734
33832
  ],
33735
- children: /* @__PURE__ */ jsx22(Text11, { style: [styles18.actionText, { color: palette.text }], children: "Share" })
33833
+ children: /* @__PURE__ */ jsx22(Text12, { style: [styles18.actionText, { color: palette.text }], children: "Share" })
33736
33834
  }
33737
33835
  ),
33738
33836
  /* @__PURE__ */ jsx22(
@@ -33745,7 +33843,7 @@ function DocumentActionsSheet({
33745
33843
  borderColor: palette.divider
33746
33844
  }
33747
33845
  ],
33748
- children: /* @__PURE__ */ jsx22(Text11, { style: [styles18.actionText, { color: palette.text }], children: "Export" })
33846
+ children: /* @__PURE__ */ jsx22(Text12, { style: [styles18.actionText, { color: palette.text }], children: "Export" })
33749
33847
  }
33750
33848
  )
33751
33849
  ] })
@@ -33770,7 +33868,7 @@ var styles18 = StyleSheet18.create({
33770
33868
  });
33771
33869
 
33772
33870
  // components/InfoSheet.tsx
33773
- import { StyleSheet as StyleSheet19, Text as Text12, View as View19 } from "react-native";
33871
+ import { StyleSheet as StyleSheet19, Text as Text13, View as View19 } from "react-native";
33774
33872
  import { useViewerStore as useViewerStore16 } from "@papyrus-sdk/core";
33775
33873
 
33776
33874
  // components/infoSheetModel.ts
@@ -33924,15 +34022,15 @@ function InfoSheet({
33924
34022
  contentContainerStyle: styles19.contentInner,
33925
34023
  showsVerticalScrollIndicator: false,
33926
34024
  children: [
33927
- /* @__PURE__ */ jsx23(Text12, { style: [styles19.sectionTitle, { color: palette.mutedText }], children: isPortuguese ? "Resumo do documento" : "Document summary" }),
34025
+ /* @__PURE__ */ jsx23(Text13, { style: [styles19.sectionTitle, { color: palette.mutedText }], children: isPortuguese ? "Resumo do documento" : "Document summary" }),
33928
34026
  /* @__PURE__ */ jsx23(View19, { style: [styles19.rows, { borderTopColor: palette.divider }], children: rows.map((row) => /* @__PURE__ */ jsxs18(
33929
34027
  View19,
33930
34028
  {
33931
34029
  style: [styles19.row, { borderBottomColor: palette.divider }],
33932
34030
  children: [
33933
- /* @__PURE__ */ jsx23(Text12, { style: [styles19.label, { color: palette.mutedText }], children: row.label }),
34031
+ /* @__PURE__ */ jsx23(Text13, { style: [styles19.label, { color: palette.mutedText }], children: row.label }),
33934
34032
  /* @__PURE__ */ jsx23(
33935
- Text12,
34033
+ Text13,
33936
34034
  {
33937
34035
  style: [styles19.value, { color: palette.text }],
33938
34036
  selectable: true,
@@ -33995,7 +34093,7 @@ var styles19 = StyleSheet19.create({
33995
34093
  });
33996
34094
 
33997
34095
  // components/OverflowSheet.tsx
33998
- import { Pressable as Pressable12, StyleSheet as StyleSheet20, Text as Text13, View as View20 } from "react-native";
34096
+ import { Pressable as Pressable12, StyleSheet as StyleSheet20, Text as Text14, View as View20 } from "react-native";
33999
34097
  import { useViewerStore as useViewerStore17 } from "@papyrus-sdk/core";
34000
34098
  import { jsx as jsx24 } from "react/jsx-runtime";
34001
34099
  var actionLabels = [{ key: "actions", label: "Document actions" }];
@@ -34035,7 +34133,7 @@ function OverflowSheet({
34035
34133
  ],
34036
34134
  accessibilityRole: "button",
34037
34135
  accessibilityLabel: action.label,
34038
- children: /* @__PURE__ */ jsx24(Text13, { style: [styles20.actionText, { color: palette.text }], children: action.label })
34136
+ children: /* @__PURE__ */ jsx24(Text14, { style: [styles20.actionText, { color: palette.text }], children: action.label })
34039
34137
  },
34040
34138
  action.key
34041
34139
  )) })
@@ -34060,7 +34158,7 @@ import {
34060
34158
  PanResponder as PanResponder2,
34061
34159
  Pressable as Pressable13,
34062
34160
  StyleSheet as StyleSheet21,
34063
- Text as Text14,
34161
+ Text as Text15,
34064
34162
  View as View21,
34065
34163
  useWindowDimensions as useWindowDimensions9
34066
34164
  } from "react-native";
@@ -34083,9 +34181,11 @@ import { jsx as jsx25, jsxs as jsxs19 } from "react/jsx-runtime";
34083
34181
  var clampPercent = (value) => Math.max(0, Math.min(100, Math.round(value)));
34084
34182
  function ProgressPill({
34085
34183
  documentType,
34184
+ navigationInDock = false,
34086
34185
  onPress,
34087
34186
  onOpenPageJump,
34088
34187
  onNavigateToPage,
34188
+ onTurnPage,
34089
34189
  onScrubbingChange
34090
34190
  }) {
34091
34191
  const {
@@ -34212,7 +34312,7 @@ function ProgressPill({
34212
34312
  onPress: () => onPressRef.current(),
34213
34313
  style: [styles21.singlePill, isDark && styles21.pillDark],
34214
34314
  testID: "papyrus-progress-text",
34215
- children: /* @__PURE__ */ jsxs19(Text14, { style: [styles21.label, isDark && styles21.labelDark], children: [
34315
+ children: /* @__PURE__ */ jsxs19(Text15, { style: [styles21.label, isDark && styles21.labelDark], children: [
34216
34316
  progress,
34217
34317
  "%"
34218
34318
  ] })
@@ -34223,14 +34323,15 @@ function ProgressPill({
34223
34323
  }
34224
34324
  const progressViewMode = documentType === "comic" ? comicLayoutMode === "single" ? "single" : "continuous" : viewMode;
34225
34325
  const pillMode = resolveProgressPillMode(progressViewMode, currentPage, pageCount);
34326
+ if (pillMode.kind === "navigation" && navigationInDock) return null;
34226
34327
  if (pillMode.kind === "navigation") {
34227
- const previousDisabled = pillMode.previousPage === null || !onNavigateToPage;
34228
- const nextDisabled = pillMode.nextPage === null || !onNavigateToPage;
34328
+ const previousDisabled = !onTurnPage && (pillMode.previousPage === null || !onNavigateToPage);
34329
+ const nextDisabled = !onTurnPage && (pillMode.nextPage === null || !onNavigateToPage);
34229
34330
  return /* @__PURE__ */ jsx25(
34230
34331
  View21,
34231
34332
  {
34232
34333
  pointerEvents: "box-none",
34233
- style: [styles21.frame, styles21.singleFrame, { top: offsets.progress, right: offsets.right }],
34334
+ style: [{ position: "absolute", zIndex: 18, bottom: offsets.bottom + MOBILE_CHROME_METRICS.bottomBarVisualHeight + 12, left: offsets.left, right: offsets.right, alignItems: "center" }],
34234
34335
  children: /* @__PURE__ */ jsxs19(View21, { style: [styles21.singlePill, isDark && styles21.pillDark], children: [
34235
34336
  /* @__PURE__ */ jsx25(
34236
34337
  Pressable13,
@@ -34239,10 +34340,10 @@ function ProgressPill({
34239
34340
  accessibilityLabel: t.previousPage,
34240
34341
  accessibilityState: { disabled: previousDisabled },
34241
34342
  disabled: previousDisabled,
34242
- onPress: () => pillMode.previousPage !== null && onNavigateToPageRef.current?.(pillMode.previousPage),
34343
+ onPress: () => onTurnPage ? onTurnPage(-1) : pillMode.previousPage !== null && onNavigateToPageRef.current?.(pillMode.previousPage),
34243
34344
  style: styles21.pageArrowHit,
34244
34345
  testID: "papyrus-progress-page-previous",
34245
- children: /* @__PURE__ */ jsx25(Text14, { style: [styles21.pageArrow, isDark && styles21.labelDark, previousDisabled && styles21.pageArrowDisabled], children: "\u2039" })
34346
+ children: /* @__PURE__ */ jsx25(Text15, { style: [styles21.pageArrow, isDark && styles21.labelDark, previousDisabled && styles21.pageArrowDisabled], children: "\u2039" })
34246
34347
  }
34247
34348
  ),
34248
34349
  /* @__PURE__ */ jsx25(
@@ -34253,7 +34354,7 @@ function ProgressPill({
34253
34354
  onPress: () => onPressRef.current(),
34254
34355
  style: styles21.singlePageCenter,
34255
34356
  testID: "papyrus-progress-page-grid",
34256
- children: /* @__PURE__ */ jsxs19(Text14, { style: [styles21.label, isDark && styles21.labelDark], children: [
34357
+ children: /* @__PURE__ */ jsxs19(Text15, { style: [styles21.label, isDark && styles21.labelDark], children: [
34257
34358
  currentPage,
34258
34359
  "/",
34259
34360
  pageCount || 0
@@ -34267,10 +34368,10 @@ function ProgressPill({
34267
34368
  accessibilityLabel: t.nextPage,
34268
34369
  accessibilityState: { disabled: nextDisabled },
34269
34370
  disabled: nextDisabled,
34270
- onPress: () => pillMode.nextPage !== null && onNavigateToPageRef.current?.(pillMode.nextPage),
34371
+ onPress: () => onTurnPage ? onTurnPage(1) : pillMode.nextPage !== null && onNavigateToPageRef.current?.(pillMode.nextPage),
34271
34372
  style: styles21.pageArrowHit,
34272
34373
  testID: "papyrus-progress-page-next",
34273
- children: /* @__PURE__ */ jsx25(Text14, { style: [styles21.pageArrow, isDark && styles21.labelDark, nextDisabled && styles21.pageArrowDisabled], children: "\u203A" })
34374
+ children: /* @__PURE__ */ jsx25(Text15, { style: [styles21.pageArrow, isDark && styles21.labelDark, nextDisabled && styles21.pageArrowDisabled], children: "\u203A" })
34274
34375
  }
34275
34376
  )
34276
34377
  ] })
@@ -34466,7 +34567,7 @@ function ProgressPill({
34466
34567
  ...responderPanHandlers,
34467
34568
  testID: "papyrus-progress-pill",
34468
34569
  children: [
34469
- /* @__PURE__ */ jsx25(View21, { style: styles21.labelHit, children: /* @__PURE__ */ jsx25(Text14, { style: [styles21.label, isDark && styles21.labelDark], children: label }) }),
34570
+ /* @__PURE__ */ jsx25(View21, { style: styles21.labelHit, children: /* @__PURE__ */ jsx25(Text15, { style: [styles21.label, isDark && styles21.labelDark], children: label }) }),
34470
34571
  /* @__PURE__ */ jsx25(View21, { style: styles21.iconHit, children: /* @__PURE__ */ jsx25(
34471
34572
  IconPageNav,
34472
34573
  {
@@ -34597,7 +34698,7 @@ import {
34597
34698
  Keyboard,
34598
34699
  Pressable as Pressable14,
34599
34700
  StyleSheet as StyleSheet22,
34600
- Text as Text15,
34701
+ Text as Text16,
34601
34702
  TextInput as TextInput3,
34602
34703
  View as View22,
34603
34704
  useWindowDimensions as useWindowDimensions10
@@ -34730,7 +34831,7 @@ function SearchOverlay({
34730
34831
  onPress: handleClose,
34731
34832
  style: [styles22.closeButton, isDark && styles22.closeButtonDark],
34732
34833
  accessibilityLabel: "Close search",
34733
- children: /* @__PURE__ */ jsx26(Text15, { style: [styles22.closeText, isDark && styles22.closeTextDark], children: t.cancel })
34834
+ children: /* @__PURE__ */ jsx26(Text16, { style: [styles22.closeText, isDark && styles22.closeTextDark], children: t.cancel })
34734
34835
  }
34735
34836
  )
34736
34837
  ] }),
@@ -34749,7 +34850,7 @@ function SearchOverlay({
34749
34850
  children: /* @__PURE__ */ jsx26(IconChevronLeft, { size: 16, color: isDark ? "#e5e7eb" : "#111827" })
34750
34851
  }
34751
34852
  ),
34752
- /* @__PURE__ */ jsx26(Text15, { style: [styles22.metaText, isDark && styles22.metaTextDark], children: isSearching ? t.searching : `${currentCount}/${results.length} ${targetLabel}` }),
34853
+ /* @__PURE__ */ jsx26(Text16, { style: [styles22.metaText, isDark && styles22.metaTextDark], children: isSearching ? t.searching : `${currentCount}/${results.length} ${targetLabel}` }),
34753
34854
  /* @__PURE__ */ jsx26(
34754
34855
  Pressable14,
34755
34856
  {
@@ -34773,7 +34874,7 @@ function SearchOverlay({
34773
34874
  style: [styles22.primaryAction, { backgroundColor: accentColor }],
34774
34875
  accessibilityLabel: "Run search",
34775
34876
  testID: "papyrus-search-run",
34776
- children: /* @__PURE__ */ jsx26(Text15, { style: styles22.primaryActionText, children: t.searchGo })
34877
+ children: /* @__PURE__ */ jsx26(Text16, { style: styles22.primaryActionText, children: t.searchGo })
34777
34878
  }
34778
34879
  ),
34779
34880
  /* @__PURE__ */ jsx26(
@@ -34788,7 +34889,7 @@ function SearchOverlay({
34788
34889
  ],
34789
34890
  accessibilityLabel: "Open all results",
34790
34891
  children: /* @__PURE__ */ jsx26(
34791
- Text15,
34892
+ Text16,
34792
34893
  {
34793
34894
  style: [
34794
34895
  styles22.secondaryActionText,
@@ -34947,7 +35048,7 @@ var styles22 = StyleSheet22.create({
34947
35048
  });
34948
35049
 
34949
35050
  // components/SearchResultsSheet.tsx
34950
- import { Pressable as Pressable15, StyleSheet as StyleSheet23, Text as Text16 } from "react-native";
35051
+ import { Pressable as Pressable15, StyleSheet as StyleSheet23, Text as Text17 } from "react-native";
34951
35052
  import { useViewerStore as useViewerStore20 } from "@papyrus-sdk/core";
34952
35053
  import { jsx as jsx27, jsxs as jsxs21 } from "react/jsx-runtime";
34953
35054
  function SearchResultsSheet({
@@ -34995,12 +35096,12 @@ function SearchResultsSheet({
34995
35096
  borderTopColor: palette.divider
34996
35097
  },
34997
35098
  children: [
34998
- /* @__PURE__ */ jsxs21(Text16, { style: [styles23.meta, { color: palette.mutedText }], children: [
35099
+ /* @__PURE__ */ jsxs21(Text17, { style: [styles23.meta, { color: palette.mutedText }], children: [
34999
35100
  results.length,
35000
35101
  " ",
35001
35102
  t.results
35002
35103
  ] }),
35003
- /* @__PURE__ */ jsx27(NativeSheetScrollView, { contentContainerStyle: styles23.content, children: results.length === 0 ? /* @__PURE__ */ jsx27(Text16, { style: [styles23.emptyText, { color: palette.mutedText }], children: t.noResults }) : results.map((result, index) => {
35104
+ /* @__PURE__ */ jsx27(NativeSheetScrollView, { contentContainerStyle: styles23.content, children: results.length === 0 ? /* @__PURE__ */ jsx27(Text17, { style: [styles23.emptyText, { color: palette.mutedText }], children: t.noResults }) : results.map((result, index) => {
35004
35105
  const isActive = index === activeSearchIndex;
35005
35106
  const isTextResult = "kind" in result && result.kind === "text";
35006
35107
  return /* @__PURE__ */ jsxs21(
@@ -35030,8 +35131,8 @@ function SearchResultsSheet({
35030
35131
  }
35031
35132
  ],
35032
35133
  children: [
35033
- /* @__PURE__ */ jsx27(Text16, { style: [styles23.resultLabel, { color: accentColor }], children: isTextResult ? getTextResultLabel(result.location.start) : getResultLabel(result.pageIndex) }),
35034
- /* @__PURE__ */ jsx27(Text16, { style: [styles23.resultText, { color: palette.text }], children: result.text })
35134
+ /* @__PURE__ */ jsx27(Text17, { style: [styles23.resultLabel, { color: accentColor }], children: isTextResult ? getTextResultLabel(result.location.start) : getResultLabel(result.pageIndex) }),
35135
+ /* @__PURE__ */ jsx27(Text17, { style: [styles23.resultText, { color: palette.text }], children: result.text })
35035
35136
  ]
35036
35137
  },
35037
35138
  isTextResult ? `text-${result.location.start}-${index}` : `page-${result.pageIndex}-${index}`
@@ -35154,13 +35255,7 @@ function ReadingShell({
35154
35255
  {
35155
35256
  engine,
35156
35257
  title,
35157
- onOpenOverflow: () => {
35158
- closeMobileDestination();
35159
- setInfoOpen(false);
35160
- setActionsOpen(false);
35161
- setSettingsOpen(false);
35162
- setOverflowOpen(true);
35163
- },
35258
+ onOpenSettings: () => openDestination("display"),
35164
35259
  onOpenPageJump: () => setPageJumpOpen(true),
35165
35260
  showPageNavigationControls: false
35166
35261
  }
@@ -35176,7 +35271,13 @@ function ReadingShell({
35176
35271
  /* @__PURE__ */ jsx28(
35177
35272
  ProgressPill,
35178
35273
  {
35274
+ navigationInDock: true,
35179
35275
  documentType,
35276
+ onTurnPage: documentType === "epub" ? (direction) => {
35277
+ const paginatedEngine = engine;
35278
+ void paginatedEngine.turnEpubPage?.(direction).catch(() => {
35279
+ });
35280
+ } : void 0,
35180
35281
  onNavigateToPage: navigateToPage,
35181
35282
  onPress: () => openDestination(
35182
35283
  documentType === "pdf" ? "pages" : documentType === "epub" ? "contents" : "progress"
@@ -35188,6 +35289,12 @@ function ReadingShell({
35188
35289
  /* @__PURE__ */ jsx28(
35189
35290
  BottomBar_default,
35190
35291
  {
35292
+ onNavigateToPage: navigateToPage,
35293
+ onOpenPages: () => setPageJumpOpen(true),
35294
+ onTurnPage: documentType === "epub" ? (direction) => {
35295
+ const paginatedEngine = engine;
35296
+ void paginatedEngine.turnEpubPage?.(direction).catch((error) => console.warn("[Papyrus] page navigation failed", error));
35297
+ } : void 0,
35191
35298
  documentType,
35192
35299
  onOpenDestination: openDestination,
35193
35300
  onOpenInfo: () => openDestination("info"),
@@ -35267,6 +35374,7 @@ function ReadingShell({
35267
35374
  /* @__PURE__ */ jsx28(
35268
35375
  SettingsSheet_default,
35269
35376
  {
35377
+ onOpenInfo: () => openDestination("info"),
35270
35378
  engine,
35271
35379
  documentType,
35272
35380
  visible: settingsOpen,