@papyrus-sdk/ui-react-native 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs ADDED
@@ -0,0 +1,2890 @@
1
+ // components/Viewer.tsx
2
+ import { useMemo as useMemo2, useRef as useRef2, useEffect as useEffect2, useCallback } from "react";
3
+ import { FlatList, ScrollView as ScrollView2, StyleSheet as StyleSheet2, View as View2, useWindowDimensions as useWindowDimensions2 } from "react-native";
4
+ import { useViewerStore as useViewerStore2 } from "@papyrus-sdk/core";
5
+
6
+ // components/PageRenderer.tsx
7
+ import { useEffect, useMemo, useRef, useState } from "react";
8
+ import {
9
+ View,
10
+ StyleSheet,
11
+ Pressable,
12
+ ScrollView,
13
+ PanResponder,
14
+ Platform,
15
+ findNodeHandle,
16
+ useWindowDimensions
17
+ } from "react-native";
18
+ import { useViewerStore } from "@papyrus-sdk/core";
19
+ import { PapyrusPageView } from "@papyrus-sdk/engine-native";
20
+ import { jsx, jsxs } from "react/jsx-runtime";
21
+ var PageRenderer = ({
22
+ engine,
23
+ pageIndex,
24
+ scale = 1,
25
+ PageViewComponent = PapyrusPageView,
26
+ availableWidth,
27
+ horizontalPadding = 16,
28
+ spacing = 24
29
+ }) => {
30
+ const viewRef = useRef(null);
31
+ const [layout, setLayout] = useState({ width: 0, height: 0 });
32
+ const [pageSize, setPageSize] = useState(null);
33
+ const { width: windowWidth } = useWindowDimensions();
34
+ const isAndroid = Platform.OS === "android";
35
+ const isNative = Platform.OS === "android" || Platform.OS === "ios";
36
+ const {
37
+ zoom,
38
+ rotation,
39
+ pageTheme,
40
+ annotations,
41
+ annotationColor,
42
+ addAnnotation,
43
+ setDocumentState,
44
+ accentColor,
45
+ selectedAnnotationId,
46
+ setSelectedAnnotation,
47
+ removeAnnotation,
48
+ searchResults,
49
+ activeSearchIndex,
50
+ setSelectionActive
51
+ } = useViewerStore();
52
+ const pageAnnotations = useMemo(
53
+ () => annotations.filter((ann) => ann.pageIndex === pageIndex),
54
+ [annotations, pageIndex]
55
+ );
56
+ const pageSearchHits = useMemo(
57
+ () => searchResults.map((result, index) => ({ result, index })).filter(({ result }) => result.pageIndex === pageIndex),
58
+ [searchResults, pageIndex]
59
+ );
60
+ const [selectionRect, setSelectionRect] = useState(null);
61
+ const [selectionRects, setSelectionRects] = useState([]);
62
+ const [selectionBounds, setSelectionBounds] = useState(null);
63
+ const [selectionText, setSelectionText] = useState("");
64
+ const [isSelecting, setIsSelecting] = useState(false);
65
+ const selectionStart = useRef(null);
66
+ const selectionRectRef = useRef(null);
67
+ const selectionBoundsRef = useRef(null);
68
+ const selectionBoundsStart = useRef(null);
69
+ const lastTapRef = useRef(null);
70
+ const pinchRef = useRef(null);
71
+ useEffect(() => {
72
+ if (!layout.width || !layout.height) return;
73
+ const viewTag = findNodeHandle(viewRef.current);
74
+ if (viewTag) {
75
+ const renderScale = isAndroid ? scale / Math.max(zoom, 0.5) : scale;
76
+ void engine.renderPage(pageIndex, viewTag, renderScale);
77
+ }
78
+ }, [engine, pageIndex, scale, zoom, rotation, layout.width, layout.height, isAndroid]);
79
+ useEffect(() => {
80
+ let active = true;
81
+ const loadDimensions = async () => {
82
+ const dims = await engine.getPageDimensions(pageIndex);
83
+ if (!active) return;
84
+ if (dims.width > 0 && dims.height > 0) {
85
+ setPageSize({ width: dims.width, height: dims.height });
86
+ }
87
+ };
88
+ void loadDimensions();
89
+ return () => {
90
+ active = false;
91
+ };
92
+ }, [engine, pageIndex]);
93
+ const handleLayout = (event) => {
94
+ const { width, height } = event.nativeEvent.layout;
95
+ if (width !== layout.width || height !== layout.height) {
96
+ setLayout({ width, height });
97
+ }
98
+ };
99
+ const addAnnotationAt = (x, y, width, height, type) => {
100
+ addAnnotation({
101
+ id: Math.random().toString(36).slice(2, 9),
102
+ pageIndex,
103
+ type,
104
+ rect: { x, y, width, height },
105
+ color: annotationColor,
106
+ content: type === "text" || type === "comment" ? "" : void 0,
107
+ createdAt: Date.now()
108
+ });
109
+ };
110
+ const clamp = (value, min, max) => Math.min(max, Math.max(min, value));
111
+ const getBoundsFromRects = (rects) => {
112
+ let minX = 1;
113
+ let minY = 1;
114
+ let maxX = 0;
115
+ let maxY = 0;
116
+ rects.forEach((rect) => {
117
+ minX = Math.min(minX, rect.x);
118
+ minY = Math.min(minY, rect.y);
119
+ maxX = Math.max(maxX, rect.x + rect.width);
120
+ maxY = Math.max(maxY, rect.y + rect.height);
121
+ });
122
+ if (maxX <= minX || maxY <= minY) return null;
123
+ return {
124
+ x: clamp(minX, 0, 1),
125
+ y: clamp(minY, 0, 1),
126
+ width: clamp(maxX - minX, 0, 1),
127
+ height: clamp(maxY - minY, 0, 1)
128
+ };
129
+ };
130
+ const clearSelection = () => {
131
+ setSelectionRect(null);
132
+ selectionRectRef.current = null;
133
+ setSelectionRects([]);
134
+ setSelectionBounds(null);
135
+ selectionBoundsRef.current = null;
136
+ setSelectionText("");
137
+ setIsSelecting(false);
138
+ selectionStart.current = null;
139
+ selectionBoundsStart.current = null;
140
+ setSelectionActive(false);
141
+ };
142
+ const applySelectionResult = (selection) => {
143
+ if (!selection || !selection.rects || selection.rects.length === 0) {
144
+ clearSelection();
145
+ return;
146
+ }
147
+ setSelectionRects(selection.rects);
148
+ setSelectionText(selection.text || "");
149
+ const bounds = getBoundsFromRects(selection.rects);
150
+ if (!bounds) {
151
+ clearSelection();
152
+ return;
153
+ }
154
+ setSelectionBounds(bounds);
155
+ selectionBoundsRef.current = bounds;
156
+ setSelectionActive(true);
157
+ };
158
+ const selectFromBounds = async (bounds) => {
159
+ const selection = await engine.selectText?.(pageIndex, bounds);
160
+ applySelectionResult(selection ?? null);
161
+ };
162
+ const selectAtPoint = async (x, y) => {
163
+ if (!layout.width || !layout.height) return;
164
+ const size = 26;
165
+ const half = size / 2;
166
+ const left = clamp(x - half, 0, Math.max(0, layout.width - size));
167
+ const top = clamp(y - half, 0, Math.max(0, layout.height - size));
168
+ const bounds = {
169
+ x: left / layout.width,
170
+ y: top / layout.height,
171
+ width: size / layout.width,
172
+ height: size / layout.height
173
+ };
174
+ await selectFromBounds(bounds);
175
+ };
176
+ const getTouchDistance = (touches) => {
177
+ if (touches.length < 2) return 0;
178
+ const [a, b] = touches;
179
+ return Math.hypot(b.pageX - a.pageX, b.pageY - a.pageY);
180
+ };
181
+ const shouldHandlePinch = (touches) => isNative && touches.length === 2;
182
+ const handlePinchStart = (touches) => {
183
+ if (!shouldHandlePinch(touches)) return;
184
+ pinchRef.current = { distance: getTouchDistance(touches), zoom };
185
+ };
186
+ const handlePinchMove = (touches) => {
187
+ if (!shouldHandlePinch(touches) || !pinchRef.current) return;
188
+ const distance = getTouchDistance(touches);
189
+ if (!distance) return;
190
+ const scale2 = distance / pinchRef.current.distance;
191
+ const nextZoom = clamp(pinchRef.current.zoom * scale2, 0.5, 4);
192
+ setDocumentState({ zoom: nextZoom });
193
+ engine.setZoom(nextZoom);
194
+ };
195
+ const handlePinchEnd = () => {
196
+ pinchRef.current = null;
197
+ };
198
+ const handlePress = (event) => {
199
+ if (!layout.width || !layout.height) return;
200
+ if (selectionRects.length > 0 || selectionBounds) {
201
+ clearSelection();
202
+ return;
203
+ }
204
+ setSelectedAnnotation(null);
205
+ if (!isNative) return;
206
+ const { locationX, locationY } = event.nativeEvent;
207
+ const now = Date.now();
208
+ const lastTap = lastTapRef.current;
209
+ lastTapRef.current = { time: now, x: locationX, y: locationY };
210
+ if (!lastTap) return;
211
+ const timeDelta = now - lastTap.time;
212
+ const distance = Math.hypot(locationX - lastTap.x, locationY - lastTap.y);
213
+ if (timeDelta < 280 && distance < 24) {
214
+ void selectAtPoint(locationX, locationY);
215
+ }
216
+ };
217
+ const selectionEnabled = Platform.OS === "web";
218
+ void selectionText;
219
+ const panResponder = useMemo(
220
+ () => PanResponder.create({
221
+ onStartShouldSetPanResponder: () => selectionEnabled,
222
+ onMoveShouldSetPanResponder: () => selectionEnabled,
223
+ onPanResponderGrant: (event) => {
224
+ if (!selectionEnabled || !layout.width || !layout.height) return;
225
+ const { locationX, locationY } = event.nativeEvent;
226
+ selectionStart.current = { x: locationX, y: locationY };
227
+ setIsSelecting(true);
228
+ const rect = { x: locationX, y: locationY, width: 0, height: 0 };
229
+ selectionRectRef.current = rect;
230
+ setSelectionRect(rect);
231
+ },
232
+ onPanResponderMove: (_, gestureState) => {
233
+ if (!selectionEnabled || !selectionStart.current) return;
234
+ const start = selectionStart.current;
235
+ const currentX = start.x + gestureState.dx;
236
+ const currentY = start.y + gestureState.dy;
237
+ const left = Math.max(0, Math.min(start.x, currentX));
238
+ const top = Math.max(0, Math.min(start.y, currentY));
239
+ const right = Math.min(layout.width, Math.max(start.x, currentX));
240
+ const bottom = Math.min(layout.height, Math.max(start.y, currentY));
241
+ const rect = { x: left, y: top, width: right - left, height: bottom - top };
242
+ selectionRectRef.current = rect;
243
+ setSelectionRect(rect);
244
+ },
245
+ onPanResponderRelease: async () => {
246
+ const rect = selectionRectRef.current;
247
+ if (!selectionEnabled || !rect || !layout.width || !layout.height) {
248
+ setIsSelecting(false);
249
+ selectionStart.current = null;
250
+ return;
251
+ }
252
+ setIsSelecting(false);
253
+ selectionStart.current = null;
254
+ const minSize = 6;
255
+ if (rect.width < minSize || rect.height < minSize) {
256
+ clearSelection();
257
+ return;
258
+ }
259
+ const normalized = {
260
+ x: rect.x / layout.width,
261
+ y: rect.y / layout.height,
262
+ width: rect.width / layout.width,
263
+ height: rect.height / layout.height
264
+ };
265
+ await selectFromBounds(normalized);
266
+ setSelectionRect(null);
267
+ }
268
+ }),
269
+ [selectionEnabled, layout.width, layout.height, engine, pageIndex]
270
+ );
271
+ const selectionBoundsPx = useMemo(() => {
272
+ if (!selectionBounds || !layout.width || !layout.height) return null;
273
+ return {
274
+ x: selectionBounds.x * layout.width,
275
+ y: selectionBounds.y * layout.height,
276
+ width: selectionBounds.width * layout.width,
277
+ height: selectionBounds.height * layout.height
278
+ };
279
+ }, [selectionBounds, layout.width, layout.height]);
280
+ const createHandleResponder = (handle) => PanResponder.create({
281
+ onStartShouldSetPanResponder: () => true,
282
+ onMoveShouldSetPanResponder: () => true,
283
+ onPanResponderGrant: () => {
284
+ selectionBoundsStart.current = selectionBoundsRef.current;
285
+ },
286
+ onPanResponderMove: (_, gestureState) => {
287
+ const start = selectionBoundsStart.current;
288
+ if (!start || !layout.width || !layout.height) return;
289
+ const dx = gestureState.dx / layout.width;
290
+ const dy = gestureState.dy / layout.height;
291
+ const minSize = 0.01;
292
+ let next = { ...start };
293
+ if (handle === "start") {
294
+ const newX = clamp(start.x + dx, 0, start.x + start.width - minSize);
295
+ const newY = clamp(start.y + dy, 0, start.y + start.height - minSize);
296
+ next = {
297
+ x: newX,
298
+ y: newY,
299
+ width: start.x + start.width - newX,
300
+ height: start.y + start.height - newY
301
+ };
302
+ } else {
303
+ const maxX = clamp(start.x + start.width + dx, start.x + minSize, 1);
304
+ const maxY = clamp(start.y + start.height + dy, start.y + minSize, 1);
305
+ next = {
306
+ x: start.x,
307
+ y: start.y,
308
+ width: maxX - start.x,
309
+ height: maxY - start.y
310
+ };
311
+ }
312
+ selectionBoundsRef.current = next;
313
+ setSelectionBounds(next);
314
+ },
315
+ onPanResponderRelease: async () => {
316
+ const next = selectionBoundsRef.current;
317
+ selectionBoundsStart.current = null;
318
+ if (!next) return;
319
+ await selectFromBounds(next);
320
+ },
321
+ onPanResponderTerminate: () => {
322
+ selectionBoundsStart.current = null;
323
+ }
324
+ });
325
+ const startHandleResponder = useMemo(
326
+ () => createHandleResponder("start"),
327
+ [layout.width, layout.height, engine, pageIndex]
328
+ );
329
+ const endHandleResponder = useMemo(
330
+ () => createHandleResponder("end"),
331
+ [layout.width, layout.height, engine, pageIndex]
332
+ );
333
+ const applySelection = (type) => {
334
+ if (selectionRects.length === 0) return;
335
+ if (type === "comment") {
336
+ const first = selectionRects[0];
337
+ addAnnotationAt(first.x, first.y, Math.max(0.08, first.width), Math.max(0.06, first.height), "comment");
338
+ clearSelection();
339
+ return;
340
+ }
341
+ selectionRects.forEach((rect) => {
342
+ addAnnotationAt(rect.x, rect.y, rect.width, rect.height, type);
343
+ });
344
+ clearSelection();
345
+ };
346
+ const themeOverlayStyle = useMemo(() => {
347
+ switch (pageTheme) {
348
+ case "sepia":
349
+ return styles.themeSepia;
350
+ case "dark":
351
+ return styles.themeDark;
352
+ case "high-contrast":
353
+ return styles.themeContrast;
354
+ default:
355
+ return styles.themeNone;
356
+ }
357
+ }, [pageTheme]);
358
+ const aspectRatio = pageSize && pageSize.width > 0 && pageSize.height > 0 ? pageSize.width / pageSize.height : 0.77;
359
+ const containerWidth = availableWidth ?? windowWidth;
360
+ const baseWidth = containerWidth * 0.92;
361
+ const pageWidth = isAndroid ? baseWidth * zoom : baseWidth;
362
+ const pageHeight = pageWidth / aspectRatio;
363
+ const scrollEnabled = isAndroid && zoom > 1;
364
+ return /* @__PURE__ */ jsx(
365
+ ScrollView,
366
+ {
367
+ horizontal: true,
368
+ scrollEnabled,
369
+ showsHorizontalScrollIndicator: false,
370
+ contentContainerStyle: [styles.scrollContent, { paddingHorizontal: horizontalPadding }],
371
+ children: /* @__PURE__ */ jsxs(
372
+ Pressable,
373
+ {
374
+ ...panResponder.panHandlers,
375
+ style: [styles.container, { width: pageWidth, height: pageHeight, marginBottom: spacing }],
376
+ onLayout: handleLayout,
377
+ onPress: handlePress,
378
+ onStartShouldSetResponder: (event) => shouldHandlePinch(event.nativeEvent.touches),
379
+ onMoveShouldSetResponder: (event) => shouldHandlePinch(event.nativeEvent.touches),
380
+ onResponderGrant: (event) => handlePinchStart(event.nativeEvent.touches),
381
+ onResponderMove: (event) => handlePinchMove(event.nativeEvent.touches),
382
+ onResponderRelease: handlePinchEnd,
383
+ onResponderTerminate: handlePinchEnd,
384
+ children: [
385
+ /* @__PURE__ */ jsx(PageViewComponent, { ref: viewRef, style: styles.page }),
386
+ /* @__PURE__ */ jsx(View, { pointerEvents: "none", style: [styles.themeOverlay, themeOverlayStyle] }),
387
+ /* @__PURE__ */ jsxs(View, { pointerEvents: "box-none", style: styles.selectionLayer, children: [
388
+ /* @__PURE__ */ jsx(View, { pointerEvents: "none", children: selectionRects.map((rect, index) => {
389
+ const style = {
390
+ left: `${rect.x * 100}%`,
391
+ top: `${rect.y * 100}%`,
392
+ width: `${rect.width * 100}%`,
393
+ height: `${rect.height * 100}%`
394
+ };
395
+ return /* @__PURE__ */ jsx(View, { style: [styles.selectionHighlight, style] }, `sel-${index}`);
396
+ }) }),
397
+ selectionBoundsPx ? /* @__PURE__ */ jsxs(
398
+ View,
399
+ {
400
+ pointerEvents: "box-none",
401
+ style: [
402
+ styles.selectionOutline,
403
+ {
404
+ left: selectionBoundsPx.x,
405
+ top: selectionBoundsPx.y,
406
+ width: selectionBoundsPx.width,
407
+ height: selectionBoundsPx.height,
408
+ borderColor: accentColor
409
+ }
410
+ ],
411
+ children: [
412
+ /* @__PURE__ */ jsx(
413
+ View,
414
+ {
415
+ ...startHandleResponder.panHandlers,
416
+ style: [styles.selectionHandle, { left: -8, top: -8, borderColor: accentColor }]
417
+ }
418
+ ),
419
+ /* @__PURE__ */ jsx(
420
+ View,
421
+ {
422
+ ...endHandleResponder.panHandlers,
423
+ style: [styles.selectionHandle, { right: -8, bottom: -8, borderColor: accentColor }]
424
+ }
425
+ )
426
+ ]
427
+ }
428
+ ) : null,
429
+ isSelecting && selectionRect ? /* @__PURE__ */ jsx(
430
+ View,
431
+ {
432
+ pointerEvents: "none",
433
+ style: [
434
+ styles.selectionOutline,
435
+ {
436
+ left: selectionRect.x,
437
+ top: selectionRect.y,
438
+ width: selectionRect.width,
439
+ height: selectionRect.height,
440
+ borderColor: accentColor
441
+ }
442
+ ]
443
+ }
444
+ ) : null
445
+ ] }),
446
+ /* @__PURE__ */ jsx(View, { pointerEvents: "none", style: styles.searchLayer, children: pageSearchHits.map(({ result, index }) => {
447
+ if (!result.rects || result.rects.length === 0) return null;
448
+ return result.rects.map((rect, rectIndex) => {
449
+ if (rect.width <= 0 || rect.height <= 0) return null;
450
+ const isActive = index === activeSearchIndex;
451
+ const highlightStyle = {
452
+ left: `${rect.x * 100}%`,
453
+ top: `${rect.y * 100}%`,
454
+ width: `${rect.width * 100}%`,
455
+ height: `${rect.height * 100}%`
456
+ };
457
+ return /* @__PURE__ */ jsx(
458
+ View,
459
+ {
460
+ style: [
461
+ styles.searchHighlight,
462
+ { borderColor: accentColor, backgroundColor: `${accentColor}26` },
463
+ isActive && styles.searchHighlightActive,
464
+ isActive && { borderColor: accentColor, backgroundColor: `${accentColor}40` },
465
+ highlightStyle
466
+ ]
467
+ },
468
+ `${index}-${rectIndex}`
469
+ );
470
+ });
471
+ }) }),
472
+ /* @__PURE__ */ jsx(View, { pointerEvents: "box-none", style: styles.annotationLayer, children: pageAnnotations.map((ann) => {
473
+ const isSelected = selectedAnnotationId === ann.id;
474
+ const style = {
475
+ left: `${ann.rect.x * 100}%`,
476
+ top: `${ann.rect.y * 100}%`,
477
+ width: `${ann.rect.width * 100}%`,
478
+ height: `${ann.rect.height * 100}%`,
479
+ backgroundColor: ann.type === "highlight" ? `${ann.color}66` : "transparent",
480
+ borderBottomWidth: ann.type === "strikeout" ? 3 : 0,
481
+ borderBottomColor: ann.type === "strikeout" ? ann.color : "transparent"
482
+ };
483
+ return /* @__PURE__ */ jsxs(
484
+ Pressable,
485
+ {
486
+ onPress: () => setSelectedAnnotation(ann.id),
487
+ style: [
488
+ styles.annotation,
489
+ style,
490
+ isSelected && styles.annotationSelected,
491
+ isSelected && { borderColor: accentColor }
492
+ ],
493
+ children: [
494
+ (ann.type === "comment" || ann.type === "text") && /* @__PURE__ */ jsx(View, { style: [styles.annotationBadge, { borderColor: ann.color }], children: /* @__PURE__ */ jsx(View, { style: [styles.annotationDot, { backgroundColor: ann.color }] }) }),
495
+ isSelected && /* @__PURE__ */ jsx(Pressable, { onPress: () => removeAnnotation(ann.id), style: styles.deleteButton, children: /* @__PURE__ */ jsx(View, { style: styles.deleteDot }) })
496
+ ]
497
+ },
498
+ ann.id
499
+ );
500
+ }) }),
501
+ selectionRects.length > 0 && selectionBoundsPx ? /* @__PURE__ */ jsxs(
502
+ View,
503
+ {
504
+ pointerEvents: "box-none",
505
+ style: [
506
+ styles.selectionToolbar,
507
+ {
508
+ left: selectionBoundsPx.x,
509
+ top: selectionBoundsPx.y + selectionBoundsPx.height + 8 > layout.height - 56 ? Math.max(8, selectionBoundsPx.y - 52) : selectionBoundsPx.y + selectionBoundsPx.height + 8
510
+ }
511
+ ],
512
+ children: [
513
+ /* @__PURE__ */ jsx(Pressable, { onPress: () => applySelection("comment"), style: styles.selectionAction, children: /* @__PURE__ */ jsx(View, { style: styles.selectionActionDot }) }),
514
+ /* @__PURE__ */ jsx(Pressable, { onPress: () => applySelection("highlight"), style: styles.selectionAction, children: /* @__PURE__ */ jsx(View, { style: [styles.selectionSwatch, { backgroundColor: annotationColor }] }) }),
515
+ /* @__PURE__ */ jsx(Pressable, { onPress: () => applySelection("strikeout"), style: [styles.selectionAction, styles.selectionActionLast], children: /* @__PURE__ */ jsx(View, { style: [styles.selectionStrike, { backgroundColor: annotationColor }] }) })
516
+ ]
517
+ }
518
+ ) : null
519
+ ]
520
+ }
521
+ )
522
+ }
523
+ );
524
+ };
525
+ var styles = StyleSheet.create({
526
+ scrollContent: {
527
+ alignItems: "center"
528
+ },
529
+ container: {
530
+ alignSelf: "center",
531
+ borderRadius: 14,
532
+ backgroundColor: "#ffffff",
533
+ shadowColor: "#000000",
534
+ shadowOpacity: 0.12,
535
+ shadowRadius: 12,
536
+ shadowOffset: { width: 0, height: 6 },
537
+ elevation: 4
538
+ },
539
+ page: {
540
+ ...StyleSheet.absoluteFillObject,
541
+ backgroundColor: "#ffffff",
542
+ borderRadius: 14,
543
+ overflow: "hidden"
544
+ },
545
+ annotationLayer: {
546
+ position: "absolute",
547
+ left: 0,
548
+ top: 0,
549
+ right: 0,
550
+ bottom: 0
551
+ },
552
+ searchLayer: {
553
+ position: "absolute",
554
+ left: 0,
555
+ top: 0,
556
+ right: 0,
557
+ bottom: 0
558
+ },
559
+ selectionLayer: {
560
+ position: "absolute",
561
+ left: 0,
562
+ top: 0,
563
+ right: 0,
564
+ bottom: 0
565
+ },
566
+ selectionHighlight: {
567
+ position: "absolute",
568
+ backgroundColor: "rgba(245, 158, 11, 0.28)",
569
+ borderRadius: 4
570
+ },
571
+ selectionOutline: {
572
+ position: "absolute",
573
+ borderWidth: 2,
574
+ borderStyle: "dashed",
575
+ borderColor: "rgba(37, 99, 235, 0.9)",
576
+ borderRadius: 6
577
+ },
578
+ selectionHandle: {
579
+ position: "absolute",
580
+ width: 16,
581
+ height: 16,
582
+ borderRadius: 8,
583
+ backgroundColor: "#ffffff",
584
+ borderWidth: 2,
585
+ borderColor: "#2563eb"
586
+ },
587
+ searchHighlight: {
588
+ position: "absolute",
589
+ backgroundColor: "rgba(59, 130, 246, 0.2)",
590
+ borderWidth: 1,
591
+ borderColor: "rgba(59, 130, 246, 0.35)",
592
+ borderRadius: 4
593
+ },
594
+ searchHighlightActive: {
595
+ backgroundColor: "rgba(59, 130, 246, 0.35)",
596
+ borderColor: "#3b82f6"
597
+ },
598
+ themeOverlay: {
599
+ ...StyleSheet.absoluteFillObject,
600
+ borderRadius: 14
601
+ },
602
+ themeNone: {
603
+ backgroundColor: "transparent"
604
+ },
605
+ themeSepia: {
606
+ backgroundColor: "rgba(244, 236, 216, 0.35)"
607
+ },
608
+ themeDark: {
609
+ backgroundColor: "rgba(0, 0, 0, 0.2)"
610
+ },
611
+ themeContrast: {
612
+ backgroundColor: "rgba(0, 0, 0, 0.35)"
613
+ },
614
+ annotation: {
615
+ position: "absolute"
616
+ },
617
+ annotationSelected: {
618
+ borderWidth: 1,
619
+ borderColor: "#3b82f6"
620
+ },
621
+ annotationBadge: {
622
+ position: "absolute",
623
+ left: 4,
624
+ top: 4,
625
+ width: 14,
626
+ height: 14,
627
+ borderRadius: 7,
628
+ borderWidth: 1,
629
+ backgroundColor: "#ffffff",
630
+ alignItems: "center",
631
+ justifyContent: "center"
632
+ },
633
+ annotationDot: {
634
+ width: 6,
635
+ height: 6,
636
+ borderRadius: 3
637
+ },
638
+ deleteButton: {
639
+ position: "absolute",
640
+ right: -8,
641
+ top: -8,
642
+ width: 20,
643
+ height: 20,
644
+ borderRadius: 10,
645
+ backgroundColor: "#ef4444",
646
+ alignItems: "center",
647
+ justifyContent: "center"
648
+ },
649
+ deleteDot: {
650
+ width: 8,
651
+ height: 2,
652
+ backgroundColor: "#ffffff",
653
+ borderRadius: 2
654
+ },
655
+ selectionToolbar: {
656
+ position: "absolute",
657
+ paddingHorizontal: 10,
658
+ paddingVertical: 8,
659
+ borderRadius: 14,
660
+ backgroundColor: "#111827",
661
+ flexDirection: "row",
662
+ alignItems: "center"
663
+ },
664
+ selectionAction: {
665
+ width: 28,
666
+ height: 28,
667
+ borderRadius: 10,
668
+ backgroundColor: "#1f2937",
669
+ alignItems: "center",
670
+ justifyContent: "center",
671
+ marginRight: 10
672
+ },
673
+ selectionActionLast: {
674
+ marginRight: 0
675
+ },
676
+ selectionActionDot: {
677
+ width: 8,
678
+ height: 8,
679
+ borderRadius: 4,
680
+ backgroundColor: "#f9fafb"
681
+ },
682
+ selectionSwatch: {
683
+ width: 14,
684
+ height: 14,
685
+ borderRadius: 7,
686
+ borderWidth: 1,
687
+ borderColor: "#ffffff"
688
+ },
689
+ selectionStrike: {
690
+ width: 14,
691
+ height: 3,
692
+ borderRadius: 3
693
+ }
694
+ });
695
+ var PageRenderer_default = PageRenderer;
696
+
697
+ // components/Viewer.tsx
698
+ import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
699
+ var Viewer = ({ engine }) => {
700
+ const { pageCount, currentPage, scrollToPageSignal, setDocumentState, uiTheme, viewMode } = useViewerStore2();
701
+ const listRef = useRef2(null);
702
+ const isDark = uiTheme === "dark";
703
+ const { width: windowWidth } = useWindowDimensions2();
704
+ const isDouble = viewMode === "double";
705
+ const isSingle = viewMode === "single";
706
+ const pages = useMemo2(() => Array.from({ length: pageCount }).map((_, i) => i), [pageCount]);
707
+ const rows = useMemo2(() => {
708
+ if (!isDouble) return [];
709
+ const result = [];
710
+ for (let i = 0; i < pageCount; i += 2) {
711
+ result.push({ left: i, right: i + 1 < pageCount ? i + 1 : null });
712
+ }
713
+ return result;
714
+ }, [isDouble, pageCount]);
715
+ useEffect2(() => {
716
+ if (scrollToPageSignal === null) return;
717
+ if (pageCount === 0) return;
718
+ if (scrollToPageSignal < 0 || scrollToPageSignal >= pageCount) return;
719
+ if (isSingle) {
720
+ setDocumentState({ currentPage: scrollToPageSignal + 1, scrollToPageSignal: null });
721
+ return;
722
+ }
723
+ const targetIndex = isDouble ? Math.floor(scrollToPageSignal / 2) : scrollToPageSignal;
724
+ listRef.current?.scrollToIndex({ index: targetIndex, animated: true });
725
+ setDocumentState({ scrollToPageSignal: null });
726
+ }, [scrollToPageSignal, pageCount, setDocumentState, isDouble, isSingle]);
727
+ const onViewableItemsChanged = useCallback(
728
+ ({ viewableItems }) => {
729
+ const first = viewableItems[0];
730
+ if (!first) return;
731
+ if (isDouble) {
732
+ const item = first.item;
733
+ if (!item) return;
734
+ const page = item.left + 1;
735
+ if (page !== currentPage) {
736
+ setDocumentState({ currentPage: page });
737
+ }
738
+ return;
739
+ }
740
+ if (first.index !== null && first.index !== void 0) {
741
+ const page = first.index + 1;
742
+ if (page !== currentPage) {
743
+ setDocumentState({ currentPage: page });
744
+ }
745
+ }
746
+ },
747
+ [currentPage, isDouble, setDocumentState]
748
+ );
749
+ if (isSingle) {
750
+ return /* @__PURE__ */ jsx2(View2, { style: [styles2.container, isDark && styles2.containerDark], children: /* @__PURE__ */ jsx2(
751
+ ScrollView2,
752
+ {
753
+ contentContainerStyle: styles2.singleContent,
754
+ showsVerticalScrollIndicator: false,
755
+ scrollEnabled: true,
756
+ children: /* @__PURE__ */ jsx2(PageRenderer_default, { engine, pageIndex: Math.max(0, currentPage - 1), spacing: 32 })
757
+ }
758
+ ) });
759
+ }
760
+ const columnGap = 12;
761
+ const horizontalPadding = 16;
762
+ const columnWidth = isDouble ? (windowWidth - horizontalPadding * 2 - columnGap) / 2 : windowWidth;
763
+ return /* @__PURE__ */ jsx2(View2, { style: [styles2.container, isDark && styles2.containerDark], children: /* @__PURE__ */ jsx2(
764
+ FlatList,
765
+ {
766
+ ref: listRef,
767
+ data: isDouble ? rows : pages,
768
+ keyExtractor: (item) => isDouble ? `row-${item.left}` : `page-${item}`,
769
+ contentContainerStyle: styles2.listContent,
770
+ renderItem: ({ item }) => isDouble ? /* @__PURE__ */ jsxs2(View2, { style: [styles2.row, { paddingHorizontal: horizontalPadding }], children: [
771
+ /* @__PURE__ */ jsx2(View2, { style: { width: columnWidth }, children: /* @__PURE__ */ jsx2(
772
+ PageRenderer_default,
773
+ {
774
+ engine,
775
+ pageIndex: item.left,
776
+ availableWidth: columnWidth,
777
+ horizontalPadding: 8,
778
+ spacing: 20
779
+ }
780
+ ) }),
781
+ item.right !== null ? /* @__PURE__ */ jsx2(View2, { style: { width: columnWidth }, children: /* @__PURE__ */ jsx2(
782
+ PageRenderer_default,
783
+ {
784
+ engine,
785
+ pageIndex: item.right,
786
+ availableWidth: columnWidth,
787
+ horizontalPadding: 8,
788
+ spacing: 20
789
+ }
790
+ ) }) : /* @__PURE__ */ jsx2(View2, { style: { width: columnWidth } })
791
+ ] }) : /* @__PURE__ */ jsx2(PageRenderer_default, { engine, pageIndex: item, spacing: 28 }),
792
+ onViewableItemsChanged,
793
+ viewabilityConfig: { itemVisiblePercentThreshold: 60 },
794
+ scrollEnabled: true,
795
+ onScrollToIndexFailed: ({ index, averageItemLength }) => {
796
+ if (index < 0 || index >= pageCount) return;
797
+ const offset = Math.max(0, averageItemLength * index);
798
+ listRef.current?.scrollToOffset({ offset, animated: true });
799
+ },
800
+ showsVerticalScrollIndicator: false
801
+ }
802
+ ) });
803
+ };
804
+ var styles2 = StyleSheet2.create({
805
+ container: {
806
+ flex: 1,
807
+ backgroundColor: "#e9ecef"
808
+ },
809
+ containerDark: {
810
+ backgroundColor: "#0f1115"
811
+ },
812
+ listContent: {
813
+ paddingTop: 18,
814
+ paddingBottom: 120
815
+ },
816
+ singleContent: {
817
+ paddingTop: 18,
818
+ paddingBottom: 140
819
+ },
820
+ row: {
821
+ flexDirection: "row",
822
+ justifyContent: "space-between"
823
+ }
824
+ });
825
+ var Viewer_default = Viewer;
826
+
827
+ // components/Topbar.tsx
828
+ import { useEffect as useEffect3, useState as useState2 } from "react";
829
+ import { View as View3, Text, Pressable as Pressable2, StyleSheet as StyleSheet3 } from "react-native";
830
+ import { useViewerStore as useViewerStore3 } from "@papyrus-sdk/core";
831
+
832
+ // icons.tsx
833
+ import Svg, { Path } from "react-native-svg";
834
+ import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
835
+ var defaultColor = "#111827";
836
+ var IconDocument = ({ size = 20, color = defaultColor, strokeWidth = 2 }) => /* @__PURE__ */ jsx3(Svg, { width: size, height: size, viewBox: "0 0 24 24", fill: "none", children: /* @__PURE__ */ jsx3(
837
+ Path,
838
+ {
839
+ d: "M10 3v4a1 1 0 0 1-1 1H5m14-4v16a1 1 0 0 1-1 1H6a1 1 0 0 1-1-1V7.914a1 1 0 0 1 .293-.707l3.914-3.914A1 1 0 0 1 9.914 3H18a1 1 0 0 1 1 1Z",
840
+ stroke: color,
841
+ strokeWidth,
842
+ strokeLinejoin: "round"
843
+ }
844
+ ) });
845
+ var IconGrid = ({ size = 20, color = defaultColor, strokeWidth = 2 }) => /* @__PURE__ */ jsx3(Svg, { width: size, height: size, viewBox: "0 0 24 24", fill: "none", children: /* @__PURE__ */ jsx3(
846
+ Path,
847
+ {
848
+ d: "M9.143 4H4.857A.857.857 0 0 0 4 4.857v4.286c0 .473.384.857.857.857h4.286A.857.857 0 0 0 10 9.143V4.857A.857.857 0 0 0 9.143 4Zm10 0h-4.286a.857.857 0 0 0-.857.857v4.286c0 .473.384.857.857.857h4.286A.857.857 0 0 0 20 9.143V4.857A.857.857 0 0 0 19.143 4Zm-10 10H4.857a.857.857 0 0 0-.857.857v4.286c0 .473.384.857.857.857h4.286a.857.857 0 0 0 .857-.857v-4.286A.857.857 0 0 0 9.143 14Zm10 0h-4.286a.857.857 0 0 0-.857.857v4.286c0 .473.384.857.857.857h4.286a.857.857 0 0 0 .857-.857v-4.286a.857.857 0 0 0-.857-.857Z",
849
+ stroke: color,
850
+ strokeWidth,
851
+ strokeLinecap: "round",
852
+ strokeLinejoin: "round"
853
+ }
854
+ ) });
855
+ var IconSearch = ({ size = 20, color = defaultColor, strokeWidth = 2 }) => /* @__PURE__ */ jsx3(Svg, { width: size, height: size, viewBox: "0 0 24 24", fill: "none", children: /* @__PURE__ */ jsx3(
856
+ Path,
857
+ {
858
+ d: "m21 21-3.5-3.5M17 10a7 7 0 1 1-14 0 7 7 0 0 1 14 0Z",
859
+ stroke: color,
860
+ strokeWidth,
861
+ strokeLinecap: "round"
862
+ }
863
+ ) });
864
+ var IconZoomIn = ({ size = 18, color = defaultColor, strokeWidth = 2 }) => /* @__PURE__ */ jsx3(Svg, { width: size, height: size, viewBox: "0 0 24 24", fill: "none", children: /* @__PURE__ */ jsx3(Path, { d: "M5 12h14m-7 7V5", stroke: color, strokeWidth, strokeLinecap: "round", strokeLinejoin: "round" }) });
865
+ var IconZoomOut = ({ size = 18, color = defaultColor, strokeWidth = 2 }) => /* @__PURE__ */ jsx3(Svg, { width: size, height: size, viewBox: "0 0 24 24", fill: "none", children: /* @__PURE__ */ jsx3(Path, { d: "M5 12h14", stroke: color, strokeWidth, strokeLinecap: "round", strokeLinejoin: "round" }) });
866
+ var IconSettings = ({ size = 20, color = defaultColor, strokeWidth = 2 }) => /* @__PURE__ */ jsxs3(Svg, { width: size, height: size, viewBox: "0 0 24 24", fill: "none", children: [
867
+ /* @__PURE__ */ jsx3(
868
+ Path,
869
+ {
870
+ d: "M21 13v-2a1 1 0 0 0-1-1h-.757l-.707-1.707.535-.536a1 1 0 0 0 0-1.414l-1.414-1.414a1 1 0 0 0-1.414 0l-.536.535L14 4.757V4a1 1 0 0 0-1-1h-2a1 1 0 0 0-1 1v.757l-1.707.707-.536-.535a1 1 0 0 0-1.414 0L4.929 6.343a1 1 0 0 0 0 1.414l.536.536L4.757 10H4a1 1 0 0 0-1 1v2a1 1 0 0 0 1 1h.757l.707 1.707-.535.536a1 1 0 0 0 0 1.414l1.414 1.414a1 1 0 0 0 1.414 0l.536-.535 1.707.707V20a1 1 0 0 0 1 1h2a1 1 0 0 0 1-1v-.757l1.707-.708.536.536a1 1 0 0 0 1.414 0l1.414-1.414a1 1 0 0 0 0-1.414l-.535-.536.707-1.707H20a1 1 0 0 0 1-1Z",
871
+ stroke: color,
872
+ strokeWidth,
873
+ strokeLinecap: "round",
874
+ strokeLinejoin: "round"
875
+ }
876
+ ),
877
+ /* @__PURE__ */ jsx3(
878
+ Path,
879
+ {
880
+ d: "M12 15a3 3 0 1 0 0-6 3 3 0 0 0 0 6Z",
881
+ stroke: color,
882
+ strokeWidth,
883
+ strokeLinecap: "round",
884
+ strokeLinejoin: "round"
885
+ }
886
+ )
887
+ ] });
888
+ var IconComment = ({ size = 20, color = defaultColor, strokeWidth = 2 }) => /* @__PURE__ */ jsx3(Svg, { width: size, height: size, viewBox: "0 0 24 24", fill: "none", children: /* @__PURE__ */ jsx3(
889
+ Path,
890
+ {
891
+ d: "M7.556 8.5h8m-8 3.5H12m7.111-7H4.89a.896.896 0 0 0-.629.256.868.868 0 0 0-.26.619v9.25c0 .232.094.455.26.619A.896.896 0 0 0 4.89 16H9l3 4 3-4h4.111a.896.896 0 0 0 .629-.256.868.868 0 0 0 .26-.619v-9.25a.868.868 0 0 0-.26-.619.896.896 0 0 0-.63-.256Z",
892
+ stroke: color,
893
+ strokeWidth,
894
+ strokeLinecap: "round",
895
+ strokeLinejoin: "round"
896
+ }
897
+ ) });
898
+ var IconChevronRight = ({ size = 18, color = defaultColor, strokeWidth = 2 }) => /* @__PURE__ */ jsx3(Svg, { width: size, height: size, viewBox: "0 0 24 24", fill: "none", children: /* @__PURE__ */ jsx3(
899
+ Path,
900
+ {
901
+ d: "m9 5 7 7-7 7",
902
+ stroke: color,
903
+ strokeWidth,
904
+ strokeLinecap: "round",
905
+ strokeLinejoin: "round"
906
+ }
907
+ ) });
908
+ var IconChevronLeft = ({ size = 18, color = defaultColor, strokeWidth = 2 }) => /* @__PURE__ */ jsx3(Svg, { width: size, height: size, viewBox: "0 0 24 24", fill: "none", children: /* @__PURE__ */ jsx3(
909
+ Path,
910
+ {
911
+ d: "m15 19-7-7 7-7",
912
+ stroke: color,
913
+ strokeWidth,
914
+ strokeLinecap: "round",
915
+ strokeLinejoin: "round"
916
+ }
917
+ ) });
918
+
919
+ // components/Topbar.tsx
920
+ import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
921
+ var Topbar = ({ engine, onOpenSettings }) => {
922
+ const {
923
+ currentPage,
924
+ pageCount,
925
+ uiTheme,
926
+ setDocumentState,
927
+ triggerScrollToPage,
928
+ accentColor
929
+ } = useViewerStore3();
930
+ const [pageLabel, setPageLabel] = useState2(`${currentPage}`);
931
+ const isDark = uiTheme === "dark";
932
+ const navIconColor = isDark ? "#e5e7eb" : "#111827";
933
+ useEffect3(() => {
934
+ setPageLabel(`${currentPage}`);
935
+ }, [currentPage]);
936
+ const handlePageChange = (delta) => {
937
+ const next = Math.max(1, Math.min(pageCount, currentPage + delta));
938
+ engine.goToPage(next);
939
+ setDocumentState({ currentPage: next });
940
+ triggerScrollToPage(next - 1);
941
+ };
942
+ return /* @__PURE__ */ jsxs4(View3, { style: [styles3.container, isDark && styles3.containerDark], children: [
943
+ /* @__PURE__ */ jsxs4(View3, { style: styles3.leftGroup, children: [
944
+ /* @__PURE__ */ jsx4(View3, { style: [styles3.logoBadge, { backgroundColor: accentColor }], children: /* @__PURE__ */ jsx4(Text, { style: styles3.logoText, children: "P" }) }),
945
+ /* @__PURE__ */ jsx4(Text, { style: [styles3.brandText, isDark && styles3.brandTextDark], children: "Papyrus" })
946
+ ] }),
947
+ /* @__PURE__ */ jsxs4(View3, { style: styles3.pageGroup, children: [
948
+ /* @__PURE__ */ jsx4(Pressable2, { onPress: () => handlePageChange(-1), style: [styles3.pageButton, isDark && styles3.pageButtonDark], children: /* @__PURE__ */ jsx4(IconChevronLeft, { size: 16, color: navIconColor }) }),
949
+ /* @__PURE__ */ jsxs4(Text, { style: [styles3.pageIndicator, isDark && styles3.pageIndicatorDark], children: [
950
+ pageLabel,
951
+ "/",
952
+ pageCount
953
+ ] }),
954
+ /* @__PURE__ */ jsx4(Pressable2, { onPress: () => handlePageChange(1), style: [styles3.pageButton, isDark && styles3.pageButtonDark], children: /* @__PURE__ */ jsx4(IconChevronRight, { size: 16, color: navIconColor }) })
955
+ ] }),
956
+ /* @__PURE__ */ jsx4(View3, { style: styles3.rightGroup, children: /* @__PURE__ */ jsx4(
957
+ Pressable2,
958
+ {
959
+ onPress: () => onOpenSettings?.(),
960
+ style: [styles3.iconButton, isDark && styles3.iconButtonDark],
961
+ children: /* @__PURE__ */ jsx4(IconSettings, { size: 16, color: isDark ? "#e5e7eb" : "#111827" })
962
+ }
963
+ ) })
964
+ ] });
965
+ };
966
+ var styles3 = StyleSheet3.create({
967
+ container: {
968
+ paddingHorizontal: 14,
969
+ paddingVertical: 8,
970
+ backgroundColor: "#ffffff",
971
+ borderBottomWidth: 1,
972
+ borderBottomColor: "#e5e7eb",
973
+ flexDirection: "row",
974
+ alignItems: "center"
975
+ },
976
+ containerDark: {
977
+ backgroundColor: "#0f1115",
978
+ borderBottomColor: "#1f2937"
979
+ },
980
+ leftGroup: {
981
+ flexDirection: "row",
982
+ alignItems: "center",
983
+ flex: 1
984
+ },
985
+ logoBadge: {
986
+ width: 26,
987
+ height: 26,
988
+ borderRadius: 8,
989
+ alignItems: "center",
990
+ justifyContent: "center",
991
+ backgroundColor: "#2563eb",
992
+ marginRight: 8
993
+ },
994
+ logoText: {
995
+ color: "#ffffff",
996
+ fontWeight: "800",
997
+ fontSize: 13
998
+ },
999
+ brandText: {
1000
+ fontSize: 14,
1001
+ fontWeight: "800",
1002
+ color: "#111827"
1003
+ },
1004
+ brandTextDark: {
1005
+ color: "#f9fafb"
1006
+ },
1007
+ pageGroup: {
1008
+ flexDirection: "row",
1009
+ alignItems: "center",
1010
+ flex: 1,
1011
+ justifyContent: "center"
1012
+ },
1013
+ pageButton: {
1014
+ width: 26,
1015
+ height: 26,
1016
+ borderRadius: 10,
1017
+ alignItems: "center",
1018
+ justifyContent: "center",
1019
+ backgroundColor: "#f3f4f6"
1020
+ },
1021
+ pageButtonDark: {
1022
+ backgroundColor: "#111827"
1023
+ },
1024
+ pageButtonText: {
1025
+ fontSize: 11,
1026
+ fontWeight: "600",
1027
+ color: "#111827"
1028
+ },
1029
+ pageButtonTextDark: {
1030
+ color: "#e5e7eb"
1031
+ },
1032
+ pageIndicator: {
1033
+ fontSize: 12,
1034
+ color: "#374151",
1035
+ minWidth: 52,
1036
+ textAlign: "center",
1037
+ marginHorizontal: 6,
1038
+ fontWeight: "700"
1039
+ },
1040
+ pageIndicatorDark: {
1041
+ color: "#d1d5db"
1042
+ },
1043
+ rightGroup: {
1044
+ flexDirection: "row",
1045
+ alignItems: "center",
1046
+ justifyContent: "flex-end",
1047
+ flex: 1
1048
+ },
1049
+ iconButton: {
1050
+ paddingHorizontal: 10,
1051
+ paddingVertical: 6,
1052
+ borderRadius: 10,
1053
+ backgroundColor: "#f3f4f6",
1054
+ marginLeft: 6
1055
+ },
1056
+ iconButtonDark: {
1057
+ backgroundColor: "#111827"
1058
+ },
1059
+ iconButtonActive: {
1060
+ backgroundColor: "#2563eb"
1061
+ },
1062
+ iconButtonText: {
1063
+ fontSize: 11,
1064
+ fontWeight: "700",
1065
+ color: "#111827"
1066
+ },
1067
+ iconButtonTextDark: {
1068
+ color: "#e5e7eb"
1069
+ },
1070
+ iconButtonTextActive: {
1071
+ color: "#ffffff"
1072
+ },
1073
+ iconRow: {
1074
+ flexDirection: "row",
1075
+ alignItems: "center"
1076
+ },
1077
+ iconRowSpacer: {
1078
+ width: 6
1079
+ }
1080
+ });
1081
+ var Topbar_default = Topbar;
1082
+
1083
+ // components/ToolDock.tsx
1084
+ import { View as View4, Text as Text2, Pressable as Pressable3, StyleSheet as StyleSheet4 } from "react-native";
1085
+ import { useViewerStore as useViewerStore4 } from "@papyrus-sdk/core";
1086
+
1087
+ // strings.ts
1088
+ var STRINGS = {
1089
+ en: {
1090
+ pages: "Pages",
1091
+ search: "Search",
1092
+ notes: "Notes",
1093
+ read: "Read",
1094
+ edit: "Edit",
1095
+ done: "Done",
1096
+ page: "Page",
1097
+ summary: "Summary",
1098
+ pagesTab: "Pages",
1099
+ summaryTab: "Summary",
1100
+ searchPlaceholder: "Search text...",
1101
+ searchGo: "Go",
1102
+ results: "results",
1103
+ searching: "Searching...",
1104
+ noResults: "No results yet.",
1105
+ noSummary: "No summary available.",
1106
+ noAnnotations: "No annotations yet.",
1107
+ untitled: "Untitled",
1108
+ pageTransition: "Page transition",
1109
+ continuous: "Continuous",
1110
+ pageByPage: "Page by page",
1111
+ layout: "Layout",
1112
+ singlePage: "Single page",
1113
+ doublePage: "Double page",
1114
+ rotate: "Rotate",
1115
+ clockwise: "Clockwise",
1116
+ counterclockwise: "Counterclockwise",
1117
+ zoom: "Zoom",
1118
+ highlight: "Highlight",
1119
+ strike: "Strike",
1120
+ text: "Text",
1121
+ note: "Note",
1122
+ editNote: "Edit note",
1123
+ notePlaceholder: "Write your note...",
1124
+ cancel: "Cancel",
1125
+ save: "Save",
1126
+ language: "Language",
1127
+ english: "English",
1128
+ portuguese: "Portuguese (BR)",
1129
+ appearance: "Appearance",
1130
+ light: "Light",
1131
+ dark: "Dark",
1132
+ pageTheme: "Page theme",
1133
+ themeOriginal: "Original",
1134
+ themeSepia: "Sepia",
1135
+ themeDark: "Dark",
1136
+ themeContrast: "High contrast"
1137
+ },
1138
+ "pt-BR": {
1139
+ pages: "Paginas",
1140
+ search: "Buscar",
1141
+ notes: "Notas",
1142
+ read: "Ler",
1143
+ edit: "Editar",
1144
+ done: "Concluir",
1145
+ page: "Pagina",
1146
+ summary: "Sumario",
1147
+ pagesTab: "Paginas",
1148
+ summaryTab: "Sumario",
1149
+ searchPlaceholder: "Pesquisar texto...",
1150
+ searchGo: "Buscar",
1151
+ results: "resultados",
1152
+ searching: "Pesquisando...",
1153
+ noResults: "Nenhum resultado.",
1154
+ noSummary: "Sem sumario.",
1155
+ noAnnotations: "Sem anotacoes.",
1156
+ untitled: "Sem titulo",
1157
+ pageTransition: "Transicao de pagina",
1158
+ continuous: "Continuo",
1159
+ pageByPage: "Pagina por pagina",
1160
+ layout: "Layout",
1161
+ singlePage: "Pagina unica",
1162
+ doublePage: "Pagina dupla",
1163
+ rotate: "Girar",
1164
+ clockwise: "Sentido horario",
1165
+ counterclockwise: "Sentido anti-horario",
1166
+ zoom: "Zoom",
1167
+ highlight: "Marca texto",
1168
+ strike: "Risco",
1169
+ text: "Texto",
1170
+ note: "Nota",
1171
+ editNote: "Editar nota",
1172
+ notePlaceholder: "Escreva sua nota...",
1173
+ cancel: "Cancelar",
1174
+ save: "Salvar",
1175
+ language: "Idioma",
1176
+ english: "Ingles",
1177
+ portuguese: "Portugues (BR)",
1178
+ appearance: "Aparencia",
1179
+ light: "Claro",
1180
+ dark: "Escuro",
1181
+ pageTheme: "Tema da pagina",
1182
+ themeOriginal: "Original",
1183
+ themeSepia: "Sepia",
1184
+ themeDark: "Escuro",
1185
+ themeContrast: "Contraste"
1186
+ }
1187
+ };
1188
+ var getStrings = (locale) => STRINGS[locale ?? "en"] ?? STRINGS.en;
1189
+
1190
+ // components/ToolDock.tsx
1191
+ import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
1192
+ var COLOR_SWATCHES = [
1193
+ "#fbbf24",
1194
+ "#f97316",
1195
+ "#ef4444",
1196
+ "#10b981",
1197
+ "#22d3ee",
1198
+ "#3b82f6",
1199
+ "#8b5cf6",
1200
+ "#ec4899",
1201
+ "#f3f4f6",
1202
+ "#111827"
1203
+ ];
1204
+ var ToolDock = () => {
1205
+ const { selectionActive, uiTheme, locale, annotationColor, setAnnotationColor, accentColor } = useViewerStore4();
1206
+ const isDark = uiTheme === "dark";
1207
+ const isVisible = selectionActive;
1208
+ const t = getStrings(locale);
1209
+ if (!isVisible) return null;
1210
+ return /* @__PURE__ */ jsxs5(View4, { style: [styles4.container, isDark && styles4.containerDark], children: [
1211
+ /* @__PURE__ */ jsx5(Text2, { style: [styles4.title, isDark && styles4.titleDark], children: t.highlight }),
1212
+ /* @__PURE__ */ jsx5(View4, { style: styles4.paletteRow, children: COLOR_SWATCHES.map((color) => {
1213
+ const isSelected = annotationColor === color;
1214
+ return /* @__PURE__ */ jsx5(
1215
+ Pressable3,
1216
+ {
1217
+ onPress: () => setAnnotationColor(color),
1218
+ style: [
1219
+ styles4.swatch,
1220
+ { backgroundColor: color },
1221
+ isSelected && styles4.swatchSelected,
1222
+ isSelected && { borderColor: accentColor }
1223
+ ]
1224
+ },
1225
+ color
1226
+ );
1227
+ }) })
1228
+ ] });
1229
+ };
1230
+ var styles4 = StyleSheet4.create({
1231
+ container: {
1232
+ position: "absolute",
1233
+ left: 16,
1234
+ right: 16,
1235
+ bottom: 72,
1236
+ paddingVertical: 10,
1237
+ paddingHorizontal: 12,
1238
+ borderRadius: 16,
1239
+ backgroundColor: "#ffffff",
1240
+ borderWidth: 1,
1241
+ borderColor: "#e5e7eb",
1242
+ shadowColor: "#000000",
1243
+ shadowOpacity: 0.15,
1244
+ shadowRadius: 14,
1245
+ shadowOffset: { width: 0, height: 6 },
1246
+ elevation: 6
1247
+ },
1248
+ containerDark: {
1249
+ backgroundColor: "#0f1115",
1250
+ borderColor: "#1f2937"
1251
+ },
1252
+ title: {
1253
+ fontSize: 11,
1254
+ fontWeight: "800",
1255
+ color: "#111827",
1256
+ marginBottom: 8
1257
+ },
1258
+ titleDark: {
1259
+ color: "#e5e7eb"
1260
+ },
1261
+ paletteRow: {
1262
+ flexDirection: "row",
1263
+ flexWrap: "wrap"
1264
+ },
1265
+ swatch: {
1266
+ width: 20,
1267
+ height: 20,
1268
+ borderRadius: 10,
1269
+ marginRight: 8,
1270
+ marginBottom: 8,
1271
+ borderWidth: 1,
1272
+ borderColor: "#e5e7eb"
1273
+ },
1274
+ swatchSelected: {
1275
+ borderColor: "#2563eb",
1276
+ borderWidth: 2
1277
+ }
1278
+ });
1279
+ var ToolDock_default = ToolDock;
1280
+
1281
+ // components/RightSheet.tsx
1282
+ import { useEffect as useEffect4, useMemo as useMemo3, useRef as useRef3, useState as useState3 } from "react";
1283
+ import {
1284
+ Modal,
1285
+ View as View5,
1286
+ Text as Text3,
1287
+ Pressable as Pressable4,
1288
+ TextInput,
1289
+ StyleSheet as StyleSheet5,
1290
+ ScrollView as ScrollView3,
1291
+ ActivityIndicator,
1292
+ FlatList as FlatList2,
1293
+ Dimensions,
1294
+ findNodeHandle as findNodeHandle2
1295
+ } from "react-native";
1296
+ import { useViewerStore as useViewerStore5, SearchService } from "@papyrus-sdk/core";
1297
+ import { PapyrusPageView as PapyrusPageView2 } from "@papyrus-sdk/engine-native";
1298
+ import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
1299
+ var withAlpha = (hex, alpha) => {
1300
+ const normalized = hex.replace("#", "").trim();
1301
+ const value = normalized.length === 3 ? normalized.split("").map((c) => c + c).join("") : normalized;
1302
+ if (value.length !== 6) return hex;
1303
+ const r = parseInt(value.slice(0, 2), 16);
1304
+ const g = parseInt(value.slice(2, 4), 16);
1305
+ const b = parseInt(value.slice(4, 6), 16);
1306
+ return `rgba(${r}, ${g}, ${b}, ${alpha})`;
1307
+ };
1308
+ var PageThumbnail = ({ engine, pageIndex, isActive, isDark, zoom, cardWidth, frameWidth, frameHeight, accentColor, onPress }) => {
1309
+ const viewRef = useRef3(null);
1310
+ const [layoutReady, setLayoutReady] = useState3(false);
1311
+ useEffect4(() => {
1312
+ if (!layoutReady) return;
1313
+ const viewTag = findNodeHandle2(viewRef.current);
1314
+ if (!viewTag) return;
1315
+ const renderScale = 2 / Math.max(zoom, 0.5);
1316
+ void engine.renderPage(pageIndex, viewTag, renderScale);
1317
+ }, [engine, pageIndex, layoutReady, zoom]);
1318
+ const handleLayout = (event) => {
1319
+ if (event.nativeEvent.layout.width && event.nativeEvent.layout.height) {
1320
+ setLayoutReady(true);
1321
+ }
1322
+ };
1323
+ return /* @__PURE__ */ jsxs6(
1324
+ Pressable4,
1325
+ {
1326
+ onPress,
1327
+ style: [
1328
+ styles5.thumbCard,
1329
+ { width: cardWidth },
1330
+ isDark && styles5.thumbCardDark,
1331
+ isActive && styles5.thumbCardActive,
1332
+ isActive && { borderColor: accentColor }
1333
+ ],
1334
+ children: [
1335
+ /* @__PURE__ */ jsx6(View5, { onLayout: handleLayout, style: [styles5.thumbFrame, { width: frameWidth, height: frameHeight }], children: /* @__PURE__ */ jsx6(PapyrusPageView2, { ref: viewRef, style: styles5.thumbView }) }),
1336
+ /* @__PURE__ */ jsx6(Text3, { style: [styles5.thumbLabel, isDark && styles5.thumbLabelDark], children: pageIndex + 1 })
1337
+ ]
1338
+ }
1339
+ );
1340
+ };
1341
+ var OutlineNode = ({ item, depth = 0, isDark, onSelect, untitledLabel }) => {
1342
+ const hasChildren = item.children && item.children.length > 0;
1343
+ const isClickable = item.pageIndex >= 0;
1344
+ return /* @__PURE__ */ jsxs6(View5, { children: [
1345
+ /* @__PURE__ */ jsx6(
1346
+ Pressable4,
1347
+ {
1348
+ onPress: () => {
1349
+ if (isClickable) onSelect(item.pageIndex);
1350
+ },
1351
+ style: [styles5.outlineRow, { paddingLeft: 12 + depth * 12 }],
1352
+ children: /* @__PURE__ */ jsx6(
1353
+ Text3,
1354
+ {
1355
+ style: [
1356
+ styles5.outlineText,
1357
+ isDark && styles5.outlineTextDark,
1358
+ !isClickable && styles5.outlineTextMuted
1359
+ ],
1360
+ numberOfLines: 2,
1361
+ children: item.title || untitledLabel
1362
+ }
1363
+ )
1364
+ }
1365
+ ),
1366
+ hasChildren && item.children.map((child, index) => /* @__PURE__ */ jsx6(
1367
+ OutlineNode,
1368
+ {
1369
+ item: child,
1370
+ depth: depth + 1,
1371
+ isDark,
1372
+ onSelect,
1373
+ untitledLabel
1374
+ },
1375
+ `${child.title}-${index}`
1376
+ ))
1377
+ ] });
1378
+ };
1379
+ var RightSheet = ({ engine }) => {
1380
+ const {
1381
+ sidebarRightOpen,
1382
+ sidebarRightTab,
1383
+ toggleSidebarRight,
1384
+ outline,
1385
+ searchResults,
1386
+ searchQuery,
1387
+ activeSearchIndex,
1388
+ nextSearchResult,
1389
+ prevSearchResult,
1390
+ annotations,
1391
+ uiTheme,
1392
+ setSearch,
1393
+ setDocumentState,
1394
+ triggerScrollToPage,
1395
+ setSelectedAnnotation,
1396
+ pageCount,
1397
+ currentPage,
1398
+ zoom,
1399
+ locale,
1400
+ accentColor
1401
+ } = useViewerStore5();
1402
+ const [pagesMode, setPagesMode] = useState3("thumbnails");
1403
+ const [query, setQuery] = useState3("");
1404
+ const [isSearching, setIsSearching] = useState3(false);
1405
+ const searchService = useMemo3(() => new SearchService(engine), [engine]);
1406
+ const isDark = uiTheme === "dark";
1407
+ const accentSoft = withAlpha(accentColor, 0.2);
1408
+ const accentStrong = withAlpha(accentColor, 0.35);
1409
+ const t = getStrings(locale);
1410
+ const sheetHeight = Math.min(640, Dimensions.get("window").height * 0.72);
1411
+ const windowWidth = Dimensions.get("window").width;
1412
+ const gridGutter = 12;
1413
+ const gridPadding = 16;
1414
+ const cardWidth = (windowWidth - gridPadding * 2 - gridGutter) / 2;
1415
+ const frameWidth = cardWidth - 16;
1416
+ const frameHeight = frameWidth * 1.28;
1417
+ const closeSheet = () => toggleSidebarRight();
1418
+ const handleSearch = async () => {
1419
+ const trimmed = query.trim();
1420
+ if (!trimmed) {
1421
+ setSearch("", []);
1422
+ return;
1423
+ }
1424
+ setIsSearching(true);
1425
+ try {
1426
+ const results = await searchService.search(trimmed);
1427
+ setSearch(trimmed, results);
1428
+ } finally {
1429
+ setIsSearching(false);
1430
+ }
1431
+ };
1432
+ const pages = useMemo3(() => Array.from({ length: pageCount }, (_, i) => i), [pageCount]);
1433
+ const renderHighlightedSnippet = (text, isActive) => {
1434
+ const trimmedQuery = searchQuery.trim();
1435
+ if (trimmedQuery.length < 2) {
1436
+ return /* @__PURE__ */ jsxs6(
1437
+ Text3,
1438
+ {
1439
+ style: [
1440
+ styles5.resultText,
1441
+ isDark && styles5.resultTextDark,
1442
+ isActive && styles5.resultTextActive,
1443
+ isActive && { color: accentColor }
1444
+ ],
1445
+ children: [
1446
+ "...",
1447
+ text,
1448
+ "..."
1449
+ ]
1450
+ }
1451
+ );
1452
+ }
1453
+ const lowerText = text.toLowerCase();
1454
+ const lowerQuery = trimmedQuery.toLowerCase();
1455
+ const parts = [];
1456
+ let cursor = 0;
1457
+ while (cursor < text.length) {
1458
+ const index = lowerText.indexOf(lowerQuery, cursor);
1459
+ if (index === -1) {
1460
+ parts.push({ text: text.slice(cursor), match: false });
1461
+ break;
1462
+ }
1463
+ if (index > cursor) {
1464
+ parts.push({ text: text.slice(cursor, index), match: false });
1465
+ }
1466
+ parts.push({ text: text.slice(index, index + trimmedQuery.length), match: true });
1467
+ cursor = index + trimmedQuery.length;
1468
+ }
1469
+ return /* @__PURE__ */ jsx6(
1470
+ Text3,
1471
+ {
1472
+ style: [
1473
+ styles5.resultText,
1474
+ isDark && styles5.resultTextDark,
1475
+ isActive && styles5.resultTextActive,
1476
+ isActive && { color: accentColor }
1477
+ ],
1478
+ children: parts.map((part, idx) => /* @__PURE__ */ jsx6(
1479
+ Text3,
1480
+ {
1481
+ style: [
1482
+ part.match && styles5.matchText,
1483
+ part.match && isDark && styles5.matchTextDark,
1484
+ part.match && isActive && styles5.matchTextActive,
1485
+ part.match && isActive && { backgroundColor: accentStrong, color: accentColor }
1486
+ ],
1487
+ children: part.text
1488
+ },
1489
+ `${idx}-${part.text}`
1490
+ ))
1491
+ }
1492
+ );
1493
+ };
1494
+ if (!sidebarRightOpen) return null;
1495
+ return /* @__PURE__ */ jsx6(Modal, { visible: true, transparent: true, animationType: "slide", onRequestClose: closeSheet, children: /* @__PURE__ */ jsxs6(View5, { style: styles5.modalRoot, children: [
1496
+ /* @__PURE__ */ jsx6(Pressable4, { style: styles5.backdrop, onPress: closeSheet }),
1497
+ /* @__PURE__ */ jsxs6(View5, { style: [styles5.sheet, { height: sheetHeight }, isDark && styles5.sheetDark], children: [
1498
+ /* @__PURE__ */ jsx6(View5, { style: [styles5.handle, isDark && styles5.handleDark] }),
1499
+ /* @__PURE__ */ jsx6(View5, { style: styles5.tabs, children: ["pages", "search", "annotations"].map((tab) => /* @__PURE__ */ jsx6(
1500
+ Pressable4,
1501
+ {
1502
+ onPress: () => toggleSidebarRight(tab),
1503
+ style: [
1504
+ styles5.tabButton,
1505
+ isDark && styles5.tabButtonDark,
1506
+ sidebarRightTab === tab && styles5.tabButtonActive,
1507
+ sidebarRightTab === tab && { backgroundColor: accentColor }
1508
+ ],
1509
+ children: /* @__PURE__ */ jsx6(
1510
+ Text3,
1511
+ {
1512
+ style: [
1513
+ styles5.tabText,
1514
+ isDark && styles5.tabTextDark,
1515
+ sidebarRightTab === tab && styles5.tabTextActive
1516
+ ],
1517
+ children: tab === "pages" ? t.pages : tab === "search" ? t.search : t.notes
1518
+ }
1519
+ )
1520
+ },
1521
+ tab
1522
+ )) }),
1523
+ sidebarRightTab === "pages" ? /* @__PURE__ */ jsxs6(View5, { style: styles5.pagesContent, children: [
1524
+ /* @__PURE__ */ jsxs6(View5, { style: styles5.pageHeader, children: [
1525
+ /* @__PURE__ */ jsxs6(Text3, { style: [styles5.pageStatus, isDark && styles5.pageStatusDark], children: [
1526
+ t.page,
1527
+ " ",
1528
+ currentPage,
1529
+ " / ",
1530
+ pageCount
1531
+ ] }),
1532
+ /* @__PURE__ */ jsxs6(View5, { style: [styles5.segmented, isDark && styles5.segmentedDark], children: [
1533
+ /* @__PURE__ */ jsx6(
1534
+ Pressable4,
1535
+ {
1536
+ onPress: () => setPagesMode("thumbnails"),
1537
+ style: [
1538
+ styles5.segmentButton,
1539
+ pagesMode === "thumbnails" && styles5.segmentButtonActive,
1540
+ pagesMode === "thumbnails" && { backgroundColor: accentColor }
1541
+ ],
1542
+ children: /* @__PURE__ */ jsx6(
1543
+ Text3,
1544
+ {
1545
+ style: [
1546
+ styles5.segmentText,
1547
+ isDark && styles5.segmentTextDark,
1548
+ pagesMode === "thumbnails" && styles5.segmentTextActive
1549
+ ],
1550
+ children: t.pagesTab
1551
+ }
1552
+ )
1553
+ }
1554
+ ),
1555
+ /* @__PURE__ */ jsx6(
1556
+ Pressable4,
1557
+ {
1558
+ onPress: () => setPagesMode("summary"),
1559
+ style: [
1560
+ styles5.segmentButton,
1561
+ pagesMode === "summary" && styles5.segmentButtonActive,
1562
+ pagesMode === "summary" && { backgroundColor: accentColor }
1563
+ ],
1564
+ children: /* @__PURE__ */ jsx6(
1565
+ Text3,
1566
+ {
1567
+ style: [
1568
+ styles5.segmentText,
1569
+ isDark && styles5.segmentTextDark,
1570
+ pagesMode === "summary" && styles5.segmentTextActive
1571
+ ],
1572
+ children: t.summaryTab
1573
+ }
1574
+ )
1575
+ }
1576
+ )
1577
+ ] })
1578
+ ] }),
1579
+ pagesMode === "thumbnails" ? /* @__PURE__ */ jsx6(
1580
+ FlatList2,
1581
+ {
1582
+ data: pages,
1583
+ keyExtractor: (item) => `thumb-${item}`,
1584
+ numColumns: 2,
1585
+ contentContainerStyle: styles5.thumbGrid,
1586
+ columnWrapperStyle: styles5.thumbRow,
1587
+ showsVerticalScrollIndicator: false,
1588
+ initialNumToRender: 6,
1589
+ renderItem: ({ item }) => /* @__PURE__ */ jsx6(
1590
+ PageThumbnail,
1591
+ {
1592
+ engine,
1593
+ pageIndex: item,
1594
+ isActive: item + 1 === currentPage,
1595
+ isDark,
1596
+ zoom,
1597
+ cardWidth,
1598
+ frameWidth,
1599
+ frameHeight,
1600
+ accentColor,
1601
+ onPress: () => {
1602
+ engine.goToPage(item + 1);
1603
+ setDocumentState({ currentPage: item + 1 });
1604
+ triggerScrollToPage(item);
1605
+ closeSheet();
1606
+ }
1607
+ }
1608
+ )
1609
+ }
1610
+ ) : /* @__PURE__ */ jsx6(ScrollView3, { contentContainerStyle: styles5.summaryContent, showsVerticalScrollIndicator: false, children: outline.length === 0 ? /* @__PURE__ */ jsx6(Text3, { style: [styles5.emptyText, isDark && styles5.emptyTextDark], children: t.noSummary }) : outline.map((item, index) => /* @__PURE__ */ jsx6(
1611
+ OutlineNode,
1612
+ {
1613
+ item,
1614
+ isDark,
1615
+ untitledLabel: t.untitled,
1616
+ onSelect: (pageIndex) => {
1617
+ engine.goToPage(pageIndex + 1);
1618
+ setDocumentState({ currentPage: pageIndex + 1 });
1619
+ triggerScrollToPage(pageIndex);
1620
+ closeSheet();
1621
+ }
1622
+ },
1623
+ `${item.title}-${index}`
1624
+ )) })
1625
+ ] }) : /* @__PURE__ */ jsx6(ScrollView3, { contentContainerStyle: styles5.content, showsVerticalScrollIndicator: false, children: sidebarRightTab === "search" ? /* @__PURE__ */ jsxs6(View5, { children: [
1626
+ /* @__PURE__ */ jsxs6(View5, { style: [styles5.searchBox, isDark && styles5.searchBoxDark], children: [
1627
+ /* @__PURE__ */ jsx6(
1628
+ TextInput,
1629
+ {
1630
+ value: query,
1631
+ onChangeText: setQuery,
1632
+ placeholder: t.searchPlaceholder,
1633
+ placeholderTextColor: isDark ? "#9ca3af" : "#6b7280",
1634
+ style: [styles5.searchInput, isDark && styles5.searchInputDark],
1635
+ onSubmitEditing: handleSearch,
1636
+ returnKeyType: "search"
1637
+ }
1638
+ ),
1639
+ /* @__PURE__ */ jsx6(Pressable4, { onPress: handleSearch, style: [styles5.searchButton, { backgroundColor: accentColor }], children: /* @__PURE__ */ jsx6(Text3, { style: styles5.searchButtonText, children: t.searchGo }) })
1640
+ ] }),
1641
+ /* @__PURE__ */ jsxs6(View5, { style: styles5.searchMeta, children: [
1642
+ /* @__PURE__ */ jsxs6(Text3, { style: [styles5.searchCount, isDark && styles5.searchCountDark, { color: accentColor }], children: [
1643
+ searchResults.length,
1644
+ " ",
1645
+ t.results
1646
+ ] }),
1647
+ /* @__PURE__ */ jsxs6(View5, { style: styles5.searchNav, children: [
1648
+ /* @__PURE__ */ jsx6(
1649
+ Pressable4,
1650
+ {
1651
+ onPress: prevSearchResult,
1652
+ disabled: searchResults.length === 0,
1653
+ style: [
1654
+ styles5.searchNavButton,
1655
+ isDark && styles5.searchNavButtonDark,
1656
+ searchResults.length === 0 && styles5.searchNavButtonDisabled
1657
+ ],
1658
+ children: /* @__PURE__ */ jsx6(IconChevronLeft, { size: 14, color: isDark ? "#e5e7eb" : "#111827" })
1659
+ }
1660
+ ),
1661
+ /* @__PURE__ */ jsx6(
1662
+ Pressable4,
1663
+ {
1664
+ onPress: nextSearchResult,
1665
+ disabled: searchResults.length === 0,
1666
+ style: [
1667
+ styles5.searchNavButton,
1668
+ isDark && styles5.searchNavButtonDark,
1669
+ searchResults.length === 0 && styles5.searchNavButtonDisabled
1670
+ ],
1671
+ children: /* @__PURE__ */ jsx6(IconChevronRight, { size: 14, color: isDark ? "#e5e7eb" : "#111827" })
1672
+ }
1673
+ )
1674
+ ] })
1675
+ ] }),
1676
+ isSearching && /* @__PURE__ */ jsxs6(View5, { style: styles5.searchStatus, children: [
1677
+ /* @__PURE__ */ jsx6(ActivityIndicator, { size: "small", color: accentColor }),
1678
+ /* @__PURE__ */ jsx6(Text3, { style: [styles5.searchStatusText, isDark && styles5.searchStatusTextDark], children: t.searching })
1679
+ ] }),
1680
+ !isSearching && searchResults.length === 0 && /* @__PURE__ */ jsx6(Text3, { style: [styles5.emptyText, isDark && styles5.emptyTextDark], children: t.noResults }),
1681
+ !isSearching && searchResults.map((res, idx) => {
1682
+ const isActive = idx === activeSearchIndex;
1683
+ return /* @__PURE__ */ jsxs6(
1684
+ Pressable4,
1685
+ {
1686
+ onPress: () => {
1687
+ setDocumentState({ activeSearchIndex: idx });
1688
+ triggerScrollToPage(res.pageIndex);
1689
+ closeSheet();
1690
+ },
1691
+ style: [
1692
+ styles5.resultCard,
1693
+ isDark && styles5.resultCardDark,
1694
+ isActive && styles5.resultCardActive,
1695
+ isActive && { borderColor: accentColor }
1696
+ ],
1697
+ children: [
1698
+ /* @__PURE__ */ jsxs6(Text3, { style: [styles5.resultPage, isDark && styles5.resultPageDark, { color: accentColor }], children: [
1699
+ t.page,
1700
+ " ",
1701
+ res.pageIndex + 1
1702
+ ] }),
1703
+ renderHighlightedSnippet(res.text, isActive)
1704
+ ]
1705
+ },
1706
+ `${res.pageIndex}-${idx}`
1707
+ );
1708
+ })
1709
+ ] }) : /* @__PURE__ */ jsx6(View5, { children: annotations.length === 0 ? /* @__PURE__ */ jsx6(Text3, { style: [styles5.emptyText, isDark && styles5.emptyTextDark], children: t.noAnnotations }) : annotations.map((ann) => /* @__PURE__ */ jsxs6(
1710
+ Pressable4,
1711
+ {
1712
+ onPress: () => {
1713
+ setSelectedAnnotation(ann.id);
1714
+ triggerScrollToPage(ann.pageIndex);
1715
+ closeSheet();
1716
+ },
1717
+ style: [styles5.noteCard, isDark && styles5.noteCardDark],
1718
+ children: [
1719
+ /* @__PURE__ */ jsxs6(View5, { style: styles5.noteHeader, children: [
1720
+ /* @__PURE__ */ jsx6(View5, { style: [styles5.noteDot, { backgroundColor: ann.color }] }),
1721
+ /* @__PURE__ */ jsxs6(Text3, { style: [styles5.noteTitle, isDark && styles5.noteTitleDark], children: [
1722
+ t.page,
1723
+ " ",
1724
+ ann.pageIndex + 1
1725
+ ] })
1726
+ ] }),
1727
+ /* @__PURE__ */ jsx6(Text3, { style: [styles5.noteType, isDark && styles5.noteTypeDark, { color: accentColor }], children: ann.type === "comment" || ann.type === "text" ? t.note.toUpperCase() : ann.type.toUpperCase() }),
1728
+ ann.content ? /* @__PURE__ */ jsx6(Text3, { style: [styles5.noteContent, isDark && styles5.noteContentDark], children: ann.content }) : null
1729
+ ]
1730
+ },
1731
+ ann.id
1732
+ )) }) })
1733
+ ] })
1734
+ ] }) });
1735
+ };
1736
+ var styles5 = StyleSheet5.create({
1737
+ modalRoot: {
1738
+ flex: 1,
1739
+ backgroundColor: "transparent"
1740
+ },
1741
+ backdrop: {
1742
+ ...StyleSheet5.absoluteFillObject,
1743
+ backgroundColor: "rgba(0, 0, 0, 0.4)"
1744
+ },
1745
+ sheet: {
1746
+ position: "absolute",
1747
+ left: 0,
1748
+ right: 0,
1749
+ bottom: 0,
1750
+ backgroundColor: "#ffffff",
1751
+ borderTopLeftRadius: 20,
1752
+ borderTopRightRadius: 20,
1753
+ borderTopWidth: 1,
1754
+ borderTopColor: "#e5e7eb",
1755
+ paddingBottom: 16
1756
+ },
1757
+ sheetDark: {
1758
+ backgroundColor: "#0f1115",
1759
+ borderTopColor: "#1f2937"
1760
+ },
1761
+ handle: {
1762
+ width: 44,
1763
+ height: 4,
1764
+ borderRadius: 999,
1765
+ backgroundColor: "#cbd5f5",
1766
+ alignSelf: "center",
1767
+ marginTop: 10,
1768
+ marginBottom: 12
1769
+ },
1770
+ handleDark: {
1771
+ backgroundColor: "#374151"
1772
+ },
1773
+ tabs: {
1774
+ flexDirection: "row",
1775
+ alignItems: "center",
1776
+ paddingHorizontal: 16,
1777
+ marginBottom: 10
1778
+ },
1779
+ tabButton: {
1780
+ paddingVertical: 6,
1781
+ paddingHorizontal: 14,
1782
+ borderRadius: 999,
1783
+ marginRight: 8,
1784
+ backgroundColor: "#e5e7eb"
1785
+ },
1786
+ tabButtonDark: {
1787
+ backgroundColor: "#111827"
1788
+ },
1789
+ tabButtonActive: {
1790
+ backgroundColor: "#2563eb"
1791
+ },
1792
+ tabText: {
1793
+ fontSize: 12,
1794
+ fontWeight: "700",
1795
+ color: "#111827"
1796
+ },
1797
+ tabTextDark: {
1798
+ color: "#e5e7eb"
1799
+ },
1800
+ tabTextActive: {
1801
+ color: "#ffffff"
1802
+ },
1803
+ pagesContent: {
1804
+ paddingHorizontal: 16,
1805
+ flex: 1
1806
+ },
1807
+ pageHeader: {
1808
+ flexDirection: "row",
1809
+ alignItems: "center",
1810
+ justifyContent: "space-between",
1811
+ marginBottom: 10
1812
+ },
1813
+ pageStatus: {
1814
+ fontSize: 12,
1815
+ fontWeight: "700",
1816
+ color: "#111827"
1817
+ },
1818
+ pageStatusDark: {
1819
+ color: "#e5e7eb"
1820
+ },
1821
+ segmented: {
1822
+ flexDirection: "row",
1823
+ backgroundColor: "#e5e7eb",
1824
+ borderRadius: 999,
1825
+ padding: 2
1826
+ },
1827
+ segmentedDark: {
1828
+ backgroundColor: "#111827"
1829
+ },
1830
+ segmentButton: {
1831
+ paddingHorizontal: 10,
1832
+ paddingVertical: 5,
1833
+ borderRadius: 999
1834
+ },
1835
+ segmentButtonActive: {
1836
+ backgroundColor: "#2563eb"
1837
+ },
1838
+ segmentText: {
1839
+ fontSize: 11,
1840
+ fontWeight: "700",
1841
+ color: "#111827"
1842
+ },
1843
+ segmentTextDark: {
1844
+ color: "#e5e7eb"
1845
+ },
1846
+ segmentTextActive: {
1847
+ color: "#ffffff"
1848
+ },
1849
+ thumbGrid: {
1850
+ paddingHorizontal: 16,
1851
+ paddingBottom: 16
1852
+ },
1853
+ thumbRow: {
1854
+ justifyContent: "space-between",
1855
+ marginBottom: 12
1856
+ },
1857
+ thumbCard: {
1858
+ padding: 8,
1859
+ borderRadius: 14,
1860
+ backgroundColor: "#f9fafb",
1861
+ borderWidth: 1,
1862
+ borderColor: "#e5e7eb",
1863
+ alignItems: "center"
1864
+ },
1865
+ thumbCardDark: {
1866
+ backgroundColor: "#111827",
1867
+ borderColor: "#1f2937"
1868
+ },
1869
+ thumbCardActive: {
1870
+ borderColor: "#2563eb"
1871
+ },
1872
+ thumbFrame: {
1873
+ borderRadius: 10,
1874
+ backgroundColor: "#ffffff",
1875
+ overflow: "hidden"
1876
+ },
1877
+ thumbView: {
1878
+ width: "100%",
1879
+ height: "100%"
1880
+ },
1881
+ thumbLabel: {
1882
+ marginTop: 6,
1883
+ fontSize: 11,
1884
+ fontWeight: "700",
1885
+ color: "#111827"
1886
+ },
1887
+ thumbLabelDark: {
1888
+ color: "#e5e7eb"
1889
+ },
1890
+ content: {
1891
+ paddingHorizontal: 16,
1892
+ paddingBottom: 16
1893
+ },
1894
+ summaryContent: {
1895
+ paddingBottom: 24
1896
+ },
1897
+ outlineRow: {
1898
+ paddingVertical: 8,
1899
+ borderBottomWidth: 1,
1900
+ borderBottomColor: "rgba(148, 163, 184, 0.18)"
1901
+ },
1902
+ outlineText: {
1903
+ fontSize: 12,
1904
+ fontWeight: "600",
1905
+ color: "#111827"
1906
+ },
1907
+ outlineTextDark: {
1908
+ color: "#e5e7eb"
1909
+ },
1910
+ outlineTextMuted: {
1911
+ color: "#9ca3af"
1912
+ },
1913
+ searchBox: {
1914
+ flexDirection: "row",
1915
+ alignItems: "center",
1916
+ borderRadius: 10,
1917
+ backgroundColor: "#f3f4f6",
1918
+ paddingHorizontal: 12,
1919
+ paddingVertical: 8,
1920
+ borderWidth: 1,
1921
+ borderColor: "#e5e7eb"
1922
+ },
1923
+ searchBoxDark: {
1924
+ backgroundColor: "#111827",
1925
+ borderColor: "#1f2937"
1926
+ },
1927
+ searchInput: {
1928
+ flex: 1,
1929
+ fontSize: 12,
1930
+ color: "#111827"
1931
+ },
1932
+ searchInputDark: {
1933
+ color: "#e5e7eb"
1934
+ },
1935
+ searchButton: {
1936
+ paddingHorizontal: 10,
1937
+ paddingVertical: 4,
1938
+ borderRadius: 6,
1939
+ backgroundColor: "#2563eb"
1940
+ },
1941
+ searchButtonText: {
1942
+ fontSize: 11,
1943
+ fontWeight: "700",
1944
+ color: "#ffffff"
1945
+ },
1946
+ searchStatus: {
1947
+ marginTop: 12,
1948
+ flexDirection: "row",
1949
+ alignItems: "center"
1950
+ },
1951
+ searchStatusText: {
1952
+ marginLeft: 8,
1953
+ fontSize: 11,
1954
+ color: "#4b5563"
1955
+ },
1956
+ searchStatusTextDark: {
1957
+ color: "#9ca3af"
1958
+ },
1959
+ searchMeta: {
1960
+ marginTop: 12,
1961
+ flexDirection: "row",
1962
+ alignItems: "center",
1963
+ justifyContent: "space-between"
1964
+ },
1965
+ searchCount: {
1966
+ fontSize: 11,
1967
+ fontWeight: "700",
1968
+ color: "#2563eb"
1969
+ },
1970
+ searchCountDark: {
1971
+ color: "#60a5fa"
1972
+ },
1973
+ searchNav: {
1974
+ flexDirection: "row",
1975
+ alignItems: "center"
1976
+ },
1977
+ searchNavButton: {
1978
+ width: 28,
1979
+ height: 28,
1980
+ borderRadius: 10,
1981
+ backgroundColor: "#e5e7eb",
1982
+ alignItems: "center",
1983
+ justifyContent: "center",
1984
+ marginLeft: 6
1985
+ },
1986
+ searchNavButtonDark: {
1987
+ backgroundColor: "#111827"
1988
+ },
1989
+ searchNavButtonDisabled: {
1990
+ opacity: 0.5
1991
+ },
1992
+ emptyText: {
1993
+ marginTop: 16,
1994
+ fontSize: 12,
1995
+ color: "#6b7280"
1996
+ },
1997
+ emptyTextDark: {
1998
+ color: "#9ca3af"
1999
+ },
2000
+ resultCard: {
2001
+ marginTop: 12,
2002
+ padding: 12,
2003
+ borderRadius: 12,
2004
+ backgroundColor: "#f9fafb",
2005
+ borderWidth: 1,
2006
+ borderColor: "#e5e7eb"
2007
+ },
2008
+ resultCardDark: {
2009
+ backgroundColor: "#111827",
2010
+ borderColor: "#1f2937"
2011
+ },
2012
+ resultCardActive: {
2013
+ borderColor: "#2563eb"
2014
+ },
2015
+ resultPage: {
2016
+ fontSize: 10,
2017
+ fontWeight: "800",
2018
+ color: "#2563eb",
2019
+ marginBottom: 6
2020
+ },
2021
+ resultPageDark: {
2022
+ color: "#60a5fa"
2023
+ },
2024
+ resultText: {
2025
+ fontSize: 11,
2026
+ color: "#374151"
2027
+ },
2028
+ resultTextDark: {
2029
+ color: "#d1d5db"
2030
+ },
2031
+ resultTextActive: {
2032
+ color: "#1d4ed8"
2033
+ },
2034
+ matchText: {
2035
+ backgroundColor: "rgba(245, 158, 11, 0.3)",
2036
+ color: "#111827",
2037
+ fontWeight: "700"
2038
+ },
2039
+ matchTextDark: {
2040
+ backgroundColor: "rgba(245, 158, 11, 0.25)",
2041
+ color: "#fde68a"
2042
+ },
2043
+ matchTextActive: {
2044
+ backgroundColor: "rgba(59, 130, 246, 0.35)",
2045
+ color: "#1d4ed8"
2046
+ },
2047
+ noteCard: {
2048
+ padding: 12,
2049
+ borderRadius: 12,
2050
+ backgroundColor: "#f9fafb",
2051
+ borderWidth: 1,
2052
+ borderColor: "#e5e7eb",
2053
+ marginBottom: 12
2054
+ },
2055
+ noteCardDark: {
2056
+ backgroundColor: "#111827",
2057
+ borderColor: "#1f2937"
2058
+ },
2059
+ noteHeader: {
2060
+ flexDirection: "row",
2061
+ alignItems: "center",
2062
+ marginBottom: 6
2063
+ },
2064
+ noteDot: {
2065
+ width: 8,
2066
+ height: 8,
2067
+ borderRadius: 4,
2068
+ marginRight: 6
2069
+ },
2070
+ noteTitle: {
2071
+ fontSize: 11,
2072
+ fontWeight: "700",
2073
+ color: "#111827"
2074
+ },
2075
+ noteTitleDark: {
2076
+ color: "#e5e7eb"
2077
+ },
2078
+ noteType: {
2079
+ fontSize: 10,
2080
+ fontWeight: "800",
2081
+ color: "#2563eb"
2082
+ },
2083
+ noteTypeDark: {
2084
+ color: "#60a5fa"
2085
+ },
2086
+ noteContent: {
2087
+ marginTop: 6,
2088
+ fontSize: 11,
2089
+ color: "#4b5563"
2090
+ },
2091
+ noteContentDark: {
2092
+ color: "#9ca3af"
2093
+ }
2094
+ });
2095
+ var RightSheet_default = RightSheet;
2096
+
2097
+ // components/AnnotationEditor.tsx
2098
+ import { useEffect as useEffect5, useState as useState4 } from "react";
2099
+ import { Modal as Modal2, View as View6, Text as Text4, TextInput as TextInput2, Pressable as Pressable5, StyleSheet as StyleSheet6 } from "react-native";
2100
+ import { useViewerStore as useViewerStore6 } from "@papyrus-sdk/core";
2101
+ import { jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
2102
+ var AnnotationEditor = () => {
2103
+ const { annotations, selectedAnnotationId, updateAnnotation, setSelectedAnnotation, uiTheme, locale, accentColor } = useViewerStore6();
2104
+ const annotation = annotations.find((ann) => ann.id === selectedAnnotationId);
2105
+ const isEditable = annotation && (annotation.type === "text" || annotation.type === "comment");
2106
+ const [draft, setDraft] = useState4("");
2107
+ const isDark = uiTheme === "dark";
2108
+ const t = getStrings(locale);
2109
+ useEffect5(() => {
2110
+ if (isEditable) {
2111
+ setDraft(annotation?.content ?? "");
2112
+ }
2113
+ }, [annotation?.id, isEditable]);
2114
+ if (!isEditable || !annotation) return null;
2115
+ const handleClose = () => setSelectedAnnotation(null);
2116
+ const handleSave = () => {
2117
+ updateAnnotation(annotation.id, { content: draft });
2118
+ setSelectedAnnotation(null);
2119
+ };
2120
+ return /* @__PURE__ */ jsx7(Modal2, { visible: true, transparent: true, animationType: "fade", onRequestClose: handleClose, children: /* @__PURE__ */ jsx7(View6, { style: styles6.overlay, children: /* @__PURE__ */ jsxs7(View6, { style: [styles6.card, isDark && styles6.cardDark], children: [
2121
+ /* @__PURE__ */ jsx7(Text4, { style: [styles6.title, isDark && styles6.titleDark], children: t.editNote }),
2122
+ /* @__PURE__ */ jsx7(
2123
+ TextInput2,
2124
+ {
2125
+ style: [styles6.input, isDark && styles6.inputDark],
2126
+ value: draft,
2127
+ onChangeText: setDraft,
2128
+ placeholder: t.notePlaceholder,
2129
+ placeholderTextColor: isDark ? "#9ca3af" : "#6b7280",
2130
+ multiline: true
2131
+ }
2132
+ ),
2133
+ /* @__PURE__ */ jsxs7(View6, { style: styles6.actions, children: [
2134
+ /* @__PURE__ */ jsx7(Pressable5, { onPress: handleClose, style: [styles6.actionButton, styles6.actionCancel], children: /* @__PURE__ */ jsx7(Text4, { style: styles6.actionText, children: t.cancel }) }),
2135
+ /* @__PURE__ */ jsx7(Pressable5, { onPress: handleSave, style: [styles6.actionButton, styles6.actionSave, { backgroundColor: accentColor }], children: /* @__PURE__ */ jsx7(Text4, { style: [styles6.actionText, styles6.actionTextLight], children: t.save }) })
2136
+ ] })
2137
+ ] }) }) });
2138
+ };
2139
+ var styles6 = StyleSheet6.create({
2140
+ overlay: {
2141
+ flex: 1,
2142
+ alignItems: "center",
2143
+ justifyContent: "center",
2144
+ backgroundColor: "rgba(0, 0, 0, 0.4)",
2145
+ padding: 24
2146
+ },
2147
+ card: {
2148
+ width: "100%",
2149
+ borderRadius: 16,
2150
+ padding: 16,
2151
+ backgroundColor: "#ffffff",
2152
+ borderWidth: 1,
2153
+ borderColor: "#e5e7eb"
2154
+ },
2155
+ cardDark: {
2156
+ backgroundColor: "#0f1115",
2157
+ borderColor: "#1f2937"
2158
+ },
2159
+ title: {
2160
+ fontSize: 14,
2161
+ fontWeight: "700",
2162
+ color: "#111827",
2163
+ marginBottom: 12
2164
+ },
2165
+ titleDark: {
2166
+ color: "#f9fafb"
2167
+ },
2168
+ input: {
2169
+ minHeight: 100,
2170
+ borderRadius: 12,
2171
+ padding: 12,
2172
+ backgroundColor: "#f3f4f6",
2173
+ color: "#111827",
2174
+ fontSize: 12
2175
+ },
2176
+ inputDark: {
2177
+ backgroundColor: "#111827",
2178
+ color: "#e5e7eb"
2179
+ },
2180
+ actions: {
2181
+ marginTop: 16,
2182
+ flexDirection: "row",
2183
+ justifyContent: "flex-end"
2184
+ },
2185
+ actionButton: {
2186
+ paddingHorizontal: 12,
2187
+ paddingVertical: 8,
2188
+ borderRadius: 8,
2189
+ marginLeft: 8
2190
+ },
2191
+ actionCancel: {
2192
+ backgroundColor: "#e5e7eb"
2193
+ },
2194
+ actionSave: {
2195
+ backgroundColor: "#2563eb"
2196
+ },
2197
+ actionText: {
2198
+ fontSize: 11,
2199
+ fontWeight: "700",
2200
+ color: "#111827"
2201
+ },
2202
+ actionTextLight: {
2203
+ color: "#ffffff"
2204
+ }
2205
+ });
2206
+ var AnnotationEditor_default = AnnotationEditor;
2207
+
2208
+ // components/BottomBar.tsx
2209
+ import { View as View7, Text as Text5, Pressable as Pressable6, StyleSheet as StyleSheet7 } from "react-native";
2210
+ import { useViewerStore as useViewerStore7 } from "@papyrus-sdk/core";
2211
+ import { jsx as jsx8, jsxs as jsxs8 } from "react/jsx-runtime";
2212
+ var BottomBar = () => {
2213
+ const { sidebarRightOpen, sidebarRightTab, toggleSidebarRight, setDocumentState, uiTheme, locale, accentColor } = useViewerStore7();
2214
+ const isDark = uiTheme === "dark";
2215
+ const t = getStrings(locale);
2216
+ const isActive = (tab) => sidebarRightOpen && sidebarRightTab === tab;
2217
+ const iconColor = (active) => {
2218
+ if (active) return "#ffffff";
2219
+ return isDark ? "#e5e7eb" : "#111827";
2220
+ };
2221
+ return /* @__PURE__ */ jsxs8(View7, { style: [styles7.container, isDark && styles7.containerDark], children: [
2222
+ /* @__PURE__ */ jsxs8(
2223
+ Pressable6,
2224
+ {
2225
+ onPress: () => toggleSidebarRight("pages"),
2226
+ style: [styles7.item, isActive("pages") && styles7.itemActive],
2227
+ children: [
2228
+ /* @__PURE__ */ jsx8(
2229
+ View7,
2230
+ {
2231
+ style: [
2232
+ styles7.itemIcon,
2233
+ isDark && styles7.itemIconDark,
2234
+ isActive("pages") && styles7.itemIconActive,
2235
+ isActive("pages") && { backgroundColor: accentColor }
2236
+ ],
2237
+ children: /* @__PURE__ */ jsx8(IconGrid, { size: 16, color: iconColor(isActive("pages")) })
2238
+ }
2239
+ ),
2240
+ /* @__PURE__ */ jsx8(
2241
+ Text5,
2242
+ {
2243
+ style: [
2244
+ styles7.itemLabel,
2245
+ isDark && styles7.itemLabelDark,
2246
+ isActive("pages") && styles7.itemLabelActive,
2247
+ isActive("pages") && { color: accentColor }
2248
+ ],
2249
+ children: t.pages
2250
+ }
2251
+ )
2252
+ ]
2253
+ }
2254
+ ),
2255
+ /* @__PURE__ */ jsxs8(
2256
+ Pressable6,
2257
+ {
2258
+ onPress: () => toggleSidebarRight("search"),
2259
+ style: [styles7.item, isActive("search") && styles7.itemActive],
2260
+ children: [
2261
+ /* @__PURE__ */ jsx8(
2262
+ View7,
2263
+ {
2264
+ style: [
2265
+ styles7.itemIcon,
2266
+ isDark && styles7.itemIconDark,
2267
+ isActive("search") && styles7.itemIconActive,
2268
+ isActive("search") && { backgroundColor: accentColor }
2269
+ ],
2270
+ children: /* @__PURE__ */ jsx8(IconSearch, { size: 16, color: iconColor(isActive("search")) })
2271
+ }
2272
+ ),
2273
+ /* @__PURE__ */ jsx8(
2274
+ Text5,
2275
+ {
2276
+ style: [
2277
+ styles7.itemLabel,
2278
+ isDark && styles7.itemLabelDark,
2279
+ isActive("search") && styles7.itemLabelActive,
2280
+ isActive("search") && { color: accentColor }
2281
+ ],
2282
+ children: t.search
2283
+ }
2284
+ )
2285
+ ]
2286
+ }
2287
+ ),
2288
+ /* @__PURE__ */ jsxs8(
2289
+ Pressable6,
2290
+ {
2291
+ onPress: () => setDocumentState({ sidebarRightOpen: false }),
2292
+ style: [styles7.item, !sidebarRightOpen && styles7.itemActive],
2293
+ children: [
2294
+ /* @__PURE__ */ jsx8(
2295
+ View7,
2296
+ {
2297
+ style: [
2298
+ styles7.itemIcon,
2299
+ isDark && styles7.itemIconDark,
2300
+ !sidebarRightOpen && styles7.itemIconActive,
2301
+ !sidebarRightOpen && { backgroundColor: accentColor }
2302
+ ],
2303
+ children: /* @__PURE__ */ jsx8(IconDocument, { size: 16, color: iconColor(!sidebarRightOpen) })
2304
+ }
2305
+ ),
2306
+ /* @__PURE__ */ jsx8(
2307
+ Text5,
2308
+ {
2309
+ style: [
2310
+ styles7.itemLabel,
2311
+ isDark && styles7.itemLabelDark,
2312
+ !sidebarRightOpen && styles7.itemLabelActive,
2313
+ !sidebarRightOpen && { color: accentColor }
2314
+ ],
2315
+ children: t.read
2316
+ }
2317
+ )
2318
+ ]
2319
+ }
2320
+ ),
2321
+ /* @__PURE__ */ jsxs8(
2322
+ Pressable6,
2323
+ {
2324
+ onPress: () => toggleSidebarRight("annotations"),
2325
+ style: [styles7.item, isActive("annotations") && styles7.itemActive],
2326
+ children: [
2327
+ /* @__PURE__ */ jsx8(
2328
+ View7,
2329
+ {
2330
+ style: [
2331
+ styles7.itemIcon,
2332
+ isDark && styles7.itemIconDark,
2333
+ isActive("annotations") && styles7.itemIconActive,
2334
+ isActive("annotations") && { backgroundColor: accentColor }
2335
+ ],
2336
+ children: /* @__PURE__ */ jsx8(IconComment, { size: 16, color: iconColor(isActive("annotations")) })
2337
+ }
2338
+ ),
2339
+ /* @__PURE__ */ jsx8(
2340
+ Text5,
2341
+ {
2342
+ style: [
2343
+ styles7.itemLabel,
2344
+ isDark && styles7.itemLabelDark,
2345
+ isActive("annotations") && styles7.itemLabelActive,
2346
+ isActive("annotations") && { color: accentColor }
2347
+ ],
2348
+ children: t.notes
2349
+ }
2350
+ )
2351
+ ]
2352
+ }
2353
+ )
2354
+ ] });
2355
+ };
2356
+ var styles7 = StyleSheet7.create({
2357
+ container: {
2358
+ flexDirection: "row",
2359
+ justifyContent: "space-around",
2360
+ alignItems: "center",
2361
+ paddingVertical: 10,
2362
+ paddingHorizontal: 12,
2363
+ backgroundColor: "#ffffff",
2364
+ borderTopWidth: 1,
2365
+ borderTopColor: "#e5e7eb"
2366
+ },
2367
+ containerDark: {
2368
+ backgroundColor: "#0f1115",
2369
+ borderTopColor: "#1f2937"
2370
+ },
2371
+ item: {
2372
+ alignItems: "center",
2373
+ paddingHorizontal: 6
2374
+ },
2375
+ itemActive: {
2376
+ transform: [{ translateY: -2 }]
2377
+ },
2378
+ itemIcon: {
2379
+ width: 28,
2380
+ height: 28,
2381
+ borderRadius: 10,
2382
+ backgroundColor: "#e5e7eb",
2383
+ alignItems: "center",
2384
+ justifyContent: "center",
2385
+ marginBottom: 4
2386
+ },
2387
+ itemIconDark: {
2388
+ backgroundColor: "#111827",
2389
+ color: "#e5e7eb"
2390
+ },
2391
+ itemIconActive: {
2392
+ backgroundColor: "#2563eb",
2393
+ color: "#ffffff"
2394
+ },
2395
+ itemLabel: {
2396
+ fontSize: 10,
2397
+ fontWeight: "700",
2398
+ color: "#6b7280"
2399
+ },
2400
+ itemLabelDark: {
2401
+ color: "#9ca3af"
2402
+ },
2403
+ itemLabelActive: {
2404
+ color: "#2563eb"
2405
+ }
2406
+ });
2407
+ var BottomBar_default = BottomBar;
2408
+
2409
+ // components/SettingsSheet.tsx
2410
+ import { Modal as Modal3, View as View8, Text as Text6, Pressable as Pressable7, StyleSheet as StyleSheet8 } from "react-native";
2411
+ import { useViewerStore as useViewerStore8 } from "@papyrus-sdk/core";
2412
+ import { jsx as jsx9, jsxs as jsxs9 } from "react/jsx-runtime";
2413
+ var SettingsSheet = ({ engine, visible, onClose }) => {
2414
+ const { viewMode, uiTheme, zoom, setDocumentState, locale, accentColor, pageTheme } = useViewerStore8();
2415
+ const isDark = uiTheme === "dark";
2416
+ const isPaged = viewMode === "single";
2417
+ const isDouble = viewMode === "double";
2418
+ const t = getStrings(locale);
2419
+ const handleTransition = (mode) => {
2420
+ if (mode === "paged") {
2421
+ setDocumentState({ viewMode: "single" });
2422
+ return;
2423
+ }
2424
+ setDocumentState({ viewMode: isDouble ? "double" : "continuous" });
2425
+ };
2426
+ const handleLayout = (layout) => {
2427
+ if (layout === "double") {
2428
+ setDocumentState({ viewMode: "double" });
2429
+ return;
2430
+ }
2431
+ if (viewMode === "double") {
2432
+ setDocumentState({ viewMode: "continuous" });
2433
+ }
2434
+ };
2435
+ const handleRotate = (direction) => {
2436
+ engine.rotate(direction);
2437
+ setDocumentState({ rotation: engine.getRotation() });
2438
+ };
2439
+ const handleZoom = (delta) => {
2440
+ const next = Math.max(0.5, Math.min(4, zoom + delta));
2441
+ engine.setZoom(next);
2442
+ setDocumentState({ zoom: next });
2443
+ };
2444
+ if (!visible) return null;
2445
+ return /* @__PURE__ */ jsx9(Modal3, { visible: true, transparent: true, animationType: "slide", onRequestClose: onClose, children: /* @__PURE__ */ jsxs9(View8, { style: styles8.modalRoot, children: [
2446
+ /* @__PURE__ */ jsx9(Pressable7, { style: styles8.backdrop, onPress: onClose }),
2447
+ /* @__PURE__ */ jsxs9(View8, { style: [styles8.sheet, isDark && styles8.sheetDark], children: [
2448
+ /* @__PURE__ */ jsx9(View8, { style: [styles8.handle, isDark && styles8.handleDark] }),
2449
+ /* @__PURE__ */ jsxs9(View8, { style: styles8.section, children: [
2450
+ /* @__PURE__ */ jsx9(Text6, { style: [styles8.sectionTitle, isDark && styles8.sectionTitleDark], children: t.appearance }),
2451
+ /* @__PURE__ */ jsxs9(View8, { style: styles8.optionRow, children: [
2452
+ /* @__PURE__ */ jsx9(
2453
+ Pressable7,
2454
+ {
2455
+ onPress: () => setDocumentState({ uiTheme: "light" }),
2456
+ style: [
2457
+ styles8.optionButton,
2458
+ isDark && styles8.optionButtonDark,
2459
+ uiTheme === "light" && styles8.optionButtonActive,
2460
+ uiTheme === "light" && { backgroundColor: accentColor }
2461
+ ],
2462
+ children: /* @__PURE__ */ jsx9(
2463
+ Text6,
2464
+ {
2465
+ style: [
2466
+ styles8.optionText,
2467
+ isDark && styles8.optionTextDark,
2468
+ uiTheme === "light" && styles8.optionTextActive
2469
+ ],
2470
+ children: t.light
2471
+ }
2472
+ )
2473
+ }
2474
+ ),
2475
+ /* @__PURE__ */ jsx9(
2476
+ Pressable7,
2477
+ {
2478
+ onPress: () => setDocumentState({ uiTheme: "dark" }),
2479
+ style: [
2480
+ styles8.optionButton,
2481
+ isDark && styles8.optionButtonDark,
2482
+ uiTheme === "dark" && styles8.optionButtonActive,
2483
+ uiTheme === "dark" && { backgroundColor: accentColor }
2484
+ ],
2485
+ children: /* @__PURE__ */ jsx9(
2486
+ Text6,
2487
+ {
2488
+ style: [
2489
+ styles8.optionText,
2490
+ isDark && styles8.optionTextDark,
2491
+ uiTheme === "dark" && styles8.optionTextActive
2492
+ ],
2493
+ children: t.dark
2494
+ }
2495
+ )
2496
+ }
2497
+ )
2498
+ ] })
2499
+ ] }),
2500
+ /* @__PURE__ */ jsxs9(View8, { style: styles8.section, children: [
2501
+ /* @__PURE__ */ jsx9(Text6, { style: [styles8.sectionTitle, isDark && styles8.sectionTitleDark], children: t.pageTheme }),
2502
+ /* @__PURE__ */ jsxs9(View8, { style: styles8.optionRow, children: [
2503
+ /* @__PURE__ */ jsx9(
2504
+ Pressable7,
2505
+ {
2506
+ onPress: () => setDocumentState({ pageTheme: "normal" }),
2507
+ style: [
2508
+ styles8.optionButton,
2509
+ isDark && styles8.optionButtonDark,
2510
+ pageTheme === "normal" && styles8.optionButtonActive,
2511
+ pageTheme === "normal" && { backgroundColor: accentColor }
2512
+ ],
2513
+ children: /* @__PURE__ */ jsx9(
2514
+ Text6,
2515
+ {
2516
+ style: [
2517
+ styles8.optionText,
2518
+ isDark && styles8.optionTextDark,
2519
+ pageTheme === "normal" && styles8.optionTextActive
2520
+ ],
2521
+ children: t.themeOriginal
2522
+ }
2523
+ )
2524
+ }
2525
+ ),
2526
+ /* @__PURE__ */ jsx9(
2527
+ Pressable7,
2528
+ {
2529
+ onPress: () => setDocumentState({ pageTheme: "sepia" }),
2530
+ style: [
2531
+ styles8.optionButton,
2532
+ isDark && styles8.optionButtonDark,
2533
+ pageTheme === "sepia" && styles8.optionButtonActive,
2534
+ pageTheme === "sepia" && { backgroundColor: accentColor }
2535
+ ],
2536
+ children: /* @__PURE__ */ jsx9(
2537
+ Text6,
2538
+ {
2539
+ style: [
2540
+ styles8.optionText,
2541
+ isDark && styles8.optionTextDark,
2542
+ pageTheme === "sepia" && styles8.optionTextActive
2543
+ ],
2544
+ children: t.themeSepia
2545
+ }
2546
+ )
2547
+ }
2548
+ ),
2549
+ /* @__PURE__ */ jsx9(
2550
+ Pressable7,
2551
+ {
2552
+ onPress: () => setDocumentState({ pageTheme: "dark" }),
2553
+ style: [
2554
+ styles8.optionButton,
2555
+ isDark && styles8.optionButtonDark,
2556
+ pageTheme === "dark" && styles8.optionButtonActive,
2557
+ pageTheme === "dark" && { backgroundColor: accentColor }
2558
+ ],
2559
+ children: /* @__PURE__ */ jsx9(
2560
+ Text6,
2561
+ {
2562
+ style: [
2563
+ styles8.optionText,
2564
+ isDark && styles8.optionTextDark,
2565
+ pageTheme === "dark" && styles8.optionTextActive
2566
+ ],
2567
+ children: t.themeDark
2568
+ }
2569
+ )
2570
+ }
2571
+ ),
2572
+ /* @__PURE__ */ jsx9(
2573
+ Pressable7,
2574
+ {
2575
+ onPress: () => setDocumentState({ pageTheme: "high-contrast" }),
2576
+ style: [
2577
+ styles8.optionButton,
2578
+ isDark && styles8.optionButtonDark,
2579
+ pageTheme === "high-contrast" && styles8.optionButtonActive,
2580
+ pageTheme === "high-contrast" && { backgroundColor: accentColor }
2581
+ ],
2582
+ children: /* @__PURE__ */ jsx9(
2583
+ Text6,
2584
+ {
2585
+ style: [
2586
+ styles8.optionText,
2587
+ isDark && styles8.optionTextDark,
2588
+ pageTheme === "high-contrast" && styles8.optionTextActive
2589
+ ],
2590
+ children: t.themeContrast
2591
+ }
2592
+ )
2593
+ }
2594
+ )
2595
+ ] })
2596
+ ] }),
2597
+ /* @__PURE__ */ jsxs9(View8, { style: styles8.section, children: [
2598
+ /* @__PURE__ */ jsx9(Text6, { style: [styles8.sectionTitle, isDark && styles8.sectionTitleDark], children: t.pageTransition }),
2599
+ /* @__PURE__ */ jsxs9(View8, { style: styles8.optionRow, children: [
2600
+ /* @__PURE__ */ jsx9(
2601
+ Pressable7,
2602
+ {
2603
+ onPress: () => handleTransition("continuous"),
2604
+ style: [
2605
+ styles8.optionButton,
2606
+ isDark && styles8.optionButtonDark,
2607
+ (!isPaged || isDouble) && styles8.optionButtonActive,
2608
+ (!isPaged || isDouble) && { backgroundColor: accentColor }
2609
+ ],
2610
+ children: /* @__PURE__ */ jsx9(
2611
+ Text6,
2612
+ {
2613
+ style: [
2614
+ styles8.optionText,
2615
+ isDark && styles8.optionTextDark,
2616
+ (!isPaged || isDouble) && styles8.optionTextActive
2617
+ ],
2618
+ children: t.continuous
2619
+ }
2620
+ )
2621
+ }
2622
+ ),
2623
+ /* @__PURE__ */ jsx9(
2624
+ Pressable7,
2625
+ {
2626
+ onPress: () => handleTransition("paged"),
2627
+ style: [
2628
+ styles8.optionButton,
2629
+ isDark && styles8.optionButtonDark,
2630
+ isPaged && styles8.optionButtonActive,
2631
+ isPaged && { backgroundColor: accentColor }
2632
+ ],
2633
+ children: /* @__PURE__ */ jsx9(
2634
+ Text6,
2635
+ {
2636
+ style: [
2637
+ styles8.optionText,
2638
+ isDark && styles8.optionTextDark,
2639
+ isPaged && styles8.optionTextActive
2640
+ ],
2641
+ children: t.pageByPage
2642
+ }
2643
+ )
2644
+ }
2645
+ )
2646
+ ] })
2647
+ ] }),
2648
+ /* @__PURE__ */ jsxs9(View8, { style: styles8.section, children: [
2649
+ /* @__PURE__ */ jsx9(Text6, { style: [styles8.sectionTitle, isDark && styles8.sectionTitleDark], children: t.layout }),
2650
+ /* @__PURE__ */ jsxs9(View8, { style: styles8.optionRow, children: [
2651
+ /* @__PURE__ */ jsx9(
2652
+ Pressable7,
2653
+ {
2654
+ onPress: () => handleLayout("single"),
2655
+ style: [
2656
+ styles8.optionButton,
2657
+ isDark && styles8.optionButtonDark,
2658
+ !isDouble && styles8.optionButtonActive,
2659
+ !isDouble && { backgroundColor: accentColor }
2660
+ ],
2661
+ children: /* @__PURE__ */ jsx9(
2662
+ Text6,
2663
+ {
2664
+ style: [
2665
+ styles8.optionText,
2666
+ isDark && styles8.optionTextDark,
2667
+ !isDouble && styles8.optionTextActive
2668
+ ],
2669
+ children: t.singlePage
2670
+ }
2671
+ )
2672
+ }
2673
+ ),
2674
+ /* @__PURE__ */ jsx9(
2675
+ Pressable7,
2676
+ {
2677
+ onPress: () => handleLayout("double"),
2678
+ style: [
2679
+ styles8.optionButton,
2680
+ isDark && styles8.optionButtonDark,
2681
+ isDouble && styles8.optionButtonActive,
2682
+ isDouble && { backgroundColor: accentColor }
2683
+ ],
2684
+ children: /* @__PURE__ */ jsx9(
2685
+ Text6,
2686
+ {
2687
+ style: [
2688
+ styles8.optionText,
2689
+ isDark && styles8.optionTextDark,
2690
+ isDouble && styles8.optionTextActive
2691
+ ],
2692
+ children: t.doublePage
2693
+ }
2694
+ )
2695
+ }
2696
+ )
2697
+ ] })
2698
+ ] }),
2699
+ /* @__PURE__ */ jsxs9(View8, { style: styles8.section, children: [
2700
+ /* @__PURE__ */ jsx9(Text6, { style: [styles8.sectionTitle, isDark && styles8.sectionTitleDark], children: t.rotate }),
2701
+ /* @__PURE__ */ jsxs9(View8, { style: styles8.optionRow, children: [
2702
+ /* @__PURE__ */ jsx9(
2703
+ Pressable7,
2704
+ {
2705
+ onPress: () => handleRotate("counterclockwise"),
2706
+ style: [styles8.optionButton, isDark && styles8.optionButtonDark],
2707
+ children: /* @__PURE__ */ jsx9(Text6, { style: [styles8.optionText, isDark && styles8.optionTextDark], children: t.counterclockwise })
2708
+ }
2709
+ ),
2710
+ /* @__PURE__ */ jsx9(
2711
+ Pressable7,
2712
+ {
2713
+ onPress: () => handleRotate("clockwise"),
2714
+ style: [styles8.optionButton, isDark && styles8.optionButtonDark],
2715
+ children: /* @__PURE__ */ jsx9(Text6, { style: [styles8.optionText, isDark && styles8.optionTextDark], children: t.clockwise })
2716
+ }
2717
+ )
2718
+ ] })
2719
+ ] }),
2720
+ /* @__PURE__ */ jsxs9(View8, { style: styles8.section, children: [
2721
+ /* @__PURE__ */ jsx9(Text6, { style: [styles8.sectionTitle, isDark && styles8.sectionTitleDark], children: t.zoom }),
2722
+ /* @__PURE__ */ jsxs9(View8, { style: styles8.optionRow, children: [
2723
+ /* @__PURE__ */ jsx9(Pressable7, { onPress: () => handleZoom(-0.1), style: [styles8.optionButton, isDark && styles8.optionButtonDark], children: /* @__PURE__ */ jsx9(IconZoomOut, { size: 16, color: isDark ? "#e5e7eb" : "#111827" }) }),
2724
+ /* @__PURE__ */ jsx9(View8, { style: styles8.zoomValue, children: /* @__PURE__ */ jsxs9(Text6, { style: [styles8.zoomText, isDark && styles8.zoomTextDark], children: [
2725
+ Math.round(zoom * 100),
2726
+ "%"
2727
+ ] }) }),
2728
+ /* @__PURE__ */ jsx9(Pressable7, { onPress: () => handleZoom(0.1), style: [styles8.optionButton, isDark && styles8.optionButtonDark], children: /* @__PURE__ */ jsx9(IconZoomIn, { size: 16, color: isDark ? "#e5e7eb" : "#111827" }) })
2729
+ ] })
2730
+ ] }),
2731
+ /* @__PURE__ */ jsxs9(View8, { style: styles8.section, children: [
2732
+ /* @__PURE__ */ jsx9(Text6, { style: [styles8.sectionTitle, isDark && styles8.sectionTitleDark], children: t.language }),
2733
+ /* @__PURE__ */ jsxs9(View8, { style: styles8.optionRow, children: [
2734
+ /* @__PURE__ */ jsx9(
2735
+ Pressable7,
2736
+ {
2737
+ onPress: () => setDocumentState({ locale: "en" }),
2738
+ style: [
2739
+ styles8.optionButton,
2740
+ isDark && styles8.optionButtonDark,
2741
+ locale === "en" && styles8.optionButtonActive,
2742
+ locale === "en" && { backgroundColor: accentColor }
2743
+ ],
2744
+ children: /* @__PURE__ */ jsx9(
2745
+ Text6,
2746
+ {
2747
+ style: [
2748
+ styles8.optionText,
2749
+ isDark && styles8.optionTextDark,
2750
+ locale === "en" && styles8.optionTextActive
2751
+ ],
2752
+ children: t.english
2753
+ }
2754
+ )
2755
+ }
2756
+ ),
2757
+ /* @__PURE__ */ jsx9(
2758
+ Pressable7,
2759
+ {
2760
+ onPress: () => setDocumentState({ locale: "pt-BR" }),
2761
+ style: [
2762
+ styles8.optionButton,
2763
+ isDark && styles8.optionButtonDark,
2764
+ locale === "pt-BR" && styles8.optionButtonActive,
2765
+ locale === "pt-BR" && { backgroundColor: accentColor }
2766
+ ],
2767
+ children: /* @__PURE__ */ jsx9(
2768
+ Text6,
2769
+ {
2770
+ style: [
2771
+ styles8.optionText,
2772
+ isDark && styles8.optionTextDark,
2773
+ locale === "pt-BR" && styles8.optionTextActive
2774
+ ],
2775
+ children: t.portuguese
2776
+ }
2777
+ )
2778
+ }
2779
+ )
2780
+ ] })
2781
+ ] })
2782
+ ] })
2783
+ ] }) });
2784
+ };
2785
+ var styles8 = StyleSheet8.create({
2786
+ modalRoot: {
2787
+ flex: 1,
2788
+ backgroundColor: "transparent"
2789
+ },
2790
+ backdrop: {
2791
+ ...StyleSheet8.absoluteFillObject,
2792
+ backgroundColor: "rgba(0, 0, 0, 0.45)"
2793
+ },
2794
+ sheet: {
2795
+ position: "absolute",
2796
+ left: 0,
2797
+ right: 0,
2798
+ bottom: 0,
2799
+ paddingHorizontal: 18,
2800
+ paddingBottom: 24,
2801
+ backgroundColor: "#ffffff",
2802
+ borderTopLeftRadius: 24,
2803
+ borderTopRightRadius: 24,
2804
+ borderTopWidth: 1,
2805
+ borderTopColor: "#e5e7eb"
2806
+ },
2807
+ sheetDark: {
2808
+ backgroundColor: "#0f1115",
2809
+ borderTopColor: "#1f2937"
2810
+ },
2811
+ handle: {
2812
+ width: 44,
2813
+ height: 4,
2814
+ borderRadius: 999,
2815
+ backgroundColor: "#cbd5f5",
2816
+ alignSelf: "center",
2817
+ marginTop: 10,
2818
+ marginBottom: 12
2819
+ },
2820
+ handleDark: {
2821
+ backgroundColor: "#374151"
2822
+ },
2823
+ section: {
2824
+ marginBottom: 16
2825
+ },
2826
+ sectionTitle: {
2827
+ fontSize: 12,
2828
+ fontWeight: "800",
2829
+ color: "#111827",
2830
+ marginBottom: 8
2831
+ },
2832
+ sectionTitleDark: {
2833
+ color: "#e5e7eb"
2834
+ },
2835
+ optionRow: {
2836
+ flexDirection: "row",
2837
+ alignItems: "center",
2838
+ flexWrap: "wrap"
2839
+ },
2840
+ optionButton: {
2841
+ paddingHorizontal: 12,
2842
+ paddingVertical: 8,
2843
+ borderRadius: 12,
2844
+ backgroundColor: "#e5e7eb",
2845
+ marginRight: 8,
2846
+ marginBottom: 8
2847
+ },
2848
+ optionButtonDark: {
2849
+ backgroundColor: "#111827"
2850
+ },
2851
+ optionButtonActive: {
2852
+ backgroundColor: "#2563eb"
2853
+ },
2854
+ optionText: {
2855
+ fontSize: 11,
2856
+ fontWeight: "700",
2857
+ color: "#111827"
2858
+ },
2859
+ optionTextDark: {
2860
+ color: "#e5e7eb"
2861
+ },
2862
+ optionTextActive: {
2863
+ color: "#ffffff"
2864
+ },
2865
+ zoomValue: {
2866
+ minWidth: 52,
2867
+ alignItems: "center",
2868
+ justifyContent: "center"
2869
+ },
2870
+ zoomText: {
2871
+ fontSize: 12,
2872
+ fontWeight: "700",
2873
+ color: "#111827"
2874
+ },
2875
+ zoomTextDark: {
2876
+ color: "#e5e7eb"
2877
+ }
2878
+ });
2879
+ var SettingsSheet_default = SettingsSheet;
2880
+ export {
2881
+ AnnotationEditor_default as AnnotationEditor,
2882
+ BottomBar_default as BottomBar,
2883
+ PageRenderer_default as PageRenderer,
2884
+ RightSheet_default as RightSheet,
2885
+ SettingsSheet_default as SettingsSheet,
2886
+ ToolDock_default as ToolDock,
2887
+ Topbar_default as Topbar,
2888
+ Viewer_default as Viewer
2889
+ };
2890
+ //# sourceMappingURL=index.mjs.map