@papyrus-sdk/ui-react 0.2.21 → 0.2.22
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/LICENSE +21 -0
- package/base.css +2 -2
- package/dist/index.js +86 -23
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +86 -23
- package/dist/index.mjs.map +1 -1
- package/package.json +5 -5
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Papyrus Contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/base.css
CHANGED
|
@@ -100,7 +100,7 @@
|
|
|
100
100
|
display: none;
|
|
101
101
|
}
|
|
102
102
|
|
|
103
|
-
@media (min-width: 640px) {
|
|
103
|
+
@media (min-width: 640px) and (min-height: 501px) {
|
|
104
104
|
.papyrus-topbar .sm\:inline {
|
|
105
105
|
display: inline !important;
|
|
106
106
|
}
|
|
@@ -122,7 +122,7 @@
|
|
|
122
122
|
}
|
|
123
123
|
}
|
|
124
124
|
|
|
125
|
-
@media (max-width: 720px) {
|
|
125
|
+
@media (max-width: 720px), (orientation: landscape) and (max-height: 500px) {
|
|
126
126
|
.papyrus-topbar {
|
|
127
127
|
flex-wrap: wrap;
|
|
128
128
|
height: auto;
|
package/dist/index.js
CHANGED
|
@@ -32,6 +32,8 @@ var import_react = require("react");
|
|
|
32
32
|
var import_react_dom = require("react-dom");
|
|
33
33
|
var import_core = require("@papyrus-sdk/core");
|
|
34
34
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
35
|
+
var MOBILE_LANDSCAPE_MAX_HEIGHT_PX = 500;
|
|
36
|
+
var MOBILE_VIEWPORT_QUERY = `(max-width: 639px), (orientation: landscape) and (max-height: ${MOBILE_LANDSCAPE_MAX_HEIGHT_PX}px)`;
|
|
35
37
|
var Topbar = ({
|
|
36
38
|
engine,
|
|
37
39
|
showBrand = false,
|
|
@@ -86,7 +88,7 @@ var Topbar = ({
|
|
|
86
88
|
}, [hasMobileMenu]);
|
|
87
89
|
(0, import_react.useEffect)(() => {
|
|
88
90
|
if (!canUseDOM || typeof window.matchMedia !== "function") return;
|
|
89
|
-
const mediaQuery = window.matchMedia(
|
|
91
|
+
const mediaQuery = window.matchMedia(MOBILE_VIEWPORT_QUERY);
|
|
90
92
|
const updateViewport = () => setIsMobileViewport(mediaQuery.matches);
|
|
91
93
|
updateViewport();
|
|
92
94
|
if (typeof mediaQuery.addEventListener === "function") {
|
|
@@ -1797,8 +1799,12 @@ var PageRenderer = ({
|
|
|
1797
1799
|
activeSearchIndex,
|
|
1798
1800
|
textLayerVersion
|
|
1799
1801
|
]);
|
|
1800
|
-
const
|
|
1801
|
-
const
|
|
1802
|
+
const getTouchPoint = (event) => {
|
|
1803
|
+
const touch = event.touches[0] ?? event.changedTouches[0];
|
|
1804
|
+
if (!touch) return null;
|
|
1805
|
+
return { x: touch.clientX, y: touch.clientY };
|
|
1806
|
+
};
|
|
1807
|
+
const handlePointerDown = (clientX, clientY, target) => {
|
|
1802
1808
|
const clickedInsideAnnotation = Boolean(
|
|
1803
1809
|
target?.closest("[data-papyrus-annotation-id]")
|
|
1804
1810
|
);
|
|
@@ -1812,8 +1818,8 @@ var PageRenderer = ({
|
|
|
1812
1818
|
if (activeTool === "ink") {
|
|
1813
1819
|
const rect2 = containerRef.current?.getBoundingClientRect();
|
|
1814
1820
|
if (!rect2) return;
|
|
1815
|
-
const x2 = (
|
|
1816
|
-
const y2 = (
|
|
1821
|
+
const x2 = (clientX - rect2.left) / rect2.width;
|
|
1822
|
+
const y2 = (clientY - rect2.top) / rect2.height;
|
|
1817
1823
|
setIsInkDrawing(true);
|
|
1818
1824
|
setInkPoints([{ x: x2, y: y2 }]);
|
|
1819
1825
|
return;
|
|
@@ -1822,25 +1828,25 @@ var PageRenderer = ({
|
|
|
1822
1828
|
const rect = containerRef.current?.getBoundingClientRect();
|
|
1823
1829
|
if (!rect) return;
|
|
1824
1830
|
setIsDragging(true);
|
|
1825
|
-
const x =
|
|
1826
|
-
const y =
|
|
1831
|
+
const x = clientX - rect.left;
|
|
1832
|
+
const y = clientY - rect.top;
|
|
1827
1833
|
setStartPos({ x, y });
|
|
1828
1834
|
setCurrentRect({ x, y, w: 0, h: 0 });
|
|
1829
1835
|
};
|
|
1830
|
-
const
|
|
1836
|
+
const handlePointerMove = (clientX, clientY) => {
|
|
1831
1837
|
if (isInkDrawing) {
|
|
1832
1838
|
const rect2 = containerRef.current?.getBoundingClientRect();
|
|
1833
1839
|
if (!rect2) return;
|
|
1834
|
-
const x = (
|
|
1835
|
-
const y = (
|
|
1840
|
+
const x = (clientX - rect2.left) / rect2.width;
|
|
1841
|
+
const y = (clientY - rect2.top) / rect2.height;
|
|
1836
1842
|
setInkPoints((prev) => [...prev, { x, y }]);
|
|
1837
1843
|
return;
|
|
1838
1844
|
}
|
|
1839
1845
|
if (!isDragging) return;
|
|
1840
1846
|
const rect = containerRef.current?.getBoundingClientRect();
|
|
1841
1847
|
if (!rect) return;
|
|
1842
|
-
const currentX =
|
|
1843
|
-
const currentY =
|
|
1848
|
+
const currentX = clientX - rect.left;
|
|
1849
|
+
const currentY = clientY - rect.top;
|
|
1844
1850
|
setCurrentRect({
|
|
1845
1851
|
x: Math.min(startPos.x, currentX),
|
|
1846
1852
|
y: Math.min(startPos.y, currentY),
|
|
@@ -1848,7 +1854,7 @@ var PageRenderer = ({
|
|
|
1848
1854
|
h: Math.abs(currentY - startPos.y)
|
|
1849
1855
|
});
|
|
1850
1856
|
};
|
|
1851
|
-
const
|
|
1857
|
+
const handlePointerUp = () => {
|
|
1852
1858
|
if (isInkDrawing) {
|
|
1853
1859
|
setIsInkDrawing(false);
|
|
1854
1860
|
if (inkPoints.length > 1) {
|
|
@@ -2013,6 +2019,37 @@ var PageRenderer = ({
|
|
|
2013
2019
|
}
|
|
2014
2020
|
}
|
|
2015
2021
|
};
|
|
2022
|
+
const handleMouseDown = (e) => {
|
|
2023
|
+
handlePointerDown(e.clientX, e.clientY, e.target);
|
|
2024
|
+
};
|
|
2025
|
+
const handleMouseMove = (e) => {
|
|
2026
|
+
handlePointerMove(e.clientX, e.clientY);
|
|
2027
|
+
};
|
|
2028
|
+
const handleMouseUp = () => {
|
|
2029
|
+
handlePointerUp();
|
|
2030
|
+
};
|
|
2031
|
+
const handleTouchStart = (event) => {
|
|
2032
|
+
if (event.touches.length > 1) return;
|
|
2033
|
+
const point = getTouchPoint(event);
|
|
2034
|
+
if (!point) return;
|
|
2035
|
+
handlePointerDown(point.x, point.y, event.target);
|
|
2036
|
+
if ((activeTool === "ink" || !canSelectText) && event.cancelable) {
|
|
2037
|
+
event.preventDefault();
|
|
2038
|
+
}
|
|
2039
|
+
};
|
|
2040
|
+
const handleTouchMove = (event) => {
|
|
2041
|
+
if (event.touches.length > 1) return;
|
|
2042
|
+
const point = getTouchPoint(event);
|
|
2043
|
+
if (!point) return;
|
|
2044
|
+
handlePointerMove(point.x, point.y);
|
|
2045
|
+
if ((isInkDrawing || isDragging) && event.cancelable) {
|
|
2046
|
+
event.preventDefault();
|
|
2047
|
+
}
|
|
2048
|
+
};
|
|
2049
|
+
const handleTouchEnd = (event) => {
|
|
2050
|
+
if (event.touches.length > 0) return;
|
|
2051
|
+
handlePointerUp();
|
|
2052
|
+
};
|
|
2016
2053
|
const getPageFilter = () => {
|
|
2017
2054
|
switch (pageTheme) {
|
|
2018
2055
|
case "sepia":
|
|
@@ -2030,10 +2067,18 @@ var PageRenderer = ({
|
|
|
2030
2067
|
{
|
|
2031
2068
|
ref: containerRef,
|
|
2032
2069
|
className: `relative inline-block shadow-2xl bg-white mb-10 ${canSelectText ? "" : "no-select cursor-crosshair"}`,
|
|
2033
|
-
style: {
|
|
2070
|
+
style: {
|
|
2071
|
+
scrollMarginTop: "20px",
|
|
2072
|
+
minHeight: "100px",
|
|
2073
|
+
touchAction: activeTool === "ink" || activeTool === "text" || activeTool === "comment" ? "none" : "auto"
|
|
2074
|
+
},
|
|
2034
2075
|
onMouseDown: handleMouseDown,
|
|
2035
2076
|
onMouseMove: handleMouseMove,
|
|
2036
2077
|
onMouseUp: handleMouseUp,
|
|
2078
|
+
onTouchStart: handleTouchStart,
|
|
2079
|
+
onTouchMove: handleTouchMove,
|
|
2080
|
+
onTouchEnd: handleTouchEnd,
|
|
2081
|
+
onTouchCancel: handleTouchEnd,
|
|
2037
2082
|
children: [
|
|
2038
2083
|
loading && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "absolute inset-0 bg-gray-50 flex items-center justify-center z-10 animate-pulse", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "text-[10px] font-black text-gray-400 uppercase tracking-widest", children: "Sincronizando..." }) }),
|
|
2039
2084
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
@@ -2509,9 +2554,12 @@ var MIN_ZOOM = 0.2;
|
|
|
2509
2554
|
var MAX_ZOOM = 5;
|
|
2510
2555
|
var WIDTH_SNAP_PX = 4;
|
|
2511
2556
|
var WIDTH_HYSTERESIS_PX = 6;
|
|
2557
|
+
var HEIGHT_SNAP_PX = 4;
|
|
2558
|
+
var HEIGHT_HYSTERESIS_PX = 6;
|
|
2512
2559
|
var MOBILE_HEADER_HIDE_DELTA_PX = 28;
|
|
2513
2560
|
var MOBILE_HEADER_SHOW_DELTA_PX = 16;
|
|
2514
2561
|
var MOBILE_HEADER_TOP_RESET_PX = 12;
|
|
2562
|
+
var MOBILE_LANDSCAPE_MAX_HEIGHT_PX2 = 500;
|
|
2515
2563
|
var Viewer = ({ engine, style }) => {
|
|
2516
2564
|
const viewerState = (0, import_core5.useViewerStore)();
|
|
2517
2565
|
const {
|
|
@@ -2537,6 +2585,7 @@ var Viewer = ({ engine, style }) => {
|
|
|
2537
2585
|
const jumpRef = (0, import_react5.useRef)(false);
|
|
2538
2586
|
const jumpTimerRef = (0, import_react5.useRef)(null);
|
|
2539
2587
|
const lastWidthRef = (0, import_react5.useRef)(null);
|
|
2588
|
+
const lastHeightRef = (0, import_react5.useRef)(null);
|
|
2540
2589
|
const lastScrollTopRef = (0, import_react5.useRef)(0);
|
|
2541
2590
|
const scrollDownAccumulatorRef = (0, import_react5.useRef)(0);
|
|
2542
2591
|
const scrollUpAccumulatorRef = (0, import_react5.useRef)(0);
|
|
@@ -2550,11 +2599,14 @@ var Viewer = ({ engine, style }) => {
|
|
|
2550
2599
|
rafId: null
|
|
2551
2600
|
});
|
|
2552
2601
|
const [availableWidth, setAvailableWidth] = (0, import_react5.useState)(null);
|
|
2602
|
+
const [availableHeight, setAvailableHeight] = (0, import_react5.useState)(null);
|
|
2553
2603
|
const [basePageSize, setBasePageSize] = (0, import_react5.useState)(null);
|
|
2554
2604
|
const [pageSizes, setPageSizes] = (0, import_react5.useState)({});
|
|
2555
2605
|
const [colorPickerOpen, setColorPickerOpen] = (0, import_react5.useState)(false);
|
|
2556
|
-
const
|
|
2557
|
-
const
|
|
2606
|
+
const isLandscape = availableWidth !== null && availableHeight !== null && availableWidth > availableHeight;
|
|
2607
|
+
const isLandscapeShort = isLandscape && availableHeight !== null && availableHeight <= MOBILE_LANDSCAPE_MAX_HEIGHT_PX2;
|
|
2608
|
+
const isCompact = availableWidth !== null && (availableWidth < 820 || isLandscapeShort);
|
|
2609
|
+
const isMobileViewport = availableWidth !== null && (availableWidth < 640 || isLandscapeShort);
|
|
2558
2610
|
const paddingY = isCompact ? "py-10" : "py-16";
|
|
2559
2611
|
const toolDockPosition = isCompact ? "bottom-4" : "bottom-8";
|
|
2560
2612
|
const colorPalette = [
|
|
@@ -2605,21 +2657,32 @@ var Viewer = ({ engine, style }) => {
|
|
|
2605
2657
|
const measurementTarget = viewerElement.parentElement ?? viewerElement;
|
|
2606
2658
|
let rafId = null;
|
|
2607
2659
|
const normalizeWidth = (rawWidth) => Math.max(0, Math.floor(rawWidth / WIDTH_SNAP_PX) * WIDTH_SNAP_PX);
|
|
2608
|
-
const
|
|
2660
|
+
const normalizeHeight = (rawHeight) => Math.max(0, Math.floor(rawHeight / HEIGHT_SNAP_PX) * HEIGHT_SNAP_PX);
|
|
2661
|
+
const updateSize = () => {
|
|
2609
2662
|
const rawWidth = measurementTarget.getBoundingClientRect?.().width ?? measurementTarget.clientWidth ?? measurementTarget.offsetWidth;
|
|
2663
|
+
const rawHeight = measurementTarget.getBoundingClientRect?.().height ?? measurementTarget.clientHeight ?? measurementTarget.offsetHeight;
|
|
2610
2664
|
const nextWidth = normalizeWidth(rawWidth);
|
|
2611
|
-
|
|
2665
|
+
const nextHeight = normalizeHeight(rawHeight);
|
|
2666
|
+
if (nextWidth <= 0 || nextHeight <= 0) return;
|
|
2612
2667
|
const previousWidth = lastWidthRef.current;
|
|
2613
|
-
|
|
2614
|
-
|
|
2615
|
-
|
|
2616
|
-
|
|
2668
|
+
const previousHeight = lastHeightRef.current;
|
|
2669
|
+
const widthChanged = previousWidth == null || Math.abs(nextWidth - previousWidth) >= WIDTH_HYSTERESIS_PX;
|
|
2670
|
+
const heightChanged = previousHeight == null || Math.abs(nextHeight - previousHeight) >= HEIGHT_HYSTERESIS_PX;
|
|
2671
|
+
if (!widthChanged && !heightChanged) return;
|
|
2672
|
+
if (widthChanged) {
|
|
2673
|
+
lastWidthRef.current = nextWidth;
|
|
2674
|
+
setAvailableWidth(nextWidth);
|
|
2675
|
+
}
|
|
2676
|
+
if (heightChanged) {
|
|
2677
|
+
lastHeightRef.current = nextHeight;
|
|
2678
|
+
setAvailableHeight(nextHeight);
|
|
2679
|
+
}
|
|
2617
2680
|
};
|
|
2618
2681
|
const scheduleWidthUpdate = () => {
|
|
2619
2682
|
if (rafId != null) cancelAnimationFrame(rafId);
|
|
2620
2683
|
rafId = requestAnimationFrame(() => {
|
|
2621
2684
|
rafId = null;
|
|
2622
|
-
|
|
2685
|
+
updateSize();
|
|
2623
2686
|
});
|
|
2624
2687
|
};
|
|
2625
2688
|
scheduleWidthUpdate();
|