@papyrus-sdk/ui-react 0.2.18 → 0.2.20
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/base.css +89 -48
- package/dist/index.d.mts +4 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +128 -5
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +136 -13
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/base.css
CHANGED
|
@@ -1,45 +1,86 @@
|
|
|
1
1
|
.papyrus-theme {
|
|
2
|
-
--papyrus-bg: #f3f4f6;
|
|
3
|
-
--papyrus-surface: #ffffff;
|
|
4
|
-
--papyrus-surface-2: #f9fafb;
|
|
5
|
-
--papyrus-border: #e5e7eb;
|
|
6
|
-
--papyrus-border-strong: #d1d5db;
|
|
7
|
-
--papyrus-text: #111827;
|
|
8
|
-
--papyrus-text-muted: #6b7280;
|
|
9
|
-
--papyrus-icon: #6b7280;
|
|
10
|
-
--papyrus-focus: #93c5fd;
|
|
11
|
-
--papyrus-canvas: #f3f4f6;
|
|
12
|
-
--papyrus-hover: #e5e7eb;
|
|
13
|
-
--papyrus-popover: #ffffff;
|
|
14
|
-
--papyrus-shadow: rgba(15, 23, 42, 0.08);
|
|
15
|
-
--papyrus-selection-bg: rgba(30, 64, 175, 0.5);
|
|
16
|
-
|
|
2
|
+
--papyrus-bg-fallback: #f3f4f6;
|
|
3
|
+
--papyrus-surface-fallback: #ffffff;
|
|
4
|
+
--papyrus-surface-2-fallback: #f9fafb;
|
|
5
|
+
--papyrus-border-fallback: #e5e7eb;
|
|
6
|
+
--papyrus-border-strong-fallback: #d1d5db;
|
|
7
|
+
--papyrus-text-fallback: #111827;
|
|
8
|
+
--papyrus-text-muted-fallback: #6b7280;
|
|
9
|
+
--papyrus-icon-fallback: #6b7280;
|
|
10
|
+
--papyrus-focus-fallback: #93c5fd;
|
|
11
|
+
--papyrus-canvas-fallback: #f3f4f6;
|
|
12
|
+
--papyrus-hover-fallback: #e5e7eb;
|
|
13
|
+
--papyrus-popover-fallback: #ffffff;
|
|
14
|
+
--papyrus-shadow-fallback: rgba(15, 23, 42, 0.08);
|
|
15
|
+
--papyrus-selection-bg-fallback: rgba(30, 64, 175, 0.5);
|
|
16
|
+
--papyrus-bg-resolved: var(--papyrus-bg, var(--papyrus-bg-fallback));
|
|
17
|
+
--papyrus-surface-resolved: var(
|
|
18
|
+
--papyrus-surface,
|
|
19
|
+
var(--papyrus-surface-fallback)
|
|
20
|
+
);
|
|
21
|
+
--papyrus-surface-2-resolved: var(
|
|
22
|
+
--papyrus-surface-2,
|
|
23
|
+
var(--papyrus-surface-2-fallback)
|
|
24
|
+
);
|
|
25
|
+
--papyrus-border-resolved: var(
|
|
26
|
+
--papyrus-border,
|
|
27
|
+
var(--papyrus-border-fallback)
|
|
28
|
+
);
|
|
29
|
+
--papyrus-border-strong-resolved: var(
|
|
30
|
+
--papyrus-border-strong,
|
|
31
|
+
var(--papyrus-border-strong-fallback)
|
|
32
|
+
);
|
|
33
|
+
--papyrus-text-resolved: var(--papyrus-text, var(--papyrus-text-fallback));
|
|
34
|
+
--papyrus-text-muted-resolved: var(
|
|
35
|
+
--papyrus-text-muted,
|
|
36
|
+
var(--papyrus-text-muted-fallback)
|
|
37
|
+
);
|
|
38
|
+
--papyrus-icon-resolved: var(--papyrus-icon, var(--papyrus-icon-fallback));
|
|
39
|
+
--papyrus-focus-resolved: var(--papyrus-focus, var(--papyrus-focus-fallback));
|
|
40
|
+
--papyrus-canvas-resolved: var(
|
|
41
|
+
--papyrus-canvas,
|
|
42
|
+
var(--papyrus-canvas-fallback)
|
|
43
|
+
);
|
|
44
|
+
--papyrus-hover-resolved: var(--papyrus-hover, var(--papyrus-hover-fallback));
|
|
45
|
+
--papyrus-popover-resolved: var(
|
|
46
|
+
--papyrus-popover,
|
|
47
|
+
var(--papyrus-popover-fallback)
|
|
48
|
+
);
|
|
49
|
+
--papyrus-shadow-resolved: var(
|
|
50
|
+
--papyrus-shadow,
|
|
51
|
+
var(--papyrus-shadow-fallback)
|
|
52
|
+
);
|
|
53
|
+
--papyrus-selection-bg-resolved: var(
|
|
54
|
+
--papyrus-selection-bg,
|
|
55
|
+
var(--papyrus-selection-bg-fallback)
|
|
56
|
+
);
|
|
57
|
+
color: var(--papyrus-text-resolved);
|
|
17
58
|
font-family: system-ui, -apple-system, "Segoe UI", sans-serif;
|
|
18
59
|
}
|
|
19
60
|
|
|
20
61
|
.papyrus-theme[data-papyrus-theme="dark"] {
|
|
21
|
-
--papyrus-bg: #0f1115;
|
|
22
|
-
--papyrus-surface: #1a1a1a;
|
|
23
|
-
--papyrus-surface-2: #222222;
|
|
24
|
-
--papyrus-border: #333333;
|
|
25
|
-
--papyrus-border-strong: #444444;
|
|
26
|
-
--papyrus-text: #f3f4f6;
|
|
27
|
-
--papyrus-text-muted: #9ca3af;
|
|
28
|
-
--papyrus-icon: #9ca3af;
|
|
29
|
-
--papyrus-focus: #2563eb;
|
|
30
|
-
--papyrus-canvas: #121212;
|
|
31
|
-
--papyrus-hover: rgba(255, 255, 255, 0.08);
|
|
32
|
-
--papyrus-popover: #1f1f1f;
|
|
33
|
-
--papyrus-shadow: rgba(0, 0, 0, 0.4);
|
|
34
|
-
--papyrus-selection-bg: rgba(96, 165, 250, 0.5);
|
|
62
|
+
--papyrus-bg-fallback: #0f1115;
|
|
63
|
+
--papyrus-surface-fallback: #1a1a1a;
|
|
64
|
+
--papyrus-surface-2-fallback: #222222;
|
|
65
|
+
--papyrus-border-fallback: #333333;
|
|
66
|
+
--papyrus-border-strong-fallback: #444444;
|
|
67
|
+
--papyrus-text-fallback: #f3f4f6;
|
|
68
|
+
--papyrus-text-muted-fallback: #9ca3af;
|
|
69
|
+
--papyrus-icon-fallback: #9ca3af;
|
|
70
|
+
--papyrus-focus-fallback: #2563eb;
|
|
71
|
+
--papyrus-canvas-fallback: #121212;
|
|
72
|
+
--papyrus-hover-fallback: rgba(255, 255, 255, 0.08);
|
|
73
|
+
--papyrus-popover-fallback: #1f1f1f;
|
|
74
|
+
--papyrus-shadow-fallback: rgba(0, 0, 0, 0.4);
|
|
75
|
+
--papyrus-selection-bg-fallback: rgba(96, 165, 250, 0.5);
|
|
35
76
|
}
|
|
36
77
|
|
|
37
78
|
.papyrus-topbar,
|
|
38
79
|
.papyrus-sidebar-left,
|
|
39
80
|
.papyrus-sidebar-right {
|
|
40
|
-
background: var(--papyrus-surface) !important;
|
|
41
|
-
border-color: var(--papyrus-border) !important;
|
|
42
|
-
color: var(--papyrus-text) !important;
|
|
81
|
+
background: var(--papyrus-surface-resolved) !important;
|
|
82
|
+
border-color: var(--papyrus-border-resolved) !important;
|
|
83
|
+
color: var(--papyrus-text-resolved) !important;
|
|
43
84
|
box-sizing: border-box;
|
|
44
85
|
font-size: 13px;
|
|
45
86
|
line-height: 1.4;
|
|
@@ -99,33 +140,33 @@
|
|
|
99
140
|
}
|
|
100
141
|
|
|
101
142
|
.papyrus-viewer {
|
|
102
|
-
background: var(--papyrus-canvas) !important;
|
|
143
|
+
background: var(--papyrus-canvas-resolved) !important;
|
|
103
144
|
box-sizing: border-box;
|
|
104
145
|
flex: 1 1 auto;
|
|
105
146
|
overflow-x: hidden;
|
|
106
147
|
overflow-y: scroll;
|
|
107
148
|
scrollbar-gutter: stable;
|
|
108
|
-
color: var(--papyrus-text);
|
|
149
|
+
color: var(--papyrus-text-resolved);
|
|
109
150
|
}
|
|
110
151
|
|
|
111
152
|
.papyrus-control,
|
|
112
153
|
.papyrus-input,
|
|
113
154
|
.papyrus-popover {
|
|
114
|
-
background: var(--papyrus-surface-2) !important;
|
|
115
|
-
border-color: var(--papyrus-border) !important;
|
|
116
|
-
color: var(--papyrus-text) !important;
|
|
155
|
+
background: var(--papyrus-surface-2-resolved) !important;
|
|
156
|
+
border-color: var(--papyrus-border-resolved) !important;
|
|
157
|
+
color: var(--papyrus-text-resolved) !important;
|
|
117
158
|
}
|
|
118
159
|
|
|
119
160
|
.papyrus-popover {
|
|
120
|
-
background: var(--papyrus-popover) !important;
|
|
121
|
-
box-shadow: 0 20px 40px var(--papyrus-shadow);
|
|
161
|
+
background: var(--papyrus-popover-resolved) !important;
|
|
162
|
+
box-shadow: 0 20px 40px var(--papyrus-shadow-resolved);
|
|
122
163
|
}
|
|
123
164
|
|
|
124
165
|
.papyrus-topbar button,
|
|
125
166
|
.papyrus-sidebar-left button,
|
|
126
167
|
.papyrus-sidebar-right button {
|
|
127
|
-
background: var(--papyrus-surface-2);
|
|
128
|
-
border: 1px solid var(--papyrus-border);
|
|
168
|
+
background: var(--papyrus-surface-2-resolved);
|
|
169
|
+
border: 1px solid var(--papyrus-border-resolved);
|
|
129
170
|
border-radius: 8px;
|
|
130
171
|
color: inherit;
|
|
131
172
|
cursor: pointer;
|
|
@@ -146,11 +187,11 @@
|
|
|
146
187
|
.papyrus-topbar select,
|
|
147
188
|
.papyrus-sidebar-left select,
|
|
148
189
|
.papyrus-sidebar-right select {
|
|
149
|
-
background: var(--papyrus-surface);
|
|
150
|
-
border: 1px solid var(--papyrus-border);
|
|
190
|
+
background: var(--papyrus-surface-resolved);
|
|
191
|
+
border: 1px solid var(--papyrus-border-resolved);
|
|
151
192
|
border-radius: 6px;
|
|
152
193
|
box-sizing: border-box;
|
|
153
|
-
color: var(--papyrus-text);
|
|
194
|
+
color: var(--papyrus-text-resolved);
|
|
154
195
|
font: inherit;
|
|
155
196
|
padding: 6px 8px;
|
|
156
197
|
}
|
|
@@ -158,8 +199,8 @@
|
|
|
158
199
|
.papyrus-topbar button:hover,
|
|
159
200
|
.papyrus-sidebar-left button:hover,
|
|
160
201
|
.papyrus-sidebar-right button:hover {
|
|
161
|
-
background: var(--papyrus-hover);
|
|
162
|
-
border-color: var(--papyrus-border-strong);
|
|
202
|
+
background: var(--papyrus-hover-resolved);
|
|
203
|
+
border-color: var(--papyrus-border-strong-resolved);
|
|
163
204
|
}
|
|
164
205
|
|
|
165
206
|
.papyrus-topbar svg,
|
|
@@ -174,7 +215,7 @@
|
|
|
174
215
|
.papyrus-topbar select:focus,
|
|
175
216
|
.papyrus-sidebar-left select:focus,
|
|
176
217
|
.papyrus-sidebar-right select:focus {
|
|
177
|
-
outline: 2px solid var(--papyrus-focus);
|
|
218
|
+
outline: 2px solid var(--papyrus-focus-resolved);
|
|
178
219
|
outline-offset: 1px;
|
|
179
220
|
}
|
|
180
221
|
|
|
@@ -190,7 +231,7 @@
|
|
|
190
231
|
}
|
|
191
232
|
|
|
192
233
|
.papyrus-viewer .textLayer ::selection {
|
|
193
|
-
background: var(--papyrus-selection-bg);
|
|
234
|
+
background: var(--papyrus-selection-bg-resolved);
|
|
194
235
|
}
|
|
195
236
|
|
|
196
237
|
.papyrus-viewer .textLayer {
|
package/dist/index.d.mts
CHANGED
|
@@ -6,6 +6,7 @@ interface TopbarProps {
|
|
|
6
6
|
showBrand?: boolean;
|
|
7
7
|
brand?: React.ReactNode;
|
|
8
8
|
title?: React.ReactNode;
|
|
9
|
+
style?: React.CSSProperties;
|
|
9
10
|
showSidebarLeftToggle?: boolean;
|
|
10
11
|
showPageControls?: boolean;
|
|
11
12
|
showZoomControls?: boolean;
|
|
@@ -18,16 +19,19 @@ declare const Topbar: React.FC<TopbarProps>;
|
|
|
18
19
|
|
|
19
20
|
interface SidebarLeftProps {
|
|
20
21
|
engine: DocumentEngine;
|
|
22
|
+
style?: React.CSSProperties;
|
|
21
23
|
}
|
|
22
24
|
declare const SidebarLeft: React.FC<SidebarLeftProps>;
|
|
23
25
|
|
|
24
26
|
interface SidebarRightProps {
|
|
25
27
|
engine: DocumentEngine;
|
|
28
|
+
style?: React.CSSProperties;
|
|
26
29
|
}
|
|
27
30
|
declare const SidebarRight: React.FC<SidebarRightProps>;
|
|
28
31
|
|
|
29
32
|
interface ViewerProps {
|
|
30
33
|
engine: DocumentEngine;
|
|
34
|
+
style?: React.CSSProperties;
|
|
31
35
|
}
|
|
32
36
|
declare const Viewer: React.FC<ViewerProps>;
|
|
33
37
|
|
package/dist/index.d.ts
CHANGED
|
@@ -6,6 +6,7 @@ interface TopbarProps {
|
|
|
6
6
|
showBrand?: boolean;
|
|
7
7
|
brand?: React.ReactNode;
|
|
8
8
|
title?: React.ReactNode;
|
|
9
|
+
style?: React.CSSProperties;
|
|
9
10
|
showSidebarLeftToggle?: boolean;
|
|
10
11
|
showPageControls?: boolean;
|
|
11
12
|
showZoomControls?: boolean;
|
|
@@ -18,16 +19,19 @@ declare const Topbar: React.FC<TopbarProps>;
|
|
|
18
19
|
|
|
19
20
|
interface SidebarLeftProps {
|
|
20
21
|
engine: DocumentEngine;
|
|
22
|
+
style?: React.CSSProperties;
|
|
21
23
|
}
|
|
22
24
|
declare const SidebarLeft: React.FC<SidebarLeftProps>;
|
|
23
25
|
|
|
24
26
|
interface SidebarRightProps {
|
|
25
27
|
engine: DocumentEngine;
|
|
28
|
+
style?: React.CSSProperties;
|
|
26
29
|
}
|
|
27
30
|
declare const SidebarRight: React.FC<SidebarRightProps>;
|
|
28
31
|
|
|
29
32
|
interface ViewerProps {
|
|
30
33
|
engine: DocumentEngine;
|
|
34
|
+
style?: React.CSSProperties;
|
|
31
35
|
}
|
|
32
36
|
declare const Viewer: React.FC<ViewerProps>;
|
|
33
37
|
|
package/dist/index.js
CHANGED
|
@@ -37,6 +37,7 @@ var Topbar = ({
|
|
|
37
37
|
showBrand = false,
|
|
38
38
|
brand,
|
|
39
39
|
title,
|
|
40
|
+
style,
|
|
40
41
|
showSidebarLeftToggle = true,
|
|
41
42
|
showPageControls = true,
|
|
42
43
|
showZoomControls = true,
|
|
@@ -45,6 +46,7 @@ var Topbar = ({
|
|
|
45
46
|
showUpload = true,
|
|
46
47
|
showSearch = true
|
|
47
48
|
}) => {
|
|
49
|
+
const viewerState = (0, import_core.useViewerStore)();
|
|
48
50
|
const {
|
|
49
51
|
currentPage,
|
|
50
52
|
pageCount,
|
|
@@ -57,13 +59,15 @@ var Topbar = ({
|
|
|
57
59
|
toggleSidebarLeft,
|
|
58
60
|
toggleSidebarRight,
|
|
59
61
|
triggerScrollToPage
|
|
60
|
-
} =
|
|
62
|
+
} = viewerState;
|
|
63
|
+
const mobileTopbarVisible = viewerState.mobileTopbarVisible ?? true;
|
|
61
64
|
const fileInputRef = (0, import_react.useRef)(null);
|
|
62
65
|
const zoomTimerRef = (0, import_react.useRef)(null);
|
|
63
66
|
const pendingZoomRef = (0, import_react.useRef)(null);
|
|
64
67
|
const [pageInput, setPageInput] = (0, import_react.useState)(currentPage.toString());
|
|
65
68
|
const [showPageThemes, setShowPageThemes] = (0, import_react.useState)(false);
|
|
66
69
|
const [showMobileMenu, setShowMobileMenu] = (0, import_react.useState)(false);
|
|
70
|
+
const [isMobileViewport, setIsMobileViewport] = (0, import_react.useState)(false);
|
|
67
71
|
const pageDigits = Math.max(2, String(pageCount || 1).length);
|
|
68
72
|
const isDark = uiTheme === "dark";
|
|
69
73
|
const canUseDOM = typeof document !== "undefined";
|
|
@@ -80,6 +84,18 @@ var Topbar = ({
|
|
|
80
84
|
(0, import_react.useEffect)(() => {
|
|
81
85
|
if (!hasMobileMenu) setShowMobileMenu(false);
|
|
82
86
|
}, [hasMobileMenu]);
|
|
87
|
+
(0, import_react.useEffect)(() => {
|
|
88
|
+
if (!canUseDOM || typeof window.matchMedia !== "function") return;
|
|
89
|
+
const mediaQuery = window.matchMedia("(max-width: 639px)");
|
|
90
|
+
const updateViewport = () => setIsMobileViewport(mediaQuery.matches);
|
|
91
|
+
updateViewport();
|
|
92
|
+
if (typeof mediaQuery.addEventListener === "function") {
|
|
93
|
+
mediaQuery.addEventListener("change", updateViewport);
|
|
94
|
+
return () => mediaQuery.removeEventListener("change", updateViewport);
|
|
95
|
+
}
|
|
96
|
+
mediaQuery.addListener(updateViewport);
|
|
97
|
+
return () => mediaQuery.removeListener(updateViewport);
|
|
98
|
+
}, [canUseDOM]);
|
|
83
99
|
(0, import_react.useEffect)(() => {
|
|
84
100
|
if (!showMobileMenu || !canUseDOM) return;
|
|
85
101
|
const previousOverflow = document.body.style.overflow;
|
|
@@ -93,6 +109,30 @@ var Topbar = ({
|
|
|
93
109
|
window.removeEventListener("keydown", handleKeyDown);
|
|
94
110
|
};
|
|
95
111
|
}, [showMobileMenu, canUseDOM]);
|
|
112
|
+
const topbarStyle = (0, import_react.useMemo)(() => {
|
|
113
|
+
const mergedStyle = { ...style ?? {} };
|
|
114
|
+
if (!isMobileViewport) {
|
|
115
|
+
mergedStyle.transition = "height 180ms ease, opacity 160ms ease, padding 180ms ease, border-width 180ms ease";
|
|
116
|
+
return mergedStyle;
|
|
117
|
+
}
|
|
118
|
+
mergedStyle.transition = "height 180ms ease, opacity 160ms ease, padding 180ms ease, border-width 180ms ease";
|
|
119
|
+
mergedStyle.overflow = "hidden";
|
|
120
|
+
if (!mobileTopbarVisible) {
|
|
121
|
+
mergedStyle.height = 0;
|
|
122
|
+
mergedStyle.minHeight = 0;
|
|
123
|
+
mergedStyle.paddingTop = 0;
|
|
124
|
+
mergedStyle.paddingBottom = 0;
|
|
125
|
+
mergedStyle.borderBottomWidth = 0;
|
|
126
|
+
mergedStyle.opacity = 0;
|
|
127
|
+
mergedStyle.pointerEvents = "none";
|
|
128
|
+
return mergedStyle;
|
|
129
|
+
}
|
|
130
|
+
mergedStyle.height = 56;
|
|
131
|
+
mergedStyle.minHeight = 56;
|
|
132
|
+
mergedStyle.opacity = 1;
|
|
133
|
+
mergedStyle.pointerEvents = "auto";
|
|
134
|
+
return mergedStyle;
|
|
135
|
+
}, [isMobileViewport, mobileTopbarVisible, style]);
|
|
96
136
|
const handleZoom = (delta) => {
|
|
97
137
|
const baseZoom = pendingZoomRef.current ?? zoom;
|
|
98
138
|
const nextZoom = Math.max(0.2, Math.min(5, baseZoom + delta));
|
|
@@ -383,6 +423,7 @@ var Topbar = ({
|
|
|
383
423
|
{
|
|
384
424
|
"data-papyrus-theme": uiTheme,
|
|
385
425
|
className: `papyrus-topbar papyrus-theme relative h-14 border-b flex items-center px-3 sm:px-4 z-50 transition-colors duration-200 ${isDark ? "bg-[#1a1a1a] border-[#333] text-white" : "bg-white border-gray-200 text-gray-800"}`,
|
|
426
|
+
style: topbarStyle,
|
|
386
427
|
children: [
|
|
387
428
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex items-center gap-2 min-w-0 z-10", children: [
|
|
388
429
|
showSidebarLeftToggle && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
@@ -915,7 +956,7 @@ var OutlineNode = ({ item, engine, isDark, accentColor, depth = 0 }) => {
|
|
|
915
956
|
)) })
|
|
916
957
|
] });
|
|
917
958
|
};
|
|
918
|
-
var SidebarLeft = ({ engine }) => {
|
|
959
|
+
var SidebarLeft = ({ engine, style }) => {
|
|
919
960
|
const {
|
|
920
961
|
pageCount,
|
|
921
962
|
currentPage,
|
|
@@ -937,6 +978,7 @@ var SidebarLeft = ({ engine }) => {
|
|
|
937
978
|
{
|
|
938
979
|
"data-papyrus-theme": uiTheme,
|
|
939
980
|
className: `papyrus-sidebar-left papyrus-theme absolute left-0 top-0 bottom-0 z-[120] w-[85vw] max-w-72 border-r flex flex-col h-full overflow-hidden transition-colors duration-200 ${isDark ? "bg-[#2a2a2a] border-[#3a3a3a]" : "bg-[#fcfcfc] border-gray-200"}`,
|
|
981
|
+
style,
|
|
940
982
|
children: [
|
|
941
983
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
942
984
|
"div",
|
|
@@ -1077,7 +1119,7 @@ var withAlpha2 = (hex, alpha) => {
|
|
|
1077
1119
|
const b = parseInt(value.slice(4, 6), 16);
|
|
1078
1120
|
return `rgba(${r}, ${g}, ${b}, ${alpha})`;
|
|
1079
1121
|
};
|
|
1080
|
-
var SidebarRight = ({ engine }) => {
|
|
1122
|
+
var SidebarRight = ({ engine, style }) => {
|
|
1081
1123
|
const {
|
|
1082
1124
|
sidebarRightOpen,
|
|
1083
1125
|
sidebarRightTab,
|
|
@@ -1114,6 +1156,7 @@ var SidebarRight = ({ engine }) => {
|
|
|
1114
1156
|
{
|
|
1115
1157
|
"data-papyrus-theme": uiTheme,
|
|
1116
1158
|
className: `papyrus-sidebar-right papyrus-theme absolute right-0 top-0 bottom-0 z-[120] w-[88vw] max-w-80 border-l flex flex-col h-full transition-colors duration-200 shadow-2xl ${isDark ? "bg-[#1a1a1a] border-[#333]" : "bg-white border-gray-200"}`,
|
|
1159
|
+
style,
|
|
1117
1160
|
children: [
|
|
1118
1161
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
1119
1162
|
"div",
|
|
@@ -2106,7 +2149,11 @@ var MIN_ZOOM = 0.2;
|
|
|
2106
2149
|
var MAX_ZOOM = 5;
|
|
2107
2150
|
var WIDTH_SNAP_PX = 4;
|
|
2108
2151
|
var WIDTH_HYSTERESIS_PX = 6;
|
|
2109
|
-
var
|
|
2152
|
+
var MOBILE_HEADER_HIDE_DELTA_PX = 28;
|
|
2153
|
+
var MOBILE_HEADER_SHOW_DELTA_PX = 16;
|
|
2154
|
+
var MOBILE_HEADER_TOP_RESET_PX = 12;
|
|
2155
|
+
var Viewer = ({ engine, style }) => {
|
|
2156
|
+
const viewerState = (0, import_core5.useViewerStore)();
|
|
2110
2157
|
const {
|
|
2111
2158
|
pageCount,
|
|
2112
2159
|
currentPage,
|
|
@@ -2119,7 +2166,8 @@ var Viewer = ({ engine }) => {
|
|
|
2119
2166
|
annotationColor,
|
|
2120
2167
|
setAnnotationColor,
|
|
2121
2168
|
toolDockOpen
|
|
2122
|
-
} =
|
|
2169
|
+
} = viewerState;
|
|
2170
|
+
const mobileTopbarVisible = viewerState.mobileTopbarVisible ?? true;
|
|
2123
2171
|
const isDark = uiTheme === "dark";
|
|
2124
2172
|
const viewerRef = (0, import_react5.useRef)(null);
|
|
2125
2173
|
const colorPickerRef = (0, import_react5.useRef)(null);
|
|
@@ -2129,6 +2177,11 @@ var Viewer = ({ engine }) => {
|
|
|
2129
2177
|
const jumpRef = (0, import_react5.useRef)(false);
|
|
2130
2178
|
const jumpTimerRef = (0, import_react5.useRef)(null);
|
|
2131
2179
|
const lastWidthRef = (0, import_react5.useRef)(null);
|
|
2180
|
+
const lastScrollTopRef = (0, import_react5.useRef)(0);
|
|
2181
|
+
const scrollDownAccumulatorRef = (0, import_react5.useRef)(0);
|
|
2182
|
+
const scrollUpAccumulatorRef = (0, import_react5.useRef)(0);
|
|
2183
|
+
const previousCurrentPageRef = (0, import_react5.useRef)(currentPage);
|
|
2184
|
+
const mobileTopbarVisibleRef = (0, import_react5.useRef)(mobileTopbarVisible);
|
|
2132
2185
|
const pinchRef = (0, import_react5.useRef)({
|
|
2133
2186
|
active: false,
|
|
2134
2187
|
startDistance: 0,
|
|
@@ -2141,6 +2194,7 @@ var Viewer = ({ engine }) => {
|
|
|
2141
2194
|
const [pageSizes, setPageSizes] = (0, import_react5.useState)({});
|
|
2142
2195
|
const [colorPickerOpen, setColorPickerOpen] = (0, import_react5.useState)(false);
|
|
2143
2196
|
const isCompact = availableWidth !== null && availableWidth < 820;
|
|
2197
|
+
const isMobileViewport = availableWidth !== null && availableWidth < 640;
|
|
2144
2198
|
const paddingY = isCompact ? "py-10" : "py-16";
|
|
2145
2199
|
const toolDockPosition = isCompact ? "bottom-4" : "bottom-8";
|
|
2146
2200
|
const colorPalette = [
|
|
@@ -2153,6 +2207,13 @@ var Viewer = ({ engine }) => {
|
|
|
2153
2207
|
"#8b5cf6",
|
|
2154
2208
|
"#111827"
|
|
2155
2209
|
];
|
|
2210
|
+
const setMobileTopbarVisibility = (visible) => {
|
|
2211
|
+
if (mobileTopbarVisibleRef.current === visible) return;
|
|
2212
|
+
mobileTopbarVisibleRef.current = visible;
|
|
2213
|
+
setDocumentState({
|
|
2214
|
+
mobileTopbarVisible: visible
|
|
2215
|
+
});
|
|
2216
|
+
};
|
|
2156
2217
|
(0, import_react5.useEffect)(() => {
|
|
2157
2218
|
if (!colorPickerOpen) return;
|
|
2158
2219
|
const handleClick = (event) => {
|
|
@@ -2167,6 +2228,9 @@ var Viewer = ({ engine }) => {
|
|
|
2167
2228
|
(0, import_react5.useEffect)(() => {
|
|
2168
2229
|
if (!toolDockOpen && colorPickerOpen) setColorPickerOpen(false);
|
|
2169
2230
|
}, [toolDockOpen, colorPickerOpen]);
|
|
2231
|
+
(0, import_react5.useEffect)(() => {
|
|
2232
|
+
mobileTopbarVisibleRef.current = mobileTopbarVisible;
|
|
2233
|
+
}, [mobileTopbarVisible]);
|
|
2170
2234
|
(0, import_react5.useEffect)(
|
|
2171
2235
|
() => () => {
|
|
2172
2236
|
if (pinchRef.current.rafId != null) {
|
|
@@ -2218,6 +2282,64 @@ var Viewer = ({ engine }) => {
|
|
|
2218
2282
|
observer.disconnect();
|
|
2219
2283
|
};
|
|
2220
2284
|
}, []);
|
|
2285
|
+
(0, import_react5.useEffect)(() => {
|
|
2286
|
+
const root = viewerRef.current;
|
|
2287
|
+
if (!root) return;
|
|
2288
|
+
if (!isMobileViewport) {
|
|
2289
|
+
lastScrollTopRef.current = root.scrollTop;
|
|
2290
|
+
scrollDownAccumulatorRef.current = 0;
|
|
2291
|
+
scrollUpAccumulatorRef.current = 0;
|
|
2292
|
+
setMobileTopbarVisibility(true);
|
|
2293
|
+
return;
|
|
2294
|
+
}
|
|
2295
|
+
lastScrollTopRef.current = root.scrollTop;
|
|
2296
|
+
scrollDownAccumulatorRef.current = 0;
|
|
2297
|
+
scrollUpAccumulatorRef.current = 0;
|
|
2298
|
+
const handleScroll = () => {
|
|
2299
|
+
const nextScrollTop = root.scrollTop;
|
|
2300
|
+
const delta = nextScrollTop - lastScrollTopRef.current;
|
|
2301
|
+
lastScrollTopRef.current = nextScrollTop;
|
|
2302
|
+
if (Math.abs(delta) < 1) return;
|
|
2303
|
+
if (nextScrollTop <= MOBILE_HEADER_TOP_RESET_PX) {
|
|
2304
|
+
scrollDownAccumulatorRef.current = 0;
|
|
2305
|
+
scrollUpAccumulatorRef.current = 0;
|
|
2306
|
+
setMobileTopbarVisibility(true);
|
|
2307
|
+
return;
|
|
2308
|
+
}
|
|
2309
|
+
if (delta > 0) {
|
|
2310
|
+
scrollDownAccumulatorRef.current += delta;
|
|
2311
|
+
scrollUpAccumulatorRef.current = 0;
|
|
2312
|
+
} else {
|
|
2313
|
+
scrollUpAccumulatorRef.current += -delta;
|
|
2314
|
+
scrollDownAccumulatorRef.current = 0;
|
|
2315
|
+
}
|
|
2316
|
+
if (scrollDownAccumulatorRef.current >= MOBILE_HEADER_HIDE_DELTA_PX && mobileTopbarVisibleRef.current) {
|
|
2317
|
+
scrollDownAccumulatorRef.current = 0;
|
|
2318
|
+
scrollUpAccumulatorRef.current = 0;
|
|
2319
|
+
setMobileTopbarVisibility(false);
|
|
2320
|
+
return;
|
|
2321
|
+
}
|
|
2322
|
+
if (scrollUpAccumulatorRef.current >= MOBILE_HEADER_SHOW_DELTA_PX && !mobileTopbarVisibleRef.current) {
|
|
2323
|
+
scrollDownAccumulatorRef.current = 0;
|
|
2324
|
+
scrollUpAccumulatorRef.current = 0;
|
|
2325
|
+
setMobileTopbarVisibility(true);
|
|
2326
|
+
}
|
|
2327
|
+
};
|
|
2328
|
+
root.addEventListener("scroll", handleScroll, { passive: true });
|
|
2329
|
+
return () => {
|
|
2330
|
+
root.removeEventListener("scroll", handleScroll);
|
|
2331
|
+
};
|
|
2332
|
+
}, [isMobileViewport, setDocumentState]);
|
|
2333
|
+
(0, import_react5.useEffect)(() => {
|
|
2334
|
+
const previousPage = previousCurrentPageRef.current;
|
|
2335
|
+
previousCurrentPageRef.current = currentPage;
|
|
2336
|
+
if (!isMobileViewport) return;
|
|
2337
|
+
if (currentPage < previousPage && !mobileTopbarVisibleRef.current) {
|
|
2338
|
+
scrollDownAccumulatorRef.current = 0;
|
|
2339
|
+
scrollUpAccumulatorRef.current = 0;
|
|
2340
|
+
setMobileTopbarVisibility(true);
|
|
2341
|
+
}
|
|
2342
|
+
}, [currentPage, isMobileViewport, setDocumentState]);
|
|
2221
2343
|
(0, import_react5.useEffect)(() => {
|
|
2222
2344
|
let active = true;
|
|
2223
2345
|
if (!pageCount) return;
|
|
@@ -2449,6 +2571,7 @@ var Viewer = ({ engine }) => {
|
|
|
2449
2571
|
onTouchEnd: handleTouchEnd,
|
|
2450
2572
|
onTouchCancel: handleTouchEnd,
|
|
2451
2573
|
className: `papyrus-viewer papyrus-theme min-w-0 w-full flex-1 overflow-y-scroll overflow-x-hidden flex flex-col items-center ${paddingY} relative custom-scrollbar scroll-smooth ${isDark ? "bg-[#121212]" : "bg-[#e9ecef]"}`,
|
|
2574
|
+
style,
|
|
2452
2575
|
children: [
|
|
2453
2576
|
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "flex flex-col items-center gap-6 w-full min-w-0", children: pages.map((idx) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
2454
2577
|
"div",
|